[
  {
    "path": ".clang-format",
    "content": "# This file is used by clang-format to autoformat paddle source code\n#\n# The clang-format is part of llvm toolchain.\n# It need to install llvm and clang to format source code style.\n#\n# The basic usage is,\n#   clang-format -i -style=file PATH/TO/SOURCE/CODE\n#\n# The -style=file implicit use \".clang-format\" file located in one of\n# parent directory.\n# The -i means inplace change.\n#\n# The document of clang-format is\n#   http://clang.llvm.org/docs/ClangFormat.html\n#   http://clang.llvm.org/docs/ClangFormatStyleOptions.html\n---\nLanguage:        Cpp\nBasedOnStyle:  Google\nIndentWidth:     4\nTabWidth:        4\nContinuationIndentWidth: 4\nMaxEmptyLinesToKeep: 2\nAccessModifierOffset: -2  # The private/protected/public has no indent in class\nStandard:  Cpp11\nAllowAllParametersOfDeclarationOnNextLine: true\nBinPackParameters: false\nBinPackArguments: false\n...\n\n"
  },
  {
    "path": ".flake8",
    "content": "[flake8]\n\n########## OPTIONS ##########\n# Set the maximum length that any line (with some exceptions) may be.\nmax-line-length = 120\n\n\n################### FILE PATTERNS ##########################\n# Provide a comma-separated list of glob patterns to exclude from checks.\nexclude =\n    # git folder\n    .git,\n    # python cache\n    __pycache__,\n    # third party\n    utils/compute-wer.py,\n    third_party/,\n# Provide a comma-separate list of glob patterns to include for checks.\nfilename =\n    *.py\n\n\n########## RULES ##########\n\n# ERROR CODES\n#\n# E/W  - PEP8 errors/warnings (pycodestyle)\n# F    - linting errors (pyflakes)\n# C    - McCabe complexity error (mccabe)\n#\n# W503 - line break before binary operator\n\n# Specify a list of codes to ignore.\nignore =\n    W503\n    E252,E262,E127,E265,E126,E266,E241,E261,E128,E125,E129\n    W291,W293,W605\n    E203,E305,E402,E501,E721,E741,F403,F405,F821,F841,F999,W503,W504,C408,E302,W291,E303,\n    # shebang has extra meaning in fbcode lints, so I think it's not worth trying\n    # to line this up with executable bit\n    EXE001,\n    # these ignores are from flake8-bugbear; please fix!\n    B007,B008,\n    # these ignores are from flake8-comprehensions; please fix!\n    C400,C401,C402,C403,C404,C405,C407,C411,C413,C414,C415\n\n\nper-file-ignores =\n    */__init__.py: F401\n\n# Specify the list of error codes you wish Flake8 to report.\nselect =\n    E,\n    W,\n    F,\n    C\n"
  },
  {
    "path": ".gitconfig",
    "content": "[alias]\n  st = status\n  ci = commit\n  br = branch\n  co = checkout\n  df = diff\n  l = log --pretty=format:\\\"%h %ad | %s%d [%an]\\\" --graph --date=short\n  ll = log --stat\n\n[merge]\n  tool = vimdiff\n\n[core]\n  excludesfile = ~/.gitignore\n  editor = vim\n\n[color]\n  branch = auto\n  diff = auto\n  status = auto\n\n[color \"branch\"]\n  current = yellow reverse\n  local = yellow\n  remote = green\n\n[color \"diff\"]\n  meta = yellow bold\n  frag = magenta bold\n  old = red bold\n  new = green bold\n\n[color \"status\"]\n  added = yellow\n  changed = green\n  untracked = cyan\n\n[push]\n  default = matching\n\n[credential]\n  helper = store\n\n[user]\n  name =\n  email =\n\n\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Racial or political allusions          \n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at paddlespeech@baidu.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# 💡 paddlespeech 提交代码须知\n\n### Discussed in https://github.com/PaddlePaddle/PaddleSpeech/discussions/1326\n\n<div type='discussions-op-text'>\n\n<sup>Originally posted by **yt605155624** January 12, 2022</sup>\n1. 写完代码之后可以用我们的 pre-commit 检查一下代码格式，注意只改自己修改的代码的格式即可，其他的代码有可能也被改了格式，不要 add 就好\n```\npip install pre-commit\npre-commit run --file 你修改的代码\n```\n2. 提交 commit 中增加必要信息跳过不必要的 CI\n- 提交 asr 相关代码\n```text\ngit commit -m \"xxxxxx, test=asr\"\n```\n- 提交 tts 相关代码\n```text\ngit commit -m \"xxxxxx, test=tts\"\n```\n- 仅修改文档\n```text\ngit commit -m \"xxxxxx, test=doc\"\n```\n注意：\n1. 虽然跳过了 CI，但是还要先排队排到才能跳过，所以非自己方向看到 pending 不要着急 🤣\n2. 在 `git commit --amend` 的时候才加 `test=xxx` 可能不太有效\n3. 一个 pr 多次提交 commit 注意每次都要加 `test=xxx`，因为每个 commit 都会触发 CI\n4. 删除 python 环境中已经安装好的 paddlespeech，否则可能会影响 import paddlespeech 的顺序</div>\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-s2t.md",
    "content": "---\nname: \"\\U0001F41B S2T Bug Report\"\nabout: Create a report to help us improve\ntitle: \"[S2T]XXXX\"\nlabels: Bug, S2T\nassignees: zh794390558\n\n---\n\nFor support and discussions, please use our [Discourse forums](https://github.com/PaddlePaddle/DeepSpeech/discussions).\n\nIf you've found a bug then please create an issue with the following information:\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Environment (please complete the following information):**\n - OS: [e.g. Ubuntu]\n - GCC/G++ Version [e.g. 8.3]\n - Python Version [e.g. 3.7]\n - PaddlePaddle Version [e.g. 2.0.0]\n - Model Version [e.g. 2.0.0]\n - GPU/DRIVER Information [e.g. Tesla V100-SXM2-32GB/440.64.00]\n - CUDA/CUDNN Version [e.g. cuda-10.2]\n - MKL Version\n- TensorRT Version\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-tts.md",
    "content": "---\nname: \"\\U0001F41B TTS Bug Report\"\nabout: Create a report to help us improve\ntitle: \"[TTS]XXXX\"\nlabels: Bug, T2S\n\n---\n\nFor support and discussions, please use our [Discourse forums](https://github.com/PaddlePaddle/DeepSpeech/discussions).\n\nIf you've found a bug then please create an issue with the following information:\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Environment (please complete the following information):**\n - OS: [e.g. Ubuntu]\n - GCC/G++ Version [e.g. 8.3]\n - Python Version [e.g. 3.7]\n - PaddlePaddle Version [e.g. 2.0.0]\n - Model Version [e.g. 2.0.0]\n - GPU/DRIVER Information [e.g. Tesla V100-SXM2-32GB/440.64.00]\n - CUDA/CUDNN Version [e.g. cuda-10.2]\n - MKL Version\n- TensorRT Version\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "content": "---\nname: \"\\U0001F680 Feature Request\"\nabout: As a user, I want to request a New Feature on the product.\ntitle: ''\nlabels: feature request\nassignees: D-DanielYang, iftaken\n\n---\n\n## Feature Request\n\n**Is your feature request related to a problem? Please describe:**\n<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->\n\n**Describe the feature you'd like:**\n<!-- A clear and concise description of what you want to happen. -->\n\n**Describe alternatives you've considered:**\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/others.md",
    "content": "---\nname: \"\\U0001F9E9 Others\"\nabout: Report any other non-support related issues.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## Others\n\n<!--\n你可以在这里提出任何前面几类模板不适用的问题，包括但不限于：优化性建议、框架使用体验反馈、版本兼容性问题、报错信息不清楚等。\nYou can report any issues that are not applicable to the previous types of templates, including but not limited to: enhancement suggestions, feedback on the use of the framework, version compatibility issues, unclear error information, etc.\n-->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: \"\\U0001F914 Ask a Question\"\nabout: I want to ask a question.\ntitle: ''\nlabels: Question\nassignees: ''\n\n---\n\n## General Question\n\n<!--\nBefore asking a question, make sure you have:\n- Baidu/Google your question.\n- Searched open and closed [GitHub issues](https://github.com/PaddlePaddle/PaddleSpeech/issues?q=is%3Aissue)\n- Read the documentation:\n  - [Readme](https://github.com/PaddlePaddle/PaddleSpeech)\n  - [Doc](https://paddlespeech.readthedocs.io/)\n-->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- Demo: https://github.com/PaddlePaddle/PaddleNLP/pull/26 -->\n### PR types\n<!-- One of [ New features | Bug fixes | Function optimization | Performance optimization | Breaking changes | Others ] -->\n\n### PR changes\n<!-- One of [ Models | APIs | Docs | Others ] -->\n\n### Describe\n<!-- Describe what this PR does -->\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 45 \n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 30\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - Roadmap \n  - Bug\n  - feature request\n  - Tips\n# Label to use when marking an issue as stale\nstaleLabel: Stale\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\nunmarkComment: false\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: >\n  This issue is closed. Please re-open if needed.\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n*.pyc\n.vscode\n*.log\n*.wav\n*.pdmodel\n*.pdiparams*\n*.zip\n*.tar\n*.tar.gz\n.ipynb_checkpoints\n*.npz\n*.done\n*.whl\n*.egg-info\nbuild\n*output/\n.history\n.idea\n\naudio/dist/\naudio/fc_patch/\n\ndocs/build/\ndocs/topic/ctc/warp-ctc/\n\ntools/venv\ntools/kenlm\ntools/sox-14.4.2\ntools/soxbindings\ntools/montreal-forced-aligner/\ntools/Montreal-Forced-Aligner/\ntools/sctk\ntools/sctk-20159b5/\ntools/kaldi\ntools/OpenBLAS/\ntools/Miniconda3-latest-Linux-x86_64.sh\ntools/activate_python.sh\ntools/miniconda.sh\ntools/CRF++-0.58/\ntools/liblbfgs-1.10/\ntools/srilm/\ntools/env.sh\ntools/openfst-1.8.1/\ntools/libsndfile/\ntools/python-soundfile/\ntools/onnx\ntools/onnxruntime\ntools/Paddle2ONNX\ntools/onnx-simplifier/\n\nspeechx/fc_patch/\n\nthird_party/ctc_decoders/paddlespeech_ctcdecoders.py\n\nkernel_meta/\n"
  },
  {
    "path": ".mergify.yml",
    "content": "pull_request_rules:\n  - name: automatic merge for develop when CI passes and 1 reviews\n    conditions:\n      - \"approved-reviews-by>=1\"\n      - check-success=Travis CI - Pull Request\n      - base=develop\n    actions:\n      merge:\n        method: merge\n  - name: delete head branch after merged\n    conditions:\n      - merged\n    actions:\n      delete_head_branch: {}\n  - name: \"add label=auto-merge for PR by mergify\"\n    conditions:\n      - author=mergify[bot]\n    actions:\n      label:\n        add: [\"auto-merge\"]\n  - name: warn on conflicts\n    conditions:\n      - conflict\n    actions:\n      comment:\n        message: This pull request is now in conflict :(\n      label:\n        add: [\"conflicts\"]\n  - name: unlabel conflicts\n    conditions:\n      - -conflict\n    actions:\n      label:\n        remove: [\"conflicts\"]\n  - name: \"auto add label=Dataset\"\n    conditions:\n      - files~=^dataset/\n    actions:\n      label:\n        add: [\"Dataset\"]\n  - name: \"auto add label=S2T\"\n    conditions:\n      - files~=^paddlespeech/s2t/\n    actions:\n      label:\n        add: [\"S2T\"]\n  - name: \"auto add label=T2S\"\n    conditions:\n      - files~=^paddlespeech/t2s/\n    actions:\n      label:\n        add: [\"T2S\"]\n  - name: \"auto add label=Audio\"\n    conditions:\n      - files~=^paddlespeech/audio/\n    actions:\n      label:\n        add: [\"Audio\"]\n  - name: \"auto add label=Vector\"\n    conditions:\n      - files~=^paddlespeech/vector/\n    actions:\n      label:\n        add: [\"Vector\"]\n  - name: \"auto add label=Text\"\n    conditions:\n      - files~=^paddlespeech/text/\n    actions:\n      label:\n        add: [\"Text\"]\n  - name: \"auto add label=Example\"\n    conditions:\n      - files~=^examples/\n    actions:\n      label:\n        add: [\"Example\"]\n  - name: \"auto add label=CLI\"\n    conditions:\n      - files~=^paddlespeech/cli\n    actions:\n      label:\n        add: [\"CLI\"]\n  - name: \"auto add label=Server\"\n    conditions:\n      - files~=^paddlespeech/server\n    actions:\n      label:\n        add: [\"Server\"]\n  - name: \"auto add label=Demo\"\n    conditions:\n      - files~=^demos/\n    actions:\n      label:\n        add: [\"Demo\"]\n  - name: \"auto add label=README\"\n    conditions:\n      - files~=(README.md|READEME_cn.md)\n    actions:\n      label:\n        add: [\"README\"]\n  - name: \"auto add label=Documentation\"\n    conditions:\n      - files~=^(docs/|CHANGELOG.md)\n    actions:\n      label:\n        add: [\"Documentation\"]\n  - name: \"auto add label=CI\"\n    conditions:\n      - files~=^(.circleci/|ci/|.github/|.travis.yml|.travis|env.sh)\n    actions:\n      label:\n        add: [\"CI\"]\n  - name: \"auto add label=Installation\"\n    conditions:\n      - files~=^(tools/|setup.py|setup.cfg|setup_audio.py)\n    actions:\n      label:\n        add: [\"Installation\"]\n  - name: \"auto add label=Test\"\n    conditions:\n      - files~=^(tests/)\n    actions:\n      label:\n        add: [\"Test\"]\n  - name: \"auto add label=mergify\"\n    conditions:\n      - files~=^.mergify.yml\n    actions:\n      label:\n        add: [\"mergify\"]\n  - name: \"auto add label=Docker\"\n    conditions:\n      - files~=^docker/\n    actions:\n      label:\n        add: [\"Docker\"]\n  - name: \"auto add label=Deployment\"\n    conditions:\n      - files~=^runtime/\n    actions:\n      label:\n        add: [\"Deployment\"]\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "repos:\n-   repo: https://github.com/pre-commit/mirrors-yapf.git\n    rev: v0.16.0\n    hooks:\n    -   id: yapf\n        files: \\.py$\n        exclude: (?=runtime/engine/kaldi|audio/paddleaudio/src|third_party).*(\\.cpp|\\.cc|\\.h\\.hpp|\\.py)$\n\n-   repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: a11d9314b22d8f8c7556443875b731ef05965464\n    hooks:\n    -   id: check-merge-conflict\n    -   id: check-symlinks\n    -   id: detect-private-key\n        files: (?!.*paddle)^.*$\n    -   id: end-of-file-fixer\n        files: \\.md$\n    #-   id: trailing-whitespace\n    #    files: \\.md$\n    -   id: requirements-txt-fixer\n        exclude: (?=third_party).*$\n    -   id: check-yaml\n    -   id: check-json\n    -   id: pretty-format-json\n        args:\n        - --no-sort-keys\n        - --autofix\n    -   id: check-merge-conflict\n      #    -   id: flake8\n      #        aergs:\n      #        -  --ignore=E501,E228,E226,E261,E266,E128,E402,W503\n      #        -  --builtins=G,request\n      #        -  --jobs=1\n      #        exclude: (?=runtime/engine/kaldi|audio/paddleaudio/src|third_party).*(\\.cpp|\\.cc|\\.h\\.hpp|\\.py)$\n\n-   repo : https://github.com/Lucas-C/pre-commit-hooks\n    rev: v1.0.1\n    hooks:\n    -   id: forbid-crlf\n        files: \\.md$\n    -   id: remove-crlf\n        files: \\.md$\n    -   id: forbid-tabs\n        files: \\.md$\n    -   id: remove-tabs\n        files: \\.md$\n\n-   repo: local\n    hooks:\n    -   id: clang-format\n        name: clang-format\n        description: Format files with ClangFormat\n        entry: bash .pre-commit-hooks/clang-format.hook -i\n        language: system\n        files: \\.(h\\+\\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\\+\\+|cxx|tpp|txx)$\n        exclude: (?=runtime/engine/kaldi|audio/paddleaudio/src|runtime/patch|runtime/tools/fstbin|runtime/tools/lmbin|third_party/ctc_decoders|runtime/engine/common/utils).*(\\.cpp|\\.cc|\\.h|\\.hpp|\\.py)$ \n    -   id: cpplint\n        name: cpplint\n        description: Static code analysis of C/C++ files\n        language: python\n        files: \\.(h\\+\\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\\+\\+|cxx|tpp|txx)$\n        exclude: (?=runtime/engine/kaldi|runtime/engine/common/matrix|audio/paddleaudio/src|runtime/patch|runtime/tools/fstbin|runtime/tools/lmbin|third_party/ctc_decoders|runtime/engine/common/utils).*(\\.cpp|\\.cc|\\.h|\\.hpp|\\.py)$ \n        entry: cpplint --filter=-build,-whitespace,+whitespace/comma,-whitespace/indent\n-   repo: https://github.com/asottile/reorder_python_imports\n    rev: v2.4.0\n    hooks:\n      - id: reorder-python-imports\n        exclude: (?=runtime/engine/kaldi|audio/paddleaudio/src|runtime/patch|runtime/tools/fstbin|runtime/tools/lmbin|third_party/ctc_decoders).*(\\.cpp|\\.cc|\\.h\\.hpp|\\.py)$\n"
  },
  {
    "path": ".pre-commit-hooks/clang-format.hook",
    "content": "#!/usr/bin/env bash\nset -e\n\nreadonly VERSION=\"3.9\"\n\nversion=$(clang-format -version)\n\n# if ! [[ $version == *\"$VERSION\"* ]]; then\n#     echo \"clang-format version check failed.\"\n#     echo \"a version contains '$VERSION' is needed, but get '$version'\"\n#     echo \"you can install the right version, and make an soft-link to '\\$PATH' env\"\n#     exit -1\n# fi\n\nclang-format $@\n"
  },
  {
    "path": ".pre-commit-hooks/copyright-check.hook",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport argparse\nimport io, re\nimport sys, os\nimport subprocess\nimport platform\n\nCOPYRIGHT = '''\nCopyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n'''\n\nLANG_COMMENT_MARK = None\n\nNEW_LINE_MARK = None\n\nCOPYRIGHT_HEADER = None\n\nif platform.system() == \"Windows\":\n    NEW_LINE_MARK = \"\\r\\n\"\nelse:\n    NEW_LINE_MARK = '\\n'\n    COPYRIGHT_HEADER = COPYRIGHT.split(NEW_LINE_MARK)[1]\n    p = re.search('(\\d{4})', COPYRIGHT_HEADER).group(0)\n    process = subprocess.Popen([\"date\", \"+%Y\"], stdout=subprocess.PIPE)\n    date, err = process.communicate()\n    date = date.decode(\"utf-8\").rstrip(\"\\n\")\n    COPYRIGHT_HEADER = COPYRIGHT_HEADER.replace(p, date)\n\n\ndef generate_copyright(template, lang='C'):\n    if lang == 'Python':\n        LANG_COMMENT_MARK = '#'\n    else:\n        LANG_COMMENT_MARK = \"//\"\n\n    lines = template.split(NEW_LINE_MARK)\n    BLANK = \" \"\n    ans = LANG_COMMENT_MARK + BLANK + COPYRIGHT_HEADER + NEW_LINE_MARK\n    for lino, line in enumerate(lines):\n        if lino == 0 or lino == 1 or lino == len(lines) - 1: continue\n        if len(line)  == 0:\n            BLANK = \"\"\n        else:\n            BLANK = \" \"\n        ans += LANG_COMMENT_MARK + BLANK + line + NEW_LINE_MARK\n\n    return ans + \"\\n\"\n\n\ndef lang_type(filename):\n    if filename.endswith(\".py\"):\n        return \"Python\"\n    elif filename.endswith(\".h\"):\n        return \"C\"\n    elif filename.endswith(\".c\"):\n        return \"C\"\n    elif filename.endswith(\".hpp\"):\n        return \"C\"\n    elif filename.endswith(\".cc\"):\n        return \"C\"\n    elif filename.endswith(\".cpp\"):\n        return \"C\"\n    elif filename.endswith(\".cu\"):\n        return \"C\"\n    elif filename.endswith(\".cuh\"):\n        return \"C\"\n    elif filename.endswith(\".go\"):\n        return \"C\"\n    elif filename.endswith(\".proto\"):\n        return \"C\"\n    else:\n        print(\"Unsupported filetype %s\", filename)\n        exit(0)\n\n\nPYTHON_ENCODE = re.compile(\"^[ \\t\\v]*#.*?coding[:=][ \\t]*([-_.a-zA-Z0-9]+)\")\n\n\ndef main(argv=None):\n    parser = argparse.ArgumentParser(\n        description='Checker for copyright declaration.')\n    parser.add_argument('filenames', nargs='*', help='Filenames to check')\n    args = parser.parse_args(argv)\n\n    retv = 0\n    for filename in args.filenames:\n        fd = io.open(filename, encoding=\"utf-8\")\n        first_line = fd.readline()\n        second_line = fd.readline()\n        if \"COPYRIGHT (C)\" in first_line.upper(): continue\n        if first_line.startswith(\"#!\") or PYTHON_ENCODE.match(\n                second_line) != None or PYTHON_ENCODE.match(first_line) != None:\n            continue\n        original_contents = io.open(filename, encoding=\"utf-8\").read()\n        new_contents = generate_copyright(\n            COPYRIGHT, lang_type(filename)) + original_contents\n        print('Auto Insert Copyright Header {}'.format(filename))\n        retv = 1\n        with io.open(filename, 'w') as output_file:\n            output_file.write(new_contents)\n\n    return retv\n\n\nif __name__ == '__main__':\n    exit(main())\n"
  },
  {
    "path": ".readthedocs.yml",
    "content": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\n# Required\nversion: 2\n\n# Build documentation in the docs/ directory with Sphinx\nsphinx:\n  configuration: docs/source/conf.py\n\n# Build documentation with MkDocs\n#mkdocs:\n#  configuration: mkdocs.yml\n\n# Optionally build your docs in additional formats such as PDF\nformats: []\n\n# Optionally set the version of Python and requirements required to build your docs\npython:\n  version: 3.7\n  install:\n    - requirements: docs/requirements.txt\n    - method: setuptools\n      path: .\n  system_packages: true\n"
  },
  {
    "path": ".style.yapf",
    "content": "[style]\nbased_on_style = pep8\ncolumn_limit = 80\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: cpp\ncache: ccache\nsudo: required\ndist: Bionic \nservices:\n  - docker\nos:\n  - linux\nenv:\n  - JOB=PRE_COMMIT\n\naddons:\n  apt:\n    packages:\n      - git\n      - python3-pip\n      - python3-dev\n\nbefore_install:\n  -  python3 --version\n  -  python3 -m pip --version\n  -  pip3 --version\n  -  sudo pip3 install -U virtualenv pre-commit pip\n  -  docker pull paddlepaddle/paddle:latest\n\nscript:\n  - exit_code=0\n  - docker run -i --rm -v \"$PWD:/py_unittest\" paddlepaddle/paddle:latest /bin/bash -c\n    'cd /py_unittest && bash .travis/precommit.sh && source env.sh && bash .travis/unittest.sh' || exit_code=$(( exit_code | $? ))\n    exit $exit_code\n\nnotifications:\n  email:\n    on_success: change\n    on_failure: always\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include paddlespeech/t2s/exps/*.txt\ninclude paddlespeech/t2s/frontend/*.yaml"
  },
  {
    "path": "README.md",
    "content": "([简体中文](./README_cn.md)|English)\n<p align=\"center\">\n  <img src=\"./docs/images/PaddleSpeech_logo.png\" />\n</p>\n\n<p align=\"center\">\n    <a href=\"./LICENSE\"><img src=\"https://img.shields.io/badge/license-Apache%202-red.svg\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/releases\"><img src=\"https://img.shields.io/github/v/release/PaddlePaddle/PaddleSpeech?color=ffa\"></a>\n    <a href=\"support os\"><img src=\"https://img.shields.io/badge/os-linux%2C%20win%2C%20mac-pink.svg\"></a>\n    <a href=\"\"><img src=\"https://img.shields.io/badge/python-3.8+-aff.svg\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/graphs/contributors\"><img src=\"https://img.shields.io/github/contributors/PaddlePaddle/PaddleSpeech?color=9ea\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/commits\"><img src=\"https://img.shields.io/github/commit-activity/m/PaddlePaddle/PaddleSpeech?color=3af\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/issues\"><img src=\"https://img.shields.io/github/issues/PaddlePaddle/PaddleSpeech?color=9cc\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/stargazers\"><img src=\"https://img.shields.io/github/stars/PaddlePaddle/PaddleSpeech?color=ccf\"></a>\n    <a href=\"=https://pypi.org/project/paddlespeech/\"><img src=\"https://img.shields.io/pypi/dm/PaddleSpeech\"></a>\n    <a href=\"=https://pypi.org/project/paddlespeech/\"><img src=\"https://static.pepy.tech/badge/paddlespeech\"></a>\n    <a href=\"https://huggingface.co/spaces\"><img src=\"https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue\"></a>\n</p>\n<div align=\"center\">  \n<h4>\n    <a href=\"#quick-start\"> Quick Start </a>\n  | <a href=\"#documents\"> Documents </a>\n  | <a href=\"#model-list\"> Models List </a>\n  | <a href=\"https://aistudio.baidu.com/aistudio/course/introduce/25130\"> AIStudio Courses </a>\n  | <a href=\"https://arxiv.org/abs/2205.12007\"> NAACL2022 Best Demo Award Paper </a>\n  | <a href=\"https://gitee.com/paddlepaddle/PaddleSpeech\"> Gitee </a>\n</h4>\n</div>\n\n------------------------------------------------------------------------------------\n\n**PaddleSpeech** is an open-source toolkit on [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) platform for a variety of critical tasks in speech and audio, with the state-of-art and influential models. \n\n**PaddleSpeech** won the [NAACL2022 Best Demo Award](https://2022.naacl.org/blog/best-demo-award/), please check out our paper on [Arxiv](https://arxiv.org/abs/2205.12007).\n\n##### Speech Recognition\n\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Input Audio  </th>\n      <th width=\"550\"> Recognition Result  </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td >I knocked at the door on the ancient side of the building.</td>\n    </tr>\n    <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td>我认为跑步最重要的就是给我带来了身体健康。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n##### Speech Translation (English to Chinese)\n\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Input Audio  </th>\n      <th width=\"550\"> Translations Result  </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td >我 在 这栋 建筑 的 古老 门上 敲门。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n##### Text-to-Speech\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th width=\"550\" > Input Text</th>\n      <th>Synthetic Audio</th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td>Life was like a box of chocolates, you never know what you're gonna get.</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_1.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>早上好，今天是2020/10/29，最低温度是-3°C。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/001.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>季姬寂，集鸡，鸡即棘鸡。棘鸡饥叽，季姬及箕稷济鸡。鸡既济，跻姬笈，季姬忌，急咭鸡，鸡急，继圾几，季姬急，即籍箕击鸡，箕疾击几伎，伎即齑，鸡叽集几基，季姬急极屐击鸡，鸡既殛，季姬激，即记《季姬击鸡记》。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/jijiji.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>大家好，我是 parrot 虚拟老师，我们来读一首诗，我与春风皆过客，I and the spring breeze are passing by，你携秋水揽星河，you take the autumn water to take the galaxy。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/labixiaoxin.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>宜家唔系事必要你讲，但系你所讲嘅说话将会变成呈堂证供。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/chengtangzhenggong.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>各个国家有各个国家嘅国歌</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/gegege.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\nFor more synthesized audios, please refer to [PaddleSpeech Text-to-Speech samples](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html).\n\n##### Punctuation Restoration\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th width=\"390\"> Input Text </th>\n      <th width=\"390\"> Output Text </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td>今天的天气真不错啊你下午有空吗我想约你一起去吃饭</td>\n      <td>今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n\n### Features\n\nVia the easy-to-use, efficient, flexible and scalable implementation, our vision is to empower both industrial application and academic research, including training, inference & testing modules, and deployment process. To be more specific, this toolkit features at:\n- 📦  **Ease of Use**: low barriers to install, [CLI](#quick-start), [Server](#quick-start-server), and [Streaming Server](#quick-start-streaming-server) is available to quick-start your journey.\n- 🏆  **Align to the State-of-the-Art**: we provide high-speed and ultra-lightweight models, and also cutting-edge technology. \n- 🏆  **Streaming ASR and TTS System**: we provide production ready streaming asr and streaming tts system.\n- 💯  **Rule-based Chinese frontend**: our frontend contains Text Normalization and Grapheme-to-Phoneme (G2P, including Polyphone and Tone Sandhi). Moreover, we use self-defined linguistic rules to adapt Chinese context.\n- 📦  **Varieties of Functions that Vitalize both Industrial and Academia**:\n  - 🛎️  *Implementation of critical audio tasks*: this toolkit contains audio functions like  Automatic Speech Recognition, Text-to-Speech Synthesis, Speaker Verification, KeyWord Spotting, Audio Classification, and Speech Translation, etc.\n  - 🔬  *Integration of mainstream models and datasets*: the toolkit implements modules that participate in the whole pipeline of the speech tasks, and uses mainstream datasets like LibriSpeech, LJSpeech, AIShell, CSMSC, etc. See also [model list](#model-list) for more details.\n  - 🧩  *Cascaded models application*: as an extension of the typical traditional audio tasks, we combine the workflows of the aforementioned tasks with other fields like Natural language processing (NLP) and Computer Vision (CV).\n\n### Recent Update\n- 🎉 2025.09.01: Add [Whisper large v3 and turbo model](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/whisper).\n- 🤗 2025.08.11: Add [code-switch online model and server demo](./examples/tal_cs/asr1/).\n- 👑 2023.05.31: Add [WavLM ASR-en](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/librispeech/asr5), WavLM fine-tuning for ASR on LibriSpeech.\n- 🎉 2023.05.18: Add [Squeezeformer](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell/asr1), Squeezeformer training for ASR on Aishell.\n- 👑 2023.05.04: Add [HuBERT ASR-en](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/librispeech/asr4), HuBERT fine-tuning for ASR on LibriSpeech.\n- ⚡ 2023.04.28: Fix [0-d tensor](https://github.com/PaddlePaddle/PaddleSpeech/pull/3214), with the upgrade of paddlepaddle==2.5, the problem of modifying 0-d tensor has been solved.\n- 👑 2023.04.25: Add [AMP for U2 conformer](https://github.com/PaddlePaddle/PaddleSpeech/pull/3167).\n- 🔥 2023.04.06: Add [subtitle file (.srt format) generation example](./demos/streaming_asr_server).\n- 🔥 2023.03.14: Add SVS(Singing Voice Synthesis) examples with Opencpop dataset, including [DiffSinger](./examples/opencpop/svs1)、[PWGAN](./examples/opencpop/voc1) and [HiFiGAN](./examples/opencpop/voc5), the effect is continuously optimized.\n- 👑 2023.03.09: Add [Wav2vec2ASR-zh](./examples/aishell/asr3).\n- 🎉 2023.03.07: Add [TTS ARM Linux C++ Demo (with C++ Chinese Text Frontend)](./demos/TTSArmLinux).\n- 🔥 2023.03.03 Add Voice Conversion [StarGANv2-VC synthesize pipeline](./examples/vctk/vc3).\n- 🎉 2023.02.16: Add [Cantonese TTS](./examples/canton/tts3).\n- 🔥 2023.01.10: Add [code-switch asr CLI and Demos](./demos/speech_recognition).\n- 👑 2023.01.06: Add [code-switch asr tal_cs recipe](./examples/tal_cs/asr1/).\n- 🎉 2022.12.02: Add [end-to-end Prosody Prediction pipeline](./examples/csmsc/tts3_rhy) (including using prosody labels in Acoustic Model).\n- 🎉 2022.11.30: Add [TTS Android Demo](./demos/TTSAndroid).\n- 🤗 2022.11.28: PP-TTS and PP-ASR demos are available in [AIStudio](https://aistudio.baidu.com/aistudio/modelsoverview) and [official website\n of paddlepaddle](https://www.paddlepaddle.org.cn/models).\n- 👑 2022.11.18: Add [Whisper CLI and Demos](https://github.com/PaddlePaddle/PaddleSpeech/pull/2640), support multi language recognition and translation.\n- 🔥 2022.11.18: Add [Wav2vec2 CLI and Demos](./demos/speech_ssl), Support ASR and Feature Extraction.\n- 🎉 2022.11.17: Add [male voice for TTS](https://github.com/PaddlePaddle/PaddleSpeech/pull/2660).\n- 🔥 2022.11.07: Add [U2/U2++ C++ High Performance Streaming ASR Deployment](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/runtime/examples/u2pp_ol/wenetspeech).\n- 👑 2022.11.01: Add [Adversarial Loss](https://arxiv.org/pdf/1907.04448.pdf) for [Chinese English mixed TTS](./examples/zh_en_tts/tts3).\n- 🔥 2022.10.26: Add [Prosody Prediction](./examples/other/rhy) for TTS.\n- 🎉 2022.10.21: Add [SSML](https://github.com/PaddlePaddle/PaddleSpeech/discussions/2538) for TTS Chinese Text Frontend.\n- 👑 2022.10.11: Add [Wav2vec2ASR-en](./examples/librispeech/asr3), wav2vec2.0 fine-tuning for ASR on LibriSpeech.\n- 🔥 2022.09.26: Add Voice Cloning, TTS finetune, and [ERNIE-SAT](https://arxiv.org/abs/2211.03545) in [PaddleSpeech Web Demo](./demos/speech_web).\n- ⚡ 2022.09.09: Add AISHELL-3 Voice Cloning [example](./examples/aishell3/vc2) with ECAPA-TDNN speaker encoder.\n- ⚡ 2022.08.25: Release TTS [finetune](./examples/other/tts_finetune/tts3) example.\n- 🔥 2022.08.22: Add [ERNIE-SAT](https://arxiv.org/abs/2211.03545) models: [ERNIE-SAT-vctk](./examples/vctk/ernie_sat)、[ERNIE-SAT-aishell3](./examples/aishell3/ernie_sat)、[ERNIE-SAT-zh_en](./examples/aishell3_vctk/ernie_sat).\n- 🔥 2022.08.15: Add [g2pW](https://github.com/GitYCC/g2pW) into TTS Chinese Text Frontend.\n- 🔥 2022.08.09: Release [Chinese English mixed TTS](./examples/zh_en_tts/tts3).\n- ⚡ 2022.08.03: Add ONNXRuntime infer for  TTS CLI.\n- 🎉 2022.07.18: Release VITS: [VITS-csmsc](./examples/csmsc/vits)、[VITS-aishell3](./examples/aishell3/vits)、[VITS-VC](./examples/aishell3/vits-vc).\n- 🎉 2022.06.22: All TTS models support ONNX format.\n- 🍀 2022.06.17: Add [PaddleSpeech Web Demo](./demos/speech_web).\n- 👑 2022.05.13: Release [PP-ASR](./docs/source/asr/PPASR.md)、[PP-TTS](./docs/source/tts/PPTTS.md)、[PP-VPR](docs/source/vpr/PPVPR.md).\n- 👏🏻 2022.05.06: `PaddleSpeech Streaming Server` is available for `Streaming ASR` with `Punctuation Restoration` and `Token Timestamp` and `Text-to-Speech`.\n- 👏🏻 2022.05.06: `PaddleSpeech Server` is available for `Audio Classification`, `Automatic Speech Recognition` and `Text-to-Speech`, `Speaker Verification` and `Punctuation Restoration`.\n- 👏🏻 2022.03.28: `PaddleSpeech CLI` is available for `Speaker Verification`.\n- 👏🏻 2021.12.10: `PaddleSpeech CLI` is available for `Audio Classification`, `Automatic Speech Recognition`, `Speech Translation (English to Chinese)` and `Text-to-Speech`.\n\n### Community\n- Scan the QR code below with your Wechat, you can access to official technical exchange group and get the bonus ( more than 20GB learning materials, such as papers, codes and videos ) and the live link of the lessons. Look forward to your participation.\n\n<div align=\"center\">\n<img src=\"https://user-images.githubusercontent.com/30135920/212860467-9e943cc3-8be8-49a4-97fd-7c94aad8e979.jpg\"  width = \"200\"  />\n</div>\n\n## Installation\n\nWe strongly recommend our users to install PaddleSpeech in **Linux** with *python>=3.8*. \n\n### **Dependency Introduction**\n\n+ gcc >= 4.8.5\n+ paddlepaddle\n+ python >= 3.8\n+ OS support:  Linux(recommend), Windows, Mac OSX\n\nPaddleSpeech depends on paddlepaddle. For installation, please refer to the official website of [paddlepaddle](https://www.paddlepaddle.org.cn/en) and choose according to your own machine. Here is an example of the cpu version.\n\n```bash\npip install paddlepaddle -i https://mirror.baidu.com/pypi/simple\n```\nYou can also specify the version of paddlepaddle or install the develop version. \n```bash\n# install 2.4.1 version. Note, 2.4.1 is just an example, please follow the minimum dependency of paddlepaddle for your selection\npip install paddlepaddle==2.4.1 -i https://mirror.baidu.com/pypi/simple\n# install develop version\npip install paddlepaddle==0.0.0 -f https://www.paddlepaddle.org.cn/whl/linux/cpu-mkl/develop.html\n```\n\nThere are two quick installation methods for PaddleSpeech, one is pip installation, and the other is source code compilation (recommended).\n### pip install\n\n```shell\npip install pytest-runner\npip install paddlespeech\n```\n\n### source code compilation\n\n```shell\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\ncd PaddleSpeech\npip install pytest-runner\npip install .\n# If you need to install in editable mode, you need to use --use-pep517. The command is as follows:\n# pip install -e . --use-pep517\n```\n\nFor more installation problems, such as conda environment, librosa-dependent, gcc problems, kaldi installation, etc., you can refer to this [installation document](./docs/source/install.md). If you encounter problems during installation, you can leave a message on [#2150](https://github.com/PaddlePaddle/PaddleSpeech/issues/2150) and find related problems\n\n\n<a name=\"quickstart\"></a>\n## Quick Start\n\nDevelopers can have a try of our models with [PaddleSpeech Command Line](./paddlespeech/cli/README.md) or Python. Change `--input` to test your own audio/text and support 16k wav format audio.\n\n**You can also quickly experience it in AI Studio 👉🏻 [PaddleSpeech API Demo](https://aistudio.baidu.com/aistudio/projectdetail/4353348?sUid=2470186&shared=1&ts=1660876445786)**\n\n\nTest audio sample download\n\n```shell\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n\n### Automatic Speech Recognition\n\n<details><summary>&emsp;（Click to expand）Open Source Speech Recognition</summary>\n\n**command line experience**\n\n```shell\npaddlespeech asr --lang zh --input zh.wav\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.asr.infer import ASRExecutor\n>>> asr = ASRExecutor()\n>>> result = asr(audio_file=\"zh.wav\")\n>>> print(result)\n我认为跑步最重要的就是给我带来了身体健康\n```\n</details>\n\n### Text-to-Speech\n\n<details><summary>&emsp;Open Source Speech Synthesis</summary>\n\nOutput 24k sample rate wav format audio\n\n\n**command line experience**\n\n```shell\npaddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.tts.infer import TTSExecutor\n>>> tts = TTSExecutor()\n>>> tts(text=\"今天天气十分不错。\", output=\"output.wav\")\n```\n- You can experience in [Huggingface Spaces](https://huggingface.co/spaces) [TTS Demo](https://huggingface.co/spaces/KPatrick/PaddleSpeechTTS)\n\n</details>\n\n### Audio Classification\n\n<details><summary>&emsp;An open-domain sound classification tool</summary>\n\nSound classification model based on 527 categories of AudioSet dataset\n\n**command line experience**\n\n```shell\npaddlespeech cls --input zh.wav\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.cls.infer import CLSExecutor\n>>> cls = CLSExecutor()\n>>> result = cls(audio_file=\"zh.wav\")\n>>> print(result)\nSpeech 0.9027186632156372\n```\n\n</details>\n\n### Voiceprint Extraction\n\n<details><summary>&emsp;Industrial-grade voiceprint extraction tool</summary>\n\n**command line experience**\n\n```shell\npaddlespeech vector --task spk --input zh.wav\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.vector import VectorExecutor\n>>> vec = VectorExecutor()\n>>> result = vec(audio_file=\"zh.wav\")\n>>> print(result) # 187维向量\n[ -0.19083306   9.474295   -14.122263    -2.0916545    0.04848729\n   4.9295826    1.4780062    0.3733844   10.695862     3.2697146\n  -4.48199     -0.6617882   -9.170393   -11.1568775   -1.2358263 ...]\n```\n\n</details>\n\n### Punctuation Restoration\n\n<details><summary>&emsp;Quick recovery of text punctuation, works with ASR models</summary>\n\n**command line experience**\n\n```shell\npaddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.text.infer import TextExecutor\n>>> text_punc = TextExecutor()\n>>> result = text_punc(text=\"今天的天气真不错啊你下午有空吗我想约你一起去吃饭\")\n今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n```\n\n</details>\n\n### Speech Translation\n\n<details><summary>&emsp;End-to-end English to Chinese Speech Translation Tool</summary>\n\nUse pre-compiled kaldi related tools, only support experience in Ubuntu system\n\n**command line experience**\n\n```shell\npaddlespeech st --input en.wav\n```\n\n**Python API experience**\n\n```python\n>>> from paddlespeech.cli.st.infer import STExecutor\n>>> st = STExecutor()\n>>> result = st(audio_file=\"en.wav\")\n['我 在 这栋 建筑 的 古老 门上 敲门 。']\n```\n\n</details>\n\n\n<a name=\"quickstartserver\"></a>\n## Quick Start Server\n\nDevelopers can have a try of our speech server with [PaddleSpeech Server Command Line](./paddlespeech/server/README.md).\n\n**You can try it quickly in AI Studio (recommend): [SpeechServer](https://aistudio.baidu.com/aistudio/projectdetail/4354592?sUid=2470186&shared=1&ts=1660877827034)**\n\n**Start server**     \n\n```shell\npaddlespeech_server start --config_file ./demos/speech_server/conf/application.yaml\n```\n\n**Access Speech Recognition Services**     \n\n```shell\npaddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n```\n\n**Access Text to Speech Services**     \n\n```shell\npaddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n```\n\n**Access Audio Classification Services**     \n```shell\npaddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input input.wav\n```\n\n\nFor more information about server command lines, please see: [speech server demos](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/speech_server)\n\n\n<a name=\"quickstartstreamingserver\"></a>\n## Quick Start Streaming Server\n\nDevelopers can have a try of  [streaming asr](./demos/streaming_asr_server/README.md) and [streaming tts](./demos/streaming_tts_server/README.md) server.\n\n**Start Streaming Speech Recognition Server**\n\n```\npaddlespeech_server start --config_file ./demos/streaming_asr_server/conf/application.yaml\n```\n\n**Access Streaming Speech Recognition Services**     \n\n```\npaddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n```\n\n**Start Streaming Text to Speech  Server**\n\n```\npaddlespeech_server start --config_file ./demos/streaming_tts_server/conf/tts_online_application.yaml\n```\n\n**Access Streaming Text to Speech Services**     \n\n```\npaddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n```\n\nFor more information please see:  [streaming asr](./demos/streaming_asr_server/README.md) and [streaming tts](./demos/streaming_tts_server/README.md) \n\n<a name=\"ModelList\"></a>\n\n## Model List\n\nPaddleSpeech supports a series of most popular models. They are summarized in [released models](./docs/source/released_model.md) and attached with available pretrained models.\n\n<a name=\"SpeechToText\"></a>\n\n**Speech-to-Text** contains *Acoustic Model*, *Language Model*, and *Speech Translation*, with the following details:\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th>Speech-to-Text Module Type</th>\n      <th>Dataset</th>\n      <th>Model Type</th>\n      <th>Example</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td rowspan=\"4\">Speech Recogination</td>\n      <td rowspan=\"2\" >Aishell</td>\n      <td >DeepSpeech2 RNN + Conv based Models</td>\n      <td>\n      <a href = \"./examples/aishell/asr0\">deepspeech2-aishell</a>\n      </td>\n    </tr>\n    <tr>\n      <td>Transformer based Attention Models </td>\n      <td>\n      <a href = \"./examples/aishell/asr1\">u2.transformer.conformer-aishell</a>\n      </td>\n    </tr>\n    <tr>\n      <td> Librispeech</td>\n      <td>Transformer based Attention Models </td>\n      <td>\n      <a href = \"./examples/librispeech/asr0\">deepspeech2-librispeech</a> / <a href = \"./examples/librispeech/asr1\">transformer.conformer.u2-librispeech</a>  / <a href = \"./examples/librispeech/asr2\">transformer.conformer.u2-kaldi-librispeech</a>\n      </td>\n      </td>\n    </tr>\n  <tr>\n      <td>TIMIT</td>\n      <td>Unified Streaming & Non-streaming Two-pass</td>\n      <td>\n    <a href = \"./examples/timit/asr1\"> u2-timit</a>\n      </td>\n  </tr>\n  <tr>\n  <td>Alignment</td>\n  <td>THCHS30</td>\n  <td>MFA</td>\n  <td>\n  <a href = \".examples/thchs30/align0\">mfa-thchs30</a>\n  </td>\n  </tr>\n   <tr>\n      <td rowspan=\"1\">Language Model</td>\n      <td colspan = \"2\">Ngram Language Model</td>\n      <td>\n      <a href = \"./examples/other/ngram_lm\">kenlm</a>\n      </td>\n    </tr>\n  <tr>\n      <td rowspan=\"2\">Speech Translation (English to Chinese)</td> \n      <td rowspan=\"2\">TED En-Zh</td>\n      <td>Transformer + ASR MTL</td>\n      <td>\n      <a href = \"./examples/ted_en_zh/st0\">transformer-ted</a>\n      </td>\n  </tr>\n  <tr>\n      <td>FAT + Transformer + ASR MTL</td>\n      <td>\n      <a href = \"./examples/ted_en_zh/st1\">fat-st-ted</a>\n      </td>\n  </tr>\n  </tbody>\n</table>\n\n<a name=\"TextToSpeech\"></a>\n\n**Text-to-Speech** in PaddleSpeech mainly contains three modules: *Text Frontend*, *Acoustic Model* and *Vocoder*. Acoustic Model and Vocoder models are listed as follow:\n\n<table>\n  <thead>\n    <tr>\n      <th> Text-to-Speech Module Type </th>\n      <th> Model Type </th>\n      <th> Dataset </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td> Text Frontend </td>\n      <td colspan=\"2\"> &emsp; </td>\n      <td>\n      <a href = \"./examples/other/tn\">tn</a> / <a href = \"./examples/other/g2p\">g2p</a>\n      </td>\n    </tr>\n    <tr>\n      <td rowspan=\"6\">Acoustic Model</td>\n      <td>Tacotron2</td>\n      <td>LJSpeech / CSMSC</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts0\">tacotron2-ljspeech</a> / <a href = \"./examples/csmsc/tts0\">tacotron2-csmsc</a>\n      </td>\n    </tr>\n    <tr>\n      <td>Transformer TTS</td>\n      <td>LJSpeech</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts1\">transformer-ljspeech</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SpeedySpeech</td>\n      <td>CSMSC</td>\n      <td >\n      <a href = \"./examples/csmsc/tts2\">speedyspeech-csmsc</a>\n      </td>\n    </tr>\n    <tr>\n      <td>FastSpeech2</td>\n      <td>LJSpeech / VCTK / CSMSC / AISHELL-3 / ZH_EN / finetune</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts3\">fastspeech2-ljspeech</a> / <a href = \"./examples/vctk/tts3\">fastspeech2-vctk</a> / <a href = \"./examples/csmsc/tts3\">fastspeech2-csmsc</a> / <a href = \"./examples/aishell3/tts3\">fastspeech2-aishell3</a> / <a href = \"./examples/zh_en_tts/tts3\">fastspeech2-zh_en</a> / <a href = \"./examples/other/tts_finetune/tts3\">fastspeech2-finetune</a>\n      </td>\n    </tr>\n    <tr>\n      <td><a href = \"https://arxiv.org/abs/2211.03545\">ERNIE-SAT</a></td>\n      <td>VCTK / AISHELL-3 / ZH_EN</td>\n      <td>\n      <a href = \"./examples/vctk/ernie_sat\">ERNIE-SAT-vctk</a> / <a href = \"./examples/aishell3/ernie_sat\">ERNIE-SAT-aishell3</a> / <a href = \"./examples/aishell3_vctk/ernie_sat\">ERNIE-SAT-zh_en</a>\n      </td>\n    </tr>\n    <tr>\n      <td>DiffSinger</td>\n      <td>Opencpop</td>\n      <td>\n      <a href = \"./examples/opencpop/svs1\">DiffSinger-opencpop</a>\n      </td>\n   </tr>\n   <tr>\n      <td rowspan=\"6\">Vocoder</td>\n      <td >WaveFlow</td>\n      <td >LJSpeech</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc0\">waveflow-ljspeech</a>\n      </td>\n    </tr>\n    <tr>\n      <td >Parallel WaveGAN</td>\n      <td >LJSpeech / VCTK / CSMSC / AISHELL-3 / Opencpop</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc1\">PWGAN-ljspeech</a> / <a href = \"./examples/vctk/voc1\">PWGAN-vctk</a> / <a href = \"./examples/csmsc/voc1\">PWGAN-csmsc</a> /  <a href = \"./examples/aishell3/voc1\">PWGAN-aishell3</a> / <a href = \"./examples/opencpop/voc1\">PWGAN-opencpop</a>\n      </td>\n    </tr>\n    <tr>\n      <td >Multi Band MelGAN</td>\n      <td >CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc3\">Multi Band MelGAN-csmsc</a> \n      </td>\n    </tr> \n    <tr>\n      <td >Style MelGAN</td>\n      <td >CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc4\">Style MelGAN-csmsc</a> \n      </td>\n    </tr>\n    <tr>\n      <td>HiFiGAN</td>\n      <td>LJSpeech / VCTK / CSMSC / AISHELL-3 / Opencpop</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc5\">HiFiGAN-ljspeech</a> / <a href = \"./examples/vctk/voc5\">HiFiGAN-vctk</a> / <a href = \"./examples/csmsc/voc5\">HiFiGAN-csmsc</a> / <a href = \"./examples/aishell3/voc5\">HiFiGAN-aishell3</a> / <a href = \"./examples/opencpop/voc5\">HiFiGAN-opencpop</a>\n      </td>\n    </tr>\n    <tr>\n      <td>WaveRNN</td>\n      <td>CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc6\">WaveRNN-csmsc</a>\n      </td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">Voice Cloning</td>\n      <td>GE2E</td>\n      <td >Librispeech, etc.</td>\n      <td>\n      <a href = \"./examples/other/ge2e\">GE2E</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (GE2E + Tacotron2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc0\">VC0</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (GE2E + FastSpeech2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc1\">VC1</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (ECAPA-TDNN + FastSpeech2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc2\">VC2</a>\n      </td>\n    </tr>\n    <tr>\n      <td>GE2E + VITS</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vits-vc\">VITS-VC</a>\n      </td>\n    </tr>\n    <tr>\n      <td rowspan=\"3\">End-to-End</td>\n      <td>VITS</td>\n      <td>CSMSC / AISHELL-3</td>\n      <td>\n      <a href = \"./examples/csmsc/vits\">VITS-csmsc</a> / <a href = \"./examples/aishell3/vits\">VITS-aishell3</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"AudioClassification\"></a>\n\n**Audio Classification**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Task </th>\n      <th> Dataset </th>\n      <th> Model Type </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>Audio Classification</td>\n      <td>ESC-50</td>\n      <td>PANN</td>\n      <td>\n      <a href = \"./examples/esc50/cls0\">pann-esc50</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"KeywordSpotting\"></a>\n\n**Keyword Spotting**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Task </th>\n      <th> Dataset </th>\n      <th> Model Type </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>Keyword Spotting</td>\n      <td>hey-snips</td>\n      <td>MDTC</td>\n      <td>\n      <a href = \"./examples/hey_snips/kws0\">mdtc-hey-snips</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"SpeakerVerification\"></a>\n\n**Speaker Verification**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Task </th>\n      <th> Dataset </th>\n      <th> Model Type </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>Speaker Verification</td>\n      <td>VoxCeleb1/2</td>\n      <td>ECAPA-TDNN</td>\n      <td>\n      <a href = \"./examples/voxceleb/sv0\">ecapa-tdnn-voxceleb12</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"SpeakerDiarization\"></a>\n\n**Speaker Diarization**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Task </th>\n      <th> Dataset </th>\n      <th> Model Type </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>Speaker Diarization</td>\n     <td>AMI</td>\n      <td>ECAPA-TDNN + AHC / SC</td>\n      <td>\n      <a href = \"./examples/ami/sd0\">ecapa-tdnn-ami</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"PunctuationRestoration\"></a>\n\n**Punctuation Restoration**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> Task </th>\n      <th> Dataset </th>\n      <th> Model Type </th>\n      <th> Example </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>Punctuation Restoration</td>\n      <td>IWLST2012_zh</td>\n      <td>Ernie Linear</td>\n      <td>\n      <a href = \"./examples/iwslt2012/punc0\">iwslt2012-punc0</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n## Documents\n\nNormally, [Speech SoTA](https://paperswithcode.com/area/speech), [Audio SoTA](https://paperswithcode.com/area/audio) and [Music SoTA](https://paperswithcode.com/area/music) give you an overview of the hot academic topics in the related area. To focus on the tasks in PaddleSpeech, you will find the following guidelines are helpful to grasp the core ideas.\n\n- [Installation](./docs/source/install.md)\n- [Quick Start](#quickstart)\n- [Some Demos](./demos/README.md)\n- Tutorials\n  - [Automatic Speech Recognition](./docs/source/asr/quick_start.md)\n    - [Introduction](./docs/source/asr/models_introduction.md)\n    - [Data Preparation](./docs/source/asr/data_preparation.md)\n    - [Ngram LM](./docs/source/asr/ngram_lm.md)\n  - [Text-to-Speech](./docs/source/tts/quick_start.md)\n    - [Introduction](./docs/source/tts/models_introduction.md)\n    - [Advanced Usage](./docs/source/tts/advanced_usage.md)\n    - [Chinese Rule Based Text Frontend](./docs/source/tts/zh_text_frontend.md)\n    - [Test Audio Samples](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html)\n  - Speaker Verification\n    - [Audio Searching](./demos/audio_searching/README.md)\n    - [Speaker Verification](./demos/speaker_verification/README.md)\n  - [Audio Classification](./demos/audio_tagging/README.md)\n  - [Speech Translation](./demos/speech_translation/README.md)\n  - [Speech Server](./demos/speech_server/README.md)\n- [Released Models](./docs/source/released_model.md)\n  - [Speech-to-Text](#SpeechToText)\n  - [Text-to-Speech](#TextToSpeech)\n  - [Audio Classification](#AudioClassification)\n  - [Speaker Verification](#SpeakerVerification)\n  - [Speaker Diarization](#SpeakerDiarization)\n  - [Punctuation Restoration](#PunctuationRestoration)\n- [Community](#Community)\n- [Welcome to contribute](#contribution)\n- [License](#License)\n\nThe Text-to-Speech module is originally called [Parakeet](https://github.com/PaddlePaddle/Parakeet), and now merged with this repository. If you are interested in academic research about this task, please see [TTS research overview](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/docs/source/tts#overview). Also, [this document](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/tts/models_introduction.md) is a good guideline for the pipeline components.\n\n\n## ⭐ Examples\n- **[PaddleBoBo](https://github.com/JiehangXie/PaddleBoBo): Use PaddleSpeech TTS to generate virtual human voice.**\n  \n<div align=\"center\"><a href=\"https://www.bilibili.com/video/BV1cL411V71o?share_source=copy_web\"><img src=\"https://ai-studio-static-online.cdn.bcebos.com/06fd746ab32042f398fb6f33f873e6869e846fe63c214596ae37860fe8103720\" / width=\"500px\"></a></div>\n\n- [PaddleSpeech Demo Video](https://paddlespeech.readthedocs.io/en/latest/demo_video.html)\n\n- **[VTuberTalk](https://github.com/jerryuhoo/VTuberTalk): Use PaddleSpeech TTS and ASR to clone voice from videos.**\n\n\n## Citation\n\nTo cite PaddleSpeech for research, please use the following format.\n\n```text\n@inproceedings{zhang2022paddlespeech,\n    title = {PaddleSpeech: An Easy-to-Use All-in-One Speech Toolkit},\n    author = {Hui Zhang, Tian Yuan, Junkun Chen, Xintong Li, Renjie Zheng, Yuxin Huang, Xiaojie Chen, Enlei Gong, Zeyu Chen, Xiaoguang Hu, dianhai yu, Yanjun Ma, Liang Huang},\n    booktitle = {Proceedings of the 2022 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies: Demonstrations},\n    year = {2022},\n    publisher = {Association for Computational Linguistics},\n}\n\n@InProceedings{pmlr-v162-bai22d,\n  title = {{A}$^3${T}: Alignment-Aware Acoustic and Text Pretraining for Speech Synthesis and Editing},\n  author = {Bai, He and Zheng, Renjie and Chen, Junkun and Ma, Mingbo and Li, Xintong and Huang, Liang},\n  booktitle = {Proceedings of the 39th International Conference on Machine Learning},\n  pages = {1399--1411},\n  year = {2022},\n  volume = {162},\n  series = {Proceedings of Machine Learning Research},\n  month = {17--23 Jul},\n  publisher = {PMLR},\n  pdf = {https://proceedings.mlr.press/v162/bai22d/bai22d.pdf},\n  url = {https://proceedings.mlr.press/v162/bai22d.html},\n}\n\n@inproceedings{zheng2021fused,\n  title={Fused acoustic and text encoding for multimodal bilingual pretraining and speech translation},\n  author={Zheng, Renjie and Chen, Junkun and Ma, Mingbo and Huang, Liang},\n  booktitle={International Conference on Machine Learning},\n  pages={12736--12746},\n  year={2021},\n  organization={PMLR}\n}\n```\n\n<a name=\"contribution\"></a>\n## Contribute to PaddleSpeech\n\nYou are warmly welcome to submit questions in [discussions](https://github.com/PaddlePaddle/PaddleSpeech/discussions) and bug reports in [issues](https://github.com/PaddlePaddle/PaddleSpeech/issues)! Also, we highly appreciate if you are willing to contribute to this project!\n\n### Contributors\n<p align=\"center\">\n<a href=\"https://github.com/zh794390558\"><img src=\"https://avatars.githubusercontent.com/u/3038472?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Jackwaterveg\"><img src=\"https://avatars.githubusercontent.com/u/87408988?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/yt605155624\"><img src=\"https://avatars.githubusercontent.com/u/24568452?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Honei\"><img src=\"https://avatars.githubusercontent.com/u/11361692?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/KPatr1ck\"><img src=\"https://avatars.githubusercontent.com/u/22954146?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kuke\"><img src=\"https://avatars.githubusercontent.com/u/3064195?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lym0302\"><img src=\"https://avatars.githubusercontent.com/u/34430015?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/SmileGoat\"><img src=\"https://avatars.githubusercontent.com/u/56786796?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/xinghai-sun\"><img src=\"https://avatars.githubusercontent.com/u/7038341?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/pkuyym\"><img src=\"https://avatars.githubusercontent.com/u/5782283?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/LittleChenCc\"><img src=\"https://avatars.githubusercontent.com/u/10339970?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/qingen\"><img src=\"https://avatars.githubusercontent.com/u/3139179?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/D-DanielYang\"><img src=\"https://avatars.githubusercontent.com/u/23690325?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Mingxue-Xu\"><img src=\"https://avatars.githubusercontent.com/u/92848346?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/745165806\"><img src=\"https://avatars.githubusercontent.com/u/20623194?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/jerryuhoo\"><img src=\"https://avatars.githubusercontent.com/u/24245709?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/WilliamZhang06\"><img src=\"https://avatars.githubusercontent.com/u/97937340?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chrisxu2016\"><img src=\"https://avatars.githubusercontent.com/u/18379485?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/iftaken\"><img src=\"https://avatars.githubusercontent.com/u/30135920?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lfchener\"><img src=\"https://avatars.githubusercontent.com/u/6771821?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/BarryKCL\"><img src=\"https://avatars.githubusercontent.com/u/48039828?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/mmglove\"><img src=\"https://avatars.githubusercontent.com/u/38800877?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/gongel\"><img src=\"https://avatars.githubusercontent.com/u/24390500?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/luotao1\"><img src=\"https://avatars.githubusercontent.com/u/6836917?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/wanghaoshuang\"><img src=\"https://avatars.githubusercontent.com/u/7534971?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kslz\"><img src=\"https://avatars.githubusercontent.com/u/54951765?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/JiehangXie\"><img src=\"https://avatars.githubusercontent.com/u/51190264?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/david-95\"><img src=\"https://avatars.githubusercontent.com/u/15189190?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/THUzyt21\"><img src=\"https://avatars.githubusercontent.com/u/91456992?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/buchongyu2\"><img src=\"https://avatars.githubusercontent.com/u/29157444?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/iclementine\"><img src=\"https://avatars.githubusercontent.com/u/16222986?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/phecda-xu\"><img src=\"https://avatars.githubusercontent.com/u/46859427?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/freeliuzc\"><img src=\"https://avatars.githubusercontent.com/u/23568094?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ZeyuChen\"><img src=\"https://avatars.githubusercontent.com/u/1371212?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ccrrong\"><img src=\"https://avatars.githubusercontent.com/u/101700995?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AK391\"><img src=\"https://avatars.githubusercontent.com/u/81195143?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/qingqing01\"><img src=\"https://avatars.githubusercontent.com/u/7845005?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/0x45f\"><img src=\"https://avatars.githubusercontent.com/u/23097963?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/vpegasus\"><img src=\"https://avatars.githubusercontent.com/u/22723154?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ericxk\"><img src=\"https://avatars.githubusercontent.com/u/4719594?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Betterman-qs\"><img src=\"https://avatars.githubusercontent.com/u/61459181?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/sneaxiy\"><img src=\"https://avatars.githubusercontent.com/u/32832641?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Doubledongli\"><img src=\"https://avatars.githubusercontent.com/u/20540661?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/apps/dependabot\"><img src=\"https://avatars.githubusercontent.com/in/29110?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kvinwang\"><img src=\"https://avatars.githubusercontent.com/u/6442159?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chenkui164\"><img src=\"https://avatars.githubusercontent.com/u/34813030?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/PaddleZhang\"><img src=\"https://avatars.githubusercontent.com/u/97284124?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/billishyahao\"><img src=\"https://avatars.githubusercontent.com/u/96406262?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/BrightXiaoHan\"><img src=\"https://avatars.githubusercontent.com/u/25839309?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/jiqiren11\"><img src=\"https://avatars.githubusercontent.com/u/82639260?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ryanrussell\"><img src=\"https://avatars.githubusercontent.com/u/523300?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/GT-ZhangAcer\"><img src=\"https://avatars.githubusercontent.com/u/46156734?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/tensor-tang\"><img src=\"https://avatars.githubusercontent.com/u/21351065?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/hysunflower\"><img src=\"https://avatars.githubusercontent.com/u/52739577?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/oyjxer\"><img src=\"https://avatars.githubusercontent.com/u/16233945?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/JamesLim-sy\"><img src=\"https://avatars.githubusercontent.com/u/61349199?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/limpidezza\"><img src=\"https://avatars.githubusercontent.com/u/71760778?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/windstamp\"><img src=\"https://avatars.githubusercontent.com/u/34057289?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AshishKarel\"><img src=\"https://avatars.githubusercontent.com/u/58069375?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chesterkuo\"><img src=\"https://avatars.githubusercontent.com/u/6285069?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/YDX-2147483647\"><img src=\"https://avatars.githubusercontent.com/u/73375426?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AdamBear\"><img src=\"https://avatars.githubusercontent.com/u/2288870?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/wwhu\"><img src=\"https://avatars.githubusercontent.com/u/6081200?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lispc\"><img src=\"https://avatars.githubusercontent.com/u/2833376?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/harisankarh\"><img src=\"https://avatars.githubusercontent.com/u/1307053?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/pengzhendong\"><img src=\"https://avatars.githubusercontent.com/u/10704539?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Jackiexiao\"><img src=\"https://avatars.githubusercontent.com/u/18050469?s=60&v=4\" width=75 height=75></a>\n</p>\n\n## Acknowledgement\n- Many thanks to [HighCWu](https://github.com/HighCWu) for adding [VITS-aishell3](./examples/aishell3/vits) and [VITS-VC](./examples/aishell3/vits-vc) examples.\n- Many thanks to [david-95](https://github.com/david-95) for fixing multi-punctuation bug、contributing to multiple program and data, and adding [SSML](https://github.com/PaddlePaddle/PaddleSpeech/discussions/2538) for TTS Chinese Text Frontend. \n- Many thanks to [BarryKCL](https://github.com/BarryKCL) for improving TTS Chinses Frontend based on [G2PW](https://github.com/GitYCC/g2pW).\n- Many thanks to [yeyupiaoling](https://github.com/yeyupiaoling)/[PPASR](https://github.com/yeyupiaoling/PPASR)/[PaddlePaddle-DeepSpeech](https://github.com/yeyupiaoling/PaddlePaddle-DeepSpeech)/[VoiceprintRecognition-PaddlePaddle](https://github.com/yeyupiaoling/VoiceprintRecognition-PaddlePaddle)/[AudioClassification-PaddlePaddle](https://github.com/yeyupiaoling/AudioClassification-PaddlePaddle) for years of attention, constructive advice and great help.\n- Many thanks to [mymagicpower](https://github.com/mymagicpower) for the Java implementation of ASR upon [short](https://github.com/mymagicpower/AIAS/tree/main/3_audio_sdks/asr_sdk) and [long](https://github.com/mymagicpower/AIAS/tree/main/3_audio_sdks/asr_long_audio_sdk) audio files.\n- Many thanks to [JiehangXie](https://github.com/JiehangXie)/[PaddleBoBo](https://github.com/JiehangXie/PaddleBoBo) for developing Virtual Uploader(VUP)/Virtual YouTuber(VTuber) with PaddleSpeech TTS function.\n- Many thanks to [745165806](https://github.com/745165806)/[PaddleSpeechTask](https://github.com/745165806/PaddleSpeechTask) for contributing Punctuation Restoration model.\n- Many thanks to [kslz](https://github.com/745165806) for supplementary Chinese documents.\n- Many thanks to [awmmmm](https://github.com/awmmmm) for contributing fastspeech2 aishell3 conformer pretrained model.\n- Many thanks to [phecda-xu](https://github.com/phecda-xu)/[PaddleDubbing](https://github.com/phecda-xu/PaddleDubbing) for developing a dubbing tool with GUI based on PaddleSpeech TTS model.\n- Many thanks to [jerryuhoo](https://github.com/jerryuhoo)/[VTuberTalk](https://github.com/jerryuhoo/VTuberTalk) for developing a GUI tool based on PaddleSpeech TTS and code for making datasets from videos based on PaddleSpeech ASR.\n- Many thanks to [vpegasus](https://github.com/vpegasus)/[xuesebot](https://github.com/vpegasus/xuesebot) for developing a rasa chatbot,which is able to speak and listen thanks to PaddleSpeech.\n- Many thanks to [chenkui164](https://github.com/chenkui164)/[FastASR](https://github.com/chenkui164/FastASR) for the C++ inference implementation of PaddleSpeech ASR.\n- Many thanks to [heyudage](https://github.com/heyudage)/[VoiceTyping](https://github.com/heyudage/VoiceTyping) for the real-time voice typing tool implementation of PaddleSpeech ASR streaming services.\n- Many thanks to [EscaticZheng](https://github.com/EscaticZheng)/[ps3.9wheel-install](https://github.com/EscaticZheng/ps3.9wheel-install) for the python3.9 prebuilt wheel for PaddleSpeech installation in Windows without Visual Studio.\nBesides, PaddleSpeech depends on a lot of open source repositories. See [references](./docs/source/reference.md) for more information.\n- Many thanks to [chinobing](https://github.com/chinobing)/[FastAPI-PaddleSpeech-Audio-To-Text](https://github.com/chinobing/FastAPI-PaddleSpeech-Audio-To-Text) for converting audio to text based on FastAPI and PaddleSpeech.\n- Many thanks to [MistEO](https://github.com/MistEO)/[Pallas-Bot](https://github.com/MistEO/Pallas-Bot) for QQ bot based on PaddleSpeech TTS.\n\n<a name=\"License\"></a>\n## License\n\nPaddleSpeech is provided under the [Apache-2.0 License](./LICENSE).\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/PaddlePaddle/PaddleSpeech.svg)](https://starchart.cc/PaddlePaddle/PaddleSpeech)\n"
  },
  {
    "path": "README_cn.md",
    "content": "(简体中文|[English](./README.md))\n<p align=\"center\">\n  <img src=\"./docs/images/PaddleSpeech_logo.png\" />\n</p>\n\n\n<p align=\"center\">\n    <a href=\"./LICENSE\"><img src=\"https://img.shields.io/badge/license-Apache%202-red.svg\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/releases\"><img src=\"https://img.shields.io/github/v/release/PaddlePaddle/PaddleSpeech?color=ffa\"></a>\n    <a href=\"support os\"><img src=\"https://img.shields.io/badge/os-linux%2C%20win%2C%20mac-pink.svg\"></a>\n    <a href=\"\"><img src=\"https://img.shields.io/badge/python-3.8+-aff.svg\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/graphs/contributors\"><img src=\"https://img.shields.io/github/contributors/PaddlePaddle/PaddleSpeech?color=9ea\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/commits\"><img src=\"https://img.shields.io/github/commit-activity/m/PaddlePaddle/PaddleSpeech?color=3af\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/issues\"><img src=\"https://img.shields.io/github/issues/PaddlePaddle/PaddleSpeech?color=9cc\"></a>\n    <a href=\"https://github.com/PaddlePaddle/PaddleSpeech/stargazers\"><img src=\"https://img.shields.io/github/stars/PaddlePaddle/PaddleSpeech?color=ccf\"></a>\n    <a href=\"=https://pypi.org/project/paddlespeech/\"><img src=\"https://img.shields.io/pypi/dm/PaddleSpeech\"></a>\n    <a href=\"=https://pypi.org/project/paddlespeech/\"><img src=\"https://static.pepy.tech/badge/paddlespeech\"></a>\n    <a href=\"https://huggingface.co/spaces\"><img src=\"https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue\"></a>\n</p>\n<div align=\"center\">  \n<h4>\n    <a href=\"#安装\"> 安装 </a>\n  | <a href=\"#快速开始\"> 快速开始 </a>\n  | <a href=\"#教程文档\"> 教程文档 </a>\n  | <a href=\"#模型列表\"> 模型列表 </a>\n  | <a href=\"https://aistudio.baidu.com/aistudio/course/introduce/25130\"> AIStudio 课程 </a>\n  | <a href=\"https://arxiv.org/abs/2205.12007\"> NAACL2022 论文 </a>\n  | <a href=\"https://gitee.com/paddlepaddle/PaddleSpeech\"> Gitee \n</h4>\n</div>\n\n\n------------------------------------------------------------------------------------\n\n**PaddleSpeech** 是基于飞桨 [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) 的语音方向的开源模型库，用于语音和音频中的各种关键任务的开发，包含大量基于深度学习前沿和有影响力的模型，一些典型的应用示例如下：\n\n**PaddleSpeech** 荣获 [NAACL2022 Best Demo Award](https://2022.naacl.org/blog/best-demo-award/), 请访问 [Arxiv](https://arxiv.org/abs/2205.12007) 论文。\n  \n### 效果展示\n\n##### 语音识别\n\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 输入音频  </th>\n      <th width=\"550\"> 识别结果 </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td >I knocked at the door on the ancient side of the building.</td>\n    </tr>\n    <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td>我认为跑步最重要的就是给我带来了身体健康。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n##### 语音翻译 (英译中)\n\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 输入音频 </th>\n      <th width=\"550\"> 翻译结果 </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n      <td >我 在 这栋 建筑 的 古老 门上 敲门。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n##### 语音合成\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th width=\"550\">输入文本</th>\n      <th>合成音频</th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td >Life was like a box of chocolates, you never know what you're gonna get.</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_1.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td >早上好，今天是2020/10/29，最低温度是-3°C。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/001.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td >季姬寂，集鸡，鸡即棘鸡。棘鸡饥叽，季姬及箕稷济鸡。鸡既济，跻姬笈，季姬忌，急咭鸡，鸡急，继圾几，季姬急，即籍箕击鸡，箕疾击几伎，伎即齑，鸡叽集几基，季姬急极屐击鸡，鸡既殛，季姬激，即记《季姬击鸡记》。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/jijiji.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>大家好，我是 parrot 虚拟老师，我们来读一首诗，我与春风皆过客，I and the spring breeze are passing by，你携秋水揽星河，you take the autumn water to take the galaxy。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/labixiaoxin.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>宜家唔系事必要你讲，但系你所讲嘅说话将会变成呈堂证供。</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/chengtangzhenggong.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td>各个国家有各个国家嘅国歌</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/gegege.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"./docs/images/audio_icon.png\" width=\"200\" style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n更多合成音频，可以参考 [PaddleSpeech 语音合成音频示例](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html)。\n\n##### 标点恢复\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th width=\"390\"> 输入文本 </th>\n      <th width=\"390\"> 输出文本 </th>\n    </tr>\n  </thead>\n  <tbody>\n   <tr>\n      <td>今天的天气真不错啊你下午有空吗我想约你一起去吃饭</td>\n      <td>今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。</td>\n    </tr>\n  </tbody>\n</table>\n\n</div>\n\n\n### 特性\n\n本项目采用了易用、高效、灵活以及可扩展的实现，旨在为工业应用、学术研究提供更好的支持，实现的功能包含训练、推断以及测试模块，以及部署过程，主要包括\n- 📦 **易用性**: 安装门槛低，可使用 [CLI](#quick-start) 快速开始。\n- 🏆 **对标 SoTA**: 提供了高速、轻量级模型，且借鉴了最前沿的技术。\n- 🏆 **流式 ASR 和 TTS 系统**：工业级的端到端流式识别、流式合成系统。\n- 💯 **基于规则的中文前端**: 我们的前端包含文本正则化和字音转换（G2P）。此外，我们使用自定义语言规则来适应中文语境。\n- **多种工业界以及学术界主流功能支持**:\n  - 🛎️ 典型音频任务: 本工具包提供了音频任务如音频分类、语音翻译、自动语音识别、文本转语音、语音合成、声纹识别、KWS等任务的实现。\n  - 🔬 主流模型及数据集: 本工具包实现了参与整条语音任务流水线的各个模块，并且采用了主流数据集如 LibriSpeech、LJSpeech、AIShell、CSMSC，详情请见 [模型列表](#model-list)。\n  - 🧩 级联模型应用: 作为传统语音任务的扩展，我们结合了自然语言处理、计算机视觉等任务，实现更接近实际需求的产业级应用。\n\n### 近期更新\n- 🎉 2025.09.01: 新增 [Whisper large v3 与 turbo 模型](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/whisper).\n- 🤗 2025.08.11: 新增 [流式中英混合 tal_cs 识别模型](./examples/tal_cs/asr1/).\n- 👑 2023.05.31: 新增 [WavLM ASR-en](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/librispeech/asr5), 基于WavLM的英语识别微调，使用LibriSpeech数据集\n- 🎉 2023.05.18: 新增 [Squeezeformer](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell/asr1), 使用Squeezeformer进行训练，使用Aishell数据集\n- 👑 2023.05.04: 新增 [HuBERT ASR-en](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/librispeech/asr4), 基于HuBERT的英语识别微调，使用LibriSpeech数据集\n- ⚡ 2023.04.28: 修正 [0-d tensor](https://github.com/PaddlePaddle/PaddleSpeech/pull/3214), 配合PaddlePaddle2.5升级修改了0-d tensor的问题。\n- 👑 2023.04.25: 新增 [U2 conformer 的 AMP 训练](https://github.com/PaddlePaddle/PaddleSpeech/pull/3167).\n- 👑 2023.04.06: 新增 [srt格式字幕生成功能](./demos/streaming_asr_server)。\n- 🔥 2023.03.14: 新增基于 Opencpop 数据集的 SVS (歌唱合成) 示例，包含 [DiffSinger](./examples/opencpop/svs1)、[PWGAN](./examples/opencpop/voc1) 和 [HiFiGAN](./examples/opencpop/voc5)，效果持续优化中。\n- 👑 2023.03.09: 新增 [Wav2vec2ASR-zh](./examples/aishell/asr3)。\n- 🎉 2023.03.07: 新增 [TTS ARM Linux C++ 部署示例 (包含 C++ 中文文本前端模块)](./demos/TTSArmLinux)。\n- 🔥 2023.03.03: 新增声音转换模型 [StarGANv2-VC 合成流程](./examples/vctk/vc3)。\n- 🎉 2023.02.16: 新增[粤语语音合成](./examples/canton/tts3)。\n- 🔥 2023.01.10: 新增[中英混合 ASR CLI 和 Demos](./demos/speech_recognition)。\n- 👑 2023.01.06: 新增 [ASR 中英混合 tal_cs 训练推理流程](./examples/tal_cs/asr1/)。\n- 🎉 2022.12.02: 新增[端到端韵律预测全流程](./examples/csmsc/tts3_rhy) (包含在声学模型中使用韵律标签)。\n- 🎉 2022.11.30: 新增 [TTS Android 部署示例](./demos/TTSAndroid)。\n- 🤗 2022.11.28: PP-TTS and PP-ASR 示例可在 [AIStudio](https://aistudio.baidu.com/aistudio/modelsoverview) 和[飞桨官网](https://www.paddlepaddle.org.cn/models)体验！\n- 👑 2022.11.18: 新增 [Whisper CLI 和 Demos](https://github.com/PaddlePaddle/PaddleSpeech/pull/2640), 支持多种语言的识别与翻译。\n- 🔥 2022.11.18: 新增 [Wav2vec2 CLI 和 Demos](./demos/speech_ssl), 支持 ASR 和特征提取。\n- 🎉 2022.11.17: TTS 新增[高质量男性音色](https://github.com/PaddlePaddle/PaddleSpeech/pull/2660)。\n- 🔥 2022.11.07: 新增 [U2/U2++ 高性能流式 ASR C++ 部署](./speechx/examples/u2pp_ol/wenetspeech)。\n- 👑 2022.11.01: [中英文混合 TTS](./examples/zh_en_tts/tts3) 新增 [Adversarial Loss](https://arxiv.org/pdf/1907.04448.pdf) 模块。\n- 🔥 2022.10.26: TTS 新增[韵律预测](./develop/examples/other/rhy)功能。\n- 🎉 2022.10.21: TTS 中文文本前端新增 [SSML](https://github.com/PaddlePaddle/PaddleSpeech/discussions/2538) 功能。\n- 👑 2022.10.11: 新增 [Wav2vec2ASR-en](./examples/librispeech/asr3), 在 LibriSpeech 上针对 ASR 任务对 wav2vec2.0 的 finetuning。\n- 🔥 2022.09.26: 新增 Voice Cloning, TTS finetune 和 [ERNIE-SAT](https://arxiv.org/abs/2211.03545) 到 [PaddleSpeech 网页应用](./demos/speech_web)。\n- ⚡ 2022.09.09: 新增基于 ECAPA-TDNN 声纹模型的 AISHELL-3 Voice Cloning [示例](./examples/aishell3/vc2)。\n- ⚡ 2022.08.25: 发布 TTS [finetune](./examples/other/tts_finetune/tts3) 示例。\n- 🔥 2022.08.22: 新增 [ERNIE-SAT](https://arxiv.org/abs/2211.03545) 模型: [ERNIE-SAT-vctk](./examples/vctk/ernie_sat)、[ERNIE-SAT-aishell3](./examples/aishell3/ernie_sat)、[ERNIE-SAT-zh_en](./examples/aishell3_vctk/ernie_sat)。\n- 🔥 2022.08.15: 将 [g2pW](https://github.com/GitYCC/g2pW) 引入 TTS 中文文本前端。\n- 🔥 2022.08.09: 发布[中英文混合 TTS](./examples/zh_en_tts/tts3)。\n- ⚡ 2022.08.03: TTS CLI 新增 ONNXRuntime 推理方式。\n- 🎉 2022.07.18: 发布 VITS 模型: [VITS-csmsc](./examples/csmsc/vits)、[VITS-aishell3](./examples/aishell3/vits)、[VITS-VC](./examples/aishell3/vits-vc)。\n- 🎉 2022.06.22: 所有 TTS 模型支持了 ONNX 格式。\n- 🍀 2022.06.17: 新增 [PaddleSpeech 网页应用](./demos/speech_web)。\n- 👑 2022.05.13: PaddleSpeech 发布 [PP-ASR](./docs/source/asr/PPASR_cn.md) 流式语音识别系统、[PP-TTS](./docs/source/tts/PPTTS_cn.md) 流式语音合成系统、[PP-VPR](docs/source/vpr/PPVPR_cn.md) 全链路声纹识别系统\n- 👏🏻 2022.05.06: PaddleSpeech Streaming Server 上线！覆盖了语音识别（标点恢复、时间戳）和语音合成。\n- 👏🏻 2022.05.06: PaddleSpeech Server 上线！覆盖了声音分类、语音识别、语音合成、声纹识别，标点恢复。\n- 👏🏻 2022.03.28: PaddleSpeech CLI 覆盖声音分类、语音识别、语音翻译（英译中）、语音合成和声纹验证。\n- 👏🏻 2021.12.10: PaddleSpeech CLI 支持语音分类, 语音识别, 语音翻译（英译中）和语音合成。\n\n\n ### 🔥 加入技术交流群获取入群福利\n\n - 3 日直播课链接: 深度解读 【一句话语音合成】【小样本语音合成】【定制化语音识别】语音交互技术\n - 20G 学习大礼包：视频课程、前沿论文与学习资料\n  \n微信扫描二维码关注公众号，点击“马上报名”填写问卷加入官方交流群，获得更高效的问题答疑，与各行各业开发者充分交流，期待您的加入。\n\n<div align=\"center\">\n<img src=\"https://user-images.githubusercontent.com/30135920/212860467-9e943cc3-8be8-49a4-97fd-7c94aad8e979.jpg\"  width = \"200\"  />\n</div>\n\n<a name=\"安装\"></a>\n## 安装\n\n我们强烈建议用户在 **Linux** 环境下，*3.8* 以上版本的 *python* 上安装 PaddleSpeech。\n\n### 相关依赖\n+ gcc >= 4.8.5\n+ paddlepaddle\n+ python >= 3.8\n+ linux(推荐), mac, windows\n\nPaddleSpeech 依赖于 paddlepaddle，安装可以参考[ paddlepaddle 官网](https://www.paddlepaddle.org.cn/)，根据自己机器的情况进行选择。这里给出 cpu 版本示例，其它版本大家可以根据自己机器的情况进行安装。\n\n```shell\npip install paddlepaddle -i https://mirror.baidu.com/pypi/simple\n```\n你也可以安装指定版本的paddlepaddle，或者安装 develop 版本。\n```bash\n# 安装2.4.1版本. 注意：2.4.1只是一个示例，请按照对paddlepaddle的最小依赖进行选择。\npip install paddlepaddle==2.4.1 -i https://mirror.baidu.com/pypi/simple\n# 安装 develop 版本\npip install paddlepaddle==0.0.0 -f https://www.paddlepaddle.org.cn/whl/linux/cpu-mkl/develop.html\n```\nPaddleSpeech 快速安装方式有两种，一种是 pip 安装，一种是源码编译（推荐）。\n\n### pip 安装\n```shell\npip install pytest-runner\npip install paddlespeech\n```\n\n### 源码编译\n```shell\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\ncd PaddleSpeech\npip install pytest-runner\npip install .\n# 如果需要在可编辑模式下安装，需要使用 --use-pep517，命令如下\n# pip install -e . --use-pep517\n```\n\n更多关于安装问题，如 conda 环境，librosa 依赖的系统库，gcc 环境问题，kaldi 安装等，可以参考这篇[安装文档](docs/source/install_cn.md)，如安装上遇到问题可以在 [#2150](https://github.com/PaddlePaddle/PaddleSpeech/issues/2150) 上留言以及查找相关问题\n\n<a name=\"快速开始\"></a>\n## 快速开始\n安装完成后，开发者可以通过命令行或者 Python 快速开始，命令行模式下改变 `--input` 可以尝试用自己的音频或文本测试，支持 16k wav 格式音频。\n\n你也可以在 `aistudio` 中快速体验 👉🏻[一键预测，快速上手 Speech 开发任务](https://aistudio.baidu.com/aistudio/projectdetail/4353348?sUid=2470186&shared=1&ts=1660878142250)。\n\n测试音频示例下载\n```shell\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n\n### 语音识别\n<details><summary>&emsp;（点击可展开）开源中文语音识别</summary>\n\n命令行一键体验\n\n```shell\npaddlespeech asr --lang zh --input zh.wav\n```\n\nPython API 一键预测\n\n```python\n>>> from paddlespeech.cli.asr.infer import ASRExecutor\n>>> asr = ASRExecutor()\n>>> result = asr(audio_file=\"zh.wav\")\n>>> print(result)\n我认为跑步最重要的就是给我带来了身体健康\n```\n</details>\n\n### 语音合成\n\n<details><summary>&emsp;开源中文语音合成</summary>\n\n输出 24k 采样率wav格式音频\n\n\n命令行一键体验\n\n```shell\npaddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n```\n\nPython API 一键预测\n\n```python\n>>> from paddlespeech.cli.tts.infer import TTSExecutor\n>>> tts = TTSExecutor()\n>>> tts(text=\"今天天气十分不错。\", output=\"output.wav\")\n```\n- 语音合成的 web demo 已经集成进了 [Huggingface Spaces](https://huggingface.co/spaces). 请参考: [TTS Demo](https://huggingface.co/spaces/KPatrick/PaddleSpeechTTS)\n\n</details>\n\n### 声音分类   \n\n<details><summary>&emsp;适配多场景的开放领域声音分类工具</summary>\n\n基于 AudioSet 数据集 527 个类别的声音分类模型\n\n命令行一键体验\n\n```shell\npaddlespeech cls --input zh.wav\n```\n\npython API 一键预测\n\n```python\n>>> from paddlespeech.cli.cls.infer import CLSExecutor\n>>> cls = CLSExecutor()\n>>> result = cls(audio_file=\"zh.wav\")\n>>> print(result)\nSpeech 0.9027186632156372\n```\n\n</details>\n\n### 声纹提取\n\n<details><summary>&emsp;工业级声纹提取工具</summary>\n\n命令行一键体验\n\n```shell\npaddlespeech vector --task spk --input zh.wav\n```\n\nPython API 一键预测\n\n```python\n>>> from paddlespeech.cli.vector import VectorExecutor\n>>> vec = VectorExecutor()\n>>> result = vec(audio_file=\"zh.wav\")\n>>> print(result) # 187维向量\n[ -0.19083306   9.474295   -14.122263    -2.0916545    0.04848729\n   4.9295826    1.4780062    0.3733844   10.695862     3.2697146\n  -4.48199     -0.6617882   -9.170393   -11.1568775   -1.2358263 ...]\n```\n\n</details>\n\n### 标点恢复 \n\n<details><summary>&emsp;一键恢复文本标点，可与ASR模型配合使用</summary>\n\n命令行一键体验\n\n```shell\npaddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n```\n\nPython API 一键预测\n\n```python\n>>> from paddlespeech.cli.text.infer import TextExecutor\n>>> text_punc = TextExecutor()\n>>> result = text_punc(text=\"今天的天气真不错啊你下午有空吗我想约你一起去吃饭\")\n今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n```\n\n</details>\n\n### 语音翻译\n\n<details><summary>&emsp;端到端英译中语音翻译工具</summary>\n\n使用预编译的 kaldi 相关工具，只支持在 Ubuntu 系统中体验\n\n命令行一键体验\n\n```shell\npaddlespeech st --input en.wav\n```\n\npython API 一键预测\n\n```python\n>>> from paddlespeech.cli.st.infer import STExecutor\n>>> st = STExecutor()\n>>> result = st(audio_file=\"en.wav\")\n['我 在 这栋 建筑 的 古老 门上 敲门 。']\n```\n\n</details>\n\n\n<a name=\"快速使用服务\"></a>\n## 快速使用服务\n安装完成后，开发者可以通过命令行一键启动语音识别，语音合成，音频分类等多种服务。\n\n你可以在 AI Studio 中快速体验：[SpeechServer 一键部署](https://aistudio.baidu.com/aistudio/projectdetail/4354592?sUid=2470186&shared=1&ts=1660878208266)\n\n**启动服务**     \n```shell\npaddlespeech_server start --config_file ./demos/speech_server/conf/application.yaml\n```\n\n**访问语音识别服务**     \n```shell\npaddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n```\n\n**访问语音合成服务**     \n```shell\npaddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n```\n\n**访问音频分类服务**     \n```shell\npaddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input input.wav\n```\n\n更多服务相关的命令行使用信息，请参考 [demos](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/speech_server)\n\n<a name=\"快速使用流式服务\"></a>\n## 快速使用流式服务\n\n开发者可以尝试 [流式 ASR](./demos/streaming_asr_server/README.md) 和 [流式 TTS](./demos/streaming_tts_server/README.md) 服务.\n\n**启动流式 ASR 服务**\n\n```\npaddlespeech_server start --config_file ./demos/streaming_asr_server/conf/application.yaml\n```\n\n**访问流式 ASR 服务**     \n\n```\npaddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n```\n\n**启动流式 TTS 服务**\n\n```\npaddlespeech_server start --config_file ./demos/streaming_tts_server/conf/tts_online_application.yaml\n```\n\n**访问流式 TTS 服务**     \n\n```\npaddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n```\n\n更多信息参看： [流式 ASR](./demos/streaming_asr_server/README.md) 和 [流式 TTS](./demos/streaming_tts_server/README.md) \n\n<a name=\"模型列表\"></a>\n## 模型列表\nPaddleSpeech 支持很多主流的模型，并提供了预训练模型，详情请见[模型列表](./docs/source/released_model.md)。\n\n<a name=\"语音识别模型\"></a>\n\nPaddleSpeech 的 **语音转文本** 包含语音识别声学模型、语音识别语言模型和语音翻译, 详情如下：\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th>语音转文本模块类型</th>\n      <th>数据集</th>\n      <th>模型类型</th>\n      <th>脚本</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td rowspan=\"4\">语音识别</td>\n      <td rowspan=\"2\" >Aishell</td>\n      <td >DeepSpeech2 RNN + Conv based Models</td>\n      <td>\n      <a href = \"./examples/aishell/asr0\">deepspeech2-aishell</a>\n      </td>\n    </tr>\n    <tr>\n      <td>Transformer based Attention Models </td>\n      <td>\n      <a href = \"./examples/aishell/asr1\">u2.transformer.conformer-aishell</a>\n      </td>\n    </tr>\n      <tr>\n      <td> Librispeech</td>\n      <td>Transformer based Attention Models </td>\n      <td>\n      <a href = \"./examples/librispeech/asr0\">deepspeech2-librispeech</a> / <a href = \"./examples/librispeech/asr1\">transformer.conformer.u2-librispeech</a>  / <a href = \"./examples/librispeech/asr2\">transformer.conformer.u2-kaldi-librispeech</a>\n      </td>\n      </td>\n    </tr>\n    <tr>\n      <td>TIMIT</td>\n      <td>Unified Streaming & Non-streaming Two-pass</td>\n      <td>\n    <a href = \"./examples/timit/asr1\"> u2-timit</a>\n      </td>\n    </tr>\n  <tr>\n  <td>对齐</td>\n  <td>THCHS30</td>\n  <td>MFA</td>\n  <td>\n  <a href = \".examples/thchs30/align0\">mfa-thchs30</a>\n  </td>\n  </tr>\n   <tr>\n      <td rowspan=\"1\">语言模型</td>\n      <td colspan = \"2\">Ngram 语言模型</td>\n      <td>\n      <a href = \"./examples/other/ngram_lm\">kenlm</a>\n      </td>\n    </tr>\n    <tr>\n      <td rowspan=\"2\">语音翻译（英译中）</td> \n      <td rowspan=\"2\">TED En-Zh</td>\n      <td>Transformer + ASR MTL</td>\n      <td>\n      <a href = \"./examples/ted_en_zh/st0\">transformer-ted</a>\n      </td>\n  </tr>\n  <tr>\n      <td>FAT + Transformer + ASR MTL</td>\n      <td>\n      <a href = \"./examples/ted_en_zh/st1\">fat-st-ted</a>\n      </td>\n  </tr>\n  </tbody>\n</table>\n\n<a name=\"语音合成模型\"></a>\n\nPaddleSpeech 的 **语音合成** 主要包含三个模块：文本前端、声学模型和声码器。声学模型和声码器模型如下：\n\n<table>\n  <thead>\n    <tr>\n      <th> 语音合成模块类型 </th>\n      <th> 模型类型 </th>\n      <th> 数据集  </th>\n      <th> 脚本  </th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n    <td> 文本前端</td>\n    <td colspan=\"2\"> &emsp; </td>\n    <td>\n    <a href = \"./examples/other/tn\">tn</a> / <a href = \"./examples/other/g2p\">g2p</a>\n    </td>\n   </tr>\n   <tr>\n      <td rowspan=\"6\">声学模型</td>\n      <td>Tacotron2</td>\n      <td>LJSpeech / CSMSC</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts0\">tacotron2-ljspeech</a> / <a href = \"./examples/csmsc/tts0\">tacotron2-csmsc</a>\n      </td>\n   </tr>\n   <tr>\n      <td>Transformer TTS</td>\n      <td>LJSpeech</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts1\">transformer-ljspeech</a>\n      </td>\n   </tr>\n   <tr>\n      <td>SpeedySpeech</td>\n      <td>CSMSC</td>\n      <td >\n      <a href = \"./examples/csmsc/tts2\">speedyspeech-csmsc</a>\n      </td>\n   </tr>\n   <tr>\n      <td>FastSpeech2</td>\n      <td>LJSpeech / VCTK / CSMSC / AISHELL-3 / ZH_EN / finetune</td>\n      <td>\n      <a href = \"./examples/ljspeech/tts3\">fastspeech2-ljspeech</a> / <a href = \"./examples/vctk/tts3\">fastspeech2-vctk</a> / <a href = \"./examples/csmsc/tts3\">fastspeech2-csmsc</a> / <a href = \"./examples/aishell3/tts3\">fastspeech2-aishell3</a> / <a href = \"./examples/zh_en_tts/tts3\">fastspeech2-zh_en</a> / <a href = \"./examples/other/tts_finetune/tts3\">fastspeech2-finetune</a>\n      </td>\n   </tr>\n   <tr>\n      <td><a href = \"https://arxiv.org/abs/2211.03545\">ERNIE-SAT</a></td>\n      <td>VCTK / AISHELL-3 / ZH_EN</td>\n      <td>\n      <a href = \"./examples/vctk/ernie_sat\">ERNIE-SAT-vctk</a> / <a href = \"./examples/aishell3/ernie_sat\">ERNIE-SAT-aishell3</a> / <a href = \"./examples/aishell3_vctk/ernie_sat\">ERNIE-SAT-zh_en</a>\n      </td>\n   </tr>\n   <tr>\n      <td>DiffSinger</td>\n      <td>Opencpop</td>\n      <td>\n      <a href = \"./examples/opencpop/svs1\">DiffSinger-opencpop</a>\n      </td>\n   </tr>\n   <tr>\n      <td rowspan=\"6\">声码器</td>\n      <td >WaveFlow</td>\n      <td >LJSpeech</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc0\">waveflow-ljspeech</a>\n      </td>\n    </tr>\n    <tr>\n      <td >Parallel WaveGAN</td>\n      <td >LJSpeech / VCTK / CSMSC / AISHELL-3 / Opencpop</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc1\">PWGAN-ljspeech</a> / <a href = \"./examples/vctk/voc1\">PWGAN-vctk</a> / <a href = \"./examples/csmsc/voc1\">PWGAN-csmsc</a> /  <a href = \"./examples/aishell3/voc1\">PWGAN-aishell3</a> / <a href = \"./examples/opencpop/voc1\">PWGAN-opencpop</a>\n      </td>\n    </tr>\n    <tr>\n      <td >Multi Band MelGAN</td>\n      <td >CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc3\">Multi Band MelGAN-csmsc</a> \n      </td>\n    </tr>\n    <tr>\n      <td >Style MelGAN</td>\n      <td >CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc4\">Style MelGAN-csmsc</a> \n      </td>\n    </tr>\n    <tr>\n      <td >HiFiGAN</td>\n      <td >LJSpeech / VCTK / CSMSC / AISHELL-3 / Opencpop</td>\n      <td>\n      <a href = \"./examples/ljspeech/voc5\">HiFiGAN-ljspeech</a> / <a href = \"./examples/vctk/voc5\">HiFiGAN-vctk</a> / <a href = \"./examples/csmsc/voc5\">HiFiGAN-csmsc</a> / <a href = \"./examples/aishell3/voc5\">HiFiGAN-aishell3</a> / <a href = \"./examples/opencpop/voc5\">HiFiGAN-opencpop</a>\n      </td>\n    </tr>\n    <tr>\n      <td >WaveRNN</td>\n      <td >CSMSC</td>\n      <td>\n      <a href = \"./examples/csmsc/voc6\">WaveRNN-csmsc</a>\n      </td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">声音克隆</td>\n      <td>GE2E</td>\n      <td >Librispeech, etc.</td>\n      <td>\n      <a href = \"./examples/other/ge2e\">GE2E</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (GE2E + Tacotron2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc0\">VC0</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (GE2E + FastSpeech2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc1\">VC1</a>\n      </td>\n    </tr>\n    <tr>\n      <td>SV2TTS (ECAPA-TDNN + FastSpeech2)</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vc2\">VC2</a>\n      </td>\n    </tr>\n    <tr>\n      <td>GE2E + VITS</td>\n      <td>AISHELL-3</td>\n      <td>\n      <a href = \"./examples/aishell3/vits-vc\">VITS-VC</a>\n      </td>\n    </tr>\n     <tr>\n      <td rowspan=\"3\">端到端</td>\n      <td>VITS</td>\n      <td>CSMSC / AISHELL-3</td>\n      <td>\n      <a href = \"./examples/csmsc/vits\">VITS-csmsc</a> / <a href = \"./examples/aishell3/vits\">VITS-aishell3</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n\n<a name=\"声音分类模型\"></a>\n**声音分类**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 任务 </th>\n      <th> 数据集 </th>\n      <th> 模型类型 </th>\n      <th> 脚本</th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>声音分类</td>\n      <td>ESC-50</td>\n      <td>PANN</td>\n      <td>\n      <a href = \"./examples/esc50/cls0\">pann-esc50</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n\n<a name=\"语音唤醒模型\"></a>\n\n**语音唤醒**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 任务 </th>\n      <th> 数据集 </th>\n      <th> 模型类型 </th>\n      <th> 脚本 </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>语音唤醒</td>\n      <td>hey-snips</td>\n      <td>MDTC</td>\n      <td>\n      <a href = \"./examples/hey_snips/kws0\">mdtc-hey-snips</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"声纹识别模型\"></a>\n\n**声纹识别**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 任务 </th>\n      <th> 数据集 </th>\n      <th> 模型类型 </th>\n      <th> 脚本 </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>声纹识别</td>\n      <td>VoxCeleb1/2</td>\n      <td>ECAPA-TDNN</td>\n      <td>\n      <a href = \"./examples/voxceleb/sv0\">ecapa-tdnn-voxceleb12</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"说话人日志模型\"></a>\n\n**说话人日志**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 任务 </th>\n      <th> 数据集 </th>\n      <th> 模型类型 </th>\n      <th> 脚本 </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>说话人日志</td>\n      <td>AMI</td>\n      <td>ECAPA-TDNN + AHC / SC</td>\n      <td>\n      <a href = \"./examples/ami/sd0\">ecapa-tdnn-ami</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"标点恢复模型\"></a>\n\n**标点恢复**\n\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 任务 </th>\n      <th> 数据集 </th>\n      <th> 模型类型 </th>\n      <th> 脚本 </th>\n    </tr>\n  </thead>\n  <tbody>\n  <tr>\n      <td>标点恢复</td>\n      <td>IWLST2012_zh</td>\n      <td>Ernie Linear</td>\n      <td>\n      <a href = \"./examples/iwslt2012/punc0\">iwslt2012-punc0</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n<a name=\"教程文档\"></a>\n## 教程文档\n\n对于 PaddleSpeech 的所关注的任务，以下指南有助于帮助开发者快速入门，了解语音相关核心思想。\n\n- [下载安装](./docs/source/install_cn.md)\n- [快速开始](#快速开始)\n- Notebook基础教程\n  - [声音分类](./docs/tutorial/cls/cls_tutorial.ipynb)\n  - [语音识别](./docs/tutorial/asr/tutorial_transformer.ipynb)\n  - [语音翻译](./docs/tutorial/st/st_tutorial.ipynb)\n  - [声音合成](./docs/tutorial/tts/tts_tutorial.ipynb)\n  - [示例Demo](./demos/README.md)\n- 进阶文档  \n  - [语音识别自定义训练](./docs/source/asr/quick_start.md)\n    - [简介](./docs/source/asr/models_introduction.md)\n    - [数据准备](./docs/source/asr/data_preparation.md)\n    - [Ngram 语言模型](./docs/source/asr/ngram_lm.md)\n  - [语音合成自定义训练](./docs/source/tts/quick_start.md)\n    - [简介](./docs/source/tts/models_introduction.md)\n    - [进阶用法](./docs/source/tts/advanced_usage.md)\n    - [中文文本前端](./docs/source/tts/zh_text_frontend.md)\n    - [测试语音样本](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html)\n  - 声纹识别\n    - [声纹识别](./demos/speaker_verification/README_cn.md)\n    - [音频检索](./demos/audio_searching/README_cn.md)\n  - [声音分类](./demos/audio_tagging/README_cn.md)\n  - [语音翻译](./demos/speech_translation/README_cn.md)\n  - [服务化部署](./demos/speech_server/README_cn.md)\n- [模型列表](#模型列表)\n  - [语音识别](#语音识别模型)\n  - [语音合成](#语音合成模型)\n  - [声音分类](#声音分类模型)\n  - [声纹识别](#声纹识别模型)\n  - [说话人日志](#说话人日志模型)\n  - [标点恢复](#标点恢复模型)\n- [技术交流群](#技术交流群)\n- [欢迎贡献](#欢迎贡献)\n- [License](#License)\n\n\n语音合成模块最初被称为 [Parakeet](https://github.com/PaddlePaddle/Parakeet)，现在与此仓库合并。如果您对该任务的学术研究感兴趣，请参阅 [TTS 研究概述](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/docs/source/tts#overview)。此外，[模型介绍](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/tts/models_introduction.md) 是了解语音合成流程的一个很好的指南。\n\n\n## ⭐ 应用案例\n- **[PaddleBoBo](https://github.com/JiehangXie/PaddleBoBo): 使用 PaddleSpeech 的语音合成模块生成虚拟人的声音。**\n  \n<div align=\"center\"><a href=\"https://www.bilibili.com/video/BV1cL411V71o?share_source=copy_web\"><img src=\"https://ai-studio-static-online.cdn.bcebos.com/06fd746ab32042f398fb6f33f873e6869e846fe63c214596ae37860fe8103720\" / width=\"500px\"></a></div>\n\n- [PaddleSpeech 示例视频](https://paddlespeech.readthedocs.io/en/latest/demo_video.html)\n\n\n- **[VTuberTalk](https://github.com/jerryuhoo/VTuberTalk): 使用 PaddleSpeech 的语音合成和语音识别从视频中克隆人声。**\n\n<div align=\"center\">\n<img src=\"https://raw.githubusercontent.com/jerryuhoo/VTuberTalk/main/gui/gui.png\"  width = \"500px\"  />\n</div>\n\n\n## 引用\n\n要引用 PaddleSpeech 进行研究，请使用以下格式进行引用。\n```text\n@InProceedings{pmlr-v162-bai22d,\n  title = {{A}$^3${T}: Alignment-Aware Acoustic and Text Pretraining for Speech Synthesis and Editing},\n  author = {Bai, He and Zheng, Renjie and Chen, Junkun and Ma, Mingbo and Li, Xintong and Huang, Liang},\n  booktitle = {Proceedings of the 39th International Conference on Machine Learning},\n  pages = {1399--1411},\n  year = {2022},\n  volume = {162},\n  series = {Proceedings of Machine Learning Research},\n  month = {17--23 Jul},\n  publisher = {PMLR},\n  pdf = {https://proceedings.mlr.press/v162/bai22d/bai22d.pdf},\n  url = {https://proceedings.mlr.press/v162/bai22d.html},\n}\n\n@inproceedings{zhang2022paddlespeech,\n    title = {PaddleSpeech: An Easy-to-Use All-in-One Speech Toolkit},\n    author = {Hui Zhang, Tian Yuan, Junkun Chen, Xintong Li, Renjie Zheng, Yuxin Huang, Xiaojie Chen, Enlei Gong, Zeyu Chen, Xiaoguang Hu, dianhai yu, Yanjun Ma, Liang Huang},\n    booktitle = {Proceedings of the 2022 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies: Demonstrations},\n    year = {2022},\n    publisher = {Association for Computational Linguistics},\n}\n\n@inproceedings{zheng2021fused,\n  title={Fused acoustic and text encoding for multimodal bilingual pretraining and speech translation},\n  author={Zheng, Renjie and Chen, Junkun and Ma, Mingbo and Huang, Liang},\n  booktitle={International Conference on Machine Learning},\n  pages={12736--12746},\n  year={2021},\n  organization={PMLR}\n}\n```\n\n<a name=\"欢迎贡献\"></a>\n## 参与 PaddleSpeech 的开发\n\n热烈欢迎您在 [Discussions](https://github.com/PaddlePaddle/PaddleSpeech/discussions) 中提交问题，并在 [Issues](https://github.com/PaddlePaddle/PaddleSpeech/issues) 中指出发现的 bug。此外，我们非常希望您参与到 PaddleSpeech 的开发中！\n\n### 贡献者\n<p align=\"center\">\n<a href=\"https://github.com/zh794390558\"><img src=\"https://avatars.githubusercontent.com/u/3038472?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Jackwaterveg\"><img src=\"https://avatars.githubusercontent.com/u/87408988?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/yt605155624\"><img src=\"https://avatars.githubusercontent.com/u/24568452?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Honei\"><img src=\"https://avatars.githubusercontent.com/u/11361692?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/KPatr1ck\"><img src=\"https://avatars.githubusercontent.com/u/22954146?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kuke\"><img src=\"https://avatars.githubusercontent.com/u/3064195?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lym0302\"><img src=\"https://avatars.githubusercontent.com/u/34430015?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/SmileGoat\"><img src=\"https://avatars.githubusercontent.com/u/56786796?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/xinghai-sun\"><img src=\"https://avatars.githubusercontent.com/u/7038341?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/pkuyym\"><img src=\"https://avatars.githubusercontent.com/u/5782283?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/LittleChenCc\"><img src=\"https://avatars.githubusercontent.com/u/10339970?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/qingen\"><img src=\"https://avatars.githubusercontent.com/u/3139179?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/D-DanielYang\"><img src=\"https://avatars.githubusercontent.com/u/23690325?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Mingxue-Xu\"><img src=\"https://avatars.githubusercontent.com/u/92848346?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/745165806\"><img src=\"https://avatars.githubusercontent.com/u/20623194?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/jerryuhoo\"><img src=\"https://avatars.githubusercontent.com/u/24245709?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/WilliamZhang06\"><img src=\"https://avatars.githubusercontent.com/u/97937340?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chrisxu2016\"><img src=\"https://avatars.githubusercontent.com/u/18379485?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/iftaken\"><img src=\"https://avatars.githubusercontent.com/u/30135920?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lfchener\"><img src=\"https://avatars.githubusercontent.com/u/6771821?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/BarryKCL\"><img src=\"https://avatars.githubusercontent.com/u/48039828?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/mmglove\"><img src=\"https://avatars.githubusercontent.com/u/38800877?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/gongel\"><img src=\"https://avatars.githubusercontent.com/u/24390500?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/luotao1\"><img src=\"https://avatars.githubusercontent.com/u/6836917?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/wanghaoshuang\"><img src=\"https://avatars.githubusercontent.com/u/7534971?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kslz\"><img src=\"https://avatars.githubusercontent.com/u/54951765?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/JiehangXie\"><img src=\"https://avatars.githubusercontent.com/u/51190264?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/david-95\"><img src=\"https://avatars.githubusercontent.com/u/15189190?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/THUzyt21\"><img src=\"https://avatars.githubusercontent.com/u/91456992?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/buchongyu2\"><img src=\"https://avatars.githubusercontent.com/u/29157444?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/iclementine\"><img src=\"https://avatars.githubusercontent.com/u/16222986?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/phecda-xu\"><img src=\"https://avatars.githubusercontent.com/u/46859427?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/freeliuzc\"><img src=\"https://avatars.githubusercontent.com/u/23568094?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ZeyuChen\"><img src=\"https://avatars.githubusercontent.com/u/1371212?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ccrrong\"><img src=\"https://avatars.githubusercontent.com/u/101700995?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AK391\"><img src=\"https://avatars.githubusercontent.com/u/81195143?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/qingqing01\"><img src=\"https://avatars.githubusercontent.com/u/7845005?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/0x45f\"><img src=\"https://avatars.githubusercontent.com/u/23097963?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/vpegasus\"><img src=\"https://avatars.githubusercontent.com/u/22723154?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ericxk\"><img src=\"https://avatars.githubusercontent.com/u/4719594?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Betterman-qs\"><img src=\"https://avatars.githubusercontent.com/u/61459181?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/sneaxiy\"><img src=\"https://avatars.githubusercontent.com/u/32832641?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Doubledongli\"><img src=\"https://avatars.githubusercontent.com/u/20540661?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/apps/dependabot\"><img src=\"https://avatars.githubusercontent.com/in/29110?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/kvinwang\"><img src=\"https://avatars.githubusercontent.com/u/6442159?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chenkui164\"><img src=\"https://avatars.githubusercontent.com/u/34813030?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/PaddleZhang\"><img src=\"https://avatars.githubusercontent.com/u/97284124?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/billishyahao\"><img src=\"https://avatars.githubusercontent.com/u/96406262?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/BrightXiaoHan\"><img src=\"https://avatars.githubusercontent.com/u/25839309?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/jiqiren11\"><img src=\"https://avatars.githubusercontent.com/u/82639260?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/ryanrussell\"><img src=\"https://avatars.githubusercontent.com/u/523300?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/GT-ZhangAcer\"><img src=\"https://avatars.githubusercontent.com/u/46156734?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/tensor-tang\"><img src=\"https://avatars.githubusercontent.com/u/21351065?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/hysunflower\"><img src=\"https://avatars.githubusercontent.com/u/52739577?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/oyjxer\"><img src=\"https://avatars.githubusercontent.com/u/16233945?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/JamesLim-sy\"><img src=\"https://avatars.githubusercontent.com/u/61349199?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/limpidezza\"><img src=\"https://avatars.githubusercontent.com/u/71760778?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/windstamp\"><img src=\"https://avatars.githubusercontent.com/u/34057289?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AshishKarel\"><img src=\"https://avatars.githubusercontent.com/u/58069375?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/chesterkuo\"><img src=\"https://avatars.githubusercontent.com/u/6285069?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/YDX-2147483647\"><img src=\"https://avatars.githubusercontent.com/u/73375426?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/AdamBear\"><img src=\"https://avatars.githubusercontent.com/u/2288870?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/wwhu\"><img src=\"https://avatars.githubusercontent.com/u/6081200?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/lispc\"><img src=\"https://avatars.githubusercontent.com/u/2833376?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/harisankarh\"><img src=\"https://avatars.githubusercontent.com/u/1307053?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/pengzhendong\"><img src=\"https://avatars.githubusercontent.com/u/10704539?s=60&v=4\" width=75 height=75></a>\n<a href=\"https://github.com/Jackiexiao\"><img src=\"https://avatars.githubusercontent.com/u/18050469?s=60&v=4\" width=75 height=75></a>\n</p>\n\n## 致谢\n- 非常感谢 [HighCWu](https://github.com/HighCWu) 新增 [VITS-aishell3](./examples/aishell3/vits) 和 [VITS-VC](./examples/aishell3/vits-vc) 代码示例。\n- 非常感谢 [david-95](https://github.com/david-95) 修复 TTS 句尾多标点符号出错的问题，贡献补充多条程序和数据。为 TTS 中文文本前端新增 [SSML](https://github.com/PaddlePaddle/PaddleSpeech/discussions/2538) 功能。\n- 非常感谢 [BarryKCL](https://github.com/BarryKCL) 基于 [G2PW](https://github.com/GitYCC/g2pW) 对 TTS 中文文本前端的优化。\n- 非常感谢 [yeyupiaoling](https://github.com/yeyupiaoling)/[PPASR](https://github.com/yeyupiaoling/PPASR)/[PaddlePaddle-DeepSpeech](https://github.com/yeyupiaoling/PaddlePaddle-DeepSpeech)/[VoiceprintRecognition-PaddlePaddle](https://github.com/yeyupiaoling/VoiceprintRecognition-PaddlePaddle)/[AudioClassification-PaddlePaddle](https://github.com/yeyupiaoling/AudioClassification-PaddlePaddle) 多年来的关注和建议，以及在诸多问题上的帮助。\n- 非常感谢 [mymagicpower](https://github.com/mymagicpower) 采用PaddleSpeech 对 ASR 的[短语音](https://github.com/mymagicpower/AIAS/tree/main/3_audio_sdks/asr_sdk)及[长语音](https://github.com/mymagicpower/AIAS/tree/main/3_audio_sdks/asr_long_audio_sdk)进行 Java 实现。\n- 非常感谢 [JiehangXie](https://github.com/JiehangXie)/[PaddleBoBo](https://github.com/JiehangXie/PaddleBoBo) 采用 PaddleSpeech 语音合成功能实现 Virtual Uploader(VUP)/Virtual YouTuber(VTuber) 虚拟主播。\n- 非常感谢 [745165806](https://github.com/745165806)/[PaddleSpeechTask](https://github.com/745165806/PaddleSpeechTask) 贡献标点重建相关模型。\n- 非常感谢 [kslz](https://github.com/kslz) 补充中文文档。\n- 非常感谢 [awmmmm](https://github.com/awmmmm) 提供 fastspeech2 aishell3 conformer 预训练模型。\n- 非常感谢 [phecda-xu](https://github.com/phecda-xu)/[PaddleDubbing](https://github.com/phecda-xu/PaddleDubbing) 基于 PaddleSpeech 的 TTS 模型搭建带 GUI 操作界面的配音工具。\n- 非常感谢 [jerryuhoo](https://github.com/jerryuhoo)/[VTuberTalk](https://github.com/jerryuhoo/VTuberTalk) 基于 PaddleSpeech 的 TTS GUI 界面和基于 ASR 制作数据集的相关代码。\n- 非常感谢 [vpegasus](https://github.com/vpegasus)/[xuesebot](https://github.com/vpegasus/xuesebot) 基于 PaddleSpeech 的 ASR 与 TTS 设计的可听、说对话机器人。\n- 非常感谢 [chenkui164](https://github.com/chenkui164)/[FastASR](https://github.com/chenkui164/FastASR) 对 PaddleSpeech 的 ASR 进行 C++ 推理实现。\n- 非常感谢 [heyudage](https://github.com/heyudage)/[VoiceTyping](https://github.com/heyudage/VoiceTyping) 基于 PaddleSpeech 的 ASR 流式服务实现的实时语音输入法工具。\n- 非常感谢 [EscaticZheng](https://github.com/EscaticZheng)/[ps3.9wheel-install](https://github.com/EscaticZheng/ps3.9wheel-install) 对PaddleSpeech在Windows下的安装提供了无需Visua Studio，基于python3.9的预编译依赖安装包。\n- 非常感谢 [chinobing](https://github.com/chinobing)/[FastAPI-PaddleSpeech-Audio-To-Text](https://github.com/chinobing/FastAPI-PaddleSpeech-Audio-To-Text) 利用 FastAPI 实现 PaddleSpeech 语音转文字，文件上传、分割、转换进度显示、后台更新任务并以 csv 格式输出。\n- 非常感谢 [MistEO](https://github.com/MistEO)/[Pallas-Bot](https://github.com/MistEO/Pallas-Bot) 基于 PaddleSpeech TTS 的 QQ Bot 项目。\n\n此外，PaddleSpeech 依赖于许多开源存储库。有关更多信息，请参阅 [references](./docs/source/reference.md)。\n\n## License\n\nPaddleSpeech 在 [Apache-2.0 许可](./LICENSE) 下提供。\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/PaddlePaddle/PaddleSpeech.svg)](https://starchart.cc/PaddlePaddle/PaddleSpeech)\n"
  },
  {
    "path": "audio/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16 FATAL_ERROR)\n\n# Use compiler ID \"AppleClang\" instead of \"Clang\" for XCode.\n# Not setting this sometimes makes XCode C compiler gets detected as \"Clang\",\n# even when the C++ one is detected as \"AppleClang\".\ncmake_policy(SET CMP0010 NEW)\ncmake_policy(SET CMP0025 NEW)\n\n# Suppress warning flags in default MSVC configuration.  It's not\n# mandatory that we do this (and we don't if cmake is old), but it's\n# nice when it's possible, and it's possible on our Windows configs.\nif(NOT CMAKE_VERSION VERSION_LESS 3.15.0)\n  cmake_policy(SET CMP0092 NEW)\nendif()\n\nproject(paddleaudio)\n\n# check and set CMAKE_CXX_STANDARD\nstring(FIND \"${CMAKE_CXX_FLAGS}\" \"-std=c++\" env_cxx_standard)\nif(env_cxx_standard GREATER -1)\n  message(\n      WARNING \"C++ standard version definition detected in environment variable.\"\n      \"paddleaudio requires -std=c++14. Please remove -std=c++ settings in your environment.\")\nendif()\n\n\nset(CMAKE_CXX_STANDARD 14)\nset(CMAKE_C_STANDARD 11)\n\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\nset(CMAKE_VERBOSE_MAKEFILE ON)\n\n# Options\noption(BUILD_SOX \"Build libsox statically\" ON)\noption(BUILD_MAD \"Enable libmad\" ON)\noption(BUILD_KALDI \"Build kaldi statically\" ON)\noption(BUILD_PADDLEAUDIO_PYTHON_EXTENSION \"Build Python extension\" ON)\n\n\n# cmake\nset(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake;${PROJECT_SOURCE_DIR}/cmake/external\")\n\n# fc_patch dir\nset(FETCHCONTENT_QUIET off)\nget_filename_component(fc_patch \"fc_patch\" REALPATH BASE_DIR \"${CMAKE_SOURCE_DIR}\")\nset(FETCHCONTENT_BASE_DIR ${fc_patch})\nset(THIRD_PARTY_PATH ${fc_patch})\n\nset(PYBIND11_PYTHON_VERSION ${PY_VERSION})\ninclude(cmake/pybind.cmake)\ninclude_directories(${PYTHON_INCLUDE_DIR})\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR}/paddleaudio/third_party/)\n\n# packages\nfind_package(Python3 COMPONENTS Interpreter Development)\n\n# set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -pthread -O0 -Wall -g\")\nadd_subdirectory(paddleaudio)\n\n# Summary\ninclude(cmake/summary.cmake)\nonnx_print_configuration_summary()\n"
  },
  {
    "path": "audio/README.md",
    "content": "# PaddleAudio\n\n安装方式： pip install paddleaudio\n\n目前支持的平台：Linux, Mac, Windows\n\n## Environment\n\n## Build wheel\ncmd: python setup.py bdist_wheel\n\nLinux test build whl environment:\n* os - Ubuntu 16.04.7 LTS\n* gcc/g++ - 8.2.0\n* cmake - 3.18.0 (need install)\n\nMAC：test build whl environment：\n* os \n* gcc/g++ 12.2.0\n* cpu Intel Xeon E5 x86_64\n\nWindows：\nnot support paddleaudio C++ extension lib (sox io, kaldi native fbank)\n"
  },
  {
    "path": "audio/cmake/FindGFortranLibs.cmake",
    "content": "#.rst:\n# FindGFortranLibs\n# --------\n#  https://github.com/Argonne-National-Laboratory/PIPS/blob/master/cmake/Modules/FindGFortranLibs.cmake\n#  https://enccs.github.io/cmake-workshop/cxx-fortran/\n#\n# Find gcc Fortran compiler & library paths\n#\n# The module defines the following variables:\n#\n# ::\n#\n#\n#   GFORTRANLIBS_FOUND - true if system has gfortran\n#   LIBGFORTRAN_LIBRARIES - path to libgfortran\n#   LIBQUADMATH_LIBRARIES - path to libquadmath\n#   GFORTRAN_LIBARIES_DIR - directory containing libgfortran, libquadmath\n#   GFORTRAN_INCLUDE_DIR - directory containing gfortran/gcc headers\n#   LIBGOMP_LIBRARIES - path to libgomp\n#   LIBGOMP_INCLUDE_DIR - directory containing omp.h header\n#   GFORTRAN_VERSION_STRING - version of gfortran found\n#\nset(CMAKE_REQUIRED_QUIET ${LIBIOMP_FIND_QUIETLY})\n\nif(NOT CMAKE_REQUIRED_QUIET)\n  message(STATUS \"Looking for gfortran related libraries...\")\nendif()\n\nenable_language(Fortran)\nif(CMAKE_Fortran_COMPILER_ID MATCHES \"GNU\")\n\n  # Basically, call \"gfortran -v\" to dump compiler info to the string\n  # GFORTRAN_VERBOSE_STR, which will be used to get necessary paths\n  message(STATUS \"Extracting library and header information by calling 'gfortran -v'...\")\n  execute_process(COMMAND \"${CMAKE_Fortran_COMPILER}\" \"-v\" ERROR_VARIABLE\n    GFORTRAN_VERBOSE_STR RESULT_VARIABLE FLAG)\n\n  # For debugging\n  message(STATUS \"'gfortran -v' returned:\")\n  message(STATUS \"${GFORTRAN_VERBOSE_STR}\")\n\n  # Detect gfortran version\n  string(REGEX MATCH \"gcc version [^\\t\\n ]+\" GFORTRAN_VER_STR \"${GFORTRAN_VERBOSE_STR}\")\n  string(REGEX REPLACE \"gcc version ([^\\t\\n ]+)\" \"\\\\1\" GFORTRAN_VERSION_STRING \"${GFORTRAN_VER_STR}\")\n  message(STATUS \"Detected gfortran version ${GFORTRAN_VERSION_STRING}\")\n  unset(GFORTRAN_VER_STR)\n\n  set(MATCH_REGEX \"[^\\t\\n ]+[\\t\\n ]+\")\n  set(REPLACE_REGEX \"([^\\t\\n ]+)\")\n\n  # Find architecture for compiler\n  string(REGEX MATCH \"Target: [^\\t\\n ]+\"\n    GFORTRAN_ARCH_STR \"${GFORTRAN_VERBOSE_STR}\")\n  message(STATUS \"Architecture string: ${GFORTRAN_ARCH_STR}\")\n  string(REGEX REPLACE \"Target: ([^\\t\\n ]+)\" \"\\\\1\"\n    GFORTRAN_ARCH \"${GFORTRAN_ARCH_STR}\")\n  message(STATUS \"Detected gfortran architecture: ${GFORTRAN_ARCH}\")\n  unset(GFORTRAN_ARCH_STR)\n\n  # Find install prefix, if it exists; if not, use default\n  string(REGEX MATCH  \"--prefix=[^\\t\\n ]+[\\t\\n ]+\"\n    GFORTRAN_PREFIX_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_PREFIX_STR)\n    message(STATUS \"Detected default gfortran prefix\")\n    set(GFORTRAN_PREFIX_DIR \"/usr/local\") # default prefix for gcc install\n  else()\n    string(REGEX REPLACE \"--prefix=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_PREFIX_DIR \"${GFORTRAN_PREFIX_STR}\")\n  endif()\n  message(STATUS \"Detected gfortran prefix: ${GFORTRAN_PREFIX_DIR}\")\n  unset(GFORTRAN_PREFIX_STR)\n\n  # Find install exec-prefix, if it exists; if not, use default\n  string(REGEX MATCH \"--exec-prefix=[^\\t\\n ]+[\\t\\n ]+\" \"\\\\1\"\n    GFORTRAN_EXEC_PREFIX_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_EXEC_PREFIX_STR)\n    message(STATUS \"Detected default gfortran exec-prefix\")\n    set(GFORTRAN_EXEC_PREFIX_DIR \"${GFORTRAN_PREFIX_DIR}\")\n  else()\n    string(REGEX REPLACE \"--exec-prefix=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_EXEC_PREFIX_DIR \"${GFORTRAN_EXEC_PREFIX_STR}\")\n  endif()\n  message(STATUS \"Detected gfortran exec-prefix: ${GFORTRAN_EXEC_PREFIX_DIR}\")\n  UNSET(GFORTRAN_EXEC_PREFIX_STR)\n\n  # Find library directory and include directory, if library directory specified\n  string(REGEX MATCH \"--libdir=[^\\t\\n ]+\"\n    GFORTRAN_LIB_DIR_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_LIB_DIR_STR)\n    message(STATUS \"Found --libdir flag -- not found\")\n    message(STATUS \"Using default gfortran library & include directory paths\")\n    string(STRIP ${GFORTRAN_PREFIX_DIR} TMPLIBDIR)\n    set(GFORTRAN_LIBRARIES_DIR \"${TMPLIBDIR}/lib64\")\n    set(GFORTRAN_INCLUDE_DIR \"${TMPLIBDIR}/include\")\n  else()\n    message(STATUS \"Found --libdir flag -- yes\")\n    string(REGEX REPLACE \"--libdir=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_LIBRARIES_DIR \"${GFORTRAN_LIB_DIR_STR}\")\n    string(CONCAT GFORTRAN_INCLUDE_DIR \"${GFORTRAN_LIBRARIES_DIR}\" \"/gcc/\" \"${GFORTRAN_ARCH}\" \"/\" \"${GFORTRAN_VERSION_STRING}\" \"/include\")\n  endif()\n  message(STATUS \"gfortran libraries path: ${GFORTRAN_LIBRARIES_DIR}\")\n  message(STATUS \"gfortran include path dir: ${GFORTRAN_INCLUDE_DIR}\")\n  unset(GFORTRAN_LIB_DIR_STR)\n\n  # There are lots of other build options for gcc & gfortran. For now, the\n  # options implemented above should cover a lot of common use cases.\n\n  # Clean up be deleting the output string from \"gfortran -v\"\n  unset(GFORTRAN_VERBOSE_STR)\n\n  # Find paths for libgfortran, libquadmath, libgomp\n  # libgomp needed for OpenMP support without Clang\n  find_library(LIBGFORTRAN_LIBRARIES NAMES gfortran libgfortran\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n  find_library(LIBQUADMATH_LIBRARIES NAMES quadmath libquadmath\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n  find_library(LIBGOMP_LIBRARIES NAMES gomp libgomp\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n\n  # Find OpenMP headers\n  find_path(LIBGOMP_INCLUDE_DIR NAMES omp.h HINTS ${GFORTRAN_INCLUDE_DIR})\n\nelse()\n  message(STATUS \"CMAKE_Fortran_COMPILER_ID does not match 'GNU'!\")\nendif()\n\ninclude(FindPackageHandleStandardArgs)\n\n# Required: libgfortran, libquadmath, path for gfortran libraries\n# Optional: libgomp, path for OpenMP headers, path for gcc/gfortran headers\nfind_package_handle_standard_args(GFortranLibs\n  REQUIRED_VARS LIBGFORTRAN_LIBRARIES LIBQUADMATH_LIBRARIES GFORTRAN_LIBRARIES_DIR\n  VERSION_VAR GFORTRAN_VERSION_STRING)\n\nif(GFORTRANLIBS_FOUND)\n  message(STATUS \"Looking for gfortran libraries -- found\")\n  message(STATUS \"gfortran version: ${GFORTRAN_VERSION_STRING}\")\nelse()\n  message(STATUS \"Looking for gfortran libraries -- not found\")\nendif()\n\nmark_as_advanced(LIBGFORTRAN_LIBRARIES LIBQUADMATH_LIBRARIES\n  LIBGOMP_LIBRARIES LIBGOMP_INCLUDE_DIR\n  GFORTRAN_LIBRARIES_DIR GFORTRAN_INCLUDE_DIR)\n# FindGFortranLIBS.cmake ends here\n\n\nmessage(STATUS LIBGFORTRAN_LIBRARIES= ${LIBGFORTRAN_LIBRARIES})\nmessage(STATUS LIBQUADMATH_LIBRARIES= ${LIBQUADMATH_LIBRARIES})\nmessage(STATUS LIBGOMP_LIBRARIES= ${LIBGOMP_LIBRARIES})\nmessage(STATUS LIBGOMP_INCLUDE_DIR= ${LIBGOMP_INCLUDE_DIR})\nmessage(STATUS GFORTRAN_LIBRARIES_DIR= ${GFORTRAN_LIBRARIES_DIR})\nmessage(STATUS GFORTRAN_INCLUDE_DIR= ${GFORTRAN_INCLUDE_DIR})\n"
  },
  {
    "path": "audio/cmake/external/openblas.cmake",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\ninclude(ExternalProject)\n\nset(CBLAS_PREFIX_DIR ${THIRD_PARTY_PATH}/openblas)\nset(CBLAS_INSTALL_DIR ${THIRD_PARTY_PATH}/install/openblas)\nset(CBLAS_REPOSITORY https://github.com/xianyi/OpenBLAS.git)\nset(CBLAS_TAG v0.3.10)\n\nif(NOT WIN32)\n  set(CBLAS_LIBRARIES\n      \"${CBLAS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}openblas${CMAKE_STATIC_LIBRARY_SUFFIX}\"\n      CACHE FILEPATH \"openblas library.\" FORCE)\n  set(CBLAS_INC_DIR\n      \"${CBLAS_INSTALL_DIR}/include\"\n      CACHE PATH \"openblas include directory.\" FORCE)\n  set(OPENBLAS_CC\n      \"${CMAKE_C_COMPILER} -Wno-unused-but-set-variable -Wno-unused-variable\")\n\n  if(APPLE)\n    set(OPENBLAS_CC \"${CMAKE_C_COMPILER} -isysroot ${CMAKE_OSX_SYSROOT}\")\n  endif()\n  set(OPTIONAL_ARGS \"\")\n  set(COMMON_ARGS \"\")\n\n  if(APPLE)\n    if(CMAKE_SYSTEM_PROCESSOR MATCHES \"^x86(_64)?$\")\n      set(OPTIONAL_ARGS DYNAMIC_ARCH=1 NUM_THREADS=64)\n    endif()\n    set(COMMON_ARGS CC=${OPENBLAS_CC} NO_SHARED=1)\n  endif()\n\n  ExternalProject_Add(\n    OPENBLAS\n    URL \"https://paddleaudio.bj.bcebos.com/build/OpenBLAS-0.3.10.zip\"\n    GIT_SHALLOW YES\n    DOWNLOAD_DIR ${CBLAS_PREFIX_DIR}\n    SOURCE_DIR ${CBLAS_PREFIX_DIR}\n    INSTALL_DIR ${CBLAS_INSTALL_DIR}\n    BUILD_IN_SOURCE 1\n    BUILD_COMMAND make -j${NPROC} ${COMMON_ARGS} ${OPTIONAL_ARGS}\n    INSTALL_COMMAND make install PREFIX=<INSTALL_DIR>\n    UPDATE_COMMAND \"\"\n    CONFIGURE_COMMAND \"\"\n    BUILD_BYPRODUCTS ${CBLAS_LIBRARIES})\n\n    ExternalProject_Get_Property(OPENBLAS INSTALL_DIR)\n    set(OpenBLAS_INSTALL_PREFIX ${INSTALL_DIR})\n    add_library(openblas STATIC IMPORTED)\n    add_dependencies(openblas OPENBLAS)\n    set_target_properties(openblas PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES Fortran)\n    set_target_properties(openblas PROPERTIES IMPORTED_LOCATION ${OpenBLAS_INSTALL_PREFIX}/lib/libopenblas.a)\n\n    link_directories(${OpenBLAS_INSTALL_PREFIX}/lib)\n    include_directories(${OpenBLAS_INSTALL_PREFIX}/include)\n\n    set(OPENBLAS_LIBRARIES\n        ${OpenBLAS_INSTALL_PREFIX}/lib/libopenblas.a\n    )\n\n    add_library(libopenblas INTERFACE)\n    add_dependencies(libopenblas openblas)\n    target_include_directories(libopenblas INTERFACE ${OpenBLAS_INSTALL_PREFIX}/include/openblas)\n    target_link_libraries(libopenblas INTERFACE ${OPENBLAS_LIBRARIES})\nelse()\n  set(CBLAS_LIBRARIES\n      \"${CBLAS_INSTALL_DIR}/lib/openblas${CMAKE_STATIC_LIBRARY_SUFFIX}\"\n      CACHE FILEPATH \"openblas library.\" FORCE)\n  set(CBLAS_INC_DIR\n      \"${CBLAS_INSTALL_DIR}/include/openblas\"\n      CACHE PATH \"openblas include directory.\" FORCE)\n  ExternalProject_Add(\n    extern_openblas\n    ${EXTERNAL_PROJECT_LOG_ARGS}\n    GIT_REPOSITORY ${CBLAS_REPOSITORY}\n    GIT_TAG ${CBLAS_TAG}\n    PREFIX ${CBLAS_PREFIX_DIR}\n    INSTALL_DIR ${CBLAS_INSTALL_DIR}\n    BUILD_IN_SOURCE 0\n    UPDATE_COMMAND \"\"\n    CMAKE_ARGS -DCMAKE_C_COMPILER=clang-cl\n               -DCMAKE_CXX_COMPILER=clang-cl\n               -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}\n               -DCMAKE_INSTALL_PREFIX=${CBLAS_INSTALL_DIR}\n               -DCMAKE_BUILD_TYPE=Release #${THIRD_PARTY_BUILD_TYPE}\n               -DCMAKE_MT=mt\n               -DUSE_THREAD=OFF\n               -DBUILD_WITHOUT_LAPACK=NO\n               -DCMAKE_Fortran_COMPILER=flang\n               -DNOFORTRAN=0\n               -DDYNAMIC_ARCH=ON\n               #${EXTERNAL_OPTIONAL_ARGS}\n    CMAKE_CACHE_ARGS\n      -DCMAKE_INSTALL_PREFIX:PATH=${CBLAS_INSTALL_DIR}\n      -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON\n      -DCMAKE_BUILD_TYPE:STRING=Release #${THIRD_PARTY_BUILD_TYPE}\n    # ninja need to know where openblas.lib comes from\n    BUILD_BYPRODUCTS ${CBLAS_LIBRARIES})\n  set(OPENBLAS_SHARED_LIB\n      ${CBLAS_INSTALL_DIR}/bin/openblas${CMAKE_SHARED_LIBRARY_SUFFIX})\n\n  add_library(openblas INTERFACE)\n  add_dependencies(openblas extern_openblas)\n  include_directories(${CBLAS_INC_DIR})\n  link_libraries(${CBLAS_LIBRARIES})\nendif()\n\n"
  },
  {
    "path": "audio/cmake/pybind.cmake",
    "content": "#the pybind11 is from:https://github.com/pybind/pybind11\n# Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.\n\nSET(PYBIND_ZIP \"v2.10.0.zip\")\nSET(LOCAL_PYBIND_ZIP ${FETCHCONTENT_BASE_DIR}/${PYBIND_ZIP})\nSET(PYBIND_SRC ${FETCHCONTENT_BASE_DIR}/pybind11)\nSET(DOWNLOAD_URL \"https://paddleaudio.bj.bcebos.com/build/v2.10.0.zip\")\nSET(PYBIND_TIMEOUT 600 CACHE STRING \"Timeout in seconds when downloading pybind.\")\n\nIF(NOT EXISTS ${LOCAL_PYBIND_ZIP})\n    FILE(DOWNLOAD ${DOWNLOAD_URL}\n      ${LOCAL_PYBIND_ZIP}\n      TIMEOUT ${PYBIND_TIMEOUT}\n      STATUS ERR\n      SHOW_PROGRESS\n    )\n\n    IF(ERR EQUAL 0)\n        MESSAGE(STATUS \"download pybind success\")\n    ELSE()\n        MESSAGE(FATAL_ERROR \"download pybind fail\")\n    ENDIF()\nENDIF()\n\nIF(NOT EXISTS ${PYBIND_SRC})\n    EXECUTE_PROCESS(\n      COMMAND ${CMAKE_COMMAND} -E tar xfz ${LOCAL_PYBIND_ZIP}\n       WORKING_DIRECTORY ${FETCHCONTENT_BASE_DIR}\n       RESULT_VARIABLE tar_result\n    )\n\n    file(RENAME ${FETCHCONTENT_BASE_DIR}/pybind11-2.10.0 ${PYBIND_SRC})\n\n  IF (tar_result MATCHES 0)\n      MESSAGE(STATUS \"unzip pybind success\")\n  ELSE()\n      MESSAGE(FATAL_ERROR \"unzip pybind fail\")\n  ENDIF()\n\nENDIF()\n\ninclude_directories(${PYBIND_SRC}/include)\n"
  },
  {
    "path": "audio/cmake/summary.cmake",
    "content": "# SPDX-License-Identifier: Apache-2.0\n\n# Prints accumulated ONNX configuration summary\nfunction (onnx_print_configuration_summary)\n  message(STATUS \"\")\n  message(STATUS \"******** Summary ********\")\n  message(STATUS \"  CMake version             : ${CMAKE_VERSION}\")\n  message(STATUS \"  CMake command             : ${CMAKE_COMMAND}\")\n  message(STATUS \"  System                    : ${CMAKE_SYSTEM_NAME}\")\n  message(STATUS \"  C++ compiler              : ${CMAKE_CXX_COMPILER}\")\n  message(STATUS \"  C++ compiler version      : ${CMAKE_CXX_COMPILER_VERSION}\")\n  message(STATUS \"  CXX flags                 : ${CMAKE_CXX_FLAGS}\")\n  message(STATUS \"  Build type                : ${CMAKE_BUILD_TYPE}\")\n  get_directory_property(tmp DIRECTORY ${PROJECT_SOURCE_DIR} COMPILE_DEFINITIONS)\n  message(STATUS \"  Compile definitions       : ${tmp}\")\n  message(STATUS \"  CMAKE_PREFIX_PATH         : ${CMAKE_PREFIX_PATH}\")\n  message(STATUS \"  CMAKE_INSTALL_PREFIX      : ${CMAKE_INSTALL_PREFIX}\")\n  message(STATUS \"  CMAKE_MODULE_PATH         : ${CMAKE_MODULE_PATH}\")\n  message(STATUS \"\")\n  message(STATUS \"  ONNX version              : ${ONNX_VERSION}\")\n  message(STATUS \"  ONNX NAMESPACE            : ${ONNX_NAMESPACE}\")\n  message(STATUS \"  ONNX_USE_LITE_PROTO       : ${ONNX_USE_LITE_PROTO}\")\n  message(STATUS \"  USE_PROTOBUF_SHARED_LIBS  : ${ONNX_USE_PROTOBUF_SHARED_LIBS}\")\n  message(STATUS \"  Protobuf_USE_STATIC_LIBS  : ${Protobuf_USE_STATIC_LIBS}\")\n  message(STATUS \"  ONNX_DISABLE_EXCEPTIONS   : ${ONNX_DISABLE_EXCEPTIONS}\")\n  message(STATUS \"  ONNX_WERROR               : ${ONNX_WERROR}\")\n  message(STATUS \"  ONNX_BUILD_TESTS          : ${ONNX_BUILD_TESTS}\")\n  message(STATUS \"  ONNX_BUILD_BENCHMARKS     : ${ONNX_BUILD_BENCHMARKS}\")\n  message(STATUS \"  ONNXIFI_DUMMY_BACKEND     : ${ONNXIFI_DUMMY_BACKEND}\")\n  message(STATUS \"  ONNXIFI_ENABLE_EXT        : ${ONNXIFI_ENABLE_EXT}\")\n  message(STATUS \"\")\n  message(STATUS \"  Protobuf compiler         : ${PROTOBUF_PROTOC_EXECUTABLE}\")\n  message(STATUS \"  Protobuf includes         : ${PROTOBUF_INCLUDE_DIRS}\")\n  message(STATUS \"  Protobuf libraries        : ${PROTOBUF_LIBRARIES}\")\n  message(STATUS \"  BUILD_ONNX_PYTHON         : ${BUILD_ONNX_PYTHON}\")\n  message(STATUS \"    Python version        : ${Python_VERSION}\")\n  message(STATUS \"    Python executable     : ${Python_EXECUTABLE}\")\n  message(STATUS \"    Python includes       : ${Python_INCLUDE_DIR}\")\n  message(STATUS \"    Python libraries      : ${Python_LIBRARY}\")\n  message(STATUS \"  PYBIND11                  : ${pybind11_FOUND}\")\n  message(STATUS \"    Pybind11 version        : ${pybind11_VERSION}\")\n  message(STATUS \"    Pybind11 include        : ${pybind11_INCLUDE_DIR}\")\n  message(STATUS \"    Pybind11 includes       : ${pybind11_INCLUDE_DIRS}\")\n  message(STATUS \"    Pybind11 libraries      : ${pybind11_LIBRARIES}\")\nendfunction()"
  },
  {
    "path": "audio/paddleaudio/CMakeLists.txt",
    "content": "\nadd_subdirectory(third_party)\nadd_subdirectory(src)\n"
  },
  {
    "path": "audio/paddleaudio/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import _extension\nfrom . import backends\nfrom . import compliance\nfrom . import datasets\nfrom . import features\nfrom . import functional\nfrom . import metric\nfrom . import sox_effects\nfrom . import utils\n"
  },
  {
    "path": "audio/paddleaudio/_extension.py",
    "content": "import contextlib\nimport ctypes\nimport os\nimport sys\nimport types\nimport warnings\nfrom pathlib import Path\n\nfrom ._internal import module_utils as _mod_utils  # noqa: F401\n\n# Query `hasattr` only once.\n_SET_GLOBAL_FLAGS = hasattr(sys, 'getdlopenflags') and hasattr(sys,\n                                                               'setdlopenflags')\n\n\n@contextlib.contextmanager\ndef dl_open_guard():\n    \"\"\"\n    # https://manpages.debian.org/bullseye/manpages-dev/dlopen.3.en.html\n    Context manager to set the RTLD_GLOBAL dynamic linker flag while we open a\n    shared library to load custom operators.\n    \"\"\"\n    if _SET_GLOBAL_FLAGS:\n        old_flags = sys.getdlopenflags()\n        sys.setdlopenflags(old_flags | ctypes.RTLD_GLOBAL)\n    yield\n    if _SET_GLOBAL_FLAGS:\n        sys.setdlopenflags(old_flags)\n\n\ndef resolve_library_path(path: str) -> str:\n    return os.path.realpath(path)\n\n\nclass _Ops(types.ModuleType):\n    #__file__ = '_ops.py'\n\n    def __init__(self):\n        super(_Ops, self).__init__('paddleaudio.ops')\n        self.loaded_libraries = set()\n\n    def load_library(self, path):\n        \"\"\"\n        Loads a shared library from the given path into the current process.\n        This allows dynamically loading custom operators. For this, \n        you should compile your operator and \n        the static registration code into a shared library object, and then\n        call ``paddleaudio.ops.load_library('path/to/libcustom.so')`` to load the\n        shared object.\n        After the library is loaded, it is added to the\n        ``paddleaudio.ops.loaded_libraries`` attribute, a set that may be inspected\n        for the paths of all libraries loaded using this function.\n        Args:\n            path (str): A path to a shared library to load.\n        \"\"\"\n        path = resolve_library_path(path)\n        with dl_open_guard():\n            # https://docs.python.org/3/library/ctypes.html?highlight=ctypes#loading-shared-libraries\n            # Import the shared library into the process, thus running its\n            # static (global) initialization code in order to register custom\n            # operators with the JIT.\n            ctypes.CDLL(path)\n        self.loaded_libraries.add(path)\n\n\n_LIB_DIR = Path(__file__).parent / \"lib\"\n\n\ndef _get_lib_path(lib: str):\n    suffix = \"pyd\" if os.name == \"nt\" else \"so\"\n    path = _LIB_DIR / f\"{lib}.{suffix}\"\n    return path\n\n\ndef _load_lib(lib: str) -> bool:\n    \"\"\"Load extension module\n    Note:\n        In case `paddleaudio` is deployed with `pex` format, the library file\n        is not in a standard location.\n        In this case, we expect that `libpaddlleaudio` is available somewhere\n        in the search path of dynamic loading mechanism, so that importing\n        `_paddlleaudio` will have library loader find and load `libpaddlleaudio`.\n        This is the reason why the function should not raising an error when the library\n        file is not found.\n    Returns:\n        bool:\n            True if the library file is found AND the library loaded without failure.\n            False if the library file is not found (like in the case where paddlleaudio\n            is deployed with pex format, thus the shared library file is\n            in a non-standard location.).\n            If the library file is found but there is an issue loading the library,\n            (such as missing dependency) then this function raises the exception as-is.\n    Raises:\n        Exception:\n            If the library file is found, but there is an issue loading the library file,\n            (when underlying `ctype.DLL` throws an exception), this function will pass\n            the exception as-is, instead of catching it and returning bool.\n            The expected case is `OSError` thrown by `ctype.DLL` when a dynamic dependency\n            is not found.\n            This behavior was chosen because the expected failure case is not recoverable.\n            If a dependency is missing, then users have to install it.\n    \"\"\"\n    path = _get_lib_path(lib)\n    if not path.exists():\n        warnings.warn(\"lib path is not exists:\" + str(path))\n        return False\n    ops.load_library(path)\n    return True\n\n\n_FFMPEG_INITIALIZED = False\n\n\ndef _init_ffmpeg():\n    global _FFMPEG_INITIALIZED\n    if _FFMPEG_INITIALIZED:\n        return\n\n    if not paddleaudio._paddlleaudio.is_ffmpeg_available():\n        raise RuntimeError(\n            \"paddlleaudio is not compiled with FFmpeg integration. Please set USE_FFMPEG=1 when compiling paddlleaudio.\"\n        )\n\n    try:\n        _load_lib(\"libpaddlleaudio_ffmpeg\")\n    except OSError as err:\n        raise ImportError(\n            \"FFmpeg libraries are not found. Please install FFmpeg.\") from err\n\n    import paddllespeech.audio._paddlleaudio_ffmpeg  # noqa\n\n    paddleaudio._paddlleaudio.ffmpeg_init()\n    if paddleaudio._paddlleaudio.ffmpeg_get_log_level() > 8:\n        paddleaudio._paddlleaudio.ffmpeg_set_log_level(8)\n\n    _FFMPEG_INITIALIZED = True\n\n\ndef _init_extension():\n    if not _mod_utils.is_module_available(\"paddleaudio._paddleaudio\"):\n        warnings.warn(\n            \"paddleaudio C++ extension is not available. sox_io, sox_effect, kaldi raw feature is not supported!!!\")\n        return\n\n    _load_lib(\"libpaddleaudio\")\n    # This import is for initializing the methods registered via PyBind11\n    # This has to happen after the base library is loaded\n    try:\n        from paddleaudio import _paddleaudio  # noqa\n    except Exception:\n        warnings.warn(\n            \"paddleaudio C++ extension is not available. sox_io, sox_effect, kaldi raw feature is not supported!!!\")\n        return\n\n    # Because this part is executed as part of `import torchaudio`, we ignore the\n    # initialization failure.\n    # If the FFmpeg integration is not properly initialized, then detailed error\n    # will be raised when client code attempts to import the dedicated feature.\n    try:\n        _init_ffmpeg()\n    except Exception:\n        pass\n\n\nops = _Ops()\n\n_init_extension()\n"
  },
  {
    "path": "audio/paddleaudio/_internal/__init__.py",
    "content": ""
  },
  {
    "path": "audio/paddleaudio/_internal/module_utils.py",
    "content": "import importlib.util\nimport platform\nimport warnings\nfrom functools import wraps\nfrom typing import Optional\n\n#code is from https://github.com/pytorch/audio/blob/main/torchaudio/_internal/module_utils.py with modification.\n\n\ndef is_module_available(*modules: str) -> bool:\n    r\"\"\"Returns if a top-level module with :attr:`name` exists *without**\n    importing it. This is generally safer than try-catch block around a\n    `import X`. It avoids third party libraries breaking assumptions of some of\n    our tests, e.g., setting multiprocessing start method when imported\n    (see librosa/#747, torchvision/#544).\n    \"\"\"\n    return all(importlib.util.find_spec(m) is not None for m in modules)\n\n\ndef requires_module(*modules: str):\n    \"\"\"Decorate function to give error message if invoked without required optional modules.\n    This decorator is to give better error message to users rather\n    than raising ``NameError:  name 'module' is not defined`` at random places.\n    \"\"\"\n    missing = [m for m in modules if not is_module_available(m)]\n\n    if not missing:\n        # fall through. If all the modules are available, no need to decorate\n        def decorator(func):\n            return func\n\n    else:\n        req = f\"module: {missing[0]}\" if len(\n            missing) == 1 else f\"modules: {missing}\"\n\n        def decorator(func):\n            @wraps(func)\n            def wrapped(*args, **kwargs):\n                raise RuntimeError(\n                    f\"{func.__module__}.{func.__name__} requires {req}\")\n\n            return wrapped\n\n    return decorator\n\n\ndef deprecated(direction: str, version: Optional[str]=None):\n    \"\"\"Decorator to add deprecation message\n    Args:\n        direction (str): Migration steps to be given to users.\n        version (str or int): The version when the object will be removed\n    \"\"\"\n\n    def decorator(func):\n        @wraps(func)\n        def wrapped(*args, **kwargs):\n            message = (\n                f\"{func.__module__}.{func.__name__} has been deprecated \"\n                f'and will be removed from {\"future\" if version is None else version} release. '\n                f\"{direction}\")\n            warnings.warn(message, stacklevel=2)\n            return func(*args, **kwargs)\n\n        return wrapped\n\n    return decorator\n\n\ndef is_kaldi_available():\n    try:\n        from paddleaudio import _paddleaudio  \n        return True\n    except Exception:\n        return False\n\ndef requires_kaldi():\n    if is_kaldi_available():\n\n        def decorator(func):\n            return func\n\n    else:\n\n        def decorator(func):\n            @wraps(func)\n            def wrapped(*args, **kwargs):\n                raise RuntimeError(\n                    f\"{func.__module__}.{func.__name__} requires libpaddleaudio build with kaldi\")\n\n            return wrapped\n\n    return decorator\n\n\ndef _check_soundfile_importable():\n    if not is_module_available(\"soundfile\"):\n        return False\n    try:\n        import soundfile  # noqa: F401\n\n        return True\n    except Exception:\n        warnings.warn(\n            \"Failed to import soundfile. 'soundfile' backend is not available.\")\n        return False\n\n\n_is_soundfile_importable = _check_soundfile_importable()\n\n\ndef is_soundfile_available():\n    return _is_soundfile_importable\n\n\ndef requires_soundfile():\n    if is_soundfile_available():\n\n        def decorator(func):\n            return func\n    else:\n\n        def decorator(func):\n            @wraps(func)\n            def wrapped(*args, **kwargs):\n                raise RuntimeError(\n                    f\"{func.__module__}.{func.__name__} requires soundfile\")\n\n            return wrapped\n\n    return decorator\n\n\ndef is_sox_available():\n    try:\n        from paddleaudio import _paddleaudio  \n        return True\n    except Exception:\n        return False\n\n\ndef requires_sox():\n    if is_sox_available():\n\n        def decorator(func):\n            return func\n    else:\n\n        def decorator(func):\n            @wraps(func)\n            def wrapped(*args, **kwargs):\n                raise RuntimeError(\n                    f\"{func.__module__}.{func.__name__} requires libpaddleaudio build with sox\")\n\n            return wrapped\n\n    return decorator\n"
  },
  {
    "path": "audio/paddleaudio/backends/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import utils\nfrom .soundfile_backend import depth_convert\nfrom .soundfile_backend import normalize\nfrom .soundfile_backend import resample\nfrom .soundfile_backend import soundfile_load\nfrom .soundfile_backend import soundfile_save\nfrom .soundfile_backend import to_mono\nfrom .utils import get_audio_backend\nfrom .utils import list_audio_backends\nfrom .utils import set_audio_backend\n\nutils._init_audio_backend()\n"
  },
  {
    "path": "audio/paddleaudio/backends/common.py",
    "content": "# Token from https://github.com/pytorch/audio/blob/main/torchaudio/backend/common.py with modification.\n\n\nclass AudioInfo:\n    \"\"\"return of info function.\n\n    This class is used by :ref:`\"sox_io\" backend<sox_io_backend>` and\n    :ref:`\"soundfile\" backend with the new interface<soundfile_backend>`.\n\n    :ivar int sample_rate: Sample rate\n    :ivar int num_frames: The number of frames\n    :ivar int num_channels: The number of channels\n    :ivar int bits_per_sample: The number of bits per sample. This is 0 for lossy formats,\n        or when it cannot be accurately inferred.\n    :ivar str encoding: Audio encoding\n        The values encoding can take are one of the following:\n\n            * ``PCM_S``: Signed integer linear PCM\n            * ``PCM_U``: Unsigned integer linear PCM\n            * ``PCM_F``: Floating point linear PCM\n            * ``FLAC``: Flac, Free Lossless Audio Codec\n            * ``ULAW``: Mu-law\n            * ``ALAW``: A-law\n            * ``MP3`` : MP3, MPEG-1 Audio Layer III\n            * ``VORBIS``: OGG Vorbis\n            * ``AMR_WB``: Adaptive Multi-Rate\n            * ``AMR_NB``: Adaptive Multi-Rate Wideband\n            * ``OPUS``: Opus\n            * ``HTK``: Single channel 16-bit PCM\n            * ``UNKNOWN`` : None of above\n    \"\"\"\n\n    def __init__(\n            self,\n            sample_rate: int,\n            num_frames: int,\n            num_channels: int,\n            bits_per_sample: int,\n            encoding: str, ):\n        self.sample_rate = sample_rate\n        self.num_frames = num_frames\n        self.num_channels = num_channels\n        self.bits_per_sample = bits_per_sample\n        self.encoding = encoding\n\n    def __str__(self):\n        return (f\"AudioMetaData(\"\n                f\"sample_rate={self.sample_rate}, \"\n                f\"num_frames={self.num_frames}, \"\n                f\"num_channels={self.num_channels}, \"\n                f\"bits_per_sample={self.bits_per_sample}, \"\n                f\"encoding={self.encoding}\"\n                f\")\")\n"
  },
  {
    "path": "audio/paddleaudio/backends/no_backend.py",
    "content": "from pathlib import Path\nfrom typing import Callable\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nfrom paddle import Tensor\n\n#code is from: https://github.com/pytorch/audio/blob/main/torchaudio/backend/no_backend.py\n\n\ndef load(\n        filepath: Union[str, Path],\n        out: Optional[Tensor]=None,\n        normalization: Union[bool, float, Callable]=True,\n        channels_first: bool=True,\n        num_frames: int=0,\n        offset: int=0,\n        filetype: Optional[str]=None, ) -> Tuple[Tensor, int]:\n    raise RuntimeError(\"No audio I/O backend is available.\")\n\n\ndef save(filepath: str,\n         src: Tensor,\n         sample_rate: int,\n         precision: int=16,\n         channels_first: bool=True) -> None:\n    raise RuntimeError(\"No audio I/O backend is available.\")\n\n\ndef info(filepath: str) -> None:\n    raise RuntimeError(\"No audio I/O backend is available.\")\n"
  },
  {
    "path": "audio/paddleaudio/backends/soundfile_backend.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport warnings\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport resampy\nimport soundfile\nfrom scipy.io import wavfile\n\nfrom ..utils import depth_convert\nfrom ..utils import ParameterError\nfrom .common import AudioInfo\n\n__all__ = [\n    'resample',\n    'to_mono',\n    'normalize',\n    'save',\n    'soundfile_save',\n    'load',\n    'soundfile_load',\n    'info',\n]\nNORMALMIZE_TYPES = ['linear', 'gaussian']\nMERGE_TYPES = ['ch0', 'ch1', 'random', 'average']\nRESAMPLE_MODES = ['kaiser_best', 'kaiser_fast']\nEPS = 1e-8\n\n\ndef resample(y: np.ndarray,\n             src_sr: int,\n             target_sr: int,\n             mode: str='kaiser_fast') -> np.ndarray:\n    \"\"\"Audio resampling.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        src_sr (int): Source sample rate.\n        target_sr (int): Target sample rate.\n        mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        np.ndarray: `y` resampled to `target_sr`\n    \"\"\"\n\n    if mode == 'kaiser_best':\n        warnings.warn(\n            f'Using resampy in kaiser_best to {src_sr}=>{target_sr}. This function is pretty slow, \\\n        we recommend the mode kaiser_fast in large scale audio training')\n\n    if not isinstance(y, np.ndarray):\n        raise ParameterError(\n            'Only support numpy np.ndarray, but received y in {type(y)}')\n\n    if mode not in RESAMPLE_MODES:\n        raise ParameterError(f'resample mode must in {RESAMPLE_MODES}')\n\n    return resampy.resample(y, src_sr, target_sr, filter=mode)\n\n\ndef to_mono(y: np.ndarray, merge_type: str='average') -> np.ndarray:\n    \"\"\"Convert sterior audio to mono.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        merge_type (str, optional): Merge type to generate mono waveform. Defaults to 'average'.\n\n    Returns:\n        np.ndarray: `y` with mono channel.\n    \"\"\"\n\n    if merge_type not in MERGE_TYPES:\n        raise ParameterError(\n            f'Unsupported merge type {merge_type}, available types are {MERGE_TYPES}'\n        )\n    if y.ndim > 2:\n        raise ParameterError(\n            f'Unsupported audio array,  y.ndim > 2, the shape is {y.shape}')\n    if y.ndim == 1:  # nothing to merge\n        return y\n\n    if merge_type == 'ch0':\n        return y[0]\n    if merge_type == 'ch1':\n        return y[1]\n    if merge_type == 'random':\n        return y[np.random.randint(0, 2)]\n\n    # need to do averaging according to dtype\n\n    if y.dtype == 'float32':\n        y_out = (y[0] + y[1]) * 0.5\n    elif y.dtype == 'int16':\n        y_out = y.astype('int32')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n\n    elif y.dtype == 'int8':\n        y_out = y.astype('int16')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n    else:\n        raise ParameterError(f'Unsupported dtype: {y.dtype}')\n    return y_out\n\n\ndef soundfile_load_(file: os.PathLike,\n                    offset: Optional[float]=None,\n                    dtype: str='int16',\n                    duration: Optional[int]=None) -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio using soundfile library. This function load audio file using libsndfile.\n\n    Args:\n        file (os.PathLike): File of waveform.\n        offset (Optional[float], optional): Offset to the start of waveform. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'int16'.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n    with soundfile.SoundFile(file) as sf_desc:\n        sr_native = sf_desc.samplerate\n        if offset:\n            sf_desc.seek(int(offset * sr_native))\n        if duration is not None:\n            frame_duration = int(duration * sr_native)\n        else:\n            frame_duration = -1\n        y = sf_desc.read(frames=frame_duration, dtype=dtype, always_2d=False).T\n\n    return y, sf_desc.samplerate\n\n\ndef normalize(y: np.ndarray, norm_type: str='linear',\n              mul_factor: float=1.0) -> np.ndarray:\n    \"\"\"Normalize an input audio with additional multiplier.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n\n    Returns:\n        np.ndarray: `y` after normalization.\n    \"\"\"\n\n    if norm_type == 'linear':\n        amax = np.max(np.abs(y))\n        factor = 1.0 / (amax + EPS)\n        y = y * factor * mul_factor\n    elif norm_type == 'gaussian':\n        amean = np.mean(y)\n        astd = np.std(y)\n        astd = max(astd, EPS)\n        y = mul_factor * (y - amean) / astd\n    else:\n        raise NotImplementedError(f'norm_type should be in {NORMALMIZE_TYPES}')\n\n    return y\n\n\ndef soundfile_save(y: np.ndarray, sr: int, file: os.PathLike) -> None:\n    \"\"\"Save audio file to disk. This function saves audio to disk using scipy.io.wavfile, with additional step to convert input waveform to int16.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        sr (int): Sample rate.\n        file (os.PathLike): Path of audio file to save.\n    \"\"\"\n    if not file.endswith('.wav'):\n        raise ParameterError(\n            f'only .wav file supported, but dst file name is: {file}')\n\n    if sr <= 0:\n        raise ParameterError(\n            f'Sample rate should be larger than 0, received sr = {sr}')\n\n    if y.dtype not in ['int16', 'int8']:\n        warnings.warn(\n            f'input data type is {y.dtype}, will convert data to int16 format before saving'\n        )\n        y_out = depth_convert(y, 'int16')\n    else:\n        y_out = y\n\n    wavfile.write(file, sr, y_out)\n\n\ndef soundfile_load(\n        file: os.PathLike,\n        sr: Optional[int]=None,\n        mono: bool=True,\n        merge_type: str='average',  # ch0,ch1,random,average\n        normal: bool=True,\n        norm_type: str='linear',\n        norm_mul_factor: float=1.0,\n        offset: float=0.0,\n        duration: Optional[int]=None,\n        dtype: str='float32',\n        resample_mode: str='kaiser_fast') -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio file from disk. This function loads audio from disk using using audio backend.\n\n    Args:\n        file (os.PathLike): Path of audio file to load.\n        sr (Optional[int], optional): Sample rate of loaded waveform. Defaults to None.\n        mono (bool, optional): Return waveform with mono channel. Defaults to True.\n        merge_type (str, optional): Merge type of multi-channels waveform. Defaults to 'average'.\n        normal (bool, optional): Waveform normalization. Defaults to True.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        norm_mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n        offset (float, optional): Offset to the start of waveform. Defaults to 0.0.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'float32'.\n        resample_mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n\n    y, r = soundfile_load_(file, offset=offset, dtype=dtype, duration=duration)\n\n    if not ((y.ndim == 1 and len(y) > 0) or (y.ndim == 2 and len(y[0]) > 0)):\n        raise ParameterError(f'audio file {file} looks empty')\n\n    if mono:\n        y = to_mono(y, merge_type)\n\n    if sr is not None and sr != r:\n        y = resample(y, r, sr, mode=resample_mode)\n        r = sr\n\n    if normal:\n        y = normalize(y, norm_type, norm_mul_factor)\n    elif dtype in ['int8', 'int16']:\n        # still need to do normalization, before depth conversion\n        y = normalize(y, 'linear', 1.0)\n\n    y = depth_convert(y, dtype)\n    return y, r\n\n\n#The code below is taken from: https://github.com/pytorch/audio/blob/main/torchaudio/backend/soundfile_backend.py, with some modifications.\n\n\ndef _get_subtype_for_wav(dtype: paddle.dtype,\n                         encoding: str,\n                         bits_per_sample: int):\n    if not encoding:\n        if not bits_per_sample:\n            subtype = {\n                paddle.uint8: \"PCM_U8\",\n                paddle.int16: \"PCM_16\",\n                paddle.int32: \"PCM_32\",\n                paddle.float32: \"FLOAT\",\n                paddle.float64: \"DOUBLE\",\n            }.get(dtype)\n            if not subtype:\n                raise ValueError(f\"Unsupported dtype for wav: {dtype}\")\n            return subtype\n        if bits_per_sample == 8:\n            return \"PCM_U8\"\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_S\":\n        if not bits_per_sample:\n            return \"PCM_32\"\n        if bits_per_sample == 8:\n            raise ValueError(\"wav does not support 8-bit signed PCM encoding.\")\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_U\":\n        if bits_per_sample in (None, 8):\n            return \"PCM_U8\"\n        raise ValueError(\"wav only supports 8-bit unsigned PCM encoding.\")\n    if encoding == \"PCM_F\":\n        if bits_per_sample in (None, 32):\n            return \"FLOAT\"\n        if bits_per_sample == 64:\n            return \"DOUBLE\"\n        raise ValueError(\"wav only supports 32/64-bit float PCM encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"wav only supports 8-bit mu-law encoding.\")\n    if encoding == \"ALAW\":\n        if bits_per_sample in (None, 8):\n            return \"ALAW\"\n        raise ValueError(\"wav only supports 8-bit a-law encoding.\")\n    raise ValueError(f\"wav does not support {encoding}.\")\n\n\ndef _get_subtype_for_sphere(encoding: str, bits_per_sample: int):\n    if encoding in (None, \"PCM_S\"):\n        return f\"PCM_{bits_per_sample}\" if bits_per_sample else \"PCM_32\"\n    if encoding in (\"PCM_U\", \"PCM_F\"):\n        raise ValueError(f\"sph does not support {encoding} encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"sph only supports 8-bit for mu-law encoding.\")\n    if encoding == \"ALAW\":\n        return \"ALAW\"\n    raise ValueError(f\"sph does not support {encoding}.\")\n\n\ndef _get_subtype(dtype: paddle.dtype,\n                 format: str,\n                 encoding: str,\n                 bits_per_sample: int):\n    if format == \"wav\":\n        return _get_subtype_for_wav(dtype, encoding, bits_per_sample)\n    if format == \"flac\":\n        if encoding:\n            raise ValueError(\"flac does not support encoding.\")\n        if not bits_per_sample:\n            return \"PCM_16\"\n        if bits_per_sample > 24:\n            raise ValueError(\"flac does not support bits_per_sample > 24.\")\n        return \"PCM_S8\" if bits_per_sample == 8 else f\"PCM_{bits_per_sample}\"\n    if format in (\"ogg\", \"vorbis\"):\n        if encoding or bits_per_sample:\n            raise ValueError(\n                \"ogg/vorbis does not support encoding/bits_per_sample.\")\n        return \"VORBIS\"\n    if format == \"sph\":\n        return _get_subtype_for_sphere(encoding, bits_per_sample)\n    if format in (\"nis\", \"nist\"):\n        return \"PCM_16\"\n    raise ValueError(f\"Unsupported format: {format}\")\n\n\ndef save(\n        filepath: str,\n        src: paddle.Tensor,\n        sample_rate: int,\n        channels_first: bool=True,\n        compression: Optional[float]=None,\n        format: Optional[str]=None,\n        encoding: Optional[str]=None,\n        bits_per_sample: Optional[int]=None, ):\n    \"\"\"Save audio data to file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (str or pathlib.Path): Path to audio file.\n        src (paddle.Tensor): Audio data to save. must be 2D tensor.\n        sample_rate (int): sampling rate\n        channels_first (bool, optional): If ``True``, the given tensor is interpreted as `[channel, time]`,\n            otherwise `[time, channel]`.\n        compression (float of None, optional): Not used.\n            It is here only for interface compatibility reason with \"sox_io\" backend.\n        format (str or None, optional): Override the audio format.\n            When ``filepath`` argument is path-like object, audio format is\n            inferred from file extension. If the file extension is missing or\n            different, you can specify the correct format with this argument.\n\n            When ``filepath`` argument is file-like object,\n            this argument is required.\n\n            Valid values are ``\"wav\"``, ``\"ogg\"``, ``\"vorbis\"``,\n            ``\"flac\"`` and ``\"sph\"``.\n        encoding (str or None, optional): Changes the encoding for supported formats.\n            This argument is effective only for supported formats, such as\n            ``\"wav\"``, ``\"\"flac\"`` and ``\"sph\"``. Valid values are:\n\n                - ``\"PCM_S\"`` (signed integer Linear PCM)\n                - ``\"PCM_U\"`` (unsigned integer Linear PCM)\n                - ``\"PCM_F\"`` (floating point PCM)\n                - ``\"ULAW\"`` (mu-law)\n                - ``\"ALAW\"`` (a-law)\n\n        bits_per_sample (int or None, optional): Changes the bit depth for the\n            supported formats.\n            When ``format`` is one of ``\"wav\"``, ``\"flac\"`` or ``\"sph\"``,\n            you can change the bit depth.\n            Valid values are ``8``, ``16``, ``24``, ``32`` and ``64``.\n\n    Supported formats/encodings/bit depth/compression are:\n\n    ``\"wav\"``\n        - 32-bit floating-point PCM\n        - 32-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 8-bit unsigned integer PCM\n        - 8-bit mu-law\n        - 8-bit a-law\n\n        Note:\n            Default encoding/bit depth is determined by the dtype of\n            the input Tensor.\n\n    ``\"flac\"``\n        - 8-bit\n        - 16-bit (default)\n        - 24-bit\n\n    ``\"ogg\"``, ``\"vorbis\"``\n        - Doesn't accept changing configuration.\n\n    ``\"sph\"``\n        - 8-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 32-bit signed integer PCM (default)\n        - 8-bit mu-law\n        - 8-bit a-law\n        - 16-bit a-law\n        - 24-bit a-law\n        - 32-bit a-law\n\n    \"\"\"\n    if src.ndim != 2:\n        raise ValueError(f\"Expected 2D Tensor, got {src.ndim}D.\")\n    if compression is not None:\n        warnings.warn(\n            '`save` function of \"soundfile\" backend does not support \"compression\" parameter. '\n            \"The argument is silently ignored.\")\n    if hasattr(filepath, \"write\"):\n        if format is None:\n            raise RuntimeError(\n                \"`format` is required when saving to file object.\")\n        ext = format.lower()\n    else:\n        ext = str(filepath).split(\".\")[-1].lower()\n\n    if bits_per_sample not in (None, 8, 16, 24, 32, 64):\n        raise ValueError(\"Invalid bits_per_sample.\")\n    if bits_per_sample == 24:\n        warnings.warn(\n            \"Saving audio with 24 bits per sample might warp samples near -1. \"\n            \"Using 16 bits per sample might be able to avoid this.\")\n    subtype = _get_subtype(src.dtype, ext, encoding, bits_per_sample)\n\n    # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format,\n    # so we extend the extensions manually here\n    if ext in [\"nis\", \"nist\", \"sph\"] and format is None:\n        format = \"NIST\"\n\n    if channels_first:\n        src = src.t()\n\n    soundfile.write(\n        file=filepath,\n        data=src,\n        samplerate=sample_rate,\n        subtype=subtype,\n        format=format)\n\n\n_SUBTYPE2DTYPE = {\n    \"PCM_S8\": \"int8\",\n    \"PCM_U8\": \"uint8\",\n    \"PCM_16\": \"int16\",\n    \"PCM_32\": \"int32\",\n    \"FLOAT\": \"float32\",\n    \"DOUBLE\": \"float64\",\n}\n\n\ndef load(\n        filepath: str,\n        frame_offset: int=0,\n        num_frames: int=-1,\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[paddle.Tensor, int]:\n    \"\"\"Load audio data from file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with\n    ``float32`` dtype and the shape of `[channel, time]`.\n    The samples are normalized to fit in the range of ``[-1.0, 1.0]``.\n\n    When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit\n    signed integer and 8-bit unsigned integer (24-bit signed integer is not supported),\n    by providing ``normalize=False``, this function can return integer Tensor, where the samples\n    are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor\n    for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM.\n\n    ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as\n    ``flac`` and ``mp3``.\n    For these formats, this function always returns ``float32`` Tensor with values normalized to\n    ``[-1.0, 1.0]``.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend.\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        frame_offset (int, optional):\n            Number of frames to skip before start reading data.\n        num_frames (int, optional):\n            Maximum number of frames to read. ``-1`` reads all the remaining samples,\n            starting from ``frame_offset``.\n            This function may return the less number of frames if there is not enough\n            frames in the given file.\n        normalize (bool, optional):\n            When ``True``, this function always return ``float32``, and sample values are\n            normalized to ``[-1.0, 1.0]``.\n            If input file is integer WAV, giving ``False`` will change the resulting Tensor type to\n            integer type.\n            This argument has no effect for formats other than integer WAV type.\n        channels_first (bool, optional):\n            When True, the returned Tensor has dimension `[channel, time]`.\n            Otherwise, the returned Tensor's dimension is `[time, channel]`.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        (paddle.Tensor, int): Resulting Tensor and sample rate.\n            If the input file has integer wav format and normalization is off, then it has\n            integer type, else ``float32`` type. If ``channels_first=True``, it has\n            `[channel, time]` else `[time, channel]`.\n    \"\"\"\n    with soundfile.SoundFile(filepath, \"r\") as file_:\n        if file_.format != \"WAV\" or normalize:\n            dtype = \"float32\"\n        elif file_.subtype not in _SUBTYPE2DTYPE:\n            raise ValueError(f\"Unsupported subtype: {file_.subtype}\")\n        else:\n            dtype = _SUBTYPE2DTYPE[file_.subtype]\n\n        frames = file_._prepare_read(frame_offset, None, num_frames)\n        waveform = file_.read(frames, dtype, always_2d=True)\n        sample_rate = file_.samplerate\n\n    waveform = paddle.to_tensor(waveform)\n    if channels_first:\n        waveform = paddle.transpose(waveform, perm=[1, 0])\n    return waveform, sample_rate\n\n\n# Mapping from soundfile subtype to number of bits per sample.\n# This is mostly heuristical and the value is set to 0 when it is irrelevant\n# (lossy formats) or when it can't be inferred.\n# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard:\n# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony,\n# the default seems to be 8 bits but it can be compressed further to 4 bits.\n# The dict is inspired from\n# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94\n_SUBTYPE_TO_BITS_PER_SAMPLE = {\n    \"PCM_S8\": 8,  # Signed 8 bit data\n    \"PCM_16\": 16,  # Signed 16 bit data\n    \"PCM_24\": 24,  # Signed 24 bit data\n    \"PCM_32\": 32,  # Signed 32 bit data\n    \"PCM_U8\": 8,  # Unsigned 8 bit data (WAV and RAW only)\n    \"FLOAT\": 32,  # 32 bit float data\n    \"DOUBLE\": 64,  # 64 bit float data\n    \"ULAW\": 8,  # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"ALAW\": 8,  # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"IMA_ADPCM\": 0,  # IMA ADPCM.\n    \"MS_ADPCM\": 0,  # Microsoft ADPCM.\n    \"GSM610\":\n    0,  # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate)\n    \"VOX_ADPCM\": 0,  # OKI / Dialogix ADPCM\n    \"G721_32\": 0,  # 32kbs G721 ADPCM encoding.\n    \"G723_24\": 0,  # 24kbs G723 ADPCM encoding.\n    \"G723_40\": 0,  # 40kbs G723 ADPCM encoding.\n    \"DWVW_12\": 12,  # 12 bit Delta Width Variable Word encoding.\n    \"DWVW_16\": 16,  # 16 bit Delta Width Variable Word encoding.\n    \"DWVW_24\": 24,  # 24 bit Delta Width Variable Word encoding.\n    \"DWVW_N\": 0,  # N bit Delta Width Variable Word encoding.\n    \"DPCM_8\": 8,  # 8 bit differential PCM (XI only)\n    \"DPCM_16\": 16,  # 16 bit differential PCM (XI only)\n    \"VORBIS\": 0,  # Xiph Vorbis encoding. (lossy)\n    \"ALAC_16\": 16,  # Apple Lossless Audio Codec (16 bit).\n    \"ALAC_20\": 20,  # Apple Lossless Audio Codec (20 bit).\n    \"ALAC_24\": 24,  # Apple Lossless Audio Codec (24 bit).\n    \"ALAC_32\": 32,  # Apple Lossless Audio Codec (32 bit).\n}\n\n\ndef _get_bit_depth(subtype):\n    if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE:\n        warnings.warn(\n            f\"The {subtype} subtype is unknown to PaddleAudio. As a result, the bits_per_sample \"\n            \"attribute will be set to 0. If you are seeing this warning, please \"\n            \"report by opening an issue on github (after checking for existing/closed ones). \"\n            \"You may otherwise ignore this warning.\")\n    return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0)\n\n\n_SUBTYPE_TO_ENCODING = {\n    \"PCM_S8\": \"PCM_S\",\n    \"PCM_16\": \"PCM_S\",\n    \"PCM_24\": \"PCM_S\",\n    \"PCM_32\": \"PCM_S\",\n    \"PCM_U8\": \"PCM_U\",\n    \"FLOAT\": \"PCM_F\",\n    \"DOUBLE\": \"PCM_F\",\n    \"ULAW\": \"ULAW\",\n    \"ALAW\": \"ALAW\",\n    \"VORBIS\": \"VORBIS\",\n}\n\n\ndef _get_encoding(format: str, subtype: str):\n    if format == \"FLAC\":\n        return \"FLAC\"\n    return _SUBTYPE_TO_ENCODING.get(subtype, \"UNKNOWN\")\n\n\ndef info(filepath: str, format: Optional[str]=None) -> AudioInfo:\n    \"\"\"Get signal information of an audio file.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        AudioInfo: meta data of the given audio.\n\n    \"\"\"\n    sinfo = soundfile.info(filepath)\n    return AudioInfo(\n        sinfo.samplerate,\n        sinfo.frames,\n        sinfo.channels,\n        bits_per_sample=_get_bit_depth(sinfo.subtype),\n        encoding=_get_encoding(sinfo.format, sinfo.subtype), )\n"
  },
  {
    "path": "audio/paddleaudio/backends/sox_io_backend.py",
    "content": "import os\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nimport paddleaudio\nfrom paddle import Tensor\nfrom paddleaudio._internal import module_utils as _mod_utils\n\nfrom .common import AudioInfo\n\n#https://github.com/pytorch/audio/blob/main/torchaudio/backend/sox_io_backend.py\n\n\ndef _fail_info(filepath: str, format: Optional[str]) -> AudioInfo:\n    raise RuntimeError(\"Failed to fetch metadata from {}\".format(filepath))\n\n\ndef _fail_info_fileobj(fileobj, format: Optional[str]) -> AudioInfo:\n    raise RuntimeError(\"Failed to fetch metadata from {}\".format(fileobj))\n\n\n# Note: need to comply TorchScript syntax -- need annotation and no f-string\ndef _fail_load(\n        filepath: str,\n        frame_offset: int=0,\n        num_frames: int=-1,\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[Tensor, int]:\n    raise RuntimeError(\"Failed to load audio from {}\".format(filepath))\n\n\ndef _fail_load_fileobj(fileobj, *args, **kwargs):\n    raise RuntimeError(f\"Failed to load audio from {fileobj}\")\n\n\n_fallback_info = _fail_info\n_fallback_info_fileobj = _fail_info_fileobj\n_fallback_load = _fail_load\n_fallback_load_filebj = _fail_load_fileobj\n\n\n@_mod_utils.requires_sox()\ndef load(\n        filepath: str,\n        frame_offset: int=0,\n        num_frames: int=-1,\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[Tensor, int]:\n    if hasattr(filepath, \"read\"):\n        ret = paddleaudio._paddleaudio.load_audio_fileobj(\n            filepath, frame_offset, num_frames, normalize, channels_first,\n            format)\n        if ret is not None:\n            audio_tensor = paddle.to_tensor(ret[0])\n            return (audio_tensor, ret[1])\n        return _fallback_load_fileobj(filepath, frame_offset, num_frames,\n                                      normalize, channels_first, format)\n    filepath = os.fspath(filepath)\n    ret = paddleaudio._paddleaudio.sox_io_load_audio_file(\n        filepath, frame_offset, num_frames, normalize, channels_first, format)\n    if ret is not None:\n        audio_tensor = paddle.to_tensor(ret[0])\n        return (audio_tensor, ret[1])\n    return _fallback_load(filepath, frame_offset, num_frames, normalize,\n                          channels_first, format)\n\n\n@_mod_utils.requires_sox()\ndef save(\n        filepath: str,\n        src: Tensor,\n        sample_rate: int,\n        channels_first: bool=True,\n        compression: Optional[float]=None,\n        format: Optional[str]=None,\n        encoding: Optional[str]=None,\n        bits_per_sample: Optional[int]=None, ):\n    src_arr = src.numpy()\n    if hasattr(filepath, \"write\"):\n        paddleaudio._paddleaudio.save_audio_fileobj(\n            filepath, src_arr, sample_rate, channels_first, compression, format,\n            encoding, bits_per_sample)\n        return\n    filepath = os.fspath(filepath)\n    paddleaudio._paddleaudio.sox_io_save_audio_file(\n        filepath, src_arr, sample_rate, channels_first, compression, format,\n        encoding, bits_per_sample)\n\n\n@_mod_utils.requires_sox()\ndef info(\n        filepath: str,\n        format: Optional[str]=None, ) -> AudioInfo:\n    if hasattr(filepath, \"read\"):\n        sinfo = paddleaudio._paddleaudio.get_info_fileobj(filepath, format)\n        if sinfo is not None:\n            return AudioInfo(*sinfo)\n        return _fallback_info_fileobj(filepath, format)\n    filepath = os.fspath(filepath)\n    sinfo = paddleaudio._paddleaudio.get_info_file(filepath, format)\n    if sinfo is not None:\n        return AudioInfo(*sinfo)\n    return _fallback_info(filepath, format)\n"
  },
  {
    "path": "audio/paddleaudio/backends/utils.py",
    "content": "\"\"\"Defines utilities for switching audio backends\"\"\"\n#code is from: https://github.com/pytorch/audio/blob/main/torchaudio/backend/utils.py\nimport warnings\nfrom typing import List\nfrom typing import Optional\n\nimport paddleaudio\nfrom paddleaudio._internal import module_utils as _mod_utils\n\nfrom . import no_backend\nfrom . import soundfile_backend\nfrom . import sox_io_backend\n\n__all__ = [\n    \"list_audio_backends\",\n    \"get_audio_backend\",\n    \"set_audio_backend\",\n]\n\n\ndef list_audio_backends() -> List[str]:\n    \"\"\"List available backends\n\n    Returns:\n        List[str]: The list of available backends.\n    \"\"\"\n    backends = []\n    if _mod_utils.is_module_available(\"soundfile\"):\n        backends.append(\"soundfile\")\n    if _mod_utils.is_sox_available():\n        backends.append(\"sox_io\")\n    return backends\n\n\ndef set_audio_backend(backend: Optional[str]):\n    \"\"\"Set the backend for I/O operation\n\n    Args:\n        backend (str or None): Name of the backend.\n            One of ``\"sox_io\"`` or ``\"soundfile\"`` based on availability\n            of the system. If ``None`` is provided the  current backend is unassigned.\n    \"\"\"\n    if backend is not None and backend not in list_audio_backends():\n        raise RuntimeError(f'Backend \"{backend}\" is not one of '\n                           f\"available backends: {list_audio_backends()}.\")\n\n    if backend is None:\n        module = no_backend\n    elif backend == \"sox_io\":\n        module = sox_io_backend\n    elif backend == \"soundfile\":\n        module = soundfile_backend\n    else:\n        raise NotImplementedError(f'Unexpected backend \"{backend}\"')\n\n    for func in [\"save\", \"load\", \"info\"]:\n        setattr(paddleaudio, func, getattr(module, func))\n\n\ndef _init_audio_backend():\n    backends = list_audio_backends()\n    if \"soundfile\" in backends:\n        set_audio_backend(\"soundfile\")\n    elif \"sox_io\" in backends:\n        set_audio_backend(\"sox_io\")\n    else:\n        warnings.warn(\"No audio backend is available.\")\n        set_audio_backend(None)\n\n\ndef get_audio_backend() -> Optional[str]:\n    \"\"\"Get the name of the current backend\n\n    Returns:\n        Optional[str]: The name of the current backend or ``None`` if no backend is assigned.\n    \"\"\"\n    if paddleaudio.load == no_backend.load:\n        return None\n    if paddleaudio.load == sox_io_backend.load:\n        return \"sox_io\"\n    if paddleaudio.load == soundfile_backend.load:\n        return \"soundfile\"\n    raise ValueError(\"Unknown backend.\")\n"
  },
  {
    "path": "audio/paddleaudio/compliance/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import kaldi\nfrom . import librosa\n"
  },
  {
    "path": "audio/paddleaudio/compliance/kaldi.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from torchaudio(https://github.com/pytorch/audio)\nimport math\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import Tensor\n\nfrom ..functional import create_dct\nfrom ..functional.window import get_window\n\n__all__ = [\n    'spectrogram',\n    'fbank',\n    'mfcc',\n]\n\n# window types\nHANNING = 'hann'\nHAMMING = 'hamming'\nPOVEY = 'povey'\nRECTANGULAR = 'rect'\nBLACKMAN = 'blackman'\n\n\ndef _get_epsilon(dtype):\n    return paddle.to_tensor(1e-07, dtype=dtype)\n\n\ndef _next_power_of_2(x: int) -> int:\n    return 1 if x == 0 else 2**(x - 1).bit_length()\n\n\ndef _get_strided(waveform: Tensor,\n                 window_size: int,\n                 window_shift: int,\n                 snip_edges: bool) -> Tensor:\n    assert waveform.dim() == 1\n    num_samples = waveform.shape[0]\n\n    if snip_edges:\n        if num_samples < window_size:\n            return paddle.empty((0, 0), dtype=waveform.dtype)\n        else:\n            m = 1 + (num_samples - window_size) // window_shift\n    else:\n        reversed_waveform = paddle.flip(waveform, [0])\n        m = (num_samples + (window_shift // 2)) // window_shift\n        pad = window_size // 2 - window_shift // 2\n        pad_right = reversed_waveform\n        if pad > 0:\n            pad_left = reversed_waveform[-pad:]\n            waveform = paddle.concat((pad_left, waveform, pad_right), axis=0)\n        else:\n            waveform = paddle.concat((waveform[-pad:], pad_right), axis=0)\n\n    return paddle.signal.frame(waveform, window_size, window_shift)[:, :m].T\n\n\ndef _feature_window_function(\n        window_type: str,\n        window_size: int,\n        blackman_coeff: float,\n        dtype: int, ) -> Tensor:\n    if window_type == \"hann\":\n        return get_window('hann', window_size, fftbins=False, dtype=dtype)\n    elif window_type == \"hamming\":\n        return get_window('hamming', window_size, fftbins=False, dtype=dtype)\n    elif window_type == \"povey\":\n        return get_window(\n            'hann', window_size, fftbins=False, dtype=dtype).pow(0.85)\n    elif window_type == \"rect\":\n        return paddle.ones([window_size], dtype=dtype)\n    elif window_type == \"blackman\":\n        a = 2 * math.pi / (window_size - 1)\n        window_function = paddle.arange(window_size, dtype=dtype)\n        return (blackman_coeff - 0.5 * paddle.cos(a * window_function) +\n                (0.5 - blackman_coeff) * paddle.cos(2 * a * window_function)\n                ).astype(dtype)\n    else:\n        raise Exception('Invalid window type ' + window_type)\n\n\ndef _get_log_energy(strided_input: Tensor, epsilon: Tensor,\n                    energy_floor: float) -> Tensor:\n    log_energy = paddle.maximum(strided_input.pow(2).sum(1), epsilon).log()\n    if energy_floor == 0.0:\n        return log_energy\n    return paddle.maximum(\n        log_energy,\n        paddle.to_tensor(math.log(energy_floor), dtype=strided_input.dtype))\n\n\ndef _get_waveform_and_window_properties(\n        waveform: Tensor,\n        channel: int,\n        sr: int,\n        frame_shift: float,\n        frame_length: float,\n        round_to_power_of_two: bool,\n        preemphasis_coefficient: float) -> Tuple[Tensor, int, int, int]:\n    channel = max(channel, 0)\n    assert channel < waveform.shape[0], (\n        'Invalid channel {} for size {}'.format(channel, waveform.shape[0]))\n    waveform = waveform[channel, :]  # size (n)\n    window_shift = int(\n        sr * frame_shift *\n        0.001)  # pass frame_shift and frame_length in milliseconds\n    window_size = int(sr * frame_length * 0.001)\n    padded_window_size = _next_power_of_2(\n        window_size) if round_to_power_of_two else window_size\n\n    assert 2 <= window_size <= len(waveform), (\n        'choose a window size {} that is [2, {}]'.format(window_size,\n                                                         len(waveform)))\n    assert 0 < window_shift, '`window_shift` must be greater than 0'\n    assert padded_window_size % 2 == 0, 'the padded `window_size` must be divisible by two.' \\\n                                        ' use `round_to_power_of_two` or change `frame_length`'\n    assert 0. <= preemphasis_coefficient <= 1.0, '`preemphasis_coefficient` must be between [0,1]'\n    assert sr > 0, '`sr` must be greater than zero'\n    return waveform, window_shift, window_size, padded_window_size\n\n\ndef _get_window(waveform: Tensor,\n                padded_window_size: int,\n                window_size: int,\n                window_shift: int,\n                window_type: str,\n                blackman_coeff: float,\n                snip_edges: bool,\n                raw_energy: bool,\n                energy_floor: float,\n                dither: float,\n                remove_dc_offset: bool,\n                preemphasis_coefficient: float) -> Tuple[Tensor, Tensor]:\n    dtype = waveform.dtype\n    epsilon = _get_epsilon(dtype)\n\n    # (m, window_size)\n    strided_input = _get_strided(waveform, window_size, window_shift,\n                                 snip_edges)\n\n    if dither != 0.0:\n        x = paddle.maximum(epsilon,\n                           paddle.rand(strided_input.shape, dtype=dtype))\n        rand_gauss = paddle.sqrt(-2 * x.log()) * paddle.cos(2 * math.pi * x)\n        strided_input = strided_input + rand_gauss * dither\n\n    if remove_dc_offset:\n        row_means = paddle.mean(strided_input, axis=1).unsqueeze(1)  # (m, 1)\n        strided_input = strided_input - row_means\n\n    if raw_energy:\n        signal_log_energy = _get_log_energy(strided_input, epsilon,\n                                            energy_floor)  # (m)\n\n    if preemphasis_coefficient != 0.0:\n        offset_strided_input = paddle.nn.functional.pad(\n            strided_input.unsqueeze(0), (1, 0),\n            data_format='NCL',\n            mode='replicate').squeeze(0)  # (m, window_size + 1)\n        strided_input = strided_input - preemphasis_coefficient * offset_strided_input[:, :\n                                                                                       -1]\n\n    window_function = _feature_window_function(\n        window_type, window_size, blackman_coeff,\n        dtype).unsqueeze(0)  # (1, window_size)\n    strided_input = strided_input * window_function  # (m, window_size)\n\n    # (m, padded_window_size)\n    if padded_window_size != window_size:\n        padding_right = padded_window_size - window_size\n        strided_input = paddle.nn.functional.pad(\n            strided_input.unsqueeze(0), (0, padding_right),\n            data_format='NCL',\n            mode='constant',\n            value=0).squeeze(0)\n\n    if not raw_energy:\n        signal_log_energy = _get_log_energy(strided_input, epsilon,\n                                            energy_floor)  # size (m)\n\n    return strided_input, signal_log_energy\n\n\ndef _subtract_column_mean(tensor: Tensor, subtract_mean: bool) -> Tensor:\n    if subtract_mean:\n        col_means = paddle.mean(tensor, axis=0).unsqueeze(0)\n        tensor = tensor - col_means\n    return tensor\n\n\ndef spectrogram(waveform: Tensor,\n                blackman_coeff: float=0.42,\n                channel: int=-1,\n                dither: float=0.0,\n                energy_floor: float=1.0,\n                frame_length: float=25.0,\n                frame_shift: float=10.0,\n                preemphasis_coefficient: float=0.97,\n                raw_energy: bool=True,\n                remove_dc_offset: bool=True,\n                round_to_power_of_two: bool=True,\n                sr: int=16000,\n                snip_edges: bool=True,\n                subtract_mean: bool=False,\n                window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return a spectrogram from a waveform. The output is identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`.\n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that can't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to \"povey\".\n\n    Returns:\n        Tensor: A spectrogram tensor with shape `(m, padded_window_size // 2 + 1)` where m is the number of frames\n            depends on frame_length and frame_shift.\n    \"\"\"\n    dtype = waveform.dtype\n    epsilon = _get_epsilon(dtype)\n\n    waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties(\n        waveform, channel, sr, frame_shift, frame_length, round_to_power_of_two,\n        preemphasis_coefficient)\n\n    strided_input, signal_log_energy = _get_window(\n        waveform, padded_window_size, window_size, window_shift, window_type,\n        blackman_coeff, snip_edges, raw_energy, energy_floor, dither,\n        remove_dc_offset, preemphasis_coefficient)\n\n    # (m, padded_window_size // 2 + 1, 2)\n    fft = paddle.fft.rfft(strided_input)\n\n    power_spectrum = paddle.maximum(\n        fft.abs().pow(2.), epsilon).log()  # (m, padded_window_size // 2 + 1)\n    power_spectrum[:, 0] = signal_log_energy\n\n    power_spectrum = _subtract_column_mean(power_spectrum, subtract_mean)\n    return power_spectrum\n\n\ndef _inverse_mel_scale_scalar(mel_freq: float) -> float:\n    return 700.0 * (math.exp(mel_freq / 1127.0) - 1.0)\n\n\ndef _inverse_mel_scale(mel_freq: Tensor) -> Tensor:\n    return 700.0 * ((mel_freq / 1127.0).exp() - 1.0)\n\n\ndef _mel_scale_scalar(freq: float) -> float:\n    return 1127.0 * math.log(1.0 + freq / 700.0)\n\n\ndef _mel_scale(freq: Tensor) -> Tensor:\n    return 1127.0 * (1.0 + freq / 700.0).log()\n\n\ndef _vtln_warp_freq(vtln_low_cutoff: float,\n                    vtln_high_cutoff: float,\n                    low_freq: float,\n                    high_freq: float,\n                    vtln_warp_factor: float,\n                    freq: Tensor) -> Tensor:\n    assert vtln_low_cutoff > low_freq, 'be sure to set the vtln_low option higher than low_freq'\n    assert vtln_high_cutoff < high_freq, 'be sure to set the vtln_high option lower than high_freq [or negative]'\n    l = vtln_low_cutoff * max(1.0, vtln_warp_factor)\n    h = vtln_high_cutoff * min(1.0, vtln_warp_factor)\n    scale = 1.0 / vtln_warp_factor\n    Fl = scale * l\n    Fh = scale * h\n    assert l > low_freq and h < high_freq\n    scale_left = (Fl - low_freq) / (l - low_freq)\n    scale_right = (high_freq - Fh) / (high_freq - h)\n    res = paddle.empty_like(freq)\n\n    outside_low_high_freq = paddle.less_than(freq, paddle.to_tensor(low_freq)) \\\n        | paddle.greater_than(freq, paddle.to_tensor(high_freq))\n    before_l = paddle.less_than(freq, paddle.to_tensor(l))\n    before_h = paddle.less_than(freq, paddle.to_tensor(h))\n    after_h = paddle.greater_equal(freq, paddle.to_tensor(h))\n\n    res[after_h] = high_freq + scale_right * (freq[after_h] - high_freq)\n    res[before_h] = scale * freq[before_h]\n    res[before_l] = low_freq + scale_left * (freq[before_l] - low_freq)\n    res[outside_low_high_freq] = freq[outside_low_high_freq]\n\n    return res\n\n\ndef _vtln_warp_mel_freq(vtln_low_cutoff: float,\n                        vtln_high_cutoff: float,\n                        low_freq,\n                        high_freq: float,\n                        vtln_warp_factor: float,\n                        mel_freq: Tensor) -> Tensor:\n    return _mel_scale(\n        _vtln_warp_freq(vtln_low_cutoff, vtln_high_cutoff, low_freq, high_freq,\n                        vtln_warp_factor, _inverse_mel_scale(mel_freq)))\n\n\ndef _get_mel_banks(num_bins: int,\n                   window_length_padded: int,\n                   sample_freq: float,\n                   low_freq: float,\n                   high_freq: float,\n                   vtln_low: float,\n                   vtln_high: float,\n                   vtln_warp_factor: float) -> Tuple[Tensor, Tensor]:\n    assert num_bins > 3, 'Must have at least 3 mel bins'\n    assert window_length_padded % 2 == 0\n    num_fft_bins = window_length_padded / 2\n    nyquist = 0.5 * sample_freq\n\n    if high_freq <= 0.0:\n        high_freq += nyquist\n\n    assert (0.0 <= low_freq < nyquist) and (0.0 < high_freq <= nyquist) and (low_freq < high_freq), \\\n        ('Bad values in options: low-freq {} and high-freq {} vs. nyquist {}'.format(low_freq, high_freq, nyquist))\n\n    fft_bin_width = sample_freq / window_length_padded\n    mel_low_freq = _mel_scale_scalar(low_freq)\n    mel_high_freq = _mel_scale_scalar(high_freq)\n\n    mel_freq_delta = (mel_high_freq - mel_low_freq) / (num_bins + 1)\n\n    if vtln_high < 0.0:\n        vtln_high += nyquist\n\n    assert vtln_warp_factor == 1.0 or ((low_freq < vtln_low < high_freq) and\n                                       (0.0 < vtln_high < high_freq) and (vtln_low < vtln_high)), \\\n        ('Bad values in options: vtln-low {} and vtln-high {}, versus '\n         'low-freq {} and high-freq {}'.format(vtln_low, vtln_high, low_freq, high_freq))\n\n    bin = paddle.arange(num_bins, dtype=paddle.float32).unsqueeze(1)\n    # left_mel = mel_low_freq + bin * mel_freq_delta  # (num_bins, 1)\n    # center_mel = mel_low_freq + (bin + 1.0) * mel_freq_delta  # (num_bins, 1)\n    # right_mel = mel_low_freq + (bin + 2.0) * mel_freq_delta  # (num_bins, 1)\n    left_mel = mel_low_freq + bin * mel_freq_delta  # (num_bins, 1)\n    center_mel = left_mel + mel_freq_delta\n    right_mel = center_mel + mel_freq_delta\n\n    if vtln_warp_factor != 1.0:\n        left_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq, high_freq,\n                                       vtln_warp_factor, left_mel)\n        center_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq,\n                                         high_freq, vtln_warp_factor,\n                                         center_mel)\n        right_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq,\n                                        high_freq, vtln_warp_factor, right_mel)\n\n    center_freqs = _inverse_mel_scale(center_mel)  # (num_bins)\n    # (1, num_fft_bins)\n    mel = _mel_scale(fft_bin_width * paddle.arange(\n        num_fft_bins, dtype=paddle.float32)).unsqueeze(0)\n\n    # (num_bins, num_fft_bins)\n    up_slope = (mel - left_mel) / (center_mel - left_mel)\n    down_slope = (right_mel - mel) / (right_mel - center_mel)\n\n    if vtln_warp_factor == 1.0:\n        bins = paddle.maximum(\n            paddle.zeros([1]), paddle.minimum(up_slope, down_slope))\n    else:\n        bins = paddle.zeros_like(up_slope)\n        up_idx = paddle.greater_than(mel, left_mel) & paddle.less_than(\n            mel, center_mel)\n        down_idx = paddle.greater_than(mel, center_mel) & paddle.less_than(\n            mel, right_mel)\n        bins[up_idx] = up_slope[up_idx]\n        bins[down_idx] = down_slope[down_idx]\n\n    return bins, center_freqs\n\n\ndef fbank(waveform: Tensor,\n          blackman_coeff: float=0.42,\n          channel: int=-1,\n          dither: float=0.0,\n          energy_floor: float=1.0,\n          frame_length: float=25.0,\n          frame_shift: float=10.0,\n          high_freq: float=0.0,\n          htk_compat: bool=False,\n          low_freq: float=20.0,\n          n_mels: int=23,\n          preemphasis_coefficient: float=0.97,\n          raw_energy: bool=True,\n          remove_dc_offset: bool=True,\n          round_to_power_of_two: bool=True,\n          sr: int=16000,\n          snip_edges: bool=True,\n          subtract_mean: bool=False,\n          use_energy: bool=False,\n          use_log_fbank: bool=True,\n          use_power: bool=True,\n          vtln_high: float=-500.0,\n          vtln_low: float=100.0,\n          vtln_warp: float=1.0,\n          window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return filter banks from a waveform. The output is identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`. `C` is in the range [0,1]. \n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        high_freq (float, optional): The upper cut-off frequency. Defaults to 0.0.\n        htk_compat (bool, optional): Put energy to the last when it is set True. Defaults to False.\n        low_freq (float, optional): The lower cut-off frequency. Defaults to 20.0.\n        n_mels (int, optional): Number of output mel bins. Defaults to 23.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that can't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        use_energy (bool, optional): Add an dimension with energy of spectrogram to the output. Defaults to False.\n        use_log_fbank (bool, optional): Return log fbank when it is set True. Defaults to True.\n        use_power (bool, optional): Whether to use power instead of magnitude. Defaults to True.\n        vtln_high (float, optional): High inflection point in piecewise linear VTLN warping function. Defaults to -500.0.\n        vtln_low (float, optional): Low inflection point in piecewise linear VTLN warping function. Defaults to 100.0.\n        vtln_warp (float, optional): Vtln warp factor. Defaults to 1.0.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to \"povey\".\n\n    Returns:\n        Tensor: A filter banks tensor with shape `(m, n_mels)`.\n    \"\"\"\n    dtype = waveform.dtype\n\n    waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties(\n        waveform, channel, sr, frame_shift, frame_length, round_to_power_of_two,\n        preemphasis_coefficient)\n\n    strided_input, signal_log_energy = _get_window(\n        waveform, padded_window_size, window_size, window_shift, window_type,\n        blackman_coeff, snip_edges, raw_energy, energy_floor, dither,\n        remove_dc_offset, preemphasis_coefficient)\n\n    # (m, padded_window_size // 2 + 1)\n    spectrum = paddle.fft.rfft(strided_input).abs()\n    if use_power:\n        spectrum = spectrum.pow(2.)\n\n    # (n_mels, padded_window_size // 2)\n    mel_energies, _ = _get_mel_banks(n_mels, padded_window_size, sr, low_freq,\n                                     high_freq, vtln_low, vtln_high, vtln_warp)\n    # mel_energies = mel_energies.astype(dtype)\n    assert mel_energies.dtype == dtype\n\n    # (n_mels, padded_window_size // 2 + 1)\n    mel_energies = paddle.nn.functional.pad(\n        mel_energies.unsqueeze(0), (0, 1),\n        data_format='NCL',\n        mode='constant',\n        value=0).squeeze(0)\n\n    # (m, n_mels)\n    mel_energies = paddle.mm(spectrum, mel_energies.T)\n    if use_log_fbank:\n        mel_energies = paddle.maximum(mel_energies, _get_epsilon(dtype)).log()\n\n    if use_energy:\n        signal_log_energy = signal_log_energy.unsqueeze(1)\n        if htk_compat:\n            mel_energies = paddle.concat(\n                (mel_energies, signal_log_energy), axis=1)\n        else:\n            mel_energies = paddle.concat(\n                (signal_log_energy, mel_energies), axis=1)\n\n    # (m, n_mels + 1)\n    mel_energies = _subtract_column_mean(mel_energies, subtract_mean)\n    return mel_energies\n\n\ndef _get_dct_matrix(n_mfcc: int, n_mels: int) -> Tensor:\n    dct_matrix = create_dct(n_mels, n_mels, 'ortho')\n    dct_matrix[:, 0] = math.sqrt(1 / float(n_mels))\n    dct_matrix = dct_matrix[:, :n_mfcc]  # (n_mels, n_mfcc)\n    return dct_matrix\n\n\ndef _get_lifter_coeffs(n_mfcc: int, cepstral_lifter: float) -> Tensor:\n    i = paddle.arange(n_mfcc)\n    return 1.0 + 0.5 * cepstral_lifter * paddle.sin(math.pi * i /\n                                                    cepstral_lifter)\n\n\ndef mfcc(waveform: Tensor,\n         blackman_coeff: float=0.42,\n         cepstral_lifter: float=22.0,\n         channel: int=-1,\n         dither: float=0.0,\n         energy_floor: float=1.0,\n         frame_length: float=25.0,\n         frame_shift: float=10.0,\n         high_freq: float=0.0,\n         htk_compat: bool=False,\n         low_freq: float=20.0,\n         n_mfcc: int=13,\n         n_mels: int=23,\n         preemphasis_coefficient: float=0.97,\n         raw_energy: bool=True,\n         remove_dc_offset: bool=True,\n         round_to_power_of_two: bool=True,\n         sr: int=16000,\n         snip_edges: bool=True,\n         subtract_mean: bool=False,\n         use_energy: bool=False,\n         vtln_high: float=-500.0,\n         vtln_low: float=100.0,\n         vtln_warp: float=1.0,\n         window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return mel frequency cepstral coefficients from a waveform. The output is\n            identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`.\n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        cepstral_lifter (float, optional): Scaling of output mfccs. Defaults to 22.0.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        high_freq (float, optional): The upper cut-off frequency. Defaults to 0.0.\n        htk_compat (bool, optional): Put energy to the last when it is set True. Defaults to False.\n        low_freq (float, optional): The lower cut-off frequency. Defaults to 20.0.\n        n_mfcc (int, optional): Number of cepstra in MFCC. Defaults to 13.\n        n_mels (int, optional): Number of output mel bins. Defaults to 23.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that can't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        use_energy (bool, optional): Add an dimension with energy of spectrogram to the output. Defaults to False.\n        vtln_high (float, optional): High inflection point in piecewise linear VTLN warping function. Defaults to -500.0.\n        vtln_low (float, optional): Low inflection point in piecewise linear VTLN warping function. Defaults to 100.0.\n        vtln_warp (float, optional): Vtln warp factor. Defaults to 1.0.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to POVEY.\n\n    Returns:\n        Tensor: A mel frequency cepstral coefficients tensor with shape `(m, n_mfcc)`.\n    \"\"\"\n    assert n_mfcc <= n_mels, 'n_mfcc cannot be larger than n_mels: %d vs %d' % (\n        n_mfcc, n_mels)\n\n    dtype = waveform.dtype\n\n    # (m, n_mels + use_energy)\n    feature = fbank(\n        waveform=waveform,\n        blackman_coeff=blackman_coeff,\n        channel=channel,\n        dither=dither,\n        energy_floor=energy_floor,\n        frame_length=frame_length,\n        frame_shift=frame_shift,\n        high_freq=high_freq,\n        htk_compat=htk_compat,\n        low_freq=low_freq,\n        n_mels=n_mels,\n        preemphasis_coefficient=preemphasis_coefficient,\n        raw_energy=raw_energy,\n        remove_dc_offset=remove_dc_offset,\n        round_to_power_of_two=round_to_power_of_two,\n        sr=sr,\n        snip_edges=snip_edges,\n        subtract_mean=False,\n        use_energy=use_energy,\n        use_log_fbank=True,\n        use_power=True,\n        vtln_high=vtln_high,\n        vtln_low=vtln_low,\n        vtln_warp=vtln_warp,\n        window_type=window_type)\n\n    if use_energy:\n        # (m)\n        signal_log_energy = feature[:, n_mels if htk_compat else 0]\n        mel_offset = int(not htk_compat)\n        feature = feature[:, mel_offset:(n_mels + mel_offset)]\n\n    # (n_mels, n_mfcc)\n    dct_matrix = _get_dct_matrix(n_mfcc, n_mels).astype(dtype=dtype)\n\n    # (m, n_mfcc)\n    feature = feature.matmul(dct_matrix)\n\n    if cepstral_lifter != 0.0:\n        # (1, n_mfcc)\n        lifter_coeffs = _get_lifter_coeffs(n_mfcc, cepstral_lifter).unsqueeze(0)\n        feature *= lifter_coeffs.astype(dtype=dtype)\n\n    if use_energy:\n        feature[:, 0] = signal_log_energy\n\n    if htk_compat:\n        energy = feature[:, 0].unsqueeze(1)  # (m, 1)\n        feature = feature[:, 1:]  # (m, n_mfcc - 1)\n        if not use_energy:\n            energy *= math.sqrt(2)\n\n        feature = paddle.concat((feature, energy), axis=1)\n\n    feature = _subtract_column_mean(feature, subtract_mean)\n    return feature\n"
  },
  {
    "path": "audio/paddleaudio/compliance/librosa.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from librosa(https://github.com/librosa/librosa)\nimport warnings\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport numpy as np\nimport scipy\nfrom numpy.lib.stride_tricks import as_strided\nfrom scipy import signal\n\nfrom ..backends import depth_convert\nfrom ..utils import ParameterError\n\n__all__ = [\n    # dsp\n    'stft',\n    'mfcc',\n    'hz_to_mel',\n    'mel_to_hz',\n    'mel_frequencies',\n    'power_to_db',\n    'compute_fbank_matrix',\n    'melspectrogram',\n    'spectrogram',\n    'mu_encode',\n    'mu_decode',\n    # augmentation\n    'depth_augment',\n    'spect_augment',\n    'random_crop1d',\n    'random_crop2d',\n    'adaptive_spect_augment',\n]\n\n\ndef _pad_center(data: np.ndarray, size: int, axis: int=-1,\n                **kwargs) -> np.ndarray:\n    \"\"\"Pad an array to a target length along a target axis.\n\n    This differs from `np.pad` by centering the data prior to padding,\n    analogous to `str.center`\n    \"\"\"\n\n    kwargs.setdefault(\"mode\", \"constant\")\n    n = data.shape[axis]\n    lpad = int((size - n) // 2)\n    lengths = [(0, 0)] * data.ndim\n    lengths[axis] = (lpad, int(size - n - lpad))\n\n    if lpad < 0:\n        raise ParameterError((\"Target size ({size:d}) must be \"\n                              \"at least input size ({n:d})\"))\n\n    return np.pad(data, lengths, **kwargs)\n\n\ndef _split_frames(x: np.ndarray,\n                  frame_length: int,\n                  hop_length: int,\n                  axis: int=-1) -> np.ndarray:\n    \"\"\"Slice a data array into (overlapping) frames.\n\n    This function is aligned with librosa.frame\n    \"\"\"\n\n    if not isinstance(x, np.ndarray):\n        raise ParameterError(\n            f\"Input must be of type numpy.ndarray, given type(x)={type(x)}\")\n\n    if x.shape[axis] < frame_length:\n        raise ParameterError(f\"Input is too short (n={x.shape[axis]:d})\"\n                             f\" for frame_length={frame_length:d}\")\n\n    if hop_length < 1:\n        raise ParameterError(f\"Invalid hop_length: {hop_length:d}\")\n\n    if axis == -1 and not x.flags[\"F_CONTIGUOUS\"]:\n        warnings.warn(f\"librosa.util.frame called with axis={axis} \"\n                      \"on a non-contiguous input. This will result in a copy.\")\n        x = np.asfortranarray(x)\n    elif axis == 0 and not x.flags[\"C_CONTIGUOUS\"]:\n        warnings.warn(f\"librosa.util.frame called with axis={axis} \"\n                      \"on a non-contiguous input. This will result in a copy.\")\n        x = np.ascontiguousarray(x)\n\n    n_frames = 1 + (x.shape[axis] - frame_length) // hop_length\n    strides = np.asarray(x.strides)\n\n    new_stride = np.prod(strides[strides > 0] // x.itemsize) * x.itemsize\n\n    if axis == -1:\n        shape = list(x.shape)[:-1] + [frame_length, n_frames]\n        strides = list(strides) + [hop_length * new_stride]\n\n    elif axis == 0:\n        shape = [n_frames, frame_length] + list(x.shape)[1:]\n        strides = [hop_length * new_stride] + list(strides)\n\n    else:\n        raise ParameterError(f\"Frame axis={axis} must be either 0 or -1\")\n\n    return as_strided(x, shape=shape, strides=strides)\n\n\ndef _check_audio(y, mono=True) -> bool:\n    \"\"\"Determine whether a variable contains valid audio data.\n\n    The audio y must be a np.ndarray, ether 1-channel or two channel\n    \"\"\"\n    if not isinstance(y, np.ndarray):\n        raise ParameterError(\"Audio data must be of type numpy.ndarray\")\n    if y.ndim > 2:\n        raise ParameterError(\n            f\"Invalid shape for audio ndim={y.ndim:d}, shape={y.shape}\")\n\n    if mono and y.ndim == 2:\n        raise ParameterError(\n            f\"Invalid shape for mono audio ndim={y.ndim:d}, shape={y.shape}\")\n\n    if (mono and len(y) == 0) or (not mono and y.shape[1] < 0):\n        raise ParameterError(f\"Audio is empty ndim={y.ndim:d}, shape={y.shape}\")\n\n    if not np.issubdtype(y.dtype, np.floating):\n        raise ParameterError(\"Audio data must be floating-point\")\n\n    if not np.isfinite(y).all():\n        raise ParameterError(\"Audio buffer is not finite everywhere\")\n\n    return True\n\n\ndef hz_to_mel(frequencies: Union[float, List[float], np.ndarray],\n              htk: bool=False) -> np.ndarray:\n    \"\"\"Convert Hz to Mels.\n\n    Args:\n        frequencies (Union[float, List[float], np.ndarray]): Frequencies in Hz.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Frequency in mels.\n    \"\"\"\n    freq = np.asanyarray(frequencies)\n\n    if htk:\n        return 2595.0 * np.log10(1.0 + freq / 700.0)\n\n    # Fill in the linear part\n    f_min = 0.0\n    f_sp = 200.0 / 3\n\n    mels = (freq - f_min) / f_sp\n\n    # Fill in the log-scale part\n\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = np.log(6.4) / 27.0  # step size for log region\n\n    if freq.ndim:\n        # If we have array data, vectorize\n        log_t = freq >= min_log_hz\n        mels[log_t] = min_log_mel + \\\n            np.log(freq[log_t] / min_log_hz) / logstep\n    elif freq >= min_log_hz:\n        # If we have scalar data, heck directly\n        mels = min_log_mel + np.log(freq / min_log_hz) / logstep\n\n    return mels\n\n\ndef mel_to_hz(mels: Union[float, List[float], np.ndarray],\n              htk: int=False) -> np.ndarray:\n    \"\"\"Convert mel bin numbers to frequencies.\n\n    Args:\n        mels (Union[float, List[float], np.ndarray]): Frequency in mels.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Frequencies in Hz.\n    \"\"\"\n    mel_array = np.asanyarray(mels)\n\n    if htk:\n        return 700.0 * (10.0**(mel_array / 2595.0) - 1.0)\n\n    # Fill in the linear scale\n    f_min = 0.0\n    f_sp = 200.0 / 3\n    freqs = f_min + f_sp * mel_array\n\n    # And now the nonlinear scale\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = np.log(6.4) / 27.0  # step size for log region\n\n    if mel_array.ndim:\n        # If we have vector data, vectorize\n        log_t = mel_array >= min_log_mel\n        freqs[log_t] = min_log_hz * \\\n            np.exp(logstep * (mel_array[log_t] - min_log_mel))\n    elif mel_array >= min_log_mel:\n        # If we have scalar data, check directly\n        freqs = min_log_hz * np.exp(logstep * (mel_array - min_log_mel))\n\n    return freqs\n\n\ndef mel_frequencies(n_mels: int=128,\n                    fmin: float=0.0,\n                    fmax: float=11025.0,\n                    htk: bool=False) -> np.ndarray:\n    \"\"\"Compute mel frequencies.\n\n    Args:\n        n_mels (int, optional): Number of mel bins. Defaults to 128.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (float, optional): Maximum frequency in Hz. Defaults to 11025.0.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Vector of n_mels frequencies in Hz with shape `(n_mels,)`.\n    \"\"\"\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    min_mel = hz_to_mel(fmin, htk=htk)\n    max_mel = hz_to_mel(fmax, htk=htk)\n\n    mels = np.linspace(min_mel, max_mel, n_mels)\n\n    return mel_to_hz(mels, htk=htk)\n\n\ndef fft_frequencies(sr: int, n_fft: int) -> np.ndarray:\n    \"\"\"Compute fourier frequencies.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): FFT size.\n\n    Returns:\n        np.ndarray: FFT frequencies in Hz with shape `(n_fft//2 + 1,)`.\n    \"\"\"\n    return np.linspace(0, float(sr) / 2, int(1 + n_fft // 2), endpoint=True)\n\n\ndef compute_fbank_matrix(sr: int,\n                         n_fft: int,\n                         n_mels: int=128,\n                         fmin: float=0.0,\n                         fmax: Optional[float]=None,\n                         htk: bool=False,\n                         norm: str=\"slaney\",\n                         dtype: type=np.float32) -> np.ndarray:\n    \"\"\"Compute fbank matrix.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): FFT size.\n        n_mels (int, optional): Number of mel bins. Defaults to 128.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        norm (str, optional): Type of normalization. Defaults to \"slaney\".\n        dtype (type, optional): Data type. Defaults to np.float32.\n\n\n    Returns:\n        np.ndarray: Mel transform matrix with shape `(n_mels, n_fft//2 + 1)`.\n    \"\"\"\n    if norm != \"slaney\":\n        raise ParameterError('norm must set to slaney')\n\n    if fmax is None:\n        fmax = float(sr) / 2\n\n    # Initialize the weights\n    n_mels = int(n_mels)\n    weights = np.zeros((n_mels, int(1 + n_fft // 2)), dtype=dtype)\n\n    # Center freqs of each FFT bin\n    fftfreqs = fft_frequencies(sr=sr, n_fft=n_fft)\n\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    mel_f = mel_frequencies(n_mels + 2, fmin=fmin, fmax=fmax, htk=htk)\n\n    fdiff = np.diff(mel_f)\n    ramps = np.subtract.outer(mel_f, fftfreqs)\n\n    for i in range(n_mels):\n        # lower and upper slopes for all bins\n        lower = -ramps[i] / fdiff[i]\n        upper = ramps[i + 2] / fdiff[i + 1]\n\n        # .. then intersect them with each other and zero\n        weights[i] = np.maximum(0, np.minimum(lower, upper))\n\n    if norm == \"slaney\":\n        # Slaney-style mel is scaled to be approx constant energy per channel\n        enorm = 2.0 / (mel_f[2:n_mels + 2] - mel_f[:n_mels])\n        weights *= enorm[:, np.newaxis]\n\n    # Only check weights if f_mel[0] is positive\n    if not np.all((mel_f[:-2] == 0) | (weights.max(axis=1) > 0)):\n        # This means we have an empty channel somewhere\n        warnings.warn(\"Empty filters detected in mel frequency basis. \"\n                      \"Some channels will produce empty responses. \"\n                      \"Try increasing your sampling rate (and fmax) or \"\n                      \"reducing n_mels.\")\n\n    return weights\n\n\ndef stft(x: np.ndarray,\n         n_fft: int=2048,\n         hop_length: Optional[int]=None,\n         win_length: Optional[int]=None,\n         window: str=\"hann\",\n         center: bool=True,\n         dtype: type=np.complex64,\n         pad_mode: str=\"reflect\") -> np.ndarray:\n    \"\"\"Short-time Fourier transform (STFT).\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        n_fft (int, optional): FFT size. Defaults to 2048.\n        hop_length (Optional[int], optional): Number of steps to advance between adjacent windows. Defaults to None.\n        win_length (Optional[int], optional): The size of window. Defaults to None.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        dtype (type, optional): Data type of STFT results. Defaults to np.complex64.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n\n    Returns:\n        np.ndarray: The complex STFT output with shape `(n_fft//2 + 1, num_frames)`.\n    \"\"\"\n    _check_audio(x)\n\n    # By default, use the entire frame\n    if win_length is None:\n        win_length = n_fft\n\n    # Set the default hop, if it's not already specified\n    if hop_length is None:\n        hop_length = int(win_length // 4)\n\n    fft_window = signal.get_window(window, win_length, fftbins=True)\n\n    # Pad the window out to n_fft size\n    fft_window = _pad_center(fft_window, n_fft)\n\n    # Reshape so that the window can be broadcast\n    fft_window = fft_window.reshape((-1, 1))\n\n    # Pad the time series so that frames are centered\n    if center:\n        if n_fft > x.shape[-1]:\n            warnings.warn(\n                f\"n_fft={n_fft} is too small for input signal of length={x.shape[-1]}\"\n            )\n        x = np.pad(x, int(n_fft // 2), mode=pad_mode)\n\n    elif n_fft > x.shape[-1]:\n        raise ParameterError(\n            f\"n_fft={n_fft} is too small for input signal of length={x.shape[-1]}\"\n        )\n\n    # Window the time series.\n    x_frames = _split_frames(x, frame_length=n_fft, hop_length=hop_length)\n    # Pre-allocate the STFT matrix\n    stft_matrix = np.empty(\n        (int(1 + n_fft // 2), x_frames.shape[1]), dtype=dtype, order=\"F\")\n    fft = np.fft  # use numpy fft as default\n    # Constrain STFT block sizes to 256 KB\n    MAX_MEM_BLOCK = 2**8 * 2**10\n    # how many columns can we fit within MAX_MEM_BLOCK?\n    n_columns = MAX_MEM_BLOCK // (stft_matrix.shape[0] * stft_matrix.itemsize)\n    n_columns = max(n_columns, 1)\n\n    for bl_s in range(0, stft_matrix.shape[1], n_columns):\n        bl_t = min(bl_s + n_columns, stft_matrix.shape[1])\n        stft_matrix[:, bl_s:bl_t] = fft.rfft(\n            fft_window * x_frames[:, bl_s:bl_t], axis=0)\n\n    return stft_matrix\n\n\ndef power_to_db(spect: np.ndarray,\n                ref: float=1.0,\n                amin: float=1e-10,\n                top_db: Optional[float]=80.0) -> np.ndarray:\n    \"\"\"Convert a power spectrogram (amplitude squared) to decibel (dB) units. The function computes the scaling `10 * log10(x / ref)` in a numerically stable way.\n\n    Args:\n        spect (np.ndarray): STFT power spectrogram of an input waveform.\n        ref (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to 80.0.\n\n    Returns:\n        np.ndarray: Power spectrogram in db scale.\n    \"\"\"\n    spect = np.asarray(spect)\n\n    if amin <= 0:\n        raise ParameterError(\"amin must be strictly positive\")\n\n    if np.issubdtype(spect.dtype, np.complexfloating):\n        warnings.warn(\n            \"power_to_db was called on complex input so phase \"\n            \"information will be discarded. To suppress this warning, \"\n            \"call power_to_db(np.abs(D)**2) instead.\")\n        magnitude = np.abs(spect)\n    else:\n        magnitude = spect\n\n    if callable(ref):\n        # User supplied a function to calculate reference power\n        ref_value = ref(magnitude)\n    else:\n        ref_value = np.abs(ref)\n\n    log_spec = 10.0 * np.log10(np.maximum(amin, magnitude))\n    log_spec -= 10.0 * np.log10(np.maximum(amin, ref_value))\n\n    if top_db is not None:\n        if top_db < 0:\n            raise ParameterError(\"top_db must be non-negative\")\n        log_spec = np.maximum(log_spec, log_spec.max() - top_db)\n\n    return log_spec\n\n\ndef mfcc(x: np.ndarray,\n         sr: int=16000,\n         spect: Optional[np.ndarray]=None,\n         n_mfcc: int=20,\n         dct_type: int=2,\n         norm: str=\"ortho\",\n         lifter: int=0,\n         **kwargs) -> np.ndarray:\n    \"\"\"Mel-frequency cepstral coefficients (MFCCs)\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        spect (Optional[np.ndarray], optional): Input log-power Mel spectrogram. Defaults to None.\n        n_mfcc (int, optional): Number of cepstra in MFCC. Defaults to 20.\n        dct_type (int, optional): Discrete cosine transform (DCT) type. Defaults to 2.\n        norm (str, optional): Type of normalization. Defaults to \"ortho\".\n        lifter (int, optional): Cepstral filtering. Defaults to 0.\n\n    Returns:\n        np.ndarray: Mel frequency cepstral coefficients array with shape `(n_mfcc, num_frames)`.\n    \"\"\"\n    if spect is None:\n        spect = melspectrogram(x, sr=sr, **kwargs)\n\n    M = scipy.fftpack.dct(spect, axis=0, type=dct_type, norm=norm)[:n_mfcc]\n\n    if lifter > 0:\n        factor = np.sin(np.pi * np.arange(1, 1 + n_mfcc, dtype=M.dtype) /\n                        lifter)\n        return M * factor[:, np.newaxis]\n    elif lifter == 0:\n        return M\n    else:\n        raise ParameterError(\n            f\"MFCC lifter={lifter} must be a non-negative number\")\n\n\ndef melspectrogram(x: np.ndarray,\n                   sr: int=16000,\n                   window_size: int=512,\n                   hop_length: int=320,\n                   n_mels: int=64,\n                   fmin: float=50.0,\n                   fmax: Optional[float]=None,\n                   window: str='hann',\n                   center: bool=True,\n                   pad_mode: str='reflect',\n                   power: float=2.0,\n                   to_db: bool=True,\n                   ref: float=1.0,\n                   amin: float=1e-10,\n                   top_db: Optional[float]=None) -> np.ndarray:\n    \"\"\"Compute mel-spectrogram.\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        window_size (int, optional): Size of FFT and window length. Defaults to 512.\n        hop_length (int, optional): Number of steps to advance between adjacent windows. Defaults to 320.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 50.0.\n        fmax (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n        power (float, optional): Exponent for the magnitude melspectrogram. Defaults to 2.0.\n        to_db (bool, optional): Enable db scale. Defaults to True.\n        ref (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to None.\n\n    Returns:\n        np.ndarray: The mel-spectrogram in power scale or db scale with shape `(n_mels, num_frames)`.\n    \"\"\"\n    _check_audio(x, mono=True)\n    if len(x) <= 0:\n        raise ParameterError('The input waveform is empty')\n\n    if fmax is None:\n        fmax = sr // 2\n    if fmin < 0 or fmin >= fmax:\n        raise ParameterError('fmin and fmax must satisfy 0<fmin<fmax')\n\n    s = stft(\n        x,\n        n_fft=window_size,\n        hop_length=hop_length,\n        win_length=window_size,\n        window=window,\n        center=center,\n        pad_mode=pad_mode)\n\n    spect_power = np.abs(s)**power\n    fb_matrix = compute_fbank_matrix(\n        sr=sr, n_fft=window_size, n_mels=n_mels, fmin=fmin, fmax=fmax)\n    mel_spect = np.matmul(fb_matrix, spect_power)\n    if to_db:\n        return power_to_db(mel_spect, ref=ref, amin=amin, top_db=top_db)\n    else:\n        return mel_spect\n\n\ndef spectrogram(x: np.ndarray,\n                sr: int=16000,\n                window_size: int=512,\n                hop_length: int=320,\n                window: str='hann',\n                center: bool=True,\n                pad_mode: str='reflect',\n                power: float=2.0) -> np.ndarray:\n    \"\"\"Compute spectrogram.\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        window_size (int, optional): Size of FFT and window length. Defaults to 512.\n        hop_length (int, optional): Number of steps to advance between adjacent windows. Defaults to 320.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n        power (float, optional): Exponent for the magnitude melspectrogram. Defaults to 2.0.\n\n    Returns:\n        np.ndarray: The STFT spectrogram in power scale `(n_fft//2 + 1, num_frames)`.\n    \"\"\"\n\n    s = stft(\n        x,\n        n_fft=window_size,\n        hop_length=hop_length,\n        win_length=window_size,\n        window=window,\n        center=center,\n        pad_mode=pad_mode)\n\n    return np.abs(s)**power\n\n\ndef mu_encode(x: np.ndarray, mu: int=255, quantized: bool=True) -> np.ndarray:\n    \"\"\"Mu-law encoding. Encode waveform based on mu-law companding. When quantized is True, the result will be converted to integer in range `[0,mu-1]`. Otherwise, the resulting waveform is in range `[-1,1]`.\n\n    Args:\n        x (np.ndarray): The input waveform to encode.\n        mu (int, optional): The endoceding parameter. Defaults to 255.\n        quantized (bool, optional): If `True`, quantize the encoded values into `1 + mu` distinct integer values. Defaults to True.\n\n    Returns:\n        np.ndarray: The mu-law encoded waveform.\n    \"\"\"\n    mu = 255\n    y = np.sign(x) * np.log1p(mu * np.abs(x)) / np.log1p(mu)\n    if quantized:\n        y = np.floor((y + 1) / 2 * mu + 0.5)  # convert to [0 , mu-1]\n    return y\n\n\ndef mu_decode(y: np.ndarray, mu: int=255, quantized: bool=True) -> np.ndarray:\n    \"\"\"Mu-law decoding. Compute the mu-law decoding given an input code. It assumes that the input `y` is in range `[0,mu-1]` when quantize is True and `[-1,1]` otherwise.\n\n    Args:\n        y (np.ndarray): The encoded waveform.\n        mu (int, optional): The endoceding parameter. Defaults to 255.\n        quantized (bool, optional): If `True`, the input is assumed to be quantized to `1 + mu` distinct integer values. Defaults to True.\n\n    Returns:\n        np.ndarray: The mu-law decoded waveform.\n    \"\"\"\n    if mu < 1:\n        raise ParameterError('mu is typically set as 2**k-1, k=1, 2, 3,...')\n\n    mu = mu - 1\n    if quantized:  # undo the quantization\n        y = y * 2 / mu - 1\n    x = np.sign(y) / mu * ((1 + mu)**np.abs(y) - 1)\n    return x\n\n\ndef _randint(high: int) -> int:\n    \"\"\"Generate one random integer in range [0 high)\n\n     This is a helper function for random data augmentation\n    \"\"\"\n    return int(np.random.randint(0, high=high))\n\n\ndef depth_augment(y: np.ndarray,\n                  choices: List=['int8', 'int16'],\n                  probs: List[float]=[0.5, 0.5]) -> np.ndarray:\n    \"\"\" Audio depth augmentation. Do audio depth augmentation to simulate the distortion brought by quantization.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        choices (List, optional): A list of data type to depth conversion. Defaults to ['int8', 'int16'].\n        probs (List[float], optional): Probabilities to depth conversion. Defaults to [0.5, 0.5].\n\n    Returns:\n        np.ndarray: The augmented waveform.\n    \"\"\"\n    assert len(probs) == len(\n        choices\n    ), 'number of choices {} must be equal to size of probs {}'.format(\n        len(choices), len(probs))\n    depth = np.random.choice(choices, p=probs)\n    src_depth = y.dtype\n    y1 = depth_convert(y, depth)\n    y2 = depth_convert(y1, src_depth)\n\n    return y2\n\n\ndef adaptive_spect_augment(spect: np.ndarray,\n                           tempo_axis: int=0,\n                           level: float=0.1) -> np.ndarray:\n    \"\"\"Do adaptive spectrogram augmentation. The level of the augmentation is govern by the parameter level, ranging from 0 to 1, with 0 represents no augmentation.\n\n    Args:\n        spect (np.ndarray): Input spectrogram.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n        level (float, optional): The level factor of masking. Defaults to 0.1.\n\n    Returns:\n        np.ndarray: The augmented spectrogram.\n    \"\"\"\n    assert spect.ndim == 2., 'only supports 2d tensor or numpy array'\n    if tempo_axis == 0:\n        nt, nf = spect.shape\n    else:\n        nf, nt = spect.shape\n\n    time_mask_width = int(nt * level * 0.5)\n    freq_mask_width = int(nf * level * 0.5)\n\n    num_time_mask = int(10 * level)\n    num_freq_mask = int(10 * level)\n\n    if tempo_axis == 0:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[start:start + time_mask_width, :] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[:, start:start + freq_mask_width] = 0\n    else:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[:, start:start + time_mask_width] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[start:start + freq_mask_width, :] = 0\n\n    return spect\n\n\ndef spect_augment(spect: np.ndarray,\n                  tempo_axis: int=0,\n                  max_time_mask: int=3,\n                  max_freq_mask: int=3,\n                  max_time_mask_width: int=30,\n                  max_freq_mask_width: int=20) -> np.ndarray:\n    \"\"\"Do spectrogram augmentation in both time and freq axis.\n\n    Args:\n        spect (np.ndarray): Input spectrogram.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n        max_time_mask (int, optional): Maximum number of time masking. Defaults to 3.\n        max_freq_mask (int, optional): Maximum number of frequency masking. Defaults to 3.\n        max_time_mask_width (int, optional): Maximum width of time masking. Defaults to 30.\n        max_freq_mask_width (int, optional): Maximum width of frequency masking. Defaults to 20.\n\n    Returns:\n        np.ndarray: The augmented spectrogram.\n    \"\"\"\n    assert spect.ndim == 2., 'only supports 2d tensor or numpy array'\n    if tempo_axis == 0:\n        nt, nf = spect.shape\n    else:\n        nf, nt = spect.shape\n\n    num_time_mask = _randint(max_time_mask)\n    num_freq_mask = _randint(max_freq_mask)\n\n    time_mask_width = _randint(max_time_mask_width)\n    freq_mask_width = _randint(max_freq_mask_width)\n\n    if tempo_axis == 0:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[start:start + time_mask_width, :] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[:, start:start + freq_mask_width] = 0\n    else:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[:, start:start + time_mask_width] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[start:start + freq_mask_width, :] = 0\n\n    return spect\n\n\ndef random_crop1d(y: np.ndarray, crop_len: int) -> np.ndarray:\n    \"\"\" Random cropping on a input waveform.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D.\n        crop_len (int): Length of waveform to crop.\n\n    Returns:\n        np.ndarray: The cropped waveform.\n    \"\"\"\n    if y.ndim != 1:\n        'only accept 1d tensor or numpy array'\n    n = len(y)\n    idx = _randint(n - crop_len)\n    return y[idx:idx + crop_len]\n\n\ndef random_crop2d(s: np.ndarray, crop_len: int,\n                  tempo_axis: int=0) -> np.ndarray:\n    \"\"\" Random cropping on a spectrogram.\n\n    Args:\n        s (np.ndarray): Input spectrogram in 2D.\n        crop_len (int): Length of spectrogram to crop.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n\n    Returns:\n        np.ndarray: The cropped spectrogram.\n    \"\"\"\n    if tempo_axis >= s.ndim:\n        raise ParameterError('axis out of range')\n\n    n = s.shape[tempo_axis]\n    idx = _randint(high=n - crop_len)\n    sli = [slice(None) for i in range(s.ndim)]\n    sli[tempo_axis] = slice(idx, idx + crop_len)\n    out = s[tuple(sli)]\n    return out\n"
  },
  {
    "path": "audio/paddleaudio/datasets/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .esc50 import ESC50\nfrom .gtzan import GTZAN\nfrom .hey_snips import HeySnips\nfrom .rirs_noises import OpenRIRNoise\nfrom .tess import TESS\nfrom .urban_sound import UrbanSound8K\nfrom .voxceleb import VoxCeleb\n"
  },
  {
    "path": "audio/paddleaudio/datasets/dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nimport numpy as np\nimport paddle\n\nfrom ..backends.soundfile_backend import soundfile_load as load_audio\nfrom ..compliance.kaldi import fbank as kaldi_fbank\nfrom ..compliance.kaldi import mfcc as kaldi_mfcc\nfrom ..compliance.librosa import melspectrogram\nfrom ..compliance.librosa import mfcc\n\nfeat_funcs = {\n    'raw': None,\n    'melspectrogram': melspectrogram,\n    'mfcc': mfcc,\n    'kaldi_fbank': kaldi_fbank,\n    'kaldi_mfcc': kaldi_mfcc,\n}\n\n\nclass AudioClassificationDataset(paddle.io.Dataset):\n    \"\"\"\n    Base class of audio classification dataset.\n    \"\"\"\n\n    def __init__(self,\n                 files: List[str],\n                 labels: List[int],\n                 feat_type: str='raw',\n                 sample_rate: int=None,\n                 **kwargs):\n        \"\"\"\n        Args:\n            files (:obj:`List[str]`): A list of absolute path of audio files.\n            labels (:obj:`List[int]`): Labels of audio files.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        super(AudioClassificationDataset, self).__init__()\n\n        if feat_type not in feat_funcs.keys():\n            raise RuntimeError(\n                f\"Unknown feat_type: {feat_type}, it must be one in {list(feat_funcs.keys())}\"\n            )\n\n        self.files = files\n        self.labels = labels\n\n        self.feat_type = feat_type\n        self.sample_rate = sample_rate\n        self.feat_config = kwargs  # Pass keyword arguments to customize feature config\n\n    def _get_data(self, input_file: str):\n        raise NotImplementedError\n\n    def _convert_to_record(self, idx):\n        file, label = self.files[idx], self.labels[idx]\n\n        if self.sample_rate is None:\n            waveform, sample_rate = load_audio(file)\n        else:\n            waveform, sample_rate = load_audio(file, sr=self.sample_rate)\n\n        feat_func = feat_funcs[self.feat_type]\n\n        record = {}\n        if self.feat_type in ['kaldi_fbank', 'kaldi_mfcc']:\n            waveform = paddle.to_tensor(waveform).unsqueeze(0)  # (C, T)\n            record['feat'] = feat_func(\n                waveform=waveform, sr=self.sample_rate, **self.feat_config)\n        else:\n            record['feat'] = feat_func(\n                waveform, sample_rate,\n                **self.feat_config) if feat_func else waveform\n        record['label'] = label\n        return record\n\n    def __getitem__(self, idx):\n        record = self._convert_to_record(idx)\n        if self.feat_type in ['kaldi_fbank', 'kaldi_mfcc']:\n            return self.keys[idx], record['feat'], record['label']\n        else:\n            return np.array(record['feat']).transpose(), np.array(\n                record['label'], dtype=np.int64)\n\n    def __len__(self):\n        return len(self.files)\n"
  },
  {
    "path": "audio/paddleaudio/datasets/esc50.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport os\nfrom typing import List\nfrom typing import Tuple\n\nfrom ..utils.download import download_and_decompress\nfrom ..utils.env import DATA_HOME\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['ESC50']\n\n\nclass ESC50(AudioClassificationDataset):\n    \"\"\"\n    The ESC-50 dataset is a labeled collection of 2000 environmental audio recordings\n    suitable for benchmarking methods of environmental sound classification. The dataset\n    consists of 5-second-long recordings organized into 50 semantical classes (with\n    40 examples per class)\n\n    Reference:\n        ESC: Dataset for Environmental Sound Classification\n        http://dx.doi.org/10.1145/2733373.2806390\n    \"\"\"\n\n    archives = [\n        {\n            'url':\n            'https://paddleaudio.bj.bcebos.com/datasets/ESC-50-master.zip',\n            'md5': '7771e4b9d86d0945acce719c7a59305a',\n        },\n    ]\n    label_list = [\n        # Animals\n        'Dog',\n        'Rooster',\n        'Pig',\n        'Cow',\n        'Frog',\n        'Cat',\n        'Hen',\n        'Insects (flying)',\n        'Sheep',\n        'Crow',\n        # Natural soundscapes & water sounds\n        'Rain',\n        'Sea waves',\n        'Crackling fire',\n        'Crickets',\n        'Chirping birds',\n        'Water drops',\n        'Wind',\n        'Pouring water',\n        'Toilet flush',\n        'Thunderstorm',\n        # Human, non-speech sounds\n        'Crying baby',\n        'Sneezing',\n        'Clapping',\n        'Breathing',\n        'Coughing',\n        'Footsteps',\n        'Laughing',\n        'Brushing teeth',\n        'Snoring',\n        'Drinking, sipping',\n        # Interior/domestic sounds\n        'Door knock',\n        'Mouse click',\n        'Keyboard typing',\n        'Door, wood creaks',\n        'Can opening',\n        'Washing machine',\n        'Vacuum cleaner',\n        'Clock alarm',\n        'Clock tick',\n        'Glass breaking',\n        # Exterior/urban noises\n        'Helicopter',\n        'Chainsaw',\n        'Siren',\n        'Car horn',\n        'Engine',\n        'Train',\n        'Church bells',\n        'Airplane',\n        'Fireworks',\n        'Hand saw',\n    ]\n    meta = os.path.join('ESC-50-master', 'meta', 'esc50.csv')\n    meta_info = collections.namedtuple(\n        'META_INFO',\n        ('filename', 'fold', 'target', 'category', 'esc10', 'src_file', 'take'))\n    audio_path = os.path.join('ESC-50-master', 'audio')\n\n    def __init__(self,\n                 mode: str='train',\n                 split: int=1,\n                 feat_type: str='raw',\n                 **kwargs):\n        \"\"\"\n        Args:\n            mode (:obj:`str`, `optional`, defaults to `train`):\n                It identifies the dataset mode (train or dev).\n            split (:obj:`int`, `optional`, defaults to 1):\n                It specify the fold of dev dataset.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        files, labels = self._get_data(mode, split)\n        super(ESC50, self).__init__(\n            files=files, labels=labels, feat_type=feat_type, **kwargs)\n\n    def _get_meta_info(self) -> List[collections.namedtuple]:\n        ret = []\n        with open(os.path.join(DATA_HOME, self.meta), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                ret.append(self.meta_info(*line.strip().split(',')))\n        return ret\n\n    def _get_data(self, mode: str, split: int) -> Tuple[List[str], List[int]]:\n        if not os.path.isdir(os.path.join(DATA_HOME, self.audio_path)) or \\\n            not os.path.isfile(os.path.join(DATA_HOME, self.meta)):\n            download_and_decompress(self.archives, DATA_HOME)\n\n        meta_info = self._get_meta_info()\n\n        files = []\n        labels = []\n        for sample in meta_info:\n            filename, fold, target, _, _, _, _ = sample\n            if mode == 'train' and int(fold) != split:\n                files.append(os.path.join(DATA_HOME, self.audio_path, filename))\n                labels.append(int(target))\n\n            if mode != 'train' and int(fold) == split:\n                files.append(os.path.join(DATA_HOME, self.audio_path, filename))\n                labels.append(int(target))\n\n        return files, labels\n"
  },
  {
    "path": "audio/paddleaudio/datasets/gtzan.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport os\nimport random\nfrom typing import List\nfrom typing import Tuple\n\nfrom ..utils.download import download_and_decompress\nfrom ..utils.env import DATA_HOME\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['GTZAN']\n\n\nclass GTZAN(AudioClassificationDataset):\n    \"\"\"\n    The GTZAN dataset consists of 1000 audio tracks each 30 seconds long. It contains 10 genres,\n    each represented by 100 tracks. The dataset is the most-used public dataset for evaluation\n    in machine listening research for music genre recognition (MGR).\n\n    Reference:\n        Musical genre classification of audio signals\n        https://ieeexplore.ieee.org/document/1021072/\n    \"\"\"\n\n    archives = [\n        {\n            'url': 'http://opihi.cs.uvic.ca/sound/genres.tar.gz',\n            'md5': '5b3d6dddb579ab49814ab86dba69e7c7',\n        },\n    ]\n    label_list = [\n        'blues', 'classical', 'country', 'disco', 'hiphop', 'jazz', 'metal',\n        'pop', 'reggae', 'rock'\n    ]\n    meta = os.path.join('genres', 'input.mf')\n    meta_info = collections.namedtuple('META_INFO', ('file_path', 'label'))\n    audio_path = 'genres'\n\n    def __init__(self,\n                 mode='train',\n                 seed=0,\n                 n_folds=5,\n                 split=1,\n                 feat_type='raw',\n                 **kwargs):\n        \"\"\"\n        Args:\n            mode (:obj:`str`, `optional`, defaults to `train`):\n                It identifies the dataset mode (train or dev).\n            seed (:obj:`int`, `optional`, defaults to 0):\n                Set the random seed to shuffle samples.\n            n_folds (:obj:`int`, `optional`, defaults to 5):\n                Split the dataset into n folds. 1 fold for dev dataset and n-1 for train dataset.\n            split (:obj:`int`, `optional`, defaults to 1):\n                It specify the fold of dev dataset.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        assert split <= n_folds, f'The selected split should not be larger than n_fold, but got {split} > {n_folds}'\n        files, labels = self._get_data(mode, seed, n_folds, split)\n        super(GTZAN, self).__init__(\n            files=files, labels=labels, feat_type=feat_type, **kwargs)\n\n    def _get_meta_info(self) -> List[collections.namedtuple]:\n        ret = []\n        with open(os.path.join(DATA_HOME, self.meta), 'r') as rf:\n            for line in rf.readlines():\n                ret.append(self.meta_info(*line.strip().split('\\t')))\n        return ret\n\n    def _get_data(self, mode, seed, n_folds,\n                  split) -> Tuple[List[str], List[int]]:\n        if not os.path.isdir(os.path.join(DATA_HOME, self.audio_path)) or \\\n            not os.path.isfile(os.path.join(DATA_HOME, self.meta)):\n            download_and_decompress(self.archives, DATA_HOME)\n\n        meta_info = self._get_meta_info()\n        random.seed(seed)  # shuffle samples to split data\n        random.shuffle(\n            meta_info\n        )  # make sure using the same seed to create train and dev dataset\n\n        files = []\n        labels = []\n        n_samples_per_fold = len(meta_info) // n_folds\n        for idx, sample in enumerate(meta_info):\n            file_path, label = sample\n            filename = os.path.basename(file_path)\n            target = self.label_list.index(label)\n            fold = idx // n_samples_per_fold + 1\n\n            if mode == 'train' and int(fold) != split:\n                files.append(\n                    os.path.join(DATA_HOME, self.audio_path, label, filename))\n                labels.append(target)\n\n            if mode != 'train' and int(fold) == split:\n                files.append(\n                    os.path.join(DATA_HOME, self.audio_path, label, filename))\n                labels.append(target)\n\n        return files, labels\n"
  },
  {
    "path": "audio/paddleaudio/datasets/hey_snips.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport json\nimport os\nfrom typing import List\nfrom typing import Tuple\n\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['HeySnips']\n\n\nclass HeySnips(AudioClassificationDataset):\n    meta_info = collections.namedtuple('META_INFO',\n                                       ('key', 'label', 'duration', 'wav'))\n\n    def __init__(self,\n                 data_dir: os.PathLike,\n                 mode: str='train',\n                 feat_type: str='kaldi_fbank',\n                 sample_rate: int=16000,\n                 **kwargs):\n        self.data_dir = data_dir\n        files, labels = self._get_data(mode)\n        super(HeySnips, self).__init__(\n            files=files,\n            labels=labels,\n            feat_type=feat_type,\n            sample_rate=sample_rate,\n            **kwargs)\n\n    def _get_meta_info(self, mode) -> List[collections.namedtuple]:\n        ret = []\n        with open(os.path.join(self.data_dir, '{}.json'.format(mode)),\n                  'r') as f:\n            data = json.load(f)\n            for item in data:\n                sample = collections.OrderedDict()\n                if item['duration'] > 0:\n                    sample['key'] = item['id']\n                    sample['label'] = 0 if item['is_hotword'] == 1 else -1\n                    sample['duration'] = item['duration']\n                    sample['wav'] = os.path.join(self.data_dir,\n                                                 item['audio_file_path'])\n                    ret.append(self.meta_info(*sample.values()))\n        return ret\n\n    def _get_data(self, mode: str) -> Tuple[List[str], List[int]]:\n        meta_info = self._get_meta_info(mode)\n\n        files = []\n        labels = []\n        self.keys = []\n        self.durations = []\n        for sample in meta_info:\n            key, target, duration, wav = sample\n            files.append(wav)\n            labels.append(int(target))\n            self.keys.append(key)\n            self.durations.append(float(duration))\n\n        return files, labels\n"
  },
  {
    "path": "audio/paddleaudio/datasets/rirs_noises.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport csv\nimport os\nimport random\nfrom typing import List\n\nfrom paddle.io import Dataset\nfrom tqdm import tqdm\n\nfrom ..backends.soundfile_backend import soundfile_load as load_audio\nfrom ..backends.soundfile_backend import soundfile_save as save_wav\nfrom ..utils import DATA_HOME\nfrom ..utils.download import download_and_decompress\nfrom .dataset import feat_funcs\n\n__all__ = ['OpenRIRNoise']\n\n\nclass OpenRIRNoise(Dataset):\n    archives = [\n        {\n            'url': 'http://www.openslr.org/resources/28/rirs_noises.zip',\n            'md5': 'e6f48e257286e05de56413b4779d8ffb',\n        },\n    ]\n\n    sample_rate = 16000\n    meta_info = collections.namedtuple('META_INFO', ('id', 'duration', 'wav'))\n    base_path = os.path.join(DATA_HOME, 'open_rir_noise')\n    wav_path = os.path.join(base_path, 'RIRS_NOISES')\n    csv_path = os.path.join(base_path, 'csv')\n    subsets = ['rir', 'noise']\n\n    def __init__(self,\n                 subset: str='rir',\n                 feat_type: str='raw',\n                 target_dir=None,\n                 random_chunk: bool=True,\n                 chunk_duration: float=3.0,\n                 seed: int=0,\n                 **kwargs):\n\n        assert subset in self.subsets, \\\n            'Dataset subset must be one in {}, but got {}'.format(self.subsets, subset)\n\n        self.subset = subset\n        self.feat_type = feat_type\n        self.feat_config = kwargs\n        self.random_chunk = random_chunk\n        self.chunk_duration = chunk_duration\n\n        OpenRIRNoise.csv_path = os.path.join(\n            target_dir, \"open_rir_noise\",\n            \"csv\") if target_dir else self.csv_path\n        self._data = self._get_data()\n        super(OpenRIRNoise, self).__init__()\n\n        # Set up a seed to reproduce training or predicting result.\n        # random.seed(seed)\n\n    def _get_data(self):\n        # Download audio files.\n        print(f\"rirs noises base path: {self.base_path}\")\n        if not os.path.isdir(self.base_path):\n            download_and_decompress(\n                self.archives, self.base_path, decompress=True)\n        else:\n            print(\n                f\"{self.base_path} already exists, we will not download and decompress again\"\n            )\n\n        # Data preparation.\n        print(f\"prepare the csv to {self.csv_path}\")\n        if not os.path.isdir(self.csv_path):\n            os.makedirs(self.csv_path)\n            self.prepare_data()\n\n        data = []\n        with open(os.path.join(self.csv_path, f'{self.subset}.csv'), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                audio_id, duration, wav = line.strip().split(',')\n                data.append(self.meta_info(audio_id, float(duration), wav))\n\n        random.shuffle(data)\n        return data\n\n    def _convert_to_record(self, idx: int):\n        sample = self._data[idx]\n\n        record = {}\n        # To show all fields in a namedtuple: `type(sample)._fields`\n        for field in type(sample)._fields:\n            record[field] = getattr(sample, field)\n\n        waveform, sr = load_audio(record['wav'])\n\n        assert self.feat_type in feat_funcs.keys(), \\\n            f\"Unknown feat_type: {self.feat_type}, it must be one in {list(feat_funcs.keys())}\"\n        feat_func = feat_funcs[self.feat_type]\n        feat = feat_func(\n            waveform, sr=sr, **self.feat_config) if feat_func else waveform\n\n        record.update({'feat': feat})\n        return record\n\n    @staticmethod\n    def _get_chunks(seg_dur, audio_id, audio_duration):\n        num_chunks = int(audio_duration / seg_dur)  # all in milliseconds\n\n        chunk_lst = [\n            audio_id + \"_\" + str(i * seg_dur) + \"_\" + str(i * seg_dur + seg_dur)\n            for i in range(num_chunks)\n        ]\n        return chunk_lst\n\n    def _get_audio_info(self, wav_file: str,\n                        split_chunks: bool) -> List[List[str]]:\n        waveform, sr = load_audio(wav_file)\n        audio_id = wav_file.split(\"/open_rir_noise/\")[-1].split(\".\")[0]\n        audio_duration = waveform.shape[0] / sr\n\n        ret = []\n        if split_chunks and audio_duration > self.chunk_duration:  # Split into pieces of self.chunk_duration seconds.\n            uniq_chunks_list = self._get_chunks(self.chunk_duration, audio_id,\n                                                audio_duration)\n\n            for idx, chunk in enumerate(uniq_chunks_list):\n                s, e = chunk.split(\"_\")[-2:]  # Timestamps of start and end\n                start_sample = int(float(s) * sr)\n                end_sample = int(float(e) * sr)\n                new_wav_file = os.path.join(self.base_path,\n                                            audio_id + f'_chunk_{idx+1:02}.wav')\n                save_wav(waveform[start_sample:end_sample], sr, new_wav_file)\n                # id, duration, new_wav\n                ret.append([chunk, self.chunk_duration, new_wav_file])\n        else:  # Keep whole audio.\n            ret.append([audio_id, audio_duration, wav_file])\n        return ret\n\n    def generate_csv(self,\n                     wav_files: List[str],\n                     output_file: str,\n                     split_chunks: bool=True):\n        print(f'Generating csv: {output_file}')\n        header = [\"id\", \"duration\", \"wav\"]\n\n        infos = list(\n            tqdm(\n                map(self._get_audio_info, wav_files, [split_chunks] * len(\n                    wav_files)),\n                total=len(wav_files)))\n\n        csv_lines = []\n        for info in infos:\n            csv_lines.extend(info)\n\n        with open(output_file, mode=\"w\") as csv_f:\n            csv_writer = csv.writer(\n                csv_f, delimiter=\",\", quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            csv_writer.writerow(header)\n            for line in csv_lines:\n                csv_writer.writerow(line)\n\n    def prepare_data(self):\n        rir_list = os.path.join(self.wav_path, \"real_rirs_isotropic_noises\",\n                                \"rir_list\")\n        rir_files = []\n        with open(rir_list, 'r') as f:\n            for line in f.readlines():\n                rir_file = line.strip().split(' ')[-1]\n                rir_files.append(os.path.join(self.base_path, rir_file))\n\n        noise_list = os.path.join(self.wav_path, \"pointsource_noises\",\n                                  \"noise_list\")\n        noise_files = []\n        with open(noise_list, 'r') as f:\n            for line in f.readlines():\n                noise_file = line.strip().split(' ')[-1]\n                noise_files.append(os.path.join(self.base_path, noise_file))\n\n        self.generate_csv(rir_files, os.path.join(self.csv_path, 'rir.csv'))\n        self.generate_csv(noise_files, os.path.join(self.csv_path, 'noise.csv'))\n\n    def __getitem__(self, idx):\n        return self._convert_to_record(idx)\n\n    def __len__(self):\n        return len(self._data)\n"
  },
  {
    "path": "audio/paddleaudio/datasets/tess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport os\nimport random\nfrom typing import List\nfrom typing import Tuple\n\nfrom ..utils.download import download_and_decompress\nfrom ..utils.env import DATA_HOME\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['TESS']\n\n\nclass TESS(AudioClassificationDataset):\n    \"\"\"\n    TESS is a set of 200 target words were spoken in the carrier phrase\n    \"Say the word _____' by two actresses (aged 26 and 64 years) and\n    recordings were made of the set portraying each of seven emotions(anger,\n    disgust, fear, happiness, pleasant surprise, sadness, and neutral).\n    There are 2800 stimuli in total.\n\n    Reference:\n        Toronto emotional speech set (TESS)\n        https://doi.org/10.5683/SP2/E8H2MF\n    \"\"\"\n\n    archives = [\n        {\n            'url':\n            'https://bj.bcebos.com/paddleaudio/datasets/TESS_Toronto_emotional_speech_set.zip',\n            'md5':\n            '1465311b24d1de704c4c63e4ccc470c7',\n        },\n    ]\n    label_list = [\n        'angry',\n        'disgust',\n        'fear',\n        'happy',\n        'neutral',\n        'ps',  # pleasant surprise\n        'sad',\n    ]\n    meta_info = collections.namedtuple('META_INFO',\n                                       ('speaker', 'word', 'emotion'))\n    audio_path = 'TESS_Toronto_emotional_speech_set'\n\n    def __init__(self,\n                 mode='train',\n                 seed=0,\n                 n_folds=5,\n                 split=1,\n                 feat_type='raw',\n                 **kwargs):\n        \"\"\"\n        Args:\n            mode (:obj:`str`, `optional`, defaults to `train`):\n                It identifies the dataset mode (train or dev).\n            seed (:obj:`int`, `optional`, defaults to 0):\n                Set the random seed to shuffle samples.\n            n_folds (:obj:`int`, `optional`, defaults to 5):\n                Split the dataset into n folds. 1 fold for dev dataset and n-1 for train dataset.\n            split (:obj:`int`, `optional`, defaults to 1):\n                It specify the fold of dev dataset.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        assert split <= n_folds, f'The selected split should not be larger than n_fold, but got {split} > {n_folds}'\n        files, labels = self._get_data(mode, seed, n_folds, split)\n        super(TESS, self).__init__(\n            files=files, labels=labels, feat_type=feat_type, **kwargs)\n\n    def _get_meta_info(self, files) -> List[collections.namedtuple]:\n        ret = []\n        for file in files:\n            basename_without_extend = os.path.basename(file)[:-4]\n            ret.append(self.meta_info(*basename_without_extend.split('_')))\n        return ret\n\n    def _get_data(self, mode, seed, n_folds,\n                  split) -> Tuple[List[str], List[int]]:\n        if not os.path.isdir(os.path.join(DATA_HOME, self.audio_path)):\n            download_and_decompress(self.archives, DATA_HOME)\n\n        wav_files = []\n        for root, _, files in os.walk(os.path.join(DATA_HOME, self.audio_path)):\n            for file in files:\n                if file.endswith('.wav'):\n                    wav_files.append(os.path.join(root, file))\n\n        random.seed(seed)  # shuffle samples to split data\n        random.shuffle(\n            wav_files\n        )  # make sure using the same seed to create train and dev dataset\n        meta_info = self._get_meta_info(wav_files)\n\n        files = []\n        labels = []\n        n_samples_per_fold = len(meta_info) // n_folds\n        for idx, sample in enumerate(meta_info):\n            _, _, emotion = sample\n            target = self.label_list.index(emotion)\n            fold = idx // n_samples_per_fold + 1\n\n            if mode == 'train' and int(fold) != split:\n                files.append(wav_files[idx])\n                labels.append(target)\n\n            if mode != 'train' and int(fold) == split:\n                files.append(wav_files[idx])\n                labels.append(target)\n\n        return files, labels\n"
  },
  {
    "path": "audio/paddleaudio/datasets/urban_sound.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport os\nfrom typing import List\nfrom typing import Tuple\n\nfrom ..utils.download import download_and_decompress\nfrom ..utils.env import DATA_HOME\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['UrbanSound8K']\n\n\nclass UrbanSound8K(AudioClassificationDataset):\n    \"\"\"\n    UrbanSound8K dataset contains 8732 labeled sound excerpts (<=4s) of urban\n    sounds from 10 classes: air_conditioner, car_horn, children_playing, dog_bark,\n    drilling, enginge_idling, gun_shot, jackhammer, siren, and street_music. The\n    classes are drawn from the urban sound taxonomy.\n\n    Reference:\n        A Dataset and Taxonomy for Urban Sound Research\n        https://dl.acm.org/doi/10.1145/2647868.2655045\n    \"\"\"\n\n    archives = [\n        {\n            'url':\n            'https://zenodo.org/record/1203745/files/UrbanSound8K.tar.gz',\n            'md5': '9aa69802bbf37fb986f71ec1483a196e',\n        },\n    ]\n    label_list = [\n        \"air_conditioner\", \"car_horn\", \"children_playing\", \"dog_bark\",\n        \"drilling\", \"engine_idling\", \"gun_shot\", \"jackhammer\", \"siren\",\n        \"street_music\"\n    ]\n    meta = os.path.join('UrbanSound8K', 'metadata', 'UrbanSound8K.csv')\n    meta_info = collections.namedtuple(\n        'META_INFO', ('filename', 'fsid', 'start', 'end', 'salience', 'fold',\n                      'class_id', 'label'))\n    audio_path = os.path.join('UrbanSound8K', 'audio')\n\n    def __init__(self,\n                 mode: str='train',\n                 split: int=1,\n                 feat_type: str='raw',\n                 **kwargs):\n        files, labels = self._get_data(mode, split)\n        super(UrbanSound8K, self).__init__(\n            files=files, labels=labels, feat_type=feat_type, **kwargs)\n        \"\"\"\n        Args:\n            mode (:obj:`str`, `optional`, defaults to `train`):\n                It identifies the dataset mode (train or dev).\n            split (:obj:`int`, `optional`, defaults to 1):\n                It specify the fold of dev dataset.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n\n    def _get_meta_info(self):\n        ret = []\n        with open(os.path.join(DATA_HOME, self.meta), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                ret.append(self.meta_info(*line.strip().split(',')))\n        return ret\n\n    def _get_data(self, mode: str, split: int) -> Tuple[List[str], List[int]]:\n        if not os.path.isdir(os.path.join(DATA_HOME, self.audio_path)) or \\\n            not os.path.isfile(os.path.join(DATA_HOME, self.meta)):\n            download_and_decompress(self.archives, DATA_HOME)\n\n        meta_info = self._get_meta_info()\n\n        files = []\n        labels = []\n        for sample in meta_info:\n            filename, _, _, _, _, fold, target, _ = sample\n            if mode == 'train' and int(fold) != split:\n                files.append(\n                    os.path.join(DATA_HOME, self.audio_path, f'fold{fold}',\n                                 filename))\n                labels.append(int(target))\n\n            if mode != 'train' and int(fold) == split:\n                files.append(\n                    os.path.join(DATA_HOME, self.audio_path, f'fold{fold}',\n                                 filename))\n                labels.append(int(target))\n\n        return files, labels\n"
  },
  {
    "path": "audio/paddleaudio/datasets/voxceleb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport csv\nimport glob\nimport os\nimport random\nfrom multiprocessing import cpu_count\nfrom typing import List\n\nfrom paddle.io import Dataset\nfrom pathos.multiprocessing import Pool\nfrom tqdm import tqdm\n\nfrom ..backends.soundfile_backend import soundfile_load as load_audio\nfrom ..utils import DATA_HOME\nfrom ..utils import decompress\nfrom ..utils.download import download_and_decompress\nfrom .dataset import feat_funcs\n\n__all__ = ['VoxCeleb']\n\n\nclass VoxCeleb(Dataset):\n    source_url = 'https://thor.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a/'\n    archives_audio_dev = [\n        {\n            'url': source_url + 'vox1_dev_wav_partaa',\n            'md5': 'e395d020928bc15670b570a21695ed96',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partab',\n            'md5': 'bbfaaccefab65d82b21903e81a8a8020',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partac',\n            'md5': '017d579a2a96a077f40042ec33e51512',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partad',\n            'md5': '7bb1e9f70fddc7a678fa998ea8b3ba19',\n        },\n    ]\n    archives_audio_test = [\n        {\n            'url': source_url + 'vox1_test_wav.zip',\n            'md5': '185fdc63c3c739954633d50379a3d102',\n        },\n    ]\n    archives_meta = [\n        {\n            'url':\n            'https://www.robots.ox.ac.uk/~vgg/data/voxceleb/meta/veri_test2.txt',\n            'md5':\n            'b73110731c9223c1461fe49cb48dddfc',\n        },\n    ]\n\n    num_speakers = 1211  # 1211 vox1, 5994 vox2, 7205 vox1+2, test speakers: 41\n    sample_rate = 16000\n    meta_info = collections.namedtuple(\n        'META_INFO', ('id', 'duration', 'wav', 'start', 'stop', 'spk_id'))\n    base_path = os.path.join(DATA_HOME, 'vox1')\n    wav_path = os.path.join(base_path, 'wav')\n    meta_path = os.path.join(base_path, 'meta')\n    veri_test_file = os.path.join(meta_path, 'veri_test2.txt')\n    csv_path = os.path.join(base_path, 'csv')\n    subsets = ['train', 'dev', 'enroll', 'test']\n\n    def __init__(\n            self,\n            subset: str='train',\n            feat_type: str='raw',\n            random_chunk: bool=True,\n            chunk_duration: float=3.0,  # seconds\n            split_ratio: float=0.9,  # train split ratio\n            seed: int=0,\n            target_dir: str=None,\n            vox2_base_path=None,\n            **kwargs):\n        \"\"\"VoxCeleb data prepare and get the specific dataset audio info\n\n        Args:\n            subset (str, optional): dataset name, such as train, dev, enroll or test. Defaults to 'train'.\n            feat_type (str, optional): feat type, such raw, melspectrogram(fbank) or mfcc . Defaults to 'raw'.\n            random_chunk (bool, optional): random select a duration from audio. Defaults to True.\n            chunk_duration (float, optional): chunk duration if random_chunk flag is set. Defaults to 3.0.\n            target_dir (str, optional): data dir, audio info will be stored in this directory. Defaults to None.\n            vox2_base_path (_type_, optional): vox2 directory. vox2 data must be converted from m4a to wav. Defaults to None.\n        \"\"\"\n        assert subset in self.subsets, \\\n            'Dataset subset must be one in {}, but got {}'.format(self.subsets, subset)\n\n        self.subset = subset\n        self.spk_id2label = {}\n        self.feat_type = feat_type\n        self.feat_config = kwargs\n        self.random_chunk = random_chunk\n        self.chunk_duration = chunk_duration\n        self.split_ratio = split_ratio\n        self.target_dir = target_dir if target_dir else VoxCeleb.base_path\n        self.vox2_base_path = vox2_base_path\n\n        # if we set the target dir, we will change the vox data info data from base path to target dir\n        VoxCeleb.csv_path = os.path.join(\n            target_dir, \"voxceleb\", 'csv') if target_dir else VoxCeleb.csv_path\n        VoxCeleb.meta_path = os.path.join(\n            target_dir, \"voxceleb\",\n            'meta') if target_dir else VoxCeleb.meta_path\n        VoxCeleb.veri_test_file = os.path.join(VoxCeleb.meta_path,\n                                               'veri_test2.txt')\n        # self._data = self._get_data()[:1000]  # KP: Small dataset test.\n        self._data = self._get_data()\n        super(VoxCeleb, self).__init__()\n\n        # Set up a seed to reproduce training or predicting result.\n        # random.seed(seed)\n\n    def _get_data(self):\n        # Download audio files.\n        # We need the users to decompress all vox1/dev/wav and vox1/test/wav/ to vox1/wav/ dir\n        # so, we check the vox1/wav dir status\n        print(f\"wav base path: {self.wav_path}\")\n        if not os.path.isdir(self.wav_path):\n            print(\"start to download the voxceleb1 dataset\")\n            download_and_decompress(  # multi-zip parts concatenate to vox1_dev_wav.zip\n                self.archives_audio_dev,\n                self.base_path,\n                decompress=False)\n            download_and_decompress(  # download the vox1_test_wav.zip and unzip\n                self.archives_audio_test,\n                self.base_path,\n                decompress=True)\n\n            # Download all parts and concatenate the files into one zip file.\n            dev_zipfile = os.path.join(self.base_path, 'vox1_dev_wav.zip')\n            print(f'Concatenating all parts to: {dev_zipfile}')\n            os.system(\n                f'cat {os.path.join(self.base_path, \"vox1_dev_wav_parta*\")} > {dev_zipfile}'\n            )\n\n            # Extract all audio files of dev and test set.\n            decompress(dev_zipfile, self.base_path)\n\n        # Download meta files.\n        if not os.path.isdir(self.meta_path):\n            print(\"prepare the meta data\")\n            download_and_decompress(\n                self.archives_meta, self.meta_path, decompress=False)\n\n        # Data preparation.\n        if not os.path.isdir(self.csv_path):\n            os.makedirs(self.csv_path)\n            self.prepare_data()\n\n        data = []\n        print(\n            f\"read the {self.subset} from {os.path.join(self.csv_path, f'{self.subset}.csv')}\"\n        )\n        with open(os.path.join(self.csv_path, f'{self.subset}.csv'), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                audio_id, duration, wav, start, stop, spk_id = line.strip(\n                ).split(',')\n                data.append(\n                    self.meta_info(audio_id,\n                                   float(duration), wav,\n                                   int(start), int(stop), spk_id))\n\n        with open(os.path.join(self.meta_path, 'spk_id2label.txt'), 'r') as f:\n            for line in f.readlines():\n                spk_id, label = line.strip().split(' ')\n                self.spk_id2label[spk_id] = int(label)\n\n        return data\n\n    def _convert_to_record(self, idx: int):\n        sample = self._data[idx]\n\n        record = {}\n        # To show all fields in a namedtuple: `type(sample)._fields`\n        for field in type(sample)._fields:\n            record[field] = getattr(sample, field)\n\n        waveform, sr = load_audio(record['wav'])\n\n        # random select a chunk audio samples from the audio\n        if self.random_chunk:\n            num_wav_samples = waveform.shape[0]\n            num_chunk_samples = int(self.chunk_duration * sr)\n            start = random.randint(0, num_wav_samples - num_chunk_samples - 1)\n            stop = start + num_chunk_samples\n        else:\n            start = record['start']\n            stop = record['stop']\n\n        waveform = waveform[start:stop]\n\n        assert self.feat_type in feat_funcs.keys(), \\\n            f\"Unknown feat_type: {self.feat_type}, it must be one in {list(feat_funcs.keys())}\"\n        feat_func = feat_funcs[self.feat_type]\n        feat = feat_func(\n            waveform, sr=sr, **self.feat_config) if feat_func else waveform\n\n        record.update({'feat': feat})\n        if self.subset in ['train',\n                           'dev']:  # Labels are available in train and dev.\n            record.update({'label': self.spk_id2label[record['spk_id']]})\n\n        return record\n\n    @staticmethod\n    def _get_chunks(seg_dur, audio_id, audio_duration):\n        num_chunks = int(audio_duration / seg_dur)  # all in milliseconds\n\n        chunk_lst = [\n            audio_id + \"_\" + str(i * seg_dur) + \"_\" + str(i * seg_dur + seg_dur)\n            for i in range(num_chunks)\n        ]\n        return chunk_lst\n\n    def _get_audio_info(self, wav_file: str,\n                        split_chunks: bool) -> List[List[str]]:\n        waveform, sr = load_audio(wav_file)\n        spk_id, sess_id, utt_id = wav_file.split(\"/\")[-3:]\n        audio_id = '-'.join([spk_id, sess_id, utt_id.split(\".\")[0]])\n        audio_duration = waveform.shape[0] / sr\n\n        ret = []\n        if split_chunks:  # Split into pieces of self.chunk_duration seconds.\n            uniq_chunks_list = self._get_chunks(self.chunk_duration, audio_id,\n                                                audio_duration)\n\n            for chunk in uniq_chunks_list:\n                s, e = chunk.split(\"_\")[-2:]  # Timestamps of start and end\n                start_sample = int(float(s) * sr)\n                end_sample = int(float(e) * sr)\n                # id, duration, wav, start, stop, spk_id\n                ret.append([\n                    chunk, audio_duration, wav_file, start_sample, end_sample,\n                    spk_id\n                ])\n        else:  # Keep whole audio.\n            ret.append([\n                audio_id, audio_duration, wav_file, 0, waveform.shape[0], spk_id\n            ])\n        return ret\n\n    def generate_csv(self,\n                     wav_files: List[str],\n                     output_file: str,\n                     split_chunks: bool=True):\n        print(f'Generating csv: {output_file}')\n        header = [\"id\", \"duration\", \"wav\", \"start\", \"stop\", \"spk_id\"]\n        # Note: this may occurs c++ exception, but the program will execute fine\n        # so we can ignore the exception \n        with Pool(cpu_count()) as p:\n            infos = list(\n                tqdm(\n                    p.imap(lambda x: self._get_audio_info(x, split_chunks),\n                           wav_files),\n                    total=len(wav_files)))\n\n        csv_lines = []\n        for info in infos:\n            csv_lines.extend(info)\n\n        with open(output_file, mode=\"w\") as csv_f:\n            csv_writer = csv.writer(\n                csv_f, delimiter=\",\", quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            csv_writer.writerow(header)\n            for line in csv_lines:\n                csv_writer.writerow(line)\n\n    def prepare_data(self):\n        # Audio of speakers in veri_test_file should not be included in training set.\n        print(\"start to prepare the data csv file\")\n        enroll_files = set()\n        test_files = set()\n        # get the enroll and test audio file path\n        with open(self.veri_test_file, 'r') as f:\n            for line in f.readlines():\n                _, enrol_file, test_file = line.strip().split(' ')\n                enroll_files.add(os.path.join(self.wav_path, enrol_file))\n                test_files.add(os.path.join(self.wav_path, test_file))\n            enroll_files = sorted(enroll_files)\n            test_files = sorted(test_files)\n\n        # get the enroll and test speakers\n        test_spks = set()\n        for file in (enroll_files + test_files):\n            spk = file.split('/wav/')[1].split('/')[0]\n            test_spks.add(spk)\n\n        # get all the train and dev audios file path\n        audio_files = []\n        speakers = set()\n        print(\"Getting file list...\")\n        for path in [self.wav_path, self.vox2_base_path]:\n            # if vox2 directory is not set and vox2 is not a directory \n            # we will not process this directory\n            if not path or not os.path.exists(path):\n                print(f\"{path} is an invalid path, please check again, \"\n                      \"and we will ignore the vox2 base path\")\n                continue\n            for file in glob.glob(\n                    os.path.join(path, \"**\", \"*.wav\"), recursive=True):\n                spk = file.split('/wav/')[1].split('/')[0]\n                if spk in test_spks:\n                    continue\n                speakers.add(spk)\n                audio_files.append(file)\n\n        print(\n            f\"start to generate the {os.path.join(self.meta_path, 'spk_id2label.txt')}\"\n        )\n        # encode the train and dev speakers label to spk_id2label.txt\n        with open(os.path.join(self.meta_path, 'spk_id2label.txt'), 'w') as f:\n            for label, spk_id in enumerate(\n                    sorted(speakers)):  # 1211 vox1, 5994 vox2, 7205 vox1+2\n                f.write(f'{spk_id} {label}\\n')\n\n        audio_files = sorted(audio_files)\n        random.shuffle(audio_files)\n        split_idx = int(self.split_ratio * len(audio_files))\n        # split_ratio to train\n        train_files, dev_files = audio_files[:split_idx], audio_files[\n            split_idx:]\n\n        self.generate_csv(train_files, os.path.join(self.csv_path, 'train.csv'))\n        self.generate_csv(dev_files, os.path.join(self.csv_path, 'dev.csv'))\n\n        self.generate_csv(\n            enroll_files,\n            os.path.join(self.csv_path, 'enroll.csv'),\n            split_chunks=False)\n        self.generate_csv(\n            test_files,\n            os.path.join(self.csv_path, 'test.csv'),\n            split_chunks=False)\n\n    def __getitem__(self, idx):\n        return self._convert_to_record(idx)\n\n    def __len__(self):\n        return len(self._data)\n"
  },
  {
    "path": "audio/paddleaudio/features/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .layers import LogMelSpectrogram\nfrom .layers import MelSpectrogram\nfrom .layers import MFCC\nfrom .layers import Spectrogram\n"
  },
  {
    "path": "audio/paddleaudio/features/layers.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom functools import partial\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nimport paddle.nn as nn\nfrom paddle import Tensor\n\nfrom ..functional import compute_fbank_matrix\nfrom ..functional import create_dct\nfrom ..functional import power_to_db\nfrom ..functional.window import get_window\n\n__all__ = [\n    'Spectrogram',\n    'MelSpectrogram',\n    'LogMelSpectrogram',\n    'MFCC',\n]\n\n\nclass Spectrogram(nn.Layer):\n    \"\"\"Compute spectrogram of given signals, typically audio waveforms.\n    The spectrogram is defined as the complex norm of the short-time Fourier transformation.\n\n    Args:\n        n_fft (int, optional): The number of frequency components of the discrete Fourier transform. Defaults to 512.\n        hop_length (Optional[int], optional): The hop length of the short time FFT. If `None`, it is set to `win_length//4`. Defaults to None.\n        win_length (Optional[int], optional): The window length of the short time FFT. If `None`, it is set to same as `n_fft`. Defaults to None.\n        window (str, optional): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'kaiser', 'gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'. Defaults to 'hann'.\n        power (float, optional): Exponent for the magnitude spectrogram. Defaults to 2.0.\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to 'reflect'.\n        dtype (str, optional): Data type of input and window. Defaults to 'float32'.\n    \"\"\"\n\n    def __init__(self,\n                 n_fft: int=512,\n                 hop_length: Optional[int]=None,\n                 win_length: Optional[int]=None,\n                 window: str='hann',\n                 power: float=2.0,\n                 center: bool=True,\n                 pad_mode: str='reflect',\n                 dtype: str='float32') -> None:\n        super(Spectrogram, self).__init__()\n\n        assert power > 0, 'Power of spectrogram must be > 0.'\n        self.power = power\n\n        if win_length is None:\n            win_length = n_fft\n\n        self.fft_window = get_window(\n            window, win_length, fftbins=True, dtype=dtype)\n        self._stft = partial(\n            paddle.signal.stft,\n            n_fft=n_fft,\n            hop_length=hop_length,\n            win_length=win_length,\n            window=self.fft_window,\n            center=center,\n            pad_mode=pad_mode)\n        self.register_buffer('fft_window', self.fft_window)\n\n    def forward(self, x: Tensor) -> Tensor:\n        \"\"\"\n        Args:\n            x (Tensor): Tensor of waveforms with shape `(N, T)`\n\n        Returns:\n            Tensor: Spectrograms with shape `(N, n_fft//2 + 1, num_frames)`.\n        \"\"\"\n        stft = self._stft(x)\n        spectrogram = paddle.pow(paddle.abs(stft), self.power)\n        return spectrogram\n\n\nclass MelSpectrogram(nn.Layer):\n    \"\"\"Compute the melspectrogram of given signals, typically audio waveforms. It is computed by multiplying spectrogram with Mel filter bank matrix.\n\n    Args:\n        sr (int, optional): Sample rate. Defaults to 22050.\n        n_fft (int, optional): The number of frequency components of the discrete Fourier transform. Defaults to 512.\n        hop_length (Optional[int], optional): The hop length of the short time FFT. If `None`, it is set to `win_length//4`. Defaults to None.\n        win_length (Optional[int], optional): The window length of the short time FFT. If `None`, it is set to same as `n_fft`. Defaults to None.\n        window (str, optional): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'kaiser', 'gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'. Defaults to 'hann'.\n        power (float, optional): Exponent for the magnitude spectrogram. Defaults to 2.0.\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to 'reflect'.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 50.0.\n        f_max (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use HTK formula in computing fbank matrix. Defaults to False.\n        norm (Union[str, float], optional): Type of normalization in computing fbank matrix. Slaney-style is used by default. You can specify norm=1.0/2.0 to use customized p-norm normalization. Defaults to 'slaney'.\n        dtype (str, optional): Data type of input and window. Defaults to 'float32'.\n    \"\"\"\n\n    def __init__(self,\n                 sr: int=22050,\n                 n_fft: int=512,\n                 hop_length: Optional[int]=None,\n                 win_length: Optional[int]=None,\n                 window: str='hann',\n                 power: float=2.0,\n                 center: bool=True,\n                 pad_mode: str='reflect',\n                 n_mels: int=64,\n                 f_min: float=50.0,\n                 f_max: Optional[float]=None,\n                 htk: bool=False,\n                 norm: Union[str, float]='slaney',\n                 dtype: str='float32') -> None:\n        super(MelSpectrogram, self).__init__()\n\n        self._spectrogram = Spectrogram(\n            n_fft=n_fft,\n            hop_length=hop_length,\n            win_length=win_length,\n            window=window,\n            power=power,\n            center=center,\n            pad_mode=pad_mode,\n            dtype=dtype)\n        self.n_mels = n_mels\n        self.f_min = f_min\n        self.f_max = f_max\n        self.htk = htk\n        self.norm = norm\n        if f_max is None:\n            f_max = sr // 2\n        self.fbank_matrix = compute_fbank_matrix(\n            sr=sr,\n            n_fft=n_fft,\n            n_mels=n_mels,\n            f_min=f_min,\n            f_max=f_max,\n            htk=htk,\n            norm=norm,\n            dtype=dtype)  # float64 for better numerical results\n        self.register_buffer('fbank_matrix', self.fbank_matrix)\n\n    def forward(self, x: Tensor) -> Tensor:\n        \"\"\"\n        Args:\n            x (Tensor): Tensor of waveforms with shape `(N, T)`\n\n        Returns:\n            Tensor: Mel spectrograms with shape `(N, n_mels, num_frames)`.\n        \"\"\"\n        spect_feature = self._spectrogram(x)\n        mel_feature = paddle.matmul(self.fbank_matrix, spect_feature)\n        return mel_feature\n\n\nclass LogMelSpectrogram(nn.Layer):\n    \"\"\"Compute log-mel-spectrogram feature of given signals, typically audio waveforms.\n\n    Args:\n        sr (int, optional): Sample rate. Defaults to 22050.\n        n_fft (int, optional): The number of frequency components of the discrete Fourier transform. Defaults to 512.\n        hop_length (Optional[int], optional): The hop length of the short time FFT. If `None`, it is set to `win_length//4`. Defaults to None.\n        win_length (Optional[int], optional): The window length of the short time FFT. If `None`, it is set to same as `n_fft`. Defaults to None.\n        window (str, optional): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'kaiser', 'gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'. Defaults to 'hann'.\n        power (float, optional): Exponent for the magnitude spectrogram. Defaults to 2.0.\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to 'reflect'.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 50.0.\n        f_max (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use HTK formula in computing fbank matrix. Defaults to False.\n        norm (Union[str, float], optional): Type of normalization in computing fbank matrix. Slaney-style is used by default. You can specify norm=1.0/2.0 to use customized p-norm normalization. Defaults to 'slaney'.\n        ref_value (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): The minimum value of input magnitude. Defaults to 1e-10.\n        top_db (Optional[float], optional): The maximum db value of spectrogram. Defaults to None.\n        dtype (str, optional): Data type of input and window. Defaults to 'float32'.\n    \"\"\"\n\n    def __init__(self,\n                 sr: int=22050,\n                 n_fft: int=512,\n                 hop_length: Optional[int]=None,\n                 win_length: Optional[int]=None,\n                 window: str='hann',\n                 power: float=2.0,\n                 center: bool=True,\n                 pad_mode: str='reflect',\n                 n_mels: int=64,\n                 f_min: float=50.0,\n                 f_max: Optional[float]=None,\n                 htk: bool=False,\n                 norm: Union[str, float]='slaney',\n                 ref_value: float=1.0,\n                 amin: float=1e-10,\n                 top_db: Optional[float]=None,\n                 dtype: str='float32') -> None:\n        super(LogMelSpectrogram, self).__init__()\n\n        self._melspectrogram = MelSpectrogram(\n            sr=sr,\n            n_fft=n_fft,\n            hop_length=hop_length,\n            win_length=win_length,\n            window=window,\n            power=power,\n            center=center,\n            pad_mode=pad_mode,\n            n_mels=n_mels,\n            f_min=f_min,\n            f_max=f_max,\n            htk=htk,\n            norm=norm,\n            dtype=dtype)\n\n        self.ref_value = ref_value\n        self.amin = amin\n        self.top_db = top_db\n\n    def forward(self, x: Tensor) -> Tensor:\n        \"\"\"\n        Args:\n            x (Tensor): Tensor of waveforms with shape `(N, T)`\n\n        Returns:\n            Tensor: Log mel spectrograms with shape `(N, n_mels, num_frames)`.\n        \"\"\"\n        mel_feature = self._melspectrogram(x)\n        log_mel_feature = power_to_db(\n            mel_feature,\n            ref_value=self.ref_value,\n            amin=self.amin,\n            top_db=self.top_db)\n        return log_mel_feature\n\n\nclass MFCC(nn.Layer):\n    \"\"\"Compute mel frequency cepstral coefficients(MFCCs) feature of given waveforms.\n\n    Args:\n        sr (int, optional): Sample rate. Defaults to 22050.\n        n_mfcc (int, optional): [description]. Defaults to 40.\n        n_fft (int, optional): The number of frequency components of the discrete Fourier transform. Defaults to 512.\n        hop_length (Optional[int], optional): The hop length of the short time FFT. If `None`, it is set to `win_length//4`. Defaults to None.\n        win_length (Optional[int], optional): The window length of the short time FFT. If `None`, it is set to same as `n_fft`. Defaults to None.\n        window (str, optional): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'kaiser', 'gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'. Defaults to 'hann'.\n        power (float, optional): Exponent for the magnitude spectrogram. Defaults to 2.0.\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to 'reflect'.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 50.0.\n        f_max (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use HTK formula in computing fbank matrix. Defaults to False.\n        norm (Union[str, float], optional): Type of normalization in computing fbank matrix. Slaney-style is used by default. You can specify norm=1.0/2.0 to use customized p-norm normalization. Defaults to 'slaney'.\n        ref_value (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): The minimum value of input magnitude. Defaults to 1e-10.\n        top_db (Optional[float], optional): The maximum db value of spectrogram. Defaults to None.\n        dtype (str, optional): Data type of input and window. Defaults to 'float32'.\n    \"\"\"\n\n    def __init__(self,\n                 sr: int=22050,\n                 n_mfcc: int=40,\n                 n_fft: int=512,\n                 hop_length: Optional[int]=None,\n                 win_length: Optional[int]=None,\n                 window: str='hann',\n                 power: float=2.0,\n                 center: bool=True,\n                 pad_mode: str='reflect',\n                 n_mels: int=64,\n                 f_min: float=50.0,\n                 f_max: Optional[float]=None,\n                 htk: bool=False,\n                 norm: Union[str, float]='slaney',\n                 ref_value: float=1.0,\n                 amin: float=1e-10,\n                 top_db: Optional[float]=None,\n                 dtype: str=paddle.float32) -> None:\n        super(MFCC, self).__init__()\n        assert n_mfcc <= n_mels, 'n_mfcc cannot be larger than n_mels: %d vs %d' % (\n            n_mfcc, n_mels)\n        self._log_melspectrogram = LogMelSpectrogram(\n            sr=sr,\n            n_fft=n_fft,\n            hop_length=hop_length,\n            win_length=win_length,\n            window=window,\n            power=power,\n            center=center,\n            pad_mode=pad_mode,\n            n_mels=n_mels,\n            f_min=f_min,\n            f_max=f_max,\n            htk=htk,\n            norm=norm,\n            ref_value=ref_value,\n            amin=amin,\n            top_db=top_db,\n            dtype=dtype)\n        self.dct_matrix = create_dct(n_mfcc=n_mfcc, n_mels=n_mels, dtype=dtype)\n        self.register_buffer('dct_matrix', self.dct_matrix)\n\n    def forward(self, x: Tensor) -> Tensor:\n        \"\"\"\n        Args:\n            x (Tensor): Tensor of waveforms with shape `(N, T)`\n\n        Returns:\n            Tensor: Mel frequency cepstral coefficients with shape `(N, n_mfcc, num_frames)`.\n        \"\"\"\n        log_mel_feature = self._log_melspectrogram(x)\n        mfcc = paddle.matmul(\n            log_mel_feature.transpose((0, 2, 1)), self.dct_matrix).transpose(\n                (0, 2, 1))  # (B, n_mels, L)\n        return mfcc\n"
  },
  {
    "path": "audio/paddleaudio/functional/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .functional import compute_fbank_matrix\nfrom .functional import create_dct\nfrom .functional import fft_frequencies\nfrom .functional import hz_to_mel\nfrom .functional import mel_frequencies\nfrom .functional import mel_to_hz\nfrom .functional import power_to_db\n"
  },
  {
    "path": "audio/paddleaudio/functional/functional.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from librosa(https://github.com/librosa/librosa)\nimport math\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nfrom paddle import Tensor\n\n__all__ = [\n    'hz_to_mel',\n    'mel_to_hz',\n    'mel_frequencies',\n    'fft_frequencies',\n    'compute_fbank_matrix',\n    'power_to_db',\n    'create_dct',\n]\n\n\ndef hz_to_mel(freq: Union[Tensor, float],\n              htk: bool=False) -> Union[Tensor, float]:\n    \"\"\"Convert Hz to Mels.\n\n    Args:\n        freq (Union[Tensor, float]): The input tensor with arbitrary shape.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        Union[Tensor, float]: Frequency in mels.\n    \"\"\"\n\n    if htk:\n        if isinstance(freq, Tensor):\n            return 2595.0 * paddle.log10(1.0 + freq / 700.0)\n        else:\n            return 2595.0 * math.log10(1.0 + freq / 700.0)\n\n    # Fill in the linear part\n    f_min = 0.0\n    f_sp = 200.0 / 3\n\n    mels = (freq - f_min) / f_sp\n\n    # Fill in the log-scale part\n\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = math.log(6.4) / 27.0  # step size for log region\n\n    if isinstance(freq, Tensor):\n        target = min_log_mel + paddle.log(\n            freq / min_log_hz + 1e-10) / logstep  # prevent nan with 1e-10\n        mask = (freq > min_log_hz).astype(freq.dtype)\n        mels = target * mask + mels * (\n            1 - mask)  # will replace by masked_fill OP in future\n    else:\n        if freq >= min_log_hz:\n            mels = min_log_mel + math.log(freq / min_log_hz + 1e-10) / logstep\n\n    return mels\n\n\ndef mel_to_hz(mel: Union[float, Tensor],\n              htk: bool=False) -> Union[float, Tensor]:\n    \"\"\"Convert mel bin numbers to frequencies.\n\n    Args:\n        mel (Union[float, Tensor]): The mel frequency represented as a tensor with arbitrary shape.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        Union[float, Tensor]: Frequencies in Hz.\n    \"\"\"\n    if htk:\n        return 700.0 * (10.0**(mel / 2595.0) - 1.0)\n\n    f_min = 0.0\n    f_sp = 200.0 / 3\n    freqs = f_min + f_sp * mel\n    # And now the nonlinear scale\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = math.log(6.4) / 27.0  # step size for log region\n    if isinstance(mel, Tensor):\n        target = min_log_hz * paddle.exp(logstep * (mel - min_log_mel))\n        mask = (mel > min_log_mel).astype(mel.dtype)\n        freqs = target * mask + freqs * (\n            1 - mask)  # will replace by masked_fill OP in future\n    else:\n        if mel >= min_log_mel:\n            freqs = min_log_hz * math.exp(logstep * (mel - min_log_mel))\n\n    return freqs\n\n\ndef mel_frequencies(n_mels: int=64,\n                    f_min: float=0.0,\n                    f_max: float=11025.0,\n                    htk: bool=False,\n                    dtype: str='float32') -> Tensor:\n    \"\"\"Compute mel frequencies.\n\n    Args:\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (float, optional): Maximum frequency in Hz. Defaults to 11025.0.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        dtype (str, optional): The data type of the return frequencies. Defaults to 'float32'.\n\n    Returns:\n        Tensor: Tensor of n_mels frequencies in Hz with shape `(n_mels,)`.\n    \"\"\"\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    min_mel = hz_to_mel(f_min, htk=htk)\n    max_mel = hz_to_mel(f_max, htk=htk)\n    mels = paddle.linspace(min_mel, max_mel, n_mels, dtype=dtype)\n    freqs = mel_to_hz(mels, htk=htk)\n    return freqs\n\n\ndef fft_frequencies(sr: int, n_fft: int, dtype: str='float32') -> Tensor:\n    \"\"\"Compute fourier frequencies.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): Number of fft bins.\n        dtype (str, optional): The data type of the return frequencies. Defaults to 'float32'.\n\n    Returns:\n        Tensor: FFT frequencies in Hz with shape `(n_fft//2 + 1,)`.\n    \"\"\"\n    return paddle.linspace(0, float(sr) / 2, int(1 + n_fft // 2), dtype=dtype)\n\n\ndef compute_fbank_matrix(sr: int,\n                         n_fft: int,\n                         n_mels: int=64,\n                         f_min: float=0.0,\n                         f_max: Optional[float]=None,\n                         htk: bool=False,\n                         norm: Union[str, float]='slaney',\n                         dtype: str='float32') -> Tensor:\n    \"\"\"Compute fbank matrix.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): Number of fft bins.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        f_max (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        norm (Union[str, float], optional): Type of normalization. Defaults to 'slaney'.\n        dtype (str, optional): The data type of the return matrix. Defaults to 'float32'.\n\n    Returns:\n        Tensor: Mel transform matrix with shape `(n_mels, n_fft//2 + 1)`.\n    \"\"\"\n\n    if f_max is None:\n        f_max = float(sr) / 2\n\n    # Initialize the weights\n    weights = paddle.zeros((n_mels, int(1 + n_fft // 2)), dtype=dtype)\n\n    # Center freqs of each FFT bin\n    fftfreqs = fft_frequencies(sr=sr, n_fft=n_fft, dtype=dtype)\n\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    mel_f = mel_frequencies(\n        n_mels + 2, f_min=f_min, f_max=f_max, htk=htk, dtype=dtype)\n\n    fdiff = mel_f[1:] - mel_f[:-1]  #np.diff(mel_f)\n    ramps = mel_f.unsqueeze(1) - fftfreqs.unsqueeze(0)\n    #ramps = np.subtract.outer(mel_f, fftfreqs)\n\n    for i in range(n_mels):\n        # lower and upper slopes for all bins\n        lower = -ramps[i] / fdiff[i]\n        upper = ramps[i + 2] / fdiff[i + 1]\n\n        # .. then intersect them with each other and zero\n        weights[i] = paddle.maximum(\n            paddle.zeros_like(lower), paddle.minimum(lower, upper))\n\n    # Slaney-style mel is scaled to be approx constant energy per channel\n    if norm == 'slaney':\n        enorm = 2.0 / (mel_f[2:n_mels + 2] - mel_f[:n_mels])\n        weights *= enorm.unsqueeze(1)\n    elif isinstance(norm, int) or isinstance(norm, float):\n        weights = paddle.nn.functional.normalize(weights, p=norm, axis=-1)\n\n    return weights\n\n\ndef power_to_db(spect: Tensor,\n                ref_value: float=1.0,\n                amin: float=1e-10,\n                top_db: Optional[float]=None) -> Tensor:\n    \"\"\"Convert a power spectrogram (amplitude squared) to decibel (dB) units. The function computes the scaling `10 * log10(x / ref)` in a numerically stable way.\n\n    Args:\n        spect (Tensor): STFT power spectrogram.\n        ref_value (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to None.\n\n    Returns:\n        Tensor: Power spectrogram in db scale.\n    \"\"\"\n    if amin <= 0:\n        raise Exception(\"amin must be strictly positive\")\n\n    if ref_value <= 0:\n        raise Exception(\"ref_value must be strictly positive\")\n\n    ones = paddle.ones_like(spect)\n    log_spec = 10.0 * paddle.log10(paddle.maximum(ones * amin, spect))\n    log_spec -= 10.0 * math.log10(max(ref_value, amin))\n\n    if top_db is not None:\n        if top_db < 0:\n            raise Exception(\"top_db must be non-negative\")\n        log_spec = paddle.maximum(log_spec, ones * (log_spec.max() - top_db))\n\n    return log_spec\n\n\ndef create_dct(n_mfcc: int,\n               n_mels: int,\n               norm: Optional[str]='ortho',\n               dtype: str='float32') -> Tensor:\n    \"\"\"Create a discrete cosine transform(DCT) matrix.\n\n    Args:\n        n_mfcc (int): Number of mel frequency cepstral coefficients. \n        n_mels (int): Number of mel filterbanks.\n        norm (Optional[str], optional): Normalization type. Defaults to 'ortho'.\n        dtype (str, optional): The data type of the return matrix. Defaults to 'float32'.\n\n    Returns:\n        Tensor: The DCT matrix with shape `(n_mels, n_mfcc)`.\n    \"\"\"\n    n = paddle.arange(n_mels, dtype=dtype)\n    k = paddle.arange(n_mfcc, dtype=dtype).unsqueeze(1)\n    dct = paddle.cos(math.pi / float(n_mels) * (n + 0.5) *\n                     k)  # size (n_mfcc, n_mels)\n    if norm is None:\n        dct *= 2.0\n    else:\n        assert norm == \"ortho\"\n        dct[0] *= 1.0 / math.sqrt(2.0)\n        dct *= math.sqrt(2.0 / float(n_mels))\n    return dct.T\n"
  },
  {
    "path": "audio/paddleaudio/functional/window.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\nimport math\nfrom typing import List\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import Tensor\n\n\nclass WindowFunctionRegister(object):\n    def __init__(self):\n        self._functions_dict = dict()\n\n    def register(self):\n        def add_subfunction(func):\n            name = func.__name__\n            self._functions_dict[name] = func\n            return func\n\n        return add_subfunction\n\n    def get(self, name):\n        return self._functions_dict[name]\n\n\nwindow_function_register = WindowFunctionRegister()\n\n\n@window_function_register.register()\ndef _cat(x: List[Tensor], data_type: str) -> Tensor:\n    l = [paddle.to_tensor(_, data_type) for _ in x]\n    return paddle.concat(l)\n\n\n@window_function_register.register()\ndef _acosh(x: Union[Tensor, float]) -> Tensor:\n    if isinstance(x, float):\n        return math.log(x + math.sqrt(x**2 - 1))\n    return paddle.log(x + paddle.sqrt(paddle.square(x) - 1))\n\n\n@window_function_register.register()\ndef _extend(M: int, sym: bool) -> bool:\n    \"\"\"Extend window by 1 sample if needed for DFT-even symmetry.\"\"\"\n    if not sym:\n        return M + 1, True\n    else:\n        return M, False\n\n\n@window_function_register.register()\ndef _len_guards(M: int) -> bool:\n    \"\"\"Handle small or incorrect window lengths.\"\"\"\n    if int(M) != M or M < 0:\n        raise ValueError('Window length M must be a non-negative integer')\n\n    return M <= 1\n\n\n@window_function_register.register()\ndef _truncate(w: Tensor, needed: bool) -> Tensor:\n    \"\"\"Truncate window by 1 sample if needed for DFT-even symmetry.\"\"\"\n    if needed:\n        return w[:-1]\n    else:\n        return w\n\n\n@window_function_register.register()\ndef _general_gaussian(\n    M: int, p, sig, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a window with a generalized Gaussian shape.\n    This function is consistent with scipy.signal.windows.general_gaussian().\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype) - (M - 1.0) / 2.0\n    w = paddle.exp(-0.5 * paddle.abs(n / sig) ** (2 * p))\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _general_cosine(\n    M: int, a: float, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a generic weighted sum of cosine terms window.\n    This function is consistent with scipy.signal.windows.general_cosine().\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    fac = paddle.linspace(-math.pi, math.pi, M, dtype=dtype)\n    w = paddle.zeros((M,), dtype=dtype)\n    for k in range(len(a)):\n        w += a[k] * paddle.cos(k * fac)\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _general_hamming(\n    M: int, alpha: float, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a generalized Hamming window.\n    This function is consistent with scipy.signal.windows.general_hamming()\n    \"\"\"\n    return _general_cosine(M, [alpha, 1.0 - alpha], sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _taylor(\n    M: int, nbar=4, sll=30, norm=True, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a Taylor window.\n    The Taylor window taper function approximates the Dolph-Chebyshev window's\n    constant sidelobe level for a parameterized number of near-in sidelobes.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    # Original text uses a negative sidelobe level parameter and then negates\n    # it in the calculation of B. To keep consistent with other methods we\n    # assume the sidelobe level parameter to be positive.\n    B = 10 ** (sll / 20)\n    A = _acosh(B) / math.pi\n    s2 = nbar**2 / (A**2 + (nbar - 0.5) ** 2)\n    ma = paddle.arange(1, nbar, dtype=dtype)\n\n    Fm = paddle.empty((nbar - 1,), dtype=dtype)\n    signs = paddle.empty_like(ma)\n    signs[::2] = 1\n    signs[1::2] = -1\n    m2 = ma * ma\n    for mi in range(len(ma)):\n        numer = signs[mi] * paddle.prod(\n            1 - m2[mi] / s2 / (A**2 + (ma - 0.5) ** 2)\n        )\n        if mi == 0:\n            denom = 2 * paddle.prod(1 - m2[mi] / m2[mi + 1 :])\n        elif mi == len(ma) - 1:\n            denom = 2 * paddle.prod(1 - m2[mi] / m2[:mi])\n        else:\n            denom = (\n                2\n                * paddle.prod(1 - m2[mi] / m2[:mi])\n                * paddle.prod(1 - m2[mi] / m2[mi + 1 :])\n            )\n\n        Fm[mi] = numer / denom\n\n    def W(n):\n        return 1 + 2 * paddle.matmul(\n            Fm.unsqueeze(0),\n            paddle.cos(2 * math.pi * ma.unsqueeze(1) * (n - M / 2.0 + 0.5) / M),\n        )\n\n    w = W(paddle.arange(0, M, dtype=dtype))\n\n    # normalize (Note that this is not described in the original text [1])\n    if norm:\n        scale = 1.0 / W((M - 1) / 2)\n        w *= scale\n    w = w.squeeze()\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _hamming(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a Hamming window.\n    The Hamming window is a taper formed by using a raised cosine with\n    non-zero endpoints, optimized to minimize the nearest side lobe.\n    \"\"\"\n    return _general_hamming(M, 0.54, sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _hann(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a Hann window.\n    The Hann window is a taper formed by using a raised cosine or sine-squared\n    with ends that touch zero.\n    \"\"\"\n    return _general_hamming(M, 0.5, sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _tukey(\n    M: int, alpha=0.5, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a Tukey window.\n    The Tukey window is also known as a tapered cosine window.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n\n    if alpha <= 0:\n        return paddle.ones((M,), dtype=dtype)\n    elif alpha >= 1.0:\n        return hann(M, sym=sym)\n\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype)\n    width = int(alpha * (M - 1) / 2.0)\n    n1 = n[0 : width + 1]\n    n2 = n[width + 1 : M - width - 1]\n    n3 = n[M - width - 1 :]\n\n    w1 = 0.5 * (1 + paddle.cos(math.pi * (-1 + 2.0 * n1 / alpha / (M - 1))))\n    w2 = paddle.ones(n2.shape, dtype=dtype)\n    w3 = 0.5 * (\n        1\n        + paddle.cos(math.pi * (-2.0 / alpha + 1 + 2.0 * n3 / alpha / (M - 1)))\n    )\n    w = paddle.concat([w1, w2, w3])\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _gaussian(\n    M: int, std: float, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute a Gaussian window.\n    The Gaussian widows has a Gaussian shape defined by the standard deviation(std).\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype) - (M - 1.0) / 2.0\n    sig2 = 2 * std * std\n    w = paddle.exp(-(n**2) / sig2)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _exponential(\n    M: int, center=None, tau=1.0, sym: bool = True, dtype: str = 'float64'\n) -> Tensor:\n    \"\"\"Compute an exponential (or Poisson) window.\"\"\"\n    if sym and center is not None:\n        raise ValueError(\"If sym==True, center must be None.\")\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    if center is None:\n        center = (M - 1) / 2\n\n    n = paddle.arange(0, M, dtype=dtype)\n    w = paddle.exp(-paddle.abs(n - center) / tau)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _triang(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a triangular window.\"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(1, (M + 1) // 2 + 1, dtype=dtype)\n    if M % 2 == 0:\n        w = (2 * n - 1.0) / M\n        w = paddle.concat([w, w[::-1]])\n    else:\n        w = 2 * n / (M + 1.0)\n        w = paddle.concat([w, w[-2::-1]])\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _bohman(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a Bohman window.\n    The Bohman window is the autocorrelation of a cosine window.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    fac = paddle.abs(paddle.linspace(-1, 1, M, dtype=dtype)[1:-1])\n    w = (1 - fac) * paddle.cos(math.pi * fac) + 1.0 / math.pi * paddle.sin(\n        math.pi * fac\n    )\n    w = _cat([0, w, 0], dtype)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _blackman(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a Blackman window.\n    The Blackman window is a taper formed by using the first three terms of\n    a summation of cosines. It was designed to have close to the minimal\n    leakage possible.  It is close to optimal, only slightly worse than a\n    Kaiser window.\n    \"\"\"\n    return _general_cosine(M, [0.42, 0.50, 0.08], sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _cosine(M: int, sym: bool = True, dtype: str = 'float64') -> Tensor:\n    \"\"\"Compute a window with a simple cosine shape.\"\"\"\n    if _len_guards(M):\n        return paddle.ones((M,), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    w = paddle.sin(math.pi / M * (paddle.arange(0, M, dtype=dtype) + 0.5))\n\n    return _truncate(w, needs_trunc)\n\n\ndef get_window(\n    window: Union[str, Tuple[str, float]],\n    win_length: int,\n    fftbins: bool = True,\n    dtype: str = 'float64',\n) -> Tensor:\n    \"\"\"Return a window of a given length and type.\n\n    Args:\n        window (Union[str, Tuple[str, float]]): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'gaussian', 'general_gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'.\n        win_length (int): Number of samples.\n        fftbins (bool, optional): If True, create a \"periodic\" window. Otherwise, create a \"symmetric\" window, for use in filter design. Defaults to True.\n        dtype (str, optional): The data type of the return window. Defaults to 'float64'.\n\n    Returns:\n        Tensor: The window represented as a tensor.\n\n    Examples:\n        .. code-block:: python\n\n            import paddle\n\n            n_fft = 512\n            cosine_window = paddle.audio.functional.get_window('cosine', n_fft)\n\n            std = 7\n            gaussian_window = paddle.audio.functional.get_window(('gaussian',std), n_fft)\n    \"\"\"\n    sym = not fftbins\n\n    args = ()\n    if isinstance(window, tuple):\n        winstr = window[0]\n        if len(window) > 1:\n            args = window[1:]\n    elif isinstance(window, str):\n        if window in ['gaussian', 'exponential']:\n            raise ValueError(\n                \"The '\" + window + \"' window needs one or \"\n                \"more parameters -- pass a tuple.\"\n            )\n        else:\n            winstr = window\n    else:\n        raise ValueError(\n            \"%s as window type is not supported.\" % str(type(window))\n        )\n\n    try:\n        winfunc = window_function_register.get('_' + winstr)\n    except KeyError as e:\n        raise ValueError(\"Unknown window type.\") from e\n\n    params = (win_length,) + args\n    kwargs = {'sym': sym}\n    return winfunc(*params, dtype=dtype, **kwargs)\n"
  },
  {
    "path": "audio/paddleaudio/kaldi/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .kaldi import fbank\n#from .kaldi import pitch\n"
  },
  {
    "path": "audio/paddleaudio/kaldi/kaldi.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddleaudio\nfrom paddleaudio._internal import module_utils\n\n__all__ = [\n    'fbank',\n]\n\n\n@module_utils.requires_kaldi()\ndef fbank(\n        wav,\n        samp_freq: int=16000,\n        frame_shift_ms: float=10.0,\n        frame_length_ms: float=25.0,\n        dither: float=0.0,\n        preemph_coeff: float=0.97,\n        remove_dc_offset: bool=True,\n        window_type: str='povey',\n        round_to_power_of_two: bool=True,\n        blackman_coeff: float=0.42,\n        snip_edges: bool=True,\n        max_feature_vectors: int=-1,\n        num_bins: int=23,\n        low_freq: float=20,\n        high_freq: float=0,\n        vtln_low: float=100,\n        vtln_high: float=-500,\n        debug_mel: bool=False,\n        htk_mode: bool=False,\n        use_energy: bool=False,  # fbank opts\n        energy_floor: float=0.0,\n        raw_energy: bool=True,\n        htk_compat: bool=False,\n        use_log_fbank: bool=True,\n        use_power: bool=True):\n    frame_opts = paddleaudio._paddleaudio.FrameExtractionOptions()\n    mel_opts = paddleaudio._paddleaudio.MelBanksOptions()\n    fbank_opts = paddleaudio._paddleaudio.FbankOptions()\n    frame_opts.samp_freq = samp_freq\n    frame_opts.frame_shift_ms = frame_shift_ms\n    frame_opts.frame_length_ms = frame_length_ms\n    frame_opts.dither = dither\n    frame_opts.preemph_coeff = preemph_coeff\n    frame_opts.remove_dc_offset = remove_dc_offset\n    frame_opts.window_type = window_type\n    frame_opts.round_to_power_of_two = round_to_power_of_two\n    frame_opts.blackman_coeff = blackman_coeff\n    frame_opts.snip_edges = snip_edges\n    frame_opts.max_feature_vectors = max_feature_vectors\n\n    mel_opts.num_bins = num_bins\n    mel_opts.low_freq = low_freq\n    mel_opts.high_freq = high_freq\n    mel_opts.vtln_low = vtln_low\n    mel_opts.vtln_high = vtln_high\n    mel_opts.debug_mel = debug_mel\n    mel_opts.htk_mode = htk_mode\n\n    fbank_opts.use_energy = use_energy\n    fbank_opts.energy_floor = energy_floor\n    fbank_opts.raw_energy = raw_energy\n    fbank_opts.htk_compat = htk_compat\n    fbank_opts.use_log_fbank = use_log_fbank\n    fbank_opts.use_power = use_power\n    feat = paddleaudio._paddleaudio.ComputeFbank(frame_opts, mel_opts,\n                                                 fbank_opts, wav)\n    return feat\n\n\n#@module_utils.requires_kaldi()\n#def pitch(wav,\n#samp_freq: int=16000,\n#frame_shift_ms: float=10.0,\n#frame_length_ms: float=25.0,\n#preemph_coeff: float=0.0,\n#min_f0: int=50,\n#max_f0: int=400,\n#soft_min_f0: float=10.0,\n#penalty_factor: float=0.1,\n#lowpass_cutoff: int=1000,\n#resample_freq: int=4000,\n#delta_pitch: float=0.005,\n#nccf_ballast: int=7000,\n#lowpass_filter_width: int=1,\n#upsample_filter_width: int=5,\n#max_frames_latency: int=0,\n#frames_per_chunk: int=0,\n#simulate_first_pass_online: bool=False,\n#recompute_frame: int=500,\n#nccf_ballast_online: bool=False,\n#snip_edges: bool=True):\n#pitch_opts = paddleaudio._paddleaudio.PitchExtractionOptions()\n#pitch_opts.samp_freq = samp_freq\n#pitch_opts.frame_shift_ms = frame_shift_ms\n#pitch_opts.frame_length_ms = frame_length_ms\n#pitch_opts.preemph_coeff = preemph_coeff\n#pitch_opts.min_f0 = min_f0\n#pitch_opts.max_f0 = max_f0\n#pitch_opts.soft_min_f0 = soft_min_f0\n#pitch_opts.penalty_factor = penalty_factor\n#pitch_opts.lowpass_cutoff = lowpass_cutoff\n#pitch_opts.resample_freq = resample_freq\n#pitch_opts.delta_pitch = delta_pitch\n#pitch_opts.nccf_ballast = nccf_ballast\n#pitch_opts.lowpass_filter_width = lowpass_filter_width\n#pitch_opts.upsample_filter_width = upsample_filter_width\n#pitch_opts.max_frames_latency = max_frames_latency\n#pitch_opts.frames_per_chunk = frames_per_chunk\n#pitch_opts.simulate_first_pass_online = simulate_first_pass_online\n#pitch_opts.recompute_frame = recompute_frame\n#pitch_opts.nccf_ballast_online = nccf_ballast_online\n#pitch_opts.snip_edges = snip_edges\n#pitch = paddleaudio._paddleaudio.ComputeKaldiPitch(pitch_opts, wav)\n#return pitch\n"
  },
  {
    "path": "audio/paddleaudio/metric/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .eer import compute_eer\nfrom .eer import compute_minDCF\n"
  },
  {
    "path": "audio/paddleaudio/metric/eer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom sklearn.metrics import roc_curve\n\n\ndef compute_eer(labels: np.ndarray, scores: np.ndarray) -> List[float]:\n    \"\"\"Compute EER and return score threshold.\n\n    Args:\n        labels (np.ndarray): the trial label, shape: [N], one-dimension, N refer to the samples num\n        scores (np.ndarray): the trial scores, shape: [N], one-dimension, N refer to the samples num\n\n    Returns:\n        List[float]: eer and the specific threshold\n    \"\"\"\n    fpr, tpr, threshold = roc_curve(y_true=labels, y_score=scores)\n    fnr = 1 - tpr\n    eer_threshold = threshold[np.nanargmin(np.absolute((fnr - fpr)))]\n    eer = fpr[np.nanargmin(np.absolute((fnr - fpr)))]\n    return eer, eer_threshold\n\n\ndef compute_minDCF(positive_scores,\n                   negative_scores,\n                   c_miss=1.0,\n                   c_fa=1.0,\n                   p_target=0.01):\n    \"\"\"\n    This is modified from SpeechBrain\n    https://github.com/speechbrain/speechbrain/blob/085be635c07f16d42cd1295045bc46c407f1e15b/speechbrain/utils/metric_stats.py#L509\n    Computes the minDCF metric normally used to evaluate speaker verification\n    systems. The min_DCF is the minimum of the following C_det function computed\n    within the defined threshold range:\n\n    C_det =  c_miss * p_miss * p_target + c_fa * p_fa * (1 -p_target)\n\n    where p_miss is the missing probability and p_fa is the probability of having\n    a false alarm.\n\n    Args:\n        positive_scores (Paddle.Tensor): The scores from entries of the same class.\n        negative_scores (Paddle.Tensor): The scores from entries of different classes.\n        c_miss (float, optional): Cost assigned to a missing error (default 1.0).\n        c_fa (float, optional): Cost assigned to a false alarm (default 1.0).\n        p_target (float, optional): Prior probability of having a target (default 0.01).\n\n    Returns:\n        List[float]: min dcf and the specific threshold\n    \"\"\"\n    # Computing candidate thresholds\n    if len(positive_scores.shape) > 1:\n        positive_scores = positive_scores.squeeze()\n\n    if len(negative_scores.shape) > 1:\n        negative_scores = negative_scores.squeeze()\n\n    thresholds = paddle.sort(paddle.concat([positive_scores, negative_scores]))\n    thresholds = paddle.unique(thresholds)\n\n    # Adding intermediate thresholds\n    interm_thresholds = (thresholds[0:-1] + thresholds[1:]) / 2\n    thresholds = paddle.sort(paddle.concat([thresholds, interm_thresholds]))\n\n    # Computing False Rejection Rate (miss detection)\n    positive_scores = paddle.concat(\n        len(thresholds) * [positive_scores.unsqueeze(0)])\n    pos_scores_threshold = positive_scores.transpose(perm=[1, 0]) <= thresholds\n    p_miss = (pos_scores_threshold.sum(0)\n              ).astype(\"float32\") / positive_scores.shape[1]\n    del positive_scores\n    del pos_scores_threshold\n\n    # Computing False Acceptance Rate (false alarm)\n    negative_scores = paddle.concat(\n        len(thresholds) * [negative_scores.unsqueeze(0)])\n    neg_scores_threshold = negative_scores.transpose(perm=[1, 0]) > thresholds\n    p_fa = (neg_scores_threshold.sum(0)\n            ).astype(\"float32\") / negative_scores.shape[1]\n    del negative_scores\n    del neg_scores_threshold\n\n    c_det = c_miss * p_miss * p_target + c_fa * p_fa * (1 - p_target)\n    c_min = paddle.min(c_det, axis=0)\n    min_index = paddle.argmin(c_det, axis=0)\n    return float(c_min), float(thresholds[min_index])\n"
  },
  {
    "path": "audio/paddleaudio/sox_effects/__init__.py",
    "content": "from paddleaudio._internal import module_utils as _mod_utils\n\nfrom .sox_effects import apply_effects_file\nfrom .sox_effects import apply_effects_tensor\nfrom .sox_effects import effect_names\nfrom .sox_effects import init_sox_effects\nfrom .sox_effects import shutdown_sox_effects\n\nif _mod_utils.is_sox_available():\n    import atexit\n\n    init_sox_effects()\n    atexit.register(shutdown_sox_effects)\n\n__all__ = [\n    \"init_sox_effects\",\n    \"shutdown_sox_effects\",\n    \"effect_names\",\n    \"apply_effects_tensor\",\n    \"apply_effects_file\",\n]\n"
  },
  {
    "path": "audio/paddleaudio/sox_effects/sox_effects.py",
    "content": "import os\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nimport paddleaudio\nfrom paddleaudio._internal import module_utils as _mod_utils\nfrom paddleaudio.utils.sox_utils import list_effects\n\n#code is from: https://github.com/pytorch/audio/blob/main/torchaudio/sox_effects/sox_effects.py\n\n\n@_mod_utils.requires_sox()\ndef init_sox_effects():\n    \"\"\"Initialize resources required to use sox effects.\n\n    Note:\n        You do not need to call this function manually. It is called automatically.\n\n    Once initialized, you do not need to call this function again across the multiple uses of\n    sox effects though it is safe to do so as long as :func:`shutdown_sox_effects` is not called yet.\n    Once :func:`shutdown_sox_effects` is called, you can no longer use SoX effects and initializing\n    again will result in error.\n    \"\"\"\n    paddleaudio._paddleaudio.sox_effects_initialize_sox_effects()\n\n\n@_mod_utils.requires_sox()\ndef shutdown_sox_effects():\n    \"\"\"Clean up resources required to use sox effects.\n\n    Note:\n        You do not need to call this function manually. It is called automatically.\n\n    It is safe to call this function multiple times.\n    Once :py:func:`shutdown_sox_effects` is called, you can no longer use SoX effects and\n    initializing again will result in error.\n    \"\"\"\n    paddleaudio._paddleaudio.sox_effects_shutdown_sox_effects()\n\n\n@_mod_utils.requires_sox()\ndef effect_names() -> List[str]:\n    \"\"\"Gets list of valid sox effect names\n\n    Returns:\n        List[str]: list of available effect names.\n\n    Example\n        >>> paddleaudio.sox_effects.effect_names()\n        ['allpass', 'band', 'bandpass', ... ]\n    \"\"\"\n    return list(list_effects().keys())\n\n\n@_mod_utils.requires_sox()\ndef apply_effects_tensor(\n        tensor: paddle.Tensor,\n        sample_rate: int,\n        effects: List[List[str]],\n        channels_first: bool=True, ) -> Tuple[paddle.Tensor, int]:\n    \"\"\"Apply sox effects to given Tensor\n\n    .. devices:: CPU\n\n    Note:\n        This function only works on CPU Tensors.\n        This function works in the way very similar to ``sox`` command, however there are slight\n        differences. For example, ``sox`` command adds certain effects automatically (such as\n        ``rate`` effect after ``speed`` and ``pitch`` and other effects), but this function does\n        only applies the given effects. (Therefore, to actually apply ``speed`` effect, you also\n        need to give ``rate`` effect with desired sampling rate.).\n\n    Args:\n        tensor (paddle.Tensor): Input 2D CPU Tensor.\n        sample_rate (int): Sample rate\n        effects (List[List[str]]): List of effects.\n        channels_first (bool, optional): Indicates if the input Tensor's dimension is\n            `[channels, time]` or `[time, channels]`\n\n    Returns:\n        (Tensor, int): Resulting Tensor and sample rate.\n        The resulting Tensor has the same ``dtype`` as the input Tensor, and\n        the same channels order. The shape of the Tensor can be different based on the\n        effects applied. Sample rate can also be different based on the effects applied.\n\n    Example - Basic usage\n        >>>\n        >>> # Defines the effects to apply\n        >>> effects = [\n        ...     ['gain', '-n'],  # normalises to 0dB\n        ...     ['pitch', '5'],  # 5 cent pitch shift\n        ...     ['rate', '8000'],  # resample to 8000 Hz\n        ... ]\n        >>>\n        >>> # Generate pseudo wave:\n        >>> # normalized, channels first, 2ch, sampling rate 16000, 1 second\n        >>> sample_rate = 16000\n        >>> waveform = 2 * paddle.rand([2, sample_rate * 1]) - 1\n        >>> waveform.shape\n        paddle.Size([2, 16000])\n        >>> waveform\n        tensor([[ 0.3138,  0.7620, -0.9019,  ..., -0.7495, -0.4935,  0.5442],\n                [-0.0832,  0.0061,  0.8233,  ..., -0.5176, -0.9140, -0.2434]])\n        >>>\n        >>> # Apply effects\n        >>> waveform, sample_rate = apply_effects_tensor(\n        ...     wave_form, sample_rate, effects, channels_first=True)\n        >>>\n        >>> # Check the result\n        >>> # The new waveform is sampling rate 8000, 1 second.\n        >>> # normalization and channel order are preserved\n        >>> waveform.shape\n        paddle.Size([2, 8000])\n        >>> waveform\n        tensor([[ 0.5054, -0.5518, -0.4800,  ..., -0.0076,  0.0096, -0.0110],\n                [ 0.1331,  0.0436, -0.3783,  ..., -0.0035,  0.0012,  0.0008]])\n        >>> sample_rate\n        8000\n\n    \"\"\"\n    tensor_np = tensor.numpy()\n    ret = paddleaudio._paddleaudio.sox_effects_apply_effects_tensor(\n        tensor_np, sample_rate, effects, channels_first)\n    if ret is not None:\n        return (paddle.to_tensor(ret[0]), ret[1])\n    raise RuntimeError(\"Failed to apply sox effect\")\n\n\n@_mod_utils.requires_sox()\ndef apply_effects_file(\n        path: str,\n        effects: List[List[str]],\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[paddle.Tensor, int]:\n    \"\"\"Apply sox effects to the audio file and load the resulting data as Tensor\n\n    Note:\n        This function works in the way very similar to ``sox`` command, however there are slight\n        differences. For example, ``sox`` command adds certain effects automatically (such as\n        ``rate`` effect after ``speed``, ``pitch`` etc), but this function only applies the given\n        effects. Therefore, to actually apply ``speed`` effect, you also need to give ``rate``\n        effect with desired sampling rate, because internally, ``speed`` effects only alter sampling\n        rate and leave samples untouched.\n\n    Args:\n        path (path-like object or file-like object):\n        effects (List[List[str]]): List of effects.\n        normalize (bool, optional):\n            When ``True``, this function always return ``float32``, and sample values are\n            normalized to ``[-1.0, 1.0]``.\n            If input file is integer WAV, giving ``False`` will change the resulting Tensor type to\n            integer type. This argument has no effect for formats other\n            than integer WAV type.\n        channels_first (bool, optional): When True, the returned Tensor has dimension `[channel, time]`.\n            Otherwise, the returned Tensor's dimension is `[time, channel]`.\n        format (str or None, optional):\n            Override the format detection with the given format.\n            Providing the argument might help when libsox can not infer the format\n            from header or extension,\n\n    Returns:\n        (Tensor, int): Resulting Tensor and sample rate.\n        If ``normalize=True``, the resulting Tensor is always ``float32`` type.\n        If ``normalize=False`` and the input audio file is of integer WAV file, then the\n        resulting Tensor has corresponding integer type. (Note 24 bit integer type is not supported)\n        If ``channels_first=True``, the resulting Tensor has dimension `[channel, time]`,\n        otherwise `[time, channel]`.\n\n    Example - Basic usage\n        >>>\n        >>> # Defines the effects to apply\n        >>> effects = [\n        ...     ['gain', '-n'],  # normalises to 0dB\n        ...     ['pitch', '5'],  # 5 cent pitch shift\n        ...     ['rate', '8000'],  # resample to 8000 Hz\n        ... ]\n        >>>\n        >>> # Apply effects and load data with channels_first=True\n        >>> waveform, sample_rate = apply_effects_file(\"data.wav\", effects, channels_first=True)\n        >>>\n        >>> # Check the result\n        >>> waveform.shape\n        paddle.Size([2, 8000])\n        >>> waveform\n        tensor([[ 5.1151e-03,  1.8073e-02,  2.2188e-02,  ...,  1.0431e-07,\n                 -1.4761e-07,  1.8114e-07],\n                [-2.6924e-03,  2.1860e-03,  1.0650e-02,  ...,  6.4122e-07,\n                 -5.6159e-07,  4.8103e-07]])\n        >>> sample_rate\n        8000\n\n    Example - Apply random speed perturbation to dataset\n        >>>\n        >>> # Load data from file, apply random speed perturbation\n        >>> class RandomPerturbationFile(paddle.utils.data.Dataset):\n        ...     \\\"\\\"\\\"Given flist, apply random speed perturbation\n        ...\n        ...     Suppose all the input files are at least one second long.\n        ...     \\\"\\\"\\\"\n        ...     def __init__(self, flist: List[str], sample_rate: int):\n        ...         super().__init__()\n        ...         self.flist = flist\n        ...         self.sample_rate = sample_rate\n        ...\n        ...     def __getitem__(self, index):\n        ...         speed = 0.5 + 1.5 * random.randn()\n        ...         effects = [\n        ...             ['gain', '-n', '-10'],  # apply 10 db attenuation\n        ...             ['remix', '-'],  # merge all the channels\n        ...             ['speed', f'{speed:.5f}'],  # duration is now 0.5 ~ 2.0 seconds.\n        ...             ['rate', f'{self.sample_rate}'],\n        ...             ['pad', '0', '1.5'],  # add 1.5 seconds silence at the end\n        ...             ['trim', '0', '2'],  # get the first 2 seconds\n        ...         ]\n        ...         waveform, _ = paddleaudio.sox_effects.apply_effects_file(\n        ...             self.flist[index], effects)\n        ...         return waveform\n        ...\n        ...     def __len__(self):\n        ...         return len(self.flist)\n        ...\n        >>> dataset = RandomPerturbationFile(file_list, sample_rate=8000)\n        >>> loader = paddle.utils.data.DataLoader(dataset, batch_size=32)\n        >>> for batch in loader:\n        >>>     pass\n    \"\"\"\n    if hasattr(path, \"read\"):\n        ret = paddleaudio._paddleaudio.apply_effects_fileobj(\n            path, effects, normalize, channels_first, format)\n        if ret is None:\n            raise RuntimeError(\"Failed to load audio from {}\".format(path))\n        return (paddle.to_tensor(ret[0]), ret[1])\n    path = os.fspath(path)\n    ret = paddleaudio._paddleaudio.sox_effects_apply_effects_file(\n        path, effects, normalize, channels_first, format)\n    if ret is not None:\n        return (paddle.to_tensor(ret[0]), ret[1])\n    raise RuntimeError(\"Failed to load audio from {}\".format(path))\n"
  },
  {
    "path": "audio/paddleaudio/src/CMakeLists.txt",
    "content": "if (MSVC)\n  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)\nendif()\n\nif(APPLE)\nset(CMAKE_SHARED_LIBRARY_SUFFIX \".so\")\nendif(APPLE)\n\n################################################################################\n# libpaddleaudio\n################################################################################\nset(\n  LIBPADDLEAUDIO_SOURCES\n  utils.cpp\n  )\n\nset(\n  LIBPADDLEAUDIO_INCLUDE_DIRS\n  ${PROJECT_SOURCE_DIR}\n  )\n\nset(\n  LIBPADDLEAUDIO_LINK_LIBRARIES\n  )\n\nset(\n  LIBPADDLEAUDIO_COMPILE_DEFINITIONS)\n\n#------------------------------------------------------------------------------#\n# START OF CUSTOMIZATION LOGICS\n#------------------------------------------------------------------------------#\n\nif(BUILD_SOX)\n  list(\n    APPEND\n    LIBPADDLEAUDIO_LINK_LIBRARIES\n    libsox\n    )\n  list(\n    APPEND\n    LIBPADDLEAUDIO_SOURCES\n    )\n  list(\n    APPEND\n    LIBPADDLEAUDIO_COMPILE_DEFINITIONS\n    INCLUDE_SOX\n    )\nendif()\n\n\nif(BUILD_KALDI)\n  list(\n    APPEND\n    LIBPADDLEAUDIO_LINK_LIBRARIES\n    kaldi-native-fbank-core\n  )\n  list(\n    APPEND\n    LIBPADDLEAUDIO_COMPILE_DEFINITIONS\n    INCLUDE_KALDI\n    COMPILE_WITHOUT_OPENFST\n  )\nendif()\n\n#------------------------------------------------------------------------------#\n# END OF CUSTOMIZATION LOGICS\n#------------------------------------------------------------------------------#\n\nfunction (define_library name source include_dirs link_libraries compile_defs)\n  add_library(${name} SHARED ${source})\n  target_include_directories(${name} PRIVATE ${include_dirs})\n  target_link_libraries(${name} ${link_libraries})\n  target_compile_definitions(${name} PRIVATE ${compile_defs})\n  set_target_properties(${name} PROPERTIES PREFIX \"\")\n  if (MSVC)\n    set_target_properties(${name} PROPERTIES SUFFIX \".pyd\")\n  endif(MSVC)\n\n  install(\n    TARGETS ${name}\n    LIBRARY DESTINATION lib\n    RUNTIME DESTINATION lib  # For Windows\n    )\nendfunction()\n\n\ndefine_library(\n  libpaddleaudio\n  \"${LIBPADDLEAUDIO_SOURCES}\"\n  \"${LIBPADDLEAUDIO_INCLUDE_DIRS}\"\n  \"${LIBPADDLEAUDIO_LINK_LIBRARIES}\"\n  \"${LIBPADDLEAUDIO_COMPILE_DEFINITIONS}\"\n)\n\nif (APPLE)\n  set(AUDIO_LIBRARY libpaddleaudio CACHE INTERNAL \"\")\nelse()\n  set(AUDIO_LIBRARY -Wl,--no-as-needed libpaddleaudio -Wl,--as-needed CACHE INTERNAL \"\")\nendif()\n\n  ################################################################################\n# _paddleaudio.so\n################################################################################\nif (BUILD_PADDLEAUDIO_PYTHON_EXTENSION)\nif (WIN32)\n  find_package(Python3 ${PYTHON_VERSION} EXACT COMPONENTS Development)\n  set(ADDITIONAL_ITEMS Python3::Python)\nendif()\nfunction(define_extension name sources include_dirs libraries definitions)\n  add_library(${name} SHARED ${sources})\n  target_compile_definitions(${name} PRIVATE \"${definitions}\")\n  target_include_directories(\n    ${name} PRIVATE ${PROJECT_SOURCE_DIR} ${Python_INCLUDE_DIR} ${pybind11_INCLUDE_DIR} ${include_dirs})\n  target_link_libraries(\n    ${name}\n    ${libraries}\n    ${PYTHON_LIBRARY}\n    ${ADDITIONAL_ITEMS}\n    )\n  set_target_properties(${name} PROPERTIES PREFIX \"\")\n  if (MSVC)\n    set_target_properties(${name} PROPERTIES SUFFIX \".pyd\")\n  endif(MSVC)\n  if (APPLE)\n    # https://github.com/facebookarchive/caffe2/issues/854#issuecomment-364538485\n    # https://github.com/pytorch/pytorch/commit/73f6715f4725a0723d8171d3131e09ac7abf0666\n    set_target_properties(${name} PROPERTIES LINK_FLAGS \"-undefined dynamic_lookup\")\n  endif()\n  install(\n    TARGETS ${name}\n    LIBRARY DESTINATION .\n    RUNTIME DESTINATION .  # For Windows\n    )\nendfunction()\n\nset(\n  EXTENSION_SOURCES\n  pybind/pybind.cpp\n  )\n#----------------------------------------------------------------------------#\n# START OF CUSTOMIZATION LOGICS\n#----------------------------------------------------------------------------#\nif(BUILD_SOX)\n  list(\n    APPEND\n    EXTENSION_SOURCES\n    pybind/sox/effects.cpp\n    pybind/sox/effects_chain.cpp\n    pybind/sox/io.cpp\n    pybind/sox/types.cpp\n    pybind/sox/utils.cpp\n    )\nendif()\n\nif(BUILD_KALDI)\n  list(\n    APPEND\n    EXTENSION_SOURCES\n    pybind/kaldi/kaldi_feature_wrapper.cc\n    pybind/kaldi/kaldi_feature.cc\n    )\nendif()\n#----------------------------------------------------------------------------#\n# END OF CUSTOMIZATION LOGICS\n#----------------------------------------------------------------------------#\ndefine_extension(\n  _paddleaudio\n  \"${EXTENSION_SOURCES}\"\n  \"\"\n  libpaddleaudio\n  \"${LIBPADDLEAUDIO_COMPILE_DEFINITIONS}\"\n  )\n# if(BUILD_CTC_DECODER)\n#   set(\n#     DECODER_EXTENSION_SOURCES\n#     decoder/bindings/pybind.cpp\n#     )\n#   define_extension(\n#     _paddleaudio_decoder\n#     \"${DECODER_EXTENSION_SOURCES}\"\n#     \"\"\n#     \"libpaddleaudio_decoder\"\n#     \"${LIBPADDLEAUDIO_DECODER_DEFINITIONS}\"\n#     )\n# endif()\n# if(USE_FFMPEG)\n#   set(\n#     FFMPEG_EXTENSION_SOURCES\n#     ffmpeg/pybind/typedefs.cpp\n#     ffmpeg/pybind/pybind.cpp\n#     ffmpeg/pybind/stream_reader.cpp\n#     )\n#   define_extension(\n#     _paddleaudio_ffmpeg\n#     \"${FFMPEG_EXTENSION_SOURCES}\"\n#     \"${FFMPEG_INCLUDE_DIRS}\"\n#     \"libpaddleaudio_ffmpeg\"\n#     \"${LIBPADDLEAUDIO_DECODER_DEFINITIONS}\"\n#     )\n# endif()\nendif()\n"
  },
  {
    "path": "audio/paddleaudio/src/optional/COPYING",
    "content": "Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS\n    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM\n    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED\n    HEREUNDER.\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator\nand subsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for\nthe purpose of contributing to a commons of creative, cultural and\nscientific works (\"Commons\") that the public can reliably and without fear\nof later claims of infringement build upon, modify, incorporate in other\nworks, reuse and redistribute as freely as possible in any form whatsoever\nand for any purposes, including without limitation commercial purposes.\nThese owners may contribute to the Commons to promote the ideal of a free\nculture and the further production of creative, cultural and scientific\nworks, or to gain reputation or greater distribution for their Work in\npart through the use and efforts of others.\n\nFor these and/or other purposes and motivations, and without any\nexpectation of additional consideration or compensation, the person\nassociating CC0 with a Work (the \"Affirmer\"), to the extent that he or she\nis an owner of Copyright and Related Rights in the Work, voluntarily\nelects to apply CC0 to the Work and publicly distribute the Work under its\nterms, with knowledge of his or her Copyright and Related Rights in the\nWork and the meaning and intended legal effect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not\nlimited to, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display,\n     communicate, and translate a Work;\n ii. moral rights retained by the original author(s) and/or performer(s);\niii. publicity and privacy rights pertaining to a person's image or\n     likeness depicted in a Work;\n iv. rights protecting against unfair competition in regards to a Work,\n     subject to the limitations in paragraph 4(a), below;\n  v. rights protecting the extraction, dissemination, use and reuse of data\n     in a Work;\n vi. database rights (such as those arising under Directive 96/9/EC of the\n     European Parliament and of the Council of 11 March 1996 on the legal\n     protection of databases, and under any national implementation\n     thereof, including any amended or successor version of such\n     directive); and\nvii. other similar, equivalent or corresponding rights throughout the\n     world based on applicable law or treaty, and any national\n     implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention\nof, applicable law, Affirmer hereby overtly, fully, permanently,\nirrevocably and unconditionally waives, abandons, and surrenders all of\nAffirmer's Copyright and Related Rights and associated claims and causes\nof action, whether now known or unknown (including existing as well as\nfuture claims and causes of action), in the Work (i) in all territories\nworldwide, (ii) for the maximum duration provided by applicable law or\ntreaty (including future time extensions), (iii) in any current or future\nmedium and for any number of copies, and (iv) for any purpose whatsoever,\nincluding without limitation commercial, advertising or promotional\npurposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each\nmember of the public at large and to the detriment of Affirmer's heirs and\nsuccessors, fully intending that such Waiver shall not be subject to\nrevocation, rescission, cancellation, termination, or any other legal or\nequitable action to disrupt the quiet enjoyment of the Work by the public\nas contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason\nbe judged legally invalid or ineffective under applicable law, then the\nWaiver shall be preserved to the maximum extent permitted taking into\naccount Affirmer's express Statement of Purpose. In addition, to the\nextent the Waiver is so judged Affirmer hereby grants to each affected\nperson a royalty-free, non transferable, non sublicensable, non exclusive,\nirrevocable and unconditional license to exercise Affirmer's Copyright and\nRelated Rights in the Work (i) in all territories worldwide, (ii) for the\nmaximum duration provided by applicable law or treaty (including future\ntime extensions), (iii) in any current or future medium and for any number\nof copies, and (iv) for any purpose whatsoever, including without\nlimitation commercial, advertising or promotional purposes (the\n\"License\"). The License shall be deemed effective as of the date CC0 was\napplied by Affirmer to the Work. Should any part of the License for any\nreason be judged legally invalid or ineffective under applicable law, such\npartial invalidity or ineffectiveness shall not invalidate the remainder\nof the License, and in such case Affirmer hereby affirms that he or she\nwill not (i) exercise any of his or her remaining Copyright and Related\nRights in the Work or (ii) assert any associated claims and causes of\naction with respect to the Work, in either case contrary to Affirmer's\nexpress Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n a. No trademark or patent rights held by Affirmer are waived, abandoned,\n    surrendered, licensed or otherwise affected by this document.\n b. Affirmer offers the Work as-is and makes no representations or\n    warranties of any kind concerning the Work, express, implied,\n    statutory or otherwise, including without limitation warranties of\n    title, merchantability, fitness for a particular purpose, non\n    infringement, or the absence of latent or other defects, accuracy, or\n    the present or absence of errors, whether or not discoverable, all to\n    the greatest extent permissible under applicable law.\n c. Affirmer disclaims responsibility for clearing rights of other persons\n    that may apply to the Work or any use thereof, including without\n    limitation any person's Copyright and Related Rights in the Work.\n    Further, Affirmer disclaims responsibility for obtaining any necessary\n    consents, permissions or other rights required for any use of the\n    Work.\n d. Affirmer understands and acknowledges that Creative Commons is not a\n    party to this document and has no duty or obligation with respect to\n    this CC0 or use of the Work.\n"
  },
  {
    "path": "audio/paddleaudio/src/optional/optional.hpp",
    "content": "\n///\n// optional - An implementation of std::optional with extensions\n// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)\n//\n// Documentation available at https://tl.tartanllama.xyz/\n//\n// To the extent possible under law, the author(s) have dedicated all\n// copyright and related and neighboring rights to this software to the\n// public domain worldwide. This software is distributed without any warranty.\n//\n// You should have received a copy of the CC0 Public Domain Dedication\n// along with this software. If not, see\n// <http://creativecommons.org/publicdomain/zero/1.0/>.\n// https://github.com/TartanLlama/optional\n///\n\n#ifndef TL_OPTIONAL_HPP\n#define TL_OPTIONAL_HPP\n\n#define TL_OPTIONAL_VERSION_MAJOR 1\n#define TL_OPTIONAL_VERSION_MINOR 0\n#define TL_OPTIONAL_VERSION_PATCH 0\n\n#include <exception>\n#include <functional>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#if (defined(_MSC_VER) && _MSC_VER == 1900)\n#define TL_OPTIONAL_MSVC2015\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC49\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC54\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \\\n     !defined(__clang__))\n#define TL_OPTIONAL_GCC55\n#endif\n\n#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \\\n     !defined(__clang__))\n// GCC < 5 doesn't support overloading on const&& for member functions\n#define TL_OPTIONAL_NO_CONSTRR\n\n// GCC < 5 doesn't support some standard C++11 type traits\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \\\n    std::has_trivial_copy_constructor<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \\\n    std::has_trivial_copy_assign<T>::value\n\n// This one will be different for GCC 5.7 if it's ever supported\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \\\n    std::is_trivially_destructible<T>::value\n\n// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks\n// std::vector\n// for non-copyable types\n#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))\n#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\n#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX\nnamespace tl {\nnamespace detail {\ntemplate <class T>\nstruct is_trivially_copy_constructible\n    : std::is_trivially_copy_constructible<T> {};\n#ifdef _GLIBCXX_VECTOR\ntemplate <class T, class A>\nstruct is_trivially_copy_constructible<std::vector<T, A>>\n    : std::is_trivially_copy_constructible<T> {};\n#endif\n}\n}\n#endif\n\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \\\n    tl::detail::is_trivially_copy_constructible<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \\\n    std::is_trivially_copy_assignable<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \\\n    std::is_trivially_destructible<T>::value\n#else\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \\\n    std::is_trivially_copy_constructible<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \\\n    std::is_trivially_copy_assignable<T>::value\n#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \\\n    std::is_trivially_destructible<T>::value\n#endif\n\n#if __cplusplus > 201103L\n#define TL_OPTIONAL_CXX14\n#endif\n\n// constexpr implies const in C++11, not C++14\n#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \\\n     defined(TL_OPTIONAL_GCC49))\n#define TL_OPTIONAL_11_CONSTEXPR\n#else\n#define TL_OPTIONAL_11_CONSTEXPR constexpr\n#endif\n\nnamespace tl {\n#ifndef TL_MONOSTATE_INPLACE_MUTEX\n#define TL_MONOSTATE_INPLACE_MUTEX\n/// Used to represent an optional with no data; essentially a bool\nclass monostate {};\n\n///  A tag type to tell optional to construct its value in-place\nstruct in_place_t {\n    explicit in_place_t() = default;\n};\n/// A tag to tell optional to construct its value in-place\nstatic constexpr in_place_t in_place{};\n#endif\n\ntemplate <class T>\nclass optional;\n\nnamespace detail {\n#ifndef TL_TRAITS_MUTEX\n#define TL_TRAITS_MUTEX\n// C++14-style aliases for brevity\ntemplate <class T>\nusing remove_const_t = typename std::remove_const<T>::type;\ntemplate <class T>\nusing remove_reference_t = typename std::remove_reference<T>::type;\ntemplate <class T>\nusing decay_t = typename std::decay<T>::type;\ntemplate <bool E, class T = void>\nusing enable_if_t = typename std::enable_if<E, T>::type;\ntemplate <bool B, class T, class F>\nusing conditional_t = typename std::conditional<B, T, F>::type;\n\n// std::conjunction from C++17\ntemplate <class...>\nstruct conjunction : std::true_type {};\ntemplate <class B>\nstruct conjunction<B> : B {};\ntemplate <class B, class... Bs>\nstruct conjunction<B, Bs...>\n    : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};\n\n#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L\n#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\n#endif\n\n// In C++11 mode, there's an issue in libc++'s std::mem_fn\n// which results in a hard-error when using it in a noexcept expression\n// in some cases. This is a check to workaround the common failing case.\n#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\ntemplate <class T>\nstruct is_pointer_to_non_const_member_func : std::false_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &>\n    : std::true_type {};\ntemplate <class T, class Ret, class... Args>\nstruct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&>\n    : std::true_type {};\n\ntemplate <class T>\nstruct is_const_or_const_ref : std::false_type {};\ntemplate <class T>\nstruct is_const_or_const_ref<T const &> : std::true_type {};\ntemplate <class T>\nstruct is_const_or_const_ref<T const> : std::true_type {};\n#endif\n\n// std::invoke from C++17\n// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround\ntemplate <\n    typename Fn,\n    typename... Args,\n#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND\n    typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value &&\n                             is_const_or_const_ref<Args...>::value)>,\n#endif\n    typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,\n    int = 0>\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\n    noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))\n    -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {\n    return std::mem_fn(f)(std::forward<Args>(args)...);\n}\n\ntemplate <typename Fn,\n          typename... Args,\n          typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>\nconstexpr auto invoke(Fn &&f, Args &&... args) noexcept(\n    noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))\n    -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {\n    return std::forward<Fn>(f)(std::forward<Args>(args)...);\n}\n\n// std::invoke_result from C++17\ntemplate <class F, class, class... Us>\nstruct invoke_result_impl;\n\ntemplate <class F, class... Us>\nstruct invoke_result_impl<\n    F,\n    decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),\n    Us...> {\n    using type =\n        decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));\n};\n\ntemplate <class F, class... Us>\nusing invoke_result = invoke_result_impl<F, void, Us...>;\n\ntemplate <class F, class... Us>\nusing invoke_result_t = typename invoke_result<F, Us...>::type;\n\n#if defined(_MSC_VER) && _MSC_VER <= 1900\n// TODO make a version which works with MSVC 2015\ntemplate <class T, class U = T>\nstruct is_swappable : std::true_type {};\n\ntemplate <class T, class U = T>\nstruct is_nothrow_swappable : std::true_type {};\n#else\n// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept\nnamespace swap_adl_tests {\n// if swap ADL finds this then it would call std::swap otherwise (same\n// signature)\nstruct tag {};\n\ntemplate <class T>\ntag swap(T &, T &);\ntemplate <class T, std::size_t N>\ntag swap(T (&a)[N], T (&b)[N]);\n\n// helper functions to test if an unqualified swap is possible, and if it\n// becomes std::swap\ntemplate <class, class>\nstd::false_type can_swap(...) noexcept(false);\ntemplate <class T,\n          class U,\n          class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>\nstd::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),\n                                                    std::declval<U &>())));\n\ntemplate <class, class>\nstd::false_type uses_std(...);\ntemplate <class T, class U>\nstd::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>\nuses_std(int);\n\ntemplate <class T>\nstruct is_std_swap_noexcept\n    : std::integral_constant<bool,\n                             std::is_nothrow_move_constructible<T>::value &&\n                                 std::is_nothrow_move_assignable<T>::value> {};\n\ntemplate <class T, std::size_t N>\nstruct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};\n\ntemplate <class T, class U>\nstruct is_adl_swap_noexcept\n    : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};\n}  // namespace swap_adl_tests\n\ntemplate <class T, class U = T>\nstruct is_swappable\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&\n              (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||\n               (std::is_move_assignable<T>::value &&\n                std::is_move_constructible<T>::value))> {};\n\ntemplate <class T, std::size_t N>\nstruct is_swappable<T[N], T[N]>\n    : std::integral_constant<\n          bool,\n          decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&\n              (!decltype(\n                   detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||\n               is_swappable<T, T>::value)> {};\n\ntemplate <class T, class U = T>\nstruct is_nothrow_swappable\n    : std::integral_constant<\n          bool,\n          is_swappable<T, U>::value &&\n              ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value\n                    &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||\n               (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&\n                    detail::swap_adl_tests::is_adl_swap_noexcept<T,\n                                                                 U>::value))> {\n};\n#endif\n#endif\n\n// std::void_t from C++17\ntemplate <class...>\nstruct voider {\n    using type = void;\n};\ntemplate <class... Ts>\nusing void_t = typename voider<Ts...>::type;\n\n// Trait for checking if a type is a tl::optional\ntemplate <class T>\nstruct is_optional_impl : std::false_type {};\ntemplate <class T>\nstruct is_optional_impl<optional<T>> : std::true_type {};\ntemplate <class T>\nusing is_optional = is_optional_impl<decay_t<T>>;\n\n// Change void to tl::monostate\ntemplate <class U>\nusing fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;\n\ntemplate <class F, class U, class = invoke_result_t<F, U>>\nusing get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;\n\n// Check if invoking F for some Us returns void\ntemplate <class F, class = void, class... U>\nstruct returns_void_impl;\ntemplate <class F, class... U>\nstruct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>\n    : std::is_void<invoke_result_t<F, U...>> {};\ntemplate <class F, class... U>\nusing returns_void = returns_void_impl<F, void, U...>;\n\ntemplate <class T, class... U>\nusing enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;\n\ntemplate <class T, class... U>\nusing disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;\n\ntemplate <class T, class U>\nusing enable_forward_value =\n    detail::enable_if_t<std::is_constructible<T, U &&>::value &&\n                        !std::is_same<detail::decay_t<U>, in_place_t>::value &&\n                        !std::is_same<optional<T>, detail::decay_t<U>>::value>;\n\ntemplate <class T, class U, class Other>\nusing enable_from_other = detail::enable_if_t<\n    std::is_constructible<T, Other>::value &&\n    !std::is_constructible<T, optional<U> &>::value &&\n    !std::is_constructible<T, optional<U> &&>::value &&\n    !std::is_constructible<T, const optional<U> &>::value &&\n    !std::is_constructible<T, const optional<U> &&>::value &&\n    !std::is_convertible<optional<U> &, T>::value &&\n    !std::is_convertible<optional<U> &&, T>::value &&\n    !std::is_convertible<const optional<U> &, T>::value &&\n    !std::is_convertible<const optional<U> &&, T>::value>;\n\ntemplate <class T, class U>\nusing enable_assign_forward = detail::enable_if_t<\n    !std::is_same<optional<T>, detail::decay_t<U>>::value &&\n    !detail::conjunction<std::is_scalar<T>,\n                         std::is_same<T, detail::decay_t<U>>>::value &&\n    std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;\n\ntemplate <class T, class U, class Other>\nusing enable_assign_from_other = detail::enable_if_t<\n    std::is_constructible<T, Other>::value &&\n    std::is_assignable<T &, Other>::value &&\n    !std::is_constructible<T, optional<U> &>::value &&\n    !std::is_constructible<T, optional<U> &&>::value &&\n    !std::is_constructible<T, const optional<U> &>::value &&\n    !std::is_constructible<T, const optional<U> &&>::value &&\n    !std::is_convertible<optional<U> &, T>::value &&\n    !std::is_convertible<optional<U> &&, T>::value &&\n    !std::is_convertible<const optional<U> &, T>::value &&\n    !std::is_convertible<const optional<U> &&, T>::value &&\n    !std::is_assignable<T &, optional<U> &>::value &&\n    !std::is_assignable<T &, optional<U> &&>::value &&\n    !std::is_assignable<T &, const optional<U> &>::value &&\n    !std::is_assignable<T &, const optional<U> &&>::value>;\n\n// The storage base manages the actual storage, and correctly propagates\n// trivial destruction from T. This case is for when T is not trivially\n// destructible.\ntemplate <class T, bool = ::std::is_trivially_destructible<T>::value>\nstruct optional_storage_base {\n    TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept\n        : m_dummy(),\n          m_has_value(false) {}\n\n    template <class... U>\n    TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)\n        : m_value(std::forward<U>(u)...), m_has_value(true) {}\n\n    ~optional_storage_base() {\n        if (m_has_value) {\n            m_value.~T();\n            m_has_value = false;\n        }\n    }\n\n    struct dummy {};\n    union {\n        dummy m_dummy;\n        T m_value;\n    };\n\n    bool m_has_value;\n};\n\n// This case is for when T is trivially destructible.\ntemplate <class T>\nstruct optional_storage_base<T, true> {\n    TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept\n        : m_dummy(),\n          m_has_value(false) {}\n\n    template <class... U>\n    TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)\n        : m_value(std::forward<U>(u)...), m_has_value(true) {}\n\n    // No destructor, so this class is trivially destructible\n\n    struct dummy {};\n    union {\n        dummy m_dummy;\n        T m_value;\n    };\n\n    bool m_has_value = false;\n};\n\n// This base class provides some handy member functions which can be used in\n// further derived classes\ntemplate <class T>\nstruct optional_operations_base : optional_storage_base<T> {\n    using optional_storage_base<T>::optional_storage_base;\n\n    void hard_reset() noexcept {\n        get().~T();\n        this->m_has_value = false;\n    }\n\n    template <class... Args>\n    void construct(Args &&... args) noexcept {\n        new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);\n        this->m_has_value = true;\n    }\n\n    template <class Opt>\n    void assign(Opt &&rhs) {\n        if (this->has_value()) {\n            if (rhs.has_value()) {\n                this->m_value = std::forward<Opt>(rhs).get();\n            } else {\n                this->m_value.~T();\n                this->m_has_value = false;\n            }\n        }\n\n        else if (rhs.has_value()) {\n            construct(std::forward<Opt>(rhs).get());\n        }\n    }\n\n    bool has_value() const { return this->m_has_value; }\n\n    TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }\n    TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }\n    TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr const T &&get() const && { return std::move(this->m_value); }\n#endif\n};\n\n// This class manages conditionally having a trivial copy constructor\n// This specialization is for when T is trivially copy constructible\ntemplate <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>\nstruct optional_copy_base : optional_operations_base<T> {\n    using optional_operations_base<T>::optional_operations_base;\n};\n\n// This specialization is for when T is not trivially copy constructible\ntemplate <class T>\nstruct optional_copy_base<T, false> : optional_operations_base<T> {\n    using optional_operations_base<T>::optional_operations_base;\n\n    optional_copy_base() = default;\n    optional_copy_base(const optional_copy_base &rhs)\n        : optional_operations_base<T>() {\n        if (rhs.has_value()) {\n            this->construct(rhs.get());\n        } else {\n            this->m_has_value = false;\n        }\n    }\n\n    optional_copy_base(optional_copy_base &&rhs) = default;\n    optional_copy_base &operator=(const optional_copy_base &rhs) = default;\n    optional_copy_base &operator=(optional_copy_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial move constructor\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_constructible. We\n// have to make do with a non-trivial move constructor even if T is trivially\n// move constructible\n#ifndef TL_OPTIONAL_GCC49\ntemplate <class T, bool = std::is_trivially_move_constructible<T>::value>\nstruct optional_move_base : optional_copy_base<T> {\n    using optional_copy_base<T>::optional_copy_base;\n};\n#else\ntemplate <class T, bool = false>\nstruct optional_move_base;\n#endif\ntemplate <class T>\nstruct optional_move_base<T, false> : optional_copy_base<T> {\n    using optional_copy_base<T>::optional_copy_base;\n\n    optional_move_base() = default;\n    optional_move_base(const optional_move_base &rhs) = default;\n\n    optional_move_base(optional_move_base &&rhs) noexcept(\n        std::is_nothrow_move_constructible<T>::value) {\n        if (rhs.has_value()) {\n            this->construct(std::move(rhs.get()));\n        } else {\n            this->m_has_value = false;\n        }\n    }\n    optional_move_base &operator=(const optional_move_base &rhs) = default;\n    optional_move_base &operator=(optional_move_base &&rhs) = default;\n};\n\n// This class manages conditionally having a trivial copy assignment operator\ntemplate <class T,\n          bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&\n                 TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&\n                 TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>\nstruct optional_copy_assign_base : optional_move_base<T> {\n    using optional_move_base<T>::optional_move_base;\n};\n\ntemplate <class T>\nstruct optional_copy_assign_base<T, false> : optional_move_base<T> {\n    using optional_move_base<T>::optional_move_base;\n\n    optional_copy_assign_base() = default;\n    optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;\n\n    optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;\n    optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {\n        this->assign(rhs);\n        return *this;\n    }\n    optional_copy_assign_base &operator=(optional_copy_assign_base &&rhs) =\n        default;\n};\n\n// This class manages conditionally having a trivial move assignment operator\n// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it\n// doesn't implement an analogue to std::is_trivially_move_assignable. We have\n// to make do with a non-trivial move assignment operator even if T is trivially\n// move assignable\n#ifndef TL_OPTIONAL_GCC49\ntemplate <class T,\n          bool = std::is_trivially_destructible<T>::value\n              &&std::is_trivially_move_constructible<T>::value\n                  &&std::is_trivially_move_assignable<T>::value>\nstruct optional_move_assign_base : optional_copy_assign_base<T> {\n    using optional_copy_assign_base<T>::optional_copy_assign_base;\n};\n#else\ntemplate <class T, bool = false>\nstruct optional_move_assign_base;\n#endif\n\ntemplate <class T>\nstruct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {\n    using optional_copy_assign_base<T>::optional_copy_assign_base;\n\n    optional_move_assign_base() = default;\n    optional_move_assign_base(const optional_move_assign_base &rhs) = default;\n\n    optional_move_assign_base(optional_move_assign_base &&rhs) = default;\n\n    optional_move_assign_base &operator=(const optional_move_assign_base &rhs) =\n        default;\n\n    optional_move_assign_base &\n    operator=(optional_move_assign_base &&rhs) noexcept(\n        std::is_nothrow_move_constructible<T>::value\n            &&std::is_nothrow_move_assignable<T>::value) {\n        this->assign(std::move(rhs));\n        return *this;\n    }\n};\n\n// optional_delete_ctor_base will conditionally delete copy and move\n// constructors depending on whether T is copy/move constructible\ntemplate <class T,\n          bool EnableCopy = std::is_copy_constructible<T>::value,\n          bool EnableMove = std::is_move_constructible<T>::value>\nstruct optional_delete_ctor_base {\n    optional_delete_ctor_base() = default;\n    optional_delete_ctor_base(const optional_delete_ctor_base &) = default;\n    optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;\n    optional_delete_ctor_base &operator=(const optional_delete_ctor_base &) =\n        default;\n    optional_delete_ctor_base &operator=(\n        optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T>\nstruct optional_delete_ctor_base<T, true, false> {\n    optional_delete_ctor_base() = default;\n    optional_delete_ctor_base(const optional_delete_ctor_base &) = default;\n    optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;\n    optional_delete_ctor_base &operator=(const optional_delete_ctor_base &) =\n        default;\n    optional_delete_ctor_base &operator=(\n        optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T>\nstruct optional_delete_ctor_base<T, false, true> {\n    optional_delete_ctor_base() = default;\n    optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;\n    optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;\n    optional_delete_ctor_base &operator=(const optional_delete_ctor_base &) =\n        default;\n    optional_delete_ctor_base &operator=(\n        optional_delete_ctor_base &&) noexcept = default;\n};\n\ntemplate <class T>\nstruct optional_delete_ctor_base<T, false, false> {\n    optional_delete_ctor_base() = default;\n    optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;\n    optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;\n    optional_delete_ctor_base &operator=(const optional_delete_ctor_base &) =\n        default;\n    optional_delete_ctor_base &operator=(\n        optional_delete_ctor_base &&) noexcept = default;\n};\n\n// optional_delete_assign_base will conditionally delete copy and move\n// constructors depending on whether T is copy/move constructible + assignable\ntemplate <class T,\n          bool EnableCopy = (std::is_copy_constructible<T>::value &&\n                             std::is_copy_assignable<T>::value),\n          bool EnableMove = (std::is_move_constructible<T>::value &&\n                             std::is_move_assignable<T>::value)>\nstruct optional_delete_assign_base {\n    optional_delete_assign_base() = default;\n    optional_delete_assign_base(const optional_delete_assign_base &) = default;\n    optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n        default;\n    optional_delete_assign_base &operator=(\n        const optional_delete_assign_base &) = default;\n    optional_delete_assign_base &operator=(\n        optional_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T>\nstruct optional_delete_assign_base<T, true, false> {\n    optional_delete_assign_base() = default;\n    optional_delete_assign_base(const optional_delete_assign_base &) = default;\n    optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n        default;\n    optional_delete_assign_base &operator=(\n        const optional_delete_assign_base &) = default;\n    optional_delete_assign_base &operator=(\n        optional_delete_assign_base &&) noexcept = delete;\n};\n\ntemplate <class T>\nstruct optional_delete_assign_base<T, false, true> {\n    optional_delete_assign_base() = default;\n    optional_delete_assign_base(const optional_delete_assign_base &) = default;\n    optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n        default;\n    optional_delete_assign_base &operator=(\n        const optional_delete_assign_base &) = delete;\n    optional_delete_assign_base &operator=(\n        optional_delete_assign_base &&) noexcept = default;\n};\n\ntemplate <class T>\nstruct optional_delete_assign_base<T, false, false> {\n    optional_delete_assign_base() = default;\n    optional_delete_assign_base(const optional_delete_assign_base &) = default;\n    optional_delete_assign_base(optional_delete_assign_base &&) noexcept =\n        default;\n    optional_delete_assign_base &operator=(\n        const optional_delete_assign_base &) = delete;\n    optional_delete_assign_base &operator=(\n        optional_delete_assign_base &&) noexcept = delete;\n};\n\n}  // namespace detail\n\n/// A tag type to represent an empty optional\nstruct nullopt_t {\n    struct do_not_use {};\n    constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}\n};\n/// Represents an empty optional\nstatic constexpr nullopt_t nullopt{nullopt_t::do_not_use{},\n                                   nullopt_t::do_not_use{}};\n\nclass bad_optional_access : public std::exception {\n  public:\n    bad_optional_access() = default;\n    const char *what() const noexcept { return \"Optional has no value\"; }\n};\n\n/// An optional object is an object that contains the storage for another\n/// object and manages the lifetime of this contained object, if any. The\n/// contained object may be initialized after the optional object has been\n/// initialized, and may be destroyed before the optional object has been\n/// destroyed. The initialization state of the contained object is tracked by\n/// the optional object.\ntemplate <class T>\nclass optional : private detail::optional_move_assign_base<T>,\n                 private detail::optional_delete_ctor_base<T>,\n                 private detail::optional_delete_assign_base<T> {\n    using base = detail::optional_move_assign_base<T>;\n\n    static_assert(!std::is_same<T, in_place_t>::value,\n                  \"instantiation of optional with in_place_t is ill-formed\");\n    static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,\n                  \"instantiation of optional with nullopt_t is ill-formed\");\n\n  public:\n// The different versions for C++14 and 11 are needed because deduced return\n// types are not SFINAE-safe. This provides better support for things like\n// generic lambdas. C.f.\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n    /// Carries out some operation which returns an optional on the stored\n    /// object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {\n        using result = detail::invoke_result_t<F, T &&>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : result(nullopt);\n    }\n\n    template <class F>\n    constexpr auto and_then(F &&f) const & {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr auto and_then(F &&f) const && {\n        using result = detail::invoke_result_t<F, const T &&>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : result(nullopt);\n    }\n#endif\n#else\n    /// Carries out some operation which returns an optional on the stored\n    /// object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(\n        F &&f) && {\n        using result = detail::invoke_result_t<F, T &&>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : result(nullopt);\n    }\n\n    template <class F>\n    constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {\n        using result = detail::invoke_result_t<F, const T &&>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : result(nullopt);\n    }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto map(F &&f) const & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto map(F &&f) const && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#else\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(\n        optional_map_impl(std::declval<optional &>(), std::declval<F &&>()))\n    map(F &&f) & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(\n        optional_map_impl(std::declval<optional &&>(), std::declval<F &&>()))\n    map(F &&f) && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr decltype(optional_map_impl(std::declval<const optional &>(),\n                                         std::declval<F &&>()))\n    map(F &&f) const & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr decltype(optional_map_impl(std::declval<const optional &&>(),\n                                         std::declval<F &&>()))\n    map(F &&f) const && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto transform(F &&f) & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto transform(F &&f) && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto transform(F &&f) const & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto transform(F &&f) const && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#else\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(\n        optional_map_impl(std::declval<optional &>(), std::declval<F &&>()))\n    transform(F &&f) & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(\n        optional_map_impl(std::declval<optional &&>(), std::declval<F &&>()))\n    transform(F &&f) && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr decltype(optional_map_impl(std::declval<const optional &>(),\n                                         std::declval<F &&>()))\n    transform(F &&f) const & {\n        return optional_map_impl(*this, std::forward<F>(f));\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr decltype(optional_map_impl(std::declval<const optional &&>(),\n                                         std::declval<F &&>()))\n    transform(F &&f) const && {\n        return optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#endif\n#endif\n\n    /// Calls `f` if the optional is empty\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n        if (has_value()) return *this;\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n        return has_value() ? *this : std::forward<F>(f)();\n    }\n\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) && {\n        if (has_value()) return std::move(*this);\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {\n        return has_value() ? std::move(*this) : std::forward<F>(f)();\n    }\n\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const & {\n        if (has_value()) return *this;\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {\n        return has_value() ? *this : std::forward<F>(f)();\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const && {\n        if (has_value()) return std::move(*this);\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const && {\n        return has_value() ? std::move(*this) : std::forward<F>(f)();\n    }\n#endif\n\n    /// Maps the stored value with `f` if there is one, otherwise returns `u`.\n    template <class F, class U>\n    U map_or(F &&f, U &&u) & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u);\n    }\n\n    template <class F, class U>\n    U map_or(F &&f, U &&u) && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u);\n    }\n\n    template <class F, class U>\n    U map_or(F &&f, U &&u) const & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, class U>\n    U map_or(F &&f, U &&u) const && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u);\n    }\n#endif\n\n    /// Maps the stored value with `f` if there is one, otherwise calls\n    /// `u` and returns the result.\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u)();\n    }\n\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u)();\n    }\n\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u)();\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u)();\n    }\n#endif\n\n    /// Returns `u` if `*this` has a value, otherwise an empty optional.\n    template <class U>\n    constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {\n        using result = optional<detail::decay_t<U>>;\n        return has_value() ? result{u} : result{nullopt};\n    }\n\n    /// Returns `rhs` if `*this` is empty, otherwise the current value.\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {\n        return has_value() ? *this : rhs;\n    }\n\n    constexpr optional disjunction(const optional &rhs) const & {\n        return has_value() ? *this : rhs;\n    }\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {\n        return has_value() ? std::move(*this) : rhs;\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr optional disjunction(const optional &rhs) const && {\n        return has_value() ? std::move(*this) : rhs;\n    }\n#endif\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {\n        return has_value() ? *this : std::move(rhs);\n    }\n\n    constexpr optional disjunction(optional &&rhs) const & {\n        return has_value() ? *this : std::move(rhs);\n    }\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {\n        return has_value() ? std::move(*this) : std::move(rhs);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr optional disjunction(optional &&rhs) const && {\n        return has_value() ? std::move(*this) : std::move(rhs);\n    }\n#endif\n\n    /// Takes the value out of the optional, leaving it empty\n    optional take() {\n        optional ret = std::move(*this);\n        reset();\n        return ret;\n    }\n\n    using value_type = T;\n\n    /// Constructs an optional that does not contain a value.\n    constexpr optional() noexcept = default;\n\n    constexpr optional(nullopt_t) noexcept {}\n\n    /// Copy constructor\n    ///\n    /// If `rhs` contains a value, the stored value is direct-initialized with\n    /// it. Otherwise, the constructed optional is empty.\n    TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default;\n\n    /// Move constructor\n    ///\n    /// If `rhs` contains a value, the stored value is direct-initialized with\n    /// it. Otherwise, the constructed optional is empty.\n    TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;\n\n    /// Constructs the stored value in-place using the given arguments.\n    template <class... Args>\n    constexpr explicit optional(\n        detail::enable_if_t<std::is_constructible<T, Args...>::value,\n                            in_place_t>,\n        Args &&... args)\n        : base(in_place, std::forward<Args>(args)...) {}\n\n    template <class U, class... Args>\n    TL_OPTIONAL_11_CONSTEXPR explicit optional(\n        detail::enable_if_t<std::is_constructible<T,\n                                                  std::initializer_list<U> &,\n                                                  Args &&...>::value,\n                            in_place_t>,\n        std::initializer_list<U> il,\n        Args &&... args) {\n        this->construct(il, std::forward<Args>(args)...);\n    }\n\n    /// Constructs the stored value with `u`.\n    template <\n        class U = T,\n        detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,\n        detail::enable_forward_value<T, U> * = nullptr>\n    constexpr optional(U &&u) : base(in_place, std::forward<U>(u)) {}\n\n    template <\n        class U = T,\n        detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,\n        detail::enable_forward_value<T, U> * = nullptr>\n    constexpr explicit optional(U &&u) : base(in_place, std::forward<U>(u)) {}\n\n    /// Converting copy constructor.\n    template <class U,\n              detail::enable_from_other<T, U, const U &> * = nullptr,\n              detail::enable_if_t<std::is_convertible<const U &, T>::value> * =\n                  nullptr>\n    optional(const optional<U> &rhs) {\n        if (rhs.has_value()) {\n            this->construct(*rhs);\n        }\n    }\n\n    template <class U,\n              detail::enable_from_other<T, U, const U &> * = nullptr,\n              detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =\n                  nullptr>\n    explicit optional(const optional<U> &rhs) {\n        if (rhs.has_value()) {\n            this->construct(*rhs);\n        }\n    }\n\n    /// Converting move constructor.\n    template <\n        class U,\n        detail::enable_from_other<T, U, U &&> * = nullptr,\n        detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>\n    optional(optional<U> &&rhs) {\n        if (rhs.has_value()) {\n            this->construct(std::move(*rhs));\n        }\n    }\n\n    template <\n        class U,\n        detail::enable_from_other<T, U, U &&> * = nullptr,\n        detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr>\n    explicit optional(optional<U> &&rhs) {\n        if (rhs.has_value()) {\n            this->construct(std::move(*rhs));\n        }\n    }\n\n    /// Destroys the stored value if there is one.\n    ~optional() = default;\n\n    /// Assignment to empty.\n    ///\n    /// Destroys the current value if there is one.\n    optional &operator=(nullopt_t) noexcept {\n        if (has_value()) {\n            this->m_value.~T();\n            this->m_has_value = false;\n        }\n\n        return *this;\n    }\n\n    /// Copy assignment.\n    ///\n    /// Copies the value from `rhs` if there is one. Otherwise resets the stored\n    /// value in `*this`.\n    optional &operator=(const optional &rhs) = default;\n\n    /// Move assignment.\n    ///\n    /// Moves the value from `rhs` if there is one. Otherwise resets the stored\n    /// value in `*this`.\n    optional &operator=(optional &&rhs) = default;\n\n    /// Assigns the stored value from `u`, destroying the old value if there was\n    /// one.\n    template <class U = T, detail::enable_assign_forward<T, U> * = nullptr>\n    optional &operator=(U &&u) {\n        if (has_value()) {\n            this->m_value = std::forward<U>(u);\n        } else {\n            this->construct(std::forward<U>(u));\n        }\n\n        return *this;\n    }\n\n    /// Converting copy assignment operator.\n    ///\n    /// Copies the value from `rhs` if there is one. Otherwise resets the stored\n    /// value in `*this`.\n    template <class U,\n              detail::enable_assign_from_other<T, U, const U &> * = nullptr>\n    optional &operator=(const optional<U> &rhs) {\n        if (has_value()) {\n            if (rhs.has_value()) {\n                this->m_value = *rhs;\n            } else {\n                this->hard_reset();\n            }\n        }\n\n        if (rhs.has_value()) {\n            this->construct(*rhs);\n        }\n\n        return *this;\n    }\n\n    // TODO check exception guarantee\n    /// Converting move assignment operator.\n    ///\n    /// Moves the value from `rhs` if there is one. Otherwise resets the stored\n    /// value in `*this`.\n    template <class U, detail::enable_assign_from_other<T, U, U> * = nullptr>\n    optional &operator=(optional<U> &&rhs) {\n        if (has_value()) {\n            if (rhs.has_value()) {\n                this->m_value = std::move(*rhs);\n            } else {\n                this->hard_reset();\n            }\n        }\n\n        if (rhs.has_value()) {\n            this->construct(std::move(*rhs));\n        }\n\n        return *this;\n    }\n\n    /// Constructs the value in-place, destroying the current one if there is\n    /// one.\n    template <class... Args>\n    T &emplace(Args &&... args) {\n        static_assert(std::is_constructible<T, Args &&...>::value,\n                      \"T must be constructible with Args\");\n\n        *this = nullopt;\n        this->construct(std::forward<Args>(args)...);\n        return value();\n    }\n\n    template <class U, class... Args>\n    detail::enable_if_t<\n        std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,\n        T &>\n    emplace(std::initializer_list<U> il, Args &&... args) {\n        *this = nullopt;\n        this->construct(il, std::forward<Args>(args)...);\n        return value();\n    }\n\n    /// Swaps this optional with the other.\n    ///\n    /// If neither optionals have a value, nothing happens.\n    /// If both have a value, the values are swapped.\n    /// If one has a value, it is moved to the other and the movee is left\n    /// valueless.\n    void swap(optional &rhs) noexcept(\n        std::is_nothrow_move_constructible<T>::value\n            &&detail::is_nothrow_swappable<T>::value) {\n        using std::swap;\n        if (has_value()) {\n            if (rhs.has_value()) {\n                swap(**this, *rhs);\n            } else {\n                new (std::addressof(rhs.m_value)) T(std::move(this->m_value));\n                this->m_value.T::~T();\n            }\n        } else if (rhs.has_value()) {\n            new (std::addressof(this->m_value)) T(std::move(rhs.m_value));\n            rhs.m_value.T::~T();\n        }\n        swap(this->m_has_value, rhs.m_has_value);\n    }\n\n    /// Returns a pointer to the stored value\n    constexpr const T *operator->() const {\n        return std::addressof(this->m_value);\n    }\n\n    TL_OPTIONAL_11_CONSTEXPR T *operator->() {\n        return std::addressof(this->m_value);\n    }\n\n    /// Returns the stored value\n    TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }\n\n    constexpr const T &operator*() const & { return this->m_value; }\n\n    TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {\n        return std::move(this->m_value);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr const T &&operator*() const && {\n        return std::move(this->m_value);\n    }\n#endif\n\n    /// Returns whether or not the optional has a value\n    constexpr bool has_value() const noexcept { return this->m_has_value; }\n\n    constexpr explicit operator bool() const noexcept {\n        return this->m_has_value;\n    }\n\n    /// Returns the contained value if there is one, otherwise throws\n    /// bad_optional_access\n    TL_OPTIONAL_11_CONSTEXPR T &value() & {\n        if (has_value()) return this->m_value;\n        throw bad_optional_access();\n    }\n    TL_OPTIONAL_11_CONSTEXPR const T &value() const & {\n        if (has_value()) return this->m_value;\n        throw bad_optional_access();\n    }\n    TL_OPTIONAL_11_CONSTEXPR T &&value() && {\n        if (has_value()) return std::move(this->m_value);\n        throw bad_optional_access();\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {\n        if (has_value()) return std::move(this->m_value);\n        throw bad_optional_access();\n    }\n#endif\n\n    /// Returns the stored value if there is one, otherwise returns `u`\n    template <class U>\n    constexpr T value_or(U &&u) const & {\n        static_assert(std::is_copy_constructible<T>::value &&\n                          std::is_convertible<U &&, T>::value,\n                      \"T must be copy constructible and convertible from U\");\n        return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n    }\n\n    template <class U>\n    TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {\n        static_assert(std::is_move_constructible<T>::value &&\n                          std::is_convertible<U &&, T>::value,\n                      \"T must be move constructible and convertible from U\");\n        return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n    }\n\n    /// Destroys the stored value if one exists, making the optional empty\n    void reset() noexcept {\n        if (has_value()) {\n            this->m_value.~T();\n            this->m_has_value = false;\n        }\n    }\n};  // namespace tl\n\n/// Compares two optional objects\ntemplate <class T, class U>\ninline constexpr bool operator==(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n    return lhs.has_value() == rhs.has_value() &&\n           (!lhs.has_value() || *lhs == *rhs);\n}\ntemplate <class T, class U>\ninline constexpr bool operator!=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n    return lhs.has_value() != rhs.has_value() ||\n           (lhs.has_value() && *lhs != *rhs);\n}\ntemplate <class T, class U>\ninline constexpr bool operator<(const optional<T> &lhs,\n                                const optional<U> &rhs) {\n    return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);\n}\ntemplate <class T, class U>\ninline constexpr bool operator>(const optional<T> &lhs,\n                                const optional<U> &rhs) {\n    return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);\n}\ntemplate <class T, class U>\ninline constexpr bool operator<=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n    return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);\n}\ntemplate <class T, class U>\ninline constexpr bool operator>=(const optional<T> &lhs,\n                                 const optional<U> &rhs) {\n    return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);\n}\n\n/// Compares an optional to a `nullopt`\ntemplate <class T>\ninline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {\n    return !lhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {\n    return !rhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {\n    return lhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {\n    return rhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {\n    return false;\n}\ntemplate <class T>\ninline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {\n    return rhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {\n    return !lhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {\n    return true;\n}\ntemplate <class T>\ninline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {\n    return lhs.has_value();\n}\ntemplate <class T>\ninline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {\n    return false;\n}\ntemplate <class T>\ninline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {\n    return true;\n}\ntemplate <class T>\ninline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {\n    return !rhs.has_value();\n}\n\n/// Compares the optional with a value.\ntemplate <class T, class U>\ninline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs == rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs == *rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs != rhs : true;\n}\ntemplate <class T, class U>\ninline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs != *rhs : true;\n}\ntemplate <class T, class U>\ninline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs < rhs : true;\n}\ntemplate <class T, class U>\ninline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs < *rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs <= rhs : true;\n}\ntemplate <class T, class U>\ninline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs <= *rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs > rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs > *rhs : true;\n}\ntemplate <class T, class U>\ninline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {\n    return lhs.has_value() ? *lhs >= rhs : false;\n}\ntemplate <class T, class U>\ninline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {\n    return rhs.has_value() ? lhs >= *rhs : true;\n}\n\ntemplate <class T,\n          detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,\n          detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>\nvoid swap(optional<T> &lhs,\n          optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {\n    return lhs.swap(rhs);\n}\n\nnamespace detail {\nstruct i_am_secret {};\n}  // namespace detail\n\ntemplate <class T = detail::i_am_secret,\n          class U,\n          class Ret =\n              detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,\n                                    detail::decay_t<U>,\n                                    T>>\ninline constexpr optional<Ret> make_optional(U &&v) {\n    return optional<Ret>(std::forward<U>(v));\n}\n\ntemplate <class T, class... Args>\ninline constexpr optional<T> make_optional(Args &&... args) {\n    return optional<T>(in_place, std::forward<Args>(args)...);\n}\ntemplate <class T, class U, class... Args>\ninline constexpr optional<T> make_optional(std::initializer_list<U> il,\n                                           Args &&... args) {\n    return optional<T>(in_place, il, std::forward<Args>(args)...);\n}\n\n#if __cplusplus >= 201703L\ntemplate <class T>\noptional(T)->optional<T>;\n#endif\n\n/// \\exclude\nnamespace detail {\n#ifdef TL_OPTIONAL_CXX14\ntemplate <class Opt,\n          class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\nconstexpr auto optional_map_impl(Opt &&opt, F &&f) {\n    return opt.has_value()\n               ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))\n               : optional<Ret>(nullopt);\n}\n\ntemplate <class Opt,\n          class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\nauto optional_map_impl(Opt &&opt, F &&f) {\n    if (opt.has_value()) {\n        detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));\n        return make_optional(monostate{});\n    }\n\n    return optional<monostate>(nullopt);\n}\n#else\ntemplate <class Opt,\n          class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>\n\nconstexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {\n    return opt.has_value()\n               ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))\n               : optional<Ret>(nullopt);\n}\n\ntemplate <class Opt,\n          class F,\n          class Ret = decltype(detail::invoke(std::declval<F>(),\n                                              *std::declval<Opt>())),\n          detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>\n\nauto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {\n    if (opt.has_value()) {\n        detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));\n        return monostate{};\n    }\n\n    return nullopt;\n}\n#endif\n}  // namespace detail\n\n/// Specialization for when `T` is a reference. `optional<T&>` acts similarly\n/// to a `T*`, but provides more operations and shows intent more clearly.\ntemplate <class T>\nclass optional<T &> {\n  public:\n// The different versions for C++14 and 11 are needed because deduced return\n// types are not SFINAE-safe. This provides better support for things like\n// generic lambdas. C.f.\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n\n    /// Carries out some operation which returns an optional on the stored\n    /// object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    constexpr auto and_then(F &&f) const & {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr auto and_then(F &&f) const && {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n#endif\n#else\n    /// Carries out some operation which returns an optional on the stored\n    /// object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(\n        F &&f) && {\n        using result = detail::invoke_result_t<F, T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n    template <class F>\n    constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {\n        using result = detail::invoke_result_t<F, const T &>;\n        static_assert(detail::is_optional<result>::value,\n                      \"F must return an optional\");\n\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : result(nullopt);\n    }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto map(F &&f) const & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto map(F &&f) const && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#else\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(\n        std::declval<optional &>(), std::declval<F &&>()))\n    map(F &&f) & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(\n        std::declval<optional &&>(), std::declval<F &&>()))\n    map(F &&f) && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr decltype(detail::optional_map_impl(\n        std::declval<const optional &>(), std::declval<F &&>()))\n    map(F &&f) const & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr decltype(detail::optional_map_impl(\n        std::declval<const optional &&>(), std::declval<F &&>()))\n    map(F &&f) const && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#endif\n#endif\n\n#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \\\n    !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto transform(F &&f) & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR auto transform(F &&f) && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto transform(F &&f) const & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr auto transform(F &&f) const && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#else\n    /// Carries out some operation on the stored object if there is one.\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(\n        std::declval<optional &>(), std::declval<F &&>()))\n    transform(F &&f) & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n    /// \\group map\n    /// \\synopsis template <class F> auto transform(F &&f) &&;\n    template <class F>\n    TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(\n        std::declval<optional &&>(), std::declval<F &&>()))\n    transform(F &&f) && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n\n    template <class F>\n    constexpr decltype(detail::optional_map_impl(\n        std::declval<const optional &>(), std::declval<F &&>()))\n    transform(F &&f) const & {\n        return detail::optional_map_impl(*this, std::forward<F>(f));\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F>\n    constexpr decltype(detail::optional_map_impl(\n        std::declval<const optional &&>(), std::declval<F &&>()))\n    transform(F &&f) const && {\n        return detail::optional_map_impl(std::move(*this), std::forward<F>(f));\n    }\n#endif\n#endif\n\n    /// Calls `f` if the optional is empty\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n        if (has_value()) return *this;\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {\n        return has_value() ? *this : std::forward<F>(f)();\n    }\n\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) && {\n        if (has_value()) return std::move(*this);\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {\n        return has_value() ? std::move(*this) : std::forward<F>(f)();\n    }\n\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const & {\n        if (has_value()) return *this;\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {\n        return has_value() ? *this : std::forward<F>(f)();\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, detail::enable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const && {\n        if (has_value()) return std::move(*this);\n\n        std::forward<F>(f)();\n        return nullopt;\n    }\n\n    template <class F, detail::disable_if_ret_void<F> * = nullptr>\n    optional<T> or_else(F &&f) const && {\n        return has_value() ? std::move(*this) : std::forward<F>(f)();\n    }\n#endif\n\n    /// Maps the stored value with `f` if there is one, otherwise returns `u`\n    template <class F, class U>\n    U map_or(F &&f, U &&u) & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u);\n    }\n\n    template <class F, class U>\n    U map_or(F &&f, U &&u) && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u);\n    }\n\n    template <class F, class U>\n    U map_or(F &&f, U &&u) const & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, class U>\n    U map_or(F &&f, U &&u) const && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u);\n    }\n#endif\n\n    /// Maps the stored value with `f` if there is one, otherwise calls\n    /// `u` and returns the result.\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u)();\n    }\n\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u)();\n    }\n\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {\n        return has_value() ? detail::invoke(std::forward<F>(f), **this)\n                           : std::forward<U>(u)();\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    template <class F, class U>\n    detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {\n        return has_value()\n                   ? detail::invoke(std::forward<F>(f), std::move(**this))\n                   : std::forward<U>(u)();\n    }\n#endif\n\n    /// Returns `u` if `*this` has a value, otherwise an empty optional.\n    template <class U>\n    constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {\n        using result = optional<detail::decay_t<U>>;\n        return has_value() ? result{u} : result{nullopt};\n    }\n\n    /// Returns `rhs` if `*this` is empty, otherwise the current value.\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {\n        return has_value() ? *this : rhs;\n    }\n\n    constexpr optional disjunction(const optional &rhs) const & {\n        return has_value() ? *this : rhs;\n    }\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {\n        return has_value() ? std::move(*this) : rhs;\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr optional disjunction(const optional &rhs) const && {\n        return has_value() ? std::move(*this) : rhs;\n    }\n#endif\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {\n        return has_value() ? *this : std::move(rhs);\n    }\n\n    constexpr optional disjunction(optional &&rhs) const & {\n        return has_value() ? *this : std::move(rhs);\n    }\n\n    TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {\n        return has_value() ? std::move(*this) : std::move(rhs);\n    }\n\n#ifndef TL_OPTIONAL_NO_CONSTRR\n    constexpr optional disjunction(optional &&rhs) const && {\n        return has_value() ? std::move(*this) : std::move(rhs);\n    }\n#endif\n\n    /// Takes the value out of the optional, leaving it empty\n    optional take() {\n        optional ret = std::move(*this);\n        reset();\n        return ret;\n    }\n\n    using value_type = T &;\n\n    /// Constructs an optional that does not contain a value.\n    constexpr optional() noexcept : m_value(nullptr) {}\n\n    constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}\n\n    /// Copy constructor\n    ///\n    /// If `rhs` contains a value, the stored value is direct-initialized with\n    /// it. Otherwise, the constructed optional is empty.\n    TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;\n\n    /// Move constructor\n    ///\n    /// If `rhs` contains a value, the stored value is direct-initialized with\n    /// it. Otherwise, the constructed optional is empty.\n    TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;\n\n    /// Constructs the stored value with `u`.\n    template <class U = T,\n              detail::enable_if_t<\n                  !detail::is_optional<detail::decay_t<U>>::value> * = nullptr>\n    constexpr optional(U &&u) noexcept : m_value(std::addressof(u)) {\n        static_assert(std::is_lvalue_reference<U>::value,\n                      \"U must be an lvalue\");\n    }\n\n    template <class U>\n    constexpr explicit optional(const optional<U> &rhs) noexcept\n        : optional(*rhs) {}\n\n    /// No-op\n    ~optional() = default;\n\n    /// Assignment to empty.\n    ///\n    /// Destroys the current value if there is one.\n    optional &operator=(nullopt_t) noexcept {\n        m_value = nullptr;\n        return *this;\n    }\n\n    /// Copy assignment.\n    ///\n    /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise\n    /// resets the stored value in `*this`.\n    optional &operator=(const optional &rhs) = default;\n\n    /// Rebinds this optional to `u`.\n    template <class U = T,\n              detail::enable_if_t<\n                  !detail::is_optional<detail::decay_t<U>>::value> * = nullptr>\n    optional &operator=(U &&u) {\n        static_assert(std::is_lvalue_reference<U>::value,\n                      \"U must be an lvalue\");\n        m_value = std::addressof(u);\n        return *this;\n    }\n\n    /// Converting copy assignment operator.\n    ///\n    /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise\n    /// resets the stored value in `*this`.\n    template <class U>\n    optional &operator=(const optional<U> &rhs) noexcept {\n        m_value = std::addressof(rhs.value());\n        return *this;\n    }\n\n    /// Rebinds this optional to `u`.\n    template <class U = T,\n              detail::enable_if_t<\n                  !detail::is_optional<detail::decay_t<U>>::value> * = nullptr>\n    optional &emplace(U &&u) noexcept {\n        return *this = std::forward<U>(u);\n    }\n\n    void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }\n\n    /// Returns a pointer to the stored value\n    constexpr const T *operator->() const noexcept { return m_value; }\n\n    TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; }\n\n    /// Returns the stored value\n    TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; }\n\n    constexpr const T &operator*() const noexcept { return *m_value; }\n\n    constexpr bool has_value() const noexcept { return m_value != nullptr; }\n\n    constexpr explicit operator bool() const noexcept {\n        return m_value != nullptr;\n    }\n\n    /// Returns the contained value if there is one, otherwise throws\n    /// bad_optional_access\n    TL_OPTIONAL_11_CONSTEXPR T &value() {\n        if (has_value()) return *m_value;\n        throw bad_optional_access();\n    }\n    TL_OPTIONAL_11_CONSTEXPR const T &value() const {\n        if (has_value()) return *m_value;\n        throw bad_optional_access();\n    }\n\n    /// Returns the stored value if there is one, otherwise returns `u`\n    template <class U>\n    constexpr T value_or(U &&u) const &noexcept {\n        static_assert(std::is_copy_constructible<T>::value &&\n                          std::is_convertible<U &&, T>::value,\n                      \"T must be copy constructible and convertible from U\");\n        return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n    }\n\n    /// \\group value_or\n    template <class U>\n        TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {\n        static_assert(std::is_move_constructible<T>::value &&\n                          std::is_convertible<U &&, T>::value,\n                      \"T must be move constructible and convertible from U\");\n        return has_value() ? **this : static_cast<T>(std::forward<U>(u));\n    }\n\n    /// Destroys the stored value if one exists, making the optional empty\n    void reset() noexcept { m_value = nullptr; }\n\n  private:\n    T *m_value;\n};  // namespace tl\n\n\n}  // namespace tl\n\nnamespace std {\n// TODO SFINAE\ntemplate <class T>\nstruct hash<tl::optional<T>> {\n    ::std::size_t operator()(const tl::optional<T> &o) const {\n        if (!o.has_value()) return 0;\n\n        return std::hash<tl::detail::remove_const_t<T>>()(*o);\n    }\n};\n}  // namespace std\n\n#endif\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/feature_common.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"pybind11/pybind11.h\"\n#include \"pybind11/numpy.h\"\n#include \"kaldi-native-fbank/csrc/feature-window.h\"\n\nnamespace paddleaudio {\nnamespace kaldi {\n\nnamespace py = pybind11;\n\ntemplate <class F>\nclass StreamingFeatureTpl {\n  public:\n    typedef typename F::Options Options;\n    StreamingFeatureTpl(const Options& opts);\n    bool ComputeFeature(const std::vector<float>& wav,\n                        std::vector<float>* feats);\n    void Reset() { remained_wav_.resize(0); }\n\n    int Dim() { return computer_.Dim(); }\n\n  private:\n    bool Compute(const std::vector<float>& waves,\n                 std::vector<float>* feats);\n    Options opts_;\n    knf::FeatureWindowFunction window_function_;\n    std::vector<float> remained_wav_;\n    F computer_;\n};\n\n}  // namespace kaldi\n}  // namespace ppspeech\n\n#include \"feature_common_inl.h\"\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/feature_common_inl.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\nnamespace paddleaudio {\nnamespace kaldi {\n\ntemplate <class F>\nStreamingFeatureTpl<F>::StreamingFeatureTpl(const Options& opts)\n    : opts_(opts), computer_(opts), window_function_(opts.frame_opts) {\n    // window_function_(computer_.GetFrameOptions()) { the opt set to zero\n}\n\ntemplate <class F>\nbool StreamingFeatureTpl<F>::ComputeFeature(\n    const std::vector<float>& wav,\n    std::vector<float>* feats) {\n    // append remained waves\n    int wav_len = wav.size();\n    if (wav_len == 0) return false;\n    int left_len = remained_wav_.size();\n    std::vector<float> waves(left_len + wav_len);\n    std::memcpy(waves.data(),\n                remained_wav_.data(),\n                left_len * sizeof(float));\n    std::memcpy(waves.data() + left_len,\n                wav.data(),\n                wav_len * sizeof(float));\n\n    // cache remained waves\n    knf::FrameExtractionOptions frame_opts = computer_.GetFrameOptions();\n    int num_frames = knf::NumFrames(waves.size(), frame_opts);\n    int frame_shift = frame_opts.WindowShift();\n    int left_samples = waves.size() - frame_shift * num_frames;\n    remained_wav_.resize(left_samples);\n    std::memcpy(remained_wav_.data(),\n                waves.data() + frame_shift * num_frames,\n                left_samples * sizeof(float));\n\n    // compute speech feature\n    Compute(waves, feats);\n    return true;\n}\n\n// Compute feat\ntemplate <class F>\nbool StreamingFeatureTpl<F>::Compute(const std::vector<float>& waves,\n                                     std::vector<float>* feats) {\n    const knf::FrameExtractionOptions& frame_opts = computer_.GetFrameOptions();\n    int num_samples = waves.size();\n    int frame_length = frame_opts.WindowSize();\n    int sample_rate = frame_opts.samp_freq;\n    if (num_samples < frame_length) {\n        return true;\n    }\n\n    int num_frames = knf::NumFrames(num_samples, frame_opts);\n    feats->resize(num_frames * Dim());\n\n    std::vector<float> window;\n    bool need_raw_log_energy = computer_.NeedRawLogEnergy();\n    for (int frame = 0; frame < num_frames; frame++) {\n        std::fill(window.begin(), window.end(), 0);\n        float raw_log_energy = 0.0;\n        float vtln_warp = 1.0;\n        knf::ExtractWindow(0,\n                           waves,\n                           frame,\n                           frame_opts,\n                           window_function_,\n                           &window,\n                           need_raw_log_energy ? &raw_log_energy : NULL);\n\n        std::vector<float> this_feature(computer_.Dim());\n        computer_.Compute(\n            raw_log_energy, vtln_warp, &window, this_feature.data());\n        std::memcpy(feats->data() + frame * Dim(),\n                    this_feature.data(),\n                    sizeof(float) * Dim());\n    }\n    return true;\n}\n\n}  // namespace kaldi\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/kaldi_feature.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"paddleaudio/src/pybind/kaldi/kaldi_feature.h\"\n//#include \"feat/pitch-functions.h\"\n\nnamespace paddleaudio {\nnamespace kaldi {\n\nbool InitFbank(\n    knf::FrameExtractionOptions frame_opts,\n    knf::MelBanksOptions mel_opts,\n    FbankOptions fbank_opts) {\n    knf::FbankOptions opts;\n    opts.frame_opts = frame_opts;\n    opts.mel_opts = mel_opts;\n    opts.use_energy = fbank_opts.use_energy;\n    opts.energy_floor = fbank_opts.energy_floor;\n    opts.raw_energy = fbank_opts.raw_energy;\n    opts.htk_compat = fbank_opts.htk_compat;\n    opts.use_log_fbank = fbank_opts.use_log_fbank;\n    opts.use_power = fbank_opts.use_power;\n    paddleaudio::kaldi::KaldiFeatureWrapper::GetInstance()->InitFbank(opts);\n    return true;\n}\n\npy::array_t<float> ComputeFbankStreaming(const py::array_t<float>& wav) {\n    return paddleaudio::kaldi::KaldiFeatureWrapper::GetInstance()->ComputeFbank(\n        wav);\n}\n\npy::array_t<float> ComputeFbank(\n    knf::FrameExtractionOptions frame_opts,\n    knf::MelBanksOptions mel_opts,\n    FbankOptions fbank_opts,\n    const py::array_t<float>& wav) {\n    InitFbank(frame_opts, mel_opts, fbank_opts);\n    py::array_t<float> result = ComputeFbankStreaming(wav);\n    paddleaudio::kaldi::KaldiFeatureWrapper::GetInstance()->ResetFbank();\n    return result;\n}\n\nvoid ResetFbank() {\n    paddleaudio::kaldi::KaldiFeatureWrapper::GetInstance()->ResetFbank();\n}\n\n//py::array_t<float> ComputeKaldiPitch(\n  //const ::kaldi::PitchExtractionOptions& opts,\n  //const py::array_t<float>& wav) {\n    //py::buffer_info info = wav.request();\n    //::kaldi::SubVector<::kaldi::BaseFloat> input_wav((float*)info.ptr, info.size);\n   \n    //::kaldi::Matrix<::kaldi::BaseFloat> features;\n    //::kaldi::ComputeKaldiPitch(opts, input_wav, &features);\n    //auto result = py::array_t<float>({features.NumRows(), features.NumCols()});\n    //for (int row_idx = 0; row_idx < features.NumRows(); ++row_idx) {\n        //std::memcpy(result.mutable_data(row_idx), features.Row(row_idx).Data(),\n                    //sizeof(float)*features.NumCols());\n    //}\n   //return result;\n//}\n\n}  // namespace kaldi\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/kaldi_feature.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <pybind11/numpy.h>\n#include <pybind11/pybind11.h>\n#include <string>\n\n#include \"paddleaudio/src/pybind/kaldi/kaldi_feature_wrapper.h\"\n//#include \"feat/pitch-functions.h\"\n\nnamespace py = pybind11;\n\nnamespace paddleaudio {\nnamespace kaldi {\n\nstruct FbankOptions{\n  bool use_energy;  // append an extra dimension with energy to the filter banks\n  float energy_floor;\n  bool raw_energy;  // If true, compute energy before preemphasis and windowing\n  bool htk_compat;  // If true, put energy last (if using energy)\n  bool use_log_fbank;  // if true (default), produce log-filterbank, else linear\n  bool use_power; \n  FbankOptions(): use_energy(false),\n                 energy_floor(0.0),\n                 raw_energy(true),\n                 htk_compat(false),\n                 use_log_fbank(true),\n                 use_power(true) {}\n};\n\nbool InitFbank(\n    knf::FrameExtractionOptions frame_opts,\n    knf::MelBanksOptions mel_opts,\n    FbankOptions fbank_opts);\n\npy::array_t<float> ComputeFbank(\n    knf::FrameExtractionOptions frame_opts,\n    knf::MelBanksOptions mel_opts,\n    FbankOptions fbank_opts,\n    const py::array_t<float>& wav);\n\npy::array_t<float> ComputeFbankStreaming(const py::array_t<float>& wav);\n\nvoid ResetFbank();\n\n//py::array_t<float> ComputeKaldiPitch(\n    //const ::kaldi::PitchExtractionOptions& opts,\n    //const py::array_t<float>& wav);\n\n}  // namespace kaldi\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/kaldi_feature_wrapper.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"paddleaudio/src/pybind/kaldi/kaldi_feature_wrapper.h\"\n\nnamespace paddleaudio {\nnamespace kaldi {\n\nKaldiFeatureWrapper* KaldiFeatureWrapper::GetInstance() {\n    static KaldiFeatureWrapper instance;\n    return &instance;\n}\n\nbool KaldiFeatureWrapper::InitFbank(knf::FbankOptions opts) {\n    fbank_.reset(new Fbank(opts));\n    return true;\n}\n\npy::array_t<float> KaldiFeatureWrapper::ComputeFbank(\n    const py::array_t<float> wav) {\n    py::buffer_info info = wav.request();\n    std::vector<float> input_wav((float*)info.ptr, (float*)info.ptr + info.size);\n\n    std::vector<float> feats;\n    bool flag = fbank_->ComputeFeature(input_wav, &feats);\n    if (flag == false || feats.size() == 0) return py::array_t<float>();\n    auto result = py::array_t<float>(feats.size());\n    py::buffer_info xs = result.request();\n    float* res_ptr = (float*)xs.ptr;\n    std::memcpy(res_ptr, feats.data(), sizeof(float)*feats.size());\n    std::vector<int> shape{static_cast<int>(feats.size() / Dim()), \n                           static_cast<int>(Dim())};\n    return result.reshape(shape);\n}\n\n}  // namespace kaldi\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/kaldi/kaldi_feature_wrapper.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"paddleaudio/third_party/kaldi-native-fbank/csrc/feature-fbank.h\"\n#include \"paddleaudio/src/pybind/kaldi/feature_common.h\"\n\nnamespace paddleaudio {\nnamespace kaldi {\n\ntypedef StreamingFeatureTpl<knf::FbankComputer> Fbank;\n\nclass KaldiFeatureWrapper {\n  public:\n    static KaldiFeatureWrapper* GetInstance();\n    bool InitFbank(knf::FbankOptions opts);\n    py::array_t<float> ComputeFbank(const py::array_t<float> wav);\n    int Dim() { return fbank_->Dim(); }\n    void ResetFbank() { fbank_->Reset(); }\n\n  private:\n    std::unique_ptr<paddleaudio::kaldi::Fbank> fbank_;\n};\n\n}  // namespace kaldi\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/pybind.cpp",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n\n#ifdef INCLUDE_KALDI\n#include \"paddleaudio/src/pybind/kaldi/kaldi_feature.h\"\n#include \"paddleaudio/third_party/kaldi-native-fbank/csrc/feature-fbank.h\"\n#endif\n\n#ifdef INCLUDE_SOX\n#include \"paddleaudio/src/pybind/sox/io.h\"\n#include \"paddleaudio/src/pybind/sox/effects.h\"\n#endif\n\n#include <pybind11/stl.h>\n#include <pybind11/pybind11.h>\n\n// `tl::optional` \n#ifdef INCLUDE_SOX\nnamespace pybind11 { namespace detail {\n   template <typename T>\n   struct type_caster<tl::optional<T>> : optional_caster<tl::optional<T>> {};\n}}\n#endif\n\nPYBIND11_MODULE(_paddleaudio, m) {\n#ifdef INCLUDE_SOX\n    m.def(\"get_info_file\",\n          &paddleaudio::sox_io::get_info_file,\n          \"Get metadata of audio file.\");\n    // support obj later\n    m.def(\"get_info_fileobj\",\n          &paddleaudio::sox_io::get_info_fileobj,\n          \"Get metadata of audio in file object.\");\n    m.def(\"load_audio_fileobj\",\n          &paddleaudio::sox_io::load_audio_fileobj,\n          \"Load audio from file object.\");\n    m.def(\"save_audio_fileobj\",\n          &paddleaudio::sox_io::save_audio_fileobj,\n          \"Save audio to file obj.\");\n          \n    // sox io\n     m.def(\"sox_io_get_info\", &paddleaudio::sox_io::get_info_file);\n     m.def(\n         \"sox_io_load_audio_file\",\n         &paddleaudio::sox_io::load_audio_file);\n     m.def(\n         \"sox_io_save_audio_file\",\n         &paddleaudio::sox_io::save_audio_file);\n    \n     // sox utils\n     m.def(\"sox_utils_set_seed\", &paddleaudio::sox_utils::set_seed);\n     m.def(\n         \"sox_utils_set_verbosity\",\n         &paddleaudio::sox_utils::set_verbosity);\n     m.def(\n         \"sox_utils_set_use_threads\",\n         &paddleaudio::sox_utils::set_use_threads);\n     m.def(\n         \"sox_utils_set_buffer_size\",\n         &paddleaudio::sox_utils::set_buffer_size);\n     m.def(\n         \"sox_utils_list_effects\",\n         &paddleaudio::sox_utils::list_effects);\n     m.def(\n         \"sox_utils_list_read_formats\",\n         &paddleaudio::sox_utils::list_read_formats);\n     m.def(\n         \"sox_utils_list_write_formats\",\n         &paddleaudio::sox_utils::list_write_formats);\n     m.def(\n         \"sox_utils_get_buffer_size\",\n         &paddleaudio::sox_utils::get_buffer_size);\n\n     // effect\n     m.def(\"apply_effects_fileobj\",\n           &paddleaudio::sox_effects::apply_effects_fileobj,\n           \"Decode audio data from file-like obj and apply effects.\");\n     m.def(\"sox_effects_initialize_sox_effects\",\n       &paddleaudio::sox_effects::initialize_sox_effects);\n     m.def(\n         \"sox_effects_shutdown_sox_effects\",\n         &paddleaudio::sox_effects::shutdown_sox_effects);\n     m.def(\n         \"sox_effects_apply_effects_tensor\",\n         &paddleaudio::sox_effects::apply_effects_tensor);\n     m.def(\n         \"sox_effects_apply_effects_file\",\n         &paddleaudio::sox_effects::apply_effects_file);\n#endif\n\n#ifdef INCLUDE_KALDI\n    m.def(\"ComputeFbank\", &paddleaudio::kaldi::ComputeFbank, \"compute fbank\");\n    //py::class_<kaldi::PitchExtractionOptions>(m, \"PitchExtractionOptions\")\n        //.def(py::init<>())\n        //.def_readwrite(\"samp_freq\", &kaldi::PitchExtractionOptions::samp_freq)\n        //.def_readwrite(\"frame_shift_ms\", &kaldi::PitchExtractionOptions::frame_shift_ms)\n        //.def_readwrite(\"frame_length_ms\", &kaldi::PitchExtractionOptions::frame_length_ms)\n        //.def_readwrite(\"preemph_coeff\", &kaldi::PitchExtractionOptions::preemph_coeff)\n        //.def_readwrite(\"min_f0\", &kaldi::PitchExtractionOptions::min_f0)\n        //.def_readwrite(\"max_f0\", &kaldi::PitchExtractionOptions::max_f0)\n        //.def_readwrite(\"soft_min_f0\", &kaldi::PitchExtractionOptions::soft_min_f0)\n        //.def_readwrite(\"penalty_factor\", &kaldi::PitchExtractionOptions::penalty_factor)\n        //.def_readwrite(\"lowpass_cutoff\", &kaldi::PitchExtractionOptions::lowpass_cutoff)\n        //.def_readwrite(\"resample_freq\", &kaldi::PitchExtractionOptions::resample_freq)\n        //.def_readwrite(\"delta_pitch\", &kaldi::PitchExtractionOptions::delta_pitch)\n        //.def_readwrite(\"nccf_ballast\", &kaldi::PitchExtractionOptions::nccf_ballast)\n        //.def_readwrite(\"lowpass_filter_width\", &kaldi::PitchExtractionOptions::lowpass_filter_width)\n        //.def_readwrite(\"upsample_filter_width\", &kaldi::PitchExtractionOptions::upsample_filter_width)\n        //.def_readwrite(\"max_frames_latency\", &kaldi::PitchExtractionOptions::max_frames_latency)\n        //.def_readwrite(\"frames_per_chunk\", &kaldi::PitchExtractionOptions::frames_per_chunk)\n        //.def_readwrite(\"simulate_first_pass_online\", &kaldi::PitchExtractionOptions::simulate_first_pass_online)\n        //.def_readwrite(\"recompute_frame\", &kaldi::PitchExtractionOptions::recompute_frame)\n        //.def_readwrite(\"nccf_ballast_online\", &kaldi::PitchExtractionOptions::nccf_ballast_online)\n        //.def_readwrite(\"snip_edges\", &kaldi::PitchExtractionOptions::snip_edges);\n    //m.def(\"ComputeKaldiPitch\", &paddleaudio::kaldi::ComputeKaldiPitch, \"compute kaldi pitch\");\n    py::class_<knf::FrameExtractionOptions>(m, \"FrameExtractionOptions\")\n        .def(py::init<>())            \n        .def_readwrite(\"samp_freq\", &knf::FrameExtractionOptions::samp_freq)\n        .def_readwrite(\"frame_shift_ms\", &knf::FrameExtractionOptions::frame_shift_ms)            \n        .def_readwrite(\"frame_length_ms\", &knf::FrameExtractionOptions::frame_length_ms)\n        .def_readwrite(\"dither\", &knf::FrameExtractionOptions::dither)            \n        .def_readwrite(\"preemph_coeff\", &knf::FrameExtractionOptions::preemph_coeff)            \n        .def_readwrite(\"remove_dc_offset\", &knf::FrameExtractionOptions::remove_dc_offset)            \n        .def_readwrite(\"window_type\", &knf::FrameExtractionOptions::window_type)\n        .def_readwrite(\"round_to_power_of_two\", &knf::FrameExtractionOptions::round_to_power_of_two)           \n        .def_readwrite(\"blackman_coeff\", &knf::FrameExtractionOptions::blackman_coeff)          \n        .def_readwrite(\"snip_edges\", &knf::FrameExtractionOptions::snip_edges)\n        .def_readwrite(\"max_feature_vectors\", &knf::FrameExtractionOptions::max_feature_vectors);\n    py::class_<knf::MelBanksOptions>(m, \"MelBanksOptions\")\n        .def(py::init<>())\n        .def_readwrite(\"num_bins\", &knf::MelBanksOptions::num_bins)\n        .def_readwrite(\"low_freq\", &knf::MelBanksOptions::low_freq)\n        .def_readwrite(\"high_freq\", &knf::MelBanksOptions::high_freq)\n        .def_readwrite(\"vtln_low\", &knf::MelBanksOptions::vtln_low)\n        .def_readwrite(\"vtln_high\", &knf::MelBanksOptions::vtln_high)\n        .def_readwrite(\"debug_mel\", &knf::MelBanksOptions::debug_mel)\n        .def_readwrite(\"htk_mode\", &knf::MelBanksOptions::htk_mode);\n\n    py::class_<paddleaudio::kaldi::FbankOptions>(m, \"FbankOptions\")\n        .def(py::init<>())\n        .def_readwrite(\"use_energy\", &paddleaudio::kaldi::FbankOptions::use_energy)\n        .def_readwrite(\"energy_floor\", &paddleaudio::kaldi::FbankOptions::energy_floor)\n        .def_readwrite(\"raw_energy\", &paddleaudio::kaldi::FbankOptions::raw_energy)\n        .def_readwrite(\"htk_compat\", &paddleaudio::kaldi::FbankOptions::htk_compat)\n        .def_readwrite(\"use_log_fbank\", &paddleaudio::kaldi::FbankOptions::use_log_fbank)\n        .def_readwrite(\"use_power\", &paddleaudio::kaldi::FbankOptions::use_power);\n#endif\n\n}\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/effects.cpp",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/effects.cpp  with modification.\n\n#include <mutex>\n#include <sox.h>\n\n#include \"paddleaudio/src/pybind/sox/effects.h\"\n#include \"paddleaudio/src/pybind/sox/effects_chain.h\"\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n\nusing namespace paddleaudio::sox_utils;\n\nnamespace paddleaudio::sox_effects {\n\n// Streaming decoding over file-like object is tricky because libsox operates on\n// FILE pointer. The following is what `sox` and `play` commands do\n//  - file input -> FILE pointer\n//  - URL input -> call wget in subprocess and pipe the data -> FILE pointer\n//  - stdin -> FILE pointer\n//\n// We want to, instead, fetch byte strings chunk by chunk, consume them, and\n// discard.\n//\n// Here is the approach\n// 1. Initialize sox_format_t using sox_open_mem_read, providing the initial\n// chunk of byte string\n//    This will perform header-based format detection, if necessary, then fill\n//    the metadata of sox_format_t. Internally, sox_open_mem_read uses fmemopen,\n//    which returns FILE* which points the buffer of the provided byte string.\n// 2. Each time sox reads a chunk from the FILE*, we update the underlying\n// buffer in a way that it\n//    starts with unseen data, and append the new data read from the given\n//    fileobj. This will trick libsox as if it keeps reading from the FILE*\n//    continuously.\n// For Step 2. see `fileobj_input_drain` function in effects_chain.cpp\nauto apply_effects_fileobj(\n    py::object fileobj,\n    const std::vector<std::vector<std::string>>& effects,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    tl::optional<std::string> format)\n    -> tl::optional<std::tuple<py::array, int64_t>> {\n  // Prepare the buffer used throughout the lifecycle of SoxEffectChain.\n  //\n  // For certain format (such as FLAC), libsox keeps reading the content at\n  // the initialization unless it reaches EOF even when the header is properly\n  // parsed. (Making buffer size 8192, which is way bigger than the header,\n  // resulted in libsox consuming all the buffer content at the time it opens\n  // the file.) Therefore buffer has to always contain valid data, except after\n  // EOF. We default to `sox_get_globals()->bufsiz`* for buffer size and we\n  // first check if there is enough data to fill the buffer. `read_fileobj`\n  // repeatedly calls `read`  method until it receives the requested length of\n  // bytes or it reaches EOF. If we get bytes shorter than requested, that means\n  // the whole audio data are fetched.\n  //\n  // * This can be changed with `paddleaudio.utils.sox_utils.set_buffer_size`.\n  const auto capacity = [&]() {\n    // NOTE:\n    // Use the abstraction provided by `libpaddleaudio` to access the global\n    // config defined by libsox. Directly using `sox_get_globals` function will\n    // end up retrieving the static variable defined in `_paddleaudio`, which is\n    // not correct.\n    const auto bufsiz = get_buffer_size();\n    const int64_t kDefaultCapacityInBytes = 256;\n    return (bufsiz > kDefaultCapacityInBytes) ? bufsiz\n                                              : kDefaultCapacityInBytes;\n  }();\n  std::string buffer(capacity, '\\0');\n  auto* in_buf = const_cast<char*>(buffer.data());\n  auto num_read = read_fileobj(&fileobj, capacity, in_buf);\n  // If the file is shorter than 256, then libsox cannot read the header.\n  auto in_buffer_size = (num_read > 256) ? num_read : 256;\n\n  // Open file (this starts reading the header)\n  // When opening a file there are two functions that can touches FILE*.\n  // * `auto_detect_format`\n  //   https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L43\n  // * `startread` handler of detected format.\n  //   https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/formats.c#L574\n  // To see the handler of a particular format, go to\n  //   https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/<FORMAT>.c\n  // For example, voribs can be found\n  //   https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/vorbis.c#L97-L158\n  SoxFormat sf(sox_open_mem_read(\n      in_buf,\n      in_buffer_size,\n      /*signal=*/nullptr,\n      /*encoding=*/nullptr,\n      /*filetype=*/format.has_value() ? format.value().c_str() : nullptr));\n\n  // In case of streamed data, length can be 0\n  if (static_cast<sox_format_t*>(sf) == nullptr ||\n      sf->encoding.encoding == SOX_ENCODING_UNKNOWN) {\n    return {};\n  }\n\n  // Prepare output buffer\n  std::vector<sox_sample_t> out_buffer;\n  out_buffer.reserve(sf->signal.length);\n\n  // Create and run SoxEffectsChain\n  const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision);\n  paddleaudio::sox_effects_chain::SoxEffectsChainPyBind chain(\n      /*input_encoding=*/sf->encoding,\n      /*output_encoding=*/get_tensor_encodinginfo(dtype));\n  chain.addInputFileObj(sf, in_buf, in_buffer_size, &fileobj);\n  for (const auto& effect : effects) {\n    chain.addEffect(effect);\n  }\n  chain.addOutputBuffer(&out_buffer);\n  chain.run();\n\n  // Create tensor from buffer\n  bool channels_first_ = channels_first.value_or(true);\n  auto tensor = convert_to_tensor(\n      /*buffer=*/out_buffer.data(),\n      /*num_samples=*/out_buffer.size(),\n      /*num_channels=*/chain.getOutputNumChannels(),\n      dtype,\n      normalize.value_or(true),\n      channels_first_);\n\n  return std::forward_as_tuple(\n      tensor, static_cast<int64_t>(chain.getOutputSampleRate()));\n}\n\nnamespace {\n\nenum SoxEffectsResourceState { NotInitialized, Initialized, ShutDown };\nSoxEffectsResourceState SOX_RESOURCE_STATE = NotInitialized;\nstd::mutex SOX_RESOURCE_STATE_MUTEX;\n\n} // namespace\n\nvoid initialize_sox_effects() {\n  const std::lock_guard<std::mutex> lock(SOX_RESOURCE_STATE_MUTEX);\n\n  switch (SOX_RESOURCE_STATE) {\n    case NotInitialized:\n      if (sox_init() != SOX_SUCCESS) {\n        throw std::runtime_error(\"Failed to initialize sox effects.\");\n      };\n      SOX_RESOURCE_STATE = Initialized;\n      break;\n    case Initialized:\n      break;\n    case ShutDown:\n      throw std::runtime_error(\n          \"SoX Effects has been shut down. Cannot initialize again.\");\n  }\n};\n\nvoid shutdown_sox_effects() {\n  const std::lock_guard<std::mutex> lock(SOX_RESOURCE_STATE_MUTEX);\n\n  switch (SOX_RESOURCE_STATE) {\n    case NotInitialized:\n      throw std::runtime_error(\n          \"SoX Effects is not initialized. Cannot shutdown.\");\n    case Initialized:\n      if (sox_quit() != SOX_SUCCESS) {\n        throw std::runtime_error(\"Failed to initialize sox effects.\");\n      };\n      SOX_RESOURCE_STATE = ShutDown;\n      break;\n    case ShutDown:\n      break;\n  }\n}\n\nauto apply_effects_tensor(\n    py::array waveform,\n    int64_t sample_rate,\n    const std::vector<std::vector<std::string>>& effects,\n    bool channels_first) -> std::tuple<py::array, int64_t> {\n  validate_input_tensor(waveform);\n\n  // Create SoxEffectsChain\n  const auto dtype = waveform.dtype();\n  paddleaudio::sox_effects_chain::SoxEffectsChain chain(\n      /*input_encoding=*/get_tensor_encodinginfo(dtype),\n      /*output_encoding=*/get_tensor_encodinginfo(dtype));\n\n  // Prepare output buffer\n  std::vector<sox_sample_t> out_buffer;\n  out_buffer.reserve(waveform.size());\n\n  // Build and run effects chain\n  chain.addInputTensor(&waveform, sample_rate, channels_first);\n  for (const auto& effect : effects) {\n    chain.addEffect(effect);\n  }\n  chain.addOutputBuffer(&out_buffer);\n  chain.run();\n\n  // Create tensor from buffer\n  auto out_tensor = convert_to_tensor(\n      /*buffer=*/out_buffer.data(),\n      /*num_samples=*/out_buffer.size(),\n      /*num_channels=*/chain.getOutputNumChannels(),\n      dtype,\n      /*normalize=*/false,\n      channels_first);\n\n  return std::tuple<py::array, int64_t>(\n      out_tensor, chain.getOutputSampleRate());\n}\n\nauto apply_effects_file(\n    const std::string& path,\n    const std::vector<std::vector<std::string>>& effects,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format)\n    -> tl::optional<std::tuple<py::array, int64_t>> {\n  // Open input file\n  SoxFormat sf(sox_open_read(\n      path.c_str(),\n      /*signal=*/nullptr,\n      /*encoding=*/nullptr,\n      /*filetype=*/format.has_value() ? format.value().c_str() : nullptr));\n\n  if (static_cast<sox_format_t*>(sf) == nullptr ||\n      sf->encoding.encoding == SOX_ENCODING_UNKNOWN) {\n    return {};\n  }\n\n  const auto dtype = get_dtype(sf->encoding.encoding, sf->signal.precision);\n\n  // Prepare output\n  std::vector<sox_sample_t> out_buffer;\n  out_buffer.reserve(sf->signal.length);\n\n  // Create and run SoxEffectsChain\n  paddleaudio::sox_effects_chain::SoxEffectsChain chain(\n      /*input_encoding=*/sf->encoding,\n      /*output_encoding=*/get_tensor_encodinginfo(dtype));\n\n  chain.addInputFile(sf);\n  for (const auto& effect : effects) {\n    chain.addEffect(effect);\n  }\n  chain.addOutputBuffer(&out_buffer);\n  chain.run();\n\n  // Create tensor from buffer\n  bool channels_first_ = channels_first.value_or(true);\n  auto tensor = convert_to_tensor(\n      /*buffer=*/out_buffer.data(),\n      /*num_samples=*/out_buffer.size(),\n      /*num_channels=*/chain.getOutputNumChannels(),\n      dtype,\n      normalize.value_or(true),\n      channels_first_);\n\n  return std::tuple<py::array, int64_t>(\n      tensor, chain.getOutputSampleRate());\n}\n\n} // namespace paddleaudio::sox_effects\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/effects.h",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/effects.h  with modification.\n#include <pybind11/pybind11.h>\n#include <pybind11/numpy.h>\n\n#include \"paddleaudio/src/optional/optional.hpp\"\n\nnamespace py = pybind11;\n\nnamespace paddleaudio::sox_effects {\n\nauto apply_effects_fileobj(\n    py::object fileobj,\n    const std::vector<std::vector<std::string>>& effects,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    tl::optional<std::string> format)\n    -> tl::optional<std::tuple<py::array, int64_t>>;\n\nvoid initialize_sox_effects();\n\nvoid shutdown_sox_effects();\n\nauto apply_effects_tensor(\n    py::array waveform,\n    int64_t sample_rate,\n    const std::vector<std::vector<std::string>>& effects,\n    bool channels_first) -> std::tuple<py::array, int64_t>;\n\nauto apply_effects_file(\n    const std::string& path,\n    const std::vector<std::vector<std::string>>& effects,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format)\n    -> tl::optional<std::tuple<py::array, int64_t>>;\n\n} // namespace paddleaudio::sox_effects\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/effects_chain.cpp",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/effects_chain.cpp with modification.\n\n#include <sox.h>\n#include <iostream>\n#include <vector>\n#include \"paddleaudio/src/pybind/sox/effects_chain.h\"\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n\nusing namespace paddleaudio::sox_utils;\n\nnamespace paddleaudio::sox_effects_chain {\n\nnamespace {\n\n/// helper classes for passing the location of input tensor and output buffer\n///\n/// drain/flow callback functions require plain C style function signature and\n/// the way to pass extra data is to attach data to sox_effect_t::priv pointer.\n/// The following structs will be assigned to sox_effect_t::priv pointer which\n/// gives sox_effect_t an access to input Tensor and output buffer object.\nstruct TensorInputPriv {\n  size_t index;\n  py::array* waveform;\n  int64_t sample_rate;\n  bool channels_first;\n};\n\nstruct TensorOutputPriv {\n  std::vector<sox_sample_t>* buffer;\n};\nstruct FileOutputPriv {\n  sox_format_t* sf;\n};\n\n/// Callback function to feed Tensor data to SoxEffectChain.\nint tensor_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp) {\n  // Retrieve the input Tensor and current index\n  auto priv = static_cast<TensorInputPriv*>(effp->priv);\n  auto index = priv->index;\n  auto tensor = *(priv->waveform);\n  auto num_channels = effp->out_signal.channels;\n\n  // Adjust the number of samples to read\n  const size_t num_samples = tensor.size();\n  if (index + *osamp > num_samples) {\n    *osamp = num_samples - index;\n  }\n\n  // Ensure that it's a multiple of the number of channels\n  *osamp -= *osamp % num_channels;\n\n  // Slice the input Tensor\n  // refactor this module, chunk\n  auto i_frame = index / num_channels;\n  auto num_frames = *osamp / num_channels;\n\n  std::vector<int> chunk(num_frames*num_channels);\n  py::buffer_info ori_info = tensor.request();\n  void* ptr = ori_info.ptr;\n  // Convert to sox_sample_t (int32_t)\n  switch (tensor.dtype().num()) {\n    //case c10::ScalarType::Float: {\n    case 11: {\n      // Need to convert to 64-bit precision so that\n      // values around INT32_MIN/MAX are handled correctly.\n      for (int idx = 0; idx < chunk.size(); ++idx) {\n        int frame_idx = (idx + index) / num_channels;\n        int channels_idx = (idx + index) % num_channels;\n        double elem = 0; \n        if (priv->channels_first) {\n          elem = *(float*)tensor.data(channels_idx, frame_idx);\n        } else {\n          elem = *(float*)tensor.data(frame_idx, channels_idx);\n        } \n        elem = elem * 2147483648.;\n        // *new_ptr = std::clamp(elem, INT32_MIN, INT32_MAX);\n        if (elem > INT32_MAX) { \n          chunk[idx] = INT32_MAX; \n        } else if (elem < INT32_MIN) {\n          chunk[idx] = INT32_MIN; \n        } else { \n          chunk[idx] = elem;\n        }\n      }\n      break;\n    }\n    //case c10::ScalarType::Int: {\n    case 5: {\n      for (int idx = 0; idx < chunk.size(); ++idx) {\n        int frame_idx = (idx + index) / num_channels;\n        int channels_idx = (idx + index) % num_channels;\n        int elem = 0;\n        if (priv->channels_first) {\n          elem = *(int*)tensor.data(channels_idx, frame_idx);\n        } else {\n          elem = *(int*)tensor.data(frame_idx, channels_idx);\n        }\n        chunk[idx] = elem;\n      }\n      break;\n    }\n    // case short\n    case 3: {\n      for (int idx = 0; idx < chunk.size(); ++idx) {\n        int frame_idx = (idx + index) / num_channels;\n        int channels_idx = (idx + index) % num_channels;\n        int16_t elem = 0;\n        if (priv->channels_first) {\n          elem = *(int16_t*)tensor.data(channels_idx, frame_idx);\n        } else {\n          elem = *(int16_t*)tensor.data(frame_idx, channels_idx);\n        }\n        chunk[idx] = elem * 65536;\n      }\n      break;\n    }\n    // case byte\n    case 1: {\n      for (int idx = 0; idx < chunk.size(); ++idx) {\n        int frame_idx = (idx + index) / num_channels;\n        int channels_idx = (idx + index) % num_channels;\n        int8_t elem = 0;\n        if (priv->channels_first) {\n          elem = *(int8_t*)tensor.data(channels_idx, frame_idx);\n        } else {\n          elem = *(int8_t*)tensor.data(frame_idx, channels_idx);\n        }\n        chunk[idx] = (elem - 128) * 16777216; \n      }\n      break;\n    }\n    default:\n      throw std::runtime_error(\"Unexpected dtype.\");\n  }\n  // Write to buffer\n  memcpy(obuf, chunk.data(), *osamp * 4);\n  priv->index += *osamp;\n  return (priv->index == num_samples) ? SOX_EOF : SOX_SUCCESS;\n}\n\n/// Callback function to fetch data from SoxEffectChain.\nint tensor_output_flow(\n    sox_effect_t* effp,\n    sox_sample_t const* ibuf,\n    sox_sample_t* obuf LSX_UNUSED,\n    size_t* isamp,\n    size_t* osamp) {\n  *osamp = 0;\n  // Get output buffer\n  auto out_buffer = static_cast<TensorOutputPriv*>(effp->priv)->buffer;\n  // Append at the end\n  out_buffer->insert(out_buffer->end(), ibuf, ibuf + *isamp);\n  return SOX_SUCCESS;\n}\n\nint file_output_flow(\n    sox_effect_t* effp,\n    sox_sample_t const* ibuf,\n    sox_sample_t* obuf LSX_UNUSED,\n    size_t* isamp,\n    size_t* osamp) {\n  *osamp = 0;\n  if (*isamp) {\n    auto sf = static_cast<FileOutputPriv*>(effp->priv)->sf;\n    if (sox_write(sf, ibuf, *isamp) != *isamp) {\n      if (sf->sox_errno) {\n        std::ostringstream stream;\n        stream << sf->sox_errstr << \" \" << sox_strerror(sf->sox_errno) << \" \"\n               << sf->filename;\n        throw std::runtime_error(stream.str());\n      }\n      return SOX_EOF;\n    }\n  }\n  return SOX_SUCCESS;\n}\n\nsox_effect_handler_t* get_tensor_input_handler() {\n  static sox_effect_handler_t handler{\n      /*name=*/\"input_tensor\",\n      /*usage=*/NULL,\n      /*flags=*/SOX_EFF_MCHAN,\n      /*getopts=*/NULL,\n      /*start=*/NULL,\n      /*flow=*/NULL,\n      /*drain=*/tensor_input_drain,\n      /*stop=*/NULL,\n      /*kill=*/NULL,\n      /*priv_size=*/sizeof(TensorInputPriv)};\n  return &handler;\n}\n\nsox_effect_handler_t* get_tensor_output_handler() {\n  static sox_effect_handler_t handler{\n      /*name=*/\"output_tensor\",\n      /*usage=*/NULL,\n      /*flags=*/SOX_EFF_MCHAN,\n      /*getopts=*/NULL,\n      /*start=*/NULL,\n      /*flow=*/tensor_output_flow,\n      /*drain=*/NULL,\n      /*stop=*/NULL,\n      /*kill=*/NULL,\n      /*priv_size=*/sizeof(TensorOutputPriv)};\n  return &handler;\n}\n\nsox_effect_handler_t* get_file_output_handler() {\n  static sox_effect_handler_t handler{\n      /*name=*/\"output_file\",\n      /*usage=*/NULL,\n      /*flags=*/SOX_EFF_MCHAN,\n      /*getopts=*/NULL,\n      /*start=*/NULL,\n      /*flow=*/file_output_flow,\n      /*drain=*/NULL,\n      /*stop=*/NULL,\n      /*kill=*/NULL,\n      /*priv_size=*/sizeof(FileOutputPriv)};\n  return &handler;\n}\n\n} // namespace\n\nSoxEffect::SoxEffect(sox_effect_t* se) noexcept : se_(se) {}\n\nSoxEffect::~SoxEffect() {\n  if (se_ != nullptr) {\n    free(se_);\n  }\n}\n\nSoxEffect::operator sox_effect_t*() const {\n  return se_;\n}\n\nauto SoxEffect::operator->() noexcept -> sox_effect_t* {\n  return se_;\n}\n\nSoxEffectsChain::SoxEffectsChain(\n    sox_encodinginfo_t input_encoding,\n    sox_encodinginfo_t output_encoding)\n    : in_enc_(input_encoding),\n      out_enc_(output_encoding),\n      in_sig_(),\n      interm_sig_(),\n      out_sig_(),\n      sec_(sox_create_effects_chain(&in_enc_, &out_enc_)) {\n  if (!sec_) {\n    throw std::runtime_error(\"Failed to create effect chain.\");\n  }\n}\n\nSoxEffectsChain::~SoxEffectsChain() {\n  if (sec_ != nullptr) {\n    sox_delete_effects_chain(sec_);\n  }\n}\n\nvoid SoxEffectsChain::run() {\n  sox_flow_effects(sec_, NULL, NULL);\n}\n\nvoid SoxEffectsChain::addInputTensor(\n    py::array* waveform,\n    int64_t sample_rate,\n    bool channels_first) {\n  in_sig_ = get_signalinfo(waveform, sample_rate, \"wav\", channels_first);\n  interm_sig_ = in_sig_;\n  SoxEffect e(sox_create_effect(get_tensor_input_handler()));\n  auto priv = static_cast<TensorInputPriv*>(e->priv);\n  priv->index = 0;\n  priv->waveform = waveform;\n  priv->sample_rate = sample_rate;\n  priv->channels_first = channels_first;\n  if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) {\n    throw std::runtime_error(\n        \"Internal Error: Failed to add effect: input_tensor\");\n  }\n}\n\nvoid SoxEffectsChain::addOutputBuffer(\n    std::vector<sox_sample_t>* output_buffer) {\n  SoxEffect e(sox_create_effect(get_tensor_output_handler()));\n  static_cast<TensorOutputPriv*>(e->priv)->buffer = output_buffer;\n  if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) {\n    throw std::runtime_error(\n        \"Internal Error: Failed to add effect: output_tensor\");\n  }\n}\n\nvoid SoxEffectsChain::addInputFile(sox_format_t* sf) {\n  in_sig_ = sf->signal;\n  interm_sig_ = in_sig_;\n  SoxEffect e(sox_create_effect(sox_find_effect(\"input\")));\n  char* opts[] = {(char*)sf};\n  sox_effect_options(e, 1, opts);\n  if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) {\n    std::ostringstream stream;\n    stream << \"Internal Error: Failed to add effect: input \" << sf->filename;\n    throw std::runtime_error(stream.str());\n  }\n}\n\nvoid SoxEffectsChain::addOutputFile(sox_format_t* sf) {\n  out_sig_ = sf->signal;\n  SoxEffect e(sox_create_effect(get_file_output_handler()));\n  static_cast<FileOutputPriv*>(e->priv)->sf = sf;\n  if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) {\n    std::ostringstream stream;\n    stream << \"Internal Error: Failed to add effect: output \" << sf->filename;\n    throw std::runtime_error(stream.str());\n  }\n}\n\nvoid SoxEffectsChain::addEffect(const std::vector<std::string> effect) {\n  const auto num_args = effect.size();\n  if (num_args == 0) {\n    throw std::runtime_error(\"Invalid argument: empty effect.\");\n  }\n  const auto name = effect[0];\n  if (UNSUPPORTED_EFFECTS.find(name) != UNSUPPORTED_EFFECTS.end()) {\n    std::ostringstream stream;\n    stream << \"Unsupported effect: \" << name;\n    throw std::runtime_error(stream.str());\n  }\n\n  auto returned_effect = sox_find_effect(name.c_str());\n  if (!returned_effect) {\n    std::ostringstream stream;\n    stream << \"Unsupported effect: \" << name;\n    throw std::runtime_error(stream.str());\n  }\n  SoxEffect e(sox_create_effect(returned_effect));\n  const auto num_options = num_args - 1;\n\n  std::vector<char*> opts;\n  for (size_t i = 1; i < num_args; ++i) {\n    opts.push_back((char*)effect[i].c_str());\n  }\n  if (sox_effect_options(e, num_options, num_options ? opts.data() : nullptr) !=\n      SOX_SUCCESS) {\n    std::ostringstream stream;\n    stream << \"Invalid effect option:\";\n    for (const auto& v : effect) {\n      stream << \" \" << v;\n    }\n    throw std::runtime_error(stream.str());\n  }\n\n  if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) {\n    std::ostringstream stream;\n    stream << \"Internal Error: Failed to add effect: \\\"\" << name;\n    for (size_t i = 1; i < num_args; ++i) {\n      stream << \" \" << effect[i];\n    }\n    stream << \"\\\"\";\n    throw std::runtime_error(stream.str());\n  }\n}\n\nint64_t SoxEffectsChain::getOutputNumChannels() {\n  return interm_sig_.channels;\n}\n\nint64_t SoxEffectsChain::getOutputSampleRate() {\n  return interm_sig_.rate;\n}\n\nnamespace {\n\n/// helper classes for passing file-like object to SoxEffectChain\nstruct FileObjInputPriv {\n  sox_format_t* sf;\n  py::object* fileobj;\n  bool eof_reached;\n  char* buffer;\n  uint64_t buffer_size;\n};\n\nstruct FileObjOutputPriv {\n  sox_format_t* sf;\n  py::object* fileobj;\n  char** buffer;\n  size_t* buffer_size;\n};\n\n/// Callback function to feed byte string\n/// https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/sox.h#L1268-L1278\nauto fileobj_input_drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp)\n    -> int {\n  auto priv = static_cast<FileObjInputPriv*>(effp->priv);\n  auto sf = priv->sf;\n  auto buffer = priv->buffer;\n\n  // 1. Refresh the buffer\n  //\n  // NOTE:\n  //   Since the underlying FILE* was opened with `fmemopen`, the only way\n  //   libsox detect EOF is reaching the end of the buffer. (null byte won't\n  //   help) Therefore we need to align the content at the end of buffer,\n  //   otherwise, libsox will keep reading the content beyond intended length.\n  //\n  // Before:\n  //\n  //     |<-------consumed------>|<---remaining--->|\n  //     |***********************|-----------------|\n  //                             ^ ftell\n  //\n  // After:\n  //\n  //     |<-offset->|<---remaining--->|<-new data->|\n  //     |**********|-----------------|++++++++++++|\n  //                ^ ftell\n\n  // NOTE:\n  //   Do not use `sf->tell_off` here. Presumably, `tell_off` and `fseek` are\n  //   supposed to be in sync, but there are cases (Vorbis) they are not\n  //   in sync and `tell_off` has seemingly uninitialized value, which\n  //   leads num_remain to be negative and cause segmentation fault\n  //   in `memmove`.\n  const auto tell = ftell((FILE*)sf->fp);\n  if (tell < 0) {\n    throw std::runtime_error(\"Internal Error: ftell failed.\");\n  }\n  const auto num_consumed = static_cast<size_t>(tell);\n  if (num_consumed > priv->buffer_size) {\n    throw std::runtime_error(\"Internal Error: buffer overrun.\");\n  }\n\n  const auto num_remain = priv->buffer_size - num_consumed;\n\n  // 1.1. Fetch the data to see if there is data to fill the buffer\n  size_t num_refill = 0;\n  std::string chunk(num_consumed, '\\0');\n  if (num_consumed && !priv->eof_reached) {\n    num_refill = read_fileobj(\n        priv->fileobj, num_consumed, const_cast<char*>(chunk.data()));\n    if (num_refill < num_consumed) {\n      priv->eof_reached = true;\n    }\n  }\n  const auto offset = num_consumed - num_refill;\n\n  // 1.2. Move the unconsumed data towards the beginning of buffer.\n  if (num_remain) {\n    auto src = static_cast<void*>(buffer + num_consumed);\n    auto dst = static_cast<void*>(buffer + offset);\n    memmove(dst, src, num_remain);\n  }\n\n  // 1.3. Refill the remaining buffer.\n  if (num_refill) {\n    auto src = static_cast<void*>(const_cast<char*>(chunk.c_str()));\n    auto dst = buffer + offset + num_remain;\n    memcpy(dst, src, num_refill);\n  }\n\n  // 1.4. Set the file pointer to the new offset\n  sf->tell_off = offset;\n  fseek((FILE*)sf->fp, offset, SEEK_SET);\n\n  // 2. Perform decoding operation\n  // The following part is practically same as \"input\" effect\n  // https://github.com/dmkrepo/libsox/blob/b9dd1a86e71bbd62221904e3e59dfaa9e5e72046/src/input.c#L30-L48\n\n  // At this point, osamp represents the buffer size in bytes,\n  // but sox_read expects the maximum number of samples ready to read.\n  // Normally, this is fine, but in case when the samples are not 4-byte\n  // aligned, (e.g. sample is 24bits), the resulting signal is not correct.\n  // https://github.com/pytorch/audio/issues/2083\n  if (sf->encoding.bits_per_sample > 0)\n    *osamp /= (sf->encoding.bits_per_sample / 8);\n\n  // Ensure that it's a multiple of the number of channels\n  *osamp -= *osamp % effp->out_signal.channels;\n\n  // Read up to *osamp samples into obuf;\n  // store the actual number read back to *osamp\n  *osamp = sox_read(sf, obuf, *osamp);\n\n  // Decoding is finished when fileobject is exhausted and sox can no longer\n  // decode a sample.\n  return (priv->eof_reached && !*osamp) ? SOX_EOF : SOX_SUCCESS;\n}\n\nauto fileobj_output_flow(\n    sox_effect_t* effp,\n    sox_sample_t const* ibuf,\n    sox_sample_t* obuf LSX_UNUSED,\n    size_t* isamp,\n    size_t* osamp) -> int {\n  *osamp = 0;\n  if (*isamp) {\n    auto priv = static_cast<FileObjOutputPriv*>(effp->priv);\n    auto sf = priv->sf;\n    auto fp = static_cast<FILE*>(sf->fp);\n    auto fileobj = priv->fileobj;\n    auto buffer = priv->buffer;\n\n    // Encode chunk\n    auto num_samples_written = sox_write(sf, ibuf, *isamp);\n    fflush(fp);\n\n    // Copy the encoded chunk to python object.\n    fileobj->attr(\"write\")(py::bytes(*buffer, ftell(fp)));\n\n    // Reset FILE*\n    sf->tell_off = 0;\n    fseek(fp, 0, SEEK_SET);\n\n    if (num_samples_written != *isamp) {\n      if (sf->sox_errno) {\n        std::ostringstream stream;\n        stream << sf->sox_errstr << \" \" << sox_strerror(sf->sox_errno) << \" \"\n               << sf->filename;\n        throw std::runtime_error(stream.str());\n      }\n      return SOX_EOF;\n    }\n  }\n  return SOX_SUCCESS;\n}\n\nauto get_fileobj_input_handler() -> sox_effect_handler_t* {\n  static sox_effect_handler_t handler{\n      /*name=*/\"input_fileobj_object\",\n      /*usage=*/nullptr,\n      /*flags=*/SOX_EFF_MCHAN,\n      /*getopts=*/nullptr,\n      /*start=*/nullptr,\n      /*flow=*/nullptr,\n      /*drain=*/fileobj_input_drain,\n      /*stop=*/nullptr,\n      /*kill=*/nullptr,\n      /*priv_size=*/sizeof(FileObjInputPriv)};\n  return &handler;\n}\n\nauto get_fileobj_output_handler() -> sox_effect_handler_t* {\n  static sox_effect_handler_t handler{\n      /*name=*/\"output_fileobj_object\",\n      /*usage=*/nullptr,\n      /*flags=*/SOX_EFF_MCHAN,\n      /*getopts=*/nullptr,\n      /*start=*/nullptr,\n      /*flow=*/fileobj_output_flow,\n      /*drain=*/nullptr,\n      /*stop=*/nullptr,\n      /*kill=*/nullptr,\n      /*priv_size=*/sizeof(FileObjOutputPriv)};\n  return &handler;\n}\n\n} // namespace\n\nvoid SoxEffectsChainPyBind::addInputFileObj(\n    sox_format_t* sf,\n    char* buffer,\n    uint64_t buffer_size,\n    py::object* fileobj) {\n  in_sig_ = sf->signal;\n  interm_sig_ = in_sig_;\n\n  SoxEffect e(sox_create_effect(get_fileobj_input_handler()));\n  auto priv = static_cast<FileObjInputPriv*>(e->priv);\n  priv->sf = sf;\n  priv->fileobj = fileobj;\n  priv->eof_reached = false;\n  priv->buffer = buffer;\n  priv->buffer_size = buffer_size;\n  if (sox_add_effect(sec_, e, &interm_sig_, &in_sig_) != SOX_SUCCESS) {\n    throw std::runtime_error(\n        \"Internal Error: Failed to add effect: input fileobj\");\n  }\n}\n\nvoid SoxEffectsChainPyBind::addOutputFileObj(\n    sox_format_t* sf,\n    char** buffer,\n    size_t* buffer_size,\n    py::object* fileobj) {\n  out_sig_ = sf->signal;\n  SoxEffect e(sox_create_effect(get_fileobj_output_handler()));\n  auto priv = static_cast<FileObjOutputPriv*>(e->priv);\n  priv->sf = sf;\n  priv->fileobj = fileobj;\n  priv->buffer = buffer;\n  priv->buffer_size = buffer_size;\n  if (sox_add_effect(sec_, e, &interm_sig_, &out_sig_) != SOX_SUCCESS) {\n    throw std::runtime_error(\n        \"Internal Error: Failed to add effect: output fileobj\");\n  }\n}\n\n} // namespace paddleaudio::sox_effects_chain\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/effects_chain.h",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/effects_chain.h with modification.\n\n#pragma once\n\n#include <sox.h>\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n\nnamespace paddleaudio::sox_effects_chain {\n\n// Helper struct to safely close sox_effect_t* pointer returned by\n// sox_create_effect\n\nstruct SoxEffect {\n  explicit SoxEffect(sox_effect_t* se) noexcept;\n  SoxEffect(const SoxEffect& other) = delete;\n  SoxEffect(const SoxEffect&& other) = delete;\n  auto operator=(const SoxEffect& other) -> SoxEffect& = delete;\n  auto operator=(SoxEffect&& other) -> SoxEffect& = delete;\n  ~SoxEffect();\n  operator sox_effect_t*() const;\n  auto operator->() noexcept -> sox_effect_t*;\n\n private:\n  sox_effect_t* se_;\n};\n\n// Helper struct to safely close sox_effects_chain_t with handy methods\nclass SoxEffectsChain {\n  const sox_encodinginfo_t in_enc_;\n  const sox_encodinginfo_t out_enc_;\n\n protected:\n  sox_signalinfo_t in_sig_;\n  sox_signalinfo_t interm_sig_;\n  sox_signalinfo_t out_sig_;\n  sox_effects_chain_t* sec_;\n\n public:\n  explicit SoxEffectsChain(\n      sox_encodinginfo_t input_encoding,\n      sox_encodinginfo_t output_encoding);\n  SoxEffectsChain(const SoxEffectsChain& other) = delete;\n  SoxEffectsChain(const SoxEffectsChain&& other) = delete;\n  SoxEffectsChain& operator=(const SoxEffectsChain& other) = delete;\n  SoxEffectsChain& operator=(SoxEffectsChain&& other) = delete;\n  ~SoxEffectsChain();\n  void run();\n  void addInputTensor(\n      py::array* waveform,\n      int64_t sample_rate,\n      bool channels_first);\n  void addInputFile(sox_format_t* sf);\n  void addOutputBuffer(std::vector<sox_sample_t>* output_buffer);\n  void addOutputFile(sox_format_t* sf);\n  void addEffect(const std::vector<std::string> effect);\n  int64_t getOutputNumChannels();\n  int64_t getOutputSampleRate();\n};\n\nclass SoxEffectsChainPyBind : public SoxEffectsChain {\n  using SoxEffectsChain::SoxEffectsChain;\n\n public:\n  void addInputFileObj(\n      sox_format_t* sf,\n      char* buffer,\n      uint64_t buffer_size,\n      py::object* fileobj);\n\n  void addOutputFileObj(\n      sox_format_t* sf,\n      char** buffer,\n      size_t* buffer_size,\n      py::object* fileobj);\n};\n\n} // namespace paddleaudio::sox_effects_chain\n\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/io.cpp",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/io.cpp with modification.\n\n#include \"paddleaudio/src/pybind/sox/io.h\"\n#include \"paddleaudio/src/pybind/sox/effects.h\"\n#include \"paddleaudio/src/pybind/sox/types.h\"\n#include \"paddleaudio/src/pybind/sox/effects_chain.h\"\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n#include \"paddleaudio/src/optional/optional.hpp\"\n\nusing namespace paddleaudio::sox_utils;\n\nnamespace paddleaudio {\nnamespace sox_io {\n\nauto get_info_file(const std::string &path, \n                   const tl::optional<std::string> &format)\n    -> std::tuple<int64_t, int64_t, int64_t, int64_t, std::string> {\n    SoxFormat sf(\n        sox_open_read(path.data(),\n                      /*signal=*/nullptr,\n                      /*encoding=*/nullptr,\n                      /*filetype=*/format.has_value() ? format.value().c_str() : nullptr));\n\n\n    validate_input_file(sf, path);\n\n    return std::make_tuple(\n        static_cast<int64_t>(sf->signal.rate),\n        static_cast<int64_t>(sf->signal.length / sf->signal.channels),\n        static_cast<int64_t>(sf->signal.channels),\n        static_cast<int64_t>(sf->encoding.bits_per_sample),\n        get_encoding(sf->encoding.encoding));\n}\n\nstd::vector<std::vector<std::string>> get_effects(\n    const tl::optional<int64_t>& frame_offset,\n    const tl::optional<int64_t>& num_frames) {\n  const auto offset = frame_offset.value_or(0);\n  if (offset < 0) {\n    throw std::runtime_error(\n        \"Invalid argument: frame_offset must be non-negative.\");\n  }\n  const auto frames = num_frames.value_or(-1);\n  if (frames == 0 || frames < -1) {\n    throw std::runtime_error(\n        \"Invalid argument: num_frames must be -1 or greater than 0.\");\n  }\n\n  std::vector<std::vector<std::string>> effects;\n  if (frames != -1) {\n    std::ostringstream os_offset, os_frames;\n    os_offset << offset << \"s\";\n    os_frames << \"+\" << frames << \"s\";\n    effects.emplace_back(\n        std::vector<std::string>{\"trim\", os_offset.str(), os_frames.str()});\n  } else if (offset != 0) {\n    std::ostringstream os_offset;\n    os_offset << offset << \"s\";\n    effects.emplace_back(std::vector<std::string>{\"trim\", os_offset.str()});\n  }\n  return effects;\n}\n\nauto get_info_fileobj(py::object fileobj, \n                      const tl::optional<std::string> &format)\n    -> std::tuple<int64_t, int64_t, int64_t, int64_t, std::string> {\n    const auto capacity = [&]() {\n        const auto bufsiz = get_buffer_size();\n        const int64_t kDefaultCapacityInBytes = 4096;\n        return (bufsiz > kDefaultCapacityInBytes) ? bufsiz\n                                                  : kDefaultCapacityInBytes;\n    }();\n    std::string buffer(capacity, '\\0');\n    auto *buf = const_cast<char *>(buffer.data());\n    auto num_read = read_fileobj(&fileobj, capacity, buf);\n    // If the file is shorter than 256, then libsox cannot read the header.\n    auto buf_size = (num_read > 256) ? num_read : 256;\n\n    SoxFormat sf(sox_open_mem_read(\n        buf,\n        buf_size,\n        /*signal=*/nullptr,\n        /*encoding=*/nullptr,\n        /*filetype=*/format.has_value() ? format.value().c_str() : nullptr));\n\n    // In case of streamed data, length can be 0\n    validate_input_memfile(sf);\n\n    return std::make_tuple(\n        static_cast<int64_t>(sf->signal.rate),\n        static_cast<int64_t>(sf->signal.length / sf->signal.channels),\n        static_cast<int64_t>(sf->signal.channels),\n        static_cast<int64_t>(sf->encoding.bits_per_sample),\n        get_encoding(sf->encoding.encoding));\n}\n\ntl::optional<std::tuple<py::array, int64_t>> load_audio_fileobj(\n    py::object fileobj,\n    const tl::optional<int64_t>& frame_offset,\n    const tl::optional<int64_t>& num_frames,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format) {\n  auto effects = get_effects(frame_offset, num_frames);\n  return paddleaudio::sox_effects::apply_effects_fileobj(\n      std::move(fileobj), effects, normalize, channels_first, std::move(format));\n}\n\ntl::optional<std::tuple<py::array, int64_t>> load_audio_file(\n    const std::string& path,\n    const tl::optional<int64_t>& frame_offset,\n    const tl::optional<int64_t>& num_frames,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format) {\n    auto effects = get_effects(frame_offset, num_frames);\n    return paddleaudio::sox_effects::apply_effects_file(\n        path, effects, normalize, channels_first, format);\n}\n\nvoid save_audio_file(const std::string& path,\n                     py::array tensor,\n                     int64_t sample_rate,\n                     bool channels_first,\n                     tl::optional<double> compression,\n                     tl::optional<std::string> format,\n                     tl::optional<std::string> encoding,\n                     tl::optional<int64_t> bits_per_sample) {\n    validate_input_tensor(tensor);\n\n    const auto filetype = [&]() {\n        if (format.has_value()) return format.value();\n        return get_filetype(path);\n    }();\n\n    if (filetype == \"amr-nb\") {\n        const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n        //TORCH_CHECK(num_channels == 1,\n        //            \"amr-nb format only supports single channel audio.\");\n        assert(num_channels == 1);\n    } else if (filetype == \"htk\") {\n        const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n       // TORCH_CHECK(num_channels == 1,\n        //            \"htk format only supports single channel audio.\");\n        assert(num_channels == 1);\n    } else if (filetype == \"gsm\") {\n        const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n        assert(num_channels == 1);\n        assert(sample_rate == 8000);\n        //TORCH_CHECK(num_channels == 1,\n        //            \"gsm format only supports single channel audio.\");\n        //TORCH_CHECK(sample_rate == 8000,\n        //            \"gsm format only supports a sampling rate of 8kHz.\");\n    }\n    const auto signal_info =\n        get_signalinfo(&tensor, sample_rate, filetype, channels_first);\n    const auto encoding_info = get_encodinginfo_for_save(\n        filetype, tensor.dtype(), compression, encoding, bits_per_sample);\n\n    SoxFormat sf(sox_open_write(path.c_str(),\n                                &signal_info,\n                                &encoding_info,\n                                /*filetype=*/filetype.c_str(),\n                                /*oob=*/nullptr,\n                                /*overwrite_permitted=*/nullptr));\n\n    if (static_cast<sox_format_t*>(sf) == nullptr) {\n        throw std::runtime_error(\n            \"Error saving audio file: failed to open file \" + path);\n    }\n\n    paddleaudio::sox_effects_chain::SoxEffectsChain chain(\n        /*input_encoding=*/get_tensor_encodinginfo(tensor.dtype()),\n        /*output_encoding=*/sf->encoding);\n    chain.addInputTensor(&tensor, sample_rate, channels_first);\n    chain.addOutputFile(sf);\n    chain.run();\n}\n\nnamespace {\n// helper class to automatically release buffer, to be used by\n// save_audio_fileobj\nstruct AutoReleaseBuffer {\n  char* ptr;\n  size_t size;\n\n  AutoReleaseBuffer() : ptr(nullptr), size(0) {}\n  AutoReleaseBuffer(const AutoReleaseBuffer& other) = delete;\n  AutoReleaseBuffer(AutoReleaseBuffer&& other) = delete;\n  auto operator=(const AutoReleaseBuffer& other) -> AutoReleaseBuffer& = delete;\n  auto operator=(AutoReleaseBuffer&& other) -> AutoReleaseBuffer& = delete;\n  ~AutoReleaseBuffer() {\n    if (ptr) {\n      free(ptr);\n    }\n  }\n};\n\n} // namespace\n\nvoid save_audio_fileobj(\n    py::object fileobj,\n    py::array tensor,\n    int64_t sample_rate,\n    bool channels_first,\n    tl::optional<double> compression,\n    tl::optional<std::string> format,\n    tl::optional<std::string> encoding,\n    tl::optional<int64_t> bits_per_sample) {\n\n  if (!format.has_value()) {\n    throw std::runtime_error(\n        \"`format` is required when saving to file object.\");\n  }\n  const auto filetype = format.value();\n\n  if (filetype == \"amr-nb\") {\n    const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n    if (num_channels != 1) {\n      throw std::runtime_error(\n          \"amr-nb format only supports single channel audio.\");\n    }\n  } else if (filetype == \"htk\") {\n    const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n    if (num_channels != 1) {\n      throw std::runtime_error(\n          \"htk format only supports single channel audio.\");\n    }\n  } else if (filetype == \"gsm\") {\n    const auto num_channels = tensor.shape(channels_first ? 0 : 1);\n    if (num_channels != 1) {\n      throw std::runtime_error(\n          \"gsm format only supports single channel audio.\");\n    }\n    if (sample_rate != 8000) {\n      throw std::runtime_error(\n          \"gsm format only supports a sampling rate of 8kHz.\");\n    }\n  }\n\n  const auto signal_info =\n      get_signalinfo(&tensor, sample_rate, filetype, channels_first);\n  const auto encoding_info = get_encodinginfo_for_save(\n      filetype,\n      tensor.dtype(),\n      compression,\n      std::move(encoding),\n      bits_per_sample);\n\n  AutoReleaseBuffer buffer;\n\n  SoxFormat sf(sox_open_memstream_write(\n      &buffer.ptr,\n      &buffer.size,\n      &signal_info,\n      &encoding_info,\n      filetype.c_str(),\n      /*oob=*/nullptr));\n\n  if (static_cast<sox_format_t*>(sf) == nullptr) {\n    throw std::runtime_error(\n        \"Error saving audio file: failed to open memory stream.\");\n  }\n\n  paddleaudio::sox_effects_chain::SoxEffectsChainPyBind chain(\n      /*input_encoding=*/get_tensor_encodinginfo(tensor.dtype()),\n      /*output_encoding=*/sf->encoding);\n  chain.addInputTensor(&tensor, sample_rate, channels_first);\n  chain.addOutputFileObj(sf, &buffer.ptr, &buffer.size, &fileobj);\n  chain.run();\n\n  // Closing the sox_format_t is necessary for flushing the last chunk to the\n  // buffer\n  sf.close();\n  fileobj.attr(\"write\")(py::bytes(buffer.ptr, buffer.size));\n}\n\n}  // namespace paddleaudio\n}  // namespace sox_io\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/io.h",
    "content": "// the code is from https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/io.h with modification.\n#pragma once\n\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n\nnamespace py = pybind11;\n\nnamespace paddleaudio {\nnamespace sox_io {\n\nauto get_info_file(const std::string &path, \n                   const tl::optional<std::string> &format)\n    -> std::tuple<int64_t, int64_t, int64_t, int64_t, std::string>;\n\nauto get_info_fileobj(py::object fileobj,\n                   const tl::optional<std::string> &format)\n    -> std::tuple<int64_t, int64_t, int64_t, int64_t, std::string>;\n\ntl::optional<std::tuple<py::array, int64_t>> load_audio_fileobj(\n    py::object fileobj,\n    const tl::optional<int64_t>& frame_offset,\n    const tl::optional<int64_t>& num_frames,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format);\n\nvoid save_audio_fileobj(\n    py::object fileobj,\n    py::array tensor,\n    int64_t sample_rate,\n    bool channels_first,\n    tl::optional<double> compression,\n    tl::optional<std::string> format,\n    tl::optional<std::string> encoding,\n    tl::optional<int64_t> bits_per_sample);\n\nauto get_effects(const tl::optional<int64_t>& frame_offset,\n                 const tl::optional<int64_t>& num_frames)\n    -> std::vector<std::vector<std::string>>;\n\n\ntl::optional<std::tuple<py::array, int64_t>> load_audio_file(\n    const std::string& path,\n    const tl::optional<int64_t>& frame_offset,\n    const tl::optional<int64_t>& num_frames,\n    tl::optional<bool> normalize,\n    tl::optional<bool> channels_first,\n    const tl::optional<std::string>& format);\n\nvoid save_audio_file(const std::string& path,\n                     py::array tensor,\n                     int64_t sample_rate,\n                     bool channels_first,\n                     tl::optional<double> compression,\n                     tl::optional<std::string> format,\n                     tl::optional<std::string> encoding,\n                     tl::optional<int64_t> bits_per_sample);    \n\n\n}  // namespace paddleaudio\n}  // namespace sox_io\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/types.cpp",
    "content": "//code is from: https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/types.cpp\n\n#include \"paddleaudio/src/pybind/sox/types.h\"\n#include <ostream>\n#include <sstream>\n\nnamespace paddleaudio {\nnamespace sox_utils {\n\nFormat get_format_from_string(const std::string& format) {\n  if (format == \"wav\")\n    return Format::WAV;\n  if (format == \"mp3\")\n    return Format::MP3;\n  if (format == \"flac\")\n    return Format::FLAC;\n  if (format == \"ogg\" || format == \"vorbis\")\n    return Format::VORBIS;\n  if (format == \"amr-nb\")\n    return Format::AMR_NB;\n  if (format == \"amr-wb\")\n    return Format::AMR_WB;\n  if (format == \"amb\")\n    return Format::AMB;\n  if (format == \"sph\")\n    return Format::SPHERE;\n  if (format == \"htk\")\n    return Format::HTK;\n  if (format == \"gsm\")\n    return Format::GSM;\n  std::ostringstream stream;\n  stream << \"Internal Error: unexpected format value: \" << format;\n  throw std::runtime_error(stream.str());\n}\n\nstd::string to_string(Encoding v) {\n  switch (v) {\n    case Encoding::UNKNOWN:\n      return \"UNKNOWN\";\n    case Encoding::PCM_SIGNED:\n      return \"PCM_S\";\n    case Encoding::PCM_UNSIGNED:\n      return \"PCM_U\";\n    case Encoding::PCM_FLOAT:\n      return \"PCM_F\";\n    case Encoding::FLAC:\n      return \"FLAC\";\n    case Encoding::ULAW:\n      return \"ULAW\";\n    case Encoding::ALAW:\n      return \"ALAW\";\n    case Encoding::MP3:\n      return \"MP3\";\n    case Encoding::VORBIS:\n      return \"VORBIS\";\n    case Encoding::AMR_WB:\n      return \"AMR_WB\";\n    case Encoding::AMR_NB:\n      return \"AMR_NB\";\n    case Encoding::OPUS:\n      return \"OPUS\";\n    default:\n      throw std::runtime_error(\"Internal Error: unexpected encoding.\");\n  }\n}\n\nEncoding get_encoding_from_option(const tl::optional<std::string> encoding) {\n  if (!encoding.has_value())\n    return Encoding::NOT_PROVIDED;\n  std::string v = encoding.value();\n  if (v == \"PCM_S\")\n    return Encoding::PCM_SIGNED;\n  if (v == \"PCM_U\")\n    return Encoding::PCM_UNSIGNED;\n  if (v == \"PCM_F\")\n    return Encoding::PCM_FLOAT;\n  if (v == \"ULAW\")\n    return Encoding::ULAW;\n  if (v == \"ALAW\")\n    return Encoding::ALAW;\n  std::ostringstream stream;\n  stream << \"Internal Error: unexpected encoding value: \" << v;\n  throw std::runtime_error(stream.str());\n}\n\nBitDepth get_bit_depth_from_option(const tl::optional<int64_t> bit_depth) {\n  if (!bit_depth.has_value())\n    return BitDepth::NOT_PROVIDED;\n  int64_t v = bit_depth.value();\n  switch (v) {\n    case 8:\n      return BitDepth::B8;\n    case 16:\n      return BitDepth::B16;\n    case 24:\n      return BitDepth::B24;\n    case 32:\n      return BitDepth::B32;\n    case 64:\n      return BitDepth::B64;\n    default: {\n      std::ostringstream s;\n      s << \"Internal Error: unexpected bit depth value: \" << v;\n      throw std::runtime_error(s.str());\n    }\n  }\n}\n\nstd::string get_encoding(sox_encoding_t encoding) {\n  switch (encoding) {\n    case SOX_ENCODING_UNKNOWN:\n      return \"UNKNOWN\";\n    case SOX_ENCODING_SIGN2:\n      return \"PCM_S\";\n    case SOX_ENCODING_UNSIGNED:\n      return \"PCM_U\";\n    case SOX_ENCODING_FLOAT:\n      return \"PCM_F\";\n    case SOX_ENCODING_FLAC:\n      return \"FLAC\";\n    case SOX_ENCODING_ULAW:\n      return \"ULAW\";\n    case SOX_ENCODING_ALAW:\n      return \"ALAW\";\n    case SOX_ENCODING_MP3:\n      return \"MP3\";\n    case SOX_ENCODING_VORBIS:\n      return \"VORBIS\";\n    case SOX_ENCODING_AMR_WB:\n      return \"AMR_WB\";\n    case SOX_ENCODING_AMR_NB:\n      return \"AMR_NB\";\n    case SOX_ENCODING_OPUS:\n      return \"OPUS\";\n    case SOX_ENCODING_GSM:\n      return \"GSM\";\n    default:\n      return \"UNKNOWN\";\n  }\n}\n\n} // namespace sox_utils\n} // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/types.h",
    "content": "//code is from: https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/types.h\n#pragma once\n\n#include <sox.h>\n#include \"paddleaudio/src/optional/optional.hpp\"\n\nnamespace paddleaudio {\nnamespace sox_utils {\n\nenum class Format {\n  WAV,\n  MP3,\n  FLAC,\n  VORBIS,\n  AMR_NB,\n  AMR_WB,\n  AMB,\n  SPHERE,\n  GSM,\n  HTK,\n};\n\nFormat get_format_from_string(const std::string& format);\n\nenum class Encoding {\n  NOT_PROVIDED,\n  UNKNOWN,\n  PCM_SIGNED,\n  PCM_UNSIGNED,\n  PCM_FLOAT,\n  FLAC,\n  ULAW,\n  ALAW,\n  MP3,\n  VORBIS,\n  AMR_WB,\n  AMR_NB,\n  OPUS,\n};\n\nstd::string to_string(Encoding v);\nEncoding get_encoding_from_option(const tl::optional<std::string> encoding);\n\nenum class BitDepth : unsigned {\n  NOT_PROVIDED = 0,\n  B8 = 8,\n  B16 = 16,\n  B24 = 24,\n  B32 = 32,\n  B64 = 64,\n};\n\nBitDepth get_bit_depth_from_option(const tl::optional<int64_t> bit_depth);\n\nstd::string get_encoding(sox_encoding_t encoding);\n\n} // namespace sox_utils\n} // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/utils.cpp",
    "content": "//code is from: https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/utils.cpp with modification.\n#include <sox.h>\n\n#include \"paddleaudio/src/pybind/sox/utils.h\"\n#include \"paddleaudio/src/pybind/sox/types.h\"\n\n#include <sstream>\n\nnamespace paddleaudio {\nnamespace sox_utils {\n\nauto read_fileobj(py::object *fileobj, const uint64_t size, char *buffer)\n    -> uint64_t {\n    uint64_t num_read = 0;\n    while (num_read < size) {\n        auto request = size - num_read;\n        auto chunk = static_cast<std::string>(\n            static_cast<py::bytes>(fileobj->attr(\"read\")(request)));\n        auto chunk_len = chunk.length();\n        if (chunk_len == 0) {\n            break;\n        }\n        if (chunk_len > request) {\n            std::ostringstream message;\n            message\n                << \"Requested up to \" << request << \" bytes but, \"\n                << \"received \" << chunk_len << \" bytes. \"\n                << \"The given object does not confirm to read protocol of file \"\n                   \"object.\";\n            throw std::runtime_error(message.str());\n        }\n        memcpy(buffer, chunk.data(), chunk_len);\n        buffer += chunk_len;\n        num_read += chunk_len;\n    }\n    return num_read;\n}\n\n\nvoid set_seed(const int64_t seed) {\n  sox_get_globals()->ranqd1 = static_cast<sox_int32_t>(seed);\n}\n\nvoid set_verbosity(const int64_t verbosity) {\n  sox_get_globals()->verbosity = static_cast<unsigned>(verbosity);\n}\n\nvoid set_use_threads(const bool use_threads) {\n  sox_get_globals()->use_threads = static_cast<sox_bool>(use_threads);\n}\n\nvoid set_buffer_size(const int64_t buffer_size) {\n  sox_get_globals()->bufsiz = static_cast<size_t>(buffer_size);\n}\n\nint64_t get_buffer_size() {\n  return sox_get_globals()->bufsiz;\n}\n\nstd::vector<std::vector<std::string>> list_effects() {\n  std::vector<std::vector<std::string>> effects;\n  for (const sox_effect_fn_t* fns = sox_get_effect_fns(); *fns; ++fns) {\n    const sox_effect_handler_t* handler = (*fns)();\n    if (handler && handler->name) {\n      if (UNSUPPORTED_EFFECTS.find(handler->name) ==\n          UNSUPPORTED_EFFECTS.end()) {\n        effects.emplace_back(std::vector<std::string>{\n            handler->name,\n            handler->usage ? std::string(handler->usage) : std::string(\"\")});\n      }\n    }\n  }\n  return effects;\n}\n\nstd::vector<std::string> list_write_formats() {\n  std::vector<std::string> formats;\n  for (const sox_format_tab_t* fns = sox_get_format_fns(); fns->fn; ++fns) {\n    const sox_format_handler_t* handler = fns->fn();\n    for (const char* const* names = handler->names; *names; ++names) {\n      if (!strchr(*names, '/') && handler->write)\n        formats.emplace_back(*names);\n    }\n  }\n  return formats;\n}\n\nstd::vector<std::string> list_read_formats() {\n  std::vector<std::string> formats;\n  for (const sox_format_tab_t* fns = sox_get_format_fns(); fns->fn; ++fns) {\n    const sox_format_handler_t* handler = fns->fn();\n    for (const char* const* names = handler->names; *names; ++names) {\n      if (!strchr(*names, '/') && handler->read)\n        formats.emplace_back(*names);\n    }\n  }\n  return formats;\n}\n\nSoxFormat::SoxFormat(sox_format_t* fd) noexcept : fd_(fd) {}\nSoxFormat::~SoxFormat() {\n  close();\n}\n\nsox_format_t* SoxFormat::operator->() const noexcept {\n  return fd_;\n}\nSoxFormat::operator sox_format_t*() const noexcept {\n  return fd_;\n}\n\nvoid SoxFormat::close() {\n  if (fd_ != nullptr) {\n    sox_close(fd_);\n    fd_ = nullptr;\n  }\n}\n\nvoid validate_input_file(const SoxFormat& sf, const std::string& path) {\n  if (static_cast<sox_format_t*>(sf) == nullptr) {\n    throw std::runtime_error(\n        \"Error loading audio file: failed to open file \" + path);\n  }\n  if (sf->encoding.encoding == SOX_ENCODING_UNKNOWN) {\n    throw std::runtime_error(\"Error loading audio file: unknown encoding.\");\n  }\n}\n\nvoid validate_input_memfile(const SoxFormat &sf) {\n    return validate_input_file(sf, \"<in memory buffer>\");\n}\n\nvoid validate_input_tensor(const py::array tensor) {\n  if (tensor.ndim() != 2) {\n    throw std::runtime_error(\"Input tensor has to be 2D.\");\n  }\n\n  char dtype = tensor.dtype().char_();\n  bool flag = (dtype == 'f') || (dtype == 'd') || (dtype == 'l') || (dtype == 'i');\n  if (flag == false) {\n      throw std::runtime_error(\n          \"Input tensor has to be one of float32, int32, int16 or uint8 type.\");\n  }\n}\n\npy::dtype get_dtype(\n    const sox_encoding_t encoding,\n    const unsigned precision) {\n    switch (encoding) {\n      case SOX_ENCODING_UNSIGNED: // 8-bit PCM WAV\n        return py::dtype('u1');\n      case SOX_ENCODING_SIGN2: // 16-bit, 24-bit, or 32-bit PCM WAV\n        switch (precision) {\n          case 16:\n            return py::dtype(\"i2\");\n          case 24: // Cast 24-bit to 32-bit.\n          case 32:\n            return py::dtype('i');\n          default:\n            throw std::runtime_error(\n                \"Only 16, 24, and 32 bits are supported for signed PCM.\");\n        }\n      default:\n        // default to float32 for the other formats, including\n        // 32-bit floating-point WAV,\n        // MP3,\n        // FLAC,\n        // VORBIS etc...\n        return py::dtype(\"f\");\n    }\n}\n\npy::array convert_to_tensor(\n    sox_sample_t* buffer,\n    const int32_t num_samples,\n    const int32_t num_channels,\n    const py::dtype dtype,\n    const bool normalize,\n    const bool channels_first) {\n  // todo refactor later(SGoat)\n  py::array t;\n  uint64_t dummy = 0;\n  SOX_SAMPLE_LOCALS;\n  int32_t num_rows = num_samples / num_channels;\n  if (normalize || dtype.char_() == 'f') {\n    t = py::array(dtype, {num_rows, num_channels});\n    auto ptr = (float*)t.mutable_data(0, 0);\n    for (int32_t i = 0; i < num_samples; ++i) {\n      ptr[i] = SOX_SAMPLE_TO_FLOAT_32BIT(buffer[i], dummy);\n    }\n    if (channels_first) {\n    py::array t2 = py::array(dtype, {num_channels, num_rows});\n    for (int32_t row_idx = 0; row_idx < num_channels; ++row_idx) {\n      for (int32_t col_idx = 0; col_idx < num_rows; ++col_idx)\n       *(float*)t2.mutable_data(row_idx, col_idx) = *(float*)t.data(col_idx, row_idx);\n    }\n    return t2;\n  }\n  } else if (dtype.char_() == 'i') {\n    t = py::array(dtype, {num_rows, num_channels});\n    auto ptr = (int*)t.mutable_data(0, 0);\n    for (int32_t i = 0; i < num_samples; ++i) {\n      ptr[i] = buffer[i];\n    }\n    if (channels_first) {\n      py::array t2 = py::array(dtype, {num_channels, num_rows});\n      for (int32_t row_idx = 0; row_idx < num_channels; ++row_idx) {\n        for (int32_t col_idx = 0; col_idx < num_rows; ++col_idx)\n          *(int*)t2.mutable_data(row_idx, col_idx) = *(int*)t.data(col_idx, row_idx);\n      }\n      return t2;\n    }\n  } else if (dtype.char_() == 'h') { // int16\n    t = py::array(dtype, {num_rows, num_channels});\n    auto ptr = (int16_t*)t.mutable_data(0, 0);\n    for (int32_t i = 0; i < num_samples; ++i) {\n      ptr[i] = SOX_SAMPLE_TO_SIGNED_16BIT(buffer[i], dummy);\n    }\n    if (channels_first) {\n      py::array t2 = py::array(dtype, {num_channels, num_rows});\n      for (int32_t row_idx = 0; row_idx < num_channels; ++row_idx) {\n        for (int32_t col_idx = 0; col_idx < num_rows; ++col_idx)\n          *(int16_t*)t2.mutable_data(row_idx, col_idx) = *(int16_t*)t.data(col_idx, row_idx);\n      }\n      return t2;\n    }\n  } else if (dtype.char_() == 'b') {\n    //t = torch::empty({num_samples / num_channels, num_channels}, torch::kUInt8);\n    t = py::array(dtype, {num_rows, num_channels});\n    auto ptr = (uint8_t*)t.mutable_data(0,0);\n    for (int32_t i = 0; i < num_samples; ++i) {\n      ptr[i] = SOX_SAMPLE_TO_UNSIGNED_8BIT(buffer[i], dummy);\n    }\n    if (channels_first) {\n      py::array t2 = py::array(dtype, {num_channels, num_rows});\n      for (int32_t row_idx = 0; row_idx < num_channels; ++row_idx) {\n        for (int32_t col_idx = 0; col_idx < num_rows; ++col_idx)\n        *(uint8_t*)t2.mutable_data(row_idx, col_idx) = *(uint8_t*)t.data(col_idx, row_idx);\n      }\n      return t2;\n    }\n  } else {\n    throw std::runtime_error(\"Unsupported dtype.\");\n  }\n  return t;\n}\n\nconst std::string get_filetype(const std::string path) {\n  std::string ext = path.substr(path.find_last_of(\".\") + 1);\n  std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);\n  return ext;\n}\n\nnamespace {\n\nstd::tuple<sox_encoding_t, unsigned> get_save_encoding_for_wav(\n    const std::string format,\n    py::dtype dtype,\n    const Encoding& encoding,\n    const BitDepth& bits_per_sample) {\n  switch (encoding) {\n    case Encoding::NOT_PROVIDED:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n          switch (dtype.num()) {\n            case 11: // float32 numpy dtype num \n              return std::make_tuple<>(SOX_ENCODING_FLOAT, 32);\n            case 5: // int numpy dtype num\n              return std::make_tuple<>(SOX_ENCODING_SIGN2, 32);\n            case 3: // int16 numpy\n              return std::make_tuple<>(SOX_ENCODING_SIGN2, 16);\n            case 1: // byte numpy\n              return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8);\n            default:\n              throw std::runtime_error(\"Internal Error: Unexpected dtype.\");\n          }\n        case BitDepth::B8:\n          return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8);\n        default:\n          return std::make_tuple<>(\n              SOX_ENCODING_SIGN2, static_cast<unsigned>(bits_per_sample));\n      }\n    case Encoding::PCM_SIGNED:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n          return std::make_tuple<>(SOX_ENCODING_SIGN2, 32);\n        case BitDepth::B8:\n          throw std::runtime_error(\n              format + \" does not support 8-bit signed PCM encoding.\");\n        default:\n          return std::make_tuple<>(\n              SOX_ENCODING_SIGN2, static_cast<unsigned>(bits_per_sample));\n      }\n    case Encoding::PCM_UNSIGNED:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n        case BitDepth::B8:\n          return std::make_tuple<>(SOX_ENCODING_UNSIGNED, 8);\n        default:\n          throw std::runtime_error(\n              format + \" only supports 8-bit for unsigned PCM encoding.\");\n      }\n    case Encoding::PCM_FLOAT:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n        case BitDepth::B32:\n          return std::make_tuple<>(SOX_ENCODING_FLOAT, 32);\n        case BitDepth::B64:\n          return std::make_tuple<>(SOX_ENCODING_FLOAT, 64);\n        default:\n          throw std::runtime_error(\n              format +\n              \" only supports 32-bit or 64-bit for floating-point PCM encoding.\");\n      }\n    case Encoding::ULAW:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n        case BitDepth::B8:\n          return std::make_tuple<>(SOX_ENCODING_ULAW, 8);\n        default:\n          throw std::runtime_error(\n              format + \" only supports 8-bit for mu-law encoding.\");\n      }\n    case Encoding::ALAW:\n      switch (bits_per_sample) {\n        case BitDepth::NOT_PROVIDED:\n        case BitDepth::B8:\n          return std::make_tuple<>(SOX_ENCODING_ALAW, 8);\n        default:\n          throw std::runtime_error(\n              format + \" only supports 8-bit for a-law encoding.\");\n      }\n    default:\n      throw std::runtime_error(\n          format + \" does not support encoding: \" + to_string(encoding));\n  }\n}\n\nstd::tuple<sox_encoding_t, unsigned> get_save_encoding(\n    const std::string& format,\n    const py::dtype dtype,\n    const tl::optional<std::string> encoding,\n    const tl::optional<int64_t> bits_per_sample) {\n  const Format fmt = get_format_from_string(format);\n  const Encoding enc = get_encoding_from_option(encoding);\n  const BitDepth bps = get_bit_depth_from_option(bits_per_sample);\n\n  switch (fmt) {\n    case Format::WAV:\n    case Format::AMB:\n      return get_save_encoding_for_wav(format, dtype, enc, bps);\n    case Format::MP3:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"mp3 does not support `encoding` option.\");\n      if (bps != BitDepth::NOT_PROVIDED)\n        throw std::runtime_error(\n            \"mp3 does not support `bits_per_sample` option.\");\n      return std::make_tuple<>(SOX_ENCODING_MP3, 16);\n    case Format::HTK:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"htk does not support `encoding` option.\");\n      if (bps != BitDepth::NOT_PROVIDED)\n        throw std::runtime_error(\n            \"htk does not support `bits_per_sample` option.\");\n      return std::make_tuple<>(SOX_ENCODING_SIGN2, 16);\n    case Format::VORBIS:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"vorbis does not support `encoding` option.\");\n      if (bps != BitDepth::NOT_PROVIDED)\n        throw std::runtime_error(\n            \"vorbis does not support `bits_per_sample` option.\");\n      return std::make_tuple<>(SOX_ENCODING_VORBIS, 16);\n    case Format::AMR_NB:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"amr-nb does not support `encoding` option.\");\n      if (bps != BitDepth::NOT_PROVIDED)\n        throw std::runtime_error(\n            \"amr-nb does not support `bits_per_sample` option.\");\n      return std::make_tuple<>(SOX_ENCODING_AMR_NB, 16);\n    case Format::FLAC:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"flac does not support `encoding` option.\");\n      switch (bps) {\n        case BitDepth::B32:\n        case BitDepth::B64:\n          throw std::runtime_error(\n              \"flac does not support `bits_per_sample` larger than 24.\");\n        default:\n          return std::make_tuple<>(\n              SOX_ENCODING_FLAC, static_cast<unsigned>(bps));\n      }\n    case Format::SPHERE:\n      switch (enc) {\n        case Encoding::NOT_PROVIDED:\n        case Encoding::PCM_SIGNED:\n          switch (bps) {\n            case BitDepth::NOT_PROVIDED:\n              return std::make_tuple<>(SOX_ENCODING_SIGN2, 32);\n            default:\n              return std::make_tuple<>(\n                  SOX_ENCODING_SIGN2, static_cast<unsigned>(bps));\n          }\n        case Encoding::PCM_UNSIGNED:\n          throw std::runtime_error(\n              \"sph does not support unsigned integer PCM.\");\n        case Encoding::PCM_FLOAT:\n          throw std::runtime_error(\"sph does not support floating point PCM.\");\n        case Encoding::ULAW:\n          switch (bps) {\n            case BitDepth::NOT_PROVIDED:\n            case BitDepth::B8:\n              return std::make_tuple<>(SOX_ENCODING_ULAW, 8);\n            default:\n              throw std::runtime_error(\n                  \"sph only supports 8-bit for mu-law encoding.\");\n          }\n        case Encoding::ALAW:\n          switch (bps) {\n            case BitDepth::NOT_PROVIDED:\n            case BitDepth::B8:\n              return std::make_tuple<>(SOX_ENCODING_ALAW, 8);\n            default:\n              return std::make_tuple<>(\n                  SOX_ENCODING_ALAW, static_cast<unsigned>(bps));\n          }\n        default:\n          throw std::runtime_error(\n              \"sph does not support encoding: \" + encoding.value());\n      }\n    case Format::GSM:\n      if (enc != Encoding::NOT_PROVIDED)\n        throw std::runtime_error(\"gsm does not support `encoding` option.\");\n      if (bps != BitDepth::NOT_PROVIDED)\n        throw std::runtime_error(\n            \"gsm does not support `bits_per_sample` option.\");\n      return std::make_tuple<>(SOX_ENCODING_GSM, 16);\n\n    default:\n      throw std::runtime_error(\"Unsupported format: \" + format);\n  }\n}\n\nunsigned get_precision(const std::string filetype, py::dtype dtype) {\n  if (filetype == \"mp3\")\n    return SOX_UNSPEC;\n  if (filetype == \"flac\")\n    return 24;\n  if (filetype == \"ogg\" || filetype == \"vorbis\")\n    return SOX_UNSPEC;\n  if (filetype == \"wav\" || filetype == \"amb\") {\n    switch (dtype.num()) {\n      case 1: // byte in numpy dtype num\n        return 8;\n      case 3: // short, in numpy dtype num\n        return 16;\n      case 5: // int, numpy dtype \n        return 32;\n      case 11: // float, numpy dtype\n        return 32;\n      default:\n        throw std::runtime_error(\"Unsupported dtype.\");\n    }\n  }\n  if (filetype == \"sph\")\n    return 32;\n  if (filetype == \"amr-nb\") {\n    return 16;\n  }\n  if (filetype == \"gsm\") {\n    return 16;\n  }\n  if (filetype == \"htk\") {\n    return 16;\n  }\n  throw std::runtime_error(\"Unsupported file type: \" + filetype);\n}\n\n} // namespace\n\nsox_signalinfo_t get_signalinfo(\n    const py::array* waveform,\n    const int64_t sample_rate,\n    const std::string filetype,\n    const bool channels_first) {\n  return sox_signalinfo_t{\n      /*rate=*/static_cast<sox_rate_t>(sample_rate),\n      /*channels=*/\n      static_cast<unsigned>(waveform->shape(channels_first ? 0 : 1)),\n      /*precision=*/get_precision(filetype, waveform->dtype()),\n      /*length=*/static_cast<uint64_t>(waveform->size())};\n}\n\nsox_encodinginfo_t get_tensor_encodinginfo(py::dtype dtype) {\n  sox_encoding_t encoding = [&]() {\n    switch (dtype.num()) {\n      case 1: // byte\n        return SOX_ENCODING_UNSIGNED;\n      case 3: // short\n        return SOX_ENCODING_SIGN2;\n      case 5: // int32\n        return SOX_ENCODING_SIGN2;\n      case 11: // float\n        return SOX_ENCODING_FLOAT;\n      default:\n        throw std::runtime_error(\"Unsupported dtype.\");\n    }\n  }();\n  unsigned bits_per_sample = [&]() {\n    switch (dtype.num()) {\n      case 1: // byte\n        return 8;\n      case 3: //short\n        return 16;\n      case 5: // int32\n        return 32;\n      case 11: // float\n        return 32;\n      default:\n        throw std::runtime_error(\"Unsupported dtype.\");\n    }\n  }();\n  return sox_encodinginfo_t{\n      /*encoding=*/encoding,\n      /*bits_per_sample=*/bits_per_sample,\n      /*compression=*/HUGE_VAL,\n      /*reverse_bytes=*/sox_option_default,\n      /*reverse_nibbles=*/sox_option_default,\n      /*reverse_bits=*/sox_option_default,\n      /*opposite_endian=*/sox_false};\n}\n\nsox_encodinginfo_t get_encodinginfo_for_save(\n    const std::string& format,\n    const py::dtype dtype,\n    const tl::optional<double> compression,\n    const tl::optional<std::string> encoding,\n    const tl::optional<int64_t> bits_per_sample) {\n  auto enc = get_save_encoding(format, dtype, encoding, bits_per_sample);\n  return sox_encodinginfo_t{\n      /*encoding=*/std::get<0>(enc),\n      /*bits_per_sample=*/std::get<1>(enc),\n      /*compression=*/compression.value_or(HUGE_VAL),\n      /*reverse_bytes=*/sox_option_default,\n      /*reverse_nibbles=*/sox_option_default,\n      /*reverse_bits=*/sox_option_default,\n      /*opposite_endian=*/sox_false};\n}\n\n}  // namespace paddleaudio\n}  // namespace sox_utils\n"
  },
  {
    "path": "audio/paddleaudio/src/pybind/sox/utils.h",
    "content": "//code is from: https://github.com/pytorch/audio/blob/main/torchaudio/csrc/sox/utils.h with modification.\n#pragma once\n\n#include <pybind11/pybind11.h>\n#include <pybind11/numpy.h>\n#include <sox.h>\n#include \"paddleaudio/src/optional/optional.hpp\"\n\nnamespace py = pybind11;\n\nnamespace paddleaudio {\nnamespace sox_utils {\n\nauto read_fileobj(py::object *fileobj, uint64_t size, char *buffer) -> uint64_t;\n\nvoid set_seed(const int64_t seed);\n\nvoid set_verbosity(const int64_t verbosity);\n\nvoid set_use_threads(const bool use_threads);\n\nvoid set_buffer_size(const int64_t buffer_size);\n\nint64_t get_buffer_size();\n\nstd::vector<std::vector<std::string>> list_effects();\n\nstd::vector<std::string> list_read_formats();\n\nstd::vector<std::string> list_write_formats();\n\n////////////////////////////////////////////////////////////////////////////////\n// Utilities for sox_io / sox_effects implementations\n////////////////////////////////////////////////////////////////////////////////\n\nconst std::unordered_set<std::string> UNSUPPORTED_EFFECTS =\n    {\"input\", \"output\", \"spectrogram\", \"noiseprof\", \"noisered\", \"splice\"};\n\n/// helper class to automatically close sox_format_t*\nstruct SoxFormat {\n  explicit SoxFormat(sox_format_t* fd) noexcept;\n  SoxFormat(const SoxFormat& other) = delete;\n  SoxFormat(SoxFormat&& other) = delete;\n  SoxFormat& operator=(const SoxFormat& other) = delete;\n  SoxFormat& operator=(SoxFormat&& other) = delete;\n  ~SoxFormat();\n  sox_format_t* operator->() const noexcept;\n  operator sox_format_t*() const noexcept;\n\n  void close();\n\n private:\n  sox_format_t* fd_;\n};\n\n///\n/// Verify that input Tensor is 2D, CPU and either uin8, int16, int32 or float32\nvoid validate_input_tensor(const py::array);\n\nvoid validate_input_file(const SoxFormat& sf, const std::string& path);\n\nvoid validate_input_memfile(const SoxFormat &sf);\n///\n/// Get target dtype for the given encoding and precision.\npy::dtype get_dtype(\n    const sox_encoding_t encoding,\n    const unsigned precision);\n\n///\n/// Convert sox_sample_t buffer to uint8/int16/int32/float32 Tensor\n/// NOTE: This function might modify the values in the input buffer to\n/// reduce the number of memory copy.\n/// @param buffer Pointer to buffer that contains audio data.\n/// @param num_samples The number of samples to read.\n/// @param num_channels The number of channels. Used to reshape the resulting\n/// Tensor.\n/// @param dtype Target dtype. Determines the output dtype and value range in\n/// conjunction with normalization.\n/// @param normalize Perform normalization. Only effective when dtype is not\n/// kFloat32. When effective, the output tensor is kFloat32 type and value range\n/// is [-1.0, 1.0]\n/// @param channels_first When True, output Tensor has shape of [num_channels,\n/// num_frames].\npy::array convert_to_tensor(\n    sox_sample_t* buffer,\n    const int32_t num_samples,\n    const int32_t num_channels,\n    const py::dtype dtype,\n    const bool normalize,\n    const bool channels_first);\n\n/// Extract extension from file path\nconst std::string get_filetype(const std::string path);\n\n/// Get sox_signalinfo_t for passing a py::array object.\nsox_signalinfo_t get_signalinfo(\n    const py::array* waveform,\n    const int64_t sample_rate,\n    const std::string filetype,\n    const bool channels_first);\n\n/// Get sox_encodinginfo_t for Tensor I/O\nsox_encodinginfo_t get_tensor_encodinginfo(const py::dtype dtype);\n\n/// Get sox_encodinginfo_t for saving to file/file object\nsox_encodinginfo_t get_encodinginfo_for_save(\n    const std::string& format,\n    const py::dtype dtype,\n    const tl::optional<double> compression,\n    const tl::optional<std::string> encoding,\n    const tl::optional<int64_t> bits_per_sample);\n\n}  // namespace paddleaudio\n}  // namespace sox_utils\n"
  },
  {
    "path": "audio/paddleaudio/src/utils.cpp",
    "content": "// this is from: https://github.com/pytorch/audio/blob/main/torchaudio/csrc/utils.cpp with modification.\n\nnamespace paddleaudio {\n\nnamespace {\n\nbool is_sox_available() {\n#ifdef INCLUDE_SOX\n    return true;\n#else\n    return false;\n#endif\n}\n\nbool is_kaldi_available() {\n#ifdef INCLUDE_KALDI\n    return true;\n#else\n    return false;\n#endif\n}\n\n// It tells whether paddleaudio was compiled with ffmpeg\n// not the runtime availability.\nbool is_ffmpeg_available() {\n#ifdef USE_FFMPEG\n    return true;\n#else\n    return false;\n#endif\n}\n\n}  // namespace\n\n}  // namespace paddleaudio\n"
  },
  {
    "path": "audio/paddleaudio/third_party/.gitignore",
    "content": "archives/\ninstall/\n"
  },
  {
    "path": "audio/paddleaudio/third_party/CMakeLists.txt",
    "content": "set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fvisibility=hidden\")\n\n################################################################################\n# sox\n################################################################################\nif (BUILD_SOX)\n  add_subdirectory(sox)\nendif()\n\n################################################################################\n# kaldi\n################################################################################\nif (BUILD_KALDI)\n  include_directories(${CMAKE_CURRENT_SOURCE_DIR})\n  add_subdirectory(kaldi-native-fbank/csrc)\nendif()\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/CMakeLists.txt",
    "content": "include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)\nadd_library(kaldi-native-fbank-core\n  feature-fbank.cc\n  feature-functions.cc\n  feature-window.cc\n  fftsg.c\n  log.cc\n  mel-computations.cc\n  rfft.cc\n)\n# We are using std::call_once() in log.h,which requires us to link with -pthread\nif(NOT WIN32)\n  target_link_libraries(kaldi-native-fbank-core -pthread)\nendif()\n\nif(KNF_HAVE_EXECINFO_H)\n  target_compile_definitions(kaldi-native-fbank-core PRIVATE KNF_HAVE_EXECINFO_H=1)\nendif()\n\nif(KNF_HAVE_CXXABI_H)\n  target_compile_definitions(kaldi-native-fbank-core PRIVATE KNF_HAVE_CXXABI_H=1)\nendif()\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-fbank.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-fbank.cc\n//\n#include \"kaldi-native-fbank/csrc/feature-fbank.h\"\n\n#include <cmath>\n\n#include \"kaldi-native-fbank/csrc/feature-functions.h\"\n\nnamespace knf {\n\nstatic void Sqrt(float *in_out, int32_t n) {\n  for (int32_t i = 0; i != n; ++i) {\n    in_out[i] = std::sqrt(in_out[i]);\n  }\n}\n\nstd::ostream &operator<<(std::ostream &os, const FbankOptions &opts) {\n  os << opts.ToString();\n  return os;\n}\n\nFbankComputer::FbankComputer(const FbankOptions &opts)\n    : opts_(opts), rfft_(opts.frame_opts.PaddedWindowSize()) {\n  if (opts.energy_floor > 0.0f) {\n    log_energy_floor_ = logf(opts.energy_floor);\n  }\n\n  // We'll definitely need the filterbanks info for VTLN warping factor 1.0.\n  // [note: this call caches it.]\n  GetMelBanks(1.0f);\n}\n\nFbankComputer::~FbankComputer() {\n  for (auto iter = mel_banks_.begin(); iter != mel_banks_.end(); ++iter)\n    delete iter->second;\n}\n\nconst MelBanks *FbankComputer::GetMelBanks(float vtln_warp) {\n  MelBanks *this_mel_banks = nullptr;\n\n  // std::map<float, MelBanks *>::iterator iter = mel_banks_.find(vtln_warp);\n  auto iter = mel_banks_.find(vtln_warp);\n  if (iter == mel_banks_.end()) {\n    this_mel_banks = new MelBanks(opts_.mel_opts, opts_.frame_opts, vtln_warp);\n    mel_banks_[vtln_warp] = this_mel_banks;\n  } else {\n    this_mel_banks = iter->second;\n  }\n  return this_mel_banks;\n}\n\nvoid FbankComputer::Compute(float signal_raw_log_energy, float vtln_warp,\n                            std::vector<float> *signal_frame, float *feature) {\n  const MelBanks &mel_banks = *(GetMelBanks(vtln_warp));\n\n  KNF_CHECK_EQ(signal_frame->size(), opts_.frame_opts.PaddedWindowSize());\n\n  // Compute energy after window function (not the raw one).\n  if (opts_.use_energy && !opts_.raw_energy) {\n    signal_raw_log_energy = std::log(\n        std::max<float>(InnerProduct(signal_frame->data(), signal_frame->data(),\n                                     signal_frame->size()),\n                        std::numeric_limits<float>::epsilon()));\n  }\n  rfft_.Compute(signal_frame->data());  // signal_frame is modified in-place\n  ComputePowerSpectrum(signal_frame);\n\n  // Use magnitude instead of power if requested.\n  if (!opts_.use_power) {\n    Sqrt(signal_frame->data(), signal_frame->size() / 2 + 1);\n  }\n\n  int32_t mel_offset = ((opts_.use_energy && !opts_.htk_compat) ? 1 : 0);\n\n  // Its length is opts_.mel_opts.num_bins\n  float *mel_energies = feature + mel_offset;\n\n  // Sum with mel filter banks over the power spectrum\n  mel_banks.Compute(signal_frame->data(), mel_energies);\n\n  if (opts_.use_log_fbank) {\n    // Avoid log of zero (which should be prevented anyway by dithering).\n    for (int32_t i = 0; i != opts_.mel_opts.num_bins; ++i) {\n      auto t = std::max(mel_energies[i], std::numeric_limits<float>::epsilon());\n      mel_energies[i] = std::log(t);\n    }\n  }\n\n  // Copy energy as first value (or the last, if htk_compat == true).\n  if (opts_.use_energy) {\n    if (opts_.energy_floor > 0.0 && signal_raw_log_energy < log_energy_floor_) {\n      signal_raw_log_energy = log_energy_floor_;\n    }\n    int32_t energy_index = opts_.htk_compat ? opts_.mel_opts.num_bins : 0;\n    feature[energy_index] = signal_raw_log_energy;\n  }\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-fbank.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-fbank.h\n\n#ifndef KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n#define KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n\n#include <map>\n\n#include \"kaldi-native-fbank/csrc/feature-window.h\"\n#include \"kaldi-native-fbank/csrc/mel-computations.h\"\n#include \"kaldi-native-fbank/csrc/rfft.h\"\n\nnamespace knf {\n\nstruct FbankOptions {\n  FrameExtractionOptions frame_opts;\n  MelBanksOptions mel_opts;\n  // append an extra dimension with energy to the filter banks\n  bool use_energy = false;\n  float energy_floor = 0.0f;  // active iff use_energy==true\n\n  // If true, compute log_energy before preemphasis and windowing\n  // If false, compute log_energy after preemphasis ans windowing\n  bool raw_energy = true;  // active iff use_energy==true\n\n  // If true, put energy last (if using energy)\n  // If false, put energy first\n  bool htk_compat = false;  // active iff use_energy==true\n\n  // if true (default), produce log-filterbank, else linear\n  bool use_log_fbank = true;\n\n  // if true (default), use power in filterbank\n  // analysis, else magnitude.\n  bool use_power = true;\n\n  FbankOptions() { mel_opts.num_bins = 23; }\n\n  std::string ToString() const {\n    std::ostringstream os;\n    os << \"frame_opts: \\n\";\n    os << frame_opts << \"\\n\";\n    os << \"\\n\";\n\n    os << \"mel_opts: \\n\";\n    os << mel_opts << \"\\n\";\n\n    os << \"use_energy: \" << use_energy << \"\\n\";\n    os << \"energy_floor: \" << energy_floor << \"\\n\";\n    os << \"raw_energy: \" << raw_energy << \"\\n\";\n    os << \"htk_compat: \" << htk_compat << \"\\n\";\n    os << \"use_log_fbank: \" << use_log_fbank << \"\\n\";\n    os << \"use_power: \" << use_power << \"\\n\";\n    return os.str();\n  }\n};\n\nstd::ostream &operator<<(std::ostream &os, const FbankOptions &opts);\n\nclass FbankComputer {\n public:\n  using Options = FbankOptions;\n\n  explicit FbankComputer(const FbankOptions &opts);\n  ~FbankComputer();\n\n  int32_t Dim() const {\n    return opts_.mel_opts.num_bins + (opts_.use_energy ? 1 : 0);\n  }\n\n  // if true, compute log_energy_pre_window but after dithering and dc removal\n  bool NeedRawLogEnergy() const { return opts_.use_energy && opts_.raw_energy; }\n\n  const FrameExtractionOptions &GetFrameOptions() const {\n    return opts_.frame_opts;\n  }\n\n  const FbankOptions &GetOptions() const { return opts_; }\n\n  /**\n     Function that computes one frame of features from\n     one frame of signal.\n\n     @param [in] signal_raw_log_energy The log-energy of the frame of the signal\n         prior to windowing and pre-emphasis, or\n         log(numeric_limits<float>::min()), whichever is greater.  Must be\n         ignored by this function if this class returns false from\n         this->NeedsRawLogEnergy().\n     @param [in] vtln_warp  The VTLN warping factor that the user wants\n         to be applied when computing features for this utterance.  Will\n         normally be 1.0, meaning no warping is to be done.  The value will\n         be ignored for feature types that don't support VLTN, such as\n         spectrogram features.\n     @param [in] signal_frame  One frame of the signal,\n       as extracted using the function ExtractWindow() using the options\n       returned by this->GetFrameOptions().  The function will use the\n       vector as a workspace, which is why it's a non-const pointer.\n     @param [out] feature  Pointer to a vector of size this->Dim(), to which\n         the computed feature will be written. It should be pre-allocated.\n  */\n  void Compute(float signal_raw_log_energy, float vtln_warp,\n               std::vector<float> *signal_frame, float *feature);\n\n private:\n  const MelBanks *GetMelBanks(float vtln_warp);\n\n  FbankOptions opts_;\n  float log_energy_floor_;\n  std::map<float, MelBanks *> mel_banks_;  // float is VTLN coefficient.\n  Rfft rfft_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-functions.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-functions.cc\n\n#include \"kaldi-native-fbank/csrc/feature-functions.h\"\n\n#include <cstdint>\n#include <vector>\n\nnamespace knf {\n\nvoid ComputePowerSpectrum(std::vector<float> *complex_fft) {\n  int32_t dim = complex_fft->size();\n\n  // now we have in complex_fft, first half of complex spectrum\n  // it's stored as [real0, realN/2, real1, im1, real2, im2, ...]\n\n  float *p = complex_fft->data();\n  int32_t half_dim = dim / 2;\n  float first_energy = p[0] * p[0];\n  float last_energy = p[1] * p[1];  // handle this special case\n\n  for (int32_t i = 1; i < half_dim; ++i) {\n    float real = p[i * 2];\n    float im = p[i * 2 + 1];\n    p[i] = real * real + im * im;\n  }\n  p[0] = first_energy;\n  p[half_dim] = last_energy;  // Will actually never be used, and anyway\n  // if the signal has been bandlimited sensibly this should be zero.\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-functions.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-functions.h\n#ifndef KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n#define KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n\n#include <vector>\nnamespace knf {\n\n// ComputePowerSpectrum converts a complex FFT (as produced by the FFT\n// functions in csrc/rfft.h), and converts it into\n// a power spectrum.  If the complex FFT is a vector of size n (representing\n// half of the complex FFT of a real signal of size n, as described there),\n// this function computes in the first (n/2) + 1 elements of it, the\n// energies of the fft bins from zero to the Nyquist frequency.  Contents of the\n// remaining (n/2) - 1 elements are undefined at output.\n\nvoid ComputePowerSpectrum(std::vector<float> *complex_fft);\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-window.cc",
    "content": "// kaldi-native-fbank/csrc/feature-window.cc\n//\n// Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n\n// This file is copied/modified from kaldi/src/feat/feature-window.cc\n\n#include \"kaldi-native-fbank/csrc/feature-window.h\"\n\n#include <cmath>\n#include <vector>\n\n#ifndef M_2PI\n#define M_2PI 6.283185307179586476925286766559005\n#endif\n\nnamespace knf {\n\nstd::ostream &operator<<(std::ostream &os, const FrameExtractionOptions &opts) {\n  os << opts.ToString();\n  return os;\n}\n\nFeatureWindowFunction::FeatureWindowFunction(const FrameExtractionOptions &opts)\n    : window_(opts.WindowSize()) {\n  int32_t frame_length = opts.WindowSize();\n  KNF_CHECK_GT(frame_length, 0);\n\n  float *window_data = window_.data();\n\n  double a = M_2PI / (frame_length - 1);\n  for (int32_t i = 0; i < frame_length; i++) {\n    double i_fl = static_cast<double>(i);\n    if (opts.window_type == \"hanning\") {\n      window_data[i] = 0.5 - 0.5 * cos(a * i_fl);\n    } else if (opts.window_type == \"sine\") {\n      // when you are checking ws wikipedia, please\n      // note that 0.5 * a = M_PI/(frame_length-1)\n      window_data[i] = sin(0.5 * a * i_fl);\n    } else if (opts.window_type == \"hamming\") {\n      window_data[i] = 0.54 - 0.46 * cos(a * i_fl);\n    } else if (opts.window_type ==\n               \"povey\") {  // like hamming but goes to zero at edges.\n      window_data[i] = pow(0.5 - 0.5 * cos(a * i_fl), 0.85);\n    } else if (opts.window_type == \"rectangular\") {\n      window_data[i] = 1.0;\n    } else if (opts.window_type == \"blackman\") {\n      window_data[i] = opts.blackman_coeff - 0.5 * cos(a * i_fl) +\n                       (0.5 - opts.blackman_coeff) * cos(2 * a * i_fl);\n    } else {\n      KNF_LOG(FATAL) << \"Invalid window type \" << opts.window_type;\n    }\n  }\n}\n\nvoid FeatureWindowFunction::Apply(float *wave) const {\n  int32_t window_size = window_.size();\n  const float *p = window_.data();\n  for (int32_t k = 0; k != window_size; ++k) {\n    wave[k] *= p[k];\n  }\n}\n\nint64_t FirstSampleOfFrame(int32_t frame, const FrameExtractionOptions &opts) {\n  int64_t frame_shift = opts.WindowShift();\n  if (opts.snip_edges) {\n    return frame * frame_shift;\n  } else {\n    int64_t midpoint_of_frame = frame_shift * frame + frame_shift / 2,\n            beginning_of_frame = midpoint_of_frame - opts.WindowSize() / 2;\n    return beginning_of_frame;\n  }\n}\n\nint32_t NumFrames(int64_t num_samples, const FrameExtractionOptions &opts,\n                  bool flush /*= true*/) {\n  int64_t frame_shift = opts.WindowShift();\n  int64_t frame_length = opts.WindowSize();\n  if (opts.snip_edges) {\n    // with --snip-edges=true (the default), we use a HTK-like approach to\n    // determining the number of frames-- all frames have to fit completely into\n    // the waveform, and the first frame begins at sample zero.\n    if (num_samples < frame_length)\n      return 0;\n    else\n      return (1 + ((num_samples - frame_length) / frame_shift));\n    // You can understand the expression above as follows: 'num_samples -\n    // frame_length' is how much room we have to shift the frame within the\n    // waveform; 'frame_shift' is how much we shift it each time; and the ratio\n    // is how many times we can shift it (integer arithmetic rounds down).\n  } else {\n    // if --snip-edges=false, the number of frames is determined by rounding the\n    // (file-length / frame-shift) to the nearest integer.  The point of this\n    // formula is to make the number of frames an obvious and predictable\n    // function of the frame shift and signal length, which makes many\n    // segmentation-related questions simpler.\n    //\n    // Because integer division in C++ rounds toward zero, we add (half the\n    // frame-shift minus epsilon) before dividing, to have the effect of\n    // rounding towards the closest integer.\n    int32_t num_frames = (num_samples + (frame_shift / 2)) / frame_shift;\n\n    if (flush) return num_frames;\n\n    // note: 'end' always means the last plus one, i.e. one past the last.\n    int64_t end_sample_of_last_frame =\n        FirstSampleOfFrame(num_frames - 1, opts) + frame_length;\n\n    // the following code is optimized more for clarity than efficiency.\n    // If flush == false, we can't output frames that extend past the end\n    // of the signal.\n    while (num_frames > 0 && end_sample_of_last_frame > num_samples) {\n      num_frames--;\n      end_sample_of_last_frame -= frame_shift;\n    }\n    return num_frames;\n  }\n}\n\nvoid ExtractWindow(int64_t sample_offset, const std::vector<float> &wave,\n                   int32_t f, const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   std::vector<float> *window,\n                   float *log_energy_pre_window /*= nullptr*/) {\n  KNF_CHECK(sample_offset >= 0 && wave.size() != 0);\n\n  int32_t frame_length = opts.WindowSize();\n  int32_t frame_length_padded = opts.PaddedWindowSize();\n\n  int64_t num_samples = sample_offset + wave.size();\n  int64_t start_sample = FirstSampleOfFrame(f, opts);\n  int64_t end_sample = start_sample + frame_length;\n\n  if (opts.snip_edges) {\n    KNF_CHECK(start_sample >= sample_offset && end_sample <= num_samples);\n  } else {\n    KNF_CHECK(sample_offset == 0 || start_sample >= sample_offset);\n  }\n\n  if (window->size() != frame_length_padded) {\n    window->resize(frame_length_padded);\n  }\n\n  // wave_start and wave_end are start and end indexes into 'wave', for the\n  // piece of wave that we're trying to extract.\n  int32_t wave_start = int32_t(start_sample - sample_offset);\n  int32_t wave_end = wave_start + frame_length;\n\n  if (wave_start >= 0 && wave_end <= wave.size()) {\n    // the normal case-- no edge effects to consider.\n    std::copy(wave.begin() + wave_start,\n              wave.begin() + wave_start + frame_length, window->data());\n  } else {\n    // Deal with any end effects by reflection, if needed.  This code will only\n    // be reached for about two frames per utterance, so we don't concern\n    // ourselves excessively with efficiency.\n    int32_t wave_dim = wave.size();\n    for (int32_t s = 0; s < frame_length; ++s) {\n      int32_t s_in_wave = s + wave_start;\n      while (s_in_wave < 0 || s_in_wave >= wave_dim) {\n        // reflect around the beginning or end of the wave.\n        // e.g. -1 -> 0, -2 -> 1.\n        // dim -> dim - 1, dim + 1 -> dim - 2.\n        // the code supports repeated reflections, although this\n        // would only be needed in pathological cases.\n        if (s_in_wave < 0)\n          s_in_wave = -s_in_wave - 1;\n        else\n          s_in_wave = 2 * wave_dim - 1 - s_in_wave;\n      }\n      (*window)[s] = wave[s_in_wave];\n    }\n  }\n\n  ProcessWindow(opts, window_function, window->data(), log_energy_pre_window);\n}\n\nstatic void RemoveDcOffset(float *d, int32_t n) {\n  float sum = 0;\n  for (int32_t i = 0; i != n; ++i) {\n    sum += d[i];\n  }\n\n  float mean = sum / n;\n\n  for (int32_t i = 0; i != n; ++i) {\n    d[i] -= mean;\n  }\n}\n\nfloat InnerProduct(const float *a, const float *b, int32_t n) {\n  float sum = 0;\n  for (int32_t i = 0; i != n; ++i) {\n    sum += a[i] * b[i];\n  }\n  return sum;\n}\n\nstatic void Preemphasize(float *d, int32_t n, float preemph_coeff) {\n  if (preemph_coeff == 0.0) {\n    return;\n  }\n\n  KNF_CHECK(preemph_coeff >= 0.0 && preemph_coeff <= 1.0);\n\n  for (int32_t i = n - 1; i > 0; --i) {\n    d[i] -= preemph_coeff * d[i - 1];\n  }\n  d[0] -= preemph_coeff * d[0];\n}\n\nvoid ProcessWindow(const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function, float *window,\n                   float *log_energy_pre_window /*= nullptr*/) {\n  int32_t frame_length = opts.WindowSize();\n\n  // TODO(fangjun): Remove dither\n  KNF_CHECK_EQ(opts.dither, 0);\n\n  if (opts.remove_dc_offset) {\n    RemoveDcOffset(window, frame_length);\n  }\n\n  if (log_energy_pre_window != NULL) {\n    float energy = std::max<float>(InnerProduct(window, window, frame_length),\n                                   std::numeric_limits<float>::epsilon());\n    *log_energy_pre_window = std::log(energy);\n  }\n\n  if (opts.preemph_coeff != 0.0) {\n    Preemphasize(window, frame_length, opts.preemph_coeff);\n  }\n\n  window_function.Apply(window);\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/feature-window.h",
    "content": "// kaldi-native-fbank/csrc/feature-window.h\n//\n// Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n\n// This file is copied/modified from kaldi/src/feat/feature-window.h\n\n#ifndef KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n#define KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"kaldi-native-fbank/csrc/log.h\"\n\nnamespace knf {\n\ninline int32_t RoundUpToNearestPowerOfTwo(int32_t n) {\n  // copied from kaldi/src/base/kaldi-math.cc\n  KNF_CHECK_GT(n, 0);\n  n--;\n  n |= n >> 1;\n  n |= n >> 2;\n  n |= n >> 4;\n  n |= n >> 8;\n  n |= n >> 16;\n  return n + 1;\n}\n\nstruct FrameExtractionOptions {\n  float samp_freq = 16000;\n  float frame_shift_ms = 10.0f;   // in milliseconds.\n  float frame_length_ms = 25.0f;  // in milliseconds.\n  float dither = 1.0f;            // Amount of dithering, 0.0 means no dither.\n  float preemph_coeff = 0.97f;    // Preemphasis coefficient.\n  bool remove_dc_offset = true;   // Subtract mean of wave before FFT.\n  std::string window_type = \"povey\";  // e.g. Hamming window\n  // May be \"hamming\", \"rectangular\", \"povey\", \"hanning\", \"sine\", \"blackman\"\n  // \"povey\" is a window I made to be similar to Hamming but to go to zero at\n  // the edges, it's pow((0.5 - 0.5*cos(n/N*2*pi)), 0.85) I just don't think the\n  // Hamming window makes sense as a windowing function.\n  bool round_to_power_of_two = true;\n  float blackman_coeff = 0.42f;\n  bool snip_edges = true;\n  // bool allow_downsample = false;\n  // bool allow_upsample = false;\n\n  // Used for streaming feature extraction. It indicates the number\n  // of feature frames to keep in the recycling vector. -1 means to\n  // keep all feature frames.\n  int32_t max_feature_vectors = -1;\n\n  int32_t WindowShift() const {\n    return static_cast<int32_t>(samp_freq * 0.001f * frame_shift_ms);\n  }\n  int32_t WindowSize() const {\n    return static_cast<int32_t>(samp_freq * 0.001f * frame_length_ms);\n  }\n  int32_t PaddedWindowSize() const {\n    return (round_to_power_of_two ? RoundUpToNearestPowerOfTwo(WindowSize())\n                                  : WindowSize());\n  }\n  std::string ToString() const {\n    std::ostringstream os;\n#define KNF_PRINT(x) os << #x << \": \" << x << \"\\n\"\n    KNF_PRINT(samp_freq);\n    KNF_PRINT(frame_shift_ms);\n    KNF_PRINT(frame_length_ms);\n    KNF_PRINT(dither);\n    KNF_PRINT(preemph_coeff);\n    KNF_PRINT(remove_dc_offset);\n    KNF_PRINT(window_type);\n    KNF_PRINT(round_to_power_of_two);\n    KNF_PRINT(blackman_coeff);\n    KNF_PRINT(snip_edges);\n    // KNF_PRINT(allow_downsample);\n    // KNF_PRINT(allow_upsample);\n    KNF_PRINT(max_feature_vectors);\n#undef KNF_PRINT\n    return os.str();\n  }\n};\n\nstd::ostream &operator<<(std::ostream &os, const FrameExtractionOptions &opts);\n\nclass FeatureWindowFunction {\n public:\n  FeatureWindowFunction() = default;\n  explicit FeatureWindowFunction(const FrameExtractionOptions &opts);\n  /**\n   * @param wave Pointer to a 1-D array of shape [window_size].\n   *             It is modified in-place: wave[i] = wave[i] * window_[i].\n   * @param\n   */\n  void Apply(float *wave) const;\n\n private:\n  std::vector<float> window_;  // of size opts.WindowSize()\n};\n\nint64_t FirstSampleOfFrame(int32_t frame, const FrameExtractionOptions &opts);\n\n/**\n   This function returns the number of frames that we can extract from a wave\n   file with the given number of samples in it (assumed to have the same\n   sampling rate as specified in 'opts').\n\n      @param [in] num_samples  The number of samples in the wave file.\n      @param [in] opts     The frame-extraction options class\n\n      @param [in] flush   True if we are asserting that this number of samples\n   is 'all there is', false if we expecting more data to possibly come in.  This\n   only makes a difference to the answer\n   if opts.snips_edges== false.  For offline feature extraction you always want\n   flush == true.  In an online-decoding context, once you know (or decide) that\n   no more data is coming in, you'd call it with flush == true at the end to\n   flush out any remaining data.\n*/\nint32_t NumFrames(int64_t num_samples, const FrameExtractionOptions &opts,\n                  bool flush = true);\n\n/*\n  ExtractWindow() extracts a windowed frame of waveform (possibly with a\n  power-of-two, padded size, depending on the config), including all the\n  processing done by ProcessWindow().\n\n  @param [in] sample_offset  If 'wave' is not the entire waveform, but\n                   part of it to the left has been discarded, then the\n                   number of samples prior to 'wave' that we have\n                   already discarded.  Set this to zero if you are\n                   processing the entire waveform in one piece, or\n                   if you get 'no matching function' compilation\n                   errors when updating the code.\n  @param [in] wave  The waveform\n  @param [in] f     The frame index to be extracted, with\n                    0 <= f < NumFrames(sample_offset + wave.Dim(), opts, true)\n  @param [in] opts  The options class to be used\n  @param [in] window_function  The windowing function, as derived from the\n                    options class.\n  @param [out] window  The windowed, possibly-padded waveform to be\n                     extracted.  Will be resized as needed.\n  @param [out] log_energy_pre_window  If non-NULL, the log-energy of\n                   the signal prior to pre-emphasis and multiplying by\n                   the windowing function will be written to here.\n*/\nvoid ExtractWindow(int64_t sample_offset, const std::vector<float> &wave,\n                   int32_t f, const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   std::vector<float> *window,\n                   float *log_energy_pre_window = nullptr);\n\n/**\n  This function does all the windowing steps after actually\n  extracting the windowed signal: depending on the\n  configuration, it does dithering, dc offset removal,\n  preemphasis, and multiplication by the windowing function.\n   @param [in] opts  The options class to be used\n   @param [in] window_function  The windowing function-- should have\n                    been initialized using 'opts'.\n   @param [in,out] window  A vector of size opts.WindowSize().  Note:\n      it will typically be a sub-vector of a larger vector of size\n      opts.PaddedWindowSize(), with the remaining samples zero,\n      as the FFT code is more efficient if it operates on data with\n      power-of-two size.\n   @param [out]   log_energy_pre_window If non-NULL, then after dithering and\n      DC offset removal, this function will write to this pointer the log of\n      the total energy (i.e. sum-squared) of the frame.\n */\nvoid ProcessWindow(const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function, float *window,\n                   float *log_energy_pre_window = nullptr);\n\n// Compute the inner product of two vectors\nfloat InnerProduct(const float *a, const float *b, int32_t n);\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/fftsg.c",
    "content": "/* This file is copied from\n * https://www.kurims.kyoto-u.ac.jp/~ooura/fft.html\n */\n/*\nFast Fourier/Cosine/Sine Transform\n    dimension   :one\n    data length :power of 2\n    decimation  :frequency\n    radix       :split-radix\n    data        :inplace\n    table       :use\nfunctions\n    cdft: Complex Discrete Fourier Transform\n    rdft: Real Discrete Fourier Transform\n    ddct: Discrete Cosine Transform\n    ddst: Discrete Sine Transform\n    dfct: Cosine Transform of RDFT (Real Symmetric DFT)\n    dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)\nfunction prototypes\n    void cdft(int, int, double *, int *, double *);\n    void rdft(int, int, double *, int *, double *);\n    void ddct(int, int, double *, int *, double *);\n    void ddst(int, int, double *, int *, double *);\n    void dfct(int, double *, double *, int *, double *);\n    void dfst(int, double *, double *, int *, double *);\nmacro definitions\n    USE_CDFT_PTHREADS : default=not defined\n        CDFT_THREADS_BEGIN_N  : must be >= 512, default=8192\n        CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536\n    USE_CDFT_WINTHREADS : default=not defined\n        CDFT_THREADS_BEGIN_N  : must be >= 512, default=32768\n        CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288\n\n\n-------- Complex DFT (Discrete Fourier Transform) --------\n    [definition]\n        <case1>\n            X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n\n        <case2>\n            X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n\n        (notes: sum_j=0^n-1 is a summation from j=0 to n-1)\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            cdft(2*n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            cdft(2*n, -1, a, ip, w);\n    [parameters]\n        2*n            :data length (int)\n                        n >= 1, n = power of 2\n        a[0...2*n-1]   :input/output data (double *)\n                        input data\n                            a[2*j] = Re(x[j]),\n                            a[2*j+1] = Im(x[j]), 0<=j<n\n                        output data\n                            a[2*k] = Re(X[k]),\n                            a[2*k+1] = Im(X[k]), 0<=k<n\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n/2-1]   :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            cdft(2*n, -1, a, ip, w);\n        is\n            cdft(2*n, 1, a, ip, w);\n            for (j = 0; j <= 2 * n - 1; j++) {\n                a[j] *= 1.0 / n;\n            }\n        .\n\n\n-------- Real DFT / Inverse of Real DFT --------\n    [definition]\n        <case1> RDFT\n            R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2\n            I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2\n        <case2> IRDFT (excluding scale)\n            a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +\n                   sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +\n                   sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            rdft(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            rdft(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        <case1>\n                            output data\n                                a[2*k] = R[k], 0<=k<n/2\n                                a[2*k+1] = I[k], 0<k<n/2\n                                a[1] = R[n/2]\n                        <case2>\n                            input data\n                                a[2*j] = R[j], 0<=j<n/2\n                                a[2*j+1] = I[j], 0<j<n/2\n                                a[1] = R[n/2]\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n/2-1]   :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            rdft(n, 1, a, ip, w);\n        is\n            rdft(n, -1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- DCT (Discrete Cosine Transform) / Inverse of DCT --------\n    [definition]\n        <case1> IDCT (excluding scale)\n            C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n\n        <case2> DCT\n            C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            ddct(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            ddct(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        output data\n                            a[k] = C[k], 0<=k<n\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/4-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            ddct(n, -1, a, ip, w);\n        is\n            a[0] *= 0.5;\n            ddct(n, 1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- DST (Discrete Sine Transform) / Inverse of DST --------\n    [definition]\n        <case1> IDST (excluding scale)\n            S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n\n        <case2> DST\n            S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            ddst(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            ddst(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        <case1>\n                            input data\n                                a[j] = A[j], 0<j<n\n                                a[0] = A[n]\n                            output data\n                                a[k] = S[k], 0<=k<n\n                        <case2>\n                            output data\n                                a[k] = S[k], 0<k<n\n                                a[0] = S[n]\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/4-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            ddst(n, -1, a, ip, w);\n        is\n            a[0] *= 0.5;\n            ddst(n, 1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- Cosine Transform of RDFT (Real Symmetric DFT) --------\n    [definition]\n        C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n\n    [usage]\n        ip[0] = 0; // first time only\n        dfct(n, a, t, ip, w);\n    [parameters]\n        n              :data length - 1 (int)\n                        n >= 2, n = power of 2\n        a[0...n]       :input/output data (double *)\n                        output data\n                            a[k] = C[k], 0<=k<=n\n        t[0...n/2]     :work area (double *)\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/4)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/8-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            a[0] *= 0.5;\n            a[n] *= 0.5;\n            dfct(n, a, t, ip, w);\n        is\n            a[0] *= 0.5;\n            a[n] *= 0.5;\n            dfct(n, a, t, ip, w);\n            for (j = 0; j <= n; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- Sine Transform of RDFT (Real Anti-symmetric DFT) --------\n    [definition]\n        S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n\n    [usage]\n        ip[0] = 0; // first time only\n        dfst(n, a, t, ip, w);\n    [parameters]\n        n              :data length + 1 (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        output data\n                            a[k] = S[k], 0<k<n\n                        (a[0] is used for work area)\n        t[0...n/2-1]   :work area (double *)\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/4)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/8-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            dfst(n, a, t, ip, w);\n        is\n            dfst(n, a, t, ip, w);\n            for (j = 1; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\nAppendix :\n    The cos/sin table is recalculated when the larger table required.\n    w[] and ip[] are compatible with all routines.\n*/\n\n\nvoid cdft(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    int nw;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    if (isgn >= 0) {\n        cftfsub(n, a, ip, nw, w);\n    } else {\n        cftbsub(n, a, ip, nw, w);\n    }\n}\n\n\nvoid rdft(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    int nw, nc;\n    double xi;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 2)) {\n        nc = n >> 2;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xi = a[0] - a[1];\n        a[0] += a[1];\n        a[1] = xi;\n    } else {\n        a[1] = 0.5 * (a[0] - a[1]);\n        a[0] -= a[1];\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n}\n\n\nvoid ddct(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    void dctsub(int n, double *a, int nc, double *c);\n    int j, nw, nc;\n    double xr;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > nc) {\n        nc = n;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn < 0) {\n        xr = a[n - 1];\n        for (j = n - 2; j >= 2; j -= 2) {\n            a[j + 1] = a[j] - a[j - 1];\n            a[j] += a[j - 1];\n        }\n        a[1] = a[0] - xr;\n        a[0] += xr;\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n    dctsub(n, a, nc, w + nw);\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xr = a[0] - a[1];\n        a[0] += a[1];\n        for (j = 2; j < n; j += 2) {\n            a[j - 1] = a[j] - a[j + 1];\n            a[j] += a[j + 1];\n        }\n        a[n - 1] = xr;\n    }\n}\n\n\nvoid ddst(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    void dstsub(int n, double *a, int nc, double *c);\n    int j, nw, nc;\n    double xr;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > nc) {\n        nc = n;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn < 0) {\n        xr = a[n - 1];\n        for (j = n - 2; j >= 2; j -= 2) {\n            a[j + 1] = -a[j] - a[j - 1];\n            a[j] -= a[j - 1];\n        }\n        a[1] = a[0] + xr;\n        a[0] -= xr;\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n    dstsub(n, a, nc, w + nw);\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xr = a[0] - a[1];\n        a[0] += a[1];\n        for (j = 2; j < n; j += 2) {\n            a[j - 1] = -a[j] - a[j + 1];\n            a[j] -= a[j + 1];\n        }\n        a[n - 1] = -xr;\n    }\n}\n\n\nvoid dfct(int n, double *a, double *t, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void dctsub(int n, double *a, int nc, double *c);\n    int j, k, l, m, mh, nw, nc;\n    double xr, xi, yr, yi;\n\n    nw = ip[0];\n    if (n > (nw << 3)) {\n        nw = n >> 3;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 1)) {\n        nc = n >> 1;\n        makect(nc, ip, w + nw);\n    }\n    m = n >> 1;\n    yi = a[m];\n    xi = a[0] + a[n];\n    a[0] -= a[n];\n    t[0] = xi - yi;\n    t[m] = xi + yi;\n    if (n > 2) {\n        mh = m >> 1;\n        for (j = 1; j < mh; j++) {\n            k = m - j;\n            xr = a[j] - a[n - j];\n            xi = a[j] + a[n - j];\n            yr = a[k] - a[n - k];\n            yi = a[k] + a[n - k];\n            a[j] = xr;\n            a[k] = yr;\n            t[j] = xi - yi;\n            t[k] = xi + yi;\n        }\n        t[mh] = a[mh] + a[n - mh];\n        a[mh] -= a[n - mh];\n        dctsub(m, a, nc, w + nw);\n        if (m > 4) {\n            cftfsub(m, a, ip, nw, w);\n            rftfsub(m, a, nc, w + nw);\n        } else if (m == 4) {\n            cftfsub(m, a, ip, nw, w);\n        }\n        a[n - 1] = a[0] - a[1];\n        a[1] = a[0] + a[1];\n        for (j = m - 2; j >= 2; j -= 2) {\n            a[2 * j + 1] = a[j] + a[j + 1];\n            a[2 * j - 1] = a[j] - a[j + 1];\n        }\n        l = 2;\n        m = mh;\n        while (m >= 2) {\n            dctsub(m, t, nc, w + nw);\n            if (m > 4) {\n                cftfsub(m, t, ip, nw, w);\n                rftfsub(m, t, nc, w + nw);\n            } else if (m == 4) {\n                cftfsub(m, t, ip, nw, w);\n            }\n            a[n - l] = t[0] - t[1];\n            a[l] = t[0] + t[1];\n            k = 0;\n            for (j = 2; j < m; j += 2) {\n                k += l << 2;\n                a[k - l] = t[j] - t[j + 1];\n                a[k + l] = t[j] + t[j + 1];\n            }\n            l <<= 1;\n            mh = m >> 1;\n            for (j = 0; j < mh; j++) {\n                k = m - j;\n                t[j] = t[m + k] - t[m + j];\n                t[k] = t[m + k] + t[m + j];\n            }\n            t[mh] = t[m + mh];\n            m = mh;\n        }\n        a[l] = t[0];\n        a[n] = t[2] - t[1];\n        a[0] = t[2] + t[1];\n    } else {\n        a[1] = a[0];\n        a[2] = t[0];\n        a[0] = t[1];\n    }\n}\n\n\nvoid dfst(int n, double *a, double *t, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void dstsub(int n, double *a, int nc, double *c);\n    int j, k, l, m, mh, nw, nc;\n    double xr, xi, yr, yi;\n\n    nw = ip[0];\n    if (n > (nw << 3)) {\n        nw = n >> 3;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 1)) {\n        nc = n >> 1;\n        makect(nc, ip, w + nw);\n    }\n    if (n > 2) {\n        m = n >> 1;\n        mh = m >> 1;\n        for (j = 1; j < mh; j++) {\n            k = m - j;\n            xr = a[j] + a[n - j];\n            xi = a[j] - a[n - j];\n            yr = a[k] + a[n - k];\n            yi = a[k] - a[n - k];\n            a[j] = xr;\n            a[k] = yr;\n            t[j] = xi + yi;\n            t[k] = xi - yi;\n        }\n        t[0] = a[mh] - a[n - mh];\n        a[mh] += a[n - mh];\n        a[0] = a[m];\n        dstsub(m, a, nc, w + nw);\n        if (m > 4) {\n            cftfsub(m, a, ip, nw, w);\n            rftfsub(m, a, nc, w + nw);\n        } else if (m == 4) {\n            cftfsub(m, a, ip, nw, w);\n        }\n        a[n - 1] = a[1] - a[0];\n        a[1] = a[0] + a[1];\n        for (j = m - 2; j >= 2; j -= 2) {\n            a[2 * j + 1] = a[j] - a[j + 1];\n            a[2 * j - 1] = -a[j] - a[j + 1];\n        }\n        l = 2;\n        m = mh;\n        while (m >= 2) {\n            dstsub(m, t, nc, w + nw);\n            if (m > 4) {\n                cftfsub(m, t, ip, nw, w);\n                rftfsub(m, t, nc, w + nw);\n            } else if (m == 4) {\n                cftfsub(m, t, ip, nw, w);\n            }\n            a[n - l] = t[1] - t[0];\n            a[l] = t[0] + t[1];\n            k = 0;\n            for (j = 2; j < m; j += 2) {\n                k += l << 2;\n                a[k - l] = -t[j] - t[j + 1];\n                a[k + l] = t[j] - t[j + 1];\n            }\n            l <<= 1;\n            mh = m >> 1;\n            for (j = 1; j < mh; j++) {\n                k = m - j;\n                t[j] = t[m + k] + t[m + j];\n                t[k] = t[m + k] - t[m + j];\n            }\n            t[0] = t[m + mh];\n            m = mh;\n        }\n        a[l] = t[0];\n    }\n    a[0] = 0;\n}\n\n\n/* -------- initializing routines -------- */\n\n\n#include <math.h>\n\nvoid makewt(int nw, int *ip, double *w) {\n    void makeipt(int nw, int *ip);\n    int j, nwh, nw0, nw1;\n    double delta, wn4r, wk1r, wk1i, wk3r, wk3i;\n\n    ip[0] = nw;\n    ip[1] = 1;\n    if (nw > 2) {\n        nwh = nw >> 1;\n        delta = atan(1.0) / nwh;\n        wn4r = cos(delta * nwh);\n        w[0] = 1;\n        w[1] = wn4r;\n        if (nwh == 4) {\n            w[2] = cos(delta * 2);\n            w[3] = sin(delta * 2);\n        } else if (nwh > 4) {\n            makeipt(nw, ip);\n            w[2] = 0.5 / cos(delta * 2);\n            w[3] = 0.5 / cos(delta * 6);\n            for (j = 4; j < nwh; j += 4) {\n                w[j] = cos(delta * j);\n                w[j + 1] = sin(delta * j);\n                w[j + 2] = cos(3 * delta * j);\n                w[j + 3] = -sin(3 * delta * j);\n            }\n        }\n        nw0 = 0;\n        while (nwh > 2) {\n            nw1 = nw0 + nwh;\n            nwh >>= 1;\n            w[nw1] = 1;\n            w[nw1 + 1] = wn4r;\n            if (nwh == 4) {\n                wk1r = w[nw0 + 4];\n                wk1i = w[nw0 + 5];\n                w[nw1 + 2] = wk1r;\n                w[nw1 + 3] = wk1i;\n            } else if (nwh > 4) {\n                wk1r = w[nw0 + 4];\n                wk3r = w[nw0 + 6];\n                w[nw1 + 2] = 0.5 / wk1r;\n                w[nw1 + 3] = 0.5 / wk3r;\n                for (j = 4; j < nwh; j += 4) {\n                    wk1r = w[nw0 + 2 * j];\n                    wk1i = w[nw0 + 2 * j + 1];\n                    wk3r = w[nw0 + 2 * j + 2];\n                    wk3i = w[nw0 + 2 * j + 3];\n                    w[nw1 + j] = wk1r;\n                    w[nw1 + j + 1] = wk1i;\n                    w[nw1 + j + 2] = wk3r;\n                    w[nw1 + j + 3] = wk3i;\n                }\n            }\n            nw0 = nw1;\n        }\n    }\n}\n\n\nvoid makeipt(int nw, int *ip) {\n    int j, l, m, m2, p, q;\n\n    ip[2] = 0;\n    ip[3] = 16;\n    m = 2;\n    for (l = nw; l > 32; l >>= 2) {\n        m2 = m << 1;\n        q = m2 << 3;\n        for (j = m; j < m2; j++) {\n            p = ip[j] << 2;\n            ip[m + j] = p;\n            ip[m2 + j] = p + q;\n        }\n        m = m2;\n    }\n}\n\n\nvoid makect(int nc, int *ip, double *c) {\n    int j, nch;\n    double delta;\n\n    ip[1] = nc;\n    if (nc > 1) {\n        nch = nc >> 1;\n        delta = atan(1.0) / nch;\n        c[0] = cos(delta * nch);\n        c[nch] = 0.5 * c[0];\n        for (j = 1; j < nch; j++) {\n            c[j] = 0.5 * cos(delta * j);\n            c[nc - j] = 0.5 * sin(delta * j);\n        }\n    }\n}\n\n\n/* -------- child routines -------- */\n\n\n#ifdef USE_CDFT_PTHREADS\n#define USE_CDFT_THREADS\n#ifndef CDFT_THREADS_BEGIN_N\n#define CDFT_THREADS_BEGIN_N 8192\n#endif\n#ifndef CDFT_4THREADS_BEGIN_N\n#define CDFT_4THREADS_BEGIN_N 65536\n#endif\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#define cdft_thread_t pthread_t\n#define cdft_thread_create(thp, func, argp)                       \\\n    {                                                             \\\n        if (pthread_create(thp, NULL, func, (void *)argp) != 0) { \\\n            fprintf(stderr, \"cdft thread error\\n\");               \\\n            exit(1);                                              \\\n        }                                                         \\\n    }\n#define cdft_thread_wait(th)                        \\\n    {                                               \\\n        if (pthread_join(th, NULL) != 0) {          \\\n            fprintf(stderr, \"cdft thread error\\n\"); \\\n            exit(1);                                \\\n        }                                           \\\n    }\n#endif /* USE_CDFT_PTHREADS */\n\n\n#ifdef USE_CDFT_WINTHREADS\n#define USE_CDFT_THREADS\n#ifndef CDFT_THREADS_BEGIN_N\n#define CDFT_THREADS_BEGIN_N 32768\n#endif\n#ifndef CDFT_4THREADS_BEGIN_N\n#define CDFT_4THREADS_BEGIN_N 524288\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <windows.h>\n#define cdft_thread_t HANDLE\n#define cdft_thread_create(thp, func, argp)                                 \\\n    {                                                                       \\\n        DWORD thid;                                                         \\\n        *(thp) = CreateThread(                                              \\\n            NULL, 0, (LPTHREAD_START_ROUTINE)func, (LPVOID)argp, 0, &thid); \\\n        if (*(thp) == 0) {                                                  \\\n            fprintf(stderr, \"cdft thread error\\n\");                         \\\n            exit(1);                                                        \\\n        }                                                                   \\\n    }\n#define cdft_thread_wait(th)               \\\n    {                                      \\\n        WaitForSingleObject(th, INFINITE); \\\n        CloseHandle(th);                   \\\n    }\n#endif /* USE_CDFT_WINTHREADS */\n\n\nvoid cftfsub(int n, double *a, int *ip, int nw, double *w) {\n    void bitrv2(int n, int *ip, double *a);\n    void bitrv216(double *a);\n    void bitrv208(double *a);\n    void cftf1st(int n, double *a, double *w);\n    void cftrec4(int n, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftfx41(int n, double *a, int nw, double *w);\n    void cftf161(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf040(double *a);\n    void cftx020(double *a);\n#ifdef USE_CDFT_THREADS\n    void cftrec4_th(int n, double *a, int nw, double *w);\n#endif /* USE_CDFT_THREADS */\n\n    if (n > 8) {\n        if (n > 32) {\n            cftf1st(n, a, &w[nw - (n >> 2)]);\n#ifdef USE_CDFT_THREADS\n            if (n > CDFT_THREADS_BEGIN_N) {\n                cftrec4_th(n, a, nw, w);\n            } else\n#endif /* USE_CDFT_THREADS */\n                if (n > 512) {\n                cftrec4(n, a, nw, w);\n            } else if (n > 128) {\n                cftleaf(n, 1, a, nw, w);\n            } else {\n                cftfx41(n, a, nw, w);\n            }\n            bitrv2(n, ip, a);\n        } else if (n == 32) {\n            cftf161(a, &w[nw - 8]);\n            bitrv216(a);\n        } else {\n            cftf081(a, w);\n            bitrv208(a);\n        }\n    } else if (n == 8) {\n        cftf040(a);\n    } else if (n == 4) {\n        cftx020(a);\n    }\n}\n\n\nvoid cftbsub(int n, double *a, int *ip, int nw, double *w) {\n    void bitrv2conj(int n, int *ip, double *a);\n    void bitrv216neg(double *a);\n    void bitrv208neg(double *a);\n    void cftb1st(int n, double *a, double *w);\n    void cftrec4(int n, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftfx41(int n, double *a, int nw, double *w);\n    void cftf161(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftb040(double *a);\n    void cftx020(double *a);\n#ifdef USE_CDFT_THREADS\n    void cftrec4_th(int n, double *a, int nw, double *w);\n#endif /* USE_CDFT_THREADS */\n\n    if (n > 8) {\n        if (n > 32) {\n            cftb1st(n, a, &w[nw - (n >> 2)]);\n#ifdef USE_CDFT_THREADS\n            if (n > CDFT_THREADS_BEGIN_N) {\n                cftrec4_th(n, a, nw, w);\n            } else\n#endif /* USE_CDFT_THREADS */\n                if (n > 512) {\n                cftrec4(n, a, nw, w);\n            } else if (n > 128) {\n                cftleaf(n, 1, a, nw, w);\n            } else {\n                cftfx41(n, a, nw, w);\n            }\n            bitrv2conj(n, ip, a);\n        } else if (n == 32) {\n            cftf161(a, &w[nw - 8]);\n            bitrv216neg(a);\n        } else {\n            cftf081(a, w);\n            bitrv208neg(a);\n        }\n    } else if (n == 8) {\n        cftb040(a);\n    } else if (n == 4) {\n        cftx020(a);\n    }\n}\n\n\nvoid bitrv2(int n, int *ip, double *a) {\n    int j, j1, k, k1, l, m, nh, nm;\n    double xr, xi, yr, yi;\n\n    m = 1;\n    for (l = n >> 2; l > 8; l >>= 2) {\n        m <<= 1;\n    }\n    nh = n >> 1;\n    nm = 4 * m;\n    if (l == 8) {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + 2 * ip[m + k];\n                k1 = 4 * k + 2 * ip[m + j];\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + 2 * ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 += 2 * nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 -= nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= 2;\n            k1 -= nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nh + 2;\n            k1 += nh + 2;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= nh - nm;\n            k1 += 2 * nm - 2;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n        }\n    } else {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + ip[m + k];\n                k1 = 4 * k + ip[m + j];\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 += nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n        }\n    }\n}\n\n\nvoid bitrv2conj(int n, int *ip, double *a) {\n    int j, j1, k, k1, l, m, nh, nm;\n    double xr, xi, yr, yi;\n\n    m = 1;\n    for (l = n >> 2; l > 8; l >>= 2) {\n        m <<= 1;\n    }\n    nh = n >> 1;\n    nm = 4 * m;\n    if (l == 8) {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + 2 * ip[m + k];\n                k1 = 4 * k + 2 * ip[m + j];\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + 2 * ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n            j1 += nm;\n            k1 += 2 * nm;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 -= nm;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= 2;\n            k1 -= nh;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nh + 2;\n            k1 += nh + 2;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= nh - nm;\n            k1 += 2 * nm - 2;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n        }\n    } else {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + ip[m + k];\n                k1 = 4 * k + ip[m + j];\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n            j1 += nm;\n            k1 += nm;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n        }\n    }\n}\n\n\nvoid bitrv216(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i,\n        x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x7r = a[14];\n    x7i = a[15];\n    x8r = a[16];\n    x8i = a[17];\n    x10r = a[20];\n    x10i = a[21];\n    x11r = a[22];\n    x11i = a[23];\n    x12r = a[24];\n    x12i = a[25];\n    x13r = a[26];\n    x13i = a[27];\n    x14r = a[28];\n    x14i = a[29];\n    a[2] = x8r;\n    a[3] = x8i;\n    a[4] = x4r;\n    a[5] = x4i;\n    a[6] = x12r;\n    a[7] = x12i;\n    a[8] = x2r;\n    a[9] = x2i;\n    a[10] = x10r;\n    a[11] = x10i;\n    a[14] = x14r;\n    a[15] = x14i;\n    a[16] = x1r;\n    a[17] = x1i;\n    a[20] = x5r;\n    a[21] = x5i;\n    a[22] = x13r;\n    a[23] = x13i;\n    a[24] = x3r;\n    a[25] = x3i;\n    a[26] = x11r;\n    a[27] = x11i;\n    a[28] = x7r;\n    a[29] = x7i;\n}\n\n\nvoid bitrv216neg(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i,\n        x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i,\n        x14r, x14i, x15r, x15i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x6r = a[12];\n    x6i = a[13];\n    x7r = a[14];\n    x7i = a[15];\n    x8r = a[16];\n    x8i = a[17];\n    x9r = a[18];\n    x9i = a[19];\n    x10r = a[20];\n    x10i = a[21];\n    x11r = a[22];\n    x11i = a[23];\n    x12r = a[24];\n    x12i = a[25];\n    x13r = a[26];\n    x13i = a[27];\n    x14r = a[28];\n    x14i = a[29];\n    x15r = a[30];\n    x15i = a[31];\n    a[2] = x15r;\n    a[3] = x15i;\n    a[4] = x7r;\n    a[5] = x7i;\n    a[6] = x11r;\n    a[7] = x11i;\n    a[8] = x3r;\n    a[9] = x3i;\n    a[10] = x13r;\n    a[11] = x13i;\n    a[12] = x5r;\n    a[13] = x5i;\n    a[14] = x9r;\n    a[15] = x9i;\n    a[16] = x1r;\n    a[17] = x1i;\n    a[18] = x14r;\n    a[19] = x14i;\n    a[20] = x6r;\n    a[21] = x6i;\n    a[22] = x10r;\n    a[23] = x10i;\n    a[24] = x2r;\n    a[25] = x2i;\n    a[26] = x12r;\n    a[27] = x12i;\n    a[28] = x4r;\n    a[29] = x4i;\n    a[30] = x8r;\n    a[31] = x8i;\n}\n\n\nvoid bitrv208(double *a) {\n    double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x6r = a[12];\n    x6i = a[13];\n    a[2] = x4r;\n    a[3] = x4i;\n    a[6] = x6r;\n    a[7] = x6i;\n    a[8] = x1r;\n    a[9] = x1i;\n    a[12] = x3r;\n    a[13] = x3i;\n}\n\n\nvoid bitrv208neg(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x6r = a[12];\n    x6i = a[13];\n    x7r = a[14];\n    x7i = a[15];\n    a[2] = x7r;\n    a[3] = x7i;\n    a[4] = x3r;\n    a[5] = x3i;\n    a[6] = x5r;\n    a[7] = x5i;\n    a[8] = x1r;\n    a[9] = x1i;\n    a[10] = x6r;\n    a[11] = x6i;\n    a[12] = x2r;\n    a[13] = x2i;\n    a[14] = x4r;\n    a[15] = x4i;\n}\n\n\nvoid cftf1st(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = a[1] + a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = a[1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    a[j2] = x1r - x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r + x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    csc1 = w[2];\n    csc3 = w[3];\n    wd1r = 1;\n    wd1i = 0;\n    wd3r = 1;\n    wd3i = 0;\n    k = 0;\n    for (j = 2; j < mh - 2; j += 4) {\n        k += 4;\n        wk1r = csc1 * (wd1r + w[k]);\n        wk1i = csc1 * (wd1i + w[k + 1]);\n        wk3r = csc3 * (wd3r + w[k + 2]);\n        wk3i = csc3 * (wd3i + w[k + 3]);\n        wd1r = w[k];\n        wd1i = w[k + 1];\n        wd3r = w[k + 2];\n        wd3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = a[j + 1] + a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = a[j + 1] - a[j2 + 1];\n        y0r = a[j + 2] + a[j2 + 2];\n        y0i = a[j + 3] + a[j2 + 3];\n        y1r = a[j + 2] - a[j2 + 2];\n        y1i = a[j + 3] - a[j2 + 3];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 + 2] + a[j3 + 2];\n        y2i = a[j1 + 3] + a[j3 + 3];\n        y3r = a[j1 + 2] - a[j3 + 2];\n        y3i = a[j1 + 3] - a[j3 + 3];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i + x2i;\n        a[j + 2] = y0r + y2r;\n        a[j + 3] = y0i + y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        a[j1 + 2] = y0r - y2r;\n        a[j1 + 3] = y0i - y2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i + y3r;\n        a[j2 + 2] = wd1r * x0r - wd1i * x0i;\n        a[j2 + 3] = wd1r * x0i + wd1i * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i - y3r;\n        a[j3 + 2] = wd3r * x0r + wd3i * x0i;\n        a[j3 + 3] = wd3r * x0i - wd3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = a[j0 + 1] + a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = a[j0 + 1] - a[j2 + 1];\n        y0r = a[j0 - 2] + a[j2 - 2];\n        y0i = a[j0 - 1] + a[j2 - 1];\n        y1r = a[j0 - 2] - a[j2 - 2];\n        y1i = a[j0 - 1] - a[j2 - 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 - 2] + a[j3 - 2];\n        y2i = a[j1 - 1] + a[j3 - 1];\n        y3r = a[j1 - 2] - a[j3 - 2];\n        y3i = a[j1 - 1] - a[j3 - 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i + x2i;\n        a[j0 - 2] = y0r + y2r;\n        a[j0 - 1] = y0i + y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        a[j1 - 2] = y0r - y2r;\n        a[j1 - 1] = y0i - y2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i + y3r;\n        a[j2 - 2] = wd1i * x0r - wd1r * x0i;\n        a[j2 - 1] = wd1i * x0i + wd1r * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i - y3r;\n        a[j3 - 2] = wd3i * x0r + wd3r * x0i;\n        a[j3 - 1] = wd3i * x0i - wd3r * x0r;\n    }\n    wk1r = csc1 * (wd1r + wn4r);\n    wk1i = csc1 * (wd1i + wn4r);\n    wk3r = csc3 * (wd3r - wn4r);\n    wk3i = csc3 * (wd3i - wn4r);\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0 - 2] + a[j2 - 2];\n    x0i = a[j0 - 1] + a[j2 - 1];\n    x1r = a[j0 - 2] - a[j2 - 2];\n    x1i = a[j0 - 1] - a[j2 - 1];\n    x2r = a[j1 - 2] + a[j3 - 2];\n    x2i = a[j1 - 1] + a[j3 - 1];\n    x3r = a[j1 - 2] - a[j3 - 2];\n    x3i = a[j1 - 1] - a[j3 - 1];\n    a[j0 - 2] = x0r + x2r;\n    a[j0 - 1] = x0i + x2i;\n    a[j1 - 2] = x0r - x2r;\n    a[j1 - 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2 - 2] = wk1r * x0r - wk1i * x0i;\n    a[j2 - 1] = wk1r * x0i + wk1i * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3 - 2] = wk3r * x0r + wk3i * x0i;\n    a[j3 - 1] = wk3r * x0i - wk3i * x0r;\n    x0r = a[j0] + a[j2];\n    x0i = a[j0 + 1] + a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = a[j0 + 1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n    x0r = a[j0 + 2] + a[j2 + 2];\n    x0i = a[j0 + 3] + a[j2 + 3];\n    x1r = a[j0 + 2] - a[j2 + 2];\n    x1i = a[j0 + 3] - a[j2 + 3];\n    x2r = a[j1 + 2] + a[j3 + 2];\n    x2i = a[j1 + 3] + a[j3 + 3];\n    x3r = a[j1 + 2] - a[j3 + 2];\n    x3i = a[j1 + 3] - a[j3 + 3];\n    a[j0 + 2] = x0r + x2r;\n    a[j0 + 3] = x0i + x2i;\n    a[j1 + 2] = x0r - x2r;\n    a[j1 + 3] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2 + 2] = wk1i * x0r - wk1r * x0i;\n    a[j2 + 3] = wk1i * x0i + wk1r * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3 + 2] = wk3i * x0r + wk3r * x0i;\n    a[j3 + 3] = wk3i * x0i - wk3r * x0r;\n}\n\n\nvoid cftb1st(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = -a[1] - a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = -a[1] + a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i - x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i + x2i;\n    a[j2] = x1r + x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r - x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    csc1 = w[2];\n    csc3 = w[3];\n    wd1r = 1;\n    wd1i = 0;\n    wd3r = 1;\n    wd3i = 0;\n    k = 0;\n    for (j = 2; j < mh - 2; j += 4) {\n        k += 4;\n        wk1r = csc1 * (wd1r + w[k]);\n        wk1i = csc1 * (wd1i + w[k + 1]);\n        wk3r = csc3 * (wd3r + w[k + 2]);\n        wk3i = csc3 * (wd3i + w[k + 3]);\n        wd1r = w[k];\n        wd1i = w[k + 1];\n        wd3r = w[k + 2];\n        wd3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = -a[j + 1] - a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = -a[j + 1] + a[j2 + 1];\n        y0r = a[j + 2] + a[j2 + 2];\n        y0i = -a[j + 3] - a[j2 + 3];\n        y1r = a[j + 2] - a[j2 + 2];\n        y1i = -a[j + 3] + a[j2 + 3];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 + 2] + a[j3 + 2];\n        y2i = a[j1 + 3] + a[j3 + 3];\n        y3r = a[j1 + 2] - a[j3 + 2];\n        y3i = a[j1 + 3] - a[j3 + 3];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i - x2i;\n        a[j + 2] = y0r + y2r;\n        a[j + 3] = y0i - y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i + x2i;\n        a[j1 + 2] = y0r - y2r;\n        a[j1 + 3] = y0i + y2i;\n        x0r = x1r + x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i + y3r;\n        a[j2 + 2] = wd1r * x0r - wd1i * x0i;\n        a[j2 + 3] = wd1r * x0i + wd1i * x0r;\n        x0r = x1r - x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i - y3r;\n        a[j3 + 2] = wd3r * x0r + wd3i * x0i;\n        a[j3 + 3] = wd3r * x0i - wd3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = -a[j0 + 1] - a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = -a[j0 + 1] + a[j2 + 1];\n        y0r = a[j0 - 2] + a[j2 - 2];\n        y0i = -a[j0 - 1] - a[j2 - 1];\n        y1r = a[j0 - 2] - a[j2 - 2];\n        y1i = -a[j0 - 1] + a[j2 - 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 - 2] + a[j3 - 2];\n        y2i = a[j1 - 1] + a[j3 - 1];\n        y3r = a[j1 - 2] - a[j3 - 2];\n        y3i = a[j1 - 1] - a[j3 - 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i - x2i;\n        a[j0 - 2] = y0r + y2r;\n        a[j0 - 1] = y0i - y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i + x2i;\n        a[j1 - 2] = y0r - y2r;\n        a[j1 - 1] = y0i + y2i;\n        x0r = x1r + x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i + y3r;\n        a[j2 - 2] = wd1i * x0r - wd1r * x0i;\n        a[j2 - 1] = wd1i * x0i + wd1r * x0r;\n        x0r = x1r - x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i - y3r;\n        a[j3 - 2] = wd3i * x0r + wd3r * x0i;\n        a[j3 - 1] = wd3i * x0i - wd3r * x0r;\n    }\n    wk1r = csc1 * (wd1r + wn4r);\n    wk1i = csc1 * (wd1i + wn4r);\n    wk3r = csc3 * (wd3r - wn4r);\n    wk3i = csc3 * (wd3i - wn4r);\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0 - 2] + a[j2 - 2];\n    x0i = -a[j0 - 1] - a[j2 - 1];\n    x1r = a[j0 - 2] - a[j2 - 2];\n    x1i = -a[j0 - 1] + a[j2 - 1];\n    x2r = a[j1 - 2] + a[j3 - 2];\n    x2i = a[j1 - 1] + a[j3 - 1];\n    x3r = a[j1 - 2] - a[j3 - 2];\n    x3i = a[j1 - 1] - a[j3 - 1];\n    a[j0 - 2] = x0r + x2r;\n    a[j0 - 1] = x0i - x2i;\n    a[j1 - 2] = x0r - x2r;\n    a[j1 - 1] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2 - 2] = wk1r * x0r - wk1i * x0i;\n    a[j2 - 1] = wk1r * x0i + wk1i * x0r;\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3 - 2] = wk3r * x0r + wk3i * x0i;\n    a[j3 - 1] = wk3r * x0i - wk3i * x0r;\n    x0r = a[j0] + a[j2];\n    x0i = -a[j0 + 1] - a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = -a[j0 + 1] + a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i - x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n    x0r = a[j0 + 2] + a[j2 + 2];\n    x0i = -a[j0 + 3] - a[j2 + 3];\n    x1r = a[j0 + 2] - a[j2 + 2];\n    x1i = -a[j0 + 3] + a[j2 + 3];\n    x2r = a[j1 + 2] + a[j3 + 2];\n    x2i = a[j1 + 3] + a[j3 + 3];\n    x3r = a[j1 + 2] - a[j3 + 2];\n    x3i = a[j1 + 3] - a[j3 + 3];\n    a[j0 + 2] = x0r + x2r;\n    a[j0 + 3] = x0i - x2i;\n    a[j1 + 2] = x0r - x2r;\n    a[j1 + 3] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2 + 2] = wk1i * x0r - wk1r * x0i;\n    a[j2 + 3] = wk1i * x0i + wk1r * x0r;\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3 + 2] = wk3i * x0r + wk3r * x0i;\n    a[j3 + 3] = wk3i * x0i - wk3r * x0r;\n}\n\n\n#ifdef USE_CDFT_THREADS\nstruct cdft_arg_st {\n    int n0;\n    int n;\n    double *a;\n    int nw;\n    double *w;\n};\ntypedef struct cdft_arg_st cdft_arg_t;\n\n\nvoid cftrec4_th(int n, double *a, int nw, double *w) {\n    void *cftrec1_th(void *p);\n    void *cftrec2_th(void *p);\n    int i, idiv4, m, nthread;\n    cdft_thread_t th[4];\n    cdft_arg_t ag[4];\n\n    nthread = 2;\n    idiv4 = 0;\n    m = n >> 1;\n    if (n > CDFT_4THREADS_BEGIN_N) {\n        nthread = 4;\n        idiv4 = 1;\n        m >>= 1;\n    }\n    for (i = 0; i < nthread; i++) {\n        ag[i].n0 = n;\n        ag[i].n = m;\n        ag[i].a = &a[i * m];\n        ag[i].nw = nw;\n        ag[i].w = w;\n        if (i != idiv4) {\n            cdft_thread_create(&th[i], cftrec1_th, &ag[i]);\n        } else {\n            cdft_thread_create(&th[i], cftrec2_th, &ag[i]);\n        }\n    }\n    for (i = 0; i < nthread; i++) {\n        cdft_thread_wait(th[i]);\n    }\n}\n\n\nvoid *cftrec1_th(void *p) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl1(int n, double *a, double *w);\n    int isplt, j, k, m, n, n0, nw;\n    double *a, *w;\n\n    n0 = ((cdft_arg_t *)p)->n0;\n    n = ((cdft_arg_t *)p)->n;\n    a = ((cdft_arg_t *)p)->a;\n    nw = ((cdft_arg_t *)p)->nw;\n    w = ((cdft_arg_t *)p)->w;\n    m = n0;\n    while (m > 512) {\n        m >>= 2;\n        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);\n    }\n    cftleaf(m, 1, &a[n - m], nw, w);\n    k = 0;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n    return (void *)0;\n}\n\n\nvoid *cftrec2_th(void *p) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    int isplt, j, k, m, n, n0, nw;\n    double *a, *w;\n\n    n0 = ((cdft_arg_t *)p)->n0;\n    n = ((cdft_arg_t *)p)->n;\n    a = ((cdft_arg_t *)p)->a;\n    nw = ((cdft_arg_t *)p)->nw;\n    w = ((cdft_arg_t *)p)->w;\n    k = 1;\n    m = n0;\n    while (m > 512) {\n        m >>= 2;\n        k <<= 2;\n        cftmdl2(m, &a[n - m], &w[nw - m]);\n    }\n    cftleaf(m, 0, &a[n - m], nw, w);\n    k >>= 1;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n    return (void *)0;\n}\n#endif /* USE_CDFT_THREADS */\n\n\nvoid cftrec4(int n, double *a, int nw, double *w) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl1(int n, double *a, double *w);\n    int isplt, j, k, m;\n\n    m = n;\n    while (m > 512) {\n        m >>= 2;\n        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);\n    }\n    cftleaf(m, 1, &a[n - m], nw, w);\n    k = 0;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n}\n\n\nint cfttree(int n, int j, int k, double *a, int nw, double *w) {\n    void cftmdl1(int n, double *a, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    int i, isplt, m;\n\n    if ((k & 3) != 0) {\n        isplt = k & 1;\n        if (isplt != 0) {\n            cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]);\n        } else {\n            cftmdl2(n, &a[j - n], &w[nw - n]);\n        }\n    } else {\n        m = n;\n        for (i = k; (i & 3) == 0; i >>= 2) {\n            m <<= 2;\n        }\n        isplt = i & 1;\n        if (isplt != 0) {\n            while (m > 128) {\n                cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]);\n                m >>= 2;\n            }\n        } else {\n            while (m > 128) {\n                cftmdl2(m, &a[j - m], &w[nw - m]);\n                m >>= 2;\n            }\n        }\n    }\n    return isplt;\n}\n\n\nvoid cftleaf(int n, int isplt, double *a, int nw, double *w) {\n    void cftmdl1(int n, double *a, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    void cftf161(double *a, double *w);\n    void cftf162(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf082(double *a, double *w);\n\n    if (n == 512) {\n        cftmdl1(128, a, &w[nw - 64]);\n        cftf161(a, &w[nw - 8]);\n        cftf162(&a[32], &w[nw - 32]);\n        cftf161(&a[64], &w[nw - 8]);\n        cftf161(&a[96], &w[nw - 8]);\n        cftmdl2(128, &a[128], &w[nw - 128]);\n        cftf161(&a[128], &w[nw - 8]);\n        cftf162(&a[160], &w[nw - 32]);\n        cftf161(&a[192], &w[nw - 8]);\n        cftf162(&a[224], &w[nw - 32]);\n        cftmdl1(128, &a[256], &w[nw - 64]);\n        cftf161(&a[256], &w[nw - 8]);\n        cftf162(&a[288], &w[nw - 32]);\n        cftf161(&a[320], &w[nw - 8]);\n        cftf161(&a[352], &w[nw - 8]);\n        if (isplt != 0) {\n            cftmdl1(128, &a[384], &w[nw - 64]);\n            cftf161(&a[480], &w[nw - 8]);\n        } else {\n            cftmdl2(128, &a[384], &w[nw - 128]);\n            cftf162(&a[480], &w[nw - 32]);\n        }\n        cftf161(&a[384], &w[nw - 8]);\n        cftf162(&a[416], &w[nw - 32]);\n        cftf161(&a[448], &w[nw - 8]);\n    } else {\n        cftmdl1(64, a, &w[nw - 32]);\n        cftf081(a, &w[nw - 8]);\n        cftf082(&a[16], &w[nw - 8]);\n        cftf081(&a[32], &w[nw - 8]);\n        cftf081(&a[48], &w[nw - 8]);\n        cftmdl2(64, &a[64], &w[nw - 64]);\n        cftf081(&a[64], &w[nw - 8]);\n        cftf082(&a[80], &w[nw - 8]);\n        cftf081(&a[96], &w[nw - 8]);\n        cftf082(&a[112], &w[nw - 8]);\n        cftmdl1(64, &a[128], &w[nw - 32]);\n        cftf081(&a[128], &w[nw - 8]);\n        cftf082(&a[144], &w[nw - 8]);\n        cftf081(&a[160], &w[nw - 8]);\n        cftf081(&a[176], &w[nw - 8]);\n        if (isplt != 0) {\n            cftmdl1(64, &a[192], &w[nw - 32]);\n            cftf081(&a[240], &w[nw - 8]);\n        } else {\n            cftmdl2(64, &a[192], &w[nw - 64]);\n            cftf082(&a[240], &w[nw - 8]);\n        }\n        cftf081(&a[192], &w[nw - 8]);\n        cftf082(&a[208], &w[nw - 8]);\n        cftf081(&a[224], &w[nw - 8]);\n    }\n}\n\n\nvoid cftmdl1(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, wk1r, wk1i, wk3r, wk3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = a[1] + a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = a[1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    a[j2] = x1r - x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r + x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    k = 0;\n    for (j = 2; j < mh; j += 2) {\n        k += 4;\n        wk1r = w[k];\n        wk1i = w[k + 1];\n        wk3r = w[k + 2];\n        wk3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = a[j + 1] + a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = a[j + 1] - a[j2 + 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i + x2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = a[j0 + 1] + a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = a[j0 + 1] - a[j2 + 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i + x2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n    }\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0] + a[j2];\n    x0i = a[j0 + 1] + a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = a[j0 + 1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n}\n\n\nvoid cftmdl2(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, kr, m, mh;\n    double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    wn4r = w[1];\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] - a[j2 + 1];\n    x0i = a[1] + a[j2];\n    x1r = a[0] + a[j2 + 1];\n    x1i = a[1] - a[j2];\n    x2r = a[j1] - a[j3 + 1];\n    x2i = a[j1 + 1] + a[j3];\n    x3r = a[j1] + a[j3 + 1];\n    x3i = a[j1 + 1] - a[j3];\n    y0r = wn4r * (x2r - x2i);\n    y0i = wn4r * (x2i + x2r);\n    a[0] = x0r + y0r;\n    a[1] = x0i + y0i;\n    a[j1] = x0r - y0r;\n    a[j1 + 1] = x0i - y0i;\n    y0r = wn4r * (x3r - x3i);\n    y0i = wn4r * (x3i + x3r);\n    a[j2] = x1r - y0i;\n    a[j2 + 1] = x1i + y0r;\n    a[j3] = x1r + y0i;\n    a[j3 + 1] = x1i - y0r;\n    k = 0;\n    kr = 2 * m;\n    for (j = 2; j < mh; j += 2) {\n        k += 4;\n        wk1r = w[k];\n        wk1i = w[k + 1];\n        wk3r = w[k + 2];\n        wk3i = w[k + 3];\n        kr -= 4;\n        wd1i = w[kr];\n        wd1r = w[kr + 1];\n        wd3i = w[kr + 2];\n        wd3r = w[kr + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] - a[j2 + 1];\n        x0i = a[j + 1] + a[j2];\n        x1r = a[j] + a[j2 + 1];\n        x1i = a[j + 1] - a[j2];\n        x2r = a[j1] - a[j3 + 1];\n        x2i = a[j1 + 1] + a[j3];\n        x3r = a[j1] + a[j3 + 1];\n        x3i = a[j1 + 1] - a[j3];\n        y0r = wk1r * x0r - wk1i * x0i;\n        y0i = wk1r * x0i + wk1i * x0r;\n        y2r = wd1r * x2r - wd1i * x2i;\n        y2i = wd1r * x2i + wd1i * x2r;\n        a[j] = y0r + y2r;\n        a[j + 1] = y0i + y2i;\n        a[j1] = y0r - y2r;\n        a[j1 + 1] = y0i - y2i;\n        y0r = wk3r * x1r + wk3i * x1i;\n        y0i = wk3r * x1i - wk3i * x1r;\n        y2r = wd3r * x3r + wd3i * x3i;\n        y2i = wd3r * x3i - wd3i * x3r;\n        a[j2] = y0r + y2r;\n        a[j2 + 1] = y0i + y2i;\n        a[j3] = y0r - y2r;\n        a[j3 + 1] = y0i - y2i;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] - a[j2 + 1];\n        x0i = a[j0 + 1] + a[j2];\n        x1r = a[j0] + a[j2 + 1];\n        x1i = a[j0 + 1] - a[j2];\n        x2r = a[j1] - a[j3 + 1];\n        x2i = a[j1 + 1] + a[j3];\n        x3r = a[j1] + a[j3 + 1];\n        x3i = a[j1 + 1] - a[j3];\n        y0r = wd1i * x0r - wd1r * x0i;\n        y0i = wd1i * x0i + wd1r * x0r;\n        y2r = wk1i * x2r - wk1r * x2i;\n        y2i = wk1i * x2i + wk1r * x2r;\n        a[j0] = y0r + y2r;\n        a[j0 + 1] = y0i + y2i;\n        a[j1] = y0r - y2r;\n        a[j1 + 1] = y0i - y2i;\n        y0r = wd3i * x1r + wd3r * x1i;\n        y0i = wd3i * x1i - wd3r * x1r;\n        y2r = wk3i * x3r + wk3r * x3i;\n        y2i = wk3i * x3i - wk3r * x3r;\n        a[j2] = y0r + y2r;\n        a[j2 + 1] = y0i + y2i;\n        a[j3] = y0r - y2r;\n        a[j3 + 1] = y0i - y2i;\n    }\n    wk1r = w[m];\n    wk1i = w[m + 1];\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0] - a[j2 + 1];\n    x0i = a[j0 + 1] + a[j2];\n    x1r = a[j0] + a[j2 + 1];\n    x1i = a[j0 + 1] - a[j2];\n    x2r = a[j1] - a[j3 + 1];\n    x2i = a[j1 + 1] + a[j3];\n    x3r = a[j1] + a[j3 + 1];\n    x3i = a[j1 + 1] - a[j3];\n    y0r = wk1r * x0r - wk1i * x0i;\n    y0i = wk1r * x0i + wk1i * x0r;\n    y2r = wk1i * x2r - wk1r * x2i;\n    y2i = wk1i * x2i + wk1r * x2r;\n    a[j0] = y0r + y2r;\n    a[j0 + 1] = y0i + y2i;\n    a[j1] = y0r - y2r;\n    a[j1 + 1] = y0i - y2i;\n    y0r = wk1i * x1r - wk1r * x1i;\n    y0i = wk1i * x1i + wk1r * x1r;\n    y2r = wk1r * x3r - wk1i * x3i;\n    y2i = wk1r * x3i + wk1i * x3r;\n    a[j2] = y0r - y2r;\n    a[j2 + 1] = y0i - y2i;\n    a[j3] = y0r + y2r;\n    a[j3 + 1] = y0i + y2i;\n}\n\n\nvoid cftfx41(int n, double *a, int nw, double *w) {\n    void cftf161(double *a, double *w);\n    void cftf162(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf082(double *a, double *w);\n\n    if (n == 128) {\n        cftf161(a, &w[nw - 8]);\n        cftf162(&a[32], &w[nw - 32]);\n        cftf161(&a[64], &w[nw - 8]);\n        cftf161(&a[96], &w[nw - 8]);\n    } else {\n        cftf081(a, &w[nw - 8]);\n        cftf082(&a[16], &w[nw - 8]);\n        cftf081(&a[32], &w[nw - 8]);\n        cftf081(&a[48], &w[nw - 8]);\n    }\n}\n\n\nvoid cftf161(double *a, double *w) {\n    double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i,\n        y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,\n        y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i,\n        y14r, y14i, y15r, y15i;\n\n    wn4r = w[1];\n    wk1r = w[2];\n    wk1i = w[3];\n    x0r = a[0] + a[16];\n    x0i = a[1] + a[17];\n    x1r = a[0] - a[16];\n    x1i = a[1] - a[17];\n    x2r = a[8] + a[24];\n    x2i = a[9] + a[25];\n    x3r = a[8] - a[24];\n    x3i = a[9] - a[25];\n    y0r = x0r + x2r;\n    y0i = x0i + x2i;\n    y4r = x0r - x2r;\n    y4i = x0i - x2i;\n    y8r = x1r - x3i;\n    y8i = x1i + x3r;\n    y12r = x1r + x3i;\n    y12i = x1i - x3r;\n    x0r = a[2] + a[18];\n    x0i = a[3] + a[19];\n    x1r = a[2] - a[18];\n    x1i = a[3] - a[19];\n    x2r = a[10] + a[26];\n    x2i = a[11] + a[27];\n    x3r = a[10] - a[26];\n    x3i = a[11] - a[27];\n    y1r = x0r + x2r;\n    y1i = x0i + x2i;\n    y5r = x0r - x2r;\n    y5i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y9r = wk1r * x0r - wk1i * x0i;\n    y9i = wk1r * x0i + wk1i * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y13r = wk1i * x0r - wk1r * x0i;\n    y13i = wk1i * x0i + wk1r * x0r;\n    x0r = a[4] + a[20];\n    x0i = a[5] + a[21];\n    x1r = a[4] - a[20];\n    x1i = a[5] - a[21];\n    x2r = a[12] + a[28];\n    x2i = a[13] + a[29];\n    x3r = a[12] - a[28];\n    x3i = a[13] - a[29];\n    y2r = x0r + x2r;\n    y2i = x0i + x2i;\n    y6r = x0r - x2r;\n    y6i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y10r = wn4r * (x0r - x0i);\n    y10i = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y14r = wn4r * (x0r + x0i);\n    y14i = wn4r * (x0i - x0r);\n    x0r = a[6] + a[22];\n    x0i = a[7] + a[23];\n    x1r = a[6] - a[22];\n    x1i = a[7] - a[23];\n    x2r = a[14] + a[30];\n    x2i = a[15] + a[31];\n    x3r = a[14] - a[30];\n    x3i = a[15] - a[31];\n    y3r = x0r + x2r;\n    y3i = x0i + x2i;\n    y7r = x0r - x2r;\n    y7i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y11r = wk1i * x0r - wk1r * x0i;\n    y11i = wk1i * x0i + wk1r * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y15r = wk1r * x0r - wk1i * x0i;\n    y15i = wk1r * x0i + wk1i * x0r;\n    x0r = y12r - y14r;\n    x0i = y12i - y14i;\n    x1r = y12r + y14r;\n    x1i = y12i + y14i;\n    x2r = y13r - y15r;\n    x2i = y13i - y15i;\n    x3r = y13r + y15r;\n    x3i = y13i + y15i;\n    a[24] = x0r + x2r;\n    a[25] = x0i + x2i;\n    a[26] = x0r - x2r;\n    a[27] = x0i - x2i;\n    a[28] = x1r - x3i;\n    a[29] = x1i + x3r;\n    a[30] = x1r + x3i;\n    a[31] = x1i - x3r;\n    x0r = y8r + y10r;\n    x0i = y8i + y10i;\n    x1r = y8r - y10r;\n    x1i = y8i - y10i;\n    x2r = y9r + y11r;\n    x2i = y9i + y11i;\n    x3r = y9r - y11r;\n    x3i = y9i - y11i;\n    a[16] = x0r + x2r;\n    a[17] = x0i + x2i;\n    a[18] = x0r - x2r;\n    a[19] = x0i - x2i;\n    a[20] = x1r - x3i;\n    a[21] = x1i + x3r;\n    a[22] = x1r + x3i;\n    a[23] = x1i - x3r;\n    x0r = y5r - y7i;\n    x0i = y5i + y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    x0r = y5r + y7i;\n    x0i = y5i - y7r;\n    x3r = wn4r * (x0r - x0i);\n    x3i = wn4r * (x0i + x0r);\n    x0r = y4r - y6i;\n    x0i = y4i + y6r;\n    x1r = y4r + y6i;\n    x1i = y4i - y6r;\n    a[8] = x0r + x2r;\n    a[9] = x0i + x2i;\n    a[10] = x0r - x2r;\n    a[11] = x0i - x2i;\n    a[12] = x1r - x3i;\n    a[13] = x1i + x3r;\n    a[14] = x1r + x3i;\n    a[15] = x1i - x3r;\n    x0r = y0r + y2r;\n    x0i = y0i + y2i;\n    x1r = y0r - y2r;\n    x1i = y0i - y2i;\n    x2r = y1r + y3r;\n    x2i = y1i + y3i;\n    x3r = y1r - y3r;\n    x3i = y1i - y3i;\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x0r - x2r;\n    a[3] = x0i - x2i;\n    a[4] = x1r - x3i;\n    a[5] = x1i + x3r;\n    a[6] = x1r + x3i;\n    a[7] = x1i - x3r;\n}\n\n\nvoid cftf162(double *a, double *w) {\n    double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r,\n        x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r,\n        y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i,\n        y13r, y13i, y14r, y14i, y15r, y15i;\n\n    wn4r = w[1];\n    wk1r = w[4];\n    wk1i = w[5];\n    wk3r = w[6];\n    wk3i = -w[7];\n    wk2r = w[8];\n    wk2i = w[9];\n    x1r = a[0] - a[17];\n    x1i = a[1] + a[16];\n    x0r = a[8] - a[25];\n    x0i = a[9] + a[24];\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    y0r = x1r + x2r;\n    y0i = x1i + x2i;\n    y4r = x1r - x2r;\n    y4i = x1i - x2i;\n    x1r = a[0] + a[17];\n    x1i = a[1] - a[16];\n    x0r = a[8] + a[25];\n    x0i = a[9] - a[24];\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    y8r = x1r - x2i;\n    y8i = x1i + x2r;\n    y12r = x1r + x2i;\n    y12i = x1i - x2r;\n    x0r = a[2] - a[19];\n    x0i = a[3] + a[18];\n    x1r = wk1r * x0r - wk1i * x0i;\n    x1i = wk1r * x0i + wk1i * x0r;\n    x0r = a[10] - a[27];\n    x0i = a[11] + a[26];\n    x2r = wk3i * x0r - wk3r * x0i;\n    x2i = wk3i * x0i + wk3r * x0r;\n    y1r = x1r + x2r;\n    y1i = x1i + x2i;\n    y5r = x1r - x2r;\n    y5i = x1i - x2i;\n    x0r = a[2] + a[19];\n    x0i = a[3] - a[18];\n    x1r = wk3r * x0r - wk3i * x0i;\n    x1i = wk3r * x0i + wk3i * x0r;\n    x0r = a[10] + a[27];\n    x0i = a[11] - a[26];\n    x2r = wk1r * x0r + wk1i * x0i;\n    x2i = wk1r * x0i - wk1i * x0r;\n    y9r = x1r - x2r;\n    y9i = x1i - x2i;\n    y13r = x1r + x2r;\n    y13i = x1i + x2i;\n    x0r = a[4] - a[21];\n    x0i = a[5] + a[20];\n    x1r = wk2r * x0r - wk2i * x0i;\n    x1i = wk2r * x0i + wk2i * x0r;\n    x0r = a[12] - a[29];\n    x0i = a[13] + a[28];\n    x2r = wk2i * x0r - wk2r * x0i;\n    x2i = wk2i * x0i + wk2r * x0r;\n    y2r = x1r + x2r;\n    y2i = x1i + x2i;\n    y6r = x1r - x2r;\n    y6i = x1i - x2i;\n    x0r = a[4] + a[21];\n    x0i = a[5] - a[20];\n    x1r = wk2i * x0r - wk2r * x0i;\n    x1i = wk2i * x0i + wk2r * x0r;\n    x0r = a[12] + a[29];\n    x0i = a[13] - a[28];\n    x2r = wk2r * x0r - wk2i * x0i;\n    x2i = wk2r * x0i + wk2i * x0r;\n    y10r = x1r - x2r;\n    y10i = x1i - x2i;\n    y14r = x1r + x2r;\n    y14i = x1i + x2i;\n    x0r = a[6] - a[23];\n    x0i = a[7] + a[22];\n    x1r = wk3r * x0r - wk3i * x0i;\n    x1i = wk3r * x0i + wk3i * x0r;\n    x0r = a[14] - a[31];\n    x0i = a[15] + a[30];\n    x2r = wk1i * x0r - wk1r * x0i;\n    x2i = wk1i * x0i + wk1r * x0r;\n    y3r = x1r + x2r;\n    y3i = x1i + x2i;\n    y7r = x1r - x2r;\n    y7i = x1i - x2i;\n    x0r = a[6] + a[23];\n    x0i = a[7] - a[22];\n    x1r = wk1i * x0r + wk1r * x0i;\n    x1i = wk1i * x0i - wk1r * x0r;\n    x0r = a[14] + a[31];\n    x0i = a[15] - a[30];\n    x2r = wk3i * x0r - wk3r * x0i;\n    x2i = wk3i * x0i + wk3r * x0r;\n    y11r = x1r + x2r;\n    y11i = x1i + x2i;\n    y15r = x1r - x2r;\n    y15i = x1i - x2i;\n    x1r = y0r + y2r;\n    x1i = y0i + y2i;\n    x2r = y1r + y3r;\n    x2i = y1i + y3i;\n    a[0] = x1r + x2r;\n    a[1] = x1i + x2i;\n    a[2] = x1r - x2r;\n    a[3] = x1i - x2i;\n    x1r = y0r - y2r;\n    x1i = y0i - y2i;\n    x2r = y1r - y3r;\n    x2i = y1i - y3i;\n    a[4] = x1r - x2i;\n    a[5] = x1i + x2r;\n    a[6] = x1r + x2i;\n    a[7] = x1i - x2r;\n    x1r = y4r - y6i;\n    x1i = y4i + y6r;\n    x0r = y5r - y7i;\n    x0i = y5i + y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[8] = x1r + x2r;\n    a[9] = x1i + x2i;\n    a[10] = x1r - x2r;\n    a[11] = x1i - x2i;\n    x1r = y4r + y6i;\n    x1i = y4i - y6r;\n    x0r = y5r + y7i;\n    x0i = y5i - y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[12] = x1r - x2i;\n    a[13] = x1i + x2r;\n    a[14] = x1r + x2i;\n    a[15] = x1i - x2r;\n    x1r = y8r + y10r;\n    x1i = y8i + y10i;\n    x2r = y9r - y11r;\n    x2i = y9i - y11i;\n    a[16] = x1r + x2r;\n    a[17] = x1i + x2i;\n    a[18] = x1r - x2r;\n    a[19] = x1i - x2i;\n    x1r = y8r - y10r;\n    x1i = y8i - y10i;\n    x2r = y9r + y11r;\n    x2i = y9i + y11i;\n    a[20] = x1r - x2i;\n    a[21] = x1i + x2r;\n    a[22] = x1r + x2i;\n    a[23] = x1i - x2r;\n    x1r = y12r - y14i;\n    x1i = y12i + y14r;\n    x0r = y13r + y15i;\n    x0i = y13i - y15r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[24] = x1r + x2r;\n    a[25] = x1i + x2i;\n    a[26] = x1r - x2r;\n    a[27] = x1i - x2i;\n    x1r = y12r + y14i;\n    x1i = y12i - y14r;\n    x0r = y13r - y15i;\n    x0i = y13i + y15r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[28] = x1r - x2i;\n    a[29] = x1i + x2r;\n    a[30] = x1r + x2i;\n    a[31] = x1i - x2r;\n}\n\n\nvoid cftf081(double *a, double *w) {\n    double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i,\n        y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;\n\n    wn4r = w[1];\n    x0r = a[0] + a[8];\n    x0i = a[1] + a[9];\n    x1r = a[0] - a[8];\n    x1i = a[1] - a[9];\n    x2r = a[4] + a[12];\n    x2i = a[5] + a[13];\n    x3r = a[4] - a[12];\n    x3i = a[5] - a[13];\n    y0r = x0r + x2r;\n    y0i = x0i + x2i;\n    y2r = x0r - x2r;\n    y2i = x0i - x2i;\n    y1r = x1r - x3i;\n    y1i = x1i + x3r;\n    y3r = x1r + x3i;\n    y3i = x1i - x3r;\n    x0r = a[2] + a[10];\n    x0i = a[3] + a[11];\n    x1r = a[2] - a[10];\n    x1i = a[3] - a[11];\n    x2r = a[6] + a[14];\n    x2i = a[7] + a[15];\n    x3r = a[6] - a[14];\n    x3i = a[7] - a[15];\n    y4r = x0r + x2r;\n    y4i = x0i + x2i;\n    y6r = x0r - x2r;\n    y6i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    x2r = x1r + x3i;\n    x2i = x1i - x3r;\n    y5r = wn4r * (x0r - x0i);\n    y5i = wn4r * (x0r + x0i);\n    y7r = wn4r * (x2r - x2i);\n    y7i = wn4r * (x2r + x2i);\n    a[8] = y1r + y5r;\n    a[9] = y1i + y5i;\n    a[10] = y1r - y5r;\n    a[11] = y1i - y5i;\n    a[12] = y3r - y7i;\n    a[13] = y3i + y7r;\n    a[14] = y3r + y7i;\n    a[15] = y3i - y7r;\n    a[0] = y0r + y4r;\n    a[1] = y0i + y4i;\n    a[2] = y0r - y4r;\n    a[3] = y0i - y4i;\n    a[4] = y2r - y6i;\n    a[5] = y2i + y6r;\n    a[6] = y2r + y6i;\n    a[7] = y2i - y6r;\n}\n\n\nvoid cftf082(double *a, double *w) {\n    double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;\n\n    wn4r = w[1];\n    wk1r = w[2];\n    wk1i = w[3];\n    y0r = a[0] - a[9];\n    y0i = a[1] + a[8];\n    y1r = a[0] + a[9];\n    y1i = a[1] - a[8];\n    x0r = a[4] - a[13];\n    x0i = a[5] + a[12];\n    y2r = wn4r * (x0r - x0i);\n    y2i = wn4r * (x0i + x0r);\n    x0r = a[4] + a[13];\n    x0i = a[5] - a[12];\n    y3r = wn4r * (x0r - x0i);\n    y3i = wn4r * (x0i + x0r);\n    x0r = a[2] - a[11];\n    x0i = a[3] + a[10];\n    y4r = wk1r * x0r - wk1i * x0i;\n    y4i = wk1r * x0i + wk1i * x0r;\n    x0r = a[2] + a[11];\n    x0i = a[3] - a[10];\n    y5r = wk1i * x0r - wk1r * x0i;\n    y5i = wk1i * x0i + wk1r * x0r;\n    x0r = a[6] - a[15];\n    x0i = a[7] + a[14];\n    y6r = wk1i * x0r - wk1r * x0i;\n    y6i = wk1i * x0i + wk1r * x0r;\n    x0r = a[6] + a[15];\n    x0i = a[7] - a[14];\n    y7r = wk1r * x0r - wk1i * x0i;\n    y7i = wk1r * x0i + wk1i * x0r;\n    x0r = y0r + y2r;\n    x0i = y0i + y2i;\n    x1r = y4r + y6r;\n    x1i = y4i + y6i;\n    a[0] = x0r + x1r;\n    a[1] = x0i + x1i;\n    a[2] = x0r - x1r;\n    a[3] = x0i - x1i;\n    x0r = y0r - y2r;\n    x0i = y0i - y2i;\n    x1r = y4r - y6r;\n    x1i = y4i - y6i;\n    a[4] = x0r - x1i;\n    a[5] = x0i + x1r;\n    a[6] = x0r + x1i;\n    a[7] = x0i - x1r;\n    x0r = y1r - y3i;\n    x0i = y1i + y3r;\n    x1r = y5r - y7r;\n    x1i = y5i - y7i;\n    a[8] = x0r + x1r;\n    a[9] = x0i + x1i;\n    a[10] = x0r - x1r;\n    a[11] = x0i - x1i;\n    x0r = y1r + y3i;\n    x0i = y1i - y3r;\n    x1r = y5r + y7r;\n    x1i = y5i + y7i;\n    a[12] = x0r - x1i;\n    a[13] = x0i + x1r;\n    a[14] = x0r + x1i;\n    a[15] = x0i - x1r;\n}\n\n\nvoid cftf040(double *a) {\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    x0r = a[0] + a[4];\n    x0i = a[1] + a[5];\n    x1r = a[0] - a[4];\n    x1i = a[1] - a[5];\n    x2r = a[2] + a[6];\n    x2i = a[3] + a[7];\n    x3r = a[2] - a[6];\n    x3i = a[3] - a[7];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x1r - x3i;\n    a[3] = x1i + x3r;\n    a[4] = x0r - x2r;\n    a[5] = x0i - x2i;\n    a[6] = x1r + x3i;\n    a[7] = x1i - x3r;\n}\n\n\nvoid cftb040(double *a) {\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    x0r = a[0] + a[4];\n    x0i = a[1] + a[5];\n    x1r = a[0] - a[4];\n    x1i = a[1] - a[5];\n    x2r = a[2] + a[6];\n    x2i = a[3] + a[7];\n    x3r = a[2] - a[6];\n    x3i = a[3] - a[7];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x1r + x3i;\n    a[3] = x1i - x3r;\n    a[4] = x0r - x2r;\n    a[5] = x0i - x2i;\n    a[6] = x1r - x3i;\n    a[7] = x1i + x3r;\n}\n\n\nvoid cftx020(double *a) {\n    double x0r, x0i;\n\n    x0r = a[0] - a[2];\n    x0i = a[1] - a[3];\n    a[0] += a[2];\n    a[1] += a[3];\n    a[2] = x0r;\n    a[3] = x0i;\n}\n\n\nvoid rftfsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr, xi, yr, yi;\n\n    m = n >> 1;\n    ks = 2 * nc / m;\n    kk = 0;\n    for (j = 2; j < m; j += 2) {\n        k = n - j;\n        kk += ks;\n        wkr = 0.5 - c[nc - kk];\n        wki = c[kk];\n        xr = a[j] - a[k];\n        xi = a[j + 1] + a[k + 1];\n        yr = wkr * xr - wki * xi;\n        yi = wkr * xi + wki * xr;\n        a[j] -= yr;\n        a[j + 1] -= yi;\n        a[k] += yr;\n        a[k + 1] -= yi;\n    }\n}\n\n\nvoid rftbsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr, xi, yr, yi;\n\n    m = n >> 1;\n    ks = 2 * nc / m;\n    kk = 0;\n    for (j = 2; j < m; j += 2) {\n        k = n - j;\n        kk += ks;\n        wkr = 0.5 - c[nc - kk];\n        wki = c[kk];\n        xr = a[j] - a[k];\n        xi = a[j + 1] + a[k + 1];\n        yr = wkr * xr + wki * xi;\n        yi = wkr * xi - wki * xr;\n        a[j] -= yr;\n        a[j + 1] -= yi;\n        a[k] += yr;\n        a[k + 1] -= yi;\n    }\n}\n\n\nvoid dctsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr;\n\n    m = n >> 1;\n    ks = nc / n;\n    kk = 0;\n    for (j = 1; j < m; j++) {\n        k = n - j;\n        kk += ks;\n        wkr = c[kk] - c[nc - kk];\n        wki = c[kk] + c[nc - kk];\n        xr = wki * a[j] - wkr * a[k];\n        a[j] = wkr * a[j] + wki * a[k];\n        a[k] = xr;\n    }\n    a[m] *= c[0];\n}\n\n\nvoid dstsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr;\n\n    m = n >> 1;\n    ks = nc / n;\n    kk = 0;\n    for (j = 1; j < m; j++) {\n        k = n - j;\n        kk += ks;\n        wkr = c[kk] - c[nc - kk];\n        wki = c[kk] + c[nc - kk];\n        xr = wki * a[k] - wkr * a[j];\n        a[k] = wkr * a[k] + wki * a[j];\n        a[j] = xr;\n    }\n    a[m] *= c[0];\n}\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/log.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Stack trace related stuff is from kaldi.\n * Refer to\n * https://github.com/kaldi-asr/kaldi/blob/master/src/base/kaldi-error.cc\n */\n\n#include \"kaldi-native-fbank/csrc/log.h\"\n\n#ifdef KNF_HAVE_EXECINFO_H\n#include <execinfo.h> // To get stack trace in error messages.\n#ifdef KNF_HAVE_CXXABI_H\n#include <cxxabi.h> // For name demangling.\n// Useful to decode the stack trace, but only used if we have execinfo.h\n#endif // KNF_HAVE_CXXABI_H\n#endif // KNF_HAVE_EXECINFO_H\n\n#include <stdlib.h>\n\n#include <ctime>\n#include <iomanip>\n#include <string>\n\nnamespace knf {\n\nstd::string GetDateTimeStr() {\n  std::ostringstream os;\n  std::time_t t = std::time(nullptr);\n  std::tm tm = *std::localtime(&t);\n  os << std::put_time(&tm, \"%F %T\"); // yyyy-mm-dd hh:mm:ss\n  return os.str();\n}\n\nstatic bool LocateSymbolRange(const std::string &trace_name, std::size_t *begin,\n                              std::size_t *end) {\n  // Find the first '_' with leading ' ' or '('.\n  *begin = std::string::npos;\n  for (std::size_t i = 1; i < trace_name.size(); ++i) {\n    if (trace_name[i] != '_') {\n      continue;\n    }\n    if (trace_name[i - 1] == ' ' || trace_name[i - 1] == '(') {\n      *begin = i;\n      break;\n    }\n  }\n  if (*begin == std::string::npos) {\n    return false;\n  }\n  *end = trace_name.find_first_of(\" +\", *begin);\n  return *end != std::string::npos;\n}\n\n#ifdef KNF_HAVE_EXECINFO_H\nstatic std::string Demangle(const std::string &trace_name) {\n#ifndef KNF_HAVE_CXXABI_H\n  return trace_name;\n#else  // KNF_HAVE_CXXABI_H\n  // Try demangle the symbol. We are trying to support the following formats\n  // produced by different platforms:\n  //\n  // Linux:\n  //   ./kaldi-error-test(_ZN5kaldi13UnitTestErrorEv+0xb) [0x804965d]\n  //\n  // Mac:\n  //   0 server 0x000000010f67614d _ZNK5kaldi13MessageLogger10LogMessageEv + 813\n  //\n  // We want to extract the name e.g., '_ZN5kaldi13UnitTestErrorEv' and\n  // demangle it info a readable name like kaldi::UnitTextError.\n  std::size_t begin, end;\n  if (!LocateSymbolRange(trace_name, &begin, &end)) {\n    return trace_name;\n  }\n  std::string symbol = trace_name.substr(begin, end - begin);\n  int status;\n  char *demangled_name = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status);\n  if (status == 0 && demangled_name != nullptr) {\n    symbol = demangled_name;\n    free(demangled_name);\n  }\n  return trace_name.substr(0, begin) + symbol +\n         trace_name.substr(end, std::string::npos);\n#endif // KNF_HAVE_CXXABI_H\n}\n#endif // KNF_HAVE_EXECINFO_H\n\nstd::string GetStackTrace() {\n  std::string ans;\n#ifdef KNF_HAVE_EXECINFO_H\n  constexpr const std::size_t kMaxTraceSize = 50;\n  constexpr const std::size_t kMaxTracePrint = 50; // Must be even.\n                                                   // Buffer for the trace.\n  void *trace[kMaxTraceSize];\n  // Get the trace.\n  std::size_t size = backtrace(trace, kMaxTraceSize);\n  // Get the trace symbols.\n  char **trace_symbol = backtrace_symbols(trace, size);\n  if (trace_symbol == nullptr)\n    return ans;\n\n  // Compose a human-readable backtrace string.\n  ans += \"[ Stack-Trace: ]\\n\";\n  if (size <= kMaxTracePrint) {\n    for (std::size_t i = 0; i < size; ++i) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n  } else { // Print out first+last (e.g.) 5.\n    for (std::size_t i = 0; i < kMaxTracePrint / 2; ++i) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n    ans += \".\\n.\\n.\\n\";\n    for (std::size_t i = size - kMaxTracePrint / 2; i < size; ++i) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n    if (size == kMaxTraceSize)\n      ans += \".\\n.\\n.\\n\"; // Stack was too long, probably a bug.\n  }\n\n  // We must free the array of pointers allocated by backtrace_symbols(),\n  // but not the strings themselves.\n  free(trace_symbol);\n#endif // KNF_HAVE_EXECINFO_H\n  return ans;\n}\n\n} // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/log.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// The content in this file is copied/modified from\n// https://github.com/k2-fsa/k2/blob/master/k2/csrc/log.h\n#ifndef KALDI_NATIVE_FBANK_CSRC_LOG_H_\n#define KALDI_NATIVE_FBANK_CSRC_LOG_H_\n\n#include <stdio.h>\n\n#include <mutex>  // NOLINT\n#include <sstream>\n#include <string>\n\nnamespace knf {\n\n#if defined(NDEBUG)\nconstexpr bool kDisableDebug = true;\n#else\nconstexpr bool kDisableDebug = false;\n#endif\n\nenum class LogLevel {\n  kTrace = 0,\n  kDebug = 1,\n  kInfo = 2,\n  kWarning = 3,\n  kError = 4,\n  kFatal = 5,  // print message and abort the program\n};\n\n// They are used in KNF_LOG(xxx), so their names\n// do not follow the google c++ code style\n//\n// You can use them in the following way:\n//\n//  KNF_LOG(TRACE) << \"some message\";\n//  KNF_LOG(DEBUG) << \"some message\";\n#ifndef _MSC_VER\nconstexpr LogLevel TRACE = LogLevel::kTrace;\nconstexpr LogLevel DEBUG = LogLevel::kDebug;\nconstexpr LogLevel INFO = LogLevel::kInfo;\nconstexpr LogLevel WARNING = LogLevel::kWarning;\nconstexpr LogLevel ERROR = LogLevel::kError;\nconstexpr LogLevel FATAL = LogLevel::kFatal;\n#else\n#define TRACE LogLevel::kTrace\n#define DEBUG LogLevel::kDebug\n#define INFO LogLevel::kInfo\n#define WARNING LogLevel::kWarning\n#define ERROR LogLevel::kError\n#define FATAL LogLevel::kFatal\n#endif\n\nstd::string GetStackTrace();\n\n/* Return the current log level.\n\n\n   If the current log level is TRACE, then all logged messages are printed out.\n\n   If the current log level is DEBUG, log messages with \"TRACE\" level are not\n   shown and all other levels are printed out.\n\n   Similarly, if the current log level is INFO, log message with \"TRACE\" and\n   \"DEBUG\" are not shown and all other levels are printed out.\n\n   If it is FATAL, then only FATAL messages are shown.\n */\ninline LogLevel GetCurrentLogLevel() {\n  static LogLevel log_level = INFO;\n  static std::once_flag init_flag;\n  std::call_once(init_flag, []() {\n    const char *env_log_level = std::getenv(\"KNF_LOG_LEVEL\");\n    if (env_log_level == nullptr) return;\n\n    std::string s = env_log_level;\n    if (s == \"TRACE\")\n      log_level = TRACE;\n    else if (s == \"DEBUG\")\n      log_level = DEBUG;\n    else if (s == \"INFO\")\n      log_level = INFO;\n    else if (s == \"WARNING\")\n      log_level = WARNING;\n    else if (s == \"ERROR\")\n      log_level = ERROR;\n    else if (s == \"FATAL\")\n      log_level = FATAL;\n    else\n      fprintf(stderr,\n              \"Unknown KNF_LOG_LEVEL: %s\"\n              \"\\nSupported values are: \"\n              \"TRACE, DEBUG, INFO, WARNING, ERROR, FATAL\",\n              s.c_str());\n  });\n  return log_level;\n}\n\ninline bool EnableAbort() {\n  static std::once_flag init_flag;\n  static bool enable_abort = false;\n  std::call_once(init_flag, []() {\n    enable_abort = (std::getenv(\"KNF_ABORT\") != nullptr);\n  });\n  return enable_abort;\n}\n\nclass Logger {\n public:\n  Logger(const char *filename, const char *func_name, uint32_t line_num,\n         LogLevel level)\n      : filename_(filename),\n        func_name_(func_name),\n        line_num_(line_num),\n        level_(level) {\n    cur_level_ = GetCurrentLogLevel();\n    fprintf(stderr, \"here\\n\");\n    switch (level) {\n      case TRACE:\n        if (cur_level_ <= TRACE) fprintf(stderr, \"[T] \");\n        break;\n      case DEBUG:\n        if (cur_level_ <= DEBUG) fprintf(stderr, \"[D] \");\n        break;\n      case INFO:\n        if (cur_level_ <= INFO) fprintf(stderr, \"[I] \");\n        break;\n      case WARNING:\n        if (cur_level_ <= WARNING) fprintf(stderr, \"[W] \");\n        break;\n      case ERROR:\n        if (cur_level_ <= ERROR) fprintf(stderr, \"[E] \");\n        break;\n      case FATAL:\n        if (cur_level_ <= FATAL) fprintf(stderr, \"[F] \");\n        break;\n    }\n\n    if (cur_level_ <= level_) {\n      fprintf(stderr, \"%s:%u:%s \", filename, line_num, func_name);\n    }\n  }\n\n  ~Logger() noexcept(false) {\n    static constexpr const char *kErrMsg = R\"(\n    Some bad things happened. Please read the above error messages and stack\n    trace. If you are using Python, the following command may be helpful:\n\n      gdb --args python /path/to/your/code.py\n\n    (You can use `gdb` to debug the code. Please consider compiling\n    a debug version of KNF.).\n\n    If you are unable to fix it, please open an issue at:\n\n      https://github.com/csukuangfj/kaldi-native-fbank/issues/new\n    )\";\n    fprintf(stderr, \"\\n\");\n    if (level_ == FATAL) {\n      std::string stack_trace = GetStackTrace();\n      if (!stack_trace.empty()) {\n        fprintf(stderr, \"\\n\\n%s\\n\", stack_trace.c_str());\n      }\n\n      fflush(nullptr);\n\n#ifndef __ANDROID_API__\n      if (EnableAbort()) {\n        // NOTE: abort() will terminate the program immediately without\n        // printing the Python stack backtrace.\n        abort();\n      }\n\n      throw std::runtime_error(kErrMsg);\n#else\n      abort();\n#endif\n    }\n  }\n\n  const Logger &operator<<(bool b) const {\n    if (cur_level_ <= level_) {\n      fprintf(stderr, b ? \"true\" : \"false\");\n    }\n    return *this;\n  }\n\n  const Logger &operator<<(int8_t i) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%d\", i);\n    return *this;\n  }\n\n  const Logger &operator<<(const char *s) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%s\", s);\n    return *this;\n  }\n\n  const Logger &operator<<(int32_t i) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%d\", i);\n    return *this;\n  }\n\n  const Logger &operator<<(uint32_t i) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%u\", i);\n    return *this;\n  }\n\n  const Logger &operator<<(uint64_t i) const {\n    if (cur_level_ <= level_)\n      fprintf(stderr, \"%llu\", (long long unsigned int)i);  // NOLINT\n    return *this;\n  }\n\n  const Logger &operator<<(int64_t i) const {\n    if (cur_level_ <= level_)\n      fprintf(stderr, \"%lli\", (long long int)i);  // NOLINT\n    return *this;\n  }\n\n  const Logger &operator<<(float f) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%f\", f);\n    return *this;\n  }\n\n  const Logger &operator<<(double d) const {\n    if (cur_level_ <= level_) fprintf(stderr, \"%f\", d);\n    return *this;\n  }\n\n  template <typename T>\n  const Logger &operator<<(const T &t) const {\n    // require T overloads operator<<\n    std::ostringstream os;\n    os << t;\n    return *this << os.str().c_str();\n  }\n\n  // specialization to fix compile error: `stringstream << nullptr` is ambiguous\n  const Logger &operator<<(const std::nullptr_t &null) const {\n    if (cur_level_ <= level_) *this << \"(null)\";\n    return *this;\n  }\n\n private:\n  const char *filename_;\n  const char *func_name_;\n  uint32_t line_num_;\n  LogLevel level_;\n  LogLevel cur_level_;\n};\n\nclass Voidifier {\n public:\n  void operator&(const Logger &)const {}\n};\n\n}  // namespace knf\n\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) || \\\n    defined(__PRETTY_FUNCTION__)\n// for clang and GCC\n#define KNF_FUNC __PRETTY_FUNCTION__\n#else\n// for other compilers\n#define KNF_FUNC __func__\n#endif\n\n#define KNF_STATIC_ASSERT(x) static_assert(x, \"\")\n\n#define KNF_CHECK(x)                                                  \\\n  (x) ? (void)0                                                       \\\n      : ::knf::Voidifier() &                                          \\\n            ::knf::Logger(__FILE__, KNF_FUNC, __LINE__, ::knf::FATAL) \\\n                << \"Check failed: \" << #x << \" \"\n\n// WARNING: x and y may be evaluated multiple times, but this happens only\n// when the check fails. Since the program aborts if it fails, we don't think\n// the extra evaluation of x and y matters.\n//\n// CAUTION: we recommend the following use case:\n//\n//      auto x = Foo();\n//      auto y = Bar();\n//      KNF_CHECK_EQ(x, y) << \"Some message\";\n//\n//  And please avoid\n//\n//      KNF_CHECK_EQ(Foo(), Bar());\n//\n//  if `Foo()` or `Bar()` causes some side effects, e.g., changing some\n//  local static variables or global variables.\n#define _KNF_CHECK_OP(x, y, op)                                              \\\n  ((x)op(y)) ? (void)0                                                       \\\n             : ::knf::Voidifier() &                                          \\\n                   ::knf::Logger(__FILE__, KNF_FUNC, __LINE__, ::knf::FATAL) \\\n                       << \"Check failed: \" << #x << \" \" << #op << \" \" << #y  \\\n                       << \" (\" << (x) << \" vs. \" << (y) << \") \"\n\n#define KNF_CHECK_EQ(x, y) _KNF_CHECK_OP(x, y, ==)\n#define KNF_CHECK_NE(x, y) _KNF_CHECK_OP(x, y, !=)\n#define KNF_CHECK_LT(x, y) _KNF_CHECK_OP(x, y, <)\n#define KNF_CHECK_LE(x, y) _KNF_CHECK_OP(x, y, <=)\n#define KNF_CHECK_GT(x, y) _KNF_CHECK_OP(x, y, >)\n#define KNF_CHECK_GE(x, y) _KNF_CHECK_OP(x, y, >=)\n\n#define KNF_LOG(x) ::knf::Logger(__FILE__, KNF_FUNC, __LINE__, ::knf::x)\n\n// ------------------------------------------------------------\n//       For debug check\n// ------------------------------------------------------------\n// If you define the macro \"-D NDEBUG\" while compiling kaldi-native-fbank,\n// the following macros are in fact empty and does nothing.\n\n#define KNF_DCHECK(x) ::knf::kDisableDebug ? (void)0 : KNF_CHECK(x)\n\n#define KNF_DCHECK_EQ(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_EQ(x, y)\n\n#define KNF_DCHECK_NE(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_NE(x, y)\n\n#define KNF_DCHECK_LT(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_LT(x, y)\n\n#define KNF_DCHECK_LE(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_LE(x, y)\n\n#define KNF_DCHECK_GT(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_GT(x, y)\n\n#define KNF_DCHECK_GE(x, y) ::knf::kDisableDebug ? (void)0 : KNF_CHECK_GE(x, y)\n\n#define KNF_DLOG(x) \\\n  ::knf::kDisableDebug ? (void)0 : ::knf::Voidifier() & KNF_LOG(x)\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_LOG_H_\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/mel-computations.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/mel-computations.cc\n\n#include \"kaldi-native-fbank/csrc/mel-computations.h\"\n\n#include <algorithm>\n#include <sstream>\n\n#include \"kaldi-native-fbank/csrc/feature-window.h\"\n\nnamespace knf {\n\nstd::ostream &operator<<(std::ostream &os, const MelBanksOptions &opts) {\n  os << opts.ToString();\n  return os;\n}\n\nfloat MelBanks::VtlnWarpFreq(\n    float vtln_low_cutoff,  // upper+lower frequency cutoffs for VTLN.\n    float vtln_high_cutoff,\n    float low_freq,  // upper+lower frequency cutoffs in mel computation\n    float high_freq, float vtln_warp_factor, float freq) {\n  /// This computes a VTLN warping function that is not the same as HTK's one,\n  /// but has similar inputs (this function has the advantage of never producing\n  /// empty bins).\n\n  /// This function computes a warp function F(freq), defined between low_freq\n  /// and high_freq inclusive, with the following properties:\n  ///  F(low_freq) == low_freq\n  ///  F(high_freq) == high_freq\n  /// The function is continuous and piecewise linear with two inflection\n  ///   points.\n  /// The lower inflection point (measured in terms of the unwarped\n  ///  frequency) is at frequency l, determined as described below.\n  /// The higher inflection point is at a frequency h, determined as\n  ///   described below.\n  /// If l <= f <= h, then F(f) = f/vtln_warp_factor.\n  /// If the higher inflection point (measured in terms of the unwarped\n  ///   frequency) is at h, then max(h, F(h)) == vtln_high_cutoff.\n  ///   Since (by the last point) F(h) == h/vtln_warp_factor, then\n  ///   max(h, h/vtln_warp_factor) == vtln_high_cutoff, so\n  ///   h = vtln_high_cutoff / max(1, 1/vtln_warp_factor).\n  ///     = vtln_high_cutoff * min(1, vtln_warp_factor).\n  /// If the lower inflection point (measured in terms of the unwarped\n  ///   frequency) is at l, then min(l, F(l)) == vtln_low_cutoff\n  ///   This implies that l = vtln_low_cutoff / min(1, 1/vtln_warp_factor)\n  ///                       = vtln_low_cutoff * max(1, vtln_warp_factor)\n\n  if (freq < low_freq || freq > high_freq)\n    return freq;  // in case this gets called\n  // for out-of-range frequencies, just return the freq.\n\n  KNF_CHECK_GT(vtln_low_cutoff, low_freq);\n  KNF_CHECK_LT(vtln_high_cutoff, high_freq);\n\n  float one = 1.0f;\n  float l = vtln_low_cutoff * std::max(one, vtln_warp_factor);\n  float h = vtln_high_cutoff * std::min(one, vtln_warp_factor);\n  float scale = 1.0f / vtln_warp_factor;\n  float Fl = scale * l;  // F(l);\n  float Fh = scale * h;  // F(h);\n  KNF_CHECK(l > low_freq && h < high_freq);\n  // slope of left part of the 3-piece linear function\n  float scale_left = (Fl - low_freq) / (l - low_freq);\n  // [slope of center part is just \"scale\"]\n\n  // slope of right part of the 3-piece linear function\n  float scale_right = (high_freq - Fh) / (high_freq - h);\n\n  if (freq < l) {\n    return low_freq + scale_left * (freq - low_freq);\n  } else if (freq < h) {\n    return scale * freq;\n  } else {  // freq >= h\n    return high_freq + scale_right * (freq - high_freq);\n  }\n}\n\nfloat MelBanks::VtlnWarpMelFreq(\n    float vtln_low_cutoff,  // upper+lower frequency cutoffs for VTLN.\n    float vtln_high_cutoff,\n    float low_freq,  // upper+lower frequency cutoffs in mel computation\n    float high_freq, float vtln_warp_factor, float mel_freq) {\n  return MelScale(VtlnWarpFreq(vtln_low_cutoff, vtln_high_cutoff, low_freq,\n                               high_freq, vtln_warp_factor,\n                               InverseMelScale(mel_freq)));\n}\n\nMelBanks::MelBanks(const MelBanksOptions &opts,\n                   const FrameExtractionOptions &frame_opts,\n                   float vtln_warp_factor)\n    : htk_mode_(opts.htk_mode) {\n  int32_t num_bins = opts.num_bins;\n  if (num_bins < 3) KNF_LOG(FATAL) << \"Must have at least 3 mel bins\";\n\n  float sample_freq = frame_opts.samp_freq;\n  int32_t window_length_padded = frame_opts.PaddedWindowSize();\n  KNF_CHECK_EQ(window_length_padded % 2, 0);\n\n  int32_t num_fft_bins = window_length_padded / 2;\n  float nyquist = 0.5f * sample_freq;\n\n  float low_freq = opts.low_freq, high_freq;\n  if (opts.high_freq > 0.0f)\n    high_freq = opts.high_freq;\n  else\n    high_freq = nyquist + opts.high_freq;\n\n  if (low_freq < 0.0f || low_freq >= nyquist || high_freq <= 0.0f ||\n      high_freq > nyquist || high_freq <= low_freq) {\n    KNF_LOG(FATAL) << \"Bad values in options: low-freq \" << low_freq\n                   << \" and high-freq \" << high_freq << \" vs. nyquist \"\n                   << nyquist;\n  }\n\n  float fft_bin_width = sample_freq / window_length_padded;\n  // fft-bin width [think of it as Nyquist-freq / half-window-length]\n\n  float mel_low_freq = MelScale(low_freq);\n  float mel_high_freq = MelScale(high_freq);\n\n  debug_ = opts.debug_mel;\n\n  // divide by num_bins+1 in next line because of end-effects where the bins\n  // spread out to the sides.\n  float mel_freq_delta = (mel_high_freq - mel_low_freq) / (num_bins + 1);\n\n  float vtln_low = opts.vtln_low, vtln_high = opts.vtln_high;\n  if (vtln_high < 0.0f) {\n    vtln_high += nyquist;\n  }\n\n  if (vtln_warp_factor != 1.0f &&\n      (vtln_low < 0.0f || vtln_low <= low_freq || vtln_low >= high_freq ||\n       vtln_high <= 0.0f || vtln_high >= high_freq || vtln_high <= vtln_low)) {\n    KNF_LOG(FATAL) << \"Bad values in options: vtln-low \" << vtln_low\n                   << \" and vtln-high \" << vtln_high << \", versus \"\n                   << \"low-freq \" << low_freq << \" and high-freq \" << high_freq;\n  }\n\n  bins_.resize(num_bins);\n  center_freqs_.resize(num_bins);\n\n  for (int32_t bin = 0; bin < num_bins; ++bin) {\n    float left_mel = mel_low_freq + bin * mel_freq_delta,\n          center_mel = mel_low_freq + (bin + 1) * mel_freq_delta,\n          right_mel = mel_low_freq + (bin + 2) * mel_freq_delta;\n\n    if (vtln_warp_factor != 1.0f) {\n      left_mel = VtlnWarpMelFreq(vtln_low, vtln_high, low_freq, high_freq,\n                                 vtln_warp_factor, left_mel);\n      center_mel = VtlnWarpMelFreq(vtln_low, vtln_high, low_freq, high_freq,\n                                   vtln_warp_factor, center_mel);\n      right_mel = VtlnWarpMelFreq(vtln_low, vtln_high, low_freq, high_freq,\n                                  vtln_warp_factor, right_mel);\n    }\n    center_freqs_[bin] = InverseMelScale(center_mel);\n\n    // this_bin will be a vector of coefficients that is only\n    // nonzero where this mel bin is active.\n    std::vector<float> this_bin(num_fft_bins);\n\n    int32_t first_index = -1, last_index = -1;\n    for (int32_t i = 0; i < num_fft_bins; ++i) {\n      float freq = (fft_bin_width * i);  // Center frequency of this fft\n                                         // bin.\n      float mel = MelScale(freq);\n      if (mel > left_mel && mel < right_mel) {\n        float weight;\n        if (mel <= center_mel)\n          weight = (mel - left_mel) / (center_mel - left_mel);\n        else\n          weight = (right_mel - mel) / (right_mel - center_mel);\n        this_bin[i] = weight;\n        if (first_index == -1) first_index = i;\n        last_index = i;\n      }\n    }\n    KNF_CHECK(first_index != -1 && last_index >= first_index &&\n              \"You may have set num_mel_bins too large.\");\n\n    bins_[bin].first = first_index;\n    int32_t size = last_index + 1 - first_index;\n    bins_[bin].second.insert(bins_[bin].second.end(),\n                             this_bin.begin() + first_index,\n                             this_bin.begin() + first_index + size);\n\n    // Replicate a bug in HTK, for testing purposes.\n    if (opts.htk_mode && bin == 0 && mel_low_freq != 0.0f) {\n      bins_[bin].second[0] = 0.0;\n    }\n  }  // for (int32_t bin = 0; bin < num_bins; ++bin) {\n\n  if (debug_) {\n    std::ostringstream os;\n    for (size_t i = 0; i < bins_.size(); i++) {\n      os << \"bin \" << i << \", offset = \" << bins_[i].first << \", vec = \";\n      for (auto k : bins_[i].second) os << k << \", \";\n      os << \"\\n\";\n    }\n    KNF_LOG(INFO) << os.str();\n  }\n}\n\n// \"power_spectrum\" contains fft energies.\nvoid MelBanks::Compute(const float *power_spectrum,\n                       float *mel_energies_out) const {\n  int32_t num_bins = bins_.size();\n\n  for (int32_t i = 0; i < num_bins; i++) {\n    int32_t offset = bins_[i].first;\n    const auto &v = bins_[i].second;\n    float energy = 0;\n    for (int32_t k = 0; k != v.size(); ++k) {\n      energy += v[k] * power_spectrum[k + offset];\n    }\n\n    // HTK-like flooring- for testing purposes (we prefer dither)\n    if (htk_mode_ && energy < 1.0) {\n      energy = 1.0;\n    }\n\n    mel_energies_out[i] = energy;\n\n    // The following assert was added due to a problem with OpenBlas that\n    // we had at one point (it was a bug in that library).  Just to detect\n    // it early.\n    KNF_CHECK_EQ(energy, energy);  // check that energy is not nan\n  }\n\n  if (debug_) {\n    fprintf(stderr, \"MEL BANKS:\\n\");\n    for (int32_t i = 0; i < num_bins; i++)\n      fprintf(stderr, \" %f\", mel_energies_out[i]);\n    fprintf(stderr, \"\\n\");\n  }\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/mel-computations.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// This file is copied/modified from kaldi/src/feat/mel-computations.h\n#ifndef KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n#define KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n\n#include <cmath>\n#include <string>\n\n#include \"kaldi-native-fbank/csrc/feature-window.h\"\n\nnamespace knf {\n\nstruct MelBanksOptions {\n  int32_t num_bins = 25;  // e.g. 25; number of triangular bins\n  float low_freq = 20;    // e.g. 20; lower frequency cutoff\n\n  // an upper frequency cutoff; 0 -> no cutoff, negative\n  // ->added to the Nyquist frequency to get the cutoff.\n  float high_freq = 0;\n\n  float vtln_low = 100;  // vtln lower cutoff of warping function.\n\n  // vtln upper cutoff of warping function: if negative, added\n  // to the Nyquist frequency to get the cutoff.\n  float vtln_high = -500;\n\n  bool debug_mel = false;\n  // htk_mode is a \"hidden\" config, it does not show up on command line.\n  // Enables more exact compatibility with HTK, for testing purposes.  Affects\n  // mel-energy flooring and reproduces a bug in HTK.\n  bool htk_mode = false;\n\n  std::string ToString() const {\n    std::ostringstream os;\n    os << \"num_bins: \" << num_bins << \"\\n\";\n    os << \"low_freq: \" << low_freq << \"\\n\";\n    os << \"high_freq: \" << high_freq << \"\\n\";\n    os << \"vtln_low: \" << vtln_low << \"\\n\";\n    os << \"vtln_high: \" << vtln_high << \"\\n\";\n    os << \"debug_mel: \" << debug_mel << \"\\n\";\n    os << \"htk_mode: \" << htk_mode << \"\\n\";\n    return os.str();\n  }\n};\n\nstd::ostream &operator<<(std::ostream &os, const MelBanksOptions &opts);\n\nclass MelBanks {\n public:\n  static inline float InverseMelScale(float mel_freq) {\n    return 700.0f * (expf(mel_freq / 1127.0f) - 1.0f);\n  }\n\n  static inline float MelScale(float freq) {\n    return 1127.0f * logf(1.0f + freq / 700.0f);\n  }\n\n  static float VtlnWarpFreq(\n      float vtln_low_cutoff,\n      float vtln_high_cutoff,  // discontinuities in warp func\n      float low_freq,\n      float high_freq,  // upper+lower frequency cutoffs in\n      // the mel computation\n      float vtln_warp_factor, float freq);\n\n  static float VtlnWarpMelFreq(float vtln_low_cutoff, float vtln_high_cutoff,\n                               float low_freq, float high_freq,\n                               float vtln_warp_factor, float mel_freq);\n\n  // TODO(fangjun): Remove vtln_warp_factor\n  MelBanks(const MelBanksOptions &opts,\n           const FrameExtractionOptions &frame_opts, float vtln_warp_factor);\n\n  /// Compute Mel energies (note: not log energies).\n  /// At input, \"fft_energies\" contains the FFT energies (not log).\n  ///\n  /// @param fft_energies 1-D array of size num_fft_bins/2+1\n  /// @param mel_energies_out  1-D array of size num_mel_bins\n  void Compute(const float *fft_energies, float *mel_energies_out) const;\n\n  int32_t NumBins() const { return bins_.size(); }\n\n private:\n  // center frequencies of bins, numbered from 0 ... num_bins-1.\n  // Needed by GetCenterFreqs().\n  std::vector<float> center_freqs_;\n\n  // the \"bins_\" vector is a vector, one for each bin, of a pair:\n  // (the first nonzero fft-bin), (the vector of weights).\n  std::vector<std::pair<int32_t, std::vector<float>>> bins_;\n\n  // TODO(fangjun): Remove debug_ and htk_mode_\n  bool debug_;\n  bool htk_mode_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/rfft.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"kaldi-native-fbank/csrc/rfft.h\"\n\n#include <cmath>\n#include <vector>\n\n#include \"kaldi-native-fbank/csrc/log.h\"\n\n// see fftsg.c\n#ifdef __cplusplus\nextern \"C\" void rdft(int n, int isgn, double *a, int *ip, double *w);\n#else\nvoid rdft(int n, int isgn, double *a, int *ip, double *w);\n#endif\n\nnamespace knf {\nclass Rfft::RfftImpl {\n public:\n  explicit RfftImpl(int32_t n) : n_(n), ip_(2 + std::sqrt(n / 2)), w_(n / 2) {\n    KNF_CHECK_EQ(n & (n - 1), 0);\n  }\n\n  void Compute(float *in_out) {\n    std::vector<double> d(in_out, in_out + n_);\n\n    Compute(d.data());\n\n    std::copy(d.begin(), d.end(), in_out);\n  }\n\n  void Compute(double *in_out) {\n    // 1 means forward fft\n    rdft(n_, 1, in_out, ip_.data(), w_.data());\n  }\n\n private:\n  int32_t n_;\n  std::vector<int32_t> ip_;\n  std::vector<double> w_;\n};\n\nRfft::Rfft(int32_t n) : impl_(std::make_unique<RfftImpl>(n)) {}\n\nRfft::~Rfft() = default;\n\nvoid Rfft::Compute(float *in_out) { impl_->Compute(in_out); }\nvoid Rfft::Compute(double *in_out) { impl_->Compute(in_out); }\n\n}  // namespace knf\n"
  },
  {
    "path": "audio/paddleaudio/third_party/kaldi-native-fbank/csrc/rfft.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n#define KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n\n#include <memory>\n\nnamespace knf {\n\n// n-point Real discrete Fourier transform\n// where n is a power of 2. n >= 2\n//\n//  R[k] = sum_j=0^n-1 in[j]*cos(2*pi*j*k/n), 0<=k<=n/2\n//  I[k] = sum_j=0^n-1 in[j]*sin(2*pi*j*k/n), 0<k<n/2\nclass Rfft {\n public:\n  // @param n Number of fft bins. it should be a power of 2.\n  explicit Rfft(int32_t n);\n  ~Rfft();\n\n  /** @param in_out A 1-D array of size n.\n   *             On return:\n   *               in_out[0] = R[0]\n   *               in_out[1] = R[n/2]\n   *               for 1 < k < n/2,\n   *                 in_out[2*k] = R[k]\n   *                 in_out[2*k+1] = I[k]\n   *\n   */\n  void Compute(float *in_out);\n  void Compute(double *in_out);\n\n private:\n  class RfftImpl;\n  std::unique_ptr<RfftImpl> impl_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n"
  },
  {
    "path": "audio/paddleaudio/third_party/patches/config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright 1992-2022 Free Software Foundation, Inc.\n\n# shellcheck disable=SC2006,SC2268 # see below for rationale\n\ntimestamp='2022-01-09'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <https://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n#\n# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.\n#\n# You can get the latest version of this script from:\n# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess\n#\n# Please send patches to <config-patches@gnu.org>.\n\n\n# The \"shellcheck disable\" line above the timestamp inhibits complaints\n# about features and limitations of the classic Bourne shell that were\n# superseded or lifted in POSIX.  However, this script identifies a wide\n# variety of pre-POSIX systems that do not have POSIX shells at all, and\n# even some reasonably current systems (Solaris 10 as case-in-point) still\n# have a pre-POSIX /bin/sh.\n\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOptions:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright 1992-2022 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\n# Just in case it came from the environment.\nGUESS=\n\n# CC_FOR_BUILD -- compiler used by this script. Note that the use of a\n# compiler to aid in system detection is discouraged as it requires\n# temporary files to be created and, as you can see below, it is a\n# headache to deal with in a portable fashion.\n\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\n# Portable tmp directory creation inspired by the Autoconf team.\n\ntmp=\n# shellcheck disable=SC2172\ntrap 'test -z \"$tmp\" || rm -fr \"$tmp\"' 0 1 2 13 15\n\nset_cc_for_build() {\n    # prevent multiple calls if $tmp is already set\n    test \"$tmp\" && return 0\n    : \"${TMPDIR=/tmp}\"\n    # shellcheck disable=SC2039,SC3028\n    { tmp=`(umask 077 && mktemp -d \"$TMPDIR/cgXXXXXX\") 2>/dev/null` && test -n \"$tmp\" && test -d \"$tmp\" ; } ||\n\t{ test -n \"$RANDOM\" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir \"$tmp\" 2>/dev/null) ; } ||\n\t{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir \"$tmp\" 2>/dev/null) && echo \"Warning: creating insecure temp directory\" >&2 ; } ||\n\t{ echo \"$me: cannot create a temporary directory in $TMPDIR\" >&2 ; exit 1 ; }\n    dummy=$tmp/dummy\n    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in\n\t,,)    echo \"int x;\" > \"$dummy.c\"\n\t       for driver in cc gcc c89 c99 ; do\n\t\t   if ($driver -c -o \"$dummy.o\" \"$dummy.c\") >/dev/null 2>&1 ; then\n\t\t       CC_FOR_BUILD=$driver\n\t\t       break\n\t\t   fi\n\t       done\n\t       if test x\"$CC_FOR_BUILD\" = x ; then\n\t\t   CC_FOR_BUILD=no_compiler_found\n\t       fi\n\t       ;;\n\t,,*)   CC_FOR_BUILD=$CC ;;\n\t,*,*)  CC_FOR_BUILD=$HOST_CC ;;\n    esac\n}\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif test -f /.attbin/uname ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown\nUNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown\nUNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown\nUNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown\n\ncase $UNAME_SYSTEM in\nLinux|GNU|GNU/*)\n\tLIBC=unknown\n\n\tset_cc_for_build\n\tcat <<-EOF > \"$dummy.c\"\n\t#include <features.h>\n\t#if defined(__UCLIBC__)\n\tLIBC=uclibc\n\t#elif defined(__dietlibc__)\n\tLIBC=dietlibc\n\t#elif defined(__GLIBC__)\n\tLIBC=gnu\n\t#else\n\t#include <stdarg.h>\n\t/* First heuristic to detect musl libc.  */\n\t#ifdef __DEFINED_va_list\n\tLIBC=musl\n\t#endif\n\t#endif\n\tEOF\n\tcc_set_libc=`$CC_FOR_BUILD -E \"$dummy.c\" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`\n\teval \"$cc_set_libc\"\n\n\t# Second heuristic to detect musl libc.\n\tif [ \"$LIBC\" = unknown ] &&\n\t   command -v ldd >/dev/null &&\n\t   ldd --version 2>&1 | grep -q ^musl; then\n\t\tLIBC=musl\n\tfi\n\n\t# If the system lacks a compiler, then just pick glibc.\n\t# We could probably try harder.\n\tif [ \"$LIBC\" = unknown ]; then\n\t\tLIBC=gnu\n\tfi\n\t;;\nesac\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t#\n\t# Note: NetBSD doesn't particularly care about the vendor\n\t# portion of the name.  We always set it to \"unknown\".\n\tUNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \\\n\t    /sbin/sysctl -n hw.machine_arch 2>/dev/null || \\\n\t    /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \\\n\t    echo unknown)`\n\tcase $UNAME_MACHINE_ARCH in\n\t    aarch64eb) machine=aarch64_be-unknown ;;\n\t    armeb) machine=armeb-unknown ;;\n\t    arm*) machine=arm-unknown ;;\n\t    sh3el) machine=shl-unknown ;;\n\t    sh3eb) machine=sh-unknown ;;\n\t    sh5el) machine=sh5le-unknown ;;\n\t    earmv*)\n\t\tarch=`echo \"$UNAME_MACHINE_ARCH\" | sed -e 's,^e\\(armv[0-9]\\).*$,\\1,'`\n\t\tendian=`echo \"$UNAME_MACHINE_ARCH\" | sed -ne 's,^.*\\(eb\\)$,\\1,p'`\n\t\tmachine=${arch}${endian}-unknown\n\t\t;;\n\t    *) machine=$UNAME_MACHINE_ARCH-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently (or will in the future) and ABI.\n\tcase $UNAME_MACHINE_ARCH in\n\t    earm*)\n\t\tos=netbsdelf\n\t\t;;\n\t    arm*|i386|m68k|ns32k|sh3*|sparc|vax)\n\t\tset_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep -q __ELF__\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t\tos=netbsd\n\t\t;;\n\tesac\n\t# Determine ABI tags.\n\tcase $UNAME_MACHINE_ARCH in\n\t    earm*)\n\t\texpr='s/^earmv[0-9]/-eabi/;s/eb$//'\n\t\tabi=`echo \"$UNAME_MACHINE_ARCH\" | sed -e \"$expr\"`\n\t\t;;\n\tesac\n\t# The OS release\n\t# Debian GNU/NetBSD machines have a different userland, and\n\t# thus, need a distinct triplet. However, they do not need\n\t# kernel version information, so it can be replaced with a\n\t# suitable tag, in the style of linux-gnu.\n\tcase $UNAME_VERSION in\n\t    Debian*)\n\t\trelease='-gnu'\n\t\t;;\n\t    *)\n\t\trelease=`echo \"$UNAME_RELEASE\" | sed -e 's/[-_].*//' | cut -d. -f1,2`\n\t\t;;\n\tesac\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\tGUESS=$machine-${os}${release}${abi-}\n\t;;\n    *:Bitrig:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`\n\tGUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE\n\t;;\n    *:OpenBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`\n\tGUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE\n\t;;\n    *:SecBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`\n\tGUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE\n\t;;\n    *:LibertyBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\\.//'`\n\tGUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE\n\t;;\n    *:MidnightBSD:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE\n\t;;\n    *:ekkoBSD:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE\n\t;;\n    *:SolidBSD:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE\n\t;;\n    *:OS108:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE\n\t;;\n    macppc:MirBSD:*:*)\n\tGUESS=powerpc-unknown-mirbsd$UNAME_RELEASE\n\t;;\n    *:MirBSD:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE\n\t;;\n    *:Sortix:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-sortix\n\t;;\n    *:Twizzler:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-twizzler\n\t;;\n    *:Redox:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-redox\n\t;;\n    mips:OSF1:*.*)\n\tGUESS=mips-dec-osf1\n\t;;\n    alpha:OSF1:*:*)\n\t# Reset EXIT trap before exiting to avoid spurious non-zero exit code.\n\ttrap '' 0\n\tcase $UNAME_RELEASE in\n\t*4.0)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`\n\t\t;;\n\t*5.*)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`\n\t\t;;\n\tesac\n\t# According to Compaq, /usr/sbin/psrinfo has been available on\n\t# OSF/1 and Tru64 systems produced since 1995.  I hope that\n\t# covers most systems running today.  This code pipes the CPU\n\t# types through head -n 1, so we only detect the type of CPU 0.\n\tALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \\(.*\\) processor.*$/\\1/p' | head -n 1`\n\tcase $ALPHA_CPU_TYPE in\n\t    \"EV4 (21064)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"EV4.5 (21064)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"LCA4 (21066/21068)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"EV5 (21164)\")\n\t\tUNAME_MACHINE=alphaev5 ;;\n\t    \"EV5.6 (21164A)\")\n\t\tUNAME_MACHINE=alphaev56 ;;\n\t    \"EV5.6 (21164PC)\")\n\t\tUNAME_MACHINE=alphapca56 ;;\n\t    \"EV5.7 (21164PC)\")\n\t\tUNAME_MACHINE=alphapca57 ;;\n\t    \"EV6 (21264)\")\n\t\tUNAME_MACHINE=alphaev6 ;;\n\t    \"EV6.7 (21264A)\")\n\t\tUNAME_MACHINE=alphaev67 ;;\n\t    \"EV6.8CB (21264C)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.8AL (21264B)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.8CX (21264D)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.9A (21264/EV69A)\")\n\t\tUNAME_MACHINE=alphaev69 ;;\n\t    \"EV7 (21364)\")\n\t\tUNAME_MACHINE=alphaev7 ;;\n\t    \"EV7.9 (21364A)\")\n\t\tUNAME_MACHINE=alphaev79 ;;\n\tesac\n\t# A Pn.n version is a patched version.\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\tOSF_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`\n\tGUESS=$UNAME_MACHINE-dec-osf$OSF_REL\n\t;;\n    Amiga*:UNIX_System_V:4.0:*)\n\tGUESS=m68k-unknown-sysv4\n\t;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-amigaos\n\t;;\n    *:[Mm]orph[Oo][Ss]:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-morphos\n\t;;\n    *:OS/390:*:*)\n\tGUESS=i370-ibm-openedition\n\t;;\n    *:z/VM:*:*)\n\tGUESS=s390-ibm-zvmoe\n\t;;\n    *:OS400:*:*)\n\tGUESS=powerpc-ibm-os400\n\t;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\tGUESS=arm-acorn-riscix$UNAME_RELEASE\n\t;;\n    arm*:riscos:*:*|arm*:RISCOS:*:*)\n\tGUESS=arm-unknown-riscos\n\t;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\tGUESS=hppa1.1-hitachi-hiuxmpp\n\t;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tcase `(/bin/universe) 2>/dev/null` in\n\t    att) GUESS=pyramid-pyramid-sysv3 ;;\n\t    *)   GUESS=pyramid-pyramid-bsd   ;;\n\tesac\n\t;;\n    NILE*:*:*:dcosx)\n\tGUESS=pyramid-pyramid-svr4\n\t;;\n    DRS?6000:unix:4.0:6*)\n\tGUESS=sparc-icl-nx6\n\t;;\n    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)\n\tcase `/usr/bin/uname -p` in\n\t    sparc) GUESS=sparc-icl-nx7 ;;\n\tesac\n\t;;\n    s390x:SunOS:*:*)\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL\n\t;;\n    sun4H:SunOS:5.*:*)\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=sparc-hal-solaris2$SUN_REL\n\t;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=sparc-sun-solaris2$SUN_REL\n\t;;\n    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)\n\tGUESS=i386-pc-auroraux$UNAME_RELEASE\n\t;;\n    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)\n\tset_cc_for_build\n\tSUN_ARCH=i386\n\t# If there is a compiler, see if it is configured for 64-bit objects.\n\t# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.\n\t# This test works for both compilers.\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS=\"\" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tSUN_ARCH=x86_64\n\t    fi\n\tfi\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=$SUN_ARCH-pc-solaris2$SUN_REL\n\t;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=sparc-sun-solaris3$SUN_REL\n\t;;\n    sun4*:SunOS:*:*)\n\tcase `/usr/bin/arch -k` in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=`uname -v`\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/-/_/'`\n\tGUESS=sparc-sun-sunos$SUN_REL\n\t;;\n    sun3*:SunOS:*:*)\n\tGUESS=m68k-sun-sunos$UNAME_RELEASE\n\t;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`\n\ttest \"x$UNAME_RELEASE\" = x && UNAME_RELEASE=3\n\tcase `/bin/arch` in\n\t    sun3)\n\t\tGUESS=m68k-sun-sunos$UNAME_RELEASE\n\t\t;;\n\t    sun4)\n\t\tGUESS=sparc-sun-sunos$UNAME_RELEASE\n\t\t;;\n\tesac\n\t;;\n    aushp:SunOS:*:*)\n\tGUESS=sparc-auspex-sunos$UNAME_RELEASE\n\t;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n\tGUESS=m68k-atari-mint$UNAME_RELEASE\n\t;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\tGUESS=m68k-atari-mint$UNAME_RELEASE\n\t;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n\tGUESS=m68k-atari-mint$UNAME_RELEASE\n\t;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n\tGUESS=m68k-milan-mint$UNAME_RELEASE\n\t;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n\tGUESS=m68k-hades-mint$UNAME_RELEASE\n\t;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n\tGUESS=m68k-unknown-mint$UNAME_RELEASE\n\t;;\n    m68k:machten:*:*)\n\tGUESS=m68k-apple-machten$UNAME_RELEASE\n\t;;\n    powerpc:machten:*:*)\n\tGUESS=powerpc-apple-machten$UNAME_RELEASE\n\t;;\n    RISC*:Mach:*:*)\n\tGUESS=mips-dec-mach_bsd4.3\n\t;;\n    RISC*:ULTRIX:*:*)\n\tGUESS=mips-dec-ultrix$UNAME_RELEASE\n\t;;\n    VAX*:ULTRIX*:*:*)\n\tGUESS=vax-dec-ultrix$UNAME_RELEASE\n\t;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\tGUESS=clipper-intergraph-clix$UNAME_RELEASE\n\t;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\tset_cc_for_build\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" &&\n\t  dummyarg=`echo \"$UNAME_RELEASE\" | sed -n 's/\\([0-9]*\\).*/\\1/p'` &&\n\t  SYSTEM_NAME=`\"$dummy\" \"$dummyarg\"` &&\n\t    { echo \"$SYSTEM_NAME\"; exit; }\n\tGUESS=mips-mips-riscos$UNAME_RELEASE\n\t;;\n    Motorola:PowerMAX_OS:*:*)\n\tGUESS=powerpc-motorola-powermax\n\t;;\n    Motorola:*:4.3:PL8-*)\n\tGUESS=powerpc-harris-powermax\n\t;;\n    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)\n\tGUESS=powerpc-harris-powermax\n\t;;\n    Night_Hawk:Power_UNIX:*:*)\n\tGUESS=powerpc-harris-powerunix\n\t;;\n    m88k:CX/UX:7*:*)\n\tGUESS=m88k-harris-cxux7\n\t;;\n    m88k:*:4*:R4*)\n\tGUESS=m88k-motorola-sysv4\n\t;;\n    m88k:*:3*:R3*)\n\tGUESS=m88k-motorola-sysv3\n\t;;\n    AViiON:dgux:*:*)\n\t# DG/UX returns AViiON for all architectures\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tif test \"$UNAME_PROCESSOR\" = mc88100 || test \"$UNAME_PROCESSOR\" = mc88110\n\tthen\n\t    if test \"$TARGET_BINARY_INTERFACE\"x = m88kdguxelfx || \\\n\t       test \"$TARGET_BINARY_INTERFACE\"x = x\n\t    then\n\t\tGUESS=m88k-dg-dgux$UNAME_RELEASE\n\t    else\n\t\tGUESS=m88k-dg-dguxbcs$UNAME_RELEASE\n\t    fi\n\telse\n\t    GUESS=i586-dg-dgux$UNAME_RELEASE\n\tfi\n\t;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\tGUESS=m88k-dolphin-sysv3\n\t;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\tGUESS=m88k-motorola-sysv3\n\t;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\tGUESS=m88k-tektronix-sysv3\n\t;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\tGUESS=m68k-tektronix-bsd\n\t;;\n    *:IRIX*:*:*)\n\tIRIX_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/-/_/g'`\n\tGUESS=mips-sgi-irix$IRIX_REL\n\t;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\tGUESS=romp-ibm-aix    # uname -m gives an 8 hex-code CPU id\n\t;;                    # Note that: echo \"'`uname -s`'\" gives 'AIX '\n    i*86:AIX:*:*)\n\tGUESS=i386-ibm-aix\n\t;;\n    ia64:AIX:*:*)\n\tif test -x /usr/bin/oslevel ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=$UNAME_VERSION.$UNAME_RELEASE\n\tfi\n\tGUESS=$UNAME_MACHINE-ibm-aix$IBM_REV\n\t;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\tset_cc_for_build\n\t\tsed 's/^\t\t//' << EOF > \"$dummy.c\"\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\tif $CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" && SYSTEM_NAME=`\"$dummy\"`\n\t\tthen\n\t\t\tGUESS=$SYSTEM_NAME\n\t\telse\n\t\t\tGUESS=rs6000-ibm-aix3.2.5\n\t\tfi\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\tGUESS=rs6000-ibm-aix3.2.4\n\telse\n\t\tGUESS=rs6000-ibm-aix3.2\n\tfi\n\t;;\n    *:AIX:*:[4567])\n\tIBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`\n\tif /usr/sbin/lsattr -El \"$IBM_CPU_ID\" | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif test -x /usr/bin/lslpp ; then\n\t\tIBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \\\n\t\t\t   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`\n\telse\n\t\tIBM_REV=$UNAME_VERSION.$UNAME_RELEASE\n\tfi\n\tGUESS=$IBM_ARCH-ibm-aix$IBM_REV\n\t;;\n    *:AIX:*:*)\n\tGUESS=rs6000-ibm-aix\n\t;;\n    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)\n\tGUESS=romp-ibm-bsd4.4\n\t;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\tGUESS=romp-ibm-bsd$UNAME_RELEASE    # 4.3 with uname added to\n\t;;                                  # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\tGUESS=rs6000-bull-bosx\n\t;;\n    DPX/2?00:B.O.S.:*:*)\n\tGUESS=m68k-bull-sysv3\n\t;;\n    9000/[34]??:4.3bsd:1.*:*)\n\tGUESS=m68k-hp-bsd\n\t;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\tGUESS=m68k-hp-bsd4.4\n\t;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*.[0B]*//'`\n\tcase $UNAME_MACHINE in\n\t    9000/31?)            HP_ARCH=m68000 ;;\n\t    9000/[34]??)         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif test -x /usr/bin/getconf; then\n\t\t    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`\n\t\t    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`\n\t\t    case $sc_cpu_version in\n\t\t      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0\n\t\t      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1\n\t\t      532)                      # CPU_PA_RISC2_0\n\t\t\tcase $sc_kernel_bits in\n\t\t\t  32) HP_ARCH=hppa2.0n ;;\n\t\t\t  64) HP_ARCH=hppa2.0w ;;\n\t\t\t  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20\n\t\t\tesac ;;\n\t\t    esac\n\t\tfi\n\t\tif test \"$HP_ARCH\" = \"\"; then\n\t\t    set_cc_for_build\n\t\t    sed 's/^\t\t//' << EOF > \"$dummy.c\"\n\n\t\t#define _HPUX_SOURCE\n\t\t#include <stdlib.h>\n\t\t#include <unistd.h>\n\n\t\tint main ()\n\t\t{\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t    long bits = sysconf(_SC_KERNEL_BITS);\n\t\t#endif\n\t\t    long cpu  = sysconf (_SC_CPU_VERSION);\n\n\t\t    switch (cpu)\n\t\t\t{\n\t\t\tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n\t\t\tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n\t\t\tcase CPU_PA_RISC2_0:\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t\t    switch (bits)\n\t\t\t\t{\n\t\t\t\tcase 64: puts (\"hppa2.0w\"); break;\n\t\t\t\tcase 32: puts (\"hppa2.0n\"); break;\n\t\t\t\tdefault: puts (\"hppa2.0\"); break;\n\t\t\t\t} break;\n\t\t#else  /* !defined(_SC_KERNEL_BITS) */\n\t\t\t    puts (\"hppa2.0\"); break;\n\t\t#endif\n\t\t\tdefault: puts (\"hppa1.0\"); break;\n\t\t\t}\n\t\t    exit (0);\n\t\t}\nEOF\n\t\t    (CCOPTS=\"\" $CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" 2>/dev/null) && HP_ARCH=`\"$dummy\"`\n\t\t    test -z \"$HP_ARCH\" && HP_ARCH=hppa\n\t\tfi ;;\n\tesac\n\tif test \"$HP_ARCH\" = hppa2.0w\n\tthen\n\t    set_cc_for_build\n\n\t    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating\n\t    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler\n\t    # generating 64-bit code.  GNU and HP use different nomenclature:\n\t    #\n\t    # $ CC_FOR_BUILD=cc ./config.guess\n\t    # => hppa2.0w-hp-hpux11.23\n\t    # $ CC_FOR_BUILD=\"cc +DA2.0w\" ./config.guess\n\t    # => hppa64-hp-hpux11.23\n\n\t    if echo __LP64__ | (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) |\n\t\tgrep -q __LP64__\n\t    then\n\t\tHP_ARCH=hppa2.0w\n\t    else\n\t\tHP_ARCH=hppa64\n\t    fi\n\tfi\n\tGUESS=$HP_ARCH-hp-hpux$HPUX_REV\n\t;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*.[0B]*//'`\n\tGUESS=ia64-hp-hpux$HPUX_REV\n\t;;\n    3050*:HI-UX:*:*)\n\tset_cc_for_build\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" && SYSTEM_NAME=`\"$dummy\"` &&\n\t\t{ echo \"$SYSTEM_NAME\"; exit; }\n\tGUESS=unknown-hitachi-hiuxwe2\n\t;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)\n\tGUESS=hppa1.1-hp-bsd\n\t;;\n    9000/8??:4.3bsd:*:*)\n\tGUESS=hppa1.0-hp-bsd\n\t;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\tGUESS=hppa1.0-hp-mpeix\n\t;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)\n\tGUESS=hppa1.1-hp-osf\n\t;;\n    hp8??:OSF1:*:*)\n\tGUESS=hppa1.0-hp-osf\n\t;;\n    i*86:OSF1:*:*)\n\tif test -x /usr/sbin/sysversion ; then\n\t    GUESS=$UNAME_MACHINE-unknown-osf1mk\n\telse\n\t    GUESS=$UNAME_MACHINE-unknown-osf1\n\tfi\n\t;;\n    parisc*:Lites*:*:*)\n\tGUESS=hppa1.1-hp-lites\n\t;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\tGUESS=c1-convex-bsd\n\t;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\tGUESS=c34-convex-bsd\n\t;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\tGUESS=c38-convex-bsd\n\t;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\tGUESS=c4-convex-bsd\n\t;;\n    CRAY*Y-MP:*:*:*)\n\tCRAY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'`\n\tGUESS=ymp-cray-unicos$CRAY_REL\n\t;;\n    CRAY*[A-Z]90:*:*:*)\n\techo \"$UNAME_MACHINE\"-cray-unicos\"$UNAME_RELEASE\" \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*TS:*:*:*)\n\tCRAY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'`\n\tGUESS=t90-cray-unicos$CRAY_REL\n\t;;\n    CRAY*T3E:*:*:*)\n\tCRAY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'`\n\tGUESS=alphaev5-cray-unicosmk$CRAY_REL\n\t;;\n    CRAY*SV1:*:*:*)\n\tCRAY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'`\n\tGUESS=sv1-cray-unicos$CRAY_REL\n\t;;\n    *:UNICOS/mp:*:*)\n\tCRAY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'`\n\tGUESS=craynv-cray-unicosmp$CRAY_REL\n\t;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`\n\tFUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/ /_/'`\n\tGUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\n\t;;\n    5000:UNIX_System_V:4.*:*)\n\tFUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo \"$UNAME_RELEASE\" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`\n\tGUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\n\t;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\tGUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE\n\t;;\n    sparc*:BSD/OS:*:*)\n\tGUESS=sparc-unknown-bsdi$UNAME_RELEASE\n\t;;\n    *:BSD/OS:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE\n\t;;\n    arm:FreeBSD:*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tset_cc_for_build\n\tif echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_PCS_VFP\n\tthen\n\t    FREEBSD_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[-(].*//'`\n\t    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi\n\telse\n\t    FREEBSD_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[-(].*//'`\n\t    GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf\n\tfi\n\t;;\n    *:FreeBSD:*:*)\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tcase $UNAME_PROCESSOR in\n\t    amd64)\n\t\tUNAME_PROCESSOR=x86_64 ;;\n\t    i386)\n\t\tUNAME_PROCESSOR=i586 ;;\n\tesac\n\tFREEBSD_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[-(].*//'`\n\tGUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL\n\t;;\n    i*:CYGWIN*:*)\n\tGUESS=$UNAME_MACHINE-pc-cygwin\n\t;;\n    *:MINGW64*:*)\n\tGUESS=$UNAME_MACHINE-pc-mingw64\n\t;;\n    *:MINGW*:*)\n\tGUESS=$UNAME_MACHINE-pc-mingw32\n\t;;\n    *:MSYS*:*)\n\tGUESS=$UNAME_MACHINE-pc-msys\n\t;;\n    i*:PW*:*)\n\tGUESS=$UNAME_MACHINE-pc-pw32\n\t;;\n    *:SerenityOS:*:*)\n        GUESS=$UNAME_MACHINE-pc-serenity\n        ;;\n    *:Interix*:*)\n\tcase $UNAME_MACHINE in\n\t    x86)\n\t\tGUESS=i586-pc-interix$UNAME_RELEASE\n\t\t;;\n\t    authenticamd | genuineintel | EM64T)\n\t\tGUESS=x86_64-unknown-interix$UNAME_RELEASE\n\t\t;;\n\t    IA64)\n\t\tGUESS=ia64-unknown-interix$UNAME_RELEASE\n\t\t;;\n\tesac ;;\n    i*:UWIN*:*)\n\tGUESS=$UNAME_MACHINE-pc-uwin\n\t;;\n    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)\n\tGUESS=x86_64-pc-cygwin\n\t;;\n    prep*:SunOS:5.*:*)\n\tSUN_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//'`\n\tGUESS=powerpcle-unknown-solaris2$SUN_REL\n\t;;\n    *:GNU:*:*)\n\t# the GNU system\n\tGNU_ARCH=`echo \"$UNAME_MACHINE\" | sed -e 's,[-/].*$,,'`\n\tGNU_REL=`echo \"$UNAME_RELEASE\" | sed -e 's,/.*$,,'`\n\tGUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL\n\t;;\n    *:GNU/*:*:*)\n\t# other systems with GNU libc and userland\n\tGNU_SYS=`echo \"$UNAME_SYSTEM\" | sed 's,^[^/]*/,,' | tr \"[:upper:]\" \"[:lower:]\"`\n\tGNU_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[-(].*//'`\n\tGUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC\n\t;;\n    *:Minix:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-minix\n\t;;\n    aarch64:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    aarch64_be:Linux:*:*)\n\tUNAME_MACHINE=aarch64_be\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    alpha:Linux:*:*)\n\tcase `sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' /proc/cpuinfo 2>/dev/null` in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n\tesac\n\tobjdump --private-headers /bin/sh | grep -q ld.so.1\n\tif test \"$?\" = 0 ; then LIBC=gnulibc1 ; fi\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    arm*:Linux:*:*)\n\tset_cc_for_build\n\tif echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_EABI__\n\tthen\n\t    GUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\telse\n\t    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t| grep -q __ARM_PCS_VFP\n\t    then\n\t\tGUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi\n\t    else\n\t\tGUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf\n\t    fi\n\tfi\n\t;;\n    avr32*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    cris:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-axis-linux-$LIBC\n\t;;\n    crisv32:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-axis-linux-$LIBC\n\t;;\n    e2k:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    frv:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    hexagon:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    i*86:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-pc-linux-$LIBC\n\t;;\n    ia64:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    k1om:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    m32r*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    m68*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    mips:Linux:*:* | mips64:Linux:*:*)\n\tset_cc_for_build\n\tIS_GLIBC=0\n\ttest x\"${LIBC}\" = xgnu && IS_GLIBC=1\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n\t#undef CPU\n\t#undef mips\n\t#undef mipsel\n\t#undef mips64\n\t#undef mips64el\n\t#if ${IS_GLIBC} && defined(_ABI64)\n\tLIBCABI=gnuabi64\n\t#else\n\t#if ${IS_GLIBC} && defined(_ABIN32)\n\tLIBCABI=gnuabin32\n\t#else\n\tLIBCABI=${LIBC}\n\t#endif\n\t#endif\n\n\t#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6\n\tCPU=mipsisa64r6\n\t#else\n\t#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6\n\tCPU=mipsisa32r6\n\t#else\n\t#if defined(__mips64)\n\tCPU=mips64\n\t#else\n\tCPU=mips\n\t#endif\n\t#endif\n\t#endif\n\n\t#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)\n\tMIPS_ENDIAN=el\n\t#else\n\t#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)\n\tMIPS_ENDIAN=\n\t#else\n\tMIPS_ENDIAN=\n\t#endif\n\t#endif\nEOF\n\tcc_set_vars=`$CC_FOR_BUILD -E \"$dummy.c\" 2>/dev/null | grep '^CPU\\|^MIPS_ENDIAN\\|^LIBCABI'`\n\teval \"$cc_set_vars\"\n\ttest \"x$CPU\" != x && { echo \"$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI\"; exit; }\n\t;;\n    mips64el:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    openrisc*:Linux:*:*)\n\tGUESS=or1k-unknown-linux-$LIBC\n\t;;\n    or32:Linux:*:* | or1k*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    padre:Linux:*:*)\n\tGUESS=sparc-unknown-linux-$LIBC\n\t;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\tGUESS=hppa64-unknown-linux-$LIBC\n\t;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in\n\t  PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;\n\t  PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;\n\t  *)    GUESS=hppa-unknown-linux-$LIBC ;;\n\tesac\n\t;;\n    ppc64:Linux:*:*)\n\tGUESS=powerpc64-unknown-linux-$LIBC\n\t;;\n    ppc:Linux:*:*)\n\tGUESS=powerpc-unknown-linux-$LIBC\n\t;;\n    ppc64le:Linux:*:*)\n\tGUESS=powerpc64le-unknown-linux-$LIBC\n\t;;\n    ppcle:Linux:*:*)\n\tGUESS=powerpcle-unknown-linux-$LIBC\n\t;;\n    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-ibm-linux-$LIBC\n\t;;\n    sh64*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    sh*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    tile*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    vax:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-dec-linux-$LIBC\n\t;;\n    x86_64:Linux:*:*)\n\tset_cc_for_build\n\tLIBCABI=$LIBC\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \\\n\t\t(CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_X32 >/dev/null\n\t    then\n\t\tLIBCABI=${LIBC}x32\n\t    fi\n\tfi\n\tGUESS=$UNAME_MACHINE-pc-linux-$LIBCABI\n\t;;\n    xtensa*:Linux:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-linux-$LIBC\n\t;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\tGUESS=i386-sequent-sysv4\n\t;;\n    i*86:UNIX_SV:4.2MP:2.*)\n\t# Unixware is an offshoot of SVR4, but it has its own version\n\t# number series starting with 2...\n\t# I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n\t# Use sysv4.2uw... so that sysv4* matches it.\n\tGUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION\n\t;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\tGUESS=$UNAME_MACHINE-pc-os2-emx\n\t;;\n    i*86:XTS-300:*:STOP)\n\tGUESS=$UNAME_MACHINE-unknown-stop\n\t;;\n    i*86:atheos:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-atheos\n\t;;\n    i*86:syllable:*:*)\n\tGUESS=$UNAME_MACHINE-pc-syllable\n\t;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)\n\tGUESS=i386-unknown-lynxos$UNAME_RELEASE\n\t;;\n    i*86:*DOS:*:*)\n\tGUESS=$UNAME_MACHINE-pc-msdosdjgpp\n\t;;\n    i*86:*:4.*:*)\n\tUNAME_REL=`echo \"$UNAME_RELEASE\" | sed 's/\\/MP$//'`\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\tGUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL\n\telse\n\t\tGUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL\n\tfi\n\t;;\n    i*86:*:5:[678]*)\n\t# UnixWare 7.x, OpenUNIX and OpenServer 6.\n\tcase `/bin/uname -X | grep \"^Machine\"` in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\tGUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\n\t;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`\n\t\tGUESS=$UNAME_MACHINE-pc-isc$UNAME_REL\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`\n\t\t(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\tGUESS=$UNAME_MACHINE-pc-sco$UNAME_REL\n\telse\n\t\tGUESS=$UNAME_MACHINE-pc-sysv32\n\tfi\n\t;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n\t# uname -m prints for DJGPP always 'pc', but it prints nothing about\n\t# the processor, so we play safe by assuming i586.\n\t# Note: whatever this is, it MUST be the same as what config.sub\n\t# prints for the \"djgpp\" host, or else GDB configure will decide that\n\t# this is a cross-build.\n\tGUESS=i586-pc-msdosdjgpp\n\t;;\n    Intel:Mach:3*:*)\n\tGUESS=i386-pc-mach3\n\t;;\n    paragon:*:*:*)\n\tGUESS=i860-intel-osf1\n\t;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  GUESS=i860-stardent-sysv$UNAME_RELEASE    # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  GUESS=i860-unknown-sysv$UNAME_RELEASE     # Unknown i860-SVR4\n\tfi\n\t;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\tGUESS=m68010-convergent-sysv\n\t;;\n    mc68k:UNIX:SYSTEM5:3.51m)\n\tGUESS=m68k-convergent-sysv\n\t;;\n    M680?0:D-NIX:5.3:*)\n\tGUESS=m68k-diab-dnix\n\t;;\n    M68*:*:R3V[5678]*:*)\n\ttest -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;\n    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; } ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4; exit; } ;;\n    NCR*:*:4.2:* | MPRAS*:*:4.2:*)\n\tOS_REL='.3'\n\ttest -r /etc/.relid \\\n\t    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t    && { echo i486-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; } ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\tGUESS=m68k-unknown-lynxos$UNAME_RELEASE\n\t;;\n    mc68030:UNIX_System_V:4.*:*)\n\tGUESS=m68k-atari-sysv4\n\t;;\n    TSUNAMI:LynxOS:2.*:*)\n\tGUESS=sparc-unknown-lynxos$UNAME_RELEASE\n\t;;\n    rs6000:LynxOS:2.*:*)\n\tGUESS=rs6000-unknown-lynxos$UNAME_RELEASE\n\t;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)\n\tGUESS=powerpc-unknown-lynxos$UNAME_RELEASE\n\t;;\n    SM[BE]S:UNIX_SV:*:*)\n\tGUESS=mips-dde-sysv$UNAME_RELEASE\n\t;;\n    RM*:ReliantUNIX-*:*:*)\n\tGUESS=mips-sni-sysv4\n\t;;\n    RM*:SINIX-*:*:*)\n\tGUESS=mips-sni-sysv4\n\t;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\t\tGUESS=$UNAME_MACHINE-sni-sysv4\n\telse\n\t\tGUESS=ns32k-sni-sysv\n\tfi\n\t;;\n    PENTIUM:*:4.0*:*)\t# Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n\t\t\t# says <Richard.M.Bartel@ccMail.Census.GOV>\n\tGUESS=i586-unisys-sysv4\n\t;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\tGUESS=hppa1.1-stratus-sysv4\n\t;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\tGUESS=i860-stratus-sysv4\n\t;;\n    i*86:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\tGUESS=$UNAME_MACHINE-stratus-vos\n\t;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\tGUESS=hppa1.1-stratus-vos\n\t;;\n    mc68*:A/UX:*:*)\n\tGUESS=m68k-apple-aux$UNAME_RELEASE\n\t;;\n    news*:NEWS-OS:6*:*)\n\tGUESS=mips-sony-newsos6\n\t;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif test -d /usr/nec; then\n\t\tGUESS=mips-nec-sysv$UNAME_RELEASE\n\telse\n\t\tGUESS=mips-unknown-sysv$UNAME_RELEASE\n\tfi\n\t;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\tGUESS=powerpc-be-beos\n\t;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\tGUESS=powerpc-apple-beos\n\t;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\tGUESS=i586-pc-beos\n\t;;\n    BePC:Haiku:*:*)\t# Haiku running on Intel PC compatible.\n\tGUESS=i586-pc-haiku\n\t;;\n    x86_64:Haiku:*:*)\n\tGUESS=x86_64-unknown-haiku\n\t;;\n    SX-4:SUPER-UX:*:*)\n\tGUESS=sx4-nec-superux$UNAME_RELEASE\n\t;;\n    SX-5:SUPER-UX:*:*)\n\tGUESS=sx5-nec-superux$UNAME_RELEASE\n\t;;\n    SX-6:SUPER-UX:*:*)\n\tGUESS=sx6-nec-superux$UNAME_RELEASE\n\t;;\n    SX-7:SUPER-UX:*:*)\n\tGUESS=sx7-nec-superux$UNAME_RELEASE\n\t;;\n    SX-8:SUPER-UX:*:*)\n\tGUESS=sx8-nec-superux$UNAME_RELEASE\n\t;;\n    SX-8R:SUPER-UX:*:*)\n\tGUESS=sx8r-nec-superux$UNAME_RELEASE\n\t;;\n    SX-ACE:SUPER-UX:*:*)\n\tGUESS=sxace-nec-superux$UNAME_RELEASE\n\t;;\n    Power*:Rhapsody:*:*)\n\tGUESS=powerpc-apple-rhapsody$UNAME_RELEASE\n\t;;\n    *:Rhapsody:*:*)\n\tGUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE\n\t;;\n    arm64:Darwin:*:*)\n\tGUESS=aarch64-apple-darwin$UNAME_RELEASE\n\t;;\n    *:Darwin:*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tcase $UNAME_PROCESSOR in\n\t    unknown) UNAME_PROCESSOR=powerpc ;;\n\tesac\n\tif command -v xcode-select > /dev/null 2> /dev/null && \\\n\t\t! xcode-select --print-path > /dev/null 2> /dev/null ; then\n\t    # Avoid executing cc if there is no toolchain installed as\n\t    # cc will be a stub that puts up a graphical alert\n\t    # prompting the user to install developer tools.\n\t    CC_FOR_BUILD=no_compiler_found\n\telse\n\t    set_cc_for_build\n\tfi\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t   (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t   grep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tcase $UNAME_PROCESSOR in\n\t\t    i386) UNAME_PROCESSOR=x86_64 ;;\n\t\t    powerpc) UNAME_PROCESSOR=powerpc64 ;;\n\t\tesac\n\t    fi\n\t    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc\n\t    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \\\n\t\t   (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t   grep IS_PPC >/dev/null\n\t    then\n\t\tUNAME_PROCESSOR=powerpc\n\t    fi\n\telif test \"$UNAME_PROCESSOR\" = i386 ; then\n\t    # uname -m returns i386 or x86_64\n\t    UNAME_PROCESSOR=$UNAME_MACHINE\n\tfi\n\tGUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE\n\t;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tif test \"$UNAME_PROCESSOR\" = x86; then\n\t\tUNAME_PROCESSOR=i386\n\t\tUNAME_MACHINE=pc\n\tfi\n\tGUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE\n\t;;\n    *:QNX:*:4*)\n\tGUESS=i386-pc-qnx\n\t;;\n    NEO-*:NONSTOP_KERNEL:*:*)\n\tGUESS=neo-tandem-nsk$UNAME_RELEASE\n\t;;\n    NSE-*:NONSTOP_KERNEL:*:*)\n\tGUESS=nse-tandem-nsk$UNAME_RELEASE\n\t;;\n    NSR-*:NONSTOP_KERNEL:*:*)\n\tGUESS=nsr-tandem-nsk$UNAME_RELEASE\n\t;;\n    NSV-*:NONSTOP_KERNEL:*:*)\n\tGUESS=nsv-tandem-nsk$UNAME_RELEASE\n\t;;\n    NSX-*:NONSTOP_KERNEL:*:*)\n\tGUESS=nsx-tandem-nsk$UNAME_RELEASE\n\t;;\n    *:NonStop-UX:*:*)\n\tGUESS=mips-compaq-nonstopux\n\t;;\n    BS2000:POSIX*:*:*)\n\tGUESS=bs2000-siemens-sysv\n\t;;\n    DS/*:UNIX_System_V:*:*)\n\tGUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE\n\t;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\tif test \"${cputype-}\" = 386; then\n\t    UNAME_MACHINE=i386\n\telif test \"x${cputype-}\" != x; then\n\t    UNAME_MACHINE=$cputype\n\tfi\n\tGUESS=$UNAME_MACHINE-unknown-plan9\n\t;;\n    *:TOPS-10:*:*)\n\tGUESS=pdp10-unknown-tops10\n\t;;\n    *:TENEX:*:*)\n\tGUESS=pdp10-unknown-tenex\n\t;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\tGUESS=pdp10-dec-tops20\n\t;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\tGUESS=pdp10-xkl-tops20\n\t;;\n    *:TOPS-20:*:*)\n\tGUESS=pdp10-unknown-tops20\n\t;;\n    *:ITS:*:*)\n\tGUESS=pdp10-unknown-its\n\t;;\n    SEI:*:*:SEIUX)\n\tGUESS=mips-sei-seiux$UNAME_RELEASE\n\t;;\n    *:DragonFly:*:*)\n\tDRAGONFLY_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/[-(].*//'`\n\tGUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL\n\t;;\n    *:*VMS:*:*)\n\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\tcase $UNAME_MACHINE in\n\t    A*) GUESS=alpha-dec-vms ;;\n\t    I*) GUESS=ia64-dec-vms ;;\n\t    V*) GUESS=vax-dec-vms ;;\n\tesac ;;\n    *:XENIX:*:SysV)\n\tGUESS=i386-pc-xenix\n\t;;\n    i*86:skyos:*:*)\n\tSKYOS_REL=`echo \"$UNAME_RELEASE\" | sed -e 's/ .*$//'`\n\tGUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL\n\t;;\n    i*86:rdos:*:*)\n\tGUESS=$UNAME_MACHINE-pc-rdos\n\t;;\n    i*86:Fiwix:*:*)\n\tGUESS=$UNAME_MACHINE-pc-fiwix\n\t;;\n    *:AROS:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-aros\n\t;;\n    x86_64:VMkernel:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-esx\n\t;;\n    amd64:Isilon\\ OneFS:*:*)\n\tGUESS=x86_64-unknown-onefs\n\t;;\n    *:Unleashed:*:*)\n\tGUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE\n\t;;\nesac\n\n# Do we have a guess based on uname results?\nif test \"x$GUESS\" != x; then\n    echo \"$GUESS\"\n    exit\nfi\n\n# No uname command or uname output not recognized.\nset_cc_for_build\ncat > \"$dummy.c\" <<EOF\n#ifdef _SEQUENT_\n#include <sys/types.h>\n#include <sys/utsname.h>\n#endif\n#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)\n#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)\n#include <signal.h>\n#if defined(_SIZE_T_) || defined(SIGLOST)\n#include <sys/utsname.h>\n#endif\n#endif\n#endif\nmain ()\n{\n#if defined (sony)\n#if defined (MIPSEB)\n  /* BFD wants \"bsd\" instead of \"newsos\".  Perhaps BFD should be changed,\n     I don't know....  */\n  printf (\"mips-sony-bsd\\n\"); exit (0);\n#else\n#include <sys/param.h>\n  printf (\"m68k-sony-newsos%s\\n\",\n#ifdef NEWSOS4\n  \"4\"\n#else\n  \"\"\n#endif\n  ); exit (0);\n#endif\n#endif\n\n#if defined (NeXT)\n#if !defined (__ARCHITECTURE__)\n#define __ARCHITECTURE__ \"m68k\"\n#endif\n  int version;\n  version=`(hostinfo | sed -n 's/.*NeXT Mach \\([0-9]*\\).*/\\1/p') 2>/dev/null`;\n  if (version < 4)\n    printf (\"%s-next-nextstep%d\\n\", __ARCHITECTURE__, version);\n  else\n    printf (\"%s-next-openstep%d\\n\", __ARCHITECTURE__, version);\n  exit (0);\n#endif\n\n#if defined (MULTIMAX) || defined (n16)\n#if defined (UMAXV)\n  printf (\"ns32k-encore-sysv\\n\"); exit (0);\n#else\n#if defined (CMU)\n  printf (\"ns32k-encore-mach\\n\"); exit (0);\n#else\n  printf (\"ns32k-encore-bsd\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (__386BSD__)\n  printf (\"i386-pc-bsd\\n\"); exit (0);\n#endif\n\n#if defined (sequent)\n#if defined (i386)\n  printf (\"i386-sequent-dynix\\n\"); exit (0);\n#endif\n#if defined (ns32000)\n  printf (\"ns32k-sequent-dynix\\n\"); exit (0);\n#endif\n#endif\n\n#if defined (_SEQUENT_)\n  struct utsname un;\n\n  uname(&un);\n  if (strncmp(un.version, \"V2\", 2) == 0) {\n    printf (\"i386-sequent-ptx2\\n\"); exit (0);\n  }\n  if (strncmp(un.version, \"V1\", 2) == 0) { /* XXX is V1 correct? */\n    printf (\"i386-sequent-ptx1\\n\"); exit (0);\n  }\n  printf (\"i386-sequent-ptx\\n\"); exit (0);\n#endif\n\n#if defined (vax)\n#if !defined (ultrix)\n#include <sys/param.h>\n#if defined (BSD)\n#if BSD == 43\n  printf (\"vax-dec-bsd4.3\\n\"); exit (0);\n#else\n#if BSD == 199006\n  printf (\"vax-dec-bsd4.3reno\\n\"); exit (0);\n#else\n  printf (\"vax-dec-bsd\\n\"); exit (0);\n#endif\n#endif\n#else\n  printf (\"vax-dec-bsd\\n\"); exit (0);\n#endif\n#else\n#if defined(_SIZE_T_) || defined(SIGLOST)\n  struct utsname un;\n  uname (&un);\n  printf (\"vax-dec-ultrix%s\\n\", un.release); exit (0);\n#else\n  printf (\"vax-dec-ultrix\\n\"); exit (0);\n#endif\n#endif\n#endif\n#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)\n#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)\n#if defined(_SIZE_T_) || defined(SIGLOST)\n  struct utsname *un;\n  uname (&un);\n  printf (\"mips-dec-ultrix%s\\n\", un.release); exit (0);\n#else\n  printf (\"mips-dec-ultrix\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (alliant) && defined (i860)\n  printf (\"i860-alliant-bsd\\n\"); exit (0);\n#endif\n\n  exit (1);\n}\nEOF\n\n$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" 2>/dev/null && SYSTEM_NAME=`\"$dummy\"` &&\n\t{ echo \"$SYSTEM_NAME\"; exit; }\n\n# Apollos put the system type in the environment.\ntest -d /usr/apollo && { echo \"$ISP-apollo-$SYSTYPE\"; exit; }\n\necho \"$0: unable to guess system type\" >&2\n\ncase $UNAME_MACHINE:$UNAME_SYSTEM in\n    mips:Linux | mips64:Linux)\n\t# If we got here on MIPS GNU/Linux, output extra information.\n\tcat >&2 <<EOF\n\nNOTE: MIPS GNU/Linux systems require a C compiler to fully recognize\nthe system type. Please install a C compiler and try again.\nEOF\n\t;;\nesac\n\ncat >&2 <<EOF\n\nThis script (version $timestamp), has failed to recognize the\noperating system you are using. If your script is old, overwrite *all*\ncopies of config.guess and config.sub with the latest versions from:\n\n  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess\nand\n  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub\nEOF\n\nour_year=`echo $timestamp | sed 's,-.*,,'`\nthisyear=`date +%Y`\n# shellcheck disable=SC2003\nscript_age=`expr \"$thisyear\" - \"$our_year\"`\nif test \"$script_age\" -lt 3 ; then\n   cat >&2 <<EOF\n\nIf $0 has already been updated, send the following data and any\ninformation you think might be pertinent to config-patches@gnu.org to\nprovide the necessary information to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`\n\nhostinfo               = `(hostinfo) 2>/dev/null`\n/bin/universe          = `(/bin/universe) 2>/dev/null`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`\n/bin/arch              = `(/bin/arch) 2>/dev/null`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`\n\nUNAME_MACHINE = \"$UNAME_MACHINE\"\nUNAME_RELEASE = \"$UNAME_RELEASE\"\nUNAME_SYSTEM  = \"$UNAME_SYSTEM\"\nUNAME_VERSION = \"$UNAME_VERSION\"\nEOF\nfi\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "audio/paddleaudio/third_party/patches/config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright 1992-2022 Free Software Foundation, Inc.\n\n# shellcheck disable=SC2006,SC2268 # see below for rationale\n\ntimestamp='2022-01-03'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <https://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n\n\n# Please send patches to <config-patches@gnu.org>.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# You can get the latest version of this script from:\n# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\n# The \"shellcheck disable\" line above the timestamp inhibits complaints\n# about features and limitations of the classic Bourne shell that were\n# superseded or lifted in POSIX.  However, this script identifies a wide\n# variety of pre-POSIX systems that do not have POSIX shells at all, and\n# even some reasonably current systems (Solaris 10 as case-in-point) still\n# have a pre-POSIX /bin/sh.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS\n\nCanonicalize a configuration name.\n\nOptions:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright 1992-2022 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo \"$1\"\n       exit ;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Split fields of configuration type\n# shellcheck disable=SC2162\nsaved_IFS=$IFS\nIFS=\"-\" read field1 field2 field3 field4 <<EOF\n$1\nEOF\nIFS=$saved_IFS\n\n# Separate into logical components for further validation\ncase $1 in\n\t*-*-*-*-*)\n\t\techo Invalid configuration \\`\"$1\"\\': more than four components >&2\n\t\texit 1\n\t\t;;\n\t*-*-*-*)\n\t\tbasic_machine=$field1-$field2\n\t\tbasic_os=$field3-$field4\n\t\t;;\n\t*-*-*)\n\t\t# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two\n\t\t# parts\n\t\tmaybe_os=$field2-$field3\n\t\tcase $maybe_os in\n\t\t\tnto-qnx* | linux-* | uclinux-uclibc* \\\n\t\t\t| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \\\n\t\t\t| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \\\n\t\t\t| storm-chaos* | os2-emx* | rtmk-nova*)\n\t\t\t\tbasic_machine=$field1\n\t\t\t\tbasic_os=$maybe_os\n\t\t\t\t;;\n\t\t\tandroid-linux)\n\t\t\t\tbasic_machine=$field1-unknown\n\t\t\t\tbasic_os=linux-android\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tbasic_machine=$field1-$field2\n\t\t\t\tbasic_os=$field3\n\t\t\t\t;;\n\t\tesac\n\t\t;;\n\t*-*)\n\t\t# A lone config we happen to match not fitting any pattern\n\t\tcase $field1-$field2 in\n\t\t\tdecstation-3100)\n\t\t\t\tbasic_machine=mips-dec\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\t*-*)\n\t\t\t\t# Second component is usually, but not always the OS\n\t\t\t\tcase $field2 in\n\t\t\t\t\t# Prevent following clause from handling this valid os\n\t\t\t\t\tsun*os*)\n\t\t\t\t\t\tbasic_machine=$field1\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\t\tzephyr*)\n\t\t\t\t\t\tbasic_machine=$field1-unknown\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\t\t# Manufacturers\n\t\t\t\t\tdec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \\\n\t\t\t\t\t| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \\\n\t\t\t\t\t| unicom* | ibm* | next | hp | isi* | apollo | altos* \\\n\t\t\t\t\t| convergent* | ncr* | news | 32* | 3600* | 3100* \\\n\t\t\t\t\t| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \\\n\t\t\t\t\t| ultra | tti* | harris | dolphin | highlevel | gould \\\n\t\t\t\t\t| cbm | ns | masscomp | apple | axis | knuth | cray \\\n\t\t\t\t\t| microblaze* | sim | cisco \\\n\t\t\t\t\t| oki | wec | wrs | winbond)\n\t\t\t\t\t\tbasic_machine=$field1-$field2\n\t\t\t\t\t\tbasic_os=\n\t\t\t\t\t\t;;\n\t\t\t\t\t*)\n\t\t\t\t\t\tbasic_machine=$field1\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\tesac\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t*)\n\t\t# Convert single-component short-hands not valid as part of\n\t\t# multi-component configurations.\n\t\tcase $field1 in\n\t\t\t386bsd)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\ta29khif)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tadobe68k)\n\t\t\t\tbasic_machine=m68010-adobe\n\t\t\t\tbasic_os=scout\n\t\t\t\t;;\n\t\t\talliant)\n\t\t\t\tbasic_machine=fx80-alliant\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\taltos | altos3068)\n\t\t\t\tbasic_machine=m68k-altos\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tam29k)\n\t\t\t\tbasic_machine=a29k-none\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tamdahl)\n\t\t\t\tbasic_machine=580-amdahl\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tamiga)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tamigaos | amigados)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=amigaos\n\t\t\t\t;;\n\t\t\tamigaunix | amix)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tapollo68)\n\t\t\t\tbasic_machine=m68k-apollo\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tapollo68bsd)\n\t\t\t\tbasic_machine=m68k-apollo\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\taros)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=aros\n\t\t\t\t;;\n\t\t\taux)\n\t\t\t\tbasic_machine=m68k-apple\n\t\t\t\tbasic_os=aux\n\t\t\t\t;;\n\t\t\tbalance)\n\t\t\t\tbasic_machine=ns32k-sequent\n\t\t\t\tbasic_os=dynix\n\t\t\t\t;;\n\t\t\tblackfin)\n\t\t\t\tbasic_machine=bfin-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tcegcc)\n\t\t\t\tbasic_machine=arm-unknown\n\t\t\t\tbasic_os=cegcc\n\t\t\t\t;;\n\t\t\tconvex-c1)\n\t\t\t\tbasic_machine=c1-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c2)\n\t\t\t\tbasic_machine=c2-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c32)\n\t\t\t\tbasic_machine=c32-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c34)\n\t\t\t\tbasic_machine=c34-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c38)\n\t\t\t\tbasic_machine=c38-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tcray)\n\t\t\t\tbasic_machine=j90-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tcrds | unos)\n\t\t\t\tbasic_machine=m68k-crds\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tda30)\n\t\t\t\tbasic_machine=m68k-da30\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tdecstation | pmax | pmin | dec3100 | decstatn)\n\t\t\t\tbasic_machine=mips-dec\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tdelta88)\n\t\t\t\tbasic_machine=m88k-motorola\n\t\t\t\tbasic_os=sysv3\n\t\t\t\t;;\n\t\t\tdicos)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=dicos\n\t\t\t\t;;\n\t\t\tdjgpp)\n\t\t\t\tbasic_machine=i586-pc\n\t\t\t\tbasic_os=msdosdjgpp\n\t\t\t\t;;\n\t\t\tebmon29k)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=ebmon\n\t\t\t\t;;\n\t\t\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\t\t\tbasic_machine=m68k-ericsson\n\t\t\t\tbasic_os=ose\n\t\t\t\t;;\n\t\t\tgmicro)\n\t\t\t\tbasic_machine=tron-gmicro\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tgo32)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=go32\n\t\t\t\t;;\n\t\t\th8300hms)\n\t\t\t\tbasic_machine=h8300-hitachi\n\t\t\t\tbasic_os=hms\n\t\t\t\t;;\n\t\t\th8300xray)\n\t\t\t\tbasic_machine=h8300-hitachi\n\t\t\t\tbasic_os=xray\n\t\t\t\t;;\n\t\t\th8500hms)\n\t\t\t\tbasic_machine=h8500-hitachi\n\t\t\t\tbasic_os=hms\n\t\t\t\t;;\n\t\t\tharris)\n\t\t\t\tbasic_machine=m88k-harris\n\t\t\t\tbasic_os=sysv3\n\t\t\t\t;;\n\t\t\thp300 | hp300hpux)\n\t\t\t\tbasic_machine=m68k-hp\n\t\t\t\tbasic_os=hpux\n\t\t\t\t;;\n\t\t\thp300bsd)\n\t\t\t\tbasic_machine=m68k-hp\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\thppaosf)\n\t\t\t\tbasic_machine=hppa1.1-hp\n\t\t\t\tbasic_os=osf\n\t\t\t\t;;\n\t\t\thppro)\n\t\t\t\tbasic_machine=hppa1.1-hp\n\t\t\t\tbasic_os=proelf\n\t\t\t\t;;\n\t\t\ti386mach)\n\t\t\t\tbasic_machine=i386-mach\n\t\t\t\tbasic_os=mach\n\t\t\t\t;;\n\t\t\tisi68 | isi)\n\t\t\t\tbasic_machine=m68k-isi\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tm68knommu)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tmagnum | m3230)\n\t\t\t\tbasic_machine=mips-mips\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tmerlin)\n\t\t\t\tbasic_machine=ns32k-utek\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tmingw64)\n\t\t\t\tbasic_machine=x86_64-pc\n\t\t\t\tbasic_os=mingw64\n\t\t\t\t;;\n\t\t\tmingw32)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=mingw32\n\t\t\t\t;;\n\t\t\tmingw32ce)\n\t\t\t\tbasic_machine=arm-unknown\n\t\t\t\tbasic_os=mingw32ce\n\t\t\t\t;;\n\t\t\tmonitor)\n\t\t\t\tbasic_machine=m68k-rom68k\n\t\t\t\tbasic_os=coff\n\t\t\t\t;;\n\t\t\tmorphos)\n\t\t\t\tbasic_machine=powerpc-unknown\n\t\t\t\tbasic_os=morphos\n\t\t\t\t;;\n\t\t\tmoxiebox)\n\t\t\t\tbasic_machine=moxie-unknown\n\t\t\t\tbasic_os=moxiebox\n\t\t\t\t;;\n\t\t\tmsdos)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=msdos\n\t\t\t\t;;\n\t\t\tmsys)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=msys\n\t\t\t\t;;\n\t\t\tmvs)\n\t\t\t\tbasic_machine=i370-ibm\n\t\t\t\tbasic_os=mvs\n\t\t\t\t;;\n\t\t\tnacl)\n\t\t\t\tbasic_machine=le32-unknown\n\t\t\t\tbasic_os=nacl\n\t\t\t\t;;\n\t\t\tncr3000)\n\t\t\t\tbasic_machine=i486-ncr\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tnetbsd386)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=netbsd\n\t\t\t\t;;\n\t\t\tnetwinder)\n\t\t\t\tbasic_machine=armv4l-rebel\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tnews | news700 | news800 | news900)\n\t\t\t\tbasic_machine=m68k-sony\n\t\t\t\tbasic_os=newsos\n\t\t\t\t;;\n\t\t\tnews1000)\n\t\t\t\tbasic_machine=m68030-sony\n\t\t\t\tbasic_os=newsos\n\t\t\t\t;;\n\t\t\tnecv70)\n\t\t\t\tbasic_machine=v70-nec\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tnh3000)\n\t\t\t\tbasic_machine=m68k-harris\n\t\t\t\tbasic_os=cxux\n\t\t\t\t;;\n\t\t\tnh[45]000)\n\t\t\t\tbasic_machine=m88k-harris\n\t\t\t\tbasic_os=cxux\n\t\t\t\t;;\n\t\t\tnindy960)\n\t\t\t\tbasic_machine=i960-intel\n\t\t\t\tbasic_os=nindy\n\t\t\t\t;;\n\t\t\tmon960)\n\t\t\t\tbasic_machine=i960-intel\n\t\t\t\tbasic_os=mon960\n\t\t\t\t;;\n\t\t\tnonstopux)\n\t\t\t\tbasic_machine=mips-compaq\n\t\t\t\tbasic_os=nonstopux\n\t\t\t\t;;\n\t\t\tos400)\n\t\t\t\tbasic_machine=powerpc-ibm\n\t\t\t\tbasic_os=os400\n\t\t\t\t;;\n\t\t\tOSE68000 | ose68000)\n\t\t\t\tbasic_machine=m68000-ericsson\n\t\t\t\tbasic_os=ose\n\t\t\t\t;;\n\t\t\tos68k)\n\t\t\t\tbasic_machine=m68k-none\n\t\t\t\tbasic_os=os68k\n\t\t\t\t;;\n\t\t\tparagon)\n\t\t\t\tbasic_machine=i860-intel\n\t\t\t\tbasic_os=osf\n\t\t\t\t;;\n\t\t\tparisc)\n\t\t\t\tbasic_machine=hppa-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tpsp)\n\t\t\t\tbasic_machine=mipsallegrexel-sony\n\t\t\t\tbasic_os=psp\n\t\t\t\t;;\n\t\t\tpw32)\n\t\t\t\tbasic_machine=i586-unknown\n\t\t\t\tbasic_os=pw32\n\t\t\t\t;;\n\t\t\trdos | rdos64)\n\t\t\t\tbasic_machine=x86_64-pc\n\t\t\t\tbasic_os=rdos\n\t\t\t\t;;\n\t\t\trdos32)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=rdos\n\t\t\t\t;;\n\t\t\trom68k)\n\t\t\t\tbasic_machine=m68k-rom68k\n\t\t\t\tbasic_os=coff\n\t\t\t\t;;\n\t\t\tsa29200)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tsei)\n\t\t\t\tbasic_machine=mips-sei\n\t\t\t\tbasic_os=seiux\n\t\t\t\t;;\n\t\t\tsequent)\n\t\t\t\tbasic_machine=i386-sequent\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsps7)\n\t\t\t\tbasic_machine=m68k-bull\n\t\t\t\tbasic_os=sysv2\n\t\t\t\t;;\n\t\t\tst2000)\n\t\t\t\tbasic_machine=m68k-tandem\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tstratus)\n\t\t\t\tbasic_machine=i860-stratus\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tsun2)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun2os3)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun2os4)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun3)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun3os3)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun3os4)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun4)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun4os3)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun4os4)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun4sol2)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=solaris2\n\t\t\t\t;;\n\t\t\tsun386 | sun386i | roadrunner)\n\t\t\t\tbasic_machine=i386-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsv1)\n\t\t\t\tbasic_machine=sv1-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tsymmetry)\n\t\t\t\tbasic_machine=i386-sequent\n\t\t\t\tbasic_os=dynix\n\t\t\t\t;;\n\t\t\tt3e)\n\t\t\t\tbasic_machine=alphaev5-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tt90)\n\t\t\t\tbasic_machine=t90-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\ttoad1)\n\t\t\t\tbasic_machine=pdp10-xkl\n\t\t\t\tbasic_os=tops20\n\t\t\t\t;;\n\t\t\ttpf)\n\t\t\t\tbasic_machine=s390x-ibm\n\t\t\t\tbasic_os=tpf\n\t\t\t\t;;\n\t\t\tudi29k)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tultra3)\n\t\t\t\tbasic_machine=a29k-nyu\n\t\t\t\tbasic_os=sym1\n\t\t\t\t;;\n\t\t\tv810 | necv810)\n\t\t\t\tbasic_machine=v810-nec\n\t\t\t\tbasic_os=none\n\t\t\t\t;;\n\t\t\tvaxv)\n\t\t\t\tbasic_machine=vax-dec\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tvms)\n\t\t\t\tbasic_machine=vax-dec\n\t\t\t\tbasic_os=vms\n\t\t\t\t;;\n\t\t\tvsta)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=vsta\n\t\t\t\t;;\n\t\t\tvxworks960)\n\t\t\t\tbasic_machine=i960-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\tvxworks68)\n\t\t\t\tbasic_machine=m68k-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\tvxworks29k)\n\t\t\t\tbasic_machine=a29k-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\txbox)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=mingw32\n\t\t\t\t;;\n\t\t\tymp)\n\t\t\t\tbasic_machine=ymp-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tbasic_machine=$1\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\n# Decode 1-component or ad-hoc basic machines\ncase $basic_machine in\n\t# Here we handle the default manufacturer of certain CPU types.  It is in\n\t# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tcpu=hppa1.1\n\t\tvendor=winbond\n\t\t;;\n\top50n)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\t;;\n\top60c)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\t;;\n\tibm*)\n\t\tcpu=i370\n\t\tvendor=ibm\n\t\t;;\n\torion105)\n\t\tcpu=clipper\n\t\tvendor=highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tcpu=m68k\n\t\tvendor=apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tcpu=powerpc\n\t\tvendor=apple\n\t\t;;\n\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tcpu=m68000\n\t\tvendor=att\n\t\t;;\n\t3b*)\n\t\tcpu=we32k\n\t\tvendor=att\n\t\t;;\n\tbluegene*)\n\t\tcpu=powerpc\n\t\tvendor=ibm\n\t\tbasic_os=cnk\n\t\t;;\n\tdecsystem10* | dec10*)\n\t\tcpu=pdp10\n\t\tvendor=dec\n\t\tbasic_os=tops10\n\t\t;;\n\tdecsystem20* | dec20*)\n\t\tcpu=pdp10\n\t\tvendor=dec\n\t\tbasic_os=tops20\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tcpu=m68k\n\t\tvendor=motorola\n\t\t;;\n\tdpx2*)\n\t\tcpu=m68k\n\t\tvendor=bull\n\t\tbasic_os=sysv3\n\t\t;;\n\tencore | umax | mmax)\n\t\tcpu=ns32k\n\t\tvendor=encore\n\t\t;;\n\telxsi)\n\t\tcpu=elxsi\n\t\tvendor=elxsi\n\t\tbasic_os=${basic_os:-bsd}\n\t\t;;\n\tfx2800)\n\t\tcpu=i860\n\t\tvendor=alliant\n\t\t;;\n\tgenix)\n\t\tcpu=ns32k\n\t\tvendor=ns\n\t\t;;\n\th3050r* | hiux*)\n\t\tcpu=hppa1.1\n\t\tvendor=hitachi\n\t\tbasic_os=hiuxwe2\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tcpu=m68000\n\t\tvendor=hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tcpu=m68k\n\t\tvendor=hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\ti*86v32)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv32\n\t\t;;\n\ti*86v4*)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv4\n\t\t;;\n\ti*86v)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv\n\t\t;;\n\ti*86sol2)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=solaris2\n\t\t;;\n\tj90 | j90-cray)\n\t\tcpu=j90\n\t\tvendor=cray\n\t\tbasic_os=${basic_os:-unicos}\n\t\t;;\n\tiris | iris4d)\n\t\tcpu=mips\n\t\tvendor=sgi\n\t\tcase $basic_os in\n\t\t    irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tbasic_os=irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tminiframe)\n\t\tcpu=m68000\n\t\tvendor=convergent\n\t\t;;\n\t*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tcpu=m68k\n\t\tvendor=atari\n\t\tbasic_os=mint\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tcpu=mips\n\t\tvendor=sony\n\t\tbasic_os=newsos\n\t\t;;\n\tnext | m*-next)\n\t\tcpu=m68k\n\t\tvendor=next\n\t\tcase $basic_os in\n\t\t    openstep*)\n\t\t        ;;\n\t\t    nextstep*)\n\t\t\t;;\n\t\t    ns2*)\n\t\t      basic_os=nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      basic_os=nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnp1)\n\t\tcpu=np1\n\t\tvendor=gould\n\t\t;;\n\top50n-* | op60c-*)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\tbasic_os=proelf\n\t\t;;\n\tpa-hitachi)\n\t\tcpu=hppa1.1\n\t\tvendor=hitachi\n\t\tbasic_os=hiuxwe2\n\t\t;;\n\tpbd)\n\t\tcpu=sparc\n\t\tvendor=tti\n\t\t;;\n\tpbb)\n\t\tcpu=m68k\n\t\tvendor=tti\n\t\t;;\n\tpc532)\n\t\tcpu=ns32k\n\t\tvendor=pc532\n\t\t;;\n\tpn)\n\t\tcpu=pn\n\t\tvendor=gould\n\t\t;;\n\tpower)\n\t\tcpu=power\n\t\tvendor=ibm\n\t\t;;\n\tps2)\n\t\tcpu=i386\n\t\tvendor=ibm\n\t\t;;\n\trm[46]00)\n\t\tcpu=mips\n\t\tvendor=siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tcpu=romp\n\t\tvendor=ibm\n\t\t;;\n\tsde)\n\t\tcpu=mipsisa32\n\t\tvendor=sde\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tsimso-wrs)\n\t\tcpu=sparclite\n\t\tvendor=wrs\n\t\tbasic_os=vxworks\n\t\t;;\n\ttower | tower-32)\n\t\tcpu=m68k\n\t\tvendor=ncr\n\t\t;;\n\tvpp*|vx|vx-*)\n\t\tcpu=f301\n\t\tvendor=fujitsu\n\t\t;;\n\tw65)\n\t\tcpu=w65\n\t\tvendor=wdc\n\t\t;;\n\tw89k-*)\n\t\tcpu=hppa1.1\n\t\tvendor=winbond\n\t\tbasic_os=proelf\n\t\t;;\n\tnone)\n\t\tcpu=none\n\t\tvendor=none\n\t\t;;\n\tleon|leon[3-9])\n\t\tcpu=sparc\n\t\tvendor=$basic_machine\n\t\t;;\n\tleon-*|leon[3-9]-*)\n\t\tcpu=sparc\n\t\tvendor=`echo \"$basic_machine\" | sed 's/-.*//'`\n\t\t;;\n\n\t*-*)\n\t\t# shellcheck disable=SC2162\n\t\tsaved_IFS=$IFS\n\t\tIFS=\"-\" read cpu vendor <<EOF\n$basic_machine\nEOF\n\t\tIFS=$saved_IFS\n\t\t;;\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t\tcpu=$basic_machine\n\t\tvendor=pc\n\t\t;;\n\t# These rules are duplicated from below for sake of the special case above;\n\t# i.e. things that normalized to x86 arches should also default to \"pc\"\n\tpc98)\n\t\tcpu=i386\n\t\tvendor=pc\n\t\t;;\n\tx64 | amd64)\n\t\tcpu=x86_64\n\t\tvendor=pc\n\t\t;;\n\t# Recognize the basic CPU types without company name.\n\t*)\n\t\tcpu=$basic_machine\n\t\tvendor=unknown\n\t\t;;\nesac\n\nunset -v basic_machine\n\n# Decode basic machines in the full and proper CPU-Company form.\ncase $cpu-$vendor in\n\t# Here we handle the default manufacturer of certain CPU types in canonical form. It is in\n\t# some cases the only manufacturer, in others, it is the most popular.\n\tcraynv-unknown)\n\t\tvendor=cray\n\t\tbasic_os=${basic_os:-unicosmp}\n\t\t;;\n\tc90-unknown | c90-cray)\n\t\tvendor=cray\n\t\tbasic_os=${Basic_os:-unicos}\n\t\t;;\n\tfx80-unknown)\n\t\tvendor=alliant\n\t\t;;\n\tromp-unknown)\n\t\tvendor=ibm\n\t\t;;\n\tmmix-unknown)\n\t\tvendor=knuth\n\t\t;;\n\tmicroblaze-unknown | microblazeel-unknown)\n\t\tvendor=xilinx\n\t\t;;\n\trs6000-unknown)\n\t\tvendor=ibm\n\t\t;;\n\tvax-unknown)\n\t\tvendor=dec\n\t\t;;\n\tpdp11-unknown)\n\t\tvendor=dec\n\t\t;;\n\twe32k-unknown)\n\t\tvendor=att\n\t\t;;\n\tcydra-unknown)\n\t\tvendor=cydrome\n\t\t;;\n\ti370-ibm*)\n\t\tvendor=ibm\n\t\t;;\n\torion-unknown)\n\t\tvendor=highlevel\n\t\t;;\n\txps-unknown | xps100-unknown)\n\t\tcpu=xps100\n\t\tvendor=honeywell\n\t\t;;\n\n\t# Here we normalize CPU types with a missing or matching vendor\n\tarmh-unknown | armh-alt)\n\t\tcpu=armv7l\n\t\tvendor=alt\n\t\tbasic_os=${basic_os:-linux-gnueabihf}\n\t\t;;\n\tdpx20-unknown | dpx20-bull)\n\t\tcpu=rs6000\n\t\tvendor=bull\n\t\tbasic_os=${basic_os:-bosx}\n\t\t;;\n\n\t# Here we normalize CPU types irrespective of the vendor\n\tamd64-*)\n\t\tcpu=x86_64\n\t\t;;\n\tblackfin-*)\n\t\tcpu=bfin\n\t\tbasic_os=linux\n\t\t;;\n\tc54x-*)\n\t\tcpu=tic54x\n\t\t;;\n\tc55x-*)\n\t\tcpu=tic55x\n\t\t;;\n\tc6x-*)\n\t\tcpu=tic6x\n\t\t;;\n\te500v[12]-*)\n\t\tcpu=powerpc\n\t\tbasic_os=${basic_os}\"spe\"\n\t\t;;\n\tmips3*-*)\n\t\tcpu=mips64\n\t\t;;\n\tms1-*)\n\t\tcpu=mt\n\t\t;;\n\tm68knommu-*)\n\t\tcpu=m68k\n\t\tbasic_os=linux\n\t\t;;\n\tm9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)\n\t\tcpu=s12z\n\t\t;;\n\topenrisc-*)\n\t\tcpu=or32\n\t\t;;\n\tparisc-*)\n\t\tcpu=hppa\n\t\tbasic_os=linux\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tcpu=i586\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)\n\t\tcpu=i686\n\t\t;;\n\tpentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)\n\t\tcpu=i686\n\t\t;;\n\tpentium4-*)\n\t\tcpu=i786\n\t\t;;\n\tpc98-*)\n\t\tcpu=i386\n\t\t;;\n\tppc-* | ppcbe-*)\n\t\tcpu=powerpc\n\t\t;;\n\tppcle-* | powerpclittle-*)\n\t\tcpu=powerpcle\n\t\t;;\n\tppc64-*)\n\t\tcpu=powerpc64\n\t\t;;\n\tppc64le-* | powerpc64little-*)\n\t\tcpu=powerpc64le\n\t\t;;\n\tsb1-*)\n\t\tcpu=mipsisa64sb1\n\t\t;;\n\tsb1el-*)\n\t\tcpu=mipsisa64sb1el\n\t\t;;\n\tsh5e[lb]-*)\n\t\tcpu=`echo \"$cpu\" | sed 's/^\\(sh.\\)e\\(.\\)$/\\1\\2e/'`\n\t\t;;\n\tspur-*)\n\t\tcpu=spur\n\t\t;;\n\tstrongarm-* | thumb-*)\n\t\tcpu=arm\n\t\t;;\n\ttx39-*)\n\t\tcpu=mipstx39\n\t\t;;\n\ttx39el-*)\n\t\tcpu=mipstx39el\n\t\t;;\n\tx64-*)\n\t\tcpu=x86_64\n\t\t;;\n\txscale-* | xscalee[bl]-*)\n\t\tcpu=`echo \"$cpu\" | sed 's/^xscale/arm/'`\n\t\t;;\n\tarm64-* | aarch64le-*)\n\t\tcpu=aarch64\n\t\t;;\n\n\t# Recognize the canonical CPU Types that limit and/or modify the\n\t# company names they are paired with.\n\tcr16-*)\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tcrisv32-* | etraxfs*-*)\n\t\tcpu=crisv32\n\t\tvendor=axis\n\t\t;;\n\tcris-* | etrax*-*)\n\t\tcpu=cris\n\t\tvendor=axis\n\t\t;;\n\tcrx-*)\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tneo-tandem)\n\t\tcpu=neo\n\t\tvendor=tandem\n\t\t;;\n\tnse-tandem)\n\t\tcpu=nse\n\t\tvendor=tandem\n\t\t;;\n\tnsr-tandem)\n\t\tcpu=nsr\n\t\tvendor=tandem\n\t\t;;\n\tnsv-tandem)\n\t\tcpu=nsv\n\t\tvendor=tandem\n\t\t;;\n\tnsx-tandem)\n\t\tcpu=nsx\n\t\tvendor=tandem\n\t\t;;\n\tmipsallegrexel-sony)\n\t\tcpu=mipsallegrexel\n\t\tvendor=sony\n\t\t;;\n\ttile*-*)\n\t\tbasic_os=${basic_os:-linux-gnu}\n\t\t;;\n\n\t*)\n\t\t# Recognize the canonical CPU types that are allowed with any\n\t\t# company name.\n\t\tcase $cpu in\n\t\t\t1750a | 580 \\\n\t\t\t| a29k \\\n\t\t\t| aarch64 | aarch64_be \\\n\t\t\t| abacus \\\n\t\t\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \\\n\t\t\t| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \\\n\t\t\t| alphapca5[67] | alpha64pca5[67] \\\n\t\t\t| am33_2.0 \\\n\t\t\t| amdgcn \\\n\t\t\t| arc | arceb | arc32 | arc64 \\\n\t\t\t| arm | arm[lb]e | arme[lb] | armv* \\\n\t\t\t| avr | avr32 \\\n\t\t\t| asmjs \\\n\t\t\t| ba \\\n\t\t\t| be32 | be64 \\\n\t\t\t| bfin | bpf | bs2000 \\\n\t\t\t| c[123]* | c30 | [cjt]90 | c4x \\\n\t\t\t| c8051 | clipper | craynv | csky | cydra \\\n\t\t\t| d10v | d30v | dlx | dsp16xx \\\n\t\t\t| e2k | elxsi | epiphany \\\n\t\t\t| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \\\n\t\t\t| h8300 | h8500 \\\n\t\t\t| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t\t\t| hexagon \\\n\t\t\t| i370 | i*86 | i860 | i960 | ia16 | ia64 \\\n\t\t\t| ip2k | iq2000 \\\n\t\t\t| k1om \\\n\t\t\t| le32 | le64 \\\n\t\t\t| lm32 \\\n\t\t\t| loongarch32 | loongarch64 | loongarchx32 \\\n\t\t\t| m32c | m32r | m32rle \\\n\t\t\t| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \\\n\t\t\t| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \\\n\t\t\t| m88110 | m88k | maxq | mb | mcore | mep | metag \\\n\t\t\t| microblaze | microblazeel \\\n\t\t\t| mips | mipsbe | mipseb | mipsel | mipsle \\\n\t\t\t| mips16 \\\n\t\t\t| mips64 | mips64eb | mips64el \\\n\t\t\t| mips64octeon | mips64octeonel \\\n\t\t\t| mips64orion | mips64orionel \\\n\t\t\t| mips64r5900 | mips64r5900el \\\n\t\t\t| mips64vr | mips64vrel \\\n\t\t\t| mips64vr4100 | mips64vr4100el \\\n\t\t\t| mips64vr4300 | mips64vr4300el \\\n\t\t\t| mips64vr5000 | mips64vr5000el \\\n\t\t\t| mips64vr5900 | mips64vr5900el \\\n\t\t\t| mipsisa32 | mipsisa32el \\\n\t\t\t| mipsisa32r2 | mipsisa32r2el \\\n\t\t\t| mipsisa32r3 | mipsisa32r3el \\\n\t\t\t| mipsisa32r5 | mipsisa32r5el \\\n\t\t\t| mipsisa32r6 | mipsisa32r6el \\\n\t\t\t| mipsisa64 | mipsisa64el \\\n\t\t\t| mipsisa64r2 | mipsisa64r2el \\\n\t\t\t| mipsisa64r3 | mipsisa64r3el \\\n\t\t\t| mipsisa64r5 | mipsisa64r5el \\\n\t\t\t| mipsisa64r6 | mipsisa64r6el \\\n\t\t\t| mipsisa64sb1 | mipsisa64sb1el \\\n\t\t\t| mipsisa64sr71k | mipsisa64sr71kel \\\n\t\t\t| mipsr5900 | mipsr5900el \\\n\t\t\t| mipstx39 | mipstx39el \\\n\t\t\t| mmix \\\n\t\t\t| mn10200 | mn10300 \\\n\t\t\t| moxie \\\n\t\t\t| mt \\\n\t\t\t| msp430 \\\n\t\t\t| nds32 | nds32le | nds32be \\\n\t\t\t| nfp \\\n\t\t\t| nios | nios2 | nios2eb | nios2el \\\n\t\t\t| none | np1 | ns16k | ns32k | nvptx \\\n\t\t\t| open8 \\\n\t\t\t| or1k* \\\n\t\t\t| or32 \\\n\t\t\t| orion \\\n\t\t\t| picochip \\\n\t\t\t| pdp10 | pdp11 | pj | pjl | pn | power \\\n\t\t\t| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \\\n\t\t\t| pru \\\n\t\t\t| pyramid \\\n\t\t\t| riscv | riscv32 | riscv32be | riscv64 | riscv64be \\\n\t\t\t| rl78 | romp | rs6000 | rx \\\n\t\t\t| s390 | s390x \\\n\t\t\t| score \\\n\t\t\t| sh | shl \\\n\t\t\t| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \\\n\t\t\t| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \\\n\t\t\t| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \\\n\t\t\t| sparclite \\\n\t\t\t| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \\\n\t\t\t| spu \\\n\t\t\t| tahoe \\\n\t\t\t| thumbv7* \\\n\t\t\t| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \\\n\t\t\t| tron \\\n\t\t\t| ubicom32 \\\n\t\t\t| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \\\n\t\t\t| vax \\\n\t\t\t| visium \\\n\t\t\t| w65 \\\n\t\t\t| wasm32 | wasm64 \\\n\t\t\t| we32k \\\n\t\t\t| x86 | x86_64 | xc16x | xgate | xps100 \\\n\t\t\t| xstormy16 | xtensa* \\\n\t\t\t| ymp \\\n\t\t\t| z8k | z80)\n\t\t\t\t;;\n\n\t\t\t*)\n\t\t\t\techo Invalid configuration \\`\"$1\"\\': machine \\`\"$cpu-$vendor\"\\' not recognized 1>&2\n\t\t\t\texit 1\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $vendor in\n\tdigital*)\n\t\tvendor=dec\n\t\t;;\n\tcommodore*)\n\t\tvendor=cbm\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif test x$basic_os != x\nthen\n\n# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just\n# set os.\ncase $basic_os in\n\tgnu/linux*)\n\t\tkernel=linux\n\t\tos=`echo \"$basic_os\" | sed -e 's|gnu/linux|gnu|'`\n\t\t;;\n\tos2-emx)\n\t\tkernel=os2\n\t\tos=`echo \"$basic_os\" | sed -e 's|os2-emx|emx|'`\n\t\t;;\n\tnto-qnx*)\n\t\tkernel=nto\n\t\tos=`echo \"$basic_os\" | sed -e 's|nto-qnx|qnx|'`\n\t\t;;\n\t*-*)\n\t\t# shellcheck disable=SC2162\n\t\tsaved_IFS=$IFS\n\t\tIFS=\"-\" read kernel os <<EOF\n$basic_os\nEOF\n\t\tIFS=$saved_IFS\n\t\t;;\n\t# Default OS when just kernel was specified\n\tnto*)\n\t\tkernel=nto\n\t\tos=`echo \"$basic_os\" | sed -e 's|nto|qnx|'`\n\t\t;;\n\tlinux*)\n\t\tkernel=linux\n\t\tos=`echo \"$basic_os\" | sed -e 's|linux|gnu|'`\n\t\t;;\n\t*)\n\t\tkernel=\n\t\tos=$basic_os\n\t\t;;\nesac\n\n# Now, normalize the OS (knowing we just have one component, it's not a kernel,\n# etc.)\ncase $os in\n\t# First match some system type aliases that might get confused\n\t# with valid system types.\n\t# solaris* is a basic system type, with this one exception.\n\tauroraux)\n\t\tos=auroraux\n\t\t;;\n\tbluegene*)\n\t\tos=cnk\n\t\t;;\n\tsolaris1 | solaris1.*)\n\t\tos=`echo \"$os\" | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\tsolaris)\n\t\tos=solaris2\n\t\t;;\n\tunixware*)\n\t\tos=sysv4.2uw\n\t\t;;\n\t# es1800 is here to avoid being matched by es* (a different OS)\n\tes1800*)\n\t\tos=ose\n\t\t;;\n\t# Some version numbers need modification\n\tchorusos*)\n\t\tos=chorusos\n\t\t;;\n\tisc)\n\t\tos=isc2.2\n\t\t;;\n\tsco6)\n\t\tos=sco5v6\n\t\t;;\n\tsco5)\n\t\tos=sco3.2v5\n\t\t;;\n\tsco4)\n\t\tos=sco3.2v4\n\t\t;;\n\tsco3.2.[4-9]*)\n\t\tos=`echo \"$os\" | sed -e 's/sco3.2./sco3.2v/'`\n\t\t;;\n\tsco*v* | scout)\n\t\t# Don't match below\n\t\t;;\n\tsco*)\n\t\tos=sco3.2v2\n\t\t;;\n\tpsos*)\n\t\tos=psos\n\t\t;;\n\tqnx*)\n\t\tos=qnx\n\t\t;;\n\thiux*)\n\t\tos=hiuxwe2\n\t\t;;\n\tlynx*178)\n\t\tos=lynxos178\n\t\t;;\n\tlynx*5)\n\t\tos=lynxos5\n\t\t;;\n\tlynxos*)\n\t\t# don't get caught up in next wildcard\n\t\t;;\n\tlynx*)\n\t\tos=lynxos\n\t\t;;\n\tmac[0-9]*)\n\t\tos=`echo \"$os\" | sed -e 's|mac|macos|'`\n\t\t;;\n\topened*)\n\t\tos=openedition\n\t\t;;\n\tos400*)\n\t\tos=os400\n\t\t;;\n\tsunos5*)\n\t\tos=`echo \"$os\" | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\tsunos6*)\n\t\tos=`echo \"$os\" | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\twince*)\n\t\tos=wince\n\t\t;;\n\tutek*)\n\t\tos=bsd\n\t\t;;\n\tdynix*)\n\t\tos=bsd\n\t\t;;\n\tacis*)\n\t\tos=aos\n\t\t;;\n\tatheos*)\n\t\tos=atheos\n\t\t;;\n\tsyllable*)\n\t\tos=syllable\n\t\t;;\n\t386bsd)\n\t\tos=bsd\n\t\t;;\n\tctix* | uts*)\n\t\tos=sysv\n\t\t;;\n\tnova*)\n\t\tos=rtmk-nova\n\t\t;;\n\tns2)\n\t\tos=nextstep2\n\t\t;;\n\t# Preserve the version number of sinix5.\n\tsinix5.*)\n\t\tos=`echo \"$os\" | sed -e 's|sinix|sysv|'`\n\t\t;;\n\tsinix*)\n\t\tos=sysv4\n\t\t;;\n\ttpf*)\n\t\tos=tpf\n\t\t;;\n\ttriton*)\n\t\tos=sysv3\n\t\t;;\n\toss*)\n\t\tos=sysv3\n\t\t;;\n\tsvr4*)\n\t\tos=sysv4\n\t\t;;\n\tsvr3)\n\t\tos=sysv3\n\t\t;;\n\tsysvr4)\n\t\tos=sysv4\n\t\t;;\n\tose*)\n\t\tos=ose\n\t\t;;\n\t*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)\n\t\tos=mint\n\t\t;;\n\tdicos*)\n\t\tos=dicos\n\t\t;;\n\tpikeos*)\n\t\t# Until real need of OS specific support for\n\t\t# particular features comes up, bare metal\n\t\t# configurations are quite functional.\n\t\tcase $cpu in\n\t\t    arm*)\n\t\t\tos=eabi\n\t\t\t;;\n\t\t    *)\n\t\t\tos=elf\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t*)\n\t\t# No normalization, but not necessarily accepted, that comes below.\n\t\t;;\nesac\n\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\nkernel=\ncase $cpu-$vendor in\n\tscore-*)\n\t\tos=elf\n\t\t;;\n\tspu-*)\n\t\tos=elf\n\t\t;;\n\t*-acorn)\n\t\tos=riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tkernel=linux\n\t\tos=gnu\n\t\t;;\n\tarm*-semi)\n\t\tos=aout\n\t\t;;\n\tc4x-* | tic4x-*)\n\t\tos=coff\n\t\t;;\n\tc8051-*)\n\t\tos=elf\n\t\t;;\n\tclipper-intergraph)\n\t\tos=clix\n\t\t;;\n\thexagon-*)\n\t\tos=elf\n\t\t;;\n\ttic54x-*)\n\t\tos=coff\n\t\t;;\n\ttic55x-*)\n\t\tos=coff\n\t\t;;\n\ttic6x-*)\n\t\tos=coff\n\t\t;;\n\t# This must come before the *-dec entry.\n\tpdp10-*)\n\t\tos=tops20\n\t\t;;\n\tpdp11-*)\n\t\tos=none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=domain\n\t\t;;\n\ti386-sun)\n\t\tos=sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=sunos3\n\t\t;;\n\tm68*-cisco)\n\t\tos=aout\n\t\t;;\n\tmep-*)\n\t\tos=elf\n\t\t;;\n\tmips*-cisco)\n\t\tos=elf\n\t\t;;\n\tmips*-*)\n\t\tos=elf\n\t\t;;\n\tor32-*)\n\t\tos=coff\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=sunos4.1.1\n\t\t;;\n\tpru-*)\n\t\tos=elf\n\t\t;;\n\t*-be)\n\t\tos=beos\n\t\t;;\n\t*-ibm)\n\t\tos=aix\n\t\t;;\n\t*-knuth)\n\t\tos=mmixware\n\t\t;;\n\t*-wec)\n\t\tos=proelf\n\t\t;;\n\t*-winbond)\n\t\tos=proelf\n\t\t;;\n\t*-oki)\n\t\tos=proelf\n\t\t;;\n\t*-hp)\n\t\tos=hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=sysv\n\t\t;;\n\t*-cbm)\n\t\tos=amigaos\n\t\t;;\n\t*-dg)\n\t\tos=dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=luna\n\t\t;;\n\t*-next)\n\t\tos=nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=ptx\n\t\t;;\n\t*-crds)\n\t\tos=unos\n\t\t;;\n\t*-ns)\n\t\tos=genix\n\t\t;;\n\ti370-*)\n\t\tos=mvs\n\t\t;;\n\t*-gould)\n\t\tos=sysv\n\t\t;;\n\t*-highlevel)\n\t\tos=bsd\n\t\t;;\n\t*-encore)\n\t\tos=bsd\n\t\t;;\n\t*-sgi)\n\t\tos=irix\n\t\t;;\n\t*-siemens)\n\t\tos=sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=coff\n\t\t;;\n\t*-*bug)\n\t\tos=coff\n\t\t;;\n\t*-apple)\n\t\tos=macos\n\t\t;;\n\t*-atari*)\n\t\tos=mint\n\t\t;;\n\t*-wrs)\n\t\tos=vxworks\n\t\t;;\n\t*)\n\t\tos=none\n\t\t;;\nesac\n\nfi\n\n# Now, validate our (potentially fixed-up) OS.\ncase $os in\n\t# Sometimes we do \"kernel-libc\", so those need to count as OSes.\n\tmusl* | newlib* | relibc* | uclibc*)\n\t\t;;\n\t# Likewise for \"kernel-abi\"\n\teabi* | gnueabi*)\n\t\t;;\n\t# VxWorks passes extra cpu info in the 4th filed.\n\tsimlinux | simwindows | spe)\n\t\t;;\n\t# Now accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST end in a * to match a version number.\n\tgnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \\\n\t     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \\\n\t     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \\\n\t     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \\\n\t     | hiux* | abug | nacl* | netware* | windows* \\\n\t     | os9* | macos* | osx* | ios* \\\n\t     | mpw* | magic* | mmixware* | mon960* | lnews* \\\n\t     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \\\n\t     | aos* | aros* | cloudabi* | sortix* | twizzler* \\\n\t     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \\\n\t     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \\\n\t     | mirbsd* | netbsd* | dicos* | openedition* | ose* \\\n\t     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \\\n\t     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \\\n\t     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \\\n\t     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \\\n\t     | udi* | lites* | ieee* | go32* | aux* | hcos* \\\n\t     | chorusrdb* | cegcc* | glidix* | serenity* \\\n\t     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \\\n\t     | midipix* | mingw32* | mingw64* | mint* \\\n\t     | uxpv* | beos* | mpeix* | udk* | moxiebox* \\\n\t     | interix* | uwin* | mks* | rhapsody* | darwin* \\\n\t     | openstep* | oskit* | conix* | pw32* | nonstopux* \\\n\t     | storm-chaos* | tops10* | tenex* | tops20* | its* \\\n\t     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \\\n\t     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \\\n\t     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \\\n\t     | skyos* | haiku* | rdos* | toppers* | drops* | es* \\\n\t     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \\\n\t     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \\\n\t     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \\\n\t     | fiwix* )\n\t\t;;\n\t# This one is extra strict with allowed versions\n\tsco3.2v2 | sco3.2v[4-9]* | sco5v6*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\t;;\n\tnone)\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`\"$1\"\\': OS \\`\"$os\"\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# As a final step for OS-related things, validate the OS-kernel combination\n# (given a valid OS), if there is a kernel.\ncase $kernel-$os in\n\tlinux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \\\n\t\t   | linux-musl* | linux-relibc* | linux-uclibc* )\n\t\t;;\n\tuclinux-uclibc* )\n\t\t;;\n\t-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )\n\t\t# These are just libc implementations, not actual OSes, and thus\n\t\t# require a kernel.\n\t\techo \"Invalid configuration \\`$1': libc \\`$os' needs explicit kernel.\" 1>&2\n\t\texit 1\n\t\t;;\n\tkfreebsd*-gnu* | kopensolaris*-gnu*)\n\t\t;;\n\tvxworks-simlinux | vxworks-simwindows | vxworks-spe)\n\t\t;;\n\tnto-qnx*)\n\t\t;;\n\tos2-emx)\n\t\t;;\n\t*-eabi* | *-gnueabi*)\n\t\t;;\n\t-*)\n\t\t# Blank kernel with real OS is always fine.\n\t\t;;\n\t*-*)\n\t\techo \"Invalid configuration \\`$1': Kernel \\`$kernel' not known to work with OS \\`$os'.\" 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\ncase $vendor in\n\tunknown)\n\t\tcase $cpu-$os in\n\t\t\t*-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t*-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t*-cnk* | *-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t*-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t*-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t*-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t*-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t*-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t*-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t*-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t*-clix*)\n\t\t\t\tvendor=intergraph\n\t\t\t\t;;\n\t\t\t*-mvs* | *-opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-os400*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\ts390-* | s390x-*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t*-tpf*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-vxsim* | *-vxworks* | *-windiss*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t*-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t*-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t*-mpw* | *-macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t*-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\necho \"$cpu-$vendor-${kernel:+$kernel-}$os\"\nexit\n\n# Local variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "audio/paddleaudio/third_party/patches/libmad.patch",
    "content": "See the followings for the origin of this patch\nhttp://www.linuxfromscratch.org/blfs/view/svn/multimedia/libmad.html\nhttp://www.linuxfromscratch.org/patches/blfs/svn/libmad-0.15.1b-fixes-1.patch\n--- src/libmad/configure\t2004-02-05 09:34:07.000000000 +0000\n+++ src/libmad/configure.new\t2020-06-30 21:10:28.528018931 +0000\n@@ -19083,71 +19083,7 @@\n \n if test \"$GCC\" = yes\n then\n-    if test -z \"$arch\"\n-    then\n-\tcase \"$host\" in\n-\t    i386-*)           ;;\n-\t    i?86-*)           arch=\"-march=i486\" ;;\n-\t    arm*-empeg-*)     arch=\"-march=armv4 -mtune=strongarm1100\" ;;\n-\t    armv4*-*)         arch=\"-march=armv4 -mtune=strongarm\" ;;\n-\t    powerpc-*)        ;;\n-\t    mips*-agenda-*)   arch=\"-mcpu=vr4100\" ;;\n-\t    mips*-luxsonor-*) arch=\"-mips1 -mcpu=r3000 -Wa,-m4010\" ;;\n-\tesac\n-    fi\n-\n-    case \"$optimize\" in\n-\t-O|\"-O \"*)\n-\t    optimize=\"-O\"\n-\t    optimize=\"$optimize -fforce-mem\"\n-\t    optimize=\"$optimize -fforce-addr\"\n-\t    : #x optimize=\"$optimize -finline-functions\"\n-\t    : #- optimize=\"$optimize -fstrength-reduce\"\n-\t    optimize=\"$optimize -fthread-jumps\"\n-\t    optimize=\"$optimize -fcse-follow-jumps\"\n-\t    optimize=\"$optimize -fcse-skip-blocks\"\n-\t    : #x optimize=\"$optimize -frerun-cse-after-loop\"\n-\t    : #x optimize=\"$optimize -frerun-loop-opt\"\n-\t    : #x optimize=\"$optimize -fgcse\"\n-\t    optimize=\"$optimize -fexpensive-optimizations\"\n-\t    optimize=\"$optimize -fregmove\"\n-\t    : #* optimize=\"$optimize -fdelayed-branch\"\n-\t    : #x optimize=\"$optimize -fschedule-insns\"\n-\t    optimize=\"$optimize -fschedule-insns2\"\n-\t    : #? optimize=\"$optimize -ffunction-sections\"\n-\t    : #? optimize=\"$optimize -fcaller-saves\"\n-\t    : #> optimize=\"$optimize -funroll-loops\"\n-\t    : #> optimize=\"$optimize -funroll-all-loops\"\n-\t    : #x optimize=\"$optimize -fmove-all-movables\"\n-\t    : #x optimize=\"$optimize -freduce-all-givs\"\n-\t    : #? optimize=\"$optimize -fstrict-aliasing\"\n-\t    : #* optimize=\"$optimize -fstructure-noalias\"\n-\n-\t    case \"$host\" in\n-\t\tarm*-*)\n-\t\t    optimize=\"$optimize -fstrength-reduce\"\n-\t\t    ;;\n-\t\tmips*-*)\n-\t\t    optimize=\"$optimize -fstrength-reduce\"\n-\t\t    optimize=\"$optimize -finline-functions\"\n-\t\t    ;;\n-\t\ti?86-*)\n-\t\t    optimize=\"$optimize -fstrength-reduce\"\n-\t\t    ;;\n-\t\tpowerpc-apple-*)\n-\t\t    # this triggers an internal compiler error with gcc2\n-\t\t    : #optimize=\"$optimize -fstrength-reduce\"\n-\n-\t\t    # this is really only beneficial with gcc3\n-\t\t    : #optimize=\"$optimize -finline-functions\"\n-\t\t    ;;\n-\t\t*)\n-\t\t    # this sometimes provokes bugs in gcc 2.95.2\n-\t\t    : #optimize=\"$optimize -fstrength-reduce\"\n-\t\t    ;;\n-\t    esac\n-\t    ;;\n-    esac\n+    optimize=\"-O2\"\n fi\n \n case \"$host\" in\n@@ -21497,6 +21433,7 @@\n then\n     case \"$host\" in\n \ti?86-*)     FPM=\"INTEL\"  ;;\n+\tx86_64*)    FPM=\"64BIT\"  ;;\n \tarm*-*)     FPM=\"ARM\"    ;;\n \tmips*-*)    FPM=\"MIPS\"   ;;\n \tsparc*-*)   FPM=\"SPARC\"  ;;\n"
  },
  {
    "path": "audio/paddleaudio/third_party/patches/sox.patch",
    "content": "See https://github.com/pytorch/audio/pull/1297\ndiff -ru sox/src/formats.c sox/src/formats.c\n--- sox/src/formats.c\t2014-10-26 19:55:50.000000000 -0700\n+++ sox/src/formats.c\t2021-02-22 16:01:02.833144070 -0800\n@@ -333,6 +333,10 @@\n   assert(ft);\n   if (!ft->fp)\n     return sox_false;\n-  fstat(fileno((FILE*)ft->fp), &st);\n+  int fd = fileno((FILE*)ft->fp);\n+  if (fd < 0)\n+    return sox_false;\n+  if (fstat(fd, &st) < 0)\n+    return sox_false;\n   return ((st.st_mode & S_IFMT) == S_IFREG);\n }\n"
  },
  {
    "path": "audio/paddleaudio/third_party/sox/CMakeLists.txt",
    "content": "find_package(PkgConfig REQUIRED)\n\ninclude(ExternalProject)\n\nset(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../install)\nset(ARCHIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../archives)\nset(patch_dir ${CMAKE_CURRENT_SOURCE_DIR}/../patches)\nset(COMMON_ARGS --quiet --disable-shared --enable-static --prefix=${INSTALL_DIR} --with-pic --disable-dependency-tracking --disable-debug --disable-examples --disable-doc)\n\n# To pass custom environment variables to ExternalProject_Add command,\n# we need to do `${CMAKE_COMMAND} -E env ${envs} <COMMAND>`.\n# https://stackoverflow.com/a/62437353\n# We construct the custom environment variables here\nset(envs\n  \"PKG_CONFIG_PATH=${INSTALL_DIR}/lib/pkgconfig\"\n  \"LDFLAGS=-L${INSTALL_DIR}/lib $ENV{LDFLAGS}\"\n  \"CFLAGS=-I${INSTALL_DIR}/include -fvisibility=hidden $ENV{CFLAGS}\"\n)\n\nif (BUILD_MAD)\n  ExternalProject_Add(mad\n    PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n    DOWNLOAD_DIR ${ARCHIVE_DIR}\n    URL https://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz\n    URL_HASH SHA256=bbfac3ed6bfbc2823d3775ebb931087371e142bb0e9bb1bee51a76a6e0078690\n    PATCH_COMMAND patch < ${patch_dir}/libmad.patch && cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/mad/\n    CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/mad/configure ${COMMON_ARGS}\n    DOWNLOAD_NO_PROGRESS ON\n    LOG_DOWNLOAD ON\n    LOG_UPDATE ON\n    LOG_CONFIGURE ON\n    LOG_BUILD ON\n    LOG_INSTALL ON\n    LOG_MERGED_STDOUTERR ON\n    LOG_OUTPUT_ON_FAILURE ON\n  )\nendif (BUILD_MAD)\n\nExternalProject_Add(amr\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://sourceforge.net/projects/opencore-amr/files/opencore-amr/opencore-amr-0.1.5.tar.gz\n  URL_HASH SHA256=2c006cb9d5f651bfb5e60156dbff6af3c9d35c7bbcc9015308c0aff1e14cd341\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/amr/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/amr/configure ${COMMON_ARGS}\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(lame\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz\n  URL_HASH SHA256=24346b4158e4af3bd9f2e194bb23eb473c75fb7377011523353196b19b9a23ff\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/lame/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/lame/configure ${COMMON_ARGS} --enable-nasm\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(ogg\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz\n  URL_HASH SHA256=c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/ogg/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/ogg/configure ${COMMON_ARGS}\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(flac\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DEPENDS ogg\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.2.tar.xz\n  URL_HASH SHA256=91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/flac/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/flac/configure ${COMMON_ARGS} --with-ogg --disable-cpplibs\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(vorbis\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DEPENDS ogg\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz\n  URL_HASH SHA256=6ed40e0241089a42c48604dc00e362beee00036af2d8b3f46338031c9e0351cb\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/vorbis/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/vorbis/configure ${COMMON_ARGS} --with-ogg\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(opus\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DEPENDS ogg\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://ftp.osuosl.org/pub/xiph/releases/opus/opus-1.3.1.tar.gz\n  URL_HASH SHA256=65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/opus/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opus/configure ${COMMON_ARGS} --with-ogg\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nExternalProject_Add(opusfile\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DEPENDS opus\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://ftp.osuosl.org/pub/xiph/releases/opus/opusfile-0.12.tar.gz\n  URL_HASH SHA256=118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b\n  PATCH_COMMAND cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/opusfile/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/opusfile/configure ${COMMON_ARGS} --disable-http\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\n# OpenMP is by default compiled against GNU OpenMP, which conflicts with the version of OpenMP that PyTorch uses.\n# See https://github.com/pytorch/audio/pull/1026\n# TODO: Add flags like https://github.com/suphoff/pytorch_parallel_extension_cpp/blob/master/setup.py\nset(SOX_OPTIONS\n  --disable-openmp\n  --with-amrnb\n  --with-amrwb\n  --with-flac\n  --with-lame\n  --with-oggvorbis\n  --with-opus\n  --without-alsa\n  --without-ao\n  --without-coreaudio\n  --without-oss\n  --without-id3tag\n  --without-ladspa\n  --without-magic\n  --without-png\n  --without-pulseaudio\n  --without-sndfile\n  --without-sndio\n  --without-sunaudio\n  --without-waveaudio\n  --without-wavpack\n  --without-twolame\n  )\n\nset(SOX_LIBRARIES\n  ${INSTALL_DIR}/lib/libsox.a\n  ${INSTALL_DIR}/lib/libopencore-amrnb.a\n  ${INSTALL_DIR}/lib/libopencore-amrwb.a\n  ${INSTALL_DIR}/lib/libmp3lame.a\n  ${INSTALL_DIR}/lib/libFLAC.a\n  ${INSTALL_DIR}/lib/libopusfile.a\n  ${INSTALL_DIR}/lib/libopus.a\n  ${INSTALL_DIR}/lib/libvorbisenc.a\n  ${INSTALL_DIR}/lib/libvorbisfile.a\n  ${INSTALL_DIR}/lib/libvorbis.a\n  ${INSTALL_DIR}/lib/libogg.a\n  )\n\nset(sox_depends\n  ogg flac vorbis opusfile lame amr\n  )\n\nif (BUILD_MAD)\n  list(\n    APPEND\n    SOX_OPTIONS\n    --with-mad\n    )\n  list(\n    APPEND\n    SOX_LIBRARIES\n    ${INSTALL_DIR}/lib/libmad.a\n    )\n  list(\n    APPEND\n    sox_depends\n    mad\n    )\nelse ()\n  list(\n    APPEND\n    SOX_OPTIONS\n    --without-mad\n    )  \nendif (BUILD_MAD)\n\nExternalProject_Add(sox\n  PREFIX ${CMAKE_CURRENT_BINARY_DIR}\n  DEPENDS ${sox_depends}\n  DOWNLOAD_DIR ${ARCHIVE_DIR}\n  URL https://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.bz2\n  URL_HASH SHA256=81a6956d4330e75b5827316e44ae381e6f1e8928003c6aa45896da9041ea149c\n  PATCH_COMMAND patch -p1 < ${patch_dir}/sox.patch && cp ${patch_dir}/config.guess ${patch_dir}/config.sub ${CMAKE_CURRENT_BINARY_DIR}/src/sox/\n  CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${envs} ${CMAKE_CURRENT_BINARY_DIR}/src/sox/configure ${COMMON_ARGS} ${SOX_OPTIONS}\n  BUILD_BYPRODUCTS ${SOX_LIBRARIES}\n  DOWNLOAD_NO_PROGRESS ON\n  LOG_DOWNLOAD ON\n  LOG_UPDATE ON\n  LOG_CONFIGURE ON\n  LOG_BUILD ON\n  LOG_INSTALL ON\n  LOG_MERGED_STDOUTERR ON\n  LOG_OUTPUT_ON_FAILURE ON\n)\n\nadd_library(libsox INTERFACE)\nadd_dependencies(libsox sox)\ntarget_include_directories(libsox INTERFACE ${INSTALL_DIR}/include)\ntarget_link_libraries(libsox INTERFACE ${SOX_LIBRARIES})"
  },
  {
    "path": "audio/paddleaudio/utils/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .download import decompress\nfrom .download import download_and_decompress\nfrom .download import load_state_dict_from_url\nfrom .env import DATA_HOME\nfrom .env import MODEL_HOME\nfrom .env import PPAUDIO_HOME\nfrom .env import USER_HOME\nfrom .error import ParameterError\nfrom .log import Logger\nfrom .log import logger\nfrom .numeric import depth_convert\nfrom .numeric import pcm16to32\nfrom .time import seconds_to_hms\nfrom .time import Timer\n"
  },
  {
    "path": "audio/paddleaudio/utils/download.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import Dict\nfrom typing import List\n\nfrom paddle.framework import load as load_state_dict\nfrom paddle.utils import download\n\nfrom .log import logger\n\ndownload.logger = logger\n\n__all__ = [\n    'decompress',\n    'download_and_decompress',\n    'load_state_dict_from_url',\n]\n\n\ndef decompress(file: str):\n    \"\"\"\n    Extracts all files from a compressed file.\n    \"\"\"\n    assert os.path.isfile(file), \"File: {} not exists.\".format(file)\n    download._decompress(file)\n\n\ndef download_and_decompress(archives: List[Dict[str, str]],\n                            path: str,\n                            decompress: bool=True):\n    \"\"\"\n    Download archives and decompress to specific path.\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    for archive in archives:\n        assert 'url' in archive and 'md5' in archive, \\\n            'Dictionary keys of \"url\" and \"md5\" are required in the archive, but got: {list(archive.keys())}'\n        download.get_path_from_url(\n            archive['url'], path, archive['md5'], decompress=decompress)\n\n\ndef load_state_dict_from_url(url: str, path: str, md5: str=None):\n    \"\"\"\n    Download and load a state dict from url\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    download.get_path_from_url(url, path, md5)\n    return load_state_dict(os.path.join(path, os.path.basename(url)))\n"
  },
  {
    "path": "audio/paddleaudio/utils/env.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n'''\nThis module is used to store environmental variables in PaddleAudio.\nPPAUDIO_HOME     -->  the root directory for storing PaddleAudio related data. Default to ~/.paddleaudio. Users can change the\n├                            default value through the PPAUDIO_HOME environment variable.\n├─ MODEL_HOME    -->  Store model files.\n└─ DATA_HOME     -->  Store automatically downloaded datasets.\n'''\nimport os\n\n__all__ = [\n    'USER_HOME',\n    'PPAUDIO_HOME',\n    'MODEL_HOME',\n    'DATA_HOME',\n]\n\n\ndef _get_user_home():\n    return os.path.expanduser('~')\n\n\ndef _get_ppaudio_home():\n    if 'PPAUDIO_HOME' in os.environ:\n        home_path = os.environ['PPAUDIO_HOME']\n        if os.path.exists(home_path):\n            if os.path.isdir(home_path):\n                return home_path\n            else:\n                raise RuntimeError(\n                    'The environment variable PPAUDIO_HOME {} is not a directory.'.\n                    format(home_path))\n        else:\n            return home_path\n    return os.path.join(_get_user_home(), '.paddleaudio')\n\n\ndef _get_sub_home(directory):\n    home = os.path.join(_get_ppaudio_home(), directory)\n    if not os.path.exists(home):\n        os.makedirs(home)\n    return home\n\n\nUSER_HOME = _get_user_home()\nPPAUDIO_HOME = _get_ppaudio_home()\nMODEL_HOME = _get_sub_home('models')\nDATA_HOME = _get_sub_home('datasets')\n"
  },
  {
    "path": "audio/paddleaudio/utils/error.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = ['ParameterError']\n\n\nclass ParameterError(Exception):\n    \"\"\"Exception class for Parameter checking\"\"\"\n    pass\n"
  },
  {
    "path": "audio/paddleaudio/utils/log.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport contextlib\nimport functools\nimport logging\nimport threading\nimport time\n\nimport colorlog\n\n__all__ = [\n    'Logger',\n    'logger',\n]\n\nlog_config = {\n    'DEBUG': {\n        'level': 10,\n        'color': 'purple'\n    },\n    'INFO': {\n        'level': 20,\n        'color': 'green'\n    },\n    'TRAIN': {\n        'level': 21,\n        'color': 'cyan'\n    },\n    'EVAL': {\n        'level': 22,\n        'color': 'blue'\n    },\n    'WARNING': {\n        'level': 30,\n        'color': 'yellow'\n    },\n    'ERROR': {\n        'level': 40,\n        'color': 'red'\n    },\n    'CRITICAL': {\n        'level': 50,\n        'color': 'bold_red'\n    }\n}\n\n\nclass Logger(object):\n    '''\n    Default logger in PaddleAudio\n    Args:\n        name(str) : Logger name, default is 'PaddleAudio'\n    '''\n\n    def __init__(self, name: str=None):\n        name = 'PaddleAudio' if not name else name\n        self.logger = logging.getLogger(name)\n\n        for key, conf in log_config.items():\n            logging.addLevelName(conf['level'], key)\n            self.__dict__[key] = functools.partial(self.__call__, conf['level'])\n            self.__dict__[key.lower()] = functools.partial(self.__call__,\n                                                           conf['level'])\n\n        self.format = colorlog.ColoredFormatter(\n            '%(log_color)s[%(asctime)-15s] [%(levelname)8s]%(reset)s - %(message)s',\n            log_colors={key: conf['color']\n                        for key, conf in log_config.items()})\n\n        self.handler = logging.StreamHandler()\n        self.handler.setFormatter(self.format)\n\n        self.logger.addHandler(self.handler)\n        self.logLevel = 'DEBUG'\n        self.logger.setLevel(logging.DEBUG)\n        self.logger.propagate = False\n        self._is_enable = True\n\n    def disable(self):\n        self._is_enable = False\n\n    def enable(self):\n        self._is_enable = True\n\n    @property\n    def is_enable(self) -> bool:\n        return self._is_enable\n\n    def __call__(self, log_level: str, msg: str):\n        if not self.is_enable:\n            return\n\n        self.logger.log(log_level, msg)\n\n    @contextlib.contextmanager\n    def use_terminator(self, terminator: str):\n        old_terminator = self.handler.terminator\n        self.handler.terminator = terminator\n        yield\n        self.handler.terminator = old_terminator\n\n    @contextlib.contextmanager\n    def processing(self, msg: str, interval: float=0.1):\n        '''\n        Continuously print a progress bar with rotating special effects.\n        Args:\n            msg(str): Message to be printed.\n            interval(float): Rotation interval. Default to 0.1.\n        '''\n        end = False\n\n        def _printer():\n            index = 0\n            flags = ['\\\\', '|', '/', '-']\n            while not end:\n                flag = flags[index % len(flags)]\n                with self.use_terminator('\\r'):\n                    self.info('{}: {}'.format(msg, flag))\n                time.sleep(interval)\n                index += 1\n\n        t = threading.Thread(target=_printer)\n        t.start()\n        yield\n        end = True\n\n\nlogger = Logger()\n"
  },
  {
    "path": "audio/paddleaudio/utils/numeric.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Union\n\nimport numpy as np\n\n__all__ = [\"pcm16to32\", \"depth_convert\"]\n\n\ndef pcm16to32(audio: np.ndarray) -> np.ndarray:\n    \"\"\"pcm int16 to float32\n\n    Args:\n        audio (np.ndarray): Waveform with dtype of int16.\n\n    Returns:\n        np.ndarray: Waveform with dtype of float32.\n    \"\"\"\n    if audio.dtype == np.int16:\n        audio = audio.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        audio = audio / (2**(bits - 1))\n    return audio\n\n\ndef _safe_cast(y: np.ndarray, dtype: Union[type, str]) -> np.ndarray:\n    \"\"\"Data type casting in a safe way, i.e., prevent overflow or underflow.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        dtype (Union[type, str]): Data type of waveform.\n\n    Returns:\n        np.ndarray: `y` after safe casting.\n    \"\"\"\n    if 'float' in str(y.dtype):\n        return np.clip(y, np.finfo(dtype).min,\n                       np.finfo(dtype).max).astype(dtype)\n    else:\n        return np.clip(y, np.iinfo(dtype).min,\n                       np.iinfo(dtype).max).astype(dtype)\n\n\ndef depth_convert(y: np.ndarray, dtype: Union[type, str]) -> np.ndarray:\n    \"\"\"Convert audio array to target dtype safely. \n    This function convert audio waveform to a target dtype, with addition steps of\n    preventing overflow/underflow and preserving audio range.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        dtype (Union[type, str]): Data type of waveform.\n\n    Returns:\n        np.ndarray: `y` after safe casting.\n    \"\"\"\n\n    SUPPORT_DTYPE = ['int16', 'int8', 'float32', 'float64']\n    if y.dtype not in SUPPORT_DTYPE:\n        raise ParameterError(\n            'Unsupported audio dtype, '\n            f'y.dtype is {y.dtype}, supported dtypes are {SUPPORT_DTYPE}')\n\n    if dtype not in SUPPORT_DTYPE:\n        raise ParameterError(\n            'Unsupported audio dtype, '\n            f'target dtype  is {dtype}, supported dtypes are {SUPPORT_DTYPE}')\n\n    if dtype == y.dtype:\n        return y\n\n    if dtype == 'float64' and y.dtype == 'float32':\n        return _safe_cast(y, dtype)\n    if dtype == 'float32' and y.dtype == 'float64':\n        return _safe_cast(y, dtype)\n\n    if dtype == 'int16' or dtype == 'int8':\n        if y.dtype in ['float64', 'float32']:\n            factor = np.iinfo(dtype).max\n            y = np.clip(y * factor, np.iinfo(dtype).min,\n                        np.iinfo(dtype).max).astype(dtype)\n            y = y.astype(dtype)\n        else:\n            if dtype == 'int16' and y.dtype == 'int8':\n                factor = np.iinfo('int16').max / np.iinfo('int8').max - EPS\n                y = y.astype('float32') * factor\n                y = y.astype('int16')\n\n            else:  # dtype == 'int8' and y.dtype=='int16':\n                y = y.astype('int32') * np.iinfo('int8').max / \\\n                    np.iinfo('int16').max\n                y = y.astype('int8')\n\n    if dtype in ['float32', 'float64']:\n        org_dtype = y.dtype\n        y = y.astype(dtype) / np.iinfo(org_dtype).max\n    return y\n"
  },
  {
    "path": "audio/paddleaudio/utils/sox_utils.py",
    "content": "from typing import Dict\nfrom typing import List\n\nimport paddleaudio\nfrom paddleaudio._internal import module_utils as _mod_utils\n\n\n@_mod_utils.requires_sox()\ndef set_seed(seed: int):\n    \"\"\"Set libsox's PRNG\n\n    Args:\n        seed (int): seed value. valid range is int32.\n\n    See Also:\n        http://sox.sourceforge.net/sox.html\n    \"\"\"\n    paddleaudio._paddleaudio.sox_utils_set_seed(seed)\n\n\n@_mod_utils.requires_sox()\ndef set_verbosity(verbosity: int):\n    \"\"\"Set libsox's verbosity\n\n    Args:\n        verbosity (int): Set verbosity level of libsox.\n\n            * ``1`` failure messages\n            * ``2`` warnings\n            * ``3`` details of processing\n            * ``4``-``6`` increasing levels of debug messages\n\n    See Also:\n        http://sox.sourceforge.net/sox.html\n    \"\"\"\n    paddleaudio._paddleaudio.sox_utils_set_verbosity(verbosity)\n\n\n@_mod_utils.requires_sox()\ndef set_buffer_size(buffer_size: int):\n    \"\"\"Set buffer size for sox effect chain\n\n    Args:\n        buffer_size (int): Set the size in bytes of the buffers used for processing audio.\n\n    See Also:\n        http://sox.sourceforge.net/sox.html\n    \"\"\"\n    paddleaudio._paddleaudio.sox_utils_set_buffer_size(buffer_size)\n\n\n@_mod_utils.requires_sox()\ndef set_use_threads(use_threads: bool):\n    \"\"\"Set multithread option for sox effect chain\n\n    Args:\n        use_threads (bool): When ``True``, enables ``libsox``'s parallel effects channels processing.\n            To use multithread, the underlying ``libsox`` has to be compiled with OpenMP support.\n\n    See Also:\n        http://sox.sourceforge.net/sox.html\n    \"\"\"\n    paddleaudio._paddleaudio.sox_utils_set_use_threads(use_threads)\n\n\n@_mod_utils.requires_sox()\ndef list_effects() -> Dict[str, str]:\n    \"\"\"List the available sox effect names\n\n    Returns:\n        Dict[str, str]: Mapping from ``effect name`` to ``usage``\n    \"\"\"\n    return dict(paddleaudio._paddleaudio.sox_utils_list_effects())\n\n\n@_mod_utils.requires_sox()\ndef list_read_formats() -> List[str]:\n    \"\"\"List the supported audio formats for read\n\n    Returns:\n        List[str]: List of supported audio formats\n    \"\"\"\n    return paddleaudio._paddleaudio.sox_utils_list_read_formats()\n\n\n@_mod_utils.requires_sox()\ndef list_write_formats() -> List[str]:\n    \"\"\"List the supported audio formats for write\n\n    Returns:\n        List[str]: List of supported audio formats\n    \"\"\"\n    return paddleaudio._paddleaudio.sox_utils_list_write_formats()\n\n\n@_mod_utils.requires_sox()\ndef get_buffer_size() -> int:\n    \"\"\"Get buffer size for sox effect chain\n\n    Returns:\n        int: size in bytes of buffers used for processing audio.\n    \"\"\"\n    return paddleaudio._paddleaudio.sox_utils_get_buffer_size()\n"
  },
  {
    "path": "audio/paddleaudio/utils/tensor_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Utility functions for Transformer.\"\"\"\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\n\nfrom .log import Logger\n\n__all__ = [\"pad_sequence\", \"add_sos_eos\", \"th_accuracy\", \"has_tensor\"]\n\nlogger = Logger(__name__)\n\n\ndef has_tensor(val):\n    if isinstance(val, (list, tuple)):\n        for item in val:\n            if has_tensor(item):\n                return True\n    elif isinstance(val, dict):\n        for k, v in val.items():\n            print(k)\n            if has_tensor(v):\n                return True\n    else:\n        return paddle.is_tensor(val)\n\n\ndef pad_sequence(sequences: List[paddle.Tensor],\n                 batch_first: bool=False,\n                 padding_value: float=0.0) -> paddle.Tensor:\n    r\"\"\"Pad a list of variable length Tensors with ``padding_value``\n\n    ``pad_sequence`` stacks a list of Tensors along a new dimension,\n    and pads them to equal length. For example, if the input is list of\n    sequences with size ``L x *`` and if batch_first is False, and ``T x B x *``\n    otherwise.\n\n    `B` is batch size. It is equal to the number of elements in ``sequences``.\n    `T` is length of the longest sequence.\n    `L` is length of the sequence.\n    `*` is any number of trailing dimensions, including none.\n\n    Example:\n        >>> from paddle.nn.utils.rnn import pad_sequence\n        >>> a = paddle.ones(25, 300)\n        >>> b = paddle.ones(22, 300)\n        >>> c = paddle.ones(15, 300)\n        >>> pad_sequence([a, b, c]).shape\n        paddle.Tensor([25, 3, 300])\n\n    Note:\n        This function returns a Tensor of size ``T x B x *`` or ``B x T x *``\n        where `T` is the length of the longest sequence. This function assumes\n        trailing dimensions and type of all the Tensors in sequences are same.\n\n    Args:\n        sequences (list[Tensor]): list of variable length sequences.\n        batch_first (bool, optional): output will be in ``B x T x *`` if True, or in\n            ``T x B x *`` otherwise\n        padding_value (float, optional): value for padded elements. Default: 0.\n\n    Returns:\n        Tensor of size ``T x B x *`` if :attr:`batch_first` is ``False``.\n        Tensor of size ``B x T x *`` otherwise\n    \"\"\"\n\n    # assuming trailing dimensions and type of all the Tensors\n    # in sequences are same and fetching those from sequences[0]\n    max_size = paddle.shape(sequences[0])\n    # (TODO Hui Zhang): slice not support `end==start`\n    # trailing_dims = max_size[1:]\n    trailing_dims = tuple(\n        max_size[1:].numpy().tolist()) if sequences[0].ndim >= 2 else ()\n    max_len = max([s.shape[0] for s in sequences])\n    if batch_first:\n        out_dims = (len(sequences), max_len) + trailing_dims\n    else:\n        out_dims = (max_len, len(sequences)) + trailing_dims\n    out_tensor = paddle.full(out_dims, padding_value, sequences[0].dtype)\n    for i, tensor in enumerate(sequences):\n        length = tensor.shape[0]\n        # use index notation to prevent duplicate references to the tensor\n        if batch_first:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # TODO (Hui Zhang): set_value op not support int16\n            # TODO (Hui Zhang): set_varbase 2 rank not support [0,0,...]\n            # out_tensor[i, :length, ...] = tensor\n            if length != 0:\n                out_tensor[i, :length] = tensor\n            else:\n                out_tensor[i, length] = tensor\n        else:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # out_tensor[:length, i, ...] = tensor\n            if length != 0:\n                out_tensor[:length, i] = tensor\n            else:\n                out_tensor[length, i] = tensor\n\n    return out_tensor\n\n\ndef add_sos_eos(ys_pad: paddle.Tensor, sos: int, eos: int,\n                ignore_id: int) -> Tuple[paddle.Tensor, paddle.Tensor]:\n    \"\"\"Add <sos> and <eos> labels.\n    Args:\n        ys_pad (paddle.Tensor): batch of padded target sequences (B, Lmax)\n        sos (int): index of <sos>\n        eos (int): index of <eeos>\n        ignore_id (int): index of padding\n    Returns:\n        ys_in (paddle.Tensor) : (B, Lmax + 1)\n        ys_out (paddle.Tensor) : (B, Lmax + 1)\n    Examples:\n        >>> sos_id = 10\n        >>> eos_id = 11\n        >>> ignore_id = -1\n        >>> ys_pad\n        tensor([[ 1,  2,  3,  4,  5],\n                [ 4,  5,  6, -1, -1],\n                [ 7,  8,  9, -1, -1]], dtype=paddle.int32)\n        >>> ys_in,ys_out=add_sos_eos(ys_pad, sos_id , eos_id, ignore_id)\n        >>> ys_in\n        tensor([[10,  1,  2,  3,  4,  5],\n                [10,  4,  5,  6, 11, 11],\n                [10,  7,  8,  9, 11, 11]])\n        >>> ys_out\n        tensor([[ 1,  2,  3,  4,  5, 11],\n                [ 4,  5,  6, 11, -1, -1],\n                [ 7,  8,  9, 11, -1, -1]])\n    \"\"\"\n    # TODO(Hui Zhang): using comment code,\n    #_sos = paddle.to_tensor(\n    #    [sos], dtype=paddle.long, stop_gradient=True, place=ys_pad.place)\n    #_eos = paddle.to_tensor(\n    #    [eos], dtype=paddle.long, stop_gradient=True, place=ys_pad.place)\n    #ys = [y[y != ignore_id] for y in ys_pad]  # parse padded ys\n    #ys_in = [paddle.cat([_sos, y], dim=0) for y in ys]\n    #ys_out = [paddle.cat([y, _eos], dim=0) for y in ys]\n    #return pad_sequence(ys_in, padding_value=eos), pad_sequence(ys_out, padding_value=ignore_id)\n    B = ys_pad.shape[0]\n    _sos = paddle.ones([B, 1], dtype=ys_pad.dtype) * sos\n    _eos = paddle.ones([B, 1], dtype=ys_pad.dtype) * eos\n    ys_in = paddle.cat([_sos, ys_pad], dim=1)\n    mask_pad = (ys_in == ignore_id)\n    ys_in = ys_in.masked_fill(mask_pad, eos)\n\n    ys_out = paddle.cat([ys_pad, _eos], dim=1)\n    ys_out = ys_out.masked_fill(mask_pad, eos)\n    mask_eos = (ys_out == ignore_id)\n    ys_out = ys_out.masked_fill(mask_eos, eos)\n    ys_out = ys_out.masked_fill(mask_pad, ignore_id)\n    return ys_in, ys_out\n\n\ndef th_accuracy(pad_outputs: paddle.Tensor,\n                pad_targets: paddle.Tensor,\n                ignore_label: int) -> float:\n    \"\"\"Calculate accuracy.\n    Args:\n        pad_outputs (Tensor): Prediction tensors (B * Lmax, D).\n        pad_targets (LongTensor): Target label tensors (B, Lmax, D).\n        ignore_label (int): Ignore label id.\n    Returns:\n        float: Accuracy value (0.0 - 1.0).\n    \"\"\"\n    pad_pred = pad_outputs.reshape(\n        [pad_targets.shape[0], pad_targets.shape[1],\n         pad_outputs.shape[1]]).argmax(2)\n    mask = pad_targets != ignore_label\n    #TODO(Hui Zhang): sum not support bool type\n    # numerator = paddle.sum(\n    #     pad_pred.masked_select(mask) == pad_targets.masked_select(mask))\n    numerator = (\n        pad_pred.masked_select(mask) == pad_targets.masked_select(mask))\n    numerator = paddle.sum(numerator.type_as(pad_targets))\n    #TODO(Hui Zhang): sum not support bool type\n    # denominator = paddle.sum(mask)\n    denominator = paddle.sum(mask.type_as(pad_targets))\n    return float(numerator) / float(denominator)\n"
  },
  {
    "path": "audio/paddleaudio/utils/time.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport time\n\n__all__ = [\n    'Timer',\n    'seconds_to_hms',\n]\n\n\nclass Timer(object):\n    '''Calculate running speed and estimated time of arrival(ETA)'''\n\n    def __init__(self, total_step: int):\n        self.total_step = total_step\n        self.last_start_step = 0\n        self.current_step = 0\n        self._is_running = True\n\n    def start(self):\n        self.last_time = time.time()\n        self.start_time = time.time()\n\n    def stop(self):\n        self._is_running = False\n        self.end_time = time.time()\n\n    def count(self) -> int:\n        if not self.current_step >= self.total_step:\n            self.current_step += 1\n        return self.current_step\n\n    @property\n    def timing(self) -> float:\n        run_steps = self.current_step - self.last_start_step\n        self.last_start_step = self.current_step\n        time_used = time.time() - self.last_time\n        self.last_time = time.time()\n        return run_steps / time_used\n\n    @property\n    def is_running(self) -> bool:\n        return self._is_running\n\n    @property\n    def eta(self) -> str:\n        if not self.is_running:\n            return '00:00:00'\n        scale = self.total_step / self.current_step\n        remaining_time = (time.time() - self.start_time) * scale\n        return seconds_to_hms(remaining_time)\n\n\ndef seconds_to_hms(seconds: int) -> str:\n    '''Convert the number of seconds to hh:mm:ss'''\n    h = math.floor(seconds / 3600)\n    m = math.floor((seconds - h * 3600) / 60)\n    s = int(seconds - h * 3600 - m * 60)\n    hms_str = '{:0>2}:{:0>2}:{:0>2}'.format(h, m, s)\n    return hms_str\n"
  },
  {
    "path": "audio/setup.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport contextlib\nimport inspect\nimport io\nimport os\nimport platform\nimport subprocess as sp\nimport sys\nfrom pathlib import Path\nfrom typing import List\nfrom typing import Tuple\nfrom typing import Union\n\nimport distutils.command.clean\nfrom setuptools import Command\nfrom setuptools import find_packages\nfrom setuptools import setup\nfrom setuptools.command.develop import develop\nfrom setuptools.command.test import test\n\nfrom tools import setup_helpers\n\nROOT_DIR = Path(__file__).parent.resolve()\n\nVERSION = '1.2.0'\nCOMMITID = 'none'\n\nbase = [\n    # paddleaudio align with librosa==0.8.1, which need numpy==1.23.x\n    \"librosa==0.8.1\",\n    \"numpy==1.23.5\",\n    \"kaldiio\",\n    \"pathos\",\n    \"pybind11\",\n    \"parameterized\",\n]\n\nrequirements = {\n    \"install\": base,\n    \"develop\": [\n        \"sox\",\n        \"soxbindings\",\n        \"pre-commit\",\n    ],\n}\n\n\ndef check_call(cmd: str, shell=False, executable=None):\n    try:\n        sp.check_call(\n            cmd.split(),\n            shell=shell,\n            executable=\"/bin/bash\" if shell else executable)\n    except sp.CalledProcessError as e:\n        print(\n            f\"{__file__}:{inspect.currentframe().f_lineno}: CMD: {cmd}, Error:\",\n            e.output,\n            file=sys.stderr)\n        raise e\n\n\ndef check_output(cmd: Union[str, List[str], Tuple[str]], shell=False):\n    try:\n\n        if isinstance(cmd, (list, tuple)):\n            cmds = cmd\n        else:\n            cmds = cmd.split()\n        out_bytes = sp.check_output(cmds)\n\n    except sp.CalledProcessError as e:\n        out_bytes = e.output  # Output generated before error\n        code = e.returncode  # Return code\n        print(\n            f\"{__file__}:{inspect.currentframe().f_lineno}: CMD: {cmd}, Error:\",\n            out_bytes,\n            file=sys.stderr)\n    return out_bytes.strip().decode('utf8')\n\n\ndef _run_cmd(cmd):\n    try:\n        return subprocess.check_output(\n            cmd, cwd=ROOT_DIR,\n            stderr=subprocess.DEVNULL).decode(\"ascii\").strip()\n    except Exception:\n        return None\n\n\n@contextlib.contextmanager\ndef pushd(new_dir):\n    old_dir = os.getcwd()\n    os.chdir(new_dir)\n    print(new_dir)\n    yield\n    os.chdir(old_dir)\n    print(old_dir)\n\n\ndef read(*names, **kwargs):\n    with io.open(\n            os.path.join(os.path.dirname(__file__), *names),\n            encoding=kwargs.get(\"encoding\", \"utf8\")) as fp:\n        return fp.read()\n\n\ndef _remove(files: str):\n    for f in files:\n        f.unlink()\n\n\n################################# Install ##################################\n\n\ndef _post_install(install_lib_dir):\n    pass\n\n\nclass DevelopCommand(develop):\n    def run(self):\n        develop.run(self)\n        # must after develop.run, or pkg install by shell will not see\n        self.execute(_post_install, (self.install_lib, ), msg=\"Post Install...\")\n\n\nclass TestCommand(test):\n    def finalize_options(self):\n        test.finalize_options(self)\n        self.test_args = []\n        self.test_suite = True\n\n    def run_tests(self):\n        # Run nose ensuring that argv simulates running nosetests directly\n        import nose\n        nose.run_exit(argv=['nosetests', '-w', 'tests'])\n\n    def run_benchmark(self):\n        for benchmark_item in glob.glob('tests/benchmark/*py'):\n            os.system(f'pytest {benchmark_item}')\n\n\n# cmd: python setup.py upload\nclass UploadCommand(Command):\n    description = \"Build and publish the package.\"\n    user_options = []\n\n    def initialize_options(self):\n        pass\n\n    def finalize_options(self):\n        pass\n\n    def run(self):\n        try:\n            print(\"Removing previous dist/ ...\")\n            shutil.rmtree(str(ROOT_DIR / \"dist\"))\n        except OSError:\n            pass\n        print(\"Building source distribution...\")\n        sp.check_call([sys.executable, \"setup.py\", \"sdist\"])\n        print(\"Uploading package to PyPi...\")\n        sp.check_call([\"twine\", \"upload\", \"dist/*\"])\n        sys.exit()\n\n\n################################# Version ##################################\ndef _get_version(sha):\n    version = VERSION\n    if os.getenv(\"BUILD_VERSION\"):\n        version = os.getenv(\"BUILD_VERSION\")\n    elif sha is not None:\n        version += \"+\" + sha[:7]\n    return version\n\n\ndef _make_version_file(version, sha):\n    sha = \"Unknown\" if sha is None else sha\n    version_path = ROOT_DIR / \"paddleaudio\" / \"__init__.py\"\n    with open(version_path, \"a\") as f:\n        f.write(f\"__version__ = '{version}'\\n\")\n\n\ndef _rm_version():\n    file_ = ROOT_DIR / \"paddleaudio\" / \"__init__.py\"\n    with open(file_, \"r\") as f:\n        lines = f.readlines()\n    with open(file_, \"w\") as f:\n        for line in lines:\n            if \"__version__\" not in line:\n                f.write(line)\n\n\n################################# Steup ##################################\nclass clean(distutils.command.clean.clean):\n    def run(self):\n        # Run default behavior first\n        distutils.command.clean.clean.run(self)\n\n        # Remove paddleaudio extension\n        for path in (ROOT_DIR / \"paddleaudio\").glob(\"**/*.so\"):\n            print(f\"removing '{path}'\")\n            path.unlink()\n        # Remove build directory\n        build_dirs = [\n            ROOT_DIR / \"build\",\n        ]\n        for path in build_dirs:\n            if path.exists():\n                print(f\"removing '{path}' (and everything under it)\")\n                shutil.rmtree(str(path), ignore_errors=True)\n\n\ndef main():\n\n    sha = _run_cmd([\"git\", \"rev-parse\", \"HEAD\"])  # commit id\n    branch = _run_cmd([\"git\", \"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n    tag = _run_cmd([\"git\", \"describe\", \"--tags\", \"--exact-match\", \"@\"])\n    print(\"-- Git branch:\", branch)\n    print(\"-- Git SHA:\", sha)\n    print(\"-- Git tag:\", tag)\n    version = _get_version(sha)\n    print(\"-- Building version\", version)\n    _rm_version()\n\n    _make_version_file(version, sha)\n    lib_package_data = {}\n    if platform.system() != 'Windows' and platform.system() != 'Linux':\n        lib_package_data = {'paddleaudio': ['lib/libgcc_s.1.1.dylib']}\n\n    #if platform.system() == 'Linux':\n    #    lib_package_data = {'paddleaudio': ['lib/lib*']}\n\n    setup_info = dict(\n        # Metadata\n        name='paddleaudio',\n        version=VERSION,\n        author='PaddlePaddle Speech and Language Team',\n        author_email='paddlesl@baidu.com',\n        url='https://github.com/PaddlePaddle/PaddleSpeech/audio',\n        license='Apache 2.0',\n        description='Speech audio tools based on Paddlepaddle',\n        keywords=[\n            \"audio process\"\n            \"paddlepaddle\",\n        ],\n        python_requires='>=3.7',\n        install_requires=requirements[\"install\"],\n        extras_require={\n            'develop': requirements[\"develop\"],\n            #'test': [\"nose\", \"torchaudio==0.10.2\", \"pytest-benchmark\", \"librosa=0.8.1\", \"parameterized\", \"paddlepaddle\"],\n        },\n        cmdclass={\n            \"build_ext\": setup_helpers.CMakeBuild,\n            'develop': DevelopCommand,\n            'test': TestCommand,\n            'upload': UploadCommand,\n            \"clean\": clean,\n        },\n\n        # Package info\n        packages=find_packages(include=['paddleaudio*']),\n        package_data=lib_package_data,\n        ext_modules=setup_helpers.get_ext_modules(),\n        zip_safe=True,\n        classifiers=[\n            'Development Status :: 5 - Production/Stable',\n            'Intended Audience :: Developers',\n            'Intended Audience :: Science/Research',\n            'Topic :: Scientific/Engineering :: Artificial Intelligence',\n            'License :: OSI Approved :: Apache Software License',\n            'Programming Language :: Python',\n            'Programming Language :: Python :: 3',\n            'Programming Language :: Python :: 3.6',\n            'Programming Language :: Python :: 3.7',\n            'Programming Language :: Python :: 3.8',\n            'Programming Language :: Python :: 3.9',\n            'Programming Language :: Python :: 3.10',\n        ], )\n\n    setup(**setup_info)\n    _rm_version()\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "audio/tests/backends/base.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport unittest\nimport urllib.request\n\nmono_channel_wav = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\nmulti_channels_wav = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/cat.wav'\n\n\nclass BackendTest(unittest.TestCase):\n    def setUp(self):\n        self.initWavInput()\n\n    def initWavInput(self):\n        self.files = []\n        for url in [mono_channel_wav, multi_channels_wav]:\n            if not os.path.isfile(os.path.basename(url)):\n                urllib.request.urlretrieve(url, os.path.basename(url))\n            self.files.append(os.path.basename(url))\n\n    def initParams(self):\n        raise NotImplementedError\n"
  },
  {
    "path": "audio/tests/backends/common.py",
    "content": "\ndef get_encoding(ext, dtype):\n    exts = {\n        \"mp3\",\n        \"flac\",\n        \"vorbis\",\n    }\n    encodings = {\n        \"float32\": \"PCM_F\",\n        \"int32\": \"PCM_S\",\n        \"int16\": \"PCM_S\",\n        \"uint8\": \"PCM_U\",\n    }\n    return ext.upper() if ext in exts else encodings[dtype]\n\n\ndef get_bit_depth(dtype):\n    bit_depths = {\n        \"float32\": 32,\n        \"int32\": 32,\n        \"int16\": 16,\n        \"uint8\": 8,\n    }\n    return bit_depths[dtype]\n\ndef get_bits_per_sample(ext, dtype):\n    bits_per_samples = {\n        \"flac\": 24,\n        \"mp3\": 0,\n        \"vorbis\": 0,\n    }\n    return bits_per_samples.get(ext, get_bit_depth(dtype))\n"
  },
  {
    "path": "audio/tests/backends/soundfile/base.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport unittest\nimport urllib.request\n\nmono_channel_wav = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\nmulti_channels_wav = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/cat.wav'\n\n\nclass BackendTest(unittest.TestCase):\n    def setUp(self):\n        self.initWavInput()\n\n    def initWavInput(self):\n        self.files = []\n        for url in [mono_channel_wav, multi_channels_wav]:\n            if not os.path.isfile(os.path.basename(url)):\n                urllib.request.urlretrieve(url, os.path.basename(url))\n            self.files.append(os.path.basename(url))\n\n    def initParams(self):\n        raise NotImplementedError\n"
  },
  {
    "path": "audio/tests/backends/soundfile/common.py",
    "content": "import itertools\nfrom unittest import skipIf\n\nfrom paddleaudio._internal.module_utils import is_module_available\nfrom parameterized import parameterized\n\n\ndef name_func(func, _, params):\n    return f'{func.__name__}_{\"_\".join(str(arg) for arg in params.args)}'\n\n\ndef dtype2subtype(dtype):\n    return {\n        \"float64\": \"DOUBLE\",\n        \"float32\": \"FLOAT\",\n        \"int32\": \"PCM_32\",\n        \"int16\": \"PCM_16\",\n        \"uint8\": \"PCM_U8\",\n        \"int8\": \"PCM_S8\",\n    }[dtype]\n\n\ndef skipIfFormatNotSupported(fmt):\n    fmts = []\n    if is_module_available(\"soundfile\"):\n        import soundfile\n\n        fmts = soundfile.available_formats()\n        return skipIf(fmt not in fmts, f'\"{fmt}\" is not supported by soundfile')\n    return skipIf(True, '\"soundfile\" not available.')\n\n\ndef parameterize(*params):\n    return parameterized.expand(\n        list(itertools.product(*params)), name_func=name_func)\n\n\ndef fetch_wav_subtype(dtype, encoding, bits_per_sample):\n    subtype = {\n        (None, None): dtype2subtype(dtype),\n        (None, 8): \"PCM_U8\",\n        (\"PCM_U\", None): \"PCM_U8\",\n        (\"PCM_U\", 8): \"PCM_U8\",\n        (\"PCM_S\", None): \"PCM_32\",\n        (\"PCM_S\", 16): \"PCM_16\",\n        (\"PCM_S\", 32): \"PCM_32\",\n        (\"PCM_F\", None): \"FLOAT\",\n        (\"PCM_F\", 32): \"FLOAT\",\n        (\"PCM_F\", 64): \"DOUBLE\",\n        (\"ULAW\", None): \"ULAW\",\n        (\"ULAW\", 8): \"ULAW\",\n        (\"ALAW\", None): \"ALAW\",\n        (\"ALAW\", 8): \"ALAW\",\n    }.get((encoding, bits_per_sample))\n    if subtype:\n        return subtype\n    raise ValueError(f\"wav does not support ({encoding}, {bits_per_sample}).\")\n\ndef get_encoding(ext, dtype):\n    exts = {\n        \"mp3\",\n        \"flac\",\n        \"vorbis\",\n    }\n    encodings = {\n        \"float32\": \"PCM_F\",\n        \"int32\": \"PCM_S\",\n        \"int16\": \"PCM_S\",\n        \"uint8\": \"PCM_U\",\n    }\n    return ext.upper() if ext in exts else encodings[dtype]\n\n\ndef get_bit_depth(dtype):\n    bit_depths = {\n        \"float32\": 32,\n        \"int32\": 32,\n        \"int16\": 16,\n        \"uint8\": 8,\n    }\n    return bit_depths[dtype]\n\ndef get_bits_per_sample(ext, dtype):\n    bits_per_samples = {\n        \"flac\": 24,\n        \"mp3\": 0,\n        \"vorbis\": 0,\n    }\n    return bits_per_samples.get(ext, get_bit_depth(dtype))\n"
  },
  {
    "path": "audio/tests/backends/soundfile/info_test.py",
    "content": "#this code is from: https://github.com/pytorch/audio/blob/main/test/torchaudio_unittest/backend/soundfile/info_test.py\nimport tarfile\nimport unittest\nimport warnings\nfrom unittest.mock import patch\n\nimport paddle\nimport soundfile\nfrom common import get_bits_per_sample\nfrom common import get_encoding\nfrom common import parameterize\nfrom common import skipIfFormatNotSupported\nfrom common_utils import get_wav_data\nfrom common_utils import nested_params\nfrom common_utils import save_wav\nfrom common_utils import TempDirMixin\nfrom paddleaudio.backends import soundfile_backend\n\n\nclass TestInfo(TempDirMixin, unittest.TestCase):\n    @parameterize(\n        [\"float32\", \"int32\"],\n        [8000, 16000],\n        [1, 2], )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.info` can check wav file correctly\"\"\"\n        duration = 1\n        path = self.get_temp_path(\"data.wav\")\n        data = get_wav_data(\n            dtype,\n            num_channels,\n            normalize=False,\n            num_frames=duration * sample_rate)\n        save_wav(path, data, sample_rate)\n        info = soundfile_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == get_bits_per_sample(\"wav\", dtype)\n        assert info.encoding == get_encoding(\"wav\", dtype)\n\n    @parameterize([8000, 16000], [1, 2])\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_flac(self, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.info` can check flac file correctly\"\"\"\n        duration = 1\n        num_frames = sample_rate * duration\n        #data = torch.randn(num_frames, num_channels).numpy()\n        data = paddle.randn(shape=[num_frames, num_channels]).numpy()\n\n        path = self.get_temp_path(\"data.flac\")\n        soundfile.write(path, data, sample_rate)\n\n        info = soundfile_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == num_frames\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == 16\n        assert info.encoding == \"FLAC\"\n\n    #@parameterize([8000, 16000], [1, 2])\n    #@skipIfFormatNotSupported(\"OGG\")\n    #def test_ogg(self, sample_rate, num_channels):\n    #\"\"\"`soundfile_backend.info` can check ogg file correctly\"\"\"\n    #duration = 1\n    #num_frames = sample_rate * duration\n    ##data = torch.randn(num_frames, num_channels).numpy()\n    #data = paddle.randn(shape=[num_frames, num_channels]).numpy()\n    #print(len(data))\n    #path = self.get_temp_path(\"data.ogg\")\n    #soundfile.write(path, data, sample_rate)\n\n    #info = soundfile_backend.info(path)\n    #print(info)\n    #assert info.sample_rate == sample_rate\n    #print(\"info\")\n    #print(info.num_frames)\n    #print(\"jiji\")\n    #print(sample_rate*duration)\n    ##assert info.num_frames == sample_rate * duration\n    #assert info.num_channels == num_channels\n    #assert info.bits_per_sample == 0\n    #assert info.encoding == \"VORBIS\"\n\n    @nested_params(\n        [8000, 16000],\n        [1, 2],\n        [(\"PCM_24\", 24), (\"PCM_32\", 32)], )\n    @skipIfFormatNotSupported(\"NIST\")\n    def test_sphere(self, sample_rate, num_channels, subtype_and_bit_depth):\n        \"\"\"`soundfile_backend.info` can check sph file correctly\"\"\"\n        duration = 1\n        num_frames = sample_rate * duration\n        #data = torch.randn(num_frames, num_channels).numpy()\n        data = paddle.randn(shape=[num_frames, num_channels]).numpy()\n        path = self.get_temp_path(\"data.nist\")\n        subtype, bits_per_sample = subtype_and_bit_depth\n        soundfile.write(path, data, sample_rate, subtype=subtype)\n\n        info = soundfile_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == bits_per_sample\n        assert info.encoding == \"PCM_S\"\n\n    def test_unknown_subtype_warning(self):\n        \"\"\"soundfile_backend.info issues a warning when the subtype is unknown\n\n        This will happen if a new subtype is supported in SoundFile: the _SUBTYPE_TO_BITS_PER_SAMPLE\n        dict should be updated.\n        \"\"\"\n\n        def _mock_info_func(_):\n            class MockSoundFileInfo:\n                samplerate = 8000\n                frames = 356\n                channels = 2\n                subtype = \"UNSEEN_SUBTYPE\"\n                format = \"UNKNOWN\"\n\n            return MockSoundFileInfo()\n\n        with patch(\"soundfile.info\", _mock_info_func):\n            with warnings.catch_warnings(record=True) as w:\n                info = soundfile_backend.info(\"foo\")\n                assert len(w) == 1\n                assert \"UNSEEN_SUBTYPE subtype is unknown to PaddleAudio\" in str(\n                    w[-1].message)\n                assert info.bits_per_sample == 0\n\n\nclass TestFileObject(TempDirMixin, unittest.TestCase):\n    def _test_fileobj(self, ext, subtype, bits_per_sample):\n        \"\"\"Query audio via file-like object works\"\"\"\n        duration = 2\n        sample_rate = 16000\n        num_channels = 2\n        num_frames = sample_rate * duration\n        path = self.get_temp_path(f\"test.{ext}\")\n\n        #data = torch.randn(num_frames, num_channels).numpy()\n        data = paddle.randn(shape=[num_frames, num_channels]).numpy()\n        soundfile.write(path, data, sample_rate, subtype=subtype)\n\n        with open(path, \"rb\") as fileobj:\n            info = soundfile_backend.info(fileobj)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == num_frames\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == bits_per_sample\n        assert info.encoding == \"FLAC\" if ext == \"flac\" else \"PCM_S\"\n\n    def test_fileobj_wav(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_fileobj(\"wav\", \"PCM_16\", 16)\n\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_fileobj_flac(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_fileobj(\"flac\", \"PCM_16\", 16)\n\n    def _test_tarobj(self, ext, subtype, bits_per_sample):\n        \"\"\"Query compressed audio via file-like object works\"\"\"\n        duration = 2\n        sample_rate = 16000\n        num_channels = 2\n        num_frames = sample_rate * duration\n        audio_file = f\"test.{ext}\"\n        audio_path = self.get_temp_path(audio_file)\n        archive_path = self.get_temp_path(\"archive.tar.gz\")\n\n        #data = torch.randn(num_frames, num_channels).numpy()\n        data = paddle.randn(shape=[num_frames, num_channels]).numpy()\n        soundfile.write(audio_path, data, sample_rate, subtype=subtype)\n\n        with tarfile.TarFile(archive_path, \"w\") as tarobj:\n            tarobj.add(audio_path, arcname=audio_file)\n        with tarfile.TarFile(archive_path, \"r\") as tarobj:\n            fileobj = tarobj.extractfile(audio_file)\n            info = soundfile_backend.info(fileobj)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == num_frames\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == bits_per_sample\n        assert info.encoding == \"FLAC\" if ext == \"flac\" else \"PCM_S\"\n\n    def test_tarobj_wav(self):\n        \"\"\"Query compressed audio via file-like object works\"\"\"\n        self._test_tarobj(\"wav\", \"PCM_16\", 16)\n\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_tarobj_flac(self):\n        \"\"\"Query compressed audio via file-like object works\"\"\"\n        self._test_tarobj(\"flac\", \"PCM_16\", 16)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/soundfile/load_test.py",
    "content": "#this code is from: https://github.com/pytorch/audio/blob/main/test/torchaudio_unittest/backend/soundfile/load_test.py\nimport os\nimport tarfile\nimport unittest\nfrom unittest.mock import patch\n\nimport numpy as np\nimport paddle\nimport soundfile\nfrom common import dtype2subtype\nfrom common import parameterize\nfrom common import skipIfFormatNotSupported\nfrom common_utils import get_wav_data\nfrom common_utils import load_wav\nfrom common_utils import normalize_wav\nfrom common_utils import save_wav\nfrom common_utils import TempDirMixin\nfrom paddleaudio.backends import soundfile_backend\nfrom parameterized import parameterized\n\n\ndef _get_mock_path(\n        ext: str,\n        dtype: str,\n        sample_rate: int,\n        num_channels: int,\n        num_frames: int, ):\n    return f\"{dtype}_{sample_rate}_{num_channels}_{num_frames}.{ext}\"\n\n\ndef _get_mock_params(path: str):\n    filename, ext = path.split(\".\")\n    parts = filename.split(\"_\")\n    return {\n        \"ext\": ext,\n        \"dtype\": parts[0],\n        \"sample_rate\": int(parts[1]),\n        \"num_channels\": int(parts[2]),\n        \"num_frames\": int(parts[3]),\n    }\n\n\nclass SoundFileMock:\n    def __init__(self, path, mode):\n        assert mode == \"r\"\n        self.path = path\n        self._params = _get_mock_params(path)\n        self._start = None\n\n    @property\n    def samplerate(self):\n        return self._params[\"sample_rate\"]\n\n    @property\n    def format(self):\n        if self._params[\"ext\"] == \"wav\":\n            return \"WAV\"\n        if self._params[\"ext\"] == \"flac\":\n            return \"FLAC\"\n        if self._params[\"ext\"] == \"ogg\":\n            return \"OGG\"\n        if self._params[\"ext\"] in [\"sph\", \"nis\", \"nist\"]:\n            return \"NIST\"\n\n    @property\n    def subtype(self):\n        if self._params[\"ext\"] == \"ogg\":\n            return \"VORBIS\"\n        return dtype2subtype(self._params[\"dtype\"])\n\n    def _prepare_read(self, start, stop, frames):\n        assert stop is None\n        self._start = start\n        return frames\n\n    def read(self, frames, dtype, always_2d):\n        assert always_2d\n        data = get_wav_data(\n            dtype,\n            self._params[\"num_channels\"],\n            normalize=False,\n            num_frames=self._params[\"num_frames\"],\n            channels_first=False, ).numpy()\n        return data[self._start:self._start + frames]\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args, **kwargs):\n        pass\n\n\nclass MockedLoadTest(unittest.TestCase):\n    def assert_dtype(self, ext, dtype, sample_rate, num_channels, normalize,\n                     channels_first):\n        \"\"\"When format is WAV or NIST, normalize=False will return the native dtype Tensor, otherwise float32\"\"\"\n        num_frames = 3 * sample_rate\n        path = _get_mock_path(ext, dtype, sample_rate, num_channels, num_frames)\n        expected_dtype = paddle.float32 if normalize or ext not in [\n            \"wav\", \"nist\"\n        ] else getattr(paddle, dtype)\n        with patch(\"soundfile.SoundFile\", SoundFileMock):\n            found, sr = soundfile_backend.load(\n                path, normalize=normalize, channels_first=channels_first)\n            assert found.dtype == expected_dtype\n            assert sample_rate == sr\n\n    @parameterize(\n        [\"int32\", \"float32\", \"float64\"],\n        [8000, 16000],\n        [1, 2],\n        [True, False],\n        [True, False], )\n    def test_wav(self, dtype, sample_rate, num_channels, normalize,\n                 channels_first):\n        \"\"\"Returns native dtype when normalize=False else float32\"\"\"\n        self.assert_dtype(\"wav\", dtype, sample_rate, num_channels, normalize,\n                          channels_first)\n\n    @parameterize(\n        [\"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [True, False],\n        [True, False], )\n    def test_sphere(self, dtype, sample_rate, num_channels, normalize,\n                    channels_first):\n        \"\"\"Returns float32 always\"\"\"\n        self.assert_dtype(\"sph\", dtype, sample_rate, num_channels, normalize,\n                          channels_first)\n\n    @parameterize([8000, 16000], [1, 2], [True, False], [True, False])\n    def test_ogg(self, sample_rate, num_channels, normalize, channels_first):\n        \"\"\"Returns float32 always\"\"\"\n        self.assert_dtype(\"ogg\", \"int16\", sample_rate, num_channels, normalize,\n                          channels_first)\n\n    @parameterize([8000, 16000], [1, 2], [True, False], [True, False])\n    def test_flac(self, sample_rate, num_channels, normalize, channels_first):\n        \"\"\"`soundfile_backend.load` can load ogg format.\"\"\"\n        self.assert_dtype(\"flac\", \"int16\", sample_rate, num_channels, normalize,\n                          channels_first)\n\n\nclass LoadTestBase(TempDirMixin, unittest.TestCase):\n    def assert_wav(\n            self,\n            dtype,\n            sample_rate,\n            num_channels,\n            normalize,\n            channels_first=True,\n            duration=1, ):\n        \"\"\"`soundfile_backend.load` can load wav format correctly.\n\n        Wav data loaded with soundfile backend should match those with scipy\n        \"\"\"\n        path = self.get_temp_path(\"reference.wav\")\n        num_frames = duration * sample_rate\n        data = get_wav_data(\n            dtype,\n            num_channels,\n            normalize=normalize,\n            num_frames=num_frames,\n            channels_first=channels_first, )\n        save_wav(path, data, sample_rate, channels_first=channels_first)\n        expected = load_wav(\n            path, normalize=normalize, channels_first=channels_first)[0]\n        data, sr = soundfile_backend.load(\n            path, normalize=normalize, channels_first=channels_first)\n        assert sr == sample_rate\n        np.testing.assert_array_almost_equal(data.numpy(), expected.numpy())\n\n    def assert_sphere(\n            self,\n            dtype,\n            sample_rate,\n            num_channels,\n            channels_first=True,\n            duration=1, ):\n        \"\"\"`soundfile_backend.load` can load SPHERE format correctly.\"\"\"\n        path = self.get_temp_path(\"reference.sph\")\n        num_frames = duration * sample_rate\n        raw = get_wav_data(\n            dtype,\n            num_channels,\n            num_frames=num_frames,\n            normalize=False,\n            channels_first=False, )\n        soundfile.write(\n            path, raw, sample_rate, subtype=dtype2subtype(dtype), format=\"NIST\")\n        expected = normalize_wav(raw.t() if channels_first else raw)\n        data, sr = soundfile_backend.load(path, channels_first=channels_first)\n        assert sr == sample_rate\n        #self.assertEqual(data, expected, atol=1e-4, rtol=1e-8)\n        np.testing.assert_array_almost_equal(data.numpy(), expected.numpy())\n\n    def assert_flac(\n            self,\n            dtype,\n            sample_rate,\n            num_channels,\n            channels_first=True,\n            duration=1, ):\n        \"\"\"`soundfile_backend.load` can load FLAC format correctly.\"\"\"\n        path = self.get_temp_path(\"reference.flac\")\n        num_frames = duration * sample_rate\n        raw = get_wav_data(\n            dtype,\n            num_channels,\n            num_frames=num_frames,\n            normalize=False,\n            channels_first=False, )\n        soundfile.write(path, raw, sample_rate)\n        expected = normalize_wav(raw.t() if channels_first else raw)\n        data, sr = soundfile_backend.load(path, channels_first=channels_first)\n        assert sr == sample_rate\n        #self.assertEqual(data, expected, atol=1e-4, rtol=1e-8)\n        np.testing.assert_array_almost_equal(data.numpy(), expected.numpy())\n\n\nclass TestLoad(LoadTestBase):\n    \"\"\"Test the correctness of `soundfile_backend.load` for various formats\"\"\"\n\n    @parameterize(\n        [\"float32\", \"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [False, True],\n        [False, True], )\n    def test_wav(self, dtype, sample_rate, num_channels, normalize,\n                 channels_first):\n        \"\"\"`soundfile_backend.load` can load wav format correctly.\"\"\"\n        self.assert_wav(dtype, sample_rate, num_channels, normalize,\n                        channels_first)\n\n    @parameterize(\n        [\"int32\"],\n        [16000],\n        [2],\n        [False], )\n    def test_wav_large(self, dtype, sample_rate, num_channels, normalize):\n        \"\"\"`soundfile_backend.load` can load large wav file correctly.\"\"\"\n        two_hours = 2 * 60 * 60\n        self.assert_wav(\n            dtype, sample_rate, num_channels, normalize, duration=two_hours)\n\n    @parameterize([\"float32\", \"int32\"], [4, 8, 16, 32], [False, True])\n    def test_multiple_channels(self, dtype, num_channels, channels_first):\n        \"\"\"`soundfile_backend.load` can load wav file with more than 2 channels.\"\"\"\n        sample_rate = 8000\n        normalize = False\n        self.assert_wav(dtype, sample_rate, num_channels, normalize,\n                        channels_first)\n\n    #@parameterize([\"int32\"], [8000, 16000], [1, 2], [False, True])\n    #@skipIfFormatNotSupported(\"NIST\")\n    #def test_sphere(self, dtype, sample_rate, num_channels, channels_first):\n    #\"\"\"`soundfile_backend.load` can load sphere format correctly.\"\"\"\n    #self.assert_sphere(dtype, sample_rate, num_channels, channels_first)\n\n    #@parameterize([\"int32\"], [8000, 16000], [1, 2], [False, True])\n    #@skipIfFormatNotSupported(\"FLAC\")\n    #def test_flac(self, dtype, sample_rate, num_channels, channels_first):\n    #\"\"\"`soundfile_backend.load` can load flac format correctly.\"\"\"\n    #self.assert_flac(dtype, sample_rate, num_channels, channels_first)\n\n\nclass TestLoadFormat(TempDirMixin, unittest.TestCase):\n    \"\"\"Given `format` parameter, `so.load` can load files without extension\"\"\"\n\n    original = None\n    path = None\n\n    def _make_file(self, format_):\n        sample_rate = 8000\n        path_with_ext = self.get_temp_path(f\"test.{format_}\")\n        data = get_wav_data(\"float32\", num_channels=2).numpy().T\n        soundfile.write(path_with_ext, data, sample_rate)\n        expected = soundfile.read(path_with_ext, dtype=\"float32\")[0].T\n        path = os.path.splitext(path_with_ext)[0]\n        os.rename(path_with_ext, path)\n        return path, expected\n\n    def _test_format(self, format_):\n        \"\"\"Providing format allows to read file without extension\"\"\"\n        path, expected = self._make_file(format_)\n        found, _ = soundfile_backend.load(path)\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(found, expected)\n\n    @parameterized.expand([\n        (\"WAV\", ),\n        (\"wav\", ),\n    ])\n    def test_wav(self, format_):\n        self._test_format(format_)\n\n    @parameterized.expand([\n        (\"FLAC\", ),\n        (\"flac\", ),\n    ])\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_flac(self, format_):\n        self._test_format(format_)\n\n\nclass TestFileObject(TempDirMixin, unittest.TestCase):\n    def _test_fileobj(self, ext):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        sample_rate = 16000\n        path = self.get_temp_path(f\"test.{ext}\")\n\n        data = get_wav_data(\"float32\", num_channels=2).numpy().T\n        soundfile.write(path, data, sample_rate)\n        expected = soundfile.read(path, dtype=\"float32\")[0].T\n\n        with open(path, \"rb\") as fileobj:\n            found, sr = soundfile_backend.load(fileobj)\n        assert sr == sample_rate\n        #self.assertEqual(expected, found)\n        np.testing.assert_array_almost_equal(found, expected)\n\n    def test_fileobj_wav(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_fileobj(\"wav\")\n\n    def test_fileobj_flac(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_fileobj(\"flac\")\n\n    def _test_tarfile(self, ext):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        sample_rate = 16000\n        audio_file = f\"test.{ext}\"\n        audio_path = self.get_temp_path(audio_file)\n        archive_path = self.get_temp_path(\"archive.tar.gz\")\n\n        data = get_wav_data(\"float32\", num_channels=2).numpy().T\n        soundfile.write(audio_path, data, sample_rate)\n        expected = soundfile.read(audio_path, dtype=\"float32\")[0].T\n\n        with tarfile.TarFile(archive_path, \"w\") as tarobj:\n            tarobj.add(audio_path, arcname=audio_file)\n        with tarfile.TarFile(archive_path, \"r\") as tarobj:\n            fileobj = tarobj.extractfile(audio_file)\n            found, sr = soundfile_backend.load(fileobj)\n\n        assert sr == sample_rate\n        #self.assertEqual(expected, found)\n        np.testing.assert_array_almost_equal(found.numpy(), expected)\n\n    def test_tarfile_wav(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_tarfile(\"wav\")\n\n    def test_tarfile_flac(self):\n        \"\"\"Loading audio via file-like object works\"\"\"\n        self._test_tarfile(\"flac\")\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/soundfile/save_test.py",
    "content": "import io\nimport unittest\nfrom unittest.mock import patch\n\nimport numpy as np\nimport paddle\nimport soundfile\nfrom common import fetch_wav_subtype\nfrom common import parameterize\nfrom common import skipIfFormatNotSupported\nfrom common_utils import get_wav_data\nfrom common_utils import load_wav\nfrom common_utils import nested_params\nfrom common_utils import TempDirMixin\nfrom paddleaudio.backends import soundfile_backend\n\n\nclass MockedSaveTest(unittest.TestCase):\n    @nested_params(\n        [\"float32\", \"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [False, True],\n        [\n            (None, None),\n            (\"PCM_U\", None),\n            (\"PCM_U\", 8),\n            (\"PCM_S\", None),\n            (\"PCM_S\", 16),\n            (\"PCM_S\", 32),\n            (\"PCM_F\", None),\n            (\"PCM_F\", 32),\n            (\"PCM_F\", 64),\n            (\"ULAW\", None),\n            (\"ULAW\", 8),\n            (\"ALAW\", None),\n            (\"ALAW\", 8),\n        ], )\n    @patch(\"soundfile.write\")\n    def test_wav(self, dtype, sample_rate, num_channels, channels_first,\n                 enc_params, mocked_write):\n        \"\"\"soundfile_backend.save passes correct subtype to soundfile.write when WAV\"\"\"\n        filepath = \"foo.wav\"\n        input_tensor = get_wav_data(\n            dtype,\n            num_channels,\n            num_frames=3 * sample_rate,\n            normalize=dtype == \"float32\",\n            channels_first=channels_first, )\n        input_tensor = paddle.transpose(input_tensor, [1, 0])\n\n        encoding, bits_per_sample = enc_params\n        soundfile_backend.save(\n            filepath,\n            input_tensor,\n            sample_rate,\n            channels_first=channels_first,\n            encoding=encoding,\n            bits_per_sample=bits_per_sample, )\n\n        # on +Py3.8 call_args.kwargs is more descriptive\n        args = mocked_write.call_args[1]\n        assert args[\"file\"] == filepath\n        assert args[\"samplerate\"] == sample_rate\n        assert args[\"subtype\"] == fetch_wav_subtype(dtype, encoding,\n                                                    bits_per_sample)\n        assert args[\"format\"] is None\n        tensor_result = paddle.transpose(\n            input_tensor, [1, 0]) if channels_first else input_tensor\n        #self.assertEqual(args[\"data\"], tensor_result.numpy())\n        np.testing.assert_array_almost_equal(args[\"data\"].numpy(),\n                                             tensor_result.numpy())\n\n    @patch(\"soundfile.write\")\n    def assert_non_wav(\n            self,\n            fmt,\n            dtype,\n            sample_rate,\n            num_channels,\n            channels_first,\n            mocked_write,\n            encoding=None,\n            bits_per_sample=None, ):\n        \"\"\"soundfile_backend.save passes correct subtype and format to soundfile.write when SPHERE\"\"\"\n        filepath = f\"foo.{fmt}\"\n        input_tensor = get_wav_data(\n            dtype,\n            num_channels,\n            num_frames=3 * sample_rate,\n            normalize=False,\n            channels_first=channels_first, )\n        input_tensor = paddle.transpose(input_tensor, [1, 0])\n\n        expected_data = paddle.transpose(\n            input_tensor, [1, 0]) if channels_first else input_tensor\n\n        soundfile_backend.save(\n            filepath,\n            input_tensor,\n            sample_rate,\n            channels_first,\n            encoding=encoding,\n            bits_per_sample=bits_per_sample, )\n\n        # on +Py3.8 call_args.kwargs is more descriptive\n        args = mocked_write.call_args[1]\n        assert args[\"file\"] == filepath\n        assert args[\"samplerate\"] == sample_rate\n        if fmt in [\"sph\", \"nist\", \"nis\"]:\n            assert args[\"format\"] == \"NIST\"\n        else:\n            assert args[\"format\"] is None\n        np.testing.assert_array_almost_equal(args[\"data\"].numpy(),\n                                             expected_data.numpy())\n        #self.assertEqual(args[\"data\"], expected_data)\n\n    @nested_params(\n        [\"sph\", \"nist\", \"nis\"],\n        [\"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [False, True],\n        [\n            (\"PCM_S\", 8),\n            (\"PCM_S\", 16),\n            (\"PCM_S\", 24),\n            (\"PCM_S\", 32),\n            (\"ULAW\", 8),\n            (\"ALAW\", 8),\n            (\"ALAW\", 16),\n            (\"ALAW\", 24),\n            (\"ALAW\", 32),\n        ], )\n    def test_sph(self, fmt, dtype, sample_rate, num_channels, channels_first,\n                 enc_params):\n        \"\"\"soundfile_backend.save passes default format and subtype (None-s) to\n        soundfile.write when not WAV\"\"\"\n        encoding, bits_per_sample = enc_params\n        self.assert_non_wav(\n            fmt,\n            dtype,\n            sample_rate,\n            num_channels,\n            channels_first,\n            encoding=encoding,\n            bits_per_sample=bits_per_sample)\n\n    @parameterize(\n        [\"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [False, True],\n        [8, 16, 24], )\n    def test_flac(self, dtype, sample_rate, num_channels, channels_first,\n                  bits_per_sample):\n        \"\"\"soundfile_backend.save passes default format and subtype (None-s) to\n        soundfile.write when not WAV\"\"\"\n        self.assert_non_wav(\n            \"flac\",\n            dtype,\n            sample_rate,\n            num_channels,\n            channels_first,\n            bits_per_sample=bits_per_sample)\n\n    @parameterize(\n        [\"int32\"],\n        [8000, 16000],\n        [1, 2],\n        [False, True], )\n    def test_ogg(self, dtype, sample_rate, num_channels, channels_first):\n        \"\"\"soundfile_backend.save passes default format and subtype (None-s) to\n        soundfile.write when not WAV\"\"\"\n        self.assert_non_wav(\"ogg\", dtype, sample_rate, num_channels,\n                            channels_first)\n\n\nclass SaveTestBase(TempDirMixin, unittest.TestCase):\n    def assert_wav(self, dtype, sample_rate, num_channels, num_frames):\n        \"\"\"`soundfile_backend.save` can save wav format.\"\"\"\n        path = self.get_temp_path(\"data.wav\")\n        expected = get_wav_data(\n            dtype, num_channels, num_frames=num_frames, normalize=False)\n        soundfile_backend.save(path, expected, sample_rate)\n        found, sr = load_wav(path, normalize=False)\n        assert sample_rate == sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n    def _assert_non_wav(self, fmt, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save non-wav format.\n\n        Due to precision mismatch, and the lack of alternative way to decode the\n        resulting files without using soundfile, only meta data are validated.\n        \"\"\"\n        num_frames = sample_rate * 3\n        path = self.get_temp_path(f\"data.{fmt}\")\n        expected = get_wav_data(\n            dtype, num_channels, num_frames=num_frames, normalize=False)\n        soundfile_backend.save(path, expected, sample_rate)\n        sinfo = soundfile.info(path)\n        assert sinfo.format == fmt.upper()\n        #assert sinfo.frames == num_frames this go wrong\n        assert sinfo.channels == num_channels\n        assert sinfo.samplerate == sample_rate\n\n    def assert_flac(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save flac format.\"\"\"\n        self._assert_non_wav(\"flac\", dtype, sample_rate, num_channels)\n\n    def assert_sphere(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save sph format.\"\"\"\n        self._assert_non_wav(\"nist\", dtype, sample_rate, num_channels)\n\n    def assert_ogg(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save ogg format.\n\n        As we cannot inspect the OGG format (it's lossy), we only check the metadata.\n        \"\"\"\n        self._assert_non_wav(\"ogg\", dtype, sample_rate, num_channels)\n\n\nclass TestSave(SaveTestBase):\n    @parameterize(\n        [\"float32\", \"int32\"],\n        [8000, 16000],\n        [1, 2], )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save wav format.\"\"\"\n        self.assert_wav(dtype, sample_rate, num_channels, num_frames=None)\n\n    @parameterize(\n        [\"float32\", \"int32\"],\n        [4, 8, 16, 32], )\n    def test_multiple_channels(self, dtype, num_channels):\n        \"\"\"`soundfile_backend.save` can save wav with more than 2 channels.\"\"\"\n        sample_rate = 8000\n        self.assert_wav(dtype, sample_rate, num_channels, num_frames=None)\n\n    @parameterize(\n        [\"int32\"],\n        [8000, 16000],\n        [1, 2], )\n    @skipIfFormatNotSupported(\"NIST\")\n    def test_sphere(self, dtype, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save sph format.\"\"\"\n        self.assert_sphere(dtype, sample_rate, num_channels)\n\n    @parameterize(\n        [8000, 16000],\n        [1, 2], )\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_flac(self, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save flac format.\"\"\"\n        self.assert_flac(\"float32\", sample_rate, num_channels)\n\n    @parameterize(\n        [8000, 16000],\n        [1, 2], )\n    @skipIfFormatNotSupported(\"OGG\")\n    def test_ogg(self, sample_rate, num_channels):\n        \"\"\"`soundfile_backend.save` can save ogg/vorbis format.\"\"\"\n        self.assert_ogg(\"float32\", sample_rate, num_channels)\n\n\nclass TestSaveParams(TempDirMixin, unittest.TestCase):\n    \"\"\"Test the correctness of optional parameters of `soundfile_backend.save`\"\"\"\n\n    @parameterize([True, False])\n    def test_channels_first(self, channels_first):\n        \"\"\"channels_first swaps axes\"\"\"\n        path = self.get_temp_path(\"data.wav\")\n        data = get_wav_data(\"int32\", 2, channels_first=channels_first)\n        soundfile_backend.save(path, data, 8000, channels_first=channels_first)\n        found = load_wav(path)[0]\n        expected = data if channels_first else data.transpose([1, 0])\n        #self.assertEqual(found, expected, atol=1e-4, rtol=1e-8)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n\nclass TestFileObject(TempDirMixin, unittest.TestCase):\n    def _test_fileobj(self, ext):\n        \"\"\"Saving audio to file-like object works\"\"\"\n        sample_rate = 16000\n        path = self.get_temp_path(f\"test.{ext}\")\n\n        subtype = \"FLOAT\" if ext == \"wav\" else None\n        data = get_wav_data(\"float32\", num_channels=2)\n        soundfile.write(path, data.numpy().T, sample_rate, subtype=subtype)\n        expected = soundfile.read(path, dtype=\"float32\")[0]\n\n        fileobj = io.BytesIO()\n        soundfile_backend.save(fileobj, data, sample_rate, format=ext)\n        fileobj.seek(0)\n        found, sr = soundfile.read(fileobj, dtype=\"float32\")\n\n        assert sr == sample_rate\n        #self.assertEqual(expected, found, atol=1e-4, rtol=1e-8)\n        np.testing.assert_array_almost_equal(found, expected)\n\n    def test_fileobj_wav(self):\n        \"\"\"Saving audio via file-like object works\"\"\"\n        self._test_fileobj(\"wav\")\n\n    @skipIfFormatNotSupported(\"FLAC\")\n    def test_fileobj_flac(self):\n        \"\"\"Saving audio via file-like object works\"\"\"\n        self._test_fileobj(\"flac\")\n\n    @skipIfFormatNotSupported(\"NIST\")\n    def test_fileobj_nist(self):\n        \"\"\"Saving audio via file-like object works\"\"\"\n        self._test_fileobj(\"NIST\")\n\n    @skipIfFormatNotSupported(\"OGG\")\n    def test_fileobj_ogg(self):\n        \"\"\"Saving audio via file-like object works\"\"\"\n        self._test_fileobj(\"OGG\")\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/soundfile/test_io.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport filecmp\nimport os\nimport unittest\n\nimport numpy as np\nfrom paddleaudio.backends import soundfile_load as load\nfrom paddleaudio.backends import soundfile_save as save\nimport soundfile as sf\n\nfrom base import BackendTest\n\n\nclass TestIO(BackendTest):\n    def test_load_mono_channel(self):\n        sf_data, sf_sr = sf.read(self.files[0])\n        pa_data, pa_sr = load(\n            self.files[0], normal=False, dtype='float64')\n\n        self.assertEqual(sf_data.dtype, pa_data.dtype)\n        self.assertEqual(sf_sr, pa_sr)\n        np.testing.assert_array_almost_equal(sf_data, pa_data)\n\n    def test_load_multi_channels(self):\n        sf_data, sf_sr = sf.read(self.files[1])\n        sf_data = sf_data.T  # Channel dim first\n        pa_data, pa_sr = load(\n            self.files[1], mono=False, normal=False, dtype='float64')\n\n        self.assertEqual(sf_data.dtype, pa_data.dtype)\n        self.assertEqual(sf_sr, pa_sr)\n        np.testing.assert_array_almost_equal(sf_data, pa_data)\n\n    def test_save_mono_channel(self):\n        waveform, sr = np.random.randint(\n            low=-32768, high=32768, size=(48000), dtype=np.int16), 16000\n        sf_tmp_file = 'sf_tmp.wav'\n        pa_tmp_file = 'pa_tmp.wav'\n\n        sf.write(sf_tmp_file, waveform, sr)\n        save(waveform, sr, pa_tmp_file)\n\n        self.assertTrue(filecmp.cmp(sf_tmp_file, pa_tmp_file))\n        for file in [sf_tmp_file, pa_tmp_file]:\n            os.remove(file)\n\n    def test_save_multi_channels(self):\n        waveform, sr = np.random.randint(\n            low=-32768, high=32768, size=(2, 48000), dtype=np.int16), 16000\n        sf_tmp_file = 'sf_tmp.wav'\n        pa_tmp_file = 'pa_tmp.wav'\n\n        sf.write(sf_tmp_file, waveform.T, sr)\n        save(waveform.T, sr, pa_tmp_file)\n\n        self.assertTrue(filecmp.cmp(sf_tmp_file, pa_tmp_file))\n        for file in [sf_tmp_file, pa_tmp_file]:\n            os.remove(file)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/common.py",
    "content": "import itertools\nfrom unittest import skipIf\n\nfrom paddleaudio._internal.module_utils import is_module_available\nfrom parameterized import parameterized\n\n\ndef name_func(func, _, params):\n    return f'{func.__name__}_{\"_\".join(str(arg) for arg in params.args)}'\n\n\ndef dtype2subtype(dtype):\n    return {\n        \"float64\": \"DOUBLE\",\n        \"float32\": \"FLOAT\",\n        \"int32\": \"PCM_32\",\n        \"int16\": \"PCM_16\",\n        \"uint8\": \"PCM_U8\",\n        \"int8\": \"PCM_S8\",\n    }[dtype]\n\n\ndef skipIfFormatNotSupported(fmt):\n    fmts = []\n    if is_module_available(\"soundfile\"):\n        import soundfile\n\n        fmts = soundfile.available_formats()\n        return skipIf(fmt not in fmts, f'\"{fmt}\" is not supported by soundfile')\n    return skipIf(True, '\"soundfile\" not available.')\n\n\ndef parameterize(*params):\n    return parameterized.expand(\n        list(itertools.product(*params)), name_func=name_func)\n\n\ndef fetch_wav_subtype(dtype, encoding, bits_per_sample):\n    subtype = {\n        (None, None): dtype2subtype(dtype),\n        (None, 8): \"PCM_U8\",\n        (\"PCM_U\", None): \"PCM_U8\",\n        (\"PCM_U\", 8): \"PCM_U8\",\n        (\"PCM_S\", None): \"PCM_32\",\n        (\"PCM_S\", 16): \"PCM_16\",\n        (\"PCM_S\", 32): \"PCM_32\",\n        (\"PCM_F\", None): \"FLOAT\",\n        (\"PCM_F\", 32): \"FLOAT\",\n        (\"PCM_F\", 64): \"DOUBLE\",\n        (\"ULAW\", None): \"ULAW\",\n        (\"ULAW\", 8): \"ULAW\",\n        (\"ALAW\", None): \"ALAW\",\n        (\"ALAW\", 8): \"ALAW\",\n    }.get((encoding, bits_per_sample))\n    if subtype:\n        return subtype\n    raise ValueError(f\"wav does not support ({encoding}, {bits_per_sample}).\")\n\ndef get_encoding(ext, dtype):\n    exts = {\n        \"mp3\",\n        \"flac\",\n        \"vorbis\",\n    }\n    encodings = {\n        \"float32\": \"PCM_F\",\n        \"int32\": \"PCM_S\",\n        \"int16\": \"PCM_S\",\n        \"uint8\": \"PCM_U\",\n    }\n    return ext.upper() if ext in exts else encodings[dtype]\n\n\ndef get_bit_depth(dtype):\n    bit_depths = {\n        \"float32\": 32,\n        \"int32\": 32,\n        \"int16\": 16,\n        \"uint8\": 8,\n    }\n    return bit_depths[dtype]\n\ndef get_bits_per_sample(ext, dtype):\n    bits_per_samples = {\n        \"flac\": 24,\n        \"mp3\": 0,\n        \"vorbis\": 0,\n    }\n    return bits_per_samples.get(ext, get_bit_depth(dtype))\n"
  },
  {
    "path": "audio/tests/backends/sox_io/info_test.py",
    "content": "import io\nimport itertools\nimport os\nimport platform\nimport tarfile\nimport unittest\nfrom contextlib import contextmanager\nif platform.system() == \"Windows\":\n    import warnings\n    warnings.warn(\"sox io not support in Windows, please skip test.\")\n    exit()\n\nfrom parameterized import parameterized\nfrom common import get_bits_per_sample, get_encoding\n\nfrom paddleaudio.backends import sox_io_backend\n\nfrom common_utils import (\n    get_wav_data,\n    save_wav,\n    TempDirMixin,\n    sox_utils, )\n\n#code is from:https://github.com/pytorch/audio/blob/main/torchaudio/test/torchaudio_unittest/backend/sox_io/info_test.py\n\n\nclass TestInfo(TempDirMixin, unittest.TestCase):\n    @parameterized.expand(\n        list(\n            itertools.product(\n                [\n                    \"float32\",\n                    \"int32\",\n                ],\n                [8000, 16000],\n                [1, 2], )), )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"`sox_io_backend.info` can check wav file correctly\"\"\"\n        duration = 1\n        path = self.get_temp_path(\"data.wav\")\n        data = get_wav_data(\n            dtype,\n            num_channels,\n            normalize=False,\n            num_frames=duration * sample_rate)\n        save_wav(path, data, sample_rate)\n        info = sox_io_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == sox_utils.get_bit_depth(dtype)\n        assert info.encoding == get_encoding(\"wav\", dtype)\n\n    @parameterized.expand(\n        list(\n            itertools.product(\n                [\"float32\", \"int32\"],\n                [8000, 16000],\n                [4, 8, 16, 32], )), )\n    def test_wav_multiple_channels(self, dtype, sample_rate, num_channels):\n        \"\"\"`sox_io_backend.info` can check wav file with channels more than 2 correctly\"\"\"\n        duration = 1\n        path = self.get_temp_path(\"data.wav\")\n        data = get_wav_data(\n            dtype,\n            num_channels,\n            normalize=False,\n            num_frames=duration * sample_rate)\n        save_wav(path, data, sample_rate)\n        info = sox_io_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == sox_utils.get_bit_depth(dtype)\n\n    def test_ulaw(self):\n        \"\"\"`sox_io_backend.info` can check ulaw file correctly\"\"\"\n        duration = 1\n        num_channels = 1\n        sample_rate = 8000\n        path = self.get_temp_path(\"data.wav\")\n        sox_utils.gen_audio_file(\n            path,\n            sample_rate=sample_rate,\n            num_channels=num_channels,\n            bit_depth=8,\n            encoding=\"u-law\",\n            duration=duration)\n        info = sox_io_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == 8\n        assert info.encoding == \"ULAW\"\n\n    def test_alaw(self):\n        \"\"\"`sox_io_backend.info` can check alaw file correctly\"\"\"\n        duration = 1\n        num_channels = 1\n        sample_rate = 8000\n        path = self.get_temp_path(\"data.wav\")\n        sox_utils.gen_audio_file(\n            path,\n            sample_rate=sample_rate,\n            num_channels=num_channels,\n            bit_depth=8,\n            encoding=\"a-law\",\n            duration=duration)\n        info = sox_io_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_frames == sample_rate * duration\n        assert info.num_channels == num_channels\n        assert info.bits_per_sample == 8\n        assert info.encoding == \"ALAW\"\n\n\n#class TestInfoOpus(unittest.TestCase):\n#@parameterized.expand(\n#list(\n#itertools.product(\n#[\"96k\"],\n#[1, 2],\n#[0, 5, 10],\n#)\n#),\n#)\n#def test_opus(self, bitrate, num_channels, compression_level):\n#\"\"\"`sox_io_backend.info` can check opus file correcty\"\"\"\n#path = data_utils.get_asset_path(\"io\", f\"{bitrate}_{compression_level}_{num_channels}ch.opus\")\n#info = sox_io_backend.info(path)\n#assert info.sample_rate == 48000\n#assert info.num_frames == 32768\n#assert info.num_channels == num_channels\n#assert info.bits_per_sample == 0  # bit_per_sample is irrelevant for compressed formats\n#assert info.encoding == \"OPUS\"\n\n\nclass FileObjTestBase(TempDirMixin):\n    def _gen_file(self,\n                  ext,\n                  dtype,\n                  sample_rate,\n                  num_channels,\n                  num_frames,\n                  *,\n                  comments=None):\n        path = self.get_temp_path(f\"test.{ext}\")\n        bit_depth = sox_utils.get_bit_depth(dtype)\n        duration = num_frames / sample_rate\n        comment_file = self._gen_comment_file(comments) if comments else None\n\n        sox_utils.gen_audio_file(\n            path,\n            sample_rate,\n            num_channels=num_channels,\n            encoding=sox_utils.get_encoding(dtype),\n            bit_depth=bit_depth,\n            duration=duration,\n            comment_file=comment_file, )\n        return path\n\n    def _gen_comment_file(self, comments):\n        comment_path = self.get_temp_path(\"comment.txt\")\n        with open(comment_path, \"w\") as file_:\n            file_.writelines(comments)\n        return comment_path\n\n\nclass Unseekable:\n    def __init__(self, fileobj):\n        self.fileobj = fileobj\n\n    def read(self, n):\n        return self.fileobj.read(n)\n\n\nclass TestFileObject(FileObjTestBase, unittest.TestCase):\n    def _query_fileobj(self,\n                       ext,\n                       dtype,\n                       sample_rate,\n                       num_channels,\n                       num_frames,\n                       *,\n                       comments=None):\n        path = self._gen_file(\n            ext,\n            dtype,\n            sample_rate,\n            num_channels,\n            num_frames,\n            comments=comments)\n        format_ = ext if ext in [\"mp3\"] else None\n        with open(path, \"rb\") as fileobj:\n            return sox_io_backend.info(fileobj, format_)\n\n    def _query_bytesio(self, ext, dtype, sample_rate, num_channels, num_frames):\n        path = self._gen_file(ext, dtype, sample_rate, num_channels, num_frames)\n        format_ = ext if ext in [\"mp3\"] else None\n        with open(path, \"rb\") as file_:\n            fileobj = io.BytesIO(file_.read())\n        return sox_io_backend.info(fileobj, format_)\n\n    def _query_tarfile(self, ext, dtype, sample_rate, num_channels, num_frames):\n        audio_path = self._gen_file(ext, dtype, sample_rate, num_channels,\n                                    num_frames)\n        audio_file = os.path.basename(audio_path)\n        archive_path = self.get_temp_path(\"archive.tar.gz\")\n        with tarfile.TarFile(archive_path, \"w\") as tarobj:\n            tarobj.add(audio_path, arcname=audio_file)\n        format_ = ext if ext in [\"mp3\"] else None\n        with tarfile.TarFile(archive_path, \"r\") as tarobj:\n            fileobj = tarobj.extractfile(audio_file)\n            return sox_io_backend.info(fileobj, format_)\n\n    @contextmanager\n    def _set_buffer_size(self, buffer_size):\n        try:\n            original_buffer_size = get_buffer_size()\n            set_buffer_size(buffer_size)\n            yield\n        finally:\n            set_buffer_size(original_buffer_size)\n\n    @parameterized.expand([\n        (\"wav\", \"float32\"),\n        (\"wav\", \"int32\"),\n        (\"wav\", \"int16\"),\n        (\"wav\", \"uint8\"),\n    ])\n    def test_fileobj(self, ext, dtype):\n        \"\"\"Querying audio via file object works\"\"\"\n        sample_rate = 16000\n        num_frames = 3 * sample_rate\n        num_channels = 2\n        sinfo = self._query_fileobj(ext, dtype, sample_rate, num_channels,\n                                    num_frames)\n\n        bits_per_sample = get_bits_per_sample(ext, dtype)\n        num_frames = 0 if ext in [\"mp3\", \"vorbis\"] else num_frames\n\n        assert sinfo.sample_rate == sample_rate\n        assert sinfo.num_channels == num_channels\n        assert sinfo.num_frames == num_frames\n        assert sinfo.bits_per_sample == bits_per_sample\n        assert sinfo.encoding == get_encoding(ext, dtype)\n\n    @parameterized.expand([\n        (\"wav\", \"float32\"),\n        (\"wav\", \"int32\"),\n        (\"wav\", \"int16\"),\n        (\"wav\", \"uint8\"),\n    ])\n    def test_bytesio(self, ext, dtype):\n        \"\"\"Querying audio via ByteIO object works for small data\"\"\"\n        sample_rate = 16000\n        num_frames = 3 * sample_rate\n        num_channels = 2\n        sinfo = self._query_bytesio(ext, dtype, sample_rate, num_channels,\n                                    num_frames)\n\n        bits_per_sample = get_bits_per_sample(ext, dtype)\n        num_frames = 0 if ext in [\"mp3\", \"vorbis\"] else num_frames\n\n        assert sinfo.sample_rate == sample_rate\n        assert sinfo.num_channels == num_channels\n        assert sinfo.num_frames == num_frames\n        assert sinfo.bits_per_sample == bits_per_sample\n        assert sinfo.encoding == get_encoding(ext, dtype)\n\n    @parameterized.expand([\n        (\"wav\", \"float32\"),\n        (\"wav\", \"int32\"),\n        (\"wav\", \"int16\"),\n        (\"wav\", \"uint8\"),\n    ])\n    def test_bytesio_tiny(self, ext, dtype):\n        \"\"\"Querying audio via ByteIO object works for small data\"\"\"\n        sample_rate = 8000\n        num_frames = 4\n        num_channels = 2\n        sinfo = self._query_bytesio(ext, dtype, sample_rate, num_channels,\n                                    num_frames)\n\n        bits_per_sample = get_bits_per_sample(ext, dtype)\n        num_frames = 0 if ext in [\"mp3\", \"vorbis\"] else num_frames\n\n        assert sinfo.sample_rate == sample_rate\n        assert sinfo.num_channels == num_channels\n        assert sinfo.num_frames == num_frames\n        assert sinfo.bits_per_sample == bits_per_sample\n        assert sinfo.encoding == get_encoding(ext, dtype)\n\n    @parameterized.expand([\n        (\"wav\", \"float32\"),\n        (\"wav\", \"int32\"),\n        (\"wav\", \"int16\"),\n        (\"wav\", \"uint8\"),\n        (\"flac\", \"float32\"),\n        (\"vorbis\", \"float32\"),\n        (\"amb\", \"int16\"),\n    ])\n    def test_tarfile(self, ext, dtype):\n        \"\"\"Querying compressed audio via file-like object works\"\"\"\n        sample_rate = 16000\n        num_frames = 3.0 * sample_rate\n        num_channels = 2\n        sinfo = self._query_tarfile(ext, dtype, sample_rate, num_channels,\n                                    num_frames)\n\n        bits_per_sample = get_bits_per_sample(ext, dtype)\n        num_frames = 0 if ext in [\"vorbis\"] else num_frames\n\n        assert sinfo.sample_rate == sample_rate\n        assert sinfo.num_channels == num_channels\n        assert sinfo.num_frames == num_frames\n        assert sinfo.bits_per_sample == bits_per_sample\n        assert sinfo.encoding == get_encoding(ext, dtype)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/load_test.py",
    "content": "import itertools\nimport platform\nimport unittest\nif platform.system() == \"Windows\":\n    import warnings\n    warnings.warn(\"sox io not support in Windows, please skip test.\")\n    exit()\n\nfrom parameterized import parameterized\nimport numpy as np\nfrom paddleaudio.backends import sox_io_backend\n\nfrom common_utils import (\n    get_wav_data,\n    load_wav,\n    save_wav, )\n\n#code is from:https://github.com/pytorch/audio/blob/main/torchaudio/test/torchaudio_unittest/backend/sox_io/load_test.py\n\n\nclass TestLoad(unittest.TestCase):\n    def assert_wav(self, dtype, sample_rate, num_channels, normalize, duration):\n        \"\"\"`sox_io_backend.load` can load wav format correctly.\n\n        Wav data loaded with sox_io backend should match those with scipy\n        \"\"\"\n        path = 'testdata/reference.wav'\n        data = get_wav_data(\n            dtype,\n            num_channels,\n            normalize=normalize,\n            num_frames=duration * sample_rate)\n        save_wav(path, data, sample_rate)\n        expected = load_wav(path, normalize=normalize)[0]\n        data, sr = sox_io_backend.load(path, normalize=normalize)\n        assert sr == sample_rate\n        np.testing.assert_array_almost_equal(data, expected, decimal=4)\n\n    @parameterized.expand(\n        list(\n            itertools.product(\n                [\n                    \"float64\",\n                    \"float32\",\n                    \"int32\",\n                ],\n                [8000, 16000],\n                [1, 2],\n                [False, True], )), )\n    def test_wav(self, dtype, sample_rate, num_channels, normalize):\n        \"\"\"`sox_io_backend.load` can load wav format correctly.\"\"\"\n        self.assert_wav(dtype, sample_rate, num_channels, normalize, duration=1)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/save_test.py",
    "content": "import io\nimport platform\nimport unittest\nif platform.system() == \"Windows\":\n    import warnings\n    warnings.warn(\"sox io not support in Windows, please skip test.\")\n    exit()\n\nimport numpy as np\nfrom paddleaudio.backends import sox_io_backend\n\nfrom common_utils import (get_wav_data, load_wav, save_wav, nested_params,\n                          TempDirMixin, sox_utils)\n\n#code is from:https://github.com/pytorch/audio/blob/main/torchaudio/test/torchaudio_unittest/backend/sox_io/save_test.py\n\n\ndef _get_sox_encoding(encoding):\n    encodings = {\n        \"PCM_F\": \"floating-point\",\n        \"PCM_S\": \"signed-integer\",\n        \"PCM_U\": \"unsigned-integer\",\n        \"ULAW\": \"u-law\",\n        \"ALAW\": \"a-law\",\n    }\n    return encodings.get(encoding)\n\n\nclass TestSaveBase(TempDirMixin):\n    def assert_save_consistency(\n            self,\n            format: str,\n            *,\n            compression: float=None,\n            encoding: str=None,\n            bits_per_sample: int=None,\n            sample_rate: float=8000,\n            num_channels: int=2,\n            num_frames: float=3 * 8000,\n            src_dtype: str=\"int32\",\n            test_mode: str=\"path\", ):\n        \"\"\"`save` function produces file that is comparable with `sox` command\n\n        To compare that the file produced by `save` function against the file produced by\n        the equivalent `sox` command, we need to load both files.\n        But there are many formats that cannot be opened with common Python modules (like\n        SciPy).\n        So we use `sox` command to prepare the original data and convert the saved files\n        into a format that SciPy can read (PCM wav).\n        The following diagram illustrates this process. The difference is 2.1. and 3.1.\n\n        This assumes that\n         - loading data with SciPy preserves the data well.\n         - converting the resulting files into WAV format with `sox` preserve the data well.\n\n                          x\n                          | 1. Generate source wav file with SciPy\n                          |\n                          v\n          -------------- wav ----------------\n         |                                   |\n         | 2.1. load with scipy              | 3.1. Convert to the target\n         |   then save it into the target    |      format depth with sox\n         |   format with paddleaudio          |\n         v                                   v\n        target format                       target format\n         |                                   |\n         | 2.2. Convert to wav with sox      | 3.2. Convert to wav with sox\n         |                                   |\n         v                                   v\n        wav                                 wav\n         |                                   |\n         | 2.3. load with scipy              | 3.3. load with scipy\n         |                                   |\n         v                                   v\n        tensor -------> compare <--------- tensor\n\n        \"\"\"\n        cmp_encoding = \"floating-point\"\n        cmp_bit_depth = 32\n\n        src_path = self.get_temp_path(\"1.source.wav\")\n        tgt_path = self.get_temp_path(f\"2.1.paddleaudio.{format}\")\n        tst_path = self.get_temp_path(\"2.2.result.wav\")\n        sox_path = self.get_temp_path(f\"3.1.sox.{format}\")\n        ref_path = self.get_temp_path(\"3.2.ref.wav\")\n\n        # 1. Generate original wav\n        data = get_wav_data(\n            src_dtype, num_channels, normalize=False, num_frames=num_frames)\n        save_wav(src_path, data, sample_rate)\n\n        # 2.1. Convert the original wav to target format with paddleaudio\n        data = load_wav(src_path, normalize=False)[0]\n        if test_mode == \"path\":\n            sox_io_backend.save(\n                tgt_path,\n                data,\n                sample_rate,\n                compression=compression,\n                encoding=encoding,\n                bits_per_sample=bits_per_sample)\n        elif test_mode == \"fileobj\":\n            with open(tgt_path, \"bw\") as file_:\n                sox_io_backend.save(\n                    file_,\n                    data,\n                    sample_rate,\n                    format=format,\n                    compression=compression,\n                    encoding=encoding,\n                    bits_per_sample=bits_per_sample, )\n        elif test_mode == \"bytesio\":\n            file_ = io.BytesIO()\n            sox_io_backend.save(\n                file_,\n                data,\n                sample_rate,\n                format=format,\n                compression=compression,\n                encoding=encoding,\n                bits_per_sample=bits_per_sample, )\n            file_.seek(0)\n            with open(tgt_path, \"bw\") as f:\n                f.write(file_.read())\n        else:\n            raise ValueError(f\"Unexpected test mode: {test_mode}\")\n        # 2.2. Convert the target format to wav with sox\n        sox_utils.convert_audio_file(\n            tgt_path, tst_path, encoding=cmp_encoding, bit_depth=cmp_bit_depth)\n        # 2.3. Load with SciPy\n        found = load_wav(tst_path, normalize=False)[0]\n\n        # 3.1. Convert the original wav to target format with sox\n        sox_encoding = _get_sox_encoding(encoding)\n        sox_utils.convert_audio_file(\n            src_path,\n            sox_path,\n            compression=compression,\n            encoding=sox_encoding,\n            bit_depth=bits_per_sample)\n        # 3.2. Convert the target format to wav with sox\n        sox_utils.convert_audio_file(\n            sox_path, ref_path, encoding=cmp_encoding, bit_depth=cmp_bit_depth)\n        # 3.3. Load with SciPy\n        expected = load_wav(ref_path, normalize=False)[0]\n\n        np.testing.assert_array_almost_equal(found, expected)\n\n\nclass TestSave(TestSaveBase, unittest.TestCase):\n    @nested_params(\n        [\n            \"path\",\n        ],\n        [\n            (\"PCM_U\", 8),\n            (\"PCM_S\", 16),\n            (\"PCM_S\", 32),\n            (\"PCM_F\", 32),\n            (\"PCM_F\", 64),\n            (\"ULAW\", 8),\n            (\"ALAW\", 8),\n        ], )\n    def test_save_wav(self, test_mode, enc_params):\n        encoding, bits_per_sample = enc_params\n        self.assert_save_consistency(\n            \"wav\",\n            encoding=encoding,\n            bits_per_sample=bits_per_sample,\n            test_mode=test_mode)\n\n    @nested_params(\n        [\n            \"path\",\n        ],\n        [\n            (\"float32\", ),\n            (\"int32\", ),\n        ], )\n    def test_save_wav_dtype(self, test_mode, params):\n        (dtype, ) = params\n        self.assert_save_consistency(\n            \"wav\", src_dtype=dtype, test_mode=test_mode)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/smoke_test.py",
    "content": "import io\nimport itertools\nimport platform\nimport unittest\nif platform.system() == \"Windows\":\n    import warnings\n    warnings.warn(\"sox io not support in Windows, please skip test.\")\n    exit()\n\nfrom parameterized import parameterized\nfrom paddleaudio.backends import sox_io_backend\nfrom common_utils import (get_wav_data, TempDirMixin, name_func)\n\n\nclass SmokeTest(TempDirMixin, unittest.TestCase):\n    \"\"\"Run smoke test on various audio format\n\n    The purpose of this test suite is to verify that sox_io_backend functionalities do not exhibit\n    abnormal behaviors.\n\n    This test suite should be able to run without any additional tools (such as sox command),\n    however without such tools, the correctness of each function cannot be verified.\n    \"\"\"\n\n    def run_smoke_test(self,\n                       ext,\n                       sample_rate,\n                       num_channels,\n                       *,\n                       compression=None,\n                       dtype=\"float32\"):\n        duration = 1\n        num_frames = sample_rate * duration\n        #path = self.get_temp_path(f\"test.{ext}\")\n        path = self.get_temp_path(f\"test.{ext}\")\n        original = get_wav_data(\n            dtype, num_channels, normalize=False, num_frames=num_frames)\n\n        # 1. run save\n        sox_io_backend.save(\n            path, original, sample_rate, compression=compression)\n        # 2. run info\n        info = sox_io_backend.info(path)\n        assert info.sample_rate == sample_rate\n        assert info.num_channels == num_channels\n        # 3. run load\n        loaded, sr = sox_io_backend.load(path, normalize=False)\n        assert sr == sample_rate\n        assert loaded.shape[0] == num_channels\n\n    @parameterized.expand(\n        list(\n            itertools.product(\n                [\"float32\", \"int32\"],\n                #[\"float32\", \"int32\", \"int16\", \"uint8\"],\n                [8000, 16000],\n                [1, 2], )),\n        name_func=name_func, )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"Run smoke test on wav format\"\"\"\n        self.run_smoke_test(\"wav\", sample_rate, num_channels, dtype=dtype)\n\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #[-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320],\n    #)\n    #)\n    #)\n    #def test_mp3(self, sample_rate, num_channels, bit_rate):\n    #\"\"\"Run smoke test on mp3 format\"\"\"\n    #self.run_smoke_test(\"mp3\", sample_rate, num_channels, compression=bit_rate)\n\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #[-1, 0, 1, 2, 3, 3.6, 5, 10],\n    #)\n    #)\n    #)\n    #def test_vorbis(self, sample_rate, num_channels, quality_level):\n    #\"\"\"Run smoke test on vorbis format\"\"\"\n    #self.run_smoke_test(\"vorbis\", sample_rate, num_channels, compression=quality_level)\n\n    @parameterized.expand(\n        list(itertools.product(\n            [8000, 16000],\n            [1, 2],\n            list(range(9)), )),\n        name_func=name_func, )\n    def test_flac(self, sample_rate, num_channels, compression_level):\n        \"\"\"Run smoke test on flac format\"\"\"\n        self.run_smoke_test(\n            \"flac\", sample_rate, num_channels, compression=compression_level)\n\n\nclass SmokeTestFileObj(unittest.TestCase):\n    \"\"\"Run smoke test on various audio format\n\n    The purpose of this test suite is to verify that sox_io_backend functionalities do not exhibit\n    abnormal behaviors.\n\n    This test suite should be able to run without any additional tools (such as sox command),\n    however without such tools, the correctness of each function cannot be verified.\n    \"\"\"\n\n    def run_smoke_test(self,\n                       ext,\n                       sample_rate,\n                       num_channels,\n                       *,\n                       compression=None,\n                       dtype=\"float32\"):\n        duration = 1\n        num_frames = sample_rate * duration\n        original = get_wav_data(\n            dtype, num_channels, normalize=False, num_frames=num_frames)\n\n        fileobj = io.BytesIO()\n        # 1. run save\n        sox_io_backend.save(\n            fileobj, original, sample_rate, compression=compression, format=ext)\n        # 2. run info\n        fileobj.seek(0)\n        info = sox_io_backend.info(fileobj, format=ext)\n        assert info.sample_rate == sample_rate\n        assert info.num_channels == num_channels\n        # 3. run load\n        fileobj.seek(0)\n        loaded, sr = sox_io_backend.load(fileobj, normalize=False, format=ext)\n        assert sr == sample_rate\n        assert loaded.shape[0] == num_channels\n\n    @parameterized.expand(\n        list(itertools.product(\n            [\"float32\", \"int32\"],\n            [8000, 16000],\n            [1, 2], )),\n        name_func=name_func, )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"Run smoke test on wav format\"\"\"\n        self.run_smoke_test(\"wav\", sample_rate, num_channels, dtype=dtype)\n\n    # not support yet\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #[-4.2, -0.2, 0, 0.2, 96, 128, 160, 192, 224, 256, 320],\n    #)\n    #)\n    #)\n    #def test_mp3(self, sample_rate, num_channels, bit_rate):\n    #\"\"\"Run smoke test on mp3 format\"\"\"\n    #self.run_smoke_test(\"mp3\", sample_rate, num_channels, compression=bit_rate)\n\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #[-1, 0, 1, 2, 3, 3.6, 5, 10],\n    #)\n    #)\n    #)\n    #def test_vorbis(self, sample_rate, num_channels, quality_level):\n    #\"\"\"Run smoke test on vorbis format\"\"\"\n    #self.run_smoke_test(\"vorbis\", sample_rate, num_channels, compression=quality_level)\n\n    @parameterized.expand(\n        list(itertools.product(\n            [8000, 16000],\n            [1, 2],\n            list(range(9)), )),\n        name_func=name_func, )\n    def test_flac(self, sample_rate, num_channels, compression_level):\n        #\"\"\"Run smoke test on flac format\"\"\"\n        self.run_smoke_test(\n            \"flac\", sample_rate, num_channels, compression=compression_level)\n\n\nif __name__ == '__main__':\n    #test_func()\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/sox_effect_test.py",
    "content": "#code is from: https://github.com/pytorch/audio/blob/main/test/torchaudio_unittest/sox_effect/sox_effect_test.py\nimport io\nimport itertools\nimport platform\nimport tarfile\nimport unittest\nfrom pathlib import Path\n\nimport numpy as np\nif platform.system() == \"Windows\":\n    import warnings\n    warnings.warn(\"sox io not support in Windows, please skip test.\")\n    exit()\n\nfrom parameterized import parameterized\nfrom paddleaudio import sox_effects\nfrom common_utils import (get_sinusoid, get_wav_data, load_wav, save_wav,\n                          sox_utils, TempDirMixin, load_effects_params)\n\n\nclass TestSoxEffects(unittest.TestCase):\n    def test_init(self):\n        \"\"\"Calling init_sox_effects multiple times does not crush\"\"\"\n        for _ in range(3):\n            sox_effects.init_sox_effects()\n\n\nclass TestSoxEffectsTensor(TempDirMixin, unittest.TestCase):\n    \"\"\"Test suite for `apply_effects_tensor` function\"\"\"\n\n    @parameterized.expand(\n        list(\n            itertools.product([\"float32\", \"int32\"], [8000, 16000], [1, 2, 4, 8],\n                              [True, False])), )\n    def test_apply_no_effect(self, dtype, sample_rate, num_channels,\n                             channels_first):\n        \"\"\"`apply_effects_tensor` without effects should return identical data as input\"\"\"\n        original = get_wav_data(\n            dtype, num_channels, channels_first=channels_first)\n        expected = original.clone()\n\n        found, output_sample_rate = sox_effects.apply_effects_tensor(\n            expected, sample_rate, [], channels_first)\n\n        assert (output_sample_rate == sample_rate)\n        # SoxEffect should not alter the input Tensor object\n        #self.assertEqual(original, expected)\n        np.testing.assert_array_almost_equal(original.numpy(), expected.numpy())\n\n        # SoxEffect should not return the same Tensor object\n        assert expected is not found\n        # Returned Tensor should equal to the input Tensor\n        #self.assertEqual(expected, found)\n        np.testing.assert_array_almost_equal(expected.numpy(), found.numpy())\n\n    @parameterized.expand(\n        load_effects_params(\"sox_effect_test_args.jsonl\"),\n        name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0][\"effects\"][0][0]}',\n    )\n    def test_apply_effects(self, args):\n        \"\"\"`apply_effects_tensor` should return identical data as sox command\"\"\"\n        effects = args[\"effects\"]\n        num_channels = args.get(\"num_channels\", 2)\n        input_sr = args.get(\"input_sample_rate\", 8000)\n        output_sr = args.get(\"output_sample_rate\")\n\n        input_path = self.get_temp_path(\"input.wav\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n\n        original = get_sinusoid(\n            frequency=800,\n            sample_rate=input_sr,\n            n_channels=num_channels,\n            dtype=\"float32\")\n        save_wav(input_path, original, input_sr)\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_sample_rate=output_sr)\n\n        expected, expected_sr = load_wav(reference_path)\n        found, sr = sox_effects.apply_effects_tensor(original, input_sr,\n                                                     effects)\n\n        assert sr == expected_sr\n        #self.assertEqual(expected, found)\n        np.testing.assert_array_almost_equal(expected.numpy(), found.numpy())\n\n\nclass TestSoxEffectsFile(TempDirMixin, unittest.TestCase):\n    \"\"\"Test suite for `apply_effects_file` function\"\"\"\n\n    @parameterized.expand(\n        list(\n            itertools.product(\n                [\"float32\", \"int32\"],\n                [8000, 16000],\n                [1, 2, 4, 8],\n                [False, True], )),\n        #name_func=name_func,\n    )\n    def test_apply_no_effect(self, dtype, sample_rate, num_channels,\n                             channels_first):\n        \"\"\"`apply_effects_file` without effects should return identical data as input\"\"\"\n        path = self.get_temp_path(\"input.wav\")\n        expected = get_wav_data(\n            dtype, num_channels, channels_first=channels_first)\n        save_wav(path, expected, sample_rate, channels_first=channels_first)\n\n        found, output_sample_rate = sox_effects.apply_effects_file(\n            path, [], normalize=False, channels_first=channels_first)\n\n        assert output_sample_rate == sample_rate\n        #self.assertEqual(expected, found)\n        np.testing.assert_array_almost_equal(expected.numpy(), found.numpy())\n\n    @parameterized.expand(\n        load_effects_params(\"sox_effect_test_args.jsonl\"),\n        #name_func=lambda f, i, p: f'{f.__name__}_{i}_{p.args[0][\"effects\"][0][0]}',\n    )\n    def test_apply_effects_str(self, args):\n        \"\"\"`apply_effects_file` should return identical data as sox command\"\"\"\n        dtype = \"int32\"\n        channels_first = True\n        effects = args[\"effects\"]\n        num_channels = args.get(\"num_channels\", 2)\n        input_sr = args.get(\"input_sample_rate\", 8000)\n        output_sr = args.get(\"output_sample_rate\")\n\n        input_path = self.get_temp_path(\"input.wav\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n        data = get_wav_data(dtype, num_channels, channels_first=channels_first)\n        save_wav(input_path, data, input_sr, channels_first=channels_first)\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_sample_rate=output_sr)\n\n        expected, expected_sr = load_wav(reference_path)\n        found, sr = sox_effects.apply_effects_file(\n            input_path, effects, normalize=False, channels_first=channels_first)\n\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(expected.numpy(), found.numpy())\n\n    def test_apply_effects_path(self):\n        \"\"\"`apply_effects_file` should return identical data as sox command when file path is given as a Path Object\"\"\"\n        dtype = \"int32\"\n        channels_first = True\n        effects = [[\"hilbert\"]]\n        num_channels = 2\n        input_sr = 8000\n        output_sr = 8000\n\n        input_path = self.get_temp_path(\"input.wav\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n        data = get_wav_data(dtype, num_channels, channels_first=channels_first)\n        save_wav(input_path, data, input_sr, channels_first=channels_first)\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_sample_rate=output_sr)\n\n        expected, expected_sr = load_wav(reference_path)\n        found, sr = sox_effects.apply_effects_file(\n            Path(input_path),\n            effects,\n            normalize=False,\n            channels_first=channels_first)\n\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(expected.numpy(), found.numpy())\n\n\nclass TestFileFormats(TempDirMixin, unittest.TestCase):\n    \"\"\"`apply_effects_file` gives the same result as sox on various file formats\"\"\"\n\n    @parameterized.expand(\n        list(itertools.product(\n            [\"float32\", \"int32\"],\n            [8000, 16000],\n            [1, 2], )),\n        #name_func=lambda f, _, p: f'{f.__name__}_{\"_\".join(str(arg) for arg in p.args)}',\n    )\n    def test_wav(self, dtype, sample_rate, num_channels):\n        \"\"\"`apply_effects_file` works on various wav format\"\"\"\n        channels_first = True\n        effects = [[\"band\", \"300\", \"10\"]]\n\n        input_path = self.get_temp_path(\"input.wav\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n        data = get_wav_data(dtype, num_channels, channels_first=channels_first)\n        save_wav(input_path, data, sample_rate, channels_first=channels_first)\n        sox_utils.run_sox_effect(input_path, reference_path, effects)\n\n        expected, expected_sr = load_wav(reference_path)\n        found, sr = sox_effects.apply_effects_file(\n            input_path, effects, normalize=False, channels_first=channels_first)\n\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n    #not support now\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #)\n    #),\n    ##name_func=lambda f, _, p: f'{f.__name__}_{\"_\".join(str(arg) for arg in p.args)}',\n    #)\n    #def test_flac(self, sample_rate, num_channels):\n    #\"\"\"`apply_effects_file` works on various flac format\"\"\"\n    #channels_first = True\n    #effects = [[\"band\", \"300\", \"10\"]]\n\n    #input_path = self.get_temp_path(\"input.flac\")\n    #reference_path = self.get_temp_path(\"reference.wav\")\n    #sox_utils.gen_audio_file(input_path, sample_rate, num_channels)\n    #sox_utils.run_sox_effect(input_path, reference_path, effects, output_bitdepth=32)\n\n    #expected, expected_sr = load_wav(reference_path)\n    #found, sr = sox_effects.apply_effects_file(input_path, effects, channels_first=channels_first)\n    #save_wav(self.get_temp_path(\"result.wav\"), found, sr, channels_first=channels_first)\n\n    #assert sr == expected_sr\n    ##self.assertEqual(found, expected)\n    #np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n    #@parameterized.expand(\n    #list(\n    #itertools.product(\n    #[8000, 16000],\n    #[1, 2],\n    #)\n    #),\n    ##name_func=lambda f, _, p: f'{f.__name__}_{\"_\".join(str(arg) for arg in p.args)}',\n    #)\n    #def test_vorbis(self, sample_rate, num_channels):\n    #\"\"\"`apply_effects_file` works on various vorbis format\"\"\"\n    #channels_first = True\n    #effects = [[\"band\", \"300\", \"10\"]]\n\n    #input_path = self.get_temp_path(\"input.vorbis\")\n    #reference_path = self.get_temp_path(\"reference.wav\")\n    #sox_utils.gen_audio_file(input_path, sample_rate, num_channels)\n    #sox_utils.run_sox_effect(input_path, reference_path, effects, output_bitdepth=32)\n\n    #expected, expected_sr = load_wav(reference_path)\n    #found, sr = sox_effects.apply_effects_file(input_path, effects, channels_first=channels_first)\n    #save_wav(self.get_temp_path(\"result.wav\"), found, sr, channels_first=channels_first)\n\n    #assert sr == expected_sr\n    ##self.assertEqual(found, expected)\n    #np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n\n    #@skipIfNoExec(\"sox\")\n    #@skipIfNoSox\nclass TestFileObject(TempDirMixin, unittest.TestCase):\n    @parameterized.expand([\n        (\"wav\", None),\n    ])\n    def test_fileobj(self, ext, compression):\n        \"\"\"Applying effects via file object works\"\"\"\n        sample_rate = 16000\n        channels_first = True\n        effects = [[\"band\", \"300\", \"10\"]]\n        input_path = self.get_temp_path(f\"input.{ext}\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n\n        #sox_utils.gen_audio_file(input_path, sample_rate, num_channels=2, compression=compression)\n        data = get_wav_data(\"int32\", 2, channels_first=channels_first)\n        save_wav(input_path, data, sample_rate, channels_first=channels_first)\n\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_bitdepth=32)\n        expected, expected_sr = load_wav(reference_path)\n\n        with open(input_path, \"rb\") as fileobj:\n            found, sr = sox_effects.apply_effects_file(\n                fileobj, effects, channels_first=channels_first)\n        save_wav(\n            self.get_temp_path(\"result.wav\"),\n            found,\n            sr,\n            channels_first=channels_first)\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n    @parameterized.expand([\n        (\"wav\", None),\n    ])\n    def test_bytesio(self, ext, compression):\n        \"\"\"Applying effects via BytesIO object works\"\"\"\n        sample_rate = 16000\n        channels_first = True\n        effects = [[\"band\", \"300\", \"10\"]]\n        input_path = self.get_temp_path(f\"input.{ext}\")\n        reference_path = self.get_temp_path(\"reference.wav\")\n\n        #sox_utils.gen_audio_file(input_path, sample_rate, num_channels=2, compression=compression)\n        data = get_wav_data(\"int32\", 2, channels_first=channels_first)\n        save_wav(input_path, data, sample_rate, channels_first=channels_first)\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_bitdepth=32)\n        expected, expected_sr = load_wav(reference_path)\n\n        with open(input_path, \"rb\") as file_:\n            fileobj = io.BytesIO(file_.read())\n        found, sr = sox_effects.apply_effects_file(\n            fileobj, effects, channels_first=channels_first)\n        save_wav(\n            self.get_temp_path(\"result.wav\"),\n            found,\n            sr,\n            channels_first=channels_first)\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        print(\"found\")\n        print(found)\n        print(\"expected\")\n        print(expected)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n    @parameterized.expand([\n        (\"wav\", None),\n    ])\n    def test_tarfile(self, ext, compression):\n        \"\"\"Applying effects to compressed audio via file-like file works\"\"\"\n        sample_rate = 16000\n        channels_first = True\n        effects = [[\"band\", \"300\", \"10\"]]\n        audio_file = f\"input.{ext}\"\n\n        input_path = self.get_temp_path(audio_file)\n        reference_path = self.get_temp_path(\"reference.wav\")\n        archive_path = self.get_temp_path(\"archive.tar.gz\")\n        data = get_wav_data(\"int32\", 2, channels_first=channels_first)\n        save_wav(input_path, data, sample_rate, channels_first=channels_first)\n\n        #       sox_utils.gen_audio_file(input_path, sample_rate, num_channels=2, compression=compression)\n        sox_utils.run_sox_effect(\n            input_path, reference_path, effects, output_bitdepth=32)\n\n        expected, expected_sr = load_wav(reference_path)\n\n        with tarfile.TarFile(archive_path, \"w\") as tarobj:\n            tarobj.add(input_path, arcname=audio_file)\n        with tarfile.TarFile(archive_path, \"r\") as tarobj:\n            fileobj = tarobj.extractfile(audio_file)\n            found, sr = sox_effects.apply_effects_file(\n                fileobj, effects, channels_first=channels_first)\n        save_wav(\n            self.get_temp_path(\"result.wav\"),\n            found,\n            sr,\n            channels_first=channels_first)\n        assert sr == expected_sr\n        #self.assertEqual(found, expected)\n        np.testing.assert_array_almost_equal(found.numpy(), expected.numpy())\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/backends/sox_io/sox_effect_test_args.jsonl",
    "content": "{\"effects\": [[\"allpass\", \"300\", \"10\"]]}\n{\"effects\": [[\"band\", \"300\", \"10\"]]}\n{\"effects\": [[\"bandpass\", \"300\", \"10\"]]}\n{\"effects\": [[\"bandreject\", \"300\", \"10\"]]}\n{\"effects\": [[\"bass\", \"-10\"]]}\n{\"effects\": [[\"biquad\", \"0.4\", \"0.2\", \"0.9\", \"0.7\", \"0.2\", \"0.6\"]]}\n{\"effects\": [[\"chorus\", \"0.7\", \"0.9\", \"55\", \"0.4\", \"0.25\", \"2\", \"-t\"]]}\n{\"effects\": [[\"chorus\", \"0.6\", \"0.9\", \"50\", \"0.4\", \"0.25\", \"2\", \"-t\", \"60\", \"0.32\", \"0.4\", \"1.3\", \"-s\"]]}\n{\"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\"]]}\n{\"effects\": [[\"channels\", \"1\"]]}\n{\"effects\": [[\"channels\", \"2\"]]}\n{\"effects\": [[\"channels\", \"3\"]]}\n{\"effects\": [[\"compand\", \"0.3,1\", \"6:-70,-60,-20\", \"-5\", \"-90\", \"0.2\"]]}\n{\"effects\": [[\"compand\", \".1,.2\", \"-inf,-50.1,-inf,-50,-50\", \"0\", \"-90\", \".1\"]]}\n{\"effects\": [[\"compand\", \".1,.1\", \"-45.1,-45,-inf,0,-inf\", \"45\", \"-90\", \".1\"]]}\n{\"effects\": [[\"contrast\", \"0\"]]}\n{\"effects\": [[\"contrast\", \"25\"]]}\n{\"effects\": [[\"contrast\", \"50\"]]}\n{\"effects\": [[\"contrast\", \"75\"]]}\n{\"effects\": [[\"contrast\", \"100\"]]}\n{\"effects\": [[\"dcshift\", \"1.0\"]]}\n{\"effects\": [[\"dcshift\", \"-1.0\"]]}\n{\"effects\": [[\"deemph\"]], \"input_sample_rate\": 44100}\n{\"effects\": [[\"dither\", \"-s\"]]}\n{\"effects\": [[\"dither\", \"-S\"]]}\n{\"effects\": [[\"divide\"]]}\n{\"effects\": [[\"downsample\", \"2\"]], \"input_sample_rate\": 8000, \"output_sample_rate\": 4000}\n{\"effects\": [[\"earwax\"]], \"input_sample_rate\": 44100}\n{\"effects\": [[\"echo\", \"0.8\", \"0.88\", \"60\", \"0.4\"]]}\n{\"effects\": [[\"echo\", \"0.8\", \"0.88\", \"6\", \"0.4\"]]}\n{\"effects\": [[\"echo\", \"0.8\", \"0.9\", \"1000\", \"0.3\"]]}\n{\"effects\": [[\"echo\", \"0.8\", \"0.9\", \"1000\", \"0.3\", \"1800\", \"0.25\"]]}\n{\"effects\": [[\"echos\", \"0.8\", \"0.7\", \"700\", \"0.25\", \"700\", \"0.3\"]]}\n{\"effects\": [[\"echos\", \"0.8\", \"0.7\", \"700\", \"0.25\", \"900\", \"0.3\"]]}\n{\"effects\": [[\"echos\", \"0.8\", \"0.7\", \"40\", \"0.25\", \"63\", \"0.3\"]]}\n{\"effects\": [[\"equalizer\", \"300\", \"10\", \"5\"]]}\n{\"effects\": [[\"fade\", \"q\", \"3\"]]}\n{\"effects\": [[\"fade\", \"h\", \"3\"]]}\n{\"effects\": [[\"fade\", \"t\", \"3\"]]}\n{\"effects\": [[\"fade\", \"l\", \"3\"]]}\n{\"effects\": [[\"fade\", \"p\", \"3\"]]}\n{\"effects\": [[\"fir\", \"0.0195\", \"-0.082\", \"0.234\", \"0.891\", \"-0.145\", \"0.043\"]]}\n{\"effects\": [[\"flanger\"]]}\n{\"effects\": [[\"gain\", \"-l\", \"-6\"]]}\n{\"effects\": [[\"highpass\", \"-1\", \"300\"]]}\n{\"effects\": [[\"highpass\", \"-2\", \"300\"]]}\n{\"effects\": [[\"hilbert\"]]}\n{\"effects\": [[\"loudness\"]]}\n{\"effects\": [[\"lowpass\", \"-1\", \"300\"]]}\n{\"effects\": [[\"lowpass\", \"-2\", \"300\"]]}\n{\"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}\n{\"effects\": [[\"oops\"]]}\n{\"effects\": [[\"overdrive\"]]}\n{\"effects\": [[\"pad\"]]}\n{\"effects\": [[\"phaser\"]]}\n{\"effects\": [[\"remix\", \"6\", \"7\", \"8\", \"0\"]], \"num_channels\": 8}\n{\"effects\": [[\"remix\", \"1-3,7\", \"3\"]], \"num_channels\": 8}\n{\"effects\": [[\"repeat\"]]}\n{\"effects\": [[\"reverb\"]]}\n{\"effects\": [[\"reverse\"]]}\n{\"effects\": [[\"riaa\"]], \"input_sample_rate\": 44100}\n{\"effects\": [[\"silence\", \"0\"]]}\n{\"effects\": [[\"speed\", \"1.3\"]], \"input_sample_rate\": 4000, \"output_sample_rate\": 5200}\n{\"effects\": [[\"speed\", \"0.7\"]], \"input_sample_rate\": 4000, \"output_sample_rate\": 2800}\n{\"effects\": [[\"stat\"]]}\n{\"effects\": [[\"stats\"]]}\n{\"effects\": [[\"stretch\"]]}\n{\"effects\": [[\"swap\"]]}\n{\"effects\": [[\"synth\"]]}\n{\"effects\": [[\"tempo\", \"0.9\"]]}\n{\"effects\": [[\"tempo\", \"1.1\"]]}\n{\"effects\": [[\"treble\", \"3\"]]}\n{\"effects\": [[\"tremolo\", \"300\", \"40\"]]}\n{\"effects\": [[\"tremolo\", \"300\", \"50\"]]}\n{\"effects\": [[\"trim\", \"0\", \"0.1\"]]}\n{\"effects\": [[\"upsample\", \"2\"]], \"input_sample_rate\": 8000, \"output_sample_rate\": 16000}\n{\"effects\": [[\"vol\", \"3\"]]}\n"
  },
  {
    "path": "audio/tests/benchmark/README.md",
    "content": "# 1. Prepare\nFirst, install `pytest-benchmark` via pip.\n```sh\npip install pytest-benchmark\n```\n\n# 2. Run\nRun the specific script for profiling.\n```sh\npytest melspectrogram.py\n```\n\nResult:\n```sh\n========================================================================== test session starts ==========================================================================\nplatform linux -- Python 3.7.7, pytest-7.0.1, pluggy-1.0.0\nbenchmark: 3.4.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)\nrootdir: /ssd3/chenxiaojie06/PaddleSpeech/DeepSpeech/paddleaudio\nplugins: typeguard-2.12.1, benchmark-3.4.1, anyio-3.5.0\ncollected 4 items\n\nmelspectrogram.py ....                                                                                                                                            [100%]\n\n\n-------------------------------------------------------------------------------------------------- benchmark: 4 tests -------------------------------------------------------------------------------------------------\nName (time in us)                        Min                    Max                   Mean              StdDev                 Median                 IQR            Outliers         OPS            Rounds  Iterations\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_melspect_gpu_torchaudio        202.0765 (1.0)         360.6230 (1.0)         218.1168 (1.0)       16.3022 (1.0)         214.2871 (1.0)       21.8451 (1.0)          40;3  4,584.7001 (1.0)         286           1\ntest_melspect_gpu                   657.8509 (3.26)        908.0470 (2.52)        724.2545 (3.32)     106.5771 (6.54)        669.9096 (3.13)     113.4719 (5.19)          1;0  1,380.7300 (0.30)          5           1\ntest_melspect_cpu_torchaudio      1,247.6053 (6.17)      2,892.5799 (8.02)      1,443.2853 (6.62)     345.3732 (21.19)     1,262.7263 (5.89)     221.6385 (10.15)       56;53    692.8637 (0.15)        399           1\ntest_melspect_cpu                20,326.2549 (100.59)   20,607.8682 (57.15)    20,473.4125 (93.86)     63.8654 (3.92)     20,467.0429 (95.51)     68.4294 (3.13)          8;1     48.8438 (0.01)         29           1\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nLegend:\n  Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile.\n  OPS: Operations Per Second, computed as 1 / Mean\n========================================================================== 4 passed in 21.12s ===========================================================================\n\n```\n"
  },
  {
    "path": "audio/tests/benchmark/log_melspectrogram.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport urllib.request\n\nimport librosa\nimport numpy as np\nimport paddle\nimport paddleaudio\nimport torch\nimport torchaudio\n\nwav_url = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\nif not os.path.isfile(os.path.basename(wav_url)):\n    urllib.request.urlretrieve(wav_url, os.path.basename(wav_url))\n\nwaveform, sr = paddleaudio.backends.soundfile_load(\n    os.path.abspath(os.path.basename(wav_url)))\nwaveform_tensor = paddle.to_tensor(waveform).unsqueeze(0)\nwaveform_tensor_torch = torch.from_numpy(waveform).unsqueeze(0)\n\n# Feature conf\nmel_conf = {\n    'sr': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n}\n\nmel_conf_torchaudio = {\n    'sample_rate': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n    'norm': 'slaney',\n    'mel_scale': 'slaney',\n}\n\n\ndef enable_cpu_device():\n    paddle.set_device('cpu')\n\n\ndef enable_gpu_device():\n    paddle.set_device('gpu')\n\n\nlog_mel_extractor = paddle.audio.features.LogMelSpectrogram(\n    **mel_conf, f_min=0.0, top_db=80.0, dtype=waveform_tensor.dtype)\n\n\ndef log_melspectrogram():\n    return log_mel_extractor(waveform_tensor).squeeze(0)\n\n\ndef test_log_melspect_cpu(benchmark):\n    enable_cpu_device()\n    feature_paddleaudio = benchmark(log_melspectrogram)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    feature_librosa = librosa.power_to_db(feature_librosa, top_db=80.0)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_log_melspect_gpu(benchmark):\n    enable_gpu_device()\n    feature_paddleaudio = benchmark(log_melspectrogram)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    feature_librosa = librosa.power_to_db(feature_librosa, top_db=80.0)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=2)\n\n\nmel_extractor_torchaudio = torchaudio.transforms.MelSpectrogram(\n    **mel_conf_torchaudio, f_min=0.0)\namplitude_to_DB = torchaudio.transforms.AmplitudeToDB('power', top_db=80.0)\n\n\ndef melspectrogram_torchaudio():\n    return mel_extractor_torchaudio(waveform_tensor_torch).squeeze(0)\n\n\ndef log_melspectrogram_torchaudio():\n    mel_specgram = mel_extractor_torchaudio(waveform_tensor_torch)\n    return amplitude_to_DB(mel_specgram).squeeze(0)\n\n\ndef test_log_melspect_cpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mel_extractor_torchaudio, amplitude_to_DB\n\n    mel_extractor_torchaudio = mel_extractor_torchaudio.to('cpu')\n    waveform_tensor_torch = waveform_tensor_torch.to('cpu')\n    amplitude_to_DB = amplitude_to_DB.to('cpu')\n\n    feature_paddleaudio = benchmark(log_melspectrogram_torchaudio)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    feature_librosa = librosa.power_to_db(feature_librosa, top_db=80.0)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_log_melspect_gpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mel_extractor_torchaudio, amplitude_to_DB\n\n    mel_extractor_torchaudio = mel_extractor_torchaudio.to('cuda')\n    waveform_tensor_torch = waveform_tensor_torch.to('cuda')\n    amplitude_to_DB = amplitude_to_DB.to('cuda')\n\n    feature_torchaudio = benchmark(log_melspectrogram_torchaudio)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    feature_librosa = librosa.power_to_db(feature_librosa, top_db=80.0)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_torchaudio.cpu(), decimal=2)\n"
  },
  {
    "path": "audio/tests/benchmark/melspectrogram.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport urllib.request\n\nimport librosa\nimport numpy as np\nimport paddle\nimport paddleaudio\nimport torch\nimport torchaudio\n\nwav_url = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\nif not os.path.isfile(os.path.basename(wav_url)):\n    urllib.request.urlretrieve(wav_url, os.path.basename(wav_url))\n\nwaveform, sr = paddleaudio.backends.soundfile_load(\n    os.path.abspath(os.path.basename(wav_url)))\nwaveform_tensor = paddle.to_tensor(waveform).unsqueeze(0)\nwaveform_tensor_torch = torch.from_numpy(waveform).unsqueeze(0)\n\n# Feature conf\nmel_conf = {\n    'sr': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n}\n\nmel_conf_torchaudio = {\n    'sample_rate': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n    'norm': 'slaney',\n    'mel_scale': 'slaney',\n}\n\n\ndef enable_cpu_device():\n    paddle.set_device('cpu')\n\n\ndef enable_gpu_device():\n    paddle.set_device('gpu')\n\n\nmel_extractor = paddle.audio.features.MelSpectrogram(\n    **mel_conf, f_min=0.0, dtype=waveform_tensor.dtype)\n\n\ndef melspectrogram():\n    return mel_extractor(waveform_tensor).squeeze(0)\n\n\ndef test_melspect_cpu(benchmark):\n    enable_cpu_device()\n    feature_paddleaudio = benchmark(melspectrogram)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_melspect_gpu(benchmark):\n    enable_gpu_device()\n    feature_paddleaudio = benchmark(melspectrogram)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\nmel_extractor_torchaudio = torchaudio.transforms.MelSpectrogram(\n    **mel_conf_torchaudio, f_min=0.0)\n\n\ndef melspectrogram_torchaudio():\n    return mel_extractor_torchaudio(waveform_tensor_torch).squeeze(0)\n\n\ndef test_melspect_cpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mel_extractor_torchaudio\n    mel_extractor_torchaudio = mel_extractor_torchaudio.to('cpu')\n    waveform_tensor_torch = waveform_tensor_torch.to('cpu')\n    feature_paddleaudio = benchmark(melspectrogram_torchaudio)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_melspect_gpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mel_extractor_torchaudio\n    mel_extractor_torchaudio = mel_extractor_torchaudio.to('cuda')\n    waveform_tensor_torch = waveform_tensor_torch.to('cuda')\n    feature_torchaudio = benchmark(melspectrogram_torchaudio)\n    feature_librosa = librosa.feature.melspectrogram(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_torchaudio.cpu(), decimal=3)\n"
  },
  {
    "path": "audio/tests/benchmark/mfcc.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport urllib.request\n\nimport librosa\nimport numpy as np\nimport paddle\nimport paddleaudio\nimport torch\nimport torchaudio\n\nwav_url = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\nif not os.path.isfile(os.path.basename(wav_url)):\n    urllib.request.urlretrieve(wav_url, os.path.basename(wav_url))\n\nwaveform, sr = paddleaudio.backends.soundfile_load(\n    os.path.abspath(os.path.basename(wav_url)))\nwaveform_tensor = paddle.to_tensor(waveform).unsqueeze(0)\nwaveform_tensor_torch = torch.from_numpy(waveform).unsqueeze(0)\n\n# Feature conf\nmel_conf = {\n    'sr': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n}\nmfcc_conf = {\n    'n_mfcc': 20,\n    'top_db': 80.0,\n}\nmfcc_conf.update(mel_conf)\n\nmel_conf_torchaudio = {\n    'sample_rate': sr,\n    'n_fft': 512,\n    'hop_length': 128,\n    'n_mels': 40,\n    'norm': 'slaney',\n    'mel_scale': 'slaney',\n}\nmfcc_conf_torchaudio = {\n    'sample_rate': sr,\n    'n_mfcc': 20,\n}\n\n\ndef enable_cpu_device():\n    paddle.set_device('cpu')\n\n\ndef enable_gpu_device():\n    paddle.set_device('gpu')\n\n\nmfcc_extractor = paddle.audio.features.MFCC(\n    **mfcc_conf, f_min=0.0, dtype=waveform_tensor.dtype)\n\n\ndef mfcc():\n    return mfcc_extractor(waveform_tensor).squeeze(0)\n\n\ndef test_mfcc_cpu(benchmark):\n    enable_cpu_device()\n    feature_paddleaudio = benchmark(mfcc)\n    feature_librosa = librosa.feature.mfcc(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_mfcc_gpu(benchmark):\n    enable_gpu_device()\n    feature_paddleaudio = benchmark(mfcc)\n    feature_librosa = librosa.feature.mfcc(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndel mel_conf_torchaudio['sample_rate']\nmfcc_extractor_torchaudio = torchaudio.transforms.MFCC(\n    **mfcc_conf_torchaudio, melkwargs=mel_conf_torchaudio)\n\n\ndef mfcc_torchaudio():\n    return mfcc_extractor_torchaudio(waveform_tensor_torch).squeeze(0)\n\n\ndef test_mfcc_cpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mfcc_extractor_torchaudio\n\n    mel_extractor_torchaudio = mfcc_extractor_torchaudio.to('cpu')\n    waveform_tensor_torch = waveform_tensor_torch.to('cpu')\n\n    feature_paddleaudio = benchmark(mfcc_torchaudio)\n    feature_librosa = librosa.feature.mfcc(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_paddleaudio, decimal=3)\n\n\ndef test_mfcc_gpu_torchaudio(benchmark):\n    global waveform_tensor_torch, mfcc_extractor_torchaudio\n\n    mel_extractor_torchaudio = mfcc_extractor_torchaudio.to('cuda')\n    waveform_tensor_torch = waveform_tensor_torch.to('cuda')\n\n    feature_torchaudio = benchmark(mfcc_torchaudio)\n    feature_librosa = librosa.feature.mfcc(waveform, **mel_conf)\n    np.testing.assert_array_almost_equal(\n        feature_librosa, feature_torchaudio.cpu(), decimal=3)\n"
  },
  {
    "path": "audio/tests/common_utils/__init__.py",
    "content": "from .case_utils import name_func\nfrom .case_utils import TempDirMixin\nfrom .data_utils import get_sinusoid\nfrom .data_utils import load_effects_params\nfrom .data_utils import load_params\nfrom .parameterized_utils import nested_params\nfrom .wav_utils import get_wav_data\nfrom .wav_utils import load_wav\nfrom .wav_utils import normalize_wav\nfrom .wav_utils import save_wav\n\n__all__ = [\n    \"get_wav_data\", \"load_wav\", \"save_wav\", \"normalize_wav\", \"load_params\",\n    \"nested_params\", \"get_sinusoid\", \"name_func\", \"load_effects_params\"\n]\n"
  },
  {
    "path": "audio/tests/common_utils/case_utils.py",
    "content": "import os.path\nimport tempfile\n\n#code is from:https://github.com/pytorch/audio/blob/main/test/torchaudio_unittest/common_utils/case_utils.py\n\n\ndef name_func(func, _, params):\n    return f'{func.__name__}_{\"_\".join(str(arg) for arg in params.args)}'\n\n\nclass TempDirMixin:\n    \"\"\"Mixin to provide easy access to temp dir\"\"\"\n\n    temp_dir_ = None\n\n    @classmethod\n    def get_base_temp_dir(cls):\n        # If PADDLEAUDIO_TEST_TEMP_DIR is set, use it instead of temporary directory.\n        # this is handy for debugging.\n        key = \"PADDLEAUDIO_TEST_TEMP_DIR\"\n        if key in os.environ:\n            return os.environ[key]\n        if cls.temp_dir_ is None:\n            cls.temp_dir_ = tempfile.TemporaryDirectory()\n        return cls.temp_dir_.name\n\n    @classmethod\n    def tearDownClass(cls):\n        if cls.temp_dir_ is not None:\n            try:\n                cls.temp_dir_.cleanup()\n                cls.temp_dir_ = None\n            except PermissionError:\n                # On Windows there is a know issue with `shutil.rmtree`,\n                # which fails intermittenly.\n                #\n                # https://github.com/python/cpython/issues/74168\n                #\n                # We observed this on CircleCI, where Windows job raises\n                # PermissionError.\n                #\n                # Following the above thread, we ignore it.\n                pass\n        super().tearDownClass()\n\n    def get_temp_path(self, *paths):\n        temp_dir = os.path.join(self.get_base_temp_dir(), self.id())\n        path = os.path.join(temp_dir, *paths)\n        os.makedirs(os.path.dirname(path), exist_ok=True)\n        return path\n"
  },
  {
    "path": "audio/tests/common_utils/data_utils.py",
    "content": "import json\nimport os.path\n\nimport paddle\nfrom parameterized import param\n#code is from:https://github.com/pytorch/audio/blob/main/test/torchaudio_unittest/common_utils/data_utils.py with modification.\n\n_TEST_DIR_PATH = os.path.realpath(os.path.join(os.path.dirname(__file__), \"..\"))\n\n\ndef get_asset_path(*paths):\n    \"\"\"Return full path of a test asset\"\"\"\n    return os.path.join(_TEST_DIR_PATH, \"assets\", *paths)\n\n\ndef load_params(*paths):\n    with open(get_asset_path(*paths), \"r\") as file:\n        return [param(json.loads(line)) for line in file]\n\n\ndef load_effects_params(*paths):\n    params = []\n    with open(*paths, \"r\") as file:\n        for line in file:\n            data = json.loads(line)\n            for effect in data[\"effects\"]:\n                for i, arg in enumerate(effect):\n                    if arg.startswith(\"<ASSET_DIR>\"):\n                        effect[i] = arg.replace(\"<ASSET_DIR>\", get_asset_path())\n            params.append(param(data))\n    return params\n\n\ndef convert_tensor_encoding(\n        tensor: paddle.tensor,\n        dtype: paddle.dtype, ):\n    \"\"\"Convert input tensor with values between -1 and 1 to integer encoding\n    Args:\n        tensor: input tensor, assumed between -1 and 1\n        dtype: desired output tensor dtype\n    Returns:\n        Tensor: shape of (n_channels, sample_rate * duration)\n    \"\"\"\n    if dtype == paddle.int32:\n        tensor *= (tensor > 0) * 2147483647 + (tensor < 0) * 2147483648\n    if dtype == paddle.int16:\n        tensor *= (tensor > 0) * 32767 + (tensor < 0) * 32768\n    if dtype == paddle.uint8:\n        tensor *= (tensor > 0) * 127 + (tensor < 0) * 128\n        tensor += 128\n    tensor = paddle.to_tensor(tensor, dtype)\n    return tensor\n\n\n#def get_whitenoise(\n#*,\n#sample_rate: int = 16000,\n#duration: float = 1,  # seconds\n#n_channels: int = 1,\n#seed: int = 0,\n#dtype: Union[str, paddle.dtype] = \"float32\",\n#device: Union[str, paddle.device] = \"cpu\",\n#channels_first=True,\n#scale_factor: float = 1,\n#):\n#\"\"\"Generate pseudo audio data with whitenoise\n#Args:\n#sample_rate: Sampling rate\n#duration: Length of the resulting Tensor in seconds.\n#n_channels: Number of channels\n#seed: Seed value used for random number generation.\n#Note that this function does not modify global random generator state.\n#dtype: Torch dtype\n#device: device\n#channels_first: whether first dimension is n_channels\n#scale_factor: scale the Tensor before clamping and quantization\n#Returns:\n#Tensor: shape of (n_channels, sample_rate * duration)\n#\"\"\"\n#if isinstance(dtype, str):\n#dtype = getattr(paddle, dtype)\n#if dtype not in [paddle.float64, paddle.float32, paddle.int32, paddle.int16, paddle.uint8]:\n#raise NotImplementedError(f\"dtype {dtype} is not supported.\")\n## According to the doc, forking rng on all CUDA devices is slow when there are many CUDA devices,\n## so we only fork on CPU, generate values and move the data to the given device\n#with paddle.random.fork_rng([]):\n#paddle.random.manual_seed(seed)\n#tensor = paddle.randn([n_channels, int(sample_rate * duration)], dtype=paddle.float32, device=\"cpu\")\n#tensor /= 2.0\n#tensor *= scale_factor\n#tensor.clamp_(-1.0, 1.0)\n#if not channels_first:\n#tensor = tensor.t()\n\n#tensor = tensor.to(device)\n\n#return convert_tensor_encoding(tensor, dtype)\n\n\ndef get_sinusoid(\n        *,\n        frequency: float=300,\n        sample_rate: int=16000,\n        duration: float=1,  # seconds\n        n_channels: int=1,\n        dtype: str=\"float32\",\n        device: str=\"cpu\",\n        channels_first: bool=True, ):\n    \"\"\"Generate pseudo audio data with sine wave.\n\n    Args:\n        frequency: Frequency of sine wave\n        sample_rate: Sampling rate\n        duration: Length of the resulting Tensor in seconds.\n        n_channels: Number of channels\n        dtype: Torch dtype\n        device: device\n\n    Returns:\n        Tensor: shape of (n_channels, sample_rate * duration)\n    \"\"\"\n    if isinstance(dtype, str):\n        dtype = getattr(paddle, dtype)\n    pie2 = 2 * 3.141592653589793\n    end = pie2 * frequency * duration\n    num_frames = int(sample_rate * duration)\n    # Randomize the initial phase. (except the first channel)\n    theta0 = pie2 * paddle.randn([n_channels, 1], dtype=paddle.float32)\n    theta0[0, :] = 0\n    theta = paddle.linspace(0, end, num_frames, dtype=paddle.float32)\n    theta = theta0 + theta\n    tensor = paddle.sin(theta)\n    if not channels_first:\n        tensor = paddle.t(tensor)\n    return convert_tensor_encoding(tensor, dtype)\n"
  },
  {
    "path": "audio/tests/common_utils/parameterized_utils.py",
    "content": "from itertools import product\n\nfrom parameterized import param\nfrom parameterized import parameterized\n\n\ndef _name_func(func, _, params):\n    strs = []\n    for arg in params.args:\n        if isinstance(arg, tuple):\n            strs.append(\"_\".join(str(a) for a in arg))\n        else:\n            strs.append(str(arg))\n    # sanitize the test name\n    name = \"_\".join(strs)\n    return parameterized.to_safe_name(f\"{func.__name__}_{name}\")\n\n\ndef nested_params(*params_set, name_func=_name_func):\n    \"\"\"Generate the cartesian product of the given list of parameters.\n\n    Args:\n        params_set (list of parameters): Parameters. When using ``parameterized.param`` class,\n            all the parameters have to be specified with the class, only using kwargs.\n    \"\"\"\n    flatten = [p for params in params_set for p in params]\n\n    # Parameters to be nested are given as list of plain objects\n    if all(not isinstance(p, param) for p in flatten):\n        args = list(product(*params_set))\n        return parameterized.expand(args, name_func=_name_func)\n\n    # Parameters to be nested are given as list of `parameterized.param`\n    if not all(isinstance(p, param) for p in flatten):\n        raise TypeError(\"When using ``parameterized.param``, \"\n                        \"all the parameters have to be of the ``param`` type.\")\n    if any(p.args for p in flatten):\n        raise ValueError(\n            \"When using ``parameterized.param``, \"\n            \"all the parameters have to be provided as keyword argument.\")\n    args = [param()]\n    for params in params_set:\n        args = [param(**x.kwargs, **y.kwargs) for x in args for y in params]\n    return parameterized.expand(args)\n"
  },
  {
    "path": "audio/tests/common_utils/sox_utils.py",
    "content": "import subprocess\nimport sys\nimport warnings\n\n\ndef get_encoding(dtype):\n    encodings = {\n        \"float32\": \"floating-point\",\n        \"int32\": \"signed-integer\",\n        \"int16\": \"signed-integer\",\n        \"uint8\": \"unsigned-integer\",\n    }\n    return encodings[dtype]\n\n\ndef get_bit_depth(dtype):\n    bit_depths = {\n        \"float32\": 32,\n        \"int32\": 32,\n        \"int16\": 16,\n        \"uint8\": 8,\n    }\n    return bit_depths[dtype]\n\n\ndef gen_audio_file(\n        path,\n        sample_rate,\n        num_channels,\n        *,\n        encoding=None,\n        bit_depth=None,\n        compression=None,\n        attenuation=None,\n        duration=1,\n        comment_file=None, ):\n    \"\"\"Generate synthetic audio file with `sox` command.\"\"\"\n    if path.endswith(\".wav\"):\n        warnings.warn(\n            \"Use get_wav_data and save_wav to generate wav file for accurate result.\"\n        )\n    command = [\n        \"sox\",\n        \"-V3\",  # verbose\n        \"--no-dither\",  # disable automatic dithering\n        \"-R\",\n        # -R is supposed to be repeatable, though the implementation looks suspicious\n        # and not setting the seed to a fixed value.\n        # https://fossies.org/dox/sox-14.4.2/sox_8c_source.html\n        # search \"sox_globals.repeatable\"\n    ]\n    if bit_depth is not None:\n        command += [\"--bits\", str(bit_depth)]\n    command += [\n        \"--rate\",\n        str(sample_rate),\n        \"--null\",  # no input\n        \"--channels\",\n        str(num_channels),\n    ]\n    if compression is not None:\n        command += [\"--compression\", str(compression)]\n    if bit_depth is not None:\n        command += [\"--bits\", str(bit_depth)]\n    if encoding is not None:\n        command += [\"--encoding\", str(encoding)]\n    if comment_file is not None:\n        command += [\"--comment-file\", str(comment_file)]\n    command += [\n        str(path),\n        \"synth\",\n        str(duration),  # synthesizes for the given duration [sec]\n        \"sawtooth\",\n        \"1\",\n        # saw tooth covers the both ends of value range, which is a good property for test.\n        # similar to linspace(-1., 1.)\n        # this introduces bigger boundary effect than sine when converted to mp3\n    ]\n    if attenuation is not None:\n        command += [\"vol\", f\"-{attenuation}dB\"]\n    print(\" \".join(command), file=sys.stderr)\n    subprocess.run(command, check=True)\n\n\ndef convert_audio_file(src_path,\n                       dst_path,\n                       *,\n                       encoding=None,\n                       bit_depth=None,\n                       compression=None):\n    \"\"\"Convert audio file with `sox` command.\"\"\"\n    command = [\"sox\", \"-V3\", \"--no-dither\", \"-R\", str(src_path)]\n    if encoding is not None:\n        command += [\"--encoding\", str(encoding)]\n    if bit_depth is not None:\n        command += [\"--bits\", str(bit_depth)]\n    if compression is not None:\n        command += [\"--compression\", str(compression)]\n    command += [dst_path]\n    print(\" \".join(command), file=sys.stderr)\n    subprocess.run(command, check=True)\n\n\ndef _flatten(effects):\n    if not effects:\n        return effects\n    if isinstance(effects[0], str):\n        return effects\n    return [item for sublist in effects for item in sublist]\n\n\ndef run_sox_effect(input_file,\n                   output_file,\n                   effect,\n                   *,\n                   output_sample_rate=None,\n                   output_bitdepth=None):\n    \"\"\"Run sox effects\"\"\"\n    effect = _flatten(effect)\n    command = [\"sox\", \"-V\", \"--no-dither\", input_file]\n    if output_bitdepth:\n        command += [\"--bits\", str(output_bitdepth)]\n    command += [output_file] + effect\n    if output_sample_rate:\n        command += [\"rate\", str(output_sample_rate)]\n    print(\" \".join(command))\n    subprocess.run(command, check=True)\n"
  },
  {
    "path": "audio/tests/common_utils/wav_utils.py",
    "content": "from typing import Optional\n\nimport paddle\nimport scipy.io.wavfile\n\n\ndef normalize_wav(tensor: paddle.Tensor) -> paddle.Tensor:\n    if tensor.dtype == paddle.float32:\n        pass\n    elif tensor.dtype == paddle.int32:\n        tensor = paddle.cast(tensor, paddle.float32)\n        tensor[tensor > 0] /= 2147483647.0\n        tensor[tensor < 0] /= 2147483648.0\n    elif tensor.dtype == paddle.int16:\n        tensor = paddle.cast(tensor, paddle.float32)\n        tensor[tensor > 0] /= 32767.0\n        tensor[tensor < 0] /= 32768.0\n    elif tensor.dtype == paddle.uint8:\n        tensor = paddle.cast(tensor, paddle.float32) - 128\n        tensor[tensor > 0] /= 127.0\n        tensor[tensor < 0] /= 128.0\n    return tensor\n\n\ndef get_wav_data(\n        dtype: str,\n        num_channels: int,\n        *,\n        num_frames: Optional[int]=None,\n        normalize: bool=True,\n        channels_first: bool=True, ):\n    \"\"\"Generate linear signal of the given dtype and num_channels\n\n    Data range is\n        [-1.0, 1.0] for float32,\n        [-2147483648, 2147483647] for int32\n        [-32768, 32767] for int16\n        [0, 255] for uint8\n\n    num_frames allow to change the linear interpolation parameter.\n    Default values are 256 for uint8, else 1 << 16.\n    1 << 16 as default is so that int16 value range is completely covered.\n    \"\"\"\n    dtype_ = getattr(paddle, dtype)\n\n    if num_frames is None:\n        if dtype == \"uint8\":\n            num_frames = 256\n        else:\n            num_frames = 1 << 16\n\n    # paddle linspace not support uint8, int8, int16\n    #if dtype == \"uint8\":\n    #    base = paddle.linspace(0, 255, num_frames, dtype=dtype_)\n    #dtype_np = getattr(np, dtype)\n    #base_np = np.linspace(0, 255, num_frames, dtype_np)\n    #base = paddle.to_tensor(base_np, dtype=dtype_)\n    #elif dtype == \"int8\":\n    #    base = paddle.linspace(-128, 127, num_frames, dtype=dtype_)\n    #dtype_np = getattr(np, dtype)\n    #base_np = np.linspace(-128, 127, num_frames, dtype_np)\n    #base = paddle.to_tensor(base_np, dtype=dtype_)\n    if dtype == \"float32\":\n        base = paddle.linspace(-1.0, 1.0, num_frames, dtype=dtype_)\n    elif dtype == \"float64\":\n        base = paddle.linspace(-1.0, 1.0, num_frames, dtype=dtype_)\n    elif dtype == \"int32\":\n        base = paddle.linspace(\n            -2147483648, 2147483647, num_frames, dtype=dtype_)\n    #elif dtype == \"int16\":\n    #    base = paddle.linspace(-32768, 32767, num_frames, dtype=dtype_)\n    #dtype_np = getattr(np, dtype)\n    #base_np = np.linspace(-32768, 32767, num_frames, dtype_np)\n    #base = paddle.to_tensor(base_np, dtype=dtype_)\n    else:\n        raise NotImplementedError(f\"Unsupported dtype {dtype}\")\n    data = base.tile([num_channels, 1])\n    if not channels_first:\n        data = data.transpose([1, 0])\n    if normalize:\n        data = normalize_wav(data)\n    return data\n\n\ndef load_wav(path: str, normalize=True, channels_first=True) -> paddle.Tensor:\n    \"\"\"Load wav file without paddleaudio\"\"\"\n    sample_rate, data = scipy.io.wavfile.read(path)\n    data = paddle.to_tensor(data.copy())\n    if data.ndim == 1:\n        data = data.unsqueeze(1)\n    if normalize:\n        data = normalize_wav(data)\n    if channels_first:\n        data = data.transpose([1, 0])\n    return data, sample_rate\n\n\ndef save_wav(path, data, sample_rate, channels_first=True):\n    \"\"\"Save wav file without paddleaudio\"\"\"\n    if channels_first:\n        data = data.transpose([1, 0])\n    scipy.io.wavfile.write(path, sample_rate, data.numpy())\n"
  },
  {
    "path": "audio/tests/features/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "audio/tests/features/base.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport unittest\nimport urllib.request\n\nimport numpy as np\nimport paddle\nfrom paddleaudio.backends import soundfile_load as load\n\nwav_url = 'https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav'\n\n\nclass FeatTest(unittest.TestCase):\n    def setUp(self):\n        self.initParams()\n        self.initWavInput()\n        self.setUpDevice()\n\n    def setUpDevice(self, device='cpu'):\n        paddle.set_device(device)\n\n    def initWavInput(self, url=wav_url):\n        if not os.path.isfile(os.path.basename(url)):\n            urllib.request.urlretrieve(url, os.path.basename(url))\n        self.waveform, self.sr = load(os.path.abspath(os.path.basename(url)))\n        self.waveform = self.waveform.astype(\n            np.float32\n        )  # paddlespeech.audio.transform.spectrogram only supports float32\n        dim = len(self.waveform.shape)\n\n        assert dim in [1, 2]\n        if dim == 1:\n            self.waveform = np.expand_dims(self.waveform, 0)\n\n    def initParams(self):\n        raise NotImplementedError\n"
  },
  {
    "path": "audio/tests/features/test_istft.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport numpy as np\nimport paddle\nfrom paddleaudio.functional.window import get_window\n\nfrom .base import FeatTest\nfrom paddlespeech.audio.transform.spectrogram import IStft\nfrom paddlespeech.audio.transform.spectrogram import Stft\n\n\nclass TestIstft(FeatTest):\n    def initParams(self):\n        self.n_fft = 512\n        self.hop_length = 128\n        self.window_str = 'hann'\n\n    def test_istft(self):\n        ps_stft = Stft(self.n_fft, self.hop_length)\n        ps_res = ps_stft(\n            self.waveform.T).squeeze(1).T  # (n_fft//2 + 1, n_frmaes)\n        x = paddle.to_tensor(ps_res)\n\n        ps_istft = IStft(self.hop_length)\n        ps_res = ps_istft(ps_res.T)\n\n        window = get_window(\n            self.window_str, self.n_fft, dtype=self.waveform.dtype)\n        pd_res = paddle.signal.istft(\n            x, self.n_fft, self.hop_length, window=window)\n\n        np.testing.assert_array_almost_equal(ps_res, pd_res, decimal=5)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_kaldi.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport numpy as np\nimport paddle\nimport paddleaudio\nimport torch\nimport torchaudio\nfrom base import FeatTest\n\n\nclass TestKaldi(FeatTest):\n    def initParams(self):\n        self.window_size = 1024\n        self.dtype = 'float32'\n\n    def test_window(self):\n        t_hann_window = torch.hann_window(\n            self.window_size, periodic=False, dtype=eval(f'torch.{self.dtype}'))\n        t_hamm_window = torch.hamming_window(\n            self.window_size,\n            periodic=False,\n            alpha=0.54,\n            beta=0.46,\n            dtype=eval(f'torch.{self.dtype}'))\n        t_povey_window = torch.hann_window(\n            self.window_size, periodic=False,\n            dtype=eval(f'torch.{self.dtype}')).pow(0.85)\n\n        p_hann_window = paddleaudio.functional.window.get_window(\n            'hann',\n            self.window_size,\n            fftbins=False,\n            dtype=eval(f'paddle.{self.dtype}'))\n        p_hamm_window = paddleaudio.functional.window.get_window(\n            'hamming',\n            self.window_size,\n            fftbins=False,\n            dtype=eval(f'paddle.{self.dtype}'))\n        p_povey_window = paddleaudio.functional.window.get_window(\n            'hann',\n            self.window_size,\n            fftbins=False,\n            dtype=eval(f'paddle.{self.dtype}')).pow(0.85)\n\n        np.testing.assert_array_almost_equal(t_hann_window, p_hann_window)\n        np.testing.assert_array_almost_equal(t_hamm_window, p_hamm_window)\n        np.testing.assert_array_almost_equal(t_povey_window, p_povey_window)\n\n    def test_fbank(self):\n        ta_features = torchaudio.compliance.kaldi.fbank(\n            torch.from_numpy(self.waveform.astype(self.dtype)))\n        pa_features = paddleaudio.compliance.kaldi.fbank(\n            paddle.to_tensor(self.waveform.astype(self.dtype)))\n        np.testing.assert_array_almost_equal(\n            ta_features, pa_features, decimal=4)\n\n    def test_mfcc(self):\n        ta_features = torchaudio.compliance.kaldi.mfcc(\n            torch.from_numpy(self.waveform.astype(self.dtype)))\n        pa_features = paddleaudio.compliance.kaldi.mfcc(\n            paddle.to_tensor(self.waveform.astype(self.dtype)))\n        np.testing.assert_array_almost_equal(\n            ta_features, pa_features, decimal=4)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_kaldi_feat.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#import platform\nimport unittest\n\nimport kaldiio\nimport numpy as np\nfrom kaldiio import ReadHelper\nfrom paddleaudio.kaldi import fbank as fbank\n#from paddleaudio.kaldi import pitch as pitch\n\n# the groundtruth feats computed in kaldi command below.\n#compute-fbank-feats  --dither=0 scp:$wav_scp ark,t:fbank_feat.ark\n#compute-kaldi-pitch-feats --sample-frequency=16000 scp:$wav_scp ark,t:pitch_feat.ark\n\n\nclass TestKaldiFbank(unittest.TestCase):\n    def test_fbank(self):\n        fbank_groundtruth = {}\n        with ReadHelper('ark:testdata/fbank_feat.ark') as reader:\n            for key, feat in reader:\n                fbank_groundtruth[key] = feat\n\n        wav_rate, wav = kaldiio.wavio.read_wav('testdata/test.wav')\n        fbank_feat = fbank(wav)\n        fbank_check = fbank_groundtruth['test_wav']\n        np.testing.assert_array_almost_equal(fbank_feat, fbank_check, decimal=4)\n\n    #def test_pitch(self):\n    #    pitch_groundtruth = {}\n    #    if platform.system() != \"Linux\":\n    #        pass\n    #    with ReadHelper('ark:testdata/pitch_feat.ark') as reader:\n    #        for key, feat in reader:\n    #            pitch_groundtruth[key] = feat\n\n    #    wav_rate, wav = kaldiio.wavio.read_wav('testdata/test.wav')\n    #    pitch_feat = pitch(wav)\n    #    pitch_check = pitch_groundtruth['test_wav']\n    #    np.testing.assert_array_almost_equal(pitch_feat, pitch_check, decimal=4)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_librosa.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport librosa\nimport numpy as np\nimport paddle\nimport paddleaudio\nfrom base import FeatTest\nfrom paddleaudio.functional.window import get_window\n\n\nclass TestLibrosa(FeatTest):\n    def initParams(self):\n        self.n_fft = 512\n        self.hop_length = 128\n        self.n_mels = 40\n        self.n_mfcc = 20\n        self.fmin = 0.0\n        self.window_str = 'hann'\n        self.pad_mode = 'reflect'\n        self.top_db = 80.0\n\n    def test_stft(self):\n        if len(self.waveform.shape) == 2:  # (C, T)\n            self.waveform = self.waveform.squeeze(\n                0)  # 1D input for librosa.feature.melspectrogram\n\n        feature_librosa = librosa.core.stft(\n            y=self.waveform,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=None,\n            window=self.window_str,\n            center=True,\n            dtype=None,\n            pad_mode=self.pad_mode, )\n        x = paddle.to_tensor(self.waveform).unsqueeze(0)\n        window = get_window(self.window_str, self.n_fft, dtype=x.dtype)\n        feature_paddle = paddle.signal.stft(\n            x=x,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=None,\n            window=window,\n            center=True,\n            pad_mode=self.pad_mode,\n            normalized=False,\n            onesided=True, ).squeeze(0)\n\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_paddle, decimal=5)\n\n    def test_istft(self):\n        if len(self.waveform.shape) == 2:  # (C, T)\n            self.waveform = self.waveform.squeeze(\n                0)  # 1D input for librosa.feature.melspectrogram\n\n        # Get stft result from librosa.\n        stft_matrix = librosa.core.stft(\n            y=self.waveform,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=None,\n            window=self.window_str,\n            center=True,\n            pad_mode=self.pad_mode, )\n\n        feature_librosa = librosa.core.istft(\n            stft_matrix=stft_matrix,\n            hop_length=self.hop_length,\n            win_length=None,\n            window=self.window_str,\n            center=True,\n            dtype=None,\n            length=None, )\n\n        x = paddle.to_tensor(stft_matrix).unsqueeze(0)\n        window = get_window(\n            self.window_str,\n            self.n_fft,\n            dtype=paddle.to_tensor(self.waveform).dtype)\n        feature_paddle = paddle.signal.istft(\n            x=x,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=None,\n            window=window,\n            center=True,\n            normalized=False,\n            onesided=True,\n            length=None,\n            return_complex=False, ).squeeze(0)\n\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_paddle, decimal=5)\n\n    def test_mel(self):\n        feature_librosa = librosa.filters.mel(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=None,\n            htk=False,\n            norm='slaney',\n            dtype=self.waveform.dtype, )\n        feature_compliance = paddleaudio.compliance.librosa.compute_fbank_matrix(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=None,\n            htk=False,\n            norm='slaney',\n            dtype=self.waveform.dtype, )\n        x = paddle.to_tensor(self.waveform)\n        feature_functional = paddleaudio.functional.compute_fbank_matrix(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            n_mels=self.n_mels,\n            f_min=self.fmin,\n            f_max=None,\n            htk=False,\n            norm='slaney',\n            dtype=x.dtype, )\n\n        np.testing.assert_array_almost_equal(feature_librosa,\n                                             feature_compliance)\n        np.testing.assert_array_almost_equal(feature_librosa,\n                                             feature_functional)\n\n    def test_melspect(self):\n        if len(self.waveform.shape) == 2:  # (C, T)\n            self.waveform = self.waveform.squeeze(\n                0)  # 1D input for librosa.feature.melspectrogram\n\n        # librosa:\n        feature_librosa = librosa.feature.melspectrogram(\n            y=self.waveform,\n            sr=self.sr,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin)\n\n        # paddleaudio.compliance.librosa:\n        feature_compliance = paddleaudio.compliance.librosa.melspectrogram(\n            x=self.waveform,\n            sr=self.sr,\n            window_size=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            to_db=False)\n\n        # paddleaudio.features.layer\n        x = paddle.to_tensor(\n            self.waveform, dtype=paddle.float64).unsqueeze(0)  # Add batch dim.\n        feature_extractor = paddle.audio.features.MelSpectrogram(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            f_min=self.fmin,\n            dtype=x.dtype)\n        feature_layer = feature_extractor(x).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_compliance, decimal=5)\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_layer, decimal=5)\n\n    def test_log_melspect(self):\n        if len(self.waveform.shape) == 2:  # (C, T)\n            self.waveform = self.waveform.squeeze(\n                0)  # 1D input for librosa.feature.melspectrogram\n\n        # librosa:\n        feature_librosa = librosa.feature.melspectrogram(\n            y=self.waveform,\n            sr=self.sr,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin)\n        feature_librosa = librosa.power_to_db(feature_librosa, top_db=None)\n\n        # paddleaudio.compliance.librosa:\n        feature_compliance = paddleaudio.compliance.librosa.melspectrogram(\n            x=self.waveform,\n            sr=self.sr,\n            window_size=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin)\n\n        # paddleaudio.features.layer\n        x = paddle.to_tensor(\n            self.waveform, dtype=paddle.float64).unsqueeze(0)  # Add batch dim.\n        feature_extractor = paddle.audio.features.LogMelSpectrogram(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            f_min=self.fmin,\n            dtype=x.dtype)\n        feature_layer = feature_extractor(x).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_compliance, decimal=5)\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_layer, decimal=4)\n\n    def test_mfcc(self):\n        if len(self.waveform.shape) == 2:  # (C, T)\n            self.waveform = self.waveform.squeeze(\n                0)  # 1D input for librosa.feature.melspectrogram\n\n        # librosa:\n        feature_librosa = librosa.feature.mfcc(\n            y=self.waveform,\n            sr=self.sr,\n            S=None,\n            n_mfcc=self.n_mfcc,\n            dct_type=2,\n            norm='ortho',\n            lifter=0,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin)\n\n        # paddleaudio.compliance.librosa:\n        feature_compliance = paddleaudio.compliance.librosa.mfcc(\n            x=self.waveform,\n            sr=self.sr,\n            n_mfcc=self.n_mfcc,\n            dct_type=2,\n            norm='ortho',\n            lifter=0,\n            window_size=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            top_db=self.top_db)\n\n        # paddle.audio.features.layer\n        x = paddle.to_tensor(\n            self.waveform, dtype=paddle.float64).unsqueeze(0)  # Add batch dim.\n        feature_extractor = paddle.audio.features.MFCC(\n            sr=self.sr,\n            n_mfcc=self.n_mfcc,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels,\n            f_min=self.fmin,\n            top_db=self.top_db,\n            dtype=x.dtype)\n        feature_layer = feature_extractor(x).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_compliance, decimal=4)\n        np.testing.assert_array_almost_equal(\n            feature_librosa, feature_layer, decimal=4)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_log_melspectrogram.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport numpy as np\nimport paddle\nimport paddleaudio\n\nfrom .base import FeatTest\nfrom paddlespeech.audio.transform.spectrogram import LogMelSpectrogram\n\n\nclass TestLogMelSpectrogram(FeatTest):\n    def initParams(self):\n        self.n_fft = 512\n        self.hop_length = 128\n        self.n_mels = 40\n\n    def test_log_melspect(self):\n        ps_melspect = LogMelSpectrogram(self.sr, self.n_mels, self.n_fft,\n                                        self.hop_length)\n        ps_res = ps_melspect(self.waveform.T).squeeze(1).T\n\n        x = paddle.to_tensor(self.waveform)\n        ps_melspect = paddleaudio.features.LogMelSpectrogram(\n            self.sr,\n            self.n_fft,\n            self.hop_length,\n            power=1.0,\n            n_mels=self.n_mels,\n            f_min=0.0)\n        pa_res = (ps_melspect(x) / 10.0).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(ps_res, pa_res, decimal=5)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_spectrogram.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport numpy as np\nimport paddle\nimport paddleaudio\n\nfrom .base import FeatTest\nfrom paddlespeech.audio.transform.spectrogram import Spectrogram\n\n\nclass TestSpectrogram(FeatTest):\n    def initParams(self):\n        self.n_fft = 512\n        self.hop_length = 128\n\n    def test_spectrogram(self):\n        ps_spect = Spectrogram(self.n_fft, self.hop_length)\n        ps_res = ps_spect(self.waveform.T).squeeze(1).T  # Magnitude\n\n        x = paddle.to_tensor(self.waveform)\n        pa_spect = paddle.audio.features.Spectrogram(\n            self.n_fft, self.hop_length, power=1.0)\n        pa_res = pa_spect(x).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(ps_res, pa_res, decimal=5)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/test_stft.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport unittest\n\nimport numpy as np\nimport paddle\nfrom paddleaudio.functional.window import get_window\n\nfrom .base import FeatTest\nfrom paddlespeech.audio.transform.spectrogram import Stft\n\n\nclass TestStft(FeatTest):\n    def initParams(self):\n        self.n_fft = 512\n        self.hop_length = 128\n        self.window_str = 'hann'\n\n    def test_stft(self):\n        ps_stft = Stft(self.n_fft, self.hop_length)\n        ps_res = ps_stft(\n            self.waveform.T).squeeze(1).T  # (n_fft//2 + 1, n_frames)\n\n        x = paddle.to_tensor(self.waveform)\n        window = get_window(self.window_str, self.n_fft, dtype=x.dtype)\n        pd_res = paddle.signal.stft(\n            x, self.n_fft, self.hop_length, window=window).squeeze(0).numpy()\n\n        np.testing.assert_array_almost_equal(ps_res, pd_res, decimal=5)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "audio/tests/features/testdata/fbank_feat_txt.ark",
    "content": "test_wav  [\n  8.86961 7.025289 6.664165 7.169617 7.317829 7.188704 8.351522 8.843228 7.711394 7.231504 6.903938 7.053499 7.293597 8.331067 7.871729 9.206844 9.434045 9.768963 10.01864 10.25888 10.68228 10.55968 10.62156 \n  8.364346 7.526375 6.915925 6.705005 7.641569 7.827819 8.253532 7.794802 7.522578 7.222802 7.388284 7.493527 8.257078 9.141049 8.994849 9.348937 9.015431 9.343955 10.42236 10.13459 10.40709 10.39534 10.22199 \n  7.230361 6.771988 6.422344 7.535786 7.164408 6.342811 8.723886 8.481328 6.804535 7.276428 7.471786 7.581892 8.757826 8.764767 8.570841 8.741215 9.756334 9.515329 9.720121 10.26671 10.67728 10.5581 10.61378 \n  8.872903 7.371414 6.360067 6.153208 7.333708 8.0974 8.851793 8.730195 7.622618 7.169075 7.85181 7.04872 7.978426 8.408302 8.802312 8.395834 9.217923 8.381662 9.777567 10.40261 10.37856 10.31888 10.34441 \n  7.532231 6.751142 8.175496 7.593341 8.063697 8.369373 7.881088 8.15251 7.428252 7.103447 7.989072 7.949497 8.124873 8.496659 8.553727 8.761693 9.109408 9.4684 10.13223 10.16827 9.71019 10.59482 10.90851 \n  6.746207 6.833902 8.067636 7.6485 7.013279 7.693223 8.147296 8.030097 7.067122 8.186153 7.784977 8.756321 8.6457 8.458344 7.769485 8.669812 9.332602 9.097817 9.444702 9.950351 10.18657 10.94016 11.36237 \n  7.128079 7.711221 6.469111 6.649592 6.508276 7.082622 7.440871 7.623552 7.594537 7.354738 8.278585 8.652099 8.709033 8.605441 8.353497 8.4307 9.50789 9.312969 9.785786 10.18853 10.35708 10.71134 11.13716 \n  8.201805 8.373339 7.420624 6.559644 6.318965 6.861043 7.299667 7.459548 7.392651 7.774329 7.917755 8.39668 8.304465 7.503887 8.319722 9.310571 9.144365 9.811728 9.738833 9.825593 10.65616 10.42954 10.28108 \n  8.140867 8.803907 7.842072 6.760153 6.040633 7.099484 7.671337 7.230731 7.280159 7.825505 8.67013 7.970374 7.691161 7.603088 8.121623 8.186304 8.884687 9.764359 9.774008 10.14217 10.57618 10.70955 10.46593 \n  9.335081 7.443659 6.302314 6.274453 6.648484 7.101899 8.31965 7.279731 7.011406 7.738722 8.111496 7.826912 9.217668 8.704701 8.520703 9.237556 9.141415 9.966189 10.13588 10.02818 10.32232 10.5961 10.39195 \n  8.623323 6.642638 6.092153 6.010561 6.961139 7.523609 7.631736 6.81785 6.3952 7.437364 7.784822 8.421501 8.569756 8.931039 8.394889 8.730085 8.568606 9.672934 10.10908 10.22258 10.30489 10.11329 10.44942 \n  8.340079 7.404711 6.73463 6.621991 6.641872 6.501914 7.429152 7.325783 7.075316 7.198759 7.573832 7.726879 8.173958 8.713857 8.947656 9.52945 9.495684 10.04432 9.70799 9.853218 10.34904 10.31011 10.33581 \n  9.458065 6.449831 5.764122 6.112749 6.633307 6.588135 7.683532 7.854395 7.497962 6.587214 7.522266 8.246718 7.842532 8.194103 8.769976 9.494311 9.410578 9.623136 9.262513 9.66307 9.958323 10.58842 10.94138 \n  9.336168 7.658177 6.552251 4.668932 5.951582 7.329723 6.881893 7.673193 8.018956 7.765876 8.092113 7.657069 8.385877 8.804426 8.99403 9.033966 9.84664 9.652982 9.678547 9.901299 10.55994 10.98264 10.42628 \n  8.845008 7.827737 6.934293 6.809871 7.603892 7.622493 7.295815 7.316114 7.707997 8.28838 7.455571 7.749361 8.357333 8.413839 8.780228 9.111949 8.773423 9.546294 9.316511 9.7621 9.853085 10.24652 10.58686 \n  9.845795 7.653487 6.760835 6.417203 6.483883 8.249362 8.985138 7.782502 8.038197 7.994664 7.512061 7.712332 8.276911 8.76414 8.027122 8.730929 8.986988 9.50342 9.225771 9.793655 10.35338 10.19652 10.67655 \n  8.068243 7.419188 7.323668 6.883723 7.588089 7.267737 7.464292 8.121238 7.117096 7.165044 7.638491 7.958453 8.368897 8.497821 8.06803 8.636445 9.186031 9.296571 9.991373 10.35782 10.44223 10.60756 10.9512 \n  8.540399 7.109134 6.417945 6.851756 7.50145 7.613665 7.395747 8.489678 7.192803 8.40198 8.48846 7.516579 8.291675 9.133558 8.94935 9.040503 9.475376 9.886353 10.04679 10.23742 10.22118 10.67988 10.29023 \n  9.943547 6.745187 7.141617 7.058182 7.203416 8.045156 7.670315 7.748672 7.009519 7.208478 7.261959 8.346151 8.425858 8.822375 8.973361 9.907825 9.710265 9.542497 9.383007 9.832958 10.30413 10.9831 10.99566 \n  9.077311 7.305787 7.036552 6.220779 6.492191 6.642952 8.301676 8.177285 7.706949 7.897906 7.814847 7.765959 8.228884 8.499186 8.701291 8.90225 9.000106 9.510703 9.477421 9.869934 10.31142 10.33504 10.62863 \n  9.609183 6.470312 6.850113 7.247727 6.606174 7.178535 7.569305 7.858948 7.907071 7.322339 7.393857 8.411836 8.555615 8.416198 8.268435 8.814535 9.016805 9.221167 8.856338 9.819329 10.63624 10.67038 10.4818 \n  8.896682 6.96038 7.062835 6.841669 6.556721 7.257597 9.19041 8.196911 7.560658 7.475944 7.570982 8.699837 8.718691 8.698103 9.604801 9.410757 9.482757 9.489608 10.0253 10.21278 10.42956 10.25078 10.40438 \n  10.05012 7.997848 8.523865 7.810099 7.064989 7.438704 8.866325 8.385101 8.702444 7.532755 6.970853 8.658536 8.904259 8.098039 8.240754 9.383977 9.924636 9.825594 10.16586 9.929379 10.33848 10.6166 10.88825 \n  9.945673 7.943526 8.236642 7.982066 7.059935 7.337771 8.282602 7.669298 6.812744 7.241785 7.059946 8.290605 8.874635 8.206081 9.037805 9.692253 9.771944 9.658941 9.887684 9.687504 10.12401 10.5467 10.46784 \n  9.24334 8.005972 8.029324 7.080775 6.692482 7.339699 6.330315 7.749064 7.191765 7.614157 7.584374 8.707373 8.633794 7.661246 8.89745 8.717183 8.727042 9.601094 9.761832 9.91165 10.89605 10.7561 10.4439 \n  9.008655 7.696863 8.051159 6.21505 6.986367 7.75211 7.125566 8.008561 8.631255 7.692895 7.423654 8.070612 7.934104 7.481667 7.878049 8.699003 9.587379 9.81943 9.638152 10.14519 10.48706 10.67093 10.95845 \n  9.56725 7.086317 7.604103 6.621353 6.861667 6.762026 7.150949 8.061196 7.548547 6.552682 7.445788 8.408651 8.276496 7.768121 8.235985 9.36837 9.303123 9.568222 9.907539 10.04948 10.3193 10.38864 11.01985 \n  9.435867 7.065077 8.260999 7.606821 7.11696 6.622849 7.453804 7.729028 6.969114 7.593372 8.076168 8.142076 7.987474 7.750668 8.709545 9.194512 9.28443 9.696207 10.08809 10.43397 10.95729 10.62421 10.32698 \n  7.326074 6.968657 7.991836 8.057238 8.277269 6.64677 8.417533 8.390658 7.716748 7.254366 8.046806 8.952176 8.943592 8.626341 8.475414 8.366508 9.379741 9.649915 9.956218 10.14107 10.0686 10.3009 10.63128 \n  8.867029 7.436584 8.325071 8.151552 7.802304 7.204567 7.817641 8.41904 8.079826 7.800119 7.738661 8.019406 8.496906 8.371117 8.895446 8.874495 9.541505 9.603241 9.702045 9.520963 10.07405 10.22188 10.69203 \n  7.892157 7.706676 8.708323 8.090714 7.298046 7.119635 7.677824 8.568966 9.065309 7.950867 7.361037 8.006032 7.704475 8.136228 9.241001 9.342211 9.766371 9.645364 10.53355 10.35027 10.26263 10.8308 10.88063 \n  9.17825 6.552885 7.865911 7.314655 7.429624 7.467305 7.331274 8.097523 8.513691 7.603092 8.123087 8.988563 8.24368 7.665757 8.043156 9.323641 9.559673 10.4114 10.44213 10.46176 10.31303 10.41219 10.04096 \n  9.499084 6.913695 8.680465 8.913202 7.983476 7.54614 8.20214 8.433187 7.619872 7.079637 7.59503 7.827682 8.021211 8.954014 8.512682 8.685501 9.039448 9.882102 10.09629 9.995301 10.25326 10.52707 10.41024 \n  8.841949 7.852749 8.220187 8.067208 6.958006 6.525739 7.606658 8.743006 8.618779 7.857424 7.85938 6.839745 8.494206 7.93556 8.554915 9.17892 9.411014 9.403722 9.75618 9.915223 10.4127 10.62058 10.75261 \n  8.80931 7.176473 8.226482 8.048065 6.875594 7.035853 8.159007 8.788584 7.998541 7.745961 7.02769 7.343524 8.768233 8.742394 8.993815 8.919962 8.948602 9.299537 9.644719 9.328181 10.0551 10.60812 10.26714 \n  8.416738 7.433433 8.202932 7.654713 7.487177 7.454067 7.807778 8.21654 7.973643 7.745943 7.477229 7.699207 8.724244 8.921854 9.167027 9.329788 9.198338 9.449234 9.350556 9.504007 10.01113 10.77754 10.79311 \n  7.265522 8.85788 8.794858 6.660202 5.630237 7.668158 8.690257 8.2572 7.200497 7.342714 7.748627 8.173976 8.632828 8.53996 9.053345 9.001765 9.227647 10.09744 9.63631 10.25264 9.908823 11.11253 11.10346 \n  8.641815 8.838676 8.314915 6.847168 5.620167 7.186635 8.486069 8.301935 7.863872 7.790708 7.733249 8.113005 8.49118 7.827488 8.389672 8.932463 9.147495 10.10519 10.22344 10.33928 10.09212 10.47646 10.13575 \n  7.634632 6.384978 8.24638 7.503924 6.99588 7.640463 7.480204 7.821477 7.610888 7.87086 8.010333 7.981211 7.871301 8.551961 8.90114 9.304276 8.653571 9.205483 9.727321 10.48769 10.20595 10.13756 10.41514 \n  8.518332 7.862745 8.034936 8.2016 6.675735 7.573159 8.171587 8.14386 7.991887 6.929758 7.718138 7.759238 8.233613 7.833398 9.010793 8.673923 9.241878 10.12235 10.55527 10.50808 10.58219 10.75335 10.4664 \n  8.728762 7.574676 6.733976 7.824086 8.000705 7.302856 7.860464 8.410678 7.924881 6.743472 7.201906 7.431501 7.915576 8.187505 8.869449 8.608752 9.654437 10.20065 9.895975 10.05015 10.0937 11.01951 10.82668 \n  7.629794 6.486794 6.295053 7.050656 7.523815 7.511558 8.234637 8.500476 8.005258 7.928689 8.219633 8.856939 8.562517 8.864034 9.246393 9.440809 9.380711 10.00752 9.569251 9.957119 10.54277 10.3938 10.80297 \n  9.755882 6.397912 7.59745 7.644662 7.147341 7.108955 8.413054 8.151018 7.909472 7.656272 9.413692 11.06461 10.69808 10.64652 11.38675 11.21603 11.1705 10.6691 9.91959 10.95611 11.29983 11.17031 10.97226 \n  9.474765 7.803607 8.385871 6.384162 7.948147 7.78756 8.428943 8.824086 8.393611 8.634716 8.208453 8.799019 9.028046 9.011028 9.807654 10.60488 10.43945 10.06425 10.27431 9.998198 11.03344 10.98869 10.06162 \n  8.450254 7.49551 6.799858 6.310681 7.20258 8.050933 8.205685 8.776224 7.973586 7.784925 7.730099 8.780946 9.105856 8.773993 8.182259 8.562423 9.90097 9.80205 10.24598 10.17385 10.20839 10.46425 10.26094 \n  8.252859 7.287729 7.475165 7.372538 6.989303 7.400277 6.899447 8.107825 7.968466 7.659332 8.521437 9.400009 9.208941 8.744918 8.120193 8.727738 9.995106 9.742892 9.950342 9.993467 10.03006 10.28127 10.45164 \n  8.592541 7.811454 7.721195 6.033926 7.451138 7.954978 7.936564 8.032441 8.207817 7.761642 7.824575 8.806037 8.584102 9.029242 9.405202 9.570443 10.0666 9.799012 10.14801 10.00847 10.26264 10.47974 10.30221 \n  8.263712 7.622368 7.388706 6.853238 7.028842 8.005108 7.877354 8.477866 8.796792 8.305426 8.403102 8.24081 8.906131 8.901518 9.546893 9.517485 9.934557 9.7798 10.04766 9.671112 10.1303 10.74265 10.63667 \n  9.357657 8.026215 7.907611 7.254067 6.912889 7.510985 8.215575 8.492505 8.151805 7.310562 8.163457 8.056206 8.009975 8.118791 8.972518 9.303927 9.412671 9.438314 9.8068 9.750667 10.35458 10.35285 10.09931 \n  8.511848 7.523149 8.195268 7.966453 7.744322 8.485562 8.004887 7.922952 8.245237 7.383193 7.844249 8.127041 8.127259 8.443523 8.102531 8.774108 8.681726 9.477551 8.882012 9.804171 10.55685 10.48077 10.37192 \n  7.975676 7.082146 7.933741 6.951503 6.272567 7.088233 7.917744 7.379583 8.238628 7.820266 8.475443 8.424726 8.05715 8.067741 8.94787 8.867351 9.374059 9.266661 9.49703 10.01138 10.3168 10.71612 10.27346 \n  8.813721 8.656951 7.681757 7.203363 7.488046 8.216457 8.221495 7.714307 7.938663 7.708951 8.019526 7.926672 7.864351 7.698409 8.801851 8.555806 9.788485 9.553381 9.62245 10.2158 9.915847 10.40117 10.80687 \n  6.477304 7.734454 8.373713 6.965827 8.077723 8.442548 7.893295 8.407219 7.909376 8.080144 8.55372 7.803288 6.868239 8.449481 8.860373 8.910608 9.437862 9.165442 9.82246 10.30201 10.48472 10.77984 11.18594 \n  9.42877 10.45913 10.29159 9.716755 9.220295 8.658374 6.794528 6.873018 7.217855 8.288869 8.809176 8.809996 8.093638 8.87556 9.207784 9.647738 9.825712 10.08347 9.918015 10.10553 10.54475 11.02415 10.92163 \n  13.23045 15.72255 15.14105 16.25381 15.65043 12.23466 10.81911 10.62931 10.80597 11.77175 12.40585 12.68368 13.26326 11.76209 10.96095 14.30546 15.08591 12.37251 12.23275 11.97119 10.67747 10.71765 10.87486 \n  13.65519 16.94076 16.0239 18.20588 16.9831 13.7648 12.16126 11.07043 11.80799 12.73412 12.98298 12.90398 14.25156 11.9087 10.24638 14.79149 15.7653 13.01829 12.92099 13.79269 11.3934 11.02932 11.13173 \n  13.2973 17.06046 16.08663 18.53358 17.69795 13.95008 12.40663 11.98961 12.74475 13.79677 14.19347 14.3372 14.89816 13.25463 12.57261 16.00417 16.9676 13.95466 13.9528 14.54457 12.07387 11.57656 11.49943 \n  11.75321 16.53652 16.49979 19.33843 18.63615 13.93179 11.64835 11.64008 12.97903 13.87796 14.90638 15.14878 15.24947 14.3757 13.73179 15.41584 15.93701 14.80291 14.12144 14.58253 12.19397 12.21274 12.09839 \n  12.51654 17.17333 16.62761 20.22687 19.77942 13.27525 11.65 12.57212 13.83558 14.21572 15.06257 15.13174 14.75701 15.54657 14.15343 15.183 16.24345 14.94379 14.57995 14.90003 12.3515 12.90885 12.08299 \n  12.59919 17.27024 16.59142 20.83065 20.46106 14.01313 12.53942 13.63936 14.82475 14.79233 15.39594 15.28064 15.61105 15.19362 13.62629 15.96059 17.22206 15.25036 15.57805 15.82821 13.8464 14.34314 12.32957 \n  12.87339 17.40207 16.69853 20.75185 20.27472 14.82241 13.57454 13.89783 14.86771 15.49655 15.69082 15.79947 15.61258 16.25987 14.84013 16.51847 18.01414 15.01476 15.3407 16.01681 14.13993 14.62834 12.70863 \n  13.17359 17.59177 16.96258 19.95944 18.9106 15.22701 13.8382 13.31798 14.14737 14.76138 15.86723 16.08653 15.98195 16.09414 14.82789 16.4943 17.65386 15.15134 15.58843 16.19427 14.51803 15.25478 14.10639 \n  13.61701 17.7865 17.24287 20.31397 19.26783 15.3012 14.27533 14.00652 14.06157 13.97732 15.41972 16.40127 16.03523 14.89164 14.54936 15.81458 16.71577 14.59401 15.69445 17.08231 15.19946 15.35905 13.67907 \n  14.00184 17.83053 17.10755 20.32385 19.31859 16.05173 14.2608 13.70262 13.87365 13.57939 14.82414 15.85239 16.70191 15.73202 13.95968 14.90556 15.42773 15.31231 15.90333 16.87693 15.50014 15.44649 13.9608 \n  14.57378 17.84243 16.76657 19.45782 18.36666 15.36792 13.44019 13.72313 14.92875 14.36976 14.25026 15.64569 15.89312 14.45428 13.3161 14.53451 15.62068 14.59393 15.80624 17.03548 14.96751 15.02374 13.4909 \n  15.21447 18.18304 16.96745 19.16579 18.69295 14.50879 13.17371 13.65467 15.22889 14.17074 13.75207 14.95903 15.48484 14.01785 11.96252 13.67882 15.37274 14.30946 15.06645 16.43822 14.03593 14.029 12.96432 \n  15.69557 18.73573 17.84295 20.32482 19.18899 14.03427 12.50394 12.18307 15.27329 13.74666 13.09154 14.42644 14.96374 13.87214 11.83368 12.93985 14.45116 14.00281 15.06362 16.09592 13.61044 13.31885 12.74485 \n  15.98183 18.61076 17.23318 18.58419 17.75739 14.66514 11.80884 13.04507 15.05399 13.23005 12.31126 13.64777 13.9603 12.94314 11.54242 12.23427 13.46654 13.42021 14.35025 15.38576 13.45529 13.28467 13.43179 \n  16.36983 18.49153 17.46072 19.55406 17.8304 14.26844 11.65388 12.54786 13.89278 12.02204 11.70842 12.86929 13.92763 13.19448 11.47678 11.02568 13.00155 13.05625 13.99241 14.93269 13.36193 12.62123 11.25201 \n  16.91053 19.31395 17.91098 18.89643 16.86432 13.72694 11.87185 13.24254 14.00205 12.05257 10.76908 12.87949 13.28356 11.94633 11.05437 11.12533 12.75738 12.05501 13.33129 14.07069 12.3796 11.7192 11.05169 \n  17.29174 19.6846 17.73157 17.35478 16.16297 14.15115 11.11073 12.40668 13.28362 11.18836 11.07174 12.54022 13.02938 11.88706 10.44743 11.13548 12.77041 12.04656 12.83903 12.8876 11.77514 11.40439 10.56045 \n  17.23432 19.42053 17.20756 16.95235 16.25754 13.89139 11.49117 11.78105 11.14721 10.20588 10.31909 12.48863 12.60464 11.83299 12.36004 11.31453 12.29337 12.36164 12.43958 12.93882 11.9782 12.27852 11.67843 \n  16.53074 18.71063 16.51751 16.94945 16.05041 12.74791 10.03071 10.72647 10.99932 9.982744 10.96635 12.68731 12.83623 11.30921 11.54913 10.90253 11.23106 11.50233 12.71762 13.18253 11.76622 12.38223 11.70104 \n  15.69217 17.89815 15.7483 14.97377 14.53612 11.96516 11.12983 9.131196 10.96767 10.9673 12.05442 12.21859 12.5895 10.55106 10.79283 10.54876 11.01498 10.7606 11.54235 11.51353 10.85205 11.89782 11.11372 \n  13.86923 16.57632 15.26331 14.85788 14.39067 12.7171 11.17243 11.00468 11.68423 13.25407 12.60769 12.59903 12.12048 12.90249 13.94144 13.63238 13.21792 12.05534 12.87838 14.90839 15.73015 16.02667 15.69104 \n  13.61382 16.34682 14.90382 14.8893 14.40084 13.49422 12.6097 13.05071 13.73629 15.75304 15.30508 13.85447 13.98672 15.82224 16.32998 16.46949 16.51073 13.91432 14.74784 17.0687 18.13454 18.42613 18.47258 \n  14.55605 16.97081 15.03501 15.3369 14.16967 11.95557 10.91977 11.08843 11.75058 13.24282 12.85878 12.96099 13.28478 15.59657 14.72278 15.30267 15.28392 13.16171 14.36229 17.22016 18.41889 19.45104 19.20117 \n  15.47327 17.72926 15.78447 15.42446 15.40768 12.5729 10.11994 10.89366 12.10496 13.59284 13.03747 13.40623 12.94038 16.30528 16.32386 14.95233 14.70298 13.22234 14.0664 16.60508 17.89858 18.17508 18.00281 \n  16.2211 18.26995 17.28866 17.57735 15.27353 13.3695 11.53266 11.68451 11.35421 11.92297 12.33619 13.06362 12.45224 15.49412 16.06547 15.92675 15.58576 12.58488 13.5124 15.40464 16.18043 15.33247 15.62229 \n  16.40175 18.42591 17.84651 18.44906 15.41768 13.78307 12.2946 12.64999 11.22093 11.41927 11.63084 10.93246 11.98123 14.54343 16.20716 16.31189 15.47426 12.76656 13.13507 15.26896 15.09722 14.0725 14.46431 \n  16.6757 18.54147 17.61383 18.17967 15.46035 13.83175 11.8658 12.33601 11.13389 11.20397 11.12461 11.22868 12.22488 13.94469 15.89769 16.34622 15.46319 12.74337 14.20451 15.74678 15.10971 14.52905 14.4963 \n  16.76283 18.5887 17.68788 18.20937 15.80549 13.99685 12.14814 12.54838 10.8432 11.06379 11.41749 11.17507 11.48255 12.85203 14.78319 16.05849 16.08326 13.06919 13.94136 15.39909 14.80749 14.61425 14.66702 \n  16.64995 18.30085 17.58634 18.3342 16.15151 14.58886 11.89366 12.30556 11.47828 11.79887 11.09667 11.30176 11.16868 14.35984 14.87677 16.13587 16.49911 13.06481 14.12372 15.51614 15.46192 15.01677 14.90916 \n  16.52672 18.18384 17.63734 18.262 16.74109 15.33377 12.32343 12.43404 12.25445 12.18885 12.2143 11.90199 11.90509 14.61265 15.28587 16.9969 17.03483 13.91487 14.51653 15.79068 15.46326 15.15117 14.32447 \n  16.60033 18.01448 17.0511 17.71783 17.75788 16.23282 12.81127 12.78385 12.44913 12.3739 12.64835 12.44617 11.88231 14.26506 14.75798 16.41036 16.44767 13.79646 14.08188 15.74754 15.21961 14.5229 14.27368 \n  16.58554 18.17001 15.6192 15.79108 17.83907 16.49691 13.58467 13.87136 13.15251 15.34053 15.64338 14.75528 12.38052 13.428 14.05307 15.71102 16.18547 13.51842 13.2032 15.82146 15.4119 15.28212 14.9756 \n  16.81706 18.37561 15.55623 15.33322 17.88172 16.29072 14.11057 14.21804 13.08518 13.69146 14.14797 14.73615 13.03893 13.11906 14.03352 14.95837 16.48228 13.51765 14.07395 15.32152 14.80149 14.38036 14.81253 \n  16.95721 18.65568 15.88247 14.83851 17.85907 16.19847 14.35859 14.35917 13.97949 13.80073 14.48404 15.46158 12.86709 12.57524 13.31753 13.57888 14.20235 13.62078 13.80603 14.58132 14.26628 15.57101 15.81091 \n  16.92929 18.59748 16.18815 16.21428 17.81978 16.08954 14.27445 14.10925 13.96899 14.1386 14.35728 14.62649 12.22072 11.41585 11.79407 12.69996 13.94304 14.1476 14.00437 14.08617 14.21517 16.62167 16.08522 \n  16.71347 18.34732 16.52386 16.70664 17.32837 15.66043 14.25163 14.13859 14.01087 14.8577 14.49389 14.02374 12.22193 12.02307 12.09513 12.59532 14.0639 13.72341 13.91703 14.04354 14.41245 16.46469 16.29546 \n  16.4208 18.01264 16.88099 17.1442 16.57642 14.64041 13.85327 13.94551 14.64954 14.75776 14.21291 14.0806 12.50921 12.25238 11.75339 12.30866 14.22572 14.74261 14.3222 14.56139 14.66986 16.32808 16.07767 \n  16.02585 17.41488 16.75061 17.14062 15.60216 13.43982 13.3218 13.5059 15.12315 15.74747 15.12732 14.97423 11.94713 11.64201 11.86428 12.81159 14.43116 14.51448 14.0855 13.91175 13.53605 16.79836 16.27676 \n  15.54676 16.81251 16.59787 16.86721 13.93739 12.5265 13.02697 13.58001 14.63541 15.0335 15.03953 14.87171 11.96232 11.17344 11.23595 12.35256 13.94297 14.62026 14.15592 14.0969 13.14401 15.85678 16.06257 \n  15.29335 16.5896 16.2428 16.40902 13.19328 11.96381 13.15584 13.4573 13.83275 14.18077 14.74952 13.4333 11.54537 11.45848 11.20981 11.44254 13.91985 14.09482 13.83819 13.72444 12.47239 15.62782 15.47463 \n  15.03695 16.41206 15.76506 15.74993 14.99031 12.53887 14.11596 13.88085 13.56149 13.86856 14.16082 13.18733 10.81969 11.83342 11.28586 11.12295 13.29487 13.72911 13.43846 13.1814 11.87428 13.31521 14.49123 \n  15.19216 16.60078 14.61114 14.46758 15.01078 13.24106 14.01335 13.57776 12.27156 13.13906 14.44345 13.87597 11.4695 11.93211 11.51881 11.86933 13.54847 13.27814 13.21632 13.90559 14.1398 14.70719 14.13614 \n  14.67921 16.36944 14.31438 14.29885 14.20024 12.58013 12.82334 12.93028 12.20578 13.60437 14.77291 14.12951 12.00097 12.08059 12.8358 12.58611 13.60779 13.56823 13.54014 15.80377 16.93598 17.07594 16.38759 \n  14.09909 15.53763 14.35333 14.36311 13.46532 12.24172 11.28518 11.79358 12.87418 12.31148 14.00558 14.61462 12.33662 12.94618 13.78474 13.02037 13.37858 14.04721 15.38267 18.08268 19.1378 18.01291 17.87174 \n  13.13866 14.28506 13.46247 13.33514 12.55707 11.26553 10.44495 10.7674 12.86463 12.67321 13.31184 12.77522 11.95182 13.00975 13.90651 13.2495 14.2042 14.69992 15.82987 18.51886 19.10749 19.2898 19.35597 \n  12.87447 13.63893 12.77628 12.87282 11.82412 10.49559 11.2738 11.53943 12.46402 13.76956 13.33128 13.70105 13.19503 13.69975 14.5716 14.70375 14.28935 14.60292 15.83705 18.41346 19.52948 19.5496 19.50181 \n  12.43892 14.00917 11.94452 12.23295 13.09062 11.04633 10.81847 11.03293 12.85549 13.9011 14.34009 14.35291 13.72982 13.88251 14.83228 14.69408 14.73889 15.0092 16.64098 19.92425 20.72796 20.62129 20.78949 \n  12.57589 14.14755 12.76697 12.63588 12.86826 10.93601 10.81407 11.39892 13.70268 15.24565 15.25113 15.90769 15.04436 13.95307 14.30912 15.37132 15.7328 15.43253 17.88644 20.36236 20.81531 21.52759 20.81256 \n  11.55697 13.42533 11.86985 12.06834 12.89067 12.34525 12.49656 12.66325 13.77704 15.66433 16.10908 16.22246 15.24011 14.59829 15.35136 15.66786 15.75713 15.76261 17.19726 20.20177 20.41369 21.18811 20.27664 \n  11.83781 11.78476 10.88169 12.16515 12.8652 12.27359 12.28256 13.37679 14.12796 16.37236 16.86594 16.74899 13.97586 14.41109 15.27517 15.25704 16.5749 15.36801 16.12666 18.94821 19.08416 20.14678 19.19424 \n  11.29138 12.42908 11.55172 11.38864 12.08098 11.84389 12.93314 13.31962 14.90897 16.77657 16.34854 15.3447 13.96065 14.13565 14.2487 14.35624 16.70179 14.96482 14.82867 17.15551 17.93615 17.96055 17.92477 \n  11.65481 13.19278 11.53873 12.37848 11.75132 12.30172 13.64941 13.70718 15.32799 15.79656 16.56388 15.52489 14.06691 13.22153 13.50002 13.39991 15.37756 14.06801 14.822 16.09739 16.44575 16.48426 16.86766 \n  10.83643 12.90215 11.20963 11.4503 12.48443 12.65709 14.0135 14.90167 14.40853 15.14135 14.69142 14.34933 13.56003 13.23642 13.07663 13.29242 14.56171 13.91872 14.96106 16.0597 15.73718 16.22322 16.35061 \n  11.76764 14.94607 14.002 12.59242 13.17363 12.93256 14.04444 14.95929 14.73403 14.32073 13.673 13.46165 12.49231 11.98037 12.40751 12.22861 14.2252 13.65674 14.01322 15.1333 14.95369 15.47503 16.08985 \n  13.89615 16.76128 15.37205 14.68637 14.55084 14.06249 14.60906 15.02118 14.96586 14.17659 13.32582 13.36398 12.40657 11.75675 12.20584 11.6482 13.49479 13.45353 13.88642 14.68982 14.64923 14.41646 14.38884 \n  14.84046 17.53472 16.00968 16.66092 14.74903 14.52959 14.44483 14.51026 14.96541 13.62469 12.74818 12.63656 11.79429 10.7945 10.28362 10.71255 12.82129 13.17442 13.48379 14.43379 14.1143 13.92664 13.57136 \n  15.24041 17.86895 16.36832 17.24933 15.26022 14.57038 14.41827 14.01725 15.12896 14.63774 13.50198 13.16672 10.8975 10.52911 10.55219 10.53394 12.4472 12.95718 13.381 14.41105 14.18102 13.43132 13.21059 \n  15.70714 18.11394 16.63966 17.54475 15.6258 14.62249 13.44291 14.33535 15.30156 14.73038 12.71182 11.88729 11.21848 11.80892 11.28598 11.00321 12.07642 12.61302 12.96624 13.64967 13.5497 13.66227 15.18429 \n  16.24144 18.45406 16.74632 17.26887 16.00562 15.20356 14.67932 14.5265 15.42036 15.9411 12.72794 11.28165 11.22411 11.92239 11.05458 10.47411 11.84302 12.45643 12.32757 13.31341 13.65614 14.01642 15.6444 \n  16.61691 18.75608 16.65908 16.05809 16.49335 15.44349 14.24317 13.74861 15.73102 16.03167 12.45979 11.43863 12.06159 11.43628 11.58031 10.96982 12.73052 13.25921 12.43133 13.44257 13.17499 13.61122 15.05092 \n  16.80972 18.82384 16.56598 15.89633 16.39415 14.86858 13.51579 13.62421 15.78119 15.96636 12.04702 12.23535 12.08618 11.75746 11.64274 11.03938 12.40111 12.2805 12.29179 13.94364 13.40477 14.06813 15.88864 \n  16.63538 18.58344 16.62993 16.47061 16.84248 15.18759 14.40616 13.94959 15.81456 15.56275 13.3875 12.99495 11.75405 11.29325 11.58946 10.95365 11.4328 12.09967 12.70522 13.64252 13.03335 14.81887 16.09799 \n  16.17998 17.74599 16.20119 16.20937 17.15302 15.38168 15.02195 14.70119 15.58851 15.20672 13.59827 13.00949 12.00444 11.9139 12.20626 11.42136 12.15257 13.27923 12.24949 13.81115 13.19789 14.65822 15.93385 \n  15.63498 16.83412 15.9795 16.01633 16.73568 14.96041 15.20592 14.9941 15.25987 15.44159 13.90219 13.12603 12.1955 12.00728 11.73402 11.36467 12.2128 13.21522 12.46231 13.59565 12.94152 14.60943 15.73831 \n  15.64667 16.88672 16.15878 16.30288 14.82288 12.78746 14.38334 14.24222 15.33887 15.6051 14.19205 13.4702 11.48957 11.67185 11.36558 11.50844 11.67504 12.6779 12.27801 13.62284 12.4663 13.766 14.50554 \n  16.1116 17.70094 16.61898 16.63179 14.50537 13.00403 14.49458 14.1091 14.77081 16.03117 14.69265 13.87188 11.65564 11.77306 11.69971 10.80465 11.53343 12.87404 11.97025 13.6426 11.97943 14.26168 15.0657 \n  16.30089 17.96895 16.63384 16.78599 15.04495 13.30599 14.34233 14.00725 14.74239 15.8376 14.84421 13.98984 11.77159 11.99564 11.91329 11.26901 12.10066 14.10714 12.30086 12.97296 11.96393 13.5807 13.9249 \n  16.11331 17.73792 16.50445 16.31737 15.14762 13.18915 13.33717 13.48801 15.0379 14.98231 14.6054 13.371 10.87303 10.89191 11.57216 11.3191 12.55595 13.71982 12.37777 13.36162 12.34734 12.24435 12.79598 \n  15.58554 16.86545 15.76826 16.14976 14.84043 12.69869 13.17145 12.83138 13.56788 13.88323 12.82279 11.39667 10.49319 10.13156 10.41932 9.690503 11.98269 12.59705 11.74903 12.81073 11.81398 12.05253 12.92546 \n  15.40506 16.56629 15.7819 16.15461 15.12686 13.06547 13.38418 13.28866 11.46526 12.2537 12.2489 12.08193 10.35587 10.30065 10.11564 10.48493 11.5637 11.96607 11.58659 11.82748 10.88299 11.80397 12.83247 \n  15.64443 17.13461 15.25182 15.23267 14.96755 12.78958 12.95011 12.96703 12.13067 12.01262 11.68263 11.51331 10.19018 10.40131 10.45652 9.893003 10.72811 11.31659 10.82685 11.00283 10.72475 11.77716 12.83387 \n  15.71785 17.45413 15.5854 15.01698 14.3412 11.71642 10.96577 11.03219 11.98035 12.71681 11.61681 10.26505 9.601998 11.02885 11.42186 10.48678 11.01715 11.48228 11.22338 11.53144 10.79359 11.5774 11.99054 \n  15.35344 17.22778 14.87986 13.97491 13.06646 10.3242 10.27509 10.32014 10.23042 10.61678 9.737593 10.01495 9.896219 9.359041 9.507567 9.67006 10.14279 10.65076 10.4929 10.57693 10.33899 11.15093 10.91731 \n  14.73678 16.47514 14.2816 13.68988 13.41362 11.12034 10.6353 10.23782 10.21636 10.79559 10.0661 10.10203 9.259908 9.090837 9.185848 9.923974 9.884459 10.10081 10.24038 10.84077 10.28913 10.66675 10.87501 \n  13.34543 15.10439 13.62741 13.43057 13.13955 11.26525 10.73161 10.48361 8.931073 10.65594 10.13154 10.01275 7.661518 8.794694 8.97205 9.528334 9.832764 10.47726 10.19211 10.24871 10.08061 10.30916 10.30075 \n  10.66386 12.08491 13.25964 13.39106 12.19863 10.12935 11.24597 11.23391 9.032432 10.34383 9.701096 9.622985 8.836775 8.976686 8.384194 8.839561 9.518727 10.43447 10.18111 9.936262 10.31167 10.56191 10.62938 \n  9.864835 11.36032 12.31589 12.7327 11.80678 10.03503 10.97492 10.7874 9.752045 8.775429 8.095765 8.616365 8.481807 8.58884 9.057997 9.505718 10.19115 10.05057 10.04556 10.14044 10.41077 10.46338 10.77466 \n  8.924618 11.12906 12.26638 12.40822 11.61309 9.230251 10.80107 10.44947 9.52743 9.636349 8.786553 9.209707 8.387288 8.182937 8.243385 9.326593 9.774284 10.1685 10.02218 10.17269 10.70011 10.49688 10.61065 \n  10.46031 12.47213 11.88194 11.74302 11.8674 10.72511 11.42089 11.52294 12.66962 13.42245 12.90012 11.16923 10.26218 10.81529 10.76803 10.16122 9.826 9.915348 9.86139 10.30795 11.00059 11.42232 11.84945 \n  12.26625 14.16075 12.72903 14.60278 14.37007 13.44235 12.87462 13.86045 15.57594 16.44231 16.44123 15.36868 13.77279 15.25738 15.21306 14.52211 13.27622 12.97607 12.30169 14.6017 16.36056 17.2046 17.79084 \n  12.88817 14.4487 12.22028 13.27812 13.9757 13.02691 12.24403 13.3259 14.29199 15.57484 15.93701 16.14005 13.74489 14.87244 15.91617 16.46932 15.27049 13.81515 13.83679 16.70215 18.24577 19.36378 19.67374 \n  12.00124 15.37659 15.7605 14.22926 13.0174 13.10144 11.59302 12.30477 13.87144 16.48501 16.24954 14.65436 13.44942 13.95702 15.1756 15.80813 15.05493 13.84618 12.97811 14.7254 15.89062 17.37466 17.80906 \n  11.40193 16.41908 17.10656 18.07596 18.44994 14.86982 11.46446 13.08391 15.70103 16.6888 15.61081 14.1348 12.79728 13.32965 13.90944 13.99649 13.78145 12.89573 11.9253 13.4449 14.24946 14.72222 15.25539 \n  11.44434 16.72986 17.13328 18.86685 20.06189 16.01924 13.17847 12.7762 17.20245 16.84163 15.03655 13.80424 11.7222 13.07261 13.83397 13.96507 13.21282 12.76647 11.96956 12.39547 12.90304 13.23651 13.36372 \n  10.10038 17.35346 17.76299 18.8912 20.46964 16.98438 14.85764 12.72846 16.86143 16.67736 14.81743 13.0213 12.2606 12.59028 13.18198 14.63323 13.8833 13.29084 11.56619 12.33959 12.88427 13.18531 13.93617 \n  11.39528 17.46929 17.92314 19.14353 20.62991 16.99307 15.65434 13.20797 15.76896 15.81176 13.97282 12.77619 11.2707 11.88343 12.92847 13.32276 13.7076 13.56002 11.07274 11.85992 12.23533 13.28798 15.04418 \n  11.27983 17.707 18.24305 19.08735 20.56552 17.11422 16.33149 13.43726 14.52213 14.48029 13.66881 12.0331 11.1849 10.85902 12.006 12.63326 13.76072 13.75976 11.0928 11.39149 11.49694 13.85464 15.78272 \n  10.4093 17.90809 18.4453 18.32235 20.13852 17.31362 17.00359 13.08082 13.30086 13.77682 13.61921 11.83928 11.08163 10.67048 11.6871 11.93983 13.32355 13.21966 11.60241 12.79556 10.68321 13.65361 15.63675 \n  11.84527 18.06657 18.71371 18.15455 20.01794 17.42912 17.4063 13.26461 13.40163 13.82001 13.56594 12.01353 11.27739 11.76238 11.80556 12.06823 13.41709 13.49274 11.33103 12.29501 11.13933 13.40397 15.07014 \n  11.17124 18.38477 19.04682 18.43799 20.28102 17.52682 17.30856 12.02493 13.38366 14.0256 12.96288 11.21294 11.00717 11.76898 11.5427 11.69634 12.18315 13.27228 12.24852 12.80867 11.54512 13.54795 14.91226 \n  11.79911 18.40328 19.16708 18.38249 20.19378 17.33193 16.52722 12.74763 13.76983 14.43673 13.70339 10.60393 10.94744 11.23283 11.7214 10.93908 12.70267 13.61965 12.34297 12.93185 11.72894 13.06544 14.49717 \n  11.53892 18.40511 19.1988 17.54394 19.24091 16.508 15.51558 11.58755 12.57494 12.96985 12.25272 10.15904 10.6575 10.79901 10.68679 10.70864 12.52 13.14616 11.88523 13.06559 11.90712 13.5841 14.07163 \n  11.24507 18.51727 19.28405 15.55707 16.47013 15.3894 15.69263 12.4398 12.47237 12.42525 11.96187 10.67544 11.41625 11.04646 10.61635 10.52443 12.70697 13.38649 11.35408 12.26194 11.28505 13.45126 13.82557 \n  11.66839 18.54571 19.34097 15.28023 16.99143 15.16772 15.61421 11.90284 12.48574 13.0267 11.92334 10.24209 11.53736 11.04919 10.13369 10.87534 12.32853 13.07113 11.1777 12.35379 11.42702 13.24903 13.47682 \n  11.33042 18.52498 19.28227 15.3864 16.97915 14.79772 15.07273 11.31091 12.86657 13.35474 11.33974 9.940867 11.48389 10.81812 9.995729 10.97024 12.09934 12.44435 10.87501 12.38766 11.07067 13.29669 13.62211 \n  11.3056 18.38368 19.13547 14.39207 16.36372 14.8709 14.99244 11.87787 12.69045 13.26806 11.46194 8.540175 10.51303 10.84584 10.27139 10.64636 11.47711 11.95679 10.57964 11.26044 10.76696 12.47983 12.5918 \n  11.55642 18.09599 18.73145 15.37899 17.526 15.3725 15.14406 11.61225 12.45738 12.59422 10.7795 8.732772 9.834822 10.28893 9.671982 10.17871 10.94767 11.20057 10.26523 10.61838 10.52447 10.65674 11.38504 \n  10.35312 17.61216 18.04445 15.89868 17.93677 15.43736 14.92465 10.95503 10.74119 11.10365 10.10367 8.769894 9.549344 9.448477 10.16095 9.991289 10.12919 10.67581 10.30081 10.2757 10.61878 11.08467 11.66054 \n  10.57029 16.80257 17.43232 15.33712 17.40169 14.69754 13.7979 10.32226 10.54766 10.62139 9.538151 8.558439 8.763721 9.43328 9.823753 9.941569 10.20876 10.29988 9.839418 10.4947 10.67628 10.63656 11.36743 \n  10.88069 16.40481 16.94452 14.63999 16.55998 13.75831 12.04815 10.07983 9.779847 9.41483 9.367539 8.638872 7.551649 8.591156 9.22356 9.253392 9.312204 10.12255 9.771526 10.66726 10.28885 10.70903 10.99041 \n  10.68995 15.9614 16.66981 12.87561 15.32809 13.38852 13.34967 10.08965 9.267484 8.510974 8.937634 8.066225 7.492024 8.559677 9.379137 8.934621 9.395594 9.947574 9.762503 10.16802 10.52471 10.62313 10.52163 \n  10.10682 15.73363 16.55744 12.98704 15.02876 13.22308 13.64594 9.306398 8.513678 8.840482 8.639846 8.813548 8.690471 9.372956 9.21609 9.271674 10.22423 10.17199 9.91317 10.44354 10.81481 10.71306 10.58567 \n  10.53498 15.85452 16.48894 13.69206 15.73015 14.98417 13.35866 12.12415 12.66079 12.8636 12.57128 11.65822 10.42173 9.932479 10.30401 10.88577 10.69672 11.60742 10.67614 10.5448 11.20179 12.58635 13.41792 \n  10.96499 15.49205 16.39072 14.58421 16.09194 14.12068 12.85947 10.9668 11.6846 11.61401 11.32033 10.1519 9.595464 9.126978 9.282423 9.871722 10.47498 11.93141 10.77083 10.79808 10.82797 12.26179 13.4949 \n  10.02513 14.95054 15.62905 12.19269 13.6047 13.04639 12.49895 9.641859 10.20514 10.12763 9.829097 9.059594 8.440591 8.796917 9.133607 9.019018 10.19306 11.17522 10.55359 10.32446 10.81375 11.08818 12.5863 \n  9.422004 14.69329 15.27407 12.65151 13.94985 12.99975 11.70039 9.886936 9.611949 10.09684 9.314202 9.766679 9.321723 8.8813 8.354034 8.528647 9.770875 10.59045 9.79849 10.28119 10.74567 10.74199 12.01325 \n  11.32263 15.05788 15.25787 15.88041 15.08022 14.13194 12.75217 11.34698 9.656963 9.717936 9.331264 8.585823 9.124638 8.87212 8.442982 8.890512 9.943332 10.48704 10.23122 10.30991 10.68609 11.49976 11.52623 \n  13.40004 15.62923 17.28662 19.34645 17.7522 14.88166 15.30356 13.29276 11.17599 10.1756 8.496209 8.687905 8.767036 7.138587 7.905816 9.155358 9.870092 11.34072 10.64145 10.56284 10.93426 11.27267 11.83103 \n  14.40832 16.92628 18.28235 19.92572 17.42484 16.51931 17.17439 13.85876 11.32172 10.88191 9.843261 8.557543 8.702249 8.43864 8.905317 9.214272 10.79284 11.19663 10.4797 10.33966 11.11496 11.59549 12.62567 \n  15.07293 17.23655 18.7453 20.03891 18.20394 17.32358 16.8287 15.43667 13.0998 12.50691 10.92344 10.46035 9.055417 9.849059 9.764614 11.06528 13.47688 13.99895 12.79779 12.12013 14.56175 14.29823 14.93593 \n  15.40606 17.37957 18.26671 19.24368 19.16639 17.99058 16.59817 14.71303 12.86606 12.04343 11.7385 9.705905 9.335643 9.112566 9.626029 10.41576 13.39695 13.71364 12.28225 11.58019 13.76471 13.65422 14.2695 \n  15.64262 17.64327 17.19793 17.43849 19.78349 18.46711 16.14888 16.3467 13.90007 12.84516 12.72527 10.46768 9.428706 9.794108 10.62751 11.56921 13.06464 12.97483 12.06074 12.42412 15.20449 15.17994 15.41442 \n  15.52258 17.33565 17.81485 18.67915 20.30933 18.47157 16.206 16.37829 16.18498 14.41841 13.32267 11.18768 9.268024 10.2243 10.31914 12.25662 14.13956 13.31647 12.61077 13.04033 15.24885 15.47131 15.91226 \n  14.72044 16.24851 17.39948 18.02982 19.91796 18.15676 16.86558 16.89674 18.34361 15.89882 13.7806 11.83443 10.31598 9.947871 10.88693 13.04681 14.78731 14.09249 13.07614 13.30486 14.96555 15.89365 16.21339 \n  12.94438 14.262 17.79223 17.94734 18.41548 17.99884 16.59502 17.46818 19.89834 17.3267 14.68132 12.74071 10.74997 11.11081 11.97623 14.37372 15.06054 13.62777 12.74747 14.17785 13.22865 15.07573 15.67369 \n  11.9413 14.24815 17.19899 17.78853 19.11386 17.95886 17.36403 17.78174 19.56396 18.41936 15.83994 13.5232 11.30285 11.13494 12.42168 14.83165 15.21284 13.93472 14.22501 15.48852 14.69647 14.61711 15.37134 \n  13.80032 15.34109 17.01766 17.4297 17.96654 17.89771 17.45484 16.8976 18.80153 19.64696 17.77114 13.78843 12.49898 11.85447 13.19477 15.72658 16.27253 14.45719 14.41123 16.36125 15.85711 15.05885 15.80895 \n  14.42734 15.95719 16.8165 17.40023 17.72437 18.32386 18.0716 16.22936 18.2776 19.88119 18.43486 14.89068 13.09634 12.62326 14.15393 16.27906 16.78207 14.59756 14.30995 16.8557 16.74701 13.89337 15.01136 \n  13.1981 15.42621 17.47243 17.46376 16.60345 17.87163 18.14639 15.80742 17.8999 18.86058 18.78569 15.2696 12.82393 12.26846 14.426 16.64136 16.84205 14.60646 14.58007 16.73913 16.8489 13.78548 15.02061 \n  14.53758 16.3012 17.77195 17.30224 18.26668 17.24618 16.88194 15.98161 16.4734 18.86712 18.13484 16.05925 12.78708 12.62607 14.48131 16.29807 16.06342 14.38513 14.33487 16.47281 16.5306 13.28973 14.15116 \n  13.29329 15.40082 17.00095 16.67248 17.51397 17.87264 17.22511 15.87745 16.17892 17.66627 18.2972 16.80437 14.20589 12.99962 14.83743 16.62644 15.83631 14.91555 14.99209 17.03086 17.57478 15.26948 15.94518 \n  12.60118 14.90419 15.67589 16.70849 16.94395 16.61985 16.03358 15.05487 15.99355 17.37237 17.7354 17.29265 14.00175 12.25772 14.06873 15.4484 15.89154 14.37778 13.64605 15.54983 15.959 14.05933 14.62753 \n  13.46687 15.90945 16.95177 16.9344 16.38556 16.47206 16.12689 15.33399 16.03906 17.06773 16.99802 17.40662 13.44633 12.45146 13.97935 15.02217 15.57034 14.04656 14.18954 15.08655 15.59686 13.81427 14.97765 \n  13.90775 15.34541 16.23319 17.18387 17.43214 17.35052 16.137 15.33103 15.5793 15.9622 16.35075 16.71717 13.52683 12.29098 13.29745 15.11607 15.76651 13.92764 14.35643 15.45294 15.56918 14.29957 14.75815 \n  12.64945 15.05234 16.66335 17.67402 17.42719 17.03349 15.29472 13.20675 14.79218 16.15494 16.06722 15.88496 14.37258 12.09099 13.10366 14.55416 15.20259 14.15096 14.36049 15.3579 14.84148 14.77236 15.21402 \n  13.63886 15.13448 17.12833 17.25077 17.57319 16.51949 14.79358 14.33071 15.40003 15.31295 14.707 15.51841 15.19862 12.16728 12.38076 13.97288 15.01122 13.84911 14.36896 15.99493 15.19653 15.71203 15.79622 \n  14.08951 15.27791 16.67466 17.38719 17.48137 15.49804 14.64399 13.99431 14.06412 14.96719 14.45313 15.07616 15.22869 11.85608 11.80214 13.4829 14.47193 13.28767 13.82474 15.54498 14.68076 15.78218 15.55037 \n  13.55869 15.54187 15.30116 16.07854 15.19114 14.89549 14.28598 13.40435 12.58551 12.71723 13.51417 14.44852 13.74717 11.34321 11.73631 12.8637 13.46484 12.86962 13.4271 14.9927 16.06477 17.438 17.00769 \n  14.03767 15.96629 15.7353 15.65322 14.90481 14.81491 13.83562 13.2442 12.39499 12.31491 12.90394 14.30139 13.67956 10.38161 11.00745 11.82061 12.68529 12.26423 13.03794 13.27276 13.62125 14.79159 14.69412 \n  14.69835 16.23426 15.85394 14.956 15.55784 15.1201 13.12001 11.77338 12.35275 13.03831 12.70205 13.89809 13.49535 10.74578 10.39047 11.01446 12.48515 11.93507 12.14398 12.33028 12.54093 12.23906 11.828 \n  13.74119 15.01042 14.63525 14.21064 15.04048 14.53166 13.30235 11.51442 11.54563 12.75932 12.87387 12.97661 12.22388 9.737226 8.855085 10.95898 12.41875 11.5811 11.65182 12.16752 11.78344 11.6825 11.58462 \n  13.79247 14.65056 14.39971 14.56042 14.50872 14.48325 12.4725 11.32357 11.69767 11.76651 11.72759 11.75854 11.63687 9.03346 8.632442 10.05544 11.80099 11.283 11.6399 11.7433 11.51521 11.30795 11.44739 \n  12.4817 13.96644 14.94901 14.22443 14.7217 14.6918 12.00653 11.63244 11.49402 12.39865 11.62017 11.95335 10.76735 9.714913 9.972126 10.44865 11.5843 10.77267 11.39896 11.29488 11.80279 12.45774 12.97729 \n  10.99601 12.48925 13.91558 13.39563 12.76022 12.97499 10.67527 11.2872 11.05415 11.66541 11.35227 12.07333 10.91728 8.470509 9.390297 9.98071 10.65596 10.24184 11.05679 11.06191 11.15756 11.02771 10.34172 \n  11.55889 13.16734 13.01277 13.71551 11.48029 11.84606 12.16008 11.11222 11.96976 12.21278 12.98672 12.49252 11.65213 12.38936 13.03628 13.42355 12.62503 11.73549 11.11625 12.92801 14.35214 14.86793 15.02906 \n  10.42775 12.77446 12.08269 12.53821 11.88333 11.98844 12.13725 11.12525 12.48612 13.17795 13.38511 12.48855 11.81891 12.69561 13.0315 13.13174 12.79269 11.96432 12.52114 14.89753 16.66616 17.80948 17.48282 \n  11.87147 13.35178 12.29651 13.07613 13.38078 12.15471 11.58152 10.57638 11.48294 11.66988 10.83331 10.95618 10.80718 12.60706 13.70898 13.6584 13.12783 12.36247 13.81388 16.36983 18.19867 19.32249 19.17922 \n  11.74805 13.03258 11.83647 10.99839 11.53884 11.58733 9.78068 10.00441 11.77152 12.2512 12.23087 13.11207 12.52222 13.45929 14.83094 14.73086 14.22945 13.92837 15.33029 17.7077 19.34477 20.7841 21.06674 \n  12.91207 13.92127 12.60293 11.2707 11.34953 11.66406 10.61612 10.41087 11.90737 12.03745 12.62049 12.73641 12.31181 15.63897 15.29306 15.0111 14.84808 15.03202 16.69465 18.62388 20.75715 22.16574 21.82943 \n  11.44404 13.17524 11.91981 11.4003 11.81657 10.4973 11.08138 10.91362 11.54249 11.68209 11.96895 12.71395 12.69716 15.29071 16.25213 15.87629 15.68893 14.98099 17.12889 18.67869 20.67893 22.07556 22.39026 \n  12.4943 14.38828 15.40293 14.53412 12.63508 10.61958 11.04276 10.82849 11.58219 11.86627 13.09368 11.76773 11.85476 15.56555 15.54773 14.94056 15.46294 14.71608 16.38725 18.32511 19.88208 20.835 20.72138 \n  12.06502 16.88607 18.26798 18.51961 18.70255 16.0556 11.92916 12.43737 13.55841 13.30871 12.92406 12.8846 12.13316 15.64249 15.85884 15.73912 15.52897 14.45106 15.96146 17.69323 18.59188 19.02813 19.20515 \n  11.12339 17.63247 18.67913 18.09006 20.21992 17.90995 12.6137 12.48078 12.48313 12.308 12.5629 13.46077 13.18955 15.1113 15.49067 16.01841 16.40285 15.20319 16.30907 17.38044 16.9833 16.74973 17.5288 \n  11.91933 17.71219 18.231 18.7819 20.81494 18.03944 12.80576 12.62215 13.70358 14.11044 12.98072 13.73609 12.88998 16.17216 15.98503 15.40534 16.2627 14.74855 14.94189 16.8815 16.57269 16.14612 17.22886 \n  10.80071 17.88858 18.37441 19.57571 20.85023 16.92813 14.54551 14.11315 14.60858 14.76622 14.24647 13.50114 13.44903 15.14018 15.77174 16.55495 16.70045 14.63158 14.95225 16.897 16.51554 16.39054 16.95824 \n  10.11735 17.24759 17.42141 19.76315 20.66429 16.31513 15.35933 15.46266 14.2526 14.75529 14.8134 13.60172 13.60854 15.0717 15.27205 15.8339 16.31969 14.84996 15.4993 17.3387 16.82842 15.77378 16.33088 \n  11.58894 15.94406 15.80265 19.82332 19.81112 16.33015 15.83328 16.12075 14.11878 13.67492 14.12749 13.19047 13.91129 14.98374 14.91681 15.74825 16.61319 15.2014 15.57807 17.29531 16.63654 15.11069 16.41315 \n  12.11817 16.37547 16.11933 19.74942 19.52616 15.253 15.60251 15.62886 13.73787 12.94972 14.53512 13.22932 13.03554 14.42677 14.02384 14.75253 15.97637 14.65869 15.00835 17.03261 16.1345 14.50001 16.3125 \n  12.40414 17.09673 16.56095 19.30345 18.83337 15.53385 15.46334 15.14222 13.0195 13.65549 14.05797 13.27337 13.1787 13.58766 13.74914 13.84215 14.70384 13.81669 14.36711 16.36557 16.29565 15.23389 17.42854 \n  13.11347 16.62823 16.08442 18.65703 19.09037 15.8935 15.2197 14.41059 14.00731 14.22315 14.2603 13.98392 12.74996 12.83496 12.62025 12.43474 14.70534 14.04083 13.31598 15.78194 16.0346 15.06308 16.98965 \n  13.64474 17.90531 17.46792 19.65909 19.84337 16.36866 15.0947 14.08054 14.56519 14.61388 14.04171 13.45949 11.97165 12.38503 12.46181 12.36982 13.73913 13.27664 12.86066 14.10406 13.75239 13.30816 15.46512 \n  14.14659 17.85538 16.63506 17.69785 17.37612 14.4621 14.21311 14.33 14.55272 14.0266 13.34313 12.6474 11.67851 12.07374 11.39458 12.00585 13.00983 13.07051 12.53945 13.83851 13.02929 13.78781 15.03182 \n  14.42228 17.95903 16.79436 17.2867 17.37424 14.4423 12.56357 13.39425 14.97358 14.38745 12.16811 12.31725 11.24478 11.62687 11.66598 11.82592 13.17022 13.03793 12.44336 12.93122 12.50479 13.24247 14.70499 \n  14.74926 17.10213 16.10866 18.41386 17.76688 14.66671 12.0519 12.36404 14.64657 13.54079 11.52991 11.67943 10.9411 11.91207 12.82024 12.68861 12.79371 12.74705 12.14265 12.87091 12.87852 13.3739 14.64138 \n  14.77377 17.52547 16.45933 18.03106 17.99345 14.37569 12.28482 12.38711 13.49167 12.96972 12.2464 11.9446 12.06746 13.32547 13.42399 12.804 13.77554 13.8069 12.38337 13.585 13.03204 13.04344 13.17559 \n  14.33936 16.05802 15.20399 17.29784 16.82894 14.67938 13.40503 14.50885 16.62795 16.48669 15.85748 14.00688 13.75563 13.0535 13.17885 13.77508 14.15859 14.48487 13.08349 14.30881 13.77487 13.4736 14.49444 \n  14.44479 16.99548 15.77001 17.10963 16.52903 14.38944 13.44239 14.06731 16.73449 17.81567 16.47066 14.45036 13.36218 11.99206 12.16488 12.52671 13.19155 13.33347 12.81071 14.34716 14.2478 14.17321 15.78081 \n  14.02579 17.08305 15.59479 15.89314 16.72221 14.24861 13.47705 14.10365 17.43085 18.94127 17.04 14.55132 12.30284 11.67238 12.13895 11.74947 12.48997 12.62799 12.61127 14.23425 14.47474 14.48953 16.6846 \n  12.98601 16.43487 15.30097 15.82755 15.67639 13.93307 12.06077 14.01533 17.31017 17.03305 16.06872 14.63635 13.17454 12.51504 12.19607 11.30268 12.40507 12.31048 13.08197 14.41822 14.24439 14.75511 16.61187 \n  12.36717 14.63769 12.81204 14.45165 13.75739 14.0802 13.48325 14.81929 17.03195 17.97369 16.36871 14.08131 13.45929 13.48154 13.22458 13.06752 12.79095 12.71402 13.04852 14.30993 14.63789 14.94942 16.90777 \n  11.93372 14.51598 12.94251 14.97276 14.5037 13.14109 12.6004 15.28386 17.44633 17.41194 15.19083 13.97468 12.30335 11.49983 12.01657 12.22904 12.7571 12.17981 13.11903 15.56299 14.76678 16.0535 16.8217 \n  12.47566 14.19673 11.79418 12.79603 13.27397 13.03157 14.51644 15.58098 16.45773 16.79338 14.77104 13.59812 12.80408 11.51495 12.39793 12.11381 12.55917 12.43729 13.31075 15.56109 14.98054 15.78551 17.06624 \n  12.2613 15.1282 13.99666 13.71514 14.27644 13.59662 14.62273 14.96381 16.1037 15.93762 14.79321 13.20536 12.09543 11.00414 11.58279 11.8383 12.9191 12.51326 13.47569 16.26331 15.60605 16.11314 16.97496 \n  12.43962 14.93872 12.93799 13.37484 14.13616 13.94297 13.31241 15.01747 17.49583 16.37276 14.13916 12.80372 11.91654 10.96919 11.34828 11.55524 13.11632 12.65655 13.44765 15.82003 15.211 15.98718 16.41879 \n  12.20704 14.56072 12.76487 14.66424 14.36893 13.81488 12.67005 14.58511 15.8139 15.15328 13.72443 12.0736 11.75713 10.39046 10.3162 11.07518 13.42291 12.18517 12.6754 14.56121 13.61762 14.73406 15.99769 \n  12.26719 14.83184 13.45157 13.9031 13.37387 13.42337 13.16261 14.01834 13.45282 14.0881 12.42882 10.71366 10.67623 9.888527 9.556181 10.42893 12.93971 12.08191 12.30767 14.6603 13.51334 14.00465 15.0682 \n  13.72396 15.37463 14.90107 14.14883 14.71334 14.23447 14.62967 15.41844 13.9625 13.62733 12.02162 10.61794 9.693156 9.38163 9.607562 10.24143 12.10383 11.62002 11.61677 13.37127 12.76904 12.98495 13.14606 \n  12.20455 15.08801 16.28204 15.02526 14.91302 14.54155 16.05799 15.24317 13.17851 13.23946 11.95253 10.98236 9.365788 9.214337 9.505456 10.4926 10.92743 11.19956 12.08282 12.89608 12.90349 12.21022 12.78775 \n  13.37813 14.82368 16.03482 15.19005 16.00402 15.02282 15.84676 15.76265 13.34728 12.43027 11.99226 11.34601 9.200621 9.239662 9.540243 11.00728 12.16874 11.82533 11.95636 13.50077 12.4501 12.26641 12.92042 \n  12.66223 14.38916 15.40475 14.94944 16.37963 15.2842 15.38037 15.8695 13.61753 13.21642 11.7801 11.01452 9.542067 9.19785 9.696535 10.70263 12.5226 12.46992 12.17822 13.79243 13.24585 13.34737 13.80106 \n  11.79797 13.75565 14.85456 15.8272 16.72862 15.18555 15.07867 15.58954 14.36672 13.03338 12.42223 11.01965 9.557907 9.226222 9.848079 10.37486 11.38179 11.42391 12.02948 13.78323 12.73048 13.11424 13.94043 \n  12.11479 14.20692 15.95607 15.77075 15.94264 15.04848 14.68504 15.58499 16.73163 14.876 13.04782 11.34189 9.554831 9.312258 9.405445 10.54039 12.08341 11.93015 12.28186 14.35123 13.82728 13.614 15.07887 \n  11.63898 13.24526 15.91903 15.04351 15.44301 14.33202 14.69388 15.04394 16.66434 15.8622 13.70809 11.39564 9.984374 9.255429 9.771338 10.38831 12.17067 12.11052 12.20296 14.49279 14.43369 13.75218 14.74203 \n  12.24345 14.6031 16.65611 14.82507 16.38684 15.87055 14.16241 14.53406 16.72972 16.78175 14.29714 11.9692 10.40499 9.319419 10.12237 10.74756 13.3062 12.89304 12.51923 15.03736 15.23477 14.65409 15.5749 \n  12.77314 15.07554 16.98285 15.57631 16.88236 15.60186 13.31313 14.22181 15.56985 16.22102 14.96699 12.77368 10.60659 9.910019 11.08181 11.14588 13.15701 12.80074 12.45314 14.14474 14.5937 14.61545 14.75511 \n  11.81499 14.35236 15.86184 15.37682 15.91093 14.51173 12.01213 12.23065 14.53028 15.26377 14.16712 12.59848 10.46429 9.104154 9.218637 9.824287 12.90368 12.61128 11.938 13.29911 13.48286 12.61785 12.90715 \n  13.13115 13.74104 13.82935 14.62105 13.24596 12.30486 11.74188 12.57558 13.35646 14.14618 12.51182 9.92897 9.892784 8.203323 8.843456 9.73543 11.10688 11.40638 11.2225 11.48934 11.82256 11.33256 11.55696 \n  13.5014 14.46064 13.74532 13.76357 14.51184 13.47387 12.36466 13.09748 12.37077 13.78026 12.56234 10.40441 9.652602 9.258573 9.640882 10.48315 11.37579 11.28799 11.69723 12.14306 11.93345 12.913 12.47232 \n  12.11707 14.41063 14.2667 13.93633 13.81357 11.92622 11.39311 12.56514 11.91435 12.2172 11.83334 10.78043 8.693699 9.34746 10.5232 10.74675 11.27402 11.17691 11.69285 11.59679 11.87287 12.48645 13.45397 \n  12.73287 14.28872 14.12864 14.03616 13.14685 12.7475 12.18416 12.10903 11.98855 12.79712 14.14206 13.79637 12.14143 12.49956 13.05192 13.06696 12.86376 11.90433 12.45795 13.79512 14.72743 15.6082 16.03671 \n  13.99284 14.59781 15.86497 15.46929 15.35721 14.4506 13.86872 13.70982 12.77764 13.87713 16.70483 16.12365 13.74394 14.14882 14.72046 14.79044 14.55702 13.26187 13.4715 15.52675 16.2828 17.03688 16.70895 \n  13.34487 14.76827 16.66223 16.6201 16.95358 16.41091 14.59964 14.13615 14.98613 15.52808 16.94203 16.33436 13.65864 12.67898 12.89719 13.15985 13.87055 13.7345 13.81801 15.46476 15.5521 15.17291 16.18393 \n  11.05816 13.38546 16.02215 16.0239 16.26703 16.0995 16.00097 15.06918 15.39436 16.33123 17.5566 17.69474 14.73381 12.76004 13.46956 13.62351 14.9516 14.46614 13.86967 15.92621 15.77614 15.14017 16.05052 \n  13.44674 14.49088 16.24643 15.87667 15.80228 16.08157 16.27578 16.11953 15.71647 16.77408 17.38955 17.5013 14.82175 12.91548 12.99751 13.53425 14.71743 14.50213 14.5002 15.80028 15.50727 14.7684 16.64701 \n  14.21669 14.68321 15.45795 15.69659 15.90129 16.00284 16.18194 16.61241 15.75285 16.67905 17.6036 17.33829 14.63122 13.52661 13.50696 13.30114 14.47372 14.06641 14.2557 16.1715 16.02145 14.45178 16.56786 \n  13.89403 13.90886 13.8904 15.63989 16.239 16.28278 16.61728 16.93481 16.17262 16.97161 18.37757 18.09198 15.23442 13.31642 13.7317 13.67162 14.61277 14.06051 14.15388 16.12131 16.52321 14.41898 16.15249 \n  13.62738 14.29071 14.26743 15.39755 16.17412 15.93856 16.81614 17.35265 17.03794 17.52091 19.20687 18.71931 15.41284 13.25959 14.02276 14.49864 15.36796 14.59919 14.92057 16.34993 16.91476 14.57673 16.4135 \n  13.91304 14.38333 15.62968 15.92608 15.88913 15.46424 17.23949 17.6737 17.75764 18.32361 19.38836 18.81548 14.75313 13.59059 14.47715 15.14762 15.94664 14.38755 14.47487 16.32241 16.61687 13.88076 16.03177 \n  13.85443 14.63751 16.63829 16.22158 16.00957 14.22576 17.54068 17.94837 17.70362 18.35151 19.07424 18.78005 15.38741 13.65261 14.89409 15.66142 16.46598 15.04117 14.94388 16.69312 17.13902 14.49912 16.41131 \n  14.16736 15.20732 17.17613 15.65355 14.81104 14.93489 17.35307 17.69239 17.67073 17.9412 18.96013 18.70328 15.56409 14.20707 14.99696 15.9745 17.04941 15.52152 15.42804 16.55275 17.19493 14.82115 16.61891 \n  14.55787 15.56332 17.40187 15.79714 15.16877 15.23872 17.43352 17.88713 17.42919 17.76297 19.16017 18.89678 16.21667 14.49569 15.32538 16.22569 17.27599 15.67997 14.60294 16.08368 16.37376 14.28088 16.07994 \n  14.28819 15.29579 16.9726 15.32225 14.96721 14.86766 17.3646 17.55653 16.88566 16.39165 17.97582 17.84254 15.61118 13.325 13.99773 15.29101 16.41687 14.61869 14.14026 15.54824 15.78234 13.5513 15.05351 \n  12.89534 14.19264 16.16715 15.45553 14.97155 14.18898 16.54575 16.86909 17.18435 16.91364 17.95696 17.44936 14.9484 14.08921 14.70956 16.02505 16.75773 14.69309 14.29639 15.83831 15.93069 13.20353 15.10151 \n  11.07287 14.01731 15.98684 15.85503 15.7026 14.17124 15.66209 16.81634 16.69689 17.06315 17.20102 16.85413 14.60714 13.95707 14.35706 15.67642 16.10085 14.48048 13.75637 15.7046 15.97279 12.9786 14.57301 \n  13.20215 14.88027 16.1391 15.30331 14.56342 14.65112 16.31849 16.70032 16.30379 16.66877 17.15785 17.35987 14.50481 13.62881 13.80476 16.18898 16.30147 13.83495 13.66053 14.89267 14.77247 12.55925 14.45503 \n  13.06126 13.95905 14.72861 15.52299 15.57437 14.80034 15.9755 16.06871 15.0617 16.14234 17.04153 17.21765 14.65441 13.15693 13.40964 15.61284 16.12287 13.8438 13.76604 15.52066 15.88898 13.41924 15.27078 \n  12.30977 13.65725 15.62276 15.12077 15.0009 14.32717 15.56222 15.53802 15.59415 16.0091 15.70288 16.7213 14.29013 13.25526 13.82748 14.57323 15.08817 13.3787 13.22771 15.28969 15.54399 12.92044 15.89454 \n  13.2355 12.87303 14.13755 14.8824 14.98317 14.09578 15.47559 14.69907 14.95037 15.00035 15.11841 15.08056 14.14125 13.50607 13.85954 13.90839 15.27832 13.46804 13.2138 15.63453 15.70406 13.72386 16.19327 \n  14.09465 13.80971 14.12421 15.16251 15.51726 14.75089 15.25305 14.35832 14.27529 14.6144 14.28123 15.06938 13.85847 13.27495 13.16495 13.6391 14.85534 13.8216 13.19121 14.84105 14.6136 13.33247 14.90938 \n  14.17169 14.05926 14.38466 15.14356 15.18883 14.75758 14.63411 13.4688 13.57265 14.68271 14.24092 14.8144 14.59175 13.15273 12.52619 13.557 14.39644 13.34105 12.86075 15.03354 14.76084 13.2114 14.36096 \n  12.94696 14.0161 14.38512 14.93382 15.28973 13.96826 13.00536 14.16216 12.7634 13.37025 13.69937 14.27973 14.28271 12.20191 11.58065 13.0691 13.86918 12.99897 12.07017 12.88836 13.36119 13.8559 13.72427 \n  14.00163 14.74522 13.96561 13.84176 13.14617 12.28493 13.21515 13.64575 12.21422 12.96211 13.65326 13.52429 13.38388 11.56683 10.93623 12.6721 12.94885 11.75394 11.93754 12.60298 12.66667 13.39652 13.23497 \n  14.01837 14.65643 14.34931 12.89079 12.44645 12.47288 12.34212 12.92817 12.88704 12.13856 13.52651 14.26985 13.20721 11.13747 10.50563 12.04486 13.04915 12.82268 12.21847 14.11812 14.85144 15.37979 15.23997 \n  13.68709 14.73938 13.74758 13.45861 13.16367 13.00546 12.78111 12.54126 11.39514 11.72749 12.81818 13.32782 12.47606 10.72879 11.57598 13.16603 12.89361 13.47785 12.73763 14.78968 15.50553 18.04643 17.43831 \n  12.58177 13.59478 14.05649 13.31381 13.11898 12.32821 13.0021 12.62218 11.5436 12.16554 12.48717 11.81394 10.50265 8.973746 10.09016 12.06378 12.39155 12.9348 12.42843 14.2313 14.86099 18.31309 17.32769 \n  12.75411 12.6887 12.49659 12.86026 12.59906 11.34449 12.41792 12.40671 10.25577 10.55363 11.62938 11.7192 11.39313 9.014958 9.833184 11.20295 11.54293 12.10884 12.57974 14.2528 15.04182 16.35394 17.43106 \n  13.07687 12.93932 12.05013 11.10465 10.92198 10.16203 11.9019 12.00359 11.20652 11.09058 11.98129 10.94307 10.32444 9.561 10.09412 11.1652 11.89071 12.46157 13.37886 14.81377 15.79583 16.46983 16.3099 \n  12.44068 12.16542 12.749 11.51701 11.75818 10.98072 11.45177 11.79877 11.41194 10.86352 11.39708 11.80494 10.21916 10.17022 10.94074 12.73651 13.22818 13.90771 14.318 16.45604 17.52512 18.12885 17.99037 \n  12.84129 12.74346 11.62644 11.11886 11.60124 9.904121 10.04816 10.7376 10.31966 11.05361 11.45463 12.15746 11.15053 10.69711 11.84554 13.98456 14.60289 15.31413 15.49967 16.84238 18.05069 19.01266 18.84834 \n  12.53398 11.96433 9.244778 8.572387 10.26614 9.39289 10.5042 10.72253 10.65647 12.75043 13.54582 13.20332 12.30947 11.8775 13.39289 15.73803 16.03198 17.65893 17.08116 18.5041 19.5771 20.24899 20.35165 \n  12.00563 12.20351 10.276 9.838881 10.18145 9.774684 9.775256 10.85217 11.57201 12.9943 13.72266 13.57533 12.36394 12.41757 14.64912 16.40559 16.40833 17.94178 17.0117 19.56192 20.42689 21.10626 20.54123 \n  11.91491 12.22656 10.11695 11.68905 13.45684 12.16579 11.17595 11.02882 13.19395 13.89767 15.23678 15.18915 13.55568 14.68092 15.77575 16.75733 17.13061 17.34155 17.21397 19.74595 20.57611 22.05666 21.36359 \n  11.47355 11.28028 10.45217 11.66897 13.02617 12.40421 12.3838 12.38136 13.96514 15.68431 16.50488 16.14618 15.39929 15.91039 16.42896 17.51905 18.45585 18.59583 17.75705 19.62965 20.81224 22.27122 21.80147 \n  12.52662 11.94858 10.55505 12.42413 13.77102 13.32065 12.9342 13.66854 14.39565 16.63391 17.94618 17.4248 17.46566 16.57822 16.48766 17.86062 18.27674 18.54208 17.23242 19.31924 20.2264 21.92178 21.3364 \n  12.02873 11.26655 9.571183 11.58556 13.19479 12.65055 12.59585 14.40476 14.95008 16.4713 18.34317 18.11756 17.86362 16.10263 16.13897 16.93494 18.05787 17.58092 17.09885 18.80086 19.4799 20.65734 19.97151 \n  10.86476 9.108546 9.552567 11.91356 12.38227 12.85921 11.95166 14.44887 16.19041 17.26532 17.9296 17.84677 17.18984 16.35882 15.73214 17.40462 17.33592 16.97078 16.5151 16.88156 17.47563 18.54997 17.5454 \n  12.60442 11.37389 10.2908 11.55008 13.28062 14.39302 13.83146 14.80365 16.86215 17.7065 17.82295 16.90414 16.20468 15.93856 16.19014 16.84039 17.83888 16.61141 15.98524 16.43695 16.56059 17.5152 17.1277 \n  12.41213 11.59318 10.9033 11.81183 13.5534 12.9817 12.88539 14.86807 16.76102 18.08833 17.84195 17.58156 15.95464 15.7454 16.94265 17.86619 18.44193 16.60484 16.43938 17.78119 16.30627 18.12034 18.17815 \n  13.1731 10.92382 11.44889 11.58021 12.51424 12.61171 11.91807 14.35635 16.45222 18.2344 18.02634 18.44849 16.43503 15.31518 16.52777 16.50167 17.21136 16.07273 16.42845 17.90891 16.48678 18.03056 17.71963 \n  12.32748 11.78882 9.929072 11.31927 12.64543 11.5685 10.86378 14.32529 17.28631 17.74572 17.08748 16.90873 15.3218 14.87652 15.57612 15.72205 15.87119 15.72217 15.76832 16.80227 16.46172 17.64037 17.64002 \n  12.19527 11.26126 10.91108 11.51357 11.88646 12.82152 12.50746 15.10742 17.22483 18.49776 18.38831 17.32627 15.58188 14.17714 15.13854 16.44323 16.22381 16.09768 16.18013 17.33267 16.986 16.6601 17.38706 \n  12.38316 10.9315 10.43465 10.56535 12.23314 11.90101 12.91362 14.65029 16.51646 18.22181 17.65647 16.37604 14.34329 13.71848 14.16311 15.41569 16.0204 15.15731 15.41514 16.67949 17.00598 15.89455 16.97392 \n  11.30577 10.28441 9.945932 11.39331 12.30649 11.96362 11.83533 14.81513 17.35564 18.33072 18.05184 15.06798 14.07956 13.20424 13.25025 14.4972 15.11539 14.80095 14.70875 16.30007 16.03745 14.93294 16.70602 \n  11.03609 11.63719 10.21918 10.6167 10.88359 11.86974 11.941 14.54243 18.29357 19.38234 16.87861 14.88691 13.15115 12.30057 13.38792 13.84875 14.85546 14.83342 14.70834 15.97845 15.37833 14.04472 16.18783 \n  13.34986 14.78248 13.79236 13.17295 12.78349 12.70567 12.45625 14.42082 17.43404 18.18635 15.59477 14.50266 12.80653 12.16918 12.35644 12.73297 13.97416 14.38635 13.72448 14.86592 14.04201 13.30526 16.08755 \n  13.90898 15.20264 15.9369 14.62706 13.72583 13.84371 14.70597 16.07141 18.13611 18.26731 15.36589 14.14722 12.81018 11.74895 11.73215 12.83022 13.8598 14.30199 14.02788 15.60954 14.73503 13.21847 15.28059 \n  12.65622 13.64794 16.40841 15.1159 12.92702 14.19901 14.66136 16.53231 18.85972 18.87691 15.47901 14.02315 13.04305 11.90804 12.02419 12.18788 13.65167 14.87863 14.52754 15.9854 15.23429 13.42042 14.61205 \n  13.16586 14.09224 15.83176 14.90314 13.58085 14.20237 14.74656 16.52872 18.05439 17.30598 14.93832 14.26765 12.49032 11.86487 11.99516 12.17831 14.06437 14.65313 14.55127 15.61084 14.85131 13.26807 13.69388 \n  13.4008 14.57262 15.16415 15.02138 13.99929 13.74122 14.89686 16.43497 18.12129 17.57994 14.38773 13.34021 11.77359 11.37652 10.77275 11.62928 13.2342 14.23693 14.04607 15.04497 14.55735 12.52344 13.15258 \n  12.58941 13.8753 16.66035 16.01036 13.94624 12.86215 14.91205 15.55473 17.18862 16.32199 14.95177 13.18178 11.81485 11.68483 12.10907 10.99695 12.64363 13.92735 13.98247 14.74136 14.57911 14.06635 14.69018 \n  12.09153 13.84327 16.73779 16.22157 14.56728 12.37056 15.10593 15.10421 16.23268 15.88102 14.39125 12.42256 11.36509 10.85059 10.98364 10.62551 11.97378 13.79792 13.98639 13.31582 13.83742 14.01882 14.74063 \n  14.35417 15.46001 15.97281 15.97872 15.05301 13.271 14.85252 14.8182 15.14593 14.99852 13.87889 12.85231 11.08199 10.78992 11.17402 10.49343 12.2052 13.27493 13.57413 13.50568 12.8814 12.89545 14.14766 \n  15.11954 16.42943 16.03817 15.8695 14.94205 13.81331 14.11605 13.90077 13.72665 14.46259 13.50304 12.15606 10.48165 10.17465 10.4161 9.912415 11.29775 13.10989 13.52075 12.40094 12.22526 13.01442 14.24785 \n  15.51706 16.90478 15.31721 15.63563 14.91287 12.8936 13.76248 14.32526 14.25805 14.36927 12.66967 12.0761 10.97497 9.48582 10.20874 10.5375 11.10218 12.73337 12.90427 12.4544 12.51494 12.39871 13.89166 \n  15.83766 17.44094 15.59742 15.76098 14.73724 13.33175 13.09907 14.17982 13.79805 13.84968 12.17967 12.07957 11.02122 10.35668 10.95256 10.26702 11.17187 12.12873 12.05996 12.1097 11.7091 12.38269 13.66632 \n  16.28121 17.97894 15.37001 15.30069 15.23669 13.93175 13.33285 13.58994 12.95194 12.94088 12.26932 12.17642 10.4537 10.94146 11.22272 10.16105 10.75595 11.85875 11.60317 11.8685 11.6532 12.81746 14.03694 \n  16.65678 18.48001 16.02887 15.72611 14.88948 13.75212 13.00821 13.84919 13.9075 12.9391 12.38781 11.60378 10.67275 10.77736 11.13959 10.14937 11.14159 12.06991 11.99633 12.57936 11.69493 12.77214 13.83402 \n  16.88027 18.81418 16.32965 15.89062 14.08585 12.9283 13.01355 14.09655 14.04627 13.70805 12.55457 12.14791 10.23291 10.64731 10.54774 10.34701 11.31384 11.85837 11.31565 12.61369 11.56602 12.69893 13.17958 \n  16.86315 18.90851 16.74496 16.61073 13.71159 11.98781 12.37382 13.89134 13.772 14.01257 12.72022 12.62209 10.90394 10.19925 10.34741 10.43047 10.72284 11.89819 11.36431 12.45117 11.00326 12.7707 13.43279 \n  16.55088 18.7428 16.48301 16.17187 14.55713 13.0492 13.09207 14.58359 13.44237 13.92513 13.25501 12.62462 10.7068 10.42912 10.70771 10.98847 11.20761 12.1386 10.86133 11.76409 10.89257 12.65522 13.48968 \n  16.31133 18.53433 16.33694 15.77417 14.38188 12.95522 13.08407 14.4475 12.69577 13.27632 12.01401 11.38529 10.35604 10.744 10.78147 10.85441 10.54302 12.20752 11.1479 11.46902 11.70803 13.0295 13.62829 \n  16.08484 18.22621 16.04434 15.1363 12.58238 11.89639 12.57116 13.53181 14.12426 14.20648 11.83826 11.15889 9.9625 10.32529 9.984441 10.63607 11.00616 12.5833 11.28041 11.6917 11.89614 12.90713 13.29698 \n  15.68179 17.81505 16.00374 14.72812 14.84708 11.26076 12.04008 13.00523 14.13205 13.28368 11.21361 10.097 9.955743 10.26499 9.792438 9.863858 11.07145 12.3472 10.51815 10.99274 11.61275 13.19388 13.72785 \n  14.55198 16.86638 15.5845 14.5592 14.73209 12.26241 10.81983 11.97698 13.21972 12.68782 10.91807 10.4126 9.59472 10.19615 9.584566 9.555467 10.64191 12.16234 10.07995 11.50145 12.38194 12.66189 12.71277 \n  13.01004 15.59743 15.64693 14.08796 13.8486 11.90227 10.5667 10.79841 12.75414 11.89225 9.598926 9.206168 9.479238 8.989665 8.048623 9.163903 10.12297 11.2002 10.10107 10.59673 10.9262 11.29577 11.6629 \n  13.91573 16.00849 15.0316 13.62253 12.95412 9.966305 10.1017 9.991467 9.596074 9.605503 9.343888 9.190509 8.865524 8.973734 8.919617 9.209815 10.08192 10.85753 10.00404 9.867455 10.36516 11.38496 11.67881 \n  14.8278 16.76171 14.70668 13.6729 13.04084 9.941384 9.693533 10.51062 10.44051 10.19218 9.282916 9.032 8.986729 8.863693 9.409104 9.42415 9.590022 10.41179 9.549519 9.795614 10.16903 11.44894 11.5452 \n  14.85072 16.98533 15.18039 13.29803 13.33594 9.623359 9.158119 10.2534 10.32673 9.353215 9.035355 9.315903 9.19397 9.060982 9.5213 9.576943 9.395948 9.738444 9.638402 9.812303 10.30602 10.88667 10.86766 \n  14.6904 17.03413 15.28008 14.86307 14.88218 11.42855 9.846802 11.10628 10.92814 10.19661 10.62403 11.59551 10.50513 9.933274 11.18404 11.79196 12.68107 11.0639 9.99734 11.25623 10.75933 12.35911 12.92669 \n  14.66271 16.80819 14.93047 15.11656 14.37493 12.24518 9.898335 10.41227 10.94259 9.562234 9.82956 10.52575 10.91687 11.3688 12.16531 13.12481 13.59379 11.50523 10.77534 12.16117 11.03448 13.25059 13.33833 \n  14.15415 16.37178 13.99285 14.13001 14.35129 12.60274 10.18616 9.21813 9.342664 9.430008 10.54196 10.54733 10.69073 12.74719 13.28319 14.68884 15.19119 12.57943 11.37738 12.86609 11.79551 14.11093 13.75384 \n  13.90892 16.035 14.79413 14.31352 13.37496 11.89549 10.30609 9.863048 9.564677 9.050714 9.766609 9.916749 9.736766 12.76469 13.29292 14.07608 15.34341 12.62214 11.65098 12.8247 11.93356 14.02104 13.58228 \n  13.60849 15.51042 14.56466 14.77384 14.10931 12.00589 9.922771 10.00272 9.233529 8.90524 9.197906 9.287741 9.224826 11.10517 11.75283 12.47408 14.07385 11.81659 10.66715 11.48033 10.96836 11.95531 11.53177 \n  12.63871 14.4074 14.43942 15.18537 14.02158 12.20864 10.17488 10.41652 8.884479 8.93423 10.05001 9.872001 10.05358 11.18607 11.13514 11.16448 12.71593 10.94455 10.9008 11.7045 11.48672 11.77495 11.38987 \n  9.470507 13.9183 15.38312 15.29352 14.31409 12.62442 10.19246 9.844234 9.015466 8.645416 9.272799 8.95722 9.29404 9.842471 10.79908 11.95937 12.56295 10.62304 10.97254 11.55685 10.80731 10.67443 10.93567 \n  9.689436 12.1227 15.04778 14.65507 12.59609 11.3594 10.29826 9.403631 8.485927 8.846539 8.928617 8.97279 8.096455 9.521686 11.13479 12.4645 12.32434 10.56936 10.17078 10.82339 10.85006 11.1649 11.38804 \n  10.98928 14.05137 14.64129 16.00715 14.09278 11.13883 9.941337 9.854771 8.722589 9.290672 8.857082 8.991954 8.21919 9.559203 12.24082 13.63578 12.84687 11.02113 10.59677 11.14553 10.55739 11.74764 11.36405 \n  12.63155 15.67096 14.68544 16.10676 14.76892 11.35606 9.204973 8.561191 8.504937 9.011736 8.932889 8.941728 8.647584 9.663374 12.39362 13.74842 12.88115 11.69389 10.94999 12.21108 11.19174 12.30093 11.63438 \n  12.10139 15.86091 14.87627 15.61644 14.75041 11.31224 8.924519 8.241544 8.472549 8.927956 8.740888 9.051448 8.190333 9.251281 12.88241 13.90231 12.65679 11.89317 11.16821 12.41968 11.02865 12.32125 11.54047 \n  11.38513 15.89259 15.55978 16.49071 15.93176 11.26818 9.120329 8.472344 9.292308 9.625569 9.129047 9.180802 8.588961 11.19132 14.33207 15.09559 13.56647 11.99036 11.61518 12.64687 10.69325 12.63932 11.8825 \n  11.33489 16.01806 16.14634 17.10612 17.0976 11.94706 10.30982 9.953162 10.28553 10.87142 10.28722 9.505128 9.044598 12.70718 15.12737 15.38648 14.23596 12.67216 11.409 11.88481 10.85025 11.92107 11.80873 \n  11.93121 16.69381 17.38387 17.6749 17.98742 13.28621 11.70719 10.43649 10.91934 11.77147 11.88422 11.13052 11.38345 13.80934 14.99402 15.98011 14.9559 12.99995 11.91326 12.93166 10.28887 13.55714 13.66834 \n  11.91258 16.81928 16.99542 18.31518 19.14895 14.40946 11.01381 11.08671 11.39375 13.21682 13.19212 12.36498 12.30863 14.04659 13.71266 15.38462 14.6618 12.61307 12.04058 12.94022 10.91476 13.20159 13.73922 \n  11.46789 17.38041 17.82477 18.2752 19.65061 15.74574 11.42097 11.61401 12.88716 14.96064 15.02348 12.79885 12.33007 13.6574 13.31771 14.41018 14.14105 12.70052 11.94269 13.00976 10.96539 14.06782 14.93854 \n  10.82074 17.51527 17.82471 18.72139 20.24971 16.65067 13.19277 11.47689 13.75297 16.15981 15.89948 12.82615 11.78095 12.68962 13.03443 13.99312 14.44622 12.8687 12.09715 12.6253 11.04033 14.82887 15.41104 \n  9.789128 17.60623 17.95166 19.12147 20.36291 16.45957 14.5175 11.95895 14.00584 15.58451 15.58284 13.09798 11.42349 12.38721 12.11636 14.10925 15.14098 13.66024 12.47174 12.31593 11.41416 15.35977 16.09952 \n  10.03751 16.87819 17.14559 18.82435 19.69844 15.54911 14.925 13.47285 13.4415 14.02402 13.91976 12.55425 11.28404 11.29449 11.12666 12.90026 14.52994 14.08993 12.81467 12.58953 11.19166 14.11535 15.23785 \n  10.93798 15.34559 15.48075 18.89332 19.13994 15.17251 14.3534 14.04348 13.22518 13.32802 12.83179 11.63252 10.8536 11.23855 11.16474 11.8378 13.7653 13.51799 12.46745 12.35123 10.79845 14.09694 15.23058 \n  11.39907 15.94585 15.80858 18.99041 19.07972 14.78049 14.1376 14.13164 12.62071 13.95744 12.93874 11.53029 10.4269 11.58948 11.19517 11.35314 12.57921 12.77587 11.52973 10.72114 11.27394 14.35466 15.65102 \n  12.50065 16.98081 16.2958 18.53826 18.03814 14.84136 14.63556 13.97874 13.23756 13.85454 13.35822 12.12458 10.75648 11.73495 10.99577 10.73339 12.26947 13.05336 11.80032 11.86604 11.52577 14.2759 16.10515 \n  14.11917 17.50495 16.44348 18.44194 18.71619 15.23897 15.50647 14.00227 12.22151 13.66027 13.43431 11.87765 10.321 11.40836 10.86816 10.51086 12.05384 13.00603 11.8335 11.91356 11.91522 14.54532 16.75152 \n  14.99379 17.92895 16.8975 18.70519 18.95995 15.73521 15.49823 12.87329 13.83215 13.62185 13.06669 12.05937 10.42773 10.73961 11.01464 10.88707 11.64818 12.58473 11.62818 11.58135 11.51648 14.55052 16.08885 \n  15.54145 17.85107 16.98327 18.49837 17.73919 15.18074 14.75038 12.77507 14.06172 13.54413 12.30926 11.52931 10.36564 11.26507 11.33629 10.336 12.06124 12.62648 11.26266 11.69004 11.93004 14.61818 15.63297 \n  16.0619 17.99921 16.89255 18.13565 17.83411 15.88005 14.93022 13.40796 14.59884 14.0794 12.40723 11.15436 10.18998 10.83631 11.137 10.82108 12.08101 13.16273 11.88929 11.08195 13.06093 14.60555 15.1582 \n  16.41592 18.74591 17.24427 17.45222 17.14775 15.69397 14.63761 13.72616 14.99289 14.96222 12.8571 11.36845 10.90592 10.93947 10.72949 10.99991 12.06396 12.11599 11.73193 12.9482 13.76328 14.24961 14.51857 \n  16.59169 18.33644 16.6729 17.92939 17.99472 15.11923 13.68678 12.95239 14.18037 14.98073 13.72894 12.48612 11.10576 11.19653 10.8321 11.57918 12.45367 12.50688 11.21697 13.96683 14.07828 13.39284 13.05171 \n  16.37931 18.53983 17.11295 17.0422 17.68007 15.11545 13.4979 12.7253 12.83473 13.30683 14.44711 13.53261 11.2399 11.29604 10.66569 11.51261 12.52057 12.61519 11.1287 14.42613 14.21188 12.91073 13.62521 \n  15.77711 16.81826 15.82284 16.26417 14.77699 13.92578 12.86666 12.48366 12.62949 12.08785 13.24057 12.46911 10.74334 10.64687 10.51021 10.52875 12.20348 12.29009 10.30058 13.55652 13.26817 13.30325 14.35986 \n  15.82015 17.46225 15.50791 15.47983 15.53145 14.01977 13.48505 11.83372 11.23159 11.60364 11.24516 11.02851 9.994411 10.127 9.874244 9.952956 11.45186 11.57752 10.71201 11.31057 11.925 12.24183 13.13455 \n  15.76488 17.33266 15.47503 15.67266 14.76409 13.55282 13.16781 10.86405 10.00527 10.30678 10.84636 10.38855 9.692888 10.62687 10.82284 10.76016 11.56705 11.6752 10.60772 11.25967 11.79259 12.14699 12.2975 \n  15.79346 17.73031 15.68137 14.88974 13.31264 11.70068 10.75016 9.699461 11.59397 11.09019 10.58869 9.898376 8.929638 9.302467 9.637378 10.49889 11.22649 10.7973 10.0415 11.52228 10.99211 11.29036 11.60892 \n  15.62056 17.43279 15.06023 14.50031 13.94001 11.11427 10.53508 10.24727 10.84226 10.2417 9.97341 9.786078 8.522814 8.529009 8.403295 8.864924 9.860689 10.12548 10.1109 10.64103 10.51032 10.91088 10.99742 \n  14.92246 17.0135 15.04857 14.46992 14.52418 12.18941 11.24207 11.29555 12.0192 13.37018 13.99349 13.40953 12.65679 13.28639 14.09664 14.8326 14.6762 13.23665 11.35561 12.54946 14.12629 15.38962 14.67778 \n  14.08548 16.16105 14.25179 13.72728 14.2951 12.56719 11.60147 10.79406 11.7847 13.46562 14.78914 15.1487 13.70664 13.32854 14.55988 16.36461 17.04605 15.91949 14.81793 16.99095 18.20212 19.37614 18.60077 \n  13.56568 15.41561 13.65116 13.80278 12.35432 10.98944 10.19834 9.714845 10.88012 12.79503 15.31259 16.04332 15.07261 13.3139 16.37029 18.55497 19.72721 18.21986 16.88817 18.66231 19.42877 21.17449 21.34429 \n  12.81052 14.82067 12.89596 12.89064 12.7278 9.884626 10.07492 10.31998 11.56146 13.61393 16.51963 16.62613 15.85953 13.70052 15.65685 20.09129 21.61243 19.28339 18.15581 19.5183 20.06223 21.13614 22.15731 \n  12.4148 13.93226 11.91046 12.1541 12.28745 11.01894 10.5866 10.27591 12.31247 14.79986 17.28344 17.50844 16.46629 14.32873 15.63348 20.89158 21.659 18.84053 18.39215 19.79963 20.31273 21.56329 22.12888 \n  12.91297 14.79987 12.71113 13.29154 13.44041 11.56215 10.49496 10.6033 12.03684 15.29325 17.49444 18.31451 16.88695 15.08641 17.40228 20.39707 21.17206 19.49123 17.8341 19.26415 20.69028 21.98025 21.82807 \n  13.12175 14.64588 12.15094 11.35538 12.11017 10.95849 11.28366 11.61484 12.85101 16.09893 18.0477 18.62724 16.99242 15.1852 17.51782 19.87419 20.87705 19.48903 17.96088 19.17698 20.07501 21.74238 22.1084 \n  13.00411 14.90964 12.85213 12.4642 12.19896 10.9285 11.4324 11.96293 13.98125 16.61734 18.89468 19.34385 16.26028 15.6907 16.13703 19.2197 20.6384 19.75793 18.03179 18.44206 20.21319 21.34424 21.91418 \n  12.53915 14.56936 12.39721 13.01271 12.77172 11.97516 11.71099 11.24299 14.61106 16.86008 19.35301 19.43951 16.80698 15.8419 16.63168 19.33833 20.47225 19.18408 17.29919 18.15383 19.49329 20.5814 20.88459 \n  12.15284 13.47757 10.60758 12.20281 13.0343 11.11187 10.97446 10.88111 14.17981 17.2116 19.27656 19.46944 16.21806 14.89002 15.36739 17.92939 19.41214 17.94695 16.58801 16.62714 18.35245 19.04712 19.02948 \n  11.57865 13.99112 12.93595 11.18491 10.64367 10.56507 10.97282 12.65517 14.05695 15.92091 18.14322 18.23843 15.92175 14.87526 15.68978 16.53125 18.24236 17.28429 16.56872 15.94291 16.28687 17.53417 17.20242 \n  11.28529 12.6209 11.65753 11.60241 11.58626 10.83581 10.27027 12.12041 14.267 15.48161 18.20242 17.39253 15.21907 14.75703 15.08057 16.2598 17.26633 17.07322 16.03636 15.15166 15.24807 16.5594 16.19338 \n  10.91567 13.44223 11.93005 10.71006 11.31781 11.7807 10.22369 12.09495 13.98265 15.85598 16.988 16.82117 15.11764 13.72713 14.96652 15.93681 17.34565 16.43155 15.34467 14.63535 14.80754 16.85585 15.56012 \n  11.37683 12.73687 10.39089 9.336987 9.831561 11.17227 10.51462 11.394 13.52753 17.06892 18.22289 16.58073 14.50473 13.4536 14.32212 15.69642 17.59365 16.24478 14.84533 14.05617 14.99095 16.48585 15.65335 \n  11.15164 13.128 10.98207 9.10566 10.39393 10.70634 10.84463 11.06166 13.15317 16.16613 17.48376 16.13078 14.46833 12.60861 13.22436 15.39284 16.83496 15.80455 14.54673 13.42426 14.11045 16.32096 15.15128 \n  11.15148 13.08558 11.24186 10.75418 11.27332 10.83193 10.16917 10.71663 12.71503 15.8612 16.86666 15.34324 13.83714 12.93292 12.91148 14.20864 16.26399 15.44005 14.26241 13.12186 13.5547 15.73553 15.21248 \n  10.32435 11.80502 10.71903 10.12998 9.243139 10.32276 10.51204 9.885305 13.37798 15.24079 15.56827 14.59323 13.25549 12.08573 12.08292 13.83259 15.49082 14.31401 13.56349 12.58398 12.93209 15.15023 14.39397 \n  9.55196 13.14198 12.09491 11.57915 11.7868 10.55393 9.688849 10.1536 12.66342 15.51936 15.60778 14.23114 13.59677 11.5554 12.35998 13.28365 14.88144 13.88197 13.16487 12.75849 12.51151 14.26958 14.14925 \n  11.14226 15.27234 14.74488 14.24864 14.20611 12.25802 11.94632 12.10342 13.43625 15.97755 15.82204 14.68259 12.32215 10.68163 11.67134 13.07826 14.39713 13.78414 12.79398 12.32595 12.68034 13.86888 14.63672 \n  11.82192 16.13304 15.37651 16.57404 16.01068 12.65684 12.84768 13.69928 14.84385 16.28752 15.21064 13.4215 11.93544 10.11553 10.96781 12.73654 13.93202 13.7597 12.7366 13.53805 13.78219 14.34586 15.65966 \n  11.16597 15.60295 14.91919 17.65105 17.25035 13.94595 13.03636 13.82953 15.81298 16.99026 16.38386 13.44202 10.67358 10.54342 11.52007 12.54199 15.2073 14.85921 13.04932 13.6851 13.8579 15.4532 16.68387 \n  10.51662 15.43471 14.99521 18.16862 17.72067 15.69889 14.12805 14.29307 16.52756 17.99657 16.64942 14.49547 11.61017 10.99339 11.64379 12.93506 15.5309 15.33103 13.2612 14.26317 14.55778 16.36224 17.4065 \n  11.90673 16.09601 15.16525 18.22427 17.79523 16.65013 14.95471 14.57647 17.00873 18.48756 16.99238 14.55247 11.84007 11.13602 12.00641 12.06635 14.78719 14.60945 13.60264 14.37275 14.25254 15.76529 16.61269 \n  11.77753 15.94984 15.05677 17.97174 17.373 17.41905 15.6169 14.73355 17.46013 18.81142 17.14954 15.49692 12.20508 11.44368 12.23865 12.73304 15.18181 14.84058 13.51544 14.6217 13.58304 15.94587 16.794 \n  10.41407 15.72303 15.14866 17.70807 17.07916 17.71496 15.88798 14.64032 17.55777 18.87132 17.8488 15.62309 12.12702 11.63624 12.23076 13.35091 14.845 14.49619 13.87168 14.96588 14.34432 16.30333 17.20194 \n  11.354 16.18204 15.44579 17.66172 16.96994 17.44448 15.66464 14.72198 17.39568 18.71137 18.22394 15.33202 11.91729 11.85658 12.49095 13.32615 14.09961 14.23158 14.58506 15.50219 16.31929 16.47316 17.44572 \n  11.67818 16.44463 15.64772 17.72272 16.90357 16.48343 15.1468 14.66261 17.37626 18.67665 18.43763 16.17672 12.68573 12.12047 12.56644 13.53683 15.69811 15.11192 15.10006 15.99792 16.72847 15.30137 16.12518 \n  11.81452 16.51302 15.8351 18.05065 17.12857 14.78708 14.79863 14.54577 17.14968 18.40389 18.33661 16.81234 12.45416 12.26822 13.33935 13.42922 16.02875 15.44887 14.45614 16.00752 17.02212 15.07159 15.84839 \n  11.66775 16.09326 15.45326 18.56066 17.73905 16.56577 15.80819 14.98165 16.93577 18.54793 18.7565 16.84025 13.44262 11.95572 12.87634 13.43538 15.80291 15.6723 14.43189 16.38626 16.87126 15.30465 16.12741 \n  11.18154 15.3121 14.98711 18.80246 18.00036 17.79539 16.50552 15.6597 16.54539 18.6693 18.88139 16.73647 13.84423 12.21505 12.68858 12.8891 14.96932 14.98377 14.47017 15.99248 16.69073 16.01393 17.04851 \n  11.39253 14.84143 14.70809 18.75023 17.97756 18.1698 16.63218 15.90916 15.77523 18.6932 18.87343 16.30272 14.07881 12.17943 12.72991 13.99461 15.09284 14.90023 14.86968 15.68508 16.95284 15.82605 17.11721 \n  11.86377 15.31133 14.59444 18.38207 17.6422 17.60731 16.2254 15.42659 15.86426 17.45585 17.54583 14.96311 13.32989 12.32241 12.82136 13.80614 16.04843 15.70225 14.60214 15.79691 16.55345 14.48477 16.21475 \n  11.73533 15.70459 14.84644 17.80892 16.99964 15.85337 15.77551 15.02913 15.56236 17.03756 17.23155 14.80542 13.2883 11.4158 12.61335 13.34564 15.46394 15.25104 14.61511 15.47291 15.86379 15.43297 16.33346 \n  10.81638 15.52154 14.9054 17.31289 16.38354 15.1073 15.92739 15.73638 16.55172 18.13293 18.54304 15.54773 13.22721 12.31508 13.16266 14.46879 16.11985 15.48509 14.86392 14.97309 15.37611 15.07204 15.87638 \n  10.26267 15.25113 14.67625 17.21563 16.31719 14.77018 14.92522 15.68053 17.32211 18.43587 17.91074 15.57454 13.49049 12.60371 13.12548 14.11297 15.84021 15.45053 14.63433 14.96083 15.49248 13.76896 15.98103 \n  10.69819 14.90186 14.28961 17.07143 16.24204 13.46402 14.20674 15.63925 17.09035 18.04039 17.88895 15.37756 12.4007 12.11112 12.55157 12.96375 15.69617 15.59222 14.15425 15.03544 15.54571 13.44852 15.65409 \n  9.915021 13.82648 13.51551 16.30905 15.34114 15.36788 15.25857 15.57581 16.88137 17.62993 16.70799 14.8589 12.48502 11.65991 12.48844 12.89608 15.70182 15.3114 14.08729 15.36026 15.73317 12.51652 15.22122 \n  8.68051 12.45413 12.77622 15.34519 14.32071 14.90527 13.81296 14.36697 15.78108 17.00771 16.51527 13.94231 11.84495 11.75392 12.35656 13.10109 14.77411 14.72279 13.45488 14.19114 14.58668 12.4133 15.44579 \n  10.05589 13.40399 13.02372 15.95843 15.3619 14.07744 14.53119 14.84178 15.96589 16.57776 15.83888 13.69824 11.78194 11.49591 11.9167 13.30375 14.69968 14.48295 12.85517 14.20968 14.40717 12.00698 13.85596 \n  11.27062 14.20996 13.00546 15.81915 15.0768 14.00317 14.15812 14.63979 15.93456 16.13581 15.80585 14.0422 10.93639 11.04755 11.28759 13.27676 14.53805 14.24715 12.69541 13.41502 13.21583 11.7954 14.09292 \n  11.82292 14.00475 12.70146 14.15521 13.96183 13.86355 13.82776 14.55097 15.977 16.62114 15.52749 14.43003 11.57255 11.82603 11.46633 12.81295 13.52481 13.20844 12.48258 12.9837 12.70388 12.01538 14.10332 \n  11.81733 14.02889 12.67105 14.56858 13.83397 13.15577 12.52465 13.75595 15.65288 15.53403 15.14229 13.78594 11.95139 10.92552 12.43795 12.72144 13.77396 13.37051 12.03247 13.05484 13.05454 12.07504 13.45452 \n  11.53573 14.69543 13.47587 14.54975 14.09588 12.23716 11.75021 12.82979 16.3925 16.57847 15.83274 15.41968 12.53094 12.0738 12.46284 13.14491 13.65205 13.70883 12.48045 13.69684 14.24071 12.90326 13.78031 \n  10.46279 13.28604 12.97831 14.62308 13.95662 12.26015 12.11266 13.03825 15.73407 15.80908 16.49609 15.14229 11.56523 11.61488 11.99993 13.00464 14.1577 13.95174 12.51486 14.32073 14.42474 13.37241 14.48748 \n  10.48366 14.08517 13.39815 12.98214 12.39788 11.79398 12.84884 13.57857 15.40684 15.60652 15.99256 14.35739 12.09316 12.1796 13.10014 13.46264 14.51066 14.02861 12.81611 14.63739 14.12812 13.86828 14.78857 \n  10.19182 14.69601 13.93462 12.37111 11.73293 10.65019 12.18164 13.14647 14.66128 15.14137 15.29343 13.7568 11.9698 12.07825 12.39925 13.19032 14.63404 14.42319 13.39776 15.18882 14.68679 13.48536 15.13381 \n  10.34476 14.25978 13.3268 12.39499 12.02569 10.45536 10.55758 11.70175 15.12028 16.20647 14.50963 12.94513 11.49872 11.71179 12.57724 12.75515 13.61092 13.75198 13.41445 15.13885 14.47829 14.33477 15.76451 \n  10.20487 12.92972 12.66008 12.42735 11.86889 10.36294 10.88357 12.17473 14.84048 16.0851 14.19029 12.64169 11.7309 11.68961 12.55493 12.70489 13.73792 13.65674 13.2528 14.73102 13.98869 14.62711 16.16679 \n  9.423117 12.70624 12.09342 10.86123 10.24333 9.513165 11.43117 11.95184 14.92405 16.06582 14.44456 13.55055 11.02903 11.31061 12.30381 12.54599 13.94664 13.53971 13.29417 14.64221 13.89266 14.74018 16.82738 \n  9.589171 12.47112 11.4502 9.131975 10.2197 10.17758 11.90142 12.39148 15.51737 16.71535 15.28426 13.4031 11.43478 11.36541 12.49403 13.41569 14.58072 13.76381 13.98231 14.93766 14.71383 14.92337 16.24941 \n  9.503296 10.60735 9.271545 9.716817 9.667707 10.52781 11.40006 11.39293 14.60591 15.02798 15.03264 13.64719 11.30165 10.74731 12.65038 13.62129 14.64687 13.53882 15.08017 15.38536 14.1648 14.99333 16.10574 \n  9.115908 11.43826 10.47298 10.14771 9.880108 9.726262 10.82772 12.05128 14.10969 15.54203 15.91383 13.69349 11.85291 11.131 13.34072 14.18404 15.38566 14.57817 14.72091 15.19623 14.41386 14.31567 15.83257 \n  9.310917 10.28504 9.811528 10.01983 10.05451 9.4747 10.45637 11.62435 13.92147 16.01029 15.57332 13.24274 11.89735 11.36156 13.09891 14.07911 15.26106 14.44157 15.20087 15.08729 14.25182 14.66974 15.79354 \n  9.030734 10.77806 10.31404 10.89988 11.18181 10.48961 10.15753 11.69851 14.42295 15.29466 14.48458 12.67693 11.36603 10.84135 11.80535 13.1063 15.03863 14.38514 14.50504 14.37171 13.37179 14.37903 15.7146 \n  7.50856 11.28577 10.72007 10.24735 10.17675 10.65663 10.4188 11.49671 14.89423 16.14469 14.11847 12.56653 11.28391 10.65832 11.76379 12.46559 14.1188 13.54819 13.30948 13.31488 13.49415 14.57029 15.60327 \n  8.540401 11.55971 10.55634 10.50483 10.84564 11.33433 10.85704 11.34962 13.89402 15.64289 14.49759 12.96604 10.80758 9.884405 10.34586 11.19268 13.79956 13.10055 13.12975 13.08347 12.67242 13.66006 14.28579 \n  11.08979 14.00895 13.28101 13.3758 13.54885 12.20103 11.48327 11.56215 13.08175 15.66193 14.28371 12.17407 9.616703 9.735795 10.51737 10.66526 12.92028 12.44681 12.94642 12.86102 11.83186 12.5984 13.619 \n  13.14398 15.67154 15.34065 16.24163 15.0646 12.54676 11.68441 12.30696 13.41859 15.11965 13.7802 11.35566 9.2933 9.63155 9.780502 10.87477 12.77262 12.19879 12.55715 12.45354 11.55077 12.7023 13.38533 \n  14.07658 16.64854 16.01492 17.56435 15.44176 13.57488 11.04171 12.65898 13.55481 14.86006 13.82938 10.95063 9.030316 9.329757 10.07974 11.01514 14.26132 13.92831 12.94692 12.58781 11.56843 13.6175 14.11914 \n  14.75746 16.99999 16.77552 18.02952 15.90656 14.6823 12.81055 14.08961 14.8099 15.94903 14.67507 12.65691 10.4475 10.15641 10.20949 12.54788 15.05997 14.94959 15.0851 14.83846 12.45193 15.8906 16.3022 \n  15.11706 17.16695 16.8549 17.89547 16.15163 14.86321 13.19364 14.13913 14.60327 15.88921 14.64402 11.80295 9.991564 9.918747 10.29794 12.53781 15.5761 15.41474 14.87424 14.64059 12.25671 15.93182 16.2683 \n  15.40835 17.45925 16.58469 16.7639 16.27665 14.75572 13.4018 13.85402 13.12921 15.10079 14.71053 11.99744 9.913205 9.705381 10.4648 12.13035 15.2068 15.025 13.92012 13.05841 12.5278 16.01011 16.19179 \n  15.45827 17.28377 16.69241 16.92484 16.34339 14.48242 13.334 13.81861 13.36756 14.88102 14.33365 11.80426 9.697133 9.240011 10.16598 11.92516 14.61208 14.43869 14.29321 13.34631 12.60551 16.59318 16.53483 \n  15.13229 16.73378 16.89245 17.1393 17.00265 14.96519 13.72409 14.02927 13.25723 15.83806 14.40103 12.19008 10.30029 9.71996 9.842927 12.35917 14.15221 13.89012 14.0526 13.6017 11.93211 16.53617 16.72011 \n  14.57705 15.6379 16.80176 16.86314 16.66628 14.47865 13.58029 14.06467 13.77963 16.02653 14.70159 12.60434 10.41194 10.06278 10.46712 12.41631 14.66149 14.67236 13.84786 12.99362 12.37743 16.0895 16.24062 \n  14.77465 16.17302 17.21569 17.31233 15.77169 13.20695 14.42118 14.81845 14.40012 16.4256 15.06712 12.46396 10.4278 10.54279 11.23261 13.11649 15.14829 15.03464 14.55053 13.6049 12.95183 16.86971 16.66895 \n  15.05606 16.52065 17.57998 17.69038 16.2915 14.25601 14.84489 15.36414 15.11178 16.8064 15.81776 13.49685 11.06283 10.37466 11.31837 13.62332 15.70944 15.07266 14.53792 14.15806 14.11397 17.4218 17.03832 \n  14.91461 16.54216 17.72679 17.76228 16.31701 14.88375 14.68025 15.63748 16.55472 17.25992 17.16825 15.38784 12.14931 11.18112 11.89017 14.01893 16.31654 15.77574 15.18395 14.93204 14.24931 17.65414 17.32909 \n  14.06235 15.76193 17.18796 17.04869 16.16309 15.03378 14.50389 15.27548 16.01657 17.05204 16.83701 15.13547 11.94728 10.58079 11.4934 13.36317 15.81689 15.14827 14.4666 14.55218 13.48098 17.22405 16.73607 \n  12.20449 13.63824 16.85458 16.60645 16.1426 16.12964 15.33291 15.36466 16.87278 18.04861 17.6068 15.85586 12.63215 11.99263 12.60324 14.04203 16.81243 16.22995 15.30362 15.6595 14.4412 17.11238 17.13072 \n  10.72764 13.3548 16.83893 16.19029 15.82427 16.1692 15.66567 15.07302 15.77989 16.54188 16.30075 15.60935 12.34325 10.73788 11.86701 13.85012 16.31892 15.11082 14.34861 14.96774 14.47254 14.20635 15.01912 \n  11.60129 14.09942 16.75742 16.20039 15.56324 15.11675 15.08574 14.86573 15.50838 17.15246 16.86691 15.52252 12.93029 10.73168 11.6597 14.13603 16.52929 15.7967 14.49399 14.30547 13.43089 14.71824 14.45458 \n  14.02859 15.28391 15.8077 15.34497 15.03183 15.79032 16.02132 15.8215 15.79886 17.51942 17.64467 15.42086 12.91273 10.42257 12.27133 14.28747 16.08209 15.12793 13.71037 14.9558 14.61221 14.93433 14.82792 \n  14.18848 15.49555 16.91608 15.82519 14.52658 13.71498 16.10671 15.94508 15.64377 17.88175 17.91087 15.55968 12.45656 10.9743 12.02333 13.80416 15.67876 14.38375 13.71993 15.67794 15.32651 14.47271 14.63666 \n  12.46225 13.96751 15.86773 14.64494 14.40544 14.4847 15.3736 16.16685 15.92646 17.85421 18.09699 16.27834 12.37715 10.08867 11.90742 13.48527 15.4419 14.10502 13.62834 14.96597 14.83753 15.32119 15.06888 \n  13.05211 14.65883 16.07732 15.72431 14.58461 14.83052 15.30428 15.05263 15.02916 16.23183 15.43935 14.29991 11.75905 11.07148 12.31495 13.43882 14.98901 13.66362 12.9674 14.51913 14.48279 14.95528 14.8023 \n  12.55515 14.89801 14.75364 14.68671 14.14907 14.13834 14.59004 13.6544 13.79198 16.03756 16.11797 13.08031 11.24561 10.83997 11.88435 12.2136 13.93883 13.77705 12.87251 14.5708 14.71351 14.24566 14.39286 \n  13.83093 15.56555 14.57585 14.22723 13.8579 13.36604 14.29341 13.54445 13.8807 14.93316 14.51684 12.76485 10.79458 10.58632 11.6082 12.35924 13.70661 13.07612 12.48223 12.69072 12.71655 12.41708 13.33185 \n  14.18465 15.79808 14.80991 14.02056 12.90899 12.66223 13.70633 13.82998 14.50648 14.96112 15.03471 13.67727 10.52017 10.59638 11.55017 11.89342 12.99354 12.42688 11.95904 12.05783 11.865 12.08287 12.86125 \n  13.25803 14.87615 13.40272 12.26935 12.22413 11.50442 12.41747 13.64918 15.23524 15.79496 15.65018 14.92247 10.86561 10.38056 10.77693 10.56645 12.19267 12.05079 11.84969 12.24822 11.36017 11.14598 12.25312 \n  12.45111 13.44244 13.22482 12.22398 12.6735 12.62569 12.88445 12.80736 13.84655 14.60308 14.62763 13.62638 10.40659 11.13378 10.61906 9.895057 11.55708 10.91639 10.84196 11.58675 11.38106 11.41171 12.38584 \n  11.51846 12.357 13.54436 12.86645 11.85491 11.5113 12.90373 11.86775 12.45533 13.17408 13.00485 11.74634 9.947218 9.551273 9.567058 9.890096 11.33025 11.05918 10.6337 10.56511 10.17946 10.49385 10.70985 \n  10.98355 12.91067 13.64736 13.10762 10.84069 10.44838 11.49005 13.12592 12.14138 12.09276 13.07966 12.63638 9.730008 9.848679 9.347866 9.414342 10.63352 10.80758 10.35773 10.48653 10.42719 11.00619 10.87458 \n  11.5681 13.21478 13.99549 13.15111 9.779534 10.84289 11.58694 12.34813 12.21469 12.28861 12.12051 10.8032 10.08394 10.18741 9.829264 9.272332 10.70571 10.90198 10.80318 10.46099 11.22602 10.77159 11.26807 \n  10.92434 12.3015 13.37657 11.97633 9.846909 10.4243 11.08952 11.22303 10.78325 12.41337 12.66613 11.84448 9.250697 9.51819 9.804947 9.046823 10.62793 10.31114 10.24323 10.33592 10.83164 10.2066 10.32049 \n  10.66577 12.14629 11.68034 9.369942 10.3728 9.903213 10.77546 11.68394 11.14858 12.63394 12.94571 11.37593 10.00287 9.558322 9.845166 10.15729 10.41532 9.908718 9.831599 10.41129 10.63024 10.63221 10.3509 \n  11.6184 13.30724 11.55282 10.44678 10.41798 10.1706 10.90822 10.41916 10.55029 11.9752 13.67633 11.79162 10.79402 9.887626 10.8025 10.48727 10.37634 10.34983 10.57088 10.24781 10.26391 11.38719 11.21457 \n  12.47586 13.6613 11.17755 10.26591 9.585545 8.900165 11.20114 11.92466 11.11244 11.51987 12.53722 10.63915 9.778065 10.18182 10.7475 10.43095 11.06562 10.47551 9.800613 9.590487 10.01961 10.74588 10.42597 \n  10.77701 12.82747 11.43204 10.35398 8.763439 9.405526 10.82308 10.63848 11.23412 12.39658 12.69621 11.6574 9.802265 10.72791 10.38412 9.456212 10.21749 10.77777 10.52131 10.53893 10.67069 11.10977 11.42564 \n  11.11245 11.89655 11.72092 11.20401 9.289854 9.801051 10.75733 10.49686 11.86391 12.7017 13.00109 11.37016 10.12052 10.20385 9.899943 10.12168 10.17335 10.37608 10.25884 10.2047 10.5204 11.22245 11.59654 \n  10.07293 9.634727 11.54807 11.43805 9.092267 9.683016 10.62169 11.24899 11.31559 11.98399 12.95545 12.45842 10.71746 10.80228 11.2789 9.754478 10.40236 10.25889 10.37339 9.958531 10.25048 11.00226 11.04672 \n  10.42046 11.45978 11.63636 10.63461 9.173406 8.947865 9.959992 9.868871 11.08009 11.51371 12.75934 12.10706 11.59692 10.57697 11.32946 10.17161 10.1469 10.40671 10.2813 10.1093 10.52484 11.39623 11.14704 \n  10.24291 11.15639 10.16661 9.884758 9.216879 9.206462 10.319 10.26303 10.83201 12.79486 13.33239 11.75389 10.45811 9.76089 10.24667 9.601921 10.60552 10.51551 10.36004 10.27134 10.3252 11.17595 10.70015 \n  9.422491 10.00307 9.304786 9.541505 9.374505 9.497077 9.545082 9.764844 10.62842 12.44954 12.87034 11.195 9.428076 10.17063 10.55802 9.774949 10.74514 10.18642 10.23282 10.14036 10.41611 10.48228 10.65022 \n  9.431662 9.925019 10.80831 9.614099 8.896067 8.509177 8.498697 8.813649 10.72018 11.46818 11.79037 10.94821 10.24577 10.29312 10.4467 10.298 11.07519 10.74677 10.3395 10.43149 10.75678 12.64705 11.43539 \n  9.448807 10.96071 9.576197 7.308518 8.883255 8.301652 8.766844 8.846759 10.22622 11.76619 12.58748 11.67644 10.72528 9.9915 10.21584 10.17676 11.38863 11.19318 9.839796 10.4516 11.10404 13.23044 11.87121 \n  10.62994 11.5706 10.67056 9.265289 10.66641 8.995152 7.84528 9.58221 9.973509 10.98804 12.24823 11.57158 10.72447 10.14804 9.541183 9.675903 11.06965 10.92531 10.45405 11.09323 10.41595 11.13436 11.58708 \n  10.39545 11.44841 10.55975 9.705544 10.74701 9.747647 8.344221 10.04484 10.6118 11.2215 12.51557 12.40113 10.53294 10.54167 10.73098 10.17531 11.36208 11.10819 10.5466 10.93015 10.72956 11.21366 11.42109 \n  9.808684 10.54995 8.585596 8.609066 9.104267 8.886292 8.315665 9.341417 10.22613 11.00258 12.79302 12.32948 11.03078 10.42751 10.86653 10.40495 11.54998 10.99841 10.25156 10.56426 10.5004 11.59432 11.25886 \n  9.783687 9.554473 9.224267 8.305874 9.829804 8.624431 9.106644 9.878937 9.975676 11.34404 12.81888 12.35782 11.02464 10.09095 10.79956 10.69735 11.30436 10.86825 10.91094 10.57113 10.4626 11.75406 11.67169 \n  9.964293 8.91133 9.597994 8.38109 10.30375 10.12096 9.371438 9.138732 10.23402 11.95144 12.71362 11.4016 10.57952 10.13566 10.54746 10.2636 10.74369 10.67116 10.78272 10.88782 11.01974 11.17345 11.2694 \n  7.987907 8.382757 9.251793 8.551911 8.960312 9.169497 9.091488 10.20918 11.97596 10.86922 12.52002 12.28877 10.51484 10.44818 10.56632 10.83528 10.84797 10.92687 10.48957 10.72594 10.87492 11.48538 11.44997 \n  9.208866 8.503493 9.972482 9.071673 9.462955 8.664878 7.662143 9.897245 10.64185 10.91716 11.13872 12.12932 11.36929 11.34245 11.2402 10.83909 11.03287 10.97415 10.68303 10.55697 10.5056 11.69601 11.68266 \n  9.830456 7.644547 9.789823 9.708093 10.68528 10.30543 9.51989 9.725322 10.94882 11.60964 13.0219 12.9686 12.24573 11.09353 11.58634 11.25884 10.88388 10.70734 11.0613 10.88753 10.72593 12.06754 11.55765 \n  10.1434 9.600281 9.03609 9.28277 9.389798 9.782507 9.522714 9.155346 10.51925 11.83723 12.88527 13.05917 12.5973 11.04044 12.4058 11.76693 11.41435 11.29793 11.33523 11.57119 11.21824 12.67894 11.60467 \n  9.044415 9.35461 8.125829 8.155436 10.21073 9.420408 8.485256 9.519516 10.80159 11.03508 12.98993 12.86469 12.11976 11.60614 11.22908 11.30737 11.26812 11.07872 11.49184 12.23885 12.01657 12.81706 11.95831 \n  9.557627 10.25238 8.452591 8.784152 10.9992 9.823544 9.510536 10.38744 11.27521 11.65287 13.02484 12.76013 11.33446 11.90731 11.69084 11.35221 11.25088 11.1325 11.48025 11.96735 11.96839 12.37707 11.87469 \n  10.23095 9.161502 8.99103 8.923839 9.805343 9.837078 10.10092 9.621623 10.84666 11.88772 13.02984 13.09626 11.90776 11.65839 11.98773 11.63274 11.56222 10.86827 11.27272 11.77922 11.91178 12.68476 12.05236 \n  8.874165 7.809851 8.695865 8.223797 8.763299 9.566321 8.770155 9.008782 11.19149 11.83618 13.52786 13.19089 11.91928 11.96163 12.16576 11.49836 11.79749 10.94192 10.88142 11.00608 11.66361 12.51995 11.84705 \n  8.437733 8.480018 7.988172 8.590461 9.420288 9.875575 9.504238 9.388609 10.90206 11.65753 13.35867 13.6816 12.48646 11.95356 12.16133 11.43572 11.42155 11.1403 10.60003 11.26259 11.62654 12.52154 11.82845 \n  9.964341 8.923758 9.201259 9.687395 9.499485 9.23505 8.127786 8.023572 10.40248 11.75716 12.92915 12.92148 11.44932 11.59385 12.10262 10.90831 11.27934 11.05236 10.57544 10.54616 11.69068 12.66987 12.08684 \n  7.982019 9.21278 8.003357 9.466326 10.96768 9.979166 8.679527 8.800684 10.64961 10.21235 12.66046 12.89555 12.06681 11.04834 11.27791 11.41866 11.11113 10.78568 10.56767 10.6112 11.04461 12.21314 11.62118 \n  8.391383 9.194236 9.299546 9.597569 11.07862 9.571204 8.833894 8.325615 10.67207 11.36724 11.90812 12.3979 11.69843 11.26144 10.98187 10.62434 10.55542 10.79755 10.96708 11.02939 11.2887 11.80884 11.33321 \n  8.614913 7.849565 7.212549 9.800451 10.48496 9.617368 9.147942 9.296861 10.13177 11.20514 12.3896 11.95667 11.57815 10.64794 11.444 10.93266 11.42423 10.72211 10.74878 10.75023 10.98787 11.26347 11.04169 \n  7.535953 8.379319 8.465982 9.019888 8.474906 8.644684 9.380523 9.011086 9.468113 10.66582 11.96134 11.67335 10.88397 10.53693 10.82633 10.25402 10.21263 10.32749 10.5247 10.19471 11.01541 11.35801 10.77586 \n  8.953902 8.443554 8.80369 8.623836 9.60961 8.834076 8.999572 8.835788 10.4686 10.42089 11.60229 11.5832 11.33114 10.05566 11.09636 10.20237 10.258 10.62062 10.48857 10.14489 11.40099 11.07088 10.64445 \n  8.500578 8.544858 7.815175 8.512371 8.136365 8.380095 9.461661 9.8258 9.200838 10.49927 11.48638 11.7742 10.49608 9.742468 9.315075 9.044184 9.661458 9.323888 9.979736 10.51669 10.50003 10.75289 10.55279 \n  8.140522 7.9291 8.467335 7.948473 7.84909 8.878713 9.228608 9.341762 9.541382 9.544453 9.793461 9.858119 10.06971 9.451279 8.51177 8.683918 9.586095 9.493937 10.0905 10.45376 10.50862 10.45298 10.89592 \n  9.174277 7.910554 8.41324 7.574174 8.196404 8.136746 8.121965 7.858237 8.164356 9.198856 10.01476 9.891054 9.341989 8.451241 8.975142 8.96706 9.390165 9.745036 9.87119 9.820464 10.01453 10.3652 10.31961 \n  9.053761 8.623909 7.898996 7.378081 7.484929 8.12253 7.869719 8.111196 7.660993 7.883986 8.894523 9.96628 9.412325 8.602212 8.978284 9.126224 9.584894 9.770082 10.27369 10.15531 10.25294 10.89211 10.43277 \n  8.431073 9.066086 7.605909 6.630337 6.98281 6.810944 7.623994 7.17003 7.13573 8.053357 9.209491 9.415495 8.662474 9.053435 9.397181 9.446578 9.86334 10.01845 10.17869 10.7758 10.44624 10.38814 10.5821 \n  8.942445 8.941487 8.016459 8.513492 8.322972 7.758252 7.450797 7.878129 7.665907 7.39168 7.762891 8.652268 8.399451 8.6668 9.206373 9.121785 10.34451 9.926603 10.24554 10.46929 10.76244 10.86812 10.72856 \n  8.17054 7.23271 7.703678 7.791962 8.005906 6.999223 7.472554 7.710637 7.925411 7.891777 8.577125 8.739526 8.736339 9.344995 9.341995 9.167021 10.40602 9.640493 9.765063 10.79863 10.77817 10.97881 10.41767 \n  8.539558 8.259498 8.565295 7.196165 6.610144 8.112316 7.271636 6.927933 7.946772 8.102273 7.875247 8.079875 9.375752 11.33052 10.81717 10.21815 10.39465 10.33572 9.731151 10.2445 10.49189 11.12053 10.76395 \n  8.240433 8.050691 8.147851 7.085478 6.498564 7.444286 7.85869 7.59498 7.437051 8.215886 8.160721 8.345738 8.091083 9.35317 9.591409 9.448403 10.31442 11.06631 10.24245 10.9984 10.90544 11.08032 10.89513 \n  8.550308 7.967917 8.127562 7.298366 7.333465 6.49415 7.352107 7.673339 7.976416 7.147206 8.484519 8.401263 8.720249 9.223616 9.384628 9.444779 9.571202 10.1814 10.25545 10.58296 10.57897 10.69769 10.3299 \n  8.480454 8.143271 8.400046 8.316236 8.42107 7.541131 8.236753 8.256838 7.837097 7.3845 8.376999 8.782026 8.372799 9.166592 9.061806 8.605547 9.607065 10.09919 10.09029 10.41691 10.74461 10.34597 10.42431 \n  8.515889 7.59104 8.670294 8.427706 8.82935 8.922324 7.844193 8.359896 10.19205 11.45637 11.92006 11.58537 10.71724 11.57984 12.44317 12.37348 11.76033 10.8328 10.71005 12.17016 13.12123 13.49667 12.32615 \n  9.425822 7.528139 8.268925 8.60403 9.334135 8.938853 8.31205 8.903502 10.90029 12.15107 12.53318 12.27021 11.24565 12.047 13.05301 12.96288 12.37509 11.36883 10.95156 12.79793 14.03581 15.59215 14.59917 \n  9.623832 8.175732 8.02983 8.535868 7.534457 7.092595 7.973546 8.616755 9.133872 9.538013 9.353437 10.20192 10.09133 10.06388 10.93718 11.69838 11.60221 10.81748 11.46689 14.67081 16.11157 18.09854 18.4955 \n  9.071504 7.593831 8.569519 7.444993 7.027435 7.670381 7.727194 8.79417 8.78412 10.26749 10.49481 10.5346 10.10987 10.96909 11.81418 12.57517 12.30537 11.48952 13.16938 15.3521 18.07163 19.78831 20.41618 \n  9.247075 8.342739 8.020856 8.513025 8.168929 8.344195 8.860204 9.17792 10.17791 11.50909 11.07768 11.59347 11.83874 13.10125 13.83476 13.61449 13.87037 13.02653 13.97317 17.72324 19.60029 21.56919 21.07852 \n  9.474851 6.999008 7.357038 8.650279 9.284972 10.27271 10.72347 10.36143 11.41015 11.70805 12.40401 12.9837 12.64802 14.57075 15.13742 14.90884 14.86531 14.43093 15.03153 18.73455 20.89188 22.41504 21.75938 \n  8.43823 7.602589 7.820417 9.932999 10.68121 10.14239 10.38401 10.35759 12.41399 12.78729 13.28866 13.30149 12.69712 15.16579 15.84278 16.40749 16.29351 14.39652 16.20181 19.23029 21.44838 22.89708 22.22457 \n  8.946985 7.907045 8.086035 9.623978 11.20953 10.96355 11.34051 11.00923 13.56718 13.85 13.94107 14.30479 14.27669 15.13896 16.49326 16.82891 16.4699 15.615 17.10016 20.28425 22.26842 23.02636 22.56798 \n  8.171475 8.090663 8.552567 10.50998 10.79045 10.79585 11.77593 11.28996 13.5619 14.10327 14.95813 15.71215 14.54693 15.72432 17.80629 18.37472 18.3487 16.05388 17.43175 20.30505 22.645 23.84378 23.11084 \n  8.994973 8.401255 10.09553 11.87671 11.69541 11.35841 11.40016 11.24762 13.69226 14.48686 14.93769 14.94588 14.56451 15.99824 18.65324 18.06892 17.89767 16.18208 18.38502 20.50726 22.87932 22.78703 22.46937 \n  9.782323 8.487134 9.374578 10.02132 10.83674 10.82025 10.9053 12.09562 13.35448 14.63213 14.8919 14.47755 14.00885 15.77607 18.01674 17.6033 18.13421 16.40895 17.83689 19.94169 22.52357 22.9064 22.88938 \n  9.201106 9.515572 10.08597 10.27731 11.7706 10.57605 11.69659 11.87735 13.37034 14.23273 14.85306 14.77176 14.40004 15.35916 18.42156 17.62954 17.38562 16.92805 18.14824 19.61706 22.00475 23.03317 22.16275 \n  8.748121 9.011187 9.970596 11.7954 12.21095 11.81142 11.55084 12.17591 13.77476 14.28944 14.6072 13.23592 13.31399 15.84934 19.25628 18.41424 18.67715 16.80241 18.52868 20.36193 21.57055 22.12268 21.53455 \n  8.204464 8.748878 10.92591 11.5593 13.19048 12.10626 12.02502 12.05263 13.87249 14.59625 14.2399 13.71816 14.30343 15.58732 18.69723 18.77998 18.86568 17.82364 18.05045 20.36054 21.73694 21.81034 20.88315 \n  9.566998 9.260836 10.80363 11.55462 12.66976 12.26979 12.27326 11.70452 12.91361 13.86102 14.35423 14.02273 14.13222 14.11232 18.20366 18.85984 18.12046 16.65557 17.61575 19.08671 20.27447 20.7323 19.79643 \n  9.615409 8.908094 10.52764 12.07648 12.35761 11.91719 11.31676 10.78619 11.90151 13.13435 13.57572 13.40028 13.16485 14.1586 17.97005 18.6574 17.49142 16.61602 16.97221 18.26481 19.8641 19.66534 19.13474 \n  9.518407 13.66414 14.68301 12.44051 12.49297 11.79643 11.65911 11.69031 11.55598 11.38682 13.41629 12.76745 13.40397 14.54726 16.66532 17.59948 16.87245 15.5036 16.39759 17.45155 18.24678 18.04825 17.68169 \n  9.886844 16.85537 18.44436 16.27383 15.36497 13.84907 13.35042 12.87622 12.51681 12.60914 13.06418 12.81159 12.38205 13.68456 16.01586 16.22343 16.41093 15.50471 16.12335 16.51148 17.60962 16.92897 15.91486 \n  9.932881 17.91137 19.72267 16.92243 17.54066 16.3813 13.78773 13.66247 14.68949 11.97803 13.91343 13.337 12.36077 13.84169 16.9629 16.03707 15.96878 15.15771 15.55823 16.98711 16.99094 16.69534 16.27666 \n  9.659884 18.09613 19.96937 17.05172 18.13224 17.0855 14.13896 14.20781 15.18947 12.32284 14.15654 13.44278 11.52995 14.65633 17.3638 16.08185 14.93075 14.58424 15.63039 16.85744 16.92874 16.18911 15.86921 \n  9.225732 17.84486 19.66064 16.73664 18.33948 17.20544 14.32049 13.99798 14.7793 14.12439 13.80436 13.0112 10.64079 14.43213 16.94347 15.76767 14.88731 14.56431 14.75913 16.57955 16.82982 14.99926 14.78576 \n  9.978578 17.50287 18.95299 15.45618 18.21201 17.02547 14.4027 13.69167 14.05373 14.97102 13.77975 12.47722 10.86374 13.84392 16.04429 14.79358 15.0554 14.68087 14.3245 15.75972 15.80098 14.99877 15.23887 \n  10.18868 17.52852 18.87184 15.18826 17.86486 16.54828 14.55269 13.6402 14.14156 15.5371 13.91196 12.7452 11.54375 13.17193 15.15623 14.38001 14.19828 14.53728 13.81415 15.57458 15.68111 14.43799 15.17661 \n  9.751181 17.77567 19.34327 16.0554 17.61001 16.27066 14.56316 13.73765 14.17065 15.73401 13.81508 12.20863 11.4907 13.34967 15.23476 13.96594 13.74054 13.87504 13.52333 15.54135 15.94359 14.1128 15.21993 \n  10.12562 17.83921 19.52574 16.31928 17.54741 16.23771 14.63482 13.75617 14.15524 15.65129 13.92926 12.40173 12.0656 13.88922 14.18397 13.18738 13.58043 13.53881 13.6731 15.04371 15.07353 14.68031 15.49483 \n  9.599173 17.72381 19.33587 16.07591 17.93183 16.65643 14.42071 13.79618 14.27678 15.20349 13.67884 12.52839 12.27971 14.40655 13.7573 12.9882 12.78122 13.05482 13.01771 15.88482 15.94137 15.41255 15.99297 \n  9.698954 17.42312 18.87054 15.56586 18.05615 16.68462 13.77028 13.44723 13.88304 14.32237 13.28011 12.27115 12.59856 13.77862 13.29578 12.70767 12.83421 13.53693 13.18715 15.76992 15.76956 15.14107 15.93729 \n  10.26758 17.18085 18.16345 14.96107 18.03324 16.52345 12.76308 12.70064 12.66801 12.16031 13.20089 12.79833 12.22538 12.70561 13.22355 12.84058 12.97821 13.38026 12.87051 16.21716 16.48619 14.9863 15.6656 \n  10.44387 17.23746 17.66788 14.44783 17.53398 15.96145 11.02331 12.6539 12.60111 13.22309 12.45506 12.53511 12.75447 13.26548 13.35413 13.15652 13.2005 13.69604 12.86835 15.36887 16.235 16.85772 16.54977 \n  10.23759 17.50456 18.4933 14.91491 16.87596 15.31868 10.46777 12.26849 12.64224 12.68833 12.15624 12.53137 13.16832 14.12793 14.15696 13.49824 13.72296 13.93223 13.8926 16.50182 18.04177 18.58524 18.28993 \n  10.35166 17.05918 18.34675 14.85144 15.89987 14.52373 9.76105 11.89735 12.64335 14.01029 13.73979 13.24587 13.72216 15.26234 15.57124 15.82822 14.74431 15.00797 14.97392 17.71632 19.5425 20.54453 20.59761 \n  9.555297 15.74934 17.18219 13.77729 15.08703 13.69022 10.26886 10.90417 12.99767 13.61335 14.09484 13.58124 14.1276 15.82747 16.31124 16.64211 16.18265 15.21884 15.42664 17.76999 19.3903 20.87875 20.63521 \n  8.862854 14.02321 15.96503 13.04325 13.75009 12.35207 10.97646 11.18398 12.65906 13.14713 13.12646 13.15454 14.30518 15.27275 15.80141 16.52305 15.9915 14.97509 15.27901 17.70121 19.40024 21.01748 20.90414 \n  9.332595 14.84705 16.37164 13.3482 13.17087 10.29789 10.88544 11.37841 12.42703 13.47049 13.44906 13.32345 14.28644 15.11956 16.00913 15.9466 15.03316 14.63348 14.81898 18.33994 19.95979 22.53777 21.45701 \n  9.877868 15.61059 16.83839 13.17729 12.35922 10.87731 12.04013 11.68683 13.13918 13.59089 14.2367 13.87884 13.71417 14.67861 15.89329 16.04236 15.43196 14.25506 15.13684 17.87797 19.84326 21.79107 21.3449 \n  9.140958 14.76068 16.10624 13.06766 13.47845 11.71019 11.03197 11.56545 12.67004 13.27332 13.428 13.15621 14.76991 15.18839 16.24062 16.5626 15.80795 14.79566 15.80218 18.18081 20.55774 22.59585 22.16014 \n  9.849629 12.1764 13.81905 12.20043 12.96303 11.37443 10.69466 11.47991 12.80477 12.91667 12.75835 13.21933 15.38656 15.95259 16.823 16.35283 16.43909 15.31986 16.49224 18.66559 20.4817 22.71685 21.85016 \n  9.36202 14.08019 15.09082 12.18999 12.97359 12.29903 11.47363 11.54493 12.6398 12.84276 13.85428 13.64815 15.08565 15.69742 16.96827 16.94289 16.80222 15.64644 16.48269 19.1488 21.81447 23.17466 22.23106 \n  9.57612 15.02501 16.06492 12.43449 13.88631 12.50848 11.44948 10.40349 11.57291 13.3126 14.31746 13.71188 14.76625 16.03081 16.07044 15.89003 16.94098 15.98808 16.14021 18.78211 21.02096 21.56885 20.88732 \n  11.78685 15.01811 15.52112 13.93588 14.43564 12.86158 11.35952 11.50686 11.3272 13.30817 13.81913 13.40519 15.05978 15.84919 15.35929 13.89001 15.52159 15.23993 15.40555 17.11906 18.97794 19.44685 18.4641 \n  13.22307 17.17885 17.15026 17.71776 17.11022 14.76405 13.44761 13.67636 13.50036 13.58129 13.95018 13.70605 14.88567 15.03857 14.84337 14.45563 14.86374 14.4649 14.85144 16.43289 16.89828 16.35405 16.94752 \n  13.76669 17.1444 16.05253 18.63818 17.65204 16.25583 13.92566 13.3862 14.08959 14.32102 14.93346 14.31664 14.22204 15.10196 14.79939 14.6737 15.79121 14.93165 14.95335 16.65422 16.83254 16.26995 16.42411 \n  14.16293 17.56638 16.68997 18.26259 16.92739 16.86658 14.25883 13.70589 14.65646 14.7077 15.98879 14.10393 13.49225 14.60994 14.55858 14.16977 16.02258 15.63895 14.65991 16.49418 17.11003 16.32096 16.05037 \n  15.02538 17.72275 16.8508 18.08271 16.43288 16.42471 14.93453 14.1509 15.1513 14.99477 16.14239 14.24235 14.14056 14.526 13.32078 13.45539 15.79795 15.33149 14.69157 15.69744 16.36747 15.60381 15.84035 \n  15.73365 18.03275 17.27561 18.75753 16.95327 15.80555 14.91612 15.18357 15.67709 14.97079 15.72672 15.15915 14.04085 14.47075 13.372 12.99742 14.7936 14.90177 14.24704 15.20238 16.2678 14.74167 16.11823 \n  16.26338 18.46109 17.27797 17.99683 16.66476 16.05012 15.40509 15.53155 15.96098 15.33267 16.30002 15.72512 14.53671 14.58817 13.3534 12.64955 14.37179 14.83991 14.59077 15.26721 16.07784 14.28749 15.199 \n  16.74382 18.91121 17.16111 18.04957 17.40871 16.48565 15.41961 15.17963 15.49974 15.08093 16.65548 15.9269 13.91849 13.88327 12.97235 12.65223 14.07203 14.75737 14.22784 14.64774 15.34663 14.63228 16.0888 \n  16.98529 19.11541 16.87011 16.74349 16.9392 15.88544 15.29093 14.62053 14.88953 15.09566 16.51639 15.45968 13.03472 13.23992 12.823 11.87619 13.33451 14.86192 14.20521 15.69702 15.84917 14.75232 16.39235 \n  17.02896 19.19595 17.16109 16.8834 16.3556 15.42284 14.74861 14.76104 14.92473 14.9596 16.6881 15.93081 13.33428 12.97397 11.86678 11.63746 13.04319 14.28844 13.94617 15.04595 15.0869 13.90257 15.89565 \n  16.85907 18.78141 16.70892 17.00507 15.92624 15.45061 14.55362 14.95892 14.77704 14.90913 16.98108 16.19264 12.85906 12.48413 11.65127 11.22398 12.58972 13.57485 13.65335 14.72739 15.04537 13.98265 15.01211 \n  16.64772 18.64282 16.71573 17.18554 14.0683 13.95587 14.57919 14.46328 14.58978 14.59518 17.19131 16.57361 11.92534 12.44241 11.72602 10.9928 12.40186 12.90819 13.48149 13.89237 14.56885 13.63314 15.65915 \n  16.43158 18.50433 16.55654 16.99913 14.52069 14.72103 15.24015 14.21969 14.87307 14.52989 16.81562 16.34734 11.70553 12.3317 12.12857 10.71785 11.98174 13.78292 13.32322 13.64274 14.45671 12.9734 15.85995 \n  16.15336 18.23414 16.24944 17.09164 15.74857 15.23684 15.1064 14.90766 14.93522 14.25292 15.3692 15.24385 11.05891 11.63416 11.56629 10.73565 11.83266 13.19534 12.7056 12.56191 13.70245 13.0052 15.80045 \n  15.78317 18.05012 16.20395 16.93727 15.87394 15.19709 14.3524 15.32856 14.63064 14.19885 14.98944 14.75296 10.62751 12.19092 12.06983 10.93399 11.87565 13.48435 13.07779 12.09982 12.47317 12.27248 14.84082 \n  15.39456 17.87456 16.5168 17.58305 15.61139 14.72246 13.21522 14.96642 14.20902 13.41669 14.09352 13.92773 10.64034 11.88319 11.45076 10.29098 11.03321 12.29812 12.70397 11.7358 12.26939 12.86226 14.78897 \n  15.02351 17.78964 16.85471 18.13364 15.47449 12.54772 11.64264 14.01794 14.02666 13.12667 13.50438 13.3572 10.43241 11.16833 10.74877 10.2707 11.00853 12.42801 11.92629 11.09674 11.43357 12.86431 14.27416 \n  15.09622 17.92495 16.85561 18.0988 15.42922 13.02023 12.68088 13.53072 14.48343 13.28728 12.15022 11.93546 9.953141 10.79692 10.91492 10.17909 10.60862 11.80252 11.56975 11.04416 11.2531 12.42208 13.60621 \n  15.60607 18.24389 16.80309 17.81159 15.3917 13.49877 12.40576 13.14706 13.09449 12.85986 11.56458 11.51797 9.652337 9.949935 10.32372 9.620278 10.69048 12.02814 11.59302 11.66032 11.30074 12.12424 13.24895 \n  15.90996 18.41689 16.64116 16.99631 14.64567 13.13194 12.07542 12.5822 11.69349 12.01927 12.62355 12.76301 9.990061 10.90189 10.44079 10.43505 10.66998 11.15739 10.76031 11.42792 10.89405 11.56491 12.52887 \n  16.00483 18.30446 16.08208 15.86133 13.48314 11.61676 10.97823 11.11799 11.98649 11.92625 11.69026 11.50517 9.732758 11.60136 12.52013 10.93729 10.51151 10.81287 10.82617 11.56538 11.44386 11.92824 12.41918 \n  15.85966 18.15599 15.9375 14.95248 13.4534 12.87702 10.83218 10.35821 11.16184 9.718279 11.04042 10.5775 9.815519 11.36835 11.88853 10.33835 10.50751 11.11677 11.1463 10.79816 10.42655 11.12749 11.29204 \n  15.60883 17.95237 15.71562 14.06708 12.83226 12.50489 11.20979 11.6847 10.72093 10.36459 9.917531 9.80342 9.078652 10.03732 10.6124 10.40085 10.80684 10.88086 10.69822 11.10227 10.46698 10.97048 11.10912 \n  15.2283 17.69786 15.57806 13.4353 12.19316 11.6246 11.0224 10.72823 9.161061 9.050728 9.18773 8.855824 9.341613 10.0488 10.13517 9.546819 9.585426 10.50744 10.39803 10.67031 10.51961 11.0685 11.14912 \n  14.64353 17.16451 15.15834 12.35796 12.72608 12.63046 11.68167 12.3668 14.25992 15.93695 17.47775 17.61803 15.56757 12.9737 13.57319 14.56981 13.7044 12.71877 12.86225 13.4201 14.1629 15.60515 15.65097 \n  14.06131 16.47077 14.28449 12.84858 13.9689 13.82744 13.50231 13.78073 15.74885 17.04282 18.63243 18.85933 16.36653 13.78124 14.21553 15.24145 14.55391 13.56051 13.44235 13.90322 15.24372 16.40675 16.67416 \n  13.27166 15.83467 13.93871 14.37551 15.34901 13.98736 12.92254 13.76627 16.36158 17.10549 18.30305 19.29653 16.39378 14.40754 14.97054 15.40539 15.09013 14.31383 14.41104 14.81105 16.28816 17.46544 17.82826 \n  12.96865 15.35536 13.58534 12.4107 13.17324 13.02235 12.97369 12.78875 14.50413 17.08331 17.24843 18.6091 16.95518 13.8684 14.65208 15.11388 14.85909 14.55639 14.21002 14.85613 16.15392 16.62638 16.38885 \n  12.74014 14.99901 13.14317 12.02542 13.41206 14.03033 13.80731 13.07016 15.74668 17.29949 18.08332 19.69819 16.80057 14.75249 15.27074 15.78106 15.3902 15.52286 15.18476 16.46467 17.64916 18.49447 18.44848 \n  12.97496 15.42951 13.52378 12.25876 12.9795 12.56979 12.22692 13.57497 16.76153 17.23584 17.87868 19.12806 16.46191 14.3858 15.09691 16.4803 16.39127 15.58957 15.17072 17.00169 18.0875 17.41795 17.79514 \n  12.85048 15.10298 13.23063 12.87181 13.15208 14.49708 13.07669 14.13431 17.66776 18.05823 18.7889 19.8481 17.92514 14.92354 15.70432 16.74818 16.99346 15.81199 15.74879 17.21499 17.70545 17.515 17.36108 \n  12.53143 14.44646 12.04487 12.66221 12.77981 14.32154 14.07838 15.03848 17.27874 19.03686 20.9606 21.08079 18.90958 15.76664 16.3242 16.48548 17.68536 17.00244 15.70976 17.18387 17.96568 17.45182 17.34422 \n  12.27433 14.13071 11.95814 11.10963 12.29782 13.32947 14.22352 14.91252 17.05256 19.26613 20.56975 21.0718 19.55671 16.45315 16.53867 17.16694 17.57012 16.58561 15.94327 18.1118 18.44273 17.04756 17.29078 \n  11.13274 13.31547 11.17836 10.36571 11.99675 13.38614 12.98195 13.65712 17.52398 18.83635 20.82496 21.25018 19.02944 15.45844 17.22033 16.9855 17.61625 16.53855 16.01951 17.28067 17.80919 16.29823 16.60528 \n  11.49348 12.72149 11.09698 10.74121 11.50064 13.47943 13.28319 14.12894 16.37674 18.3519 20.4639 21.47652 19.33566 15.77035 17.06349 16.64114 18.07568 16.64302 15.36201 16.04336 16.91956 15.94561 15.99434 \n  9.608139 11.75429 10.06571 11.10138 12.11786 11.58483 13.1205 14.21301 17.56386 19.13147 20.32322 20.12503 18.29022 15.28772 16.86212 17.37056 17.82328 16.0193 14.99997 15.78904 16.12305 14.55896 16.01875 \n  10.37425 13.20676 13.2479 12.19929 12.48866 11.74895 13.30715 14.54824 16.49951 18.31167 18.70988 19.54097 18.35619 15.11479 16.51697 15.98994 17.09819 15.56539 14.59282 15.14828 15.75255 14.43601 15.72609 \n  12.24577 13.50046 14.6557 13.99299 13.82843 14.16929 14.48501 15.5354 17.66883 19.51937 19.39577 20.05754 18.37926 15.92839 17.23025 16.90665 17.33165 15.74956 14.90289 15.95183 16.37263 14.70161 16.83718 \n  11.82463 14.14506 14.91792 15.10521 13.43633 14.76357 14.50471 16.30964 18.37582 20.10591 19.70662 20.12249 18.50193 16.44523 17.84676 17.22989 18.06538 15.9933 14.78116 15.97121 16.63473 14.1447 16.62147 \n  11.49515 12.57675 14.99955 15.12591 14.04319 14.90118 15.1428 16.90608 19.3396 19.58758 19.89336 20.47232 19.38027 16.83281 17.80051 16.78543 17.68006 16.1482 15.12499 16.29321 17.28958 14.39812 16.74356 \n  12.83119 13.36858 15.33085 15.8993 14.98862 15.06884 16.27656 17.09787 19.89 19.45495 19.66687 20.41065 20.05285 16.93578 17.84101 17.22516 16.6539 15.47889 14.51853 15.41234 16.16337 13.92638 16.21105 \n  12.24501 13.81182 15.54418 15.71802 14.7434 15.25031 16.42093 16.59528 18.99483 18.75741 18.65719 19.56692 19.45428 16.5445 17.94703 16.85806 17.52571 15.87006 14.62513 16.25237 16.75192 14.53815 16.44307 \n  12.43977 14.4055 15.44666 14.61817 14.49417 15.49514 16.47301 15.8417 18.29481 18.40584 18.14786 18.99505 18.48756 16.02132 17.57674 16.21739 17.56367 15.96092 14.12129 15.69186 16.08254 13.29479 15.69123 \n  13.40359 14.56592 14.56405 14.75467 14.80557 15.61075 16.30825 16.00495 17.7576 17.7054 18.44081 18.78086 17.91715 15.75736 16.79029 16.09669 16.95103 15.45958 14.6285 16.45296 17.08261 14.81537 16.62719 \n  13.40314 14.79066 14.44038 14.9208 15.28192 15.93543 16.12896 15.63424 17.53443 16.71537 17.66586 18.26663 18.14948 15.38054 15.57821 15.0981 16.37489 14.9254 14.11771 16.22453 16.63408 13.88445 16.03982 \n  13.27263 15.37152 14.98211 15.65071 16.10147 16.25443 16.39878 15.22288 16.07312 15.48051 16.95177 17.88365 17.64783 15.38212 14.85438 14.25418 15.50375 13.87315 13.85102 15.71543 15.58055 13.48126 13.54171 \n  12.79769 14.03458 15.15382 15.77783 16.13641 15.98903 15.71088 14.83081 15.42676 14.42686 16.35059 17.19747 15.89601 14.84456 14.84353 13.56014 14.43848 14.02768 13.56937 15.50516 15.01935 13.35548 13.45835 \n  12.93903 13.22154 14.53004 14.98958 15.29645 14.57587 14.04077 13.26272 15.32759 15.32236 15.08416 15.42689 14.78734 13.71587 13.79163 12.75518 14.19596 13.34965 13.19663 14.03743 14.96614 16.49541 15.33635 \n  12.45864 14.61374 13.87632 13.62215 13.72294 14.31611 14.38086 14.30659 15.43989 15.61096 14.15577 14.35514 14.81355 13.64131 13.45614 12.72456 14.13968 12.8555 13.59385 14.17748 16.39845 18.38371 17.80732 \n  12.33578 14.00891 13.07828 13.71424 14.10664 14.0687 13.13889 13.63885 14.8914 14.61784 13.90929 15.45194 14.73162 13.03892 13.2657 13.5637 13.76148 13.25706 15.10444 16.29706 16.97831 19.44946 19.79165 \n  11.96159 13.51957 13.01035 13.54761 13.69153 14.00353 13.68937 12.58661 13.48017 14.13214 13.91707 15.31068 14.23771 12.71703 12.92456 13.6957 14.43063 13.71029 15.22686 17.15446 18.45062 20.47192 20.89673 \n  12.05161 13.9109 13.16452 12.97099 13.18609 13.13105 12.99765 11.58859 13.5218 14.01596 14.89017 16.47881 15.28746 13.67678 14.92654 14.96245 15.16147 15.0592 16.54627 18.17285 20.02958 21.51884 20.96085 \n  11.84209 13.52904 12.77278 13.65398 13.20718 12.63755 11.65749 11.51693 13.74348 13.71783 15.14928 15.87488 15.38048 14.01578 15.41916 16.25989 16.82 15.85239 17.44685 18.49073 20.68714 23.03419 22.3119 \n  10.61903 12.43421 12.6958 13.1518 12.79633 12.09934 11.18174 12.15249 13.5683 12.78554 14.49859 16.1356 16.38138 15.60392 15.1943 16.6934 17.43444 17.15856 17.69735 18.73776 20.3603 23.0533 22.83157 \n  11.10656 11.3087 12.01439 12.55888 12.73079 12.43724 11.43508 11.91604 11.70938 13.99057 15.63961 17.28322 16.47677 15.20305 15.66617 17.61813 17.6751 17.60305 17.77451 19.25667 19.94949 21.90983 21.98059 \n  10.16949 12.0564 11.52991 9.989189 11.37004 11.68872 11.52673 12.63663 12.73647 14.62583 15.9687 17.945 17.5506 15.1612 15.45209 17.22151 17.94404 18.35554 18.20267 19.54291 20.5292 21.7872 21.39606 \n  10.79198 11.45736 9.874234 11.29701 11.26837 11.21837 10.89179 11.62866 12.76508 14.6835 16.18573 17.36658 16.85448 15.94918 15.41981 17.08667 18.88033 18.45577 17.89176 18.7529 19.93383 20.91602 20.71407 \n  10.99965 11.83611 10.76372 12.36669 12.88359 12.50686 12.02554 11.77562 12.96449 14.7419 17.49727 19.05647 17.76691 16.14889 15.8502 16.94702 18.54008 18.61212 17.60375 18.40122 18.75871 20.56727 20.2013 \n  10.71721 12.24653 11.40098 12.01936 13.33127 11.90686 10.65947 11.82579 13.32248 15.28793 17.01124 18.64284 17.72797 16.53176 16.11108 16.70494 17.7008 16.87293 16.90321 17.01193 17.9865 19.62047 18.54438 \n  10.84808 11.77401 10.30343 12.64884 13.14566 11.23923 10.88098 13.11721 13.34063 16.31784 16.83382 18.21345 17.3839 15.27081 15.50685 15.6567 16.72981 16.33526 16.45064 16.3113 16.49539 17.15864 16.46489 \n  9.56905 11.07326 11.29717 12.00945 12.56924 11.74636 11.67797 12.27109 12.33903 15.01359 17.29026 17.98109 16.23312 14.9431 14.57544 15.20214 16.10517 16.19224 15.99478 15.25868 15.40402 16.06674 15.44316 \n  10.508 10.89142 10.47173 10.95241 11.76593 10.98585 10.76927 12.52917 13.36483 14.31004 15.60877 16.93384 15.8426 14.30149 13.70551 14.91785 15.92855 15.53096 15.40199 15.04334 15.08857 15.01525 14.25574 \n  10.63981 10.66823 10.20522 11.10935 11.52312 11.02348 10.33216 11.91914 13.66731 13.93949 16.71332 17.01327 15.03499 14.47763 14.38019 14.41362 15.83647 15.67047 14.47045 14.31423 14.19904 14.82268 14.1559 \n  8.488654 10.10538 10.92675 10.09366 10.85918 11.26827 12.20304 11.80998 13.27558 13.73623 16.86435 16.49012 14.37312 13.21352 13.43559 13.28338 14.71591 15.0856 14.91768 13.89271 13.95088 14.00356 13.01124 \n  10.81898 13.143 12.69162 12.18221 12.55161 11.64523 12.4468 13.02303 11.64384 13.77602 16.63419 16.27282 14.54465 12.69009 12.62936 13.17467 13.86224 14.07909 14.24895 13.57493 13.15678 13.56058 14.07112 \n  11.59634 16.15282 16.04291 14.96902 14.3159 12.56915 13.37283 13.76863 13.54054 15.07096 17.31351 15.84202 14.1527 12.01037 12.44869 12.54331 13.90306 14.87695 13.81047 14.15678 13.85537 13.21027 14.43797 \n  11.50468 16.01534 15.65023 16.86644 16.7308 13.15539 13.75249 14.19167 14.84136 15.6804 16.669 15.56741 13.27599 12.18581 12.46388 13.30746 14.70786 14.89385 13.59378 14.1329 13.90083 13.44039 14.82801 \n  10.83374 15.32171 15.06138 17.48699 17.51079 13.80905 13.93069 14.59176 15.34084 16.82994 18.43996 15.90578 13.45436 11.4224 12.79343 13.04898 15.73146 15.33158 13.21905 14.24352 13.77445 13.27233 15.71018 \n  10.87577 15.47127 14.70888 17.73984 17.70155 15.23704 14.3281 14.20854 15.22783 16.9904 18.81393 15.66493 12.64094 11.61629 12.53687 12.72079 15.53799 15.56939 13.56948 13.97123 13.99972 13.84164 15.74528 \n  9.678106 15.093 14.73196 18.04266 17.9735 15.98976 14.84349 14.29395 15.38192 17.14681 18.48132 15.55414 11.81447 11.31875 12.51214 13.46786 15.07734 14.72639 12.89217 14.18221 13.942 14.46083 16.30935 \n  9.27702 15.11397 14.6864 18.26455 18.06617 16.64905 15.23202 14.50276 15.79894 17.31784 17.91948 15.71456 11.84832 11.10479 12.36307 13.02193 14.84241 13.94248 12.61262 14.14687 13.61714 14.61513 16.65529 \n  10.31116 15.20001 14.41779 18.20655 17.87181 17.37104 15.80053 14.73345 16.33781 17.26945 17.61073 15.76432 12.14948 11.87968 12.84734 13.35572 15.99964 15.05299 12.98151 13.59093 13.31608 14.26525 16.48788 \n  11.03995 15.58457 14.74849 18.04535 17.62146 17.83399 16.13437 15.02326 16.80089 17.59974 17.02293 15.01341 11.93478 12.57936 13.6127 14.46719 15.84169 14.35661 12.21926 13.44742 13.43839 15.56678 17.01775 \n  10.68538 15.81025 15.13098 18.21277 17.8306 18.10699 16.28154 15.16807 17.16661 18.57889 16.92452 14.87336 11.62055 12.73409 14.09998 15.07829 15.77258 14.38338 12.46635 13.38107 13.42031 15.66041 16.70012 \n  10.80705 16.10119 15.46497 18.4098 18.0212 17.97135 16.10877 15.19762 17.24214 18.58634 16.91249 15.42679 11.88585 13.91432 14.45943 15.74949 15.78372 14.54293 11.42183 13.62915 13.34823 14.55129 16.14689 \n  11.94579 16.89884 16.24403 18.55092 17.98724 17.20735 15.26665 14.65565 17.00868 18.47542 17.43419 16.03572 12.83943 14.0368 13.85004 14.82996 15.17481 14.47794 11.56922 13.58228 13.62983 13.59302 13.86895 \n  12.38524 17.37505 16.7696 18.47446 17.26857 15.96833 14.24874 13.03042 16.26422 17.79273 17.16697 15.42565 13.5957 14.48988 15.57542 16.0727 14.58922 13.24106 11.54757 13.28529 14.40883 13.49071 12.73336 \n  13.03429 17.5047 16.87468 18.99148 17.70904 16.97621 14.13228 12.62222 14.45247 16.32981 16.61537 14.76507 12.27121 13.29012 13.69145 14.77818 13.90872 12.32405 11.65774 13.06149 13.20633 12.79723 14.08691 \n  13.543 17.20046 16.71364 19.24344 17.89848 16.23823 13.61446 12.58731 13.79848 15.94572 15.83083 13.94334 12.33336 12.76893 13.26038 13.66663 13.53549 12.52763 10.97694 12.18569 12.12396 12.52927 14.61442 \n  13.93316 16.19917 16.60253 18.37887 16.34868 15.3344 13.60281 12.46623 14.00873 15.9596 15.67228 13.47866 13.02688 12.05685 12.97747 13.6599 13.39636 12.42592 11.40474 12.42729 12.39029 12.35651 14.67778 \n  14.61915 17.17112 17.5472 19.37409 17.49985 15.90717 13.63423 11.95899 12.93315 15.14544 15.01936 13.25283 12.0639 11.61034 12.99201 13.5629 12.46684 11.77172 11.48846 12.21882 12.39871 12.28264 13.6378 \n  15.01957 17.45677 17.19109 18.36874 17.45291 15.49117 13.40853 11.98515 13.43848 14.47075 13.50971 13.02251 11.71136 11.68848 13.16979 13.33672 12.58453 12.35258 10.77152 11.58895 12.66962 12.02104 13.51065 \n  14.3445 16.08383 16.46618 18.37986 17.49754 15.51561 12.724 11.01192 12.56261 14.75061 13.70792 13.23755 11.97928 11.47003 12.88496 13.19709 12.51916 12.02072 11.23445 11.98222 12.57755 12.58092 13.76349 \n  14.65777 17.34103 16.21595 17.87756 17.01974 14.35497 12.22902 10.17611 12.75461 14.43687 13.74576 11.96353 11.00994 10.55103 11.22951 12.06966 11.58648 11.32696 10.70369 11.09274 11.97977 11.15652 12.0545 \n  13.84403 16.75669 15.79734 15.90669 15.87204 12.81713 11.09628 9.869988 11.99412 13.88495 12.05193 12.04093 9.865374 9.98888 10.54978 11.08329 11.51721 11.287 10.19415 10.19129 11.11317 10.82287 11.26695 \n  12.03434 15.45859 15.11167 15.11641 15.16317 14.43024 11.65586 9.923259 11.36602 12.3641 11.81006 10.42863 9.54241 9.423545 10.06809 10.60886 9.986245 10.09022 9.895988 9.939384 10.39964 10.69043 10.78549 \n  11.62159 13.6024 13.63344 15.00115 13.6637 13.22205 10.87602 8.768591 9.799749 12.06331 11.48621 10.03431 9.139547 9.069712 9.670283 10.33705 9.896729 9.732963 9.743416 9.657762 10.36899 10.26934 10.40027 \n  11.81183 14.29564 13.63866 13.6298 13.18893 11.65243 10.08644 8.713807 10.15905 11.12224 10.93487 10.20999 9.452074 8.578758 9.197603 9.436418 9.835726 10.35768 10.15316 9.921681 10.65349 10.78003 10.5952 \n  12.90228 14.67107 13.85628 14.29541 14.35086 11.63753 8.860591 8.425612 9.22795 10.41009 10.2974 10.03016 9.485574 8.96593 9.532566 10.04701 10.0559 10.14437 9.809213 10.09447 10.73098 10.48613 10.97839 \n  12.14247 14.62703 13.12694 13.76217 13.40734 11.91112 10.03432 10.69592 11.79923 14.96772 14.89136 11.78498 11.03141 11.00658 12.59778 13.80232 13.4921 12.70364 11.11213 11.89696 12.66712 11.61696 12.02989 \n  12.4993 14.9535 13.76636 14.01113 13.60918 11.75265 9.318426 8.455474 10.17039 14.04918 14.17533 10.41443 9.469222 8.986806 10.21098 11.43141 11.99639 11.92311 10.10373 10.33753 11.20988 10.83258 10.75896 \n  12.68394 14.34959 12.56896 14.07434 13.22602 10.90166 8.476089 7.972132 8.819757 12.4768 12.05638 10.18155 9.379935 9.701678 9.932637 10.54168 10.334 10.5734 9.954249 10.09657 10.31382 10.49024 10.26939 \n  11.75025 13.98052 12.16752 14.10251 13.03628 9.846658 8.836266 7.344621 8.59577 10.93273 10.1303 9.196149 9.388488 9.020345 10.06814 10.79366 10.47544 10.58243 10.03372 10.03065 10.42077 10.64656 10.34247 \n  11.83129 14.04893 12.96955 13.20662 12.82525 9.696637 7.323474 8.177329 8.925125 10.40487 10.10953 8.585592 8.994603 8.708897 9.25738 9.843696 9.578411 9.801521 10.00724 10.09079 10.59092 10.64287 10.58762 \n  9.790665 12.15129 12.64895 13.58438 12.95563 9.711924 8.575097 9.001645 8.701345 10.52208 10.09897 8.517282 8.199652 8.714253 9.041263 10.04511 10.11496 10.00863 9.805107 10.16271 11.0758 11.04546 10.75644 \n  9.414765 12.83946 11.98675 12.726 12.46979 9.267152 9.039246 8.176429 8.053612 10.21454 10.41292 8.622193 7.66354 8.369621 8.642668 9.53128 9.865145 9.638438 9.991666 10.25773 10.73875 10.72115 10.65728 \n  8.779566 11.93363 11.50436 10.50424 9.622196 9.267383 8.582248 8.53771 7.890744 10.04505 10.20443 8.095118 8.612964 8.879345 8.707826 9.227075 9.176577 8.984758 10.03803 10.03335 10.5386 10.95927 10.46486 \n  10.31262 11.88174 11.99282 11.90945 9.594206 8.671169 8.318475 8.181697 8.13483 10.15049 10.25244 7.071458 7.442567 8.785149 9.691864 9.679538 9.605824 9.961757 10.42259 10.17275 10.75009 11.18037 10.72504 \n  9.364248 11.96104 11.57661 12.01562 10.75383 6.945975 7.367255 7.736284 7.312432 8.969963 9.153383 7.523694 7.927206 8.369026 8.890183 8.625024 9.480546 9.502405 9.561119 10.14811 10.62848 10.7046 10.59589 \n  8.967705 11.99061 11.26416 11.1752 9.580898 7.045003 7.880908 7.853495 8.063289 8.442639 8.374674 7.542927 8.712921 9.363231 8.787829 8.940651 8.762001 9.656484 9.560316 9.75022 9.998157 10.96855 10.83991 \n  10.79417 10.95528 10.71563 9.979272 8.763993 8.042848 7.088778 6.67021 7.448594 8.206177 8.038567 8.22692 8.547086 7.783141 9.548368 9.043281 9.180702 10.15911 10.00978 9.834736 10.7707 10.82731 10.66534 \n  9.814768 12.13082 11.35585 9.269568 8.184406 7.729397 6.804678 6.910729 7.282489 8.309008 8.415974 8.394214 7.598199 8.050271 7.802004 8.228464 9.248132 9.948934 9.981988 9.834879 10.65781 10.51871 10.32499 \n  9.652328 11.7325 10.80005 9.37675 9.013214 7.384077 7.177258 6.372046 7.152434 7.877509 7.752526 8.609852 8.207765 8.032439 8.76918 8.827532 10.00151 9.213638 9.988755 9.774078 9.915665 9.921049 10.41844 \n  9.466437 10.99616 10.88723 9.492371 8.961466 7.342728 7.358507 7.339148 7.301462 8.448383 7.55255 8.734881 8.417077 8.13668 8.47903 9.036981 9.332474 9.148084 9.903509 9.827729 9.972055 10.26808 10.0221 \n  9.64337 12.05854 10.97252 10.21088 9.235108 7.101156 7.432653 8.052295 7.081014 6.580639 7.278504 8.679576 8.280871 7.73062 8.75071 8.532309 9.329696 9.757581 9.649004 9.204338 10.25986 10.47111 10.64369 \n  8.506092 11.0128 10.68274 8.38584 7.542353 7.152045 7.326688 7.308694 7.642912 8.45325 8.044881 7.742783 7.756063 7.661537 8.275199 9.033102 9.546831 10.0107 9.767799 9.575422 10.45731 10.67947 10.68756 \n  9.190603 9.530713 10.03561 9.930932 8.509491 7.016098 7.502091 7.892929 8.24372 8.307619 7.979042 8.022539 7.607509 8.970244 9.02056 9.152427 9.395686 9.654662 10.00138 9.774302 10.25611 10.34001 10.50237 \n  8.055989 10.48079 9.946203 8.668516 8.405702 6.663228 7.840029 7.953751 7.417573 8.407804 8.318707 8.09545 8.268252 8.237886 8.408285 9.147687 9.502143 9.359609 9.642401 10.35548 10.85097 10.35253 10.09162 \n  8.523983 10.58812 10.45586 9.346948 8.423094 6.955203 7.860735 7.061844 7.640428 8.098751 8.684567 8.348521 8.667695 8.787177 8.56147 9.256539 9.863892 9.601056 9.600217 10.26275 10.53992 10.67695 10.53019 \n  8.54944 10.105 9.919378 8.700562 8.344156 7.651311 7.920049 8.247942 7.364244 7.392271 7.95518 8.640728 8.450232 9.633104 9.684301 9.891527 10.32047 10.18789 10.04646 9.441429 9.973019 10.92726 11.09868 \n  8.736779 10.67164 10.37507 8.660881 7.410948 6.964188 8.062383 8.657798 8.175787 8.124825 8.552548 8.639585 9.223927 9.4434 9.095827 9.018662 9.108647 9.592525 9.690062 9.847681 10.15555 10.88235 11.25451 \n  9.102138 10.24407 9.305552 7.972584 7.585355 7.130199 8.330059 8.346169 7.620663 7.047201 7.893063 7.923952 8.201685 8.679209 8.079769 8.701505 9.398625 9.830337 10.10372 10.45054 10.39745 10.80141 11.24109 \n  8.334327 8.800347 7.70179 9.206788 7.814823 6.755373 8.229139 8.560562 8.269526 8.002664 8.831103 8.463894 8.141541 9.049789 8.658106 9.396982 9.033927 9.765074 9.622846 9.758422 10.27184 10.49305 10.98647 \n  8.128156 10.12106 8.910188 8.762326 7.666012 6.949401 7.950629 8.1798 7.218674 8.2833 9.230454 8.431417 8.010346 8.432215 9.385073 9.408096 9.264348 9.842328 9.402944 10.16326 10.44512 10.27258 10.61046 \n  9.777776 10.17425 9.162596 8.756527 9.402295 7.245045 6.706331 7.813528 7.5786 6.985806 8.648697 8.302122 8.295655 9.284019 9.676419 9.26071 9.179568 9.636398 10.1599 10.62567 10.66345 10.83598 11.00543 \n  9.4869 9.121305 8.684687 8.700015 9.641527 9.05888 7.269274 8.791707 8.11694 7.627497 7.894124 8.112581 8.470985 9.387035 9.151163 9.710186 10.16911 10.16346 9.604074 9.987885 10.31005 10.77668 10.24039 \n  7.866471 9.883156 9.715327 8.677911 9.516367 8.34246 6.843951 7.838072 7.583541 7.852625 8.79549 7.970304 7.762091 8.846987 8.563057 9.384929 9.697865 10.01375 9.721039 9.735113 10.16057 10.63224 10.43368 \n  9.080318 8.246053 9.041588 9.417509 9.518696 7.989542 8.403717 7.463982 7.206106 7.981693 8.578013 8.107899 8.514518 7.873508 8.147607 8.765822 9.033931 9.63969 10.04347 10.20652 10.35496 10.39911 10.52451 \n  9.13128 9.074238 9.046019 9.162777 9.203651 7.817907 8.81809 9.218652 8.689803 8.523691 8.246085 7.754849 8.768758 8.798193 9.144502 9.340219 8.860093 9.865606 10.48086 10.25486 10.56614 10.47177 10.82067 \n  7.529797 9.080559 9.025809 9.092778 9.069881 7.946015 8.707859 8.578739 7.658888 7.688912 8.116105 8.22648 8.638034 8.394612 8.661798 9.266599 9.497275 10.0152 10.51752 10.32173 10.39726 10.61129 10.75329 \n  8.053345 7.806293 9.592606 9.250229 10.12409 9.191865 7.827196 8.112508 8.535282 8.097424 9.000211 8.186003 8.92979 8.464402 8.670289 9.216187 8.820874 9.527074 9.87499 10.41622 10.59681 10.51637 10.55027 \n  8.95764 9.454929 9.582647 10.45938 9.56032 9.433331 8.428452 8.183547 8.032114 8.346304 9.071006 7.965348 8.02034 8.698916 8.684159 9.147419 9.093694 9.894665 9.954333 9.885933 10.35833 10.71119 10.45288 \n  8.644167 9.48673 9.193418 10.94477 10.83592 10.44026 9.28124 8.387064 8.084641 8.072067 8.342614 7.222877 7.512965 8.233858 8.808452 9.225642 9.137754 9.547808 9.455416 9.747941 9.971579 10.64146 10.5402 \n  9.362679 9.369581 9.729918 10.51496 11.36854 10.06961 9.509526 8.469991 7.580379 7.402191 8.035908 8.038517 7.526035 8.179871 9.229591 9.114322 9.371479 8.994488 10.0342 9.992566 10.37911 10.48729 10.1093 \n  9.234426 10.02822 10.1721 10.36807 11.38841 10.48724 9.894856 8.55321 7.932958 7.556772 6.919079 7.997473 8.420939 8.136166 8.576433 8.605513 9.379736 9.246395 9.551528 10.12443 10.13093 10.29004 10.01479 \n  7.140229 7.340988 9.690434 11.22617 10.54758 9.907132 10.23349 7.846205 7.38694 7.756484 8.138117 7.949685 8.286037 7.875541 8.682808 9.680047 8.736238 9.250605 9.806664 9.929686 10.29157 10.88262 10.53922 \n  7.609503 8.446361 7.927704 10.19232 9.981958 9.750368 10.16796 8.132822 7.723164 7.520811 7.855199 7.349501 7.666749 8.55197 8.498571 9.580915 9.49983 9.968874 9.624427 10.19383 9.79729 10.48853 10.77697 \n  8.643137 8.622834 9.379179 10.04107 10.14056 9.3327 9.441696 7.66965 6.918215 7.325087 8.433827 7.403569 7.932473 9.355262 8.961336 9.433534 8.987287 9.442863 9.373944 9.75194 9.910201 10.3459 10.44656 \n  8.102217 8.064889 10.64028 12.49552 11.73663 10.07672 9.110008 8.321954 7.095238 7.711002 7.663853 7.130478 7.74688 9.022202 9.092591 9.239534 9.148391 9.078291 9.648328 9.942706 10.50384 10.56971 10.62924 \n  9.490426 8.373809 10.40654 12.21494 12.46647 10.44266 9.246642 8.188566 7.077143 7.664156 7.372887 8.266142 8.489851 8.568101 8.872865 9.148156 8.987501 9.957211 10.15845 9.909985 10.00002 10.26888 11.01089 \n  8.798372 9.025386 11.31425 11.42679 10.40138 9.216152 9.422606 8.502447 7.214077 7.507916 7.581383 7.426453 7.74972 8.678537 8.401515 9.35175 9.522068 9.689368 10.34969 10.18144 10.10829 10.22423 10.66045 \n  8.333779 8.557695 11.21921 11.96504 10.46627 9.176018 9.10099 8.930181 6.847103 7.599282 7.893191 7.544654 8.840031 8.585423 8.405005 8.922948 9.007273 9.288807 9.946635 10.77755 10.62705 10.41732 10.66157 \n  7.559142 9.412998 10.48524 11.38948 11.17182 9.945296 9.195613 7.687301 7.509073 7.597322 8.275542 8.369865 7.823867 8.430854 8.52591 8.722355 9.220226 9.689714 9.526666 9.805052 10.34926 10.81544 10.53098 \n  11.4918 14.00084 16.17197 16.42617 15.349 12.41796 11.39773 11.66957 13.16477 16.12451 15.81399 11.20098 8.846268 9.76712 11.6804 12.1915 12.09149 11.27532 10.66243 11.10545 11.89396 11.18614 11.62189 \n  12.7754 14.8082 17.40473 16.74525 14.93741 12.71457 10.89088 11.37673 13.37231 16.26893 15.81663 11.01917 8.918041 9.566416 11.83768 12.05284 12.66729 11.85449 10.60257 11.00357 11.39586 10.96889 11.1296 \n  13.36541 15.34315 17.2086 17.66689 14.65784 13.48884 12.4741 12.45936 13.42722 15.72825 15.79719 14.43064 12.889 10.51247 12.3019 12.30175 12.62188 12.04293 10.42985 10.74694 10.95862 12.90817 13.67789 \n  14.24038 16.24807 17.4501 18.67464 18.25082 16.41788 13.84389 13.58693 15.07749 17.34456 17.16127 16.20167 15.06416 11.77578 12.49449 13.45164 13.06607 12.11281 10.48501 10.73691 11.01208 15.49132 16.34476 \n  15.46261 17.19522 17.5746 18.0107 18.14651 16.75021 13.80587 13.41014 14.9592 17.26956 16.178 14.19134 11.93522 11.6239 12.82757 14.12765 13.70803 12.50571 10.75355 11.29876 11.34688 16.21528 16.64844 \n  15.85424 17.58728 17.14469 17.19608 18.15673 16.2019 13.98389 14.04934 14.00954 16.88185 15.97725 14.16334 13.0995 11.42474 11.70505 13.47377 14.31889 12.8265 11.54771 11.79184 11.55733 14.441 14.84616 \n  16.01069 17.67813 17.21562 17.56873 18.24154 16.43555 14.16117 14.16953 13.69155 17.32711 16.4162 13.46104 12.36254 11.61799 11.27409 13.07141 14.62038 12.76868 11.54521 12.79095 12.39311 14.58929 14.84247 \n  16.09941 17.7363 16.53284 17.27621 18.18447 16.58593 14.33624 14.35762 14.19332 17.44104 17.00833 13.70702 12.45344 12.21988 13.11712 14.56761 16.01712 13.74598 12.13099 13.26468 13.10818 15.27417 15.56255 \n  16.42318 17.98415 16.44273 16.57448 17.62833 16.28909 14.36828 14.6948 13.78254 16.22694 15.95521 14.12572 12.26701 11.85083 12.46605 14.29742 16.13456 13.84185 12.26186 12.63923 12.99921 15.56506 15.71164 \n  16.66626 18.41392 16.23549 16.69583 17.69269 16.16858 13.91554 14.21553 13.17823 15.73793 16.4865 15.50647 12.3832 11.67269 11.71129 12.98511 15.19916 14.09333 12.14127 13.53028 13.66361 16.01434 15.8486 \n  16.93131 18.80218 16.81364 17.33029 16.89452 15.53996 14.12277 13.81145 13.03909 15.09264 16.55081 16.00311 12.3552 12.25566 11.77334 12.40888 14.75922 13.7299 12.90318 13.40209 14.23598 16.61812 16.00201 \n  17.09422 18.93463 16.77671 17.12045 16.87137 15.12399 13.50143 13.57805 12.80646 15.09097 16.1608 15.57011 12.32053 11.78571 11.45637 11.75474 14.11037 13.6446 12.81923 13.51655 14.85688 16.60715 15.62787 \n  17.18843 19.15834 16.90851 16.13819 16.45988 14.99436 12.40748 12.04965 12.14001 13.26226 14.0558 13.51968 12.57948 11.99215 11.86336 12.04673 13.09016 13.15625 12.4888 12.85295 14.979 16.59832 15.41977 \n  17.2978 19.31523 17.34639 17.72629 15.35329 13.78927 12.61048 11.38221 11.57769 13.06238 13.21393 12.3947 11.35336 11.29097 10.76642 10.99077 12.29214 12.08838 12.20228 12.01544 11.86961 12.86051 13.13075 \n  17.29455 19.39194 17.52913 18.08251 14.94142 11.73378 12.26912 13.0758 11.84843 11.48248 13.48376 13.39672 11.70031 11.98227 11.31891 10.61537 11.5765 11.5006 12.25064 12.40025 11.37915 12.90368 12.65543 \n  17.11082 19.30302 17.25127 17.65386 14.90019 12.53856 11.45692 13.26181 11.62685 11.53579 13.36939 12.93143 11.07778 11.12064 10.86599 10.39632 11.41168 11.49042 11.78741 12.00982 11.57957 12.68554 12.28857 \n  16.81596 19.11267 17.10374 17.62917 15.10644 12.49786 11.83172 13.11271 12.08539 11.51897 12.27075 12.25029 10.05081 10.51726 10.23621 9.723547 11.47403 11.38655 11.75697 12.38226 11.68046 12.32908 12.25521 \n  16.18891 18.7452 17.12043 17.90645 15.35898 12.87751 11.93357 11.34936 12.12841 12.00346 12.70253 13.15777 10.02708 9.598401 9.508228 9.663599 10.49346 10.55344 11.21704 12.04108 11.25043 12.10459 11.84318 \n  15.3587 18.25852 17.01021 17.94506 15.36013 11.68553 10.90639 9.600526 11.48932 11.83768 11.86593 12.23622 10.37516 10.22231 9.242025 9.690022 10.79908 10.51446 10.66708 11.09983 11.20814 11.95468 11.32153 \n  14.94686 18.0086 16.66558 16.91915 14.43537 11.78186 10.37191 10.1009 10.64833 11.51232 11.21707 11.44729 10.38132 10.89793 11.71739 11.39077 10.99349 11.08029 10.52239 10.70206 11.1781 11.64449 11.60586 \n  15.2814 17.80077 15.7858 15.0733 13.19273 10.99025 11.4507 10.23576 11.88874 11.69319 11.04233 10.65287 11.20542 12.47354 12.96547 12.31134 12.59687 12.5441 11.05464 11.68961 12.18429 12.52163 12.24349 \n  15.48732 17.81838 15.57828 14.95755 13.17332 11.15086 11.35037 10.27524 11.15464 11.83677 10.82353 10.86964 10.84648 12.2185 12.01063 11.35811 12.14788 12.13265 10.27622 11.16301 10.85313 11.33077 11.19722 \n  15.64028 18.04706 15.90875 13.46693 12.71794 10.47495 10.41679 10.41669 11.51304 10.97092 10.52732 10.51946 10.18956 11.28483 11.5248 11.06633 10.79301 11.08132 10.48834 11.23098 10.90977 10.93761 11.2342 \n  15.691 18.08693 15.95903 14.5647 13.08687 11.96817 11.98348 10.27445 10.82906 10.65066 10.7676 10.49903 10.69828 10.99068 11.62179 10.48239 10.64531 10.73122 10.30917 10.84842 11.01107 11.19445 10.96024 \n  15.70235 17.87411 15.54562 14.17106 13.73759 13.39945 12.94871 11.86754 12.32136 13.34113 14.04813 13.64429 12.8817 14.03526 13.78847 14.31763 14.08296 12.28475 12.26945 13.41342 15.16624 15.82314 14.65862 \n  15.111 17.38759 15.23328 14.86325 16.06344 16.10236 14.34899 14.72656 14.66246 16.20999 16.94175 17.2274 15.76645 16.78901 16.12683 16.99647 16.62846 13.99079 13.86968 16.12244 18.25901 19.34782 17.66724 \n  15.03301 16.61184 14.17075 13.25705 14.54141 14.69707 13.71418 15.49278 15.08241 16.18828 17.16152 16.65724 15.34151 13.99803 13.97429 15.01542 15.35275 14.87416 14.55297 15.45949 16.31717 18.42344 16.47798 \n  13.45951 15.78569 13.98534 13.04344 13.92377 14.24774 14.06853 15.00025 15.36809 16.57527 17.38427 17.02029 15.19632 14.64439 14.65536 14.64023 15.68649 15.49167 14.9104 15.35289 16.33175 18.0865 16.37584 \n  13.07347 14.7915 12.67954 13.23848 14.1819 13.9683 13.21752 14.69234 17.90232 17.24359 17.5149 18.04125 15.55333 15.03565 14.85524 15.23376 15.60953 15.83141 15.17968 15.23778 16.42048 17.88067 16.92698 \n  12.37712 14.9033 13.8624 13.76913 13.30324 14.3478 14.02929 14.99968 18.80645 18.39549 18.51047 18.57759 16.0035 14.5608 15.19788 16.24825 16.87722 16.25792 15.09623 15.11478 16.32289 17.68389 16.08194 \n  12.66646 14.60857 12.63233 12.64944 13.4228 13.81045 14.2454 15.89087 17.83408 17.56272 18.75677 18.45625 15.79576 15.1664 15.52465 16.30447 17.33408 16.53073 14.91176 15.41308 16.24126 17.18274 15.97926 \n  12.81794 14.79919 12.64581 13.73917 14.27735 12.86728 13.65656 16.11627 17.94633 17.98828 18.37813 18.78796 17.11118 16.00847 15.83047 16.21775 16.80949 15.5775 14.92074 15.60607 15.80383 16.84433 15.66324 \n  12.5034 15.02809 13.34704 12.59922 13.16282 13.18943 13.6498 16.22042 17.74181 18.11487 19.01717 18.76182 16.68096 15.37317 16.47843 15.88386 16.60799 16.23045 15.78561 15.60193 15.58282 16.25681 16.40265 \n  13.06095 14.47213 11.57626 11.60358 12.57563 13.76851 13.97735 14.38274 16.31401 17.55055 18.43916 18.5317 17.04531 14.99704 16.53685 17.02856 17.58887 16.26225 14.9763 14.45201 15.51912 15.21459 16.6817 \n  12.86505 15.85786 14.75419 13.01475 12.67307 14.4433 15.20655 15.15495 16.09785 16.51936 17.95182 18.31379 16.75537 15.01732 15.75735 16.82045 17.44093 15.66828 14.33217 14.62619 15.22149 15.17155 17.20671 \n  13.12523 16.5502 15.50594 15.34845 14.73641 15.80987 16.79601 17.06586 17.48354 16.89506 16.9989 17.87918 16.51353 15.33819 15.52597 17.10384 16.88856 15.24374 15.05034 15.51818 15.27853 14.60615 17.90415 \n  12.69545 15.62294 14.66864 16.31116 15.64141 15.63712 16.38996 17.50281 17.90165 17.66326 17.61484 17.62272 16.00488 15.10813 14.94744 17.00407 17.49522 15.62474 15.2027 15.69592 15.58376 14.26855 17.33854 \n  11.70221 15.91556 15.21819 16.73549 15.93421 15.34525 15.80453 16.35826 17.22446 17.98482 17.83851 17.86388 16.83107 16.10304 15.82976 17.13237 17.91541 15.26026 15.10075 15.98048 15.72246 14.22937 16.43557 \n  12.58039 16.54533 15.48762 17.14302 16.20825 15.26482 15.79737 16.80904 17.53083 17.92554 17.57588 16.92835 16.21835 16.24897 16.26789 16.09962 16.68681 15.19278 14.3501 15.73407 15.31177 14.58012 16.44425 \n  12.52427 16.68682 15.6768 17.41134 16.48487 16.26741 15.93352 16.79063 17.23722 17.75588 17.59963 16.55783 16.45605 16.19305 16.34012 15.8233 16.01214 14.49679 14.05411 15.83327 15.75738 14.70327 16.81463 \n  13.08901 16.92737 15.88609 17.48892 16.60913 16.92618 15.98914 16.84229 16.96335 17.23575 17.33563 17.23502 16.5829 16.31644 16.85165 16.5601 16.59091 14.8695 14.04865 15.1961 15.04456 15.03072 16.76081 \n  13.25131 16.82976 15.65168 17.33111 16.53403 16.99053 16.30228 16.67911 16.8145 17.26553 17.52997 17.40855 16.6225 16.19843 16.2693 16.43582 16.03738 13.90187 14.50136 15.9589 15.88366 15.52198 16.96512 \n  12.86011 16.4959 15.32254 16.57291 15.98928 16.51817 16.59031 17.21095 17.32273 17.24012 17.26693 17.4594 16.63605 16.95958 17.0414 16.83618 16.73441 14.66106 14.54188 15.98279 15.59871 15.42995 16.82753 \n  12.3734 16.38073 15.23618 15.71347 15.76168 16.80319 16.83652 17.01589 17.01722 16.75942 16.97372 17.74806 16.4648 16.73439 16.26514 16.33158 16.27448 13.83779 14.71891 15.37935 14.90931 15.09158 16.92881 \n  13.16311 16.98702 15.90418 16.86047 16.45071 17.14736 16.50004 16.52925 16.95103 16.78541 16.71283 17.1481 15.68781 16.3924 15.7757 16.42943 16.24413 13.86384 14.62436 15.48191 14.93738 14.84517 16.21951 \n  13.59746 17.23912 16.12656 17.50044 16.93601 17.43536 16.78477 16.41955 16.75596 16.41606 17.25539 17.49482 16.25328 16.44511 15.88677 16.52536 16.53255 14.46775 14.81169 15.79123 14.8385 15.43922 17.17949 \n  13.25004 16.94229 15.93826 17.73337 17.23859 17.89079 17.34496 15.97857 15.19893 15.15988 16.91029 17.25496 16.62859 16.25416 15.48432 15.56355 16.21918 14.83444 15.0622 15.81797 15.64522 15.32866 16.89268 \n  12.62537 16.47641 15.74364 17.85862 17.47602 18.16114 17.55453 15.95657 15.11439 15.08639 16.68707 16.74309 16.72464 16.83375 15.94381 16.12422 16.87457 15.30209 14.94832 16.63556 16.4691 15.57759 17.3871 \n  12.6226 16.10576 15.56736 18.04713 17.56757 18.11768 17.59097 16.34696 15.375 14.14986 15.13968 15.70977 16.85783 17.35108 16.21252 16.49694 16.90446 14.97466 14.87337 16.36794 16.10093 15.90252 17.58858 \n  12.7855 15.88645 15.67985 18.15505 17.37622 17.52381 17.42296 16.19477 15.50058 13.98604 15.38529 15.37528 15.93515 16.47197 15.3381 15.97862 16.40454 14.95582 15.0605 16.63037 15.63746 16.15078 17.13511 \n  12.65207 15.56413 15.72229 18.15676 17.02139 16.67873 16.7427 15.08276 14.19359 12.79751 14.48611 15.64405 16.11738 15.6327 14.42156 14.5413 15.50612 14.09361 14.9137 16.91826 15.45331 16.1494 17.52712 \n  12.56314 15.1539 15.81251 18.0403 17.20735 16.9832 15.43454 13.55827 13.10696 12.59839 13.23814 15.90523 16.60976 15.61129 13.46397 13.59857 14.55115 13.29045 14.68942 16.51844 14.84454 16.06714 16.90926 \n  12.64222 15.16426 16.14207 18.01224 17.03122 16.82287 13.88338 12.87623 12.53724 12.11878 13.98522 15.42566 15.64351 14.8041 13.28969 13.65548 14.46269 13.32662 13.92385 14.84129 13.31076 15.09256 15.82777 \n  12.85059 15.56986 16.29726 18.16373 16.31842 15.27977 12.30446 12.48871 12.05114 12.02475 13.32861 15.53581 15.44006 14.6188 12.19517 12.34837 13.52474 12.41385 13.52724 14.1898 12.92852 15.22741 15.49917 \n  12.59761 14.4621 15.45572 17.18511 15.81542 15.78824 11.84854 11.87338 12.32981 11.94361 12.86972 14.26315 14.89518 14.27585 11.97713 12.49144 13.58669 12.65414 13.09633 13.75735 14.88413 16.18767 15.3166 \n  12.64882 14.81147 14.45962 16.38583 15.72507 15.59489 12.376 11.95343 12.09104 11.86625 12.24266 13.68499 13.91463 13.24626 10.7595 12.1026 13.03325 11.85887 12.62869 13.85928 16.20368 18.33456 16.91249 \n  12.12053 15.05175 14.22981 15.73134 14.97451 14.68129 13.12028 11.97819 11.38219 11.20992 11.37042 12.24603 13.25563 13.08652 10.43595 10.82252 11.63596 11.33452 11.86574 13.24061 15.52648 17.4119 16.81245 \n  11.19065 14.21162 13.51477 14.70132 14.9847 15.25536 14.19143 12.48769 11.34493 9.814653 9.99059 11.53341 12.29802 11.784 10.16933 10.75036 11.20462 10.74964 11.48954 12.01296 13.41964 14.80476 14.38404 \n  10.00999 12.74599 12.14843 14.51654 15.13391 15.2609 13.72731 11.66748 10.16199 9.022615 10.54656 11.04408 11.06597 10.65407 9.941639 9.674333 10.40516 10.81487 11.25098 11.6855 11.23007 11.83496 12.85696 \n  10.08466 11.83495 11.54785 14.59242 13.85901 13.03223 12.44154 11.23707 9.762304 8.823195 10.68114 10.62345 10.76976 10.03955 9.436696 9.586202 11.22563 10.83237 11.0967 10.70838 10.57485 11.49634 11.70702 \n  10.48889 12.83749 11.55844 14.30776 13.98957 13.29756 10.27051 11.19239 10.73191 8.282329 9.798191 11.28903 11.10856 10.43637 9.679453 9.696969 10.23166 10.5042 10.2436 10.84797 10.9094 11.14272 11.04821 \n  10.19536 11.74172 11.33944 13.41399 13.06223 13.24977 10.40681 9.719469 9.504123 8.071562 9.28103 10.37499 11.08919 10.83884 9.125082 9.426393 10.12565 10.30615 10.62199 11.02502 10.98999 11.49767 10.76202 \n  10.88223 12.977 11.56636 10.88618 12.75476 12.96493 10.24409 9.20118 8.650577 7.399164 8.780226 9.993423 11.50119 11.16004 9.309609 9.911741 10.38707 9.787494 10.5507 10.78142 10.8794 11.07239 10.47661 \n  10.47173 13.69682 12.45944 12.35382 12.58801 12.46847 10.00025 10.27305 11.53972 12.61611 13.00516 13.0168 12.24968 12.74772 13.46355 13.35037 12.67452 11.07662 10.77348 12.34726 13.52226 13.54476 12.45269 \n  10.39999 12.38218 11.96567 12.83998 11.78783 11.14596 10.65086 9.983682 11.39105 12.32884 12.81081 12.60661 11.70481 12.39304 13.20282 13.14799 12.67365 11.12111 11.64005 15.3785 17.26889 19.2809 18.58731 \n  10.06194 11.97701 11.10652 11.85843 11.02539 11.2265 10.7828 9.873035 10.32476 11.25525 11.96012 12.71968 11.64478 11.76205 12.47315 13.18736 12.99789 12.38262 13.63724 17.6046 20.06792 21.4036 21.43807 \n  9.509731 11.85916 11.10777 12.50954 12.18235 11.80091 11.27237 10.29496 12.2601 12.32322 13.42 14.12483 13.16052 13.71877 13.45849 13.22503 14.22825 13.49225 15.37626 19.22064 21.55962 22.73142 22.24018 \n  9.15207 11.07175 10.86126 11.87928 12.69756 12.46886 11.5245 13.08445 13.88625 14.80505 14.99481 15.52319 15.05282 15.02273 14.87423 15.29251 15.91438 14.93134 16.80274 21.40077 22.54545 22.58663 22.29738 \n  8.860111 10.74111 10.50416 12.93807 12.55079 13.06175 12.17259 13.51095 14.48125 15.87022 17.08365 15.86352 15.00874 14.95488 15.34727 15.18754 16.02795 15.03839 16.93264 19.53366 21.6056 21.50261 21.28786 \n  10.75877 10.37344 10.58075 12.34408 12.94353 11.96778 11.4975 12.68404 14.95128 16.74927 16.77153 15.63198 13.98707 14.3226 14.68699 15.35497 16.36192 15.49951 15.98009 17.65331 18.19219 18.41393 18.1715 \n  9.39485 10.52738 11.42019 12.21228 12.45682 12.18025 11.33037 12.44518 14.51794 15.84477 14.62877 14.42839 14.07113 13.2896 13.65752 13.82688 15.6779 15.75582 15.67209 17.08607 16.55664 17.27306 16.92216 \n  9.381274 11.83695 11.8863 11.62455 11.99966 11.92766 12.16977 12.76743 14.2169 15.01731 14.82383 13.0397 13.42383 13.10484 13.42112 13.71131 14.73178 14.64882 14.79978 16.09834 16.16719 17.4647 16.77292 \n  9.585428 10.993 10.5035 11.81598 11.44083 12.43314 11.64416 12.2522 14.10823 14.41961 14.19406 12.61582 11.76546 12.10949 13.28017 13.21444 14.49621 14.27315 14.40105 16.25966 16.55149 17.44991 16.81313 \n  8.175888 11.18484 11.35472 11.47145 12.36835 12.95294 11.74024 12.37499 14.70968 14.42316 13.73902 12.62927 11.59597 12.07641 12.50259 12.79706 14.06515 14.19124 14.13676 15.15194 15.65369 18.23908 17.15416 \n  9.260625 10.70815 9.263671 9.806908 11.83224 12.31308 11.73443 13.4353 14.60034 15.05972 13.83386 12.88395 11.57649 12.02801 12.20291 12.59455 14.31687 14.47969 14.6405 15.52516 15.67438 18.1055 17.65921 \n  9.911335 10.50611 10.12131 9.937845 12.0217 12.06643 12.41577 13.58587 15.64432 14.32141 13.08726 12.30006 11.95351 12.71829 11.26942 12.65187 14.17917 13.53116 13.70112 15.10717 14.98607 17.59751 17.46946 \n  9.024209 8.987809 9.160165 10.86254 12.75719 12.29259 12.99271 14.01397 14.93609 15.38431 14.07591 12.15879 11.33199 11.99755 11.29723 12.28741 13.99432 13.90781 13.2847 14.09958 14.27385 16.84444 16.68974 \n  11.9299 13.47678 12.837 11.34953 12.98505 12.79702 14.93977 14.99091 14.8044 15.23901 13.70815 12.30987 11.19355 11.14724 11.14456 11.97139 13.38016 13.39131 13.10051 13.16111 13.63137 15.1045 15.48153 \n  14.41228 16.11685 15.7402 15.5474 13.80078 14.53132 14.65797 14.65964 15.91533 16.35481 13.96598 12.8188 11.46816 10.90168 10.61743 11.47446 13.77556 13.64553 13.89567 13.91599 13.57935 15.20967 15.69138 \n  15.08783 16.8548 16.49383 16.41818 14.09665 15.30241 14.7049 14.89885 15.83918 18.0921 16.22671 14.06109 11.65885 11.18969 11.55042 12.64634 15.04636 14.6538 14.17054 14.18222 15.13279 16.13375 16.41827 \n  15.16109 16.7801 16.56729 16.43837 15.12475 14.8846 14.26196 15.39288 16.01123 17.1432 17.07575 15.71479 12.39699 11.93664 11.86322 12.98023 15.49663 15.14287 14.6057 14.86261 15.40321 16.85805 17.07797 \n  15.09084 16.57223 16.80362 16.58635 15.20792 15.10697 14.90998 15.40153 15.35094 16.88487 17.96318 16.37918 12.55137 12.20782 12.30409 12.03328 14.67583 15.03111 14.56669 14.42755 15.211 17.10543 17.10053 \n  14.69408 15.81541 16.46612 16.37843 15.2229 14.59921 13.61355 14.3778 14.58977 16.18752 17.5792 16.62926 12.41473 12.08434 12.35257 11.9434 14.27981 14.79067 13.80497 13.96159 14.25573 17.45439 16.78282 \n  14.43095 15.41959 16.21408 16.07892 15.18807 14.0085 13.96235 14.37799 14.08463 15.0561 16.641 15.33981 12.0121 10.58257 10.67117 11.07191 13.45955 14.30978 13.5234 13.39615 13.00758 15.30398 14.59562 \n  14.58677 15.82187 15.58251 15.65558 15.2996 14.34471 13.48909 13.53928 12.62957 13.79965 15.50717 14.88582 12.17444 11.02395 10.55875 10.28314 11.87372 12.80804 12.80521 12.87114 12.06493 14.00245 13.72964 \n  14.95683 16.3266 15.16857 15.4292 15.51012 13.59986 12.23133 12.66695 12.21721 13.14255 14.3418 13.26337 11.4309 11.01019 10.59134 10.42654 11.62912 13.19194 13.29006 13.23644 11.81969 14.27526 13.76118 \n  15.59626 17.08241 15.06971 15.65379 14.82292 13.31317 11.43343 11.9617 11.85537 12.2777 14.29009 13.45866 10.72894 10.13381 9.537953 9.800446 11.53536 12.31185 12.60432 11.92848 11.34388 12.84455 12.54369 \n  16.04304 17.82648 15.79309 16.24393 14.73321 13.42411 10.97739 10.73002 11.65459 12.07827 13.2604 12.44436 10.10683 9.841578 9.451722 9.291868 11.41494 11.8923 11.88242 11.91761 11.27107 12.20158 12.1325 \n  16.25625 18.22469 16.04192 16.12708 14.96282 13.00054 10.65593 11.17855 11.14046 12.55776 12.52015 11.42063 9.433226 9.00628 9.585645 9.290247 10.70464 11.49628 11.68974 12.07785 11.17581 11.06459 11.13168 \n  16.04482 18.14673 15.86384 14.91284 13.05532 12.45239 11.72008 11.51588 11.29592 11.78518 12.2973 11.38977 10.29393 9.548064 9.722668 10.09043 10.84775 11.8718 11.26131 11.56782 11.02544 11.18756 11.03338 \n  15.26615 17.28764 15.16505 14.44016 13.28143 12.07429 10.97578 11.15899 11.50891 11.01097 11.61723 11.36335 10.16722 9.822009 9.901525 10.20638 10.18853 11.82158 11.44402 10.68624 10.50383 11.11971 11.41882 \n  13.81127 16.00517 14.23292 13.67491 13.21358 11.73995 9.486867 10.56567 9.862735 10.49043 11.29869 10.67811 9.464268 9.29777 9.709767 10.42091 10.48922 10.93209 10.42687 11.04964 12.2851 12.72577 12.39185 \n  12.14262 14.94287 14.0802 14.32626 12.80348 10.66512 9.237948 9.739904 9.596913 10.61011 11.65724 10.63011 9.505305 9.886621 10.47523 11.0215 10.59563 10.78076 11.00128 13.60528 15.06756 16.77889 16.86555 \n  10.83472 14.31258 12.90632 12.77348 12.20279 9.816229 9.277019 10.18015 9.096459 9.997322 11.51482 10.87203 9.44985 10.83187 12.01145 12.17475 12.17965 11.82202 12.18132 14.90107 17.46739 18.73794 18.04218 \n  11.36189 14.46365 13.13914 12.11007 11.7593 10.0019 9.75862 10.77737 11.03628 12.26316 12.78038 11.30242 11.24927 12.86973 13.40784 13.56777 13.70109 13.02316 12.83176 16.09006 18.6455 20.18859 19.64919 \n  12.72338 15.11341 13.32158 12.74039 11.63489 10.73177 10.17774 10.56085 11.74206 12.8467 13.64448 12.64196 13.06981 14.0199 13.50293 14.09397 14.45456 13.70243 13.05322 16.6385 19.08248 21.01362 20.21127 \n  14.20404 15.91786 14.92538 15.12413 14.77285 12.89441 12.79587 11.85586 12.40155 12.80069 14.29893 14.05416 12.61579 13.57712 13.58947 13.30546 13.65021 12.84343 13.35256 14.62488 16.85373 18.83813 18.01679 \n  14.53132 17.33943 16.26635 18.11593 17.92229 16.41659 14.97751 13.63034 14.93866 15.25947 16.20634 15.82948 14.33713 12.11738 13.05697 13.88322 14.07832 13.04026 13.09391 14.61522 14.58644 16.06195 17.62827 \n  14.11968 16.69542 15.12335 18.32276 17.78468 17.74669 15.92803 14.50374 15.56971 16.23568 16.50482 16.08389 14.88408 13.72153 14.5031 14.91234 14.72964 13.03544 12.99891 14.99354 14.95278 15.26584 17.54221 \n  12.58309 15.06906 15.59264 18.20675 17.21118 17.89225 16.83617 15.57529 15.21058 16.55922 16.91265 16.39316 15.46596 14.28004 14.31382 15.09121 15.5357 13.50103 13.16001 15.68369 15.05554 15.30483 17.25786 \n  13.38149 16.1832 16.11864 18.42098 17.48438 17.89621 18.30592 16.22846 16.11395 16.84072 17.24339 16.6131 15.43338 14.83396 15.42686 15.86161 16.32101 15.09858 13.3338 15.44106 14.9978 14.34465 16.55215 \n  14.37599 16.83687 16.94507 18.2267 16.84422 18.06699 18.55002 15.54701 16.76327 16.83081 17.27568 17.00946 16.32395 15.44895 15.63621 15.85781 16.74874 15.47261 13.73446 15.28013 15.02808 14.89976 16.14604 \n  15.05994 16.78429 17.38232 18.71122 17.29902 17.89909 18.18792 17.06817 16.19571 16.4189 16.93696 17.02257 16.01795 15.9466 15.9529 16.66254 17.07906 14.79625 13.80007 15.45906 15.62278 14.89583 16.3634 \n  15.31985 17.11125 16.90094 17.50673 18.12416 17.26594 18.61826 17.81363 16.92988 17.33131 17.22307 17.6853 17.16475 17.8327 17.79674 18.01369 18.75657 16.41342 14.83692 16.64419 17.08493 16.10439 17.74908 \n  14.81287 16.67113 17.24438 17.58853 16.56671 17.4409 19.14317 17.1272 17.22141 17.37194 17.30178 17.35553 16.81259 17.59592 17.2289 17.99676 18.54756 16.97488 15.1711 17.01239 17.41453 16.61493 18.02877 \n  14.10214 16.48185 16.70473 17.83863 17.09863 17.92168 18.60074 17.03748 17.01916 17.1662 17.45386 16.9503 17.22705 17.88758 17.25076 18.06163 18.82708 17.06891 15.6639 17.32082 17.86867 16.99368 18.4935 \n  14.47095 16.27239 17.20447 16.68737 16.69925 16.92639 17.55458 16.4129 16.37072 16.70506 17.13801 16.74328 16.66209 17.66596 17.03108 17.52262 18.5179 16.57609 15.3233 16.59836 16.57953 15.76227 17.69633 \n  13.24856 14.56392 16.16074 15.96923 16.11824 17.0615 17.37887 16.89696 16.49023 16.93359 17.04477 16.61666 17.3206 18.46787 17.4531 17.96162 19.10358 16.9934 15.63334 17.35444 17.27749 16.49334 18.51469 \n  13.37477 14.40732 15.3166 16.12179 16.0549 17.9857 18.24229 15.97747 16.51573 16.80781 17.66976 16.77187 17.07391 18.37435 17.8941 17.99025 18.43793 16.58463 15.94918 17.33995 17.58286 16.71625 18.26147 \n  13.93172 15.95009 16.12278 16.62806 16.77155 17.70332 18.30991 16.70022 16.12438 16.63647 16.96805 16.56441 16.83017 17.72108 17.19194 17.83681 18.34489 16.32563 15.5139 17.0459 17.14361 16.61393 17.9541 \n  13.97243 15.71532 14.24013 15.94024 16.42779 17.24181 18.20842 16.16203 15.17454 15.77178 16.21501 15.67723 16.35604 17.39831 16.76721 17.22853 17.88738 15.95963 14.72727 16.41531 16.48671 16.12189 17.57236 \n  13.12301 15.36403 14.92359 14.51013 15.03061 17.25054 18.02694 15.68099 14.72595 15.05695 15.51794 15.62031 15.82822 17.21599 16.45444 16.81317 17.53438 15.40422 14.59688 15.75735 15.82233 15.50435 17.19834 \n  13.63734 15.75846 15.76891 16.33092 16.02224 15.02408 15.51878 13.95916 13.93933 15.34064 15.0723 15.51362 15.4393 16.63021 16.81165 16.50006 17.1815 15.69489 14.01058 16.13823 15.96146 15.71183 17.02876 \n  13.19862 15.13811 14.20608 14.87641 13.86195 15.69343 16.0471 14.37471 12.70754 13.07089 13.74677 13.72397 14.30151 15.42236 14.87322 14.77012 16.19817 14.61831 14.36353 14.7163 14.1343 13.27196 14.94497 \n  13.07108 14.96432 15.33887 15.41621 16.32788 16.2543 15.70077 13.64809 12.23586 13.97429 14.36621 14.99106 14.89284 15.73454 15.09936 16.08811 17.21342 14.54043 14.93736 16.18698 15.30752 15.68343 17.1031 \n  12.17307 13.8663 14.74691 13.82833 15.29623 15.13898 14.94032 14.15431 13.22405 12.60576 13.50053 13.70859 14.2374 14.95605 14.1026 13.79868 15.32834 13.637 13.26627 13.85343 12.49579 13.00945 15.18009 \n  12.25888 13.0473 13.98215 15.20883 14.53955 14.94806 15.02145 12.94323 12.06552 12.47472 12.65622 12.89004 14.31748 15.0515 13.45358 13.49286 14.73266 13.38384 12.97834 13.98633 13.04967 14.18903 15.84389 \n  12.96655 13.67219 15.57411 16.78977 16.06032 13.93955 14.09687 13.42214 11.74005 12.39577 12.6212 13.11872 14.73195 14.7253 13.47528 13.54747 14.39114 12.98527 13.10725 14.80631 13.07693 14.86841 16.53499 \n  10.92069 13.71753 13.87495 14.55451 14.22817 13.57006 13.76763 12.60664 11.17306 11.62393 12.25004 11.81037 13.68605 13.56421 12.86382 12.15489 13.24436 12.0221 12.38628 13.08033 11.34459 12.62064 14.02351 \n  11.5769 13.79373 14.03928 14.87669 13.80563 13.71551 14.04329 12.57617 11.19479 11.37623 10.92707 11.98935 12.46576 12.69549 12.09219 11.78906 13.35041 11.86954 12.23488 13.13238 10.95979 13.09149 14.30729 \n  10.74847 13.18716 13.24313 12.67642 13.39273 12.77279 12.68126 11.46781 10.00143 9.96587 10.43531 11.69773 12.84946 12.46179 11.33073 10.75771 12.40113 11.34042 11.7729 12.49863 11.20993 11.8419 11.45071 \n  11.98419 13.92745 12.27599 12.76547 12.93638 12.34464 12.64864 11.34802 10.23944 9.272176 10.22678 11.26323 11.94163 12.36338 11.0064 10.31246 12.27957 11.23496 11.376 12.09842 11.01261 11.91821 11.30618 \n  11.78683 13.45012 12.74603 13.96315 13.49791 12.03139 12.34809 11.16278 9.914504 8.632698 10.02429 10.49186 10.53503 11.25449 10.37139 10.6025 11.64441 10.73072 11.01634 10.47035 9.727706 10.35247 10.77614 \n  11.52162 12.46663 11.89697 14.03308 13.64052 11.73958 11.48232 9.956855 8.571227 8.986975 9.7626 10.39963 10.45375 10.46915 10.78598 10.67382 11.57074 10.30212 9.981796 10.63711 10.12906 10.43168 10.83299 \n  10.47112 11.29303 12.18044 11.88793 10.8442 10.59727 11.06464 9.595164 9.016017 8.599607 8.99171 9.042683 10.83571 10.81611 9.935513 10.24435 10.53577 9.991421 10.32891 10.49404 10.43093 10.59912 10.33619 \n  11.11114 12.00806 12.1118 11.56301 11.28773 11.11582 11.11947 10.14109 9.354194 9.394133 8.459903 9.571765 10.62552 10.94563 10.39587 10.17176 11.07636 10.36478 10.18448 10.5289 10.58135 11.55 12.22885 \n  9.4698 10.58114 11.28397 11.78697 11.88663 11.19909 11.94986 8.947301 8.886659 9.0145 8.525748 9.001356 10.4408 10.03337 9.662758 9.838831 10.64479 9.835432 9.941095 11.35219 12.8765 13.6802 13.69769 \n  9.431818 10.37749 9.402466 11.65605 12.08712 11.54609 11.73875 8.867339 9.922234 10.61318 10.76134 10.87708 10.16173 10.49702 11.13492 10.97119 10.87446 9.942475 10.69347 12.76756 14.78555 15.63049 15.3683 \n  9.377582 10.94667 11.15134 12.46202 11.73515 10.88063 11.25175 9.65536 11.14065 11.88232 11.94413 11.89391 10.90223 11.40995 12.1747 11.62114 11.59762 10.78957 11.37593 13.46099 15.81433 17.16356 17.15998 \n  9.576265 11.13453 10.96931 10.33049 10.23858 10.44758 10.76839 8.92027 9.525447 10.34433 9.90531 9.858282 9.904203 11.16824 11.88748 11.96853 11.37809 11.49845 11.76391 14.43392 16.65162 18.26472 17.6829 \n  9.068971 10.9832 11.37302 11.22971 9.851135 9.574883 9.735991 9.078069 9.105554 10.11883 10.55576 10.29943 9.432137 11.80125 12.00973 12.56134 12.2724 12.0964 12.37772 14.91978 17.71165 19.49631 18.86863 \n  10.06087 11.30585 10.13232 9.214253 8.846772 9.325168 10.23292 9.699574 10.61134 11.65377 12.32304 11.8669 11.56203 13.31346 13.75598 14.85218 14.10346 13.62769 13.95514 16.67099 18.7434 19.90597 20.01846 \n  9.883128 9.034005 10.26573 9.922016 9.431784 8.751758 10.03959 10.56669 12.11162 13.17491 13.19539 13.8256 12.93738 14.20389 14.85687 14.53677 14.83226 13.86686 14.76633 17.12251 20.07998 22.08923 21.37822 \n  9.735471 10.76163 10.26859 10.09679 10.99103 9.163989 9.649745 10.54053 11.75659 12.85315 12.67314 13.1372 12.42263 13.90682 15.30728 15.41667 14.59862 14.48736 15.16387 17.94337 20.98712 23.08864 22.34081 \n  8.208311 9.269901 9.024371 9.993098 11.19902 9.208381 9.769848 11.40966 12.96586 14.02102 14.22982 14.19959 13.32056 14.34479 16.31928 16.57144 15.62925 14.52523 16.18148 18.67118 20.88604 23.1573 22.48557 \n  8.409505 9.858494 9.497688 10.31458 11.88834 9.982258 10.32621 11.68756 12.89914 13.39427 14.21135 14.64743 13.3156 14.29278 16.14828 15.96886 15.35177 15.5271 16.91822 18.72905 21.57679 23.61708 23.15364 \n  8.934703 9.573559 9.441955 8.765581 10.14542 9.618201 10.5309 11.58863 12.7027 13.85705 14.36015 14.13195 13.7818 15.45178 16.22048 15.6483 15.75696 15.26135 16.86555 19.28024 22.11215 24.40104 23.93007 \n  8.684306 8.866581 8.434036 8.029984 10.91321 11.22698 10.23968 11.33583 12.85784 13.39227 14.42832 14.13936 13.58225 16.27074 17.07727 16.51017 16.3993 16.14433 16.99274 19.69513 23.2365 24.59908 24.04222 \n  8.643711 9.807123 9.50042 9.324292 10.83774 11.15303 10.39372 11.22418 12.95454 13.35421 14.3774 13.54205 13.72393 17.05115 17.68932 16.12386 15.83425 16.01268 17.58204 19.77008 23.01275 24.67944 24.14307 \n  7.688036 8.535404 9.236469 10.83574 11.49044 11.28016 11.46384 12.16683 13.50681 13.8899 13.76011 13.80902 13.72299 16.50299 18.20104 16.61069 16.52741 16.1986 18.36386 20.11685 22.81937 23.6178 23.35131 \n  10.17826 8.205004 9.347319 12.3267 13.34488 11.22051 10.90597 11.83232 13.47991 13.05177 12.89349 13.7592 13.9114 16.77988 18.02056 16.96051 16.41222 16.26488 18.08109 20.25217 22.95943 23.70821 22.32704 \n  9.040493 8.760096 8.527176 9.89751 10.56365 9.972799 10.10701 10.67076 12.86245 12.45882 13.2768 14.06905 14.12293 17.41031 18.83172 16.48821 16.42317 16.09177 17.95219 20.02211 23.01787 23.78878 22.42188 \n  9.399467 7.837672 9.216712 10.6783 10.54392 10.52287 11.50509 11.89538 12.42534 13.73793 12.68215 13.53249 13.51577 16.23136 18.68464 17.29062 16.49525 15.83475 18.22473 19.69581 22.15342 22.9642 22.44792 \n  8.776668 9.244227 9.925127 11.38309 10.78001 10.8051 10.342 11.05655 12.77748 14.84761 13.69246 13.08996 13.35411 16.14378 18.69108 17.32467 17.7679 16.45478 17.57494 19.5618 22.46428 22.97581 21.49464 \n  8.894381 9.427493 10.64883 11.46896 10.78124 9.074279 10.21656 11.47114 12.82468 12.99811 12.95543 12.60641 13.26145 15.72201 18.2295 17.42356 17.95378 16.7246 17.54635 19.24829 21.3367 21.933 20.77688 \n  9.042042 8.76036 10.59839 11.72806 12.2252 10.01876 10.65936 11.28481 12.38915 12.18661 11.73761 12.19487 12.95884 15.87654 18.47887 17.35869 17.52493 16.28156 16.84913 18.45013 20.72539 20.79898 19.75169 \n  10.06297 12.90782 12.88049 10.60552 11.71332 10.51397 9.21656 10.82334 11.41065 12.40258 13.10792 13.42447 12.83565 15.32679 18.56764 17.4046 16.69835 15.57237 16.41321 17.4268 18.71982 19.50741 18.1189 \n  9.921656 16.52995 17.53824 15.70275 15.32331 12.92085 12.47987 12.10413 12.42868 12.15174 12.5522 11.8612 12.07436 13.91121 17.06873 16.3721 16.04488 15.49017 15.58386 17.01062 17.89955 17.60539 17.31772 \n  11.36264 17.33499 18.40477 17.00244 18.4658 15.7809 13.04894 11.71813 12.67283 13.29064 13.457 12.057 11.66851 13.66247 17.68314 16.57116 15.98984 14.92666 16.06848 17.17213 17.39293 17.66684 17.4516 \n  10.62282 17.60542 18.32822 17.09484 19.33393 16.77328 12.53772 11.13757 13.03852 14.02408 14.38111 13.17555 12.76845 14.38874 17.52058 16.74355 16.38338 15.24556 15.39419 16.26055 16.64132 16.97384 16.89183 \n  10.47606 17.70844 18.43419 17.68979 19.75669 16.95199 11.87117 12.01979 13.45656 14.36295 14.81179 13.49354 12.68675 14.77314 17.4999 16.20375 15.68843 15.2202 15.67017 16.32603 16.47589 16.68805 16.65318 \n  10.98051 17.72518 18.46542 18.05853 19.93608 16.77472 12.27509 12.2058 13.27803 14.52329 15.10997 13.82026 12.10452 13.67547 16.55763 15.52405 15.14251 14.49046 15.37576 16.78892 16.64076 16.92625 17.4085 \n  10.61574 17.7157 18.246 18.44892 20.22108 17.01719 13.5045 12.65141 12.83893 14.40987 15.02312 13.29914 13.55334 15.01744 16.19461 15.84118 15.6518 14.68441 15.11373 16.25138 16.23415 16.90338 17.4352 \n  10.69256 17.79112 18.42277 18.3324 20.11359 16.95714 13.75263 13.08895 13.11321 14.44533 15.22537 13.40903 13.27475 15.41946 15.46931 15.14482 15.65731 14.71926 15.28069 17.00951 16.92454 17.32482 17.49486 \n  10.73899 17.75406 18.27556 17.87709 19.47082 15.97545 13.59863 13.1574 13.07014 14.04729 14.62672 13.32558 12.45246 15.42138 14.76762 14.0249 15.21964 14.52955 15.10038 17.08111 17.13165 16.41658 17.86931 \n  9.618335 17.47857 17.98661 17.55681 18.80152 14.7733 13.48202 12.65518 13.07832 13.56103 13.67241 12.99241 12.99369 14.52666 14.21892 14.50008 15.0451 14.01138 14.70819 17.09094 17.17188 17.34347 17.56815 \n  11.57962 16.64433 17.44956 16.3053 18.07066 14.92957 13.12261 12.80251 13.23727 13.17543 12.1275 12.36365 13.38163 14.66714 14.47845 14.50121 14.2356 14.29019 15.07313 17.368 19.52579 21.40561 20.27804 \n  10.79007 16.8456 17.36958 16.39471 18.20171 15.12339 12.79474 10.63306 11.83869 12.54484 13.22725 12.38338 12.43016 14.38861 14.98121 15.43519 15.47331 14.8543 16.05373 18.43741 20.38091 22.39174 21.13035 \n  11.29912 15.8077 16.54896 16.36229 18.221 15.09686 11.11965 9.979053 10.83024 13.19693 13.55953 12.65395 12.45233 12.89222 15.0179 15.60445 14.92871 14.3497 15.49676 18.35275 19.81606 22.24131 21.26899 \n  10.58634 15.52423 16.11585 16.42515 18.17402 15.00347 10.48176 11.49412 11.44849 12.50072 12.81663 12.37796 12.68344 12.88461 13.50673 14.09901 14.95052 14.7693 14.78594 17.34875 19.04901 21.56851 20.89043 \n  9.614183 15.8431 16.38121 15.86494 17.58311 14.49032 11.02957 10.22538 9.527282 10.68686 12.11254 12.43469 12.31795 13.20986 13.51692 13.65216 14.22145 14.17002 14.99944 16.96408 18.17498 20.48696 20.18502 \n  10.00105 14.93148 15.57334 14.18313 15.84909 13.41543 10.91846 10.40649 10.04232 11.3954 11.08972 10.65496 11.28233 12.84103 13.64318 13.3043 13.51652 13.92885 14.5559 16.84107 18.5327 20.81325 20.21984 \n  8.364077 14.47285 15.08788 13.55744 15.35808 12.38914 10.11354 10.69198 10.48146 11.39112 12.41379 12.30688 11.5294 12.61159 13.42383 14.04588 13.40064 13.34902 14.46458 16.70078 18.35919 20.76412 19.943 \n  9.641496 14.35918 14.95244 14.19986 15.70295 12.1898 10.18897 9.93488 11.01549 11.42438 12.44854 12.86371 11.5565 13.17326 13.65934 14.53895 13.90649 12.75882 14.03429 16.0668 18.27451 20.19135 19.50024 \n  8.998137 15.16441 15.34586 14.19052 15.65328 11.88099 10.49521 10.64151 11.44318 12.29878 12.59886 12.93051 11.39418 13.67889 14.56925 14.55365 14.10461 13.24354 14.07761 16.63885 18.53308 20.30708 20.31402 \n  8.946667 14.58632 14.90333 13.99691 15.40372 11.7403 9.425845 11.23817 12.30968 13.13296 12.68324 12.09499 11.59824 14.54168 14.32594 15.0352 14.37218 13.71023 14.06014 17.93824 19.09838 21.4241 20.9504 \n  9.447927 13.22877 13.59622 13.29706 14.72807 10.7798 10.31542 10.73058 12.23221 13.26059 12.40936 13.92871 12.75949 13.78177 15.05717 15.43973 15.04269 14.58284 15.24181 18.27596 20.08396 22.0071 21.56488 \n  8.942842 12.3533 12.72897 12.85406 14.50646 11.68498 10.16205 11.14519 12.01001 13.16905 12.63423 12.60056 13.09376 15.80599 15.64569 15.43857 15.37898 14.46924 16.22836 18.90742 20.43498 22.41726 21.382 \n  9.982429 12.81441 13.19554 12.47804 14.03025 11.90199 10.44281 10.78242 11.68254 11.92076 12.58015 12.23102 12.68594 15.57787 14.6662 15.05085 15.23528 13.82845 15.80674 17.82709 19.04893 21.38214 19.97395 \n  9.869902 15.98693 17.0225 15.82257 16.53093 14.39392 13.55346 13.0189 13.5896 13.15744 13.18752 12.97133 12.9559 14.33525 13.73748 13.04741 14.4363 13.70424 15.57391 16.99634 17.09068 17.86176 18.46799 \n  11.20318 16.74047 17.93852 17.55423 19.5529 17.38312 15.2714 13.70905 14.90142 15.34691 15.5448 12.94791 14.09873 15.03901 14.75121 14.84058 15.57433 14.77669 15.42783 17.23933 17.08564 16.54724 18.42886 \n  10.00581 16.99308 17.64376 17.35759 19.84209 17.72609 16.06901 13.94531 14.6718 16.30286 16.95507 13.571 14.54512 15.59432 15.28288 16.09251 16.91068 14.48281 15.62211 16.89838 16.95857 16.07769 17.91624 \n  10.26451 17.10342 17.68718 17.12966 18.80752 16.72883 17.11706 14.18921 15.08757 17.02866 17.63015 14.70868 14.18901 15.36524 15.08402 16.53765 17.53717 14.94885 15.30448 16.46144 16.25202 15.7747 17.48356 \n  10.57615 17.0614 17.78706 16.76842 18.19138 17.44588 18.12214 14.26881 15.37736 17.35711 17.82368 16.12888 14.66693 15.406 15.11084 16.10291 17.21349 14.85879 14.25072 15.92479 15.79147 15.51069 17.19426 \n  9.48652 16.911 17.18489 17.25456 18.75069 18.27182 18.70464 15.1519 15.75929 18.05139 18.79077 18.19505 14.61217 15.21042 14.50809 16.6024 17.5759 14.97376 14.62691 15.54537 15.83502 14.67196 16.36763 \n  9.985225 16.74782 17.24112 17.25887 18.27095 18.51624 18.83493 16.13771 15.24101 18.14103 19.13589 18.64982 14.49468 13.72041 14.16209 16.20668 16.41984 14.58272 14.20643 15.07785 16.00739 15.01148 16.37612 \n  8.453218 16.44852 16.53209 17.24354 18.39434 18.03302 18.01833 17.08058 14.58579 18.43371 19.00238 18.1741 14.07615 12.95393 12.84746 15.36702 15.92542 14.33508 13.597 14.46982 16.11521 14.52893 17.01237 \n  9.352406 16.0076 16.35685 16.47454 16.98188 17.873 17.68334 17.51781 14.67671 18.76287 18.72811 17.72148 13.38931 12.69698 13.39213 14.65827 15.30858 15.00858 14.27974 14.66115 15.79502 13.98777 16.22205 \n  9.672524 14.51215 14.49281 17.57202 18.71115 18.5533 18.56325 18.01528 15.20035 18.96259 18.58512 17.13366 13.41415 12.05879 12.61457 14.21013 14.71272 14.4392 14.22963 14.40962 15.35258 14.32724 15.84399 \n  9.294844 14.85708 15.12689 17.73894 18.71831 18.47003 18.26656 17.68312 15.53754 18.16326 17.79104 15.80158 12.8884 11.75445 11.60362 14.12353 14.61159 13.81479 13.50152 14.23705 15.36493 14.26479 16.47873 \n  8.768968 15.45139 15.69153 17.49653 18.18467 18.7153 18.61305 16.95576 17.30786 17.01988 16.78725 15.96744 13.20623 11.91497 10.71408 13.16159 14.11679 14.18742 13.99787 14.10843 14.59204 14.09456 16.28277 \n  9.966001 15.72716 15.85344 17.40161 18.01343 18.25241 18.0155 17.06878 17.53317 16.64179 16.41474 15.78998 13.04946 11.22962 10.81054 12.68965 14.08202 14.16896 13.95166 14.16778 15.26385 14.41844 15.19306 \n  9.675585 15.72316 15.94752 16.87626 17.34341 17.19278 16.94996 16.84417 17.60019 16.79139 15.83696 14.38576 11.87001 11.4011 11.60792 12.10766 13.4803 13.23835 12.92072 14.22253 15.03658 14.08519 14.59369 \n  8.843268 15.32752 15.28943 16.05486 16.22001 15.98866 16.2473 16.98972 17.01772 16.9006 16.29029 14.78596 10.99794 11.25592 11.78223 12.48373 13.76172 13.57825 13.22475 14.14124 14.77772 14.18768 15.47867 \n  9.988932 15.02293 15.06712 16.10529 16.68101 14.5116 15.2082 16.47553 16.51361 17.52498 17.05329 14.73698 11.47603 11.26132 11.55777 12.60618 14.0904 13.70418 12.92093 14.22556 15.54817 14.19895 15.33703 \n  9.373691 14.60107 14.44204 16.04573 16.79593 15.65233 15.8361 15.7082 15.76369 17.70542 17.72066 15.61394 12.20694 11.29502 12.29862 12.74661 13.96791 13.84649 13.18555 14.58438 16.68427 15.04027 15.47512 \n  9.678563 14.24788 13.43199 15.21713 15.649 16.42124 16.40302 16.3937 15.09498 16.95411 17.4481 16.14875 12.54013 12.54267 13.3262 13.59261 15.50308 14.9336 13.64636 14.634 16.40599 14.55039 15.61549 \n  10.3574 15.14911 14.75568 15.57308 15.29968 16.94623 16.488 16.12799 15.32639 15.1618 16.76408 16.33082 12.41711 12.65482 13.66632 13.70024 15.7187 15.12583 13.7085 15.76237 17.63751 14.65858 15.68508 \n  10.7973 15.52072 14.91968 15.44418 16.11236 16.58336 16.3113 15.46747 14.99532 15.4524 15.88347 15.21543 12.29164 12.56826 12.42722 12.49476 14.77974 14.30123 13.07562 15.28318 17.01124 14.17749 15.07545 \n  11.72055 14.70813 14.33016 15.86267 16.10855 16.00652 15.79218 14.71058 14.24063 14.49434 15.89563 14.62785 13.76968 14.33625 13.71839 14.10913 14.64376 14.01509 13.78574 15.50584 16.63034 17.31616 17.19594 \n  11.63814 14.6362 14.03121 15.15585 15.78361 15.6864 15.34269 14.2795 14.29758 15.06682 15.55843 14.9841 14.52794 14.38037 14.58176 15.49519 16.01623 14.98994 16.1685 17.89346 19.66196 20.41212 19.85152 \n  11.20878 14.61073 14.74267 14.05825 15.03689 14.27688 13.934 13.7751 13.63184 13.97793 14.57368 14.39714 14.21094 14.06395 14.52638 15.53573 16.57571 15.51742 17.78471 19.37989 21.206 22.15632 21.33591 \n  10.45609 14.74396 14.32149 13.18418 13.62141 14.69138 14.50593 13.22618 13.50317 13.10417 13.68227 13.81558 14.411 13.72738 14.54855 15.41036 16.20938 15.58582 17.08364 18.51379 20.73615 22.85728 22.03742 \n  9.892098 14.23401 13.93373 13.37699 13.63826 14.14518 13.86748 12.95281 12.58174 13.15587 13.58239 13.93001 14.0541 14.45245 14.81557 15.24402 15.24497 14.92806 16.91828 19.23318 21.00042 22.89181 22.22411 \n  8.341251 13.11608 13.08356 12.63929 12.80791 12.68776 12.75128 13.05065 11.75436 13.81135 13.41625 12.83436 13.37474 14.62833 15.19703 15.31099 14.71062 15.49001 16.62827 18.99271 20.98364 22.86999 22.26387 \n  9.033696 14.0476 13.55966 12.04009 12.19411 12.87305 12.72984 12.89095 12.6282 13.35929 13.01105 12.84826 12.64545 13.73565 15.17793 15.06093 14.961 14.88946 16.90281 18.75511 20.67654 22.07957 22.50922 \n  9.733017 14.11259 13.47146 12.15287 12.6395 12.34159 11.76064 12.4338 12.91527 13.87755 13.5646 12.60468 13.0273 14.35512 15.41535 15.23291 15.34092 14.8519 15.97584 18.7154 21.41322 22.42959 23.02157 \n  8.697401 12.64109 12.03506 13.12382 13.84305 11.54991 11.58626 11.05973 11.39041 14.03995 14.19523 13.01843 13.23257 14.71688 15.60102 14.75217 15.33405 14.82154 16.59491 18.86729 21.02257 22.58431 22.67589 \n  9.467981 13.12758 12.64267 12.87043 13.40577 11.28999 10.91053 11.14885 11.37754 13.09841 14.32014 13.18549 12.73418 14.28728 14.77119 14.96639 15.80654 15.12319 16.99688 18.39054 20.01874 22.73198 22.52024 \n  9.764517 13.51877 13.10358 11.6141 12.21243 11.77503 11.65425 10.68032 11.29402 14.13506 14.52542 13.75776 13.12655 14.90901 14.66903 15.17769 14.88138 14.35127 15.96097 17.97906 20.40209 22.40177 22.05331 \n  9.448538 12.1722 12.48105 11.88218 12.70931 12.26048 11.73737 10.74498 12.15391 13.1719 13.41782 12.89102 12.99866 15.54638 15.04468 15.65555 15.56007 14.52773 15.27511 18.04018 19.91089 21.79332 21.80087 \n  8.763973 11.93478 11.62999 11.1273 12.46282 11.85779 11.41145 11.12057 12.67596 13.37468 12.94005 12.73368 12.64572 15.58685 15.55944 15.38471 14.74936 14.22819 16.26686 18.11139 19.70222 21.42123 21.45517 \n  8.306178 9.252882 9.844025 11.26888 10.83866 11.36586 11.08982 10.34481 11.93284 12.10324 12.52144 12.75002 12.61329 14.85645 14.61 14.17808 15.05804 14.43231 15.56323 17.80058 18.97718 20.20973 19.62204 \n  11.66475 14.36481 14.23808 12.98364 11.47848 11.98761 11.70588 10.32386 11.46336 12.05531 11.33844 11.47684 12.1066 15.10926 14.7728 13.86291 14.54506 14.13791 14.81665 16.32619 17.66183 18.56561 18.54115 \n  13.551 15.17671 16.76833 15.87209 15.30873 11.94541 10.92486 11.23132 11.48584 13.04966 12.27409 11.97255 11.65486 14.969 14.62882 13.83866 13.70533 13.39387 13.99928 15.66928 16.7587 16.72407 16.5293 \n  12.76456 14.3368 17.05488 16.533 16.53849 12.9081 12.13053 12.54419 11.06146 11.80947 11.34655 11.66301 11.78405 14.4737 14.33242 13.79723 14.23168 13.66543 14.59762 15.88466 16.25202 16.19663 16.058 \n  12.61326 13.91244 16.62031 16.31223 16.49494 13.073 12.46359 13.13346 11.08299 12.0898 12.36925 12.15002 11.55262 14.73402 14.74845 14.4159 15.61065 14.59098 14.15156 15.8146 16.68856 15.90823 15.70445 \n  13.72736 14.60473 16.47353 16.42584 16.23803 13.49946 13.32173 13.55856 11.47504 12.57557 13.47919 12.9309 12.37103 15.21231 15.2276 15.20738 16.28225 14.82661 15.0314 16.40727 17.3156 15.99237 15.84188 \n  13.94386 14.66504 15.96983 16.09722 16.08472 13.28472 14.21239 13.74801 11.81877 13.22909 13.79301 13.41157 12.9921 15.82657 15.1773 15.28221 16.49038 15.39782 15.09806 16.5119 17.39903 16.71843 16.71772 \n  13.7535 15.06458 15.29338 15.41305 15.38942 12.72157 14.62464 13.94845 13.23048 13.06216 13.54 12.74474 13.10539 14.58909 14.21166 14.60993 15.12524 14.18825 14.24555 15.87136 16.5764 16.25047 16.18505 \n  12.87529 15.11237 17.02908 16.62773 14.56104 13.15497 14.62326 14.26014 13.4457 13.14097 14.58538 14.2613 13.35599 14.02586 13.7997 13.72621 14.95759 14.69201 13.92311 15.1955 15.75672 15.51821 15.26852 \n  14.88954 16.34912 15.96387 16.39929 15.98874 13.18963 13.59016 13.90227 13.35802 13.87966 14.67649 14.61434 13.03115 13.09564 12.67227 13.00849 14.46988 13.8509 13.29925 14.3982 14.9851 14.69154 15.44168 \n  15.86816 17.34939 15.38919 15.75551 14.90487 13.54091 13.4477 14.09079 13.59264 14.21146 13.69315 13.91447 12.34339 11.63899 11.57346 11.78274 13.74251 13.4482 12.77586 13.67141 13.67339 14.87321 15.2977 \n  16.05614 17.80696 15.5341 15.78276 14.98103 13.54131 13.31379 14.18915 14.42894 15.16783 13.61487 12.74171 12.90643 12.58465 11.50915 11.18896 13.20965 13.26229 12.49681 12.70356 12.91538 14.117 14.82414 \n  16.10782 18.11083 15.80454 15.79372 14.83904 13.20489 12.75853 14.28803 15.24095 14.56751 12.98957 12.72844 12.02183 12.00667 11.41799 10.49253 12.19255 12.55818 12.08304 12.07552 12.59875 13.70636 14.76297 \n  16.48818 18.47473 16.28432 16.31223 13.50066 12.83804 13.33812 14.4014 15.45115 14.3461 12.77997 12.5514 11.41195 11.27457 9.940119 10.18195 11.79267 12.34199 12.40519 12.08422 12.70067 13.04217 14.32282 \n  16.58727 18.6493 16.57899 16.56668 13.67641 12.70696 13.48661 14.16076 15.01744 13.59957 12.72013 12.734 11.13864 11.15946 10.10025 10.58426 12.08072 12.54692 12.42924 12.06971 13.08699 12.87339 13.88818 \n  16.46552 18.60275 16.49226 16.2148 14.75385 13.87186 13.3091 13.94653 14.61146 13.24284 12.09616 11.93655 11.40253 11.15538 10.07787 9.789737 11.60745 12.03494 11.88888 12.21645 12.83724 12.63594 13.60312 \n  16.42601 18.49523 16.10097 14.80393 15.19385 14.14109 13.04128 13.45862 14.21167 13.62841 11.52437 10.68034 10.83395 10.6881 10.08846 10.43773 10.89225 11.42747 11.60774 13.2441 13.97224 11.69935 13.44734 \n  16.38114 18.33183 15.98755 14.96587 15.34151 13.83746 12.48781 12.56362 13.59895 13.62195 11.67679 11.84699 11.38903 10.70972 10.37174 10.57339 10.79502 11.32389 11.35826 13.23451 14.09176 12.10806 13.03413 \n  16.22431 17.94065 15.84532 15.77651 16.14402 14.11528 12.80109 13.16647 14.27707 13.8602 11.68355 11.39642 10.84387 10.61396 9.958416 9.830719 10.69155 11.12258 11.26303 13.12325 13.99851 11.67061 12.9628 \n  15.79015 17.19271 15.68581 15.83383 16.8037 14.45622 12.3988 12.65228 14.56971 13.79517 10.82631 9.563471 10.30857 9.767759 10.45248 9.569944 10.59113 11.10918 11.09264 12.86746 13.68986 11.89357 12.99938 \n  15.2913 16.56188 15.66566 15.6369 15.88488 12.91912 13.74727 13.40825 14.74673 12.99693 11.53082 10.84703 10.13508 9.678087 9.518613 9.16087 10.43609 11.18994 10.68452 11.71982 12.54992 12.5922 13.53928 \n  14.92816 16.64891 16.45783 16.25064 16.19631 13.19242 13.77824 14.43863 15.26204 15.19201 12.83485 11.38921 10.91256 11.21886 10.82799 12.13972 13.95731 12.54356 12.07864 12.44756 12.12163 12.97568 14.7286 \n  15.13246 17.03524 15.97898 15.40096 15.36011 13.36627 13.54038 14.25134 15.57904 16.03234 13.77775 12.25592 10.30315 10.69148 10.83694 12.56628 14.37519 12.44555 12.39819 13.07718 11.56385 13.12282 15.2996 \n  15.5982 17.27533 16.06111 15.55091 15.21003 14.51325 13.98331 14.05154 14.17753 16.04241 15.2899 13.87621 11.14674 10.69581 11.96811 14.34262 14.9851 13.41596 13.65708 14.32451 13.39169 12.8552 14.58668 \n  14.91011 16.69463 15.57334 15.01008 15.36094 14.74225 14.26171 13.92481 13.91756 15.95652 16.69785 16.57439 12.48547 11.33714 12.08421 15.43829 15.81007 13.38737 13.30834 14.67949 14.26769 13.08782 14.67955 \n  13.62063 15.99206 15.72027 15.10223 15.1442 15.15948 14.64559 13.86851 12.91738 14.75704 17.01463 17.44593 14.92344 12.40641 12.71938 16.50565 16.63255 13.53405 12.98962 15.20941 15.12311 13.42216 15.25566 \n  15.30581 16.69621 15.66549 15.66445 16.12411 15.10698 15.31674 14.56899 12.28834 15.10705 16.23727 16.72542 15.70731 13.46484 13.77255 16.57919 16.63644 13.61368 13.20484 14.98691 15.30538 13.48375 14.71632 \n  14.74377 15.90853 16.02791 15.53424 15.54271 15.17513 15.70076 15.01335 12.41409 14.9216 15.6982 15.6553 14.80186 13.63735 14.12234 16.54076 16.64301 13.9333 13.65155 15.33424 15.71972 14.00131 14.723 \n  13.63359 14.52747 16.50115 15.59644 14.78498 14.94671 15.83353 15.04419 12.83702 15.15406 14.95185 15.14444 14.53343 14.07447 14.4541 16.43644 16.78634 13.96131 13.85571 15.59888 16.54558 14.7505 15.17269 \n  15.09095 15.96606 16.31398 15.20485 14.33777 14.76441 15.66189 15.22405 12.65838 15.33522 14.93109 15.00384 14.89501 14.88041 14.65054 16.52218 17.02337 14.22087 14.82588 15.54361 17.17436 15.60863 15.80521 \n  15.26671 15.98887 16.00072 15.11115 14.80698 14.81987 15.41057 15.06448 12.76331 14.64497 15.39146 15.59635 15.41956 14.94571 14.81527 16.34526 16.81958 14.88231 15.31733 15.54397 16.68404 16.08439 16.50137 \n  14.82031 15.1955 15.81392 14.74509 13.80763 14.37639 15.23381 14.08953 13.05277 14.46634 15.04908 15.01031 14.62417 15.87493 14.96298 16.19891 16.81858 14.21854 14.53428 15.09545 15.81948 15.23545 15.83264 \n  14.47235 14.64184 15.65243 14.61598 13.88489 14.16747 15.15573 13.50578 13.0122 14.29219 15.03921 14.0275 13.43212 15.84878 14.55854 14.92103 15.28403 13.08439 14.17978 15.17877 15.71674 13.99384 15.05782 \n  14.84271 15.37902 15.59052 14.53613 13.88661 14.49238 15.42805 13.71516 12.43119 13.77503 14.90729 14.78802 14.2214 15.8298 14.60928 14.95287 15.55999 13.44495 13.74132 15.10681 16.23884 14.13648 15.53918 \n  14.90855 15.54294 15.92132 14.83505 13.52632 14.82017 15.56321 12.84901 12.36878 12.84481 13.59268 13.83251 13.89308 14.76446 13.99949 14.81193 15.35496 13.92693 14.23314 14.60406 16.01696 13.7629 15.32229 \n  14.34874 14.65815 15.8946 14.89865 13.93546 14.51131 15.38126 12.69744 12.18602 11.85635 12.55572 13.3946 13.59089 14.50925 13.44721 14.08821 15.0949 13.18603 13.76213 14.69819 15.71466 14.58852 16.02038 \n  14.12023 14.95996 14.94988 14.08591 14.26389 15.05177 15.42382 14.23856 13.6525 13.4122 13.92378 13.58581 13.71874 15.37159 13.65612 14.78279 15.35144 12.51747 13.10743 13.96306 14.74565 13.60848 15.42061 \n  13.03794 14.3534 14.61717 14.4276 14.20311 14.88333 16.29688 13.85629 12.45 12.66146 13.211 13.02482 13.61957 15.25426 13.65302 14.40839 15.28184 12.64547 12.91868 13.65031 15.02586 13.60051 14.85588 \n  12.80224 14.75209 15.02113 14.23392 13.57626 14.24956 14.97642 13.44714 11.19146 11.87919 12.94502 13.08048 12.71222 14.35021 13.33305 13.61649 14.14324 12.44998 12.97652 14.02602 14.98486 13.33818 14.75948 \n  13.16971 14.54832 13.68839 12.53332 12.31186 13.85297 14.5408 12.63638 10.70129 10.50308 11.22596 12.15875 12.87752 14.50729 13.75705 13.03189 14.20643 12.62912 13.04198 13.98892 14.39815 13.00242 14.93295 \n  12.32784 14.45602 13.87575 12.9689 12.90031 12.28457 12.79731 12.50595 11.64002 10.49457 12.00499 11.84997 12.20587 13.69985 12.74907 13.07555 13.99215 12.42866 12.85618 13.70903 14.67477 12.98654 15.42268 \n  13.97398 15.76731 14.26718 13.93614 13.3635 12.53315 12.47679 12.46972 10.95234 10.91325 11.5195 11.66877 12.05166 13.99423 12.40961 12.80348 13.87326 12.39891 12.30221 12.87925 14.37371 12.68297 14.16082 \n  14.184 16.03344 14.21303 12.96472 13.494 13.50742 12.40183 12.13428 11.0977 10.09598 11.73288 11.88649 11.97245 12.51878 11.91088 12.78705 13.84648 12.43722 11.65642 12.11694 12.9002 12.40637 14.5552 \n  13.45738 15.55 14.00745 12.82178 12.33664 11.91138 12.54709 12.3248 11.18794 10.89101 11.58366 11.65439 12.35607 12.53853 11.86051 12.31624 13.99491 12.18095 11.57812 11.95029 13.21074 12.14984 13.58227 \n  12.75044 14.95871 13.36009 13.20988 12.31619 11.93608 11.93395 12.31846 11.38457 11.1864 11.68532 11.97781 12.34169 12.93438 11.78984 12.08069 13.22225 11.86906 11.43046 11.13731 12.37698 12.51735 13.13258 \n  12.4284 14.15335 13.07597 11.76668 11.4075 11.61571 12.59232 11.93633 12.10711 12.10692 12.07862 13.06988 12.64771 14.07678 12.7958 11.8246 12.44421 11.69291 11.27304 11.0924 11.61102 12.44975 12.95033 \n  11.18342 11.99406 12.91778 11.29505 11.66648 10.58673 12.03916 12.36362 11.94302 11.53715 12.30084 12.70467 12.66107 14.14579 13.0996 11.72703 12.5057 11.78472 11.09719 10.43786 12.19886 12.96147 12.51465 \n  11.16282 12.16246 10.93769 9.637576 10.93914 11.07357 12.48322 11.72473 10.95556 11.30609 12.062 12.24674 12.28014 13.23953 12.19423 12.05279 12.69395 11.68082 11.26663 10.09986 10.75675 11.19461 11.49739 \n  10.68674 13.24407 11.97083 9.004447 9.364768 10.10863 12.20102 11.69279 10.02772 10.04208 11.35098 11.3541 12.00796 12.02115 10.81907 10.48873 11.81506 11.11288 11.23438 10.76176 10.97295 11.27559 11.05051 \n  11.25764 13.04875 10.96754 9.594095 9.950509 9.515109 10.90454 10.44351 10.30407 10.58162 11.61821 10.79663 11.97438 12.49545 10.3045 10.45207 10.77822 10.23204 10.59221 10.55611 10.73 11.25474 10.92693 \n  10.77957 12.84101 10.96046 9.825205 9.921305 10.27295 11.00374 9.069146 9.143576 9.619534 9.886018 9.683996 11.43353 11.68437 10.21345 9.418591 10.17027 9.919155 9.729475 10.12781 10.13701 10.20216 10.49461 \n  10.50037 12.81704 10.93899 8.919902 9.181169 9.454815 9.864502 9.160638 7.950092 8.281847 9.608268 9.700049 10.10044 10.43497 10.07498 9.374721 10.09255 9.838331 9.777655 9.972161 10.5668 10.3991 10.44382 \n  10.9499 12.69608 10.32951 8.873781 9.134046 8.758868 9.037214 8.199131 7.569058 8.374478 9.34644 9.717125 9.732412 10.43906 8.821301 8.579359 9.148021 9.602486 9.728423 9.711402 10.63859 10.64856 10.91956 \n  11.27755 12.95559 10.74122 9.436187 9.256186 9.484769 9.586822 8.388662 7.160058 8.068262 9.397726 9.698923 10.2531 10.30162 9.136081 8.90623 9.838286 9.443312 9.586123 9.845777 10.52771 11.16902 11.16297 \n  10.61487 12.45117 10.35181 8.28381 7.78183 7.990805 8.725731 8.746444 7.518696 7.472842 8.455659 9.625546 9.859873 9.179219 8.927357 9.205382 9.615867 10.14538 10.18613 10.31581 10.64848 10.60155 10.51831 \n  9.637716 11.20578 9.314525 7.651236 7.868614 8.413736 9.356231 8.070017 8.155 7.390232 8.749864 9.116447 9.567814 9.369207 9.694729 9.147233 9.482315 9.444982 9.887435 9.599484 9.862085 10.45017 10.60415 \n  8.626204 9.187364 9.029099 8.493851 7.209723 7.690259 8.042856 7.316092 8.150468 8.128954 8.491919 8.446475 8.681947 8.747696 8.789898 9.233255 10.31805 9.660691 9.486577 10.23518 9.970778 9.988548 10.34961 \n  9.442098 8.689657 9.283001 7.998808 6.22693 6.962261 9.189577 8.19746 7.75057 8.493724 8.455694 7.799927 8.001998 8.729837 9.923102 9.574437 9.835016 9.547566 9.595923 10.27687 9.859653 10.14931 10.31981 \n  9.97291 9.826776 8.408665 7.496465 8.021371 7.480401 6.859789 7.656764 8.673873 8.172565 8.807829 9.007799 9.039057 8.638908 9.110216 9.078871 9.454023 9.512172 9.644451 9.953197 10.47481 10.57586 11.22771 \n  7.733074 9.88445 8.777633 8.313414 8.081938 7.271777 8.92068 8.634503 8.78035 8.908507 9.615075 9.58618 10.19903 9.804263 9.953383 9.936666 10.38816 9.741985 10.35782 10.95726 11.52999 11.21175 11.48313 \n  10.96227 9.154578 8.698281 7.998504 7.728884 6.602579 8.022117 8.025263 9.123106 8.844633 8.908731 10.21477 9.655914 9.417415 9.496919 9.789172 10.42569 10.3659 11.02518 10.92264 11.54033 11.66203 11.41841 \n  10.86337 9.16935 9.55076 7.872849 7.942523 7.244263 7.779666 7.115378 7.89739 8.183571 8.867866 9.697963 9.289954 9.11062 9.085766 9.426685 9.012211 9.846148 10.90698 10.7715 10.9265 11.21198 11.22182 \n  9.851903 10.36412 8.908376 7.846486 7.46843 7.405447 7.65377 8.196727 7.064144 8.249885 8.761197 8.942713 9.204334 8.628345 8.864152 9.710718 9.490798 9.545791 10.44929 10.69282 10.93337 10.86275 10.97815 \n  11.25423 10.87261 8.889456 7.461558 7.015344 7.351716 8.382879 8.503271 7.68911 7.91639 8.643186 8.87805 9.065163 9.099637 9.386837 9.786633 10.39724 10.21951 10.45584 10.46524 10.56583 10.76281 10.16936 \n  10.68273 9.817769 8.26171 8.016673 8.054502 7.516357 7.65291 7.820787 7.519141 7.720293 7.444949 8.414156 9.215623 8.999539 9.341202 10.16718 9.897247 10.21318 10.05819 10.82438 10.51383 10.53982 10.3831 \n  9.478124 9.167519 9.010949 7.99378 7.74503 6.204545 7.584774 7.112559 7.285814 7.478474 7.668393 7.974492 8.957026 8.854042 8.923244 10.00307 9.395614 9.709485 9.681889 10.5162 10.42807 10.61794 10.64966 \n  10.47888 7.862177 7.167226 8.245425 7.75247 7.6353 7.317435 8.184895 7.887283 7.203204 8.485103 8.665626 8.602202 8.789666 8.851316 9.74954 9.710799 9.547979 9.842075 10.54527 10.60706 10.56509 10.56258 \n  9.801606 8.885911 7.033187 7.478241 6.67696 7.042121 7.39953 7.7513 7.696868 7.563337 8.205177 8.162902 8.607606 8.607259 8.436271 9.256256 9.444992 9.138235 9.183046 10.3544 10.70144 10.78459 10.73416 \n  8.729084 9.680941 8.473826 7.128935 7.117252 7.535285 7.976354 8.395122 7.388021 7.665706 7.663038 7.935491 7.918374 8.014401 9.072487 9.747068 9.442183 10.02906 9.621786 10.21271 10.62509 10.38278 10.59681 \n  9.071483 8.072448 8.148285 8.208888 6.865083 7.357923 7.7726 7.642717 7.373379 7.314355 6.811155 8.184822 8.202291 9.007961 8.424119 9.344726 9.500482 9.494846 9.845454 10.21647 10.59387 10.59069 10.30458 \n  9.551182 8.782715 9.017637 8.455041 7.292755 6.371716 8.139261 7.807406 6.868361 7.754928 8.373298 7.639658 8.648994 8.402566 9.127618 9.492344 9.512679 9.582137 10.01061 10.36339 10.5303 10.40906 10.77627 \n  10.07956 9.123581 9.239129 7.188252 7.983877 7.36659 7.689083 7.349831 6.549315 7.351971 7.765708 8.071753 8.22062 8.234403 9.252606 9.165942 9.141379 9.528788 10.10328 10.09754 10.46661 10.03632 10.45256 \n  10.45638 9.177458 8.172346 6.487576 7.374524 7.649885 7.573339 6.959404 7.260113 6.734559 7.447418 8.466086 8.382314 8.260194 8.807273 9.042309 9.807338 9.552331 9.757251 10.22166 10.39291 10.50788 10.47725 \n  11.13613 7.758188 7.694408 7.91339 6.591579 7.690708 7.883243 6.817697 6.937893 6.617546 7.995504 8.199288 8.606889 7.930028 8.27558 9.028001 9.202659 9.807508 10.00867 10.30622 10.30117 10.22799 10.23392 \n  10.84375 8.658377 8.964039 7.577753 5.997756 6.243629 6.59042 7.667848 7.77693 7.160565 7.672915 8.214157 7.767068 8.187228 8.741798 9.008192 8.761507 9.775722 9.991219 10.50324 10.35022 10.56752 10.42405 \n  9.856415 8.33345 7.864082 7.394323 7.037837 7.429994 7.053414 8.148975 7.734139 7.73136 8.126728 8.250671 8.107525 8.775521 8.947971 9.013912 8.709566 9.952392 10.0177 10.55204 10.14417 10.48263 10.89007 \n  11.22424 8.785028 8.384821 6.571542 6.668182 6.510378 7.012306 7.705905 6.736544 7.154219 8.193804 7.920104 8.426934 8.557131 8.854219 9.46376 10.04807 9.964184 9.701237 9.969363 10.31233 9.983346 10.42036 \n  11.32489 8.361799 9.032561 7.834023 7.204043 6.074617 7.471241 8.117975 7.885279 7.726513 8.305443 8.50788 8.930935 8.875918 8.786529 9.071368 10.33387 9.977633 10.02416 10.06347 10.81268 11.20751 10.80103 \n  10.06941 6.52937 7.571665 6.465108 6.881132 6.903685 7.100048 7.664837 8.100976 8.205462 8.043177 8.448032 8.847051 8.371434 9.149493 9.756526 10.0323 9.265886 10.12252 10.04926 10.18163 10.70782 10.76523 \n  10.31685 7.024517 5.869543 5.841137 6.383105 6.215681 7.949264 7.746029 7.835628 7.861153 8.296052 8.204115 8.655869 8.276096 8.929706 8.994547 9.447945 9.700706 10.37251 10.27933 10.33522 10.72122 10.48557 \n  10.91509 7.91675 8.244367 6.124669 6.732698 7.492036 8.363312 8.124249 8.108838 7.358902 8.053522 7.411808 8.716305 8.342316 8.457804 9.005593 9.336573 10.05767 9.578779 10.344 10.4169 10.55184 10.60104 \n  10.32075 8.261191 8.136519 6.961864 6.799195 7.198459 7.713956 6.972926 6.764237 7.75519 7.804876 7.912869 8.563591 8.987835 9.309792 9.610885 9.492855 9.925476 10.05713 10.52021 10.62411 10.47692 10.59566 \n  9.86818 8.572285 8.530177 7.359343 7.294422 6.582515 6.642591 7.496963 7.95584 7.202435 7.878167 8.503516 8.365258 9.081302 8.992274 9.197975 9.750833 9.722472 9.760623 9.966175 10.59453 10.34588 10.6256 \n  10.25583 7.347171 7.843901 6.244213 6.5353 6.617674 7.064937 7.198507 6.530531 7.619411 7.706642 8.672579 8.665023 9.01842 9.258142 9.454097 9.65053 9.569846 10.16275 10.25629 10.61747 10.79843 11.0936 \n  11.3455 8.169881 7.368921 6.081739 7.016907 7.807951 8.699952 7.736558 6.748681 7.378449 7.852139 8.727378 9.049452 8.352005 9.397895 9.694369 9.896957 9.87398 9.838742 10.29402 10.58788 9.819412 10.6098 \n  11.90842 7.299352 8.247597 6.929464 5.668571 7.252095 8.041783 7.685021 7.479499 7.446598 7.486227 8.122455 8.321239 8.863303 8.986836 9.896532 10.01282 9.700945 10.13044 10.36466 10.79011 10.65473 10.96276 \n  11.22572 8.534163 7.996068 7.321532 6.95424 7.306089 8.242614 7.205853 7.210618 7.631306 8.128415 8.210221 7.745347 8.572201 9.164312 9.454391 9.143291 9.996038 9.919705 10.61216 10.94615 11.0497 10.50996 \n  11.99271 8.205185 9.120809 8.732939 7.727026 7.459247 9.017488 8.611053 9.431357 8.641321 9.48832 9.588237 9.180689 8.96218 9.460557 9.78753 10.30156 10.65017 10.35131 10.94515 12.2452 13.12846 12.19351 \n  11.79253 9.627811 9.291315 7.524522 6.52378 7.294258 8.705289 7.135509 8.226054 8.742827 9.064022 9.066143 8.709431 8.971881 9.728841 9.269897 9.861171 10.09128 10.07978 10.35271 10.13663 11.0843 11.13849 \n  10.56259 9.232968 9.15976 6.620336 6.150416 6.181613 7.583303 6.586105 7.54056 7.118359 8.163677 8.156444 8.354664 8.431437 9.365588 9.699803 9.425529 9.986162 10.02214 9.757886 9.986296 10.37123 11.12805 \n  11.46303 8.064131 8.81135 8.263533 7.772588 6.787446 7.045297 7.507244 7.852684 7.8141 8.464418 8.278731 8.368163 9.374079 9.125239 9.165322 8.79129 9.501587 10.15753 9.792738 10.41069 10.7875 10.81474 \n  11.05755 8.402949 8.103877 8.311771 7.382164 7.518039 8.082945 8.166703 8.587493 8.333583 7.051155 8.128522 9.163286 9.241158 9.282046 9.011143 9.606009 9.214875 9.92196 10.35358 10.19762 11.04288 11.07783 \n  9.634427 8.981845 9.008856 8.496973 8.026294 6.744306 7.501451 7.233029 7.99301 7.752292 7.717514 8.286538 9.62907 9.19305 8.897845 9.250588 9.401032 9.651338 10.04432 10.55263 10.60681 10.55907 10.44911 \n  9.16023 9.718575 9.712869 9.499995 9.118845 7.099794 7.596916 7.821012 7.377513 7.772183 8.825283 8.444467 8.374529 8.278049 8.336656 9.146471 9.616967 9.900914 9.985411 10.23762 10.56904 10.3051 10.82687 \n  10.26259 9.707577 7.891645 7.938838 8.196815 7.030812 7.729892 8.539984 7.097323 7.639617 8.26931 8.103879 8.820785 8.756143 8.088627 7.633537 8.861978 9.411267 9.507934 9.617286 10.103 10.32123 10.60248 \n  9.416736 8.067968 8.121611 8.702229 8.153371 7.398215 8.101689 7.075943 7.48716 7.682926 7.930077 7.562144 7.981254 8.482229 8.007603 8.850947 9.587449 9.971848 10.00796 10.0423 10.69032 11.02298 10.9979 \n  9.875791 9.180859 8.33131 7.329909 7.138772 6.531456 7.820087 7.730562 7.006549 7.355982 8.221857 7.397998 8.619684 9.434539 8.325085 8.88515 9.217641 10.11225 10.50192 10.39947 10.4549 10.84156 10.37869 \n  10.21343 8.826467 8.089176 7.33913 7.855656 7.318372 7.243741 7.606412 7.226522 7.431902 7.899468 8.143455 8.827127 9.14143 8.887341 8.847593 9.56572 9.84055 9.684552 9.931477 10.32066 10.90385 10.82047 \n  8.685722 8.634503 8.177417 7.393768 7.107471 7.263133 7.5967 7.938039 6.885909 7.359814 8.428015 8.861872 8.920212 7.885601 8.544594 9.326226 9.538568 9.941797 10.37305 10.73129 10.24279 10.99198 10.71185 \n  9.49738 9.815642 8.553341 7.461448 7.640052 7.98072 7.311526 8.038465 7.255682 6.560006 7.371539 7.967708 8.035154 7.652845 8.489419 9.47836 9.636602 9.799182 10.27001 10.54407 10.1862 10.5361 11.08353 \n  9.237267 8.263541 7.987866 7.640958 7.269582 6.937474 6.849837 7.717149 7.656352 7.173209 7.225511 7.958437 8.102967 8.547636 8.357112 8.845057 9.423195 9.327521 10.10193 10.10455 10.16159 10.10588 10.53935 \n  8.52638 7.134833 7.512567 7.138206 6.746409 7.367229 7.365469 6.383105 7.514528 7.68226 8.600569 8.164186 8.062187 8.582131 9.225581 9.787975 9.365478 9.480648 9.960615 9.841322 9.842931 10.30676 10.41945 \n  9.151896 6.975066 6.058979 7.529419 6.584132 6.413368 7.757835 7.395633 7.860129 7.49466 8.109066 7.873742 8.698033 9.225484 9.379223 9.214903 9.393662 9.46548 9.963161 10.11975 10.1148 10.09052 10.40652 \n  9.582273 6.791395 7.215298 7.381511 7.378876 7.854954 7.890674 7.242115 7.359837 7.425533 8.024413 7.492979 8.248519 8.686938 8.807583 9.178555 9.128061 9.372928 9.666212 9.78712 9.796471 10.31979 10.85505 ]\n"
  },
  {
    "path": "audio/tests/features/testdata/pitch_feat_txt.ark",
    "content": "test_wav  [\n  0.4300044 238.1164 \n  0.7310953 238.1164 \n  0.0589752 238.1164 \n  0.3706925 238.1164 \n  0.6353879 238.1164 \n  0.4168843 238.1164 \n  0.7615743 238.1164 \n  0.7359886 238.1164 \n  0.5104555 238.1164 \n  0.843815 238.1164 \n  0.574707 238.1164 \n  0.8757079 238.1164 \n  0.8545787 238.1164 \n  0.5284878 238.1164 \n  0.8398617 238.1164 \n  0.8405749 238.1164 \n  0.7291093 238.1164 \n  0.3530312 238.1164 \n  0.8516902 238.1164 \n  0.8366287 238.1164 \n  0.7860549 238.1164 \n  0.7996263 238.1164 \n  0.8769377 238.1164 \n  0.8062987 238.1164 \n  0.5502667 238.1164 \n  0.8050084 236.9318 \n  0.8435217 235.753 \n  0.6781067 234.5801 \n  0.6275977 233.4131 \n  0.8354951 232.2518 \n  0.7898548 231.0963 \n  0.6786529 229.9466 \n  0.5784115 228.8026 \n  0.8078744 227.6642 \n  0.7860623 226.5316 \n  0.3529067 225.4046 \n  0.7398534 224.2832 \n  0.7554479 223.1673 \n  0.3688865 222.057 \n  0.431939 220.9523 \n  -0.2559481 219.853 \n  0.5161331 218.7592 \n  0.736354 217.6709 \n  0.2649688 216.5879 \n  0.6187224 215.5104 \n  0.8040497 214.4382 \n  0.4176693 213.3714 \n  0.7362868 212.3098 \n  0.6412426 211.2535 \n  0.01994592 210.2025 \n  -0.09901931 209.1568 \n  0.4139394 208.1162 \n  0.7458671 207.0808 \n  0.7015585 206.0505 \n  0.8989595 206.0505 \n  0.9356874 209.1568 \n  0.9370709 212.3098 \n  0.9640602 216.5879 \n  0.9851464 217.6709 \n  0.9874667 217.6709 \n  0.9662011 215.5104 \n  0.9561557 211.2535 \n  0.9835509 209.1568 \n  0.9764188 209.1568 \n  0.8779365 208.1162 \n  0.8911879 207.0808 \n  0.8716732 205.0254 \n  0.8663442 197.9909 \n  0.9105747 191.1978 \n  0.9614732 191.1978 \n  0.9704162 187.4211 \n  0.9690547 186.4887 \n  0.9596871 187.4211 \n  0.9392474 190.2465 \n  0.8951484 192.1537 \n  0.8852764 190.2465 \n  0.9345272 185.5609 \n  0.9304817 182.8051 \n  0.9600235 180.0902 \n  0.9829449 178.3027 \n  0.9876611 178.3027 \n  0.9889374 178.3027 \n  0.9911457 178.3027 \n  0.9835688 176.533 \n  0.9755108 175.6547 \n  0.9868198 174.7808 \n  0.9932452 175.6547 \n  0.9902206 175.6547 \n  0.9920143 176.533 \n  0.9922135 175.6547 \n  0.9892406 174.7808 \n  0.9888865 172.185 \n  0.9796383 172.185 \n  0.9825094 170.476 \n  0.9640273 170.476 \n  0.9416605 173.046 \n  0.9690976 173.9112 \n  0.9527848 173.9112 \n  0.8625391 173.046 \n  0.8571138 173.9112 \n  0.826855 174.7808 \n  0.8046249 176.533 \n  0.6064064 178.3027 \n  0.4831207 180.9906 \n  0.4654697 183.7191 \n  0.6392145 186.4887 \n  0.6342434 190.2465 \n  0.8626602 194.0801 \n  0.953752 194.0801 \n  0.987371 191.1978 \n  0.9915444 188.3582 \n  0.9920763 186.4887 \n  0.9898383 184.6377 \n  0.9908906 181.8956 \n  0.9892344 180.9906 \n  0.9779232 179.1942 \n  0.962887 175.6547 \n  0.9623674 170.476 \n  0.9719465 171.3284 \n  0.9843823 173.046 \n  0.9776363 173.9112 \n  0.9711902 173.9112 \n  0.9477384 172.185 \n  0.9629893 172.185 \n  0.9716213 173.9112 \n  0.9675733 176.533 \n  0.9643332 178.3027 \n  0.9592766 180.0902 \n  0.8798139 181.8956 \n  0.7133937 185.5609 \n  0.558998 190.2465 \n  0.3460312 196.0257 \n  0.645723 201.9805 \n  0.538826 208.1162 \n  0.6076745 216.5879 \n  0.5921855 228.8026 \n  0.8826846 238.1164 \n  0.9501736 242.9146 \n  0.9898381 245.3498 \n  0.9941772 245.3498 \n  0.9901065 246.5766 \n  0.9880084 247.8095 \n  0.9941741 249.0485 \n  0.9959649 249.0485 \n  0.9930359 250.2938 \n  0.9856881 252.8029 \n  0.9906433 252.8029 \n  0.9973371 252.8029 \n  0.9980655 252.8029 \n  0.9958057 251.5452 \n  0.9909865 250.2938 \n  0.990723 249.0485 \n  0.987911 249.0485 \n  0.9759061 251.5452 \n  0.9722236 251.5452 \n  0.9578422 251.5452 \n  0.936386 250.2938 \n  0.9094891 245.3498 \n  0.8420637 235.753 \n  0.6358631 218.7592 \n  0.757064 198.9809 \n  0.8944787 192.1537 \n  0.9415626 188.3582 \n  0.9400396 183.7191 \n  0.9019431 180.9906 \n  0.904547 175.6547 \n  0.8742625 173.046 \n  0.7475201 169.6279 \n  0.5156456 164.6269 \n  0.4781345 161.3751 \n  0.4000205 149.7427 \n  0.4614965 147.5188 \n  0.4422437 141.7487 \n  0.3527509 136.2042 \n  0.191848 130.2255 \n  0.3072545 128.2915 \n  0.5506754 127.0181 \n  0.6923887 129.5776 \n  0.6101584 132.8496 \n  0.3040284 138.2575 \n  0.1897903 155.8383 \n  0.4685728 164.6269 \n  0.5444003 164.6269 \n  0.5138596 162.9929 \n  0.5802024 160.5723 \n  0.2090085 160.5723 \n  0.2416739 162.9929 \n  0.2459603 168.784 \n  0.6345571 176.533 \n  0.5914032 184.6377 \n  0.4447052 193.1145 \n  0.2762254 201.9805 \n  0.2842087 212.3098 \n  -0.1974148 224.2832 \n  0.5095772 238.1164 \n  0.7442543 252.8029 \n  0.8915138 252.8029 \n  0.9569594 247.8095 \n  0.9625007 242.9146 \n  0.9194686 235.753 \n  0.8994824 227.6642 \n  0.9381443 218.7592 \n  0.7226841 219.853 \n  0.6949252 223.1673 \n  0.6777956 222.057 \n  0.7978759 214.4382 \n  0.8507771 209.1568 \n  0.7713854 211.2535 \n  0.6789038 211.2535 \n  0.7500904 206.0505 \n  0.7494768 204.0054 \n  0.7971382 206.0505 \n  0.8222839 206.0505 \n  0.7602305 200.9756 \n  0.6428912 197.0059 \n  0.6536841 193.1145 \n  0.7034875 188.3582 \n  0.5804744 181.8956 \n  0.4417492 173.046 \n  0.3494109 161.3751 \n  0.1981726 148.2564 \n  0.6261529 140.3417 \n  0.7587391 136.8852 \n  0.3861219 134.8523 \n  0.2585415 138.2575 \n  0.4469885 141.7487 \n  0.7737626 140.3417 \n  0.7246874 138.2575 \n  0.6511324 136.8852 \n  0.4254677 136.8852 \n  0.1780608 141.7487 \n  0.4341104 146.7849 \n  0.2834992 149.7427 \n  0.4845652 151.2439 \n  0.4879717 151.2439 \n  0.5601908 152.0001 \n  0.7019184 152.0001 \n  0.8482625 152.0001 \n  0.8672082 152.0001 \n  0.8626106 151.2439 \n  0.8626055 149.7427 \n  0.9013379 148.2564 \n  0.8793075 146.7849 \n  0.8914734 144.605 \n  0.8311929 141.7487 \n  0.6839114 139.6435 \n  0.5378032 136.8852 \n  0.3579432 131.531 \n  0.3721773 123.8897 \n  0.259927 118.4515 \n  0.4204291 116.1118 \n  0.7305987 117.2759 \n  0.6386622 122.6601 \n  0.4521356 127.0181 \n  0.1688575 132.1886 \n  0.2404094 136.8852 \n  0.161655 139.6435 \n  0.361738 140.3417 \n  -0.02500387 138.2575 \n  0.4358978 136.2042 \n  0.4791997 134.8523 \n  0.5491226 134.1814 \n  0.6218376 133.5138 \n  0.566164 133.5138 \n  0.6004029 134.1814 \n  0.4282176 134.8523 \n  0.2462277 135.5266 \n  0.468562 136.8852 \n  0.1709644 137.5696 \n  -0.1866998 138.2575 \n  -0.2322609 138.9488 \n  -0.3413201 138.9488 \n  -0.5628413 138.9488 \n  -0.3278477 138.2575 \n  -0.1193225 138.9488 \n  0.04384596 140.3417 \n  0.04935479 142.4574 \n  0.1841608 144.605 \n  0.5726393 147.5188 \n  0.6960948 151.2439 \n  0.7003101 153.5239 \n  0.7147154 155.8383 \n  0.7900128 158.9785 \n  0.7915136 160.5723 \n  0.8635668 162.9929 \n  0.9153162 167.1087 \n  0.9632365 168.784 \n  0.9837555 173.046 \n  0.9895447 174.7808 \n  0.9936979 178.3027 \n  0.9939244 180.0902 \n  0.9943298 180.9906 \n  0.9935455 183.7191 \n  0.9959602 184.6377 \n  0.9956325 184.6377 \n  0.9592334 185.5609 \n  0.8768551 189.3 \n  0.7307228 193.1145 \n  0.511133 192.1537 \n  0.6857247 188.3582 \n  0.9158598 184.6377 \n  0.9108561 186.4887 \n  0.9116812 187.4211 \n  0.9223366 187.4211 \n  0.8974369 188.3582 \n  0.8092315 189.3 \n  0.6424754 190.2465 \n  0.415496 193.1145 \n  -0.09486372 194.0801 \n  0.06201403 196.0257 \n  0.7022306 199.9758 \n  0.8596367 206.0505 \n  0.8891434 212.3098 \n  0.8837855 220.9523 \n  0.7532349 229.9466 \n  0.8273478 235.753 \n  0.8926229 240.5036 \n  0.9618158 242.9146 \n  0.9802947 242.9146 \n  0.9757999 241.7061 \n  0.9556377 236.9318 \n  0.9495205 228.8026 \n  0.8714783 222.057 \n  0.6913882 217.6709 \n  0.5996734 214.4382 \n  0.5818065 196.0257 \n  0.7346321 182.8051 \n  0.8720678 184.6377 \n  0.8043494 181.8956 \n  0.7913815 184.6377 \n  0.8019897 179.1942 \n  0.8272967 177.4156 \n  0.917188 173.9112 \n  0.948779 178.3027 \n  0.9491397 179.1942 \n  0.9660939 181.8956 \n  0.948925 181.8956 \n  0.9438759 183.7191 \n  0.9082419 182.8051 \n  0.8157918 182.8051 \n  0.7726267 183.7191 \n  0.7925529 184.6377 \n  0.82323 185.5609 \n  0.7710455 186.4887 \n  0.7245523 187.4211 \n  0.6725792 188.3582 \n  0.6098945 190.2465 \n  0.6053364 192.1537 \n  0.5669799 194.0801 \n  0.6425812 196.0257 \n  0.5920788 198.9809 \n  0.5982969 201.9805 \n  0.5845767 206.0505 \n  0.8673239 210.2025 \n  0.8958703 213.3714 \n  0.9322492 215.5104 \n  0.9763456 216.5879 \n  0.9871499 217.6709 \n  0.9847117 216.5879 \n  0.9803717 215.5104 \n  0.9864718 214.4382 \n  0.9891353 213.3714 \n  0.9886542 212.3098 \n  0.9887235 211.2535 \n  0.9895412 211.2535 \n  0.987739 210.2025 \n  0.9813522 211.2535 \n  0.979372 210.2025 \n  0.9715059 211.2535 \n  0.9659958 212.3098 \n  0.9582934 213.3714 \n  0.9457313 214.4382 \n  0.9001306 214.4382 \n  0.8375491 214.4382 \n  0.8580287 213.3714 \n  0.8090529 212.3098 \n  0.7204515 211.2535 \n  0.727868 211.2535 \n  0.8134795 211.2535 \n  0.7847017 212.3098 \n  0.855688 212.3098 \n  0.9308017 212.3098 \n  0.8832355 211.2535 \n  0.7976366 210.2025 \n  0.6125828 208.1162 \n  0.7335693 206.0505 \n  0.5974885 204.0054 \n  0.5784881 201.9805 \n  0.626056 199.9758 \n  0.3227086 197.9909 \n  0.4882276 196.0257 \n  0.5797763 194.0801 \n  0.6834005 191.1978 \n  0.8976591 190.2465 \n  0.9618267 188.3582 \n  0.9768698 185.5609 \n  0.9630268 181.8956 \n  0.951674 178.3027 \n  0.9476838 173.9112 \n  0.9517156 172.185 \n  0.9504529 169.6279 \n  0.9870636 169.6279 \n  0.9741296 168.784 \n  0.9508372 168.784 \n  0.90883 165.4501 \n  0.8581914 161.3751 \n  0.8267851 156.6175 \n  0.6312259 150.4914 \n  0.546525 146.7849 \n  0.5260749 146.7849 \n  0.4342186 153.5239 \n  0.492891 160.5723 \n  0.6401276 166.2773 \n  0.7607003 168.784 \n  0.8006893 169.6279 \n  0.754485 169.6279 \n  0.3563844 168.784 \n  0.2301813 168.784 \n  0.5213931 168.784 \n  0.4302804 169.6279 \n  0.203999 170.476 \n  0.5803608 172.185 \n  0.799207 173.9112 \n  0.7838959 175.6547 \n  0.6272278 177.4156 \n  0.5649745 179.1942 \n  0.1334038 180.9906 \n  0.4665532 182.8051 \n  0.7017906 184.6377 \n  0.574991 186.4887 \n  0.1776394 188.3582 \n  0.7058933 190.2465 \n  0.7285945 192.1537 \n  0.5696192 194.0801 \n  0.5714518 196.0257 \n  0.8047431 198.9809 \n  0.7406042 200.9756 \n  0.3201705 202.9904 \n  0.7420282 205.0254 \n  0.8154832 207.0808 \n  0.7317356 209.1568 \n  0.3067544 211.2535 \n  0.8014479 213.3714 \n  0.8102676 215.5104 \n  0.4439816 217.6709 \n  0.8234195 219.853 \n  0.7885534 222.057 \n  0.4245847 224.2832 \n  0.00418177 226.5316 \n  0.3035149 228.8026 \n  0.6538261 231.0963 \n  0.847946 233.4131 \n  0.6219971 235.753 \n  0.858582 236.9318 \n  0.8284138 239.307 \n  0.4044586 240.5036 \n  0.7807371 241.7061 \n  0.6421613 242.9146 \n  0.4366452 244.1292 \n  0.8172922 245.3498 \n  0.7077252 246.5766 \n  0.7137164 247.8095 \n  0.8416377 249.0485 \n  0.8084357 250.2938 \n  0.6429872 251.5452 \n  0.8479958 252.8029 \n  0.8376269 254.067 \n  0.5148344 255.3373 \n  0.8253111 256.614 \n  0.792549 257.8971 \n  0.7535735 259.1866 \n  0.08307214 260.4825 \n  0.7227954 261.7849 \n  0.7564813 264.4093 \n  0.4621202 265.7313 \n  0.4633192 267.06 \n  0.7247673 268.3953 \n  0.7581604 269.7372 \n  0.5511292 271.0859 \n  0.9282034 272.4414 \n  0.9706463 271.0859 \n  0.9854098 273.8036 \n  0.9971125 273.8036 \n  0.9954729 272.4414 \n  0.9888761 269.7372 \n  0.9950762 267.06 \n  0.9968371 269.7372 \n  0.9980098 269.7372 \n  0.997749 268.3953 \n  0.9915248 265.7313 \n  0.9653835 259.1866 \n  0.9663866 256.614 \n  0.9707376 259.1866 \n  0.9852746 263.0938 \n  0.982106 265.7313 \n  0.9469596 267.06 \n  0.9675582 264.4093 \n  0.9636477 261.7849 \n  0.9427549 257.8971 \n  0.7895892 251.5452 \n  0.8654758 245.3498 \n  0.5468963 235.753 \n  0.683558 220.9523 \n  0.8124123 211.2535 \n  0.9160304 205.0254 \n  0.9279389 197.0059 \n  0.9523526 191.1978 \n  0.9704132 186.4887 \n  0.9692958 185.5609 \n  0.9680378 184.6377 \n  0.9765167 184.6377 \n  0.9860514 182.8051 \n  0.9883636 182.8051 \n  0.9909548 181.8956 \n  0.991558 183.7191 \n  0.9909708 185.5609 \n  0.9903755 187.4211 \n  0.9908676 189.3 \n  0.9932029 191.1978 \n  0.9957952 191.1978 \n  0.9942914 191.1978 \n  0.9921359 189.3 \n  0.9943052 187.4211 \n  0.9959483 186.4887 \n  0.995445 188.3582 \n  0.9905357 190.2465 \n  0.9810765 189.3 \n  0.9172173 189.3 \n  0.8372061 189.3 \n  0.7548154 189.3 \n  0.7888815 189.3 \n  0.7481033 187.4211 \n  0.598231 181.8956 \n  0.4594265 180.9906 \n  0.3907863 181.8956 \n  0.3352165 180.9906 \n  0.1176405 178.3027 \n  0.07078327 173.046 \n  -0.04527154 169.6279 \n  -0.1348021 168.784 \n  0.04466751 167.1087 \n  0.09953013 164.6269 \n  0.0682964 162.182 \n  0.06978174 163.8079 \n  0.1322864 165.4501 \n  0.2013361 169.6279 \n  0.2920707 174.7808 \n  0.3333177 176.533 \n  0.3332107 176.533 \n  0.3530797 177.4156 \n  0.4650808 179.1942 \n  0.5486825 180.9906 \n  0.4580497 182.8051 \n  0.4908407 184.6377 \n  0.4697383 186.4887 \n  0.3304503 188.3582 \n  0.3914385 190.2465 \n  0.6257187 192.1537 \n  0.3618582 195.0505 \n  0.1043633 197.9909 \n  0.3943349 200.9756 \n  0.5306126 204.0054 \n  0.1373097 207.0808 \n  0.2010625 210.2025 \n  0.3670651 213.3714 \n  0.3145425 216.5879 \n  0.8130425 219.853 \n  0.8798357 222.057 \n  0.9403205 223.1673 \n  0.97297 224.2832 \n  0.9836287 223.1673 \n  0.9911686 222.057 \n  0.9915301 220.9523 \n  0.9894016 219.853 \n  0.9908847 218.7592 \n  0.9930059 217.6709 \n  0.9904228 217.6709 \n  0.962741 213.3714 \n  0.9670218 209.1568 \n  0.9779282 206.0505 \n  0.9113222 202.9904 \n  0.863717 196.0257 \n  0.7813085 193.1145 \n  0.7102375 197.0059 \n  0.6673803 201.9805 \n  0.7775867 202.9904 \n  0.8043374 204.0054 \n  0.7297218 200.9756 \n  0.5714095 197.0059 \n  0.5821126 194.0801 \n  0.7140544 193.1145 \n  0.7262678 194.0801 \n  0.7389845 195.0505 \n  0.7598057 196.0257 \n  0.7466297 197.9909 \n  0.6394933 199.9758 \n  0.6129577 201.9805 \n  0.672642 202.9904 \n  0.715472 202.9904 \n  0.7394825 202.9904 \n  0.5446303 202.9904 \n  0.7562882 202.9904 \n  0.7478679 202.9904 \n  0.3738182 201.9805 \n  0.7470279 200.9756 \n  0.7631992 199.9758 \n  0.4866134 198.9809 \n  0.6727687 197.9909 \n  0.6740197 197.0059 \n  0.5121869 196.0257 \n  0.5960711 195.0505 \n  0.4775652 194.0801 \n  0.7727789 193.1145 \n  0.7569727 192.1537 \n  0.3645771 190.2465 \n  0.7480979 188.3582 \n  0.669458 186.4887 \n  0.06009803 184.6377 \n  -0.2068706 182.8051 \n  0.2833839 180.9906 \n  0.6422815 179.1942 \n  0.3581112 177.4156 \n  0.2500266 175.6547 \n  0.3498747 173.9112 \n  0.569603 172.185 \n  0.097353 170.476 \n  0.3730714 168.784 \n  -0.1027659 167.1087 \n  -0.1343261 165.4501 \n  -0.1674749 163.8079 \n  -0.09346908 162.182 \n  0.02017644 160.5723 \n  0.01829195 158.9785 \n  0.2345988 157.4006 \n  0.254218 155.8383 \n  0.4619125 154.2915 \n  0.2792292 165.4501 \n  0.6047359 176.533 \n  0.7835823 178.3027 \n  0.8670148 175.6547 \n  0.9359789 173.9112 \n  0.9631585 175.6547 \n  0.9587292 176.533 \n  0.9695755 176.533 \n  0.9835575 179.1942 \n  0.9900097 179.1942 \n  0.9886937 180.0902 \n  0.9895495 180.9906 \n  0.9944302 183.7191 \n  0.9966992 183.7191 \n  0.9946688 186.4887 \n  0.992237 189.3 \n  0.9917749 191.1978 \n  0.9863276 192.1537 \n  0.9785607 192.1537 \n  0.9806378 190.2465 \n  0.9924863 189.3 \n  0.99017 188.3582 \n  0.9820646 187.4211 \n  0.9470521 188.3582 \n  0.8216711 187.4211 \n  0.7153458 190.2465 \n  0.7442878 193.1145 \n  0.5942695 196.0257 \n  0.5665525 197.0059 \n  0.535006 195.0505 \n  0.6266476 193.1145 \n  0.6059493 194.0801 \n  0.6425897 198.9809 \n  0.8118222 206.0505 \n  0.8551767 210.2025 \n  0.8889339 211.2535 \n  0.947816 211.2535 \n  0.9787855 209.1568 \n  0.988611 208.1162 \n  0.987321 207.0808 \n  0.9843316 205.0254 \n  0.9737096 204.0054 \n  0.9765185 202.9904 \n  0.9856598 202.9904 \n  0.9898718 204.0054 \n  0.9886413 204.0054 \n  0.989678 202.9904 \n  0.9851701 200.9756 \n  0.9817263 198.9809 \n  0.9766667 196.0257 \n  0.9717003 194.0801 \n  0.9652438 193.1145 \n  0.9332103 193.1145 \n  0.9138572 194.0801 \n  0.8846416 194.0801 \n  0.9482771 195.0505 \n  0.9305538 196.0257 \n  0.8390872 197.0059 \n  0.7701216 197.9909 \n  0.7264634 197.9909 \n  0.7708728 197.9909 \n  0.8309863 197.9909 \n  0.8339165 197.9909 \n  0.723191 197.0059 \n  0.7247626 196.0257 \n  0.608819 195.0505 \n  0.3213559 194.0801 \n  0.2234745 193.1145 \n  -0.02573975 191.1978 \n  0.05725723 189.3 \n  0.218053 187.4211 \n  0.4777128 185.5609 \n  0.5337029 182.8051 \n  0.2318052 180.0902 \n  0.4889631 177.4156 \n  0.08109105 174.7808 \n  0.7427355 172.185 \n  0.8433576 171.3284 \n  0.938632 170.476 \n  0.9607551 168.784 \n  0.9642593 167.1087 \n  0.963613 166.2773 \n  0.9651926 167.1087 \n  0.9591027 168.784 \n  0.9754831 172.185 \n  0.9820764 176.533 \n  0.9875088 180.0902 \n  0.9851621 181.8956 \n  0.9825414 183.7191 \n  0.9723955 185.5609 \n  0.9567259 187.4211 \n  0.8835074 189.3 \n  0.8628154 192.1537 \n  0.9157982 195.0505 \n  0.5938084 198.9809 \n  0.6943321 209.1568 \n  0.7714629 212.3098 \n  0.8662375 211.2535 \n  0.849728 205.0254 \n  0.7945137 196.0257 \n  0.7933522 188.3582 \n  0.6368725 178.3027 \n  0.5897154 167.1087 \n  0.3229582 158.1876 \n  0.2969382 144.605 \n  0.3351896 141.7487 \n  0.384491 146.0546 \n  0.04096958 151.2439 \n  0.1369363 172.185 \n  0.3727793 180.9906 \n  0.4194036 183.7191 \n  0.4396896 185.5609 \n  0.5275242 185.5609 \n  0.2498598 186.4887 \n  0.05898202 190.2465 \n  0.04901373 195.0505 \n  0.1100158 197.9909 \n  0.2187118 198.9809 \n  0.4847157 197.9909 \n  0.4972816 197.9909 \n  0.5150168 198.9809 \n  0.5341532 200.9756 \n  0.2631531 202.9904 \n  0.1344986 205.0254 \n  0.1769232 207.0808 \n  0.2019505 209.1568 \n  0.3217678 211.2535 \n  0.366561 213.3714 \n  0.3891162 215.5104 \n  0.3456501 217.6709 \n  0.3461981 219.853 \n  0.1349857 222.057 \n  0.06558777 224.2832 \n  0.397542 226.5316 \n  0.697022 228.8026 \n  0.4396819 231.0963 \n  0.7819827 233.4131 \n  0.7121504 235.753 \n  0.2208821 238.1164 \n  0.7816582 240.5036 \n  0.7002975 242.9146 \n  0.03593514 245.3498 \n  0.1999688 247.8095 \n  0.6519101 249.0485 \n  0.5185443 251.5452 \n  0.9164662 254.067 \n  0.9069665 255.3373 \n  0.9549389 254.067 \n  0.9885621 252.8029 \n  0.9925307 251.5452 \n  0.9942389 249.0485 \n  0.996495 249.0485 \n  0.9955549 247.8095 \n  0.9936098 246.5766 \n  0.980476 245.3498 \n  0.9671 246.5766 \n  0.9642795 249.0485 \n  0.9722587 249.0485 \n  0.974653 249.0485 \n  0.9627596 247.8095 \n  0.9594576 247.8095 \n  0.9352374 247.8095 \n  0.9516878 246.5766 \n  0.9676836 245.3498 \n  0.9551129 246.5766 \n  0.9023392 249.0485 \n  0.8472683 251.5452 \n  0.8856258 254.067 \n  0.8884159 255.3373 \n  0.9254211 255.3373 \n  0.9612991 254.067 \n  0.9673759 250.2938 \n  0.9728466 245.3498 \n  0.967782 242.9146 \n  0.9654288 240.5036 \n  0.9444144 238.1164 \n  0.9269778 236.9318 \n  0.9488637 236.9318 \n  0.9771202 236.9318 \n  0.9830479 235.753 \n  0.97499 234.5801 \n  0.968623 233.4131 \n  0.9521769 233.4131 \n  0.9390221 233.4131 \n  0.9339334 233.4131 \n  0.887956 232.2518 \n  0.9046763 231.0963 \n  0.8827981 229.9466 \n  0.8236388 231.0963 \n  0.7853005 231.0963 \n  0.8529194 229.9466 \n  0.8421693 227.6642 \n  0.880672 224.2832 \n  0.8143209 219.853 \n  0.8765387 215.5104 \n  0.8224545 210.2025 \n  0.5476995 204.0054 \n  0.3984698 197.0059 \n  0.2524756 189.3 \n  0.0114817 180.9906 \n  0.2040667 172.185 \n  -0.1669366 163.8079 \n  0.504205 154.2915 \n  0.7180874 151.2439 \n  0.8632782 151.2439 \n  0.8973259 150.4914 \n  0.9185986 151.2439 \n  0.7587776 154.2915 \n  0.7147576 159.7734 \n  0.7589291 165.4501 \n  0.8840488 171.3284 \n  0.972356 175.6547 \n  0.9816653 179.1942 \n  0.988443 180.9906 \n  0.9923041 181.8956 \n  0.9943824 182.8051 \n  0.9964477 183.7191 \n  0.9936554 181.8956 \n  0.9887792 180.0902 \n  0.9771134 175.6547 \n  0.9618319 170.476 \n  0.9328524 167.9442 \n  0.819974 168.784 \n  0.8450117 170.476 \n  0.8293109 171.3284 \n  0.6963592 171.3284 \n  0.6338254 164.6269 \n  0.7285098 158.9785 \n  0.7664092 154.2915 \n  0.8064316 152.0001 \n  0.9278697 152.0001 \n  0.9533199 151.2439 \n  0.9601526 149.7427 \n  0.9562845 148.9977 \n  0.963026 149.7427 \n  0.9602929 149.7427 \n  0.8744306 150.4914 \n  0.5927675 154.2915 \n  0.3564559 159.7734 \n  0.2405773 164.6269 \n  0.2860079 169.6279 \n  0.6529107 173.9112 \n  0.835753 176.533 \n  0.8849658 179.1942 \n  0.875807 180.9906 \n  0.823069 182.8051 \n  0.6626108 184.6377 \n  0.2836408 187.4211 \n  0.6051244 190.2465 \n  0.7253854 193.1145 \n  0.765985 196.0257 \n  0.8194041 198.9809 \n  0.6263421 201.9805 \n  0.8017131 205.0254 \n  0.682602 209.1568 \n  0.5036187 213.3714 \n  0.5814967 218.7592 \n  0.814868 224.2832 \n  0.8269848 229.9466 \n  0.7358219 235.753 \n  0.4268066 241.7061 \n  0.8835183 247.8095 \n  0.8267587 254.067 \n  0.5491355 259.1866 \n  0.8746379 264.4093 \n  0.8389229 269.7372 \n  0.6826822 275.1726 \n  0.9028191 280.7175 \n  0.8286572 286.3741 \n  0.4525082 292.1447 \n  0.7583002 298.0316 \n  0.9073849 304.037 \n  0.9051184 310.1635 \n  0.64346 316.4135 \n  0.9253378 322.7894 \n  0.9132795 329.2938 \n  0.6598362 334.2579 \n  0.9356085 339.2969 \n  0.9236958 344.4118 \n  0.8228285 349.6039 \n  0.9376769 354.8742 \n  0.9356694 360.224 \n  0.9184375 365.6544 \n  0.9058462 371.1667 \n  0.9012623 374.8877 \n  0.9611984 378.6459 \n  0.9567629 382.4419 \n  0.7675866 384.3541 \n  0.9645271 386.2758 \n  0.9546855 388.2072 \n  0.7844603 388.2072 \n  0.9640375 388.2072 \n  0.9452955 388.2072 \n  0.5753929 388.2072 \n  0.394645 388.2072 \n  0.5464906 388.2072 \n  0.7876784 388.2072 \n  0.7982122 388.2072 \n  0.5932955 388.2072 \n  0.4936025 388.2072 \n  0.7250561 388.2072 \n  0.6559195 388.2072 \n  0.7656435 388.2072 \n  0.9420093 388.2072 \n  0.7749707 388.2072 ]\n"
  },
  {
    "path": "audio/tools/setup_helpers/__init__.py",
    "content": "from .extension import *\r\n"
  },
  {
    "path": "audio/tools/setup_helpers/extension.py",
    "content": "import os\nimport platform\nimport subprocess\nfrom pathlib import Path\n\nimport distutils.sysconfig\nfrom setuptools import Extension\nfrom setuptools.command.build_ext import build_ext\n\n__all__ = [\n    \"get_ext_modules\",\n    \"CMakeBuild\",\n]\n\n_THIS_DIR = Path(__file__).parent.resolve()\n_ROOT_DIR = _THIS_DIR.parent.parent.resolve()\n_PADDLESPEECH_DIR = _ROOT_DIR / \"paddleaudio\"\n\n\ndef _get_build(var, default=False):\n    if var not in os.environ:\n        return default\n\n    val = os.environ.get(var, \"0\")\n    trues = [\"1\", \"true\", \"TRUE\", \"on\", \"ON\", \"yes\", \"YES\"]\n    falses = [\"0\", \"false\", \"FALSE\", \"off\", \"OFF\", \"no\", \"NO\"]\n    if val in trues:\n        return True\n    if val not in falses:\n        print(f\"WARNING: Unexpected environment variable value `{var}={val}`. \"\n              f\"Expected one of {trues + falses}\")\n    return False\n\n\n_BUILD_SOX = False if platform.system() == \"Windows\" else _get_build(\n    \"BUILD_SOX\", True)\n_BUILD_MAD = _get_build(\"BUILD_MAD\", False)\n_BUILD_KALDI = False if platform.system() == \"Windows\" else _get_build(\n    \"BUILD_KALDI\", True)\n_PADDLESPEECH_CUDA_ARCH_LIST = os.environ.get(\"PADDLESPEECH_CUDA_ARCH_LIST\",\n                                              None)\n\ndef get_ext_modules():\n    if platform.system() == \"Windows\":\n        return []\n    modules = [\n        Extension(name=\"paddleaudio.lib.libpaddleaudio\", sources=[]),\n        Extension(name=\"paddleaudio._paddleaudio\", sources=[]),\n    ]\n    return modules\n\n\n# Based off of\n# https://github.com/pybind/cmake_example/blob/580c5fd29d4651db99d8874714b07c0c49a53f8a/setup.py\nclass CMakeBuild(build_ext):\n    def run(self):\n        try:\n            subprocess.check_output([\"cmake\", \"--version\"])\n        except OSError:\n            raise RuntimeError(\"CMake is not available.\") from None\n        super().run()\n\n    def build_extension(self, ext):\n        # Since two library files (libpaddleaudio and _paddleaudio) need to be\n        # recognized by setuptools, we instantiate `Extension` twice. (see `get_ext_modules`)\n        # This leads to the situation where this `build_extension` method is called twice.\n        # However, the following `cmake` command will build all of them at the same time,\n        # so, we do not need to perform `cmake` twice.\n        # Therefore we call `cmake` only for `paddleaudio._paddleaudio`.\n        if ext.name != \"paddleaudio._paddleaudio\":\n            return\n\n        extdir = os.path.abspath(\n            os.path.dirname(self.get_ext_fullpath(ext.name)))\n\n        # required for auto-detection of auxiliary \"native\" libs\n        if not extdir.endswith(os.path.sep):\n            extdir += os.path.sep\n\n        cfg = \"Debug\" if self.debug else \"Release\"\n\n        cmake_args = [\n            f\"-DCMAKE_BUILD_TYPE={cfg}\",\n            # f\"-DCMAKE_PREFIX_PATH={torch.utils.cmake_prefix_path}\",\n            f\"-DCMAKE_INSTALL_PREFIX={extdir}\",\n            \"-DCMAKE_VERBOSE_MAKEFILE=ON\",\n            f\"-DPYTHON_INCLUDE_DIR={distutils.sysconfig.get_python_inc()}\",\n            #f\"-DPYTHON_LIBRARY={distutils.sysconfig.get_config_var('LIBDIR')}\",\n            f\"-DBUILD_SOX:BOOL={'ON' if _BUILD_SOX else 'OFF'}\",\n            f\"-DBUILD_MAD:BOOL={'ON' if _BUILD_MAD else 'OFF'}\",\n            f\"-DBUILD_KALDI:BOOL={'ON' if _BUILD_KALDI else 'OFF'}\",\n            # f\"-DBUILD_RNNT:BOOL={'ON' if _BUILD_RNNT else 'OFF'}\",\n            # f\"-DBUILD_CTC_DECODER:BOOL={'ON' if _BUILD_CTC_DECODER else 'OFF'}\",\n            \"-DBUILD_PADDLEAUDIO_PYTHON_EXTENSION:BOOL=ON\",\n            # f\"-DUSE_ROCM:BOOL={'ON' if _USE_ROCM else 'OFF'}\",\n            # f\"-DUSE_CUDA:BOOL={'ON' if _USE_CUDA else 'OFF'}\",\n            # f\"-DUSE_OPENMP:BOOL={'ON' if _USE_OPENMP else 'OFF'}\",\n            # f\"-DUSE_FFMPEG:BOOL={'ON' if _USE_FFMPEG else 'OFF'}\",\n        ]\n        build_args = [\"--target\", \"install\"]\n        # Pass CUDA architecture to cmake\n        if _PADDLESPEECH_CUDA_ARCH_LIST is not None:\n            # Convert MAJOR.MINOR[+PTX] list to new style one\n            # defined at https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html\n            _arches = _PADDLESPEECH_CUDA_ARCH_LIST.replace(\".\", \"\").replace(\n                \" \", \";\").split(\";\")\n            _arches = [\n                arch[:-4] if arch.endswith(\"+PTX\") else f\"{arch}-real\"\n                for arch in _arches\n            ]\n            cmake_args += [f\"-DCMAKE_CUDA_ARCHITECTURES={';'.join(_arches)}\"]\n\n        # Default to Ninja\n        if \"CMAKE_GENERATOR\" not in os.environ or platform.system() == \"Windows\":\n            cmake_args += [\"-GNinja\"]\n\n        if platform.system() == \"Windows\":\n            import sys\n\n            python_version = sys.version_info\n            cmake_args += [\n                \"-DCMAKE_C_COMPILER=cl\",\n                \"-DCMAKE_CXX_COMPILER=cl\",\n                f\"-DPYTHON_VERSION={python_version.major}.{python_version.minor}\",\n            ]\n\n        # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level\n        # across all generators.\n        if \"CMAKE_BUILD_PARALLEL_LEVEL\" not in os.environ:\n            # self.parallel is a Python 3 only way to set parallel jobs by hand\n            # using -j in the build_ext call, not supported by pip or PyPA-build.\n            if hasattr(self, \"parallel\") and self.parallel:\n                # CMake 3.12+ only.\n                build_args += [\"-j{}\".format(self.parallel)]\n\n        if not os.path.exists(self.build_temp):\n            os.makedirs(self.build_temp)\n\n        print(\n            f\"cmake {_ROOT_DIR} {' '.join(cmake_args)}, cwd={self.build_temp}\")\n        subprocess.check_call(\n            [\"cmake\", str(_ROOT_DIR)] + cmake_args, cwd=self.build_temp)\n        print(f\"cmake --build . {' '.join(build_args)}, cwd={self.build_temp}\")\n        subprocess.check_call(\n            [\"cmake\", \"--build\", \".\"] + build_args, cwd=self.build_temp)\n\n    def get_ext_filename(self, fullname):\n        ext_filename = super().get_ext_filename(fullname)\n        ext_filename_parts = ext_filename.split(\".\")\n        without_abi = ext_filename_parts[:-2] + ext_filename_parts[-1:]\n        ext_filename = \".\".join(without_abi)\n        return ext_filename\n"
  },
  {
    "path": "dataset/aishell/.gitignore",
    "content": "data_aishell*\n*.meta\nmanifest.*\n*.tgz\nresource_aishell\n"
  },
  {
    "path": "dataset/aishell/aishell.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Aishell mandarin dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nfrom paddlespeech.dataset.aishell import aishell_main\n\nif __name__ == '__main__':\n    aishell_main()\n"
  },
  {
    "path": "dataset/aishell3/README.md",
    "content": "# [Aishell3](http://www.openslr.org/93/)\n\nAISHELL-3 is a large-scale and high-fidelity multi-speaker Mandarin speech corpus which could be used to train multi-speaker Text-to-Speech (TTS) systems. The corpus contains roughly **85 hours** of emotion-neutral recordings spoken by 218 native Chinese mandarin speakers and total 88035 utterances. Their auxiliary attributes such as gender, age group and native accents are explicitly marked and provided in the corpus. Accordingly, transcripts in Chinese character-level and pinyin-level are provided along with the recordings. The  word & tone transcription accuracy rate is above 98%, through professional speech annotation and strict quality inspection for tone and prosody. ( This database is free for academic research, not in the commerce, if without permission. )\n"
  },
  {
    "path": "dataset/chime3_background/chime3_background.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare CHiME3 background data.\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport io\nimport json\nimport os\nimport zipfile\n\nimport soundfile\nimport wget\nfrom paddle.v2.dataset.common import md5file\n\n# DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\nDATA_HOME = os.path.expanduser('.')\n\nURL = \"https://d4s.myairbridge.com/packagev2/AG0Y3DNBE5IWRRTV/?dlid=W19XG7T0NNHB027139H0EQ\"\nMD5 = \"c3ff512618d7a67d4f85566ea1bc39ec\"\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/chime3_background\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_filepath\",\n    default=\"manifest.chime3.background\",\n    type=str,\n    help=\"Filepath for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef download(url, md5sum, target_dir, filename=None):\n    \"\"\"Download file from url to target_dir, and check md5sum.\"\"\"\n    if filename is None:\n        filename = url.split(\"/\")[-1]\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n    filepath = os.path.join(target_dir, filename)\n    if not (os.path.exists(filepath) and md5file(filepath) == md5sum):\n        print(\"Downloading %s ...\" % url)\n        wget.download(url, target_dir)\n        print(\"\\nMD5 Checksum %s ...\" % filepath)\n        if not md5file(filepath) == md5sum:\n            raise RuntimeError(\"MD5 checksum failed.\")\n    else:\n        print(\"File exists, skip downloading. (%s)\" % filepath)\n    return filepath\n\n\ndef unpack(filepath, target_dir):\n    \"\"\"Unpack the file to the target_dir.\"\"\"\n    print(\"Unpacking %s ...\" % filepath)\n    if filepath.endswith('.zip'):\n        zip = zipfile.ZipFile(filepath, 'r')\n        zip.extractall(target_dir)\n        zip.close()\n    elif filepath.endswith('.tar') or filepath.endswith('.tar.gz'):\n        tar = zipfile.open(filepath)\n        tar.extractall(target_dir)\n        tar.close()\n    else:\n        raise ValueError(\"File format is not supported for unpacking.\")\n\n\ndef create_manifest(data_dir, manifest_path):\n    \"\"\"Create a manifest json file summarizing the data set, with each line\n    containing the meta data (i.e. audio filepath, transcription text, audio\n    duration) of each audio file within the data set.\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path)\n    json_lines = []\n    for subfolder, _, filelist in sorted(os.walk(data_dir)):\n        for filename in filelist:\n            if filename.endswith('.wav'):\n                filepath = os.path.join(data_dir, subfolder, filename)\n                audio_data, samplerate = soundfile.read(filepath)\n                duration = float(len(audio_data)) / samplerate\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt': os.path.splitext(os.path.basename(filepath))[\n                                0],\n                            'feat': filepath,\n                            'feat_shape': (duration, ),  # second\n                            'type': 'background'\n                        }))\n    with io.open(manifest_path, mode='w', encoding='utf8') as out_file:\n        for line in json_lines:\n            out_file.write(line + '\\n')\n\n\ndef prepare_chime3(url, md5sum, target_dir, manifest_path):\n    \"\"\"Download, unpack and create summary manifest file.\"\"\"\n    if not os.path.exists(os.path.join(target_dir, \"CHiME3\")):\n        # download\n        filepath = download(url, md5sum, target_dir,\n                            \"myairbridge-AG0Y3DNBE5IWRRTV.zip\")\n        # unpack\n        unpack(filepath, target_dir)\n        unpack(\n            os.path.join(target_dir, 'CHiME3_background_bus.zip'), target_dir)\n        unpack(\n            os.path.join(target_dir, 'CHiME3_background_caf.zip'), target_dir)\n        unpack(\n            os.path.join(target_dir, 'CHiME3_background_ped.zip'), target_dir)\n        unpack(\n            os.path.join(target_dir, 'CHiME3_background_str.zip'), target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n    # create manifest json file\n    create_manifest(target_dir, manifest_path)\n\n\ndef main():\n    prepare_chime3(\n        url=URL,\n        md5sum=MD5,\n        target_dir=args.target_dir,\n        manifest_path=args.manifest_filepath)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/gigaspeech/.gitignore",
    "content": "GigaSpeech/\n"
  },
  {
    "path": "dataset/gigaspeech/README.md",
    "content": "# [GigaSpeech](https://github.com/SpeechColab/GigaSpeech)\n\n```\ngit clone https://github.com/SpeechColab/GigaSpeech.git\n\ncd GigaSpeech\nutils/gigaspeech_download.sh /disk1/audio_data/gigaspeech\ntoolkits/kaldi/gigaspeech_data_prep.sh --train-subset XL /disk1/audio_data/gigaspeech ../data\ncd ..\n```\n"
  },
  {
    "path": "dataset/gigaspeech/gigaspeech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "dataset/gigaspeech/run.sh",
    "content": "#!/bin/bash\n\nset -e\n\ncurdir=$PWD\n\ntest -d GigaSpeech || git clone https://github.com/SpeechColab/GigaSpeech.git\n\n\npushd GigaSpeech\nsource env_vars.sh\n./utils/download_gigaspeech.sh ${curdir}/\n#toolkits/kaldi/gigaspeech_data_prep.sh --train-subset XL /disk1/audio_data/gigaspeech ../data\npopd\n"
  },
  {
    "path": "dataset/librispeech/.gitignore",
    "content": "dev-clean\ndev-other\ntest-clean\ntest-other\ntrain-clean-100\ntrain-clean-360\ntrain-other-500\n*.meta\nmanifest.*\n"
  },
  {
    "path": "dataset/librispeech/librispeech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Librispeech ASR datasets.\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport io\nimport json\nimport os\nfrom multiprocessing.pool import Pool\n\nimport distutils.util\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\nfrom paddlespeech.utils.argparse import strtobool\n\nURL_ROOT = \"http://openslr.elda.org/resources/12\"\n#URL_ROOT = \"https://openslr.magicdatatech.com/resources/12\"\nURL_TEST_CLEAN = URL_ROOT + \"/test-clean.tar.gz\"\nURL_TEST_OTHER = URL_ROOT + \"/test-other.tar.gz\"\nURL_DEV_CLEAN = URL_ROOT + \"/dev-clean.tar.gz\"\nURL_DEV_OTHER = URL_ROOT + \"/dev-other.tar.gz\"\nURL_TRAIN_CLEAN_100 = URL_ROOT + \"/train-clean-100.tar.gz\"\nURL_TRAIN_CLEAN_360 = URL_ROOT + \"/train-clean-360.tar.gz\"\nURL_TRAIN_OTHER_500 = URL_ROOT + \"/train-other-500.tar.gz\"\n\nMD5_TEST_CLEAN = \"32fa31d27d2e1cad72775fee3f4849a9\"\nMD5_TEST_OTHER = \"fb5a50374b501bb3bac4815ee91d3135\"\nMD5_DEV_CLEAN = \"42e2234ba48799c1f50f24a7926300a1\"\nMD5_DEV_OTHER = \"c8d0bcc9cca99d4f8b62fcc847357931\"\nMD5_TRAIN_CLEAN_100 = \"2a93770f6d5c6c964bc36631d331a522\"\nMD5_TRAIN_CLEAN_360 = \"c0e676e450a7ff2f54aeade5171606fa\"\nMD5_TRAIN_OTHER_500 = \"d1a0fd59409feb2c614ce4d30c387708\"\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default='~/.cache/paddle/dataset/speech/libri',\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nparser.add_argument(\n    \"--full_download\",\n    default=\"True\",\n    type=strtobool,\n    help=\"Download all datasets for Librispeech.\"\n    \" If False, only download a minimal requirement (test-clean, dev-clean\"\n    \" train-clean-100). (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path):\n    \"\"\"Create a manifest json file summarizing the data set, with each line\n    containing the meta data (i.e. audio filepath, transcription text, audio\n    duration) of each audio file within the data set.\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path)\n    json_lines = []\n    total_sec = 0.0\n    total_char = 0.0\n    total_num = 0\n\n    for subfolder, _, filelist in sorted(os.walk(data_dir)):\n        text_filelist = [\n            filename for filename in filelist if filename.endswith('trans.txt')\n        ]\n        if len(text_filelist) > 0:\n            text_filepath = os.path.join(subfolder, text_filelist[0])\n            for line in io.open(text_filepath, encoding=\"utf8\"):\n                segments = line.strip().split()\n                nchars = len(segments[1:])\n                text = ' '.join(segments[1:]).lower()\n\n                audio_filepath = os.path.abspath(\n                    os.path.join(subfolder, segments[0] + '.flac'))\n                audio_data, samplerate = soundfile.read(audio_filepath)\n                duration = float(len(audio_data)) / samplerate\n\n                utt = os.path.splitext(os.path.basename(audio_filepath))[0]\n                utt2spk = '-'.join(utt.split('-')[:2])\n\n                json_lines.append(\n                    json.dumps({\n                        'utt': utt,\n                        'utt2spk': utt2spk,\n                        'feat': audio_filepath,\n                        'feat_shape': (duration, ),  # second\n                        'text': text,\n                    }))\n\n                total_sec += duration\n                total_char += nchars\n                total_num += 1\n\n    with codecs.open(manifest_path, 'w', 'utf-8') as out_file:\n        for line in json_lines:\n            out_file.write(line + '\\n')\n\n    subset = os.path.splitext(manifest_path)[1][1:]\n    manifest_dir = os.path.dirname(manifest_path)\n    data_dir_name = os.path.split(data_dir)[-1]\n    meta_path = os.path.join(manifest_dir, data_dir_name) + '.meta'\n    with open(meta_path, 'w') as f:\n        print(f\"{subset}:\", file=f)\n        print(f\"{total_num} utts\", file=f)\n        print(f\"{total_sec / (60*60)} h\", file=f)\n        print(f\"{total_char} char\", file=f)\n        print(f\"{total_char / total_sec} char/sec\", file=f)\n        print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path):\n    \"\"\"Download, unpack and create summary manifest file.\n    \"\"\"\n    if not os.path.exists(os.path.join(target_dir, \"LibriSpeech\")):\n        # download\n        filepath = download(url, md5sum, target_dir)\n        # unpack\n        unpack(filepath, target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n    # create manifest json file\n    create_manifest(target_dir, manifest_path)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    tasks = [\n        (URL_TEST_CLEAN, MD5_TEST_CLEAN, os.path.join(args.target_dir,\n                                                      \"test-clean\"),\n         args.manifest_prefix + \".test-clean\"),\n        (URL_DEV_CLEAN, MD5_DEV_CLEAN, os.path.join(\n            args.target_dir, \"dev-clean\"), args.manifest_prefix + \".dev-clean\"),\n    ]\n    if args.full_download:\n        tasks.extend([\n            (URL_TRAIN_CLEAN_100, MD5_TRAIN_CLEAN_100,\n             os.path.join(args.target_dir, \"train-clean-100\"),\n             args.manifest_prefix + \".train-clean-100\"),\n            (URL_TEST_OTHER, MD5_TEST_OTHER, os.path.join(args.target_dir,\n                                                          \"test-other\"),\n             args.manifest_prefix + \".test-other\"),\n            (URL_DEV_OTHER, MD5_DEV_OTHER, os.path.join(args.target_dir,\n                                                        \"dev-other\"),\n             args.manifest_prefix + \".dev-other\"),\n            (URL_TRAIN_CLEAN_360, MD5_TRAIN_CLEAN_360,\n             os.path.join(args.target_dir, \"train-clean-360\"),\n             args.manifest_prefix + \".train-clean-360\"),\n            (URL_TRAIN_OTHER_500, MD5_TRAIN_OTHER_500,\n             os.path.join(args.target_dir, \"train-other-500\"),\n             args.manifest_prefix + \".train-other-500\"),\n        ])\n\n    with Pool(7) as pool:\n        pool.starmap(prepare_dataset, tasks)\n\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/magicdata/README.md",
    "content": "# [MagicData](http://openslr.elda.org/68/)\n\nMAGICDATA Mandarin Chinese Read Speech Corpus was developed by MAGIC DATA Technology Co., Ltd. and freely published for non-commercial use.\nThe contents and the corresponding descriptions of the corpus include:\n\n* The corpus contains 755 hours of speech data, which is mostly mobile recorded data.\n* 1080 speakers from different accent areas in China are invited to participate in the recording.\n* The sentence transcription accuracy is higher than 98%.\n* Recordings are conducted in a quiet indoor environment.\n* The database is divided into training set, validation set, and testing set in a ratio of 51: 1: 2.\n* Detail information such as speech data coding and speaker information is preserved in the metadata file.\n* The domain of recording texts is diversified, including interactive Q&A, music search, SNS messages, home command and control, etc.\n* Segmented transcripts are also provided.\n\nThe corpus aims to support researchers in speech recognition, machine translation, speaker recognition, and other speech-related fields. Therefore, the corpus is totally free for academic use.\n"
  },
  {
    "path": "dataset/mini_librispeech/.gitignore",
    "content": "dev-clean/\nmanifest.dev-clean\nmanifest.train-clean\ntrain-clean/\n*.meta\n"
  },
  {
    "path": "dataset/mini_librispeech/mini_librispeech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Librispeech ASR datasets.\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport io\nimport json\nimport os\nfrom multiprocessing.pool import Pool\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\n\nURL_ROOT = \"http://openslr.elda.org/resources/31\"\nURL_TRAIN_CLEAN = URL_ROOT + \"/train-clean-5.tar.gz\"\nURL_DEV_CLEAN = URL_ROOT + \"/dev-clean-2.tar.gz\"\n\nMD5_TRAIN_CLEAN = \"5df7d4e78065366204ca6845bb08f490\"\nMD5_DEV_CLEAN = \"6d7ab67ac6a1d2c993d050e16d61080d\"\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default='~/.cache/paddle/dataset/speech/libri',\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path):\n    \"\"\"Create a manifest json file summarizing the data set, with each line\n    containing the meta data (i.e. audio filepath, transcription text, audio\n    duration) of each audio file within the data set.\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path)\n    json_lines = []\n    total_sec = 0.0\n    total_text = 0.0\n    total_num = 0\n\n    for subfolder, _, filelist in sorted(os.walk(data_dir)):\n        text_filelist = [\n            filename for filename in filelist if filename.endswith('trans.txt')\n        ]\n        if len(text_filelist) > 0:\n            text_filepath = os.path.join(subfolder, text_filelist[0])\n            for line in io.open(text_filepath, encoding=\"utf8\"):\n                segments = line.strip().split()\n                text = ' '.join(segments[1:]).lower()\n                audio_filepath = os.path.join(subfolder, segments[0] + '.flac')\n                audio_data, samplerate = soundfile.read(audio_filepath)\n                duration = float(len(audio_data)) / samplerate\n\n                utt = os.path.splitext(os.path.basename(audio_filepath))[0]\n                utt2spk = '-'.join(utt.split('-')[:2])\n                json_lines.append(\n                    json.dumps({\n                        'utt': utt,\n                        'utt2spk': utt2spk,\n                        'feat': audio_filepath,\n                        'feat_shape': (duration, ),  #second\n                        'text': text,\n                    }))\n\n                total_sec += duration\n                total_text += len(text)\n                total_num += 1\n\n    with codecs.open(manifest_path, 'w', 'utf-8') as out_file:\n        for line in json_lines:\n            out_file.write(line + '\\n')\n\n    subset = os.path.splitext(manifest_path)[1][1:]\n    manifest_dir = os.path.dirname(manifest_path)\n    data_dir_name = os.path.split(data_dir)[-1]\n    meta_path = os.path.join(manifest_dir, data_dir_name) + '.meta'\n    with open(meta_path, 'w') as f:\n        print(f\"{subset}:\", file=f)\n        print(f\"{total_num} utts\", file=f)\n        print(f\"{total_sec / (60*60)} h\", file=f)\n        print(f\"{total_text} text\", file=f)\n        print(f\"{total_text / total_sec} text/sec\", file=f)\n        print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path):\n    \"\"\"Download, unpack and create summary manifest file.\n    \"\"\"\n    if not os.path.exists(os.path.join(target_dir, \"LibriSpeech\")):\n        # download\n        filepath = download(url, md5sum, target_dir)\n        # unpack\n        unpack(filepath, target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n    # create manifest json file\n    create_manifest(target_dir, manifest_path)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    tasks = [\n        (URL_TRAIN_CLEAN, MD5_TRAIN_CLEAN,\n         os.path.join(args.target_dir, \"train-clean\"),\n         args.manifest_prefix + \".train-clean\"),\n        (URL_DEV_CLEAN, MD5_DEV_CLEAN, os.path.join(\n            args.target_dir, \"dev-clean\"), args.manifest_prefix + \".dev-clean\"),\n    ]\n\n    with Pool(2) as pool:\n        pool.starmap(prepare_dataset, tasks)\n\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/multi_cn/README.md",
    "content": "# multi-cn\n\nThis is a Chinese speech recognition recipe that trains on all Chinese corpora on OpenSLR, including:\n\n* Aidatatang (140 hours)\n* Aishell (151 hours)\n* MagicData (712 hours)\n* Primewords (99 hours)\n* ST-CMDS (110 hours)\n* THCHS-30 (26 hours)\n* optional AISHELL2 (~1000 hours) if available\n"
  },
  {
    "path": "dataset/primewords/README.md",
    "content": "# [Primewords](http://openslr.elda.org/47/)\n\nThis free Chinese Mandarin speech corpus set is released by Shanghai Primewords Information Technology Co., Ltd.\nThe corpus is recorded by smart mobile phones from 296 native Chinese speakers. The transcription accuracy is larger than 98%, at the confidence level of 95%. It is free for academic use.\n\nThe mapping between the transcript and utterance is given in JSON format.\n"
  },
  {
    "path": "dataset/rir_noise/.gitignore",
    "content": "RIRS_NOISES/\nmanifest.pointsource_noises\nmanifest.real_rirs_isotropic_noises\nmanifest.simulated_rirs\nrirs_noises.zip\n"
  },
  {
    "path": "dataset/rir_noise/rir_noise.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Aishell mandarin dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport argparse\nimport codecs\nimport json\nimport os\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unzip\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nURL_ROOT = '--no-check-certificate https://us.openslr.org/resources/28/rirs_noises.zip'\nDATA_URL = URL_ROOT + '/rirs_noises.zip'\nMD5_DATA = 'e6f48e257286e05de56413b4779d8ffb'\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/rirs_noise\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n    data_types = [\n        'pointsource_noises', 'real_rirs_isotropic_noises', 'simulated_rirs'\n    ]\n    for dtype in data_types:\n        del json_lines[:]\n        audio_dir = os.path.join(data_dir, dtype)\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for fname in filelist:\n                audio_path = os.path.join(subfolder, fname)\n                if not audio_path.endswith('.wav'):\n                    continue\n                audio_data, samplerate = soundfile.read(audio_path)\n                duration = float(len(audio_data) / samplerate)\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt':\n                            os.path.splitext(os.path.basename(audio_path))[0],\n                            'feat':\n                            audio_path,\n                            'feat_shape': (duration, ),  #second\n                            'type':\n                            dtype,\n                        },\n                        ensure_ascii=False))\n        manifest_path = manifest_path_prefix + '.' + dtype\n\n        if not os.path.exists(os.path.dirname(manifest_path)):\n            os.makedirs(os.path.dirname(manifest_path))\n\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path):\n    \"\"\"Download, unzip and create manifest file.\"\"\"\n    data_dir = os.path.join(target_dir, 'RIRS_NOISES')\n    if not os.path.exists(data_dir):\n        filepath = download(url, md5sum, target_dir)\n        unzip(filepath, target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n    create_manifest(data_dir, manifest_path)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    prepare_dataset(\n        url=DATA_URL,\n        md5sum=MD5_DATA,\n        target_dir=args.target_dir,\n        manifest_path=args.manifest_prefix)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/st-cmds/README.md",
    "content": "# [FreeST](http://openslr.elda.org/38/)\n"
  },
  {
    "path": "dataset/tal_cs/README.md",
    "content": "# [TAL_CSASR](https://ai.100tal.com/dataset/)\n\nThis data set is TAL English class audio, including mixed Chinese and English speech. Each audio has only one speaker, and this data set has more than 100 speakers. (File 63.36G) This data contains the sample of intra sentence and inter sentence mixing. The ratio between Chinese characters and English words in the data is 13:1. \n\n- Total data: 587H (train_set: 555.9H, dev_set: 8H, test_set: 23.6H)\n- Sample rate: 16000\n- Sample bit: 16\n- Recording device: microphone\n- Speaker number: 200+\n- Recording time: 2019\n- Data format: audio: .wav; test: .txt\n- Audio duration: 1-60s\n- Data type: audio of English teachers' teaching\n"
  },
  {
    "path": "dataset/tal_cs/tal_cs.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare TALCS ASR datasets.\n\ncreate manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport io\nimport json\nimport os\n\nimport soundfile\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\nTRAIN_SET = os.path.join(args.target_dir, \"train_set\")\nDEV_SET = os.path.join(args.target_dir, \"dev_set\")\nTEST_SET = os.path.join(args.target_dir, \"test_set\")\n\nmanifest_train_path = os.path.join(args.manifest_prefix, \"manifest.train.raw\")\nmanifest_dev_path = os.path.join(args.manifest_prefix, \"manifest.dev.raw\")\nmanifest_test_path = os.path.join(args.manifest_prefix, \"manifest.test.raw\")\n\n\ndef create_manifest(data_dir, manifest_path):\n    \"\"\"Create a manifest json file summarizing the data set, with each line\n    containing the meta data (i.e. audio filepath, transcription text, audio\n    duration) of each audio file within the data set.\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path)\n    json_lines = []\n    total_sec = 0.0\n    total_char = 0.0\n    total_num = 0\n    wav_dir = os.path.join(data_dir, 'wav')\n    text_filepath = os.path.join(data_dir, 'label.txt')\n    for subfolder, _, filelist in sorted(os.walk(wav_dir)):\n        for line in io.open(text_filepath, encoding=\"utf8\"):\n            segments = line.strip().split()\n            nchars = len(segments[1:])\n            text = ' '.join(segments[1:]).lower()\n\n            audio_filepath = os.path.abspath(\n                os.path.join(subfolder, segments[0] + '.wav'))\n            audio_data, samplerate = soundfile.read(audio_filepath)\n            duration = float(len(audio_data)) / samplerate\n\n            utt = os.path.splitext(os.path.basename(audio_filepath))[0]\n            utt2spk = '-'.join(utt.split('-')[:2])\n\n            json_lines.append(\n                json.dumps({\n                    'utt': utt,\n                    'utt2spk': utt2spk,\n                    'feat': audio_filepath,\n                    'feat_shape': (duration, ),  # second\n                    'text': text,\n                }))\n\n            total_sec += duration\n            total_char += nchars\n            total_num += 1\n\n    with codecs.open(manifest_path, 'w', 'utf-8') as out_file:\n        for line in json_lines:\n            out_file.write(line + '\\n')\n\n    subset = os.path.splitext(manifest_path)[1][1:]\n    manifest_dir = os.path.dirname(manifest_path)\n    data_dir_name = os.path.split(data_dir)[-1]\n    meta_path = os.path.join(manifest_dir, data_dir_name) + '.meta'\n    with open(meta_path, 'w') as f:\n        print(f\"{subset}:\", file=f)\n        print(f\"{total_num} utts\", file=f)\n        print(f\"{total_sec / (60*60)} h\", file=f)\n        print(f\"{total_char} char\", file=f)\n        print(f\"{total_char / total_sec} char/sec\", file=f)\n        print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    create_manifest(TRAIN_SET, manifest_train_path)\n    create_manifest(DEV_SET, manifest_dev_path)\n    create_manifest(TEST_SET, manifest_test_path)\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/ted_en_zh/.gitignore",
    "content": "*.tar.gz.*\nmanifest.*\n*.md\nEN-ZH/\ntrain-split/\ntest-segment/"
  },
  {
    "path": "dataset/ted_en_zh/ted_en_zh.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Ted-En-Zh speech translation dataset\n\nCreate manifest files from splited dataset. \ndev set: tst2010, test set: tst2015\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\n\nimport soundfile\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--src-dir\",\n    default=\"\",\n    type=str,\n    help=\"Directory to kaldi splited data. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n\n    data_types_infos = [\n        ('train', 'train-split/train-segment', 'En-Zh/train.en-zh'),\n        ('dev', 'test-segment/tst2010', 'En-Zh/tst2010.en-zh'),\n        ('test', 'test-segment/tst2015', 'En-Zh/tst2015.en-zh')\n    ]\n    for data_info in data_types_infos:\n        dtype, audio_relative_dir, text_relative_path = data_info\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        text_path = os.path.join(data_dir, text_relative_path)\n        audio_dir = os.path.join(data_dir, audio_relative_dir)\n\n        for line in codecs.open(text_path, 'r', 'utf-8', errors='ignore'):\n            line = line.strip()\n            if len(line) < 1:\n                continue\n            audio_id, trancription, translation = line.split('\\t')\n            utt = audio_id.split('.')[0]\n\n            audio_path = os.path.join(audio_dir, audio_id)\n            if os.path.exists(audio_path):\n                if os.path.getsize(audio_path) < 30000:\n                    continue\n                audio_data, samplerate = soundfile.read(audio_path)\n                duration = float(len(audio_data) / samplerate)\n\n                translation_str = \" \".join(translation.split())\n                trancription_str = \" \".join(trancription.split())\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt': utt,\n                            'feat': audio_path,\n                            'feat_shape': (duration, ),  # second\n                            'text': [translation_str, trancription_str],\n                        },\n                        ensure_ascii=False))\n\n                total_sec += duration\n                total_text += len(translation.split())\n                total_num += 1\n                if not total_num % 1000:\n                    print(dtype, 'Processed:', total_num)\n\n        manifest_path = manifest_path_prefix + '.' + dtype + '.raw'\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n\ndef prepare_dataset(src_dir, manifest_path=None):\n    \"\"\"create manifest file.\"\"\"\n    if os.path.isdir(manifest_path):\n        manifest_path = os.path.join(manifest_path, 'manifest')\n    if manifest_path:\n        create_manifest(src_dir, manifest_path)\n\n\ndef main():\n    if args.src_dir.startswith('~'):\n        args.src_dir = os.path.expanduser(args.src_dir)\n\n    prepare_dataset(src_dir=args.src_dir, manifest_path=args.manifest_prefix)\n\n    print(\"manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/thchs30/.gitignore",
    "content": "*.tgz\nmanifest.*\ndata_thchs30\nresource\ntest-noise\n*.meta\n"
  },
  {
    "path": "dataset/thchs30/README.md",
    "content": "# [THCHS30](http://openslr.elda.org/18/)\n\nThis is the *data part* of the `THCHS30 2015` acoustic data\n& scripts dataset.\n\nThe dataset is described in more detail in the paper ``THCHS-30 : A Free\nChinese Speech Corpus`` by Dong Wang, Xuewei Zhang.\n\nA paper (if it can be called a paper) 13 years ago regarding the database:\n\nDong Wang, Dalei Wu, Xiaoyan Zhu, ``TCMSD: A new Chinese Continuous Speech Database``,\nInternational Conference on Chinese Computing (ICCC'01), 2001, Singapore.\n\nThe layout of this data pack is the following:\n\n  ``data``\n      ``*.wav``\n        audio data\n\n      ``*.wav.trn``  \n        transcriptions\n\n  ``{train,dev,test}``\n    contain symlinks into the ``data`` directory for both audio and\n    transcription files. Contents of these directories define the\n    train/dev/test split of the data.\n\n  ``{lm_word}``\n       ``word.3gram.lm``\n         trigram LM based on word\n        ``lexicon.txt``\n         lexicon based on word\n\n   ``{lm_phone}``\n       ``phone.3gram.lm``\n         trigram LM based on phone\n        ``lexicon.txt``\n         lexicon based on phone\n\n  ``README.TXT``\n    this file\n\n\nData statistics\n===============\n\nStatistics for the data are as follows:\n\n    ===========  ==========  ==========  ===========\n    **dataset**  **audio**   **#sents**  **#words**\n    ===========  ==========  ==========  ===========\n        train        25        10,000      198,252\n        dev         2:14         893        17,743\n        test        6:15        2,495       49,085\n    ===========  ==========  ==========  ===========\n"
  },
  {
    "path": "dataset/thchs30/thchs30.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare THCHS-30 mandarin dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\nfrom multiprocessing.pool import Pool\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nURL_ROOT = 'http://openslr.elda.org/resources/18'\n# URL_ROOT = 'https://openslr.magicdatatech.com/resources/18'\nDATA_URL = URL_ROOT + '/data_thchs30.tgz'\nTEST_NOISE_URL = URL_ROOT + '/test-noise.tgz'\nRESOURCE_URL = URL_ROOT + '/resource.tgz'\nMD5_DATA = '2d2252bde5c8429929e1841d4cb95e90'\nMD5_TEST_NOISE = '7e8a985fb965b84141b68c68556c2030'\nMD5_RESOURCE = 'c0b2a565b4970a0c4fe89fefbf2d97e1'\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/THCHS30\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef read_trn(filepath):\n    \"\"\"read trn file.\n    word text in first line.\n    syllable text in second line.\n    phoneme text in third line.\n\n    Args:\n        filepath (str): trn path.\n\n    Returns:\n        list(str): (word, syllable, phone)\n    \"\"\"\n    texts = []\n    with open(filepath, 'r') as f:\n        lines = f.read().strip().split('\\n')\n        assert len(lines) == 3, lines\n    # character text, remove whitespace\n    texts.append(''.join(lines[0].split()))\n    texts.extend(lines[1:])\n    return texts\n\n\ndef resolve_symlink(filepath):\n    \"\"\"resolve symlink which content is norm file.\n\n    Args:\n        filepath (str): norm file symlink.\n    \"\"\"\n    sym_path = Path(filepath)\n    relative_link = sym_path.read_text().strip()\n    relative = Path(relative_link)\n    relpath = sym_path.parent / relative\n    return relpath.resolve()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n    data_types = ['train', 'dev', 'test']\n    for dtype in data_types:\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        audio_dir = os.path.join(data_dir, dtype)\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for fname in filelist:\n                file_path = os.path.join(subfolder, fname)\n                if file_path.endswith('.wav'):\n                    audio_path = os.path.abspath(file_path)\n                    text_path = resolve_symlink(audio_path + '.trn')\n                else:\n                    continue\n\n                assert os.path.exists(audio_path) and os.path.exists(text_path)\n\n                audio_id = os.path.basename(audio_path)[:-4]\n                spk = audio_id.split('_')[0]\n\n                word_text, syllable_text, phone_text = read_trn(text_path)\n                audio_data, samplerate = soundfile.read(audio_path)\n                duration = float(len(audio_data) / samplerate)\n\n                # not dump alignment infos\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt': audio_id,\n                            'utt2spk': spk,\n                            'feat': audio_path,\n                            'feat_shape': (duration, ),  # second\n                            'text': word_text,  # character\n                            'syllable': syllable_text,\n                            'phone': phone_text,\n                        },\n                        ensure_ascii=False))\n\n                total_sec += duration\n                total_text += len(word_text)\n                total_num += 1\n\n        manifest_path = manifest_path_prefix + '.' + dtype\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n        manifest_dir = os.path.dirname(manifest_path_prefix)\n        meta_path = os.path.join(manifest_dir, dtype) + '.meta'\n        with open(meta_path, 'w') as f:\n            print(f\"{dtype}:\", file=f)\n            print(f\"{total_num} utts\", file=f)\n            print(f\"{total_sec / (60*60)} h\", file=f)\n            print(f\"{total_text} text\", file=f)\n            print(f\"{total_text / total_sec} text/sec\", file=f)\n            print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path, subset):\n    \"\"\"Download, unpack and create manifest file.\"\"\"\n    datadir = os.path.join(target_dir, subset)\n    if not os.path.exists(datadir):\n        filepath = download(url, md5sum, target_dir)\n        unpack(filepath, target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n\n    if subset == 'data_thchs30':\n        create_manifest(datadir, manifest_path)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    tasks = [\n        (DATA_URL, MD5_DATA, args.target_dir, args.manifest_prefix,\n         \"data_thchs30\"),\n        (TEST_NOISE_URL, MD5_TEST_NOISE, args.target_dir, args.manifest_prefix,\n         \"test-noise\"),\n        (RESOURCE_URL, MD5_RESOURCE, args.target_dir, args.manifest_prefix,\n         \"resource\"),\n    ]\n    with Pool(7) as pool:\n        pool.starmap(prepare_dataset, tasks)\n\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/timit/.gitignore",
    "content": "TIMIT.*\nTIMIT\nmanifest.*\n*.meta\n"
  },
  {
    "path": "dataset/timit/timit.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Librispeech ASR datasets.\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\nimport re\nimport string\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import unzip\n\nURL_ROOT = \"\"\nMD5_DATA = \"45c68037c7fdfe063a43c851f181fb2d\"\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default='~/.cache/paddle/dataset/speech/timit',\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n#: A string containing Chinese punctuation marks (non-stops).\nnon_stops = (\n    # Fullwidth ASCII variants\n    '\\uFF02\\uFF03\\uFF04\\uFF05\\uFF06\\uFF07\\uFF08\\uFF09\\uFF0A\\uFF0B\\uFF0C\\uFF0D'\n    '\\uFF0F\\uFF1A\\uFF1B\\uFF1C\\uFF1D\\uFF1E\\uFF20\\uFF3B\\uFF3C\\uFF3D\\uFF3E\\uFF3F'\n    '\\uFF40\\uFF5B\\uFF5C\\uFF5D\\uFF5E\\uFF5F\\uFF60'\n\n    # Halfwidth CJK punctuation\n    '\\uFF62\\uFF63\\uFF64'\n\n    # CJK symbols and punctuation\n    '\\u3000\\u3001\\u3003'\n\n    # CJK angle and corner brackets\n    '\\u3008\\u3009\\u300A\\u300B\\u300C\\u300D\\u300E\\u300F\\u3010\\u3011'\n\n    # CJK brackets and symbols/punctuation\n    '\\u3014\\u3015\\u3016\\u3017\\u3018\\u3019\\u301A\\u301B\\u301C\\u301D\\u301E\\u301F'\n\n    # Other CJK symbols\n    '\\u3030'\n\n    # Special CJK indicators\n    '\\u303E\\u303F'\n\n    # Dashes\n    '\\u2013\\u2014'\n\n    # Quotation marks and apostrophe\n    '\\u2018\\u2019\\u201B\\u201C\\u201D\\u201E\\u201F'\n\n    # General punctuation\n    '\\u2026\\u2027'\n\n    # Overscores and underscores\n    '\\uFE4F'\n\n    # Small form variants\n    '\\uFE51\\uFE54'\n\n    # Latin punctuation\n    '\\u00B7')\n\n#: A string of Chinese stops.\nstops = (\n    '\\uFF01'  # Fullwidth exclamation mark\n    '\\uFF1F'  # Fullwidth question mark\n    '\\uFF61'  # Halfwidth ideographic full stop\n    '\\u3002'  # Ideographic full stop\n)\n\n#: A string containing all Chinese punctuation.\npunctuation = non_stops + stops\n\n\ndef tn(text):\n    # lower text\n    text = text.lower()\n    # remove punc\n    text = re.sub(f'[{punctuation}{string.punctuation}]', \"\", text)\n    return text\n\n\ndef read_txt(filepath: str) -> str:\n    with open(filepath, 'r') as f:\n        line = f.read().strip().split(maxsplit=2)[2]\n        return tn(line)\n\n\ndef read_algin(filepath: str) -> str:\n    \"\"\"read word or phone alignment file.\n    <start-sample> <end-sample> <token><newline>\n    \n    Args:\n        filepath (str): [description]\n\n    Returns:\n        str: token separate by <space>\n    \"\"\"\n    aligns = []  # (start, end, token)\n    with open(filepath, 'r') as f:\n        for line in f:\n            items = line.strip().split()\n            # for phone: (Note: beginning and ending silence regions are marked with h#)\n            if items[2].strip() == 'h#':\n                continue\n            aligns.append(items)\n    return ' '.join([item[2] for item in aligns])\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    \"\"\"Create a manifest json file summarizing the data set, with each line\n    containing the meta data (i.e. audio filepath, transcription text, audio\n    duration) of each audio file within the data set.\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n    utts = set()\n\n    data_types = ['TRAIN', 'TEST']\n    for dtype in data_types:\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        audio_dir = Path(os.path.join(data_dir, dtype))\n        for fname in sorted(audio_dir.rglob('*.WAV')):\n            audio_path = fname.resolve()  # .WAV\n            audio_id = audio_path.stem\n            # if uttid exits,  then skipped\n            if audio_id in utts:\n                continue\n\n            utts.add(audio_id)\n            text_path = audio_path.with_suffix('.TXT')\n            phone_path = audio_path.with_suffix('.PHN')\n            word_path = audio_path.with_suffix('.WRD')\n\n            audio_data, samplerate = soundfile.read(\n                str(audio_path), dtype='int16')\n            duration = float(len(audio_data) / samplerate)\n            word_text = read_txt(text_path)\n            phone_text = read_algin(phone_path)\n\n            gender_spk = str(audio_path.parent.stem)\n            spk = gender_spk[1:]\n            gender = gender_spk[0]\n            utt_id = '_'.join([spk, gender, audio_id])\n            # not dump alignment infos\n            json_lines.append(\n                json.dumps(\n                    {\n                        'utt': utt_id,\n                        'utt2spk': spk,\n                        'utt2gender': gender,\n                        'feat': str(audio_path),\n                        'feat_shape': (duration, ),  # second\n                        'text': word_text,  # word\n                        'phone': phone_text,\n                    },\n                    ensure_ascii=False))\n\n            total_sec += duration\n            total_text += len(word_text.split())\n            total_num += 1\n\n        manifest_path = manifest_path_prefix + '.' + dtype.lower()\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n        manifest_dir = os.path.dirname(manifest_path_prefix)\n        meta_path = os.path.join(manifest_dir, dtype.lower()) + '.meta'\n        with open(meta_path, 'w') as f:\n            print(f\"{dtype}:\", file=f)\n            print(f\"{total_num} utts\", file=f)\n            print(f\"{total_sec / (60*60)} h\", file=f)\n            print(f\"{total_text} text\", file=f)\n            print(f\"{total_text / total_sec} text/sec\", file=f)\n            print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path):\n    \"\"\"Download, unpack and create summary manifest file.\n    \"\"\"\n    filepath = os.path.join(target_dir, \"TIMIT.zip\")\n    if not os.path.exists(filepath):\n        print(f\"Please download TIMIT.zip into {target_dir}.\")\n        raise FileNotFoundError\n\n    if not os.path.exists(os.path.join(target_dir, \"TIMIT\")):\n        # check md5sum\n        assert check_md5sum(filepath, md5sum)\n        # unpack\n        unzip(filepath, target_dir)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n    # create manifest json file\n    create_manifest(os.path.join(target_dir, \"TIMIT\"), manifest_path)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    prepare_dataset(URL_ROOT, MD5_DATA, args.target_dir, args.manifest_prefix)\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/timit/timit_kaldi_standard_split.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare TIMIT dataset (Standard split from Kaldi)\n\nCreate manifest files from splited dataset.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\nfrom pathlib import Path\n\nimport soundfile\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--src_dir\",\n    default=\"\",\n    type=str,\n    help=\"Directory to kaldi splited data. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n\n    data_types = ['train', 'dev', 'test']\n    for dtype in data_types:\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        phn_path = os.path.join(data_dir, dtype + '.text')\n        phn_dict = {}\n        for line in codecs.open(phn_path, 'r', 'utf-8'):\n            line = line.strip()\n            if line == '':\n                continue\n            audio_id, text = line.split(' ', 1)\n            phn_dict[audio_id] = text\n\n        audio_dir = os.path.join(data_dir, dtype + '_sph.scp')\n        for line in codecs.open(audio_dir, 'r', 'utf-8'):\n            audio_id, audio_path = line.strip().split()\n            # if no transcription for audio then raise error\n            assert audio_id in phn_dict\n            audio_data, samplerate = soundfile.read(audio_path)\n            duration = float(len(audio_data) / samplerate)\n            text = phn_dict[audio_id]\n\n            gender_spk = str(Path(audio_path).parent.stem)\n            spk = gender_spk[1:]\n            gender = gender_spk[0]\n            utt_id = '_'.join([spk, gender, audio_id])\n            json_lines.append(\n                json.dumps(\n                    {\n                        'utt': audio_id,\n                        'utt2spk': spk,\n                        'utt2gender': gender,\n                        'feat': audio_path,\n                        'feat_shape': (duration, ),  # second\n                        'text': text\n                    },\n                    ensure_ascii=False))\n\n            total_sec += duration\n            total_text += len(text)\n            total_num += 1\n\n        manifest_path = manifest_path_prefix + '.' + dtype + '.raw'\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n\ndef prepare_dataset(src_dir, manifest_path=None):\n    \"\"\"create manifest file.\"\"\"\n    if os.path.isdir(manifest_path):\n        manifest_path = os.path.join(manifest_path, 'manifest')\n    if manifest_path:\n        create_manifest(src_dir, manifest_path)\n\n\ndef main():\n    if args.src_dir.startswith('~'):\n        args.src_dir = os.path.expanduser(args.src_dir)\n\n    prepare_dataset(src_dir=args.src_dir, manifest_path=args.manifest_prefix)\n\n    print(\"manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/voxceleb/README.md",
    "content": "# [VoxCeleb](http://www.robots.ox.ac.uk/~vgg/data/voxceleb/)\nVoxCeleb is an audio-visual dataset consisting of short clips of human speech, extracted from interview videos uploaded to YouTube。\n\nVoxCeleb contains speech from speakers spanning a wide range of different ethnicities, accents, professions and ages.\nAll speaking face-tracks are captured \"in the wild\", with background chatter, laughter, overlapping speech, pose variation and different lighting conditions.\nVoxCeleb consists of both audio and video. Each segment is at least 3 seconds long.\n\nThe dataset consists of two versions, VoxCeleb1 and VoxCeleb2. Each version has it's own train/test split. For each we provide YouTube URLs, face detections and tracks, audio files, cropped face videos and speaker meta-data. There is no overlap between the two versions.\n\nmore info in details refers to http://www.robots.ox.ac.uk/~vgg/data/voxceleb/\n"
  },
  {
    "path": "dataset/voxceleb/voxceleb1.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare VoxCeleb1 dataset\n\ncreate manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\nresearchers should download the voxceleb1 dataset yourselves\nthrough google form to get the username & password and unpack the data\n\"\"\"\nimport argparse\nimport codecs\nimport glob\nimport json\nimport os\nimport subprocess\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import check_md5sum\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unzip\n\n# all the data will be download in the current data/voxceleb directory default\nDATA_HOME = os.path.expanduser('.')\n\n# if you use the http://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a/ as the download base url\n# you need to get the username & password via the google form\n\n# if you use the https://thor.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a as the download base url,\n# you need use --no-check-certificate to connect the target download url \n\nBASE_URL = \"https://thor.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a\"\n\n# dev data\nDEV_LIST = {\n    \"vox1_dev_wav_partaa\": \"e395d020928bc15670b570a21695ed96\",\n    \"vox1_dev_wav_partab\": \"bbfaaccefab65d82b21903e81a8a8020\",\n    \"vox1_dev_wav_partac\": \"017d579a2a96a077f40042ec33e51512\",\n    \"vox1_dev_wav_partad\": \"7bb1e9f70fddc7a678fa998ea8b3ba19\",\n}\nDEV_TARGET_DATA = \"vox1_dev_wav_parta* vox1_dev_wav.zip ae63e55b951748cc486645f532ba230b\"\n\n# test data\nTEST_LIST = {\"vox1_test_wav.zip\": \"185fdc63c3c739954633d50379a3d102\"}\nTEST_TARGET_DATA = \"vox1_test_wav.zip vox1_test_wav.zip 185fdc63c3c739954633d50379a3d102\"\n\n# voxceleb trial\n\nTRIAL_BASE_URL = \"https://www.robots.ox.ac.uk/~vgg/data/voxceleb/meta/\"\nTRIAL_LIST = {\n    \"veri_test.txt\": \"29fc7cc1c5d59f0816dc15d6e8be60f7\",  # voxceleb1\n    \"veri_test2.txt\": \"b73110731c9223c1461fe49cb48dddfc\",  # voxceleb1(cleaned)\n    \"list_test_hard.txt\": \"21c341b6b2168eea2634df0fb4b8fff1\",  # voxceleb1-H\n    \"list_test_hard2.txt\":\n    \"857790e09d579a68eb2e339a090343c8\",  # voxceleb1-H(cleaned)\n    \"list_test_all.txt\": \"b9ecf7aa49d4b656aa927a8092844e4a\",  # voxceleb1-E\n    \"list_test_all2.txt\":\n    \"a53e059deb562ffcfc092bf5d90d9f3a\"  # voxceleb1-E(cleaned)\n}\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/voxceleb1/\",\n    type=str,\n    help=\"Directory to save the voxceleb1 dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\n\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(f\"Creating manifest {manifest_path_prefix} from {data_dir}\")\n    json_lines = []\n    data_path = os.path.join(data_dir, \"wav\", \"**\", \"*.wav\")\n    total_sec = 0.0\n    total_text = 0.0\n    total_num = 0\n    speakers = set()\n    for audio_path in glob.glob(data_path, recursive=True):\n        audio_id = \"-\".join(audio_path.split(\"/\")[-3:])\n        utt2spk = audio_path.split(\"/\")[-3]\n        duration = soundfile.info(audio_path).duration\n        text = \"\"\n        json_lines.append(\n            json.dumps(\n                {\n                    \"utt\": audio_id,\n                    \"utt2spk\": str(utt2spk),\n                    \"feat\": audio_path,\n                    \"feat_shape\": (duration, ),\n                    \"text\": text  # compatible with asr data format\n                },\n                ensure_ascii=False))\n\n        total_sec += duration\n        total_text += len(text)\n        total_num += 1\n        speakers.add(utt2spk)\n\n    # data_dir_name refer to dev or test\n    # voxceleb1 is given explicit in the path\n    data_dir_name = Path(data_dir).name\n    manifest_path_prefix = manifest_path_prefix + \".\" + data_dir_name\n    if not os.path.exists(os.path.dirname(manifest_path_prefix)):\n        os.makedirs(os.path.dirname(manifest_path_prefix))\n\n    with codecs.open(manifest_path_prefix, 'w', encoding='utf-8') as f:\n        for line in json_lines:\n            f.write(line + \"\\n\")\n\n    manifest_dir = os.path.dirname(manifest_path_prefix)\n    meta_path = os.path.join(manifest_dir, \"voxceleb1.\" +\n                             data_dir_name) + \".meta\"\n    with codecs.open(meta_path, 'w', encoding='utf-8') as f:\n        print(f\"{total_num} utts\", file=f)\n        print(f\"{len(speakers)} speakers\", file=f)\n        print(f\"{total_sec / (60 * 60)} h\", file=f)\n        print(f\"{total_text} text\", file=f)\n        print(f\"{total_text / total_sec} text/sec\", file=f)\n        print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(base_url, data_list, target_dir, manifest_path,\n                    target_data):\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n\n    # wav directory already exists, it need do nothing\n    # we will download the voxceleb1 data to ${target_dir}/vox1/dev/ or ${target_dir}/vox1/test directory \n    if not os.path.exists(os.path.join(target_dir, \"wav\")):\n        # download all dataset part\n        print(f\"start to download the vox1 zip package to {target_dir}\")\n        for zip_part in data_list.keys():\n            download_url = \" --no-check-certificate \" + base_url + \"/\" + zip_part\n            download(\n                url=download_url,\n                md5sum=data_list[zip_part],\n                target_dir=target_dir)\n\n        # pack the all part to target zip file\n        all_target_part, target_name, target_md5sum = target_data.split()\n        target_name = os.path.join(target_dir, target_name)\n        if not os.path.exists(target_name):\n            pack_part_cmd = \"cat {}/{} > {}\".format(target_dir, all_target_part,\n                                                    target_name)\n            subprocess.call(pack_part_cmd, shell=True)\n\n        # check the target zip file md5sum\n        if not check_md5sum(target_name, target_md5sum):\n            raise RuntimeError(\"{} MD5 checksum failed\".format(target_name))\n        else:\n            print(\"Check {} md5sum successfully\".format(target_name))\n\n        # unzip the all zip file\n        if target_name.endswith(\".zip\"):\n            unzip(target_name, target_dir)\n\n    # create the manifest file\n    create_manifest(data_dir=target_dir, manifest_path_prefix=manifest_path)\n\n\ndef prepare_trial(base_url, data_list, target_dir):\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n\n    for trial, md5sum in data_list.items():\n        target_trial = os.path.join(target_dir, trial)\n        if not os.path.exists(os.path.join(target_dir, trial)):\n            download_url = \" --no-check-certificate \" + base_url + \"/\" + trial\n            download(url=download_url, md5sum=md5sum, target_dir=target_dir)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    # prepare the vox1 dev data\n    prepare_dataset(\n        base_url=BASE_URL,\n        data_list=DEV_LIST,\n        target_dir=os.path.join(args.target_dir, \"dev\"),\n        manifest_path=args.manifest_prefix,\n        target_data=DEV_TARGET_DATA)\n\n    # prepare the vox1 test data\n    prepare_dataset(\n        base_url=BASE_URL,\n        data_list=TEST_LIST,\n        target_dir=os.path.join(args.target_dir, \"test\"),\n        manifest_path=args.manifest_prefix,\n        target_data=TEST_TARGET_DATA)\n\n    # prepare the vox1 trial\n    prepare_trial(\n        base_url=TRIAL_BASE_URL,\n        data_list=TRIAL_LIST,\n        target_dir=os.path.dirname(args.manifest_prefix))\n\n    print(\"Manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/voxceleb/voxceleb2.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare VoxCeleb2 dataset\n\nDownload and unpack the voxceleb2 data files.\nVoxceleb2 data is stored as the m4a format, \nso we need convert the m4a to wav with the convert.sh scripts\n\"\"\"\nimport argparse\nimport codecs\nimport glob\nimport json\nimport os\nimport subprocess\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import check_md5sum\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unzip\n\n# all the data will be download in the current data/voxceleb directory default\nDATA_HOME = os.path.expanduser('.')\n\nBASE_URL = \"--no-check-certificate https://www.robots.ox.ac.uk/~vgg/data/voxceleb/data/\"\n\n# dev data\nDEV_LIST = {\n    \"vox2_dev_aac_partaa\": \"da070494c573e5c0564b1d11c3b20577\",\n    \"vox2_dev_aac_partab\": \"17fe6dab2b32b48abaf1676429cdd06f\",\n    \"vox2_dev_aac_partac\": \"1de58e086c5edf63625af1cb6d831528\",\n    \"vox2_dev_aac_partad\": \"5a043eb03e15c5a918ee6a52aad477f9\",\n    \"vox2_dev_aac_partae\": \"cea401b624983e2d0b2a87fb5d59aa60\",\n    \"vox2_dev_aac_partaf\": \"fc886d9ba90ab88e7880ee98effd6ae9\",\n    \"vox2_dev_aac_partag\": \"d160ecc3f6ee3eed54d55349531cb42e\",\n    \"vox2_dev_aac_partah\": \"6b84a81b9af72a9d9eecbb3b1f602e65\",\n}\n\nDEV_TARGET_DATA = \"vox2_dev_aac_parta* vox2_dev_aac.zip bbc063c46078a602ca71605645c2a402\"\n\n# test data\nTEST_LIST = {\"vox2_test_aac.zip\": \"0d2b3ea430a821c33263b5ea37ede312\"}\nTEST_TARGET_DATA = \"vox2_test_aac.zip vox2_test_aac.zip 0d2b3ea430a821c33263b5ea37ede312\"\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/voxceleb2/\",\n    type=str,\n    help=\"Directory to save the voxceleb1 dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nparser.add_argument(\n    \"--download\",\n    default=False,\n    action=\"store_true\",\n    help=\"Download the voxceleb2 dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--generate\",\n    default=False,\n    action=\"store_true\",\n    help=\"Generate the manifest files. (default: %(default)s)\")\n\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    \"\"\"Generate the voxceleb2 dataset manifest file.\n    We will create the ${manifest_path_prefix}.vox2 as the final manifest file \n    The dev and test wav info will be put in one manifest file.\n\n    Args:\n        data_dir (str): voxceleb2 wav directory, which include dev and test subdataset\n        manifest_path_prefix (str): manifest file prefix\n    \"\"\"\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n    data_path = os.path.join(data_dir, \"**\", \"*.wav\")\n    total_sec = 0.0\n    total_text = 0.0\n    total_num = 0\n    speakers = set()\n    for audio_path in glob.glob(data_path, recursive=True):\n        audio_id = \"-\".join(audio_path.split(\"/\")[-3:])\n        utt2spk = audio_path.split(\"/\")[-3]\n        duration = soundfile.info(audio_path).duration\n        text = \"\"\n        json_lines.append(\n            json.dumps(\n                {\n                    \"utt\": audio_id,\n                    \"utt2spk\": str(utt2spk),\n                    \"feat\": audio_path,\n                    \"feat_shape\": (duration, ),\n                    \"text\": text  # compatible with asr data format\n                },\n                ensure_ascii=False))\n\n        total_sec += duration\n        total_text += len(text)\n        total_num += 1\n        speakers.add(utt2spk)\n\n    # data_dir_name refer to dev or test\n    # voxceleb2 is given explicit in the path\n    data_dir_name = Path(data_dir).name\n    manifest_path_prefix = manifest_path_prefix + \".\" + data_dir_name\n\n    if not os.path.exists(os.path.dirname(manifest_path_prefix)):\n        os.makedirs(os.path.dirname(manifest_path_prefix))\n    with codecs.open(manifest_path_prefix, 'w', encoding='utf-8') as f:\n        for line in json_lines:\n            f.write(line + \"\\n\")\n\n    manifest_dir = os.path.dirname(manifest_path_prefix)\n    meta_path = os.path.join(manifest_dir, \"voxceleb2.\" +\n                             data_dir_name) + \".meta\"\n    with codecs.open(meta_path, 'w', encoding='utf-8') as f:\n        print(f\"{total_num} utts\", file=f)\n        print(f\"{len(speakers)} speakers\", file=f)\n        print(f\"{total_sec / (60 * 60)} h\", file=f)\n        print(f\"{total_text} text\", file=f)\n        print(f\"{total_text / total_sec} text/sec\", file=f)\n        print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef download_dataset(base_url, data_list, target_data, target_dir, dataset):\n    \"\"\"Download the voxceleb2 zip package\n\n    Args:\n        base_url (str): the voxceleb2 dataset download baseline url\n        data_list (dict): the dataset part zip package and the md5 value\n        target_data (str): the final dataset zip info\n        target_dir (str): the dataset stored directory\n        dataset (str): the dataset name, dev or test\n\n    Raises:\n        RuntimeError: the md5sum occurs error\n    \"\"\"\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n\n    # wav directory already exists, it need do nothing\n    print(\"target dir {}\".format(os.path.join(target_dir, dataset)))\n    # unzip the dev dataset will create the dev and unzip the m4a to dev dir\n    # but the test dataset will unzip to aac\n    # so, wo create the ${target_dir}/test and unzip the m4a to test dir\n    if not os.path.exists(os.path.join(target_dir, dataset)):\n        print(f\"start to download the vox2 zip package to {target_dir}\")\n        for zip_part in data_list.keys():\n            download_url = \" --no-check-certificate \" + base_url + \"/\" + zip_part\n            download(\n                url=download_url,\n                md5sum=data_list[zip_part],\n                target_dir=target_dir)\n\n        # pack the all part to target zip file\n        all_target_part, target_name, target_md5sum = target_data.split()\n        target_name = os.path.join(target_dir, target_name)\n        if not os.path.exists(target_name):\n            pack_part_cmd = \"cat {}/{} > {}\".format(target_dir, all_target_part,\n                                                    target_name)\n            subprocess.call(pack_part_cmd, shell=True)\n\n        # check the target zip file md5sum\n        if not check_md5sum(target_name, target_md5sum):\n            raise RuntimeError(\"{} MD5 checksum failed\".format(target_name))\n        else:\n            print(\"Check {} md5sum successfully\".format(target_name))\n\n        if dataset == \"test\":\n            # we need make the test directory\n            unzip(target_name, os.path.join(target_dir, \"test\"))\n        else:\n            # unzip dev zip package and will create the dev directory\n            unzip(target_name, target_dir)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    # download and unpack the vox2-dev data\n    print(\"download: {}\".format(args.download))\n    if args.download:\n        download_dataset(\n            base_url=BASE_URL,\n            data_list=DEV_LIST,\n            target_data=DEV_TARGET_DATA,\n            target_dir=args.target_dir,\n            dataset=\"dev\")\n\n        download_dataset(\n            base_url=BASE_URL,\n            data_list=TEST_LIST,\n            target_data=TEST_TARGET_DATA,\n            target_dir=args.target_dir,\n            dataset=\"test\")\n\n        print(\"VoxCeleb2 download is done!\")\n\n    if args.generate:\n        create_manifest(\n            args.target_dir, manifest_path_prefix=args.manifest_prefix)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "dataset/voxforge/run_data.sh",
    "content": "#! /usr/bin/env bash\n\nTARGET_DIR=${MAIN_ROOT}/dataset/voxforge\nmkdir -p ${TARGET_DIR}\n\n# download data, generate manifests\npython ${MAIN_ROOT}/dataset/voxforge/voxforge.py \\\n--manifest_prefix=\"${TARGET_DIR}/manifest\" \\\n--target_dir=\"${TARGET_DIR}\" \\\n--is_merge_dialect=True \\\n--dialects 'american' 'british' 'australian' 'european' 'irish' 'canadian' 'indian'\n\nif [ $? -ne 0 ]; then\n    echo \"Prepare VoxForge failed. Terminated.\"\n    exit 1\nfi\n\necho \"VoxForge Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "dataset/voxforge/voxforge.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare VoxForge dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport datetime\nimport json\nimport os\nimport shutil\nimport subprocess\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download_multi\nfrom paddlespeech.dataset.download import getfile_insensitive\nfrom paddlespeech.dataset.download import unpack\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nDATA_URL = 'http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/' \\\n           'Audio/Main/16kHz_16bit'\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/VoxForge\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--dialects\",\n    default=[\n        'american', 'british', 'australian', 'european', 'irish', 'canadian',\n        'indian'\n    ],\n    nargs='+',\n    type=str,\n    help=\"Dialect types. (default: %(default)s)\")\nparser.add_argument(\n    \"--is_merge_dialect\",\n    default=True,\n    type=bool,\n    help=\"If set True, manifests of american dialect and canadian dialect will \"\n    \"be merged to american-canadian dialect; manifests of british \"\n    \"dialect, irish dialect and australian dialect will be merged to \"\n    \"commonwealth dialect. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef download_and_unpack(target_dir, url):\n    wget_args = '-q -l 1 -N -nd -c -e robots=off -A tgz -r -np'\n    tgz_dir = os.path.join(target_dir, 'tgz')\n    exit_code = download_multi(url, tgz_dir, wget_args)\n    if exit_code != 0:\n        print('Download tgz audio files failed with exit code %d.' % exit_code)\n    else:\n        print('Download done, start unpacking ...')\n        audio_dir = os.path.join(target_dir, 'audio')\n        for root, dirs, files in os.walk(tgz_dir):\n            for file in files:\n                print(file)\n                if file.endswith('.tgz'):\n                    unpack(os.path.join(root, file), audio_dir)\n\n\ndef select_dialects(target_dir, dialect_list):\n    \"\"\"Classify audio files by dialect.\"\"\"\n    dialect_root_dir = os.path.join(target_dir, 'dialect')\n    if os.path.exists(dialect_root_dir):\n        shutil.rmtree(dialect_root_dir)\n    os.mkdir(dialect_root_dir)\n    audio_dir = os.path.abspath(os.path.join(target_dir, 'audio'))\n    for dialect in dialect_list:\n        # filter files by dialect\n        command = 'find %s -iwholename \"*etc/readme*\" -exec egrep -iHl \\\n            \"pronunciation dialect.*%s\" {} \\;' % (audio_dir, dialect)\n        p = subprocess.Popen(\n            command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)\n        output, err = p.communicate()\n        dialect_dir = os.path.join(dialect_root_dir, dialect)\n        if os.path.exists(dialect_dir):\n            shutil.rmtree(dialect_dir)\n        os.mkdir(dialect_dir)\n        for path in output.splitlines():\n            src_dir = os.path.dirname(os.path.dirname(path))\n            link = os.path.basename(os.path.normpath(src_dir))\n            os.symlink(src_dir, os.path.join(dialect_dir, link))\n\n\ndef generate_manifest(data_dir, manifest_path):\n    json_lines = []\n\n    for path in os.listdir(data_dir):\n        audio_link = os.path.join(data_dir, path)\n        assert os.path.islink(\n            audio_link), '%s should be symbolic link.' % audio_link\n        actual_audio_dir = os.path.abspath(os.readlink(audio_link))\n\n        audio_type = ''\n        if os.path.isdir(os.path.join(actual_audio_dir, 'wav')):\n            audio_type = 'wav'\n        elif os.path.isdir(os.path.join(actual_audio_dir, 'flac')):\n            audio_type = 'flac'\n        else:\n            print('Unknown audio type, skipped processing %s.' %\n                  actual_audio_dir)\n            continue\n\n        etc_dir = os.path.join(actual_audio_dir, 'etc')\n        prompts_file = os.path.join(etc_dir, 'PROMPTS')\n        if not os.path.isfile(prompts_file):\n            print('PROMPTS file missing, skip processing %s.' %\n                  actual_audio_dir)\n            continue\n\n        readme_file = getfile_insensitive(os.path.join(etc_dir, 'README'))\n        if readme_file is None:\n            print('README file missing, skip processing %s.' % actual_audio_dir)\n            continue\n\n        for line in file(prompts_file):\n            u, trans = line.strip().split(None, 1)\n            u_parts = u.split('/')\n\n            # try to format the date time\n            try:\n                speaker, date, sfx = u_parts[-3].split('-')\n                obj = datetime.datetime.strptime(date, '%y.%m.%d')\n                formatted = obj.strftime('%Y%m%d')\n                u_parts[-3] = '-'.join([speaker, formatted, sfx])\n            except Exception as e:\n                pass\n\n            if len(u_parts) < 2:\n                u_parts = [audio_type] + u_parts\n            u_parts[-2] = audio_type\n            u_parts[-1] += '.' + audio_type\n            u = os.path.join(actual_audio_dir, '/'.join(u_parts[-2:]))\n\n            if not os.path.isfile(u):\n                print('Audio file missing, skip processing %s.' % u)\n                continue\n\n            if os.stat(u).st_size == 0:\n                print('Empty audio file, skip processing %s.' % u)\n                continue\n\n            trans = trans.strip().replace('-', ' ')\n            if not trans.isupper() or \\\n                not trans.strip().replace(' ', '').replace(\"'\", \"\").isalpha():\n                print(\"Transcript not normalized properly, skip processing %s.\"\n                      % u)\n                continue\n\n            audio_data, samplerate = soundfile.read(u)\n            duration = float(len(audio_data)) / samplerate\n\n            utt = os.path.splitext(os.path.basename(u))[0]\n            json_lines.append(\n                json.dumps({\n                    'utt': utt,\n                    'utt2spk': speaker,\n                    'feat': u,\n                    'feat_shape': (duration, ),  #second\n                    'text': trans.lower()\n                }))\n\n    with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n        for line in json_lines:\n            fout.write(line + '\\n')\n\n\ndef merge_manifests(manifest_files, save_path):\n    lines = []\n    for manifest_file in manifest_files:\n        line = codecs.open(manifest_file, 'r', 'utf-8').readlines()\n        lines += line\n\n    with codecs.open(save_path, 'w', 'utf-8') as fout:\n        for line in lines:\n            fout.write(line)\n\n\ndef prepare_dataset(url, dialects, target_dir, manifest_prefix, is_merge):\n    download_and_unpack(target_dir, url)\n    select_dialects(target_dir, dialects)\n    american_canadian_manifests = []\n    commonwealth_manifests = []\n    for dialect in dialects:\n        dialect_dir = os.path.join(target_dir, 'dialect', dialect)\n        manifest_fpath = manifest_prefix + '.' + dialect\n        if dialect == 'american' or dialect == 'canadian':\n            american_canadian_manifests.append(manifest_fpath)\n        if dialect == 'australian' \\\n                or dialect == 'british' \\\n                or dialect == 'irish':\n            commonwealth_manifests.append(manifest_fpath)\n        generate_manifest(dialect_dir, manifest_fpath)\n\n    if is_merge:\n        if len(american_canadian_manifests) > 0:\n            manifest_fpath = manifest_prefix + '.american-canadian'\n            merge_manifests(american_canadian_manifests, manifest_fpath)\n        if len(commonwealth_manifests) > 0:\n            manifest_fpath = manifest_prefix + '.commonwealth'\n            merge_manifests(commonwealth_manifests, manifest_fpath)\n\n\ndef main():\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    prepare_dataset(DATA_URL, args.dialects, args.target_dir,\n                    args.manifest_prefix, args.is_merge_dialect)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "demos/README.md",
    "content": "# Speech Application based on PaddleSpeech\n\n([简体中文](./README_cn.md)|English)\n\nThis directory contains many speech applications in multiple scenarios.\n\n* audio searching - mass audio similarity retrieval\n* audio tagging - multi-label tagging of an audio file\n* automatic_video_subtitles - generate subtitles from a video\n* metaverse - 2D AR with TTS  \n* punctuation_restoration - restore punctuation from raw text\n* speech recognition - recognize text of an audio file \n* speech server - Server for Speech Task, e.g. ASR,TTS,CLS\n* streaming asr server - receive audio stream from websocket, and recognize to transcript.\n* streaming tts server - receive text from http or websocket, and streaming audio data stream.\n* speech translation - end to end speech translation  \n* story talker - book reader based on OCR and TTS  \n* style_fs2 - multi style control for FastSpeech2 model  \n* text_to_speech - convert text into speech \n* self supervised pretraining - speech feature extraction and speech recognition based on wav2vec2\n* Whisper - speech recognize and translate based on Whisper model\n"
  },
  {
    "path": "demos/README_cn.md",
    "content": "# PaddleSpeech 语音应用 Demo\n\n(简体中文|[English](./README.md))\n\n该目录包含基于 PaddleSpeech 开发的不同场景的语音应用 Demo：\n\n* 声音检索 - 海量音频相似性检索。\n* 声音分类 - 基于 AudioSet 的 527 类标签的音频多标签分类。 \n* 视频字幕生成 - 识别视频中语音的文本，并进行文本后处理。\n* 元宇宙 - 基于语音合成的 2D 增强现实。\n* 标点恢复 - 通常作为语音识别的文本后处理任务，为一段无标点的纯文本添加相应的标点符号。\n* 语音识别 - 识别一段音频中包含的语音文字。\n* 语音服务 - 离线语音服务，包括ASR、TTS、CLS等。\n* 流式语音识别服务 - 流式输入语音数据流识别音频中的文字。\n* 流式语音合成服务 - 根据待合成文本流式生成合成音频数据流。\n* 语音翻译 - 实时识别音频中的语言，并同时翻译成目标语言。\n* 会说话的故事书 - 基于 OCR 和语音合成的会说话的故事书。\n* 个性化语音合成 - 基于 FastSpeech2 模型的个性化语音合成。 \n* 语音合成 - 基于给定的文本生成语音音频。\n* 自监督预训练模型 - 基于wav2vec2的语音特征提取和语音识别。\n* Whisper - 基于Whisper模型的语音识别与翻译。\n"
  },
  {
    "path": "demos/TTSAndroid/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "demos/TTSAndroid/README.md",
    "content": "# 语音合成 Java API Demo 使用指南\n\n在 Android 上实现语音合成功能，此 Demo 有很好的易用性和开放性，如在 Demo 中跑自己训练好的模型等。\n\n本文主要介绍语音合成 Demo 运行方法。\n\n## 如何运行语音合成 Demo\n\n### 环境准备\n\n1. 在本地环境安装好 Android Studio 工具，详细安装方法请见 [Android Studio 官网](https://developer.android.com/studio)。\n2. 准备一部 Android 手机，并开启 USB 调试模式。开启方法: `手机设置 -> 查找开发者选项 -> 打开开发者选项和 USB 调试模式`。\n\n**注意**：\n> 如果您的 Android Studio 尚未配置 NDK ，请根据 Android Studio 用户指南中的[安装及配置 NDK 和 CMake ](https://developer.android.com/studio/projects/install-ndk)内容，预先配置好 NDK 。您可以选择最新的 NDK 版本，或者使用 Paddle Lite 预测库版本一样的 NDK。\n\n### 部署步骤\n\n1. 用 Android Studio 打开 TTSAndroid 工程。\n2. 手机连接电脑，打开 USB 调试和文件传输模式，并在 Android Studio 上连接自己的手机设备（手机需要开启允许从 USB 安装软件权限）。\n\n**注意：**\n>1. 如果您在导入项目、编译或者运行过程中遇到 NDK 配置错误的提示，请打开 `File > Project Structure > SDK Location`，修改 `Android NDK location` 为您本机配置的 NDK 所在路径。\n>2. 如果您是通过 Android Studio 的 SDK Tools 下载的 NDK (见本章节\"环境准备\")，可以直接点击下拉框选择默认路径。\n>3. 还有一种 NDK 配置方法，你可以在 `TTSAndroid/local.properties` 文件中手动添加 NDK 路径配置 `nkd.dir=/root/android-ndk-r20b`\n>4. 如果以上步骤仍旧无法解决 NDK 配置错误，请尝试根据 Android Studio 官方文档中的[更新 Android Gradle 插件](https://developer.android.com/studio/releases/gradle-plugin?hl=zh-cn#updating-plugin)章节，尝试更新 Android Gradle plugin 版本。\n\n3. 点击 Run 按钮，自动编译 APP 并安装到手机。(该过程会自动下载 Paddle Lite 预测库和模型，需要联网)\n   成功后效果如下：\n    - pic 1：APP 安装到手机。\n    - pic 2：APP 打开后的效果，在下拉框中选择待合成的文本。\n    - pic 3：合成后点击按钮播放音频。\n\n<p align=\"center\"><img width=\"350\" height=\"500\"  src=\"https://user-images.githubusercontent.com/24568452/204450217-d166588a-5341-4565-8662-0f8129284bba.png\"/><img width=\"350\" height=\"500\" src=\"https://user-images.githubusercontent.com/24568452/204450231-d6f3105c-276a-4af5-a3ba-864d9f5ee24e.png\"/><img width=\"350\" height=\"500\" src=\"https://user-images.githubusercontent.com/24568452/204450269-0ddf46ec-eedd-4c90-8a0d-e915622fdf3e.png\"/></p>\n\n## 更新预测库\n\n* Paddle Lite\n  项目：[https://github.com/PaddlePaddle/Paddle-Lite](https://github.com/PaddlePaddle/Paddle-Lite)。\n\n\n参考 [Paddle Lite 源码编译文档](https://www.paddlepaddle.org.cn/lite/v2.11/source_compile/compile_env.html)，编译\nAndroid 预测库。\n\n* 编译最终产物位于 `build.lite.xxx.xxx.xxx` 下的 `inference_lite_lib.xxx.xxx`\n* 替换 java 库\n    * jar 包\n      将生成的 `build.lite.android.xxx.gcc/inference_lite_lib.android.xxx/java/jar/PaddlePredictor.jar`\n      替换 Demo 中的 `TTSAndroid/app/libs/PaddlePredictor.jar`。\n    * Java so\n        * arm64-v8a\n          将生成的 `build.lite.android.armv8.gcc/inference_lite_lib.android.armv8/java/so/libpaddle_lite_jni.so`\n          库替换 Demo 中的 `TTSAndroid/app/src/main/jniLibs/arm64-v8a/libpaddle_lite_jni.so`。\n\n## Demo 内容介绍\n\n先整体介绍下目标检测 Demo 的代码结构，然后介绍 Java 各功能模块的功能。\n\n<p align=\"center\">\n<img width=\"442\" alt=\"image\" src=\"https://user-images.githubusercontent.com/24568452/204455080-4f96fe55-6058-4235-bb92-cc98cfcc8bb6.png\">\n</p>\n\n### 重点关注内容\n\n1. `Predictor.java`： 预测代码。\n\n```bash\n# 位置：\nTTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/Predictor.java\n```\n\n2. `fastspeech2_csmsc_arm.nb`  和 `mb_melgan_csmsc_arm.nb`: 模型文件 (opt 工具转化后 Paddle Lite 模型)\n   ，分别来自 [fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip)\n   和 [mb_melgan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_pdlite_1.3.0.zip)。\n\n```bash\n# 位置：\nTTSAndroid/app/src/main/assets/models/cpu/fastspeech2_csmsc_arm.nb\nTTSAndroid/app/src/main/assets/models/cpu/mb_melgan_csmsc_arm.nb\n```\n\n3. `libpaddle_lite_jni.so`、`PaddlePredictor.jar`：Paddle Lite Java 预测库与 jar 包。\n\n```bash\n# 位置\nTTSAndroid/app/src/main/jniLibs/arm64-v8a/libpaddle_lite_jni.so\nTTSAndroid/app/libs/PaddlePredictor.jar\n```\n\n> 如果要替换动态库 so 和 jar 文件，则将新的动态库 so 更新到 `TTSAndroid/app/src/main/jniLibs/arm64-v8a/` 目录下 新的 jar 文件更新到 `TTSAndroid/app/libs/` 目录下\n\n4. `build.gradle` : 定义编译过程的 gradle 脚本。（不用改动，定义了自动下载 Paddle Lite 预测和模型的过程）\n\n```bash\n# 位置\nTTSAndroid/app/build.gradle\n```\n\n如果需要手动更新模型和预测库，则可将 gradle 脚本中的 `download*` 接口注释即可, 将新的预测库替换至相应目录下\n\n### Java 端\n\n* 模型存放，将下载好的模型解压存放在 `app/src/assets/models` 目录下。\n* TTSAndroid Java 包在 `app/src/main/java/com/baidu/paddle/lite/demo/tts` 目录下，实现 APP 界面消息事件。\n* MainActivity 实现 APP 的创建、运行、释放功能，重点关注 `onLoadModel` 和 `onRunModel` 函数，实现 APP 界面值传递和推理处理。\n\n     ```java\n    public boolean onLoadModel() {\n        return predictor.init(MainActivity.this, modelPath, AMmodelName, VOCmodelName, cpuThreadNum,\n                cpuPowerMode);\n    }\n     \n    public boolean onRunModel() {\n        return predictor.isLoaded() && predictor.runModel(phones);\n    }\n     ```\n\n* SettingActivity 实现设置界面各个元素的更新与显示如模型地址、线程数、输入 shape 大小等，如果新增/删除界面的某个元素，均在这个类里面实现：\n    - 参数的默认值可在 `app/src/main/res/values/strings.xml` 查看\n    - 每个元素的 ID 和 value 是对应 `app/src/main/res/xml/settings.xml`\n      和 `app/src/main/res/values/string.xml` 文件中的值\n    - 这部分内容不建议修改，如果有新增属性，可以按照此格式进行添加\n\n* Predictor 使用 Java API 实现语音合成模型的预测功能，重点关注 `init`、和 `runModel` 函数，实现 Paddle Lite 端侧推理功能：\n     ```java\n     // 初始化函数，完成预测器初始化\n     public boolean init(Context appCtx, String modelPath, String AMmodelName, String VOCmodelName, int cpuThreadNum, String cpuPowerMode);\n     // 模型推理函数\n     public boolean runModel(float[] phones);\n     ```\n\n## 代码讲解 （使用 Paddle Lite `Java API` 执行预测）\n\nAndroid 示例基于 Java API 开发，调用 Paddle Lite `Java API` 包括以下五步。更详细的 `API`\n描述参考：[Paddle Lite Java API ](https://www.paddlepaddle.org.cn/lite/v2.11/api_reference/java_api_doc.html)。\n\n## 如何更新模型和输入\n\n### 更新模型\n\n1. 将优化后的模型存放到目录 `TTSAndroid/app/src/main/assets/models/cpu/`\n   下，可任意换成 [released_model.md](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md)\n   中的 `*_pdlite_*.zip/*_arm.nb`\n   格式的声学模型和声码器，注意更换声学模型需要对应修改 `TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/MainActivity.java`\n   中的 `sentencesToChoose` 数组。\n2. 如果模型名字跟工程中模型名字一模一样，即均是使用`fastspeech2_csmsc_arm.nb` （假设声学模型的 `phone_id_map.txt`\n   也一样）和 `mb_melgan_csmsc_arm.nb`\n   ，则代码不需更新；否则，需要修改  `TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/MainActivity.java`\n   中的 `AMmodelName` 和 `VOCmodelName`：\n\n<p align=\"center\">\n<img src=\"https://user-images.githubusercontent.com/24568452/204458299-25e305a6-7cbb-4308-86ee-03f146bb938e.png\">\n</p>\n\n3. 如果更新模型的输入/输出 Tensor 个数、shape 和 Dtype\n   发生更新，需要更新文件 `TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/Predictor.java`。\n\n### 更新输入\n\n**本 Demo 不包含文本前端模块**，通过下拉框选择预先设置好的文本，在代码中映射成对应的 phone_id，**如需文本前端模块请自行处理**，可参考：\n- C++ 中文前端 [lym0302/paddlespeech_tts_cpp](https://github.com/lym0302/paddlespeech_tts_cpp)\n- C++ 英文 g2p [yazone/g2pE_mobile](https://github.com/yazone/g2pE_mobile)\n\n`phone_id_map.txt` 请参考 [fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip)。\n\n## 通过 setting 界面更新语音合成的相关参数\n\n### setting 界面参数介绍\n\n可通过 APP 上的 Settings 按钮，实现语音合成 Demo 中参数的更新，目前支持以下参数的更新：\n参数的默认值可在 `app/src/main/res/values/strings.xml` 查看\n\n- CPU setting：\n    - power_mode 默认是 `LITE_POWER_HIGH`\n    - thread_num 默认是 1\n\n### setting 界面参数更新\n\n1. 打开 APP，点击右上角的 `:` 符合，选择 `Settings..` 选项，打开 setting 界面；\n2. 再将 setting 界面的 Enable custom settings 选中☑️，然后更新部分参数；\n3. 假设更新线程数据，将 CPU Thread Num 设置为 4，更新后，返回原界面，APP 将自动重新加载模型，在下拉框中选择文本会进行合成，合成结束后悔打印 4 线程的耗时和结果\n\n## 性能优化方法\n\n如果你觉得当前性能不符合需求，想进一步提升模型性能，可参考[性能优化文档](https://github.com/PaddlePaddle/Paddle-Lite-Demo#%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96)完成性能优化。\n\n## Release\n\n[2022-11-29-app-release.apk](https://paddlespeech.cdn.bcebos.com/demos/TTSAndroid/2022-11-29-app-release.apk)\n\n## More\n本 Demo 合并自 [yt605155624/TTSAndroid](https://github.com/yt605155624/TTSAndroid)。\n"
  },
  {
    "path": "demos/TTSAndroid/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "demos/TTSAndroid/app/build.gradle",
    "content": "import java.security.MessageDigest\n\napply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 28\n    defaultConfig {\n        applicationId \"com.baidu.paddle.lite.demo.tts\"\n        minSdkVersion 15\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    implementation fileTree(include: ['*.jar'], dir: 'libs')\n    implementation 'com.android.support:appcompat-v7:28.0.0'\n    implementation 'com.android.support.constraint:constraint-layout:1.1.3'\n    implementation 'com.android.support:design:28.0.0'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n    implementation files('libs/PaddlePredictor.jar')\n}\n\ndef paddleLiteLibs = 'https://paddlespeech.cdn.bcebos.com/demos/TTSAndroid/paddle_lite_libs_68b66fd3.tar.gz'\ntask downloadAndExtractPaddleLiteLibs(type: DefaultTask) {\n    doFirst {\n        println \"Downloading and extracting Paddle Lite libs\"\n    }\n    doLast {\n        // Prepare cache folder for libs\n        if (!file(\"cache\").exists()) {\n            mkdir \"cache\"\n        }\n        // Generate cache name for libs\n        MessageDigest messageDigest = MessageDigest.getInstance('MD5')\n        messageDigest.update(paddleLiteLibs.bytes)\n        String cacheName = new BigInteger(1, messageDigest.digest()).toString(32)\n        // Download libs\n        if (!file(\"cache/${cacheName}.tar.gz\").exists()) {\n            ant.get(src: paddleLiteLibs, dest: file(\"cache/${cacheName}.tar.gz\"))\n        }\n        // Unpack libs\n        if (!file(\"cache/${cacheName}\").exists()) {\n            copy {\n                from tarTree(\"cache/${cacheName}.tar.gz\")\n                into \"cache/${cacheName}\"\n            }\n        }\n        // Copy PaddlePredictor.jar\n        if (!file(\"libs/PaddlePredictor.jar\").exists()) {\n            copy {\n                from \"cache/${cacheName}/java/PaddlePredictor.jar\"\n                into \"libs\"\n            }\n        }\n        if (!file(\"src/main/jniLibs/arm64-v8a/libpaddle_lite_jni.so\").exists()) {\n            copy {\n                from \"cache/${cacheName}/java/libs/arm64-v8a/\"\n                into \"src/main/jniLibs/arm64-v8a\"\n            }\n        }\n    }\n}\npreBuild.dependsOn downloadAndExtractPaddleLiteLibs\n\ndef paddleLiteModels = [['src' : 'https://paddlespeech.cdn.bcebos.com/demos/TTSAndroid/fs2cnn_mbmelgan_cpu_v1.3.0.tar.gz',\n                         'dest': 'src/main/assets/models'],]\ntask downloadAndExtractPaddleLiteModels(type: DefaultTask) {\n    doFirst {\n        println \"Downloading and extracting Paddle Lite models\"\n    }\n    doLast {\n        // Prepare cache folder for models\n        String cachePath = \"cache\"\n        if (!file(\"${cachePath}\").exists()) {\n            mkdir \"${cachePath}\"\n        }\n        paddleLiteModels.eachWithIndex { model, index ->\n            MessageDigest messageDigest = MessageDigest.getInstance('MD5')\n            messageDigest.update(model.src.bytes)\n            String cacheName = new BigInteger(1, messageDigest.digest()).toString(32)\n            // Download the target model if not exists\n            boolean copyFiles = !file(\"${model.dest}\").exists()\n            if (!file(\"${cachePath}/${cacheName}.tar.gz\").exists()) {\n                ant.get(src: model.src, dest: file(\"${cachePath}/${cacheName}.tar.gz\"))\n                copyFiles = true // force to copy files from the latest archive files\n            }\n            // Copy model file\n            if (copyFiles) {\n                copy {\n                    from tarTree(\"${cachePath}/${cacheName}.tar.gz\")\n                    into \"${model.dest}\"\n                }\n            }\n        }\n    }\n}\npreBuild.dependsOn downloadAndExtractPaddleLiteModels\n"
  },
  {
    "path": "demos/TTSAndroid/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/androidTest/java/com/baidu/paddle/lite/demo/tts/ExampleInstrumentedTest.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.baidu.paddle.lite.demo\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.baidu.paddle.lite.demo.tts\">\n\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@drawable/logo\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@drawable/logo\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\"com.baidu.paddle.lite.demo.tts.MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\"com.baidu.paddle.lite.demo.tts.SettingsActivity\"\n            android:label=\"Settings\"></activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/AppCompatPreferenceActivity.java",
    "content": "/*\n * Copyright (C) 2014 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.baidu.paddle.lite.demo.tts;\n\nimport android.content.res.Configuration;\nimport android.os.Bundle;\nimport android.preference.PreferenceActivity;\nimport android.support.annotation.LayoutRes;\nimport android.support.v7.app.ActionBar;\nimport android.support.v7.app.AppCompatDelegate;\nimport android.view.MenuInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\n/**\n * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls\n * to be used with AppCompat.\n * <p>\n * This technique can be used with an {@link android.app.Activity} class, not just\n * {@link android.preference.PreferenceActivity}.\n */\npublic abstract class AppCompatPreferenceActivity extends PreferenceActivity {\n    private AppCompatDelegate mDelegate;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        getDelegate().installViewFactory();\n        getDelegate().onCreate(savedInstanceState);\n        super.onCreate(savedInstanceState);\n    }\n\n    @Override\n    protected void onPostCreate(Bundle savedInstanceState) {\n        super.onPostCreate(savedInstanceState);\n        getDelegate().onPostCreate(savedInstanceState);\n    }\n\n    public ActionBar getSupportActionBar() {\n        return getDelegate().getSupportActionBar();\n    }\n\n\n    @Override\n    public MenuInflater getMenuInflater() {\n        return getDelegate().getMenuInflater();\n    }\n\n    @Override\n    public void setContentView(@LayoutRes int layoutResID) {\n        getDelegate().setContentView(layoutResID);\n    }\n\n    @Override\n    public void setContentView(View view) {\n        getDelegate().setContentView(view);\n    }\n\n    @Override\n    public void setContentView(View view, ViewGroup.LayoutParams params) {\n        getDelegate().setContentView(view, params);\n    }\n\n    @Override\n    public void addContentView(View view, ViewGroup.LayoutParams params) {\n        getDelegate().addContentView(view, params);\n    }\n\n    @Override\n    protected void onPostResume() {\n        super.onPostResume();\n        getDelegate().onPostResume();\n    }\n\n    @Override\n    protected void onTitleChanged(CharSequence title, int color) {\n        super.onTitleChanged(title, color);\n        getDelegate().setTitle(title);\n    }\n\n    @Override\n    public void onConfigurationChanged(Configuration newConfig) {\n        super.onConfigurationChanged(newConfig);\n        getDelegate().onConfigurationChanged(newConfig);\n    }\n\n    @Override\n    protected void onStop() {\n        super.onStop();\n        getDelegate().onStop();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        getDelegate().onDestroy();\n    }\n\n    public void invalidateOptionsMenu() {\n        getDelegate().invalidateOptionsMenu();\n    }\n\n    private AppCompatDelegate getDelegate() {\n        if (mDelegate == null) {\n            mDelegate = AppCompatDelegate.create(this, null);\n        }\n        return mDelegate;\n    }\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/MainActivity.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport android.Manifest;\nimport android.app.ProgressDialog;\nimport android.content.Intent;\nimport android.content.SharedPreferences;\nimport android.content.pm.PackageManager;\nimport android.media.MediaPlayer;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.os.Message;\nimport android.preference.PreferenceManager;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.ActivityCompat;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v7.app.AppCompatActivity;\nimport android.text.method.ScrollingMovementMethod;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\nimport android.widget.Button;\nimport android.widget.Spinner;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport java.io.File;\nimport java.io.IOException;\n\npublic class MainActivity extends AppCompatActivity implements View.OnClickListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, AdapterView.OnItemSelectedListener {\n    public static final int REQUEST_LOAD_MODEL = 0;\n    public static final int REQUEST_RUN_MODEL = 1;\n    public static final int RESPONSE_LOAD_MODEL_SUCCESSED = 0;\n    public static final int RESPONSE_LOAD_MODEL_FAILED = 1;\n    public static final int RESPONSE_RUN_MODEL_SUCCESSED = 2;\n    public static final int RESPONSE_RUN_MODEL_FAILED = 3;\n    public MediaPlayer mediaPlayer = new MediaPlayer();\n    private static final String TAG = Predictor.class.getSimpleName();\n    protected ProgressDialog pbLoadModel = null;\n    protected ProgressDialog pbRunModel = null;\n    // Receive messages from worker thread\n    protected Handler receiver = null;\n    // Send command to worker thread\n    protected Handler sender = null;\n    // Worker thread to load&run model\n    protected HandlerThread worker = null;\n    // UI components of image classification\n    protected TextView tvInputSetting;\n    protected TextView tvInferenceTime;\n    protected Button btn_play;\n    protected Button btn_pause;\n    protected Button btn_stop;\n    // Model settings of image classification\n    protected String modelPath = \"\";\n    protected int cpuThreadNum = 1;\n    protected String cpuPowerMode = \"\";\n    protected Predictor predictor = new Predictor();\n    int sampleRate = 24000;\n    private final String wavName = \"tts_output.wav\";\n    private final String wavFile = Environment.getExternalStorageDirectory() + File.separator + wavName;\n    private final String AMmodelName = \"fastspeech2_csmsc_arm.nb\";\n    private final String VOCmodelName = \"mb_melgan_csmsc_arm.nb\";\n    private float[] phones = {};\n    private final float[][] sentencesToChoose = {\n            // 009901 昨日，这名“伤者”与医生全部被警方依法刑事拘留。\n            {261, 231, 175, 116, 179, 262, 44, 154, 126, 177, 19, 262, 42, 241, 72, 177, 56, 174, 245, 37, 186, 37, 49, 151, 127, 69, 19, 179, 72, 69, 4, 260, 126, 177, 116, 151, 239, 153, 141},\n            // 009902 钱伟长想到上海来办学校是经过深思熟虑的。\n            {174, 83, 213, 39, 20, 260, 89, 40, 30, 177, 22, 71, 9, 153, 8, 37, 17, 260, 251, 260, 99, 179, 177, 116, 151, 125, 70, 233, 177, 51, 176, 108, 177, 184, 153, 242, 40, 45},\n            // 009903 她见我一进门就骂，吃饭时也骂，骂得我抬不起头。\n            {182, 2, 151, 85, 232, 73, 151, 123, 154, 52, 151, 143, 154, 5, 179, 39, 113, 69, 17, 177, 114, 105, 154, 5, 179, 154, 5, 40, 45, 232, 182, 8, 37, 186, 174, 74, 182, 168},\n            // 009904 李述德在离开之前，只说了一句“柱驼杀父亲了”。\n            {153, 74, 177, 186, 40, 42, 261, 10, 153, 73, 152, 7, 262, 113, 174, 83, 179, 262, 115, 177, 230, 153, 45, 73, 151, 242, 180, 262, 186, 182, 231, 177, 2, 69, 186, 174, 124, 153, 45},\n            // 009905 这种车票和保险单捆绑出售属于重复性购买。\n            {262, 44, 262, 163, 39, 41, 173, 99, 71, 42, 37, 28, 260, 84, 40, 14, 179, 152, 220, 37, 21, 39, 183, 177, 170, 179, 177, 185, 240, 39, 162, 69, 186, 260, 128, 70, 170, 154, 9},\n            // 009906 戴佩妮的男友西米露接唱情歌，让她非常开心。\n            {40, 10, 173, 49, 155, 72, 40, 45, 155, 15, 142, 260, 72, 154, 74, 153, 186, 179, 151, 103, 39, 22, 174, 126, 70, 41, 179, 175, 22, 182, 2, 69, 46, 39, 20, 152, 7, 260, 120},\n            // 009907 观大势、谋大局、出大策始终是该院的办院方针。\n            {70, 199, 40, 5, 177, 116, 154, 168, 40, 5, 151, 240, 179, 39, 183, 40, 5, 38, 44, 179, 177, 115, 262, 161, 177, 116, 70, 7, 247, 40, 45, 37, 17, 247, 69, 19, 262, 51},\n            // 009908 他们骑着摩托回家，正好为农忙时的父母帮忙。\n            {182, 2, 154, 55, 174, 73, 262, 45, 154, 157, 182, 230, 71, 212, 151, 77, 180, 262, 59, 71, 29, 214, 155, 162, 154, 20, 177, 114, 40, 45, 69, 186, 154, 185, 37, 19, 154, 20},\n            // 009909 但是因为还没到退休年龄，只能掰着指头捱日子。\n            {40, 17, 177, 116, 120, 214, 71, 8, 154, 47, 40, 30, 182, 214, 260, 140, 155, 83, 153, 126, 180, 262, 115, 155, 57, 37, 7, 262, 45, 262, 115, 182, 171, 8, 175, 116, 261, 112},\n            // 009910 这几天雨水不断，人们恨不得待在家里不出门。\n            {262, 44, 151, 74, 182, 82, 240, 177, 213, 37, 184, 40, 202, 180, 175, 52, 154, 55, 71, 54, 37, 186, 40, 42, 40, 7, 261, 10, 151, 77, 153, 74, 37, 186, 39, 183, 154, 52}\n\n    };\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.btn_play:\n                if (!mediaPlayer.isPlaying()) {\n                    mediaPlayer.start();\n                }\n                break;\n            case R.id.btn_pause:\n                if (mediaPlayer.isPlaying()) {\n                    mediaPlayer.pause();\n                }\n                break;\n            case R.id.btn_stop:\n                if (mediaPlayer.isPlaying()) {\n                    mediaPlayer.reset();\n                    initMediaPlayer();\n                }\n                break;\n            default:\n                break;\n        }\n    }\n\n    private void initMediaPlayer() {\n        try {\n            File file = new File(wavFile);\n            // 指定音频文件的路径\n            mediaPlayer.setDataSource(file.getPath());\n            // 让 MediaPlayer 进入到准备状态\n            mediaPlayer.prepare();\n            // 该方法使得进入应用时就播放音频\n            // mediaPlayer.setOnPreparedListener(this);\n            // prepare async to not block main thread\n            mediaPlayer.prepareAsync();\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Override\n    public void onPrepared(MediaPlayer player) {\n        player.start();\n    }\n\n    @Override\n    public boolean onError(MediaPlayer mp, int what, int extra) {\n        // The MediaPlayer has moved to the Error state, must be reset!\n        mediaPlayer.reset();\n        initMediaPlayer();\n        return true;\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        requestAllPermissions();\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        // 初始化控件\n        Spinner spinner = findViewById(R.id.spinner1);\n        // 建立数据源\n        String[] sentences = getResources().getStringArray(R.array.text);\n        // 建立 Adapter 并且绑定数据源\n        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, sentences);\n        // 第一个参数表示在哪个 Activity 上显示，第二个参数是系统下拉框的样式，第三个参数是数组。\n        spinner.setAdapter(adapter);//绑定Adapter到控件\n        spinner.setOnItemSelectedListener(this);\n\n        btn_play = findViewById(R.id.btn_play);\n        btn_pause = findViewById(R.id.btn_pause);\n        btn_stop = findViewById(R.id.btn_stop);\n\n        btn_play.setOnClickListener(this);\n        btn_pause.setOnClickListener(this);\n        btn_stop.setOnClickListener(this);\n\n        btn_play.setVisibility(View.INVISIBLE);\n        btn_pause.setVisibility(View.INVISIBLE);\n        btn_stop.setVisibility(View.INVISIBLE);\n\n\n        // Clear all setting items to avoid app crashing due to the incorrect settings\n        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);\n        SharedPreferences.Editor editor = sharedPreferences.edit();\n        editor.clear();\n        editor.commit();\n\n        // Prepare the worker thread for mode loading and inference\n        receiver = new Handler() {\n            @Override\n            public void handleMessage(Message msg) {\n                switch (msg.what) {\n                    case RESPONSE_LOAD_MODEL_SUCCESSED:\n                        pbLoadModel.dismiss();\n                        onLoadModelSuccessed();\n                        break;\n                    case RESPONSE_LOAD_MODEL_FAILED:\n                        pbLoadModel.dismiss();\n                        Toast.makeText(MainActivity.this, \"Load model failed!\", Toast.LENGTH_SHORT).show();\n                        onLoadModelFailed();\n                        break;\n                    case RESPONSE_RUN_MODEL_SUCCESSED:\n                        pbRunModel.dismiss();\n                        onRunModelSuccessed();\n                        break;\n                    case RESPONSE_RUN_MODEL_FAILED:\n                        pbRunModel.dismiss();\n                        Toast.makeText(MainActivity.this, \"Run model failed!\", Toast.LENGTH_SHORT).show();\n                        onRunModelFailed();\n                        break;\n                    default:\n                        break;\n                }\n            }\n        };\n\n        worker = new HandlerThread(\"Predictor Worker\");\n        worker.start();\n        sender = new Handler(worker.getLooper()) {\n            public void handleMessage(Message msg) {\n                switch (msg.what) {\n                    case REQUEST_LOAD_MODEL:\n                        // Load model and reload test image\n                        if (onLoadModel()) {\n                            receiver.sendEmptyMessage(RESPONSE_LOAD_MODEL_SUCCESSED);\n                        } else {\n                            receiver.sendEmptyMessage(RESPONSE_LOAD_MODEL_FAILED);\n                        }\n                        break;\n                    case REQUEST_RUN_MODEL:\n                        // Run model if model is loaded\n                        if (onRunModel()) {\n                            receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_SUCCESSED);\n                        } else {\n                            receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_FAILED);\n                        }\n                        break;\n                    default:\n                        break;\n                }\n            }\n        };\n\n        // Setup the UI components\n        tvInputSetting = findViewById(R.id.tv_input_setting);\n        tvInferenceTime = findViewById(R.id.tv_inference_time);\n        tvInputSetting.setMovementMethod(ScrollingMovementMethod.getInstance());\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        boolean settingsChanged = false;\n        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);\n        String model_path = sharedPreferences.getString(getString(R.string.MODEL_PATH_KEY),\n                getString(R.string.MODEL_PATH_DEFAULT));\n\n        settingsChanged |= !model_path.equalsIgnoreCase(modelPath);\n\n        int cpu_thread_num = Integer.parseInt(sharedPreferences.getString(getString(R.string.CPU_THREAD_NUM_KEY),\n                getString(R.string.CPU_THREAD_NUM_DEFAULT)));\n        settingsChanged |= cpu_thread_num != cpuThreadNum;\n        String cpu_power_mode =\n                sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY),\n                        getString(R.string.CPU_POWER_MODE_DEFAULT));\n        settingsChanged |= !cpu_power_mode.equalsIgnoreCase(cpuPowerMode);\n\n        if (settingsChanged) {\n            modelPath = model_path;\n            cpuThreadNum = cpu_thread_num;\n            cpuPowerMode = cpu_power_mode;\n            // Update UI\n            tvInputSetting.setText(\"Model: \" + modelPath.substring(modelPath.lastIndexOf(\"/\") + 1) + \"\\n\" + \"CPU\" +\n                    \" Thread Num: \" + cpuThreadNum + \"\\n\" + \"CPU Power Mode: \" + cpuPowerMode + \"\\n\");\n            tvInputSetting.scrollTo(0, 0);\n            // Reload model if configure has been changed\n            loadModel();\n        }\n    }\n\n    public void loadModel() {\n        pbLoadModel = ProgressDialog.show(this, \"\", \"Loading model...\", false, false);\n        sender.sendEmptyMessage(REQUEST_LOAD_MODEL);\n    }\n\n    public void runModel() {\n        pbRunModel = ProgressDialog.show(this, \"\", \"Running model...\", false, false);\n        sender.sendEmptyMessage(REQUEST_RUN_MODEL);\n    }\n\n    public boolean onLoadModel() {\n        return predictor.init(MainActivity.this, modelPath, AMmodelName, VOCmodelName, cpuThreadNum,\n                cpuPowerMode);\n    }\n\n    public boolean onRunModel() {\n        return predictor.isLoaded() && predictor.runModel(phones);\n    }\n\n    public boolean onLoadModelSuccessed() {\n        // Load test image from path and run model\n//        runModel();\n        return true;\n    }\n\n    public void onLoadModelFailed() {\n    }\n\n    public void onRunModelSuccessed() {\n        // Obtain results and update UI\n        btn_play.setVisibility(View.VISIBLE);\n        btn_pause.setVisibility(View.VISIBLE);\n        btn_stop.setVisibility(View.VISIBLE);\n        tvInferenceTime.setText(\"Inference done！\\nInference time: \" + predictor.inferenceTime() + \" ms\"\n                + \"\\nRTF: \" + predictor.inferenceTime() * sampleRate / (predictor.wav.length * 1000) + \"\\nAudio saved in \" + wavFile);\n        try {\n            Utils.rawToWave(wavFile, predictor.wav, sampleRate);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        if (ContextCompat.checkSelfPermission(MainActivity.this,\n                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {\n            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);\n        } else {\n            // 初始化 MediaPlayer\n            initMediaPlayer();\n        }\n    }\n\n    public void onRunModelFailed() {\n    }\n\n\n    public void onSettingsClicked() {\n        startActivity(new Intent(MainActivity.this, SettingsActivity.class));\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        MenuInflater inflater = getMenuInflater();\n        inflater.inflate(R.menu.menu_action_options, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                finish();\n                break;\n            case R.id.settings:\n                onSettingsClicked();\n        }\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,\n                                           @NonNull int[] grantResults) {\n\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n        if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {\n            Toast.makeText(this, \"Permission Denied\", Toast.LENGTH_SHORT).show();\n        }\n    }\n\n\n    @Override\n    protected void onDestroy() {\n        if (predictor != null) {\n            predictor.releaseModel();\n        }\n        worker.quit();\n        super.onDestroy();\n        if (mediaPlayer != null) {\n            mediaPlayer.stop();\n            mediaPlayer.release();\n        }\n    }\n\n    private boolean requestAllPermissions() {\n        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)\n                != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,\n                Manifest.permission.CAMERA)\n                != PackageManager.PERMISSION_GRANTED) {\n            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},\n                    0);\n            return false;\n        }\n        return true;\n    }\n\n\n    @Override\n    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {\n        if (position > 0) {\n            phones = sentencesToChoose[position - 1];\n            runModel();\n        }\n\n    }\n\n    @Override\n    public void onNothingSelected(AdapterView<?> parent) {\n\n    }\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/Predictor.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com.baidu.paddle.lite.MobileConfig;\nimport com.baidu.paddle.lite.PaddlePredictor;\nimport com.baidu.paddle.lite.PowerMode;\nimport com.baidu.paddle.lite.Tensor;\n\nimport java.io.File;\nimport java.util.Date;\n\n\npublic class Predictor {\n    private static final String TAG = Predictor.class.getSimpleName();\n    public boolean isLoaded = false;\n    public int cpuThreadNum = 1;\n    public String cpuPowerMode = \"LITE_POWER_HIGH\";\n    public String modelPath = \"\";\n    protected PaddlePredictor AMPredictor = null;\n    protected PaddlePredictor VOCPredictor = null;\n    protected float inferenceTime = 0;\n    protected float[] wav;\n\n    public boolean init(Context appCtx, String modelPath, String AMmodelName, String VOCmodelName, int cpuThreadNum, String cpuPowerMode) {\n        // Release model if exists\n        releaseModel();\n\n        AMPredictor = loadModel(appCtx, modelPath, AMmodelName, cpuThreadNum, cpuPowerMode);\n        if (AMPredictor == null) {\n            return false;\n        }\n        VOCPredictor = loadModel(appCtx, modelPath, VOCmodelName, cpuThreadNum, cpuPowerMode);\n        if (VOCPredictor == null) {\n            return false;\n        }\n        isLoaded = true;\n        return true;\n    }\n\n    protected PaddlePredictor loadModel(Context appCtx, String modelPath, String modelName, int cpuThreadNum, String cpuPowerMode) {\n        // Load model\n        if (modelPath.isEmpty()) {\n            return null;\n        }\n        String realPath = modelPath;\n        if (modelPath.charAt(0) != '/') {\n            // Read model files from custom path if the first character of mode path is '/'\n            // otherwise copy model to cache from assets\n            realPath = appCtx.getCacheDir() + \"/\" + modelPath;\n            // push model to mobile\n            Utils.copyDirectoryFromAssets(appCtx, modelPath, realPath);\n        }\n        if (realPath.isEmpty()) {\n            return null;\n        }\n        MobileConfig config = new MobileConfig();\n        config.setModelFromFile(realPath + File.separator + modelName);\n        Log.e(TAG, \"File:\" + realPath + File.separator + modelName);\n        config.setThreads(cpuThreadNum);\n        if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_HIGH\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_HIGH);\n        } else if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_LOW\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_LOW);\n        } else if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_FULL\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_FULL);\n        } else if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_NO_BIND\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_NO_BIND);\n        } else if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_RAND_HIGH\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_RAND_HIGH);\n        } else if (cpuPowerMode.equalsIgnoreCase(\"LITE_POWER_RAND_LOW\")) {\n            config.setPowerMode(PowerMode.LITE_POWER_RAND_LOW);\n        } else {\n            Log.e(TAG, \"Unknown cpu power mode!\");\n            return null;\n        }\n        return PaddlePredictor.createPaddlePredictor(config);\n    }\n\n    public void releaseModel() {\n        AMPredictor = null;\n        VOCPredictor = null;\n        isLoaded = false;\n        cpuThreadNum = 1;\n        cpuPowerMode = \"LITE_POWER_HIGH\";\n        modelPath = \"\";\n    }\n\n    public boolean runModel(float[] phones) {\n        if (!isLoaded()) {\n            return false;\n        }\n        Date start = new Date();\n        Tensor am_output_handle = getAMOutput(phones, AMPredictor);\n        wav = getVOCOutput(am_output_handle, VOCPredictor);\n        Date end = new Date();\n        inferenceTime = (end.getTime() - start.getTime());\n        return true;\n    }\n\n    public Tensor getAMOutput(float[] phones, PaddlePredictor am_predictor) {\n        Tensor phones_handle = am_predictor.getInput(0);\n        long[] dims = {phones.length};\n        phones_handle.resize(dims);\n        phones_handle.setData(phones);\n        am_predictor.run();\n        Tensor am_output_handle = am_predictor.getOutput(0);\n        // [?, 80]\n        // long outputShape[] = am_output_handle.shape();\n        float[] am_output_data = am_output_handle.getFloatData();\n        // [? x 80]\n        // long[] am_output_data_shape = {am_output_data.length};\n        // Log.e(TAG, Arrays.toString(am_output_data));\n        // 打印 mel 数组\n        // for (int i=0;i<outputShape[0];i++) {\n        //      Log.e(TAG, Arrays.toString(Arrays.copyOfRange(am_output_data,i*80,(i+1)*80)));\n        // }\n        // voc_predictor 需要知道输入的 shape，所以不能输出转成 float 之后的一维数组\n        return am_output_handle;\n    }\n\n    public float[] getVOCOutput(Tensor input, PaddlePredictor voc_predictor) {\n        Tensor mel_handle = voc_predictor.getInput(0);\n        // [?, 80]\n        long[] dims = input.shape();\n        mel_handle.resize(dims);\n        float[] am_output_data = input.getFloatData();\n        mel_handle.setData(am_output_data);\n        voc_predictor.run();\n        Tensor voc_output_handle = voc_predictor.getOutput(0);\n        // [? x 300, 1]\n        // long[] outputShape = voc_output_handle.shape();\n        float[] voc_output_data = voc_output_handle.getFloatData();\n        // long[] voc_output_data_shape = {voc_output_data.length};\n        return voc_output_data;\n    }\n\n\n    public boolean isLoaded() {\n        return AMPredictor != null && VOCPredictor != null && isLoaded;\n    }\n\n\n    public float inferenceTime() {\n        return inferenceTime;\n    }\n\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/SettingsActivity.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport android.content.SharedPreferences;\nimport android.os.Bundle;\nimport android.preference.CheckBoxPreference;\nimport android.preference.EditTextPreference;\nimport android.preference.ListPreference;\nimport android.support.v7.app.ActionBar;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SettingsActivity extends AppCompatPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {\n    ListPreference lpChoosePreInstalledModel = null;\n    CheckBoxPreference cbEnableCustomSettings = null;\n    EditTextPreference etModelPath = null;\n    ListPreference lpCPUThreadNum = null;\n    ListPreference lpCPUPowerMode = null;\n\n    List<String> preInstalledModelPaths = null;\n    List<String> preInstalledCPUThreadNums = null;\n    List<String> preInstalledCPUPowerModes = null;\n\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        addPreferencesFromResource(R.xml.settings);\n        ActionBar supportActionBar = getSupportActionBar();\n        if (supportActionBar != null) {\n            supportActionBar.setDisplayHomeAsUpEnabled(true);\n        }\n\n        // Initialized pre-installed models\n        preInstalledModelPaths = new ArrayList<String>();\n        preInstalledCPUThreadNums = new ArrayList<String>();\n        preInstalledCPUPowerModes = new ArrayList<String>();\n        preInstalledModelPaths.add(getString(R.string.MODEL_PATH_DEFAULT));\n        preInstalledCPUThreadNums.add(getString(R.string.CPU_THREAD_NUM_DEFAULT));\n        preInstalledCPUPowerModes.add(getString(R.string.CPU_POWER_MODE_DEFAULT));\n\n\n        // Setup UI components\n        lpChoosePreInstalledModel = (ListPreference) findPreference(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY));\n        String[] preInstalledModelNames = new String[preInstalledModelPaths.size()];\n        for (int i = 0; i < preInstalledModelPaths.size(); i++) {\n            preInstalledModelNames[i] = preInstalledModelPaths.get(i).substring(preInstalledModelPaths.get(i).lastIndexOf(\"/\") + 1);\n        }\n        lpChoosePreInstalledModel.setEntries(preInstalledModelNames);\n        lpChoosePreInstalledModel.setEntryValues(preInstalledModelPaths.toArray(new String[preInstalledModelPaths.size()]));\n        lpCPUThreadNum = (ListPreference) findPreference(getString(R.string.CPU_THREAD_NUM_KEY));\n        lpCPUPowerMode = (ListPreference) findPreference(getString(R.string.CPU_POWER_MODE_KEY));\n        cbEnableCustomSettings = (CheckBoxPreference) findPreference(getString(R.string.ENABLE_CUSTOM_SETTINGS_KEY));\n        etModelPath = (EditTextPreference) findPreference(getString(R.string.MODEL_PATH_KEY));\n        etModelPath.setTitle(\"Model Path (SDCard: \" + Utils.getSDCardDirectory() + \")\");\n    }\n\n    private void reloadPreferenceAndUpdateUI() {\n        SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();\n        boolean enableCustomSettings = sharedPreferences.getBoolean(getString(R.string.ENABLE_CUSTOM_SETTINGS_KEY), false);\n        String modelPath = sharedPreferences.getString(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY), getString(R.string.MODEL_PATH_DEFAULT));\n        int modelIdx = lpChoosePreInstalledModel.findIndexOfValue(modelPath);\n        if (modelIdx >= 0 && modelIdx < preInstalledModelPaths.size()) {\n            if (!enableCustomSettings) {\n                SharedPreferences.Editor editor = sharedPreferences.edit();\n                editor.putString(getString(R.string.MODEL_PATH_KEY), preInstalledModelPaths.get(modelIdx));\n                editor.putString(getString(R.string.CPU_THREAD_NUM_KEY), preInstalledCPUThreadNums.get(modelIdx));\n                editor.putString(getString(R.string.CPU_POWER_MODE_KEY), preInstalledCPUPowerModes.get(modelIdx));\n                editor.commit();\n            }\n            lpChoosePreInstalledModel.setSummary(modelPath);\n        }\n        cbEnableCustomSettings.setChecked(enableCustomSettings);\n        etModelPath.setEnabled(enableCustomSettings);\n        lpCPUThreadNum.setEnabled(enableCustomSettings);\n        lpCPUPowerMode.setEnabled(enableCustomSettings);\n        modelPath = sharedPreferences.getString(getString(R.string.MODEL_PATH_KEY), getString(R.string.MODEL_PATH_DEFAULT));\n        String cpuThreadNum = sharedPreferences.getString(getString(R.string.CPU_THREAD_NUM_KEY), getString(R.string.CPU_THREAD_NUM_DEFAULT));\n        String cpuPowerMode = sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY), getString(R.string.CPU_POWER_MODE_DEFAULT));\n\n        etModelPath.setSummary(modelPath);\n        etModelPath.setText(modelPath);\n        lpCPUThreadNum.setValue(cpuThreadNum);\n        lpCPUThreadNum.setSummary(cpuThreadNum);\n        lpCPUPowerMode.setValue(cpuPowerMode);\n        lpCPUPowerMode.setSummary(cpuPowerMode);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);\n        reloadPreferenceAndUpdateUI();\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);\n    }\n\n    @Override\n    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\n        if (key.equals(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY))) {\n            SharedPreferences.Editor editor = sharedPreferences.edit();\n            editor.putBoolean(getString(R.string.ENABLE_CUSTOM_SETTINGS_KEY), false);\n            editor.commit();\n        }\n        reloadPreferenceAndUpdateUI();\n    }\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/java/com/baidu/paddle/lite/demo/tts/Utils.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport static java.lang.Math.abs;\n\nimport android.content.Context;\nimport android.os.Environment;\n\nimport java.io.BufferedInputStream;\nimport java.io.BufferedOutputStream;\nimport java.io.DataOutputStream;\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\n\npublic class Utils {\n    public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) {\n        if (srcPath.isEmpty() || dstPath.isEmpty()) {\n            return;\n        }\n        InputStream is = null;\n        OutputStream os = null;\n        try {\n            is = new BufferedInputStream(appCtx.getAssets().open(srcPath));\n            os = new BufferedOutputStream(new FileOutputStream(new File(dstPath)));\n            byte[] buffer = new byte[1024];\n            int length = 0;\n            while ((length = is.read(buffer)) != -1) {\n                os.write(buffer, 0, length);\n            }\n        } catch (FileNotFoundException e) {\n            e.printStackTrace();\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                os.close();\n                is.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) {\n        if (srcDir.isEmpty() || dstDir.isEmpty()) {\n            return;\n        }\n        try {\n            if (!new File(dstDir).exists()) {\n                new File(dstDir).mkdirs();\n            }\n            for (String fileName : appCtx.getAssets().list(srcDir)) {\n                String srcSubPath = srcDir + File.separator + fileName;\n                String dstSubPath = dstDir + File.separator + fileName;\n                if (new File(srcSubPath).isDirectory()) {\n                    copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath);\n                } else {\n                    copyFileFromAssets(appCtx, srcSubPath, dstSubPath);\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n\n    public static String getSDCardDirectory() {\n        return Environment.getExternalStorageDirectory().getAbsolutePath();\n    }\n\n    public static void rawToWave(String file, float[] data, int samplerate) throws IOException {\n        // creating the empty wav file.\n        File waveFile = new File(file);\n        waveFile.createNewFile();\n        //following block is converting raw to wav.\n        DataOutputStream output = null;\n        try {\n            output = new DataOutputStream(new FileOutputStream(waveFile));\n            // WAVE header\n            // chunk id\n            writeString(output, \"RIFF\");\n            // chunk size\n            writeInt(output, 36 + data.length * 2);\n            // format\n            writeString(output, \"WAVE\");\n            // subchunk 1 id\n            writeString(output, \"fmt \");\n            // subchunk 1 size\n            writeInt(output, 16);\n            // audio format (1 = PCM)\n            writeShort(output, (short) 1);\n            // number of channels\n            writeShort(output, (short) 1);\n            // sample rate\n            writeInt(output, samplerate);\n            // byte rate\n            writeInt(output, samplerate * 2);\n            // block align\n            writeShort(output, (short) 2);\n            // bits per sample\n            writeShort(output, (short) 16);\n            // subchunk 2 id\n            writeString(output, \"data\");\n            // subchunk 2 size\n            writeInt(output, data.length * 2);\n            short[] short_data = FloatArray2ShortArray(data);\n            for (int i = 0; i < short_data.length; i++) {\n                writeShort(output, short_data[i]);\n            }\n        } finally {\n            if (output != null) {\n                output.close();\n            }\n        }\n    }\n\n    private static void writeInt(final DataOutputStream output, final int value) throws IOException {\n        output.write(value);\n        output.write(value >> 8);\n        output.write(value >> 16);\n        output.write(value >> 24);\n    }\n\n    private static void writeShort(final DataOutputStream output, final short value) throws IOException {\n        output.write(value);\n        output.write(value >> 8);\n    }\n\n    private static void writeString(final DataOutputStream output, final String value) throws IOException {\n        for (int i = 0; i < value.length(); i++) {\n            output.write(value.charAt(i));\n        }\n    }\n\n    public static short[] FloatArray2ShortArray(float[] values) {\n        float mmax = (float) 0.01;\n        short[] ret = new short[values.length];\n\n        for (int i = 0; i < values.length; i++) {\n            if (abs(values[i]) > mmax) {\n                mmax = abs(values[i]);\n            }\n        }\n\n        for (int i = 0; i < values.length; i++) {\n            values[i] = values[i] * (32767 / mmax);\n            ret[i] = (short) (values[i]);\n        }\n        return ret;\n    }\n\n}\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/drawable/button_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"false\"><!--没点击按钮的时候-->\n        <shape android:shape=\"rectangle\"><!--按钮形状-->\n            <solid android:color=\"#008577\" /><!--按钮背景填充色-->\n            <corners android:radius=\"10dp\" />\n            <stroke android:width=\"1dp\" android:color=\"#009688\" /><!--按钮边框-->\n        </shape>\n    </item>\n\n    <item android:state_pressed=\"true\">\n        <shape android:shape=\"rectangle\"><!--按钮形状-->\n            <solid android:color=\"#C3009688\" /><!--按钮背景填充色-->\n            <corners android:radius=\"10dp\" />\n            <stroke android:width=\"1dp\" android:color=\"#009688\" /><!--按钮边框-->\n        </shape>\n    </item>\n\n</selector>\n\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\">\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <ImageView\n            android:id=\"@+id/logo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"20dp\"\n            android:src=\"@drawable/paddlespeech_logo\" />\n\n        <LinearLayout\n            android:id=\"@+id/v_input_info\"\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@+id/logo\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginTop=\"120dp\"\n            android:orientation=\"vertical\">\n\n            <TextView\n                android:id=\"@+id/tv_input_setting\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginRight=\"12dp\"\n                android:layout_marginBottom=\"5dp\"\n                android:lineSpacingExtra=\"4dp\"\n                android:maxLines=\"6\"\n                android:scrollbars=\"vertical\"\n                android:singleLine=\"false\"\n                android:text=\"\"\n                android:textColor=\"#3C3C3C\" />\n\n            <Spinner\n                android:id=\"@+id/spinner1\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:dropDownSelector=\"#63D81B60\"\n                android:spinnerMode=\"dropdown\" />\n\n            <TextView\n                android:id=\"@+id/tv_inference_time\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_below=\"@+id/spinner1\"\n                android:layout_centerHorizontal=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginTop=\"50dp\"\n                android:layout_marginRight=\"12dp\"\n                android:layout_marginBottom=\"5dp\"\n                android:gravity=\"start\"\n                android:lineSpacingExtra=\"4dp\"\n                android:maxLines=\"6\"\n                android:textColor=\"#3C3C3C\" />\n\n            <LinearLayout\n                android:id=\"@+id/btns\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_below=\"@+id/tv_inference_time\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginTop=\"30dp\">\n\n                <Button\n                    android:id=\"@+id/btn_play\"\n                    android:layout_width=\"60dp\"\n                    android:layout_height=\"40dp\"\n                    android:background=\"@drawable/button_drawable\"\n                    android:text=\"Play\"\n                    android:textAllCaps=\"false\"\n                    android:textColor=\"#ffffff\" />\n\n                <Button\n                    android:id=\"@+id/btn_pause\"\n                    android:layout_width=\"60dp\"\n                    android:layout_height=\"40dp\"\n                    android:layout_marginLeft=\"3dp\"\n                    android:background=\"@drawable/button_drawable\"\n                    android:text=\"Pause\"\n                    android:textAllCaps=\"false\"\n                    android:textColor=\"#ffffff\" />\n\n                <Button\n                    android:id=\"@+id/btn_stop\"\n                    android:layout_width=\"60dp\"\n                    android:layout_height=\"40dp\"\n                    android:layout_marginLeft=\"3dp\"\n                    android:background=\"@drawable/button_drawable\"\n                    android:text=\"Stop\"\n                    android:textAllCaps=\"false\"\n                    android:textColor=\"#ffffff\" />\n\n            </LinearLayout>\n\n\n        </LinearLayout>\n\n\n    </RelativeLayout>\n\n\n</android.support.constraint.ConstraintLayout>"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/menu/menu_action_options.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <group>\n        <item\n            android:id=\"@+id/settings\"\n            android:title=\"Settings...\"\n            app:showAsAction=\"withText\" />\n    </group>\n</menu>\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/values/arrays.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string-array name=\"cpu_thread_num_entries\">\n        <item>1 threads</item>\n        <item>2 threads</item>\n        <item>4 threads</item>\n        <item>8 threads</item>\n    </string-array>\n    <string-array name=\"cpu_thread_num_values\">\n        <item>1</item>\n        <item>2</item>\n        <item>4</item>\n        <item>8</item>\n    </string-array>\n    <string-array name=\"cpu_power_mode_entries\">\n        <item>HIGH(only big cores)</item>\n        <item>LOW(only LITTLE cores)</item>\n        <item>FULL(all cores)</item>\n        <item>NO_BIND(depends on system)</item>\n        <item>RAND_HIGH</item>\n        <item>RAND_LOW</item>\n    </string-array>\n    <string-array name=\"cpu_power_mode_values\">\n        <item>LITE_POWER_HIGH</item>\n        <item>LITE_POWER_LOW</item>\n        <item>LITE_POWER_FULL</item>\n        <item>LITE_POWER_NO_BIND</item>\n        <item>LITE_POWER_RAND_HIGH</item>\n        <item>LITE_POWER_RAND_LOW</item>\n    </string-array>\n    <string-array name=\"text\">\n        <item>Please select a sentence to be synthesized</item>\n        <item>昨日，这名“伤者”与医生全部被警方依法刑事拘留。</item>\n        <item>钱伟长想到上海来办学校是经过深思熟虑的。</item>\n        <item>她见我一进门就骂，吃饭时也骂，骂得我抬不起头。</item>\n        <item>李述德在离开之前，只说了一句“柱驼杀父亲了”。</item>\n        <item>这种车票和保险单捆绑出售属于重复性购买。</item>\n        <item>戴佩妮的男友西米露接唱情歌，让她非常开心。</item>\n        <item>观大势、谋大局、出大策始终是该院的办院方针。</item>\n        <item>他们骑着摩托回家，正好为农忙时的父母帮忙。</item>\n        <item>但是因为还没到退休年龄，只能掰着指头捱日子。</item>\n        <item>这几天雨水不断，人们恨不得待在家里不出门。</item>\n    </string-array>\n</resources>"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#D81B60</color>\n</resources>\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">TTS</string>\n    <string name=\"CHOOSE_PRE_INSTALLED_MODEL_KEY\">CHOOSE_PRE_INSTALLED_MODEL_KEY</string>\n    <string name=\"ENABLE_CUSTOM_SETTINGS_KEY\">ENABLE_CUSTOM_SETTINGS_KEY</string>\n    <string name=\"MODEL_PATH_KEY\">MODEL_PATH_KEY</string>\n    <string name=\"CPU_THREAD_NUM_KEY\">CPU_THREAD_NUM_KEY</string>\n    <string name=\"CPU_POWER_MODE_KEY\">CPU_POWER_MODE_KEY</string>\n    <string name=\"MODEL_PATH_DEFAULT\">models/cpu</string>\n    <string name=\"CPU_THREAD_NUM_DEFAULT\">1</string>\n    <string name=\"CPU_POWER_MODE_DEFAULT\">LITE_POWER_HIGH</string>\n</resources>\n\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n        <item name=\"actionOverflowMenuStyle\">@style/OverflowMenuStyle</item>\n    </style>\n\n    <style name=\"OverflowMenuStyle\" parent=\"Widget.AppCompat.Light.PopupMenu.Overflow\">\n        <item name=\"overlapAnchor\">false</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/main/res/xml/settings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <PreferenceCategory android:title=\"Model Settings\">\n        <ListPreference\n            android:defaultValue=\"@string/MODEL_PATH_DEFAULT\"\n            android:key=\"@string/CHOOSE_PRE_INSTALLED_MODEL_KEY\"\n            android:negativeButtonText=\"@null\"\n            android:positiveButtonText=\"@null\"\n            android:title=\"Choose pre-installed models\" />\n        <CheckBoxPreference\n            android:defaultValue=\"false\"\n            android:key=\"@string/ENABLE_CUSTOM_SETTINGS_KEY\"\n            android:summaryOff=\"Disable\"\n            android:summaryOn=\"Enable\"\n            android:title=\"Enable custom settings\" />\n        <EditTextPreference\n            android:defaultValue=\"@string/MODEL_PATH_DEFAULT\"\n            android:key=\"@string/MODEL_PATH_KEY\"\n            android:title=\"Model Path\" />\n    </PreferenceCategory>\n    <PreferenceCategory android:title=\"CPU Settings\">\n        <ListPreference\n            android:defaultValue=\"@string/CPU_THREAD_NUM_DEFAULT\"\n            android:entries=\"@array/cpu_thread_num_entries\"\n            android:entryValues=\"@array/cpu_thread_num_values\"\n            android:key=\"@string/CPU_THREAD_NUM_KEY\"\n            android:negativeButtonText=\"@null\"\n            android:positiveButtonText=\"@null\"\n            android:title=\"CPU Thread Num\" />\n        <ListPreference\n            android:defaultValue=\"@string/CPU_POWER_MODE_DEFAULT\"\n            android:entries=\"@array/cpu_power_mode_entries\"\n            android:entryValues=\"@array/cpu_power_mode_values\"\n            android:key=\"@string/CPU_POWER_MODE_KEY\"\n            android:negativeButtonText=\"@null\"\n            android:positiveButtonText=\"@null\"\n            android:title=\"CPU Power Mode\" />\n    </PreferenceCategory>\n</PreferenceScreen>\n"
  },
  {
    "path": "demos/TTSAndroid/app/src/test/java/com/baidu/paddle/lite/demo/tts/ExampleUnitTest.java",
    "content": "package com.baidu.paddle.lite.demo.tts;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "demos/TTSAndroid/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        google()\n        jcenter()\n\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:4.1.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "demos/TTSAndroid/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Jun 16 14:31:28 CST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.0-all.zip\n"
  },
  {
    "path": "demos/TTSAndroid/gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\n\n"
  },
  {
    "path": "demos/TTSAndroid/gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "demos/TTSAndroid/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "demos/TTSAndroid/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "demos/TTSArmLinux/.gitignore",
    "content": "# 目录\nbuild/\noutput/\nlibs/\nmodels/\n\n# 符号连接\ndict\n"
  },
  {
    "path": "demos/TTSArmLinux/README.md",
    "content": "# TTS ARM Linux C++ Demo\n\n修改自 [demos/TTSAndroid](../TTSAndroid)，模型也来自该安卓 Demo。\n\n### 配置编译选项\n\n打开 [config.sh](config.sh) 按需修改配置。\n\n默认编译 64 位版本，如果要编译 32 位版本，把 `ARM_ABI=armv8` 改成 `ARM_ABI=armv7hf` 。\n\n### 安装依赖\n\n```bash\n# Ubuntu\nsudo apt install build-essential cmake pkg-config wget tar unzip\n\n# CentOS\nsudo yum groupinstall \"Development Tools\"\nsudo yum install cmake wget tar unzip\n```\n\n### 下载 Paddle Lite 库文件和模型文件\n\n预编译的二进制使用与安卓 Demo 版本相同的 Paddle Lite 推理库（[Paddle-Lite:68b66fd35](https://github.com/PaddlePaddle/Paddle-Lite/tree/68b66fd356c875c92167d311ad458e6093078449)）和模型（[fs2cnn_mbmelgan_cpu_v1.3.0](https://paddlespeech.cdn.bcebos.com/demos/TTSAndroid/fs2cnn_mbmelgan_cpu_v1.3.0.tar.gz)）。\n\n可用以下命令下载：\n\n```bash\n./download.sh\n```\n\n### 编译 Demo\n\n```bash\n./build.sh\n```\n\n预编译的二进制兼容 Ubuntu 16.04 到 20.04。\n\n如果编译或链接失败，说明发行版与预编译库不兼容，请尝试手动编译 Paddle Lite 库，具体步骤在最下面。\n\n### 运行\n\n你可以修改 `./front.conf` 中 `--phone2id_path` 参数为你自己的声学模型的 `phone_id_map.txt` 。\n\n```bash\n./run.sh\n./run.sh --sentence \"语音合成测试\"\n./run.sh --sentence \"输出到指定的音频文件\" --output_wav ./output/test.wav\n./run.sh --help\n```\n\n目前只支持中文合成，出现任何英文都会导致程序崩溃。\n\n如果未指定`--wav_file`，默认输出到`./output/tts.wav`。\n\n## 手动编译 Paddle Lite 库\n\n预编译的二进制兼容 Ubuntu 16.04 到 20.04，如果你的发行版与其不兼容，可以自行从源代码编译。\n\n注意，我们只能保证 [Paddle-Lite:68b66fd35](https://github.com/PaddlePaddle/Paddle-Lite/tree/68b66fd356c875c92167d311ad458e6093078449) 与通过 `download.sh` 下载的模型兼容。\n如果使用其他版本的 Paddle Lite 库，可能需要用对应版本的 opt 工具重新导出模型。\n\n此外，[Paddle-Lite 2.12](https://github.com/PaddlePaddle/Paddle-Lite/releases/tag/v2.12) 与 TTS 不兼容，无法导出或运行 TTS 模型，需要使用更新的版本（比如 `develop` 分支中的代码）。\n但 `develop` 分支中的代码可能与通过 `download.sh` 下载的模型不兼容，Demo 运行起来可能会崩溃。\n\n### 安装 Paddle Lite 的编译依赖\n\n```bash\n# Ubuntu\nsudo apt install build-essential cmake git python\n\n# CentOS\nsudo yum groupinstall \"Development Tools\"\nsudo yum install cmake git python\n```\n\n### 编译 Paddle Lite 68b66fd35\n\n```\ngit clone https://github.com/PaddlePaddle/Paddle-Lite.git\ncd Paddle-Lite\ngit checkout 68b66fd356c875c92167d311ad458e6093078449\n./lite/tools/build_linux.sh --with_extra=ON\n```\n\n编译完成后，打开 Demo 的 [config.sh](config.sh)，把 `PADDLE_LITE_DIR` 改成以下值即可（注意替换 `/path/to/` 为实际目录）：\n\n```\nPADDLE_LITE_DIR=\"/path/to/Paddle-Lite/build.lite.linux.${ARM_ABI}.gcc/inference_lite_lib.armlinux.${ARM_ABI}/cxx\"\n```\n"
  },
  {
    "path": "demos/TTSArmLinux/build.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\nBASE_DIR=\"$PWD\"\n\n# load configure\n. ./config.sh\n\n# build\necho \"ARM_ABI is ${ARM_ABI}\"\necho \"PADDLE_LITE_DIR is ${PADDLE_LITE_DIR}\"\n\necho \"Build depends...\"\n./build-depends.sh \"$@\"\n\nmkdir -p \"$BASE_DIR/build\"\ncd \"$BASE_DIR/build\"\ncmake -DPADDLE_LITE_DIR=\"${PADDLE_LITE_DIR}\" -DARM_ABI=\"${ARM_ABI}\" ../src\n\nif [ \"$*\" = \"\" ]; then\n    make -j$(nproc)\nelse\n    make \"$@\"\nfi\n\necho \"make successful!\"\n"
  },
  {
    "path": "demos/TTSArmLinux/clean.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\nBASE_DIR=\"$PWD\"\n\n# load configure\n. ./config.sh\n\n# remove dirs\nset -x\n\nrm -rf \"$OUTPUT_DIR\"\nrm -rf \"$LIBS_DIR\"\nrm -rf \"$MODELS_DIR\"\nrm -rf \"$BASE_DIR/build\"\n\n\"$BASE_DIR/src/TTSCppFrontend/clean.sh\"\n\n# 符号连接\nrm \"$BASE_DIR/dict\"\n"
  },
  {
    "path": "demos/TTSArmLinux/config.sh",
    "content": "# configuration\n\nARM_ABI=armv8\n#ARM_ABI=armv7hf\n\nMODELS_DIR=\"${PWD}/models\"\nLIBS_DIR=\"${PWD}/libs\"\nOUTPUT_DIR=\"${PWD}/output\"\n\nPADDLE_LITE_DIR=\"${LIBS_DIR}/inference_lite_lib.armlinux.${ARM_ABI}.gcc.with_extra.with_cv/cxx\"\n#PADDLE_LITE_DIR=\"/path/to/Paddle-Lite/build.lite.linux.${ARM_ABI}.gcc/inference_lite_lib.armlinux.${ARM_ABI}/cxx\"\n\nACOUSTIC_MODEL_PATH=\"${MODELS_DIR}/cpu/fastspeech2_csmsc_arm.nb\"\nVOCODER_PATH=\"${MODELS_DIR}/cpu/mb_melgan_csmsc_arm.nb\"\nFRONT_CONF=\"${PWD}/front.conf\"\n"
  },
  {
    "path": "demos/TTSArmLinux/download.sh",
    "content": "#!/bin/bash\nset -e\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\nBASE_DIR=\"$PWD\"\n\n# load configure\n. ./config.sh\n\nmkdir -p \"$LIBS_DIR\" \"$MODELS_DIR\"\n\ndownload() {\n    file=\"$1\"\n    url=\"$2\"\n    md5=\"$3\"\n    dir=\"$4\"\n\n    cd \"$dir\"\n\n    if [ -f \"$file\" ] && [ \"$(md5sum \"$file\" | awk '{ print $1 }')\" = \"$md5\" ]; then\n        echo \"File $file (MD5: $md5) has been downloaded.\"\n    else\n        echo \"Downloading $file...\"\n        wget -O \"$file\" \"$url\"\n\n        # MD5 verify\n        fileMd5=\"$(md5sum \"$file\" | awk '{ print $1 }')\"\n        if [ \"$fileMd5\" == \"$md5\" ]; then\n            echo \"File $file (MD5: $md5) has been downloaded.\"\n        else\n            echo \"MD5 mismatch, file may be corrupt\"\n            echo \"$file MD5: $fileMd5, it should be $md5\"\n        fi\n    fi\n\n    echo \"Extracting $file...\"\n    echo '-----------------------'\n    tar -vxf \"$file\"\n    echo '======================='\n}\n\n########################################\n\necho \"Download models...\"\n\ndownload 'inference_lite_lib.armlinux.armv8.gcc.with_extra.with_cv.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/demos/TTSArmLinux/inference_lite_lib.armlinux.armv8.gcc.with_extra.with_cv.tar.gz' \\\n    '39e0c6604f97c70f5d13c573d7e709b9' \\\n    \"$LIBS_DIR\"\n\ndownload 'inference_lite_lib.armlinux.armv7hf.gcc.with_extra.with_cv.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/demos/TTSArmLinux/inference_lite_lib.armlinux.armv7hf.gcc.with_extra.with_cv.tar.gz' \\\n    'f5ceb509f0b610dafb8379889c5f36f8' \\\n    \"$LIBS_DIR\"\n\ndownload 'fs2cnn_mbmelgan_cpu_v1.3.0.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/demos/TTSAndroid/fs2cnn_mbmelgan_cpu_v1.3.0.tar.gz' \\\n    '93ef17d44b498aff3bea93e2c5c09a1e' \\\n    \"$MODELS_DIR\"\n\necho \"Done.\"\n\n########################################\n\necho \"Download dictionary files...\"\n\nln -s src/TTSCppFrontend/front_demo/dict \"$BASE_DIR/\"\n\n\"$BASE_DIR/src/TTSCppFrontend/download.sh\"\n"
  },
  {
    "path": "demos/TTSArmLinux/front.conf",
    "content": "# jieba conf\n--jieba_dict_path=./dict/jieba/jieba.dict.utf8\n--jieba_hmm_path=./dict/jieba/hmm_model.utf8\n--jieba_user_dict_path=./dict/jieba/user.dict.utf8\n--jieba_idf_path=./dict/jieba/idf.utf8\n--jieba_stop_word_path=./dict/jieba/stop_words.utf8\n\n# dict conf fastspeech2_0.4\n--separate_tone=false\n--word2phone_path=./dict/fastspeech2_nosil_baker_ckpt_0.4/word2phone_fs2.dict\n--phone2id_path=./dict/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n--tone2id_path=./dict/fastspeech2_nosil_baker_ckpt_0.4/word2phone_fs2.dict\n\n# dict conf speedyspeech_0.5\n#--separate_tone=true\n#--word2phone_path=./dict/speedyspeech_nosil_baker_ckpt_0.5/word2phone.dict\n#--phone2id_path=./dict/speedyspeech_nosil_baker_ckpt_0.5/phone_id_map.txt\n#--tone2id_path=./dict/speedyspeech_nosil_baker_ckpt_0.5/tone_id_map.txt\n\n# dict of tranditional_to_simplified\n--trand2simpd_path=./dict/tranditional_to_simplified/trand2simp.txt\n"
  },
  {
    "path": "demos/TTSArmLinux/run.sh",
    "content": "#!/bin/bash\nset -e\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\n# load configure\n. ./config.sh\n\n# create dir\nmkdir -p \"$OUTPUT_DIR\"\n\n# run\nset -x\n./build/paddlespeech_tts_demo \\\n    --front_conf \"$FRONT_CONF\" \\\n    --acoustic_model \"$ACOUSTIC_MODEL_PATH\" \\\n    --vocoder \"$VOCODER_PATH\" \\\n    \"$@\"\n# end\n"
  },
  {
    "path": "demos/TTSArmLinux/src/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\nproject(paddlespeech_tts_demo)\n\n\n########## Global Options ##########\n\noption(WITH_FRONT_DEMO \"Build front demo\" OFF)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\nset(ABSL_PROPAGATE_CXX_STD ON)\n\n\n########## ARM Options ##########\n\nset(CMAKE_SYSTEM_NAME Linux)\nif(ARM_ABI STREQUAL \"armv8\")\n    set(CMAKE_SYSTEM_PROCESSOR aarch64)\n    #set(CMAKE_C_COMPILER \"aarch64-linux-gnu-gcc\")\n    #set(CMAKE_CXX_COMPILER \"aarch64-linux-gnu-g++\")\nelseif(ARM_ABI STREQUAL \"armv7hf\")\n    set(CMAKE_SYSTEM_PROCESSOR arm)\n    #set(CMAKE_C_COMPILER \"arm-linux-gnueabihf-gcc\")\n    #set(CMAKE_CXX_COMPILER \"arm-linux-gnueabihf-g++\")\nelse()\n    message(FATAL_ERROR \"Unknown arch abi ${ARM_ABI}, only support armv8 and armv7hf.\")\n    return()\nendif()\n\n\n########## Paddle Lite Options ##########\n\nmessage(STATUS \"TARGET ARCH ABI: ${ARM_ABI}\")\nmessage(STATUS \"PADDLE LITE DIR: ${PADDLE_LITE_DIR}\")\n\ninclude_directories(${PADDLE_LITE_DIR}/include)\nlink_directories(${PADDLE_LITE_DIR}/libs/${ARM_ABI})\nlink_directories(${PADDLE_LITE_DIR}/lib)\n\nif(ARM_ABI STREQUAL \"armv8\")\n    set(CMAKE_CXX_FLAGS \"-march=armv8-a ${CMAKE_CXX_FLAGS}\")\n    set(CMAKE_C_FLAGS \"-march=armv8-a ${CMAKE_C_FLAGS}\")\nelseif(ARM_ABI STREQUAL \"armv7hf\")\n    set(CMAKE_CXX_FLAGS \"-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_CXX_FLAGS}\")\n    set(CMAKE_C_FLAGS \"-march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ${CMAKE_C_FLAGS}\" )\nendif()\n\n\n########## Dependencies ##########\n\nfind_package(OpenMP REQUIRED)\nif(OpenMP_FOUND OR OpenMP_CXX_FOUND)\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}\")\n    message(STATUS \"Found OpenMP ${OpenMP_VERSION} ${OpenMP_CXX_VERSION}\")\n    message(STATUS \"OpenMP C flags:  ${OpenMP_C_FLAGS}\")\n    message(STATUS \"OpenMP CXX flags:  ${OpenMP_CXX_FLAGS}\")\n    message(STATUS \"OpenMP OpenMP_CXX_LIB_NAMES:  ${OpenMP_CXX_LIB_NAMES}\")\n    message(STATUS \"OpenMP OpenMP_CXX_LIBRARIES:  ${OpenMP_CXX_LIBRARIES}\")\nelse()\n    message(FATAL_ERROR \"Could not found OpenMP!\")\n    return()\nendif()\n\n\n############### tts cpp frontend ###############\n\nadd_subdirectory(TTSCppFrontend)\n\ninclude_directories(\n    TTSCppFrontend/src\n    third-party/build/src/cppjieba/include\n    third-party/build/src/limonp/include\n)\n\n\n############### paddlespeech_tts_demo ###############\n\nadd_executable(paddlespeech_tts_demo main.cc)\ntarget_link_libraries(paddlespeech_tts_demo paddle_light_api_shared paddlespeech_tts_front)\n"
  },
  {
    "path": "demos/TTSArmLinux/src/Predictor.hpp",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include <algorithm>\n#include <chrono>\n#include <fstream>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n#include \"paddle_api.h\"\n\nusing namespace paddle::lite_api;\n\nclass PredictorInterface {\n  public:\n    virtual ~PredictorInterface() = 0;\n    virtual bool Init(const std::string &AcousticModelPath,\n                      const std::string &VocoderPath,\n                      PowerMode cpuPowerMode,\n                      int cpuThreadNum,\n                      // WAV采样率（必须与模型输出匹配）\n                      // 如果播放速度和音调异常，请修改采样率\n                      // 常见采样率：16000, 24000, 32000, 44100, 48000, 96000\n                      uint32_t wavSampleRate) = 0;\n    virtual std::shared_ptr<PaddlePredictor> LoadModel(\n        const std::string &modelPath,\n        int cpuThreadNum,\n        PowerMode cpuPowerMode) = 0;\n    virtual void ReleaseModel() = 0;\n    virtual bool RunModel(const std::vector<int64_t> &phones) = 0;\n    virtual std::unique_ptr<const Tensor> GetAcousticModelOutput(\n        const std::vector<int64_t> &phones) = 0;\n    virtual std::unique_ptr<const Tensor> GetVocoderOutput(\n        std::unique_ptr<const Tensor> &&amOutput) = 0;\n    virtual void VocoderOutputToWav(\n        std::unique_ptr<const Tensor> &&vocOutput) = 0;\n    virtual void SaveFloatWav(float *floatWav, int64_t size) = 0;\n    virtual bool IsLoaded() = 0;\n    virtual float GetInferenceTime() = 0;\n    virtual int GetWavSize() = 0;\n    // 获取WAV持续时间（单位：毫秒）\n    virtual float GetWavDuration() = 0;\n    // 获取RTF（合成时间 / 音频时长）\n    virtual float GetRTF() = 0;\n    virtual void ReleaseWav() = 0;\n    virtual bool WriteWavToFile(const std::string &wavPath) = 0;\n};\n\nPredictorInterface::~PredictorInterface() {}\n\n// WavDataType: WAV数据类型\n// 可在 int16_t 和 float 之间切换，\n// 用于生成 16-bit PCM 或 32-bit IEEE float 格式的 WAV\ntemplate <typename WavDataType>\nclass Predictor : public PredictorInterface {\n  public:\n    bool Init(const std::string &AcousticModelPath,\n              const std::string &VocoderPath,\n              PowerMode cpuPowerMode,\n              int cpuThreadNum,\n              // WAV采样率（必须与模型输出匹配）\n              // 如果播放速度和音调异常，请修改采样率\n              // 常见采样率：16000, 24000, 32000, 44100, 48000, 96000\n              uint32_t wavSampleRate) override {\n        // Release model if exists\n        ReleaseModel();\n\n        acoustic_model_predictor_ =\n            LoadModel(AcousticModelPath, cpuThreadNum, cpuPowerMode);\n        if (acoustic_model_predictor_ == nullptr) {\n            return false;\n        }\n        vocoder_predictor_ = LoadModel(VocoderPath, cpuThreadNum, cpuPowerMode);\n        if (vocoder_predictor_ == nullptr) {\n            return false;\n        }\n\n        wav_sample_rate_ = wavSampleRate;\n\n        return true;\n    }\n\n    virtual ~Predictor() {\n        ReleaseModel();\n        ReleaseWav();\n    }\n\n    std::shared_ptr<PaddlePredictor> LoadModel(\n        const std::string &modelPath,\n        int cpuThreadNum,\n        PowerMode cpuPowerMode) override {\n        if (modelPath.empty()) {\n            return nullptr;\n        }\n\n        // 设置MobileConfig\n        MobileConfig config;\n        config.set_model_from_file(modelPath);\n        config.set_threads(cpuThreadNum);\n        config.set_power_mode(cpuPowerMode);\n\n        return CreatePaddlePredictor<MobileConfig>(config);\n    }\n\n    void ReleaseModel() override {\n        acoustic_model_predictor_ = nullptr;\n        vocoder_predictor_ = nullptr;\n    }\n\n    bool RunModel(const std::vector<int64_t> &phones) override {\n        if (!IsLoaded()) {\n            return false;\n        }\n\n        // 计时开始\n        auto start = std::chrono::system_clock::now();\n\n        // 执行推理\n        VocoderOutputToWav(GetVocoderOutput(GetAcousticModelOutput(phones)));\n\n        // 计时结束\n        auto end = std::chrono::system_clock::now();\n\n        // 计算用时\n        std::chrono::duration<float> duration = end - start;\n        inference_time_ = duration.count() * 1000;  // 单位：毫秒\n\n        return true;\n    }\n\n    std::unique_ptr<const Tensor> GetAcousticModelOutput(\n        const std::vector<int64_t> &phones) override {\n        auto phones_handle = acoustic_model_predictor_->GetInput(0);\n        phones_handle->Resize({static_cast<int64_t>(phones.size())});\n        phones_handle->CopyFromCpu(phones.data());\n        acoustic_model_predictor_->Run();\n\n        // 获取输出Tensor\n        auto am_output_handle = acoustic_model_predictor_->GetOutput(0);\n        // 打印输出Tensor的shape\n        std::cout << \"Acoustic Model Output shape: \";\n        auto shape = am_output_handle->shape();\n        for (auto s : shape) {\n            std::cout << s << \", \";\n        }\n        std::cout << std::endl;\n\n        return am_output_handle;\n    }\n\n    std::unique_ptr<const Tensor> GetVocoderOutput(\n        std::unique_ptr<const Tensor> &&amOutput) override {\n        auto mel_handle = vocoder_predictor_->GetInput(0);\n        // [?, 80]\n        auto dims = amOutput->shape();\n        mel_handle->Resize(dims);\n        auto am_output_data = amOutput->mutable_data<float>();\n        mel_handle->CopyFromCpu(am_output_data);\n        vocoder_predictor_->Run();\n\n        // 获取输出Tensor\n        auto voc_output_handle = vocoder_predictor_->GetOutput(0);\n        // 打印输出Tensor的shape\n        std::cout << \"Vocoder Output shape: \";\n        auto shape = voc_output_handle->shape();\n        for (auto s : shape) {\n            std::cout << s << \", \";\n        }\n        std::cout << std::endl;\n\n        return voc_output_handle;\n    }\n\n    void VocoderOutputToWav(\n        std::unique_ptr<const Tensor> &&vocOutput) override {\n        // 获取输出Tensor的数据\n        int64_t output_size = 1;\n        for (auto dim : vocOutput->shape()) {\n            output_size *= dim;\n        }\n        auto output_data = vocOutput->mutable_data<float>();\n\n        SaveFloatWav(output_data, output_size);\n    }\n\n    void SaveFloatWav(float *floatWav, int64_t size) override;\n\n    bool IsLoaded() override {\n        return acoustic_model_predictor_ != nullptr &&\n               vocoder_predictor_ != nullptr;\n    }\n\n    float GetInferenceTime() override { return inference_time_; }\n\n    const std::vector<WavDataType> &GetWav() { return wav_; }\n\n    int GetWavSize() override { return wav_.size() * sizeof(WavDataType); }\n\n    // 获取WAV持续时间（单位：毫秒）\n    float GetWavDuration() override {\n        return static_cast<float>(GetWavSize()) / sizeof(WavDataType) /\n               static_cast<float>(wav_sample_rate_) * 1000;\n    }\n\n    // 获取RTF（合成时间 / 音频时长）\n    float GetRTF() override { return GetInferenceTime() / GetWavDuration(); }\n\n    void ReleaseWav() override { wav_.clear(); }\n\n    bool WriteWavToFile(const std::string &wavPath) override {\n        std::ofstream fout(wavPath, std::ios::binary);\n        if (!fout.is_open()) {\n            return false;\n        }\n\n        // 写入头信息\n        WavHeader header;\n        header.audio_format = GetWavAudioFormat();\n        header.data_size = GetWavSize();\n        header.size = sizeof(header) - 8 + header.data_size;\n        header.sample_rate = wav_sample_rate_;\n        header.byte_rate = header.sample_rate * header.num_channels *\n                           header.bits_per_sample / 8;\n        header.block_align = header.num_channels * header.bits_per_sample / 8;\n        fout.write(reinterpret_cast<const char *>(&header), sizeof(header));\n\n        // 写入wav数据\n        fout.write(reinterpret_cast<const char *>(wav_.data()),\n                   header.data_size);\n\n        fout.close();\n        return true;\n    }\n\n  protected:\n    struct WavHeader {\n        // RIFF 头\n        char riff[4] = {'R', 'I', 'F', 'F'};\n        uint32_t size = 0;\n        char wave[4] = {'W', 'A', 'V', 'E'};\n\n        // FMT 头\n        char fmt[4] = {'f', 'm', 't', ' '};\n        uint32_t fmt_size = 16;\n        uint16_t audio_format = 0;\n        uint16_t num_channels = 1;\n        uint32_t sample_rate = 0;\n        uint32_t byte_rate = 0;\n        uint16_t block_align = 0;\n        uint16_t bits_per_sample = sizeof(WavDataType) * 8;\n\n        // DATA 头\n        char data[4] = {'d', 'a', 't', 'a'};\n        uint32_t data_size = 0;\n    };\n\n    enum WavAudioFormat {\n        WAV_FORMAT_16BIT_PCM = 1,   // 16-bit PCM 格式\n        WAV_FORMAT_32BIT_FLOAT = 3  // 32-bit IEEE float 格式\n    };\n\n  protected:\n    // 返回值通过模板特化由 WavDataType 决定\n    inline uint16_t GetWavAudioFormat();\n\n    inline float Abs(float number) { return (number < 0) ? -number : number; }\n\n  protected:\n    float inference_time_ = 0;\n    uint32_t wav_sample_rate_ = 0;\n    std::vector<WavDataType> wav_;\n    std::shared_ptr<PaddlePredictor> acoustic_model_predictor_ = nullptr;\n    std::shared_ptr<PaddlePredictor> vocoder_predictor_ = nullptr;\n};\n\ntemplate <>\nuint16_t Predictor<int16_t>::GetWavAudioFormat() {\n    return Predictor::WAV_FORMAT_16BIT_PCM;\n}\n\ntemplate <>\nuint16_t Predictor<float>::GetWavAudioFormat() {\n    return Predictor::WAV_FORMAT_32BIT_FLOAT;\n}\n\n// 保存 16-bit PCM 格式 WAV\ntemplate <>\nvoid Predictor<int16_t>::SaveFloatWav(float *floatWav, int64_t size) {\n    wav_.resize(size);\n    float maxSample = 0.01;\n    // 寻找最大采样值\n    for (int64_t i = 0; i < size; i++) {\n        float sample = Abs(floatWav[i]);\n        if (sample > maxSample) {\n            maxSample = sample;\n        }\n    }\n    // 把采样值缩放到 int_16 范围\n    for (int64_t i = 0; i < size; i++) {\n        wav_[i] = floatWav[i] * 32767.0f / maxSample;\n    }\n}\n\n// 保存 32-bit IEEE float 格式 WAV\ntemplate <>\nvoid Predictor<float>::SaveFloatWav(float *floatWav, int64_t size) {\n    wav_.resize(size);\n    std::copy_n(floatWav, size, wav_.data());\n}\n"
  },
  {
    "path": "demos/TTSArmLinux/src/main.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <front/front_interface.h>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <paddle_api.h>\n#include <cstdlib>\n#include <iostream>\n#include <map>\n#include <memory>\n#include <string>\n#include \"Predictor.hpp\"\n\nusing namespace paddle::lite_api;\n\nDEFINE_string(\n    sentence,\n    \"你好，欢迎使用语音合成服务\",\n    \"Text to be synthesized (Chinese only. English will crash the program.)\");\nDEFINE_string(front_conf, \"./front.conf\", \"Front configuration file\");\nDEFINE_string(acoustic_model,\n              \"./models/cpu/fastspeech2_csmsc_arm.nb\",\n              \"Acoustic model .nb file\");\nDEFINE_string(vocoder,\n              \"./models/cpu/fastspeech2_csmsc_arm.nb\",\n              \"vocoder .nb file\");\nDEFINE_string(output_wav, \"./output/tts.wav\", \"Output WAV file\");\nDEFINE_string(wav_bit_depth,\n              \"16\",\n              \"WAV bit depth, 16 (16-bit PCM) or 32 (32-bit IEEE float)\");\nDEFINE_string(wav_sample_rate,\n              \"24000\",\n              \"WAV sample rate, should match the output of the vocoder\");\nDEFINE_string(cpu_thread, \"1\", \"CPU thread numbers\");\n\nint main(int argc, char *argv[]) {\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    PredictorInterface *predictor;\n\n    if (FLAGS_wav_bit_depth == \"16\") {\n        predictor = new Predictor<int16_t>();\n    } else if (FLAGS_wav_bit_depth == \"32\") {\n        predictor = new Predictor<float>();\n    } else {\n        LOG(ERROR) << \"Unsupported WAV bit depth: \" << FLAGS_wav_bit_depth;\n        return -1;\n    }\n\n\n    /////////////////////////// 前端：文本转音素 ///////////////////////////\n\n    // 实例化文本前端引擎\n    ppspeech::FrontEngineInterface *front_inst = nullptr;\n    front_inst = new ppspeech::FrontEngineInterface(FLAGS_front_conf);\n    if ((!front_inst) || (front_inst->init())) {\n        LOG(ERROR) << \"Creater tts engine failed!\";\n        if (front_inst != nullptr) {\n            delete front_inst;\n        }\n        front_inst = nullptr;\n        return -1;\n    }\n\n    std::wstring ws_sentence = ppspeech::utf8string2wstring(FLAGS_sentence);\n\n    // 繁体转简体\n    std::wstring sentence_simp;\n    front_inst->Trand2Simp(ws_sentence, &sentence_simp);\n    ws_sentence = sentence_simp;\n\n    std::string s_sentence;\n    std::vector<std::wstring> sentence_part;\n    std::vector<int> phoneids = {};\n    std::vector<int> toneids = {};\n\n    // 根据标点进行分句\n    LOG(INFO) << \"Start to segment sentences by punctuation\";\n    front_inst->SplitByPunc(ws_sentence, &sentence_part);\n    LOG(INFO) << \"Segment sentences through punctuation successfully\";\n\n    // 分句后获取音素id\n    LOG(INFO)\n        << \"Start to get the phoneme and tone id sequence of each sentence\";\n    for (int i = 0; i < sentence_part.size(); i++) {\n        LOG(INFO) << \"Raw sentence is: \"\n                  << ppspeech::wstring2utf8string(sentence_part[i]);\n        front_inst->SentenceNormalize(&sentence_part[i]);\n        s_sentence = ppspeech::wstring2utf8string(sentence_part[i]);\n        LOG(INFO) << \"After normalization sentence is: \" << s_sentence;\n\n        if (0 != front_inst->GetSentenceIds(s_sentence, &phoneids, &toneids)) {\n            LOG(ERROR) << \"TTS inst get sentence phoneids and toneids failed\";\n            return -1;\n        }\n    }\n    LOG(INFO) << \"The phoneids of the sentence is: \"\n              << limonp::Join(phoneids.begin(), phoneids.end(), \" \");\n    LOG(INFO) << \"The toneids of the sentence is: \"\n              << limonp::Join(toneids.begin(), toneids.end(), \" \");\n    LOG(INFO) << \"Get the phoneme id sequence of each sentence successfully\";\n\n\n    /////////////////////////// 后端：音素转音频 ///////////////////////////\n\n    // WAV采样率（必须与模型输出匹配）\n    // 如果播放速度和音调异常，请修改采样率\n    // 常见采样率：16000, 24000, 32000, 44100, 48000, 96000\n    const uint32_t wavSampleRate = std::stoul(FLAGS_wav_sample_rate);\n\n    // CPU线程数\n    const int cpuThreadNum = std::stol(FLAGS_cpu_thread);\n\n    // CPU电源模式\n    const PowerMode cpuPowerMode = PowerMode::LITE_POWER_HIGH;\n\n    if (!predictor->Init(FLAGS_acoustic_model,\n                         FLAGS_vocoder,\n                         cpuPowerMode,\n                         cpuThreadNum,\n                         wavSampleRate)) {\n        LOG(ERROR) << \"predictor init failed\" << std::endl;\n        return -1;\n    }\n\n    std::vector<int64_t> phones(phoneids.size());\n    std::transform(phoneids.begin(), phoneids.end(), phones.begin(), [](int x) {\n        return static_cast<int64_t>(x);\n    });\n\n    if (!predictor->RunModel(phones)) {\n        LOG(ERROR) << \"predictor run model failed\" << std::endl;\n        return -1;\n    }\n\n    LOG(INFO) << \"Inference time: \" << predictor->GetInferenceTime() << \" ms, \"\n              << \"WAV size (without header): \" << predictor->GetWavSize()\n              << \" bytes, \"\n              << \"WAV duration: \" << predictor->GetWavDuration() << \" ms, \"\n              << \"RTF: \" << predictor->GetRTF() << std::endl;\n\n    if (!predictor->WriteWavToFile(FLAGS_output_wav)) {\n        LOG(ERROR) << \"write wav file failed\" << std::endl;\n        return -1;\n    }\n\n    delete predictor;\n\n    return 0;\n}\n"
  },
  {
    "path": "demos/TTSCppFrontend/.gitignore",
    "content": "build/\ndict/\n"
  },
  {
    "path": "demos/TTSCppFrontend/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\nproject(paddlespeech_tts_cpp)\n\n\n########## Global Options ##########\n\noption(WITH_FRONT_DEMO \"Build front demo\" ON)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\nset(ABSL_PROPAGATE_CXX_STD ON)\n\n\n########## Dependencies ##########\n\nset(ENV{PKG_CONFIG_PATH} \"${CMAKE_SOURCE_DIR}/third-party/build/lib/pkgconfig:${CMAKE_SOURCE_DIR}/third-party/build/lib64/pkgconfig\")\nfind_package(PkgConfig REQUIRED)\n\n# It is hard to load xxx-config.cmake in a custom location, so use pkgconfig instead.\npkg_check_modules(ABSL   REQUIRED absl_strings IMPORTED_TARGET)\npkg_check_modules(GFLAGS REQUIRED gflags       IMPORTED_TARGET)\npkg_check_modules(GLOG   REQUIRED libglog      IMPORTED_TARGET)\n\n# load header-only libraries\ninclude_directories(\n    ${CMAKE_SOURCE_DIR}/third-party/build/src/cppjieba/include\n    ${CMAKE_SOURCE_DIR}/third-party/build/src/limonp/include\n)\n\nfind_package(Threads REQUIRED)\n\n\n########## paddlespeech_tts_front ##########\n\ninclude_directories(src)\n\nfile(GLOB FRONT_SOURCES\n    ./src/base/*.cpp\n    ./src/front/*.cpp\n)\nadd_library(paddlespeech_tts_front STATIC ${FRONT_SOURCES})\n\ntarget_link_libraries(\n    paddlespeech_tts_front\n    PUBLIC\n    PkgConfig::GFLAGS\n    PkgConfig::GLOG\n    PkgConfig::ABSL\n    Threads::Threads\n)\n\n\n########## tts_front_demo ##########\n\nif (WITH_FRONT_DEMO)\n\n    file(GLOB FRONT_DEMO_SOURCES front_demo/*.cpp)\n    add_executable(tts_front_demo ${FRONT_DEMO_SOURCES})\n\n    target_include_directories(tts_front_demo PRIVATE ./front_demo)\n    target_link_libraries(tts_front_demo PRIVATE paddlespeech_tts_front)\n\nendif (WITH_FRONT_DEMO)\n"
  },
  {
    "path": "demos/TTSCppFrontend/README.md",
    "content": "# PaddleSpeech TTS CPP Frontend\n\nA TTS frontend that implements text-to-phoneme conversion.\n\nCurrently it only supports Chinese, any English word will crash the demo.\n\n## Install Build Tools\n\n```bash\n# Ubuntu\nsudo apt install build-essential cmake pkg-config\n\n# CentOS\nsudo yum groupinstall \"Development Tools\"\nsudo yum install cmake\n```\n\nIf your cmake version is too old, you can go here to download a precompiled new version: https://cmake.org/download/\n\n## Build\n\n```bash\n# Build with all CPU cores\n./build.sh\n\n# Build with 1 core\n./build.sh -j1\n```\n\nDependent libraries will be automatically downloaded to the `third-party/build` folder.\n\nIf the download speed is too slow, you can open [third-party/CMakeLists.txt](third-party/CMakeLists.txt) and modify `GIT_REPOSITORY` URLs.\n\n## Download dictionary files\n\n```bash\n./download.sh\n```\n\n## Run\nYou can change `--phone2id_path` in `./front_demo/front.conf` to the `phone_id_map.txt` of your own acoustic model.\n\n```bash\n./run_front_demo.sh\n./run_front_demo.sh --help\n./run_front_demo.sh --sentence \"这是语音合成服务的文本前端，用于将文本转换为音素序号数组。\"\n./run_front_demo.sh --front_conf ./front_demo/front.conf --sentence \"你还需要一个语音合成后端才能将其转换为实际的声音。\"\n```\n\n## Clean\n\n```bash\n./clean.sh\n```\n\nThe folders `front_demo/dict`, `build` and `third-party/build` will be deleted.\n"
  },
  {
    "path": "demos/TTSCppFrontend/build-depends.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\ncd ./third-party\n\nmkdir -p build\ncd build\n\ncmake ..\n\nif [ \"$*\" = \"\" ]; then\n    make -j$(nproc)\nelse\n    make \"$@\"\nfi\n\necho \"Done.\"\n"
  },
  {
    "path": "demos/TTSCppFrontend/build.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\necho \"************* Download & Build Dependencies *************\"\n./build-depends.sh \"$@\"\n\necho \"************* Build Front Lib and Demo *************\"\nmkdir -p ./build\ncd ./build\ncmake ..\n\nif [ \"$*\" = \"\" ]; then\n    make -j$(nproc)\nelse\n    make \"$@\"\nfi\n\necho \"Done.\"\n"
  },
  {
    "path": "demos/TTSCppFrontend/clean.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\nrm -rf \"./front_demo/dict\"\nrm -rf \"./build\"\nrm -rf \"./third-party/build\"\n\necho \"Done.\"\n"
  },
  {
    "path": "demos/TTSCppFrontend/download.sh",
    "content": "#!/bin/bash\nset -e\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\ndownload() {\n    file=\"$1\"\n    url=\"$2\"\n    md5=\"$3\"\n    dir=\"$4\"\n\n    cd \"$dir\"\n\n    if [ -f \"$file\" ] && [ \"$(md5sum \"$file\" | awk '{ print $1 }')\" = \"$md5\" ]; then\n        echo \"File $file (MD5: $md5) has been downloaded.\"\n    else\n        echo \"Downloading $file...\"\n        wget -O \"$file\" \"$url\"\n\n        # MD5 verify\n        fileMd5=\"$(md5sum \"$file\" | awk '{ print $1 }')\"\n        if [ \"$fileMd5\" == \"$md5\" ]; then\n            echo \"File $file (MD5: $md5) has been downloaded.\"\n        else\n            echo \"MD5 mismatch, file may be corrupt\"\n            echo \"$file MD5: $fileMd5, it should be $md5\"\n        fi\n    fi\n\n    echo \"Extracting $file...\"\n    echo '-----------------------'\n    tar -vxf \"$file\"\n    echo '======================='\n}\n\n########################################\n\nDIST_DIR=\"$PWD/front_demo/dict\"\n\nmkdir -p \"$DIST_DIR\"\n\ndownload 'fastspeech2_nosil_baker_ckpt_0.4.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/t2s/text_frontend/fastspeech2_nosil_baker_ckpt_0.4.tar.gz' \\\n    '7bf1bab1737375fa123c413eb429c573' \\\n    \"$DIST_DIR\"\n\ndownload 'speedyspeech_nosil_baker_ckpt_0.5.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/t2s/text_frontend/speedyspeech_nosil_baker_ckpt_0.5.tar.gz' \\\n    '0b7754b21f324789aef469c61f4d5b8f' \\\n    \"$DIST_DIR\"\n\ndownload 'jieba.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/t2s/text_frontend/jieba.tar.gz' \\\n    '6d30f426bd8c0025110a483f051315ca' \\\n    \"$DIST_DIR\"\n\ndownload 'tranditional_to_simplified.tar.gz' \\\n    'https://paddlespeech.cdn.bcebos.com/t2s/text_frontend/tranditional_to_simplified.tar.gz' \\\n    '258f5b59d5ebfe96d02007ca1d274a7f' \\\n    \"$DIST_DIR\"\n\necho \"Done.\"\n"
  },
  {
    "path": "demos/TTSCppFrontend/front_demo/front.conf",
    "content": "# jieba conf\n--jieba_dict_path=./front_demo/dict/jieba/jieba.dict.utf8\n--jieba_hmm_path=./front_demo/dict/jieba/hmm_model.utf8\n--jieba_user_dict_path=./front_demo/dict/jieba/user.dict.utf8\n--jieba_idf_path=./front_demo/dict/jieba/idf.utf8\n--jieba_stop_word_path=./front_demo/dict/jieba/stop_words.utf8\n\n# dict conf fastspeech2_0.4\n--separate_tone=false\n--word2phone_path=./front_demo/dict/fastspeech2_nosil_baker_ckpt_0.4/word2phone_fs2.dict\n--phone2id_path=./front_demo/dict/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n--tone2id_path=./front_demo/dict/fastspeech2_nosil_baker_ckpt_0.4/word2phone_fs2.dict\n\n# dict conf speedyspeech_0.5\n#--separate_tone=true\n#--word2phone_path=./front_demo/dict/speedyspeech_nosil_baker_ckpt_0.5/word2phone.dict\n#--phone2id_path=./front_demo/dict/speedyspeech_nosil_baker_ckpt_0.5/phone_id_map.txt\n#--tone2id_path=./front_demo/dict/speedyspeech_nosil_baker_ckpt_0.5/tone_id_map.txt\n\n# dict of tranditional_to_simplified\n--trand2simpd_path=./front_demo/dict/tranditional_to_simplified/trand2simp.txt\n"
  },
  {
    "path": "demos/TTSCppFrontend/front_demo/front_demo.cpp",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <map>\n#include <string>\n#include \"front/front_interface.h\"\n\nDEFINE_string(sentence, \"你好，欢迎使用语音合成服务\", \"Text to be synthesized\");\nDEFINE_string(front_conf, \"./front_demo/front.conf\", \"Front conf file\");\n// DEFINE_string(separate_tone, \"true\", \"If true, get phoneids and tonesid\");\n\n\nint main(int argc, char** argv) {\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n    // 实例化文本前端引擎\n    ppspeech::FrontEngineInterface* front_inst = nullptr;\n    front_inst = new ppspeech::FrontEngineInterface(FLAGS_front_conf);\n    if ((!front_inst) || (front_inst->init())) {\n        LOG(ERROR) << \"Creater tts engine failed!\";\n        if (front_inst != nullptr) {\n            delete front_inst;\n        }\n        front_inst = nullptr;\n        return -1;\n    }\n\n    std::wstring ws_sentence = ppspeech::utf8string2wstring(FLAGS_sentence);\n\n    // 繁体转简体\n    std::wstring sentence_simp;\n    front_inst->Trand2Simp(ws_sentence, &sentence_simp);\n    ws_sentence = sentence_simp;\n\n    std::string s_sentence;\n    std::vector<std::wstring> sentence_part;\n    std::vector<int> phoneids = {};\n    std::vector<int> toneids = {};\n\n    // 根据标点进行分句\n    LOG(INFO) << \"Start to segment sentences by punctuation\";\n    front_inst->SplitByPunc(ws_sentence, &sentence_part);\n    LOG(INFO) << \"Segment sentences through punctuation successfully\";\n\n    // 分句后获取音素id\n    LOG(INFO)\n        << \"Start to get the phoneme and tone id sequence of each sentence\";\n    for (int i = 0; i < sentence_part.size(); i++) {\n        LOG(INFO) << \"Raw sentence is: \"\n                  << ppspeech::wstring2utf8string(sentence_part[i]);\n        front_inst->SentenceNormalize(&sentence_part[i]);\n        s_sentence = ppspeech::wstring2utf8string(sentence_part[i]);\n        LOG(INFO) << \"After normalization sentence is: \" << s_sentence;\n\n        if (0 != front_inst->GetSentenceIds(s_sentence, &phoneids, &toneids)) {\n            LOG(ERROR) << \"TTS inst get sentence phoneids and toneids failed\";\n            return -1;\n        }\n    }\n    LOG(INFO) << \"The phoneids of the sentence is: \"\n              << limonp::Join(phoneids.begin(), phoneids.end(), \" \");\n    LOG(INFO) << \"The toneids of the sentence is: \"\n              << limonp::Join(toneids.begin(), toneids.end(), \" \");\n    LOG(INFO) << \"Get the phoneme id sequence of each sentence successfully\";\n\n    return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "demos/TTSCppFrontend/front_demo/gentools/gen_dict_paddlespeech.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport configparser\n\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\n\ndef get_phone(frontend,\n              word,\n              merge_sentences=True,\n              print_info=False,\n              robot=False,\n              get_tone_ids=False):\n    phonemes = frontend.get_phonemes(word, merge_sentences, print_info, robot)\n    # Some optimizations\n    phones, tones = frontend._get_phone_tone(phonemes[0], get_tone_ids)\n    #print(type(phones), phones)\n    #print(type(tones), tones)\n    return phones, tones\n\n\ndef gen_word2phone_dict(frontend,\n                        jieba_words_dict,\n                        word2phone_dict,\n                        get_tone=False):\n    with open(jieba_words_dict, \"r\") as f1, open(word2phone_dict, \"w+\") as f2:\n        for line in f1.readlines():\n            word = line.split(\" \")[0]\n            phone, tone = get_phone(frontend, word, get_tone_ids=get_tone)\n            phone_str = \"\"\n\n            if tone:\n                assert (len(phone) == len(tone))\n                for i in range(len(tone)):\n                    phone_tone = phone[i] + tone[i]\n                    phone_str += (\" \" + phone_tone)\n                phone_str = phone_str.strip(\"sp0\").strip(\" \")\n            else:\n                for x in phone:\n                    phone_str += (\" \" + x)\n                phone_str = phone_str.strip(\"sp\").strip(\" \")\n            print(phone_str)\n            f2.write(word + \" \" + phone_str + \"\\n\")\n    print(\"Generate word2phone dict successfully.\")\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Generate dictionary\")\n    parser.add_argument(\n        \"--config\", type=str, default=\"./config.ini\", help=\"config file.\")\n    parser.add_argument(\n        \"--am_type\",\n        type=str,\n        default=\"fastspeech2\",\n        help=\"fastspeech2 or speedyspeech\")\n    args = parser.parse_args()\n\n    # Read config\n    cf = configparser.ConfigParser()\n    cf.read(args.config)\n    jieba_words_dict_file = cf.get(\"jieba\",\n                                   \"jieba_words_dict\")  # get words dict\n\n    am_type = args.am_type\n    if (am_type == \"fastspeech2\"):\n        phone2id_dict_file = cf.get(am_type, \"phone2id_dict\")\n        word2phone_dict_file = cf.get(am_type, \"word2phone_dict\")\n\n        frontend = Frontend(phone_vocab_path=phone2id_dict_file)\n        print(\"frontend done!\")\n\n        gen_word2phone_dict(\n            frontend,\n            jieba_words_dict_file,\n            word2phone_dict_file,\n            get_tone=False)\n\n    elif (am_type == \"speedyspeech\"):\n        phone2id_dict_file = cf.get(am_type, \"phone2id_dict\")\n        tone2id_dict_file = cf.get(am_type, \"tone2id_dict\")\n        word2phone_dict_file = cf.get(am_type, \"word2phone_dict\")\n\n        frontend = Frontend(\n            phone_vocab_path=phone2id_dict_file,\n            tone_vocab_path=tone2id_dict_file)\n        print(\"frontend done!\")\n\n        gen_word2phone_dict(\n            frontend,\n            jieba_words_dict_file,\n            word2phone_dict_file,\n            get_tone=True)\n\n    else:\n        print(\"Please set correct am type, fastspeech2 or speedyspeech.\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "demos/TTSCppFrontend/front_demo/gentools/genid.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nPHONESFILE = \"./dict/phones.txt\"\nPHONES_ID_FILE = \"./dict/phonesid.dict\"\nTONESFILE = \"./dict/tones.txt\"\nTONES_ID_FILE = \"./dict/tonesid.dict\"\n\n\ndef GenIdFile(file, idfile):\n    id = 2\n    with open(file, 'r') as f1, open(idfile, \"w+\") as f2:\n        f2.write(\"<pad> 0\\n\")\n        f2.write(\"<unk> 1\\n\")\n        for line in f1.readlines():\n            phone = line.strip()\n            print(phone + \" \" + str(id) + \"\\n\")\n            f2.write(phone + \" \" + str(id) + \"\\n\")\n            id += 1\n\n\nif __name__ == \"__main__\":\n    GenIdFile(PHONESFILE, PHONES_ID_FILE)\n    GenIdFile(TONESFILE, TONES_ID_FILE)\n"
  },
  {
    "path": "demos/TTSCppFrontend/front_demo/gentools/word2phones.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\n\nfrom pypinyin import lazy_pinyin\nfrom pypinyin import Style\n\nworddict = \"./dict/jieba_part.dict.utf8\"\nnewdict = \"./dict/word_phones.dict\"\n\n\ndef GenPhones(initials, finals, separate=True):\n\n    phones = []\n    for c, v in zip(initials, finals):\n        if re.match(r'i\\d', v):\n            if c in ['z', 'c', 's']:\n                v = re.sub('i', 'ii', v)\n            elif c in ['zh', 'ch', 'sh', 'r']:\n                v = re.sub('i', 'iii', v)\n        if c:\n            if separate is True:\n                phones.append(c + '0')\n            elif separate is False:\n                phones.append(c)\n            else:\n                print(\"Not sure whether phone and tone need to be separated\")\n        if v:\n            phones.append(v)\n    return phones\n\n\nwith open(worddict, \"r\") as f1, open(newdict, \"w+\") as f2:\n    for line in f1.readlines():\n        word = line.split(\" \")[0]\n        initials = lazy_pinyin(\n            word, neutral_tone_with_five=True, style=Style.INITIALS)\n        finals = lazy_pinyin(\n            word, neutral_tone_with_five=True, style=Style.FINALS_TONE3)\n\n        phones = GenPhones(initials, finals, True)\n\n        temp = \" \".join(phones)\n        f2.write(word + \" \" + temp + \"\\n\")\n"
  },
  {
    "path": "demos/TTSCppFrontend/run_front_demo.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\ncd \"$(dirname \"$(realpath \"$0\")\")\"\n\n./build/tts_front_demo \"$@\"\n"
  },
  {
    "path": "demos/TTSCppFrontend/src/base/type_conv.cpp",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"base/type_conv.h\"\n\nnamespace ppspeech {\n// wstring to string\nstd::string wstring2utf8string(const std::wstring& str) {\n    static std::wstring_convert<std::codecvt_utf8<wchar_t>> strCnv;\n    return strCnv.to_bytes(str);\n}\n\n// string to wstring\nstd::wstring utf8string2wstring(const std::string& str) {\n    static std::wstring_convert<std::codecvt_utf8<wchar_t>> strCnv;\n    return strCnv.from_bytes(str);\n}\n}  // namespace ppspeech\n"
  },
  {
    "path": "demos/TTSCppFrontend/src/base/type_conv.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef BASE_TYPE_CONVC_H\n#define BASE_TYPE_CONVC_H\n\n#include <codecvt>\n#include <locale>\n#include <string>\n\n\nnamespace ppspeech {\n// wstring to string\nstd::string wstring2utf8string(const std::wstring& str);\n\n// string to wstring\nstd::wstring utf8string2wstring(const std::string& str);\n}\n\n#endif  // BASE_TYPE_CONVC_H"
  },
  {
    "path": "demos/TTSCppFrontend/src/front/front_interface.cpp",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"front/front_interface.h\"\n\nnamespace ppspeech {\n\nint FrontEngineInterface::init() {\n    if (_initialed) {\n        return 0;\n    }\n    if (0 != ReadConfFile()) {\n        LOG(ERROR) << \"Read front conf file failed\";\n        return -1;\n    }\n\n    _jieba = new cppjieba::Jieba(_jieba_dict_path,\n                                 _jieba_hmm_path,\n                                 _jieba_user_dict_path,\n                                 _jieba_idf_path,\n                                 _jieba_stop_word_path);\n\n    _punc = {\"，\",\n             \"。\",\n             \"、\",\n             \"？\",\n             \"：\",\n             \"；\",\n             \"~\",\n             \"！\",\n             \",\",\n             \".\",\n             \"?\",\n             \"!\",\n             \":\",\n             \";\",\n             \"/\",\n             \"\\\\\"};\n    _punc_omit = {\"“\", \"”\", \"\\\"\", \"\\\"\"};\n\n    // 需要儿化音处理的词语\n    must_erhua = {\n        \"小院儿\", \"胡同儿\", \"范儿\", \"老汉儿\", \"撒欢儿\", \"寻老礼儿\", \"妥妥儿\"};\n    not_erhua = {\"虐儿\",   \"为儿\",   \"护儿\",   \"瞒儿\",   \"救儿\",   \"替儿\",\n                 \"有儿\",   \"一儿\",   \"我儿\",   \"俺儿\",   \"妻儿\",   \"拐儿\",\n                 \"聋儿\",   \"乞儿\",   \"患儿\",   \"幼儿\",   \"孤儿\",   \"婴儿\",\n                 \"婴幼儿\", \"连体儿\", \"脑瘫儿\", \"流浪儿\", \"体弱儿\", \"混血儿\",\n                 \"蜜雪儿\", \"舫儿\",   \"祖儿\",   \"美儿\",   \"应采儿\", \"可儿\",\n                 \"侄儿\",   \"孙儿\",   \"侄孙儿\", \"女儿\",   \"男儿\",   \"红孩儿\",\n                 \"花儿\",   \"虫儿\",   \"马儿\",   \"鸟儿\",   \"猪儿\",   \"猫儿\",\n                 \"狗儿\"};\n\n    must_not_neural_tone_words = {\n        \"男子\", \"女子\", \"分子\", \"原子\", \"量子\", \"莲子\", \"石子\", \"瓜子\", \"电子\"};\n    // 需要轻声处理的词语\n    must_neural_tone_words = {\n        \"麻烦\", \"麻利\", \"鸳鸯\", \"高粱\", \"骨头\", \"骆驼\", \"马虎\", \"首饰\", \"馒头\",\n        \"馄饨\", \"风筝\", \"难为\", \"队伍\", \"阔气\", \"闺女\", \"门道\", \"锄头\", \"铺盖\",\n        \"铃铛\", \"铁匠\", \"钥匙\", \"里脊\", \"里头\", \"部分\", \"那么\", \"道士\", \"造化\",\n        \"迷糊\", \"连累\", \"这么\", \"这个\", \"运气\", \"过去\", \"软和\", \"转悠\", \"踏实\",\n        \"跳蚤\", \"跟头\", \"趔趄\", \"财主\", \"豆腐\", \"讲究\", \"记性\", \"记号\", \"认识\",\n        \"规矩\", \"见识\", \"裁缝\", \"补丁\", \"衣裳\", \"衣服\", \"衙门\", \"街坊\", \"行李\",\n        \"行当\", \"蛤蟆\", \"蘑菇\", \"薄荷\", \"葫芦\", \"葡萄\", \"萝卜\", \"荸荠\", \"苗条\",\n        \"苗头\", \"苍蝇\", \"芝麻\", \"舒服\", \"舒坦\", \"舌头\", \"自在\", \"膏药\", \"脾气\",\n        \"脑袋\", \"脊梁\", \"能耐\", \"胳膊\", \"胭脂\", \"胡萝\", \"胡琴\", \"胡同\", \"聪明\",\n        \"耽误\", \"耽搁\", \"耷拉\", \"耳朵\", \"老爷\", \"老实\", \"老婆\", \"老头\", \"老太\",\n        \"翻腾\", \"罗嗦\", \"罐头\", \"编辑\", \"结实\", \"红火\", \"累赘\", \"糨糊\", \"糊涂\",\n        \"精神\", \"粮食\", \"簸箕\", \"篱笆\", \"算计\", \"算盘\", \"答应\", \"笤帚\", \"笑语\",\n        \"笑话\", \"窟窿\", \"窝囊\", \"窗户\", \"稳当\", \"稀罕\", \"称呼\", \"秧歌\", \"秀气\",\n        \"秀才\", \"福气\", \"祖宗\", \"砚台\", \"码头\", \"石榴\", \"石头\", \"石匠\", \"知识\",\n        \"眼睛\", \"眯缝\", \"眨巴\", \"眉毛\", \"相声\", \"盘算\", \"白净\", \"痢疾\", \"痛快\",\n        \"疟疾\", \"疙瘩\", \"疏忽\", \"畜生\", \"生意\", \"甘蔗\", \"琵琶\", \"琢磨\", \"琉璃\",\n        \"玻璃\", \"玫瑰\", \"玄乎\", \"狐狸\", \"状元\", \"特务\", \"牲口\", \"牙碜\", \"牌楼\",\n        \"爽快\", \"爱人\", \"热闹\", \"烧饼\", \"烟筒\", \"烂糊\", \"点心\", \"炊帚\", \"灯笼\",\n        \"火候\", \"漂亮\", \"滑溜\", \"溜达\", \"温和\", \"清楚\", \"消息\", \"浪头\", \"活泼\",\n        \"比方\", \"正经\", \"欺负\", \"模糊\", \"槟榔\", \"棺材\", \"棒槌\", \"棉花\", \"核桃\",\n        \"栅栏\", \"柴火\", \"架势\", \"枕头\", \"枇杷\", \"机灵\", \"本事\", \"木头\", \"木匠\",\n        \"朋友\", \"月饼\", \"月亮\", \"暖和\", \"明白\", \"时候\", \"新鲜\", \"故事\", \"收拾\",\n        \"收成\", \"提防\", \"挖苦\", \"挑剔\", \"指甲\", \"指头\", \"拾掇\", \"拳头\", \"拨弄\",\n        \"招牌\", \"招呼\", \"抬举\", \"护士\", \"折腾\", \"扫帚\", \"打量\", \"打算\", \"打点\",\n        \"打扮\", \"打听\", \"打发\", \"扎实\", \"扁担\", \"戒指\", \"懒得\", \"意识\", \"意思\",\n        \"情形\", \"悟性\", \"怪物\", \"思量\", \"怎么\", \"念头\", \"念叨\", \"快活\", \"忙活\",\n        \"志气\", \"心思\", \"得罪\", \"张罗\", \"弟兄\", \"开通\", \"应酬\", \"庄稼\", \"干事\",\n        \"帮手\", \"帐篷\", \"希罕\", \"师父\", \"师傅\", \"巴结\", \"巴掌\", \"差事\", \"工夫\",\n        \"岁数\", \"屁股\", \"尾巴\", \"少爷\", \"小气\", \"小伙\", \"将就\", \"对头\", \"对付\",\n        \"寡妇\", \"家伙\", \"客气\", \"实在\", \"官司\", \"学问\", \"学生\", \"字号\", \"嫁妆\",\n        \"媳妇\", \"媒人\", \"婆家\", \"娘家\", \"委屈\", \"姑娘\", \"姐夫\", \"妯娌\", \"妥当\",\n        \"妖精\", \"奴才\", \"女婿\", \"头发\", \"太阳\", \"大爷\", \"大方\", \"大意\", \"大夫\",\n        \"多少\", \"多么\", \"外甥\", \"壮实\", \"地道\", \"地方\", \"在乎\", \"困难\", \"嘴巴\",\n        \"嘱咐\", \"嘟囔\", \"嘀咕\", \"喜欢\", \"喇嘛\", \"喇叭\", \"商量\", \"唾沫\", \"哑巴\",\n        \"哈欠\", \"哆嗦\", \"咳嗽\", \"和尚\", \"告诉\", \"告示\", \"含糊\", \"吓唬\", \"后头\",\n        \"名字\", \"名堂\", \"合同\", \"吆喝\", \"叫唤\", \"口袋\", \"厚道\", \"厉害\", \"千斤\",\n        \"包袱\", \"包涵\", \"匀称\", \"勤快\", \"动静\", \"动弹\", \"功夫\", \"力气\", \"前头\",\n        \"刺猬\", \"刺激\", \"别扭\", \"利落\", \"利索\", \"利害\", \"分析\", \"出息\", \"凑合\",\n        \"凉快\", \"冷战\", \"冤枉\", \"冒失\", \"养活\", \"关系\", \"先生\", \"兄弟\", \"便宜\",\n        \"使唤\", \"佩服\", \"作坊\", \"体面\", \"位置\", \"似的\", \"伙计\", \"休息\", \"什么\",\n        \"人家\", \"亲戚\", \"亲家\", \"交情\", \"云彩\", \"事情\", \"买卖\", \"主意\", \"丫头\",\n        \"丧气\", \"两口\", \"东西\", \"东家\", \"世故\", \"不由\", \"不在\", \"下水\", \"下巴\",\n        \"上头\", \"上司\", \"丈夫\", \"丈人\", \"一辈\", \"那个\", \"菩萨\", \"父亲\", \"母亲\",\n        \"咕噜\", \"邋遢\", \"费用\", \"冤家\", \"甜头\", \"介绍\", \"荒唐\", \"大人\", \"泥鳅\",\n        \"幸福\", \"熟悉\", \"计划\", \"扑腾\", \"蜡烛\", \"姥爷\", \"照顾\", \"喉咙\", \"吉他\",\n        \"弄堂\", \"蚂蚱\", \"凤凰\", \"拖沓\", \"寒碜\", \"糟蹋\", \"倒腾\", \"报复\", \"逻辑\",\n        \"盘缠\", \"喽啰\", \"牢骚\", \"咖喱\", \"扫把\", \"惦记\"};\n\n\n    // 生成词典（词到音素的映射）\n    if (0 != GenDict(_word2phone_path, &word_phone_map)) {\n        LOG(ERROR) << \"Generate word2phone dict failed\";\n        return -1;\n    }\n\n    // 生成音素字典（音素到音素id的映射）\n    if (0 != GenDict(_phone2id_path, &phone_id_map)) {\n        LOG(ERROR) << \"Generate phone2id dict failed\";\n        return -1;\n    }\n\n    // 生成音调字典（音调到音调id的映射）\n    if (_separate_tone == \"true\") {\n        if (0 != GenDict(_tone2id_path, &tone_id_map)) {\n            LOG(ERROR) << \"Generate tone2id dict failed\";\n            return -1;\n        }\n    }\n\n    // 生成繁简字典（繁体到简体id的映射）\n    if (0 != GenDict(_trand2simp_path, &trand_simp_map)) {\n        LOG(ERROR) << \"Generate trand2simp dict failed\";\n        return -1;\n    }\n\n    _initialed = true;\n    return 0;\n}\n\nint FrontEngineInterface::ReadConfFile() {\n    std::ifstream is(_conf_file.c_str(), std::ifstream::in);\n    if (!is.good()) {\n        LOG(ERROR) << \"Cannot open config file: \" << _conf_file;\n        return -1;\n    }\n    std::string line, key, value;\n    while (std::getline(is, line)) {\n        if (line.substr(0, 2) == \"--\") {\n            size_t pos = line.find_first_of(\"=\", 0);\n            std::string key = line.substr(2, pos - 2);\n            std::string value = line.substr(pos + 1);\n            conf_map[key] = value;\n            LOG(INFO) << \"Key: \" << key << \"; Value: \" << value;\n        }\n    }\n\n    // jieba conf path\n    _jieba_dict_path = conf_map[\"jieba_dict_path\"];\n    _jieba_hmm_path = conf_map[\"jieba_hmm_path\"];\n    _jieba_user_dict_path = conf_map[\"jieba_user_dict_path\"];\n    _jieba_idf_path = conf_map[\"jieba_idf_path\"];\n    _jieba_stop_word_path = conf_map[\"jieba_stop_word_path\"];\n\n    // dict path\n    _separate_tone = conf_map[\"separate_tone\"];\n    _word2phone_path = conf_map[\"word2phone_path\"];\n    _phone2id_path = conf_map[\"phone2id_path\"];\n    _tone2id_path = conf_map[\"tone2id_path\"];\n    _trand2simp_path = conf_map[\"trand2simpd_path\"];\n\n    return 0;\n}\n\nint FrontEngineInterface::Trand2Simp(const std::wstring &sentence,\n                                     std::wstring *sentence_simp) {\n    // sentence_simp = sentence;\n    for (int i = 0; i < sentence.length(); i++) {\n        std::wstring temp(1, sentence[i]);\n        std::string sigle_word = ppspeech::wstring2utf8string(temp);\n        // 单个字是否在繁转简的字典里\n        if (trand_simp_map.find(sigle_word) == trand_simp_map.end()) {\n            sentence_simp->append(temp);\n        } else {\n            sentence_simp->append(\n                (ppspeech::utf8string2wstring(trand_simp_map[sigle_word])));\n        }\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::GenDict(const std::string &dict_file,\n                                  std::map<std::string, std::string> *map) {\n    std::ifstream is(dict_file.c_str(), std::ifstream::in);\n    if (!is.good()) {\n        LOG(ERROR) << \"Cannot open dict file: \" << dict_file;\n        return -1;\n    }\n    std::string line, key, value;\n    while (std::getline(is, line)) {\n        size_t pos = line.find_first_of(\" \", 0);\n        key = line.substr(0, pos);\n        value = line.substr(pos + 1);\n        (*map)[key] = value;\n    }\n    return 0;\n}\n\nint FrontEngineInterface::GetSegResult(\n    std::vector<std::pair<std::string, std::string>> *seg,\n    std::vector<std::string> *seg_words) {\n    std::vector<std::pair<std::string, std::string>>::iterator iter;\n    for (iter = seg->begin(); iter != seg->end(); iter++) {\n        seg_words->push_back((*iter).first);\n    }\n    return 0;\n}\n\nint FrontEngineInterface::GetSentenceIds(const std::string &sentence,\n                                         std::vector<int> *phoneids,\n                                         std::vector<int> *toneids) {\n    std::vector<std::pair<std::string, std::string>>\n        cut_result;  //分词结果包含词和词性\n    if (0 != Cut(sentence, &cut_result)) {\n        LOG(ERROR) << \"Cut sentence: \\\"\" << sentence << \"\\\" failed\";\n        return -1;\n    }\n\n    if (0 != GetWordsIds(cut_result, phoneids, toneids)) {\n        LOG(ERROR) << \"Get words phoneids failed\";\n        return -1;\n    }\n    return 0;\n}\n\nint FrontEngineInterface::GetWordsIds(\n    const std::vector<std::pair<std::string, std::string>> &cut_result,\n    std::vector<int> *phoneids,\n    std::vector<int> *toneids) {\n    std::string word;\n    std::string pos;\n    std::vector<std::string> word_initials;\n    std::vector<std::string> word_finals;\n    std::string phone;\n    for (int i = 0; i < cut_result.size(); i++) {\n        word = cut_result[i].first;\n        pos = cut_result[i].second;\n        if (std::find(_punc_omit.begin(), _punc_omit.end(), word) ==\n            _punc_omit.end()) {  // 非可忽略的标点\n            word_initials = {};\n            word_finals = {};\n            phone = \"\";\n            // 判断是否在标点符号集合中\n            if (std::find(_punc.begin(), _punc.end(), word) ==\n                _punc.end()) {  // 文字\n                // 获取字词的声母韵母列表\n                if (0 !=\n                    GetInitialsFinals(word, &word_initials, &word_finals)) {\n                    LOG(ERROR)\n                        << \"Generate the word_initials and word_finals of \"\n                        << word << \" failed\";\n                    return -1;\n                }\n\n                // 对读音进行修改\n                if (0 != ModifyTone(word, pos, &word_finals)) {\n                    LOG(ERROR) << \"Failed to modify tone.\";\n                }\n\n                // 对儿化音进行修改\n                std::vector<std::vector<std::string>> new_initals_finals =\n                    MergeErhua(word_initials, word_finals, word, pos);\n                word_initials = new_initals_finals[0];\n                word_finals = new_initals_finals[1];\n\n                // 将声母和韵母合并成音素\n                assert(word_initials.size() == word_finals.size());\n                std::string temp_phone;\n                for (int j = 0; j < word_initials.size(); j++) {\n                    if (word_initials[j] != \"\") {\n                        temp_phone = word_initials[j] + \" \" + word_finals[j];\n                    } else {\n                        temp_phone = word_finals[j];\n                    }\n                    if (j == 0) {\n                        phone += temp_phone;\n                    } else {\n                        phone += (\" \" + temp_phone);\n                    }\n                }\n            } else {  // 标点符号\n                if (_separate_tone == \"true\") {\n                    phone = \"sp0\";  // speedyspeech\n                } else {\n                    phone = \"sp\";  // fastspeech2\n                }\n            }\n\n            // 音素到音素id\n            if (0 != Phone2Phoneid(phone, phoneids, toneids)) {\n                LOG(ERROR) << \"Generate the phone id of \" << word << \" failed\";\n                return -1;\n            }\n        }\n    }\n    return 0;\n}\n\nint FrontEngineInterface::Cut(\n    const std::string &sentence,\n    std::vector<std::pair<std::string, std::string>> *cut_result) {\n    std::vector<std::pair<std::string, std::string>> cut_result_jieba;\n\n    // 结巴分词\n    _jieba->Tag(sentence, cut_result_jieba);\n\n    // 对分词后结果进行整合\n    if (0 != MergeforModify(&cut_result_jieba, cut_result)) {\n        LOG(ERROR) << \"Failed to modify  for word segmentation result.\";\n        return -1;\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::GetPhone(const std::string &word,\n                                   std::string *phone) {\n    // 判断 word 在不在 词典里，如果不在，进行CutAll分词\n    if (word_phone_map.find(word) == word_phone_map.end()) {\n        std::vector<std::string> wordcut;\n        _jieba->CutAll(word, wordcut);\n        phone->assign(word_phone_map[wordcut[0]]);\n        for (int i = 1; i < wordcut.size(); i++) {\n            phone->assign((*phone) + (\" \" + word_phone_map[wordcut[i]]));\n        }\n    } else {\n        phone->assign(word_phone_map[word]);\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::Phone2Phoneid(const std::string &phone,\n                                        std::vector<int> *phoneid,\n                                        std::vector<int> *toneid) {\n    std::vector<std::string> phone_vec;\n    phone_vec = absl::StrSplit(phone, \" \");\n    std::string temp_phone;\n    for (int i = 0; i < phone_vec.size(); i++) {\n        temp_phone = phone_vec[i];\n        if (_separate_tone == \"true\") {\n            phoneid->push_back(atoi(\n                (phone_id_map[temp_phone.substr(0, temp_phone.length() - 1)])\n                    .c_str()));\n            toneid->push_back(\n                atoi((tone_id_map[temp_phone.substr(temp_phone.length() - 1,\n                                                    temp_phone.length())])\n                         .c_str()));\n        } else {\n            phoneid->push_back(atoi((phone_id_map[temp_phone]).c_str()));\n        }\n    }\n    return 0;\n}\n\n\n// 根据韵母判断该词中每个字的读音都为第三声。true表示词中每个字都是第三声\nbool FrontEngineInterface::AllToneThree(\n    const std::vector<std::string> &finals) {\n    bool flags = true;\n    for (int i = 0; i < finals.size(); i++) {\n        if (static_cast<int>(finals[i].back()) != 51) {  //如果读音不为第三声\n            flags = false;\n        }\n    }\n    return flags;\n}\n\n// 判断词是否是叠词\nbool FrontEngineInterface::IsReduplication(const std::string &word) {\n    bool flags = false;\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    int len = word_wstr.length();\n    if (len == 2 && word_wstr[0] == word_wstr[1]) {\n        flags = true;\n    }\n    return flags;\n}\n\n// 获取每个字词的声母和韵母列表， word_initials 为声母列表，word_finals\n// 为韵母列表\nint FrontEngineInterface::GetInitialsFinals(\n    const std::string &word,\n    std::vector<std::string> *word_initials,\n    std::vector<std::string> *word_finals) {\n    std::string phone;\n    GetPhone(word, &phone);  //获取字词对应的音素\n    std::vector<std::string> phone_vec = absl::StrSplit(phone, \" \");\n    //获取韵母，每个字的音素有1或者2个，start为单个字音素的起始位置。\n    int start = 0;\n    while (start < phone_vec.size()) {\n        if (phone_vec[start] == \"sp\" || phone_vec[start] == \"sp0\") {\n            start += 1;\n        } else if (isdigit(phone_vec[start].back()) == 0 ||\n                   static_cast<int>(phone_vec[start].back()) == 48) {\n            word_initials->push_back(phone_vec[start]);\n            word_finals->push_back(phone_vec[start + 1]);\n            start += 2;\n        } else {\n            word_initials->push_back(\"\");\n            word_finals->push_back(phone_vec[start]);\n            start += 1;\n        }\n    }\n\n    assert(word_finals->size() == ppspeech::utf8string2wstring(word).length() &&\n           word_finals->size() == word_initials->size());\n\n    return 0;\n}\n\n// 获取每个字词的韵母列表\nint FrontEngineInterface::GetFinals(const std::string &word,\n                                    std::vector<std::string> *word_finals) {\n    std::vector<std::string> word_initials;\n    if (0 != GetInitialsFinals(word, &word_initials, word_finals)) {\n        LOG(ERROR) << \"Failed to get word finals\";\n        return -1;\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::Word2WordVec(const std::string &word,\n                                       std::vector<std::wstring> *wordvec) {\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    for (int i = 0; i < word_wstr.length(); i++) {\n        std::wstring word_sigle(1, word_wstr[i]);\n        wordvec->push_back(word_sigle);\n    }\n    return 0;\n}\n\n// yuantian01解释：把一个词再进行分词找到。例子：小雨伞 --> 小 雨伞 或者 小雨 伞\nint FrontEngineInterface::SplitWord(const std::string &word,\n                                    std::vector<std::string> *new_word_vec) {\n    std::vector<std::string> word_vec;\n    std::string second_subword;\n    _jieba->CutForSearch(word, word_vec);\n    // 升序\n    std::sort(word_vec.begin(),\n              word_vec.end(),\n              [](std::string a, std::string b) { return a.size() > b.size(); });\n    std::string first_subword = word_vec[0];  // 提取长度最短的字符串\n    int first_begin_idx = word.find_first_of(first_subword);\n    if (first_begin_idx == 0) {\n        second_subword = word.substr(first_subword.length());\n        new_word_vec->push_back(first_subword);\n        new_word_vec->push_back(second_subword);\n    } else {\n        second_subword = word.substr(0, word.length() - first_subword.length());\n        new_word_vec->push_back(second_subword);\n        new_word_vec->push_back(first_subword);\n    }\n\n    return 0;\n}\n\n\n// example: 不 一起 --> 不一起\nstd::vector<std::pair<std::string, std::string>> FrontEngineInterface::MergeBu(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> result;\n    std::string word;\n    std::string pos;\n    std::string last_word = \"\";\n\n    for (int i = 0; i < seg_result->size(); i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if (last_word == \"不\") {\n            word = last_word + word;\n        }\n        if (word != \"不\") {\n            result.push_back(make_pair(word, pos));\n        }\n        last_word = word;\n    }\n\n    if (last_word == \"不\") {\n        result.push_back(make_pair(last_word, \"d\"));\n        last_word = \"\";\n    }\n\n    return result;\n}\n\nstd::vector<std::pair<std::string, std::string>> FrontEngineInterface::Mergeyi(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> *result_temp =\n        new std::vector<std::pair<std::string, std::string>>();\n    std::string word;\n    std::string pos;\n    // function 1  example: 听 一 听 --> 听一听\n    for (int i = 0; i < seg_result->size(); i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n\n        if ((i - 1 >= 0) && (word == \"一\") && (i + 1 < seg_result->size()) &&\n            (std::get<0>((*seg_result)[i - 1]) ==\n             std::get<0>((*seg_result)[i + 1])) &&\n            std::get<1>((*seg_result)[i - 1]) == \"v\") {\n            std::get<0>((*result_temp)[i - 1]) =\n                std::get<0>((*result_temp)[i - 1]) + \"一\" +\n                std::get<0>((*result_temp)[i - 1]);\n        } else {\n            if ((i - 2 >= 0) && (std::get<0>((*seg_result)[i - 1]) == \"一\") &&\n                (std::get<0>((*seg_result)[i - 2]) == word) && (pos == \"v\")) {\n                continue;\n            } else {\n                result_temp->push_back(make_pair(word, pos));\n            }\n        }\n    }\n\n    // function 2  example: 一 你 -->  一你\n    std::vector<std::pair<std::string, std::string>> result = {};\n    for (int j = 0; j < result_temp->size(); j++) {\n        word = std::get<0>((*result_temp)[j]);\n        pos = std::get<1>((*result_temp)[j]);\n        if ((result.size() != 0) && (result.back().first == \"一\")) {\n            result.back().first = result.back().first + word;\n        } else {\n            result.push_back(make_pair(word, pos));\n        }\n    }\n\n    return result;\n}\n\n// example: 你 你 --> 你你\nstd::vector<std::pair<std::string, std::string>>\nFrontEngineInterface::MergeReduplication(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> result;\n    std::string word;\n    std::string pos;\n\n    for (int i = 0; i < seg_result->size(); i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if ((result.size() != 0) && (word == result.back().first)) {\n            result.back().first =\n                result.back().first + std::get<0>((*seg_result)[i]);\n        } else {\n            result.push_back(make_pair(word, pos));\n        }\n    }\n\n    return result;\n}\n\n// the first and the second words are all_tone_three\nstd::vector<std::pair<std::string, std::string>>\nFrontEngineInterface::MergeThreeTones(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> result;\n    std::string word;\n    std::string pos;\n    std::vector<std::vector<std::string>> finals;  //韵母数组\n    std::vector<std::string> word_final;\n    std::vector<bool> merge_last(seg_result->size(), false);\n\n    // 判断最后一个分词结果是不是标点，不看标点的声母韵母\n    int word_num = seg_result->size() - 1;\n\n    // seg_result[word_num].first\n    if (std::find(\n            _punc.begin(), _punc.end(), std::get<0>((*seg_result)[word_num])) ==\n        _punc.end()) {  // 最后一个分词结果不是标点\n        word_num += 1;\n    }\n\n    // 获取韵母数组\n    for (int i = 0; i < word_num; i++) {\n        word_final = {};\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if (std::find(_punc_omit.begin(), _punc_omit.end(), word) ==\n            _punc_omit.end()) {  // 非可忽略的标点，即文字\n            if (0 != GetFinals(word, &word_final)) {\n                LOG(ERROR) << \"Failed to get the final of word.\";\n            }\n        }\n\n        finals.push_back(word_final);\n    }\n    assert(word_num == finals.size());\n\n    // 对第三声读音的字词分词结果进行处理\n    for (int i = 0; i < word_num; i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if (i - 1 >= 0 && AllToneThree(finals[i - 1]) &&\n            AllToneThree(finals[i]) && !merge_last[i - 1]) {\n            // if the last word is reduplication, not merge, because\n            // reduplication need to be _neural_sandhi\n            // seg_result[i - 1].first\n            if (!IsReduplication(std::get<0>((*seg_result)[i - 1])) &&\n                (ppspeech::utf8string2wstring(\n                     std::get<0>((*seg_result)[i - 1])))\n                            .length() +\n                        (ppspeech::utf8string2wstring(word)).length() <=\n                    3) {\n                result.back().first =\n                    result.back().first + std::get<0>((*seg_result)[i]);\n                merge_last[i] = true;\n            } else {\n                result.push_back(make_pair(word, pos));\n            }\n        } else {\n            result.push_back(make_pair(word, pos));\n        }\n    }\n\n    //把标点的分词结果补上\n    if (word_num < seg_result->size()) {\n        result.push_back(\n            // seg_result[word_num].first seg_result[word_num].second\n            // std::get<0>((*seg_result)[word_num])\n            make_pair(std::get<0>((*seg_result)[word_num]),\n                      std::get<1>((*seg_result)[word_num])));\n    }\n\n    return result;\n}\n\n// the last char of first word and the first char of second word is tone_three\nstd::vector<std::pair<std::string, std::string>>\nFrontEngineInterface::MergeThreeTones2(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> result;\n    std::string word;\n    std::string pos;\n    std::vector<std::vector<std::string>> finals;  //韵母数组\n    std::vector<std::string> word_final;\n    std::vector<bool> merge_last(seg_result->size(), false);\n\n    // 判断最后一个分词结果是不是标点\n    int word_num = seg_result->size() - 1;\n    if (std::find(\n            _punc.begin(), _punc.end(), std::get<0>((*seg_result)[word_num])) ==\n        _punc.end()) {  // 最后一个分词结果不是标点\n        word_num += 1;\n    }\n\n    // 获取韵母数组\n    for (int i = 0; i < word_num; i++) {\n        word_final = {};\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        // 如果是文字，则获取韵母，如果是可忽略的标点，例如引号，则跳过\n        if (std::find(_punc_omit.begin(), _punc_omit.end(), word) ==\n            _punc_omit.end()) {\n            if (0 != GetFinals(word, &word_final)) {\n                LOG(ERROR) << \"Failed to get the final of word.\";\n            }\n        }\n\n        finals.push_back(word_final);\n    }\n    assert(word_num == finals.size());\n\n    // 对第三声读音的字词分词结果进行处理\n    for (int i = 0; i < word_num; i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if (i - 1 >= 0 && !finals[i - 1].empty() &&\n            absl::EndsWith(finals[i - 1].back(), \"3\") == true &&\n            !finals[i].empty() &&\n            absl::EndsWith(finals[i].front(), \"3\") == true &&\n            !merge_last[i - 1]) {\n            // if the last word is reduplication, not merge, because\n            // reduplication need to be _neural_sandhi\n            // seg_result[i - 1].first\n            if (!IsReduplication(std::get<0>((*seg_result)[i - 1])) &&\n                (ppspeech::utf8string2wstring(\n                     std::get<0>((*seg_result)[i - 1])))\n                            .length() +\n                        ppspeech::utf8string2wstring(word).length() <=\n                    3) {\n                result.back().first =\n                    result.back().first + std::get<0>((*seg_result)[i]);\n                merge_last[i] = true;\n            } else {\n                result.push_back(make_pair(word, pos));\n            }\n        } else {\n            result.push_back(make_pair(word, pos));\n        }\n    }\n\n    //把标点的分词结果补上\n    if (word_num < seg_result->size()) {\n        result.push_back(make_pair(std::get<0>((*seg_result)[word_num]),\n                                   std::get<1>((*seg_result)[word_num])));\n    }\n\n    return result;\n}\n\n// example: 吃饭 儿 --> 吃饭儿\nstd::vector<std::pair<std::string, std::string>> FrontEngineInterface::MergeEr(\n    std::vector<std::pair<std::string, std::string>> *seg_result) {\n    std::vector<std::pair<std::string, std::string>> result;\n    std::string word;\n    std::string pos;\n\n    for (int i = 0; i < seg_result->size(); i++) {\n        word = std::get<0>((*seg_result)[i]);\n        pos = std::get<1>((*seg_result)[i]);\n        if ((i - 1 >= 0) && (word == \"儿\")) {\n            result.back().first =\n                result.back().first + std::get<0>((*seg_result)[i]);\n        } else {\n            result.push_back(make_pair(word, pos));\n        }\n    }\n\n    return result;\n}\n\nint FrontEngineInterface::MergeforModify(\n    std::vector<std::pair<std::string, std::string>> *seg_word_type,\n    std::vector<std::pair<std::string, std::string>> *modify_seg_word_type) {\n    std::vector<std::string> seg_result;\n    GetSegResult(seg_word_type, &seg_result);\n    LOG(INFO) << \"Before merge, seg result is: \"\n              << limonp::Join(seg_result.begin(), seg_result.end(), \"/\");\n    std::vector<std::pair<std::string, std::string>> tmp;\n    tmp = MergeBu(seg_word_type);\n    *modify_seg_word_type = tmp;\n    tmp = Mergeyi(modify_seg_word_type);\n    *modify_seg_word_type = tmp;\n    tmp = MergeReduplication(modify_seg_word_type);\n    *modify_seg_word_type = tmp;\n    tmp = MergeThreeTones(modify_seg_word_type);\n    *modify_seg_word_type = tmp;\n    tmp = MergeThreeTones2(modify_seg_word_type);\n    *modify_seg_word_type = tmp;\n    tmp = MergeEr(modify_seg_word_type);\n    *modify_seg_word_type = tmp;\n    seg_result = {};\n\n    GetSegResult(modify_seg_word_type, &seg_result);\n    LOG(INFO) << \"After merge, seg result is: \"\n              << limonp::Join(seg_result.begin(), seg_result.end(), \"/\");\n\n    return 0;\n}\n\n\nint FrontEngineInterface::BuSandi(const std::string &word,\n                                  std::vector<std::string> *finals) {\n    std::wstring bu = L\"不\";\n    std::vector<std::wstring> wordvec;\n    // 一个词转成向量形式\n    if (0 != Word2WordVec(word, &wordvec)) {\n        LOG(ERROR) << \"Failed to get word vector\";\n        return -1;\n    }\n\n    // e.g. 看不懂   b u4  -->  b u5, 将韵母的最后一位替换成 5\n    if (wordvec.size() == 3 && wordvec[1] == bu) {\n        (*finals)[1] = (*finals)[1].replace((*finals)[1].length() - 1, 1, \"5\");\n    } else {\n        // e.g. 不怕  b u4 --> b u2, 将韵母的最后一位替换成 2\n        for (int i = 0; i < wordvec.size(); i++) {\n            if (wordvec[i] == bu && i + 1 < wordvec.size() &&\n                absl::EndsWith((*finals)[i + 1], \"4\") == true) {\n                (*finals)[i] =\n                    (*finals)[i].replace((*finals)[i].length() - 1, 1, \"2\");\n            }\n        }\n    }\n\n    return 0;\n}\n\n\nint FrontEngineInterface::YiSandhi(const std::string &word,\n                                   std::vector<std::string> *finals) {\n    std::wstring yi = L\"一\";\n    std::vector<std::wstring> wordvec;\n    // 一个词转成向量形式\n    if (0 != Word2WordVec(word, &wordvec)) {\n        LOG(ERROR) << \"Failed to get word vector\";\n        return -1;\n    }\n\n    //情况1：\"一\" in number sequences, e.g. 一零零, 二一零\n    std::wstring num_wstr = L\"零一二三四六七八九\";\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    if (word_wstr.find(yi) != word_wstr.npos && wordvec.back() != yi) {\n        int flags = 0;\n        for (int j = 0; j < wordvec.size(); j++) {\n            if (num_wstr.find(wordvec[j]) == num_wstr.npos) {\n                flags = -1;\n                break;\n            }\n        }\n        if (flags == 0) {\n            return 0;\n        }\n    } else if (wordvec.size() == 3 && wordvec[1] == yi &&\n               wordvec[0] == wordvec[2]) {\n        // \"一\" between reduplication words shold be yi5, e.g. 看一看\n        (*finals)[1] = (*finals)[1].replace((*finals)[1].length() - 1, 1, \"5\");\n    } else if (wordvec[0] == L\"第\" && wordvec[1] == yi) {  //以第一位开始\n        (*finals)[1] = (*finals)[1].replace((*finals)[1].length() - 1, 1, \"1\");\n    } else {\n        for (int i = 0; i < wordvec.size(); i++) {\n            if (wordvec[i] == yi && i + 1 < wordvec.size()) {\n                if (absl::EndsWith((*finals)[i + 1], \"4\") == true) {\n                    // \"一\" before tone4 should be yi2, e.g. 一段\n                    (*finals)[i] =\n                        (*finals)[i].replace((*finals)[i].length() - 1, 1, \"2\");\n                } else {\n                    // \"一\" before non-tone4 should be yi4, e.g. 一天\n                    (*finals)[i] =\n                        (*finals)[i].replace((*finals)[i].length() - 1, 1, \"4\");\n                }\n            }\n        }\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::NeuralSandhi(const std::string &word,\n                                       const std::string &pos,\n                                       std::vector<std::string> *finals) {\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    std::vector<std::wstring> wordvec;\n    // 一个词转成向量形式\n    if (0 != Word2WordVec(word, &wordvec)) {\n        LOG(ERROR) << \"Failed to get word vector\";\n        return -1;\n    }\n    int word_num = wordvec.size();\n    assert(word_num == word_wstr.length());\n\n    // 情况1：reduplication words for n. and v. e.g. 奶奶, 试试, 旺旺\n    for (int j = 0; j < wordvec.size(); j++) {\n        std::string inits = \"nva\";\n        if (j - 1 >= 0 && wordvec[j] == wordvec[j - 1] &&\n            inits.find(pos[0]) != inits.npos) {\n            (*finals)[j] =\n                (*finals)[j].replace((*finals)[j].length() - 1, 1, \"5\");\n        }\n    }\n\n    // 情况2：对下述词的处理\n    std::wstring yuqici = L\"吧呢哈啊呐噻嘛吖嗨呐哦哒额滴哩哟喽啰耶喔诶\";\n    std::wstring de = L\"的地得\";\n    std::wstring le = L\"了着过\";\n    std::vector<std::string> le_pos = {\"ul\", \"uz\", \"ug\"};\n    std::wstring men = L\"们子\";\n    std::vector<std::string> men_pos = {\"r\", \"n\"};\n    std::wstring weizhi = L\"上下里\";\n    std::vector<std::string> weizhi_pos = {\"s\", \"l\", \"f\"};\n    std::wstring dong = L\"来去\";\n    std::wstring fangxiang = L\"上下进出回过起开\";\n    std::wstring ge = L\"个\";\n    std::wstring xiushi = L\"几有两半多各整每做是零一二三四六七八九\";\n    auto ge_idx = word_wstr.find_first_of(ge);  // 出现“个”的第一个位置\n\n    if (word_num >= 1 && yuqici.find(wordvec.back()) != yuqici.npos) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if (word_num >= 1 && de.find(wordvec.back()) != de.npos) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if (word_num == 1 && le.find(wordvec[0]) != le.npos &&\n               find(le_pos.begin(), le_pos.end(), pos) != le_pos.end()) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if (word_num > 1 && men.find(wordvec.back()) != men.npos &&\n               find(men_pos.begin(), men_pos.end(), pos) != men_pos.end() &&\n               find(must_not_neural_tone_words.begin(),\n                    must_not_neural_tone_words.end(),\n                    word) != must_not_neural_tone_words.end()) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if (word_num > 1 && weizhi.find(wordvec.back()) != weizhi.npos &&\n               find(weizhi_pos.begin(), weizhi_pos.end(), pos) !=\n                   weizhi_pos.end()) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if (word_num > 1 && dong.find(wordvec.back()) != dong.npos &&\n               fangxiang.find(wordvec[word_num - 2]) != fangxiang.npos) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else if ((ge_idx != word_wstr.npos && ge_idx >= 1 &&\n                xiushi.find(wordvec[ge_idx - 1]) != xiushi.npos) ||\n               word_wstr == ge) {\n        (*finals).back() =\n            (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n    } else {\n        if (find(must_neural_tone_words.begin(),\n                 must_neural_tone_words.end(),\n                 word) != must_neural_tone_words.end() ||\n            (word_num >= 2 && find(must_neural_tone_words.begin(),\n                                   must_neural_tone_words.end(),\n                                   ppspeech::wstring2utf8string(\n                                       word_wstr.substr(word_num - 2))) !=\n                                  must_neural_tone_words.end())) {\n            (*finals).back() =\n                (*finals).back().replace((*finals).back().length() - 1, 1, \"5\");\n        }\n    }\n\n    // 进行进一步分词，把长词切分更短些\n    std::vector<std::string> word_list;\n    if (0 != SplitWord(word, &word_list)) {\n        LOG(ERROR) << \"Failed to split word.\";\n        return -1;\n    }\n    // 创建对应的 韵母列表\n    std::vector<std::vector<std::string>> finals_list;\n    std::vector<std::string> finals_temp;\n    finals_temp.assign((*finals).begin(),\n                       (*finals).begin() +\n                           ppspeech::utf8string2wstring(word_list[0]).length());\n    finals_list.push_back(finals_temp);\n    finals_temp.assign(\n        (*finals).begin() + ppspeech::utf8string2wstring(word_list[0]).length(),\n        (*finals).end());\n    finals_list.push_back(finals_temp);\n\n    finals = new std::vector<std::string>();\n    for (int i = 0; i < word_list.size(); i++) {\n        std::wstring temp_wstr = ppspeech::utf8string2wstring(word_list[i]);\n        if ((find(must_neural_tone_words.begin(),\n                  must_neural_tone_words.end(),\n                  word_list[i]) != must_neural_tone_words.end()) ||\n            (temp_wstr.length() >= 2 &&\n             find(must_neural_tone_words.begin(),\n                  must_neural_tone_words.end(),\n                  ppspeech::wstring2utf8string(\n                      temp_wstr.substr(temp_wstr.length() - 2))) !=\n                 must_neural_tone_words.end())) {\n            finals_list[i].back() = finals_list[i].back().replace(\n                finals_list[i].back().length() - 1, 1, \"5\");\n        }\n        (*finals).insert(\n            (*finals).end(), finals_list[i].begin(), finals_list[i].end());\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::ThreeSandhi(const std::string &word,\n                                      std::vector<std::string> *finals) {\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    std::vector<std::vector<std::string>> finals_list;\n    std::vector<std::string> finals_temp;\n    std::vector<std::wstring> wordvec;\n    // 一个词转成向量形式\n    if (0 != Word2WordVec(word, &wordvec)) {\n        LOG(ERROR) << \"Failed to get word vector\";\n        return -1;\n    }\n    int word_num = wordvec.size();\n    assert(word_num == word_wstr.length());\n\n    if (word_num == 2 && AllToneThree((*finals))) {\n        (*finals)[0] = (*finals)[0].replace((*finals)[0].length() - 1, 1, \"2\");\n    } else if (word_num == 3) {\n        // 进行进一步分词，把长词切分更短些\n        std::vector<std::string> word_list;\n        if (0 != SplitWord(word, &word_list)) {\n            LOG(ERROR) << \"Failed to split word.\";\n            return -1;\n        }\n        if (AllToneThree((*finals))) {\n            std::wstring temp_wstr = ppspeech::utf8string2wstring(word_list[0]);\n            // disyllabic + monosyllabic, e.g. 蒙古/包\n            if (temp_wstr.length() == 2) {\n                (*finals)[0] =\n                    (*finals)[0].replace((*finals)[0].length() - 1, 1, \"2\");\n                (*finals)[1] =\n                    (*finals)[1].replace((*finals)[1].length() - 1, 1, \"2\");\n            } else if (temp_wstr.length() ==\n                       1) {  // monosyllabic + disyllabic, e.g. 纸/老虎\n                (*finals)[1] =\n                    (*finals)[1].replace((*finals)[1].length() - 1, 1, \"2\");\n            }\n        } else {\n            // 创建对应的 韵母列表\n            finals_temp = {};\n            finals_list = {};\n            finals_temp.assign(\n                (*finals).begin(),\n                (*finals).begin() +\n                    ppspeech::utf8string2wstring(word_list[0]).length());\n            finals_list.push_back(finals_temp);\n            finals_temp.assign(\n                (*finals).begin() +\n                    ppspeech::utf8string2wstring(word_list[0]).length(),\n                (*finals).end());\n            finals_list.push_back(finals_temp);\n\n            finals = new std::vector<std::string>();\n            for (int i = 0; i < finals_list.size(); i++) {\n                // e.g. 所有/人\n                if (AllToneThree(finals_list[i]) &&\n                    finals_list[i].size() == 2) {\n                    finals_list[i][0] = finals_list[i][0].replace(\n                        finals_list[i][0].length() - 1, 1, \"2\");\n                } else if (i == 1 && !(AllToneThree(finals_list[i])) &&\n                           absl::EndsWith(finals_list[i][0], \"3\") == true &&\n                           absl::EndsWith(finals_list[0].back(), \"3\") == true) {\n                    finals_list[0].back() = finals_list[0].back().replace(\n                        finals_list[0].back().length() - 1, 1, \"2\");\n                }\n            }\n            (*finals).insert(\n                (*finals).end(), finals_list[0].begin(), finals_list[0].end());\n            (*finals).insert(\n                (*finals).end(), finals_list[1].begin(), finals_list[1].end());\n        }\n\n    } else if (word_num == 4) {  //将成语拆分为两个长度为 2 的单词\n        // 创建对应的 韵母列表\n        finals_temp = {};\n        finals_list = {};\n        finals_temp.assign((*finals).begin(), (*finals).begin() + 2);\n        finals_list.push_back(finals_temp);\n        finals_temp.assign((*finals).begin() + 2, (*finals).end());\n        finals_list.push_back(finals_temp);\n\n        finals = new std::vector<std::string>();\n        for (int j = 0; j < finals_list.size(); j++) {\n            if (AllToneThree(finals_list[j])) {\n                finals_list[j][0] = finals_list[j][0].replace(\n                    finals_list[j][0].length() - 1, 1, \"2\");\n            }\n            (*finals).insert(\n                (*finals).end(), finals_list[j].begin(), finals_list[j].end());\n        }\n    }\n\n    return 0;\n}\n\nint FrontEngineInterface::ModifyTone(const std::string &word,\n                                     const std::string &pos,\n                                     std::vector<std::string> *finals) {\n    if ((0 != BuSandi(word, finals)) || (0 != YiSandhi(word, finals)) ||\n        (0 != NeuralSandhi(word, pos, finals)) ||\n        (0 != ThreeSandhi(word, finals))) {\n        LOG(ERROR) << \"Failed to modify tone of the word: \" << word;\n        return -1;\n    }\n\n    return 0;\n}\n\nstd::vector<std::vector<std::string>> FrontEngineInterface::MergeErhua(\n    const std::vector<std::string> &initials,\n    const std::vector<std::string> &finals,\n    const std::string &word,\n    const std::string &pos) {\n    std::vector<std::string> new_initials = {};\n    std::vector<std::string> new_finals = {};\n    std::vector<std::vector<std::string>> new_initials_finals;\n    std::vector<std::string> specified_pos = {\"a\", \"j\", \"nr\"};\n    std::wstring word_wstr = ppspeech::utf8string2wstring(word);\n    std::vector<std::wstring> wordvec;\n    // 一个词转成向量形式\n    if (0 != Word2WordVec(word, &wordvec)) {\n        LOG(ERROR) << \"Failed to get word vector\";\n    }\n    int word_num = wordvec.size();\n\n    if ((find(must_erhua.begin(), must_erhua.end(), word) ==\n         must_erhua.end()) &&\n        ((find(not_erhua.begin(), not_erhua.end(), word) != not_erhua.end()) ||\n         (find(specified_pos.begin(), specified_pos.end(), pos) !=\n          specified_pos.end()))) {\n        new_initials_finals.push_back(initials);\n        new_initials_finals.push_back(finals);\n        return new_initials_finals;\n    }\n    if (finals.size() != word_num) {\n        new_initials_finals.push_back(initials);\n        new_initials_finals.push_back(finals);\n        return new_initials_finals;\n    }\n\n    assert(finals.size() == word_num);\n    for (int i = 0; i < finals.size(); i++) {\n        if (i == finals.size() - 1 && wordvec[i] == L\"儿\" &&\n            (finals[i] == \"er2\" || finals[i] == \"er5\") && word_num >= 2 &&\n            find(not_erhua.begin(),\n                 not_erhua.end(),\n                 ppspeech::wstring2utf8string(word_wstr.substr(\n                     word_wstr.length() - 2))) == not_erhua.end() &&\n            !new_finals.empty()) {\n            new_finals.back() =\n                new_finals.back().substr(0, new_finals.back().length() - 1) +\n                \"r\" + new_finals.back().substr(new_finals.back().length() - 1);\n        } else {\n            new_initials.push_back(initials[i]);\n            new_finals.push_back(finals[i]);\n        }\n    }\n    new_initials_finals.push_back(new_initials);\n    new_initials_finals.push_back(new_finals);\n\n    return new_initials_finals;\n}\n}  // namespace ppspeech\n"
  },
  {
    "path": "demos/TTSCppFrontend/src/front/front_interface.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef PADDLE_TTS_SERVING_FRONT_FRONT_INTERFACE_H\n#define PADDLE_TTS_SERVING_FRONT_FRONT_INTERFACE_H\n\n#include <glog/logging.h>\n#include <fstream>\n#include <map>\n#include <memory>\n#include <string>\n//#include \"utils/dir_utils.h\"\n#include <cppjieba/Jieba.hpp>\n#include \"absl/strings/str_split.h\"\n#include \"front/text_normalize.h\"\n\n\nnamespace ppspeech {\n\nclass FrontEngineInterface : public TextNormalizer {\n  public:\n    explicit FrontEngineInterface(std::string conf) : _conf_file(conf) {\n        TextNormalizer();\n        _jieba = nullptr;\n        _initialed = false;\n        init();\n    }\n\n    int init();\n    ~FrontEngineInterface() {}\n\n    // 读取配置文件\n    int ReadConfFile();\n\n    // 简体转繁体\n    int Trand2Simp(const std::wstring &sentence, std::wstring *sentence_simp);\n\n    // 生成字典\n    int GenDict(const std::string &file,\n                std::map<std::string, std::string> *map);\n\n    // 由 词+词性的分词结果转为仅包含词的结果\n    int GetSegResult(std::vector<std::pair<std::string, std::string>> *seg,\n                     std::vector<std::string> *seg_words);\n\n    // 生成句子的音素，音调id。如果音素和音调未分开，则 toneids\n    // 为空（fastspeech2），反之则不为空(speedyspeech)\n    int GetSentenceIds(const std::string &sentence,\n                       std::vector<int> *phoneids,\n                       std::vector<int> *toneids);\n\n    // 根据分词结果获取词的音素，音调id，并对读音进行适当修改\n    // (ModifyTone)。如果音素和音调未分开，则 toneids\n    // 为空（fastspeech2），反之则不为空(speedyspeech)\n    int GetWordsIds(\n        const std::vector<std::pair<std::string, std::string>> &cut_result,\n        std::vector<int> *phoneids,\n        std::vector<int> *toneids);\n\n    // 结巴分词生成包含词和词性的分词结果，再对分词结果进行适当修改\n    // (MergeforModify)\n    int Cut(const std::string &sentence,\n            std::vector<std::pair<std::string, std::string>> *cut_result);\n\n    // 字词到音素的映射，查找字典\n    int GetPhone(const std::string &word, std::string *phone);\n\n    // 音素到音素id\n    int Phone2Phoneid(const std::string &phone,\n                      std::vector<int> *phoneid,\n                      std::vector<int> *toneids);\n\n\n    // 根据韵母判断该词中每个字的读音都为第三声。true表示词中每个字都是第三声\n    bool AllToneThree(const std::vector<std::string> &finals);\n\n    // 判断词是否是叠词\n    bool IsReduplication(const std::string &word);\n\n    // 获取每个字词的声母韵母列表\n    int GetInitialsFinals(const std::string &word,\n                          std::vector<std::string> *word_initials,\n                          std::vector<std::string> *word_finals);\n\n    // 获取每个字词的韵母列表\n    int GetFinals(const std::string &word,\n                  std::vector<std::string> *word_finals);\n\n    // 整个词转成向量形式，向量的每个元素对应词的一个字\n    int Word2WordVec(const std::string &word,\n                     std::vector<std::wstring> *wordvec);\n\n    // 将整个词重新进行 full cut，分词后，各个词会在词典中\n    int SplitWord(const std::string &word,\n                  std::vector<std::string> *fullcut_word);\n\n    // 对分词结果进行处理：对包含“不”字的分词结果进行整理\n    std::vector<std::pair<std::string, std::string>> MergeBu(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对分词结果进行处理：对包含“一”字的分词结果进行整理\n    std::vector<std::pair<std::string, std::string>> Mergeyi(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对分词结果进行处理：对前后相同的两个字进行合并\n    std::vector<std::pair<std::string, std::string>> MergeReduplication(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对一个词和后一个词他们的读音均为第三声的两个词进行合并\n    std::vector<std::pair<std::string, std::string>> MergeThreeTones(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对一个词的最后一个读音和后一个词的第一个读音为第三声的两个词进行合并\n    std::vector<std::pair<std::string, std::string>> MergeThreeTones2(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对分词结果进行处理：对包含“儿”字的分词结果进行整理\n    std::vector<std::pair<std::string, std::string>> MergeEr(\n        std::vector<std::pair<std::string, std::string>> *seg_result);\n\n    // 对分词结果进行处理、修改\n    int MergeforModify(\n        std::vector<std::pair<std::string, std::string>> *seg_result,\n        std::vector<std::pair<std::string, std::string>> *merge_seg_result);\n\n\n    // 对包含“不”字的相关词音调进行修改\n    int BuSandi(const std::string &word, std::vector<std::string> *finals);\n\n    // 对包含“一”字的相关词音调进行修改\n    int YiSandhi(const std::string &word, std::vector<std::string> *finals);\n\n    // 对一些特殊词（包括量词，语助词等）的相关词音调进行修改\n    int NeuralSandhi(const std::string &word,\n                     const std::string &pos,\n                     std::vector<std::string> *finals);\n\n    // 对包含第三声的相关词音调进行修改\n    int ThreeSandhi(const std::string &word, std::vector<std::string> *finals);\n\n    // 对字词音调进行处理、修改\n    int ModifyTone(const std::string &word,\n                   const std::string &pos,\n                   std::vector<std::string> *finals);\n\n\n    // 对儿化音进行处理\n    std::vector<std::vector<std::string>> MergeErhua(\n        const std::vector<std::string> &initials,\n        const std::vector<std::string> &finals,\n        const std::string &word,\n        const std::string &pos);\n\n\n  private:\n    bool _initialed;\n    cppjieba::Jieba *_jieba;\n    std::vector<std::string> _punc;\n    std::vector<std::string> _punc_omit;\n\n    std::string _conf_file;\n    std::map<std::string, std::string> conf_map;\n    std::map<std::string, std::string> word_phone_map;\n    std::map<std::string, std::string> phone_id_map;\n    std::map<std::string, std::string> tone_id_map;\n    std::map<std::string, std::string> trand_simp_map;\n\n\n    std::string _jieba_dict_path;\n    std::string _jieba_hmm_path;\n    std::string _jieba_user_dict_path;\n    std::string _jieba_idf_path;\n    std::string _jieba_stop_word_path;\n\n    std::string _separate_tone;\n    std::string _word2phone_path;\n    std::string _phone2id_path;\n    std::string _tone2id_path;\n    std::string _trand2simp_path;\n\n    std::vector<std::string> must_erhua;\n    std::vector<std::string> not_erhua;\n\n    std::vector<std::string> must_not_neural_tone_words;\n    std::vector<std::string> must_neural_tone_words;\n};\n}  // namespace ppspeech\n#endif"
  },
  {
    "path": "demos/TTSCppFrontend/src/front/text_normalize.cpp",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"front/text_normalize.h\"\n\nnamespace ppspeech {\n\n// 初始化 digits_map and unit_map\nint TextNormalizer::InitMap() {\n    digits_map[\"0\"] = \"零\";\n    digits_map[\"1\"] = \"一\";\n    digits_map[\"2\"] = \"二\";\n    digits_map[\"3\"] = \"三\";\n    digits_map[\"4\"] = \"四\";\n    digits_map[\"5\"] = \"五\";\n    digits_map[\"6\"] = \"六\";\n    digits_map[\"7\"] = \"七\";\n    digits_map[\"8\"] = \"八\";\n    digits_map[\"9\"] = \"九\";\n\n    units_map[1] = \"十\";\n    units_map[2] = \"百\";\n    units_map[3] = \"千\";\n    units_map[4] = \"万\";\n    units_map[8] = \"亿\";\n\n    return 0;\n}\n\n// 替换\nint TextNormalizer::Replace(std::wstring *sentence,\n                            const int &pos,\n                            const int &len,\n                            const std::wstring &repstr) {\n    // 删除原来的\n    sentence->erase(pos, len);\n    // 插入新的\n    sentence->insert(pos, repstr);\n    return 0;\n}\n\n// 根据标点符号切分句子\nint TextNormalizer::SplitByPunc(const std::wstring &sentence,\n                                std::vector<std::wstring> *sentence_part) {\n    std::wstring temp = sentence;\n    std::wregex reg(L\"[：，；。？！,;?!]\");\n    std::wsmatch match;\n\n    while (std::regex_search(temp, match, reg)) {\n        sentence_part->push_back(\n            temp.substr(0, match.position(0) + match.length(0)));\n        Replace(&temp, 0, match.position(0) + match.length(0), L\"\");\n    }\n    // 如果最后没有标点符号\n    if (temp != L\"\") {\n        sentence_part->push_back(temp);\n    }\n    return 0;\n}\n\n// 数字转文本，10200 - > 一万零二百\nstd::string TextNormalizer::CreateTextValue(const std::string &num_str,\n                                            bool use_zero) {\n    std::string num_lstrip =\n        std::string(absl::StripPrefix(num_str, \"0\")).data();\n    int len = num_lstrip.length();\n\n    if (len == 0) {\n        return \"\";\n    } else if (len == 1) {\n        if (use_zero && (len < num_str.length())) {\n            return digits_map[\"0\"] + digits_map[num_lstrip];\n        } else {\n            return digits_map[num_lstrip];\n        }\n    } else {\n        int largest_unit = 0;  // 最大单位\n        std::string first_part;\n        std::string second_part;\n\n        if (len > 1 && len <= 2) {\n            largest_unit = 1;\n        } else if (len > 2 && len <= 3) {\n            largest_unit = 2;\n        } else if (len > 3 && len <= 4) {\n            largest_unit = 3;\n        } else if (len > 4 && len <= 8) {\n            largest_unit = 4;\n        } else if (len > 8) {\n            largest_unit = 8;\n        }\n\n        first_part = num_str.substr(0, num_str.length() - largest_unit);\n        second_part = num_str.substr(num_str.length() - largest_unit);\n\n        return CreateTextValue(first_part, use_zero) + units_map[largest_unit] +\n               CreateTextValue(second_part, use_zero);\n    }\n}\n\n// 数字一个一个对应，可直接用于年份，电话，手机，\nstd::string TextNormalizer::SingleDigit2Text(const std::string &num_str,\n                                             bool alt_one) {\n    std::string text = \"\";\n    if (alt_one) {\n        digits_map[\"1\"] = \"幺\";\n    } else {\n        digits_map[\"1\"] = \"一\";\n    }\n\n    for (size_t i = 0; i < num_str.size(); i++) {\n        std::string num_int(1, num_str[i]);\n        if (digits_map.find(num_int) == digits_map.end()) {\n            LOG(ERROR) << \"digits_map doesn't have key: \" << num_int;\n        }\n        text += digits_map[num_int];\n    }\n\n    return text;\n}\n\nstd::string TextNormalizer::SingleDigit2Text(const std::wstring &num,\n                                             bool alt_one) {\n    std::string num_str = wstring2utf8string(num);\n    return SingleDigit2Text(num_str, alt_one);\n}\n\n//  数字整体对应，可直接用于月份，日期，数值整数部分\nstd::string TextNormalizer::MultiDigit2Text(const std::string &num_str,\n                                            bool alt_one,\n                                            bool use_zero) {\n    LOG(INFO) << \"aaaaaaaaaaaaaaaa: \" << alt_one << use_zero;\n    if (alt_one) {\n        digits_map[\"1\"] = \"幺\";\n    } else {\n        digits_map[\"1\"] = \"一\";\n    }\n\n    std::wstring result =\n        utf8string2wstring(CreateTextValue(num_str, use_zero));\n    std::wstring result_0(1, result[0]);\n    std::wstring result_1(1, result[1]);\n    // 一十八 --> 十八\n    if ((result_0 == utf8string2wstring(digits_map[\"1\"])) &&\n        (result_1 == utf8string2wstring(units_map[1]))) {\n        return wstring2utf8string(result.substr(1, result.length()));\n    } else {\n        return wstring2utf8string(result);\n    }\n}\n\nstd::string TextNormalizer::MultiDigit2Text(const std::wstring &num,\n                                            bool alt_one,\n                                            bool use_zero) {\n    std::string num_str = wstring2utf8string(num);\n    return MultiDigit2Text(num_str, alt_one, use_zero);\n}\n\n// 数字转文本，包括整数和小数\nstd::string TextNormalizer::Digits2Text(const std::string &num_str) {\n    std::string text;\n    std::vector<std::string> integer_decimal;\n    integer_decimal = absl::StrSplit(num_str, \".\");\n\n    if (integer_decimal.size() == 1) {  // 整数\n        text = MultiDigit2Text(integer_decimal[0]);\n    } else if (integer_decimal.size() == 2) {  // 小数\n        if (integer_decimal[0] == \"\") {  // 无整数的小数类型，例如：.22\n            text = \"点\" +\n                   SingleDigit2Text(\n                       std::string(absl::StripSuffix(integer_decimal[1], \"0\"))\n                           .data());\n        } else {  // 常规小数类型，例如：12.34\n            text = MultiDigit2Text(integer_decimal[0]) + \"点\" +\n                   SingleDigit2Text(\n                       std::string(absl::StripSuffix(integer_decimal[1], \"0\"))\n                           .data());\n        }\n    } else {\n        return \"The value does not conform to the numeric format\";\n    }\n\n    return text;\n}\n\nstd::string TextNormalizer::Digits2Text(const std::wstring &num) {\n    std::string num_str = wstring2utf8string(num);\n    return Digits2Text(num_str);\n}\n\n// 日期，2021年8月18日 --> 二零二一年八月十八日\nint TextNormalizer::ReData(std::wstring *sentence) {\n    std::wregex reg(\n        L\"(\\\\d{4}|\\\\d{2})年((0?[1-9]|1[0-2])月)?(((0?[1-9])|((1|2)[0-9])|30|31)\"\n        L\"([日号]))?\");\n    std::wsmatch match;\n    std::string rep;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"\";\n        rep += SingleDigit2Text(match[1]) + \"年\";\n        if (match[3] != L\"\") {\n            rep += MultiDigit2Text(match[3], false, false) + \"月\";\n        }\n        if (match[5] != L\"\") {\n            rep += MultiDigit2Text(match[5], false, false) +\n                   wstring2utf8string(match[9]);\n        }\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n\n// XX-XX-XX or XX/XX/XX 例如：2021/08/18 --> 二零二一年八月十八日\nint TextNormalizer::ReData2(std::wstring *sentence) {\n    std::wregex reg(\n        L\"(\\\\d{4})([- /.])(0[1-9]|1[012])\\\\2(0[1-9]|[12][0-9]|3[01])\");\n    std::wsmatch match;\n    std::string rep;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"\";\n        rep += (SingleDigit2Text(match[1]) + \"年\");\n        rep += (MultiDigit2Text(match[3], false, false) + \"月\");\n        rep += (MultiDigit2Text(match[4], false, false) + \"日\");\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// XX:XX:XX   09:09:02 --> 九点零九分零二秒\nint TextNormalizer::ReTime(std::wstring *sentence) {\n    std::wregex reg(L\"([0-1]?[0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9]))?\");\n    std::wsmatch match;\n    std::string rep;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"\";\n        rep += (MultiDigit2Text(match[1], false, false) + \"点\");\n        if (absl::StartsWith(wstring2utf8string(match[2]), \"0\")) {\n            rep += \"零\";\n        }\n        rep += (MultiDigit2Text(match[2]) + \"分\");\n        if (absl::StartsWith(wstring2utf8string(match[4]), \"0\")) {\n            rep += \"零\";\n        }\n        rep += (MultiDigit2Text(match[4]) + \"秒\");\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 温度，例如：-24.3℃ --> 零下二十四点三度\nint TextNormalizer::ReTemperature(std::wstring *sentence) {\n    std::wregex reg(L\"(-?)(\\\\d+(\\\\.\\\\d+)?)(°C|℃|度|摄氏度)\");\n    std::wsmatch match;\n    std::string rep;\n    std::string sign;\n    std::vector<std::string> integer_decimal;\n    std::string unit;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        match[1] == L\"-\" ? sign = \"负\" : sign = \"\";\n        match[4] == L\"摄氏度\" ? unit = \"摄氏度\" : unit = \"度\";\n        rep = sign + Digits2Text(match[2]) + unit;\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 分数，例如： 1/3 --> 三分之一\nint TextNormalizer::ReFrac(std::wstring *sentence) {\n    std::wregex reg(L\"(-?)(\\\\d+)/(\\\\d+)\");\n    std::wsmatch match;\n    std::string sign;\n    std::string rep;\n    while (std::regex_search(*sentence, match, reg)) {\n        match[1] == L\"-\" ? sign = \"负\" : sign = \"\";\n        rep = sign + MultiDigit2Text(match[3]) + \"分之\" +\n              MultiDigit2Text(match[2]);\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 百分数，例如：45.5% --> 百分之四十五点五\nint TextNormalizer::RePercentage(std::wstring *sentence) {\n    std::wregex reg(L\"(-?)(\\\\d+(\\\\.\\\\d+)?)%\");\n    std::wsmatch match;\n    std::string sign;\n    std::string rep;\n    std::vector<std::string> integer_decimal;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        match[1] == L\"-\" ? sign = \"负\" : sign = \"\";\n        rep = sign + \"百分之\" + Digits2Text(match[2]);\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 手机号码，例如：+86 18883862235 --> 八六幺八八八三八六二二三五\nint TextNormalizer::ReMobilePhone(std::wstring *sentence) {\n    std::wregex reg(\n        L\"(\\\\d)?((\\\\+?86 ?)?1([38]\\\\d|5[0-35-9]|7[678]|9[89])\\\\d{8})(\\\\d)?\");\n    std::wsmatch match;\n    std::string rep;\n    std::vector<std::string> country_phonenum;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        country_phonenum = absl::StrSplit(wstring2utf8string(match[0]), \"+\");\n        rep = \"\";\n        for (int i = 0; i < country_phonenum.size(); i++) {\n            LOG(INFO) << country_phonenum[i];\n            rep += SingleDigit2Text(country_phonenum[i], true);\n        }\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 座机号码，例如：010-51093154 --> 零幺零五幺零九三幺五四\nint TextNormalizer::RePhone(std::wstring *sentence) {\n    std::wregex reg(\n        L\"(\\\\d)?((0(10|2[1-3]|[3-9]\\\\d{2})-?)?[1-9]\\\\d{6,7})(\\\\d)?\");\n    std::wsmatch match;\n    std::vector<std::string> zone_phonenum;\n    std::string rep;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"\";\n        zone_phonenum = absl::StrSplit(wstring2utf8string(match[0]), \"-\");\n        for (int i = 0; i < zone_phonenum.size(); i++) {\n            rep += SingleDigit2Text(zone_phonenum[i], true);\n        }\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 范围，例如：60~90 --> 六十到九十\nint TextNormalizer::ReRange(std::wstring *sentence) {\n    std::wregex reg(\n        L\"((-?)((\\\\d+)(\\\\.\\\\d+)?)|(\\\\.(\\\\d+)))[-~]((-?)((\\\\d+)(\\\\.\\\\d+)?)|(\\\\.(\"\n        L\"\\\\d+)))\");\n    std::wsmatch match;\n    std::string rep;\n    std::string sign1;\n    std::string sign2;\n\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"\";\n        match[2] == L\"-\" ? sign1 = \"负\" : sign1 = \"\";\n        if (match[6] != L\"\") {\n            rep += sign1 + Digits2Text(match[6]) + \"到\";\n        } else {\n            rep += sign1 + Digits2Text(match[3]) + \"到\";\n        }\n        match[9] == L\"-\" ? sign2 = \"负\" : sign2 = \"\";\n        if (match[13] != L\"\") {\n            rep += sign2 + Digits2Text(match[13]);\n        } else {\n            rep += sign2 + Digits2Text(match[10]);\n        }\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 带负号的整数，例如：-10 --> 负十\nint TextNormalizer::ReInterger(std::wstring *sentence) {\n    std::wregex reg(L\"(-)(\\\\d+)\");\n    std::wsmatch match;\n    std::string rep;\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = \"负\" + MultiDigit2Text(match[2]);\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 纯小数\nint TextNormalizer::ReDecimalNum(std::wstring *sentence) {\n    std::wregex reg(L\"(-?)((\\\\d+)(\\\\.\\\\d+))|(\\\\.(\\\\d+))\");\n    std::wsmatch match;\n    std::string sign;\n    std::string rep;\n    // std::vector<std::string> integer_decimal;\n    while (std::regex_search(*sentence, match, reg)) {\n        match[1] == L\"-\" ? sign = \"负\" : sign = \"\";\n        if (match[5] != L\"\") {\n            rep = sign + Digits2Text(match[5]);\n        } else {\n            rep = sign + Digits2Text(match[2]);\n        }\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 正整数 + 量词\nint TextNormalizer::RePositiveQuantifiers(std::wstring *sentence) {\n    std::wstring common_quantifiers =\n        L\"(朵|匹|张|座|回|场|尾|条|个|首|阙|阵|网|炮|顶|丘|棵|只|支|袭|辆|挑|\"\n        L\"担|颗|壳|窠|曲|墙|群|腔|砣|座|客|贯|扎|捆|刀|令|打|手|罗|坡|山|岭|江|\"\n        L\"溪|钟|队|单|双|对|出|口|头|脚|板|跳|枝|件|贴|针|线|管|名|位|身|堂|课|\"\n        L\"本|页|家|户|层|丝|毫|厘|分|钱|两|斤|担|铢|石|钧|锱|忽|(千|毫|微)克|\"\n        L\"毫|厘|(公)分|分|寸|尺|丈|里|寻|常|铺|程|(千|分|厘|毫|微)米|米|撮|勺|\"\n        L\"合|升|斗|石|盘|碗|碟|叠|桶|笼|盆|盒|杯|钟|斛|锅|簋|篮|盘|桶|罐|瓶|壶|\"\n        L\"卮|盏|箩|箱|煲|啖|袋|钵|年|月|日|季|刻|时|周|天|秒|分|旬|纪|岁|世|更|\"\n        L\"夜|春|夏|秋|冬|代|伏|辈|丸|泡|粒|颗|幢|堆|条|根|支|道|面|片|张|颗|块|\"\n        L\"元|(亿|千万|百万|万|千|百)|(亿|千万|百万|万|千|百|美|)元|(亿|千万|\"\n        L\"百万|万|千|百|)块|角|毛|分)\";\n    std::wregex reg(L\"(\\\\d+)([多余几])?\" + common_quantifiers);\n    std::wsmatch match;\n    std::string rep;\n    while (std::regex_search(*sentence, match, reg)) {\n        rep = MultiDigit2Text(match[1]);\n        Replace(sentence,\n                match.position(1),\n                match.length(1),\n                utf8string2wstring(rep));\n    }\n\n    return 0;\n}\n\n// 编号类数字，例如： 89757 --> 八九七五七\nint TextNormalizer::ReDefalutNum(std::wstring *sentence) {\n    std::wregex reg(L\"\\\\d{3}\\\\d*\");\n    std::wsmatch match;\n    while (std::regex_search(*sentence, match, reg)) {\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(SingleDigit2Text(match[0])));\n    }\n\n    return 0;\n}\n\nint TextNormalizer::ReNumber(std::wstring *sentence) {\n    std::wregex reg(L\"(-?)((\\\\d+)(\\\\.\\\\d+)?)|(\\\\.(\\\\d+))\");\n    std::wsmatch match;\n    std::string sign;\n    std::string rep;\n    while (std::regex_search(*sentence, match, reg)) {\n        match[1] == L\"-\" ? sign = \"负\" : sign = \"\";\n        if (match[5] != L\"\") {\n            rep = sign + Digits2Text(match[5]);\n        } else {\n            rep = sign + Digits2Text(match[2]);\n        }\n\n        Replace(sentence,\n                match.position(0),\n                match.length(0),\n                utf8string2wstring(rep));\n    }\n    return 0;\n}\n\n// 整体正则，按顺序\nint TextNormalizer::SentenceNormalize(std::wstring *sentence) {\n    ReData(sentence);\n    ReData2(sentence);\n    ReTime(sentence);\n    ReTemperature(sentence);\n    ReFrac(sentence);\n    RePercentage(sentence);\n    ReMobilePhone(sentence);\n    RePhone(sentence);\n    ReRange(sentence);\n    ReInterger(sentence);\n    ReDecimalNum(sentence);\n    RePositiveQuantifiers(sentence);\n    ReDefalutNum(sentence);\n    ReNumber(sentence);\n    return 0;\n}\n}  // namespace ppspeech"
  },
  {
    "path": "demos/TTSCppFrontend/src/front/text_normalize.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef PADDLE_TTS_SERVING_FRONT_TEXT_NORMALIZE_H\n#define PADDLE_TTS_SERVING_FRONT_TEXT_NORMALIZE_H\n\n#include <glog/logging.h>\n#include <codecvt>\n#include <map>\n#include <regex>\n#include <string>\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/strip.h\"\n#include \"base/type_conv.h\"\n\nnamespace ppspeech {\n\nclass TextNormalizer {\n  public:\n    TextNormalizer() { InitMap(); }\n    ~TextNormalizer() {}\n\n    int InitMap();\n    int Replace(std::wstring *sentence,\n                const int &pos,\n                const int &len,\n                const std::wstring &repstr);\n    int SplitByPunc(const std::wstring &sentence,\n                    std::vector<std::wstring> *sentence_part);\n\n    std::string CreateTextValue(const std::string &num, bool use_zero = true);\n    std::string SingleDigit2Text(const std::string &num_str,\n                                 bool alt_one = false);\n    std::string SingleDigit2Text(const std::wstring &num, bool alt_one = false);\n    std::string MultiDigit2Text(const std::string &num_str,\n                                bool alt_one = false,\n                                bool use_zero = true);\n    std::string MultiDigit2Text(const std::wstring &num,\n                                bool alt_one = false,\n                                bool use_zero = true);\n    std::string Digits2Text(const std::string &num_str);\n    std::string Digits2Text(const std::wstring &num);\n\n    int ReData(std::wstring *sentence);\n    int ReData2(std::wstring *sentence);\n    int ReTime(std::wstring *sentence);\n    int ReTemperature(std::wstring *sentence);\n    int ReFrac(std::wstring *sentence);\n    int RePercentage(std::wstring *sentence);\n    int ReMobilePhone(std::wstring *sentence);\n    int RePhone(std::wstring *sentence);\n    int ReRange(std::wstring *sentence);\n    int ReInterger(std::wstring *sentence);\n    int ReDecimalNum(std::wstring *sentence);\n    int RePositiveQuantifiers(std::wstring *sentence);\n    int ReDefalutNum(std::wstring *sentence);\n    int ReNumber(std::wstring *sentence);\n    int SentenceNormalize(std::wstring *sentence);\n\n\n  private:\n    std::map<std::string, std::string> digits_map;\n    std::map<int, std::string> units_map;\n};\n}  // namespace ppspeech\n\n#endif"
  },
  {
    "path": "demos/TTSCppFrontend/third-party/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\nproject(tts_third_party_libs)\n\ninclude(ExternalProject)\n\n# gflags\nExternalProject_Add(gflags\n    GIT_REPOSITORY https://github.com/gflags/gflags.git\n    GIT_TAG        v2.2.2\n    PREFIX         ${CMAKE_CURRENT_BINARY_DIR}\n    INSTALL_DIR    ${CMAKE_CURRENT_BINARY_DIR}\n    CMAKE_ARGS     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>\n                   -DCMAKE_POSITION_INDEPENDENT_CODE=ON\n                   -DBUILD_STATIC_LIBS=OFF\n                   -DBUILD_SHARED_LIBS=ON\n)\n\n# glog\nExternalProject_Add(\n    glog\n    GIT_REPOSITORY https://github.com/google/glog.git\n    GIT_TAG        v0.6.0\n    PREFIX         ${CMAKE_CURRENT_BINARY_DIR}\n    INSTALL_DIR    ${CMAKE_CURRENT_BINARY_DIR}\n    CMAKE_ARGS     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>\n                   -DCMAKE_POSITION_INDEPENDENT_CODE=ON\n    DEPENDS        gflags\n)\n\n# abseil\nExternalProject_Add(\n    abseil\n    GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git\n    GIT_TAG        20230125.1\n    PREFIX         ${CMAKE_CURRENT_BINARY_DIR}\n    INSTALL_DIR    ${CMAKE_CURRENT_BINARY_DIR}\n    CMAKE_ARGS     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>\n                   -DCMAKE_POSITION_INDEPENDENT_CODE=ON\n                   -DABSL_PROPAGATE_CXX_STD=ON\n)\n\n# cppjieba (header-only)\nExternalProject_Add(\n    cppjieba\n    GIT_REPOSITORY https://github.com/yanyiwu/cppjieba.git\n    GIT_TAG        v5.0.3\n    PREFIX         ${CMAKE_CURRENT_BINARY_DIR}\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND     \"\"\n    INSTALL_COMMAND   \"\"\n    TEST_COMMAND      \"\"\n)\n\n# limonp (header-only)\nExternalProject_Add(\n    limonp\n    GIT_REPOSITORY https://github.com/yanyiwu/limonp.git\n    GIT_TAG        v0.6.6\n    PREFIX         ${CMAKE_CURRENT_BINARY_DIR}\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND     \"\"\n    INSTALL_COMMAND   \"\"\n    TEST_COMMAND      \"\"\n)\n"
  },
  {
    "path": "demos/asr_deployment/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# ASR Deployment by SpeechX\n\n## Introduction\n\nASR deployment support U2/U2++/Deepspeech2 asr model using c++, which is good practice in industry deployment.\n\nMore info about SpeechX, please see [here](../../speechx/README.md).\n\n## Usage\n### 1. Environment\n\n* python - 3.7\n* docker - `registry.baidubce.com/paddlepaddle/paddle:2.2.2-gpu-cuda10.2-cudnn7`\n* os - Ubuntu 16.04.7 LTS\n* gcc/g++/gfortran - 8.2.0\n* cmake - 3.16.0\n\nMore info please see [here](../../speechx/README.md).\n\n### 2. Compile SpeechX\n\nPlease see [here](../../speechx/README.md).\n\n### 3. Usage\n\nFor u2++ asr deployment example, please to see [here](../../speechx/examples/u2pp_ol/wenetspeech/).\n\nFirst go to `speechx/speechx/examples/u2pp_ol/wenetspeech` dir.\n\n- Source path.sh\n  ```bash\n  source path.sh\n  ```\n\n- Download Model, Prepare test data and cmvn\n  ```bash\n  run.sh --stage 0 --stop_stage 1\n  ```\n\n- Decode with WAV\n  \n  ```bash\n  # FP32\n  ./local/recognizer.sh\n\n  # INT8\n  ./local/recognizer_quant.sh\n  ```\n\n  Output:\n  ```bash\n  I1026 16:13:24.683531 48038 u2_recognizer_main.cc:55] utt: BAC009S0916W0495\n  I1026 16:13:24.683578 48038 u2_recognizer_main.cc:56] wav dur: 4.17119 sec.\n  I1026 16:13:24.683595 48038 u2_recognizer_main.cc:64] wav len (sample): 66739\n  I1026 16:13:25.037652 48038 u2_recognizer_main.cc:87] Pratial result: 3 这令\n  I1026 16:13:25.043697 48038 u2_recognizer_main.cc:87] Pratial result: 4 这令\n  I1026 16:13:25.222124 48038 u2_recognizer_main.cc:87] Pratial result: 5 这令被贷款\n  I1026 16:13:25.228385 48038 u2_recognizer_main.cc:87] Pratial result: 6 这令被贷款\n  I1026 16:13:25.414669 48038 u2_recognizer_main.cc:87] Pratial result: 7 这令被贷款的员工\n  I1026 16:13:25.420714 48038 u2_recognizer_main.cc:87] Pratial result: 8 这令被贷款的员工\n  I1026 16:13:25.608129 48038 u2_recognizer_main.cc:87] Pratial result: 9 这令被贷款的员工们请\n  I1026 16:13:25.801620 48038 u2_recognizer_main.cc:87] Pratial result: 10 这令被贷款的员工们请食难安\n  I1026 16:13:25.804101 48038 feature_cache.h:44] set finished\n  I1026 16:13:25.804128 48038 feature_cache.h:51] compute last feats done.\n  I1026 16:13:25.948771 48038 u2_recognizer_main.cc:87] Pratial result: 11 这令被贷款的员工们请食难安\n  I1026 16:13:26.246963 48038 u2_recognizer_main.cc:113] BAC009S0916W0495 这令被贷款的员工们请食难安\n  ```\n\n## Result\n\n> CER compute under aishell-test.\n> RTF compute with feature and decoder, which is more end to end.\n> Machine Intel(R) Xeon(R) Gold 6271C CPU @ 2.60GHz avx512_vnni\n\n### FP32\n\n```\nOverall -> 5.75 % N=104765 C=99035 S=5587 D=143 I=294\nMandarin -> 5.75 % N=104762 C=99035 S=5584 D=143 I=294\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n```\nRTF is: 0.315337\n```\n\n### INT8\n\n```\nOverall -> 5.83 % N=104765 C=98943 S=5675 D=147 I=286\nMandarin -> 5.83 % N=104762 C=98943 S=5672 D=147 I=286\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n```\nRTF is: 0.269674\n```\n"
  },
  {
    "path": "demos/asr_deployment/README_cn.md",
    "content": "([简体中文](./README_cn.md)|English)\n# 基于SpeechX 的 ASR 部署 \n\n## 简介\n\n支持 U2/U2++/Deepspeech2 模型的 C++ 部署，其在工业实践中经常被用到。\n\n更多 Speechx 信息可以参看[文档](../../speechx/README.md)。\n\n## 使用\n### 1. 环境\n\n* python - 3.7\n* docker - `registry.baidubce.com/paddlepaddle/paddle:2.2.2-gpu-cuda10.2-cudnn7`\n* os - Ubuntu 16.04.7 LTS\n* gcc/g++/gfortran - 8.2.0\n* cmake - 3.16.0\n\n更多信息可以参看[文档](../../speechx/README.md)。\n\n### 2. 编译 SpeechX\n\n更多信息可以参看[文档](../../speechx/README.md)。\n\n### 3. 例子\n\nu2++ 识别部署参看[这里](../../speechx/examples/u2pp_ol/wenetspeech/)。\n\n以下是在 `speechx/speechx/examples/u2pp_ol/wenetspeech`.\n\n- Source path.sh\n  ```bash\n  source path.sh\n  ```\n\n- 下载模型，准备测试数据和cmvn文件\n  ```bash\n  run.sh --stage 0 --stop_stage 1\n  ```\n\n- 解码\n  \n  ```bash\n  # FP32\n  ./local/recognizer.sh\n\n  # INT8\n  ./local/recognizer_quant.sh\n  ```\n\n  输出:\n  ```bash\n  I1026 16:13:24.683531 48038 u2_recognizer_main.cc:55] utt: BAC009S0916W0495\n  I1026 16:13:24.683578 48038 u2_recognizer_main.cc:56] wav dur: 4.17119 sec.\n  I1026 16:13:24.683595 48038 u2_recognizer_main.cc:64] wav len (sample): 66739\n  I1026 16:13:25.037652 48038 u2_recognizer_main.cc:87] Pratial result: 3 这令\n  I1026 16:13:25.043697 48038 u2_recognizer_main.cc:87] Pratial result: 4 这令\n  I1026 16:13:25.222124 48038 u2_recognizer_main.cc:87] Pratial result: 5 这令被贷款\n  I1026 16:13:25.228385 48038 u2_recognizer_main.cc:87] Pratial result: 6 这令被贷款\n  I1026 16:13:25.414669 48038 u2_recognizer_main.cc:87] Pratial result: 7 这令被贷款的员工\n  I1026 16:13:25.420714 48038 u2_recognizer_main.cc:87] Pratial result: 8 这令被贷款的员工\n  I1026 16:13:25.608129 48038 u2_recognizer_main.cc:87] Pratial result: 9 这令被贷款的员工们请\n  I1026 16:13:25.801620 48038 u2_recognizer_main.cc:87] Pratial result: 10 这令被贷款的员工们请食难安\n  I1026 16:13:25.804101 48038 feature_cache.h:44] set finished\n  I1026 16:13:25.804128 48038 feature_cache.h:51] compute last feats done.\n  I1026 16:13:25.948771 48038 u2_recognizer_main.cc:87] Pratial result: 11 这令被贷款的员工们请食难安\n  I1026 16:13:26.246963 48038 u2_recognizer_main.cc:113] BAC009S0916W0495 这令被贷款的员工们请食难安\n  ```\n\n## 结果\n\n> CER 测试集为 aishell-test\n> RTF 计算包含提特征和解码\n> 测试机器： Intel(R) Xeon(R) Gold 6271C CPU @ 2.60GHz avx512_vnni\n\n### FP32\n\n```\nOverall -> 5.75 % N=104765 C=99035 S=5587 D=143 I=294\nMandarin -> 5.75 % N=104762 C=99035 S=5584 D=143 I=294\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n```\nRTF is: 0.315337\n```\n\n### INT8\n\n```\nOverall -> 5.87 % N=104765 C=98909 S=5711 D=145 I=289\nMandarin -> 5.86 % N=104762 C=98909 S=5708 D=145 I=289\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n"
  },
  {
    "path": "demos/audio_content_search/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# ACS (Audio Content Search)\n\n## Introduction\nACS, or Audio Content Search, refers to the problem of getting the key word time stamp from automatically transcribe spoken language (speech-to-text). \n\nThis demo is an implementation of obtaining the keyword timestamp in the text from a given audio file. It can be done by a single command or a few lines in python using `PaddleSpeech`. \nNow, the search word in demo is:\n```\n我\n康\n```\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from medium and hard to install paddlespeech.\n\nThe dependency refers to the requirements.txt, and install the dependency as follows:\n\n```\npip install -r requirements.txt \n```\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 3. run paddlespeech_server\nBefore using the client, it is necessary to start paddlespeech_servers.\n\nHere are sample server configuration：\n```bash\nbash demos/audio_content_search/run.sh\n```\nThe logs of the two services will be recorded in 'acs.log' and 'streaming_asr.log' in this configuration.\n\n### 4. Usage\n- Command Line(Recommended)\n  ```bash\n  # Chinese\n  paddlespeech_client acs --server_ip 127.0.0.1 --port 8490 --input ./zh.wav \n  ```\n  \n  Usage:\n  ```bash\n  paddlespeech asr --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize.\n  - `server_ip`: the server ip.\n  - `port`: the server port.\n  - `lang`: the language type of the model. Default: `zh`.\n  - `sample_rate`: Sample rate of the model. Default: `16000`.\n  - `audio_format`: The audio format.\n\n  Output:\n  ```bash\n  [2022-05-15 15:00:58,185] [    INFO] - acs http client start\n  [2022-05-15 15:00:58,185] [    INFO] - endpoint: http://127.0.0.1:8490/paddlespeech/asr/search\n  [2022-05-15 15:01:03,220] [    INFO] - acs http client finished\n  [2022-05-15 15:01:03,221] [    INFO] - ACS result: {'transcription': '我认为跑步最重要的就是给我带来了身体健康', 'acs': [{'w': '我', 'bg': 0, 'ed': 1.6800000000000002}, {'w': '我', 'bg': 2.1, 'ed': 4.28}, {'w': '康', 'bg': 3.2, 'ed': 4.92}]}\n  [2022-05-15 15:01:03,221] [    INFO] - Response time 5.036084 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ACSClientExecutor\n\n  acs_executor = ACSClientExecutor()\n  res = acs_executor(\n      input='./zh.wav',\n      server_ip=\"127.0.0.1\",\n      port=8490,)\n  print(res)\n  ```\n\n  Output:\n  ```bash\n  [2022-05-15 15:08:13,955] [    INFO] - acs http client start\n  [2022-05-15 15:08:13,956] [    INFO] - endpoint: http://127.0.0.1:8490/paddlespeech/asr/search\n  [2022-05-15 15:08:19,026] [    INFO] - acs http client finished\n  {'transcription': '我认为跑步最重要的就是给我带来了身体健康', 'acs': [{'w': '我', 'bg': 0, 'ed': 1.6800000000000002}, {'w': '我', 'bg': 2.1, 'ed': 4.28}, {'w': '康', 'bg': 3.2, 'ed': 4.92}]}\n  ```\n"
  },
  {
    "path": "demos/audio_content_search/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 语音内容搜索\n## 介绍\n语音内容搜索是一项用计算机程序获取转录语音内容关键词时间戳的技术。\n\n这个 demo 是一个从给定音频文件获取其文本中关键词时间戳的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n当前示例中检索词是\n```\n我\n康\n```\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 medium，hard 三中方式中选择一种方式安装。\n依赖参见 requirements.txt, 安装依赖\n\n```\npip install -r requirements.txt\n```\n\n### 2. 准备输入\n这个 demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 demo 的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 3. 启动 server\n使用 client 之前需要先启动 paddlespeech_server。\n\n可以使用默认 server 配置：\n```bash\nbash demos/audio_content_search/run.sh\n```\n该配置下两个服务的日志会被记录在 `acs.log` 和 `streaming_asr.log` 中。\n\n### 4. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  # 中文\n  paddlespeech_client acs --server_ip 127.0.0.1 --port 8490 --input ./zh.wav \n  ```\n  \n  使用方法：\n  ```bash\n  paddlespeech asr --help\n  ```\n  参数：\n  - `input`(必须输入)：用于识别的音频文件。\n  - `server_ip`: 服务的ip。\n  - `port`：服务的端口。\n  - `lang`：模型语言，默认值：`zh`。\n  - `sample_rate`：音频采样率，默认值：`16000`。\n  - `audio_format`: 音频的格式。\n\n  输出：\n  ```bash\n  [2022-05-15 15:00:58,185] [    INFO] - acs http client start\n  [2022-05-15 15:00:58,185] [    INFO] - endpoint: http://127.0.0.1:8490/paddlespeech/asr/search\n  [2022-05-15 15:01:03,220] [    INFO] - acs http client finished\n  [2022-05-15 15:01:03,221] [    INFO] - ACS result: {'transcription': '我认为跑步最重要的就是给我带来了身体健康', 'acs': [{'w': '我', 'bg': 0, 'ed': 1.6800000000000002}, {'w': '我', 'bg': 2.1, 'ed': 4.28}, {'w': '康', 'bg': 3.2, 'ed': 4.92}]}\n  [2022-05-15 15:01:03,221] [    INFO] - Response time 5.036084 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ACSClientExecutor\n\n  acs_executor = ACSClientExecutor()\n  res = acs_executor(\n      input='./zh.wav',\n      server_ip=\"127.0.0.1\",\n      port=8490,)\n  print(res)\n  ```\n\n  输出：\n  ```bash\n  [2022-05-15 15:08:13,955] [    INFO] - acs http client start\n  [2022-05-15 15:08:13,956] [    INFO] - endpoint: http://127.0.0.1:8490/paddlespeech/asr/search\n  [2022-05-15 15:08:19,026] [    INFO] - acs http client finished\n  {'transcription': '我认为跑步最重要的就是给我带来了身体健康', 'acs': [{'w': '我', 'bg': 0, 'ed': 1.6800000000000002}, {'w': '我', 'bg': 2.1, 'ed': 4.28}, {'w': '康', 'bg': 3.2, 'ed': 4.92}]}\n  ```\n"
  },
  {
    "path": "demos/audio_content_search/acs_clinet.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.utils.audio_handler import ASRHttpHandler\n\n\ndef main(args):\n    logger.info(\"asr http client start\")\n    audio_format = \"wav\"\n    sample_rate = 16000\n    lang = \"zh\"\n    handler = ASRHttpHandler(\n        server_ip=args.server_ip, port=args.port, endpoint=args.endpoint)\n    res = handler.run(args.wavfile, audio_format, sample_rate, lang)\n    # res = res['result']\n    logger.info(f\"the final result: {res}\")\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"audio content search client\")\n    parser.add_argument(\n        '--server_ip', type=str, default='127.0.0.1', help='server ip')\n    parser.add_argument('--port', type=int, default=8090, help='server port')\n    parser.add_argument(\n        \"--wavfile\",\n        action=\"store\",\n        help=\"wav file path \",\n        default=\"./16_audio.wav\")\n    parser.add_argument(\n        '--endpoint',\n        type=str,\n        default='/paddlespeech/asr/search',\n        help='server endpoint')\n    args = parser.parse_args()\n\n    main(args)\n"
  },
  {
    "path": "demos/audio_content_search/conf/acs_application.yaml",
    "content": "#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8490\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['acs_python']\n# protocol = ['http'] (only one can be selected). \n# http only support offline engine type.\nprotocol: 'http'\nengine_list: ['acs_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ACS #########################################\n################### acs task: engine_type: python ###############################\nacs_python:\n    task: acs\n    asr_protocol: 'websocket' # 'websocket'\n    offset: 1.0 # second\n    asr_server_ip: 127.0.0.1\n    asr_server_port: 8390\n    lang: 'zh'\n    word_list: \"./conf/words.txt\"\n    sample_rate: 16000\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n    ping_timeout: 100 # seconds\n\n\n\n\n"
  },
  {
    "path": "demos/audio_content_search/conf/words.txt",
    "content": "我\n康"
  },
  {
    "path": "demos/audio_content_search/conf/ws_conformer_application.yaml",
    "content": "#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8390\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_multicn'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: 'attention_rescoring' \n    num_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    continuous_decoding: False # disable continue decoding when endpoint detected\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2"
  },
  {
    "path": "demos/audio_content_search/conf/ws_conformer_wenetspeech_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8390\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    num_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/audio_content_search/requirements.txt",
    "content": "websocket-client"
  },
  {
    "path": "demos/audio_content_search/run.sh",
    "content": "export CUDA_VISIBLE_DEVICE=0,1,2,3\n# we need the streaming asr server\nnohup python3 streaming_asr_server.py --config_file conf/ws_conformer_application.yaml > streaming_asr.log  2>&1  &\n\n# start the acs server\nnohup paddlespeech_server start --config_file conf/acs_application.yaml > acs.log 2>&1 &\n\n"
  },
  {
    "path": "demos/audio_content_search/streaming_asr_server.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.bin.paddlespeech_server import ServerExecutor\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        prog='paddlespeech_server.start', add_help=True)\n    parser.add_argument(\n        \"--config_file\",\n        action=\"store\",\n        help=\"yaml file of the app\",\n        default=None,\n        required=True)\n\n    parser.add_argument(\n        \"--log_file\",\n        action=\"store\",\n        help=\"log file\",\n        default=\"./log/paddlespeech.log\")\n    logger.info(\"start to parse the args\")\n    args = parser.parse_args()\n\n    logger.info(\"start to launch the streaming asr server\")\n    streaming_asr_server = ServerExecutor()\n    streaming_asr_server(config_file=args.config_file, log_file=args.log_file)\n"
  },
  {
    "path": "demos/audio_searching/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Audio Searching\n\n## Introduction\nAs the Internet continues to evolve, unstructured data such as emails, social media photos, live videos, and customer service voice calls have become increasingly common. If we want to process the data on a computer, we need to use embedding technology to transform the data into vector and store, index, and query it.\n\nHowever, when there is a large amount of data, such as hundreds of millions of audio tracks, it is more difficult to do a similarity search. The exhaustive method is feasible, but very time consuming.  For this scenario, this demo will introduce how to build an audio similarity retrieval system using the open source vector database Milvus.\n\nAudio retrieval (speech, music, speaker, etc.) enables querying and finding similar sounds (or the same speaker) in a large amount of audio data.  The audio similarity retrieval system can be used to identify similar sound effects, minimize intellectual property infringement, quickly retrieve the voice print library, and help enterprises control fraud and identity theft. Audio retrieval also plays an important role in the classification and statistical analysis of audio data.\n\nIn this demo, you will learn how to build an audio retrieval system to retrieve similar sound snippets. The uploaded audio clips are converted into vector data using paddlespeech-based pre-training models (audio classification model, speaker recognition model, etc.) and stored in Milvus.  Milvus automatically generates a unique ID for each vector, then stores the ID and the corresponding audio information (audio ID, audio speaker ID, etc.) in MySQL to complete the library construction.  During retrieval, users upload test audio to obtain vector, and then conduct vector similarity search in Milvus.The retrieval result returned by Milvus is vector ID, and the corresponding audio information can be queried in MySQL by ID.\n\n![Workflow of an audio searching system](./img/audio_searching.png)\n\nNote：this demo uses the [CN-Celeb](http://openslr.org/82/) dataset of at least 650,000 audio entries and 3000 speakers to build the audio vector library, which is then retrieved using a preset distance calculation. The dataset can also use other,  Adjust as needed, e.g. Librispeech, VoxCeleb, UrbanSound, GloVe, MNIST, etc.\n\n## Usage\n### 1. Prepare PaddleSpeech\nAudio vector extraction requires PaddleSpeech training model, so please make sure that PaddleSpeech has been installed before running. Specific installation steps: See [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).  \n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare MySQL and Milvus services by docker-compose\nThe audio similarity search system requires Milvus, MySQL services. We can start these containers with one click through [docker-compose.yaml](./docker-compose.yaml), so please make sure you have [installed Docker Engine](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) before running. then\n\n```bash\n## Enter the audio_searching directory for the following example\ncd ~/PaddleSpeech/demos/audio_searching/\n\n## Then start the related services within the container\ndocker-compose -f docker-compose.yaml up -d\n```\n\nYou will see the that all containers are created:\n\n```bash\nCreating network \"quick_deploy_app_net\" with driver \"bridge\"\nCreating milvus-minio    ... done\nCreating milvus-etcd     ... done\nCreating audio-mysql     ... done\nCreating milvus-standalone ... done\nCreating audio-webclient     ... done\n```\n\nAnd show all containers with `docker ps`, and you can use `docker logs audio-mysql` to get the logs of server container\n\n```bash\nCONTAINER ID  IMAGE COMMAND CREATED STATUS  PORTS NAMES\nb2bcf279e599  milvusdb/milvus:v2.0.1  \"/tini -- milvus run…\"  22 hours ago  Up 22 hours 0.0.0.0:19530->19530/tcp  milvus-standalone\nd8ef4c84e25c  mysql:5.7 \"docker-entrypoint.s…\"  22 hours ago  Up 22 hours 0.0.0.0:3306->3306/tcp, 33060/tcp audio-mysql\n8fb501edb4f3  quay.io/coreos/etcd:v3.5.0  \"etcd -advertise-cli…\"  22 hours ago  Up 22 hours 2379-2380/tcp milvus-etcd\nffce340b3790  minio/minio:RELEASE.2020-12-03T00-03-10Z  \"/usr/bin/docker-ent…\"  22 hours ago  Up 22 hours (healthy) 9000/tcp  milvus-minio\n15c84a506754  paddlepaddle/paddlespeech-audio-search-client:2.3  \"/bin/bash -c '/usr/…\"  22 hours ago  Up 22 hours (healthy) 0.0.0.0:8068->80/tcp  audio-webclient\n```\n\n### 3. Start API Server\nThen to start the system server, and it provides HTTP backend services.\n\n- Install the Python packages\n\n  ```bash\n  pip install -r requirements.txt\n  ```\n- Set configuration(In the case of local running, you can skip this step.)\n\n  ```bash\n  ## Method 1: Modify the source file\n  vim src/config.py\n\n  ## Method 2: Modify the environment variables, as shown in\n  export MILVUS_HOST=127.0.0.1\n  export MYSQL_HOST=127.0.0.1\n  ```\n\n  Here listing some parameters that need to be set, for more information please refer to [config.py](./src/config.py).\n\n  | **Parameter**    |**Description**         | **Default setting** |\n  | ---------------- | -----------------------| ------------------- |\n  | MILVUS_HOST      | The IP address of Milvus, you can get it by ifconfig. If running everything on one machine, most likely 127.0.0.1 | 127.0.0.1\n  | MILVUS_PORT      | Port of Milvus.    | 19530               |\n  | VECTOR_DIMENSION | Dimension of the vectors.        | 2048          |\n  | MYSQL_HOST       | The IP address of Mysql.    | 127.0.0.1           |\n  | MYSQL_PORT       | Port of Mysql.        | 3306                |\n  | DEFAULT_TABLE    | The milvus and mysql default collection name.  | audio_table          |\n\n- Run the code\n\n  Then start the server with Fastapi.\n\n  ```bash\n  export PYTHONPATH=$PYTHONPATH:./src\n  python src/audio_search.py\n  ```\n\n  Then you will see the Application is started:\n\n  ```bash\n  INFO:     Started server process [13352]\n  2022-03-26 22:45:30,838 ｜ INFO ｜ server.py ｜ serve ｜ 75 ｜ Started server process [13352]\n  INFO:     Waiting for application startup.\n  2022-03-26 22:45:30,839 ｜ INFO ｜ on.py ｜ startup ｜ 45 ｜ Waiting for application startup.\n  INFO:     Application startup complete.\n  2022-03-26 22:45:30,839 ｜ INFO ｜ on.py ｜ startup ｜ 59 ｜ Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit)\n  2022-03-26 22:45:30,840 ｜ INFO ｜ server.py ｜ _log_started_message ｜ 206 ｜ Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit)\n  ```\n\n### 4. Usage\n- Prepare data\n  ```bash\n  wget -c https://www.openslr.org/resources/82/cn-celeb_v2.tar.gz && tar -xvf cn-celeb_v2.tar.gz \n  ```\n  **Note**: If you want to build a quick demo, you can use ./src/test_audio_search.py:download_audio_data function, it downloads 20 audio files , Subsequent results show this collection as an example\n\n- Prepare model(Skip this step if you use the default model.)\n  ```bash\n  ## Modify model configuration parameters. Currently, only ecapatdnn_voxceleb12 is supported, and multiple types will be supported in the future\n  vim ./src/encode.py\n  ```\n \n- Scripts test (Recommended)\n\n    The internal process is downloading data, loading the paddlespeech model, extracting embedding, storing library, retrieving and deleting library  \n    ```bash\n    python ./src/test_audio_search.py\n    ```\n\n    Output：\n    ```bash\n    Downloading https://paddlespeech.cdn.bcebos.com/vector/audio/example_audio.tar.gz ...\n    ...\n    Unpacking ./example_audio.tar.gz ...\n    [2022-03-26 22:50:54,987] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:50:54,987] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:50:54,987] [    INFO] - The audio file format is right\n    [2022-03-26 22:50:54,988] [    INFO] - device type: cpu\n    [2022-03-26 22:50:54,988] [    INFO] - load the pretrained model: ecapatdnn_voxceleb12-16k\n    [2022-03-26 22:50:54,990] [    INFO] - Downloading sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_0.tar.gz from https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_0.tar.gz\n    ...\n    [2022-03-26 22:51:17,285] [    INFO] - start to dynamic import the model class\n    [2022-03-26 22:51:17,285] [    INFO] - model name ecapatdnn\n    [2022-03-26 22:51:23,864] [    INFO] - start to set the model parameters to model\n    [2022-03-26 22:54:08,115] [    INFO] - create the model instance success\n    [2022-03-26 22:54:08,116] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_\n    searching/example_audio/knife_hit_iron3.wav\n    [2022-03-26 22:54:08,116] [    INFO] - load the audio sample points, shape is: (11012,)\n    [2022-03-26 22:54:08,150] [    INFO] - extract the audio feat, shape is: (80, 69)\n    [2022-03-26 22:54:08,152] [    INFO] - feats shape: [1, 80, 69]\n    [2022-03-26 22:54:08,154] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:08,155] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:08,155] [    INFO] - feats shape:[1, 80, 69], lengths shape: [1]\n    [2022-03-26 22:54:08,433] [    INFO] - embedding size: (192,)\n    Extracting feature from audio No. 1 , 20 audios in total\n    [2022-03-26 22:54:08,435] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:54:08,435] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:54:08,436] [    INFO] - The audio file format is right\n    [2022-03-26 22:54:08,436] [    INFO] - device type: cpu\n    [2022-03-26 22:54:08,436] [    INFO] - Model has been initialized\n    [2022-03-26 22:54:08,436] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_searching/example_audio/sword_wielding.wav\n    [2022-03-26 22:54:08,436] [    INFO] - load the audio sample points, shape is: (6391,)\n    [2022-03-26 22:54:08,452] [    INFO] - extract the audio feat, shape is: (80, 40)\n    [2022-03-26 22:54:08,454] [    INFO] - feats shape: [1, 80, 40]\n    [2022-03-26 22:54:08,454] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:08,454] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:08,455] [    INFO] - feats shape:[1, 80, 40], lengths shape: [1]\n    [2022-03-26 22:54:08,633] [    INFO] - embedding size: (192,)\n    Extracting feature from audio No. 2 , 20 audios in total\n    ...\n    2022-03-26 22:54:15,892 ｜ INFO ｜ audio_search.py ｜ load_audios ｜ 85 ｜ Successfully loaded data, total count: 20\n    2022-03-26 22:54:15,908 ｜ INFO ｜ audio_search.py ｜ count_audio ｜ 148 ｜ Successfully count the number of data!\n    [2022-03-26 22:54:15,916] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:54:15,916] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:54:15,916] [    INFO] - The audio file format is right\n    [2022-03-26 22:54:15,916] [    INFO] - device type: cpu\n    [2022-03-26 22:54:15,916] [    INFO] - Model has been initialized\n    [2022-03-26 22:54:15,916] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_searching/example_audio/test.wav\n    [2022-03-26 22:54:15,917] [    INFO] - load the audio sample points, shape is: (8456,)\n    [2022-03-26 22:54:15,923] [    INFO] - extract the audio feat, shape is: (80, 53)\n    [2022-03-26 22:54:15,924] [    INFO] - feats shape: [1, 80, 53]\n    [2022-03-26 22:54:15,924] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:15,924] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:15,924] [    INFO] - feats shape:[1, 80, 53], lengths shape: [1]\n    [2022-03-26 22:54:16,051] [    INFO] - embedding size: (192,)\n    ...\n    2022-03-26 22:54:16,086 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/test.wav, score 100.0\n    2022-03-26 22:54:16,087 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/knife_chopping.wav, score 29.182177782058716\n    2022-03-26 22:54:16,087 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/knife_cut_into_body.wav, score 22.73637056350708\n    ...\n    2022-03-26 22:54:16,088 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 136 ｜ Successfully searched similar audio!\n    2022-03-26 22:54:17,164 ｜ INFO ｜ audio_search.py ｜ drop_tables ｜ 160 ｜ Successfully drop tables in Milvus and MySQL!\n    ```\n- GUI test (Optional)\n  \n    Navigate to 127.0.0.1:8068 in your browser to access the front-end interface.\n\n    **Note**: If the browser and the service are not on the same machine, then the IP needs to be changed to the IP of the machine where the service is located, and the corresponding API_URL in docker-compose.yaml needs to be changed, and the docker-compose.yaml file needs to be re-executed for the change to take effect.\n\n    - Insert data\n\n      Download the data on the server and decompress it to a file, for example, /home/speech/data/. Then enter /home/speech/data/ in the address bar of the upload page to upload the data.\n    \n      ![](./img/insert.png)\n\n    - Search for similar audio\n\n      Select the magnifying glass icon on the left side of the interface. Then, press the \"Default Target Audio File\" button and upload a .wav sound file from the client you'd like to search. Results will be displayed.\n\n      ![](./img/search.png)\n\n### 5.Result\n\n machine configuration：\n- OS: CentOS release 7.6 \n- kernel：4.17.11-1.el7.elrepo.x86_64\n- CPU：Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz \n- memory：132G\n\ndataset：\n- CN-Celeb, train size 650,000, test size 10,000, dimension 192, distance L2\n\nrecall and elapsed time statistics are shown in the following figure：\n\n  ![](./img/result.png)\n\n\nThe retrieval framework based on Milvus takes about 2.9 milliseconds to retrieve on the premise of 90% recall rate, and it takes about 500 milliseconds for feature extraction (testing audio takes about 5 seconds), that is, a single audio test takes about 503 milliseconds in total, which can meet most application scenarios.\n\n* compute embedding takes 500 ms\n* retrieval with cosine takes 2.9 ms\n* total takes 503 ms\n\n> test audio is 5 sec\n\n### 6.Pretrained Models\n\nHere is a list of pretrained models released by PaddleSpeech :\n\n| Model | Sample Rate\n| :--- | :---: \n| ecapa_tdnn | 16000\n"
  },
  {
    "path": "demos/audio_searching/README_cn.md",
    "content": "\n(简体中文|[English](./README.md))\n\n# 音频相似性检索\n## 介绍\n\n随着互联网不断发展，电子邮件、社交媒体照片、直播视频、客服语音等非结构化数据已经变得越来越普遍。如果想要使用计算机来处理这些数据，需要使用 embedding 技术将这些数据转化为向量 vector，然后进行存储、建索引、并查询。\n\n但是，当数据量很大，比如上亿条音频要做相似度搜索，就比较困难了。穷举法固然可行，但非常耗时。针对这种场景，该 demo 将介绍如何使用开源向量数据库 Milvus 搭建音频相似度检索系统。\n\n音频检索（如演讲、音乐、说话人等检索）实现了在海量音频数据中查询并找出相似声音（或相同说话人）片段。音频相似性检索系统可用于识别相似的音效、最大限度减少知识产权侵权等，还可以快速的检索声纹库、帮助企业控制欺诈和身份盗用等。在音频数据的分类和统计分析中，音频检索也发挥着重要作用。\n\n在本 demo 中，你将学会如何构建一个音频检索系统，用来检索相似的声音片段。使用基于 PaddleSpeech 预训练模型（音频分类模型，说话人识别模型等）将上传的音频片段转换为向量数据，并存储在 Milvus 中。Milvus 自动为每个向量生成唯一的 ID，然后将 ID 和 相应的音频信息（音频id，音频的说话人id等等）存储在 MySQL，这样就完成建库的工作。用户在检索时，上传测试音频，得到向量，然后在 Milvus 中进行向量相似度搜索，Milvus 返回的检索结果为向量 ID，通过 ID 在 MySQL 内部查询相应的音频信息即可。\n\n![音频检索流程图](./img/audio_searching.png)\n\n注：该 demo 使用 [CN-Celeb](http://openslr.org/82/) 数据集，包括至少 650000 条音频，3000 个说话人，来建立音频向量库（音频特征，或音频说话人特征），然后通过预设的距离计算方式进行音频（或说话人）检索，这里面数据集也可以使用其他的，根据需要调整，如Librispeech，VoxCeleb，UrbanSound，GloVe，MNIST等。\n\n## 使用方法\n### 1. PaddleSpeech 安装\n音频向量的提取需要用到基于 PaddleSpeech 训练的模型，所以请确保在运行之前已经安装了 PaddleSpeech，具体安装步骤，详见[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三种方式中选择一种方式安装。\n\n### 2. MySQL 和 Milvus 安装\n音频相似性的检索需要用到 Milvus, MySQL 服务。 我们可以通过 [docker-compose.yaml](./docker-compose.yaml) 一键启动这些容器，所以请确保在运行之前已经安装了 [Docker Engine](https://docs.docker.com/engine/install/) 和 [Docker Compose](https://docs.docker.com/compose/install/)。 即\n\n```bash\n## 先进入到 audio_searching 目录，如下示例\ncd ~/PaddleSpeech/demos/audio_searching/\n\n## 然后启动容器内的相关服务\ndocker-compose -f docker-compose.yaml up -d\n```\n\n你会看到所有的容器都被创建:\n\n```bash\nCreating network \"quick_deploy_app_net\" with driver \"bridge\"\nCreating milvus-minio    ... done\nCreating milvus-etcd     ... done\nCreating audio-mysql     ... done\nCreating milvus-standalone ... done\nCreating audio-webclient     ... done\n```\n\n可以采用'docker ps'来显示所有的容器，还可以使用'docker logs audio-mysql'来获取服务器容器的日志：\n\n```bash\nCONTAINER ID  IMAGE COMMAND CREATED STATUS  PORTS NAMES\nb2bcf279e599  milvusdb/milvus:v2.0.1  \"/tini -- milvus run…\"  22 hours ago  Up 22 hours 0.0.0.0:19530->19530/tcp  milvus-standalone\nd8ef4c84e25c  mysql:5.7 \"docker-entrypoint.s…\"  22 hours ago  Up 22 hours 0.0.0.0:3306->3306/tcp, 33060/tcp audio-mysql\n8fb501edb4f3  quay.io/coreos/etcd:v3.5.0  \"etcd -advertise-cli…\"  22 hours ago  Up 22 hours 2379-2380/tcp milvus-etcd\nffce340b3790  minio/minio:RELEASE.2020-12-03T00-03-10Z  \"/usr/bin/docker-ent…\"  22 hours ago  Up 22 hours (healthy) 9000/tcp  milvus-minio\n15c84a506754  paddlepaddle/paddlespeech-audio-search-client:2.3  \"/bin/bash -c '/usr/…\"  22 hours ago  Up 22 hours (healthy) 0.0.0.0:8068->80/tcp  audio-webclient\n\n```\n\n### 3. 配置并启动 API 服务\n启动系统服务程序，它会提供基于 HTTP 后端服务。\n\n- 安装服务依赖的 python 基础包\n\n  ```bash\n  pip install -r requirements.txt\n  ```\n- 修改配置(本地运行情况下，一般不用修改，可以跳过该步骤)\n\n  ```bash\n  ## 方法一：修改源码文件\n  vim src/config.py\n\n  ## 方法二：修改环境变量，如下所示\n  export MILVUS_HOST=127.0.0.1\n  export MYSQL_HOST=127.0.0.1\n  ```\n\n  这里列出了一些需要设置的参数，更多信息请参考 [config.py](./src/config.py)\n\n  | **参数**    | **描述**                | **默认设置** |\n  | ---------------- | -------------------- | ------------------- |\n  | MILVUS_HOST      | Milvus 服务的 IP 地址 | 127.0.0.1           |\n  | MILVUS_PORT      | Milvus 服务的端口号   | 19530               |\n  | VECTOR_DIMENSION | 特征向量的维度        | 192                 |\n  | MYSQL_HOST       | Mysql 服务的 IP 地址  | 127.0.0.1           |\n  | MYSQL_PORT       | Mysql 服务的端口号    | 3306                |\n  | DEFAULT_TABLE    | 默认存储的表名        | audio_table         |\n\n- 运行程序\n\n  启动用 Fastapi 构建的服务\n\n  ```bash\n  export PYTHONPATH=$PYTHONPATH:./src\n  python src/audio_search.py\n  ```\n\n  然后你会看到应用程序启动:\n\n  ```bash\n  INFO:     Started server process [13352]\n  2022-03-26 22:45:30,838 ｜ INFO ｜ server.py ｜ serve ｜ 75 ｜ Started server process [13352]\n  INFO:     Waiting for application startup.\n  2022-03-26 22:45:30,839 ｜ INFO ｜ on.py ｜ startup ｜ 45 ｜ Waiting for application startup.\n  INFO:     Application startup complete.\n  2022-03-26 22:45:30,839 ｜ INFO ｜ on.py ｜ startup ｜ 59 ｜ Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit)\n  2022-03-26 22:45:30,840 ｜ INFO ｜ server.py ｜ _log_started_message ｜ 206 ｜ Uvicorn running on http://0.0.0.0:8002 (Press CTRL+C to quit)\n  ```\n\n### 4. 测试方法\n- 准备数据\n  ```bash\n  wget -c https://www.openslr.org/resources/82/cn-celeb_v2.tar.gz && tar -xvf cn-celeb_v2.tar.gz \n  ```\n  **注**：如果希望快速搭建 demo，可以采用 ./src/test_audio_search.py:download_audio_data 内部的 20 条音频，另外后续结果展示以该集合为例\n\n- 准备模型（如果使用默认模型，可以跳过此步骤）\n  ```bash\n  ## 修改模型配置参数，目前 model 仅支持 ecapatdnn_voxceleb12，后续将支持多种类型\n  vim ./src/encode.py\n  ```\n \n - 脚本测试（推荐）\n\n    ```bash\n    python ./src/test_audio_search.py\n    ```\n    注：内部将依次下载数据，加载 paddlespeech 模型，提取 embedding，存储建库，检索，删库\n\n    输出：\n    ```bash\n    Downloading https://paddlespeech.cdn.bcebos.com/vector/audio/example_audio.tar.gz ...\n    ...\n    Unpacking ./example_audio.tar.gz ...\n    [2022-03-26 22:50:54,987] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:50:54,987] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:50:54,987] [    INFO] - The audio file format is right\n    [2022-03-26 22:50:54,988] [    INFO] - device type: cpu\n    [2022-03-26 22:50:54,988] [    INFO] - load the pretrained model: ecapatdnn_voxceleb12-16k\n    [2022-03-26 22:50:54,990] [    INFO] - Downloading sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_0.tar.gz from https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_0.tar.gz\n    ...\n    [2022-03-26 22:51:17,285] [    INFO] - start to dynamic import the model class\n    [2022-03-26 22:51:17,285] [    INFO] - model name ecapatdnn\n    [2022-03-26 22:51:23,864] [    INFO] - start to set the model parameters to model\n    [2022-03-26 22:54:08,115] [    INFO] - create the model instance success\n    [2022-03-26 22:54:08,116] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_\n    searching/example_audio/knife_hit_iron3.wav\n    [2022-03-26 22:54:08,116] [    INFO] - load the audio sample points, shape is: (11012,)\n    [2022-03-26 22:54:08,150] [    INFO] - extract the audio feat, shape is: (80, 69)\n    [2022-03-26 22:54:08,152] [    INFO] - feats shape: [1, 80, 69]\n    [2022-03-26 22:54:08,154] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:08,155] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:08,155] [    INFO] - feats shape:[1, 80, 69], lengths shape: [1]\n    [2022-03-26 22:54:08,433] [    INFO] - embedding size: (192,)\n    Extracting feature from audio No. 1 , 20 audios in total\n    [2022-03-26 22:54:08,435] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:54:08,435] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:54:08,436] [    INFO] - The audio file format is right\n    [2022-03-26 22:54:08,436] [    INFO] - device type: cpu\n    [2022-03-26 22:54:08,436] [    INFO] - Model has been initialized\n    [2022-03-26 22:54:08,436] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_searching/example_audio/sword_wielding.wav\n    [2022-03-26 22:54:08,436] [    INFO] - load the audio sample points, shape is: (6391,)\n    [2022-03-26 22:54:08,452] [    INFO] - extract the audio feat, shape is: (80, 40)\n    [2022-03-26 22:54:08,454] [    INFO] - feats shape: [1, 80, 40]\n    [2022-03-26 22:54:08,454] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:08,454] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:08,455] [    INFO] - feats shape:[1, 80, 40], lengths shape: [1]\n    [2022-03-26 22:54:08,633] [    INFO] - embedding size: (192,)\n    Extracting feature from audio No. 2 , 20 audios in total\n    ...\n    2022-03-26 22:54:15,892 ｜ INFO ｜ audio_search.py ｜ load_audios ｜ 85 ｜ Successfully loaded data, total count: 20\n    2022-03-26 22:54:15,908 ｜ INFO ｜ audio_search.py ｜ count_audio ｜ 148 ｜ Successfully count the number of data!\n    [2022-03-26 22:54:15,916] [    INFO] - checking the aduio file format......\n    [2022-03-26 22:54:15,916] [    INFO] - The sample rate is 16000\n    [2022-03-26 22:54:15,916] [    INFO] - The audio file format is right\n    [2022-03-26 22:54:15,916] [    INFO] - device type: cpu\n    [2022-03-26 22:54:15,916] [    INFO] - Model has been initialized\n    [2022-03-26 22:54:15,916] [    INFO] - Preprocess audio file: /home/zhaoqingen/PaddleSpeech/demos/audio_searching/example_audio/test.wav\n    [2022-03-26 22:54:15,917] [    INFO] - load the audio sample points, shape is: (8456,)\n    [2022-03-26 22:54:15,923] [    INFO] - extract the audio feat, shape is: (80, 53)\n    [2022-03-26 22:54:15,924] [    INFO] - feats shape: [1, 80, 53]\n    [2022-03-26 22:54:15,924] [    INFO] - audio extract the feat success\n    [2022-03-26 22:54:15,924] [    INFO] - start to do backbone network model forward\n    [2022-03-26 22:54:15,924] [    INFO] - feats shape:[1, 80, 53], lengths shape: [1]\n    [2022-03-26 22:54:16,051] [    INFO] - embedding size: (192,)\n    ...\n    2022-03-26 22:54:16,086 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/test.wav, score 100.0\n    2022-03-26 22:54:16,087 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/knife_chopping.wav, score 29.182177782058716\n    2022-03-26 22:54:16,087 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 132 ｜ search result http://testserver/data?audio_path=./example_audio/knife_cut_into_body.wav, score 22.73637056350708\n    ...\n    2022-03-26 22:54:16,088 ｜ INFO ｜ audio_search.py ｜ search_local_audio ｜ 136 ｜ Successfully searched similar audio!\n    2022-03-26 22:54:17,164 ｜ INFO ｜ audio_search.py ｜ drop_tables ｜ 160 ｜ Successfully drop tables in Milvus and MySQL!\n    ```\n\n  - 前端测试（可选）\n  \n    在浏览器中输入 127.0.0.1:8068 访问前端页面\n    \n    **注**：如果浏览器和服务不在同一台机器上，那么 IP 需要修改成服务所在的机器 IP，并且 docker-compose.yaml 中相应的 API_URL 也要修改，然后重新执行 docker-compose.yaml 文件，使修改生效。\n\n    - 上传音频\n    \n      在服务端下载数据并解压到一文件夹，假设为 /home/speech/data/，那么在上传页面地址栏输入 /home/speech/data/ 进行数据上传\n    \n      ![](./img/insert.png)\n\n    - 检索相似音频\n\n      选择左上角放大镜，点击 “Default Target Audio File” 按钮，从客户端上传测试音频，接着你将看到检索结果\n\n      ![](./img/search.png)\n\n### 5. 结果\n\n机器配置：\n- 操作系统: CentOS release 7.6 \n- 内核：4.17.11-1.el7.elrepo.x86_64\n- 处理器：Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz \n- 内存：132G\n\n数据集：\n- CN-Celeb, 训练集 65万, 测试集 1万，向量维度 192，距离计算方式 L2\n\n召回和耗时统计如下图：\n\n  ![](./img/result.png)\n\n基于 Milvus 的检索框架在召回率 90% 的前提下，检索耗时约 2.9 毫秒，加上特征提取(Embedding)耗时约 500 毫秒(测试音频时长约 5 秒)，即单条音频测试总共耗时约 503 毫秒，可以满足大多数应用场景。\n\n### 6. 预训练模型\n\n以下是 PaddleSpeech 提供的预训练模型列表：\n\n| 模型 | 采样率\n| :--- | :---: \n| ecapa_tdnn| 16000\n"
  },
  {
    "path": "demos/audio_searching/docker-compose.yaml",
    "content": "version: '3.5'\n\nservices:\n  etcd:\n    container_name: milvus-etcd\n    image: quay.io/coreos/etcd:v3.5.0\n    networks:\n      app_net:\n    environment:\n      - ETCD_AUTO_COMPACTION_MODE=revision\n      - ETCD_AUTO_COMPACTION_RETENTION=1000\n      - ETCD_QUOTA_BACKEND_BYTES=4294967296\n    volumes:\n      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd\n    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd\n\n  minio:\n    container_name: milvus-minio\n    image: minio/minio:RELEASE.2020-12-03T00-03-10Z\n    networks:\n      app_net:\n    environment:\n      MINIO_ACCESS_KEY: minioadmin\n      MINIO_SECRET_KEY: minioadmin\n    volumes:\n      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data\n    command: minio server /minio_data\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:9000/minio/health/live\"]\n      interval: 30s\n      timeout: 20s\n      retries: 3\n\n  standalone:\n    container_name: milvus-standalone\n    image: milvusdb/milvus:v2.0.1\n    networks:\n      app_net:\n        ipv4_address: 172.16.23.10\n    command: [\"milvus\", \"run\", \"standalone\"]\n    environment:\n      ETCD_ENDPOINTS: etcd:2379\n      MINIO_ADDRESS: minio:9000\n    volumes:\n      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus\n    ports:\n      - \"19530:19530\"\n    depends_on:\n      - \"etcd\"\n      - \"minio\"\n  \n  mysql:\n    container_name: audio-mysql\n    image: mysql:5.7\n    networks:\n      app_net:\n        ipv4_address: 172.16.23.11\n    environment:\n      - MYSQL_ROOT_PASSWORD=123456\n    volumes:\n      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/mysql:/var/lib/mysql\n    ports:\n      - \"3306:3306\"\n\n  webclient:\n    container_name: audio-webclient\n    image: paddlepaddle/paddlespeech-audio-search-client:2.3\n    networks:\n      app_net:\n        ipv4_address: 172.16.23.13\n    environment:\n      API_URL: 'http://127.0.0.1:8002'\n    ports:\n      - \"8068:80\"\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost/\"]\n      interval: 30s\n      timeout: 20s\n      retries: 3\n\nnetworks:\n  app_net:\n    driver: bridge\n    ipam:\n      driver: default\n      config:\n        - subnet: 172.16.23.0/24\n          gateway: 172.16.23.1\n"
  },
  {
    "path": "demos/audio_searching/requirements.txt",
    "content": "diskcache\nfastapi\nlibrosa==0.8.0\nnumpy==1.22.0\npydantic\npymilvus==2.0.1\npymysql\npython-multipart\nsoundfile==0.10.3.post1\nstarlette\ntyping\nuvicorn\n"
  },
  {
    "path": "demos/audio_searching/src/audio_search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import Optional\n\nimport uvicorn\nfrom config import UPLOAD_PATH\nfrom diskcache import Cache\nfrom fastapi import FastAPI\nfrom fastapi import File\nfrom fastapi import UploadFile\nfrom logs import LOGGER\nfrom milvus_helpers import MilvusHelper\nfrom mysql_helpers import MySQLHelper\nfrom operations.count import do_count\nfrom operations.drop import do_drop\nfrom operations.load import do_load\nfrom operations.search import do_search\nfrom pydantic import BaseModel\nfrom starlette.middleware.cors import CORSMiddleware\nfrom starlette.requests import Request\nfrom starlette.responses import FileResponse\n\napp = FastAPI()\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"])\n\nMILVUS_CLI = MilvusHelper()\nMYSQL_CLI = MySQLHelper()\n\n# Mkdir 'tmp/audio-data'\nif not os.path.exists(UPLOAD_PATH):\n    os.makedirs(UPLOAD_PATH)\n    LOGGER.info(f\"Mkdir the path: {UPLOAD_PATH}\")\n\n\n@app.get('/data')\ndef audio_path(audio_path):\n    # Get the audio file\n    try:\n        LOGGER.info(f\"Successfully load audio: {audio_path}\")\n        return FileResponse(audio_path)\n    except Exception as e:\n        LOGGER.error(f\"upload audio error: {e}\")\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/progress')\ndef get_progress():\n    # Get the progress of dealing with data\n    try:\n        cache = Cache('./tmp')\n        return f\"current: {cache['current']}, total: {cache['total']}\"\n    except Exception as e:\n        LOGGER.error(f\"Upload data error: {e}\")\n        return {'status': False, 'msg': e}, 400\n\n\nclass Item(BaseModel):\n    Table: Optional[str] = None\n    File: str\n\n\n@app.post('/audio/load')\nasync def load_audios(item: Item):\n    # Insert all the audio files under the file path to Milvus/MySQL\n    try:\n        total_num = do_load(item.Table, item.File, MILVUS_CLI, MYSQL_CLI)\n        LOGGER.info(f\"Successfully loaded data, total count: {total_num}\")\n        return {'status': True, 'msg': \"Successfully loaded data!\"}\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/audio/search')\nasync def search_audio(request: Request,\n                       table_name: str=None,\n                       audio: UploadFile=File(...)):\n    # Search the uploaded audio in Milvus/MySQL\n    try:\n        # Save the upload data to server.\n        content = await audio.read()\n        query_audio_path = os.path.join(UPLOAD_PATH, audio.filename)\n        with open(query_audio_path, \"wb+\") as f:\n            f.write(content)\n        host = request.headers['host']\n        _, paths, distances = do_search(host, table_name, query_audio_path,\n                                        MILVUS_CLI, MYSQL_CLI)\n        names = []\n        for path, score in zip(paths, distances):\n            names.append(os.path.basename(path))\n            LOGGER.info(f\"search result {path}, score {score}\")\n        res = dict(zip(paths, zip(names, distances)))\n        # Sort results by distance metric, closest distances first\n        res = sorted(res.items(), key=lambda item: item[1][1], reverse=True)\n        LOGGER.info(\"Successfully searched similar audio!\")\n        return res\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/audio/search/local')\nasync def search_local_audio(request: Request,\n                             query_audio_path: str,\n                             table_name: str=None):\n    # Search the uploaded audio in Milvus/MySQL\n    try:\n        host = request.headers['host']\n        _, paths, distances = do_search(host, table_name, query_audio_path,\n                                        MILVUS_CLI, MYSQL_CLI)\n        names = []\n        for path, score in zip(paths, distances):\n            names.append(os.path.basename(path))\n            LOGGER.info(f\"search result {path}, score {score}\")\n        res = dict(zip(paths, zip(names, distances)))\n        # Sort results by distance metric, closest distances first\n        res = sorted(res.items(), key=lambda item: item[1][1], reverse=True)\n        LOGGER.info(\"Successfully searched similar audio!\")\n        return res\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/audio/count')\nasync def count_audio(table_name: str=None):\n    # Returns the total number of vectors in the system\n    try:\n        num = do_count(table_name, MILVUS_CLI)\n        LOGGER.info(\"Successfully count the number of data!\")\n        return num\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/audio/drop')\nasync def drop_tables(table_name: str=None):\n    # Delete the collection of Milvus and MySQL\n    try:\n        status = do_drop(table_name, MILVUS_CLI, MYSQL_CLI)\n        LOGGER.info(\"Successfully drop tables in Milvus and MySQL!\")\n        return status\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\nif __name__ == '__main__':\n    uvicorn.run(app=app, host='0.0.0.0', port=8002)\n"
  },
  {
    "path": "demos/audio_searching/src/config.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\n############### Milvus Configuration ###############\nMILVUS_HOST = os.getenv(\"MILVUS_HOST\", \"127.0.0.1\")\nMILVUS_PORT = int(os.getenv(\"MILVUS_PORT\", \"19530\"))\nVECTOR_DIMENSION = int(os.getenv(\"VECTOR_DIMENSION\", \"192\"))\nINDEX_FILE_SIZE = int(os.getenv(\"INDEX_FILE_SIZE\", \"1024\"))\nMETRIC_TYPE = os.getenv(\"METRIC_TYPE\", \"L2\")\nDEFAULT_TABLE = os.getenv(\"DEFAULT_TABLE\", \"audio_table\")\nTOP_K = int(os.getenv(\"TOP_K\", \"10\"))\n\n############### MySQL Configuration ###############\nMYSQL_HOST = os.getenv(\"MYSQL_HOST\", \"127.0.0.1\")\nMYSQL_PORT = int(os.getenv(\"MYSQL_PORT\", \"3306\"))\nMYSQL_USER = os.getenv(\"MYSQL_USER\", \"root\")\nMYSQL_PWD = os.getenv(\"MYSQL_PWD\", \"123456\")\nMYSQL_DB = os.getenv(\"MYSQL_DB\", \"mysql\")\n\n############### Data Path ###############\nUPLOAD_PATH = os.getenv(\"UPLOAD_PATH\", \"tmp/audio-data\")\n\n############### Number of Log Files ###############\nLOGS_NUM = int(os.getenv(\"logs_num\", \"0\"))\n"
  },
  {
    "path": "demos/audio_searching/src/encode.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom logs import LOGGER\n\nfrom paddlespeech.cli.vector import VectorExecutor\n\nvector_executor = VectorExecutor()\n\n\ndef get_audio_embedding(path):\n    \"\"\"\n    Use vpr_inference to generate embedding of audio\n    \"\"\"\n    try:\n        embedding = vector_executor(\n            audio_file=path, model='ecapatdnn_voxceleb12')\n        embedding = embedding / np.linalg.norm(embedding)\n        embedding = embedding.tolist()\n        return embedding\n    except Exception as e:\n        LOGGER.error(f\"Error with embedding:{e}\")\n        return None\n"
  },
  {
    "path": "demos/audio_searching/src/logs.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport datetime\nimport logging\nimport os\nimport re\nimport sys\n\nfrom config import LOGS_NUM\n\n\nclass MultiprocessHandler(logging.FileHandler):\n    \"\"\"\n    A handler class which writes formatted logging records to disk files\n    \"\"\"\n\n    def __init__(self,\n                 filename,\n                 when='D',\n                 backupCount=0,\n                 encoding=None,\n                 delay=False):\n        \"\"\"\n        Open the specified file and use it as the stream for logging\n        \"\"\"\n        self.prefix = filename\n        self.backupCount = backupCount\n        self.when = when.upper()\n        self.extMath = r\"^\\d{4}-\\d{2}-\\d{2}\"\n\n        self.when_dict = {\n            'S': \"%Y-%m-%d-%H-%M-%S\",\n            'M': \"%Y-%m-%d-%H-%M\",\n            'H': \"%Y-%m-%d-%H\",\n            'D': \"%Y-%m-%d\"\n        }\n\n        self.suffix = self.when_dict.get(when)\n        if not self.suffix:\n            print('The specified date interval unit is invalid: ', self.when)\n            sys.exit(1)\n\n        self.filefmt = os.path.join('.', \"logs\",\n                                    f\"{self.prefix}-{self.suffix}.log\")\n\n        self.filePath = datetime.datetime.now().strftime(self.filefmt)\n\n        _dir = os.path.dirname(self.filefmt)\n        try:\n            if not os.path.exists(_dir):\n                os.makedirs(_dir)\n        except Exception as e:\n            print('Failed to create log file: ', e)\n            print(\"log_path：\" + self.filePath)\n            sys.exit(1)\n\n        logging.FileHandler.__init__(self, self.filePath, 'a+', encoding, delay)\n\n    def should_change_file_to_write(self):\n        \"\"\"\n        To write the file\n        \"\"\"\n        _filePath = datetime.datetime.now().strftime(self.filefmt)\n        if _filePath != self.filePath:\n            self.filePath = _filePath\n            return True\n        return False\n\n    def do_change_file(self):\n        \"\"\"\n        To change file states\n        \"\"\"\n        self.baseFilename = os.path.abspath(self.filePath)\n        if self.stream:\n            self.stream.close()\n            self.stream = None\n\n        if not self.delay:\n            self.stream = self._open()\n        if self.backupCount > 0:\n            for s in self.get_files_to_delete():\n                os.remove(s)\n\n    def get_files_to_delete(self):\n        \"\"\"\n        To delete backup files\n        \"\"\"\n        dir_name, _ = os.path.split(self.baseFilename)\n        file_names = os.listdir(dir_name)\n        result = []\n        prefix = self.prefix + '-'\n        for file_name in file_names:\n            if file_name[:len(prefix)] == prefix:\n                suffix = file_name[len(prefix):-4]\n                if re.compile(self.extMath).match(suffix):\n                    result.append(os.path.join(dir_name, file_name))\n        result.sort()\n\n        if len(result) < self.backupCount:\n            result = []\n        else:\n            result = result[:len(result) - self.backupCount]\n        return result\n\n    def emit(self, record):\n        \"\"\"\n        Emit a record\n        \"\"\"\n        try:\n            if self.should_change_file_to_write():\n                self.do_change_file()\n            logging.FileHandler.emit(self, record)\n        except (KeyboardInterrupt, SystemExit):\n            raise\n        except Exception as e:\n            self.handleError(record)\n\n\ndef write_log():\n    \"\"\"\n    Init a logger\n    \"\"\"\n    logger = logging.getLogger()\n    logger.setLevel(logging.DEBUG)\n    # formatter = '%(asctime)s ｜ %(levelname)s ｜ %(filename)s ｜ %(funcName)s ｜ %(module)s ｜ %(lineno)s ｜ %(message)s'\n    fmt = logging.Formatter(\n        '%(asctime)s ｜ %(levelname)s ｜ %(filename)s ｜ %(funcName)s ｜ %(lineno)s ｜ %(message)s'\n    )\n\n    stream_handler = logging.StreamHandler(sys.stdout)\n    stream_handler.setLevel(logging.INFO)\n    stream_handler.setFormatter(fmt)\n\n    log_name = \"audio-searching\"\n    file_handler = MultiprocessHandler(log_name, when='D', backupCount=LOGS_NUM)\n    file_handler.setLevel(logging.DEBUG)\n    file_handler.setFormatter(fmt)\n    file_handler.do_change_file()\n\n    logger.addHandler(stream_handler)\n    logger.addHandler(file_handler)\n\n    return logger\n\n\nLOGGER = write_log()\n\nif __name__ == \"__main__\":\n    message = 'test writing logs'\n    LOGGER.info(message)\n    LOGGER.debug(message)\n    LOGGER.error(message)\n"
  },
  {
    "path": "demos/audio_searching/src/milvus_helpers.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nfrom config import METRIC_TYPE\nfrom config import MILVUS_HOST\nfrom config import MILVUS_PORT\nfrom config import VECTOR_DIMENSION\nfrom logs import LOGGER\nfrom pymilvus import Collection\nfrom pymilvus import CollectionSchema\nfrom pymilvus import connections\nfrom pymilvus import DataType\nfrom pymilvus import FieldSchema\nfrom pymilvus import utility\n\n\nclass MilvusHelper:\n    \"\"\"\n    the basic operations of PyMilvus\n\n    # This example shows how to:\n    #   1. connect to Milvus server\n    #   2. create a collection\n    #   3. insert entities\n    #   4. create index\n    #   5. search\n    #   6. delete a collection\n\n    \"\"\"\n\n    def __init__(self):\n        try:\n            self.collection = None\n            connections.connect(host=MILVUS_HOST, port=MILVUS_PORT)\n            LOGGER.debug(\n                f\"Successfully connect to Milvus with IP:{MILVUS_HOST} and PORT:{MILVUS_PORT}\"\n            )\n        except Exception as e:\n            LOGGER.error(f\"Failed to connect Milvus: {e}\")\n            sys.exit(1)\n\n    def set_collection(self, collection_name):\n        try:\n            if self.has_collection(collection_name):\n                self.collection = Collection(name=collection_name)\n            else:\n                raise Exception(\n                    f\"There is no collection named:{collection_name}\")\n        except Exception as e:\n            LOGGER.error(f\"Failed to set collection in Milvus: {e}\")\n            sys.exit(1)\n\n    def has_collection(self, collection_name):\n        # Return if Milvus has the collection\n        try:\n            return utility.has_collection(collection_name)\n        except Exception as e:\n            LOGGER.error(f\"Failed to check state of collection in Milvus: {e}\")\n            sys.exit(1)\n\n    def create_collection(self, collection_name):\n        # Create milvus collection if not exists\n        try:\n            if not self.has_collection(collection_name):\n                field1 = FieldSchema(\n                    name=\"id\",\n                    dtype=DataType.INT64,\n                    description=\"int64\",\n                    is_primary=True,\n                    auto_id=True)\n                field2 = FieldSchema(\n                    name=\"embedding\",\n                    dtype=DataType.FLOAT_VECTOR,\n                    description=\"speaker embeddings\",\n                    dim=VECTOR_DIMENSION,\n                    is_primary=False)\n                schema = CollectionSchema(\n                    fields=[field1, field2], description=\"embeddings info\")\n                self.collection = Collection(\n                    name=collection_name, schema=schema)\n                LOGGER.debug(f\"Create Milvus collection: {collection_name}\")\n            else:\n                self.set_collection(collection_name)\n            return \"OK\"\n        except Exception as e:\n            LOGGER.error(f\"Failed to create collection in Milvus: {e}\")\n            sys.exit(1)\n\n    def insert(self, collection_name, vectors):\n        # Batch insert vectors to milvus collection\n        try:\n            self.create_collection(collection_name)\n            data = [vectors]\n            self.set_collection(collection_name)\n            mr = self.collection.insert(data)\n            ids = mr.primary_keys\n            self.collection.load()\n            LOGGER.debug(\n                f\"Insert vectors to Milvus in collection: {collection_name} with {len(vectors)} rows\"\n            )\n            return ids\n        except Exception as e:\n            LOGGER.error(f\"Failed to insert data to Milvus: {e}\")\n            sys.exit(1)\n\n    def create_index(self, collection_name):\n        # Create IVF_FLAT index on milvus collection\n        try:\n            self.set_collection(collection_name)\n            default_index = {\n                \"index_type\": \"IVF_SQ8\",\n                \"metric_type\": METRIC_TYPE,\n                \"params\": {\n                    \"nlist\": 16384\n                }\n            }\n            status = self.collection.create_index(\n                field_name=\"embedding\", index_params=default_index)\n            if not status.code:\n                LOGGER.debug(\n                    f\"Successfully create index in collection:{collection_name} with param:{default_index}\"\n                )\n                return status\n            else:\n                raise Exception(status.message)\n        except Exception as e:\n            LOGGER.error(f\"Failed to create index: {e}\")\n            sys.exit(1)\n\n    def delete_collection(self, collection_name):\n        # Delete Milvus collection\n        try:\n            self.set_collection(collection_name)\n            self.collection.drop()\n            LOGGER.debug(\"Successfully drop collection!\")\n            return \"ok\"\n        except Exception as e:\n            LOGGER.error(f\"Failed to drop collection: {e}\")\n            sys.exit(1)\n\n    def search_vectors(self, collection_name, vectors, top_k):\n        # Search vector in milvus collection\n        try:\n            self.set_collection(collection_name)\n            search_params = {\n                \"metric_type\": METRIC_TYPE,\n                \"params\": {\n                    \"nprobe\": 16\n                }\n            }\n            res = self.collection.search(\n                vectors,\n                anns_field=\"embedding\",\n                param=search_params,\n                limit=top_k)\n            LOGGER.debug(f\"Successfully search in collection: {res}\")\n            return res\n        except Exception as e:\n            LOGGER.error(f\"Failed to search vectors in Milvus: {e}\")\n            sys.exit(1)\n\n    def count(self, collection_name):\n        # Get the number of milvus collection\n        try:\n            self.set_collection(collection_name)\n            num = self.collection.num_entities\n            LOGGER.debug(\n                f\"Successfully get the num:{num} of the collection:{collection_name}\"\n            )\n            return num\n        except Exception as e:\n            LOGGER.error(f\"Failed to count vectors in Milvus: {e}\")\n            sys.exit(1)\n"
  },
  {
    "path": "demos/audio_searching/src/mysql_helpers.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nimport numpy\nimport pymysql\nfrom config import MYSQL_DB\nfrom config import MYSQL_HOST\nfrom config import MYSQL_PORT\nfrom config import MYSQL_PWD\nfrom config import MYSQL_USER\nfrom logs import LOGGER\n\n\nclass MySQLHelper():\n    \"\"\"\n    the basic operations of PyMySQL\n\n    # This example shows how to:\n    #   1. connect to MySQL server\n    #   2. create a table\n    #   3. insert data to table\n    #   4. search by milvus ids\n    #   5. delete table\n    \"\"\"\n\n    def __init__(self):\n        self.conn = pymysql.connect(\n            host=MYSQL_HOST,\n            user=MYSQL_USER,\n            port=MYSQL_PORT,\n            password=MYSQL_PWD,\n            database=MYSQL_DB,\n            local_infile=True)\n        self.cursor = self.conn.cursor()\n\n    def test_connection(self):\n        try:\n            self.conn.ping()\n        except Exception:\n            self.conn = pymysql.connect(\n                host=MYSQL_HOST,\n                user=MYSQL_USER,\n                port=MYSQL_PORT,\n                password=MYSQL_PWD,\n                database=MYSQL_DB,\n                local_infile=True)\n            self.cursor = self.conn.cursor()\n\n    def create_mysql_table(self, table_name):\n        # Create mysql table if not exists\n        self.test_connection()\n        sql = \"create table if not exists \" + table_name + \"(milvus_id TEXT, audio_path TEXT);\"\n        try:\n            self.cursor.execute(sql)\n            LOGGER.debug(f\"MYSQL create table: {table_name} with sql: {sql}\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def load_data_to_mysql(self, table_name, data):\n        # Batch insert (Milvus_ids, audio_path) to mysql\n        self.test_connection()\n        sql = \"insert into \" + table_name + \" (milvus_id,audio_path) values (%s,%s);\"\n        try:\n            self.cursor.executemany(sql, data)\n            self.conn.commit()\n            LOGGER.debug(\n                f\"MYSQL loads data to table: {table_name} successfully\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def search_by_milvus_ids(self, ids, table_name):\n        # Get the audio_path according to the milvus ids\n        self.test_connection()\n        str_ids = str(ids).replace('[', '').replace(']', '')\n        sql = \"select audio_path from \" + table_name + \" where milvus_id in (\" + str_ids + \") order by field (milvus_id,\" + str_ids + \");\"\n        try:\n            self.cursor.execute(sql)\n            results = self.cursor.fetchall()\n            results = [res[0] for res in results]\n            LOGGER.debug(\"MYSQL search by milvus id.\")\n            return results\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def delete_table(self, table_name):\n        # Delete mysql table if exists\n        self.test_connection()\n        sql = \"drop table if exists \" + table_name + \";\"\n        try:\n            self.cursor.execute(sql)\n            LOGGER.debug(f\"MYSQL delete table:{table_name}\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def delete_all_data(self, table_name):\n        # Delete all the data in mysql table\n        self.test_connection()\n        sql = 'delete from ' + table_name + ';'\n        try:\n            self.cursor.execute(sql)\n            self.conn.commit()\n            LOGGER.debug(f\"MYSQL delete all data in table:{table_name}\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def count_table(self, table_name):\n        # Get the number of spk in mysql table\n        self.test_connection()\n        sql = \"select count(spk_id) from \" + table_name + \";\"\n        try:\n            self.cursor.execute(sql)\n            results = self.cursor.fetchall()\n            LOGGER.debug(f\"MYSQL count table:{results[0][0]}\")\n            return results[0][0]\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def create_mysql_table_vpr(self, table_name):\n        # Create mysql table if not exists\n        self.test_connection()\n        sql = \"create table if not exists \" + table_name + \"(spk_id TEXT, audio_path TEXT, embedding TEXT);\"\n        try:\n            self.cursor.execute(sql)\n            LOGGER.debug(f\"MYSQL create table: {table_name} with sql: {sql}\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def load_data_to_mysql_vpr(self, table_name, data):\n        # Insert (spk, audio, embedding) to mysql\n        self.test_connection()\n        sql = \"insert into \" + table_name + \" (spk_id,audio_path,embedding) values (%s,%s,%s);\"\n        try:\n            self.cursor.execute(sql, data)\n            LOGGER.debug(\n                f\"MYSQL loads data to table: {table_name} successfully\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def list_vpr(self, table_name):\n        # Get all records in mysql\n        self.test_connection()\n        sql = \"select * from \" + table_name + \" ;\"\n        try:\n            self.cursor.execute(sql)\n            results = self.cursor.fetchall()\n            self.conn.commit()\n            spk_ids = [res[0] for res in results]\n            audio_paths = [res[1] for res in results]\n            embeddings = [\n                numpy.array(\n                    str(res[2]).replace('[', '').replace(']', '').split(\",\"))\n                for res in results\n            ]\n            return spk_ids, audio_paths, embeddings\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def search_audio_vpr(self, table_name, spk_id):\n        # Get the audio_path according to the spk_id\n        self.test_connection()\n        sql = \"select audio_path from \" + table_name + \" where spk_id='\" + spk_id + \"' ;\"\n        try:\n            self.cursor.execute(sql)\n            results = self.cursor.fetchall()\n            LOGGER.debug(\n                f\"MYSQL search by spk id {spk_id} to get audio {results[0][0]}.\")\n            return results[0][0]\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n\n    def delete_data_vpr(self, table_name, spk_id):\n        # Delete a record by spk_id in mysql table\n        self.test_connection()\n        sql = \"delete from \" + table_name + \" where spk_id='\" + spk_id + \"';\"\n        try:\n            self.cursor.execute(sql)\n            LOGGER.debug(\n                f\"MYSQL delete a record {spk_id} in table {table_name}\")\n        except Exception as e:\n            LOGGER.error(f\"MYSQL ERROR: {e} with sql: {sql}\")\n            sys.exit(1)\n"
  },
  {
    "path": "demos/audio_searching/src/operations/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "demos/audio_searching/src/operations/count.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nfrom config import DEFAULT_TABLE\nfrom logs import LOGGER\n\n\ndef do_count(table_name, milvus_cli):\n    \"\"\"\n    Returns the total number of vectors in the system\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        if not milvus_cli.has_collection(table_name):\n            return None\n        num = milvus_cli.count(table_name)\n        return num\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to count table {e}\")\n        sys.exit(1)\n\n\ndef do_count_vpr(table_name, mysql_cli):\n    \"\"\"\n    Returns the total number of spk in the system\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        num = mysql_cli.count_table(table_name)\n        return num\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to count table {e}\")\n        sys.exit(1)\n\n\ndef do_list(table_name, mysql_cli):\n    \"\"\"\n    Returns the total records of vpr in the system\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        spk_ids, audio_paths, _ = mysql_cli.list_vpr(table_name)\n        return spk_ids, audio_paths\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to count table {e}\")\n        sys.exit(1)\n\n\ndef do_get(table_name, spk_id, mysql_cli):\n    \"\"\"\n    Returns the audio path by spk_id in the system\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        audio_apth = mysql_cli.search_audio_vpr(table_name, spk_id)\n        return audio_apth\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to count table {e}\")\n        sys.exit(1)\n"
  },
  {
    "path": "demos/audio_searching/src/operations/drop.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nfrom config import DEFAULT_TABLE\nfrom logs import LOGGER\n\n\ndef do_drop(table_name, milvus_cli, mysql_cli):\n    \"\"\"\n    Delete the collection of Milvus and MySQL\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        if not milvus_cli.has_collection(table_name):\n            return \"Collection is not exist\"\n        status = milvus_cli.delete_collection(table_name)\n        mysql_cli.delete_table(table_name)\n        return status\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to drop table: {e}\")\n        sys.exit(1)\n\n\ndef do_drop_vpr(table_name, mysql_cli):\n    \"\"\"\n    Delete the table of MySQL\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        mysql_cli.delete_table(table_name)\n        return \"OK\"\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to drop table: {e}\")\n        sys.exit(1)\n\n\ndef do_delete(table_name, spk_id, mysql_cli):\n    \"\"\"\n    Delete a record by spk_id in MySQL\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    try:\n        mysql_cli.delete_data_vpr(table_name, spk_id)\n        return \"OK\"\n    except Exception as e:\n        LOGGER.error(f\"Error attempting to drop table: {e}\")\n        sys.exit(1)\n"
  },
  {
    "path": "demos/audio_searching/src/operations/load.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\n\nfrom config import DEFAULT_TABLE\nfrom diskcache import Cache\nfrom encode import get_audio_embedding\nfrom logs import LOGGER\n\n\ndef get_audios(path):\n    \"\"\"\n    List all wav and aif files recursively under the path folder.\n    \"\"\"\n    supported_formats = [\".wav\", \".mp3\", \".ogg\", \".flac\", \".m4a\"]\n    return [\n        item\n        for sublist in [[os.path.join(dir, file) for file in files]\n                        for dir, _, files in list(os.walk(path))]\n        for item in sublist if os.path.splitext(item)[1] in supported_formats\n    ]\n\n\ndef extract_features(audio_dir):\n    \"\"\"\n    Get the vector of audio\n    \"\"\"\n    try:\n        cache = Cache('./tmp')\n        feats = []\n        names = []\n        audio_list = get_audios(audio_dir)\n        total = len(audio_list)\n        cache['total'] = total\n        for i, audio_path in enumerate(audio_list):\n            norm_feat = get_audio_embedding(audio_path)\n            if norm_feat is None:\n                continue\n            feats.append(norm_feat)\n            names.append(audio_path.encode())\n            cache['current'] = i + 1\n            print(\n                f\"Extracting feature from audio No. {i + 1} , {total} audios in total\"\n            )\n        return feats, names\n    except Exception as e:\n        LOGGER.error(f\"Error with extracting feature from audio {e}\")\n        sys.exit(1)\n\n\ndef format_data(ids, names):\n    \"\"\"\n    Combine the id of the vector and the name of the audio into a list\n    \"\"\"\n    data = []\n    for i in range(len(ids)):\n        value = (str(ids[i]), names[i])\n        data.append(value)\n    return data\n\n\ndef do_load(table_name, audio_dir, milvus_cli, mysql_cli):\n    \"\"\"\n    Import vectors to Milvus and data to Mysql respectively\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    vectors, names = extract_features(audio_dir)\n    ids = milvus_cli.insert(table_name, vectors)\n    milvus_cli.create_index(table_name)\n    mysql_cli.create_mysql_table(table_name)\n    mysql_cli.load_data_to_mysql(table_name, format_data(ids, names))\n    return len(ids)\n\n\ndef do_enroll(table_name, spk_id, audio_path, mysql_cli):\n    \"\"\"\n    Import spk_id,audio_path,embedding to Mysql\n    \"\"\"\n    if not table_name:\n        table_name = DEFAULT_TABLE\n    embedding = get_audio_embedding(audio_path)\n    mysql_cli.create_mysql_table_vpr(table_name)\n    data = (spk_id, audio_path, str(embedding))\n    mysql_cli.load_data_to_mysql_vpr(table_name, data)\n    return \"OK\"\n"
  },
  {
    "path": "demos/audio_searching/src/operations/search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nimport numpy\nfrom config import DEFAULT_TABLE\nfrom config import TOP_K\nfrom encode import get_audio_embedding\nfrom logs import LOGGER\n\n\ndef do_search(host, table_name, audio_path, milvus_cli, mysql_cli):\n    \"\"\"\n    Search the uploaded audio in Milvus/MySQL\n    \"\"\"\n    try:\n        if not table_name:\n            table_name = DEFAULT_TABLE\n        feat = get_audio_embedding(audio_path)\n        vectors = milvus_cli.search_vectors(table_name, [feat], TOP_K)\n        vids = [str(x.id) for x in vectors[0]]\n        paths = mysql_cli.search_by_milvus_ids(vids, table_name)\n        distances = [x.distance for x in vectors[0]]\n        for i in range(len(paths)):\n            tmp = \"http://\" + str(host) + \"/data?audio_path=\" + str(paths[i])\n            paths[i] = tmp\n            distances[i] = (1 - distances[i]) * 100\n        return vids, paths, distances\n    except Exception as e:\n        LOGGER.error(f\"Error with search: {e}\")\n        sys.exit(1)\n\n\ndef do_search_vpr(host, table_name, audio_path, mysql_cli):\n    \"\"\"\n    Search the uploaded audio in MySQL\n    \"\"\"\n    try:\n        if not table_name:\n            table_name = DEFAULT_TABLE\n        emb = get_audio_embedding(audio_path)\n        emb = numpy.array(emb)\n        spk_ids, paths, vectors = mysql_cli.list_vpr(table_name)\n        scores = [numpy.dot(emb, x.astype(numpy.float64)) for x in vectors]\n        spk_ids = [str(x) for x in spk_ids]\n        paths = [str(x) for x in paths]\n        for i in range(len(paths)):\n            tmp = \"http://\" + str(host) + \"/data?audio_path=\" + str(paths[i])\n            paths[i] = tmp\n            scores[i] = scores[i] * 100\n        return spk_ids, paths, scores\n    except Exception as e:\n        LOGGER.error(f\"Error with search: {e}\")\n        sys.exit(1)\n"
  },
  {
    "path": "demos/audio_searching/src/test_audio_search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom audio_search import app\nfrom fastapi.testclient import TestClient\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\n\nclient = TestClient(app)\n\n\ndef download_audio_data():\n    \"\"\"\n    Download audio data\n    \"\"\"\n    url = \"https://paddlespeech.cdn.bcebos.com/vector/audio/example_audio.tar.gz\"\n    md5sum = \"52ac69316c1aa1fdef84da7dd2c67b39\"\n    target_dir = \"./\"\n    filepath = download(url, md5sum, target_dir)\n    unpack(filepath, target_dir, True)\n\n\ndef test_drop():\n    \"\"\"\n    Delete the collection of Milvus and MySQL\n    \"\"\"\n    response = client.post(\"/audio/drop\")\n    assert response.status_code == 200\n\n\ndef test_load():\n    \"\"\"\n    Insert all the audio files under the file path to Milvus/MySQL\n    \"\"\"\n    response = client.post(\"/audio/load\", json={\"File\": \"./example_audio\"})\n    assert response.status_code == 200\n    assert response.json() == {\n        'status': True,\n        'msg': \"Successfully loaded data!\"\n    }\n\n\ndef test_progress():\n    \"\"\"\n    Get the progress of dealing with data\n    \"\"\"\n    response = client.get(\"/progress\")\n    assert response.status_code == 200\n    assert response.json() == \"current: 20, total: 20\"\n\n\ndef test_count():\n    \"\"\"\n    Returns the total number of vectors in the system\n    \"\"\"\n    response = client.get(\"/audio/count\")\n    assert response.status_code == 200\n    assert response.json() == 20\n\n\ndef test_search():\n    \"\"\"\n    Search the uploaded audio in Milvus/MySQL\n    \"\"\"\n    response = client.post(\n        \"/audio/search/local?query_audio_path=.%2Fexample_audio%2Ftest.wav\")\n    assert response.status_code == 200\n    assert len(response.json()) == 10\n\n\ndef test_data():\n    \"\"\"\n    Get the audio file\n    \"\"\"\n    response = client.get(\"/data?audio_path=.%2Fexample_audio%2Ftest.wav\")\n    assert response.status_code == 200\n\n\nif __name__ == \"__main__\":\n    download_audio_data()\n    test_load()\n    test_count()\n    test_search()\n    test_drop()\n"
  },
  {
    "path": "demos/audio_searching/src/test_vpr_search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom fastapi.testclient import TestClient\nfrom vpr_search import app\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\n\nclient = TestClient(app)\n\n\ndef download_audio_data():\n    \"\"\"\n    Download audio data\n    \"\"\"\n    url = \"https://paddlespeech.cdn.bcebos.com/vector/audio/example_audio.tar.gz\"\n    md5sum = \"52ac69316c1aa1fdef84da7dd2c67b39\"\n    target_dir = \"./\"\n    filepath = download(url, md5sum, target_dir)\n    unpack(filepath, target_dir, True)\n\n\ndef test_drop():\n    \"\"\"\n    Delete the table of MySQL\n    \"\"\"\n    response = client.post(\"/vpr/drop\")\n    assert response.status_code == 200\n\n\ndef test_enroll_local(spk: str, audio: str):\n    \"\"\"\n    Enroll the audio to MySQL\n    \"\"\"\n    response = client.post(\"/vpr/enroll/local?spk_id=\" + spk +\n                           \"&audio_path=.%2Fexample_audio%2F\" + audio + \".wav\")\n    assert response.status_code == 200\n    assert response.json() == {\n        'status': True,\n        'msg': \"Successfully enroll data!\"\n    }\n\n\ndef test_search_local():\n    \"\"\"\n    Search the spk in MySQL by audio\n    \"\"\"\n    response = client.post(\n        \"/vpr/recog/local?audio_path=.%2Fexample_audio%2Ftest.wav\")\n    assert response.status_code == 200\n\n\ndef test_list():\n    \"\"\"\n    Get all records in MySQL\n    \"\"\"\n    response = client.get(\"/vpr/list\")\n    assert response.status_code == 200\n\n\ndef test_data(spk: str):\n    \"\"\"\n    Get the audio file by spk_id in MySQL\n    \"\"\"\n    response = client.get(\n        \"/vpr/data\",\n        json={\"spk_id\": spk}, )\n    assert response.status_code == 200\n\n\ndef test_del(spk: str):\n    \"\"\"\n    Delete the record in MySQL by spk_id\n    \"\"\"\n    response = client.post(\n        \"/vpr/del\",\n        json={\"spk_id\": spk}, )\n    assert response.status_code == 200\n\n\ndef test_count():\n    \"\"\"\n    Get the number of spk in MySQL\n    \"\"\"\n    response = client.get(\"/vpr/count\")\n    assert response.status_code == 200\n\n\nif __name__ == \"__main__\":\n    download_audio_data()\n\n    test_enroll_local(\"spk1\", \"arms_strikes\")\n    test_enroll_local(\"spk2\", \"sword_wielding\")\n    test_enroll_local(\"spk3\", \"test\")\n    test_list()\n    test_data(\"spk1\")\n    test_count()\n    test_search_local()\n\n    test_del(\"spk1\")\n    test_count()\n    test_search_local()\n\n    test_enroll_local(\"spk1\", \"arms_strikes\")\n    test_count()\n    test_search_local()\n\n    test_drop()\n"
  },
  {
    "path": "demos/audio_searching/src/vpr_search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport uvicorn\nfrom config import UPLOAD_PATH\nfrom fastapi import FastAPI\nfrom fastapi import File\nfrom fastapi import Form\nfrom fastapi import UploadFile\nfrom logs import LOGGER\nfrom mysql_helpers import MySQLHelper\nfrom operations.count import do_count_vpr\nfrom operations.count import do_get\nfrom operations.count import do_list\nfrom operations.drop import do_delete\nfrom operations.drop import do_drop_vpr\nfrom operations.load import do_enroll\nfrom operations.search import do_search_vpr\nfrom starlette.middleware.cors import CORSMiddleware\nfrom starlette.requests import Request\nfrom starlette.responses import FileResponse\n\napp = FastAPI()\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"])\n\nMYSQL_CLI = MySQLHelper()\n\n# Mkdir 'tmp/audio-data'\nif not os.path.exists(UPLOAD_PATH):\n    os.makedirs(UPLOAD_PATH)\n    LOGGER.info(f\"Mkdir the path: {UPLOAD_PATH}\")\n\n\n@app.post('/vpr/enroll')\nasync def vpr_enroll(table_name: str=None,\n                     spk_id: str=Form(...),\n                     audio: UploadFile=File(...)):\n    # Enroll the uploaded audio with spk-id into MySQL\n    try:\n        if not spk_id:\n            return {'status': False, 'msg': \"spk_id can not be None\"}\n        # Save the upload data to server.\n        content = await audio.read()\n        audio_path = os.path.join(UPLOAD_PATH, audio.filename)\n        with open(audio_path, \"wb+\") as f:\n            f.write(content)\n        do_enroll(table_name, spk_id, audio_path, MYSQL_CLI)\n        LOGGER.info(f\"Successfully enrolled {spk_id} online!\")\n        return {'status': True, 'msg': \"Successfully enroll data!\"}\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}\n\n\n@app.post('/vpr/enroll/local')\nasync def vpr_enroll_local(table_name: str=None,\n                           spk_id: str=None,\n                           audio_path: str=None):\n    # Enroll the local audio with spk-id into MySQL\n    try:\n        do_enroll(table_name, spk_id, audio_path, MYSQL_CLI)\n        LOGGER.info(f\"Successfully enrolled {spk_id} locally!\")\n        return {'status': True, 'msg': \"Successfully enroll data!\"}\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/vpr/recog')\nasync def vpr_recog(request: Request,\n                    table_name: str=None,\n                    audio: UploadFile=File(...)):\n    # Voice print recognition online\n    try:\n        # Save the upload data to server.\n        content = await audio.read()\n        query_audio_path = os.path.join(UPLOAD_PATH, audio.filename)\n        with open(query_audio_path, \"wb+\") as f:\n            f.write(content)\n        host = request.headers['host']\n        spk_ids, paths, scores = do_search_vpr(host, table_name,\n                                               query_audio_path, MYSQL_CLI)\n        for spk_id, path, score in zip(spk_ids, paths, scores):\n            LOGGER.info(f\"spk {spk_id}, score {score}, audio path {path}, \")\n        res = dict(zip(spk_ids, zip(paths, scores)))\n        # Sort results by distance metric, closest distances first\n        res = sorted(res.items(), key=lambda item: item[1][1], reverse=True)\n        LOGGER.info(\"Successfully speaker recognition online!\")\n        return res\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/vpr/recog/local')\nasync def vpr_recog_local(request: Request,\n                          table_name: str=None,\n                          audio_path: str=None):\n    # Voice print recognition locally\n    try:\n        host = request.headers['host']\n        spk_ids, paths, scores = do_search_vpr(host, table_name, audio_path,\n                                               MYSQL_CLI)\n        for spk_id, path, score in zip(spk_ids, paths, scores):\n            LOGGER.info(f\"spk {spk_id}, score {score}, audio path {path}, \")\n        res = dict(zip(spk_ids, zip(paths, scores)))\n        # Sort results by distance metric, closest distances first\n        res = sorted(res.items(), key=lambda item: item[1][1], reverse=True)\n        LOGGER.info(\"Successfully speaker recognition locally!\")\n        return res\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/vpr/del')\nasync def vpr_del(table_name: str=None, spk_id: dict=None):\n    # Delete a record by spk_id in MySQL\n    try:\n        spk_id = spk_id['spk_id']\n        if not spk_id:\n            return {'status': False, 'msg': \"spk_id can not be None\"}\n        do_delete(table_name, spk_id, MYSQL_CLI)\n        LOGGER.info(\"Successfully delete a record by spk_id in MySQL\")\n        return {'status': True, 'msg': \"Successfully delete data!\"}\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/list')\nasync def vpr_list(table_name: str=None):\n    # Get all records in MySQL\n    try:\n        spk_ids, audio_paths = do_list(table_name, MYSQL_CLI)\n        for i in range(len(spk_ids)):\n            LOGGER.debug(f\"spk {spk_ids[i]}, audio path {audio_paths[i]}\")\n        LOGGER.info(\"Successfully list all records from mysql!\")\n        return spk_ids, audio_paths\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/data')\nasync def vpr_data(\n    table_name: str=None,\n    spk_id: dict=None, ):\n    # Get the audio file from path by spk_id in MySQL\n    try:\n        spk_id = spk_id['spk_id']\n        if not spk_id:\n            return {'status': False, 'msg': \"spk_id can not be None\"}\n        audio_path = do_get(table_name, spk_id, MYSQL_CLI)\n        LOGGER.info(f\"Successfully get audio path {audio_path}!\")\n        return FileResponse(audio_path)\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/count')\nasync def vpr_count(table_name: str=None):\n    # Get the total number of spk in MySQL\n    try:\n        num = do_count_vpr(table_name, MYSQL_CLI)\n        LOGGER.info(\"Successfully count the number of spk!\")\n        return num\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.post('/vpr/drop')\nasync def drop_tables(table_name: str=None):\n    # Delete the table of MySQL\n    try:\n        do_drop_vpr(table_name, MYSQL_CLI)\n        LOGGER.info(\"Successfully drop tables in MySQL!\")\n        return {'status': True, 'msg': \"Successfully drop tables!\"}\n    except Exception as e:\n        LOGGER.error(e)\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/data')\ndef audio_path(audio_path):\n    # Get the audio file from path\n    try:\n        LOGGER.info(f\"Successfully get audio: {audio_path}\")\n        return FileResponse(audio_path)\n    except Exception as e:\n        LOGGER.error(f\"get audio error: {e}\")\n        return {'status': False, 'msg': e}, 400\n\n\nif __name__ == '__main__':\n    uvicorn.run(app=app, host='0.0.0.0', port=8002)\n"
  },
  {
    "path": "demos/audio_tagging/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Audio Tagging\n\n## Introduction\nAudio tagging is the task of labeling an audio clip with one or more labels or tags, including music tagging, acoustic scene classification, audio event classification, etc.\n\nThis demo is an implementation to tag an audio file with 527 [AudioSet](https://research.google.com/audioset/) labels. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`).\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/cat.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/dog.wav\n```\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  paddlespeech cls --input ./cat.wav --topk 10\n  ```\n  Usage:\n  ```bash\n  paddlespeech cls --help\n  ```\n  Arguments:\n  - `input`(required): The audio file to tag.\n  - `model`: Model type of tagging task. Default: `panns_cnn14`.\n  - `config`: Config of tagging task. Use a pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use a pretrained model when it is None. Default: `None`.\n  - `label_file`: Label file of tagging task. Use audio set labels when it is None. Default: `None`.\n  - `topk`: Show topk tagging labels of the result. Default: `1`.\n  - `device`: Choose the device to execute model inference. Default: default device of paddlepaddle in the current environment.\n\n  Output:\n  ```bash\n  [2021-12-08 14:49:40,671] [    INFO] [utils.py] [L225] - CLS Result:\n  Cat: 0.8991316556930542\n  Domestic animals, pets: 0.8806838393211365\n  Meow: 0.8784668445587158\n  Animal: 0.8776564598083496\n  Caterwaul: 0.2232048511505127\n  Speech: 0.03101264126598835\n  Music: 0.02870696596801281\n  Inside, small room: 0.016673989593982697\n  Purr: 0.008387474343180656\n  Bird: 0.006304860580712557\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.cls import CLSExecutor\n\n  cls_executor = CLSExecutor()\n  result = cls_executor(\n      model='panns_cnn14',\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      label_file=None,\n      ckpt_path=None,\n      audio_file='./cat.wav',\n      topk=10,\n      device=paddle.get_device())\n  print('CLS Result: \\n{}'.format(result))\n  ```\n  Output:\n  ```bash\n  CLS Result:\n  Cat: 0.8991316556930542\n  Domestic animals, pets: 0.8806838393211365\n  Meow: 0.8784668445587158\n  Animal: 0.8776564598083496\n  Caterwaul: 0.2232048511505127\n  Speech: 0.03101264126598835\n  Music: 0.02870696596801281\n  Inside, small room: 0.016673989593982697\n  Purr: 0.008387474343180656\n  Bird: 0.006304860580712557\n  ```\n\n### 4.Pretrained Models\n\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n| Model | Sample Rate\n| :--- | :---: \n| panns_cnn6| 32000\n| panns_cnn10| 32000\n| panns_cnn14| 32000\n"
  },
  {
    "path": "demos/audio_tagging/README_cn.md",
    "content": "\n(简体中文|[English](./README.md))\n\n# 声音分类\n## 介绍\n声音分类任务为音频片段添加一个或多个标签的任务，包括音乐分类、声学场景分类、音频事件分类等。\n\n这个 demo 使用 527 个 [AudioSet](https://research.google.com/audioset/) 数据集中的标签为音频进行分类，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 demo 的输入应该是一个 WAV 文件（`.wav`），\n\n可以下载此 demo 的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/cat.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/dog.wav\n```\n\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  paddlespeech cls --input ./cat.wav --topk 10\n  ```\n  使用方法：\n  ```bash\n  paddlespeech cls --help\n  ```\n  参数：\n  - `input`(必须输入)： 用于分类的音频。\n  - `model`： 声音分类任务的模型， 默认值： `panns_cnn14`.\n  - `config`： 声音分类任务的配置文件，若不设置则使用预训练模型中的默认配置，  默认值： `None`。\n  - `ckpt_path`：模型参数文件， 若不设置则下载预训练模型使用， 默认值： `None`。\n  - `label_file`：声音分类任务的标签文件，若不是设置则使用音频数据集标签，默认值： `None`。\n  - `topk`：展示分类结果的 topk 个结果，默认值： `1`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n\n  输出：\n  ```bash\n  [2021-12-08 14:49:40,671] [    INFO] [utils.py] [L225] - CLS Result:\n  Cat: 0.8991316556930542\n  Domestic animals, pets: 0.8806838393211365\n  Meow: 0.8784668445587158\n  Animal: 0.8776564598083496\n  Caterwaul: 0.2232048511505127\n  Speech: 0.03101264126598835\n  Music: 0.02870696596801281\n  Inside, small room: 0.016673989593982697\n  Purr: 0.008387474343180656\n  Bird: 0.006304860580712557\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.cls import CLSExecutor\n\n  cls_executor = CLSExecutor()\n  result = cls_executor(\n      model='panns_cnn14',\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      label_file=None,\n      ckpt_path=None,\n      audio_file='./cat.wav',\n      topk=10,\n      device=paddle.get_device())\n  print('CLS Result: \\n{}'.format(result))\n  ```\n  输出：\n  ```bash\n  CLS Result:\n  Cat: 0.8991316556930542\n  Domestic animals, pets: 0.8806838393211365\n  Meow: 0.8784668445587158\n  Animal: 0.8776564598083496\n  Caterwaul: 0.2232048511505127\n  Speech: 0.03101264126598835\n  Music: 0.02870696596801281\n  Inside, small room: 0.016673989593982697\n  Purr: 0.008387474343180656\n  Bird: 0.006304860580712557\n  ```\n\n### 4. 预训练模型\n\n以下是 PaddleSpeech 提供的可以被命令行和 python api 使用的预训练模型列表：\n\n| 模型 | 采样率\n| :--- | :---: \n| panns_cnn6| 32000\n| panns_cnn10| 32000\n| panns_cnn14| 32000\n"
  },
  {
    "path": "demos/audio_tagging/run.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/cat.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/dog.wav\npaddlespeech cls --input ./cat.wav --topk 10\n"
  },
  {
    "path": "demos/automatic_video_subtitiles/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# Automatic Video Subtitiles\n\n## Introduction\nAutomatic video subtitles can generate subtitles from a specific video by using the Automatic Speech Recognition (ASR) system. \n\nThis demo is an implementation to automatic video subtitles from a video file. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md). \n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input\nGet a video file with the speech of the specific language:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/demos/asr_demos/subtitle_demo1.mp4\n```\n\nExtract `.wav` with one channel and 16000 sample rate from the video:\n```bash\nffmpeg -i subtitle_demo1.mp4 -ac 1 -ar 16000 -vn input.wav\n```\n\n### 3. Usage\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.asr import ASRExecutor\n  from paddlespeech.cli.text import TextExecutor\n\n  asr_executor = ASRExecutor()\n  text_executor = TextExecutor()\n\n  text = asr_executor(\n      audio_file='input.wav',\n      device=paddle.get_device())\n  result = text_executor(\n      text=text,\n      task='punc',\n      model='ernie_linear_p3_wudao',\n      device=paddle.get_device())\n  print('Text Result: \\n{}'.format(result))\n  ```\n  Output:\n  ```bash\n  Text Result:\n  当我说我可以把三十年的经验变成一个准确的算法，他们说不可能。当我说我们十个人就能实现对十九个城市变电站七乘二十四小时的实时监管，他们说不可能。\n  ```\n"
  },
  {
    "path": "demos/automatic_video_subtitiles/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n# 视频字幕生成\n## 介绍\n视频字幕生成可以使用语音识别系统从特定视频生成字幕。\n\n这个 demo 是一个为视频自动生成字幕的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n获取包含特定语言语音的视频文件：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/demos/asr_demos/subtitle_demo1.mp4\n```\n从视频文件中提取单通道的 16kHz 采样率的 `.wav` 文件：\n```bash\nffmpeg -i subtitle_demo1.mp4 -ac 1 -ar 16000 -vn input.wav\n```\n### 3. 使用方法\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.asr import ASRExecutor\n  from paddlespeech.cli.text import TextExecutor\n\n  asr_executor = ASRExecutor()\n  text_executor = TextExecutor()\n\n  text = asr_executor(\n      audio_file='input.wav',\n      device=paddle.get_device())\n  result = text_executor(\n      text=text,\n      task='punc',\n      model='ernie_linear_p3_wudao',\n      device=paddle.get_device())\n  print('Text Result: \\n{}'.format(result))\n  ```\n  输出:\n  ```bash\n  Text Result:\n  当我说我可以把三十年的经验变成一个准确的算法，他们说不可能。当我说我们十个人就能实现对十九个城市变电站七乘二十四小时的实时监管，他们说不可能。\n  ```\n"
  },
  {
    "path": "demos/automatic_video_subtitiles/recognize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport paddle\n\nfrom paddlespeech.cli.asr import ASRExecutor\nfrom paddlespeech.cli.text import TextExecutor\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument(\"--input\", type=str, required=True)\nparser.add_argument(\"--device\", type=str, default=paddle.get_device())\nargs = parser.parse_args()\n# yapf: enable\n\nif __name__ == \"__main__\":\n    asr_executor = ASRExecutor()\n    text_executor = TextExecutor()\n\n    text = asr_executor(\n        audio_file=os.path.abspath(os.path.expanduser(args.input)),\n        device=args.device)\n    result = text_executor(\n        text=text,\n        task='punc',\n        model='ernie_linear_p3_wudao',\n        device=args.device)\n\n    print('ASR Result: \\n{}'.format(text))\n    print('Text Result: \\n{}'.format(result))\n"
  },
  {
    "path": "demos/automatic_video_subtitiles/run.sh",
    "content": "#!/bin/bash\n\nvideo_url=https://paddlespeech.cdn.bcebos.com/demos/asr_demos/subtitle_demo1.mp4\nvideo_file=$(basename ${video_url})\naudio_file=$(echo ${video_file} | awk -F'.' '{print $1}').wav\nnum_channels=1\nsr=16000\n\n# Download video\nif [ ! -f ${video_file} ]; then\n    wget -c ${video_url}\nfi\n\n# Extract audio from video\nif [ ! -f ${audio_file} ]; then\n    ffmpeg -i ${video_file} -ac ${num_channels} -ar ${sr} -vn ${audio_file}\nfi\n\npython -u recognize.py --input ${audio_file}\nexit 0\n"
  },
  {
    "path": "demos/custom_streaming_asr/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Customized Auto Speech Recognition\n\n## introduction\n\nIn some cases, we need to recognize the specific rare words with high accuracy. eg: address recognition in navigation apps. customized ASR can slove those issues.\n\nthis demo is customized for expense account, which need to recognize rare address.\n\nthe scripts are in https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/speechx/examples/custom_asr\n\n* G with slot: 打车到 \"address_slot\"。  \n![](https://ai-studio-static-online.cdn.bcebos.com/28d9ef132a7f47a895a65ae9e5c4f55b8f472c9f3dd24be8a2e66e0b88b173a4)\n\n* this is address slot wfst, you can add the address which want to recognize.  \n![](https://ai-studio-static-online.cdn.bcebos.com/47c89100ef8c465bac733605ffc53d76abefba33d62f4d818d351f8cea3c8fe2)\n\n* after replace operation, G = fstreplace(G_with_slot, address_slot), we will get the customized graph.  \n![](https://ai-studio-static-online.cdn.bcebos.com/60a3095293044f10b73039ab10c7950d139a6717580a44a3ba878c6e74de402b)  \n\n## Usage\n### 1. Installation\ninstall paddle:2.2.2 docker.\n```\nsudo docker pull registry.baidubce.com/paddlepaddle/paddle:2.2.2\n\nsudo docker run --privileged  --net=host --ipc=host -it --rm -v $PWD:/paddle --name=paddle_demo_docker registry.baidubce.com/paddlepaddle/paddle:2.2.2 /bin/bash \n```\n\n### 2. demo\n* run websocket_server.sh.  This script will download resources and libs, and launch the service.\n```\ncd /paddle\nbash websocket_server.sh\n```\nthis script run in two steps:  \n1. download the resources.tar.gz, those direcotries will be found in resource directory.  \nmodel: acustic model  \ngraph: the decoder graph (TLG.fst)  \nlib: some libs  \nbin: binary  \ndata: audio and wav.scp  \n\n2. websocket_server_main launch the service.  \nsome params:  \nport: the service port  \ngraph_path: the decoder graph path  \nmodel_path: acustic model path  \nplease refer other params in those files:  \nPaddleSpeech/speechx/speechx/decoder/param.h  \nPaddleSpeech/speechx/examples/ds2_ol/websocket/websocket_server_main.cc  \n\n* In other terminal, run script websocket_client.sh, the client will send data and get the results.\n```\nbash websocket_client.sh\n```\nwebsocket_client_main will launch the client, the wav_scp is the wav set, port is the server service port.\n\n* result:\nIn the log of client, you will see the message below:\n```\n0513 10:58:13.827821 41768 recognizer_test_main.cc:56] wav len (sample): 70208\nI0513 10:58:13.884493 41768 feature_cache.h:52] set finished\nI0513 10:58:24.247171 41768 paddle_nnet.h:76] Tensor neml: 10240\nI0513 10:58:24.247249 41768 paddle_nnet.h:76] Tensor neml: 10240\nLOG ([5.5.544~2-f21d7]:main():decoder/recognizer_test_main.cc:90)  the result of case_10 is 五月十二日二十二点三十六分加班打车回家四十一元\n```\n"
  },
  {
    "path": "demos/custom_streaming_asr/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 定制化语音识别演示\n## 介绍\n在一些场景中，识别系统需要高精度的识别一些稀有词，例如导航软件中地名识别。而通过定制化识别可以满足这一需求。  \n\n这个 demo 是打车报销单的场景识别，需要识别一些稀有的地名，可以通过如下操作实现。\n\n相关脚本:https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/speechx/examples/custom_asr\n\n* G with slot: 打车到 \"address_slot\"。  \n![](https://ai-studio-static-online.cdn.bcebos.com/28d9ef132a7f47a895a65ae9e5c4f55b8f472c9f3dd24be8a2e66e0b88b173a4)\n\n* 这是 address slot wfst, 可以添加一些需要识别的地名.  \n![](https://ai-studio-static-online.cdn.bcebos.com/47c89100ef8c465bac733605ffc53d76abefba33d62f4d818d351f8cea3c8fe2)\n\n* 通过 replace 操作, G = fstreplace(G_with_slot, address_slot), 最终可以得到定制化的解码图。  \n![](https://ai-studio-static-online.cdn.bcebos.com/60a3095293044f10b73039ab10c7950d139a6717580a44a3ba878c6e74de402b)  \n\n## 使用方法\n### 1. 配置环境\n安装paddle:2.2.2 docker镜像。\n```\nsudo docker pull registry.baidubce.com/paddlepaddle/paddle:2.2.2\n\nsudo docker run --privileged  --net=host --ipc=host -it --rm -v $PWD:/paddle --name=paddle_demo_docker registry.baidubce.com/paddlepaddle/paddle:2.2.2 /bin/bash \n```\n\n### 2. 演示\n* 运行如下命令，完成相关资源和库的下载和服务启动。\n```\ncd /paddle\nbash websocket_server.sh\n```\n上面脚本完成了如下两个功能：\n1. 完成 resource.tar.gz 下载，解压后,会在 resource 中发现如下目录：  \nmodel: 声学模型  \ngraph: 解码构图  \nlib: 相关库  \nbin: 运行程序  \ndata: 语音数据  \n\n2. 通过 websocket_server_main 来启动服务。\n这里简单的介绍几个参数:  \nport 是服务端口，  \ngraph_path 用来指定解码图文件，  \n其他参数说明可参见代码：  \nPaddleSpeech/speechx/speechx/decoder/param.h  \nPaddleSpeech/speechx/examples/ds2_ol/websocket/websocket_server_main.cc  \n\n* 在另一个终端中， 通过 client 发送数据，得到结果。运行如下命令：\n```\nbash websocket_client.sh\n```\n通过 websocket_client_main 来启动 client 服务，其中 wav_scp 是发送的语音句子集合，port 为服务端口。\n\n* 结果：\nclient 的 log 中可以看到如下类似的结果\n```\n0513 10:58:13.827821 41768 recognizer_test_main.cc:56] wav len (sample): 70208\nI0513 10:58:13.884493 41768 feature_cache.h:52] set finished\nI0513 10:58:24.247171 41768 paddle_nnet.h:76] Tensor neml: 10240\nI0513 10:58:24.247249 41768 paddle_nnet.h:76] Tensor neml: 10240\nLOG ([5.5.544~2-f21d7]:main():decoder/recognizer_test_main.cc:90)  the result of case_10 is 五月十二日二十二点三十六分加班打车回家四十一元\n```\n"
  },
  {
    "path": "demos/custom_streaming_asr/path.sh",
    "content": "export LD_LIBRARY_PATH=$PWD/resource/lib\nexport PATH=$PATH:$PWD/resource/bin\n"
  },
  {
    "path": "demos/custom_streaming_asr/setup_docker.sh",
    "content": "sudo nvidia-docker run --privileged  --net=host --ipc=host -it --rm -v $PWD:/paddle --name=paddle_demo_docker registry.baidubce.com/paddlepaddle/paddle:2.2.2 /bin/bash\n"
  },
  {
    "path": "demos/custom_streaming_asr/websocket_client.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\n. path.sh\n# input\ndata=$PWD/data\n\n# output\nwav_scp=wav.scp\n\nexport GLOG_logtostderr=1\n\n# websocket client\nwebsocket_client_main \\\n    --wav_rspecifier=scp:$data/$wav_scp \\\n    --streaming_chunk=0.36 \\\n    --port=8881\n"
  },
  {
    "path": "demos/custom_streaming_asr/websocket_server.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\nexport GLOG_logtostderr=1\n\n. path.sh\n#test websocket server \n\nmodel_dir=./resource/model\ngraph_dir=./resource/graph\ncmvn=./data/cmvn.ark\n\n\n#paddle_asr_online/resource.tar.gz\nif [ ! -f $cmvn ]; then\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/paddle_asr_online/resource.tar.gz\n    tar xzfv resource.tar.gz\n    ln -s ./resource/data .\nfi\n\nwebsocket_server_main \\\n    --cmvn_file=$cmvn \\\n    --streaming_chunk=0.1 \\\n    --use_fbank=true \\\n    --model_path=$model_dir/avg_10.jit.pdmodel \\\n    --param_path=$model_dir/avg_10.jit.pdiparams \\\n    --model_cache_shapes=\"5-1-2048,5-1-2048\" \\\n    --model_output_names=softmax_0.tmp_0,tmp_5,concat_0.tmp_0,concat_1.tmp_0 \\\n    --word_symbol_table=$graph_dir/words.txt \\\n    --graph_path=$graph_dir/TLG.fst --max_active=7500 \\\n    --port=8881 \\\n    --acoustic_scale=12 \n"
  },
  {
    "path": "demos/keyword_spotting/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# KWS (Keyword Spotting)\n\n## Introduction\nKWS(Keyword Spotting) is a technique to recognize keyword from a giving speech audio.\n\nThis demo is an implementation to recognize keyword from a specific audio file. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/kws/hey_snips.wav https://paddlespeech.cdn.bcebos.com/kws/non-keyword.wav\n```\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  paddlespeech kws --input ./hey_snips.wav\n  paddlespeech kws --input ./non-keyword.wav\n  ```\n  \n  Usage:\n  ```bash\n  paddlespeech kws --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize.\n  - `threshold`：Score threshold for kws. Default: `0.8`.\n  - `model`: Model type of kws task. Default: `mdtc_heysnips`.\n  - `config`: Config of kws task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n  - `verbose`: Show the log information.\n\n  Output:\n  ```bash\n  # Input file: ./hey_snips.wav\n  Score: 1.000, Threshold: 0.8, Is keyword: True\n  # Input file: ./non-keyword.wav\n  Score: 0.000, Threshold: 0.8, Is keyword: False\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.kws import KWSExecutor\n\n  kws_executor = KWSExecutor()\n  result = kws_executor(\n      audio_file='./hey_snips.wav',\n      threshold=0.8,\n      model='mdtc_heysnips',\n      config=None,\n      ckpt_path=None,\n      device=paddle.get_device())\n  print('KWS Result: \\n{}'.format(result))\n  ```\n\n  Output:\n  ```bash\n  KWS Result:\n  Score: 1.000, Threshold: 0.8, Is keyword: True\n  ```\n\n### 4.Pretrained Models\n\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n| Model | Language | Sample Rate\n| :--- | :---: | :---: |\n| mdtc_heysnips | en | 16k\n"
  },
  {
    "path": "demos/keyword_spotting/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 关键词识别\n## 介绍\n关键词识别是一项用于识别一段语音内是否包含特定的关键词。\n\n这个 demo 是一个从给定音频文件识别特定关键词的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 demo 的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/kws/hey_snips.wav https://paddlespeech.cdn.bcebos.com/kws/non-keyword.wav\n```\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  paddlespeech kws --input ./hey_snips.wav\n  paddlespeech kws --input ./non-keyword.wav\n  ```\n  \n  使用方法：\n  ```bash\n  paddlespeech kws --help\n  ```\n  参数：\n  - `input`(必须输入)：用于识别关键词的音频文件。\n  - `threshold`：用于判别是包含关键词的得分阈值，默认值：`0.8`。\n  - `model`：KWS 任务的模型，默认值：`mdtc_heysnips`。\n  - `config`：KWS 任务的参数文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n  - `ckpt_path`：模型参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n  - `verbose`: 如果使用，显示 logger 信息。\n\n  输出：\n  ```bash\n  # 输入为 ./hey_snips.wav\n  Score: 1.000, Threshold: 0.8, Is keyword: True\n  # 输入为 ./non-keyword.wav\n  Score: 0.000, Threshold: 0.8, Is keyword: False\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.kws import KWSExecutor\n\n  kws_executor = KWSExecutor()\n  result = kws_executor(\n      audio_file='./hey_snips.wav',\n      threshold=0.8,\n      model='mdtc_heysnips',\n      config=None,\n      ckpt_path=None,\n      device=paddle.get_device())\n  print('KWS Result: \\n{}'.format(result))\n  ```\n\n  输出：\n  ```bash\n  KWS Result:\n  Score: 1.000, Threshold: 0.8, Is keyword: True\n  ```\n\n### 4.预训练模型\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n| 模型 | 语言 | 采样率\n| :--- | :---: | :---: |\n| mdtc_heysnips | en | 16k\n"
  },
  {
    "path": "demos/keyword_spotting/run.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/kws/hey_snips.wav https://paddlespeech.cdn.bcebos.com/kws/non-keyword.wav\n\n# kws\npaddlespeech kws --input ./hey_snips.wav\npaddlespeech kws --input non-keyword.wav\n"
  },
  {
    "path": "demos/metaverse/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Metaverse\n## Introduction\nMetaverse is a new Internet application and social form integrating virtual reality produced by integrating a variety of new technologies. \n\nThis demo is an implementation to let a celebrity in an image \"speak\". With the composition of the `TTS` module of `PaddleSpeech` and `PaddleGAN`, we integrate the installation and the specific modules in a single shell script. \n## Usage\n\nYou can make your favorite person say the specified content with the `TTS` module of `PaddleSpeech` and `PaddleGAN`, and construct your virtual human.\n\nRun `run.sh` to complete all the essential procedures, including the installation.  \n\n```bash\n./run.sh\n```\nIn `run.sh`, it will execute `source path.sh` firstly, which will set the environment variants. \n\nIf you would like to try your sentence, please replace the sentence in `sentences.txt`.\n\nIf you would like to try your image, please replace the image `download/Lamarr.png` in the shell script.\n\nThe result has shown in our [notebook](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/tutorial/tts/tts_tutorial.ipynb).\n"
  },
  {
    "path": "demos/metaverse/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# Metaverse\n\n## 简介\n\nMetaverse 是一种新的互联网应用和社交形式，融合了多种新技术，产生了虚拟现实。\n\n这个演示是一个让图片中的名人“说话”的实现。通过 `PaddleSpeech` 的 `TTS` 模块和 `PaddleGAN` 的组合，我们集成了安装和特定模块到一个 shell 脚本中。\n\n## 使用\n\n您可以使用 `PaddleSpeech` 的 `TTS` 模块和 `PaddleGAN` 让您最喜欢的人说出指定的内容，并构建您的虚拟人。\n\n运行 `run.sh` 完成所有基本程序，包括安装。\n\n```bash\n./run.sh\n```\n\n在 `run.sh`, 先会执行 `source path.sh` 来设置好环境变量。\n\n如果您想尝试您的句子，请替换 `sentences.txt` 中的句子。\n\n如果您想尝试图像，请将图像替换 shell 脚本中的 `download/Lamarr.png` 。\n\n结果已显示在我们的 [notebook](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/tutorial/tts/tts_tutorial.ipynb)。\n"
  },
  {
    "path": "demos/metaverse/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=fastspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "demos/metaverse/run.sh",
    "content": "#!/bin/bash\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\n# with the following command, you can choice the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nmkdir -p download\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # install PaddleGAN\n    git clone https://github.com/PaddlePaddle/PaddleGAN.git\n    pip install -e PaddleGAN/\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then \n    # download pretrained PaddleGAN model\n    wget -P download https://paddlegan.bj.bcebos.com/models/wav2lip_hq.pdparams\nfi \n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # download pretrained tts models and unzip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip\n    unzip -d download download/pwg_baker_ckpt_0.4.zip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip\n    unzip -d download download/fastspeech2_nosil_baker_ckpt_0.4.zip\n    # donload sources\n    wget -P download https://paddlespeech.cdn.bcebos.com/demos/metaverse/Lamarr.png\n\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # run tts\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=download/fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n        --am_ckpt=download/fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n        --am_stat=download/fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy  \\\n        --voc=pwgan_csmsc \\\n        --voc_config=download/pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=download/pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=download/pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=sentences.txt \\\n        --output_dir=output/wavs \\\n        --inference_dir=output/inference \\\n        --phones_dict=download/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n    # output/inference is not needed here, which save the static models\n    rm -rf output/inference\nfi\n\nif [ ${stage} -le  4 ] && [ ${stop_stage} -ge 4 ]; then\n    # We only test one audio here, cause it's slow\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    python3 PaddleGAN/applications/tools/wav2lip.py \\\n        --checkpoint_path download/wav2lip_hq.pdparams \\\n        --face download/Lamarr.png \\\n        --audio output/wavs/000.wav \\\n        --outfile output/tts_lips.mp4 \\\n        --face_enhancement\nfi\n"
  },
  {
    "path": "demos/metaverse/sentences.txt",
    "content": "000 谁知青蛙一落地，竟变成了一位英俊的王子。于是遵照国王的意思，他做了公主的亲密伴侣。\n"
  },
  {
    "path": "demos/punctuation_restoration/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# Punctuation Restoration\n## Introduction\nPunctuation restoration is a common post-processing problem for Automatic Speech Recognition (ASR) systems. It is important to improve the readability of the transcribed text for the human reader and facilitate NLP tasks. \n\nThis demo is an implementation to restore punctuation from raw text. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input\nThe input of this demo should be a text of the specific language that can be passed via argument.\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  paddlespeech text --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n  ```\n  Usage:\n  ```bash\n  paddlespeech text --help\n  ```\n  Arguments:\n  - `input`(required): Input raw text.\n  - `task`: Choose subtask. Default: `punc`.\n  - `model`: Model type of text task. Default: `ernie_linear_p7_wudao`.\n  - `lang`: Choose model language.. Default: `zh`.\n  - `config`: Config of text task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `punc_vocab`: Vocabulary file of punctuation restoration task. Default: `None`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n\n  Output:\n  ```bash\n  [2021-12-14 19:50:22,200] [    INFO] [log.py] [L57] - Text Result:\n  今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.text import TextExecutor\n\n  text_executor = TextExecutor()\n  result = text_executor(\n      text='今天的天气真不错啊你下午有空吗我想约你一起去吃饭',\n      task='punc',\n      model='ernie_linear_p7_wudao',\n      lang='zh',\n      config=None,\n      ckpt_path=None,\n      punc_vocab=None,\n      device=paddle.get_device())\n  print('Text Result: \\n{}'.format(result))\n  ```\n  Output:\n  ```bash\n  Text Result:\n  今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n  ```\n\n### 4.Pretrained Models\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n- Punctuation Restoration\n  | Model | Language | Number of Punctuation Characters\n  | :--- | :---: | :---: \n  | ernie_linear_p3_wudao| zh | 3(，。？)\n  | ernie_linear_p7_wudao| zh | 7(，。！？、：；)\n"
  },
  {
    "path": "demos/punctuation_restoration/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 标点恢复\n## 介绍\n\n标点恢复是语音识别系统中常见的后处理步骤。提高转录文本的可读性对于人类阅读和后续的自然语言处理任务是非常重要的。\n\n这个 demo 是一个为原始文本恢复标点的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 demo 的输入是通过参数传递的特定语言的文本。\n\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  paddlespeech text --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n  ```\n  使用方法:\n  ```bash\n  paddlespeech text --help\n  ```\n  参数：\n  - `input`(必须输入)：原始文本。\n  - `task`：子任务，默认值：`punc`。\n  - `model`：文本模型类型，默认值：`ernie_linear_p7_wudao`。\n  - `lang`：模型语言， 默认值：`zh`。\n  - `config`：文本任务的配置文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n  - `ckpt_path`：模型参数文件， 若不设置则下载预训练模型使用，默认值：`None`。\n  - `punc_vocab`：标点恢复任务的标点词表文件，默认值：`None`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n\n  输出：\n  ```bash\n  [2021-12-14 19:50:22,200] [    INFO] [log.py] [L57] - Text Result:\n  今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.text import TextExecutor\n\n  text_executor = TextExecutor()\n  result = text_executor(\n      text='今天的天气真不错啊你下午有空吗我想约你一起去吃饭',\n      task='punc',\n      model='ernie_linear_p7_wudao',\n      lang='zh',\n      config=None,\n      ckpt_path=None,\n      punc_vocab=None,\n      device=paddle.get_device())\n  print('Text Result: \\n{}'.format(result))\n  ```\n  输出：\n  ```bash\n  Text Result:\n  今天的天气真不错啊！你下午有空吗？我想约你一起去吃饭。\n  ```\n\n### 预训练模型\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n- 标点恢复\n  | 模型 | 语言 | 标点类型数\n  | :--- | :---: | :---: \n  | ernie_linear_p3_wudao| zh | 3(，。？)\n  | ernie_linear_p7_wudao| zh | 7(，。！？、：；)\n"
  },
  {
    "path": "demos/punctuation_restoration/run.sh",
    "content": "#!/bin/bash\n\npaddlespeech text --input 今天的天气真好啊你下午有空吗我想约你一起去吃饭\n"
  },
  {
    "path": "demos/speaker_verification/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# Speech Verification\n\n## Introduction\n\nSpeaker Verification, refers to the problem of getting a speaker embedding from an audio. \n\nThis demo is an implementation to extract speaker embedding from a specific audio file. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input File\nThe input of this cli demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n```\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  paddlespeech vector --task spk --input 85236145389.wav\n\n  echo -e \"demo1 85236145389.wav\" > vec.job\n  paddlespeech vector --task spk --input vec.job\n\n  echo -e \"demo2 85236145389.wav \\n demo3 85236145389.wav\" | paddlespeech vector --task spk\n\n  paddlespeech vector --task score --input \"./85236145389.wav ./123456789.wav\"\n  \n  echo -e \"demo4 85236145389.wav 85236145389.wav \\n demo5 85236145389.wav 123456789.wav\" > vec.job\n  paddlespeech vector --task score --input vec.job\n  ```\n  \n  Usage:\n  ```bash\n  paddlespeech vector --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize.\n  - `task` (required): Specify `vector` task. Default `spk`。\n  - `model`: Model type of vector task. Default: `ecapatdnn_voxceleb12`.\n  - `sample_rate`: Sample rate of the model. Default: `16000`.\n  - `config`: Config of vector task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n\n  Output:\n\n  ```bash\n    demo [ -1.3251206    7.8606825   -4.620626     0.3000721    2.2648535\n    -1.1931441    3.0647137    7.673595    -6.0044727  -12.02426\n    -1.9496069    3.1269536    1.618838    -7.6383104   -1.2299773\n  -12.338331     2.1373026   -5.3957124    9.717328     5.6752305\n    3.7805123    3.0597172    3.429692     8.97601     13.174125\n    -0.53132284   8.9424715    4.46511     -4.4262476   -9.726503\n    8.399328     7.2239175   -7.435854     2.9441683   -4.3430395\n  -13.886965    -1.6346735  -10.9027405   -5.311245     3.8007221\n    3.8976038   -2.1230774   -2.3521194    4.151031    -7.4048667\n    0.13911647   2.4626107    4.9664545    0.9897574    5.4839754\n    -3.3574002   10.1340065   -0.6120171  -10.403095     4.6007543\n    16.00935     -7.7836914   -4.1945305   -6.9368606    1.1789556\n    11.490801     4.2380238    9.550931     8.375046     7.5089145\n    -0.65707296  -0.30051577   2.8406055    3.0828028    0.730817\n    6.148354     0.13766119 -13.424735    -7.7461405   -2.3227983\n    -8.305252     2.9879124  -10.995229     0.15211068  -2.3820348\n    -1.7984174    8.495629    -5.8522367   -3.755498     0.6989711\n    -5.2702994   -2.6188622   -1.8828466   -4.64665     14.078544\n    -0.5495333   10.579158    -3.2160501    9.349004    -4.381078\n  -11.675817    -2.8630207    4.5721755    2.246612    -4.574342\n    1.8610188    2.3767874    5.6257877   -9.784078     0.64967257\n    -1.4579505    0.4263264   -4.9211264   -2.454784     3.4869802\n    -0.42654222   8.341269     1.356552     7.0966883  -13.102829\n    8.016734    -7.1159344    1.8699781    0.208721    14.699384\n    -1.025278    -2.6107233   -2.5082312    8.427193     6.9138527\n    -6.2912464    0.6157366    2.489688    -3.4668267    9.921763\n    11.200815    -0.1966403    7.4916005   -0.62312716  -0.25848144\n    -9.947997    -0.9611041    1.1649219   -2.1907122   -1.5028487\n    -0.51926106  15.165954     2.4649463   -0.9980445    7.4416637\n    -2.0768049    3.5896823   -7.3055434   -7.5620847    4.323335\n    0.0804418   -6.56401     -2.3148053   -1.7642345   -2.4708817\n    -7.675618    -9.548878    -1.0177554    0.16986446   2.5877135\n    -1.8752296   -0.36614323  -6.0493784   -2.3965611   -5.9453387\n    0.9424033  -13.155974    -7.457801     0.14658108  -3.742797\n    5.8414927   -1.2872906    5.5694313   12.57059      1.0939219\n    2.2142086    1.9181576    6.9914207   -5.888139     3.1409824\n    -2.003628     2.4434285    9.973139     5.03668      2.0051203\n    2.8615603    5.860224     2.9176188   -1.6311141    2.0292206\n    -4.070415    -6.831437  ]\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.cli.vector import VectorExecutor\n\n  vector_executor = VectorExecutor()\n  audio_emb = vector_executor(\n      model='ecapatdnn_voxceleb12',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./85236145389.wav',\n      device=paddle.get_device())\n  print('Audio embedding Result: \\n{}'.format(audio_emb))\n\n  test_emb = vector_executor(\n      model='ecapatdnn_voxceleb12',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./123456789.wav',\n      device=paddle.get_device())\n  print('Test embedding Result: \\n{}'.format(test_emb))\n\n  # score range [0, 1]\n  score = vector_executor.get_embeddings_score(audio_emb, test_emb)\n  print(f\"Eembeddings Score: {score}\")\n  ```\n\n  Output：\n\n  ```bash\n  # Vector Result:\n   Audio embedding Result:\n    [ -1.3251206    7.8606825   -4.620626     0.3000721    2.2648535\n      -1.1931441    3.0647137    7.673595    -6.0044727  -12.02426\n      -1.9496069    3.1269536    1.618838    -7.6383104   -1.2299773\n    -12.338331     2.1373026   -5.3957124    9.717328     5.6752305\n      3.7805123    3.0597172    3.429692     8.97601     13.174125\n      -0.53132284   8.9424715    4.46511     -4.4262476   -9.726503\n      8.399328     7.2239175   -7.435854     2.9441683   -4.3430395\n    -13.886965    -1.6346735  -10.9027405   -5.311245     3.8007221\n      3.8976038   -2.1230774   -2.3521194    4.151031    -7.4048667\n      0.13911647   2.4626107    4.9664545    0.9897574    5.4839754\n      -3.3574002   10.1340065   -0.6120171  -10.403095     4.6007543\n      16.00935     -7.7836914   -4.1945305   -6.9368606    1.1789556\n      11.490801     4.2380238    9.550931     8.375046     7.5089145\n      -0.65707296  -0.30051577   2.8406055    3.0828028    0.730817\n      6.148354     0.13766119 -13.424735    -7.7461405   -2.3227983\n      -8.305252     2.9879124  -10.995229     0.15211068  -2.3820348\n      -1.7984174    8.495629    -5.8522367   -3.755498     0.6989711\n      -5.2702994   -2.6188622   -1.8828466   -4.64665     14.078544\n      -0.5495333   10.579158    -3.2160501    9.349004    -4.381078\n    -11.675817    -2.8630207    4.5721755    2.246612    -4.574342\n      1.8610188    2.3767874    5.6257877   -9.784078     0.64967257\n      -1.4579505    0.4263264   -4.9211264   -2.454784     3.4869802\n      -0.42654222   8.341269     1.356552     7.0966883  -13.102829\n      8.016734    -7.1159344    1.8699781    0.208721    14.699384\n      -1.025278    -2.6107233   -2.5082312    8.427193     6.9138527\n      -6.2912464    0.6157366    2.489688    -3.4668267    9.921763\n      11.200815    -0.1966403    7.4916005   -0.62312716  -0.25848144\n      -9.947997    -0.9611041    1.1649219   -2.1907122   -1.5028487\n      -0.51926106  15.165954     2.4649463   -0.9980445    7.4416637\n      -2.0768049    3.5896823   -7.3055434   -7.5620847    4.323335\n      0.0804418   -6.56401     -2.3148053   -1.7642345   -2.4708817\n      -7.675618    -9.548878    -1.0177554    0.16986446   2.5877135\n      -1.8752296   -0.36614323  -6.0493784   -2.3965611   -5.9453387\n      0.9424033  -13.155974    -7.457801     0.14658108  -3.742797\n      5.8414927   -1.2872906    5.5694313   12.57059      1.0939219\n      2.2142086    1.9181576    6.9914207   -5.888139     3.1409824\n      -2.003628     2.4434285    9.973139     5.03668      2.0051203\n      2.8615603    5.860224     2.9176188   -1.6311141    2.0292206\n      -4.070415    -6.831437  ]\n    # get the test embedding\n    Test embedding Result:\n    [  2.5247195    5.119042    -4.335273     4.4583654    5.047907\n      3.5059214    1.6159848    0.49364898 -11.6899185   -3.1014526\n      -5.6589785   -0.42684984   2.674276   -11.937654     6.2248464\n    -10.776924    -5.694543     1.112041     1.5709964    1.0961034\n      1.3976512    2.324352     1.339981     5.279319    13.734659\n      -2.5753925   13.651442    -2.2357535    5.1575427   -3.251567\n      1.4023279    6.1191974   -6.0845175   -1.3646189   -2.6789894\n    -15.220778     9.779349    -9.411551    -6.388947     6.8313975\n      -9.245996     0.31196198   2.5509644   -4.413065     6.1649427\n      6.793837     2.6328635    8.620976     3.4832475    0.52491665\n      2.9115407    5.8392377    0.6702376   -3.2726715    2.6694255\n      16.91701     -5.5811176    0.23362345  -4.5573606  -11.801059\n      14.728292    -0.5198082   -3.999922     7.0927105   -7.0459595\n      -5.4389      -0.46420583  -5.1085467   10.376568    -8.889225\n      -0.37705845  -1.659806     2.6731026   -7.1909504    1.4608804\n      -2.163136    -0.17949677   4.0241547    0.11319201   0.601279\n      2.039692     3.1910992  -11.649526    -8.121584    -4.8707457\n      0.3851982    1.4231744   -2.3321972    0.99332285  14.121717\n      5.899413     0.7384519  -17.760096    10.555021     4.1366534\n      -0.3391071   -0.20792882   3.208204     0.8847948   -8.721497\n      -6.432868    13.006379     4.8956      -9.155822    -1.9441519\n      5.7815638   -2.066733    10.425042    -0.8802383   -2.4314315\n      -9.869258     0.35095334  -5.3549943    2.1076174   -8.290468\n      8.4433365   -4.689333     9.334139    -2.172678    -3.0250976\n      8.394216    -3.2110903   -7.93868      2.3960824   -2.3213403\n      -1.4963245   -3.476059     4.132903   -10.893354     4.362673\n      -0.45456508  10.258634    -1.1655927   -6.7799754    0.22885278\n      -4.399287     2.333433    -4.84745     -4.2752337   -1.3577863\n      -1.0685898    9.505196     7.3062205    0.08708266  12.927811\n      -9.57974      1.3936648   -1.9444873    5.776769    15.251903\n      10.6118355   -1.4903594   -9.535318    -3.6553776   -1.6699586\n      -0.5933151    7.600357    -4.8815503   -8.698617   -15.855757\n      0.25632986  -7.2235737    0.9506656    0.7128582   -9.051738\n      8.74869     -1.6426028   -6.5762258    2.506905    -6.7431564\n      5.129912   -12.189555    -3.6435068   12.068113    -6.0059533\n      -2.3535995    2.9014351   22.3082      -1.5563312   13.193291\n      2.7583609   -7.468798     1.3407065   -4.599617    -6.2345777\n      10.7689295    7.137627     5.099476     0.3473359    9.647881\n      -2.0484571   -5.8549366 ]\n    # get the score between enroll and test\n    Eembeddings Score: 0.45332613587379456\n  ```\n\n### 4.Pretrained Models\n\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n| Model | Sample Rate\n| :--- | :---: |\n| ecapatdnn_voxceleb12 | 16k\n"
  },
  {
    "path": "demos/speaker_verification/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 声纹识别\n## 介绍\n声纹识别是一项用计算机程序自动提取说话人特征的技术。\n\n这个 demo 是从一个给定音频文件中提取说话人特征，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从easy medium，hard 三种方式中选择一种方式安装。\n\n### 2. 准备输入\n声纹cli demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 demo 的示例音频：\n```bash\n# 该音频的内容是数字串 85236145389\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n```\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  paddlespeech vector --task spk --input 85236145389.wav\n\n  echo -e \"demo1 85236145389.wav\" > vec.job\n  paddlespeech vector --task spk --input vec.job\n\n  echo -e \"demo2 85236145389.wav \\n demo3 85236145389.wav\" | paddlespeech vector --task spk\n  \n  paddlespeech vector --task score --input \"./85236145389.wav ./123456789.wav\"\n  \n  echo -e \"demo4 85236145389.wav 85236145389.wav \\n demo5 85236145389.wav 123456789.wav\" > vec.job\n  paddlespeech vector --task score --input vec.job\n  ```\n  \n  使用方法：\n  ```bash\n  paddlespeech vector --help\n  ```\n  参数：\n  - `input`(必须输入)：用于识别的音频文件。\n  - `task` (必须输入): 用于指定 `vector` 处理的具体任务，默认是 `spk`。\n  - `model`：声纹任务的模型，默认值：`ecapatdnn_voxceleb12`。\n  - `sample_rate`：音频采样率，默认值：`16000`。\n  - `config`：声纹任务的参数文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n  - `ckpt_path`：模型参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n\n  输出：\n  ```bash\n    [ -1.3251206    7.8606825   -4.620626     0.3000721    2.2648535\n    -1.1931441    3.0647137    7.673595    -6.0044727  -12.02426\n    -1.9496069    3.1269536    1.618838    -7.6383104   -1.2299773\n  -12.338331     2.1373026   -5.3957124    9.717328     5.6752305\n    3.7805123    3.0597172    3.429692     8.97601     13.174125\n    -0.53132284   8.9424715    4.46511     -4.4262476   -9.726503\n    8.399328     7.2239175   -7.435854     2.9441683   -4.3430395\n  -13.886965    -1.6346735  -10.9027405   -5.311245     3.8007221\n    3.8976038   -2.1230774   -2.3521194    4.151031    -7.4048667\n    0.13911647   2.4626107    4.9664545    0.9897574    5.4839754\n    -3.3574002   10.1340065   -0.6120171  -10.403095     4.6007543\n    16.00935     -7.7836914   -4.1945305   -6.9368606    1.1789556\n    11.490801     4.2380238    9.550931     8.375046     7.5089145\n    -0.65707296  -0.30051577   2.8406055    3.0828028    0.730817\n    6.148354     0.13766119 -13.424735    -7.7461405   -2.3227983\n    -8.305252     2.9879124  -10.995229     0.15211068  -2.3820348\n    -1.7984174    8.495629    -5.8522367   -3.755498     0.6989711\n    -5.2702994   -2.6188622   -1.8828466   -4.64665     14.078544\n    -0.5495333   10.579158    -3.2160501    9.349004    -4.381078\n  -11.675817    -2.8630207    4.5721755    2.246612    -4.574342\n    1.8610188    2.3767874    5.6257877   -9.784078     0.64967257\n    -1.4579505    0.4263264   -4.9211264   -2.454784     3.4869802\n    -0.42654222   8.341269     1.356552     7.0966883  -13.102829\n    8.016734    -7.1159344    1.8699781    0.208721    14.699384\n    -1.025278    -2.6107233   -2.5082312    8.427193     6.9138527\n    -6.2912464    0.6157366    2.489688    -3.4668267    9.921763\n    11.200815    -0.1966403    7.4916005   -0.62312716  -0.25848144\n    -9.947997    -0.9611041    1.1649219   -2.1907122   -1.5028487\n    -0.51926106  15.165954     2.4649463   -0.9980445    7.4416637\n    -2.0768049    3.5896823   -7.3055434   -7.5620847    4.323335\n    0.0804418   -6.56401     -2.3148053   -1.7642345   -2.4708817\n    -7.675618    -9.548878    -1.0177554    0.16986446   2.5877135\n    -1.8752296   -0.36614323  -6.0493784   -2.3965611   -5.9453387\n    0.9424033  -13.155974    -7.457801     0.14658108  -3.742797\n    5.8414927   -1.2872906    5.5694313   12.57059      1.0939219\n    2.2142086    1.9181576    6.9914207   -5.888139     3.1409824\n    -2.003628     2.4434285    9.973139     5.03668      2.0051203\n    2.8615603    5.860224     2.9176188   -1.6311141    2.0292206\n    -4.070415    -6.831437  ]\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.vector import VectorExecutor\n\n  vector_executor = VectorExecutor()\n  audio_emb = vector_executor(\n      model='ecapatdnn_voxceleb12',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./85236145389.wav',\n      device=paddle.get_device())\n  print('Audio embedding Result: \\n{}'.format(audio_emb))\n\n  test_emb = vector_executor(\n      model='ecapatdnn_voxceleb12',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./123456789.wav',\n      device=paddle.get_device())\n  print('Test embedding Result: \\n{}'.format(test_emb))\n\n  # score range [0, 1]\n  score = vector_executor.get_embeddings_score(audio_emb, test_emb)\n  print(f\"Eembeddings Score: {score}\")\n  ```\n\n  输出：\n  ```bash\n  # Vector Result:\n   Audio embedding Result:\n    [ -1.3251206    7.8606825   -4.620626     0.3000721    2.2648535\n      -1.1931441    3.0647137    7.673595    -6.0044727  -12.02426\n      -1.9496069    3.1269536    1.618838    -7.6383104   -1.2299773\n    -12.338331     2.1373026   -5.3957124    9.717328     5.6752305\n      3.7805123    3.0597172    3.429692     8.97601     13.174125\n      -0.53132284   8.9424715    4.46511     -4.4262476   -9.726503\n      8.399328     7.2239175   -7.435854     2.9441683   -4.3430395\n    -13.886965    -1.6346735  -10.9027405   -5.311245     3.8007221\n      3.8976038   -2.1230774   -2.3521194    4.151031    -7.4048667\n      0.13911647   2.4626107    4.9664545    0.9897574    5.4839754\n      -3.3574002   10.1340065   -0.6120171  -10.403095     4.6007543\n      16.00935     -7.7836914   -4.1945305   -6.9368606    1.1789556\n      11.490801     4.2380238    9.550931     8.375046     7.5089145\n      -0.65707296  -0.30051577   2.8406055    3.0828028    0.730817\n      6.148354     0.13766119 -13.424735    -7.7461405   -2.3227983\n      -8.305252     2.9879124  -10.995229     0.15211068  -2.3820348\n      -1.7984174    8.495629    -5.8522367   -3.755498     0.6989711\n      -5.2702994   -2.6188622   -1.8828466   -4.64665     14.078544\n      -0.5495333   10.579158    -3.2160501    9.349004    -4.381078\n    -11.675817    -2.8630207    4.5721755    2.246612    -4.574342\n      1.8610188    2.3767874    5.6257877   -9.784078     0.64967257\n      -1.4579505    0.4263264   -4.9211264   -2.454784     3.4869802\n      -0.42654222   8.341269     1.356552     7.0966883  -13.102829\n      8.016734    -7.1159344    1.8699781    0.208721    14.699384\n      -1.025278    -2.6107233   -2.5082312    8.427193     6.9138527\n      -6.2912464    0.6157366    2.489688    -3.4668267    9.921763\n      11.200815    -0.1966403    7.4916005   -0.62312716  -0.25848144\n      -9.947997    -0.9611041    1.1649219   -2.1907122   -1.5028487\n      -0.51926106  15.165954     2.4649463   -0.9980445    7.4416637\n      -2.0768049    3.5896823   -7.3055434   -7.5620847    4.323335\n      0.0804418   -6.56401     -2.3148053   -1.7642345   -2.4708817\n      -7.675618    -9.548878    -1.0177554    0.16986446   2.5877135\n      -1.8752296   -0.36614323  -6.0493784   -2.3965611   -5.9453387\n      0.9424033  -13.155974    -7.457801     0.14658108  -3.742797\n      5.8414927   -1.2872906    5.5694313   12.57059      1.0939219\n      2.2142086    1.9181576    6.9914207   -5.888139     3.1409824\n      -2.003628     2.4434285    9.973139     5.03668      2.0051203\n      2.8615603    5.860224     2.9176188   -1.6311141    2.0292206\n      -4.070415    -6.831437  ]\n    # get the test embedding\n    Test embedding Result:\n    [  2.5247195    5.119042    -4.335273     4.4583654    5.047907\n      3.5059214    1.6159848    0.49364898 -11.6899185   -3.1014526\n      -5.6589785   -0.42684984   2.674276   -11.937654     6.2248464\n    -10.776924    -5.694543     1.112041     1.5709964    1.0961034\n      1.3976512    2.324352     1.339981     5.279319    13.734659\n      -2.5753925   13.651442    -2.2357535    5.1575427   -3.251567\n      1.4023279    6.1191974   -6.0845175   -1.3646189   -2.6789894\n    -15.220778     9.779349    -9.411551    -6.388947     6.8313975\n      -9.245996     0.31196198   2.5509644   -4.413065     6.1649427\n      6.793837     2.6328635    8.620976     3.4832475    0.52491665\n      2.9115407    5.8392377    0.6702376   -3.2726715    2.6694255\n      16.91701     -5.5811176    0.23362345  -4.5573606  -11.801059\n      14.728292    -0.5198082   -3.999922     7.0927105   -7.0459595\n      -5.4389      -0.46420583  -5.1085467   10.376568    -8.889225\n      -0.37705845  -1.659806     2.6731026   -7.1909504    1.4608804\n      -2.163136    -0.17949677   4.0241547    0.11319201   0.601279\n      2.039692     3.1910992  -11.649526    -8.121584    -4.8707457\n      0.3851982    1.4231744   -2.3321972    0.99332285  14.121717\n      5.899413     0.7384519  -17.760096    10.555021     4.1366534\n      -0.3391071   -0.20792882   3.208204     0.8847948   -8.721497\n      -6.432868    13.006379     4.8956      -9.155822    -1.9441519\n      5.7815638   -2.066733    10.425042    -0.8802383   -2.4314315\n      -9.869258     0.35095334  -5.3549943    2.1076174   -8.290468\n      8.4433365   -4.689333     9.334139    -2.172678    -3.0250976\n      8.394216    -3.2110903   -7.93868      2.3960824   -2.3213403\n      -1.4963245   -3.476059     4.132903   -10.893354     4.362673\n      -0.45456508  10.258634    -1.1655927   -6.7799754    0.22885278\n      -4.399287     2.333433    -4.84745     -4.2752337   -1.3577863\n      -1.0685898    9.505196     7.3062205    0.08708266  12.927811\n      -9.57974      1.3936648   -1.9444873    5.776769    15.251903\n      10.6118355   -1.4903594   -9.535318    -3.6553776   -1.6699586\n      -0.5933151    7.600357    -4.8815503   -8.698617   -15.855757\n      0.25632986  -7.2235737    0.9506656    0.7128582   -9.051738\n      8.74869     -1.6426028   -6.5762258    2.506905    -6.7431564\n      5.129912   -12.189555    -3.6435068   12.068113    -6.0059533\n      -2.3535995    2.9014351   22.3082      -1.5563312   13.193291\n      2.7583609   -7.468798     1.3407065   -4.599617    -6.2345777\n      10.7689295    7.137627     5.099476     0.3473359    9.647881\n      -2.0484571   -5.8549366 ]\n    # get the score between enroll and test\n    Eembeddings Score: 0.45332613587379456\n  ```\n\n### 4.预训练模型\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n| 模型 | 采样率\n| :--- | :---: |\n| ecapatdnn_voxceleb12 | 16k\n"
  },
  {
    "path": "demos/speaker_verification/run.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n\n# vector\npaddlespeech vector --task spk --input ./85236145389.wav\n\npaddlespeech vector --task score --input \"./85236145389.wav ./123456789.wav\"\n"
  },
  {
    "path": "demos/speech_recognition/.gitignore",
    "content": "*.wav\n"
  },
  {
    "path": "demos/speech_recognition/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# ASR (Automatic Speech Recognition)\n\n## Introduction\nASR, or Automatic Speech Recognition, refers to the problem of getting a program to automatically transcribe spoken language (speech-to-text). \n\nThis demo is an implementation to recognize text from a specific audio file. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/ch_zh_mix.wav\n```\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  # Chinese\n  paddlespeech asr --input ./zh.wav -v\n  # English\n  paddlespeech asr --model transformer_librispeech --lang en --input ./en.wav -v\n  # Code-Switch\n  paddlespeech asr --model conformer_talcs --lang zh_en --codeswitch True --input ./ch_zh_mix.wav -v \n  # Chinese ASR + Punctuation Restoration\n  paddlespeech asr --input ./zh.wav -v | paddlespeech text --task punc -v\n  ```\n  (If you don't want to see the log information, you can remove \"-v\". Besides, it doesn't matter if package `paddlespeech-ctcdecoders` is not found, this package is optional.)\n  \n  Usage:\n  ```bash\n  paddlespeech asr --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize.\n  - `model`: Model type of asr task. Default: `conformer_wenetspeech`.\n  - `lang`: Model language. Default: `zh`.\n  - `codeswitch`: Code Swith Model. Default: `False`\n  - `sample_rate`: Sample rate of the model. Default: `16000`.\n  - `config`: Config of asr task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `yes`: No additional parameters required. Once set this parameter, it means accepting the request of the program by default, which includes transforming the audio sample rate. Default: `False`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n  - `verbose`: Show the log information.\n\n  Output:\n  ```bash\n  # Chinese\n  [2021-12-08 13:12:34,063] [    INFO] [utils.py] [L225] - ASR Result: 我认为跑步最重要的就是给我带来了身体健康\n  # English\n  [2022-01-12 11:51:10,815] [    INFO] - ASR Result: i knocked at the door on the ancient side of the building\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.asr import ASRExecutor\n\n  asr_executor = ASRExecutor()\n  text = asr_executor(\n      model='conformer_wenetspeech',\n      lang='zh',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./zh.wav',\n      force_yes=False,\n      device=paddle.get_device())\n  print('ASR Result: \\n{}'.format(text))\n  ```\n\n  Output:\n  ```bash\n  ASR Result:\n  我认为跑步最重要的就是给我带来了身体健康\n  ```\n\n### 4.Pretrained Models\n\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n| Model | Code Switch | Language | Sample Rate\n| :--- | :---: | :---: | :---: |\n| conformer_wenetspeech | False | zh | 16k\n| conformer_online_multicn | False | zh | 16k\n| conformer_aishell | False | zh | 16k\n| conformer_online_aishell | False | zh | 16k\n| transformer_librispeech | False | en | 16k\n| deepspeech2online_wenetspeech | False | zh | 16k\n| deepspeech2offline_aishell | False | zh| 16k\n| deepspeech2online_aishell | False | zh | 16k\n| deepspeech2offline_librispeech | False | en | 16k\n| conformer_talcs | True | zh_en | 16k\n"
  },
  {
    "path": "demos/speech_recognition/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n (简体中文|[English](./README.md))\n\n# 语音识别\n## 介绍\n语音识别是一项用计算机程序自动转录语音的技术。\n\n这个 demo 是一个从给定音频文件识别文本的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 demo 的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/ch_zh_mix.wav\n```\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n  # 中文\n  paddlespeech asr --input ./zh.wav -v\n  # 英文\n  paddlespeech asr --model transformer_librispeech --lang en --input ./en.wav -v\n  #中英混合\n  paddlespeech asr --model conformer_talcs --lang zh_en --codeswitch True --input ./ch_zh_mix.wav -v \n  # 中文 + 标点恢复\n  paddlespeech asr --input ./zh.wav -v | paddlespeech text --task punc -v\n  ```\n  (如果不想显示 log 信息，可以不使用\"-v\", 另外如果显示 `paddlespeech-ctcdecoders` 这个 python 包没有找到的 Error，没有关系，这个包是非必须的。)\n  \n  使用方法：\n  ```bash\n  paddlespeech asr --help\n  ```\n  参数：\n  - `input`(必须输入)：用于识别的音频文件。\n  - `model`：ASR 任务的模型，默认值：`conformer_wenetspeech`。\n  - `lang`：模型语言，默认值：`zh`。\n  - `codeswitch`: 是否使用语言转换，默认值：`False`。\n  - `sample_rate`：音频采样率，默认值：`16000`。\n  - `config`：ASR 任务的参数文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n  - `ckpt_path`：模型参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `yes`；不需要设置额外的参数，一旦设置了该参数，说明你默认同意程序的所有请求，其中包括自动转换输入音频的采样率。默认值：`False`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n  - `verbose`: 如果使用，显示 logger 信息。\n\n  输出：\n  ```bash\n  # 中文\n  [2021-12-08 13:12:34,063] [    INFO] [utils.py] [L225] - ASR Result: 我认为跑步最重要的就是给我带来了身体健康\n  # 英文\n  [2022-01-12 11:51:10,815] [    INFO] - ASR Result: i knocked at the door on the ancient side of the building\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.asr import ASRExecutor\n\n  asr_executor = ASRExecutor()\n  text = asr_executor(\n      model='conformer_wenetspeech',\n      lang='zh',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./zh.wav',\n      force_yes=False,\n      device=paddle.get_device())\n  print('ASR Result: \\n{}'.format(text))\n  ```\n\n  输出：\n  ```bash\n  ASR Result:\n  我认为跑步最重要的就是给我带来了身体健康\n  ```\n\n### 4.预训练模型\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n| 模型 | 语言转换 | 语言 | 采样率\n| :--- | :---: | :---: | :---: |\n| conformer_wenetspeech | False | zh | 16k\n| conformer_online_multicn | False | zh | 16k\n| conformer_aishell | False | zh | 16k\n| conformer_online_aishell | False | zh | 16k\n| transformer_librispeech | False | en | 16k\n| deepspeech2online_wenetspeech | False | zh | 16k\n| deepspeech2offline_aishell | False | zh| 16k\n| deepspeech2online_aishell | False | zh | 16k\n| deepspeech2offline_librispeech | False | en | 16k\n| conformer_talcs | True | zh_en | 16k\n"
  },
  {
    "path": "demos/speech_recognition/run.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/ch_zh_mix.wav\n\n# asr\npaddlespeech asr --input ./zh.wav\n\n\n# asr + punc\npaddlespeech asr --input ./zh.wav | paddlespeech text --task punc\n\n\n# asr help\npaddlespeech asr --help\n\n\n# english asr\npaddlespeech asr --lang en --model transformer_librispeech --input ./en.wav\n\n\n# code-switch asr\npaddlespeech asr --lang zh_en --codeswitch True --model conformer_talcs --input ./ch_zh_mix.wav\n\n\n# model stats\npaddlespeech stats --task asr\n\n\n# paddlespeech help\npaddlespeech --help\n"
  },
  {
    "path": "demos/speech_server/.gitignore",
    "content": "*.wav\n"
  },
  {
    "path": "demos/speech_server/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Speech Server\n\n## Introduction\nThis demo is an implementation of starting the voice service and accessing the service. It can be achieved with a single command using `paddlespeech_server` and `paddlespeech_client` or a few lines of code in python.\n\nFor service interface definition, please check:\n- [PaddleSpeech Server RESTful API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-RESTful-API)\n\n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nIt is recommended to use **paddlepaddle 2.4rc** or above.\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n**If you install in easy mode, you need to prepare the yaml file by yourself, you can refer to the yaml file in the conf directory.**\n\n### 2. Prepare config File\nThe configuration file can be found in `conf/application.yaml` .\nAmong them, `engine_list` indicates the speech engine that will be included in the service to be started, in the format of `<speech task>_<engine type>`.\nAt present, the speech tasks integrated by the service include: asr (speech recognition), tts (text to sppech) and cls (audio classification).\nCurrently the engine type supports two forms: python and inference (Paddle Inference)\n**Note:** If the service can be started normally in the container, but the client access IP is unreachable, you can try to replace the `host` address in the configuration file with the local IP address.\n\n### 3. Server Usage\n- Command Line (Recommended)\n\n  ```bash\n  # start the service\n  paddlespeech_server start --config_file ./conf/application.yaml\n  ```\n\n  > **Note:** For mixed Chinese and English speech recognition, please use the `./conf/conformer_talcs_application.yaml` configuration file \n\n  Usage:\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  Arguments:\n  - `config_file`: yaml file of the app, default: ./conf/application.yaml\n  - `log_file`: log file. Default: ./log/paddlespeech.log\n\n  Output:\n  ```text\n  [2022-02-23 11:17:32] [INFO] [server.py:64] Started server process [6384]\n  INFO:     Waiting for application startup.\n  [2022-02-23 11:17:32] [INFO] [on.py:26] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-02-23 11:17:32] [INFO] [on.py:38] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-02-23 11:17:32] [INFO] [server.py:204] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  Output:\n  ```text\n  INFO:     Started server process [529]\n  [2022-02-23 14:57:56] [INFO] [server.py:64] Started server process [529]\n  INFO:     Waiting for application startup.\n  [2022-02-23 14:57:56] [INFO] [on.py:26] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-02-23 14:57:56] [INFO] [on.py:38] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-02-23 14:57:56] [INFO] [server.py:204] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n\n### 4. ASR Client Usage\n\nThe input of  ASR client demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this ASR client demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/ch_zh_mix.wav\n```\n\n**Note:** The response time will be slightly longer when using the client for the first time\n- Command Line (Recommended)\n\n   If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n   ```bash\n   paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n  \n   # Chinese and English mixed speech recognition,  using `./conf/conformer_talcs_application.yaml` config file\n   paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input ./ch_zh_mix.wav\n   ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_client asr --help\n  ```\n  Arguments:\n  - `server_ip`: server ip. Default: 127.0.0.1\n  - `port`: server port. Default: 8090\n  - `input`(required): Audio file to be recognized.\n  - `sample_rate`: Audio ampling rate, default: 16000.\n  - `lang`: Language. Default: \"zh_cn\".\n  - `audio_format`: Audio format. Default: \"wav\".\n\n  Output:\n  ```text\n  [2022-08-01 07:54:01,646] [    INFO] - ASR result: 我认为跑步最重要的就是给我带来了身体健康\n  [2022-08-01 07:54:01,646] [    INFO] - Response time 4.898965 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ASRClientExecutor\n\n  asrclient_executor = ASRClientExecutor()\n  res = asrclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      sample_rate=16000,\n      lang=\"zh_cn\",\n      audio_format=\"wav\")\n  print(res)\n  ```\n  Output:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康\n  ```\n \n### 5. TTS Client Usage\n**Note:** The response time will be slightly longer when using the client for the first time\n- Command Line (Recommended)\n\n   If `127.0.0.1` is not accessible, you need to use the actual service IP address\n\n   ```bash\n   paddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n   ```\n     Usage:\n  \n    ```bash\n    paddlespeech_client tts --help\n    ```\n    Arguments:\n    - `server_ip`: server ip. Default: 127.0.0.1\n    - `port`: server port. Default: 8090\n    - `input`(required): Input text to generate.\n    - `spk_id`: Speaker id for multi-speaker text to speech. Default: 0\n    - `speed`: Audio speed, the value should be set between 0 and 3. Default: 1.0\n    - `volume`: Audio volume, the value should be set between 0 and 3. Default: 1.0\n    - `sample_rate`: Sampling rate, choice: [0, 8000, 16000], the default is the same as the model. Default: 0\n    - `output`: Output wave filepath. Default: None, which means not to save the audio to the local.\n\n    Output:\n    ```text\n    [2022-02-23 15:20:37,875] [    INFO] - Save synthesized audio successfully on output.wav.\n    [2022-02-23 15:20:37,875] [    INFO] - Audio duration: 3.612500 s.\n    [2022-02-23 15:20:37,875] [    INFO] - Response time: 0.348050 s.\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSClientExecutor\n  import json\n\n  ttsclient_executor = TTSClientExecutor()\n  res = ttsclient_executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      spk_id=0,\n      speed=1.0,\n      volume=1.0,\n      sample_rate=0,\n      output=\"./output.wav\")\n\n  response_dict = res.json()\n  print(response_dict[\"message\"])\n  print(\"Save synthesized audio successfully on %s.\" % (response_dict['result']['save_path']))\n  print(\"Audio duration: %f s.\" %(response_dict['result']['duration']))\n  ```\n\n  Output:\n  ```text\n  {'description': 'success.'}\n  Save synthesized audio successfully on ./output.wav.\n  Audio duration: 3.612500 s.\n  ```\n\n### 6. CLS Client Usage\n\nHere are sample files for this CLS Client demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav \n```\n\n**Note:** The response time will be slightly longer when using the client for the first time\n- Command Line (Recommended)\n\n   If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n   ```bash\n   paddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n   ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_client cls --help\n  ```\n  Arguments:\n  - `server_ip`: server ip. Default: 127.0.0.1\n  - `port`: server port. Default: 8090\n  - `input`(required): Audio file to be classified.\n  - `topk`: topk scores of classification result.\n\n  Output:\n  ```text\n  [2022-03-09 20:44:39,974] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'topk': 1, 'results': [{'class_name': 'Speech', 'prob': 0.9027184844017029}]}}\n  [2022-03-09 20:44:39,975] [    INFO] - Response time 0.104360 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import CLSClientExecutor\n  import json\n\n  clsclient_executor = CLSClientExecutor()\n  res = clsclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      topk=1)\n  print(res.json())\n  ```\n\n  Output:\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'topk': 1, 'results': [{'class_name': 'Speech', 'prob': 0.9027184844017029}]}}\n  ```\n\n\n### 7. Speaker Verification Client Usage\n\nHere are sample files for this Speaker Verification Client demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n```\n\n#### 7.1 Extract speaker embedding\n**Note:** The response time will be slightly longer when using the client for the first time\n- Command Line (Recommended)\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ``` bash\n  paddlespeech_client vector --task spk  --server_ip 127.0.0.1 --port 8090 --input 85236145389.wav\n  ```\n\n  Usage:\n\n  ``` bash\n  paddlespeech_client vector --help\n  ```\n\n  Arguments:\n    * server_ip: server ip. Default: 127.0.0.1\n    * port: server port. Default: 8090\n    * input(required): Input text to generate.\n    * task: the task of vector, can be use 'spk' or 'score。Default is 'spk'。\n    * enroll: enroll audio\n    * test: test audio\n\n  Output:\n\n  ```text\n  [2022-08-01 09:01:22,151] [    INFO] - vector http client start\n  [2022-08-01 09:01:22,152] [    INFO] - the input audio: 85236145389.wav\n  [2022-08-01 09:01:22,152] [    INFO] - endpoint: http://127.0.0.1:8090/paddlespeech/vector\n  [2022-08-01 09:01:27,093] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'vec': [1.4217487573623657, 5.626248836517334, -5.342073440551758, 1.177390217781067, 3.308061122894287, 1.7565997838974, 5.1678876876831055, 10.806346893310547, -3.822679042816162, -5.614130973815918, 2.6238481998443604, -0.8072965741157532, 1.963512659072876, -7.312864780426025, 0.011034967377781868, -9.723127365112305, 0.661963164806366, -6.976816654205322, 10.213465690612793, 7.494767189025879, 2.9105641841888428, 3.894925117492676, 3.7999846935272217, 7.106173992156982, 16.905324935913086, -7.149376392364502, 8.733112335205078, 3.423002004623413, -4.831653118133545, -11.403371810913086, 11.232216835021973, 7.127464771270752, -4.282831192016602, 2.4523589611053467, -5.13075065612793, -18.17765998840332, -2.611666440963745, -11.00034236907959, -6.731431007385254, 1.6564655303955078, 0.7618184685707092, 1.1253058910369873, -2.0838277339935303, 4.725739002227783, -8.782590866088867, -3.5398736000061035, 3.8142387866973877, 5.142062664031982, 2.162053346633911, 4.09642219543457, -6.416221618652344, 12.747454643249512, 1.9429889917373657, -15.152948379516602, 6.417416572570801, 16.097013473510742, -9.716649055480957, -1.9920448064804077, -3.364956855773926, -1.8719490766525269, 11.567351341247559, 3.6978795528411865, 11.258269309997559, 7.442364692687988, 9.183405876159668, 4.528151512145996, -1.2417811155319214, 4.395910263061523, 6.672768592834473, 5.889888763427734, 7.627115249633789, -0.6692016124725342, -11.889703750610352, -9.208883285522461, -7.427401542663574, -3.777655601501465, 6.917237758636475, -9.848749160766602, -2.094479560852051, -5.1351189613342285, 0.49564215540885925, 9.317541122436523, -5.9141845703125, -1.809845209121704, -0.11738205701112747, -7.169270992279053, -1.0578246116638184, -5.721685886383057, -5.117387294769287, 16.137670516967773, -4.473618984222412, 7.66243314743042, -0.5538089871406555, 9.631582260131836, -6.470466613769531, -8.54850959777832, 4.371622085571289, -0.7970349192619324, 4.479003429412842, -2.9758646488189697, 3.2721707820892334, 2.8382749557495117, 5.1345953941345215, -9.19078254699707, -0.5657423138618469, -4.874573230743408, 2.316561460494995, -5.984307289123535, -2.1798791885375977, 0.35541653633117676, -0.3178458511829376, 9.493547439575195, 2.114448070526123, 4.358088493347168, -12.089820861816406, 8.451695442199707, -7.925461769104004, 4.624246120452881, 4.428938388824463, 18.691999435424805, -2.620460033416748, -5.149182319641113, -0.3582168221473694, 8.488557815551758, 4.98148250579834, -9.326834678649902, -2.2544236183166504, 6.64176607131958, 1.2119656801223755, 10.977132797241211, 16.55504035949707, 3.323848247528076, 9.55185317993164, -1.6677050590515137, -0.7953923940658569, -8.605660438537598, -0.4735637903213501, 2.6741855144500732, -5.359188079833984, -2.6673784255981445, 0.6660736799240112, 15.443212509155273, 4.740597724914551, -3.4725306034088135, 11.592561721801758, -2.05450701713562, 1.7361239194869995, -8.26533031463623, -9.304476737976074, 5.406835079193115, -1.5180232524871826, -7.746610641479492, -6.089605331420898, 0.07112561166286469, -0.34904858469963074, -8.649889945983887, -9.998958587646484, -2.5648481845855713, -0.5399898886680603, 2.6018145084381104, -0.31927648186683655, -1.8815231323242188, -2.0721378326416016, -3.4105639457702637, -8.299802780151367, 1.4836379289627075, -15.366002082824707, -8.288193702697754, 3.884773015975952, -3.4876506328582764, 7.362995624542236, 0.4657321572303772, 3.1326000690460205, 12.438883781433105, -1.8337029218673706, 4.532927513122559, 2.726433277130127, 10.145345687866211, -6.521956920623779, 2.8971481323242188, -3.3925881385803223, 5.079156398773193, 7.759725093841553, 4.677562236785889, 5.8457818031311035, 2.4023921489715576, 7.707108974456787, 3.9711389541625977, -6.390035152435303, 6.126871109008789, -3.776031017303467, -11.118141174316406]}}\n  [2022-08-01 09:01:27,094] [    INFO] - Response time 4.941739 s.\n  ```\n\n* Python API\n\n  ``` python\n  from paddlespeech.server.bin.paddlespeech_client import VectorClientExecutor\n  import json\n\n  vectorclient_executor = VectorClientExecutor()\n  res = vectorclient_executor(\n      input=\"85236145389.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      task=\"spk\")\n  print(res.json())\n  ```\n\n  Output:\n\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'vec': [1.4217487573623657, 5.626248836517334, -5.342073440551758, 1.177390217781067, 3.308061122894287, 1.7565997838974, 5.1678876876831055, 10.806346893310547, -3.822679042816162, -5.614130973815918, 2.6238481998443604, -0.8072965741157532, 1.963512659072876, -7.312864780426025, 0.011034967377781868, -9.723127365112305, 0.661963164806366, -6.976816654205322, 10.213465690612793, 7.494767189025879, 2.9105641841888428, 3.894925117492676, 3.7999846935272217, 7.106173992156982, 16.905324935913086, -7.149376392364502, 8.733112335205078, 3.423002004623413, -4.831653118133545, -11.403371810913086, 11.232216835021973, 7.127464771270752, -4.282831192016602, 2.4523589611053467, -5.13075065612793, -18.17765998840332, -2.611666440963745, -11.00034236907959, -6.731431007385254, 1.6564655303955078, 0.7618184685707092, 1.1253058910369873, -2.0838277339935303, 4.725739002227783, -8.782590866088867, -3.5398736000061035, 3.8142387866973877, 5.142062664031982, 2.162053346633911, 4.09642219543457, -6.416221618652344, 12.747454643249512, 1.9429889917373657, -15.152948379516602, 6.417416572570801, 16.097013473510742, -9.716649055480957, -1.9920448064804077, -3.364956855773926, -1.8719490766525269, 11.567351341247559, 3.6978795528411865, 11.258269309997559, 7.442364692687988, 9.183405876159668, 4.528151512145996, -1.2417811155319214, 4.395910263061523, 6.672768592834473, 5.889888763427734, 7.627115249633789, -0.6692016124725342, -11.889703750610352, -9.208883285522461, -7.427401542663574, -3.777655601501465, 6.917237758636475, -9.848749160766602, -2.094479560852051, -5.1351189613342285, 0.49564215540885925, 9.317541122436523, -5.9141845703125, -1.809845209121704, -0.11738205701112747, -7.169270992279053, -1.0578246116638184, -5.721685886383057, -5.117387294769287, 16.137670516967773, -4.473618984222412, 7.66243314743042, -0.5538089871406555, 9.631582260131836, -6.470466613769531, -8.54850959777832, 4.371622085571289, -0.7970349192619324, 4.479003429412842, -2.9758646488189697, 3.2721707820892334, 2.8382749557495117, 5.1345953941345215, -9.19078254699707, -0.5657423138618469, -4.874573230743408, 2.316561460494995, -5.984307289123535, -2.1798791885375977, 0.35541653633117676, -0.3178458511829376, 9.493547439575195, 2.114448070526123, 4.358088493347168, -12.089820861816406, 8.451695442199707, -7.925461769104004, 4.624246120452881, 4.428938388824463, 18.691999435424805, -2.620460033416748, -5.149182319641113, -0.3582168221473694, 8.488557815551758, 4.98148250579834, -9.326834678649902, -2.2544236183166504, 6.64176607131958, 1.2119656801223755, 10.977132797241211, 16.55504035949707, 3.323848247528076, 9.55185317993164, -1.6677050590515137, -0.7953923940658569, -8.605660438537598, -0.4735637903213501, 2.6741855144500732, -5.359188079833984, -2.6673784255981445, 0.6660736799240112, 15.443212509155273, 4.740597724914551, -3.4725306034088135, 11.592561721801758, -2.05450701713562, 1.7361239194869995, -8.26533031463623, -9.304476737976074, 5.406835079193115, -1.5180232524871826, -7.746610641479492, -6.089605331420898, 0.07112561166286469, -0.34904858469963074, -8.649889945983887, -9.998958587646484, -2.5648481845855713, -0.5399898886680603, 2.6018145084381104, -0.31927648186683655, -1.8815231323242188, -2.0721378326416016, -3.4105639457702637, -8.299802780151367, 1.4836379289627075, -15.366002082824707, -8.288193702697754, 3.884773015975952, -3.4876506328582764, 7.362995624542236, 0.4657321572303772, 3.1326000690460205, 12.438883781433105, -1.8337029218673706, 4.532927513122559, 2.726433277130127, 10.145345687866211, -6.521956920623779, 2.8971481323242188, -3.3925881385803223, 5.079156398773193, 7.759725093841553, 4.677562236785889, 5.8457818031311035, 2.4023921489715576, 7.707108974456787, 3.9711389541625977, -6.390035152435303, 6.126871109008789, -3.776031017303467, -11.118141174316406]}}\n  ```\n\n#### 7.2 Get the score between speaker audio embedding\n\n**Note:** The response time will be slightly longer when using the client for the first time\n\n- Command Line (Recommended)\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ``` bash\n  paddlespeech_client vector --task score  --server_ip 127.0.0.1 --port 8090 --enroll 85236145389.wav --test 123456789.wav\n  ```\n\n  Usage:\n\n  ``` bash\n  paddlespeech_client vector --help\n  ```\n\n  Arguments:\n    * server_ip: server ip. Default: 127.0.0.1\n    * port: server port. Default: 8090\n    * input(required): Input text to generate.\n    * task: the task of vector, can be use 'spk' or 'score。If get the score, this must be 'score' parameter.\n    * enroll: enroll audio\n    * test: test audio\n  \n  Output:\n\n  ```text\n  [2022-08-01 09:04:42,275] [    INFO] - vector score http client start\n  [2022-08-01 09:04:42,275] [    INFO] - enroll audio: 85236145389.wav, test audio: 123456789.wav\n  [2022-08-01 09:04:42,275] [    INFO] - endpoint: http://127.0.0.1:8090/paddlespeech/vector/score\n  [2022-08-01 09:04:44,611] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'score': 0.4292638897895813}}\n  [2022-08-01 09:04:44,611] [    INFO] - Response time 2.336258 s.\n  ```\n\n* Python API\n\n  ``` python \n  from paddlespeech.server.bin.paddlespeech_client import VectorClientExecutor\n  import json\n\n  vectorclient_executor = VectorClientExecutor()\n  res = vectorclient_executor(\n      input=None,\n      enroll_audio=\"85236145389.wav\",\n      test_audio=\"123456789.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      task=\"score\")\n  print(res.json())\n  ```\n\n  Output:\n\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'score': 0.4292638897895813}}\n  ```\n\n### 8. Punctuation prediction\n  \n**Note:** The response time will be slightly longer when using the client for the first time\n\n- Command Line (Recommended)\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n   ``` bash\n   paddlespeech_client text --server_ip 127.0.0.1 --port 8090 --input \"我认为跑步最重要的就是给我带来了身体健康\"\n   ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_client text --help\n  ```\n  Arguments:\n  - `server_ip`: server ip. Default: 127.0.0.1\n  - `port`: server port. Default: 8090\n  - `input`(required): Input text to get punctuation.\n\n  Output:\n  ```text\n  [2022-05-09 18:19:04,397] [    INFO] - The punc text: 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-09 18:19:04,397] [    INFO] - Response time 0.092407 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TextClientExecutor\n\n  textclient_executor = TextClientExecutor()\n  res = textclient_executor(\n      input=\"我认为跑步最重要的就是给我带来了身体健康\",\n      server_ip=\"127.0.0.1\",\n      port=8090,)\n  print(res)\n  ```\n\n  Output:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康。\n  ```\n\n## Models supported by the service\n### ASR model\nGet all models supported by the ASR service via `paddlespeech_server stats --task asr`, where static models can be used for paddle inference inference.\n\n### TTS model\nGet all models supported by the TTS service via `paddlespeech_server stats --task tts`, where static models can be used for paddle inference inference.\n\n### CLS model\nGet all models supported by the CLS service via `paddlespeech_server stats --task cls`, where static models can be used for paddle inference inference.\n\n### Vector model\nGet all models supported by the TTS service via `paddlespeech_server stats --task vector`, where static models can be used for paddle inference inference.\n\n### Text model\nGet all models supported by the CLS service via `paddlespeech_server stats --task text`, where static models can be used for paddle inference inference.\n"
  },
  {
    "path": "demos/speech_server/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 语音服务\n\n## 介绍\n\n这个 demo 是一个启动离线语音服务和访问服务的实现。它可以通过使用 `paddlespeech_server` 和 `paddlespeech_client` 的单个命令或 python 的几行代码来实现。\n\n\n服务接口定义请参考:\n- [PaddleSpeech Server RESTful API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-RESTful-API)\n\n## 使用方法\n### 1. 安装\n请看 [安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\n推荐使用 **paddlepaddle 2.4rc** 或以上版本。\n\n你可以从简单，中等，困难 几种方式中选择一种方式安装 PaddleSpeech。\n\n**如果使用简单模式安装，需要自行准备 yaml 文件，可参考 conf 目录下的 yaml 文件。**\n\n### 2. 准备配置文件\n配置文件可参见 `conf/application.yaml` 。\n其中，`engine_list` 表示即将启动的服务将会包含的语音引擎，格式为 <语音任务>_<引擎类型>。\n\n目前服务集成的语音任务有： asr (语音识别)、tts (语音合成)、cls (音频分类)、vector (声纹识别)以及 text (文本处理)。\n\n目前引擎类型支持两种形式：python 及 inference (Paddle Inference)\n**注意：** 如果在容器里可正常启动服务，但客户端访问 ip 不可达，可尝试将配置文件中 `host` 地址换成本地 ip 地址。\n\n### 3. 服务端使用方法\n- 命令行 (推荐使用)\n\n  ```bash\n  # 启动服务\n  paddlespeech_server start --config_file ./conf/application.yaml\n  ```\n\n  > **注意：** 中英文混合语音识别请使用  `./conf/conformer_talcs_application.yaml` 配置文件\n\n  使用方法：\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  参数:\n  - `config_file`: 服务的配置文件，默认： ./conf/application.yaml\n  - `log_file`: log 文件. 默认：./log/paddlespeech.log\n\n  输出:\n  ```text\n  [2022-02-23 11:17:32] [INFO] [server.py:64] Started server process [6384]\n  INFO:     Waiting for application startup.\n  [2022-02-23 11:17:32] [INFO] [on.py:26] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-02-23 11:17:32] [INFO] [on.py:38] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-02-23 11:17:32] [INFO] [server.py:204] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  输出：\n  ```text\n  INFO:     Started server process [529]\n  [2022-02-23 14:57:56] [INFO] [server.py:64] Started server process [529]\n  INFO:     Waiting for application startup.\n  [2022-02-23 14:57:56] [INFO] [on.py:26] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-02-23 14:57:56] [INFO] [on.py:38] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-02-23 14:57:56] [INFO] [server.py:204] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n\n\n### 4. ASR 客户端使用方法\n\nASR 客户端的输入是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载 ASR 客户端的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/ch_zh_mix.wav\n```\n\n**注意：** 初次使用客户端时响应时间会略长\n- 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n  \n  # 中英文混合语音识别 , 请使用  `./conf/conformer_talcs_application.yaml` 配置文件\n  paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input ./ch_zh_mix.wav\n  ```\n\n  使用帮助:\n\n  ```bash\n  paddlespeech_client asr --help\n  ```\n\n  参数:\n  - `server_ip`: 服务端 ip 地址，默认: 127.0.0.1。\n  - `port`: 服务端口，默认: 8090。\n  - `input`(必须输入): 用于识别的音频文件。\n  - `sample_rate`: 音频采样率，默认值：16000。\n  - `lang`: 模型语言，默认值：zh_cn。\n  - `audio_format`: 音频格式，默认值：wav。\n\n  输出:\n  ```text\n  [2022-08-01 07:54:01,646] [    INFO] - ASR result: 我认为跑步最重要的就是给我带来了身体健康\n  [2022-08-01 07:54:01,646] [    INFO] - Response time 4.898965 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ASRClientExecutor\n\n  asrclient_executor = ASRClientExecutor()\n  res = asrclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      sample_rate=16000,\n      lang=\"zh_cn\",\n      audio_format=\"wav\")\n  print(res)\n  ```\n\n  输出:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康\n  ```\n \n### 5. TTS 客户端使用方法\n**注意：** 初次使用客户端时响应时间会略长\n- 命令行 (推荐使用)\n  \n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n  ```\n  使用帮助:\n\n  ```bash\n  paddlespeech_client tts --help\n  ```\n\n  参数:\n  - `server_ip`: 服务端ip地址，默认: 127.0.0.1。\n  - `port`: 服务端口，默认: 8090。\n  - `input`(必须输入): 待合成的文本。\n  - `spk_id`: 说话人 id，用于多说话人语音合成，默认值： 0。\n  - `speed`: 音频速度，该值应设置在 0 到 3 之间。 默认值：1.0\n  - `volume`: 音频音量，该值应设置在 0 到 3 之间。 默认值： 1.0\n  - `sample_rate`: 采样率，可选 [0, 8000, 16000]，默认与模型相同。 默认值：0\n  - `output`: 输出音频的路径， 默认值：None，表示不保存音频到本地。\n\n  输出:\n  ```text\n  [2022-02-23 15:20:37,875] [    INFO] - Save synthesized audio successfully on output.wav.\n  [2022-02-23 15:20:37,875] [    INFO] - Audio duration: 3.612500 s.\n  [2022-02-23 15:20:37,875] [    INFO] - Response time: 0.348050 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSClientExecutor\n  import json\n\n  ttsclient_executor = TTSClientExecutor()\n  res = ttsclient_executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      spk_id=0,\n      speed=1.0,\n      volume=1.0,\n      sample_rate=0,\n      output=\"./output.wav\")\n\n  response_dict = res.json()\n  print(response_dict[\"message\"])\n  print(\"Save synthesized audio successfully on %s.\" % (response_dict['result']['save_path']))\n  print(\"Audio duration: %f s.\" %(response_dict['result']['duration']))\n  ```\n\n  输出:\n  ```text\n  {'description': 'success.'}\n  Save synthesized audio successfully on ./output.wav.\n  Audio duration: 3.612500 s.\n  ```\n\n### 6. CLS 客户端使用方法\n\n可以下载 CLS 客户端的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n**注意：** 初次使用客户端时响应时间会略长\n\n- 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n  ```\n\n  使用帮助:\n  \n  ```bash\n  paddlespeech_client cls --help\n  ```\n  参数:\n  - `server_ip`: 服务端 ip 地址，默认: 127.0.0.1。\n  - `port`: 服务端口，默认: 8090。\n  - `input`(必须输入): 用于分类的音频文件。\n  - `topk`: 分类结果的topk。\n\n  输出:\n  ```text\n  [2022-03-09 20:44:39,974] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'topk': 1, 'results': [{'class_name': 'Speech', 'prob': 0.9027184844017029}]}}\n  [2022-03-09 20:44:39,975] [    INFO] - Response time 0.104360 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import CLSClientExecutor\n  import json\n\n  clsclient_executor = CLSClientExecutor()\n  res = clsclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      topk=1)\n  print(res.json())\n  ```\n\n  输出:\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'topk': 1, 'results': [{'class_name': 'Speech', 'prob': 0.9027184844017029}]}}\n  ```\n\n### 7. 声纹客户端使用方法\n\n可以下载声纹客户端的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n```\n\n#### 7.1 提取声纹特征\n**注意：** 初次使用客户端时响应时间会略长\n* 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client vector --task spk  --server_ip 127.0.0.1 --port 8090 --input 85236145389.wav\n  ```\n\n  使用帮助:\n\n  ``` bash\n  paddlespeech_client vector --help\n  ```\n  参数:\n  * server_ip: 服务端ip地址，默认: 127.0.0.1。\n  * port: 服务端口，默认: 8090。\n  * input(必须输入): 用于识别的音频文件。\n  * task: vector 的任务，可选spk或者score。默认是 spk。\n  * enroll: 注册音频；。\n  * test: 测试音频。\n\n  输出:\n  ```text\n  [2022-08-01 09:01:22,151] [    INFO] - vector http client start\n  [2022-08-01 09:01:22,152] [    INFO] - the input audio: 85236145389.wav\n  [2022-08-01 09:01:22,152] [    INFO] - endpoint: http://127.0.0.1:8090/paddlespeech/vector\n  [2022-08-01 09:01:27,093] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'vec': [1.4217487573623657, 5.626248836517334, -5.342073440551758, 1.177390217781067, 3.308061122894287, 1.7565997838974, 5.1678876876831055, 10.806346893310547, -3.822679042816162, -5.614130973815918, 2.6238481998443604, -0.8072965741157532, 1.963512659072876, -7.312864780426025, 0.011034967377781868, -9.723127365112305, 0.661963164806366, -6.976816654205322, 10.213465690612793, 7.494767189025879, 2.9105641841888428, 3.894925117492676, 3.7999846935272217, 7.106173992156982, 16.905324935913086, -7.149376392364502, 8.733112335205078, 3.423002004623413, -4.831653118133545, -11.403371810913086, 11.232216835021973, 7.127464771270752, -4.282831192016602, 2.4523589611053467, -5.13075065612793, -18.17765998840332, -2.611666440963745, -11.00034236907959, -6.731431007385254, 1.6564655303955078, 0.7618184685707092, 1.1253058910369873, -2.0838277339935303, 4.725739002227783, -8.782590866088867, -3.5398736000061035, 3.8142387866973877, 5.142062664031982, 2.162053346633911, 4.09642219543457, -6.416221618652344, 12.747454643249512, 1.9429889917373657, -15.152948379516602, 6.417416572570801, 16.097013473510742, -9.716649055480957, -1.9920448064804077, -3.364956855773926, -1.8719490766525269, 11.567351341247559, 3.6978795528411865, 11.258269309997559, 7.442364692687988, 9.183405876159668, 4.528151512145996, -1.2417811155319214, 4.395910263061523, 6.672768592834473, 5.889888763427734, 7.627115249633789, -0.6692016124725342, -11.889703750610352, -9.208883285522461, -7.427401542663574, -3.777655601501465, 6.917237758636475, -9.848749160766602, -2.094479560852051, -5.1351189613342285, 0.49564215540885925, 9.317541122436523, -5.9141845703125, -1.809845209121704, -0.11738205701112747, -7.169270992279053, -1.0578246116638184, -5.721685886383057, -5.117387294769287, 16.137670516967773, -4.473618984222412, 7.66243314743042, -0.5538089871406555, 9.631582260131836, -6.470466613769531, -8.54850959777832, 4.371622085571289, -0.7970349192619324, 4.479003429412842, -2.9758646488189697, 3.2721707820892334, 2.8382749557495117, 5.1345953941345215, -9.19078254699707, -0.5657423138618469, -4.874573230743408, 2.316561460494995, -5.984307289123535, -2.1798791885375977, 0.35541653633117676, -0.3178458511829376, 9.493547439575195, 2.114448070526123, 4.358088493347168, -12.089820861816406, 8.451695442199707, -7.925461769104004, 4.624246120452881, 4.428938388824463, 18.691999435424805, -2.620460033416748, -5.149182319641113, -0.3582168221473694, 8.488557815551758, 4.98148250579834, -9.326834678649902, -2.2544236183166504, 6.64176607131958, 1.2119656801223755, 10.977132797241211, 16.55504035949707, 3.323848247528076, 9.55185317993164, -1.6677050590515137, -0.7953923940658569, -8.605660438537598, -0.4735637903213501, 2.6741855144500732, -5.359188079833984, -2.6673784255981445, 0.6660736799240112, 15.443212509155273, 4.740597724914551, -3.4725306034088135, 11.592561721801758, -2.05450701713562, 1.7361239194869995, -8.26533031463623, -9.304476737976074, 5.406835079193115, -1.5180232524871826, -7.746610641479492, -6.089605331420898, 0.07112561166286469, -0.34904858469963074, -8.649889945983887, -9.998958587646484, -2.5648481845855713, -0.5399898886680603, 2.6018145084381104, -0.31927648186683655, -1.8815231323242188, -2.0721378326416016, -3.4105639457702637, -8.299802780151367, 1.4836379289627075, -15.366002082824707, -8.288193702697754, 3.884773015975952, -3.4876506328582764, 7.362995624542236, 0.4657321572303772, 3.1326000690460205, 12.438883781433105, -1.8337029218673706, 4.532927513122559, 2.726433277130127, 10.145345687866211, -6.521956920623779, 2.8971481323242188, -3.3925881385803223, 5.079156398773193, 7.759725093841553, 4.677562236785889, 5.8457818031311035, 2.4023921489715576, 7.707108974456787, 3.9711389541625977, -6.390035152435303, 6.126871109008789, -3.776031017303467, -11.118141174316406]}}\n  [2022-08-01 09:01:27,094] [    INFO] - Response time 4.941739 s.\n  ```\n\n* Python API\n\n  ``` python\n  from paddlespeech.server.bin.paddlespeech_client import VectorClientExecutor\n  import json\n\n  vectorclient_executor = VectorClientExecutor()\n  res = vectorclient_executor(\n      input=\"85236145389.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      task=\"spk\")\n  print(res.json())\n  ```\n\n  输出:\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'vec': [1.4217487573623657, 5.626248836517334, -5.342073440551758, 1.177390217781067, 3.308061122894287, 1.7565997838974, 5.1678876876831055, 10.806346893310547, -3.822679042816162, -5.614130973815918, 2.6238481998443604, -0.8072965741157532, 1.963512659072876, -7.312864780426025, 0.011034967377781868, -9.723127365112305, 0.661963164806366, -6.976816654205322, 10.213465690612793, 7.494767189025879, 2.9105641841888428, 3.894925117492676, 3.7999846935272217, 7.106173992156982, 16.905324935913086, -7.149376392364502, 8.733112335205078, 3.423002004623413, -4.831653118133545, -11.403371810913086, 11.232216835021973, 7.127464771270752, -4.282831192016602, 2.4523589611053467, -5.13075065612793, -18.17765998840332, -2.611666440963745, -11.00034236907959, -6.731431007385254, 1.6564655303955078, 0.7618184685707092, 1.1253058910369873, -2.0838277339935303, 4.725739002227783, -8.782590866088867, -3.5398736000061035, 3.8142387866973877, 5.142062664031982, 2.162053346633911, 4.09642219543457, -6.416221618652344, 12.747454643249512, 1.9429889917373657, -15.152948379516602, 6.417416572570801, 16.097013473510742, -9.716649055480957, -1.9920448064804077, -3.364956855773926, -1.8719490766525269, 11.567351341247559, 3.6978795528411865, 11.258269309997559, 7.442364692687988, 9.183405876159668, 4.528151512145996, -1.2417811155319214, 4.395910263061523, 6.672768592834473, 5.889888763427734, 7.627115249633789, -0.6692016124725342, -11.889703750610352, -9.208883285522461, -7.427401542663574, -3.777655601501465, 6.917237758636475, -9.848749160766602, -2.094479560852051, -5.1351189613342285, 0.49564215540885925, 9.317541122436523, -5.9141845703125, -1.809845209121704, -0.11738205701112747, -7.169270992279053, -1.0578246116638184, -5.721685886383057, -5.117387294769287, 16.137670516967773, -4.473618984222412, 7.66243314743042, -0.5538089871406555, 9.631582260131836, -6.470466613769531, -8.54850959777832, 4.371622085571289, -0.7970349192619324, 4.479003429412842, -2.9758646488189697, 3.2721707820892334, 2.8382749557495117, 5.1345953941345215, -9.19078254699707, -0.5657423138618469, -4.874573230743408, 2.316561460494995, -5.984307289123535, -2.1798791885375977, 0.35541653633117676, -0.3178458511829376, 9.493547439575195, 2.114448070526123, 4.358088493347168, -12.089820861816406, 8.451695442199707, -7.925461769104004, 4.624246120452881, 4.428938388824463, 18.691999435424805, -2.620460033416748, -5.149182319641113, -0.3582168221473694, 8.488557815551758, 4.98148250579834, -9.326834678649902, -2.2544236183166504, 6.64176607131958, 1.2119656801223755, 10.977132797241211, 16.55504035949707, 3.323848247528076, 9.55185317993164, -1.6677050590515137, -0.7953923940658569, -8.605660438537598, -0.4735637903213501, 2.6741855144500732, -5.359188079833984, -2.6673784255981445, 0.6660736799240112, 15.443212509155273, 4.740597724914551, -3.4725306034088135, 11.592561721801758, -2.05450701713562, 1.7361239194869995, -8.26533031463623, -9.304476737976074, 5.406835079193115, -1.5180232524871826, -7.746610641479492, -6.089605331420898, 0.07112561166286469, -0.34904858469963074, -8.649889945983887, -9.998958587646484, -2.5648481845855713, -0.5399898886680603, 2.6018145084381104, -0.31927648186683655, -1.8815231323242188, -2.0721378326416016, -3.4105639457702637, -8.299802780151367, 1.4836379289627075, -15.366002082824707, -8.288193702697754, 3.884773015975952, -3.4876506328582764, 7.362995624542236, 0.4657321572303772, 3.1326000690460205, 12.438883781433105, -1.8337029218673706, 4.532927513122559, 2.726433277130127, 10.145345687866211, -6.521956920623779, 2.8971481323242188, -3.3925881385803223, 5.079156398773193, 7.759725093841553, 4.677562236785889, 5.8457818031311035, 2.4023921489715576, 7.707108974456787, 3.9711389541625977, -6.390035152435303, 6.126871109008789, -3.776031017303467, -11.118141174316406]}}\n  ```\n\n#### 7.2 音频声纹打分\n\n**注意：** 初次使用客户端时响应时间会略长\n* 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ``` bash\n  paddlespeech_client vector --task score  --server_ip 127.0.0.1 --port 8090 --enroll 85236145389.wav --test 123456789.wav\n  ```\n\n  使用帮助:\n\n  ``` bash\n  paddlespeech_client vector --help\n  ```\n\n  参数:\n  * server_ip: 服务端ip地址，默认: 127.0.0.1。\n  * port: 服务端口，默认: 8090。\n  * input(必须输入): 用于识别的音频文件。\n  * task: vector 的任务，可选spk或者score。默认是 spk。\n  * enroll: 注册音频；。\n  * test: 测试音频。\n\n  输出:\n  ```text\n  [2022-08-01 09:04:42,275] [    INFO] - vector score http client start\n  [2022-08-01 09:04:42,275] [    INFO] - enroll audio: 85236145389.wav, test audio: 123456789.wav\n  [2022-08-01 09:04:42,275] [    INFO] - endpoint: http://127.0.0.1:8090/paddlespeech/vector/score\n  [2022-08-01 09:04:44,611] [    INFO] - {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'score': 0.4292638897895813}}\n  [2022-08-01 09:04:44,611] [    INFO] - Response time 2.336258 s.\n  ```\n\n* Python API\n\n  ```python \n  from paddlespeech.server.bin.paddlespeech_client import VectorClientExecutor\n  import json\n\n  vectorclient_executor = VectorClientExecutor()\n  res = vectorclient_executor(\n      input=None,\n      enroll_audio=\"85236145389.wav\",\n      test_audio=\"123456789.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      task=\"score\")\n  print(res.json())\n  ```\n\n  输出:\n  ```text\n  {'success': True, 'code': 200, 'message': {'description': 'success'}, 'result': {'score': 0.4292638897895813}}\n  ```\n\n### 8. 标点预测\n  \n  **注意：** 初次使用客户端时响应时间会略长\n- 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ``` bash\n  paddlespeech_client text --server_ip 127.0.0.1 --port 8090 --input \"我认为跑步最重要的就是给我带来了身体健康\"\n  ```\n\n  使用帮助:\n  \n  ```bash\n  paddlespeech_client text --help\n  ```\n  参数:\n  - `server_ip`: 服务端ip地址，默认: 127.0.0.1。\n  - `port`: 服务端口，默认: 8090。\n  - `input`(必须输入): 用于标点预测的文本内容。\n\n  输出:\n  ```text\n  [2022-05-09 18:19:04,397] [    INFO] - The punc text: 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-09 18:19:04,397] [    INFO] - Response time 0.092407 s.\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TextClientExecutor\n\n  textclient_executor = TextClientExecutor()\n  res = textclient_executor(\n      input=\"我认为跑步最重要的就是给我带来了身体健康\",\n      server_ip=\"127.0.0.1\",\n      port=8090,)\n  print(res)\n  ```\n\n  输出:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康。\n  ```\n\n## 服务支持的模型\n### ASR 支持的模型\n通过 `paddlespeech_server stats --task asr` 获取 ASR 服务支持的所有模型，其中静态模型可用于 paddle inference 推理。 \n\n### TTS 支持的模型\n通过 `paddlespeech_server stats --task tts` 获取 TTS 服务支持的所有模型，其中静态模型可用于 paddle inference 推理。\n\n### CLS 支持的模型\n通过 `paddlespeech_server stats --task cls` 获取 CLS 服务支持的所有模型，其中静态模型可用于 paddle inference 推理。\n\n### Vector 支持的模型\n通过 `paddlespeech_server stats --task vector` 获取 Vector 服务支持的所有模型。\n\n### Text支持的模型\n通过 `paddlespeech_server stats --task text` 获取 Text 服务支持的所有模型。\n"
  },
  {
    "path": "demos/speech_server/asr_client.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n"
  },
  {
    "path": "demos/speech_server/cls_client.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input ./zh.wav --topk 1\n"
  },
  {
    "path": "demos/speech_server/conf/application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Offline Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_python', 'asr_inference', 'tts_python', 'tts_inference', 'cls_python', 'cls_inference', 'text_python', 'vector_python']\nprotocol: 'http'\nengine_list: ['asr_python', 'tts_python', 'cls_python', 'text_python', 'vector_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: python #######################\nasr_python:\n    model: 'conformer_wenetspeech'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    decode_method: 'attention_rescoring'\n    force_yes: True\n    device:  # set 'gpu:id' or 'cpu'\n\n################### speech task: asr; engine_type: inference #######################\nasr_inference:\n    # model_type choices=['deepspeech2offline_aishell']\n    model_type: 'deepspeech2offline_aishell'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: python #######################\ntts_python:\n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc',\n    #                             'fastspeech2_ljspeech', 'fastspeech2_aishell3',\n    #                             'fastspeech2_vctk', 'fastspeech2_mix',\n    #                             'tacotron2_csmsc', 'tacotron2_ljspeech']\n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'pwgan_ljspeech', 'pwgan_aishell3',\n    #                        'pwgan_vctk', 'mb_melgan_csmsc', 'style_melgan_csmsc',\n    #                        'hifigan_csmsc', 'hifigan_ljspeech', 'hifigan_aishell3',\n    #                        'hifigan_vctk', 'wavernn_csmsc']\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: tts; engine_type: inference #######################\ntts_inference:\n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc']\n    am: 'fastspeech2_csmsc'   \n    am_model: # the pdmodel file of your am static model (XX.pdmodel)\n    am_params: # the pdiparams file of your am static model (XX.pdipparams)\n    am_sample_rate: 24000\n    phones_dict: \n    tones_dict: \n    speaker_dict: \n\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'mb_melgan_csmsc','hifigan_csmsc']\n    voc: 'mb_melgan_csmsc'\n    voc_model: # the pdmodel file of your vocoder static model (XX.pdmodel)\n    voc_params: # the pdiparams file of your vocoder static model (XX.pdipparams)\n    voc_sample_rate: 24000\n\n    voc_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'  \n        switch_ir_optim: True  \n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # others\n    lang: 'zh'\n\n\n################################### CLS #########################################\n################### speech task: cls; engine_type: python #######################\ncls_python:\n    # model choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model: 'panns_cnn14'\n    cfg_path: # [optional] Config of cls task.\n    ckpt_path: # [optional] Checkpoint file of model.\n    label_file: # [optional] Label file of cls task.\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: cls; engine_type: inference #######################\ncls_inference:\n    # model_type choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model_type: 'panns_cnn14' \n    cfg_path: \n    model_path:  # the pdmodel file of am static model [optional]\n    params_path:  # the pdiparams file of am static model [optional]\n    label_file:  # [optional] Label file of cls task.\n\n    predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### Text #########################################\n################### text task: punc; engine_type: python #######################\ntext_python:\n    task: punc\n    model_type: 'ernie_linear_p3_wudao'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    vocab_file: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################################### Vector ######################################\n################### Vector task: spk; engine_type: python #######################\nvector_python:\n    task: spk\n    model_type: 'ecapatdnn_voxceleb12'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n"
  },
  {
    "path": "demos/speech_server/conf/conformer_talcs_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Offline Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_python', 'asr_inference', 'tts_python', 'tts_inference', 'cls_python', 'cls_inference', 'text_python', 'vector_python']\nprotocol: 'http'\nengine_list: ['asr_python', 'tts_python', 'cls_python', 'text_python', 'vector_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: python #######################\nasr_python:\n    model: 'conformer_talcs'\n    lang: 'zh_en'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    decode_method: 'attention_rescoring'\n    force_yes: True\n    codeswitch: True\n    device:  # set 'gpu:id' or 'cpu'\n\n################### speech task: asr; engine_type: inference #######################\nasr_inference:\n    # model_type choices=['deepspeech2offline_aishell']\n    model_type: 'deepspeech2offline_aishell'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: python #######################\ntts_python:\n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc',\n    #                             'fastspeech2_ljspeech', 'fastspeech2_aishell3',\n    #                             'fastspeech2_vctk', 'fastspeech2_mix',\n    #                             'tacotron2_csmsc', 'tacotron2_ljspeech']\n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'pwgan_ljspeech', 'pwgan_aishell3',\n    #                        'pwgan_vctk', 'mb_melgan_csmsc', 'style_melgan_csmsc',\n    #                        'hifigan_csmsc', 'hifigan_ljspeech', 'hifigan_aishell3',\n    #                        'hifigan_vctk', 'wavernn_csmsc']\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: tts; engine_type: inference #######################\ntts_inference:\n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc']\n    am: 'fastspeech2_csmsc'   \n    am_model: # the pdmodel file of your am static model (XX.pdmodel)\n    am_params: # the pdiparams file of your am static model (XX.pdipparams)\n    am_sample_rate: 24000\n    phones_dict: \n    tones_dict: \n    speaker_dict: \n\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'mb_melgan_csmsc','hifigan_csmsc']\n    voc: 'mb_melgan_csmsc'\n    voc_model: # the pdmodel file of your vocoder static model (XX.pdmodel)\n    voc_params: # the pdiparams file of your vocoder static model (XX.pdipparams)\n    voc_sample_rate: 24000\n\n    voc_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'  \n        switch_ir_optim: True  \n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # others\n    lang: 'zh'\n\n\n################################### CLS #########################################\n################### speech task: cls; engine_type: python #######################\ncls_python:\n    # model choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model: 'panns_cnn14'\n    cfg_path: # [optional] Config of cls task.\n    ckpt_path: # [optional] Checkpoint file of model.\n    label_file: # [optional] Label file of cls task.\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: cls; engine_type: inference #######################\ncls_inference:\n    # model_type choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model_type: 'panns_cnn14' \n    cfg_path: \n    model_path:  # the pdmodel file of am static model [optional]\n    params_path:  # the pdiparams file of am static model [optional]\n    label_file:  # [optional] Label file of cls task.\n\n    predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### Text #########################################\n################### text task: punc; engine_type: python #######################\ntext_python:\n    task: punc\n    model_type: 'ernie_linear_p3_wudao'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    vocab_file: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################################### Vector ######################################\n################### Vector task: spk; engine_type: python #######################\nvector_python:\n    task: spk\n    model_type: 'ecapatdnn_voxceleb12'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n"
  },
  {
    "path": "demos/speech_server/server.sh",
    "content": "#!/bin/bash\n\npaddlespeech_server start --config_file ./conf/application.yaml &> server.log &\n"
  },
  {
    "path": "demos/speech_server/sid_client.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/85236145389.wav\nwget -c https://paddlespeech.cdn.bcebos.com/vector/audio/123456789.wav\n\n# sid extract\npaddlespeech_client vector --server_ip 127.0.0.1 --port 8090 --task spk --input ./85236145389.wav\n\n# sid score\npaddlespeech_client vector --server_ip 127.0.0.1 --port 8090 --task score --enroll ./85236145389.wav --test ./123456789.wav\n"
  },
  {
    "path": "demos/speech_server/start_multi_progress_server.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport warnings\n\nimport uvicorn\nfrom fastapi import FastAPI\nfrom starlette.middleware.cors import CORSMiddleware\n\nfrom paddlespeech.server.engine.engine_pool import init_engine_pool\nfrom paddlespeech.server.restful.api import setup_router as setup_http_router\nfrom paddlespeech.server.utils.config import get_config\nfrom paddlespeech.server.ws.api import setup_router as setup_ws_router\nwarnings.filterwarnings(\"ignore\")\nimport sys\n\napp = FastAPI(\n    title=\"PaddleSpeech Serving API\", description=\"Api\", version=\"0.0.1\")\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"])\n\n# change yaml file here\nconfig_file = \"./conf/application.yaml\"\nconfig = get_config(config_file)\n\n# init engine\nif not init_engine_pool(config):\n    print(\"Failed to init engine.\")\n    sys.exit(-1)\n\n# get api_router\napi_list = list(engine.split(\"_\")[0] for engine in config.engine_list)\nif config.protocol == \"websocket\":\n    api_router = setup_ws_router(api_list)\nelif config.protocol == \"http\":\n    api_router = setup_http_router(api_list)\nelse:\n    raise Exception(\"unsupported protocol\")\n    sys.exit(-1)\n\n# app needs to operate outside the main function \napp.include_router(api_router)\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(add_help=True)\n    parser.add_argument(\n        \"--workers\", type=int, help=\"workers of server\", default=1)\n    args = parser.parse_args()\n\n    uvicorn.run(\n        \"start_multi_progress_server:app\",\n        host=config.host,\n        port=config.port,\n        debug=True,\n        workers=args.workers)\n"
  },
  {
    "path": "demos/speech_server/text_client.sh",
    "content": "#!/bin/bash\n\n\npaddlespeech_client text --server_ip 127.0.0.1 --port 8090 --input 今天的天气真好啊你下午有空吗我想约你一起去吃饭\n"
  },
  {
    "path": "demos/speech_server/tts_client.sh",
    "content": "#!/bin/bash\n\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n"
  },
  {
    "path": "demos/speech_ssl/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# Speech SSL (Self-Supervised Learning)\n\n## Introduction\nSpeech SSL, or Self-Supervised Learning, refers to a training method on the large-scale unlabeled speech dataset. The model trained in this way can produce a good acoustic representation, and can be applied to other downstream speech tasks by fine-tuning on labeled datasets.\n\nThis demo is an implementation to recognize text or produce the acoustic representation from a specific audio file by speech ssl models. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n\n### 3. Usage\n- Command Line(Recommended)\n  ```bash\n  # to recognize text \n  paddlespeech ssl --task asr --lang en --input ./en.wav\n\n  # to get acoustic representation\n  paddlespeech ssl --task vector --lang en --input ./en.wav\n  ```\n\n  Usage:\n  ```bash\n  paddlespeech ssl --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize.\n  - `model`: Model type of asr task. Default: `wav2vec2`, choices: [wav2vec2, hubert, wavlm].\n  - `task`: Output type. Default: `asr`.\n  - `lang`: Model language. Default: `en`.\n  - `sample_rate`: Sample rate of the model. Default: `16000`.\n  - `config`: Config of asr task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `yes`: No additional parameters required. Once set this parameter, it means accepting the request of the program by default, which includes transforming the audio sample rate. Default: `False`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n  - `verbose`: Show the log information.\n\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.ssl import SSLExecutor\n\n  ssl_executor = SSLExecutor()\n\n  # to recognize text \n  text = ssl_executor(\n      model='wav2vec2',\n      task='asr',\n      lang='en',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('ASR Result: \\n{}'.format(text))\n\n  # to get acoustic representation\n  feature = ssl_executor(\n      model='wav2vec2',\n      task='vector',\n      lang='en',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('Representation: \\n{}'.format(feature))\n  ```\n\n  Output:\n  ```bash\n  ASR Result:\n  i knocked at the door on the ancient side of the building\n\n  Representation:\n  Tensor(shape=[1, 164, 1024], dtype=float32, place=Place(gpu:0), stop_gradient=True,\n       [[[ 0.02351918, -0.12980647,  0.17868176, ...,  0.10118122,\n          -0.04614586,  0.17853957],\n         [ 0.02361383, -0.12978461,  0.17870593, ...,  0.10103855,\n          -0.04638699,  0.17855372],\n         [ 0.02345137, -0.12982975,  0.17883906, ...,  0.10104341,\n          -0.04643029,  0.17856732],\n         ...,\n         [ 0.02313030, -0.12918393,  0.17845058, ...,  0.10073373,\n          -0.04701405,  0.17862988],\n         [ 0.02176583, -0.12929161,  0.17797582, ...,  0.10097728,\n          -0.04687393,  0.17864393],\n         [ 0.05269200,  0.01297141, -0.23336855, ..., -0.11257174,\n          -0.17227529,  0.20338398]]])\n  ```\n"
  },
  {
    "path": "demos/speech_ssl/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 语音自监督学习\n## 介绍\n语音自监督学习，指的是在大规模无标记的语音数据集上的训练方法。用这种方法训练出来的模型可以产生很好的声学表征。并且可以通过在有标签的数据集上进行微调，应用于其他下游的语音任务。\n\n这个 demo 是通过语音自监督模型将一个特定的音频文件识别成文本或产生声学表征，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 demo 的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n### 3. 使用方法\n- 命令行 (推荐使用)\n  ```bash\n\n  # 识别文本\n  paddlespeech ssl --task asr --lang en --input ./en.wav\n\n  # 产生声学表征\n  paddlespeech ssl --task vector --lang en --input ./en.wav\n  ```\n  \n  使用方法：\n  ```bash\n  paddlespeech asr --help\n  ```\n  参数：\n  - `input`(必须输入)：用于识别的音频文件。\n  - `model`：ASR 任务的模型，默认值：`wav2vec2`, 可选项：[wav2vec2, hubert, wavlm]。\n  - `task`：输出类别，默认值：`asr`。\n  - `lang`：模型语言，默认值：`en`。\n  - `sample_rate`：音频采样率，默认值：`16000`。\n  - `config`：ASR 任务的参数文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n  - `ckpt_path`：模型参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `yes`；不需要设置额外的参数，一旦设置了该参数，说明你默认同意程序的所有请求，其中包括自动转换输入音频的采样率。默认值：`False`。\n  - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n  - `verbose`: 如果使用，显示 logger 信息。\n\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.ssl import SSLExecutor\n\n  ssl_executor = SSLExecutor()\n\n  # 识别文本\n  text = ssl_executor(\n      model='wav2vec2',\n      task='asr',\n      lang='en',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('ASR Result: \\n{}'.format(text))\n\n  # 得到声学表征\n  feature = ssl_executor(\n      model='wav2vec2',\n      task='vector',\n      lang='en',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('Representation: \\n{}'.format(feature))\n  ```\n\n\n  输出：\n  ```bash\n  ASR Result:\n  i knocked at the door on the ancient side of the building\n  \n  Representation:\n  Tensor(shape=[1, 164, 1024], dtype=float32, place=Place(gpu:0), stop_gradient=True,\n       [[[ 0.02351918, -0.12980647,  0.17868176, ...,  0.10118122,\n          -0.04614586,  0.17853957],\n         [ 0.02361383, -0.12978461,  0.17870593, ...,  0.10103855,\n          -0.04638699,  0.17855372],\n         [ 0.02345137, -0.12982975,  0.17883906, ...,  0.10104341,\n          -0.04643029,  0.17856732],\n         ...,\n         [ 0.02313030, -0.12918393,  0.17845058, ...,  0.10073373,\n          -0.04701405,  0.17862988],\n         [ 0.02176583, -0.12929161,  0.17797582, ...,  0.10097728,\n          -0.04687393,  0.17864393],\n         [ 0.05269200,  0.01297141, -0.23336855, ..., -0.11257174,\n          -0.17227529,  0.20338398]]])\n  ```\n"
  },
  {
    "path": "demos/speech_ssl/run.sh",
    "content": "#!/bin/bash\n\n# audio download\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n\n# to recognize text \npaddlespeech ssl --task asr --lang en --input ./en.wav\n\n# to get acoustic representation\npaddlespeech ssl --task vector --lang en --input ./en.wav\n"
  },
  {
    "path": "demos/speech_translation/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# Speech Translation\n## Introduction\nSpeech translation is the process by which conversational spoken phrases are instantly translated and spoken aloud in a second language.\n\nThis demo is an implementation to recognize text from a specific audio file and translate it to the target language. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n\n### 2. Prepare Input File\nThe input of this demo should be a WAV file(`.wav`).\n\nHere are sample files for this demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n\n### 3. Usage (not support for Windows now)\n- Command Line(Recommended)\n  ```bash\n  paddlespeech st --input ./en.wav\n  ```\n  Usage:\n  ```bash\n  paddlespeech st --help\n  ```\n  Arguments:\n  - `input`(required): Audio file to recognize and translate.\n  - `model`: Model type of st task. Default: `fat_st_ted`.\n  - `src_lang`: Source language. Default: `en`.\n  - `tgt_lang`: Target language. Default: `zh`.\n  - `sample_rate`: Sample rate of the model. Default: `16000`.\n  - `config`: Config of st task. Use pretrained model when it is None. Default: `None`.\n  - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n\n  Output:\n  ```bash\n  [2021-12-09 11:13:03,178] [    INFO] [utils.py] [L225] - ST Result: ['我 在 这栋 建筑 的 古老 门上 敲门 。']\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.st import STExecutor\n\n  st_executor = STExecutor()\n  text = st_executor(\n      model='fat_st_ted',\n      src_lang='en',\n      tgt_lang='zh',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('ST Result: \\n{}'.format(text))\n  ```\n\n  Output:\n  ```bash\n  ST Result:\n  ['我 在 这栋 建筑 的 古老 门上 敲门 。'] \n  ```\n\n### 4.Pretrained Models\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n| Model | Source Language | Target Language\n| :--- | :---: | :---: |\n| fat_st_ted| en| zh\n"
  },
  {
    "path": "demos/speech_translation/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n# 语音翻译\n\n## 介绍\n语音翻译是将会话口语短语翻译成另一语言的过程。\n\n该 Demo 是从特定音频文件中识别文本并将其翻译为目标语言的实现。它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n这个 Demo 的输入是 WAV(`.wav`) 语音文件\n\n这里给出一些样例文件供 Demo 使用：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n```\n\n### 3. 使用方法 (暂不支持Windows)\n- 命令行(推荐使用)\n  ```bash\n  paddlespeech st --input ./en.wav\n  ```\n  使用方法：\n  ```bash\n  paddlespeech st --help\n  ```\n  参数：\n  - `input`(必须输入)：用于翻译的音频。\n  - `model`： 语音翻译的模型类型. 默认：`fat_st_ted`。\n  - `src_lang`： 源语言. 默认：`en`。\n  - `tgt_lang`： 目标语言. 默认：`zh`。\n  - `sample_rate`：输入音频的采样率. 默认：`16000`。\n  - `config`：语音翻译任务的配置文件. 如果没有默认使用预训练模型的配置文件. 默认：`None`。\n  - `ckpt_path`：模型文件. 如果没有默认使用预训练模型. 默认：`None`。\n  - `device`：选择执行的设备. 默认： 当前环境 paddlepaddle 的默认设备。\n\n  输出：\n  ```bash\n  [2021-12-09 11:13:03,178] [    INFO] [utils.py] [L225] - ST Result: ['我 在 这栋 建筑 的 古老 门上 敲门 。']\n  ```\n\n- Python API\n  ```python\n  import paddle\n  from paddlespeech.cli.st import STExecutor\n  \n  st_executor = STExecutor()\n  text = st_executor(\n      model='fat_st_ted',\n      src_lang='en',\n      tgt_lang='zh',\n      sample_rate=16000,\n      config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n      ckpt_path=None,\n      audio_file='./en.wav',\n      device=paddle.get_device())\n  print('ST Result: \\n{}'.format(text))\n  ```\n\n  输出：\n  ```bash\n  ST Result:\n  ['我 在 这栋 建筑 的 古老 门上 敲门 。'] \n  ```\n\n### 4. 预训练模型\n\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n| 模型 | 源语言 | 目标语言\n| :--- | :---: | :---: |\n| fat_st_ted| en| zh\n"
  },
  {
    "path": "demos/speech_translation/run.sh",
    "content": "#!/bin/bash\n\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\npaddlespeech st --input ./en.wav\n"
  },
  {
    "path": "demos/speech_web/.gitignore",
    "content": "*/.vscode/*\n*.wav\n*/resource/*\n.Ds*\n*.pyc\n*.pcm\n*.npy\n*.diff\n*.sqlite\n*/static/*\n*.pdparams\n*.pdiparams*\n*.pdmodel\n*/source/*\n*/PaddleSpeech/*\n*/tmp*/*\n*/duration.txt\n*/oov_info.txt\n\n"
  },
  {
    "path": "demos/speech_web/API.md",
    "content": "# 接口文档\n\n开启服务后可参照：\n\nhttp://0.0.0.0:8010/docs\n\n## ASR\n\n### 【POST】/asr/offline\n\n说明：上传 16k, 16bit wav 文件，返回 offline 语音识别模型识别结果\n\n返回: JSON\n\n前端接口： ASR-端到端识别，音频文件识别；语音指令-录音上传\n\n示例:\n\n```json\n{\n  \"code\": 0,\n  \"result\": \"你也喜欢这个天气吗\",\n  \"message\": \"ok\"\n}\n```\n\n### 【POST】/asr/offlinefile\n\n说明：上传16k,16bit wav文件，返回 offline 语音识别模型识别结果 + wav 数据的 base64\n\n返回: JSON\n\n前端接口： 音频文件识别(播放这段base64还原后记得添加 wav 头，采样率 16k, int16，添加后才能播放)\n\n示例:\n\n```json\n{\n  \"code\": 0,\n  \"result\": {\n    \"asr_result\": \"今天天气真好\",\n    \"wav_base64\": \"///+//3//f/8/////v/////////////////+/wAA//8AAAEAAQACAAIAAQABAP\"\n    },\n  \"message\": \"ok\"\n}\n```\n\n\n### 【POST】/asr/collectEnv\n\n说明： 通过采集环境噪音，上传 16k, int16 wav 文件，来生成后台 VAD 的能量阈值， 返回阈值结果\n\n前端接口：ASR-环境采样\n\n返回: JSON\n\n```json\n{\n  \"code\": 0,\n  \"result\": 3624.93505859375,\n  \"message\": \"采集环境噪音成功\"\n}\n```\n\n### 【GET】/asr/stopRecord\n\n说明：通过 GET 请求 /asr/stopRecord, 后台停止接收 offlineStream 中通过 WS 协议 上传的数据\n\n前端接口：语音聊天-暂停录音（获取 NLP，播放 TTS 时暂停）\n\n返回: JSON\n\n```JSON\n{\n  \"code\": 0,\n  \"result\": null,\n  \"message\": \"停止成功\"\n}\n```\n\n### 【GET】/asr/resumeRecord\n\n说明：通过 GET 请求 /asr/resumeRecord, 后台停止接收 offlineStream 中通过 WS 协议 上传的数据\n\n前端接口：语音聊天-恢复录音（ TTS 播放完毕时，告诉后台恢复录音）\n\n返回: JSON\n\n```JSON\n{\n  \"code\": 0,\n  \"result\": null,\n  \"message\": \"Online录音恢复\"\n}\n```\n\n### 【Websocket】/ws/asr/offlineStream\n\n说明：通过 WS 协议，将前端音频持续上传到后台，前端采集 16k，Int16 类型的PCM片段，持续上传到后端\n\n前端接口：语音聊天-开始录音，持续将麦克风语音传给后端，后端推送语音识别结果\n\n返回：后端返回识别结果，offline 模型识别结果， 由WS推送\n\n\n### 【Websocket】/ws/asr/onlineStream\n\n说明：通过 WS 协议，将前端音频持续上传到后台，前端采集 16k，Int16 类型的 PCM 片段，持续上传到后端\n\n前端接口：ASR-流式识别开始录音，持续将麦克风语音传给后端，后端推送语音识别结果\n\n返回：后端返回识别结果，online 模型识别结果， 由 WS 推送\n\n## NLP\n\n### 【POST】/nlp/chat\n\n说明：返回闲聊对话的结果\n\n前端接口：语音聊天-获取到ASR识别结果后，向后端获取闲聊文本\n\n上传示例：\n\n```json\n{\n  \"chat\": \"天气非常棒\"\n}\n```\n\n返回示例：\n\n```json\n{\n  \"code\": 0,\n  \"result\": \"是的,我也挺喜欢的\",\n  \"message\": \"ok\"\n}\n```\n\n\n### 【POST】/nlp/ie\n\n说明：返回信息抽取结果\n\n前端接口：语音指令-向后端获取信息抽取结果\n\n上传示例：\n\n```json\n{\n  \"chat\": \"今天我从马来西亚出发去香港花了五十万元\"\n}\n```\n\n返回示例：\n\n```json\n{\n  \"code\": 0,\n  \"result\": [\n    {\n      \"时间\": [\n        {\n          \"text\": \"今天\",\n          \"start\": 0,\n          \"end\": 2,\n          \"probability\": 0.9817976247505698\n        }\n      ],\n      \"出发地\": [\n        {\n          \"text\": \"马来西亚\",\n          \"start\": 4,\n          \"end\": 8,\n          \"probability\": 0.974892389414169\n        }\n      ],\n      \"目的地\": [\n        {\n          \"text\": \"马来西亚\",\n          \"start\": 4,\n          \"end\": 8,\n          \"probability\": 0.7347504438136951\n        }\n      ],\n      \"费用\": [\n        {\n          \"text\": \"五十万元\",\n          \"start\": 15,\n          \"end\": 19,\n          \"probability\": 0.9679076530644402\n        }\n      ]\n    }\n  ],\n  \"message\": \"ok\"\n}\n```\n\n\n## TTS\n\n### 【POST】/tts/offline\n\n说明：获取 TTS 离线模型音频\n\n前端接口：TTS-端到端合成\n\n上传示例：\n\n```json\n{\n  \"text\": \"天气非常棒\"\n}\n```\n\n返回示例：对应音频对应的 base64 编码\n\n```json\n{\n  \"code\": 0,\n  \"result\": \"UklGRrzQAABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAAZGF0YZjQAAADAP7/BAADAAAA...\",\n  \"message\": \"ok\"\n}\n```\n\n### 【POST】/tts/online\n\n说明：流式获取语音合成音频\n\n前端接口：流式合成\n\n上传示例：\n```json\n{\n  \"text\": \"天气非常棒\"\n}\n\n```\n\n返回示例：\n\n二进制PCM片段，16k Int 16类型\n\n## VPR\n\n### 【POST】/vpr/enroll\n\n说明：声纹注册，通过表单上传 spk_id（字符串，非空）, 与 audio (文件)\n\n前端接口：声纹识别-声纹注册\n\n上传示例：\n\n```text\ncurl -X 'POST' \\\n  'http://0.0.0.0:8010/vpr/enroll' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: multipart/form-data' \\\n  -F 'spk_id=啦啦啦啦' \\\n  -F 'audio=@demo_16k.wav;type=audio/wav'\n```\n\n返回示例：\n\n```json\n{\n  \"status\": true,\n  \"msg\": \"Successfully enroll data!\"\n}\n```\n\n### 【POST】/vpr/recog\n\n说明：声纹识别，识别文件，提取文件的声纹信息做比对 音频 16k, int 16 wav 格式\n\n前端接口：声纹识别-上传音频，返回声纹识别结果\n\n上传示例： \n\n```shell\ncurl -X 'POST' \\\n  'http://0.0.0.0:8010/vpr/recog' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: multipart/form-data' \\\n  -F 'audio=@demo_16k.wav;type=audio/wav'\n```\n\n返回示例：\n\n```json\n[\n  [\n    \"啦啦啦啦\",\n    [\n      \"\",\n      100\n    ]\n  ],\n  [\n    \"test1\",\n    [\n      \"\",\n      11.64\n    ]\n  ],\n  [\n    \"test2\",\n    [\n      \"\",\n      6.09\n    ]\n  ]\n]\n\n```\n\n\n### 【POST】/vpr/del\n\n说明： 根据 spk_id 删除用户数据\n\n前端接口：声纹识别-删除用户数据\n\n上传示例：\n```json\n{\n \"spk_id\":\"啦啦啦啦\"\n}\n```\n\n返回示例\n\n```json\n{\n  \"status\": true,\n  \"msg\": \"Successfully delete data!\"\n}\n\n```\n\n\n### 【GET】/vpr/list\n\n说明：查询用户列表数据，无需参数，返回 spk_id 与 vpr_id\n\n前端接口：声纹识别-获取声纹数据列表\n\n返回示例：\n\n```json\n[\n  [\n    \"test1\",\n    \"test2\"\n  ],\n  [\n    9,\n    10\n  ]\n]\n\n```\n\n\n### 【GET】/vpr/data\n\n说明： 根据 vpr_id 获取用户vpr时使用的音频\n\n前端接口：声纹识别-获取vpr对应的音频\n\n访问示例：\n\n```shell\ncurl -X 'GET' \\\n  'http://0.0.0.0:8010/vpr/data?vprId=9' \\\n  -H 'accept: application/json'\n```\n\n返回示例：\n\n对应音频文件\n\n### 【GET】/vpr/database64\n\n说明： 根据 vpr_id 获取用户 vpr 时注册使用音频转换成 16k, int16 类型的数组，返回 base64 编码\n\n前端接口：声纹识别-获取 vpr 对应的音频（注意：播放时需要添加 wav头，16k,int16, 可参考 tts 播放时添加 wav 的方式，注意更改采样率）\n\n访问示例：\n\n```shell\ncurl -X 'GET' \\\n  'http://localhost:8010/vpr/database64?vprId=12' \\\n  -H 'accept: application/json'\n```\n\n返回示例：\n```json\n{\n  \"code\": 0,\n  \"result\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\n  \"message\": \"ok\"\n```\n"
  },
  {
    "path": "demos/speech_web/README.md",
    "content": "# Paddle Speech Demo\n\n## 简介\nPaddle Speech Demo 是一个以 PaddleSpeech 的语音交互功能为主体开发的 Demo 展示项目，用于帮助大家更好的上手 PaddleSpeech 以及使用 PaddleSpeech 构建自己的应用。\n\n智能语音交互部分使用 PaddleSpeech，对话以及信息抽取部分使用 PaddleNLP，网页前端展示部分基于 Vue3 进行开发。\n\n主要功能：\n\n`main.py` 中包含功能\n+ 语音聊天：PaddleSpeech 的语音识别能力+语音合成能力，对话部分基于 PaddleNLP 的闲聊功能\n+ 声纹识别：PaddleSpeech 的声纹识别功能展示\n+ 语音识别：支持【实时语音识别】，【端到端识别】，【音频文件识别】三种模式\n+ 语音合成：支持【流式合成】与【端到端合成】两种方式\n+ 语音指令：基于 PaddleSpeech 的语音识别能力与 PaddleNLP 的信息抽取，实现交通费的智能报销\n\n`vc.py` 中包含功能\n+ 一句话合成：基于 GE2E 和 ECAPA-TDNN 模型的一句话合成方案，可以模仿输入的音频的音色进行合成任务\n  + GE2E 音色克隆方案可以参考： [【FastSpeech2 + AISHELL-3 Voice Cloning】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc1)\n  + ECAPA-TDNN 音色克隆方案可以参考: [【FastSpeech2 + AISHELL-3 Voice Cloning (ECAPA-TDNN)】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc2)\n\n+ 小数据微调：基于小数据集的微调方案，内置用12句话标贝中文女声微调示例，你也可以通过一键重置，录制自己的声音，注意在安静环境下录制，效果会更好。你可以在 [【Finetune your own AM based on FastSpeech2 with AISHELL-3】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/tts_finetune/tts3)中尝试使用自己的数据集进行微调。\n\n+ ERNIE-SAT：语言-语音跨模态大模型 ERNIE-SAT 可视化展示示例，支持个性化合成，跨语言语音合成（音频为中文则输入英文文本进行合成），语音编辑（修改音频文字中间的结果）功能。 ERNIE-SAT 更多实现细节，可以参考：\n  + [【ERNIE-SAT with AISHELL-3 dataset】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/ernie_sat)\n  + [【ERNIE-SAT with AISHELL3 and VCTK datasets】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3_vctk/ernie_sat)\n  + [【ERNIE-SAT with VCTK dataset】](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/ernie_sat)\n\n运行效果：\n\n ![效果](https://user-images.githubusercontent.com/30135920/196076507-7eb33d39-2345-4268-aee7-6270b9ac8b98.png)\n\n\n\n## 基础环境安装\n\n### 后端环境安装\n```bash \n# 需要先安装 PaddleSpeech\ncd speech_server\npip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple\ncd ../\n```\n\n### 前端环境安装\n前端依赖 `node.js` ，需要提前安装，确保 `npm` 可用，`npm` 测试版本 `8.3.1`，建议下载[官网](https://nodejs.org/en/)稳定版的 `node.js`\n\n如果因为网络问题，无法下载依赖库，可以参考 FAQ 部分，`npm / yarn 下载速度慢问题`\n\n```bash\n# 进入前端目录\ncd web_client\n# 安装 `yarn`，已经安装可跳过\nnpm install -g yarn\n# 使用yarn安装前端依赖\nyarn install\ncd ../\n```\n\n\n## 启动服务\n【注意】目前只支持 `main.py` 和 `vc.py` 两者中选择开启一个后端服务。\n\n### 启动 `main.py` 后端服务\n\n#### 下载相关模型\n\n只需手动下载语音指令所需模型即可，其他模型会自动下载。\n\n```bash\ncd speech_server\nmkdir -p source/model\ncd source/model\n# 下载IE模型\nwget https://bj.bcebos.com/paddlenlp/applications/speech-cmd-analysis/finetune/model_state.pdparams\ncd ../../../\n\n```\n#### 启动后端服务\n\n```\ncd speech_server\n# 默认8010端口\npython main.py --port 8010\n```\n\n\n### 启动 `vc.py` 后端服务\n\n参照下面的步骤自行配置项目所需环境。\n\nAistudio 在线体验小样本合成后端功能：[【PaddleSpeech进阶】PaddleSpeech小样本合成方案体验](https://aistudio.baidu.com/aistudio/projectdetail/4573549?sUid=2470186&shared=1&ts=1664174385948)\n\n#### 下载相关模型和音频\n\n```bash\ncd speech_server\n\n# 已创建则跳过\nmkdir -p source/model\ncd source\n# 下载 & 解压 wav （包含VC测试音频）\nwget https://paddlespeech.cdn.bcebos.com/demos/speech_web/wav_vc.zip\nunzip wav_vc.zip\n\ncd model\n# 下载 GE2E 相关模型\nwget https://bj.bcebos.com/paddlespeech/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip\nunzip ge2e_ckpt_0.3.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip\nunzip pwg_aishell3_ckpt_0.5.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip\nunzip fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip\n\n# 下载 ECAPA-TDNN 相关模型\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_vc2_1.2.0.zip\nunzip fastspeech2_aishell3_ckpt_vc2_1.2.0.zip\n\n# 下载 ERNIE-SAT 相关模型\n# aishell3 ERNIE-SAT\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_aishell3_ckpt_1.2.0.zip\nunzip erniesat_aishell3_ckpt_1.2.0.zip\n\n# vctk ERNIE-SAT\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_vctk_ckpt_1.2.0.zip\nunzip erniesat_vctk_ckpt_1.2.0.zip\n\n# aishell3_vctk ERNIE-SAT\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_aishell3_vctk_ckpt_1.2.0.zip\nunzip erniesat_aishell3_vctk_ckpt_1.2.0.zip\n\n# 下载 finetune 相关模型\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_1.1.0.zip\nunzip fastspeech2_aishell3_ckpt_1.1.0.zip\n\n# 下载声码器\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip\nunzip hifigan_aishell3_ckpt_0.2.0.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip\nunzip hifigan_vctk_ckpt_0.2.0.zip\n\ncd ../../../\n```\n\n#### ERNIE-SAT 环境配置\n\nERNIE-SAT 体验依赖于 [examples/aishell3_vctk/ernie_sat](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3_vctk/ernie_sat) 的环境。参考 `examples/aishell3_vctk/ernie_sat` 下的 `README.md`， 确保 `examples/aishell3_vctk/ernie_sat` 下 `run.sh` 相关示例代码有效。\n \n运行好 `examples/aishell3_vctk/ernie_sat` 后，回到当前目录，创建环境：\n```bash\ncd speech_server\nln -snf ../../../examples/aishell3_vctk/ernie_sat/download .\nln -snf ../../../examples/aishell3_vctk/ernie_sat/tools .\ncd ../\n```\n\n#### finetune 环境配置\n\n`finetune` 需要解压 `tools/aligner` 中的 `aishell3_model.zip`，finetune 过程需要使用到 `tools/aligner/aishell3_model/meta.yaml` 文件。\n\n```bash\ncd speech_server/tools/aligner\nunzip aishell3_model.zip\ncd -\n```\n\n#### 启动后端服务\n\n```\ncd speech_server\n# 默认8010端口\npython vc.py --port 8010\n```\n\n### 启动前端服务\n\n```\ncd web_client\nyarn dev --port 8011\n```\n\n默认配置下，前端配置的后台地址信息是 `localhost`，确保后端服务器和打开页面的游览器在同一台机器上，不在一台机器的配置方式见下方的 FAQ：【后端如果部署在其它机器或者别的端口如何修改】\n\n#### 关于前端的一些说明\n\n为了方便后期的维护，这里并没有给出打包好的 HTML 文件，而是 Vue3 的项目，使用 `yarn dev --port 8011` 的方式启动测试，方便大家debug，相当于是启动了一个前端服务器。\n\n比如我们在本机启动的这个前端服务（运行 `yarn dev --port 8011` ），我们就可以通过在游览器中通过 `http://localhost:8011` 访问前端页面\n\n如果我们在其它服务器上（例如：`*.*.*.*` ）启动这个前端服务（运行 `yarn dev --port 8011` ），我们就可以通过在游览器中访问 `http://*.*.*.*:8011` 访问前端页面\n\n那前端跟后端是什么关系呢？ 两个是独立的，只要前端能够通过代理访问到后端的接口，那就没有问题。你可以在 A 机器上部署后端服务，然后在 B 机器上部署前端服务。我们在 `./web_client/vite.config.js` 中将 `/api` 映射到的是 `http://localhost:8010`，你可以把它配置成任意你想要访问后端地址。\n\n当前端在以 `*.*.*.*` 这类以 IP 地址形式的网页中访问时，由于游览器的安全限制，会禁止录音，需要重新配置游览器的安全策略， 可以看下面 FAQ 部分： [【前端以IP地址的形式访问，无法录音】]\n\n\n## FAQ \n\n#### Q: 如何安装node.js\n\nA： node.js的安装可以参考[【菜鸟教程】](https://www.runoob.com/nodejs/nodejs-install-setup.html), 确保 npm 可用\n\n#### Q：后端如果部署在其它机器或者别的端口如何修改\n\nA：后端的配置地址有分散在两个文件中\n\n修改第一个文件 `./web_client/vite.config.js`\n\n```\nserver: {\n    host: \"0.0.0.0\",\n    proxy: {\n      \"/api\": {\n        target: \"http://localhost:8010\",  // 这里改成后端所在接口\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, \"\"),\n      },\n    },\n  }\n```\n\n修改第二个文件 `./web_client/src/api/API.js`（ Websocket 代理配置失败，所以需要在这个文件中修改）\n\n```\n// websocket （这里改成后端所在的接口）\nCHAT_SOCKET_RECORD: 'ws://localhost:8010/ws/asr/offlineStream', // ChatBot websocket 接口\nASR_SOCKET_RECORD: 'ws://localhost:8010/ws/asr/onlineStream',  // Stream ASR 接口\nTTS_SOCKET_RECORD: 'ws://localhost:8010/ws/tts/online', // Stream TTS 接口\n```\n\n#### Q：前端以IP地址的形式访问，无法录音\n\nA：这里主要是游览器安全策略的限制，需要配置游览器后重启。游览器修改配置可参考[使用js-audio-recorder报浏览器不支持getUserMedia](https://blog.csdn.net/YRY_LIKE_YOU/article/details/113745273)\n\nchrome设置地址: chrome://flags/#unsafely-treat-insecure-origin-as-secure\n\n#### Q: npm / yarn 配置淘宝镜像源\n\nA: 配置淘宝镜像源，详细可以参考 [【yarn npm 设置淘宝镜像】](https://www.jianshu.com/p/f6f43e8f9d6b)\n\n```bash\n# npm 配置淘宝镜像源\nnpm config set registry https://registry.npmmirror.com\n\n# yarn 配置淘宝镜像源\nyarn config set registry http://registry.npm.taobao.org/\n```\n\n## 参考资料\n\nvue实现录音参考资料：https://blog.csdn.net/qq_41619796/article/details/107865602#t1\n\n前端流式播放音频参考仓库：\n\nhttps://github.com/AnthumChris/fetch-stream-audio\n\nhttps://bm.enthuses.me/buffered.php?bref=6677\n"
  },
  {
    "path": "demos/speech_web/speech_server/conf/tts3_finetune.yaml",
    "content": "###########################################################\n#                 PARAS SETTING               #\n###########################################################\n# Set to -1 to indicate that the parameter is the same as the pretrained model configuration\n\nbatch_size: 10\nlearning_rate: 0.0001     # learning rate\nnum_snapshots: -1\n\n# frozen_layers should be a list\n# if you don't need to freeze, set frozen_layers to []\nfrozen_layers: [\"encoder\"]\n"
  },
  {
    "path": "demos/speech_web/speech_server/conf/tts_online_application.yaml",
    "content": "# This is the parameter configuration file for streaming tts server.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8092\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# engine_list choices = ['tts_online', 'tts_online-onnx'], the inference speed of tts_online-onnx is faster than tts_online.\n# protocol choices = ['websocket', 'http'] \nprotocol: 'http'\nengine_list: ['tts_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online #######################\ntts_online: \n    # am (acoustic model) choices=['fastspeech2_csmsc', 'fastspeech2_cnndecoder_csmsc']   \n    # fastspeech2_cnndecoder_csmsc support streaming am infer.     \n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n\n    # voc (vocoder) choices=['mb_melgan_csmsc, hifigan_csmsc']\n    # Both mb_melgan_csmsc and hifigan_csmsc support streaming voc inference\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    \n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online-onnx #######################\ntts_online-onnx: \n    # am (acoustic model) choices=['fastspeech2_csmsc_onnx', 'fastspeech2_cnndecoder_csmsc_onnx']\n    # fastspeech2_cnndecoder_csmsc_onnx support streaming am infer.        \n    am: 'fastspeech2_cnndecoder_csmsc_onnx' \n    # am_ckpt is a list, if am is fastspeech2_cnndecoder_csmsc_onnx, am_ckpt = [encoder model, decoder model, postnet model];\n    # if am is fastspeech2_csmsc_onnx, am_ckpt = [ckpt model];\n    am_ckpt:   # list\n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n    am_sample_rate: 24000\n    am_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # voc (vocoder) choices=['mb_melgan_csmsc_onnx, hifigan_csmsc_onnx']\n    # Both mb_melgan_csmsc_onnx and hifigan_csmsc_onnx support streaming voc inference\n    voc: 'hifigan_csmsc_onnx'\n    voc_ckpt: \n    voc_sample_rate: 24000\n    voc_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # others\n    lang: 'zh'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc_onnx, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc_onnx, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    # voc_upsample should be same as n_shift on voc config.\n    voc_upsample: 300\n    \n"
  },
  {
    "path": "demos/speech_web/speech_server/conf/ws_conformer_wenetspeech_application_faster.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n    num_decoding_left_chunks: 16\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/speech_web/speech_server/main.py",
    "content": "import argparse\nimport base64\nimport datetime\nimport json\nimport os\nfrom typing import List\n\nimport aiofiles\nimport librosa\nimport soundfile as sf\nimport uvicorn\nfrom fastapi import FastAPI\nfrom fastapi import File\nfrom fastapi import Form\nfrom fastapi import UploadFile\nfrom fastapi import WebSocket\nfrom fastapi import WebSocketDisconnect\nfrom fastapi.responses import StreamingResponse\nfrom pydantic import BaseModel\nfrom src.AudioManeger import AudioMannger\nfrom src.robot import Robot\nfrom src.SpeechBase.vpr import VPR\nfrom src.util import *\nfrom src.WebsocketManeger import ConnectionManager\nfrom starlette.middleware.cors import CORSMiddleware\nfrom starlette.requests import Request\nfrom starlette.responses import FileResponse\nfrom starlette.websockets import WebSocketState as WebSocketState\n\nfrom paddlespeech.cli.tts.infer import TTSExecutor\nfrom paddlespeech.server.engine.asr.online.python.asr_engine import PaddleASRConnectionHanddler\nfrom paddlespeech.server.utils.audio_process import float2pcm\n\n# 解析配置\nparser = argparse.ArgumentParser(prog='PaddleSpeechDemo', add_help=True)\n\nparser.add_argument(\n    \"--port\",\n    action=\"store\",\n    type=int,\n    help=\"port of the app\",\n    default=8010,\n    required=False)\n\nargs = parser.parse_args()\nport = args.port\n\n# 配置文件\ntts_config = \"conf/tts_online_application.yaml\"\nasr_config = \"conf/ws_conformer_wenetspeech_application_faster.yaml\"\nasr_init_path = \"source/demo/demo.wav\"\ndb_path = \"source/db/vpr.sqlite\"\nie_model_path = \"source/model\"\ntts_model = TTSExecutor()\n# 路径配置\nUPLOAD_PATH = \"source/vpr\"\nWAV_PATH = \"source/wav\"\n\nbase_sources = [UPLOAD_PATH, WAV_PATH]\nfor path in base_sources:\n    os.makedirs(path, exist_ok=True)\n\n# 初始化\napp = FastAPI()\nchatbot = Robot(\n    asr_config, tts_config, asr_init_path, ie_model_path=ie_model_path)\nmanager = ConnectionManager()\naumanager = AudioMannger(chatbot)\naumanager.init()\nvpr = VPR(db_path, dim=192, top_k=5)\n# 初始化下载模型\ntts_model(\n    text=\"今天天气准不错\",\n    output=\"test.wav\",\n    am='fastspeech2_mix',\n    spk_id=174,\n    voc='hifigan_csmsc',\n    lang='mix', )\n\n\n# 服务配置\nclass NlpBase(BaseModel):\n    chat: str\n\n\nclass TtsBase(BaseModel):\n    text: str\n\n\nclass Audios:\n    def __init__(self) -> None:\n        self.audios = b\"\"\n\n\naudios = Audios()\n\n######################################################################\n########################### ASR 服务 #################################\n#####################################################################\n\n\n# 接收文件，返回ASR结果\n# 上传文件\n@app.post(\"/asr/offline\")\nasync def speech2textOffline(files: List[UploadFile]):\n    # 只有第一个有效\n    asr_res = \"\"\n    for file in files[:1]:\n        # 生成时间戳\n        now_name = \"asr_offline_\" + datetime.datetime.strftime(\n            datetime.datetime.now(), '%Y%m%d%H%M%S') + randName() + \".wav\"\n        out_file_path = os.path.join(WAV_PATH, now_name)\n        async with aiofiles.open(out_file_path, 'wb') as out_file:\n            content = await file.read()  # async read\n            await out_file.write(content)  # async write\n\n        # 返回ASR识别结果\n        asr_res = chatbot.speech2text(out_file_path)\n        return SuccessRequest(result=asr_res)\n    return ErrorRequest(message=\"上传文件为空\")\n\n\n# 接收文件，同时将wav强制转成16k, int16类型\n@app.post(\"/asr/offlinefile\")\nasync def speech2textOfflineFile(files: List[UploadFile]):\n    # 只有第一个有效\n    asr_res = \"\"\n    for file in files[:1]:\n        # 生成时间戳\n        now_name = \"asr_offline_\" + datetime.datetime.strftime(\n            datetime.datetime.now(), '%Y%m%d%H%M%S') + randName() + \".wav\"\n        out_file_path = os.path.join(WAV_PATH, now_name)\n        async with aiofiles.open(out_file_path, 'wb') as out_file:\n            content = await file.read()  # async read\n            await out_file.write(content)  # async write\n\n        # 将文件转成16k, 16bit类型的wav文件\n        wav, sr = librosa.load(out_file_path, sr=16000)\n        wav = float2pcm(wav)  # float32 to int16\n        wav_bytes = wav.tobytes()  # to bytes\n        wav_base64 = base64.b64encode(wav_bytes).decode('utf8')\n\n        # 将文件重新写入\n        now_name = now_name[:-4] + \"_16k\" + \".wav\"\n        out_file_path = os.path.join(WAV_PATH, now_name)\n        sf.write(out_file_path, wav, 16000)\n\n        # 返回ASR识别结果\n        asr_res = chatbot.speech2text(out_file_path)\n        response_res = {\"asr_result\": asr_res, \"wav_base64\": wav_base64}\n        return SuccessRequest(result=response_res)\n\n    return ErrorRequest(message=\"上传文件为空\")\n\n\n# 流式接收测试\n@app.post(\"/asr/online1\")\nasync def speech2textOnlineRecive(files: List[UploadFile]):\n    audio_bin = b''\n    for file in files:\n        content = await file.read()\n        audio_bin += content\n    audios.audios += audio_bin\n    print(f\"audios长度变化: {len(audios.audios)}\")\n    return SuccessRequest(message=\"接收成功\")\n\n\n# 采集环境噪音大小\n@app.post(\"/asr/collectEnv\")\nasync def collectEnv(files: List[UploadFile]):\n    for file in files[:1]:\n        content = await file.read()  # async read\n        # 初始化, wav 前44字节是头部信息\n        aumanager.compute_env_volume(content[44:])\n        vad_ = aumanager.vad_threshold\n        return SuccessRequest(result=vad_, message=\"采集环境噪音成功\")\n\n\n# 停止录音\n@app.get(\"/asr/stopRecord\")\nasync def stopRecord():\n    audios.audios = b\"\"\n    aumanager.stop()\n    print(\"Online录音暂停\")\n    return SuccessRequest(message=\"停止成功\")\n\n\n# 恢复录音\n@app.get(\"/asr/resumeRecord\")\nasync def resumeRecord():\n    aumanager.resume()\n    print(\"Online录音恢复\")\n    return SuccessRequest(message=\"Online录音恢复\")\n\n\n# 聊天用的 ASR\n@app.websocket(\"/ws/asr/offlineStream\")\nasync def websocket_endpoint(websocket: WebSocket):\n    await manager.connect(websocket)\n    try:\n        while True:\n            asr_res = None\n            # websocket 不接收，只推送\n            data = await websocket.receive_bytes()\n            if not aumanager.is_pause:\n                asr_res = aumanager.stream_asr(data)\n            else:\n                print(\"录音暂停\")\n            if asr_res:\n                await manager.send_personal_message(asr_res, websocket)\n                aumanager.clear_asr()\n\n    except WebSocketDisconnect:\n        manager.disconnect(websocket)\n        # await manager.broadcast(f\"用户-{user}-离开\")\n        # print(f\"用户-{user}-离开\")\n\n\n    # 流式识别的 ASR\n@app.websocket('/ws/asr/onlineStream')\nasync def websocket_endpoint_online(websocket: WebSocket):\n    \"\"\"PaddleSpeech Online ASR Server api\n\n    Args:\n        websocket (WebSocket): the websocket instance\n    \"\"\"\n\n    #1. the interface wait to accept the websocket protocol header\n    #   and only we receive the header, it establish the connection with specific thread\n    await websocket.accept()\n\n    #2. if we accept the websocket headers, we will get the online asr engine instance\n    engine = chatbot.asr.engine\n\n    #3. each websocket connection, we will create an PaddleASRConnectionHanddler to process such audio\n    #   and each connection has its own connection instance to process the request\n    #   and only if client send the start signal, we create the PaddleASRConnectionHanddler instance\n    connection_handler = None\n\n    try:\n        #4. we do a loop to process the audio package by package according the protocol\n        #   and only if the client send finished signal, we will break the loop\n        while True:\n            # careful here, changed the source code from starlette.websockets\n            # 4.1 we wait for the client signal for the specific action\n            assert websocket.application_state == WebSocketState.CONNECTED\n            message = await websocket.receive()\n            websocket._raise_on_disconnect(message)\n\n            #4.2 text for the action command and bytes for pcm data\n            if \"text\" in message:\n                # we first parse the specific command\n                message = json.loads(message[\"text\"])\n                if 'signal' not in message:\n                    resp = {\"status\": \"ok\", \"message\": \"no valid json data\"}\n                    await websocket.send_json(resp)\n\n                # start command, we create the PaddleASRConnectionHanddler instance to process the audio data\n                # end command, we process the all the last audio pcm and return the final result\n                #              and we break the loop\n                if message['signal'] == 'start':\n                    resp = {\"status\": \"ok\", \"signal\": \"server_ready\"}\n                    # do something at beginning here\n                    # create the instance to process the audio\n                    # connection_handler = chatbot.asr.connection_handler\n                    connection_handler = PaddleASRConnectionHanddler(engine)\n                    await websocket.send_json(resp)\n                elif message['signal'] == 'end':\n                    # reset single  engine for an new connection\n                    # and we will destroy the connection\n                    connection_handler.decode(is_finished=True)\n                    connection_handler.rescoring()\n                    asr_results = connection_handler.get_result()\n                    connection_handler.reset()\n\n                    resp = {\n                        \"status\": \"ok\",\n                        \"signal\": \"finished\",\n                        'result': asr_results\n                    }\n                    await websocket.send_json(resp)\n                    break\n                else:\n                    resp = {\"status\": \"ok\", \"message\": \"no valid json data\"}\n                    await websocket.send_json(resp)\n            elif \"bytes\" in message:\n                # bytes for the pcm data\n                message = message[\"bytes\"]\n                print(\"###############\")\n                print(\"len message: \", len(message))\n                print(\"###############\")\n\n                # we extract the remained audio pcm \n                # and decode for the result in this package data\n                connection_handler.extract_feat(message)\n                connection_handler.decode(is_finished=False)\n                asr_results = connection_handler.get_result()\n\n                # return the current period result\n                # if the engine create the vad instance, this connection will have many period results \n                resp = {'result': asr_results}\n                print(resp)\n                await websocket.send_json(resp)\n    except WebSocketDisconnect:\n        pass\n\n\n######################################################################\n########################### NLP 服务 #################################\n#####################################################################\n\n\n@app.post(\"/nlp/chat\")\nasync def chatOffline(nlp_base: NlpBase):\n    chat = nlp_base.chat\n    if not chat:\n        return ErrorRequest(message=\"传入文本为空\")\n    else:\n        res = chatbot.chat(chat)\n        return SuccessRequest(result=res)\n\n\n@app.post(\"/nlp/ie\")\nasync def ieOffline(nlp_base: NlpBase):\n    nlp_text = nlp_base.chat\n    if not nlp_text:\n        return ErrorRequest(message=\"传入文本为空\")\n    else:\n        res = chatbot.ie(nlp_text)\n        return SuccessRequest(result=res)\n\n\n######################################################################\n########################### TTS 服务 #################################\n#####################################################################\n\n\n# 端到端合成\n@app.post(\"/tts/offline\")\nasync def text2speechOffline(tts_base: TtsBase):\n    text = tts_base.text\n    if not text:\n        return ErrorRequest(message=\"文本为空\")\n    else:\n        now_name = \"tts_\" + datetime.datetime.strftime(\n            datetime.datetime.now(), '%Y%m%d%H%M%S') + randName() + \".wav\"\n        out_file_path = os.path.join(WAV_PATH, now_name)\n        # 使用中英混合CLI\n        tts_model(\n            text=text,\n            output=out_file_path,\n            am='fastspeech2_mix',\n            spk_id=174,\n            voc='hifigan_csmsc',\n            lang='mix')\n        with open(out_file_path, \"rb\") as f:\n            data_bin = f.read()\n        base_str = base64.b64encode(data_bin)\n        return SuccessRequest(result=base_str)\n\n\n# http流式TTS\n@app.post(\"/tts/online\")\nasync def stream_tts(request_body: TtsBase):\n    text = request_body.text\n    return StreamingResponse(chatbot.text2speechStreamBytes(text=text))\n\n\n# ws流式TTS\n@app.websocket(\"/ws/tts/online\")\nasync def stream_ttsWS(websocket: WebSocket):\n    await manager.connect(websocket)\n    try:\n        while True:\n            text = await websocket.receive_text()\n            # 用 websocket 流式接收音频数据\n            if text:\n                for sub_wav in chatbot.text2speechStream(text=text):\n                    # print(\"发送sub wav: \", len(sub_wav))\n                    res = {\"wav\": sub_wav, \"done\": False}\n                    await websocket.send_json(res)\n\n                # 输送结束\n                res = {\"wav\": sub_wav, \"done\": True}\n                await websocket.send_json(res)\n            # manager.disconnect(websocket)\n\n    except WebSocketDisconnect:\n        manager.disconnect(websocket)\n\n\n######################################################################\n########################### VPR 服务 #################################\n#####################################################################\n\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"])\n\n\n@app.post('/vpr/enroll')\nasync def vpr_enroll(table_name: str=None,\n                     spk_id: str=Form(...),\n                     audio: UploadFile=File(...)):\n    # Enroll the uploaded audio with spk-id into MySQL\n    try:\n        if not spk_id:\n            return {'status': False, 'msg': \"spk_id can not be None\"}\n        # Save the upload data to server.\n        content = await audio.read()\n        now_name = \"vpr_enroll_\" + datetime.datetime.strftime(\n            datetime.datetime.now(), '%Y%m%d%H%M%S') + randName() + \".wav\"\n        audio_path = os.path.join(UPLOAD_PATH, now_name)\n\n        with open(audio_path, \"wb+\") as f:\n            f.write(content)\n        vpr.vpr_enroll(username=spk_id, wav_path=audio_path)\n        return {'status': True, 'msg': \"Successfully enroll data!\"}\n    except Exception as e:\n        return {'status': False, 'msg': e}\n\n\n@app.post('/vpr/recog')\nasync def vpr_recog(request: Request,\n                    table_name: str=None,\n                    audio: UploadFile=File(...)):\n    # Voice print recognition online\n    # try:\n    # Save the upload data to server.\n    content = await audio.read()\n    now_name = \"vpr_query_\" + datetime.datetime.strftime(\n        datetime.datetime.now(), '%Y%m%d%H%M%S') + randName() + \".wav\"\n    query_audio_path = os.path.join(UPLOAD_PATH, now_name)\n    with open(query_audio_path, \"wb+\") as f:\n        f.write(content)\n    spk_ids, paths, scores = vpr.do_search_vpr(query_audio_path)\n\n    res = dict(zip(spk_ids, zip(paths, scores)))\n    # Sort results by distance metric, closest distances first\n    res = sorted(res.items(), key=lambda item: item[1][1], reverse=True)\n    return res\n\n\n@app.post('/vpr/del')\nasync def vpr_del(spk_id: dict=None):\n    # Delete a record by spk_id in MySQL\n    try:\n        spk_id = spk_id['spk_id']\n        if not spk_id:\n            return {'status': False, 'msg': \"spk_id can not be None\"}\n        vpr.vpr_del(username=spk_id)\n        return {'status': True, 'msg': \"Successfully delete data!\"}\n    except Exception as e:\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/list')\nasync def vpr_list():\n    # Get all records in MySQL\n    try:\n        spk_ids, vpr_ids = vpr.do_list()\n        return spk_ids, vpr_ids\n    except Exception as e:\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/database64')\nasync def vpr_database64(vprId: int):\n    # Get the audio file from path by spk_id in MySQL\n    try:\n        if not vprId:\n            return {'status': False, 'msg': \"vpr_id can not be None\"}\n        audio_path = vpr.do_get_wav(vprId)\n        # 返回base64\n\n        # 将文件转成16k, 16bit类型的wav文件\n        wav, sr = librosa.load(audio_path, sr=16000)\n        wav = float2pcm(wav)  # float32 to int16\n        wav_bytes = wav.tobytes()  # to bytes\n        wav_base64 = base64.b64encode(wav_bytes).decode('utf8')\n\n        return SuccessRequest(result=wav_base64)\n    except Exception as e:\n        return {'status': False, 'msg': e}, 400\n\n\n@app.get('/vpr/data')\nasync def vpr_data(vprId: int):\n    # Get the audio file from path by spk_id in MySQL\n    try:\n        if not vprId:\n            return {'status': False, 'msg': \"vpr_id can not be None\"}\n        audio_path = vpr.do_get_wav(vprId)\n        return FileResponse(audio_path)\n    except Exception as e:\n        return {'status': False, 'msg': e}, 400\n\n\nif __name__ == '__main__':\n    uvicorn.run(app=app, host='0.0.0.0', port=port)\n"
  },
  {
    "path": "demos/speech_web/speech_server/requirements.txt",
    "content": "aiofiles\nfaiss-cpu\npraatio>=5.0.0\npydantic\npython-multipart\nstarlette\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/AudioManeger.py",
    "content": "import datetime\nimport os\nimport wave\n\nimport numpy as np\n\nfrom .util import randName\n\n\nclass AudioMannger:\n    def __init__(self,\n                 robot,\n                 frame_length=160,\n                 frame=10,\n                 data_width=2,\n                 vad_default=300):\n        # 二进制 pcm 流 \n        self.audios = b''\n        self.asr_result = \"\"\n        # Speech 核心主体\n        self.robot = robot\n\n        self.file_dir = \"source\"\n        os.makedirs(self.file_dir, exist_ok=True)\n        self.vad_deafult = vad_default\n        self.vad_threshold = vad_default\n        self.vad_threshold_path = os.path.join(self.file_dir,\n                                               \"vad_threshold.npy\")\n\n        # 10ms 一帧\n        self.frame_length = frame_length\n        # 10帧，检测一次 vad\n        self.frame = frame\n        # int 16, 两个bytes\n        self.data_width = data_width\n        # window\n        self.window_length = frame_length * frame * data_width\n\n        # 是否开始录音\n        self.on_asr = False\n        self.silence_cnt = 0\n        self.max_silence_cnt = 4\n        self.is_pause = False  # 录音暂停与恢复\n\n    def init(self):\n        if os.path.exists(self.vad_threshold_path):\n            # 平均响度文件存在\n            self.vad_threshold = np.load(self.vad_threshold_path)\n\n    def clear_audio(self):\n        # 清空 pcm 累积片段与 asr 识别结果\n        self.audios = b''\n\n    def clear_asr(self):\n        self.asr_result = \"\"\n\n    def compute_chunk_volume(self, start_index, pcm_bins):\n        # 根据帧长计算能量平均值\n        pcm_bin = pcm_bins[start_index:start_index + self.window_length]\n        # 转成 numpy\n        pcm_np = np.frombuffer(pcm_bin, np.int16)\n        # 归一化 + 计算响度\n        x = pcm_np.astype(np.float32)\n        x = np.abs(x)\n        return np.mean(x)\n\n    def is_speech(self, start_index, pcm_bins):\n        # 检查是否没\n        if start_index > len(pcm_bins):\n            return False\n        # 检查从这个 start 开始是否为静音帧\n        energy = self.compute_chunk_volume(\n            start_index=start_index, pcm_bins=pcm_bins)\n        # print(energy)\n        if energy > self.vad_threshold:\n            return True\n        else:\n            return False\n\n    def compute_env_volume(self, pcm_bins):\n        max_energy = 0\n        start = 0\n        while start < len(pcm_bins):\n            energy = self.compute_chunk_volume(\n                start_index=start, pcm_bins=pcm_bins)\n            if energy > max_energy:\n                max_energy = energy\n            start += self.window_length\n        self.vad_threshold = max_energy + 100 if max_energy > self.vad_deafult else self.vad_deafult\n\n        # 保存成文件\n        np.save(self.vad_threshold_path, self.vad_threshold)\n        print(f\"vad 阈值大小: {self.vad_threshold}\")\n        print(f\"环境采样保存: {os.path.realpath(self.vad_threshold_path)}\")\n\n    def stream_asr(self, pcm_bin):\n        # 先把 pcm_bin 送进去做端点检测\n        start = 0\n        while start < len(pcm_bin):\n            if self.is_speech(start_index=start, pcm_bins=pcm_bin):\n                self.on_asr = True\n                self.silence_cnt = 0\n                print(\"录音中\")\n                self.audios += pcm_bin[start:start + self.window_length]\n            else:\n                if self.on_asr:\n                    self.silence_cnt += 1\n                    if self.silence_cnt > self.max_silence_cnt:\n                        self.on_asr = False\n                        self.silence_cnt = 0\n                        # 录音停止\n                        print(\"录音停止\")\n                        # audios 保存为 wav, 送入 ASR\n                        if len(self.audios) > 2 * 16000:\n                            file_path = os.path.join(\n                                self.file_dir,\n                                \"asr_\" + datetime.datetime.strftime(\n                                    datetime.datetime.now(),\n                                    '%Y%m%d%H%M%S') + randName() + \".wav\")\n                            self.save_audio(file_path=file_path)\n                            self.asr_result = self.robot.speech2text(file_path)\n                        self.clear_audio()\n                        return self.asr_result\n                    else:\n                        # 正常接收\n                        print(\"录音中 静音\")\n                        self.audios += pcm_bin[start:start + self.window_length]\n            start += self.window_length\n        return \"\"\n\n    def save_audio(self, file_path):\n        print(\"保存音频\")\n        wf = wave.open(file_path, 'wb')  # 创建一个音频文件，名字为“01.wav\"\n        wf.setnchannels(1)  # 设置声道数为2\n        wf.setsampwidth(2)  # 设置采样深度为\n        wf.setframerate(16000)  # 设置采样率为16000\n        # 将数据写入创建的音频文件\n        wf.writeframes(self.audios)\n        # 写完后将文件关闭\n        wf.close()\n\n    def end(self):\n        # audios 保存为 wav, 送入 ASR\n        file_path = os.path.join(self.file_dir, \"asr.wav\")\n        self.save_audio(file_path=file_path)\n        return self.robot.speech2text(file_path)\n\n    def stop(self):\n        self.is_pause = True\n        self.audios = b''\n\n    def resume(self):\n        self.is_pause = False\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/asr.py",
    "content": "import numpy as np\n\nfrom paddlespeech.server.engine.asr.online.python.asr_engine import ASREngine\nfrom paddlespeech.server.engine.asr.online.python.asr_engine import PaddleASRConnectionHanddler\nfrom paddlespeech.server.utils.config import get_config\n\n\ndef readWave(samples):\n    x_len = len(samples)\n\n    chunk_size = 85 * 16  #80ms, sample_rate = 16kHz\n    if x_len % chunk_size != 0:\n        padding_len_x = chunk_size - x_len % chunk_size\n    else:\n        padding_len_x = 0\n\n    padding = np.zeros((padding_len_x), dtype=samples.dtype)\n    padded_x = np.concatenate([samples, padding], axis=0)\n\n    assert (x_len + padding_len_x) % chunk_size == 0\n    num_chunk = (x_len + padding_len_x) / chunk_size\n    num_chunk = int(num_chunk)\n    for i in range(0, num_chunk):\n        start = i * chunk_size\n        end = start + chunk_size\n        x_chunk = padded_x[start:end]\n        yield x_chunk\n\n\nclass ASR:\n    def __init__(\n            self,\n            config_path, ) -> None:\n        self.config = get_config(config_path)['asr_online']\n        self.engine = ASREngine()\n        self.engine.init(self.config)\n        self.connection_handler = PaddleASRConnectionHanddler(self.engine)\n\n    def offlineASR(self, samples, sample_rate=16000):\n        x_chunk, x_chunk_lens = self.engine.preprocess(\n            samples=samples, sample_rate=sample_rate)\n        self.engine.run(x_chunk, x_chunk_lens)\n        result = self.engine.postprocess()\n        self.engine.reset()\n        return result\n\n    def onlineASR(self, samples: bytes=None, is_finished=False):\n        if not is_finished:\n            # 流式开始\n            self.connection_handler.extract_feat(samples)\n            self.connection_handler.decode(is_finished)\n            asr_results = self.connection_handler.get_result()\n            return asr_results\n        else:\n            # 流式结束\n            self.connection_handler.decode(is_finished=True)\n            self.connection_handler.rescoring()\n            asr_results = self.connection_handler.get_result()\n            self.connection_handler.reset()\n            return asr_results\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/nlp.py",
    "content": "from paddlenlp import Taskflow\n\n\nclass NLP:\n    def __init__(self, ie_model_path=None):\n        schema = [\"时间\", \"出发地\", \"目的地\", \"费用\"]\n        if ie_model_path:\n            self.ie_model = Taskflow(\n                \"information_extraction\",\n                schema=schema,\n                task_path=ie_model_path)\n        else:\n            self.ie_model = Taskflow(\"information_extraction\", schema=schema)\n\n        self.dialogue_model = Taskflow(\"dialogue\")\n\n    def chat(self, text):\n        result = self.dialogue_model([text])\n        return result[0]\n\n    def ie(self, text):\n        result = self.ie_model(text)\n        return result\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/sql_helper.py",
    "content": "import base64\nimport os\nimport sqlite3\n\nimport numpy as np\n\n\ndef dict_factory(cursor, row):\n    d = {}\n    for idx, col in enumerate(cursor.description):\n        d[col[0]] = row[idx]\n    return d\n\n\nclass DataBase(object):\n    def __init__(self, db_path: str):\n        db_path = os.path.realpath(db_path)\n\n        if os.path.exists(db_path):\n            self.db_path = db_path\n        else:\n            db_path_dir = os.path.dirname(db_path)\n            os.makedirs(db_path_dir, exist_ok=True)\n            self.db_path = db_path\n\n        self.conn = sqlite3.connect(self.db_path)\n        self.conn.row_factory = dict_factory\n        self.cursor = self.conn.cursor()\n        self.init_database()\n\n    def init_database(self):\n        \"\"\"\n        初始化数据库， 若表不存在则创建\n        \"\"\"\n        sql = \"\"\"\n        CREATE TABLE IF NOT EXISTS vprtable (\n            `id` INTEGER PRIMARY KEY AUTOINCREMENT,\n            `username` TEXT NOT NULL,\n            `vector` TEXT NOT NULL,\n            `wavpath` TEXT  NOT NULL\n            ); \n        \"\"\"\n        self.cursor.execute(sql)\n        self.conn.commit()\n\n    def execute_base(self, sql, data_dict):\n        self.cursor.execute(sql, data_dict)\n        self.conn.commit()\n\n    def insert_one(self, username, vector_base64: str, wav_path):\n        if not os.path.exists(wav_path):\n            return None, \"wav not exists\"\n        else:\n            sql = \"\"\"\n            insert into \n            vprtable (username, vector, wavpath)\n            values (?, ?, ?)\n            \"\"\"\n\n            try:\n                self.cursor.execute(sql, (username, vector_base64, wav_path))\n                self.conn.commit()\n                lastidx = self.cursor.lastrowid\n                return lastidx, \"data insert success\"\n            except Exception as e:\n                print(e)\n                return None, e\n\n    def select_all(self):\n        sql = \"\"\"\n        SELECT * from vprtable\n        \"\"\"\n        result = self.cursor.execute(sql).fetchall()\n        return result\n\n    def select_by_id(self, vpr_id):\n        sql = f\"\"\"\n        SELECT * from vprtable WHERE `id` = {vpr_id}\n        \"\"\"\n\n        result = self.cursor.execute(sql).fetchall()\n        return result\n\n    def select_by_username(self, username):\n        sql = f\"\"\"\n        SELECT * from vprtable WHERE `username` = '{username}'\n        \"\"\"\n\n        result = self.cursor.execute(sql).fetchall()\n        return result\n\n    def drop_by_username(self, username):\n        sql = f\"\"\"\n        DELETE from vprtable WHERE `username`='{username}'\n        \"\"\"\n\n        self.cursor.execute(sql)\n        self.conn.commit()\n\n    def drop_all(self):\n        sql = \"\"\"\n        DELETE from vprtable\n        \"\"\"\n\n        self.cursor.execute(sql)\n        self.conn.commit()\n\n    def drop_table(self):\n        sql = \"\"\"\n            DROP TABLE vprtable\n        \"\"\"\n\n        self.cursor.execute(sql)\n        self.conn.commit()\n\n    def encode_vector(self, vector: np.ndarray):\n        return base64.b64encode(vector).decode('utf8')\n\n    def decode_vector(self, vector_base64, dtype=np.float32):\n        b = base64.b64decode(vector_base64)\n        vc = np.frombuffer(b, dtype=dtype)\n        return vc\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/tts.py",
    "content": "# tts 推理引擎，支持流式与非流式\n# 精简化使用\n# 用 onnxruntime 进行推理\n# 1. 下载对应的模型\n# 2. 加载模型\n# 3. 端到端推理\n# 4. 流式推理\nimport base64\nimport logging\nimport math\n\nimport numpy as np\n\nfrom paddlespeech.server.engine.tts.online.onnx.tts_engine import TTSEngine\nfrom paddlespeech.server.utils.audio_process import float2pcm\nfrom paddlespeech.server.utils.config import get_config\nfrom paddlespeech.server.utils.util import denorm\nfrom paddlespeech.server.utils.util import get_chunks\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\n\nclass TTS:\n    def __init__(self, config_path):\n        self.config = get_config(config_path)['tts_online-onnx']\n        self.config['voc_block'] = 36\n        self.engine = TTSEngine()\n        self.engine.init(self.config)\n        self.executor = self.engine.executor\n        #self.engine.warm_up()\n\n        # 前端初始化\n        self.frontend = Frontend(\n            phone_vocab_path=self.engine.executor.phones_dict,\n            tone_vocab_path=None)\n\n    def depadding(self, data, chunk_num, chunk_id, block, pad, upsample):\n        \"\"\" \n        Streaming inference removes the result of pad inference\n        \"\"\"\n        front_pad = min(chunk_id * block, pad)\n        # first chunk\n        if chunk_id == 0:\n            data = data[:block * upsample]\n        # last chunk\n        elif chunk_id == chunk_num - 1:\n            data = data[front_pad * upsample:]\n        # middle chunk\n        else:\n            data = data[front_pad * upsample:(front_pad + block) * upsample]\n\n        return data\n\n    def offlineTTS(self, text):\n        get_tone_ids = False\n        merge_sentences = False\n\n        input_ids = self.frontend.get_input_ids(\n            text, merge_sentences=merge_sentences, get_tone_ids=get_tone_ids)\n        phone_ids = input_ids[\"phone_ids\"]\n        wav_list = []\n        for i in range(len(phone_ids)):\n            orig_hs = self.engine.executor.am_encoder_infer_sess.run(\n                None, input_feed={'text': phone_ids[i].numpy()})\n            hs = orig_hs[0]\n            am_decoder_output = self.engine.executor.am_decoder_sess.run(\n                None, input_feed={'xs': hs})\n            am_postnet_output = self.engine.executor.am_postnet_sess.run(\n                None,\n                input_feed={\n                    'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                })\n            am_output_data = am_decoder_output + np.transpose(\n                am_postnet_output[0], (0, 2, 1))\n            normalized_mel = am_output_data[0][0]\n            mel = denorm(normalized_mel, self.engine.executor.am_mu,\n                         self.engine.executor.am_std)\n            wav = self.engine.executor.voc_sess.run(\n                output_names=None, input_feed={'logmel': mel})[0]\n            wav_list.append(wav)\n        wavs = np.concatenate(wav_list)\n        return wavs\n\n    def streamTTS(self, text):\n\n        get_tone_ids = False\n        merge_sentences = False\n\n        # front \n        input_ids = self.frontend.get_input_ids(\n            text, merge_sentences=merge_sentences, get_tone_ids=get_tone_ids)\n        phone_ids = input_ids[\"phone_ids\"]\n\n        for i in range(len(phone_ids)):\n            part_phone_ids = phone_ids[i].numpy()\n            voc_chunk_id = 0\n\n            # fastspeech2_csmsc\n            if self.config.am == \"fastspeech2_csmsc_onnx\":\n                # am \n                mel = self.executor.am_sess.run(\n                    output_names=None, input_feed={'text': part_phone_ids})\n                mel = mel[0]\n\n                # voc streaming\n                mel_chunks = get_chunks(mel, self.config.voc_block,\n                                        self.config.voc_pad, \"voc\")\n                voc_chunk_num = len(mel_chunks)\n                for i, mel_chunk in enumerate(mel_chunks):\n                    sub_wav = self.executor.voc_sess.run(\n                        output_names=None, input_feed={'logmel': mel_chunk})\n                    sub_wav = self.depadding(\n                        sub_wav[0], voc_chunk_num, i, self.config.voc_block,\n                        self.config.voc_pad, self.config.voc_upsample)\n\n                    yield self.after_process(sub_wav)\n\n            # fastspeech2_cnndecoder_csmsc \n            elif self.config.am == \"fastspeech2_cnndecoder_csmsc_onnx\":\n                # am \n                orig_hs = self.executor.am_encoder_infer_sess.run(\n                    None, input_feed={'text': part_phone_ids})\n                orig_hs = orig_hs[0]\n\n                # streaming voc chunk info\n                mel_len = orig_hs.shape[1]\n                voc_chunk_num = math.ceil(mel_len / self.config.voc_block)\n                start = 0\n                end = min(self.config.voc_block + self.config.voc_pad, mel_len)\n\n                # streaming am\n                hss = get_chunks(orig_hs, self.config.am_block,\n                                 self.config.am_pad, \"am\")\n                am_chunk_num = len(hss)\n                for i, hs in enumerate(hss):\n                    am_decoder_output = self.executor.am_decoder_sess.run(\n                        None, input_feed={'xs': hs})\n                    am_postnet_output = self.executor.am_postnet_sess.run(\n                        None,\n                        input_feed={\n                            'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                        })\n                    am_output_data = am_decoder_output + np.transpose(\n                        am_postnet_output[0], (0, 2, 1))\n                    normalized_mel = am_output_data[0][0]\n\n                    sub_mel = denorm(normalized_mel, self.executor.am_mu,\n                                     self.executor.am_std)\n                    sub_mel = self.depadding(sub_mel, am_chunk_num, i,\n                                             self.config.am_block,\n                                             self.config.am_pad, 1)\n\n                    if i == 0:\n                        mel_streaming = sub_mel\n                    else:\n                        mel_streaming = np.concatenate(\n                            (mel_streaming, sub_mel), axis=0)\n\n                    # streaming voc\n                    # 当流式AM推理的mel帧数大于流式voc推理的chunk size，开始进行流式voc 推理\n                    while (mel_streaming.shape[0] >= end and\n                           voc_chunk_id < voc_chunk_num):\n                        voc_chunk = mel_streaming[start:end, :]\n\n                        sub_wav = self.executor.voc_sess.run(\n                            output_names=None, input_feed={'logmel': voc_chunk})\n                        sub_wav = self.depadding(\n                            sub_wav[0], voc_chunk_num, voc_chunk_id,\n                            self.config.voc_block, self.config.voc_pad,\n                            self.config.voc_upsample)\n\n                        yield self.after_process(sub_wav)\n\n                        voc_chunk_id += 1\n                        start = max(0, voc_chunk_id * self.config.voc_block -\n                                    self.config.voc_pad)\n                        end = min((voc_chunk_id + 1) * self.config.voc_block +\n                                  self.config.voc_pad, mel_len)\n\n            else:\n                logging.error(\n                    \"Only support fastspeech2_csmsc or fastspeech2_cnndecoder_csmsc on streaming tts.\"\n                )\n\n    def streamTTSBytes(self, text):\n        for wav in self.engine.executor.infer(\n                text=text,\n                lang=self.engine.config.lang,\n                am=self.engine.config.am,\n                spk_id=0):\n            wav = float2pcm(wav)  # float32 to int16\n            wav_bytes = wav.tobytes()  # to bytes\n            yield wav_bytes\n\n    def after_process(self, wav):\n        # for tvm\n        wav = float2pcm(wav)  # float32 to int16\n        wav_bytes = wav.tobytes()  # to bytes\n        wav_base64 = base64.b64encode(wav_bytes).decode('utf8')  # to base64\n        return wav_base64\n\n    def streamTTS_TVM(self, text):\n        # 用 TVM 优化\n        pass\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/vpr.py",
    "content": "# vpr Demo 没有使用 mysql 与 muilvs, 仅用于docker演示\nimport logging\n\nimport faiss\nimport numpy as np\n\nfrom .sql_helper import DataBase\nfrom .vpr_encode import get_audio_embedding\n\n\nclass VPR:\n    def __init__(self, db_path, dim, top_k) -> None:\n        # 初始化\n        self.db_path = db_path\n        self.dim = dim\n        self.top_k = top_k\n        self.dtype = np.float32\n        self.vpr_idx = 0\n\n        # db 初始化\n        self.db = DataBase(db_path)\n\n        # faiss 初始化\n        index_ip = faiss.IndexFlatIP(dim)\n        self.index_ip = faiss.IndexIDMap(index_ip)\n        self.init()\n\n    def init(self):\n        # demo 初始化，把 mysql中的向量注册到 faiss 中\n        sql_dbs = self.db.select_all()\n        if sql_dbs:\n            for sql_db in sql_dbs:\n                idx = sql_db['id']\n                vc_bs64 = sql_db['vector']\n                vc = self.db.decode_vector(vc_bs64)\n                if len(vc.shape) == 1:\n                    vc = np.expand_dims(vc, axis=0)\n                # 构建数据库\n                self.index_ip.add_with_ids(vc, np.array(\n                    (idx, )).astype('int64'))\n            logging.info(\"faiss 构建完毕\")\n\n    def faiss_enroll(self, idx, vc):\n        self.index_ip.add_with_ids(vc, np.array((idx, )).astype('int64'))\n\n    def vpr_enroll(self, username, wav_path):\n        # 注册声纹\n        emb = get_audio_embedding(wav_path)\n        emb = np.expand_dims(emb, axis=0)\n        if emb is not None:\n            emb_bs64 = self.db.encode_vector(emb)\n            last_idx, mess = self.db.insert_one(username, emb_bs64, wav_path)\n            if last_idx:\n                # faiss 注册\n                self.faiss_enroll(last_idx, emb)\n        else:\n            last_idx, mess = None\n        return last_idx\n\n    def vpr_recog(self, wav_path):\n        # 识别声纹\n        emb_search = get_audio_embedding(wav_path)\n\n        if emb_search is not None:\n            emb_search = np.expand_dims(emb_search, axis=0)\n            D, I = self.index_ip.search(emb_search, self.top_k)\n            D = D.tolist()[0]\n            I = I.tolist()[0]\n            return [(round(D[i] * 100, 2), I[i]) for i in range(len(D))\n                    if I[i] != -1]\n        else:\n            logging.error(\"识别失败\")\n            return None\n\n    def do_search_vpr(self, wav_path):\n        spk_ids, paths, scores = [], [], []\n        recog_result = self.vpr_recog(wav_path)\n        for score, idx in recog_result:\n            username = self.db.select_by_id(idx)[0]['username']\n            if username not in spk_ids:\n                spk_ids.append(username)\n                scores.append(score)\n                paths.append(\"\")\n        return spk_ids, paths, scores\n\n    def vpr_del(self, username):\n        # 根据用户username, 删除声纹\n        # 查用户ID，删除对应向量\n        res = self.db.select_by_username(username)\n        for r in res:\n            idx = r['id']\n            self.index_ip.remove_ids(np.array((idx, )).astype('int64'))\n\n        self.db.drop_by_username(username)\n\n    def vpr_list(self):\n        # 获取数据列表\n        return self.db.select_all()\n\n    def do_list(self):\n        spk_ids, vpr_ids = [], []\n        for res in self.db.select_all():\n            spk_ids.append(res['username'])\n            vpr_ids.append(res['id'])\n        return spk_ids, vpr_ids\n\n    def do_get_wav(self, vpr_idx):\n        res = self.db.select_by_id(vpr_idx)\n        return res[0]['wavpath']\n\n    def vpr_data(self, idx):\n        # 获取对应ID的数据\n        res = self.db.select_by_id(idx)\n        return res\n\n    def vpr_droptable(self):\n        # 删除表\n        self.db.drop_table()\n        # 清空 faiss\n        self.index_ip.reset()\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/SpeechBase/vpr_encode.py",
    "content": "import logging\n\nimport numpy as np\n\nfrom paddlespeech.cli.vector import VectorExecutor\n\nvector_executor = VectorExecutor()\n\n\ndef get_audio_embedding(path):\n    \"\"\"\n    Use vpr_inference to generate embedding of audio\n    \"\"\"\n    try:\n        embedding = vector_executor(\n            audio_file=path, model='ecapatdnn_voxceleb12')\n        embedding = embedding / np.linalg.norm(embedding)\n        return embedding\n    except Exception as e:\n        logging.error(f\"Error with embedding:{e}\")\n        return None\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/WebsocketManeger.py",
    "content": "from typing import List\n\nfrom fastapi import WebSocket\n\n\nclass ConnectionManager:\n    def __init__(self):\n        # 存放激活的ws连接对象\n        self.active_connections: List[WebSocket] = []\n\n    async def connect(self, ws: WebSocket):\n        # 等待连接\n        await ws.accept()\n        # 存储ws连接对象\n        self.active_connections.append(ws)\n\n    def disconnect(self, ws: WebSocket):\n        # 关闭时 移除ws对象\n        self.active_connections.remove(ws)\n\n    @staticmethod\n    async def send_personal_message(message: str, ws: WebSocket):\n        # 发送个人消息\n        await ws.send_text(message)\n\n    async def broadcast(self, message: str):\n        # 广播消息\n        for connection in self.active_connections:\n            await connection.send_text(message)\n\n\nmanager = ConnectionManager()\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/ernie_sat.py",
    "content": "import os\n\nfrom .util import get_ngpu\nfrom .util import MAIN_ROOT\nfrom .util import run_cmd\n\n\nclass SAT:\n    def __init__(self):\n        # pretrain model path\n        self.zh_pretrain_model_path = os.path.realpath(\n            \"source/model/erniesat_aishell3_ckpt_1.2.0\")\n        self.en_pretrain_model_path = os.path.realpath(\n            \"source/model/erniesat_vctk_ckpt_1.2.0\")\n        self.cross_pretrain_model_path = os.path.realpath(\n            \"source/model/erniesat_aishell3_vctk_ckpt_1.2.0\")\n\n        self.zh_voc_model_path = os.path.realpath(\n            \"source/model/hifigan_aishell3_ckpt_0.2.0\")\n        self.eb_voc_model_path = os.path.realpath(\n            \"source/model/hifigan_vctk_ckpt_0.2.0\")\n        self.cross_voc_model_path = os.path.realpath(\n            \"source/model/hifigan_aishell3_ckpt_0.2.0\")\n\n        self.BIN_DIR = os.path.join(MAIN_ROOT,\n                                    \"paddlespeech/t2s/exps/ernie_sat\")\n\n    def zh_synthesize_edit(self,\n                           old_str: str,\n                           new_str: str,\n                           input_name: os.PathLike,\n                           output_name: os.PathLike,\n                           task_name: str=\"synthesize\",\n                           erniesat_ckpt_name: str=\"snapshot_iter_289500.pdz\"):\n\n        if task_name not in ['synthesize', 'edit']:\n            print(\"task name only in ['edit', 'synthesize']\")\n            return None\n\n        # 推理文件配置\n        config_path = os.path.join(self.zh_pretrain_model_path, \"default.yaml\")\n        phones_dict = os.path.join(self.zh_pretrain_model_path,\n                                   \"phone_id_map.txt\")\n        erniesat_ckpt = os.path.join(self.zh_pretrain_model_path,\n                                     erniesat_ckpt_name)\n        erniesat_stat = os.path.join(self.zh_pretrain_model_path,\n                                     \"speech_stats.npy\")\n\n        voc = \"hifigan_aishell3\"\n        voc_config = os.path.join(self.zh_voc_model_path, \"default.yaml\")\n        voc_ckpt = os.path.join(self.zh_voc_model_path,\n                                \"snapshot_iter_2500000.pdz\")\n        voc_stat = os.path.join(self.zh_voc_model_path, \"feats_stats.npy\")\n\n        cmd = self.get_cmd(\n            task_name=task_name,\n            input_name=input_name,\n            old_str=old_str,\n            new_str=new_str,\n            config_path=config_path,\n            phones_dict=phones_dict,\n            erniesat_ckpt=erniesat_ckpt,\n            erniesat_stat=erniesat_stat,\n            voc=voc,\n            voc_config=voc_config,\n            voc_ckpt=voc_ckpt,\n            voc_stat=voc_stat,\n            output_name=output_name,\n            source_lang=\"zh\",\n            target_lang=\"zh\")\n\n        return run_cmd(cmd, output_name)\n\n    def crossclone(self,\n                   old_str: str,\n                   new_str: str,\n                   input_name: os.PathLike,\n                   output_name: os.PathLike,\n                   source_lang: str,\n                   target_lang: str,\n                   erniesat_ckpt_name: str=\"snapshot_iter_489000.pdz\"):\n        # 推理文件配置\n        config_path = os.path.join(self.cross_pretrain_model_path,\n                                   \"default.yaml\")\n        phones_dict = os.path.join(self.cross_pretrain_model_path,\n                                   \"phone_id_map.txt\")\n        erniesat_ckpt = os.path.join(self.cross_pretrain_model_path,\n                                     erniesat_ckpt_name)\n        erniesat_stat = os.path.join(self.cross_pretrain_model_path,\n                                     \"speech_stats.npy\")\n\n        voc = \"hifigan_aishell3\"\n        voc_config = os.path.join(self.cross_voc_model_path, \"default.yaml\")\n        voc_ckpt = os.path.join(self.cross_voc_model_path,\n                                \"snapshot_iter_2500000.pdz\")\n        voc_stat = os.path.join(self.cross_voc_model_path, \"feats_stats.npy\")\n        task_name = \"synthesize\"\n        cmd = self.get_cmd(\n            task_name=task_name,\n            input_name=input_name,\n            old_str=old_str,\n            new_str=new_str,\n            config_path=config_path,\n            phones_dict=phones_dict,\n            erniesat_ckpt=erniesat_ckpt,\n            erniesat_stat=erniesat_stat,\n            voc=voc,\n            voc_config=voc_config,\n            voc_ckpt=voc_ckpt,\n            voc_stat=voc_stat,\n            output_name=output_name,\n            source_lang=source_lang,\n            target_lang=target_lang)\n\n        return run_cmd(cmd, output_name)\n\n    def en_synthesize_edit(self,\n                           old_str: str,\n                           new_str: str,\n                           input_name: os.PathLike,\n                           output_name: os.PathLike,\n                           task_name: str=\"synthesize\",\n                           erniesat_ckpt_name: str=\"snapshot_iter_199500.pdz\"):\n\n        # 推理文件配置\n        config_path = os.path.join(self.en_pretrain_model_path, \"default.yaml\")\n        phones_dict = os.path.join(self.en_pretrain_model_path,\n                                   \"phone_id_map.txt\")\n        erniesat_ckpt = os.path.join(self.en_pretrain_model_path,\n                                     erniesat_ckpt_name)\n        erniesat_stat = os.path.join(self.en_pretrain_model_path,\n                                     \"speech_stats.npy\")\n\n        voc = \"hifigan_aishell3\"\n        voc_config = os.path.join(self.zh_voc_model_path, \"default.yaml\")\n        voc_ckpt = os.path.join(self.zh_voc_model_path,\n                                \"snapshot_iter_2500000.pdz\")\n        voc_stat = os.path.join(self.zh_voc_model_path, \"feats_stats.npy\")\n\n        cmd = self.get_cmd(\n            task_name=task_name,\n            input_name=input_name,\n            old_str=old_str,\n            new_str=new_str,\n            config_path=config_path,\n            phones_dict=phones_dict,\n            erniesat_ckpt=erniesat_ckpt,\n            erniesat_stat=erniesat_stat,\n            voc=voc,\n            voc_config=voc_config,\n            voc_ckpt=voc_ckpt,\n            voc_stat=voc_stat,\n            output_name=output_name,\n            source_lang=\"en\",\n            target_lang=\"en\")\n\n        return run_cmd(cmd, output_name)\n\n    def get_cmd(self,\n                task_name: str,\n                input_name: str,\n                old_str: str,\n                new_str: str,\n                config_path: str,\n                phones_dict: str,\n                erniesat_ckpt: str,\n                erniesat_stat: str,\n                voc: str,\n                voc_config: str,\n                voc_ckpt: str,\n                voc_stat: str,\n                output_name: str,\n                source_lang: str,\n                target_lang: str):\n        ngpu = get_ngpu()\n        cmd = f\"\"\"\n            FLAGS_allocator_strategy=naive_best_fit \\\n            FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n            python3 {self.BIN_DIR}/synthesize_e2e.py \\\n                --task_name={task_name} \\\n                --wav_path={input_name} \\\n                --old_str='{old_str}' \\\n                --new_str='{new_str}' \\\n                --source_lang={source_lang} \\\n                --target_lang={target_lang} \\\n                --erniesat_config={config_path} \\\n                --phones_dict={phones_dict} \\\n                --erniesat_ckpt={erniesat_ckpt} \\\n                --erniesat_stat={erniesat_stat} \\\n                --voc={voc} \\\n                --voc_config={voc_config} \\\n                --voc_ckpt={voc_ckpt} \\\n                --voc_stat={voc_stat} \\\n                --output_name={output_name} \\\n                --ngpu={ngpu}\n        \"\"\"\n\n        return cmd\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/finetune.py",
    "content": "import os\n\nfrom .util import get_ngpu\nfrom .util import MAIN_ROOT\nfrom .util import run_cmd\n\n\ndef find_max_ckpt(model_path):\n    max_ckpt = 0\n    for filename in os.listdir(model_path):\n        if filename.endswith('.pdz'):\n            files = filename[:-4]\n            a1, a2, it = files.split(\"_\")\n            if int(it) > max_ckpt:\n                max_ckpt = int(it)\n    return max_ckpt\n\n\nclass FineTune:\n    def __init__(self):\n        self.now_file_path = os.path.dirname(__file__)\n        self.PYTHONPATH = os.path.join(MAIN_ROOT,\n                                       \"examples/other/tts_finetune/tts3\")\n        self.BIN_DIR = os.path.join(MAIN_ROOT,\n                                    \"paddlespeech/t2s/exps/fastspeech2\")\n        self.pretrained_model_dir = os.path.realpath(\n            \"source/model/fastspeech2_aishell3_ckpt_1.1.0\")\n        self.voc_model_dir = os.path.realpath(\n            \"source/model/hifigan_aishell3_ckpt_0.2.0\")\n        self.finetune_config = os.path.join(\"conf/tts3_finetune.yaml\")\n\n    def finetune(self, input_dir, exp_dir='temp', epoch=100):\n        \"\"\"\n        use cmd follow examples/other/tts_finetune/tts3/run.sh\n        \"\"\"\n        newdir_name = \"newdir\"\n        new_dir = os.path.join(input_dir, newdir_name)\n        mfa_dir = os.path.join(exp_dir, 'mfa_result')\n        dump_dir = os.path.join(exp_dir, 'dump')\n        output_dir = os.path.join(exp_dir, 'exp')\n        lang = \"zh\"\n        ngpu = get_ngpu()\n\n        cmd = f\"\"\"\n            # check oov\n            python3 {self.PYTHONPATH}/local/check_oov.py \\\n                --input_dir={input_dir} \\\n                --pretrained_model_dir={self.pretrained_model_dir} \\\n                --newdir_name={newdir_name} \\\n                --lang={lang}\n            \n            # get mfa result\n            python3 {self.PYTHONPATH}/local/get_mfa_result.py \\\n                --input_dir={new_dir} \\\n                --mfa_dir={mfa_dir} \\\n                --lang={lang}\n            \n            # generate durations.txt\n            python3 {self.PYTHONPATH}/local/generate_duration.py \\\n                --mfa_dir={mfa_dir} \n            \n            # extract feature\n            python3 {self.PYTHONPATH}/local/extract_feature.py \\\n                --duration_file=\"./durations.txt\" \\\n                --input_dir={new_dir} \\\n                --dump_dir={dump_dir} \\\n                --pretrained_model_dir={self.pretrained_model_dir}\n            \n            # create finetune env\n            python3 {self.PYTHONPATH}/local/prepare_env.py \\\n                --pretrained_model_dir={self.pretrained_model_dir} \\\n                --output_dir={output_dir}\n            \n            # finetune\n            python3 {self.PYTHONPATH}/local/finetune.py \\\n                --pretrained_model_dir={self.pretrained_model_dir} \\\n                --dump_dir={dump_dir} \\\n                --output_dir={output_dir} \\\n                --ngpu={ngpu} \\\n                --epoch=100 \\\n                --finetune_config={self.finetune_config}\n        \"\"\"\n\n        print(cmd)\n\n        return run_cmd(cmd, exp_dir)\n\n    def synthesize(self, text, wav_name, out_wav_dir, exp_dir='temp'):\n\n        voc = \"hifigan_aishell3\"\n        dump_dir = os.path.join(exp_dir, 'dump')\n        output_dir = os.path.join(exp_dir, 'exp')\n        text_path = os.path.join(exp_dir, 'sentences.txt')\n        lang = \"zh\"\n        ngpu = get_ngpu()\n\n        model_path = f\"{output_dir}/checkpoints\"\n        ckpt = find_max_ckpt(model_path)\n\n        # 生成对应的语句\n        with open(text_path, \"w\", encoding='utf8') as f:\n            f.write(wav_name + \" \" + text)\n\n        cmd = f\"\"\"\n            FLAGS_allocator_strategy=naive_best_fit \\\n            FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n            python3 {self.BIN_DIR}/../synthesize_e2e.py \\\n                --am=fastspeech2_aishell3 \\\n                --am_config={self.pretrained_model_dir}/default.yaml \\\n                --am_ckpt={output_dir}/checkpoints/snapshot_iter_{ckpt}.pdz \\\n                --am_stat={self.pretrained_model_dir}/speech_stats.npy \\\n                --voc={voc} \\\n                --voc_config={self.voc_model_dir}/default.yaml \\\n                --voc_ckpt={self.voc_model_dir}/snapshot_iter_2500000.pdz \\\n                --voc_stat={self.voc_model_dir}/feats_stats.npy \\\n                --lang={lang} \\\n                --text={text_path} \\\n                --output_dir={out_wav_dir} \\\n                --phones_dict={dump_dir}/phone_id_map.txt \\\n                --speaker_dict={dump_dir}/speaker_id_map.txt \\\n                --spk_id=0 \\\n                --ngpu={ngpu}\n        \"\"\"\n\n        out_path = os.path.join(out_wav_dir, f\"{wav_name}.wav\")\n\n        return run_cmd(cmd, out_path)\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/ge2e_clone.py",
    "content": "import os\nimport shutil\n\nfrom .util import get_ngpu\nfrom .util import MAIN_ROOT\nfrom .util import run_cmd\n\n\nclass VoiceCloneGE2E():\n    def __init__(self):\n        # Path 到指定路径上\n        self.BIN_DIR = os.path.join(MAIN_ROOT, \"paddlespeech/t2s/exps\")\n        # am\n        self.am = \"fastspeech2_aishell3\"\n        self.am_config = \"source/model/fastspeech2_nosil_aishell3_vc1_ckpt_0.5/default.yaml\"\n        self.am_ckpt = \"source/model/fastspeech2_nosil_aishell3_vc1_ckpt_0.5/snapshot_iter_96400.pdz\"\n        self.am_stat = \"source/model/fastspeech2_nosil_aishell3_vc1_ckpt_0.5/speech_stats.npy\"\n        self.phones_dict = \"source/model/fastspeech2_nosil_aishell3_vc1_ckpt_0.5/phone_id_map.txt\"\n        # voc\n        self.voc = \"pwgan_aishell3\"\n        self.voc_config = \"source/model/pwg_aishell3_ckpt_0.5/default.yaml\"\n        self.voc_ckpt = \"source/model/pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz\"\n        self.voc_stat = \"source/model/pwg_aishell3_ckpt_0.5/feats_stats.npy\"\n        # ge2e\n        self.ge2e_params_path = \"source/model/ge2e_ckpt_0.3/step-3000000.pdparams\"\n\n    def vc(self, text, input_wav, out_wav):\n\n        # input wav 需要形成临时单独文件夹\n        _, full_file_name = os.path.split(input_wav)\n        ref_audio_dir = os.path.realpath(\"tmp_dir/ge2e\")\n        if os.path.exists(ref_audio_dir):\n            shutil.rmtree(ref_audio_dir)\n\n        os.makedirs(ref_audio_dir, exist_ok=True)\n        shutil.copy(input_wav, ref_audio_dir)\n\n        output_dir = os.path.dirname(out_wav)\n        ngpu = get_ngpu()\n\n        cmd = f\"\"\"python {self.BIN_DIR}/voice_cloning.py --am={self.am} --am_config={self.am_config} --am_ckpt={self.am_ckpt} --am_stat={self.am_stat} --voc={self.voc} --voc_config={self.voc_config} --voc_ckpt={self.voc_ckpt} --voc_stat={self.voc_stat} --ge2e_params_path={self.ge2e_params_path} --text=\"{text}\" --input-dir={ref_audio_dir} --output-dir={output_dir} --phones-dict={self.phones_dict} --ngpu={ngpu}\"\"\"\n\n        print(cmd)\n\n        output_name = os.path.join(output_dir, full_file_name)\n        return run_cmd(cmd, output_name=output_name)\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/robot.py",
    "content": "import os\n\nimport soundfile as sf\nfrom src.SpeechBase.asr import ASR\nfrom src.SpeechBase.nlp import NLP\nfrom src.SpeechBase.tts import TTS\n\nfrom paddlespeech.cli.asr.infer import ASRExecutor\n\n\nclass Robot:\n    def __init__(self,\n                 asr_config,\n                 tts_config,\n                 asr_init_path,\n                 ie_model_path=None) -> None:\n        self.nlp = NLP(ie_model_path=ie_model_path)\n        self.asr = ASR(config_path=asr_config)\n        self.tts = TTS(config_path=tts_config)\n        self.tts_sample_rate = 24000\n        self.asr_sample_rate = 16000\n\n        # 流式识别效果不如端到端的模型，这里流式模型与端到端模型分开\n        self.asr_model = ASRExecutor()\n        self.asr_name = \"conformer_wenetspeech\"\n        self.warm_up_asrmodel(asr_init_path)\n\n    def warm_up_asrmodel(self, asr_init_path):\n        if not os.path.exists(asr_init_path):\n            path_dir = os.path.dirname(asr_init_path)\n            if not os.path.exists(path_dir):\n                os.makedirs(path_dir, exist_ok=True)\n\n            # TTS生成，采样率24000\n            text = \"生成初始音频\"\n            self.text2speech(text, asr_init_path)\n\n        # asr model初始化\n        self.asr_model(\n            asr_init_path,\n            model=self.asr_name,\n            lang='zh',\n            sample_rate=16000,\n            force_yes=True)\n\n    def speech2text(self, audio_file):\n        self.asr_model.preprocess(self.asr_name, audio_file)\n        self.asr_model.infer(self.asr_name)\n        res = self.asr_model.postprocess()\n        return res\n\n    def text2speech(self, text, outpath):\n        wav = self.tts.offlineTTS(text)\n        sf.write(outpath, wav, samplerate=self.tts_sample_rate)\n        res = wav\n        return res\n\n    def text2speechStream(self, text):\n        for sub_wav_base64 in self.tts.streamTTS(text=text):\n            yield sub_wav_base64\n\n    def text2speechStreamBytes(self, text):\n        for wav_bytes in self.tts.streamTTSBytes(text=text):\n            yield wav_bytes\n\n    def chat(self, text):\n        result = self.nlp.chat(text)\n        return result\n\n    def ie(self, text):\n        result = self.nlp.ie(text)\n        return result\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/tdnn_clone.py",
    "content": "import os\nimport shutil\n\nfrom .util import get_ngpu\nfrom .util import MAIN_ROOT\nfrom .util import run_cmd\n\n\nclass VoiceCloneTDNN():\n    def __init__(self):\n        # Path 到指定路径上\n        self.BIN_DIR = os.path.join(MAIN_ROOT, \"paddlespeech/t2s/exps\")\n\n        self.am = \"fastspeech2_aishell3\"\n        self.am_config = \"source/model/fastspeech2_aishell3_ckpt_vc2_1.2.0/default.yaml\"\n        self.am_ckpt = \"source/model/fastspeech2_aishell3_ckpt_vc2_1.2.0/snapshot_iter_96400.pdz\"\n        self.am_stat = \"source/model/fastspeech2_aishell3_ckpt_vc2_1.2.0/speech_stats.npy\"\n        self.phones_dict = \"source/model/fastspeech2_aishell3_ckpt_vc2_1.2.0/phone_id_map.txt\"\n        # voc\n        self.voc = \"pwgan_aishell3\"\n        self.voc_config = \"source/model/pwg_aishell3_ckpt_0.5/default.yaml\"\n        self.voc_ckpt = \"source/model/pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz\"\n        self.voc_stat = \"source/model/pwg_aishell3_ckpt_0.5/feats_stats.npy\"\n\n    def vc(self, text, input_wav, out_wav):\n        # input wav 需要形成临时单独文件夹\n        _, full_file_name = os.path.split(input_wav)\n        ref_audio_dir = os.path.realpath(\"tmp_dir/tdnn\")\n        if os.path.exists(ref_audio_dir):\n            shutil.rmtree(ref_audio_dir)\n        os.makedirs(ref_audio_dir, exist_ok=True)\n        shutil.copy(input_wav, ref_audio_dir)\n\n        output_dir = os.path.dirname(out_wav)\n        ngpu = get_ngpu()\n\n        cmd = f\"\"\"\n            python3 {self.BIN_DIR}/voice_cloning.py \\\n                    --am={self.am} \\\n                    --am_config={self.am_config} \\\n                    --am_ckpt={self.am_ckpt} \\\n                    --am_stat={self.am_stat} \\\n                    --voc={self.voc} \\\n                    --voc_config={self.voc_config} \\\n                    --voc_ckpt={self.voc_ckpt} \\\n                    --voc_stat={self.voc_stat} \\\n                    --text=\"{text}\" \\\n                    --input-dir={ref_audio_dir} \\\n                    --output-dir={output_dir} \\\n                    --phones-dict={self.phones_dict} \\\n                    --use_ecapa=True \\\n                    --ngpu={ngpu}\n        \"\"\"\n\n        output_name = os.path.join(output_dir, full_file_name)\n        return run_cmd(cmd, output_name=output_name)\n"
  },
  {
    "path": "demos/speech_web/speech_server/src/util.py",
    "content": "import os\nimport random\nimport subprocess\n\nimport paddle\n\nNOW_FILE_PATH = os.path.dirname(__file__)\nMAIN_ROOT = os.path.realpath(os.path.join(NOW_FILE_PATH, \"../../../../\"))\n\n\ndef get_ngpu():\n    if paddle.device.get_device() == \"cpu\":\n        return 0\n    else:\n        return 1\n\n\ndef randName(n=5):\n    return \"\".join(random.sample('zyxwvutsrqponmlkjihgfedcba', n))\n\n\ndef SuccessRequest(result=None, message=\"ok\"):\n    return {\"code\": 0, \"result\": result, \"message\": message}\n\n\ndef ErrorRequest(result=None, message=\"error\"):\n    return {\"code\": -1, \"result\": result, \"message\": message}\n\n\ndef run_cmd(cmd, output_name):\n    p = subprocess.Popen(cmd, shell=True)\n    res = p.wait()\n    print(cmd)\n    print(\"运行结果：\", res)\n    if res == 0:\n        # 运行成功\n        if os.path.exists(output_name):\n            return output_name\n        else:\n            # 合成的文件不存在\n            return None\n    else:\n        # 运行失败\n        return None\n"
  },
  {
    "path": "demos/speech_web/speech_server/vc.py",
    "content": "import argparse\nimport base64\nimport datetime\nimport json\nimport os\nfrom typing import List\n\nimport aiofiles\nimport librosa\nimport soundfile as sf\nimport uvicorn\nfrom fastapi import FastAPI\nfrom fastapi import UploadFile\nfrom pydantic import BaseModel\nfrom src.ernie_sat import SAT\nfrom src.finetune import FineTune\nfrom src.ge2e_clone import VoiceCloneGE2E\nfrom src.tdnn_clone import VoiceCloneTDNN\nfrom src.util import *\nfrom starlette.responses import FileResponse\n\nfrom paddlespeech.server.utils.audio_process import float2pcm\n\n# 解析配置\nparser = argparse.ArgumentParser(prog='PaddleSpeechDemo', add_help=True)\n\nparser.add_argument(\n    \"--port\",\n    action=\"store\",\n    type=int,\n    help=\"port of the app\",\n    default=8010,\n    required=False)\n\nargs = parser.parse_args()\nport = args.port\n\n# 这里会对finetune产生影响，所以finetune使用了cmd\nvc_model = VoiceCloneGE2E()\nvc_model_tdnn = VoiceCloneTDNN()\n\nsat_model = SAT()\nft_model = FineTune()\n\n# 配置文件\ntts_config = \"conf/tts_online_application.yaml\"\nasr_config = \"conf/ws_conformer_wenetspeech_application_faster.yaml\"\nasr_init_path = \"source/demo/demo.wav\"\ndb_path = \"source/db/vc.sqlite\"\nie_model_path = \"source/model\"\n\n# 路径配置\nVC_UPLOAD_PATH = \"source/wav/vc/upload\"\nVC_OUT_PATH = \"source/wav/vc/out\"\n\nFT_UPLOAD_PATH = \"source/wav/finetune/upload\"\nFT_OUT_PATH = \"source/wav/finetune/out\"\nFT_LABEL_PATH = \"source/wav/finetune/label.json\"\nFT_LABEL_TXT_PATH = \"source/wav/finetune/labels.txt\"\nFT_DEFAULT_PATH = \"source/wav/finetune/default\"\nFT_EXP_BASE_PATH = \"tmp_dir/finetune\"\n\nSAT_UPLOAD_PATH = \"source/wav/SAT/upload\"\nSAT_OUT_PATH = \"source/wav/SAT/out\"\nSAT_LABEL_PATH = \"source/wav/SAT/label.json\"\n\n# SAT 标注结果初始化\nif os.path.exists(SAT_LABEL_PATH):\n    with open(SAT_LABEL_PATH, \"r\", encoding='utf8') as f:\n        sat_label_dic = json.load(f)\nelse:\n    sat_label_dic = {}\n\n# ft 标注结果初始化\nif os.path.exists(FT_LABEL_PATH):\n    with open(FT_LABEL_PATH, \"r\", encoding='utf8') as f:\n        ft_label_dic = json.load(f)\nelse:\n    ft_label_dic = {}\n\n# 新建文件夹\nbase_sources = [\n    VC_UPLOAD_PATH,\n    VC_OUT_PATH,\n    FT_UPLOAD_PATH,\n    FT_OUT_PATH,\n    FT_DEFAULT_PATH,\n    SAT_UPLOAD_PATH,\n    SAT_OUT_PATH,\n]\nfor path in base_sources:\n    os.makedirs(path, exist_ok=True)\n#####################################################################\n########################### APP初始化  ###############################\n#####################################################################\napp = FastAPI()\n\n######################################################################\n########################### 接口类型  #################################\n#####################################################################\n\n\n# 接口结构\nclass VcBase(BaseModel):\n    wavName: str\n    wavPath: str\n\n\nclass VcBaseText(BaseModel):\n    wavName: str\n    wavPath: str\n    text: str\n    func: str\n\n\nclass VcBaseSAT(BaseModel):\n    old_str: str\n    new_str: str\n    language: str\n    function: str\n    wav: str  # base64编码\n    filename: str\n\n\nclass FTPath(BaseModel):\n    dataPath: str\n\n\nclass VcBaseFT(BaseModel):\n    wav: str  # base64编码\n    filename: str\n    wav_path: str\n\n\nclass VcBaseFTModel(BaseModel):\n    wav_path: str\n\n\nclass VcBaseFTSyn(BaseModel):\n    exp_path: str\n    text: str\n\n\n######################################################################\n########################### 文件列表查询与保存服务 #################################\n#####################################################################\n\n\ndef getVCList(path):\n    VC_FileDict = []\n    # 查询upload路径下的wav文件名\n    for root, dirs, files in os.walk(path, topdown=False):\n        for name in files:\n            # print(os.path.join(root, name))\n            VC_FileDict.append({'name': name, 'path': os.path.join(root, name)})\n    VC_FileDict = sorted(VC_FileDict, key=lambda x: x['name'], reverse=True)\n    return VC_FileDict\n\n\nasync def saveFiles(files, SavePath):\n    right = 0\n    error = 0\n    error_info = \"错误文件：\"\n    for file in files:\n        try:\n            if 'blob' in file.filename:\n                out_file_path = os.path.join(\n                    SavePath,\n                    datetime.datetime.strftime(datetime.datetime.now(),\n                                               '%H%M') + randName(3) + \".wav\")\n            else:\n                out_file_path = os.path.join(SavePath, file.filename)\n\n            print(\"上传文件名:\", out_file_path)\n            async with aiofiles.open(out_file_path, 'wb') as out_file:\n                content = await file.read()  # async read\n                await out_file.write(content)  # async write\n            # 将文件转成24k, 16bit类型的wav文件\n            wav, sr = librosa.load(out_file_path, sr=16000)\n            sf.write(out_file_path, data=wav, samplerate=sr)\n            right += 1\n        except Exception as e:\n            error += 1\n            error_info = error_info + file.filename + \" \" + str(e) + \"\\n\"\n            continue\n    return f\"上传成功：{right}, 上传失败：{error}, 失败原因： {error_info}\"\n\n\n# 音频下载\n@app.post(\"/vc/download\")\nasync def VcDownload(base: VcBase):\n    if os.path.exists(base.wavPath):\n        return FileResponse(base.wavPath)\n    else:\n        return ErrorRequest(message=\"下载请求失败，文件不存在\")\n\n\n# 音频下载base64\n@app.post(\"/vc/download_base64\")\nasync def VcDownloadBase64(base: VcBase):\n    if os.path.exists(base.wavPath):\n        # 将文件转成16k, 16bit类型的wav文件\n        wav, sr = librosa.load(base.wavPath, sr=16000)\n        wav = float2pcm(wav)  # float32 to int16\n        wav_bytes = wav.tobytes()  # to bytes\n        wav_base64 = base64.b64encode(wav_bytes).decode('utf8')\n        return SuccessRequest(result=wav_base64)\n    else:\n        return ErrorRequest(message=\"播放请求失败，文件不存在\")\n\n\n######################################################################\n########################### VC 服务 #################################\n#####################################################################\n\n\n# 上传文件\n@app.post(\"/vc/upload\")\nasync def VcUpload(files: List[UploadFile]):\n    # res = saveFiles(files, VC_UPLOAD_PATH)\n    right = 0\n    error = 0\n    error_info = \"错误文件：\"\n    for file in files:\n        try:\n            if 'blob' in file.filename:\n                out_file_path = os.path.join(\n                    VC_UPLOAD_PATH,\n                    datetime.datetime.strftime(datetime.datetime.now(),\n                                               '%H%M') + randName(3) + \".wav\")\n            else:\n                out_file_path = os.path.join(VC_UPLOAD_PATH, file.filename)\n\n            print(\"上传文件名:\", out_file_path)\n            async with aiofiles.open(out_file_path, 'wb') as out_file:\n                content = await file.read()  # async read\n                await out_file.write(content)  # async write\n            # 将文件转成24k, 16bit类型的wav文件\n            wav, sr = librosa.load(out_file_path, sr=16000)\n            sf.write(out_file_path, data=wav, samplerate=sr)\n            right += 1\n        except Exception as e:\n            error += 1\n            error_info = error_info + file.filename + \" \" + str(e) + \"\\n\"\n            continue\n    return SuccessRequest(\n        result=f\"上传成功：{right}, 上传失败：{error}, 失败原因： {error_info}\")\n\n\n# 获取文件列表\n@app.get(\"/vc/list\")\nasync def VcList():\n    res = getVCList(VC_UPLOAD_PATH)\n    return SuccessRequest(result=res)\n\n\n# 获取音频文件\n@app.post(\"/vc/file\")\nasync def VcFileGet(base: VcBase):\n    if os.path.exists(base.wavPath):\n        return FileResponse(base.wavPath)\n    else:\n        return ErrorRequest(result=\"获取文件失败\")\n\n\n# 删除音频文件\n@app.post(\"/vc/del\")\nasync def VcFileDel(base: VcBase):\n    if os.path.exists(base.wavPath):\n        os.remove(base.wavPath)\n        return SuccessRequest(result=\"删除成功\")\n    else:\n        return ErrorRequest(result=\"删除失败\")\n\n\n# 声音克隆G2P\n@app.post(\"/vc/clone_g2p\")\nasync def VcCloneG2P(base: VcBaseText):\n    if os.path.exists(base.wavPath):\n        try:\n            if base.func == 'ge2e':\n                wavName = base.wavName\n                wavPath = os.path.join(VC_OUT_PATH, wavName)\n                wavPath = vc_model.vc(\n                    text=base.text, input_wav=base.wavPath, out_wav=wavPath)\n            else:\n                wavName = base.wavName\n                wavPath = os.path.join(VC_OUT_PATH, wavName)\n                wavPath = vc_model_tdnn.vc(\n                    text=base.text, input_wav=base.wavPath, out_wav=wavPath)\n            if wavPath:\n                res = {\"wavName\": wavName, \"wavPath\": wavPath}\n                return SuccessRequest(result=res)\n            else:\n                return ErrorRequest(message=\"克隆失败，检查克隆脚本是否有效\")\n        except Exception as e:\n            print(e)\n            return ErrorRequest(message=\"克隆失败，合成过程报错\")\n    else:\n        return ErrorRequest(message=\"克隆失败，音频不存在\")\n\n\n######################################################################\n########################### SAT 服务 #################################\n#####################################################################\n# 声音克隆SAT\n@app.post(\"/vc/clone_sat\")\nasync def VcCloneSAT(base: VcBaseSAT):\n    # 重新整理 sat_label_dict\n    if base.filename not in sat_label_dic or sat_label_dic[\n            base.filename] != base.old_str:\n        sat_label_dic[base.filename] = base.old_str\n        with open(SAT_LABEL_PATH, \"w\", encoding='utf8') as f:\n            json.dump(sat_label_dic, f, ensure_ascii=False, indent=4)\n\n    input_file_path = base.wav\n\n    # 选择任务\n    if base.language == \"zh\":\n        # 中文\n        if base.function == \"synthesize\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_syn_zh_\" + base.filename)\n            # 中文克隆\n            sat_result = sat_model.zh_synthesize_edit(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                task_name=\"synthesize\")\n        elif base.function == \"edit\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_edit_zh_\" + base.filename)\n            # 中文语音编辑\n            sat_result = sat_model.zh_synthesize_edit(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                task_name=\"edit\")\n        elif base.function == \"crossclone\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_cross_zh_\" + base.filename)\n            # 中文跨语言\n            sat_result = sat_model.crossclone(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                source_lang=\"zh\",\n                target_lang=\"en\")\n        else:\n            return ErrorRequest(\n                message=\"请检查功能选项是否正确，仅支持:synthesize, edit, crossclone\")\n    elif base.language == \"en\":\n        if base.function == \"synthesize\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_syn_zh_\" + base.filename)\n            # 英文语音克隆\n            sat_result = sat_model.en_synthesize_edit(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                task_name=\"synthesize\")\n        elif base.function == \"edit\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_edit_zh_\" + base.filename)\n            # 英文语音编辑\n            sat_result = sat_model.en_synthesize_edit(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                task_name=\"edit\")\n        elif base.function == \"crossclone\":\n            output_file_path = os.path.join(SAT_OUT_PATH,\n                                            \"sat_cross_zh_\" + base.filename)\n            # 英文跨语言\n            sat_result = sat_model.crossclone(\n                old_str=base.old_str,\n                new_str=base.new_str,\n                input_name=os.path.realpath(input_file_path),\n                output_name=os.path.realpath(output_file_path),\n                source_lang=\"en\",\n                target_lang=\"zh\")\n        else:\n            return ErrorRequest(\n                message=\"请检查功能选项是否正确，仅支持:synthesize, edit, crossclone\")\n    else:\n        return ErrorRequest(message=\"请检查功能选项是否正确，仅支持中文和英文\")\n\n    if sat_result:\n        return SuccessRequest(result=sat_result, message=\"SAT合成成功\")\n    else:\n        return ErrorRequest(message=\"SAT 合成失败，请从后台检查错误信息！\")\n\n\n# SAT 文件列表\n@app.get(\"/sat/list\")\nasync def SatList():\n    res = []\n    filelist = getVCList(SAT_UPLOAD_PATH)\n    for fileitem in filelist:\n        if fileitem['name'] in sat_label_dic:\n            fileitem['label'] = sat_label_dic[fileitem['name']]\n        else:\n            fileitem['label'] = \"\"\n        res.append(fileitem)\n    return SuccessRequest(result=res)\n\n\n# 上传 SAT 音频\n# 上传文件\n@app.post(\"/sat/upload\")\nasync def SATUpload(files: List[UploadFile]):\n    right = 0\n    error = 0\n    error_info = \"错误文件：\"\n    for file in files:\n        try:\n            if 'blob' in file.filename:\n                out_file_path = os.path.join(\n                    SAT_UPLOAD_PATH,\n                    datetime.datetime.strftime(datetime.datetime.now(),\n                                               '%H%M') + randName(3) + \".wav\")\n            else:\n                out_file_path = os.path.join(SAT_UPLOAD_PATH, file.filename)\n\n            print(\"上传文件名:\", out_file_path)\n            async with aiofiles.open(out_file_path, 'wb') as out_file:\n                content = await file.read()  # async read\n                await out_file.write(content)  # async write\n            # 将文件转成24k, 16bit类型的wav文件\n            wav, sr = librosa.load(out_file_path, sr=16000)\n            sf.write(out_file_path, data=wav, samplerate=sr)\n            right += 1\n        except Exception as e:\n            error += 1\n            error_info = error_info + file.filename + \" \" + str(e) + \"\\n\"\n            continue\n    return SuccessRequest(\n        result=f\"上传成功：{right}, 上传失败：{error}, 失败原因： {error_info}\")\n\n\n######################################################################\n########################### FinueTune 服务 #################################\n#####################################################################\n\n\n# finetune 文件列表\n@app.post(\"/finetune/list\")\nasync def FineTuneList(Path: FTPath):\n    dataPath = Path.dataPath\n    if dataPath == \"default\":\n        # 默认路径\n        FT_PATH = FT_DEFAULT_PATH\n    else:\n        FT_PATH = dataPath\n\n    res = []\n    filelist = getVCList(FT_PATH)\n    for name, value in ft_label_dic.items():\n        wav_path = os.path.join(FT_PATH, name)\n        if not os.path.exists(wav_path):\n            wav_path = \"\"\n        d = {'text': value['text'], 'name': name, 'path': wav_path}\n        res.append(d)\n    return SuccessRequest(result=res)\n\n\n# 一键重置，获取新的文件地址\n@app.get('/finetune/newdir')\nasync def FTGetNewDir():\n    new_path = os.path.join(FT_UPLOAD_PATH, randName(3))\n    if not os.path.exists(new_path):\n        os.makedirs(new_path, exist_ok=True)\n    # 把 labels.txt 复制进去\n    cmd = f\"cp {FT_LABEL_TXT_PATH} {new_path}\"\n    os.system(cmd)\n    return SuccessRequest(result=new_path)\n\n\n# finetune 上传文件\n@app.post(\"/finetune/upload\")\nasync def FTUpload(base: VcBaseFT):\n    try:\n        # 文件夹是否存在\n        if not os.path.exists(base.wav_path):\n            os.makedirs(base.wav_path)\n        # 保存音频文件\n        out_file_path = os.path.join(base.wav_path, base.filename)\n        wav_b = base64.b64decode(base.wav)\n        async with aiofiles.open(out_file_path, 'wb') as out_file:\n            await out_file.write(wav_b)  # async write\n\n        return SuccessRequest(result=\"上传成功\")\n    except Exception as e:\n        return ErrorRequest(result=\"上传失败\")\n\n\n# finetune 微调\n@app.post(\"/finetune/clone_finetune\")\nasync def FTModel(base: VcBaseFTModel):\n    # 先检查 wav_path 是否有效\n    if base.wav_path == 'default':\n        data_path = FT_DEFAULT_PATH\n    else:\n        data_path = base.wav_path\n    if not os.path.exists(data_path):\n        return ErrorRequest(message=\"数据文件夹不存在\")\n\n    data_base = data_path.split(os.sep)[-1]\n    exp_dir = os.path.join(FT_EXP_BASE_PATH, data_base)\n    try:\n        exp_dir = ft_model.finetune(\n            input_dir=os.path.realpath(data_path),\n            exp_dir=os.path.realpath(exp_dir))\n        if exp_dir:\n            return SuccessRequest(result=exp_dir)\n        else:\n            return ErrorRequest(message=\"微调失败\")\n    except Exception as e:\n        print(e)\n        return ErrorRequest(message=\"微调失败\")\n\n\n# finetune 合成\n@app.post(\"/finetune/clone_finetune_syn\")\nasync def FTSyn(base: VcBaseFTSyn):\n    try:\n        if not os.path.exists(base.exp_path):\n            return ErrorRequest(result=\"模型路径不存在\")\n        wav_name = randName(5)\n        wav_path = ft_model.synthesize(\n            text=base.text,\n            wav_name=wav_name,\n            out_wav_dir=os.path.realpath(FT_OUT_PATH),\n            exp_dir=os.path.realpath(base.exp_path))\n        if wav_path:\n            res = {\"wavName\": wav_name + \".wav\", \"wavPath\": wav_path}\n            return SuccessRequest(result=res)\n        else:\n            return ErrorRequest(message=\"音频合成失败\")\n    except Exception as e:\n        return ErrorRequest(message=\"音频合成失败\")\n\n\nif __name__ == '__main__':\n    uvicorn.run(app=app, host='0.0.0.0', port=port)\n"
  },
  {
    "path": "demos/speech_web/web_client/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n.vscode/*\n"
  },
  {
    "path": "demos/speech_web/web_client/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"/favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>飞桨PaddleSpeech</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "demos/speech_web/web_client/package.json",
    "content": "{\n  \"name\": \"paddlespeechwebclient\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@element-plus/icons-vue\": \"^2.0.9\",\n    \"ant-design-vue\": \"^2.2.8\",\n    \"axios\": \"^1.8.2\",\n    \"element-plus\": \"^2.1.9\",\n    \"js-audio-recorder\": \"0.5.7\",\n    \"lamejs\": \"^1.2.1\",\n    \"less\": \"^4.1.2\",\n    \"vue\": \"^3.2.25\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^2.3.0\",\n    \"vite\": \"^2.9.13\",\n    \"@vue/compiler-sfc\": \"^3.1.0\"\n  }\n}\n"
  },
  {
    "path": "demos/speech_web/web_client/src/App.vue",
    "content": "<script setup>\nimport Experience from './components/Experience.vue'\nimport Header from './components/Content/Header/Header.vue'\n</script>\n\n<template>\n  <div class=\"app\">\n    <Header></Header>\n    <Experience></Experience>\n  </div>\n\n\n</template>\n\n<style style=\"less\">\n.app {\n  background: url(\"assets/image/在线体验-背景@2x.png\") no-repeat;\n};\n</style>\n"
  },
  {
    "path": "demos/speech_web/web_client/src/api/API.js",
    "content": "export const apiURL =   {\n    ASR_OFFLINE : '/api/asr/offline',           // 获取离线语音识别结果\n    ASR_COLLECT_ENV : '/api/asr/collectEnv',    // 采集环境噪音\n    ASR_STOP_RECORD : '/api/asr/stopRecord',    // 后端暂停录音\n    ASR_RESUME_RECORD : '/api/asr/resumeRecord',// 后端恢复录音\n\n    NLP_CHAT : '/api/nlp/chat',                 // NLP闲聊接口\n    NLP_IE : '/api/nlp/ie',                     // 信息抽取接口\n\n    TTS_OFFLINE : '/api/tts/offline',           // 获取TTS音频\n\n    VPR_RECOG : '/api/vpr/recog',               // 声纹识别接口，返回声纹对比相似度\n    VPR_ENROLL : '/api/vpr/enroll',             // 声纹识别注册接口\n    VPR_LIST : '/api/vpr/list',                 // 获取声纹注册的数据列表\n    VPR_DEL : '/api/vpr/del',                   // 删除用户声纹\n    VPR_DATA : '/api/vpr/database64?vprId=',            // 获取声纹注册数据 bs64格式\n\n    // websocket\n    CHAT_SOCKET_RECORD: 'ws://localhost:8010/ws/asr/offlineStream', // ChatBot websocket 接口\n    ASR_SOCKET_RECORD: 'ws://localhost:8010/ws/asr/onlineStream',  // Stream ASR 接口\n    TTS_SOCKET_RECORD: 'ws://localhost:8010/ws/tts/online', // Stream TTS 接口\n\n    // voice clone\n    // Voice Clone\n    VC_List: '/api/vc/list',\n    SAT_List: '/api/sat/list',\n    FineTune_List: '/api/finetune/list',\n\n    VC_Upload: '/api/vc/upload',\n    SAT_Upload: '/api/sat/upload',\n    FineTune_Upload: '/api/finetune/upload',\n    FineTune_NewDir: '/api/finetune/newdir',\n\n    VC_Download: '/api/vc/download',\n    VC_Download_Base64: '/api/vc/download_base64',\n    VC_Del: '/api/vc/del',\n    \n    VC_CloneG2p: '/api/vc/clone_g2p',\n    VC_CloneSAT: '/api/vc/clone_sat',\n    VC_CloneFineTune: '/api/finetune/clone_finetune',\n    VC_CloneFineTuneSyn: '/api/finetune/clone_finetune_syn',\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "demos/speech_web/web_client/src/api/ApiASR.js",
    "content": "import axios from 'axios'\nimport {apiURL} from \"./API.js\"\n\n// 上传音频文件，获得识别结果\nexport async function asrOffline(params){\n    const result = await axios.post(\n        apiURL.ASR_OFFLINE, params\n    )\n    return result\n}\n\n// 上传环境采集文件\nexport async function asrCollentEnv(params){\n    const result = await axios.post(\n        apiURL.ASR_OFFLINE, params\n    )\n    return result\n}\n\n// 暂停录音\nexport async function asrStopRecord(){\n    const result = await axios.get(apiURL.ASR_STOP_RECORD);\n    return result\n}\n\n// 恢复录音\nexport async function asrResumeRecord(){\n    const result = await axios.get(apiURL.ASR_RESUME_RECORD);\n    return result\n}"
  },
  {
    "path": "demos/speech_web/web_client/src/api/ApiNLP.js",
    "content": "import axios from 'axios'\nimport {apiURL} from \"./API.js\"\n\n// 获取闲聊对话结果\nexport async function nlpChat(text){\n    const result = await axios.post(apiURL.NLP_CHAT, { chat : text});\n    return result\n}\n\n// 获取信息抽取结果\nexport async function nlpIE(text){\n    const result = await axios.post(apiURL.NLP_IE, { chat : text});\n    return result\n}\n\n\n\n"
  },
  {
    "path": "demos/speech_web/web_client/src/api/ApiTTS.js",
    "content": "import axios from 'axios'\nimport {apiURL} from \"./API.js\"\n\nexport async function ttsOffline(text){\n    const result = await axios.post(apiURL.TTS_OFFLINE, { text : text});\n    return result\n}\n\n"
  },
  {
    "path": "demos/speech_web/web_client/src/api/ApiVC.js",
    "content": "import axios from 'axios'\nimport {apiURL} from \"./API.js\"\n\n// 上传音频-vc\nexport async function vcUpload(params){\n    const result = await axios.post(apiURL.VC_Upload, params);\n    return result\n}\n\n// 上传音频-sat\nexport async function satUpload(params){\n    const result = await axios.post(apiURL.SAT_Upload, params);\n    return result\n}\n\n// 上传音频-finetune\nexport async function fineTuneUpload(params){\n    const result = await axios.post(apiURL.FineTune_Upload, params);\n    return result\n}\n\n// 删除音频\nexport async function vcDel(params){\n    const result = await axios.post(apiURL.VC_Del, params);\n    return result\n}\n\n// 获取音频列表vc\nexport async function vcList(){\n    const result = await axios.get(apiURL.VC_List);\n    return result\n}\n// 获取音频列表Sat\nexport async function satList(){\n    const result = await axios.get(apiURL.SAT_List);\n    return result\n}\n\n// 获取音频列表fineTune\nexport async function fineTuneList(params){\n    const result = await axios.post(apiURL.FineTune_List, params);\n    return result\n}\n\n// fineTune 一键重置 获取新的文件夹\nexport async function fineTuneNewDir(){\n    const result = await axios.get(apiURL.FineTune_NewDir);\n    return result\n}\n\n// 获取音频数据\nexport async function vcDownload(params){\n    const result = await axios.post(apiURL.VC_Download, params);\n    return result\n}\n\n// 获取音频数据Base64\nexport async function vcDownloadBase64(params){\n    const result = await axios.post(apiURL.VC_Download_Base64, params);\n    return result\n}\n\n\n// 克隆合成G2P\nexport async function vcCloneG2P(params){\n    const result = await axios.post(apiURL.VC_CloneG2p, params);\n    return result\n}\n\n// 克隆合成SAT\nexport async function vcCloneSAT(params){\n    const result = await axios.post(apiURL.VC_CloneSAT, params);\n    return result\n}\n\n// 克隆合成 - finetune 微调\nexport async function vcCloneFineTune(params){\n    const result = await axios.post(apiURL.VC_CloneFineTune, params);\n    return result\n}\n\n// 克隆合成 - finetune 合成\nexport async function vcCloneFineTuneSyn(params){\n    const result = await axios.post(apiURL.VC_CloneFineTuneSyn, params);\n    return result\n}\n\n\n"
  },
  {
    "path": "demos/speech_web/web_client/src/api/ApiVPR.js",
    "content": "import axios from 'axios'\nimport {apiURL} from \"./API.js\"\n\n// 注册声纹\nexport async function vprEnroll(params){\n    const result = await axios.post(apiURL.VPR_ENROLL, params);\n    return result\n}\n\n// 声纹识别\nexport async function vprRecog(params){\n    const result = await axios.post(apiURL.VPR_RECOG, params);\n    return result\n}\n\n// 删除声纹\nexport async function vprDel(params){\n    const result = await axios.post(apiURL.VPR_DEL, params);\n    return result\n}\n\n// 获取声纹列表\nexport async function vprList(){\n    const result = await axios.get(apiURL.VPR_LIST);\n    return result\n}\n\n// 获取声纹音频\nexport async function vprData(params){\n    const result = await axios.get(apiURL.VPR_DATA+params);\n    return result\n}\n"
  },
  {
    "path": "demos/speech_web/web_client/src/components/Content/Header/Header.vue",
    "content": "<template>\n<div className=\"speech_header\">\n      <div className=\"speech_header_title\">\n        飞桨-PaddleSpeech\n      </div>\n      <div className=\"speech_header_describe\">\n        PaddleSpeech 是基于飞桨 PaddlePaddle 的语音方向的开源模型库，用于语音和音频中的各种关键任务的开发。支持语音识别，语音合成，声纹识别，声音分类，语音唤醒，语音翻译等多种语音任务，荣获 NAACL2022 Best Demo Award 。如果你喜欢这个示例，欢迎在 github 中 star 收藏鼓励。\n      </div>\n      <div className=\"speech_header_link_box\">\n        <a href=\"https://github.com/PaddlePaddle/PaddleSpeech\" className=\"speech_header_link\"  target='_blank' rel='noreferrer' key={index}>\n            前往Github\n        </a>\n      </div>\n    </div>\n\n</template>\n\n<script>\nexport default {\n    name:\"Header\"\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/Content/Header/style.less",
    "content": ".speech_header {\n    width: 1200px;\n    margin: 0 auto;\n    padding-top: 50px;\n    // background: url(\"../../../assets/image/在线体验-背景@2x.png\") no-repeat;\n    box-sizing: border-box;\n    &::after {\n        content: \"\";\n        display: block;\n        clear: both;\n        visibility: hidden;\n    }\n\n    ;\n\n    // background: pink;\n    .speech_header_title {\n        height: 57px;\n        font-family: PingFangSC-Medium;\n        font-size: 38px;\n        color: #000000;\n        letter-spacing: 0;\n        line-height: 57px;\n        font-weight: 500;\n        margin-bottom: 15px;\n    }\n\n    ;\n\n    .speech_header_describe {\n        height: 26px;\n        font-family: PingFangSC-Regular;\n        font-size: 16px;\n        color: #575757;\n        line-height: 26px;\n        font-weight: 400;\n        margin-bottom: 24px;\n    }\n\n    ;\n    .speech_header_link_box {\n        height: 40px;\n        margin-bottom: 40px;\n        display: flex;\n        align-items: center;\n        margin-top: 40px;\n    };\n    .speech_header_link {\n        display: block;\n        background: #2932E1;\n        width: 120px;\n        height: 40px;\n        line-height: 40px;\n        border-radius: 20px;\n        font-family: PingFangSC-Medium;\n        font-size: 14px;\n        color: #FFFFFF;\n        text-align: center;\n        font-weight: 500;\n        margin-right: 20px;\n        // margin-bottom: 40px;\n\n        &:hover {\n            opacity: 0.9;\n        }\n\n        ;\n    }\n\n    ;\n\n    .speech_header_divider {\n        width: 1200px;\n        height: 1px;\n        background: #D1D1D1;\n        margin-bottom: 40px;\n    }\n\n    ;\n\n    .speech_header_content_wrapper {\n        width: 1200px;\n        margin: 0 auto;\n        // background: pink;\n        margin-bottom: 20px;\n        display: flex;\n        justify-content: space-between;\n        flex-wrap: wrap;\n\n        .speech_header_module {\n            width: 384px;\n            background: #FFFFFF;\n            border: 1px solid rgba(224, 224, 224, 1);\n            box-shadow: 4px 8px 12px 0px rgba(0, 0, 0, 0.05);\n            border-radius: 16px;\n            padding: 30px 34px 0px 34px;\n            box-sizing: border-box;\n            display: flex;\n            margin-bottom: 40px;\n            .speech_header_background_img {\n                width: 46px;\n                height: 46px;\n                background-size: 46px 46px;\n                background-repeat: no-repeat;\n                background-position: center;\n                margin-right: 20px;\n            }\n\n            ;\n\n            .speech_header_content {\n                padding-top: 4px;\n                margin-bottom: 32px;\n               \n                .speech_header_module_title {\n                    height: 26px;\n                    font-family: PingFangSC-Medium;\n                    font-size: 20px;\n                    color: #000000;\n                    letter-spacing: 0;\n                    line-height: 26px;\n                    font-weight: 500;\n                    margin-bottom: 10px;\n                }\n\n                ;\n\n                .speech_header_module_introduce {\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #666666;\n                    letter-spacing: 0;\n                    font-weight: 400;\n                }\n\n                ;\n            }\n\n            ;\n        }\n\n        ;\n    }\n\n    ;\n}\n\n;\n\n"
  },
  {
    "path": "demos/speech_web/web_client/src/components/Content/Tail/Tail.vue",
    "content": ""
  },
  {
    "path": "demos/speech_web/web_client/src/components/Content/Tail/style.less",
    "content": ""
  },
  {
    "path": "demos/speech_web/web_client/src/components/Experience.vue",
    "content": "<script setup>\n\nimport ChatT from './SubMenu/ChatBot/ChatT.vue'\nimport ASRT from './SubMenu/ASR/ASRT.vue'\nimport TTST from './SubMenu/TTS/TTST.vue'\nimport VPRT from './SubMenu/VPR/VPRT.vue'\nimport IET from './SubMenu/IE/IET.vue'\n\nimport VoiceCloneT from './SubMenu/VoiceClone/VoiceClone.vue'\nimport ERNIE_SATT from './SubMenu/ERNIE_SAT/ERNIE_SAT.vue'\nimport FineTuneT from './SubMenu/FineTune/FineTune.vue'\n\n</script>\n\n<template>\n    <div className=\"experience\">\n      <div className=\"experience_wrapper\">\n        <div className=\"experience_title\">\n          功能体验\n        </div>\n        <div className=\"experience_describe\">\n          体验前，请允许浏览器获取麦克风权限\n        </div>\n        <div className=\"experience_content\" >\n          <el-tabs\n            className=\"experience_tabs\"\n            type=\"border-card\"\n          >\n            <el-tab-pane label=\"语音聊天\" key=\"1\">\n              <ChatT></ChatT>\n            </el-tab-pane>\n            <el-tab-pane label=\"声纹识别\" key=\"2\">\n             <VPRT></VPRT>\n            </el-tab-pane>\n            <el-tab-pane label=\"语音识别\" key=\"3\">\n            <ASRT></ASRT>\n            </el-tab-pane>\n            <el-tab-pane label=\"语音合成\" key=\"4\">\n            <TTST></TTST>\n            </el-tab-pane>\n            <el-tab-pane label=\"语音指令\" key=\"5\">\n            <IET></IET>\n            </el-tab-pane>\n            <el-tab-pane label=\"一句话合成\" key=\"6\">\n            <VoiceCloneT></VoiceCloneT>\n            </el-tab-pane>\n            <el-tab-pane label=\"小数据微调\" key=\"7\">\n            <FineTuneT></FineTuneT>\n            </el-tab-pane>\n            <el-tab-pane label=\"ERNIE-SAT\" key=\"8\">\n            <ERNIE_SATT></ERNIE_SATT>\n            </el-tab-pane>\n          </el-tabs>\n        </div>\n      </div>\n    </div>\n</template>\n\n\n<style lang=\"less\">\n@import \"./style.less\";\n\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/ASR.vue",
    "content": "<template>\n    <div class=\"asrbox\">\n        <h5> ASR 体验</h5>\n        <div class=\"home\" style=\"margin:1vw;\">\n            <el-button :type=\"recoType\" @click=\"startRecorderChunk()\"  style=\"margin:1vw;\">{{ recoText }} (流式)</el-button>\n            <el-button :type=\"recoType\" @click=\"startRecorder()\"  style=\"margin:1vw;\">{{ recoText }} (端到端)</el-button>\n      </div>\n      <a> asr_stream: {{ streamAsrResult }}</a>\n      <br>\n      <a> asr_offline: {{ asrResultOffline }} </a>\n\n    </div>\n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\n\nconst recorder_chunk = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\n    export default {\n        name: \"ASR\",\n        data(){\n            return {\n                streamAsrResult: '',\n                recoType: \"primary\",\n                recoText: \"开始录音\",\n                playType: \"success\",\n                asrResultOffline: '',\n                onReco: false,\n                ws:'',\n            }\n        },\n        mounted (){\n            // 初始化ws\n            this.ws = new WebSocket(\"ws://localhost:8010/ws/asr/onlineStream\")\n            // 定义消息处理逻辑\n            var _that = this\n            this.ws.addEventListener('message', function (event) {\n                var temp = JSON.parse(event.data);\n                // console.log('ws message', event.data)\n                if(temp.result && (temp.result != _that.streamAsrResult)){\n                    _that.streamAsrResult = temp.result\n                    _that.$nextTick(()=>{})\n                    console.log('更新了')\n                }                \n            })\n        },\n\n        methods: {\n            startRecorder () {\n                if(!this.onReco){\n                    recorder.clear()\n                    recorder.start().then(() => {\n                    }, (error) => {\n                    console.log(\"录音出错\");\n                })\n                this.onReco = true\n                this.recoType = \"danger\"\n                this.recoText = \"结束录音\"\n                this.$nextTick(()=>{\n                })\n                } else {\n                // 结束录音\n                    recorder.stop()\n                    this.onReco = false\n                    this.recoType = \"primary\"\n                    this.recoText = \"开始录音\"\n                    this.$nextTick(()=>{})\n                    // 音频导出成wav,然后上传到服务器\n                    const wavs = recorder.getWAVBlob()\n                    this.uploadFile(wavs, \"/api/asr/offline\")\n                }\n            },\n\n\n            startRecorderChunk() {\n                if(!this.onReco){\n                    // 跟后端说：开始流式传输\n                    var start = JSON.stringify({name:\"test.wav\", \"nbest\":5, signal:\"start\"})\n                    this.ws.send(start)\n                    recorder_chunk.start().then(() => {\n                        setInterval(() => {\n                        // 持续录音\n                        let newData = recorder_chunk.getNextData();\n                        if (!newData.length) {\n                            return;\n                        }\n                        // 上传到流式测试1\n                        this.uploadChunk(newData)\n                        }, 500)\n                    }, (error) => {\n                    console.log(\"录音出错\");\n                    })\n                    this.onReco = true\n                    this.recoType = \"danger\"\n                    this.recoText = \"结束录音\"\n                    this.$nextTick(()=>{\n                    })\n                } else {\n                    // 结束录音\n                    recorder_chunk.stop()\n                    // 跟后端说不录了\n                    // var end = JSON.stringify({name:\"test.wav\", \"nbest\":5, signal:\"end\"})\n                    // this.ws.send(end)\n                    this.onReco = false\n                    this.recoType = \"primary\"\n                    this.recoText = \"开始录音\"\n                    this.$nextTick(()=>{})\n                    recorder_chunk.clear()\n                }\n            },\n            uploadChunk(chunkDatas){\n                chunkDatas.forEach((chunkData) => {\n                this.ws.send(chunkData)\n              })\n            },\n            async uploadFile(file, post_url){\n                const formData = new FormData()\n                formData.append('files', file)\n                const result = await this.$http.post(post_url, formData);\n                if (result.data.code === 0) {\n                    this.asrResultOffline = result.data.result\n                    this.$nextTick(()=>{})\n                    this.$message.success(result.data.message);\n                } else {\n                    this.$message.error(result.data.message);\n                }\n            },\n        },\n    }\n</script>\n\n<style lang='less' scoped>\n .asrbox {\n  border: 4px solid #F00;\n//   position: fixed;\n  top:40%;\n  width: 100%;\n  height: 20%;\n  overflow: auto;\n }\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/ASRT.vue",
    "content": "<script setup>\nimport AudioFileIdentification from \"./AudioFile/AudioFileIdentification.vue\"\nimport RealTime from \"./RealTime/RealTime.vue\"\nimport EndToEndIdentification from \"./EndToEnd/EndToEndIdentification.vue\";\n\n\n</script>\n\n<template>\n    <div class=\"speech_recognition\">\n      <div class=\"speech_recognition_tabs\">\n        <div class=\"frame\"></div>\n        <el-tabs class=\"speech_recognition_mytabs\" type=\"border-card\">\n          <el-tab-pane label=\"实时语音识别\" key=\"1\">\n            <RealTime />\n          </el-tab-pane>\n          <el-tab-pane label=\"端到端识别\" key=\"2\">\n            <EndToEndIdentification />\n          </el-tab-pane>\n          <el-tab-pane label=\"音频文件识别\" key=\"3\">\n            <AudioFileIdentification />\n          </el-tab-pane>\n        </el-tabs>\n      </div>\n    </div>\n</template>\n\n<script>\n\nexport default {\n    \n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/AudioFile/AudioFileIdentification.vue",
    "content": "<template>\n        <div class=\"audioFileIdentification\">\n\n      \n        <div v-if=\"uploadStatus === 0\" class=\"public_recognition_speech\">\n            <!-- 上传前 -->\n            <el-upload\n                :multiple=\"false\"\n                :accept=\"'.wav'\"\n                :limit=\"1\"\n                :auto-upload=\"false\"\n                :on-change=\"handleChange\"\n                :show-file-list=\"false\"\n            >\n                <div class=\"upload_img\">\n                <div class=\"upload_img_back\"></div>\n                </div>\n            </el-upload>\n            <div class=\"speech_text\">\n                上传文件\n            </div>\n            <div class=\"speech_text_prompt\">\n                支持50秒内的.wav文件\n            </div>\n        </div>\n        <!-- 上传中 -->\n        <div v-else-if=\"uploadStatus === 1\" class=\"on_the_cross_speech\">\n            <div class=\"on_the_upload_img\">\n                <div class=\"on_the_upload_img_back\"></div>\n            </div>\n            <div class=\"on_the_speech_text\">\n                <span class=\"on_the_speech_loading\"> <Spin indicator={antIcon} /></span> 上传中\n            </div>\n        </div>\n        <div v-else>\n\n            <!-- // {/* //开始识别 */} -->\n                <div v-if=\"recognitionStatus === 0\" class=\"public_recognition_speech_start\">\n                <div class=\"public_recognition_speech_content\">\n                  <div\n                    class=\"public_recognition_speech_title\"\n                  >\n                   {{ filename }}\n                  </div>\n                  <div\n                    class=\"public_recognition_speech_again\"\n                    @click=\"uploadAgain()\"\n                  >重新上传</div>\n                  <div\n                    class=\"public_recognition_speech_play\"\n                    @click=\"paly()\"\n                  >播放</div>\n                </div>\n                <div class=\"speech_promp\"\n                    @click=\"beginToIdentify()\">\n                  开始识别\n                </div>\n                </div>\n                <!-- //  {/* 识别中 */} -->\n                <div v-else-if=\"recognitionStatus === 1\" class=\"public_recognition_speech_identify\">\n                <div class=\"public_recognition_speech_identify_box\">\n                <div\n                    class=\"public_recognition_speech_identify_back_img\"\n                  > \n                    <a-spin  />\n                  </div> \n\n                  <div\n                    class=\"public_recognition__identify_the_promp\"\n                  >识别中</div>\n        \n                </div>\n                </div>\n              \n                <!-- //  {/* // 重新识别 */} -->\n              <div v-else class=\"public_recognition_speech_identify_ahain\">\n              <div class=\"public_recognition_speech_identify_box_btn\">\n              \n                <div\n                  class=\"public_recognition__identify_the_btn\"\n                  @click=\"toIdentifyThe()\"\n                >重新识别</div>\n      \n              </div>\n                </div>\n            \n        </div>\n\n      <!-- {/* 指向 */} -->\n      <div class=\"public_recognition_point_to\">\n\n      </div>\n      <!-- {/* 识别结果 */} -->\n      <div class=\"public_recognition_result\">\n        <div>识别结果</div>\n        <div>{{ asrResult }}</div>\n      </div>\n    </div>\n</template>\n\n<script>\nimport { asrOffline } from '../../../../api/ApiASR'\n\nlet audioCtx = new AudioContext({\n  latencyHint: 'interactive',\n  sampleRate: 24000,\n});\n\nexport default {\n    name:\"\",\n    data(){\n        return {\n            uploadStatus : 0,\n            recognitionStatus : 0,\n            asrResult : \"\",\n            indicator : \"\",\n            \n            filename: \"\",\n            upfile: \"\"\n\n        }\n    },\n\n    methods:{\n        // 上传文件切换\n        handleChange(file, fileList){\n            this.uploadStatus = 2\n            this.filename = file.name\n            this.upfile = file\n            console.log(file)\n            \n            // debugger\n            // var result = Buffer.from(file);\n\n            \n        },\n        readFile(file) {\n            return new Promise((resolve, reject) => {\n                const fileReader = new FileReader();\n                fileReader.onload = function () {\n                    resolve(fileReader);\n                };\n                fileReader.onerror = function (err) {\n                    reject(err);\n                };\n                fileReader.readAsDataURL(file);\n                });\n            },\n        // 重新上传\n        uploadAgain(){\n            this.uploadStatus = 0\n            this.upfile = \"\"\n            this.filename = \"\"\n            this.asrResult = \"\"\n        },\n\n        // 播放音频\n        playAudioData(wav_buffer){\n            audioCtx.decodeAudioData(wav_buffer, buffer => {\n                let source = audioCtx.createBufferSource();\n                source.buffer = buffer\n            \n                source.connect(audioCtx.destination);\n                source.start();\n            }, function (e) {\n            });\n        },\n\n        // 播放本地音频\n        async paly(){\n            if(this.upfile){\n                let fileRes = \"\"\n                let fileString = \"\"\n                fileRes = await this.readFile(this.upfile.raw);\n                fileString = fileRes.result;\n                const audioBase64type = (fileString.match(/data:[^;]*;base64,/))?.[0] ?? '';\n                const isBase64 = !!fileString.match(/data:[^;]*;base64,/);\n                const uploadBase64 = fileString.substr(audioBase64type.length);\n                // isBase64 ? uploadBase64 : undefined\n                // base转换二进制数\n                let typedArray = this.base64ToUint8Array(isBase64 ? uploadBase64 : undefined)\n                this.playAudioData(typedArray.buffer)\n            }\n        },\n        base64ToUint8Array(base64String){\n           const padding = '='.repeat((4 - base64String.length % 4) % 4);\n            const base64 = (base64String + padding)\n                .replace(/-/g, '+')\n                .replace(/_/g, '/');\n        \n            const rawData = window.atob(base64);\n            const outputArray = new Uint8Array(rawData.length);\n        \n            for (let i = 0; i < rawData.length; ++i) {\n                outputArray[i] = rawData.charCodeAt(i);\n            }\n            return outputArray; \n        },\n\n        // 开始识别\n        async beginToIdentify(){\n          // 识别中\n          this.recognitionStatus = 1\n          \n          const formData = new FormData();\n          formData.append('files', this.upfile.raw);\n          \n          const result = await asrOffline(formData)\n          // 重新识别\n          this.recognitionStatus = 2\n          console.log(result);\n          // debugger\n          if (result.data.code === 0) {\n\n            this.$message.success(\"识别成功\")\n            // 获取识别文本\n            this.asrResult = result.data.result\n\n          } else {\n            this.$message.success(\"识别失败\")\n          };\n        },\n\n        // 重新识别\n        toIdentifyThe(){\n          // this.uploadAgain()\n          this.uploadStatus = 0\n          this.recognitionStatus = 0\n          this.asrResult = \"\"\n        }\n\n    }\n}   \n\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n\n\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/AudioFile/style.less",
    "content": ".audioFileIdentification {\n    width: 1106px;\n    height: 270px;\n    // background-color: pink;\n    padding-top: 40px;\n    box-sizing: border-box;\n    display: flex;\n    // 开始上传\n    .public_recognition_speech {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        // 开始上传\n        .upload_img {\n            width: 116px;\n            height: 116px;\n            background: #2932E1;\n            border-radius: 50%;\n            margin-left: 98px;\n            cursor: pointer;\n            margin-bottom: 20px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            .upload_img_back {\n                width: 34.38px;\n                height: 30.82px;\n                background: #2932E1;\n                background: url(\"../../../../assets/image/ic_大-上传文件.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 34.38px  30.82px;\n                cursor: pointer;\n            }\n            &:hover {\n                opacity: 0.9;\n            };\n\n        };\n      \n          \n        .speech_text {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 124px;\n                margin-bottom: 10px;\n        };\n        .speech_text_prompt {\n            height: 20px;\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #999999;\n            font-weight: 400;\n            margin-left: 84px;\n        };\n    };\n    // 上传中\n    .on_the_cross_speech {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        \n        .on_the_upload_img {\n            width: 116px;\n            height: 116px;\n           background: #7278F5;\n            border-radius: 50%;\n            margin-left: 98px;\n            cursor: pointer;\n            margin-bottom: 20px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            \n            .on_the_upload_img_back {\n                width: 34.38px;\n                height: 30.82px;\n               background: #7278F5;\n                background: url(\"../../../../assets/image/ic_大-上传文件.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 34.38px  30.82px;\n                cursor: pointer;\n              \n            };\n        };\n      \n          \n        .on_the_speech_text {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 124px;\n                margin-bottom: 10px;\n                display: flex;\n                // justify-content: center;\n                align-items: center;\n                .on_the_speech_loading {\n                    display: inline-block;\n                    width: 16px;\n                    height: 16px;\n                   background: #7278F5;\n                    // background: url(\"../../../../assets/image/ic_开始聊天.svg\");\n                    // background-repeat: no-repeat;\n                    // background-position: center;\n                    // background-size: 16px  16px;\n                    margin-right: 8px;\n                };\n        };\n    };\n\n    //开始识别\n    .public_recognition_speech_start {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        position: relative;\n        .public_recognition_speech_content {\n        width: 100%;\n          position: absolute;\n          top: 40px;\n          left: 50%;\n          transform: translateX(-50%);\n          display: flex;\n          justify-content: center;\n          align-items: center;\n\n            .public_recognition_speech_title {\n                height: 22px;\n                font-family: PingFangSC-Regular;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 400;\n            };\n            .public_recognition_speech_again {\n                height: 22px;\n                font-family: PingFangSC-Regular;\n                font-size: 16px;\n                color: #2932E1;\n                font-weight: 400;\n                margin-left: 30px;\n                cursor: pointer;\n            };\n            .public_recognition_speech_play {\n                height: 22px;\n                font-family: PingFangSC-Regular;\n                font-size: 16px;\n                color: #2932E1;\n                font-weight: 400;\n                margin-left: 20px;\n                cursor: pointer;\n            };\n        };\n        .speech_promp {\n            position: absolute;\n            top: 112px;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 142px;\n            height: 44px;\n            background: #2932E1;\n            border-radius: 22px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #FFFFFF;\n            text-align: center;\n            line-height: 44px;\n            font-weight: 500;\n            cursor: pointer;\n        };\n          \n      \n    };\n    // 识别中\n    .public_recognition_speech_identify {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        position: relative;\n       .public_recognition_speech_identify_box {\n        width: 143px;\n        height: 44px;\n        background: #7278F5;\n        border-radius: 22px;\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%,-50%);\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        cursor: pointer;\n        .public_recognition_speech_identify_back_img {\n            width: 16px;\n            height: 16px;\n        //    background: #7278F5;\n        //     background: url(\"../../../../assets/image/ic_开始聊天.svg\");\n        //     background-repeat: no-repeat;\n        //     background-position: center;\n        //     background-size: 16px  16px;\n        };\n        .public_recognition__identify_the_promp {\n            height: 20px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #FFFFFF;\n            font-weight: 500;\n            margin-left: 12px;\n        };\n       };\n       \n\n        \n    };\n    // 重新识别\n    .public_recognition_speech_identify_ahain {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        position: relative;\n        cursor: pointer;\n       .public_recognition_speech_identify_box_btn {\n        width: 143px;\n        height: 44px;\n        background: #2932E1;\n        border-radius: 22px;\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%,-50%);\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        cursor: pointer;\n        .public_recognition__identify_the_btn {\n            height: 20px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #FFFFFF;\n            font-weight: 500;\n        };\n       };\n       \n\n        \n    };\n    // 指向\n    .public_recognition_point_to {\n        width: 47px;\n        height: 67px;\n        background: url(\"../../../../assets/image/步骤-箭头切图@2x.png\") no-repeat;\n        background-position: center;\n        background-size: 47px 67px;\n       margin-top: 91px;\n       margin-right: 67px;\n    };\n    // 识别结果\n    .public_recognition_result {\n        width: 680px;\n        height: 230px;\n        background: #FAFAFA;\n        padding: 40px 50px 0px 50px;\n        div {\n            &:nth-of-type(1) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n                margin-bottom: 20px;\n            };\n            &:nth-of-type(2) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n            };\n        };\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/EndToEnd/EndToEndIdentification.vue",
    "content": "<template>\n    <div class=\"endToEndIdentification\">\n      <div  class=\"public_recognition_speech\">\n      \n      <div v-if=\"onReco\"> \n        <!-- 结束录音 -->\n        <div @click=\"endRecorder()\" class=\"endToEndIdentification_end_recorder_img\">\n              <div class='endToEndIdentification_end_recorder_img_back'></div>\n        </div>\n      </div>\n      <div v-else>\n        <div @click=\"startRecorder()\" class=\"endToEndIdentification_start_recorder_img\"></div>\n      </div>\n      \n        <div class=\"endToEndIdentification_prompt\" >\n            <div v-if=\"onReco\">\n                结束识别\n            </div>\n            <div v-else>\n                开始识别\n            </div>\n        </div>\n        <div class=\"speech_text_prompt\">\n            停止录音后得到识别结果\n        </div>\n      </div>\n      <div class=\"public_recognition_point_to\"></div>\n      <div class=\"public_recognition_result\">\n        <div>识别结果</div>\n        <div> {{asrResult}} </div>\n      </div>\n    </div>\n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\nimport { asrOffline } from '../../../../api/ApiASR'\n\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\nexport default {\n    data () {\n        return {\n            onReco: false,\n            asrResult: \"\",\n        }\n    },\n    methods: {\n        // 开始录音\n        startRecorder(){\n            this.onReco = true\n            recorder.clear()\n            recorder.start()\n        },\n\n        // 停止录音\n        endRecorder(){\n            recorder.stop()\n            this.onReco = false\n            // this.$nextTick(()=>{})\n            // 音频导出成wav,然后上传到服务器\n            const wavs = recorder.getWAVBlob()\n            this.uploadFile(wavs)\n        },\n        \n        // 上传文件\n         async uploadFile(file){\n            const formData = new FormData()\n            formData.append('files', file)\n            const result = await asrOffline(formData)\n            if (result.data.code === 0) {\n                this.asrResult = result.data.result\n                // this.$nextTick(()=>{})\n                this.$message.success(result.data.message);\n            } else {\n                this.$message.error(result.data.message);\n            }\n        },\n\n    }\n    \n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/EndToEnd/style.less",
    "content": ".endToEndIdentification {\n    width: 1106px;\n    height: 270px;\n    // background-color: pink;\n    padding-top: 40px;\n    box-sizing: border-box;\n    display: flex;\n    // 开始识别\n    .public_recognition_speech {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        \n        .endToEndIdentification_start_recorder_img {\n            width: 116px;\n            height: 116px;\n            background: #2932E1;\n            background: url(\"../../../../assets/image/ic_开始聊天.svg\");\n            background-repeat: no-repeat;\n            background-position: center;\n            background-size: 116px 116px;\n            margin-left: 98px;\n            cursor: pointer;\n            margin-bottom: 20px;\n            &:hover {\n                background: url(\"../../../../assets/image/ic_开始聊天_hover.svg\");\n\n            };\n\n        };\n\n        .endToEndIdentification_end_recorder_img {\n            width: 116px;\n            height: 116px;\n            background: #2932E1;\n            border-radius: 50%;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            margin-left: 98px;\n            margin-bottom: 20px;\n            cursor: pointer;\n            .endToEndIdentification_end_recorder_img_back {\n                width: 50px;\n                height: 50px;\n                background: url(\"../../../../assets/image/ic_大-声音波浪.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 50px 50px;\n              \n                &:hover {\n                    opacity: 0.9;\n        \n                };\n            };\n           \n        };\n        .endToEndIdentification_prompt {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 124px;\n                margin-bottom: 10px;\n        };\n        .speech_text_prompt {\n            height: 20px;\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #999999;\n            font-weight: 400;\n            margin-left: 90px;\n        };\n    };\n    // 指向\n    .public_recognition_point_to {\n        width: 47px;\n        height: 67px;\n        background: url(\"../../../../assets/image/步骤-箭头切图@2x.png\") no-repeat;\n        background-position: center;\n        background-size: 47px 67px;\n       margin-top: 91px;\n       margin-right: 67px;\n    };\n    // 识别结果\n    .public_recognition_result {\n        width: 680px;\n        height: 230px;\n        background: #FAFAFA;\n        padding: 40px 50px 0px 50px;\n        div {\n            &:nth-of-type(1) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n                margin-bottom: 20px;\n            };\n            &:nth-of-type(2) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n            };\n        };\n    };\n   \n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/RealTime/RealTime.vue",
    "content": "<template>\n    <div class=\"realTime\">\n      <div  class=\"public_recognition_speech\">\n      \n      <div v-if=\"onReco\"> \n        <!-- 结束录音 -->\n        <div @click=\"endRecorder()\" class=\"endToEndIdentification_end_recorder_img\">\n              <div class='endToEndIdentification_end_recorder_img_back'></div>\n        </div>\n      </div>\n      <div v-else>\n        <div @click=\"startRecorder()\" class=\"endToEndIdentification_start_recorder_img\"></div>\n      </div>\n      \n        <div class=\"endToEndIdentification_prompt\" >\n            <div v-if=\"onReco\">\n                结束识别\n            </div>\n            <div v-else>\n                开始识别\n            </div>\n        </div>\n\n        <div class=\"speech_text_prompt\">\n            实时得到识别结果\n        </div>\n\n      </div>\n      <div class=\"public_recognition_point_to\"></div>\n      <div class=\"public_recognition_result\">\n        <div>识别结果</div>\n        <div> {{asrResult}} </div>\n      </div>\n    </div>\n  \n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\nimport { apiURL } from '../../../../api/API'\n\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\nexport default {\n    data () {\n        return {\n            onReco: false,\n            asrResult: \"\",\n            wsUrl: \"\",\n            ws: \"\"\n        }\n    },\n    mounted () {\n        this.wsUrl = apiURL.ASR_SOCKET_RECORD\n        this.ws = new WebSocket(this.wsUrl)\n        var _that = this\n        this.ws.addEventListener('message', function (event) {\n                var temp = JSON.parse(event.data);\n                // console.log('ws message', event.data)\n                if(temp.result && (temp.result != _that.streamAsrResult)){\n                    _that.asrResult = temp.result\n                    _that.$nextTick(()=>{})\n                }                \n        })\n\n    },\n    methods: {\n        // 开始录音\n        startRecorder(){\n            // 检查 websocket 状态\n            // debugger\n            if(this.ws.readyState != this.ws.OPEN){\n                this.$message.error(\"websocket 链接失败，请检查 Websocket 后端服务是否正确开启\")\n                return\n            }\n\n            this.onReco = true\n\n            // 先跟后端说开始\n            var start = JSON.stringify({name:\"test.wav\", \"nbest\":5, signal:\"start\"})\n            this.ws.send(start)\n\n            recorder.start().then(() => {\n                setInterval(() => {\n                // 持续录音\n                let newData = recorder.getNextData();\n                if (!newData.length) {\n                    return;\n                }\n                // 上传到流式测试1\n                this.uploadChunk(newData)\n                }, 300)\n            }, (error) => {\n            console.log(\"录音出错\");\n            })\n            // this.onReco = true\n        },\n        \n        // 停止录音\n        endRecorder(){\n            // 结束录音\n            recorder.stop()\n            this.onReco = false\n            recorder.clear()\n        },\n\n        // 流式上传\n        uploadChunk(chunkDatas){\n                chunkDatas.forEach((chunkData) => {\n                this.ws.send(chunkData)\n            })\n        },\n    },\n\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/RealTime/style.less",
    "content": ".realTime{\n    width: 1106px;\n    height: 270px;\n    // background-color: pink;\n    padding-top: 40px;\n    box-sizing: border-box;\n    display: flex;\n    // 开始识别\n    .public_recognition_speech {\n        width: 295px;\n        height: 230px;\n        padding-top: 32px;\n        box-sizing: border-box;\n        .endToEndIdentification_start_recorder_img {\n            width: 116px;\n            height: 116px;\n            background: #2932E1;\n            background: url(\"../../../../assets/image/ic_开始聊天.svg\");\n            background-repeat: no-repeat;\n            background-position: center;\n            background-size: 116px 116px;\n            margin-left: 98px;\n            cursor: pointer;\n            margin-bottom: 20px;\n            &:hover {\n                background: url(\"../../../../assets/image/ic_开始聊天_hover.svg\");\n\n            };\n\n        };\n\n        .endToEndIdentification_end_recorder_img {\n            width: 116px;\n            height: 116px;\n            background: #2932E1;\n            border-radius: 50%;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            margin-left: 98px;\n            margin-bottom: 20px;\n            cursor: pointer;\n            .endToEndIdentification_end_recorder_img_back {\n                width: 50px;\n                height: 50px;\n                background: url(\"../../../../assets/image/ic_大-声音波浪.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 50px 50px;\n              \n                &:hover {\n                    opacity: 0.9;\n        \n                };\n            };\n           \n        };\n        .endToEndIdentification_prompt {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 124px;\n                margin-bottom: 10px;\n        };\n        .speech_text_prompt {\n            height: 20px;\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #999999;\n            font-weight: 400;\n            margin-left: 105px;\n        };\n    };\n    // 指向\n    .public_recognition_point_to {\n        width: 47px;\n        height: 67px;\n        background: url(\"../../../../assets/image/步骤-箭头切图@2x.png\") no-repeat;\n        background-position: center;\n        background-size: 47px 67px;\n       margin-top: 91px;\n       margin-right: 67px;\n    };\n    // 识别结果\n    .public_recognition_result {\n        width: 680px;\n        height: 230px;\n        background: #FAFAFA;\n        padding: 40px 50px 0px 50px;\n        div {\n            &:nth-of-type(1) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n                margin-bottom: 20px;\n            };\n            &:nth-of-type(2) {\n                height: 26px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #666666;\n                line-height: 26px;\n                font-weight: 500;\n            };\n        };\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ASR/style.less",
    "content": ".speech_recognition {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 40px 50px 50px 44px;\n    position: relative;\n    .frame {\n        width: 605px;\n        height: 50px;\n        border: 1px solid rgba(238,238,238,1);\n        border-radius: 25px;\n        position: absolute;\n    }\n    .speech_recognition_mytabs {\n        .ant-tabs-tab {\n            position: relative;\n            display: inline-flex;\n            align-items: center;\n            // padding: 12px 0;\n            font-size: 14px;\n            background: transparent;\n            border: 0;\n            outline: none;\n            cursor: pointer;\n            padding: 12px 26px;\n            box-sizing: border-box;\n        }\n        .ant-tabs-tab-active {\n            height: 50px;\n            background: #EEEFFD;\n            border-radius: 25px;\n            padding: 12px 26px;\n            box-sizing: border-box;\n        };\n        .speech_recognition .speech_recognition_mytabs .ant-tabs-ink-bar {\n            position: absolute;\n            background: transparent !important;\n            pointer-events: none;\n        }\n        .ant-tabs-ink-bar {\n            position: absolute;\n            background: transparent !important;\n            pointer-events: none;\n        }\n        .experience .experience_wrapper .experience_content .experience_tabs .ant-tabs-nav::before {\n            position: absolute;\n            right: 0;\n            left: 0;\n            border-bottom: 1px solid transparent !important;\n            // border: none;\n            content: '';\n        }\n        .ant-tabs-top > .ant-tabs-nav::before, .ant-tabs-bottom > .ant-tabs-nav::before, .ant-tabs-top > div > .ant-tabs-nav::before, .ant-tabs-bottom > div > .ant-tabs-nav::before {\n            position: absolute;\n            right: 0;\n            left: 0;\n             border-bottom: 1px solid transparent !important;\n            //  border: none;\n            content: '';\n        }\n        .ant-tabs-top > .ant-tabs-nav::before, .ant-tabs-bottom > .ant-tabs-nav::before, .ant-tabs-top > div > .ant-tabs-nav::before, .ant-tabs-bottom > div > .ant-tabs-nav::before {\n            position: absolute;\n            right: 0;\n            left: 0;\n            border-bottom: 1px solid transparent !important;\n            content: '';\n        }\n        .ant-tabs-nav::before {\n            position: absolute;\n            right: 0;\n            left: 0;\n            border-bottom: 1px solid transparent !important;\n            content: '';\n        };\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ChatBot/ChatT.vue",
    "content": "<template>\n    <div className=\"voice_chat\">\n        <!-- 开始聊天 -->\n        <div v-if=\"!onReco\" className=\"voice_chat_wrapper\">\n        <div className=\"voice_chat_btn\"\n            @click=\"startRecorder()\"\n        ></div>\n        <div className=\"voice_chat_btn_title\">点击开始聊天</div>\n        <div className=\"voice_chat_btn_prompt\">聊天前请允许浏览器获取麦克风权限</div>\n        </div>\n          <!-- 结束聊天 -->\n        <div v-else className=\"voice_chat_dialog_wrapper\">\n            <div className=\"dialog_box\" >\n              <ul className=\"dialog_content\" >\n                <li id=\"speech_list\" :key=\"index\">\n                    <div className=\"dialog_content_img_pp\"></div>\n                    <div className=\"dialog_content_dialogue_pp\">\n                        {{ nlpResult }}\n                    </div>\n                </li>\n                <li id=\"speech_list\" className=\"move_dialogue\">\n                    \n                    <div className=\"dialog_content_dialogue_user\">\n                        {{ asrResult }}\n                    </div>\n                    <div className=\"dialog_content_img_user\"></div>\n                </li>\n              </ul>\n            </div>\n            <div className=\"btn_end_dialog\"\n              @click=\"startRecorder()\"\n            >\n              <span></span>\n              <span>结束聊天</span>\n            </div>\n          </div>\n\n    </div>\n</template>\n\n<script>\nimport { asrCollentEnv, asrOffline, asrResumeRecord, asrStopRecord } from '../../../api/ApiASR'\nimport { apiURL } from '../../../api/API'\nimport Recorder from 'js-audio-recorder'\nimport { nlpChat } from '../../../api/ApiNLP';\n\n\nconst audioCtx = new (window.AudioContext || window.webkitAudioContext)({\n   latencyHint: 'interactive',\n   sampleRate: 24000,\n  });\n\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\n\nexport default {\n    data () {\n        return {\n            onReco: false,\n            allResultList: [],\n            asrResult: \"\",\n            nlpResult: \"\",\n            ws:\"\",\n\n            initChatText: \"欢迎使用飞桨语音对话系统，试试和我说话吧\",\n            speakingText: \"我正在说话...\",\n            stopText: \"等待音频播放结束...\"\n        }\n    },\n    mounted () {\n      // 初始化ws\n      this.ws = new WebSocket(apiURL.CHAT_SOCKET_RECORD);\n      var _that = this\n      this.ws.addEventListener('message', function (event) {\n          _that.allResultList.push(\n            {\n              value : event.data,\n              name : \"asr\"\n            }\n          )\n          _that.asrResult = event.data\n          _that.$nextTick(()=>{})\n          _that.getNlp(event.data)\n      })\n    },\n    methods: {\n        // 开始录音\n        startRecorder(){\n          if(this.ws.readyState != this.ws.OPEN){\n                this.$message.error(\"websocket 链接失败，请检查 Websocket 后端服务是否正确开启\")\n                return\n            }\n          this.allResultList = []\n          if(!this.onReco){\n            this.asrResult = this.speakingText\n            this.resumeRecordOnline()\n            recorder.start().then(() => {\n              setInterval(() => {\n                // 1.07版本不再实现 getNextData函数，只做了声明\n                let newData = recorder?.getNextData();\n                if (!newData.length) {\n                  return;\n                }\n                // 上传到流式测试1\n                this.uploadChunk(newData)\n              }, 500)\n            }, () => {\n              console.log(\"录音出错\");\n            })\n          this.onReco = true\n          // 初始化NLP\n          this.initNLP()\n        } else {\n          // 结束录音\n          recorder.stop()\n          this.onReco = false\n          this.asrResult = \"\"\n          this.stopRecordOnline()\n        }\n        },\n\n        // 录音数据上传\n        uploadChunk(chunkDatas){\n          chunkDatas.forEach((chunkData) => {\n            this.ws.send(chunkData)\n          })\n        },\n\n\n        // 恢复后端录音\n        async resumeRecordOnline(){\n            const result = await asrResumeRecord();\n        },\n        // 暂停后端录音\n        async stopRecordOnline(){\n            const result = await asrStopRecord();\n        },\n        // 清空录音\n        clearChat(){\n            this.allResultList = []\n        },\n\n        // 采集环境录音\n\n\n        // 初始化NLP\n        initNLP(){\n            // 录音暂停\n            this.onRecoPause = true\n            recorder.pause()\n            this.stopRecordOnline()\n            console.log('录音暂停')\n            this.asrResult = this.stopText\n\n            // 开场语句\n            // this.allResultList.push(\n            //     {\n            //         value:this.initChatText,\n            //         name: \"nlp\"\n            //     }\n            // )\n            this.nlpResult = this.initChatText\n            this.getTts(this.initChatText)\n\n        },\n\n        // 获得NLP聊天结果\n        async getNlp(text){\n            \n            // 录音暂停\n            this.onRecoPause = true\n            recorder.pause()\n            this.stopRecordOnline()\n            console.log('录音暂停')\n\n            const result = await nlpChat(text);\n            if (result.data.code === 0) {\n                // this.allResultList.push(\n                //     {\n                //         value:result.data.result,\n                //         name: \"nlp\"\n                //     }\n                // )\n                this.nlpResult = result.data.result\n                this.getTts(result.data.result)\n            } else {\n                this.$message.error(result.data.message);\n            }\n        },\n\n\n        // 获得TTS录音\n        async getTts(nlpText){\n            // base64\n            var result = await this.$http.post(\"/api/tts/offline\", { text : nlpText});\n            if (result.data.code === 0) {\n                var typedArray = this.base64ToUint8Array(result.data.result)\n                this.playAudioData( typedArray.buffer )\n            } else {\n                this.$message.error(result.data.message)\n            }\n            \n        },\n\n        // bs64解码\n         base64ToUint8Array(base64String) {\n            const padding = '='.repeat((4 - base64String.length % 4) % 4);\n            const base64 = (base64String + padding)\n                            .replace(/-/g, '+')\n                            .replace(/_/g, '/');\n\n            const rawData = window.atob(base64);\n            const outputArray = new Uint8Array(rawData.length);\n\n            for (let i = 0; i < rawData.length; ++i) {\n                    outputArray[i] = rawData.charCodeAt(i);\n            }\n            return outputArray;\n            },\n\n        // 播放音频\n        playAudioData( wav_buffer ) {\n            var _that = this\n            audioCtx.decodeAudioData(wav_buffer, buffer => {\n            var source = audioCtx.createBufferSource();\n            source.onended = () => {\n              // 如果被暂停\n              if(_that.onRecoPause){\n                console.log(\"恢复录音\")\n                // 客户端录音恢复\n                this.onRecoPause = false\n                recorder.resume()\n                this.asrResult = this.speakingText\n\n                // 服务器录音恢复\n                this.resumeRecordOnline()\n              }\n              \n            }\n            source.buffer = buffer;\n            source.connect(audioCtx.destination);\n            source.start();\n        }, function(e) {\n            Recorder.throwError(e);\n        });\n    },\n\n    }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ChatBot/style.less",
    "content": ".voice_chat {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    position: relative;\n    // 开始聊天\n    .voice_chat_wrapper {\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%,-50%);\n        position: absolute;\n        .voice_chat_btn {\n            width: 116px;\n            height: 116px;\n            margin-left: 54px;\n            // background: #2932E1;\n            border-radius: 50%;\n            cursor: pointer;\n            background: url(\"../../../assets/image/ic_开始聊天.svg\");\n            background-repeat: no-repeat;\n            background-position: center;\n            background-size: 116px 116px;\n            margin-bottom: 17px;\n            &:hover {\n                width: 116px;\n                height: 116px;\n                background: url(\"../../../assets/image/ic_开始聊天_hover.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 116px 116px;\n            };\n           \n        };\n        .voice_chat_btn_title {\n            height: 22px;\n            font-family: PingFangSC-Medium;\n            font-size: 16px;\n            color: #000000;\n            letter-spacing: 0;\n            text-align: center;\n            line-height: 22px;\n            font-weight: 500;\n            margin-bottom: 10px;\n        };\n        .voice_chat_btn_prompt {\n            height: 24px;\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #999999;\n            letter-spacing: 0;\n            text-align: center;\n            line-height: 24px;\n            font-weight: 400;\n        };\n    };\n    .voice_chat_wrapper::after {\n        content: \"\";\n        display: block;\n        clear: both;\n        visibility: hidden;\n    };\n    // 结束聊天\n    .voice_chat_dialog_wrapper {\n        width: 1200px;\n        height: 410px;\n        background: #FFFFFF;\n        position: relative;\n        .dialog_box {\n            width: 100%;\n            height: 410px;\n            padding: 50px 198px 82px 199px;\n            box-sizing: border-box;\n           \n            .dialog_content {\n                width: 100%;\n                height: 268px;\n                // background: rgb(113, 144, 145);\n                padding: 0px;  \n                overflow: auto;           \n                li {\n                    list-style-type: none;\n                    margin-bottom: 33px;\n                    display: flex;\n                    align-items: center;\n                    &:last-of-type(1) {\n                        margin-bottom: 0px;\n                    };\n                    .dialog_content_img_pp {\n                        width: 60px;\n                        height: 60px;\n                        // transform: scaleX(-1);\n                        background: url(\"../../../assets/image/飞桨头像@2x.png\");\n                        background-repeat: no-repeat;\n                        background-position: center;\n                        background-size: 60px 60px;\n                        margin-right: 20px;\n                    };\n                    .dialog_content_img_user {\n                        width: 60px;\n                        height: 60px;\n                        transform: scaleX(-1);\n                        background: url(\"../../../assets/image/用户头像@2x.png\");\n                        background-repeat: no-repeat;\n                        background-position: center;\n                        background-size: 60px 60px;\n                        margin-left: 20px;\n                    };\n                    .dialog_content_dialogue_pp {\n                        height: 50px;\n                        background: #F5F5F5;\n                        border-radius: 25px;\n                        font-family: PingFangSC-Regular;\n                        font-size: 14px;\n                        color: #000000;\n                        line-height: 50px;\n                        font-weight: 400;\n                        padding: 0px 16px;\n                        box-sizing: border-box;\n                    };\n                    .dialog_content_dialogue_user {\n                        height: 50px;\n                        background: rgba(41,50,225,0.90);\n                        border-radius: 25px;\n                        font-family: PingFangSC-Regular;\n                        font-size: 14px;\n                        color: #FFFFFF;\n                        line-height: 50px;\n                        font-weight: 400;\n                        padding: 0px 16px;\n                        box-sizing: border-box;\n                    };\n                };\n            };\n            .move_dialogue {\n                justify-content: flex-end;\n            };\n\n        };\n       \n        .btn_end_dialog {\n            width: 124px;\n            height: 42px;\n            line-height: 42px;\n            background: #FFFFFF;\n            box-shadow: 0px 4px 16px 0px rgba(0,0,0,0.09);\n            border-radius: 21px;\n            padding: 0px 24px;\n            box-sizing: border-box;\n            position: absolute;\n            left: 50%;\n            bottom: 40px;\n            transform: translateX(-50%);\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            cursor: pointer;\n            span {\n                display: inline-block;\n                &:nth-of-type(1) {\n                    width: 16px;\n                    height: 16px;\n                    background: url(\"../../../assets/image/ic_小-结束.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 16px 16px;\n                   \n                };\n                &:nth-of-type(2) {\n                    height: 20px;\n                    font-family: PingFangSC-Regular;\n                    font-size: 14px;\n                    color: #F33E3E;\n                    text-align: center;\n                    font-weight: 400;\n                    line-height: 20px;\n                    margin-left: 4px;\n                };\n            };\n        };\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/ERNIE_SAT/ERNIE_SAT.vue",
    "content": "<template>\n    <div class=\"sat\">\n      <el-row :gutter=\"20\">\n            <el-col :span=\"12\"><div class=\"grid-content ep-bg-purple\" />\n                <el-row :gutter=\"60\" class=\"btn_row_wav\" justify=\"center\">\n                    <el-button class=\"ml-3\" v-if=\"onEnrollRec === 0\" @click=\"startRecorderEnroll()\" type=\"primary\">录制音频</el-button>\n                    <el-button class=\"ml-3\" v-else-if=\"onEnrollRec === 1\" @click=\"stopRecorderEnroll()\" type=\"danger\">停止录音</el-button>\n                    <el-button class=\"ml-3\" v-else @click=\"uploadRecord()\" type=\"success\">上传录音</el-button>\n                    <a>&#12288</a>\n                    <el-upload\n                        :multiple=\"false\"\n                        :accept=\"'.wav'\"\n                        :auto-upload=\"false\"\n                        :on-change=\"handleChange\"\n                        :show-file-list=\"false\"\n                    >\n                        <el-button class=\"ml-3\" type=\"success\">上传音频文件</el-button>\n                    </el-upload>\n                </el-row>\n                <div class=\"recording_table\">\n                <el-table :data=\"vcDatas\" border class=\"recording_table_box\" scrollbar-always-on max-height=\"250px\">\n                    <!-- <el-table-column prop=\"wavId\" label=\"序号\" width=\"60\"/> -->\n                    <el-table-column prop=\"wavName\" label=\"文件名\" width=\"150\"/>\n                    <el-table-column label=\"文本\">\n                      <template #default=\"scope\">\n                            <el-input \n                              v-model=\"scope.row.label\"\n                              :autosize=\"{ minRows: 8, maxRows: 13 }\" \n                              placeholder=\"Please input\"\n                              />\n                            \n                        </template>\n                    </el-table-column>\n                    <el-table-column label=\"操作\" width=\"80\">\n                        <template #default=\"scope\">\n                            <div class=\"flex justify-space-between mb-4 flex-wrap gap-4\">\n                                <a @click=\"PlayTable(scope.row.wavId)\"><el-icon><VideoPlay /></el-icon></a>\n                                <a>&#12288</a>\n                                <a @click=\"delWav(scope.row.wavId)\"><el-icon><DeleteFilled /></el-icon></a>\n                            </div>\n                        </template>\n                    </el-table-column>\n                    <el-table-column fixed=\"right\" label=\"选择\" width=\"70\">\n                        <template #default=\"scope\">\n                            <el-switch v-model=\"scope.row.status\"  @click=\"choseWav(scope.row.wavId)\"/>\n                        </template>\n                    </el-table-column>\n                </el-table>\n                </div>\n\n            </el-col>\n            <el-col :span=\"8\"><div class=\"grid-content ep-bg-purple\" />\n                <el-space direction=\"vertical\">\n                    <el-card class=\"box-card\" style=\"width: 250px; height:310px\">\n                        <template #header>\n                            <div class=\"card-header\">\n                            <span>功能选择</span>\n                            </div>\n                        </template>  \n                        <el-radio-group v-model=\"funcMode\">\n                          <el-radio label=\"1\" size=\"middle\" border style=\"margin-bottom: 10px\">个性化语音合成</el-radio>\n                            <el-input\n                              v-if=\"funcMode === '1'\"\n                              v-model=\"ttsText\"\n                              :autosize=\"{ minRows: 2, maxRows: 2 }\"\n                              type=\"textarea\"\n                              placeholder=\"Please input\"\n                              style=\"margin-bottom: 10px\"\n                              />\n                          <el-radio label=\"2\" size=\"middle\" border style=\"margin-bottom: 10px\">跨语言语音合成</el-radio>\n                            <el-input\n                              v-if=\"funcMode === '2'\"\n                              v-model=\"ttsText\"\n                              :autosize=\"{ minRows: 2, maxRows: 2 }\"\n                              type=\"textarea\"\n                              placeholder=\"Please input\"\n                              style=\"margin-bottom: 10px\"\n                              />\n                          <el-radio label=\"3\" size=\"middle\" border style=\"margin-bottom: 10px\">语音编辑</el-radio>\n                            <el-input\n                                v-if=\"funcMode === '3'\"\n                                v-model=\"ttsText\"\n                                :autosize=\"{ minRows: 2, maxRows: 2 }\"\n                                type=\"textarea\"\n                                placeholder=\"Please input\"\n                                style=\"margin-bottom: 10px\"\n                                />\n                        </el-radio-group>\n                    </el-card>                    \n                </el-space>\n            </el-col>\n            <el-col :span=\"4\"><div class=\"grid-content ep-bg-purple\" />\n                <div class=\"play_board\">\n                    <el-space direction=\"vertical\">\n                        <el-row :gutter=\"20\">\n                            <el-button size=\"large\" v-if=\"onSyn === 0\" type=\"primary\" @click=\"SatSyn()\">开始合成</el-button>\n                            <el-button size=\"large\" v-else :loading-icon=\"Eleme\" type=\"danger\">合成中</el-button>\n                        </el-row>\n                        <el-row :gutter=\"20\">\n                            <el-button v-if='this.cloneWav' type=\"success\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-if='this.cloneWav' type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                        </el-row>\n                    </el-space>\n                </div>\n            </el-col>\n        </el-row>\n</div>\n</template>\n\n<script>\nimport { vcCloneSAT, vcDownload, vcDownloadBase64, satUpload, satList, vcDel } from '../../../api/ApiVC'\nimport Recorder from 'js-audio-recorder'\n\nlet audioCtx = new AudioContext({\nlatencyHint: 'interactive',\nsampleRate: 24000,\n});\n\n// 初始化录音\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\nexport default {\nname:\"\",\ndata(){\n    return {\n        uploadStatus : 0,\n        recognitionStatus : 0,\n        asrResult : \"\",\n        indicator : \"\",\n        \n        filename: \"\",\n        upfile: \"\",\n        mode: 1,\n        language: 1,\n        wav_input: \"卡尔普陪外孙玩滑梯\",\n        new_input: \"卡尔普陪外孙打滑梯\",\n        received_file:\"\",\n\n        // 分割线\n        onEnrollRec: 0,\n        onSyn:0,\n        vcDatas: [],\n        funcMode: '1',\n        selected_Id: -1,\n        ttsText: '',\n        cloneWav: '',\n        wav:''\n    }\n},\n\nmounted () {\n        this.GetList()\n    },\n\nmethods:{\n    // 获取文件列表\n    async GetList(){\n            this.vcDatas =[]\n            const result = await satList();\n            console.log(\"List: \", result);\n            for(let i=0; i < result.data.result.length; i++){\n                this.vcDatas.push({\n                    wavName: result.data.result[i]['name'],\n                    wavId: i,\n                    wavPath: result.data.result[i]['path'],\n                    status: false,\n                    label: result.data.result[i]['label']\n                })\n            }\n            console.log(\"vcDatas: \", this.vcDatas);\n            this.$nextTick(()=>{})\n    },\n\n    // 上传文件切换\n    async handleChange(file, fileList){\n      for(let i=0; i<fileList.length; i++){\n        this.uploadFile(fileList[i])\n      }\n      this.GetList()\n    },\n\n    async uploadFile(file){\n      let formData = new FormData();\n      formData.append('files', file.raw);\n      const result = await satUpload(formData);\n      if (result.data.code === 0) {\n          this.$message.success(\"音频上传成功\")\n          \n      } else {\n          this.$message.error(\"音频上传失败\")\n      }\n    },\n\n    // 开始录音\n    startRecorderEnroll(){\n            this.onEnrollRec = 1\n            recorder.clear()\n            recorder.start()\n        },\n    \n    // 结束录音\n    stopRecorderEnroll(){\n        this.onEnrollRec = 2\n        recorder.stop()\n        this.wav = recorder.getWAVBlob()\n    },\n\n    // 上传录音\n    async uploadRecord(){\n            this.onEnrollRec = 0\n            if(this.wav === \"\"){\n                this.$message.error(\"未检测到录音，录音失败，请重新录制\")\n                return\n            } else {\n                if(this.wav === ''){\n                    this.$message.error(\"请先完成录音\");\n                    this.onEnrollRec = 0\n                    return\n                } else {\n                    let formData = new FormData();\n                    formData.append('files', this.wav);\n                    const result = await satUpload(formData);\n                    console.log(result)\n                    this.GetList() \n                }\n                this.$message.success(\"录音上传成功\")\n            }\n        }, \n\n    // 删除音频文件\n    async delWav(wavId){\n            console.log('wavId', wavId)\n            // 删除文件\n            const result = await vcDel(\n                {\n                  wavName: this.vcDatas[wavId]['wavName'],\n                  wavPath: this.vcDatas[wavId]['wavPath']\n                }\n            );\n            if(!result.data.code){\n                this.$message.success(\"删除成功\")\n            } else {\n                this.$message.error(result.data.msg)\n            }\n            this.GetList()\n            this.reset()\n        },\n    \n    // 播放表格\n    async PlayTable(wavId){\n        this.Play(this.vcDatas[wavId])\n    },\n\n    // 播放音频\n    async Play(wavBase){\n        // 获取音频数据\n        const result = await vcDownloadBase64(wavBase);\n        // console.log('play result', result)\n        if (result.data.code === 0) {\n            // base转换二进制数\n            let typedArray = this.base64ToUint8Array(result.data.result)\n            // 添加wav文件头\n            let view = new DataView(typedArray.buffer);\n            view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n            // 播放音频\n            this.playAudioData(view.buffer);\n        };\n        },\n    // chose wav\n    choseWav(wavId){\n            this.cloneWav = ''\n            this.nowFile = this.vcDatas[wavId].wavName\n            this.nowIndex = wavId\n            // only wavId is true else false\n            for(let i=0; i<this.vcDatas.length; i++){\n                if(i==wavId){\n                    this.vcDatas[wavId].status = true\n                    this.selected_Id = wavId\n                    this.ttsText = this.vcDatas[wavId]['label']\n                } else {\n                    this.vcDatas[i].status = false\n                }\n            }\n            this.$nextTick(()=>{})\n        },\n\n    // 播放音频\n    playAudioData(wav_buffer){\n        audioCtx.decodeAudioData(wav_buffer, buffer => {\n            let source = audioCtx.createBufferSource();\n            source.buffer = buffer\n            source.connect(audioCtx.destination);\n            source.start();\n        }, function (e) {\n        });\n    },\n\n\n    base64ToUint8Array(base64String){\n       const padding = '='.repeat((4 - base64String.length % 4) % 4);\n        const base64 = (base64String + padding)\n            .replace(/-/g, '+')\n            .replace(/_/g, '/');\n    \n        const rawData = window.atob(base64);\n        const outputArray = new Uint8Array(rawData.length);\n    \n        for (let i = 0; i < rawData.length; ++i) {\n            outputArray[i] = rawData.charCodeAt(i);\n        }\n        return outputArray; \n    },\n\n    // 检查是否包含中文\n    hasChinese(str) {\n      return /[\\u4E00-\\u9FA5]+/g.test(str)\n    },\n\n    // SAT合成\n    async SatSyn(){\n      // 检查 select id\n      if(this.selected_Id < 0){\n        return this.$message.error(\"请先选择音频文件！\")\n      }\n\n      // 检查音频对应的文本\n      if(!this.vcDatas[this.selected_Id]['label']){\n        return this.$message.error(\"音频对应文本不可以为空！\")\n      }\n\n      // 检查待合成文本\n      if(!this.ttsText){\n        return this.$message.error(\"合成文本不可以为空！\")\n      }\n\n      // 合成中\n      this.onSyn = 1\n      // 重置 clone wav\n      this.cloneWav = \"\"\n  \n      const old_str = this.vcDatas[this.selected_Id]['label']\n      const new_str = this.ttsText\n      let language = \"\"\n      // 包含中文\n      if(this.hasChinese(old_str)){\n        language = \"zh\"\n      } else{\n        language = \"en\"\n      }\n      // 功能选择\n      let func = \"\"\n      if(this.funcMode === '1') {\n        func = \"synthesize\"\n      } else if(this.funcMode === '2'){\n        func = \"crossclone\"\n      } else {\n        func = \"edit\"\n      }\n      \n      let wav_path = this.vcDatas[this.selected_Id]['wavPath']\n      let filename = this.vcDatas[this.selected_Id]['wavName']\n\n      const data = {\n        old_str: old_str,\n        new_str: new_str,\n        language: language,\n        function: func,\n        wav: wav_path,\n        filename: filename\n\n      }\n\n      console.log(\"sat data: \", data)\n      \n      // sat 接口\n      const result = await vcCloneSAT(data)\n      // 合成完成\n      this.onSyn = 0\n      console.log(result);\n      // debugger\n      if (result.data.code === 0) {\n\n        this.$message.success(result.data.message)\n        // 获取识别文本\n        this.cloneWav = result.data.result\n        console.log(\"cloneWave\", this.cloneWav);\n\n      } else {\n        this.$message.error(result.data.message)\n      };\n    },\n    // 播放合成的音频\n    // 播放音频\n    async PlaySyn(){\n        // 获取音频数据\n        const data = {\n          wavName: \"sat_\"+this.filename,\n          wavPath: this.cloneWav\n        }\n        const result = await vcDownloadBase64(data);\n        // console.log('play result', result)\n        if (result.data.code === 0) {\n            // base转换二进制数\n            let typedArray = this.base64ToUint8Array(result.data.result)\n            // 添加wav文件头\n            let view = new DataView(typedArray.buffer);\n            view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n            // 播放音频\n            this.playAudioData(view.buffer);\n        };\n        },\n\n\n    // 下载合成文件\n    async downLoadCloneWav(){\n    if(this.cloneWav  === \"\"){\n        this.$message.error(\"音频合成完毕后再下载！\")\n    } else {\n        // const result = await vcDownload(this.cloneWav);\n        // 获取音频数据\n        const data = {\n          wavName: \"sat_\"+this.filename,\n          wavPath: this.cloneWav\n        }\n        const result = await vcDownloadBase64(data);\n        let view;\n        // console.log('play result', result)\n        if (result.data.code === 0) {\n            // base转换二进制数\n            let typedArray = this.base64ToUint8Array(result.data.result)\n            // 添加wav文件头\n            view = new DataView(typedArray.buffer);\n            view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n            // 播放音频\n            // this.playAudioData(view.buffer);\n        }\n        console.log(view.buffer)\n        // debugger\n        const blob = new Blob([view.buffer], { type: 'audio/wav' });\n        const fileName = new Date().getTime() + '.wav';\n        const down = document.createElement('a');\n        down.download = fileName;\n        down.style.display = 'none';//隐藏,没必要展示出来\n        down.href = URL.createObjectURL(blob);\n        document.body.appendChild(down);\n        down.click();\n        URL.revokeObjectURL(down.href); // 释放URL 对象\n        document.body.removeChild(down);//下载完成移除\n      }\n    },\n\n}\n}   \n\n</script>\n\n<style lang=\"less\" scoped>\n// @import \"./style.less\";\n.sat {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 5px 80px 56px 80px;\n    box-sizing: border-box;\n}\n\n.el-row {\n  margin-bottom: 20px;\n}\n.grid-content {\n  border-radius: 4px;\n  min-height: 36px;\n}\n.play_board{\n    height: 100%;\n    display: flex;\n    align-items: center;\n}\n\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/FineTune/FineTune.vue",
    "content": "<template>\n    <div class=\"finetune\">\n      <el-row :gutter=\"20\"> \n        <el-col :span=\"12\"><div class=\"grid-content ep-bg-purple\" />\n          <el-row :gutter=\"60\" class=\"btn_row_wav\" justify=\"center\">\n              <el-button class=\"ml-3\" @click=\"clearAll()\" type=\"primary\">一键重置</el-button>\n              <el-button class=\"ml-3\" @click=\"resetDefault()\" type=\"primary\">默认示例</el-button>\n              <el-button v-if='onFinetune === 0' class=\"ml-3\" @click=\"fineTuneModel()\" type=\"primary\">一键微调</el-button>\n              <el-button v-else-if='onFinetune === 1' class=\"ml-3\" @click=\"fineTuneModel()\" type=\"danger\">微调中</el-button>\n              <el-button v-else-if='onFinetune === 2' class=\"ml-3\" @click=\"resetFinetuneBtn()\" type=\"success\">微调成功</el-button>\n              <el-button v-else class=\"ml-3\" @click=\"resetFinetuneBtn()\" type=\"success\">微调失败</el-button>\n              <!-- <el-button class=\"ml-3\" @click=\"chooseHistory()\" type=\"warning\">历史数据选择</el-button> -->\n        </el-row>\n\n        <div class=\"recording_table\">\n            <el-table :data=\"vcDatas\" border class=\"recording_table_box\" scrollbar-always-on max-height=\"250px\">\n                <el-table-column prop=\"wavId\" label=\"序号\" width=\"60\"/>\n                <el-table-column prop=\"text\" label=\"文本\" />\n                <el-table-column label=\"音频\" width=\"80\">\n                    <template #default=\"scope\">\n                        <a v-if=\"scope.row.wavPath != ''\">{{ scope.row.wavName }}</a>\n                        <a v-else>\n                            \n                            <el-button class=\"ml-3\" v-if=\"onEnrollRec === 0\" @click=\"startRecorderEnroll()\" type=\"primary\" circle>\n                                <el-icon><Microphone /></el-icon>\n                            </el-button>\n                            <el-button class=\"ml-3\" v-else-if=\"onEnrollRec === 1\" @click=\"stopRecorderEnroll()\" type=\"danger\" circle>\n                                <el-icon><Microphone /></el-icon>\n                            </el-button>\n                            <el-button class=\"ml-3\" v-else @click=\"uploadRecord(scope.row.wavId)\" type=\"success\" circle>\n                                <el-icon><Upload /></el-icon>\n                            </el-button>\n                        </a>\n                    </template>\n                </el-table-column>\n                <el-table-column label=\"操作\" width=\"80\" fixed=\"right\">\n                    <template #default=\"scope\">\n                        <div class=\"flex justify-space-between mb-4 flex-wrap gap-4\">\n                            <a @click=\"PlayTable(scope.row.wavId)\"><el-icon><VideoPlay /></el-icon></a>\n                            <a>&#12288</a>\n                            <a @click=\"delWav(scope.row.wavId)\"><el-icon><DeleteFilled /></el-icon></a>\n                        </div>\n                    </template>\n                </el-table-column>\n            </el-table>\n        </div>\n\n            </el-col>\n            <el-col :span=\"8\"><div class=\"grid-content ep-bg-purple\" />\n                <el-space direction=\"vertical\">\n                    <el-card class=\"box-card\" style=\"width: 250px; height:310px\">\n                        <template #header>\n                            \n                            <div class=\"card-header\">\n                                <span>试验路径</span>\n                                <el-input\n                                    v-model=\"expPath\"\n                                    :autosize=\"{ minRows: 2, maxRows: 3 }\"\n                                    type=\"textarea\"\n                                    placeholder=\"一键微调自动生成，可使用历史试验路径\"\n                                    />\n                            </div>\n                        </template>\n                        <span>请输入中文文本</span>\n                        <el-input\n                            v-model=\"ttsText\"\n                            :autosize=\"{ minRows: 5, maxRows: 6 }\"\n                            type=\"textarea\"\n                            placeholder=\"请输入待合成文本\"\n                            />\n                    </el-card>                    \n                </el-space>\n            </el-col>\n            <el-col :span=\"4\"><div class=\"grid-content ep-bg-purple\" />\n                <div class=\"play_board\">\n                    <el-space direction=\"vertical\">\n                        <el-row :gutter=\"20\">\n                            <el-button size=\"large\" v-if=\"onSyn === 0\" type=\"primary\" @click=\"fineTuneSyn()\">开始合成</el-button>\n                            <el-button size=\"large\" v-else :loading-icon=\"Eleme\" type=\"danger\">合成中</el-button>\n                        </el-row>\n\n                        <el-row :gutter=\"20\">\n                            <el-button v-if='this.cloneWav' type=\"success\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-if='this.cloneWav' type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                        </el-row>\n                    </el-space>\n                </div>\n            </el-col>\n        </el-row>\n    </div>\n    </template>\n    \n    <script>\n    import Recorder from 'js-audio-recorder'\n    import { vcDownload, vcDownloadBase64, vcCloneFineTune, vcCloneFineTuneSyn, fineTuneList, vcDel, fineTuneUpload, fineTuneNewDir } from '../../../api/ApiVC';\n    \n    // 初始化录音\n    const recorder = new Recorder({\n      sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n      sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n      numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n      compiling: true\n    })\n    \n    // 初始化播放器\n    const audioCtx = new AudioContext({\n        latencyHint: 'interactive',\n        sampleRate: 16000,\n    });\n\n    function blobToDataURL(blob, callback) {\n        let a = new FileReader();\n        a.onload = function (e) { callback(e.target.result); }\n        a.readAsDataURL(blob);\n    }\n\n    \n    export default {\n        data(){\n            return {\n              vcDatas:[],\n              defaultDataPath: 'default',\n              nowDataPath: '',\n              expPath: '',\n              wav: '',\n              wav_base64: '',\n              ttsText: '欢迎使用飞桨语音套件',\n              cloneWav: '',\n              \n              onEnrollRec: 0,  // 录音状态\n              onFinetune: 0,  // 微调状态\n              onSyn: 0, // 合成状态\n            }\n        },\n        mounted () {\n            this.nowDataPath = this.defaultDataPath\n            this.GetList()\n            \n        },\n        methods: {\n            // 重置 btn \n            resetFinetuneBtn(){\n                this.onFinetune = 0\n            },\n        \n        // 一键重置\n        async clearAll(){\n            this.vcDatas = []\n            const result = await fineTuneNewDir()\n            console.log(\"clearALL: \", result.data.result);\n            this.nowDataPath = result.data.result\n            this.expPath = ''\n            this.onFinetune = 0\n            await this.GetList()\n        },\n        // 显示默认\n        async resetDefault(){\n            this.nowDataPath = this.defaultDataPath\n            await this.GetList()\n            this.expPath = ''\n        },\n\n        // 开始录音\n        startRecorderEnroll(){\n            this.onEnrollRec = 1\n            recorder.clear()\n            recorder.start()\n        },\n        // 结束录音\n        stopRecorderEnroll(){\n            this.onEnrollRec = 2\n            recorder.stop()\n            this.wav = recorder.getWAVBlob()\n        },\n\n        // 上传录音\n        async uploadRecord(wavId){\n            this.onEnrollRec = 0\n            if(this.wav === \"\"){\n                this.$message.error(\"未检测到录音，录音失败，请重新录制\")\n                return\n            } else {\n                if(this.wav === ''){\n                    this.$message.error(\"请先完成录音\");\n                    this.onEnrollRec = 0\n                    return\n                } else {\n                    let fileRes = \"\"\n                    let fileString = \"\"\n                    fileRes = await this.readFile(this.wav);\n                    fileString = fileRes.result;\n                    const audioBase64type = (fileString.match(/data:[^;]*;base64,/))?.[0] ?? '';\n                    const isBase64 = !!fileString.match(/data:[^;]*;base64,/);\n                    const uploadBase64 = fileString.substr(audioBase64type.length);\n                    \n                    // 上传时指定文件路径\n                    const data = {\n                        'wav': uploadBase64,\n                        'filename': this.vcDatas[wavId]['wavName'],\n                        'wav_path': this.nowDataPath\n                    }\n\n                    const result = await fineTuneUpload(data);\n                    console.log(result)\n                    this.GetList() \n                }\n                this.$message.success(\"录音上传成功\")\n            }\n        }, \n        // 读取文件和Blob\n        readFile(file) {\n            return new Promise((resolve, reject) => {\n                const fileReader = new FileReader();\n                fileReader.onload = function () {\n                    resolve(fileReader);\n                };\n                fileReader.onerror = function (err) {\n                    reject(err);\n                };\n                fileReader.readAsDataURL(file);\n                });\n            },\n\n            // 获取文件列表\n          async GetList(){\n            this.vcDatas = []\n            const result = await fineTuneList({\n              dataPath: this.nowDataPath\n            });\n            console.log(result, result.data.result);\n            for(let i=0; i<result.data.result.length; i++){\n                this.vcDatas.push({\n                  wavId: i,\n                  text: result.data.result[i]['text'],\n                  wavName: result.data.result[i]['name'],\n                  wavPath: result.data.result[i]['path'],\n                })\n            }\n            this.$nextTick(()=>{})\n          },\n                  // 播放音频\n    playAudioData( wav_buffer ) {\n        audioCtx.decodeAudioData(wav_buffer, buffer => {\n            var source = audioCtx.createBufferSource();\n            source.buffer = buffer;\n            source.connect(audioCtx.destination);\n            source.start();\n        }, function(e) {\n            Recorder.throwError(e);\n            })\n    },\n        // base64解码\n        base64ToUint8Array(base64String) {\n        const padding = '='.repeat((4 - base64String.length % 4) % 4);\n        const base64 = (base64String + padding)\n                        .replace(/-/g, '+')\n                        .replace(/_/g, '/');\n\n        const rawData = window.atob(base64);\n        const outputArray = new Uint8Array(rawData.length);\n\n        for (let i = 0; i < rawData.length; ++i) {\n                outputArray[i] = rawData.charCodeAt(i);\n        }\n        return outputArray;\n    },\n            // 播放表格\n        async PlayTable(wavId){\n            this.Play(this.vcDatas[wavId])\n        },\n        // 播放合成后的音频\n        async PlaySyn(){\n           \n            if(this.cloneWav  === \"\"){\n                this.$message.error(\"请合成音频后再播放！！\")\n                return\n            } else {\n                this.Play(this.cloneWav)\n            }\n        },\n        // 播放音频\n        async Play(wavBase){\n                // 获取音频数据\n                const result = await vcDownloadBase64(wavBase);\n                // console.log('play result', result)\n                if (result.data.code === 0) {\n                    // base转换二进制数\n                    let typedArray = this.base64ToUint8Array(result.data.result)\n                    // 添加wav文件头\n                    let view = new DataView(typedArray.buffer);\n                    view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n                    // 播放音频\n                    this.playAudioData(view.buffer);\n                } else {\n                    this.$message.error(\"获取音频文件失败\")\n                }\n        },\n                // 下载合成文件\n        async downLoadCloneWav(){\n            if(this.cloneWav  === \"\"){\n                this.$message.error(\"音频合成完毕后再下载！\")\n            } else {\n                // const result = await vcDownload(this.cloneWav);\n                // 获取音频数据\n                const result = await vcDownloadBase64(this.cloneWav);\n                let view;\n                // console.log('play result', result)\n                if (result.data.code === 0) {\n                    // base转换二进制数\n                    let typedArray = this.base64ToUint8Array(result.data.result)\n                    // 添加wav文件头\n                    view = new DataView(typedArray.buffer);\n                    view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n                    // 播放音频\n                    // this.playAudioData(view.buffer);\n                }\n                console.log(view.buffer)\n                // debugger\n                const blob = new Blob([view.buffer], { type: 'audio/wav' });\n                const fileName = new Date().getTime() + '.wav';\n                const down = document.createElement('a');\n                down.download = fileName;\n                down.style.display = 'none';//隐藏,没必要展示出来\n                down.href = URL.createObjectURL(blob);\n                document.body.appendChild(down);\n                down.click();\n                URL.revokeObjectURL(down.href); // 释放URL 对象\n                document.body.removeChild(down);//下载完成移除\n            }\n        },\n        // 删除音频文件\n        async delWav(wavId){\n            if(this.nowDataPath === this.defaultDataPath){\n                this.$message.error(\"默认音频不允许删除，可以一键重置，重新录音\")\n                return \n            }\n\n            console.log('wavId', wavId)\n            // 删除文件\n            const result = await vcDel(\n                {\n                    wavName: this.vcDatas[wavId]['wavName'],\n                    wavPath: this.vcDatas[wavId]['wavPath']\n                }\n            );\n            if(!result.data.code){\n                this.$message.success(\"删除成功\")\n                this.GetList()\n            } else {\n                this.$message.error(\"文件删除失败\")\n            }\n        }, \n        // 微调模型\n        async fineTuneModel(){\n            // 先检查是否都有录音\n            for(let i=0; i < this.vcDatas.length; i++){\n                if(this.vcDatas['wavPath'] === ''){\n                    return this.$message.error(\"还有录音未完成，请先完成录音！\")\n                }\n            }\n            this.onFinetune = 1\n            const result = await vcCloneFineTune(\n                {\n                    wav_path: this.nowDataPath,\n                }\n            );\n            if(!result.data.code){\n                this.onFinetune = 2\n                this.expPath = result.data.result\n                console.log(\"this.expPath: \", this.expPath)\n                this.$message.success(\"小数据微调成功\")\n            } else {\n                this.onFinetune = 3\n                this.$message.error(result.data.msg)\n            }\n        },\n        // 合成音频\n        async fineTuneSyn(){\n            if(!this.expPath){\n                return this.$message.error(\"请先微调生成模型后再生成！\")\n            }\n            // 合成\n            this.onSyn = 1\n            const result = await vcCloneFineTuneSyn(\n                {\n                    exp_path: this.expPath,\n                    text: this.ttsText\n                }\n            );\n            this.onSyn = 0\n            if(!result.data.code){\n                this.cloneWav = result.data.result\n                console.log(\"clone wav: \", this.cloneWav)\n                this.$message.success(\"音色克隆成功\")\n            } else {\n                this.$message.error(result.data.msg)\n            }\n            this.$nextTick(()=>{})\n        }\n},\n};\n</script>\n    \n<style lang=\"less\" scoped>\n// @import \"./style.less\";\n.finetune {\n  width: 1200px;\n  height: 410px;\n  background: #FFFFFF;\n  padding: 5px 80px 56px 80px;\n  box-sizing: border-box;\n}\n.el-row {\n  margin-bottom: 20px;\n}\n.grid-content {\n  border-radius: 4px;\n  min-height: 36px;\n}\n.play_board{\n    height: 100%;\n    display: flex;\n    align-items: center;\n}\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/IE/IET.vue",
    "content": "<template>\n    <div class=\"voice_commands\">\n      <div class=\"voice_commands_traffic\">\n        <div class=\"voice_commands_traffic_title\">交通费报销</div>\n        <div class=\"voice_commands_traffic_wrapper\">\n          <div class=\"voice_commands_traffic_wrapper_move\">\n            <div class=\"traffic_btn_img_btn\">\n                <!-- 结束录音 -->\n                <div v-if=\"onReco\"\n                @click=\"endRecorder()\"\n                class=\"end_recorder_img\"\n                ></div>\n                <!-- 开始录音 -->\n                <div v-else\n                @click= \"startRecorder()\"\n                class=\"start_recorder_img\"\n                ></div>\n            </div>\n            <div class=\"traffic_btn_prompt\">\n                <div v-if=\"onReco\">\n                    结束识别\n                </div>\n                <div v-else>\n                    开始识别\n                </div>\n            </div>\n            <div class=\"traffic_btn_list\">试试说“早上八点，我从广州到北京花了四百二十六元”</div>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"voice_point_to\"></div>\n\n      <!-- 识别结果 -->\n      <div class=\"voice_commands_IdentifyTheResults\">\n        <div class=\"voice_commands_IdentifyTheResults_title\">\n          识别结果\n        </div>\n \n        <div v-if=\"postStatus\" class=\"voice_commands_IdentifyTheResults_show\">\n            <div class=\"voice_commands_IdentifyTheResults_show_title\">\n              {{ asrResult }}\n            </div>\n            <div class=\"oice_commands_IdentifyTheResults_show_time\">\n              时间：{{voiceCommandsData.time}}\n            </div>\n            <div class=\"oice_commands_IdentifyTheResults_show_money\">\n              费用：{{voiceCommandsData.amount}}\n            </div>\n            <div class=\"oice_commands_IdentifyTheResults_show_origin\">\n              出发地：{{voiceCommandsData.outset}}\n            </div>\n            <div class=\"oice_commands_IdentifyTheResults_show_destination\">\n              目的地：{{voiceCommandsData.destination}}\n            </div>\n            </div>\n        <div v-else class=\"voice_commands_IdentifyTheResults_show_loading\">\n                <a-spin />\n        </div>\n        \n      </div>\n    </div >\n\n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\nimport { asrOffline } from '../../../api/ApiASR'\nimport { nlpIE } from '../../../api/ApiNLP'\n\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\n\nexport default {\n  \n    data () {\n        return {\n            voiceCommandsData:{\n                time:\"\",\n                amount:\"\",\n                outset:\"\",\n                destination:\"\"\n            },\n            asrDeafult : \"语音识别结果\",\n            asrResult: \"\",\n            postStatus:true,\n            onReco:false\n        }\n    },\n    mounted () {\n      this.asrResult = this.asrDeafult\n    },\n    methods: {\n      // reset\n      reset(){\n          this.asrResult = this.asrDeafult\n          this.voiceCommandsData = {\n                  time:\"\",\n                  amount:\"\",\n                  outset:\"\",\n                  destination:\"\"\n              }\n         },\n\n      // 开始录音\n        startRecorder(){\n          this.reset()\n          this.onReco = true\n          recorder.clear()\n          recorder.start()\n        },\n      // 停止录音\n        endRecorder(){\n            recorder.stop()\n            this.onReco = false\n            // this.$nextTick(()=>{})\n            this.postStatus = false\n            const wavs = recorder.getWAVBlob()\n            this.uploadFile(wavs)\n        },\n      // 上传识别结果\n        async uploadFile(file){\n          const formData = new FormData();\n          formData.append('files', file)\n          const result = await asrOffline(formData)\n            if (result.data.code === 0) {\n                this.asrResult = result.data.result\n                this.$message.success(result.data.message);\n                this.informationExtract()\n            } else {\n                this.$message.error(result.data.message);\n            }\n        },\n        // 信息抽取\n        async informationExtract(){\n                const result = await nlpIE(this.asrResult)\n\n                if(result.data.result[0]['时间']){\n                    this.voiceCommandsData.time = result.data.result[0]['时间'][0]['text']\n                }\n                \n                if(result.data.result[0]['出发地']){\n                    this.voiceCommandsData.outset = result.data.result[0]['出发地'][0]['text']\n                }\n\n                if(result.data.result[0]['目的地']){\n                    this.voiceCommandsData.destination = result.data.result[0]['目的地'][0]['text']\n                }\n\n                if(result.data.result[0]['费用']){\n                    this.voiceCommandsData.amount = result.data.result[0]['费用'][0]['text']\n                }\n                this.postStatus = true\n            }\n    }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/IE/style.less",
    "content": ".voice_commands {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 40px 50px 50px 50px;\n    box-sizing: border-box;\n    display: flex;\n    // 交通报销\n    .voice_commands_traffic {\n        width: 468px;\n        height: 320px;\n        .voice_commands_traffic_title {\n            height: 26px;\n            font-family: PingFangSC-Medium;\n            font-size: 16px;\n            color: #000000;\n            letter-spacing: 0;\n            line-height: 26px;\n            font-weight: 500;\n            margin-bottom: 30px;\n            // background: pink;\n        };\n        .voice_commands_traffic_wrapper {\n            width: 465px;\n            height: 264px;\n            // background: #FAFAFA;\n            position: relative;\n            .voice_commands_traffic_wrapper_move {\n                position: absolute;\n                top: 50%;\n                left: 50%;\n                transform: translate(-50%,-50%);\n            };\n            .traffic_btn_img_btn {\n                width: 116px;\n                height: 116px;\n                background: #2932E1;\n                display: flex;\n                justify-content: center;\n                align-items: center;\n                border-radius: 50%;\n                cursor: pointer;\n                margin-bottom: 20px;\n                margin-left: 84px;\n                &:hover {\n                    width: 116px;\n                    height: 116px;\n                    background: #7278F5;\n                   \n                        .start_recorder_img{\n                            width: 50px;\n                            height: 50px;\n                            background: url(\"../../../assets/image/ic_开始聊天_hover.svg\") no-repeat;\n                            background-position: center;\n                            background-size: 50px 50px;\n                        };\n                   \n                };\n            \n                    .start_recorder_img{\n                        width: 50px;\n                        height: 50px;\n                        background: url(\"../../../assets/image/ic_开始聊天.svg\") no-repeat;\n                        background-position: center;\n                        background-size: 50px 50px;\n                    };\n                \n            };\n            .traffic_btn_prompt {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                font-weight: 500;\n                margin-bottom: 16px;\n                margin-left: 110px;\n            };\n            .traffic_btn_list {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #999999;\n                font-weight: 400;\n                width: 112%;\n            };\n        };\n    };\n    //指向\n    .voice_point_to {\n        width: 47px;\n        height: 63px;\n        background: url(\"../../../assets/image/步骤-箭头切图@2x.png\") no-repeat;\n        background-position: center;\n        background-size: 47px 63px;\n        margin-top: 164px;\n        margin-right: 82px;\n    };\n    //识别结果\n    .voice_commands_IdentifyTheResults {\n        .voice_commands_IdentifyTheResults_title {\n            height: 26px;\n            font-family: PingFangSC-Medium;\n            font-size: 16px;\n            color: #000000;\n            line-height: 26px;\n            font-weight: 500;\n            margin-bottom: 30px;\n        };\n        // 显示框\n        .voice_commands_IdentifyTheResults_show {\n            width: 503px;\n            height: 264px;\n            background: #FAFAFA;\n            padding: 40px 0px 0px 50px;\n            box-sizing: border-box;\n            .voice_commands_IdentifyTheResults_show_title {\n                height: 22px;\n                font-family: PingFangSC-Medium;\n                font-size: 16px;\n                color: #000000;\n                // text-align: center;\n                font-weight: 500;\n                margin-bottom: 30px;\n            };\n            .oice_commands_IdentifyTheResults_show_time {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #666666;\n                font-weight: 500;\n                margin-bottom: 12px;\n            };\n            .oice_commands_IdentifyTheResults_show_money {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #666666;\n                font-weight: 500;\n                margin-bottom: 12px;\n            };\n            .oice_commands_IdentifyTheResults_show_origin {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #666666;\n                font-weight: 500;\n                margin-bottom: 12px;\n            };\n            .oice_commands_IdentifyTheResults_show_destination {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #666666;\n                font-weight: 500;\n            };\n        };\n        //加载状态\n        .voice_commands_IdentifyTheResults_show_loading {\n            width: 503px;\n            height: 264px;\n            background: #FAFAFA;\n            padding: 40px 0px 0px 50px;\n            box-sizing: border-box;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n        };\n    };\n    .end_recorder_img {\n        width: 50px;\n        height: 50px;\n        background: url(\"../../../assets/image/ic_大-声音波浪.svg\") no-repeat;\n        background-position: center;\n        background-size: 50px 50px;\n    };\n    .end_recorder_img:hover {\n        opacity: 0.9;\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/TTS/TTST.vue",
    "content": "<template>\n    <div class=\"speech_recognition\">\n      <!-- {/* 中文文本 */} -->\n      <div class=\"recognition_text\">\n        <div class=\"recognition_text_header\">\n          <div class=\"recognition_text_title\">\n            中文文本\n          </div>\n          <div class=\"recognition_text_random\" @click=\"getRandomChineseWord()\">\n            <span></span><span>更换示例</span>\n          </div>\n        </div>\n\n        <div class=\"recognition_text_field\">\n\n            <el-input\n            v-model=\"textarea\"\n            :autosize=\"{ minRows: 13, maxRows: 13 }\"\n            type=\"textarea\"\n            placeholder=\"Please input\"\n            />\n\n            \n        </div>\n      </div>\n      <!-- {/* 指向 */} -->\n      <div class=\"recognition_point_to\"></div>\n      <!-- {/* 语音合成 */} -->\n      <div class=\"speech_recognition_new\">\n        <div class=\"speech_recognition_title\">\n          语音合成\n        </div>\n            <!-- 流式合成初始状态 -->\n            <div  v-if=\"streamingOnInit\" class=\"speech_recognition_streaming\"\n              @click=\"getTtsChunkWavWS()\"\n            >\n              流式合成\n            </div>\n            <!-- 流式合成播放状态 -->\n            <div v-else>\n                <div v-if=\"streamingStopStatus\" class=\"streaming_ing_box\">\n                <div class=\"streaming_ing\">\n                <div class=\"streaming_ing_img\"></div>\n                <!-- <Spin indicator={antIcon} /> -->\n                <div class=\"streaming_ing_text\">合成中</div>\n                </div>\n                <div class=\"streaming_time\">响应时间：0ms</div>\n            </div>\n            <div v-else>\n                <div v-if=\"streamingContinueStatus\" class=\"streaming_suspended_box\">\n                    <div class=\"streaming_suspended\"\n                    @click=\"streamingStop()\"\n                    >\n                    <div class=\"streaming_suspended_img\"></div>\n                    <div class=\"streaming_suspended_text\">暂停播放</div>\n\n                    </div>\n                    <div class=\"suspended_time\">\n                    响应时间：{{ Number(streamingAcceptStamp) - Number(streamingSendStamp) }}ms\n                    </div>\n                </div>\n                <div v-else class=\"streaming_continue\"\n                    @click=\"streamingResume()\"\n                >\n                    <div class=\"streaming_continue_img\"></div>\n                    <div class=\"streaming_continue_text\">继续播放</div>\n                </div>\n                </div>\n            </div>\n         \n            \n\n\n            <!-- //  {/* 端到端合成 */} -->\n            <div v-if=\"endToEndOnInit\" class=\"speech_recognition_end_to_end\"\n              @click=\"EndToEndSynthesis()\"\n            >\n              端到端合成\n            </div>\n            <div v-else>\n                <div  v-if=\"endToEndStopStatus\"  class=\"end_to_end_ing_box\">\n                  <div class=\"end_to_end_ing\">\n                    <div class=\"end_to_end_ing_img\"> </div>\n                    <!-- <Spin indicator={antIcon}></Spin> -->\n                    <div class=\"end_to_end_ing_text\">合成中</div>\n\n                  </div>\n                  <div class=\"end_to_end_ing_time\">响应时间：0s</div>\n                </div>\n                \n                <div v-else class=\"end_to_end_suspended_box\">\n                    <div v-if=\"endToEndContinueStatus\" class=\"end_to_end_suspended\"\n                        @onClick=\"EndToEndStop()\"\n                    >\n                    <div class=\"end_to_end_suspended_img\"></div>\n                    <div class=\"end_to_end_suspended_text\">暂停播放</div>\n\n                    </div>\n                    <div v-else class=\"end_to_end_continue\"\n                      @click=\"EndToEndResume()\"\n                    >\n                      <div class=\"end_to_end_continue_img\"></div>\n                      <div class=\"end_to_end_continue_text\">继续播放</div>\n                    </div>\n                    <div class=\"end_to_end_ing_suspended_time\">响应时间：{{Number(endToEndAcceptStamp) - Number(endToEndSendStamp) }}ms</div>\n                </div>\n            </div>\n                \n      </div>\n    </div>\n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\nimport { apiURL } from '../../../api/API'\n\n// 全局承接流式 chunk 块\nlet chunks = []\nlet AudioContext = window.AudioContext || window.webkitAudioContext;\nlet chunk_index = 0\nlet palyIndex = 0\nlet reciveOver = false\n\n\n// 定义新的流式播放服务\nlet _audioSrcNodes = []\nconst _audioCtx = new (window.AudioContext || window.webkitAudioContext)({ latencyHint: 'interactive' });\nlet _playStartedAt = 0\nlet _totalTimeScheduled = 0\n\nfunction _reset(){\n    _playStartedAt = 0\n    _totalTimeScheduled = 0\n    _audioSrcNodes = []\n}\n\n\n\nexport default {\n    name: \"TTSTS\",\n    data () {\n        return {\n            textarea: \"\",\n            audioCtx: '',\n            source: '',\n            typedArray: '',\n            ttsResult: '',\n            ws: '',\n\n            // 控制播放状态\n            streamingContinueStatus: true,\n            endToEndContinueStatus: true,\n            // 控制初始状态\n            streamingOnInit: true, \n            endToEndOnInit: true, \n            // 控制是否开始\n            streamingStopStatus: false,\n            endToEndStopStatus: false,\n\n            // 流式接收时间戳\n            streamingAcceptStamp: '0',\n            endToEndAcceptStamp: '0',\n            // 流式发起时间戳\n            streamingSendStamp: '0',\n            endToEndSendStamp: '0'\n            \n        }\n    },\n    mounted(){\n        this.getRandomChineseWord()\n        \n        this.ws = new WebSocket(apiURL.TTS_SOCKET_RECORD)\n        var _that = this\n        this.ws.addEventListener('message', function (event) {\n            let temp = JSON.parse(event.data);\n            if(chunk_index === 0){\n                _that.streamingStopStatus = false\n                _that.streamingAcceptStamp = Date.now()\n            }\n\n            // 接收的数据刷进播放器\n            if(!temp.done){\n                chunk_index += 1\n                let chunk = temp.wav\n                let arraybuffer = _that.base64ToUint8Array(chunk)\n                let view = new DataView(arraybuffer.buffer);\n                \n                let length = view.buffer.byteLength / 2\n                \n                view = Recorder.encodeWAV(view, 24000, 24000, 1, 16, true) \n                _that._schedulePlaybackWav({\n                    wavData: view.buffer,\n                })\n            } else {\n                reciveOver = true\n                // this.streamingOnInit = true\n            }})\n    },\n\n    methods: {\n        // 状态变量重置\n        resetStatus(){\n            this.streamingContinueStatus = true\n            this.streamingOnInit = true\n            this.streamingStopStatus = false\n\n            this.endToEndContinueStatus = true\n            this.endToEndOnInit = true\n            this.endToEndStopStatus = false\n        },\n\n        // 生成随机文本\n        getRandomChineseWord(){\n            const resultChina = [\n                \"钱伟长想到上海来办学校是经过深思熟虑的。\",\n                \"林荒大吼出声，即便十年挣扎，他也从未感到过如此无助。自己的身体一点点陷入岁月之门，却眼睁睁的看着君倾城一手持剑，雪白的身影决然凄厉。就这样孤身一人，于漫天风雪中，对阵数千武者。\",\n                \"我们将继续成长，用行动回击那些只会说风凉话，不愿意和我们相向而行的害群之马。\",\n                \"许多道理，人们已经证明过千遍万遍，为什么还要带着侥幸的心理再去试验一回呢？\",\n                \"宫内整洁利索，廊柱门窗颜色鲜艳，几名电工正在维修线路。\",\n                \"他身材矮小，颧骨突出，留着小胡子，说话一口浓重的福建口音。\",\n                \"阿杰让阿悦看下剩下的盒饭合不合他的胃口。\",\n                \"有网友问，能不能回忆几件刘洋在学校里的趣事或糗事。\"\n                ];\n            let text = \"\";\n\n            text = resultChina[Math.floor(Math.random() * 7)];\n            this.textarea = text\n        },\n        // 基于WS的流式合成\n        async getTtsChunkWavWS(){\n            if(this.ws.readyState != this.ws.OPEN){\n                this.$message.error(\"websocket 链接失败，请检查 Websocket 后端服务是否正确开启\")\n                return\n            }\n            // 初始化 chunks\n            chunks = []\n            chunk_index = 0\n            reciveOver = false\n            _reset()\n            \n            this.streamingOnInit = false\n            this.streamingStopStatus = true\n            this.streamingContinueStatus = true\n\n            this.streamingSendStamp = Date.now()\n            this.ws.send(this.textarea)\n        },\n        // 流式播放器\n        _schedulePlaybackWav({wavData}) {\n            var _that = this\n            _audioCtx.decodeAudioData(wavData, audioBuffer => {\n            const audioSrc = _audioCtx.createBufferSource()\n            audioSrc.onended = () => {\n                _audioSrcNodes.shift();\n                if(_audioSrcNodes.length === 0){\n                    _that.resetStatus()\n                }\n                };\n            _audioSrcNodes.push(audioSrc);\n            let startDelay = 0;\n            if (!_playStartedAt) {\n                startDelay = 10 / 1000;\n                _playStartedAt = _audioCtx.currentTime + startDelay;\n                }\n            audioSrc.buffer = audioBuffer;\n            audioSrc.connect(_audioCtx.destination);\n            \n            const startAt = _playStartedAt + _totalTimeScheduled;\n            audioSrc.start(startAt);\n\n            _totalTimeScheduled+= audioBuffer.duration;\n\n            })    \n        },\n\n        // base64转换\n        base64ToUint8Array(base64String) {\n            const padding = '='.repeat((4 - base64String.length % 4) % 4);\n            const base64 = (base64String + padding)\n                            .replace(/-/g, '+')\n                            .replace(/_/g, '/');\n\n            const rawData = window.atob(base64);\n            const outputArray = new Uint8Array(rawData.length);\n\n            for (let i = 0; i < rawData.length; ++i) {\n                    outputArray[i] = rawData.charCodeAt(i);\n            }\n            return outputArray;\n        }, \n        \n        // 暂停播放\n        playerPaused(){\n            _audioCtx.suspend()\n        },\n\n        // 恢复播放\n        playerResume(){\n            _audioCtx.resume()\n        },\n\n        // 流式播放暂停\n        streamingStop(){\n            this.playerPaused()\n            // 切换为暂停状态\n            this.streamingContinueStatus = false\n\n        },\n        // 流式播放恢复\n        streamingResume(){\n            this.playerResume()\n            this.streamingContinueStatus = true\n        },\n        \n        // 端到端合成\n        async EndToEndSynthesis(){\n            this.endToEndSendStamp = Date.now()\n            this.endToEndOnInit = false\n            this.endToEndStopStatus = true\n\n            let ttsResult = await this.$http.post(\"/api/tts/offline\", { text : this.textarea});\n            \n            if (ttsResult.status == 200) {\n                this.endToEndAcceptStamp = Date.now()\n                this.endToEndStopStatus = false\n                this.endToEndContinueStatus = true\n                // base转换二进制数\n                console.log('res', ttsResult)\n                let typedArray = this.base64ToUint8Array(ttsResult.data.result)\n                // 播放音频\n                this._schedulePlaybackWav({\n                    wavData: typedArray.buffer,\n                })                \n            };\n        },\n\n        // 端到端播放暂停\n        streamingStop(){\n            this.playerPaused()\n            // 切换为暂停状态\n            this.endToEndContinueStatus = false\n\n        },\n        // 端到端播放恢复\n        streamingResume(){\n            this.playerResume()\n            this.endToEndContinueStatus = true\n        },\n\n\n\n\n    }\n\n}\n\n</script>\n\n\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/TTS/style.less",
    "content": ".speech_recognition {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 40px 0px 50px 50px;\n    box-sizing: border-box;\n    display: flex;\n    .recognition_text {\n        width: 589px; \n        height: 320px;\n        // background: pink;\n       .recognition_text_header {\n           margin-bottom: 30px;\n           display: flex;\n           justify-content: space-between;\n           align-items: center;\n           .recognition_text_title {\n            height: 26px;\n            font-family: PingFangSC-Medium;\n            font-size: 16px;\n            color: #000000;\n            letter-spacing: 0;\n            line-height: 26px;\n            font-weight: 500;\n           };\n           .recognition_text_random {\n               display: flex;\n               align-items: center;\n               cursor: pointer;\n               span {\n                display: inline-block;\n                    &:nth-of-type(1) {\n                        width: 20px;\n                        height: 20px;\n                        background: url(\"../../../assets/image/ic_更换示例.svg\") no-repeat;\n                        background-position: center;\n                        background-size: 20px 20px;\n                        margin-right: 5px;\n                       \n                    };\n                    &:nth-of-type(2) {\n                        height: 20px;\n                        font-family: PingFangSC-Regular;\n                        font-size: 14px;\n                        color: #2932E1;\n                        letter-spacing: 0;\n                        font-weight: 400;\n                    };\n               };\n           };\n       };\n       .recognition_text_field {\n        width: 589px;\n        height: 264px;\n        background: #FAFAFA;\n        .textToSpeech_content_show_text{\n            width: 100%;\n            height: 264px;\n            padding: 0px 30px 30px 0px;\n            box-sizing: border-box;\n            .ant-input {\n                height: 208px;\n                resize: none;\n                // margin-bottom: 230px;\n                padding: 21px 20px;\n            };\n        };\n       };\n    };\n    // 指向\n    .recognition_point_to {\n        width: 47px;\n        height: 63px;\n        background: url(\"../../../assets/image/步骤-箭头切图@2x.png\") no-repeat;\n        background-position: center;\n        background-size: 47px 63px;\n        margin-top: 164px;\n        margin-right: 101px;\n        margin-left: 100px;\n        margin-top: 164px;\n       };\n    //    语音合成\n    .speech_recognition_new {\n        .speech_recognition_title {\n            height: 26px;\n            font-family: PingFangSC-Medium;\n            font-size: 16px;\n            color: #000000;\n            line-height: 26px;\n            font-weight: 500;\n            margin-left: 32px;\n            margin-bottom: 96px;\n        };\n        // 流式合成\n        .speech_recognition_streaming {\n            width: 136px;\n            height: 44px;\n            background: #2932E1;\n            border-radius: 22px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #FFFFFF;\n            font-weight: 500;\n            text-align: center;\n            line-height: 44px;\n            margin-bottom: 40px;\n            cursor: pointer;\n            &:hover {\n                opacity: .9;\n            };\n        };\n         // 合成中\n        .streaming_ing_box {\n            display: flex;\n            align-items: center;\n            height: 44px;\n            margin-bottom: 40px;\n         .streaming_ing {\n            width: 136px;\n            height: 44px;\n            background: #7278F5;\n            border-radius: 22px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            cursor: pointer;\n          \n            .streaming_ing_img {\n                width: 16px;\n                height: 16px;\n                // background: url(\"../../../assets/image/ic_小-录制语音.svg\");\n                // background-repeat: no-repeat;\n                // background-position: center;\n                // background-size: 16px 16px;\n                // margin-right: 12px;\n            };\n            .streaming_ing_text {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #FFFFFF;\n                font-weight: 500;\n                margin-left: 12px;\n            };\n        };\n        // 合成时间文字\n        .streaming_time {\n            height: 20px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #000000;\n            font-weight: 500;\n            margin-left: 12px;\n        };\n        };\n        \n\n        // 暂停播放\n        .streaming_suspended_box {\n            display: flex;\n            align-items: center;\n            height: 44px;\n            margin-bottom: 40px;\n            .streaming_suspended {\n                width: 136px;\n                height: 44px;\n                background: #2932E1;\n                border-radius: 22px;\n                display: flex;\n                justify-content: center;\n                align-items: center;\n                cursor: pointer;\n              \n                .streaming_suspended_img {\n                    width: 16px;\n                    height: 16px;\n                    background: url(\"../../../assets/image/ic_暂停（按钮）.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 16px 16px;\n                    margin-right: 12px;\n                };\n                .streaming_suspended_text {\n                    height: 20px;\n                    font-family: PingFangSC-Medium;\n                    font-size: 14px;\n                    color: #FFFFFF;\n                    font-weight: 500;\n                    margin-left: 12px;\n                };\n               \n            };\n            // 暂停获取时间\n            .suspended_time {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 12px;\n            }\n        };\n       \n        // 继续播放\n        .streaming_continue {\n            width: 136px;\n            height: 44px;\n            background: #2932E1;\n            border-radius: 22px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            cursor: pointer;\n            margin-bottom: 40px;\n            .streaming_continue_img {\n                width: 16px;\n                height: 16px;\n                background: url(\"../../../assets/image/ic_播放（按钮）.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 16px 16px;\n                margin-right: 12px;\n            };\n            .streaming_continue_text {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #FFFFFF;\n                font-weight: 500;\n            };\n        };\n\n\n\n\n\n\n        // 端到端合成\n        .speech_recognition_end_to_end {\n            width: 136px;\n            height: 44px;\n            background: #2932E1;\n            border-radius: 22px;\n            font-family: PingFangSC-Medium;\n            font-size: 14px;\n            color: #FFFFFF;\n            font-weight: 500;\n            text-align: center;\n            line-height: 44px;\n            cursor: pointer;\n            &:hover {\n                opacity: .9;\n            };\n        };\n        // 合成中\n        .end_to_end_ing_box {\n            display: flex;\n            align-items: center;\n            height: 44px;\n            .end_to_end_ing {\n                width: 136px;\n                height: 44px;\n                background: #7278F5;\n                border-radius: 22px;\n                display: flex;\n                justify-content: center;\n                align-items: center;\n                cursor: pointer;\n                .end_to_end_ing_img {\n                    width: 16px;\n                    height: 16px;\n                    // background: url(\"../../../assets/image/ic_小-录制语音.svg\");\n                    // background-repeat: no-repeat;\n                    // background-position: center;\n                    // background-size: 16px 16px;\n                   \n                };\n                .end_to_end_ing_text {\n                    height: 20px;\n                    font-family: PingFangSC-Medium;\n                    font-size: 14px;\n                    color: #FFFFFF;\n                    font-weight: 500;\n                    margin-left: 12px;\n                };\n            };\n            // 合成时间文本\n            .end_to_end_ing_time {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 12px;\n            };\n        };\n       \n\n        // 暂停播放\n        .end_to_end_suspended_box {\n            display: flex;\n            align-items: center;\n            height: 44px;\n            .end_to_end_suspended {\n                width: 136px;\n                height: 44px;\n                background: #2932E1;\n                border-radius: 22px;\n                display: flex;\n                justify-content: center;\n                align-items: center;\n                cursor: pointer;\n                .end_to_end_suspended_img {\n                    width: 16px;\n                    height: 16px;\n                    background: url(\"../../../assets/image/ic_暂停（按钮）.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 16px 16px;\n                    margin-right: 12px;\n                };\n                .end_to_end_suspended_text {\n                    height: 20px;\n                    font-family: PingFangSC-Medium;\n                    font-size: 14px;\n                    color: #FFFFFF;\n                    font-weight: 500;\n                };\n            };\n            // 暂停播放时间\n            .end_to_end_ing_suspended_time {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #000000;\n                font-weight: 500;\n                margin-left: 12px;\n            };\n        };\n       \n        // 继续播放\n        .end_to_end_continue {\n            width: 136px;\n            height: 44px;\n            background: #2932E1;\n            border-radius: 22px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            cursor: pointer;\n            .end_to_end_continue_img {\n                width: 16px;\n                height: 16px;\n                background: url(\"../../../assets/image/ic_播放（按钮）.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 16px 16px;\n                margin-right: 12px;\n            };\n            .end_to_end_continue_text {\n                height: 20px;\n                font-family: PingFangSC-Medium;\n                font-size: 14px;\n                color: #FFFFFF;\n                font-weight: 500;\n            };\n        };\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/VPR/VPRT.vue",
    "content": "<template>\n<div class=\"voiceprint\">\n        <div class=\"voiceprint_recording\">\n            <div class=\"recording_title\">\n                <div>1</div>\n                <div>\n                    录制声纹\n                </div>\n            </div>\n            <div>\n                试试对我说：欢迎使用飞桨声纹识别系统\n            </div>\n            <!-- 开始录音 -->\n                <div v-if=\"onEnrollRec === 0 \" class=\"recording_btn\"\n                    @click=\"startRecorderEnroll()\"\n                >\n                    <div class=\"recording_img\"></div>\n                        <div class=\"recording_prompt\">\n                            录制声音\n                        </div>\n                </div>\n                <!-- 结束录音 -->\n                <div v-else-if=\"onEnrollRec === 1 \" class=\"recording_btn_the_recording\"\n                    @click=\"stopRecorderEnroll(0)\"\n                >\n                    <a-spin />\n                    <div class=\"recording_prompt\">\n                            停止录音\n                    </div>\n                </div>\n\n                <!-- :\n                //  {/* 完成录音 */} -->\n                <div v-else class=\"complete_the_recording_btn\"\n                    @click=\"enrollVoicePrint()\"\n                >\n                    <div class=\"complete_the_recording_img\"></div>\n                    <div class=\"complete_the_recording_prompt\">\n                        注册声纹\n                    </div>\n                </div>\n            \n            <!-- 用户名输入框 -->\n            <div class=\"recording_input\">\n                <el-input v-model=\"enrollSpkId\" class=\"w-50 m-2\" autosize placeholder=\"请输入注册用户名\" />\n            </div>\n            \n\n            <!-- {/* table */} -->\n            <div class=\"recording_table\">\n\n                <el-table :data=\"vpr_datas\" border class=\"recording_table_box\">\n                    <el-table-column prop=\"spkId\" label=\"用户\" />\n                    <el-table-column fixed=\"right\" label=\"操作\">\n                        <template #default=\"scope\">\n                            <el-button @click=\"Play(scope.row.vprId)\" type=\"text\" size=\"small\">播放</el-button>\n                            <el-button @click=\"Del(scope.row.spkId)\" type=\"text\" size=\"small\">删除</el-button>\n                        </template>\n                    </el-table-column>\n                </el-table>\n\n            </div>\n        </div>\n\n        <!-- {/* 指向 */} -->\n        <div class=\"recording_point_to\"></div>\n\n        <!-- {/* 识别声纹 */} -->\n        <div class=\"voiceprint_identify\">\n            <div class=\"identify_title\">\n                <div>2</div>\n                <div>\n                    识别声纹\n                </div>\n            </div>\n            <div>\n                试试对我说：请识别一下我的声音\n            </div>\n                    <div v-if=\"onRegRec === 0\" class=\"identify_btn\"\n                        @click=\"startRecorderRecog()\"\n                    >\n                        <div class=\"identify_img\"></div>\n                        <div class=\"identify_prompt\">\n                            录制声音\n                        </div>\n                    </div>\n\n                    <div v-else-if=\"onRegRec === 1\" class=\"identify_btn_the_recording\"\n                    @click=\"stopRecorderRecog()\">\n                        <a-spin />\n                        <div class=\"recording_prompt\">\n                                停止录音\n                        </div>\n                           \n                    </div>\n                    \n                    <div v-else class=\"identify_complete_the_recording_btn\"\n                        @click=\"Recog()\">\n                        <div class=\"identify_complete_the_recording_img\"></div>\n                        <div class=\"identify_complete_the_recording_prompt\">\n                            开始识别\n                        </div>\n                    </div>\n\n            <div class=\"identify_result\">\n                <div class=\"identify_result_content\">\n                    <div>识别结果</div>\n                    <div>{{scoreResult}}</div>\n                </div>\n            </div>\n        </div>\n</div>\n</template>\n\n<script>\nimport Recorder from 'js-audio-recorder'\nimport { vprData, vprList, vprEnroll, vprRecog, vprDel } from '../../../api/ApiVPR';\n\n// 初始化录音\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\n// 初始化播放器\nconst audioCtx = new AudioContext({\n    latencyHint: 'interactive',\n    sampleRate: 16000,\n});\n\nexport default {\n    data(){\n        return {\n            onEnrollRec: 0,     // 注册录音状态\n            onRegRec:0,         // 识别录音状态\n\n            scoreResult: \"\",   // 得分结果\n            enrollSpkId: \"\",    // SpkId注册\n\n            wav: '',            // 录音结果\n\n            scoreResults: [],   // 得分结果\n            vpr_datas: []       // 数据列表\n\n\n        }\n    },\n    mounted () {\n        this.GetList()\n        this.randomSpkId()\n    },\n    methods: {\n        // 重置\n        reset(){\n            this.wav = ''\n            this.scoreResults = []\n            this.scoreResult = \"\"\n        },\n        // random SpkName\n        randomSpkId(){\n            var e = 3;\n            var t = \"赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮卞齐康伍余元卜顾孟平黄\",\n            a = t.length,\n            n = \"\";\n            for (var i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));\n            this.enrollSpkId = n\n            console.log(\"n\", n)\n        },\n        // 注册声纹开始录音\n        startRecorderEnroll(){\n            this.onEnrollRec = 1\n            recorder.clear()\n            recorder.start()\n        },\n        // 注册声纹结束录音\n        stopRecorderEnroll(){\n            this,this.onEnrollRec = 2\n            recorder.stop()\n            this.wav = recorder.getWAVBlob()\n        },\n\n        // 识别声纹开始录音\n        startRecorderRecog(){\n            // this.wav = ''\n            this.onRegRec = 1\n            this.reset()\n            recorder.clear()\n            recorder.start()\n        },\n\n        // 注册声纹结束录音\n        stopRecorderRecog(){\n            this,this.onRegRec = 2\n            recorder.stop()\n            this.wav = recorder.getWAVBlob()\n        },\n\n        // 注册声纹\n        async enrollVoicePrint(){\n                if(this.wav === ''){\n                    this.$message.error(\"请先完成录音\");\n                    this.onEnrollRec = 0\n                    return\n                }\n                if(this.enrollSpkId === \"\"){\n                    this.$message.error(\"请输入声纹用户名\")\n                    this.onEnrollRec = 2\n                    return\n                }\n                this.onEnrollRec = 0\n\n                let formData = new FormData()\n                formData.append('spk_id', this.enrollSpkId)\n                formData.append('audio', this.wav)\n                \n                const result = await vprEnroll(formData)\n                if (!result){\n                    this.$message.error(\"请检查后端服务是否正确开启\")\n                    return \n                }\n                if(result.data.status){\n                    this.$message.success(\"声纹注册成功\")\n                } else {\n                    this.$message.error(result.data.msg)\n                }\n                this.GetList()\n                this.wav = ''\n                this.randomSpkId()\n            },\n\n        // 识别声纹\n        async Recog(){\n            this.scoreResults = []\n            this.onRegRec = 0\n            if(this.wav === ''){\n                this.$message.error(\"请先完成录音\");\n                return\n            }\n            if(this.vpr_datas.length == 0){\n                this.$message.error(\"未查询到声纹数据，请先注册\");\n                return\n            }\n            let formData = new FormData()\n            formData.append('audio', this.wav)\n            const result = await vprRecog(formData);\n            console.log(result)\n            result.data.forEach(dat => {\n                this.scoreResults.push({\n                    spkId: dat[0],\n                    score: dat[1][1]\n                })\n            });\n            if(this.scoreResults.length > 0){\n                this.scoreResult = this.scoreResults[0]['spkId']\n            }\n        },\n\n        // 删除声纹\n        async Del(spkId){\n                console.log('spkId', spkId)\n                // 删除用户\n                const result = await vprDel({spk_id: spkId});\n                if(result.data.status){\n                    this.$message.success(\"删除成功\")\n                } else {\n                    this.$message.error(result.data.msg)\n                }\n                this.GetList()\n            },\n        \n        // 获取声纹列表\n        async GetList(){\n            this.vpr_datas =[]\n            const result = await vprList();\n            console.log(\"list\", result)\n            for(let i=0; i<result.data[0].length; i++){\n                this.vpr_datas.push({\n                    spkId: result.data[0][i],\n                    vprId: result.data[1][i]\n                })\n            }\n            this.$nextTick(()=>{})\n        },\n\n        // 播放音频\n        async Play(vprId){\n                console.log('vprId', vprId)\n                // 获取音频数据\n                const result = await vprData(vprId);\n                console.log('play result', result)\n                if (result.data.code == 0) {\n                    // base转换二进制数\n                    let typedArray = this.base64ToUint8Array(result.data.result)\n\n                    // 添加wav文件头\n                    let view = new DataView(typedArray.buffer);\n                    view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n\n                    // 播放音频\n                    this.playAudioData(view.buffer);\n                };\n        },\n\n        // base64解码\n        base64ToUint8Array(base64String) {\n            const padding = '='.repeat((4 - base64String.length % 4) % 4);\n            const base64 = (base64String + padding)\n                            .replace(/-/g, '+')\n                            .replace(/_/g, '/');\n\n            const rawData = window.atob(base64);\n            const outputArray = new Uint8Array(rawData.length);\n\n            for (let i = 0; i < rawData.length; ++i) {\n                    outputArray[i] = rawData.charCodeAt(i);\n            }\n            return outputArray;\n        }, \n        // 播放音频\n        playAudioData( wav_buffer ) {\n        audioCtx.decodeAudioData(wav_buffer, buffer => {\n            var source = audioCtx.createBufferSource();\n            source.buffer = buffer;\n            source.connect(audioCtx.destination);\n            source.start();\n        }, function(e) {\n            Recorder.throwError(e);\n            })\n        }\n    }\n};\n</script>\n\n<style lang=\"less\" scoped>\n@import \"./style.less\";\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/VPR/style.less",
    "content": ".voiceprint {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 41px 80px 56px 80px;\n    box-sizing: border-box;\n    display: flex;\n    // 录制声纹\n    .voiceprint_recording {\n        width: 423px;\n        height: 354px;\n        margin-right: 66px;\n        .recording_title {\n            display: flex;\n            align-items: center;\n            margin-bottom: 20px;\n            div {\n                &:nth-of-type(1) {\n                    width: 24px;\n                    height: 24px;\n                    background: rgba(41,50,225,0.70);\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #FFFFFF;\n                    letter-spacing: 0;\n                    text-align: center;\n                    line-height: 24px;\n                    font-weight: 400;\n                    margin-right: 16px;\n                    border-radius: 50%;\n                };\n                &:nth-of-type(2) {\n                    height: 26px;\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #000000;\n                    line-height: 26px;\n                    font-weight: 400;\n                };\n            };\n        };\n        // 开始录音\n        .recording_btn {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #2932E1;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            margin-bottom: 20px;\n            margin-top: 10px;\n            \n            &:hover {\n                background: #7278F5;\n                .recording_img {\n                    width: 20px;\n                    height: 20px;\n                    background: url(\"../../../assets/image//icon_录制声音小语音1.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 20px 20px;\n                    margin-right: 8.26px;\n                \n                };\n            }\n            .recording_img {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_录制声音小语音1.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            \n            };\n            .recording_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n           \n        };\n        // 录音中\n        .recording_btn_the_recording {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #7278F5;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            margin-bottom: 40px;\n            .recording_img_the_recording {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_小-声音波浪.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            };\n            .recording_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n        };\n        // 完成录音\n        .complete_the_recording_btn {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #2932E1;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            margin-bottom: 40px;\n            &:hover {\n                background: #7278F5;\n                .complete_the_recording_img {\n                    width: 20px;\n                    height: 20px;\n                    background: url(\"../../../assets/image//icon_小-声音波浪.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 20px 20px;\n                    margin-right: 8.26px;\n                \n                };\n            }\n            .complete_the_recording_img {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_小-声音波浪.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            \n            };\n            .complete_the_recording_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n           \n        };\n         // table\n         .recording_table {\n            width: 322px;\n            .recording_table_box {\n                .ant-table-thead > tr > th {\n                    color: rgba(0, 0, 0, 0.85);\n                    font-weight: 500;\n                    text-align: left;\n                    background: rgba(40,50,225,0.08);\n                    border-bottom: none; \n                    transition: background 0.3s ease;\n                    height: 22px;\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #333333;\n                    // text-align: center;\n                    font-weight: 400;\n                    &:nth-of-type(2) {\n                       border-left: 2px solid white; \n                    };\n                };\n            .ant-table-tbody > tr > td {\n                border-bottom: 1px solid #f0f0f0;\n                transition: background 0.3s;\n                height: 22px;\n                font-family: PingFangSC-Regular;\n                font-size: 16px;\n                color: #333333;\n                // text-align: center;\n                font-weight: 400;\n            };\n            };\n        };\n        // input\n        .recording_input {\n            width: 322px;\n            margin-bottom: 20px;\n        };\n    };\n    // 指向\n    .recording_point_to {\n        width: 63px;\n        height: 47px;\n        background: url(\"../../../assets/image//步骤-箭头切图@2x.png\");\n        background-repeat: no-repeat;\n        background-position: center;\n        background-size: 63px 47px;\n        margin-right: 66px;\n        margin-top: 198px;\n    };\n    //识别声纹\n    .voiceprint_identify {\n        width: 423px;\n        height: 354px;\n        .identify_title {\n            display: flex;\n            align-items: center;\n            margin-bottom: 20px;\n            div {\n                &:nth-of-type(1) {\n                    width: 24px;\n                    height: 24px;\n                    background: rgba(41,50,225,0.70);\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #FFFFFF;\n                    letter-spacing: 0;\n                    text-align: center;\n                    line-height: 24px;\n                    font-weight: 400;\n                    margin-right: 16px;\n                    border-radius: 50%;\n                };\n                &:nth-of-type(2) {\n                    height: 26px;\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #000000;\n                    line-height: 26px;\n                    font-weight: 400;\n                };\n            };\n        };\n        // 开始识别\n        .identify_btn {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #2932E1;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            margin-bottom: 40px;\n            margin-top: 10px;\n            &:hover {\n                background: #7278F5;\n                .identify_img {\n                    width: 20px;\n                    height: 20px;\n                    background: url(\"../../../assets/image//icon_录制声音小语音1.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 20px 20px;\n                    margin-right: 8.26px;\n                \n                };\n            }\n            .identify_img {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_录制声音小语音1.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            \n            };\n            .identify_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n           \n        };\n         // 识别中\n         .identify_btn_the_recording {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #7278F5;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            margin-bottom: 40px;\n            .identify_img_the_recording {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_录制声音小语音1.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            };\n            .recording_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n        };\n        // 完成识别\n        .identify_complete_the_recording_btn {\n            width: 143px;\n            height: 44px;\n            cursor: pointer;\n            background: #2932E1;\n            padding: 0px  24px 0px 21px;\n            box-sizing: border-box;\n            border-radius: 22px;\n            display: flex;\n            align-items: center;\n            margin-bottom: 40px;\n            &:hover {\n                background: #7278F5;\n                .identify_complete_the_recording_img {\n                    width: 20px;\n                    height: 20px;\n                    background: url(\"../../../assets/image//icon_小-声音波浪.svg\");\n                    background-repeat: no-repeat;\n                    background-position: center;\n                    background-size: 20px 20px;\n                    margin-right: 8.26px;\n                \n                };\n            }\n            .identify_complete_the_recording_img {\n                width: 20px;\n                height: 20px;\n                background: url(\"../../../assets/image//icon_小-声音波浪.svg\");\n                background-repeat: no-repeat;\n                background-position: center;\n                background-size: 20px 20px;\n                margin-right: 8.26px;\n            \n            };\n            .identify_complete_the_recording_prompt {\n                height: 20px;\n                font-family: PingFangSC-Regular;\n                font-size: 12px;\n                color: #FFFFFF;\n                font-weight: 400;\n            };\n           \n        };\n\n\n\n\n        // 结果\n        .identify_result {\n            width: 422px;\n            height: 184px;\n            text-align: center;\n            line-height: 184px;\n            background: #FAFAFA;\n            position: relative;\n            .identify_result_default {\n               \n            font-family: PingFangSC-Regular;\n            font-size: 16px;\n            color: #999999;\n            font-weight: 400;\n            };\n            .identify_result_content {\n                // text-align: center;\n                // position: absolute;\n                // top: 50%;\n                // left: 50%;\n                // transform: translate(-50%,-50%);\n               div {\n                   &:nth-of-type(1) {\n                    height: 22px;\n                    font-family: PingFangSC-Regular;\n                    font-size: 16px;\n                    color: #666666;\n                    font-weight: 400;\n                    margin-bottom: 10px;\n                   };\n                   &:nth-of-type(2) {\n                    height: 33px;\n                    font-family: PingFangSC-Medium;\n                    font-size: 24px;\n                    color: #000000;\n                    font-weight: 500;\n                   };\n               };\n            };\n        };\n    };\n    .action_btn {\n        display: inline-block;\n        height: 22px;\n        font-family: PingFangSC-Regular;\n        font-size: 16px;\n        color: #2932E1;\n        text-align: center;\n        font-weight: 400;\n        cursor: pointer;\n    };\n};"
  },
  {
    "path": "demos/speech_web/web_client/src/components/SubMenu/VoiceClone/VoiceClone.vue",
    "content": "<template>\n    <div class=\"voiceclone\">\n        <el-row :gutter=\"20\">\n            <el-col :span=\"12\"><div class=\"grid-content ep-bg-purple\" />\n                <el-row :gutter=\"60\" class=\"btn_row_wav\" justify=\"center\">\n                    <el-button class=\"ml-3\" v-if=\"onEnrollRec === 0\" @click=\"startRecorderEnroll()\" type=\"primary\">录制音频</el-button>\n                    <el-button class=\"ml-3\" v-else-if=\"onEnrollRec === 1\" @click=\"stopRecorderEnroll()\" type=\"danger\">停止录音</el-button>\n                    <el-button class=\"ml-3\" v-else @click=\"uploadRecord()\" type=\"success\">上传录音</el-button>\n                    <a>&#12288</a>\n                    <el-upload\n                        :multiple=\"false\"\n                        :accept=\"'.wav'\"\n                        :auto-upload=\"false\"\n                        :on-change=\"handleChange\"\n                        :show-file-list=\"false\"\n                    >\n                        <el-button class=\"ml-3\" type=\"success\">上传音频文件</el-button>\n                    </el-upload>\n                </el-row>\n                <div class=\"recording_table\">\n                <el-table :data=\"vcDatas\" border class=\"recording_table_box\" scrollbar-always-on max-height=\"250px\">\n                    <el-table-column prop=\"wavId\" label=\"序号\" width=\"60\"/>\n                    <el-table-column prop=\"wavName\" label=\"文件名\" />\n                    <el-table-column label=\"操作\" width=\"80\">\n                        <template #default=\"scope\">\n                            <div class=\"flex justify-space-between mb-4 flex-wrap gap-4\">\n                                <a @click=\"PlayTable(scope.row.wavId)\"><el-icon><VideoPlay /></el-icon></a>\n                                <a>&#12288</a>\n                                <a @click=\"delWav(scope.row.wavId)\"><el-icon><DeleteFilled /></el-icon></a>\n                            </div>\n                        </template>\n                    </el-table-column>\n                    <el-table-column fixed=\"right\" label=\"选择\" width=\"70\">\n                        <template #default=\"scope\">\n                            <el-switch v-model=\"scope.row.status\"  @click=\"choseWav(scope.row.wavId)\"/>\n                        </template>\n                    </el-table-column>\n                </el-table>\n                </div>\n\n            </el-col>\n            <el-col :span=\"8\"><div class=\"grid-content ep-bg-purple\" />\n                <el-space direction=\"vertical\">\n                    <el-card class=\"box-card\" style=\"width: 250px; height:310px\">\n                        <template #header>\n                            <div class=\"card-header\">\n                            <span>请输入中文文本</span>\n                            </div>\n                        </template>\n                        <div class=\"mb-2 flex items-center text-sm\">\n                            <el-radio-group v-model=\"func_radio\" class=\"ml-4\">\n                            <el-radio label=\"1\" size=\"large\">GE2E</el-radio>\n                            <el-radio label=\"2\" size=\"large\">ECAPA-TDNN</el-radio>\n                            </el-radio-group>\n                        </div>\n                        <el-input\n                            v-model=\"ttsText\"\n                            :autosize=\"{ minRows: 8, maxRows: 13 }\"\n                            type=\"textarea\"\n                            placeholder=\"Please input\"\n                            />\n                    </el-card>                    \n                </el-space>\n            </el-col>\n            <el-col :span=\"4\"><div class=\"grid-content ep-bg-purple\" />\n                <div class=\"play_board\">\n                    <el-space direction=\"vertical\">\n                        <el-row :gutter=\"20\">\n                            <el-button size=\"large\" v-if=\"g2pOnSys === 0\" type=\"primary\" @click=\"g2pClone()\">开始合成</el-button>\n                            <el-button size=\"large\" v-else :loading-icon=\"Eleme\" type=\"danger\">合成中</el-button>\n                        </el-row>\n\n                        <el-row :gutter=\"20\">\n                            <el-button v-if='this.cloneWav' type=\"success\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"PlaySyn()\">播放</el-button>\n                            <el-button v-if='this.cloneWav' type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                            <el-button v-else disabled type=\"primary\" @click=\"downLoadCloneWav()\">下载</el-button>\n                        </el-row>\n                    </el-space>\n                </div>\n            </el-col>\n        </el-row>\n    </div>\n</template>\n\n<script>\n\nimport Recorder from 'js-audio-recorder'\nimport { vcCloneG2P, vcCloneSAT, vcDel, vcUpload, vcList, vcDownload, vcDownloadBase64 } from '../../../api/ApiVC';\n\n// 初始化录音\nconst recorder = new Recorder({\n  sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16\n  sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000\n  numChannels: 1,                 // 声道，支持 1 或 2， 默认是1\n  compiling: true\n})\n\n// 初始化播放器\nconst audioCtx = new AudioContext({\n    latencyHint: 'interactive',\n    sampleRate: 16000,\n});\n\nexport default {\n    data(){\n         return {\n            onEnrollRec: 0,     // 注册录音状态\n            wav: '',            // 录音结果\n            vcDatas: [],       // 已录制的音频\n            nowFile: \"\",        // 当前选择的音频\n            ttsText: \"欢迎使用飞桨语音套件\",\n            nowIndex: -1,\n            cloneWav: \"\",\n            g2pOnSys: 0,\n            func_radio: '1',\n         }\n    },\n    mounted () {\n        this.GetList()\n    },\n    methods:{\n        // 重置\n        reset(){\n            this.onEnrollRec = 0\n            this.wav = ''\n            this.vcDatas = []\n            this.nowFile = \"\"\n            this.ttsText = \"欢迎使用飞桨语音套件\"\n            this.nowIndex = -1\n        },\n        // 开始录音\n        startRecorderEnroll(){\n            this.onEnrollRec = 1\n            recorder.clear()\n            recorder.start()\n        },\n        // 结束录音\n        stopRecorderEnroll(){\n            this.onEnrollRec = 2\n            recorder.stop()\n            this.wav = recorder.getWAVBlob()\n        },\n        // chose wav\n        choseWav(wavId){\n            this.cloneWav = ''\n            this.nowFile = this.vcDatas[wavId].wavName\n            this.nowIndex = wavId\n            // only wavId is true else false\n            for(let i=0; i<this.vcDatas.length; i++){\n                if(i==wavId){\n                    this.vcDatas[wavId].status = true\n                } else {\n                    this.vcDatas[i].status = false\n                }\n            }\n            this.$nextTick(()=>{})\n        },\n        // 上传录音\n        async uploadRecord(){\n            this.onEnrollRec = 0\n            if(this.wav === \"\"){\n                this.$message.error(\"未检测到录音，录音失败，请重新录制\")\n                return\n            } else {\n                if(this.wav === ''){\n                    this.$message.error(\"请先完成录音\");\n                    this.onEnrollRec = 0\n                    return\n                } else {\n                    let formData = new FormData();\n                    formData.append('files', this.wav);\n                    const result = await vcUpload(formData);\n                    console.log(result)\n                    this.GetList() \n                }\n                this.$message.success(\"录音上传成功\")\n            }\n        }, \n        // 上传列表改变\n        async handleChange(file, fileList){\n            for(let i=0; i<fileList.length; i++){\n                this.uploadFile(fileList[i])\n            } \n        },\n\n        // 上传音频\n        async uploadFile(file){\n            let formData = new FormData();\n            formData.append('files', file.raw);\n            const result = await vcUpload(formData);\n            if (result.data.code === 0) {\n                this.$message.success(\"音频上传成功\")\n                this.GetList()\n            } else {\n                this.$message.error(\"音频上传失败\")\n            }\n        },\n        // 获取文件列表\n        async GetList(){\n            this.vcDatas =[]\n            const result = await vcList();\n            for(let i=0; i<result.data.result.length; i++){\n                this.vcDatas.push({\n                    wavName: result.data.result[i]['name'],\n                    wavId: i,\n                    wavPath: result.data.result[i]['path'],\n                    status: false\n                })\n            }\n            this.$nextTick(()=>{})\n        },\n        // 删除音频文件\n        async delWav(wavId){\n            console.log('wavId', wavId)\n            // 删除文件\n            const result = await vcDel(\n                {\n                    wavName: this.vcDatas[wavId]['wavName'],\n                    wavPath: this.vcDatas[wavId]['wavPath']\n                }\n            );\n            if(!result.data.code){\n                this.$message.success(\"删除成功\")\n            } else {\n                this.$message.error(result.data.msg)\n            }\n            this.GetList()\n            this.reset()\n        },\n        // 下载合成文件\n        async downLoadCloneWav(){\n            if(this.cloneWav  === \"\"){\n                this.$message.error(\"音频合成完毕后再下载！\")\n            } else {\n                // const result = await vcDownload(this.cloneWav);\n                // 获取音频数据\n                const result = await vcDownloadBase64(this.cloneWav);\n                let view;\n                // console.log('play result', result)\n                if (result.data.code === 0) {\n                    // base转换二进制数\n                    let typedArray = this.base64ToUint8Array(result.data.result)\n                    // 添加wav文件头\n                    view = new DataView(typedArray.buffer);\n                    view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n                    // 播放音频\n                    // this.playAudioData(view.buffer);\n                }\n                console.log(view.buffer)\n                // debugger\n                const blob = new Blob([view.buffer], { type: 'audio/wav' });\n                const fileName = new Date().getTime() + '.wav';\n                const down = document.createElement('a');\n                down.download = fileName;\n                down.style.display = 'none';//隐藏,没必要展示出来\n                down.href = URL.createObjectURL(blob);\n                document.body.appendChild(down);\n                down.click();\n                URL.revokeObjectURL(down.href); // 释放URL 对象\n                document.body.removeChild(down);//下载完成移除\n            }\n        },\n        // g2p voice clone\n        async g2pClone(){\n            if(this.nowIndex === -1){\n                return this.$message.error(\"请先录音并上传，选择音频后再点击合成\")\n            } else if (this.ttsText === \"\"){\n                return this.$message.error(\"合成文本不可以为空\")\n            } else if (this.nowIndex >= this.vcDatas.length){\n                return this.$message.error(\"当前序号不可以超过音频个数\")\n            }\n            this.cloneWav = \"\"\n            let func = ''\n            if(this.func_radio === '1'){\n                func = 'ge2e'\n            } else {\n                func = 'ecapa_tdnn'\n            }\n            console.log('func', func)\n\n            // 合成\n            this.g2pOnSys = 1\n            const result = await vcCloneG2P(\n                {\n                    wavName: this.vcDatas[this.nowIndex]['wavName'],\n                    wavPath: this.vcDatas[this.nowIndex]['wavPath'],\n                    text: this.ttsText,\n                    func: func\n                }\n            );\n            this.g2pOnSys = 0\n            if(result.data.code == 0){\n                this.cloneWav = result.data.result\n                console.log(\"clone wav: \", this.cloneWav)\n                this.$message.success(\"音频合成成功\")\n            } else {\n                this.$message.error(\"音频合成失败，请检查后台错误后重试！\")\n            }\n        },\n        // 播放表格\n        async PlayTable(wavId){\n            this.Play(this.vcDatas[wavId])\n        },\n        // 播放合成后的音频\n        async PlaySyn(){\n            if(this.cloneWav  === \"\"){\n                this.$message.error(\"请合成音频后再播放！！\")\n                return\n            } else {\n                this.Play(this.cloneWav)\n            }\n        },\n        // 播放音频\n        async Play(wavBase){\n                // 获取音频数据\n                const result = await vcDownloadBase64(wavBase);\n                // console.log('play result', result)\n                if (result.data.code === 0) {\n                    // base转换二进制数\n                    let typedArray = this.base64ToUint8Array(result.data.result)\n                    // 添加wav文件头\n                    let view = new DataView(typedArray.buffer);\n                    view = Recorder.encodeWAV(view, 16000, 16000, 1, 16, true);\n                    // 播放音频\n                    this.playAudioData(view.buffer);\n                };\n        },\n        // base64解码\n        base64ToUint8Array(base64String) {\n            const padding = '='.repeat((4 - base64String.length % 4) % 4);\n            const base64 = (base64String + padding)\n                            .replace(/-/g, '+')\n                            .replace(/_/g, '/');\n\n            const rawData = window.atob(base64);\n            const outputArray = new Uint8Array(rawData.length);\n\n            for (let i = 0; i < rawData.length; ++i) {\n                    outputArray[i] = rawData.charCodeAt(i);\n            }\n            return outputArray;\n        }, \n        // 播放音频\n        playAudioData( wav_buffer ) {\n        audioCtx.decodeAudioData(wav_buffer, buffer => {\n            var source = audioCtx.createBufferSource();\n            source.buffer = buffer;\n            source.connect(audioCtx.destination);\n            source.start();\n        }, function(e) {\n            Recorder.throwError(e);\n            })\n        },\n    },\n}\n</script>\n\n<style lang=\"less\" scoped>\n// @import \"./style.less\";\n.voiceclone {\n    width: 1200px;\n    height: 410px;\n    background: #FFFFFF;\n    padding: 5px 80px 56px 80px;\n    box-sizing: border-box;\n}\n.el-row {\n  margin-bottom: 20px;\n}\n.grid-content {\n  border-radius: 4px;\n  min-height: 36px;\n}\n.play_board{\n    height: 100%;\n    display: flex;\n    align-items: center;\n}\n</style>"
  },
  {
    "path": "demos/speech_web/web_client/src/components/style.less",
    "content": ".experience {\n    width: 100%;\n    height: 709px;\n    // background: url(\"../assets/image/在线体验-背景@2x.png\") no-repeat;\n    background-size: 100% 709px;\n    background-position: initial;   \n    // \n    .experience_wrapper {\n        width: 1200px;\n        height: 709px;\n        margin: 0 auto;\n        padding: 0px 0px 0px 0px;\n        box-sizing: border-box;\n        // background: red;\n        .experience_title {\n            height: 42px;\n            font-family: PingFangSC-Semibold;\n            font-size: 30px;\n            color: #000000;\n            font-weight: 600;\n            line-height: 42px;\n            text-align: center;\n            margin-bottom: 10px;\n        };\n        .experience_describe {\n            height: 22px;\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #666666;\n            letter-spacing: 0;\n            text-align: center;\n            line-height: 22px;\n            font-weight: 400;\n            margin-bottom: 30px;\n        };\n        .experience_content {\n            width: 1200px;\n            margin: 0 auto;\n            display: flex;\n            justify-content: center;\n            .experience_tabs {\n                \n                    margin-top: 15px;\n            \n                    & > .ant-tabs-nav {\n                        margin-bottom: 20px;\n                \n                        &::before {\n                            content: none;\n                        }\n                \n                        .ant-tabs-nav-wrap {\n                            justify-content: center;\n                        }\n                \n                        .ant-tabs-tab {\n                            font-size: 20px;\n                        }\n                \n                        .ant-tabs-nav-list {\n                            margin-right: -32px;\n                            flex: none;\n                        }\n                    };\n            \n                .ant-tabs-nav::before {\n                    position: absolute;\n                    right: 0;\n                    left: 0;\n                    border-bottom: 1px solid #f6f7fe;\n                    content: '';\n                };\n               \n            };\n        };\n    };\n};\n.experience::after {\n    content: \"\";\n    display: block;\n    clear: both;\n    visibility: hidden;\n}"
  },
  {
    "path": "demos/speech_web/web_client/src/main.js",
    "content": "import { createApp } from 'vue'\nimport ElementPlus from 'element-plus'\nimport * as ElementPlusIconsVue from '@element-plus/icons-vue'\nimport 'element-plus/dist/index.css'\nimport Antd from 'ant-design-vue';\nimport 'ant-design-vue/dist/antd.css';\nimport App from './App.vue'\nimport axios from 'axios'\n\nconst app = createApp(App)\napp.config.globalProperties.$http = axios\n\nfor (const [key, component] of Object.entries(ElementPlusIconsVue)) {\n    app.component(key, component)\n  }\napp.use(ElementPlus).use(Antd)\napp.mount('#app')\n"
  },
  {
    "path": "demos/speech_web/web_client/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [vue()],\n  css: \n    { preprocessorOptions:\n      { css: \n        { \n          charset: false \n        } \n      } \n    },\n  build: {\n      assetsInlineLimit: '2048' // 2kb\n  },\n  server: {\n    host: \"0.0.0.0\",\n    proxy: {\n      \"/api\": {\n        target: \"http://localhost:8010\",\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, \"\"),\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "demos/story_talker/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Story Talker\n## Introduction\nStorybooks are very important children's enlightenment books, but parents usually don't have enough time to read storybooks for their children. For very young children, they may not understand the Chinese characters in storybooks. Or sometimes, children just want to \"listen\" but don't want to \"read\".\n\nYou can use `PaddleOCR` to get the text of a storybook and read it by the `TTS` module of `PaddleSpeech`.\n\n## Usage\nRun the following command line to get started:\n```\n./run.sh\n```\nThe result has shown in our [notebook](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/tutorial/tts/tts_tutorial.ipynb).\n"
  },
  {
    "path": "demos/story_talker/README_cn.md",
    "content": "\n(简体中文|[English](./README.md))\n\n# Story Talker\n\n## 简介\n\n故事书是非常重要的儿童启蒙书，但家长通常没有足够的时间为孩子读故事书。对于非常小的孩子，他们可能不理解故事书中的汉字。或有时，孩子们只是想“听”，而不想“读”。\n\n您可以使用 `PaddleOCR` 获取故事书的文本，并通过 `PaddleSpeech` 的 `TTS` 模块进行阅读。\n\n## 使用\n\n运行以下命令行开始：\n\n```\n./run.sh\n```\n\n结果已显示在 [notebook](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/tutorial/tts/tts_tutorial.ipynb)。\n"
  },
  {
    "path": "demos/story_talker/ocr.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport re\nfrom pathlib import Path\n\nimport paddle\nfrom paddleocr import draw_ocr\nfrom paddleocr import PaddleOCR\nfrom PIL import Image\n\n\ndef evaluate(args, ocr):\n    img_dir = Path(args.img_dir)\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    img_out_dir = output_dir / \"imgs\"\n    img_out_dir.mkdir(parents=True, exist_ok=True)\n    with open(output_dir / \"sentences.txt\", \"w\") as wf:\n        for name in os.listdir(img_dir):\n            id = name.split(\".\")[0]\n            img_path = img_dir / name\n            result = ocr.ocr(str(img_path), cls=True)\n            # draw result\n            image = Image.open(img_path).convert('RGB')\n            boxes = [line[0] for line in result]\n            txts = [line[1][0] for line in result]\n            scores = [line[1][1] for line in result]\n            im_show = draw_ocr(\n                image, boxes, txts, scores, font_path=args.font_path)\n            im_show = Image.fromarray(im_show)\n            paragraph = \"\".join(txts)\n            # 过滤出中文结果\n            pattern = re.compile(r'[^(\\u4e00-\\u9fa5)+，。？、]')\n            sentence = re.sub(pattern, '', paragraph)\n            im_show.save(img_out_dir / name)\n            wf.write(id + \" \" + sentence + \"\\n\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with fastspeech2 & parallel wavegan.\")\n    parser.add_argument(\"--img-dir\", default=\"imgs\", type=str, help=\"img_dir.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        default=\"output\",\n        help=\"output sentences path.\")\n    parser.add_argument(\n        \"--font-path\", type=str, default=\"simfang.ttf\", help=\"font path\")\n    args = parser.parse_args()\n\n    paddle.set_device(\"gpu\")\n    # need to run only once to download and load model into memory\n    ocr = PaddleOCR(use_angle_cls=True, lang='ch')\n\n    evaluate(args, ocr)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "demos/story_talker/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=fastspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "demos/story_talker/run.sh",
    "content": "#!/bin/bash\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\n# with the following command, you can choice the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nmkdir -p download\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # install PaddleOCR\n    pip install \"paddleocr>=2.0.1\"\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # download pretrained tts models and unzip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip\n    unzip -d download download/pwg_baker_ckpt_0.4.zip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip\n    unzip -d download download/fastspeech2_nosil_baker_ckpt_0.4.zip\n    # download sources\n    wget -P download https://paddlespeech.cdn.bcebos.com/demos/story_talker/simfang.ttf\n    wget -P download/imgs https://paddlespeech.cdn.bcebos.com/demos/story_talker/000.jpg\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # run ocr\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    python3 ocr.py --img-dir=download/imgs --output-dir=output --font-path=download/simfang.ttf\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # run tts\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=download/fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n        --am_ckpt=download/fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n        --am_stat=download/fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy  \\\n        --voc=pwgan_csmsc \\\n        --voc_config=download/pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=download/pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=download/pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=output/sentences.txt \\\n        --output_dir=output/wavs \\\n        --inference_dir=output/inference \\\n        --phones_dict=download/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n    # output/inference is not needed here, which save the static models\n    rm -rf output/inference\nfi\n"
  },
  {
    "path": "demos/streaming_asr_server/.gitignore",
    "content": "exp\n\n"
  },
  {
    "path": "demos/streaming_asr_server/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n> conf/ws_ds2_application.yaml need onnxruntime>=1.11.0\n\n# Streaming ASR Server\n\n## Introduction\nThis demo is an implementation of starting the streaming speech service and accessing the service. It can be achieved with a single command using `paddlespeech_server` and `paddlespeech_client` or a few lines of code in python.\n\nStreaming ASR server only support `websocket` protocol, and doesn't support `http` protocol.\n\nFor service interface definitions, please refer to:\n- [PaddleSpeech Streaming Server WebSocket API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-WebSocket-API)\n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nIt is recommended to use **paddlepaddle 2.4rc** or above.\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n**If you install in easy mode, you need to prepare the yaml file by yourself, you can refer to \n\n### 2. Prepare config File\nThe configuration file can be found in `conf/ws_application.yaml` or `conf/ws_conformer_wenetspeech_application.yaml`.\n\nAt present, the speech tasks integrated by the model include: DeepSpeech2 and conformer.\n\n\nThe input of  ASR client demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for thisASR client demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 3. Server Usage\n- Command Line (Recommended)\n  **Note:** The default deployment of the server is on the 'CPU' device, which can be deployed on the 'GPU' by modifying the 'device' parameter in the service configuration file.\n  ```bash\n  # in PaddleSpeech/demos/streaming_asr_server start the service\n   paddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application.yaml\n  # if you want to increase decoding speed, you can use the config file below, it will increase decoding speed and reduce accuracy  \n   paddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application_faster.yaml\n  ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  Arguments:\n  - `config_file`: yaml file of the app, default: `./conf/application.yaml`\n  - `log_file`: log file. Default: `./log/paddlespeech.log`\n\n  Output:\n  ```text\n  [2022-05-14 04:56:13,086] [    INFO] - create the online asr engine instance\n  [2022-05-14 04:56:13,086] [    INFO] - paddlespeech_server set the device: cpu\n  [2022-05-14 04:56:13,087] [    INFO] - Load the pretrained model, tag = conformer_online_wenetspeech-zh-16k\n  [2022-05-14 04:56:13,087] [    INFO] - File /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz md5        checking...\n  [2022-05-14 04:56:17,542] [    INFO] - Use pretrained model stored in: /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.  0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/model.yaml\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,852] [    INFO] - start to create the stream conformer asr engine\n  [2022-05-14 04:56:17,863] [    INFO] - model name: conformer_online\n  [2022-05-14 04:56:22,756] [    INFO] - create the transformer like model success\n  [2022-05-14 04:56:22,758] [    INFO] - Initialize ASR server engine successfully.\n  INFO:     Started server process [4242]\n  [2022-05-14 04:56:22] [INFO] [server.py:75] Started server process [4242]\n  INFO:     Waiting for application startup.\n  [2022-05-14 04:56:22] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-14 04:56:22] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-05-14 04:56:22] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  **Note:** The default deployment of the server is on the 'CPU' device, which can be deployed on the 'GPU' by modifying the 'device' parameter in the service configuration file.\n  ```python\n  # in PaddleSpeech/demos/streaming_asr_server directory\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/ws_conformer_wenetspeech_application_faster.yaml\",\n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  Output:\n  ```text\n  [2022-05-14 04:56:13,086] [    INFO] - create the online asr engine instance\n  [2022-05-14 04:56:13,086] [    INFO] - paddlespeech_server set the device: cpu\n  [2022-05-14 04:56:13,087] [    INFO] - Load the pretrained model, tag = conformer_online_wenetspeech-zh-16k\n  [2022-05-14 04:56:13,087] [    INFO] - File /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz md5        checking...\n  [2022-05-14 04:56:17,542] [    INFO] - Use pretrained model stored in: /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.  0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/model.yaml\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,852] [    INFO] - start to create the stream conformer asr engine\n  [2022-05-14 04:56:17,863] [    INFO] - model name: conformer_online\n  [2022-05-14 04:56:22,756] [    INFO] - create the transformer like model success\n  [2022-05-14 04:56:22,758] [    INFO] - Initialize ASR server engine successfully.\n  INFO:     Started server process [4242]\n  [2022-05-14 04:56:22] [INFO] [server.py:75] Started server process [4242]\n  INFO:     Waiting for application startup.\n  [2022-05-14 04:56:22] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-14 04:56:22] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-05-14 04:56:22] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n\n### 4. ASR Client Usage\n\n**Note:** The response time will be slightly longer when using the client for the first time\n- Command Line (Recommended)\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ```bash\n  paddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n  ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_client asr_online --help\n  ```\n\n  Arguments:\n  - `server_ip`: server ip. Default: 127.0.0.1\n  - `port`: server port. Default: 8090\n  - `input`(required): Audio file to be recognized.\n  - `sample_rate`: Audio ampling rate, default: 16000.\n  - `lang`: Language. Default: \"zh_cn\".\n  - `audio_format`: Audio format. Default: \"wav\".\n  - `punc.server_ip`: punctuation server ip. Default: None.\n  - `punc.server_port`: punctuation server port. Default: None.\n\n  Output:\n  ```text\n  [2022-05-06 21:10:35,598] [    INFO] - Start to do streaming asr client\n  [2022-05-06 21:10:35,600] [    INFO] - asr websocket client start\n  [2022-05-06 21:10:35,600] [    INFO] - endpoint: ws://127.0.0.1:8390/paddlespeech/asr/streaming\n  [2022-05-06 21:10:35,600] [    INFO] - start to process the wavscp: ./zh.wav\n  [2022-05-06 21:10:35,670] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-06 21:10:35,699] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,713] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,726] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,738] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,750] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,762] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,774] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,786] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,387] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,398] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,407] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,416] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,425] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,434] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,442] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,930] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,938] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,946] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,954] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,962] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,970] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,977] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,985] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:37,484] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,492] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,500] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,508] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,517] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,525] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,532] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:38,050] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,058] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,066] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,073] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,081] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,089] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,097] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,105] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,630] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,639] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,647] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,655] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,663] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,671] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,679] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:39,216] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,224] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,232] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,240] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,248] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,256] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,264] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,272] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,885] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,896] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,905] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,915] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,924] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,934] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:44,827] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-06 21:10:44,827] [    INFO] - audio duration: 4.9968125, elapsed time: 9.225094079971313, RTF=1.846195765794957\n  [2022-05-06 21:10:44,828] [    INFO] - asr websocket client finished : 我认为跑步最重要的就是给我带来了身体健康\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ASROnlineClientExecutor\n\n  asrclient_executor = ASROnlineClientExecutor()\n  res = asrclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      sample_rate=16000,\n      lang=\"zh_cn\",\n      audio_format=\"wav\")\n  print(res)\n  ```\n\n  Output:\n  ```text\n  [2022-05-06 21:14:03,137] [    INFO] - asr websocket client start\n  [2022-05-06 21:14:03,137] [    INFO] - endpoint: ws://127.0.0.1:8390/paddlespeech/asr/streaming\n  [2022-05-06 21:14:03,149] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-06 21:14:03,167] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,181] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,194] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,207] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,219] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,230] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,241] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,252] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,768] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,776] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,784] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,792] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,800] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,807] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,815] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:04,301] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,309] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,317] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,325] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,333] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,341] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,349] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,356] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,855] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,864] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,871] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,879] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,887] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,894] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,902] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:05,418] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,426] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,434] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,442] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,449] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,457] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,465] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,473] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,996] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,006] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,013] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,021] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,029] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,037] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,045] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,581] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,589] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,597] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,605] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,613] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,621] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,628] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,636] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:07,188] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,196] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,203] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,211] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,219] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,226] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:12,158] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-06 21:14:12,159] [    INFO] - audio duration: 4.9968125, elapsed time: 9.019973039627075, RTF=1.8051453881103354\n  [2022-05-06 21:14:12,160] [    INFO] - asr websocket client finished\n  ```\n\n\n## Punctuation service\n\n### 1. Server usage\n \n- Command Line\n  **Note:** The default deployment of the server is on the 'CPU' device, which can be deployed on the 'GPU' by modifying the 'device' parameter in the service configuration file.\n  ```bash\n  In PaddleSpeech/demos/streaming_asr_server directory to launch punctuation service\n  paddlespeech_server start --config_file conf/punc_application.yaml\n  ```\n\n   Usage:\n  ```bash\n  paddlespeech_server start --help\n  ```\n  \n  Arguments:\n  - `config_file`: configuration file.\n  - `log_file`: log file.\n\n\n  Output:\n  ```text\n  [2022-05-02 17:59:26,285] [    INFO] - Create the TextEngine Instance\n  [2022-05-02 17:59:26,285] [    INFO] - Init the text engine\n  [2022-05-02 17:59:26,285] [    INFO] - Text Engine set the device: gpu:0\n  [2022-05-02 17:59:26,286] [    INFO] - File /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar.gz md5 checking...\n  [2022-05-02 17:59:30,810] [    INFO] - Use pretrained model stored in: /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar\n  W0502 17:59:31.486552  9595 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 10.2, Runtime API Version: 10.2\n  W0502 17:59:31.491360  9595 device_context.cc:465] device: 0, cuDNN Version: 7.6.\n  [2022-05-02 17:59:34,688] [    INFO] - Already cached /home/users/xiongxinlei/.paddlenlp/models/ernie-1.0/vocab.txt\n  [2022-05-02 17:59:34,701] [    INFO] - Init the text engine successfully\n  INFO:     Started server process [9595]\n  [2022-05-02 17:59:34] [INFO] [server.py:75] Started server process [9595]\n  INFO:     Waiting for application startup.\n  [2022-05-02 17:59:34] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-02 17:59:34] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  [2022-05-02 17:59:34] [INFO] [server.py:206] Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  **Note:** The default deployment of the server is on the 'CPU' device, which can be deployed on the 'GPU' by modifying the 'device' parameter in the service configuration file.\n  ```python\n  # 在 PaddleSpeech/demos/streaming_asr_server 目录\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/punc_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  Output:\n  ```text\n  [2022-05-02 18:09:02,542] [    INFO] - Create the TextEngine Instance\n  [2022-05-02 18:09:02,543] [    INFO] - Init the text engine\n  [2022-05-02 18:09:02,543] [    INFO] - Text Engine set the device: gpu:0\n  [2022-05-02 18:09:02,545] [    INFO] - File /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar.gz md5 checking...\n  [2022-05-02 18:09:06,919] [    INFO] - Use pretrained model stored in: /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar\n  W0502 18:09:07.523002 22615 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 10.2, Runtime API Version: 10.2\n  W0502 18:09:07.527882 22615 device_context.cc:465] device: 0, cuDNN Version: 7.6.\n  [2022-05-02 18:09:10,900] [    INFO] - Already cached /home/users/xiongxinlei/.paddlenlp/models/ernie-1.0/vocab.txt\n  [2022-05-02 18:09:10,913] [    INFO] - Init the text engine successfully\n  INFO:     Started server process [22615]\n  [2022-05-02 18:09:10] [INFO] [server.py:75] Started server process [22615]\n  INFO:     Waiting for application startup.\n  [2022-05-02 18:09:10] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-02 18:09:10] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  [2022-05-02 18:09:10] [INFO] [server.py:206] Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  ```\n\n### 2. Client usage\n**Note** The response time will be slightly longer when using the client for the first time\n\n- Command line:\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ```bash\n  paddlespeech_client text --server_ip 127.0.0.1 --port 8190 --input \"我认为跑步最重要的就是给我带来了身体健康\"\n  ```\n  \n  Output\n  ```text\n  [2022-05-02 18:12:29,767] [    INFO] - The punc text: 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-02 18:12:29,767] [    INFO] - Response time 0.096548 s.\n  ```\n\n- Python API\n\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TextClientExecutor\n\n  textclient_executor = TextClientExecutor()\n  res = textclient_executor(\n      input=\"我认为跑步最重要的就是给我带来了身体健康\",\n      server_ip=\"127.0.0.1\",\n      port=8190,)\n  print(res)\n  ```\n\n  Output:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康。\n  ```\n\n## Join streaming asr and punctuation server\n\nBy default, each server is deployed on the 'CPU' device and speech recognition and punctuation prediction can be deployed on different 'GPU' by modifying the' device 'parameter in the service configuration file respectively.\n\nWe use `streaming_ asr_server.py` and `punc_server.py` two services to launch streaming speech recognition and punctuation prediction services respectively. And the `websocket_client.py` script can be used to call streaming speech recognition and punctuation prediction services at the same time.\n\n### 1. Start two server\n\n```bash\nNote: streaming speech recognition and punctuation prediction are configured on different graphics cards through configuration files\nbash server.sh\n```\n\n### 2. Call client\n- Command line\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ```bash\n  paddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --input ./zh.wav\n  ```\n  Output:\n  ```text\n  [2022-05-07 11:21:47,060] [    INFO] - asr websocket client start\n  [2022-05-07 11:21:47,060] [    INFO] - endpoint: ws://127.0.0.1:8490/paddlespeech/asr/streaming\n  [2022-05-07 11:21:47,080] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-07 11:21:47,096] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,108] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,120] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,131] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,142] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,152] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,163] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,173] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,705] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,713] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,721] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,728] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,736] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,743] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,751] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:48,459] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,572] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,681] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,790] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,898] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,005] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,112] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,219] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,935] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,062] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,186] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,310] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,435] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,560] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,686] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:51,444] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,606] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,744] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,882] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,020] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,159] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,298] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,437] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:53,298] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,450] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,589] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,728] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,867] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:54,007] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:54,146] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:55,002] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,148] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,292] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,437] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,584] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,731] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,877] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:56,021] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:56,842] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,013] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,174] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,336] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,497] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,659] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:22:03,035] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康。', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-07 11:22:03,035] [    INFO] - audio duration: 4.9968125, elapsed time: 15.974023818969727, RTF=3.1968427510477384\n  [2022-05-07 11:22:03,037] [    INFO] - asr websocket client finished\n  [2022-05-07 11:22:03,037] [    INFO] - 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-07 11:22:03,037] [    INFO] - Response time 15.977116 s.\n  ```\n\n- Use script\n\n  If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n  ```bash\n  python3 local/websocket_client.py --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ./zh.wav\n  ```\n  Output:\n  ```text\n  [2022-05-07 11:11:02,984] [    INFO] - Start to do streaming asr client\n  [2022-05-07 11:11:02,985] [    INFO] - asr websocket client start\n  [2022-05-07 11:11:02,985] [    INFO] - endpoint: ws://127.0.0.1:8490/paddlespeech/asr/streaming\n  [2022-05-07 11:11:02,986] [    INFO] - start to process the wavscp: ./zh.wav\n  [2022-05-07 11:11:03,006] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-07 11:11:03,021] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,034] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,046] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,058] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,070] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,081] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,092] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,102] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,629] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,638] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,645] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,653] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,661] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,668] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,676] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:04,402] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,510] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,619] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,743] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,849] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,956] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,063] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,170] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,876] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,019] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,184] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,342] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,537] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,727] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,871] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:07,617] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:07,769] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:07,905] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,043] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,186] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,326] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,466] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,611] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:09,431] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,571] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,714] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,853] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,992] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:10,129] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:10,266] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:11,113] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,296] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,439] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,582] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,727] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,869] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,011] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,153] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,969] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,137] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,297] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,456] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,615] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,776] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:18,915] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康。', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-07 11:11:18,915] [    INFO] - audio duration: 4.9968125, elapsed time: 15.928460597991943, RTF=3.187724293835709\n  [2022-05-07 11:11:18,916] [    INFO] - asr websocket client finished : 我认为跑步最重要的就是给我带来了身体健康\n  ```\n\n## Generate corresponding subtitle (.srt format) from audio file (.wav format or.mp3 format)\n\nBy default, each server is deployed on the 'CPU' device and speech recognition and punctuation prediction can be deployed on different 'GPU' by modifying the' device 'parameter in the service configuration file respectively.\n\nWe use `streaming_ asr_server.py` and `punc_server.py` two services to launch streaming speech recognition and punctuation prediction services respectively. And the `websocket_client_srt.py` script can be used to call streaming speech recognition and punctuation prediction services at the same time, and will generate the corresponding subtitle (.srt format).\n\n**need to install ffmpeg before running this script**\n\n**You should at the directory of `.../demos/streaming_asr_server/`**\n\n### 1. Start two server\n\n```bash\nNote: streaming speech recognition and punctuation prediction are configured on different graphics cards through configuration files\npaddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application.yaml\n```\n\nOpen another terminal run the following commands:\n```bash\npaddlespeech_server start --config_file conf/punc_application.yaml\n```\n\n### 2. Call client\n\n  ```bash\n  python3 local/websocket_client_srt.py --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ../../data/认知.mp3\n  ```\n  Output:\n  ```text\n  [2023-03-30 23:26:13,991] [    INFO] - Start to do streaming asr client\n[2023-03-30 23:26:13,994] [    INFO] - asr websocket client start\n[2023-03-30 23:26:13,994] [    INFO] - endpoint: http://127.0.0.1:8190/paddlespeech/text\n[2023-03-30 23:26:13,994] [    INFO] - endpoint: ws://127.0.0.1:8090/paddlespeech/asr/streaming\n[2023-03-30 23:26:14,475] [    INFO] - /home/fxb/PaddleSpeech-develop/data/认知.mp3 converted to /home/fxb/PaddleSpeech-develop/data/认知.wav\n[2023-03-30 23:26:14,476] [    INFO] - start to process the wavscp: /home/fxb/PaddleSpeech-develop/data/认知.wav\n[2023-03-30 23:26:14,515] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n[2023-03-30 23:26:14,533] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,545] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,556] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,572] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,588] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,600] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,613] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,626] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:15,122] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,135] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,154] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,163] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,175] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,185] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,196] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,637] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,648] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,657] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,666] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,676] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,683] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,691] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,703] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:16,146] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,159] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,167] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,177] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,187] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,197] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,210] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,694] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,704] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,713] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,725] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,737] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,749] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,759] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,770] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:17,279] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,302] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,316] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,332] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,343] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,358] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,958] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:17,971] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:17,987] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,000] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,017] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,028] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,038] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,049] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,653] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,689] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,701] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,712] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,723] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,750] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,767] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:19,295] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,307] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,323] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,332] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,342] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,349] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:20,046] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,055] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,067] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,076] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,124] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,135] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,732] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,742] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,757] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,770] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,782] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,798] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,815] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,834] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:21,390] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,405] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,416] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,428] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,459] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,473] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:22,065] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,085] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,110] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,118] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,137] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,144] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,154] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,169] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,698] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,709] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,731] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,743] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,755] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,771] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,782] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:23,415] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,430] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,442] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,456] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,470] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,487] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,498] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,524] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:24,200] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,210] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,219] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,231] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,250] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,262] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,272] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,898] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,903] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,907] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,932] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,957] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,979] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,991] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:25,011] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:25,616] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,625] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,648] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,658] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,669] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,681] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,690] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,707] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,378] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,384] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,402] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,415] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,428] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:27,008] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,018] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,026] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,037] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,046] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,054] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,062] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,070] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,735] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,745] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,755] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,769] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,783] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,794] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,804] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:28,454] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,472] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,481] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,489] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,499] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,533] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,543] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,556] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:29,212] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,222] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,233] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,246] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,258] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,270] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,286] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:30,003] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,013] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,038] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,048] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,062] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,074] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,114] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,125] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,856] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,876] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,885] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,897] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,914] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,940] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,952] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:31,655] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,696] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,709] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,718] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,727] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,740] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,757] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,768] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:32,476] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,486] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,495] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,549] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,560] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,574] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,590] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:33,338] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,356] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,368] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,386] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,409] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,424] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,434] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:34,352] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,364] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,377] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,395] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,410] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,423] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,434] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:35,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,410] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,420] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,437] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,460] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,473] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:36,288] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,297] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,306] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,326] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,336] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,351] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,365] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:37,164] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,173] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,182] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,192] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,204] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,232] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,238] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,252] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:38,084] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,093] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,106] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,122] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,140] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,181] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,206] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:39,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,111] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,132] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,150] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,174] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,190] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,197] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,212] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:40,009] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,105] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,128] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,149] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,173] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,189] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,200] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,952] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,973] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,986] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,999] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,013] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,022] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,033] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,819] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,832] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,845] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,878] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,886] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,893] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,925] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,935] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:42,562] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,589] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,621] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,634] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,644] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,657] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,668] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:43,380] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,436] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,462] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,472] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,486] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,496] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:44,346] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,356] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,364] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,374] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,398] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,420] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:45,226] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,235] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,258] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,273] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,295] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,306] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:46,380] [    INFO] - client punctuation restored msg={'result': '第一部分是认知部分，该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理，让学生对设备有大致的认知。随后使用真实传感器的内部构造图，辅以文字说明，进一步帮助学生对传感器有更深刻的印象，最后结合具体的实践应用，提升学生对实训的兴趣以及意义感。'}\n[2023-03-30 23:27:01,059] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '第一部分是认知部分，该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理，让学生对设备有大致的认知。随后使用真实传感器的内部构造图，辅以文字说明，进一步帮助学生对传感器有更深刻的印象，最后结合具体的实践应用，提升学生对实训的兴趣以及意义感。', 'times': [{'w': '第', 'bg': 0.0, 'ed': 0.36}, {'w': '一', 'bg': 0.36, 'ed': 0.48}, {'w': '部', 'bg': 0.48, 'ed': 0.62}, {'w': '分', 'bg': 0.62, 'ed': 0.8200000000000001}, {'w': '是', 'bg': 0.8200000000000001, 'ed': 1.08}, {'w': '认', 'bg': 1.08, 'ed': 1.28}, {'w': '知', 'bg': 1.28, 'ed': 1.44}, {'w': '部', 'bg': 1.44, 'ed': 1.58}, {'w': '分', 'bg': 1.58, 'ed': 2.1}, {'w': '该', 'bg': 2.1, 'ed': 2.6}, {'w': '部', 'bg': 2.6, 'ed': 2.72}, {'w': '分', 'bg': 2.72, 'ed': 2.94}, {'w': '通', 'bg': 2.94, 'ed': 3.16}, {'w': '过', 'bg': 3.16, 'ed': 3.36}, {'w': '示', 'bg': 3.36, 'ed': 3.54}, {'w': '意', 'bg': 3.54, 'ed': 3.68}, {'w': '图', 'bg': 3.68, 'ed': 3.9}, {'w': '和', 'bg': 3.9, 'ed': 4.14}, {'w': '文', 'bg': 4.14, 'ed': 4.32}, {'w': '本', 'bg': 4.32, 'ed': 4.46}, {'w': '的', 'bg': 4.46, 'ed': 4.58}, {'w': '形', 'bg': 4.58, 'ed': 4.72}, {'w': '式', 'bg': 4.72, 'ed': 5.0}, {'w': '向', 'bg': 5.0, 'ed': 5.32}, {'w': '学', 'bg': 5.32, 'ed': 5.5}, {'w': '生', 'bg': 5.5, 'ed': 5.66}, {'w': '讲', 'bg': 5.66, 'ed': 5.86}, {'w': '解', 'bg': 5.86, 'ed': 6.18}, {'w': '主', 'bg': 6.18, 'ed': 6.46}, {'w': '要', 'bg': 6.46, 'ed': 6.62}, {'w': '传', 'bg': 6.62, 'ed': 6.8}, {'w': '感', 'bg': 6.8, 'ed': 7.0}, {'w': '器', 'bg': 7.0, 'ed': 7.16}, {'w': '的', 'bg': 7.16, 'ed': 7.28}, {'w': '工', 'bg': 7.28, 'ed': 7.44}, {'w': '作', 'bg': 7.44, 'ed': 7.6000000000000005}, {'w': '原', 'bg': 7.6000000000000005, 'ed': 7.74}, {'w': '理', 'bg': 7.74, 'ed': 8.06}, {'w': '让', 'bg': 8.06, 'ed': 8.44}, {'w': '学', 'bg': 8.44, 'ed': 8.64}, {'w': '生', 'bg': 8.64, 'ed': 8.84}, {'w': '对', 'bg': 8.84, 'ed': 9.06}, {'w': '设', 'bg': 9.06, 'ed': 9.24}, {'w': '备', 'bg': 9.24, 'ed': 9.52}, {'w': '有', 'bg': 9.52, 'ed': 9.86}, {'w': '大', 'bg': 9.86, 'ed': 10.1}, {'w': '致', 'bg': 10.1, 'ed': 10.24}, {'w': '的', 'bg': 10.24, 'ed': 10.36}, {'w': '认', 'bg': 10.36, 'ed': 10.5}, {'w': '知', 'bg': 10.5, 'ed': 11.040000000000001}, {'w': '随', 'bg': 11.040000000000001, 'ed': 11.56}, {'w': '后', 'bg': 11.56, 'ed': 11.82}, {'w': '使', 'bg': 11.82, 'ed': 12.1}, {'w': '用', 'bg': 12.1, 'ed': 12.26}, {'w': '真', 'bg': 12.26, 'ed': 12.44}, {'w': '实', 'bg': 12.44, 'ed': 12.620000000000001}, {'w': '传', 'bg': 12.620000000000001, 'ed': 12.780000000000001}, {'w': '感', 'bg': 12.780000000000001, 'ed': 12.94}, {'w': '器', 'bg': 12.94, 'ed': 13.1}, {'w': '的', 'bg': 13.1, 'ed': 13.26}, {'w': '内', 'bg': 13.26, 'ed': 13.42}, {'w': '部', 'bg': 13.42, 'ed': 13.56}, {'w': '构', 'bg': 13.56, 'ed': 13.700000000000001}, {'w': '造', 'bg': 13.700000000000001, 'ed': 13.86}, {'w': '图', 'bg': 13.86, 'ed': 14.280000000000001}, {'w': '辅', 'bg': 14.280000000000001, 'ed': 14.66}, {'w': '以', 'bg': 14.66, 'ed': 14.82}, {'w': '文', 'bg': 14.82, 'ed': 15.0}, {'w': '字', 'bg': 15.0, 'ed': 15.16}, {'w': '说', 'bg': 15.16, 'ed': 15.32}, {'w': '明', 'bg': 15.32, 'ed': 15.72}, {'w': '进', 'bg': 15.72, 'ed': 16.1}, {'w': '一', 'bg': 16.1, 'ed': 16.2}, {'w': '步', 'bg': 16.2, 'ed': 16.32}, {'w': '帮', 'bg': 16.32, 'ed': 16.48}, {'w': '助', 'bg': 16.48, 'ed': 16.66}, {'w': '学', 'bg': 16.66, 'ed': 16.82}, {'w': '生', 'bg': 16.82, 'ed': 17.12}, {'w': '对', 'bg': 17.12, 'ed': 17.48}, {'w': '传', 'bg': 17.48, 'ed': 17.66}, {'w': '感', 'bg': 17.66, 'ed': 17.84}, {'w': '器', 'bg': 17.84, 'ed': 18.12}, {'w': '有', 'bg': 18.12, 'ed': 18.42}, {'w': '更', 'bg': 18.42, 'ed': 18.66}, {'w': '深', 'bg': 18.66, 'ed': 18.88}, {'w': '刻', 'bg': 18.88, 'ed': 19.04}, {'w': '的', 'bg': 19.04, 'ed': 19.16}, {'w': '印', 'bg': 19.16, 'ed': 19.3}, {'w': '象', 'bg': 19.3, 'ed': 19.8}, {'w': '最', 'bg': 19.8, 'ed': 20.3}, {'w': '后', 'bg': 20.3, 'ed': 20.62}, {'w': '结', 'bg': 20.62, 'ed': 20.96}, {'w': '合', 'bg': 20.96, 'ed': 21.14}, {'w': '具', 'bg': 21.14, 'ed': 21.3}, {'w': '体', 'bg': 21.3, 'ed': 21.42}, {'w': '的', 'bg': 21.42, 'ed': 21.580000000000002}, {'w': '实', 'bg': 21.580000000000002, 'ed': 21.76}, {'w': '践', 'bg': 21.76, 'ed': 21.92}, {'w': '应', 'bg': 21.92, 'ed': 22.080000000000002}, {'w': '用', 'bg': 22.080000000000002, 'ed': 22.44}, {'w': '提', 'bg': 22.44, 'ed': 22.78}, {'w': '升', 'bg': 22.78, 'ed': 22.94}, {'w': '学', 'bg': 22.94, 'ed': 23.12}, {'w': '生', 'bg': 23.12, 'ed': 23.34}, {'w': '对', 'bg': 23.34, 'ed': 23.62}, {'w': '实', 'bg': 23.62, 'ed': 23.82}, {'w': '训', 'bg': 23.82, 'ed': 23.96}, {'w': '的', 'bg': 23.96, 'ed': 24.12}, {'w': '兴', 'bg': 24.12, 'ed': 24.3}, {'w': '趣', 'bg': 24.3, 'ed': 24.6}, {'w': '以', 'bg': 24.6, 'ed': 24.88}, {'w': '及', 'bg': 24.88, 'ed': 25.12}, {'w': '意', 'bg': 25.12, 'ed': 25.34}, {'w': '义', 'bg': 25.34, 'ed': 25.46}, {'w': '感', 'bg': 25.46, 'ed': 26.04}]}\n[2023-03-30 23:27:01,060] [    INFO] - audio duration: 26.04, elapsed time: 46.581613540649414, RTF=1.7888484462614982\nsentences:  ['第一部分是认知部分', '该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理', '让学生对设备有大致的认知', '随后使用真实传感器的内部构造图', '辅以文字说明', '进一步帮助学生对传感器有更深刻的印象', '最后结合具体的实践应用', '提升学生对实训的兴趣以及意义感']\nrelative_times:  [[0.0, 2.1], [2.1, 8.06], [8.06, 11.040000000000001], [11.040000000000001, 14.280000000000001], [14.280000000000001, 15.72], [15.72, 19.8], [19.8, 22.44], [22.44, 26.04]]\n[2023-03-30 23:27:01,076] [    INFO] - results saved to /home/fxb/PaddleSpeech-develop/data/认知.srt\n  ```\n"
  },
  {
    "path": "demos/streaming_asr_server/README_cn.md",
    "content": "([English](./README.md)|中文)\n\n# 流式语音识别服务\n\n## 介绍\n这个 demo 是一个启动流式语音服务和访问服务的实现。 它可以通过使用 `paddlespeech_server` 和 `paddlespeech_client` 的单个命令或 python 的几行代码来实现。\n\n**流式语音识别服务只支持 `websocket` 协议，不支持 `http` 协议。**\n\n服务接口定义请参考:\n- [PaddleSpeech Streaming Server WebSocket API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-WebSocket-API)\n\n## 使用方法\n### 1. 安装\n安装 PaddleSpeech 的详细过程请看 [安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md)。\n\n推荐使用 **paddlepaddle 2.4rc** 或以上版本。\n\n你可以从简单，中等，困难 几种方式中选择一种方式安装 PaddleSpeech。\n\n**如果使用简单模式安装，需要自行准备 yaml 文件，可参考 conf 目录下的 yaml 文件。**\n\n### 2. 准备配置文件\n\n流式ASR的服务启动脚本和服务测试脚本存放在 `PaddleSpeech/demos/streaming_asr_server` 目录。\n下载好 `PaddleSpeech` 之后，进入到 `PaddleSpeech/demos/streaming_asr_server` 目录。\n配置文件可参见该目录下 `conf/ws_application.yaml` 和 `conf/ws_conformer_wenetspeech_application.yaml` 。\n\n目前服务集成的模型有： DeepSpeech2 和 conformer模型，对应的配置文件如下：\n* DeepSpeech: `conf/ws_application.yaml`\n* conformer: `conf/ws_conformer_wenetspeech_application.yaml`\n\n\n这个 ASR client 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 ASR client的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 3. 服务端使用方法\n- 命令行 (推荐使用)\n  **注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数部署在 `gpu` 上。\n  ```bash\n  # 在 PaddleSpeech/demos/streaming_asr_server 目录启动服务\n  paddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application.yaml\n  # 你如果愿意为了增加解码的速度而牺牲一定的模型精度，你可以使用如下的脚本 \n   paddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application_faster.yaml\n  ```\n\n  使用方法：\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  参数:\n  - `config_file`: 服务的配置文件，默认： `./conf/application.yaml`\n  - `log_file`: log 文件. 默认：`./log/paddlespeech.log`\n\n  输出:\n  ```text\n  [2022-05-14 04:56:13,086] [    INFO] - create the online asr engine instance\n  [2022-05-14 04:56:13,086] [    INFO] - paddlespeech_server set the device: cpu\n  [2022-05-14 04:56:13,087] [    INFO] - Load the pretrained model, tag = conformer_online_wenetspeech-zh-16k\n  [2022-05-14 04:56:13,087] [    INFO] - File /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz md5        checking...\n  [2022-05-14 04:56:17,542] [    INFO] - Use pretrained model stored in: /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.  0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/model.yaml\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,852] [    INFO] - start to create the stream conformer asr engine\n  [2022-05-14 04:56:17,863] [    INFO] - model name: conformer_online\n  [2022-05-14 04:56:22,756] [    INFO] - create the transformer like model success\n  [2022-05-14 04:56:22,758] [    INFO] - Initialize ASR server engine successfully.\n  INFO:     Started server process [4242]\n  [2022-05-14 04:56:22] [INFO] [server.py:75] Started server process [4242]\n  INFO:     Waiting for application startup.\n  [2022-05-14 04:56:22] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-14 04:56:22] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-05-14 04:56:22] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  **注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数部署在 `gpu` 上。\n  ```python\n  # 在 PaddleSpeech/demos/streaming_asr_server 目录\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/ws_conformer_wenetspeech_application_faster.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  输出:\n  ```text\n  [2022-05-14 04:56:13,086] [    INFO] - create the online asr engine instance\n  [2022-05-14 04:56:13,086] [    INFO] - paddlespeech_server set the device: cpu\n  [2022-05-14 04:56:13,087] [    INFO] - Load the pretrained model, tag = conformer_online_wenetspeech-zh-16k\n  [2022-05-14 04:56:13,087] [    INFO] - File /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz md5        checking...\n  [2022-05-14 04:56:17,542] [    INFO] - Use pretrained model stored in: /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.  0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/model.yaml\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,543] [    INFO] - /root/.paddlespeech/models/conformer_online_wenetspeech-zh-16k/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar/exp/               chunk_conformer/checkpoints/avg_10.pdparams\n  [2022-05-14 04:56:17,852] [    INFO] - start to create the stream conformer asr engine\n  [2022-05-14 04:56:17,863] [    INFO] - model name: conformer_online\n  [2022-05-14 04:56:22,756] [    INFO] - create the transformer like model success\n  [2022-05-14 04:56:22,758] [    INFO] - Initialize ASR server engine successfully.\n  INFO:     Started server process [4242]\n  [2022-05-14 04:56:22] [INFO] [server.py:75] Started server process [4242]\n  INFO:     Waiting for application startup.\n  [2022-05-14 04:56:22] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-14 04:56:22] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  [2022-05-14 04:56:22] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)\n  ```\n\n### 4. ASR 客户端使用方法\n\n**注意：** 初次使用客户端时响应时间会略长\n- 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n  ```\n\n  使用帮助:\n\n  ```bash\n  paddlespeech_client asr_online --help\n  ```\n\n  参数:\n  - `server_ip`: 服务端ip地址，默认: 127.0.0.1。\n  - `port`: 服务端口，默认: 8090。\n  - `input`(必须输入): 用于识别的音频文件。\n  - `sample_rate`: 音频采样率，默认值：16000。\n  - `lang`: 模型语言，默认值：zh_cn。\n  - `audio_format`: 音频格式，默认值：wav。\n  - `punc.server_ip` 标点预测服务的ip。默认是None。\n  - `punc.server_port` 标点预测服务的端口port。默认是None。\n\n  输出:\n  ```text\n  [2022-05-06 21:10:35,598] [    INFO] - Start to do streaming asr client\n  [2022-05-06 21:10:35,600] [    INFO] - asr websocket client start\n  [2022-05-06 21:10:35,600] [    INFO] - endpoint: ws://127.0.0.1:8390/paddlespeech/asr/streaming\n  [2022-05-06 21:10:35,600] [    INFO] - start to process the wavscp: ./zh.wav\n  [2022-05-06 21:10:35,670] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-06 21:10:35,699] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,713] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,726] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,738] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,750] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,762] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,774] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:35,786] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,387] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,398] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,407] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,416] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,425] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,434] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,442] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:10:36,930] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,938] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,946] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,954] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,962] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,970] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,977] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:36,985] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:10:37,484] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,492] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,500] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,508] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,517] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,525] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:37,532] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:10:38,050] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,058] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,066] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,073] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,081] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,089] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,097] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,105] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:10:38,630] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,639] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,647] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,655] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,663] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,671] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:38,679] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:10:39,216] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,224] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,232] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,240] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,248] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,256] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,264] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,272] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:10:39,885] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,896] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,905] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,915] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,924] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:39,934] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:10:44,827] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-06 21:10:44,827] [    INFO] - audio duration: 4.9968125, elapsed time: 9.225094079971313, RTF=1.846195765794957\n  [2022-05-06 21:10:44,828] [    INFO] - asr websocket client finished : 我认为跑步最重要的就是给我带来了身体健康\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import ASROnlineClientExecutor\n\n  asrclient_executor = ASROnlineClientExecutor()\n  res = asrclient_executor(\n      input=\"./zh.wav\",\n      server_ip=\"127.0.0.1\",\n      port=8090,\n      sample_rate=16000,\n      lang=\"zh_cn\",\n      audio_format=\"wav\")\n  print(res)\n  ```\n\n  输出:\n  ```text\n  [2022-05-06 21:14:03,137] [    INFO] - asr websocket client start\n  [2022-05-06 21:14:03,137] [    INFO] - endpoint: ws://127.0.0.1:8390/paddlespeech/asr/streaming\n  [2022-05-06 21:14:03,149] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-06 21:14:03,167] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,181] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,194] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,207] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,219] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,230] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,241] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,252] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,768] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,776] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,784] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,792] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,800] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,807] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:03,815] [    INFO] - client receive msg={'result': ''}\n  [2022-05-06 21:14:04,301] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,309] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,317] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,325] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,333] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,341] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,349] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,356] [    INFO] - client receive msg={'result': '我认为跑'}\n  [2022-05-06 21:14:04,855] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,864] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,871] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,879] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,887] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,894] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:04,902] [    INFO] - client receive msg={'result': '我认为跑步最重要的'}\n  [2022-05-06 21:14:05,418] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,426] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,434] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,442] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,449] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,457] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,465] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,473] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是'}\n  [2022-05-06 21:14:05,996] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,006] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,013] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,021] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,029] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,037] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,045] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给'}\n  [2022-05-06 21:14:06,581] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,589] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,597] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,605] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,613] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,621] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,628] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:06,636] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了'}\n  [2022-05-06 21:14:07,188] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,196] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,203] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,211] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,219] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:07,226] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康'}\n  [2022-05-06 21:14:12,158] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-06 21:14:12,159] [    INFO] - audio duration: 4.9968125, elapsed time: 9.019973039627075, RTF=1.8051453881103354\n  [2022-05-06 21:14:12,160] [    INFO] - asr websocket client finished\n  ```\n## 标点预测\n\n### 1. 服务端使用方法\n\n- 命令行\n  **注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数部署在 `gpu` 上。\n  ```bash\n  # 在 PaddleSpeech/demos/streaming_asr_server 目录下启动标点预测服务\n  paddlespeech_server start --config_file conf/punc_application.yaml\n  ```\n\n  使用方法:\n  ```bash\n  paddlespeech_server start --help\n  ```\n  \n  参数:\n  - `config_file`: 服务的配置文件。\n  - `log_file`: log 文件。\n\n\n  输出:\n  ```text\n  [2022-05-02 17:59:26,285] [    INFO] - Create the TextEngine Instance\n  [2022-05-02 17:59:26,285] [    INFO] - Init the text engine\n  [2022-05-02 17:59:26,285] [    INFO] - Text Engine set the device: gpu:0\n  [2022-05-02 17:59:26,286] [    INFO] - File /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar.gz md5 checking...\n  [2022-05-02 17:59:30,810] [    INFO] - Use pretrained model stored in: /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar\n  W0502 17:59:31.486552  9595 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 10.2, Runtime API Version: 10.2\n  W0502 17:59:31.491360  9595 device_context.cc:465] device: 0, cuDNN Version: 7.6.\n  [2022-05-02 17:59:34,688] [    INFO] - Already cached /home/users/xiongxinlei/.paddlenlp/models/ernie-1.0/vocab.txt\n  [2022-05-02 17:59:34,701] [    INFO] - Init the text engine successfully\n  INFO:     Started server process [9595]\n  [2022-05-02 17:59:34] [INFO] [server.py:75] Started server process [9595]\n  INFO:     Waiting for application startup.\n  [2022-05-02 17:59:34] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-02 17:59:34] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  [2022-05-02 17:59:34] [INFO] [server.py:206] Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  **注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数部署在 `gpu` 上。\n  ```python\n  # 在 PaddleSpeech/demos/streaming_asr_server 目录\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/punc_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  输出:\n  ```text\n  [2022-05-02 18:09:02,542] [    INFO] - Create the TextEngine Instance\n  [2022-05-02 18:09:02,543] [    INFO] - Init the text engine\n  [2022-05-02 18:09:02,543] [    INFO] - Text Engine set the device: gpu:0\n  [2022-05-02 18:09:02,545] [    INFO] - File /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar.gz md5 checking...\n  [2022-05-02 18:09:06,919] [    INFO] - Use pretrained model stored in: /home/users/xiongxinlei/.paddlespeech/models/ernie_linear_p3_wudao-punc-zh/ernie_linear_p3_wudao-punc-zh.tar\n  W0502 18:09:07.523002 22615 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 10.2, Runtime API Version: 10.2\n  W0502 18:09:07.527882 22615 device_context.cc:465] device: 0, cuDNN Version: 7.6.\n  [2022-05-02 18:09:10,900] [    INFO] - Already cached /home/users/xiongxinlei/.paddlenlp/models/ernie-1.0/vocab.txt\n  [2022-05-02 18:09:10,913] [    INFO] - Init the text engine successfully\n  INFO:     Started server process [22615]\n  [2022-05-02 18:09:10] [INFO] [server.py:75] Started server process [22615]\n  INFO:     Waiting for application startup.\n  [2022-05-02 18:09:10] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-05-02 18:09:10] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  [2022-05-02 18:09:10] [INFO] [server.py:206] Uvicorn running on http://0.0.0.0:8190 (Press CTRL+C to quit)\n  ```\n\n### 2. 标点预测客户端使用方法\n**注意：** 初次使用客户端时响应时间会略长\n\n- 命令行 (推荐使用)\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client text --server_ip 127.0.0.1 --port 8190 --input \"我认为跑步最重要的就是给我带来了身体健康\"\n  ```\n  \n  输出:\n  ```text\n  [2022-05-02 18:12:29,767] [    INFO] - The punc text: 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-02 18:12:29,767] [    INFO] - Response time 0.096548 s.\n  ```\n\n- Python API\n\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TextClientExecutor\n\n  textclient_executor = TextClientExecutor()\n  res = textclient_executor(\n      input=\"我认为跑步最重要的就是给我带来了身体健康\",\n      server_ip=\"127.0.0.1\",\n      port=8190,)\n  print(res)\n  ```\n\n  输出:\n  ```text\n  我认为跑步最重要的就是给我带来了身体健康。\n  ```\n\n## 联合流式语音识别和标点预测\n**注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数将语音识别和标点预测部署在不同的 `gpu` 上。\n\n使用 `streaming_asr_server.py` 和 `punc_server.py` 两个服务，分别启动流式语音识别和标点预测服务。调用 `websocket_client.py` 脚本可以同时调用流式语音识别和标点预测服务。\n\n### 1. 启动服务\n\n```bash\n注意：流式语音识别和标点预测通过配置文件配置到不同的显卡上\nbash server.sh\n```\n\n### 2. 调用服务\n- 使用命令行：\n\n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  paddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --input ./zh.wav\n  ```\n  输出:\n  ```text\n  [2022-05-07 11:21:47,060] [    INFO] - asr websocket client start\n  [2022-05-07 11:21:47,060] [    INFO] - endpoint: ws://127.0.0.1:8490/paddlespeech/asr/streaming\n  [2022-05-07 11:21:47,080] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-07 11:21:47,096] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,108] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,120] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,131] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,142] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,152] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,163] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,173] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,705] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,713] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,721] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,728] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,736] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,743] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:47,751] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:21:48,459] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,572] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,681] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,790] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:48,898] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,005] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,112] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,219] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:21:49,935] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,062] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,186] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,310] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,435] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,560] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:50,686] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:21:51,444] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,606] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,744] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:51,882] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,020] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,159] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,298] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:52,437] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:21:53,298] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,450] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,589] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,728] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:53,867] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:54,007] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:54,146] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:21:55,002] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,148] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,292] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,437] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,584] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,731] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:55,877] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:56,021] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:21:56,842] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,013] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,174] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,336] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,497] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:21:57,659] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:22:03,035] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康。', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-07 11:22:03,035] [    INFO] - audio duration: 4.9968125, elapsed time: 15.974023818969727, RTF=3.1968427510477384\n  [2022-05-07 11:22:03,037] [    INFO] - asr websocket client finished\n  [2022-05-07 11:22:03,037] [    INFO] - 我认为跑步最重要的就是给我带来了身体健康。\n  [2022-05-07 11:22:03,037] [    INFO] - Response time 15.977116 s.\n  ```\n\n- 使用脚本调用\n  \n  若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n  ```bash\n  python3 local/websocket_client.py --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ./zh.wav\n  ```\n  输出:\n  ```text\n  [2022-05-07 11:11:02,984] [    INFO] - Start to do streaming asr client\n  [2022-05-07 11:11:02,985] [    INFO] - asr websocket client start\n  [2022-05-07 11:11:02,985] [    INFO] - endpoint: ws://127.0.0.1:8490/paddlespeech/asr/streaming\n  [2022-05-07 11:11:02,986] [    INFO] - start to process the wavscp: ./zh.wav\n  [2022-05-07 11:11:03,006] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n  [2022-05-07 11:11:03,021] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,034] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,046] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,058] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,070] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,081] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,092] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,102] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,629] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,638] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,645] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,653] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,661] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,668] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:03,676] [    INFO] - client receive msg={'result': ''}\n  [2022-05-07 11:11:04,402] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,510] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,619] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,743] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,849] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:04,956] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,063] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,170] [    INFO] - client receive msg={'result': '我认为，跑'}\n  [2022-05-07 11:11:05,876] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,019] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,184] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,342] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,537] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,727] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:06,871] [    INFO] - client receive msg={'result': '我认为，跑步最重要的。'}\n  [2022-05-07 11:11:07,617] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:07,769] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:07,905] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,043] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,186] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,326] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,466] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:08,611] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是。'}\n  [2022-05-07 11:11:09,431] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,571] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,714] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,853] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:09,992] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:10,129] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:10,266] [    INFO] - client receive msg={'result': '我认为，跑步最重要的就是给。'}\n  [2022-05-07 11:11:11,113] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,296] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,439] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,582] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,727] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:11,869] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,011] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,153] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了。'}\n  [2022-05-07 11:11:12,969] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,137] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,297] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,456] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,615] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:13,776] [    INFO] - client receive msg={'result': '我认为跑步最重要的就是给我带来了身体健康。'}\n  [2022-05-07 11:11:18,915] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '我认为跑步最重要的就是给我带来了身体健康。', 'times': [{'w': '我', 'bg': 0.0, 'ed': 0.7000000000000001}, {'w': '认', 'bg': 0.7000000000000001, 'ed': 0.84}, {'w': '为', 'bg': 0.84, 'ed': 1.0}, {'w': '跑', 'bg': 1.0, 'ed': 1.18}, {'w': '步', 'bg': 1.18, 'ed': 1.36}, {'w': '最', 'bg': 1.36, 'ed': 1.5}, {'w': '重', 'bg': 1.5, 'ed': 1.6400000000000001}, {'w': '要', 'bg': 1.6400000000000001, 'ed': 1.78}, {'w': '的', 'bg': 1.78, 'ed': 1.9000000000000001}, {'w': '就', 'bg': 1.9000000000000001, 'ed': 2.06}, {'w': '是', 'bg': 2.06, 'ed': 2.62}, {'w': '给', 'bg': 2.62, 'ed': 3.16}, {'w': '我', 'bg': 3.16, 'ed': 3.3200000000000003}, {'w': '带', 'bg': 3.3200000000000003, 'ed': 3.48}, {'w': '来', 'bg': 3.48, 'ed': 3.62}, {'w': '了', 'bg': 3.62, 'ed': 3.7600000000000002}, {'w': '身', 'bg': 3.7600000000000002, 'ed': 3.9}, {'w': '体', 'bg': 3.9, 'ed': 4.0600000000000005}, {'w': '健', 'bg': 4.0600000000000005, 'ed': 4.26}, {'w': '康', 'bg': 4.26, 'ed': 4.96}]}\n  [2022-05-07 11:11:18,915] [    INFO] - audio duration: 4.9968125, elapsed time: 15.928460597991943, RTF=3.187724293835709\n  [2022-05-07 11:11:18,916] [    INFO] - asr websocket client finished : 我认为跑步最重要的就是给我带来了身体健康\n  ```\n\n## 从音频文件(.wav 格式 或者.mp3 格式)生成字幕文件 (.srt 格式)\n\n**注意:** 默认部署在 `cpu` 设备上，可以通过修改服务配置文件中 `device` 参数将语音识别和标点预测部署在不同的 `gpu` 上。\n\n使用 `streaming_asr_server.py` 和 `punc_server.py` 两个服务，分别启动流式语音识别和标点预测服务。调用 `websocket_client.py` 脚本可以同时调用流式语音识别和标点预测服务，将会生成对应的字幕文件(.srt格式)。\n\n**使用该脚本前需要安装mffpeg**\n\n**应该在对应的`.../demos/streaming_asr_server/`目录下运行以下脚本**\n\n### 1. 启动服务端\n\n```bash\nNote: streaming speech recognition and punctuation prediction are configured on different graphics cards through configuration files\npaddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application.yaml\n```\n\nOpen another terminal run the following commands:\n```bash\npaddlespeech_server start --config_file conf/punc_application.yaml\n```\n\n### 2. 启动客户端\n\n  ```bash\n  python3 local/websocket_client_srt.py --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ../../data/认知.mp3\n  ```\n  Output:\n  ```text\n  [2023-03-30 23:26:13,991] [    INFO] - Start to do streaming asr client\n[2023-03-30 23:26:13,994] [    INFO] - asr websocket client start\n[2023-03-30 23:26:13,994] [    INFO] - endpoint: http://127.0.0.1:8190/paddlespeech/text\n[2023-03-30 23:26:13,994] [    INFO] - endpoint: ws://127.0.0.1:8090/paddlespeech/asr/streaming\n[2023-03-30 23:26:14,475] [    INFO] - /home/fxb/PaddleSpeech-develop/data/认知.mp3 converted to /home/fxb/PaddleSpeech-develop/data/认知.wav\n[2023-03-30 23:26:14,476] [    INFO] - start to process the wavscp: /home/fxb/PaddleSpeech-develop/data/认知.wav\n[2023-03-30 23:26:14,515] [    INFO] - client receive msg={\"status\": \"ok\", \"signal\": \"server_ready\"}\n[2023-03-30 23:26:14,533] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,545] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,556] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,572] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,588] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,600] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,613] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:14,626] [    INFO] - client receive msg={'result': ''}\n[2023-03-30 23:26:15,122] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,135] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,154] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,163] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,175] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,185] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,196] [    INFO] - client receive msg={'result': '第一部'}\n[2023-03-30 23:26:15,637] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,648] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,657] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,666] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,676] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,683] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,691] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:15,703] [    INFO] - client receive msg={'result': '第一部分是认'}\n[2023-03-30 23:26:16,146] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,159] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,167] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,177] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,187] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,197] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,210] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,694] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,704] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,713] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,725] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,737] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,749] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,759] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:16,770] [    INFO] - client receive msg={'result': '第一部分是认知部分'}\n[2023-03-30 23:26:17,279] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,302] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,316] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,332] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,343] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,358] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通'}\n[2023-03-30 23:26:17,958] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:17,971] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:17,987] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,000] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,017] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,028] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,038] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,049] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图'}\n[2023-03-30 23:26:18,653] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,689] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,701] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,712] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,723] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,750] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:18,767] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本'}\n[2023-03-30 23:26:19,295] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,307] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,323] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,332] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,342] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,349] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:19,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式'}\n[2023-03-30 23:26:20,046] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,055] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,067] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,076] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,124] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,135] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生'}\n[2023-03-30 23:26:20,732] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,742] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,757] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,770] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,782] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,798] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,815] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:20,834] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解'}\n[2023-03-30 23:26:21,390] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,405] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,416] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,428] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,459] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:21,473] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感'}\n[2023-03-30 23:26:22,065] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,085] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,110] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,118] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,137] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,144] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,154] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,169] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作'}\n[2023-03-30 23:26:22,698] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,709] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,731] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,743] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,755] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,771] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:22,782] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理'}\n[2023-03-30 23:26:23,415] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,430] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,442] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,456] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,470] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,487] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,498] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:23,524] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生'}\n[2023-03-30 23:26:24,200] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,210] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,219] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,231] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,250] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,262] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,272] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备'}\n[2023-03-30 23:26:24,898] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,903] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,907] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,932] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,957] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,979] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:24,991] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:25,011] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致'}\n[2023-03-30 23:26:25,616] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,625] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,648] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,658] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,669] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,681] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,690] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:25,707] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,378] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,384] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,402] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,415] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:26,428] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知'}\n[2023-03-30 23:26:27,008] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,018] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,026] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,037] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,046] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,054] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,062] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,070] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使'}\n[2023-03-30 23:26:27,735] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,745] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,755] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,769] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,783] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,794] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:27,804] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传'}\n[2023-03-30 23:26:28,454] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,472] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,481] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,489] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,499] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,533] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,543] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:28,556] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内'}\n[2023-03-30 23:26:29,212] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,222] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,233] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,246] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,258] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,270] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:29,286] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图'}\n[2023-03-30 23:26:30,003] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,013] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,038] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,048] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,062] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,074] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,114] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,125] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅'}\n[2023-03-30 23:26:30,856] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,876] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,885] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,897] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,914] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,940] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:30,952] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说'}\n[2023-03-30 23:26:31,655] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,696] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,709] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,718] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,727] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,740] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,757] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:31,768] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明'}\n[2023-03-30 23:26:32,476] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,486] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,495] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,549] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,560] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,574] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:32,590] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助'}\n[2023-03-30 23:26:33,338] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,356] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,368] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,386] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,409] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,424] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:33,434] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生'}\n[2023-03-30 23:26:34,352] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,364] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,377] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,395] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,410] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,423] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:34,434] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感'}\n[2023-03-30 23:26:35,373] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,397] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,410] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,420] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,437] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,460] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:35,473] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有'}\n[2023-03-30 23:26:36,288] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,297] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,306] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,326] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,336] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,351] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:36,365] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的'}\n[2023-03-30 23:26:37,164] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,173] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,182] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,192] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,204] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,232] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,238] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:37,252] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象'}\n[2023-03-30 23:26:38,084] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,093] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,106] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,122] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,140] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,181] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:38,206] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后'}\n[2023-03-30 23:26:39,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,111] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,132] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,150] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,174] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,190] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,197] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:39,212] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合'}\n[2023-03-30 23:26:40,009] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,094] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,105] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,128] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,149] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,173] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,189] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,200] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实'}\n[2023-03-30 23:26:40,952] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,973] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,986] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:40,999] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,013] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,022] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,033] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用'}\n[2023-03-30 23:26:41,819] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,832] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,845] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,878] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,886] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,893] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,925] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:41,935] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升'}\n[2023-03-30 23:26:42,562] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,589] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,621] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,634] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,644] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,657] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:42,668] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对'}\n[2023-03-30 23:26:43,380] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,436] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,448] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,462] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,472] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,486] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:43,496] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴'}\n[2023-03-30 23:26:44,346] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,356] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,364] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,374] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,389] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,398] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:44,420] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以'}\n[2023-03-30 23:26:45,226] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,235] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,258] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,273] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,295] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:45,306] [    INFO] - client receive msg={'result': '第一部分是认知部分该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理让学生对设备有大致的认知随后使用真实传感器的内部构造图辅以文字说明进一步帮助学生对传感器有更深刻的印象最后结合具体的实践应用提升学生对实训的兴趣以及意义感'}\n[2023-03-30 23:26:46,380] [    INFO] - client punctuation restored msg={'result': '第一部分是认知部分，该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理，让学生对设备有大致的认知。随后使用真实传感器的内部构造图，辅以文字说明，进一步帮助学生对传感器有更深刻的印象，最后结合具体的实践应用，提升学生对实训的兴趣以及意义感。'}\n[2023-03-30 23:27:01,059] [    INFO] - client final receive msg={'status': 'ok', 'signal': 'finished', 'result': '第一部分是认知部分，该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理，让学生对设备有大致的认知。随后使用真实传感器的内部构造图，辅以文字说明，进一步帮助学生对传感器有更深刻的印象，最后结合具体的实践应用，提升学生对实训的兴趣以及意义感。', 'times': [{'w': '第', 'bg': 0.0, 'ed': 0.36}, {'w': '一', 'bg': 0.36, 'ed': 0.48}, {'w': '部', 'bg': 0.48, 'ed': 0.62}, {'w': '分', 'bg': 0.62, 'ed': 0.8200000000000001}, {'w': '是', 'bg': 0.8200000000000001, 'ed': 1.08}, {'w': '认', 'bg': 1.08, 'ed': 1.28}, {'w': '知', 'bg': 1.28, 'ed': 1.44}, {'w': '部', 'bg': 1.44, 'ed': 1.58}, {'w': '分', 'bg': 1.58, 'ed': 2.1}, {'w': '该', 'bg': 2.1, 'ed': 2.6}, {'w': '部', 'bg': 2.6, 'ed': 2.72}, {'w': '分', 'bg': 2.72, 'ed': 2.94}, {'w': '通', 'bg': 2.94, 'ed': 3.16}, {'w': '过', 'bg': 3.16, 'ed': 3.36}, {'w': '示', 'bg': 3.36, 'ed': 3.54}, {'w': '意', 'bg': 3.54, 'ed': 3.68}, {'w': '图', 'bg': 3.68, 'ed': 3.9}, {'w': '和', 'bg': 3.9, 'ed': 4.14}, {'w': '文', 'bg': 4.14, 'ed': 4.32}, {'w': '本', 'bg': 4.32, 'ed': 4.46}, {'w': '的', 'bg': 4.46, 'ed': 4.58}, {'w': '形', 'bg': 4.58, 'ed': 4.72}, {'w': '式', 'bg': 4.72, 'ed': 5.0}, {'w': '向', 'bg': 5.0, 'ed': 5.32}, {'w': '学', 'bg': 5.32, 'ed': 5.5}, {'w': '生', 'bg': 5.5, 'ed': 5.66}, {'w': '讲', 'bg': 5.66, 'ed': 5.86}, {'w': '解', 'bg': 5.86, 'ed': 6.18}, {'w': '主', 'bg': 6.18, 'ed': 6.46}, {'w': '要', 'bg': 6.46, 'ed': 6.62}, {'w': '传', 'bg': 6.62, 'ed': 6.8}, {'w': '感', 'bg': 6.8, 'ed': 7.0}, {'w': '器', 'bg': 7.0, 'ed': 7.16}, {'w': '的', 'bg': 7.16, 'ed': 7.28}, {'w': '工', 'bg': 7.28, 'ed': 7.44}, {'w': '作', 'bg': 7.44, 'ed': 7.6000000000000005}, {'w': '原', 'bg': 7.6000000000000005, 'ed': 7.74}, {'w': '理', 'bg': 7.74, 'ed': 8.06}, {'w': '让', 'bg': 8.06, 'ed': 8.44}, {'w': '学', 'bg': 8.44, 'ed': 8.64}, {'w': '生', 'bg': 8.64, 'ed': 8.84}, {'w': '对', 'bg': 8.84, 'ed': 9.06}, {'w': '设', 'bg': 9.06, 'ed': 9.24}, {'w': '备', 'bg': 9.24, 'ed': 9.52}, {'w': '有', 'bg': 9.52, 'ed': 9.86}, {'w': '大', 'bg': 9.86, 'ed': 10.1}, {'w': '致', 'bg': 10.1, 'ed': 10.24}, {'w': '的', 'bg': 10.24, 'ed': 10.36}, {'w': '认', 'bg': 10.36, 'ed': 10.5}, {'w': '知', 'bg': 10.5, 'ed': 11.040000000000001}, {'w': '随', 'bg': 11.040000000000001, 'ed': 11.56}, {'w': '后', 'bg': 11.56, 'ed': 11.82}, {'w': '使', 'bg': 11.82, 'ed': 12.1}, {'w': '用', 'bg': 12.1, 'ed': 12.26}, {'w': '真', 'bg': 12.26, 'ed': 12.44}, {'w': '实', 'bg': 12.44, 'ed': 12.620000000000001}, {'w': '传', 'bg': 12.620000000000001, 'ed': 12.780000000000001}, {'w': '感', 'bg': 12.780000000000001, 'ed': 12.94}, {'w': '器', 'bg': 12.94, 'ed': 13.1}, {'w': '的', 'bg': 13.1, 'ed': 13.26}, {'w': '内', 'bg': 13.26, 'ed': 13.42}, {'w': '部', 'bg': 13.42, 'ed': 13.56}, {'w': '构', 'bg': 13.56, 'ed': 13.700000000000001}, {'w': '造', 'bg': 13.700000000000001, 'ed': 13.86}, {'w': '图', 'bg': 13.86, 'ed': 14.280000000000001}, {'w': '辅', 'bg': 14.280000000000001, 'ed': 14.66}, {'w': '以', 'bg': 14.66, 'ed': 14.82}, {'w': '文', 'bg': 14.82, 'ed': 15.0}, {'w': '字', 'bg': 15.0, 'ed': 15.16}, {'w': '说', 'bg': 15.16, 'ed': 15.32}, {'w': '明', 'bg': 15.32, 'ed': 15.72}, {'w': '进', 'bg': 15.72, 'ed': 16.1}, {'w': '一', 'bg': 16.1, 'ed': 16.2}, {'w': '步', 'bg': 16.2, 'ed': 16.32}, {'w': '帮', 'bg': 16.32, 'ed': 16.48}, {'w': '助', 'bg': 16.48, 'ed': 16.66}, {'w': '学', 'bg': 16.66, 'ed': 16.82}, {'w': '生', 'bg': 16.82, 'ed': 17.12}, {'w': '对', 'bg': 17.12, 'ed': 17.48}, {'w': '传', 'bg': 17.48, 'ed': 17.66}, {'w': '感', 'bg': 17.66, 'ed': 17.84}, {'w': '器', 'bg': 17.84, 'ed': 18.12}, {'w': '有', 'bg': 18.12, 'ed': 18.42}, {'w': '更', 'bg': 18.42, 'ed': 18.66}, {'w': '深', 'bg': 18.66, 'ed': 18.88}, {'w': '刻', 'bg': 18.88, 'ed': 19.04}, {'w': '的', 'bg': 19.04, 'ed': 19.16}, {'w': '印', 'bg': 19.16, 'ed': 19.3}, {'w': '象', 'bg': 19.3, 'ed': 19.8}, {'w': '最', 'bg': 19.8, 'ed': 20.3}, {'w': '后', 'bg': 20.3, 'ed': 20.62}, {'w': '结', 'bg': 20.62, 'ed': 20.96}, {'w': '合', 'bg': 20.96, 'ed': 21.14}, {'w': '具', 'bg': 21.14, 'ed': 21.3}, {'w': '体', 'bg': 21.3, 'ed': 21.42}, {'w': '的', 'bg': 21.42, 'ed': 21.580000000000002}, {'w': '实', 'bg': 21.580000000000002, 'ed': 21.76}, {'w': '践', 'bg': 21.76, 'ed': 21.92}, {'w': '应', 'bg': 21.92, 'ed': 22.080000000000002}, {'w': '用', 'bg': 22.080000000000002, 'ed': 22.44}, {'w': '提', 'bg': 22.44, 'ed': 22.78}, {'w': '升', 'bg': 22.78, 'ed': 22.94}, {'w': '学', 'bg': 22.94, 'ed': 23.12}, {'w': '生', 'bg': 23.12, 'ed': 23.34}, {'w': '对', 'bg': 23.34, 'ed': 23.62}, {'w': '实', 'bg': 23.62, 'ed': 23.82}, {'w': '训', 'bg': 23.82, 'ed': 23.96}, {'w': '的', 'bg': 23.96, 'ed': 24.12}, {'w': '兴', 'bg': 24.12, 'ed': 24.3}, {'w': '趣', 'bg': 24.3, 'ed': 24.6}, {'w': '以', 'bg': 24.6, 'ed': 24.88}, {'w': '及', 'bg': 24.88, 'ed': 25.12}, {'w': '意', 'bg': 25.12, 'ed': 25.34}, {'w': '义', 'bg': 25.34, 'ed': 25.46}, {'w': '感', 'bg': 25.46, 'ed': 26.04}]}\n[2023-03-30 23:27:01,060] [    INFO] - audio duration: 26.04, elapsed time: 46.581613540649414, RTF=1.7888484462614982\nsentences:  ['第一部分是认知部分', '该部分通过示意图和文本的形式向学生讲解主要传感器的工作原理', '让学生对设备有大致的认知', '随后使用真实传感器的内部构造图', '辅以文字说明', '进一步帮助学生对传感器有更深刻的印象', '最后结合具体的实践应用', '提升学生对实训的兴趣以及意义感']\nrelative_times:  [[0.0, 2.1], [2.1, 8.06], [8.06, 11.040000000000001], [11.040000000000001, 14.280000000000001], [14.280000000000001, 15.72], [15.72, 19.8], [19.8, 22.44], [22.44, 26.04]]\n[2023-03-30 23:27:01,076] [    INFO] - results saved to /home/fxb/PaddleSpeech-develop/data/认知.srt\n  ```\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_u2pp_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: -1\n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/punc_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8190\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_python']\n# protocol = ['http'] (only one can be selected). \n# http only support offline engine type.\nprotocol: 'http'\nengine_list: ['text_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### Text #########################################\n################### text task: punc; engine_type: python #######################\ntext_python:\n    task: punc\n    model_type: 'ernie_linear_p3_wudao'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    vocab_file: # [optional]\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n\n\n\n\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/ws_conformer_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8091\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_multicn'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: -1\n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/ws_conformer_talcs_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_talcs'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    codeswitch: True\n    lang: 'zh_en'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: -1\n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/ws_conformer_wenetspeech_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n    num_decoding_left_chunks: -1\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/ws_conformer_wenetspeech_application_faster.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n    num_decoding_left_chunks: 16\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "demos/streaming_asr_server/conf/ws_ds2_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online-inference', 'asr_online-onnx']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online-onnx #######################\nasr_online-onnx:\n    model_type: 'deepspeech2online_wenetspeech'\n    am_model:  # the pdmodel file of onnx am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n\n    # https://onnxruntime.ai/docs/api/python/api_summary.html#inferencesession\n    am_predictor_conf:\n        device: 'cpu' # set 'gpu:id' or 'cpu'\n        graph_optimization_level: 0 \n        intra_op_num_threads: 0 # Sets the number of threads used to parallelize the execution within nodes.\n        inter_op_num_threads: 0 # Sets the number of threads used to parallelize the execution of the graph (across nodes).\n        log_severity_level: 2   # Log severity level. Applies to session load, initialization, etc. 0:Verbose, 1:Info, 2:Warning. 3:Error, 4:Fatal. Default is 2.\n        log_verbosity_level: 0  # VLOG level if DEBUG build and session_log_severity_level is 0. Applies to session load, initialization, etc. Default is 0.\n\n    chunk_buffer_conf:\n        frame_duration_ms: 85\n        shift_ms: 40\n        sample_rate: 16000\n        sample_width: 2\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online-inference #######################\nasr_online-inference:\n    model_type: 'deepspeech2online_wenetspeech'\n    am_model:    # the pdmodel file of am static model [optional]\n    am_params:   # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        frame_duration_ms: 85\n        shift_ms: 40\n        sample_rate: 16000\n        sample_width: 2\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms"
  },
  {
    "path": "demos/streaming_asr_server/local/punc_server.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.bin.paddlespeech_server import ServerExecutor\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        prog='paddlespeech_server.start', add_help=True)\n    parser.add_argument(\n        \"--config_file\",\n        action=\"store\",\n        help=\"yaml file of the app\",\n        default=None,\n        required=True)\n\n    parser.add_argument(\n        \"--log_file\",\n        action=\"store\",\n        help=\"log file\",\n        default=\"./log/paddlespeech.log\")\n    logger.info(\"start to parse the args\")\n    args = parser.parse_args()\n\n    logger.info(\"start to launch the punctuation server\")\n    punc_server = ServerExecutor()\n    punc_server(config_file=args.config_file, log_file=args.log_file)\n"
  },
  {
    "path": "demos/streaming_asr_server/local/rtf_from_log.py",
    "content": "#!/usr/bin/env python3\nimport argparse\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(prog=__doc__)\n    parser.add_argument(\n        '--logfile', type=str, required=True, help='ws client log file')\n\n    args = parser.parse_args()\n\n    rtfs = []\n    with open(args.logfile, 'r') as f:\n        for line in f:\n            if 'RTF=' in line:\n                # udio duration: 6.126, elapsed time: 3.471978187561035, RTF=0.5667610492264177\n                line = line.strip()\n                beg = line.index(\"audio\")\n                line = line[beg:]\n\n                items = line.split(',')\n                vals = []\n                for elem in items:\n                    if \"RTF=\" in elem:\n                        continue\n                    _, val = elem.split(\":\")\n                    vals.append(eval(val))\n                keys = ['T', 'P']\n                meta = dict(zip(keys, vals))\n\n                rtfs.append(meta)\n\n    T = 0.0\n    P = 0.0\n    n = 0\n    for m in rtfs:\n        # not accurate, may have duplicate log\n        n += 1\n        T += m['T']\n        P += m['P']\n\n    print(f\"RTF: {P/T}, utts: {n}\")\n"
  },
  {
    "path": "demos/streaming_asr_server/local/streaming_asr_server.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.bin.paddlespeech_server import ServerExecutor\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        prog='paddlespeech_server.start', add_help=True)\n    parser.add_argument(\n        \"--config_file\",\n        action=\"store\",\n        help=\"yaml file of the app\",\n        default=None,\n        required=True)\n\n    parser.add_argument(\n        \"--log_file\",\n        action=\"store\",\n        help=\"log file\",\n        default=\"./log/paddlespeech.log\")\n    logger.info(\"start to parse the args\")\n    args = parser.parse_args()\n\n    logger.info(\"start to launch the streaming asr server\")\n    streaming_asr_server = ServerExecutor()\n    streaming_asr_server(config_file=args.config_file, log_file=args.log_file)\n"
  },
  {
    "path": "demos/streaming_asr_server/local/test.sh",
    "content": "#!/bin/bash \n\nif [ $# != 1 ];then\n    echo \"usage: $0 wav_scp\"\n    exit -1\nfi\n\nscp=$1\n\n# calc RTF\n# wav_scp can generate from `speechx/examples/ds2_ol/aishell`\n\nexp=exp\nmkdir -p $exp\n\npython3 local/websocket_client.py --server_ip 127.0.0.1 --port 8090 --wavscp $scp &> $exp/log.rsl\n\npython3 local/rtf_from_log.py --logfile $exp/log.rsl\n\n\n "
  },
  {
    "path": "demos/streaming_asr_server/local/websocket_client.py",
    "content": "#!/usr/bin/python\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# calc avg RTF(NOT Accurate): grep -rn RTF log.txt | awk '{print $NF}' | awk -F \"=\" '{sum += $NF} END {print \"all time\",sum, \"audio num\", NR,  \"RTF\", sum/NR}'\n# python3 websocket_client.py --server_ip 127.0.0.1 --port 8290 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ./zh.wav\n# python3 websocket_client.py --server_ip 127.0.0.1 --port 8290 --wavfile ./zh.wav\nimport argparse\nimport asyncio\nimport codecs\nimport os\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.utils.audio_handler import ASRWsAudioHandler\n\n\ndef main(args):\n    logger.info(\"asr websocket client start\")\n    handler = ASRWsAudioHandler(\n        args.server_ip,\n        args.port,\n        endpoint=args.endpoint,\n        punc_server_ip=args.punc_server_ip,\n        punc_server_port=args.punc_server_port)\n    loop = asyncio.get_event_loop()\n\n    # support to process single audio file\n    if args.wavfile and os.path.exists(args.wavfile):\n        logger.info(f\"start to process the wavscp: {args.wavfile}\")\n        result = loop.run_until_complete(handler.run(args.wavfile))\n        result = result[\"result\"]\n        logger.info(f\"asr websocket client finished : {result}\")\n\n    # support to process batch audios from wav.scp\n    if args.wavscp and os.path.exists(args.wavscp):\n        logger.info(f\"start to process the wavscp: {args.wavscp}\")\n        with codecs.open(args.wavscp, 'r', encoding='utf-8') as f,\\\n             codecs.open(\"result.txt\", 'w', encoding='utf-8') as w:\n            for line in f:\n                utt_name, utt_path = line.strip().split()\n                result = loop.run_until_complete(handler.run(utt_path))\n                result = result[\"result\"]\n                w.write(f\"{utt_name} {result}\\n\")\n\n\nif __name__ == \"__main__\":\n    logger.info(\"Start to do streaming asr client\")\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        '--server_ip', type=str, default='127.0.0.1', help='server ip')\n    parser.add_argument('--port', type=int, default=8090, help='server port')\n    parser.add_argument(\n        '--punc.server_ip',\n        type=str,\n        default=None,\n        dest=\"punc_server_ip\",\n        help='Punctuation server ip')\n    parser.add_argument(\n        '--punc.port',\n        type=int,\n        default=8091,\n        dest=\"punc_server_port\",\n        help='Punctuation server port')\n    parser.add_argument(\n        \"--endpoint\",\n        type=str,\n        default=\"/paddlespeech/asr/streaming\",\n        help=\"ASR websocket endpoint\")\n    parser.add_argument(\n        \"--wavfile\",\n        action=\"store\",\n        help=\"wav file path \",\n        default=\"./16_audio.wav\")\n    parser.add_argument(\n        \"--wavscp\", type=str, default=None, help=\"The batch audios dict text\")\n    args = parser.parse_args()\n\n    main(args)\n"
  },
  {
    "path": "demos/streaming_asr_server/local/websocket_client_srt.py",
    "content": "#!/usr/bin/python\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# calc avg RTF(NOT Accurate): grep -rn RTF log.txt | awk '{print $NF}' | awk -F \"=\" '{sum += $NF} END {print \"all time\",sum, \"audio num\", NR,  \"RTF\", sum/NR}'\n# python3 websocket_client.py --server_ip 127.0.0.1 --port 8290 --punc.server_ip 127.0.0.1 --punc.port 8190 --wavfile ./zh.wav\n# python3 websocket_client.py --server_ip 127.0.0.1 --port 8290 --wavfile ./zh.wav\nimport argparse\nimport asyncio\nimport codecs\nimport os\nfrom pydub import AudioSegment\nimport re\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.utils.audio_handler import ASRWsAudioHandler\n\ndef convert_to_wav(input_file):\n    # Load audio file\n    audio = AudioSegment.from_file(input_file)\n\n    # Set parameters for audio file\n    audio = audio.set_channels(1)\n    audio = audio.set_frame_rate(16000)\n\n    # Create output filename\n    output_file = os.path.splitext(input_file)[0] + \".wav\"\n\n    # Export audio file as WAV\n    audio.export(output_file, format=\"wav\")\n\n    logger.info(f\"{input_file} converted to {output_file}\")\n\ndef format_time(sec):\n    # Convert seconds to SRT format (HH:MM:SS,ms)\n    hours = int(sec/3600)\n    minutes = int((sec%3600)/60)\n    seconds = int(sec%60)\n    milliseconds = int((sec%1)*1000)\n    return f'{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d}'\n\ndef results2srt(results, srt_file):\n    \"\"\"convert results from paddlespeech to srt format for subtitle\n    Args:\n        results (dict): results from paddlespeech\n    \"\"\"\n    # times contains start and end time of each word\n    times = results['times']\n    # result contains the whole sentence including punctuation\n    result = results['result']\n    # split result into several sencences by '，' and '。'\n    sentences = re.split('，|。', result)[:-1]\n    # print(\"sentences: \", sentences)\n    # generate relative time for each sentence in sentences\n    relative_times = []\n    word_i = 0\n    for sentence in sentences:\n        relative_times.append([])\n        for word in sentence:\n            if relative_times[-1] == []:\n                relative_times[-1].append(times[word_i]['bg'])\n            if len(relative_times[-1]) == 1:\n                relative_times[-1].append(times[word_i]['ed'])\n            else:\n                relative_times[-1][1] = times[word_i]['ed']\n            word_i += 1\n    # print(\"relative_times: \", relative_times)\n    # generate srt file acoording to relative_times and sentences\n    with open(srt_file, 'w') as f:\n        for i in range(len(sentences)):\n            # Write index number\n            f.write(str(i+1)+'\\n')\n            \n            # Write start and end times\n            start = format_time(relative_times[i][0])\n            end = format_time(relative_times[i][1])\n            f.write(start + ' --> ' + end + '\\n')\n            \n            # Write text\n            f.write(sentences[i]+'\\n\\n')\n    logger.info(f\"results saved to {srt_file}\")\n\ndef main(args):\n    logger.info(\"asr websocket client start\")\n    handler = ASRWsAudioHandler(\n        args.server_ip,\n        args.port,\n        endpoint=args.endpoint,\n        punc_server_ip=args.punc_server_ip,\n        punc_server_port=args.punc_server_port)\n    loop = asyncio.get_event_loop()\n\n    # check if the wav file is mp3 format\n    # if so, convert it to wav format using convert_to_wav function\n    if args.wavfile and os.path.exists(args.wavfile):\n        if args.wavfile.endswith(\".mp3\"):\n            convert_to_wav(args.wavfile)\n            args.wavfile = args.wavfile.replace(\".mp3\", \".wav\")\n\n    # support to process single audio file\n    if args.wavfile and os.path.exists(args.wavfile):\n        logger.info(f\"start to process the wavscp: {args.wavfile}\")\n        result = loop.run_until_complete(handler.run(args.wavfile))\n        # result = result[\"result\"]\n        # logger.info(f\"asr websocket client finished : {result}\")\n        results2srt(result, args.wavfile.replace(\".wav\", \".srt\"))\n\n    # support to process batch audios from wav.scp\n    if args.wavscp and os.path.exists(args.wavscp):\n        logger.info(f\"start to process the wavscp: {args.wavscp}\")\n        with codecs.open(args.wavscp, 'r', encoding='utf-8') as f,\\\n             codecs.open(\"result.txt\", 'w', encoding='utf-8') as w:\n            for line in f:\n                utt_name, utt_path = line.strip().split()\n                result = loop.run_until_complete(handler.run(utt_path))\n                result = result[\"result\"]\n                w.write(f\"{utt_name} {result}\\n\")\n\n\nif __name__ == \"__main__\":\n    logger.info(\"Start to do streaming asr client\")\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        '--server_ip', type=str, default='127.0.0.1', help='server ip')\n    parser.add_argument('--port', type=int, default=8090, help='server port')\n    parser.add_argument(\n        '--punc.server_ip',\n        type=str,\n        default=None,\n        dest=\"punc_server_ip\",\n        help='Punctuation server ip')\n    parser.add_argument(\n        '--punc.port',\n        type=int,\n        default=8091,\n        dest=\"punc_server_port\",\n        help='Punctuation server port')\n    parser.add_argument(\n        \"--endpoint\",\n        type=str,\n        default=\"/paddlespeech/asr/streaming\",\n        help=\"ASR websocket endpoint\")\n    parser.add_argument(\n        \"--wavfile\",\n        action=\"store\",\n        help=\"wav file path \",\n        default=\"./16_audio.wav\")\n    parser.add_argument(\n        \"--wavscp\", type=str, default=None, help=\"The batch audios dict text\")\n    args = parser.parse_args()\n\n    main(args)\n"
  },
  {
    "path": "demos/streaming_asr_server/run.sh",
    "content": "# start the streaming asr service\npaddlespeech_server start --config_file ./conf/ws_conformer_application.yaml"
  },
  {
    "path": "demos/streaming_asr_server/server.sh",
    "content": "#export CUDA_VISIBLE_DEVICE=0,1,2,3\n\n# nohup python3 local/punc_server.py --config_file conf/punc_application.yaml > punc.log 2>&1 &\npaddlespeech_server start --config_file conf/punc_application.yaml &> punc.log &\n\n# nohup python3 local/streaming_asr_server.py --config_file conf/ws_conformer_wenetspeech_application.yaml > streaming_asr.log 2>&1 &\npaddlespeech_server start --config_file conf/ws_conformer_wenetspeech_application.yaml &> streaming_asr.log  &\n\n"
  },
  {
    "path": "demos/streaming_asr_server/test.sh",
    "content": "# download the test wav\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav \n\n# read the wav and pass it to only streaming asr service\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --input ./zh.wav\n\n# read the wav and call streaming and punc service\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client asr_online --server_ip 127.0.0.1 --port 8090 --punc.server_ip 127.0.0.1 --punc.port 8190 --input ./zh.wav\n\n"
  },
  {
    "path": "demos/streaming_asr_server/web/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"./favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>飞桨PaddleSpeech</title>\n    <script type=\"module\" crossorigin>\n//assets/index.c0d7cb1a.js\nvar m9=Object.defineProperty,g9=Object.defineProperties;var y9=Object.getOwnPropertyDescriptors;var Xf=Object.getOwnPropertySymbols;var Sk=Object.prototype.hasOwnProperty,kk=Object.prototype.propertyIsEnumerable;var wk=(e,t,n)=>t in e?m9(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Te=(e,t)=>{for(var n in t||(t={}))Sk.call(t,n)&&wk(e,n,t[n]);if(Xf)for(var n of Xf(t))kk.call(t,n)&&wk(e,n,t[n]);return e},Ke=(e,t)=>g9(e,y9(t));var $k=(e,t)=>{var n={};for(var r in e)Sk.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&Xf)for(var r of Xf(e))t.indexOf(r)<0&&kk.call(e,r)&&(n[r]=e[r]);return n};var b9=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var cLe=b9((fa,Sr)=>{const C9=function(){const t=document.createElement(\"link\").relList;if(t&&t.supports&&t.supports(\"modulepreload\"))return;for(const a of document.querySelectorAll('link[rel=\"modulepreload\"]'))r(a);new MutationObserver(a=>{for(const o of a)if(o.type===\"childList\")for(const i of o.addedNodes)i.tagName===\"LINK\"&&i.rel===\"modulepreload\"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerpolicy&&(o.referrerPolicy=a.referrerpolicy),a.crossorigin===\"use-credentials\"?o.credentials=\"include\":a.crossorigin===\"anonymous\"?o.credentials=\"omit\":o.credentials=\"same-origin\",o}function r(a){if(a.ep)return;a.ep=!0;const o=n(a);fetch(a.href,o)}};C9();function H1(e,t){const n=Object.create(null),r=e.split(\",\");for(let a=0;a<r.length;a++)n[r[a]]=!0;return t?a=>!!n[a.toLowerCase()]:a=>!!n[a]}const w9=\"itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly\",S9=H1(w9);function W_(e){return!!e||e===\"\"}function Xe(e){if(pt(e)){const t={};for(let n=0;n<e.length;n++){const r=e[n],a=wt(r)?O9(r):Xe(r);if(a)for(const o in a)t[o]=a[o]}return t}else{if(wt(e))return e;if(zt(e))return e}}const k9=/;(?![^(]*\\))/g,$9=/:(.+)/;function O9(e){const t={};return e.split(k9).forEach(n=>{if(n){const r=n.split($9);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function U(e){let t=\"\";if(wt(e))t=e;else if(pt(e))for(let n=0;n<e.length;n++){const r=U(e[n]);r&&(t+=r+\" \")}else if(zt(e))for(const n in e)e[n]&&(t+=n+\" \");return t.trim()}function Za(e){if(!e)return null;let{class:t,style:n}=e;return t&&!wt(t)&&(e.class=U(t)),n&&(e.style=Xe(n)),e}function P9(e,t){if(e.length!==t.length)return!1;let n=!0;for(let r=0;n&&r<e.length;r++)n=Vu(e[r],t[r]);return n}function Vu(e,t){if(e===t)return!0;let n=Ok(e),r=Ok(t);if(n||r)return n&&r?e.getTime()===t.getTime():!1;if(n=pt(e),r=pt(t),n||r)return n&&r?P9(e,t):!1;if(n=zt(e),r=zt(t),n||r){if(!n||!r)return!1;const a=Object.keys(e).length,o=Object.keys(t).length;if(a!==o)return!1;for(const i in e){const l=e.hasOwnProperty(i),s=t.hasOwnProperty(i);if(l&&!s||!l&&s||!Vu(e[i],t[i]))return!1}}return String(e)===String(t)}function U_(e,t){return e.findIndex(n=>Vu(n,t))}const Me=e=>wt(e)?e:e==null?\"\":pt(e)||zt(e)&&(e.toString===q_||!Ct(e.toString))?JSON.stringify(e,Y_,2):String(e),Y_=(e,t)=>t&&t.__v_isRef?Y_(e,t.value):ku(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,a])=>(n[`${r} =>`]=a,n),{})}:hm(t)?{[`Set(${t.size})`]:[...t.values()]}:zt(t)&&!pt(t)&&!G_(t)?String(t):t,wn={},Su=[],Qt=()=>{},T9=()=>!1,x9=/^on[^a-z]/,fm=e=>x9.test(e),j1=e=>e.startsWith(\"onUpdate:\"),fr=Object.assign,K1=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},_9=Object.prototype.hasOwnProperty,Mt=(e,t)=>_9.call(e,t),pt=Array.isArray,ku=e=>bf(e)===\"[object Map]\",hm=e=>bf(e)===\"[object Set]\",Ok=e=>e instanceof Date,Ct=e=>typeof e==\"function\",wt=e=>typeof e==\"string\",W1=e=>typeof e==\"symbol\",zt=e=>e!==null&&typeof e==\"object\",hs=e=>zt(e)&&Ct(e.then)&&Ct(e.catch),q_=Object.prototype.toString,bf=e=>q_.call(e),np=e=>bf(e).slice(8,-1),G_=e=>bf(e)===\"[object Object]\",U1=e=>wt(e)&&e!==\"NaN\"&&e[0]!==\"-\"&&\"\"+parseInt(e,10)===e,rp=H1(\",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"),pm=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},E9=/-(\\w)/g,_a=pm(e=>e.replace(E9,(t,n)=>n?n.toUpperCase():\"\")),M9=/\\B([A-Z])/g,vl=pm(e=>e.replace(M9,\"-$1\").toLowerCase()),ia=pm(e=>e.charAt(0).toUpperCase()+e.slice(1)),ap=pm(e=>e?`on${ia(e)}`:\"\"),Md=(e,t)=>!Object.is(e,t),op=(e,t)=>{for(let n=0;n<e.length;n++)e[n](t)},rv=(e,t,n)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},av=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let Pk;const I9=()=>Pk||(Pk=typeof globalThis!=\"undefined\"?globalThis:typeof self!=\"undefined\"?self:typeof window!=\"undefined\"?window:typeof global!=\"undefined\"?global:{});let ta;class X_{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&ta&&(this.parent=ta,this.index=(ta.scopes||(ta.scopes=[])).push(this)-1)}run(t){if(this.active){const n=ta;try{return ta=this,t()}finally{ta=n}}}on(){ta=this}off(){ta=this.parent}stop(t){if(this.active){let n,r;for(n=0,r=this.effects.length;n<r;n++)this.effects[n].stop();for(n=0,r=this.cleanups.length;n<r;n++)this.cleanups[n]();if(this.scopes)for(n=0,r=this.scopes.length;n<r;n++)this.scopes[n].stop(!0);if(this.parent&&!t){const a=this.parent.scopes.pop();a&&a!==this&&(this.parent.scopes[this.index]=a,a.index=this.index)}this.active=!1}}}function N9(e){return new X_(e)}function A9(e,t=ta){t&&t.active&&t.effects.push(e)}function D9(){return ta}function Z_(e){ta&&ta.cleanups.push(e)}const Y1=e=>{const t=new Set(e);return t.w=0,t.n=0,t},J_=e=>(e.w&il)>0,Q_=e=>(e.n&il)>0,R9=({deps:e})=>{if(e.length)for(let t=0;t<e.length;t++)e[t].w|=il},L9=e=>{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r<t.length;r++){const a=t[r];J_(a)&&!Q_(a)?a.delete(e):t[n++]=a,a.w&=~il,a.n&=~il}t.length=n}},Fb=new WeakMap;let Qc=0,il=1;const Bb=30;let To;const es=Symbol(\"\"),Vb=Symbol(\"\");class q1{constructor(t,n=null,r){this.fn=t,this.scheduler=n,this.active=!0,this.deps=[],this.parent=void 0,A9(this,r)}run(){if(!this.active)return this.fn();let t=To,n=Ji;for(;t;){if(t===this)return;t=t.parent}try{return this.parent=To,To=this,Ji=!0,il=1<<++Qc,Qc<=Bb?R9(this):Tk(this),this.fn()}finally{Qc<=Bb&&L9(this),il=1<<--Qc,To=this.parent,Ji=n,this.parent=void 0}}stop(){this.active&&(Tk(this),this.onStop&&this.onStop(),this.active=!1)}}function Tk(e){const{deps:t}=e;if(t.length){for(let n=0;n<t.length;n++)t[n].delete(e);t.length=0}}let Ji=!0;const e6=[];function $s(){e6.push(Ji),Ji=!1}function Os(){const e=e6.pop();Ji=e===void 0?!0:e}function ha(e,t,n){if(Ji&&To){let r=Fb.get(e);r||Fb.set(e,r=new Map);let a=r.get(n);a||r.set(n,a=Y1()),t6(a)}}function t6(e,t){let n=!1;Qc<=Bb?Q_(e)||(e.n|=il,n=!J_(e)):n=!e.has(To),n&&(e.add(To),To.deps.push(e))}function mi(e,t,n,r,a,o){const i=Fb.get(e);if(!i)return;let l=[];if(t===\"clear\")l=[...i.values()];else if(n===\"length\"&&pt(e))i.forEach((s,c)=>{(c===\"length\"||c>=r)&&l.push(s)});else switch(n!==void 0&&l.push(i.get(n)),t){case\"add\":pt(e)?U1(n)&&l.push(i.get(\"length\")):(l.push(i.get(es)),ku(e)&&l.push(i.get(Vb)));break;case\"delete\":pt(e)||(l.push(i.get(es)),ku(e)&&l.push(i.get(Vb)));break;case\"set\":ku(e)&&l.push(i.get(es));break}if(l.length===1)l[0]&&zb(l[0]);else{const s=[];for(const c of l)c&&s.push(...c);zb(Y1(s))}}function zb(e,t){for(const n of pt(e)?e:[...e])(n!==To||n.allowRecurse)&&(n.scheduler?n.scheduler():n.run())}const F9=H1(\"__proto__,__v_isRef,__isVue\"),n6=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(W1)),B9=G1(),V9=G1(!1,!0),z9=G1(!0),xk=H9();function H9(){const e={};return[\"includes\",\"indexOf\",\"lastIndexOf\"].forEach(t=>{e[t]=function(...n){const r=Gt(this);for(let o=0,i=this.length;o<i;o++)ha(r,\"get\",o+\"\");const a=r[t](...n);return a===-1||a===!1?r[t](...n.map(Gt)):a}}),[\"push\",\"pop\",\"shift\",\"unshift\",\"splice\"].forEach(t=>{e[t]=function(...n){$s();const r=Gt(this)[t].apply(this,n);return Os(),r}}),e}function G1(e=!1,t=!1){return function(r,a,o){if(a===\"__v_isReactive\")return!e;if(a===\"__v_isReadonly\")return e;if(a===\"__v_isShallow\")return t;if(a===\"__v_raw\"&&o===(e?t?aL:l6:t?i6:o6).get(r))return r;const i=pt(r);if(!e&&i&&Mt(xk,a))return Reflect.get(xk,a,o);const l=Reflect.get(r,a,o);return(W1(a)?n6.has(a):F9(a))||(e||ha(r,\"get\",a),t)?l:_n(l)?!i||!U1(a)?l.value:l:zt(l)?e?Cf(l):bt(l):l}}const j9=r6(),K9=r6(!0);function r6(e=!1){return function(n,r,a,o){let i=n[r];if(Id(i)&&_n(i)&&!_n(a))return!1;if(!e&&!Id(a)&&(s6(a)||(a=Gt(a),i=Gt(i)),!pt(n)&&_n(i)&&!_n(a)))return i.value=a,!0;const l=pt(n)&&U1(r)?Number(r)<n.length:Mt(n,r),s=Reflect.set(n,r,a,o);return n===Gt(o)&&(l?Md(a,i)&&mi(n,\"set\",r,a):mi(n,\"add\",r,a)),s}}function W9(e,t){const n=Mt(e,t);e[t];const r=Reflect.deleteProperty(e,t);return r&&n&&mi(e,\"delete\",t,void 0),r}function U9(e,t){const n=Reflect.has(e,t);return(!W1(t)||!n6.has(t))&&ha(e,\"has\",t),n}function Y9(e){return ha(e,\"iterate\",pt(e)?\"length\":es),Reflect.ownKeys(e)}const a6={get:B9,set:j9,deleteProperty:W9,has:U9,ownKeys:Y9},q9={get:z9,set(e,t){return!0},deleteProperty(e,t){return!0}},G9=fr({},a6,{get:V9,set:K9}),X1=e=>e,vm=e=>Reflect.getPrototypeOf(e);function Zf(e,t,n=!1,r=!1){e=e.__v_raw;const a=Gt(e),o=Gt(t);t!==o&&!n&&ha(a,\"get\",t),!n&&ha(a,\"get\",o);const{has:i}=vm(a),l=r?X1:n?Q1:Nd;if(i.call(a,t))return l(e.get(t));if(i.call(a,o))return l(e.get(o));e!==a&&e.get(t)}function Jf(e,t=!1){const n=this.__v_raw,r=Gt(n),a=Gt(e);return e!==a&&!t&&ha(r,\"has\",e),!t&&ha(r,\"has\",a),e===a?n.has(e):n.has(e)||n.has(a)}function Qf(e,t=!1){return e=e.__v_raw,!t&&ha(Gt(e),\"iterate\",es),Reflect.get(e,\"size\",e)}function _k(e){e=Gt(e);const t=Gt(this);return vm(t).has.call(t,e)||(t.add(e),mi(t,\"add\",e,e)),this}function Ek(e,t){t=Gt(t);const n=Gt(this),{has:r,get:a}=vm(n);let o=r.call(n,e);o||(e=Gt(e),o=r.call(n,e));const i=a.call(n,e);return n.set(e,t),o?Md(t,i)&&mi(n,\"set\",e,t):mi(n,\"add\",e,t),this}function Mk(e){const t=Gt(this),{has:n,get:r}=vm(t);let a=n.call(t,e);a||(e=Gt(e),a=n.call(t,e)),r&&r.call(t,e);const o=t.delete(e);return a&&mi(t,\"delete\",e,void 0),o}function Ik(){const e=Gt(this),t=e.size!==0,n=e.clear();return t&&mi(e,\"clear\",void 0,void 0),n}function eh(e,t){return function(r,a){const o=this,i=o.__v_raw,l=Gt(i),s=t?X1:e?Q1:Nd;return!e&&ha(l,\"iterate\",es),i.forEach((c,d)=>r.call(a,s(c),s(d),o))}}function th(e,t,n){return function(...r){const a=this.__v_raw,o=Gt(a),i=ku(o),l=e===\"entries\"||e===Symbol.iterator&&i,s=e===\"keys\"&&i,c=a[e](...r),d=n?X1:t?Q1:Nd;return!t&&ha(o,\"iterate\",s?Vb:es),{next(){const{value:f,done:p}=c.next();return p?{value:f,done:p}:{value:l?[d(f[0]),d(f[1])]:d(f),done:p}},[Symbol.iterator](){return this}}}}function Ai(e){return function(...t){return e===\"delete\"?!1:this}}function X9(){const e={get(o){return Zf(this,o)},get size(){return Qf(this)},has:Jf,add:_k,set:Ek,delete:Mk,clear:Ik,forEach:eh(!1,!1)},t={get(o){return Zf(this,o,!1,!0)},get size(){return Qf(this)},has:Jf,add:_k,set:Ek,delete:Mk,clear:Ik,forEach:eh(!1,!0)},n={get(o){return Zf(this,o,!0)},get size(){return Qf(this,!0)},has(o){return Jf.call(this,o,!0)},add:Ai(\"add\"),set:Ai(\"set\"),delete:Ai(\"delete\"),clear:Ai(\"clear\"),forEach:eh(!0,!1)},r={get(o){return Zf(this,o,!0,!0)},get size(){return Qf(this,!0)},has(o){return Jf.call(this,o,!0)},add:Ai(\"add\"),set:Ai(\"set\"),delete:Ai(\"delete\"),clear:Ai(\"clear\"),forEach:eh(!0,!0)};return[\"keys\",\"values\",\"entries\",Symbol.iterator].forEach(o=>{e[o]=th(o,!1,!1),n[o]=th(o,!0,!1),t[o]=th(o,!1,!0),r[o]=th(o,!0,!0)}),[e,n,t,r]}const[Z9,J9,Q9,eL]=X9();function Z1(e,t){const n=t?e?eL:Q9:e?J9:Z9;return(r,a,o)=>a===\"__v_isReactive\"?!e:a===\"__v_isReadonly\"?e:a===\"__v_raw\"?r:Reflect.get(Mt(n,a)&&a in r?n:r,a,o)}const tL={get:Z1(!1,!1)},nL={get:Z1(!1,!0)},rL={get:Z1(!0,!1)},o6=new WeakMap,i6=new WeakMap,l6=new WeakMap,aL=new WeakMap;function oL(e){switch(e){case\"Object\":case\"Array\":return 1;case\"Map\":case\"Set\":case\"WeakMap\":case\"WeakSet\":return 2;default:return 0}}function iL(e){return e.__v_skip||!Object.isExtensible(e)?0:oL(np(e))}function bt(e){return Id(e)?e:J1(e,!1,a6,tL,o6)}function lL(e){return J1(e,!1,G9,nL,i6)}function Cf(e){return J1(e,!0,q9,rL,l6)}function J1(e,t,n,r,a){if(!zt(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=a.get(e);if(o)return o;const i=iL(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return a.set(e,l),l}function $u(e){return Id(e)?$u(e.__v_raw):!!(e&&e.__v_isReactive)}function Id(e){return!!(e&&e.__v_isReadonly)}function s6(e){return!!(e&&e.__v_isShallow)}function u6(e){return $u(e)||Id(e)}function Gt(e){const t=e&&e.__v_raw;return t?Gt(t):e}function ps(e){return rv(e,\"__v_skip\",!0),e}const Nd=e=>zt(e)?bt(e):e,Q1=e=>zt(e)?Cf(e):e;function c6(e){Ji&&To&&(e=Gt(e),t6(e.dep||(e.dep=Y1())))}function eC(e,t){e=Gt(e),e.dep&&zb(e.dep)}function _n(e){return!!(e&&e.__v_isRef===!0)}function H(e){return d6(e,!1)}function Qn(e){return d6(e,!0)}function d6(e,t){return _n(e)?e:new sL(e,t)}class sL{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:Gt(t),this._value=n?t:Nd(t)}get value(){return c6(this),this._value}set value(t){t=this.__v_isShallow?t:Gt(t),Md(t,this._rawValue)&&(this._rawValue=t,this._value=this.__v_isShallow?t:Nd(t),eC(this))}}function Dc(e){eC(e)}function A(e){return _n(e)?e.value:e}const uL={get:(e,t,n)=>A(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const a=e[t];return _n(a)&&!_n(n)?(a.value=n,!0):Reflect.set(e,t,n,r)}};function f6(e){return $u(e)?e:new Proxy(e,uL)}function or(e){const t=pt(e)?new Array(e.length):{};for(const n in e)t[n]=yn(e,n);return t}class cL{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}}function yn(e,t,n){const r=e[t];return _n(r)?r:new cL(e,t,n)}class dL{constructor(t,n,r,a){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this._dirty=!0,this.effect=new q1(t,()=>{this._dirty||(this._dirty=!0,eC(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!a,this.__v_isReadonly=r}get value(){const t=Gt(this);return c6(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function fL(e,t,n=!1){let r,a;const o=Ct(e);return o?(r=e,a=Qt):(r=e.get,a=e.set),new dL(r,a,o||!a,n)}Promise.resolve();const ud=[];function hL(e,...t){$s();const n=ud.length?ud[ud.length-1].component:null,r=n&&n.appContext.config.warnHandler,a=pL();if(r)ci(r,n,11,[e+t.join(\"\"),n&&n.proxy,a.map(({vnode:o})=>`at <${K6(n,o.type)}>`).join(`\n`),a]);else{const o=[`[Vue warn]: ${e}`,...t];a.length&&o.push(`\n`,...vL(a)),console.warn(...o)}Os()}function pL(){let e=ud[ud.length-1];if(!e)return[];const t=[];for(;e;){const n=t[0];n&&n.vnode===e?n.recurseCount++:t.push({vnode:e,recurseCount:0});const r=e.component&&e.component.parent;e=r&&r.vnode}return t}function vL(e){const t=[];return e.forEach((n,r)=>{t.push(...r===0?[]:[`\n`],...mL(n))}),t}function mL({vnode:e,recurseCount:t}){const n=t>0?`... (${t} recursive calls)`:\"\",r=e.component?e.component.parent==null:!1,a=` at <${K6(e.component,e.type,r)}`,o=\">\"+n;return e.props?[a,...gL(e.props),o]:[a+o]}function gL(e){const t=[],n=Object.keys(e);return n.slice(0,3).forEach(r=>{t.push(...h6(r,e[r]))}),n.length>3&&t.push(\" ...\"),t}function h6(e,t,n){return wt(t)?(t=JSON.stringify(t),n?t:[`${e}=${t}`]):typeof t==\"number\"||typeof t==\"boolean\"||t==null?n?t:[`${e}=${t}`]:_n(t)?(t=h6(e,Gt(t.value),!0),n?t:[`${e}=Ref<`,t,\">\"]):Ct(t)?[`${e}=fn${t.name?`<${t.name}>`:\"\"}`]:(t=Gt(t),n?t:[`${e}=`,t])}function ci(e,t,n,r){let a;try{a=r?e(...r):e()}catch(o){mm(o,t,n)}return a}function Pa(e,t,n,r){if(Ct(e)){const o=ci(e,t,n,r);return o&&hs(o)&&o.catch(i=>{mm(i,t,n)}),o}const a=[];for(let o=0;o<e.length;o++)a.push(Pa(e[o],t,n,r));return a}function mm(e,t,n,r=!0){const a=t?t.vnode:null;if(t){let o=t.parent;const i=t.proxy,l=n;for(;o;){const c=o.ec;if(c){for(let d=0;d<c.length;d++)if(c[d](e,i,l)===!1)return}o=o.parent}const s=t.appContext.config.errorHandler;if(s){ci(s,null,10,[e,i,l]);return}}yL(e,n,a,r)}function yL(e,t,n,r=!0){console.error(e)}let ov=!1,Hb=!1;const la=[];let ri=0;const cd=[];let ed=null,au=0;const dd=[];let Bi=null,ou=0;const p6=Promise.resolve();let tC=null,jb=null;function Ne(e){const t=tC||p6;return e?t.then(this?e.bind(this):e):t}function bL(e){let t=ri+1,n=la.length;for(;t<n;){const r=t+n>>>1;Ad(la[r])<e?t=r+1:n=r}return t}function v6(e){(!la.length||!la.includes(e,ov&&e.allowRecurse?ri+1:ri))&&e!==jb&&(e.id==null?la.push(e):la.splice(bL(e.id),0,e),m6())}function m6(){!ov&&!Hb&&(Hb=!0,tC=p6.then(b6))}function CL(e){const t=la.indexOf(e);t>ri&&la.splice(t,1)}function g6(e,t,n,r){pt(e)?n.push(...e):(!t||!t.includes(e,e.allowRecurse?r+1:r))&&n.push(e),m6()}function wL(e){g6(e,ed,cd,au)}function SL(e){g6(e,Bi,dd,ou)}function nC(e,t=null){if(cd.length){for(jb=t,ed=[...new Set(cd)],cd.length=0,au=0;au<ed.length;au++)ed[au]();ed=null,au=0,jb=null,nC(e,t)}}function y6(e){if(dd.length){const t=[...new Set(dd)];if(dd.length=0,Bi){Bi.push(...t);return}for(Bi=t,Bi.sort((n,r)=>Ad(n)-Ad(r)),ou=0;ou<Bi.length;ou++)Bi[ou]();Bi=null,ou=0}}const Ad=e=>e.id==null?1/0:e.id;function b6(e){Hb=!1,ov=!0,nC(e),la.sort((n,r)=>Ad(n)-Ad(r));const t=Qt;try{for(ri=0;ri<la.length;ri++){const n=la[ri];n&&n.active!==!1&&ci(n,null,14)}}finally{ri=0,la.length=0,y6(),ov=!1,tC=null,(la.length||cd.length||dd.length)&&b6(e)}}function kL(e,t,...n){const r=e.vnode.props||wn;let a=n;const o=t.startsWith(\"update:\"),i=o&&t.slice(7);if(i&&i in r){const d=`${i===\"modelValue\"?\"model\":i}Modifiers`,{number:f,trim:p}=r[d]||wn;p?a=n.map(v=>v.trim()):f&&(a=n.map(av))}let l,s=r[l=ap(t)]||r[l=ap(_a(t))];!s&&o&&(s=r[l=ap(vl(t))]),s&&Pa(s,e,6,a);const c=r[l+\"Once\"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Pa(c,e,6,a)}}function C6(e,t,n=!1){const r=t.emitsCache,a=r.get(e);if(a!==void 0)return a;const o=e.emits;let i={},l=!1;if(!Ct(e)){const s=c=>{const d=C6(c,t,!0);d&&(l=!0,fr(i,d))};!n&&t.mixins.length&&t.mixins.forEach(s),e.extends&&s(e.extends),e.mixins&&e.mixins.forEach(s)}return!o&&!l?(r.set(e,null),null):(pt(o)?o.forEach(s=>i[s]=null):fr(i,o),r.set(e,i),i)}function gm(e,t){return!e||!fm(t)?!1:(t=t.slice(2).replace(/Once$/,\"\"),Mt(e,t[0].toLowerCase()+t.slice(1))||Mt(e,vl(t))||Mt(e,t))}let ua=null,ym=null;function iv(e){const t=ua;return ua=e,ym=e&&e.type.__scopeId||null,t}function rC(e){ym=e}function aC(){ym=null}function re(e,t=ua,n){if(!t||e._n)return e;const r=(...a)=>{r._d&&Kk(-1);const o=iv(t),i=e(...a);return iv(o),r._d&&Kk(1),i};return r._n=!0,r._c=!0,r._d=!0,r}function Ug(e){const{type:t,vnode:n,proxy:r,withProxy:a,props:o,propsOptions:[i],slots:l,attrs:s,emit:c,render:d,renderCache:f,data:p,setupState:v,ctx:m,inheritAttrs:y}=e;let b,C;const S=iv(e);try{if(n.shapeFlag&4){const k=a||r;b=ko(d.call(k,k,f,o,v,p,m)),C=s}else{const k=t;b=ko(k.length>1?k(o,{attrs:s,slots:l,emit:c}):k(o,null)),C=t.props?s:$L(s)}}catch(k){hd.length=0,mm(k,e,1),b=g(Ir)}let w=b;if(C&&y!==!1){const k=Object.keys(C),{shapeFlag:$}=w;k.length&&$&7&&(i&&k.some(j1)&&(C=OL(C,i)),w=hr(w,C))}return n.dirs&&(w.dirs=w.dirs?w.dirs.concat(n.dirs):n.dirs),n.transition&&(w.transition=n.transition),b=w,iv(S),b}const $L=e=>{let t;for(const n in e)(n===\"class\"||n===\"style\"||fm(n))&&((t||(t={}))[n]=e[n]);return t},OL=(e,t)=>{const n={};for(const r in e)(!j1(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function PL(e,t,n){const{props:r,children:a,component:o}=e,{props:i,children:l,patchFlag:s}=t,c=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&s>=0){if(s&1024)return!0;if(s&16)return r?Nk(r,i,c):!!i;if(s&8){const d=t.dynamicProps;for(let f=0;f<d.length;f++){const p=d[f];if(i[p]!==r[p]&&!gm(c,p))return!0}}}else return(a||l)&&(!l||!l.$stable)?!0:r===i?!1:r?i?Nk(r,i,c):!0:!!i;return!1}function Nk(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let a=0;a<r.length;a++){const o=r[a];if(t[o]!==e[o]&&!gm(n,o))return!0}return!1}function TL({vnode:e,parent:t},n){for(;t&&t.subTree===e;)(e=t.vnode).el=n,t=t.parent}const xL=e=>e.__isSuspense;function _L(e,t){t&&t.pendingBranch?pt(e)?t.effects.push(...e):t.effects.push(e):SL(e)}function ot(e,t){if(dr){let n=dr.provides;const r=dr.parent&&dr.parent.provides;r===n&&(n=dr.provides=Object.create(r)),n[e]=t}}function ve(e,t,n=!1){const r=dr||ua;if(r){const a=r.parent==null?r.vnode.appContext&&r.vnode.appContext.provides:r.parent.provides;if(a&&e in a)return a[e];if(arguments.length>1)return n&&Ct(t)?t.call(r.proxy):t}}function Wn(e,t){return oC(e,null,t)}const Ak={};function ce(e,t,n){return oC(e,t,n)}function oC(e,t,{immediate:n,deep:r,flush:a,onTrack:o,onTrigger:i}=wn){const l=dr;let s,c=!1,d=!1;if(_n(e)?(s=()=>e.value,c=s6(e)):$u(e)?(s=()=>e,r=!0):pt(e)?(d=!0,c=e.some($u),s=()=>e.map(C=>{if(_n(C))return C.value;if($u(C))return Wl(C);if(Ct(C))return ci(C,l,2)})):Ct(e)?t?s=()=>ci(e,l,2):s=()=>{if(!(l&&l.isUnmounted))return f&&f(),Pa(e,l,3,[p])}:s=Qt,t&&r){const C=s;s=()=>Wl(C())}let f,p=C=>{f=b.onStop=()=>{ci(C,l,4)}};if(Ld)return p=Qt,t?n&&Pa(t,l,3,[s(),d?[]:void 0,p]):s(),Qt;let v=d?[]:Ak;const m=()=>{if(!!b.active)if(t){const C=b.run();(r||c||(d?C.some((S,w)=>Md(S,v[w])):Md(C,v)))&&(f&&f(),Pa(t,l,3,[C,v===Ak?void 0:v,p]),v=C)}else b.run()};m.allowRecurse=!!t;let y;a===\"sync\"?y=m:a===\"post\"?y=()=>Rr(m,l&&l.suspense):y=()=>{!l||l.isMounted?wL(m):m()};const b=new q1(s,y);return t?n?m():v=b.run():a===\"post\"?Rr(b.run.bind(b),l&&l.suspense):b.run(),()=>{b.stop(),l&&l.scope&&K1(l.scope.effects,b)}}function EL(e,t,n){const r=this.proxy,a=wt(e)?e.includes(\".\")?w6(r,e):()=>r[e]:e.bind(r,r);let o;Ct(t)?o=t:(o=t.handler,n=t);const i=dr;zu(this);const l=oC(a,o.bind(r),n);return i?zu(i):ns(),l}function w6(e,t){const n=t.split(\".\");return()=>{let r=e;for(let a=0;a<n.length&&r;a++)r=r[n[a]];return r}}function Wl(e,t){if(!zt(e)||e.__v_skip||(t=t||new Set,t.has(e)))return e;if(t.add(e),_n(e))Wl(e.value,t);else if(pt(e))for(let n=0;n<e.length;n++)Wl(e[n],t);else if(hm(e)||ku(e))e.forEach(n=>{Wl(n,t)});else if(G_(e))for(const n in e)Wl(e[n],t);return e}function S6(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return et(()=>{e.isMounted=!0}),Lt(()=>{e.isUnmounting=!0}),e}const ba=[Function,Array],ML={name:\"BaseTransition\",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ba,onEnter:ba,onAfterEnter:ba,onEnterCancelled:ba,onBeforeLeave:ba,onLeave:ba,onAfterLeave:ba,onLeaveCancelled:ba,onBeforeAppear:ba,onAppear:ba,onAfterAppear:ba,onAppearCancelled:ba},setup(e,{slots:t}){const n=$t(),r=S6();let a;return()=>{const o=t.default&&iC(t.default(),!0);if(!o||!o.length)return;const i=Gt(e),{mode:l}=i,s=o[0];if(r.isLeaving)return Yg(s);const c=Dk(s);if(!c)return Yg(s);const d=Dd(c,i,r,n);Rd(c,d);const f=n.subTree,p=f&&Dk(f);let v=!1;const{getTransitionKey:m}=c.type;if(m){const y=m();a===void 0?a=y:y!==a&&(a=y,v=!0)}if(p&&p.type!==Ir&&(!Rl(c,p)||v)){const y=Dd(p,i,r,n);if(Rd(p,y),l===\"out-in\")return r.isLeaving=!0,y.afterLeave=()=>{r.isLeaving=!1,n.update()},Yg(s);l===\"in-out\"&&c.type!==Ir&&(y.delayLeave=(b,C,S)=>{const w=$6(r,p);w[String(p.key)]=p,b._leaveCb=()=>{C(),b._leaveCb=void 0,delete d.delayedLeave},d.delayedLeave=S})}return s}}},k6=ML;function $6(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Dd(e,t,n,r){const{appear:a,mode:o,persisted:i=!1,onBeforeEnter:l,onEnter:s,onAfterEnter:c,onEnterCancelled:d,onBeforeLeave:f,onLeave:p,onAfterLeave:v,onLeaveCancelled:m,onBeforeAppear:y,onAppear:b,onAfterAppear:C,onAppearCancelled:S}=t,w=String(e.key),k=$6(n,e),$=(T,_)=>{T&&Pa(T,r,9,_)},O={mode:o,persisted:i,beforeEnter(T){let _=l;if(!n.isMounted)if(a)_=y||l;else return;T._leaveCb&&T._leaveCb(!0);const I=k[w];I&&Rl(e,I)&&I.el._leaveCb&&I.el._leaveCb(),$(_,[T])},enter(T){let _=s,I=c,L=d;if(!n.isMounted)if(a)_=b||s,I=C||c,L=S||d;else return;let j=!1;const F=T._enterCb=N=>{j||(j=!0,N?$(L,[T]):$(I,[T]),O.delayedLeave&&O.delayedLeave(),T._enterCb=void 0)};_?(_(T,F),_.length<=1&&F()):F()},leave(T,_){const I=String(e.key);if(T._enterCb&&T._enterCb(!0),n.isUnmounting)return _();$(f,[T]);let L=!1;const j=T._leaveCb=F=>{L||(L=!0,_(),F?$(m,[T]):$(v,[T]),T._leaveCb=void 0,k[I]===e&&delete k[I])};k[I]=e,p?(p(T,j),p.length<=1&&j()):j()},clone(T){return Dd(T,t,n,r)}};return O}function Yg(e){if(bm(e))return e=hr(e),e.children=null,e}function Dk(e){return bm(e)?e.children?e.children[0]:void 0:e}function Rd(e,t){e.shapeFlag&6&&e.component?Rd(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function iC(e,t=!1,n){let r=[],a=0;for(let o=0;o<e.length;o++){let i=e[o];const l=n==null?i.key:String(n)+String(i.key!=null?i.key:o);i.type===Fe?(i.patchFlag&128&&a++,r=r.concat(iC(i.children,t,l))):(t||i.type!==Ir)&&r.push(l!=null?hr(i,{key:l}):i)}if(a>1)for(let o=0;o<r.length;o++)r[o].patchFlag=-2;return r}function G(e){return Ct(e)?{setup:e,name:e.name}:e}const Kb=e=>!!e.type.__asyncLoader,bm=e=>e.type.__isKeepAlive;function O6(e,t){T6(e,\"a\",t)}function P6(e,t){T6(e,\"da\",t)}function T6(e,t,n=dr){const r=e.__wdc||(e.__wdc=()=>{let a=n;for(;a;){if(a.isDeactivated)return;a=a.parent}return e()});if(Cm(t,r,n),n){let a=n.parent;for(;a&&a.parent;)bm(a.parent.vnode)&&IL(r,t,n,a),a=a.parent}}function IL(e,t,n,r){const a=Cm(t,e,r,!0);Wr(()=>{K1(r[t],a)},n)}function Cm(e,t,n=dr,r=!1){if(n){const a=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;$s(),zu(n);const l=Pa(t,n,e,i);return ns(),Os(),l});return r?a.unshift(o):a.push(o),o}}const ki=e=>(t,n=dr)=>(!Ld||e===\"sp\")&&Cm(e,t,n),hc=ki(\"bm\"),et=ki(\"m\"),wm=ki(\"bu\"),ur=ki(\"u\"),Lt=ki(\"bum\"),Wr=ki(\"um\"),NL=ki(\"sp\"),AL=ki(\"rtg\"),DL=ki(\"rtc\");function RL(e,t=dr){Cm(\"ec\",e,t)}let Wb=!0;function LL(e){const t=_6(e),n=e.proxy,r=e.ctx;Wb=!1,t.beforeCreate&&Rk(t.beforeCreate,e,\"bc\");const{data:a,computed:o,methods:i,watch:l,provide:s,inject:c,created:d,beforeMount:f,mounted:p,beforeUpdate:v,updated:m,activated:y,deactivated:b,beforeDestroy:C,beforeUnmount:S,destroyed:w,unmounted:k,render:$,renderTracked:O,renderTriggered:T,errorCaptured:_,serverPrefetch:I,expose:L,inheritAttrs:j,components:F,directives:N,filters:D}=t;if(c&&FL(c,r,null,e.appContext.config.unwrapInjectedRef),i)for(const M in i){const E=i[M];Ct(E)&&(r[M]=E.bind(n))}if(a){const M=a.call(n,n);zt(M)&&(e.data=bt(M))}if(Wb=!0,o)for(const M in o){const E=o[M],K=Ct(E)?E.bind(n,n):Ct(E.get)?E.get.bind(n,n):Qt,W=!Ct(E)&&Ct(E.set)?E.set.bind(n):Qt,Y=x({get:K,set:W});Object.defineProperty(r,M,{enumerable:!0,configurable:!0,get:()=>Y.value,set:q=>Y.value=q})}if(l)for(const M in l)x6(l[M],r,n,M);if(s){const M=Ct(s)?s.call(n):s;Reflect.ownKeys(M).forEach(E=>{ot(E,M[E])})}d&&Rk(d,e,\"c\");function B(M,E){pt(E)?E.forEach(K=>M(K.bind(n))):E&&M(E.bind(n))}if(B(hc,f),B(et,p),B(wm,v),B(ur,m),B(O6,y),B(P6,b),B(RL,_),B(DL,O),B(AL,T),B(Lt,S),B(Wr,k),B(NL,I),pt(L))if(L.length){const M=e.exposed||(e.exposed={});L.forEach(E=>{Object.defineProperty(M,E,{get:()=>n[E],set:K=>n[E]=K})})}else e.exposed||(e.exposed={});$&&e.render===Qt&&(e.render=$),j!=null&&(e.inheritAttrs=j),F&&(e.components=F),N&&(e.directives=N)}function FL(e,t,n=Qt,r=!1){pt(e)&&(e=Ub(e));for(const a in e){const o=e[a];let i;zt(o)?\"default\"in o?i=ve(o.from||a,o.default,!0):i=ve(o.from||a):i=ve(o),_n(i)&&r?Object.defineProperty(t,a,{enumerable:!0,configurable:!0,get:()=>i.value,set:l=>i.value=l}):t[a]=i}}function Rk(e,t,n){Pa(pt(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function x6(e,t,n,r){const a=r.includes(\".\")?w6(n,r):()=>n[r];if(wt(e)){const o=t[e];Ct(o)&&ce(a,o)}else if(Ct(e))ce(a,e.bind(n));else if(zt(e))if(pt(e))e.forEach(o=>x6(o,t,n,r));else{const o=Ct(e.handler)?e.handler.bind(n):t[e.handler];Ct(o)&&ce(a,o,e)}}function _6(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:a,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,l=o.get(t);let s;return l?s=l:!a.length&&!n&&!r?s=t:(s={},a.length&&a.forEach(c=>lv(s,c,i,!0)),lv(s,t,i)),o.set(t,s),s}function lv(e,t,n,r=!1){const{mixins:a,extends:o}=t;o&&lv(e,o,n,!0),a&&a.forEach(i=>lv(e,i,n,!0));for(const i in t)if(!(r&&i===\"expose\")){const l=BL[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const BL={data:Lk,props:Ml,emits:Ml,methods:Ml,computed:Ml,beforeCreate:xr,created:xr,beforeMount:xr,mounted:xr,beforeUpdate:xr,updated:xr,beforeDestroy:xr,beforeUnmount:xr,destroyed:xr,unmounted:xr,activated:xr,deactivated:xr,errorCaptured:xr,serverPrefetch:xr,components:Ml,directives:Ml,watch:zL,provide:Lk,inject:VL};function Lk(e,t){return t?e?function(){return fr(Ct(e)?e.call(this,this):e,Ct(t)?t.call(this,this):t)}:t:e}function VL(e,t){return Ml(Ub(e),Ub(t))}function Ub(e){if(pt(e)){const t={};for(let n=0;n<e.length;n++)t[e[n]]=e[n];return t}return e}function xr(e,t){return e?[...new Set([].concat(e,t))]:t}function Ml(e,t){return e?fr(fr(Object.create(null),e),t):t}function zL(e,t){if(!e)return t;if(!t)return e;const n=fr(Object.create(null),e);for(const r in t)n[r]=xr(e[r],t[r]);return n}function HL(e,t,n,r=!1){const a={},o={};rv(o,Sm,1),e.propsDefaults=Object.create(null),E6(e,t,a,o);for(const i in e.propsOptions[0])i in a||(a[i]=void 0);n?e.props=r?a:lL(a):e.type.props?e.props=a:e.props=o,e.attrs=o}function jL(e,t,n,r){const{props:a,attrs:o,vnode:{patchFlag:i}}=e,l=Gt(a),[s]=e.propsOptions;let c=!1;if((r||i>0)&&!(i&16)){if(i&8){const d=e.vnode.dynamicProps;for(let f=0;f<d.length;f++){let p=d[f];if(gm(e.emitsOptions,p))continue;const v=t[p];if(s)if(Mt(o,p))v!==o[p]&&(o[p]=v,c=!0);else{const m=_a(p);a[m]=Yb(s,l,m,v,e,!1)}else v!==o[p]&&(o[p]=v,c=!0)}}}else{E6(e,t,a,o)&&(c=!0);let d;for(const f in l)(!t||!Mt(t,f)&&((d=vl(f))===f||!Mt(t,d)))&&(s?n&&(n[f]!==void 0||n[d]!==void 0)&&(a[f]=Yb(s,l,f,void 0,e,!0)):delete a[f]);if(o!==l)for(const f in o)(!t||!Mt(t,f)&&!0)&&(delete o[f],c=!0)}c&&mi(e,\"set\",\"$attrs\")}function E6(e,t,n,r){const[a,o]=e.propsOptions;let i=!1,l;if(t)for(let s in t){if(rp(s))continue;const c=t[s];let d;a&&Mt(a,d=_a(s))?!o||!o.includes(d)?n[d]=c:(l||(l={}))[d]=c:gm(e.emitsOptions,s)||(!(s in r)||c!==r[s])&&(r[s]=c,i=!0)}if(o){const s=Gt(n),c=l||wn;for(let d=0;d<o.length;d++){const f=o[d];n[f]=Yb(a,s,f,c[f],e,!Mt(c,f))}}return i}function Yb(e,t,n,r,a,o){const i=e[n];if(i!=null){const l=Mt(i,\"default\");if(l&&r===void 0){const s=i.default;if(i.type!==Function&&Ct(s)){const{propsDefaults:c}=a;n in c?r=c[n]:(zu(a),r=c[n]=s.call(null,t),ns())}else r=s}i[0]&&(o&&!l?r=!1:i[1]&&(r===\"\"||r===vl(n))&&(r=!0))}return r}function M6(e,t,n=!1){const r=t.propsCache,a=r.get(e);if(a)return a;const o=e.props,i={},l=[];let s=!1;if(!Ct(e)){const d=f=>{s=!0;const[p,v]=M6(f,t,!0);fr(i,p),v&&l.push(...v)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!o&&!s)return r.set(e,Su),Su;if(pt(o))for(let d=0;d<o.length;d++){const f=_a(o[d]);Fk(f)&&(i[f]=wn)}else if(o)for(const d in o){const f=_a(d);if(Fk(f)){const p=o[d],v=i[f]=pt(p)||Ct(p)?{type:p}:p;if(v){const m=zk(Boolean,v.type),y=zk(String,v.type);v[0]=m>-1,v[1]=y<0||m<y,(m>-1||Mt(v,\"default\"))&&l.push(f)}}}const c=[i,l];return r.set(e,c),c}function Fk(e){return e[0]!==\"$\"}function Bk(e){const t=e&&e.toString().match(/^\\s*function (\\w+)/);return t?t[1]:e===null?\"null\":\"\"}function Vk(e,t){return Bk(e)===Bk(t)}function zk(e,t){return pt(t)?t.findIndex(n=>Vk(n,e)):Ct(t)&&Vk(t,e)?0:-1}const I6=e=>e[0]===\"_\"||e===\"$stable\",lC=e=>pt(e)?e.map(ko):[ko(e)],KL=(e,t,n)=>{const r=re((...a)=>lC(t(...a)),n);return r._c=!1,r},N6=(e,t,n)=>{const r=e._ctx;for(const a in e){if(I6(a))continue;const o=e[a];if(Ct(o))t[a]=KL(a,o,r);else if(o!=null){const i=lC(o);t[a]=()=>i}}},A6=(e,t)=>{const n=lC(t);e.slots.default=()=>n},WL=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=Gt(t),rv(t,\"_\",n)):N6(t,e.slots={})}else e.slots={},t&&A6(e,t);rv(e.slots,Sm,1)},UL=(e,t,n)=>{const{vnode:r,slots:a}=e;let o=!0,i=wn;if(r.shapeFlag&32){const l=t._;l?n&&l===1?o=!1:(fr(a,t),!n&&l===1&&delete a._):(o=!t.$stable,N6(t,a)),i=t}else t&&(A6(e,t),i={default:1});if(o)for(const l in a)!I6(l)&&!(l in i)&&delete a[l]};function at(e,t){const n=ua;if(n===null)return e;const r=km(n)||n.proxy,a=e.dirs||(e.dirs=[]);for(let o=0;o<t.length;o++){let[i,l,s,c=wn]=t[o];Ct(i)&&(i={mounted:i,updated:i}),i.deep&&Wl(l),a.push({dir:i,instance:r,value:l,oldValue:void 0,arg:s,modifiers:c})}return e}function Cl(e,t,n,r){const a=e.dirs,o=t&&t.dirs;for(let i=0;i<a.length;i++){const l=a[i];o&&(l.oldValue=o[i].value);let s=l.dir[r];s&&($s(),Pa(s,n,8,[e.el,l,e,t]),Os())}}function D6(){return{app:null,config:{isNativeTag:T9,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let YL=0;function qL(e,t){return function(r,a=null){Ct(r)||(r=Object.assign({},r)),a!=null&&!zt(a)&&(a=null);const o=D6(),i=new Set;let l=!1;const s=o.app={_uid:YL++,_component:r,_props:a,_container:null,_context:o,_instance:null,version:vF,get config(){return o.config},set config(c){},use(c,...d){return i.has(c)||(c&&Ct(c.install)?(i.add(c),c.install(s,...d)):Ct(c)&&(i.add(c),c(s,...d))),s},mixin(c){return o.mixins.includes(c)||o.mixins.push(c),s},component(c,d){return d?(o.components[c]=d,s):o.components[c]},directive(c,d){return d?(o.directives[c]=d,s):o.directives[c]},mount(c,d,f){if(!l){const p=g(r,a);return p.appContext=o,d&&t?t(p,c):e(p,c,f),l=!0,s._container=c,c.__vue_app__=s,km(p.component)||p.component.proxy}},unmount(){l&&(e(null,s._container),delete s._container.__vue_app__)},provide(c,d){return o.provides[c]=d,s}};return s}}function qb(e,t,n,r,a=!1){if(pt(e)){e.forEach((p,v)=>qb(p,t&&(pt(t)?t[v]:t),n,r,a));return}if(Kb(r)&&!a)return;const o=r.shapeFlag&4?km(r.component)||r.component.proxy:r.el,i=a?null:o,{i:l,r:s}=e,c=t&&t.r,d=l.refs===wn?l.refs={}:l.refs,f=l.setupState;if(c!=null&&c!==s&&(wt(c)?(d[c]=null,Mt(f,c)&&(f[c]=null)):_n(c)&&(c.value=null)),Ct(s))ci(s,l,12,[i,d]);else{const p=wt(s),v=_n(s);if(p||v){const m=()=>{if(e.f){const y=p?d[s]:s.value;a?pt(y)&&K1(y,o):pt(y)?y.includes(o)||y.push(o):p?(d[s]=[o],Mt(f,s)&&(f[s]=d[s])):(s.value=[o],e.k&&(d[e.k]=s.value))}else p?(d[s]=i,Mt(f,s)&&(f[s]=i)):_n(s)&&(s.value=i,e.k&&(d[e.k]=i))};i?(m.id=-1,Rr(m,n)):m()}}}const Rr=_L;function GL(e){return XL(e)}function XL(e,t){const n=I9();n.__VUE__=!0;const{insert:r,remove:a,patchProp:o,createElement:i,createText:l,createComment:s,setText:c,setElementText:d,parentNode:f,nextSibling:p,setScopeId:v=Qt,cloneNode:m,insertStaticContent:y}=e,b=(te,ie,ge,ke=null,xe=null,Ie=null,ye=!1,pe=null,ue=!!ie.dynamicChildren)=>{if(te===ie)return;te&&!Rl(te,ie)&&(ke=de(te),J(te,xe,Ie,!0),te=null),ie.patchFlag===-2&&(ue=!1,ie.dynamicChildren=null);const{type:Ce,ref:je,shapeFlag:ee}=ie;switch(Ce){case Fo:C(te,ie,ge,ke);break;case Ir:S(te,ie,ge,ke);break;case qg:te==null&&w(ie,ge,ke,ye);break;case Fe:N(te,ie,ge,ke,xe,Ie,ye,pe,ue);break;default:ee&1?O(te,ie,ge,ke,xe,Ie,ye,pe,ue):ee&6?D(te,ie,ge,ke,xe,Ie,ye,pe,ue):(ee&64||ee&128)&&Ce.process(te,ie,ge,ke,xe,Ie,ye,pe,ue,Ee)}je!=null&&xe&&qb(je,te&&te.ref,Ie,ie||te,!ie)},C=(te,ie,ge,ke)=>{if(te==null)r(ie.el=l(ie.children),ge,ke);else{const xe=ie.el=te.el;ie.children!==te.children&&c(xe,ie.children)}},S=(te,ie,ge,ke)=>{te==null?r(ie.el=s(ie.children||\"\"),ge,ke):ie.el=te.el},w=(te,ie,ge,ke)=>{[te.el,te.anchor]=y(te.children,ie,ge,ke,te.el,te.anchor)},k=({el:te,anchor:ie},ge,ke)=>{let xe;for(;te&&te!==ie;)xe=p(te),r(te,ge,ke),te=xe;r(ie,ge,ke)},$=({el:te,anchor:ie})=>{let ge;for(;te&&te!==ie;)ge=p(te),a(te),te=ge;a(ie)},O=(te,ie,ge,ke,xe,Ie,ye,pe,ue)=>{ye=ye||ie.type===\"svg\",te==null?T(ie,ge,ke,xe,Ie,ye,pe,ue):L(te,ie,xe,Ie,ye,pe,ue)},T=(te,ie,ge,ke,xe,Ie,ye,pe)=>{let ue,Ce;const{type:je,props:ee,shapeFlag:me,transition:He,patchFlag:lt,dirs:Ye}=te;if(te.el&&m!==void 0&&lt===-1)ue=te.el=m(te.el);else{if(ue=te.el=i(te.type,Ie,ee&&ee.is,ee),me&8?d(ue,te.children):me&16&&I(te.children,ue,null,ke,xe,Ie&&je!==\"foreignObject\",ye,pe),Ye&&Cl(te,null,ke,\"created\"),ee){for(const _e in ee)_e!==\"value\"&&!rp(_e)&&o(ue,_e,null,ee[_e],Ie,te.children,ke,xe,ae);\"value\"in ee&&o(ue,\"value\",null,ee.value),(Ce=ee.onVnodeBeforeMount)&&bo(Ce,ke,te)}_(ue,te,te.scopeId,ye,ke)}Ye&&Cl(te,null,ke,\"beforeMount\");const he=(!xe||xe&&!xe.pendingBranch)&&He&&!He.persisted;he&&He.beforeEnter(ue),r(ue,ie,ge),((Ce=ee&&ee.onVnodeMounted)||he||Ye)&&Rr(()=>{Ce&&bo(Ce,ke,te),he&&He.enter(ue),Ye&&Cl(te,null,ke,\"mounted\")},xe)},_=(te,ie,ge,ke,xe)=>{if(ge&&v(te,ge),ke)for(let Ie=0;Ie<ke.length;Ie++)v(te,ke[Ie]);if(xe){let Ie=xe.subTree;if(ie===Ie){const ye=xe.vnode;_(te,ye,ye.scopeId,ye.slotScopeIds,xe.parent)}}},I=(te,ie,ge,ke,xe,Ie,ye,pe,ue=0)=>{for(let Ce=ue;Ce<te.length;Ce++){const je=te[Ce]=pe?Ki(te[Ce]):ko(te[Ce]);b(null,je,ie,ge,ke,xe,Ie,ye,pe)}},L=(te,ie,ge,ke,xe,Ie,ye)=>{const pe=ie.el=te.el;let{patchFlag:ue,dynamicChildren:Ce,dirs:je}=ie;ue|=te.patchFlag&16;const ee=te.props||wn,me=ie.props||wn;let He;ge&&wl(ge,!1),(He=me.onVnodeBeforeUpdate)&&bo(He,ge,ie,te),je&&Cl(ie,te,ge,\"beforeUpdate\"),ge&&wl(ge,!0);const lt=xe&&ie.type!==\"foreignObject\";if(Ce?j(te.dynamicChildren,Ce,pe,ge,ke,lt,Ie):ye||K(te,ie,pe,null,ge,ke,lt,Ie,!1),ue>0){if(ue&16)F(pe,ie,ee,me,ge,ke,xe);else if(ue&2&&ee.class!==me.class&&o(pe,\"class\",null,me.class,xe),ue&4&&o(pe,\"style\",ee.style,me.style,xe),ue&8){const Ye=ie.dynamicProps;for(let he=0;he<Ye.length;he++){const _e=Ye[he],$e=ee[_e],Ve=me[_e];(Ve!==$e||_e===\"value\")&&o(pe,_e,$e,Ve,xe,te.children,ge,ke,ae)}}ue&1&&te.children!==ie.children&&d(pe,ie.children)}else!ye&&Ce==null&&F(pe,ie,ee,me,ge,ke,xe);((He=me.onVnodeUpdated)||je)&&Rr(()=>{He&&bo(He,ge,ie,te),je&&Cl(ie,te,ge,\"updated\")},ke)},j=(te,ie,ge,ke,xe,Ie,ye)=>{for(let pe=0;pe<ie.length;pe++){const ue=te[pe],Ce=ie[pe],je=ue.el&&(ue.type===Fe||!Rl(ue,Ce)||ue.shapeFlag&70)?f(ue.el):ge;b(ue,Ce,je,null,ke,xe,Ie,ye,!0)}},F=(te,ie,ge,ke,xe,Ie,ye)=>{if(ge!==ke){for(const pe in ke){if(rp(pe))continue;const ue=ke[pe],Ce=ge[pe];ue!==Ce&&pe!==\"value\"&&o(te,pe,Ce,ue,ye,ie.children,xe,Ie,ae)}if(ge!==wn)for(const pe in ge)!rp(pe)&&!(pe in ke)&&o(te,pe,ge[pe],null,ye,ie.children,xe,Ie,ae);\"value\"in ke&&o(te,\"value\",ge.value,ke.value)}},N=(te,ie,ge,ke,xe,Ie,ye,pe,ue)=>{const Ce=ie.el=te?te.el:l(\"\"),je=ie.anchor=te?te.anchor:l(\"\");let{patchFlag:ee,dynamicChildren:me,slotScopeIds:He}=ie;He&&(pe=pe?pe.concat(He):He),te==null?(r(Ce,ge,ke),r(je,ge,ke),I(ie.children,ge,je,xe,Ie,ye,pe,ue)):ee>0&&ee&64&&me&&te.dynamicChildren?(j(te.dynamicChildren,me,ge,xe,Ie,ye,pe),(ie.key!=null||xe&&ie===xe.subTree)&&sC(te,ie,!0)):K(te,ie,ge,je,xe,Ie,ye,pe,ue)},D=(te,ie,ge,ke,xe,Ie,ye,pe,ue)=>{ie.slotScopeIds=pe,te==null?ie.shapeFlag&512?xe.ctx.activate(ie,ge,ke,ye,ue):z(ie,ge,ke,xe,Ie,ye,ue):B(te,ie,ue)},z=(te,ie,ge,ke,xe,Ie,ye)=>{const pe=te.component=sF(te,ke,xe);if(bm(te)&&(pe.ctx.renderer=Ee),uF(pe),pe.asyncDep){if(xe&&xe.registerDep(pe,M),!te.el){const ue=pe.subTree=g(Ir);S(null,ue,ie,ge)}return}M(pe,te,ie,ge,xe,Ie,ye)},B=(te,ie,ge)=>{const ke=ie.component=te.component;if(PL(te,ie,ge))if(ke.asyncDep&&!ke.asyncResolved){E(ke,ie,ge);return}else ke.next=ie,CL(ke.update),ke.update();else ie.component=te.component,ie.el=te.el,ke.vnode=ie},M=(te,ie,ge,ke,xe,Ie,ye)=>{const pe=()=>{if(te.isMounted){let{next:je,bu:ee,u:me,parent:He,vnode:lt}=te,Ye=je,he;wl(te,!1),je?(je.el=lt.el,E(te,je,ye)):je=lt,ee&&op(ee),(he=je.props&&je.props.onVnodeBeforeUpdate)&&bo(he,He,je,lt),wl(te,!0);const _e=Ug(te),$e=te.subTree;te.subTree=_e,b($e,_e,f($e.el),de($e),te,xe,Ie),je.el=_e.el,Ye===null&&TL(te,_e.el),me&&Rr(me,xe),(he=je.props&&je.props.onVnodeUpdated)&&Rr(()=>bo(he,He,je,lt),xe)}else{let je;const{el:ee,props:me}=ie,{bm:He,m:lt,parent:Ye}=te,he=Kb(ie);if(wl(te,!1),He&&op(He),!he&&(je=me&&me.onVnodeBeforeMount)&&bo(je,Ye,ie),wl(te,!0),ee&&Be){const _e=()=>{te.subTree=Ug(te),Be(ee,te.subTree,te,xe,null)};he?ie.type.__asyncLoader().then(()=>!te.isUnmounted&&_e()):_e()}else{const _e=te.subTree=Ug(te);b(null,_e,ge,ke,te,xe,Ie),ie.el=_e.el}if(lt&&Rr(lt,xe),!he&&(je=me&&me.onVnodeMounted)){const _e=ie;Rr(()=>bo(je,Ye,_e),xe)}ie.shapeFlag&256&&te.a&&Rr(te.a,xe),te.isMounted=!0,ie=ge=ke=null}},ue=te.effect=new q1(pe,()=>v6(te.update),te.scope),Ce=te.update=ue.run.bind(ue);Ce.id=te.uid,wl(te,!0),Ce()},E=(te,ie,ge)=>{ie.component=te;const ke=te.vnode.props;te.vnode=ie,te.next=null,jL(te,ie.props,ke,ge),UL(te,ie.children,ge),$s(),nC(void 0,te.update),Os()},K=(te,ie,ge,ke,xe,Ie,ye,pe,ue=!1)=>{const Ce=te&&te.children,je=te?te.shapeFlag:0,ee=ie.children,{patchFlag:me,shapeFlag:He}=ie;if(me>0){if(me&128){Y(Ce,ee,ge,ke,xe,Ie,ye,pe,ue);return}else if(me&256){W(Ce,ee,ge,ke,xe,Ie,ye,pe,ue);return}}He&8?(je&16&&ae(Ce,xe,Ie),ee!==Ce&&d(ge,ee)):je&16?He&16?Y(Ce,ee,ge,ke,xe,Ie,ye,pe,ue):ae(Ce,xe,Ie,!0):(je&8&&d(ge,\"\"),He&16&&I(ee,ge,ke,xe,Ie,ye,pe,ue))},W=(te,ie,ge,ke,xe,Ie,ye,pe,ue)=>{te=te||Su,ie=ie||Su;const Ce=te.length,je=ie.length,ee=Math.min(Ce,je);let me;for(me=0;me<ee;me++){const He=ie[me]=ue?Ki(ie[me]):ko(ie[me]);b(te[me],He,ge,null,xe,Ie,ye,pe,ue)}Ce>je?ae(te,xe,Ie,!0,!1,ee):I(ie,ge,ke,xe,Ie,ye,pe,ue,ee)},Y=(te,ie,ge,ke,xe,Ie,ye,pe,ue)=>{let Ce=0;const je=ie.length;let ee=te.length-1,me=je-1;for(;Ce<=ee&&Ce<=me;){const He=te[Ce],lt=ie[Ce]=ue?Ki(ie[Ce]):ko(ie[Ce]);if(Rl(He,lt))b(He,lt,ge,null,xe,Ie,ye,pe,ue);else break;Ce++}for(;Ce<=ee&&Ce<=me;){const He=te[ee],lt=ie[me]=ue?Ki(ie[me]):ko(ie[me]);if(Rl(He,lt))b(He,lt,ge,null,xe,Ie,ye,pe,ue);else break;ee--,me--}if(Ce>ee){if(Ce<=me){const He=me+1,lt=He<je?ie[He].el:ke;for(;Ce<=me;)b(null,ie[Ce]=ue?Ki(ie[Ce]):ko(ie[Ce]),ge,lt,xe,Ie,ye,pe,ue),Ce++}}else if(Ce>me)for(;Ce<=ee;)J(te[Ce],xe,Ie,!0),Ce++;else{const He=Ce,lt=Ce,Ye=new Map;for(Ce=lt;Ce<=me;Ce++){const Ft=ie[Ce]=ue?Ki(ie[Ce]):ko(ie[Ce]);Ft.key!=null&&Ye.set(Ft.key,Ce)}let he,_e=0;const $e=me-lt+1;let Ve=!1,st=0;const Dt=new Array($e);for(Ce=0;Ce<$e;Ce++)Dt[Ce]=0;for(Ce=He;Ce<=ee;Ce++){const Ft=te[Ce];if(_e>=$e){J(Ft,xe,Ie,!0);continue}let Jt;if(Ft.key!=null)Jt=Ye.get(Ft.key);else for(he=lt;he<=me;he++)if(Dt[he-lt]===0&&Rl(Ft,ie[he])){Jt=he;break}Jt===void 0?J(Ft,xe,Ie,!0):(Dt[Jt-lt]=Ce+1,Jt>=st?st=Jt:Ve=!0,b(Ft,ie[Jt],ge,null,xe,Ie,ye,pe,ue),_e++)}const Ut=Ve?ZL(Dt):Su;for(he=Ut.length-1,Ce=$e-1;Ce>=0;Ce--){const Ft=lt+Ce,Jt=ie[Ft],Mn=Ft+1<je?ie[Ft+1].el:ke;Dt[Ce]===0?b(null,Jt,ge,Mn,xe,Ie,ye,pe,ue):Ve&&(he<0||Ce!==Ut[he]?q(Jt,ge,Mn,2):he--)}}},q=(te,ie,ge,ke,xe=null)=>{const{el:Ie,type:ye,transition:pe,children:ue,shapeFlag:Ce}=te;if(Ce&6){q(te.component.subTree,ie,ge,ke);return}if(Ce&128){te.suspense.move(ie,ge,ke);return}if(Ce&64){ye.move(te,ie,ge,Ee);return}if(ye===Fe){r(Ie,ie,ge);for(let ee=0;ee<ue.length;ee++)q(ue[ee],ie,ge,ke);r(te.anchor,ie,ge);return}if(ye===qg){k(te,ie,ge);return}if(ke!==2&&Ce&1&&pe)if(ke===0)pe.beforeEnter(Ie),r(Ie,ie,ge),Rr(()=>pe.enter(Ie),xe);else{const{leave:ee,delayLeave:me,afterLeave:He}=pe,lt=()=>r(Ie,ie,ge),Ye=()=>{ee(Ie,()=>{lt(),He&&He()})};me?me(Ie,lt,Ye):Ye()}else r(Ie,ie,ge)},J=(te,ie,ge,ke=!1,xe=!1)=>{const{type:Ie,props:ye,ref:pe,children:ue,dynamicChildren:Ce,shapeFlag:je,patchFlag:ee,dirs:me}=te;if(pe!=null&&qb(pe,null,ge,te,!0),je&256){ie.ctx.deactivate(te);return}const He=je&1&&me,lt=!Kb(te);let Ye;if(lt&&(Ye=ye&&ye.onVnodeBeforeUnmount)&&bo(Ye,ie,te),je&6)Q(te.component,ge,ke);else{if(je&128){te.suspense.unmount(ge,ke);return}He&&Cl(te,null,ie,\"beforeUnmount\"),je&64?te.type.remove(te,ie,ge,xe,Ee,ke):Ce&&(Ie!==Fe||ee>0&&ee&64)?ae(Ce,ie,ge,!1,!0):(Ie===Fe&&ee&384||!xe&&je&16)&&ae(ue,ie,ge),ke&&ne(te)}(lt&&(Ye=ye&&ye.onVnodeUnmounted)||He)&&Rr(()=>{Ye&&bo(Ye,ie,te),He&&Cl(te,null,ie,\"unmounted\")},ge)},ne=te=>{const{type:ie,el:ge,anchor:ke,transition:xe}=te;if(ie===Fe){oe(ge,ke);return}if(ie===qg){$(te);return}const Ie=()=>{a(ge),xe&&!xe.persisted&&xe.afterLeave&&xe.afterLeave()};if(te.shapeFlag&1&&xe&&!xe.persisted){const{leave:ye,delayLeave:pe}=xe,ue=()=>ye(ge,Ie);pe?pe(te.el,Ie,ue):ue()}else Ie()},oe=(te,ie)=>{let ge;for(;te!==ie;)ge=p(te),a(te),te=ge;a(ie)},Q=(te,ie,ge)=>{const{bum:ke,scope:xe,update:Ie,subTree:ye,um:pe}=te;ke&&op(ke),xe.stop(),Ie&&(Ie.active=!1,J(ye,te,ie,ge)),pe&&Rr(pe,ie),Rr(()=>{te.isUnmounted=!0},ie),ie&&ie.pendingBranch&&!ie.isUnmounted&&te.asyncDep&&!te.asyncResolved&&te.suspenseId===ie.pendingId&&(ie.deps--,ie.deps===0&&ie.resolve())},ae=(te,ie,ge,ke=!1,xe=!1,Ie=0)=>{for(let ye=Ie;ye<te.length;ye++)J(te[ye],ie,ge,ke,xe)},de=te=>te.shapeFlag&6?de(te.component.subTree):te.shapeFlag&128?te.suspense.next():p(te.anchor||te.el),be=(te,ie,ge)=>{te==null?ie._vnode&&J(ie._vnode,null,null,!0):b(ie._vnode||null,te,ie,null,null,null,ge),y6(),ie._vnode=te},Ee={p:b,um:J,m:q,r:ne,mt:z,mc:I,pc:K,pbc:j,n:de,o:e};let Pe,Be;return t&&([Pe,Be]=t(Ee)),{render:be,hydrate:Pe,createApp:qL(be,Pe)}}function wl({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function sC(e,t,n=!1){const r=e.children,a=t.children;if(pt(r)&&pt(a))for(let o=0;o<r.length;o++){const i=r[o];let l=a[o];l.shapeFlag&1&&!l.dynamicChildren&&((l.patchFlag<=0||l.patchFlag===32)&&(l=a[o]=Ki(a[o]),l.el=i.el),n||sC(i,l))}}function ZL(e){const t=e.slice(),n=[0];let r,a,o,i,l;const s=e.length;for(r=0;r<s;r++){const c=e[r];if(c!==0){if(a=n[n.length-1],e[a]<c){t[r]=a,n.push(r);continue}for(o=0,i=n.length-1;o<i;)l=o+i>>1,e[n[l]]<c?o=l+1:i=l;c<e[n[o]]&&(o>0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}const JL=e=>e.__isTeleport,fd=e=>e&&(e.disabled||e.disabled===\"\"),Hk=e=>typeof SVGElement!=\"undefined\"&&e instanceof SVGElement,Gb=(e,t)=>{const n=e&&e.to;return wt(n)?t?t(n):null:n},QL={__isTeleport:!0,process(e,t,n,r,a,o,i,l,s,c){const{mc:d,pc:f,pbc:p,o:{insert:v,querySelector:m,createText:y,createComment:b}}=c,C=fd(t.props);let{shapeFlag:S,children:w,dynamicChildren:k}=t;if(e==null){const $=t.el=y(\"\"),O=t.anchor=y(\"\");v($,n,r),v(O,n,r);const T=t.target=Gb(t.props,m),_=t.targetAnchor=y(\"\");T&&(v(_,T),i=i||Hk(T));const I=(L,j)=>{S&16&&d(w,L,j,a,o,i,l,s)};C?I(n,O):T&&I(T,_)}else{t.el=e.el;const $=t.anchor=e.anchor,O=t.target=e.target,T=t.targetAnchor=e.targetAnchor,_=fd(e.props),I=_?n:O,L=_?$:T;if(i=i||Hk(O),k?(p(e.dynamicChildren,k,I,a,o,i,l),sC(e,t,!0)):s||f(e,t,I,L,a,o,i,l,!1),C)_||nh(t,n,$,c,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const j=t.target=Gb(t.props,m);j&&nh(t,j,null,c,0)}else _&&nh(t,O,T,c,1)}},remove(e,t,n,r,{um:a,o:{remove:o}},i){const{shapeFlag:l,children:s,anchor:c,targetAnchor:d,target:f,props:p}=e;if(f&&o(d),(i||!fd(p))&&(o(c),l&16))for(let v=0;v<s.length;v++){const m=s[v];a(m,t,n,!0,!!m.dynamicChildren)}},move:nh,hydrate:eF};function nh(e,t,n,{o:{insert:r},m:a},o=2){o===0&&r(e.targetAnchor,t,n);const{el:i,anchor:l,shapeFlag:s,children:c,props:d}=e,f=o===2;if(f&&r(i,t,n),(!f||fd(d))&&s&16)for(let p=0;p<c.length;p++)a(c[p],t,n,2);f&&r(l,t,n)}function eF(e,t,n,r,a,o,{o:{nextSibling:i,parentNode:l,querySelector:s}},c){const d=t.target=Gb(t.props,s);if(d){const f=d._lpa||d.firstChild;t.shapeFlag&16&&(fd(t.props)?(t.anchor=c(i(e),t,l(e),n,r,a,o),t.targetAnchor=f):(t.anchor=i(e),t.targetAnchor=c(f,t,d,n,r,a,o)),d._lpa=t.targetAnchor&&i(t.targetAnchor))}return t.anchor&&i(t.anchor)}const Ps=QL,uC=\"components\",tF=\"directives\";function we(e,t){return cC(uC,e,!0,t)||e}const R6=Symbol();function Kt(e){return wt(e)?cC(uC,e,!1)||e:e||R6}function pa(e){return cC(tF,e)}function cC(e,t,n=!0,r=!1){const a=ua||dr;if(a){const o=a.type;if(e===uC){const l=j6(o);if(l&&(l===t||l===_a(t)||l===ia(_a(t))))return o}const i=jk(a[e]||o[e],t)||jk(a.appContext[e],t);return!i&&r?o:i}}function jk(e,t){return e&&(e[t]||e[_a(t)]||e[ia(_a(t))])}const Fe=Symbol(void 0),Fo=Symbol(void 0),Ir=Symbol(void 0),qg=Symbol(void 0),hd=[];let ts=null;function R(e=!1){hd.push(ts=e?null:[])}function nF(){hd.pop(),ts=hd[hd.length-1]||null}let sv=1;function Kk(e){sv+=e}function L6(e){return e.dynamicChildren=sv>0?ts||Su:null,nF(),sv>0&&ts&&ts.push(e),e}function X(e,t,n,r,a,o){return L6(Z(e,t,n,r,a,o,!0))}function fe(e,t,n,r,a){return L6(g(e,t,n,r,a,!0))}function rn(e){return e?e.__v_isVNode===!0:!1}function Rl(e,t){return e.type===t.type&&e.key===t.key}const Sm=\"__vInternal\",F6=({key:e})=>e!=null?e:null,ip=({ref:e,ref_key:t,ref_for:n})=>e!=null?wt(e)||_n(e)||Ct(e)?{i:ua,r:e,k:t,f:!!n}:e:null;function Z(e,t=null,n=null,r=0,a=null,o=e===Fe?0:1,i=!1,l=!1){const s={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&F6(t),ref:t&&ip(t),scopeId:ym,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:a,dynamicChildren:null,appContext:null};return l?(dC(s,n),o&128&&e.normalize(s)):n&&(s.shapeFlag|=wt(n)?8:16),sv>0&&!i&&ts&&(s.patchFlag>0||o&6)&&s.patchFlag!==32&&ts.push(s),s}const g=rF;function rF(e,t=null,n=null,r=0,a=null,o=!1){if((!e||e===R6)&&(e=Ir),rn(e)){const l=hr(e,t,!0);return n&&dC(l,n),l}if(pF(e)&&(e=e.__vccOpts),t){t=ll(t);let{class:l,style:s}=t;l&&!wt(l)&&(t.class=U(l)),zt(s)&&(u6(s)&&!pt(s)&&(s=fr({},s)),t.style=Xe(s))}const i=wt(e)?1:xL(e)?128:JL(e)?64:zt(e)?4:Ct(e)?2:0;return Z(e,t,n,r,a,i,o,!0)}function ll(e){return e?u6(e)||Sm in e?fr({},e):e:null}function hr(e,t,n=!1){const{props:r,ref:a,patchFlag:o,children:i}=e,l=t?hn(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&F6(l),ref:t&&t.ref?n&&a?pt(a)?a.concat(ip(t)):[a,ip(t)]:ip(t):a,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Fe?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&hr(e.ssContent),ssFallback:e.ssFallback&&hr(e.ssFallback),el:e.el,anchor:e.anchor}}function yt(e=\" \",t=0){return g(Fo,null,e,t)}function se(e=\"\",t=!1){return t?(R(),fe(Ir,null,e)):g(Ir,null,e)}function ko(e){return e==null||typeof e==\"boolean\"?g(Ir):pt(e)?g(Fe,null,e.slice()):typeof e==\"object\"?Ki(e):g(Fo,null,String(e))}function Ki(e){return e.el===null||e.memo?e:hr(e)}function dC(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(pt(t))n=16;else if(typeof t==\"object\")if(r&65){const a=t.default;a&&(a._c&&(a._d=!1),dC(e,a()),a._c&&(a._d=!0));return}else{n=32;const a=t._;!a&&!(Sm in t)?t._ctx=ua:a===3&&ua&&(ua.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else Ct(t)?(t={default:t,_ctx:ua},n=32):(t=String(t),r&64?(n=16,t=[yt(t)]):n=8);e.children=t,e.shapeFlag|=n}function hn(...e){const t={};for(let n=0;n<e.length;n++){const r=e[n];for(const a in r)if(a===\"class\")t.class!==r.class&&(t.class=U([t.class,r.class]));else if(a===\"style\")t.style=Xe([t.style,r.style]);else if(fm(a)){const o=t[a],i=r[a];i&&o!==i&&!(pt(o)&&o.includes(i))&&(t[a]=o?[].concat(o,i):i)}else a!==\"\"&&(t[a]=r[a])}return t}function bo(e,t,n,r=null){Pa(e,t,7,[n,r])}function Rt(e,t,n,r){let a;const o=n&&n[r];if(pt(e)||wt(e)){a=new Array(e.length);for(let i=0,l=e.length;i<l;i++)a[i]=t(e[i],i,void 0,o&&o[i])}else if(typeof e==\"number\"){a=new Array(e);for(let i=0;i<e;i++)a[i]=t(i+1,i,void 0,o&&o[i])}else if(zt(e))if(e[Symbol.iterator])a=Array.from(e,(i,l)=>t(i,l,void 0,o&&o[l]));else{const i=Object.keys(e);a=new Array(i.length);for(let l=0,s=i.length;l<s;l++){const c=i[l];a[l]=t(e[c],c,l,o&&o[l])}}else a=[];return n&&(n[r]=a),a}function sl(e,t){for(let n=0;n<t.length;n++){const r=t[n];if(pt(r))for(let a=0;a<r.length;a++)e[r[a].name]=r[a].fn;else r&&(e[r.name]=r.fn)}return e}function Oe(e,t,n={},r,a){if(ua.isCE)return g(\"slot\",t===\"default\"?null:{name:t},r&&r());let o=e[t];o&&o._c&&(o._d=!1),R();const i=o&&B6(o(n)),l=fe(Fe,{key:n.key||`_${t}`},i||(r?r():[]),i&&e._===1?64:-2);return!a&&l.scopeId&&(l.slotScopeIds=[l.scopeId+\"-s\"]),o&&o._c&&(o._d=!0),l}function B6(e){return e.some(t=>rn(t)?!(t.type===Ir||t.type===Fe&&!B6(t.children)):!0)?e:null}function aF(e){const t={};for(const n in e)t[ap(n)]=e[n];return t}const Xb=e=>e?V6(e)?km(e)||e.proxy:Xb(e.parent):null,uv=fr(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Xb(e.parent),$root:e=>Xb(e.root),$emit:e=>e.emit,$options:e=>_6(e),$forceUpdate:e=>()=>v6(e.update),$nextTick:e=>Ne.bind(e.proxy),$watch:e=>EL.bind(e)}),oF={get({_:e},t){const{ctx:n,setupState:r,data:a,props:o,accessCache:i,type:l,appContext:s}=e;let c;if(t[0]!==\"$\"){const v=i[t];if(v!==void 0)switch(v){case 1:return r[t];case 2:return a[t];case 4:return n[t];case 3:return o[t]}else{if(r!==wn&&Mt(r,t))return i[t]=1,r[t];if(a!==wn&&Mt(a,t))return i[t]=2,a[t];if((c=e.propsOptions[0])&&Mt(c,t))return i[t]=3,o[t];if(n!==wn&&Mt(n,t))return i[t]=4,n[t];Wb&&(i[t]=0)}}const d=uv[t];let f,p;if(d)return t===\"$attrs\"&&ha(e,\"get\",t),d(e);if((f=l.__cssModules)&&(f=f[t]))return f;if(n!==wn&&Mt(n,t))return i[t]=4,n[t];if(p=s.config.globalProperties,Mt(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:a,ctx:o}=e;return a!==wn&&Mt(a,t)?(a[t]=n,!0):r!==wn&&Mt(r,t)?(r[t]=n,!0):Mt(e.props,t)||t[0]===\"$\"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:a,propsOptions:o}},i){let l;return!!n[i]||e!==wn&&Mt(e,i)||t!==wn&&Mt(t,i)||(l=o[0])&&Mt(l,i)||Mt(r,i)||Mt(uv,i)||Mt(a.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e.$.accessCache[t]=0:Mt(n,\"value\")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}},iF=D6();let lF=0;function sF(e,t,n){const r=e.type,a=(t?t.appContext:e.appContext)||iF,o={uid:lF++,vnode:e,type:r,parent:t,appContext:a,root:null,next:null,subTree:null,effect:null,update:null,scope:new X_(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(a.provides),accessCache:null,renderCache:[],components:null,directives:null,propsOptions:M6(r,a),emitsOptions:C6(r,a),emit:null,emitted:null,propsDefaults:wn,inheritAttrs:r.inheritAttrs,ctx:wn,data:wn,props:wn,attrs:wn,slots:wn,refs:wn,setupState:wn,setupContext:null,suspense:n,suspenseId:n?n.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return o.ctx={_:o},o.root=t?t.root:o,o.emit=kL.bind(null,o),e.ce&&e.ce(o),o}let dr=null;const $t=()=>dr||ua,zu=e=>{dr=e,e.scope.on()},ns=()=>{dr&&dr.scope.off(),dr=null};function V6(e){return e.vnode.shapeFlag&4}let Ld=!1;function uF(e,t=!1){Ld=t;const{props:n,children:r}=e.vnode,a=V6(e);HL(e,n,a,t),WL(e,r);const o=a?cF(e,t):void 0;return Ld=!1,o}function cF(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=ps(new Proxy(e.ctx,oF));const{setup:r}=n;if(r){const a=e.setupContext=r.length>1?H6(e):null;zu(e),$s();const o=ci(r,e,0,[e.props,a]);if(Os(),ns(),hs(o)){if(o.then(ns,ns),t)return o.then(i=>{Wk(e,i,t)}).catch(i=>{mm(i,e,0)});e.asyncDep=o}else Wk(e,o,t)}else z6(e,t)}function Wk(e,t,n){Ct(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:zt(t)&&(e.setupState=f6(t)),z6(e,n)}let Uk;function z6(e,t,n){const r=e.type;if(!e.render){if(!t&&Uk&&!r.render){const a=r.template;if(a){const{isCustomElement:o,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:s}=r,c=fr(fr({isCustomElement:o,delimiters:l},i),s);r.render=Uk(a,c)}}e.render=r.render||Qt}zu(e),$s(),LL(e),Os(),ns()}function dF(e){return new Proxy(e.attrs,{get(t,n){return ha(e,\"get\",\"$attrs\"),t[n]}})}function H6(e){const t=r=>{e.exposed=r||{}};let n;return{get attrs(){return n||(n=dF(e))},slots:e.slots,emit:e.emit,expose:t}}function km(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(f6(ps(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in uv)return uv[n](e)}}))}const fF=/(?:^|[-_])(\\w)/g,hF=e=>e.replace(fF,t=>t.toUpperCase()).replace(/[-_]/g,\"\");function j6(e){return Ct(e)&&e.displayName||e.name}function K6(e,t,n=!1){let r=j6(t);if(!r&&t.__file){const a=t.__file.match(/([^/\\\\]+)\\.\\w+$/);a&&(r=a[1])}if(!r&&e&&e.parent){const a=o=>{for(const i in o)if(o[i]===t)return i};r=a(e.components||e.parent.type.components)||a(e.appContext.components)}return r?hF(r):n?\"App\":\"Anonymous\"}function pF(e){return Ct(e)&&\"__vccOpts\"in e}const x=(e,t)=>fL(e,t,Ld);function wf(){return U6().slots}function W6(){return U6().attrs}function U6(){const e=$t();return e.setupContext||(e.setupContext=H6(e))}function qe(e,t,n){const r=arguments.length;return r===2?zt(t)&&!pt(t)?rn(t)?g(e,null,[t]):g(e,t):g(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&rn(n)&&(n=[n]),g(e,t,n))}const vF=\"3.2.32\",mF=\"http://www.w3.org/2000/svg\",Ll=typeof document!=\"undefined\"?document:null,Yk=Ll&&Ll.createElement(\"template\"),gF={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const a=t?Ll.createElementNS(mF,e):Ll.createElement(e,n?{is:n}:void 0);return e===\"select\"&&r&&r.multiple!=null&&a.setAttribute(\"multiple\",r.multiple),a},createText:e=>Ll.createTextNode(e),createComment:e=>Ll.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ll.querySelector(e),setScopeId(e,t){e.setAttribute(t,\"\")},cloneNode(e){const t=e.cloneNode(!0);return\"_value\"in e&&(t._value=e._value),t},insertStaticContent(e,t,n,r,a,o){const i=n?n.previousSibling:t.lastChild;if(a&&(a===o||a.nextSibling))for(;t.insertBefore(a.cloneNode(!0),n),!(a===o||!(a=a.nextSibling)););else{Yk.innerHTML=r?`<svg>${e}</svg>`:e;const l=Yk.content;if(r){const s=l.firstChild;for(;s.firstChild;)l.appendChild(s.firstChild);l.removeChild(s)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function yF(e,t,n){const r=e._vtc;r&&(t=(t?[t,...r]:[...r]).join(\" \")),t==null?e.removeAttribute(\"class\"):n?e.setAttribute(\"class\",t):e.className=t}function bF(e,t,n){const r=e.style,a=wt(n);if(n&&!a){for(const o in n)Zb(r,o,n[o]);if(t&&!wt(t))for(const o in t)n[o]==null&&Zb(r,o,\"\")}else{const o=r.display;a?t!==n&&(r.cssText=n):t&&e.removeAttribute(\"style\"),\"_vod\"in e&&(r.display=o)}}const qk=/\\s*!important$/;function Zb(e,t,n){if(pt(n))n.forEach(r=>Zb(e,t,r));else if(t.startsWith(\"--\"))e.setProperty(t,n);else{const r=CF(e,t);qk.test(n)?e.setProperty(vl(r),n.replace(qk,\"\"),\"important\"):e[r]=n}}const Gk=[\"Webkit\",\"Moz\",\"ms\"],Gg={};function CF(e,t){const n=Gg[t];if(n)return n;let r=_a(t);if(r!==\"filter\"&&r in e)return Gg[t]=r;r=ia(r);for(let a=0;a<Gk.length;a++){const o=Gk[a]+r;if(o in e)return Gg[t]=o}return t}const Xk=\"http://www.w3.org/1999/xlink\";function wF(e,t,n,r,a){if(r&&t.startsWith(\"xlink:\"))n==null?e.removeAttributeNS(Xk,t.slice(6,t.length)):e.setAttributeNS(Xk,t,n);else{const o=S9(t);n==null||o&&!W_(n)?e.removeAttribute(t):e.setAttribute(t,o?\"\":n)}}function SF(e,t,n,r,a,o,i){if(t===\"innerHTML\"||t===\"textContent\"){r&&i(r,a,o),e[t]=n==null?\"\":n;return}if(t===\"value\"&&e.tagName!==\"PROGRESS\"&&!e.tagName.includes(\"-\")){e._value=n;const l=n==null?\"\":n;(e.value!==l||e.tagName===\"OPTION\")&&(e.value=l),n==null&&e.removeAttribute(t);return}if(n===\"\"||n==null){const l=typeof e[t];if(l===\"boolean\"){e[t]=W_(n);return}else if(n==null&&l===\"string\"){e[t]=\"\",e.removeAttribute(t);return}else if(l===\"number\"){try{e[t]=0}catch{}e.removeAttribute(t);return}}try{e[t]=n}catch{}}let cv=Date.now,Y6=!1;if(typeof window!=\"undefined\"){cv()>document.createEvent(\"Event\").timeStamp&&(cv=()=>performance.now());const e=navigator.userAgent.match(/firefox\\/(\\d+)/i);Y6=!!(e&&Number(e[1])<=53)}let Jb=0;const kF=Promise.resolve(),$F=()=>{Jb=0},OF=()=>Jb||(kF.then($F),Jb=cv());function Wi(e,t,n,r){e.addEventListener(t,n,r)}function PF(e,t,n,r){e.removeEventListener(t,n,r)}function TF(e,t,n,r,a=null){const o=e._vei||(e._vei={}),i=o[t];if(r&&i)i.value=r;else{const[l,s]=xF(t);if(r){const c=o[t]=_F(r,a);Wi(e,l,c,s)}else i&&(PF(e,l,i,s),o[t]=void 0)}}const Zk=/(?:Once|Passive|Capture)$/;function xF(e){let t;if(Zk.test(e)){t={};let n;for(;n=e.match(Zk);)e=e.slice(0,e.length-n[0].length),t[n[0].toLowerCase()]=!0}return[vl(e.slice(2)),t]}function _F(e,t){const n=r=>{const a=r.timeStamp||cv();(Y6||a>=n.attached-1)&&Pa(EF(r,n.value),t,5,[r])};return n.value=e,n.attached=OF(),n}function EF(e,t){if(pt(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>a=>!a._stopped&&r&&r(a))}else return t}const Jk=/^on[a-z]/,MF=(e,t,n,r,a=!1,o,i,l,s)=>{t===\"class\"?yF(e,r,a):t===\"style\"?bF(e,n,r):fm(t)?j1(t)||TF(e,t,n,r,i):(t[0]===\".\"?(t=t.slice(1),!0):t[0]===\"^\"?(t=t.slice(1),!1):IF(e,t,r,a))?SF(e,t,r,o,i,l,s):(t===\"true-value\"?e._trueValue=r:t===\"false-value\"&&(e._falseValue=r),wF(e,t,r,a))};function IF(e,t,n,r){return r?!!(t===\"innerHTML\"||t===\"textContent\"||t in e&&Jk.test(t)&&Ct(n)):t===\"spellcheck\"||t===\"draggable\"||t===\"form\"||t===\"list\"&&e.tagName===\"INPUT\"||t===\"type\"&&e.tagName===\"TEXTAREA\"||Jk.test(t)&&wt(n)?!1:t in e}const Di=\"transition\",Rc=\"animation\",Vn=(e,{slots:t})=>qe(k6,G6(e),t);Vn.displayName=\"Transition\";const q6={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},NF=Vn.props=fr({},k6.props,q6),Sl=(e,t=[])=>{pt(e)?e.forEach(n=>n(...t)):e&&e(...t)},Qk=e=>e?pt(e)?e.some(t=>t.length>1):e.length>1:!1;function G6(e){const t={};for(const F in e)F in q6||(t[F]=e[F]);if(e.css===!1)return t;const{name:n=\"v\",type:r,duration:a,enterFromClass:o=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:s=o,appearActiveClass:c=i,appearToClass:d=l,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:v=`${n}-leave-to`}=e,m=AF(a),y=m&&m[0],b=m&&m[1],{onBeforeEnter:C,onEnter:S,onEnterCancelled:w,onLeave:k,onLeaveCancelled:$,onBeforeAppear:O=C,onAppear:T=S,onAppearCancelled:_=w}=t,I=(F,N,D)=>{Il(F,N?d:l),Il(F,N?c:i),D&&D()},L=(F,N)=>{Il(F,v),Il(F,p),N&&N()},j=F=>(N,D)=>{const z=F?T:S,B=()=>I(N,F,D);Sl(z,[N,B]),e$(()=>{Il(N,F?s:o),Qo(N,F?d:l),Qk(z)||t$(N,r,y,B)})};return fr(t,{onBeforeEnter(F){Sl(C,[F]),Qo(F,o),Qo(F,i)},onBeforeAppear(F){Sl(O,[F]),Qo(F,s),Qo(F,c)},onEnter:j(!1),onAppear:j(!0),onLeave(F,N){const D=()=>L(F,N);Qo(F,f),Z6(),Qo(F,p),e$(()=>{Il(F,f),Qo(F,v),Qk(k)||t$(F,r,b,D)}),Sl(k,[F,D])},onEnterCancelled(F){I(F,!1),Sl(w,[F])},onAppearCancelled(F){I(F,!0),Sl(_,[F])},onLeaveCancelled(F){L(F),Sl($,[F])}})}function AF(e){if(e==null)return null;if(zt(e))return[Xg(e.enter),Xg(e.leave)];{const t=Xg(e);return[t,t]}}function Xg(e){return av(e)}function Qo(e,t){t.split(/\\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function Il(e,t){t.split(/\\s+/).forEach(r=>r&&e.classList.remove(r));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function e$(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let DF=0;function t$(e,t,n,r){const a=e._endId=++DF,o=()=>{a===e._endId&&r()};if(n)return setTimeout(o,n);const{type:i,timeout:l,propCount:s}=X6(e,t);if(!i)return r();const c=i+\"end\";let d=0;const f=()=>{e.removeEventListener(c,p),o()},p=v=>{v.target===e&&++d>=s&&f()};setTimeout(()=>{d<s&&f()},l+1),e.addEventListener(c,p)}function X6(e,t){const n=window.getComputedStyle(e),r=m=>(n[m]||\"\").split(\", \"),a=r(Di+\"Delay\"),o=r(Di+\"Duration\"),i=n$(a,o),l=r(Rc+\"Delay\"),s=r(Rc+\"Duration\"),c=n$(l,s);let d=null,f=0,p=0;t===Di?i>0&&(d=Di,f=i,p=o.length):t===Rc?c>0&&(d=Rc,f=c,p=s.length):(f=Math.max(i,c),d=f>0?i>c?Di:Rc:null,p=d?d===Di?o.length:s.length:0);const v=d===Di&&/\\b(transform|all)(,|$)/.test(n[Di+\"Property\"]);return{type:d,timeout:f,propCount:p,hasTransform:v}}function n$(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max(...t.map((n,r)=>r$(n)+r$(e[r])))}function r$(e){return Number(e.slice(0,-1).replace(\",\",\".\"))*1e3}function Z6(){return document.body.offsetHeight}const J6=new WeakMap,Q6=new WeakMap,RF={name:\"TransitionGroup\",props:fr({},NF,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=$t(),r=S6();let a,o;return ur(()=>{if(!a.length)return;const i=e.moveClass||`${e.name||\"v\"}-move`;if(!VF(a[0].el,n.vnode.el,i))return;a.forEach(LF),a.forEach(FF);const l=a.filter(BF);Z6(),l.forEach(s=>{const c=s.el,d=c.style;Qo(c,i),d.transform=d.webkitTransform=d.transitionDuration=\"\";const f=c._moveCb=p=>{p&&p.target!==c||(!p||/transform$/.test(p.propertyName))&&(c.removeEventListener(\"transitionend\",f),c._moveCb=null,Il(c,i))};c.addEventListener(\"transitionend\",f)})}),()=>{const i=Gt(e),l=G6(i);let s=i.tag||Fe;a=o,o=t.default?iC(t.default()):[];for(let c=0;c<o.length;c++){const d=o[c];d.key!=null&&Rd(d,Dd(d,l,r,n))}if(a)for(let c=0;c<a.length;c++){const d=a[c];Rd(d,Dd(d,l,r,n)),J6.set(d,d.el.getBoundingClientRect())}return g(s,null,o)}}},e8=RF;function LF(e){const t=e.el;t._moveCb&&t._moveCb(),t._enterCb&&t._enterCb()}function FF(e){Q6.set(e,e.el.getBoundingClientRect())}function BF(e){const t=J6.get(e),n=Q6.get(e),r=t.left-n.left,a=t.top-n.top;if(r||a){const o=e.el.style;return o.transform=o.webkitTransform=`translate(${r}px,${a}px)`,o.transitionDuration=\"0s\",e}}function VF(e,t,n){const r=e.cloneNode();e._vtc&&e._vtc.forEach(i=>{i.split(/\\s+/).forEach(l=>l&&r.classList.remove(l))}),n.split(/\\s+/).forEach(i=>i&&r.classList.add(i)),r.style.display=\"none\";const a=t.nodeType===1?t:t.parentNode;a.appendChild(r);const{hasTransform:o}=X6(r);return a.removeChild(r),o}const Hu=e=>{const t=e.props[\"onUpdate:modelValue\"];return pt(t)?n=>op(t,n):t};function zF(e){e.target.composing=!0}function a$(e){const t=e.target;t.composing&&(t.composing=!1,HF(t,\"input\"))}function HF(e,t){const n=document.createEvent(\"HTMLEvents\");n.initEvent(t,!0,!0),e.dispatchEvent(n)}const fC={created(e,{modifiers:{lazy:t,trim:n,number:r}},a){e._assign=Hu(a);const o=r||a.props&&a.props.type===\"number\";Wi(e,t?\"change\":\"input\",i=>{if(i.target.composing)return;let l=e.value;n?l=l.trim():o&&(l=av(l)),e._assign(l)}),n&&Wi(e,\"change\",()=>{e.value=e.value.trim()}),t||(Wi(e,\"compositionstart\",zF),Wi(e,\"compositionend\",a$),Wi(e,\"change\",a$))},mounted(e,{value:t}){e.value=t==null?\"\":t},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:a}},o){if(e._assign=Hu(o),e.composing||document.activeElement===e&&(n||r&&e.value.trim()===t||(a||e.type===\"number\")&&av(e.value)===t))return;const i=t==null?\"\":t;e.value!==i&&(e.value=i)}},dv={deep:!0,created(e,t,n){e._assign=Hu(n),Wi(e,\"change\",()=>{const r=e._modelValue,a=n8(e),o=e.checked,i=e._assign;if(pt(r)){const l=U_(r,a),s=l!==-1;if(o&&!s)i(r.concat(a));else if(!o&&s){const c=[...r];c.splice(l,1),i(c)}}else if(hm(r)){const l=new Set(r);o?l.add(a):l.delete(a),i(l)}else i(r8(e,o))})},mounted:o$,beforeUpdate(e,t,n){e._assign=Hu(n),o$(e,t,n)}};function o$(e,{value:t,oldValue:n},r){e._modelValue=t,pt(t)?e.checked=U_(t,r.props.value)>-1:hm(t)?e.checked=t.has(r.props.value):t!==n&&(e.checked=Vu(t,r8(e,!0)))}const t8={created(e,{value:t},n){e.checked=Vu(t,n.props.value),e._assign=Hu(n),Wi(e,\"change\",()=>{e._assign(n8(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e._assign=Hu(r),t!==n&&(e.checked=Vu(t,r.props.value))}};function n8(e){return\"_value\"in e?e._value:e.value}function r8(e,t){const n=t?\"_trueValue\":\"_falseValue\";return n in e?e[n]:t}const jF=[\"ctrl\",\"shift\",\"alt\",\"meta\"],KF={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>\"button\"in e&&e.button!==0,middle:e=>\"button\"in e&&e.button!==1,right:e=>\"button\"in e&&e.button!==2,exact:(e,t)=>jF.some(n=>e[`${n}Key`]&&!t.includes(n))},dt=(e,t)=>(n,...r)=>{for(let a=0;a<t.length;a++){const o=KF[t[a]];if(o&&o(n,t))return}return e(n,...r)},WF={esc:\"escape\",space:\" \",up:\"arrow-up\",left:\"arrow-left\",right:\"arrow-right\",down:\"arrow-down\",delete:\"backspace\"},It=(e,t)=>n=>{if(!(\"key\"in n))return;const r=vl(n.key);if(t.some(a=>a===r||WF[a]===r))return e(n)},_t={beforeMount(e,{value:t},{transition:n}){e._vod=e.style.display===\"none\"?\"\":e.style.display,n&&t?n.beforeEnter(e):Lc(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Lc(e,!0),r.enter(e)):r.leave(e,()=>{Lc(e,!1)}):Lc(e,t))},beforeUnmount(e,{value:t}){Lc(e,t)}};function Lc(e,t){e.style.display=t?e._vod:\"none\"}const UF=fr({patchProp:MF},gF);let i$;function a8(){return i$||(i$=GL(UF))}const vs=(...e)=>{a8().render(...e)},$m=(...e)=>{const t=a8().createApp(...e),{mount:n}=t;return t.mount=r=>{const a=YF(r);if(!a)return;const o=t._component;!Ct(o)&&!o.render&&!o.template&&(o.template=a.innerHTML),a.innerHTML=\"\";const i=n(a,!1,a instanceof SVGElement);return a instanceof Element&&(a.removeAttribute(\"v-cloak\"),a.setAttribute(\"data-v-app\",\"\")),i},t};function YF(e){return wt(e)?document.querySelector(e):e}var qF=typeof global==\"object\"&&global&&global.Object===Object&&global,o8=qF,GF=typeof self==\"object\"&&self&&self.Object===Object&&self,XF=o8||GF||Function(\"return this\")(),fo=XF,ZF=fo.Symbol,Ea=ZF,i8=Object.prototype,JF=i8.hasOwnProperty,QF=i8.toString,Fc=Ea?Ea.toStringTag:void 0;function eB(e){var t=JF.call(e,Fc),n=e[Fc];try{e[Fc]=void 0;var r=!0}catch{}var a=QF.call(e);return r&&(t?e[Fc]=n:delete e[Fc]),a}var tB=Object.prototype,nB=tB.toString;function rB(e){return nB.call(e)}var aB=\"[object Null]\",oB=\"[object Undefined]\",l$=Ea?Ea.toStringTag:void 0;function ml(e){return e==null?e===void 0?oB:aB:l$&&l$ in Object(e)?eB(e):rB(e)}function ao(e){return e!=null&&typeof e==\"object\"}var iB=\"[object Symbol]\";function Om(e){return typeof e==\"symbol\"||ao(e)&&ml(e)==iB}function Pm(e,t){for(var n=-1,r=e==null?0:e.length,a=Array(r);++n<r;)a[n]=t(e[n],n,e);return a}var lB=Array.isArray,Nr=lB,sB=1/0,s$=Ea?Ea.prototype:void 0,u$=s$?s$.toString:void 0;function hC(e){if(typeof e==\"string\")return e;if(Nr(e))return Pm(e,hC)+\"\";if(Om(e))return u$?u$.call(e):\"\";var t=e+\"\";return t==\"0\"&&1/e==-sB?\"-0\":t}var uB=/\\s/;function cB(e){for(var t=e.length;t--&&uB.test(e.charAt(t)););return t}var dB=/^\\s+/;function fB(e){return e&&e.slice(0,cB(e)+1).replace(dB,\"\")}function Ar(e){var t=typeof e;return e!=null&&(t==\"object\"||t==\"function\")}var c$=0/0,hB=/^[-+]0x[0-9a-f]+$/i,pB=/^0b[01]+$/i,vB=/^0o[0-7]+$/i,mB=parseInt;function Qb(e){if(typeof e==\"number\")return e;if(Om(e))return c$;if(Ar(e)){var t=typeof e.valueOf==\"function\"?e.valueOf():e;e=Ar(t)?t+\"\":t}if(typeof e!=\"string\")return e===0?e:+e;e=fB(e);var n=pB.test(e);return n||vB.test(e)?mB(e.slice(2),n?2:8):hB.test(e)?c$:+e}var d$=1/0,gB=17976931348623157e292;function yB(e){if(!e)return e===0?e:0;if(e=Qb(e),e===d$||e===-d$){var t=e<0?-1:1;return t*gB}return e===e?e:0}function Tm(e){var t=yB(e),n=t%1;return t===t?n?t-n:t:0}function pC(e){return e}var bB=\"[object AsyncFunction]\",CB=\"[object Function]\",wB=\"[object GeneratorFunction]\",SB=\"[object Proxy]\";function vC(e){if(!Ar(e))return!1;var t=ml(e);return t==CB||t==wB||t==bB||t==SB}var kB=fo[\"__core-js_shared__\"],Zg=kB,f$=function(){var e=/[^.]+$/.exec(Zg&&Zg.keys&&Zg.keys.IE_PROTO||\"\");return e?\"Symbol(src)_1.\"+e:\"\"}();function $B(e){return!!f$&&f$ in e}var OB=Function.prototype,PB=OB.toString;function Ts(e){if(e!=null){try{return PB.call(e)}catch{}try{return e+\"\"}catch{}}return\"\"}var TB=/[\\\\^$.*+?()[\\]{}|]/g,xB=/^\\[object .+?Constructor\\]$/,_B=Function.prototype,EB=Object.prototype,MB=_B.toString,IB=EB.hasOwnProperty,NB=RegExp(\"^\"+MB.call(IB).replace(TB,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\");function AB(e){if(!Ar(e)||$B(e))return!1;var t=vC(e)?NB:xB;return t.test(Ts(e))}function DB(e,t){return e==null?void 0:e[t]}function xs(e,t){var n=DB(e,t);return AB(n)?n:void 0}var RB=xs(fo,\"WeakMap\"),e0=RB,h$=Object.create,LB=function(){function e(){}return function(t){if(!Ar(t))return{};if(h$)return h$(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}(),FB=LB;function BB(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function VB(){}function l8(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n<r;)t[n]=e[n];return t}var zB=800,HB=16,jB=Date.now;function KB(e){var t=0,n=0;return function(){var r=jB(),a=HB-(r-n);if(n=r,a>0){if(++t>=zB)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function WB(e){return function(){return e}}var UB=function(){try{var e=xs(Object,\"defineProperty\");return e({},\"\",{}),e}catch{}}(),fv=UB,YB=fv?function(e,t){return fv(e,\"toString\",{configurable:!0,enumerable:!1,value:WB(t),writable:!0})}:pC,qB=YB,GB=KB(qB),s8=GB;function XB(e,t){for(var n=-1,r=e==null?0:e.length;++n<r&&t(e[n],n,e)!==!1;);return e}function u8(e,t,n,r){for(var a=e.length,o=n+(r?1:-1);r?o--:++o<a;)if(t(e[o],o,e))return o;return-1}function ZB(e){return e!==e}function JB(e,t,n){for(var r=n-1,a=e.length;++r<a;)if(e[r]===t)return r;return-1}function c8(e,t,n){return t===t?JB(e,t,n):u8(e,ZB,n)}function d8(e,t){var n=e==null?0:e.length;return!!n&&c8(e,t,0)>-1}var QB=9007199254740991,eV=/^(?:0|[1-9]\\d*)$/;function xm(e,t){var n=typeof e;return t=t==null?QB:t,!!t&&(n==\"number\"||n!=\"symbol\"&&eV.test(e))&&e>-1&&e%1==0&&e<t}function mC(e,t,n){t==\"__proto__\"&&fv?fv(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}function Sf(e,t){return e===t||e!==e&&t!==t}var tV=Object.prototype,nV=tV.hasOwnProperty;function gC(e,t,n){var r=e[t];(!(nV.call(e,t)&&Sf(r,n))||n===void 0&&!(t in e))&&mC(e,t,n)}function pc(e,t,n,r){var a=!n;n||(n={});for(var o=-1,i=t.length;++o<i;){var l=t[o],s=r?r(n[l],e[l],l,n,e):void 0;s===void 0&&(s=e[l]),a?mC(n,l,s):gC(n,l,s)}return n}var p$=Math.max;function f8(e,t,n){return t=p$(t===void 0?e.length-1:t,0),function(){for(var r=arguments,a=-1,o=p$(r.length-t,0),i=Array(o);++a<o;)i[a]=r[t+a];a=-1;for(var l=Array(t+1);++a<t;)l[a]=r[a];return l[t]=n(i),BB(e,this,l)}}function yC(e,t){return s8(f8(e,t,pC),e+\"\")}var rV=9007199254740991;function bC(e){return typeof e==\"number\"&&e>-1&&e%1==0&&e<=rV}function vc(e){return e!=null&&bC(e.length)&&!vC(e)}function aV(e,t,n){if(!Ar(n))return!1;var r=typeof t;return(r==\"number\"?vc(n)&&xm(t,n.length):r==\"string\"&&t in n)?Sf(n[t],e):!1}function oV(e){return yC(function(t,n){var r=-1,a=n.length,o=a>1?n[a-1]:void 0,i=a>2?n[2]:void 0;for(o=e.length>3&&typeof o==\"function\"?(a--,o):void 0,i&&aV(n[0],n[1],i)&&(o=a<3?void 0:o,a=1),t=Object(t);++r<a;){var l=n[r];l&&e(t,l,r,o)}return t})}var iV=Object.prototype;function CC(e){var t=e&&e.constructor,n=typeof t==\"function\"&&t.prototype||iV;return e===n}function lV(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}var sV=\"[object Arguments]\";function v$(e){return ao(e)&&ml(e)==sV}var h8=Object.prototype,uV=h8.hasOwnProperty,cV=h8.propertyIsEnumerable,dV=v$(function(){return arguments}())?v$:function(e){return ao(e)&&uV.call(e,\"callee\")&&!cV.call(e,\"callee\")},Fd=dV;function fV(){return!1}var p8=typeof fa==\"object\"&&fa&&!fa.nodeType&&fa,m$=p8&&typeof Sr==\"object\"&&Sr&&!Sr.nodeType&&Sr,hV=m$&&m$.exports===p8,g$=hV?fo.Buffer:void 0,pV=g$?g$.isBuffer:void 0,vV=pV||fV,Bd=vV,mV=\"[object Arguments]\",gV=\"[object Array]\",yV=\"[object Boolean]\",bV=\"[object Date]\",CV=\"[object Error]\",wV=\"[object Function]\",SV=\"[object Map]\",kV=\"[object Number]\",$V=\"[object Object]\",OV=\"[object RegExp]\",PV=\"[object Set]\",TV=\"[object String]\",xV=\"[object WeakMap]\",_V=\"[object ArrayBuffer]\",EV=\"[object DataView]\",MV=\"[object Float32Array]\",IV=\"[object Float64Array]\",NV=\"[object Int8Array]\",AV=\"[object Int16Array]\",DV=\"[object Int32Array]\",RV=\"[object Uint8Array]\",LV=\"[object Uint8ClampedArray]\",FV=\"[object Uint16Array]\",BV=\"[object Uint32Array]\",In={};In[MV]=In[IV]=In[NV]=In[AV]=In[DV]=In[RV]=In[LV]=In[FV]=In[BV]=!0;In[mV]=In[gV]=In[_V]=In[yV]=In[EV]=In[bV]=In[CV]=In[wV]=In[SV]=In[kV]=In[$V]=In[OV]=In[PV]=In[TV]=In[xV]=!1;function VV(e){return ao(e)&&bC(e.length)&&!!In[ml(e)]}function _m(e){return function(t){return e(t)}}var v8=typeof fa==\"object\"&&fa&&!fa.nodeType&&fa,pd=v8&&typeof Sr==\"object\"&&Sr&&!Sr.nodeType&&Sr,zV=pd&&pd.exports===v8,Jg=zV&&o8.process,HV=function(){try{var e=pd&&pd.require&&pd.require(\"util\").types;return e||Jg&&Jg.binding&&Jg.binding(\"util\")}catch{}}(),ju=HV,y$=ju&&ju.isTypedArray,jV=y$?_m(y$):VV,wC=jV,KV=Object.prototype,WV=KV.hasOwnProperty;function m8(e,t){var n=Nr(e),r=!n&&Fd(e),a=!n&&!r&&Bd(e),o=!n&&!r&&!a&&wC(e),i=n||r||a||o,l=i?lV(e.length,String):[],s=l.length;for(var c in e)(t||WV.call(e,c))&&!(i&&(c==\"length\"||a&&(c==\"offset\"||c==\"parent\")||o&&(c==\"buffer\"||c==\"byteLength\"||c==\"byteOffset\")||xm(c,s)))&&l.push(c);return l}function g8(e,t){return function(n){return e(t(n))}}var UV=g8(Object.keys,Object),YV=UV,qV=Object.prototype,GV=qV.hasOwnProperty;function XV(e){if(!CC(e))return YV(e);var t=[];for(var n in Object(e))GV.call(e,n)&&n!=\"constructor\"&&t.push(n);return t}function mc(e){return vc(e)?m8(e):XV(e)}function ZV(e){var t=[];if(e!=null)for(var n in Object(e))t.push(n);return t}var JV=Object.prototype,QV=JV.hasOwnProperty;function ez(e){if(!Ar(e))return ZV(e);var t=CC(e),n=[];for(var r in e)r==\"constructor\"&&(t||!QV.call(e,r))||n.push(r);return n}function kf(e){return vc(e)?m8(e,!0):ez(e)}var tz=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,nz=/^\\w*$/;function SC(e,t){if(Nr(e))return!1;var n=typeof e;return n==\"number\"||n==\"symbol\"||n==\"boolean\"||e==null||Om(e)?!0:nz.test(e)||!tz.test(e)||t!=null&&e in Object(t)}var rz=xs(Object,\"create\"),Vd=rz;function az(){this.__data__=Vd?Vd(null):{},this.size=0}function oz(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}var iz=\"__lodash_hash_undefined__\",lz=Object.prototype,sz=lz.hasOwnProperty;function uz(e){var t=this.__data__;if(Vd){var n=t[e];return n===iz?void 0:n}return sz.call(t,e)?t[e]:void 0}var cz=Object.prototype,dz=cz.hasOwnProperty;function fz(e){var t=this.__data__;return Vd?t[e]!==void 0:dz.call(t,e)}var hz=\"__lodash_hash_undefined__\";function pz(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=Vd&&t===void 0?hz:t,this}function ms(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}ms.prototype.clear=az;ms.prototype.delete=oz;ms.prototype.get=uz;ms.prototype.has=fz;ms.prototype.set=pz;function vz(){this.__data__=[],this.size=0}function Em(e,t){for(var n=e.length;n--;)if(Sf(e[n][0],t))return n;return-1}var mz=Array.prototype,gz=mz.splice;function yz(e){var t=this.__data__,n=Em(t,e);if(n<0)return!1;var r=t.length-1;return n==r?t.pop():gz.call(t,n,1),--this.size,!0}function bz(e){var t=this.__data__,n=Em(t,e);return n<0?void 0:t[n][1]}function Cz(e){return Em(this.__data__,e)>-1}function wz(e,t){var n=this.__data__,r=Em(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}function $i(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}$i.prototype.clear=vz;$i.prototype.delete=yz;$i.prototype.get=bz;$i.prototype.has=Cz;$i.prototype.set=wz;var Sz=xs(fo,\"Map\"),zd=Sz;function kz(){this.size=0,this.__data__={hash:new ms,map:new(zd||$i),string:new ms}}function $z(e){var t=typeof e;return t==\"string\"||t==\"number\"||t==\"symbol\"||t==\"boolean\"?e!==\"__proto__\":e===null}function Mm(e,t){var n=e.__data__;return $z(t)?n[typeof t==\"string\"?\"string\":\"hash\"]:n.map}function Oz(e){var t=Mm(this,e).delete(e);return this.size-=t?1:0,t}function Pz(e){return Mm(this,e).get(e)}function Tz(e){return Mm(this,e).has(e)}function xz(e,t){var n=Mm(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}function Oi(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}Oi.prototype.clear=kz;Oi.prototype.delete=Oz;Oi.prototype.get=Pz;Oi.prototype.has=Tz;Oi.prototype.set=xz;var _z=\"Expected a function\";function Im(e,t){if(typeof e!=\"function\"||t!=null&&typeof t!=\"function\")throw new TypeError(_z);var n=function(){var r=arguments,a=t?t.apply(this,r):r[0],o=n.cache;if(o.has(a))return o.get(a);var i=e.apply(this,r);return n.cache=o.set(a,i)||o,i};return n.cache=new(Im.Cache||Oi),n}Im.Cache=Oi;var Ez=500;function Mz(e){var t=Im(e,function(r){return n.size===Ez&&n.clear(),r}),n=t.cache;return t}var Iz=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,Nz=/\\\\(\\\\)?/g,Az=Mz(function(e){var t=[];return e.charCodeAt(0)===46&&t.push(\"\"),e.replace(Iz,function(n,r,a,o){t.push(a?o.replace(Nz,\"$1\"):r||n)}),t}),Dz=Az;function kC(e){return e==null?\"\":hC(e)}function gc(e,t){return Nr(e)?e:SC(e,t)?[e]:Dz(kC(e))}var Rz=1/0;function yc(e){if(typeof e==\"string\"||Om(e))return e;var t=e+\"\";return t==\"0\"&&1/e==-Rz?\"-0\":t}function Nm(e,t){t=gc(t,e);for(var n=0,r=t.length;e!=null&&n<r;)e=e[yc(t[n++])];return n&&n==r?e:void 0}function vn(e,t,n){var r=e==null?void 0:Nm(e,t);return r===void 0?n:r}function $C(e,t){for(var n=-1,r=t.length,a=e.length;++n<r;)e[a+n]=t[n];return e}var b$=Ea?Ea.isConcatSpreadable:void 0;function Lz(e){return Nr(e)||Fd(e)||!!(b$&&e&&e[b$])}function Am(e,t,n,r,a){var o=-1,i=e.length;for(n||(n=Lz),a||(a=[]);++o<i;){var l=e[o];t>0&&n(l)?t>1?Am(l,t-1,n,r,a):$C(a,l):r||(a[a.length]=l)}return a}function Fz(e){var t=e==null?0:e.length;return t?Am(e,1):[]}function y8(e){return s8(f8(e,void 0,Fz),e+\"\")}var Bz=g8(Object.getPrototypeOf,Object),OC=Bz,Vz=\"[object Object]\",zz=Function.prototype,Hz=Object.prototype,b8=zz.toString,jz=Hz.hasOwnProperty,Kz=b8.call(Object);function bc(e){if(!ao(e)||ml(e)!=Vz)return!1;var t=OC(e);if(t===null)return!0;var n=jz.call(t,\"constructor\")&&t.constructor;return typeof n==\"function\"&&n instanceof n&&b8.call(n)==Kz}function C8(e,t,n){var r=-1,a=e.length;t<0&&(t=-t>a?0:a+t),n=n>a?a:n,n<0&&(n+=a),a=t>n?0:n-t>>>0,t>>>=0;for(var o=Array(a);++r<a;)o[r]=e[r+t];return o}function Wz(e,t,n){var r=e.length;return n=n===void 0?r:n,!t&&n>=r?e:C8(e,t,n)}var Uz=\"\\\\ud800-\\\\udfff\",Yz=\"\\\\u0300-\\\\u036f\",qz=\"\\\\ufe20-\\\\ufe2f\",Gz=\"\\\\u20d0-\\\\u20ff\",Xz=Yz+qz+Gz,Zz=\"\\\\ufe0e\\\\ufe0f\",Jz=\"\\\\u200d\",Qz=RegExp(\"[\"+Jz+Uz+Xz+Zz+\"]\");function PC(e){return Qz.test(e)}function eH(e){return e.split(\"\")}var w8=\"\\\\ud800-\\\\udfff\",tH=\"\\\\u0300-\\\\u036f\",nH=\"\\\\ufe20-\\\\ufe2f\",rH=\"\\\\u20d0-\\\\u20ff\",aH=tH+nH+rH,oH=\"\\\\ufe0e\\\\ufe0f\",iH=\"[\"+w8+\"]\",t0=\"[\"+aH+\"]\",n0=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",lH=\"(?:\"+t0+\"|\"+n0+\")\",S8=\"[^\"+w8+\"]\",k8=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",$8=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",sH=\"\\\\u200d\",O8=lH+\"?\",P8=\"[\"+oH+\"]?\",uH=\"(?:\"+sH+\"(?:\"+[S8,k8,$8].join(\"|\")+\")\"+P8+O8+\")*\",cH=P8+O8+uH,dH=\"(?:\"+[S8+t0+\"?\",t0,k8,$8,iH].join(\"|\")+\")\",fH=RegExp(n0+\"(?=\"+n0+\")|\"+dH+cH,\"g\");function hH(e){return e.match(fH)||[]}function pH(e){return PC(e)?hH(e):eH(e)}function Hd(){if(!arguments.length)return[];var e=arguments[0];return Nr(e)?e:[e]}function vH(){this.__data__=new $i,this.size=0}function mH(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}function gH(e){return this.__data__.get(e)}function yH(e){return this.__data__.has(e)}var bH=200;function CH(e,t){var n=this.__data__;if(n instanceof $i){var r=n.__data__;if(!zd||r.length<bH-1)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Oi(r)}return n.set(e,t),this.size=n.size,this}function Qa(e){var t=this.__data__=new $i(e);this.size=t.size}Qa.prototype.clear=vH;Qa.prototype.delete=mH;Qa.prototype.get=gH;Qa.prototype.has=yH;Qa.prototype.set=CH;function wH(e,t){return e&&pc(t,mc(t),e)}function SH(e,t){return e&&pc(t,kf(t),e)}var T8=typeof fa==\"object\"&&fa&&!fa.nodeType&&fa,C$=T8&&typeof Sr==\"object\"&&Sr&&!Sr.nodeType&&Sr,kH=C$&&C$.exports===T8,w$=kH?fo.Buffer:void 0,S$=w$?w$.allocUnsafe:void 0;function x8(e,t){if(t)return e.slice();var n=e.length,r=S$?S$(n):new e.constructor(n);return e.copy(r),r}function $H(e,t){for(var n=-1,r=e==null?0:e.length,a=0,o=[];++n<r;){var i=e[n];t(i,n,e)&&(o[a++]=i)}return o}function _8(){return[]}var OH=Object.prototype,PH=OH.propertyIsEnumerable,k$=Object.getOwnPropertySymbols,TH=k$?function(e){return e==null?[]:(e=Object(e),$H(k$(e),function(t){return PH.call(e,t)}))}:_8,TC=TH;function xH(e,t){return pc(e,TC(e),t)}var _H=Object.getOwnPropertySymbols,EH=_H?function(e){for(var t=[];e;)$C(t,TC(e)),e=OC(e);return t}:_8,E8=EH;function MH(e,t){return pc(e,E8(e),t)}function M8(e,t,n){var r=t(e);return Nr(e)?r:$C(r,n(e))}function r0(e){return M8(e,mc,TC)}function I8(e){return M8(e,kf,E8)}var IH=xs(fo,\"DataView\"),a0=IH,NH=xs(fo,\"Promise\"),o0=NH,AH=xs(fo,\"Set\"),Ou=AH,$$=\"[object Map]\",DH=\"[object Object]\",O$=\"[object Promise]\",P$=\"[object Set]\",T$=\"[object WeakMap]\",x$=\"[object DataView]\",RH=Ts(a0),LH=Ts(zd),FH=Ts(o0),BH=Ts(Ou),VH=Ts(e0),Nl=ml;(a0&&Nl(new a0(new ArrayBuffer(1)))!=x$||zd&&Nl(new zd)!=$$||o0&&Nl(o0.resolve())!=O$||Ou&&Nl(new Ou)!=P$||e0&&Nl(new e0)!=T$)&&(Nl=function(e){var t=ml(e),n=t==DH?e.constructor:void 0,r=n?Ts(n):\"\";if(r)switch(r){case RH:return x$;case LH:return $$;case FH:return O$;case BH:return P$;case VH:return T$}return t});var jd=Nl,zH=Object.prototype,HH=zH.hasOwnProperty;function jH(e){var t=e.length,n=new e.constructor(t);return t&&typeof e[0]==\"string\"&&HH.call(e,\"index\")&&(n.index=e.index,n.input=e.input),n}var KH=fo.Uint8Array,hv=KH;function xC(e){var t=new e.constructor(e.byteLength);return new hv(t).set(new hv(e)),t}function WH(e,t){var n=t?xC(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}var UH=/\\w*$/;function YH(e){var t=new e.constructor(e.source,UH.exec(e));return t.lastIndex=e.lastIndex,t}var _$=Ea?Ea.prototype:void 0,E$=_$?_$.valueOf:void 0;function qH(e){return E$?Object(E$.call(e)):{}}function N8(e,t){var n=t?xC(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}var GH=\"[object Boolean]\",XH=\"[object Date]\",ZH=\"[object Map]\",JH=\"[object Number]\",QH=\"[object RegExp]\",ej=\"[object Set]\",tj=\"[object String]\",nj=\"[object Symbol]\",rj=\"[object ArrayBuffer]\",aj=\"[object DataView]\",oj=\"[object Float32Array]\",ij=\"[object Float64Array]\",lj=\"[object Int8Array]\",sj=\"[object Int16Array]\",uj=\"[object Int32Array]\",cj=\"[object Uint8Array]\",dj=\"[object Uint8ClampedArray]\",fj=\"[object Uint16Array]\",hj=\"[object Uint32Array]\";function pj(e,t,n){var r=e.constructor;switch(t){case rj:return xC(e);case GH:case XH:return new r(+e);case aj:return WH(e,n);case oj:case ij:case lj:case sj:case uj:case cj:case dj:case fj:case hj:return N8(e,n);case ZH:return new r;case JH:case tj:return new r(e);case QH:return YH(e);case ej:return new r;case nj:return qH(e)}}function A8(e){return typeof e.constructor==\"function\"&&!CC(e)?FB(OC(e)):{}}var vj=\"[object Map]\";function mj(e){return ao(e)&&jd(e)==vj}var M$=ju&&ju.isMap,gj=M$?_m(M$):mj,yj=gj,bj=\"[object Set]\";function Cj(e){return ao(e)&&jd(e)==bj}var I$=ju&&ju.isSet,wj=I$?_m(I$):Cj,Sj=wj,kj=1,$j=2,Oj=4,D8=\"[object Arguments]\",Pj=\"[object Array]\",Tj=\"[object Boolean]\",xj=\"[object Date]\",_j=\"[object Error]\",R8=\"[object Function]\",Ej=\"[object GeneratorFunction]\",Mj=\"[object Map]\",Ij=\"[object Number]\",L8=\"[object Object]\",Nj=\"[object RegExp]\",Aj=\"[object Set]\",Dj=\"[object String]\",Rj=\"[object Symbol]\",Lj=\"[object WeakMap]\",Fj=\"[object ArrayBuffer]\",Bj=\"[object DataView]\",Vj=\"[object Float32Array]\",zj=\"[object Float64Array]\",Hj=\"[object Int8Array]\",jj=\"[object Int16Array]\",Kj=\"[object Int32Array]\",Wj=\"[object Uint8Array]\",Uj=\"[object Uint8ClampedArray]\",Yj=\"[object Uint16Array]\",qj=\"[object Uint32Array]\",Pn={};Pn[D8]=Pn[Pj]=Pn[Fj]=Pn[Bj]=Pn[Tj]=Pn[xj]=Pn[Vj]=Pn[zj]=Pn[Hj]=Pn[jj]=Pn[Kj]=Pn[Mj]=Pn[Ij]=Pn[L8]=Pn[Nj]=Pn[Aj]=Pn[Dj]=Pn[Rj]=Pn[Wj]=Pn[Uj]=Pn[Yj]=Pn[qj]=!0;Pn[_j]=Pn[R8]=Pn[Lj]=!1;function Pu(e,t,n,r,a,o){var i,l=t&kj,s=t&$j,c=t&Oj;if(n&&(i=a?n(e,r,a,o):n(e)),i!==void 0)return i;if(!Ar(e))return e;var d=Nr(e);if(d){if(i=jH(e),!l)return l8(e,i)}else{var f=jd(e),p=f==R8||f==Ej;if(Bd(e))return x8(e,l);if(f==L8||f==D8||p&&!a){if(i=s||p?{}:A8(e),!l)return s?MH(e,SH(i,e)):xH(e,wH(i,e))}else{if(!Pn[f])return a?e:{};i=pj(e,f,l)}}o||(o=new Qa);var v=o.get(e);if(v)return v;o.set(e,i),Sj(e)?e.forEach(function(b){i.add(Pu(b,t,n,b,e,o))}):yj(e)&&e.forEach(function(b,C){i.set(C,Pu(b,t,n,C,e,o))});var m=c?s?I8:r0:s?kf:mc,y=d?void 0:m(e);return XB(y||e,function(b,C){y&&(C=b,b=e[C]),gC(i,C,Pu(b,t,n,C,e,o))}),i}var Gj=4;function Xj(e){return Pu(e,Gj)}var Zj=1,Jj=4;function lp(e){return Pu(e,Zj|Jj)}var Qj=\"__lodash_hash_undefined__\";function eK(e){return this.__data__.set(e,Qj),this}function tK(e){return this.__data__.has(e)}function Ku(e){var t=-1,n=e==null?0:e.length;for(this.__data__=new Oi;++t<n;)this.add(e[t])}Ku.prototype.add=Ku.prototype.push=eK;Ku.prototype.has=tK;function nK(e,t){for(var n=-1,r=e==null?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1}function pv(e,t){return e.has(t)}var rK=1,aK=2;function F8(e,t,n,r,a,o){var i=n&rK,l=e.length,s=t.length;if(l!=s&&!(i&&s>l))return!1;var c=o.get(e),d=o.get(t);if(c&&d)return c==t&&d==e;var f=-1,p=!0,v=n&aK?new Ku:void 0;for(o.set(e,t),o.set(t,e);++f<l;){var m=e[f],y=t[f];if(r)var b=i?r(y,m,f,t,e,o):r(m,y,f,e,t,o);if(b!==void 0){if(b)continue;p=!1;break}if(v){if(!nK(t,function(C,S){if(!pv(v,S)&&(m===C||a(m,C,n,r,o)))return v.push(S)})){p=!1;break}}else if(!(m===y||a(m,y,n,r,o))){p=!1;break}}return o.delete(e),o.delete(t),p}function oK(e){var t=-1,n=Array(e.size);return e.forEach(function(r,a){n[++t]=[a,r]}),n}function _C(e){var t=-1,n=Array(e.size);return e.forEach(function(r){n[++t]=r}),n}var iK=1,lK=2,sK=\"[object Boolean]\",uK=\"[object Date]\",cK=\"[object Error]\",dK=\"[object Map]\",fK=\"[object Number]\",hK=\"[object RegExp]\",pK=\"[object Set]\",vK=\"[object String]\",mK=\"[object Symbol]\",gK=\"[object ArrayBuffer]\",yK=\"[object DataView]\",N$=Ea?Ea.prototype:void 0,Qg=N$?N$.valueOf:void 0;function bK(e,t,n,r,a,o,i){switch(n){case yK:if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case gK:return!(e.byteLength!=t.byteLength||!o(new hv(e),new hv(t)));case sK:case uK:case fK:return Sf(+e,+t);case cK:return e.name==t.name&&e.message==t.message;case hK:case vK:return e==t+\"\";case dK:var l=oK;case pK:var s=r&iK;if(l||(l=_C),e.size!=t.size&&!s)return!1;var c=i.get(e);if(c)return c==t;r|=lK,i.set(e,t);var d=F8(l(e),l(t),r,a,o,i);return i.delete(e),d;case mK:if(Qg)return Qg.call(e)==Qg.call(t)}return!1}var CK=1,wK=Object.prototype,SK=wK.hasOwnProperty;function kK(e,t,n,r,a,o){var i=n&CK,l=r0(e),s=l.length,c=r0(t),d=c.length;if(s!=d&&!i)return!1;for(var f=s;f--;){var p=l[f];if(!(i?p in t:SK.call(t,p)))return!1}var v=o.get(e),m=o.get(t);if(v&&m)return v==t&&m==e;var y=!0;o.set(e,t),o.set(t,e);for(var b=i;++f<s;){p=l[f];var C=e[p],S=t[p];if(r)var w=i?r(S,C,p,t,e,o):r(C,S,p,e,t,o);if(!(w===void 0?C===S||a(C,S,n,r,o):w)){y=!1;break}b||(b=p==\"constructor\")}if(y&&!b){var k=e.constructor,$=t.constructor;k!=$&&\"constructor\"in e&&\"constructor\"in t&&!(typeof k==\"function\"&&k instanceof k&&typeof $==\"function\"&&$ instanceof $)&&(y=!1)}return o.delete(e),o.delete(t),y}var $K=1,A$=\"[object Arguments]\",D$=\"[object Array]\",rh=\"[object Object]\",OK=Object.prototype,R$=OK.hasOwnProperty;function PK(e,t,n,r,a,o){var i=Nr(e),l=Nr(t),s=i?D$:jd(e),c=l?D$:jd(t);s=s==A$?rh:s,c=c==A$?rh:c;var d=s==rh,f=c==rh,p=s==c;if(p&&Bd(e)){if(!Bd(t))return!1;i=!0,d=!1}if(p&&!d)return o||(o=new Qa),i||wC(e)?F8(e,t,n,r,a,o):bK(e,t,s,n,r,a,o);if(!(n&$K)){var v=d&&R$.call(e,\"__wrapped__\"),m=f&&R$.call(t,\"__wrapped__\");if(v||m){var y=v?e.value():e,b=m?t.value():t;return o||(o=new Qa),a(y,b,n,r,o)}}return p?(o||(o=new Qa),kK(e,t,n,r,a,o)):!1}function Dm(e,t,n,r,a){return e===t?!0:e==null||t==null||!ao(e)&&!ao(t)?e!==e&&t!==t:PK(e,t,n,r,Dm,a)}var TK=1,xK=2;function _K(e,t,n,r){var a=n.length,o=a,i=!r;if(e==null)return!o;for(e=Object(e);a--;){var l=n[a];if(i&&l[2]?l[1]!==e[l[0]]:!(l[0]in e))return!1}for(;++a<o;){l=n[a];var s=l[0],c=e[s],d=l[1];if(i&&l[2]){if(c===void 0&&!(s in e))return!1}else{var f=new Qa;if(r)var p=r(c,d,s,e,t,f);if(!(p===void 0?Dm(d,c,TK|xK,r,f):p))return!1}}return!0}function B8(e){return e===e&&!Ar(e)}function EK(e){for(var t=mc(e),n=t.length;n--;){var r=t[n],a=e[r];t[n]=[r,a,B8(a)]}return t}function V8(e,t){return function(n){return n==null?!1:n[e]===t&&(t!==void 0||e in Object(n))}}function MK(e){var t=EK(e);return t.length==1&&t[0][2]?V8(t[0][0],t[0][1]):function(n){return n===e||_K(n,e,t)}}function IK(e,t){return e!=null&&t in Object(e)}function NK(e,t,n){t=gc(t,e);for(var r=-1,a=t.length,o=!1;++r<a;){var i=yc(t[r]);if(!(o=e!=null&&n(e,i)))break;e=e[i]}return o||++r!=a?o:(a=e==null?0:e.length,!!a&&bC(a)&&xm(i,a)&&(Nr(e)||Fd(e)))}function z8(e,t){return e!=null&&NK(e,t,IK)}var AK=1,DK=2;function RK(e,t){return SC(e)&&B8(t)?V8(yc(e),t):function(n){var r=vn(n,e);return r===void 0&&r===t?z8(n,e):Dm(t,r,AK|DK)}}function H8(e){return function(t){return t==null?void 0:t[e]}}function LK(e){return function(t){return Nm(t,e)}}function FK(e){return SC(e)?H8(yc(e)):LK(e)}function Rm(e){return typeof e==\"function\"?e:e==null?pC:typeof e==\"object\"?Nr(e)?RK(e[0],e[1]):MK(e):FK(e)}function BK(e,t,n,r){for(var a=-1,o=e==null?0:e.length;++a<o;){var i=e[a];t(r,i,n(i),e)}return r}function VK(e){return function(t,n,r){for(var a=-1,o=Object(t),i=r(t),l=i.length;l--;){var s=i[e?l:++a];if(n(o[s],s,o)===!1)break}return t}}var zK=VK(),j8=zK;function HK(e,t){return e&&j8(e,t,mc)}function jK(e,t){return function(n,r){if(n==null)return n;if(!vc(n))return e(n,r);for(var a=n.length,o=t?a:-1,i=Object(n);(t?o--:++o<a)&&r(i[o],o,i)!==!1;);return n}}var KK=jK(HK),WK=KK;function UK(e,t,n,r){return WK(e,function(a,o,i){t(r,a,n(a),i)}),r}function YK(e,t){return function(n,r){var a=Nr(n)?BK:UK,o=t?t():{};return a(n,e,Rm(r),o)}}var qK=function(){return fo.Date.now()},ey=qK,GK=\"Expected a function\",XK=Math.max,ZK=Math.min;function Yn(e,t,n){var r,a,o,i,l,s,c=0,d=!1,f=!1,p=!0;if(typeof e!=\"function\")throw new TypeError(GK);t=Qb(t)||0,Ar(n)&&(d=!!n.leading,f=\"maxWait\"in n,o=f?XK(Qb(n.maxWait)||0,t):o,p=\"trailing\"in n?!!n.trailing:p);function v(O){var T=r,_=a;return r=a=void 0,c=O,i=e.apply(_,T),i}function m(O){return c=O,l=setTimeout(C,t),d?v(O):i}function y(O){var T=O-s,_=O-c,I=t-T;return f?ZK(I,o-_):I}function b(O){var T=O-s,_=O-c;return s===void 0||T>=t||T<0||f&&_>=o}function C(){var O=ey();if(b(O))return S(O);l=setTimeout(C,y(O))}function S(O){return l=void 0,p&&r?v(O):(r=a=void 0,i)}function w(){l!==void 0&&clearTimeout(l),c=0,r=s=a=l=void 0}function k(){return l===void 0?i:S(ey())}function $(){var O=ey(),T=b(O);if(r=arguments,a=this,s=O,T){if(l===void 0)return m(s);if(f)return clearTimeout(l),l=setTimeout(C,t),v(s)}return l===void 0&&(l=setTimeout(C,t)),i}return $.cancel=w,$.flush=k,$}function i0(e,t,n){(n!==void 0&&!Sf(e[t],n)||n===void 0&&!(t in e))&&mC(e,t,n)}function EC(e){return ao(e)&&vc(e)}function l0(e,t){if(!(t===\"constructor\"&&typeof e[t]==\"function\")&&t!=\"__proto__\")return e[t]}function JK(e){return pc(e,kf(e))}function QK(e,t,n,r,a,o,i){var l=l0(e,n),s=l0(t,n),c=i.get(s);if(c){i0(e,n,c);return}var d=o?o(l,s,n+\"\",e,t,i):void 0,f=d===void 0;if(f){var p=Nr(s),v=!p&&Bd(s),m=!p&&!v&&wC(s);d=s,p||v||m?Nr(l)?d=l:EC(l)?d=l8(l):v?(f=!1,d=x8(s,!0)):m?(f=!1,d=N8(s,!0)):d=[]:bc(s)||Fd(s)?(d=l,Fd(l)?d=JK(l):(!Ar(l)||vC(l))&&(d=A8(s))):f=!1}f&&(i.set(s,d),a(d,s,r,o,i),i.delete(s)),i0(e,n,d)}function K8(e,t,n,r,a){e!==t&&j8(t,function(o,i){if(a||(a=new Qa),Ar(o))QK(e,t,i,n,K8,r,a);else{var l=r?r(l0(e,i),o,i+\"\",e,t,a):void 0;l===void 0&&(l=o),i0(e,i,l)}},kf)}function W8(e,t,n){for(var r=-1,a=e==null?0:e.length;++r<a;)if(n(t,e[r]))return!0;return!1}function eW(e){var t=e==null?0:e.length;return t?e[t-1]:void 0}function tW(e){return function(t,n,r){var a=Object(t);if(!vc(t)){var o=Rm(n);t=mc(t),n=function(l){return o(a[l],l,a)}}var i=e(t,n,r);return i>-1?a[o?t[i]:i]:void 0}}var nW=Math.max;function U8(e,t,n){var r=e==null?0:e.length;if(!r)return-1;var a=n==null?0:Tm(n);return a<0&&(a=nW(r+a,0)),u8(e,Rm(t),a)}var rW=tW(U8),aW=rW,oW=1/0;function iW(e){var t=e==null?0:e.length;return t?Am(e,oW):[]}function Y8(e){for(var t=-1,n=e==null?0:e.length,r={};++t<n;){var a=e[t];r[a[0]]=a[1]}return r}var lW=Math.max;function ty(e,t,n){var r=e==null?0:e.length;if(!r)return-1;var a=n==null?0:Tm(n);return a<0&&(a=lW(r+a,0)),c8(e,t,a)}var sW=Math.min;function uW(e,t,n){for(var r=n?W8:d8,a=e[0].length,o=e.length,i=o,l=Array(o),s=1/0,c=[];i--;){var d=e[i];i&&t&&(d=Pm(d,_m(t))),s=sW(d.length,s),l[i]=!n&&(t||a>=120&&d.length>=120)?new Ku(i&&d):void 0}d=e[0];var f=-1,p=l[0];e:for(;++f<a&&c.length<s;){var v=d[f],m=t?t(v):v;if(v=n||v!==0?v:0,!(p?pv(p,m):r(c,m,n))){for(i=o;--i;){var y=l[i];if(!(y?pv(y,m):r(e[i],m,n)))continue e}p&&p.push(m),c.push(v)}}return c}function cW(e){return EC(e)?e:[]}var dW=yC(function(e){var t=Pm(e,cW);return t.length&&t[0]===e[0]?uW(t):[]}),fW=dW;function hW(e,t){return t.length<2?e:Nm(e,C8(t,0,-1))}function er(e,t){return Dm(e,t)}var pW=\"[object Number]\";function vW(e){return typeof e==\"number\"||ao(e)&&ml(e)==pW}function ul(e){return e==null}var mW=oV(function(e,t,n){K8(e,t,n)}),L$=mW;function gW(e,t){return t=gc(t,e),e=hW(e,t),e==null||delete e[yc(eW(t))]}function yW(e){return bc(e)?void 0:e}var bW=1,CW=2,wW=4,SW=y8(function(e,t){var n={};if(e==null)return n;var r=!1;t=Pm(t,function(o){return o=gc(o,e),r||(r=o.length>1),o}),pc(e,I8(e),n),r&&(n=Pu(n,bW|CW|wW,yW));for(var a=t.length;a--;)gW(n,t[a]);return n}),MC=SW;function q8(e,t,n,r){if(!Ar(e))return e;t=gc(t,e);for(var a=-1,o=t.length,i=o-1,l=e;l!=null&&++a<o;){var s=yc(t[a]),c=n;if(s===\"__proto__\"||s===\"constructor\"||s===\"prototype\")return e;if(a!=i){var d=l[s];c=r?r(d,s,l):void 0,c===void 0&&(c=Ar(d)?d:xm(t[a+1])?[]:{})}gC(l,s,c),l=l[s]}return e}function kW(e,t,n){for(var r=-1,a=t.length,o={};++r<a;){var i=t[r],l=Nm(e,i);n(l,i)&&q8(o,gc(i,e),l)}return o}var $W=9007199254740991,OW=Math.floor;function F$(e,t){var n=\"\";if(!e||t<1||t>$W)return n;do t%2&&(n+=e),t=OW(t/2),t&&(e+=e);while(t);return n}var PW=H8(\"length\"),TW=PW,G8=\"\\\\ud800-\\\\udfff\",xW=\"\\\\u0300-\\\\u036f\",_W=\"\\\\ufe20-\\\\ufe2f\",EW=\"\\\\u20d0-\\\\u20ff\",MW=xW+_W+EW,IW=\"\\\\ufe0e\\\\ufe0f\",NW=\"[\"+G8+\"]\",s0=\"[\"+MW+\"]\",u0=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",AW=\"(?:\"+s0+\"|\"+u0+\")\",X8=\"[^\"+G8+\"]\",Z8=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",J8=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",DW=\"\\\\u200d\",Q8=AW+\"?\",eE=\"[\"+IW+\"]?\",RW=\"(?:\"+DW+\"(?:\"+[X8,Z8,J8].join(\"|\")+\")\"+eE+Q8+\")*\",LW=eE+Q8+RW,FW=\"(?:\"+[X8+s0+\"?\",s0,Z8,J8,NW].join(\"|\")+\")\",B$=RegExp(u0+\"(?=\"+u0+\")|\"+FW+LW,\"g\");function BW(e){for(var t=B$.lastIndex=0;B$.test(e);)++t;return t}function IC(e){return PC(e)?BW(e):TW(e)}var VW=Math.ceil;function tE(e,t){t=t===void 0?\" \":hC(t);var n=t.length;if(n<2)return n?F$(t,e):t;var r=F$(t,VW(e/IC(t)));return PC(t)?Wz(pH(r),0,e).join(\"\"):r.slice(0,e)}function zW(e,t,n){e=kC(e),t=Tm(t);var r=t?IC(e):0;return t&&r<t?e+tE(t-r,n):e}function HW(e,t,n){e=kC(e),t=Tm(t);var r=t?IC(e):0;return t&&r<t?tE(t-r,n)+e:e}var jW=YK(function(e,t,n){e[n?0:1].push(t)},function(){return[[],[]]}),KW=jW;function WW(e,t){return kW(e,t,function(n,r){return z8(e,r)})}var UW=y8(function(e,t){return e==null?{}:WW(e,t)}),Yi=UW;function YW(e,t,n){return e==null?e:q8(e,t,n)}var qW=\"Expected a function\";function Qi(e,t,n){var r=!0,a=!0;if(typeof e!=\"function\")throw new TypeError(qW);return Ar(n)&&(r=\"leading\"in n?!!n.leading:r,a=\"trailing\"in n?!!n.trailing:a),Yn(e,t,{leading:r,maxWait:t,trailing:a})}var GW=1/0,XW=Ou&&1/_C(new Ou([,-0]))[1]==GW?function(e){return new Ou(e)}:VB,ZW=XW,JW=200;function NC(e,t,n){var r=-1,a=d8,o=e.length,i=!0,l=[],s=l;if(n)i=!1,a=W8;else if(o>=JW){var c=t?null:ZW(e);if(c)return _C(c);i=!1,a=pv,s=new Ku}else s=t?[]:l;e:for(;++r<o;){var d=e[r],f=t?t(d):d;if(d=n||d!==0?d:0,i&&f===f){for(var p=s.length;p--;)if(s[p]===f)continue e;t&&s.push(f),l.push(d)}else a(s,f,n)||(s!==l&&s.push(f),l.push(d))}return l}var QW=yC(function(e){return NC(Am(e,1,EC,!0))}),ny=QW;function eU(e){return e&&e.length?NC(e):[]}function tU(e,t){return e&&e.length?NC(e,Rm(t)):[]}const nU='a[href],button:not([disabled]),button:not([hidden]),:not([tabindex=\"-1\"]),input:not([disabled]),input:not([type=\"hidden\"]),select:not([disabled]),textarea:not([disabled])',rU=e=>getComputedStyle(e).position===\"fixed\"?!1:e.offsetParent!==null,V$=e=>Array.from(e.querySelectorAll(nU)).filter(t=>aU(t)&&rU(t)),aU=e=>{if(e.tabIndex>0||e.tabIndex===0&&e.getAttribute(\"tabIndex\")!==null)return!0;if(e.disabled)return!1;switch(e.nodeName){case\"A\":return!!e.href&&e.rel!==\"ignore\";case\"INPUT\":return!(e.type===\"hidden\"||e.type===\"file\");case\"BUTTON\":case\"SELECT\":case\"TEXTAREA\":return!0;default:return!1}},sp=function(e,t,...n){let r;t.includes(\"mouse\")||t.includes(\"click\")?r=\"MouseEvents\":t.includes(\"key\")?r=\"KeyboardEvent\":r=\"HTMLEvents\";const a=document.createEvent(r);return a.initEvent(t,...n),e.dispatchEvent(a),e},nE=e=>!e.getAttribute(\"aria-owns\"),rE=(e,t,n)=>{const{parentNode:r}=e;if(!r)return null;const a=r.querySelectorAll(n),o=Array.prototype.indexOf.call(a,e);return a[o+t]||null},up=e=>{!e||(e.focus(),!nE(e)&&e.click())},gn=(e,t,n,r=!1)=>{e&&t&&n&&(e==null||e.addEventListener(t,n,r))},Bn=(e,t,n,r=!1)=>{e&&t&&n&&(e==null||e.removeEventListener(t,n,r))},oU=(e,t,n)=>{const r=function(...a){n&&n.apply(this,a),Bn(e,t,r)};gn(e,t,r)},Tn=(e,t,{checkForDefaultPrevented:n=!0}={})=>a=>{const o=e==null?void 0:e(a);if(n===!1||!o)return t==null?void 0:t(a)},z$=e=>t=>t.pointerType===\"mouse\"?e(t):void 0;var iU=Object.defineProperty,lU=Object.defineProperties,sU=Object.getOwnPropertyDescriptors,H$=Object.getOwnPropertySymbols,uU=Object.prototype.hasOwnProperty,cU=Object.prototype.propertyIsEnumerable,j$=(e,t,n)=>t in e?iU(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,dU=(e,t)=>{for(var n in t||(t={}))uU.call(t,n)&&j$(e,n,t[n]);if(H$)for(var n of H$(t))cU.call(t,n)&&j$(e,n,t[n]);return e},fU=(e,t)=>lU(e,sU(t));function K$(e,t){var n;const r=Qn();return Wn(()=>{r.value=e()},fU(dU({},t),{flush:(n=t==null?void 0:t.flush)!=null?n:\"sync\"})),Cf(r)}function Lm(e){return D9()?(Z_(e),!0):!1}const Bt=typeof window!=\"undefined\",yr=e=>typeof e==\"boolean\",Yt=e=>typeof e==\"number\",hU=e=>typeof e==\"string\",ry=()=>{};function aE(e,t){function n(...r){e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})}return n}function pU(e,t={}){let n,r;return o=>{const i=A(e),l=A(t.maxWait);if(n&&clearTimeout(n),i<=0||l!==void 0&&l<=0)return r&&(clearTimeout(r),r=null),o();l&&!r&&(r=setTimeout(()=>{n&&clearTimeout(n),r=null,o()},l)),n=setTimeout(()=>{r&&clearTimeout(r),r=null,o()},i)}}function vU(e,t=!0,n=!0){let r=0,a,o=!n;const i=()=>{a&&(clearTimeout(a),a=void 0)};return s=>{const c=A(e),d=Date.now()-r;if(i(),c<=0)return r=Date.now(),s();d>c&&(r=Date.now(),o?o=!1:s()),t&&(a=setTimeout(()=>{r=Date.now(),n||(o=!0),i(),s()},c)),!n&&!a&&(a=setTimeout(()=>o=!0,c))}}function mU(e,t=200,n={}){return aE(pU(t,n),e)}function gU(e,t=200,n={}){if(t<=0)return e;const r=H(e.value),a=mU(()=>{r.value=e.value},t,n);return ce(e,()=>a()),r}function oE(e,t=200,n=!0,r=!0){return aE(vU(t,n,r),e)}function yU(e,t=!0){$t()?et(e):t?e():Ne(e)}function gs(e,t,n={}){const{immediate:r=!0}=n,a=H(!1);let o=null;function i(){o&&(clearTimeout(o),o=null)}function l(){a.value=!1,i()}function s(...c){i(),a.value=!0,o=setTimeout(()=>{a.value=!1,o=null,e(...c)},A(t))}return r&&(a.value=!0,Bt&&s()),Lm(l),{isPending:a,start:s,stop:l}}function eo(e){var t;const n=A(e);return(t=n==null?void 0:n.$el)!=null?t:n}const $f=Bt?window:void 0,bU=Bt?window.document:void 0;function Hn(...e){let t,n,r,a;if(hU(e[0])?([n,r,a]=e,t=$f):[t,n,r,a]=e,!t)return ry;let o=ry;const i=ce(()=>eo(t),s=>{o(),s&&(s.addEventListener(n,r,a),o=()=>{s.removeEventListener(n,r,a),o=ry})},{immediate:!0,flush:\"post\"}),l=()=>{i(),o()};return Lm(l),l}function vv(e,t,n={}){const{window:r=$f,ignore:a,capture:o=!0}=n;if(!r)return;const i=H(!0),s=[Hn(r,\"click\",d=>{const f=eo(e),p=d.composedPath();!f||f===d.target||p.includes(f)||!i.value||a&&a.length>0&&a.some(v=>{const m=eo(v);return m&&(d.target===m||p.includes(m))})||t(d)},{passive:!0,capture:o}),Hn(r,\"pointerdown\",d=>{const f=eo(e);i.value=!!f&&!d.composedPath().includes(f)},{passive:!0})];return()=>s.forEach(d=>d())}const c0=typeof globalThis!=\"undefined\"?globalThis:typeof window!=\"undefined\"?window:typeof global!=\"undefined\"?global:typeof self!=\"undefined\"?self:{},d0=\"__vueuse_ssr_handlers__\";c0[d0]=c0[d0]||{};c0[d0];function CU({document:e=bU}={}){if(!e)return H(\"visible\");const t=H(e.visibilityState);return Hn(e,\"visibilitychange\",()=>{t.value=e.visibilityState}),t}var W$=Object.getOwnPropertySymbols,wU=Object.prototype.hasOwnProperty,SU=Object.prototype.propertyIsEnumerable,kU=(e,t)=>{var n={};for(var r in e)wU.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&W$)for(var r of W$(e))t.indexOf(r)<0&&SU.call(e,r)&&(n[r]=e[r]);return n};function Cc(e,t,n={}){const r=n,{window:a=$f}=r,o=kU(r,[\"window\"]);let i;const l=a&&\"ResizeObserver\"in a,s=()=>{i&&(i.disconnect(),i=void 0)},c=ce(()=>eo(e),f=>{s(),l&&a&&f&&(i=new ResizeObserver(t),i.observe(f,o))},{immediate:!0,flush:\"post\"}),d=()=>{s(),c()};return Lm(d),{isSupported:l,stop:d}}function U$(e,t={}){const{reset:n=!0,windowResize:r=!0,windowScroll:a=!0}=t,o=H(0),i=H(0),l=H(0),s=H(0),c=H(0),d=H(0),f=H(0),p=H(0);function v(){const m=eo(e);if(!m){n&&(o.value=0,i.value=0,l.value=0,s.value=0,c.value=0,d.value=0,f.value=0,p.value=0);return}const y=m.getBoundingClientRect();o.value=y.height,i.value=y.bottom,l.value=y.left,s.value=y.right,c.value=y.top,d.value=y.width,f.value=y.x,p.value=y.y}return Cc(e,v),ce(()=>eo(e),m=>!m&&v()),a&&Hn(\"scroll\",v,{passive:!0}),r&&Hn(\"resize\",v,{passive:!0}),{height:o,bottom:i,left:l,right:s,top:c,width:d,x:f,y:p,update:v}}var Y$,q$;Bt&&(window==null?void 0:window.navigator)&&((Y$=window==null?void 0:window.navigator)==null?void 0:Y$.platform)&&/iP(ad|hone|od)/.test((q$=window==null?void 0:window.navigator)==null?void 0:q$.platform);function $U({window:e=$f}={}){if(!e)return H(!1);const t=H(e.document.hasFocus());return Hn(e,\"blur\",()=>{t.value=!1}),Hn(e,\"focus\",()=>{t.value=!0}),t}function OU({window:e=$f,initialWidth:t=1/0,initialHeight:n=1/0}={}){const r=H(t),a=H(n),o=()=>{e&&(r.value=e.innerWidth,a.value=e.innerHeight)};return o(),yU(o),Hn(\"resize\",o,{passive:!0}),{width:r,height:a}}const PU=(e,t)=>{if(!Bt||!e||!t)return!1;const n=e.getBoundingClientRect();let r;return t instanceof Element?r=t.getBoundingClientRect():r={top:0,right:window.innerWidth,bottom:window.innerHeight,left:0},n.top<r.bottom&&n.bottom>r.top&&n.right>r.left&&n.left<r.right},G$=e=>{let t=0,n=e;for(;n;)t+=n.offsetTop,n=n.offsetParent;return t},TU=(e,t)=>Math.abs(G$(e)-G$(t)),AC=e=>{let t,n;return e.type===\"touchend\"?(n=e.changedTouches[0].clientY,t=e.changedTouches[0].clientX):e.type.startsWith(\"touch\")?(n=e.touches[0].clientY,t=e.touches[0].clientX):(n=e.clientY,t=e.clientX),{clientX:t,clientY:n}},xU=function(e){for(const t of e){const n=t.target.__resizeListeners__||[];n.length&&n.forEach(r=>{r()})}},wc=function(e,t){!Bt||!e||(e.__resizeListeners__||(e.__resizeListeners__=[],e.__ro__=new ResizeObserver(xU),e.__ro__.observe(e)),e.__resizeListeners__.push(t))},Sc=function(e,t){var n;!e||!e.__resizeListeners__||(e.__resizeListeners__.splice(e.__resizeListeners__.indexOf(t),1),e.__resizeListeners__.length||(n=e.__ro__)==null||n.disconnect())},sa=e=>e===void 0,Kd=e=>!e&&e!==0||pt(e)&&e.length===0||zt(e)&&!Object.keys(e).length,ys=e=>typeof Element==\"undefined\"?!1:e instanceof Element,_U=e=>ul(e),EU=(e=\"\")=>e.replace(/[|\\\\{}()[\\]^$+*?.]/g,\"\\\\$&\").replace(/-/g,\"\\\\x2d\"),f0=e=>Object.keys(e),MU=e=>Object.entries(e),cp=(e,t,n)=>({get value(){return vn(e,t,n)},set value(r){YW(e,t,r)}}),iE=(e=\"\")=>e.split(\" \").filter(t=>!!t.trim()),to=(e,t)=>{if(!e||!t)return!1;if(t.includes(\" \"))throw new Error(\"className should not contain space.\");return e.classList.contains(t)},xo=(e,t)=>{!e||!t.trim()||e.classList.add(...iE(t))},Br=(e,t)=>{!e||!t.trim()||e.classList.remove(...iE(t))},$o=(e,t)=>{var n;if(!Bt||!e||!t)return\"\";_a(t);try{const r=e.style[t];if(r)return r;const a=(n=document.defaultView)==null?void 0:n.getComputedStyle(e,\"\");return a?a[t]:\"\"}catch{return e.style[t]}},IU=(e,t)=>{if(!Bt)return!1;const n={undefined:\"overflow\",true:\"overflow-y\",false:\"overflow-x\"}[String(t)],r=$o(e,n);return[\"scroll\",\"auto\",\"overlay\"].some(a=>r.includes(a))},DC=(e,t)=>{if(!Bt)return;let n=e;for(;n;){if([window,document,document.documentElement].includes(n))return window;if(IU(n,t))return n;n=n.parentNode}return n};let ah;const NU=()=>{var e;if(!Bt)return 0;if(ah!==void 0)return ah;const t=document.createElement(\"div\");t.className=\"el-scrollbar__wrap\",t.style.visibility=\"hidden\",t.style.width=\"100px\",t.style.position=\"absolute\",t.style.top=\"-9999px\",document.body.appendChild(t);const n=t.offsetWidth;t.style.overflow=\"scroll\";const r=document.createElement(\"div\");r.style.width=\"100%\",t.appendChild(r);const a=r.offsetWidth;return(e=t.parentNode)==null||e.removeChild(t),ah=n-a,ah};function lE(e,t){if(!Bt)return;if(!t){e.scrollTop=0;return}const n=[];let r=t.offsetParent;for(;r!==null&&e!==r&&e.contains(r);)n.push(r),r=r.offsetParent;const a=t.offsetTop+n.reduce((s,c)=>s+c.offsetTop,0),o=a+t.offsetHeight,i=e.scrollTop,l=i+e.clientHeight;a<i?e.scrollTop=a:o>l&&(e.scrollTop=o-e.clientHeight)}var Xt=(e,t)=>{const n=e.__vccOpts||e;for(const[r,a]of t)n[r]=a;return n};const AU=G({name:\"ArrowDown\"}),DU={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},RU=Z(\"path\",{fill:\"currentColor\",d:\"M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z\"},null,-1),LU=[RU];function FU(e,t,n,r,a,o){return R(),X(\"svg\",DU,LU)}var _s=Xt(AU,[[\"render\",FU]]);const BU=G({name:\"ArrowLeft\"}),VU={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},zU=Z(\"path\",{fill:\"currentColor\",d:\"M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z\"},null,-1),HU=[zU];function jU(e,t,n,r,a,o){return R(),X(\"svg\",VU,HU)}var Es=Xt(BU,[[\"render\",jU]]);const KU=G({name:\"ArrowRight\"}),WU={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},UU=Z(\"path\",{fill:\"currentColor\",d:\"M340.864 149.312a30.592 30.592 0 0 0 0 42.752L652.736 512 340.864 831.872a30.592 30.592 0 0 0 0 42.752 29.12 29.12 0 0 0 41.728 0L714.24 534.336a32 32 0 0 0 0-44.672L382.592 149.376a29.12 29.12 0 0 0-41.728 0z\"},null,-1),YU=[UU];function qU(e,t,n,r,a,o){return R(),X(\"svg\",WU,YU)}var Da=Xt(KU,[[\"render\",qU]]);const GU=G({name:\"ArrowUp\"}),XU={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},ZU=Z(\"path\",{fill:\"currentColor\",d:\"m488.832 344.32-339.84 356.672a32 32 0 0 0 0 44.16l.384.384a29.44 29.44 0 0 0 42.688 0l320-335.872 319.872 335.872a29.44 29.44 0 0 0 42.688 0l.384-.384a32 32 0 0 0 0-44.16L535.168 344.32a32 32 0 0 0-46.336 0z\"},null,-1),JU=[ZU];function QU(e,t,n,r,a,o){return R(),X(\"svg\",XU,JU)}var Of=Xt(GU,[[\"render\",QU]]);const eY=G({name:\"Back\"}),tY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},nY=Z(\"path\",{fill:\"currentColor\",d:\"M224 480h640a32 32 0 1 1 0 64H224a32 32 0 0 1 0-64z\"},null,-1),rY=Z(\"path\",{fill:\"currentColor\",d:\"m237.248 512 265.408 265.344a32 32 0 0 1-45.312 45.312l-288-288a32 32 0 0 1 0-45.312l288-288a32 32 0 1 1 45.312 45.312L237.248 512z\"},null,-1),aY=[nY,rY];function oY(e,t,n,r,a,o){return R(),X(\"svg\",tY,aY)}var iY=Xt(eY,[[\"render\",oY]]);const lY=G({name:\"Calendar\"}),sY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},uY=Z(\"path\",{fill:\"currentColor\",d:\"M128 384v512h768V192H768v32a32 32 0 1 1-64 0v-32H320v32a32 32 0 0 1-64 0v-32H128v128h768v64H128zm192-256h384V96a32 32 0 1 1 64 0v32h160a32 32 0 0 1 32 32v768a32 32 0 0 1-32 32H96a32 32 0 0 1-32-32V160a32 32 0 0 1 32-32h160V96a32 32 0 0 1 64 0v32zm-32 384h64a32 32 0 0 1 0 64h-64a32 32 0 0 1 0-64zm0 192h64a32 32 0 1 1 0 64h-64a32 32 0 1 1 0-64zm192-192h64a32 32 0 0 1 0 64h-64a32 32 0 0 1 0-64zm0 192h64a32 32 0 1 1 0 64h-64a32 32 0 1 1 0-64zm192-192h64a32 32 0 1 1 0 64h-64a32 32 0 1 1 0-64zm0 192h64a32 32 0 1 1 0 64h-64a32 32 0 1 1 0-64z\"},null,-1),cY=[uY];function dY(e,t,n,r,a,o){return R(),X(\"svg\",sY,cY)}var fY=Xt(lY,[[\"render\",dY]]);const hY=G({name:\"CaretRight\"}),pY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},vY=Z(\"path\",{fill:\"currentColor\",d:\"M384 192v640l384-320.064z\"},null,-1),mY=[vY];function gY(e,t,n,r,a,o){return R(),X(\"svg\",pY,mY)}var sE=Xt(hY,[[\"render\",gY]]);const yY=G({name:\"CaretTop\"}),bY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},CY=Z(\"path\",{fill:\"currentColor\",d:\"M512 320 192 704h639.936z\"},null,-1),wY=[CY];function SY(e,t,n,r,a,o){return R(),X(\"svg\",bY,wY)}var kY=Xt(yY,[[\"render\",SY]]);const $Y=G({name:\"Check\"}),OY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},PY=Z(\"path\",{fill:\"currentColor\",d:\"M406.656 706.944 195.84 496.256a32 32 0 1 0-45.248 45.248l256 256 512-512a32 32 0 0 0-45.248-45.248L406.592 706.944z\"},null,-1),TY=[PY];function xY(e,t,n,r,a,o){return R(),X(\"svg\",OY,TY)}var Wu=Xt($Y,[[\"render\",xY]]);const _Y=G({name:\"CircleCheckFilled\"}),EY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},MY=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-55.808 536.384-99.52-99.584a38.4 38.4 0 1 0-54.336 54.336l126.72 126.72a38.272 38.272 0 0 0 54.336 0l262.4-262.464a38.4 38.4 0 1 0-54.272-54.336L456.192 600.384z\"},null,-1),IY=[MY];function NY(e,t,n,r,a,o){return R(),X(\"svg\",EY,IY)}var AY=Xt(_Y,[[\"render\",NY]]);const DY=G({name:\"CircleCheck\"}),RY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},LY=Z(\"path\",{fill:\"currentColor\",d:\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896z\"},null,-1),FY=Z(\"path\",{fill:\"currentColor\",d:\"M745.344 361.344a32 32 0 0 1 45.312 45.312l-288 288a32 32 0 0 1-45.312 0l-160-160a32 32 0 1 1 45.312-45.312L480 626.752l265.344-265.408z\"},null,-1),BY=[LY,FY];function VY(e,t,n,r,a,o){return R(),X(\"svg\",RY,BY)}var mv=Xt(DY,[[\"render\",VY]]);const zY=G({name:\"CircleCloseFilled\"}),HY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},jY=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336L512 457.664z\"},null,-1),KY=[jY];function WY(e,t,n,r,a,o){return R(),X(\"svg\",HY,KY)}var RC=Xt(zY,[[\"render\",WY]]);const UY=G({name:\"CircleClose\"}),YY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},qY=Z(\"path\",{fill:\"currentColor\",d:\"m466.752 512-90.496-90.496a32 32 0 0 1 45.248-45.248L512 466.752l90.496-90.496a32 32 0 1 1 45.248 45.248L557.248 512l90.496 90.496a32 32 0 1 1-45.248 45.248L512 557.248l-90.496 90.496a32 32 0 0 1-45.248-45.248L466.752 512z\"},null,-1),GY=Z(\"path\",{fill:\"currentColor\",d:\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896z\"},null,-1),XY=[qY,GY];function ZY(e,t,n,r,a,o){return R(),X(\"svg\",YY,XY)}var gi=Xt(UY,[[\"render\",ZY]]);const JY=G({name:\"Clock\"}),QY={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},eq=Z(\"path\",{fill:\"currentColor\",d:\"M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768zm0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896z\"},null,-1),tq=Z(\"path\",{fill:\"currentColor\",d:\"M480 256a32 32 0 0 1 32 32v256a32 32 0 0 1-64 0V288a32 32 0 0 1 32-32z\"},null,-1),nq=Z(\"path\",{fill:\"currentColor\",d:\"M480 512h256q32 0 32 32t-32 32H480q-32 0-32-32t32-32z\"},null,-1),rq=[eq,tq,nq];function aq(e,t,n,r,a,o){return R(),X(\"svg\",QY,rq)}var uE=Xt(JY,[[\"render\",aq]]);const oq=G({name:\"Close\"}),iq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},lq=Z(\"path\",{fill:\"currentColor\",d:\"M764.288 214.592 512 466.88 259.712 214.592a31.936 31.936 0 0 0-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1 0 45.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0 0 45.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 1 0-45.12-45.184z\"},null,-1),sq=[lq];function uq(e,t,n,r,a,o){return R(),X(\"svg\",iq,sq)}var Ma=Xt(oq,[[\"render\",uq]]);const cq=G({name:\"DArrowLeft\"}),dq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},fq=Z(\"path\",{fill:\"currentColor\",d:\"M529.408 149.376a29.12 29.12 0 0 1 41.728 0 30.592 30.592 0 0 1 0 42.688L259.264 511.936l311.872 319.936a30.592 30.592 0 0 1-.512 43.264 29.12 29.12 0 0 1-41.216-.512L197.76 534.272a32 32 0 0 1 0-44.672l331.648-340.224zm256 0a29.12 29.12 0 0 1 41.728 0 30.592 30.592 0 0 1 0 42.688L515.264 511.936l311.872 319.936a30.592 30.592 0 0 1-.512 43.264 29.12 29.12 0 0 1-41.216-.512L453.76 534.272a32 32 0 0 1 0-44.672l331.648-340.224z\"},null,-1),hq=[fq];function pq(e,t,n,r,a,o){return R(),X(\"svg\",dq,hq)}var Fm=Xt(cq,[[\"render\",pq]]);const vq=G({name:\"DArrowRight\"}),mq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},gq=Z(\"path\",{fill:\"currentColor\",d:\"M452.864 149.312a29.12 29.12 0 0 1 41.728.064L826.24 489.664a32 32 0 0 1 0 44.672L494.592 874.624a29.12 29.12 0 0 1-41.728 0 30.592 30.592 0 0 1 0-42.752L764.736 512 452.864 192a30.592 30.592 0 0 1 0-42.688zm-256 0a29.12 29.12 0 0 1 41.728.064L570.24 489.664a32 32 0 0 1 0 44.672L238.592 874.624a29.12 29.12 0 0 1-41.728 0 30.592 30.592 0 0 1 0-42.752L508.736 512 196.864 192a30.592 30.592 0 0 1 0-42.688z\"},null,-1),yq=[gq];function bq(e,t,n,r,a,o){return R(),X(\"svg\",mq,yq)}var Bm=Xt(vq,[[\"render\",bq]]);const Cq=G({name:\"Delete\"}),wq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},Sq=Z(\"path\",{fill:\"currentColor\",d:\"M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32V256zm448-64v-64H416v64h192zM224 896h576V256H224v640zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32zm192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32z\"},null,-1),kq=[Sq];function $q(e,t,n,r,a,o){return R(),X(\"svg\",wq,kq)}var Oq=Xt(Cq,[[\"render\",$q]]);const Pq=G({name:\"Document\"}),Tq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},xq=Z(\"path\",{fill:\"currentColor\",d:\"M832 384H576V128H192v768h640V384zm-26.496-64L640 154.496V320h165.504zM160 64h480l256 256v608a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V96a32 32 0 0 1 32-32zm160 448h384v64H320v-64zm0-192h160v64H320v-64zm0 384h384v64H320v-64z\"},null,-1),_q=[xq];function Eq(e,t,n,r,a,o){return R(),X(\"svg\",Tq,_q)}var Mq=Xt(Pq,[[\"render\",Eq]]);const Iq=G({name:\"FullScreen\"}),Nq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},Aq=Z(\"path\",{fill:\"currentColor\",d:\"m160 96.064 192 .192a32 32 0 0 1 0 64l-192-.192V352a32 32 0 0 1-64 0V96h64v.064zm0 831.872V928H96V672a32 32 0 1 1 64 0v191.936l192-.192a32 32 0 1 1 0 64l-192 .192zM864 96.064V96h64v256a32 32 0 1 1-64 0V160.064l-192 .192a32 32 0 1 1 0-64l192-.192zm0 831.872-192-.192a32 32 0 0 1 0-64l192 .192V672a32 32 0 1 1 64 0v256h-64v-.064z\"},null,-1),Dq=[Aq];function Rq(e,t,n,r,a,o){return R(),X(\"svg\",Nq,Dq)}var Lq=Xt(Iq,[[\"render\",Rq]]);const Fq=G({name:\"Hide\"}),Bq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},Vq=Z(\"path\",{d:\"M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2L371.2 588.8ZM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z\",fill:\"currentColor\"},null,-1),zq=Z(\"path\",{d:\"M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z\",fill:\"currentColor\"},null,-1),Hq=[Vq,zq];function jq(e,t,n,r,a,o){return R(),X(\"svg\",Bq,Hq)}var Kq=Xt(Fq,[[\"render\",jq]]);const Wq=G({name:\"InfoFilled\"}),Uq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},Yq=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896.064A448 448 0 0 1 512 64zm67.2 275.072c33.28 0 60.288-23.104 60.288-57.344s-27.072-57.344-60.288-57.344c-33.28 0-60.16 23.104-60.16 57.344s26.88 57.344 60.16 57.344zM590.912 699.2c0-6.848 2.368-24.64 1.024-34.752l-52.608 60.544c-10.88 11.456-24.512 19.392-30.912 17.28a12.992 12.992 0 0 1-8.256-14.72l87.68-276.992c7.168-35.136-12.544-67.2-54.336-71.296-44.096 0-108.992 44.736-148.48 101.504 0 6.784-1.28 23.68.064 33.792l52.544-60.608c10.88-11.328 23.552-19.328 29.952-17.152a12.8 12.8 0 0 1 7.808 16.128L388.48 728.576c-10.048 32.256 8.96 63.872 55.04 71.04 67.84 0 107.904-43.648 147.456-100.416z\"},null,-1),qq=[Yq];function Gq(e,t,n,r,a,o){return R(),X(\"svg\",Uq,qq)}var LC=Xt(Wq,[[\"render\",Gq]]);const Xq=G({name:\"Loading\"}),Zq={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},Jq=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z\"},null,-1),Qq=[Jq];function eG(e,t,n,r,a,o){return R(),X(\"svg\",Zq,Qq)}var gl=Xt(Xq,[[\"render\",eG]]);const tG=G({name:\"Minus\"}),nG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},rG=Z(\"path\",{fill:\"currentColor\",d:\"M128 544h768a32 32 0 1 0 0-64H128a32 32 0 0 0 0 64z\"},null,-1),aG=[rG];function oG(e,t,n,r,a,o){return R(),X(\"svg\",nG,aG)}var iG=Xt(tG,[[\"render\",oG]]);const lG=G({name:\"MoreFilled\"}),sG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},uG=Z(\"path\",{fill:\"currentColor\",d:\"M176 416a112 112 0 1 1 0 224 112 112 0 0 1 0-224zm336 0a112 112 0 1 1 0 224 112 112 0 0 1 0-224zm336 0a112 112 0 1 1 0 224 112 112 0 0 1 0-224z\"},null,-1),cG=[uG];function dG(e,t,n,r,a,o){return R(),X(\"svg\",sG,cG)}var fG=Xt(lG,[[\"render\",dG]]);const hG=G({name:\"More\"}),pG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},vG=Z(\"path\",{fill:\"currentColor\",d:\"M176 416a112 112 0 1 0 0 224 112 112 0 0 0 0-224m0 64a48 48 0 1 1 0 96 48 48 0 0 1 0-96zm336-64a112 112 0 1 1 0 224 112 112 0 0 1 0-224zm0 64a48 48 0 1 0 0 96 48 48 0 0 0 0-96zm336-64a112 112 0 1 1 0 224 112 112 0 0 1 0-224zm0 64a48 48 0 1 0 0 96 48 48 0 0 0 0-96z\"},null,-1),mG=[vG];function gG(e,t,n,r,a,o){return R(),X(\"svg\",pG,mG)}var yG=Xt(hG,[[\"render\",gG]]);const bG=G({name:\"PictureFilled\"}),CG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},wG=Z(\"path\",{fill:\"currentColor\",d:\"M96 896a32 32 0 0 1-32-32V160a32 32 0 0 1 32-32h832a32 32 0 0 1 32 32v704a32 32 0 0 1-32 32H96zm315.52-228.48-68.928-68.928a32 32 0 0 0-45.248 0L128 768.064h778.688l-242.112-290.56a32 32 0 0 0-49.216 0L458.752 665.408a32 32 0 0 1-47.232 2.112zM256 384a96 96 0 1 0 192.064-.064A96 96 0 0 0 256 384z\"},null,-1),SG=[wG];function kG(e,t,n,r,a,o){return R(),X(\"svg\",CG,SG)}var $G=Xt(bG,[[\"render\",kG]]);const OG=G({name:\"Plus\"}),PG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},TG=Z(\"path\",{fill:\"currentColor\",d:\"M480 480V128a32 32 0 0 1 64 0v352h352a32 32 0 1 1 0 64H544v352a32 32 0 1 1-64 0V544H128a32 32 0 0 1 0-64h352z\"},null,-1),xG=[TG];function _G(e,t,n,r,a,o){return R(),X(\"svg\",PG,xG)}var cE=Xt(OG,[[\"render\",_G]]);const EG=G({name:\"QuestionFilled\"}),MG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},IG=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm23.744 191.488c-52.096 0-92.928 14.784-123.2 44.352-30.976 29.568-45.76 70.4-45.76 122.496h80.256c0-29.568 5.632-52.8 17.6-68.992 13.376-19.712 35.2-28.864 66.176-28.864 23.936 0 42.944 6.336 56.32 19.712 12.672 13.376 19.712 31.68 19.712 54.912 0 17.6-6.336 34.496-19.008 49.984l-8.448 9.856c-45.76 40.832-73.216 70.4-82.368 89.408-9.856 19.008-14.08 42.24-14.08 68.992v9.856h80.96v-9.856c0-16.896 3.52-31.68 10.56-45.76 6.336-12.672 15.488-24.64 28.16-35.2 33.792-29.568 54.208-48.576 60.544-55.616 16.896-22.528 26.048-51.392 26.048-86.592 0-42.944-14.08-76.736-42.24-101.376-28.16-25.344-65.472-37.312-111.232-37.312zm-12.672 406.208a54.272 54.272 0 0 0-38.72 14.784 49.408 49.408 0 0 0-15.488 38.016c0 15.488 4.928 28.16 15.488 38.016A54.848 54.848 0 0 0 523.072 768c15.488 0 28.16-4.928 38.72-14.784a51.52 51.52 0 0 0 16.192-38.72 51.968 51.968 0 0 0-15.488-38.016 55.936 55.936 0 0 0-39.424-14.784z\"},null,-1),NG=[IG];function AG(e,t,n,r,a,o){return R(),X(\"svg\",MG,NG)}var DG=Xt(EG,[[\"render\",AG]]);const RG=G({name:\"RefreshLeft\"}),LG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},FG=Z(\"path\",{fill:\"currentColor\",d:\"M289.088 296.704h92.992a32 32 0 0 1 0 64H232.96a32 32 0 0 1-32-32V179.712a32 32 0 0 1 64 0v50.56a384 384 0 0 1 643.84 282.88 384 384 0 0 1-383.936 384 384 384 0 0 1-384-384h64a320 320 0 1 0 640 0 320 320 0 0 0-555.712-216.448z\"},null,-1),BG=[FG];function VG(e,t,n,r,a,o){return R(),X(\"svg\",LG,BG)}var zG=Xt(RG,[[\"render\",VG]]);const HG=G({name:\"RefreshRight\"}),jG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},KG=Z(\"path\",{fill:\"currentColor\",d:\"M784.512 230.272v-50.56a32 32 0 1 1 64 0v149.056a32 32 0 0 1-32 32H667.52a32 32 0 1 1 0-64h92.992A320 320 0 1 0 524.8 833.152a320 320 0 0 0 320-320h64a384 384 0 0 1-384 384 384 384 0 0 1-384-384 384 384 0 0 1 643.712-282.88z\"},null,-1),WG=[KG];function UG(e,t,n,r,a,o){return R(),X(\"svg\",jG,WG)}var YG=Xt(HG,[[\"render\",UG]]);const qG=G({name:\"ScaleToOriginal\"}),GG={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},XG=Z(\"path\",{fill:\"currentColor\",d:\"M813.176 180.706a60.235 60.235 0 0 1 60.236 60.235v481.883a60.235 60.235 0 0 1-60.236 60.235H210.824a60.235 60.235 0 0 1-60.236-60.235V240.94a60.235 60.235 0 0 1 60.236-60.235h602.352zm0-60.235H210.824A120.47 120.47 0 0 0 90.353 240.94v481.883a120.47 120.47 0 0 0 120.47 120.47h602.353a120.47 120.47 0 0 0 120.471-120.47V240.94a120.47 120.47 0 0 0-120.47-120.47zm-120.47 180.705a30.118 30.118 0 0 0-30.118 30.118v301.177a30.118 30.118 0 0 0 60.236 0V331.294a30.118 30.118 0 0 0-30.118-30.118zm-361.412 0a30.118 30.118 0 0 0-30.118 30.118v301.177a30.118 30.118 0 1 0 60.236 0V331.294a30.118 30.118 0 0 0-30.118-30.118zM512 361.412a30.118 30.118 0 0 0-30.118 30.117v30.118a30.118 30.118 0 0 0 60.236 0V391.53A30.118 30.118 0 0 0 512 361.412zM512 512a30.118 30.118 0 0 0-30.118 30.118v30.117a30.118 30.118 0 0 0 60.236 0v-30.117A30.118 30.118 0 0 0 512 512z\"},null,-1),ZG=[XG];function JG(e,t,n,r,a,o){return R(),X(\"svg\",GG,ZG)}var QG=Xt(qG,[[\"render\",JG]]);const eX=G({name:\"Search\"}),tX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},nX=Z(\"path\",{fill:\"currentColor\",d:\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704z\"},null,-1),rX=[nX];function aX(e,t,n,r,a,o){return R(),X(\"svg\",tX,rX)}var oX=Xt(eX,[[\"render\",aX]]);const iX=G({name:\"StarFilled\"}),lX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},sX=Z(\"path\",{fill:\"currentColor\",d:\"M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z\"},null,-1),uX=[sX];function cX(e,t,n,r,a,o){return R(),X(\"svg\",lX,uX)}var oh=Xt(iX,[[\"render\",cX]]);const dX=G({name:\"Star\"}),fX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},hX=Z(\"path\",{fill:\"currentColor\",d:\"m512 747.84 228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72L512 747.84zM313.6 924.48a70.4 70.4 0 0 1-102.144-74.24l37.888-220.928L88.96 472.96A70.4 70.4 0 0 1 128 352.896l221.76-32.256 99.2-200.96a70.4 70.4 0 0 1 126.208 0l99.2 200.96 221.824 32.256a70.4 70.4 0 0 1 39.04 120.064L774.72 629.376l37.888 220.928a70.4 70.4 0 0 1-102.144 74.24L512 820.096l-198.4 104.32z\"},null,-1),pX=[hX];function vX(e,t,n,r,a,o){return R(),X(\"svg\",fX,pX)}var mX=Xt(dX,[[\"render\",vX]]);const gX=G({name:\"SuccessFilled\"}),yX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},bX=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-55.808 536.384-99.52-99.584a38.4 38.4 0 1 0-54.336 54.336l126.72 126.72a38.272 38.272 0 0 0 54.336 0l262.4-262.464a38.4 38.4 0 1 0-54.272-54.336L456.192 600.384z\"},null,-1),CX=[bX];function wX(e,t,n,r,a,o){return R(),X(\"svg\",yX,CX)}var dE=Xt(gX,[[\"render\",wX]]);const SX=G({name:\"View\"}),kX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},$X=Z(\"path\",{fill:\"currentColor\",d:\"M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352zm0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288zm0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448zm0 64a160.192 160.192 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160z\"},null,-1),OX=[$X];function PX(e,t,n,r,a,o){return R(),X(\"svg\",kX,OX)}var TX=Xt(SX,[[\"render\",PX]]);const xX=G({name:\"WarningFilled\"}),_X={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},EX=Z(\"path\",{fill:\"currentColor\",d:\"M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 192a58.432 58.432 0 0 0-58.24 63.744l23.36 256.384a35.072 35.072 0 0 0 69.76 0l23.296-256.384A58.432 58.432 0 0 0 512 256zm0 512a51.2 51.2 0 1 0 0-102.4 51.2 51.2 0 0 0 0 102.4z\"},null,-1),MX=[EX];function IX(e,t,n,r,a,o){return R(),X(\"svg\",_X,MX)}var Wd=Xt(xX,[[\"render\",IX]]);const NX=G({name:\"ZoomIn\"}),AX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},DX=Z(\"path\",{fill:\"currentColor\",d:\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704zm-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64h96z\"},null,-1),RX=[DX];function LX(e,t,n,r,a,o){return R(),X(\"svg\",AX,RX)}var fE=Xt(NX,[[\"render\",LX]]);const FX=G({name:\"ZoomOut\"}),BX={viewBox:\"0 0 1024 1024\",xmlns:\"http://www.w3.org/2000/svg\"},VX=Z(\"path\",{fill:\"currentColor\",d:\"m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704zM352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64z\"},null,-1),zX=[VX];function HX(e,t,n,r,a,o){return R(),X(\"svg\",BX,zX)}var jX=Xt(FX,[[\"render\",HX]]);const h0=Symbol(),X$=\"__elPropsReservedKey\";function ho(e,t){if(!zt(e)||!!e[X$])return e;const{values:n,required:r,default:a,type:o,validator:i}=e,l=n||i?c=>{let d=!1,f=[];if(n&&(f=Array.from(n),Mt(e,\"default\")&&f.push(a),d||(d=f.includes(c))),i&&(d||(d=i(c))),!d&&f.length>0){const p=[...new Set(f)].map(v=>JSON.stringify(v)).join(\", \");hL(`Invalid prop: validation failed${t?` for prop \"${t}\"`:\"\"}. Expected one of [${p}], got value ${JSON.stringify(c)}.`)}return d}:void 0,s={type:zt(o)&&Object.getOwnPropertySymbols(o).includes(h0)?o[h0]:o,required:!!r,validator:l,[X$]:!0};return Mt(e,\"default\")&&(s.default=a),s}const Ze=e=>Y8(Object.entries(e).map(([t,n])=>[t,ho(n,t)])),Le=e=>({[h0]:e}),wr=Le([String,Object,Function]),KX={Close:Ma},Vm={Close:Ma,SuccessFilled:dE,InfoFilled:LC,WarningFilled:Wd,CircleCloseFilled:RC},yi={success:dE,warning:Wd,error:RC,info:LC},hE={validating:gl,success:mv,error:gi},xt=(e,t)=>{if(e.install=n=>{for(const r of[e,...Object.values(t!=null?t:{})])n.component(r.name,r)},t)for(const[n,r]of Object.entries(t))e[n]=r;return e},pE=(e,t)=>(e.install=n=>{e._context=n._context,n.config.globalProperties[t]=e},e),En=e=>(e.install=Qt,e),FC=(...e)=>t=>{e.forEach(n=>{Ct(n)?n(t):n.value=t})};class WX extends Error{constructor(t){super(t),this.name=\"ElementPlusError\"}}function qn(e,t){throw new WX(`[${e}] ${t}`)}function oo(e,t=\"px\"){if(!e)return\"\";if(wt(e))return e;if(Yt(e))return`${e}${t}`}const Ge={tab:\"Tab\",enter:\"Enter\",space:\"Space\",left:\"ArrowLeft\",up:\"ArrowUp\",right:\"ArrowRight\",down:\"ArrowDown\",esc:\"Escape\",delete:\"Delete\",backspace:\"Backspace\",numpadEnter:\"NumpadEnter\",pageUp:\"PageUp\",pageDown:\"PageDown\",home:\"Home\",end:\"End\"},UX=[\"year\",\"month\",\"date\",\"dates\",\"week\",\"datetime\",\"datetimerange\",\"daterange\",\"monthrange\"],ay=[\"sun\",\"mon\",\"tue\",\"wed\",\"thu\",\"fri\",\"sat\"],Pt=\"update:modelValue\",ir=\"change\",cl=\"input\",Bo=[\"\",\"default\",\"small\",\"large\"],YX={large:40,default:32,small:24},vE=(e=\"default\")=>YX[e||\"default\"],va=e=>[\"\",...Bo].includes(e),mE=e=>[...UX].includes(e);var ka=(e=>(e[e.TEXT=1]=\"TEXT\",e[e.CLASS=2]=\"CLASS\",e[e.STYLE=4]=\"STYLE\",e[e.PROPS=8]=\"PROPS\",e[e.FULL_PROPS=16]=\"FULL_PROPS\",e[e.HYDRATE_EVENTS=32]=\"HYDRATE_EVENTS\",e[e.STABLE_FRAGMENT=64]=\"STABLE_FRAGMENT\",e[e.KEYED_FRAGMENT=128]=\"KEYED_FRAGMENT\",e[e.UNKEYED_FRAGMENT=256]=\"UNKEYED_FRAGMENT\",e[e.NEED_PATCH=512]=\"NEED_PATCH\",e[e.DYNAMIC_SLOTS=1024]=\"DYNAMIC_SLOTS\",e[e.HOISTED=-1]=\"HOISTED\",e[e.BAIL=-2]=\"BAIL\",e))(ka||{});function gE(e){return rn(e)&&e.type===Fe}function qX(e){return rn(e)&&e.type===Ir}function GX(e){return rn(e)&&!gE(e)&&!qX(e)}const XX=e=>{if(!rn(e))return{};const t=e.props||{},n=(rn(e.type)?e.type.props:void 0)||{},r={};return Object.keys(n).forEach(a=>{Mt(n[a],\"default\")&&(r[a]=n[a].default)}),Object.keys(t).forEach(a=>{r[_a(a)]=t[a]}),r},ZX=e=>{if(!pt(e)||e.length>1)throw new Error(\"expect to receive a single Vue element child\");return e[0]},Z$=e=>e**3,JX=e=>e<.5?Z$(e*2)/2:1-Z$((1-e)*2)/2,J$=e=>[...new Set(e)],rs=e=>!e&&e!==0?[]:Array.isArray(e)?e:[e],BC=()=>Bt&&/firefox/i.test(window.navigator.userAgent),zm=e=>/([(\\uAC00-\\uD7AF)|(\\u3130-\\u318F)])+/gi.test(e),yE=e=>Bt?window.requestAnimationFrame(e):setTimeout(e,16),bE=e=>Bt?window.cancelAnimationFrame(e):clearTimeout(e),Pf=()=>Math.floor(Math.random()*1e4),xn=e=>e,QX=[\"class\",\"style\"],eZ=/^on[A-Z]/,VC=(e={})=>{const{excludeListeners:t=!1,excludeKeys:n=[]}=e,r=n.concat(QX),a=$t();return x(a?()=>{var o;return Y8(Object.entries((o=a.proxy)==null?void 0:o.$attrs).filter(([i])=>!r.includes(i)&&!(t&&eZ.test(i))))}:()=>({}))},CE=Symbol(\"breadcrumbKey\"),wE=Symbol(\"buttonGroupContextKey\"),SE=Symbol(\"carouselContextKey\"),kE=Symbol(\"collapseContextKey\"),$E=Symbol(),OE=Symbol(\"dialogInjectionKey\"),ga=Symbol(\"formContextKey\"),Ia=Symbol(\"formItemContextKey\"),PE=Symbol(\"elPaginationKey\"),TE=Symbol(\"radioGroupKey\"),xE=Symbol(\"rowContextKey\"),_E=Symbol(\"scrollbarContextKey\"),Hm=Symbol(\"tabsRootContextKey\"),EE=Symbol(\"uploadContextKey\"),zC=Symbol(\"popper\"),ME=Symbol(\"popperContent\"),jm=Symbol(\"tooltipV2\"),IE=Symbol(\"tooltipV2Content\"),oy=\"tooltip_v2.open\",NE=e=>{const t=$t();return x(()=>{var n,r;return(r=(n=t.proxy)==null?void 0:n.$props[e])!=null?r:void 0})},gv=H();function kc(e,t=void 0){const n=$t()?ve($E,gv):gv;return e?x(()=>{var r,a;return(a=(r=n.value)==null?void 0:r[e])!=null?a:t}):n}const AE=(e,t,n=!1)=>{var r;const a=!!$t(),o=a?kc():void 0,i=(r=t==null?void 0:t.provide)!=null?r:a?ot:void 0;if(!i)return;const l=x(()=>{const s=A(e);return o!=null&&o.value?tZ(o.value,s):s});return i($E,l),(n||!gv.value)&&(gv.value=l.value),l},tZ=(e,t)=>{var n;const r=[...new Set([...f0(e),...f0(t)])],a={};for(const o of r)a[o]=(n=t[o])!=null?n:e[o];return a},Km=ho({type:String,values:Bo,required:!1}),Gn=(e,t={})=>{const n=H(void 0),r=t.prop?n:NE(\"size\"),a=t.global?n:kc(\"size\"),o=t.form?{size:void 0}:ve(ga,void 0),i=t.formItem?{size:void 0}:ve(Ia,void 0);return x(()=>r.value||A(e)||(i==null?void 0:i.size)||(o==null?void 0:o.size)||a.value||\"\")},Ms=e=>{const t=NE(\"disabled\"),n=ve(ga,void 0);return x(()=>t.value||A(e)||(n==null?void 0:n.disabled)||!1)},Tf=({from:e,replacement:t,scope:n,version:r,ref:a,type:o=\"API\"},i)=>{ce(()=>A(i),l=>{},{immediate:!0})},DE=(e,t,n)=>{let r={offsetX:0,offsetY:0};const a=l=>{const s=l.clientX,c=l.clientY,{offsetX:d,offsetY:f}=r,p=e.value.getBoundingClientRect(),v=p.left,m=p.top,y=p.width,b=p.height,C=document.documentElement.clientWidth,S=document.documentElement.clientHeight,w=-v+d,k=-m+f,$=C-v-y+d,O=S-m-b+f,T=I=>{const L=Math.min(Math.max(d+I.clientX-s,w),$),j=Math.min(Math.max(f+I.clientY-c,k),O);r={offsetX:L,offsetY:j},e.value.style.transform=`translate(${oo(L)}, ${oo(j)})`},_=()=>{document.removeEventListener(\"mousemove\",T),document.removeEventListener(\"mouseup\",_)};document.addEventListener(\"mousemove\",T),document.addEventListener(\"mouseup\",_)},o=()=>{t.value&&e.value&&t.value.addEventListener(\"mousedown\",a)},i=()=>{t.value&&e.value&&t.value.removeEventListener(\"mousedown\",a)};et(()=>{Wn(()=>{n.value?o():i()})}),Lt(()=>{i()})},nZ=e=>({focus:()=>{var t,n;(n=(t=e.value)==null?void 0:t.focus)==null||n.call(t)}}),$c=()=>{const e=ve(ga,void 0),t=ve(Ia,void 0);return{form:e,formItem:t}};var rZ={name:\"en\",el:{colorpicker:{confirm:\"OK\",clear:\"Clear\"},datepicker:{now:\"Now\",today:\"Today\",cancel:\"Cancel\",clear:\"Clear\",confirm:\"OK\",selectDate:\"Select date\",selectTime:\"Select time\",startDate:\"Start Date\",startTime:\"Start Time\",endDate:\"End Date\",endTime:\"End Time\",prevYear:\"Previous Year\",nextYear:\"Next Year\",prevMonth:\"Previous Month\",nextMonth:\"Next Month\",year:\"\",month1:\"January\",month2:\"February\",month3:\"March\",month4:\"April\",month5:\"May\",month6:\"June\",month7:\"July\",month8:\"August\",month9:\"September\",month10:\"October\",month11:\"November\",month12:\"December\",week:\"week\",weeks:{sun:\"Sun\",mon:\"Mon\",tue:\"Tue\",wed:\"Wed\",thu:\"Thu\",fri:\"Fri\",sat:\"Sat\"},months:{jan:\"Jan\",feb:\"Feb\",mar:\"Mar\",apr:\"Apr\",may:\"May\",jun:\"Jun\",jul:\"Jul\",aug:\"Aug\",sep:\"Sep\",oct:\"Oct\",nov:\"Nov\",dec:\"Dec\"}},select:{loading:\"Loading\",noMatch:\"No matching data\",noData:\"No data\",placeholder:\"Select\"},cascader:{noMatch:\"No matching data\",loading:\"Loading\",placeholder:\"Select\",noData:\"No data\"},pagination:{goto:\"Go to\",pagesize:\"/page\",total:\"Total {total}\",pageClassifier:\"\",deprecationWarning:\"Deprecated usages detected, please refer to the el-pagination documentation for more details\"},messagebox:{title:\"Message\",confirm:\"OK\",cancel:\"Cancel\",error:\"Illegal input\"},upload:{deleteTip:\"press delete to remove\",delete:\"Delete\",preview:\"Preview\",continue:\"Continue\"},table:{emptyText:\"No Data\",confirmFilter:\"Confirm\",resetFilter:\"Reset\",clearFilter:\"All\",sumText:\"Sum\"},tree:{emptyText:\"No Data\"},transfer:{noMatch:\"No matching data\",noData:\"No data\",titles:[\"List 1\",\"List 2\"],filterPlaceholder:\"Enter keyword\",noCheckedFormat:\"{total} items\",hasCheckedFormat:\"{checked}/{total} checked\"},image:{error:\"FAILED\"},pageHeader:{title:\"Back\"},popconfirm:{confirmButtonText:\"Yes\",cancelButtonText:\"No\"}}};const aZ=e=>(t,n)=>oZ(t,n,A(e)),oZ=(e,t,n)=>vn(n,e,e).replace(/\\{(\\w+)\\}/g,(r,a)=>{var o;return`${(o=t==null?void 0:t[a])!=null?o:`{${a}}`}`}),iZ=e=>{const t=x(()=>A(e).name),n=_n(e)?e:H(e);return{lang:t,locale:n,t:aZ(e)}},ln=()=>{const e=kc(\"locale\");return iZ(x(()=>e.value||rZ))},RE=e=>{if(_n(e)||qn(\"[useLockscreen]\",\"You need to pass a ref param to this function\"),!Bt||to(document.body,\"el-popup-parent--hidden\"))return;let t=0,n=!1,r=\"0\",a=0;const o=()=>{Br(document.body,\"el-popup-parent--hidden\"),n&&(document.body.style.paddingRight=r)};ce(e,i=>{if(!i){o();return}n=!to(document.body,\"el-popup-parent--hidden\"),n&&(r=document.body.style.paddingRight,a=Number.parseInt($o(document.body,\"paddingRight\"),10)),t=NU();const l=document.documentElement.clientHeight<document.body.scrollHeight,s=$o(document.body,\"overflowY\");t>0&&(l||s===\"scroll\")&&n&&(document.body.style.paddingRight=`${a+t}px`),xo(document.body,\"el-popup-parent--hidden\")}),Z_(()=>o())},Tu=[],lZ=e=>{Tu.length!==0&&e.code===Ge.esc&&(e.stopPropagation(),Tu[Tu.length-1].handleClose())},LE=(e,t)=>{ce(t,n=>{n?Tu.push(e):Tu.splice(Tu.indexOf(e),1)})};Bt&&Hn(document,\"keydown\",lZ);const sZ=ho({type:Le(Boolean),default:null}),uZ=ho({type:Le(Function)}),cZ=e=>{const t={[e]:sZ,[`onUpdate:${e}`]:uZ},n=[`update:${e}`];return{useModelToggle:({indicator:a,shouldHideWhenRouteChanges:o,shouldProceed:i,onShow:l,onHide:s})=>{const c=$t(),d=c.props,{emit:f}=c,p=`update:${e}`,v=x(()=>Ct(d[`onUpdate:${e}`])),m=x(()=>d[e]===null),y=()=>{a.value!==!0&&(a.value=!0,Ct(l)&&l())},b=()=>{a.value!==!1&&(a.value=!1,Ct(s)&&s())},C=()=>{if(d.disabled===!0||Ct(i)&&!i())return;const $=v.value&&Bt;$&&f(p,!0),(m.value||!$)&&y()},S=()=>{if(d.disabled===!0||!Bt)return;const $=v.value&&Bt;$&&f(p,!1),(m.value||!$)&&b()},w=$=>{!yr($)||(d.disabled&&$?v.value&&f(p,!1):a.value!==$&&($?y():b()))},k=()=>{a.value?S():C()};return ce(()=>d[e],w),o&&c.appContext.config.globalProperties.$route!==void 0&&ce(()=>Te({},c.proxy.$route),()=>{o.value&&a.value&&S()}),et(()=>{w(d[e])}),{hide:S,show:C,toggle:k}},useModelToggleProps:t,useModelToggleEmits:n}},dZ=(e,t,n)=>{const r=o=>{n(o)&&o.stopImmediatePropagation()};let a;ce(()=>e.value,o=>{o?a=Hn(document,t,r,!0):a==null||a()},{immediate:!0})},FE=(e,t)=>{let n;ce(()=>e.value,r=>{var a,o;r?(n=document.activeElement,_n(t)&&((o=(a=t.value).focus)==null||o.call(a))):n.focus()})},HC=e=>{if(!e)return{onClick:Qt,onMousedown:Qt,onMouseup:Qt};let t=!1,n=!1;return{onClick:i=>{t&&n&&e(i),t=n=!1},onMousedown:i=>{t=i.target===i.currentTarget},onMouseup:i=>{n=i.target===i.currentTarget}}},fZ=(e,t=0)=>{if(t===0)return e;const n=H(!1);let r=0;const a=()=>{r&&clearTimeout(r),r=window.setTimeout(()=>{n.value=e.value},t)};return et(a),ce(()=>e.value,o=>{o?a():n.value=o}),n};function hZ(){let e;const t=(r,a)=>{n(),e=window.setTimeout(r,a)},n=()=>window.clearTimeout(e);return Lm(()=>n()),{registerTimeout:t,cancelTimeout:n}}const pZ={prefix:Math.floor(Math.random()*1e4),current:0},vZ=Symbol(\"elIdInjection\"),jC=e=>{const t=ve(vZ,pZ);return x(()=>A(e)||`el-id-${t.prefix}-${t.current++}`)},mZ=e=>{const t=n=>{const r=n;r.key===Ge.esc&&(e==null||e(r))};et(()=>{gn(document,\"keydown\",t)}),Lt(()=>{Bn(document,\"keydown\",t)})};let Q$;const BE=`el-popper-container-${Pf()}`,VE=`#${BE}`,gZ=()=>{const e=document.createElement(\"div\");return e.id=BE,document.body.appendChild(e),e},yZ=()=>{hc(()=>{!Bt||(!Q$||!document.body.querySelector(VE))&&(Q$=gZ())})},bZ=Ze({showAfter:{type:Number,default:0},hideAfter:{type:Number,default:200}}),CZ=({showAfter:e,hideAfter:t,open:n,close:r})=>{const{registerTimeout:a}=hZ();return{onOpen:()=>{a(()=>{n()},A(e))},onClose:()=>{a(()=>{r()},A(t))}}},zE=Symbol(\"elForwardRef\"),wZ=e=>{ot(zE,{setForwardRef:n=>{e.value=n}})},SZ=e=>({mounted(t){e(t)},updated(t){e(t)},unmounted(){e(null)}}),kZ=\"el\",$Z=\"is-\",kl=(e,t,n,r,a)=>{let o=`${e}-${t}`;return n&&(o+=`-${n}`),r&&(o+=`__${r}`),a&&(o+=`--${a}`),o},De=e=>{const t=kc(\"namespace\"),n=x(()=>t.value||kZ);return{namespace:n,b:(f=\"\")=>kl(A(n),e,f,\"\",\"\"),e:f=>f?kl(A(n),e,\"\",f,\"\"):\"\",m:f=>f?kl(A(n),e,\"\",\"\",f):\"\",be:(f,p)=>f&&p?kl(A(n),e,f,p,\"\"):\"\",em:(f,p)=>f&&p?kl(A(n),e,\"\",f,p):\"\",bm:(f,p)=>f&&p?kl(A(n),e,f,\"\",p):\"\",bem:(f,p,v)=>f&&p&&v?kl(A(n),e,f,p,v):\"\",is:(f,...p)=>{const v=p.length>=1?p[0]:!0;return f&&v?`${$Z}${f}`:\"\"}}},e4=H(0),Pi=()=>{const e=kc(\"zIndex\",2e3),t=x(()=>e.value+e4.value);return{initialZIndex:e,currentZIndex:t,nextZIndex:()=>(e4.value++,t.value)}};function KC(e){return e.split(\"-\")[0]}function HE(e){return e.split(\"-\")[1]}function WC(e){return[\"top\",\"bottom\"].includes(KC(e))?\"x\":\"y\"}function jE(e){return e===\"y\"?\"height\":\"width\"}function t4(e,t,n){let{reference:r,floating:a}=e;const o=r.x+r.width/2-a.width/2,i=r.y+r.height/2-a.height/2,l=WC(t),s=jE(l),c=r[s]/2-a[s]/2,d=l===\"x\";let f;switch(KC(t)){case\"top\":f={x:o,y:r.y-a.height};break;case\"bottom\":f={x:o,y:r.y+r.height};break;case\"right\":f={x:r.x+r.width,y:i};break;case\"left\":f={x:r.x-a.width,y:i};break;default:f={x:r.x,y:r.y}}switch(HE(t)){case\"start\":f[l]-=c*(n&&d?-1:1);break;case\"end\":f[l]+=c*(n&&d?-1:1)}return f}const OZ=async(e,t,n)=>{const{placement:r=\"bottom\",strategy:a=\"absolute\",middleware:o=[],platform:i}=n,l=await(i.isRTL==null?void 0:i.isRTL(t));let s=await i.getElementRects({reference:e,floating:t,strategy:a}),{x:c,y:d}=t4(s,r,l),f=r,p={};for(let v=0;v<o.length;v++){const{name:m,fn:y}=o[v],{x:b,y:C,data:S,reset:w}=await y({x:c,y:d,initialPlacement:r,placement:f,strategy:a,middlewareData:p,rects:s,platform:i,elements:{reference:e,floating:t}});c=b!=null?b:c,d=C!=null?C:d,p=Ke(Te({},p),{[m]:Te(Te({},p[m]),S)}),w&&(typeof w==\"object\"&&(w.placement&&(f=w.placement),w.rects&&(s=w.rects===!0?await i.getElementRects({reference:e,floating:t,strategy:a}):w.rects),{x:c,y:d}=t4(s,f,l)),v=-1)}return{x:c,y:d,placement:f,strategy:a,middlewareData:p}};function PZ(e){return typeof e!=\"number\"?function(t){return Te({top:0,right:0,bottom:0,left:0},t)}(e):{top:e,right:e,bottom:e,left:e}}function n4(e){return Ke(Te({},e),{top:e.y,left:e.x,right:e.x+e.width,bottom:e.y+e.height})}const TZ=Math.min,xZ=Math.max;function _Z(e,t,n){return xZ(e,TZ(t,n))}const EZ=e=>({name:\"arrow\",options:e,async fn(t){const{element:n,padding:r=0}=e!=null?e:{},{x:a,y:o,placement:i,rects:l,platform:s}=t;if(n==null)return{};const c=PZ(r),d={x:a,y:o},f=WC(i),p=jE(f),v=await s.getDimensions(n),m=f===\"y\"?\"top\":\"left\",y=f===\"y\"?\"bottom\":\"right\",b=l.reference[p]+l.reference[f]-d[f]-l.floating[p],C=d[f]-l.reference[f],S=await(s.getOffsetParent==null?void 0:s.getOffsetParent(n)),w=S?f===\"y\"?S.clientHeight||0:S.clientWidth||0:0,k=b/2-C/2,$=c[m],O=w-v[p]-c[y],T=w/2-v[p]/2+k,_=_Z($,T,O);return{data:{[f]:_,centerOffset:T-_}}}}),MZ=[\"top\",\"right\",\"bottom\",\"left\"];MZ.reduce((e,t)=>e.concat(t,t+\"-start\",t+\"-end\"),[]);const IZ=function(e){return e===void 0&&(e=0),{name:\"offset\",options:e,async fn(t){const{x:n,y:r,placement:a,rects:o,platform:i,elements:l}=t,s=function(c,d,f,p){p===void 0&&(p=!1);const v=KC(c),m=HE(c),y=WC(c)===\"x\",b=[\"left\",\"top\"].includes(v)?-1:1,C=p&&y?-1:1,S=typeof f==\"function\"?f(Ke(Te({},d),{placement:c})):f,w=typeof S==\"number\";let{mainAxis:k,crossAxis:$,alignmentAxis:O}=w?{mainAxis:S,crossAxis:0,alignmentAxis:null}:Te({mainAxis:0,crossAxis:0,alignmentAxis:null},S);return m&&typeof O==\"number\"&&($=m===\"end\"?-1*O:O),y?{x:$*C,y:k*b}:{x:k*b,y:$*C}}(a,o,e,await(i.isRTL==null?void 0:i.isRTL(l.floating)));return{x:n+s.x,y:r+s.y,data:s}}}};function KE(e){return e&&e.document&&e.location&&e.alert&&e.setInterval}function Ti(e){if(e==null)return window;if(!KE(e)){const t=e.ownerDocument;return t&&t.defaultView||window}return e}function xf(e){return Ti(e).getComputedStyle(e)}function di(e){return KE(e)?\"\":e?(e.nodeName||\"\").toLowerCase():\"\"}function No(e){return e instanceof Ti(e).HTMLElement}function Uu(e){return e instanceof Ti(e).Element}function UC(e){return e instanceof Ti(e).ShadowRoot||e instanceof ShadowRoot}function Wm(e){const{overflow:t,overflowX:n,overflowY:r}=xf(e);return/auto|scroll|overlay|hidden/.test(t+r+n)}function NZ(e){return[\"table\",\"td\",\"th\"].includes(di(e))}function r4(e){const t=navigator.userAgent.toLowerCase().includes(\"firefox\"),n=xf(e);return n.transform!==\"none\"||n.perspective!==\"none\"||n.contain===\"paint\"||[\"transform\",\"perspective\"].includes(n.willChange)||t&&n.willChange===\"filter\"||t&&!!n.filter&&n.filter!==\"none\"}function WE(){return!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}const a4=Math.min,vd=Math.max,yv=Math.round;function as(e,t,n){var r,a,o,i;t===void 0&&(t=!1),n===void 0&&(n=!1);const l=e.getBoundingClientRect();let s=1,c=1;t&&No(e)&&(s=e.offsetWidth>0&&yv(l.width)/e.offsetWidth||1,c=e.offsetHeight>0&&yv(l.height)/e.offsetHeight||1);const d=Uu(e)?Ti(e):window,f=!WE()&&n,p=(l.left+(f&&(r=(a=d.visualViewport)==null?void 0:a.offsetLeft)!=null?r:0))/s,v=(l.top+(f&&(o=(i=d.visualViewport)==null?void 0:i.offsetTop)!=null?o:0))/c,m=l.width/s,y=l.height/c;return{width:m,height:y,top:v,right:p+m,bottom:v+y,left:p,x:p,y:v}}function el(e){return(t=e,(t instanceof Ti(t).Node?e.ownerDocument:e.document)||window.document).documentElement;var t}function Um(e){return Uu(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function UE(e){return as(el(e)).left+Um(e).scrollLeft}function AZ(e,t,n){const r=No(t),a=el(t),o=as(e,r&&function(s){const c=as(s);return yv(c.width)!==s.offsetWidth||yv(c.height)!==s.offsetHeight}(t),n===\"fixed\");let i={scrollLeft:0,scrollTop:0};const l={x:0,y:0};if(r||!r&&n!==\"fixed\")if((di(t)!==\"body\"||Wm(a))&&(i=Um(t)),No(t)){const s=as(t,!0);l.x=s.x+t.clientLeft,l.y=s.y+t.clientTop}else a&&(l.x=UE(a));return{x:o.left+i.scrollLeft-l.x,y:o.top+i.scrollTop-l.y,width:o.width,height:o.height}}function YE(e){return di(e)===\"html\"?e:e.assignedSlot||e.parentNode||(UC(e)?e.host:null)||el(e)}function o4(e){return No(e)&&getComputedStyle(e).position!==\"fixed\"?e.offsetParent:null}function p0(e){const t=Ti(e);let n=o4(e);for(;n&&NZ(n)&&getComputedStyle(n).position===\"static\";)n=o4(n);return n&&(di(n)===\"html\"||di(n)===\"body\"&&getComputedStyle(n).position===\"static\"&&!r4(n))?t:n||function(r){let a=YE(r);for(UC(a)&&(a=a.host);No(a)&&![\"html\",\"body\"].includes(di(a));){if(r4(a))return a;a=a.parentNode}return null}(e)||t}function i4(e){if(No(e))return{width:e.offsetWidth,height:e.offsetHeight};const t=as(e);return{width:t.width,height:t.height}}function qE(e){const t=YE(e);return[\"html\",\"body\",\"#document\"].includes(di(t))?e.ownerDocument.body:No(t)&&Wm(t)?t:qE(t)}function GE(e,t){var n;t===void 0&&(t=[]);const r=qE(e),a=r===((n=e.ownerDocument)==null?void 0:n.body),o=Ti(r),i=a?[o].concat(o.visualViewport||[],Wm(r)?r:[]):r,l=t.concat(i);return a?l:l.concat(GE(i))}function l4(e,t,n){return t===\"viewport\"?n4(function(r,a){const o=Ti(r),i=el(r),l=o.visualViewport;let s=i.clientWidth,c=i.clientHeight,d=0,f=0;if(l){s=l.width,c=l.height;const p=WE();(p||!p&&a===\"fixed\")&&(d=l.offsetLeft,f=l.offsetTop)}return{width:s,height:c,x:d,y:f}}(e,n)):Uu(t)?function(r,a){const o=as(r,!1,a===\"fixed\"),i=o.top+r.clientTop,l=o.left+r.clientLeft;return{top:i,left:l,x:l,y:i,right:l+r.clientWidth,bottom:i+r.clientHeight,width:r.clientWidth,height:r.clientHeight}}(t,n):n4(function(r){var a;const o=el(r),i=Um(r),l=(a=r.ownerDocument)==null?void 0:a.body,s=vd(o.scrollWidth,o.clientWidth,l?l.scrollWidth:0,l?l.clientWidth:0),c=vd(o.scrollHeight,o.clientHeight,l?l.scrollHeight:0,l?l.clientHeight:0);let d=-i.scrollLeft+UE(r);const f=-i.scrollTop;return xf(l||o).direction===\"rtl\"&&(d+=vd(o.clientWidth,l?l.clientWidth:0)-s),{width:s,height:c,x:d,y:f}}(el(e)))}function DZ(e){const t=GE(e),n=[\"absolute\",\"fixed\"].includes(xf(e).position)&&No(e)?p0(e):e;return Uu(n)?t.filter(r=>Uu(r)&&function(a,o){const i=o==null||o.getRootNode==null?void 0:o.getRootNode();if(a!=null&&a.contains(o))return!0;if(i&&UC(i)){let l=o;do{if(l&&a===l)return!0;l=l.parentNode||l.host}while(l)}return!1}(r,n)&&di(r)!==\"body\"):[]}const RZ={getClippingRect:function(e){let{element:t,boundary:n,rootBoundary:r,strategy:a}=e;const o=[...n===\"clippingAncestors\"?DZ(t):[].concat(n),r],i=o[0],l=o.reduce((s,c)=>{const d=l4(t,c,a);return s.top=vd(d.top,s.top),s.right=a4(d.right,s.right),s.bottom=a4(d.bottom,s.bottom),s.left=vd(d.left,s.left),s},l4(t,i,a));return{width:l.right-l.left,height:l.bottom-l.top,x:l.left,y:l.top}},convertOffsetParentRelativeRectToViewportRelativeRect:function(e){let{rect:t,offsetParent:n,strategy:r}=e;const a=No(n),o=el(n);if(n===o)return t;let i={scrollLeft:0,scrollTop:0};const l={x:0,y:0};if((a||!a&&r!==\"fixed\")&&((di(n)!==\"body\"||Wm(o))&&(i=Um(n)),No(n))){const s=as(n,!0);l.x=s.x+n.clientLeft,l.y=s.y+n.clientTop}return Ke(Te({},t),{x:t.x-i.scrollLeft+l.x,y:t.y-i.scrollTop+l.y})},isElement:Uu,getDimensions:i4,getOffsetParent:p0,getDocumentElement:el,getElementRects:e=>{let{reference:t,floating:n,strategy:r}=e;return{reference:AZ(t,p0(n),r),floating:Ke(Te({},i4(n)),{x:0,y:0})}},getClientRects:e=>Array.from(e.getClientRects()),isRTL:e=>xf(e).direction===\"rtl\"},LZ=(e,t,n)=>OZ(e,t,Te({platform:RZ},n));Ze({});const FZ=e=>{if(!Bt)return;if(!e)return e;const t=eo(e);return t||(_n(e)?t:e)},BZ=({middleware:e,placement:t,strategy:n})=>{const r=H(),a=H(),o=H(),i=H(),l=H({}),s={x:o,y:i,placement:t,strategy:n,middlewareData:l},c=async()=>{if(!Bt)return;const d=FZ(r),f=eo(a);if(!d||!f)return;const p=await LZ(d,f,{placement:A(t),strategy:A(n),middleware:A(e)});Object.keys(s).forEach(v=>{s[v].value=p[v]})};return et(()=>{Wn(()=>{c()})}),Ke(Te({},s),{update:c,referenceRef:r,contentRef:a})},VZ=({arrowRef:e,padding:t})=>({name:\"arrow\",options:{element:e,padding:t},fn(n){const r=A(e);return r?EZ({element:r,padding:t}).fn(n):{}}}),zZ=\"2.1.9\",s4=Symbol(\"INSTALLED_KEY\"),HZ=(e=[])=>({version:zZ,install:(n,r)=>{n[s4]||(n[s4]=!0,e.forEach(a=>n.use(a)),r&&AE(r,n,!0))}}),jZ=Ze({zIndex:{type:Le([Number,String]),default:100},target:{type:String,default:\"\"},offset:{type:Number,default:0},position:{type:String,values:[\"top\",\"bottom\"],default:\"top\"}}),KZ={scroll:({scrollTop:e,fixed:t})=>typeof e==\"number\"&&typeof t==\"boolean\",change:e=>typeof e==\"boolean\"};var Ae=(e,t)=>{const n=e.__vccOpts||e;for(const[r,a]of t)n[r]=a;return n};const WZ={name:\"ElAffix\"},UZ=G(Ke(Te({},WZ),{props:jZ,emits:KZ,setup(e,{expose:t,emit:n}){const r=e,a=\"ElAffix\",o=De(\"affix\"),i=Qn(),l=Qn(),s=Qn(),{height:c}=OU(),{height:d,width:f,top:p,bottom:v,update:m}=U$(l),y=U$(i),b=H(!1),C=H(0),S=H(0),w=x(()=>({height:b.value?`${d.value}px`:\"\",width:b.value?`${f.value}px`:\"\"})),k=x(()=>{if(!b.value)return{};const T=r.offset?`${r.offset}px`:0;return{height:`${d.value}px`,width:`${f.value}px`,top:r.position===\"top\"?T:\"\",bottom:r.position===\"bottom\"?T:\"\",transform:S.value?`translateY(${S.value}px)`:\"\",zIndex:r.zIndex}}),$=()=>{if(!!s.value)if(C.value=s.value instanceof Window?document.documentElement.scrollTop:s.value.scrollTop||0,r.position===\"top\")if(r.target){const T=y.bottom.value-r.offset-d.value;b.value=r.offset>p.value&&y.bottom.value>0,S.value=T<0?T:0}else b.value=r.offset>p.value;else if(r.target){const T=c.value-y.top.value-r.offset-d.value;b.value=c.value-r.offset<v.value&&c.value>y.top.value,S.value=T<0?-T:0}else b.value=c.value-r.offset<v.value},O=()=>{n(\"scroll\",{scrollTop:C.value,fixed:b.value})};return ce(b,T=>n(\"change\",T)),et(()=>{var T;r.target?(i.value=(T=document.querySelector(r.target))!=null?T:void 0,i.value||qn(a,`Target is not existed: ${r.target}`)):i.value=document.documentElement,s.value=DC(l.value,!0),m()}),Hn(s,\"scroll\",O),Wn($),t({update:$}),(T,_)=>(R(),X(\"div\",{ref_key:\"root\",ref:l,class:U(A(o).b()),style:Xe(A(w))},[Z(\"div\",{class:U({[A(o).m(\"fixed\")]:b.value}),style:Xe(A(k))},[Oe(T.$slots,\"default\")],6)],6))}}));var YZ=Ae(UZ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/affix/src/affix.vue\"]]);const qZ=xt(YZ),GZ=Ze({size:{type:Le([Number,String])},color:{type:String}}),XZ={name:\"ElIcon\",inheritAttrs:!1},ZZ=G(Ke(Te({},XZ),{props:GZ,setup(e){const t=e,n=De(\"icon\"),r=x(()=>!t.size&&!t.color?{}:{fontSize:sa(t.size)?void 0:oo(t.size),\"--color\":t.color});return(a,o)=>(R(),X(\"i\",hn({class:A(n).b(),style:A(r)},a.$attrs),[Oe(a.$slots,\"default\")],16))}}));var JZ=Ae(ZZ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/icon/src/icon.vue\"]]);const ft=xt(JZ),QZ=[\"light\",\"dark\"],eJ=Ze({title:{type:String,default:\"\"},description:{type:String,default:\"\"},type:{type:String,values:f0(yi),default:\"info\"},closable:{type:Boolean,default:!0},closeText:{type:String,default:\"\"},showIcon:Boolean,center:Boolean,effect:{type:String,values:QZ,default:\"light\"}}),tJ={close:e=>e instanceof MouseEvent},nJ={name:\"ElAlert\"},rJ=G(Ke(Te({},nJ),{props:eJ,emits:tJ,setup(e,{emit:t}){const n=e,{Close:r}=Vm,a=wf(),o=De(\"alert\"),i=H(!0),l=x(()=>yi[n.type]||yi.info),s=x(()=>n.description||{[o.is(\"big\")]:a.default}),c=x(()=>n.description||{[o.is(\"bold\")]:a.default}),d=f=>{i.value=!1,t(\"close\",f)};return(f,p)=>(R(),fe(Vn,{name:A(o).b(\"fade\")},{default:re(()=>[at(Z(\"div\",{class:U([A(o).b(),A(o).m(f.type),A(o).is(\"center\",f.center),A(o).is(f.effect)]),role:\"alert\"},[f.showIcon&&A(l)?(R(),fe(A(ft),{key:0,class:U([A(o).e(\"icon\"),A(s)])},{default:re(()=>[(R(),fe(Kt(A(l))))]),_:1},8,[\"class\"])):se(\"v-if\",!0),Z(\"div\",{class:U(A(o).e(\"content\"))},[f.title||f.$slots.title?(R(),X(\"span\",{key:0,class:U([A(o).e(\"title\"),A(c)])},[Oe(f.$slots,\"title\",{},()=>[yt(Me(f.title),1)])],2)):se(\"v-if\",!0),f.$slots.default||f.description?(R(),X(\"p\",{key:1,class:U(A(o).e(\"description\"))},[Oe(f.$slots,\"default\",{},()=>[yt(Me(f.description),1)])],2)):se(\"v-if\",!0),f.closable?(R(),X(Fe,{key:2},[f.closeText?(R(),X(\"div\",{key:0,class:U([A(o).e(\"close-btn\"),A(o).is(\"customed\")]),onClick:d},Me(f.closeText),3)):(R(),fe(A(ft),{key:1,class:U(A(o).e(\"close-btn\")),onClick:d},{default:re(()=>[g(A(r))]),_:1},8,[\"class\"]))],2112)):se(\"v-if\",!0)],2)],2),[[_t,i.value]])]),_:3},8,[\"name\"]))}}));var aJ=Ae(rJ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/alert/src/alert.vue\"]]);const oJ=xt(aJ);let Ha;const iJ=`\n  height:0 !important;\n  visibility:hidden !important;\n  overflow:hidden !important;\n  position:absolute !important;\n  z-index:-1000 !important;\n  top:0 !important;\n  right:0 !important;\n`,lJ=[\"letter-spacing\",\"line-height\",\"padding-top\",\"padding-bottom\",\"font-family\",\"font-weight\",\"font-size\",\"text-rendering\",\"text-transform\",\"width\",\"text-indent\",\"padding-left\",\"padding-right\",\"border-width\",\"box-sizing\"];function sJ(e){const t=window.getComputedStyle(e),n=t.getPropertyValue(\"box-sizing\"),r=Number.parseFloat(t.getPropertyValue(\"padding-bottom\"))+Number.parseFloat(t.getPropertyValue(\"padding-top\")),a=Number.parseFloat(t.getPropertyValue(\"border-bottom-width\"))+Number.parseFloat(t.getPropertyValue(\"border-top-width\"));return{contextStyle:lJ.map(i=>`${i}:${t.getPropertyValue(i)}`).join(\";\"),paddingSize:r,borderSize:a,boxSizing:n}}function u4(e,t=1,n){var r;Ha||(Ha=document.createElement(\"textarea\"),document.body.appendChild(Ha));const{paddingSize:a,borderSize:o,boxSizing:i,contextStyle:l}=sJ(e);Ha.setAttribute(\"style\",`${l};${iJ}`),Ha.value=e.value||e.placeholder||\"\";let s=Ha.scrollHeight;const c={};i===\"border-box\"?s=s+o:i===\"content-box\"&&(s=s-a),Ha.value=\"\";const d=Ha.scrollHeight-a;if(Yt(t)){let f=d*t;i===\"border-box\"&&(f=f+a+o),s=Math.max(f,s),c.minHeight=`${f}px`}if(Yt(n)){let f=d*n;i===\"border-box\"&&(f=f+a+o),s=Math.min(f,s)}return c.height=`${s}px`,(r=Ha.parentNode)==null||r.removeChild(Ha),Ha=void 0,c}const uJ=Ze({size:Km,disabled:Boolean,modelValue:{type:Le([String,Number,Object]),default:\"\"},type:{type:String,default:\"text\"},resize:{type:String,values:[\"none\",\"both\",\"horizontal\",\"vertical\"]},autosize:{type:Le([Boolean,Object]),default:!1},autocomplete:{type:String,default:\"off\"},placeholder:{type:String},form:{type:String,default:\"\"},readonly:{type:Boolean,default:!1},clearable:{type:Boolean,default:!1},showPassword:{type:Boolean,default:!1},showWordLimit:{type:Boolean,default:!1},suffixIcon:{type:wr,default:\"\"},prefixIcon:{type:wr,default:\"\"},label:{type:String},tabindex:{type:[Number,String]},validateEvent:{type:Boolean,default:!0},inputStyle:{type:Le([Object,Array,String]),default:()=>xn({})}}),cJ={[Pt]:e=>wt(e),input:e=>wt(e),change:e=>wt(e),focus:e=>e instanceof FocusEvent,blur:e=>e instanceof FocusEvent,clear:()=>!0,mouseleave:e=>e instanceof MouseEvent,mouseenter:e=>e instanceof MouseEvent,keydown:e=>e instanceof Event,compositionstart:e=>e instanceof CompositionEvent,compositionupdate:e=>e instanceof CompositionEvent,compositionend:e=>e instanceof CompositionEvent},dJ=[\"type\",\"disabled\",\"readonly\",\"autocomplete\",\"tabindex\",\"aria-label\",\"placeholder\"],fJ=[\"tabindex\",\"disabled\",\"readonly\",\"autocomplete\",\"aria-label\",\"placeholder\"],hJ={name:\"ElInput\",inheritAttrs:!1},pJ=G(Ke(Te({},hJ),{props:uJ,emits:cJ,setup(e,{expose:t,emit:n}){const r=e,a={suffix:\"append\",prefix:\"prepend\"},o=$t(),i=W6(),l=wf(),s=VC(),{form:c,formItem:d}=$c(),f=Gn(),p=Ms(),v=De(\"input\"),m=De(\"textarea\"),y=Qn(),b=Qn(),C=H(!1),S=H(!1),w=H(!1),k=H(!1),$=Qn(r.inputStyle),O=x(()=>y.value||b.value),T=x(()=>{var ee;return(ee=c==null?void 0:c.statusIcon)!=null?ee:!1}),_=x(()=>(d==null?void 0:d.validateState)||\"\"),I=x(()=>hE[_.value]),L=x(()=>k.value?TX:Kq),j=x(()=>[i.style,r.inputStyle]),F=x(()=>[r.inputStyle,$.value,{resize:r.resize}]),N=x(()=>ul(r.modelValue)?\"\":String(r.modelValue)),D=x(()=>r.clearable&&!p.value&&!r.readonly&&!!N.value&&(C.value||S.value)),z=x(()=>r.showPassword&&!p.value&&!r.readonly&&(!!N.value||C.value)),B=x(()=>r.showWordLimit&&!!s.value.maxlength&&(r.type===\"text\"||r.type===\"textarea\")&&!p.value&&!r.readonly&&!r.showPassword),M=x(()=>Array.from(N.value).length),E=x(()=>!!B.value&&M.value>Number(s.value.maxlength)),K=x(()=>!!l.suffix||!!r.suffixIcon||D.value||r.showPassword||B.value||!!_.value&&T.value),W=()=>{const{type:ee,autosize:me}=r;if(!(!Bt||ee!==\"textarea\"))if(me){const He=zt(me)?me.minRows:void 0,lt=zt(me)?me.maxRows:void 0;$.value=Te({},u4(b.value,He,lt))}else $.value={minHeight:u4(b.value).minHeight}},Y=()=>{const ee=O.value;!ee||ee.value===N.value||(ee.value=N.value)},q=ee=>{const{el:me}=o.vnode;if(!me)return;const lt=Array.from(me.querySelectorAll(`.${v.e(ee)}`)).find(he=>he.parentNode===me);if(!lt)return;const Ye=a[ee];l[Ye]?lt.style.transform=`translateX(${ee===\"suffix\"?\"-\":\"\"}${me.querySelector(`.${v.be(\"group\",Ye)}`).offsetWidth}px)`:lt.removeAttribute(\"style\")},J=()=>{q(\"prefix\"),q(\"suffix\")},ne=async ee=>{const{value:me}=ee.target;w.value||me!==N.value&&(n(Pt,me),n(\"input\",me),await Ne(),Y())},oe=ee=>{n(\"change\",ee.target.value)},Q=ee=>{n(\"compositionstart\",ee),w.value=!0},ae=ee=>{var me;n(\"compositionupdate\",ee);const He=(me=ee.target)==null?void 0:me.value,lt=He[He.length-1]||\"\";w.value=!zm(lt)},de=ee=>{n(\"compositionend\",ee),w.value&&(w.value=!1,ne(ee))},be=()=>{k.value=!k.value,Ee()},Ee=async()=>{var ee;await Ne(),(ee=O.value)==null||ee.focus()},Pe=()=>{var ee;return(ee=O.value)==null?void 0:ee.blur()},Be=ee=>{C.value=!0,n(\"focus\",ee)},te=ee=>{var me;C.value=!1,n(\"blur\",ee),r.validateEvent&&((me=d==null?void 0:d.validate)==null||me.call(d,\"blur\").catch(He=>void 0))},ie=ee=>{S.value=!1,n(\"mouseleave\",ee)},ge=ee=>{S.value=!0,n(\"mouseenter\",ee)},ke=ee=>{n(\"keydown\",ee)},xe=()=>{var ee;(ee=O.value)==null||ee.select()},Ie=()=>{n(Pt,\"\"),n(\"change\",\"\"),n(\"clear\"),n(\"input\",\"\")};ce(()=>r.modelValue,()=>{var ee;Ne(()=>W()),r.validateEvent&&((ee=d==null?void 0:d.validate)==null||ee.call(d,\"change\").catch(me=>void 0))}),ce(N,()=>Y()),ce(()=>r.type,async()=>{await Ne(),Y(),W(),J()});const ye=H(),pe=H(),ue=H({}),Ce=(ee,me)=>{if(ee.value){const He=ee.value.offsetWidth;return He>0?He+16:me}return me},je=()=>{ue.value=Te({paddingRight:`${Ce(ye,0)}px`,paddingLeft:`${Ce(pe,11)}px`},r.inputStyle)};return ce(D,()=>{Ne(()=>{je()})}),et(async()=>{je(),Y(),J(),await Ne(),W()}),ur(async()=>{await Ne(),J()}),t({input:y,textarea:b,ref:O,textareaStyle:F,autosize:yn(r,\"autosize\"),focus:Ee,blur:Pe,select:xe,clear:Ie,resizeTextarea:W}),(ee,me)=>at((R(),X(\"div\",{class:U([ee.type===\"textarea\"?A(m).b():A(v).b(),A(v).m(A(f)),A(v).is(\"disabled\",A(p)),A(v).is(\"exceed\",A(E)),{[A(v).b(\"group\")]:ee.$slots.prepend||ee.$slots.append,[A(v).bm(\"group\",\"append\")]:ee.$slots.append,[A(v).bm(\"group\",\"prepend\")]:ee.$slots.prepend,[A(v).m(\"prefix\")]:ee.$slots.prefix||ee.prefixIcon,[A(v).m(\"suffix\")]:ee.$slots.suffix||ee.suffixIcon||ee.clearable||ee.showPassword,[A(v).m(\"suffix--password-clear\")]:A(D)&&A(z)},ee.$attrs.class]),style:Xe(A(j)),onMouseenter:ge,onMouseleave:ie},[se(\" input \"),ee.type!==\"textarea\"?(R(),X(Fe,{key:0},[se(\" prepend slot \"),ee.$slots.prepend?(R(),X(\"div\",{key:0,class:U(A(v).be(\"group\",\"prepend\"))},[Oe(ee.$slots,\"prepend\")],2)):se(\"v-if\",!0),Z(\"input\",hn({ref_key:\"input\",ref:y,class:A(v).e(\"inner\")},A(s),{type:ee.showPassword?k.value?\"text\":\"password\":ee.type,disabled:A(p),readonly:ee.readonly,autocomplete:ee.autocomplete,tabindex:ee.tabindex,\"aria-label\":ee.label,placeholder:ee.placeholder,style:ue.value,onCompositionstart:Q,onCompositionupdate:ae,onCompositionend:de,onInput:ne,onFocus:Be,onBlur:te,onChange:oe,onKeydown:ke}),null,16,dJ),se(\" prefix slot \"),ee.$slots.prefix||ee.prefixIcon?(R(),X(\"span\",{key:1,class:U(A(v).e(\"prefix\"))},[Z(\"span\",{ref_key:\"innerPrefixRef\",ref:pe,class:U(A(v).e(\"prefix-inner\"))},[Oe(ee.$slots,\"prefix\"),ee.prefixIcon?(R(),fe(A(ft),{key:0,class:U(A(v).e(\"icon\"))},{default:re(()=>[(R(),fe(Kt(ee.prefixIcon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],2)],2)):se(\"v-if\",!0),se(\" suffix slot \"),A(K)?(R(),X(\"span\",{key:2,class:U(A(v).e(\"suffix\"))},[Z(\"span\",{ref_key:\"innerSuffixRef\",ref:ye,class:U(A(v).e(\"suffix-inner\"))},[!A(D)||!A(z)||!A(B)?(R(),X(Fe,{key:0},[Oe(ee.$slots,\"suffix\"),ee.suffixIcon?(R(),fe(A(ft),{key:0,class:U(A(v).e(\"icon\"))},{default:re(()=>[(R(),fe(Kt(ee.suffixIcon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],64)):se(\"v-if\",!0),A(D)?(R(),fe(A(ft),{key:1,class:U([A(v).e(\"icon\"),A(v).e(\"clear\")]),onMousedown:me[0]||(me[0]=dt(()=>{},[\"prevent\"])),onClick:Ie},{default:re(()=>[g(A(gi))]),_:1},8,[\"class\"])):se(\"v-if\",!0),A(z)?(R(),fe(A(ft),{key:2,class:U([A(v).e(\"icon\"),A(v).e(\"clear\")]),onClick:be},{default:re(()=>[(R(),fe(Kt(A(L))))]),_:1},8,[\"class\"])):se(\"v-if\",!0),A(B)?(R(),X(\"span\",{key:3,class:U(A(v).e(\"count\"))},[Z(\"span\",{class:U(A(v).e(\"count-inner\"))},Me(A(M))+\" / \"+Me(A(s).maxlength),3)],2)):se(\"v-if\",!0)],2),A(_)&&A(I)&&A(T)?(R(),fe(A(ft),{key:0,class:U([A(v).e(\"icon\"),A(v).e(\"validateIcon\"),A(v).is(\"loading\",A(_)===\"validating\")])},{default:re(()=>[(R(),fe(Kt(A(I))))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],2)):se(\"v-if\",!0),se(\" append slot \"),ee.$slots.append?(R(),X(\"div\",{key:3,class:U(A(v).be(\"group\",\"append\"))},[Oe(ee.$slots,\"append\")],2)):se(\"v-if\",!0)],64)):(R(),X(Fe,{key:1},[se(\" textarea \"),Z(\"textarea\",hn({ref_key:\"textarea\",ref:b,class:A(m).e(\"inner\")},A(s),{tabindex:ee.tabindex,disabled:A(p),readonly:ee.readonly,autocomplete:ee.autocomplete,style:A(F),\"aria-label\":ee.label,placeholder:ee.placeholder,onCompositionstart:Q,onCompositionupdate:ae,onCompositionend:de,onInput:ne,onFocus:Be,onBlur:te,onChange:oe,onKeydown:ke}),null,16,fJ),A(B)?(R(),X(\"span\",{key:0,class:U(A(v).e(\"count\"))},Me(A(M))+\" / \"+Me(A(s).maxlength),3)):se(\"v-if\",!0)],64))],38)),[[_t,ee.type!==\"hidden\"]])}}));var vJ=Ae(pJ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/input/src/input.vue\"]]);const Ra=xt(vJ),XE={vertical:{offset:\"offsetHeight\",scroll:\"scrollTop\",scrollSize:\"scrollHeight\",size:\"height\",key:\"vertical\",axis:\"Y\",client:\"clientY\",direction:\"top\"},horizontal:{offset:\"offsetWidth\",scroll:\"scrollLeft\",scrollSize:\"scrollWidth\",size:\"width\",key:\"horizontal\",axis:\"X\",client:\"clientX\",direction:\"left\"}},mJ=({move:e,size:t,bar:n})=>({[n.size]:t,transform:`translate${n.axis}(${e}%)`}),gJ=Ze({vertical:Boolean,size:String,move:Number,ratio:{type:Number,required:!0},always:Boolean}),c4=\"Thumb\",yJ=G({name:c4,props:gJ,setup(e){const t=ve(_E),n=De(\"scrollbar\");t||qn(c4,\"can not inject scrollbar context\");const r=H(),a=H(),o=H({}),i=H(!1);let l=!1,s=!1,c=Bt?document.onselectstart:null;const d=x(()=>XE[e.vertical?\"vertical\":\"horizontal\"]),f=x(()=>mJ({size:e.size,move:e.move,bar:d.value})),p=x(()=>r.value[d.value.offset]**2/t.wrapElement[d.value.scrollSize]/e.ratio/a.value[d.value.offset]),v=$=>{var O;if($.stopPropagation(),$.ctrlKey||[1,2].includes($.button))return;(O=window.getSelection())==null||O.removeAllRanges(),y($);const T=$.currentTarget;!T||(o.value[d.value.axis]=T[d.value.offset]-($[d.value.client]-T.getBoundingClientRect()[d.value.direction]))},m=$=>{if(!a.value||!r.value||!t.wrapElement)return;const O=Math.abs($.target.getBoundingClientRect()[d.value.direction]-$[d.value.client]),T=a.value[d.value.offset]/2,_=(O-T)*100*p.value/r.value[d.value.offset];t.wrapElement[d.value.scroll]=_*t.wrapElement[d.value.scrollSize]/100},y=$=>{$.stopImmediatePropagation(),l=!0,document.addEventListener(\"mousemove\",b),document.addEventListener(\"mouseup\",C),c=document.onselectstart,document.onselectstart=()=>!1},b=$=>{if(!r.value||!a.value||l===!1)return;const O=o.value[d.value.axis];if(!O)return;const T=(r.value.getBoundingClientRect()[d.value.direction]-$[d.value.client])*-1,_=a.value[d.value.offset]-O,I=(T-_)*100*p.value/r.value[d.value.offset];t.wrapElement[d.value.scroll]=I*t.wrapElement[d.value.scrollSize]/100},C=()=>{l=!1,o.value[d.value.axis]=0,document.removeEventListener(\"mousemove\",b),document.removeEventListener(\"mouseup\",C),k(),s&&(i.value=!1)},S=()=>{s=!1,i.value=!!e.size},w=()=>{s=!0,i.value=l};Lt(()=>{k(),document.removeEventListener(\"mouseup\",C)});const k=()=>{document.onselectstart!==c&&(document.onselectstart=c)};return Hn(yn(t,\"scrollbarElement\"),\"mousemove\",S),Hn(yn(t,\"scrollbarElement\"),\"mouseleave\",w),{ns:n,instance:r,thumb:a,bar:d,thumbStyle:f,visible:i,clickTrackHandler:m,clickThumbHandler:v}}});function bJ(e,t,n,r,a,o){return R(),fe(Vn,{name:e.ns.b(\"fade\")},{default:re(()=>[at(Z(\"div\",{ref:\"instance\",class:U([e.ns.e(\"bar\"),e.ns.is(e.bar.key)]),onMousedown:t[1]||(t[1]=(...i)=>e.clickTrackHandler&&e.clickTrackHandler(...i))},[Z(\"div\",{ref:\"thumb\",class:U(e.ns.e(\"thumb\")),style:Xe(e.thumbStyle),onMousedown:t[0]||(t[0]=(...i)=>e.clickThumbHandler&&e.clickThumbHandler(...i))},null,38)],34),[[_t,e.always||e.visible]])]),_:1},8,[\"name\"])}var CJ=Ae(yJ,[[\"render\",bJ],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/scrollbar/src/thumb.vue\"]]);const wJ=Ze({always:{type:Boolean,default:!0},width:{type:String,default:\"\"},height:{type:String,default:\"\"},ratioX:{type:Number,default:1},ratioY:{type:Number,default:1}}),SJ=G({components:{Thumb:CJ},props:wJ,setup(e){const t=H(0),n=H(0),r=4;return{handleScroll:o=>{if(o){const i=o.offsetHeight-r,l=o.offsetWidth-r;n.value=o.scrollTop*100/i*e.ratioY,t.value=o.scrollLeft*100/l*e.ratioX}},moveX:t,moveY:n}}});function kJ(e,t,n,r,a,o){const i=we(\"thumb\");return R(),X(Fe,null,[g(i,{move:e.moveX,ratio:e.ratioX,size:e.width,always:e.always},null,8,[\"move\",\"ratio\",\"size\",\"always\"]),g(i,{move:e.moveY,ratio:e.ratioY,size:e.height,vertical:\"\",always:e.always},null,8,[\"move\",\"ratio\",\"size\",\"always\"])],64)}var $J=Ae(SJ,[[\"render\",kJ],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/scrollbar/src/bar.vue\"]]);const OJ=Ze({height:{type:[String,Number],default:\"\"},maxHeight:{type:[String,Number],default:\"\"},native:{type:Boolean,default:!1},wrapStyle:{type:Le([String,Object,Array]),default:\"\"},wrapClass:{type:[String,Array],default:\"\"},viewClass:{type:[String,Array],default:\"\"},viewStyle:{type:[String,Array,Object],default:\"\"},noresize:Boolean,tag:{type:String,default:\"div\"},always:{type:Boolean,default:!1},minSize:{type:Number,default:20}}),PJ={scroll:({scrollTop:e,scrollLeft:t})=>Yt(e)&&Yt(t)},TJ=G({name:\"ElScrollbar\",components:{Bar:$J},props:OJ,emits:PJ,setup(e,{emit:t}){const n=De(\"scrollbar\");let r,a;const o=H(),i=H(),l=H(),s=H(\"0\"),c=H(\"0\"),d=H(),f=H(0),p=H(0),v=H(1),m=H(1),y=4,b=x(()=>{const O={};return e.height&&(O.height=oo(e.height)),e.maxHeight&&(O.maxHeight=oo(e.maxHeight)),[e.wrapStyle,O]}),C=()=>{var O;i.value&&((O=d.value)==null||O.handleScroll(i.value),t(\"scroll\",{scrollTop:i.value.scrollTop,scrollLeft:i.value.scrollLeft}))};function S(O,T){zt(O)?i.value.scrollTo(O):Yt(O)&&Yt(T)&&i.value.scrollTo(O,T)}const w=O=>{!Yt(O)||(i.value.scrollTop=O)},k=O=>{!Yt(O)||(i.value.scrollLeft=O)},$=()=>{if(!i.value)return;const O=i.value.offsetHeight-y,T=i.value.offsetWidth-y,_=O**2/i.value.scrollHeight,I=T**2/i.value.scrollWidth,L=Math.max(_,e.minSize),j=Math.max(I,e.minSize);v.value=_/(O-_)/(L/(O-L)),m.value=I/(T-I)/(j/(T-j)),c.value=L+y<O?`${L}px`:\"\",s.value=j+y<T?`${j}px`:\"\"};return ce(()=>e.noresize,O=>{O?(r==null||r(),a==null||a()):({stop:r}=Cc(l,$),a=Hn(\"resize\",$))},{immediate:!0}),ce(()=>[e.maxHeight,e.height],()=>{e.native||Ne(()=>{var O;$(),i.value&&((O=d.value)==null||O.handleScroll(i.value))})}),ot(_E,bt({scrollbarElement:o,wrapElement:i})),et(()=>{e.native||Ne(()=>$())}),ur(()=>$()),{ns:n,scrollbar$:o,wrap$:i,resize$:l,barRef:d,moveX:f,moveY:p,ratioX:m,ratioY:v,sizeWidth:s,sizeHeight:c,style:b,update:$,handleScroll:C,scrollTo:S,setScrollTop:w,setScrollLeft:k}}});function xJ(e,t,n,r,a,o){const i=we(\"bar\");return R(),X(\"div\",{ref:\"scrollbar$\",class:U(e.ns.b())},[Z(\"div\",{ref:\"wrap$\",class:U([e.wrapClass,e.ns.e(\"wrap\"),{[e.ns.em(\"wrap\",\"hidden-default\")]:!e.native}]),style:Xe(e.style),onScroll:t[0]||(t[0]=(...l)=>e.handleScroll&&e.handleScroll(...l))},[(R(),fe(Kt(e.tag),{ref:\"resize$\",class:U([e.ns.e(\"view\"),e.viewClass]),style:Xe(e.viewStyle)},{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},8,[\"class\",\"style\"]))],38),e.native?se(\"v-if\",!0):(R(),fe(i,{key:0,ref:\"barRef\",height:e.sizeHeight,width:e.sizeWidth,always:e.always,\"ratio-x\":e.ratioX,\"ratio-y\":e.ratioY},null,8,[\"height\",\"width\",\"always\",\"ratio-x\",\"ratio-y\"]))],2)}var _J=Ae(TJ,[[\"render\",xJ],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/scrollbar/src/scrollbar.vue\"]]);const xi=xt(_J),EJ={name:\"ElPopperRoot\",inheritAttrs:!1},MJ=G(Ke(Te({},EJ),{setup(e,{expose:t}){const n=H(),r=H(),a=H(),o=H(),i={triggerRef:n,popperInstanceRef:r,contentRef:a,referenceRef:o};return t(i),ot(zC,i),(l,s)=>Oe(l.$slots,\"default\")}}));var IJ=Ae(MJ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popper/src/popper.vue\"]]);const ZE=Ze({arrowOffset:{type:Number,default:5}}),NJ={name:\"ElPopperArrow\",inheritAttrs:!1},AJ=G(Ke(Te({},NJ),{props:ZE,setup(e,{expose:t}){const n=e,r=De(\"popper\"),{arrowOffset:a,arrowRef:o}=ve(ME,void 0);return ce(()=>n.arrowOffset,i=>{a.value=i}),Lt(()=>{o.value=void 0}),t({arrowRef:o}),(i,l)=>(R(),X(\"span\",{ref_key:\"arrowRef\",ref:o,class:U(A(r).e(\"arrow\")),\"data-popper-arrow\":\"\"},null,2))}}));var DJ=Ae(AJ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popper/src/arrow.vue\"]]);const RJ=\"ElOnlyChild\",LJ=G({name:RJ,setup(e,{slots:t,attrs:n}){var r;const a=ve(zE),o=SZ((r=a==null?void 0:a.setForwardRef)!=null?r:Qt);return()=>{var i;const l=(i=t.default)==null?void 0:i.call(t,n);if(!l||l.length>1)return null;const s=JE(l);return s?at(hr(s,n),[[o]]):null}}});function JE(e){if(!e)return null;const t=e;for(const n of t){if(zt(n))switch(n.type){case Ir:continue;case Fo:return iy(n);case\"svg\":return iy(n);case Fe:return JE(n.children);default:return n}return iy(n)}return null}function iy(e){return g(\"span\",{class:\"el-only-child__content\"},[e])}const QE=Ze({virtualRef:{type:Le(Object)},virtualTriggering:Boolean,onMouseenter:Function,onMouseleave:Function,onClick:Function,onKeydown:Function,onFocus:Function,onBlur:Function,onContextmenu:Function,id:String,open:Boolean}),FJ={name:\"ElPopperTrigger\",inheritAttrs:!1},BJ=G(Ke(Te({},FJ),{props:QE,setup(e,{expose:t}){const n=e,{triggerRef:r}=ve(zC,void 0);return wZ(r),et(()=>{ce(()=>n.virtualRef,a=>{a&&(r.value=eo(a))},{immediate:!0}),ce(()=>r.value,(a,o)=>{ys(a)&&[\"onMouseenter\",\"onMouseleave\",\"onClick\",\"onKeydown\",\"onFocus\",\"onBlur\",\"onContextmenu\"].forEach(i=>{var l;const s=n[i];s&&(a.addEventListener(i.slice(2).toLowerCase(),s),(l=o==null?void 0:o.removeEventListener)==null||l.call(o,i.slice(2).toLowerCase(),s))})},{immediate:!0})}),t({triggerRef:r}),(a,o)=>a.virtualTriggering?se(\"v-if\",!0):(R(),fe(A(LJ),hn({key:0},a.$attrs,{\"aria-describedby\":a.open?a.id:void 0}),{default:re(()=>[Oe(a.$slots,\"default\")]),_:3},16,[\"aria-describedby\"]))}}));var VJ=Ae(BJ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popper/src/trigger.vue\"]]),Vr=\"top\",Na=\"bottom\",Aa=\"right\",zr=\"left\",YC=\"auto\",_f=[Vr,Na,Aa,zr],Yu=\"start\",Ud=\"end\",zJ=\"clippingParents\",eM=\"viewport\",Bc=\"popper\",HJ=\"reference\",d4=_f.reduce(function(e,t){return e.concat([t+\"-\"+Yu,t+\"-\"+Ud])},[]),qC=[].concat(_f,[YC]).reduce(function(e,t){return e.concat([t,t+\"-\"+Yu,t+\"-\"+Ud])},[]),jJ=\"beforeRead\",KJ=\"read\",WJ=\"afterRead\",UJ=\"beforeMain\",YJ=\"main\",qJ=\"afterMain\",GJ=\"beforeWrite\",XJ=\"write\",ZJ=\"afterWrite\",JJ=[jJ,KJ,WJ,UJ,YJ,qJ,GJ,XJ,ZJ];function Ao(e){return e?(e.nodeName||\"\").toLowerCase():null}function po(e){if(e==null)return window;if(e.toString()!==\"[object Window]\"){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function qu(e){var t=po(e).Element;return e instanceof t||e instanceof Element}function Ta(e){var t=po(e).HTMLElement;return e instanceof t||e instanceof HTMLElement}function GC(e){if(typeof ShadowRoot==\"undefined\")return!1;var t=po(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot}function QJ(e){var t=e.state;Object.keys(t.elements).forEach(function(n){var r=t.styles[n]||{},a=t.attributes[n]||{},o=t.elements[n];!Ta(o)||!Ao(o)||(Object.assign(o.style,r),Object.keys(a).forEach(function(i){var l=a[i];l===!1?o.removeAttribute(i):o.setAttribute(i,l===!0?\"\":l)}))})}function eQ(e){var t=e.state,n={popper:{position:t.options.strategy,left:\"0\",top:\"0\",margin:\"0\"},arrow:{position:\"absolute\"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach(function(r){var a=t.elements[r],o=t.attributes[r]||{},i=Object.keys(t.styles.hasOwnProperty(r)?t.styles[r]:n[r]),l=i.reduce(function(s,c){return s[c]=\"\",s},{});!Ta(a)||!Ao(a)||(Object.assign(a.style,l),Object.keys(o).forEach(function(s){a.removeAttribute(s)}))})}}var tQ={name:\"applyStyles\",enabled:!0,phase:\"write\",fn:QJ,effect:eQ,requires:[\"computeStyles\"]};function Mo(e){return e.split(\"-\")[0]}var os=Math.max,bv=Math.min,Gu=Math.round;function Xu(e,t){t===void 0&&(t=!1);var n=e.getBoundingClientRect(),r=1,a=1;if(Ta(e)&&t){var o=e.offsetHeight,i=e.offsetWidth;i>0&&(r=Gu(n.width)/i||1),o>0&&(a=Gu(n.height)/o||1)}return{width:n.width/r,height:n.height/a,top:n.top/a,right:n.right/r,bottom:n.bottom/a,left:n.left/r,x:n.left/r,y:n.top/a}}function XC(e){var t=Xu(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function tM(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&GC(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function bi(e){return po(e).getComputedStyle(e)}function nQ(e){return[\"table\",\"td\",\"th\"].indexOf(Ao(e))>=0}function yl(e){return((qu(e)?e.ownerDocument:e.document)||window.document).documentElement}function Ym(e){return Ao(e)===\"html\"?e:e.assignedSlot||e.parentNode||(GC(e)?e.host:null)||yl(e)}function f4(e){return!Ta(e)||bi(e).position===\"fixed\"?null:e.offsetParent}function rQ(e){var t=navigator.userAgent.toLowerCase().indexOf(\"firefox\")!==-1,n=navigator.userAgent.indexOf(\"Trident\")!==-1;if(n&&Ta(e)){var r=bi(e);if(r.position===\"fixed\")return null}var a=Ym(e);for(GC(a)&&(a=a.host);Ta(a)&&[\"html\",\"body\"].indexOf(Ao(a))<0;){var o=bi(a);if(o.transform!==\"none\"||o.perspective!==\"none\"||o.contain===\"paint\"||[\"transform\",\"perspective\"].indexOf(o.willChange)!==-1||t&&o.willChange===\"filter\"||t&&o.filter&&o.filter!==\"none\")return a;a=a.parentNode}return null}function Ef(e){for(var t=po(e),n=f4(e);n&&nQ(n)&&bi(n).position===\"static\";)n=f4(n);return n&&(Ao(n)===\"html\"||Ao(n)===\"body\"&&bi(n).position===\"static\")?t:n||rQ(e)||t}function ZC(e){return[\"top\",\"bottom\"].indexOf(e)>=0?\"x\":\"y\"}function md(e,t,n){return os(e,bv(t,n))}function aQ(e,t,n){var r=md(e,t,n);return r>n?n:r}function nM(){return{top:0,right:0,bottom:0,left:0}}function rM(e){return Object.assign({},nM(),e)}function aM(e,t){return t.reduce(function(n,r){return n[r]=e,n},{})}var oQ=function(t,n){return t=typeof t==\"function\"?t(Object.assign({},n.rects,{placement:n.placement})):t,rM(typeof t!=\"number\"?t:aM(t,_f))};function iQ(e){var t,n=e.state,r=e.name,a=e.options,o=n.elements.arrow,i=n.modifiersData.popperOffsets,l=Mo(n.placement),s=ZC(l),c=[zr,Aa].indexOf(l)>=0,d=c?\"height\":\"width\";if(!(!o||!i)){var f=oQ(a.padding,n),p=XC(o),v=s===\"y\"?Vr:zr,m=s===\"y\"?Na:Aa,y=n.rects.reference[d]+n.rects.reference[s]-i[s]-n.rects.popper[d],b=i[s]-n.rects.reference[s],C=Ef(o),S=C?s===\"y\"?C.clientHeight||0:C.clientWidth||0:0,w=y/2-b/2,k=f[v],$=S-p[d]-f[m],O=S/2-p[d]/2+w,T=md(k,O,$),_=s;n.modifiersData[r]=(t={},t[_]=T,t.centerOffset=T-O,t)}}function lQ(e){var t=e.state,n=e.options,r=n.element,a=r===void 0?\"[data-popper-arrow]\":r;a!=null&&(typeof a==\"string\"&&(a=t.elements.popper.querySelector(a),!a)||!tM(t.elements.popper,a)||(t.elements.arrow=a))}var sQ={name:\"arrow\",enabled:!0,phase:\"main\",fn:iQ,effect:lQ,requires:[\"popperOffsets\"],requiresIfExists:[\"preventOverflow\"]};function Zu(e){return e.split(\"-\")[1]}var uQ={top:\"auto\",right:\"auto\",bottom:\"auto\",left:\"auto\"};function cQ(e){var t=e.x,n=e.y,r=window,a=r.devicePixelRatio||1;return{x:Gu(t*a)/a||0,y:Gu(n*a)/a||0}}function h4(e){var t,n=e.popper,r=e.popperRect,a=e.placement,o=e.variation,i=e.offsets,l=e.position,s=e.gpuAcceleration,c=e.adaptive,d=e.roundOffsets,f=e.isFixed,p=i.x,v=p===void 0?0:p,m=i.y,y=m===void 0?0:m,b=typeof d==\"function\"?d({x:v,y}):{x:v,y};v=b.x,y=b.y;var C=i.hasOwnProperty(\"x\"),S=i.hasOwnProperty(\"y\"),w=zr,k=Vr,$=window;if(c){var O=Ef(n),T=\"clientHeight\",_=\"clientWidth\";if(O===po(n)&&(O=yl(n),bi(O).position!==\"static\"&&l===\"absolute\"&&(T=\"scrollHeight\",_=\"scrollWidth\")),O=O,a===Vr||(a===zr||a===Aa)&&o===Ud){k=Na;var I=f&&O===$&&$.visualViewport?$.visualViewport.height:O[T];y-=I-r.height,y*=s?1:-1}if(a===zr||(a===Vr||a===Na)&&o===Ud){w=Aa;var L=f&&O===$&&$.visualViewport?$.visualViewport.width:O[_];v-=L-r.width,v*=s?1:-1}}var j=Object.assign({position:l},c&&uQ),F=d===!0?cQ({x:v,y}):{x:v,y};if(v=F.x,y=F.y,s){var N;return Object.assign({},j,(N={},N[k]=S?\"0\":\"\",N[w]=C?\"0\":\"\",N.transform=($.devicePixelRatio||1)<=1?\"translate(\"+v+\"px, \"+y+\"px)\":\"translate3d(\"+v+\"px, \"+y+\"px, 0)\",N))}return Object.assign({},j,(t={},t[k]=S?y+\"px\":\"\",t[w]=C?v+\"px\":\"\",t.transform=\"\",t))}function dQ(e){var t=e.state,n=e.options,r=n.gpuAcceleration,a=r===void 0?!0:r,o=n.adaptive,i=o===void 0?!0:o,l=n.roundOffsets,s=l===void 0?!0:l,c={placement:Mo(t.placement),variation:Zu(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:a,isFixed:t.options.strategy===\"fixed\"};t.modifiersData.popperOffsets!=null&&(t.styles.popper=Object.assign({},t.styles.popper,h4(Object.assign({},c,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:i,roundOffsets:s})))),t.modifiersData.arrow!=null&&(t.styles.arrow=Object.assign({},t.styles.arrow,h4(Object.assign({},c,{offsets:t.modifiersData.arrow,position:\"absolute\",adaptive:!1,roundOffsets:s})))),t.attributes.popper=Object.assign({},t.attributes.popper,{\"data-popper-placement\":t.placement})}var fQ={name:\"computeStyles\",enabled:!0,phase:\"beforeWrite\",fn:dQ,data:{}},ih={passive:!0};function hQ(e){var t=e.state,n=e.instance,r=e.options,a=r.scroll,o=a===void 0?!0:a,i=r.resize,l=i===void 0?!0:i,s=po(t.elements.popper),c=[].concat(t.scrollParents.reference,t.scrollParents.popper);return o&&c.forEach(function(d){d.addEventListener(\"scroll\",n.update,ih)}),l&&s.addEventListener(\"resize\",n.update,ih),function(){o&&c.forEach(function(d){d.removeEventListener(\"scroll\",n.update,ih)}),l&&s.removeEventListener(\"resize\",n.update,ih)}}var pQ={name:\"eventListeners\",enabled:!0,phase:\"write\",fn:function(){},effect:hQ,data:{}},vQ={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"};function dp(e){return e.replace(/left|right|bottom|top/g,function(t){return vQ[t]})}var mQ={start:\"end\",end:\"start\"};function p4(e){return e.replace(/start|end/g,function(t){return mQ[t]})}function JC(e){var t=po(e),n=t.pageXOffset,r=t.pageYOffset;return{scrollLeft:n,scrollTop:r}}function QC(e){return Xu(yl(e)).left+JC(e).scrollLeft}function gQ(e){var t=po(e),n=yl(e),r=t.visualViewport,a=n.clientWidth,o=n.clientHeight,i=0,l=0;return r&&(a=r.width,o=r.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(i=r.offsetLeft,l=r.offsetTop)),{width:a,height:o,x:i+QC(e),y:l}}function yQ(e){var t,n=yl(e),r=JC(e),a=(t=e.ownerDocument)==null?void 0:t.body,o=os(n.scrollWidth,n.clientWidth,a?a.scrollWidth:0,a?a.clientWidth:0),i=os(n.scrollHeight,n.clientHeight,a?a.scrollHeight:0,a?a.clientHeight:0),l=-r.scrollLeft+QC(e),s=-r.scrollTop;return bi(a||n).direction===\"rtl\"&&(l+=os(n.clientWidth,a?a.clientWidth:0)-o),{width:o,height:i,x:l,y:s}}function ew(e){var t=bi(e),n=t.overflow,r=t.overflowX,a=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+a+r)}function oM(e){return[\"html\",\"body\",\"#document\"].indexOf(Ao(e))>=0?e.ownerDocument.body:Ta(e)&&ew(e)?e:oM(Ym(e))}function gd(e,t){var n;t===void 0&&(t=[]);var r=oM(e),a=r===((n=e.ownerDocument)==null?void 0:n.body),o=po(r),i=a?[o].concat(o.visualViewport||[],ew(r)?r:[]):r,l=t.concat(i);return a?l:l.concat(gd(Ym(i)))}function v0(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function bQ(e){var t=Xu(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}function v4(e,t){return t===eM?v0(gQ(e)):qu(t)?bQ(t):v0(yQ(yl(e)))}function CQ(e){var t=gd(Ym(e)),n=[\"absolute\",\"fixed\"].indexOf(bi(e).position)>=0,r=n&&Ta(e)?Ef(e):e;return qu(r)?t.filter(function(a){return qu(a)&&tM(a,r)&&Ao(a)!==\"body\"}):[]}function wQ(e,t,n){var r=t===\"clippingParents\"?CQ(e):[].concat(t),a=[].concat(r,[n]),o=a[0],i=a.reduce(function(l,s){var c=v4(e,s);return l.top=os(c.top,l.top),l.right=bv(c.right,l.right),l.bottom=bv(c.bottom,l.bottom),l.left=os(c.left,l.left),l},v4(e,o));return i.width=i.right-i.left,i.height=i.bottom-i.top,i.x=i.left,i.y=i.top,i}function iM(e){var t=e.reference,n=e.element,r=e.placement,a=r?Mo(r):null,o=r?Zu(r):null,i=t.x+t.width/2-n.width/2,l=t.y+t.height/2-n.height/2,s;switch(a){case Vr:s={x:i,y:t.y-n.height};break;case Na:s={x:i,y:t.y+t.height};break;case Aa:s={x:t.x+t.width,y:l};break;case zr:s={x:t.x-n.width,y:l};break;default:s={x:t.x,y:t.y}}var c=a?ZC(a):null;if(c!=null){var d=c===\"y\"?\"height\":\"width\";switch(o){case Yu:s[c]=s[c]-(t[d]/2-n[d]/2);break;case Ud:s[c]=s[c]+(t[d]/2-n[d]/2);break}}return s}function Yd(e,t){t===void 0&&(t={});var n=t,r=n.placement,a=r===void 0?e.placement:r,o=n.boundary,i=o===void 0?zJ:o,l=n.rootBoundary,s=l===void 0?eM:l,c=n.elementContext,d=c===void 0?Bc:c,f=n.altBoundary,p=f===void 0?!1:f,v=n.padding,m=v===void 0?0:v,y=rM(typeof m!=\"number\"?m:aM(m,_f)),b=d===Bc?HJ:Bc,C=e.rects.popper,S=e.elements[p?b:d],w=wQ(qu(S)?S:S.contextElement||yl(e.elements.popper),i,s),k=Xu(e.elements.reference),$=iM({reference:k,element:C,strategy:\"absolute\",placement:a}),O=v0(Object.assign({},C,$)),T=d===Bc?O:k,_={top:w.top-T.top+y.top,bottom:T.bottom-w.bottom+y.bottom,left:w.left-T.left+y.left,right:T.right-w.right+y.right},I=e.modifiersData.offset;if(d===Bc&&I){var L=I[a];Object.keys(_).forEach(function(j){var F=[Aa,Na].indexOf(j)>=0?1:-1,N=[Vr,Na].indexOf(j)>=0?\"y\":\"x\";_[j]+=L[N]*F})}return _}function SQ(e,t){t===void 0&&(t={});var n=t,r=n.placement,a=n.boundary,o=n.rootBoundary,i=n.padding,l=n.flipVariations,s=n.allowedAutoPlacements,c=s===void 0?qC:s,d=Zu(r),f=d?l?d4:d4.filter(function(m){return Zu(m)===d}):_f,p=f.filter(function(m){return c.indexOf(m)>=0});p.length===0&&(p=f);var v=p.reduce(function(m,y){return m[y]=Yd(e,{placement:y,boundary:a,rootBoundary:o,padding:i})[Mo(y)],m},{});return Object.keys(v).sort(function(m,y){return v[m]-v[y]})}function kQ(e){if(Mo(e)===YC)return[];var t=dp(e);return[p4(e),t,p4(t)]}function $Q(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var a=n.mainAxis,o=a===void 0?!0:a,i=n.altAxis,l=i===void 0?!0:i,s=n.fallbackPlacements,c=n.padding,d=n.boundary,f=n.rootBoundary,p=n.altBoundary,v=n.flipVariations,m=v===void 0?!0:v,y=n.allowedAutoPlacements,b=t.options.placement,C=Mo(b),S=C===b,w=s||(S||!m?[dp(b)]:kQ(b)),k=[b].concat(w).reduce(function(ne,oe){return ne.concat(Mo(oe)===YC?SQ(t,{placement:oe,boundary:d,rootBoundary:f,padding:c,flipVariations:m,allowedAutoPlacements:y}):oe)},[]),$=t.rects.reference,O=t.rects.popper,T=new Map,_=!0,I=k[0],L=0;L<k.length;L++){var j=k[L],F=Mo(j),N=Zu(j)===Yu,D=[Vr,Na].indexOf(F)>=0,z=D?\"width\":\"height\",B=Yd(t,{placement:j,boundary:d,rootBoundary:f,altBoundary:p,padding:c}),M=D?N?Aa:zr:N?Na:Vr;$[z]>O[z]&&(M=dp(M));var E=dp(M),K=[];if(o&&K.push(B[F]<=0),l&&K.push(B[M]<=0,B[E]<=0),K.every(function(ne){return ne})){I=j,_=!1;break}T.set(j,K)}if(_)for(var W=m?3:1,Y=function(oe){var Q=k.find(function(ae){var de=T.get(ae);if(de)return de.slice(0,oe).every(function(be){return be})});if(Q)return I=Q,\"break\"},q=W;q>0;q--){var J=Y(q);if(J===\"break\")break}t.placement!==I&&(t.modifiersData[r]._skip=!0,t.placement=I,t.reset=!0)}}var OQ={name:\"flip\",enabled:!0,phase:\"main\",fn:$Q,requiresIfExists:[\"offset\"],data:{_skip:!1}};function m4(e,t,n){return n===void 0&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function g4(e){return[Vr,Aa,Na,zr].some(function(t){return e[t]>=0})}function PQ(e){var t=e.state,n=e.name,r=t.rects.reference,a=t.rects.popper,o=t.modifiersData.preventOverflow,i=Yd(t,{elementContext:\"reference\"}),l=Yd(t,{altBoundary:!0}),s=m4(i,r),c=m4(l,a,o),d=g4(s),f=g4(c);t.modifiersData[n]={referenceClippingOffsets:s,popperEscapeOffsets:c,isReferenceHidden:d,hasPopperEscaped:f},t.attributes.popper=Object.assign({},t.attributes.popper,{\"data-popper-reference-hidden\":d,\"data-popper-escaped\":f})}var TQ={name:\"hide\",enabled:!0,phase:\"main\",requiresIfExists:[\"preventOverflow\"],fn:PQ};function xQ(e,t,n){var r=Mo(e),a=[zr,Vr].indexOf(r)>=0?-1:1,o=typeof n==\"function\"?n(Object.assign({},t,{placement:e})):n,i=o[0],l=o[1];return i=i||0,l=(l||0)*a,[zr,Aa].indexOf(r)>=0?{x:l,y:i}:{x:i,y:l}}function _Q(e){var t=e.state,n=e.options,r=e.name,a=n.offset,o=a===void 0?[0,0]:a,i=qC.reduce(function(d,f){return d[f]=xQ(f,t.rects,o),d},{}),l=i[t.placement],s=l.x,c=l.y;t.modifiersData.popperOffsets!=null&&(t.modifiersData.popperOffsets.x+=s,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=i}var EQ={name:\"offset\",enabled:!0,phase:\"main\",requires:[\"popperOffsets\"],fn:_Q};function MQ(e){var t=e.state,n=e.name;t.modifiersData[n]=iM({reference:t.rects.reference,element:t.rects.popper,strategy:\"absolute\",placement:t.placement})}var IQ={name:\"popperOffsets\",enabled:!0,phase:\"read\",fn:MQ,data:{}};function NQ(e){return e===\"x\"?\"y\":\"x\"}function AQ(e){var t=e.state,n=e.options,r=e.name,a=n.mainAxis,o=a===void 0?!0:a,i=n.altAxis,l=i===void 0?!1:i,s=n.boundary,c=n.rootBoundary,d=n.altBoundary,f=n.padding,p=n.tether,v=p===void 0?!0:p,m=n.tetherOffset,y=m===void 0?0:m,b=Yd(t,{boundary:s,rootBoundary:c,padding:f,altBoundary:d}),C=Mo(t.placement),S=Zu(t.placement),w=!S,k=ZC(C),$=NQ(k),O=t.modifiersData.popperOffsets,T=t.rects.reference,_=t.rects.popper,I=typeof y==\"function\"?y(Object.assign({},t.rects,{placement:t.placement})):y,L=typeof I==\"number\"?{mainAxis:I,altAxis:I}:Object.assign({mainAxis:0,altAxis:0},I),j=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,F={x:0,y:0};if(!!O){if(o){var N,D=k===\"y\"?Vr:zr,z=k===\"y\"?Na:Aa,B=k===\"y\"?\"height\":\"width\",M=O[k],E=M+b[D],K=M-b[z],W=v?-_[B]/2:0,Y=S===Yu?T[B]:_[B],q=S===Yu?-_[B]:-T[B],J=t.elements.arrow,ne=v&&J?XC(J):{width:0,height:0},oe=t.modifiersData[\"arrow#persistent\"]?t.modifiersData[\"arrow#persistent\"].padding:nM(),Q=oe[D],ae=oe[z],de=md(0,T[B],ne[B]),be=w?T[B]/2-W-de-Q-L.mainAxis:Y-de-Q-L.mainAxis,Ee=w?-T[B]/2+W+de+ae+L.mainAxis:q+de+ae+L.mainAxis,Pe=t.elements.arrow&&Ef(t.elements.arrow),Be=Pe?k===\"y\"?Pe.clientTop||0:Pe.clientLeft||0:0,te=(N=j==null?void 0:j[k])!=null?N:0,ie=M+be-te-Be,ge=M+Ee-te,ke=md(v?bv(E,ie):E,M,v?os(K,ge):K);O[k]=ke,F[k]=ke-M}if(l){var xe,Ie=k===\"x\"?Vr:zr,ye=k===\"x\"?Na:Aa,pe=O[$],ue=$===\"y\"?\"height\":\"width\",Ce=pe+b[Ie],je=pe-b[ye],ee=[Vr,zr].indexOf(C)!==-1,me=(xe=j==null?void 0:j[$])!=null?xe:0,He=ee?Ce:pe-T[ue]-_[ue]-me+L.altAxis,lt=ee?pe+T[ue]+_[ue]-me-L.altAxis:je,Ye=v&&ee?aQ(He,pe,lt):md(v?He:Ce,pe,v?lt:je);O[$]=Ye,F[$]=Ye-pe}t.modifiersData[r]=F}}var DQ={name:\"preventOverflow\",enabled:!0,phase:\"main\",fn:AQ,requiresIfExists:[\"offset\"]};function RQ(e){return{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}}function LQ(e){return e===po(e)||!Ta(e)?JC(e):RQ(e)}function FQ(e){var t=e.getBoundingClientRect(),n=Gu(t.width)/e.offsetWidth||1,r=Gu(t.height)/e.offsetHeight||1;return n!==1||r!==1}function BQ(e,t,n){n===void 0&&(n=!1);var r=Ta(t),a=Ta(t)&&FQ(t),o=yl(t),i=Xu(e,a),l={scrollLeft:0,scrollTop:0},s={x:0,y:0};return(r||!r&&!n)&&((Ao(t)!==\"body\"||ew(o))&&(l=LQ(t)),Ta(t)?(s=Xu(t,!0),s.x+=t.clientLeft,s.y+=t.clientTop):o&&(s.x=QC(o))),{x:i.left+l.scrollLeft-s.x,y:i.top+l.scrollTop-s.y,width:i.width,height:i.height}}function VQ(e){var t=new Map,n=new Set,r=[];e.forEach(function(o){t.set(o.name,o)});function a(o){n.add(o.name);var i=[].concat(o.requires||[],o.requiresIfExists||[]);i.forEach(function(l){if(!n.has(l)){var s=t.get(l);s&&a(s)}}),r.push(o)}return e.forEach(function(o){n.has(o.name)||a(o)}),r}function zQ(e){var t=VQ(e);return JJ.reduce(function(n,r){return n.concat(t.filter(function(a){return a.phase===r}))},[])}function HQ(e){var t;return function(){return t||(t=new Promise(function(n){Promise.resolve().then(function(){t=void 0,n(e())})})),t}}function jQ(e){var t=e.reduce(function(n,r){var a=n[r.name];return n[r.name]=a?Object.assign({},a,r,{options:Object.assign({},a.options,r.options),data:Object.assign({},a.data,r.data)}):r,n},{});return Object.keys(t).map(function(n){return t[n]})}var y4={placement:\"bottom\",modifiers:[],strategy:\"absolute\"};function b4(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return!t.some(function(r){return!(r&&typeof r.getBoundingClientRect==\"function\")})}function KQ(e){e===void 0&&(e={});var t=e,n=t.defaultModifiers,r=n===void 0?[]:n,a=t.defaultOptions,o=a===void 0?y4:a;return function(l,s,c){c===void 0&&(c=o);var d={placement:\"bottom\",orderedModifiers:[],options:Object.assign({},y4,o),modifiersData:{},elements:{reference:l,popper:s},attributes:{},styles:{}},f=[],p=!1,v={state:d,setOptions:function(C){var S=typeof C==\"function\"?C(d.options):C;y(),d.options=Object.assign({},o,d.options,S),d.scrollParents={reference:qu(l)?gd(l):l.contextElement?gd(l.contextElement):[],popper:gd(s)};var w=zQ(jQ([].concat(r,d.options.modifiers)));return d.orderedModifiers=w.filter(function(k){return k.enabled}),m(),v.update()},forceUpdate:function(){if(!p){var C=d.elements,S=C.reference,w=C.popper;if(!!b4(S,w)){d.rects={reference:BQ(S,Ef(w),d.options.strategy===\"fixed\"),popper:XC(w)},d.reset=!1,d.placement=d.options.placement,d.orderedModifiers.forEach(function(L){return d.modifiersData[L.name]=Object.assign({},L.data)});for(var k=0;k<d.orderedModifiers.length;k++){if(d.reset===!0){d.reset=!1,k=-1;continue}var $=d.orderedModifiers[k],O=$.fn,T=$.options,_=T===void 0?{}:T,I=$.name;typeof O==\"function\"&&(d=O({state:d,options:_,name:I,instance:v})||d)}}}},update:HQ(function(){return new Promise(function(b){v.forceUpdate(),b(d)})}),destroy:function(){y(),p=!0}};if(!b4(l,s))return v;v.setOptions(c).then(function(b){!p&&c.onFirstUpdate&&c.onFirstUpdate(b)});function m(){d.orderedModifiers.forEach(function(b){var C=b.name,S=b.options,w=S===void 0?{}:S,k=b.effect;if(typeof k==\"function\"){var $=k({state:d,name:C,instance:v,options:w}),O=function(){};f.push($||O)}})}function y(){f.forEach(function(b){return b()}),f=[]}return v}}var WQ=[pQ,IQ,fQ,tQ,EQ,OQ,DQ,sQ,TQ],lM=KQ({defaultModifiers:WQ});const UQ=[\"fixed\",\"absolute\"],YQ=Ze({boundariesPadding:{type:Number,default:0},fallbackPlacements:{type:Le(Array),default:()=>[]},gpuAcceleration:{type:Boolean,default:!0},offset:{type:Number,default:12},placement:{type:String,values:qC,default:\"bottom\"},popperOptions:{type:Le(Object),default:()=>({})},strategy:{type:String,values:UQ,default:\"absolute\"}}),sM=Ze(Ke(Te({},YQ),{style:{type:Le([String,Array,Object])},className:{type:Le([String,Array,Object])},effect:{type:String,default:\"dark\"},visible:Boolean,enterable:{type:Boolean,default:!0},pure:Boolean,popperClass:{type:Le([String,Array,Object])},popperStyle:{type:Le([String,Array,Object])},referenceEl:{type:Le(Object)},stopPopperMouseEvent:{type:Boolean,default:!0},zIndex:Number})),C4=(e,t)=>{const{placement:n,strategy:r,popperOptions:a}=e,o=Ke(Te({placement:n,strategy:r},a),{modifiers:GQ(e)});return XQ(o,t),ZQ(o,a==null?void 0:a.modifiers),o},qQ=e=>{if(!!Bt)return eo(e)};function GQ(e){const{offset:t,gpuAcceleration:n,fallbackPlacements:r}=e;return[{name:\"offset\",options:{offset:[0,t!=null?t:12]}},{name:\"preventOverflow\",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:\"flip\",options:{padding:5,fallbackPlacements:r!=null?r:[]}},{name:\"computeStyles\",options:{gpuAcceleration:n,adaptive:n}}]}function XQ(e,{arrowEl:t,arrowOffset:n}){e.modifiers.push({name:\"arrow\",options:{element:t,padding:n!=null?n:5}})}function ZQ(e,t){t&&(e.modifiers=[...e.modifiers,...t!=null?t:[]])}const JQ={name:\"ElPopperContent\"},QQ=G(Ke(Te({},JQ),{props:sM,emits:[\"mouseenter\",\"mouseleave\"],setup(e,{expose:t}){const n=e,{popperInstanceRef:r,contentRef:a,triggerRef:o}=ve(zC,void 0),{nextZIndex:i}=Pi(),l=De(\"popper\"),s=H(),c=H(),d=H();ot(ME,{arrowRef:c,arrowOffset:d});const f=H(n.zIndex||i()),p=x(()=>qQ(n.referenceEl)||A(o)),v=x(()=>[{zIndex:A(f)},n.popperStyle]),m=x(()=>[l.b(),l.is(\"pure\",n.pure),l.is(n.effect),n.popperClass]),y=({referenceEl:S,popperContentEl:w,arrowEl:k})=>{const $=C4(n,{arrowEl:k,arrowOffset:A(d)});return lM(S,w,$)},b=()=>{var S;(S=A(r))==null||S.update(),f.value=n.zIndex||f.value||i()},C=()=>{var S,w;const k={name:\"eventListeners\",enabled:n.visible};(w=(S=A(r))==null?void 0:S.setOptions)==null||w.call(S,$=>Ke(Te({},$),{modifiers:[...$.modifiers||[],k]})),b()};return et(()=>{let S;ce(p,w=>{var k;S==null||S();const $=A(r);if((k=$==null?void 0:$.destroy)==null||k.call($),w){const O=A(s);a.value=O,r.value=y({referenceEl:w,popperContentEl:O,arrowEl:A(c)}),S=ce(()=>w.getBoundingClientRect(),()=>b(),{immediate:!0})}else r.value=void 0},{immediate:!0}),ce(()=>n.visible,C,{immediate:!0}),ce(()=>C4(n,{arrowEl:A(c),arrowOffset:A(d)}),w=>{var k;return(k=r.value)==null?void 0:k.setOptions(w)})}),t({popperContentRef:s,popperInstanceRef:r,updatePopper:b,contentStyle:v}),(S,w)=>(R(),X(\"div\",{ref_key:\"popperContentRef\",ref:s,style:Xe(A(v)),class:U(A(m)),role:\"tooltip\",onMouseenter:w[0]||(w[0]=k=>S.$emit(\"mouseenter\",k)),onMouseleave:w[1]||(w[1]=k=>S.$emit(\"mouseleave\",k))},[Oe(S.$slots,\"default\")],38))}}));var eee=Ae(QQ,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popper/src/content.vue\"]]);const tee={LIGHT:\"light\",DARK:\"dark\"};Ze({autoClose:{type:Number,default:0},cutoff:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1}});function Oc(e,t){const n=$t(),r=x(()=>yr(n.props[t])?n.props[t]:n.props.teleported);return Tf({scope:e,from:t,replacement:\"teleported\",version:\"2.1.0\",ref:\"https://element-plus.org/en-US/component/tooltip.html#attributes\"},x(()=>yr(n.props[t]))),{compatTeleported:r}}const uM=xt(IJ),nee=G({name:\"ElVisuallyHidden\",props:{style:{type:[String,Object,Array]}},setup(e){return{computedStyle:x(()=>[e.style,{position:\"absolute\",border:0,width:1,height:1,padding:0,margin:-1,overflow:\"hidden\",clip:\"rect(0, 0, 0, 0)\",whiteSpace:\"nowrap\",wordWrap:\"normal\"}])}}});function ree(e,t,n,r,a,o){return R(),X(\"span\",hn(e.$attrs,{style:e.computedStyle}),[Oe(e.$slots,\"default\")],16)}var cM=Ae(nee,[[\"render\",ree],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/visual-hidden/src/visual-hidden.vue\"]]);const mr=Ze(Ke(Te(Te({},bZ),sM),{appendTo:{type:Le([String,Object]),default:VE},content:{type:String,default:\"\"},rawContent:{type:Boolean,default:!1},persistent:Boolean,ariaLabel:String,visible:{type:Le(Boolean),default:null},transition:{type:String,default:\"el-fade-in-linear\"},teleported:{type:Boolean,default:!0},disabled:{type:Boolean}})),qd=Ze(Ke(Te({},QE),{disabled:Boolean,trigger:{type:Le([String,Array]),default:\"hover\"}})),aee=Ze({openDelay:{type:Number},visibleArrow:{type:Boolean,default:void 0},hideAfter:{type:Number,default:200},showArrow:{type:Boolean,default:!0}}),qm=Symbol(\"elTooltip\"),oee=G({name:\"ElTooltipContent\",components:{ElPopperContent:eee,ElVisuallyHidden:cM},inheritAttrs:!1,props:mr,setup(e){const t=H(null),n=H(!1),r=H(!1),a=H(!1),o=H(!1),{controlled:i,id:l,open:s,trigger:c,onClose:d,onOpen:f,onShow:p,onHide:v,onBeforeShow:m,onBeforeHide:y}=ve(qm,void 0),b=x(()=>e.persistent);Lt(()=>{o.value=!0});const C=x(()=>A(b)?!0:A(s)),S=x(()=>e.disabled?!1:A(s)),w=x(()=>{var N;return(N=e.style)!=null?N:{}}),k=x(()=>!A(s));mZ(d);const $=()=>{v()},O=()=>{if(A(i))return!0},T=Tn(O,()=>{e.enterable&&A(c)===\"hover\"&&f()}),_=Tn(O,()=>{A(c)===\"hover\"&&d()}),I=()=>{var N,D;(D=(N=t.value)==null?void 0:N.updatePopper)==null||D.call(N),m==null||m()},L=()=>{y==null||y()},j=()=>{p()};let F;return ce(()=>A(s),N=>{N?F=vv(x(()=>{var D;return(D=t.value)==null?void 0:D.popperContentRef}),()=>{if(A(i))return;A(c)!==\"hover\"&&d()}):F==null||F()},{flush:\"post\"}),{ariaHidden:k,entering:r,leaving:a,id:l,intermediateOpen:n,contentStyle:w,contentRef:t,destroyed:o,shouldRender:C,shouldShow:S,open:s,onAfterShow:j,onBeforeEnter:I,onBeforeLeave:L,onContentEnter:T,onContentLeave:_,onTransitionLeave:$}}});function iee(e,t,n,r,a,o){const i=we(\"el-visually-hidden\"),l=we(\"el-popper-content\");return R(),fe(Ps,{disabled:!e.teleported,to:e.appendTo},[g(Vn,{name:e.transition,onAfterLeave:e.onTransitionLeave,onBeforeEnter:e.onBeforeEnter,onAfterEnter:e.onAfterShow,onBeforeLeave:e.onBeforeLeave},{default:re(()=>[e.shouldRender?at((R(),fe(l,hn({key:0,ref:\"contentRef\"},e.$attrs,{\"aria-hidden\":e.ariaHidden,\"boundaries-padding\":e.boundariesPadding,\"fallback-placements\":e.fallbackPlacements,\"gpu-acceleration\":e.gpuAcceleration,offset:e.offset,placement:e.placement,\"popper-options\":e.popperOptions,strategy:e.strategy,effect:e.effect,enterable:e.enterable,pure:e.pure,\"popper-class\":e.popperClass,\"popper-style\":[e.popperStyle,e.contentStyle],\"reference-el\":e.referenceEl,visible:e.shouldShow,\"z-index\":e.zIndex,onMouseenter:e.onContentEnter,onMouseleave:e.onContentLeave}),{default:re(()=>[se(\" Workaround bug #6378 \"),e.destroyed?se(\"v-if\",!0):(R(),X(Fe,{key:0},[Oe(e.$slots,\"default\"),g(i,{id:e.id,role:\"tooltip\"},{default:re(()=>[yt(Me(e.ariaLabel),1)]),_:1},8,[\"id\"])],64))]),_:3},16,[\"aria-hidden\",\"boundaries-padding\",\"fallback-placements\",\"gpu-acceleration\",\"offset\",\"placement\",\"popper-options\",\"strategy\",\"effect\",\"enterable\",\"pure\",\"popper-class\",\"popper-style\",\"reference-el\",\"visible\",\"z-index\",\"onMouseenter\",\"onMouseleave\"])),[[_t,e.shouldShow]]):se(\"v-if\",!0)]),_:3},8,[\"name\",\"onAfterLeave\",\"onBeforeEnter\",\"onAfterEnter\",\"onBeforeLeave\"])],8,[\"disabled\",\"to\"])}var lee=Ae(oee,[[\"render\",iee],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip/src/content.vue\"]]);const see=(e,t)=>pt(e)?e.includes(t):e===t,Ls=(e,t,n)=>r=>{see(A(e),t)&&n(r)},uee=G({name:\"ElTooltipTrigger\",components:{ElPopperTrigger:VJ},props:qd,setup(e){const t=De(\"tooltip\"),{controlled:n,id:r,open:a,onOpen:o,onClose:i,onToggle:l}=ve(qm,void 0),s=H(null),c=()=>{if(A(n)||e.disabled)return!0},d=yn(e,\"trigger\"),f=Tn(c,Ls(d,\"hover\",o)),p=Tn(c,Ls(d,\"hover\",i)),v=Tn(c,Ls(d,\"click\",S=>{S.button===0&&l(S)})),m=Tn(c,Ls(d,\"focus\",o)),y=Tn(c,Ls(d,\"focus\",i)),b=Tn(c,Ls(d,\"contextmenu\",S=>{S.preventDefault(),l(S)})),C=Tn(c,S=>{const{code:w}=S;(w===Ge.enter||w===Ge.space)&&l(S)});return{onBlur:y,onContextMenu:b,onFocus:m,onMouseenter:f,onMouseleave:p,onClick:v,onKeydown:C,open:a,id:r,triggerRef:s,ns:t}}});function cee(e,t,n,r,a,o){const i=we(\"el-popper-trigger\");return R(),fe(i,{id:e.id,\"virtual-ref\":e.virtualRef,open:e.open,\"virtual-triggering\":e.virtualTriggering,class:U(e.ns.e(\"trigger\")),onBlur:e.onBlur,onClick:e.onClick,onContextmenu:e.onContextMenu,onFocus:e.onFocus,onMouseenter:e.onMouseenter,onMouseleave:e.onMouseleave,onKeydown:e.onKeydown},{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},8,[\"id\",\"virtual-ref\",\"open\",\"virtual-triggering\",\"class\",\"onBlur\",\"onClick\",\"onContextmenu\",\"onFocus\",\"onMouseenter\",\"onMouseleave\",\"onKeydown\"])}var dee=Ae(uee,[[\"render\",cee],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip/src/trigger.vue\"]]);const{useModelToggleProps:fee,useModelToggle:hee,useModelToggleEmits:pee}=cZ(\"visible\"),vee=G({name:\"ElTooltip\",components:{ElPopper:uM,ElPopperArrow:DJ,ElTooltipContent:lee,ElTooltipTrigger:dee},props:Te(Te(Te(Te(Te({},fee),mr),qd),ZE),aee),emits:[...pee,\"before-show\",\"before-hide\",\"show\",\"hide\"],setup(e,{emit:t}){yZ();const n=x(()=>(sa(e.openDelay),e.openDelay||e.showAfter)),r=x(()=>(sa(e.visibleArrow),yr(e.visibleArrow)?e.visibleArrow:e.showArrow)),a=jC(),o=H(null),i=()=>{var v;const m=A(o);m&&((v=m.popperInstanceRef)==null||v.update())},l=H(!1),{show:s,hide:c}=hee({indicator:l}),{onOpen:d,onClose:f}=CZ({showAfter:n,hideAfter:yn(e,\"hideAfter\"),open:s,close:c}),p=x(()=>yr(e.visible));return ot(qm,{controlled:p,id:a,open:Cf(l),trigger:yn(e,\"trigger\"),onOpen:d,onClose:f,onToggle:()=>{A(l)?f():d()},onShow:()=>{t(\"show\")},onHide:()=>{t(\"hide\")},onBeforeShow:()=>{t(\"before-show\")},onBeforeHide:()=>{t(\"before-hide\")},updatePopper:i}),ce(()=>e.disabled,v=>{v&&l.value&&(l.value=!1)}),{compatShowAfter:n,compatShowArrow:r,popperRef:o,open:l,hide:c,updatePopper:i,onOpen:d,onClose:f}}}),mee=[\"innerHTML\"],gee={key:1};function yee(e,t,n,r,a,o){const i=we(\"el-tooltip-trigger\"),l=we(\"el-popper-arrow\"),s=we(\"el-tooltip-content\"),c=we(\"el-popper\");return R(),fe(c,{ref:\"popperRef\"},{default:re(()=>[g(i,{disabled:e.disabled,trigger:e.trigger,\"virtual-ref\":e.virtualRef,\"virtual-triggering\":e.virtualTriggering},{default:re(()=>[e.$slots.default?Oe(e.$slots,\"default\",{key:0}):se(\"v-if\",!0)]),_:3},8,[\"disabled\",\"trigger\",\"virtual-ref\",\"virtual-triggering\"]),g(s,{\"aria-label\":e.ariaLabel,\"boundaries-padding\":e.boundariesPadding,content:e.content,disabled:e.disabled,effect:e.effect,enterable:e.enterable,\"fallback-placements\":e.fallbackPlacements,\"hide-after\":e.hideAfter,\"gpu-acceleration\":e.gpuAcceleration,offset:e.offset,persistent:e.persistent,\"popper-class\":e.popperClass,\"popper-style\":e.popperStyle,placement:e.placement,\"popper-options\":e.popperOptions,pure:e.pure,\"raw-content\":e.rawContent,\"reference-el\":e.referenceEl,\"show-after\":e.compatShowAfter,strategy:e.strategy,teleported:e.teleported,transition:e.transition,\"z-index\":e.zIndex,\"append-to\":e.appendTo},{default:re(()=>[Oe(e.$slots,\"content\",{},()=>[e.rawContent?(R(),X(\"span\",{key:0,innerHTML:e.content},null,8,mee)):(R(),X(\"span\",gee,Me(e.content),1))]),e.compatShowArrow?(R(),fe(l,{key:0,\"arrow-offset\":e.arrowOffset},null,8,[\"arrow-offset\"])):se(\"v-if\",!0)]),_:3},8,[\"aria-label\",\"boundaries-padding\",\"content\",\"disabled\",\"effect\",\"enterable\",\"fallback-placements\",\"hide-after\",\"gpu-acceleration\",\"offset\",\"persistent\",\"popper-class\",\"popper-style\",\"placement\",\"popper-options\",\"pure\",\"raw-content\",\"reference-el\",\"show-after\",\"strategy\",\"teleported\",\"transition\",\"z-index\",\"append-to\"])]),_:3},512)}var bee=Ae(vee,[[\"render\",yee],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip/src/tooltip.vue\"]]);const Ur=xt(bee),Cee=Ze({valueKey:{type:String,default:\"value\"},modelValue:{type:[String,Number],default:\"\"},debounce:{type:Number,default:300},placement:{type:Le(String),values:[\"top\",\"top-start\",\"top-end\",\"bottom\",\"bottom-start\",\"bottom-end\"],default:\"bottom-start\"},fetchSuggestions:{type:Le([Function,Array]),default:Qt},popperClass:{type:String,default:\"\"},triggerOnFocus:{type:Boolean,default:!0},selectWhenUnmatched:{type:Boolean,default:!1},hideLoading:{type:Boolean,default:!1},popperAppendToBody:{type:Boolean,default:void 0},teleported:mr.teleported,highlightFirstItem:{type:Boolean,default:!1}}),wee={[Pt]:e=>wt(e),input:e=>wt(e),change:e=>wt(e),focus:e=>e instanceof FocusEvent,blur:e=>e instanceof FocusEvent,clear:()=>!0,select:e=>zt(e)},See=[\"aria-expanded\",\"aria-owns\"],kee={key:0},$ee=[\"id\",\"aria-selected\",\"onClick\"],Oee={name:\"ElAutocomplete\",inheritAttrs:!1},Pee=G(Ke(Te({},Oee),{props:Cee,emits:wee,setup(e,{expose:t,emit:n}){const r=e,a=\"ElAutocomplete\",o=De(\"autocomplete\"),{compatTeleported:i}=Oc(a,\"popperAppendToBody\");let l=!1;const s=VC(),c=W6(),d=H([]),f=H(-1),p=H(\"\"),v=H(!1),m=H(!1),y=H(!1),b=H(),C=H(),S=H(),w=H(),k=x(()=>o.b(String(Pf()))),$=x(()=>c.style),O=x(()=>(pt(d.value)&&d.value.length>0||y.value)&&v.value),T=x(()=>!r.hideLoading&&y.value),_=()=>{Ne(()=>{O.value&&(p.value=`${b.value.$el.offsetWidth}px`)})},L=Yn(Y=>{if(m.value)return;y.value=!0;const q=J=>{y.value=!1,!m.value&&(pt(J)?(d.value=J,f.value=r.highlightFirstItem?0:-1):qn(a,\"autocomplete suggestions must be an array\"))};if(pt(r.fetchSuggestions))q(r.fetchSuggestions);else{const J=r.fetchSuggestions(Y,q);pt(J)?q(J):hs(J)&&J.then(q)}},r.debounce),j=Y=>{const q=Boolean(Y);if(n(\"input\",Y),n(Pt,Y),m.value=!1,v.value||(v.value=l&&q),!r.triggerOnFocus&&!Y){m.value=!0,d.value=[];return}l&&q&&(l=!1),L(Y)},F=Y=>{n(\"change\",Y)},N=Y=>{v.value=!0,n(\"focus\",Y),r.triggerOnFocus&&L(String(r.modelValue))},D=Y=>{n(\"blur\",Y)},z=()=>{v.value=!1,l=!0,n(Pt,\"\"),n(\"clear\")},B=()=>{O.value&&f.value>=0&&f.value<d.value.length?K(d.value[f.value]):r.selectWhenUnmatched&&(n(\"select\",{value:r.modelValue}),Ne(()=>{d.value=[],f.value=-1}))},M=()=>{v.value=!1},E=()=>{var Y;(Y=b.value)==null||Y.focus()},K=Y=>{n(\"input\",Y[r.valueKey]),n(Pt,Y[r.valueKey]),n(\"select\",Y),Ne(()=>{d.value=[],f.value=-1})},W=Y=>{if(!O.value||y.value)return;if(Y<0){f.value=-1;return}Y>=d.value.length&&(Y=d.value.length-1);const q=C.value.querySelector(`.${o.be(\"suggestion\",\"wrap\")}`),ne=q.querySelectorAll(`.${o.be(\"suggestion\",\"list\")} li`)[Y],oe=q.scrollTop,{offsetTop:Q,scrollHeight:ae}=ne;Q+ae>oe+q.clientHeight&&(q.scrollTop+=ae),Q<oe&&(q.scrollTop-=ae),f.value=Y,b.value.ref.setAttribute(\"aria-activedescendant\",`${k.value}-item-${f.value}`)};return vv(w,M),et(()=>{b.value.ref.setAttribute(\"role\",\"textbox\"),b.value.ref.setAttribute(\"aria-autocomplete\",\"list\"),b.value.ref.setAttribute(\"aria-controls\",\"id\"),b.value.ref.setAttribute(\"aria-activedescendant\",`${k.value}-item-${f.value}`)}),t({highlightedIndex:f,activated:v,loading:y,inputRef:b,popperRef:S,suggestions:d,handleSelect:K,handleKeyEnter:B,focus:E,close:M,highlight:W}),(Y,q)=>(R(),fe(A(Ur),{ref_key:\"popperRef\",ref:S,visible:A(O),\"onUpdate:visible\":q[2]||(q[2]=J=>_n(O)?O.value=J:null),placement:Y.placement,\"fallback-placements\":[\"bottom-start\",\"top-start\"],\"popper-class\":[A(o).e(\"popper\"),Y.popperClass],teleported:A(i),\"gpu-acceleration\":!1,pure:\"\",\"manual-mode\":\"\",effect:\"light\",trigger:\"click\",transition:`${A(o).namespace.value}-zoom-in-top`,persistent:\"\",onBeforeShow:_},{content:re(()=>[Z(\"div\",{ref_key:\"regionRef\",ref:C,class:U([A(o).b(\"suggestion\"),A(o).is(\"loading\",A(T))]),style:Xe({minWidth:p.value,outline:\"none\"}),role:\"region\"},[g(A(xi),{id:A(k),tag:\"ul\",\"wrap-class\":A(o).be(\"suggestion\",\"wrap\"),\"view-class\":A(o).be(\"suggestion\",\"list\"),role:\"listbox\"},{default:re(()=>[A(T)?(R(),X(\"li\",kee,[g(A(ft),{class:U(A(o).is(\"loading\"))},{default:re(()=>[g(A(gl))]),_:1},8,[\"class\"])])):(R(!0),X(Fe,{key:1},Rt(d.value,(J,ne)=>(R(),X(\"li\",{id:`${A(k)}-item-${ne}`,key:ne,class:U({highlighted:f.value===ne}),role:\"option\",\"aria-selected\":f.value===ne,onClick:oe=>K(J)},[Oe(Y.$slots,\"default\",{item:J},()=>[yt(Me(J[Y.valueKey]),1)])],10,$ee))),128))]),_:3},8,[\"id\",\"wrap-class\",\"view-class\"])],6)]),default:re(()=>[Z(\"div\",{ref_key:\"listboxRef\",ref:w,class:U([A(o).b(),Y.$attrs.class]),style:Xe(A($)),role:\"combobox\",\"aria-haspopup\":\"listbox\",\"aria-expanded\":A(O),\"aria-owns\":A(k)},[g(A(Ra),hn({ref_key:\"inputRef\",ref:b},A(s),{\"model-value\":Y.modelValue,onInput:j,onChange:F,onFocus:N,onBlur:D,onClear:z,onKeydown:[q[0]||(q[0]=It(dt(J=>W(f.value-1),[\"prevent\"]),[\"up\"])),q[1]||(q[1]=It(dt(J=>W(f.value+1),[\"prevent\"]),[\"down\"])),It(B,[\"enter\"]),It(M,[\"tab\"])]}),sl({_:2},[Y.$slots.prepend?{name:\"prepend\",fn:re(()=>[Oe(Y.$slots,\"prepend\")])}:void 0,Y.$slots.append?{name:\"append\",fn:re(()=>[Oe(Y.$slots,\"append\")])}:void 0,Y.$slots.prefix?{name:\"prefix\",fn:re(()=>[Oe(Y.$slots,\"prefix\")])}:void 0,Y.$slots.suffix?{name:\"suffix\",fn:re(()=>[Oe(Y.$slots,\"suffix\")])}:void 0]),1040,[\"model-value\",\"onKeydown\"])],14,See)]),_:3},8,[\"visible\",\"placement\",\"popper-class\",\"teleported\",\"transition\"]))}}));var Tee=Ae(Pee,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/autocomplete/src/autocomplete.vue\"]]);const xee=xt(Tee),_ee=Ze({size:{type:[Number,String],values:Bo,default:\"\",validator:e=>typeof e==\"number\"},shape:{type:String,values:[\"circle\",\"square\"],default:\"circle\"},icon:{type:wr},src:{type:String,default:\"\"},alt:String,srcSet:String,fit:{type:Le(String),default:\"cover\"}}),Eee={error:e=>e instanceof Event},Mee=[\"src\",\"alt\",\"srcset\"],Iee={name:\"ElAvatar\"},Nee=G(Ke(Te({},Iee),{props:_ee,emits:Eee,setup(e,{emit:t}){const n=e,r=De(\"avatar\"),a=H(!1),o=x(()=>{const{size:c,icon:d,shape:f}=n,p=[r.b()];return wt(c)&&p.push(r.m(c)),d&&p.push(r.m(\"icon\")),f&&p.push(r.m(f)),p}),i=x(()=>{const{size:c}=n;return Yt(c)?{\"--el-avatar-size\":oo(c)}:void 0}),l=x(()=>({objectFit:n.fit}));ce(()=>n.src,()=>a.value=!1);function s(c){a.value=!0,t(\"error\",c)}return(c,d)=>(R(),X(\"span\",{class:U(A(o)),style:Xe(A(i))},[(c.src||c.srcSet)&&!a.value?(R(),X(\"img\",{key:0,src:c.src,alt:c.alt,srcset:c.srcSet,style:Xe(A(l)),onError:s},null,44,Mee)):c.icon?(R(),fe(A(ft),{key:1},{default:re(()=>[(R(),fe(Kt(c.icon)))]),_:1})):Oe(c.$slots,\"default\",{key:2})],6))}}));var Aee=Ae(Nee,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/avatar/src/avatar.vue\"]]);const Dee=xt(Aee),Ree={visibilityHeight:{type:Number,default:200},target:{type:String,default:\"\"},right:{type:Number,default:40},bottom:{type:Number,default:40}},Lee={click:e=>e instanceof MouseEvent},Fee=[\"onClick\"],Bee={name:\"ElBacktop\"},Vee=G(Ke(Te({},Bee),{props:Ree,emits:Lee,setup(e,{emit:t}){const n=e,r=\"ElBacktop\",a=De(\"backtop\"),o=Qn(),i=Qn(),l=H(!1),s=x(()=>({right:`${n.right}px`,bottom:`${n.bottom}px`})),c=()=>{if(!o.value)return;const v=Date.now(),m=o.value.scrollTop,y=()=>{if(!o.value)return;const b=(Date.now()-v)/500;b<1?(o.value.scrollTop=m*(1-JX(b)),requestAnimationFrame(y)):o.value.scrollTop=0};requestAnimationFrame(y)},d=()=>{o.value&&(l.value=o.value.scrollTop>=n.visibilityHeight)},f=v=>{c(),t(\"click\",v)},p=oE(d,300);return et(()=>{var v;i.value=document,o.value=document.documentElement,n.target&&(o.value=(v=document.querySelector(n.target))!=null?v:void 0,o.value||qn(r,`target is not existed: ${n.target}`),i.value=o.value),Hn(i,\"scroll\",p)}),(v,m)=>(R(),fe(Vn,{name:`${A(a).namespace.value}-fade-in`},{default:re(()=>[l.value?(R(),X(\"div\",{key:0,style:Xe(A(s)),class:U(A(a).b()),onClick:dt(f,[\"stop\"])},[Oe(v.$slots,\"default\",{},()=>[g(A(ft),{class:U(A(a).e(\"icon\"))},{default:re(()=>[g(A(kY))]),_:1},8,[\"class\"])])],14,Fee)):se(\"v-if\",!0)]),_:3},8,[\"name\"]))}}));var zee=Ae(Vee,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/backtop/src/backtop.vue\"]]);const Hee=xt(zee),jee=Ze({value:{type:[String,Number],default:\"\"},max:{type:Number,default:99},isDot:Boolean,hidden:Boolean,type:{type:String,values:[\"primary\",\"success\",\"warning\",\"info\",\"danger\"],default:\"danger\"}}),Kee=[\"textContent\"],Wee={name:\"ElBadge\"},Uee=G(Ke(Te({},Wee),{props:jee,setup(e,{expose:t}){const n=e,r=De(\"badge\"),a=x(()=>n.isDot?\"\":Yt(n.value)&&Yt(n.max)?n.max<n.value?`${n.max}+`:`${n.value}`:`${n.value}`);return t({content:a}),(o,i)=>(R(),X(\"div\",{class:U(A(r).b())},[Oe(o.$slots,\"default\"),g(Vn,{name:`${A(r).namespace.value}-zoom-in-center`},{default:re(()=>[at(Z(\"sup\",{class:U([A(r).e(\"content\"),A(r).em(\"content\",o.type),A(r).is(\"fixed\",!!o.$slots.default),A(r).is(\"dot\",o.isDot)]),textContent:Me(A(a))},null,10,Kee),[[_t,!o.hidden&&(A(a)||A(a)===\"0\"||o.isDot)]])]),_:1},8,[\"name\"])],2))}}));var Yee=Ae(Uee,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/badge/src/badge.vue\"]]);const dM=xt(Yee),qee=Ze({separator:{type:String,default:\"/\"},separatorIcon:{type:wr,default:\"\"}}),Gee={name:\"ElBreadcrumb\"},Xee=G(Ke(Te({},Gee),{props:qee,setup(e){const t=e,n=De(\"breadcrumb\"),r=H();return ot(CE,t),et(()=>{const a=r.value.querySelectorAll(`.${n.e(\"item\")}`);a.length&&a[a.length-1].setAttribute(\"aria-current\",\"page\")}),(a,o)=>(R(),X(\"div\",{ref_key:\"breadcrumb\",ref:r,class:U(A(n).b()),\"aria-label\":\"Breadcrumb\",role:\"navigation\"},[Oe(a.$slots,\"default\")],2))}}));var Zee=Ae(Xee,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/breadcrumb/src/breadcrumb.vue\"]]);const Jee=Ze({to:{type:Le([String,Object]),default:\"\"},replace:{type:Boolean,default:!1}}),Qee={name:\"ElBreadcrumbItem\"},ete=G(Ke(Te({},Qee),{props:Jee,setup(e){const t=e,r=$t().appContext.config.globalProperties.$router,a=ve(CE,{}),o=De(\"breadcrumb\"),{separator:i,separatorIcon:l}=a,s=H(),c=()=>{!t.to||!r||(t.replace?r.replace(t.to):r.push(t.to))};return(d,f)=>(R(),X(\"span\",{class:U(A(o).e(\"item\"))},[Z(\"span\",{ref_key:\"link\",ref:s,class:U([A(o).e(\"inner\"),A(o).is(\"link\",!!d.to)]),role:\"link\",onClick:c},[Oe(d.$slots,\"default\")],2),A(l)?(R(),fe(A(ft),{key:0,class:U(A(o).e(\"separator\"))},{default:re(()=>[(R(),fe(Kt(A(l))))]),_:1},8,[\"class\"])):(R(),X(\"span\",{key:1,class:U(A(o).e(\"separator\")),role:\"presentation\"},Me(A(i)),3))],2))}}));var fM=Ae(ete,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/breadcrumb/src/breadcrumb-item.vue\"]]);const tte=xt(Zee,{BreadcrumbItem:fM}),nte=En(fM),m0=[\"default\",\"primary\",\"success\",\"warning\",\"info\",\"danger\",\"text\",\"\"],rte=[\"button\",\"submit\",\"reset\"],g0=Ze({size:Km,disabled:Boolean,type:{type:String,values:m0,default:\"\"},icon:{type:wr,default:\"\"},nativeType:{type:String,values:rte,default:\"button\"},loading:Boolean,loadingIcon:{type:wr,default:()=>gl},plain:Boolean,autofocus:Boolean,round:Boolean,circle:Boolean,color:String,dark:Boolean,autoInsertSpace:{type:Boolean,default:void 0}}),ate={click:e=>e instanceof MouseEvent};function br(e,t){ote(e)&&(e=\"100%\");var n=ite(e);return e=t===360?e:Math.min(t,Math.max(0,parseFloat(e))),n&&(e=parseInt(String(e*t),10)/100),Math.abs(e-t)<1e-6?1:(t===360?e=(e<0?e%t+t:e%t)/parseFloat(String(t)):e=e%t/parseFloat(String(t)),e)}function lh(e){return Math.min(1,Math.max(0,e))}function ote(e){return typeof e==\"string\"&&e.indexOf(\".\")!==-1&&parseFloat(e)===1}function ite(e){return typeof e==\"string\"&&e.indexOf(\"%\")!==-1}function hM(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function sh(e){return e<=1?\"\".concat(Number(e)*100,\"%\"):e}function Ul(e){return e.length===1?\"0\"+e:String(e)}function lte(e,t,n){return{r:br(e,255)*255,g:br(t,255)*255,b:br(n,255)*255}}function w4(e,t,n){e=br(e,255),t=br(t,255),n=br(n,255);var r=Math.max(e,t,n),a=Math.min(e,t,n),o=0,i=0,l=(r+a)/2;if(r===a)i=0,o=0;else{var s=r-a;switch(i=l>.5?s/(2-r-a):s/(r+a),r){case e:o=(t-n)/s+(t<n?6:0);break;case t:o=(n-e)/s+2;break;case n:o=(e-t)/s+4;break}o/=6}return{h:o,s:i,l}}function ly(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*(6*n):n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function ste(e,t,n){var r,a,o;if(e=br(e,360),t=br(t,100),n=br(n,100),t===0)a=n,o=n,r=n;else{var i=n<.5?n*(1+t):n+t-n*t,l=2*n-i;r=ly(l,i,e+1/3),a=ly(l,i,e),o=ly(l,i,e-1/3)}return{r:r*255,g:a*255,b:o*255}}function y0(e,t,n){e=br(e,255),t=br(t,255),n=br(n,255);var r=Math.max(e,t,n),a=Math.min(e,t,n),o=0,i=r,l=r-a,s=r===0?0:l/r;if(r===a)o=0;else{switch(r){case e:o=(t-n)/l+(t<n?6:0);break;case t:o=(n-e)/l+2;break;case n:o=(e-t)/l+4;break}o/=6}return{h:o,s,v:i}}function ute(e,t,n){e=br(e,360)*6,t=br(t,100),n=br(n,100);var r=Math.floor(e),a=e-r,o=n*(1-t),i=n*(1-a*t),l=n*(1-(1-a)*t),s=r%6,c=[n,i,o,o,l,n][s],d=[l,n,n,i,o,o][s],f=[o,o,l,n,n,i][s];return{r:c*255,g:d*255,b:f*255}}function b0(e,t,n,r){var a=[Ul(Math.round(e).toString(16)),Ul(Math.round(t).toString(16)),Ul(Math.round(n).toString(16))];return r&&a[0].startsWith(a[0].charAt(1))&&a[1].startsWith(a[1].charAt(1))&&a[2].startsWith(a[2].charAt(1))?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0):a.join(\"\")}function cte(e,t,n,r,a){var o=[Ul(Math.round(e).toString(16)),Ul(Math.round(t).toString(16)),Ul(Math.round(n).toString(16)),Ul(dte(r))];return a&&o[0].startsWith(o[0].charAt(1))&&o[1].startsWith(o[1].charAt(1))&&o[2].startsWith(o[2].charAt(1))&&o[3].startsWith(o[3].charAt(1))?o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0):o.join(\"\")}function dte(e){return Math.round(parseFloat(e)*255).toString(16)}function S4(e){return ea(e)/255}function ea(e){return parseInt(e,16)}function fte(e){return{r:e>>16,g:(e&65280)>>8,b:e&255}}var C0={aliceblue:\"#f0f8ff\",antiquewhite:\"#faebd7\",aqua:\"#00ffff\",aquamarine:\"#7fffd4\",azure:\"#f0ffff\",beige:\"#f5f5dc\",bisque:\"#ffe4c4\",black:\"#000000\",blanchedalmond:\"#ffebcd\",blue:\"#0000ff\",blueviolet:\"#8a2be2\",brown:\"#a52a2a\",burlywood:\"#deb887\",cadetblue:\"#5f9ea0\",chartreuse:\"#7fff00\",chocolate:\"#d2691e\",coral:\"#ff7f50\",cornflowerblue:\"#6495ed\",cornsilk:\"#fff8dc\",crimson:\"#dc143c\",cyan:\"#00ffff\",darkblue:\"#00008b\",darkcyan:\"#008b8b\",darkgoldenrod:\"#b8860b\",darkgray:\"#a9a9a9\",darkgreen:\"#006400\",darkgrey:\"#a9a9a9\",darkkhaki:\"#bdb76b\",darkmagenta:\"#8b008b\",darkolivegreen:\"#556b2f\",darkorange:\"#ff8c00\",darkorchid:\"#9932cc\",darkred:\"#8b0000\",darksalmon:\"#e9967a\",darkseagreen:\"#8fbc8f\",darkslateblue:\"#483d8b\",darkslategray:\"#2f4f4f\",darkslategrey:\"#2f4f4f\",darkturquoise:\"#00ced1\",darkviolet:\"#9400d3\",deeppink:\"#ff1493\",deepskyblue:\"#00bfff\",dimgray:\"#696969\",dimgrey:\"#696969\",dodgerblue:\"#1e90ff\",firebrick:\"#b22222\",floralwhite:\"#fffaf0\",forestgreen:\"#228b22\",fuchsia:\"#ff00ff\",gainsboro:\"#dcdcdc\",ghostwhite:\"#f8f8ff\",goldenrod:\"#daa520\",gold:\"#ffd700\",gray:\"#808080\",green:\"#008000\",greenyellow:\"#adff2f\",grey:\"#808080\",honeydew:\"#f0fff0\",hotpink:\"#ff69b4\",indianred:\"#cd5c5c\",indigo:\"#4b0082\",ivory:\"#fffff0\",khaki:\"#f0e68c\",lavenderblush:\"#fff0f5\",lavender:\"#e6e6fa\",lawngreen:\"#7cfc00\",lemonchiffon:\"#fffacd\",lightblue:\"#add8e6\",lightcoral:\"#f08080\",lightcyan:\"#e0ffff\",lightgoldenrodyellow:\"#fafad2\",lightgray:\"#d3d3d3\",lightgreen:\"#90ee90\",lightgrey:\"#d3d3d3\",lightpink:\"#ffb6c1\",lightsalmon:\"#ffa07a\",lightseagreen:\"#20b2aa\",lightskyblue:\"#87cefa\",lightslategray:\"#778899\",lightslategrey:\"#778899\",lightsteelblue:\"#b0c4de\",lightyellow:\"#ffffe0\",lime:\"#00ff00\",limegreen:\"#32cd32\",linen:\"#faf0e6\",magenta:\"#ff00ff\",maroon:\"#800000\",mediumaquamarine:\"#66cdaa\",mediumblue:\"#0000cd\",mediumorchid:\"#ba55d3\",mediumpurple:\"#9370db\",mediumseagreen:\"#3cb371\",mediumslateblue:\"#7b68ee\",mediumspringgreen:\"#00fa9a\",mediumturquoise:\"#48d1cc\",mediumvioletred:\"#c71585\",midnightblue:\"#191970\",mintcream:\"#f5fffa\",mistyrose:\"#ffe4e1\",moccasin:\"#ffe4b5\",navajowhite:\"#ffdead\",navy:\"#000080\",oldlace:\"#fdf5e6\",olive:\"#808000\",olivedrab:\"#6b8e23\",orange:\"#ffa500\",orangered:\"#ff4500\",orchid:\"#da70d6\",palegoldenrod:\"#eee8aa\",palegreen:\"#98fb98\",paleturquoise:\"#afeeee\",palevioletred:\"#db7093\",papayawhip:\"#ffefd5\",peachpuff:\"#ffdab9\",peru:\"#cd853f\",pink:\"#ffc0cb\",plum:\"#dda0dd\",powderblue:\"#b0e0e6\",purple:\"#800080\",rebeccapurple:\"#663399\",red:\"#ff0000\",rosybrown:\"#bc8f8f\",royalblue:\"#4169e1\",saddlebrown:\"#8b4513\",salmon:\"#fa8072\",sandybrown:\"#f4a460\",seagreen:\"#2e8b57\",seashell:\"#fff5ee\",sienna:\"#a0522d\",silver:\"#c0c0c0\",skyblue:\"#87ceeb\",slateblue:\"#6a5acd\",slategray:\"#708090\",slategrey:\"#708090\",snow:\"#fffafa\",springgreen:\"#00ff7f\",steelblue:\"#4682b4\",tan:\"#d2b48c\",teal:\"#008080\",thistle:\"#d8bfd8\",tomato:\"#ff6347\",turquoise:\"#40e0d0\",violet:\"#ee82ee\",wheat:\"#f5deb3\",white:\"#ffffff\",whitesmoke:\"#f5f5f5\",yellow:\"#ffff00\",yellowgreen:\"#9acd32\"};function iu(e){var t={r:0,g:0,b:0},n=1,r=null,a=null,o=null,i=!1,l=!1;return typeof e==\"string\"&&(e=vte(e)),typeof e==\"object\"&&(Yo(e.r)&&Yo(e.g)&&Yo(e.b)?(t=lte(e.r,e.g,e.b),i=!0,l=String(e.r).substr(-1)===\"%\"?\"prgb\":\"rgb\"):Yo(e.h)&&Yo(e.s)&&Yo(e.v)?(r=sh(e.s),a=sh(e.v),t=ute(e.h,r,a),i=!0,l=\"hsv\"):Yo(e.h)&&Yo(e.s)&&Yo(e.l)&&(r=sh(e.s),o=sh(e.l),t=ste(e.h,r,o),i=!0,l=\"hsl\"),Object.prototype.hasOwnProperty.call(e,\"a\")&&(n=e.a)),n=hM(n),{ok:i,format:e.format||l,r:Math.min(255,Math.max(t.r,0)),g:Math.min(255,Math.max(t.g,0)),b:Math.min(255,Math.max(t.b,0)),a:n}}var hte=\"[-\\\\+]?\\\\d+%?\",pte=\"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\",qi=\"(?:\".concat(pte,\")|(?:\").concat(hte,\")\"),sy=\"[\\\\s|\\\\(]+(\".concat(qi,\")[,|\\\\s]+(\").concat(qi,\")[,|\\\\s]+(\").concat(qi,\")\\\\s*\\\\)?\"),uy=\"[\\\\s|\\\\(]+(\".concat(qi,\")[,|\\\\s]+(\").concat(qi,\")[,|\\\\s]+(\").concat(qi,\")[,|\\\\s]+(\").concat(qi,\")\\\\s*\\\\)?\"),ja={CSS_UNIT:new RegExp(qi),rgb:new RegExp(\"rgb\"+sy),rgba:new RegExp(\"rgba\"+uy),hsl:new RegExp(\"hsl\"+sy),hsla:new RegExp(\"hsla\"+uy),hsv:new RegExp(\"hsv\"+sy),hsva:new RegExp(\"hsva\"+uy),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/};function vte(e){if(e=e.trim().toLowerCase(),e.length===0)return!1;var t=!1;if(C0[e])e=C0[e],t=!0;else if(e===\"transparent\")return{r:0,g:0,b:0,a:0,format:\"name\"};var n=ja.rgb.exec(e);return n?{r:n[1],g:n[2],b:n[3]}:(n=ja.rgba.exec(e),n?{r:n[1],g:n[2],b:n[3],a:n[4]}:(n=ja.hsl.exec(e),n?{h:n[1],s:n[2],l:n[3]}:(n=ja.hsla.exec(e),n?{h:n[1],s:n[2],l:n[3],a:n[4]}:(n=ja.hsv.exec(e),n?{h:n[1],s:n[2],v:n[3]}:(n=ja.hsva.exec(e),n?{h:n[1],s:n[2],v:n[3],a:n[4]}:(n=ja.hex8.exec(e),n?{r:ea(n[1]),g:ea(n[2]),b:ea(n[3]),a:S4(n[4]),format:t?\"name\":\"hex8\"}:(n=ja.hex6.exec(e),n?{r:ea(n[1]),g:ea(n[2]),b:ea(n[3]),format:t?\"name\":\"hex\"}:(n=ja.hex4.exec(e),n?{r:ea(n[1]+n[1]),g:ea(n[2]+n[2]),b:ea(n[3]+n[3]),a:S4(n[4]+n[4]),format:t?\"name\":\"hex8\"}:(n=ja.hex3.exec(e),n?{r:ea(n[1]+n[1]),g:ea(n[2]+n[2]),b:ea(n[3]+n[3]),format:t?\"name\":\"hex\"}:!1)))))))))}function Yo(e){return Boolean(ja.CSS_UNIT.exec(String(e)))}var pM=function(){function e(t,n){t===void 0&&(t=\"\"),n===void 0&&(n={});var r;if(t instanceof e)return t;typeof t==\"number\"&&(t=fte(t)),this.originalInput=t;var a=iu(t);this.originalInput=t,this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a,this.roundA=Math.round(100*this.a)/100,this.format=(r=n.format)!==null&&r!==void 0?r:a.format,this.gradientType=n.gradientType,this.r<1&&(this.r=Math.round(this.r)),this.g<1&&(this.g=Math.round(this.g)),this.b<1&&(this.b=Math.round(this.b)),this.isValid=a.ok}return e.prototype.isDark=function(){return this.getBrightness()<128},e.prototype.isLight=function(){return!this.isDark()},e.prototype.getBrightness=function(){var t=this.toRgb();return(t.r*299+t.g*587+t.b*114)/1e3},e.prototype.getLuminance=function(){var t=this.toRgb(),n,r,a,o=t.r/255,i=t.g/255,l=t.b/255;return o<=.03928?n=o/12.92:n=Math.pow((o+.055)/1.055,2.4),i<=.03928?r=i/12.92:r=Math.pow((i+.055)/1.055,2.4),l<=.03928?a=l/12.92:a=Math.pow((l+.055)/1.055,2.4),.2126*n+.7152*r+.0722*a},e.prototype.getAlpha=function(){return this.a},e.prototype.setAlpha=function(t){return this.a=hM(t),this.roundA=Math.round(100*this.a)/100,this},e.prototype.toHsv=function(){var t=y0(this.r,this.g,this.b);return{h:t.h*360,s:t.s,v:t.v,a:this.a}},e.prototype.toHsvString=function(){var t=y0(this.r,this.g,this.b),n=Math.round(t.h*360),r=Math.round(t.s*100),a=Math.round(t.v*100);return this.a===1?\"hsv(\".concat(n,\", \").concat(r,\"%, \").concat(a,\"%)\"):\"hsva(\".concat(n,\", \").concat(r,\"%, \").concat(a,\"%, \").concat(this.roundA,\")\")},e.prototype.toHsl=function(){var t=w4(this.r,this.g,this.b);return{h:t.h*360,s:t.s,l:t.l,a:this.a}},e.prototype.toHslString=function(){var t=w4(this.r,this.g,this.b),n=Math.round(t.h*360),r=Math.round(t.s*100),a=Math.round(t.l*100);return this.a===1?\"hsl(\".concat(n,\", \").concat(r,\"%, \").concat(a,\"%)\"):\"hsla(\".concat(n,\", \").concat(r,\"%, \").concat(a,\"%, \").concat(this.roundA,\")\")},e.prototype.toHex=function(t){return t===void 0&&(t=!1),b0(this.r,this.g,this.b,t)},e.prototype.toHexString=function(t){return t===void 0&&(t=!1),\"#\"+this.toHex(t)},e.prototype.toHex8=function(t){return t===void 0&&(t=!1),cte(this.r,this.g,this.b,this.a,t)},e.prototype.toHex8String=function(t){return t===void 0&&(t=!1),\"#\"+this.toHex8(t)},e.prototype.toRgb=function(){return{r:Math.round(this.r),g:Math.round(this.g),b:Math.round(this.b),a:this.a}},e.prototype.toRgbString=function(){var t=Math.round(this.r),n=Math.round(this.g),r=Math.round(this.b);return this.a===1?\"rgb(\".concat(t,\", \").concat(n,\", \").concat(r,\")\"):\"rgba(\".concat(t,\", \").concat(n,\", \").concat(r,\", \").concat(this.roundA,\")\")},e.prototype.toPercentageRgb=function(){var t=function(n){return\"\".concat(Math.round(br(n,255)*100),\"%\")};return{r:t(this.r),g:t(this.g),b:t(this.b),a:this.a}},e.prototype.toPercentageRgbString=function(){var t=function(n){return Math.round(br(n,255)*100)};return this.a===1?\"rgb(\".concat(t(this.r),\"%, \").concat(t(this.g),\"%, \").concat(t(this.b),\"%)\"):\"rgba(\".concat(t(this.r),\"%, \").concat(t(this.g),\"%, \").concat(t(this.b),\"%, \").concat(this.roundA,\")\")},e.prototype.toName=function(){if(this.a===0)return\"transparent\";if(this.a<1)return!1;for(var t=\"#\"+b0(this.r,this.g,this.b,!1),n=0,r=Object.entries(C0);n<r.length;n++){var a=r[n],o=a[0],i=a[1];if(t===i)return o}return!1},e.prototype.toString=function(t){var n=Boolean(t);t=t!=null?t:this.format;var r=!1,a=this.a<1&&this.a>=0,o=!n&&a&&(t.startsWith(\"hex\")||t===\"name\");return o?t===\"name\"&&this.a===0?this.toName():this.toRgbString():(t===\"rgb\"&&(r=this.toRgbString()),t===\"prgb\"&&(r=this.toPercentageRgbString()),(t===\"hex\"||t===\"hex6\")&&(r=this.toHexString()),t===\"hex3\"&&(r=this.toHexString(!0)),t===\"hex4\"&&(r=this.toHex8String(!0)),t===\"hex8\"&&(r=this.toHex8String()),t===\"name\"&&(r=this.toName()),t===\"hsl\"&&(r=this.toHslString()),t===\"hsv\"&&(r=this.toHsvString()),r||this.toHexString())},e.prototype.toNumber=function(){return(Math.round(this.r)<<16)+(Math.round(this.g)<<8)+Math.round(this.b)},e.prototype.clone=function(){return new e(this.toString())},e.prototype.lighten=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l+=t/100,n.l=lh(n.l),new e(n)},e.prototype.brighten=function(t){t===void 0&&(t=10);var n=this.toRgb();return n.r=Math.max(0,Math.min(255,n.r-Math.round(255*-(t/100)))),n.g=Math.max(0,Math.min(255,n.g-Math.round(255*-(t/100)))),n.b=Math.max(0,Math.min(255,n.b-Math.round(255*-(t/100)))),new e(n)},e.prototype.darken=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l-=t/100,n.l=lh(n.l),new e(n)},e.prototype.tint=function(t){return t===void 0&&(t=10),this.mix(\"white\",t)},e.prototype.shade=function(t){return t===void 0&&(t=10),this.mix(\"black\",t)},e.prototype.desaturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s-=t/100,n.s=lh(n.s),new e(n)},e.prototype.saturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s+=t/100,n.s=lh(n.s),new e(n)},e.prototype.greyscale=function(){return this.desaturate(100)},e.prototype.spin=function(t){var n=this.toHsl(),r=(n.h+t)%360;return n.h=r<0?360+r:r,new e(n)},e.prototype.mix=function(t,n){n===void 0&&(n=50);var r=this.toRgb(),a=new e(t).toRgb(),o=n/100,i={r:(a.r-r.r)*o+r.r,g:(a.g-r.g)*o+r.g,b:(a.b-r.b)*o+r.b,a:(a.a-r.a)*o+r.a};return new e(i)},e.prototype.analogous=function(t,n){t===void 0&&(t=6),n===void 0&&(n=30);var r=this.toHsl(),a=360/n,o=[this];for(r.h=(r.h-(a*t>>1)+720)%360;--t;)r.h=(r.h+a)%360,o.push(new e(r));return o},e.prototype.complement=function(){var t=this.toHsl();return t.h=(t.h+180)%360,new e(t)},e.prototype.monochromatic=function(t){t===void 0&&(t=6);for(var n=this.toHsv(),r=n.h,a=n.s,o=n.v,i=[],l=1/t;t--;)i.push(new e({h:r,s:a,v:o})),o=(o+l)%1;return i},e.prototype.splitcomplement=function(){var t=this.toHsl(),n=t.h;return[this,new e({h:(n+72)%360,s:t.s,l:t.l}),new e({h:(n+216)%360,s:t.s,l:t.l})]},e.prototype.onBackground=function(t){var n=this.toRgb(),r=new e(t).toRgb();return new e({r:r.r+(n.r-r.r)*n.a,g:r.g+(n.g-r.g)*n.a,b:r.b+(n.b-r.b)*n.a})},e.prototype.triad=function(){return this.polyad(3)},e.prototype.tetrad=function(){return this.polyad(4)},e.prototype.polyad=function(t){for(var n=this.toHsl(),r=n.h,a=[this],o=360/t,i=1;i<t;i++)a.push(new e({h:(r+i*o)%360,s:n.s,l:n.l}));return a},e.prototype.equals=function(t){return this.toRgbString()===new e(t).toRgbString()},e}();function Ri(e,t=20){return e.mix(\"#141414\",t).toString()}function mte(e){const t=Ms();return x(()=>{let n={};const r=e.color;if(r){const a=new pM(r),o=e.dark?a.tint(20).toString():Ri(a,20);if(e.plain)n={\"--el-button-bg-color\":e.dark?Ri(a,90):a.tint(90).toString(),\"--el-button-text-color\":r,\"--el-button-border-color\":e.dark?Ri(a,50):a.tint(50).toString(),\"--el-button-hover-text-color\":\"var(--el-color-white)\",\"--el-button-hover-bg-color\":r,\"--el-button-hover-border-color\":r,\"--el-button-active-bg-color\":o,\"--el-button-active-text-color\":\"var(--el-color-white)\",\"--el-button-active-border-color\":o},t.value&&(n[\"--el-button-disabled-bg-color\"]=e.dark?Ri(a,90):a.tint(90).toString(),n[\"--el-button-disabled-text-color\"]=e.dark?Ri(a,50):a.tint(50).toString(),n[\"--el-button-disabled-border-color\"]=e.dark?Ri(a,80):a.tint(80).toString());else{const i=e.dark?Ri(a,30):a.tint(30).toString(),l=a.isDark()?\"var(--el-color-white)\":\"var(--el-color-black)\";if(n={\"--el-button-bg-color\":r,\"--el-button-text-color\":l,\"--el-button-border-color\":r,\"--el-button-hover-bg-color\":i,\"--el-button-hover-text-color\":l,\"--el-button-hover-border-color\":i,\"--el-button-active-bg-color\":o,\"--el-button-active-border-color\":o},t.value){const s=e.dark?Ri(a,50):a.tint(50).toString();n[\"--el-button-disabled-bg-color\"]=s,n[\"--el-button-disabled-text-color\"]=e.dark?\"rgba(255, 255, 255, 0.5)\":\"var(--el-color-white)\",n[\"--el-button-disabled-border-color\"]=s}}}return n})}const gte=[\"disabled\",\"autofocus\",\"type\"],yte={name:\"ElButton\"},bte=G(Ke(Te({},yte),{props:g0,emits:ate,setup(e,{expose:t,emit:n}){const r=e,a=wf(),o=ve(wE,void 0),i=kc(\"button\"),l=De(\"button\"),{form:s}=$c(),c=Gn(x(()=>o==null?void 0:o.size)),d=Ms(),f=H(),p=x(()=>r.type||(o==null?void 0:o.type)||\"\"),v=x(()=>{var C,S,w;return(w=(S=r.autoInsertSpace)!=null?S:(C=i.value)==null?void 0:C.autoInsertSpace)!=null?w:!1}),m=x(()=>{var C;const S=(C=a.default)==null?void 0:C.call(a);if(v.value&&(S==null?void 0:S.length)===1){const w=S[0];if((w==null?void 0:w.type)===Fo){const k=w.children;return/^\\p{Unified_Ideograph}{2}$/u.test(k.trim())}}return!1}),y=mte(r),b=C=>{r.nativeType===\"reset\"&&(s==null||s.resetFields()),n(\"click\",C)};return t({ref:f,size:c,type:p,disabled:d,shouldAddSpace:m}),(C,S)=>(R(),X(\"button\",{ref_key:\"_ref\",ref:f,class:U([A(l).b(),A(l).m(A(p)),A(l).m(A(c)),A(l).is(\"disabled\",A(d)),A(l).is(\"loading\",C.loading),A(l).is(\"plain\",C.plain),A(l).is(\"round\",C.round),A(l).is(\"circle\",C.circle)]),disabled:A(d)||C.loading,autofocus:C.autofocus,type:C.nativeType,style:Xe(A(y)),onClick:b},[C.loading?(R(),X(Fe,{key:0},[C.$slots.loading?Oe(C.$slots,\"loading\",{key:0}):(R(),fe(A(ft),{key:1,class:U(A(l).is(\"loading\"))},{default:re(()=>[(R(),fe(Kt(C.loadingIcon)))]),_:1},8,[\"class\"]))],2112)):C.icon||C.$slots.icon?(R(),fe(A(ft),{key:1},{default:re(()=>[C.icon?(R(),fe(Kt(C.icon),{key:0})):Oe(C.$slots,\"icon\",{key:1})]),_:3})):se(\"v-if\",!0),C.$slots.default?(R(),X(\"span\",{key:2,class:U({[A(l).em(\"text\",\"expand\")]:A(m)})},[Oe(C.$slots,\"default\")],2)):se(\"v-if\",!0)],14,gte))}}));var Cte=Ae(bte,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/button/src/button.vue\"]]);const wte={size:g0.size,type:g0.type},Ste={name:\"ElButtonGroup\"},kte=G(Ke(Te({},Ste),{props:wte,setup(e){const t=e;ot(wE,bt({size:yn(t,\"size\"),type:yn(t,\"type\")}));const n=De(\"button\");return(r,a)=>(R(),X(\"div\",{class:U(`${A(n).b(\"group\")}`)},[Oe(r.$slots,\"default\")],2))}}));var vM=Ae(kte,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/button/src/button-group.vue\"]]);const xa=xt(Cte,{ButtonGroup:vM}),mM=En(vM);var vo=typeof globalThis!=\"undefined\"?globalThis:typeof window!=\"undefined\"?window:typeof global!=\"undefined\"?global:typeof self!=\"undefined\"?self:{},gM={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){var n=1e3,r=6e4,a=36e5,o=\"millisecond\",i=\"second\",l=\"minute\",s=\"hour\",c=\"day\",d=\"week\",f=\"month\",p=\"quarter\",v=\"year\",m=\"date\",y=\"Invalid Date\",b=/^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[Tt\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/,C=/\\[([^\\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,S={name:\"en\",weekdays:\"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday\".split(\"_\"),months:\"January_February_March_April_May_June_July_August_September_October_November_December\".split(\"_\")},w=function(N,D,z){var B=String(N);return!B||B.length>=D?N:\"\"+Array(D+1-B.length).join(z)+N},k={s:w,z:function(N){var D=-N.utcOffset(),z=Math.abs(D),B=Math.floor(z/60),M=z%60;return(D<=0?\"+\":\"-\")+w(B,2,\"0\")+\":\"+w(M,2,\"0\")},m:function N(D,z){if(D.date()<z.date())return-N(z,D);var B=12*(z.year()-D.year())+(z.month()-D.month()),M=D.clone().add(B,f),E=z-M<0,K=D.clone().add(B+(E?-1:1),f);return+(-(B+(z-M)/(E?M-K:K-M))||0)},a:function(N){return N<0?Math.ceil(N)||0:Math.floor(N)},p:function(N){return{M:f,y:v,w:d,d:c,D:m,h:s,m:l,s:i,ms:o,Q:p}[N]||String(N||\"\").toLowerCase().replace(/s$/,\"\")},u:function(N){return N===void 0}},$=\"en\",O={};O[$]=S;var T=function(N){return N instanceof j},_=function N(D,z,B){var M;if(!D)return $;if(typeof D==\"string\"){var E=D.toLowerCase();O[E]&&(M=E),z&&(O[E]=z,M=E);var K=D.split(\"-\");if(!M&&K.length>1)return N(K[0])}else{var W=D.name;O[W]=D,M=W}return!B&&M&&($=M),M||!B&&$},I=function(N,D){if(T(N))return N.clone();var z=typeof D==\"object\"?D:{};return z.date=N,z.args=arguments,new j(z)},L=k;L.l=_,L.i=T,L.w=function(N,D){return I(N,{locale:D.$L,utc:D.$u,x:D.$x,$offset:D.$offset})};var j=function(){function N(z){this.$L=_(z.locale,null,!0),this.parse(z)}var D=N.prototype;return D.parse=function(z){this.$d=function(B){var M=B.date,E=B.utc;if(M===null)return new Date(NaN);if(L.u(M))return new Date;if(M instanceof Date)return new Date(M);if(typeof M==\"string\"&&!/Z$/i.test(M)){var K=M.match(b);if(K){var W=K[2]-1||0,Y=(K[7]||\"0\").substring(0,3);return E?new Date(Date.UTC(K[1],W,K[3]||1,K[4]||0,K[5]||0,K[6]||0,Y)):new Date(K[1],W,K[3]||1,K[4]||0,K[5]||0,K[6]||0,Y)}}return new Date(M)}(z),this.$x=z.x||{},this.init()},D.init=function(){var z=this.$d;this.$y=z.getFullYear(),this.$M=z.getMonth(),this.$D=z.getDate(),this.$W=z.getDay(),this.$H=z.getHours(),this.$m=z.getMinutes(),this.$s=z.getSeconds(),this.$ms=z.getMilliseconds()},D.$utils=function(){return L},D.isValid=function(){return this.$d.toString()!==y},D.isSame=function(z,B){var M=I(z);return this.startOf(B)<=M&&M<=this.endOf(B)},D.isAfter=function(z,B){return I(z)<this.startOf(B)},D.isBefore=function(z,B){return this.endOf(B)<I(z)},D.$g=function(z,B,M){return L.u(z)?this[B]:this.set(M,z)},D.unix=function(){return Math.floor(this.valueOf()/1e3)},D.valueOf=function(){return this.$d.getTime()},D.startOf=function(z,B){var M=this,E=!!L.u(B)||B,K=L.p(z),W=function(de,be){var Ee=L.w(M.$u?Date.UTC(M.$y,be,de):new Date(M.$y,be,de),M);return E?Ee:Ee.endOf(c)},Y=function(de,be){return L.w(M.toDate()[de].apply(M.toDate(\"s\"),(E?[0,0,0,0]:[23,59,59,999]).slice(be)),M)},q=this.$W,J=this.$M,ne=this.$D,oe=\"set\"+(this.$u?\"UTC\":\"\");switch(K){case v:return E?W(1,0):W(31,11);case f:return E?W(1,J):W(0,J+1);case d:var Q=this.$locale().weekStart||0,ae=(q<Q?q+7:q)-Q;return W(E?ne-ae:ne+(6-ae),J);case c:case m:return Y(oe+\"Hours\",0);case s:return Y(oe+\"Minutes\",1);case l:return Y(oe+\"Seconds\",2);case i:return Y(oe+\"Milliseconds\",3);default:return this.clone()}},D.endOf=function(z){return this.startOf(z,!1)},D.$set=function(z,B){var M,E=L.p(z),K=\"set\"+(this.$u?\"UTC\":\"\"),W=(M={},M[c]=K+\"Date\",M[m]=K+\"Date\",M[f]=K+\"Month\",M[v]=K+\"FullYear\",M[s]=K+\"Hours\",M[l]=K+\"Minutes\",M[i]=K+\"Seconds\",M[o]=K+\"Milliseconds\",M)[E],Y=E===c?this.$D+(B-this.$W):B;if(E===f||E===v){var q=this.clone().set(m,1);q.$d[W](Y),q.init(),this.$d=q.set(m,Math.min(this.$D,q.daysInMonth())).$d}else W&&this.$d[W](Y);return this.init(),this},D.set=function(z,B){return this.clone().$set(z,B)},D.get=function(z){return this[L.p(z)]()},D.add=function(z,B){var M,E=this;z=Number(z);var K=L.p(B),W=function(J){var ne=I(E);return L.w(ne.date(ne.date()+Math.round(J*z)),E)};if(K===f)return this.set(f,this.$M+z);if(K===v)return this.set(v,this.$y+z);if(K===c)return W(1);if(K===d)return W(7);var Y=(M={},M[l]=r,M[s]=a,M[i]=n,M)[K]||1,q=this.$d.getTime()+z*Y;return L.w(q,this)},D.subtract=function(z,B){return this.add(-1*z,B)},D.format=function(z){var B=this,M=this.$locale();if(!this.isValid())return M.invalidDate||y;var E=z||\"YYYY-MM-DDTHH:mm:ssZ\",K=L.z(this),W=this.$H,Y=this.$m,q=this.$M,J=M.weekdays,ne=M.months,oe=function(be,Ee,Pe,Be){return be&&(be[Ee]||be(B,E))||Pe[Ee].substr(0,Be)},Q=function(be){return L.s(W%12||12,be,\"0\")},ae=M.meridiem||function(be,Ee,Pe){var Be=be<12?\"AM\":\"PM\";return Pe?Be.toLowerCase():Be},de={YY:String(this.$y).slice(-2),YYYY:this.$y,M:q+1,MM:L.s(q+1,2,\"0\"),MMM:oe(M.monthsShort,q,ne,3),MMMM:oe(ne,q),D:this.$D,DD:L.s(this.$D,2,\"0\"),d:String(this.$W),dd:oe(M.weekdaysMin,this.$W,J,2),ddd:oe(M.weekdaysShort,this.$W,J,3),dddd:J[this.$W],H:String(W),HH:L.s(W,2,\"0\"),h:Q(1),hh:Q(2),a:ae(W,Y,!0),A:ae(W,Y,!1),m:String(Y),mm:L.s(Y,2,\"0\"),s:String(this.$s),ss:L.s(this.$s,2,\"0\"),SSS:L.s(this.$ms,3,\"0\"),Z:K};return E.replace(C,function(be,Ee){return Ee||de[be]||K.replace(\":\",\"\")})},D.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},D.diff=function(z,B,M){var E,K=L.p(B),W=I(z),Y=(W.utcOffset()-this.utcOffset())*r,q=this-W,J=L.m(this,W);return J=(E={},E[v]=J/12,E[f]=J,E[p]=J/3,E[d]=(q-Y)/6048e5,E[c]=(q-Y)/864e5,E[s]=q/a,E[l]=q/r,E[i]=q/n,E)[K]||q,M?J:L.a(J)},D.daysInMonth=function(){return this.endOf(f).$D},D.$locale=function(){return O[this.$L]},D.locale=function(z,B){if(!z)return this.$L;var M=this.clone(),E=_(z,B,!0);return E&&(M.$L=E),M},D.clone=function(){return L.w(this.$d,this)},D.toDate=function(){return new Date(this.valueOf())},D.toJSON=function(){return this.isValid()?this.toISOString():null},D.toISOString=function(){return this.$d.toISOString()},D.toString=function(){return this.$d.toUTCString()},N}(),F=j.prototype;return I.prototype=F,[[\"$ms\",o],[\"$s\",i],[\"$m\",l],[\"$H\",s],[\"$W\",c],[\"$M\",f],[\"$y\",v],[\"$D\",m]].forEach(function(N){F[N[1]]=function(D){return this.$g(D,N[0],N[1])}}),I.extend=function(N,D){return N.$i||(N(D,j,I),N.$i=!0),I},I.locale=_,I.isDayjs=T,I.unix=function(N){return I(1e3*N)},I.en=O[$],I.Ls=O,I.p={},I})})(gM);var mt=gM.exports,yM={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r,a){var o=r.prototype,i=function(f){return f&&(f.indexOf?f:f.s)},l=function(f,p,v,m,y){var b=f.name?f:f.$locale(),C=i(b[p]),S=i(b[v]),w=C||S.map(function($){return $.substr(0,m)});if(!y)return w;var k=b.weekStart;return w.map(function($,O){return w[(O+(k||0))%7]})},s=function(){return a.Ls[a.locale()]},c=function(f,p){return f.formats[p]||function(v){return v.replace(/(\\[[^\\]]+])|(MMMM|MM|DD|dddd)/g,function(m,y,b){return y||b.slice(1)})}(f.formats[p.toUpperCase()])},d=function(){var f=this;return{months:function(p){return p?p.format(\"MMMM\"):l(f,\"months\")},monthsShort:function(p){return p?p.format(\"MMM\"):l(f,\"monthsShort\",\"months\",3)},firstDayOfWeek:function(){return f.$locale().weekStart||0},weekdays:function(p){return p?p.format(\"dddd\"):l(f,\"weekdays\")},weekdaysMin:function(p){return p?p.format(\"dd\"):l(f,\"weekdaysMin\",\"weekdays\",2)},weekdaysShort:function(p){return p?p.format(\"ddd\"):l(f,\"weekdaysShort\",\"weekdays\",3)},longDateFormat:function(p){return c(f.$locale(),p)},meridiem:this.$locale().meridiem,ordinal:this.$locale().ordinal}};o.localeData=function(){return d.bind(this)()},a.localeData=function(){var f=s();return{firstDayOfWeek:function(){return f.weekStart||0},weekdays:function(){return a.weekdays()},weekdaysShort:function(){return a.weekdaysShort()},weekdaysMin:function(){return a.weekdaysMin()},months:function(){return a.months()},monthsShort:function(){return a.monthsShort()},longDateFormat:function(p){return c(f,p)},meridiem:f.meridiem,ordinal:f.ordinal}},a.months=function(){return l(s(),\"months\")},a.monthsShort=function(){return l(s(),\"monthsShort\",\"months\",3)},a.weekdays=function(f){return l(s(),\"weekdays\",null,null,f)},a.weekdaysShort=function(f){return l(s(),\"weekdaysShort\",\"weekdays\",3,f)},a.weekdaysMin=function(f){return l(s(),\"weekdaysMin\",\"weekdays\",2,f)}}})})(yM);var bM=yM.exports,CM={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){var n={LTS:\"h:mm:ss A\",LT:\"h:mm A\",L:\"MM/DD/YYYY\",LL:\"MMMM D, YYYY\",LLL:\"MMMM D, YYYY h:mm A\",LLLL:\"dddd, MMMM D, YYYY h:mm A\"},r=/(\\[[^[]*\\])|([-:/.()\\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,a=/\\d\\d/,o=/\\d\\d?/,i=/\\d*[^\\s\\d-_:/()]+/,l={},s=function(y){return(y=+y)+(y>68?1900:2e3)},c=function(y){return function(b){this[y]=+b}},d=[/[+-]\\d\\d:?(\\d\\d)?|Z/,function(y){(this.zone||(this.zone={})).offset=function(b){if(!b||b===\"Z\")return 0;var C=b.match(/([+-]|\\d\\d)/g),S=60*C[1]+(+C[2]||0);return S===0?0:C[0]===\"+\"?-S:S}(y)}],f=function(y){var b=l[y];return b&&(b.indexOf?b:b.s.concat(b.f))},p=function(y,b){var C,S=l.meridiem;if(S){for(var w=1;w<=24;w+=1)if(y.indexOf(S(w,0,b))>-1){C=w>12;break}}else C=y===(b?\"pm\":\"PM\");return C},v={A:[i,function(y){this.afternoon=p(y,!1)}],a:[i,function(y){this.afternoon=p(y,!0)}],S:[/\\d/,function(y){this.milliseconds=100*+y}],SS:[a,function(y){this.milliseconds=10*+y}],SSS:[/\\d{3}/,function(y){this.milliseconds=+y}],s:[o,c(\"seconds\")],ss:[o,c(\"seconds\")],m:[o,c(\"minutes\")],mm:[o,c(\"minutes\")],H:[o,c(\"hours\")],h:[o,c(\"hours\")],HH:[o,c(\"hours\")],hh:[o,c(\"hours\")],D:[o,c(\"day\")],DD:[a,c(\"day\")],Do:[i,function(y){var b=l.ordinal,C=y.match(/\\d+/);if(this.day=C[0],b)for(var S=1;S<=31;S+=1)b(S).replace(/\\[|\\]/g,\"\")===y&&(this.day=S)}],M:[o,c(\"month\")],MM:[a,c(\"month\")],MMM:[i,function(y){var b=f(\"months\"),C=(f(\"monthsShort\")||b.map(function(S){return S.substr(0,3)})).indexOf(y)+1;if(C<1)throw new Error;this.month=C%12||C}],MMMM:[i,function(y){var b=f(\"months\").indexOf(y)+1;if(b<1)throw new Error;this.month=b%12||b}],Y:[/[+-]?\\d+/,c(\"year\")],YY:[a,function(y){this.year=s(y)}],YYYY:[/\\d{4}/,c(\"year\")],Z:d,ZZ:d};function m(y){var b,C;b=y,C=l&&l.formats;for(var S=(y=b.replace(/(\\[[^\\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(I,L,j){var F=j&&j.toUpperCase();return L||C[j]||n[j]||C[F].replace(/(\\[[^\\]]+])|(MMMM|MM|DD|dddd)/g,function(N,D,z){return D||z.slice(1)})})).match(r),w=S.length,k=0;k<w;k+=1){var $=S[k],O=v[$],T=O&&O[0],_=O&&O[1];S[k]=_?{regex:T,parser:_}:$.replace(/^\\[|\\]$/g,\"\")}return function(I){for(var L={},j=0,F=0;j<w;j+=1){var N=S[j];if(typeof N==\"string\")F+=N.length;else{var D=N.regex,z=N.parser,B=I.substr(F),M=D.exec(B)[0];z.call(L,M),I=I.replace(M,\"\")}}return function(E){var K=E.afternoon;if(K!==void 0){var W=E.hours;K?W<12&&(E.hours+=12):W===12&&(E.hours=0),delete E.afternoon}}(L),L}}return function(y,b,C){C.p.customParseFormat=!0,y&&y.parseTwoDigitYear&&(s=y.parseTwoDigitYear);var S=b.prototype,w=S.parse;S.parse=function(k){var $=k.date,O=k.utc,T=k.args;this.$u=O;var _=T[1];if(typeof _==\"string\"){var I=T[2]===!0,L=T[3]===!0,j=I||L,F=T[2];L&&(F=T[2]),l=this.$locale(),!I&&F&&(l=C.Ls[F]),this.$d=function(B,M,E){try{if([\"x\",\"X\"].indexOf(M)>-1)return new Date((M===\"X\"?1e3:1)*B);var K=m(M)(B),W=K.year,Y=K.month,q=K.day,J=K.hours,ne=K.minutes,oe=K.seconds,Q=K.milliseconds,ae=K.zone,de=new Date,be=q||(W||Y?1:de.getDate()),Ee=W||de.getFullYear(),Pe=0;W&&!Y||(Pe=Y>0?Y-1:de.getMonth());var Be=J||0,te=ne||0,ie=oe||0,ge=Q||0;return ae?new Date(Date.UTC(Ee,Pe,be,Be,te,ie,ge+60*ae.offset*1e3)):E?new Date(Date.UTC(Ee,Pe,be,Be,te,ie,ge)):new Date(Ee,Pe,be,Be,te,ie,ge)}catch{return new Date(\"\")}}($,_,O),this.init(),F&&F!==!0&&(this.$L=this.locale(F).$L),j&&$!=this.format(_)&&(this.$d=new Date(\"\")),l={}}else if(_ instanceof Array)for(var N=_.length,D=1;D<=N;D+=1){T[1]=_[D-1];var z=C.apply(this,T);if(z.isValid()){this.$d=z.$d,this.$L=z.$L,this.init();break}D===N&&(this.$d=new Date(\"\"))}else w.call(this,k)}}})})(CM);var tw=CM.exports;const w0=\"HH:mm:ss\",td=\"YYYY-MM-DD\",$te={date:td,week:\"gggg[w]ww\",year:\"YYYY\",month:\"YYYY-MM\",datetime:`${td} ${w0}`,monthrange:\"YYYY-MM\",daterange:td,datetimerange:`${td} ${w0}`},nw={id:{type:[Array,String]},name:{type:[Array,String],default:\"\"},popperClass:{type:String,default:\"\"},format:{type:String},valueFormat:{type:String},type:{type:String,default:\"\"},clearable:{type:Boolean,default:!0},clearIcon:{type:[String,Object],default:gi},editable:{type:Boolean,default:!0},prefixIcon:{type:[String,Object],default:\"\"},size:{type:String,validator:va},readonly:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},placeholder:{type:String,default:\"\"},popperOptions:{type:Object,default:()=>({})},modelValue:{type:[Date,Array,String,Number],default:\"\"},rangeSeparator:{type:String,default:\"-\"},startPlaceholder:String,endPlaceholder:String,defaultValue:{type:[Date,Array]},defaultTime:{type:[Date,Array]},isRange:{type:Boolean,default:!1},disabledHours:{type:Function},disabledMinutes:{type:Function},disabledSeconds:{type:Function},disabledDate:{type:Function},cellClassName:{type:Function},shortcuts:{type:Array,default:()=>[]},arrowControl:{type:Boolean,default:!1},validateEvent:{type:Boolean,default:!0},unlinkPanels:Boolean},k4=function(e,t){const n=e instanceof Date,r=t instanceof Date;return n&&r?e.getTime()===t.getTime():!n&&!r?e===t:!1},$4=function(e,t){const n=Array.isArray(e),r=Array.isArray(t);return n&&r?e.length!==t.length?!1:e.every((a,o)=>k4(a,t[o])):!n&&!r?k4(e,t):!1},O4=function(e,t,n){const r=Kd(t)||t===\"x\"?mt(e).locale(n):mt(e,t).locale(n);return r.isValid()?r:void 0},P4=function(e,t,n){return Kd(t)?e:t===\"x\"?+e:mt(e).locale(n).format(t)},Ote=G({name:\"Picker\",components:{ElInput:Ra,ElTooltip:Ur,ElIcon:ft},props:nw,emits:[\"update:modelValue\",\"change\",\"focus\",\"blur\",\"calendar-change\",\"panel-change\",\"visible-change\"],setup(e,t){const{lang:n}=ln(),r=De(\"date\"),a=De(\"input\"),o=De(\"range\"),i=ve(ga,{}),l=ve(Ia,{}),s=ve(\"ElPopperOptions\",{}),c=H(),d=H(),f=H(!1),p=H(!1),v=H(null);ce(f,ee=>{var me;ee?v.value=e.modelValue:(de.value=null,Ne(()=>{m(e.modelValue)}),t.emit(\"blur\"),Ee(),e.validateEvent&&((me=l.validate)==null||me.call(l,\"blur\").catch(He=>void 0)))});const m=(ee,me)=>{var He;(me||!$4(ee,v.value))&&(t.emit(\"change\",ee),e.validateEvent&&((He=l.validate)==null||He.call(l,\"change\").catch(lt=>void 0)))},y=ee=>{if(!$4(e.modelValue,ee)){let me;Array.isArray(ee)?me=ee.map(He=>P4(He,e.valueFormat,n.value)):ee&&(me=P4(ee,e.valueFormat,n.value)),t.emit(\"update:modelValue\",ee&&me,n.value)}},b=x(()=>{if(d.value){const ee=J.value?d.value:d.value.$el;return Array.from(ee.querySelectorAll(\"input\"))}return[]}),C=x(()=>b==null?void 0:b.value[0]),S=x(()=>b==null?void 0:b.value[1]),w=(ee,me,He)=>{const lt=b.value;!lt.length||(!He||He===\"min\"?(lt[0].setSelectionRange(ee,me),lt[0].focus()):He===\"max\"&&(lt[1].setSelectionRange(ee,me),lt[1].focus()))},k=(ee=\"\",me=!1)=>{f.value=me;let He;Array.isArray(ee)?He=ee.map(lt=>lt.toDate()):He=ee&&ee.toDate(),de.value=null,y(He)},$=()=>{p.value=!0},O=()=>{t.emit(\"visible-change\",!0)},T=()=>{p.value=!1,t.emit(\"visible-change\",!1)},_=(ee=!0)=>{let me=C.value;!ee&&J.value&&(me=S.value),me&&me.focus()},I=ee=>{e.readonly||j.value||f.value||(f.value=!0,t.emit(\"focus\",ee))},L=()=>{var ee;(ee=c.value)==null||ee.onClose(),Ee()},j=x(()=>e.disabled||i.disabled),F=x(()=>{let ee;if(W.value?pe.value.getDefaultValue&&(ee=pe.value.getDefaultValue()):Array.isArray(e.modelValue)?ee=e.modelValue.map(me=>O4(me,e.valueFormat,n.value)):ee=O4(e.modelValue,e.valueFormat,n.value),pe.value.getRangeAvailableTime){const me=pe.value.getRangeAvailableTime(ee);er(me,ee)||(ee=me,y(Array.isArray(ee)?ee.map(He=>He.toDate()):ee.toDate()))}return Array.isArray(ee)&&ee.some(me=>!me)&&(ee=[]),ee}),N=x(()=>{if(!pe.value.panelReady)return;const ee=Be(F.value);if(Array.isArray(de.value))return[de.value[0]||ee&&ee[0]||\"\",de.value[1]||ee&&ee[1]||\"\"];if(de.value!==null)return de.value;if(!(!z.value&&W.value)&&!(!f.value&&W.value))return ee?B.value?ee.join(\", \"):ee:\"\"}),D=x(()=>e.type.includes(\"time\")),z=x(()=>e.type.startsWith(\"time\")),B=x(()=>e.type===\"dates\"),M=x(()=>e.prefixIcon||(D.value?uE:fY)),E=H(!1),K=ee=>{e.readonly||j.value||E.value&&(ee.stopPropagation(),y(null),m(null,!0),E.value=!1,f.value=!1,pe.value.handleClear&&pe.value.handleClear())},W=x(()=>!e.modelValue||Array.isArray(e.modelValue)&&!e.modelValue.length),Y=()=>{e.readonly||j.value||!W.value&&e.clearable&&(E.value=!0)},q=()=>{E.value=!1},J=x(()=>e.type.includes(\"range\")),ne=Gn(),oe=x(()=>{var ee,me;return(me=(ee=c.value)==null?void 0:ee.popperRef)==null?void 0:me.contentRef}),Q=x(()=>{var ee,me;return(me=(ee=A(c))==null?void 0:ee.popperRef)==null?void 0:me.contentRef}),ae=x(()=>{var ee;return A(J)?A(d):(ee=A(d))==null?void 0:ee.$el});vv(ae,ee=>{const me=A(Q),He=A(ae);me&&(ee.target===me||ee.composedPath().includes(me))||ee.target===He||ee.composedPath().includes(He)||(f.value=!1)});const de=H(null),be=()=>{if(de.value){const ee=Pe(N.value);ee&&te(ee)&&(y(Array.isArray(ee)?ee.map(me=>me.toDate()):ee.toDate()),de.value=null)}de.value===\"\"&&(y(null),m(null),de.value=null)},Ee=()=>{b.value.forEach(ee=>ee.blur())},Pe=ee=>ee?pe.value.parseUserInput(ee):null,Be=ee=>ee?pe.value.formatToString(ee):null,te=ee=>pe.value.isValidValue(ee),ie=ee=>{const me=ee.code;if(me===Ge.esc){f.value=!1,ee.stopPropagation();return}if(me===Ge.tab){J.value?setTimeout(()=>{b.value.includes(document.activeElement)||(f.value=!1,Ee())},0):(be(),f.value=!1,ee.stopPropagation());return}if(me===Ge.enter||me===Ge.numpadEnter){(de.value===null||de.value===\"\"||te(Pe(N.value)))&&(be(),f.value=!1),ee.stopPropagation();return}if(de.value){ee.stopPropagation();return}pe.value.handleKeydown&&pe.value.handleKeydown(ee)},ge=ee=>{de.value=ee},ke=ee=>{de.value?de.value=[ee.target.value,de.value[1]]:de.value=[ee.target.value,null]},xe=ee=>{de.value?de.value=[de.value[0],ee.target.value]:de.value=[null,ee.target.value]},Ie=()=>{const ee=Pe(de.value&&de.value[0]);if(ee&&ee.isValid()){de.value=[Be(ee),N.value[1]];const me=[ee,F.value&&F.value[1]];te(me)&&(y(me),de.value=null)}},ye=()=>{const ee=Pe(de.value&&de.value[1]);if(ee&&ee.isValid()){de.value=[N.value[0],Be(ee)];const me=[F.value&&F.value[0],ee];te(me)&&(y(me),de.value=null)}},pe=H({}),ue=ee=>{pe.value[ee[0]]=ee[1],pe.value.panelReady=!0},Ce=ee=>{t.emit(\"calendar-change\",ee)},je=(ee,me,He)=>{t.emit(\"panel-change\",ee,me,He)};return ot(\"EP_PICKER_BASE\",{props:e}),{nsDate:r,nsInput:a,nsRange:o,elPopperOptions:s,isDatesPicker:B,handleEndChange:ye,handleStartChange:Ie,handleStartInput:ke,handleEndInput:xe,onUserInput:ge,handleChange:be,handleKeydown:ie,popperPaneRef:oe,onClickOutside:vv,pickerSize:ne,isRangeInput:J,onMouseLeave:q,onMouseEnter:Y,onClearIconClick:K,showClose:E,triggerIcon:M,onPick:k,handleFocus:I,handleBlur:L,pickerVisible:f,pickerActualVisible:p,displayValue:N,parsedValue:F,setSelectionRange:w,refPopper:c,inputRef:d,pickerDisabled:j,onSetPickerOption:ue,onCalendarChange:Ce,onPanelChange:je,focus:_,onShow:O,onBeforeShow:$,onHide:T}}}),Pte=[\"id\",\"name\",\"placeholder\",\"value\",\"disabled\",\"readonly\"],Tte=[\"id\",\"name\",\"placeholder\",\"value\",\"disabled\",\"readonly\"];function xte(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"el-input\"),s=we(\"el-tooltip\");return R(),fe(s,hn({ref:\"refPopper\",visible:e.pickerVisible,\"onUpdate:visible\":t[17]||(t[17]=c=>e.pickerVisible=c),effect:\"light\",pure:\"\",trigger:\"click\"},e.$attrs,{\"append-to-body\":\"\",transition:`${e.nsDate.namespace.value}-zoom-in-top`,\"popper-class\":[`${e.nsDate.namespace.value}-picker__popper`,e.popperClass],\"popper-options\":e.elPopperOptions,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],\"gpu-acceleration\":!1,\"stop-popper-mouse-event\":!1,\"hide-after\":0,persistent:\"\",onBeforeShow:e.onBeforeShow,onShow:e.onShow,onHide:e.onHide}),{default:re(()=>[e.isRangeInput?(R(),X(\"div\",{key:1,ref:\"inputRef\",class:U([e.nsDate.b(\"editor\"),e.nsDate.bm(\"editor\",e.type),e.nsInput.e(\"inner\"),e.nsDate.is(\"disabled\",e.pickerDisabled),e.nsDate.is(\"active\",e.pickerVisible),e.nsRange.b(\"editor\"),e.pickerSize?e.nsRange.bm(\"editor\",e.pickerSize):\"\",e.$attrs.class]),style:Xe(e.$attrs.style),onClick:t[7]||(t[7]=(...c)=>e.handleFocus&&e.handleFocus(...c)),onMouseenter:t[8]||(t[8]=(...c)=>e.onMouseEnter&&e.onMouseEnter(...c)),onMouseleave:t[9]||(t[9]=(...c)=>e.onMouseLeave&&e.onMouseLeave(...c)),onKeydown:t[10]||(t[10]=(...c)=>e.handleKeydown&&e.handleKeydown(...c))},[e.triggerIcon?(R(),fe(i,{key:0,class:U([e.nsInput.e(\"icon\"),e.nsRange.e(\"icon\")]),onClick:e.handleFocus},{default:re(()=>[(R(),fe(Kt(e.triggerIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0),Z(\"input\",{id:e.id&&e.id[0],autocomplete:\"off\",name:e.name&&e.name[0],placeholder:e.startPlaceholder,value:e.displayValue&&e.displayValue[0],disabled:e.pickerDisabled,readonly:!e.editable||e.readonly,class:U(e.nsRange.b(\"input\")),onInput:t[1]||(t[1]=(...c)=>e.handleStartInput&&e.handleStartInput(...c)),onChange:t[2]||(t[2]=(...c)=>e.handleStartChange&&e.handleStartChange(...c)),onFocus:t[3]||(t[3]=(...c)=>e.handleFocus&&e.handleFocus(...c))},null,42,Pte),Oe(e.$slots,\"range-separator\",{},()=>[Z(\"span\",{class:U(e.nsRange.b(\"separator\"))},Me(e.rangeSeparator),3)]),Z(\"input\",{id:e.id&&e.id[1],autocomplete:\"off\",name:e.name&&e.name[1],placeholder:e.endPlaceholder,value:e.displayValue&&e.displayValue[1],disabled:e.pickerDisabled,readonly:!e.editable||e.readonly,class:U(e.nsRange.b(\"input\")),onFocus:t[4]||(t[4]=(...c)=>e.handleFocus&&e.handleFocus(...c)),onInput:t[5]||(t[5]=(...c)=>e.handleEndInput&&e.handleEndInput(...c)),onChange:t[6]||(t[6]=(...c)=>e.handleEndChange&&e.handleEndChange(...c))},null,42,Tte),e.clearIcon?(R(),fe(i,{key:1,class:U([e.nsInput.e(\"icon\"),e.nsRange.e(\"close-icon\"),{[e.nsRange.e(\"close-icon--hidden\")]:!e.showClose}]),onClick:e.onClearIconClick},{default:re(()=>[(R(),fe(Kt(e.clearIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)],38)):(R(),fe(l,{key:0,id:e.id,ref:\"inputRef\",\"model-value\":e.displayValue,name:e.name,size:e.pickerSize,disabled:e.pickerDisabled,placeholder:e.placeholder,class:U([e.nsDate.b(\"editor\"),e.nsDate.bm(\"editor\",e.type),e.$attrs.class]),style:Xe(e.$attrs.style),readonly:!e.editable||e.readonly||e.isDatesPicker||e.type===\"week\",onInput:e.onUserInput,onFocus:e.handleFocus,onKeydown:e.handleKeydown,onChange:e.handleChange,onMouseenter:e.onMouseEnter,onMouseleave:e.onMouseLeave,onClick:t[0]||(t[0]=dt(()=>{},[\"stop\"]))},{prefix:re(()=>[e.triggerIcon?(R(),fe(i,{key:0,class:U(e.nsInput.e(\"icon\")),onClick:e.handleFocus},{default:re(()=>[(R(),fe(Kt(e.triggerIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)]),suffix:re(()=>[e.showClose&&e.clearIcon?(R(),fe(i,{key:0,class:U(`${e.nsInput.e(\"icon\")} clear-icon`),onClick:e.onClearIconClick},{default:re(()=>[(R(),fe(Kt(e.clearIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)]),_:1},8,[\"id\",\"model-value\",\"name\",\"size\",\"disabled\",\"placeholder\",\"class\",\"style\",\"readonly\",\"onInput\",\"onFocus\",\"onKeydown\",\"onChange\",\"onMouseenter\",\"onMouseleave\"]))]),content:re(()=>[Oe(e.$slots,\"default\",{visible:e.pickerVisible,actualVisible:e.pickerActualVisible,parsedValue:e.parsedValue,format:e.format,unlinkPanels:e.unlinkPanels,type:e.type,defaultValue:e.defaultValue,onPick:t[11]||(t[11]=(...c)=>e.onPick&&e.onPick(...c)),onSelectRange:t[12]||(t[12]=(...c)=>e.setSelectionRange&&e.setSelectionRange(...c)),onSetPickerOption:t[13]||(t[13]=(...c)=>e.onSetPickerOption&&e.onSetPickerOption(...c)),onCalendarChange:t[14]||(t[14]=(...c)=>e.onCalendarChange&&e.onCalendarChange(...c)),onPanelChange:t[15]||(t[15]=(...c)=>e.onPanelChange&&e.onPanelChange(...c)),onMousedown:t[16]||(t[16]=dt(()=>{},[\"stop\"]))})]),_:3},16,[\"visible\",\"transition\",\"popper-class\",\"popper-options\",\"onBeforeShow\",\"onShow\",\"onHide\"])}var wM=Ae(Ote,[[\"render\",xte],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/time-picker/src/common/picker.vue\"]]);const Vi=new Map;let T4;Bt&&(document.addEventListener(\"mousedown\",e=>T4=e),document.addEventListener(\"mouseup\",e=>{for(const t of Vi.values())for(const{documentHandler:n}of t)n(e,T4)}));function x4(e,t){let n=[];return Array.isArray(t.arg)?n=t.arg:ys(t.arg)&&n.push(t.arg),function(r,a){const o=t.instance.popperRef,i=r.target,l=a==null?void 0:a.target,s=!t||!t.instance,c=!i||!l,d=e.contains(i)||e.contains(l),f=e===i,p=n.length&&n.some(m=>m==null?void 0:m.contains(i))||n.length&&n.includes(l),v=o&&(o.contains(i)||o.contains(l));s||c||d||f||p||v||t.value(r,a)}}const Is={beforeMount(e,t){Vi.has(e)||Vi.set(e,[]),Vi.get(e).push({documentHandler:x4(e,t),bindingFn:t.value})},updated(e,t){Vi.has(e)||Vi.set(e,[]);const n=Vi.get(e),r=n.findIndex(o=>o.bindingFn===t.oldValue),a={documentHandler:x4(e,t),bindingFn:t.value};r>=0?n.splice(r,1,a):n.push(a)},unmounted(e){Vi.delete(e)}};var SM={beforeMount(e,t){let n=null,r;const a=()=>t.value&&t.value(),o=()=>{Date.now()-r<100&&a(),clearInterval(n),n=null};gn(e,\"mousedown\",i=>{i.button===0&&(r=Date.now(),oU(document,\"mouseup\",o),clearInterval(n),n=setInterval(a,100))})}};const S0=\"_trap-focus-children\",Yl=[],_4=e=>{if(Yl.length===0)return;const t=Yl[Yl.length-1][S0];if(t.length>0&&e.code===Ge.tab){if(t.length===1){e.preventDefault(),document.activeElement!==t[0]&&t[0].focus();return}const n=e.shiftKey,r=e.target===t[0],a=e.target===t[t.length-1];r&&n&&(e.preventDefault(),t[t.length-1].focus()),a&&!n&&(e.preventDefault(),t[0].focus())}},kM={beforeMount(e){e[S0]=V$(e),Yl.push(e),Yl.length<=1&&gn(document,\"keydown\",_4)},updated(e){Ne(()=>{e[S0]=V$(e)})},unmounted(){Yl.shift(),Yl.length===0&&Bn(document,\"keydown\",_4)}};var E4=!1,Fl,k0,$0,fp,hp,$M,pp,O0,P0,T0,OM,x0,_0,PM,TM;function Dr(){if(!E4){E4=!0;var e=navigator.userAgent,t=/(?:MSIE.(\\d+\\.\\d+))|(?:(?:Firefox|GranParadiso|Iceweasel).(\\d+\\.\\d+))|(?:Opera(?:.+Version.|.)(\\d+\\.\\d+))|(?:AppleWebKit.(\\d+(?:\\.\\d+)?))|(?:Trident\\/\\d+\\.\\d+.*rv:(\\d+\\.\\d+))/.exec(e),n=/(Mac OS X)|(Windows)|(Linux)/.exec(e);if(x0=/\\b(iPhone|iP[ao]d)/.exec(e),_0=/\\b(iP[ao]d)/.exec(e),T0=/Android/i.exec(e),PM=/FBAN\\/\\w+;/i.exec(e),TM=/Mobile/i.exec(e),OM=!!/Win64/.exec(e),t){Fl=t[1]?parseFloat(t[1]):t[5]?parseFloat(t[5]):NaN,Fl&&document&&document.documentMode&&(Fl=document.documentMode);var r=/(?:Trident\\/(\\d+.\\d+))/.exec(e);$M=r?parseFloat(r[1])+4:Fl,k0=t[2]?parseFloat(t[2]):NaN,$0=t[3]?parseFloat(t[3]):NaN,fp=t[4]?parseFloat(t[4]):NaN,fp?(t=/(?:Chrome\\/(\\d+\\.\\d+))/.exec(e),hp=t&&t[1]?parseFloat(t[1]):NaN):hp=NaN}else Fl=k0=$0=hp=fp=NaN;if(n){if(n[1]){var a=/(?:Mac OS X (\\d+(?:[._]\\d+)?))/.exec(e);pp=a?parseFloat(a[1].replace(\"_\",\".\")):!0}else pp=!1;O0=!!n[2],P0=!!n[3]}else pp=O0=P0=!1}}var E0={ie:function(){return Dr()||Fl},ieCompatibilityMode:function(){return Dr()||$M>Fl},ie64:function(){return E0.ie()&&OM},firefox:function(){return Dr()||k0},opera:function(){return Dr()||$0},webkit:function(){return Dr()||fp},safari:function(){return E0.webkit()},chrome:function(){return Dr()||hp},windows:function(){return Dr()||O0},osx:function(){return Dr()||pp},linux:function(){return Dr()||P0},iphone:function(){return Dr()||x0},mobile:function(){return Dr()||x0||_0||T0||TM},nativeApp:function(){return Dr()||PM},android:function(){return Dr()||T0},ipad:function(){return Dr()||_0}},_te=E0,uh=!!(typeof window<\"u\"&&window.document&&window.document.createElement),Ete={canUseDOM:uh,canUseWorkers:typeof Worker<\"u\",canUseEventListeners:uh&&!!(window.addEventListener||window.attachEvent),canUseViewport:uh&&!!window.screen,isInWorker:!uh},xM=Ete,_M;xM.canUseDOM&&(_M=document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature(\"\",\"\")!==!0);function Mte(e,t){if(!xM.canUseDOM||t&&!(\"addEventListener\"in document))return!1;var n=\"on\"+e,r=n in document;if(!r){var a=document.createElement(\"div\");a.setAttribute(n,\"return;\"),r=typeof a[n]==\"function\"}return!r&&_M&&e===\"wheel\"&&(r=document.implementation.hasFeature(\"Events.wheel\",\"3.0\")),r}var Ite=Mte,M4=10,I4=40,N4=800;function EM(e){var t=0,n=0,r=0,a=0;return\"detail\"in e&&(n=e.detail),\"wheelDelta\"in e&&(n=-e.wheelDelta/120),\"wheelDeltaY\"in e&&(n=-e.wheelDeltaY/120),\"wheelDeltaX\"in e&&(t=-e.wheelDeltaX/120),\"axis\"in e&&e.axis===e.HORIZONTAL_AXIS&&(t=n,n=0),r=t*M4,a=n*M4,\"deltaY\"in e&&(a=e.deltaY),\"deltaX\"in e&&(r=e.deltaX),(r||a)&&e.deltaMode&&(e.deltaMode==1?(r*=I4,a*=I4):(r*=N4,a*=N4)),r&&!t&&(t=r<1?-1:1),a&&!n&&(n=a<1?-1:1),{spinX:t,spinY:n,pixelX:r,pixelY:a}}EM.getEventType=function(){return _te.firefox()?\"DOMMouseScroll\":Ite(\"wheel\")?\"wheel\":\"mousewheel\"};var Nte=EM;/**\n* Checks if an event is supported in the current execution environment.\n*\n* NOTE: This will not work correctly for non-generic events such as `change`,\n* `reset`, `load`, `error`, and `select`.\n*\n* Borrows from Modernizr.\n*\n* @param {string} eventNameSuffix Event name, e.g. \"click\".\n* @param {?boolean} capture Check if the capture phase is supported.\n* @return {boolean} True if the event is supported.\n* @internal\n* @license Modernizr 3.0.0pre (Custom Build) | MIT\n*/const Ate=function(e,t){if(e&&e.addEventListener){const n=function(r){const a=Nte(r);t&&Reflect.apply(t,this,[r,a])};BC()?e.addEventListener(\"DOMMouseScroll\",n):e.onmousewheel=n}},Dte={beforeMount(e,t){Ate(e,t.value)}},Rte={beforeMount(e,t){e._handleResize=()=>{var n;e&&((n=t.value)==null||n.call(t,e))},wc(e,e._handleResize)},beforeUnmount(e){Sc(e,e._handleResize)}},cy=(e,t,n)=>{const r=[],a=t&&n();for(let o=0;o<e;o++)r[o]=a?a.includes(o):!1;return r},dy=e=>e.map((t,n)=>t||n).filter(t=>t!==!0),MM=(e,t,n)=>({getHoursList:(i,l)=>cy(24,e,()=>e(i,l)),getMinutesList:(i,l,s)=>cy(60,t,()=>t(i,l,s)),getSecondsList:(i,l,s,c)=>cy(60,n,()=>n(i,l,s,c))}),IM=(e,t,n)=>{const{getHoursList:r,getMinutesList:a,getSecondsList:o}=MM(e,t,n);return{getAvailableHours:(c,d)=>dy(r(c,d)),getAvailableMinutes:(c,d,f)=>dy(a(c,d,f)),getAvailableSeconds:(c,d,f,p)=>dy(o(c,d,f,p))}},NM=e=>{const t=H(e.parsedValue);return ce(()=>e.visible,n=>{n||(t.value=e.parsedValue)}),t},Lte=G({directives:{repeatClick:SM},components:{ElScrollbar:xi,ElIcon:ft,ArrowUp:Of,ArrowDown:_s},props:{role:{type:String,required:!0},spinnerDate:{type:Object,required:!0},showSeconds:{type:Boolean,default:!0},arrowControl:Boolean,amPmMode:{type:String,default:\"\"},disabledHours:{type:Function},disabledMinutes:{type:Function},disabledSeconds:{type:Function}},emits:[\"change\",\"select-range\",\"set-option\"],setup(e,t){const n=De(\"time\");let r=!1;const a=Yn(Q=>{r=!1,I(Q)},200),o=H(null),i=H(null),l=H(null),s=H(null),c={hours:i,minutes:l,seconds:s},d=x(()=>{const Q=[\"hours\",\"minutes\",\"seconds\"];return e.showSeconds?Q:Q.slice(0,2)}),f=x(()=>e.spinnerDate.hour()),p=x(()=>e.spinnerDate.minute()),v=x(()=>e.spinnerDate.second()),m=x(()=>({hours:f,minutes:p,seconds:v})),y=x(()=>J(e.role)),b=x(()=>ne(f.value,e.role)),C=x(()=>oe(f.value,p.value,e.role)),S=x(()=>({hours:y,minutes:b,seconds:C})),w=x(()=>{const Q=f.value;return[Q>0?Q-1:void 0,Q,Q<23?Q+1:void 0]}),k=x(()=>{const Q=p.value;return[Q>0?Q-1:void 0,Q,Q<59?Q+1:void 0]}),$=x(()=>{const Q=v.value;return[Q>0?Q-1:void 0,Q,Q<59?Q+1:void 0]}),O=x(()=>({hours:w,minutes:k,seconds:$})),T=Q=>{if(!!!e.amPmMode)return\"\";const de=e.amPmMode===\"A\";let be=Q<12?\" am\":\" pm\";return de&&(be=be.toUpperCase()),be},_=Q=>{Q===\"hours\"?t.emit(\"select-range\",0,2):Q===\"minutes\"?t.emit(\"select-range\",3,5):Q===\"seconds\"&&t.emit(\"select-range\",6,8),o.value=Q},I=Q=>{F(Q,m.value[Q].value)},L=()=>{I(\"hours\"),I(\"minutes\"),I(\"seconds\")},j=Q=>Q.querySelector(`.${n.namespace.value}-scrollbar__wrap`),F=(Q,ae)=>{if(e.arrowControl)return;const de=c[Q];de&&de.$el&&(j(de.$el).scrollTop=Math.max(0,ae*N(Q)))},N=Q=>c[Q].$el.querySelector(\"li\").offsetHeight,D=()=>{B(1)},z=()=>{B(-1)},B=Q=>{o.value||_(\"hours\");const ae=o.value;let de=m.value[ae].value;const be=o.value===\"hours\"?24:60;de=(de+Q+be)%be,M(ae,de),F(ae,de),Ne(()=>_(o.value))},M=(Q,ae)=>{if(!S.value[Q].value[ae])switch(Q){case\"hours\":t.emit(\"change\",e.spinnerDate.hour(ae).minute(p.value).second(v.value));break;case\"minutes\":t.emit(\"change\",e.spinnerDate.hour(f.value).minute(ae).second(v.value));break;case\"seconds\":t.emit(\"change\",e.spinnerDate.hour(f.value).minute(p.value).second(ae));break}},E=(Q,{value:ae,disabled:de})=>{de||(M(Q,ae),_(Q),F(Q,ae))},K=Q=>{r=!0,a(Q);const ae=Math.min(Math.round((j(c[Q].$el).scrollTop-(W(Q)*.5-10)/N(Q)+3)/N(Q)),Q===\"hours\"?23:59);M(Q,ae)},W=Q=>c[Q].$el.offsetHeight,Y=()=>{const Q=ae=>{c[ae]&&c[ae].$el&&(j(c[ae].$el).onscroll=()=>{K(ae)})};Q(\"hours\"),Q(\"minutes\"),Q(\"seconds\")};et(()=>{Ne(()=>{!e.arrowControl&&Y(),L(),e.role===\"start\"&&_(\"hours\")})});const q=(Q,ae)=>{c[ae]=Q};t.emit(\"set-option\",[`${e.role}_scrollDown`,B]),t.emit(\"set-option\",[`${e.role}_emitSelectRange`,_]);const{getHoursList:J,getMinutesList:ne,getSecondsList:oe}=MM(e.disabledHours,e.disabledMinutes,e.disabledSeconds);return ce(()=>e.spinnerDate,()=>{r||L()}),{ns:n,setRef:q,spinnerItems:d,currentScrollbar:o,hours:f,minutes:p,seconds:v,hoursList:y,minutesList:b,arrowHourList:w,arrowMinuteList:k,arrowSecondList:$,getAmPmFlag:T,emitSelectRange:_,adjustCurrentSpinner:I,typeItemHeight:N,listHoursRef:i,listMinutesRef:l,listSecondsRef:s,onIncreaseClick:D,onDecreaseClick:z,handleClick:E,secondsList:C,timePartsMap:m,arrowListMap:O,listMap:S}}}),Fte=[\"onClick\"],Bte=[\"onMouseenter\"];function Vte(e,t,n,r,a,o){const i=we(\"el-scrollbar\"),l=we(\"arrow-up\"),s=we(\"el-icon\"),c=we(\"arrow-down\"),d=pa(\"repeat-click\");return R(),X(\"div\",{class:U([e.ns.b(\"spinner\"),{\"has-seconds\":e.showSeconds}])},[e.arrowControl?se(\"v-if\",!0):(R(!0),X(Fe,{key:0},Rt(e.spinnerItems,f=>(R(),fe(i,{key:f,ref_for:!0,ref:p=>e.setRef(p,f),class:U(e.ns.be(\"spinner\",\"wrapper\")),\"wrap-style\":\"max-height: inherit;\",\"view-class\":e.ns.be(\"spinner\",\"list\"),noresize:\"\",tag:\"ul\",onMouseenter:p=>e.emitSelectRange(f),onMousemove:p=>e.adjustCurrentSpinner(f)},{default:re(()=>[(R(!0),X(Fe,null,Rt(e.listMap[f].value,(p,v)=>(R(),X(\"li\",{key:v,class:U([e.ns.be(\"spinner\",\"item\"),e.ns.is(\"active\",v===e.timePartsMap[f].value),e.ns.is(\"disabled\",p)]),onClick:m=>e.handleClick(f,{value:v,disabled:p})},[f===\"hours\"?(R(),X(Fe,{key:0},[yt(Me((\"0\"+(e.amPmMode?v%12||12:v)).slice(-2))+Me(e.getAmPmFlag(v)),1)],2112)):(R(),X(Fe,{key:1},[yt(Me((\"0\"+v).slice(-2)),1)],2112))],10,Fte))),128))]),_:2},1032,[\"class\",\"view-class\",\"onMouseenter\",\"onMousemove\"]))),128)),e.arrowControl?(R(!0),X(Fe,{key:1},Rt(e.spinnerItems,f=>(R(),X(\"div\",{key:f,class:U([e.ns.be(\"spinner\",\"wrapper\"),e.ns.is(\"arrow\")]),onMouseenter:p=>e.emitSelectRange(f)},[at((R(),fe(s,{class:U([\"arrow-up\",e.ns.be(\"spinner\",\"arrow\")])},{default:re(()=>[g(l)]),_:1},8,[\"class\"])),[[d,e.onDecreaseClick]]),at((R(),fe(s,{class:U([\"arrow-down\",e.ns.be(\"spinner\",\"arrow\")])},{default:re(()=>[g(c)]),_:1},8,[\"class\"])),[[d,e.onIncreaseClick]]),Z(\"ul\",{class:U(e.ns.be(\"spinner\",\"list\"))},[(R(!0),X(Fe,null,Rt(e.arrowListMap[f].value,(p,v)=>(R(),X(\"li\",{key:v,class:U([e.ns.be(\"spinner\",\"item\"),e.ns.is(\"active\",p===e.timePartsMap[f].value),e.ns.is(\"disabled\",e.listMap[f].value[p])])},[typeof p==\"number\"?(R(),X(Fe,{key:0},[f===\"hours\"?(R(),X(Fe,{key:0},[yt(Me((\"0\"+(e.amPmMode?p%12||12:p)).slice(-2))+Me(e.getAmPmFlag(p)),1)],2112)):(R(),X(Fe,{key:1},[yt(Me((\"0\"+p).slice(-2)),1)],2112))],2112)):se(\"v-if\",!0)],2))),128))],2)],42,Bte))),128)):se(\"v-if\",!0)],2)}var AM=Ae(Lte,[[\"render\",Vte],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/time-picker/src/time-picker-com/basic-time-spinner.vue\"]]);const zte=G({components:{TimeSpinner:AM},props:{visible:Boolean,actualVisible:{type:Boolean,default:void 0},datetimeRole:{type:String},parsedValue:{type:[Object,String]},format:{type:String,default:\"\"}},emits:[\"pick\",\"select-range\",\"set-picker-option\"],setup(e,t){const n=De(\"time\"),{t:r,lang:a}=ln(),o=H([0,2]),i=NM(e),l=x(()=>sa(e.actualVisible)?`${n.namespace.value}-zoom-in-top`:\"\"),s=x(()=>e.format.includes(\"ss\")),c=x(()=>e.format.includes(\"A\")?\"A\":e.format.includes(\"a\")?\"a\":\"\"),d=B=>{const M=mt(B).locale(a.value),E=C(M);return M.isSame(E)},f=()=>{t.emit(\"pick\",i.value,!1)},p=(B=!1,M=!1)=>{M||t.emit(\"pick\",e.parsedValue,B)},v=B=>{if(!e.visible)return;const M=C(B).millisecond(0);t.emit(\"pick\",M,!0)},m=(B,M)=>{t.emit(\"select-range\",B,M),o.value=[B,M]},y=B=>{const M=[0,3].concat(s.value?[6]:[]),E=[\"hours\",\"minutes\"].concat(s.value?[\"seconds\"]:[]),W=(M.indexOf(o.value[0])+B+M.length)%M.length;$.start_emitSelectRange(E[W])},b=B=>{const M=B.code;if(M===Ge.left||M===Ge.right){const E=M===Ge.left?-1:1;y(E),B.preventDefault();return}if(M===Ge.up||M===Ge.down){const E=M===Ge.up?-1:1;$.start_scrollDown(E),B.preventDefault();return}},C=B=>{const M={hour:N,minute:D,second:z};let E=B;return[\"hour\",\"minute\",\"second\"].forEach(K=>{if(M[K]){let W;const Y=M[K];K===\"minute\"?W=Y(E.hour(),e.datetimeRole):K===\"second\"?W=Y(E.hour(),E.minute(),e.datetimeRole):W=Y(e.datetimeRole),W&&W.length&&!W.includes(E[K]())&&(E=E[K](W[0]))}}),E},S=B=>B?mt(B,e.format).locale(a.value):null,w=B=>B?B.format(e.format):null,k=()=>mt(F).locale(a.value);t.emit(\"set-picker-option\",[\"isValidValue\",d]),t.emit(\"set-picker-option\",[\"formatToString\",w]),t.emit(\"set-picker-option\",[\"parseUserInput\",S]),t.emit(\"set-picker-option\",[\"handleKeydown\",b]),t.emit(\"set-picker-option\",[\"getRangeAvailableTime\",C]),t.emit(\"set-picker-option\",[\"getDefaultValue\",k]);const $={},O=B=>{$[B[0]]=B[1]},T=ve(\"EP_PICKER_BASE\"),{arrowControl:_,disabledHours:I,disabledMinutes:L,disabledSeconds:j,defaultValue:F}=T.props,{getAvailableHours:N,getAvailableMinutes:D,getAvailableSeconds:z}=IM(I,L,j);return{ns:n,transitionName:l,arrowControl:_,onSetOption:O,t:r,handleConfirm:p,handleChange:v,setSelectionRange:m,amPmMode:c,showSeconds:s,handleCancel:f,disabledHours:I,disabledMinutes:L,disabledSeconds:j}}});function Hte(e,t,n,r,a,o){const i=we(\"time-spinner\");return R(),fe(Vn,{name:e.transitionName},{default:re(()=>[e.actualVisible||e.visible?(R(),X(\"div\",{key:0,class:U(e.ns.b(\"panel\"))},[Z(\"div\",{class:U([e.ns.be(\"panel\",\"content\"),{\"has-seconds\":e.showSeconds}])},[g(i,{ref:\"spinner\",role:e.datetimeRole||\"start\",\"arrow-control\":e.arrowControl,\"show-seconds\":e.showSeconds,\"am-pm-mode\":e.amPmMode,\"spinner-date\":e.parsedValue,\"disabled-hours\":e.disabledHours,\"disabled-minutes\":e.disabledMinutes,\"disabled-seconds\":e.disabledSeconds,onChange:e.handleChange,onSetOption:e.onSetOption,onSelectRange:e.setSelectionRange},null,8,[\"role\",\"arrow-control\",\"show-seconds\",\"am-pm-mode\",\"spinner-date\",\"disabled-hours\",\"disabled-minutes\",\"disabled-seconds\",\"onChange\",\"onSetOption\",\"onSelectRange\"])],2),Z(\"div\",{class:U(e.ns.be(\"panel\",\"footer\"))},[Z(\"button\",{type:\"button\",class:U([e.ns.be(\"panel\",\"btn\"),\"cancel\"]),onClick:t[0]||(t[0]=(...l)=>e.handleCancel&&e.handleCancel(...l))},Me(e.t(\"el.datepicker.cancel\")),3),Z(\"button\",{type:\"button\",class:U([e.ns.be(\"panel\",\"btn\"),\"confirm\"]),onClick:t[1]||(t[1]=l=>e.handleConfirm())},Me(e.t(\"el.datepicker.confirm\")),3)],2)],2)):se(\"v-if\",!0)]),_:1},8,[\"name\"])}var rw=Ae(zte,[[\"render\",Hte],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/time-picker/src/time-picker-com/panel-time-pick.vue\"]]);const Fs=(e,t)=>{const n=[];for(let r=e;r<=t;r++)n.push(r);return n},jte=G({components:{TimeSpinner:AM},props:{visible:Boolean,actualVisible:Boolean,parsedValue:{type:[Array]},format:{type:String,default:\"\"}},emits:[\"pick\",\"select-range\",\"set-picker-option\"],setup(e,t){const{t:n,lang:r}=ln(),a=De(\"time\"),o=De(\"picker\"),i=x(()=>e.parsedValue[0]),l=x(()=>e.parsedValue[1]),s=NM(e),c=()=>{t.emit(\"pick\",s.value,!1)},d=x(()=>e.format.includes(\"ss\")),f=x(()=>e.format.includes(\"A\")?\"A\":e.format.includes(\"a\")?\"a\":\"\"),p=H([]),v=H([]),m=(be=!1)=>{t.emit(\"pick\",[i.value,l.value],be)},y=be=>{S(be.millisecond(0),l.value)},b=be=>{S(i.value,be.millisecond(0))},C=be=>{const Ee=be.map(Be=>mt(Be).locale(r.value)),Pe=N(Ee);return Ee[0].isSame(Pe[0])&&Ee[1].isSame(Pe[1])},S=(be,Ee)=>{t.emit(\"pick\",[be,Ee],!0)},w=x(()=>i.value>l.value),k=H([0,2]),$=(be,Ee)=>{t.emit(\"select-range\",be,Ee,\"min\"),k.value=[be,Ee]},O=x(()=>d.value?11:8),T=(be,Ee)=>{t.emit(\"select-range\",be,Ee,\"max\"),k.value=[be+O.value,Ee+O.value]},_=be=>{const Ee=d.value?[0,3,6,11,14,17]:[0,3,8,11],Pe=[\"hours\",\"minutes\"].concat(d.value?[\"seconds\"]:[]),te=(Ee.indexOf(k.value[0])+be+Ee.length)%Ee.length,ie=Ee.length/2;te<ie?Y.start_emitSelectRange(Pe[te]):Y.end_emitSelectRange(Pe[te-ie])},I=be=>{const Ee=be.code;if(Ee===Ge.left||Ee===Ge.right){const Pe=Ee===Ge.left?-1:1;_(Pe),be.preventDefault();return}if(Ee===Ge.up||Ee===Ge.down){const Pe=Ee===Ge.up?-1:1,Be=k.value[0]<O.value?\"start\":\"end\";Y[`${Be}_scrollDown`](Pe),be.preventDefault();return}},L=(be,Ee)=>{const Pe=oe?oe(be):[],Be=be===\"start\",ie=(Ee||(Be?l.value:i.value)).hour(),ge=Be?Fs(ie+1,23):Fs(0,ie-1);return ny(Pe,ge)},j=(be,Ee,Pe)=>{const Be=Q?Q(be,Ee):[],te=Ee===\"start\",ie=Pe||(te?l.value:i.value),ge=ie.hour();if(be!==ge)return Be;const ke=ie.minute(),xe=te?Fs(ke+1,59):Fs(0,ke-1);return ny(Be,xe)},F=(be,Ee,Pe,Be)=>{const te=ae?ae(be,Ee,Pe):[],ie=Pe===\"start\",ge=Be||(ie?l.value:i.value),ke=ge.hour(),xe=ge.minute();if(be!==ke||Ee!==xe)return te;const Ie=ge.second(),ye=ie?Fs(Ie+1,59):Fs(0,Ie-1);return ny(te,ye)},N=be=>be.map((Ee,Pe)=>M(be[0],be[1],Pe===0?\"start\":\"end\")),{getAvailableHours:D,getAvailableMinutes:z,getAvailableSeconds:B}=IM(L,j,F),M=(be,Ee,Pe)=>{const Be={hour:D,minute:z,second:B},te=Pe===\"start\";let ie=te?be:Ee;const ge=te?Ee:be;return[\"hour\",\"minute\",\"second\"].forEach(ke=>{if(Be[ke]){let xe;const Ie=Be[ke];if(ke===\"minute\"?xe=Ie(ie.hour(),Pe,ge):ke===\"second\"?xe=Ie(ie.hour(),ie.minute(),Pe,ge):xe=Ie(Pe,ge),xe&&xe.length&&!xe.includes(ie[ke]())){const ye=te?0:xe.length-1;ie=ie[ke](xe[ye])}}}),ie},E=be=>be?Array.isArray(be)?be.map(Ee=>mt(Ee,e.format).locale(r.value)):mt(be,e.format).locale(r.value):null,K=be=>be?Array.isArray(be)?be.map(Ee=>Ee.format(e.format)):be.format(e.format):null,W=()=>{if(Array.isArray(de))return de.map(Ee=>mt(Ee).locale(r.value));const be=mt(de).locale(r.value);return[be,be.add(60,\"m\")]};t.emit(\"set-picker-option\",[\"formatToString\",K]),t.emit(\"set-picker-option\",[\"parseUserInput\",E]),t.emit(\"set-picker-option\",[\"isValidValue\",C]),t.emit(\"set-picker-option\",[\"handleKeydown\",I]),t.emit(\"set-picker-option\",[\"getDefaultValue\",W]),t.emit(\"set-picker-option\",[\"getRangeAvailableTime\",N]);const Y={},q=be=>{Y[be[0]]=be[1]},J=ve(\"EP_PICKER_BASE\"),{arrowControl:ne,disabledHours:oe,disabledMinutes:Q,disabledSeconds:ae,defaultValue:de}=J.props;return{nsTime:a,nsPicker:o,arrowControl:ne,onSetOption:q,setMaxSelectionRange:T,setMinSelectionRange:$,btnConfirmDisabled:w,handleCancel:c,handleConfirm:m,t:n,showSeconds:d,minDate:i,maxDate:l,amPmMode:f,handleMinChange:y,handleMaxChange:b,minSelectableRange:p,maxSelectableRange:v,disabledHours_:L,disabledMinutes_:j,disabledSeconds_:F}}}),Kte=[\"disabled\"];function Wte(e,t,n,r,a,o){const i=we(\"time-spinner\");return e.actualVisible?(R(),X(\"div\",{key:0,class:U([e.nsTime.b(\"range-picker\"),e.nsPicker.b(\"panel\")])},[Z(\"div\",{class:U(e.nsTime.be(\"range-picker\",\"content\"))},[Z(\"div\",{class:U(e.nsTime.be(\"range-picker\",\"cell\"))},[Z(\"div\",{class:U(e.nsTime.be(\"range-picker\",\"header\"))},Me(e.t(\"el.datepicker.startTime\")),3),Z(\"div\",{class:U([e.nsTime.be(\"range-picker\",\"body\"),e.nsTime.be(\"panel\",\"content\"),e.nsTime.is(\"arrow\",e.arrowControl),{\"has-seconds\":e.showSeconds}])},[g(i,{ref:\"minSpinner\",role:\"start\",\"show-seconds\":e.showSeconds,\"am-pm-mode\":e.amPmMode,\"arrow-control\":e.arrowControl,\"spinner-date\":e.minDate,\"disabled-hours\":e.disabledHours_,\"disabled-minutes\":e.disabledMinutes_,\"disabled-seconds\":e.disabledSeconds_,onChange:e.handleMinChange,onSetOption:e.onSetOption,onSelectRange:e.setMinSelectionRange},null,8,[\"show-seconds\",\"am-pm-mode\",\"arrow-control\",\"spinner-date\",\"disabled-hours\",\"disabled-minutes\",\"disabled-seconds\",\"onChange\",\"onSetOption\",\"onSelectRange\"])],2)],2),Z(\"div\",{class:U(e.nsTime.be(\"range-picker\",\"cell\"))},[Z(\"div\",{class:U(e.nsTime.be(\"range-picker\",\"header\"))},Me(e.t(\"el.datepicker.endTime\")),3),Z(\"div\",{class:U([e.nsTime.be(\"range-picker\",\"body\"),e.nsTime.be(\"panel\",\"content\"),e.nsTime.is(\"arrow\",e.arrowControl),{\"has-seconds\":e.showSeconds}])},[g(i,{ref:\"maxSpinner\",role:\"end\",\"show-seconds\":e.showSeconds,\"am-pm-mode\":e.amPmMode,\"arrow-control\":e.arrowControl,\"spinner-date\":e.maxDate,\"disabled-hours\":e.disabledHours_,\"disabled-minutes\":e.disabledMinutes_,\"disabled-seconds\":e.disabledSeconds_,onChange:e.handleMaxChange,onSetOption:e.onSetOption,onSelectRange:e.setMaxSelectionRange},null,8,[\"show-seconds\",\"am-pm-mode\",\"arrow-control\",\"spinner-date\",\"disabled-hours\",\"disabled-minutes\",\"disabled-seconds\",\"onChange\",\"onSetOption\",\"onSelectRange\"])],2)],2)],2),Z(\"div\",{class:U(e.nsTime.be(\"panel\",\"footer\"))},[Z(\"button\",{type:\"button\",class:U([e.nsTime.be(\"panel\",\"btn\"),\"cancel\"]),onClick:t[0]||(t[0]=l=>e.handleCancel())},Me(e.t(\"el.datepicker.cancel\")),3),Z(\"button\",{type:\"button\",class:U([e.nsTime.be(\"panel\",\"btn\"),\"confirm\"]),disabled:e.btnConfirmDisabled,onClick:t[1]||(t[1]=l=>e.handleConfirm())},Me(e.t(\"el.datepicker.confirm\")),11,Kte)],2)],2)):se(\"v-if\",!0)}var Ute=Ae(jte,[[\"render\",Wte],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/time-picker/src/time-picker-com/panel-time-range.vue\"]]);mt.extend(tw);var Yte=G({name:\"ElTimePicker\",install:null,props:Ke(Te({},nw),{isRange:{type:Boolean,default:!1}}),emits:[\"update:modelValue\"],setup(e,t){const n=H(null),r=e.isRange?\"timerange\":\"time\",a=e.isRange?Ute:rw,o=Ke(Te({},e),{focus:()=>{var i;(i=n.value)==null||i.handleFocus()},blur:()=>{var i;(i=n.value)==null||i.handleBlur()}});return ot(\"ElPopperOptions\",e.popperOptions),t.expose(o),()=>{var i;const l=(i=e.format)!=null?i:w0;return qe(wM,Ke(Te({},e),{format:l,type:r,ref:n,\"onUpdate:modelValue\":s=>t.emit(\"update:modelValue\",s)}),{default:s=>qe(a,s)})}}});const tl=e=>Array.from(Array.from({length:e}).keys()),DM=e=>e.replace(/\\W?m{1,2}|\\W?ZZ/g,\"\").replace(/\\W?h{1,2}|\\W?s{1,3}|\\W?a/gi,\"\").trim(),RM=e=>e.replace(/\\W?D{1,2}|\\W?Do|\\W?d{1,4}|\\W?M{1,4}|\\W?Y{2,4}/g,\"\").trim(),vp=Yte;vp.install=e=>{e.component(vp.name,vp)};const qte=vp,Gte=(e,t)=>{const n=e.subtract(1,\"month\").endOf(\"month\").date();return tl(t).map((r,a)=>n-(t-a-1))},Xte=e=>{const t=e.daysInMonth();return tl(t).map((n,r)=>r+1)},Zte=e=>tl(e.length/7).map(t=>{const n=t*7;return e.slice(n,n+7)}),Jte=Ze({selectedDay:{type:Le(Object)},range:{type:Le(Array)},date:{type:Le(Object),required:!0},hideHeader:{type:Boolean}}),Qte={pick:e=>zt(e)},ene={key:0},tne=[\"onClick\"],nne={name:\"DateTable\"},rne=G(Ke(Te({},nne),{props:Jte,emits:Qte,setup(e,{expose:t,emit:n}){const r=e;mt.extend(bM);const{t:a,lang:o}=ln(),i=De(\"calendar-table\"),l=De(\"calendar-day\"),s=mt().locale(o.value),c=s.$locale().weekStart||0,d=x(()=>!!r.range&&!!r.range.length),f=x(()=>{let C=[];if(d.value){const[S,w]=r.range,k=tl(w.date()-S.date()+1).map(T=>({text:S.date()+T,type:\"current\"}));let $=k.length%7;$=$===0?0:7-$;const O=tl($).map((T,_)=>({text:_+1,type:\"next\"}));C=k.concat(O)}else{const S=r.date.startOf(\"month\").day()||7,w=Gte(r.date,S-c).map(O=>({text:O,type:\"prev\"})),k=Xte(r.date).map(O=>({text:O,type:\"current\"}));C=[...w,...k];const $=tl(42-C.length).map((O,T)=>({text:T+1,type:\"next\"}));C=C.concat($)}return Zte(C)}),p=x(()=>{const C=c;return C===0?ay.map(S=>a(`el.datepicker.weeks.${S}`)):ay.slice(C).concat(ay.slice(0,C)).map(S=>a(`el.datepicker.weeks.${S}`))}),v=(C,S)=>{switch(S){case\"prev\":return r.date.startOf(\"month\").subtract(1,\"month\").date(C);case\"next\":return r.date.startOf(\"month\").add(1,\"month\").date(C);case\"current\":return r.date.date(C)}},m=({text:C,type:S})=>{const w=[S];if(S===\"current\"){const k=v(C,S);k.isSame(r.selectedDay,\"day\")&&w.push(l.is(\"selected\")),k.isSame(s,\"day\")&&w.push(l.is(\"today\"))}return w},y=({text:C,type:S})=>{const w=v(C,S);n(\"pick\",w)},b=({text:C,type:S})=>{const w=v(C,S);return{isSelected:w.isSame(r.selectedDay),type:`${S}-month`,day:w.format(\"YYYY-MM-DD\"),date:w.toDate()}};return t({getFormattedDate:v}),(C,S)=>(R(),X(\"table\",{class:U([A(i).b(),A(i).is(\"range\",A(d))]),cellspacing:\"0\",cellpadding:\"0\"},[C.hideHeader?se(\"v-if\",!0):(R(),X(\"thead\",ene,[(R(!0),X(Fe,null,Rt(A(p),w=>(R(),X(\"th\",{key:w},Me(w),1))),128))])),Z(\"tbody\",null,[(R(!0),X(Fe,null,Rt(A(f),(w,k)=>(R(),X(\"tr\",{key:k,class:U({[A(i).e(\"row\")]:!0,[A(i).em(\"row\",\"hide-border\")]:k===0&&C.hideHeader})},[(R(!0),X(Fe,null,Rt(w,($,O)=>(R(),X(\"td\",{key:O,class:U(m($)),onClick:T=>y($)},[Z(\"div\",{class:U(A(l).b())},[Oe(C.$slots,\"dateCell\",{data:b($)},()=>[Z(\"span\",null,Me($.text),1)])],2)],10,tne))),128))],2))),128))])],2))}}));var A4=Ae(rne,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/calendar/src/date-table.vue\"]]);const ane=Ze({modelValue:{type:Date},range:{type:Le(Array),validator:e=>Array.isArray(e)&&e.length===2&&e.every(t=>t instanceof Date)}}),one={[Pt]:e=>e instanceof Date,input:e=>e instanceof Date},ine={name:\"ElCalendar\"},lne=G(Ke(Te({},ine),{props:ane,emits:one,setup(e,{expose:t,emit:n}){const r=e,a=De(\"calendar\"),{t:o,lang:i}=ln(),l=H(),s=mt().locale(i.value),c=x(()=>y.value.subtract(1,\"month\").date(1)),d=x(()=>y.value.add(1,\"month\").date(1)),f=x(()=>y.value.subtract(1,\"year\").date(1)),p=x(()=>y.value.add(1,\"year\").date(1)),v=x(()=>{const k=`el.datepicker.month${y.value.format(\"M\")}`;return`${y.value.year()} ${o(\"el.datepicker.year\")} ${o(k)}`}),m=x({get(){return r.modelValue?y.value:l.value},set(k){if(!k)return;l.value=k;const $=k.toDate();n(\"input\",$),n(\"update:modelValue\",$)}}),y=x(()=>r.modelValue?mt(r.modelValue).locale(i.value):m.value?m.value:C.value.length?C.value[0][0]:s),b=(k,$)=>{const O=k.startOf(\"week\"),T=$.endOf(\"week\"),_=O.get(\"month\"),I=T.get(\"month\");if(_===I)return[[O,T]];if(_+1===I){const L=O.endOf(\"month\"),j=T.startOf(\"month\"),N=L.isSame(j,\"week\")?j.add(1,\"week\"):j;return[[O,L],[N.startOf(\"week\"),T]]}else if(_+2===I){const L=O.endOf(\"month\"),j=O.add(1,\"month\").startOf(\"month\"),F=L.isSame(j,\"week\")?j.add(1,\"week\"):j,N=F.endOf(\"month\"),D=T.startOf(\"month\"),z=N.isSame(D,\"week\")?D.add(1,\"week\"):D;return[[O,L],[F.startOf(\"week\"),N],[z.startOf(\"week\"),T]]}else return[]},C=x(()=>{if(!r.range)return[];const k=r.range.map(T=>mt(T).locale(i.value)),[$,O]=k;return $.isAfter(O)?[]:$.isSame(O,\"month\")?b($,O):$.add(1,\"month\").month()!==O.month()?[]:b($,O)}),S=k=>{m.value=k},w=k=>{let $;k===\"prev-month\"?$=c.value:k===\"next-month\"?$=d.value:k===\"prev-year\"?$=f.value:k===\"next-year\"?$=p.value:$=s,!$.isSame(y.value,\"day\")&&S($)};return t({selectedDay:m,pickDay:S,selectDate:w,calculateValidatedDateRange:b}),(k,$)=>(R(),X(\"div\",{class:U(A(a).b())},[Z(\"div\",{class:U(A(a).e(\"header\"))},[Oe(k.$slots,\"header\",{date:A(v)},()=>[Z(\"div\",{class:U(A(a).e(\"title\"))},Me(A(v)),3),A(C).length===0?(R(),X(\"div\",{key:0,class:U(A(a).e(\"button-group\"))},[g(A(mM),null,{default:re(()=>[g(A(xa),{size:\"small\",onClick:$[0]||($[0]=O=>w(\"prev-month\"))},{default:re(()=>[yt(Me(A(o)(\"el.datepicker.prevMonth\")),1)]),_:1}),g(A(xa),{size:\"small\",onClick:$[1]||($[1]=O=>w(\"today\"))},{default:re(()=>[yt(Me(A(o)(\"el.datepicker.today\")),1)]),_:1}),g(A(xa),{size:\"small\",onClick:$[2]||($[2]=O=>w(\"next-month\"))},{default:re(()=>[yt(Me(A(o)(\"el.datepicker.nextMonth\")),1)]),_:1})]),_:1})],2)):se(\"v-if\",!0)])],2),A(C).length===0?(R(),X(\"div\",{key:0,class:U(A(a).e(\"body\"))},[g(A4,{date:A(y),\"selected-day\":A(m),onPick:S},sl({_:2},[k.$slots.dateCell?{name:\"dateCell\",fn:re(O=>[Oe(k.$slots,\"dateCell\",Za(ll(O)))])}:void 0]),1032,[\"date\",\"selected-day\"])],2)):(R(),X(\"div\",{key:1,class:U(A(a).e(\"body\"))},[(R(!0),X(Fe,null,Rt(A(C),(O,T)=>(R(),fe(A4,{key:T,date:O[0],\"selected-day\":A(m),range:O,\"hide-header\":T!==0,onPick:S},sl({_:2},[k.$slots.dateCell?{name:\"dateCell\",fn:re(_=>[Oe(k.$slots,\"dateCell\",Za(ll(_)))])}:void 0]),1032,[\"date\",\"selected-day\",\"range\",\"hide-header\"]))),128))],2))],2))}}));var sne=Ae(lne,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/calendar/src/calendar.vue\"]]);const une=xt(sne),cne=Ze({header:{type:String,default:\"\"},bodyStyle:{type:Le([String,Object,Array]),default:\"\"},shadow:{type:String,default:\"always\"}}),dne={name:\"ElCard\"},fne=G(Ke(Te({},dne),{props:cne,setup(e){const t=De(\"card\");return(n,r)=>(R(),X(\"div\",{class:U([A(t).b(),A(t).is(`${n.shadow}-shadow`)])},[n.$slots.header||n.header?(R(),X(\"div\",{key:0,class:U(A(t).e(\"header\"))},[Oe(n.$slots,\"header\",{},()=>[yt(Me(n.header),1)])],2)):se(\"v-if\",!0),Z(\"div\",{class:U(A(t).e(\"body\")),style:Xe(n.bodyStyle)},[Oe(n.$slots,\"default\")],6)],2))}}));var hne=Ae(fne,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/card/src/card.vue\"]]);const pne=xt(hne),vne=Ze({initialIndex:{type:Number,default:0},height:{type:String,default:\"\"},trigger:{type:String,default:\"hover\"},autoplay:{type:Boolean,default:!0},interval:{type:Number,default:3e3},indicatorPosition:{type:String,default:\"\"},indicator:{type:Boolean,default:!0},arrow:{type:String,default:\"hover\"},type:{type:String,default:\"\"},loop:{type:Boolean,default:!0},direction:{type:String,default:\"horizontal\",validator(e){return[\"horizontal\",\"vertical\"].includes(e)}},pauseOnHover:{type:Boolean,default:!0}}),mne={change:(e,t)=>[e,t].every(Yt)},gne=[\"onMouseenter\",\"onMouseleave\"],yne=[\"onMouseenter\",\"onClick\"],bne={key:0},Cne={name:\"ElCarousel\"},wne=G(Ke(Te({},Cne),{props:vne,emits:mne,setup(e,{expose:t,emit:n}){const r=e,a=De(\"carousel\"),o=300,i=H(-1),l=H(null),s=H(!1),c=H(),d=H([]),f=x(()=>r.arrow!==\"never\"&&!A(b)),p=x(()=>d.value.some(W=>W.props.label.toString().length>0)),v=x(()=>{const W=[a.b(),a.m(r.direction)];return A(y)&&W.push(a.m(\"card\")),W}),m=x(()=>{const W=[a.e(\"indicators\"),a.em(\"indicators\",r.direction)];return p.value&&W.push(a.em(\"indicators\",\"labels\")),(r.indicatorPosition===\"outside\"||A(y))&&W.push(a.em(\"indicators\",\"outside\")),W}),y=x(()=>r.type===\"card\"),b=x(()=>r.direction===\"vertical\"),C=Qi(W=>{O(W)},o,{trailing:!0}),S=Qi(W=>{B(W)},o);function w(){l.value&&(clearInterval(l.value),l.value=null)}function k(){r.interval<=0||!r.autoplay||l.value||(l.value=setInterval(()=>$(),r.interval))}const $=()=>{i.value<d.value.length-1?i.value=i.value+1:r.loop&&(i.value=0)};function O(W){if(wt(W)){const J=d.value.filter(ne=>ne.props.name===W);J.length>0&&(W=d.value.indexOf(J[0]))}if(W=Number(W),Number.isNaN(W)||W!==Math.floor(W))return;const Y=d.value.length,q=i.value;W<0?i.value=r.loop?Y-1:0:W>=Y?i.value=r.loop?0:Y-1:i.value=W,q===i.value&&T(q)}function T(W){d.value.forEach((Y,q)=>{Y.translateItem(q,i.value,W)})}function _(W){d.value.push(W)}function I(W){const Y=d.value.findIndex(q=>q.uid===W);Y!==-1&&(d.value.splice(Y,1),i.value===Y&&E())}function L(W,Y){var q,J,ne,oe;const Q=A(d),ae=Q.length;if(ae===0||!W.states.inStage)return!1;const de=Y+1,be=Y-1,Ee=ae-1,Pe=Q[Ee].states.active,Be=Q[0].states.active,te=(J=(q=Q[de])==null?void 0:q.states)==null?void 0:J.active,ie=(oe=(ne=Q[be])==null?void 0:ne.states)==null?void 0:oe.active;return Y===Ee&&Be||te?\"left\":Y===0&&Pe||ie?\"right\":!1}function j(){s.value=!0,r.pauseOnHover&&w()}function F(){s.value=!1,k()}function N(W){A(b)||d.value.forEach((Y,q)=>{W===L(Y,q)&&(Y.states.hover=!0)})}function D(){A(b)||d.value.forEach(W=>{W.states.hover=!1})}function z(W){i.value=W}function B(W){r.trigger===\"hover\"&&W!==i.value&&(i.value=W)}function M(){O(i.value-1)}function E(){O(i.value+1)}ce(()=>i.value,(W,Y)=>{T(Y),Y>-1&&n(\"change\",W,Y)}),ce(()=>r.autoplay,W=>{W?k():w()}),ce(()=>r.loop,()=>{O(i.value)});const K=Qn();return et(async()=>{await Ne(),K.value=Cc(c.value,()=>{T()}),r.initialIndex<d.value.length&&r.initialIndex>=0&&(i.value=r.initialIndex),k()}),Lt(()=>{w(),c.value&&K.value&&K.value.stop()}),ot(SE,{root:c,isCardType:y,isVertical:b,items:d,loop:r.loop,addItem:_,removeItem:I,setActiveItem:O}),t({setActiveItem:O,prev:M,next:E}),(W,Y)=>(R(),X(\"div\",{ref_key:\"root\",ref:c,class:U(A(v)),onMouseenter:dt(j,[\"stop\"]),onMouseleave:dt(F,[\"stop\"])},[Z(\"div\",{class:U(A(a).e(\"container\")),style:Xe({height:W.height})},[A(f)?(R(),fe(Vn,{key:0,name:\"carousel-arrow-left\"},{default:re(()=>[at(Z(\"button\",{type:\"button\",class:U([A(a).e(\"arrow\"),A(a).em(\"arrow\",\"left\")]),onMouseenter:Y[0]||(Y[0]=q=>N(\"left\")),onMouseleave:D,onClick:Y[1]||(Y[1]=dt(q=>A(C)(i.value-1),[\"stop\"]))},[g(A(ft),null,{default:re(()=>[g(A(Es))]),_:1})],34),[[_t,(W.arrow===\"always\"||s.value)&&(r.loop||i.value>0)]])]),_:1})):se(\"v-if\",!0),A(f)?(R(),fe(Vn,{key:1,name:\"carousel-arrow-right\"},{default:re(()=>[at(Z(\"button\",{type:\"button\",class:U([A(a).e(\"arrow\"),A(a).em(\"arrow\",\"right\")]),onMouseenter:Y[2]||(Y[2]=q=>N(\"right\")),onMouseleave:D,onClick:Y[3]||(Y[3]=dt(q=>A(C)(i.value+1),[\"stop\"]))},[g(A(ft),null,{default:re(()=>[g(A(Da))]),_:1})],34),[[_t,(W.arrow===\"always\"||s.value)&&(r.loop||i.value<d.value.length-1)]])]),_:1})):se(\"v-if\",!0),Oe(W.$slots,\"default\")],6),W.indicatorPosition!==\"none\"?(R(),X(\"ul\",{key:0,class:U(A(m))},[(R(!0),X(Fe,null,Rt(d.value,(q,J)=>(R(),X(\"li\",{key:J,class:U([A(a).e(\"indicator\"),A(a).em(\"indicator\",W.direction),A(a).is(\"active\",J===i.value)]),onMouseenter:ne=>A(S)(J),onClick:dt(ne=>z(J),[\"stop\"])},[Z(\"button\",{class:U(A(a).e(\"button\"))},[A(p)?(R(),X(\"span\",bne,Me(q.props.label),1)):se(\"v-if\",!0)],2)],42,yne))),128))],2)):se(\"v-if\",!0)],42,gne))}}));var Sne=Ae(wne,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/carousel/src/carousel.vue\"]]);const kne=Ze({name:{type:String,default:\"\"},label:{type:[String,Number],default:\"\"}}),$ne={name:\"ElCarouselItem\"},One=G(Ke(Te({},$ne),{props:kne,setup(e){const t=e,n=De(\"carousel\"),r=ve(SE),a=$t(),o=.83,i=H(!1),l=H(0),s=H(1),c=H(!1),d=H(!1),f=H(!1),p=H(!1),{isCardType:v,isVertical:m}=r,y=x(()=>{const O=`${`translate${A(m)?\"Y\":\"X\"}`}(${A(l)}px)`,T=`scale(${A(s)})`;return{transform:[O,T].join(\" \")}});function b($,O,T){const _=T-1,I=O-1,L=O+1,j=T/2;return O===0&&$===_?-1:O===_&&$===0?T:$<I&&O-$>=j?T+1:$>L&&$-O>=j?-2:$}function C($,O){var T;const _=((T=r.root.value)==null?void 0:T.offsetWidth)||0;return f.value?_*((2-o)*($-O)+1)/4:$<O?-(1+o)*_/4:(3+o)*_/4}function S($,O,T){const _=r.root.value;return _?((T?_.offsetHeight:_.offsetWidth)||0)*($-O):0}const w=($,O,T)=>{var _;const I=A(v),L=(_=r.items.value.length)!=null?_:Number.NaN,j=$===O;!I&&!sa(T)&&(p.value=j||$===T),!j&&L>2&&r.loop&&($=b($,O,L));const F=A(m);c.value=j,I?(f.value=Math.round(Math.abs($-O))<=1,l.value=C($,O),s.value=A(c)?1:o):l.value=S($,O,F),d.value=!0};function k(){if(r&&A(v)){const $=r.items.value.findIndex(({uid:O})=>O===a.uid);r.setActiveItem($)}}return et(()=>{r.addItem({props:t,states:bt({hover:i,translate:l,scale:s,active:c,ready:d,inStage:f,animating:p}),uid:a.uid,translateItem:w})}),Wr(()=>{r.removeItem(a.uid)}),($,O)=>at((R(),X(\"div\",{class:U([A(n).e(\"item\"),A(n).is(\"active\",c.value),A(n).is(\"in-stage\",f.value),A(n).is(\"hover\",i.value),A(n).is(\"animating\",p.value),{[A(n).em(\"item\",\"card\")]:A(v)}]),style:Xe(A(y)),onClick:k},[A(v)?at((R(),X(\"div\",{key:0,class:U(A(n).e(\"mask\"))},null,2)),[[_t,!c.value]]):se(\"v-if\",!0),Oe($.$slots,\"default\")],6)),[[_t,d.value]])}}));var LM=Ae(One,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/carousel/src/carousel-item.vue\"]]);const Pne=xt(Sne,{CarouselItem:LM}),Tne=En(LM),xne={modelValue:{type:[Boolean,Number,String],default:()=>{}},label:{type:[String,Boolean,Number,Object]},indeterminate:Boolean,disabled:Boolean,checked:Boolean,name:{type:String,default:void 0},trueLabel:{type:[String,Number],default:void 0},falseLabel:{type:[String,Number],default:void 0},tabindex:[String,Number],size:String},Pc=()=>{const e=ve(ga,{}),t=ve(Ia,{}),n=ve(\"CheckboxGroup\",{}),r=x(()=>n&&(n==null?void 0:n.name)===\"ElCheckboxGroup\"),a=x(()=>t.size);return{isGroup:r,checkboxGroup:n,elForm:e,elFormItemSize:a,elFormItem:t}},_ne=e=>{const t=H(!1),{emit:n}=$t(),{isGroup:r,checkboxGroup:a}=Pc(),o=H(!1);return{model:x({get(){var l,s;return r.value?(l=a.modelValue)==null?void 0:l.value:(s=e.modelValue)!=null?s:t.value},set(l){var s;r.value&&Array.isArray(l)?(o.value=a.max!==void 0&&l.length>a.max.value,o.value===!1&&((s=a==null?void 0:a.changeEvent)==null||s.call(a,l))):(n(Pt,l),t.value=l)}}),isLimitExceeded:o}},Ene=(e,{model:t})=>{const{isGroup:n,checkboxGroup:r}=Pc(),a=H(!1),o=Gn(r==null?void 0:r.checkboxGroupSize,{prop:!0}),i=x(()=>{const s=t.value;return bf(s)===\"[object Boolean]\"?s:Array.isArray(s)?s.includes(e.label):s!=null?s===e.trueLabel:!!s}),l=Gn(x(()=>{var s;return n.value?(s=r==null?void 0:r.checkboxGroupSize)==null?void 0:s.value:void 0}));return{isChecked:i,focus:a,size:o,checkboxSize:l}},Mne=(e,{model:t,isChecked:n})=>{const{elForm:r,isGroup:a,checkboxGroup:o}=Pc(),i=x(()=>{var s,c;const d=(s=o.max)==null?void 0:s.value,f=(c=o.min)==null?void 0:c.value;return!!(d||f)&&t.value.length>=d&&!n.value||t.value.length<=f&&n.value});return{isDisabled:x(()=>{var s,c;const d=e.disabled||r.disabled;return(c=a.value?((s=o.disabled)==null?void 0:s.value)||d||i.value:e.disabled||r.disabled)!=null?c:!1}),isLimitDisabled:i}},Ine=(e,{model:t})=>{function n(){Array.isArray(t.value)&&!t.value.includes(e.label)?t.value.push(e.label):t.value=e.trueLabel||!0}e.checked&&n()},Nne=(e,{isLimitExceeded:t})=>{const{elFormItem:n}=Pc(),{emit:r}=$t();function a(o){var i,l;if(t.value)return;const c=o.target.checked?(i=e.trueLabel)!=null?i:!0:(l=e.falseLabel)!=null?l:!1;r(\"change\",c,o)}return ce(()=>e.modelValue,()=>{var o;(o=n.validate)==null||o.call(n,\"change\").catch(i=>void 0)}),{handleChange:a}},FM=e=>{const{model:t,isLimitExceeded:n}=_ne(e),{focus:r,size:a,isChecked:o,checkboxSize:i}=Ene(e,{model:t}),{isDisabled:l}=Mne(e,{model:t,isChecked:o}),{handleChange:s}=Nne(e,{isLimitExceeded:n});return Ine(e,{model:t}),{isChecked:o,isDisabled:l,checkboxSize:i,model:t,handleChange:s,focus:r,size:a}},Ane=G({name:\"ElCheckbox\",props:{modelValue:{type:[Number,String,Boolean],default:()=>{}},label:{type:[String,Boolean,Number,Object]},indeterminate:Boolean,disabled:Boolean,checked:Boolean,name:{type:String,default:void 0},trueLabel:{type:[String,Number],default:void 0},falseLabel:{type:[String,Number],default:void 0},id:{type:String,default:void 0},controls:{type:String,default:void 0},border:Boolean,size:{type:String,validator:va},tabindex:[String,Number]},emits:[Pt,\"change\"],setup(e){const t=De(\"checkbox\");return Te({ns:t},FM(e))}}),Dne=[\"id\",\"aria-controls\"],Rne=[\"tabindex\",\"role\",\"aria-checked\"],Lne=[\"aria-hidden\",\"name\",\"tabindex\",\"disabled\",\"true-value\",\"false-value\"],Fne=[\"aria-hidden\",\"disabled\",\"value\",\"name\",\"tabindex\"];function Bne(e,t,n,r,a,o){return R(),X(\"label\",{id:e.id,class:U([e.ns.b(),e.ns.m(e.checkboxSize),e.ns.is(\"disabled\",e.isDisabled),e.ns.is(\"bordered\",e.border),e.ns.is(\"checked\",e.isChecked)]),\"aria-controls\":e.indeterminate?e.controls:null},[Z(\"span\",{class:U([e.ns.e(\"input\"),e.ns.is(\"disabled\",e.isDisabled),e.ns.is(\"checked\",e.isChecked),e.ns.is(\"indeterminate\",e.indeterminate),e.ns.is(\"focus\",e.focus)]),tabindex:e.indeterminate?0:void 0,role:e.indeterminate?\"checkbox\":void 0,\"aria-checked\":e.indeterminate?\"mixed\":!1},[Z(\"span\",{class:U(e.ns.e(\"inner\"))},null,2),e.trueLabel||e.falseLabel?at((R(),X(\"input\",{key:0,\"onUpdate:modelValue\":t[0]||(t[0]=i=>e.model=i),class:U(e.ns.e(\"original\")),type:\"checkbox\",\"aria-hidden\":e.indeterminate?\"true\":\"false\",name:e.name,tabindex:e.tabindex,disabled:e.isDisabled,\"true-value\":e.trueLabel,\"false-value\":e.falseLabel,onChange:t[1]||(t[1]=(...i)=>e.handleChange&&e.handleChange(...i)),onFocus:t[2]||(t[2]=i=>e.focus=!0),onBlur:t[3]||(t[3]=i=>e.focus=!1)},null,42,Lne)),[[dv,e.model]]):at((R(),X(\"input\",{key:1,\"onUpdate:modelValue\":t[4]||(t[4]=i=>e.model=i),class:U(e.ns.e(\"original\")),type:\"checkbox\",\"aria-hidden\":e.indeterminate?\"true\":\"false\",disabled:e.isDisabled,value:e.label,name:e.name,tabindex:e.tabindex,onChange:t[5]||(t[5]=(...i)=>e.handleChange&&e.handleChange(...i)),onFocus:t[6]||(t[6]=i=>e.focus=!0),onBlur:t[7]||(t[7]=i=>e.focus=!1)},null,42,Fne)),[[dv,e.model]])],10,Rne),e.$slots.default||e.label?(R(),X(\"span\",{key:0,class:U(e.ns.e(\"label\"))},[Oe(e.$slots,\"default\"),e.$slots.default?se(\"v-if\",!0):(R(),X(Fe,{key:0},[yt(Me(e.label),1)],2112))],2)):se(\"v-if\",!0)],10,Dne)}var Vne=Ae(Ane,[[\"render\",Bne],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/checkbox/src/checkbox.vue\"]]);const zne=G({name:\"ElCheckboxButton\",props:xne,emits:[Pt,\"change\"],setup(e){const{focus:t,isChecked:n,isDisabled:r,size:a,model:o,handleChange:i}=FM(e),{checkboxGroup:l}=Pc(),s=De(\"checkbox\"),c=x(()=>{var d,f,p,v;const m=(f=(d=l==null?void 0:l.fill)==null?void 0:d.value)!=null?f:\"\";return{backgroundColor:m,borderColor:m,color:(v=(p=l==null?void 0:l.textColor)==null?void 0:p.value)!=null?v:\"\",boxShadow:m?`-1px 0 0 0 ${m}`:null}});return{focus:t,isChecked:n,isDisabled:r,model:o,handleChange:i,activeStyle:c,size:a,ns:s}}}),Hne=[\"aria-checked\",\"aria-disabled\"],jne=[\"name\",\"tabindex\",\"disabled\",\"true-value\",\"false-value\"],Kne=[\"name\",\"tabindex\",\"disabled\",\"value\"];function Wne(e,t,n,r,a,o){return R(),X(\"label\",{class:U([e.ns.b(\"button\"),e.ns.bm(\"button\",e.size),e.ns.is(\"disabled\",e.isDisabled),e.ns.is(\"checked\",e.isChecked),e.ns.is(\"focus\",e.focus)]),role:\"checkbox\",\"aria-checked\":e.isChecked,\"aria-disabled\":e.isDisabled},[e.trueLabel||e.falseLabel?at((R(),X(\"input\",{key:0,\"onUpdate:modelValue\":t[0]||(t[0]=i=>e.model=i),class:U(e.ns.be(\"button\",\"original\")),type:\"checkbox\",name:e.name,tabindex:e.tabindex,disabled:e.isDisabled,\"true-value\":e.trueLabel,\"false-value\":e.falseLabel,onChange:t[1]||(t[1]=(...i)=>e.handleChange&&e.handleChange(...i)),onFocus:t[2]||(t[2]=i=>e.focus=!0),onBlur:t[3]||(t[3]=i=>e.focus=!1)},null,42,jne)),[[dv,e.model]]):at((R(),X(\"input\",{key:1,\"onUpdate:modelValue\":t[4]||(t[4]=i=>e.model=i),class:U(e.ns.be(\"button\",\"original\")),type:\"checkbox\",name:e.name,tabindex:e.tabindex,disabled:e.isDisabled,value:e.label,onChange:t[5]||(t[5]=(...i)=>e.handleChange&&e.handleChange(...i)),onFocus:t[6]||(t[6]=i=>e.focus=!0),onBlur:t[7]||(t[7]=i=>e.focus=!1)},null,42,Kne)),[[dv,e.model]]),e.$slots.default||e.label?(R(),X(\"span\",{key:2,class:U(e.ns.be(\"button\",\"inner\")),style:Xe(e.isChecked?e.activeStyle:null)},[Oe(e.$slots,\"default\",{},()=>[yt(Me(e.label),1)])],6)):se(\"v-if\",!0)],10,Hne)}var BM=Ae(zne,[[\"render\",Wne],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/checkbox/src/checkbox-button.vue\"]]);const Une=G({name:\"ElCheckboxGroup\",props:{modelValue:{type:Array,default:()=>[]},disabled:Boolean,min:{type:Number,default:void 0},max:{type:Number,default:void 0},size:{type:String,validator:va},fill:{type:String,default:void 0},textColor:{type:String,default:void 0},tag:{type:String,default:\"div\"}},emits:[Pt,\"change\"],setup(e,{emit:t,slots:n}){const{elFormItem:r}=Pc(),a=Gn(),o=De(\"checkbox\"),i=s=>{t(Pt,s),Ne(()=>{t(\"change\",s)})},l=x({get(){return e.modelValue},set(s){i(s)}});return ot(\"CheckboxGroup\",Ke(Te({name:\"ElCheckboxGroup\",modelValue:l},or(e)),{checkboxGroupSize:a,changeEvent:i})),ce(()=>e.modelValue,()=>{var s;(s=r.validate)==null||s.call(r,\"change\").catch(c=>void 0)}),()=>qe(e.tag,{class:o.b(\"group\"),role:\"group\",\"aria-label\":\"checkbox-group\"},[Oe(n,\"default\")])}});var VM=Ae(Une,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/checkbox/src/checkbox-group.vue\"]]);const io=xt(Vne,{CheckboxButton:BM,CheckboxGroup:VM}),Yne=En(BM),zM=En(VM),HM=Ze({size:Km,disabled:Boolean,label:{type:[String,Number,Boolean],default:\"\"}}),qne=Ze(Ke(Te({},HM),{modelValue:{type:[String,Number,Boolean],default:\"\"},name:{type:String,default:\"\"},border:Boolean})),jM={[Pt]:e=>wt(e)||Yt(e)||yr(e),change:e=>wt(e)||Yt(e)||yr(e)},KM=(e,t)=>{const n=H(),r=ve(TE,void 0),a=x(()=>!!r),o=x({get(){return a.value?r.modelValue:e.modelValue},set(d){a.value?r.changeEvent(d):t(Pt,d),n.value.checked=e.modelValue===e.label}}),i=Gn(x(()=>r==null?void 0:r.size)),l=Ms(x(()=>r==null?void 0:r.disabled)),s=H(!1),c=x(()=>l.value||a.value&&o.value!==e.label?-1:0);return{radioRef:n,isGroup:a,radioGroup:r,focus:s,size:i,disabled:l,tabIndex:c,modelValue:o}},Gne=G({name:\"ElRadio\",props:qne,emits:jM,setup(e,{emit:t}){const n=De(\"radio\"),{radioRef:r,isGroup:a,focus:o,size:i,disabled:l,tabIndex:s,modelValue:c}=KM(e,t);function d(){Ne(()=>t(\"change\",c.value))}return{ns:n,focus:o,isGroup:a,modelValue:c,tabIndex:s,size:i,disabled:l,radioRef:r,handleChange:d}}}),Xne=[\"aria-checked\",\"aria-disabled\",\"tabindex\"],Zne=[\"value\",\"name\",\"disabled\"];function Jne(e,t,n,r,a,o){return R(),X(\"label\",{class:U([e.ns.b(),e.ns.is(\"disabled\",e.disabled),e.ns.is(\"focus\",e.focus),e.ns.is(\"bordered\",e.border),e.ns.is(\"checked\",e.modelValue===e.label),e.ns.m(e.size)]),role:\"radio\",\"aria-checked\":e.modelValue===e.label,\"aria-disabled\":e.disabled,tabindex:e.tabIndex,onKeydown:t[5]||(t[5]=It(dt(i=>e.modelValue=e.disabled?e.modelValue:e.label,[\"stop\",\"prevent\"]),[\"space\"]))},[Z(\"span\",{class:U([e.ns.e(\"input\"),e.ns.is(\"disabled\",e.disabled),e.ns.is(\"checked\",e.modelValue===e.label)])},[Z(\"span\",{class:U(e.ns.e(\"inner\"))},null,2),at(Z(\"input\",{ref:\"radioRef\",\"onUpdate:modelValue\":t[0]||(t[0]=i=>e.modelValue=i),class:U(e.ns.e(\"original\")),value:e.label,type:\"radio\",\"aria-hidden\":\"true\",name:e.name,disabled:e.disabled,tabindex:\"-1\",onFocus:t[1]||(t[1]=i=>e.focus=!0),onBlur:t[2]||(t[2]=i=>e.focus=!1),onChange:t[3]||(t[3]=(...i)=>e.handleChange&&e.handleChange(...i))},null,42,Zne),[[t8,e.modelValue]])],2),Z(\"span\",{class:U(e.ns.e(\"label\")),onKeydown:t[4]||(t[4]=dt(()=>{},[\"stop\"]))},[Oe(e.$slots,\"default\",{},()=>[yt(Me(e.label),1)])],34)],42,Xne)}var Qne=Ae(Gne,[[\"render\",Jne],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/radio/src/radio.vue\"]]);const ere=Ze(Ke(Te({},HM),{name:{type:String,default:\"\"}})),tre=G({name:\"ElRadioButton\",props:ere,setup(e,{emit:t}){const n=De(\"radio\"),{radioRef:r,isGroup:a,focus:o,size:i,disabled:l,tabIndex:s,modelValue:c,radioGroup:d}=KM(e,t),f=x(()=>({backgroundColor:(d==null?void 0:d.fill)||\"\",borderColor:(d==null?void 0:d.fill)||\"\",boxShadow:d!=null&&d.fill?`-1px 0 0 0 ${d.fill}`:\"\",color:(d==null?void 0:d.textColor)||\"\"}));return{ns:n,isGroup:a,size:i,disabled:l,tabIndex:s,modelValue:c,focus:o,activeStyle:f,radioRef:r}}}),nre=[\"aria-checked\",\"aria-disabled\",\"tabindex\"],rre=[\"value\",\"name\",\"disabled\"];function are(e,t,n,r,a,o){return R(),X(\"label\",{class:U([e.ns.b(\"button\"),e.ns.is(\"active\",e.modelValue===e.label),e.ns.is(\"disabled\",e.disabled),e.ns.is(\"focus\",e.focus),e.ns.bm(\"button\",e.size)]),role:\"radio\",\"aria-checked\":e.modelValue===e.label,\"aria-disabled\":e.disabled,tabindex:e.tabIndex,onKeydown:t[4]||(t[4]=It(dt(i=>e.modelValue=e.disabled?e.modelValue:e.label,[\"stop\",\"prevent\"]),[\"space\"]))},[at(Z(\"input\",{ref:\"radioRef\",\"onUpdate:modelValue\":t[0]||(t[0]=i=>e.modelValue=i),class:U(e.ns.be(\"button\",\"original-radio\")),value:e.label,type:\"radio\",name:e.name,disabled:e.disabled,tabindex:\"-1\",onFocus:t[1]||(t[1]=i=>e.focus=!0),onBlur:t[2]||(t[2]=i=>e.focus=!1)},null,42,rre),[[t8,e.modelValue]]),Z(\"span\",{class:U(e.ns.be(\"button\",\"inner\")),style:Xe(e.modelValue===e.label?e.activeStyle:{}),onKeydown:t[3]||(t[3]=dt(()=>{},[\"stop\"]))},[Oe(e.$slots,\"default\",{},()=>[yt(Me(e.label),1)])],38)],42,nre)}var WM=Ae(tre,[[\"render\",are],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/radio/src/radio-button.vue\"]]);const ore=Ze({size:Km,disabled:Boolean,modelValue:{type:[String,Number,Boolean],default:\"\"},fill:{type:String,default:\"\"},textColor:{type:String,default:\"\"}}),ire=jM,lre=G({name:\"ElRadioGroup\",props:ore,emits:ire,setup(e,t){const n=De(\"radio\"),r=H(),{formItem:a}=$c(),o=l=>{t.emit(Pt,l),Ne(()=>t.emit(\"change\",l))},i=l=>{if(!r.value)return;const s=l.target,c=s.nodeName===\"INPUT\"?\"[type=radio]\":\"[role=radio]\",d=r.value.querySelectorAll(c),f=d.length,p=Array.from(d).indexOf(s),v=r.value.querySelectorAll(\"[role=radio]\");let m=null;switch(l.code){case Ge.left:case Ge.up:l.stopPropagation(),l.preventDefault(),m=p===0?f-1:p-1;break;case Ge.right:case Ge.down:l.stopPropagation(),l.preventDefault(),m=p===f-1?0:p+1;break}m!==null&&(v[m].click(),v[m].focus())};return et(()=>{const l=r.value.querySelectorAll(\"[type=radio]\"),s=l[0];!Array.from(l).some(c=>c.checked)&&s&&(s.tabIndex=0)}),ot(TE,bt(Ke(Te({},or(e)),{changeEvent:o}))),ce(()=>e.modelValue,()=>a==null?void 0:a.validate(\"change\").catch(l=>void 0)),{ns:n,radioGroupRef:r,handleKeydown:i}}});function sre(e,t,n,r,a,o){return R(),X(\"div\",{ref:\"radioGroupRef\",class:U(e.ns.b(\"group\")),role:\"radiogroup\",onKeydown:t[0]||(t[0]=(...i)=>e.handleKeydown&&e.handleKeydown(...i))},[Oe(e.$slots,\"default\")],34)}var UM=Ae(lre,[[\"render\",sre],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/radio/src/radio-group.vue\"]]);const YM=xt(Qne,{RadioButton:WM,RadioGroup:UM}),ure=En(UM),cre=En(WM);var dre=G({name:\"NodeContent\",setup(){return{ns:De(\"cascader-node\")}},render(){const{ns:e}=this,{node:t,panel:n}=this.$parent,{data:r,label:a}=t,{renderLabelFn:o}=n;return qe(\"span\",{class:e.e(\"label\")},o?o({node:t,data:r}):a)}});const aw=Symbol(),fre=G({name:\"ElCascaderNode\",components:{ElCheckbox:io,ElRadio:YM,NodeContent:dre,ElIcon:ft,Check:Wu,Loading:gl,ArrowRight:Da},props:{node:{type:Object,required:!0},menuId:String},emits:[\"expand\"],setup(e,{emit:t}){const n=ve(aw),r=De(\"cascader-node\"),a=x(()=>n.isHoverMenu),o=x(()=>n.config.multiple),i=x(()=>n.config.checkStrictly),l=x(()=>{var O;return(O=n.checkedNodes[0])==null?void 0:O.uid}),s=x(()=>e.node.isDisabled),c=x(()=>e.node.isLeaf),d=x(()=>i.value&&!c.value||!s.value),f=x(()=>v(n.expandingNode)),p=x(()=>i.value&&n.checkedNodes.some(v)),v=O=>{var T;const{level:_,uid:I}=e.node;return((T=O==null?void 0:O.pathNodes[_-1])==null?void 0:T.uid)===I},m=()=>{f.value||n.expandNode(e.node)},y=O=>{const{node:T}=e;O!==T.checked&&n.handleCheckChange(T,O)},b=()=>{n.lazyLoad(e.node,()=>{c.value||m()})},C=O=>{!a.value||(S(),!c.value&&t(\"expand\",O))},S=()=>{const{node:O}=e;!d.value||O.loading||(O.loaded?m():b())},w=()=>{a.value&&!c.value||(c.value&&!s.value&&!i.value&&!o.value?$(!0):S())},k=O=>{i.value?(y(O),e.node.loaded&&m()):$(O)},$=O=>{e.node.loaded?(y(O),!i.value&&m()):b()};return{panel:n,isHoverMenu:a,multiple:o,checkStrictly:i,checkedNodeId:l,isDisabled:s,isLeaf:c,expandable:d,inExpandingPath:f,inCheckedPath:p,ns:r,handleHoverExpand:C,handleExpand:S,handleClick:w,handleCheck:$,handleSelectCheck:k}}}),hre=[\"id\",\"aria-haspopup\",\"aria-owns\",\"aria-expanded\",\"tabindex\"],pre=Z(\"span\",null,null,-1);function vre(e,t,n,r,a,o){const i=we(\"el-checkbox\"),l=we(\"el-radio\"),s=we(\"check\"),c=we(\"el-icon\"),d=we(\"node-content\"),f=we(\"loading\"),p=we(\"arrow-right\");return R(),X(\"li\",{id:`${e.menuId}-${e.node.uid}`,role:\"menuitem\",\"aria-haspopup\":!e.isLeaf,\"aria-owns\":e.isLeaf?null:e.menuId,\"aria-expanded\":e.inExpandingPath,tabindex:e.expandable?-1:void 0,class:U([e.ns.b(),e.ns.is(\"selectable\",e.checkStrictly),e.ns.is(\"active\",e.node.checked),e.ns.is(\"disabled\",!e.expandable),e.inExpandingPath&&\"in-active-path\",e.inCheckedPath&&\"in-checked-path\"]),onMouseenter:t[2]||(t[2]=(...v)=>e.handleHoverExpand&&e.handleHoverExpand(...v)),onFocus:t[3]||(t[3]=(...v)=>e.handleHoverExpand&&e.handleHoverExpand(...v)),onClick:t[4]||(t[4]=(...v)=>e.handleClick&&e.handleClick(...v))},[se(\" prefix \"),e.multiple?(R(),fe(i,{key:0,\"model-value\":e.node.checked,indeterminate:e.node.indeterminate,disabled:e.isDisabled,onClick:t[0]||(t[0]=dt(()=>{},[\"stop\"])),\"onUpdate:modelValue\":e.handleSelectCheck},null,8,[\"model-value\",\"indeterminate\",\"disabled\",\"onUpdate:modelValue\"])):e.checkStrictly?(R(),fe(l,{key:1,\"model-value\":e.checkedNodeId,label:e.node.uid,disabled:e.isDisabled,\"onUpdate:modelValue\":e.handleSelectCheck,onClick:t[1]||(t[1]=dt(()=>{},[\"stop\"]))},{default:re(()=>[se(`\n        Add an empty element to avoid render label,\n        do not use empty fragment here for https://github.com/vuejs/vue-next/pull/2485\n      `),pre]),_:1},8,[\"model-value\",\"label\",\"disabled\",\"onUpdate:modelValue\"])):e.isLeaf&&e.node.checked?(R(),fe(c,{key:2,class:U(e.ns.e(\"prefix\"))},{default:re(()=>[g(s)]),_:1},8,[\"class\"])):se(\"v-if\",!0),se(\" content \"),g(d),se(\" postfix \"),e.isLeaf?se(\"v-if\",!0):(R(),X(Fe,{key:3},[e.node.loading?(R(),fe(c,{key:0,class:U([e.ns.is(\"loading\"),e.ns.e(\"postfix\")])},{default:re(()=>[g(f)]),_:1},8,[\"class\"])):(R(),fe(c,{key:1,class:U([\"arrow-right\",e.ns.e(\"postfix\")])},{default:re(()=>[g(p)]),_:1},8,[\"class\"]))],2112))],42,hre)}var mre=Ae(fre,[[\"render\",vre],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/cascader-panel/src/node.vue\"]]);const gre=G({name:\"ElCascaderMenu\",components:{Loading:gl,ElIcon:ft,ElScrollbar:xi,ElCascaderNode:mre},props:{nodes:{type:Array,required:!0},index:{type:Number,required:!0}},setup(e){const t=$t(),n=De(\"cascader-menu\"),{t:r}=ln(),a=Pf();let o=null,i=null;const l=ve(aw),s=H(null),c=x(()=>!e.nodes.length),d=x(()=>!l.initialLoaded),f=x(()=>`cascader-menu-${a}-${e.index}`),p=b=>{o=b.target},v=b=>{if(!(!l.isHoverMenu||!o||!s.value))if(o.contains(b.target)){m();const C=t.vnode.el,{left:S}=C.getBoundingClientRect(),{offsetWidth:w,offsetHeight:k}=C,$=b.clientX-S,O=o.offsetTop,T=O+o.offsetHeight;s.value.innerHTML=`\n          <path style=\"pointer-events: auto;\" fill=\"transparent\" d=\"M${$} ${O} L${w} 0 V${O} Z\" />\n          <path style=\"pointer-events: auto;\" fill=\"transparent\" d=\"M${$} ${T} L${w} ${k} V${T} Z\" />\n        `}else i||(i=window.setTimeout(y,l.config.hoverThreshold))},m=()=>{!i||(clearTimeout(i),i=null)},y=()=>{!s.value||(s.value.innerHTML=\"\",m())};return{ns:n,panel:l,hoverZone:s,isEmpty:c,isLoading:d,menuId:f,t:r,handleExpand:p,handleMouseMove:v,clearHoverZone:y}}});function yre(e,t,n,r,a,o){const i=we(\"el-cascader-node\"),l=we(\"loading\"),s=we(\"el-icon\"),c=we(\"el-scrollbar\");return R(),fe(c,{key:e.menuId,tag:\"ul\",role:\"menu\",class:U(e.ns.b()),\"wrap-class\":e.ns.e(\"wrap\"),\"view-class\":[e.ns.e(\"list\"),e.ns.is(\"empty\",e.isEmpty)],onMousemove:e.handleMouseMove,onMouseleave:e.clearHoverZone},{default:re(()=>{var d;return[(R(!0),X(Fe,null,Rt(e.nodes,f=>(R(),fe(i,{key:f.uid,node:f,\"menu-id\":e.menuId,onExpand:e.handleExpand},null,8,[\"node\",\"menu-id\",\"onExpand\"]))),128)),e.isLoading?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"empty-text\"))},[g(s,{size:\"14\",class:U(e.ns.is(\"loading\"))},{default:re(()=>[g(l)]),_:1},8,[\"class\"]),yt(\" \"+Me(e.t(\"el.cascader.loading\")),1)],2)):e.isEmpty?(R(),X(\"div\",{key:1,class:U(e.ns.e(\"empty-text\"))},Me(e.t(\"el.cascader.noData\")),3)):(d=e.panel)!=null&&d.isHoverMenu?(R(),X(\"svg\",{key:2,ref:\"hoverZone\",class:U(e.ns.e(\"hover-zone\"))},null,2)):se(\"v-if\",!0)]}),_:1},8,[\"class\",\"wrap-class\",\"view-class\",\"onMousemove\",\"onMouseleave\"])}var bre=Ae(gre,[[\"render\",yre],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/cascader-panel/src/menu.vue\"]]),ow=(e=>(e.CLICK=\"click\",e.HOVER=\"hover\",e))(ow||{});let Cre=0;const wre=e=>{const t=[e];let{parent:n}=e;for(;n;)t.unshift(n),n=n.parent;return t};class Ju{constructor(t,n,r,a=!1){this.data=t,this.config=n,this.parent=r,this.root=a,this.uid=Cre++,this.checked=!1,this.indeterminate=!1,this.loading=!1;const{value:o,label:i,children:l}=n,s=t[l],c=wre(this);this.level=a?0:r?r.level+1:1,this.value=t[o],this.label=t[i],this.pathNodes=c,this.pathValues=c.map(d=>d.value),this.pathLabels=c.map(d=>d.label),this.childrenData=s,this.children=(s||[]).map(d=>new Ju(d,n,this)),this.loaded=!n.lazy||this.isLeaf||!Kd(s)}get isDisabled(){const{data:t,parent:n,config:r}=this,{disabled:a,checkStrictly:o}=r;return(Ct(a)?a(t,this):!!t[a])||!o&&(n==null?void 0:n.isDisabled)}get isLeaf(){const{data:t,config:n,childrenData:r,loaded:a}=this,{lazy:o,leaf:i}=n,l=Ct(i)?i(t,this):t[i];return sa(l)?o&&!a?!1:!(Array.isArray(r)&&r.length):!!l}get valueByOption(){return this.config.emitPath?this.pathValues:this.value}appendChild(t){const{childrenData:n,children:r}=this,a=new Ju(t,this.config,this);return Array.isArray(n)?n.push(t):this.childrenData=[t],r.push(a),a}calcText(t,n){const r=t?this.pathLabels.join(n):this.label;return this.text=r,r}broadcast(t,...n){const r=`onParent${ia(t)}`;this.children.forEach(a=>{a&&(a.broadcast(t,...n),a[r]&&a[r](...n))})}emit(t,...n){const{parent:r}=this,a=`onChild${ia(t)}`;r&&(r[a]&&r[a](...n),r.emit(t,...n))}onParentCheck(t){this.isDisabled||this.setCheckState(t)}onChildCheck(){const{children:t}=this,n=t.filter(a=>!a.isDisabled),r=n.length?n.every(a=>a.checked):!1;this.setCheckState(r)}setCheckState(t){const n=this.children.length,r=this.children.reduce((a,o)=>{const i=o.checked?1:o.indeterminate?.5:0;return a+i},0);this.checked=this.loaded&&this.children.every(a=>a.loaded&&a.checked)&&t,this.indeterminate=this.loaded&&r!==n&&r>0}doCheck(t){if(this.checked===t)return;const{checkStrictly:n,multiple:r}=this.config;n||!r?this.checked=t:(this.broadcast(\"check\",t),this.setCheckState(t),this.emit(\"check\"))}}const M0=(e,t)=>e.reduce((n,r)=>(r.isLeaf?n.push(r):(!t&&n.push(r),n=n.concat(M0(r.children,t))),n),[]);class D4{constructor(t,n){this.config=n;const r=(t||[]).map(a=>new Ju(a,this.config));this.nodes=r,this.allNodes=M0(r,!1),this.leafNodes=M0(r,!0)}getNodes(){return this.nodes}getFlattedNodes(t){return t?this.leafNodes:this.allNodes}appendNode(t,n){const r=n?n.appendChild(t):new Ju(t,this.config);n||this.nodes.push(r),this.allNodes.push(r),r.isLeaf&&this.leafNodes.push(r)}appendNodes(t,n){t.forEach(r=>this.appendNode(r,n))}getNodeByValue(t,n=!1){return!t&&t!==0?null:this.getFlattedNodes(n).find(a=>er(a.value,t)||er(a.pathValues,t))||null}getSameNode(t){return t&&this.getFlattedNodes(!1).find(({value:r,level:a})=>er(t.value,r)&&t.level===a)||null}}const qM={modelValue:[Number,String,Array],options:{type:Array,default:()=>[]},props:{type:Object,default:()=>({})}},Sre={expandTrigger:ow.CLICK,multiple:!1,checkStrictly:!1,emitPath:!0,lazy:!1,lazyLoad:Qt,value:\"value\",label:\"label\",children:\"children\",leaf:\"leaf\",disabled:\"disabled\",hoverThreshold:500},kre=e=>x(()=>Te(Te({},Sre),e.props)),R4=e=>{if(!e)return 0;const t=e.id.split(\"-\");return Number(t[t.length-2])},$re=e=>{if(!e)return;const t=e.querySelector(\"input\");t?t.click():nE(e)&&e.click()},Ore=(e,t)=>{const n=t.slice(0),r=n.map(o=>o.uid),a=e.reduce((o,i)=>{const l=r.indexOf(i.uid);return l>-1&&(o.push(i),n.splice(l,1),r.splice(l,1)),o},[]);return a.push(...n),a},Pre=G({name:\"ElCascaderPanel\",components:{ElCascaderMenu:bre},props:Ke(Te({},qM),{border:{type:Boolean,default:!0},renderLabel:Function}),emits:[Pt,ir,\"close\",\"expand-change\"],setup(e,{emit:t,slots:n}){let r=!1;const a=De(\"cascader\"),o=kre(e);let i=null;const l=H(!0),s=H([]),c=H(null),d=H([]),f=H(null),p=H([]),v=x(()=>o.value.expandTrigger===ow.HOVER),m=x(()=>e.renderLabel||n.default),y=()=>{const{options:F}=e,N=o.value;r=!1,i=new D4(F,N),d.value=[i.getNodes()],N.lazy&&Kd(e.options)?(l.value=!1,b(void 0,D=>{D&&(i=new D4(D,N),d.value=[i.getNodes()]),l.value=!0,_(!1,!0)})):_(!1,!0)},b=(F,N)=>{const D=o.value;F=F||new Ju({},D,void 0,!0),F.loading=!0;const z=B=>{const M=F,E=M.root?null:M;B&&(i==null||i.appendNodes(B,E)),M.loading=!1,M.loaded=!0,M.childrenData=M.childrenData||[],N&&N(B)};D.lazyLoad(F,z)},C=(F,N)=>{var D;const{level:z}=F,B=d.value.slice(0,z);let M;F.isLeaf?M=F.pathNodes[z-2]:(M=F,B.push(F.children)),((D=f.value)==null?void 0:D.uid)!==(M==null?void 0:M.uid)&&(f.value=F,d.value=B,!N&&t(\"expand-change\",(F==null?void 0:F.pathValues)||[]))},S=(F,N,D=!0)=>{const{checkStrictly:z,multiple:B}=o.value,M=p.value[0];r=!0,!B&&(M==null||M.doCheck(!1)),F.doCheck(N),T(),D&&!B&&!z&&t(\"close\"),!D&&!B&&!z&&w(F)},w=F=>{!F||(F=F.parent,w(F),F&&C(F))},k=F=>i==null?void 0:i.getFlattedNodes(F),$=F=>{var N;return(N=k(F))==null?void 0:N.filter(D=>D.checked!==!1)},O=()=>{p.value.forEach(F=>F.doCheck(!1)),T()},T=()=>{var F;const{checkStrictly:N,multiple:D}=o.value,z=p.value,B=$(!N),M=Ore(z,B),E=M.map(K=>K.valueByOption);p.value=M,c.value=D?E:(F=E[0])!=null?F:null},_=(F=!1,N=!1)=>{const{modelValue:D}=e,{lazy:z,multiple:B,checkStrictly:M}=o.value,E=!M;if(!(!l.value||r||!N&&er(D,c.value)))if(z&&!F){const W=J$(iW(rs(D))).map(Y=>i==null?void 0:i.getNodeByValue(Y)).filter(Y=>!!Y&&!Y.loaded&&!Y.loading);W.length?W.forEach(Y=>{b(Y,()=>_(!1,N))}):_(!0,N)}else{const K=B?rs(D):[D],W=J$(K.map(Y=>i==null?void 0:i.getNodeByValue(Y,E)));I(W,!1),c.value=D}},I=(F,N=!0)=>{const{checkStrictly:D}=o.value,z=p.value,B=F.filter(K=>!!K&&(D||K.isLeaf)),M=i==null?void 0:i.getSameNode(f.value),E=N&&M||B[0];E?E.pathNodes.forEach(K=>C(K,!0)):f.value=null,z.forEach(K=>K.doCheck(!1)),B.forEach(K=>K.doCheck(!0)),p.value=B,Ne(L)},L=()=>{!Bt||s.value.forEach(F=>{const N=F==null?void 0:F.$el;if(N){const D=N.querySelector(`.${a.namespace.value}-scrollbar__wrap`),z=N.querySelector(`.${a.b(\"node\")}.${a.is(\"active\")}`)||N.querySelector(`.${a.b(\"node\")}.in-active-path`);lE(D,z)}})},j=F=>{const N=F.target,{code:D}=F;switch(D){case Ge.up:case Ge.down:{F.preventDefault();const z=D===Ge.up?-1:1;up(rE(N,z,`.${a.b(\"node\")}[tabindex=\"-1\"]`));break}case Ge.left:{F.preventDefault();const z=s.value[R4(N)-1],B=z==null?void 0:z.$el.querySelector(`.${a.b(\"node\")}[aria-expanded=\"true\"]`);up(B);break}case Ge.right:{F.preventDefault();const z=s.value[R4(N)+1],B=z==null?void 0:z.$el.querySelector(`.${a.b(\"node\")}[tabindex=\"-1\"]`);up(B);break}case Ge.enter:$re(N);break;case Ge.esc:case Ge.tab:t(\"close\");break}};return ot(aw,bt({config:o,expandingNode:f,checkedNodes:p,isHoverMenu:v,initialLoaded:l,renderLabelFn:m,lazyLoad:b,expandNode:C,handleCheckChange:S})),ce([o,()=>e.options],y,{deep:!0,immediate:!0}),ce(()=>e.modelValue,()=>{r=!1,_()}),ce(c,F=>{er(F,e.modelValue)||(t(Pt,F),t(ir,F))}),wm(()=>s.value=[]),et(()=>!Kd(e.modelValue)&&_()),{ns:a,menuList:s,menus:d,checkedNodes:p,handleKeyDown:j,handleCheckChange:S,getFlattedNodes:k,getCheckedNodes:$,clearCheckedNodes:O,calculateCheckedValue:T,scrollToExpandingNode:L}}});function Tre(e,t,n,r,a,o){const i=we(\"el-cascader-menu\");return R(),X(\"div\",{class:U([e.ns.b(\"panel\"),e.ns.is(\"bordered\",e.border)]),onKeydown:t[0]||(t[0]=(...l)=>e.handleKeyDown&&e.handleKeyDown(...l))},[(R(!0),X(Fe,null,Rt(e.menus,(l,s)=>(R(),fe(i,{key:s,ref_for:!0,ref:c=>e.menuList[s]=c,index:s,nodes:[...l]},null,8,[\"index\",\"nodes\"]))),128))],34)}var mp=Ae(Pre,[[\"render\",Tre],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/cascader-panel/src/index.vue\"]]);mp.install=e=>{e.component(mp.name,mp)};const GM=mp,xre=GM,iw=Ze({closable:Boolean,type:{type:String,values:[\"success\",\"info\",\"warning\",\"danger\",\"\"],default:\"\"},hit:Boolean,disableTransitions:Boolean,color:{type:String,default:\"\"},size:{type:String,values:Bo,default:\"\"},effect:{type:String,values:[\"dark\",\"light\",\"plain\"],default:\"light\"},round:Boolean}),_re={close:e=>e instanceof MouseEvent,click:e=>e instanceof MouseEvent},Ere={name:\"ElTag\"},Mre=G(Ke(Te({},Ere),{props:iw,emits:_re,setup(e,{emit:t}){const n=e,r=Gn(),a=De(\"tag\"),o=x(()=>{const{type:s,hit:c,effect:d,closable:f,round:p}=n;return[a.b(),a.is(\"closable\",f),a.m(s),a.m(r.value),a.m(d),a.is(\"hit\",c),a.is(\"round\",p)]}),i=s=>{s.stopPropagation(),t(\"close\",s)},l=s=>{t(\"click\",s)};return(s,c)=>s.disableTransitions?(R(),fe(Vn,{key:1,name:`${A(a).namespace.value}-zoom-in-center`},{default:re(()=>[Z(\"span\",{class:U(A(o)),style:Xe({backgroundColor:s.color}),onClick:l},[Z(\"span\",{class:U(A(a).e(\"content\"))},[Oe(s.$slots,\"default\")],2),s.closable?(R(),fe(A(ft),{key:0,class:U(A(a).e(\"close\")),onClick:i},{default:re(()=>[g(A(Ma))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],6)]),_:3},8,[\"name\"])):(R(),X(\"span\",{key:0,class:U(A(o)),style:Xe({backgroundColor:s.color}),onClick:l},[Z(\"span\",{class:U(A(a).e(\"content\"))},[Oe(s.$slots,\"default\")],2),s.closable?(R(),fe(A(ft),{key:0,class:U(A(a).e(\"close\")),onClick:i},{default:re(()=>[g(A(Ma))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],6))}}));var Ire=Ae(Mre,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tag/src/tag.vue\"]]);const Gm=xt(Ire),Nre=40,Are={large:36,default:32,small:28},Dre={modifiers:[{name:\"arrowPosition\",enabled:!0,phase:\"main\",fn:({state:e})=>{const{modifiersData:t,placement:n}=e;[\"right\",\"left\",\"bottom\",\"top\"].includes(n)||(t.arrow.x=35)},requires:[\"arrow\"]}]},L4=\"ElCascader\",Rre=G({name:L4,components:{ElCascaderPanel:GM,ElInput:Ra,ElTooltip:Ur,ElScrollbar:xi,ElTag:Gm,ElIcon:ft,CircleClose:gi,Check:Wu,ArrowDown:_s},directives:{Clickoutside:Is},props:Ke(Te({},qM),{size:{type:String,validator:va},placeholder:{type:String},disabled:Boolean,clearable:Boolean,filterable:Boolean,filterMethod:{type:Function,default:(e,t)=>e.text.includes(t)},separator:{type:String,default:\" / \"},showAllLevels:{type:Boolean,default:!0},collapseTags:Boolean,collapseTagsTooltip:{type:Boolean,default:!1},debounce:{type:Number,default:300},beforeFilter:{type:Function,default:()=>!0},popperClass:{type:String,default:\"\"},popperAppendToBody:{type:Boolean,default:void 0},teleported:mr.teleported,tagType:Ke(Te({},iw.type),{default:\"info\"})}),emits:[Pt,ir,\"focus\",\"blur\",\"visible-change\",\"expand-change\",\"remove-tag\"],setup(e,{emit:t}){let n=0,r=0;const{compatTeleported:a}=Oc(L4,\"popperAppendToBody\"),o=De(\"cascader\"),i=De(\"input\"),{t:l}=ln(),s=ve(ga,{}),c=ve(Ia,{}),d=H(null),f=H(null),p=H(null),v=H(null),m=H(null),y=H(!1),b=H(!1),C=H(!1),S=H(\"\"),w=H(\"\"),k=H([]),$=H([]),O=H([]),T=H(!1),_=x(()=>e.disabled||s.disabled),I=x(()=>e.placeholder||l(\"el.cascader.placeholder\")),L=Gn(),j=x(()=>[\"small\"].includes(L.value)?\"small\":\"default\"),F=x(()=>!!e.props.multiple),N=x(()=>!e.filterable||F.value),D=x(()=>F.value?w.value:S.value),z=x(()=>{var ye;return((ye=v.value)==null?void 0:ye.checkedNodes)||[]}),B=x(()=>!e.clearable||_.value||C.value||!b.value?!1:!!z.value.length),M=x(()=>{const{showAllLevels:ye,separator:pe}=e,ue=z.value;return ue.length?F.value?\" \":ue[0].calcText(ye,pe):\"\"}),E=x({get(){return e.modelValue},set(ye){var pe;t(Pt,ye),t(ir,ye),(pe=c.validate)==null||pe.call(c,\"change\").catch(ue=>void 0)}}),K=x(()=>{var ye,pe;return(pe=(ye=d.value)==null?void 0:ye.popperRef)==null?void 0:pe.contentRef}),W=ye=>{var pe,ue,Ce;if(!_.value&&(ye=ye!=null?ye:!y.value,ye!==y.value)){if(y.value=ye,(ue=(pe=f.value)==null?void 0:pe.input)==null||ue.setAttribute(\"aria-expanded\",`${ye}`),ye)Y(),Ne((Ce=v.value)==null?void 0:Ce.scrollToExpandingNode);else if(e.filterable){const{value:je}=M;S.value=je,w.value=je}t(\"visible-change\",ye)}},Y=()=>{Ne(()=>{var ye;(ye=d.value)==null||ye.updatePopper()})},q=()=>{C.value=!1},J=ye=>{const{showAllLevels:pe,separator:ue}=e;return{node:ye,key:ye.uid,text:ye.calcText(pe,ue),hitState:!1,closable:!_.value&&!ye.isDisabled,isCollapseTag:!1}},ne=ye=>{var pe;const ue=ye.node;ue.doCheck(!1),(pe=v.value)==null||pe.calculateCheckedValue(),t(\"remove-tag\",ue.valueByOption)},oe=()=>{if(!F.value)return;const ye=z.value,pe=[],ue=[];if(ye.forEach(Ce=>ue.push(J(Ce))),$.value=ue,ye.length){const[Ce,...je]=ye,ee=je.length;pe.push(J(Ce)),ee&&(e.collapseTags?pe.push({key:-1,text:`+ ${ee}`,closable:!1,isCollapseTag:!0}):je.forEach(me=>pe.push(J(me))))}k.value=pe},Q=()=>{var ye,pe;const{filterMethod:ue,showAllLevels:Ce,separator:je}=e,ee=(pe=(ye=v.value)==null?void 0:ye.getFlattedNodes(!e.props.checkStrictly))==null?void 0:pe.filter(me=>me.isDisabled?!1:(me.calcText(Ce,je),ue(me,D.value)));F.value&&(k.value.forEach(me=>{me.hitState=!1}),$.value.forEach(me=>{me.hitState=!1})),C.value=!0,O.value=ee,Y()},ae=()=>{var ye;let pe;C.value&&m.value?pe=m.value.$el.querySelector(`.${o.e(\"suggestion-item\")}`):pe=(ye=v.value)==null?void 0:ye.$el.querySelector(`.${o.b(\"node\")}[tabindex=\"-1\"]`),pe&&(pe.focus(),!C.value&&pe.click())},de=()=>{var ye,pe;const ue=(ye=f.value)==null?void 0:ye.input,Ce=p.value,je=(pe=m.value)==null?void 0:pe.$el;if(!(!Bt||!ue)){if(je){const ee=je.querySelector(`.${o.e(\"suggestion-list\")}`);ee.style.minWidth=`${ue.offsetWidth}px`}if(Ce){const{offsetHeight:ee}=Ce,me=k.value.length>0?`${Math.max(ee+6,n)}px`:`${n}px`;ue.style.height=me,Y()}}},be=ye=>{var pe;return(pe=v.value)==null?void 0:pe.getCheckedNodes(ye)},Ee=ye=>{Y(),t(\"expand-change\",ye)},Pe=ye=>{var pe;const ue=(pe=ye.target)==null?void 0:pe.value;if(ye.type===\"compositionend\")T.value=!1,Ne(()=>Ie(ue));else{const Ce=ue[ue.length-1]||\"\";T.value=!zm(Ce)}},Be=ye=>{if(!T.value)switch(ye.code){case Ge.enter:W();break;case Ge.down:W(!0),Ne(ae),ye.preventDefault();break;case Ge.esc:case Ge.tab:W(!1);break}},te=()=>{var ye;(ye=v.value)==null||ye.clearCheckedNodes(),W(!1)},ie=ye=>{var pe,ue;const{checked:Ce}=ye;F.value?(pe=v.value)==null||pe.handleCheckChange(ye,!Ce,!1):(!Ce&&((ue=v.value)==null||ue.handleCheckChange(ye,!0,!1)),W(!1))},ge=ye=>{const pe=ye.target,{code:ue}=ye;switch(ue){case Ge.up:case Ge.down:{const Ce=ue===Ge.up?-1:1;up(rE(pe,Ce,`.${o.e(\"suggestion-item\")}[tabindex=\"-1\"]`));break}case Ge.enter:pe.click();break;case Ge.esc:case Ge.tab:W(!1);break}},ke=()=>{const ye=k.value,pe=ye[ye.length-1];r=w.value?0:r+1,!(!pe||!r)&&(pe.hitState?ne(pe):pe.hitState=!0)},xe=Yn(()=>{const{value:ye}=D;if(!ye)return;const pe=e.beforeFilter(ye);hs(pe)?pe.then(Q).catch(()=>{}):pe!==!1?Q():q()},e.debounce),Ie=(ye,pe)=>{!y.value&&W(!0),!(pe!=null&&pe.isComposing)&&(ye?xe():q())};return ce(C,Y),ce([z,_],oe),ce(k,()=>{Ne(()=>de())}),ce(M,ye=>S.value=ye,{immediate:!0}),et(()=>{var ye;const pe=(ye=f.value)==null?void 0:ye.$el;n=(pe==null?void 0:pe.offsetHeight)||Are[L.value]||Nre,wc(pe,de)}),Lt(()=>{var ye;Sc((ye=f.value)==null?void 0:ye.$el,de)}),{popperOptions:Dre,tooltipRef:d,popperPaneRef:K,input:f,tagWrapper:p,panel:v,suggestionPanel:m,popperVisible:y,inputHover:b,inputPlaceholder:I,filtering:C,presentText:M,checkedValue:E,inputValue:S,searchInputValue:w,presentTags:k,allPresentTags:$,suggestions:O,isDisabled:_,isOnComposition:T,realSize:L,tagSize:j,multiple:F,readonly:N,clearBtnVisible:B,compatTeleported:a,nsCascader:o,nsInput:i,t:l,togglePopperVisible:W,hideSuggestionPanel:q,deleteTag:ne,focusFirstNode:ae,getCheckedNodes:be,handleExpandChange:Ee,handleKeyDown:Be,handleComposition:Pe,handleClear:te,handleSuggestionClick:ie,handleSuggestionKeyDown:ge,handleDelete:ke,handleInput:Ie}}}),Lre={key:0},Fre={class:\"el-cascader__collapse-tags\"},Bre=[\"placeholder\"],Vre=[\"onClick\"];function zre(e,t,n,r,a,o){const i=we(\"circle-close\"),l=we(\"el-icon\"),s=we(\"arrow-down\"),c=we(\"el-input\"),d=we(\"el-tag\"),f=we(\"el-tooltip\"),p=we(\"el-cascader-panel\"),v=we(\"check\"),m=we(\"el-scrollbar\"),y=pa(\"clickoutside\");return R(),fe(f,{ref:\"tooltipRef\",visible:e.popperVisible,\"onUpdate:visible\":t[17]||(t[17]=b=>e.popperVisible=b),teleported:e.compatTeleported,\"popper-class\":[e.nsCascader.e(\"dropdown\"),e.popperClass],\"popper-options\":e.popperOptions,\"fallback-placements\":[\"bottom-start\",\"bottom\",\"top-start\",\"top\",\"right\",\"left\"],\"stop-popper-mouse-event\":!1,\"gpu-acceleration\":!1,placement:\"bottom-start\",transition:`${e.nsCascader.namespace.value}-zoom-in-top`,effect:\"light\",pure:\"\",persistent:\"\",onHide:e.hideSuggestionPanel},{default:re(()=>[at((R(),X(\"div\",{class:U([e.nsCascader.b(),e.nsCascader.m(e.realSize),e.nsCascader.is(\"disabled\",e.isDisabled),e.$attrs.class]),style:Xe(e.$attrs.style),onClick:t[11]||(t[11]=()=>e.togglePopperVisible(e.readonly?void 0:!0)),onKeydown:t[12]||(t[12]=(...b)=>e.handleKeyDown&&e.handleKeyDown(...b)),onMouseenter:t[13]||(t[13]=b=>e.inputHover=!0),onMouseleave:t[14]||(t[14]=b=>e.inputHover=!1)},[g(c,{ref:\"input\",modelValue:e.inputValue,\"onUpdate:modelValue\":t[1]||(t[1]=b=>e.inputValue=b),placeholder:e.inputPlaceholder,readonly:e.readonly,disabled:e.isDisabled,\"validate-event\":!1,size:e.realSize,class:U(e.nsCascader.is(\"focus\",e.popperVisible)),onCompositionstart:e.handleComposition,onCompositionupdate:e.handleComposition,onCompositionend:e.handleComposition,onFocus:t[2]||(t[2]=b=>e.$emit(\"focus\",b)),onBlur:t[3]||(t[3]=b=>e.$emit(\"blur\",b)),onInput:e.handleInput},{suffix:re(()=>[e.clearBtnVisible?(R(),fe(l,{key:\"clear\",class:U([e.nsInput.e(\"icon\"),\"icon-circle-close\"]),onClick:dt(e.handleClear,[\"stop\"])},{default:re(()=>[g(i)]),_:1},8,[\"class\",\"onClick\"])):(R(),fe(l,{key:\"arrow-down\",class:U([e.nsInput.e(\"icon\"),\"icon-arrow-down\",e.nsCascader.is(\"reverse\",e.popperVisible)]),onClick:t[0]||(t[0]=dt(b=>e.togglePopperVisible(),[\"stop\"]))},{default:re(()=>[g(s)]),_:1},8,[\"class\"]))]),_:1},8,[\"modelValue\",\"placeholder\",\"readonly\",\"disabled\",\"size\",\"class\",\"onCompositionstart\",\"onCompositionupdate\",\"onCompositionend\",\"onInput\"]),e.multiple?(R(),X(\"div\",{key:0,ref:\"tagWrapper\",class:U(e.nsCascader.e(\"tags\"))},[(R(!0),X(Fe,null,Rt(e.presentTags,b=>(R(),fe(d,{key:b.key,type:e.tagType,size:e.tagSize,hit:b.hitState,closable:b.closable,\"disable-transitions\":\"\",onClose:C=>e.deleteTag(b)},{default:re(()=>[b.isCollapseTag===!1?(R(),X(\"span\",Lre,Me(b.text),1)):(R(),fe(f,{key:1,teleported:!1,disabled:e.popperVisible||!e.collapseTagsTooltip,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],placement:\"bottom\",effect:\"light\"},{default:re(()=>[Z(\"span\",null,Me(b.text),1)]),content:re(()=>[Z(\"div\",Fre,[(R(!0),X(Fe,null,Rt(e.allPresentTags,(C,S)=>(R(),X(\"div\",{key:S,class:\"el-cascader__collapse-tag\"},[(R(),fe(d,{key:C.key,class:\"in-tooltip\",type:e.tagType,size:e.tagSize,hit:C.hitState,closable:C.closable,\"disable-transitions\":\"\",onClose:w=>e.deleteTag(C)},{default:re(()=>[Z(\"span\",null,Me(C.text),1)]),_:2},1032,[\"type\",\"size\",\"hit\",\"closable\",\"onClose\"]))]))),128))])]),_:2},1032,[\"disabled\"]))]),_:2},1032,[\"type\",\"size\",\"hit\",\"closable\",\"onClose\"]))),128)),e.filterable&&!e.isDisabled?at((R(),X(\"input\",{key:0,\"onUpdate:modelValue\":t[4]||(t[4]=b=>e.searchInputValue=b),type:\"text\",class:U(e.nsCascader.e(\"search-input\")),placeholder:e.presentText?\"\":e.inputPlaceholder,onInput:t[5]||(t[5]=b=>e.handleInput(e.searchInputValue,b)),onClick:t[6]||(t[6]=dt(b=>e.togglePopperVisible(!0),[\"stop\"])),onKeydown:t[7]||(t[7]=It((...b)=>e.handleDelete&&e.handleDelete(...b),[\"delete\"])),onCompositionstart:t[8]||(t[8]=(...b)=>e.handleComposition&&e.handleComposition(...b)),onCompositionupdate:t[9]||(t[9]=(...b)=>e.handleComposition&&e.handleComposition(...b)),onCompositionend:t[10]||(t[10]=(...b)=>e.handleComposition&&e.handleComposition(...b))},null,42,Bre)),[[fC,e.searchInputValue]]):se(\"v-if\",!0)],2)):se(\"v-if\",!0)],38)),[[y,()=>e.togglePopperVisible(!1),e.popperPaneRef]])]),content:re(()=>[at(g(p,{ref:\"panel\",modelValue:e.checkedValue,\"onUpdate:modelValue\":t[15]||(t[15]=b=>e.checkedValue=b),options:e.options,props:e.props,border:!1,\"render-label\":e.$slots.default,onExpandChange:e.handleExpandChange,onClose:t[16]||(t[16]=b=>e.$nextTick(()=>e.togglePopperVisible(!1)))},null,8,[\"modelValue\",\"options\",\"props\",\"render-label\",\"onExpandChange\"]),[[_t,!e.filtering]]),e.filterable?at((R(),fe(m,{key:0,ref:\"suggestionPanel\",tag:\"ul\",class:U(e.nsCascader.e(\"suggestion-panel\")),\"view-class\":e.nsCascader.e(\"suggestion-list\"),onKeydown:e.handleSuggestionKeyDown},{default:re(()=>[e.suggestions.length?(R(!0),X(Fe,{key:0},Rt(e.suggestions,b=>(R(),X(\"li\",{key:b.uid,class:U([e.nsCascader.e(\"suggestion-item\"),e.nsCascader.is(\"checked\",b.checked)]),tabindex:-1,onClick:C=>e.handleSuggestionClick(b)},[Z(\"span\",null,Me(b.text),1),b.checked?(R(),fe(l,{key:0},{default:re(()=>[g(v)]),_:1})):se(\"v-if\",!0)],10,Vre))),128)):Oe(e.$slots,\"empty\",{key:1},()=>[Z(\"li\",{class:U(e.nsCascader.e(\"empty-text\"))},Me(e.t(\"el.cascader.noMatch\")),3)])]),_:3},8,[\"class\",\"view-class\",\"onKeydown\"])),[[_t,e.filtering]]):se(\"v-if\",!0)]),_:3},8,[\"visible\",\"teleported\",\"popper-class\",\"popper-options\",\"transition\",\"onHide\"])}var gp=Ae(Rre,[[\"render\",zre],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/cascader/src/index.vue\"]]);gp.install=e=>{e.component(gp.name,gp)};const Hre=gp,jre=Hre,Kre=Ze({checked:{type:Boolean,default:!1}}),Wre={\"update:checked\":e=>yr(e),change:e=>yr(e)},Ure={name:\"ElCheckTag\"},Yre=G(Ke(Te({},Ure),{props:Kre,emits:Wre,setup(e,{emit:t}){const n=e,r=De(\"check-tag\"),a=()=>{const o=!n.checked;t(\"change\",o),t(\"update:checked\",o)};return(o,i)=>(R(),X(\"span\",{class:U([A(r).b(),A(r).is(\"checked\",o.checked)]),onClick:a},[Oe(o.$slots,\"default\")],2))}}));var qre=Ae(Yre,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/check-tag/src/check-tag.vue\"]]);const Gre=xt(qre),Xre=Ze({tag:{type:String,default:\"div\"},span:{type:Number,default:24},offset:{type:Number,default:0},pull:{type:Number,default:0},push:{type:Number,default:0},xs:{type:Le([Number,Object]),default:()=>xn({})},sm:{type:Le([Number,Object]),default:()=>xn({})},md:{type:Le([Number,Object]),default:()=>xn({})},lg:{type:Le([Number,Object]),default:()=>xn({})},xl:{type:Le([Number,Object]),default:()=>xn({})}});var Zre=G({name:\"ElCol\",props:Xre,setup(e,{slots:t}){const{gutter:n}=ve(xE,{gutter:x(()=>0)}),r=De(\"col\"),a=x(()=>n.value?{paddingLeft:`${n.value/2}px`,paddingRight:`${n.value/2}px`}:{}),o=x(()=>{const i=[];return[\"span\",\"offset\",\"pull\",\"push\"].forEach(c=>{const d=e[c];typeof d==\"number\"&&(c===\"span\"?i.push(r.b(`${e[c]}`)):d>0&&i.push(r.b(`${c}-${e[c]}`)))}),[\"xs\",\"sm\",\"md\",\"lg\",\"xl\"].forEach(c=>{if(typeof e[c]==\"number\")i.push(r.b(`${c}-${e[c]}`));else if(typeof e[c]==\"object\"){const d=e[c];Object.keys(d).forEach(f=>{i.push(f!==\"span\"?r.b(`${c}-${f}-${d[f]}`):r.b(`${c}-${d[f]}`))})}}),n.value&&i.push(r.is(\"guttered\")),i});return()=>g(e.tag,{class:[r.b(),o.value],style:a.value},t)}});const Jre=xt(Zre),F4=e=>typeof Yt(e),Qre=Ze({accordion:Boolean,modelValue:{type:Le([Array,String,Number]),default:()=>xn([])}}),eae={[Pt]:F4,[ir]:F4},tae={name:\"ElCollapse\"},nae=G(Ke(Te({},tae),{props:Qre,emits:eae,setup(e,{expose:t,emit:n}){const r=e,a=De(\"collapse\"),o=H(Hd(r.modelValue)),i=s=>{o.value=s;const c=r.accordion?o.value[0]:o.value;n(Pt,c),n(ir,c)},l=s=>{if(r.accordion)i([(o.value[0]||o.value[0]===0)&&o.value[0]===s?\"\":s]);else{const c=[...o.value],d=c.indexOf(s);d>-1?c.splice(d,1):c.push(s),i(c)}};return ce(()=>r.modelValue,()=>o.value=Hd(r.modelValue),{deep:!0}),ot(kE,{activeNames:o,handleItemClick:l}),t({activeNames:o,setActiveNames:i}),(s,c)=>(R(),X(\"div\",{class:U(A(a).b()),role:\"tablist\",\"aria-multiselectable\":\"true\"},[Oe(s.$slots,\"default\")],2))}}));var rae=Ae(nae,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/collapse/src/collapse.vue\"]]);const aae=G({name:\"ElCollapseTransition\",setup(){return{ns:De(\"collapse-transition\"),on:{beforeEnter(t){t.dataset||(t.dataset={}),t.dataset.oldPaddingTop=t.style.paddingTop,t.dataset.oldPaddingBottom=t.style.paddingBottom,t.style.maxHeight=0,t.style.paddingTop=0,t.style.paddingBottom=0},enter(t){t.dataset.oldOverflow=t.style.overflow,t.scrollHeight!==0?(t.style.maxHeight=`${t.scrollHeight}px`,t.style.paddingTop=t.dataset.oldPaddingTop,t.style.paddingBottom=t.dataset.oldPaddingBottom):(t.style.maxHeight=0,t.style.paddingTop=t.dataset.oldPaddingTop,t.style.paddingBottom=t.dataset.oldPaddingBottom),t.style.overflow=\"hidden\"},afterEnter(t){t.style.maxHeight=\"\",t.style.overflow=t.dataset.oldOverflow},beforeLeave(t){t.dataset||(t.dataset={}),t.dataset.oldPaddingTop=t.style.paddingTop,t.dataset.oldPaddingBottom=t.style.paddingBottom,t.dataset.oldOverflow=t.style.overflow,t.style.maxHeight=`${t.scrollHeight}px`,t.style.overflow=\"hidden\"},leave(t){t.scrollHeight!==0&&(t.style.maxHeight=0,t.style.paddingTop=0,t.style.paddingBottom=0)},afterLeave(t){t.style.maxHeight=\"\",t.style.overflow=t.dataset.oldOverflow,t.style.paddingTop=t.dataset.oldPaddingTop,t.style.paddingBottom=t.dataset.oldPaddingBottom}}}}});function oae(e,t,n,r,a,o){return R(),fe(Vn,hn({name:e.ns.b()},aF(e.on)),{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},16,[\"name\"])}var yp=Ae(aae,[[\"render\",oae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/collapse-transition/src/collapse-transition.vue\"]]);yp.install=e=>{e.component(yp.name,yp)};const Xm=yp,iae=Xm,lae=Ze({title:{type:String,default:\"\"},name:{type:Le([String,Number]),default:()=>Pf()},disabled:Boolean}),sae=[\"aria-expanded\",\"aria-controls\",\"aria-describedby\"],uae=[\"id\",\"tabindex\",\"onKeypress\"],cae=[\"id\",\"aria-hidden\",\"aria-labelledby\"],dae={name:\"ElCollapseItem\"},fae=G(Ke(Te({},dae),{props:lae,setup(e,{expose:t}){const n=e,r=ve(kE),a=De(\"collapse\"),o=H(!1),i=H(!1),l=H(Pf()),s=x(()=>r==null?void 0:r.activeNames.value.includes(n.name)),c=()=>{setTimeout(()=>{i.value?i.value=!1:o.value=!0},50)},d=()=>{n.disabled||(r==null||r.handleItemClick(n.name),o.value=!1,i.value=!0)},f=()=>{r==null||r.handleItemClick(n.name)};return t({isActive:s}),(p,v)=>(R(),X(\"div\",{class:U([A(a).b(\"item\"),A(a).is(\"active\",A(s)),A(a).is(\"disabled\",p.disabled)])},[Z(\"div\",{role:\"tab\",\"aria-expanded\":A(s),\"aria-controls\":A(a).b(`content-${l.value}`),\"aria-describedby\":A(a).b(`content-${l.value}`)},[Z(\"div\",{id:A(a).b(`head-${l.value}`),class:U([A(a).be(\"item\",\"header\"),A(a).is(\"active\",A(s)),{focusing:o.value}]),role:\"button\",tabindex:p.disabled?-1:0,onClick:d,onKeypress:It(dt(f,[\"stop\",\"prevent\"]),[\"space\",\"enter\"]),onFocus:c,onBlur:v[0]||(v[0]=m=>o.value=!1)},[Oe(p.$slots,\"title\",{},()=>[yt(Me(p.title),1)]),g(A(ft),{class:U([A(a).be(\"item\",\"arrow\"),A(a).is(\"active\",A(s))])},{default:re(()=>[g(A(Da))]),_:1},8,[\"class\"])],42,uae)],8,sae),g(A(Xm),null,{default:re(()=>[at(Z(\"div\",{id:A(a).b(`content-${l.value}`),class:U(A(a).be(\"item\",\"wrap\")),role:\"tabpanel\",\"aria-hidden\":!A(s),\"aria-labelledby\":A(a).b(`head-${l.value}`)},[Z(\"div\",{class:U(A(a).be(\"item\",\"content\"))},[Oe(p.$slots,\"default\")],2)],10,cae),[[_t,A(s)]])]),_:3})],2))}}));var XM=Ae(fae,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/collapse/src/collapse-item.vue\"]]);const hae=xt(rae,{CollapseItem:XM}),pae=En(XM);let fy=!1;function Gd(e,t){if(!Bt)return;const n=function(o){var i;(i=t.drag)==null||i.call(t,o)},r=function(o){var i;Bn(document,\"mousemove\",n),Bn(document,\"mouseup\",r),Bn(document,\"touchmove\",n),Bn(document,\"touchend\",r),document.onselectstart=null,document.ondragstart=null,fy=!1,(i=t.end)==null||i.call(t,o)},a=function(o){var i;fy||(o.preventDefault(),document.onselectstart=()=>!1,document.ondragstart=()=>!1,gn(document,\"mousemove\",n),gn(document,\"mouseup\",r),gn(document,\"touchmove\",n),gn(document,\"touchend\",r),fy=!0,(i=t.start)==null||i.call(t,o))};gn(e,\"mousedown\",a),gn(e,\"touchstart\",a)}const vae=G({name:\"ElColorAlphaSlider\",props:{color:{type:Object,required:!0},vertical:{type:Boolean,default:!1}},setup(e){const t=$t(),n=Qn(null),r=Qn(null),a=H(0),o=H(0),i=H(null);ce(()=>e.color.get(\"alpha\"),()=>{p()}),ce(()=>e.color.value,()=>{p()});function l(){if(e.vertical)return 0;const v=t.vnode.el,m=e.color.get(\"alpha\");return v?Math.round(m*(v.offsetWidth-n.value.offsetWidth/2)/100):0}function s(){const v=t.vnode.el;if(!e.vertical)return 0;const m=e.color.get(\"alpha\");return v?Math.round(m*(v.offsetHeight-n.value.offsetHeight/2)/100):0}function c(){if(e.color&&e.color.value){const{r:v,g:m,b:y}=e.color.toRgb();return`linear-gradient(to right, rgba(${v}, ${m}, ${y}, 0) 0%, rgba(${v}, ${m}, ${y}, 1) 100%)`}return null}function d(v){v.target!==n.value&&f(v)}function f(v){const y=t.vnode.el.getBoundingClientRect(),{clientX:b,clientY:C}=AC(v);if(e.vertical){let S=C-y.top;S=Math.max(n.value.offsetHeight/2,S),S=Math.min(S,y.height-n.value.offsetHeight/2),e.color.set(\"alpha\",Math.round((S-n.value.offsetHeight/2)/(y.height-n.value.offsetHeight)*100))}else{let S=b-y.left;S=Math.max(n.value.offsetWidth/2,S),S=Math.min(S,y.width-n.value.offsetWidth/2),e.color.set(\"alpha\",Math.round((S-n.value.offsetWidth/2)/(y.width-n.value.offsetWidth)*100))}}function p(){a.value=l(),o.value=s(),i.value=c()}return et(()=>{const v={drag:m=>{f(m)},end:m=>{f(m)}};Gd(r.value,v),Gd(n.value,v),p()}),{thumb:n,bar:r,thumbLeft:a,thumbTop:o,background:i,handleClick:d,update:p}}});function mae(e,t,n,r,a,o){return R(),X(\"div\",{class:U([\"el-color-alpha-slider\",{\"is-vertical\":e.vertical}])},[Z(\"div\",{ref:\"bar\",class:\"el-color-alpha-slider__bar\",style:Xe({background:e.background}),onClick:t[0]||(t[0]=(...i)=>e.handleClick&&e.handleClick(...i))},null,4),Z(\"div\",{ref:\"thumb\",class:\"el-color-alpha-slider__thumb\",style:Xe({left:e.thumbLeft+\"px\",top:e.thumbTop+\"px\"})},null,4)],2)}var gae=Ae(vae,[[\"render\",mae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/color-picker/src/components/alpha-slider.vue\"]]);const yae=G({name:\"ElColorHueSlider\",props:{color:{type:Object,required:!0},vertical:Boolean},setup(e){const t=$t(),n=H(null),r=H(null),a=H(0),o=H(0),i=x(()=>e.color.get(\"hue\"));ce(()=>i.value,()=>{f()});function l(p){p.target!==n.value&&s(p)}function s(p){const m=t.vnode.el.getBoundingClientRect(),{clientX:y,clientY:b}=AC(p);let C;if(e.vertical){let S=b-m.top;S=Math.min(S,m.height-n.value.offsetHeight/2),S=Math.max(n.value.offsetHeight/2,S),C=Math.round((S-n.value.offsetHeight/2)/(m.height-n.value.offsetHeight)*360)}else{let S=y-m.left;S=Math.min(S,m.width-n.value.offsetWidth/2),S=Math.max(n.value.offsetWidth/2,S),C=Math.round((S-n.value.offsetWidth/2)/(m.width-n.value.offsetWidth)*360)}e.color.set(\"hue\",C)}function c(){const p=t.vnode.el;if(e.vertical)return 0;const v=e.color.get(\"hue\");return p?Math.round(v*(p.offsetWidth-n.value.offsetWidth/2)/360):0}function d(){const p=t.vnode.el;if(!e.vertical)return 0;const v=e.color.get(\"hue\");return p?Math.round(v*(p.offsetHeight-n.value.offsetHeight/2)/360):0}function f(){a.value=c(),o.value=d()}return et(()=>{const p={drag:v=>{s(v)},end:v=>{s(v)}};Gd(r.value,p),Gd(n.value,p),f()}),{bar:r,thumb:n,thumbLeft:a,thumbTop:o,hueValue:i,handleClick:l,update:f}}});function bae(e,t,n,r,a,o){return R(),X(\"div\",{class:U([\"el-color-hue-slider\",{\"is-vertical\":e.vertical}])},[Z(\"div\",{ref:\"bar\",class:\"el-color-hue-slider__bar\",onClick:t[0]||(t[0]=(...i)=>e.handleClick&&e.handleClick(...i))},null,512),Z(\"div\",{ref:\"thumb\",class:\"el-color-hue-slider__thumb\",style:Xe({left:e.thumbLeft+\"px\",top:e.thumbTop+\"px\"})},null,4)],2)}var Cae=Ae(yae,[[\"render\",bae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/color-picker/src/components/hue-slider.vue\"]]);const ZM=Symbol(),wae=()=>ve(ZM),B4=function(e,t,n){return[e,t*n/((e=(2-t)*n)<1?e:2-e)||0,e/2]},Sae=function(e){return typeof e==\"string\"&&e.includes(\".\")&&Number.parseFloat(e)===1},kae=function(e){return typeof e==\"string\"&&e.includes(\"%\")},xu=function(e,t){Sae(e)&&(e=\"100%\");const n=kae(e);return e=Math.min(t,Math.max(0,Number.parseFloat(`${e}`))),n&&(e=Number.parseInt(`${e*t}`,10)/100),Math.abs(e-t)<1e-6?1:e%t/Number.parseFloat(t)},V4={10:\"A\",11:\"B\",12:\"C\",13:\"D\",14:\"E\",15:\"F\"},bp=function(e){e=Math.min(Math.round(e),255);const t=Math.floor(e/16),n=e%16;return`${V4[t]||t}${V4[n]||n}`},z4=function({r:e,g:t,b:n}){return Number.isNaN(+e)||Number.isNaN(+t)||Number.isNaN(+n)?\"\":`#${bp(e)}${bp(t)}${bp(n)}`},hy={A:10,B:11,C:12,D:13,E:14,F:15},$l=function(e){return e.length===2?(hy[e[0].toUpperCase()]||+e[0])*16+(hy[e[1].toUpperCase()]||+e[1]):hy[e[1].toUpperCase()]||+e[1]},$ae=function(e,t,n){t=t/100,n=n/100;let r=t;const a=Math.max(n,.01);n*=2,t*=n<=1?n:2-n,r*=a<=1?a:2-a;const o=(n+t)/2,i=n===0?2*r/(a+r):2*t/(n+t);return{h:e,s:i*100,v:o*100}},H4=function(e,t,n){e=xu(e,255),t=xu(t,255),n=xu(n,255);const r=Math.max(e,t,n),a=Math.min(e,t,n);let o;const i=r,l=r-a,s=r===0?0:l/r;if(r===a)o=0;else{switch(r){case e:{o=(t-n)/l+(t<n?6:0);break}case t:{o=(n-e)/l+2;break}case n:{o=(e-t)/l+4;break}}o/=6}return{h:o*360,s:s*100,v:i*100}},Vc=function(e,t,n){e=xu(e,360)*6,t=xu(t,100),n=xu(n,100);const r=Math.floor(e),a=e-r,o=n*(1-t),i=n*(1-a*t),l=n*(1-(1-a)*t),s=r%6,c=[n,i,o,o,l,n][s],d=[l,n,n,i,o,o][s],f=[o,o,l,n,n,i][s];return{r:Math.round(c*255),g:Math.round(d*255),b:Math.round(f*255)}};class yd{constructor(t){this._hue=0,this._saturation=100,this._value=100,this._alpha=100,this.enableAlpha=!1,this.format=\"hex\",this.value=\"\",t=t||{};for(const n in t)Mt(t,n)&&(this[n]=t[n]);t.value?this.fromString(t.value):this.doOnChange()}set(t,n){if(arguments.length===1&&typeof t==\"object\"){for(const r in t)Mt(t,r)&&this.set(r,t[r]);return}this[`_${t}`]=n,this.doOnChange()}get(t){return t===\"alpha\"?Math.floor(this[`_${t}`]):this[`_${t}`]}toRgb(){return Vc(this._hue,this._saturation,this._value)}fromString(t){if(!t){this._hue=0,this._saturation=100,this._value=100,this.doOnChange();return}const n=(r,a,o)=>{this._hue=Math.max(0,Math.min(360,r)),this._saturation=Math.max(0,Math.min(100,a)),this._value=Math.max(0,Math.min(100,o)),this.doOnChange()};if(t.includes(\"hsl\")){const r=t.replace(/hsla|hsl|\\(|\\)/gm,\"\").split(/\\s|,/g).filter(a=>a!==\"\").map((a,o)=>o>2?Number.parseFloat(a):Number.parseInt(a,10));if(r.length===4?this._alpha=Number.parseFloat(r[3])*100:r.length===3&&(this._alpha=100),r.length>=3){const{h:a,s:o,v:i}=$ae(r[0],r[1],r[2]);n(a,o,i)}}else if(t.includes(\"hsv\")){const r=t.replace(/hsva|hsv|\\(|\\)/gm,\"\").split(/\\s|,/g).filter(a=>a!==\"\").map((a,o)=>o>2?Number.parseFloat(a):Number.parseInt(a,10));r.length===4?this._alpha=Number.parseFloat(r[3])*100:r.length===3&&(this._alpha=100),r.length>=3&&n(r[0],r[1],r[2])}else if(t.includes(\"rgb\")){const r=t.replace(/rgba|rgb|\\(|\\)/gm,\"\").split(/\\s|,/g).filter(a=>a!==\"\").map((a,o)=>o>2?Number.parseFloat(a):Number.parseInt(a,10));if(r.length===4?this._alpha=Number.parseFloat(r[3])*100:r.length===3&&(this._alpha=100),r.length>=3){const{h:a,s:o,v:i}=H4(r[0],r[1],r[2]);n(a,o,i)}}else if(t.includes(\"#\")){const r=t.replace(\"#\",\"\").trim();if(!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$|^[0-9a-fA-F]{8}$/.test(r))return;let a,o,i;r.length===3?(a=$l(r[0]+r[0]),o=$l(r[1]+r[1]),i=$l(r[2]+r[2])):(r.length===6||r.length===8)&&(a=$l(r.slice(0,2)),o=$l(r.slice(2,4)),i=$l(r.slice(4,6))),r.length===8?this._alpha=$l(r.slice(6))/255*100:(r.length===3||r.length===6)&&(this._alpha=100);const{h:l,s,v:c}=H4(a,o,i);n(l,s,c)}}compare(t){return Math.abs(t._hue-this._hue)<2&&Math.abs(t._saturation-this._saturation)<1&&Math.abs(t._value-this._value)<1&&Math.abs(t._alpha-this._alpha)<1}doOnChange(){const{_hue:t,_saturation:n,_value:r,_alpha:a,format:o}=this;if(this.enableAlpha)switch(o){case\"hsl\":{const i=B4(t,n/100,r/100);this.value=`hsla(${t}, ${Math.round(i[1]*100)}%, ${Math.round(i[2]*100)}%, ${this.get(\"alpha\")/100})`;break}case\"hsv\":{this.value=`hsva(${t}, ${Math.round(n)}%, ${Math.round(r)}%, ${this.get(\"alpha\")/100})`;break}case\"hex\":{this.value=`${z4(Vc(t,n,r))}${bp(a*255/100)}`;break}default:{const{r:i,g:l,b:s}=Vc(t,n,r);this.value=`rgba(${i}, ${l}, ${s}, ${this.get(\"alpha\")/100})`}}else switch(o){case\"hsl\":{const i=B4(t,n/100,r/100);this.value=`hsl(${t}, ${Math.round(i[1]*100)}%, ${Math.round(i[2]*100)}%)`;break}case\"hsv\":{this.value=`hsv(${t}, ${Math.round(n)}%, ${Math.round(r)}%)`;break}case\"rgb\":{const{r:i,g:l,b:s}=Vc(t,n,r);this.value=`rgb(${i}, ${l}, ${s})`;break}default:this.value=z4(Vc(t,n,r))}}}const Oae=G({props:{colors:{type:Array,required:!0},color:{type:Object,required:!0}},setup(e){const{currentColor:t}=wae(),n=H(a(e.colors,e.color));ce(()=>t.value,o=>{const i=new yd;i.fromString(o),n.value.forEach(l=>{l.selected=i.compare(l)})}),Wn(()=>{n.value=a(e.colors,e.color)});function r(o){e.color.fromString(e.colors[o])}function a(o,i){return o.map(l=>{const s=new yd;return s.enableAlpha=!0,s.format=\"rgba\",s.fromString(l),s.selected=s.value===i.value,s})}return{rgbaColors:n,handleSelect:r}}}),Pae={class:\"el-color-predefine\"},Tae={class:\"el-color-predefine__colors\"},xae=[\"onClick\"];function _ae(e,t,n,r,a,o){return R(),X(\"div\",Pae,[Z(\"div\",Tae,[(R(!0),X(Fe,null,Rt(e.rgbaColors,(i,l)=>(R(),X(\"div\",{key:e.colors[l],class:U([\"el-color-predefine__color-selector\",{selected:i.selected,\"is-alpha\":i._alpha<100}]),onClick:s=>e.handleSelect(l)},[Z(\"div\",{style:Xe({backgroundColor:i.value})},null,4)],10,xae))),128))])])}var Eae=Ae(Oae,[[\"render\",_ae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/color-picker/src/components/predefine.vue\"]]);const Mae=G({name:\"ElSlPanel\",props:{color:{type:Object,required:!0}},setup(e){const t=$t(),n=H(0),r=H(0),a=H(\"hsl(0, 100%, 50%)\"),o=x(()=>{const s=e.color.get(\"hue\"),c=e.color.get(\"value\");return{hue:s,value:c}});function i(){const s=e.color.get(\"saturation\"),c=e.color.get(\"value\"),d=t.vnode.el,{clientWidth:f,clientHeight:p}=d;r.value=s*f/100,n.value=(100-c)*p/100,a.value=`hsl(${e.color.get(\"hue\")}, 100%, 50%)`}function l(s){const d=t.vnode.el.getBoundingClientRect(),{clientX:f,clientY:p}=AC(s);let v=f-d.left,m=p-d.top;v=Math.max(0,v),v=Math.min(v,d.width),m=Math.max(0,m),m=Math.min(m,d.height),r.value=v,n.value=m,e.color.set({saturation:v/d.width*100,value:100-m/d.height*100})}return ce(()=>o.value,()=>{i()}),et(()=>{Gd(t.vnode.el,{drag:s=>{l(s)},end:s=>{l(s)}}),i()}),{cursorTop:n,cursorLeft:r,background:a,colorValue:o,handleDrag:l,update:i}}}),Iae=Z(\"div\",{class:\"el-color-svpanel__white\"},null,-1),Nae=Z(\"div\",{class:\"el-color-svpanel__black\"},null,-1),Aae=Z(\"div\",null,null,-1),Dae=[Aae];function Rae(e,t,n,r,a,o){return R(),X(\"div\",{class:\"el-color-svpanel\",style:Xe({backgroundColor:e.background})},[Iae,Nae,Z(\"div\",{class:\"el-color-svpanel__cursor\",style:Xe({top:e.cursorTop+\"px\",left:e.cursorLeft+\"px\"})},Dae,4)],4)}var Lae=Ae(Mae,[[\"render\",Rae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/color-picker/src/components/sv-panel.vue\"]]);const Fae=G({name:\"ElColorPicker\",components:{ElButton:xa,ElTooltip:Ur,ElInput:Ra,ElIcon:ft,Close:Ma,ArrowDown:_s,SvPanel:Lae,HueSlider:Cae,AlphaSlider:gae,Predefine:Eae},directives:{ClickOutside:Is},props:{modelValue:String,showAlpha:Boolean,colorFormat:String,disabled:Boolean,size:{type:String,validator:va},popperClass:String,predefine:Array},emits:[\"change\",\"active-change\",Pt],setup(e,{emit:t}){const{t:n}=ln(),r=De(\"color\"),a=ve(ga,{}),o=ve(Ia,{}),i=H(null),l=H(null),s=H(null),c=H(null),d=bt(new yd({enableAlpha:e.showAlpha,format:e.colorFormat,value:e.modelValue})),f=H(!1),p=H(!1),v=H(\"\"),m=x(()=>!e.modelValue&&!p.value?\"transparent\":S(d,e.showAlpha)),y=Gn(),b=x(()=>!!(e.disabled||a.disabled)),C=x(()=>!e.modelValue&&!p.value?\"\":d.value);ce(()=>e.modelValue,j=>{j?j&&j!==d.value&&d.fromString(j):p.value=!1}),ce(()=>C.value,j=>{v.value=j,t(\"active-change\",j)}),ce(()=>d.value,()=>{!e.modelValue&&!p.value&&(p.value=!0)});function S(j,F){if(!(j instanceof yd))throw new TypeError(\"color should be instance of _color Class\");const{r:N,g:D,b:z}=j.toRgb();return F?`rgba(${N}, ${D}, ${z}, ${j.get(\"alpha\")/100})`:`rgb(${N}, ${D}, ${z})`}function w(j){f.value=j}const k=Yn(w,100);function $(){k(!1),O()}function O(){Ne(()=>{e.modelValue?d.fromString(e.modelValue):p.value=!1})}function T(){b.value||k(!f.value)}function _(){d.fromString(v.value)}function I(){var j;const F=d.value;t(Pt,F),t(\"change\",F),(j=o.validate)==null||j.call(o,\"change\").catch(N=>void 0),k(!1),Ne(()=>{const N=new yd({enableAlpha:e.showAlpha,format:e.colorFormat,value:e.modelValue});d.compare(N)||O()})}function L(){var j;k(!1),t(Pt,null),t(\"change\",null),e.modelValue!==null&&((j=o.validate)==null||j.call(o,\"change\").catch(F=>void 0)),O()}return et(()=>{e.modelValue&&(v.value=C.value)}),ce(()=>f.value,()=>{Ne(()=>{var j,F,N;(j=i.value)==null||j.update(),(F=l.value)==null||F.update(),(N=s.value)==null||N.update()})}),ot(ZM,{currentColor:C}),{color:d,colorDisabled:b,colorSize:y,displayedColor:m,showPanelColor:p,showPicker:f,customInput:v,handleConfirm:_,hide:$,handleTrigger:T,clear:L,confirmValue:I,t:n,ns:r,hue:i,svPanel:l,alpha:s,popper:c}}});function Bae(e,t,n,r,a,o){const i=we(\"hue-slider\"),l=we(\"sv-panel\"),s=we(\"alpha-slider\"),c=we(\"predefine\"),d=we(\"el-input\"),f=we(\"el-button\"),p=we(\"arrow-down\"),v=we(\"el-icon\"),m=we(\"close\"),y=we(\"el-tooltip\"),b=pa(\"click-outside\");return R(),fe(y,{ref:\"popper\",visible:e.showPicker,\"onUpdate:visible\":t[2]||(t[2]=C=>e.showPicker=C),\"show-arrow\":!1,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],offset:0,\"gpu-acceleration\":!1,\"popper-class\":[e.ns.be(\"picker\",\"panel\"),e.ns.b(\"dropdown\"),e.popperClass],\"stop-popper-mouse-event\":!1,effect:\"light\",trigger:\"click\",transition:\"el-zoom-in-top\",persistent:\"\"},{content:re(()=>[at((R(),X(\"div\",null,[Z(\"div\",{class:U(e.ns.be(\"dropdown\",\"main-wrapper\"))},[g(i,{ref:\"hue\",class:\"hue-slider\",color:e.color,vertical:\"\"},null,8,[\"color\"]),g(l,{ref:\"svPanel\",color:e.color},null,8,[\"color\"])],2),e.showAlpha?(R(),fe(s,{key:0,ref:\"alpha\",color:e.color},null,8,[\"color\"])):se(\"v-if\",!0),e.predefine?(R(),fe(c,{key:1,ref:\"predefine\",color:e.color,colors:e.predefine},null,8,[\"color\",\"colors\"])):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.be(\"dropdown\",\"btns\"))},[Z(\"span\",{class:U(e.ns.be(\"dropdown\",\"value\"))},[g(d,{modelValue:e.customInput,\"onUpdate:modelValue\":t[0]||(t[0]=C=>e.customInput=C),\"validate-event\":!1,size:\"small\",onKeyup:It(e.handleConfirm,[\"enter\"]),onBlur:e.handleConfirm},null,8,[\"modelValue\",\"onKeyup\",\"onBlur\"])],2),g(f,{size:\"small\",type:\"text\",class:U(e.ns.be(\"dropdown\",\"link-btn\")),onClick:e.clear},{default:re(()=>[yt(Me(e.t(\"el.colorpicker.clear\")),1)]),_:1},8,[\"class\",\"onClick\"]),g(f,{plain:\"\",size:\"small\",class:U(e.ns.be(\"dropdown\",\"btn\")),onClick:e.confirmValue},{default:re(()=>[yt(Me(e.t(\"el.colorpicker.confirm\")),1)]),_:1},8,[\"class\",\"onClick\"])],2)])),[[b,e.hide]])]),default:re(()=>[Z(\"div\",{class:U([e.ns.b(\"picker\"),e.ns.is(\"disabled\",e.colorDisabled),e.ns.bm(\"picker\",e.colorSize)])},[e.colorDisabled?(R(),X(\"div\",{key:0,class:U(e.ns.be(\"picker\",\"mask\"))},null,2)):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.be(\"picker\",\"trigger\")),onClick:t[1]||(t[1]=(...C)=>e.handleTrigger&&e.handleTrigger(...C))},[Z(\"span\",{class:U([e.ns.be(\"picker\",\"color\"),e.ns.is(\"alpha\",e.showAlpha)])},[Z(\"span\",{class:U(e.ns.be(\"picker\",\"color-inner\")),style:Xe({backgroundColor:e.displayedColor})},[at(g(v,{class:U([e.ns.be(\"picker\",\"icon\"),e.ns.is(\"icon-arrow-down\")])},{default:re(()=>[g(p)]),_:1},8,[\"class\"]),[[_t,e.modelValue||e.showPanelColor]]),!e.modelValue&&!e.showPanelColor?(R(),fe(v,{key:0,class:U([e.ns.be(\"picker\",\"empty\"),e.ns.is(\"icon-close\")])},{default:re(()=>[g(m)]),_:1},8,[\"class\"])):se(\"v-if\",!0)],6)],2)],2)],2)]),_:1},8,[\"visible\",\"popper-class\"])}var Cp=Ae(Fae,[[\"render\",Bae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/color-picker/src/index.vue\"]]);Cp.install=e=>{e.component(Cp.name,Cp)};const Vae=Cp,zae=Vae,I0={},Hae=Ze({a11y:{type:Boolean,default:!0},locale:{type:Le(Object)},size:{type:String,values:Bo,default:\"\"},button:{type:Le(Object)},experimentalFeatures:{type:Le(Object)},keyboardNavigation:{type:Boolean,default:!0},message:{type:Le(Object)},zIndex:{type:Number},namespace:{type:String,default:\"el\"}});var jae=G({name:\"ElConfigProvider\",props:Hae,setup(e,{slots:t}){ce(()=>e.message,r=>{Object.assign(I0,r!=null?r:{})},{immediate:!0,deep:!0});const n=AE(e);return()=>Oe(t,\"default\",{config:n==null?void 0:n.value})}});const Kae=xt(jae),Wae=G({name:\"ElContainer\",props:{direction:{type:String,default:\"\"}},setup(e,{slots:t}){const n=De(\"container\");return{isVertical:x(()=>e.direction===\"vertical\"?!0:e.direction===\"horizontal\"?!1:t&&t.default?t.default().some(o=>{const i=o.type.name;return i===\"ElHeader\"||i===\"ElFooter\"}):!1),ns:n}}});function Uae(e,t,n,r,a,o){return R(),X(\"section\",{class:U([e.ns.b(),e.ns.is(\"vertical\",e.isVertical)])},[Oe(e.$slots,\"default\")],2)}var Yae=Ae(Wae,[[\"render\",Uae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/container/src/container.vue\"]]);const qae=G({name:\"ElAside\",props:{width:{type:String,default:null}},setup(e){const t=De(\"aside\");return{style:x(()=>e.width?{\"--el-aside-width\":e.width}:{}),ns:t}}});function Gae(e,t,n,r,a,o){return R(),X(\"aside\",{class:U(e.ns.b()),style:Xe(e.style)},[Oe(e.$slots,\"default\")],6)}var JM=Ae(qae,[[\"render\",Gae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/container/src/aside.vue\"]]);const Xae=G({name:\"ElFooter\",props:{height:{type:String,default:null}},setup(e){const t=De(\"footer\");return{style:x(()=>e.height?{\"--el-footer-height\":e.height}:{}),ns:t}}});function Zae(e,t,n,r,a,o){return R(),X(\"footer\",{class:U(e.ns.b()),style:Xe(e.style)},[Oe(e.$slots,\"default\")],6)}var QM=Ae(Xae,[[\"render\",Zae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/container/src/footer.vue\"]]);const Jae=G({name:\"ElHeader\",props:{height:{type:String,default:null}},setup(e){const t=De(\"header\");return{style:x(()=>e.height?{\"--el-header-height\":e.height}:{}),ns:t}}});function Qae(e,t,n,r,a,o){return R(),X(\"header\",{class:U(e.ns.b()),style:Xe(e.style)},[Oe(e.$slots,\"default\")],6)}var e5=Ae(Jae,[[\"render\",Qae],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/container/src/header.vue\"]]);const eoe=G({name:\"ElMain\",setup(){return{ns:De(\"main\")}}});function toe(e,t,n,r,a,o){return R(),X(\"main\",{class:U(e.ns.b())},[Oe(e.$slots,\"default\")],2)}var t5=Ae(eoe,[[\"render\",toe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/container/src/main.vue\"]]);const noe=xt(Yae,{Aside:JM,Footer:QM,Header:e5,Main:t5}),roe=En(JM),aoe=En(QM),ooe=En(e5),ioe=En(t5);var n5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r,a){var o=r.prototype,i=o.format;a.en.ordinal=function(l){var s=[\"th\",\"st\",\"nd\",\"rd\"],c=l%100;return\"[\"+l+(s[(c-20)%10]||s[c]||s[0])+\"]\"},o.format=function(l){var s=this,c=this.$locale();if(!this.isValid())return i.bind(this)(l);var d=this.$utils(),f=(l||\"YYYY-MM-DDTHH:mm:ssZ\").replace(/\\[([^\\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(p){switch(p){case\"Q\":return Math.ceil((s.$M+1)/3);case\"Do\":return c.ordinal(s.$D);case\"gggg\":return s.weekYear();case\"GGGG\":return s.isoWeekYear();case\"wo\":return c.ordinal(s.week(),\"W\");case\"w\":case\"ww\":return d.s(s.week(),p===\"w\"?1:2,\"0\");case\"W\":case\"WW\":return d.s(s.isoWeek(),p===\"W\"?1:2,\"0\");case\"k\":case\"kk\":return d.s(String(s.$H===0?24:s.$H),p===\"k\"?1:2,\"0\");case\"X\":return Math.floor(s.$d.getTime()/1e3);case\"x\":return s.$d.getTime();case\"z\":return\"[\"+s.offsetName()+\"]\";case\"zzz\":return\"[\"+s.offsetName(\"long\")+\"]\";default:return p}});return i.bind(this)(f)}}})})(n5);var loe=n5.exports,r5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){var n=\"week\",r=\"year\";return function(a,o,i){var l=o.prototype;l.week=function(s){if(s===void 0&&(s=null),s!==null)return this.add(7*(s-this.week()),\"day\");var c=this.$locale().yearStart||1;if(this.month()===11&&this.date()>25){var d=i(this).startOf(r).add(1,r).date(c),f=i(this).endOf(n);if(d.isBefore(f))return 1}var p=i(this).startOf(r).date(c).startOf(n).subtract(1,\"millisecond\"),v=this.diff(p,n,!0);return v<0?i(this).startOf(\"week\").week():Math.ceil(v)},l.weeks=function(s){return s===void 0&&(s=null),this.week(s)}}})})(r5);var soe=r5.exports,a5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r){r.prototype.weekYear=function(){var a=this.month(),o=this.week(),i=this.year();return o===1&&a===11?i+1:a===0&&o>=52?i-1:i}}})})(a5);var uoe=a5.exports,o5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r,a){r.prototype.dayOfYear=function(o){var i=Math.round((a(this).startOf(\"day\")-a(this).startOf(\"year\"))/864e5)+1;return o==null?i:this.add(o-i,\"day\")}}})})(o5);var coe=o5.exports,i5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r){r.prototype.isSameOrAfter=function(a,o){return this.isSame(a,o)||this.isAfter(a,o)}}})})(i5);var doe=i5.exports,l5={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n,r){r.prototype.isSameOrBefore=function(a,o){return this.isSame(a,o)||this.isBefore(a,o)}}})})(l5);var foe=l5.exports;const s5=Symbol();var hoe=G({name:\"ElDatePickerCell\",props:Ze({cell:{type:Le(Object)}}),setup(e){const t=ve(s5);return()=>{const n=e.cell;if(t!=null&&t.ctx.slots.default){const r=t.ctx.slots.default(n).filter(a=>a.patchFlag!==-2&&a.type.toString()!==\"Symbol(Comment)\");if(r.length)return r}return qe(\"div\",{class:\"el-date-table-cell\"},[qe(\"span\",{class:\"el-date-table-cell__text\"},[n==null?void 0:n.text])])}}});const poe=G({components:{ElDatePickerCell:hoe},props:{date:{type:Object},minDate:{type:Object},maxDate:{type:Object},parsedValue:{type:[Object,Array]},selectionMode:{type:String,default:\"day\"},showWeekNumber:{type:Boolean,default:!1},disabledDate:{type:Function},cellClassName:{type:Function},rangeState:{type:Object,default:()=>({endDate:null,selecting:!1})}},emits:[\"changerange\",\"pick\",\"select\"],setup(e,t){const{t:n,lang:r}=ln(),a=H(null),o=H(null),i=H([[],[],[],[],[],[]]),l=e.date.$locale().weekStart||7,s=e.date.locale(\"en\").localeData().weekdaysShort().map(k=>k.toLowerCase()),c=x(()=>l>3?7-l:-l),d=x(()=>{const k=e.date.startOf(\"month\");return k.subtract(k.day()||7,\"day\")}),f=x(()=>s.concat(s).slice(l,l+7)),p=x(()=>{var k;const $=e.date.startOf(\"month\"),O=$.day()||7,T=$.daysInMonth(),_=$.subtract(1,\"month\").daysInMonth(),I=c.value,L=i.value;let j=1;const F=e.selectionMode===\"dates\"?rs(e.parsedValue):[],N=mt().locale(r.value).startOf(\"day\");for(let D=0;D<6;D++){const z=L[D];e.showWeekNumber&&(z[0]||(z[0]={type:\"week\",text:d.value.add(D*7+1,\"day\").week()}));for(let B=0;B<7;B++){let M=z[e.showWeekNumber?B+1:B];M||(M={row:D,column:B,type:\"normal\",inRange:!1,start:!1,end:!1});const E=D*7+B,K=d.value.add(E-I,\"day\");M.dayjs=K,M.date=K.toDate(),M.timestamp=K.valueOf(),M.type=\"normal\";const W=e.rangeState.endDate||e.maxDate||e.rangeState.selecting&&e.minDate;if(M.inRange=e.minDate&&K.isSameOrAfter(e.minDate,\"day\")&&W&&K.isSameOrBefore(W,\"day\")||e.minDate&&K.isSameOrBefore(e.minDate,\"day\")&&W&&K.isSameOrAfter(W,\"day\"),(k=e.minDate)!=null&&k.isSameOrAfter(W)?(M.start=W&&K.isSame(W,\"day\"),M.end=e.minDate&&K.isSame(e.minDate,\"day\")):(M.start=e.minDate&&K.isSame(e.minDate,\"day\"),M.end=W&&K.isSame(W,\"day\")),K.isSame(N,\"day\")&&(M.type=\"today\"),D>=0&&D<=1){const J=O+I<0?7+O+I:O+I;B+D*7>=J?M.text=j++:(M.text=_-(J-B%7)+1+D*7,M.type=\"prev-month\")}else j<=T?M.text=j++:(M.text=j++-T,M.type=\"next-month\");const q=K.toDate();M.selected=F.find(J=>J.valueOf()===K.valueOf()),M.isSelected=!!M.selected,M.isCurrent=v(M),M.disabled=e.disabledDate&&e.disabledDate(q),M.customClass=e.cellClassName&&e.cellClassName(q),z[e.showWeekNumber?B+1:B]=M}if(e.selectionMode===\"week\"){const B=e.showWeekNumber?1:0,M=e.showWeekNumber?7:6,E=w(z[B+1]);z[B].inRange=E,z[B].start=E,z[M].inRange=E,z[M].end=E}}return L}),v=k=>e.selectionMode===\"day\"&&(k.type===\"normal\"||k.type===\"today\")&&m(k,e.parsedValue),m=(k,$)=>$?mt($).locale(r.value).isSame(e.date.date(Number(k.text)),\"day\"):!1,y=k=>{const $=[];return(k.type===\"normal\"||k.type===\"today\")&&!k.disabled?($.push(\"available\"),k.type===\"today\"&&$.push(\"today\")):$.push(k.type),v(k)&&$.push(\"current\"),k.inRange&&(k.type===\"normal\"||k.type===\"today\"||e.selectionMode===\"week\")&&($.push(\"in-range\"),k.start&&$.push(\"start-date\"),k.end&&$.push(\"end-date\")),k.disabled&&$.push(\"disabled\"),k.selected&&$.push(\"selected\"),k.customClass&&$.push(k.customClass),$.join(\" \")},b=(k,$)=>{const O=k*7+($-(e.showWeekNumber?1:0))-c.value;return d.value.add(O,\"day\")},C=k=>{if(!e.rangeState.selecting)return;let $=k.target;if($.tagName===\"SPAN\"&&($=$.parentNode.parentNode),$.tagName===\"DIV\"&&($=$.parentNode),$.tagName!==\"TD\")return;const O=$.parentNode.rowIndex-1,T=$.cellIndex;p.value[O][T].disabled||(O!==a.value||T!==o.value)&&(a.value=O,o.value=T,t.emit(\"changerange\",{selecting:!0,endDate:b(O,T)}))},S=k=>{let $=k.target;for(;$&&$.tagName!==\"TD\";)$=$.parentNode;if(!$||$.tagName!==\"TD\")return;const O=$.parentNode.rowIndex-1,T=$.cellIndex,_=p.value[O][T];if(_.disabled||_.type===\"week\")return;const I=b(O,T);if(e.selectionMode===\"range\")e.rangeState.selecting?(I>=e.minDate?t.emit(\"pick\",{minDate:e.minDate,maxDate:I}):t.emit(\"pick\",{minDate:I,maxDate:e.minDate}),t.emit(\"select\",!1)):(t.emit(\"pick\",{minDate:I,maxDate:null}),t.emit(\"select\",!0));else if(e.selectionMode===\"day\")t.emit(\"pick\",I);else if(e.selectionMode===\"week\"){const L=I.week(),j=`${I.year()}w${L}`;t.emit(\"pick\",{year:I.year(),week:L,value:j,date:I.startOf(\"week\")})}else if(e.selectionMode===\"dates\"){const L=_.selected?rs(e.parsedValue).filter(j=>j.valueOf()!==I.valueOf()):rs(e.parsedValue).concat([I]);t.emit(\"pick\",L)}},w=k=>{if(e.selectionMode!==\"week\")return!1;let $=e.date.startOf(\"day\");if(k.type===\"prev-month\"&&($=$.subtract(1,\"month\")),k.type===\"next-month\"&&($=$.add(1,\"month\")),$=$.date(Number.parseInt(k.text,10)),e.parsedValue&&!Array.isArray(e.parsedValue)){const O=(e.parsedValue.day()-l+7)%7-1;return e.parsedValue.subtract(O,\"day\").isSame($,\"day\")}return!1};return{handleMouseMove:C,t:n,rows:p,isWeekActive:w,getCellClasses:y,WEEKS:f,handleClick:S}}}),voe={key:0};function moe(e,t,n,r,a,o){const i=we(\"el-date-picker-cell\");return R(),X(\"table\",{cellspacing:\"0\",cellpadding:\"0\",class:U([\"el-date-table\",{\"is-week-mode\":e.selectionMode===\"week\"}]),onClick:t[0]||(t[0]=(...l)=>e.handleClick&&e.handleClick(...l)),onMousemove:t[1]||(t[1]=(...l)=>e.handleMouseMove&&e.handleMouseMove(...l))},[Z(\"tbody\",null,[Z(\"tr\",null,[e.showWeekNumber?(R(),X(\"th\",voe,Me(e.t(\"el.datepicker.week\")),1)):se(\"v-if\",!0),(R(!0),X(Fe,null,Rt(e.WEEKS,(l,s)=>(R(),X(\"th\",{key:s},Me(e.t(\"el.datepicker.weeks.\"+l)),1))),128))]),(R(!0),X(Fe,null,Rt(e.rows,(l,s)=>(R(),X(\"tr\",{key:s,class:U([\"el-date-table__row\",{current:e.isWeekActive(l[1])}])},[(R(!0),X(Fe,null,Rt(l,(c,d)=>(R(),X(\"td\",{key:d,class:U(e.getCellClasses(c))},[g(i,{cell:c},null,8,[\"cell\"])],2))),128))],2))),128))])],34)}var u5=Ae(poe,[[\"render\",moe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/basic-date-table.vue\"]]);const goe=(e,t,n)=>{const r=mt().locale(n).startOf(\"month\").month(t).year(e),a=r.daysInMonth();return tl(a).map(o=>r.add(o,\"day\").toDate())},yoe=G({props:{disabledDate:{type:Function},selectionMode:{type:String,default:\"month\"},minDate:{type:Object},maxDate:{type:Object},date:{type:Object},parsedValue:{type:Object},rangeState:{type:Object,default:()=>({endDate:null,selecting:!1})}},emits:[\"changerange\",\"pick\",\"select\"],setup(e,t){const{t:n,lang:r}=ln(),a=H(e.date.locale(\"en\").localeData().monthsShort().map(p=>p.toLowerCase())),o=H([[],[],[]]),i=H(null),l=H(null),s=x(()=>{var p;const v=o.value,m=mt().locale(r.value).startOf(\"month\");for(let y=0;y<3;y++){const b=v[y];for(let C=0;C<4;C++){let S=b[C];S||(S={row:y,column:C,type:\"normal\",inRange:!1,start:!1,end:!1}),S.type=\"normal\";const w=y*4+C,k=e.date.startOf(\"year\").month(w),$=e.rangeState.endDate||e.maxDate||e.rangeState.selecting&&e.minDate;S.inRange=e.minDate&&k.isSameOrAfter(e.minDate,\"month\")&&$&&k.isSameOrBefore($,\"month\")||e.minDate&&k.isSameOrBefore(e.minDate,\"month\")&&$&&k.isSameOrAfter($,\"month\"),(p=e.minDate)!=null&&p.isSameOrAfter($)?(S.start=$&&k.isSame($,\"month\"),S.end=e.minDate&&k.isSame(e.minDate,\"month\")):(S.start=e.minDate&&k.isSame(e.minDate,\"month\"),S.end=$&&k.isSame($,\"month\")),m.isSame(k)&&(S.type=\"today\"),S.text=w;const T=k.toDate();S.disabled=e.disabledDate&&e.disabledDate(T),b[C]=S}}return v});return{handleMouseMove:p=>{if(!e.rangeState.selecting)return;let v=p.target;if(v.tagName===\"A\"&&(v=v.parentNode.parentNode),v.tagName===\"DIV\"&&(v=v.parentNode),v.tagName!==\"TD\")return;const m=v.parentNode.rowIndex,y=v.cellIndex;s.value[m][y].disabled||(m!==i.value||y!==l.value)&&(i.value=m,l.value=y,t.emit(\"changerange\",{selecting:!0,endDate:e.date.startOf(\"year\").month(m*4+y)}))},handleMonthTableClick:p=>{let v=p.target;if(v.tagName===\"A\"&&(v=v.parentNode.parentNode),v.tagName===\"DIV\"&&(v=v.parentNode),v.tagName!==\"TD\"||to(v,\"disabled\"))return;const m=v.cellIndex,b=v.parentNode.rowIndex*4+m,C=e.date.startOf(\"year\").month(b);e.selectionMode===\"range\"?e.rangeState.selecting?(C>=e.minDate?t.emit(\"pick\",{minDate:e.minDate,maxDate:C}):t.emit(\"pick\",{minDate:C,maxDate:e.minDate}),t.emit(\"select\",!1)):(t.emit(\"pick\",{minDate:C,maxDate:null}),t.emit(\"select\",!0)):t.emit(\"pick\",b)},rows:s,getCellStyle:p=>{const v={},m=e.date.year(),y=new Date,b=p.text;return v.disabled=e.disabledDate?goe(m,b,r.value).every(e.disabledDate):!1,v.current=rs(e.parsedValue).findIndex(C=>C.year()===m&&C.month()===b)>=0,v.today=y.getFullYear()===m&&y.getMonth()===b,p.inRange&&(v[\"in-range\"]=!0,p.start&&(v[\"start-date\"]=!0),p.end&&(v[\"end-date\"]=!0)),v},t:n,months:a}}}),boe={class:\"cell\"};function Coe(e,t,n,r,a,o){return R(),X(\"table\",{class:\"el-month-table\",onClick:t[0]||(t[0]=(...i)=>e.handleMonthTableClick&&e.handleMonthTableClick(...i)),onMousemove:t[1]||(t[1]=(...i)=>e.handleMouseMove&&e.handleMouseMove(...i))},[Z(\"tbody\",null,[(R(!0),X(Fe,null,Rt(e.rows,(i,l)=>(R(),X(\"tr\",{key:l},[(R(!0),X(Fe,null,Rt(i,(s,c)=>(R(),X(\"td\",{key:c,class:U(e.getCellStyle(s))},[Z(\"div\",null,[Z(\"a\",boe,Me(e.t(\"el.datepicker.months.\"+e.months[s.text])),1)])],2))),128))]))),128))])],32)}var c5=Ae(yoe,[[\"render\",Coe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/basic-month-table.vue\"]]);const woe=(e,t)=>{const n=mt(String(e)).locale(t).startOf(\"year\"),a=n.endOf(\"year\").dayOfYear();return tl(a).map(o=>n.add(o,\"day\").toDate())},Soe=G({props:{disabledDate:{type:Function},parsedValue:{type:Object},date:{type:Object}},emits:[\"pick\"],setup(e,t){const{lang:n}=ln();return{startYear:x(()=>Math.floor(e.date.year()/10)*10),getCellStyle:i=>{const l={},s=mt().locale(n.value);return l.disabled=e.disabledDate?woe(i,n.value).every(e.disabledDate):!1,l.current=rs(e.parsedValue).findIndex(c=>c.year()===i)>=0,l.today=s.year()===i,l},handleYearTableClick:i=>{const l=i.target;if(l.tagName===\"A\"){if(to(l.parentNode,\"disabled\"))return;const s=l.textContent||l.innerText;t.emit(\"pick\",Number(s))}}}}}),koe={class:\"cell\"},$oe={class:\"cell\"},Ooe={class:\"cell\"},Poe={class:\"cell\"},Toe={class:\"cell\"},xoe={class:\"cell\"},_oe={class:\"cell\"},Eoe={class:\"cell\"},Moe={class:\"cell\"},Ioe={class:\"cell\"},Noe=Z(\"td\",null,null,-1),Aoe=Z(\"td\",null,null,-1);function Doe(e,t,n,r,a,o){return R(),X(\"table\",{class:\"el-year-table\",onClick:t[0]||(t[0]=(...i)=>e.handleYearTableClick&&e.handleYearTableClick(...i))},[Z(\"tbody\",null,[Z(\"tr\",null,[Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+0)])},[Z(\"a\",koe,Me(e.startYear),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+1)])},[Z(\"a\",$oe,Me(e.startYear+1),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+2)])},[Z(\"a\",Ooe,Me(e.startYear+2),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+3)])},[Z(\"a\",Poe,Me(e.startYear+3),1)],2)]),Z(\"tr\",null,[Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+4)])},[Z(\"a\",Toe,Me(e.startYear+4),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+5)])},[Z(\"a\",xoe,Me(e.startYear+5),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+6)])},[Z(\"a\",_oe,Me(e.startYear+6),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+7)])},[Z(\"a\",Eoe,Me(e.startYear+7),1)],2)]),Z(\"tr\",null,[Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+8)])},[Z(\"a\",Moe,Me(e.startYear+8),1)],2),Z(\"td\",{class:U([\"available\",e.getCellStyle(e.startYear+9)])},[Z(\"a\",Ioe,Me(e.startYear+9),1)],2),Noe,Aoe])])])}var Roe=Ae(Soe,[[\"render\",Doe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/basic-year-table.vue\"]]);const Loe=(e,t,n)=>!0,Foe=G({components:{DateTable:u5,ElInput:Ra,ElButton:xa,ElIcon:ft,TimePickPanel:rw,MonthTable:c5,YearTable:Roe,DArrowLeft:Fm,ArrowLeft:Es,DArrowRight:Bm,ArrowRight:Da},directives:{clickoutside:Is},props:{visible:{type:Boolean,default:!1},parsedValue:{type:[Object,Array]},format:{type:String,default:\"\"},type:{type:String,required:!0,validator:mE}},emits:[\"pick\",\"set-picker-option\",\"panel-change\"],setup(e,t){const{t:n,lang:r}=ln(),a=ve(\"EP_PICKER_BASE\"),o=ve(qm),{shortcuts:i,disabledDate:l,cellClassName:s,defaultTime:c,arrowControl:d}=a.props,f=yn(a.props,\"defaultValue\"),p=H(mt().locale(r.value)),v=x(()=>mt(c).locale(r.value)),m=x(()=>p.value.month()),y=x(()=>p.value.year()),b=H([]),C=H(null),S=H(null),w=ue=>b.value.length>0?Loe(ue,b.value,e.format||\"HH:mm:ss\"):!0,k=ue=>c&&!Q.value?v.value.year(ue.year()).month(ue.month()).date(ue.date()):W.value?ue.millisecond(0):ue.startOf(\"day\"),$=(ue,...Ce)=>{if(!ue)t.emit(\"pick\",ue,...Ce);else if(Array.isArray(ue)){const je=ue.map(k);t.emit(\"pick\",je,...Ce)}else t.emit(\"pick\",k(ue),...Ce);C.value=null,S.value=null},O=ue=>{if(D.value===\"day\"){let Ce=e.parsedValue?e.parsedValue.year(ue.year()).month(ue.month()).date(ue.date()):ue;w(Ce)||(Ce=b.value[0][0].year(ue.year()).month(ue.month()).date(ue.date())),p.value=Ce,$(Ce,W.value)}else D.value===\"week\"?$(ue.date):D.value===\"dates\"&&$(ue,!0)},T=()=>{p.value=p.value.subtract(1,\"month\"),pe(\"month\")},_=()=>{p.value=p.value.add(1,\"month\"),pe(\"month\")},I=()=>{j.value===\"year\"?p.value=p.value.subtract(10,\"year\"):p.value=p.value.subtract(1,\"year\"),pe(\"year\")},L=()=>{j.value===\"year\"?p.value=p.value.add(10,\"year\"):p.value=p.value.add(1,\"year\"),pe(\"year\")},j=H(\"date\"),F=x(()=>{const ue=n(\"el.datepicker.year\");if(j.value===\"year\"){const Ce=Math.floor(y.value/10)*10;return ue?`${Ce} ${ue} - ${Ce+9} ${ue}`:`${Ce} - ${Ce+9}`}return`${y.value} ${ue}`}),N=ue=>{const Ce=typeof ue.value==\"function\"?ue.value():ue.value;if(Ce){$(mt(Ce).locale(r.value));return}ue.onClick&&ue.onClick(t)},D=x(()=>[\"week\",\"month\",\"year\",\"dates\"].includes(e.type)?e.type:\"day\");ce(()=>D.value,ue=>{if([\"month\",\"year\"].includes(ue)){j.value=ue;return}j.value=\"date\"},{immediate:!0}),ce(()=>j.value,()=>{o==null||o.updatePopper()});const z=x(()=>!!i.length),B=ue=>{p.value=p.value.startOf(\"month\").month(ue),D.value===\"month\"?$(p.value):j.value=\"date\",pe(\"month\")},M=ue=>{D.value===\"year\"?(p.value=p.value.startOf(\"year\").year(ue),$(p.value)):(p.value=p.value.year(ue),j.value=\"month\"),pe(\"year\")},E=()=>{j.value=\"month\"},K=()=>{j.value=\"year\"},W=x(()=>e.type===\"datetime\"||e.type===\"datetimerange\"),Y=x(()=>W.value||D.value===\"dates\"),q=()=>{if(D.value===\"dates\")$(e.parsedValue);else{let ue=e.parsedValue;if(!ue){const Ce=mt(c).locale(r.value),je=xe();ue=Ce.year(je.year()).month(je.month()).date(je.date())}p.value=ue,$(ue)}},J=()=>{const Ce=mt().locale(r.value).toDate();(!l||!l(Ce))&&w(Ce)&&(p.value=mt().locale(r.value),$(p.value))},ne=x(()=>RM(e.format)),oe=x(()=>DM(e.format)),Q=x(()=>{if(S.value)return S.value;if(!(!e.parsedValue&&!f.value))return(e.parsedValue||p.value).format(ne.value)}),ae=x(()=>{if(C.value)return C.value;if(!(!e.parsedValue&&!f.value))return(e.parsedValue||p.value).format(oe.value)}),de=H(!1),be=()=>{de.value=!0},Ee=()=>{de.value=!1},Pe=(ue,Ce,je)=>{const ee=e.parsedValue?e.parsedValue.hour(ue.hour()).minute(ue.minute()).second(ue.second()):ue;p.value=ee,$(p.value,!0),je||(de.value=Ce)},Be=ue=>{const Ce=mt(ue,ne.value).locale(r.value);Ce.isValid()&&w(Ce)&&(p.value=Ce.year(p.value.year()).month(p.value.month()).date(p.value.date()),S.value=null,de.value=!1,$(p.value,!0))},te=ue=>{const Ce=mt(ue,oe.value).locale(r.value);if(Ce.isValid()){if(l&&l(Ce.toDate()))return;p.value=Ce.hour(p.value.hour()).minute(p.value.minute()).second(p.value.second()),C.value=null,$(p.value,!0)}},ie=ue=>mt.isDayjs(ue)&&ue.isValid()&&(l?!l(ue.toDate()):!0),ge=ue=>D.value===\"dates\"?ue.map(Ce=>Ce.format(e.format)):ue.format(e.format),ke=ue=>mt(ue,e.format).locale(r.value),xe=()=>{const ue=mt(f.value).locale(r.value);if(!f.value){const Ce=v.value;return mt().hour(Ce.hour()).minute(Ce.minute()).second(Ce.second()).locale(r.value)}return ue},Ie=ue=>{const{code:Ce,keyCode:je}=ue,ee=[Ge.up,Ge.down,Ge.left,Ge.right];e.visible&&!de.value&&(ee.includes(Ce)&&(ye(je),ue.stopPropagation(),ue.preventDefault()),Ce===Ge.enter&&C.value===null&&S.value===null&&$(p,!1))},ye=ue=>{const Ce={year:{38:-4,40:4,37:-1,39:1,offset:(ee,me)=>ee.setFullYear(ee.getFullYear()+me)},month:{38:-4,40:4,37:-1,39:1,offset:(ee,me)=>ee.setMonth(ee.getMonth()+me)},week:{38:-1,40:1,37:-1,39:1,offset:(ee,me)=>ee.setDate(ee.getDate()+me*7)},day:{38:-7,40:7,37:-1,39:1,offset:(ee,me)=>ee.setDate(ee.getDate()+me)}},je=p.value.toDate();for(;Math.abs(p.value.diff(je,\"year\",!0))<1;){const ee=Ce[D.value];if(ee.offset(je,ee[ue]),l&&l(je))continue;const me=mt(je).locale(r.value);p.value=me,t.emit(\"pick\",me,!0);break}},pe=ue=>{t.emit(\"panel-change\",p.value.toDate(),ue,j.value)};return t.emit(\"set-picker-option\",[\"isValidValue\",ie]),t.emit(\"set-picker-option\",[\"formatToString\",ge]),t.emit(\"set-picker-option\",[\"parseUserInput\",ke]),t.emit(\"set-picker-option\",[\"handleKeydown\",Ie]),ce(()=>f.value,ue=>{ue&&(p.value=xe())},{immediate:!0}),ce(()=>e.parsedValue,ue=>{if(ue){if(D.value===\"dates\"||Array.isArray(ue))return;p.value=ue}else p.value=xe()},{immediate:!0}),{handleTimePick:Pe,handleTimePickClose:Ee,onTimePickerInputFocus:be,timePickerVisible:de,visibleTime:Q,visibleDate:ae,showTime:W,changeToNow:J,onConfirm:q,footerVisible:Y,handleYearPick:M,showMonthPicker:E,showYearPicker:K,handleMonthPick:B,hasShortcuts:z,shortcuts:i,arrowControl:d,disabledDate:l,cellClassName:s,selectionMode:D,handleShortcutClick:N,prevYear_:I,nextYear_:L,prevMonth_:T,nextMonth_:_,innerDate:p,t:n,yearLabel:F,currentView:j,month:m,handleDatePick:O,handleVisibleTimeChange:Be,handleVisibleDateChange:te,timeFormat:ne,userInputTime:S,userInputDate:C}}}),Boe={class:\"el-picker-panel__body-wrapper\"},Voe={key:0,class:\"el-picker-panel__sidebar\"},zoe=[\"onClick\"],Hoe={class:\"el-picker-panel__body\"},joe={key:0,class:\"el-date-picker__time-header\"},Koe={class:\"el-date-picker__editor-wrap\"},Woe={class:\"el-date-picker__editor-wrap\"},Uoe=[\"aria-label\"],Yoe=[\"aria-label\"],qoe=[\"aria-label\"],Goe=[\"aria-label\"],Xoe={class:\"el-picker-panel__content\"},Zoe={class:\"el-picker-panel__footer\"};function Joe(e,t,n,r,a,o){const i=we(\"el-input\"),l=we(\"time-pick-panel\"),s=we(\"d-arrow-left\"),c=we(\"el-icon\"),d=we(\"arrow-left\"),f=we(\"d-arrow-right\"),p=we(\"arrow-right\"),v=we(\"date-table\"),m=we(\"year-table\"),y=we(\"month-table\"),b=we(\"el-button\"),C=pa(\"clickoutside\");return R(),X(\"div\",{class:U([\"el-picker-panel el-date-picker\",[{\"has-sidebar\":e.$slots.sidebar||e.hasShortcuts,\"has-time\":e.showTime}]])},[Z(\"div\",Boe,[Oe(e.$slots,\"sidebar\",{class:\"el-picker-panel__sidebar\"}),e.hasShortcuts?(R(),X(\"div\",Voe,[(R(!0),X(Fe,null,Rt(e.shortcuts,(S,w)=>(R(),X(\"button\",{key:w,type:\"button\",class:\"el-picker-panel__shortcut\",onClick:k=>e.handleShortcutClick(S)},Me(S.text),9,zoe))),128))])):se(\"v-if\",!0),Z(\"div\",Hoe,[e.showTime?(R(),X(\"div\",joe,[Z(\"span\",Koe,[g(i,{placeholder:e.t(\"el.datepicker.selectDate\"),\"model-value\":e.visibleDate,size:\"small\",onInput:t[0]||(t[0]=S=>e.userInputDate=S),onChange:e.handleVisibleDateChange},null,8,[\"placeholder\",\"model-value\",\"onChange\"])]),at((R(),X(\"span\",Woe,[g(i,{placeholder:e.t(\"el.datepicker.selectTime\"),\"model-value\":e.visibleTime,size:\"small\",onFocus:e.onTimePickerInputFocus,onInput:t[1]||(t[1]=S=>e.userInputTime=S),onChange:e.handleVisibleTimeChange},null,8,[\"placeholder\",\"model-value\",\"onFocus\",\"onChange\"]),g(l,{visible:e.timePickerVisible,format:e.timeFormat,\"time-arrow-control\":e.arrowControl,\"parsed-value\":e.innerDate,onPick:e.handleTimePick},null,8,[\"visible\",\"format\",\"time-arrow-control\",\"parsed-value\",\"onPick\"])])),[[C,e.handleTimePickClose]])])):se(\"v-if\",!0),at(Z(\"div\",{class:U([\"el-date-picker__header\",{\"el-date-picker__header--bordered\":e.currentView===\"year\"||e.currentView===\"month\"}])},[Z(\"button\",{type:\"button\",\"aria-label\":e.t(\"el.datepicker.prevYear\"),class:\"el-picker-panel__icon-btn el-date-picker__prev-btn d-arrow-left\",onClick:t[2]||(t[2]=(...S)=>e.prevYear_&&e.prevYear_(...S))},[g(c,null,{default:re(()=>[g(s)]),_:1})],8,Uoe),at(Z(\"button\",{type:\"button\",\"aria-label\":e.t(\"el.datepicker.prevMonth\"),class:\"el-picker-panel__icon-btn el-date-picker__prev-btn arrow-left\",onClick:t[3]||(t[3]=(...S)=>e.prevMonth_&&e.prevMonth_(...S))},[g(c,null,{default:re(()=>[g(d)]),_:1})],8,Yoe),[[_t,e.currentView===\"date\"]]),Z(\"span\",{role:\"button\",class:\"el-date-picker__header-label\",onClick:t[4]||(t[4]=(...S)=>e.showYearPicker&&e.showYearPicker(...S))},Me(e.yearLabel),1),at(Z(\"span\",{role:\"button\",class:U([\"el-date-picker__header-label\",{active:e.currentView===\"month\"}]),onClick:t[5]||(t[5]=(...S)=>e.showMonthPicker&&e.showMonthPicker(...S))},Me(e.t(`el.datepicker.month${e.month+1}`)),3),[[_t,e.currentView===\"date\"]]),Z(\"button\",{type:\"button\",\"aria-label\":e.t(\"el.datepicker.nextYear\"),class:\"el-picker-panel__icon-btn el-date-picker__next-btn d-arrow-right\",onClick:t[6]||(t[6]=(...S)=>e.nextYear_&&e.nextYear_(...S))},[g(c,null,{default:re(()=>[g(f)]),_:1})],8,qoe),at(Z(\"button\",{type:\"button\",\"aria-label\":e.t(\"el.datepicker.nextMonth\"),class:\"el-picker-panel__icon-btn el-date-picker__next-btn arrow-right\",onClick:t[7]||(t[7]=(...S)=>e.nextMonth_&&e.nextMonth_(...S))},[g(c,null,{default:re(()=>[g(p)]),_:1})],8,Goe),[[_t,e.currentView===\"date\"]])],2),[[_t,e.currentView!==\"time\"]]),Z(\"div\",Xoe,[e.currentView===\"date\"?(R(),fe(v,{key:0,\"selection-mode\":e.selectionMode,date:e.innerDate,\"parsed-value\":e.parsedValue,\"disabled-date\":e.disabledDate,onPick:e.handleDatePick},null,8,[\"selection-mode\",\"date\",\"parsed-value\",\"disabled-date\",\"onPick\"])):se(\"v-if\",!0),e.currentView===\"year\"?(R(),fe(m,{key:1,date:e.innerDate,\"disabled-date\":e.disabledDate,\"parsed-value\":e.parsedValue,onPick:e.handleYearPick},null,8,[\"date\",\"disabled-date\",\"parsed-value\",\"onPick\"])):se(\"v-if\",!0),e.currentView===\"month\"?(R(),fe(y,{key:2,date:e.innerDate,\"parsed-value\":e.parsedValue,\"disabled-date\":e.disabledDate,onPick:e.handleMonthPick},null,8,[\"date\",\"parsed-value\",\"disabled-date\",\"onPick\"])):se(\"v-if\",!0)])])]),at(Z(\"div\",Zoe,[at(g(b,{size:\"small\",type:\"text\",class:\"el-picker-panel__link-btn\",onClick:e.changeToNow},{default:re(()=>[yt(Me(e.t(\"el.datepicker.now\")),1)]),_:1},8,[\"onClick\"]),[[_t,e.selectionMode!==\"dates\"]]),g(b,{plain:\"\",size:\"small\",class:\"el-picker-panel__link-btn\",onClick:e.onConfirm},{default:re(()=>[yt(Me(e.t(\"el.datepicker.confirm\")),1)]),_:1},8,[\"onClick\"])],512),[[_t,e.footerVisible&&e.currentView===\"date\"]])],2)}var Qoe=Ae(Foe,[[\"render\",Joe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/panel-date-pick.vue\"]]);const eie=G({directives:{clickoutside:Is},components:{TimePickPanel:rw,DateTable:u5,ElInput:Ra,ElButton:xa,ElIcon:ft,DArrowLeft:Fm,ArrowLeft:Es,DArrowRight:Bm,ArrowRight:Da},props:{unlinkPanels:Boolean,parsedValue:{type:Array},type:{type:String,required:!0,validator:mE}},emits:[\"pick\",\"set-picker-option\",\"calendar-change\",\"panel-change\"],setup(e,t){const{t:n,lang:r}=ln(),a=H(mt().locale(r.value)),o=H(mt().locale(r.value).add(1,\"month\")),i=H(null),l=H(null),s=H({min:null,max:null}),c=H({min:null,max:null}),d=x(()=>`${a.value.year()} ${n(\"el.datepicker.year\")} ${n(`el.datepicker.month${a.value.month()+1}`)}`),f=x(()=>`${o.value.year()} ${n(\"el.datepicker.year\")} ${n(`el.datepicker.month${o.value.month()+1}`)}`),p=x(()=>a.value.year()),v=x(()=>a.value.month()),m=x(()=>o.value.year()),y=x(()=>o.value.month()),b=x(()=>!!je.length),C=x(()=>s.value.min!==null?s.value.min:i.value?i.value.format(O.value):\"\"),S=x(()=>s.value.max!==null?s.value.max:l.value||i.value?(l.value||i.value).format(O.value):\"\"),w=x(()=>c.value.min!==null?c.value.min:i.value?i.value.format($.value):\"\"),k=x(()=>c.value.max!==null?c.value.max:l.value||i.value?(l.value||i.value).format($.value):\"\"),$=x(()=>RM(He)),O=x(()=>DM(He)),T=()=>{a.value=a.value.subtract(1,\"year\"),e.unlinkPanels||(o.value=a.value.add(1,\"month\")),z(\"year\")},_=()=>{a.value=a.value.subtract(1,\"month\"),e.unlinkPanels||(o.value=a.value.add(1,\"month\")),z(\"month\")},I=()=>{e.unlinkPanels?o.value=o.value.add(1,\"year\"):(a.value=a.value.add(1,\"year\"),o.value=a.value.add(1,\"month\")),z(\"year\")},L=()=>{e.unlinkPanels?o.value=o.value.add(1,\"month\"):(a.value=a.value.add(1,\"month\"),o.value=a.value.add(1,\"month\")),z(\"month\")},j=()=>{a.value=a.value.add(1,\"year\"),z(\"year\")},F=()=>{a.value=a.value.add(1,\"month\"),z(\"month\")},N=()=>{o.value=o.value.subtract(1,\"year\"),z(\"year\")},D=()=>{o.value=o.value.subtract(1,\"month\"),z(\"month\")},z=$e=>{t.emit(\"panel-change\",[a.value.toDate(),o.value.toDate()],$e)},B=x(()=>{const $e=(v.value+1)%12,Ve=v.value+1>=12?1:0;return e.unlinkPanels&&new Date(p.value+Ve,$e)<new Date(m.value,y.value)}),M=x(()=>e.unlinkPanels&&m.value*12+y.value-(p.value*12+v.value+1)>=12),E=$e=>Array.isArray($e)&&$e[0]&&$e[1]&&$e[0].valueOf()<=$e[1].valueOf(),K=H({endDate:null,selecting:!1}),W=x(()=>!(i.value&&l.value&&!K.value.selecting&&E([i.value,l.value]))),Y=$e=>{K.value=$e},q=$e=>{K.value.selecting=$e,$e||(K.value.endDate=null)},J=x(()=>e.type===\"datetime\"||e.type===\"datetimerange\"),ne=($e=!1)=>{E([i.value,l.value])&&t.emit(\"pick\",[i.value,l.value],$e)},oe=($e,Ve)=>{if(!!$e)return lt?mt(lt[Ve]||lt).locale(r.value).year($e.year()).month($e.month()).date($e.date()):$e},Q=($e,Ve=!0)=>{const st=$e.minDate,Dt=$e.maxDate,Ut=oe(st,0),Ft=oe(Dt,1);l.value===Ft&&i.value===Ut||(t.emit(\"calendar-change\",[st.toDate(),Dt&&Dt.toDate()]),l.value=Ft,i.value=Ut,!(!Ve||J.value)&&ne())},ae=$e=>{const Ve=typeof $e.value==\"function\"?$e.value():$e.value;if(Ve){t.emit(\"pick\",[mt(Ve[0]).locale(r.value),mt(Ve[1]).locale(r.value)]);return}$e.onClick&&$e.onClick(t)},de=H(!1),be=H(!1),Ee=()=>{de.value=!1},Pe=()=>{be.value=!1},Be=($e,Ve)=>{s.value[Ve]=$e;const st=mt($e,O.value).locale(r.value);if(st.isValid()){if(ee&&ee(st.toDate()))return;Ve===\"min\"?(a.value=st,i.value=(i.value||a.value).year(st.year()).month(st.month()).date(st.date()),e.unlinkPanels||(o.value=st.add(1,\"month\"),l.value=i.value.add(1,\"month\"))):(o.value=st,l.value=(l.value||o.value).year(st.year()).month(st.month()).date(st.date()),e.unlinkPanels||(a.value=st.subtract(1,\"month\"),i.value=l.value.subtract(1,\"month\")))}},te=($e,Ve)=>{s.value[Ve]=null},ie=($e,Ve)=>{c.value[Ve]=$e;const st=mt($e,$.value).locale(r.value);st.isValid()&&(Ve===\"min\"?(de.value=!0,i.value=(i.value||a.value).hour(st.hour()).minute(st.minute()).second(st.second()),(!l.value||l.value.isBefore(i.value))&&(l.value=i.value)):(be.value=!0,l.value=(l.value||o.value).hour(st.hour()).minute(st.minute()).second(st.second()),o.value=l.value,l.value&&l.value.isBefore(i.value)&&(i.value=l.value)))},ge=($e,Ve)=>{c.value[Ve]=null,Ve===\"min\"?(a.value=i.value,de.value=!1):(o.value=l.value,be.value=!1)},ke=($e,Ve,st)=>{c.value.min||($e&&(a.value=$e,i.value=(i.value||a.value).hour($e.hour()).minute($e.minute()).second($e.second())),st||(de.value=Ve),(!l.value||l.value.isBefore(i.value))&&(l.value=i.value,o.value=$e))},xe=($e,Ve,st)=>{c.value.max||($e&&(o.value=$e,l.value=(l.value||o.value).hour($e.hour()).minute($e.minute()).second($e.second())),st||(be.value=Ve),l.value&&l.value.isBefore(i.value)&&(i.value=l.value))},Ie=()=>{a.value=ue()[0],o.value=a.value.add(1,\"month\"),t.emit(\"pick\",null)},ye=$e=>Array.isArray($e)?$e.map(Ve=>Ve.format(He)):$e.format(He),pe=$e=>Array.isArray($e)?$e.map(Ve=>mt(Ve,He).locale(r.value)):mt($e,He).locale(r.value),ue=()=>{let $e;if(Array.isArray(_e.value)){const Ve=mt(_e.value[0]);let st=mt(_e.value[1]);return e.unlinkPanels||(st=Ve.add(1,\"month\")),[Ve,st]}else _e.value?$e=mt(_e.value):$e=mt();return $e=$e.locale(r.value),[$e,$e.add(1,\"month\")]};t.emit(\"set-picker-option\",[\"isValidValue\",E]),t.emit(\"set-picker-option\",[\"parseUserInput\",pe]),t.emit(\"set-picker-option\",[\"formatToString\",ye]),t.emit(\"set-picker-option\",[\"handleClear\",Ie]);const Ce=ve(\"EP_PICKER_BASE\"),{shortcuts:je,disabledDate:ee,cellClassName:me,format:He,defaultTime:lt,arrowControl:Ye,clearable:he}=Ce.props,_e=yn(Ce.props,\"defaultValue\");return ce(()=>_e.value,$e=>{if($e){const Ve=ue();i.value=null,l.value=null,a.value=Ve[0],o.value=Ve[1]}},{immediate:!0}),ce(()=>e.parsedValue,$e=>{if($e&&$e.length===2)if(i.value=$e[0],l.value=$e[1],a.value=i.value,e.unlinkPanels&&l.value){const Ve=i.value.year(),st=i.value.month(),Dt=l.value.year(),Ut=l.value.month();o.value=Ve===Dt&&st===Ut?l.value.add(1,\"month\"):l.value}else o.value=a.value.add(1,\"month\"),l.value&&(o.value=o.value.hour(l.value.hour()).minute(l.value.minute()).second(l.value.second()));else{const Ve=ue();i.value=null,l.value=null,a.value=Ve[0],o.value=Ve[1]}},{immediate:!0}),{shortcuts:je,disabledDate:ee,cellClassName:me,minTimePickerVisible:de,maxTimePickerVisible:be,handleMinTimeClose:Ee,handleMaxTimeClose:Pe,handleShortcutClick:ae,rangeState:K,minDate:i,maxDate:l,handleRangePick:Q,onSelect:q,handleChangeRange:Y,btnDisabled:W,enableYearArrow:M,enableMonthArrow:B,rightPrevMonth:D,rightPrevYear:N,rightNextMonth:L,rightNextYear:I,leftPrevMonth:_,leftPrevYear:T,leftNextMonth:F,leftNextYear:j,hasShortcuts:b,leftLabel:d,rightLabel:f,leftDate:a,rightDate:o,showTime:J,t:n,minVisibleDate:C,maxVisibleDate:S,minVisibleTime:w,maxVisibleTime:k,arrowControl:Ye,handleDateInput:Be,handleDateChange:te,handleTimeInput:ie,handleTimeChange:ge,handleMinTimePick:ke,handleMaxTimePick:xe,handleClear:Ie,handleConfirm:ne,timeFormat:$,clearable:he}}}),tie={class:\"el-picker-panel__body-wrapper\"},nie={key:0,class:\"el-picker-panel__sidebar\"},rie=[\"onClick\"],aie={class:\"el-picker-panel__body\"},oie={key:0,class:\"el-date-range-picker__time-header\"},iie={class:\"el-date-range-picker__editors-wrap\"},lie={class:\"el-date-range-picker__time-picker-wrap\"},sie={class:\"el-date-range-picker__time-picker-wrap\"},uie={class:\"el-date-range-picker__editors-wrap is-right\"},cie={class:\"el-date-range-picker__time-picker-wrap\"},die={class:\"el-date-range-picker__time-picker-wrap\"},fie={class:\"el-picker-panel__content el-date-range-picker__content is-left\"},hie={class:\"el-date-range-picker__header\"},pie=[\"disabled\"],vie=[\"disabled\"],mie={class:\"el-picker-panel__content el-date-range-picker__content is-right\"},gie={class:\"el-date-range-picker__header\"},yie=[\"disabled\"],bie=[\"disabled\"],Cie={key:0,class:\"el-picker-panel__footer\"};function wie(e,t,n,r,a,o){const i=we(\"el-input\"),l=we(\"time-pick-panel\"),s=we(\"arrow-right\"),c=we(\"el-icon\"),d=we(\"d-arrow-left\"),f=we(\"arrow-left\"),p=we(\"d-arrow-right\"),v=we(\"date-table\"),m=we(\"el-button\"),y=pa(\"clickoutside\");return R(),X(\"div\",{class:U([\"el-picker-panel el-date-range-picker\",[{\"has-sidebar\":e.$slots.sidebar||e.hasShortcuts,\"has-time\":e.showTime}]])},[Z(\"div\",tie,[Oe(e.$slots,\"sidebar\",{class:\"el-picker-panel__sidebar\"}),e.hasShortcuts?(R(),X(\"div\",nie,[(R(!0),X(Fe,null,Rt(e.shortcuts,(b,C)=>(R(),X(\"button\",{key:C,type:\"button\",class:\"el-picker-panel__shortcut\",onClick:S=>e.handleShortcutClick(b)},Me(b.text),9,rie))),128))])):se(\"v-if\",!0),Z(\"div\",aie,[e.showTime?(R(),X(\"div\",oie,[Z(\"span\",iie,[Z(\"span\",lie,[g(i,{size:\"small\",disabled:e.rangeState.selecting,placeholder:e.t(\"el.datepicker.startDate\"),class:\"el-date-range-picker__editor\",\"model-value\":e.minVisibleDate,onInput:t[0]||(t[0]=b=>e.handleDateInput(b,\"min\")),onChange:t[1]||(t[1]=b=>e.handleDateChange(b,\"min\"))},null,8,[\"disabled\",\"placeholder\",\"model-value\"])]),at((R(),X(\"span\",sie,[g(i,{size:\"small\",class:\"el-date-range-picker__editor\",disabled:e.rangeState.selecting,placeholder:e.t(\"el.datepicker.startTime\"),\"model-value\":e.minVisibleTime,onFocus:t[2]||(t[2]=b=>e.minTimePickerVisible=!0),onInput:t[3]||(t[3]=b=>e.handleTimeInput(b,\"min\")),onChange:t[4]||(t[4]=b=>e.handleTimeChange(b,\"min\"))},null,8,[\"disabled\",\"placeholder\",\"model-value\"]),g(l,{visible:e.minTimePickerVisible,format:e.timeFormat,\"datetime-role\":\"start\",\"time-arrow-control\":e.arrowControl,\"parsed-value\":e.leftDate,onPick:e.handleMinTimePick},null,8,[\"visible\",\"format\",\"time-arrow-control\",\"parsed-value\",\"onPick\"])])),[[y,e.handleMinTimeClose]])]),Z(\"span\",null,[g(c,null,{default:re(()=>[g(s)]),_:1})]),Z(\"span\",uie,[Z(\"span\",cie,[g(i,{size:\"small\",class:\"el-date-range-picker__editor\",disabled:e.rangeState.selecting,placeholder:e.t(\"el.datepicker.endDate\"),\"model-value\":e.maxVisibleDate,readonly:!e.minDate,onInput:t[5]||(t[5]=b=>e.handleDateInput(b,\"max\")),onChange:t[6]||(t[6]=b=>e.handleDateChange(b,\"max\"))},null,8,[\"disabled\",\"placeholder\",\"model-value\",\"readonly\"])]),at((R(),X(\"span\",die,[g(i,{size:\"small\",class:\"el-date-range-picker__editor\",disabled:e.rangeState.selecting,placeholder:e.t(\"el.datepicker.endTime\"),\"model-value\":e.maxVisibleTime,readonly:!e.minDate,onFocus:t[7]||(t[7]=b=>e.minDate&&(e.maxTimePickerVisible=!0)),onInput:t[8]||(t[8]=b=>e.handleTimeInput(b,\"max\")),onChange:t[9]||(t[9]=b=>e.handleTimeChange(b,\"max\"))},null,8,[\"disabled\",\"placeholder\",\"model-value\",\"readonly\"]),g(l,{\"datetime-role\":\"end\",visible:e.maxTimePickerVisible,format:e.timeFormat,\"time-arrow-control\":e.arrowControl,\"parsed-value\":e.rightDate,onPick:e.handleMaxTimePick},null,8,[\"visible\",\"format\",\"time-arrow-control\",\"parsed-value\",\"onPick\"])])),[[y,e.handleMaxTimeClose]])])])):se(\"v-if\",!0),Z(\"div\",fie,[Z(\"div\",hie,[Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn d-arrow-left\",onClick:t[10]||(t[10]=(...b)=>e.leftPrevYear&&e.leftPrevYear(...b))},[g(c,null,{default:re(()=>[g(d)]),_:1})]),Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn arrow-left\",onClick:t[11]||(t[11]=(...b)=>e.leftPrevMonth&&e.leftPrevMonth(...b))},[g(c,null,{default:re(()=>[g(f)]),_:1})]),e.unlinkPanels?(R(),X(\"button\",{key:0,type:\"button\",disabled:!e.enableYearArrow,class:U([{\"is-disabled\":!e.enableYearArrow},\"el-picker-panel__icon-btn d-arrow-right\"]),onClick:t[12]||(t[12]=(...b)=>e.leftNextYear&&e.leftNextYear(...b))},[g(c,null,{default:re(()=>[g(p)]),_:1})],10,pie)):se(\"v-if\",!0),e.unlinkPanels?(R(),X(\"button\",{key:1,type:\"button\",disabled:!e.enableMonthArrow,class:U([{\"is-disabled\":!e.enableMonthArrow},\"el-picker-panel__icon-btn arrow-right\"]),onClick:t[13]||(t[13]=(...b)=>e.leftNextMonth&&e.leftNextMonth(...b))},[g(c,null,{default:re(()=>[g(s)]),_:1})],10,vie)):se(\"v-if\",!0),Z(\"div\",null,Me(e.leftLabel),1)]),g(v,{\"selection-mode\":\"range\",date:e.leftDate,\"min-date\":e.minDate,\"max-date\":e.maxDate,\"range-state\":e.rangeState,\"disabled-date\":e.disabledDate,\"cell-class-name\":e.cellClassName,onChangerange:e.handleChangeRange,onPick:e.handleRangePick,onSelect:e.onSelect},null,8,[\"date\",\"min-date\",\"max-date\",\"range-state\",\"disabled-date\",\"cell-class-name\",\"onChangerange\",\"onPick\",\"onSelect\"])]),Z(\"div\",mie,[Z(\"div\",gie,[e.unlinkPanels?(R(),X(\"button\",{key:0,type:\"button\",disabled:!e.enableYearArrow,class:U([{\"is-disabled\":!e.enableYearArrow},\"el-picker-panel__icon-btn d-arrow-left\"]),onClick:t[14]||(t[14]=(...b)=>e.rightPrevYear&&e.rightPrevYear(...b))},[g(c,null,{default:re(()=>[g(d)]),_:1})],10,yie)):se(\"v-if\",!0),e.unlinkPanels?(R(),X(\"button\",{key:1,type:\"button\",disabled:!e.enableMonthArrow,class:U([{\"is-disabled\":!e.enableMonthArrow},\"el-picker-panel__icon-btn arrow-left\"]),onClick:t[15]||(t[15]=(...b)=>e.rightPrevMonth&&e.rightPrevMonth(...b))},[g(c,null,{default:re(()=>[g(f)]),_:1})],10,bie)):se(\"v-if\",!0),Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn d-arrow-right\",onClick:t[16]||(t[16]=(...b)=>e.rightNextYear&&e.rightNextYear(...b))},[g(c,null,{default:re(()=>[g(p)]),_:1})]),Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn arrow-right\",onClick:t[17]||(t[17]=(...b)=>e.rightNextMonth&&e.rightNextMonth(...b))},[g(c,null,{default:re(()=>[g(s)]),_:1})]),Z(\"div\",null,Me(e.rightLabel),1)]),g(v,{\"selection-mode\":\"range\",date:e.rightDate,\"min-date\":e.minDate,\"max-date\":e.maxDate,\"range-state\":e.rangeState,\"disabled-date\":e.disabledDate,\"cell-class-name\":e.cellClassName,onChangerange:e.handleChangeRange,onPick:e.handleRangePick,onSelect:e.onSelect},null,8,[\"date\",\"min-date\",\"max-date\",\"range-state\",\"disabled-date\",\"cell-class-name\",\"onChangerange\",\"onPick\",\"onSelect\"])])])]),e.showTime?(R(),X(\"div\",Cie,[e.clearable?(R(),fe(m,{key:0,size:\"small\",type:\"text\",class:\"el-picker-panel__link-btn\",onClick:e.handleClear},{default:re(()=>[yt(Me(e.t(\"el.datepicker.clear\")),1)]),_:1},8,[\"onClick\"])):se(\"v-if\",!0),g(m,{plain:\"\",size:\"small\",class:\"el-picker-panel__link-btn\",disabled:e.btnDisabled,onClick:t[18]||(t[18]=b=>e.handleConfirm(!1))},{default:re(()=>[yt(Me(e.t(\"el.datepicker.confirm\")),1)]),_:1},8,[\"disabled\"])])):se(\"v-if\",!0)],2)}var Sie=Ae(eie,[[\"render\",wie],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/panel-date-range.vue\"]]);const kie=G({components:{MonthTable:c5,ElIcon:ft,DArrowLeft:Fm,DArrowRight:Bm},props:{unlinkPanels:Boolean,parsedValue:{type:Array}},emits:[\"pick\",\"set-picker-option\"],setup(e,t){const{t:n,lang:r}=ln(),a=H(mt().locale(r.value)),o=H(mt().locale(r.value).add(1,\"year\")),i=x(()=>!!F.length),l=B=>{const M=typeof B.value==\"function\"?B.value():B.value;if(M){t.emit(\"pick\",[mt(M[0]).locale(r.value),mt(M[1]).locale(r.value)]);return}B.onClick&&B.onClick(t)},s=()=>{a.value=a.value.subtract(1,\"year\"),e.unlinkPanels||(o.value=o.value.subtract(1,\"year\"))},c=()=>{e.unlinkPanels||(a.value=a.value.add(1,\"year\")),o.value=o.value.add(1,\"year\")},d=()=>{a.value=a.value.add(1,\"year\")},f=()=>{o.value=o.value.subtract(1,\"year\")},p=x(()=>`${a.value.year()} ${n(\"el.datepicker.year\")}`),v=x(()=>`${o.value.year()} ${n(\"el.datepicker.year\")}`),m=x(()=>a.value.year()),y=x(()=>o.value.year()===a.value.year()?a.value.year()+1:o.value.year()),b=x(()=>e.unlinkPanels&&y.value>m.value+1),C=H(null),S=H(null),w=H({endDate:null,selecting:!1}),k=B=>{w.value=B},$=(B,M=!0)=>{const E=B.minDate,K=B.maxDate;S.value===K&&C.value===E||(S.value=K,C.value=E,M&&T())},O=B=>Array.isArray(B)&&B&&B[0]&&B[1]&&B[0].valueOf()<=B[1].valueOf(),T=(B=!1)=>{O([C.value,S.value])&&t.emit(\"pick\",[C.value,S.value],B)},_=B=>{w.value.selecting=B,B||(w.value.endDate=null)},I=B=>B.map(M=>M.format(D)),L=()=>{let B;if(Array.isArray(z.value)){const M=mt(z.value[0]);let E=mt(z.value[1]);return e.unlinkPanels||(E=M.add(1,\"year\")),[M,E]}else z.value?B=mt(z.value):B=mt();return B=B.locale(r.value),[B,B.add(1,\"year\")]};t.emit(\"set-picker-option\",[\"formatToString\",I]);const j=ve(\"EP_PICKER_BASE\"),{shortcuts:F,disabledDate:N,format:D}=j.props,z=yn(j.props,\"defaultValue\");return ce(()=>z.value,B=>{if(B){const M=L();a.value=M[0],o.value=M[1]}},{immediate:!0}),ce(()=>e.parsedValue,B=>{if(B&&B.length===2)if(C.value=B[0],S.value=B[1],a.value=C.value,e.unlinkPanels&&S.value){const M=C.value.year(),E=S.value.year();o.value=M===E?S.value.add(1,\"year\"):S.value}else o.value=a.value.add(1,\"year\");else{const M=L();C.value=null,S.value=null,a.value=M[0],o.value=M[1]}},{immediate:!0}),{shortcuts:F,disabledDate:N,onSelect:_,handleRangePick:$,rangeState:w,handleChangeRange:k,minDate:C,maxDate:S,enableYearArrow:b,leftLabel:p,rightLabel:v,leftNextYear:d,leftPrevYear:s,rightNextYear:c,rightPrevYear:f,t:n,leftDate:a,rightDate:o,hasShortcuts:i,handleShortcutClick:l}}}),$ie={class:\"el-picker-panel__body-wrapper\"},Oie={key:0,class:\"el-picker-panel__sidebar\"},Pie=[\"onClick\"],Tie={class:\"el-picker-panel__body\"},xie={class:\"el-picker-panel__content el-date-range-picker__content is-left\"},_ie={class:\"el-date-range-picker__header\"},Eie=[\"disabled\"],Mie={class:\"el-picker-panel__content el-date-range-picker__content is-right\"},Iie={class:\"el-date-range-picker__header\"},Nie=[\"disabled\"];function Aie(e,t,n,r,a,o){const i=we(\"d-arrow-left\"),l=we(\"el-icon\"),s=we(\"d-arrow-right\"),c=we(\"month-table\");return R(),X(\"div\",{class:U([\"el-picker-panel el-date-range-picker\",[{\"has-sidebar\":e.$slots.sidebar||e.hasShortcuts}]])},[Z(\"div\",$ie,[Oe(e.$slots,\"sidebar\",{class:\"el-picker-panel__sidebar\"}),e.hasShortcuts?(R(),X(\"div\",Oie,[(R(!0),X(Fe,null,Rt(e.shortcuts,(d,f)=>(R(),X(\"button\",{key:f,type:\"button\",class:\"el-picker-panel__shortcut\",onClick:p=>e.handleShortcutClick(d)},Me(d.text),9,Pie))),128))])):se(\"v-if\",!0),Z(\"div\",Tie,[Z(\"div\",xie,[Z(\"div\",_ie,[Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn d-arrow-left\",onClick:t[0]||(t[0]=(...d)=>e.leftPrevYear&&e.leftPrevYear(...d))},[g(l,null,{default:re(()=>[g(i)]),_:1})]),e.unlinkPanels?(R(),X(\"button\",{key:0,type:\"button\",disabled:!e.enableYearArrow,class:U([{\"is-disabled\":!e.enableYearArrow},\"el-picker-panel__icon-btn d-arrow-right\"]),onClick:t[1]||(t[1]=(...d)=>e.leftNextYear&&e.leftNextYear(...d))},[g(l,null,{default:re(()=>[g(s)]),_:1})],10,Eie)):se(\"v-if\",!0),Z(\"div\",null,Me(e.leftLabel),1)]),g(c,{\"selection-mode\":\"range\",date:e.leftDate,\"min-date\":e.minDate,\"max-date\":e.maxDate,\"range-state\":e.rangeState,\"disabled-date\":e.disabledDate,onChangerange:e.handleChangeRange,onPick:e.handleRangePick,onSelect:e.onSelect},null,8,[\"date\",\"min-date\",\"max-date\",\"range-state\",\"disabled-date\",\"onChangerange\",\"onPick\",\"onSelect\"])]),Z(\"div\",Mie,[Z(\"div\",Iie,[e.unlinkPanels?(R(),X(\"button\",{key:0,type:\"button\",disabled:!e.enableYearArrow,class:U([{\"is-disabled\":!e.enableYearArrow},\"el-picker-panel__icon-btn d-arrow-left\"]),onClick:t[2]||(t[2]=(...d)=>e.rightPrevYear&&e.rightPrevYear(...d))},[g(l,null,{default:re(()=>[g(i)]),_:1})],10,Nie)):se(\"v-if\",!0),Z(\"button\",{type:\"button\",class:\"el-picker-panel__icon-btn d-arrow-right\",onClick:t[3]||(t[3]=(...d)=>e.rightNextYear&&e.rightNextYear(...d))},[g(l,null,{default:re(()=>[g(s)]),_:1})]),Z(\"div\",null,Me(e.rightLabel),1)]),g(c,{\"selection-mode\":\"range\",date:e.rightDate,\"min-date\":e.minDate,\"max-date\":e.maxDate,\"range-state\":e.rangeState,\"disabled-date\":e.disabledDate,onChangerange:e.handleChangeRange,onPick:e.handleRangePick,onSelect:e.onSelect},null,8,[\"date\",\"min-date\",\"max-date\",\"range-state\",\"disabled-date\",\"onChangerange\",\"onPick\",\"onSelect\"])])])])],2)}var Die=Ae(kie,[[\"render\",Aie],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/date-picker/src/date-picker-com/panel-month-range.vue\"]]);mt.extend(bM);mt.extend(loe);mt.extend(tw);mt.extend(soe);mt.extend(uoe);mt.extend(coe);mt.extend(doe);mt.extend(foe);const Rie=function(e){return e===\"daterange\"||e===\"datetimerange\"?Sie:e===\"monthrange\"?Die:Qoe};var Lie=G({name:\"ElDatePicker\",install:null,props:Ke(Te({},nw),{type:{type:String,default:\"date\"}}),emits:[\"update:modelValue\"],setup(e,t){ot(\"ElPopperOptions\",e.popperOptions),ot(s5,{ctx:t});const n=H(null),r=Ke(Te({},e),{focus:(a=!0)=>{var o;(o=n.value)==null||o.focus(a)}});return t.expose(r),()=>{var a;const o=(a=e.format)!=null?a:$te[e.type]||td;return qe(wM,Ke(Te({},e),{format:o,type:e.type,ref:n,\"onUpdate:modelValue\":i=>t.emit(\"update:modelValue\",i)}),{default:i=>qe(Rie(e.type),i),\"range-separator\":()=>Oe(t.slots,\"range-separator\")})}}});const wp=Lie;wp.install=e=>{e.component(wp.name,wp)};const Fie=wp,lw=\"elDescriptions\";var j4=G({name:\"ElDescriptionsCell\",props:{cell:{type:Object},tag:{type:String},type:{type:String}},setup(){return{descriptions:ve(lw,{})}},render(){var e,t,n,r,a,o;const i=XX(this.cell),{border:l,direction:s}=this.descriptions,c=s===\"vertical\",d=((n=(t=(e=this.cell)==null?void 0:e.children)==null?void 0:t.label)==null?void 0:n.call(t))||i.label,f=(o=(a=(r=this.cell)==null?void 0:r.children)==null?void 0:a.default)==null?void 0:o.call(a),p=i.span,v=i.align?`is-${i.align}`:\"\",m=i.labelAlign?`is-${i.labelAlign}`:v,y=i.className,b=i.labelClassName,C={width:oo(i.width),minWidth:oo(i.minWidth)},S=De(\"descriptions\");switch(this.type){case\"label\":return qe(this.tag,{style:C,class:[S.e(\"cell\"),S.e(\"label\"),S.is(\"bordered-label\",l),S.is(\"vertical-label\",c),m,b],colSpan:c?p:1},d);case\"content\":return qe(this.tag,{style:C,class:[S.e(\"cell\"),S.e(\"content\"),S.is(\"bordered-content\",l),S.is(\"vertical-content\",c),v,y],colSpan:c?p:p*2-1},f);default:return qe(\"td\",{style:C,class:[S.e(\"cell\"),v],colSpan:p},[qe(\"span\",{class:[S.e(\"label\"),b]},d),qe(\"span\",{class:[S.e(\"content\"),y]},f)])}}});const Bie=G({name:\"ElDescriptionsRow\",components:{[j4.name]:j4},props:{row:{type:Array}},setup(){return{descriptions:ve(lw,{})}}}),Vie={key:1};function zie(e,t,n,r,a,o){const i=we(\"el-descriptions-cell\");return e.descriptions.direction===\"vertical\"?(R(),X(Fe,{key:0},[Z(\"tr\",null,[(R(!0),X(Fe,null,Rt(e.row,(l,s)=>(R(),fe(i,{key:`tr1-${s}`,cell:l,tag:\"th\",type:\"label\"},null,8,[\"cell\"]))),128))]),Z(\"tr\",null,[(R(!0),X(Fe,null,Rt(e.row,(l,s)=>(R(),fe(i,{key:`tr2-${s}`,cell:l,tag:\"td\",type:\"content\"},null,8,[\"cell\"]))),128))])],64)):(R(),X(\"tr\",Vie,[(R(!0),X(Fe,null,Rt(e.row,(l,s)=>(R(),X(Fe,{key:`tr3-${s}`},[e.descriptions.border?(R(),X(Fe,{key:0},[g(i,{cell:l,tag:\"td\",type:\"label\"},null,8,[\"cell\"]),g(i,{cell:l,tag:\"td\",type:\"content\"},null,8,[\"cell\"])],64)):(R(),fe(i,{key:1,cell:l,tag:\"td\",type:\"both\"},null,8,[\"cell\"]))],64))),128))]))}var K4=Ae(Bie,[[\"render\",zie],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/descriptions/src/descriptions-row.vue\"]]);const Hie=G({name:\"ElDescriptions\",components:{[K4.name]:K4},props:{border:{type:Boolean,default:!1},column:{type:Number,default:3},direction:{type:String,default:\"horizontal\"},size:{type:String,validator:va},title:{type:String,default:\"\"},extra:{type:String,default:\"\"}},setup(e,{slots:t}){ot(lw,e);const n=Gn(),r=De(\"descriptions\"),a=x(()=>[r.b(),r.is(r.m(n.value),!!n.value)]),o=s=>{const c=Array.isArray(s)?s:[s],d=[];return c.forEach(f=>{Array.isArray(f.children)?d.push(...o(f.children)):d.push(f)}),d},i=(s,c,d,f=!1)=>(s.props||(s.props={}),c>d&&(s.props.span=d),f&&(s.props.span=c),s);return{descriptionKls:a,getRows:()=>{var s;const c=o((s=t.default)==null?void 0:s.call(t)).filter(m=>{var y;return((y=m==null?void 0:m.type)==null?void 0:y.name)===\"ElDescriptionsItem\"}),d=[];let f=[],p=e.column,v=0;return c.forEach((m,y)=>{var b;const C=((b=m.props)==null?void 0:b.span)||1;if(y<c.length-1&&(v+=C>p?p:C),y===c.length-1){const S=e.column-v%e.column;f.push(i(m,S,p,!0)),d.push(f);return}C<p?(p-=C,f.push(m)):(f.push(i(m,C,p)),d.push(f),p=e.column,f=[])}),d},ns:r}}});function jie(e,t,n,r,a,o){const i=we(\"el-descriptions-row\");return R(),X(\"div\",{class:U(e.descriptionKls)},[e.title||e.extra||e.$slots.title||e.$slots.extra?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"header\"))},[Z(\"div\",{class:U(e.ns.e(\"title\"))},[Oe(e.$slots,\"title\",{},()=>[yt(Me(e.title),1)])],2),Z(\"div\",{class:U(e.ns.e(\"extra\"))},[Oe(e.$slots,\"extra\",{},()=>[yt(Me(e.extra),1)])],2)],2)):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.e(\"body\"))},[Z(\"table\",{class:U([e.ns.e(\"table\"),e.ns.is(\"bordered\",e.border)])},[Z(\"tbody\",null,[(R(!0),X(Fe,null,Rt(e.getRows(),(l,s)=>(R(),fe(i,{key:s,row:l},null,8,[\"row\"]))),128))])],2)],2)],2)}var Kie=Ae(Hie,[[\"render\",jie],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/descriptions/src/index.vue\"]]),d5=G({name:\"ElDescriptionsItem\",props:{label:{type:String,default:\"\"},span:{type:Number,default:1},width:{type:[String,Number],default:\"\"},minWidth:{type:[String,Number],default:\"\"},align:{type:String,default:\"left\"},labelAlign:{type:String,default:\"\"},className:{type:String,default:\"\"},labelClassName:{type:String,default:\"\"}}});const Wie=xt(Kie,{DescriptionsItem:d5}),Uie=En(d5),Yie=Ze({mask:{type:Boolean,default:!0},customMaskEvent:{type:Boolean,default:!1},overlayClass:{type:Le([String,Array,Object])},zIndex:{type:Le([String,Number])}}),qie={click:e=>e instanceof MouseEvent};var Gie=G({name:\"ElOverlay\",props:Yie,emits:qie,setup(e,{slots:t,emit:n}){const r=De(\"overlay\"),a=s=>{n(\"click\",s)},{onClick:o,onMousedown:i,onMouseup:l}=HC(e.customMaskEvent?void 0:a);return()=>e.mask?g(\"div\",{class:[r.b(),e.overlayClass],style:{zIndex:e.zIndex},onClick:o,onMousedown:i,onMouseup:l},[Oe(t,\"default\")],ka.STYLE|ka.CLASS|ka.PROPS,[\"onClick\",\"onMouseup\",\"onMousedown\"]):qe(\"div\",{class:e.overlayClass,style:{zIndex:e.zIndex,position:\"fixed\",top:\"0px\",right:\"0px\",bottom:\"0px\",left:\"0px\"}},[Oe(t,\"default\")])}});const sw=Gie,f5=Ze({center:{type:Boolean,default:!1},closeIcon:{type:wr,default:\"\"},customClass:{type:String,default:\"\"},draggable:{type:Boolean,default:!1},fullscreen:{type:Boolean,default:!1},showClose:{type:Boolean,default:!0},title:{type:String,default:\"\"}}),Xie={close:()=>!0},Zie=[\"aria-label\"],Jie={name:\"ElDialogContent\"},Qie=G(Ke(Te({},Jie),{props:f5,emits:Xie,setup(e){const{Close:t}=KX,{dialogRef:n,headerRef:r,ns:a,style:o}=ve(OE);return(i,l)=>(R(),X(\"div\",{ref_key:\"dialogRef\",ref:n,class:U([A(a).b(),A(a).is(\"fullscreen\",i.fullscreen),A(a).is(\"draggable\",i.draggable),{[A(a).m(\"center\")]:i.center},i.customClass]),\"aria-modal\":\"true\",role:\"dialog\",\"aria-label\":i.title||\"dialog\",style:Xe(A(o)),onClick:l[1]||(l[1]=dt(()=>{},[\"stop\"]))},[Z(\"div\",{ref_key:\"headerRef\",ref:r,class:U(A(a).e(\"header\"))},[Oe(i.$slots,\"title\",{},()=>[Z(\"span\",{class:U(A(a).e(\"title\"))},Me(i.title),3)])],2),Z(\"div\",{class:U(A(a).e(\"body\"))},[Oe(i.$slots,\"default\")],2),i.$slots.footer?(R(),X(\"div\",{key:0,class:U(A(a).e(\"footer\"))},[Oe(i.$slots,\"footer\")],2)):se(\"v-if\",!0),i.showClose?(R(),X(\"button\",{key:1,\"aria-label\":\"close\",class:U(A(a).e(\"headerbtn\")),type:\"button\",onClick:l[0]||(l[0]=s=>i.$emit(\"close\"))},[g(A(ft),{class:U(A(a).e(\"close\"))},{default:re(()=>[(R(),fe(Kt(i.closeIcon||A(t))))]),_:1},8,[\"class\"])],2)):se(\"v-if\",!0)],14,Zie))}}));var ele=Ae(Qie,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dialog/src/dialog-content.vue\"]]);const h5=Ze(Ke(Te({},f5),{appendToBody:{type:Boolean,default:!1},beforeClose:{type:Le(Function)},destroyOnClose:{type:Boolean,default:!1},closeOnClickModal:{type:Boolean,default:!0},closeOnPressEscape:{type:Boolean,default:!0},lockScroll:{type:Boolean,default:!0},modal:{type:Boolean,default:!0},openDelay:{type:Number,default:0},closeDelay:{type:Number,default:0},top:{type:String},modelValue:{type:Boolean,required:!0},modalClass:String,width:{type:[String,Number]},zIndex:{type:Number},trapFocus:{type:Boolean,default:!1}})),p5={open:()=>!0,opened:()=>!0,close:()=>!0,closed:()=>!0,[Pt]:e=>yr(e),openAutoFocus:()=>!0,closeAutoFocus:()=>!0},v5=(e,t)=>{const r=$t().emit,{nextZIndex:a}=Pi();let o=\"\";const i=H(!1),l=H(!1),s=H(!1),c=H(e.zIndex||a());let d,f;const p=x(()=>Yt(e.width)?`${e.width}px`:e.width),v=x(()=>{const T={},_=\"--el-dialog\";return e.fullscreen||(e.top&&(T[`${_}-margin-top`]=e.top),e.width&&(T[`${_}-width`]=p.value)),T});function m(){r(\"opened\")}function y(){r(\"closed\"),r(Pt,!1),e.destroyOnClose&&(s.value=!1)}function b(){r(\"close\")}function C(){f==null||f(),d==null||d(),e.openDelay&&e.openDelay>0?{stop:d}=gs(()=>$(),e.openDelay):$()}function S(){d==null||d(),f==null||f(),e.closeDelay&&e.closeDelay>0?{stop:f}=gs(()=>O(),e.closeDelay):O()}function w(){function T(_){_||(l.value=!0,i.value=!1)}e.beforeClose?e.beforeClose(T):S()}function k(){e.closeOnClickModal&&w()}function $(){!Bt||(i.value=!0)}function O(){i.value=!1}return e.lockScroll&&RE(i),e.closeOnPressEscape&&LE({handleClose:w},i),FE(i),ce(()=>e.modelValue,T=>{T?(l.value=!1,C(),s.value=!0,r(\"open\"),c.value=e.zIndex?c.value++:a(),Ne(()=>{t.value&&(t.value.scrollTop=0)})):i.value&&S()}),ce(()=>e.fullscreen,T=>{!t.value||(T?(o=t.value.style.transform,t.value.style.transform=\"\"):t.value.style.transform=o)}),et(()=>{e.modelValue&&(i.value=!0,s.value=!0,C())}),{afterEnter:m,afterLeave:y,beforeLeave:b,handleClose:w,onModalClick:k,close:S,doClose:O,closed:l,style:v,rendered:s,visible:i,zIndex:c}},tle={name:\"ElDialog\"},nle=G(Ke(Te({},tle),{props:h5,emits:p5,setup(e,{expose:t}){const n=e,r=De(\"dialog\"),a=H(),o=H(),{visible:i,style:l,rendered:s,zIndex:c,afterEnter:d,afterLeave:f,beforeLeave:p,handleClose:v,onModalClick:m}=v5(n,a);ot(OE,{dialogRef:a,headerRef:o,ns:r,rendered:s,style:l});const y=HC(m),b=x(()=>n.draggable&&!n.fullscreen);return DE(a,o,b),t({visible:i}),(C,S)=>(R(),fe(Ps,{to:\"body\",disabled:!C.appendToBody},[g(Vn,{name:\"dialog-fade\",onAfterEnter:A(d),onAfterLeave:A(f),onBeforeLeave:A(p)},{default:re(()=>[at(g(A(sw),{\"custom-mask-event\":\"\",mask:C.modal,\"overlay-class\":C.modalClass,\"z-index\":A(c)},{default:re(()=>[Z(\"div\",{class:U(`${A(r).namespace.value}-overlay-dialog`),onClick:S[0]||(S[0]=(...w)=>A(y).onClick&&A(y).onClick(...w)),onMousedown:S[1]||(S[1]=(...w)=>A(y).onMousedown&&A(y).onMousedown(...w)),onMouseup:S[2]||(S[2]=(...w)=>A(y).onMouseup&&A(y).onMouseup(...w))},[A(s)?(R(),fe(ele,{key:0,\"custom-class\":C.customClass,center:C.center,\"close-icon\":C.closeIcon,draggable:A(b),fullscreen:C.fullscreen,\"show-close\":C.showClose,style:Xe(A(l)),title:C.title,onClose:A(v)},sl({title:re(()=>[Oe(C.$slots,\"title\")]),default:re(()=>[Oe(C.$slots,\"default\")]),_:2},[C.$slots.footer?{name:\"footer\",fn:re(()=>[Oe(C.$slots,\"footer\")])}:void 0]),1032,[\"custom-class\",\"center\",\"close-icon\",\"draggable\",\"fullscreen\",\"show-close\",\"style\",\"title\",\"onClose\"])):se(\"v-if\",!0)],34)]),_:3},8,[\"mask\",\"overlay-class\",\"z-index\"]),[[_t,A(i)]])]),_:3},8,[\"onAfterEnter\",\"onAfterLeave\",\"onBeforeLeave\"])],8,[\"disabled\"]))}}));var rle=Ae(nle,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dialog/src/dialog.vue\"]]);const ale=xt(rle),ole=Ze({direction:{type:String,values:[\"horizontal\",\"vertical\"],default:\"horizontal\"},contentPosition:{type:String,values:[\"left\",\"center\",\"right\"],default:\"center\"},borderStyle:{type:Le(String),default:\"solid\"}}),ile={name:\"ElDivider\"},lle=G(Ke(Te({},ile),{props:ole,setup(e){const t=e,n=De(\"divider\"),r=x(()=>({\"--el-border-style\":t.borderStyle}));return(a,o)=>(R(),X(\"div\",{class:U([A(n).b(),A(n).m(a.direction)]),style:Xe(A(r))},[a.$slots.default&&a.direction!==\"vertical\"?(R(),X(\"div\",{key:0,class:U([A(n).e(\"text\"),A(n).is(a.contentPosition)])},[Oe(a.$slots,\"default\")],2)):se(\"v-if\",!0)],6))}}));var sle=Ae(lle,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/divider/src/divider.vue\"]]);const ule=xt(sle),cle=Ze(Ke(Te({},h5),{direction:{type:String,default:\"rtl\",values:[\"ltr\",\"rtl\",\"ttb\",\"btt\"]},size:{type:[String,Number],default:\"30%\"},withHeader:{type:Boolean,default:!0},modalFade:{type:Boolean,default:!0}})),dle=p5,fle=G({name:\"ElDrawer\",components:{ElOverlay:sw,ElIcon:ft,Close:Ma},directives:{TrapFocus:kM},props:cle,emits:dle,setup(e,t){const n=H(),r=De(\"drawer\"),a=x(()=>e.direction===\"rtl\"||e.direction===\"ltr\"),o=x(()=>typeof e.size==\"number\"?`${e.size}px`:e.size);return Ke(Te({},v5(e,t,n)),{drawerRef:n,isHorizontal:a,drawerSize:o,ns:r})}}),hle=[\"aria-labelledby\",\"aria-label\"],ple=[\"id\"],vle=[\"title\"],mle=[\"aria-label\"];function gle(e,t,n,r,a,o){const i=we(\"close\"),l=we(\"el-icon\"),s=we(\"el-overlay\"),c=pa(\"trap-focus\");return R(),fe(Ps,{to:\"body\",disabled:!e.appendToBody},[g(Vn,{name:e.ns.b(\"fade\"),onAfterEnter:e.afterEnter,onAfterLeave:e.afterLeave,onBeforeLeave:e.beforeLeave},{default:re(()=>[at(g(s,{mask:e.modal,\"overlay-class\":e.modalClass,\"z-index\":e.zIndex,onClick:e.onModalClick},{default:re(()=>[at((R(),X(\"div\",{ref:\"drawerRef\",\"aria-modal\":\"true\",\"aria-labelledby\":e.ns.e(\"title\"),\"aria-label\":e.title,class:U([e.ns.b(),e.direction,e.visible&&\"open\",e.customClass]),style:Xe(e.isHorizontal?\"width: \"+e.drawerSize:\"height: \"+e.drawerSize),role:\"dialog\",onClick:t[1]||(t[1]=dt(()=>{},[\"stop\"]))},[e.withHeader?(R(),X(\"header\",{key:0,id:e.ns.e(\"title\"),class:U(e.ns.e(\"header\"))},[Oe(e.$slots,\"title\",{},()=>[Z(\"span\",{role:\"heading\",title:e.title},Me(e.title),9,vle)]),e.showClose?(R(),X(\"button\",{key:0,\"aria-label\":\"close \"+(e.title||\"drawer\"),class:U(e.ns.e(\"close-btn\")),type:\"button\",onClick:t[0]||(t[0]=(...d)=>e.handleClose&&e.handleClose(...d))},[g(l,{class:U(e.ns.e(\"close\"))},{default:re(()=>[g(i)]),_:1},8,[\"class\"])],10,mle)):se(\"v-if\",!0)],10,ple)):se(\"v-if\",!0),e.rendered?(R(),X(\"section\",{key:1,class:U(e.ns.e(\"body\"))},[Oe(e.$slots,\"default\")],2)):se(\"v-if\",!0),e.$slots.footer?(R(),X(\"div\",{key:2,class:U(e.ns.e(\"footer\"))},[Oe(e.$slots,\"footer\")],2)):se(\"v-if\",!0)],14,hle)),[[c]])]),_:3},8,[\"mask\",\"overlay-class\",\"z-index\",\"onClick\"]),[[_t,e.visible]])]),_:3},8,[\"name\",\"onAfterEnter\",\"onAfterLeave\",\"onBeforeLeave\"])],8,[\"disabled\"])}var yle=Ae(fle,[[\"render\",gle],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/drawer/src/drawer.vue\"]]);const ble=xt(yle),m5=e=>{const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:r=>{const a=r.tagName===\"INPUT\"&&r.type===\"hidden\";return r.disabled||r.hidden||a?NodeFilter.FILTER_SKIP:r.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t},W4=(e,t)=>{for(const n of e)if(!Cle(n,t))return n},Cle=(e,t)=>{if(getComputedStyle(e).visibility===\"hidden\")return!0;for(;e;){if(t&&e===t)return!1;if(getComputedStyle(e).display===\"none\")return!0;e=e.parentElement}return!1},wle=e=>{const t=m5(e),n=W4(t,e),r=W4(t.reverse(),e);return[n,r]},Sle=e=>e instanceof HTMLInputElement&&\"select\"in e,Al=(e,t)=>{if(e&&e.focus){const n=document.activeElement;e.focus({preventScroll:!0}),e!==n&&Sle(e)&&t&&e.select()}};function U4(e,t){const n=[...e],r=e.indexOf(t);return r!==-1&&n.splice(r,1),n}const kle=()=>{let e=[];return{push:r=>{const a=e[0];a&&r!==a&&a.pause(),e=U4(e,r),e.unshift(r)},remove:r=>{var a,o;e=U4(e,r),(o=(a=e[0])==null?void 0:a.resume)==null||o.call(a)}}},$le=(e,t=!1)=>{const n=document.activeElement;for(const r of e)if(Al(r,t),document.activeElement!==n)return},Y4=kle(),py=\"focus-trap.focus-on-mount\",vy=\"focus-trap.focus-on-unmount\",q4={cancelable:!0,bubbles:!1},G4=\"mountOnFocus\",X4=\"unmountOnFocus\",g5=Symbol(\"elFocusTrap\"),Ole=G({name:\"ElFocusTrap\",inheritAttrs:!1,props:{loop:Boolean,trapped:Boolean},emits:[G4,X4],setup(e,{emit:t}){const n=H(),r=H(null);let a,o;const i={paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}},l=v=>{if(!e.loop&&!e.trapped||i.paused)return;const{key:m,altKey:y,ctrlKey:b,metaKey:C,currentTarget:S,shiftKey:w}=v,{loop:k}=e,$=m===Ge.tab&&!y&&!b&&!C,O=document.activeElement;if($&&O){const T=S,[_,I]=wle(T);_&&I?!w&&O===I?(v.preventDefault(),k&&Al(_,!0)):w&&O===_&&(v.preventDefault(),k&&Al(I,!0)):O===T&&v.preventDefault()}};ot(g5,{focusTrapRef:r,onKeydown:l});const s=v=>{t(G4,v)},c=v=>t(X4,v),d=v=>{const m=A(r);if(i.paused||!m)return;const y=v.target;y&&m.contains(y)?o=y:Al(o,!0)},f=v=>{const m=A(r);i.paused||!m||m.contains(v.relatedTarget)||Al(o,!0)},p=()=>{document.removeEventListener(\"focusin\",d),document.removeEventListener(\"focusout\",f)};return et(()=>{const v=A(r);if(v){Y4.push(i);const m=document.activeElement;if(a=m,!v.contains(m)){const b=new Event(py,q4);v.addEventListener(py,s),v.dispatchEvent(b),b.defaultPrevented||Ne(()=>{$le(m5(v),!0),document.activeElement===m&&Al(v)})}}ce(()=>e.trapped,m=>{m?(document.addEventListener(\"focusin\",d),document.addEventListener(\"focusout\",f)):p()},{immediate:!0})}),Lt(()=>{p();const v=A(r);if(v){v.removeEventListener(py,s);const m=new Event(vy,q4);v.addEventListener(vy,c),v.dispatchEvent(m),m.defaultPrevented||Al(a!=null?a:document.body,!0),v.removeEventListener(vy,s),Y4.remove(i)}}),{focusTrapRef:n,forwardRef:r,onKeydown:l}}});function Ple(e,t,n,r,a,o){return Oe(e.$slots,\"default\")}var Tle=Ae(Ole,[[\"render\",Ple],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/focus-trap/src/focus-trap.vue\"]]);const xle=G({inheritAttrs:!1});function _le(e,t,n,r,a,o){return Oe(e.$slots,\"default\")}var Ele=Ae(xle,[[\"render\",_le],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/collection/src/collection.vue\"]]);const Mle=G({name:\"ElCollectionItem\",inheritAttrs:!1});function Ile(e,t,n,r,a,o){return Oe(e.$slots,\"default\")}var Nle=Ae(Mle,[[\"render\",Ile],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/collection/src/collection-item.vue\"]]);const y5=\"data-el-collection-item\",b5=e=>{const t=`El${e}Collection`,n=`${t}Item`,r=Symbol(t),a=Symbol(n),o=Ke(Te({},Ele),{name:t,setup(){const l=H(null),s=new Map;ot(r,{itemMap:s,getItems:()=>{const d=A(l);if(!d)return[];const f=Array.from(d.querySelectorAll(`[${y5}]`));return[...s.values()].sort((m,y)=>f.indexOf(m.ref)-f.indexOf(y.ref))},collectionRef:l})}}),i=Ke(Te({},Nle),{name:n,setup(l,{attrs:s}){const c=H(null),d=ve(r,void 0);ot(a,{collectionItemRef:c}),et(()=>{const f=A(c);f&&d.itemMap.set(f,Te({ref:f},s))}),Lt(()=>{const f=A(c);d.itemMap.delete(f)})}});return{COLLECTION_INJECTION_KEY:r,COLLECTION_ITEM_INJECTION_KEY:a,ElCollection:o,ElCollectionItem:i}},Ale=Ze({style:{type:Le([String,Array,Object])},currentTabId:{type:Le(String)},defaultCurrentTabId:String,loop:Boolean,dir:{type:String,values:[\"ltr\",\"rtl\"],default:\"ltr\"},orientation:{type:Le(String)},onBlur:Function,onFocus:Function,onMousedown:Function}),{ElCollection:Dle,ElCollectionItem:Rle,COLLECTION_INJECTION_KEY:uw,COLLECTION_ITEM_INJECTION_KEY:Lle}=b5(\"RovingFocusGroup\"),cw=Symbol(\"elRovingFocusGroup\"),C5=Symbol(\"elRovingFocusGroupItem\"),Fle={ArrowLeft:\"prev\",ArrowUp:\"prev\",ArrowRight:\"next\",ArrowDown:\"next\",PageUp:\"first\",Home:\"first\",PageDown:\"last\",End:\"last\"},Ble=(e,t)=>{if(t!==\"rtl\")return e;switch(e){case Ge.right:return Ge.left;case Ge.left:return Ge.right;default:return e}},Vle=(e,t,n)=>{const r=Ble(e.key,n);if(!(t===\"vertical\"&&[Ge.left,Ge.right].includes(r))&&!(t===\"horizontal\"&&[Ge.up,Ge.down].includes(r)))return Fle[r]},zle=(e,t)=>e.map((n,r)=>e[(r+t)%e.length]),dw=e=>{const{activeElement:t}=document;for(const n of e)if(n===t||(n.focus(),t!==document.activeElement))return},Z4=\"currentTabIdChange\",my=\"rovingFocusGroup.entryFocus\",Hle={bubbles:!1,cancelable:!0},jle=G({name:\"ElRovingFocusGroupImpl\",inheritAttrs:!1,props:Ale,emits:[Z4,\"entryFocus\"],setup(e,{emit:t}){var n;const r=H((n=e.currentTabId||e.defaultCurrentTabId)!=null?n:null),a=H(!1),o=H(!1),i=H(null),{getItems:l}=ve(uw,void 0),s=x(()=>[{outline:\"none\"},e.style]),c=y=>{t(Z4,y)},d=()=>{a.value=!0},f=Tn(y=>{var b;(b=e.onMousedown)==null||b.call(e,y)},()=>{o.value=!0}),p=Tn(y=>{var b;(b=e.onFocus)==null||b.call(e,y)},y=>{const b=!A(o),{target:C,currentTarget:S}=y;if(C===S&&b&&!A(a)){const w=new Event(my,Hle);if(S==null||S.dispatchEvent(w),!w.defaultPrevented){const k=l().filter(I=>I.focusable),$=k.find(I=>I.active),O=k.find(I=>I.id===A(r)),_=[$,O,...k].filter(Boolean).map(I=>I.ref);dw(_)}}o.value=!1}),v=Tn(y=>{var b;(b=e.onBlur)==null||b.call(e,y)},()=>{a.value=!1}),m=(...y)=>{t(\"entryFocus\",...y)};ot(cw,{currentTabbedId:Cf(r),loop:yn(e,\"loop\"),tabIndex:x(()=>A(a)?-1:0),rovingFocusGroupRef:i,rovingFocusGroupRootStyle:s,orientation:yn(e,\"orientation\"),dir:yn(e,\"dir\"),onItemFocus:c,onItemShiftTab:d,onBlur:v,onFocus:p,onMousedown:f}),ce(()=>e.currentTabId,y=>{r.value=y!=null?y:null}),et(()=>{const y=A(i);gn(y,my,m)}),Lt(()=>{const y=A(i);Bn(y,my,m)})}});function Kle(e,t,n,r,a,o){return Oe(e.$slots,\"default\")}var Wle=Ae(jle,[[\"render\",Kle],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/roving-focus-group/src/roving-focus-group-impl.vue\"]]);const Ule=G({name:\"ElRovingFocusGroup\",components:{ElFocusGroupCollection:Dle,ElRovingFocusGroupImpl:Wle}});function Yle(e,t,n,r,a,o){const i=we(\"el-roving-focus-group-impl\"),l=we(\"el-focus-group-collection\");return R(),fe(l,null,{default:re(()=>[g(i,Za(ll(e.$attrs)),{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},16)]),_:3})}var qle=Ae(Ule,[[\"render\",Yle],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/roving-focus-group/src/roving-focus-group.vue\"]]);const Gle=G({components:{ElRovingFocusCollectionItem:Rle},props:{focusable:{type:Boolean,default:!0},active:{type:Boolean,default:!1}},emits:[\"mousedown\",\"focus\",\"keydown\"],setup(e,{emit:t}){const{currentTabbedId:n,loop:r,onItemFocus:a,onItemShiftTab:o}=ve(cw,void 0),{getItems:i}=ve(uw,void 0),l=jC(),s=H(null),c=Tn(v=>{t(\"mousedown\",v)},v=>{e.focusable?a(A(l)):v.preventDefault()}),d=Tn(v=>{t(\"focus\",v)},()=>{a(A(l))}),f=Tn(v=>{t(\"keydown\",v)},v=>{const{key:m,shiftKey:y,target:b,currentTarget:C}=v;if(m===Ge.tab&&y){o();return}if(b!==C)return;const S=Vle(v);if(S){v.preventDefault();let k=i().filter($=>$.focusable).map($=>$.ref);switch(S){case\"last\":{k.reverse();break}case\"prev\":case\"next\":{S===\"prev\"&&k.reverse();const $=k.indexOf(C);k=r.value?zle(k,$+1):k.slice($+1);break}}Ne(()=>{dw(k)})}}),p=x(()=>n.value===A(l));return ot(C5,{rovingFocusGroupItemRef:s,tabIndex:x(()=>A(p)?0:-1),handleMousedown:c,handleFocus:d,handleKeydown:f}),{id:l,handleKeydown:f,handleFocus:d,handleMousedown:c}}});function Xle(e,t,n,r,a,o){const i=we(\"el-roving-focus-collection-item\");return R(),fe(i,{id:e.id,focusable:e.focusable,active:e.active},{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},8,[\"id\",\"focusable\",\"active\"])}var Zle=Ae(Gle,[[\"render\",Xle],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/roving-focus-group/src/roving-focus-item.vue\"]]);const Sp=Ze({trigger:qd.trigger,effect:Ke(Te({},mr.effect),{default:\"light\"}),type:{type:Le(String)},placement:{type:Le(String),default:\"bottom\"},popperOptions:{type:Le(Object),default:()=>({})},size:{type:String,default:\"\"},splitButton:Boolean,hideOnClick:{type:Boolean,default:!0},loop:{type:Boolean},showTimeout:{type:Number,default:150},hideTimeout:{type:Number,default:150},tabindex:{type:Le([Number,String]),default:0},maxHeight:{type:Le([Number,String]),default:\"\"},popperClass:{type:String,default:\"\"},disabled:{type:Boolean,default:!1},buttonProps:{type:Le(Object)}}),w5=Ze({command:{type:[Object,String,Number],default:()=>({})},disabled:Boolean,divided:Boolean,textValue:String,icon:{type:wr}}),Jle=Ze({onKeydown:{type:Le(Function)}}),Qle=[Ge.down,Ge.pageDown,Ge.home],S5=[Ge.up,Ge.pageUp,Ge.end],ese=[...Qle,...S5],{ElCollection:tse,ElCollectionItem:nse,COLLECTION_INJECTION_KEY:rse,COLLECTION_ITEM_INJECTION_KEY:ase}=b5(\"Dropdown\"),fw=Symbol(\"elDropdown\"),{ButtonGroup:ose}=xa,ise=G({name:\"ElDropdown\",components:{ElButton:xa,ElFocusTrap:Tle,ElButtonGroup:ose,ElScrollbar:xi,ElDropdownCollection:tse,ElTooltip:Ur,ElRovingFocusGroup:qle,ElIcon:ft,ArrowDown:_s},props:Sp,emits:[\"visible-change\",\"click\",\"command\"],setup(e,{emit:t}){const n=$t(),r=De(\"dropdown\"),a=H(),o=H(),i=H(null),l=H(null),s=H(null),c=H(null),d=H(!1),f=x(()=>({maxHeight:oo(e.maxHeight)})),p=x(()=>[r.m(b.value)]);function v(){m()}function m(){var _;(_=i.value)==null||_.onClose()}function y(){var _;(_=i.value)==null||_.onOpen()}const b=Gn();function C(..._){t(\"command\",..._)}function S(){}function w(){const _=A(l);_==null||_.focus(),c.value=null}function k(_){c.value=_}function $(_){d.value||(_.preventDefault(),_.stopImmediatePropagation())}return ot(fw,{contentRef:l,isUsingKeyboard:d,onItemEnter:S,onItemLeave:w}),ot(\"elDropdown\",{instance:n,dropdownSize:b,handleClick:v,commandHandler:C,trigger:yn(e,\"trigger\"),hideOnClick:yn(e,\"hideOnClick\")}),{ns:r,scrollbar:s,wrapStyle:f,dropdownTriggerKls:p,dropdownSize:b,currentTabId:c,handleCurrentTabIdChange:k,handlerMainButtonClick:_=>{t(\"click\",_)},handleEntryFocus:$,handleClose:m,handleOpen:y,onMountOnFocus:_=>{var I,L;_.preventDefault(),(L=(I=l.value)==null?void 0:I.focus)==null||L.call(I,{preventScroll:!0})},popperRef:i,triggeringElementRef:a,referenceElementRef:o}}});function lse(e,t,n,r,a,o){var i;const l=we(\"el-dropdown-collection\"),s=we(\"el-roving-focus-group\"),c=we(\"el-focus-trap\"),d=we(\"el-scrollbar\"),f=we(\"el-tooltip\"),p=we(\"el-button\"),v=we(\"arrow-down\"),m=we(\"el-icon\"),y=we(\"el-button-group\");return R(),X(\"div\",{class:U([e.ns.b(),e.ns.is(\"disabled\",e.disabled)])},[g(f,{ref:\"popperRef\",effect:e.effect,\"fallback-placements\":[\"bottom\",\"top\"],\"popper-options\":e.popperOptions,\"gpu-acceleration\":!1,\"hide-after\":e.trigger===\"hover\"?e.hideTimeout:0,\"manual-mode\":!0,placement:e.placement,\"popper-class\":[e.ns.e(\"popper\"),e.popperClass],\"reference-element\":(i=e.referenceElementRef)==null?void 0:i.$el,trigger:e.trigger,\"show-after\":e.trigger===\"hover\"?e.showTimeout:0,\"stop-popper-mouse-event\":!1,\"virtual-ref\":e.triggeringElementRef,\"virtual-triggering\":e.splitButton,disabled:e.disabled,\"append-to-body\":\"\",pure:\"\",transition:`${e.ns.namespace.value}-zoom-in-top`,persistent:\"\",onShow:t[0]||(t[0]=b=>e.$emit(\"visible-change\",!0)),onHide:t[1]||(t[1]=b=>e.$emit(\"visible-change\",!1))},sl({content:re(()=>[g(d,{ref:\"scrollbar\",\"wrap-style\":e.wrapStyle,tag:\"div\",\"view-class\":e.ns.e(\"list\")},{default:re(()=>[g(c,{trapped:\"\",onMountOnFocus:e.onMountOnFocus},{default:re(()=>[g(s,{loop:e.loop,\"current-tab-id\":e.currentTabId,orientation:\"horizontal\",onCurrentTabIdChange:e.handleCurrentTabIdChange,onEntryFocus:e.handleEntryFocus},{default:re(()=>[g(l,null,{default:re(()=>[Oe(e.$slots,\"dropdown\")]),_:3})]),_:3},8,[\"loop\",\"current-tab-id\",\"onCurrentTabIdChange\",\"onEntryFocus\"])]),_:3},8,[\"onMountOnFocus\"])]),_:3},8,[\"wrap-style\",\"view-class\"])]),_:2},[e.splitButton?void 0:{name:\"default\",fn:re(()=>[Z(\"div\",{class:U(e.dropdownTriggerKls)},[Oe(e.$slots,\"default\")],2)])}]),1032,[\"effect\",\"popper-options\",\"hide-after\",\"placement\",\"popper-class\",\"reference-element\",\"trigger\",\"show-after\",\"virtual-ref\",\"virtual-triggering\",\"disabled\",\"transition\"]),e.splitButton?(R(),fe(y,{key:0},{default:re(()=>[g(p,hn({ref:\"referenceElementRef\"},e.buttonProps,{size:e.dropdownSize,type:e.type,disabled:e.disabled,onClick:e.handlerMainButtonClick}),{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},16,[\"size\",\"type\",\"disabled\",\"onClick\"]),g(p,hn({ref:\"triggeringElementRef\"},e.buttonProps,{size:e.dropdownSize,type:e.type,class:e.ns.e(\"caret-button\"),disabled:e.disabled}),{default:re(()=>[g(m,{class:U(e.ns.e(\"icon\"))},{default:re(()=>[g(v)]),_:1},8,[\"class\"])]),_:1},16,[\"size\",\"type\",\"class\",\"disabled\"])]),_:3})):se(\"v-if\",!0)],2)}var sse=Ae(ise,[[\"render\",lse],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dropdown/src/dropdown.vue\"]]);const use=G({name:\"DropdownItemImpl\",components:{ElIcon:ft},props:w5,emits:[\"pointermove\",\"pointerleave\",\"click\",\"clickimpl\"],setup(e,{emit:t}){const n=De(\"dropdown\"),{collectionItemRef:r}=ve(ase,void 0),{collectionItemRef:a}=ve(Lle,void 0),{rovingFocusGroupItemRef:o,tabIndex:i,handleFocus:l,handleKeydown:s,handleMousedown:c}=ve(C5,void 0),d=FC(r,a,o),f=Tn(p=>{const{code:v}=p;if(v===Ge.enter||v===Ge.space)return p.preventDefault(),p.stopImmediatePropagation(),t(\"clickimpl\",p),!0},s);return{ns:n,itemRef:d,dataset:{[y5]:\"\"},tabIndex:i,handleFocus:l,handleKeydown:f,handleMousedown:c}}}),cse=[\"aria-disabled\",\"tabindex\"];function dse(e,t,n,r,a,o){const i=we(\"el-icon\");return R(),X(Fe,null,[e.divided?(R(),X(\"li\",hn({key:0,class:e.ns.bem(\"menu\",\"item\",\"divided\")},e.$attrs),null,16)):se(\"v-if\",!0),Z(\"li\",hn({ref:e.itemRef},Te(Te({},e.dataset),e.$attrs),{\"aria-disabled\":e.disabled,class:[e.ns.be(\"menu\",\"item\"),e.ns.is(\"disabled\",e.disabled)],tabindex:e.tabIndex,role:\"menuitem\",onClick:t[0]||(t[0]=l=>e.$emit(\"clickimpl\",l)),onFocus:t[1]||(t[1]=(...l)=>e.handleFocus&&e.handleFocus(...l)),onKeydown:t[2]||(t[2]=(...l)=>e.handleKeydown&&e.handleKeydown(...l)),onMousedown:t[3]||(t[3]=(...l)=>e.handleMousedown&&e.handleMousedown(...l)),onPointermove:t[4]||(t[4]=l=>e.$emit(\"pointermove\",l)),onPointerleave:t[5]||(t[5]=l=>e.$emit(\"pointerleave\",l))}),[e.icon?(R(),fe(i,{key:0},{default:re(()=>[(R(),fe(Kt(e.icon)))]),_:1})):se(\"v-if\",!0),Oe(e.$slots,\"default\")],16,cse)],64)}var fse=Ae(use,[[\"render\",dse],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dropdown/src/dropdown-item-impl.vue\"]]);const k5=()=>{const e=ve(\"elDropdown\",{}),t=x(()=>e==null?void 0:e.dropdownSize);return{elDropdown:e,_elDropdownSize:t}},hse=G({name:\"ElDropdownItem\",components:{ElDropdownCollectionItem:nse,ElRovingFocusItem:Zle,ElDropdownItemImpl:fse},inheritAttrs:!1,props:w5,emits:[\"pointermove\",\"pointerleave\",\"click\"],setup(e,{emit:t,attrs:n}){const{elDropdown:r}=k5(),a=$t(),o=H(null),i=x(()=>{var v,m;return(m=(v=A(o))==null?void 0:v.textContent)!=null?m:\"\"}),{onItemEnter:l,onItemLeave:s}=ve(fw,void 0),c=Tn(v=>(t(\"pointermove\",v),v.defaultPrevented),z$(v=>{var m;e.disabled?s(v):(l(v),v.defaultPrevented||(m=v.currentTarget)==null||m.focus())})),d=Tn(v=>(t(\"pointerleave\",v),v.defaultPrevented),z$(v=>{s(v)})),f=Tn(v=>(t(\"click\",v),v.defaultPrevented),v=>{var m,y,b;if(e.disabled){v.stopImmediatePropagation();return}(m=r==null?void 0:r.hideOnClick)!=null&&m.value&&((y=r.handleClick)==null||y.call(r)),(b=r.commandHandler)==null||b.call(r,e.command,a,v)}),p=x(()=>Te(Te({},e),n));return{handleClick:f,handlePointerMove:c,handlePointerLeave:d,textContent:i,propsAndAttrs:p}}});function pse(e,t,n,r,a,o){var i;const l=we(\"el-dropdown-item-impl\"),s=we(\"el-roving-focus-item\"),c=we(\"el-dropdown-collection-item\");return R(),fe(c,{disabled:e.disabled,\"text-value\":(i=e.textValue)!=null?i:e.textContent},{default:re(()=>[g(s,{focusable:!e.disabled},{default:re(()=>[g(l,hn(e.propsAndAttrs,{onPointerleave:e.handlePointerLeave,onPointermove:e.handlePointerMove,onClickimpl:e.handleClick}),{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},16,[\"onPointerleave\",\"onPointermove\",\"onClickimpl\"])]),_:3},8,[\"focusable\"])]),_:3},8,[\"disabled\",\"text-value\"])}var $5=Ae(hse,[[\"render\",pse],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dropdown/src/dropdown-item.vue\"]]);const vse=G({name:\"ElDropdownMenu\",props:Jle,setup(e){const t=De(\"dropdown\"),{_elDropdownSize:n}=k5(),r=n.value,{focusTrapRef:a,onKeydown:o}=ve(g5,void 0),{contentRef:i}=ve(fw,void 0),{collectionRef:l,getItems:s}=ve(rse,void 0),{rovingFocusGroupRef:c,rovingFocusGroupRootStyle:d,tabIndex:f,onBlur:p,onFocus:v,onMousedown:m}=ve(cw,void 0),{collectionRef:y}=ve(uw,void 0),b=x(()=>[t.b(\"menu\"),t.bm(\"menu\",r==null?void 0:r.value)]),C=FC(i,l,a,c,y),S=Tn(k=>{var $;($=e.onKeydown)==null||$.call(e,k)},k=>{const{currentTarget:$,code:O,target:T}=k;if($.contains(T),Ge.tab===O&&k.stopImmediatePropagation(),k.preventDefault(),T!==A(i)||!ese.includes(O))return;const I=s().filter(L=>!L.disabled).map(L=>L.ref);S5.includes(O)&&I.reverse(),dw(I)});return{size:r,rovingFocusGroupRootStyle:d,tabIndex:f,dropdownKls:b,dropdownListWrapperRef:C,handleKeydown:k=>{S(k),o(k)},onBlur:p,onFocus:v,onMousedown:m}}});function mse(e,t,n,r,a,o){return R(),X(\"ul\",{ref:e.dropdownListWrapperRef,class:U(e.dropdownKls),style:Xe(e.rovingFocusGroupRootStyle),tabindex:-1,role:\"menu\",onBlur:t[0]||(t[0]=(...i)=>e.onBlur&&e.onBlur(...i)),onFocus:t[1]||(t[1]=(...i)=>e.onFocus&&e.onFocus(...i)),onKeydown:t[2]||(t[2]=(...i)=>e.handleKeydown&&e.handleKeydown(...i)),onMousedown:t[3]||(t[3]=(...i)=>e.onMousedown&&e.onMousedown(...i))},[Oe(e.$slots,\"default\")],38)}var O5=Ae(vse,[[\"render\",mse],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/dropdown/src/dropdown-menu.vue\"]]);const gse=xt(sse,{DropdownItem:$5,DropdownMenu:O5}),yse=En($5),bse=En(O5);let Cse=0;const wse=G({name:\"ImgEmpty\",setup(){return{id:++Cse}}}),Sse={viewBox:\"0 0 79 86\",version:\"1.1\",xmlns:\"http://www.w3.org/2000/svg\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\"},kse=[\"id\"],$se=Z(\"stop\",{\"stop-color\":\"var(--el-empty-fill-color-1)\",offset:\"0%\"},null,-1),Ose=Z(\"stop\",{\"stop-color\":\"var(--el-empty-fill-color-4)\",offset:\"100%\"},null,-1),Pse=[$se,Ose],Tse=[\"id\"],xse=Z(\"stop\",{\"stop-color\":\"var(--el-empty-fill-color-1)\",offset:\"0%\"},null,-1),_se=Z(\"stop\",{\"stop-color\":\"var(--el-empty-fill-color-6)\",offset:\"100%\"},null,-1),Ese=[xse,_se],Mse=[\"id\"],Ise={id:\"Illustrations\",stroke:\"none\",\"stroke-width\":\"1\",fill:\"none\",\"fill-rule\":\"evenodd\"},Nse={id:\"B-type\",transform:\"translate(-1268.000000, -535.000000)\"},Ase={id:\"Group-2\",transform:\"translate(1268.000000, 535.000000)\"},Dse=Z(\"path\",{id:\"Oval-Copy-2\",d:\"M39.5,86 C61.3152476,86 79,83.9106622 79,81.3333333 C79,78.7560045 57.3152476,78 35.5,78 C13.6847524,78 0,78.7560045 0,81.3333333 C0,83.9106622 17.6847524,86 39.5,86 Z\",fill:\"var(--el-empty-fill-color-3)\"},null,-1),Rse=Z(\"polygon\",{id:\"Rectangle-Copy-14\",fill:\"var(--el-empty-fill-color-7)\",transform:\"translate(27.500000, 51.500000) scale(1, -1) translate(-27.500000, -51.500000) \",points:\"13 58 53 58 42 45 2 45\"},null,-1),Lse={id:\"Group-Copy\",transform:\"translate(34.500000, 31.500000) scale(-1, 1) rotate(-25.000000) translate(-34.500000, -31.500000) translate(7.000000, 10.000000)\"},Fse=Z(\"polygon\",{id:\"Rectangle-Copy-10\",fill:\"var(--el-empty-fill-color-7)\",transform:\"translate(11.500000, 5.000000) scale(1, -1) translate(-11.500000, -5.000000) \",points:\"2.84078316e-14 3 18 3 23 7 5 7\"},null,-1),Bse=Z(\"polygon\",{id:\"Rectangle-Copy-11\",fill:\"var(--el-empty-fill-color-5)\",points:\"-3.69149156e-15 7 38 7 38 43 -3.69149156e-15 43\"},null,-1),Vse=[\"fill\"],zse=Z(\"polygon\",{id:\"Rectangle-Copy-13\",fill:\"var(--el-empty-fill-color-2)\",transform:\"translate(39.500000, 3.500000) scale(-1, 1) translate(-39.500000, -3.500000) \",points:\"24 7 41 7 55 -3.63806207e-12 38 -3.63806207e-12\"},null,-1),Hse=[\"fill\"],jse={id:\"Rectangle-Copy-17\",transform:\"translate(53.000000, 45.000000)\"},Kse=[\"id\"],Wse=[\"xlink:href\"],Use=[\"xlink:href\"],Yse=[\"mask\"],qse=Z(\"polygon\",{id:\"Rectangle-Copy-18\",fill:\"var(--el-empty-fill-color-2)\",transform:\"translate(66.000000, 51.500000) scale(-1, 1) translate(-66.000000, -51.500000) \",points:\"62 45 79 45 70 58 53 58\"},null,-1);function Gse(e,t,n,r,a,o){return R(),X(\"svg\",Sse,[Z(\"defs\",null,[Z(\"linearGradient\",{id:`linearGradient-1-${e.id}`,x1:\"38.8503086%\",y1:\"0%\",x2:\"61.1496914%\",y2:\"100%\"},Pse,8,kse),Z(\"linearGradient\",{id:`linearGradient-2-${e.id}`,x1:\"0%\",y1:\"9.5%\",x2:\"100%\",y2:\"90.5%\"},Ese,8,Tse),Z(\"rect\",{id:`path-3-${e.id}`,x:\"0\",y:\"0\",width:\"17\",height:\"36\"},null,8,Mse)]),Z(\"g\",Ise,[Z(\"g\",Nse,[Z(\"g\",Ase,[Dse,Rse,Z(\"g\",Lse,[Fse,Bse,Z(\"rect\",{id:\"Rectangle-Copy-12\",fill:`url(#linearGradient-1-${e.id})`,transform:\"translate(46.500000, 25.000000) scale(-1, 1) translate(-46.500000, -25.000000) \",x:\"38\",y:\"7\",width:\"17\",height:\"36\"},null,8,Vse),zse]),Z(\"rect\",{id:\"Rectangle-Copy-15\",fill:`url(#linearGradient-2-${e.id})`,x:\"13\",y:\"45\",width:\"40\",height:\"36\"},null,8,Hse),Z(\"g\",jse,[Z(\"mask\",{id:`mask-4-${e.id}`,fill:\"var(--el-empty-fill-color-0)\"},[Z(\"use\",{\"xlink:href\":`#path-3-${e.id}`},null,8,Wse)],8,Kse),Z(\"use\",{id:\"Mask\",fill:\"var(--el-empty-fill-color-8)\",transform:\"translate(8.500000, 18.000000) scale(-1, 1) translate(-8.500000, -18.000000) \",\"xlink:href\":`#path-3-${e.id}`},null,8,Use),Z(\"polygon\",{id:\"Rectangle-Copy\",fill:\"var(--el-empty-fill-color-9)\",mask:`url(#mask-4-${e.id})`,transform:\"translate(12.000000, 9.000000) scale(-1, 1) translate(-12.000000, -9.000000) \",points:\"7 0 24 0 20 18 -1.70530257e-13 16\"},null,8,Yse)]),qse])])])])}var Xse=Ae(wse,[[\"render\",Gse],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/empty/src/img-empty.vue\"]]);const Zse={image:{type:String,default:\"\"},imageSize:Number,description:{type:String,default:\"\"}},Jse=[\"src\"],Qse={key:1},eue={name:\"ElEmpty\"},tue=G(Ke(Te({},eue),{props:Zse,setup(e){const t=e,{t:n}=ln(),r=De(\"empty\"),a=x(()=>t.description||n(\"el.table.emptyText\")),o=x(()=>({width:t.imageSize?`${t.imageSize}px`:\"\"}));return(i,l)=>(R(),X(\"div\",{class:U(A(r).b())},[Z(\"div\",{class:U(A(r).e(\"image\")),style:Xe(A(o))},[i.image?(R(),X(\"img\",{key:0,src:i.image,ondragstart:\"return false\"},null,8,Jse)):Oe(i.$slots,\"image\",{key:1},()=>[g(Xse)])],6),Z(\"div\",{class:U(A(r).e(\"description\"))},[i.$slots.description?Oe(i.$slots,\"description\",{key:0}):(R(),X(\"p\",Qse,Me(A(a)),1))],2),i.$slots.default?(R(),X(\"div\",{key:0,class:U(A(r).e(\"bottom\"))},[Oe(i.$slots,\"default\")],2)):se(\"v-if\",!0)],2))}}));var nue=Ae(tue,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/empty/src/empty.vue\"]]);const rue=xt(nue),aue=Ze({model:Object,rules:{type:Le(Object)},labelPosition:String,labelWidth:{type:[String,Number],default:\"\"},labelSuffix:{type:String,default:\"\"},inline:Boolean,inlineMessage:Boolean,statusIcon:Boolean,showMessage:{type:Boolean,default:!0},size:{type:String,values:Bo},disabled:Boolean,validateOnRuleChange:{type:Boolean,default:!0},hideRequiredAsterisk:{type:Boolean,default:!1},scrollToError:Boolean}),oue={validate:(e,t,n)=>(pt(e)||wt(e))&&yr(t)&&wt(n)};function iue(){const e=H([]),t=x(()=>{if(!e.value.length)return\"0\";const o=Math.max(...e.value);return o?`${o}px`:\"\"});function n(o){return e.value.indexOf(o)}function r(o,i){if(o&&i){const l=n(i);e.value.splice(l,1,o)}else o&&e.value.push(o)}function a(o){const i=n(o);i>-1&&e.value.splice(i,1)}return{autoLabelWidth:t,registerLabelWidth:r,deregisterLabelWidth:a}}const ch=(e,t)=>{const n=Hd(t);return n.length>0?e.filter(r=>r.prop&&n.includes(r.prop)):e},lue={name:\"ElForm\"},sue=G(Ke(Te({},lue),{props:aue,emits:oue,setup(e,{expose:t,emit:n}){const r=e,a=[],o=Gn(),i=De(\"form\"),l=x(()=>{const{labelPosition:S,inline:w}=r;return[i.b(),i.m(o.value||\"default\"),{[i.m(`label-${S}`)]:S,[i.m(\"inline\")]:w}]}),s=S=>{a.push(S)},c=S=>{S.prop&&a.splice(a.indexOf(S),1)},d=(S=[])=>{!r.model||ch(a,S).forEach(w=>w.resetField())},f=(S=[])=>{ch(a,S).forEach(w=>w.clearValidate())},p=x(()=>!!r.model),v=S=>{if(a.length===0)return[];const w=ch(a,S);return w.length?w:[]},m=async S=>b(void 0,S),y=async(S=[])=>{if(!p.value)return!1;const w=v(S);if(w.length===0)return!0;let k={};for(const $ of w)try{await $.validate(\"\")}catch(O){k=Te(Te({},k),O)}return Object.keys(k).length===0?!0:Promise.reject(k)},b=async(S=[],w)=>{const k=!Ct(w);try{const $=await y(S);return $===!0&&(w==null||w($)),$}catch($){const O=$;return r.scrollToError&&C(Object.keys(O)[0]),w==null||w(!1,O),k&&Promise.reject(O)}},C=S=>{var w;const k=ch(a,S)[0];k&&((w=k.$el)==null||w.scrollIntoView())};return ce(()=>r.rules,()=>{r.validateOnRuleChange&&m()},{deep:!0}),ot(ga,bt(Te(Ke(Te({},or(r)),{emit:n,resetFields:d,clearValidate:f,validateField:b,addField:s,removeField:c}),iue()))),t({validate:m,validateField:b,resetFields:d,clearValidate:f,scrollToField:C}),(S,w)=>(R(),X(\"form\",{class:U(A(l))},[Oe(S.$slots,\"default\")],2))}}));var uue=Ae(sue,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/form/src/form.vue\"]]);function ql(){return ql=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},ql.apply(this,arguments)}function cue(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,Xd(e,t)}function N0(e){return N0=Object.setPrototypeOf?Object.getPrototypeOf:function(n){return n.__proto__||Object.getPrototypeOf(n)},N0(e)}function Xd(e,t){return Xd=Object.setPrototypeOf||function(r,a){return r.__proto__=a,r},Xd(e,t)}function due(){if(typeof Reflect==\"undefined\"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy==\"function\")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function kp(e,t,n){return due()?kp=Reflect.construct:kp=function(a,o,i){var l=[null];l.push.apply(l,o);var s=Function.bind.apply(a,l),c=new s;return i&&Xd(c,i.prototype),c},kp.apply(null,arguments)}function fue(e){return Function.toString.call(e).indexOf(\"[native code]\")!==-1}function A0(e){var t=typeof Map==\"function\"?new Map:void 0;return A0=function(r){if(r===null||!fue(r))return r;if(typeof r!=\"function\")throw new TypeError(\"Super expression must either be null or a function\");if(typeof t!=\"undefined\"){if(t.has(r))return t.get(r);t.set(r,a)}function a(){return kp(r,arguments,N0(this).constructor)}return a.prototype=Object.create(r.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),Xd(a,r)},A0(e)}var hue=/%[sdj%]/g,pue=function(){};typeof process!=\"undefined\"&&process.env;function D0(e){if(!e||!e.length)return null;var t={};return e.forEach(function(n){var r=n.field;t[r]=t[r]||[],t[r].push(n)}),t}function ca(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var a=0,o=n.length;if(typeof e==\"function\")return e.apply(null,n);if(typeof e==\"string\"){var i=e.replace(hue,function(l){if(l===\"%%\")return\"%\";if(a>=o)return l;switch(l){case\"%s\":return String(n[a++]);case\"%d\":return Number(n[a++]);case\"%j\":try{return JSON.stringify(n[a++])}catch{return\"[Circular]\"}break;default:return l}});return i}return e}function vue(e){return e===\"string\"||e===\"url\"||e===\"hex\"||e===\"email\"||e===\"date\"||e===\"pattern\"}function lr(e,t){return!!(e==null||t===\"array\"&&Array.isArray(e)&&!e.length||vue(t)&&typeof e==\"string\"&&!e)}function mue(e,t,n){var r=[],a=0,o=e.length;function i(l){r.push.apply(r,l||[]),a++,a===o&&n(r)}e.forEach(function(l){t(l,i)})}function J4(e,t,n){var r=0,a=e.length;function o(i){if(i&&i.length){n(i);return}var l=r;r=r+1,l<a?t(e[l],o):n([])}o([])}function gue(e){var t=[];return Object.keys(e).forEach(function(n){t.push.apply(t,e[n]||[])}),t}var Q4=function(e){cue(t,e);function t(n,r){var a;return a=e.call(this,\"Async Validation Error\")||this,a.errors=n,a.fields=r,a}return t}(A0(Error));function yue(e,t,n,r,a){if(t.first){var o=new Promise(function(p,v){var m=function(C){return r(C),C.length?v(new Q4(C,D0(C))):p(a)},y=gue(e);J4(y,n,m)});return o.catch(function(p){return p}),o}var i=t.firstFields===!0?Object.keys(e):t.firstFields||[],l=Object.keys(e),s=l.length,c=0,d=[],f=new Promise(function(p,v){var m=function(b){if(d.push.apply(d,b),c++,c===s)return r(d),d.length?v(new Q4(d,D0(d))):p(a)};l.length||(r(d),p(a)),l.forEach(function(y){var b=e[y];i.indexOf(y)!==-1?J4(b,n,m):mue(b,n,m)})});return f.catch(function(p){return p}),f}function bue(e){return!!(e&&e.message!==void 0)}function Cue(e,t){for(var n=e,r=0;r<t.length;r++){if(n==null)return n;n=n[t[r]]}return n}function eO(e,t){return function(n){var r;return e.fullFields?r=Cue(t,e.fullFields):r=t[n.field||e.fullField],bue(n)?(n.field=n.field||e.fullField,n.fieldValue=r,n):{message:typeof n==\"function\"?n():n,fieldValue:r,field:n.field||e.fullField}}}function tO(e,t){if(t){for(var n in t)if(t.hasOwnProperty(n)){var r=t[n];typeof r==\"object\"&&typeof e[n]==\"object\"?e[n]=ql({},e[n],r):e[n]=r}}return e}var P5=function(t,n,r,a,o,i){t.required&&(!r.hasOwnProperty(t.field)||lr(n,i||t.type))&&a.push(ca(o.messages.required,t.fullField))},wue=function(t,n,r,a,o){(/^\\s+$/.test(n)||n===\"\")&&a.push(ca(o.messages.whitespace,t.fullField))},gy={email:/^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+\\.)+[a-zA-Z\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{2,}))$/,url:new RegExp(\"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}(?:\\\\.(?:[0-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]+-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]+-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))|localhost)(?::\\\\d{2,5})?(?:(/|\\\\?|#)[^\\\\s]*)?$\",\"i\"),hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},nd={integer:function(t){return nd.number(t)&&parseInt(t,10)===t},float:function(t){return nd.number(t)&&!nd.integer(t)},array:function(t){return Array.isArray(t)},regexp:function(t){if(t instanceof RegExp)return!0;try{return!!new RegExp(t)}catch{return!1}},date:function(t){return typeof t.getTime==\"function\"&&typeof t.getMonth==\"function\"&&typeof t.getYear==\"function\"&&!isNaN(t.getTime())},number:function(t){return isNaN(t)?!1:typeof t==\"number\"},object:function(t){return typeof t==\"object\"&&!nd.array(t)},method:function(t){return typeof t==\"function\"},email:function(t){return typeof t==\"string\"&&t.length<=320&&!!t.match(gy.email)},url:function(t){return typeof t==\"string\"&&t.length<=2048&&!!t.match(gy.url)},hex:function(t){return typeof t==\"string\"&&!!t.match(gy.hex)}},Sue=function(t,n,r,a,o){if(t.required&&n===void 0){P5(t,n,r,a,o);return}var i=[\"integer\",\"float\",\"array\",\"regexp\",\"object\",\"method\",\"email\",\"number\",\"date\",\"url\",\"hex\"],l=t.type;i.indexOf(l)>-1?nd[l](n)||a.push(ca(o.messages.types[l],t.fullField,t.type)):l&&typeof n!==t.type&&a.push(ca(o.messages.types[l],t.fullField,t.type))},kue=function(t,n,r,a,o){var i=typeof t.len==\"number\",l=typeof t.min==\"number\",s=typeof t.max==\"number\",c=/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,d=n,f=null,p=typeof n==\"number\",v=typeof n==\"string\",m=Array.isArray(n);if(p?f=\"number\":v?f=\"string\":m&&(f=\"array\"),!f)return!1;m&&(d=n.length),v&&(d=n.replace(c,\"_\").length),i?d!==t.len&&a.push(ca(o.messages[f].len,t.fullField,t.len)):l&&!s&&d<t.min?a.push(ca(o.messages[f].min,t.fullField,t.min)):s&&!l&&d>t.max?a.push(ca(o.messages[f].max,t.fullField,t.max)):l&&s&&(d<t.min||d>t.max)&&a.push(ca(o.messages[f].range,t.fullField,t.min,t.max))},Bs=\"enum\",$ue=function(t,n,r,a,o){t[Bs]=Array.isArray(t[Bs])?t[Bs]:[],t[Bs].indexOf(n)===-1&&a.push(ca(o.messages[Bs],t.fullField,t[Bs].join(\", \")))},Oue=function(t,n,r,a,o){if(t.pattern){if(t.pattern instanceof RegExp)t.pattern.lastIndex=0,t.pattern.test(n)||a.push(ca(o.messages.pattern.mismatch,t.fullField,n,t.pattern));else if(typeof t.pattern==\"string\"){var i=new RegExp(t.pattern);i.test(n)||a.push(ca(o.messages.pattern.mismatch,t.fullField,n,t.pattern))}}},tn={required:P5,whitespace:wue,type:Sue,range:kue,enum:$ue,pattern:Oue},Pue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n,\"string\")&&!t.required)return r();tn.required(t,n,a,i,o,\"string\"),lr(n,\"string\")||(tn.type(t,n,a,i,o),tn.range(t,n,a,i,o),tn.pattern(t,n,a,i,o),t.whitespace===!0&&tn.whitespace(t,n,a,i,o))}r(i)},Tue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&tn.type(t,n,a,i,o)}r(i)},xue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(n===\"\"&&(n=void 0),lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&(tn.type(t,n,a,i,o),tn.range(t,n,a,i,o))}r(i)},_ue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&tn.type(t,n,a,i,o)}r(i)},Eue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),lr(n)||tn.type(t,n,a,i,o)}r(i)},Mue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&(tn.type(t,n,a,i,o),tn.range(t,n,a,i,o))}r(i)},Iue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&(tn.type(t,n,a,i,o),tn.range(t,n,a,i,o))}r(i)},Nue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(n==null&&!t.required)return r();tn.required(t,n,a,i,o,\"array\"),n!=null&&(tn.type(t,n,a,i,o),tn.range(t,n,a,i,o))}r(i)},Aue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&tn.type(t,n,a,i,o)}r(i)},Due=\"enum\",Rue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o),n!==void 0&&tn[Due](t,n,a,i,o)}r(i)},Lue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n,\"string\")&&!t.required)return r();tn.required(t,n,a,i,o),lr(n,\"string\")||tn.pattern(t,n,a,i,o)}r(i)},Fue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n,\"date\")&&!t.required)return r();if(tn.required(t,n,a,i,o),!lr(n,\"date\")){var s;n instanceof Date?s=n:s=new Date(n),tn.type(t,s,a,i,o),s&&tn.range(t,s.getTime(),a,i,o)}}r(i)},Bue=function(t,n,r,a,o){var i=[],l=Array.isArray(n)?\"array\":typeof n;tn.required(t,n,a,i,o,l),r(i)},yy=function(t,n,r,a,o){var i=t.type,l=[],s=t.required||!t.required&&a.hasOwnProperty(t.field);if(s){if(lr(n,i)&&!t.required)return r();tn.required(t,n,a,l,o,i),lr(n,i)||tn.type(t,n,a,l,o)}r(l)},Vue=function(t,n,r,a,o){var i=[],l=t.required||!t.required&&a.hasOwnProperty(t.field);if(l){if(lr(n)&&!t.required)return r();tn.required(t,n,a,i,o)}r(i)},bd={string:Pue,method:Tue,number:xue,boolean:_ue,regexp:Eue,integer:Mue,float:Iue,array:Nue,object:Aue,enum:Rue,pattern:Lue,date:Fue,url:yy,hex:yy,email:yy,required:Bue,any:Vue};function R0(){return{default:\"Validation error on field %s\",required:\"%s is required\",enum:\"%s must be one of %s\",whitespace:\"%s cannot be empty\",date:{format:\"%s date %s is invalid for format %s\",parse:\"%s date could not be parsed, %s is invalid \",invalid:\"%s date %s is invalid\"},types:{string:\"%s is not a %s\",method:\"%s is not a %s (function)\",array:\"%s is not an %s\",object:\"%s is not an %s\",number:\"%s is not a %s\",date:\"%s is not a %s\",boolean:\"%s is not a %s\",integer:\"%s is not an %s\",float:\"%s is not a %s\",regexp:\"%s is not a valid %s\",email:\"%s is not a valid %s\",url:\"%s is not a valid %s\",hex:\"%s is not a valid %s\"},string:{len:\"%s must be exactly %s characters\",min:\"%s must be at least %s characters\",max:\"%s cannot be longer than %s characters\",range:\"%s must be between %s and %s characters\"},number:{len:\"%s must equal %s\",min:\"%s cannot be less than %s\",max:\"%s cannot be greater than %s\",range:\"%s must be between %s and %s\"},array:{len:\"%s must be exactly %s in length\",min:\"%s cannot be less than %s in length\",max:\"%s cannot be greater than %s in length\",range:\"%s must be between %s and %s in length\"},pattern:{mismatch:\"%s value %s does not match pattern %s\"},clone:function(){var t=JSON.parse(JSON.stringify(this));return t.clone=this.clone,t}}}var L0=R0(),Mf=function(){function e(n){this.rules=null,this._messages=L0,this.define(n)}var t=e.prototype;return t.define=function(r){var a=this;if(!r)throw new Error(\"Cannot configure a schema with no rules\");if(typeof r!=\"object\"||Array.isArray(r))throw new Error(\"Rules must be an object\");this.rules={},Object.keys(r).forEach(function(o){var i=r[o];a.rules[o]=Array.isArray(i)?i:[i]})},t.messages=function(r){return r&&(this._messages=tO(R0(),r)),this._messages},t.validate=function(r,a,o){var i=this;a===void 0&&(a={}),o===void 0&&(o=function(){});var l=r,s=a,c=o;if(typeof s==\"function\"&&(c=s,s={}),!this.rules||Object.keys(this.rules).length===0)return c&&c(null,l),Promise.resolve(l);function d(y){var b=[],C={};function S(k){if(Array.isArray(k)){var $;b=($=b).concat.apply($,k)}else b.push(k)}for(var w=0;w<y.length;w++)S(y[w]);b.length?(C=D0(b),c(b,C)):c(null,l)}if(s.messages){var f=this.messages();f===L0&&(f=R0()),tO(f,s.messages),s.messages=f}else s.messages=this.messages();var p={},v=s.keys||Object.keys(this.rules);v.forEach(function(y){var b=i.rules[y],C=l[y];b.forEach(function(S){var w=S;typeof w.transform==\"function\"&&(l===r&&(l=ql({},l)),C=l[y]=w.transform(C)),typeof w==\"function\"?w={validator:w}:w=ql({},w),w.validator=i.getValidationMethod(w),w.validator&&(w.field=y,w.fullField=w.fullField||y,w.type=i.getType(w),p[y]=p[y]||[],p[y].push({rule:w,value:C,source:l,field:y}))})});var m={};return yue(p,s,function(y,b){var C=y.rule,S=(C.type===\"object\"||C.type===\"array\")&&(typeof C.fields==\"object\"||typeof C.defaultField==\"object\");S=S&&(C.required||!C.required&&y.value),C.field=y.field;function w(O,T){return ql({},T,{fullField:C.fullField+\".\"+O,fullFields:C.fullFields?[].concat(C.fullFields,[O]):[O]})}function k(O){O===void 0&&(O=[]);var T=Array.isArray(O)?O:[O];!s.suppressWarning&&T.length&&e.warning(\"async-validator:\",T),T.length&&C.message!==void 0&&(T=[].concat(C.message));var _=T.map(eO(C,l));if(s.first&&_.length)return m[C.field]=1,b(_);if(!S)b(_);else{if(C.required&&!y.value)return C.message!==void 0?_=[].concat(C.message).map(eO(C,l)):s.error&&(_=[s.error(C,ca(s.messages.required,C.field))]),b(_);var I={};C.defaultField&&Object.keys(y.value).map(function(F){I[F]=C.defaultField}),I=ql({},I,y.rule.fields);var L={};Object.keys(I).forEach(function(F){var N=I[F],D=Array.isArray(N)?N:[N];L[F]=D.map(w.bind(null,F))});var j=new e(L);j.messages(s.messages),y.rule.options&&(y.rule.options.messages=s.messages,y.rule.options.error=s.error),j.validate(y.value,y.rule.options||s,function(F){var N=[];_&&_.length&&N.push.apply(N,_),F&&F.length&&N.push.apply(N,F),b(N.length?N:null)})}}var $;C.asyncValidator?$=C.asyncValidator(C,y.value,k,y.source,s):C.validator&&($=C.validator(C,y.value,k,y.source,s),$===!0?k():$===!1?k(typeof C.message==\"function\"?C.message(C.fullField||C.field):C.message||(C.fullField||C.field)+\" fails\"):$ instanceof Array?k($):$ instanceof Error&&k($.message)),$&&$.then&&$.then(function(){return k()},function(O){return k(O)})},function(y){d(y)},l)},t.getType=function(r){if(r.type===void 0&&r.pattern instanceof RegExp&&(r.type=\"pattern\"),typeof r.validator!=\"function\"&&r.type&&!bd.hasOwnProperty(r.type))throw new Error(ca(\"Unknown rule type %s\",r.type));return r.type||\"string\"},t.getValidationMethod=function(r){if(typeof r.validator==\"function\")return r.validator;var a=Object.keys(r),o=a.indexOf(\"message\");return o!==-1&&a.splice(o,1),a.length===1&&a[0]===\"required\"?bd.required:bd[this.getType(r)]||void 0},e}();Mf.register=function(t,n){if(typeof n!=\"function\")throw new Error(\"Cannot register a validator by type, validator is not a function\");bd[t]=n};Mf.warning=pue;Mf.messages=L0;Mf.validators=bd;const zue=[\"\",\"error\",\"validating\",\"success\"],Hue=Ze({label:String,labelWidth:{type:[String,Number],default:\"\"},prop:{type:Le([String,Array])},required:{type:Boolean,default:void 0},rules:{type:Le([Object,Array])},error:String,validateStatus:{type:String,values:zue},for:String,inlineMessage:{type:[String,Boolean],default:\"\"},showMessage:{type:Boolean,default:!0},size:{type:String,values:Bo}}),nO=\"ElLabelWrap\";var jue=G({name:nO,props:{isAutoWidth:Boolean,updateAll:Boolean},setup(e,{slots:t}){const n=ve(ga),r=ve(Ia);(!n||!r)&&qn(nO,\"usage: <el-form><el-form-item><label-wrap /></el-form-item></el-form>\");const a=De(\"form\"),o=H(),i=H(0),l=()=>{var d;if((d=o.value)!=null&&d.firstElementChild){const f=window.getComputedStyle(o.value.firstElementChild).width;return Math.ceil(Number.parseFloat(f))}else return 0},s=(d=\"update\")=>{Ne(()=>{t.default&&e.isAutoWidth&&(d===\"update\"?i.value=l():d===\"remove\"&&n.deregisterLabelWidth(i.value))})},c=()=>s(\"update\");return et(()=>{c()}),Lt(()=>{s(\"remove\")}),ur(()=>c()),ce(i,(d,f)=>{e.updateAll&&n.registerLabelWidth(d,f)}),Cc(x(()=>{var d,f;return(f=(d=o.value)==null?void 0:d.firstElementChild)!=null?f:null}),c),()=>{var d,f;if(!t)return null;const{isAutoWidth:p}=e;if(p){const v=n.autoLabelWidth,m={};if(v&&v!==\"auto\"){const y=Math.max(0,Number.parseInt(v,10)-i.value),b=n.labelPosition===\"left\"?\"marginRight\":\"marginLeft\";y&&(m[b]=`${y}px`)}return g(\"div\",{ref:o,class:[a.be(\"item\",\"label-wrap\")],style:m},[(d=t.default)==null?void 0:d.call(t)])}else return g(Fe,{ref:o},[(f=t.default)==null?void 0:f.call(t)])}}});const Kue=[\"for\"],Wue={name:\"ElFormItem\"},Uue=G(Ke(Te({},Wue),{props:Hue,setup(e,{expose:t}){const n=e,r=\"ElFormItem\",a=wf(),o=ve(ga);o||qn(r,\"usage: <el-form><el-form-item /></el-form>\");const i=ve(Ia,void 0),l=Gn(void 0,{formItem:!1}),s=De(\"form-item\"),c=H(\"\"),d=gU(c,100),f=H(\"\"),p=H();let v,m=!1;const y=x(()=>{if(o.labelPosition===\"top\")return{};const q=oo(n.labelWidth||o.labelWidth||\"\");return q?{width:q}:{}}),b=x(()=>{if(o.labelPosition===\"top\"||o.inline)return{};if(!n.label&&!n.labelWidth&&O)return{};const q=oo(n.labelWidth||o.labelWidth||\"\");return!n.label&&!a.label?{marginLeft:q}:{}}),C=x(()=>[s.b(),s.m(l.value),s.is(\"error\",c.value===\"error\"),s.is(\"validating\",c.value===\"validating\"),s.is(\"success\",c.value===\"success\"),s.is(\"required\",j.value||n.required),s.is(\"no-asterisk\",o.hideRequiredAsterisk),{[s.m(\"feedback\")]:o.statusIcon}]),S=x(()=>yr(n.inlineMessage)?n.inlineMessage:o.inlineMessage||!1),w=x(()=>[s.e(\"error\"),{[s.em(\"error\",\"inline\")]:S.value}]),k=x(()=>n.prop?wt(n.prop)?n.prop:n.prop.join(\".\"):\"\"),$=x(()=>n.for||k.value),O=!!i,T=x(()=>{const q=o.model;if(!(!q||!n.prop))return cp(q,n.prop).value}),_=x(()=>{const q=n.rules?Hd(n.rules):[],J=o.rules;if(J&&n.prop){const ne=cp(J,n.prop).value;ne&&q.push(...Hd(ne))}return n.required!==void 0&&q.push({required:!!n.required}),q}),I=x(()=>_.value.length>0),L=q=>_.value.filter(ne=>!ne.trigger||!q?!0:Array.isArray(ne.trigger)?ne.trigger.includes(q):ne.trigger===q).map(Q=>{var ae=Q,{trigger:ne}=ae,oe=$k(ae,[\"trigger\"]);return oe}),j=x(()=>_.value.some(q=>q.required===!0)),F=x(()=>d.value===\"error\"&&n.showMessage&&o.showMessage),N=x(()=>`${n.label||\"\"}${o.labelSuffix||\"\"}`),D=q=>{c.value=q},z=q=>{var J,ne;const{errors:oe,fields:Q}=q;(!oe||!Q)&&console.error(q),D(\"error\"),f.value=oe?(ne=(J=oe==null?void 0:oe[0])==null?void 0:J.message)!=null?ne:`${n.prop} is required`:\"\",o.emit(\"validate\",n.prop,!1,f.value)},B=()=>{D(\"success\"),o.emit(\"validate\",n.prop,!0,\"\")},M=async q=>{const J=k.value;return new Mf({[J]:q}).validate({[J]:T.value},{firstFields:!0}).then(()=>(B(),!0)).catch(oe=>(z(oe),Promise.reject(oe)))},E=async(q,J)=>{if(m)return m=!1,!1;const ne=Ct(J);if(!I.value)return J==null||J(!1),!1;const oe=L(q);return oe.length===0?(J==null||J(!0),!0):(D(\"validating\"),M(oe).then(()=>(J==null||J(!0),!0)).catch(Q=>{const{fields:ae}=Q;return J==null||J(!1,ae),ne?!1:Promise.reject(ae)}))},K=()=>{D(\"\"),f.value=\"\"},W=async()=>{const q=o.model;if(!q||!n.prop)return;const J=cp(q,n.prop);er(J.value,v)||(m=!0),J.value=v,await Ne(),K()};ce(()=>n.error,q=>{f.value=q||\"\",D(q?\"error\":\"\")},{immediate:!0}),ce(()=>n.validateStatus,q=>D(q||\"\"));const Y=bt(Ke(Te({},or(n)),{$el:p,size:l,validateState:c,resetField:W,clearValidate:K,validate:E}));return ot(Ia,Y),et(()=>{n.prop&&(o.addField(Y),v=Xj(T.value))}),Lt(()=>{o.removeField(Y)}),t({size:l,validateMessage:f,validateState:c,validate:E,clearValidate:K,resetField:W}),(q,J)=>(R(),X(\"div\",{ref_key:\"formItemRef\",ref:p,class:U(A(C))},[g(A(jue),{\"is-auto-width\":A(y).width===\"auto\",\"update-all\":A(o).labelWidth===\"auto\"},{default:re(()=>[q.label||q.$slots.label?(R(),X(\"label\",{key:0,for:A($),class:U(A(s).e(\"label\")),style:Xe(A(y))},[Oe(q.$slots,\"label\",{label:A(N)},()=>[yt(Me(A(N)),1)])],14,Kue)):se(\"v-if\",!0)]),_:3},8,[\"is-auto-width\",\"update-all\"]),Z(\"div\",{class:U(A(s).e(\"content\")),style:Xe(A(b))},[Oe(q.$slots,\"default\"),g(Vn,{name:`${A(s).namespace.value}-zoom-in-top`},{default:re(()=>[A(F)?Oe(q.$slots,\"error\",{key:0,error:f.value},()=>[Z(\"div\",{class:U(A(w))},Me(f.value),3)]):se(\"v-if\",!0)]),_:3},8,[\"name\"])],6)],2))}}));var T5=Ae(Uue,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/form/src/form-item.vue\"]]);const Yue=xt(uue,{FormItem:T5}),que=En(T5),Gue=Ze({urlList:{type:Le(Array),default:()=>xn([])},zIndex:{type:Number},initialIndex:{type:Number,default:0},infinite:{type:Boolean,default:!0},hideOnClickModal:{type:Boolean,default:!1},teleported:{type:Boolean,default:!1}}),Xue={close:()=>!0,switch:e=>typeof e==\"number\"},Zue=[\"src\"],Jue={name:\"ElImageViewer\"},Que=G(Ke(Te({},Jue),{props:Gue,emits:Xue,setup(e,{emit:t}){const n=e,r={CONTAIN:{name:\"contain\",icon:ps(Lq)},ORIGINAL:{name:\"original\",icon:ps(QG)}},a=BC()?\"DOMMouseScroll\":\"mousewheel\",{t:o}=ln(),i=De(\"image-viewer\"),{nextZIndex:l}=Pi(),s=H(),c=H([]),d=N9(),f=H(!0),p=H(n.initialIndex),v=H(r.CONTAIN),m=H({scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}),y=x(()=>{const{urlList:B}=n;return B.length<=1}),b=x(()=>p.value===0),C=x(()=>p.value===n.urlList.length-1),S=x(()=>n.urlList[p.value]),w=x(()=>{const{scale:B,deg:M,offsetX:E,offsetY:K,enableTransition:W}=m.value;let Y=E/B,q=K/B;switch(M%360){case 90:case-270:[Y,q]=[q,-Y];break;case 180:case-180:[Y,q]=[-Y,-q];break;case 270:case-90:[Y,q]=[-q,Y];break}const J={transform:`scale(${B}) rotate(${M}deg) translate(${Y}px, ${q}px)`,transition:W?\"transform .3s\":\"\"};return v.value.name===r.CONTAIN.name&&(J.maxWidth=J.maxHeight=\"100%\"),J}),k=x(()=>Yt(n.zIndex)?n.zIndex:l());function $(){T(),t(\"close\")}function O(){const B=Qi(E=>{switch(E.code){case Ge.esc:$();break;case Ge.space:F();break;case Ge.left:N();break;case Ge.up:z(\"zoomIn\");break;case Ge.right:D();break;case Ge.down:z(\"zoomOut\");break}}),M=Qi(E=>{(E.wheelDelta?E.wheelDelta:-E.detail)>0?z(\"zoomIn\",{zoomRate:1.2,enableTransition:!1}):z(\"zoomOut\",{zoomRate:1.2,enableTransition:!1})});d.run(()=>{Hn(document,\"keydown\",B),Hn(document,a,M)})}function T(){d.stop()}function _(){f.value=!1}function I(B){f.value=!1,B.target.alt=o(\"el.image.error\")}function L(B){if(f.value||B.button!==0||!s.value)return;m.value.enableTransition=!1;const{offsetX:M,offsetY:E}=m.value,K=B.pageX,W=B.pageY,Y=Qi(J=>{m.value=Ke(Te({},m.value),{offsetX:M+J.pageX-K,offsetY:E+J.pageY-W})}),q=Hn(document,\"mousemove\",Y);Hn(document,\"mouseup\",()=>{q()}),B.preventDefault()}function j(){m.value={scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}}function F(){if(f.value)return;const B=Object.keys(r),M=Object.values(r),E=v.value.name,W=(M.findIndex(Y=>Y.name===E)+1)%B.length;v.value=r[B[W]],j()}function N(){if(b.value&&!n.infinite)return;const B=n.urlList.length;p.value=(p.value-1+B)%B}function D(){if(C.value&&!n.infinite)return;const B=n.urlList.length;p.value=(p.value+1)%B}function z(B,M={}){if(f.value)return;const{zoomRate:E,rotateDeg:K,enableTransition:W}=Te({zoomRate:1.4,rotateDeg:90,enableTransition:!0},M);switch(B){case\"zoomOut\":m.value.scale>.2&&(m.value.scale=Number.parseFloat((m.value.scale/E).toFixed(3)));break;case\"zoomIn\":m.value.scale<7&&(m.value.scale=Number.parseFloat((m.value.scale*E).toFixed(3)));break;case\"clockwise\":m.value.deg+=K;break;case\"anticlockwise\":m.value.deg-=K;break}m.value.enableTransition=W}return ce(S,()=>{Ne(()=>{const B=c.value[0];B!=null&&B.complete||(f.value=!0)})}),ce(p,B=>{j(),t(\"switch\",B)}),et(()=>{var B,M;O(),(M=(B=s.value)==null?void 0:B.focus)==null||M.call(B)}),(B,M)=>(R(),fe(Ps,{to:\"body\",disabled:!B.teleported},[g(Vn,{name:\"viewer-fade\",appear:\"\"},{default:re(()=>[Z(\"div\",{ref_key:\"wrapper\",ref:s,tabindex:-1,class:U(A(i).e(\"wrapper\")),style:Xe({zIndex:A(k)})},[Z(\"div\",{class:U(A(i).e(\"mask\")),onClick:M[0]||(M[0]=dt(E=>B.hideOnClickModal&&$(),[\"self\"]))},null,2),se(\" CLOSE \"),Z(\"span\",{class:U([A(i).e(\"btn\"),A(i).e(\"close\")]),onClick:$},[g(A(ft),null,{default:re(()=>[g(A(Ma))]),_:1})],2),se(\" ARROW \"),A(y)?se(\"v-if\",!0):(R(),X(Fe,{key:0},[Z(\"span\",{class:U([A(i).e(\"btn\"),A(i).e(\"prev\"),A(i).is(\"disabled\",!B.infinite&&A(b))]),onClick:N},[g(A(ft),null,{default:re(()=>[g(A(Es))]),_:1})],2),Z(\"span\",{class:U([A(i).e(\"btn\"),A(i).e(\"next\"),A(i).is(\"disabled\",!B.infinite&&A(C))]),onClick:D},[g(A(ft),null,{default:re(()=>[g(A(Da))]),_:1})],2)],64)),se(\" ACTIONS \"),Z(\"div\",{class:U([A(i).e(\"btn\"),A(i).e(\"actions\")])},[Z(\"div\",{class:U(A(i).e(\"actions__inner\"))},[g(A(ft),{onClick:M[1]||(M[1]=E=>z(\"zoomOut\"))},{default:re(()=>[g(A(jX))]),_:1}),g(A(ft),{onClick:M[2]||(M[2]=E=>z(\"zoomIn\"))},{default:re(()=>[g(A(fE))]),_:1}),Z(\"i\",{class:U(A(i).e(\"actions__divider\"))},null,2),g(A(ft),{onClick:F},{default:re(()=>[(R(),fe(Kt(v.value.icon)))]),_:1}),Z(\"i\",{class:U(A(i).e(\"actions__divider\"))},null,2),g(A(ft),{onClick:M[3]||(M[3]=E=>z(\"anticlockwise\"))},{default:re(()=>[g(A(zG))]),_:1}),g(A(ft),{onClick:M[4]||(M[4]=E=>z(\"clockwise\"))},{default:re(()=>[g(A(YG))]),_:1})],2)],2),se(\" CANVAS \"),Z(\"div\",{class:U(A(i).e(\"canvas\"))},[(R(!0),X(Fe,null,Rt(B.urlList,(E,K)=>at((R(),X(\"img\",{ref_for:!0,ref:W=>c.value[K]=W,key:E,src:E,style:Xe(A(w)),class:U(A(i).e(\"img\")),onLoad:_,onError:I,onMousedown:L},null,46,Zue)),[[_t,K===p.value]])),128))],2),Oe(B.$slots,\"default\")],6)]),_:3})],8,[\"disabled\"]))}}));var ece=Ae(Que,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/image-viewer/src/image-viewer.vue\"]]);const x5=xt(ece),tce=Ze({appendToBody:{type:Boolean,default:void 0},hideOnClickModal:{type:Boolean,default:!1},src:{type:String,default:\"\"},fit:{type:String,values:[\"\",\"contain\",\"cover\",\"fill\",\"none\",\"scale-down\"],default:\"\"},lazy:{type:Boolean,default:!1},scrollContainer:{type:Le([String,Object])},previewSrcList:{type:Le(Array),default:()=>xn([])},previewTeleported:{type:Boolean,default:!1},zIndex:{type:Number},initialIndex:{type:Number,default:0},infinite:{type:Boolean,default:!0}}),nce={error:e=>e instanceof Event,switch:e=>Yt(e),close:()=>!0},rce=[\"src\"],ace={key:0},oce={name:\"ElImage\"},ice=G(Ke(Te({},oce),{props:tce,emits:nce,setup(e,{emit:t}){const n=e;let r=\"\";Tf({scope:\"el-image\",from:\"append-to-body\",replacement:\"preview-teleported\",version:\"2.2.0\",ref:\"https://element-plus.org/en-US/component/image.html#image-attributess\"},x(()=>yr(n.appendToBody)));const{t:a}=ln(),o=De(\"image\"),i=VC(),l=H(!1),s=H(!0),c=H(0),d=H(0),f=H(!1),p=H(),v=H();let m,y;const b=x(()=>i.value.style),C=x(()=>{const{fit:B}=n;return Bt&&B?{objectFit:B}:{}}),S=x(()=>{const{previewSrcList:B}=n;return Array.isArray(B)&&B.length>0}),w=x(()=>n.appendToBody||n.previewTeleported),k=x(()=>{const{previewSrcList:B,initialIndex:M}=n;let E=M;return M>B.length-1&&(E=0),E}),$=()=>{if(!Bt)return;s.value=!0,l.value=!1;const B=new Image,M=n.src;B.addEventListener(\"load\",E=>{M===n.src&&O(E,B)}),B.addEventListener(\"error\",E=>{M===n.src&&T(E)}),Object.entries(i.value).forEach(([E,K])=>{E.toLowerCase()!==\"onload\"&&B.setAttribute(E,K)}),B.src=M};function O(B,M){c.value=M.width,d.value=M.height,s.value=!1,l.value=!1}function T(B){s.value=!1,l.value=!0,t(\"error\",B)}function _(){PU(p.value,v.value)&&($(),j())}const I=oE(_,200);async function L(){var B;if(!Bt)return;await Ne();const{scrollContainer:M}=n;ys(M)?v.value=M:wt(M)&&M!==\"\"?v.value=(B=document.querySelector(M))!=null?B:void 0:p.value&&(v.value=DC(p.value)),v.value&&(m=Hn(v,\"scroll\",I),setTimeout(()=>_(),100))}function j(){!Bt||!v.value||!I||(m(),v.value=void 0)}function F(B){if(!!B.ctrlKey){if(B.deltaY<0)return B.preventDefault(),!1;if(B.deltaY>0)return B.preventDefault(),!1}}function N(){!S.value||(y=Hn(\"wheel\",F,{passive:!1}),r=document.body.style.overflow,document.body.style.overflow=\"hidden\",f.value=!0)}function D(){y==null||y(),document.body.style.overflow=r,f.value=!1,t(\"close\")}function z(B){t(\"switch\",B)}return ce(()=>n.src,()=>{n.lazy?(s.value=!0,l.value=!1,j(),L()):$()}),et(()=>{n.lazy?L():$()}),(B,M)=>(R(),X(\"div\",{ref_key:\"container\",ref:p,class:U([A(o).b(),B.$attrs.class]),style:Xe(A(b))},[s.value?Oe(B.$slots,\"placeholder\",{key:0},()=>[Z(\"div\",{class:U(A(o).e(\"placeholder\"))},null,2)]):l.value?Oe(B.$slots,\"error\",{key:1},()=>[Z(\"div\",{class:U(A(o).e(\"error\"))},Me(A(a)(\"el.image.error\")),3)]):(R(),X(\"img\",hn({key:2},A(i),{src:B.src,style:A(C),class:[A(o).e(\"inner\"),A(S)?A(o).e(\"preview\"):\"\"],onClick:N}),null,16,rce)),A(S)?(R(),X(Fe,{key:3},[f.value?(R(),fe(A(x5),{key:0,\"z-index\":B.zIndex,\"initial-index\":A(k),infinite:B.infinite,\"url-list\":B.previewSrcList,\"hide-on-click-modal\":B.hideOnClickModal,teleported:A(w),onClose:D,onSwitch:z},{default:re(()=>[B.$slots.viewer?(R(),X(\"div\",ace,[Oe(B.$slots,\"viewer\")])):se(\"v-if\",!0)]),_:3},8,[\"z-index\",\"initial-index\",\"infinite\",\"url-list\",\"hide-on-click-modal\",\"teleported\"])):se(\"v-if\",!0)],2112)):se(\"v-if\",!0)],6))}}));var lce=Ae(ice,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/image/src/image.vue\"]]);const sce=xt(lce),uce=Ze({step:{type:Number,default:1},stepStrictly:{type:Boolean,default:!1},max:{type:Number,default:Number.POSITIVE_INFINITY},min:{type:Number,default:Number.NEGATIVE_INFINITY},modelValue:{type:Number},disabled:{type:Boolean,default:!1},size:{type:String,values:Bo},controls:{type:Boolean,default:!0},controlsPosition:{type:String,default:\"\",values:[\"\",\"right\"]},name:String,label:String,placeholder:String,precision:{type:Number,validator:e=>e>=0&&e===Number.parseInt(`${e}`,10)}}),cce={change:(e,t)=>e!==t,blur:e=>e instanceof FocusEvent,focus:e=>e instanceof FocusEvent,input:e=>Yt(e),\"update:modelValue\":e=>Yt(e)||e===void 0},dce=G({name:\"ElInputNumber\",components:{ElInput:Ra,ElIcon:ft,ArrowUp:Of,ArrowDown:_s,Plus:cE,Minus:iG},directives:{RepeatClick:SM},props:uce,emits:cce,setup(e,{emit:t}){const n=H(),r=bt({currentValue:e.modelValue,userInput:null}),{formItem:a}=$c(),o=De(\"input-number\"),i=x(()=>y(e.modelValue,-1)<e.min),l=x(()=>y(e.modelValue)>e.max),s=x(()=>{const L=m(e.step);return sa(e.precision)?Math.max(m(e.modelValue),L):(L>e.precision,e.precision)}),c=x(()=>e.controls&&e.controlsPosition===\"right\"),d=Gn(),f=Ms(),p=x(()=>{if(r.userInput!==null)return r.userInput;let L=r.currentValue;if(Yt(L)){if(Number.isNaN(L))return\"\";sa(e.precision)||(L=L.toFixed(e.precision))}return L}),v=(L,j)=>(sa(j)&&(j=s.value),Number.parseFloat(`${Math.round(L*10**j)/10**j}`)),m=L=>{if(sa(L))return 0;const j=L.toString(),F=j.indexOf(\".\");let N=0;return F!==-1&&(N=j.length-F-1),N},y=(L,j=1)=>Yt(L)?(L=Yt(L)?L:Number.NaN,v(L+e.step*j)):r.currentValue,b=()=>{if(f.value||l.value)return;const L=e.modelValue||0,j=y(L);w(j)},C=()=>{if(f.value||i.value)return;const L=e.modelValue||0,j=y(L,-1);w(j)},S=(L,j)=>{const{max:F,min:N,step:D,precision:z,stepStrictly:B}=e;let M=Number(L);return L===null&&(M=Number.NaN),Number.isNaN(M)||(B&&(M=Math.round(M/D)*D),sa(z)||(M=v(M,z)),(M>F||M<N)&&(M=M>F?F:N,j&&t(\"update:modelValue\",M))),M},w=L=>{var j;const F=r.currentValue;let N=S(L);F!==N&&(Number.isNaN(N)&&(N=void 0),r.userInput=null,t(\"update:modelValue\",N),t(\"input\",N),t(\"change\",N,F),(j=a==null?void 0:a.validate)==null||j.call(a,\"change\").catch(D=>void 0),r.currentValue=N)},k=L=>r.userInput=L,$=L=>{const j=L!==\"\"?Number(L):\"\";(Yt(j)&&!Number.isNaN(j)||L===\"\")&&w(j),r.userInput=null},O=()=>{var L,j;(j=(L=n.value)==null?void 0:L.focus)==null||j.call(L)},T=()=>{var L,j;(j=(L=n.value)==null?void 0:L.blur)==null||j.call(L)},_=L=>{t(\"focus\",L)},I=L=>{var j;t(\"blur\",L),(j=a==null?void 0:a.validate)==null||j.call(a,\"blur\").catch(F=>void 0)};return ce(()=>e.modelValue,L=>{const j=S(L,!0);r.currentValue=j,r.userInput=null},{immediate:!0}),et(()=>{var L;const j=(L=n.value)==null?void 0:L.input;if(j.setAttribute(\"role\",\"spinbutton\"),j.setAttribute(\"aria-valuemax\",String(e.max)),j.setAttribute(\"aria-valuemin\",String(e.min)),j.setAttribute(\"aria-valuenow\",String(r.currentValue)),j.setAttribute(\"aria-disabled\",String(f.value)),!Yt(e.modelValue)){let F=Number(e.modelValue);Number.isNaN(F)&&(F=void 0),t(\"update:modelValue\",F)}}),ur(()=>{var L;const j=(L=n.value)==null?void 0:L.input;j==null||j.setAttribute(\"aria-valuenow\",r.currentValue)}),{input:n,displayValue:p,handleInput:k,handleInputChange:$,controlsAtRight:c,decrease:C,increase:b,inputNumberSize:d,inputNumberDisabled:f,maxDisabled:l,minDisabled:i,focus:O,blur:T,handleFocus:_,handleBlur:I,ns:o}}});function fce(e,t,n,r,a,o){const i=we(\"arrow-down\"),l=we(\"minus\"),s=we(\"el-icon\"),c=we(\"arrow-up\"),d=we(\"plus\"),f=we(\"el-input\"),p=pa(\"repeat-click\");return R(),X(\"div\",{class:U([e.ns.b(),e.ns.m(e.inputNumberSize),e.ns.is(\"disabled\",e.inputNumberDisabled),e.ns.is(\"without-controls\",!e.controls),e.ns.is(\"controls-right\",e.controlsAtRight)]),onDragstart:t[2]||(t[2]=dt(()=>{},[\"prevent\"]))},[e.controls?at((R(),X(\"span\",{key:0,role:\"button\",class:U([e.ns.e(\"decrease\"),e.ns.is(\"disabled\",e.minDisabled)]),onKeydown:t[0]||(t[0]=It((...v)=>e.decrease&&e.decrease(...v),[\"enter\"]))},[g(s,null,{default:re(()=>[e.controlsAtRight?(R(),fe(i,{key:0})):(R(),fe(l,{key:1}))]),_:1})],34)),[[p,e.decrease]]):se(\"v-if\",!0),e.controls?at((R(),X(\"span\",{key:1,role:\"button\",class:U([e.ns.e(\"increase\"),e.ns.is(\"disabled\",e.maxDisabled)]),onKeydown:t[1]||(t[1]=It((...v)=>e.increase&&e.increase(...v),[\"enter\"]))},[g(s,null,{default:re(()=>[e.controlsAtRight?(R(),fe(c,{key:0})):(R(),fe(d,{key:1}))]),_:1})],34)),[[p,e.increase]]):se(\"v-if\",!0),g(f,{ref:\"input\",type:\"number\",step:e.step,\"model-value\":e.displayValue,placeholder:e.placeholder,disabled:e.inputNumberDisabled,size:e.inputNumberSize,max:e.max,min:e.min,name:e.name,label:e.label,\"validate-event\":!1,onKeydown:[It(dt(e.increase,[\"prevent\"]),[\"up\"]),It(dt(e.decrease,[\"prevent\"]),[\"down\"])],onBlur:e.handleBlur,onFocus:e.handleFocus,onInput:e.handleInput,onChange:e.handleInputChange},null,8,[\"step\",\"model-value\",\"placeholder\",\"disabled\",\"size\",\"max\",\"min\",\"name\",\"label\",\"onKeydown\",\"onBlur\",\"onFocus\",\"onInput\",\"onChange\"])],34)}var hce=Ae(dce,[[\"render\",fce],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/input-number/src/input-number.vue\"]]);const _5=xt(hce),pce=Ze({type:{type:String,values:[\"primary\",\"success\",\"warning\",\"info\",\"danger\",\"default\"],default:\"default\"},underline:{type:Boolean,default:!0},disabled:{type:Boolean,default:!1},href:{type:String,default:\"\"},icon:{type:wr,default:\"\"}}),vce={click:e=>e instanceof MouseEvent},mce=[\"href\"],gce={name:\"ElLink\"},yce=G(Ke(Te({},gce),{props:pce,emits:vce,setup(e,{emit:t}){const n=e,r=De(\"link\");function a(o){n.disabled||t(\"click\",o)}return(o,i)=>(R(),X(\"a\",{class:U([A(r).b(),A(r).m(o.type),A(r).is(\"disabled\",o.disabled),A(r).is(\"underline\",o.underline&&!o.disabled)]),href:o.disabled||!o.href?void 0:o.href,onClick:a},[o.icon?(R(),fe(A(ft),{key:0},{default:re(()=>[(R(),fe(Kt(o.icon)))]),_:1})):se(\"v-if\",!0),o.$slots.default?(R(),X(\"span\",{key:1,class:U(A(r).e(\"inner\"))},[Oe(o.$slots,\"default\")],2)):se(\"v-if\",!0),o.$slots.icon?Oe(o.$slots,\"icon\",{key:2}):se(\"v-if\",!0)],10,mce))}}));var bce=Ae(yce,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/link/src/link.vue\"]]);const Cce=xt(bce);class wce{constructor(t,n){this.parent=t,this.domNode=n,this.subIndex=0,this.subIndex=0,this.init()}init(){this.subMenuItems=this.domNode.querySelectorAll(\"li\"),this.addListeners()}gotoSubIndex(t){t===this.subMenuItems.length?t=0:t<0&&(t=this.subMenuItems.length-1),this.subMenuItems[t].focus(),this.subIndex=t}addListeners(){const t=this.parent.domNode;Array.prototype.forEach.call(this.subMenuItems,n=>{n.addEventListener(\"keydown\",r=>{let a=!1;switch(r.code){case Ge.down:{this.gotoSubIndex(this.subIndex+1),a=!0;break}case Ge.up:{this.gotoSubIndex(this.subIndex-1),a=!0;break}case Ge.tab:{sp(t,\"mouseleave\");break}case Ge.enter:case Ge.space:{a=!0,r.currentTarget.click();break}}return a&&(r.preventDefault(),r.stopPropagation()),!1})})}}class Sce{constructor(t){this.domNode=t,this.submenu=null,this.submenu=null,this.init()}init(){this.domNode.setAttribute(\"tabindex\",\"0\");const t=this.domNode.querySelector(\".el-menu\");t&&(this.submenu=new wce(this,t)),this.addListeners()}addListeners(){this.domNode.addEventListener(\"keydown\",t=>{let n=!1;switch(t.code){case Ge.down:{sp(t.currentTarget,\"mouseenter\"),this.submenu&&this.submenu.gotoSubIndex(0),n=!0;break}case Ge.up:{sp(t.currentTarget,\"mouseenter\"),this.submenu&&this.submenu.gotoSubIndex(this.submenu.subMenuItems.length-1),n=!0;break}case Ge.tab:{sp(t.currentTarget,\"mouseleave\");break}case Ge.enter:case Ge.space:{n=!0,t.currentTarget.click();break}}n&&t.preventDefault()})}}class kce{constructor(t){this.domNode=t,this.init()}init(){const t=this.domNode.childNodes;Array.from(t).forEach(n=>{n.nodeType===1&&new Sce(n)})}}const $ce=G({name:\"ElMenuCollapseTransition\",setup(){return{listeners:{onBeforeEnter:t=>t.style.opacity=\"0.2\",onEnter(t,n){xo(t,\"el-opacity-transition\"),t.style.opacity=\"1\",n()},onAfterEnter(t){Br(t,\"el-opacity-transition\"),t.style.opacity=\"\"},onBeforeLeave(t){t.dataset||(t.dataset={}),to(t,\"el-menu--collapse\")?(Br(t,\"el-menu--collapse\"),t.dataset.oldOverflow=t.style.overflow,t.dataset.scrollWidth=t.clientWidth.toString(),xo(t,\"el-menu--collapse\")):(xo(t,\"el-menu--collapse\"),t.dataset.oldOverflow=t.style.overflow,t.dataset.scrollWidth=t.clientWidth.toString(),Br(t,\"el-menu--collapse\")),t.style.width=`${t.scrollWidth}px`,t.style.overflow=\"hidden\"},onLeave(t){xo(t,\"horizontal-collapse-transition\"),t.style.width=`${t.dataset.scrollWidth}px`}}}}});function Oce(e,t,n,r,a,o){return R(),fe(Vn,hn({mode:\"out-in\"},e.listeners),{default:re(()=>[Oe(e.$slots,\"default\")]),_:3},16)}var Pce=Ae($ce,[[\"render\",Oce],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/menu/src/menu-collapse-transition.vue\"]]);function E5(e,t){const n=ve(\"rootMenu\");n||qn(\"useMenu\",\"can not inject root menu\");const r=x(()=>{let i=e.parent;const l=[t.value];for(;i.type.name!==\"ElMenu\";)i.props.index&&l.unshift(i.props.index),i=i.parent;return l}),a=x(()=>{let i=e.parent;for(;i&&![\"ElMenu\",\"ElSubMenu\"].includes(i.type.name);)i=i.parent;return i}),o=x(()=>{let i=e.parent;if(n.props.mode!==\"vertical\")return{};let l=20;if(n.props.collapse)l=20;else for(;i&&i.type.name!==\"ElMenu\";)i.type.name===\"ElSubMenu\"&&(l+=20),i=i.parent;return{paddingLeft:`${l}px`}});return{parentMenu:a,paddingStyle:o,indexPath:r}}function Tce(e){return x(()=>{const n=e.backgroundColor;return n?new pM(n).shade(20).toString():\"\"})}const M5=e=>x(()=>({\"--el-menu-text-color\":e.textColor||\"\",\"--el-menu-hover-text-color\":e.textColor||\"\",\"--el-menu-bg-color\":e.backgroundColor||\"\",\"--el-menu-hover-bg-color\":Tce(e).value||\"\",\"--el-menu-active-color\":e.activeTextColor||\"\"})),xce=Ze({index:{type:String,required:!0},showTimeout:{type:Number,default:300},hideTimeout:{type:Number,default:300},popperClass:String,disabled:Boolean,popperAppendToBody:{type:Boolean,default:void 0},popperOffset:{type:Number,default:6}}),by=\"ElSubMenu\";var hw=G({name:by,props:xce,setup(e,{slots:t,expose:n}){const r=$t(),{paddingStyle:a,indexPath:o,parentMenu:i}=E5(r,x(()=>e.index)),l=ve(\"rootMenu\");l||qn(by,\"can not inject root menu\");const s=ve(`subMenu:${i.value.uid}`);s||qn(by,\"can not inject sub menu\");const c=H({}),d=H({});let f;const p=H(!1),v=H(),m=H(null),y=x(()=>L.value===\"horizontal\"&&C.value?\"bottom-start\":\"right-start\"),b=x(()=>L.value===\"horizontal\"&&C.value||L.value===\"vertical\"&&!l.props.collapse?_s:Da),C=x(()=>{let E=!0,K=r.parent;for(;K&&K.type.name!==\"ElMenu\";)if([\"ElSubMenu\",\"ElMenuItemGroup\"].includes(K.type.name)){E=!1;break}else K=K.parent;return E}),S=x(()=>e.popperAppendToBody===void 0?C.value:Boolean(e.popperAppendToBody)),w=x(()=>l.props.collapse?\"el-zoom-in-left\":\"el-zoom-in-top\"),k=x(()=>L.value===\"horizontal\"&&C.value?[\"bottom-start\",\"bottom-end\",\"top-start\",\"top-end\",\"right-start\",\"left-start\"]:[\"right-start\",\"left-start\",\"bottom-start\",\"bottom-end\",\"top-start\",\"top-end\"]),$=x(()=>l.openedMenus.includes(e.index)),O=x(()=>{let E=!1;return Object.values(c.value).forEach(K=>{K.active&&(E=!0)}),Object.values(d.value).forEach(K=>{K.active&&(E=!0)}),E}),T=x(()=>l.props.backgroundColor||\"\"),_=x(()=>l.props.activeTextColor||\"\"),I=x(()=>l.props.textColor||\"\"),L=x(()=>l.props.mode),j=bt({index:e.index,indexPath:o,active:O}),F=x(()=>L.value!==\"horizontal\"?{color:I.value}:{borderBottomColor:O.value?l.props.activeTextColor?_.value:\"\":\"transparent\",color:O.value?_.value:I.value}),N=()=>{var E,K,W;return(W=(K=(E=m.value)==null?void 0:E.popperRef)==null?void 0:K.popperInstanceRef)==null?void 0:W.destroy()},D=E=>{E||N()},z=()=>{l.props.menuTrigger===\"hover\"&&l.props.mode===\"horizontal\"||l.props.collapse&&l.props.mode===\"vertical\"||e.disabled||l.handleSubMenuClick({index:e.index,indexPath:o.value,active:O.value})},B=(E,K=e.showTimeout)=>{var W;E.type===\"focus\"&&!E.relatedTarget||l.props.menuTrigger===\"click\"&&l.props.mode===\"horizontal\"||!l.props.collapse&&l.props.mode===\"vertical\"||e.disabled||(s.mouseInChild.value=!0,f==null||f(),{stop:f}=gs(()=>{l.openMenu(e.index,o.value)},K),S.value&&((W=i.value.vnode.el)==null||W.dispatchEvent(new MouseEvent(\"mouseenter\"))))},M=(E=!1)=>{var K,W;l.props.menuTrigger===\"click\"&&l.props.mode===\"horizontal\"||!l.props.collapse&&l.props.mode===\"vertical\"||(f==null||f(),s.mouseInChild.value=!1,{stop:f}=gs(()=>!p.value&&l.closeMenu(e.index,o.value),e.hideTimeout),S.value&&E&&((K=r.parent)==null?void 0:K.type.name)===\"ElSubMenu\"&&((W=s.handleMouseleave)==null||W.call(s,!0)))};ce(()=>l.props.collapse,E=>D(Boolean(E)));{const E=W=>{d.value[W.index]=W},K=W=>{delete d.value[W.index]};ot(`subMenu:${r.uid}`,{addSubMenu:E,removeSubMenu:K,handleMouseleave:M,mouseInChild:p})}return n({opened:$}),et(()=>{l.addSubMenu(j),s.addSubMenu(j)}),Lt(()=>{s.removeSubMenu(j),l.removeSubMenu(j)}),()=>{var E;const K=[(E=t.title)==null?void 0:E.call(t),qe(ft,{class:[\"el-sub-menu__icon-arrow\"]},{default:()=>qe(b.value)})],W=M5(l.props),Y=l.isMenuPopup?qe(Ur,{ref:m,visible:$.value,effect:\"light\",pure:!0,offset:e.popperOffset,showArrow:!1,persistent:!0,popperClass:e.popperClass,placement:y.value,teleported:S.value,fallbackPlacements:k.value,transition:w.value,gpuAcceleration:!1},{content:()=>{var q;return qe(\"div\",{class:[`el-menu--${L.value}`,e.popperClass],onMouseenter:J=>B(J,100),onMouseleave:()=>M(!0),onFocus:J=>B(J,100)},[qe(\"ul\",{class:[\"el-menu el-menu--popup\",`el-menu--popup-${y.value}`],style:W.value},[(q=t.default)==null?void 0:q.call(t)])])},default:()=>qe(\"div\",{class:\"el-sub-menu__title\",style:[a.value,F.value,{backgroundColor:T.value}],onClick:z},K)}):qe(Fe,{},[qe(\"div\",{class:\"el-sub-menu__title\",style:[a.value,F.value,{backgroundColor:T.value}],ref:v,onClick:z},K),qe(Xm,{},{default:()=>{var q;return at(qe(\"ul\",{role:\"menu\",class:\"el-menu el-menu--inline\",style:W.value},[(q=t.default)==null?void 0:q.call(t)]),[[_t,$.value]])}})]);return qe(\"li\",{class:[\"el-sub-menu\",{\"is-active\":O.value,\"is-opened\":$.value,\"is-disabled\":e.disabled}],role:\"menuitem\",ariaHaspopup:!0,ariaExpanded:$.value,onMouseenter:B,onMouseleave:()=>M(!0),onFocus:B},[Y])}}});const _ce=Ze({mode:{type:String,values:[\"horizontal\",\"vertical\"],default:\"vertical\"},defaultActive:{type:String,default:\"\"},defaultOpeneds:{type:Le(Array),default:()=>xn([])},uniqueOpened:Boolean,router:Boolean,menuTrigger:{type:String,values:[\"hover\",\"click\"],default:\"hover\"},collapse:Boolean,backgroundColor:String,textColor:String,activeTextColor:String,collapseTransition:{type:Boolean,default:!0},ellipsis:{type:Boolean,default:!0}}),Cy=e=>Array.isArray(e)&&e.every(t=>wt(t)),Ece={close:(e,t)=>wt(e)&&Cy(t),open:(e,t)=>wt(e)&&Cy(t),select:(e,t,n,r)=>wt(e)&&Cy(t)&&zt(n)&&(r===void 0||r instanceof Promise)};var Mce=G({name:\"ElMenu\",props:_ce,emits:Ece,setup(e,{emit:t,slots:n,expose:r}){const a=$t(),o=a.appContext.config.globalProperties.$router,i=H(),l=H(e.defaultOpeneds&&!e.collapse?e.defaultOpeneds.slice(0):[]),s=H(e.defaultActive),c=H({}),d=H({}),f=x(()=>e.mode===\"horizontal\"||e.mode===\"vertical\"&&e.collapse),p=()=>{const $=s.value&&c.value[s.value];if(!$||e.mode===\"horizontal\"||e.collapse)return;$.indexPath.forEach(T=>{const _=d.value[T];_&&v(T,_.indexPath)})},v=($,O)=>{l.value.includes($)||(e.uniqueOpened&&(l.value=l.value.filter(T=>O.includes(T))),l.value.push($),t(\"open\",$,O))},m=($,O)=>{const T=l.value.indexOf($);T!==-1&&l.value.splice(T,1),t(\"close\",$,O)},y=({index:$,indexPath:O})=>{l.value.includes($)?m($,O):v($,O)},b=$=>{(e.mode===\"horizontal\"||e.collapse)&&(l.value=[]);const{index:O,indexPath:T}=$;if(!(O===void 0||T===void 0))if(e.router&&o){const _=$.route||O,I=o.push(_).then(L=>(L||(s.value=O),L));t(\"select\",O,T,{index:O,indexPath:T,route:_},I)}else s.value=O,t(\"select\",O,T,{index:O,indexPath:T})},C=$=>{const O=c.value,T=O[$]||s.value&&O[s.value]||O[e.defaultActive];T?(s.value=T.index,p()):s.value=$},S=()=>{Ne(()=>a.proxy.$forceUpdate())};ce(()=>e.defaultActive,$=>{c.value[$]||(s.value=\"\"),C($)}),ce(c.value,()=>p()),ce(()=>e.collapse,$=>{$&&(l.value=[])});{const $=I=>{d.value[I.index]=I},O=I=>{delete d.value[I.index]};ot(\"rootMenu\",bt({props:e,openedMenus:l,items:c,subMenus:d,activeIndex:s,isMenuPopup:f,addMenuItem:I=>{c.value[I.index]=I},removeMenuItem:I=>{delete c.value[I.index]},addSubMenu:$,removeSubMenu:O,openMenu:v,closeMenu:m,handleMenuItemClick:b,handleSubMenuClick:y})),ot(`subMenu:${a.uid}`,{addSubMenu:$,removeSubMenu:O,mouseInChild:H(!1)})}et(()=>{p(),e.mode===\"horizontal\"&&new kce(a.vnode.el)}),r({open:O=>{const{indexPath:T}=d.value[O];T.forEach(_=>v(_,T))},close:m,handleResize:S});const w=$=>{const O=Array.isArray($)?$:[$],T=[];return O.forEach(_=>{Array.isArray(_.children)?T.push(...w(_.children)):T.push(_)}),T},k=$=>e.mode===\"horizontal\"?at($,[[Rte,S]]):$;return()=>{var $,O,T,_;let I=(O=($=n.default)==null?void 0:$.call(n))!=null?O:[];const L=[];if(e.mode===\"horizontal\"&&i.value){const D=Array.from((_=(T=i.value)==null?void 0:T.childNodes)!=null?_:[]).filter(ne=>ne.nodeName!==\"#text\"||ne.nodeValue),z=w(I),B=64,M=Number.parseInt(getComputedStyle(i.value).paddingLeft,10),E=Number.parseInt(getComputedStyle(i.value).paddingRight,10),K=i.value.clientWidth-M-E;let W=0,Y=0;D.forEach((ne,oe)=>{W+=ne.offsetWidth||0,W<=K-B&&(Y=oe+1)});const q=z.slice(0,Y),J=z.slice(Y);(J==null?void 0:J.length)&&e.ellipsis&&(I=q,L.push(qe(hw,{index:\"sub-menu-more\",class:\"el-sub-menu__hide-arrow\"},{title:()=>qe(ft,{class:[\"el-sub-menu__icon-more\"]},{default:()=>qe(yG)}),default:()=>J})))}const j=M5(e),N=(D=>e.ellipsis?k(D):D)(qe(\"ul\",{key:String(e.collapse),role:\"menubar\",ref:i,style:j.value,class:{\"el-menu\":!0,\"el-menu--horizontal\":e.mode===\"horizontal\",\"el-menu--collapse\":e.collapse}},[...I,...L]));return e.collapseTransition&&e.mode===\"vertical\"?qe(Pce,()=>N):N}}});const Ice=Ze({index:{type:Le([String,null]),default:null},route:{type:Le([String,Object])},disabled:Boolean}),Nce={click:e=>wt(e.index)&&Array.isArray(e.indexPath)},wy=\"ElMenuItem\",Ace=G({name:wy,components:{ElTooltip:Ur},props:Ice,emits:Nce,setup(e,{emit:t}){const n=$t(),r=ve(\"rootMenu\");r||qn(wy,\"can not inject root menu\");const{parentMenu:a,paddingStyle:o,indexPath:i}=E5(n,yn(e,\"index\")),l=ve(`subMenu:${a.value.uid}`);l||qn(wy,\"can not inject sub menu\");const s=x(()=>e.index===r.activeIndex),c=bt({index:e.index,indexPath:i,active:s}),d=()=>{e.disabled||(r.handleMenuItemClick({index:e.index,indexPath:i.value,route:e.route}),t(\"click\",c))};return et(()=>{l.addSubMenu(c),r.addMenuItem(c)}),Lt(()=>{l.removeSubMenu(c),r.removeMenuItem(c)}),{Effect:tee,parentMenu:a,rootMenu:r,paddingStyle:o,active:s,handleClick:d}}}),Dce={class:\"el-menu-tooltip__trigger\"};function Rce(e,t,n,r,a,o){const i=we(\"el-tooltip\");return R(),X(\"li\",{class:U([\"el-menu-item\",{\"is-active\":e.active,\"is-disabled\":e.disabled}]),role:\"menuitem\",tabindex:\"-1\",style:Xe(e.paddingStyle),onClick:t[0]||(t[0]=(...l)=>e.handleClick&&e.handleClick(...l))},[e.parentMenu.type.name===\"ElMenu\"&&e.rootMenu.props.collapse&&e.$slots.title?(R(),fe(i,{key:0,effect:e.Effect.DARK,placement:\"right\",\"fallback-placements\":[\"left\"],persistent:\"\"},{content:re(()=>[Oe(e.$slots,\"title\")]),default:re(()=>[Z(\"div\",Dce,[Oe(e.$slots,\"default\")])]),_:3},8,[\"effect\"])):(R(),X(Fe,{key:1},[Oe(e.$slots,\"default\"),Oe(e.$slots,\"title\")],64))],6)}var I5=Ae(Ace,[[\"render\",Rce],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/menu/src/menu-item.vue\"]]);const Lce={title:String},rO=\"ElMenuItemGroup\",Fce=G({name:rO,props:Lce,setup(){const e=$t(),t=ve(\"rootMenu\");return t||qn(rO,\"can not inject root menu\"),{levelPadding:x(()=>{if(t.props.collapse)return 20;let r=20,a=e.parent;for(;a&&a.type.name!==\"ElMenu\";)a.type.name===\"ElSubMenu\"&&(r+=20),a=a.parent;return r})}}}),Bce={class:\"el-menu-item-group\"};function Vce(e,t,n,r,a,o){return R(),X(\"li\",Bce,[Z(\"div\",{class:\"el-menu-item-group__title\",style:Xe({paddingLeft:`${e.levelPadding}px`})},[e.$slots.title?Oe(e.$slots,\"title\",{key:1}):(R(),X(Fe,{key:0},[yt(Me(e.title),1)],2112))],4),Z(\"ul\",null,[Oe(e.$slots,\"default\")])])}var N5=Ae(Fce,[[\"render\",Vce],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/menu/src/menu-item-group.vue\"]]);const zce=xt(Mce,{MenuItem:I5,MenuItemGroup:N5,SubMenu:hw}),Hce=En(I5),jce=En(N5);En(hw);const Kce=Ze({icon:{type:wr,default:()=>iY},title:String,content:{type:String,default:\"\"}}),Wce={back:()=>!0},Uce={name:\"ElPageHeader\"},Yce=G(Ke(Te({},Uce),{props:Kce,emits:Wce,setup(e,{emit:t}){const{t:n}=ln(),r=De(\"page-header\");function a(){t(\"back\")}return(o,i)=>(R(),X(\"div\",{class:U(A(r).b())},[Z(\"div\",{class:U(A(r).e(\"left\")),onClick:a},[o.icon||o.$slots.icon?(R(),X(\"div\",{key:0,class:U(A(r).e(\"icon\"))},[Oe(o.$slots,\"icon\",{},()=>[o.icon?(R(),fe(A(ft),{key:0},{default:re(()=>[(R(),fe(Kt(o.icon)))]),_:1})):se(\"v-if\",!0)])],2)):se(\"v-if\",!0),Z(\"div\",{class:U(A(r).e(\"title\"))},[Oe(o.$slots,\"title\",{},()=>[yt(Me(o.title||A(n)(\"el.pageHeader.title\")),1)])],2)],2),Z(\"div\",{class:U(A(r).e(\"content\"))},[Oe(o.$slots,\"content\",{},()=>[yt(Me(o.content),1)])],2)],2))}}));var qce=Ae(Yce,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/page-header/src/page-header.vue\"]]);const Gce=xt(qce),Xce={disabled:Boolean,currentPage:{type:Number,default:1},prevText:{type:String,default:\"\"}},Zce=G({name:\"ElPaginationPrev\",components:{ElIcon:ft,ArrowLeft:Es},props:Xce,emits:[\"click\"],setup(e){return{internalDisabled:x(()=>e.disabled||e.currentPage<=1)}}}),Jce=[\"disabled\",\"aria-disabled\"],Qce={key:0};function ede(e,t,n,r,a,o){const i=we(\"arrow-left\"),l=we(\"el-icon\");return R(),X(\"button\",{type:\"button\",class:\"btn-prev\",disabled:e.internalDisabled,\"aria-disabled\":e.internalDisabled,onClick:t[0]||(t[0]=s=>e.$emit(\"click\",s))},[e.prevText?(R(),X(\"span\",Qce,Me(e.prevText),1)):(R(),fe(l,{key:1},{default:re(()=>[g(i)]),_:1}))],8,Jce)}var tde=Ae(Zce,[[\"render\",ede],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/prev.vue\"]]);const nde={disabled:Boolean,currentPage:{type:Number,default:1},pageCount:{type:Number,default:50},nextText:{type:String,default:\"\"}},rde=G({name:\"ElPaginationNext\",components:{ElIcon:ft,ArrowRight:Da},props:nde,emits:[\"click\"],setup(e){return{internalDisabled:x(()=>e.disabled||e.currentPage===e.pageCount||e.pageCount===0)}}}),ade=[\"disabled\",\"aria-disabled\"],ode={key:0};function ide(e,t,n,r,a,o){const i=we(\"arrow-right\"),l=we(\"el-icon\");return R(),X(\"button\",{type:\"button\",class:\"btn-next\",disabled:e.internalDisabled,\"aria-disabled\":e.internalDisabled,onClick:t[0]||(t[0]=s=>e.$emit(\"click\",s))},[e.nextText?(R(),X(\"span\",ode,Me(e.nextText),1)):(R(),fe(l,{key:1},{default:re(()=>[g(i)]),_:1}))],8,ade)}var lde=Ae(rde,[[\"render\",ide],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/next.vue\"]]);const A5=\"ElSelectGroup\",Zm=\"ElSelect\";function sde(e,t){const n=ve(Zm),r=ve(A5,{disabled:!1}),a=x(()=>Object.prototype.toString.call(e.value).toLowerCase()===\"[object object]\"),o=x(()=>n.props.multiple?f(n.props.modelValue,e.value):p(e.value,n.props.modelValue)),i=x(()=>{if(n.props.multiple){const y=n.props.modelValue||[];return!o.value&&y.length>=n.props.multipleLimit&&n.props.multipleLimit>0}else return!1}),l=x(()=>e.label||(a.value?\"\":e.value)),s=x(()=>e.value||e.label||\"\"),c=x(()=>e.disabled||t.groupDisabled||i.value),d=$t(),f=(y=[],b)=>{if(a.value){const C=n.props.valueKey;return y&&y.some(S=>vn(S,C)===vn(b,C))}else return y&&y.includes(b)},p=(y,b)=>{if(a.value){const{valueKey:C}=n.props;return vn(y,C)===vn(b,C)}else return y===b},v=()=>{!e.disabled&&!r.disabled&&(n.hoverIndex=n.optionsArray.indexOf(d.proxy))};ce(()=>l.value,()=>{!e.created&&!n.props.remote&&n.setSelected()}),ce(()=>e.value,(y,b)=>{const{remote:C,valueKey:S}=n.props;if(!e.created&&!C){if(S&&typeof y==\"object\"&&typeof b==\"object\"&&y[S]===b[S])return;n.setSelected()}}),ce(()=>r.disabled,()=>{t.groupDisabled=r.disabled},{immediate:!0});const{queryChange:m}=Gt(n);return ce(m,y=>{const{query:b}=A(y),C=new RegExp(EU(b),\"i\");t.visible=C.test(l.value)||e.created,t.visible||n.filteredOptionsCount--}),{select:n,currentLabel:l,currentValue:s,itemSelected:o,isDisabled:c,hoverItem:v}}const ude=G({name:\"ElOption\",componentName:\"ElOption\",props:{value:{required:!0,type:[String,Number,Boolean,Object]},label:[String,Number],created:Boolean,disabled:{type:Boolean,default:!1}},setup(e){const t=De(\"select\"),n=bt({index:-1,groupDisabled:!1,visible:!0,hitState:!1,hover:!1}),{currentLabel:r,itemSelected:a,isDisabled:o,select:i,hoverItem:l}=sde(e,n),{visible:s,hover:c}=or(n),d=$t().proxy,f=d.value;i.onOptionCreate(d),Lt(()=>{const{selected:v}=i,y=(i.props.multiple?v:[v]).some(b=>b.value===d.value);i.cachedOptions.get(f)===d&&!y&&Ne(()=>{i.cachedOptions.delete(f)}),i.onOptionDestroy(f,d)});function p(){e.disabled!==!0&&n.groupDisabled!==!0&&i.handleOptionSelect(d,!0)}return{ns:t,currentLabel:r,itemSelected:a,isDisabled:o,select:i,hoverItem:l,visible:s,hover:c,selectOptionClick:p,states:n}}});function cde(e,t,n,r,a,o){return at((R(),X(\"li\",{class:U([e.ns.be(\"dropdown\",\"item\"),e.ns.is(\"disabled\",e.isDisabled),{selected:e.itemSelected,hover:e.hover}]),onMouseenter:t[0]||(t[0]=(...i)=>e.hoverItem&&e.hoverItem(...i)),onClick:t[1]||(t[1]=dt((...i)=>e.selectOptionClick&&e.selectOptionClick(...i),[\"stop\"]))},[Oe(e.$slots,\"default\",{},()=>[Z(\"span\",null,Me(e.currentLabel),1)])],34)),[[_t,e.visible]])}var pw=Ae(ude,[[\"render\",cde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select/src/option.vue\"]]);const dde=G({name:\"ElSelectDropdown\",componentName:\"ElSelectDropdown\",setup(){const e=ve(Zm),t=De(\"select\"),n=x(()=>e.props.popperClass),r=x(()=>e.props.multiple),a=x(()=>e.props.fitInputWidth),o=H(\"\");function i(){var l;o.value=`${(l=e.selectWrapper)==null?void 0:l.getBoundingClientRect().width}px`}return et(()=>{i(),wc(e.selectWrapper,i)}),Lt(()=>{Sc(e.selectWrapper,i)}),{ns:t,minWidth:o,popperClass:n,isMultiple:r,isFitInputWidth:a}}});function fde(e,t,n,r,a,o){return R(),X(\"div\",{class:U([e.ns.b(\"dropdown\"),e.ns.is(\"multiple\",e.isMultiple),e.popperClass]),style:Xe({[e.isFitInputWidth?\"width\":\"minWidth\"]:e.minWidth})},[Oe(e.$slots,\"default\")],6)}var hde=Ae(dde,[[\"render\",fde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select/src/select-dropdown.vue\"]]);function pde(e){const{t}=ln();return bt({options:new Map,cachedOptions:new Map,createdLabel:null,createdSelected:!1,selected:e.multiple?[]:{},inputLength:20,inputWidth:0,initialInputHeight:0,optionsCount:0,filteredOptionsCount:0,visible:!1,softFocus:!1,selectedLabel:\"\",hoverIndex:-1,query:\"\",previousQuery:null,inputHovering:!1,cachedPlaceHolder:\"\",currentPlaceholder:t(\"el.select.placeholder\"),menuVisibleOnFocus:!1,isOnComposition:!1,isSilentBlur:!1,prefixWidth:11,tagInMultiLine:!1})}const vde=(e,t,n)=>{const{t:r}=ln(),a=De(\"select\"),o=H(null),i=H(null),l=H(null),s=H(null),c=H(null),d=H(null),f=H(-1),p=Qn({query:\"\"}),v=Qn(\"\"),m=ve(ga,{}),y=ve(Ia,{}),b=x(()=>!e.filterable||e.multiple||!t.visible),C=x(()=>e.disabled||m.disabled),S=x(()=>{const he=e.multiple?Array.isArray(e.modelValue)&&e.modelValue.length>0:e.modelValue!==void 0&&e.modelValue!==null&&e.modelValue!==\"\";return e.clearable&&!C.value&&t.inputHovering&&he}),w=x(()=>e.remote&&e.filterable?\"\":e.suffixIcon),k=x(()=>a.is(\"reverse\",w.value&&t.visible)),$=x(()=>e.remote?300:0),O=x(()=>e.loading?e.loadingText||r(\"el.select.loading\"):e.remote&&t.query===\"\"&&t.options.size===0?!1:e.filterable&&t.query&&t.options.size>0&&t.filteredOptionsCount===0?e.noMatchText||r(\"el.select.noMatch\"):t.options.size===0?e.noDataText||r(\"el.select.noData\"):null),T=x(()=>Array.from(t.options.values())),_=x(()=>Array.from(t.cachedOptions.values())),I=x(()=>{const he=T.value.filter(_e=>!_e.created).some(_e=>_e.currentLabel===t.query);return e.filterable&&e.allowCreate&&t.query!==\"\"&&!he}),L=Gn(),j=x(()=>[\"small\"].includes(L.value)?\"small\":\"default\"),F=x({get(){return t.visible&&O.value!==!1},set(he){t.visible=he}});ce(()=>C.value,()=>{Ne(()=>{N()})}),ce(()=>e.placeholder,he=>{t.cachedPlaceHolder=t.currentPlaceholder=he}),ce(()=>e.modelValue,(he,_e)=>{var $e;e.multiple&&(N(),he&&he.length>0||i.value&&t.query!==\"\"?t.currentPlaceholder=\"\":t.currentPlaceholder=t.cachedPlaceHolder,e.filterable&&!e.reserveKeyword&&(t.query=\"\",D(t.query))),M(),e.filterable&&!e.multiple&&(t.inputLength=20),er(he,_e)||($e=y.validate)==null||$e.call(y,\"change\").catch(Ve=>void 0)},{flush:\"post\",deep:!0}),ce(()=>t.visible,he=>{var _e,$e,Ve;he?(($e=(_e=l.value)==null?void 0:_e.updatePopper)==null||$e.call(_e),e.filterable&&(t.filteredOptionsCount=t.optionsCount,t.query=e.remote?\"\":t.selectedLabel,e.multiple?(Ve=i.value)==null||Ve.focus():t.selectedLabel&&(t.currentPlaceholder=`${t.selectedLabel}`,t.selectedLabel=\"\"),D(t.query),!e.multiple&&!e.remote&&(p.value.query=\"\",Dc(p),Dc(v)))):(i.value&&i.value.blur(),t.query=\"\",t.previousQuery=null,t.selectedLabel=\"\",t.inputLength=20,t.menuVisibleOnFocus=!1,K(),Ne(()=>{i.value&&i.value.value===\"\"&&t.selected.length===0&&(t.currentPlaceholder=t.cachedPlaceHolder)}),e.multiple||(t.selected&&(e.filterable&&e.allowCreate&&t.createdSelected&&t.createdLabel?t.selectedLabel=t.createdLabel:t.selectedLabel=t.selected.currentLabel,e.filterable&&(t.query=t.selectedLabel)),e.filterable&&(t.currentPlaceholder=t.cachedPlaceHolder))),n.emit(\"visible-change\",he)}),ce(()=>t.options.entries(),()=>{var he,_e,$e;if(!Bt)return;(_e=(he=l.value)==null?void 0:he.updatePopper)==null||_e.call(he),e.multiple&&N();const Ve=(($e=c.value)==null?void 0:$e.querySelectorAll(\"input\"))||[];Array.from(Ve).includes(document.activeElement)||M(),e.defaultFirstOption&&(e.filterable||e.remote)&&t.filteredOptionsCount&&B()},{flush:\"post\"}),ce(()=>t.hoverIndex,he=>{typeof he==\"number\"&&he>-1&&(f.value=T.value[he]||{}),T.value.forEach(_e=>{_e.hover=f.value===_e})});const N=()=>{e.collapseTags&&!e.filterable||Ne(()=>{var he,_e;if(!o.value)return;const $e=o.value.$el.childNodes,Ve=Array.from($e).find(Ut=>Ut.tagName===\"INPUT\"),st=s.value,Dt=t.initialInputHeight||vE(L.value||m.size);Ve.style.height=t.selected.length===0?`${Dt}px`:`${Math.max(st?st.clientHeight+(st.clientHeight>Dt?6:0):0,Dt)}px`,t.tagInMultiLine=Number.parseFloat(Ve.style.height)>=Dt,t.visible&&O.value!==!1&&((_e=(he=l.value)==null?void 0:he.updatePopper)==null||_e.call(he))})},D=he=>{if(!(t.previousQuery===he||t.isOnComposition)){if(t.previousQuery===null&&(typeof e.filterMethod==\"function\"||typeof e.remoteMethod==\"function\")){t.previousQuery=he;return}t.previousQuery=he,Ne(()=>{var _e,$e;t.visible&&(($e=(_e=l.value)==null?void 0:_e.updatePopper)==null||$e.call(_e))}),t.hoverIndex=-1,e.multiple&&e.filterable&&Ne(()=>{const _e=i.value.value.length*15+20;t.inputLength=e.collapseTags?Math.min(50,_e):_e,z(),N()}),e.remote&&typeof e.remoteMethod==\"function\"?(t.hoverIndex=-1,e.remoteMethod(he)):typeof e.filterMethod==\"function\"?(e.filterMethod(he),Dc(v)):(t.filteredOptionsCount=t.optionsCount,p.value.query=he,Dc(p),Dc(v)),e.defaultFirstOption&&(e.filterable||e.remote)&&t.filteredOptionsCount&&B()}},z=()=>{t.currentPlaceholder!==\"\"&&(t.currentPlaceholder=i.value.value?\"\":t.cachedPlaceHolder)},B=()=>{const he=T.value.filter(Ve=>Ve.visible&&!Ve.disabled&&!Ve.states.groupDisabled),_e=he.find(Ve=>Ve.created),$e=he[0];t.hoverIndex=Ee(T.value,_e||$e)},M=()=>{var he;if(e.multiple)t.selectedLabel=\"\";else{const $e=E(e.modelValue);(he=$e.props)!=null&&he.created?(t.createdLabel=$e.props.value,t.createdSelected=!0):t.createdSelected=!1,t.selectedLabel=$e.currentLabel,t.selected=$e,e.filterable&&(t.query=t.selectedLabel);return}const _e=[];Array.isArray(e.modelValue)&&e.modelValue.forEach($e=>{_e.push(E($e))}),t.selected=_e,Ne(()=>{N()})},E=he=>{let _e;const $e=np(he).toLowerCase()===\"object\",Ve=np(he).toLowerCase()===\"null\",st=np(he).toLowerCase()===\"undefined\";for(let Ft=t.cachedOptions.size-1;Ft>=0;Ft--){const Jt=_.value[Ft];if($e?vn(Jt,e.valueKey)===vn(he,e.valueKey):Jt.value===he){_e={value:he,currentLabel:Jt.currentLabel,isDisabled:Jt.isDisabled};break}}if(_e)return _e;const Dt=$e?he.label:!Ve&&!st?he:\"\",Ut={value:he,currentLabel:Dt};return e.multiple&&(Ut.hitState=!1),Ut},K=()=>{setTimeout(()=>{const he=e.valueKey;e.multiple?t.selected.length>0?t.hoverIndex=Math.min.apply(null,t.selected.map(_e=>T.value.findIndex($e=>vn($e,he)===vn(_e,he)))):t.hoverIndex=-1:t.hoverIndex=T.value.findIndex(_e=>He(_e)===He(t.selected))},300)},W=()=>{var he,_e;Y(),(_e=(he=l.value)==null?void 0:he.updatePopper)==null||_e.call(he),e.multiple&&!e.filterable&&N()},Y=()=>{var he;t.inputWidth=(he=o.value)==null?void 0:he.$el.getBoundingClientRect().width},q=()=>{e.filterable&&t.query!==t.selectedLabel&&(t.query=t.selectedLabel,D(t.query))},J=Yn(()=>{q()},$.value),ne=Yn(he=>{D(he.target.value)},$.value),oe=he=>{er(e.modelValue,he)||n.emit(ir,he)},Q=he=>{if(he.target.value.length<=0&&!ke()){const _e=e.modelValue.slice();_e.pop(),n.emit(Pt,_e),oe(_e)}he.target.value.length===1&&e.modelValue.length===0&&(t.currentPlaceholder=t.cachedPlaceHolder)},ae=(he,_e)=>{const $e=t.selected.indexOf(_e);if($e>-1&&!C.value){const Ve=e.modelValue.slice();Ve.splice($e,1),n.emit(Pt,Ve),oe(Ve),n.emit(\"remove-tag\",_e.value)}he.stopPropagation()},de=he=>{he.stopPropagation();const _e=e.multiple?[]:\"\";if(typeof _e!=\"string\")for(const $e of t.selected)$e.isDisabled&&_e.push($e.value);n.emit(Pt,_e),oe(_e),t.visible=!1,n.emit(\"clear\")},be=(he,_e)=>{var $e;if(e.multiple){const Ve=(e.modelValue||[]).slice(),st=Ee(Ve,he.value);st>-1?Ve.splice(st,1):(e.multipleLimit<=0||Ve.length<e.multipleLimit)&&Ve.push(he.value),n.emit(Pt,Ve),oe(Ve),he.created&&(t.query=\"\",D(\"\"),t.inputLength=20),e.filterable&&(($e=i.value)==null||$e.focus())}else n.emit(Pt,he.value),oe(he.value),t.visible=!1;t.isSilentBlur=_e,Pe(),!t.visible&&Ne(()=>{Be(he)})},Ee=(he=[],_e)=>{if(!zt(_e))return he.indexOf(_e);const $e=e.valueKey;let Ve=-1;return he.some((st,Dt)=>vn(st,$e)===vn(_e,$e)?(Ve=Dt,!0):!1),Ve},Pe=()=>{t.softFocus=!0;const he=i.value||o.value;he&&(he==null||he.focus())},Be=he=>{var _e,$e,Ve,st,Dt;const Ut=Array.isArray(he)?he[0]:he;let Ft=null;if(Ut!=null&&Ut.value){const Jt=T.value.filter(Mn=>Mn.value===Ut.value);Jt.length>0&&(Ft=Jt[0].$el)}if(l.value&&Ft){const Jt=(st=(Ve=($e=(_e=l.value)==null?void 0:_e.popperRef)==null?void 0:$e.contentRef)==null?void 0:Ve.querySelector)==null?void 0:st.call(Ve,`.${a.be(\"dropdown\",\"wrap\")}`);Jt&&lE(Jt,Ft)}(Dt=d.value)==null||Dt.handleScroll()},te=he=>{t.optionsCount++,t.filteredOptionsCount++,t.options.set(he.value,he),t.cachedOptions.set(he.value,he)},ie=(he,_e)=>{t.options.get(he)===_e&&(t.optionsCount--,t.filteredOptionsCount--,t.options.delete(he))},ge=he=>{he.code!==Ge.backspace&&ke(!1),t.inputLength=i.value.value.length*15+20,N()},ke=he=>{if(!Array.isArray(t.selected))return;const _e=t.selected[t.selected.length-1];if(!!_e)return he===!0||he===!1?(_e.hitState=he,he):(_e.hitState=!_e.hitState,_e.hitState)},xe=he=>{const _e=he.target.value;if(he.type===\"compositionend\")t.isOnComposition=!1,Ne(()=>D(_e));else{const $e=_e[_e.length-1]||\"\";t.isOnComposition=!zm($e)}},Ie=()=>{Ne(()=>Be(t.selected))},ye=he=>{t.softFocus?t.softFocus=!1:((e.automaticDropdown||e.filterable)&&(e.filterable&&!t.visible&&(t.menuVisibleOnFocus=!0),t.visible=!0),n.emit(\"focus\",he))},pe=()=>{var he;t.visible=!1,(he=o.value)==null||he.blur()},ue=he=>{Ne(()=>{t.isSilentBlur?t.isSilentBlur=!1:n.emit(\"blur\",he)}),t.softFocus=!1},Ce=he=>{de(he)},je=()=>{t.visible=!1},ee=()=>{var he;e.automaticDropdown||C.value||(t.menuVisibleOnFocus?t.menuVisibleOnFocus=!1:t.visible=!t.visible,t.visible&&((he=i.value||o.value)==null||he.focus()))},me=()=>{t.visible?T.value[t.hoverIndex]&&be(T.value[t.hoverIndex],void 0):ee()},He=he=>zt(he.value)?vn(he.value,e.valueKey):he.value,lt=x(()=>T.value.filter(he=>he.visible).every(he=>he.disabled)),Ye=he=>{if(!t.visible){t.visible=!0;return}if(!(t.options.size===0||t.filteredOptionsCount===0)&&!t.isOnComposition&&!lt.value){he===\"next\"?(t.hoverIndex++,t.hoverIndex===t.options.size&&(t.hoverIndex=0)):he===\"prev\"&&(t.hoverIndex--,t.hoverIndex<0&&(t.hoverIndex=t.options.size-1));const _e=T.value[t.hoverIndex];(_e.disabled===!0||_e.states.groupDisabled===!0||!_e.visible)&&Ye(he),Ne(()=>Be(f.value))}};return{optionsArray:T,selectSize:L,handleResize:W,debouncedOnInputChange:J,debouncedQueryChange:ne,deletePrevTag:Q,deleteTag:ae,deleteSelected:de,handleOptionSelect:be,scrollToOption:Be,readonly:b,resetInputHeight:N,showClose:S,iconComponent:w,iconReverse:k,showNewOption:I,collapseTagSize:j,setSelected:M,managePlaceholder:z,selectDisabled:C,emptyText:O,toggleLastOptionHitState:ke,resetInputState:ge,handleComposition:xe,onOptionCreate:te,onOptionDestroy:ie,handleMenuEnter:Ie,handleFocus:ye,blur:pe,handleBlur:ue,handleClearClick:Ce,handleClose:je,toggleMenu:ee,selectOption:me,getValueKey:He,navigateOptions:Ye,dropMenuVisible:F,queryChange:p,groupQueryChange:v,reference:o,input:i,tooltipRef:l,tags:s,selectWrapper:c,scrollbar:d}},Sy=\"ElSelect\",mde=G({name:Sy,componentName:Sy,components:{ElInput:Ra,ElSelectMenu:hde,ElOption:pw,ElTag:Gm,ElScrollbar:xi,ElTooltip:Ur,ElIcon:ft},directives:{ClickOutside:Is},props:{name:String,id:String,modelValue:{type:[Array,String,Number,Boolean,Object],default:void 0},autocomplete:{type:String,default:\"off\"},automaticDropdown:Boolean,size:{type:String,validator:va},effect:{type:String,default:\"light\"},disabled:Boolean,clearable:Boolean,filterable:Boolean,allowCreate:Boolean,loading:Boolean,popperClass:{type:String,default:\"\"},remote:Boolean,loadingText:String,noMatchText:String,noDataText:String,remoteMethod:Function,filterMethod:Function,multiple:Boolean,multipleLimit:{type:Number,default:0},placeholder:{type:String},defaultFirstOption:Boolean,reserveKeyword:{type:Boolean,default:!0},valueKey:{type:String,default:\"value\"},collapseTags:Boolean,collapseTagsTooltip:{type:Boolean,default:!1},popperAppendToBody:{type:Boolean,default:void 0},teleported:mr.teleported,persistent:{type:Boolean,default:!0},clearIcon:{type:[String,Object],default:gi},fitInputWidth:{type:Boolean,default:!1},suffixIcon:{type:[String,Object],default:Of},tagType:Ke(Te({},iw.type),{default:\"info\"})},emits:[Pt,ir,\"remove-tag\",\"clear\",\"visible-change\",\"focus\",\"blur\"],setup(e,t){const n=De(\"select\"),r=De(\"input\"),{t:a}=ln(),o=pde(e),{optionsArray:i,selectSize:l,readonly:s,handleResize:c,collapseTagSize:d,debouncedOnInputChange:f,debouncedQueryChange:p,deletePrevTag:v,deleteTag:m,deleteSelected:y,handleOptionSelect:b,scrollToOption:C,setSelected:S,resetInputHeight:w,managePlaceholder:k,showClose:$,selectDisabled:O,iconComponent:T,iconReverse:_,showNewOption:I,emptyText:L,toggleLastOptionHitState:j,resetInputState:F,handleComposition:N,onOptionCreate:D,onOptionDestroy:z,handleMenuEnter:B,handleFocus:M,blur:E,handleBlur:K,handleClearClick:W,handleClose:Y,toggleMenu:q,selectOption:J,getValueKey:ne,navigateOptions:oe,dropMenuVisible:Q,reference:ae,input:de,tooltipRef:be,tags:Ee,selectWrapper:Pe,scrollbar:Be,queryChange:te,groupQueryChange:ie}=vde(e,o,t),{focus:ge}=nZ(ae),{inputWidth:ke,selected:xe,inputLength:Ie,filteredOptionsCount:ye,visible:pe,softFocus:ue,selectedLabel:Ce,hoverIndex:je,query:ee,inputHovering:me,currentPlaceholder:He,menuVisibleOnFocus:lt,isOnComposition:Ye,isSilentBlur:he,options:_e,cachedOptions:$e,optionsCount:Ve,prefixWidth:st,tagInMultiLine:Dt}=or(o),Ut=x(()=>{const tr=[n.b()],nr=A(l);return nr&&tr.push(n.m(nr)),e.disabled&&tr.push(n.m(\"disabled\")),tr}),Ft=x(()=>({maxWidth:`${A(ke)-32}px`,width:\"100%\"}));ot(Zm,bt({props:e,options:_e,optionsArray:i,cachedOptions:$e,optionsCount:Ve,filteredOptionsCount:ye,hoverIndex:je,handleOptionSelect:b,onOptionCreate:D,onOptionDestroy:z,selectWrapper:Pe,selected:xe,setSelected:S,queryChange:te,groupQueryChange:ie})),et(()=>{if(o.cachedPlaceHolder=He.value=e.placeholder||a(\"el.select.placeholder\"),e.multiple&&Array.isArray(e.modelValue)&&e.modelValue.length>0&&(He.value=\"\"),wc(Pe.value,c),ae.value&&ae.value.$el){const tr=ae.value.input;o.initialInputHeight=tr.getBoundingClientRect().height||vE(l.value)}e.remote&&e.multiple&&w(),Ne(()=>{if(!!ae.value&&(ae.value.$el&&(ke.value=ae.value.$el.getBoundingClientRect().width),t.slots.prefix)){const tr=ae.value.$el.childNodes,nr=Array.from(tr).find(Wo=>Wo.tagName===\"INPUT\"),Va=ae.value.$el.querySelector(`.${r.e(\"prefix\")}`);st.value=Math.max(Va.getBoundingClientRect().width+5,30),o.prefixWidth&&(nr.style.paddingLeft=`${Math.max(o.prefixWidth,30)}px`)}}),S()}),Lt(()=>{Sc(Pe.value,c)}),e.multiple&&!Array.isArray(e.modelValue)&&t.emit(Pt,[]),!e.multiple&&Array.isArray(e.modelValue)&&t.emit(Pt,\"\");const Jt=x(()=>{var tr,nr;return(nr=(tr=be.value)==null?void 0:tr.popperRef)==null?void 0:nr.contentRef}),{compatTeleported:Mn}=Oc(Sy,\"popperAppendToBody\");return{tagInMultiLine:Dt,prefixWidth:st,selectSize:l,readonly:s,handleResize:c,collapseTagSize:d,debouncedOnInputChange:f,debouncedQueryChange:p,deletePrevTag:v,deleteTag:m,deleteSelected:y,handleOptionSelect:b,scrollToOption:C,inputWidth:ke,selected:xe,inputLength:Ie,filteredOptionsCount:ye,visible:pe,softFocus:ue,selectedLabel:Ce,hoverIndex:je,query:ee,inputHovering:me,currentPlaceholder:He,menuVisibleOnFocus:lt,isOnComposition:Ye,isSilentBlur:he,options:_e,resetInputHeight:w,managePlaceholder:k,showClose:$,selectDisabled:O,iconComponent:T,iconReverse:_,showNewOption:I,emptyText:L,toggleLastOptionHitState:j,resetInputState:F,handleComposition:N,handleMenuEnter:B,handleFocus:M,blur:E,handleBlur:K,handleClearClick:W,handleClose:Y,toggleMenu:q,selectOption:J,getValueKey:ne,navigateOptions:oe,dropMenuVisible:Q,focus:ge,reference:ae,input:de,tooltipRef:be,popperPaneRef:Jt,tags:Ee,selectWrapper:Pe,scrollbar:Be,wrapperKls:Ut,selectTagsStyle:Ft,compatTeleported:Mn,nsSelect:n}}}),gde={class:\"select-trigger\"},yde=[\"disabled\",\"autocomplete\"],bde={style:{height:\"100%\",display:\"flex\",\"justify-content\":\"center\",\"align-items\":\"center\"}};function Cde(e,t,n,r,a,o){const i=we(\"el-tag\"),l=we(\"el-tooltip\"),s=we(\"el-icon\"),c=we(\"el-input\"),d=we(\"el-option\"),f=we(\"el-scrollbar\"),p=we(\"el-select-menu\"),v=pa(\"click-outside\");return at((R(),X(\"div\",{ref:\"selectWrapper\",class:U(e.wrapperKls),onClick:t[24]||(t[24]=dt((...m)=>e.toggleMenu&&e.toggleMenu(...m),[\"stop\"]))},[g(l,{ref:\"tooltipRef\",visible:e.dropMenuVisible,\"onUpdate:visible\":t[23]||(t[23]=m=>e.dropMenuVisible=m),placement:\"bottom-start\",teleported:e.compatTeleported,\"popper-class\":[e.nsSelect.e(\"popper\"),e.popperClass],\"fallback-placements\":[\"bottom-start\",\"top-start\",\"right\",\"left\"],effect:e.effect,pure:\"\",trigger:\"click\",transition:`${e.nsSelect.namespace.value}-zoom-in-top`,\"stop-popper-mouse-event\":!1,\"gpu-acceleration\":!1,persistent:e.persistent,onShow:e.handleMenuEnter},{default:re(()=>[Z(\"div\",gde,[e.multiple?(R(),X(\"div\",{key:0,ref:\"tags\",class:U(e.nsSelect.e(\"tags\")),style:Xe(e.selectTagsStyle)},[e.collapseTags&&e.selected.length?(R(),X(\"span\",{key:0,class:U([e.nsSelect.b(\"tags-wrapper\"),{\"has-prefix\":e.prefixWidth&&e.selected.length}])},[g(i,{closable:!e.selectDisabled&&!e.selected[0].isDisabled,size:e.collapseTagSize,hit:e.selected[0].hitState,type:e.tagType,\"disable-transitions\":\"\",onClose:t[0]||(t[0]=m=>e.deleteTag(m,e.selected[0]))},{default:re(()=>[Z(\"span\",{class:U(e.nsSelect.e(\"tags-text\")),style:Xe({maxWidth:e.inputWidth-123+\"px\"})},Me(e.selected[0].currentLabel),7)]),_:1},8,[\"closable\",\"size\",\"hit\",\"type\"]),e.selected.length>1?(R(),fe(i,{key:0,closable:!1,size:e.collapseTagSize,type:e.tagType,\"disable-transitions\":\"\"},{default:re(()=>[e.collapseTagsTooltip?(R(),fe(l,{key:0,disabled:e.dropMenuVisible,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],effect:e.effect,placement:\"bottom\",teleported:!1},{default:re(()=>[Z(\"span\",{class:U(e.nsSelect.e(\"tags-text\"))},\"+ \"+Me(e.selected.length-1),3)]),content:re(()=>[Z(\"div\",{class:U(e.nsSelect.e(\"collapse-tags\"))},[(R(!0),X(Fe,null,Rt(e.selected,(m,y)=>(R(),X(\"div\",{key:y,class:U(e.nsSelect.e(\"collapse-tag\"))},[(R(),fe(i,{key:e.getValueKey(m),class:\"in-tooltip\",closable:!e.selectDisabled&&!m.isDisabled,size:e.collapseTagSize,hit:m.hitState,type:e.tagType,\"disable-transitions\":\"\",style:{margin:\"2px\"},onClose:b=>e.deleteTag(b,m)},{default:re(()=>[Z(\"span\",{class:U(e.nsSelect.e(\"tags-text\")),style:Xe({maxWidth:e.inputWidth-75+\"px\"})},Me(m.currentLabel),7)]),_:2},1032,[\"closable\",\"size\",\"hit\",\"type\",\"onClose\"]))],2))),128))],2)]),_:1},8,[\"disabled\",\"effect\"])):(R(),X(\"span\",{key:1,class:U(e.nsSelect.e(\"tags-text\"))},\"+ \"+Me(e.selected.length-1),3))]),_:1},8,[\"size\",\"type\"])):se(\"v-if\",!0)],2)):se(\"v-if\",!0),se(\" <div> \"),e.collapseTags?se(\"v-if\",!0):(R(),fe(Vn,{key:1,onAfterLeave:e.resetInputHeight},{default:re(()=>[Z(\"span\",{class:U([e.nsSelect.b(\"tags-wrapper\"),{\"has-prefix\":e.prefixWidth&&e.selected.length}])},[(R(!0),X(Fe,null,Rt(e.selected,m=>(R(),fe(i,{key:e.getValueKey(m),closable:!e.selectDisabled&&!m.isDisabled,size:e.collapseTagSize,hit:m.hitState,type:e.tagType,\"disable-transitions\":\"\",onClose:y=>e.deleteTag(y,m)},{default:re(()=>[Z(\"span\",{class:U(e.nsSelect.e(\"tags-text\")),style:Xe({maxWidth:e.inputWidth-75+\"px\"})},Me(m.currentLabel),7)]),_:2},1032,[\"closable\",\"size\",\"hit\",\"type\",\"onClose\"]))),128))],2)]),_:1},8,[\"onAfterLeave\"])),se(\" </div> \"),e.filterable?at((R(),X(\"input\",{key:2,ref:\"input\",\"onUpdate:modelValue\":t[1]||(t[1]=m=>e.query=m),type:\"text\",class:U([e.nsSelect.e(\"input\"),e.nsSelect.is(e.selectSize)]),disabled:e.selectDisabled,autocomplete:e.autocomplete,style:Xe({marginLeft:e.prefixWidth&&!e.selected.length||e.tagInMultiLine?`${e.prefixWidth}px`:\"\",flexGrow:1,width:`${e.inputLength/(e.inputWidth-32)}%`,maxWidth:`${e.inputWidth-42}px`}),onFocus:t[2]||(t[2]=(...m)=>e.handleFocus&&e.handleFocus(...m)),onBlur:t[3]||(t[3]=(...m)=>e.handleBlur&&e.handleBlur(...m)),onKeyup:t[4]||(t[4]=(...m)=>e.managePlaceholder&&e.managePlaceholder(...m)),onKeydown:[t[5]||(t[5]=(...m)=>e.resetInputState&&e.resetInputState(...m)),t[6]||(t[6]=It(dt(m=>e.navigateOptions(\"next\"),[\"prevent\"]),[\"down\"])),t[7]||(t[7]=It(dt(m=>e.navigateOptions(\"prev\"),[\"prevent\"]),[\"up\"])),t[8]||(t[8]=It(dt(m=>e.visible=!1,[\"stop\",\"prevent\"]),[\"esc\"])),t[9]||(t[9]=It(dt((...m)=>e.selectOption&&e.selectOption(...m),[\"stop\",\"prevent\"]),[\"enter\"])),t[10]||(t[10]=It((...m)=>e.deletePrevTag&&e.deletePrevTag(...m),[\"delete\"])),t[11]||(t[11]=It(m=>e.visible=!1,[\"tab\"]))],onCompositionstart:t[12]||(t[12]=(...m)=>e.handleComposition&&e.handleComposition(...m)),onCompositionupdate:t[13]||(t[13]=(...m)=>e.handleComposition&&e.handleComposition(...m)),onCompositionend:t[14]||(t[14]=(...m)=>e.handleComposition&&e.handleComposition(...m)),onInput:t[15]||(t[15]=(...m)=>e.debouncedQueryChange&&e.debouncedQueryChange(...m))},null,46,yde)),[[fC,e.query]]):se(\"v-if\",!0)],6)):se(\"v-if\",!0),g(c,{id:e.id,ref:\"reference\",modelValue:e.selectedLabel,\"onUpdate:modelValue\":t[16]||(t[16]=m=>e.selectedLabel=m),type:\"text\",placeholder:e.currentPlaceholder,name:e.name,autocomplete:e.autocomplete,size:e.selectSize,disabled:e.selectDisabled,readonly:e.readonly,\"validate-event\":!1,class:U([e.nsSelect.is(\"focus\",e.visible)]),tabindex:e.multiple&&e.filterable?-1:void 0,onFocus:e.handleFocus,onBlur:e.handleBlur,onInput:e.debouncedOnInputChange,onPaste:e.debouncedOnInputChange,onCompositionstart:e.handleComposition,onCompositionupdate:e.handleComposition,onCompositionend:e.handleComposition,onKeydown:[t[17]||(t[17]=It(dt(m=>e.navigateOptions(\"next\"),[\"stop\",\"prevent\"]),[\"down\"])),t[18]||(t[18]=It(dt(m=>e.navigateOptions(\"prev\"),[\"stop\",\"prevent\"]),[\"up\"])),It(dt(e.selectOption,[\"stop\",\"prevent\"]),[\"enter\"]),t[19]||(t[19]=It(dt(m=>e.visible=!1,[\"stop\",\"prevent\"]),[\"esc\"])),t[20]||(t[20]=It(m=>e.visible=!1,[\"tab\"]))],onMouseenter:t[21]||(t[21]=m=>e.inputHovering=!0),onMouseleave:t[22]||(t[22]=m=>e.inputHovering=!1)},sl({suffix:re(()=>[e.iconComponent?at((R(),fe(s,{key:0,class:U([e.nsSelect.e(\"caret\"),e.nsSelect.e(\"icon\"),e.iconReverse])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])),[[_t,!e.showClose]]):se(\"v-if\",!0),e.showClose&&e.clearIcon?(R(),fe(s,{key:1,class:U([e.nsSelect.e(\"caret\"),e.nsSelect.e(\"icon\")]),onClick:e.handleClearClick},{default:re(()=>[(R(),fe(Kt(e.clearIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)]),_:2},[e.$slots.prefix?{name:\"prefix\",fn:re(()=>[Z(\"div\",bde,[Oe(e.$slots,\"prefix\")])])}:void 0]),1032,[\"id\",\"modelValue\",\"placeholder\",\"name\",\"autocomplete\",\"size\",\"disabled\",\"readonly\",\"class\",\"tabindex\",\"onFocus\",\"onBlur\",\"onInput\",\"onPaste\",\"onCompositionstart\",\"onCompositionupdate\",\"onCompositionend\",\"onKeydown\"])])]),content:re(()=>[g(p,null,{default:re(()=>[at(g(f,{ref:\"scrollbar\",tag:\"ul\",\"wrap-class\":e.nsSelect.be(\"dropdown\",\"wrap\"),\"view-class\":e.nsSelect.be(\"dropdown\",\"list\"),class:U([e.nsSelect.is(\"empty\",!e.allowCreate&&Boolean(e.query)&&e.filteredOptionsCount===0)])},{default:re(()=>[e.showNewOption?(R(),fe(d,{key:0,value:e.query,created:!0},null,8,[\"value\"])):se(\"v-if\",!0),Oe(e.$slots,\"default\")]),_:3},8,[\"wrap-class\",\"view-class\",\"class\"]),[[_t,e.options.size>0&&!e.loading]]),e.emptyText&&(!e.allowCreate||e.loading||e.allowCreate&&e.options.size===0)?(R(),X(Fe,{key:0},[e.$slots.empty?Oe(e.$slots,\"empty\",{key:0}):(R(),X(\"p\",{key:1,class:U(e.nsSelect.be(\"dropdown\",\"empty\"))},Me(e.emptyText),3))],2112)):se(\"v-if\",!0)]),_:3})]),_:3},8,[\"visible\",\"teleported\",\"popper-class\",\"effect\",\"transition\",\"persistent\",\"onShow\"])],2)),[[v,e.handleClose,e.popperPaneRef]])}var wde=Ae(mde,[[\"render\",Cde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select/src/select.vue\"]]);const Sde=G({name:\"ElOptionGroup\",componentName:\"ElOptionGroup\",props:{label:String,disabled:{type:Boolean,default:!1}},setup(e){const t=De(\"select\"),n=H(!0),r=$t(),a=H([]);ot(A5,bt(Te({},or(e))));const o=ve(Zm);et(()=>{a.value=i(r.subTree)});const i=s=>{const c=[];return Array.isArray(s.children)&&s.children.forEach(d=>{var f;d.type&&d.type.name===\"ElOption\"&&d.component&&d.component.proxy?c.push(d.component.proxy):(f=d.children)!=null&&f.length&&c.push(...i(d))}),c},{groupQueryChange:l}=Gt(o);return ce(l,()=>{n.value=a.value.some(s=>s.visible===!0)}),{visible:n,ns:t}}});function kde(e,t,n,r,a,o){return at((R(),X(\"ul\",{class:U(e.ns.be(\"group\",\"wrap\"))},[Z(\"li\",{class:U(e.ns.be(\"group\",\"title\"))},Me(e.label),3),Z(\"li\",null,[Z(\"ul\",{class:U(e.ns.b(\"group\"))},[Oe(e.$slots,\"default\")],2)])],2)),[[_t,e.visible]])}var D5=Ae(Sde,[[\"render\",kde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select/src/option-group.vue\"]]);const bs=xt(wde,{Option:pw,OptionGroup:D5}),Cv=En(pw),$de=En(D5),vw=()=>ve(PE,{}),Ode=Ze({pageSize:{type:Number,required:!0},pageSizes:{type:Le(Array),default:()=>xn([10,20,30,40,50,100])},popperClass:{type:String,default:\"\"},disabled:Boolean,size:{type:String,default:\"default\"}}),Pde=G({name:\"ElPaginationSizes\",components:{ElSelect:bs,ElOption:Cv},props:Ode,emits:[\"page-size-change\"],setup(e,{emit:t}){const{t:n}=ln(),r=De(\"pagination\"),a=vw(),o=H(e.pageSize);ce(()=>e.pageSizes,(s,c)=>{if(!er(s,c)&&Array.isArray(s)){const d=s.includes(e.pageSize)?e.pageSize:e.pageSizes[0];t(\"page-size-change\",d)}}),ce(()=>e.pageSize,s=>{o.value=s});const i=x(()=>e.pageSizes);function l(s){var c;s!==o.value&&(o.value=s,(c=a.handleSizeChange)==null||c.call(a,Number(s)))}return{ns:r,innerPagesizes:i,innerPageSize:o,t:n,handleChange:l}}});function Tde(e,t,n,r,a,o){const i=we(\"el-option\"),l=we(\"el-select\");return R(),X(\"span\",{class:U(e.ns.e(\"sizes\"))},[g(l,{\"model-value\":e.innerPageSize,disabled:e.disabled,\"popper-class\":e.popperClass,size:e.size,onChange:e.handleChange},{default:re(()=>[(R(!0),X(Fe,null,Rt(e.innerPagesizes,s=>(R(),fe(i,{key:s,value:s,label:s+e.t(\"el.pagination.pagesize\")},null,8,[\"value\",\"label\"]))),128))]),_:1},8,[\"model-value\",\"disabled\",\"popper-class\",\"size\",\"onChange\"])],2)}var xde=Ae(Pde,[[\"render\",Tde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/sizes.vue\"]]);const _de=G({name:\"ElPaginationJumper\",components:{ElInput:Ra},setup(){const{t:e}=ln(),t=De(\"pagination\"),{pageCount:n,disabled:r,currentPage:a,changeEvent:o}=vw(),i=H(),l=x(()=>{var d;return(d=i.value)!=null?d:a==null?void 0:a.value});function s(d){i.value=+d}function c(d){d=Math.trunc(+d),o==null||o(+d),i.value=void 0}return{ns:t,pageCount:n,disabled:r,innerValue:l,t:e,handleInput:s,handleChange:c}}}),Ede=[\"disabled\"];function Mde(e,t,n,r,a,o){const i=we(\"el-input\");return R(),X(\"span\",{class:U(e.ns.e(\"jump\")),disabled:e.disabled},[yt(Me(e.t(\"el.pagination.goto\"))+\" \",1),g(i,{size:\"small\",class:U([e.ns.e(\"editor\"),e.ns.is(\"in-pagination\")]),min:1,max:e.pageCount,disabled:e.disabled,\"model-value\":e.innerValue,type:\"number\",\"onUpdate:modelValue\":e.handleInput,onChange:e.handleChange},null,8,[\"class\",\"max\",\"disabled\",\"model-value\",\"onUpdate:modelValue\",\"onChange\"]),yt(\" \"+Me(e.t(\"el.pagination.pageClassifier\")),1)],10,Ede)}var Ide=Ae(_de,[[\"render\",Mde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/jumper.vue\"]]);const Nde={total:{type:Number,default:1e3}},Ade=G({name:\"ElPaginationTotal\",props:Nde,setup(){const{t:e}=ln(),t=De(\"pagination\"),{disabled:n}=vw();return{t:e,ns:t,disabled:n}}}),Dde=[\"disabled\"];function Rde(e,t,n,r,a,o){return R(),X(\"span\",{class:U(e.ns.e(\"total\")),disabled:e.disabled},Me(e.t(\"el.pagination.total\",{total:e.total})),11,Dde)}var Lde=Ae(Ade,[[\"render\",Rde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/total.vue\"]]);const Fde={currentPage:{type:Number,default:1},pageCount:{type:Number,required:!0},pagerCount:{type:Number,default:7},disabled:Boolean},Bde=G({name:\"ElPaginationPager\",components:{DArrowLeft:Fm,DArrowRight:Bm,MoreFilled:fG},props:Fde,emits:[\"change\"],setup(e,{emit:t}){const n=De(\"pager\"),r=De(\"icon\"),a=H(!1),o=H(!1),i=H(!1),l=H(!1),s=x(()=>{const p=e.pagerCount,v=(p-1)/2,m=Number(e.currentPage),y=Number(e.pageCount);let b=!1,C=!1;y>p&&(m>p-v&&(b=!0),m<y-v&&(C=!0));const S=[];if(b&&!C){const w=y-(p-2);for(let k=w;k<y;k++)S.push(k)}else if(!b&&C)for(let w=2;w<p;w++)S.push(w);else if(b&&C){const w=Math.floor(p/2)-1;for(let k=m-w;k<=m+w;k++)S.push(k)}else for(let w=2;w<y;w++)S.push(w);return S});Wn(()=>{const p=(e.pagerCount-1)/2;a.value=!1,o.value=!1,e.pageCount>e.pagerCount&&(e.currentPage>e.pagerCount-p&&(a.value=!0),e.currentPage<e.pageCount-p&&(o.value=!0))});function c(p){e.disabled||(p===\"left\"?i.value=!0:l.value=!0)}function d(p){const v=p.target;if(v.tagName.toLowerCase()===\"li\"&&Array.from(v.classList).includes(\"number\")){const m=Number(v.textContent);m!==e.currentPage&&t(\"change\",m)}}function f(p){const v=p.target;if(v.tagName.toLowerCase()===\"ul\"||e.disabled)return;let m=Number(v.textContent);const y=e.pageCount,b=e.currentPage,C=e.pagerCount-2;v.className.includes(\"more\")&&(v.className.includes(\"quickprev\")?m=b-C:v.className.includes(\"quicknext\")&&(m=b+C)),Number.isNaN(+m)||(m<1&&(m=1),m>y&&(m=y)),m!==b&&t(\"change\",m)}return{showPrevMore:a,showNextMore:o,quickPrevHover:i,quickNextHover:l,pagers:s,nsPager:n,nsIcon:r,onMouseenter:c,onPagerClick:f,onEnter:d}}}),Vde=[\"aria-current\"],zde=[\"aria-current\"],Hde=[\"aria-current\"];function jde(e,t,n,r,a,o){const i=we(\"d-arrow-left\"),l=we(\"more-filled\"),s=we(\"d-arrow-right\");return R(),X(\"ul\",{class:U(e.nsPager.b()),onClick:t[4]||(t[4]=(...c)=>e.onPagerClick&&e.onPagerClick(...c)),onKeyup:t[5]||(t[5]=It((...c)=>e.onEnter&&e.onEnter(...c),[\"enter\"]))},[e.pageCount>0?(R(),X(\"li\",{key:0,class:U([[e.nsPager.is(\"active\",e.currentPage===1),e.nsPager.is(\"disabled\",e.disabled)],\"number\"]),\"aria-current\":e.currentPage===1,tabindex:\"0\"},\" 1 \",10,Vde)):se(\"v-if\",!0),e.showPrevMore?(R(),X(\"li\",{key:1,class:U([\"more\",\"btn-quickprev\",e.nsIcon.b(),e.nsPager.is(\"disabled\",e.disabled)]),onMouseenter:t[0]||(t[0]=c=>e.onMouseenter(\"left\")),onMouseleave:t[1]||(t[1]=c=>e.quickPrevHover=!1)},[e.quickPrevHover?(R(),fe(i,{key:0})):(R(),fe(l,{key:1}))],34)):se(\"v-if\",!0),(R(!0),X(Fe,null,Rt(e.pagers,c=>(R(),X(\"li\",{key:c,class:U([[e.nsPager.is(\"active\",e.currentPage===c),e.nsPager.is(\"disabled\",e.disabled)],\"number\"]),\"aria-current\":e.currentPage===c,tabindex:\"0\"},Me(c),11,zde))),128)),e.showNextMore?(R(),X(\"li\",{key:2,class:U([\"more\",\"btn-quicknext\",e.nsIcon.b(),e.nsPager.is(\"disabled\",e.disabled)]),onMouseenter:t[2]||(t[2]=c=>e.onMouseenter(\"right\")),onMouseleave:t[3]||(t[3]=c=>e.quickNextHover=!1)},[e.quickNextHover?(R(),fe(s,{key:0})):(R(),fe(l,{key:1}))],34)):se(\"v-if\",!0),e.pageCount>1?(R(),X(\"li\",{key:3,class:U([[e.nsPager.is(\"active\",e.currentPage===e.pageCount),e.nsPager.is(\"disabled\",e.disabled)],\"number\"]),\"aria-current\":e.currentPage===e.pageCount,tabindex:\"0\"},Me(e.pageCount),11,Hde)):se(\"v-if\",!0)],34)}var Kde=Ae(Bde,[[\"render\",jde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/pagination/src/components/pager.vue\"]]);const Tr=e=>typeof e!=\"number\",Wde=Ze({total:Number,pageSize:Number,defaultPageSize:Number,currentPage:Number,defaultCurrentPage:Number,pageCount:Number,pagerCount:{type:Number,validator:e=>typeof e==\"number\"&&Math.trunc(e)===e&&e>4&&e<22&&e%2===1,default:7},layout:{type:String,default:[\"prev\",\"pager\",\"next\",\"jumper\",\"->\",\"total\"].join(\", \")},pageSizes:{type:Le(Array),default:()=>xn([10,20,30,40,50,100])},popperClass:{type:String,default:\"\"},prevText:{type:String,default:\"\"},nextText:{type:String,default:\"\"},small:Boolean,background:Boolean,disabled:Boolean,hideOnSinglePage:Boolean}),Ude={\"update:current-page\":e=>typeof e==\"number\",\"update:page-size\":e=>typeof e==\"number\",\"size-change\":e=>typeof e==\"number\",\"current-change\":e=>typeof e==\"number\",\"prev-click\":e=>typeof e==\"number\",\"next-click\":e=>typeof e==\"number\"},aO=\"ElPagination\";var Yde=G({name:aO,props:Wde,emits:Ude,setup(e,{emit:t,slots:n}){const{t:r}=ln(),a=De(\"pagination\"),o=$t().vnode.props||{},i=\"onUpdate:currentPage\"in o||\"onUpdate:current-page\"in o||\"onCurrentChange\"in o,l=\"onUpdate:pageSize\"in o||\"onUpdate:page-size\"in o||\"onSizeChange\"in o,s=x(()=>{if(Tr(e.total)&&Tr(e.pageCount)||!Tr(e.currentPage)&&!i)return!1;if(e.layout.includes(\"sizes\")){if(Tr(e.pageCount)){if(!Tr(e.total)&&!Tr(e.pageSize)&&!l)return!1}else if(!l)return!1}return!0}),c=H(Tr(e.defaultPageSize)?10:e.defaultPageSize),d=H(Tr(e.defaultCurrentPage)?1:e.defaultCurrentPage),f=x({get(){return Tr(e.pageSize)?c.value:e.pageSize},set(w){Tr(e.pageSize)&&(c.value=w),l&&(t(\"update:page-size\",w),t(\"size-change\",w))}}),p=x(()=>{let w=0;return Tr(e.pageCount)?Tr(e.total)||(w=Math.max(1,Math.ceil(e.total/f.value))):w=e.pageCount,w}),v=x({get(){return Tr(e.currentPage)?d.value:e.currentPage},set(w){let k=w;w<1?k=1:w>p.value&&(k=p.value),Tr(e.currentPage)&&(d.value=k),i&&(t(\"update:current-page\",k),t(\"current-change\",k))}});ce(p,w=>{v.value>w&&(v.value=w)});function m(w){v.value=w}function y(w){f.value=w;const k=p.value;v.value>k&&(v.value=k)}function b(){e.disabled||(v.value-=1,t(\"prev-click\",v.value))}function C(){e.disabled||(v.value+=1,t(\"next-click\",v.value))}function S(w,k){w&&(w.props||(w.props={}),w.props.class=[w.props.class,k].join(\" \"))}return ot(PE,{pageCount:p,disabled:x(()=>e.disabled),currentPage:v,changeEvent:m,handleSizeChange:y}),()=>{var w,k;if(!s.value)return r(\"el.pagination.deprecationWarning\"),null;if(!e.layout||e.hideOnSinglePage&&p.value<=1)return null;const $=[],O=[],T=qe(\"div\",{class:a.e(\"rightwrapper\")},O),_={prev:qe(tde,{disabled:e.disabled,currentPage:v.value,prevText:e.prevText,onClick:b}),jumper:qe(Ide),pager:qe(Kde,{currentPage:v.value,pageCount:p.value,pagerCount:e.pagerCount,onChange:m,disabled:e.disabled}),next:qe(lde,{disabled:e.disabled,currentPage:v.value,pageCount:p.value,nextText:e.nextText,onClick:C}),sizes:qe(xde,{pageSize:f.value,pageSizes:e.pageSizes,popperClass:e.popperClass,disabled:e.disabled,size:e.small?\"small\":\"default\"}),slot:(k=(w=n==null?void 0:n.default)==null?void 0:w.call(n))!=null?k:null,total:qe(Lde,{total:Tr(e.total)?0:e.total})},I=e.layout.split(\",\").map(j=>j.trim());let L=!1;return I.forEach(j=>{if(j===\"->\"){L=!0;return}L?O.push(_[j]):$.push(_[j])}),S($[0],a.is(\"first\")),S($[$.length-1],a.is(\"last\")),L&&O.length>0&&(S(O[0],a.is(\"first\")),S(O[O.length-1],a.is(\"last\")),$.push(T)),qe(\"div\",{role:\"pagination\",\"aria-label\":\"pagination\",class:[a.b(),a.is(\"background\",e.background),{[a.m(\"small\")]:e.small}]},$)}}});const qde=xt(Yde),Gde=Ze({title:{type:String},confirmButtonText:{type:String},cancelButtonText:{type:String},confirmButtonType:{type:String,values:m0,default:\"primary\"},cancelButtonType:{type:String,values:m0,default:\"text\"},icon:{type:wr,default:DG},iconColor:{type:String,default:\"#f90\"},hideIcon:{type:Boolean,default:!1},hideAfter:{type:Number,default:200},onConfirm:{type:Le(Function)},onCancel:{type:Le(Function)},teleported:mr.teleported,persistent:mr.persistent}),oO=\"ElPopconfirm\",Xde=G({name:oO,components:{ElButton:xa,ElTooltip:Ur,ElIcon:ft},props:Gde,setup(e){const{compatTeleported:t}=Oc(oO,\"appendToBody\"),{t:n}=ln(),r=De(\"popconfirm\"),a=H(),o=()=>{var f,p;(p=(f=A(a))==null?void 0:f.onClose)==null||p.call(f)},i=()=>{o()},l=f=>{var p;(p=e.onConfirm)==null||p.call(e,f),i()},s=f=>{var p;(p=e.onCancel)==null||p.call(e,f),i()},c=x(()=>e.confirmButtonText||n(\"el.popconfirm.confirmButtonText\")),d=x(()=>e.cancelButtonText||n(\"el.popconfirm.cancelButtonText\"));return{finalConfirmButtonText:c,finalCancelButtonText:d,tooltipRef:a,ns:r,compatTeleported:t,confirm:l,cancel:s}}});function Zde(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"el-button\"),s=we(\"el-tooltip\");return R(),fe(s,hn({ref:\"tooltipRef\"},e.$attrs,{trigger:\"click\",effect:\"light\",\"popper-class\":`${e.ns.namespace.value}-popover`,teleported:e.compatTeleported,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],\"hide-after\":e.hideAfter,persistent:e.persistent}),{content:re(()=>[Z(\"div\",{class:U(e.ns.b())},[Z(\"div\",{class:U(e.ns.e(\"main\"))},[!e.hideIcon&&e.icon?(R(),fe(i,{key:0,class:U(e.ns.e(\"icon\")),style:Xe({color:e.iconColor})},{default:re(()=>[(R(),fe(Kt(e.icon)))]),_:1},8,[\"class\",\"style\"])):se(\"v-if\",!0),yt(\" \"+Me(e.title),1)],2),Z(\"div\",{class:U(e.ns.e(\"action\"))},[g(l,{size:\"small\",type:e.cancelButtonType,onClick:e.cancel},{default:re(()=>[yt(Me(e.finalCancelButtonText),1)]),_:1},8,[\"type\",\"onClick\"]),g(l,{size:\"small\",type:e.confirmButtonType,onClick:e.confirm},{default:re(()=>[yt(Me(e.finalConfirmButtonText),1)]),_:1},8,[\"type\",\"onClick\"])],2)],2)]),default:re(()=>[e.$slots.reference?Oe(e.$slots,\"reference\",{key:0}):se(\"v-if\",!0)]),_:3},16,[\"popper-class\",\"teleported\",\"hide-after\",\"persistent\"])}var Jde=Ae(Xde,[[\"render\",Zde],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popconfirm/src/popconfirm.vue\"]]);const Qde=xt(Jde),efe=Ze({trigger:qd.trigger,placement:Sp.placement,disabled:qd.disabled,visible:mr.visible,transition:mr.transition,popperOptions:Sp.popperOptions,tabindex:Sp.tabindex,appendToBody:{type:Boolean,default:void 0},content:mr.content,popperStyle:mr.popperStyle,popperClass:mr.popperClass,enterable:Ke(Te({},mr.enterable),{default:!0}),effect:Ke(Te({},mr.effect),{default:\"light\"}),teleported:mr.teleported,title:String,width:{type:[String,Number],default:150},offset:{type:Number,default:void 0},showAfter:{type:Number,default:0},hideAfter:{type:Number,default:200},autoClose:{type:Number,default:0},showArrow:{type:Boolean,default:!0},persistent:{type:Boolean,default:!0}}),tfe=[\"update:visible\",\"before-enter\",\"before-leave\",\"after-enter\",\"after-leave\"],iO=\"ElPopover\",nfe=G({name:iO,components:{ElTooltip:Ur},props:efe,emits:tfe,setup(e,{emit:t}){const n=De(\"popover\"),r=H(null),a=x(()=>{var y;return(y=A(r))==null?void 0:y.popperRef}),o=x(()=>wt(e.width)?e.width:`${e.width}px`),i=x(()=>[{width:o.value},e.popperStyle]),l=x(()=>[n.b(),e.popperClass,{[n.m(\"plain\")]:!!e.content}]),s=x(()=>e.transition===\"el-fade-in-linear\"),{compatTeleported:c}=Oc(iO,\"appendToBody\");return{compatTeleported:c,ns:n,kls:l,gpuAcceleration:s,style:i,tooltipRef:r,popperRef:a,hide:()=>{var y;(y=r.value)==null||y.hide()},beforeEnter:()=>{t(\"before-enter\")},beforeLeave:()=>{t(\"before-leave\")},afterEnter:()=>{t(\"after-enter\")},afterLeave:()=>{t(\"update:visible\",!1),t(\"after-leave\")}}}});function rfe(e,t,n,r,a,o){const i=we(\"el-tooltip\");return R(),fe(i,hn({ref:\"tooltipRef\"},e.$attrs,{trigger:e.trigger,placement:e.placement,disabled:e.disabled,visible:e.visible,transition:e.transition,\"popper-options\":e.popperOptions,tabindex:e.tabindex,\"append-to-body\":e.appendToBody,content:e.content,offset:e.offset,\"show-after\":e.showAfter,\"hide-after\":e.hideAfter,\"auto-close\":e.autoClose,\"show-arrow\":e.showArrow,\"aria-label\":e.title,effect:e.effect,enterable:e.enterable,\"popper-class\":e.kls,\"popper-style\":e.style,teleported:e.compatTeleported,persistent:e.persistent,\"gpu-acceleration\":e.gpuAcceleration,onBeforeShow:e.beforeEnter,onBeforeHide:e.beforeLeave,onShow:e.afterEnter,onHide:e.afterLeave}),{content:re(()=>[e.title?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"title\")),role:\"title\"},Me(e.title),3)):se(\"v-if\",!0),Oe(e.$slots,\"default\",{},()=>[yt(Me(e.content),1)])]),default:re(()=>[e.$slots.reference?Oe(e.$slots,\"reference\",{key:0}):se(\"v-if\",!0)]),_:3},16,[\"trigger\",\"placement\",\"disabled\",\"visible\",\"transition\",\"popper-options\",\"tabindex\",\"append-to-body\",\"content\",\"offset\",\"show-after\",\"hide-after\",\"auto-close\",\"show-arrow\",\"aria-label\",\"effect\",\"enterable\",\"popper-class\",\"popper-style\",\"teleported\",\"persistent\",\"gpu-acceleration\",\"onBeforeShow\",\"onBeforeHide\",\"onShow\",\"onHide\"])}var Cd=Ae(nfe,[[\"render\",rfe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/popover/src/index.vue\"]]);const lO=(e,t)=>{const n=t.arg||t.value,r=n==null?void 0:n.popperRef;r&&(r.triggerRef=e)};var F0={mounted(e,t){lO(e,t)},updated(e,t){lO(e,t)}};const afe=\"popover\";Cd.install=e=>{e.component(Cd.name,Cd)};F0.install=e=>{e.directive(afe,F0)};const R5=F0;Cd.directive=R5;const ofe=Cd,ife=ofe,lfe=R5,sfe=Ze({type:{type:String,default:\"line\",values:[\"line\",\"circle\",\"dashboard\"]},percentage:{type:Number,default:0,validator:e=>e>=0&&e<=100},status:{type:String,default:\"\",values:[\"\",\"success\",\"exception\",\"warning\"]},indeterminate:{type:Boolean,default:!1},duration:{type:Number,default:3},strokeWidth:{type:Number,default:6},strokeLinecap:{type:Le(String),default:\"round\"},textInside:{type:Boolean,default:!1},width:{type:Number,default:126},showText:{type:Boolean,default:!0},color:{type:Le([String,Array,Function]),default:\"\"},format:{type:Le(Function),default:e=>`${e}%`}}),ufe=G({name:\"ElProgress\",components:{ElIcon:ft,CircleCheck:mv,CircleClose:gi,Check:Wu,Close:Ma,WarningFilled:Wd},props:sfe,setup(e){const t=De(\"progress\"),n=x(()=>({width:`${e.percentage}%`,animationDuration:`${e.duration}s`,backgroundColor:y(e.percentage)})),r=x(()=>(e.strokeWidth/e.width*100).toFixed(1)),a=x(()=>e.type===\"circle\"||e.type===\"dashboard\"?Number.parseInt(`${50-Number.parseFloat(r.value)/2}`,10):0),o=x(()=>{const C=a.value,S=e.type===\"dashboard\";return`\n          M 50 50\n          m 0 ${S?\"\":\"-\"}${C}\n          a ${C} ${C} 0 1 1 0 ${S?\"-\":\"\"}${C*2}\n          a ${C} ${C} 0 1 1 0 ${S?\"\":\"-\"}${C*2}\n          `}),i=x(()=>2*Math.PI*a.value),l=x(()=>e.type===\"dashboard\"?.75:1),s=x(()=>`${-1*i.value*(1-l.value)/2}px`),c=x(()=>({strokeDasharray:`${i.value*l.value}px, ${i.value}px`,strokeDashoffset:s.value})),d=x(()=>({strokeDasharray:`${i.value*l.value*(e.percentage/100)}px, ${i.value}px`,strokeDashoffset:s.value,transition:\"stroke-dasharray 0.6s ease 0s, stroke 0.6s ease\"})),f=x(()=>{let C;if(e.color)C=y(e.percentage);else switch(e.status){case\"success\":C=\"#13ce66\";break;case\"exception\":C=\"#ff4949\";break;case\"warning\":C=\"#e6a23c\";break;default:C=\"#20a0ff\"}return C}),p=x(()=>e.status===\"warning\"?Wd:e.type===\"line\"?e.status===\"success\"?mv:gi:e.status===\"success\"?Wu:Ma),v=x(()=>e.type===\"line\"?12+e.strokeWidth*.4:e.width*.111111+2),m=x(()=>e.format(e.percentage)),y=C=>{var S;const{color:w}=e;if(typeof w==\"function\")return w(C);if(typeof w==\"string\")return w;{const k=100/w.length,O=w.map((T,_)=>typeof T==\"string\"?{color:T,percentage:(_+1)*k}:T).sort((T,_)=>T.percentage-_.percentage);for(const T of O)if(T.percentage>C)return T.color;return(S=O[O.length-1])==null?void 0:S.color}},b=x(()=>({percentage:e.percentage}));return{ns:t,barStyle:n,relativeStrokeWidth:r,radius:a,trackPath:o,perimeter:i,rate:l,strokeDashoffset:s,trailPathStyle:c,circlePathStyle:d,stroke:f,statusIcon:p,progressTextSize:v,content:m,slotData:b}}}),cfe=[\"aria-valuenow\"],dfe={viewBox:\"0 0 100 100\"},ffe=[\"d\",\"stroke-width\"],hfe=[\"d\",\"stroke\",\"stroke-linecap\",\"stroke-width\"],pfe={key:0};function vfe(e,t,n,r,a,o){const i=we(\"el-icon\");return R(),X(\"div\",{class:U([e.ns.b(),e.ns.m(e.type),e.ns.is(e.status),{[e.ns.m(\"without-text\")]:!e.showText,[e.ns.m(\"text-inside\")]:e.textInside}]),role:\"progressbar\",\"aria-valuenow\":e.percentage,\"aria-valuemin\":\"0\",\"aria-valuemax\":\"100\"},[e.type===\"line\"?(R(),X(\"div\",{key:0,class:U(e.ns.b(\"bar\"))},[Z(\"div\",{class:U(e.ns.be(\"bar\",\"outer\")),style:Xe({height:`${e.strokeWidth}px`})},[Z(\"div\",{class:U([e.ns.be(\"bar\",\"inner\"),{[e.ns.bem(\"bar\",\"inner\",\"indeterminate\")]:e.indeterminate}]),style:Xe(e.barStyle)},[(e.showText||e.$slots.default)&&e.textInside?(R(),X(\"div\",{key:0,class:U(e.ns.be(\"bar\",\"innerText\"))},[Oe(e.$slots,\"default\",Za(ll(e.slotData)),()=>[Z(\"span\",null,Me(e.content),1)])],2)):se(\"v-if\",!0)],6)],6)],2)):(R(),X(\"div\",{key:1,class:U(e.ns.b(\"circle\")),style:Xe({height:`${e.width}px`,width:`${e.width}px`})},[(R(),X(\"svg\",dfe,[Z(\"path\",{class:U(e.ns.be(\"circle\",\"track\")),d:e.trackPath,stroke:\"var(--el-fill-color-light, #e5e9f2)\",\"stroke-width\":e.relativeStrokeWidth,fill:\"none\",style:Xe(e.trailPathStyle)},null,14,ffe),Z(\"path\",{class:U(e.ns.be(\"circle\",\"path\")),d:e.trackPath,stroke:e.stroke,fill:\"none\",\"stroke-linecap\":e.strokeLinecap,\"stroke-width\":e.percentage?e.relativeStrokeWidth:0,style:Xe(e.circlePathStyle)},null,14,hfe)]))],6)),(e.showText||e.$slots.default)&&!e.textInside?(R(),X(\"div\",{key:2,class:U(e.ns.e(\"text\")),style:Xe({fontSize:`${e.progressTextSize}px`})},[Oe(e.$slots,\"default\",Za(ll(e.slotData)),()=>[e.status?(R(),fe(i,{key:1},{default:re(()=>[(R(),fe(Kt(e.statusIcon)))]),_:1})):(R(),X(\"span\",pfe,Me(e.content),1))])],6)):se(\"v-if\",!0)],10,cfe)}var mfe=Ae(ufe,[[\"render\",vfe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/progress/src/progress.vue\"]]);const L5=xt(mfe),gfe=Ze({modelValue:{type:Number,default:0},lowThreshold:{type:Number,default:2},highThreshold:{type:Number,default:4},max:{type:Number,default:5},colors:{type:Le([Array,Object]),default:()=>xn([\"\",\"\",\"\"])},voidColor:{type:String,default:\"\"},disabledVoidColor:{type:String,default:\"\"},icons:{type:Le([Array,Object]),default:()=>[oh,oh,oh]},voidIcon:{type:wr,default:()=>mX},disabledVoidIcon:{type:wr,default:()=>oh},disabled:{type:Boolean,default:!1},allowHalf:{type:Boolean,default:!1},showText:{type:Boolean,default:!1},showScore:{type:Boolean,default:!1},textColor:{type:String,default:\"\"},texts:{type:Le(Array),default:()=>xn([\"Extremely bad\",\"Disappointed\",\"Fair\",\"Satisfied\",\"Surprise\"])},scoreTemplate:{type:String,default:\"{value}\"},size:{type:String,validator:va}}),yfe={change:e=>typeof e==\"number\",[Pt]:e=>typeof e==\"number\"},bfe=[\"aria-valuenow\",\"aria-valuetext\",\"aria-valuemax\"],Cfe=[\"onMousemove\",\"onClick\"],wfe={name:\"ElRate\"},Sfe=G(Ke(Te({},wfe),{props:gfe,emits:yfe,setup(e,{expose:t,emit:n}){const r=e;function a(N,D){const z=E=>zt(E),B=Object.keys(D).map(E=>+E).filter(E=>{const K=D[E];return(z(K)?K.excluded:!1)?N<E:N<=E}).sort((E,K)=>E-K),M=D[B[0]];return z(M)&&M.value||M}const o=ve(ga,void 0),i=Gn(),l=De(\"rate\"),s=H(r.modelValue),c=H(-1),d=H(!0),f=x(()=>[l.b(),l.m(i.value)]),p=x(()=>r.disabled||(o==null?void 0:o.disabled)),v=x(()=>({\"--el-rate-void-color\":r.voidColor,\"--el-rate-disabled-void-color\":r.disabledVoidColor,\"--el-rate-fill-color\":C.value})),m=x(()=>{let N=\"\";return r.showScore?N=r.scoreTemplate.replace(/\\{\\s*value\\s*\\}/,p.value?`${r.modelValue}`:`${s.value}`):r.showText&&(N=r.texts[Math.ceil(s.value)-1]),N}),y=x(()=>r.modelValue*100-Math.floor(r.modelValue)*100),b=x(()=>pt(r.colors)?{[r.lowThreshold]:r.colors[0],[r.highThreshold]:{value:r.colors[1],excluded:!0},[r.max]:r.colors[2]}:r.colors),C=x(()=>{const N=a(s.value,b.value);return zt(N)?\"\":N}),S=x(()=>{let N=\"\";return p.value?N=`${y.value}%`:r.allowHalf&&(N=\"50%\"),{color:C.value,width:N}}),w=x(()=>pt(r.icons)?{[r.lowThreshold]:r.icons[0],[r.highThreshold]:{value:r.icons[1],excluded:!0},[r.max]:r.icons[2]}:r.icons),k=x(()=>a(r.modelValue,w.value)),$=x(()=>p.value?r.disabledVoidIcon:r.voidIcon),O=x(()=>a(s.value,w.value)),T=x(()=>{const N=Array.from({length:r.max}),D=s.value;return N.fill(O.value,0,D),N.fill($.value,D,r.max),N});function _(N){const D=p.value&&y.value>0&&N-1<r.modelValue&&N>r.modelValue,z=r.allowHalf&&d.value&&N-.5<=s.value&&N>s.value;return D||z}function I(N){p.value||(r.allowHalf&&d.value?(n(Pt,s.value),r.modelValue!==s.value&&n(\"change\",s.value)):(n(Pt,N),r.modelValue!==N&&n(\"change\",N)))}function L(N){if(p.value)return;let D=s.value;const z=N.code;return z===Ge.up||z===Ge.right?(r.allowHalf?D+=.5:D+=1,N.stopPropagation(),N.preventDefault()):(z===Ge.left||z===Ge.down)&&(r.allowHalf?D-=.5:D-=1,N.stopPropagation(),N.preventDefault()),D=D<0?0:D,D=D>r.max?r.max:D,n(Pt,D),n(\"change\",D),D}function j(N,D){if(!p.value){if(r.allowHalf){let z=D.target;to(z,l.e(\"item\"))&&(z=z.querySelector(`.${l.e(\"icon\")}`)),(z.clientWidth===0||to(z,l.e(\"decimal\")))&&(z=z.parentNode),d.value=D.offsetX*2<=z.clientWidth,s.value=d.value?N-.5:N}else s.value=N;c.value=N}}function F(){p.value||(r.allowHalf&&(d.value=r.modelValue!==Math.floor(r.modelValue)),s.value=r.modelValue,c.value=-1)}return ce(()=>r.modelValue,N=>{s.value=N,d.value=r.modelValue!==Math.floor(r.modelValue)}),r.modelValue||n(Pt,0),t({setCurrentValue:j,resetCurrentValue:F}),(N,D)=>(R(),X(\"div\",{class:U([A(f),A(l).is(\"disabled\",A(p))]),role:\"slider\",\"aria-valuenow\":s.value,\"aria-valuetext\":A(m),\"aria-valuemin\":\"0\",\"aria-valuemax\":N.max,tabindex:\"0\",style:Xe(A(v)),onKeydown:L},[(R(!0),X(Fe,null,Rt(N.max,(z,B)=>(R(),X(\"span\",{key:B,class:U(A(l).e(\"item\")),onMousemove:M=>j(z,M),onMouseleave:F,onClick:M=>I(z)},[g(A(ft),{class:U([A(l).e(\"icon\"),{hover:c.value===z},A(l).is(\"active\",z<=s.value)])},{default:re(()=>[_(z)?se(\"v-if\",!0):(R(),fe(Kt(A(T)[z-1]),{key:0})),_(z)?(R(),fe(A(ft),{key:1,style:Xe(A(S)),class:U([A(l).e(\"icon\"),A(l).e(\"decimal\")])},{default:re(()=>[(R(),fe(Kt(A(k))))]),_:1},8,[\"style\",\"class\"])):se(\"v-if\",!0)]),_:2},1032,[\"class\"])],42,Cfe))),128)),N.showText||N.showScore?(R(),X(\"span\",{key:0,class:U(A(l).e(\"text\"))},Me(A(m)),3)):se(\"v-if\",!0)],46,bfe))}}));var kfe=Ae(Sfe,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/rate/src/rate.vue\"]]);const $fe=xt(kfe),vu={success:\"icon-success\",warning:\"icon-warning\",error:\"icon-error\",info:\"icon-info\"},sO={[vu.success]:AY,[vu.warning]:Wd,[vu.error]:RC,[vu.info]:LC},Ofe=Ze({title:{type:String,default:\"\"},subTitle:{type:String,default:\"\"},icon:{values:[\"success\",\"warning\",\"info\",\"error\"],default:\"info\"}}),uO=\"ElResult\",Pfe=G({name:uO,props:Ofe,setup(e,{slots:t}){const n=De(\"result\");Tf({scope:uO,type:\"Slot\",from:\"subTitle\",replacement:\"sub-title\",version:\"2.1.3\",ref:\"https://github.com/element-plus/element-plus/pull/6636/\"},x(()=>!!t.subTitle));const r=x(()=>{const a=e.icon,o=a&&vu[a]?vu[a]:\"icon-info\",i=sO[o]||sO[\"icon-info\"];return{class:o,component:i}});return{ns:n,resultIcon:r}}});function Tfe(e,t,n,r,a,o){return R(),X(\"div\",{class:U(e.ns.b())},[Z(\"div\",{class:U(e.ns.e(\"icon\"))},[Oe(e.$slots,\"icon\",{},()=>[e.resultIcon.component?(R(),fe(Kt(e.resultIcon.component),{key:0,class:U(e.resultIcon.class)},null,8,[\"class\"])):se(\"v-if\",!0)])],2),e.title||e.$slots.title?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"title\"))},[Oe(e.$slots,\"title\",{},()=>[Z(\"p\",null,Me(e.title),1)])],2)):se(\"v-if\",!0),e.subTitle||e.$slots[\"sub-title\"]?(R(),X(\"div\",{key:1,class:U(e.ns.e(\"subtitle\"))},[Oe(e.$slots,\"sub-title\",{},()=>[Z(\"p\",null,Me(e.subTitle),1)])],2)):se(\"v-if\",!0),e.$slots.extra?(R(),X(\"div\",{key:2,class:U(e.ns.e(\"extra\"))},[Oe(e.$slots,\"extra\")],2)):se(\"v-if\",!0)],2)}var xfe=Ae(Pfe,[[\"render\",Tfe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/result/src/result.vue\"]]);const _fe=xt(xfe),Efe=Ze({tag:{type:String,default:\"div\"},gutter:{type:Number,default:0},justify:{type:String,values:[\"start\",\"center\",\"end\",\"space-around\",\"space-between\",\"space-evenly\"],default:\"start\"},align:{type:String,values:[\"top\",\"middle\",\"bottom\"],default:\"top\"}}),Mfe=G({name:\"ElRow\",props:Efe,setup(e,{slots:t}){const n=De(\"row\"),r=x(()=>e.gutter);ot(xE,{gutter:r});const a=x(()=>{const o={marginLeft:\"\",marginRight:\"\"};return e.gutter&&(o.marginLeft=`-${e.gutter/2}px`,o.marginRight=o.marginLeft),o});return()=>g(e.tag,{class:[n.b(),n.is(`justify-${e.justify}`,e.justify!==\"start\"),n.is(`align-${e.align}`,e.align!==\"top\")],style:a.value},{default:()=>{var o;return[(o=t.default)==null?void 0:o.call(t)]}})}}),Ife=xt(Mfe);var cO=Number.isNaN||function(t){return typeof t==\"number\"&&t!==t};function Nfe(e,t){return!!(e===t||cO(e)&&cO(t))}function Afe(e,t){if(e.length!==t.length)return!1;for(var n=0;n<e.length;n++)if(!Nfe(e[n],t[n]))return!1;return!0}function Dfe(e,t){t===void 0&&(t=Afe);var n=null;function r(){for(var a=[],o=0;o<arguments.length;o++)a[o]=arguments[o];if(n&&n.lastThis===this&&t(a,n.lastArgs))return n.lastResult;var i=e.apply(this,a);return n={lastResult:i,lastArgs:a,lastThis:this},i}return r.clear=function(){n=null},r}const Rfe=()=>{const t=$t().proxy.$props;return x(()=>{const n=(r,a,o)=>({});return t.perfMode?Im(n):Dfe(n)})},Lfe=50,dO=\"item-rendered\",fO=\"scroll\",F5=\"forward\",B5=\"backward\",Zd=\"auto\",V5=\"smart\",z5=\"start\",wv=\"center\",H5=\"end\",Qu=\"horizontal\",mw=\"vertical\",Ffe=\"ltr\",$p=\"rtl\",j5=\"negative\",Bfe=\"positive-ascending\",K5=\"positive-descending\",Vfe={[Qu]:\"left\",[mw]:\"top\"},zfe=20,Hfe={[Qu]:\"deltaX\",[mw]:\"deltaY\"},jfe=({atEndEdge:e,atStartEdge:t,layout:n},r)=>{let a,o=0;const i=s=>s<0&&t.value||s>0&&e.value;return{hasReachedEdge:i,onWheel:s=>{bE(a);const c=s[Hfe[n.value]];i(o)&&i(o+c)||(o+=c,BC()||s.preventDefault(),a=yE(()=>{r(o),o=0}))}}},B0=ho({type:Le([Number,Function]),required:!0}),V0=ho({type:Number}),z0=ho({type:Number,default:2}),Kfe=ho({type:String,values:[\"ltr\",\"rtl\"],default:\"ltr\"}),H0=ho({type:Number,default:0}),Sv=ho({type:Number,required:!0}),W5=ho({type:String,values:[\"horizontal\",\"vertical\"],default:mw}),U5=Ze({className:{type:String,default:\"\"},containerElement:{type:Le([String,Object]),default:\"div\"},data:{type:Le(Array),default:()=>xn([])},direction:Kfe,height:{type:[String,Number],required:!0},innerElement:{type:[String,Object],default:\"div\"},style:{type:Le([Object,String,Array])},useIsScrolling:{type:Boolean,default:!1},width:{type:[Number,String],required:!1},perfMode:{type:Boolean,default:!0},scrollbarAlwaysOn:{type:Boolean,default:!1}}),Wfe=Ze(Te({cache:z0,estimatedItemSize:V0,layout:W5,initScrollOffset:H0,total:Sv,itemSize:B0},U5));Ze(Te({columnCache:z0,columnWidth:B0,estimatedColumnWidth:V0,estimatedRowHeight:V0,initScrollLeft:H0,initScrollTop:H0,rowCache:z0,rowHeight:B0,totalColumn:Sv,totalRow:Sv},U5));const Ufe=Ze({layout:W5,total:Sv,ratio:{type:Number,required:!0},clientSize:{type:Number,required:!0},scrollFrom:{type:Number,required:!0},visible:Boolean}),ky=(e,t)=>e<t?F5:B5,Jd=e=>e===Ffe||e===$p||e===Qu;let Vs=null;function hO(e=!1){if(Vs===null||e){const t=document.createElement(\"div\"),n=t.style;n.width=\"50px\",n.height=\"50px\",n.overflow=\"scroll\",n.direction=\"rtl\";const r=document.createElement(\"div\"),a=r.style;return a.width=\"100px\",a.height=\"100px\",t.appendChild(r),document.body.appendChild(t),t.scrollLeft>0?Vs=K5:(t.scrollLeft=1,t.scrollLeft===0?Vs=j5:Vs=Bfe),document.body.removeChild(t),Vs}return Vs}function Yfe({move:e,size:t,bar:n},r){const a={},o=`translate${n.axis}(${e}px)`;return a[n.size]=t,a.transform=o,a.msTransform=o,a.webkitTransform=o,r===\"horizontal\"?a.height=\"100%\":a.width=\"100%\",a}const qfe=G({name:\"ElVirtualScrollBar\",props:Ufe,emits:[\"scroll\",\"start-move\",\"stop-move\"],setup(e,{emit:t}){const r=H(),a=H();let o=null,i=null;const l=bt({isDragging:!1,traveled:0}),s=x(()=>XE[e.layout]),c=x(()=>e.clientSize-4),d=x(()=>({position:\"absolute\",width:Qu===e.layout?`${c.value}px`:\"6px\",height:Qu===e.layout?\"6px\":`${c.value}px`,[Vfe[e.layout]]:\"2px\",right:\"2px\",bottom:\"2px\",borderRadius:\"4px\"})),f=x(()=>{const $=e.ratio,O=e.clientSize;if($>=100)return Number.POSITIVE_INFINITY;if($>=50)return $*O/100;const T=O/3;return Math.floor(Math.min(Math.max($*O,zfe),T))}),p=x(()=>{if(!Number.isFinite(f.value))return{display:\"none\"};const $=`${f.value}px`;return Yfe({bar:s.value,size:$,move:l.traveled},e.layout)}),v=x(()=>Math.floor(e.clientSize-f.value-4)),m=()=>{gn(window,\"mousemove\",S),gn(window,\"mouseup\",C);const $=A(a);!$||(i=document.onselectstart,document.onselectstart=()=>!1,gn($,\"touchmove\",S),gn($,\"touchend\",C))},y=()=>{Bn(window,\"mousemove\",S),Bn(window,\"mouseup\",C),document.onselectstart=i,i=null;const $=A(a);!$||(Bn($,\"touchmove\",S),Bn($,\"touchend\",C))},b=$=>{$.stopImmediatePropagation(),!($.ctrlKey||[1,2].includes($.button))&&(l.isDragging=!0,l[s.value.axis]=$.currentTarget[s.value.offset]-($[s.value.client]-$.currentTarget.getBoundingClientRect()[s.value.direction]),t(\"start-move\"),m())},C=()=>{l.isDragging=!1,l[s.value.axis]=0,t(\"stop-move\"),y()},S=$=>{const{isDragging:O}=l;if(!O||!a.value||!r.value)return;const T=l[s.value.axis];if(!T)return;bE(o);const _=(r.value.getBoundingClientRect()[s.value.direction]-$[s.value.client])*-1,I=a.value[s.value.offset]-T,L=_-I;o=yE(()=>{l.traveled=Math.max(0,Math.min(L,v.value)),t(\"scroll\",L,v.value)})},w=$=>{const O=Math.abs($.target.getBoundingClientRect()[s.value.direction]-$[s.value.client]),T=a.value[s.value.offset]/2,_=O-T;l.traveled=Math.max(0,Math.min(_,v.value)),t(\"scroll\",_,v.value)},k=$=>$.preventDefault();return ce(()=>e.scrollFrom,$=>{l.isDragging||(l.traveled=Math.ceil($*v.value))}),et(()=>{!Bt||(gn(r.value,\"touchstart\",k),gn(a.value,\"touchstart\",b))}),Lt(()=>{Bn(r.value,\"touchstart\",k),y()}),()=>qe(\"div\",{role:\"presentation\",ref:r,class:\"el-virtual-scrollbar\",style:d.value,onMousedown:dt(w,[\"stop\",\"prevent\"])},qe(\"div\",{ref:a,class:\"el-scrollbar__thumb\",style:p.value,onMousedown:b},[]))}}),Y5=({name:e,getOffset:t,getItemSize:n,getItemOffset:r,getEstimatedTotalSize:a,getStartIndexForOffset:o,getStopIndexForStartIndex:i,initCache:l,clearCache:s,validateProps:c})=>G({name:e!=null?e:\"ElVirtualList\",props:Wfe,emits:[dO,fO],setup(d,{emit:f,expose:p}){c(d);const v=$t(),m=H(l(d,v)),y=Rfe(),b=H(),C=H(),S=H(),w=H({isScrolling:!1,scrollDir:\"forward\",scrollOffset:Yt(d.initScrollOffset)?d.initScrollOffset:0,updateRequested:!1,isScrollbarDragging:!1,scrollbarAlwaysOn:d.scrollbarAlwaysOn}),k=x(()=>{const{total:q,cache:J}=d,{isScrolling:ne,scrollDir:oe,scrollOffset:Q}=A(w);if(q===0)return[0,0,0,0];const ae=o(d,Q,A(m)),de=i(d,ae,Q,A(m)),be=!ne||oe===B5?Math.max(1,J):1,Ee=!ne||oe===F5?Math.max(1,J):1;return[Math.max(0,ae-be),Math.max(0,Math.min(q-1,de+Ee)),ae,de]}),$=x(()=>a(d,A(m))),O=x(()=>Jd(d.layout)),T=x(()=>[{position:\"relative\",[`overflow-${O.value?\"x\":\"y\"}`]:\"scroll\",WebkitOverflowScrolling:\"touch\",willChange:\"transform\"},{direction:d.direction,height:Yt(d.height)?`${d.height}px`:d.height,width:Yt(d.width)?`${d.width}px`:d.width},d.style]),_=x(()=>{const q=A($),J=A(O);return{height:J?\"100%\":`${q}px`,pointerEvents:A(w).isScrolling?\"none\":void 0,width:J?`${q}px`:\"100%\"}}),I=x(()=>O.value?d.width:d.height),{onWheel:L}=jfe({atStartEdge:x(()=>w.value.scrollOffset<=0),atEndEdge:x(()=>w.value.scrollOffset>=$.value),layout:x(()=>d.layout)},q=>{var J,ne;(ne=(J=S.value).onMouseUp)==null||ne.call(J),B(Math.min(w.value.scrollOffset+q,$.value-I.value))}),j=()=>{const{total:q}=d;if(q>0){const[Q,ae,de,be]=A(k);f(dO,Q,ae,de,be)}const{scrollDir:J,scrollOffset:ne,updateRequested:oe}=A(w);f(fO,J,ne,oe)},F=q=>{const{clientHeight:J,scrollHeight:ne,scrollTop:oe}=q.currentTarget,Q=A(w);if(Q.scrollOffset===oe)return;const ae=Math.max(0,Math.min(oe,ne-J));w.value=Ke(Te({},Q),{isScrolling:!0,scrollDir:ky(Q.scrollOffset,ae),scrollOffset:ae,updateRequested:!1}),Ne(K)},N=q=>{const{clientWidth:J,scrollLeft:ne,scrollWidth:oe}=q.currentTarget,Q=A(w);if(Q.scrollOffset===ne)return;const{direction:ae}=d;let de=ne;if(ae===$p)switch(hO()){case j5:{de=-ne;break}case K5:{de=oe-J-ne;break}}de=Math.max(0,Math.min(de,oe-J)),w.value=Ke(Te({},Q),{isScrolling:!0,scrollDir:ky(Q.scrollOffset,de),scrollOffset:de,updateRequested:!1}),Ne(K)},D=q=>{A(O)?N(q):F(q),j()},z=(q,J)=>{const ne=($.value-I.value)/J*q;B(Math.min($.value-I.value,ne))},B=q=>{q=Math.max(q,0),q!==A(w).scrollOffset&&(w.value=Ke(Te({},A(w)),{scrollOffset:q,scrollDir:ky(A(w).scrollOffset,q),updateRequested:!0}),Ne(K))},M=(q,J=Zd)=>{const{scrollOffset:ne}=A(w);q=Math.max(0,Math.min(q,d.total-1)),B(t(d,q,J,ne,A(m)))},E=q=>{const{direction:J,itemSize:ne,layout:oe}=d,Q=y.value(s&&ne,s&&oe,s&&J);let ae;if(Mt(Q,String(q)))ae=Q[q];else{const de=r(d,q,A(m)),be=n(d,q,A(m)),Ee=A(O),Pe=J===$p,Be=Ee?de:0;Q[q]=ae={position:\"absolute\",left:Pe?void 0:`${Be}px`,right:Pe?`${Be}px`:void 0,top:Ee?0:`${de}px`,height:Ee?\"100%\":`${be}px`,width:Ee?`${be}px`:\"100%\"}}return ae},K=()=>{w.value.isScrolling=!1,Ne(()=>{y.value(-1,null,null)})},W=()=>{const q=b.value;q&&(q.scrollTop=0)};et(()=>{if(!Bt)return;const{initScrollOffset:q}=d,J=A(b);Yt(q)&&J&&(A(O)?J.scrollLeft=q:J.scrollTop=q),j()}),ur(()=>{const{direction:q,layout:J}=d,{scrollOffset:ne,updateRequested:oe}=A(w),Q=A(b);if(oe&&Q)if(J===Qu)if(q===$p)switch(hO()){case\"negative\":{Q.scrollLeft=-ne;break}case\"positive-ascending\":{Q.scrollLeft=ne;break}default:{const{clientWidth:ae,scrollWidth:de}=Q;Q.scrollLeft=de-ae-ne;break}}else Q.scrollLeft=ne;else Q.scrollTop=ne});const Y={clientSize:I,estimatedTotalSize:$,windowStyle:T,windowRef:b,innerRef:C,innerStyle:_,itemsToRender:k,scrollbarRef:S,states:w,getItemStyle:E,onScroll:D,onScrollbarScroll:z,onWheel:L,scrollTo:B,scrollToItem:M,resetScrollTop:W};return p({windowRef:b,innerRef:C,getItemStyleCache:y,scrollTo:B,scrollToItem:M,resetScrollTop:W,states:w}),Y},render(d){var f;const{$slots:p,className:v,clientSize:m,containerElement:y,data:b,getItemStyle:C,innerElement:S,itemsToRender:w,innerStyle:k,layout:$,total:O,onScroll:T,onScrollbarScroll:_,onWheel:I,states:L,useIsScrolling:j,windowStyle:F}=d,[N,D]=w,z=Kt(y),B=Kt(S),M=[];if(O>0)for(let Y=N;Y<=D;Y++)M.push((f=p.default)==null?void 0:f.call(p,{data:b,key:Y,index:Y,isScrolling:j?L.isScrolling:void 0,style:C(Y)}));const E=[qe(B,{style:k,ref:\"innerRef\"},wt(B)?M:{default:()=>M})],K=qe(qfe,{ref:\"scrollbarRef\",clientSize:m,layout:$,onScroll:_,ratio:m*100/this.estimatedTotalSize,scrollFrom:L.scrollOffset/(this.estimatedTotalSize-m),total:O}),W=qe(z,{class:[\"el-vl__window\",v],style:F,onScroll:T,onWheel:I,ref:\"windowRef\",key:0},wt(z)?[E]:{default:()=>[E]});return qe(\"div\",{key:0,class:[\"el-vl__wrapper\",L.scrollbarAlwaysOn?\"always-on\":\"\"]},[W,K])}}),q5=Y5({name:\"ElFixedSizeList\",getItemOffset:({itemSize:e},t)=>t*e,getItemSize:({itemSize:e})=>e,getEstimatedTotalSize:({total:e,itemSize:t})=>t*e,getOffset:({height:e,total:t,itemSize:n,layout:r,width:a},o,i,l)=>{const s=Jd(r)?a:e,c=Math.max(0,t*n-s),d=Math.min(c,o*n),f=Math.max(0,(o+1)*n-s);switch(i===V5&&(l>=f-s&&l<=d+s?i=Zd:i=wv),i){case z5:return d;case H5:return f;case wv:{const p=Math.round(f+(d-f)/2);return p<Math.ceil(s/2)?0:p>c+Math.floor(s/2)?c:p}case Zd:default:return l>=f&&l<=d?l:l<f?f:d}},getStartIndexForOffset:({total:e,itemSize:t},n)=>Math.max(0,Math.min(e-1,Math.floor(n/t))),getStopIndexForStartIndex:({height:e,total:t,itemSize:n,layout:r,width:a},o,i)=>{const l=o*n,s=Jd(r)?a:e,c=Math.ceil((s+i-l)/n);return Math.max(0,Math.min(t-1,o+c-1))},initCache(){},clearCache:!0,validateProps(){}}),mu=(e,t,n)=>{const{itemSize:r}=e,{items:a,lastVisitedIndex:o}=n;if(t>o){let i=0;if(o>=0){const l=a[o];i=l.offset+l.size}for(let l=o+1;l<=t;l++){const s=r(l);a[l]={offset:i,size:s},i+=s}n.lastVisitedIndex=t}return a[t]},Gfe=(e,t,n)=>{const{items:r,lastVisitedIndex:a}=t;return(a>0?r[a].offset:0)>=n?G5(e,t,0,a,n):Xfe(e,t,Math.max(0,a),n)},G5=(e,t,n,r,a)=>{for(;n<=r;){const o=n+Math.floor((r-n)/2),i=mu(e,o,t).offset;if(i===a)return o;i<a?n=o+1:i>a&&(r=o-1)}return Math.max(0,n-1)},Xfe=(e,t,n,r)=>{const{total:a}=e;let o=1;for(;n<a&&mu(e,n,t).offset<r;)n+=o,o*=2;return G5(e,t,Math.floor(n/2),Math.min(n,a-1),r)},pO=({total:e},{items:t,estimatedItemSize:n,lastVisitedIndex:r})=>{let a=0;if(r>=e&&(r=e-1),r>=0){const l=t[r];a=l.offset+l.size}const i=(e-r-1)*n;return a+i},Zfe=Y5({name:\"ElDynamicSizeList\",getItemOffset:(e,t,n)=>mu(e,t,n).offset,getItemSize:(e,t,{items:n})=>n[t].size,getEstimatedTotalSize:pO,getOffset:(e,t,n,r,a)=>{const{height:o,layout:i,width:l}=e,s=Jd(i)?l:o,c=mu(e,t,a),d=pO(e,a),f=Math.max(0,Math.min(d-s,c.offset)),p=Math.max(0,c.offset-s+c.size);switch(n===V5&&(r>=p-s&&r<=f+s?n=Zd:n=wv),n){case z5:return f;case H5:return p;case wv:return Math.round(p+(f-p)/2);case Zd:default:return r>=p&&r<=f?r:r<p?p:f}},getStartIndexForOffset:(e,t,n)=>Gfe(e,n,t),getStopIndexForStartIndex:(e,t,n,r)=>{const{height:a,total:o,layout:i,width:l}=e,s=Jd(i)?l:a,c=mu(e,t,r),d=n+s;let f=c.offset+c.size,p=t;for(;p<o-1&&f<d;)p++,f+=mu(e,p,r).size;return p},initCache({estimatedItemSize:e=Lfe},t){const n={items:{},estimatedItemSize:e,lastVisitedIndex:-1};return n.clearCacheAfterIndex=(r,a=!0)=>{var o,i;n.lastVisitedIndex=Math.min(n.lastVisitedIndex,r-1),(o=t.exposed)==null||o.getItemStyleCache(-1),a&&((i=t.proxy)==null||i.$forceUpdate())},n},clearCache:!1,validateProps:({itemSize:e})=>{}}),Jfe=G({props:{item:{type:Object,required:!0},style:Object,height:Number},setup(){return{ns:De(\"select\")}}});function Qfe(e,t,n,r,a,o){return e.item.isTitle?(R(),X(\"div\",{key:0,class:U(e.ns.be(\"group\",\"title\")),style:Xe([e.style,{lineHeight:`${e.height}px`}])},Me(e.item.label),7)):(R(),X(\"div\",{key:1,class:U(e.ns.be(\"group\",\"split\")),style:Xe(e.style)},[Z(\"span\",{class:U(e.ns.be(\"group\",\"split-dash\")),style:Xe({top:`${e.height/2}px`})},null,6)],6))}var ehe=Ae(Jfe,[[\"render\",Qfe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select-v2/src/group-item.vue\"]]);function the(e,{emit:t}){return{hoverItem:()=>{e.disabled||t(\"hover\",e.index)},selectOptionClick:()=>{e.disabled||t(\"select\",e.item,e.index)}}}const nhe={allowCreate:Boolean,autocomplete:{type:String,default:\"none\"},automaticDropdown:Boolean,clearable:Boolean,clearIcon:{type:[String,Object],default:gi},effect:{type:String,default:\"light\"},collapseTags:Boolean,collapseTagsTooltip:{type:Boolean,default:!1},defaultFirstOption:Boolean,disabled:Boolean,estimatedOptionHeight:{type:Number,default:void 0},filterable:Boolean,filterMethod:Function,height:{type:Number,default:170},itemHeight:{type:Number,default:34},id:String,loading:Boolean,loadingText:String,label:String,modelValue:[Array,String,Number,Boolean,Object],multiple:Boolean,multipleLimit:{type:Number,default:0},name:String,noDataText:String,noMatchText:String,remoteMethod:Function,reserveKeyword:{type:Boolean,default:!0},options:{type:Array,required:!0},placeholder:{type:String},popperAppendToBody:{type:Boolean,default:void 0},teleported:mr.teleported,persistent:{type:Boolean,default:!0},popperClass:{type:String,default:\"\"},popperOptions:{type:Object,default:()=>({})},remote:Boolean,size:{type:String,validator:va},valueKey:{type:String,default:\"value\"},scrollbarAlwaysOn:{type:Boolean,default:!1}},rhe={data:Array,disabled:Boolean,hovering:Boolean,item:Object,index:Number,style:Object,selected:Boolean,created:Boolean},ahe=G({props:rhe,emits:[\"select\",\"hover\"],setup(e,{emit:t}){const n=De(\"select\"),{hoverItem:r,selectOptionClick:a}=the(e,{emit:t});return{ns:n,hoverItem:r,selectOptionClick:a}}}),ohe=[\"aria-selected\"];function ihe(e,t,n,r,a,o){return R(),X(\"li\",{\"aria-selected\":e.selected,style:Xe(e.style),class:U([e.ns.be(\"dropdown\",\"option-item\"),e.ns.is(\"selected\",e.selected),e.ns.is(\"disabled\",e.disabled),e.ns.is(\"created\",e.created),{hover:e.hovering}]),onMouseenter:t[0]||(t[0]=(...i)=>e.hoverItem&&e.hoverItem(...i)),onClick:t[1]||(t[1]=dt((...i)=>e.selectOptionClick&&e.selectOptionClick(...i),[\"stop\"]))},[Oe(e.$slots,\"default\",{item:e.item,index:e.index,disabled:e.disabled},()=>[Z(\"span\",null,Me(e.item.label),1)])],46,ohe)}var lhe=Ae(ahe,[[\"render\",ihe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select-v2/src/option-item.vue\"]]);const X5=\"ElSelectV2Injection\",she=G({name:\"ElSelectDropdown\",props:{data:Array,hoveringIndex:Number,width:Number},setup(e){const t=ve(X5),n=De(\"select\"),r=H([]),a=H(null),o=x(()=>sa(t.props.estimatedOptionHeight)),i=x(()=>o.value?{itemSize:t.props.itemHeight}:{estimatedSize:t.props.estimatedOptionHeight,itemSize:m=>r.value[m]}),l=(m=[],y)=>{const{props:{valueKey:b}}=t;return zt(y)?m&&m.some(C=>vn(C,b)===vn(y,b)):m.includes(y)},s=(m,y)=>{if(zt(y)){const{valueKey:b}=t.props;return vn(m,b)===vn(y,b)}else return m===y};return{ns:n,select:t,listProps:i,listRef:a,isSized:o,isItemDisabled:(m,y)=>{const{disabled:b,multiple:C,multipleLimit:S}=t.props;return b||!y&&(C?S>0&&m.length>=S:!1)},isItemHovering:m=>e.hoveringIndex===m,isItemSelected:(m,y)=>{const{valueKey:b}=t.props;return t.props.multiple?l(m,vn(y,b)):s(m,vn(y,b))},scrollToItem:m=>{const y=a.value;y&&y.scrollToItem(m)},resetScrollTop:()=>{const m=a.value;m&&m.resetScrollTop()}}},render(e,t){var n;const{$slots:r,data:a,listProps:o,select:i,isSized:l,width:s,ns:c,isItemDisabled:d,isItemHovering:f,isItemSelected:p}=e,v=l?q5:Zfe,{props:m,onSelect:y,onHover:b,onKeyboardNavigate:C,onKeyboardSelect:S}=i,{height:w,modelValue:k,multiple:$}=m;if(a.length===0)return qe(\"div\",{class:c.b(\"dropdown\"),style:{width:`${s}px`}},(n=r.empty)==null?void 0:n.call(r));const O=re(_=>{const{index:I,data:L}=_,j=L[I];if(L[I].type===\"Group\")return qe(ehe,{item:j,style:_.style,height:l?o.itemSize:o.estimatedSize});const F=p(k,j),N=d(k,F);return qe(lhe,Ke(Te({},_),{selected:F,disabled:j.disabled||N,created:!!j.created,hovering:f(I),item:j,onSelect:y,onHover:b}),{default:re(D=>Oe(r,\"default\",D,()=>[qe(\"span\",j.label)]))})}),T=qe(v,Te({ref:\"listRef\",className:c.be(\"dropdown\",\"list\"),data:a,height:w,width:s,total:a.length,scrollbarAlwaysOn:m.scrollbarAlwaysOn,onKeydown:[t[1]||(t[1]=It(dt(()=>C(\"forward\"),[\"stop\",\"prevent\"]),[\"down\"])),t[2]||(t[2]=It(dt(()=>C(\"backward\"),[\"stop\",\"prevent\"]),[\"up\"])),t[3]||(t[3]=It(dt(S,[\"stop\",\"prevent\"]),[\"enter\"])),t[4]||(t[4]=It(dt(()=>i.expanded=!1,[\"stop\",\"prevent\"]),[\"esc\"])),t[5]||(t[5]=It(()=>i.expanded=!1,[\"tab\"]))]},o),{default:O});return qe(\"div\",{class:[c.b(\"dropdown\"),c.is(\"multiple\",$)]},[T])}});var uhe=Ae(she,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select-v2/src/select-dropdown.vue\"]]);function che(e,t){const n=H(0),r=H(null),a=x(()=>e.allowCreate&&e.filterable);function o(d){const f=p=>p.value===d;return e.options&&e.options.some(f)||t.createdOptions.some(f)}function i(d){!a.value||(e.multiple&&d.created?n.value++:r.value=d)}function l(d){if(a.value)if(d&&d.length>0&&!o(d)){const f={value:d,label:d,created:!0,disabled:!1};t.createdOptions.length>=n.value?t.createdOptions[n.value]=f:t.createdOptions.push(f)}else if(e.multiple)t.createdOptions.length=n.value;else{const f=r.value;t.createdOptions.length=0,f&&f.created&&t.createdOptions.push(f)}}function s(d){if(!a.value||!d||!d.created||d.created&&e.reserveKeyword&&t.inputValue===d.label)return;const f=t.createdOptions.findIndex(p=>p.value===d.value);~f&&(t.createdOptions.splice(f,1),n.value--)}function c(){a.value&&(t.createdOptions.length=0,n.value=0)}return{createNewOption:l,removeNewOption:s,selectNewOption:i,clearAllNewOption:c}}const dhe=e=>{const t=[];return e.forEach(n=>{pt(n.options)?(t.push({label:n.label,isTitle:!0,type:\"Group\"}),n.options.forEach(r=>{t.push(r)}),t.push({type:\"Group\"})):t.push(n)}),t};function fhe(e){const t=H(!1);return{handleCompositionStart:()=>{t.value=!0},handleCompositionUpdate:o=>{const i=o.target.value,l=i[i.length-1]||\"\";t.value=!zm(l)},handleCompositionEnd:o=>{t.value&&(t.value=!1,Ct(e)&&e(o))}}}const vO=\"\",mO=11,hhe={larget:51,default:42,small:33},phe=\"ElSelectV2\",vhe=(e,t)=>{const{t:n}=ln(),r=De(\"select-v2\"),a=De(\"input\"),{form:o,formItem:i}=$c(),{compatTeleported:l}=Oc(phe,\"popperAppendToBody\"),s=bt({inputValue:vO,displayInputValue:vO,calculatedWidth:0,cachedPlaceholder:\"\",cachedOptions:[],createdOptions:[],createdLabel:\"\",createdSelected:!1,currentPlaceholder:\"\",hoveringIndex:-1,comboBoxHovering:!1,isOnComposition:!1,isSilentBlur:!1,isComposing:!1,inputLength:20,selectWidth:200,initialInputHeight:0,previousQuery:null,previousValue:\"\",query:\"\",selectedLabel:\"\",softFocus:!1,tagInMultiLine:!1}),c=H(-1),d=H(-1),f=H(null),p=H(null),v=H(null),m=H(null),y=H(null),b=H(null),C=H(null),S=H(!1),w=x(()=>e.disabled||(o==null?void 0:o.disabled)),k=x(()=>{const Re=N.value.length*34;return Re>e.height?e.height:Re}),$=x(()=>e.modelValue!==void 0&&e.modelValue!==null&&e.modelValue!==\"\"),O=x(()=>{const Re=e.multiple?Array.isArray(e.modelValue)&&e.modelValue.length>0:$.value;return e.clearable&&!w.value&&s.comboBoxHovering&&Re}),T=x(()=>e.remote&&e.filterable?\"\":Of),_=x(()=>T.value&&r.is(\"reverse\",S.value)),I=x(()=>(i==null?void 0:i.validateState)||\"\"),L=x(()=>hE[I.value]),j=x(()=>e.remote?300:0),F=x(()=>{const Re=N.value;return e.loading?e.loadingText||n(\"el.select.loading\"):e.remote&&s.inputValue===\"\"&&Re.length===0?!1:e.filterable&&s.inputValue&&Re.length>0?e.noMatchText||n(\"el.select.noMatch\"):Re.length===0?e.noDataText||n(\"el.select.noData\"):null}),N=x(()=>{const Re=ut=>{const Vt=s.inputValue;return Vt?ut.label.includes(Vt):!0};return e.loading?[]:dhe(e.options.concat(s.createdOptions).map(ut=>{if(pt(ut.options)){const Vt=ut.options.filter(Re);if(Vt.length>0)return Ke(Te({},ut),{options:Vt})}else if(e.remote||Re(ut))return ut;return null}).filter(ut=>ut!==null))}),D=x(()=>N.value.every(Re=>Re.disabled)),z=Gn(),B=x(()=>z.value===\"small\"?\"small\":\"default\"),M=x(()=>{const Re=b.value,ut=B.value||\"default\",Vt=Re?Number.parseInt(getComputedStyle(Re).paddingLeft):0,it=Re?Number.parseInt(getComputedStyle(Re).paddingRight):0;return s.selectWidth-it-Vt-hhe[ut]}),E=()=>{var Re,ut,Vt;d.value=((Vt=(ut=(Re=y.value)==null?void 0:Re.getBoundingClientRect)==null?void 0:ut.call(Re))==null?void 0:Vt.width)||200},K=x(()=>({width:`${s.calculatedWidth===0?mO:Math.ceil(s.calculatedWidth)+mO}px`})),W=x(()=>pt(e.modelValue)?e.modelValue.length===0&&!s.displayInputValue:e.filterable?s.displayInputValue.length===0:!0),Y=x(()=>{const Re=e.placeholder||n(\"el.select.placeholder\");return e.multiple?Re:s.selectedLabel||Re}),q=x(()=>{var Re,ut;return(ut=(Re=m.value)==null?void 0:Re.popperRef)==null?void 0:ut.contentRef}),J=x(()=>{if(e.multiple){const Re=e.modelValue.length;if(e.modelValue.length>0)return N.value.findIndex(ut=>ut.value===e.modelValue[Re-1])}else if(e.modelValue)return N.value.findIndex(Re=>Re.value===e.modelValue);return-1}),ne=x(()=>S.value&&F.value!==!1),{createNewOption:oe,removeNewOption:Q,selectNewOption:ae,clearAllNewOption:de}=che(e,s),{handleCompositionStart:be,handleCompositionUpdate:Ee,handleCompositionEnd:Pe}=fhe(Re=>Mn(Re)),Be=()=>{var Re,ut,Vt;(ut=(Re=p.value).focus)==null||ut.call(Re),(Vt=m.value)==null||Vt.updatePopper()},te=()=>{if(!e.automaticDropdown&&!w.value)return s.isComposing&&(s.softFocus=!0),Ne(()=>{var Re,ut;S.value=!S.value,(ut=(Re=p.value)==null?void 0:Re.focus)==null||ut.call(Re)})},ie=()=>(e.filterable&&s.inputValue!==s.selectedLabel&&(s.query=s.selectedLabel),ke(s.inputValue),Ne(()=>{oe(s.inputValue)})),ge=Yn(ie,j.value),ke=Re=>{s.previousQuery!==Re&&(s.previousQuery=Re,e.filterable&&Ct(e.filterMethod)?e.filterMethod(Re):e.filterable&&e.remote&&Ct(e.remoteMethod)&&e.remoteMethod(Re))},xe=Re=>{er(e.modelValue,Re)||t(ir,Re)},Ie=Re=>{t(Pt,Re),xe(Re),s.previousValue=Re.toString()},ye=(Re=[],ut)=>{if(!zt(ut))return Re.indexOf(ut);const Vt=e.valueKey;let it=-1;return Re.some((ct,Nt)=>vn(ct,Vt)===vn(ut,Vt)?(it=Nt,!0):!1),it},pe=Re=>zt(Re)?vn(Re,e.valueKey):Re,ue=Re=>zt(Re)?Re.label:Re,Ce=()=>{if(!(e.collapseTags&&!e.filterable))return Ne(()=>{var Re,ut;if(!p.value)return;const Vt=b.value;y.value.height=Vt.offsetHeight,S.value&&F.value!==!1&&((ut=(Re=m.value)==null?void 0:Re.updatePopper)==null||ut.call(Re))})},je=()=>{var Re,ut;if(ee(),E(),(ut=(Re=m.value)==null?void 0:Re.updatePopper)==null||ut.call(Re),e.multiple)return Ce()},ee=()=>{const Re=b.value;Re&&(s.selectWidth=Re.getBoundingClientRect().width)},me=(Re,ut,Vt=!0)=>{var it,ct;if(e.multiple){let Nt=e.modelValue.slice();const sn=ye(Nt,pe(Re));sn>-1?(Nt=[...Nt.slice(0,sn),...Nt.slice(sn+1)],s.cachedOptions.splice(sn,1),Q(Re)):(e.multipleLimit<=0||Nt.length<e.multipleLimit)&&(Nt=[...Nt,pe(Re)],s.cachedOptions.push(Re),ae(Re),Ut(ut)),Ie(Nt),Re.created&&(s.query=\"\",ke(\"\"),s.inputLength=20),e.filterable&&!e.reserveKeyword&&((ct=(it=p.value).focus)==null||ct.call(it),Ve(\"\")),e.filterable&&(s.calculatedWidth=C.value.getBoundingClientRect().width),Ce(),Jt()}else c.value=ut,s.selectedLabel=Re.label,Ie(pe(Re)),S.value=!1,s.isComposing=!1,s.isSilentBlur=Vt,ae(Re),Re.created||de(),Ut(ut)},He=(Re,ut)=>{const{valueKey:Vt}=e,it=e.modelValue.indexOf(vn(ut,Vt));if(it>-1&&!w.value){const ct=[...e.modelValue.slice(0,it),...e.modelValue.slice(it+1)];return s.cachedOptions.splice(it,1),Ie(ct),t(\"remove-tag\",vn(ut,Vt)),s.softFocus=!0,Q(ut),Ne(Be)}Re.stopPropagation()},lt=Re=>{const ut=s.isComposing;s.isComposing=!0,s.softFocus?s.softFocus=!1:ut||t(\"focus\",Re)},Ye=()=>(s.softFocus=!1,Ne(()=>{var Re,ut;(ut=(Re=p.value)==null?void 0:Re.blur)==null||ut.call(Re),C.value&&(s.calculatedWidth=C.value.getBoundingClientRect().width),s.isSilentBlur?s.isSilentBlur=!1:s.isComposing&&t(\"blur\"),s.isComposing=!1})),he=()=>{s.displayInputValue.length>0?Ve(\"\"):S.value=!1},_e=Re=>{if(s.displayInputValue.length===0){Re.preventDefault();const ut=e.modelValue.slice();ut.pop(),Q(s.cachedOptions.pop()),Ie(ut)}},$e=()=>{let Re;return pt(e.modelValue)?Re=[]:Re=\"\",s.softFocus=!0,e.multiple?s.cachedOptions=[]:s.selectedLabel=\"\",S.value=!1,Ie(Re),t(\"clear\"),de(),Ne(Be)},Ve=Re=>{s.displayInputValue=Re,s.inputValue=Re},st=(Re,ut=void 0)=>{const Vt=N.value;if(![\"forward\",\"backward\"].includes(Re)||w.value||Vt.length<=0||D.value)return;if(!S.value)return te();ut===void 0&&(ut=s.hoveringIndex);let it=-1;Re===\"forward\"?(it=ut+1,it>=Vt.length&&(it=0)):Re===\"backward\"&&(it=ut-1,it<0&&(it=Vt.length-1));const ct=Vt[it];if(ct.disabled||ct.type===\"Group\")return st(Re,it);Ut(it),Va(it)},Dt=()=>{if(S.value)~s.hoveringIndex&&N.value[s.hoveringIndex]&&me(N.value[s.hoveringIndex],s.hoveringIndex,!1);else return te()},Ut=Re=>{s.hoveringIndex=Re},Ft=()=>{s.hoveringIndex=-1},Jt=()=>{var Re;const ut=p.value;ut&&((Re=ut.focus)==null||Re.call(ut))},Mn=Re=>{const ut=Re.target.value;if(Ve(ut),s.displayInputValue.length>0&&!S.value&&(S.value=!0),s.calculatedWidth=C.value.getBoundingClientRect().width,e.multiple&&Ce(),e.remote)ge();else return ie()},tr=()=>(S.value=!1,Ye()),nr=()=>(s.inputValue=s.displayInputValue,Ne(()=>{~J.value&&(Ut(J.value),Va(s.hoveringIndex))})),Va=Re=>{v.value.scrollToItem(Re)},Wo=()=>{if(Ft(),e.multiple)if(e.modelValue.length>0){let Re=!1;s.cachedOptions.length=0,s.previousValue=e.modelValue.toString(),e.modelValue.forEach(ut=>{const Vt=N.value.findIndex(it=>pe(it)===ut);~Vt&&(s.cachedOptions.push(N.value[Vt]),Re||Ut(Vt),Re=!0)})}else s.cachedOptions=[],s.previousValue=\"\";else if($.value){s.previousValue=e.modelValue;const Re=N.value,ut=Re.findIndex(Vt=>pe(Vt)===pe(e.modelValue));~ut?(s.selectedLabel=Re[ut].label,Ut(ut)):s.selectedLabel=`${e.modelValue}`}else s.selectedLabel=\"\",s.previousValue=\"\";E()};return ce(S,Re=>{var ut,Vt;t(\"visible-change\",Re),Re?(Vt=(ut=m.value).update)==null||Vt.call(ut):(s.displayInputValue=\"\",oe(\"\"))}),ce(()=>e.modelValue,(Re,ut)=>{var Vt;(!Re||Re.toString()!==s.previousValue)&&Wo(),er(Re,ut)||(Vt=i==null?void 0:i.validate)==null||Vt.call(i,\"change\").catch(it=>void 0)},{deep:!0}),ce(()=>e.options,()=>{const Re=p.value;(!Re||Re&&document.activeElement!==Re)&&Wo()},{deep:!0}),ce(N,()=>Ne(v.value.resetScrollTop)),et(()=>{Wo(),wc(y.value,je)}),hc(()=>{Sc(y.value,je)}),{collapseTagSize:B,currentPlaceholder:Y,expanded:S,emptyText:F,popupHeight:k,debounce:j,filteredOptions:N,iconComponent:T,iconReverse:_,inputWrapperStyle:K,popperSize:d,dropdownMenuVisible:ne,hasModelValue:$,shouldShowPlaceholder:W,selectDisabled:w,selectSize:z,showClearBtn:O,states:s,tagMaxWidth:M,nsSelectV2:r,nsInput:a,calculatorRef:C,controlRef:f,inputRef:p,menuRef:v,popper:m,selectRef:y,selectionRef:b,popperRef:q,validateState:I,validateIcon:L,compatTeleported:l,debouncedOnInputChange:ge,deleteTag:He,getLabel:ue,getValueKey:pe,handleBlur:Ye,handleClear:$e,handleClickOutside:tr,handleDel:_e,handleEsc:he,handleFocus:lt,handleMenuEnter:nr,handleResize:je,toggleMenu:te,scrollTo:Va,onInput:Mn,onKeyboardNavigate:st,onKeyboardSelect:Dt,onSelect:me,onHover:Ut,onUpdateInputValue:Ve,handleCompositionStart:be,handleCompositionEnd:Pe,handleCompositionUpdate:Ee}},mhe=G({name:\"ElSelectV2\",components:{ElSelectMenu:uhe,ElTag:Gm,ElTooltip:Ur,ElIcon:ft},directives:{ClickOutside:Is,ModelText:fC},props:nhe,emits:[Pt,ir,\"remove-tag\",\"clear\",\"visible-change\",\"focus\",\"blur\"],setup(e,{emit:t}){const n=vhe(e,t);return ot(X5,{props:bt(Ke(Te({},or(e)),{height:n.popupHeight})),onSelect:n.onSelect,onHover:n.onHover,onKeyboardNavigate:n.onKeyboardNavigate,onKeyboardSelect:n.onKeyboardSelect}),n}}),ghe={key:0},yhe=[\"id\",\"autocomplete\",\"aria-expanded\",\"aria-labelledby\",\"disabled\",\"readonly\",\"name\",\"unselectable\"],bhe=[\"textContent\"],Che=[\"id\",\"aria-labelledby\",\"aria-expanded\",\"autocomplete\",\"disabled\",\"name\",\"readonly\",\"unselectable\"],whe=[\"textContent\"];function She(e,t,n,r,a,o){const i=we(\"el-tag\"),l=we(\"el-tooltip\"),s=we(\"el-icon\"),c=we(\"el-select-menu\"),d=pa(\"model-text\"),f=pa(\"click-outside\");return at((R(),X(\"div\",{ref:\"selectRef\",class:U([e.nsSelectV2.b(),e.nsSelectV2.m(e.selectSize)]),onClick:t[24]||(t[24]=dt((...p)=>e.toggleMenu&&e.toggleMenu(...p),[\"stop\"])),onMouseenter:t[25]||(t[25]=p=>e.states.comboBoxHovering=!0),onMouseleave:t[26]||(t[26]=p=>e.states.comboBoxHovering=!1)},[g(l,{ref:\"popper\",visible:e.dropdownMenuVisible,\"onUpdate:visible\":t[22]||(t[22]=p=>e.dropdownMenuVisible=p),teleported:e.compatTeleported,\"popper-class\":[e.nsSelectV2.e(\"popper\"),e.popperClass],\"gpu-acceleration\":!1,\"stop-popper-mouse-event\":!1,\"popper-options\":e.popperOptions,\"fallback-placements\":[\"bottom-start\",\"top-start\",\"right\",\"left\"],effect:e.effect,placement:\"bottom-start\",pure:\"\",transition:`${e.nsSelectV2.namespace.value}-zoom-in-top`,trigger:\"click\",persistent:e.persistent,onBeforeShow:e.handleMenuEnter,onHide:t[23]||(t[23]=p=>e.states.inputValue=e.states.displayInputValue)},{default:re(()=>{var p;return[Z(\"div\",{ref:\"selectionRef\",class:U([e.nsSelectV2.e(\"wrapper\"),e.nsSelectV2.is(\"focused\",e.states.isComposing),e.nsSelectV2.is(\"hovering\",e.states.comboBoxHovering),e.nsSelectV2.is(\"filterable\",e.filterable),e.nsSelectV2.is(\"disabled\",e.selectDisabled)])},[e.$slots.prefix?(R(),X(\"div\",ghe,[Oe(e.$slots,\"prefix\")])):se(\"v-if\",!0),e.multiple?(R(),X(\"div\",{key:1,class:U(e.nsSelectV2.e(\"selection\"))},[e.collapseTags&&e.modelValue.length>0?(R(),X(\"div\",{key:0,class:U(e.nsSelectV2.e(\"selected-item\"))},[g(i,{closable:!e.selectDisabled&&!((p=e.states.cachedOptions[0])!=null&&p.disable),size:e.collapseTagSize,type:\"info\",\"disable-transitions\":\"\",onClose:t[0]||(t[0]=v=>e.deleteTag(v,e.states.cachedOptions[0]))},{default:re(()=>{var v;return[Z(\"span\",{class:U(e.nsSelectV2.e(\"tags-text\")),style:Xe({maxWidth:`${e.tagMaxWidth}px`})},Me((v=e.states.cachedOptions[0])==null?void 0:v.label),7)]}),_:1},8,[\"closable\",\"size\"]),e.modelValue.length>1?(R(),fe(i,{key:0,closable:!1,size:e.collapseTagSize,type:\"info\",\"disable-transitions\":\"\"},{default:re(()=>[e.collapseTagsTooltip?(R(),fe(l,{key:0,disabled:e.dropdownMenuVisible,\"fallback-placements\":[\"bottom\",\"top\",\"right\",\"left\"],effect:e.effect,placement:\"bottom\",teleported:!1},{default:re(()=>[Z(\"span\",{class:U(e.nsSelectV2.e(\"tags-text\")),style:Xe({maxWidth:`${e.tagMaxWidth}px`})},\"+ \"+Me(e.modelValue.length-1),7)]),content:re(()=>[Z(\"div\",{class:U(e.nsSelectV2.e(\"selection\"))},[(R(!0),X(Fe,null,Rt(e.states.cachedOptions,(v,m)=>(R(),X(\"div\",{key:m,class:U(e.nsSelectV2.e(\"selected-item\"))},[(R(),fe(i,{key:e.getValueKey(v),closable:!e.selectDisabled&&!v.disabled,size:e.collapseTagSize,class:\"in-tooltip\",type:\"info\",\"disable-transitions\":\"\",onClose:y=>e.deleteTag(y,v)},{default:re(()=>[Z(\"span\",{class:U(e.nsSelectV2.e(\"tags-text\")),style:Xe({maxWidth:`${e.tagMaxWidth}px`})},Me(e.getLabel(v)),7)]),_:2},1032,[\"closable\",\"size\",\"onClose\"]))],2))),128))],2)]),_:1},8,[\"disabled\",\"effect\"])):(R(),X(\"span\",{key:1,class:U(e.nsSelectV2.e(\"tags-text\")),style:Xe({maxWidth:`${e.tagMaxWidth}px`})},\"+ \"+Me(e.modelValue.length-1),7))]),_:1},8,[\"size\"])):se(\"v-if\",!0)],2)):(R(!0),X(Fe,{key:1},Rt(e.states.cachedOptions,(v,m)=>(R(),X(\"div\",{key:m,class:U(e.nsSelectV2.e(\"selected-item\"))},[(R(),fe(i,{key:e.getValueKey(v),closable:!e.selectDisabled&&!v.disabled,size:e.collapseTagSize,type:\"info\",\"disable-transitions\":\"\",onClose:y=>e.deleteTag(y,v)},{default:re(()=>[Z(\"span\",{class:U(e.nsSelectV2.e(\"tags-text\")),style:Xe({maxWidth:`${e.tagMaxWidth}px`})},Me(e.getLabel(v)),7)]),_:2},1032,[\"closable\",\"size\",\"onClose\"]))],2))),128)),Z(\"div\",{class:U([e.nsSelectV2.e(\"selected-item\"),e.nsSelectV2.e(\"input-wrapper\")]),style:Xe(e.inputWrapperStyle)},[at(Z(\"input\",{id:e.id,ref:\"inputRef\",autocomplete:e.autocomplete,\"aria-autocomplete\":\"list\",\"aria-haspopup\":\"listbox\",autocapitalize:\"off\",\"aria-expanded\":e.expanded,\"aria-labelledby\":e.label,class:U([e.nsSelectV2.is(e.selectSize),e.nsSelectV2.e(\"combobox-input\")]),disabled:e.disabled,role:\"combobox\",readonly:!e.filterable,spellcheck:\"false\",type:\"text\",name:e.name,unselectable:e.expanded?\"on\":void 0,\"onUpdate:modelValue\":t[1]||(t[1]=(...v)=>e.onUpdateInputValue&&e.onUpdateInputValue(...v)),onFocus:t[2]||(t[2]=(...v)=>e.handleFocus&&e.handleFocus(...v)),onInput:t[3]||(t[3]=(...v)=>e.onInput&&e.onInput(...v)),onCompositionstart:t[4]||(t[4]=(...v)=>e.handleCompositionStart&&e.handleCompositionStart(...v)),onCompositionupdate:t[5]||(t[5]=(...v)=>e.handleCompositionUpdate&&e.handleCompositionUpdate(...v)),onCompositionend:t[6]||(t[6]=(...v)=>e.handleCompositionEnd&&e.handleCompositionEnd(...v)),onKeydown:[t[7]||(t[7]=It(dt(v=>e.onKeyboardNavigate(\"backward\"),[\"stop\",\"prevent\"]),[\"up\"])),t[8]||(t[8]=It(dt(v=>e.onKeyboardNavigate(\"forward\"),[\"stop\",\"prevent\"]),[\"down\"])),t[9]||(t[9]=It(dt((...v)=>e.onKeyboardSelect&&e.onKeyboardSelect(...v),[\"stop\",\"prevent\"]),[\"enter\"])),t[10]||(t[10]=It(dt((...v)=>e.handleEsc&&e.handleEsc(...v),[\"stop\",\"prevent\"]),[\"esc\"])),t[11]||(t[11]=It(dt((...v)=>e.handleDel&&e.handleDel(...v),[\"stop\"]),[\"delete\"]))]},null,42,yhe),[[d,e.states.displayInputValue]]),e.filterable?(R(),X(\"span\",{key:0,ref:\"calculatorRef\",\"aria-hidden\":\"true\",class:U(e.nsSelectV2.e(\"input-calculator\")),textContent:Me(e.states.displayInputValue)},null,10,bhe)):se(\"v-if\",!0)],6)],2)):(R(),X(Fe,{key:2},[Z(\"div\",{class:U([e.nsSelectV2.e(\"selected-item\"),e.nsSelectV2.e(\"input-wrapper\")])},[at(Z(\"input\",{id:e.id,ref:\"inputRef\",\"aria-autocomplete\":\"list\",\"aria-haspopup\":\"listbox\",\"aria-labelledby\":e.label,\"aria-expanded\":e.expanded,autocapitalize:\"off\",autocomplete:e.autocomplete,class:U(e.nsSelectV2.e(\"combobox-input\")),disabled:e.disabled,name:e.name,role:\"combobox\",readonly:!e.filterable,spellcheck:\"false\",type:\"text\",unselectable:e.expanded?\"on\":void 0,onCompositionstart:t[12]||(t[12]=(...v)=>e.handleCompositionStart&&e.handleCompositionStart(...v)),onCompositionupdate:t[13]||(t[13]=(...v)=>e.handleCompositionUpdate&&e.handleCompositionUpdate(...v)),onCompositionend:t[14]||(t[14]=(...v)=>e.handleCompositionEnd&&e.handleCompositionEnd(...v)),onFocus:t[15]||(t[15]=(...v)=>e.handleFocus&&e.handleFocus(...v)),onInput:t[16]||(t[16]=(...v)=>e.onInput&&e.onInput(...v)),onKeydown:[t[17]||(t[17]=It(dt(v=>e.onKeyboardNavigate(\"backward\"),[\"stop\",\"prevent\"]),[\"up\"])),t[18]||(t[18]=It(dt(v=>e.onKeyboardNavigate(\"forward\"),[\"stop\",\"prevent\"]),[\"down\"])),t[19]||(t[19]=It(dt((...v)=>e.onKeyboardSelect&&e.onKeyboardSelect(...v),[\"stop\",\"prevent\"]),[\"enter\"])),t[20]||(t[20]=It(dt((...v)=>e.handleEsc&&e.handleEsc(...v),[\"stop\",\"prevent\"]),[\"esc\"]))],\"onUpdate:modelValue\":t[21]||(t[21]=(...v)=>e.onUpdateInputValue&&e.onUpdateInputValue(...v))},null,42,Che),[[d,e.states.displayInputValue]])],2),e.filterable?(R(),X(\"span\",{key:0,ref:\"calculatorRef\",\"aria-hidden\":\"true\",class:U([e.nsSelectV2.e(\"selected-item\"),e.nsSelectV2.e(\"input-calculator\")]),textContent:Me(e.states.displayInputValue)},null,10,whe)):se(\"v-if\",!0)],64)),e.shouldShowPlaceholder?(R(),X(\"span\",{key:3,class:U([e.nsSelectV2.e(\"placeholder\"),e.nsSelectV2.is(\"transparent\",e.states.isComposing||(e.placeholder&&e.multiple?e.modelValue.length===0:!e.hasModelValue))])},Me(e.currentPlaceholder),3)):se(\"v-if\",!0),Z(\"span\",{class:U(e.nsSelectV2.e(\"suffix\"))},[e.iconComponent?at((R(),fe(s,{key:0,class:U([e.nsSelectV2.e(\"caret\"),e.nsInput.e(\"icon\"),e.iconReverse])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])),[[_t,!e.showClearBtn]]):se(\"v-if\",!0),e.showClearBtn&&e.clearIcon?(R(),fe(s,{key:1,class:U([e.nsSelectV2.e(\"caret\"),e.nsInput.e(\"icon\")]),onClick:dt(e.handleClear,[\"prevent\",\"stop\"])},{default:re(()=>[(R(),fe(Kt(e.clearIcon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0),e.validateState&&e.validateIcon?(R(),fe(s,{key:2,class:U([e.nsInput.e(\"icon\"),e.nsInput.e(\"validateIcon\")])},{default:re(()=>[(R(),fe(Kt(e.validateIcon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],2)],2)]}),content:re(()=>[g(c,{ref:\"menuRef\",data:e.filteredOptions,width:e.popperSize,\"hovering-index\":e.states.hoveringIndex,\"scrollbar-always-on\":e.scrollbarAlwaysOn},{default:re(p=>[Oe(e.$slots,\"default\",Za(ll(p)))]),empty:re(()=>[Oe(e.$slots,\"empty\",{},()=>[Z(\"p\",{class:U(e.nsSelectV2.e(\"empty\"))},Me(e.emptyText?e.emptyText:\"\"),3)])]),_:3},8,[\"data\",\"width\",\"hovering-index\",\"scrollbar-always-on\"])]),_:3},8,[\"visible\",\"teleported\",\"popper-class\",\"popper-options\",\"effect\",\"transition\",\"persistent\",\"onBeforeShow\"])],34)),[[f,e.handleClickOutside,e.popperRef]])}var Op=Ae(mhe,[[\"render\",She],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/select-v2/src/select.vue\"]]);Op.install=e=>{e.component(Op.name,Op)};const khe=Op,$he=khe,Ohe=Ze({animated:{type:Boolean,default:!1},count:{type:Number,default:1},rows:{type:Number,default:3},loading:{type:Boolean,default:!0},throttle:{type:Number}}),Phe=Ze({variant:{type:String,values:[\"circle\",\"rect\",\"h1\",\"h3\",\"text\",\"caption\",\"p\",\"image\",\"button\"],default:\"text\"}}),The={name:\"ElSkeletonItem\"},xhe=G(Ke(Te({},The),{props:Phe,setup(e){const t=De(\"skeleton\");return(n,r)=>(R(),X(\"div\",{class:U([A(t).e(\"item\"),A(t).e(n.variant)])},[n.variant===\"image\"?(R(),fe(A($G),{key:0})):se(\"v-if\",!0)],2))}}));var kv=Ae(xhe,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/skeleton/src/skeleton-item.vue\"]]);const _he={name:\"ElSkeleton\"},Ehe=G(Ke(Te({},_he),{props:Ohe,setup(e,{expose:t}){const n=e,r=De(\"skeleton\"),a=fZ(yn(n,\"loading\"),n.throttle);return t({uiLoading:a}),(o,i)=>A(a)?(R(),X(\"div\",hn({key:0,class:[A(r).b(),A(r).is(\"animated\",o.animated)]},o.$attrs),[(R(!0),X(Fe,null,Rt(o.count,l=>(R(),X(Fe,{key:l},[o.loading?Oe(o.$slots,\"template\",{key:l},()=>[g(kv,{class:U(A(r).is(\"first\")),variant:\"p\"},null,8,[\"class\"]),(R(!0),X(Fe,null,Rt(o.rows,s=>(R(),fe(kv,{key:s,class:U([A(r).e(\"paragraph\"),A(r).is(\"last\",s===o.rows&&o.rows>1)]),variant:\"p\"},null,8,[\"class\"]))),128))]):se(\"v-if\",!0)],64))),128))],16)):Oe(o.$slots,\"default\",Za(hn({key:1},o.$attrs)))}}));var Mhe=Ae(Ehe,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/skeleton/src/skeleton.vue\"]]);const Ihe=xt(Mhe,{SkeletonItem:kv}),Nhe=En(kv),Ahe=(e,t,n)=>{const r=H(null),a=H(!1),o=x(()=>t.value instanceof Function),i=x(()=>o.value&&t.value(e.modelValue)||e.modelValue),l=Yn(()=>{n.value&&(a.value=!0)},50),s=Yn(()=>{n.value&&(a.value=!1)},50);return{tooltip:r,tooltipVisible:a,formatValue:i,displayTooltip:l,hideTooltip:s}},Dhe=(e,t,n)=>{const{disabled:r,min:a,max:o,step:i,showTooltip:l,precision:s,sliderSize:c,formatTooltip:d,emitChange:f,resetSize:p,updateDragging:v}=ve(\"SliderProvider\"),{tooltip:m,tooltipVisible:y,formatValue:b,displayTooltip:C,hideTooltip:S}=Ahe(e,d,l),w=x(()=>`${(e.modelValue-a.value)/(o.value-a.value)*100}%`),k=x(()=>e.vertical?{bottom:w.value}:{left:w.value}),$=()=>{t.hovering=!0,C()},O=()=>{t.hovering=!1,t.dragging||S()},T=z=>{r.value||(z.preventDefault(),j(z),gn(window,\"mousemove\",F),gn(window,\"touchmove\",F),gn(window,\"mouseup\",N),gn(window,\"touchend\",N),gn(window,\"contextmenu\",N))},_=()=>{r.value||(t.newPosition=Number.parseFloat(w.value)-i.value/(o.value-a.value)*100,D(t.newPosition),f())},I=()=>{r.value||(t.newPosition=Number.parseFloat(w.value)+i.value/(o.value-a.value)*100,D(t.newPosition),f())},L=z=>{let B,M;return z.type.startsWith(\"touch\")?(M=z.touches[0].clientY,B=z.touches[0].clientX):(M=z.clientY,B=z.clientX),{clientX:B,clientY:M}},j=z=>{t.dragging=!0,t.isClick=!0;const{clientX:B,clientY:M}=L(z);e.vertical?t.startY=M:t.startX=B,t.startPosition=Number.parseFloat(w.value),t.newPosition=t.startPosition},F=z=>{if(t.dragging){t.isClick=!1,C(),p();let B;const{clientX:M,clientY:E}=L(z);e.vertical?(t.currentY=E,B=(t.startY-t.currentY)/c.value*100):(t.currentX=M,B=(t.currentX-t.startX)/c.value*100),t.newPosition=t.startPosition+B,D(t.newPosition)}},N=()=>{t.dragging&&(setTimeout(()=>{t.dragging=!1,t.hovering||S(),t.isClick||(D(t.newPosition),f())},0),Bn(window,\"mousemove\",F),Bn(window,\"touchmove\",F),Bn(window,\"mouseup\",N),Bn(window,\"touchend\",N),Bn(window,\"contextmenu\",N))},D=async z=>{if(z===null||Number.isNaN(+z))return;z<0?z=0:z>100&&(z=100);const B=100/((o.value-a.value)/i.value);let E=Math.round(z/B)*B*(o.value-a.value)*.01+a.value;E=Number.parseFloat(E.toFixed(s.value)),n(Pt,E),!t.dragging&&e.modelValue!==t.oldValue&&(t.oldValue=e.modelValue),await Ne(),t.dragging&&C(),m.value.updatePopper()};return ce(()=>t.dragging,z=>{v(z)}),{tooltip:m,tooltipVisible:y,showTooltip:l,wrapperStyle:k,formatValue:b,handleMouseEnter:$,handleMouseLeave:O,onButtonDown:T,onLeftKeyDown:_,onRightKeyDown:I,setPosition:D}},Rhe=G({name:\"ElSliderButton\",components:{ElTooltip:Ur},props:{modelValue:{type:Number,default:0},vertical:{type:Boolean,default:!1},tooltipClass:{type:String,default:\"\"}},emits:[Pt],setup(e,{emit:t}){const n=De(\"slider\"),r=bt({hovering:!1,dragging:!1,isClick:!1,startX:0,currentX:0,startY:0,currentY:0,startPosition:0,newPosition:0,oldValue:e.modelValue}),{tooltip:a,showTooltip:o,tooltipVisible:i,wrapperStyle:l,formatValue:s,handleMouseEnter:c,handleMouseLeave:d,onButtonDown:f,onLeftKeyDown:p,onRightKeyDown:v,setPosition:m}=Dhe(e,r,t),{hovering:y,dragging:b}=or(r);return{ns:n,tooltip:a,tooltipVisible:i,showTooltip:o,wrapperStyle:l,formatValue:s,handleMouseEnter:c,handleMouseLeave:d,onButtonDown:f,onLeftKeyDown:p,onRightKeyDown:v,setPosition:m,hovering:y,dragging:b}}});function Lhe(e,t,n,r,a,o){const i=we(\"el-tooltip\");return R(),X(\"div\",{ref:\"button\",class:U([e.ns.e(\"button-wrapper\"),{hover:e.hovering,dragging:e.dragging}]),style:Xe(e.wrapperStyle),tabindex:\"0\",onMouseenter:t[1]||(t[1]=(...l)=>e.handleMouseEnter&&e.handleMouseEnter(...l)),onMouseleave:t[2]||(t[2]=(...l)=>e.handleMouseLeave&&e.handleMouseLeave(...l)),onMousedown:t[3]||(t[3]=(...l)=>e.onButtonDown&&e.onButtonDown(...l)),onTouchstart:t[4]||(t[4]=(...l)=>e.onButtonDown&&e.onButtonDown(...l)),onFocus:t[5]||(t[5]=(...l)=>e.handleMouseEnter&&e.handleMouseEnter(...l)),onBlur:t[6]||(t[6]=(...l)=>e.handleMouseLeave&&e.handleMouseLeave(...l)),onKeydown:[t[7]||(t[7]=It((...l)=>e.onLeftKeyDown&&e.onLeftKeyDown(...l),[\"left\"])),t[8]||(t[8]=It((...l)=>e.onRightKeyDown&&e.onRightKeyDown(...l),[\"right\"])),t[9]||(t[9]=It(dt((...l)=>e.onLeftKeyDown&&e.onLeftKeyDown(...l),[\"prevent\"]),[\"down\"])),t[10]||(t[10]=It(dt((...l)=>e.onRightKeyDown&&e.onRightKeyDown(...l),[\"prevent\"]),[\"up\"]))]},[g(i,{ref:\"tooltip\",visible:e.tooltipVisible,\"onUpdate:visible\":t[0]||(t[0]=l=>e.tooltipVisible=l),placement:\"top\",\"stop-popper-mouse-event\":!1,\"popper-class\":e.tooltipClass,disabled:!e.showTooltip,persistent:\"\"},{content:re(()=>[Z(\"span\",null,Me(e.formatValue),1)]),default:re(()=>[Z(\"div\",{class:U([e.ns.e(\"button\"),{hover:e.hovering,dragging:e.dragging}])},null,2)]),_:1},8,[\"visible\",\"popper-class\",\"disabled\"])],38)}var Fhe=Ae(Rhe,[[\"render\",Lhe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/slider/src/button.vue\"]]);const Bhe=G({name:\"ElMarker\",props:{mark:{type:[String,Object],default:()=>{}}},setup(e){const t=De(\"slider\"),n=x(()=>typeof e.mark==\"string\"?e.mark:e.mark.label);return{ns:t,label:n}},render(){var e;return qe(\"div\",{class:this.ns.e(\"marks-text\"),style:(e=this.mark)==null?void 0:e.style},this.label)}});var Vhe=Ae(Bhe,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/slider/src/marker.vue\"]]);const zhe=e=>x(()=>e.marks?Object.keys(e.marks).map(parseFloat).sort((n,r)=>n-r).filter(n=>n<=e.max&&n>=e.min).map(n=>({point:n,position:(n-e.min)*100/(e.max-e.min),mark:e.marks[n]})):[]),Hhe=(e,t,n)=>{const r=ve(ga,{}),a=ve(Ia,{}),o=Qn(null),i=H(null),l=H(null),s={firstButton:i,secondButton:l},c=x(()=>e.disabled||r.disabled||!1),d=x(()=>Math.min(t.firstValue,t.secondValue)),f=x(()=>Math.max(t.firstValue,t.secondValue)),p=x(()=>e.range?`${100*(f.value-d.value)/(e.max-e.min)}%`:`${100*(t.firstValue-e.min)/(e.max-e.min)}%`),v=x(()=>e.range?`${100*(d.value-e.min)/(e.max-e.min)}%`:\"0%\"),m=x(()=>e.vertical?{height:e.height}:{}),y=x(()=>e.vertical?{height:p.value,bottom:v.value}:{width:p.value,left:v.value}),b=()=>{o.value&&(t.sliderSize=o.value[`client${e.vertical?\"Height\":\"Width\"}`])},C=T=>{const _=e.min+T*(e.max-e.min)/100;if(!e.range){i.value.setPosition(T);return}let I;Math.abs(d.value-_)<Math.abs(f.value-_)?I=t.firstValue<t.secondValue?\"firstButton\":\"secondButton\":I=t.firstValue>t.secondValue?\"firstButton\":\"secondButton\",s[I].value.setPosition(T)},S=T=>{t.firstValue=T,k(e.range?[d.value,f.value]:T)},w=T=>{t.secondValue=T,e.range&&k([d.value,f.value])},k=T=>{n(Pt,T),n(cl,T)},$=async()=>{await Ne(),n(ir,e.range?[d.value,f.value]:e.modelValue)};return{elFormItem:a,slider:o,firstButton:i,secondButton:l,sliderDisabled:c,minValue:d,maxValue:f,runwayStyle:m,barStyle:y,resetSize:b,setPosition:C,emitChange:$,onSliderClick:T=>{if(!(c.value||t.dragging)){if(b(),e.vertical){const _=o.value.getBoundingClientRect().bottom;C((_-T.clientY)/t.sliderSize*100)}else{const _=o.value.getBoundingClientRect().left;C((T.clientX-_)/t.sliderSize*100)}$()}},setFirstValue:S,setSecondValue:w}},jhe=(e,t,n,r)=>({stops:x(()=>{if(!e.showStops||e.min>e.max)return[];if(e.step===0)return[];const i=(e.max-e.min)/e.step,l=100*e.step/(e.max-e.min),s=Array.from({length:i-1}).map((c,d)=>(d+1)*l);return e.range?s.filter(c=>c<100*(n.value-e.min)/(e.max-e.min)||c>100*(r.value-e.min)/(e.max-e.min)):s.filter(c=>c>100*(t.firstValue-e.min)/(e.max-e.min))}),getStopStyle:i=>e.vertical?{bottom:`${i}%`}:{left:`${i}%`}}),Khe=G({name:\"ElSlider\",components:{ElInputNumber:_5,SliderButton:Fhe,SliderMarker:Vhe},props:{modelValue:{type:[Number,Array],default:0},min:{type:Number,default:0},max:{type:Number,default:100},step:{type:Number,default:1},showInput:{type:Boolean,default:!1},showInputControls:{type:Boolean,default:!0},size:{type:String,validator:va},inputSize:{type:String,validator:va},showStops:{type:Boolean,default:!1},showTooltip:{type:Boolean,default:!0},formatTooltip:{type:Function,default:void 0},disabled:{type:Boolean,default:!1},range:{type:Boolean,default:!1},vertical:{type:Boolean,default:!1},height:{type:String,default:\"\"},debounce:{type:Number,default:300},label:{type:String,default:void 0},tooltipClass:{type:String,default:void 0},marks:Object},emits:[Pt,ir,cl],setup(e,{emit:t}){const n=De(\"slider\"),r=bt({firstValue:0,secondValue:0,oldValue:0,dragging:!1,sliderSize:1}),{elFormItem:a,slider:o,firstButton:i,secondButton:l,sliderDisabled:s,minValue:c,maxValue:d,runwayStyle:f,barStyle:p,resetSize:v,emitChange:m,onSliderClick:y,setFirstValue:b,setSecondValue:C}=Hhe(e,r,t),{stops:S,getStopStyle:w}=jhe(e,r,c,d),k=Gn(),$=x(()=>e.inputSize||k.value),O=x(()=>[n.b(),n.m(k.value),n.is(\"vertical\",e.vertical),{[n.m(\"with-input\")]:e.showInput}]),T=zhe(e);Whe(e,r,c,d,t,a);const _=x(()=>{const B=[e.min,e.max,e.step].map(M=>{const E=`${M}`.split(\".\")[1];return E?E.length:0});return Math.max.apply(null,B)}),{sliderWrapper:I}=Uhe(e,r,v),{firstValue:L,secondValue:j,oldValue:F,dragging:N,sliderSize:D}=or(r),z=B=>{r.dragging=B};return ot(\"SliderProvider\",Ke(Te({},or(e)),{sliderSize:D,disabled:s,precision:_,emitChange:m,resetSize:v,updateDragging:z})),{ns:n,firstValue:L,secondValue:j,oldValue:F,dragging:N,sliderSize:D,slider:o,firstButton:i,secondButton:l,sliderDisabled:s,runwayStyle:f,barStyle:p,emitChange:m,onSliderClick:y,getStopStyle:w,setFirstValue:b,setSecondValue:C,stops:S,markList:T,sliderWrapper:I,sliderWrapperSize:k,sliderInputSize:$,sliderKls:O}}}),Whe=(e,t,n,r,a,o)=>{const i=c=>{a(Pt,c),a(cl,c)},l=()=>e.range?![n.value,r.value].every((c,d)=>c===t.oldValue[d]):e.modelValue!==t.oldValue,s=()=>{var c,d;if(e.min>e.max){qn(\"Slider\",\"min should not be greater than max.\");return}const f=e.modelValue;e.range&&Array.isArray(f)?f[1]<e.min?i([e.min,e.min]):f[0]>e.max?i([e.max,e.max]):f[0]<e.min?i([e.min,f[1]]):f[1]>e.max?i([f[0],e.max]):(t.firstValue=f[0],t.secondValue=f[1],l()&&((c=o.validate)==null||c.call(o,\"change\").catch(p=>void 0),t.oldValue=f.slice())):!e.range&&typeof f==\"number\"&&!Number.isNaN(f)&&(f<e.min?i(e.min):f>e.max?i(e.max):(t.firstValue=f,l()&&((d=o.validate)==null||d.call(o,\"change\").catch(p=>void 0),t.oldValue=f)))};s(),ce(()=>t.dragging,c=>{c||s()}),ce(()=>e.modelValue,(c,d)=>{t.dragging||Array.isArray(c)&&Array.isArray(d)&&c.every((f,p)=>f===d[p])&&t.firstValue===c[0]&&t.secondValue===c[1]||s()},{deep:!0}),ce(()=>[e.min,e.max],()=>{s()})},Uhe=(e,t,n)=>{const r=H(null);return et(async()=>{let a;e.range?(Array.isArray(e.modelValue)?(t.firstValue=Math.max(e.min,e.modelValue[0]),t.secondValue=Math.min(e.max,e.modelValue[1])):(t.firstValue=e.min,t.secondValue=e.max),t.oldValue=[t.firstValue,t.secondValue],a=`${t.firstValue}-${t.secondValue}`):(typeof e.modelValue!=\"number\"||Number.isNaN(e.modelValue)?t.firstValue=e.min:t.firstValue=Math.min(e.max,Math.max(e.min,e.modelValue)),t.oldValue=t.firstValue,a=t.firstValue),r.value.setAttribute(\"aria-valuetext\",a),r.value.setAttribute(\"aria-label\",e.label?e.label:`slider between ${e.min} and ${e.max}`),gn(window,\"resize\",n),await Ne(),n()}),Lt(()=>{Bn(window,\"resize\",n)}),{sliderWrapper:r}},Yhe=[\"aria-valuemin\",\"aria-valuemax\",\"aria-orientation\",\"aria-disabled\"],qhe={key:1};function Ghe(e,t,n,r,a,o){const i=we(\"slider-button\"),l=we(\"slider-marker\"),s=we(\"el-input-number\");return R(),X(\"div\",{ref:\"sliderWrapper\",class:U(e.sliderKls),role:\"slider\",\"aria-valuemin\":e.min,\"aria-valuemax\":e.max,\"aria-orientation\":e.vertical?\"vertical\":\"horizontal\",\"aria-disabled\":e.sliderDisabled},[Z(\"div\",{ref:\"slider\",class:U([e.ns.e(\"runway\"),{\"show-input\":e.showInput&&!e.range},e.ns.is(\"disabled\",e.sliderDisabled)]),style:Xe(e.runwayStyle),onClick:t[0]||(t[0]=(...c)=>e.onSliderClick&&e.onSliderClick(...c))},[Z(\"div\",{class:U(e.ns.e(\"bar\")),style:Xe(e.barStyle)},null,6),g(i,{ref:\"firstButton\",\"model-value\":e.firstValue,vertical:e.vertical,\"tooltip-class\":e.tooltipClass,\"onUpdate:modelValue\":e.setFirstValue},null,8,[\"model-value\",\"vertical\",\"tooltip-class\",\"onUpdate:modelValue\"]),e.range?(R(),fe(i,{key:0,ref:\"secondButton\",\"model-value\":e.secondValue,vertical:e.vertical,\"tooltip-class\":e.tooltipClass,\"onUpdate:modelValue\":e.setSecondValue},null,8,[\"model-value\",\"vertical\",\"tooltip-class\",\"onUpdate:modelValue\"])):se(\"v-if\",!0),e.showStops?(R(),X(\"div\",qhe,[(R(!0),X(Fe,null,Rt(e.stops,(c,d)=>(R(),X(\"div\",{key:d,class:U(e.ns.e(\"stop\")),style:Xe(e.getStopStyle(c))},null,6))),128))])):se(\"v-if\",!0),e.markList.length>0?(R(),X(Fe,{key:2},[Z(\"div\",null,[(R(!0),X(Fe,null,Rt(e.markList,(c,d)=>(R(),X(\"div\",{key:d,style:Xe(e.getStopStyle(c.position)),class:U([e.ns.e(\"stop\"),e.ns.e(\"marks-stop\")])},null,6))),128))]),Z(\"div\",{class:U(e.ns.e(\"marks\"))},[(R(!0),X(Fe,null,Rt(e.markList,(c,d)=>(R(),fe(l,{key:d,mark:c.mark,style:Xe(e.getStopStyle(c.position))},null,8,[\"mark\",\"style\"]))),128))],2)],64)):se(\"v-if\",!0)],6),e.showInput&&!e.range?(R(),fe(s,{key:0,ref:\"input\",\"model-value\":e.firstValue,class:U(e.ns.e(\"input\")),step:e.step,disabled:e.sliderDisabled,controls:e.showInputControls,min:e.min,max:e.max,debounce:e.debounce,size:e.sliderInputSize,\"onUpdate:modelValue\":e.setFirstValue,onChange:e.emitChange},null,8,[\"model-value\",\"class\",\"step\",\"disabled\",\"controls\",\"min\",\"max\",\"debounce\",\"size\",\"onUpdate:modelValue\",\"onChange\"])):se(\"v-if\",!0)],10,Yhe)}var Pp=Ae(Khe,[[\"render\",Ghe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/slider/src/index.vue\"]]);Pp.install=e=>{e.component(Pp.name,Pp)};const Xhe=Pp,Zhe=Xhe,Jhe=Ze({prefixCls:{type:String,default:\"\"}}),Qhe=G({props:Jhe,setup(e){const t=De(\"space\");return{classes:x(()=>`${e.prefixCls||t.b()}__item`)}}});function epe(e,t,n,r,a,o){return R(),X(\"div\",{class:U(e.classes)},[Oe(e.$slots,\"default\")],2)}var gO=Ae(Qhe,[[\"render\",epe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/space/src/item.vue\"]]);const yO={small:8,default:12,large:16};function tpe(e){const t=De(\"space\"),n=x(()=>[t.b(),t.m(e.direction),e.class]),r=H(0),a=H(0),o=x(()=>{const l=e.wrap||e.fill?{flexWrap:\"wrap\",marginBottom:`-${a.value}px`}:{},s={alignItems:e.alignment};return[l,s,e.style]}),i=x(()=>{const l={paddingBottom:`${a.value}px`,marginRight:`${r.value}px`},s=e.fill?{flexGrow:1,minWidth:`${e.fillRatio}%`}:{};return[l,s]});return Wn(()=>{const{size:l=\"small\",wrap:s,direction:c,fill:d}=e;if(Array.isArray(l)){const[f=0,p=0]=l;r.value=f,a.value=p}else{let f;Yt(l)?f=l:f=yO[l]||yO.small,(s||d)&&c===\"horizontal\"?r.value=a.value=f:c===\"horizontal\"?(r.value=f,a.value=0):(a.value=f,r.value=0)}}),{classes:n,containerStyle:o,itemStyle:i}}const npe=Ze({direction:{type:String,values:[\"horizontal\",\"vertical\"],default:\"horizontal\"},class:{type:Le([String,Object,Array]),default:\"\"},style:{type:Le([String,Array,Object]),default:\"\"},alignment:{type:Le(String),default:\"center\"},prefixCls:{type:String},spacer:{type:Le([Object,String,Number,Array]),default:null,validator:e=>rn(e)||Yt(e)||wt(e)},wrap:{type:Boolean,default:!1},fill:{type:Boolean,default:!1},fillRatio:{type:Number,default:100},size:{type:[String,Array,Number],values:Bo,validator:e=>Yt(e)||pt(e)&&e.length===2&&e.every(t=>Yt(t))}});var rpe=G({name:\"ElSpace\",props:npe,setup(e,{slots:t}){const{classes:n,containerStyle:r,itemStyle:a}=tpe(e);return()=>{var o;const{spacer:i,prefixCls:l,direction:s}=e,c=Oe(t,\"default\",{key:0},()=>[]);if(((o=c.children)!=null?o:[]).length===0)return null;if(pt(c.children)){let d=[];if(c.children.forEach((f,p)=>{gE(f)?pt(f.children)&&f.children.forEach((v,m)=>{d.push(g(gO,{style:a.value,prefixCls:l,key:`nested-${m}`},{default:()=>[v]},ka.PROPS|ka.STYLE,[\"style\",\"prefixCls\"]))}):GX(f)&&d.push(g(gO,{style:a.value,prefixCls:l,key:`LoopKey${p}`},{default:()=>[f]},ka.PROPS|ka.STYLE,[\"style\",\"prefixCls\"]))}),i){const f=d.length-1;d=d.reduce((p,v,m)=>{const y=[...p,v];return m!==f&&y.push(g(\"span\",{style:[a.value,s===\"vertical\"?\"width: 100%\":null],key:m},[rn(i)?i:yt(i,ka.TEXT)],ka.STYLE)),y},[])}return g(\"div\",{class:n.value,style:r.value},d,ka.STYLE|ka.CLASS)}return c.children}}});const ape=xt(rpe),ope=G({name:\"ElSteps\",props:{space:{type:[Number,String],default:\"\"},active:{type:Number,default:0},direction:{type:String,default:\"horizontal\",validator:e=>[\"horizontal\",\"vertical\"].includes(e)},alignCenter:{type:Boolean,default:!1},simple:{type:Boolean,default:!1},finishStatus:{type:String,default:\"finish\",validator:e=>[\"wait\",\"process\",\"finish\",\"error\",\"success\"].includes(e)},processStatus:{type:String,default:\"process\",validator:e=>[\"wait\",\"process\",\"finish\",\"error\",\"success\"].includes(e)}},emits:[ir],setup(e,{emit:t}){const n=De(\"steps\"),r=H([]);return ce(r,()=>{r.value.forEach((a,o)=>{a.setIndex(o)})}),ot(\"ElSteps\",{props:e,steps:r}),ce(()=>e.active,(a,o)=>{t(ir,a,o)}),{steps:r,ns:n}}});function ipe(e,t,n,r,a,o){return R(),X(\"div\",{class:U([e.ns.b(),e.ns.m(e.simple?\"simple\":e.direction)])},[Oe(e.$slots,\"default\")],2)}var lpe=Ae(ope,[[\"render\",ipe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/steps/src/index.vue\"]]);const spe=G({name:\"ElStep\",components:{ElIcon:ft,Close:Ma,Check:Wu},props:{title:{type:String,default:\"\"},icon:{type:[String,Object],default:\"\"},description:{type:String,default:\"\"},status:{type:String,default:\"\",validator:e=>[\"\",\"wait\",\"process\",\"finish\",\"error\",\"success\"].includes(e)}},setup(e){const t=De(\"step\"),n=H(-1),r=H({}),a=H(\"\"),o=ve(\"ElSteps\"),i=$t();et(()=>{ce([()=>o.props.active,()=>o.props.processStatus,()=>o.props.finishStatus],([k])=>{S(k)},{immediate:!0})}),Lt(()=>{o.steps.value=o.steps.value.filter(k=>k.uid!==i.uid)});const l=x(()=>e.status||a.value),s=x(()=>{const k=o.steps.value[n.value-1];return k?k.currentStatus:\"wait\"}),c=x(()=>o.props.alignCenter),d=x(()=>o.props.direction===\"vertical\"),f=x(()=>o.props.simple),p=x(()=>o.steps.value.length),v=x(()=>{var k;return((k=o.steps.value[p.value-1])==null?void 0:k.uid)===i.uid}),m=x(()=>f.value?\"\":o.props.space),y=x(()=>{const k={flexBasis:typeof m.value==\"number\"?`${m.value}px`:m.value?m.value:`${100/(p.value-(c.value?0:1))}%`};return d.value||v.value&&(k.maxWidth=`${100/p.value}%`),k}),b=k=>{n.value=k},C=k=>{let $=100;const O={};O.transitionDelay=`${150*n.value}ms`,k===o.props.processStatus?$=0:k===\"wait\"&&($=0,O.transitionDelay=`${-150*n.value}ms`),O.borderWidth=$&&!f.value?\"1px\":0,O[o.props.direction===\"vertical\"?\"height\":\"width\"]=`${$}%`,r.value=O},S=k=>{k>n.value?a.value=o.props.finishStatus:k===n.value&&s.value!==\"error\"?a.value=o.props.processStatus:a.value=\"wait\";const $=o.steps.value[p.value-1];$&&$.calcProgress(a.value)},w=bt({uid:x(()=>i.uid),currentStatus:l,setIndex:b,calcProgress:C});return o.steps.value=[...o.steps.value,w],{ns:t,index:n,lineStyle:r,currentStatus:l,isCenter:c,isVertical:d,isSimple:f,isLast:v,space:m,style:y,parent:o,setIndex:b,calcProgress:C,updateStatus:S}}});function upe(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"check\"),s=we(\"close\");return R(),X(\"div\",{style:Xe(e.style),class:U([e.ns.b(),e.ns.is(e.isSimple?\"simple\":e.parent.props.direction),e.ns.is(\"flex\",e.isLast&&!e.space&&!e.isCenter),e.ns.is(\"center\",e.isCenter&&!e.isVertical&&!e.isSimple)])},[se(\" icon & line \"),Z(\"div\",{class:U([e.ns.e(\"head\"),e.ns.is(e.currentStatus)])},[e.isSimple?se(\"v-if\",!0):(R(),X(\"div\",{key:0,class:U(e.ns.e(\"line\"))},[Z(\"i\",{class:U(e.ns.e(\"line-inner\")),style:Xe(e.lineStyle)},null,6)],2)),Z(\"div\",{class:U([e.ns.e(\"icon\"),e.ns.is(e.icon?\"icon\":\"text\")])},[e.currentStatus!==\"success\"&&e.currentStatus!==\"error\"?Oe(e.$slots,\"icon\",{key:0},()=>[e.icon?(R(),fe(i,{key:0,class:U(e.ns.e(\"icon-inner\"))},{default:re(()=>[(R(),fe(Kt(e.icon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),!e.icon&&!e.isSimple?(R(),X(\"div\",{key:1,class:U(e.ns.e(\"icon-inner\"))},Me(e.index+1),3)):se(\"v-if\",!0)]):(R(),fe(i,{key:1,class:U([e.ns.e(\"icon-inner\"),e.ns.is(\"status\")])},{default:re(()=>[e.currentStatus===\"success\"?(R(),fe(l,{key:0})):(R(),fe(s,{key:1}))]),_:1},8,[\"class\"]))],2)],2),se(\" title & description \"),Z(\"div\",{class:U(e.ns.e(\"main\"))},[Z(\"div\",{class:U([e.ns.e(\"title\"),e.ns.is(e.currentStatus)])},[Oe(e.$slots,\"title\",{},()=>[yt(Me(e.title),1)])],2),e.isSimple?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"arrow\"))},null,2)):(R(),X(\"div\",{key:1,class:U([e.ns.e(\"description\"),e.ns.is(e.currentStatus)])},[Oe(e.$slots,\"description\",{},()=>[yt(Me(e.description),1)])],2))],2)],6)}var Z5=Ae(spe,[[\"render\",upe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/steps/src/item.vue\"]]);const cpe=xt(lpe,{Step:Z5}),dpe=En(Z5),fpe=Ze({modelValue:{type:[Boolean,String,Number],default:!1},value:{type:[Boolean,String,Number],default:!1},disabled:{type:Boolean,default:!1},width:{type:Number,default:40},inlinePrompt:{type:Boolean,default:!1},activeIcon:{type:wr,default:\"\"},inactiveIcon:{type:wr,default:\"\"},activeText:{type:String,default:\"\"},inactiveText:{type:String,default:\"\"},activeColor:{type:String,default:\"\"},inactiveColor:{type:String,default:\"\"},borderColor:{type:String,default:\"\"},activeValue:{type:[Boolean,String,Number],default:!0},inactiveValue:{type:[Boolean,String,Number],default:!1},name:{type:String,default:\"\"},validateEvent:{type:Boolean,default:!0},id:String,loading:{type:Boolean,default:!1},beforeChange:{type:Le(Function)},size:{type:String,validator:va}}),hpe={[Pt]:e=>yr(e)||wt(e)||Yt(e),[ir]:e=>yr(e)||wt(e)||Yt(e),[cl]:e=>yr(e)||wt(e)||Yt(e)},bO=\"ElSwitch\",ppe=G({name:bO,components:{ElIcon:ft,Loading:gl},props:fpe,emits:hpe,setup(e,{emit:t}){const{formItem:n}=$c(),r=Ms(x(()=>e.loading)),a=De(\"switch\"),o=Gn(),i=H(e.modelValue!==!1),l=H(),s=H(),c=x(()=>[a.b(),a.m(o.value),a.is(\"disabled\",r.value),a.is(\"checked\",f.value)]);ce(()=>e.modelValue,()=>{i.value=!0}),ce(()=>e.value,()=>{i.value=!1});const d=x(()=>i.value?e.modelValue:e.value),f=x(()=>d.value===e.activeValue);[e.activeValue,e.inactiveValue].includes(d.value)||(t(Pt,e.inactiveValue),t(ir,e.inactiveValue),t(cl,e.inactiveValue)),ce(f,()=>{var b;l.value.checked=f.value,(e.activeColor||e.inactiveColor)&&m(),e.validateEvent&&((b=n==null?void 0:n.validate)==null||b.call(n,\"change\").catch(C=>void 0))});const p=()=>{const b=f.value?e.inactiveValue:e.activeValue;t(Pt,b),t(ir,b),t(cl,b),Ne(()=>{l.value.checked=f.value})},v=()=>{if(r.value)return;const{beforeChange:b}=e;if(!b){p();return}const C=b();[hs(C),yr(C)].some(w=>w)||qn(bO,\"beforeChange must return type `Promise<boolean>` or `boolean`\"),hs(C)?C.then(w=>{w&&p()}).catch(w=>{}):C&&p()},m=()=>{const b=f.value?e.activeColor:e.inactiveColor,C=s.value;e.borderColor?C.style.borderColor=e.borderColor:e.borderColor||(C.style.borderColor=b),C.style.backgroundColor=b,C.children[0].style.color=b},y=()=>{var b,C;(C=(b=l.value)==null?void 0:b.focus)==null||C.call(b)};return et(()=>{(e.activeColor||e.inactiveColor||e.borderColor)&&m(),l.value.checked=f.value}),{ns:a,input:l,core:s,switchDisabled:r,checked:f,switchKls:c,handleChange:p,switchValue:v,focus:y}}}),vpe=[\"aria-checked\",\"aria-disabled\"],mpe=[\"id\",\"name\",\"true-value\",\"false-value\",\"disabled\"],gpe=[\"aria-hidden\"],ype=[\"aria-hidden\"],bpe=[\"aria-hidden\"],Cpe=[\"aria-hidden\"];function wpe(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"loading\");return R(),X(\"div\",{class:U(e.switchKls),role:\"switch\",\"aria-checked\":e.checked,\"aria-disabled\":e.switchDisabled,onClick:t[2]||(t[2]=dt((...s)=>e.switchValue&&e.switchValue(...s),[\"prevent\"]))},[Z(\"input\",{id:e.id,ref:\"input\",class:U(e.ns.e(\"input\")),type:\"checkbox\",name:e.name,\"true-value\":e.activeValue,\"false-value\":e.inactiveValue,disabled:e.switchDisabled,onChange:t[0]||(t[0]=(...s)=>e.handleChange&&e.handleChange(...s)),onKeydown:t[1]||(t[1]=It((...s)=>e.switchValue&&e.switchValue(...s),[\"enter\"]))},null,42,mpe),!e.inlinePrompt&&(e.inactiveIcon||e.inactiveText)?(R(),X(\"span\",{key:0,class:U([e.ns.e(\"label\"),e.ns.em(\"label\",\"left\"),e.ns.is(\"active\",!e.checked)])},[e.inactiveIcon?(R(),fe(i,{key:0},{default:re(()=>[(R(),fe(Kt(e.inactiveIcon)))]),_:1})):se(\"v-if\",!0),!e.inactiveIcon&&e.inactiveText?(R(),X(\"span\",{key:1,\"aria-hidden\":e.checked},Me(e.inactiveText),9,gpe)):se(\"v-if\",!0)],2)):se(\"v-if\",!0),Z(\"span\",{ref:\"core\",class:U(e.ns.e(\"core\")),style:Xe({width:(e.width||40)+\"px\"})},[e.inlinePrompt?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"inner\"))},[e.activeIcon||e.inactiveIcon?(R(),X(Fe,{key:0},[e.activeIcon?(R(),fe(i,{key:0,class:U([e.ns.is(\"icon\"),e.checked?e.ns.is(\"show\"):e.ns.is(\"hide\")])},{default:re(()=>[(R(),fe(Kt(e.activeIcon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),e.inactiveIcon?(R(),fe(i,{key:1,class:U([e.ns.is(\"icon\"),e.checked?e.ns.is(\"hide\"):e.ns.is(\"show\")])},{default:re(()=>[(R(),fe(Kt(e.inactiveIcon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],64)):e.activeText||e.inactiveIcon?(R(),X(Fe,{key:1},[e.activeText?(R(),X(\"span\",{key:0,class:U([e.ns.is(\"text\"),e.checked?e.ns.is(\"show\"):e.ns.is(\"hide\")]),\"aria-hidden\":!e.checked},Me(e.activeText.substring(0,3)),11,ype)):se(\"v-if\",!0),e.inactiveText?(R(),X(\"span\",{key:1,class:U([e.ns.is(\"text\"),e.checked?e.ns.is(\"hide\"):e.ns.is(\"show\")]),\"aria-hidden\":e.checked},Me(e.inactiveText.substring(0,3)),11,bpe)):se(\"v-if\",!0)],64)):se(\"v-if\",!0)],2)):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.e(\"action\"))},[e.loading?(R(),fe(i,{key:0,class:U(e.ns.is(\"loading\"))},{default:re(()=>[g(l)]),_:1},8,[\"class\"])):se(\"v-if\",!0)],2)],6),!e.inlinePrompt&&(e.activeIcon||e.activeText)?(R(),X(\"span\",{key:1,class:U([e.ns.e(\"label\"),e.ns.em(\"label\",\"right\"),e.ns.is(\"active\",e.checked)])},[e.activeIcon?(R(),fe(i,{key:0},{default:re(()=>[(R(),fe(Kt(e.activeIcon)))]),_:1})):se(\"v-if\",!0),!e.activeIcon&&e.activeText?(R(),X(\"span\",{key:1,\"aria-hidden\":!e.checked},Me(e.activeText),9,Cpe)):se(\"v-if\",!0)],2)):se(\"v-if\",!0)],10,vpe)}var Spe=Ae(ppe,[[\"render\",wpe],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/switch/src/switch.vue\"]]);const kpe=xt(Spe);/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */var $pe=/[\"'&<>]/,Ope=Ppe;function Ppe(e){var t=\"\"+e,n=$pe.exec(t);if(!n)return t;var r,a=\"\",o=0,i=0;for(o=n.index;o<t.length;o++){switch(t.charCodeAt(o)){case 34:r=\"&quot;\";break;case 38:r=\"&amp;\";break;case 39:r=\"&#39;\";break;case 60:r=\"&lt;\";break;case 62:r=\"&gt;\";break;default:continue}i!==o&&(a+=t.substring(i,o)),i=o+1,a+=r}return i!==o?a+t.substring(i,o):a}const $y=function(e){let t=e.target;for(;t&&t.tagName.toUpperCase()!==\"HTML\";){if(t.tagName.toUpperCase()===\"TD\")return t;t=t.parentNode}return null},CO=function(e){return e!==null&&typeof e==\"object\"},Tpe=function(e,t,n,r,a){if(!t&&!r&&(!a||Array.isArray(a)&&!a.length))return e;typeof n==\"string\"?n=n===\"descending\"?-1:1:n=n&&n<0?-1:1;const o=r?null:function(l,s){return a?(Array.isArray(a)||(a=[a]),a.map(c=>typeof c==\"string\"?vn(l,c):c(l,s,e))):(t!==\"$key\"&&CO(l)&&\"$value\"in l&&(l=l.$value),[CO(l)?vn(l,t):l])},i=function(l,s){if(r)return r(l.value,s.value);for(let c=0,d=l.key.length;c<d;c++){if(l.key[c]<s.key[c])return-1;if(l.key[c]>s.key[c])return 1}return 0};return e.map((l,s)=>({value:l,index:s,key:o?o(l,s):null})).sort((l,s)=>{let c=i(l,s);return c||(c=l.index-s.index),c*+n}).map(l=>l.value)},J5=function(e,t){let n=null;return e.columns.forEach(r=>{r.id===t&&(n=r)}),n},xpe=function(e,t){let n=null;for(let r=0;r<e.columns.length;r++){const a=e.columns[r];if(a.columnKey===t){n=a;break}}return n},wO=function(e,t,n){const r=(t.className||\"\").match(new RegExp(`${n}-table_[^\\\\s]+`,\"gm\"));return r?J5(e,r[0]):null},gr=(e,t)=>{if(!e)throw new Error(\"Row is required when get row identity\");if(typeof t==\"string\"){if(!t.includes(\".\"))return`${e[t]}`;const n=t.split(\".\");let r=e;for(const a of n)r=r[a];return`${r}`}else if(typeof t==\"function\")return t.call(null,e)},Gl=function(e,t){const n={};return(e||[]).forEach((r,a)=>{n[gr(r,t)]={row:r,index:a}}),n};function _pe(e,t){const n={};let r;for(r in e)n[r]=e[r];for(r in t)if(Mt(t,r)){const a=t[r];typeof a!=\"undefined\"&&(n[r]=a)}return n}function gw(e){return e===\"\"||e!==void 0&&(e=Number.parseInt(e,10),Number.isNaN(e)&&(e=\"\")),e}function Q5(e){return e===\"\"||e!==void 0&&(e=gw(e),Number.isNaN(e)&&(e=80)),e}function j0(e){return typeof e==\"number\"?e:typeof e==\"string\"?/^\\d+(?:px)?$/.test(e)?Number.parseInt(e,10):e:null}function Epe(...e){return e.length===0?t=>t:e.length===1?e[0]:e.reduce((t,n)=>(...r)=>t(n(...r)))}function Tp(e,t,n){let r=!1;const a=e.indexOf(t),o=a!==-1,i=()=>{e.push(t),r=!0},l=()=>{e.splice(a,1),r=!0};return typeof n==\"boolean\"?n&&!o?i():!n&&o&&l():o?l():i(),r}function Mpe(e,t,n=\"children\",r=\"hasChildren\"){const a=i=>!(Array.isArray(i)&&i.length);function o(i,l,s){t(i,l,s),l.forEach(c=>{if(c[r]){t(c,null,s+1);return}const d=c[n];a(d)||o(c,d,s+1)})}e.forEach(i=>{if(i[r]){t(i,null,0);return}const l=i[n];a(l)||o(i,l,0)})}let $v;function Ipe(e,t,n,r){const{nextZIndex:a}=Pi();function o(){const f=r===\"light\",p=document.createElement(\"div\");return p.className=`el-popper ${f?\"is-light\":\"is-dark\"}`,t=Ope(t),p.innerHTML=t,p.style.zIndex=String(a()),document.body.appendChild(p),p}function i(){const f=document.createElement(\"div\");return f.className=\"el-popper__arrow\",f}function l(){s&&s.update()}$v=function f(){try{s&&s.destroy(),c&&document.body.removeChild(c),Bn(e,\"mouseenter\",l),Bn(e,\"mouseleave\",f)}catch{}};let s=null;const c=o(),d=i();return c.appendChild(d),s=lM(e,c,Te({modifiers:[{name:\"offset\",options:{offset:[0,8]}},{name:\"arrow\",options:{element:d,padding:10}}]},n)),gn(e,\"mouseenter\",l),gn(e,\"mouseleave\",$v),s}const eI=(e,t,n,r)=>{let a=0,o=e;if(r){if(r[e].colSpan>1)return{};for(let s=0;s<e;s++)a+=r[s].colSpan;o=a+r[e].colSpan-1}else a=e;let i;const l=n.states.columns;switch(t){case\"left\":o<n.states.fixedLeafColumnsLength.value&&(i=\"left\");break;case\"right\":a>=l.value.length-n.states.rightFixedLeafColumnsLength.value&&(i=\"right\");break;default:o<n.states.fixedLeafColumnsLength.value?i=\"left\":a>=l.value.length-n.states.rightFixedLeafColumnsLength.value&&(i=\"right\")}return i?{direction:i,start:a,after:o}:{}},yw=(e,t,n,r,a)=>{const o=[],{direction:i,start:l}=eI(t,n,r,a);if(i){const s=i===\"left\";o.push(`${e}-fixed-column--${i}`),s&&l===r.states.fixedLeafColumnsLength.value-1?o.push(\"is-last-column\"):!s&&l===r.states.columns.value.length-r.states.rightFixedLeafColumnsLength.value&&o.push(\"is-first-column\")}return o};function SO(e,t){return e+(t.realWidth===null||Number.isNaN(t.realWidth)?Number(t.width):t.realWidth)}const bw=(e,t,n,r)=>{const{direction:a,start:o=0}=eI(e,t,n,r);if(!a)return;const i={},l=a===\"left\",s=n.states.columns.value;return l?i.left=s.slice(0,e).reduce(SO,0):i.right=s.slice(o+1).reverse().reduce(SO,0),i},ec=(e,t)=>{!e||Number.isNaN(e[t])||(e[t]=`${e[t]}px`)};function Npe(e){const t=$t(),n=H(!1),r=H([]);return{updateExpandRows:()=>{const s=e.data.value||[],c=e.rowKey.value;if(n.value)r.value=s.slice();else if(c){const d=Gl(r.value,c);r.value=s.reduce((f,p)=>{const v=gr(p,c);return d[v]&&f.push(p),f},[])}else r.value=[]},toggleRowExpansion:(s,c)=>{Tp(r.value,s,c)&&t.emit(\"expand-change\",s,r.value.slice())},setExpandRowKeys:s=>{t.store.assertRowKey();const c=e.data.value||[],d=e.rowKey.value,f=Gl(c,d);r.value=s.reduce((p,v)=>{const m=f[v];return m&&p.push(m.row),p},[])},isRowExpanded:s=>{const c=e.rowKey.value;return c?!!Gl(r.value,c)[gr(s,c)]:r.value.includes(s)},states:{expandRows:r,defaultExpandAll:n}}}function Ape(e){const t=$t(),n=H(null),r=H(null),a=c=>{t.store.assertRowKey(),n.value=c,i(c)},o=()=>{n.value=null},i=c=>{const{data:d,rowKey:f}=e;let p=null;f.value&&(p=(A(d)||[]).find(v=>gr(v,f.value)===c)),r.value=p,t.emit(\"current-change\",r.value,null)};return{setCurrentRowKey:a,restoreCurrentRowKey:o,setCurrentRowByKey:i,updateCurrentRow:c=>{const d=r.value;if(c&&c!==d){r.value=c,t.emit(\"current-change\",r.value,d);return}!c&&d&&(r.value=null,t.emit(\"current-change\",null,d))},updateCurrentRowData:()=>{const c=e.rowKey.value,d=e.data.value||[],f=r.value;if(!d.includes(f)&&f){if(c){const p=gr(f,c);i(p)}else r.value=null;r.value===null&&t.emit(\"current-change\",null,f)}else n.value&&(i(n.value),o())},states:{_currentRowKey:n,currentRow:r}}}function Dpe(e){const t=H([]),n=H({}),r=H(16),a=H(!1),o=H({}),i=H(\"hasChildren\"),l=H(\"children\"),s=$t(),c=x(()=>{if(!e.rowKey.value)return{};const C=e.data.value||[];return f(C)}),d=x(()=>{const C=e.rowKey.value,S=Object.keys(o.value),w={};return S.length&&S.forEach(k=>{if(o.value[k].length){const $={children:[]};o.value[k].forEach(O=>{const T=gr(O,C);$.children.push(T),O[i.value]&&!w[T]&&(w[T]={children:[]})}),w[k]=$}}),w}),f=C=>{const S=e.rowKey.value,w={};return Mpe(C,(k,$,O)=>{const T=gr(k,S);Array.isArray($)?w[T]={children:$.map(_=>gr(_,S)),level:O}:a.value&&(w[T]={children:[],lazy:!0,level:O})},l.value,i.value),w},p=(C=!1,S=(w=>(w=s.store)==null?void 0:w.states.defaultExpandAll.value)())=>{var w;const k=c.value,$=d.value,O=Object.keys(k),T={};if(O.length){const _=A(n),I=[],L=(F,N)=>{if(C)return t.value?S||t.value.includes(N):!!(S||(F==null?void 0:F.expanded));{const D=S||t.value&&t.value.includes(N);return!!((F==null?void 0:F.expanded)||D)}};O.forEach(F=>{const N=_[F],D=Te({},k[F]);if(D.expanded=L(N,F),D.lazy){const{loaded:z=!1,loading:B=!1}=N||{};D.loaded=!!z,D.loading=!!B,I.push(F)}T[F]=D});const j=Object.keys($);a.value&&j.length&&I.length&&j.forEach(F=>{const N=_[F],D=$[F].children;if(I.includes(F)){if(T[F].children.length!==0)throw new Error(\"[ElTable]children must be an empty array.\");T[F].children=D}else{const{loaded:z=!1,loading:B=!1}=N||{};T[F]={lazy:!0,loaded:!!z,loading:!!B,expanded:L(N,F),children:D,level:\"\"}}})}n.value=T,(w=s.store)==null||w.updateTableScrollY()};ce(()=>t.value,()=>{p(!0)}),ce(()=>c.value,()=>{p()}),ce(()=>d.value,()=>{p()});const v=C=>{t.value=C,p()},m=(C,S)=>{s.store.assertRowKey();const w=e.rowKey.value,k=gr(C,w),$=k&&n.value[k];if(k&&$&&\"expanded\"in $){const O=$.expanded;S=typeof S==\"undefined\"?!$.expanded:S,n.value[k].expanded=S,O!==S&&s.emit(\"expand-change\",C,S),s.store.updateTableScrollY()}},y=C=>{s.store.assertRowKey();const S=e.rowKey.value,w=gr(C,S),k=n.value[w];a.value&&k&&\"loaded\"in k&&!k.loaded?b(C,w,k):m(C,void 0)},b=(C,S,w)=>{const{load:k}=s.props;k&&!n.value[S].loaded&&(n.value[S].loading=!0,k(C,w,$=>{if(!Array.isArray($))throw new TypeError(\"[ElTable] data must be an array\");n.value[S].loading=!1,n.value[S].loaded=!0,n.value[S].expanded=!0,$.length&&(o.value[S]=$),s.emit(\"expand-change\",C,!0)}))};return{loadData:b,loadOrToggle:y,toggleTreeExpansion:m,updateTreeExpandKeys:v,updateTreeData:p,normalize:f,states:{expandRowKeys:t,treeData:n,indent:r,lazy:a,lazyTreeNodeMap:o,lazyColumnIdentifier:i,childrenColumnName:l}}}const Rpe=(e,t)=>{const n=t.sortingColumn;return!n||typeof n.sortable==\"string\"?e:Tpe(e,t.sortProp,t.sortOrder,n.sortMethod,n.sortBy)},xp=e=>{const t=[];return e.forEach(n=>{n.children?t.push.apply(t,xp(n.children)):t.push(n)}),t};function Lpe(){var e;const t=$t(),{size:n}=or((e=t.proxy)==null?void 0:e.$props),r=H(null),a=H([]),o=H([]),i=H(!1),l=H([]),s=H([]),c=H([]),d=H([]),f=H([]),p=H([]),v=H([]),m=H([]),y=H(0),b=H(0),C=H(0),S=H(!1),w=H([]),k=H(!1),$=H(!1),O=H(null),T=H({}),_=H(null),I=H(null),L=H(null),j=H(null),F=H(null);ce(a,()=>t.state&&z(!1),{deep:!0});const N=()=>{if(!r.value)throw new Error(\"[ElTable] prop row-key is required\")},D=()=>{d.value=l.value.filter(Ve=>Ve.fixed===!0||Ve.fixed===\"left\"),f.value=l.value.filter(Ve=>Ve.fixed===\"right\"),d.value.length>0&&l.value[0]&&l.value[0].type===\"selection\"&&!l.value[0].fixed&&(l.value[0].fixed=!0,d.value.unshift(l.value[0]));const Ye=l.value.filter(Ve=>!Ve.fixed);s.value=[].concat(d.value).concat(Ye).concat(f.value);const he=xp(Ye),_e=xp(d.value),$e=xp(f.value);y.value=he.length,b.value=_e.length,C.value=$e.length,c.value=[].concat(_e).concat(he).concat($e),i.value=d.value.length>0||f.value.length>0},z=(Ye,he=!1)=>{Ye&&D(),he?t.state.doLayout():t.state.debouncedUpdateLayout()},B=Ye=>w.value.includes(Ye),M=()=>{S.value=!1,w.value.length&&(w.value=[],t.emit(\"selection-change\",[]))},E=()=>{let Ye;if(r.value){Ye=[];const he=Gl(w.value,r.value),_e=Gl(a.value,r.value);for(const $e in he)Mt(he,$e)&&!_e[$e]&&Ye.push(he[$e].row)}else Ye=w.value.filter(he=>!a.value.includes(he));if(Ye.length){const he=w.value.filter(_e=>!Ye.includes(_e));w.value=he,t.emit(\"selection-change\",he.slice())}},K=()=>(w.value||[]).slice(),W=(Ye,he=void 0,_e=!0)=>{if(Tp(w.value,Ye,he)){const Ve=(w.value||[]).slice();_e&&t.emit(\"select\",Ve,Ye),t.emit(\"selection-change\",Ve)}},Y=()=>{var Ye,he;const _e=$.value?!S.value:!(S.value||w.value.length);S.value=_e;let $e=!1,Ve=0;const st=(he=(Ye=t==null?void 0:t.store)==null?void 0:Ye.states)==null?void 0:he.rowKey.value;a.value.forEach((Dt,Ut)=>{const Ft=Ut+Ve;O.value?O.value.call(null,Dt,Ft)&&Tp(w.value,Dt,_e)&&($e=!0):Tp(w.value,Dt,_e)&&($e=!0),Ve+=ne(gr(Dt,st))}),$e&&t.emit(\"selection-change\",w.value?w.value.slice():[]),t.emit(\"select-all\",w.value)},q=()=>{const Ye=Gl(w.value,r.value);a.value.forEach(he=>{const _e=gr(he,r.value),$e=Ye[_e];$e&&(w.value[$e.index]=he)})},J=()=>{var Ye,he,_e;if(((Ye=a.value)==null?void 0:Ye.length)===0){S.value=!1;return}let $e;r.value&&($e=Gl(w.value,r.value));const Ve=function(Ft){return $e?!!$e[gr(Ft,r.value)]:w.value.includes(Ft)};let st=!0,Dt=0,Ut=0;for(let Ft=0,Jt=(a.value||[]).length;Ft<Jt;Ft++){const Mn=(_e=(he=t==null?void 0:t.store)==null?void 0:he.states)==null?void 0:_e.rowKey.value,tr=Ft+Ut,nr=a.value[Ft],Va=O.value&&O.value.call(null,nr,tr);if(Ve(nr))Dt++;else if(!O.value||Va){st=!1;break}Ut+=ne(gr(nr,Mn))}Dt===0&&(st=!1),S.value=st},ne=Ye=>{var he;if(!t||!t.store)return 0;const{treeData:_e}=t.store.states;let $e=0;const Ve=(he=_e.value[Ye])==null?void 0:he.children;return Ve&&($e+=Ve.length,Ve.forEach(st=>{$e+=ne(st)})),$e},oe=(Ye,he)=>{Array.isArray(Ye)||(Ye=[Ye]);const _e={};return Ye.forEach($e=>{T.value[$e.id]=he,_e[$e.columnKey||$e.id]=he}),_e},Q=(Ye,he,_e)=>{I.value&&I.value!==Ye&&(I.value.order=null),I.value=Ye,L.value=he,j.value=_e},ae=()=>{let Ye=A(o);Object.keys(T.value).forEach(he=>{const _e=T.value[he];if(!_e||_e.length===0)return;const $e=J5({columns:c.value},he);$e&&$e.filterMethod&&(Ye=Ye.filter(Ve=>_e.some(st=>$e.filterMethod.call(null,st,Ve,$e))))}),_.value=Ye},de=()=>{a.value=Rpe(_.value,{sortingColumn:I.value,sortProp:L.value,sortOrder:j.value})},be=(Ye=void 0)=>{Ye&&Ye.filter||ae(),de()},Ee=Ye=>{const{tableHeaderRef:he}=t.refs;if(!he)return;const _e=Object.assign({},he.filterPanels),$e=Object.keys(_e);if(!!$e.length)if(typeof Ye==\"string\"&&(Ye=[Ye]),Array.isArray(Ye)){const Ve=Ye.map(st=>xpe({columns:c.value},st));$e.forEach(st=>{const Dt=Ve.find(Ut=>Ut.id===st);Dt&&(Dt.filteredValue=[])}),t.store.commit(\"filterChange\",{column:Ve,values:[],silent:!0,multi:!0})}else $e.forEach(Ve=>{const st=c.value.find(Dt=>Dt.id===Ve);st&&(st.filteredValue=[])}),T.value={},t.store.commit(\"filterChange\",{column:{},values:[],silent:!0})},Pe=()=>{!I.value||(Q(null,null,null),t.store.commit(\"changeSortCondition\",{silent:!0}))},{setExpandRowKeys:Be,toggleRowExpansion:te,updateExpandRows:ie,states:ge,isRowExpanded:ke}=Npe({data:a,rowKey:r}),{updateTreeExpandKeys:xe,toggleTreeExpansion:Ie,updateTreeData:ye,loadOrToggle:pe,states:ue}=Dpe({data:a,rowKey:r}),{updateCurrentRowData:Ce,updateCurrentRow:je,setCurrentRowKey:ee,states:me}=Ape({data:a,rowKey:r});return{assertRowKey:N,updateColumns:D,scheduleLayout:z,isSelected:B,clearSelection:M,cleanSelection:E,getSelectionRows:K,toggleRowSelection:W,_toggleAllSelection:Y,toggleAllSelection:null,updateSelectionByRowKey:q,updateAllSelected:J,updateFilters:oe,updateCurrentRow:je,updateSort:Q,execFilter:ae,execSort:de,execQuery:be,clearFilter:Ee,clearSort:Pe,toggleRowExpansion:te,setExpandRowKeysAdapter:Ye=>{Be(Ye),xe(Ye)},setCurrentRowKey:ee,toggleRowExpansionAdapter:(Ye,he)=>{c.value.some(({type:$e})=>$e===\"expand\")?te(Ye,he):Ie(Ye,he)},isRowExpanded:ke,updateExpandRows:ie,updateCurrentRowData:Ce,loadOrToggle:pe,updateTreeData:ye,states:Te(Te(Te({tableSize:n,rowKey:r,data:a,_data:o,isComplex:i,_columns:l,originColumns:s,columns:c,fixedColumns:d,rightFixedColumns:f,leafColumns:p,fixedLeafColumns:v,rightFixedLeafColumns:m,leafColumnsLength:y,fixedLeafColumnsLength:b,rightFixedLeafColumnsLength:C,isAllSelected:S,selection:w,reserveSelection:k,selectOnIndeterminate:$,selectable:O,filters:T,filteredData:_,sortingColumn:I,sortProp:L,sortOrder:j,hoverRow:F},ge),ue),me)}}function K0(e,t){return e.map(n=>{var r;return n.id===t.id?t:((r=n.children)!=null&&r.length&&(n.children=K0(n.children,t)),n)})}function tI(e){e.forEach(t=>{var n,r;t.no=(n=t.getColumnIndex)==null?void 0:n.call(t),(r=t.children)!=null&&r.length&&tI(t.children)}),e.sort((t,n)=>t.no-n.no)}function Fpe(){const e=$t(),t=Lpe(),n=De(\"table\"),r={setData(i,l){const s=A(i._data)!==l;i.data.value=l,i._data.value=l,e.store.execQuery(),e.store.updateCurrentRowData(),e.store.updateExpandRows(),e.store.updateTreeData(e.store.states.defaultExpandAll.value),A(i.reserveSelection)?(e.store.assertRowKey(),e.store.updateSelectionByRowKey()):s?e.store.clearSelection():e.store.cleanSelection(),e.store.updateAllSelected(),e.$ready&&e.store.scheduleLayout()},insertColumn(i,l,s){const c=A(i._columns);let d=[];s?(s&&!s.children&&(s.children=[]),s.children.push(l),d=K0(c,s)):(c.push(l),d=c),tI(d),i._columns.value=d,l.type===\"selection\"&&(i.selectable.value=l.selectable,i.reserveSelection.value=l.reserveSelection),e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},removeColumn(i,l,s){const c=A(i._columns)||[];if(s)s.children.splice(s.children.findIndex(d=>d.id===l.id),1),s.children.length===0&&delete s.children,i._columns.value=K0(c,s);else{const d=c.indexOf(l);d>-1&&(c.splice(d,1),i._columns.value=c)}e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},sort(i,l){const{prop:s,order:c,init:d}=l;if(s){const f=A(i.columns).find(p=>p.property===s);f&&(f.order=c,e.store.updateSort(f,s,c),e.store.commit(\"changeSortCondition\",{init:d}))}},changeSortCondition(i,l){const{sortingColumn:s,sortProp:c,sortOrder:d}=i;A(d)===null&&(i.sortingColumn.value=null,i.sortProp.value=null);const f={filter:!0};e.store.execQuery(f),(!l||!(l.silent||l.init))&&e.emit(\"sort-change\",{column:A(s),prop:A(c),order:A(d)}),e.store.updateTableScrollY()},filterChange(i,l){const{column:s,values:c,silent:d}=l,f=e.store.updateFilters(s,c);e.store.execQuery(),d||e.emit(\"filter-change\",f),e.store.updateTableScrollY()},toggleAllSelection(){e.store.toggleAllSelection()},rowSelectedChanged(i,l){e.store.toggleRowSelection(l),e.store.updateAllSelected()},setHoverRow(i,l){i.hoverRow.value=l},setCurrentRow(i,l){e.store.updateCurrentRow(l)}},a=function(i,...l){const s=e.store.mutations;if(s[i])s[i].apply(e,[e.store.states].concat(l));else throw new Error(`Action not found: ${i}`)},o=function(){Ne(()=>e.layout.updateScrollY.apply(e.layout))};return Ke(Te({ns:n},t),{mutations:r,commit:a,updateTableScrollY:o})}const wd={rowKey:\"rowKey\",defaultExpandAll:\"defaultExpandAll\",selectOnIndeterminate:\"selectOnIndeterminate\",indent:\"indent\",lazy:\"lazy\",data:\"data\",[\"treeProps.hasChildren\"]:{key:\"lazyColumnIdentifier\",default:\"hasChildren\"},[\"treeProps.children\"]:{key:\"childrenColumnName\",default:\"children\"}};function Bpe(e,t){if(!e)throw new Error(\"Table is required.\");const n=Fpe();return n.toggleAllSelection=Yn(n._toggleAllSelection,10),Object.keys(wd).forEach(r=>{nI(rI(t,r),r,n)}),Vpe(n,t),n}function Vpe(e,t){Object.keys(wd).forEach(n=>{ce(()=>rI(t,n),r=>{nI(r,n,e)})})}function nI(e,t,n){let r=e,a=wd[t];typeof wd[t]==\"object\"&&(a=a.key,r=r||wd[t].default),n.states[a].value=r}function rI(e,t){if(t.includes(\".\")){const n=t.split(\".\");let r=e;return n.forEach(a=>{r=r[a]}),r}else return e[t]}class zpe{constructor(t){this.observers=[],this.table=null,this.store=null,this.columns=[],this.fit=!0,this.showHeader=!0,this.height=H(null),this.scrollX=H(!1),this.scrollY=H(!1),this.bodyWidth=H(null),this.fixedWidth=H(null),this.rightFixedWidth=H(null),this.tableHeight=H(null),this.headerHeight=H(44),this.appendHeight=H(0),this.footerHeight=H(44),this.viewportHeight=H(null),this.bodyHeight=H(null),this.bodyScrollHeight=H(0),this.fixedBodyHeight=H(null),this.gutterWidth=0;for(const n in t)Mt(t,n)&&(_n(this[n])?this[n].value=t[n]:this[n]=t[n]);if(!this.table)throw new Error(\"Table is required for Table Layout\");if(!this.store)throw new Error(\"Store is required for Table Layout\")}updateScrollY(){if(this.height.value===null)return!1;const n=this.table.refs.bodyWrapper;if(this.table.vnode.el&&n){let r=!0;const a=this.scrollY.value;return this.bodyHeight.value===null?r=!1:r=n.scrollHeight>this.bodyHeight.value,this.scrollY.value=r,a!==r}return!1}setHeight(t,n=\"height\"){if(!Bt)return;const r=this.table.vnode.el;if(t=j0(t),this.height.value=Number(t),!r&&(t||t===0))return Ne(()=>this.setHeight(t,n));typeof t==\"number\"?(r.style[n]=`${t}px`,this.updateElsHeight()):typeof t==\"string\"&&(r.style[n]=t,this.updateElsHeight())}setMaxHeight(t){this.setHeight(t,\"max-height\")}getFlattenColumns(){const t=[];return this.table.store.states.columns.value.forEach(r=>{r.isColumnGroup?t.push.apply(t,r.columns):t.push(r)}),t}updateElsHeight(){var t,n;if(!this.table.$ready)return Ne(()=>this.updateElsHeight());const{tableWrapper:r,headerWrapper:a,appendWrapper:o,footerWrapper:i,tableHeader:l,tableBody:s}=this.table.refs;if(r&&r.style.display===\"none\")return;const{tableLayout:c}=this.table.props;if(this.appendHeight.value=o?o.offsetHeight:0,this.showHeader&&!a&&c===\"fixed\")return;const d=l||null,f=this.headerDisplayNone(d),p=(a==null?void 0:a.offsetHeight)||0,v=this.headerHeight.value=this.showHeader?p:0;if(this.showHeader&&!f&&p>0&&(this.table.store.states.columns.value||[]).length>0&&v<2)return Ne(()=>this.updateElsHeight());const m=this.tableHeight.value=(n=(t=this.table)==null?void 0:t.vnode.el)==null?void 0:n.clientHeight,y=this.footerHeight.value=i?i.offsetHeight:0;this.height.value!==null&&(this.bodyHeight.value===null&&requestAnimationFrame(()=>this.updateElsHeight()),this.bodyHeight.value=m-v-y+(i?1:0),this.bodyScrollHeight.value=s==null?void 0:s.scrollHeight),this.fixedBodyHeight.value=this.scrollX.value?this.bodyHeight.value-this.gutterWidth:this.bodyHeight.value,this.viewportHeight.value=this.scrollX.value?m-this.gutterWidth:m,this.updateScrollY(),this.notifyObservers(\"scrollable\")}headerDisplayNone(t){if(!t)return!0;let n=t;for(;n.tagName!==\"DIV\";){if(getComputedStyle(n).display===\"none\")return!0;n=n.parentElement}return!1}updateColumnsWidth(){if(!Bt)return;const t=this.fit,n=this.table.vnode.el.clientWidth;let r=0;const a=this.getFlattenColumns(),o=a.filter(s=>typeof s.width!=\"number\");if(a.forEach(s=>{typeof s.width==\"number\"&&s.realWidth&&(s.realWidth=null)}),o.length>0&&t){if(a.forEach(s=>{r+=Number(s.width||s.minWidth||80)}),r<=n){this.scrollX.value=!1;const s=n-r;if(o.length===1)o[0].realWidth=Number(o[0].minWidth||80)+s;else{const c=o.reduce((p,v)=>p+Number(v.minWidth||80),0),d=s/c;let f=0;o.forEach((p,v)=>{if(v===0)return;const m=Math.floor(Number(p.minWidth||80)*d);f+=m,p.realWidth=Number(p.minWidth||80)+m}),o[0].realWidth=Number(o[0].minWidth||80)+s-f}}else this.scrollX.value=!0,o.forEach(s=>{s.realWidth=Number(s.minWidth)});this.bodyWidth.value=Math.max(r,n),this.table.state.resizeState.value.width=this.bodyWidth.value}else a.forEach(s=>{!s.width&&!s.minWidth?s.realWidth=80:s.realWidth=Number(s.width||s.minWidth),r+=s.realWidth}),this.scrollX.value=r>n,this.bodyWidth.value=r;const i=this.store.states.fixedColumns.value;if(i.length>0){let s=0;i.forEach(c=>{s+=Number(c.realWidth||c.width)}),this.fixedWidth.value=s}const l=this.store.states.rightFixedColumns.value;if(l.length>0){let s=0;l.forEach(c=>{s+=Number(c.realWidth||c.width)}),this.rightFixedWidth.value=s}this.notifyObservers(\"columns\")}addObserver(t){this.observers.push(t)}removeObserver(t){const n=this.observers.indexOf(t);n!==-1&&this.observers.splice(n,1)}notifyObservers(t){this.observers.forEach(r=>{var a,o;switch(t){case\"columns\":(a=r.state)==null||a.onColumnsChange(this);break;case\"scrollable\":(o=r.state)==null||o.onScrollableChange(this);break;default:throw new Error(`Table Layout don't have event ${t}.`)}})}}const{CheckboxGroup:Hpe}=io,jpe=G({name:\"ElTableFilterPanel\",components:{ElCheckbox:io,ElCheckboxGroup:Hpe,ElScrollbar:xi,ElTooltip:Ur,ElIcon:ft,ArrowDown:_s,ArrowUp:Of},directives:{ClickOutside:Is},props:{placement:{type:String,default:\"bottom-start\"},store:{type:Object},column:{type:Object},upDataColumn:{type:Function}},setup(e){const t=$t(),{t:n}=ln(),r=De(\"table-filter\"),a=t==null?void 0:t.parent;a.filterPanels.value[e.column.id]||(a.filterPanels.value[e.column.id]=t);const o=H(!1),i=H(null),l=x(()=>e.column&&e.column.filters),s=x({get:()=>{var k;return(((k=e.column)==null?void 0:k.filteredValue)||[])[0]},set:k=>{c.value&&(typeof k!=\"undefined\"&&k!==null?c.value.splice(0,1,k):c.value.splice(0,1))}}),c=x({get(){return e.column?e.column.filteredValue||[]:[]},set(k){e.column&&e.upDataColumn(\"filteredValue\",k)}}),d=x(()=>e.column?e.column.filterMultiple:!0),f=k=>k.value===s.value,p=()=>{o.value=!1},v=k=>{k.stopPropagation(),o.value=!o.value},m=()=>{o.value=!1},y=()=>{S(c.value),p()},b=()=>{c.value=[],S(c.value),p()},C=k=>{s.value=k,S(typeof k!=\"undefined\"&&k!==null?c.value:[]),p()},S=k=>{e.store.commit(\"filterChange\",{column:e.column,values:k}),e.store.updateAllSelected()};ce(o,k=>{e.column&&e.upDataColumn(\"filterOpened\",k)},{immediate:!0});const w=x(()=>{var k,$;return($=(k=i.value)==null?void 0:k.popperRef)==null?void 0:$.contentRef});return{tooltipVisible:o,multiple:d,filteredValue:c,filterValue:s,filters:l,handleConfirm:y,handleReset:b,handleSelect:C,isActive:f,t:n,ns:r,showFilterPanel:v,hideFilterPanel:m,popperPaneRef:w,tooltip:i}}}),Kpe={key:0},Wpe=[\"disabled\"],Upe=[\"label\",\"onClick\"];function Ype(e,t,n,r,a,o){const i=we(\"el-checkbox\"),l=we(\"el-checkbox-group\"),s=we(\"el-scrollbar\"),c=we(\"arrow-up\"),d=we(\"arrow-down\"),f=we(\"el-icon\"),p=we(\"el-tooltip\"),v=pa(\"click-outside\");return R(),fe(p,{ref:\"tooltip\",visible:e.tooltipVisible,\"onUpdate:visible\":t[5]||(t[5]=m=>e.tooltipVisible=m),offset:0,placement:e.placement,\"show-arrow\":!1,\"stop-popper-mouse-event\":!1,\"append-to-body\":\"\",effect:\"light\",pure:\"\",\"popper-class\":e.ns.b(),persistent:\"\"},{content:re(()=>[e.multiple?(R(),X(\"div\",Kpe,[Z(\"div\",{class:U(e.ns.e(\"content\"))},[g(s,{\"wrap-class\":e.ns.e(\"wrap\")},{default:re(()=>[g(l,{modelValue:e.filteredValue,\"onUpdate:modelValue\":t[0]||(t[0]=m=>e.filteredValue=m),class:U(e.ns.e(\"checkbox-group\"))},{default:re(()=>[(R(!0),X(Fe,null,Rt(e.filters,m=>(R(),fe(i,{key:m.value,label:m.value},{default:re(()=>[yt(Me(m.text),1)]),_:2},1032,[\"label\"]))),128))]),_:1},8,[\"modelValue\",\"class\"])]),_:1},8,[\"wrap-class\"])],2),Z(\"div\",{class:U(e.ns.e(\"bottom\"))},[Z(\"button\",{class:U({[e.ns.is(\"disabled\")]:e.filteredValue.length===0}),disabled:e.filteredValue.length===0,type:\"button\",onClick:t[1]||(t[1]=(...m)=>e.handleConfirm&&e.handleConfirm(...m))},Me(e.t(\"el.table.confirmFilter\")),11,Wpe),Z(\"button\",{type:\"button\",onClick:t[2]||(t[2]=(...m)=>e.handleReset&&e.handleReset(...m))},Me(e.t(\"el.table.resetFilter\")),1)],2)])):(R(),X(\"ul\",{key:1,class:U(e.ns.e(\"list\"))},[Z(\"li\",{class:U([e.ns.e(\"list-item\"),{[e.ns.is(\"active\")]:e.filterValue===void 0||e.filterValue===null}]),onClick:t[3]||(t[3]=m=>e.handleSelect(null))},Me(e.t(\"el.table.clearFilter\")),3),(R(!0),X(Fe,null,Rt(e.filters,m=>(R(),X(\"li\",{key:m.value,class:U([e.ns.e(\"list-item\"),e.ns.is(\"active\",e.isActive(m))]),label:m.value,onClick:y=>e.handleSelect(m.value)},Me(m.text),11,Upe))),128))],2))]),default:re(()=>[at((R(),X(\"span\",{class:U([`${e.ns.namespace.value}-table__column-filter-trigger`,`${e.ns.namespace.value}-none-outline`]),onClick:t[4]||(t[4]=(...m)=>e.showFilterPanel&&e.showFilterPanel(...m))},[g(f,null,{default:re(()=>[e.column.filterOpened?(R(),fe(c,{key:0})):(R(),fe(d,{key:1}))]),_:1})],2)),[[v,e.hideFilterPanel,e.popperPaneRef]])]),_:1},8,[\"visible\",\"placement\",\"popper-class\"])}var qpe=Ae(jpe,[[\"render\",Ype],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/table/src/filter-panel.vue\"]]);function aI(e){const t=$t();hc(()=>{n.value.addObserver(t)}),et(()=>{r(n.value),a(n.value)}),ur(()=>{r(n.value),a(n.value)}),Wr(()=>{n.value.removeObserver(t)});const n=x(()=>{const o=e.layout;if(!o)throw new Error(\"Can not find table layout.\");return o}),r=o=>{var i;const l=((i=e.vnode.el)==null?void 0:i.querySelectorAll(\"colgroup > col\"))||[];if(!l.length)return;const s=o.getFlattenColumns(),c={};s.forEach(d=>{c[d.id]=d});for(let d=0,f=l.length;d<f;d++){const p=l[d],v=p.getAttribute(\"name\"),m=c[v];m&&p.setAttribute(\"width\",m.realWidth||m.width)}},a=o=>{var i,l;const s=((i=e.vnode.el)==null?void 0:i.querySelectorAll(\"colgroup > col[name=gutter]\"))||[];for(let d=0,f=s.length;d<f;d++)s[d].setAttribute(\"width\",o.scrollY.value?o.gutterWidth:\"0\");const c=((l=e.vnode.el)==null?void 0:l.querySelectorAll(\"th.gutter\"))||[];for(let d=0,f=c.length;d<f;d++){const p=c[d];p.style.width=o.scrollY.value?`${o.gutterWidth}px`:\"0\",p.style.display=o.scrollY.value?\"\":\"none\"}};return{tableLayout:n.value,onColumnsChange:r,onScrollableChange:a}}const Vo=Symbol(\"ElTable\");function Gpe(e,t){const n=$t(),r=ve(Vo),a=y=>{y.stopPropagation()},o=(y,b)=>{!b.filters&&b.sortable?m(y,b,!1):b.filterable&&!b.sortable&&a(y),r==null||r.emit(\"header-click\",b,y)},i=(y,b)=>{r==null||r.emit(\"header-contextmenu\",b,y)},l=H(null),s=H(!1),c=H({}),d=(y,b)=>{if(!!Bt&&!(b.children&&b.children.length>0)&&l.value&&e.border){s.value=!0;const C=r;t(\"set-drag-visible\",!0);const w=(C==null?void 0:C.vnode.el).getBoundingClientRect().left,k=n.vnode.el.querySelector(`th.${b.id}`),$=k.getBoundingClientRect(),O=$.left-w+30;xo(k,\"noclick\"),c.value={startMouseLeft:y.clientX,startLeft:$.right-w,startColumnLeft:$.left-w,tableLeft:w};const T=C==null?void 0:C.refs.resizeProxy;T.style.left=`${c.value.startLeft}px`,document.onselectstart=function(){return!1},document.ondragstart=function(){return!1};const _=L=>{const j=L.clientX-c.value.startMouseLeft,F=c.value.startLeft+j;T.style.left=`${Math.max(O,F)}px`},I=()=>{if(s.value){const{startColumnLeft:L,startLeft:j}=c.value,N=Number.parseInt(T.style.left,10)-L;b.width=b.realWidth=N,C==null||C.emit(\"header-dragend\",b.width,j-L,b,y),requestAnimationFrame(()=>{e.store.scheduleLayout(!1,!0)}),document.body.style.cursor=\"\",s.value=!1,l.value=null,c.value={},t(\"set-drag-visible\",!1)}document.removeEventListener(\"mousemove\",_),document.removeEventListener(\"mouseup\",I),document.onselectstart=null,document.ondragstart=null,setTimeout(()=>{Br(k,\"noclick\")},0)};document.addEventListener(\"mousemove\",_),document.addEventListener(\"mouseup\",I)}},f=(y,b)=>{if(b.children&&b.children.length>0)return;let C=y.target;for(;C&&C.tagName!==\"TH\";)C=C.parentNode;if(!(!b||!b.resizable)&&!s.value&&e.border){const S=C.getBoundingClientRect(),w=document.body.style;S.width>12&&S.right-y.pageX<8?(w.cursor=\"col-resize\",to(C,\"is-sortable\")&&(C.style.cursor=\"col-resize\"),l.value=b):s.value||(w.cursor=\"\",to(C,\"is-sortable\")&&(C.style.cursor=\"pointer\"),l.value=null)}},p=()=>{!Bt||(document.body.style.cursor=\"\")},v=({order:y,sortOrders:b})=>{if(y===\"\")return b[0];const C=b.indexOf(y||null);return b[C>b.length-2?0:C+1]},m=(y,b,C)=>{y.stopPropagation();const S=b.order===C?null:C||v(b);let w=y.target;for(;w&&w.tagName!==\"TH\";)w=w.parentNode;if(w&&w.tagName===\"TH\"&&to(w,\"noclick\")){Br(w,\"noclick\");return}if(!b.sortable)return;const k=e.store.states;let $=k.sortProp.value,O;const T=k.sortingColumn.value;(T!==b||T===b&&T.order===null)&&(T&&(T.order=null),k.sortingColumn.value=b,$=b.property),S?O=b.order=S:O=b.order=null,k.sortProp.value=$,k.sortOrder.value=O,r==null||r.store.commit(\"changeSortCondition\")};return{handleHeaderClick:o,handleHeaderContextMenu:i,handleMouseDown:d,handleMouseMove:f,handleMouseOut:p,handleSortClick:m,handleFilterClick:a}}function Xpe(e){const t=ve(Vo),n=De(\"table\");return{getHeaderRowStyle:l=>{const s=t==null?void 0:t.props.headerRowStyle;return typeof s==\"function\"?s.call(null,{rowIndex:l}):s},getHeaderRowClass:l=>{const s=[],c=t==null?void 0:t.props.headerRowClassName;return typeof c==\"string\"?s.push(c):typeof c==\"function\"&&s.push(c.call(null,{rowIndex:l})),s.join(\" \")},getHeaderCellStyle:(l,s,c,d)=>{var f;let p=(f=t==null?void 0:t.props.headerCellStyle)!=null?f:{};typeof p==\"function\"&&(p=p.call(null,{rowIndex:l,columnIndex:s,row:c,column:d}));const v=d.isSubColumn?null:bw(s,d.fixed,e.store,c);return ec(v,\"left\"),ec(v,\"right\"),Object.assign({},p,v)},getHeaderCellClass:(l,s,c,d)=>{const f=d.isSubColumn?[]:yw(n.b(),s,d.fixed,e.store,c),p=[d.id,d.order,d.headerAlign,d.className,d.labelClassName,...f];d.children||p.push(\"is-leaf\"),d.sortable&&p.push(\"is-sortable\");const v=t==null?void 0:t.props.headerCellClassName;return typeof v==\"string\"?p.push(v):typeof v==\"function\"&&p.push(v.call(null,{rowIndex:l,columnIndex:s,row:c,column:d})),p.push(n.e(\"cell\")),p.filter(m=>Boolean(m)).join(\" \")}}}const oI=e=>{const t=[];return e.forEach(n=>{n.children?(t.push(n),t.push.apply(t,oI(n.children))):t.push(n)}),t},Zpe=e=>{let t=1;const n=(o,i)=>{if(i&&(o.level=i.level+1,t<o.level&&(t=o.level)),o.children){let l=0;o.children.forEach(s=>{n(s,o),l+=s.colSpan}),o.colSpan=l}else o.colSpan=1};e.forEach(o=>{o.level=1,n(o,void 0)});const r=[];for(let o=0;o<t;o++)r.push([]);return oI(e).forEach(o=>{o.children?(o.rowSpan=1,o.children.forEach(i=>i.isSubColumn=!0)):o.rowSpan=t-o.level+1,r[o.level-1].push(o)}),r};function Jpe(e){const t=ve(Vo),n=x(()=>Zpe(e.store.states.originColumns.value));return{isGroup:x(()=>{const o=n.value.length>1;return o&&t&&(t.state.isGroup.value=!0),o}),toggleAllSelection:o=>{o.stopPropagation(),t==null||t.store.commit(\"toggleAllSelection\")},columnRows:n}}var Qpe=G({name:\"ElTableHeader\",components:{ElCheckbox:io},props:{fixed:{type:String,default:\"\"},store:{required:!0,type:Object},border:Boolean,defaultSort:{type:Object,default:()=>({prop:\"\",order:\"\"})}},setup(e,{emit:t}){const n=$t(),r=ve(Vo),a=De(\"table\"),o=H({}),{onColumnsChange:i,onScrollableChange:l}=aI(r);et(async()=>{await Ne(),await Ne();const{prop:O,order:T}=e.defaultSort;r==null||r.store.commit(\"sort\",{prop:O,order:T,init:!0})});const{handleHeaderClick:s,handleHeaderContextMenu:c,handleMouseDown:d,handleMouseMove:f,handleMouseOut:p,handleSortClick:v,handleFilterClick:m}=Gpe(e,t),{getHeaderRowStyle:y,getHeaderRowClass:b,getHeaderCellStyle:C,getHeaderCellClass:S}=Xpe(e),{isGroup:w,toggleAllSelection:k,columnRows:$}=Jpe(e);return n.state={onColumnsChange:i,onScrollableChange:l},n.filterPanels=o,{ns:a,filterPanels:o,onColumnsChange:i,onScrollableChange:l,columnRows:$,getHeaderRowClass:b,getHeaderRowStyle:y,getHeaderCellClass:S,getHeaderCellStyle:C,handleHeaderClick:s,handleHeaderContextMenu:c,handleMouseDown:d,handleMouseMove:f,handleMouseOut:p,handleSortClick:v,handleFilterClick:m,isGroup:w,toggleAllSelection:k}},render(){const{ns:e,isGroup:t,columnRows:n,getHeaderCellStyle:r,getHeaderCellClass:a,getHeaderRowClass:o,getHeaderRowStyle:i,handleHeaderClick:l,handleHeaderContextMenu:s,handleMouseDown:c,handleMouseMove:d,handleSortClick:f,handleMouseOut:p,store:v,$parent:m}=this;let y=1;return qe(\"thead\",{class:{[e.is(\"group\")]:t}},n.map((b,C)=>qe(\"tr\",{class:o(C),key:C,style:i(C)},b.map((S,w)=>(S.rowSpan>y&&(y=S.rowSpan),qe(\"th\",{class:a(C,w,b,S),colspan:S.colSpan,key:`${S.id}-thead`,rowspan:S.rowSpan,style:r(C,w,b,S),onClick:k=>l(k,S),onContextmenu:k=>s(k,S),onMousedown:k=>c(k,S),onMousemove:k=>d(k,S),onMouseout:p},[qe(\"div\",{class:[\"cell\",S.filteredValue&&S.filteredValue.length>0?\"highlight\":\"\",S.labelClassName]},[S.renderHeader?S.renderHeader({column:S,$index:w,store:v,_self:m}):S.label,S.sortable&&qe(\"span\",{onClick:k=>f(k,S),class:\"caret-wrapper\"},[qe(\"i\",{onClick:k=>f(k,S,\"ascending\"),class:\"sort-caret ascending\"}),qe(\"i\",{onClick:k=>f(k,S,\"descending\"),class:\"sort-caret descending\"})]),S.filterable&&qe(qpe,{store:v,placement:S.filterPlacement||\"bottom-start\",column:S,upDataColumn:(k,$)=>{S[k]=$}})])]))))))}});function eve(e){const t=ve(Vo),n=H(\"\"),r=H(qe(\"div\")),a=(p,v,m)=>{var y;const b=t,C=$y(p);let S;const w=(y=b==null?void 0:b.vnode.el)==null?void 0:y.dataset.prefix;C&&(S=wO({columns:e.store.states.columns.value},C,w),S&&(b==null||b.emit(`cell-${m}`,v,S,C,p))),b==null||b.emit(`row-${m}`,v,S,p)},o=(p,v)=>{a(p,v,\"dblclick\")},i=(p,v)=>{e.store.commit(\"setCurrentRow\",v),a(p,v,\"click\")},l=(p,v)=>{a(p,v,\"contextmenu\")},s=Yn(p=>{e.store.commit(\"setHoverRow\",p)},30),c=Yn(()=>{e.store.commit(\"setHoverRow\",null)},30);return{handleDoubleClick:o,handleClick:i,handleContextMenu:l,handleMouseEnter:s,handleMouseLeave:c,handleCellMouseEnter:(p,v)=>{var m;const y=t,b=$y(p),C=(m=y==null?void 0:y.vnode.el)==null?void 0:m.dataset.prefix;if(b){const O=wO({columns:e.store.states.columns.value},b,C),T=y.hoverState={cell:b,column:O,row:v};y==null||y.emit(\"cell-mouse-enter\",T.row,T.column,T.cell,p)}const S=p.target.querySelector(\".cell\");if(!(to(S,`${C}-tooltip`)&&S.childNodes.length))return;const w=document.createRange();w.setStart(S,0),w.setEnd(S,S.childNodes.length);const k=w.getBoundingClientRect().width,$=(Number.parseInt($o(S,\"paddingLeft\"),10)||0)+(Number.parseInt($o(S,\"paddingRight\"),10)||0);(k+$>S.offsetWidth||S.scrollWidth>S.offsetWidth)&&Ipe(b,b.innerText||b.textContent,{placement:\"top\",strategy:\"fixed\"},v.tooltipEffect)},handleCellMouseLeave:p=>{if(!$y(p))return;const m=t==null?void 0:t.hoverState;t==null||t.emit(\"cell-mouse-leave\",m==null?void 0:m.row,m==null?void 0:m.column,m==null?void 0:m.cell,p)},tooltipContent:n,tooltipTrigger:r}}function tve(e){const t=ve(Vo),n=De(\"table\");return{getRowStyle:(c,d)=>{const f=t==null?void 0:t.props.rowStyle;return typeof f==\"function\"?f.call(null,{row:c,rowIndex:d}):f||null},getRowClass:(c,d)=>{const f=[n.e(\"row\")];(t==null?void 0:t.props.highlightCurrentRow)&&c===e.store.states.currentRow.value&&f.push(\"current-row\"),e.stripe&&d%2===1&&f.push(n.em(\"row\",\"striped\"));const p=t==null?void 0:t.props.rowClassName;return typeof p==\"string\"?f.push(p):typeof p==\"function\"&&f.push(p.call(null,{row:c,rowIndex:d})),f},getCellStyle:(c,d,f,p)=>{const v=t==null?void 0:t.props.cellStyle;let m=v!=null?v:{};typeof v==\"function\"&&(m=v.call(null,{rowIndex:c,columnIndex:d,row:f,column:p}));const y=p.isSubColumn?null:bw(d,e==null?void 0:e.fixed,e.store);return ec(y,\"left\"),ec(y,\"right\"),Object.assign({},m,y)},getCellClass:(c,d,f,p)=>{const v=p.isSubColumn?[]:yw(n.b(),d,e==null?void 0:e.fixed,e.store),m=[p.id,p.align,p.className,...v],y=t==null?void 0:t.props.cellClassName;return typeof y==\"string\"?m.push(y):typeof y==\"function\"&&m.push(y.call(null,{rowIndex:c,columnIndex:d,row:f,column:p})),m.push(n.e(\"cell\")),m.filter(b=>Boolean(b)).join(\" \")},getSpan:(c,d,f,p)=>{let v=1,m=1;const y=t==null?void 0:t.props.spanMethod;if(typeof y==\"function\"){const b=y({row:c,column:d,rowIndex:f,columnIndex:p});Array.isArray(b)?(v=b[0],m=b[1]):typeof b==\"object\"&&(v=b.rowspan,m=b.colspan)}return{rowspan:v,colspan:m}},getColspanRealWidth:(c,d,f)=>{if(d<1)return c[f].realWidth;const p=c.map(({realWidth:v,width:m})=>v||m).slice(f,f+d);return Number(p.reduce((v,m)=>Number(v)+Number(m),-1))}}}function nve(e){const t=ve(Vo),{handleDoubleClick:n,handleClick:r,handleContextMenu:a,handleMouseEnter:o,handleMouseLeave:i,handleCellMouseEnter:l,handleCellMouseLeave:s,tooltipContent:c,tooltipTrigger:d}=eve(e),{getRowStyle:f,getRowClass:p,getCellStyle:v,getCellClass:m,getSpan:y,getColspanRealWidth:b}=tve(e),C=x(()=>e.store.states.columns.value.findIndex(({type:O})=>O===\"default\")),S=(O,T)=>{const _=t.props.rowKey;return _?gr(O,_):T},w=(O,T,_,I=!1)=>{const{tooltipEffect:L,store:j}=e,{indent:F,columns:N}=j.states,D=p(O,T);let z=!0;return _&&(D.push(`el-table__row--level-${_.level}`),z=_.display),qe(\"tr\",{style:[z?null:{display:\"none\"},f(O,T)],class:D,key:S(O,T),onDblclick:M=>n(M,O),onClick:M=>r(M,O),onContextmenu:M=>a(M,O),onMouseenter:()=>o(T),onMouseleave:i},N.value.map((M,E)=>{const{rowspan:K,colspan:W}=y(O,M,T,E);if(!K||!W)return null;const Y=Te({},M);Y.realWidth=b(N.value,W,E);const q={store:e.store,_self:e.context||t,column:Y,row:O,$index:T,cellIndex:E,expanded:I};E===C.value&&_&&(q.treeNode={indent:_.level*F.value,level:_.level},typeof _.expanded==\"boolean\"&&(q.treeNode.expanded=_.expanded,\"loading\"in _&&(q.treeNode.loading=_.loading),\"noLazyChildren\"in _&&(q.treeNode.noLazyChildren=_.noLazyChildren)));const J=`${T},${E}`,ne=Y.columnKey||Y.rawColumnKey||\"\",oe=k(E,M,q);return qe(\"td\",{style:v(T,E,O,M),class:m(T,E,O,M),key:`${ne}${J}`,rowspan:K,colspan:W,onMouseenter:Q=>l(Q,Ke(Te({},O),{tooltipEffect:L})),onMouseleave:s},[oe])}))},k=(O,T,_)=>T.renderCell(_);return{wrappedRowRender:(O,T)=>{const _=e.store,{isRowExpanded:I,assertRowKey:L}=_,{treeData:j,lazyTreeNodeMap:F,childrenColumnName:N,rowKey:D}=_.states,z=_.states.columns.value;if(z.some(({type:M})=>M===\"expand\")){const M=I(O),E=w(O,T,void 0,M),K=t.renderExpanded;return M?K?[[E,qe(\"tr\",{key:`expanded-row__${E.key}`},[qe(\"td\",{colspan:z.length,class:\"el-table__cell el-table__expanded-cell\"},[K({row:O,$index:T,store:_,expanded:M})])])]]:(console.error(\"[Element Error]renderExpanded is required.\"),E):[[E]]}else if(Object.keys(j.value).length){L();const M=gr(O,D.value);let E=j.value[M],K=null;E&&(K={expanded:E.expanded,level:E.level,display:!0},typeof E.lazy==\"boolean\"&&(typeof E.loaded==\"boolean\"&&E.loaded&&(K.noLazyChildren=!(E.children&&E.children.length)),K.loading=E.loading));const W=[w(O,T,K)];if(E){let Y=0;const q=(ne,oe)=>{!(ne&&ne.length&&oe)||ne.forEach(Q=>{const ae={display:oe.display&&oe.expanded,level:oe.level+1,expanded:!1,noLazyChildren:!1,loading:!1},de=gr(Q,D.value);if(de==null)throw new Error(\"For nested data item, row-key is required.\");if(E=Te({},j.value[de]),E&&(ae.expanded=E.expanded,E.level=E.level||ae.level,E.display=!!(E.expanded&&ae.display),typeof E.lazy==\"boolean\"&&(typeof E.loaded==\"boolean\"&&E.loaded&&(ae.noLazyChildren=!(E.children&&E.children.length)),ae.loading=E.loading)),Y++,W.push(w(Q,T+Y,ae)),E){const be=F.value[de]||Q[N.value];q(be,E)}})};E.display=!0;const J=F.value[M]||O[N.value];q(J,E)}return W}else return w(O,T,void 0)},tooltipContent:c,tooltipTrigger:d}}const rve={store:{required:!0,type:Object},stripe:Boolean,tooltipEffect:String,context:{default:()=>({}),type:Object},rowClassName:[String,Function],rowStyle:[Object,Function],fixed:{type:String,default:\"\"},highlight:Boolean};var ave=G({name:\"ElTableBody\",props:rve,setup(e){const t=$t(),n=ve(Vo),r=De(\"table\"),{wrappedRowRender:a,tooltipContent:o,tooltipTrigger:i}=nve(e),{onColumnsChange:l,onScrollableChange:s}=aI(n);return ce(e.store.states.hoverRow,(c,d)=>{if(!e.store.states.isComplex.value||!Bt)return;let f=window.requestAnimationFrame;f||(f=p=>window.setTimeout(p,16)),f(()=>{var p;const v=(p=t==null?void 0:t.vnode.el)==null?void 0:p.querySelectorAll(`.${r.e(\"row\")}`),m=v[d],y=v[c];m&&Br(m,\"hover-row\"),y&&xo(y,\"hover-row\")})}),Wr(()=>{var c;(c=$v)==null||c()}),ur(()=>{var c;(c=$v)==null||c()}),{ns:r,onColumnsChange:l,onScrollableChange:s,wrappedRowRender:a,tooltipContent:o,tooltipTrigger:i}},render(){const{wrappedRowRender:e,store:t}=this,n=t.states.data.value||[];return qe(\"tbody\",{},[n.reduce((r,a)=>r.concat(e(a,r.length)),[])])}});function Cw(e){const t=e.tableLayout===\"auto\";let n=e.columns||[];t&&n.every(a=>a.width===void 0)&&(n=[]);const r=a=>{const o={key:`${e.tableLayout}_${a.id}`,style:{},name:void 0};return t?o.style={width:`${a.width}px`}:o.name=a.id,o};return qe(\"colgroup\",{},n.map(a=>qe(\"col\",r(a))))}Cw.props=[\"columns\",\"tableLayout\"];function ove(){const e=ve(Vo),t=e==null?void 0:e.store,n=x(()=>t.states.fixedLeafColumnsLength.value),r=x(()=>t.states.rightFixedColumns.value.length),a=x(()=>t.states.columns.value.length),o=x(()=>t.states.fixedColumns.value.length),i=x(()=>t.states.rightFixedColumns.value.length);return{leftFixedLeafCount:n,rightFixedLeafCount:r,columnsCount:a,leftFixedCount:o,rightFixedCount:i,columns:t.states.columns}}function ive(e){const{columns:t}=ove(),n=De(\"table\");return{getCellClasses:(o,i)=>{const l=o[i],s=[n.e(\"cell\"),l.id,l.align,l.labelClassName,...yw(n.b(),i,l.fixed,e.store)];return l.className&&s.push(l.className),l.children||s.push(n.is(\"leaf\")),s},getCellStyles:(o,i)=>{const l=bw(i,o.fixed,e.store);return ec(l,\"left\"),ec(l,\"right\"),l},columns:t}}var lve=G({name:\"ElTableFooter\",props:{fixed:{type:String,default:\"\"},store:{required:!0,type:Object},summaryMethod:Function,sumText:String,border:Boolean,defaultSort:{type:Object,default:()=>({prop:\"\",order:\"\"})}},setup(e){const{getCellClasses:t,getCellStyles:n,columns:r}=ive(e);return{ns:De(\"table\"),getCellClasses:t,getCellStyles:n,columns:r}},render(){const{columns:e,getCellStyles:t,getCellClasses:n,summaryMethod:r,sumText:a,ns:o}=this,i=this.store.states.data.value;let l=[];return r?l=r({columns:e,data:i}):e.forEach((s,c)=>{if(c===0){l[c]=a;return}const d=i.map(m=>Number(m[s.property])),f=[];let p=!0;d.forEach(m=>{if(!Number.isNaN(+m)){p=!1;const y=`${m}`.split(\".\")[1];f.push(y?y.length:0)}});const v=Math.max.apply(null,f);p?l[c]=\"\":l[c]=d.reduce((m,y)=>{const b=Number(y);return Number.isNaN(+b)?m:Number.parseFloat((m+y).toFixed(Math.min(v,20)))},0)}),qe(\"table\",{class:o.e(\"footer\"),cellspacing:\"0\",cellpadding:\"0\",border:\"0\"},[Cw({columns:e}),qe(\"tbody\",[qe(\"tr\",{},[...e.map((s,c)=>qe(\"td\",{key:c,colspan:s.colSpan,rowspan:s.rowSpan,class:n(e,c),style:t(s,c)},[qe(\"div\",{class:[\"cell\",s.labelClassName]},[l[c]])]))])])])}});function sve(e){return{setCurrentRow:d=>{e.commit(\"setCurrentRow\",d)},getSelectionRows:()=>e.getSelectionRows(),toggleRowSelection:(d,f)=>{e.toggleRowSelection(d,f,!1),e.updateAllSelected()},clearSelection:()=>{e.clearSelection()},clearFilter:d=>{e.clearFilter(d)},toggleAllSelection:()=>{e.commit(\"toggleAllSelection\")},toggleRowExpansion:(d,f)=>{e.toggleRowExpansionAdapter(d,f)},clearSort:()=>{e.clearSort()},sort:(d,f)=>{e.commit(\"sort\",{prop:d,order:f})}}}function uve(e,t,n,r){const a=H(!1),o=H(null),i=H(!1),l=E=>{i.value=E},s=H({width:null,height:null}),c=H(!1),d={display:\"inline-block\",verticalAlign:\"middle\"},f=H();Wn(()=>{t.setHeight(e.height)}),Wn(()=>{t.setMaxHeight(e.maxHeight)}),ce(()=>[e.currentRowKey,n.states.rowKey],([E,K])=>{!A(K)||n.setCurrentRowKey(`${E}`)},{immediate:!0}),ce(()=>e.data,E=>{r.store.commit(\"setData\",E)},{immediate:!0,deep:!0}),Wn(()=>{e.expandRowKeys&&n.setExpandRowKeysAdapter(e.expandRowKeys)});const p=()=>{r.store.commit(\"setHoverRow\",null),r.hoverState&&(r.hoverState=null)},v=(E,K)=>{const{pixelX:W,pixelY:Y}=K;Math.abs(W)>=Math.abs(Y)&&(r.refs.bodyWrapper.scrollLeft+=K.pixelX/5)},m=x(()=>e.height||e.maxHeight||n.states.fixedColumns.value.length>0||n.states.rightFixedColumns.value.length>0),y=x(()=>({width:t.bodyWidth.value?`${t.bodyWidth.value}px`:\"\"})),b=()=>{m.value&&t.updateElsHeight(),t.updateColumnsWidth(),requestAnimationFrame(k)};et(async()=>{await Ne(),n.updateColumns(),$(),requestAnimationFrame(b),s.value={width:f.value=r.vnode.el.offsetWidth,height:r.vnode.el.offsetHeight},n.states.columns.value.forEach(E=>{E.filteredValue&&E.filteredValue.length&&r.store.commit(\"filterChange\",{column:E,values:E.filteredValue,silent:!0})}),r.$ready=!0});const C=(E,K)=>{if(!E)return;const W=Array.from(E.classList).filter(Y=>!Y.startsWith(\"is-scrolling-\"));W.push(t.scrollX.value?K:\"is-scrolling-none\"),E.className=W.join(\" \")},S=E=>{const{tableWrapper:K}=r.refs;C(K,E)},w=E=>{const{tableWrapper:K}=r.refs;return!!(K&&K.classList.contains(E))},k=function(){if(!r.refs.scrollBarRef)return;if(!t.scrollX.value){const oe=\"is-scrolling-none\";w(oe)||S(oe);return}const E=r.refs.scrollBarRef.wrap$;if(!E)return;const{scrollLeft:K,offsetWidth:W,scrollWidth:Y}=E,{headerWrapper:q,footerWrapper:J}=r.refs;q&&(q.scrollLeft=K),J&&(J.scrollLeft=K);const ne=Y-W-1;K>=ne?S(\"is-scrolling-right\"):S(K===0?\"is-scrolling-left\":\"is-scrolling-middle\")},$=()=>{var E;!r.refs.scrollBarRef||((E=r.refs.scrollBarRef.wrap$)==null||E.addEventListener(\"scroll\",k,{passive:!0}),e.fit?wc(r.vnode.el,T):gn(window,\"resize\",b))};Lt(()=>{O()});const O=()=>{var E;(E=r.refs.scrollBarRef.wrap$)==null||E.removeEventListener(\"scroll\",k,!0),e.fit?Sc(r.vnode.el,T):Bn(window,\"resize\",b)},T=()=>{if(!r.$ready)return;let E=!1;const K=r.vnode.el,{width:W,height:Y}=s.value,q=f.value=K.offsetWidth;W!==q&&(E=!0);const J=K.offsetHeight;(e.height||m.value)&&Y!==J&&(E=!0),E&&(s.value={width:q,height:J},b())},_=Gn(),I=x(()=>{const{bodyWidth:E,scrollY:K,gutterWidth:W}=t;return E.value?`${E.value-(K.value?W:0)}px`:\"\"}),L=x(()=>e.maxHeight?\"fixed\":e.tableLayout);function j(E,K,W){const Y=j0(E),q=e.showHeader?W:0;if(Y!==null)return wt(Y)?`calc(${Y} - ${K}px - ${q}px)`:Y-K-q}const F=x(()=>{const E=t.headerHeight.value||0,K=t.bodyHeight.value,W=t.footerHeight.value||0;if(e.height)return K||void 0;if(e.maxHeight)return j(e.maxHeight,W,E)}),N=x(()=>{const E=t.headerHeight.value||0,K=t.bodyHeight.value,W=t.footerHeight.value||0;if(e.height)return{height:K?`${K}px`:\"\"};if(e.maxHeight){const Y=j(e.maxHeight,W,E);if(Y!==null)return{\"max-height\":`${Y}${Yt(Y)?\"px\":\"\"}`}}return{}}),D=x(()=>{if(e.data&&e.data.length)return null;let E=\"100%\";return t.appendHeight.value&&(E=`calc(100% - ${t.appendHeight.value}px)`),{width:f.value?`${f.value}px`:\"\",height:E}}),z=(E,K)=>{const W=r.refs.bodyWrapper;if(Math.abs(K.spinY)>0){const Y=W.scrollTop;K.pixelY<0&&Y!==0&&E.preventDefault(),K.pixelY>0&&W.scrollHeight-W.clientHeight>Y&&E.preventDefault(),W.scrollTop+=Math.ceil(K.pixelY/5)}else W.scrollLeft+=Math.ceil(K.pixelX/5)},B=x(()=>e.maxHeight?e.showSummary?{bottom:0}:{bottom:t.scrollX.value&&e.data.length?`${t.gutterWidth}px`:\"\"}:e.showSummary?{height:t.tableHeight.value?`${t.tableHeight.value}px`:\"\"}:{height:t.viewportHeight.value?`${t.viewportHeight.value}px`:\"\"}),M=x(()=>{if(e.height)return{height:t.fixedBodyHeight.value?`${t.fixedBodyHeight.value}px`:\"\"};if(e.maxHeight){let E=j0(e.maxHeight);if(typeof E==\"number\")return E=t.scrollX.value?E-t.gutterWidth:E,e.showHeader&&(E-=t.headerHeight.value),E-=t.footerHeight.value,{\"max-height\":`${E}px`}}return{}});return{isHidden:a,renderExpanded:o,setDragVisible:l,isGroup:c,handleMouseLeave:p,handleHeaderFooterMousewheel:v,tableSize:_,bodyHeight:N,height:F,emptyBlockStyle:D,handleFixedMousewheel:z,fixedHeight:B,fixedBodyHeight:M,resizeProxyVisible:i,bodyWidth:I,resizeState:s,doLayout:b,tableBodyStyles:y,tableLayout:L,scrollbarViewStyle:d}}var cve={data:{type:Array,default:()=>[]},size:String,width:[String,Number],height:[String,Number],maxHeight:[String,Number],fit:{type:Boolean,default:!0},stripe:Boolean,border:Boolean,rowKey:[String,Function],showHeader:{type:Boolean,default:!0},showSummary:Boolean,sumText:String,summaryMethod:Function,rowClassName:[String,Function],rowStyle:[Object,Function],cellClassName:[String,Function],cellStyle:[Object,Function],headerRowClassName:[String,Function],headerRowStyle:[Object,Function],headerCellClassName:[String,Function],headerCellStyle:[Object,Function],highlightCurrentRow:Boolean,currentRowKey:[String,Number],emptyText:String,expandRowKeys:Array,defaultExpandAll:Boolean,defaultSort:Object,tooltipEffect:String,spanMethod:Function,selectOnIndeterminate:{type:Boolean,default:!0},indent:{type:Number,default:16},treeProps:{type:Object,default:()=>({hasChildren:\"hasChildren\",children:\"children\"})},lazy:Boolean,load:Function,style:{type:Object,default:()=>({})},className:{type:String,default:\"\"},tableLayout:{type:String,default:\"fixed\"},scrollbarAlwaysOn:{type:Boolean,default:!1}};const dve=()=>{const e=H(),t=(o,i)=>{const l=e.value;l&&l.scrollTo(o,i)},n=(o,i)=>{const l=e.value;l&&Yt(i)&&[\"Top\",\"Left\"].includes(o)&&l[`setScroll${o}`](i)};return{scrollBarRef:e,scrollTo:t,setScrollTop:o=>n(\"Top\",o),setScrollLeft:o=>n(\"Left\",o)}};let fve=1;const hve=G({name:\"ElTable\",directives:{Mousewheel:Dte},components:{TableHeader:Qpe,TableBody:ave,TableFooter:lve,ElScrollbar:xi,hColgroup:Cw},props:cve,emits:[\"select\",\"select-all\",\"selection-change\",\"cell-mouse-enter\",\"cell-mouse-leave\",\"cell-contextmenu\",\"cell-click\",\"cell-dblclick\",\"row-click\",\"row-contextmenu\",\"row-dblclick\",\"header-click\",\"header-contextmenu\",\"sort-change\",\"filter-change\",\"current-change\",\"header-dragend\",\"expand-change\"],setup(e){const{t}=ln(),n=De(\"table\"),r=$t();ot(Vo,r);const a=Bpe(r,e);r.store=a;const o=new zpe({store:r.store,table:r,fit:e.fit,showHeader:e.showHeader});r.layout=o;const i=x(()=>(a.states.data.value||[]).length===0),{setCurrentRow:l,getSelectionRows:s,toggleRowSelection:c,clearSelection:d,clearFilter:f,toggleAllSelection:p,toggleRowExpansion:v,clearSort:m,sort:y}=sve(a),{isHidden:b,renderExpanded:C,setDragVisible:S,isGroup:w,handleMouseLeave:k,handleHeaderFooterMousewheel:$,tableSize:O,bodyHeight:T,height:_,emptyBlockStyle:I,handleFixedMousewheel:L,fixedHeight:j,fixedBodyHeight:F,resizeProxyVisible:N,bodyWidth:D,resizeState:z,doLayout:B,tableBodyStyles:M,tableLayout:E,scrollbarViewStyle:K}=uve(e,o,a,r),{scrollBarRef:W,scrollTo:Y,setScrollLeft:q,setScrollTop:J}=dve(),ne=Yn(B,50),oe=`el-table_${fve++}`;r.tableId=oe,r.state={isGroup:w,resizeState:z,doLayout:B,debouncedUpdateLayout:ne};const Q=x(()=>e.sumText||t(\"el.table.sumText\")),ae=x(()=>e.emptyText||t(\"el.table.emptyText\"));return{ns:n,layout:o,store:a,handleHeaderFooterMousewheel:$,handleMouseLeave:k,tableId:oe,tableSize:O,isHidden:b,isEmpty:i,renderExpanded:C,resizeProxyVisible:N,resizeState:z,isGroup:w,bodyWidth:D,bodyHeight:T,height:_,tableBodyStyles:M,emptyBlockStyle:I,debouncedUpdateLayout:ne,handleFixedMousewheel:L,fixedHeight:j,fixedBodyHeight:F,setCurrentRow:l,getSelectionRows:s,toggleRowSelection:c,clearSelection:d,clearFilter:f,toggleAllSelection:p,toggleRowExpansion:v,clearSort:m,doLayout:B,sort:y,t,setDragVisible:S,context:r,computedSumText:Q,computedEmptyText:ae,tableLayout:E,scrollbarViewStyle:K,scrollBarRef:W,scrollTo:Y,setScrollLeft:q,setScrollTop:J}}}),pve=[\"data-prefix\"],vve={ref:\"hiddenColumns\",class:\"hidden-columns\"};function mve(e,t,n,r,a,o){const i=we(\"hColgroup\"),l=we(\"table-header\"),s=we(\"table-body\"),c=we(\"el-scrollbar\"),d=we(\"table-footer\"),f=pa(\"mousewheel\");return R(),X(\"div\",{ref:\"tableWrapper\",class:U([{[e.ns.m(\"fit\")]:e.fit,[e.ns.m(\"striped\")]:e.stripe,[e.ns.m(\"border\")]:e.border||e.isGroup,[e.ns.m(\"hidden\")]:e.isHidden,[e.ns.m(\"group\")]:e.isGroup,[e.ns.m(\"fluid-height\")]:e.maxHeight,[e.ns.m(\"scrollable-x\")]:e.layout.scrollX.value,[e.ns.m(\"scrollable-y\")]:e.layout.scrollY.value,[e.ns.m(\"enable-row-hover\")]:!e.store.states.isComplex.value,[e.ns.m(\"enable-row-transition\")]:(e.store.states.data.value||[]).length!==0&&(e.store.states.data.value||[]).length<100,\"has-footer\":e.showSummary},e.ns.m(e.tableSize),e.className,e.ns.b(),e.ns.m(`layout-${e.tableLayout}`)]),style:Xe(e.style),\"data-prefix\":e.ns.namespace.value,onMouseleave:t[0]||(t[0]=p=>e.handleMouseLeave())},[Z(\"div\",{class:U(e.ns.e(\"inner-wrapper\"))},[Z(\"div\",vve,[Oe(e.$slots,\"default\")],512),e.showHeader&&e.tableLayout===\"fixed\"?at((R(),X(\"div\",{key:0,ref:\"headerWrapper\",class:U(e.ns.e(\"header-wrapper\"))},[Z(\"table\",{ref:\"tableHeader\",class:U(e.ns.e(\"header\")),style:Xe(e.tableBodyStyles),border:\"0\",cellpadding:\"0\",cellspacing:\"0\"},[g(i,{columns:e.store.states.columns.value,\"table-layout\":e.tableLayout},null,8,[\"columns\",\"table-layout\"]),g(l,{ref:\"tableHeaderRef\",border:e.border,\"default-sort\":e.defaultSort,store:e.store,onSetDragVisible:e.setDragVisible},null,8,[\"border\",\"default-sort\",\"store\",\"onSetDragVisible\"])],6)],2)),[[f,e.handleHeaderFooterMousewheel]]):se(\"v-if\",!0),Z(\"div\",{ref:\"bodyWrapper\",style:Xe(e.bodyHeight),class:U(e.ns.e(\"body-wrapper\"))},[g(c,{ref:\"scrollBarRef\",height:e.maxHeight?void 0:e.height,\"max-height\":e.maxHeight?e.height:void 0,\"view-style\":e.scrollbarViewStyle,always:e.scrollbarAlwaysOn},{default:re(()=>[Z(\"table\",{ref:\"tableBody\",class:U(e.ns.e(\"body\")),cellspacing:\"0\",cellpadding:\"0\",border:\"0\",style:Xe({width:e.bodyWidth,tableLayout:e.tableLayout})},[g(i,{columns:e.store.states.columns.value,\"table-layout\":e.tableLayout},null,8,[\"columns\",\"table-layout\"]),e.showHeader&&e.tableLayout===\"auto\"?(R(),fe(l,{key:0,border:e.border,\"default-sort\":e.defaultSort,store:e.store,onSetDragVisible:e.setDragVisible},null,8,[\"border\",\"default-sort\",\"store\",\"onSetDragVisible\"])):se(\"v-if\",!0),g(s,{context:e.context,highlight:e.highlightCurrentRow,\"row-class-name\":e.rowClassName,\"tooltip-effect\":e.tooltipEffect,\"row-style\":e.rowStyle,store:e.store,stripe:e.stripe},null,8,[\"context\",\"highlight\",\"row-class-name\",\"tooltip-effect\",\"row-style\",\"store\",\"stripe\"])],6),e.isEmpty?(R(),X(\"div\",{key:0,ref:\"emptyBlock\",style:Xe(e.emptyBlockStyle),class:U(e.ns.e(\"empty-block\"))},[Z(\"span\",{class:U(e.ns.e(\"empty-text\"))},[Oe(e.$slots,\"empty\",{},()=>[yt(Me(e.computedEmptyText),1)])],2)],6)):se(\"v-if\",!0),e.$slots.append?(R(),X(\"div\",{key:1,ref:\"appendWrapper\",class:U(e.ns.e(\"append-wrapper\"))},[Oe(e.$slots,\"append\")],2)):se(\"v-if\",!0)]),_:3},8,[\"height\",\"max-height\",\"view-style\",\"always\"])],6),e.border||e.isGroup?(R(),X(\"div\",{key:1,class:U(e.ns.e(\"border-left-patch\"))},null,2)):se(\"v-if\",!0)],2),e.showSummary?at((R(),X(\"div\",{key:0,ref:\"footerWrapper\",class:U(e.ns.e(\"footer-wrapper\"))},[g(d,{border:e.border,\"default-sort\":e.defaultSort,store:e.store,style:Xe(e.tableBodyStyles),\"sum-text\":e.computedSumText,\"summary-method\":e.summaryMethod},null,8,[\"border\",\"default-sort\",\"store\",\"style\",\"sum-text\",\"summary-method\"])],2)),[[_t,!e.isEmpty],[f,e.handleHeaderFooterMousewheel]]):se(\"v-if\",!0),at(Z(\"div\",{ref:\"resizeProxy\",class:U(e.ns.e(\"column-resize-proxy\"))},null,2),[[_t,e.resizeProxyVisible]])],46,pve)}var gve=Ae(hve,[[\"render\",mve],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/table/src/table.vue\"]]);const yve={selection:\"table-column--selection\",expand:\"table__expand-column\"},bve={default:{order:\"\"},selection:{width:48,minWidth:48,realWidth:48,order:\"\"},expand:{width:48,minWidth:48,realWidth:48,order:\"\"},index:{width:48,minWidth:48,realWidth:48,order:\"\"}},Cve=e=>yve[e]||\"\",wve={selection:{renderHeader({store:e}){function t(){return e.states.data.value&&e.states.data.value.length===0}return qe(io,{disabled:t(),size:e.states.tableSize.value,indeterminate:e.states.selection.value.length>0&&!e.states.isAllSelected.value,\"onUpdate:modelValue\":e.toggleAllSelection,modelValue:e.states.isAllSelected.value})},renderCell({row:e,column:t,store:n,$index:r}){return qe(io,{disabled:t.selectable?!t.selectable.call(null,e,r):!1,size:n.states.tableSize.value,onChange:()=>{n.commit(\"rowSelectedChanged\",e)},onClick:a=>a.stopPropagation(),modelValue:n.isSelected(e)})},sortable:!1,resizable:!1},index:{renderHeader({column:e}){return e.label||\"#\"},renderCell({column:e,$index:t}){let n=t+1;const r=e.index;return typeof r==\"number\"?n=t+r:typeof r==\"function\"&&(n=r(t)),qe(\"div\",{},[n])},sortable:!1},expand:{renderHeader({column:e}){return e.label||\"\"},renderCell({row:e,store:t,expanded:n}){const{ns:r}=t,a=[r.e(\"expand-icon\")];return n&&a.push(r.em(\"expand-icon\",\"expanded\")),qe(\"div\",{class:a,onClick:function(i){i.stopPropagation(),t.toggleRowExpansion(e)}},{default:()=>[qe(ft,null,{default:()=>[qe(Da)]})]})},sortable:!1,resizable:!1}};function Sve({row:e,column:t,$index:n}){var r;const a=t.property,o=a&&cp(e,a).value;return t&&t.formatter?t.formatter(e,t,o,n):((r=o==null?void 0:o.toString)==null?void 0:r.call(o))||\"\"}function kve({row:e,treeNode:t,store:n},r=!1){const{ns:a}=n;if(!t)return r?[qe(\"span\",{class:a.e(\"placeholder\")})]:null;const o=[],i=function(l){l.stopPropagation(),n.loadOrToggle(e)};if(t.indent&&o.push(qe(\"span\",{class:a.e(\"indent\"),style:{\"padding-left\":`${t.indent}px`}})),typeof t.expanded==\"boolean\"&&!t.noLazyChildren){const l=[a.e(\"expand-icon\"),t.expanded?a.em(\"expand-icon\",\"expanded\"):\"\"];let s=Da;t.loading&&(s=gl),o.push(qe(\"div\",{class:l,onClick:i},{default:()=>[qe(ft,{class:{[a.is(\"loading\")]:t.loading}},{default:()=>[qe(s)]})]}))}else o.push(qe(\"span\",{class:a.e(\"placeholder\")}));return o}function kO(e,t){return e.reduce((n,r)=>(n[r]=r,n),t)}function $ve(e,t){const n=$t();return{registerComplexWatchers:()=>{const o=[\"fixed\"],i={realWidth:\"width\",realMinWidth:\"minWidth\"},l=kO(o,i);Object.keys(l).forEach(s=>{const c=i[s];Mt(t,c)&&ce(()=>t[c],d=>{let f=d;c===\"width\"&&s===\"realWidth\"&&(f=gw(d)),c===\"minWidth\"&&s===\"realMinWidth\"&&(f=Q5(d)),n.columnConfig.value[c]=f,n.columnConfig.value[s]=f;const p=c===\"fixed\";e.value.store.scheduleLayout(p)})})},registerNormalWatchers:()=>{const o=[\"label\",\"filters\",\"filterMultiple\",\"sortable\",\"index\",\"formatter\",\"className\",\"labelClassName\",\"showOverflowTooltip\"],i={property:\"prop\",align:\"realAlign\",headerAlign:\"realHeaderAlign\"},l=kO(o,i);Object.keys(l).forEach(s=>{const c=i[s];Mt(t,c)&&ce(()=>t[c],d=>{n.columnConfig.value[s]=d})})}}}function Ove(e,t,n){const r=$t(),a=H(\"\"),o=H(!1),i=H(),l=H(),s=De(\"table\");Wn(()=>{i.value=e.align?`is-${e.align}`:null,i.value}),Wn(()=>{l.value=e.headerAlign?`is-${e.headerAlign}`:i.value,l.value});const c=x(()=>{let w=r.vnode.vParent||r.parent;for(;w&&!w.tableId&&!w.columnId;)w=w.vnode.vParent||w.parent;return w}),d=x(()=>{const{store:w}=r.parent;if(!w)return!1;const{treeData:k}=w.states,$=k.value;return $&&Object.keys($).length>0}),f=H(gw(e.width)),p=H(Q5(e.minWidth)),v=w=>(f.value&&(w.width=f.value),p.value&&(w.minWidth=p.value),w.minWidth||(w.minWidth=80),w.realWidth=Number(w.width===void 0?w.minWidth:w.width),w),m=w=>{const k=w.type,$=wve[k]||{};Object.keys($).forEach(T=>{const _=$[T];T!==\"className\"&&_!==void 0&&(w[T]=_)});const O=Cve(k);if(O){const T=`${A(s.namespace)}-${O}`;w.className=w.className?`${w.className} ${T}`:T}return w},y=w=>{Array.isArray(w)?w.forEach($=>k($)):k(w);function k($){var O;((O=$==null?void 0:$.type)==null?void 0:O.name)===\"ElTableColumn\"&&($.vParent=r)}};return{columnId:a,realAlign:i,isSubColumn:o,realHeaderAlign:l,columnOrTableParent:c,setColumnWidth:v,setColumnForcedProps:m,setColumnRenders:w=>{e.renderHeader||w.type!==\"selection\"&&(w.renderHeader=O=>{r.columnConfig.value.label;const T=t.header;return T?T(O):w.label});let k=w.renderCell;const $=d.value;return w.type===\"expand\"?(w.renderCell=O=>qe(\"div\",{class:\"cell\"},[k(O)]),n.value.renderExpanded=O=>t.default?t.default(O):t.default):(k=k||Sve,w.renderCell=O=>{let T=null;if(t.default){const j=t.default(O);T=j.some(F=>F.type!==Ir)?j:k(O)}else T=k(O);const _=$&&O.cellIndex===0,I=kve(O,_),L={class:\"cell\",style:{}};return w.showOverflowTooltip&&(L.class=`${L.class} ${A(s.namespace)}-tooltip`,L.style={width:`${(O.column.realWidth||Number(O.column.width))-1}px`}),y(T),qe(\"div\",L,[I,T])}),w},getPropsData:(...w)=>w.reduce((k,$)=>(Array.isArray($)&&$.forEach(O=>{k[O]=e[O]}),k),{}),getColumnElIndex:(w,k)=>Array.prototype.indexOf.call(w,k)}}var Pve={type:{type:String,default:\"default\"},label:String,className:String,labelClassName:String,property:String,prop:String,width:{type:[String,Number],default:\"\"},minWidth:{type:[String,Number],default:\"\"},renderHeader:Function,sortable:{type:[Boolean,String],default:!1},sortMethod:Function,sortBy:[String,Function,Array],resizable:{type:Boolean,default:!0},columnKey:String,align:String,headerAlign:String,showTooltipWhenOverflow:Boolean,showOverflowTooltip:Boolean,fixed:[Boolean,String],formatter:Function,selectable:Function,reserveSelection:Boolean,filterMethod:Function,filteredValue:Array,filters:Array,filterPlacement:String,filterMultiple:{type:Boolean,default:!0},index:[Number,Function],sortOrders:{type:Array,default:()=>[\"ascending\",\"descending\",null],validator:e=>e.every(t=>[\"ascending\",\"descending\",null].includes(t))}};let Tve=1;var iI=G({name:\"ElTableColumn\",components:{ElCheckbox:io},props:Pve,setup(e,{slots:t}){const n=$t(),r=H({}),a=x(()=>{let S=n.parent;for(;S&&!S.tableId;)S=S.parent;return S}),{registerNormalWatchers:o,registerComplexWatchers:i}=$ve(a,e),{columnId:l,isSubColumn:s,realHeaderAlign:c,columnOrTableParent:d,setColumnWidth:f,setColumnForcedProps:p,setColumnRenders:v,getPropsData:m,getColumnElIndex:y,realAlign:b}=Ove(e,t,a),C=d.value;l.value=`${C.tableId||C.columnId}_column_${Tve++}`,hc(()=>{s.value=a.value!==C;const S=e.type||\"default\",w=e.sortable===\"\"?!0:e.sortable,k=Ke(Te({},bve[S]),{id:l.value,type:S,property:e.prop||e.property,align:b,headerAlign:c,showOverflowTooltip:e.showOverflowTooltip||e.showTooltipWhenOverflow,filterable:e.filters||e.filterMethod,filteredValue:[],filterPlacement:\"\",isColumnGroup:!1,isSubColumn:!1,filterOpened:!1,sortable:w,index:e.index,rawColumnKey:n.vnode.key});let I=m([\"columnKey\",\"label\",\"className\",\"labelClassName\",\"type\",\"renderHeader\",\"formatter\",\"fixed\",\"resizable\"],[\"sortMethod\",\"sortBy\",\"sortOrders\"],[\"selectable\",\"reserveSelection\"],[\"filterMethod\",\"filters\",\"filterMultiple\",\"filterOpened\",\"filteredValue\",\"filterPlacement\"]);I=_pe(k,I),I=Epe(v,f,p)(I),r.value=I,o(),i()}),et(()=>{var S;const w=d.value,k=s.value?w.vnode.el.children:(S=w.refs.hiddenColumns)==null?void 0:S.children,$=()=>y(k||[],n.vnode.el);r.value.getColumnIndex=$,$()>-1&&a.value.store.commit(\"insertColumn\",r.value,s.value?w.columnConfig.value:null)}),Lt(()=>{a.value.store.commit(\"removeColumn\",r.value,s.value?C.columnConfig.value:null)}),n.columnId=l.value,n.columnConfig=r},render(){var e,t,n;try{const r=(t=(e=this.$slots).default)==null?void 0:t.call(e,{row:{},column:{},$index:-1}),a=[];if(Array.isArray(r))for(const i of r)((n=i.type)==null?void 0:n.name)===\"ElTableColumn\"||i.shapeFlag&2?a.push(i):i.type===Fe&&Array.isArray(i.children)&&i.children.forEach(l=>{(l==null?void 0:l.patchFlag)!==1024&&!wt(l==null?void 0:l.children)&&a.push(l)});return qe(\"div\",a)}catch{return qe(\"div\",[])}}});const xve=xt(gve,{TableColumn:iI}),_ve=En(iI),Eve=Ze({tabs:{type:Le(Array),default:()=>xn([])}}),Mve={name:\"ElTabBar\"},Ive=G(Ke(Te({},Mve),{props:Eve,setup(e,{expose:t}){const n=e,r=\"ElTabBar\",a=$t(),o=ve(Hm);o||qn(r,\"<el-tabs><el-tab-bar /></el-tabs>\");const i=De(\"tabs\"),l=H(),s=H(),c=()=>{let f=0,p=0;const v=[\"top\",\"bottom\"].includes(o.props.tabPosition)?\"width\":\"height\",m=v===\"width\"?\"x\":\"y\";return n.tabs.every(y=>{var b,C,S,w;const k=(C=(b=a.parent)==null?void 0:b.refs)==null?void 0:C[`tab-${y.paneName}`];if(!k)return!1;if(!y.active)return!0;p=k[`client${ia(v)}`];const $=m===\"x\"?\"left\":\"top\";f=k.getBoundingClientRect()[$]-((w=(S=k.parentElement)==null?void 0:S.getBoundingClientRect()[$])!=null?w:0);const O=window.getComputedStyle(k);return v===\"width\"&&(n.tabs.length>1&&(p-=Number.parseFloat(O.paddingLeft)+Number.parseFloat(O.paddingRight)),f+=Number.parseFloat(O.paddingLeft)),!1}),{[v]:`${p}px`,transform:`translate${ia(m)}(${f}px)`}},d=()=>s.value=c();return ce(()=>n.tabs,async()=>{await Ne(),d()},{immediate:!0}),Cc(l,()=>d()),t({ref:l,update:d}),(f,p)=>(R(),X(\"div\",{ref_key:\"barRef\",ref:l,class:U([A(i).e(\"active-bar\"),A(i).is(A(o).props.tabPosition)]),style:Xe(s.value)},null,6))}}));var Nve=Ae(Ive,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tabs/src/tab-bar.vue\"]]);const Ave=Ze({panes:{type:Le(Array),default:()=>xn([])},currentName:{type:[String,Number],default:\"\"},editable:Boolean,onTabClick:{type:Le(Function),default:Qt},onTabRemove:{type:Le(Function),default:Qt},type:{type:String,values:[\"card\",\"border-card\",\"\"],default:\"\"},stretch:Boolean}),$O=\"ElTabNav\",Dve=G({name:$O,props:Ave,setup(e,{expose:t}){const n=ve(Hm);n||qn($O,\"<el-tabs><tab-nav /></el-tabs>\");const r=De(\"tabs\"),a=CU(),o=$U(),i=H(),l=H(),s=H(),c=H(!1),d=H(0),f=H(!1),p=H(!0),v=x(()=>[\"top\",\"bottom\"].includes(n.props.tabPosition)?\"width\":\"height\"),m=x(()=>({transform:`translate${v.value===\"width\"?\"X\":\"Y\"}(-${d.value}px)`})),y=()=>{if(!i.value)return;const O=i.value[`offset${ia(v.value)}`],T=d.value;if(!T)return;const _=T>O?T-O:0;d.value=_},b=()=>{if(!i.value||!l.value)return;const O=l.value[`offset${ia(v.value)}`],T=i.value[`offset${ia(v.value)}`],_=d.value;if(O-_<=T)return;const I=O-_>T*2?_+T:O-T;d.value=I},C=()=>{const O=l.value;if(!c.value||!s.value||!i.value||!O)return;const T=s.value.querySelector(\".is-active\");if(!T)return;const _=i.value,I=[\"top\",\"bottom\"].includes(n.props.tabPosition),L=T.getBoundingClientRect(),j=_.getBoundingClientRect(),F=I?O.offsetWidth-j.width:O.offsetHeight-j.height,N=d.value;let D=N;I?(L.left<j.left&&(D=N-(j.left-L.left)),L.right>j.right&&(D=N+L.right-j.right)):(L.top<j.top&&(D=N-(j.top-L.top)),L.bottom>j.bottom&&(D=N+(L.bottom-j.bottom))),D=Math.max(D,0),d.value=Math.min(D,F)},S=()=>{if(!l.value||!i.value)return;const O=l.value[`offset${ia(v.value)}`],T=i.value[`offset${ia(v.value)}`],_=d.value;if(T<O){const I=d.value;c.value=c.value||{},c.value.prev=I,c.value.next=I+T<O,O-I<T&&(d.value=O-T)}else c.value=!1,_>0&&(d.value=0)},w=O=>{const T=O.code,{up:_,down:I,left:L,right:j}=Ge;if(![_,I,L,j].includes(T))return;const F=Array.from(O.currentTarget.querySelectorAll(\"[role=tab]\")),N=F.indexOf(O.target);let D;T===L||T===_?N===0?D=F.length-1:D=N-1:N<F.length-1?D=N+1:D=0,F[D].focus(),F[D].click(),k()},k=()=>{p.value&&(f.value=!0)},$=()=>f.value=!1;return ce(a,O=>{O===\"hidden\"?p.value=!1:O===\"visible\"&&setTimeout(()=>p.value=!0,50)}),ce(o,O=>{O?setTimeout(()=>p.value=!0,50):p.value=!1}),Cc(s,S),et(()=>setTimeout(()=>C(),0)),ur(()=>S()),t({scrollToActiveTab:C,removeFocus:$}),()=>{const O=c.value?[g(\"span\",{class:[r.e(\"nav-prev\"),r.is(\"disabled\",!c.value.prev)],onClick:y},[g(ft,null,{default:()=>[g(Es,null,null)]})]),g(\"span\",{class:[r.e(\"nav-next\"),r.is(\"disabled\",!c.value.next)],onClick:b},[g(ft,null,{default:()=>[g(Da,null,null)]})])]:null,T=e.panes.map((_,I)=>{var L,j;const F=_.props.name||_.index||`${I}`,N=_.isClosable||e.editable;_.index=`${I}`;const D=N?g(ft,{class:\"is-icon-close\",onClick:M=>e.onTabRemove(_,M)},{default:()=>[g(Ma,null,null)]}):null,z=((j=(L=_.instance.slots).label)==null?void 0:j.call(L))||_.props.label,B=_.active?0:-1;return g(\"div\",{ref:`tab-${F}`,class:[r.e(\"item\"),r.is(n.props.tabPosition),r.is(\"active\",_.active),r.is(\"disabled\",_.props.disabled),r.is(\"closable\",N),r.is(\"focus\",f.value)],id:`tab-${F}`,key:`tab-${F}`,\"aria-controls\":`pane-${F}`,role:\"tab\",\"aria-selected\":_.active,tabindex:B,onFocus:()=>k(),onBlur:()=>$(),onClick:M=>{$(),e.onTabClick(_,F,M)},onKeydown:M=>{N&&(M.code===Ge.delete||M.code===Ge.backspace)&&e.onTabRemove(_,M)}},[z,D])});return g(\"div\",{ref:s,class:[r.e(\"nav-wrap\"),r.is(\"scrollable\",!!c.value),r.is(n.props.tabPosition)]},[O,g(\"div\",{class:r.e(\"nav-scroll\"),ref:i},[g(\"div\",{class:[r.e(\"nav\"),r.is(n.props.tabPosition),r.is(\"stretch\",e.stretch&&[\"top\",\"bottom\"].includes(n.props.tabPosition))],ref:l,style:m.value,role:\"tablist\",onKeydown:w},[e.type?null:g(Nve,{tabs:[...e.panes]},null),T])])])}}}),Rve=Ze({type:{type:String,values:[\"card\",\"border-card\",\"\"],default:\"\"},activeName:{type:[String,Number],default:\"\"},closable:Boolean,addable:Boolean,modelValue:{type:[String,Number],default:\"\"},editable:Boolean,tabPosition:{type:String,values:[\"top\",\"right\",\"bottom\",\"left\"],default:\"top\"},beforeLeave:{type:Le(Function),default:()=>!0},stretch:Boolean}),dh=e=>wt(e)||Yt(e),Lve={[Pt]:e=>dh(e),[cl]:e=>dh(e),\"tab-click\":(e,t)=>t instanceof Event,\"tab-change\":e=>dh(e),edit:(e,t)=>[\"remove\",\"add\"].includes(t),\"tab-remove\":e=>dh(e),\"tab-add\":()=>!0},lI=(e,t=[])=>{const n=e.children||[];return Array.from(n).forEach(r=>{let a=r.type;a=a.name||a,a===\"ElTabPane\"&&r.component?t.push(r.component):(a===Fe||a===\"template\")&&lI(r,t)}),t};var Fve=G({name:\"ElTabs\",props:Rve,emits:Lve,setup(e,{emit:t,slots:n,expose:r}){const a=$t();Tf({scope:\"el-tabs\",type:\"Event\",from:\"input\",replacement:\"tab-change\",version:\"2.5.0\",ref:\"https://element-plus.org/en-US/component/tabs.html#tabs-events\"},x(()=>{var b;return Ct((b=a.vnode.props)==null?void 0:b.onInput)}));const o=De(\"tabs\"),i=H(),l=H([]),s=H(e.modelValue||e.activeName||\"0\"),c={},d=(b=!1)=>{if(n.default){const C=a.subTree.children,S=Array.from(C).find(({props:$})=>($==null?void 0:$.class)===o.e(\"content\"));if(!S)return;const w=lI(S).map($=>c[$.uid]),k=!(w.length===l.value.length&&w.every(($,O)=>$.uid===l.value[O].uid));(b||k)&&(l.value=w)}else l.value.length!==0&&(l.value=[])},f=b=>{s.value=b,t(cl,b),t(Pt,b),t(\"tab-change\",b)},p=b=>{var C;if(s.value===b)return;const S=(C=e.beforeLeave)==null?void 0:C.call(e,b,s.value);hs(S)?S.then(()=>{var w,k;f(b),(k=(w=i.value)==null?void 0:w.removeFocus)==null||k.call(w)},Qt):S!==!1&&f(b)},v=(b,C,S)=>{b.props.disabled||(p(C),t(\"tab-click\",b,S))},m=(b,C)=>{b.props.disabled||(C.stopPropagation(),t(\"edit\",b.props.name,\"remove\"),t(\"tab-remove\",b.props.name))},y=()=>{t(\"edit\",void 0,\"add\"),t(\"tab-add\")};return ur(()=>d()),et(()=>d()),ce(()=>e.activeName,b=>p(b)),ce(()=>e.modelValue,b=>p(b)),ce(s,async()=>{var b,C;d(!0),await Ne(),await((b=i.value)==null?void 0:b.$nextTick()),(C=i.value)==null||C.scrollToActiveTab()}),ot(Hm,{props:e,currentName:s,updatePaneState:b=>c[b.uid]=b}),r({currentName:s}),()=>{const b=e.editable||e.addable?g(\"span\",{class:o.e(\"new-tab\"),tabindex:\"0\",onClick:y,onKeydown:w=>{w.code===Ge.enter&&y()}},[g(ft,{class:o.is(\"icon-plus\")},{default:()=>[g(cE,null,null)]})]):null,C=g(\"div\",{class:[o.e(\"header\"),o.is(e.tabPosition)]},[b,g(Dve,{ref:i,currentName:s.value,editable:e.editable,type:e.type,panes:l.value,stretch:e.stretch,onTabClick:v,onTabRemove:m},null)]),S=g(\"div\",{class:o.e(\"content\")},[Oe(n,\"default\")]);return g(\"div\",{class:[o.b(),o.m(e.tabPosition),{[o.m(\"card\")]:e.type===\"card\",[o.m(\"border-card\")]:e.type===\"border-card\"}]},[...e.tabPosition!==\"bottom\"?[C,S]:[S,C]])}}});const Bve=Ze({label:{type:String,default:\"\"},name:{type:[String,Number],default:\"\"},closable:Boolean,disabled:Boolean,lazy:Boolean}),Vve=[\"id\",\"aria-hidden\",\"aria-labelledby\"],zve={name:\"ElTabPane\"},Hve=G(Ke(Te({},zve),{props:Bve,setup(e){const t=e,n=\"ElTabPane\",r=$t(),a=ve(Hm);a||qn(n,\"usage: <el-tabs><el-tab-pane /></el-tabs/>\");const o=De(\"tab-pane\"),i=H(),l=x(()=>t.closable||a.props.closable),s=K$(()=>a.currentName.value===(t.name||i.value)),c=H(s.value),d=x(()=>t.name||i.value),f=K$(()=>!t.lazy||c.value||s.value);return ce(s,p=>{p&&(c.value=!0)}),a.updatePaneState(bt({uid:r.uid,instance:ps(r),props:t,paneName:d,active:s,index:i,isClosable:l})),(p,v)=>A(f)?at((R(),X(\"div\",{key:0,id:`pane-${A(d)}`,class:U(A(o).b()),role:\"tabpanel\",\"aria-hidden\":!A(s),\"aria-labelledby\":`tab-${A(d)}`},[Oe(p.$slots,\"default\")],10,Vve)),[[_t,A(s)]]):se(\"v-if\",!0)}}));var sI=Ae(Hve,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tabs/src/tab-pane.vue\"]]);const jve=xt(Fve,{TabPane:sI}),Kve=En(sI);mt.extend(tw);const{Option:Wve}=bs,ai=e=>{const t=(e||\"\").split(\":\");if(t.length>=2){let n=Number.parseInt(t[0],10);const r=Number.parseInt(t[1],10),a=e.toUpperCase();return a.includes(\"AM\")&&n===12?n=0:a.includes(\"PM\")&&n!==12&&(n+=12),{hours:n,minutes:r}}return null},Oy=(e,t)=>{const n=ai(e),r=ai(t),a=n.minutes+n.hours*60,o=r.minutes+r.hours*60;return a===o?0:a>o?1:-1},OO=e=>`${e}`.padStart(2,\"0\"),lu=e=>`${OO(e.hours)}:${OO(e.minutes)}`,Uve=(e,t)=>{const n=ai(e),r=ai(t),a={hours:n.hours,minutes:n.minutes};return a.minutes+=r.minutes,a.hours+=r.hours,a.hours+=Math.floor(a.minutes/60),a.minutes=a.minutes%60,lu(a)},Yve=G({name:\"ElTimeSelect\",components:{ElSelect:bs,ElOption:Wve,ElIcon:ft},model:{prop:\"value\",event:\"change\"},props:{format:{type:String,default:\"HH:mm\"},modelValue:String,disabled:{type:Boolean,default:!1},editable:{type:Boolean,default:!0},effect:{type:String,default:\"light\"},clearable:{type:Boolean,default:!0},size:{type:String,values:Bo,default:\"\"},placeholder:{type:String,default:\"\"},start:{type:String,default:\"09:00\"},end:{type:String,default:\"18:00\"},step:{type:String,default:\"00:30\"},minTime:{type:String,default:\"\"},maxTime:{type:String,default:\"\"},name:{type:String,default:\"\"},prefixIcon:{type:[String,Object],default:uE},clearIcon:{type:[String,Object],default:gi}},emits:[\"change\",\"blur\",\"focus\",\"update:modelValue\"],setup(e){const t=H(null),n=x(()=>e.modelValue),r=x(()=>{const f=ai(e.start);return lu(f)}),a=x(()=>{const f=ai(e.end);return lu(f)}),o=x(()=>{const f=ai(e.step);return lu(f)}),i=x(()=>{const f=ai(e.minTime);return f?lu(f):null}),l=x(()=>{const f=ai(e.maxTime);return f?lu(f):null}),s=x(()=>{const f=[];if(e.start&&e.end&&e.step){let p=r.value,v;for(;Oy(p,a.value)<=0;)v=mt(p,\"HH:mm\").format(e.format),f.push({value:v,disabled:Oy(p,i.value||\"-1:-1\")<=0||Oy(p,l.value||\"100:100\")>=0}),p=Uve(p,o.value)}return f});return{select:t,value:n,items:s,blur:()=>{var f,p;(p=(f=t.value)==null?void 0:f.blur)==null||p.call(f)},focus:()=>{var f,p;(p=(f=t.value)==null?void 0:f.focus)==null||p.call(f)}}}});function qve(e,t,n,r,a,o){const i=we(\"el-option\"),l=we(\"el-icon\"),s=we(\"el-select\");return R(),fe(s,{ref:\"select\",\"model-value\":e.value,disabled:e.disabled,clearable:e.clearable,\"clear-icon\":e.clearIcon,size:e.size,effect:e.effect,placeholder:e.placeholder,\"default-first-option\":\"\",filterable:e.editable,\"onUpdate:modelValue\":t[0]||(t[0]=c=>e.$emit(\"update:modelValue\",c)),onChange:t[1]||(t[1]=c=>e.$emit(\"change\",c)),onBlur:t[2]||(t[2]=c=>e.$emit(\"blur\",c)),onFocus:t[3]||(t[3]=c=>e.$emit(\"focus\",c))},{prefix:re(()=>[e.prefixIcon?(R(),fe(l,{key:0,class:\"el-input__prefix-icon\"},{default:re(()=>[(R(),fe(Kt(e.prefixIcon)))]),_:1})):se(\"v-if\",!0)]),default:re(()=>[(R(!0),X(Fe,null,Rt(e.items,c=>(R(),fe(i,{key:c.value,label:c.value,value:c.value,disabled:c.disabled},null,8,[\"label\",\"value\",\"disabled\"]))),128))]),_:1},8,[\"model-value\",\"disabled\",\"clearable\",\"clear-icon\",\"size\",\"effect\",\"placeholder\",\"filterable\"])}var _p=Ae(Yve,[[\"render\",qve],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/time-select/src/time-select.vue\"]]);_p.install=e=>{e.component(_p.name,_p)};const Gve=_p,Xve=Gve,Zve=G({name:\"ElTimeline\",setup(e,{slots:t}){const n=De(\"timeline\");return ot(\"timeline\",t),()=>qe(\"ul\",{class:[n.b()]},[Oe(t,\"default\")])}}),Jve=Ze({timestamp:{type:String,default:\"\"},hideTimestamp:{type:Boolean,default:!1},center:{type:Boolean,default:!1},placement:{type:String,default:\"bottom\"},type:{type:String,default:\"\"},color:{type:String,default:\"\"},size:{type:String,default:\"normal\"},icon:{type:wr,default:\"\"},hollow:{type:Boolean,default:!1}}),Qve=G({name:\"ElTimelineItem\",components:{ElIcon:ft},props:Jve,setup(){return{ns:De(\"timeline-item\")}}});function eme(e,t,n,r,a,o){const i=we(\"el-icon\");return R(),X(\"li\",{class:U([e.ns.b(),{[e.ns.e(\"center\")]:e.center}])},[Z(\"div\",{class:U(e.ns.e(\"tail\"))},null,2),e.$slots.dot?se(\"v-if\",!0):(R(),X(\"div\",{key:0,class:U([e.ns.e(\"node\"),e.ns.em(\"node\",e.size||\"\"),e.ns.em(\"node\",e.type||\"\"),e.ns.is(\"hollow\",e.hollow)]),style:Xe({backgroundColor:e.color})},[e.icon?(R(),fe(i,{key:0,class:U(e.ns.e(\"icon\"))},{default:re(()=>[(R(),fe(Kt(e.icon)))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],6)),e.$slots.dot?(R(),X(\"div\",{key:1,class:U(e.ns.e(\"dot\"))},[Oe(e.$slots,\"dot\")],2)):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.e(\"wrapper\"))},[!e.hideTimestamp&&e.placement===\"top\"?(R(),X(\"div\",{key:0,class:U([e.ns.e(\"timestamp\"),e.ns.is(\"top\")])},Me(e.timestamp),3)):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.e(\"content\"))},[Oe(e.$slots,\"default\")],2),!e.hideTimestamp&&e.placement===\"bottom\"?(R(),X(\"div\",{key:1,class:U([e.ns.e(\"timestamp\"),e.ns.is(\"bottom\")])},Me(e.timestamp),3)):se(\"v-if\",!0)],2)],2)}var uI=Ae(Qve,[[\"render\",eme],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/timeline/src/timeline-item.vue\"]]);const tme=xt(Zve,{TimelineItem:uI}),nme=En(uI),cI=Ze({nowrap:Boolean});var dI=(e=>(e.top=\"top\",e.bottom=\"bottom\",e.left=\"left\",e.right=\"right\",e))(dI||{});const rme=Object.values(dI),ww=Ze({width:{type:Number,default:10},height:{type:Number,default:10},style:{type:Le(Object),default:null}}),ame=Ze({side:{type:Le(String),values:rme,required:!0}}),ome=[\"absolute\",\"fixed\"],ime=[\"top-start\",\"top-end\",\"top\",\"bottom-start\",\"bottom-end\",\"bottom\",\"left-start\",\"left-end\",\"left\",\"right-start\",\"right-end\",\"right\"],Sw=Ze({ariaLabel:String,arrowPadding:{type:Le(Number),default:5},effect:{type:String,default:\"\"},contentClass:String,placement:{type:Le(String),values:ime,default:\"bottom\"},reference:{type:Le(Object),default:null},offset:{type:Number,default:8},strategy:{type:Le(String),values:ome,default:\"absolute\"},showArrow:{type:Boolean,default:!1}}),kw=Ze({delayDuration:{type:Number,default:300},defaultOpen:Boolean,open:{type:Boolean,default:void 0},onOpenChange:{type:Le(Function)},\"onUpdate:open\":{type:Le(Function)}}),zs={type:Le(Function)},$w=Ze({onBlur:zs,onClick:zs,onFocus:zs,onMouseDown:zs,onMouseEnter:zs,onMouseLeave:zs}),lme=Ze(Ke(Te(Te(Te(Te({},kw),ww),$w),Sw),{alwaysOn:Boolean,fullTransition:Boolean,transitionProps:{type:Le(Object),default:null},teleported:Boolean,to:{type:Le(String),default:\"body\"}})),sme={name:\"ElTooltipV2Root\"},ume=G(Ke(Te({},sme),{props:kw,setup(e,{expose:t}){const n=e,r=H(n.defaultOpen),a=H(null),o=x({get:()=>_U(n.open)?r.value:n.open,set:b=>{var C;r.value=b,(C=n[\"onUpdate:open\"])==null||C.call(n,b)}}),i=x(()=>Yt(n.delayDuration)&&n.delayDuration>0),{start:l,stop:s}=gs(()=>{o.value=!0},x(()=>n.delayDuration),{immediate:!1}),c=De(\"tooltip-v2\"),d=jC(),f=()=>{s(),o.value=!0},p=()=>{A(i)?l():f()},v=f,m=()=>{s(),o.value=!1};return ce(o,b=>{var C;b&&(document.dispatchEvent(new CustomEvent(oy)),v()),(C=n.onOpenChange)==null||C.call(n,b)}),et(()=>{document.addEventListener(oy,m)}),Lt(()=>{s(),document.removeEventListener(oy,m)}),ot(jm,{contentId:d,triggerRef:a,ns:c,onClose:m,onDelayOpen:p,onOpen:v}),t({onOpen:v,onClose:m}),(b,C)=>Oe(b.$slots,\"default\",{open:A(o)})}}));var cme=Ae(ume,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip-v2/src/root.vue\"]]);const dme={name:\"ElTooltipV2Arrow\"},fme=G(Ke(Te({},dme),{props:Te(Te({},ww),ame),setup(e){const t=e,{ns:n}=ve(jm),{arrowRef:r}=ve(IE),a=x(()=>{const{style:o,width:i,height:l}=t,s=n.namespace.value;return Te({[`--${s}-tooltip-v2-arrow-width`]:`${i}px`,[`--${s}-tooltip-v2-arrow-height`]:`${l}px`,[`--${s}-tooltip-v2-arrow-border-width`]:`${i/2}px`,[`--${s}-tooltip-v2-arrow-cover-width`]:i/2-1},o||{})});return(o,i)=>(R(),X(\"span\",{ref_key:\"arrowRef\",ref:r,style:Xe(A(a)),class:U(A(n).e(\"arrow\"))},null,6))}}));var PO=Ae(fme,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip-v2/src/arrow.vue\"]]);const hme=[\"data-side\"],pme={name:\"ElTooltipV2Content\"},vme=G(Ke(Te({},pme),{props:Te(Te({},Sw),cI),setup(e){const t=e,{triggerRef:n,contentId:r}=ve(jm),a=H(t.placement),o=H(t.strategy),i=H(null),{referenceRef:l,contentRef:s,middlewareData:c,x:d,y:f,update:p}=BZ({placement:a,strategy:o,middleware:x(()=>{const w=[IZ(t.offset)];return t.showArrow&&w.push(VZ({arrowRef:i})),w})}),v=Pi().nextZIndex(),m=De(\"tooltip-v2\"),y=x(()=>a.value.split(\"-\")[0]),b=x(()=>({position:A(o),top:`${A(f)||0}px`,left:`${A(d)||0}px`,zIndex:v})),C=x(()=>{if(!t.showArrow)return{};const{arrow:w}=A(c);return{[`--${m.namespace.value}-tooltip-v2-arrow-x`]:`${w==null?void 0:w.x}px`||\"\",[`--${m.namespace.value}-tooltip-v2-arrow-y`]:`${w==null?void 0:w.y}px`||\"\"}}),S=x(()=>[m.e(\"content\"),m.is(\"dark\",t.effect===\"dark\"),m.is(A(o)),t.contentClass]);return ce(i,()=>p()),ce(()=>t.placement,w=>a.value=w),et(()=>{ce(()=>t.reference||n.value,w=>{l.value=w||void 0},{immediate:!0})}),ot(IE,{arrowRef:i}),(w,k)=>(R(),X(\"div\",{ref_key:\"contentRef\",ref:s,style:Xe(A(b)),\"data-tooltip-v2-root\":\"\"},[w.nowrap?se(\"v-if\",!0):(R(),X(\"div\",{key:0,\"data-side\":A(y),class:U(A(S))},[Oe(w.$slots,\"default\",{contentStyle:A(b),contentClass:A(S)}),g(A(cM),{id:A(r),role:\"tooltip\"},{default:re(()=>[w.ariaLabel?(R(),X(Fe,{key:0},[yt(Me(w.ariaLabel),1)],2112)):Oe(w.$slots,\"default\",{key:1})]),_:3},8,[\"id\"]),Oe(w.$slots,\"arrow\",{style:Xe(A(C)),side:A(y)})],10,hme))],4))}}));var TO=Ae(vme,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip-v2/src/content.vue\"]]);const mme=Ze({setRef:{type:Le(Function),required:!0},onlyChild:Boolean});var gme=G({props:mme,setup(e,{slots:t}){const n=H(),r=FC(n,a=>{a?e.setRef(a.nextElementSibling):e.setRef(null)});return()=>{var a;const[o]=((a=t.default)==null?void 0:a.call(t))||[],i=e.onlyChild?ZX(o.children):o.children;return g(Fe,{ref:r},[i])}}});const yme={name:\"ElTooltipV2Trigger\"},bme=G(Ke(Te({},yme),{props:Te(Te({},cI),$w),setup(e){const t=e,{onClose:n,onOpen:r,onDelayOpen:a,triggerRef:o,contentId:i}=ve(jm);let l=!1;const s=S=>{o.value=S},c=()=>{l=!1},d=Tn(t.onMouseEnter,a),f=Tn(t.onMouseLeave,n),p=Tn(t.onMouseDown,()=>{n(),l=!0,document.addEventListener(\"mouseup\",c,{once:!0})}),v=Tn(t.onFocus,()=>{l||r()}),m=Tn(t.onBlur,n),y=Tn(t.onClick,S=>{S.detail===0&&n()}),b={blur:m,click:y,focus:v,mousedown:p,mouseenter:d,mouseleave:f},C=(S,w,k)=>{S&&Object.entries(w).forEach(([$,O])=>{S[k]($,O)})};return ce(o,(S,w)=>{C(S,b,\"addEventListener\"),C(w,b,\"removeEventListener\"),S&&S.setAttribute(\"aria-describedby\",i.value)}),Lt(()=>{C(o.value,b,\"removeEventListener\"),document.removeEventListener(\"mouseup\",c)}),(S,w)=>S.nowrap?(R(),fe(A(gme),{key:0,\"set-ref\":s,\"only-child\":\"\"},{default:re(()=>[Oe(S.$slots,\"default\")]),_:3})):(R(),X(\"button\",hn({key:1,ref_key:\"triggerRef\",ref:o},S.$attrs),[Oe(S.$slots,\"default\")],16))}}));var Cme=Ae(bme,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip-v2/src/trigger.vue\"]]);const wme={name:\"ElTooltipV2\"},Sme=G(Ke(Te({},wme),{props:lme,setup(e){const n=or(e),r=bt(Yi(n,Object.keys(ww))),a=bt(Yi(n,Object.keys(Sw))),o=bt(Yi(n,Object.keys(kw))),i=bt(Yi(n,Object.keys($w)));return(l,s)=>(R(),fe(cme,Za(ll(A(o))),{default:re(({open:c})=>[g(Cme,hn(A(i),{nowrap:\"\"}),{default:re(()=>[Oe(l.$slots,\"trigger\")]),_:3},16),(R(),fe(Ps,{to:l.to,disabled:!l.teleported},[l.fullTransition?(R(),fe(Vn,Za(hn({key:0},l.transitionProps)),{default:re(()=>[l.alwaysOn||c?(R(),fe(TO,Za(hn({key:0},A(a))),{arrow:re(({style:d,side:f})=>[l.showArrow?(R(),fe(PO,hn({key:0},A(r),{style:d,side:f}),null,16,[\"style\",\"side\"])):se(\"v-if\",!0)]),default:re(()=>[Oe(l.$slots,\"default\")]),_:3},16)):se(\"v-if\",!0)]),_:2},1040)):(R(),X(Fe,{key:1},[l.alwaysOn||c?(R(),fe(TO,Za(hn({key:0},A(a))),{arrow:re(({style:d,side:f})=>[l.showArrow?(R(),fe(PO,hn({key:0},A(r),{style:d,side:f}),null,16,[\"style\",\"side\"])):se(\"v-if\",!0)]),default:re(()=>[Oe(l.$slots,\"default\")]),_:3},16)):se(\"v-if\",!0)],2112))],8,[\"to\",\"disabled\"]))]),_:3},16))}}));var kme=Ae(Sme,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tooltip-v2/src/tooltip.vue\"]]);const $me=xt(kme),W0=\"checked-change\",Ome={data:{type:Array,default(){return[]}},optionRender:Function,placeholder:String,title:String,filterable:Boolean,format:Object,filterMethod:Function,defaultChecked:Array,props:Object},Pme=(e,t)=>{const{emit:n}=$t(),r=x(()=>e.props.label||\"label\"),a=x(()=>e.props.key||\"key\"),o=x(()=>e.props.disabled||\"disabled\"),i=x(()=>e.data.filter(p=>typeof e.filterMethod==\"function\"?e.filterMethod(t.query,p):(p[r.value]||p[a.value].toString()).toLowerCase().includes(t.query.toLowerCase()))),l=x(()=>i.value.filter(p=>!p[o.value])),s=x(()=>{const p=t.checked.length,v=e.data.length,{noChecked:m,hasChecked:y}=e.format;return m&&y?p>0?y.replace(/\\${checked}/g,p.toString()).replace(/\\${total}/g,v.toString()):m.replace(/\\${total}/g,v.toString()):`${p}/${v}`}),c=x(()=>{const p=t.checked.length;return p>0&&p<l.value.length}),d=()=>{const p=l.value.map(v=>v[a.value]);t.allChecked=p.length>0&&p.every(v=>t.checked.includes(v))},f=p=>{t.checked=p?l.value.map(v=>v[a.value]):[]};return ce(()=>t.checked,(p,v)=>{if(d(),t.checkChangeByUser){const m=p.concat(v).filter(y=>!p.includes(y)||!v.includes(y));n(W0,p,m)}else n(W0,p),t.checkChangeByUser=!0}),ce(l,()=>{d()}),ce(()=>e.data,()=>{const p=[],v=i.value.map(m=>m[a.value]);t.checked.forEach(m=>{v.includes(m)&&p.push(m)}),t.checkChangeByUser=!1,t.checked=p}),ce(()=>e.defaultChecked,(p,v)=>{if(v&&p.length===v.length&&p.every(b=>v.includes(b)))return;const m=[],y=l.value.map(b=>b[a.value]);p.forEach(b=>{y.includes(b)&&m.push(b)}),t.checkChangeByUser=!1,t.checked=m},{immediate:!0}),{labelProp:r,keyProp:a,disabledProp:o,filteredData:i,checkableData:l,checkedSummary:s,isIndeterminate:c,updateAllChecked:d,handleAllCheckedChange:f}},Tme=G({name:\"ElTransferPanel\",components:{ElCheckboxGroup:zM,ElCheckbox:io,ElInput:Ra,OptionContent:({option:e})=>e},props:Ome,emits:[W0],setup(e,{slots:t}){const{t:n}=ln(),r=De(\"transfer\"),a=bt({checked:[],allChecked:!1,query:\"\",inputHover:!1,checkChangeByUser:!0}),{labelProp:o,keyProp:i,disabledProp:l,filteredData:s,checkedSummary:c,isIndeterminate:d,handleAllCheckedChange:f}=Pme(e,a),p=x(()=>a.query.length>0&&s.value.length===0),v=x(()=>!!t.default()[0].children.length),{checked:m,allChecked:y,query:b,inputHover:C,checkChangeByUser:S}=or(a);return{ns:r,labelProp:o,keyProp:i,disabledProp:l,filteredData:s,checkedSummary:c,isIndeterminate:d,handleAllCheckedChange:f,checked:m,allChecked:y,query:b,inputHover:C,checkChangeByUser:S,hasNoMatch:p,SearchIcon:oX,hasFooter:v,t:n}}});function xme(e,t,n,r,a,o){const i=we(\"el-checkbox\"),l=we(\"el-input\"),s=we(\"option-content\"),c=we(\"el-checkbox-group\");return R(),X(\"div\",{class:U(e.ns.b(\"panel\"))},[Z(\"p\",{class:U(e.ns.be(\"panel\",\"header\"))},[g(i,{modelValue:e.allChecked,\"onUpdate:modelValue\":t[0]||(t[0]=d=>e.allChecked=d),indeterminate:e.isIndeterminate,onChange:e.handleAllCheckedChange},{default:re(()=>[yt(Me(e.title)+\" \",1),Z(\"span\",null,Me(e.checkedSummary),1)]),_:1},8,[\"modelValue\",\"indeterminate\",\"onChange\"])],2),Z(\"div\",{class:U([e.ns.be(\"panel\",\"body\"),e.ns.is(\"with-footer\",e.hasFooter)])},[e.filterable?(R(),fe(l,{key:0,modelValue:e.query,\"onUpdate:modelValue\":t[1]||(t[1]=d=>e.query=d),class:U(e.ns.be(\"panel\",\"filter\")),size:\"default\",placeholder:e.placeholder,\"prefix-icon\":e.SearchIcon,clearable:\"\",onMouseenter:t[2]||(t[2]=d=>e.inputHover=!0),onMouseleave:t[3]||(t[3]=d=>e.inputHover=!1)},null,8,[\"modelValue\",\"class\",\"placeholder\",\"prefix-icon\"])):se(\"v-if\",!0),at(g(c,{modelValue:e.checked,\"onUpdate:modelValue\":t[4]||(t[4]=d=>e.checked=d),class:U([e.ns.is(\"filterable\",e.filterable),e.ns.be(\"panel\",\"list\")])},{default:re(()=>[(R(!0),X(Fe,null,Rt(e.filteredData,d=>(R(),fe(i,{key:d[e.keyProp],class:U(e.ns.be(\"panel\",\"item\")),label:d[e.keyProp],disabled:d[e.disabledProp]},{default:re(()=>[g(s,{option:e.optionRender(d)},null,8,[\"option\"])]),_:2},1032,[\"class\",\"label\",\"disabled\"]))),128))]),_:1},8,[\"modelValue\",\"class\"]),[[_t,!e.hasNoMatch&&e.data.length>0]]),at(Z(\"p\",{class:U(e.ns.be(\"panel\",\"empty\"))},Me(e.hasNoMatch?e.t(\"el.transfer.noMatch\"):e.t(\"el.transfer.noData\")),3),[[_t,e.hasNoMatch||e.data.length===0]])],2),e.hasFooter?(R(),X(\"p\",{key:0,class:U(e.ns.be(\"panel\",\"footer\"))},[Oe(e.$slots,\"default\")],2)):se(\"v-if\",!0)],2)}var _me=Ae(Tme,[[\"render\",xme],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/transfer/src/transfer-panel.vue\"]]);const Eme=e=>{const t=x(()=>e.props.key),n=x(()=>e.data.reduce((o,i)=>(o[i[t.value]]=i)&&o,{})),r=x(()=>e.data.filter(o=>!e.modelValue.includes(o[t.value]))),a=x(()=>e.targetOrder===\"original\"?e.data.filter(o=>e.modelValue.includes(o[t.value])):e.modelValue.reduce((o,i)=>{const l=n.value[i];return l&&o.push(l),o},[]));return{propsKey:t,sourceData:r,targetData:a}},fI=\"left-check-change\",hI=\"right-check-change\",Mme=(e,t)=>({onSourceCheckedChange:(a,o)=>{e.leftChecked=a,o!==void 0&&t(fI,a,o)},onTargetCheckedChange:(a,o)=>{e.rightChecked=a,o!==void 0&&t(hI,a,o)}}),Ime=(e,t,n,r)=>{const a=(l,s,c)=>{r(Pt,l),r(ir,l,s,c)};return{addToLeft:()=>{const l=e.modelValue.slice();t.rightChecked.forEach(s=>{const c=l.indexOf(s);c>-1&&l.splice(c,1)}),a(l,\"left\",t.rightChecked)},addToRight:()=>{let l=e.modelValue.slice();const s=e.data.filter(c=>{const d=c[n.value];return t.leftChecked.includes(d)&&!e.modelValue.includes(d)}).map(c=>c[n.value]);l=e.targetOrder===\"unshift\"?s.concat(l):l.concat(s),e.targetOrder===\"original\"&&(l=e.data.filter(c=>l.includes(c[n.value])).map(c=>c[n.value])),a(l,\"right\",t.leftChecked)}}},Nme=G({name:\"ElTransfer\",components:{TransferPanel:_me,ElButton:xa,ElIcon:ft,ArrowLeft:Es,ArrowRight:Da},props:{data:{type:Array,default:()=>[]},titles:{type:Array,default:()=>[]},buttonTexts:{type:Array,default:()=>[]},filterPlaceholder:{type:String,default:\"\"},filterMethod:Function,leftDefaultChecked:{type:Array,default:()=>[]},rightDefaultChecked:{type:Array,default:()=>[]},renderContent:Function,modelValue:{type:Array,default:()=>[]},format:{type:Object,default:()=>({})},filterable:{type:Boolean,default:!1},props:{type:Object,default:()=>({label:\"label\",key:\"key\",disabled:\"disabled\"})},targetOrder:{type:String,default:\"original\",validator:e=>[\"original\",\"push\",\"unshift\"].includes(e)}},emits:[Pt,ir,fI,hI],setup(e,{emit:t,slots:n}){const{t:r}=ln(),a=De(\"transfer\"),o=ve(Ia,{}),i=bt({leftChecked:[],rightChecked:[]}),{propsKey:l,sourceData:s,targetData:c}=Eme(e),{onSourceCheckedChange:d,onTargetCheckedChange:f}=Mme(i,t),{addToLeft:p,addToRight:v}=Ime(e,i,l,t),m=H(),y=H(),b=O=>{switch(O){case\"left\":m.value.query=\"\";break;case\"right\":y.value.query=\"\";break}},C=x(()=>e.buttonTexts.length===2),S=x(()=>e.titles[0]||r(\"el.transfer.titles.0\")),w=x(()=>e.titles[1]||r(\"el.transfer.titles.1\")),k=x(()=>e.filterPlaceholder||r(\"el.transfer.filterPlaceholder\"));ce(()=>e.modelValue,()=>{var O;(O=o.validate)==null||O.call(o,\"change\").catch(T=>void 0)});const $=x(()=>O=>e.renderContent?e.renderContent(qe,O):n.default?n.default({option:O}):qe(\"span\",O[e.props.label]||O[e.props.key]));return Ke(Te({ns:a,sourceData:s,targetData:c,onSourceCheckedChange:d,onTargetCheckedChange:f,addToLeft:p,addToRight:v},or(i)),{hasButtonTexts:C,leftPanelTitle:S,rightPanelTitle:w,panelFilterPlaceholder:k,clearQuery:b,leftPanel:m,rightPanel:y,optionRender:$})}}),Ame={key:0},Dme={key:0};function Rme(e,t,n,r,a,o){const i=we(\"transfer-panel\"),l=we(\"arrow-left\"),s=we(\"el-icon\"),c=we(\"el-button\"),d=we(\"arrow-right\");return R(),X(\"div\",{class:U(e.ns.b())},[g(i,{ref:\"leftPanel\",data:e.sourceData,\"option-render\":e.optionRender,placeholder:e.panelFilterPlaceholder,title:e.leftPanelTitle,filterable:e.filterable,format:e.format,\"filter-method\":e.filterMethod,\"default-checked\":e.leftDefaultChecked,props:e.props,onCheckedChange:e.onSourceCheckedChange},{default:re(()=>[Oe(e.$slots,\"left-footer\")]),_:3},8,[\"data\",\"option-render\",\"placeholder\",\"title\",\"filterable\",\"format\",\"filter-method\",\"default-checked\",\"props\",\"onCheckedChange\"]),Z(\"div\",{class:U(e.ns.e(\"buttons\"))},[g(c,{type:\"primary\",class:U([e.ns.e(\"button\"),e.ns.is(\"with-texts\",e.hasButtonTexts)]),disabled:e.rightChecked.length===0,onClick:e.addToLeft},{default:re(()=>[g(s,null,{default:re(()=>[g(l)]),_:1}),e.buttonTexts[0]!==void 0?(R(),X(\"span\",Ame,Me(e.buttonTexts[0]),1)):se(\"v-if\",!0)]),_:1},8,[\"class\",\"disabled\",\"onClick\"]),g(c,{type:\"primary\",class:U([e.ns.e(\"button\"),e.ns.is(\"with-texts\",e.hasButtonTexts)]),disabled:e.leftChecked.length===0,onClick:e.addToRight},{default:re(()=>[e.buttonTexts[1]!==void 0?(R(),X(\"span\",Dme,Me(e.buttonTexts[1]),1)):se(\"v-if\",!0),g(s,null,{default:re(()=>[g(d)]),_:1})]),_:1},8,[\"class\",\"disabled\",\"onClick\"])],2),g(i,{ref:\"rightPanel\",data:e.targetData,\"option-render\":e.optionRender,placeholder:e.panelFilterPlaceholder,filterable:e.filterable,format:e.format,\"filter-method\":e.filterMethod,title:e.rightPanelTitle,\"default-checked\":e.rightDefaultChecked,props:e.props,onCheckedChange:e.onTargetCheckedChange},{default:re(()=>[Oe(e.$slots,\"right-footer\")]),_:3},8,[\"data\",\"option-render\",\"placeholder\",\"filterable\",\"format\",\"filter-method\",\"title\",\"default-checked\",\"props\",\"onCheckedChange\"])],2)}var Ep=Ae(Nme,[[\"render\",Rme],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/transfer/src/index.vue\"]]);Ep.install=e=>{e.component(Ep.name,Ep)};const Lme=Ep,Fme=Lme,_u=\"$treeNodeId\",xO=function(e,t){!t||t[_u]||Object.defineProperty(t,_u,{value:e.id,enumerable:!1,configurable:!1,writable:!1})},Ow=function(e,t){return e?t[e]:t[_u]},U0=e=>{let t=!0,n=!0,r=!0;for(let a=0,o=e.length;a<o;a++){const i=e[a];(i.checked!==!0||i.indeterminate)&&(t=!1,i.disabled||(r=!1)),(i.checked!==!1||i.indeterminate)&&(n=!1)}return{all:t,none:n,allWithoutDisable:r,half:!t&&!n}},Mp=function(e){if(e.childNodes.length===0)return;const{all:t,none:n,half:r}=U0(e.childNodes);t?(e.checked=!0,e.indeterminate=!1):r?(e.checked=!1,e.indeterminate=!0):n&&(e.checked=!1,e.indeterminate=!1);const a=e.parent;!a||a.level===0||e.store.checkStrictly||Mp(a)},fh=function(e,t){const n=e.store.props,r=e.data||{},a=n[t];if(typeof a==\"function\")return a(r,e);if(typeof a==\"string\")return r[a];if(typeof a==\"undefined\"){const o=r[t];return o===void 0?\"\":o}};let Bme=0;class is{constructor(t){this.id=Bme++,this.text=null,this.checked=!1,this.indeterminate=!1,this.data=null,this.expanded=!1,this.parent=null,this.visible=!0,this.isCurrent=!1,this.canFocus=!1;for(const n in t)Mt(t,n)&&(this[n]=t[n]);this.level=0,this.loaded=!1,this.childNodes=[],this.loading=!1,this.parent&&(this.level=this.parent.level+1)}initialize(){const t=this.store;if(!t)throw new Error(\"[Node]store is required!\");t.registerNode(this);const n=t.props;if(n&&typeof n.isLeaf!=\"undefined\"){const o=fh(this,\"isLeaf\");typeof o==\"boolean\"&&(this.isLeafByUser=o)}if(t.lazy!==!0&&this.data?(this.setData(this.data),t.defaultExpandAll&&(this.expanded=!0,this.canFocus=!0)):this.level>0&&t.lazy&&t.defaultExpandAll&&this.expand(),Array.isArray(this.data)||xO(this,this.data),!this.data)return;const r=t.defaultExpandedKeys,a=t.key;a&&r&&r.includes(this.key)&&this.expand(null,t.autoExpandParent),a&&t.currentNodeKey!==void 0&&this.key===t.currentNodeKey&&(t.currentNode=this,t.currentNode.isCurrent=!0),t.lazy&&t._initDefaultCheckedNode(this),this.updateLeafState(),this.parent&&(this.level===1||this.parent.expanded===!0)&&(this.canFocus=!0)}setData(t){Array.isArray(t)||xO(this,t),this.data=t,this.childNodes=[];let n;this.level===0&&Array.isArray(this.data)?n=this.data:n=fh(this,\"children\")||[];for(let r=0,a=n.length;r<a;r++)this.insertChild({data:n[r]})}get label(){return fh(this,\"label\")}get key(){const t=this.store.key;return this.data?this.data[t]:null}get disabled(){return fh(this,\"disabled\")}get nextSibling(){const t=this.parent;if(t){const n=t.childNodes.indexOf(this);if(n>-1)return t.childNodes[n+1]}return null}get previousSibling(){const t=this.parent;if(t){const n=t.childNodes.indexOf(this);if(n>-1)return n>0?t.childNodes[n-1]:null}return null}contains(t,n=!0){return(this.childNodes||[]).some(r=>r===t||n&&r.contains(t))}remove(){const t=this.parent;t&&t.removeChild(this)}insertChild(t,n,r){if(!t)throw new Error(\"InsertChild error: child is required.\");if(!(t instanceof is)){if(!r){const a=this.getChildren(!0);a.includes(t.data)||(typeof n==\"undefined\"||n<0?a.push(t.data):a.splice(n,0,t.data))}Object.assign(t,{parent:this,store:this.store}),t=bt(new is(t)),t instanceof is&&t.initialize()}t.level=this.level+1,typeof n==\"undefined\"||n<0?this.childNodes.push(t):this.childNodes.splice(n,0,t),this.updateLeafState()}insertBefore(t,n){let r;n&&(r=this.childNodes.indexOf(n)),this.insertChild(t,r)}insertAfter(t,n){let r;n&&(r=this.childNodes.indexOf(n),r!==-1&&(r+=1)),this.insertChild(t,r)}removeChild(t){const n=this.getChildren()||[],r=n.indexOf(t.data);r>-1&&n.splice(r,1);const a=this.childNodes.indexOf(t);a>-1&&(this.store&&this.store.deregisterNode(t),t.parent=null,this.childNodes.splice(a,1)),this.updateLeafState()}removeChildByData(t){let n=null;for(let r=0;r<this.childNodes.length;r++)if(this.childNodes[r].data===t){n=this.childNodes[r];break}n&&this.removeChild(n)}expand(t,n){const r=()=>{if(n){let a=this.parent;for(;a.level>0;)a.expanded=!0,a=a.parent}this.expanded=!0,t&&t(),this.childNodes.forEach(a=>{a.canFocus=!0})};this.shouldLoadData()?this.loadData(a=>{Array.isArray(a)&&(this.checked?this.setChecked(!0,!0):this.store.checkStrictly||Mp(this),r())}):r()}doCreateChildren(t,n={}){t.forEach(r=>{this.insertChild(Object.assign({data:r},n),void 0,!0)})}collapse(){this.expanded=!1,this.childNodes.forEach(t=>{t.canFocus=!1})}shouldLoadData(){return this.store.lazy===!0&&this.store.load&&!this.loaded}updateLeafState(){if(this.store.lazy===!0&&this.loaded!==!0&&typeof this.isLeafByUser!=\"undefined\"){this.isLeaf=this.isLeafByUser;return}const t=this.childNodes;if(!this.store.lazy||this.store.lazy===!0&&this.loaded===!0){this.isLeaf=!t||t.length===0;return}this.isLeaf=!1}setChecked(t,n,r,a){if(this.indeterminate=t===\"half\",this.checked=t===!0,this.store.checkStrictly)return;if(!(this.shouldLoadData()&&!this.store.checkDescendants)){const{all:i,allWithoutDisable:l}=U0(this.childNodes);!this.isLeaf&&!i&&l&&(this.checked=!1,t=!1);const s=()=>{if(n){const c=this.childNodes;for(let p=0,v=c.length;p<v;p++){const m=c[p];a=a||t!==!1;const y=m.disabled?m.checked:a;m.setChecked(y,n,!0,a)}const{half:d,all:f}=U0(c);f||(this.checked=f,this.indeterminate=d)}};if(this.shouldLoadData()){this.loadData(()=>{s(),Mp(this)},{checked:t!==!1});return}else s()}const o=this.parent;!o||o.level===0||r||Mp(o)}getChildren(t=!1){if(this.level===0)return this.data;const n=this.data;if(!n)return null;const r=this.store.props;let a=\"children\";return r&&(a=r.children||\"children\"),n[a]===void 0&&(n[a]=null),t&&!n[a]&&(n[a]=[]),n[a]}updateChildren(){const t=this.getChildren()||[],n=this.childNodes.map(o=>o.data),r={},a=[];t.forEach((o,i)=>{const l=o[_u];!!l&&n.findIndex(c=>c[_u]===l)>=0?r[l]={index:i,data:o}:a.push({index:i,data:o})}),this.store.lazy||n.forEach(o=>{r[o[_u]]||this.removeChildByData(o)}),a.forEach(({index:o,data:i})=>{this.insertChild({data:i},o)}),this.updateLeafState()}loadData(t,n={}){if(this.store.lazy===!0&&this.store.load&&!this.loaded&&(!this.loading||Object.keys(n).length)){this.loading=!0;const r=a=>{this.loaded=!0,this.loading=!1,this.childNodes=[],this.doCreateChildren(a,n),this.updateLeafState(),t&&t.call(this,a)};this.store.load(this,r)}else t&&t.call(this)}}class Vme{constructor(t){this.currentNode=null,this.currentNodeKey=null;for(const n in t)Mt(t,n)&&(this[n]=t[n]);this.nodesMap={}}initialize(){this.root=new is({data:this.data,store:this}),this.root.initialize(),this.lazy&&this.load?this.load(this.root,n=>{this.root.doCreateChildren(n),this._initDefaultCheckedNodes()}):this._initDefaultCheckedNodes()}filter(t){const n=this.filterNodeMethod,r=this.lazy,a=function(o){const i=o.root?o.root.childNodes:o.childNodes;if(i.forEach(l=>{l.visible=n.call(l,t,l.data,l),a(l)}),!o.visible&&i.length){let l=!0;l=!i.some(s=>s.visible),o.root?o.root.visible=l===!1:o.visible=l===!1}!t||o.visible&&!o.isLeaf&&!r&&o.expand()};a(this)}setData(t){t!==this.root.data?(this.root.setData(t),this._initDefaultCheckedNodes()):this.root.updateChildren()}getNode(t){if(t instanceof is)return t;const n=typeof t!=\"object\"?t:Ow(this.key,t);return this.nodesMap[n]||null}insertBefore(t,n){const r=this.getNode(n);r.parent.insertBefore({data:t},r)}insertAfter(t,n){const r=this.getNode(n);r.parent.insertAfter({data:t},r)}remove(t){const n=this.getNode(t);n&&n.parent&&(n===this.currentNode&&(this.currentNode=null),n.parent.removeChild(n))}append(t,n){const r=n?this.getNode(n):this.root;r&&r.insertChild({data:t})}_initDefaultCheckedNodes(){const t=this.defaultCheckedKeys||[],n=this.nodesMap;t.forEach(r=>{const a=n[r];a&&a.setChecked(!0,!this.checkStrictly)})}_initDefaultCheckedNode(t){(this.defaultCheckedKeys||[]).includes(t.key)&&t.setChecked(!0,!this.checkStrictly)}setDefaultCheckedKey(t){t!==this.defaultCheckedKeys&&(this.defaultCheckedKeys=t,this._initDefaultCheckedNodes())}registerNode(t){const n=this.key;!t||!t.data||(n?t.key!==void 0&&(this.nodesMap[t.key]=t):this.nodesMap[t.id]=t)}deregisterNode(t){!this.key||!t||!t.data||(t.childNodes.forEach(r=>{this.deregisterNode(r)}),delete this.nodesMap[t.key])}getCheckedNodes(t=!1,n=!1){const r=[],a=function(o){(o.root?o.root.childNodes:o.childNodes).forEach(l=>{(l.checked||n&&l.indeterminate)&&(!t||t&&l.isLeaf)&&r.push(l.data),a(l)})};return a(this),r}getCheckedKeys(t=!1){return this.getCheckedNodes(t).map(n=>(n||{})[this.key])}getHalfCheckedNodes(){const t=[],n=function(r){(r.root?r.root.childNodes:r.childNodes).forEach(o=>{o.indeterminate&&t.push(o.data),n(o)})};return n(this),t}getHalfCheckedKeys(){return this.getHalfCheckedNodes().map(t=>(t||{})[this.key])}_getAllNodes(){const t=[],n=this.nodesMap;for(const r in n)Mt(n,r)&&t.push(n[r]);return t}updateChildren(t,n){const r=this.nodesMap[t];if(!r)return;const a=r.childNodes;for(let o=a.length-1;o>=0;o--){const i=a[o];this.remove(i.data)}for(let o=0,i=n.length;o<i;o++){const l=n[o];this.append(l,r.data)}}_setCheckedKeys(t,n=!1,r){const a=this._getAllNodes().sort((l,s)=>s.level-l.level),o=Object.create(null),i=Object.keys(r);a.forEach(l=>l.setChecked(!1,!1));for(let l=0,s=a.length;l<s;l++){const c=a[l],d=c.data[t].toString();if(!i.includes(d)){c.checked&&!o[d]&&c.setChecked(!1,!1);continue}let p=c.parent;for(;p&&p.level>0;)o[p.data[t]]=!0,p=p.parent;if(c.isLeaf||this.checkStrictly){c.setChecked(!0,!1);continue}if(c.setChecked(!0,!0),n){c.setChecked(!1,!1);const v=function(m){m.childNodes.forEach(b=>{b.isLeaf||b.setChecked(!1,!1),v(b)})};v(c)}}}setCheckedNodes(t,n=!1){const r=this.key,a={};t.forEach(o=>{a[(o||{})[r]]=!0}),this._setCheckedKeys(r,n,a)}setCheckedKeys(t,n=!1){this.defaultCheckedKeys=t;const r=this.key,a={};t.forEach(o=>{a[o]=!0}),this._setCheckedKeys(r,n,a)}setDefaultExpandedKeys(t){t=t||[],this.defaultExpandedKeys=t,t.forEach(n=>{const r=this.getNode(n);r&&r.expand(null,this.autoExpandParent)})}setChecked(t,n,r){const a=this.getNode(t);a&&a.setChecked(!!n,r)}getCurrentNode(){return this.currentNode}setCurrentNode(t){const n=this.currentNode;n&&(n.isCurrent=!1),this.currentNode=t,this.currentNode.isCurrent=!0}setUserCurrentNode(t,n=!0){const r=t[this.key],a=this.nodesMap[r];this.setCurrentNode(a),n&&this.currentNode.level>1&&this.currentNode.parent.expand(null,!0)}setCurrentNodeKey(t,n=!0){if(t==null){this.currentNode&&(this.currentNode.isCurrent=!1),this.currentNode=null;return}const r=this.getNode(t);r&&(this.setCurrentNode(r),n&&this.currentNode.level>1&&this.currentNode.parent.expand(null,!0))}}const zme=G({name:\"ElTreeNodeContent\",props:{node:{type:Object,required:!0},renderContent:Function},setup(e){const t=De(\"tree\"),n=ve(\"NodeInstance\"),r=ve(\"RootTree\");return()=>{const a=e.node,{data:o,store:i}=a;return e.renderContent?e.renderContent(qe,{_self:n,node:a,data:o,store:i}):r.ctx.slots.default?r.ctx.slots.default({node:a,data:o}):qe(\"span\",{class:t.be(\"node\",\"label\")},[a.label])}}});var Hme=Ae(zme,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree/src/tree-node-content.vue\"]]);function pI(e){const t=ve(\"TreeNodeMap\",null),n={treeNodeExpand:r=>{e.node!==r&&e.node.collapse()},children:[]};return t&&t.children.push(n),ot(\"TreeNodeMap\",n),{broadcastExpanded:r=>{if(!!e.accordion)for(const a of n.children)a.treeNodeExpand(r)}}}const vI=Symbol(\"dragEvents\");function jme({props:e,ctx:t,el$:n,dropIndicator$:r,store:a}){const o=De(\"tree\"),i=H({showDropIndicator:!1,draggingNode:null,dropNode:null,allowDrop:!0,dropType:null});return ot(vI,{treeNodeDragStart:({event:d,treeNode:f})=>{if(typeof e.allowDrag==\"function\"&&!e.allowDrag(f.node))return d.preventDefault(),!1;d.dataTransfer.effectAllowed=\"move\";try{d.dataTransfer.setData(\"text/plain\",\"\")}catch{}i.value.draggingNode=f,t.emit(\"node-drag-start\",f.node,d)},treeNodeDragOver:({event:d,treeNode:f})=>{const p=f,v=i.value.dropNode;v&&v!==p&&Br(v.$el,o.is(\"drop-inner\"));const m=i.value.draggingNode;if(!m||!p)return;let y=!0,b=!0,C=!0,S=!0;typeof e.allowDrop==\"function\"&&(y=e.allowDrop(m.node,p.node,\"prev\"),S=b=e.allowDrop(m.node,p.node,\"inner\"),C=e.allowDrop(m.node,p.node,\"next\")),d.dataTransfer.dropEffect=b||y||C?\"move\":\"none\",(y||b||C)&&v!==p&&(v&&t.emit(\"node-drag-leave\",m.node,v.node,d),t.emit(\"node-drag-enter\",m.node,p.node,d)),(y||b||C)&&(i.value.dropNode=p),p.node.nextSibling===m.node&&(C=!1),p.node.previousSibling===m.node&&(y=!1),p.node.contains(m.node,!1)&&(b=!1),(m.node===p.node||m.node.contains(p.node))&&(y=!1,b=!1,C=!1);const w=p.$el.getBoundingClientRect(),k=n.value.getBoundingClientRect();let $;const O=y?b?.25:C?.45:1:-1,T=C?b?.75:y?.55:0:1;let _=-9999;const I=d.clientY-w.top;I<w.height*O?$=\"before\":I>w.height*T?$=\"after\":b?$=\"inner\":$=\"none\";const L=p.$el.querySelector(`.${o.be(\"node\",\"expand-icon\")}`).getBoundingClientRect(),j=r.value;$===\"before\"?_=L.top-k.top:$===\"after\"&&(_=L.bottom-k.top),j.style.top=`${_}px`,j.style.left=`${L.right-k.left}px`,$===\"inner\"?xo(p.$el,o.is(\"drop-inner\")):Br(p.$el,o.is(\"drop-inner\")),i.value.showDropIndicator=$===\"before\"||$===\"after\",i.value.allowDrop=i.value.showDropIndicator||S,i.value.dropType=$,t.emit(\"node-drag-over\",m.node,p.node,d)},treeNodeDragEnd:d=>{const{draggingNode:f,dropType:p,dropNode:v}=i.value;if(d.preventDefault(),d.dataTransfer.dropEffect=\"move\",f&&v){const m={data:f.node.data};p!==\"none\"&&f.node.remove(),p===\"before\"?v.node.parent.insertBefore(m,v.node):p===\"after\"?v.node.parent.insertAfter(m,v.node):p===\"inner\"&&v.node.insertChild(m),p!==\"none\"&&a.value.registerNode(m),Br(v.$el,o.is(\"drop-inner\")),t.emit(\"node-drag-end\",f.node,v.node,p,d),p!==\"none\"&&t.emit(\"node-drop\",f.node,v.node,p,d)}f&&!v&&t.emit(\"node-drag-end\",f.node,null,p,d),i.value.showDropIndicator=!1,i.value.draggingNode=null,i.value.dropNode=null,i.value.allowDrop=!0}}),{dragState:i}}const Kme=G({name:\"ElTreeNode\",components:{ElCollapseTransition:Xm,ElCheckbox:io,NodeContent:Hme,ElIcon:ft,Loading:gl},props:{node:{type:is,default:()=>({})},props:{type:Object,default:()=>({})},accordion:Boolean,renderContent:Function,renderAfterExpand:Boolean,showCheckbox:{type:Boolean,default:!1}},emits:[\"node-expand\"],setup(e,t){const n=De(\"tree\"),{broadcastExpanded:r}=pI(e),a=ve(\"RootTree\"),o=H(!1),i=H(!1),l=H(null),s=H(null),c=H(null),d=ve(vI),f=$t();ot(\"NodeInstance\",f),e.node.expanded&&(o.value=!0,i.value=!0);const p=a.props.children||\"children\";ce(()=>{const I=e.node.data[p];return I&&[...I]},()=>{e.node.updateChildren()}),ce(()=>e.node.indeterminate,I=>{y(e.node.checked,I)}),ce(()=>e.node.checked,I=>{y(I,e.node.indeterminate)}),ce(()=>e.node.expanded,I=>{Ne(()=>o.value=I),I&&(i.value=!0)});const v=I=>Ow(a.props.nodeKey,I.data),m=I=>{const L=e.props.class;if(!L)return{};let j;if(Ct(L)){const{data:F}=I;j=L(F,I)}else j=L;return wt(j)?{[j]:!0}:j},y=(I,L)=>{(l.value!==I||s.value!==L)&&a.ctx.emit(\"check-change\",e.node.data,I,L),l.value=I,s.value=L},b=I=>{const L=a.store.value;L.setCurrentNode(e.node),a.ctx.emit(\"current-change\",L.currentNode?L.currentNode.data:null,L.currentNode),a.currentNode.value=e.node,a.props.expandOnClickNode&&S(),a.props.checkOnClickNode&&!e.node.disabled&&w(null,{target:{checked:!e.node.checked}}),a.ctx.emit(\"node-click\",e.node.data,e.node,f,I)},C=I=>{a.instance.vnode.props.onNodeContextmenu&&(I.stopPropagation(),I.preventDefault()),a.ctx.emit(\"node-contextmenu\",I,e.node.data,e.node,f)},S=()=>{e.node.isLeaf||(o.value?(a.ctx.emit(\"node-collapse\",e.node.data,e.node,f),e.node.collapse()):(e.node.expand(),t.emit(\"node-expand\",e.node.data,e.node,f)))},w=(I,L)=>{e.node.setChecked(L.target.checked,!a.props.checkStrictly),Ne(()=>{const j=a.store.value;a.ctx.emit(\"check\",e.node.data,{checkedNodes:j.getCheckedNodes(),checkedKeys:j.getCheckedKeys(),halfCheckedNodes:j.getHalfCheckedNodes(),halfCheckedKeys:j.getHalfCheckedKeys()})})};return{ns:n,node$:c,tree:a,expanded:o,childNodeRendered:i,oldChecked:l,oldIndeterminate:s,getNodeKey:v,getNodeClass:m,handleSelectChange:y,handleClick:b,handleContextMenu:C,handleExpandIconClick:S,handleCheckChange:w,handleChildNodeExpand:(I,L,j)=>{r(L),a.ctx.emit(\"node-expand\",I,L,j)},handleDragStart:I=>{!a.props.draggable||d.treeNodeDragStart({event:I,treeNode:e})},handleDragOver:I=>{I.preventDefault(),a.props.draggable&&d.treeNodeDragOver({event:I,treeNode:{$el:c.value,node:e.node}})},handleDrop:I=>{I.preventDefault()},handleDragEnd:I=>{!a.props.draggable||d.treeNodeDragEnd(I)},CaretRight:sE}}}),Wme=[\"aria-expanded\",\"aria-disabled\",\"aria-checked\",\"draggable\",\"data-key\"],Ume=[\"aria-expanded\"];function Yme(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"el-checkbox\"),s=we(\"loading\"),c=we(\"node-content\"),d=we(\"el-tree-node\"),f=we(\"el-collapse-transition\");return at((R(),X(\"div\",{ref:\"node$\",class:U([e.ns.b(\"node\"),e.ns.is(\"expanded\",e.expanded),e.ns.is(\"current\",e.node.isCurrent),e.ns.is(\"hidden\",!e.node.visible),e.ns.is(\"focusable\",!e.node.disabled),e.ns.is(\"checked\",!e.node.disabled&&e.node.checked),e.getNodeClass(e.node)]),role:\"treeitem\",tabindex:\"-1\",\"aria-expanded\":e.expanded,\"aria-disabled\":e.node.disabled,\"aria-checked\":e.node.checked,draggable:e.tree.props.draggable,\"data-key\":e.getNodeKey(e.node),onClick:t[1]||(t[1]=dt((...p)=>e.handleClick&&e.handleClick(...p),[\"stop\"])),onContextmenu:t[2]||(t[2]=(...p)=>e.handleContextMenu&&e.handleContextMenu(...p)),onDragstart:t[3]||(t[3]=dt((...p)=>e.handleDragStart&&e.handleDragStart(...p),[\"stop\"])),onDragover:t[4]||(t[4]=dt((...p)=>e.handleDragOver&&e.handleDragOver(...p),[\"stop\"])),onDragend:t[5]||(t[5]=dt((...p)=>e.handleDragEnd&&e.handleDragEnd(...p),[\"stop\"])),onDrop:t[6]||(t[6]=dt((...p)=>e.handleDrop&&e.handleDrop(...p),[\"stop\"]))},[Z(\"div\",{class:U(e.ns.be(\"node\",\"content\")),style:Xe({paddingLeft:(e.node.level-1)*e.tree.props.indent+\"px\"})},[e.tree.props.icon||e.CaretRight?(R(),fe(i,{key:0,class:U([e.ns.be(\"node\",\"expand-icon\"),e.ns.is(\"leaf\",e.node.isLeaf),{expanded:!e.node.isLeaf&&e.expanded}]),onClick:dt(e.handleExpandIconClick,[\"stop\"])},{default:re(()=>[(R(),fe(Kt(e.tree.props.icon||e.CaretRight)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0),e.showCheckbox?(R(),fe(l,{key:1,\"model-value\":e.node.checked,indeterminate:e.node.indeterminate,disabled:!!e.node.disabled,onClick:t[0]||(t[0]=dt(()=>{},[\"stop\"])),onChange:e.handleCheckChange},null,8,[\"model-value\",\"indeterminate\",\"disabled\",\"onChange\"])):se(\"v-if\",!0),e.node.loading?(R(),fe(i,{key:2,class:U([e.ns.be(\"node\",\"loading-icon\"),e.ns.is(\"loading\")])},{default:re(()=>[g(s)]),_:1},8,[\"class\"])):se(\"v-if\",!0),g(c,{node:e.node,\"render-content\":e.renderContent},null,8,[\"node\",\"render-content\"])],6),g(f,null,{default:re(()=>[!e.renderAfterExpand||e.childNodeRendered?at((R(),X(\"div\",{key:0,class:U(e.ns.be(\"node\",\"children\")),role:\"group\",\"aria-expanded\":e.expanded},[(R(!0),X(Fe,null,Rt(e.node.childNodes,p=>(R(),fe(d,{key:e.getNodeKey(p),\"render-content\":e.renderContent,\"render-after-expand\":e.renderAfterExpand,\"show-checkbox\":e.showCheckbox,node:p,accordion:e.accordion,props:e.props,onNodeExpand:e.handleChildNodeExpand},null,8,[\"render-content\",\"render-after-expand\",\"show-checkbox\",\"node\",\"accordion\",\"props\",\"onNodeExpand\"]))),128))],10,Ume)),[[_t,e.expanded]]):se(\"v-if\",!0)]),_:1})],42,Wme)),[[_t,e.node.visible]])}var qme=Ae(Kme,[[\"render\",Yme],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree/src/tree-node.vue\"]]);function Gme({el$:e},t){const n=De(\"tree\"),r=Qn([]),a=Qn([]);et(()=>{i(),gn(e.value,\"keydown\",o)}),Lt(()=>{Bn(e.value,\"keydown\",o)}),ur(()=>{r.value=Array.from(e.value.querySelectorAll(\"[role=treeitem]\")),a.value=Array.from(e.value.querySelectorAll(\"input[type=checkbox]\"))}),ce(a,l=>{l.forEach(s=>{s.setAttribute(\"tabindex\",\"-1\")})});const o=l=>{const s=l.target;if(!s.className.includes(n.b(\"node\")))return;const c=l.code;r.value=Array.from(e.value.querySelectorAll(`.${n.is(\"focusable\")}[role=treeitem]`));const d=r.value.indexOf(s);let f;if([Ge.up,Ge.down].includes(c)){if(l.preventDefault(),c===Ge.up){f=d===-1?0:d!==0?d-1:r.value.length-1;const v=f;for(;!t.value.getNode(r.value[f].dataset.key).canFocus;){if(f--,f===v){f=-1;break}f<0&&(f=r.value.length-1)}}else{f=d===-1?0:d<r.value.length-1?d+1:0;const v=f;for(;!t.value.getNode(r.value[f].dataset.key).canFocus;){if(f++,f===v){f=-1;break}f>=r.value.length&&(f=0)}}f!==-1&&r.value[f].focus()}[Ge.left,Ge.right].includes(c)&&(l.preventDefault(),s.click());const p=s.querySelector('[type=\"checkbox\"]');[Ge.enter,Ge.space].includes(c)&&p&&(l.preventDefault(),p.click())},i=()=>{var l;r.value=Array.from(e.value.querySelectorAll(`.${n.is(\"focusable\")}[role=treeitem]`)),a.value=Array.from(e.value.querySelectorAll(\"input[type=checkbox]\"));const s=e.value.querySelectorAll(`.${n.is(\"checked\")}[role=treeitem]`);if(s.length){s[0].setAttribute(\"tabindex\",\"0\");return}(l=r.value[0])==null||l.setAttribute(\"tabindex\",\"0\")}}const Xme=G({name:\"ElTree\",components:{ElTreeNode:qme},props:{data:{type:Array,default:()=>[]},emptyText:{type:String},renderAfterExpand:{type:Boolean,default:!0},nodeKey:String,checkStrictly:Boolean,defaultExpandAll:Boolean,expandOnClickNode:{type:Boolean,default:!0},checkOnClickNode:Boolean,checkDescendants:{type:Boolean,default:!1},autoExpandParent:{type:Boolean,default:!0},defaultCheckedKeys:Array,defaultExpandedKeys:Array,currentNodeKey:[String,Number],renderContent:Function,showCheckbox:{type:Boolean,default:!1},draggable:{type:Boolean,default:!1},allowDrag:Function,allowDrop:Function,props:{type:Object,default:()=>({children:\"children\",label:\"label\",disabled:\"disabled\"})},lazy:{type:Boolean,default:!1},highlightCurrent:Boolean,load:Function,filterNodeMethod:Function,accordion:Boolean,indent:{type:Number,default:18},icon:[String,Object]},emits:[\"check-change\",\"current-change\",\"node-click\",\"node-contextmenu\",\"node-collapse\",\"node-expand\",\"check\",\"node-drag-start\",\"node-drag-end\",\"node-drop\",\"node-drag-leave\",\"node-drag-enter\",\"node-drag-over\"],setup(e,t){const{t:n}=ln(),r=De(\"tree\"),a=H(new Vme({key:e.nodeKey,data:e.data,lazy:e.lazy,props:e.props,load:e.load,currentNodeKey:e.currentNodeKey,checkStrictly:e.checkStrictly,checkDescendants:e.checkDescendants,defaultCheckedKeys:e.defaultCheckedKeys,defaultExpandedKeys:e.defaultExpandedKeys,autoExpandParent:e.autoExpandParent,defaultExpandAll:e.defaultExpandAll,filterNodeMethod:e.filterNodeMethod}));a.value.initialize();const o=H(a.value.root),i=H(null),l=H(null),s=H(null),{broadcastExpanded:c}=pI(e),{dragState:d}=jme({props:e,ctx:t,el$:l,dropIndicator$:s,store:a});Gme({el$:l},a);const f=x(()=>{const{childNodes:M}=o.value;return!M||M.length===0||M.every(({visible:E})=>!E)});ce(()=>e.defaultCheckedKeys,M=>{a.value.setDefaultCheckedKey(M)}),ce(()=>e.defaultExpandedKeys,M=>{a.value.setDefaultExpandedKeys(M)}),ce(()=>e.data,M=>{a.value.setData(M)},{deep:!0}),ce(()=>e.checkStrictly,M=>{a.value.checkStrictly=M});const p=M=>{if(!e.filterNodeMethod)throw new Error(\"[Tree] filterNodeMethod is required when filter\");a.value.filter(M)},v=M=>Ow(e.nodeKey,M.data),m=M=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in getNodePath\");const E=a.value.getNode(M);if(!E)return[];const K=[E.data];let W=E.parent;for(;W&&W!==o.value;)K.push(W.data),W=W.parent;return K.reverse()},y=(M,E)=>a.value.getCheckedNodes(M,E),b=M=>a.value.getCheckedKeys(M),C=()=>{const M=a.value.getCurrentNode();return M?M.data:null},S=()=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in getCurrentKey\");const M=C();return M?M[e.nodeKey]:null},w=(M,E)=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in setCheckedNodes\");a.value.setCheckedNodes(M,E)},k=(M,E)=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in setCheckedKeys\");a.value.setCheckedKeys(M,E)},$=(M,E,K)=>{a.value.setChecked(M,E,K)},O=()=>a.value.getHalfCheckedNodes(),T=()=>a.value.getHalfCheckedKeys(),_=(M,E=!0)=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in setCurrentNode\");a.value.setUserCurrentNode(M,E)},I=(M,E=!0)=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in setCurrentKey\");a.value.setCurrentNodeKey(M,E)},L=M=>a.value.getNode(M),j=M=>{a.value.remove(M)},F=(M,E)=>{a.value.append(M,E)},N=(M,E)=>{a.value.insertBefore(M,E)},D=(M,E)=>{a.value.insertAfter(M,E)},z=(M,E,K)=>{c(E),t.emit(\"node-expand\",M,E,K)},B=(M,E)=>{if(!e.nodeKey)throw new Error(\"[Tree] nodeKey is required in updateKeyChild\");a.value.updateChildren(M,E)};return ot(\"RootTree\",{ctx:t,props:e,store:a,root:o,currentNode:i,instance:$t()}),{ns:r,store:a,root:o,currentNode:i,dragState:d,el$:l,dropIndicator$:s,isEmpty:f,filter:p,getNodeKey:v,getNodePath:m,getCheckedNodes:y,getCheckedKeys:b,getCurrentNode:C,getCurrentKey:S,setCheckedNodes:w,setCheckedKeys:k,setChecked:$,getHalfCheckedNodes:O,getHalfCheckedKeys:T,setCurrentNode:_,setCurrentKey:I,t:n,getNode:L,remove:j,append:F,insertBefore:N,insertAfter:D,handleNodeExpand:z,updateKeyChildren:B}}});function Zme(e,t,n,r,a,o){var i;const l=we(\"el-tree-node\");return R(),X(\"div\",{ref:\"el$\",class:U([e.ns.b(),e.ns.is(\"dragging\",!!e.dragState.draggingNode),e.ns.is(\"drop-not-allow\",!e.dragState.allowDrop),e.ns.is(\"drop-inner\",e.dragState.dropType===\"inner\"),{[e.ns.m(\"highlight-current\")]:e.highlightCurrent}]),role:\"tree\"},[(R(!0),X(Fe,null,Rt(e.root.childNodes,s=>(R(),fe(l,{key:e.getNodeKey(s),node:s,props:e.props,accordion:e.accordion,\"render-after-expand\":e.renderAfterExpand,\"show-checkbox\":e.showCheckbox,\"render-content\":e.renderContent,onNodeExpand:e.handleNodeExpand},null,8,[\"node\",\"props\",\"accordion\",\"render-after-expand\",\"show-checkbox\",\"render-content\",\"onNodeExpand\"]))),128)),e.isEmpty?(R(),X(\"div\",{key:0,class:U(e.ns.e(\"empty-block\"))},[Z(\"span\",{class:U(e.ns.e(\"empty-text\"))},Me((i=e.emptyText)!=null?i:e.t(\"el.tree.emptyText\")),3)],2)):se(\"v-if\",!0),at(Z(\"div\",{ref:\"dropIndicator$\",class:U(e.ns.e(\"drop-indicator\"))},null,2),[[_t,e.dragState.showDropIndicator]])],2)}var Ip=Ae(Xme,[[\"render\",Zme],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree/src/tree.vue\"]]);Ip.install=e=>{e.component(Ip.name,Ip)};const Ov=Ip,Jme=Ov,Qme=(e,{attrs:t},{tree:n,key:r})=>{const a=De(\"tree-select\"),o=Ke(Te(Te({},Yi(or(e),Object.keys(bs.props))),t),{valueKey:r,popperClass:x(()=>{const i=[a.e(\"popper\")];return e.popperClass&&i.push(e.popperClass),i.join(\" \")}),filterMethod:(i=\"\")=>{e.filterMethod&&e.filterMethod(i),Ne(()=>{var l;(l=n.value)==null||l.filter(i)})},onVisibleChange:i=>{var l;(l=t.onVisibleChange)==null||l.call(t,i),e.filterable&&i&&o.filterMethod()}});return o},ege=G({extends:Cv,setup(e,t){const n=Cv.setup(e,t);return delete n.selectOptionClick,n},methods:{selectOptionClick(){this.$el.parentElement.click()}}}),tge=(e,{attrs:t,slots:n,emit:r},{select:a,tree:o,key:i})=>{ce(()=>e.modelValue,()=>{e.showCheckbox&&Ne(()=>{const c=o.value;c&&!er(c.getCheckedKeys(),Py(e.modelValue))&&c.setCheckedKeys(Py(e.modelValue))})},{immediate:!0,deep:!0});const l=x(()=>Te({value:i.value},e.props)),s=(c,d)=>{var f;const p=l.value[c];return Ct(p)?p(d,(f=o.value)==null?void 0:f.getNode(s(\"value\",d))):d[p]};return Ke(Te(Te({},Yi(or(e),Object.keys(Ov.props))),t),{nodeKey:i,defaultExpandedKeys:x(()=>e.defaultExpandedKeys?e.defaultExpandedKeys.concat(e.modelValue):Py(e.modelValue)),renderContent:(c,{node:d,data:f,store:p})=>c(ege,{value:s(\"value\",f),label:s(\"label\",f),disabled:s(\"disabled\",f)},e.renderContent?()=>e.renderContent(c,{node:d,data:f,store:p}):n.default?()=>n.default({node:d,data:f,store:p}):void 0),filterNodeMethod:(c,d,f)=>{var p;return e.filterNodeMethod?e.filterNodeMethod(c,d,f):c?(p=s(\"label\",d))==null?void 0:p.includes(c):!0},onNodeClick:(c,d,f)=>{var p,v,m;if((p=t.onNodeClick)==null||p.call(t,c,d,f),e.checkStrictly||d.isLeaf){if(!s(\"disabled\",c)){const y=(v=a.value)==null?void 0:v.options.get(s(\"value\",c));(m=a.value)==null||m.handleOptionSelect(y,!0)}}else f.ctx.handleExpandIconClick()},onCheck:(c,d)=>{var f,p;(f=t.onCheck)==null||f.call(t,c,d);const v=e.checkStrictly?d.checkedKeys:(p=o.value)==null?void 0:p.getCheckedKeys(!0),m=s(\"value\",c);r(Pt,e.multiple?v:v.includes(m)?m:void 0)}})};function Py(e){return Array.isArray(e)?e:e||e===0?[e]:[]}const nge=G({name:\"ElTreeSelect\",props:Te(Te({},bs.props),Ov.props),setup(e,t){const{slots:n,expose:r}=t,a=H(),o=H(),i=x(()=>e.valueKey||e.nodeKey||\"value\"),l=Qme(e,t,{select:a,tree:o,key:i}),s=tge(e,t,{select:a,tree:o,key:i}),c=bt({});return r(c),et(()=>{Object.assign(c,Te(Te({},Yi(o.value,[\"filter\",\"updateKeyChildren\",\"getCheckedNodes\",\"setCheckedNodes\",\"getCheckedKeys\",\"setCheckedKeys\",\"setChecked\",\"getHalfCheckedNodes\",\"getHalfCheckedKeys\",\"getCurrentKey\",\"getCurrentNode\",\"setCurrentKey\",\"setCurrentNode\",\"getNode\",\"remove\",\"append\",\"insertBefore\",\"insertAfter\"])),Yi(a.value,[\"focus\",\"blur\"])))}),()=>qe(bs,bt(Ke(Te({},l),{ref:d=>a.value=d})),Ke(Te({},n),{default:()=>qe(Ov,bt(Ke(Te({},s),{ref:d=>o.value=d})))}))}});var Np=Ae(nge,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree-select/src/tree-select.vue\"]]);Np.install=e=>{e.component(Np.name,Np)};const rge=Np,age=rge,Pw=Symbol(),oge={key:-1,level:-1,data:{}};var rd=(e=>(e.KEY=\"id\",e.LABEL=\"label\",e.CHILDREN=\"children\",e.DISABLED=\"disabled\",e))(rd||{}),Y0=(e=>(e.ADD=\"add\",e.DELETE=\"delete\",e))(Y0||{});const ige=Ze({data:{type:Le(Array),default:()=>xn([])},emptyText:{type:String},height:{type:Number,default:200},props:{type:Le(Object),default:()=>xn({children:\"children\",label:\"label\",disabled:\"disabled\",value:\"id\"})},highlightCurrent:{type:Boolean,default:!1},showCheckbox:{type:Boolean,default:!1},defaultCheckedKeys:{type:Le(Array),default:()=>xn([])},checkStrictly:{type:Boolean,default:!1},defaultExpandedKeys:{type:Le(Array),default:()=>xn([])},indent:{type:Number,default:16},icon:{type:String},expandOnClickNode:{type:Boolean,default:!0},checkOnClickNode:{type:Boolean,default:!1},currentNodeKey:{type:Le([String,Number])},accordion:{type:Boolean,default:!1},filterMethod:{type:Le(Function)},perfMode:{type:Boolean,default:!0}}),lge=Ze({node:{type:Le(Object),default:()=>xn(oge)},expanded:{type:Boolean,default:!1},checked:{type:Boolean,default:!1},indeterminate:{type:Boolean,default:!1},showCheckbox:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},current:{type:Boolean,default:!1},hiddenExpandIcon:{type:Boolean,default:!1}}),sge=Ze({node:{type:Le(Object),required:!0}}),mI=\"node-click\",gI=\"node-expand\",yI=\"node-collapse\",bI=\"current-change\",CI=\"check\",wI=\"check-change\",SI=\"node-contextmenu\",uge={[mI]:(e,t,n)=>e&&t&&n,[gI]:(e,t)=>e&&t,[yI]:(e,t)=>e&&t,[bI]:(e,t)=>e&&t,[CI]:(e,t)=>e&&t,[wI]:(e,t)=>e&&typeof t==\"boolean\",[SI]:(e,t,n)=>e&&t&&n},cge={click:(e,t)=>!!(e&&t),toggle:e=>!!e,check:(e,t)=>e&&typeof t==\"boolean\"};function dge(e,t){const n=H(new Set),r=H(new Set),{emit:a}=$t();ce(()=>t.value,()=>Ne(()=>{S(e.defaultCheckedKeys)}),{immediate:!0});const o=()=>{if(!t.value||!e.showCheckbox||e.checkStrictly)return;const{levelTreeNodeMap:w,maxLevel:k}=t.value,$=n.value,O=new Set;for(let T=k-1;T>=1;--T){const _=w.get(T);!_||_.forEach(I=>{const L=I.children;if(L){let j=!0,F=!1;for(const N of L){const D=N.key;if($.has(D))F=!0;else if(O.has(D)){j=!1,F=!0;break}else j=!1}j?$.add(I.key):F?(O.add(I.key),$.delete(I.key)):($.delete(I.key),O.delete(I.key))}})}r.value=O},i=w=>n.value.has(w.key),l=w=>r.value.has(w.key),s=(w,k,$=!0)=>{const O=n.value,T=(_,I)=>{O[I?Y0.ADD:Y0.DELETE](_.key);const L=_.children;!e.checkStrictly&&L&&L.forEach(j=>{j.disabled||T(j,I)})};T(w,k),o(),$&&c(w,k)},c=(w,k)=>{const{checkedNodes:$,checkedKeys:O}=m(),{halfCheckedNodes:T,halfCheckedKeys:_}=y();a(CI,w.data,{checkedKeys:O,checkedNodes:$,halfCheckedKeys:_,halfCheckedNodes:T}),a(wI,w.data,k)};function d(w=!1){return m(w).checkedKeys}function f(w=!1){return m(w).checkedNodes}function p(){return y().halfCheckedKeys}function v(){return y().halfCheckedNodes}function m(w=!1){const k=[],$=[];if((t==null?void 0:t.value)&&e.showCheckbox){const{treeNodeMap:O}=t.value;n.value.forEach(T=>{const _=O.get(T);_&&(!w||w&&_.isLeaf)&&($.push(T),k.push(_.data))})}return{checkedKeys:$,checkedNodes:k}}function y(){const w=[],k=[];if((t==null?void 0:t.value)&&e.showCheckbox){const{treeNodeMap:$}=t.value;r.value.forEach(O=>{const T=$.get(O);T&&(k.push(O),w.push(T.data))})}return{halfCheckedNodes:w,halfCheckedKeys:k}}function b(w){n.value.clear(),r.value.clear(),S(w)}function C(w,k){if((t==null?void 0:t.value)&&e.showCheckbox){const $=t.value.treeNodeMap.get(w);$&&s($,k,!1)}}function S(w){if(t!=null&&t.value){const{treeNodeMap:k}=t.value;if(e.showCheckbox&&k&&w)for(const $ of w){const O=k.get($);O&&!i(O)&&s(O,!0,!1)}}}return{updateCheckedKeys:o,toggleCheckbox:s,isChecked:i,isIndeterminate:l,getCheckedKeys:d,getCheckedNodes:f,getHalfCheckedKeys:p,getHalfCheckedNodes:v,setChecked:C,setCheckedKeys:b}}function fge(e,t){const n=H(new Set([])),r=H(new Set([])),a=x(()=>Ct(e.filterMethod));function o(l){var s;if(!a.value)return;const c=new Set,d=r.value,f=n.value,p=[],v=((s=t.value)==null?void 0:s.treeNodes)||[],m=e.filterMethod;f.clear();function y(b){b.forEach(C=>{p.push(C),m!=null&&m(l,C.data)?p.forEach(w=>{c.add(w.key)}):C.isLeaf&&f.add(C.key);const S=C.children;if(S&&y(S),!C.isLeaf){if(!c.has(C.key))f.add(C.key);else if(S){let w=!0;for(const k of S)if(!f.has(k.key)){w=!1;break}w?d.add(C.key):d.delete(C.key)}}p.pop()})}return y(v),c}function i(l){return r.value.has(l.key)}return{hiddenExpandIconKeySet:r,hiddenNodeKeySet:n,doFilter:o,isForceHiddenExpandIcon:i}}function hge(e,t){const n=H(new Set(e.defaultExpandedKeys)),r=H(),a=Qn();ce(()=>e.currentNodeKey,Q=>{r.value=Q},{immediate:!0}),ce(()=>e.data,Q=>{oe(Q)},{immediate:!0});const{isIndeterminate:o,isChecked:i,toggleCheckbox:l,getCheckedKeys:s,getCheckedNodes:c,getHalfCheckedKeys:d,getHalfCheckedNodes:f,setChecked:p,setCheckedKeys:v}=dge(e,a),{doFilter:m,hiddenNodeKeySet:y,isForceHiddenExpandIcon:b}=fge(e,a),C=x(()=>{var Q;return((Q=e.props)==null?void 0:Q.value)||rd.KEY}),S=x(()=>{var Q;return((Q=e.props)==null?void 0:Q.children)||rd.CHILDREN}),w=x(()=>{var Q;return((Q=e.props)==null?void 0:Q.disabled)||rd.DISABLED}),k=x(()=>{var Q;return((Q=e.props)==null?void 0:Q.label)||rd.LABEL}),$=x(()=>{const Q=n.value,ae=y.value,de=[],be=a.value&&a.value.treeNodes||[];function Ee(){const Pe=[];for(let Be=be.length-1;Be>=0;--Be)Pe.push(be[Be]);for(;Pe.length;){const Be=Pe.pop();if(!!Be&&(ae.has(Be.key)||de.push(Be),Q.has(Be.key))){const te=Be.children;if(te){const ie=te.length;for(let ge=ie-1;ge>=0;--ge)Pe.push(te[ge])}}}}return Ee(),de}),O=x(()=>$.value.length>0);function T(Q){const ae=new Map,de=new Map;let be=1;function Ee(Be,te=1,ie=void 0){var ge;const ke=[];for(const xe of Be){const Ie=L(xe),ye={level:te,key:Ie,data:xe};ye.label=F(xe),ye.parent=ie;const pe=I(xe);ye.disabled=j(xe),ye.isLeaf=!pe||pe.length===0,pe&&pe.length&&(ye.children=Ee(pe,te+1,ye)),ke.push(ye),ae.set(Ie,ye),de.has(te)||de.set(te,[]),(ge=de.get(te))==null||ge.push(ye)}return te>be&&(be=te),ke}const Pe=Ee(Q);return{treeNodeMap:ae,levelTreeNodeMap:de,maxLevel:be,treeNodes:Pe}}function _(Q){const ae=m(Q);ae&&(n.value=ae)}function I(Q){return Q[S.value]}function L(Q){return Q?Q[C.value]:\"\"}function j(Q){return Q[w.value]}function F(Q){return Q[k.value]}function N(Q){n.value.has(Q.key)?E(Q):M(Q)}function D(Q,ae){t(mI,Q.data,Q,ae),z(Q),e.expandOnClickNode&&N(Q),e.showCheckbox&&e.checkOnClickNode&&!Q.disabled&&l(Q,!i(Q),!0)}function z(Q){Y(Q)||(r.value=Q.key,t(bI,Q.data,Q))}function B(Q,ae){l(Q,ae)}function M(Q){const ae=n.value;if((a==null?void 0:a.value)&&e.accordion){const{treeNodeMap:de}=a.value;ae.forEach(be=>{const Ee=de.get(be);Ee&&Ee.level===Ee.level&&ae.delete(be)})}ae.add(Q.key),t(gI,Q.data,Q)}function E(Q){n.value.delete(Q.key),t(yI,Q.data,Q)}function K(Q){return n.value.has(Q.key)}function W(Q){return!!Q.disabled}function Y(Q){const ae=r.value;return!!ae&&ae===Q.key}function q(){var Q,ae;if(!!r.value)return(ae=(Q=a==null?void 0:a.value)==null?void 0:Q.treeNodeMap.get(r.value))==null?void 0:ae.data}function J(){return r.value}function ne(Q){r.value=Q}function oe(Q){Ne(()=>a.value=T(Q))}return{tree:a,flattenTree:$,isNotEmpty:O,getKey:L,getChildren:I,toggleExpand:N,toggleCheckbox:l,isExpanded:K,isChecked:i,isIndeterminate:o,isDisabled:W,isCurrent:Y,isForceHiddenExpandIcon:b,handleNodeClick:D,handleNodeCheck:B,getCurrentNode:q,getCurrentKey:J,setCurrentKey:ne,getCheckedKeys:s,getCheckedNodes:c,getHalfCheckedKeys:d,getHalfCheckedNodes:f,setChecked:p,setCheckedKeys:v,filter:_,setData:oe}}var pge=G({name:\"ElTreeNodeContent\",props:sge,setup(e){const t=ve(Pw),n=De(\"tree\");return()=>{const r=e.node,{data:a}=r;return t!=null&&t.ctx.slots.default?t.ctx.slots.default({node:r,data:a}):qe(\"span\",{class:n.be(\"node\",\"label\")},[r==null?void 0:r.label])}}});const vge=\"caret-right\",mge=G({name:\"ElTreeNode\",components:{ElIcon:ft,CaretRight:sE,ElCheckbox:io,ElNodeContent:pge},props:lge,emits:cge,setup(e,{emit:t}){const n=ve(Pw),r=De(\"tree\"),a=x(()=>{var d;return(d=n==null?void 0:n.props.indent)!=null?d:16}),o=x(()=>{var d;return(d=n==null?void 0:n.props.icon)!=null?d:vge});return{ns:r,indent:a,icon:o,handleClick:d=>{t(\"click\",e.node,d)},handleExpandIconClick:()=>{t(\"toggle\",e.node)},handleCheckChange:d=>{t(\"check\",e.node,d)},handleContextMenu:d=>{var f,p,v,m;(v=(p=(f=n==null?void 0:n.instance)==null?void 0:f.vnode)==null?void 0:p.props)!=null&&v.onNodeContextmenu&&(d.stopPropagation(),d.preventDefault()),n==null||n.ctx.emit(SI,d,(m=e.node)==null?void 0:m.data,e.node)}}}}),gge=[\"aria-expanded\",\"aria-disabled\",\"aria-checked\",\"data-key\"];function yge(e,t,n,r,a,o){var i,l,s;const c=we(\"el-icon\"),d=we(\"el-checkbox\"),f=we(\"el-node-content\");return R(),X(\"div\",{ref:\"node$\",class:U([e.ns.b(\"node\"),e.ns.is(\"expanded\",e.expanded),e.ns.is(\"current\",e.current),e.ns.is(\"focusable\",!e.disabled),e.ns.is(\"checked\",!e.disabled&&e.checked)]),role:\"treeitem\",tabindex:\"-1\",\"aria-expanded\":e.expanded,\"aria-disabled\":e.disabled,\"aria-checked\":e.checked,\"data-key\":(i=e.node)==null?void 0:i.key,onClick:t[1]||(t[1]=dt((...p)=>e.handleClick&&e.handleClick(...p),[\"stop\"])),onContextmenu:t[2]||(t[2]=(...p)=>e.handleContextMenu&&e.handleContextMenu(...p))},[Z(\"div\",{class:U(e.ns.be(\"node\",\"content\")),style:Xe({paddingLeft:`${(e.node.level-1)*e.indent}px`})},[e.icon?(R(),fe(c,{key:0,class:U([e.ns.is(\"leaf\",!!((l=e.node)!=null&&l.isLeaf)),e.ns.is(\"hidden\",e.hiddenExpandIcon),{expanded:!((s=e.node)!=null&&s.isLeaf)&&e.expanded},e.ns.be(\"node\",\"expand-icon\")]),onClick:dt(e.handleExpandIconClick,[\"stop\"])},{default:re(()=>[(R(),fe(Kt(e.icon)))]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0),e.showCheckbox?(R(),fe(d,{key:1,\"model-value\":e.checked,indeterminate:e.indeterminate,disabled:e.disabled,onChange:e.handleCheckChange,onClick:t[0]||(t[0]=dt(()=>{},[\"stop\"]))},null,8,[\"model-value\",\"indeterminate\",\"disabled\",\"onChange\"])):se(\"v-if\",!0),g(f,{node:e.node},null,8,[\"node\"])],6)],42,gge)}var bge=Ae(mge,[[\"render\",yge],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree-v2/src/tree-node.vue\"]]);const Cge=G({name:\"ElTreeV2\",components:{ElTreeNode:bge,FixedSizeList:q5},props:ige,emits:uge,setup(e,t){ot(Pw,{ctx:t,props:e,instance:$t()});const{t:n}=ln(),r=De(\"tree\"),{flattenTree:a,isNotEmpty:o,toggleExpand:i,isExpanded:l,isIndeterminate:s,isChecked:c,isDisabled:d,isCurrent:f,isForceHiddenExpandIcon:p,toggleCheckbox:v,handleNodeClick:m,handleNodeCheck:y,getCurrentNode:b,getCurrentKey:C,setCurrentKey:S,getCheckedKeys:w,getCheckedNodes:k,getHalfCheckedKeys:$,getHalfCheckedNodes:O,setChecked:T,setCheckedKeys:_,filter:I,setData:L}=hge(e,t.emit);return t.expose({getCurrentNode:b,getCurrentKey:C,setCurrentKey:S,getCheckedKeys:w,getCheckedNodes:k,getHalfCheckedKeys:$,getHalfCheckedNodes:O,setChecked:T,setCheckedKeys:_,filter:I,setData:L}),{t:n,ns:r,flattenTree:a,itemSize:26,isNotEmpty:o,toggleExpand:i,toggleCheckbox:v,isExpanded:l,isIndeterminate:s,isChecked:c,isDisabled:d,isCurrent:f,isForceHiddenExpandIcon:p,handleNodeClick:m,handleNodeCheck:y}}});function wge(e,t,n,r,a,o){var i;const l=we(\"el-tree-node\"),s=we(\"fixed-size-list\");return R(),X(\"div\",{class:U([e.ns.b(),{[e.ns.m(\"highlight-current\")]:e.highlightCurrent}]),role:\"tree\"},[e.isNotEmpty?(R(),fe(s,{key:0,\"class-name\":e.ns.b(\"virtual-list\"),data:e.flattenTree,total:e.flattenTree.length,height:e.height,\"item-size\":e.itemSize,\"perf-mode\":e.perfMode},{default:re(({data:c,index:d,style:f})=>[(R(),fe(l,{key:c[d].key,style:Xe(f),node:c[d],expanded:e.isExpanded(c[d]),\"show-checkbox\":e.showCheckbox,checked:e.isChecked(c[d]),indeterminate:e.isIndeterminate(c[d]),disabled:e.isDisabled(c[d]),current:e.isCurrent(c[d]),\"hidden-expand-icon\":e.isForceHiddenExpandIcon(c[d]),onClick:e.handleNodeClick,onToggle:e.toggleExpand,onCheck:e.handleNodeCheck},null,8,[\"style\",\"node\",\"expanded\",\"show-checkbox\",\"checked\",\"indeterminate\",\"disabled\",\"current\",\"hidden-expand-icon\",\"onClick\",\"onToggle\",\"onCheck\"]))]),_:1},8,[\"class-name\",\"data\",\"total\",\"height\",\"item-size\",\"perf-mode\"])):(R(),X(\"div\",{key:1,class:U(e.ns.e(\"empty-block\"))},[Z(\"span\",{class:U(e.ns.e(\"empty-text\"))},Me((i=e.emptyText)!=null?i:e.t(\"el.tree.emptyText\")),3)],2))],2)}var Sge=Ae(Cge,[[\"render\",wge],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/tree-v2/src/tree.vue\"]]);const kge=xt(Sge),$ge=\"ElUpload\";class Oge extends Error{constructor(t,n,r,a){super(t),this.name=\"UploadAjaxError\",this.status=n,this.method=r,this.url=a}}function _O(e,t,n){let r;return n.response?r=`${n.response.error||n.response}`:n.responseText?r=`${n.responseText}`:r=`fail to ${t.method} ${e} ${n.status}`,new Oge(r,n.status,t.method,e)}function Pge(e){const t=e.responseText||e.response;if(!t)return t;try{return JSON.parse(t)}catch{return t}}const Tge=e=>{typeof XMLHttpRequest==\"undefined\"&&qn($ge,\"XMLHttpRequest is undefined\");const t=new XMLHttpRequest,n=e.action;t.upload&&t.upload.addEventListener(\"progress\",o=>{const i=o;i.percent=o.total>0?o.loaded/o.total*100:0,e.onProgress(i)});const r=new FormData;if(e.data)for(const[o,i]of Object.entries(e.data))Array.isArray(i)?r.append(o,...i):r.append(o,i);r.append(e.filename,e.file,e.file.name),t.addEventListener(\"error\",()=>{e.onError(_O(n,e,t))}),t.addEventListener(\"load\",()=>{if(t.status<200||t.status>=300)return e.onError(_O(n,e,t));e.onSuccess(Pge(t))}),t.open(e.method,n,!0),e.withCredentials&&\"withCredentials\"in t&&(t.withCredentials=!0);const a=e.headers||{};if(a instanceof Headers)a.forEach((o,i)=>t.setRequestHeader(i,o));else for(const[o,i]of Object.entries(a))ul(i)||t.setRequestHeader(o,String(i));return t.send(r),t},kI=[\"text\",\"picture\",\"picture-card\"];let xge=1;const $I=()=>Date.now()+xge++,OI=Ze({action:{type:String,required:!0},headers:{type:Le(Object)},method:{type:String,default:\"post\"},data:{type:Object,default:()=>xn({})},multiple:{type:Boolean,default:!1},name:{type:String,default:\"file\"},drag:{type:Boolean,default:!1},withCredentials:Boolean,showFileList:{type:Boolean,default:!0},accept:{type:String,default:\"\"},type:{type:String,default:\"select\"},fileList:{type:Le(Array),default:()=>xn([])},autoUpload:{type:Boolean,default:!0},listType:{type:String,values:kI,default:\"text\"},httpRequest:{type:Le(Function),default:Tge},disabled:Boolean,limit:Number}),_ge=Ze(Ke(Te({},OI),{beforeUpload:{type:Le(Function),default:Qt},beforeRemove:{type:Le(Function)},onRemove:{type:Le(Function),default:Qt},onChange:{type:Le(Function),default:Qt},onPreview:{type:Le(Function),default:Qt},onSuccess:{type:Le(Function),default:Qt},onProgress:{type:Le(Function),default:Qt},onError:{type:Le(Function),default:Qt},onExceed:{type:Le(Function),default:Qt}})),Ege=Ze({files:{type:Le(Array),default:()=>xn([])},disabled:{type:Boolean,default:!1},handlePreview:{type:Le(Function),default:Qt},listType:{type:String,values:kI,default:\"text\"}}),Mge={remove:e=>!!e},Ige=[\"onKeydown\"],Nge=[\"src\"],Age=[\"onClick\"],Dge=[\"onClick\"],Rge=[\"onClick\"],Lge={name:\"ElUploadList\"},Fge=G(Ke(Te({},Lge),{props:Ege,emits:Mge,setup(e,{emit:t}){const n=e,{t:r}=ln(),a=De(\"upload\"),o=De(\"icon\"),i=De(\"list\"),l=H(!1),s=f=>{n.handlePreview(f)},c=f=>{f.target.focus()},d=f=>{t(\"remove\",f)};return(f,p)=>(R(),fe(e8,{tag:\"ul\",class:U([A(a).b(\"list\"),A(a).bm(\"list\",f.listType),A(a).is(\"disabled\",f.disabled)]),name:A(i).b()},{default:re(()=>[(R(!0),X(Fe,null,Rt(f.files,v=>(R(),X(\"li\",{key:v.uid||v.name,class:U([A(a).be(\"list\",\"item\"),A(a).is(v.status),{focusing:l.value}]),tabindex:\"0\",onKeydown:It(m=>!f.disabled&&d(v),[\"delete\"]),onFocus:p[0]||(p[0]=m=>l.value=!0),onBlur:p[1]||(p[1]=m=>l.value=!1),onClick:c},[Oe(f.$slots,\"default\",{file:v},()=>[f.listType===\"picture\"||v.status!==\"uploading\"&&f.listType===\"picture-card\"?(R(),X(\"img\",{key:0,class:U(A(a).be(\"list\",\"item-thumbnail\")),src:v.url,alt:\"\"},null,10,Nge)):se(\"v-if\",!0),f.listType!==\"picture\"&&(v.status===\"uploading\"||f.listType!==\"picture-card\")?(R(),X(\"div\",{key:1,class:U(A(a).be(\"list\",\"item-info\"))},[Z(\"a\",{class:U(A(a).be(\"list\",\"item-name\")),onClick:m=>s(v)},[g(A(ft),{class:U(A(o).m(\"document\"))},{default:re(()=>[g(A(Mq))]),_:1},8,[\"class\"]),yt(\" \"+Me(v.name),1)],10,Age),v.status===\"uploading\"?(R(),fe(A(L5),{key:0,type:f.listType===\"picture-card\"?\"circle\":\"line\",\"stroke-width\":f.listType===\"picture-card\"?6:2,percentage:Number(v.percentage),style:Xe(f.listType===\"picture-card\"?\"\":\"margin-top: 0.5rem\")},null,8,[\"type\",\"stroke-width\",\"percentage\",\"style\"])):se(\"v-if\",!0)],2)):se(\"v-if\",!0),Z(\"label\",{class:U(A(a).be(\"list\",\"item-status-label\"))},[f.listType===\"text\"?(R(),fe(A(ft),{key:0,class:U([A(o).m(\"upload-success\"),A(o).m(\"circle-check\")])},{default:re(()=>[g(A(mv))]),_:1},8,[\"class\"])):[\"picture-card\",\"picture\"].includes(f.listType)?(R(),fe(A(ft),{key:1,class:U([A(o).m(\"upload-success\"),A(o).m(\"check\")])},{default:re(()=>[g(A(Wu))]),_:1},8,[\"class\"])):se(\"v-if\",!0)],2),f.disabled?se(\"v-if\",!0):(R(),fe(A(ft),{key:2,class:U(A(o).m(\"close\")),onClick:m=>d(v)},{default:re(()=>[g(A(Ma))]),_:2},1032,[\"class\",\"onClick\"])),se(\" Due to close btn only appears when li gets focused disappears after li gets blurred, thus keyboard navigation can never reach close btn\"),se(\" This is a bug which needs to be fixed \"),se(\" TODO: Fix the incorrect navigation interaction \"),f.disabled?se(\"v-if\",!0):(R(),X(\"i\",{key:3,class:U(A(o).m(\"close-tip\"))},Me(A(r)(\"el.upload.deleteTip\")),3)),f.listType===\"picture-card\"?(R(),X(\"span\",{key:4,class:U(A(a).be(\"list\",\"item-actions\"))},[Z(\"span\",{class:U(A(a).be(\"list\",\"item-preview\")),onClick:m=>f.handlePreview(v)},[g(A(ft),{class:U(A(o).m(\"zoom-in\"))},{default:re(()=>[g(A(fE))]),_:1},8,[\"class\"])],10,Dge),f.disabled?se(\"v-if\",!0):(R(),X(\"span\",{key:0,class:U(A(a).be(\"list\",\"item-delete\")),onClick:m=>d(v)},[g(A(ft),{class:U(A(o).m(\"delete\"))},{default:re(()=>[g(A(Oq))]),_:1},8,[\"class\"])],10,Rge))],2)):se(\"v-if\",!0)])],42,Ige))),128)),Oe(f.$slots,\"append\")]),_:3},8,[\"class\",\"name\"]))}}));var EO=Ae(Fge,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/upload/src/upload-list.vue\"]]);const Bge=Ze({disabled:{type:Boolean,default:!1}}),Vge={file:e=>pt(e)},zge=[\"onDrop\",\"onDragover\"],Hge={name:\"ElUploadDrag\"},jge=G(Ke(Te({},Hge),{props:Bge,emits:Vge,setup(e,{emit:t}){const n=e,r=\"ElUploadDrag\",a=ve(EE);a||qn(r,\"usage: <el-upload><el-upload-dragger /></el-upload>\");const o=De(\"upload\"),i=H(!1),l=c=>{if(n.disabled)return;i.value=!1;const d=Array.from(c.dataTransfer.files),f=a.accept.value;if(!f){t(\"file\",d);return}const p=d.filter(v=>{const{type:m,name:y}=v,b=y.includes(\".\")?`.${y.split(\".\").pop()}`:\"\",C=m.replace(/\\/.*$/,\"\");return f.split(\",\").map(S=>S.trim()).filter(S=>S).some(S=>S.startsWith(\".\")?b===S:/\\/\\*$/.test(S)?C===S.replace(/\\/\\*$/,\"\"):/^[^/]+\\/[^/]+$/.test(S)?m===S:!1)});t(\"file\",p)},s=()=>{n.disabled||(i.value=!0)};return(c,d)=>(R(),X(\"div\",{class:U([A(o).b(\"dragger\"),A(o).is(\"dragover\",i.value)]),onDrop:dt(l,[\"prevent\"]),onDragover:dt(s,[\"prevent\"]),onDragleave:d[0]||(d[0]=dt(f=>i.value=!1,[\"prevent\"]))},[Oe(c.$slots,\"default\")],42,zge))}}));var Kge=Ae(jge,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/upload/src/upload-dragger.vue\"]]);const Wge=Ze(Ke(Te({},OI),{fileList:{type:Le(Array),default:()=>xn([])},beforeUpload:{type:Le(Function),default:Qt},onRemove:{type:Le(Function),default:Qt},onStart:{type:Le(Function),default:Qt},onSuccess:{type:Le(Function),default:Qt},onProgress:{type:Le(Function),default:Qt},onError:{type:Le(Function),default:Qt},onExceed:{type:Le(Function),default:Qt}})),Uge=[\"onKeydown\"],Yge=[\"name\",\"multiple\",\"accept\"],qge={name:\"ElUploadContent\",inheritAttrs:!1},Gge=G(Ke(Te({},qge),{props:Wge,setup(e,{expose:t}){const n=e,r=De(\"upload\"),a=Qn({}),o=Qn(),i=v=>{if(v.length===0)return;const{autoUpload:m,limit:y,fileList:b,multiple:C,onStart:S,onExceed:w}=n;if(y&&b.length+v.length>y){w(v,b);return}C||(v=v.slice(0,1));for(const k of v){const $=k;$.uid=$I(),S($),m&&l($)}},l=async v=>{if(o.value.value=\"\",!n.beforeUpload)return s(v);let m;try{m=await n.beforeUpload(v)}catch{m=!1}if(m===!1){n.onRemove(v);return}let y=v;if(m instanceof Blob){m instanceof File?y=m:y=new File([m],v.name,{type:v.type});for(const b of Object.keys(v))y[b]=v[b]}s(v)},s=v=>{const{headers:m,data:y,method:b,withCredentials:C,name:S,action:w,onProgress:k,onSuccess:$,onError:O,httpRequest:T}=n,{uid:_}=v,I={headers:m||{},withCredentials:C,file:v,data:y,method:b,filename:S,action:w,onProgress:j=>{k(j,v)},onSuccess:j=>{$(j,v),delete a.value[_]},onError:j=>{O(j,v),delete a.value[_]}},L=T(I);a.value[_]=L,L instanceof Promise&&L.then(I.onSuccess,I.onError)},c=v=>{const m=v.target.files;!m||i(Array.from(m))},d=()=>{n.disabled||(o.value.value=\"\",o.value.click())},f=()=>{d()};return t({abort:v=>{MU(a.value).filter(v?([y])=>String(v.uid)===y:()=>!0).forEach(([y,b])=>{b instanceof XMLHttpRequest&&b.abort(),delete a.value[y]})},upload:l}),(v,m)=>(R(),X(\"div\",{class:U([A(r).b(),A(r).m(v.listType)]),tabindex:\"0\",onClick:d,onKeydown:It(dt(f,[\"self\"]),[\"enter\",\"space\"])},[v.drag?(R(),fe(Kge,{key:0,disabled:v.disabled,onFile:i},{default:re(()=>[Oe(v.$slots,\"default\")]),_:3},8,[\"disabled\"])):Oe(v.$slots,\"default\",{key:1}),Z(\"input\",{ref_key:\"inputRef\",ref:o,class:U(A(r).e(\"input\")),name:v.name,multiple:v.multiple,accept:v.accept,type:\"file\",onChange:c},null,42,Yge)],42,Uge))}}));var MO=Ae(Gge,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/upload/src/upload-content.vue\"]]);const Ty=\"ElUpload\",Xge=e=>{var t;(t=e.url)!=null&&t.startsWith(\"blob:\")&&URL.revokeObjectURL(e.url)},Zge=(e,t)=>{const n=H([]),r=p=>n.value.find(v=>v.uid===p.uid);function a(p){var v;(v=t.value)==null||v.abort(p)}function o(p=[\"ready\",\"uploading\",\"success\",\"fail\"]){n.value=n.value.filter(v=>!p.includes(v.status))}const i=(p,v)=>{const m=r(v);!m||(m.status=\"fail\",n.value.splice(n.value.indexOf(m),1),e.onError(p,m,n.value),e.onChange(m,n.value))},l=(p,v)=>{const m=r(v);!m||(e.onProgress(p,m,n.value),m.status=\"uploading\",m.percentage=Math.round(p.percent))},s=(p,v)=>{const m=r(v);!m||(m.status=\"success\",m.response=p,e.onSuccess(p,m,n.value),e.onChange(m,n.value))},c=p=>{const v={name:p.name,percentage:0,status:\"ready\",size:p.size,raw:p,uid:p.uid};if(e.listType===\"picture-card\"||e.listType===\"picture\")try{v.url=URL.createObjectURL(p)}catch(m){m.message,e.onError(m,v,n.value)}n.value.push(v),e.onChange(v,n.value)},d=async(p,v)=>{v&&Tf({scope:Ty,from:\"handleRemove second argument\",version:\"2.2\",replacement:\"first argument `file`\",ref:\"https://element-plus.org/en-US/component/upload.html#methods\"},!0);const m=v||p,y=m instanceof File?r(m):m;y||qn(Ty,\"file to be removed not found\");const b=C=>{a(C);const S=n.value;S.splice(S.indexOf(C),1),e.onRemove(C,S),Xge(C)};e.beforeRemove?await e.beforeRemove(y,n.value)!==!1&&b(y):b(y)};function f(){n.value.filter(({status:p})=>p===\"ready\").forEach(({raw:p})=>{var v;return p&&((v=t.value)==null?void 0:v.upload(p))})}return ce(()=>e.listType,p=>{p!==\"picture-card\"&&p!==\"picture\"||(n.value=n.value.map(v=>{const{raw:m,url:y}=v;if(!y&&m)try{v.url=URL.createObjectURL(m)}catch(b){e.onError(b,v,n.value)}return v}))}),ce(()=>e.fileList,p=>{for(const v of p)v.uid||(v.uid=$I()),v.status||(v.status=\"success\");n.value=p},{immediate:!0,deep:!0}),{abort:a,clearFiles:o,handleError:i,handleProgress:l,handleStart:c,handleSuccess:s,handleRemove:d,submit:f,uploadFiles:n}},Jge={name:\"ElUpload\"},Qge=G(Ke(Te({},Jge),{props:_ge,setup(e,{expose:t}){const n=e,r=wf(),a=Ms(),o=Qn(),{abort:i,submit:l,clearFiles:s,uploadFiles:c,handleStart:d,handleError:f,handleRemove:p,handleSuccess:v,handleProgress:m}=Zge(n,o),y=x(()=>n.listType===\"picture-card\"),b=x(()=>Ke(Te({},n),{onStart:d,onProgress:m,onSuccess:v,onError:f,onRemove:p}));return Lt(()=>{c.value.forEach(({url:C})=>{C!=null&&C.startsWith(\"blob:\")&&URL.revokeObjectURL(C)})}),ot(EE,{accept:yn(n,\"accept\")}),t({abort:i,submit:l,clearFiles:s,handleStart:d,handleRemove:p}),(C,S)=>(R(),X(\"div\",null,[A(y)&&C.showFileList?(R(),fe(EO,{key:0,disabled:A(a),\"list-type\":C.listType,files:A(c),\"handle-preview\":C.onPreview,onRemove:A(p)},sl({append:re(()=>[C.listType===\"picture-card\"?(R(),fe(MO,hn({key:0,ref_key:\"uploadRef\",ref:o},A(b)),{default:re(()=>[A(r).trigger?Oe(C.$slots,\"trigger\",{key:0}):se(\"v-if\",!0),!A(r).trigger&&A(r).default?Oe(C.$slots,\"default\",{key:1}):se(\"v-if\",!0)]),_:3},16)):se(\"v-if\",!0)]),_:2},[C.$slots.file?{name:\"default\",fn:re(({file:w})=>[Oe(C.$slots,\"file\",{file:w})])}:void 0]),1032,[\"disabled\",\"list-type\",\"files\",\"handle-preview\",\"onRemove\"])):se(\"v-if\",!0),C.listType!==\"picture-card\"?(R(),fe(MO,hn({key:1,ref_key:\"uploadRef\",ref:o},A(b)),{default:re(()=>[A(r).trigger?Oe(C.$slots,\"trigger\",{key:0}):se(\"v-if\",!0),!A(r).trigger&&A(r).default?Oe(C.$slots,\"default\",{key:1}):se(\"v-if\",!0)]),_:3},16)):se(\"v-if\",!0),C.$slots.trigger?Oe(C.$slots,\"default\",{key:2}):se(\"v-if\",!0),Oe(C.$slots,\"tip\"),!A(y)&&C.showFileList?(R(),fe(EO,{key:3,disabled:A(a),\"list-type\":C.listType,files:A(c),\"handle-preview\":C.onPreview,onRemove:A(p)},sl({_:2},[C.$slots.file?{name:\"default\",fn:re(({file:w})=>[Oe(C.$slots,\"file\",{file:w})])}:void 0]),1032,[\"disabled\",\"list-type\",\"files\",\"handle-preview\",\"onRemove\"])):se(\"v-if\",!0)]))}}));var eye=Ae(Qge,[[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/upload/src/upload.vue\"]]);const tye=xt(eye);var nye=[qZ,oJ,xee,Dee,Hee,dM,tte,nte,xa,mM,une,pne,Pne,Tne,jre,xre,Gre,io,Yne,zM,Jre,hae,pae,iae,zae,Kae,noe,roe,aoe,ooe,ioe,Fie,Wie,Uie,ale,ule,ble,gse,yse,bse,rue,Yue,que,ft,sce,x5,Ra,_5,Cce,zce,Hce,jce,Gce,qde,Qde,ife,uM,L5,YM,cre,ure,$fe,_fe,Ife,xi,bs,Cv,$de,$he,Ihe,Nhe,Zhe,ape,cpe,dpe,kpe,xve,_ve,jve,Kve,Gm,qte,Xve,tme,nme,Ur,$me,Fme,Jme,age,kge,tye];const Ga=\"ElInfiniteScroll\",rye=50,aye=200,oye=0,iye={delay:{type:Number,default:aye},distance:{type:Number,default:oye},disabled:{type:Boolean,default:!1},immediate:{type:Boolean,default:!0}},Tw=(e,t)=>Object.entries(iye).reduce((n,[r,a])=>{var o,i;const{type:l,default:s}=a,c=e.getAttribute(`infinite-scroll-${r}`);let d=(i=(o=t[c])!=null?o:c)!=null?i:s;return d=d===\"false\"?!1:d,d=l(d),n[r]=Number.isNaN(d)?s:d,n},{}),PI=e=>{const{observer:t}=e[Ga];t&&(t.disconnect(),delete e[Ga].observer)},lye=(e,t)=>{const{container:n,containerEl:r,instance:a,observer:o,lastScrollTop:i}=e[Ga],{disabled:l,distance:s}=Tw(e,a),{clientHeight:c,scrollHeight:d,scrollTop:f}=r,p=f-i;if(e[Ga].lastScrollTop=f,o||l||p<0)return;let v=!1;if(n===e)v=d-(c+f)<=s;else{const{clientTop:m,scrollHeight:y}=e,b=TU(e,r);v=f+c>=b+m+y-s}v&&t.call(a)};function xy(e,t){const{containerEl:n,instance:r}=e[Ga],{disabled:a}=Tw(e,r);a||n.clientHeight===0||(n.scrollHeight<=n.clientHeight?t.call(r):PI(e))}const sye={async mounted(e,t){const{instance:n,value:r}=t;Ct(r)||qn(Ga,\"'v-infinite-scroll' binding value must be a function\"),await Ne();const{delay:a,immediate:o}=Tw(e,n),i=DC(e,!0),l=i===window?document.documentElement:i,s=Qi(lye.bind(null,e,r),a);if(!!i){if(e[Ga]={instance:n,container:i,containerEl:l,delay:a,cb:r,onScroll:s,lastScrollTop:l.scrollTop},o){const c=new MutationObserver(Qi(xy.bind(null,e,r),rye));e[Ga].observer=c,c.observe(e,{childList:!0,subtree:!0}),xy(e,r)}i.addEventListener(\"scroll\",s)}},unmounted(e){const{container:t,onScroll:n}=e[Ga];t==null||t.removeEventListener(\"scroll\",n),PI(e)},async updated(e){e[Ga]||await Ne();const{containerEl:t,cb:n,observer:r}=e[Ga];t.clientHeight&&r&&xy(e,n)}},q0=sye;q0.install=e=>{e.directive(\"InfiniteScroll\",q0)};const uye=q0;function cye(e){let t;const n=H(!1),r=bt(Ke(Te({},e),{originalPosition:\"\",originalOverflow:\"\",visible:!1}));function a(f){r.text=f}function o(){const f=r.parent;if(!f.vLoadingAddClassList){let p=f.getAttribute(\"loading-number\");p=Number.parseInt(p)-1,p?f.setAttribute(\"loading-number\",p.toString()):(Br(f,\"el-loading-parent--relative\"),f.removeAttribute(\"loading-number\")),Br(f,\"el-loading-parent--hidden\")}i()}function i(){var f,p;(p=(f=d.$el)==null?void 0:f.parentNode)==null||p.removeChild(d.$el)}function l(){var f;if(e.beforeClose&&!e.beforeClose())return;const p=r.parent;p.vLoadingAddClassList=void 0,n.value=!0,clearTimeout(t),t=window.setTimeout(()=>{n.value&&(n.value=!1,o())},400),r.visible=!1,(f=e.closed)==null||f.call(e)}function s(){!n.value||(n.value=!1,o())}const d=$m({name:\"ElLoading\",setup(){return()=>{const f=r.spinner||r.svg,p=qe(\"svg\",Te({class:\"circular\",viewBox:r.svgViewBox?r.svgViewBox:\"25 25 50 50\"},f?{innerHTML:f}:{}),[qe(\"circle\",{class:\"path\",cx:\"50\",cy:\"50\",r:\"20\",fill:\"none\"})]),v=r.text?qe(\"p\",{class:\"el-loading-text\"},[r.text]):void 0;return qe(Vn,{name:\"el-loading-fade\",onAfterLeave:s},{default:re(()=>[at(g(\"div\",{style:{backgroundColor:r.background||\"\"},class:[\"el-loading-mask\",r.customClass,r.fullscreen?\"is-fullscreen\":\"\"]},[qe(\"div\",{class:\"el-loading-spinner\"},[p,v])]),[[_t,r.visible]])])})}}}).mount(document.createElement(\"div\"));return Ke(Te({},or(r)),{setText:a,remvoeElLoadingChild:i,close:l,handleAfterLeave:s,vm:d,get $el(){return d.$el}})}let zc;const G0=function(e={}){if(!Bt)return;const t=dye(e);t.fullscreen&&zc&&(zc.remvoeElLoadingChild(),zc.close());const n=cye(Ke(Te({},t),{closed:()=>{var a;(a=t.closed)==null||a.call(t),t.fullscreen&&(zc=void 0)}}));fye(t,t.parent,n),IO(t,t.parent,n),t.parent.vLoadingAddClassList=()=>IO(t,t.parent,n);let r=t.parent.getAttribute(\"loading-number\");return r?r=`${Number.parseInt(r)+1}`:r=\"1\",t.parent.setAttribute(\"loading-number\",r),t.parent.appendChild(n.$el),Ne(()=>n.visible.value=t.visible),t.fullscreen&&(zc=n),n},dye=e=>{var t,n,r,a;let o;return wt(e.target)?o=(t=document.querySelector(e.target))!=null?t:document.body:o=e.target||document.body,{parent:o===document.body||e.body?document.body:o,background:e.background||\"\",svg:e.svg||\"\",svgViewBox:e.svgViewBox||\"\",spinner:e.spinner||!1,text:e.text||\"\",fullscreen:o===document.body&&((n=e.fullscreen)!=null?n:!0),lock:(r=e.lock)!=null?r:!1,customClass:e.customClass||\"\",visible:(a=e.visible)!=null?a:!0,target:o}},fye=async(e,t,n)=>{const{nextZIndex:r}=Pi(),a={};if(e.fullscreen)n.originalPosition.value=$o(document.body,\"position\"),n.originalOverflow.value=$o(document.body,\"overflow\"),a.zIndex=r();else if(e.parent===document.body){n.originalPosition.value=$o(document.body,\"position\"),await Ne();for(const o of[\"top\",\"left\"]){const i=o===\"top\"?\"scrollTop\":\"scrollLeft\";a[o]=`${e.target.getBoundingClientRect()[o]+document.body[i]+document.documentElement[i]-Number.parseInt($o(document.body,`margin-${o}`),10)}px`}for(const o of[\"height\",\"width\"])a[o]=`${e.target.getBoundingClientRect()[o]}px`}else n.originalPosition.value=$o(t,\"position\");for(const[o,i]of Object.entries(a))n.$el.style[o]=i},IO=(e,t,n)=>{n.originalPosition.value!==\"absolute\"&&n.originalPosition.value!==\"fixed\"?xo(t,\"el-loading-parent--relative\"):Br(t,\"el-loading-parent--relative\"),e.fullscreen&&e.lock?xo(t,\"el-loading-parent--hidden\"):Br(t,\"el-loading-parent--hidden\")},X0=Symbol(\"ElLoading\"),NO=(e,t)=>{var n,r,a,o;const i=t.instance,l=p=>zt(t.value)?t.value[p]:void 0,s=p=>{const v=wt(p)&&(i==null?void 0:i[p])||p;return v&&H(v)},c=p=>s(l(p)||e.getAttribute(`element-loading-${vl(p)}`)),d=(n=l(\"fullscreen\"))!=null?n:t.modifiers.fullscreen,f={text:c(\"text\"),svg:c(\"svg\"),svgViewBox:c(\"svgViewBox\"),spinner:c(\"spinner\"),background:c(\"background\"),customClass:c(\"customClass\"),fullscreen:d,target:(r=l(\"target\"))!=null?r:d?void 0:e,body:(a=l(\"body\"))!=null?a:t.modifiers.body,lock:(o=l(\"lock\"))!=null?o:t.modifiers.lock};e[X0]={options:f,instance:G0(f)}},hye=(e,t)=>{for(const n of Object.keys(t))_n(t[n])&&(t[n].value=e[n])},AO={mounted(e,t){t.value&&NO(e,t)},updated(e,t){const n=e[X0];t.oldValue!==t.value&&(t.value&&!t.oldValue?NO(e,t):t.value&&t.oldValue?zt(t.value)&&hye(t.value,n.options):n==null||n.instance.close())},unmounted(e){var t;(t=e[X0])==null||t.instance.close()}},pye={install(e){e.directive(\"loading\",AO),e.config.globalProperties.$loading=G0},directive:AO,service:G0},TI=[\"success\",\"info\",\"warning\",\"error\"],vye=Ze({customClass:{type:String,default:\"\"},center:{type:Boolean,default:!1},dangerouslyUseHTMLString:{type:Boolean,default:!1},duration:{type:Number,default:3e3},icon:{type:wr,default:\"\"},id:{type:String,default:\"\"},message:{type:Le([String,Object,Function]),default:\"\"},onClose:{type:Le(Function),required:!1},showClose:{type:Boolean,default:!1},type:{type:String,values:TI,default:\"info\"},offset:{type:Number,default:20},zIndex:{type:Number,default:0},grouping:{type:Boolean,default:!1},repeatNum:{type:Number,default:1}}),mye={destroy:()=>!0},gye=G({name:\"ElMessage\",components:Te({ElBadge:dM,ElIcon:ft},Vm),props:vye,emits:mye,setup(e){const t=De(\"message\"),n=H(!1),r=H(e.type?e.type===\"error\"?\"danger\":e.type:\"info\");let a;const o=x(()=>{const p=e.type;return{[t.bm(\"icon\",p)]:p&&yi[p]}}),i=x(()=>e.icon||yi[e.type]||\"\"),l=x(()=>({top:`${e.offset}px`,zIndex:e.zIndex}));function s(){e.duration>0&&({stop:a}=gs(()=>{n.value&&d()},e.duration))}function c(){a==null||a()}function d(){n.value=!1}function f({code:p}){p===Ge.esc?n.value&&d():s()}return et(()=>{s(),n.value=!0}),ce(()=>e.repeatNum,()=>{c(),s()}),Hn(document,\"keydown\",f),{ns:t,typeClass:o,iconComponent:i,customStyle:l,visible:n,badgeType:r,close:d,clearTimer:c,startTimer:s}}}),yye=[\"id\"],bye=[\"innerHTML\"];function Cye(e,t,n,r,a,o){const i=we(\"el-badge\"),l=we(\"el-icon\"),s=we(\"close\");return R(),fe(Vn,{name:e.ns.b(\"fade\"),onBeforeLeave:e.onClose,onAfterLeave:t[2]||(t[2]=c=>e.$emit(\"destroy\"))},{default:re(()=>[at(Z(\"div\",{id:e.id,class:U([e.ns.b(),{[e.ns.m(e.type)]:e.type&&!e.icon},e.ns.is(\"center\",e.center),e.ns.is(\"closable\",e.showClose),e.customClass]),style:Xe(e.customStyle),role:\"alert\",onMouseenter:t[0]||(t[0]=(...c)=>e.clearTimer&&e.clearTimer(...c)),onMouseleave:t[1]||(t[1]=(...c)=>e.startTimer&&e.startTimer(...c))},[e.repeatNum>1?(R(),fe(i,{key:0,value:e.repeatNum,type:e.badgeType,class:U(e.ns.e(\"badge\"))},null,8,[\"value\",\"type\",\"class\"])):se(\"v-if\",!0),e.iconComponent?(R(),fe(l,{key:1,class:U([e.ns.e(\"icon\"),e.typeClass])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),Oe(e.$slots,\"default\",{},()=>[e.dangerouslyUseHTMLString?(R(),X(Fe,{key:1},[se(\" Caution here, message could've been compromised, never use user's input as message \"),Z(\"p\",{class:U(e.ns.e(\"content\")),innerHTML:e.message},null,10,bye)],2112)):(R(),X(\"p\",{key:0,class:U(e.ns.e(\"content\"))},Me(e.message),3))]),e.showClose?(R(),fe(l,{key:2,class:U(e.ns.e(\"closeBtn\")),onClick:dt(e.close,[\"stop\"])},{default:re(()=>[g(s)]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)],46,yye),[[_t,e.visible]])]),_:3},8,[\"name\",\"onBeforeLeave\"])}var wye=Ae(gye,[[\"render\",Cye],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/message/src/message.vue\"]]);const ra=[];let Sye=1;const tc=function(e={},t){if(!Bt)return{close:()=>{}};if(Yt(I0.max)&&ra.length>=I0.max)return{close:()=>{}};if(!rn(e)&&zt(e)&&e.grouping&&!rn(e.message)&&ra.length){const f=ra.find(p=>{var v,m,y;return`${(m=(v=p.vm.props)==null?void 0:v.message)!=null?m:\"\"}`==`${(y=e.message)!=null?y:\"\"}`});if(f)return f.vm.component.props.repeatNum+=1,f.vm.component.props.type=(e==null?void 0:e.type)||\"info\",{close:()=>d.component.proxy.visible=!1}}(wt(e)||rn(e))&&(e={message:e});let n=e.offset||20;ra.forEach(({vm:f})=>{var p;n+=(((p=f.el)==null?void 0:p.offsetHeight)||0)+16}),n+=16;const{nextZIndex:r}=Pi(),a=`message_${Sye++}`,o=e.onClose,i=Ke(Te({zIndex:r()},e),{offset:n,id:a,onClose:()=>{kye(a,o)}});let l=document.body;ys(e.appendTo)?l=e.appendTo:wt(e.appendTo)&&(l=document.querySelector(e.appendTo)),ys(l)||(l=document.body);const s=document.createElement(\"div\");s.className=`container_${a}`;const c=i.message,d=g(wye,i,Ct(c)?{default:c}:rn(c)?{default:()=>c}:null);return d.appContext=t||tc._context,d.props.onDestroy=()=>{vs(null,s)},vs(d,s),ra.push({vm:d}),l.appendChild(s.firstElementChild),{close:()=>d.component.proxy.visible=!1}};TI.forEach(e=>{tc[e]=(t={},n)=>((wt(t)||rn(t))&&(t={message:t}),tc(Ke(Te({},t),{type:e}),n))});function kye(e,t){const n=ra.findIndex(({vm:i})=>e===i.component.props.id);if(n===-1)return;const{vm:r}=ra[n];if(!r)return;t==null||t(r);const a=r.el.offsetHeight;ra.splice(n,1);const o=ra.length;if(!(o<1))for(let i=n;i<o;i++){const l=Number.parseInt(ra[i].vm.el.style.top,10)-a-16;ra[i].vm.component.props.offset=l}}function $ye(){var e;for(let t=ra.length-1;t>=0;t--){const n=ra[t].vm.component;(e=n==null?void 0:n.proxy)==null||e.close()}}tc.closeAll=$ye;tc._context=null;const Oye=pE(tc,\"$message\"),Pye=G({name:\"ElMessageBox\",directives:{TrapFocus:kM},components:Te({ElButton:xa,ElInput:Ra,ElOverlay:sw,ElIcon:ft},Vm),inheritAttrs:!1,props:{buttonSize:{type:String,validator:va},modal:{type:Boolean,default:!0},lockScroll:{type:Boolean,default:!0},showClose:{type:Boolean,default:!0},closeOnClickModal:{type:Boolean,default:!0},closeOnPressEscape:{type:Boolean,default:!0},closeOnHashChange:{type:Boolean,default:!0},center:Boolean,draggable:Boolean,roundButton:{default:!1,type:Boolean},container:{type:String,default:\"body\"},boxType:{type:String,default:\"\"}},emits:[\"vanish\",\"action\"],setup(e,{emit:t}){const{t:n}=ln(),r=H(!1),{nextZIndex:a}=Pi(),o=bt({beforeClose:null,callback:null,cancelButtonText:\"\",cancelButtonClass:\"\",confirmButtonText:\"\",confirmButtonClass:\"\",customClass:\"\",customStyle:{},dangerouslyUseHTMLString:!1,distinguishCancelAndClose:!1,icon:\"\",inputPattern:null,inputPlaceholder:\"\",inputType:\"text\",inputValue:null,inputValidator:null,inputErrorMessage:\"\",message:null,modalFade:!0,modalClass:\"\",showCancelButton:!1,showConfirmButton:!0,type:\"\",title:void 0,showInput:!1,action:\"\",confirmButtonLoading:!1,cancelButtonLoading:!1,confirmButtonDisabled:!1,editorErrorMessage:\"\",validateError:!1,zIndex:a()}),i=x(()=>{const _=o.type;return _&&yi[_]?`el-message-box-icon--${_}`:\"\"}),l=Gn(x(()=>e.buttonSize),{prop:!0,form:!0,formItem:!0}),s=x(()=>o.icon||yi[o.type]||\"\"),c=x(()=>!!o.message),d=H(),f=H(),p=H(),v=H(),m=x(()=>o.confirmButtonClass);ce(()=>o.inputValue,async _=>{await Ne(),e.boxType===\"prompt\"&&_!==null&&$()},{immediate:!0}),ce(()=>r.value,_=>{_&&((e.boxType===\"alert\"||e.boxType===\"confirm\")&&Ne().then(()=>{var I,L,j;(j=(L=(I=v.value)==null?void 0:I.$el)==null?void 0:L.focus)==null||j.call(L)}),o.zIndex=a()),e.boxType===\"prompt\"&&(_?Ne().then(()=>{p.value&&p.value.$el&&O().focus()}):(o.editorErrorMessage=\"\",o.validateError=!1))});const y=x(()=>e.draggable);DE(d,f,y),et(async()=>{await Ne(),e.closeOnHashChange&&gn(window,\"hashchange\",b)}),Lt(()=>{e.closeOnHashChange&&Bn(window,\"hashchange\",b)});function b(){!r.value||(r.value=!1,Ne(()=>{o.action&&t(\"action\",o.action)}))}const C=()=>{e.closeOnClickModal&&k(o.distinguishCancelAndClose?\"close\":\"cancel\")},S=HC(C),w=_=>{if(o.inputType!==\"textarea\")return _.preventDefault(),k(\"confirm\")},k=_=>{var I;e.boxType===\"prompt\"&&_===\"confirm\"&&!$()||(o.action=_,o.beforeClose?(I=o.beforeClose)==null||I.call(o,_,o,b):b())},$=()=>{if(e.boxType===\"prompt\"){const _=o.inputPattern;if(_&&!_.test(o.inputValue||\"\"))return o.editorErrorMessage=o.inputErrorMessage||n(\"el.messagebox.error\"),o.validateError=!0,!1;const I=o.inputValidator;if(typeof I==\"function\"){const L=I(o.inputValue);if(L===!1)return o.editorErrorMessage=o.inputErrorMessage||n(\"el.messagebox.error\"),o.validateError=!0,!1;if(typeof L==\"string\")return o.editorErrorMessage=L,o.validateError=!0,!1}}return o.editorErrorMessage=\"\",o.validateError=!1,!0},O=()=>{const _=p.value.$refs;return _.input||_.textarea},T=()=>{k(\"close\")};return e.closeOnPressEscape?LE({handleClose:T},r):dZ(r,\"keydown\",_=>_.code===Ge.esc),e.lockScroll&&RE(r),FE(r),Ke(Te({},or(o)),{overlayEvent:S,visible:r,hasMessage:c,typeClass:i,btnSize:l,iconComponent:s,confirmButtonClasses:m,rootRef:d,headerRef:f,inputRef:p,confirmRef:v,doClose:b,handleClose:T,handleWrapperClick:C,handleInputEnter:w,handleAction:k,t:n})}}),Tye=[\"aria-label\"],xye={key:0,ref:\"headerRef\",class:\"el-message-box__header\"},_ye={class:\"el-message-box__title\"},Eye={class:\"el-message-box__content\"},Mye={class:\"el-message-box__container\"},Iye={key:1,class:\"el-message-box__message\"},Nye={key:0},Aye=[\"innerHTML\"],Dye={class:\"el-message-box__input\"},Rye={class:\"el-message-box__btns\"};function Lye(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"close\"),s=we(\"el-input\"),c=we(\"el-button\"),d=we(\"el-overlay\"),f=pa(\"trap-focus\");return R(),fe(Vn,{name:\"fade-in-linear\",onAfterLeave:t[11]||(t[11]=p=>e.$emit(\"vanish\"))},{default:re(()=>[at(g(d,{\"z-index\":e.zIndex,\"overlay-class\":[\"is-message-box\",e.modalClass],mask:e.modal},{default:re(()=>[Z(\"div\",{class:\"el-overlay-message-box\",onClick:t[8]||(t[8]=(...p)=>e.overlayEvent.onClick&&e.overlayEvent.onClick(...p)),onMousedown:t[9]||(t[9]=(...p)=>e.overlayEvent.onMousedown&&e.overlayEvent.onMousedown(...p)),onMouseup:t[10]||(t[10]=(...p)=>e.overlayEvent.onMouseup&&e.overlayEvent.onMouseup(...p))},[at((R(),X(\"div\",{ref:\"rootRef\",role:\"dialog\",\"aria-label\":e.title||\"dialog\",\"aria-modal\":\"true\",class:U([\"el-message-box\",e.customClass,{\"el-message-box--center\":e.center,\"is-draggable\":e.draggable}]),style:Xe(e.customStyle),onClick:t[7]||(t[7]=dt(()=>{},[\"stop\"]))},[e.title!==null&&e.title!==void 0?(R(),X(\"div\",xye,[Z(\"div\",_ye,[e.iconComponent&&e.center?(R(),fe(i,{key:0,class:U([\"el-message-box__status\",e.typeClass])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),Z(\"span\",null,Me(e.title),1)]),e.showClose?(R(),X(\"button\",{key:0,type:\"button\",class:\"el-message-box__headerbtn\",\"aria-label\":\"Close\",onClick:t[0]||(t[0]=p=>e.handleAction(e.distinguishCancelAndClose?\"close\":\"cancel\")),onKeydown:t[1]||(t[1]=It(dt(p=>e.handleAction(e.distinguishCancelAndClose?\"close\":\"cancel\"),[\"prevent\"]),[\"enter\"]))},[g(i,{class:\"el-message-box__close\"},{default:re(()=>[g(l)]),_:1})],32)):se(\"v-if\",!0)],512)):se(\"v-if\",!0),Z(\"div\",Eye,[Z(\"div\",Mye,[e.iconComponent&&!e.center&&e.hasMessage?(R(),fe(i,{key:0,class:U([\"el-message-box__status\",e.typeClass])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),e.hasMessage?(R(),X(\"div\",Iye,[Oe(e.$slots,\"default\",{},()=>[e.dangerouslyUseHTMLString?(R(),X(\"p\",{key:1,innerHTML:e.message},null,8,Aye)):(R(),X(\"p\",Nye,Me(e.message),1))])])):se(\"v-if\",!0)]),at(Z(\"div\",Dye,[g(s,{ref:\"inputRef\",modelValue:e.inputValue,\"onUpdate:modelValue\":t[2]||(t[2]=p=>e.inputValue=p),type:e.inputType,placeholder:e.inputPlaceholder,class:U({invalid:e.validateError}),onKeydown:It(e.handleInputEnter,[\"enter\"])},null,8,[\"modelValue\",\"type\",\"placeholder\",\"class\",\"onKeydown\"]),Z(\"div\",{class:\"el-message-box__errormsg\",style:Xe({visibility:e.editorErrorMessage?\"visible\":\"hidden\"})},Me(e.editorErrorMessage),5)],512),[[_t,e.showInput]])]),Z(\"div\",Rye,[e.showCancelButton?(R(),fe(c,{key:0,loading:e.cancelButtonLoading,class:U([e.cancelButtonClass]),round:e.roundButton,size:e.btnSize,onClick:t[3]||(t[3]=p=>e.handleAction(\"cancel\")),onKeydown:t[4]||(t[4]=It(dt(p=>e.handleAction(\"cancel\"),[\"prevent\"]),[\"enter\"]))},{default:re(()=>[yt(Me(e.cancelButtonText||e.t(\"el.messagebox.cancel\")),1)]),_:1},8,[\"loading\",\"class\",\"round\",\"size\"])):se(\"v-if\",!0),at(g(c,{ref:\"confirmRef\",type:\"primary\",loading:e.confirmButtonLoading,class:U([e.confirmButtonClasses]),round:e.roundButton,disabled:e.confirmButtonDisabled,size:e.btnSize,onClick:t[5]||(t[5]=p=>e.handleAction(\"confirm\")),onKeydown:t[6]||(t[6]=It(dt(p=>e.handleAction(\"confirm\"),[\"prevent\"]),[\"enter\"]))},{default:re(()=>[yt(Me(e.confirmButtonText||e.t(\"el.messagebox.confirm\")),1)]),_:1},8,[\"loading\",\"class\",\"round\",\"disabled\",\"size\"]),[[_t,e.showConfirmButton]])])],14,Tye)),[[f]])],32)]),_:3},8,[\"z-index\",\"overlay-class\",\"mask\"]),[[_t,e.visible]])]),_:3})}var Fye=Ae(Pye,[[\"render\",Lye],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/message-box/src/index.vue\"]]);const Qd=new Map,Bye=(e,t,n=null)=>{const r=qe(Fye,e);return r.appContext=n,vs(r,t),document.body.appendChild(t.firstElementChild),r.component},Vye=()=>document.createElement(\"div\"),zye=(e,t)=>{const n=Vye();e.onVanish=()=>{vs(null,n),Qd.delete(a)},e.onAction=o=>{const i=Qd.get(a);let l;e.showInput?l={value:a.inputValue,action:o}:l=o,e.callback?e.callback(l,r.proxy):o===\"cancel\"||o===\"close\"?e.distinguishCancelAndClose&&o!==\"cancel\"?i.reject(\"close\"):i.reject(\"cancel\"):i.resolve(l)};const r=Bye(e,n,t),a=r.proxy;for(const o in e)Mt(e,o)&&!Mt(a.$props,o)&&(a[o]=e[o]);return ce(()=>a.message,(o,i)=>{rn(o)?r.slots.default=()=>[o]:rn(i)&&!rn(o)&&delete r.slots.default},{immediate:!0}),a.visible=!0,a};function Tc(e,t=null){if(!Bt)return Promise.reject();let n;return wt(e)||rn(e)?e={message:e}:n=e.callback,new Promise((r,a)=>{const o=zye(e,t!=null?t:Tc._context);Qd.set(o,{options:e,callback:n,resolve:r,reject:a})})}const Hye=[\"alert\",\"confirm\",\"prompt\"],jye={alert:{closeOnPressEscape:!1,closeOnClickModal:!1},confirm:{showCancelButton:!0},prompt:{showCancelButton:!0,showInput:!0}};Hye.forEach(e=>{Tc[e]=Kye(e)});function Kye(e){return(t,n,r,a)=>{let o;return zt(n)?(r=n,o=\"\"):sa(n)?o=\"\":o=n,Tc(Object.assign(Te({title:o,message:t,type:\"\"},jye[e]),r,{boxType:e}),a)}}Tc.close=()=>{Qd.forEach((e,t)=>{t.doClose()}),Qd.clear()};Tc._context=null;const zi=Tc;zi.install=e=>{zi._context=e._context,e.config.globalProperties.$msgbox=zi,e.config.globalProperties.$messageBox=zi,e.config.globalProperties.$alert=zi.alert,e.config.globalProperties.$confirm=zi.confirm,e.config.globalProperties.$prompt=zi.prompt};const Wye=zi,xI=[\"success\",\"info\",\"warning\",\"error\"],Uye=Ze({customClass:{type:String,default:\"\"},dangerouslyUseHTMLString:{type:Boolean,default:!1},duration:{type:Number,default:4500},icon:{type:Le([String,Object]),default:\"\"},id:{type:String,default:\"\"},message:{type:Le([String,Object]),default:\"\"},offset:{type:Number,default:0},onClick:{type:Le(Function),default:()=>{}},onClose:{type:Le(Function),required:!0},position:{type:String,values:[\"top-right\",\"top-left\",\"bottom-right\",\"bottom-left\"],default:\"top-right\"},showClose:{type:Boolean,default:!0},title:{type:String,default:\"\"},type:{type:String,values:[...xI,\"\"],default:\"\"},zIndex:{type:Number,default:0}}),Yye={destroy:()=>!0},qye=G({name:\"ElNotification\",components:Te({ElIcon:ft},Vm),props:Uye,emits:Yye,setup(e){const t=De(\"notification\"),n=H(!1);let r;const a=x(()=>{const v=e.type;return v&&yi[e.type]?t.m(v):\"\"}),o=x(()=>yi[e.type]||e.icon||\"\"),i=x(()=>e.position.endsWith(\"right\")?\"right\":\"left\"),l=x(()=>e.position.startsWith(\"top\")?\"top\":\"bottom\"),s=x(()=>({[l.value]:`${e.offset}px`,zIndex:e.zIndex}));function c(){e.duration>0&&({stop:r}=gs(()=>{n.value&&f()},e.duration))}function d(){r==null||r()}function f(){n.value=!1}function p({code:v}){v===Ge.delete||v===Ge.backspace?d():v===Ge.esc?n.value&&f():c()}return et(()=>{c(),n.value=!0}),Hn(document,\"keydown\",p),{ns:t,horizontalClass:i,typeClass:a,iconComponent:o,positionStyle:s,visible:n,close:f,clearTimer:d,startTimer:c}}}),Gye=[\"id\"],Xye=[\"textContent\"],Zye={key:0},Jye=[\"innerHTML\"];function Qye(e,t,n,r,a,o){const i=we(\"el-icon\"),l=we(\"close\");return R(),fe(Vn,{name:e.ns.b(\"fade\"),onBeforeLeave:e.onClose,onAfterLeave:t[3]||(t[3]=s=>e.$emit(\"destroy\"))},{default:re(()=>[at(Z(\"div\",{id:e.id,class:U([e.ns.b(),e.customClass,e.horizontalClass]),style:Xe(e.positionStyle),role:\"alert\",onMouseenter:t[0]||(t[0]=(...s)=>e.clearTimer&&e.clearTimer(...s)),onMouseleave:t[1]||(t[1]=(...s)=>e.startTimer&&e.startTimer(...s)),onClick:t[2]||(t[2]=(...s)=>e.onClick&&e.onClick(...s))},[e.iconComponent?(R(),fe(i,{key:0,class:U([e.ns.e(\"icon\"),e.typeClass])},{default:re(()=>[(R(),fe(Kt(e.iconComponent)))]),_:1},8,[\"class\"])):se(\"v-if\",!0),Z(\"div\",{class:U(e.ns.e(\"group\"))},[Z(\"h2\",{class:U(e.ns.e(\"title\")),textContent:Me(e.title)},null,10,Xye),at(Z(\"div\",{class:U(e.ns.e(\"content\")),style:Xe(e.title?void 0:{margin:0})},[Oe(e.$slots,\"default\",{},()=>[e.dangerouslyUseHTMLString?(R(),X(Fe,{key:1},[se(\" Caution here, message could've been compromized, nerver use user's input as message \"),se(\" eslint-disable-next-line \"),Z(\"p\",{innerHTML:e.message},null,8,Jye)],2112)):(R(),X(\"p\",Zye,Me(e.message),1))])],6),[[_t,e.message]]),e.showClose?(R(),fe(i,{key:0,class:U(e.ns.e(\"closeBtn\")),onClick:dt(e.close,[\"stop\"])},{default:re(()=>[g(l)]),_:1},8,[\"class\",\"onClick\"])):se(\"v-if\",!0)],2)],46,Gye),[[_t,e.visible]])]),_:3},8,[\"name\",\"onBeforeLeave\"])}var ebe=Ae(qye,[[\"render\",Qye],[\"__file\",\"/home/runner/work/element-plus/element-plus/packages/components/notification/src/notification.vue\"]]);const Pv={\"top-left\":[],\"top-right\":[],\"bottom-left\":[],\"bottom-right\":[]},Z0=16;let tbe=1;const nc=function(e={},t=null){if(!Bt)return{close:()=>{}};(typeof e==\"string\"||rn(e))&&(e={message:e});const n=e.position||\"top-right\";let r=e.offset||0;Pv[n].forEach(({vm:f})=>{var p;r+=(((p=f.el)==null?void 0:p.offsetHeight)||0)+Z0}),r+=Z0;const{nextZIndex:a}=Pi(),o=`notification_${tbe++}`,i=e.onClose,l=Ke(Te({zIndex:a(),offset:r},e),{id:o,onClose:()=>{nbe(o,n,i)}});let s=document.body;ys(e.appendTo)?s=e.appendTo:wt(e.appendTo)&&(s=document.querySelector(e.appendTo)),ys(s)||(s=document.body);const c=document.createElement(\"div\"),d=g(ebe,l,rn(l.message)?{default:()=>l.message}:null);return d.appContext=t!=null?t:nc._context,d.props.onDestroy=()=>{vs(null,c)},vs(d,c),Pv[n].push({vm:d}),s.appendChild(c.firstElementChild),{close:()=>{d.component.proxy.visible=!1}}};xI.forEach(e=>{nc[e]=(t={})=>((typeof t==\"string\"||rn(t))&&(t={message:t}),nc(Ke(Te({},t),{type:e})))});function nbe(e,t,n){const r=Pv[t],a=r.findIndex(({vm:c})=>{var d;return((d=c.component)==null?void 0:d.props.id)===e});if(a===-1)return;const{vm:o}=r[a];if(!o)return;n==null||n(o);const i=o.el.offsetHeight,l=t.split(\"-\")[0];r.splice(a,1);const s=r.length;if(!(s<1))for(let c=a;c<s;c++){const{el:d,component:f}=r[c].vm,p=Number.parseInt(d.style[l],10)-i-Z0;f.props.offset=p}}function rbe(){for(const e of Object.values(Pv))e.forEach(({vm:t})=>{t.component.proxy.visible=!1})}nc.closeAll=rbe;nc._context=null;const abe=pE(nc,\"$notify\");var obe=[uye,pye,Oye,Wye,abe,lfe],ibe=HZ([...nye,...obe]);function V(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function DO(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),n.push.apply(n,r)}return n}function le(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?DO(Object(n),!0).forEach(function(r){V(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):DO(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function P(){return P=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},P.apply(this,arguments)}function RO(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _I(e,t,n){return t&&RO(e.prototype,t),n&&RO(e,n),e}function Ap(){return(Ap=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function EI(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function MI(e,t){if(e==null)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(a[n]=e[n]);return a}function LO(e){return((t=e)!=null&&typeof t==\"object\"&&Array.isArray(t)===!1)==1&&Object.prototype.toString.call(e)===\"[object Object]\";var t}var II=Object.prototype,NI=II.toString,lbe=II.hasOwnProperty,AI=/^\\s*function (\\w+)/;function FO(e){var t,n=(t=e==null?void 0:e.type)!==null&&t!==void 0?t:e;if(n){var r=n.toString().match(AI);return r?r[1]:\"\"}return\"\"}var Cs=function(e){var t,n;return LO(e)!==!1&&typeof(t=e.constructor)==\"function\"&&LO(n=t.prototype)!==!1&&n.hasOwnProperty(\"isPrototypeOf\")!==!1},sbe=function(e){return e},Er=sbe,ef=function(e,t){return lbe.call(e,t)},ube=Number.isInteger||function(e){return typeof e==\"number\"&&isFinite(e)&&Math.floor(e)===e},rc=Array.isArray||function(e){return NI.call(e)===\"[object Array]\"},ac=function(e){return NI.call(e)===\"[object Function]\"},Tv=function(e){return Cs(e)&&ef(e,\"_vueTypes_name\")},DI=function(e){return Cs(e)&&(ef(e,\"type\")||[\"_vueTypes_name\",\"validator\",\"default\",\"required\"].some(function(t){return ef(e,t)}))};function xw(e,t){return Object.defineProperty(e.bind(t),\"__original\",{value:e})}function Ns(e,t,n){var r;n===void 0&&(n=!1);var a=!0,o=\"\";r=Cs(e)?e:{type:e};var i=Tv(r)?r._vueTypes_name+\" - \":\"\";if(DI(r)&&r.type!==null){if(r.type===void 0||r.type===!0||!r.required&&t===void 0)return a;rc(r.type)?(a=r.type.some(function(f){return Ns(f,t,!0)===!0}),o=r.type.map(function(f){return FO(f)}).join(\" or \")):a=(o=FO(r))===\"Array\"?rc(t):o===\"Object\"?Cs(t):o===\"String\"||o===\"Number\"||o===\"Boolean\"||o===\"Function\"?function(f){if(f==null)return\"\";var p=f.constructor.toString().match(AI);return p?p[1]:\"\"}(t)===o:t instanceof r.type}if(!a){var l=i+'value \"'+t+'\" should be of type \"'+o+'\"';return n===!1?(Er(l),!1):l}if(ef(r,\"validator\")&&ac(r.validator)){var s=Er,c=[];if(Er=function(f){c.push(f)},a=r.validator(t),Er=s,!a){var d=(c.length>1?\"* \":\"\")+c.join(`\n* `);return c.length=0,n===!1?(Er(d),a):d}}return a}function ma(e,t){var n=Object.defineProperties(t,{_vueTypes_name:{value:e,writable:!0},isRequired:{get:function(){return this.required=!0,this}},def:{value:function(a){return a!==void 0||this.default?ac(a)||Ns(this,a,!0)===!0?(this.default=rc(a)?function(){return[].concat(a)}:Cs(a)?function(){return Object.assign({},a)}:a,this):(Er(this._vueTypes_name+' - invalid default value: \"'+a+'\"'),this):this}}}),r=n.validator;return ac(r)&&(n.validator=xw(r,n)),n}function Do(e,t){var n=ma(e,t);return Object.defineProperty(n,\"validate\",{value:function(r){return ac(this.validator)&&Er(this._vueTypes_name+` - calling .validate() will overwrite the current custom validator function. Validator info:\n`+JSON.stringify(this)),this.validator=xw(r,this),this}})}function BO(e,t,n){var r,a,o=(r=t,a={},Object.getOwnPropertyNames(r).forEach(function(f){a[f]=Object.getOwnPropertyDescriptor(r,f)}),Object.defineProperties({},a));if(o._vueTypes_name=e,!Cs(n))return o;var i,l,s=n.validator,c=MI(n,[\"validator\"]);if(ac(s)){var d=o.validator;d&&(d=(l=(i=d).__original)!==null&&l!==void 0?l:i),o.validator=xw(d?function(f){return d.call(this,f)&&s.call(this,f)}:s,o)}return Object.assign(o,c)}function Jm(e){return e.replace(/^(?!\\s*$)/gm,\"  \")}var cbe=function(){return Do(\"any\",{})},dbe=function(){return Do(\"function\",{type:Function})},fbe=function(){return Do(\"boolean\",{type:Boolean})},hbe=function(){return Do(\"string\",{type:String})},pbe=function(){return Do(\"number\",{type:Number})},vbe=function(){return Do(\"array\",{type:Array})},mbe=function(){return Do(\"object\",{type:Object})},gbe=function(){return ma(\"integer\",{type:Number,validator:function(e){return ube(e)}})},ybe=function(){return ma(\"symbol\",{validator:function(e){return typeof e==\"symbol\"}})};function bbe(e,t){if(t===void 0&&(t=\"custom validation failed\"),typeof e!=\"function\")throw new TypeError(\"[VueTypes error]: You must provide a function as argument\");return ma(e.name||\"<<anonymous function>>\",{validator:function(n){var r=e(n);return r||Er(this._vueTypes_name+\" - \"+t),r}})}function Cbe(e){if(!rc(e))throw new TypeError(\"[VueTypes error]: You must provide an array as argument.\");var t='oneOf - value should be one of \"'+e.join('\", \"')+'\".',n=e.reduce(function(r,a){if(a!=null){var o=a.constructor;r.indexOf(o)===-1&&r.push(o)}return r},[]);return ma(\"oneOf\",{type:n.length>0?n:void 0,validator:function(r){var a=e.indexOf(r)!==-1;return a||Er(t),a}})}function wbe(e){if(!rc(e))throw new TypeError(\"[VueTypes error]: You must provide an array as argument\");for(var t=!1,n=[],r=0;r<e.length;r+=1){var a=e[r];if(DI(a)){if(Tv(a)&&a._vueTypes_name===\"oneOf\"){n=n.concat(a.type);continue}if(ac(a.validator)&&(t=!0),a.type!==!0&&a.type){n=n.concat(a.type);continue}}n.push(a)}return n=n.filter(function(o,i){return n.indexOf(o)===i}),ma(\"oneOfType\",t?{type:n,validator:function(o){var i=[],l=e.some(function(s){var c=Ns(Tv(s)&&s._vueTypes_name===\"oneOf\"?s.type||null:s,o,!0);return typeof c==\"string\"&&i.push(c),c===!0});return l||Er(\"oneOfType - provided value does not match any of the \"+i.length+` passed-in validators:\n`+Jm(i.join(`\n`))),l}}:{type:n})}function Sbe(e){return ma(\"arrayOf\",{type:Array,validator:function(t){var n,r=t.every(function(a){return(n=Ns(e,a,!0))===!0});return r||Er(`arrayOf - value validation error:\n`+Jm(n)),r}})}function kbe(e){return ma(\"instanceOf\",{type:e})}function $be(e){return ma(\"objectOf\",{type:Object,validator:function(t){var n,r=Object.keys(t).every(function(a){return(n=Ns(e,t[a],!0))===!0});return r||Er(`objectOf - value validation error:\n`+Jm(n)),r}})}function Obe(e){var t=Object.keys(e),n=t.filter(function(a){var o;return!!(!((o=e[a])===null||o===void 0)&&o.required)}),r=ma(\"shape\",{type:Object,validator:function(a){var o=this;if(!Cs(a))return!1;var i=Object.keys(a);if(n.length>0&&n.some(function(s){return i.indexOf(s)===-1})){var l=n.filter(function(s){return i.indexOf(s)===-1});return Er(l.length===1?'shape - required property \"'+l[0]+'\" is not defined.':'shape - required properties \"'+l.join('\", \"')+'\" are not defined.'),!1}return i.every(function(s){if(t.indexOf(s)===-1)return o._vueTypes_isLoose===!0||(Er('shape - shape definition does not include a \"'+s+'\" property. Allowed keys: \"'+t.join('\", \"')+'\".'),!1);var c=Ns(e[s],a[s],!0);return typeof c==\"string\"&&Er('shape - \"'+s+`\" property validation error:\n `+Jm(c)),c===!0})}});return Object.defineProperty(r,\"_vueTypes_isLoose\",{writable:!0,value:!1}),Object.defineProperty(r,\"loose\",{get:function(){return this._vueTypes_isLoose=!0,this}}),r}var wo=function(){function e(){}return e.extend=function(t){var n=this;if(rc(t))return t.forEach(function(f){return n.extend(f)}),this;var r=t.name,a=t.validate,o=a!==void 0&&a,i=t.getter,l=i!==void 0&&i,s=MI(t,[\"name\",\"validate\",\"getter\"]);if(ef(this,r))throw new TypeError('[VueTypes error]: Type \"'+r+'\" already defined');var c,d=s.type;return Tv(d)?(delete s.type,Object.defineProperty(this,r,l?{get:function(){return BO(r,d,s)}}:{value:function(){var f,p=BO(r,d,s);return p.validator&&(p.validator=(f=p.validator).bind.apply(f,[p].concat([].slice.call(arguments)))),p}})):(c=l?{get:function(){var f=Object.assign({},s);return o?Do(r,f):ma(r,f)},enumerable:!0}:{value:function(){var f,p,v=Object.assign({},s);return f=o?Do(r,v):ma(r,v),v.validator&&(f.validator=(p=v.validator).bind.apply(p,[f].concat([].slice.call(arguments)))),f},enumerable:!0},Object.defineProperty(this,r,c))},_I(e,null,[{key:\"any\",get:function(){return cbe()}},{key:\"func\",get:function(){return dbe().def(this.defaults.func)}},{key:\"bool\",get:function(){return fbe().def(this.defaults.bool)}},{key:\"string\",get:function(){return hbe().def(this.defaults.string)}},{key:\"number\",get:function(){return pbe().def(this.defaults.number)}},{key:\"array\",get:function(){return vbe().def(this.defaults.array)}},{key:\"object\",get:function(){return mbe().def(this.defaults.object)}},{key:\"integer\",get:function(){return gbe().def(this.defaults.integer)}},{key:\"symbol\",get:function(){return ybe()}}]),e}();function RI(e){var t;return e===void 0&&(e={func:function(){},bool:!0,string:\"\",number:0,array:function(){return[]},object:function(){return{}},integer:0}),(t=function(n){function r(){return n.apply(this,arguments)||this}return EI(r,n),_I(r,null,[{key:\"sensibleDefaults\",get:function(){return Ap({},this.defaults)},set:function(a){this.defaults=a!==!1?Ap({},a!==!0?a:e):{}}}]),r}(wo)).defaults=Ap({},e),t}wo.defaults={},wo.custom=bbe,wo.oneOf=Cbe,wo.instanceOf=kbe,wo.oneOfType=wbe,wo.arrayOf=Sbe,wo.objectOf=$be,wo.shape=Obe,wo.utils={validate:function(e,t){return Ns(t,e,!0)===!0},toType:function(e,t,n){return n===void 0&&(n=!1),n?Do(e,t):ma(e,t)}};(function(e){function t(){return e.apply(this,arguments)||this}return EI(t,e),t})(RI());var LI=RI({func:void 0,bool:void 0,string:void 0,number:void 0,array:void 0,object:void 0,integer:void 0});LI.extend([{name:\"looseBool\",getter:!0,type:Boolean,default:void 0},{name:\"style\",getter:!0,type:[String,Object],default:void 0},{name:\"VNodeChild\",getter:!0,type:null}]);function an(e){return e.default=void 0,e}var u=LI;function kt(e){return kt=typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?function(t){return typeof t}:function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},kt(e)}var Pbe=function(t){return typeof t==\"function\"},Tbe=Array.isArray,xbe=function(t){return typeof t==\"string\"},_be=function(t){return t!==null&&kt(t)===\"object\"},Ebe=/^on[^a-z]/,Mbe=function(t){return Ebe.test(t)},FI=function(t){var n=Object.create(null);return function(r){var a=n[r];return a||(n[r]=t(r))}},Ibe=/-(\\w)/g,Qm=FI(function(e){return e.replace(Ibe,function(t,n){return n?n.toUpperCase():\"\"})}),Nbe=/\\B([A-Z])/g,Abe=FI(function(e){return e.replace(Nbe,\"-$1\").toLowerCase()}),Dbe=Object.prototype.hasOwnProperty,VO=function(t,n){return Dbe.call(t,n)};function BI(e,t,n,r){var a=e[n];if(a!=null){var o=VO(a,\"default\");if(o&&r===void 0){var i=a.default;r=a.type!==Function&&Pbe(i)?i():i}a.type===Boolean&&(!VO(t,n)&&!o?r=!1:r===\"\"&&(r=!0))}return r}function eg(e){return Object.keys(e).reduce(function(t,n){return(n.substr(0,5)===\"data-\"||n.substr(0,5)===\"aria-\")&&(t[n]=e[n]),t},{})}function Se(){for(var e=[],t=0;t<arguments.length;t++){var n=t<0||arguments.length<=t?void 0:arguments[t];if(!!n){if(xbe(n))e.push(n);else if(Tbe(n))for(var r=0;r<n.length;r++){var a=Se(n[r]);a&&e.push(a)}else if(_be(n))for(var o in n)n[o]&&e.push(o)}}return e.join(\" \")}function bn(e,t){for(var n=Object.assign({},e),r=0;r<t.length;r+=1){var a=t[r];delete n[a]}return n}var VI=function(){if(typeof Map!=\"undefined\")return Map;function e(t,n){var r=-1;return t.some(function(a,o){return a[0]===n?(r=o,!0):!1}),r}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,\"size\",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(n){var r=e(this.__entries__,n),a=this.__entries__[r];return a&&a[1]},t.prototype.set=function(n,r){var a=e(this.__entries__,n);~a?this.__entries__[a][1]=r:this.__entries__.push([n,r])},t.prototype.delete=function(n){var r=this.__entries__,a=e(r,n);~a&&r.splice(a,1)},t.prototype.has=function(n){return!!~e(this.__entries__,n)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(n,r){r===void 0&&(r=null);for(var a=0,o=this.__entries__;a<o.length;a++){var i=o[a];n.call(r,i[1],i[0])}},t}()}(),J0=typeof window!=\"undefined\"&&typeof document!=\"undefined\"&&window.document===document,xv=function(){return typeof global!=\"undefined\"&&global.Math===Math?global:typeof self!=\"undefined\"&&self.Math===Math?self:typeof window!=\"undefined\"&&window.Math===Math?window:Function(\"return this\")()}(),Rbe=function(){return typeof requestAnimationFrame==\"function\"?requestAnimationFrame.bind(xv):function(e){return setTimeout(function(){return e(Date.now())},1e3/60)}}(),Lbe=2;function Fbe(e,t){var n=!1,r=!1,a=0;function o(){n&&(n=!1,e()),r&&l()}function i(){Rbe(o)}function l(){var s=Date.now();if(n){if(s-a<Lbe)return;r=!0}else n=!0,r=!1,setTimeout(i,t);a=s}return l}var Bbe=20,Vbe=[\"top\",\"right\",\"bottom\",\"left\",\"width\",\"height\",\"size\",\"weight\"],zbe=typeof MutationObserver!=\"undefined\",Hbe=function(){function e(){this.connected_=!1,this.mutationEventsAdded_=!1,this.mutationsObserver_=null,this.observers_=[],this.onTransitionEnd_=this.onTransitionEnd_.bind(this),this.refresh=Fbe(this.refresh.bind(this),Bbe)}return e.prototype.addObserver=function(t){~this.observers_.indexOf(t)||this.observers_.push(t),this.connected_||this.connect_()},e.prototype.removeObserver=function(t){var n=this.observers_,r=n.indexOf(t);~r&&n.splice(r,1),!n.length&&this.connected_&&this.disconnect_()},e.prototype.refresh=function(){var t=this.updateObservers_();t&&this.refresh()},e.prototype.updateObservers_=function(){var t=this.observers_.filter(function(n){return n.gatherActive(),n.hasActive()});return t.forEach(function(n){return n.broadcastActive()}),t.length>0},e.prototype.connect_=function(){!J0||this.connected_||(document.addEventListener(\"transitionend\",this.onTransitionEnd_),window.addEventListener(\"resize\",this.refresh),zbe?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener(\"DOMSubtreeModified\",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!J0||!this.connected_||(document.removeEventListener(\"transitionend\",this.onTransitionEnd_),window.removeEventListener(\"resize\",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener(\"DOMSubtreeModified\",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var n=t.propertyName,r=n===void 0?\"\":n,a=Vbe.some(function(o){return!!~r.indexOf(o)});a&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),zI=function(e,t){for(var n=0,r=Object.keys(t);n<r.length;n++){var a=r[n];Object.defineProperty(e,a,{value:t[a],enumerable:!1,writable:!1,configurable:!0})}return e},oc=function(e){var t=e&&e.ownerDocument&&e.ownerDocument.defaultView;return t||xv},HI=tg(0,0,0,0);function _v(e){return parseFloat(e)||0}function zO(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return t.reduce(function(r,a){var o=e[\"border-\"+a+\"-width\"];return r+_v(o)},0)}function jbe(e){for(var t=[\"top\",\"right\",\"bottom\",\"left\"],n={},r=0,a=t;r<a.length;r++){var o=a[r],i=e[\"padding-\"+o];n[o]=_v(i)}return n}function Kbe(e){var t=e.getBBox();return tg(0,0,t.width,t.height)}function Wbe(e){var t=e.clientWidth,n=e.clientHeight;if(!t&&!n)return HI;var r=oc(e).getComputedStyle(e),a=jbe(r),o=a.left+a.right,i=a.top+a.bottom,l=_v(r.width),s=_v(r.height);if(r.boxSizing===\"border-box\"&&(Math.round(l+o)!==t&&(l-=zO(r,\"left\",\"right\")+o),Math.round(s+i)!==n&&(s-=zO(r,\"top\",\"bottom\")+i)),!Ybe(e)){var c=Math.round(l+o)-t,d=Math.round(s+i)-n;Math.abs(c)!==1&&(l-=c),Math.abs(d)!==1&&(s-=d)}return tg(a.left,a.top,l,s)}var Ube=function(){return typeof SVGGraphicsElement!=\"undefined\"?function(e){return e instanceof oc(e).SVGGraphicsElement}:function(e){return e instanceof oc(e).SVGElement&&typeof e.getBBox==\"function\"}}();function Ybe(e){return e===oc(e).document.documentElement}function qbe(e){return J0?Ube(e)?Kbe(e):Wbe(e):HI}function Gbe(e){var t=e.x,n=e.y,r=e.width,a=e.height,o=typeof DOMRectReadOnly!=\"undefined\"?DOMRectReadOnly:Object,i=Object.create(o.prototype);return zI(i,{x:t,y:n,width:r,height:a,top:n,right:t+r,bottom:a+n,left:t}),i}function tg(e,t,n,r){return{x:e,y:t,width:n,height:r}}var Xbe=function(){function e(t){this.broadcastWidth=0,this.broadcastHeight=0,this.contentRect_=tg(0,0,0,0),this.target=t}return e.prototype.isActive=function(){var t=qbe(this.target);return this.contentRect_=t,t.width!==this.broadcastWidth||t.height!==this.broadcastHeight},e.prototype.broadcastRect=function(){var t=this.contentRect_;return this.broadcastWidth=t.width,this.broadcastHeight=t.height,t},e}(),Zbe=function(){function e(t,n){var r=Gbe(n);zI(this,{target:t,contentRect:r})}return e}(),Jbe=function(){function e(t,n,r){if(this.activeObservations_=[],this.observations_=new VI,typeof t!=\"function\")throw new TypeError(\"The callback provided as parameter 1 is not a function.\");this.callback_=t,this.controller_=n,this.callbackCtx_=r}return e.prototype.observe=function(t){if(!arguments.length)throw new TypeError(\"1 argument required, but only 0 present.\");if(!(typeof Element==\"undefined\"||!(Element instanceof Object))){if(!(t instanceof oc(t).Element))throw new TypeError('parameter 1 is not of type \"Element\".');var n=this.observations_;n.has(t)||(n.set(t,new Xbe(t)),this.controller_.addObserver(this),this.controller_.refresh())}},e.prototype.unobserve=function(t){if(!arguments.length)throw new TypeError(\"1 argument required, but only 0 present.\");if(!(typeof Element==\"undefined\"||!(Element instanceof Object))){if(!(t instanceof oc(t).Element))throw new TypeError('parameter 1 is not of type \"Element\".');var n=this.observations_;!n.has(t)||(n.delete(t),n.size||this.controller_.removeObserver(this))}},e.prototype.disconnect=function(){this.clearActive(),this.observations_.clear(),this.controller_.removeObserver(this)},e.prototype.gatherActive=function(){var t=this;this.clearActive(),this.observations_.forEach(function(n){n.isActive()&&t.activeObservations_.push(n)})},e.prototype.broadcastActive=function(){if(!!this.hasActive()){var t=this.callbackCtx_,n=this.activeObservations_.map(function(r){return new Zbe(r.target,r.broadcastRect())});this.callback_.call(t,n,t),this.clearActive()}},e.prototype.clearActive=function(){this.activeObservations_.splice(0)},e.prototype.hasActive=function(){return this.activeObservations_.length>0},e}(),jI=typeof WeakMap!=\"undefined\"?new WeakMap:new VI,KI=function(){function e(t){if(!(this instanceof e))throw new TypeError(\"Cannot call a class as a function.\");if(!arguments.length)throw new TypeError(\"1 argument required, but only 0 present.\");var n=Hbe.getInstance(),r=new Jbe(t,n,this);jI.set(this,r)}return e}();[\"observe\",\"unobserve\",\"disconnect\"].forEach(function(e){KI.prototype[e]=function(){var t;return(t=jI.get(this))[e].apply(t,arguments)}});var ng=function(){return typeof xv.ResizeObserver!=\"undefined\"?xv.ResizeObserver:KI}();function WI(e){if(Array.isArray(e))return e}function Qbe(e,t){var n=e==null?null:typeof Symbol!=\"undefined\"&&e[Symbol.iterator]||e[\"@@iterator\"];if(n!=null){var r=[],a=!0,o=!1,i,l;try{for(n=n.call(e);!(a=(i=n.next()).done)&&(r.push(i.value),!(t&&r.length===t));a=!0);}catch(s){o=!0,l=s}finally{try{!a&&n.return!=null&&n.return()}finally{if(o)throw l}}return r}}function Q0(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function rg(e,t){if(!!e){if(typeof e==\"string\")return Q0(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if(n===\"Object\"&&e.constructor&&(n=e.constructor.name),n===\"Map\"||n===\"Set\")return Array.from(e);if(n===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Q0(e,t)}}function UI(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function fn(e,t){return WI(e)||Qbe(e,t)||rg(e,t)||UI()}function e0e(e){if(Array.isArray(e))return Q0(e)}function YI(e){if(typeof Symbol!=\"undefined\"&&e[Symbol.iterator]!=null||e[\"@@iterator\"]!=null)return Array.from(e)}function t0e(){throw new TypeError(`Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Je(e){return e0e(e)||YI(e)||rg(e)||t0e()}var n0e=function(t){return t!=null&&t!==\"\"},tf=n0e,If=function(t){for(var n=Object.keys(t),r={},a={},o={},i=0,l=n.length;i<l;i++){var s=n[i];Mbe(s)?(r[s[2].toLowerCase()+s.slice(3)]=t[s],a[s]=t[s]):o[s]=t[s]}return{onEvents:a,events:r,extraAttrs:o}},r0e=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",n=arguments.length>1?arguments[1]:void 0,r={},a=/;(?![^(]*\\))/g,o=/:(.+)/;return t.split(a).forEach(function(i){if(i){var l=i.split(o);if(l.length>1){var s=n?Qm(l[0].trim()):l[0].trim();r[s]=l[1].trim()}}}),r},vt=function(t,n){return n in Qe(t)},Un=function e(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,r=Array.isArray(t)?t:[t],a=[];return r.forEach(function(o){Array.isArray(o)?a.push.apply(a,Je(e(o,n))):o&&o.type===Fe?a.push.apply(a,Je(e(o.children,n))):o&&rn(o)?n&&!As(o)?a.push(o):n||a.push(o):tf(o)&&a.push(o)}),a},ht=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"default\",r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};if(rn(t))return t.type===Fe?n===\"default\"?Un(t.children):[]:t.children&&t.children[n]?Un(t.children[n](r)):[];var a=t.$slots[n]&&t.$slots[n](r);return Un(a)},Sn=function(t){for(var n,r=((n=t==null?void 0:t.vnode)===null||n===void 0?void 0:n.el)||t&&(t.$el||t);r&&!r.tagName;)r=r.nextSibling;return r},Qe=function(t){var n={};if(t.$&&t.$.vnode){var r=t.$.vnode.props||{};Object.keys(t.$props).forEach(function(l){var s=t.$props[l],c=Abe(l);(s!==void 0||c in r)&&(n[l]=s)})}else if(rn(t)&&kt(t.type)===\"object\"){var a=t.props||{},o={};Object.keys(a).forEach(function(l){o[Qm(l)]=a[l]});var i=t.type.props||{};Object.keys(i).forEach(function(l){var s=BI(i,o,l,o[l]);(s!==void 0||l in o)&&(n[l]=s)})}return n},We=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"default\",r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:t,a=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,o=void 0;if(t.$){var i=t[n];if(i!==void 0)return typeof i==\"function\"&&a?i(r):i;o=t.$slots[n],o=a&&o?o(r):o}else if(rn(t)){var l=t.props&&t.props[n];if(l!==void 0&&t.props!==null)return typeof l==\"function\"&&a?l(r):l;t.type===Fe?o=t.children:t.children&&t.children[n]&&(o=t.children[n],o=a&&o?o(r):o)}return Array.isArray(o)&&(o=Un(o),o=o.length===1?o[0]:o,o=o.length===0?void 0:o),o},rr=function(t){var n=t.$?t.$:t,r={},a=n.props||{},o={};Object.keys(a).forEach(function(l){o[Qm(l)]=a[l]});var i=bc(n.type)?n.type.props:{};return i&&Object.keys(i).forEach(function(l){var s=BI(i,o,l,o[l]);l in o&&(r[l]=s)}),P(P({},o),r)},a0e=function(t){var n=t.key;return n};function nf(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,n={};return e.$?n=P(P({},n),e.$attrs):n=P(P({},n),e.props),If(n)[t?\"onEvents\":\"events\"]}function o0e(e){var t=(rn(e)?e.props:e.$attrs)||{},n=t.class||{},r={};return typeof n==\"string\"?n.split(\" \").forEach(function(a){r[a.trim()]=!0}):Array.isArray(n)?Se(n).split(\" \").forEach(function(a){r[a.trim()]=!0}):r=P(P({},r),n),r}function qI(e,t){var n=(rn(e)?e.props:e.$attrs)||{},r=n.style||{};if(typeof r==\"string\")r=r0e(r,t);else if(t&&r){var a={};return Object.keys(r).forEach(function(o){return a[Qm(o)]=r[o]}),a}return r}function i0e(e){return e==null||e===\"\"||Array.isArray(e)&&e.length===0}function As(e){return e&&(e.type===Ir||e.type===Fe&&e.children.length===0||e.type===Fo&&e.children.trim()===\"\")}function l0e(e){return!e||e().every(As)}function s0e(e){return e&&e.type===Fo}function La(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t=[];return e.forEach(function(n){Array.isArray(n)?t.push.apply(t,Je(n)):n.type===Fe?t.push.apply(t,Je(n.children)):t.push(n)}),t.filter(function(n){return!As(n)})}var An=function(t,n){return Object.keys(n).forEach(function(r){if(t[r])t[r].def&&(t[r]=t[r].def(n[r]));else throw new Error(\"not have \".concat(r,\" prop\"))}),t};function HO(){var e=[].slice.call(arguments,0),t={};return e.forEach(function(){for(var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=0,a=Object.entries(n);r<a.length;r++){var o=fn(a[r],2),i=o[0],l=o[1];t[i]=t[i]||{},bc(l)?P(t[i],l):t[i]=l}}),t}function zn(e){return e&&e.__v_isVNode&&kt(e.type)!==\"symbol\"}function jn(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:\"default\",r,a;return(r=t[n])!==null&&r!==void 0?r:(a=e[n])===null||a===void 0?void 0:a.call(e)}var rf=vt,zo=G({name:\"ResizeObserver\",props:{disabled:Boolean,onResize:Function},emits:[\"resize\"],setup:function(t,n){var r=n.slots,a=bt({width:0,height:0,offsetHeight:0,offsetWidth:0}),o=null,i=null,l=function(){i&&(i.disconnect(),i=null)},s=function(p){var v=t.onResize,m=p[0].target,y=m.getBoundingClientRect(),b=y.width,C=y.height,S=m.offsetWidth,w=m.offsetHeight,k=Math.floor(b),$=Math.floor(C);if(a.width!==k||a.height!==$||a.offsetWidth!==S||a.offsetHeight!==w){var O={width:k,height:$,offsetWidth:S,offsetHeight:w};P(a,O),v&&Promise.resolve().then(function(){v(P(P({},O),{offsetWidth:S,offsetHeight:w}),m)})}},c=$t(),d=function(){var p=t.disabled;if(p){l();return}var v=Sn(c),m=v!==o;m&&(l(),o=v),!i&&v&&(i=new ng(s),i.observe(v))};return et(function(){d()}),ur(function(){d()}),Wr(function(){l()}),ce(function(){return t.disabled},function(){d()},{flush:\"post\"}),function(){var f;return(f=r.default)===null||f===void 0?void 0:f.call(r)[0]}}});function e1(e){var t,n=function(o){return function(){t=null,e.apply(void 0,Je(o))}},r=function(){if(t==null){for(var o=arguments.length,i=new Array(o),l=0;l<o;l++)i[l]=arguments[l];t=requestAnimationFrame(n(i))}};return r.cancel=function(){return cancelAnimationFrame(t)},r}var rt=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return n},u0e=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return n},kn=function(t){var n=t;return n.install=function(r){r.component(n.displayName||n.name,t)},t},GI=!1;try{var jO=Object.defineProperty({},\"passive\",{get:function(){GI=!0}});window.addEventListener(\"testPassive\",null,jO),window.removeEventListener(\"testPassive\",null,jO)}catch{}var mn=GI;function Kn(e,t,n,r){if(e.addEventListener){var a=r;a===void 0&&mn&&(t===\"touchstart\"||t===\"touchmove\"||t===\"wheel\")&&(a={passive:!1}),e.addEventListener(t,n,a)}return{remove:function(){e.removeEventListener&&e.removeEventListener(t,n)}}}function hh(e){return e!==window?e.getBoundingClientRect():{top:0,bottom:window.innerHeight}}function KO(e,t,n){if(n!==void 0&&t.top>e.top-n)return\"\".concat(n+t.top,\"px\")}function WO(e,t,n){if(n!==void 0&&t.bottom<e.bottom+n){var r=window.innerHeight-t.bottom;return\"\".concat(n+r,\"px\")}}var XI=[\"resize\",\"scroll\",\"touchstart\",\"touchmove\",\"touchend\",\"pageshow\",\"load\"],Sd=[];function UO(e,t){if(!!e){var n=Sd.find(function(r){return r.target===e});n?n.affixList.push(t):(n={target:e,affixList:[t],eventHandlers:{}},Sd.push(n),XI.forEach(function(r){n.eventHandlers[r]=Kn(e,r,function(){n.affixList.forEach(function(a){var o=a.exposed.lazyUpdatePosition;o()},(r===\"touchstart\"||r===\"touchmove\")&&mn?{passive:!0}:!1)})}))}}function YO(e){var t=Sd.find(function(n){var r=n.affixList.some(function(a){return a===e});return r&&(n.affixList=n.affixList.filter(function(a){return a!==e})),r});t&&t.affixList.length===0&&(Sd=Sd.filter(function(n){return n!==t}),XI.forEach(function(n){var r=t.eventHandlers[n];r&&r.remove&&r.remove()}))}var ZI={items_per_page:\"/ page\",jump_to:\"Go to\",jump_to_confirm:\"confirm\",page:\"\",prev_page:\"Previous Page\",next_page:\"Next Page\",prev_5:\"Previous 5 Pages\",next_5:\"Next 5 Pages\",prev_3:\"Previous 3 Pages\",next_3:\"Next 3 Pages\"},Nf={today:\"Today\",now:\"Now\",backToToday:\"Back to today\",ok:\"Ok\",clear:\"Clear\",month:\"Month\",year:\"Year\",timeSelect:\"select time\",dateSelect:\"select date\",weekSelect:\"Choose a week\",monthSelect:\"Choose a month\",yearSelect:\"Choose a year\",decadeSelect:\"Choose a decade\",yearFormat:\"YYYY\",dateFormat:\"M/D/YYYY\",dayFormat:\"D\",dateTimeFormat:\"M/D/YYYY HH:mm:ss\",monthBeforeYear:!0,previousMonth:\"Previous month (PageUp)\",nextMonth:\"Next month (PageDown)\",previousYear:\"Last year (Control + left)\",nextYear:\"Next year (Control + right)\",previousDecade:\"Last decade\",nextDecade:\"Next decade\",previousCentury:\"Last century\",nextCentury:\"Next century\"},c0e={placeholder:\"Select time\"},_w=c0e,d0e={lang:P({placeholder:\"Select date\",rangePlaceholder:[\"Start date\",\"End date\"]},Nf),timePickerLocale:P({},_w)},Ev=d0e,Gr=\"${label} is not a valid ${type}\",lo={locale:\"en\",Pagination:ZI,DatePicker:Ev,TimePicker:_w,Calendar:Ev,global:{placeholder:\"Please select\"},Table:{filterTitle:\"Filter menu\",filterConfirm:\"OK\",filterReset:\"Reset\",filterEmptyText:\"No filters\",emptyText:\"No data\",selectAll:\"Select current page\",selectInvert:\"Invert current page\",selectNone:\"Clear all data\",selectionAll:\"Select all data\",sortTitle:\"Sort\",expand:\"Expand row\",collapse:\"Collapse row\",triggerDesc:\"Click to sort descending\",triggerAsc:\"Click to sort ascending\",cancelSort:\"Click to cancel sorting\"},Modal:{okText:\"OK\",cancelText:\"Cancel\",justOkText:\"OK\"},Popconfirm:{okText:\"OK\",cancelText:\"Cancel\"},Transfer:{titles:[\"\",\"\"],searchPlaceholder:\"Search here\",itemUnit:\"item\",itemsUnit:\"items\",remove:\"Remove\",selectCurrent:\"Select current page\",removeCurrent:\"Remove current page\",selectAll:\"Select all data\",removeAll:\"Remove all data\",selectInvert:\"Invert current page\"},Upload:{uploading:\"Uploading...\",removeFile:\"Remove file\",uploadError:\"Upload error\",previewFile:\"Preview file\",downloadFile:\"Download file\"},Empty:{description:\"No Data\"},Icon:{icon:\"icon\"},Text:{edit:\"Edit\",copy:\"Copy\",copied:\"Copied\",expand:\"Expand\"},PageHeader:{back:\"Back\"},Form:{optional:\"(optional)\",defaultValidateMessages:{default:\"Field validation error for ${label}\",required:\"Please enter ${label}\",enum:\"${label} must be one of [${enum}]\",whitespace:\"${label} cannot be a blank character\",date:{format:\"${label} date format is invalid\",parse:\"${label} cannot be converted to a date\",invalid:\"${label} is an invalid date\"},types:{string:Gr,method:Gr,array:Gr,object:Gr,number:Gr,date:Gr,boolean:Gr,integer:Gr,float:Gr,regexp:Gr,email:Gr,url:Gr,hex:Gr},string:{len:\"${label} must be ${len} characters\",min:\"${label} must be at least ${min} characters\",max:\"${label} must be up to ${max} characters\",range:\"${label} must be between ${min}-${max} characters\"},number:{len:\"${label} must be equal to ${len}\",min:\"${label} must be minimum ${min}\",max:\"${label} must be maximum ${max}\",range:\"${label} must be between ${min}-${max}\"},array:{len:\"Must be ${len} ${label}\",min:\"At least ${min} ${label}\",max:\"At most ${max} ${label}\",range:\"The amount of ${label} must be between ${min}-${max}\"},pattern:{mismatch:\"${label} does not match the pattern ${pattern}\"}}},Image:{preview:\"Preview\"}},Kr=G({name:\"LocaleReceiver\",props:{componentName:u.string,defaultLocale:{type:[Object,Function]},children:{type:Function}},setup:function(t,n){var r=n.slots,a=ve(\"localeData\",{}),o=x(function(){var l=t.componentName,s=l===void 0?\"global\":l,c=t.defaultLocale,d=c||lo[s||\"global\"],f=a.antLocale,p=s&&f?f[s]:{};return P(P({},typeof d==\"function\"?d():d),p||{})}),i=x(function(){var l=a.antLocale,s=l&&l.locale;return l&&l.exist&&!s?lo.locale:s});return function(){var l=t.children||r.default,s=a.antLocale;return l==null?void 0:l(o.value,i.value,s)}}});function f0e(e,t){var n=ve(\"localeData\",{}),r=x(function(){var a=n.antLocale,o=t||lo[e||\"global\"],i=e&&a?a[e]:{};return P(P({},typeof o==\"function\"?o():o),i||{})});return[r]}var JI=function(){var t=ve(\"configProvider\",St),n=t.getPrefixCls,r=n(\"empty-img-default\");return g(\"svg\",{class:r,width:\"184\",height:\"152\",viewBox:\"0 0 184 152\"},[g(\"g\",{fill:\"none\",\"fill-rule\":\"evenodd\"},[g(\"g\",{transform:\"translate(24 31.67)\"},[g(\"ellipse\",{class:\"\".concat(r,\"-ellipse\"),cx:\"67.797\",cy:\"106.89\",rx:\"67.797\",ry:\"12.668\"},null),g(\"path\",{class:\"\".concat(r,\"-path-1\"),d:\"M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z\"},null),g(\"path\",{class:\"\".concat(r,\"-path-2\"),d:\"M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z\",transform:\"translate(13.56)\"},null),g(\"path\",{class:\"\".concat(r,\"-path-3\"),d:\"M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z\"},null),g(\"path\",{class:\"\".concat(r,\"-path-4\"),d:\"M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z\"},null)]),g(\"path\",{class:\"\".concat(r,\"-path-5\"),d:\"M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z\"},null),g(\"g\",{class:\"\".concat(r,\"-g\"),transform:\"translate(149.65 15.383)\"},[g(\"ellipse\",{cx:\"20.654\",cy:\"3.167\",rx:\"2.849\",ry:\"2.815\"},null),g(\"path\",{d:\"M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z\"},null)])])])};JI.PRESENTED_IMAGE_DEFAULT=!0;var h0e=JI,QI=function(){var t=ve(\"configProvider\",St),n=t.getPrefixCls,r=n(\"empty-img-simple\");return g(\"svg\",{class:r,width:\"64\",height:\"41\",viewBox:\"0 0 64 41\"},[g(\"g\",{transform:\"translate(0 1)\",fill:\"none\",\"fill-rule\":\"evenodd\"},[g(\"ellipse\",{class:\"\".concat(r,\"-ellipse\"),fill:\"#F5F5F5\",cx:\"32\",cy:\"33\",rx:\"32\",ry:\"7\"},null),g(\"g\",{class:\"\".concat(r,\"-g\"),\"fill-rule\":\"nonzero\",stroke:\"#D9D9D9\"},[g(\"path\",{d:\"M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z\"},null),g(\"path\",{d:\"M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z\",fill:\"#FAFAFA\",class:\"\".concat(r,\"-path\")},null)])])])};QI.PRESENTED_IMAGE_SIMPLE=!0;var p0e=QI,v0e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},eN=g(h0e,null,null),tN=g(p0e,null,null),xc=function(t,n){var r=n.slots,a=r===void 0?{}:r,o=n.attrs,i,l=ve(\"configProvider\",St),s=l.getPrefixCls,c=l.direction,d=P(P({},t),o),f=d.prefixCls,p=d.image,v=p===void 0?eN:p,m=d.description,y=m===void 0?((i=a.description)===null||i===void 0?void 0:i.call(a))||void 0:m,b=d.imageStyle,C=d.class,S=C===void 0?\"\":C,w=v0e(d,[\"prefixCls\",\"image\",\"description\",\"imageStyle\",\"class\"]);return g(Kr,{componentName:\"Empty\",children:function($){var O,T=s(\"empty\",f),_=typeof y!=\"undefined\"?y:$.description,I=typeof _==\"string\"?_:\"empty\",L=null;return typeof v==\"string\"?L=g(\"img\",{alt:I,src:v},null):L=v,g(\"div\",le({class:Se(T,S,(O={},V(O,\"\".concat(T,\"-normal\"),v===tN),V(O,\"\".concat(T,\"-rtl\"),c===\"rtl\"),O))},w),[g(\"div\",{class:\"\".concat(T,\"-image\"),style:b},[L]),_&&g(\"p\",{class:\"\".concat(T,\"-description\")},[_]),a.default&&g(\"div\",{class:\"\".concat(T,\"-footer\")},[La(a.default())])])}},null)};xc.displayName=\"AEmpty\";xc.PRESENTED_IMAGE_DEFAULT=eN;xc.PRESENTED_IMAGE_SIMPLE=tN;xc.inheritAttrs=!1;xc.props={prefixCls:u.string,image:u.any,description:u.any,imageStyle:u.object};var su=kn(xc),m0e=function(t){var n=ve(\"configProvider\",St),r=function(o){var i=n.getPrefixCls,l=i(\"empty\");switch(o){case\"Table\":case\"List\":return g(su,{image:su.PRESENTED_IMAGE_SIMPLE},null);case\"Select\":case\"TreeSelect\":case\"Cascader\":case\"Transfer\":case\"Mentions\":return g(su,{image:su.PRESENTED_IMAGE_SIMPLE,class:\"\".concat(l,\"-small\")},null);default:return g(su,null,null)}};return r(t.componentName)};function nN(e){return g(m0e,{componentName:e},null)}//! moment.js\n//! version : 2.29.3\n//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n//! license : MIT\n//! momentjs.com\nvar rN;function Ue(){return rN.apply(null,arguments)}function g0e(e){rN=e}function so(e){return e instanceof Array||Object.prototype.toString.call(e)===\"[object Array]\"}function ls(e){return e!=null&&Object.prototype.toString.call(e)===\"[object Object]\"}function cn(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function Ew(e){if(Object.getOwnPropertyNames)return Object.getOwnPropertyNames(e).length===0;var t;for(t in e)if(cn(e,t))return!1;return!0}function Lr(e){return e===void 0}function Ci(e){return typeof e==\"number\"||Object.prototype.toString.call(e)===\"[object Number]\"}function Af(e){return e instanceof Date||Object.prototype.toString.call(e)===\"[object Date]\"}function aN(e,t){var n=[],r,a=e.length;for(r=0;r<a;++r)n.push(t(e[r],r));return n}function Gi(e,t){for(var n in t)cn(t,n)&&(e[n]=t[n]);return cn(t,\"toString\")&&(e.toString=t.toString),cn(t,\"valueOf\")&&(e.valueOf=t.valueOf),e}function Ho(e,t,n,r){return xN(e,t,n,r,!0).utc()}function y0e(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidEra:null,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],era:null,meridiem:null,rfc2822:!1,weekdayMismatch:!1}}function qt(e){return e._pf==null&&(e._pf=y0e()),e._pf}var t1;Array.prototype.some?t1=Array.prototype.some:t1=function(e){var t=Object(this),n=t.length>>>0,r;for(r=0;r<n;r++)if(r in t&&e.call(this,t[r],r,t))return!0;return!1};function Mw(e){if(e._isValid==null){var t=qt(e),n=t1.call(t.parsedDateParts,function(a){return a!=null}),r=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidEra&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(r=r&&t.charsLeftOver===0&&t.unusedTokens.length===0&&t.bigHour===void 0),Object.isFrozen==null||!Object.isFrozen(e))e._isValid=r;else return r}return e._isValid}function ag(e){var t=Ho(NaN);return e!=null?Gi(qt(t),e):qt(t).userInvalidated=!0,t}var qO=Ue.momentProperties=[],_y=!1;function Iw(e,t){var n,r,a,o=qO.length;if(Lr(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),Lr(t._i)||(e._i=t._i),Lr(t._f)||(e._f=t._f),Lr(t._l)||(e._l=t._l),Lr(t._strict)||(e._strict=t._strict),Lr(t._tzm)||(e._tzm=t._tzm),Lr(t._isUTC)||(e._isUTC=t._isUTC),Lr(t._offset)||(e._offset=t._offset),Lr(t._pf)||(e._pf=qt(t)),Lr(t._locale)||(e._locale=t._locale),o>0)for(n=0;n<o;n++)r=qO[n],a=t[r],Lr(a)||(e[r]=a);return e}function Df(e){Iw(this,e),this._d=new Date(e._d!=null?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),_y===!1&&(_y=!0,Ue.updateOffset(this),_y=!1)}function uo(e){return e instanceof Df||e!=null&&e._isAMomentObject!=null}function oN(e){Ue.suppressDeprecationWarnings===!1&&typeof console!=\"undefined\"&&console.warn&&console.warn(\"Deprecation warning: \"+e)}function Fa(e,t){var n=!0;return Gi(function(){if(Ue.deprecationHandler!=null&&Ue.deprecationHandler(null,e),n){var r=[],a,o,i,l=arguments.length;for(o=0;o<l;o++){if(a=\"\",typeof arguments[o]==\"object\"){a+=`\n[`+o+\"] \";for(i in arguments[0])cn(arguments[0],i)&&(a+=i+\": \"+arguments[0][i]+\", \");a=a.slice(0,-2)}else a=arguments[o];r.push(a)}oN(e+`\nArguments: `+Array.prototype.slice.call(r).join(\"\")+`\n`+new Error().stack),n=!1}return t.apply(this,arguments)},t)}var GO={};function iN(e,t){Ue.deprecationHandler!=null&&Ue.deprecationHandler(e,t),GO[e]||(oN(t),GO[e]=!0)}Ue.suppressDeprecationWarnings=!1;Ue.deprecationHandler=null;function jo(e){return typeof Function!=\"undefined\"&&e instanceof Function||Object.prototype.toString.call(e)===\"[object Function]\"}function b0e(e){var t,n;for(n in e)cn(e,n)&&(t=e[n],jo(t)?this[n]=t:this[\"_\"+n]=t);this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+\"|\"+/\\d{1,2}/.source)}function n1(e,t){var n=Gi({},e),r;for(r in t)cn(t,r)&&(ls(e[r])&&ls(t[r])?(n[r]={},Gi(n[r],e[r]),Gi(n[r],t[r])):t[r]!=null?n[r]=t[r]:delete n[r]);for(r in e)cn(e,r)&&!cn(t,r)&&ls(e[r])&&(n[r]=Gi({},n[r]));return n}function Nw(e){e!=null&&this.set(e)}var r1;Object.keys?r1=Object.keys:r1=function(e){var t,n=[];for(t in e)cn(e,t)&&n.push(t);return n};var C0e={sameDay:\"[Today at] LT\",nextDay:\"[Tomorrow at] LT\",nextWeek:\"dddd [at] LT\",lastDay:\"[Yesterday at] LT\",lastWeek:\"[Last] dddd [at] LT\",sameElse:\"L\"};function w0e(e,t,n){var r=this._calendar[e]||this._calendar.sameElse;return jo(r)?r.call(t,n):r}function Ro(e,t,n){var r=\"\"+Math.abs(e),a=t-r.length,o=e>=0;return(o?n?\"+\":\"\":\"-\")+Math.pow(10,Math.max(0,a)).toString().substr(1)+r}var Aw=/(\\[[^\\[]*\\])|(\\\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,ph=/(\\[[^\\[]*\\])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ey={},Eu={};function Tt(e,t,n,r){var a=r;typeof r==\"string\"&&(a=function(){return this[r]()}),e&&(Eu[e]=a),t&&(Eu[t[0]]=function(){return Ro(a.apply(this,arguments),t[1],t[2])}),n&&(Eu[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),e)})}function S0e(e){return e.match(/\\[[\\s\\S]/)?e.replace(/^\\[|\\]$/g,\"\"):e.replace(/\\\\/g,\"\")}function k0e(e){var t=e.match(Aw),n,r;for(n=0,r=t.length;n<r;n++)Eu[t[n]]?t[n]=Eu[t[n]]:t[n]=S0e(t[n]);return function(a){var o=\"\",i;for(i=0;i<r;i++)o+=jo(t[i])?t[i].call(a,e):t[i];return o}}function Dp(e,t){return e.isValid()?(t=lN(t,e.localeData()),Ey[t]=Ey[t]||k0e(t),Ey[t](e)):e.localeData().invalidDate()}function lN(e,t){var n=5;function r(a){return t.longDateFormat(a)||a}for(ph.lastIndex=0;n>=0&&ph.test(e);)e=e.replace(ph,r),ph.lastIndex=0,n-=1;return e}var $0e={LTS:\"h:mm:ss A\",LT:\"h:mm A\",L:\"MM/DD/YYYY\",LL:\"MMMM D, YYYY\",LLL:\"MMMM D, YYYY h:mm A\",LLLL:\"dddd, MMMM D, YYYY h:mm A\"};function O0e(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.match(Aw).map(function(r){return r===\"MMMM\"||r===\"MM\"||r===\"DD\"||r===\"dddd\"?r.slice(1):r}).join(\"\"),this._longDateFormat[e])}var P0e=\"Invalid date\";function T0e(){return this._invalidDate}var x0e=\"%d\",_0e=/\\d{1,2}/;function E0e(e){return this._ordinal.replace(\"%d\",e)}var M0e={future:\"in %s\",past:\"%s ago\",s:\"a few seconds\",ss:\"%d seconds\",m:\"a minute\",mm:\"%d minutes\",h:\"an hour\",hh:\"%d hours\",d:\"a day\",dd:\"%d days\",w:\"a week\",ww:\"%d weeks\",M:\"a month\",MM:\"%d months\",y:\"a year\",yy:\"%d years\"};function I0e(e,t,n,r){var a=this._relativeTime[n];return jo(a)?a(e,t,n,r):a.replace(/%d/i,e)}function N0e(e,t){var n=this._relativeTime[e>0?\"future\":\"past\"];return jo(n)?n(t):n.replace(/%s/i,t)}var kd={};function Or(e,t){var n=e.toLowerCase();kd[n]=kd[n+\"s\"]=kd[t]=e}function Ba(e){return typeof e==\"string\"?kd[e]||kd[e.toLowerCase()]:void 0}function Dw(e){var t={},n,r;for(r in e)cn(e,r)&&(n=Ba(r),n&&(t[n]=e[r]));return t}var sN={};function Pr(e,t){sN[e]=t}function A0e(e){var t=[],n;for(n in e)cn(e,n)&&t.push({unit:n,priority:sN[n]});return t.sort(function(r,a){return r.priority-a.priority}),t}function og(e){return e%4===0&&e%100!==0||e%400===0}function Oa(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function Zt(e){var t=+e,n=0;return t!==0&&isFinite(t)&&(n=Oa(t)),n}function _c(e,t){return function(n){return n!=null?(uN(this,e,n),Ue.updateOffset(this,t),this):Mv(this,e)}}function Mv(e,t){return e.isValid()?e._d[\"get\"+(e._isUTC?\"UTC\":\"\")+t]():NaN}function uN(e,t,n){e.isValid()&&!isNaN(n)&&(t===\"FullYear\"&&og(e.year())&&e.month()===1&&e.date()===29?(n=Zt(n),e._d[\"set\"+(e._isUTC?\"UTC\":\"\")+t](n,e.month(),dg(n,e.month()))):e._d[\"set\"+(e._isUTC?\"UTC\":\"\")+t](n))}function D0e(e){return e=Ba(e),jo(this[e])?this[e]():this}function R0e(e,t){if(typeof e==\"object\"){e=Dw(e);var n=A0e(e),r,a=n.length;for(r=0;r<a;r++)this[n[r].unit](e[n[r].unit])}else if(e=Ba(e),jo(this[e]))return this[e](t);return this}var cN=/\\d/,ya=/\\d\\d/,dN=/\\d{3}/,Rw=/\\d{4}/,ig=/[+-]?\\d{6}/,Dn=/\\d\\d?/,fN=/\\d\\d\\d\\d?/,hN=/\\d\\d\\d\\d\\d\\d?/,lg=/\\d{1,3}/,Lw=/\\d{1,4}/,sg=/[+-]?\\d{1,6}/,Ec=/\\d+/,ug=/[+-]?\\d+/,L0e=/Z|[+-]\\d\\d:?\\d\\d/gi,cg=/Z|[+-]\\d\\d(?::?\\d\\d)?/gi,F0e=/[+-]?\\d+(\\.\\d{1,3})?/,Rf=/[0-9]{0,256}['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF07\\uFF10-\\uFFEF]{1,256}|[\\u0600-\\u06FF\\/]{1,256}(\\s*?[\\u0600-\\u06FF]{1,256}){1,2}/i,Iv;Iv={};function gt(e,t,n){Iv[e]=jo(t)?t:function(r,a){return r&&n?n:t}}function B0e(e,t){return cn(Iv,e)?Iv[e](t._strict,t._locale):new RegExp(V0e(e))}function V0e(e){return aa(e.replace(\"\\\\\",\"\").replace(/\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g,function(t,n,r,a,o){return n||r||a||o}))}function aa(e){return e.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\")}var a1={};function Cn(e,t){var n,r=t,a;for(typeof e==\"string\"&&(e=[e]),Ci(t)&&(r=function(o,i){i[t]=Zt(o)}),a=e.length,n=0;n<a;n++)a1[e[n]]=r}function Lf(e,t){Cn(e,function(n,r,a,o){a._w=a._w||{},t(n,a._w,a,o)})}function z0e(e,t,n){t!=null&&cn(a1,e)&&a1[e](t,n._a,n,e)}var kr=0,ii=1,Oo=2,ar=3,Ja=4,li=5,Xl=6,H0e=7,j0e=8;function K0e(e,t){return(e%t+t)%t}var Zn;Array.prototype.indexOf?Zn=Array.prototype.indexOf:Zn=function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1};function dg(e,t){if(isNaN(e)||isNaN(t))return NaN;var n=K0e(t,12);return e+=(t-n)/12,n===1?og(e)?29:28:31-n%7%2}Tt(\"M\",[\"MM\",2],\"Mo\",function(){return this.month()+1});Tt(\"MMM\",0,0,function(e){return this.localeData().monthsShort(this,e)});Tt(\"MMMM\",0,0,function(e){return this.localeData().months(this,e)});Or(\"month\",\"M\");Pr(\"month\",8);gt(\"M\",Dn);gt(\"MM\",Dn,ya);gt(\"MMM\",function(e,t){return t.monthsShortRegex(e)});gt(\"MMMM\",function(e,t){return t.monthsRegex(e)});Cn([\"M\",\"MM\"],function(e,t){t[ii]=Zt(e)-1});Cn([\"MMM\",\"MMMM\"],function(e,t,n,r){var a=n._locale.monthsParse(e,r,n._strict);a!=null?t[ii]=a:qt(n).invalidMonth=e});var W0e=\"January_February_March_April_May_June_July_August_September_October_November_December\".split(\"_\"),pN=\"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec\".split(\"_\"),vN=/D[oD]?(\\[[^\\[\\]]*\\]|\\s)+MMMM?/,U0e=Rf,Y0e=Rf;function q0e(e,t){return e?so(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||vN).test(t)?\"format\":\"standalone\"][e.month()]:so(this._months)?this._months:this._months.standalone}function G0e(e,t){return e?so(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[vN.test(t)?\"format\":\"standalone\"][e.month()]:so(this._monthsShort)?this._monthsShort:this._monthsShort.standalone}function X0e(e,t,n){var r,a,o,i=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],r=0;r<12;++r)o=Ho([2e3,r]),this._shortMonthsParse[r]=this.monthsShort(o,\"\").toLocaleLowerCase(),this._longMonthsParse[r]=this.months(o,\"\").toLocaleLowerCase();return n?t===\"MMM\"?(a=Zn.call(this._shortMonthsParse,i),a!==-1?a:null):(a=Zn.call(this._longMonthsParse,i),a!==-1?a:null):t===\"MMM\"?(a=Zn.call(this._shortMonthsParse,i),a!==-1?a:(a=Zn.call(this._longMonthsParse,i),a!==-1?a:null)):(a=Zn.call(this._longMonthsParse,i),a!==-1?a:(a=Zn.call(this._shortMonthsParse,i),a!==-1?a:null))}function Z0e(e,t,n){var r,a,o;if(this._monthsParseExact)return X0e.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),r=0;r<12;r++){if(a=Ho([2e3,r]),n&&!this._longMonthsParse[r]&&(this._longMonthsParse[r]=new RegExp(\"^\"+this.months(a,\"\").replace(\".\",\"\")+\"$\",\"i\"),this._shortMonthsParse[r]=new RegExp(\"^\"+this.monthsShort(a,\"\").replace(\".\",\"\")+\"$\",\"i\")),!n&&!this._monthsParse[r]&&(o=\"^\"+this.months(a,\"\")+\"|^\"+this.monthsShort(a,\"\"),this._monthsParse[r]=new RegExp(o.replace(\".\",\"\"),\"i\")),n&&t===\"MMMM\"&&this._longMonthsParse[r].test(e))return r;if(n&&t===\"MMM\"&&this._shortMonthsParse[r].test(e))return r;if(!n&&this._monthsParse[r].test(e))return r}}function mN(e,t){var n;if(!e.isValid())return e;if(typeof t==\"string\"){if(/^\\d+$/.test(t))t=Zt(t);else if(t=e.localeData().monthsParse(t),!Ci(t))return e}return n=Math.min(e.date(),dg(e.year(),t)),e._d[\"set\"+(e._isUTC?\"UTC\":\"\")+\"Month\"](t,n),e}function gN(e){return e!=null?(mN(this,e),Ue.updateOffset(this,!0),this):Mv(this,\"Month\")}function J0e(){return dg(this.year(),this.month())}function Q0e(e){return this._monthsParseExact?(cn(this,\"_monthsRegex\")||yN.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(cn(this,\"_monthsShortRegex\")||(this._monthsShortRegex=U0e),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)}function e1e(e){return this._monthsParseExact?(cn(this,\"_monthsRegex\")||yN.call(this),e?this._monthsStrictRegex:this._monthsRegex):(cn(this,\"_monthsRegex\")||(this._monthsRegex=Y0e),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)}function yN(){function e(i,l){return l.length-i.length}var t=[],n=[],r=[],a,o;for(a=0;a<12;a++)o=Ho([2e3,a]),t.push(this.monthsShort(o,\"\")),n.push(this.months(o,\"\")),r.push(this.months(o,\"\")),r.push(this.monthsShort(o,\"\"));for(t.sort(e),n.sort(e),r.sort(e),a=0;a<12;a++)t[a]=aa(t[a]),n[a]=aa(n[a]);for(a=0;a<24;a++)r[a]=aa(r[a]);this._monthsRegex=new RegExp(\"^(\"+r.join(\"|\")+\")\",\"i\"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp(\"^(\"+n.join(\"|\")+\")\",\"i\"),this._monthsShortStrictRegex=new RegExp(\"^(\"+t.join(\"|\")+\")\",\"i\")}Tt(\"Y\",0,0,function(){var e=this.year();return e<=9999?Ro(e,4):\"+\"+e});Tt(0,[\"YY\",2],0,function(){return this.year()%100});Tt(0,[\"YYYY\",4],0,\"year\");Tt(0,[\"YYYYY\",5],0,\"year\");Tt(0,[\"YYYYYY\",6,!0],0,\"year\");Or(\"year\",\"y\");Pr(\"year\",1);gt(\"Y\",ug);gt(\"YY\",Dn,ya);gt(\"YYYY\",Lw,Rw);gt(\"YYYYY\",sg,ig);gt(\"YYYYYY\",sg,ig);Cn([\"YYYYY\",\"YYYYYY\"],kr);Cn(\"YYYY\",function(e,t){t[kr]=e.length===2?Ue.parseTwoDigitYear(e):Zt(e)});Cn(\"YY\",function(e,t){t[kr]=Ue.parseTwoDigitYear(e)});Cn(\"Y\",function(e,t){t[kr]=parseInt(e,10)});function $d(e){return og(e)?366:365}Ue.parseTwoDigitYear=function(e){return Zt(e)+(Zt(e)>68?1900:2e3)};var bN=_c(\"FullYear\",!0);function t1e(){return og(this.year())}function n1e(e,t,n,r,a,o,i){var l;return e<100&&e>=0?(l=new Date(e+400,t,n,r,a,o,i),isFinite(l.getFullYear())&&l.setFullYear(e)):l=new Date(e,t,n,r,a,o,i),l}function af(e){var t,n;return e<100&&e>=0?(n=Array.prototype.slice.call(arguments),n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)):t=new Date(Date.UTC.apply(null,arguments)),t}function Nv(e,t,n){var r=7+t-n,a=(7+af(e,0,r).getUTCDay()-t)%7;return-a+r-1}function CN(e,t,n,r,a){var o=(7+n-r)%7,i=Nv(e,r,a),l=1+7*(t-1)+o+i,s,c;return l<=0?(s=e-1,c=$d(s)+l):l>$d(e)?(s=e+1,c=l-$d(e)):(s=e,c=l),{year:s,dayOfYear:c}}function of(e,t,n){var r=Nv(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1,o,i;return a<1?(i=e.year()-1,o=a+fi(i,t,n)):a>fi(e.year(),t,n)?(o=a-fi(e.year(),t,n),i=e.year()+1):(i=e.year(),o=a),{week:o,year:i}}function fi(e,t,n){var r=Nv(e,t,n),a=Nv(e+1,t,n);return($d(e)-r+a)/7}Tt(\"w\",[\"ww\",2],\"wo\",\"week\");Tt(\"W\",[\"WW\",2],\"Wo\",\"isoWeek\");Or(\"week\",\"w\");Or(\"isoWeek\",\"W\");Pr(\"week\",5);Pr(\"isoWeek\",5);gt(\"w\",Dn);gt(\"ww\",Dn,ya);gt(\"W\",Dn);gt(\"WW\",Dn,ya);Lf([\"w\",\"ww\",\"W\",\"WW\"],function(e,t,n,r){t[r.substr(0,1)]=Zt(e)});function r1e(e){return of(e,this._week.dow,this._week.doy).week}var a1e={dow:0,doy:6};function o1e(){return this._week.dow}function i1e(){return this._week.doy}function l1e(e){var t=this.localeData().week(this);return e==null?t:this.add((e-t)*7,\"d\")}function s1e(e){var t=of(this,1,4).week;return e==null?t:this.add((e-t)*7,\"d\")}Tt(\"d\",0,\"do\",\"day\");Tt(\"dd\",0,0,function(e){return this.localeData().weekdaysMin(this,e)});Tt(\"ddd\",0,0,function(e){return this.localeData().weekdaysShort(this,e)});Tt(\"dddd\",0,0,function(e){return this.localeData().weekdays(this,e)});Tt(\"e\",0,0,\"weekday\");Tt(\"E\",0,0,\"isoWeekday\");Or(\"day\",\"d\");Or(\"weekday\",\"e\");Or(\"isoWeekday\",\"E\");Pr(\"day\",11);Pr(\"weekday\",11);Pr(\"isoWeekday\",11);gt(\"d\",Dn);gt(\"e\",Dn);gt(\"E\",Dn);gt(\"dd\",function(e,t){return t.weekdaysMinRegex(e)});gt(\"ddd\",function(e,t){return t.weekdaysShortRegex(e)});gt(\"dddd\",function(e,t){return t.weekdaysRegex(e)});Lf([\"dd\",\"ddd\",\"dddd\"],function(e,t,n,r){var a=n._locale.weekdaysParse(e,r,n._strict);a!=null?t.d=a:qt(n).invalidWeekday=e});Lf([\"d\",\"e\",\"E\"],function(e,t,n,r){t[r]=Zt(e)});function u1e(e,t){return typeof e!=\"string\"?e:isNaN(e)?(e=t.weekdaysParse(e),typeof e==\"number\"?e:null):parseInt(e,10)}function c1e(e,t){return typeof e==\"string\"?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}function Fw(e,t){return e.slice(t,7).concat(e.slice(0,t))}var d1e=\"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday\".split(\"_\"),wN=\"Sun_Mon_Tue_Wed_Thu_Fri_Sat\".split(\"_\"),f1e=\"Su_Mo_Tu_We_Th_Fr_Sa\".split(\"_\"),h1e=Rf,p1e=Rf,v1e=Rf;function m1e(e,t){var n=so(this._weekdays)?this._weekdays:this._weekdays[e&&e!==!0&&this._weekdays.isFormat.test(t)?\"format\":\"standalone\"];return e===!0?Fw(n,this._week.dow):e?n[e.day()]:n}function g1e(e){return e===!0?Fw(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function y1e(e){return e===!0?Fw(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function b1e(e,t,n){var r,a,o,i=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],r=0;r<7;++r)o=Ho([2e3,1]).day(r),this._minWeekdaysParse[r]=this.weekdaysMin(o,\"\").toLocaleLowerCase(),this._shortWeekdaysParse[r]=this.weekdaysShort(o,\"\").toLocaleLowerCase(),this._weekdaysParse[r]=this.weekdays(o,\"\").toLocaleLowerCase();return n?t===\"dddd\"?(a=Zn.call(this._weekdaysParse,i),a!==-1?a:null):t===\"ddd\"?(a=Zn.call(this._shortWeekdaysParse,i),a!==-1?a:null):(a=Zn.call(this._minWeekdaysParse,i),a!==-1?a:null):t===\"dddd\"?(a=Zn.call(this._weekdaysParse,i),a!==-1||(a=Zn.call(this._shortWeekdaysParse,i),a!==-1)?a:(a=Zn.call(this._minWeekdaysParse,i),a!==-1?a:null)):t===\"ddd\"?(a=Zn.call(this._shortWeekdaysParse,i),a!==-1||(a=Zn.call(this._weekdaysParse,i),a!==-1)?a:(a=Zn.call(this._minWeekdaysParse,i),a!==-1?a:null)):(a=Zn.call(this._minWeekdaysParse,i),a!==-1||(a=Zn.call(this._weekdaysParse,i),a!==-1)?a:(a=Zn.call(this._shortWeekdaysParse,i),a!==-1?a:null))}function C1e(e,t,n){var r,a,o;if(this._weekdaysParseExact)return b1e.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),r=0;r<7;r++){if(a=Ho([2e3,1]).day(r),n&&!this._fullWeekdaysParse[r]&&(this._fullWeekdaysParse[r]=new RegExp(\"^\"+this.weekdays(a,\"\").replace(\".\",\"\\\\.?\")+\"$\",\"i\"),this._shortWeekdaysParse[r]=new RegExp(\"^\"+this.weekdaysShort(a,\"\").replace(\".\",\"\\\\.?\")+\"$\",\"i\"),this._minWeekdaysParse[r]=new RegExp(\"^\"+this.weekdaysMin(a,\"\").replace(\".\",\"\\\\.?\")+\"$\",\"i\")),this._weekdaysParse[r]||(o=\"^\"+this.weekdays(a,\"\")+\"|^\"+this.weekdaysShort(a,\"\")+\"|^\"+this.weekdaysMin(a,\"\"),this._weekdaysParse[r]=new RegExp(o.replace(\".\",\"\"),\"i\")),n&&t===\"dddd\"&&this._fullWeekdaysParse[r].test(e))return r;if(n&&t===\"ddd\"&&this._shortWeekdaysParse[r].test(e))return r;if(n&&t===\"dd\"&&this._minWeekdaysParse[r].test(e))return r;if(!n&&this._weekdaysParse[r].test(e))return r}}function w1e(e){if(!this.isValid())return e!=null?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return e!=null?(e=u1e(e,this.localeData()),this.add(e-t,\"d\")):t}function S1e(e){if(!this.isValid())return e!=null?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return e==null?t:this.add(e-t,\"d\")}function k1e(e){if(!this.isValid())return e!=null?this:NaN;if(e!=null){var t=c1e(e,this.localeData());return this.day(this.day()%7?t:t-7)}else return this.day()||7}function $1e(e){return this._weekdaysParseExact?(cn(this,\"_weekdaysRegex\")||Bw.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(cn(this,\"_weekdaysRegex\")||(this._weekdaysRegex=h1e),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function O1e(e){return this._weekdaysParseExact?(cn(this,\"_weekdaysRegex\")||Bw.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(cn(this,\"_weekdaysShortRegex\")||(this._weekdaysShortRegex=p1e),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function P1e(e){return this._weekdaysParseExact?(cn(this,\"_weekdaysRegex\")||Bw.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(cn(this,\"_weekdaysMinRegex\")||(this._weekdaysMinRegex=v1e),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Bw(){function e(d,f){return f.length-d.length}var t=[],n=[],r=[],a=[],o,i,l,s,c;for(o=0;o<7;o++)i=Ho([2e3,1]).day(o),l=aa(this.weekdaysMin(i,\"\")),s=aa(this.weekdaysShort(i,\"\")),c=aa(this.weekdays(i,\"\")),t.push(l),n.push(s),r.push(c),a.push(l),a.push(s),a.push(c);t.sort(e),n.sort(e),r.sort(e),a.sort(e),this._weekdaysRegex=new RegExp(\"^(\"+a.join(\"|\")+\")\",\"i\"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp(\"^(\"+r.join(\"|\")+\")\",\"i\"),this._weekdaysShortStrictRegex=new RegExp(\"^(\"+n.join(\"|\")+\")\",\"i\"),this._weekdaysMinStrictRegex=new RegExp(\"^(\"+t.join(\"|\")+\")\",\"i\")}function Vw(){return this.hours()%12||12}function T1e(){return this.hours()||24}Tt(\"H\",[\"HH\",2],0,\"hour\");Tt(\"h\",[\"hh\",2],0,Vw);Tt(\"k\",[\"kk\",2],0,T1e);Tt(\"hmm\",0,0,function(){return\"\"+Vw.apply(this)+Ro(this.minutes(),2)});Tt(\"hmmss\",0,0,function(){return\"\"+Vw.apply(this)+Ro(this.minutes(),2)+Ro(this.seconds(),2)});Tt(\"Hmm\",0,0,function(){return\"\"+this.hours()+Ro(this.minutes(),2)});Tt(\"Hmmss\",0,0,function(){return\"\"+this.hours()+Ro(this.minutes(),2)+Ro(this.seconds(),2)});function SN(e,t){Tt(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}SN(\"a\",!0);SN(\"A\",!1);Or(\"hour\",\"h\");Pr(\"hour\",13);function kN(e,t){return t._meridiemParse}gt(\"a\",kN);gt(\"A\",kN);gt(\"H\",Dn);gt(\"h\",Dn);gt(\"k\",Dn);gt(\"HH\",Dn,ya);gt(\"hh\",Dn,ya);gt(\"kk\",Dn,ya);gt(\"hmm\",fN);gt(\"hmmss\",hN);gt(\"Hmm\",fN);gt(\"Hmmss\",hN);Cn([\"H\",\"HH\"],ar);Cn([\"k\",\"kk\"],function(e,t,n){var r=Zt(e);t[ar]=r===24?0:r});Cn([\"a\",\"A\"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e});Cn([\"h\",\"hh\"],function(e,t,n){t[ar]=Zt(e),qt(n).bigHour=!0});Cn(\"hmm\",function(e,t,n){var r=e.length-2;t[ar]=Zt(e.substr(0,r)),t[Ja]=Zt(e.substr(r)),qt(n).bigHour=!0});Cn(\"hmmss\",function(e,t,n){var r=e.length-4,a=e.length-2;t[ar]=Zt(e.substr(0,r)),t[Ja]=Zt(e.substr(r,2)),t[li]=Zt(e.substr(a)),qt(n).bigHour=!0});Cn(\"Hmm\",function(e,t,n){var r=e.length-2;t[ar]=Zt(e.substr(0,r)),t[Ja]=Zt(e.substr(r))});Cn(\"Hmmss\",function(e,t,n){var r=e.length-4,a=e.length-2;t[ar]=Zt(e.substr(0,r)),t[Ja]=Zt(e.substr(r,2)),t[li]=Zt(e.substr(a))});function x1e(e){return(e+\"\").toLowerCase().charAt(0)===\"p\"}var _1e=/[ap]\\.?m?\\.?/i,E1e=_c(\"Hours\",!0);function M1e(e,t,n){return e>11?n?\"pm\":\"PM\":n?\"am\":\"AM\"}var $N={calendar:C0e,longDateFormat:$0e,invalidDate:P0e,ordinal:x0e,dayOfMonthOrdinalParse:_0e,relativeTime:M0e,months:W0e,monthsShort:pN,week:a1e,weekdays:d1e,weekdaysMin:f1e,weekdaysShort:wN,meridiemParse:_1e},Fn={},Hc={},lf;function I1e(e,t){var n,r=Math.min(e.length,t.length);for(n=0;n<r;n+=1)if(e[n]!==t[n])return n;return r}function XO(e){return e&&e.toLowerCase().replace(\"_\",\"-\")}function N1e(e){for(var t=0,n,r,a,o;t<e.length;){for(o=XO(e[t]).split(\"-\"),n=o.length,r=XO(e[t+1]),r=r?r.split(\"-\"):null;n>0;){if(a=fg(o.slice(0,n).join(\"-\")),a)return a;if(r&&r.length>=n&&I1e(o,r)>=n-1)break;n--}t++}return lf}function A1e(e){return e.match(\"^[^/\\\\\\\\]*$\")!=null}function fg(e){var t=null,n;if(Fn[e]===void 0&&typeof Sr!=\"undefined\"&&Sr&&Sr.exports&&A1e(e))try{t=lf._abbr,n=require,n(\"./locale/\"+e),nl(t)}catch{Fn[e]=null}return Fn[e]}function nl(e,t){var n;return e&&(Lr(t)?n=_i(e):n=zw(e,t),n?lf=n:typeof console!=\"undefined\"&&console.warn&&console.warn(\"Locale \"+e+\" not found. Did you forget to load it?\")),lf._abbr}function zw(e,t){if(t!==null){var n,r=$N;if(t.abbr=e,Fn[e]!=null)iN(\"defineLocaleOverride\",\"use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info.\"),r=Fn[e]._config;else if(t.parentLocale!=null)if(Fn[t.parentLocale]!=null)r=Fn[t.parentLocale]._config;else if(n=fg(t.parentLocale),n!=null)r=n._config;else return Hc[t.parentLocale]||(Hc[t.parentLocale]=[]),Hc[t.parentLocale].push({name:e,config:t}),null;return Fn[e]=new Nw(n1(r,t)),Hc[e]&&Hc[e].forEach(function(a){zw(a.name,a.config)}),nl(e),Fn[e]}else return delete Fn[e],null}function D1e(e,t){if(t!=null){var n,r,a=$N;Fn[e]!=null&&Fn[e].parentLocale!=null?Fn[e].set(n1(Fn[e]._config,t)):(r=fg(e),r!=null&&(a=r._config),t=n1(a,t),r==null&&(t.abbr=e),n=new Nw(t),n.parentLocale=Fn[e],Fn[e]=n),nl(e)}else Fn[e]!=null&&(Fn[e].parentLocale!=null?(Fn[e]=Fn[e].parentLocale,e===nl()&&nl(e)):Fn[e]!=null&&delete Fn[e]);return Fn[e]}function _i(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return lf;if(!so(e)){if(t=fg(e),t)return t;e=[e]}return N1e(e)}function R1e(){return r1(Fn)}function Hw(e){var t,n=e._a;return n&&qt(e).overflow===-2&&(t=n[ii]<0||n[ii]>11?ii:n[Oo]<1||n[Oo]>dg(n[kr],n[ii])?Oo:n[ar]<0||n[ar]>24||n[ar]===24&&(n[Ja]!==0||n[li]!==0||n[Xl]!==0)?ar:n[Ja]<0||n[Ja]>59?Ja:n[li]<0||n[li]>59?li:n[Xl]<0||n[Xl]>999?Xl:-1,qt(e)._overflowDayOfYear&&(t<kr||t>Oo)&&(t=Oo),qt(e)._overflowWeeks&&t===-1&&(t=H0e),qt(e)._overflowWeekday&&t===-1&&(t=j0e),qt(e).overflow=t),e}var L1e=/^\\s*((?:[+-]\\d{6}|\\d{4})-(?:\\d\\d-\\d\\d|W\\d\\d-\\d|W\\d\\d|\\d\\d\\d|\\d\\d))(?:(T| )(\\d\\d(?::\\d\\d(?::\\d\\d(?:[.,]\\d+)?)?)?)([+-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,F1e=/^\\s*((?:[+-]\\d{6}|\\d{4})(?:\\d\\d\\d\\d|W\\d\\d\\d|W\\d\\d|\\d\\d\\d|\\d\\d|))(?:(T| )(\\d\\d(?:\\d\\d(?:\\d\\d(?:[.,]\\d+)?)?)?)([+-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,B1e=/Z|[+-]\\d\\d(?::?\\d\\d)?/,vh=[[\"YYYYYY-MM-DD\",/[+-]\\d{6}-\\d\\d-\\d\\d/],[\"YYYY-MM-DD\",/\\d{4}-\\d\\d-\\d\\d/],[\"GGGG-[W]WW-E\",/\\d{4}-W\\d\\d-\\d/],[\"GGGG-[W]WW\",/\\d{4}-W\\d\\d/,!1],[\"YYYY-DDD\",/\\d{4}-\\d{3}/],[\"YYYY-MM\",/\\d{4}-\\d\\d/,!1],[\"YYYYYYMMDD\",/[+-]\\d{10}/],[\"YYYYMMDD\",/\\d{8}/],[\"GGGG[W]WWE\",/\\d{4}W\\d{3}/],[\"GGGG[W]WW\",/\\d{4}W\\d{2}/,!1],[\"YYYYDDD\",/\\d{7}/],[\"YYYYMM\",/\\d{6}/,!1],[\"YYYY\",/\\d{4}/,!1]],My=[[\"HH:mm:ss.SSSS\",/\\d\\d:\\d\\d:\\d\\d\\.\\d+/],[\"HH:mm:ss,SSSS\",/\\d\\d:\\d\\d:\\d\\d,\\d+/],[\"HH:mm:ss\",/\\d\\d:\\d\\d:\\d\\d/],[\"HH:mm\",/\\d\\d:\\d\\d/],[\"HHmmss.SSSS\",/\\d\\d\\d\\d\\d\\d\\.\\d+/],[\"HHmmss,SSSS\",/\\d\\d\\d\\d\\d\\d,\\d+/],[\"HHmmss\",/\\d\\d\\d\\d\\d\\d/],[\"HHmm\",/\\d\\d\\d\\d/],[\"HH\",/\\d\\d/]],V1e=/^\\/?Date\\((-?\\d+)/i,z1e=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\\s)?(\\d{1,2})\\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\s(\\d{2,4})\\s(\\d\\d):(\\d\\d)(?::(\\d\\d))?\\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\\d{4}))$/,H1e={UT:0,GMT:0,EDT:-4*60,EST:-5*60,CDT:-5*60,CST:-6*60,MDT:-6*60,MST:-7*60,PDT:-7*60,PST:-8*60};function ON(e){var t,n,r=e._i,a=L1e.exec(r)||F1e.exec(r),o,i,l,s,c=vh.length,d=My.length;if(a){for(qt(e).iso=!0,t=0,n=c;t<n;t++)if(vh[t][1].exec(a[1])){i=vh[t][0],o=vh[t][2]!==!1;break}if(i==null){e._isValid=!1;return}if(a[3]){for(t=0,n=d;t<n;t++)if(My[t][1].exec(a[3])){l=(a[2]||\" \")+My[t][0];break}if(l==null){e._isValid=!1;return}}if(!o&&l!=null){e._isValid=!1;return}if(a[4])if(B1e.exec(a[4]))s=\"Z\";else{e._isValid=!1;return}e._f=i+(l||\"\")+(s||\"\"),Kw(e)}else e._isValid=!1}function j1e(e,t,n,r,a,o){var i=[K1e(e),pN.indexOf(t),parseInt(n,10),parseInt(r,10),parseInt(a,10)];return o&&i.push(parseInt(o,10)),i}function K1e(e){var t=parseInt(e,10);return t<=49?2e3+t:t<=999?1900+t:t}function W1e(e){return e.replace(/\\([^)]*\\)|[\\n\\t]/g,\" \").replace(/(\\s\\s+)/g,\" \").replace(/^\\s\\s*/,\"\").replace(/\\s\\s*$/,\"\")}function U1e(e,t,n){if(e){var r=wN.indexOf(e),a=new Date(t[0],t[1],t[2]).getDay();if(r!==a)return qt(n).weekdayMismatch=!0,n._isValid=!1,!1}return!0}function Y1e(e,t,n){if(e)return H1e[e];if(t)return 0;var r=parseInt(n,10),a=r%100,o=(r-a)/100;return o*60+a}function PN(e){var t=z1e.exec(W1e(e._i)),n;if(t){if(n=j1e(t[4],t[3],t[2],t[5],t[6],t[7]),!U1e(t[1],n,e))return;e._a=n,e._tzm=Y1e(t[8],t[9],t[10]),e._d=af.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),qt(e).rfc2822=!0}else e._isValid=!1}function q1e(e){var t=V1e.exec(e._i);if(t!==null){e._d=new Date(+t[1]);return}if(ON(e),e._isValid===!1)delete e._isValid;else return;if(PN(e),e._isValid===!1)delete e._isValid;else return;e._strict?e._isValid=!1:Ue.createFromInputFallback(e)}Ue.createFromInputFallback=Fa(\"value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.\",function(e){e._d=new Date(e._i+(e._useUTC?\" UTC\":\"\"))});function uu(e,t,n){return e!=null?e:t!=null?t:n}function G1e(e){var t=new Date(Ue.now());return e._useUTC?[t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()]:[t.getFullYear(),t.getMonth(),t.getDate()]}function jw(e){var t,n,r=[],a,o,i;if(!e._d){for(a=G1e(e),e._w&&e._a[Oo]==null&&e._a[ii]==null&&X1e(e),e._dayOfYear!=null&&(i=uu(e._a[kr],a[kr]),(e._dayOfYear>$d(i)||e._dayOfYear===0)&&(qt(e)._overflowDayOfYear=!0),n=af(i,0,e._dayOfYear),e._a[ii]=n.getUTCMonth(),e._a[Oo]=n.getUTCDate()),t=0;t<3&&e._a[t]==null;++t)e._a[t]=r[t]=a[t];for(;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];e._a[ar]===24&&e._a[Ja]===0&&e._a[li]===0&&e._a[Xl]===0&&(e._nextDay=!0,e._a[ar]=0),e._d=(e._useUTC?af:n1e).apply(null,r),o=e._useUTC?e._d.getUTCDay():e._d.getDay(),e._tzm!=null&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ar]=24),e._w&&typeof e._w.d!=\"undefined\"&&e._w.d!==o&&(qt(e).weekdayMismatch=!0)}}function X1e(e){var t,n,r,a,o,i,l,s,c;t=e._w,t.GG!=null||t.W!=null||t.E!=null?(o=1,i=4,n=uu(t.GG,e._a[kr],of(Nn(),1,4).year),r=uu(t.W,1),a=uu(t.E,1),(a<1||a>7)&&(s=!0)):(o=e._locale._week.dow,i=e._locale._week.doy,c=of(Nn(),o,i),n=uu(t.gg,e._a[kr],c.year),r=uu(t.w,c.week),t.d!=null?(a=t.d,(a<0||a>6)&&(s=!0)):t.e!=null?(a=t.e+o,(t.e<0||t.e>6)&&(s=!0)):a=o),r<1||r>fi(n,o,i)?qt(e)._overflowWeeks=!0:s!=null?qt(e)._overflowWeekday=!0:(l=CN(n,r,a,o,i),e._a[kr]=l.year,e._dayOfYear=l.dayOfYear)}Ue.ISO_8601=function(){};Ue.RFC_2822=function(){};function Kw(e){if(e._f===Ue.ISO_8601){ON(e);return}if(e._f===Ue.RFC_2822){PN(e);return}e._a=[],qt(e).empty=!0;var t=\"\"+e._i,n,r,a,o,i,l=t.length,s=0,c,d;for(a=lN(e._f,e._locale).match(Aw)||[],d=a.length,n=0;n<d;n++)o=a[n],r=(t.match(B0e(o,e))||[])[0],r&&(i=t.substr(0,t.indexOf(r)),i.length>0&&qt(e).unusedInput.push(i),t=t.slice(t.indexOf(r)+r.length),s+=r.length),Eu[o]?(r?qt(e).empty=!1:qt(e).unusedTokens.push(o),z0e(o,r,e)):e._strict&&!r&&qt(e).unusedTokens.push(o);qt(e).charsLeftOver=l-s,t.length>0&&qt(e).unusedInput.push(t),e._a[ar]<=12&&qt(e).bigHour===!0&&e._a[ar]>0&&(qt(e).bigHour=void 0),qt(e).parsedDateParts=e._a.slice(0),qt(e).meridiem=e._meridiem,e._a[ar]=Z1e(e._locale,e._a[ar],e._meridiem),c=qt(e).era,c!==null&&(e._a[kr]=e._locale.erasConvertYear(c,e._a[kr])),jw(e),Hw(e)}function Z1e(e,t,n){var r;return n==null?t:e.meridiemHour!=null?e.meridiemHour(t,n):(e.isPM!=null&&(r=e.isPM(n),r&&t<12&&(t+=12),!r&&t===12&&(t=0)),t)}function J1e(e){var t,n,r,a,o,i,l=!1,s=e._f.length;if(s===0){qt(e).invalidFormat=!0,e._d=new Date(NaN);return}for(a=0;a<s;a++)o=0,i=!1,t=Iw({},e),e._useUTC!=null&&(t._useUTC=e._useUTC),t._f=e._f[a],Kw(t),Mw(t)&&(i=!0),o+=qt(t).charsLeftOver,o+=qt(t).unusedTokens.length*10,qt(t).score=o,l?o<r&&(r=o,n=t):(r==null||o<r||i)&&(r=o,n=t,i&&(l=!0));Gi(e,n||t)}function Q1e(e){if(!e._d){var t=Dw(e._i),n=t.day===void 0?t.date:t.day;e._a=aN([t.year,t.month,n,t.hour,t.minute,t.second,t.millisecond],function(r){return r&&parseInt(r,10)}),jw(e)}}function eCe(e){var t=new Df(Hw(TN(e)));return t._nextDay&&(t.add(1,\"d\"),t._nextDay=void 0),t}function TN(e){var t=e._i,n=e._f;return e._locale=e._locale||_i(e._l),t===null||n===void 0&&t===\"\"?ag({nullInput:!0}):(typeof t==\"string\"&&(e._i=t=e._locale.preparse(t)),uo(t)?new Df(Hw(t)):(Af(t)?e._d=t:so(n)?J1e(e):n?Kw(e):tCe(e),Mw(e)||(e._d=null),e))}function tCe(e){var t=e._i;Lr(t)?e._d=new Date(Ue.now()):Af(t)?e._d=new Date(t.valueOf()):typeof t==\"string\"?q1e(e):so(t)?(e._a=aN(t.slice(0),function(n){return parseInt(n,10)}),jw(e)):ls(t)?Q1e(e):Ci(t)?e._d=new Date(t):Ue.createFromInputFallback(e)}function xN(e,t,n,r,a){var o={};return(t===!0||t===!1)&&(r=t,t=void 0),(n===!0||n===!1)&&(r=n,n=void 0),(ls(e)&&Ew(e)||so(e)&&e.length===0)&&(e=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=a,o._l=n,o._i=e,o._f=t,o._strict=r,eCe(o)}function Nn(e,t,n,r){return xN(e,t,n,r,!1)}var nCe=Fa(\"moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/\",function(){var e=Nn.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:ag()}),rCe=Fa(\"moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/\",function(){var e=Nn.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:ag()});function _N(e,t){var n,r;if(t.length===1&&so(t[0])&&(t=t[0]),!t.length)return Nn();for(n=t[0],r=1;r<t.length;++r)(!t[r].isValid()||t[r][e](n))&&(n=t[r]);return n}function aCe(){var e=[].slice.call(arguments,0);return _N(\"isBefore\",e)}function oCe(){var e=[].slice.call(arguments,0);return _N(\"isAfter\",e)}var iCe=function(){return Date.now?Date.now():+new Date},jc=[\"year\",\"quarter\",\"month\",\"week\",\"day\",\"hour\",\"minute\",\"second\",\"millisecond\"];function lCe(e){var t,n=!1,r,a=jc.length;for(t in e)if(cn(e,t)&&!(Zn.call(jc,t)!==-1&&(e[t]==null||!isNaN(e[t]))))return!1;for(r=0;r<a;++r)if(e[jc[r]]){if(n)return!1;parseFloat(e[jc[r]])!==Zt(e[jc[r]])&&(n=!0)}return!0}function sCe(){return this._isValid}function uCe(){return mo(NaN)}function hg(e){var t=Dw(e),n=t.year||0,r=t.quarter||0,a=t.month||0,o=t.week||t.isoWeek||0,i=t.day||0,l=t.hour||0,s=t.minute||0,c=t.second||0,d=t.millisecond||0;this._isValid=lCe(t),this._milliseconds=+d+c*1e3+s*6e4+l*1e3*60*60,this._days=+i+o*7,this._months=+a+r*3+n*12,this._data={},this._locale=_i(),this._bubble()}function Rp(e){return e instanceof hg}function o1(e){return e<0?Math.round(-1*e)*-1:Math.round(e)}function cCe(e,t,n){var r=Math.min(e.length,t.length),a=Math.abs(e.length-t.length),o=0,i;for(i=0;i<r;i++)(n&&e[i]!==t[i]||!n&&Zt(e[i])!==Zt(t[i]))&&o++;return o+a}function EN(e,t){Tt(e,0,0,function(){var n=this.utcOffset(),r=\"+\";return n<0&&(n=-n,r=\"-\"),r+Ro(~~(n/60),2)+t+Ro(~~n%60,2)})}EN(\"Z\",\":\");EN(\"ZZ\",\"\");gt(\"Z\",cg);gt(\"ZZ\",cg);Cn([\"Z\",\"ZZ\"],function(e,t,n){n._useUTC=!0,n._tzm=Ww(cg,e)});var dCe=/([\\+\\-]|\\d\\d)/gi;function Ww(e,t){var n=(t||\"\").match(e),r,a,o;return n===null?null:(r=n[n.length-1]||[],a=(r+\"\").match(dCe)||[\"-\",0,0],o=+(a[1]*60)+Zt(a[2]),o===0?0:a[0]===\"+\"?o:-o)}function Uw(e,t){var n,r;return t._isUTC?(n=t.clone(),r=(uo(e)||Af(e)?e.valueOf():Nn(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+r),Ue.updateOffset(n,!1),n):Nn(e).local()}function i1(e){return-Math.round(e._d.getTimezoneOffset())}Ue.updateOffset=function(){};function fCe(e,t,n){var r=this._offset||0,a;if(!this.isValid())return e!=null?this:NaN;if(e!=null){if(typeof e==\"string\"){if(e=Ww(cg,e),e===null)return this}else Math.abs(e)<16&&!n&&(e=e*60);return!this._isUTC&&t&&(a=i1(this)),this._offset=e,this._isUTC=!0,a!=null&&this.add(a,\"m\"),r!==e&&(!t||this._changeInProgress?NN(this,mo(e-r,\"m\"),1,!1):this._changeInProgress||(this._changeInProgress=!0,Ue.updateOffset(this,!0),this._changeInProgress=null)),this}else return this._isUTC?r:i1(this)}function hCe(e,t){return e!=null?(typeof e!=\"string\"&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}function pCe(e){return this.utcOffset(0,e)}function vCe(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(i1(this),\"m\")),this}function mCe(){if(this._tzm!=null)this.utcOffset(this._tzm,!1,!0);else if(typeof this._i==\"string\"){var e=Ww(L0e,this._i);e!=null?this.utcOffset(e):this.utcOffset(0,!0)}return this}function gCe(e){return this.isValid()?(e=e?Nn(e).utcOffset():0,(this.utcOffset()-e)%60===0):!1}function yCe(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function bCe(){if(!Lr(this._isDSTShifted))return this._isDSTShifted;var e={},t;return Iw(e,this),e=TN(e),e._a?(t=e._isUTC?Ho(e._a):Nn(e._a),this._isDSTShifted=this.isValid()&&cCe(e._a,t.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function CCe(){return this.isValid()?!this._isUTC:!1}function wCe(){return this.isValid()?this._isUTC:!1}function MN(){return this.isValid()?this._isUTC&&this._offset===0:!1}var SCe=/^(-|\\+)?(?:(\\d*)[. ])?(\\d+):(\\d+)(?::(\\d+)(\\.\\d*)?)?$/,kCe=/^(-|\\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function mo(e,t){var n=e,r=null,a,o,i;return Rp(e)?n={ms:e._milliseconds,d:e._days,M:e._months}:Ci(e)||!isNaN(+e)?(n={},t?n[t]=+e:n.milliseconds=+e):(r=SCe.exec(e))?(a=r[1]===\"-\"?-1:1,n={y:0,d:Zt(r[Oo])*a,h:Zt(r[ar])*a,m:Zt(r[Ja])*a,s:Zt(r[li])*a,ms:Zt(o1(r[Xl]*1e3))*a}):(r=kCe.exec(e))?(a=r[1]===\"-\"?-1:1,n={y:Ol(r[2],a),M:Ol(r[3],a),w:Ol(r[4],a),d:Ol(r[5],a),h:Ol(r[6],a),m:Ol(r[7],a),s:Ol(r[8],a)}):n==null?n={}:typeof n==\"object\"&&(\"from\"in n||\"to\"in n)&&(i=$Ce(Nn(n.from),Nn(n.to)),n={},n.ms=i.milliseconds,n.M=i.months),o=new hg(n),Rp(e)&&cn(e,\"_locale\")&&(o._locale=e._locale),Rp(e)&&cn(e,\"_isValid\")&&(o._isValid=e._isValid),o}mo.fn=hg.prototype;mo.invalid=uCe;function Ol(e,t){var n=e&&parseFloat(e.replace(\",\",\".\"));return(isNaN(n)?0:n)*t}function ZO(e,t){var n={};return n.months=t.month()-e.month()+(t.year()-e.year())*12,e.clone().add(n.months,\"M\").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,\"M\"),n}function $Ce(e,t){var n;return e.isValid()&&t.isValid()?(t=Uw(t,e),e.isBefore(t)?n=ZO(e,t):(n=ZO(t,e),n.milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function IN(e,t){return function(n,r){var a,o;return r!==null&&!isNaN(+r)&&(iN(t,\"moment().\"+t+\"(period, number) is deprecated. Please use moment().\"+t+\"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.\"),o=n,n=r,r=o),a=mo(n,r),NN(this,a,e),this}}function NN(e,t,n,r){var a=t._milliseconds,o=o1(t._days),i=o1(t._months);!e.isValid()||(r=r==null?!0:r,i&&mN(e,Mv(e,\"Month\")+i*n),o&&uN(e,\"Date\",Mv(e,\"Date\")+o*n),a&&e._d.setTime(e._d.valueOf()+a*n),r&&Ue.updateOffset(e,o||i))}var OCe=IN(1,\"add\"),PCe=IN(-1,\"subtract\");function AN(e){return typeof e==\"string\"||e instanceof String}function TCe(e){return uo(e)||Af(e)||AN(e)||Ci(e)||_Ce(e)||xCe(e)||e===null||e===void 0}function xCe(e){var t=ls(e)&&!Ew(e),n=!1,r=[\"years\",\"year\",\"y\",\"months\",\"month\",\"M\",\"days\",\"day\",\"d\",\"dates\",\"date\",\"D\",\"hours\",\"hour\",\"h\",\"minutes\",\"minute\",\"m\",\"seconds\",\"second\",\"s\",\"milliseconds\",\"millisecond\",\"ms\"],a,o,i=r.length;for(a=0;a<i;a+=1)o=r[a],n=n||cn(e,o);return t&&n}function _Ce(e){var t=so(e),n=!1;return t&&(n=e.filter(function(r){return!Ci(r)&&AN(e)}).length===0),t&&n}function ECe(e){var t=ls(e)&&!Ew(e),n=!1,r=[\"sameDay\",\"nextDay\",\"lastDay\",\"nextWeek\",\"lastWeek\",\"sameElse\"],a,o;for(a=0;a<r.length;a+=1)o=r[a],n=n||cn(e,o);return t&&n}function MCe(e,t){var n=e.diff(t,\"days\",!0);return n<-6?\"sameElse\":n<-1?\"lastWeek\":n<0?\"lastDay\":n<1?\"sameDay\":n<2?\"nextDay\":n<7?\"nextWeek\":\"sameElse\"}function ICe(e,t){arguments.length===1&&(arguments[0]?TCe(arguments[0])?(e=arguments[0],t=void 0):ECe(arguments[0])&&(t=arguments[0],e=void 0):(e=void 0,t=void 0));var n=e||Nn(),r=Uw(n,this).startOf(\"day\"),a=Ue.calendarFormat(this,r)||\"sameElse\",o=t&&(jo(t[a])?t[a].call(this,n):t[a]);return this.format(o||this.localeData().calendar(a,this,Nn(n)))}function NCe(){return new Df(this)}function ACe(e,t){var n=uo(e)?e:Nn(e);return this.isValid()&&n.isValid()?(t=Ba(t)||\"millisecond\",t===\"millisecond\"?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf()):!1}function DCe(e,t){var n=uo(e)?e:Nn(e);return this.isValid()&&n.isValid()?(t=Ba(t)||\"millisecond\",t===\"millisecond\"?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf()):!1}function RCe(e,t,n,r){var a=uo(e)?e:Nn(e),o=uo(t)?t:Nn(t);return this.isValid()&&a.isValid()&&o.isValid()?(r=r||\"()\",(r[0]===\"(\"?this.isAfter(a,n):!this.isBefore(a,n))&&(r[1]===\")\"?this.isBefore(o,n):!this.isAfter(o,n))):!1}function LCe(e,t){var n=uo(e)?e:Nn(e),r;return this.isValid()&&n.isValid()?(t=Ba(t)||\"millisecond\",t===\"millisecond\"?this.valueOf()===n.valueOf():(r=n.valueOf(),this.clone().startOf(t).valueOf()<=r&&r<=this.clone().endOf(t).valueOf())):!1}function FCe(e,t){return this.isSame(e,t)||this.isAfter(e,t)}function BCe(e,t){return this.isSame(e,t)||this.isBefore(e,t)}function VCe(e,t,n){var r,a,o;if(!this.isValid())return NaN;if(r=Uw(e,this),!r.isValid())return NaN;switch(a=(r.utcOffset()-this.utcOffset())*6e4,t=Ba(t),t){case\"year\":o=Lp(this,r)/12;break;case\"month\":o=Lp(this,r);break;case\"quarter\":o=Lp(this,r)/3;break;case\"second\":o=(this-r)/1e3;break;case\"minute\":o=(this-r)/6e4;break;case\"hour\":o=(this-r)/36e5;break;case\"day\":o=(this-r-a)/864e5;break;case\"week\":o=(this-r-a)/6048e5;break;default:o=this-r}return n?o:Oa(o)}function Lp(e,t){if(e.date()<t.date())return-Lp(t,e);var n=(t.year()-e.year())*12+(t.month()-e.month()),r=e.clone().add(n,\"months\"),a,o;return t-r<0?(a=e.clone().add(n-1,\"months\"),o=(t-r)/(r-a)):(a=e.clone().add(n+1,\"months\"),o=(t-r)/(a-r)),-(n+o)||0}Ue.defaultFormat=\"YYYY-MM-DDTHH:mm:ssZ\";Ue.defaultFormatUtc=\"YYYY-MM-DDTHH:mm:ss[Z]\";function zCe(){return this.clone().locale(\"en\").format(\"ddd MMM DD YYYY HH:mm:ss [GMT]ZZ\")}function HCe(e){if(!this.isValid())return null;var t=e!==!0,n=t?this.clone().utc():this;return n.year()<0||n.year()>9999?Dp(n,t?\"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]\":\"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ\"):jo(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+this.utcOffset()*60*1e3).toISOString().replace(\"Z\",Dp(n,\"Z\")):Dp(n,t?\"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]\":\"YYYY-MM-DD[T]HH:mm:ss.SSSZ\")}function jCe(){if(!this.isValid())return\"moment.invalid(/* \"+this._i+\" */)\";var e=\"moment\",t=\"\",n,r,a,o;return this.isLocal()||(e=this.utcOffset()===0?\"moment.utc\":\"moment.parseZone\",t=\"Z\"),n=\"[\"+e+'(\"]',r=0<=this.year()&&this.year()<=9999?\"YYYY\":\"YYYYYY\",a=\"-MM-DD[T]HH:mm:ss.SSS\",o=t+'[\")]',this.format(n+r+a+o)}function KCe(e){e||(e=this.isUtc()?Ue.defaultFormatUtc:Ue.defaultFormat);var t=Dp(this,e);return this.localeData().postformat(t)}function WCe(e,t){return this.isValid()&&(uo(e)&&e.isValid()||Nn(e).isValid())?mo({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function UCe(e){return this.from(Nn(),e)}function YCe(e,t){return this.isValid()&&(uo(e)&&e.isValid()||Nn(e).isValid())?mo({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function qCe(e){return this.to(Nn(),e)}function DN(e){var t;return e===void 0?this._locale._abbr:(t=_i(e),t!=null&&(this._locale=t),this)}var RN=Fa(\"moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.\",function(e){return e===void 0?this.localeData():this.locale(e)});function LN(){return this._locale}var Av=1e3,Mu=60*Av,Dv=60*Mu,FN=(365*400+97)*24*Dv;function Iu(e,t){return(e%t+t)%t}function BN(e,t,n){return e<100&&e>=0?new Date(e+400,t,n)-FN:new Date(e,t,n).valueOf()}function VN(e,t,n){return e<100&&e>=0?Date.UTC(e+400,t,n)-FN:Date.UTC(e,t,n)}function GCe(e){var t,n;if(e=Ba(e),e===void 0||e===\"millisecond\"||!this.isValid())return this;switch(n=this._isUTC?VN:BN,e){case\"year\":t=n(this.year(),0,1);break;case\"quarter\":t=n(this.year(),this.month()-this.month()%3,1);break;case\"month\":t=n(this.year(),this.month(),1);break;case\"week\":t=n(this.year(),this.month(),this.date()-this.weekday());break;case\"isoWeek\":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case\"day\":case\"date\":t=n(this.year(),this.month(),this.date());break;case\"hour\":t=this._d.valueOf(),t-=Iu(t+(this._isUTC?0:this.utcOffset()*Mu),Dv);break;case\"minute\":t=this._d.valueOf(),t-=Iu(t,Mu);break;case\"second\":t=this._d.valueOf(),t-=Iu(t,Av);break}return this._d.setTime(t),Ue.updateOffset(this,!0),this}function XCe(e){var t,n;if(e=Ba(e),e===void 0||e===\"millisecond\"||!this.isValid())return this;switch(n=this._isUTC?VN:BN,e){case\"year\":t=n(this.year()+1,0,1)-1;break;case\"quarter\":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case\"month\":t=n(this.year(),this.month()+1,1)-1;break;case\"week\":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case\"isoWeek\":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case\"day\":case\"date\":t=n(this.year(),this.month(),this.date()+1)-1;break;case\"hour\":t=this._d.valueOf(),t+=Dv-Iu(t+(this._isUTC?0:this.utcOffset()*Mu),Dv)-1;break;case\"minute\":t=this._d.valueOf(),t+=Mu-Iu(t,Mu)-1;break;case\"second\":t=this._d.valueOf(),t+=Av-Iu(t,Av)-1;break}return this._d.setTime(t),Ue.updateOffset(this,!0),this}function ZCe(){return this._d.valueOf()-(this._offset||0)*6e4}function JCe(){return Math.floor(this.valueOf()/1e3)}function QCe(){return new Date(this.valueOf())}function ewe(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function twe(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function nwe(){return this.isValid()?this.toISOString():null}function rwe(){return Mw(this)}function awe(){return Gi({},qt(this))}function owe(){return qt(this).overflow}function iwe(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}Tt(\"N\",0,0,\"eraAbbr\");Tt(\"NN\",0,0,\"eraAbbr\");Tt(\"NNN\",0,0,\"eraAbbr\");Tt(\"NNNN\",0,0,\"eraName\");Tt(\"NNNNN\",0,0,\"eraNarrow\");Tt(\"y\",[\"y\",1],\"yo\",\"eraYear\");Tt(\"y\",[\"yy\",2],0,\"eraYear\");Tt(\"y\",[\"yyy\",3],0,\"eraYear\");Tt(\"y\",[\"yyyy\",4],0,\"eraYear\");gt(\"N\",Yw);gt(\"NN\",Yw);gt(\"NNN\",Yw);gt(\"NNNN\",gwe);gt(\"NNNNN\",ywe);Cn([\"N\",\"NN\",\"NNN\",\"NNNN\",\"NNNNN\"],function(e,t,n,r){var a=n._locale.erasParse(e,r,n._strict);a?qt(n).era=a:qt(n).invalidEra=e});gt(\"y\",Ec);gt(\"yy\",Ec);gt(\"yyy\",Ec);gt(\"yyyy\",Ec);gt(\"yo\",bwe);Cn([\"y\",\"yy\",\"yyy\",\"yyyy\"],kr);Cn([\"yo\"],function(e,t,n,r){var a;n._locale._eraYearOrdinalRegex&&(a=e.match(n._locale._eraYearOrdinalRegex)),n._locale.eraYearOrdinalParse?t[kr]=n._locale.eraYearOrdinalParse(e,a):t[kr]=parseInt(e,10)});function lwe(e,t){var n,r,a,o=this._eras||_i(\"en\")._eras;for(n=0,r=o.length;n<r;++n){switch(typeof o[n].since){case\"string\":a=Ue(o[n].since).startOf(\"day\"),o[n].since=a.valueOf();break}switch(typeof o[n].until){case\"undefined\":o[n].until=1/0;break;case\"string\":a=Ue(o[n].until).startOf(\"day\").valueOf(),o[n].until=a.valueOf();break}}return o}function swe(e,t,n){var r,a,o=this.eras(),i,l,s;for(e=e.toUpperCase(),r=0,a=o.length;r<a;++r)if(i=o[r].name.toUpperCase(),l=o[r].abbr.toUpperCase(),s=o[r].narrow.toUpperCase(),n)switch(t){case\"N\":case\"NN\":case\"NNN\":if(l===e)return o[r];break;case\"NNNN\":if(i===e)return o[r];break;case\"NNNNN\":if(s===e)return o[r];break}else if([i,l,s].indexOf(e)>=0)return o[r]}function uwe(e,t){var n=e.since<=e.until?1:-1;return t===void 0?Ue(e.since).year():Ue(e.since).year()+(t-e.offset)*n}function cwe(){var e,t,n,r=this.localeData().eras();for(e=0,t=r.length;e<t;++e)if(n=this.clone().startOf(\"day\").valueOf(),r[e].since<=n&&n<=r[e].until||r[e].until<=n&&n<=r[e].since)return r[e].name;return\"\"}function dwe(){var e,t,n,r=this.localeData().eras();for(e=0,t=r.length;e<t;++e)if(n=this.clone().startOf(\"day\").valueOf(),r[e].since<=n&&n<=r[e].until||r[e].until<=n&&n<=r[e].since)return r[e].narrow;return\"\"}function fwe(){var e,t,n,r=this.localeData().eras();for(e=0,t=r.length;e<t;++e)if(n=this.clone().startOf(\"day\").valueOf(),r[e].since<=n&&n<=r[e].until||r[e].until<=n&&n<=r[e].since)return r[e].abbr;return\"\"}function hwe(){var e,t,n,r,a=this.localeData().eras();for(e=0,t=a.length;e<t;++e)if(n=a[e].since<=a[e].until?1:-1,r=this.clone().startOf(\"day\").valueOf(),a[e].since<=r&&r<=a[e].until||a[e].until<=r&&r<=a[e].since)return(this.year()-Ue(a[e].since).year())*n+a[e].offset;return this.year()}function pwe(e){return cn(this,\"_erasNameRegex\")||qw.call(this),e?this._erasNameRegex:this._erasRegex}function vwe(e){return cn(this,\"_erasAbbrRegex\")||qw.call(this),e?this._erasAbbrRegex:this._erasRegex}function mwe(e){return cn(this,\"_erasNarrowRegex\")||qw.call(this),e?this._erasNarrowRegex:this._erasRegex}function Yw(e,t){return t.erasAbbrRegex(e)}function gwe(e,t){return t.erasNameRegex(e)}function ywe(e,t){return t.erasNarrowRegex(e)}function bwe(e,t){return t._eraYearOrdinalRegex||Ec}function qw(){var e=[],t=[],n=[],r=[],a,o,i=this.eras();for(a=0,o=i.length;a<o;++a)t.push(aa(i[a].name)),e.push(aa(i[a].abbr)),n.push(aa(i[a].narrow)),r.push(aa(i[a].name)),r.push(aa(i[a].abbr)),r.push(aa(i[a].narrow));this._erasRegex=new RegExp(\"^(\"+r.join(\"|\")+\")\",\"i\"),this._erasNameRegex=new RegExp(\"^(\"+t.join(\"|\")+\")\",\"i\"),this._erasAbbrRegex=new RegExp(\"^(\"+e.join(\"|\")+\")\",\"i\"),this._erasNarrowRegex=new RegExp(\"^(\"+n.join(\"|\")+\")\",\"i\")}Tt(0,[\"gg\",2],0,function(){return this.weekYear()%100});Tt(0,[\"GG\",2],0,function(){return this.isoWeekYear()%100});function pg(e,t){Tt(0,[e,e.length],0,t)}pg(\"gggg\",\"weekYear\");pg(\"ggggg\",\"weekYear\");pg(\"GGGG\",\"isoWeekYear\");pg(\"GGGGG\",\"isoWeekYear\");Or(\"weekYear\",\"gg\");Or(\"isoWeekYear\",\"GG\");Pr(\"weekYear\",1);Pr(\"isoWeekYear\",1);gt(\"G\",ug);gt(\"g\",ug);gt(\"GG\",Dn,ya);gt(\"gg\",Dn,ya);gt(\"GGGG\",Lw,Rw);gt(\"gggg\",Lw,Rw);gt(\"GGGGG\",sg,ig);gt(\"ggggg\",sg,ig);Lf([\"gggg\",\"ggggg\",\"GGGG\",\"GGGGG\"],function(e,t,n,r){t[r.substr(0,2)]=Zt(e)});Lf([\"gg\",\"GG\"],function(e,t,n,r){t[r]=Ue.parseTwoDigitYear(e)});function Cwe(e){return zN.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function wwe(e){return zN.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)}function Swe(){return fi(this.year(),1,4)}function kwe(){return fi(this.isoWeekYear(),1,4)}function $we(){var e=this.localeData()._week;return fi(this.year(),e.dow,e.doy)}function Owe(){var e=this.localeData()._week;return fi(this.weekYear(),e.dow,e.doy)}function zN(e,t,n,r,a){var o;return e==null?of(this,r,a).year:(o=fi(e,r,a),t>o&&(t=o),Pwe.call(this,e,t,n,r,a))}function Pwe(e,t,n,r,a){var o=CN(e,t,n,r,a),i=af(o.year,0,o.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}Tt(\"Q\",0,\"Qo\",\"quarter\");Or(\"quarter\",\"Q\");Pr(\"quarter\",7);gt(\"Q\",cN);Cn(\"Q\",function(e,t){t[ii]=(Zt(e)-1)*3});function Twe(e){return e==null?Math.ceil((this.month()+1)/3):this.month((e-1)*3+this.month()%3)}Tt(\"D\",[\"DD\",2],\"Do\",\"date\");Or(\"date\",\"D\");Pr(\"date\",9);gt(\"D\",Dn);gt(\"DD\",Dn,ya);gt(\"Do\",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient});Cn([\"D\",\"DD\"],Oo);Cn(\"Do\",function(e,t){t[Oo]=Zt(e.match(Dn)[0])});var HN=_c(\"Date\",!0);Tt(\"DDD\",[\"DDDD\",3],\"DDDo\",\"dayOfYear\");Or(\"dayOfYear\",\"DDD\");Pr(\"dayOfYear\",4);gt(\"DDD\",lg);gt(\"DDDD\",dN);Cn([\"DDD\",\"DDDD\"],function(e,t,n){n._dayOfYear=Zt(e)});function xwe(e){var t=Math.round((this.clone().startOf(\"day\")-this.clone().startOf(\"year\"))/864e5)+1;return e==null?t:this.add(e-t,\"d\")}Tt(\"m\",[\"mm\",2],0,\"minute\");Or(\"minute\",\"m\");Pr(\"minute\",14);gt(\"m\",Dn);gt(\"mm\",Dn,ya);Cn([\"m\",\"mm\"],Ja);var _we=_c(\"Minutes\",!1);Tt(\"s\",[\"ss\",2],0,\"second\");Or(\"second\",\"s\");Pr(\"second\",15);gt(\"s\",Dn);gt(\"ss\",Dn,ya);Cn([\"s\",\"ss\"],li);var Ewe=_c(\"Seconds\",!1);Tt(\"S\",0,0,function(){return~~(this.millisecond()/100)});Tt(0,[\"SS\",2],0,function(){return~~(this.millisecond()/10)});Tt(0,[\"SSS\",3],0,\"millisecond\");Tt(0,[\"SSSS\",4],0,function(){return this.millisecond()*10});Tt(0,[\"SSSSS\",5],0,function(){return this.millisecond()*100});Tt(0,[\"SSSSSS\",6],0,function(){return this.millisecond()*1e3});Tt(0,[\"SSSSSSS\",7],0,function(){return this.millisecond()*1e4});Tt(0,[\"SSSSSSSS\",8],0,function(){return this.millisecond()*1e5});Tt(0,[\"SSSSSSSSS\",9],0,function(){return this.millisecond()*1e6});Or(\"millisecond\",\"ms\");Pr(\"millisecond\",16);gt(\"S\",lg,cN);gt(\"SS\",lg,ya);gt(\"SSS\",lg,dN);var Xi,jN;for(Xi=\"SSSS\";Xi.length<=9;Xi+=\"S\")gt(Xi,Ec);function Mwe(e,t){t[Xl]=Zt((\"0.\"+e)*1e3)}for(Xi=\"S\";Xi.length<=9;Xi+=\"S\")Cn(Xi,Mwe);jN=_c(\"Milliseconds\",!1);Tt(\"z\",0,0,\"zoneAbbr\");Tt(\"zz\",0,0,\"zoneName\");function Iwe(){return this._isUTC?\"UTC\":\"\"}function Nwe(){return this._isUTC?\"Coordinated Universal Time\":\"\"}var tt=Df.prototype;tt.add=OCe;tt.calendar=ICe;tt.clone=NCe;tt.diff=VCe;tt.endOf=XCe;tt.format=KCe;tt.from=WCe;tt.fromNow=UCe;tt.to=YCe;tt.toNow=qCe;tt.get=D0e;tt.invalidAt=owe;tt.isAfter=ACe;tt.isBefore=DCe;tt.isBetween=RCe;tt.isSame=LCe;tt.isSameOrAfter=FCe;tt.isSameOrBefore=BCe;tt.isValid=rwe;tt.lang=RN;tt.locale=DN;tt.localeData=LN;tt.max=rCe;tt.min=nCe;tt.parsingFlags=awe;tt.set=R0e;tt.startOf=GCe;tt.subtract=PCe;tt.toArray=ewe;tt.toObject=twe;tt.toDate=QCe;tt.toISOString=HCe;tt.inspect=jCe;typeof Symbol!=\"undefined\"&&Symbol.for!=null&&(tt[Symbol.for(\"nodejs.util.inspect.custom\")]=function(){return\"Moment<\"+this.format()+\">\"});tt.toJSON=nwe;tt.toString=zCe;tt.unix=JCe;tt.valueOf=ZCe;tt.creationData=iwe;tt.eraName=cwe;tt.eraNarrow=dwe;tt.eraAbbr=fwe;tt.eraYear=hwe;tt.year=bN;tt.isLeapYear=t1e;tt.weekYear=Cwe;tt.isoWeekYear=wwe;tt.quarter=tt.quarters=Twe;tt.month=gN;tt.daysInMonth=J0e;tt.week=tt.weeks=l1e;tt.isoWeek=tt.isoWeeks=s1e;tt.weeksInYear=$we;tt.weeksInWeekYear=Owe;tt.isoWeeksInYear=Swe;tt.isoWeeksInISOWeekYear=kwe;tt.date=HN;tt.day=tt.days=w1e;tt.weekday=S1e;tt.isoWeekday=k1e;tt.dayOfYear=xwe;tt.hour=tt.hours=E1e;tt.minute=tt.minutes=_we;tt.second=tt.seconds=Ewe;tt.millisecond=tt.milliseconds=jN;tt.utcOffset=fCe;tt.utc=pCe;tt.local=vCe;tt.parseZone=mCe;tt.hasAlignedHourOffset=gCe;tt.isDST=yCe;tt.isLocal=CCe;tt.isUtcOffset=wCe;tt.isUtc=MN;tt.isUTC=MN;tt.zoneAbbr=Iwe;tt.zoneName=Nwe;tt.dates=Fa(\"dates accessor is deprecated. Use date instead.\",HN);tt.months=Fa(\"months accessor is deprecated. Use month instead\",gN);tt.years=Fa(\"years accessor is deprecated. Use year instead\",bN);tt.zone=Fa(\"moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/\",hCe);tt.isDSTShifted=Fa(\"isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information\",bCe);function Awe(e){return Nn(e*1e3)}function Dwe(){return Nn.apply(null,arguments).parseZone()}function KN(e){return e}var dn=Nw.prototype;dn.calendar=w0e;dn.longDateFormat=O0e;dn.invalidDate=T0e;dn.ordinal=E0e;dn.preparse=KN;dn.postformat=KN;dn.relativeTime=I0e;dn.pastFuture=N0e;dn.set=b0e;dn.eras=lwe;dn.erasParse=swe;dn.erasConvertYear=uwe;dn.erasAbbrRegex=vwe;dn.erasNameRegex=pwe;dn.erasNarrowRegex=mwe;dn.months=q0e;dn.monthsShort=G0e;dn.monthsParse=Z0e;dn.monthsRegex=e1e;dn.monthsShortRegex=Q0e;dn.week=r1e;dn.firstDayOfYear=i1e;dn.firstDayOfWeek=o1e;dn.weekdays=m1e;dn.weekdaysMin=y1e;dn.weekdaysShort=g1e;dn.weekdaysParse=C1e;dn.weekdaysRegex=$1e;dn.weekdaysShortRegex=O1e;dn.weekdaysMinRegex=P1e;dn.isPM=x1e;dn.meridiem=M1e;function Rv(e,t,n,r){var a=_i(),o=Ho().set(r,t);return a[n](o,e)}function WN(e,t,n){if(Ci(e)&&(t=e,e=void 0),e=e||\"\",t!=null)return Rv(e,t,n,\"month\");var r,a=[];for(r=0;r<12;r++)a[r]=Rv(e,r,n,\"month\");return a}function Gw(e,t,n,r){typeof e==\"boolean\"?(Ci(t)&&(n=t,t=void 0),t=t||\"\"):(t=e,n=t,e=!1,Ci(t)&&(n=t,t=void 0),t=t||\"\");var a=_i(),o=e?a._week.dow:0,i,l=[];if(n!=null)return Rv(t,(n+o)%7,r,\"day\");for(i=0;i<7;i++)l[i]=Rv(t,(i+o)%7,r,\"day\");return l}function Rwe(e,t){return WN(e,t,\"months\")}function Lwe(e,t){return WN(e,t,\"monthsShort\")}function Fwe(e,t,n){return Gw(e,t,n,\"weekdays\")}function Bwe(e,t,n){return Gw(e,t,n,\"weekdaysShort\")}function Vwe(e,t,n){return Gw(e,t,n,\"weekdaysMin\")}nl(\"en\",{eras:[{since:\"0001-01-01\",until:1/0,offset:1,name:\"Anno Domini\",narrow:\"AD\",abbr:\"AD\"},{since:\"0000-12-31\",until:-1/0,offset:1,name:\"Before Christ\",narrow:\"BC\",abbr:\"BC\"}],dayOfMonthOrdinalParse:/\\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10,n=Zt(e%100/10)===1?\"th\":t===1?\"st\":t===2?\"nd\":t===3?\"rd\":\"th\";return e+n}});Ue.lang=Fa(\"moment.lang is deprecated. Use moment.locale instead.\",nl);Ue.langData=Fa(\"moment.langData is deprecated. Use moment.localeData instead.\",_i);var qo=Math.abs;function zwe(){var e=this._data;return this._milliseconds=qo(this._milliseconds),this._days=qo(this._days),this._months=qo(this._months),e.milliseconds=qo(e.milliseconds),e.seconds=qo(e.seconds),e.minutes=qo(e.minutes),e.hours=qo(e.hours),e.months=qo(e.months),e.years=qo(e.years),this}function UN(e,t,n,r){var a=mo(t,n);return e._milliseconds+=r*a._milliseconds,e._days+=r*a._days,e._months+=r*a._months,e._bubble()}function Hwe(e,t){return UN(this,e,t,1)}function jwe(e,t){return UN(this,e,t,-1)}function JO(e){return e<0?Math.floor(e):Math.ceil(e)}function Kwe(){var e=this._milliseconds,t=this._days,n=this._months,r=this._data,a,o,i,l,s;return e>=0&&t>=0&&n>=0||e<=0&&t<=0&&n<=0||(e+=JO(l1(n)+t)*864e5,t=0,n=0),r.milliseconds=e%1e3,a=Oa(e/1e3),r.seconds=a%60,o=Oa(a/60),r.minutes=o%60,i=Oa(o/60),r.hours=i%24,t+=Oa(i/24),s=Oa(YN(t)),n+=s,t-=JO(l1(s)),l=Oa(n/12),n%=12,r.days=t,r.months=n,r.years=l,this}function YN(e){return e*4800/146097}function l1(e){return e*146097/4800}function Wwe(e){if(!this.isValid())return NaN;var t,n,r=this._milliseconds;if(e=Ba(e),e===\"month\"||e===\"quarter\"||e===\"year\")switch(t=this._days+r/864e5,n=this._months+YN(t),e){case\"month\":return n;case\"quarter\":return n/3;case\"year\":return n/12}else switch(t=this._days+Math.round(l1(this._months)),e){case\"week\":return t/7+r/6048e5;case\"day\":return t+r/864e5;case\"hour\":return t*24+r/36e5;case\"minute\":return t*1440+r/6e4;case\"second\":return t*86400+r/1e3;case\"millisecond\":return Math.floor(t*864e5)+r;default:throw new Error(\"Unknown unit \"+e)}}function Uwe(){return this.isValid()?this._milliseconds+this._days*864e5+this._months%12*2592e6+Zt(this._months/12)*31536e6:NaN}function Ei(e){return function(){return this.as(e)}}var Ywe=Ei(\"ms\"),qwe=Ei(\"s\"),Gwe=Ei(\"m\"),Xwe=Ei(\"h\"),Zwe=Ei(\"d\"),Jwe=Ei(\"w\"),Qwe=Ei(\"M\"),e2e=Ei(\"Q\"),t2e=Ei(\"y\");function n2e(){return mo(this)}function r2e(e){return e=Ba(e),this.isValid()?this[e+\"s\"]():NaN}function Ds(e){return function(){return this.isValid()?this._data[e]:NaN}}var a2e=Ds(\"milliseconds\"),o2e=Ds(\"seconds\"),i2e=Ds(\"minutes\"),l2e=Ds(\"hours\"),s2e=Ds(\"days\"),u2e=Ds(\"months\"),c2e=Ds(\"years\");function d2e(){return Oa(this.days()/7)}var ti=Math.round,gu={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function f2e(e,t,n,r,a){return a.relativeTime(t||1,!!n,e,r)}function h2e(e,t,n,r){var a=mo(e).abs(),o=ti(a.as(\"s\")),i=ti(a.as(\"m\")),l=ti(a.as(\"h\")),s=ti(a.as(\"d\")),c=ti(a.as(\"M\")),d=ti(a.as(\"w\")),f=ti(a.as(\"y\")),p=o<=n.ss&&[\"s\",o]||o<n.s&&[\"ss\",o]||i<=1&&[\"m\"]||i<n.m&&[\"mm\",i]||l<=1&&[\"h\"]||l<n.h&&[\"hh\",l]||s<=1&&[\"d\"]||s<n.d&&[\"dd\",s];return n.w!=null&&(p=p||d<=1&&[\"w\"]||d<n.w&&[\"ww\",d]),p=p||c<=1&&[\"M\"]||c<n.M&&[\"MM\",c]||f<=1&&[\"y\"]||[\"yy\",f],p[2]=t,p[3]=+e>0,p[4]=r,f2e.apply(null,p)}function p2e(e){return e===void 0?ti:typeof e==\"function\"?(ti=e,!0):!1}function v2e(e,t){return gu[e]===void 0?!1:t===void 0?gu[e]:(gu[e]=t,e===\"s\"&&(gu.ss=t-1),!0)}function m2e(e,t){if(!this.isValid())return this.localeData().invalidDate();var n=!1,r=gu,a,o;return typeof e==\"object\"&&(t=e,e=!1),typeof e==\"boolean\"&&(n=e),typeof t==\"object\"&&(r=Object.assign({},gu,t),t.s!=null&&t.ss==null&&(r.ss=t.s-1)),a=this.localeData(),o=h2e(this,!n,r,a),n&&(o=a.pastFuture(+this,o)),a.postformat(o)}var Iy=Math.abs;function Hs(e){return(e>0)-(e<0)||+e}function vg(){if(!this.isValid())return this.localeData().invalidDate();var e=Iy(this._milliseconds)/1e3,t=Iy(this._days),n=Iy(this._months),r,a,o,i,l=this.asSeconds(),s,c,d,f;return l?(r=Oa(e/60),a=Oa(r/60),e%=60,r%=60,o=Oa(n/12),n%=12,i=e?e.toFixed(3).replace(/\\.?0+$/,\"\"):\"\",s=l<0?\"-\":\"\",c=Hs(this._months)!==Hs(l)?\"-\":\"\",d=Hs(this._days)!==Hs(l)?\"-\":\"\",f=Hs(this._milliseconds)!==Hs(l)?\"-\":\"\",s+\"P\"+(o?c+o+\"Y\":\"\")+(n?c+n+\"M\":\"\")+(t?d+t+\"D\":\"\")+(a||r||e?\"T\":\"\")+(a?f+a+\"H\":\"\")+(r?f+r+\"M\":\"\")+(e?f+i+\"S\":\"\")):\"P0D\"}var un=hg.prototype;un.isValid=sCe;un.abs=zwe;un.add=Hwe;un.subtract=jwe;un.as=Wwe;un.asMilliseconds=Ywe;un.asSeconds=qwe;un.asMinutes=Gwe;un.asHours=Xwe;un.asDays=Zwe;un.asWeeks=Jwe;un.asMonths=Qwe;un.asQuarters=e2e;un.asYears=t2e;un.valueOf=Uwe;un._bubble=Kwe;un.clone=n2e;un.get=r2e;un.milliseconds=a2e;un.seconds=o2e;un.minutes=i2e;un.hours=l2e;un.days=s2e;un.weeks=d2e;un.months=u2e;un.years=c2e;un.humanize=m2e;un.toISOString=vg;un.toString=vg;un.toJSON=vg;un.locale=DN;un.localeData=LN;un.toIsoString=Fa(\"toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)\",vg);un.lang=RN;Tt(\"X\",0,0,\"unix\");Tt(\"x\",0,0,\"valueOf\");gt(\"x\",ug);gt(\"X\",F0e);Cn(\"X\",function(e,t,n){n._d=new Date(parseFloat(e)*1e3)});Cn(\"x\",function(e,t,n){n._d=new Date(Zt(e))});//! moment.js\nUe.version=\"2.29.3\";g0e(Nn);Ue.fn=tt;Ue.min=aCe;Ue.max=oCe;Ue.now=iCe;Ue.utc=Ho;Ue.unix=Awe;Ue.months=Rwe;Ue.isDate=Af;Ue.locale=nl;Ue.invalid=ag;Ue.duration=mo;Ue.isMoment=uo;Ue.weekdays=Fwe;Ue.parseZone=Dwe;Ue.localeData=_i;Ue.isDuration=Rp;Ue.monthsShort=Lwe;Ue.weekdaysMin=Vwe;Ue.defineLocale=zw;Ue.updateLocale=D1e;Ue.locales=R1e;Ue.weekdaysShort=Bwe;Ue.normalizeUnits=Ba;Ue.relativeTimeRounding=p2e;Ue.relativeTimeThreshold=v2e;Ue.calendarFormat=MCe;Ue.prototype=tt;Ue.HTML5_FMT={DATETIME_LOCAL:\"YYYY-MM-DDTHH:mm\",DATETIME_LOCAL_SECONDS:\"YYYY-MM-DDTHH:mm:ss\",DATETIME_LOCAL_MS:\"YYYY-MM-DDTHH:mm:ss.SSS\",DATE:\"YYYY-MM-DD\",TIME:\"HH:mm\",TIME_SECONDS:\"HH:mm:ss\",TIME_MS:\"HH:mm:ss.SSS\",WEEK:\"GGGG-[W]WW\",MONTH:\"YYYY-MM\"};function Hr(e){return e.default||e}var Fp=P({},lo.Modal);function QO(e){e?Fp=P(P({},Fp),e):Fp=P({},lo.Modal)}function qN(){return Fp}var eP={};function g2e(e,t){}function y2e(e,t){}function GN(e,t,n){!t&&!eP[n]&&(e(!1,n),eP[n]=!0)}function Ua(e,t){GN(g2e,e,t)}function tP(e,t){GN(y2e,e,t)}var on=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:\"\";Ua(e,\"[antdv: \".concat(t,\"] \").concat(n))},s1=\"internalMark\";function b2e(e){e&&e.locale?Hr(Ue).locale(e.locale):Hr(Ue).locale(\"en\")}var Bp=G({name:\"ALocaleProvider\",props:{locale:{type:Object},ANT_MARK__:u.string},setup:function(t,n){var r=n.slots;on(t.ANT_MARK__===s1,\"LocaleProvider\",\"`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead\");var a=bt({antLocale:P(P({},t.locale),{exist:!0}),ANT_MARK__:s1});return ot(\"localeData\",a),ce(function(){return t.locale},function(o){a.antLocale=P(P({},o),{exist:!0}),b2e(o),QO(o&&o.Modal)},{immediate:!0}),Wr(function(){QO()}),function(){var o;return(o=r.default)===null||o===void 0?void 0:o.call(r)}}});Bp.install=function(e){return e.component(Bp.name,Bp),e};var XN=kn(Bp),C2e={getTargetContainer:{type:Function},getPopupContainer:{type:Function},prefixCls:String,getPrefixCls:{type:Function},renderEmpty:{type:Function},transformCellText:{type:Function},csp:{type:Object},autoInsertSpaceInButton:u.looseBool,locale:{type:Object},pageHeader:{type:Object},componentSize:{type:String},direction:{type:String},space:{type:Object},virtual:u.looseBool,dropdownMatchSelectWidth:u.looseBool,form:{type:Object}},w2e=G({name:\"AConfigProvider\",props:C2e,setup:function(t,n){var r=n.slots,a=function(d,f){var p=t.prefixCls,v=p===void 0?\"ant\":p;return f||(d?\"\".concat(v,\"-\").concat(d):v)},o=function(d){var f=t.renderEmpty||r.renderEmpty||nN;return f(d)},i=function(d,f){var p=t.prefixCls;if(f)return f;var v=p||a(\"\");return d?\"\".concat(v,\"-\").concat(d):v},l=bt(P(P({},t),{getPrefixCls:i,renderEmpty:o}));Object.keys(t).forEach(function(c){ce(function(){return t[c]},function(){l[c]=t[c]})}),ot(\"configProvider\",l);var s=function(d){var f;return g(XN,{locale:t.locale||d,ANT_MARK__:s1},{default:function(){return[(f=r.default)===null||f===void 0?void 0:f.call(r)]}})};return function(){return g(Kr,{children:function(d,f,p){return s(p)}},null)}}}),St=bt({getPrefixCls:function(t,n){return n||(t?\"ant-\".concat(t):\"ant\")},renderEmpty:nN,direction:\"ltr\"}),S2e=kn(w2e),Wt=function(e,t){var n=ve(\"configProvider\",St),r=x(function(){return n.getPrefixCls(e,t.prefixCls)}),a=x(function(){return n.direction}),o=x(function(){return n.autoInsertSpaceInButton}),i=x(function(){return n.renderEmpty}),l=x(function(){return n.space}),s=x(function(){return n.pageHeader}),c=x(function(){return n.form}),d=x(function(){return t.size||n.componentSize}),f=x(function(){return t.getTargetContainer});return{configProvider:n,prefixCls:r,direction:a,size:d,getTargetContainer:f,space:l,pageHeader:s,form:c,autoInsertSpaceInButton:o,renderEmpty:i}};function k2e(){return typeof window!=\"undefined\"?window:null}var yu;(function(e){e[e.None=0]=\"None\",e[e.Prepare=1]=\"Prepare\"})(yu||(yu={}));var $2e={offsetTop:u.number,offset:u.number,offsetBottom:u.number,target:u.func.def(k2e),prefixCls:u.string,onChange:u.func,onTestUpdatePosition:u.func},O2e=G({name:\"AAffix\",props:$2e,emits:[\"change\",\"testUpdatePosition\"],setup:function(t,n){var r=n.slots,a=n.emit,o=n.expose,i=H(),l=H(),s=bt({affixStyle:void 0,placeholderStyle:void 0,status:yu.None,lastAffix:!1,prevTarget:null,timeout:null}),c=$t(),d=x(function(){return t.offsetBottom===void 0&&t.offsetTop===void 0?0:t.offsetTop}),f=x(function(){return t.offsetBottom}),p=function(){var w=s.status,k=s.lastAffix,$=t.target;if(!(w!==yu.Prepare||!l.value||!i.value||!$)){var O=$();if(!!O){var T={status:yu.None},_=hh(O),I=hh(i.value),L=KO(I,_,d.value),j=WO(I,_,f.value);L!==void 0?(T.affixStyle={position:\"fixed\",top:L,width:I.width+\"px\",height:I.height+\"px\"},T.placeholderStyle={width:I.width+\"px\",height:I.height+\"px\"}):j!==void 0&&(T.affixStyle={position:\"fixed\",bottom:j,width:I.width+\"px\",height:I.height+\"px\"},T.placeholderStyle={width:I.width+\"px\",height:I.height+\"px\"}),T.lastAffix=!!T.affixStyle,k!==T.lastAffix&&a(\"change\",T.lastAffix),P(s,T)}}},v=function(){P(s,{status:yu.Prepare,affixStyle:void 0,placeholderStyle:void 0}),c.update()},m=e1(function(){v()}),y=e1(function(){var S=t.target,w=s.affixStyle;if(S&&w){var k=S();if(k&&i.value){var $=hh(k),O=hh(i.value),T=KO(O,$,d.value),_=WO(O,$,f.value);if(T!==void 0&&w.top===T||_!==void 0&&w.bottom===_)return}}v()});o({updatePosition:m,lazyUpdatePosition:y}),ce(function(){return t.target},function(S){var w=null;S&&(w=S()||null),s.prevTarget!==w&&(YO(c),w&&(UO(w,c),m()),s.prevTarget=w)}),ce(function(){return[t.offsetTop,t.offsetBottom]},m),et(function(){var S=t.target;S&&(s.timeout=setTimeout(function(){UO(S(),c),m()}))}),ur(function(){p()}),Wr(function(){clearTimeout(s.timeout),YO(c),m.cancel(),y.cancel()});var b=Wt(\"affix\",t),C=b.prefixCls;return function(){var S,w=s.affixStyle,k=s.placeholderStyle,$=Se(V({},C.value,w)),O=bn(t,[\"prefixCls\",\"offsetTop\",\"offsetBottom\",\"target\"]);return g(zo,{onResize:m},{default:function(){return[g(\"div\",le(le({},O),{},{style:k,ref:i}),[g(\"div\",{class:$,ref:l,style:w},[(S=r.default)===null||S===void 0?void 0:S.call(r)])])]}})}}}),ZN=kn(O2e),P2e=0,Nu={};function en(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1,n=P2e++,r=t;function a(){r-=1,r<=0?(e(),delete Nu[n]):Nu[n]=requestAnimationFrame(a)}return Nu[n]=requestAnimationFrame(a),n}en.cancel=function(t){t!==void 0&&(cancelAnimationFrame(Nu[t]),delete Nu[t])};en.ids=Nu;function u1(e){return e!=null&&e===e.window}function Xw(e,t){var n;if(typeof window==\"undefined\")return 0;var r=t?\"scrollTop\":\"scrollLeft\",a=0;return u1(e)?a=e[t?\"pageYOffset\":\"pageXOffset\"]:e instanceof Document?a=e.documentElement[r]:e&&(a=e[r]),e&&!u1(e)&&typeof a!=\"number\"&&(a=(n=(e.ownerDocument||e).documentElement)===null||n===void 0?void 0:n[r]),a}function T2e(e,t,n,r){var a=n-t;return e/=r/2,e<1?a/2*e*e*e+t:a/2*((e-=2)*e*e+2)+t}function Zw(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.getContainer,r=n===void 0?function(){return window}:n,a=t.callback,o=t.duration,i=o===void 0?450:o,l=r(),s=Xw(l,!0),c=Date.now(),d=function f(){var p=Date.now(),v=p-c,m=T2e(v>i?i:v,s,e,i);u1(l)?l.scrollTo(window.pageXOffset,m):l instanceof HTMLDocument||l.constructor.name===\"HTMLDocument\"?l.documentElement.scrollTop=m:l.scrollTop=m,v<i?en(f):typeof a==\"function\"&&a()};en(d)}function mh(){}var JN=Symbol(\"anchorContextKey\"),x2e=function(t){ot(JN,t)},_2e=function(){return ve(JN,{registerLink:mh,unregisterLink:mh,scrollTo:mh,activeLink:x(function(){return\"\"}),handleClick:mh})};function QN(){return window}function nP(e,t){if(!e.getClientRects().length)return 0;var n=e.getBoundingClientRect();return n.width||n.height?t===window?(t=e.ownerDocument.documentElement,n.top-t.clientTop):n.top-t.getBoundingClientRect().top:n.top}var rP=/#(\\S+)$/,E2e={prefixCls:u.string,offsetTop:u.number,bounds:u.number,affix:u.looseBool.def(!0),showInkInFixed:u.looseBool.def(!1),getContainer:u.func.def(QN),wrapperClass:u.string,wrapperStyle:u.style,getCurrentAnchor:u.func,targetOffset:u.number,onChange:u.func,onClick:u.func},Bl=G({name:\"AAnchor\",inheritAttrs:!1,props:E2e,emits:[\"change\",\"click\"],setup:function(t,n){var r=n.emit,a=n.attrs,o=n.slots,i=n.expose,l=Wt(\"anchor\",t),s=l.prefixCls,c=l.getTargetContainer,d=l.direction,f=H(),p=H(),v=bt({links:[],scrollContainer:null,scrollEvent:null,animating:!1}),m=H(null),y=x(function(){var $=t.getContainer;return $||c.value||QN}),b=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:0,T=arguments.length>1&&arguments[1]!==void 0?arguments[1]:5,_=[],I=y.value();if(v.links.forEach(function(j){var F=rP.exec(j.toString());if(!!F){var N=document.getElementById(F[1]);if(N){var D=nP(N,I);D<O+T&&_.push({link:j,top:D})}}}),_.length){var L=_.reduce(function(j,F){return F.top>j.top?F:j});return L.link}return\"\"},C=function(O){var T=t.getCurrentAnchor;m.value!==O&&(m.value=typeof T==\"function\"?T():O,r(\"change\",O))},S=function(O){var T=t.offsetTop,_=t.getContainer,I=t.targetOffset;C(O);var L=_(),j=Xw(L,!0),F=rP.exec(O);if(!!F){var N=document.getElementById(F[1]);if(!!N){var D=nP(N,L),z=j+D;z-=I!==void 0?I:T||0,v.animating=!0,Zw(z,{callback:function(){v.animating=!1},getContainer:_})}}};i({scrollTo:S});var w=function(){if(!v.animating){var O=t.offsetTop,T=t.bounds,_=t.targetOffset,I=b(_!==void 0?_:O||0,T);C(I)}},k=function(){var O=p.value.getElementsByClassName(\"\".concat(s.value,\"-link-title-active\"))[0];O&&(f.value.style.top=\"\".concat(O.offsetTop+O.clientHeight/2-4.5,\"px\"))};return x2e({registerLink:function(O){v.links.includes(O)||v.links.push(O)},unregisterLink:function(O){var T=v.links.indexOf(O);T!==-1&&v.links.splice(T,1)},activeLink:m,scrollTo:S,handleClick:function(O,T){r(\"click\",O,T)}}),et(function(){Ne(function(){var $=y.value();v.scrollContainer=$,v.scrollEvent=Kn(v.scrollContainer,\"scroll\",w),w()})}),Lt(function(){v.scrollEvent&&v.scrollEvent.remove()}),ur(function(){if(v.scrollEvent){var $=y.value();v.scrollContainer!==$&&(v.scrollContainer=$,v.scrollEvent.remove(),v.scrollEvent=Kn(v.scrollContainer,\"scroll\",w),w())}k()}),function(){var $,O=t.offsetTop,T=t.affix,_=t.showInkInFixed,I=s.value,L=Se(\"\".concat(I,\"-ink-ball\"),{visible:m.value}),j=Se(t.wrapperClass,\"\".concat(I,\"-wrapper\"),V({},\"\".concat(I,\"-rtl\"),d.value===\"rtl\")),F=Se(I,{fixed:!T&&!_}),N=P({maxHeight:O?\"calc(100vh - \".concat(O,\"px)\"):\"100vh\"},t.wrapperStyle),D=g(\"div\",{class:j,style:N,ref:p},[g(\"div\",{class:F},[g(\"div\",{class:\"\".concat(I,\"-ink\")},[g(\"span\",{class:L,ref:f},null)]),($=o.default)===null||$===void 0?void 0:$.call(o)])]);return T?g(ZN,le(le({},a),{},{offsetTop:O,target:y.value}),{default:function(){return[D]}}):D}}}),M2e={prefixCls:u.string,href:u.string.def(\"#\"),title:u.VNodeChild,target:u.string},eA=G({name:\"AAnchorLink\",props:M2e,slots:[\"title\"],setup:function(t,n){var r=n.slots,a=null,o=_2e(),i=o.handleClick,l=o.scrollTo,s=o.unregisterLink,c=o.registerLink,d=o.activeLink,f=Wt(\"anchor\",t),p=f.prefixCls,v=function(y){var b=t.href;i(y,{title:a,href:b}),l(b)};return ce(function(){return t.href},function(m,y){Ne(function(){s(y),c(m)})}),et(function(){c(t.href)}),Lt(function(){s(t.href)}),function(){var m,y=t.href,b=t.target,C=p.value,S=jn(r,t,\"title\");a=S;var w=d.value===y,k=Se(\"\".concat(C,\"-link\"),V({},\"\".concat(C,\"-link-active\"),w)),$=Se(\"\".concat(C,\"-link-title\"),V({},\"\".concat(C,\"-link-title-active\"),w));return g(\"div\",{class:k},[g(\"a\",{class:$,href:y,title:typeof S==\"string\"?S:\"\",target:b,onClick:v},[S]),(m=r.default)===null||m===void 0?void 0:m.call(r)])}}});Bl.Link=eA;Bl.install=function(e){return e.component(Bl.name,Bl),e.component(Bl.Link.name,Bl.Link),e};var mg=function(t,n){var r=n.slots,a,o=t.class,i=t.customizeIcon,l=t.customizeIconProps,s=t.onMousedown,c=t.onClick,d;return typeof i==\"function\"?d=i(l):d=i,g(\"span\",{class:o,onMousedown:function(p){p.preventDefault(),s&&s(p)},style:{userSelect:\"none\",WebkitUserSelect:\"none\"},unselectable:\"on\",onClick:c,\"aria-hidden\":!0},[d!==void 0?d:g(\"span\",{class:o.split(/\\s+/).map(function(f){return\"\".concat(f,\"-icon\")})},[(a=r.default)===null||a===void 0?void 0:a.call(r)])])};mg.inheritAttrs=!1;mg.displayName=\"TransBtn\";mg.props={class:u.string,customizeIcon:u.any,customizeIconProps:u.any,onMousedown:u.func,onClick:u.func};var Lv=mg,At={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(t){var n=t.keyCode;if(t.altKey&&!t.ctrlKey||t.metaKey||n>=At.F1&&n<=At.F12)return!1;switch(n){case At.ALT:case At.CAPS_LOCK:case At.CONTEXT_MENU:case At.CTRL:case At.DOWN:case At.END:case At.ESC:case At.HOME:case At.INSERT:case At.LEFT:case At.MAC_FF_META:case At.META:case At.NUMLOCK:case At.NUM_CENTER:case At.PAGE_DOWN:case At.PAGE_UP:case At.PAUSE:case At.PRINT_SCREEN:case At.RIGHT:case At.SHIFT:case At.UP:case At.WIN_KEY:case At.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(t){if(t>=At.ZERO&&t<=At.NINE||t>=At.NUM_ZERO&&t<=At.NUM_MULTIPLY||t>=At.A&&t<=At.Z||window.navigator.userAgent.indexOf(\"WebKit\")!==-1&&t===0)return!0;switch(t){case At.SPACE:case At.QUESTION_MARK:case At.NUM_PLUS:case At.NUM_MINUS:case At.NUM_PERIOD:case At.NUM_DIVISION:case At.SEMICOLON:case At.DASH:case At.EQUALS:case At.COMMA:case At.PERIOD:case At.SLASH:case At.APOSTROPHE:case At.SINGLE_QUOTE:case At.OPEN_SQUARE_BRACKET:case At.BACKSLASH:case At.CLOSE_SQUARE_BRACKET:return!0;default:return!1}}},ze=At,I2e=`accept acceptcharset accesskey action allowfullscreen allowtransparency\nalt async autocomplete autofocus autoplay capture cellpadding cellspacing challenge\ncharset checked classid classname colspan cols content contenteditable contextmenu\ncontrols coords crossorigin data datetime default defer dir disabled download draggable\nenctype form formaction formenctype formmethod formnovalidate formtarget frameborder\nheaders height hidden high href hreflang htmlfor httpequiv icon id inputmode integrity\nis keyparams keytype kind label lang list loop low manifest marginheight marginwidth max maxlength media\nmediagroup method min minlength multiple muted name novalidate nonce open\noptimum pattern placeholder poster preload radiogroup readonly rel required\nreversed role rowspan rows sandbox scope scoped scrolling seamless selected\nshape size sizes span spellcheck src srcdoc srclang srcset start step style\nsummary tabindex target title type usemap value width wmode wrap`,N2e=`onCopy onCut onPaste onCompositionend onCompositionstart onCompositionupdate onKeydown\n    onKeypress onKeyup onFocus onBlur onChange onInput onSubmit onClick onContextmenu onDoubleclick onDblclick\n    onDrag onDragend onDragenter onDragexit onDragleave onDragover onDragstart onDrop onMousedown\n    onMouseenter onMouseleave onMousemove onMouseout onMouseover onMouseup onSelect onTouchcancel\n    onTouchend onTouchmove onTouchstart onTouchstartPassive onTouchmovePassive onScroll onWheel onAbort onCanplay onCanplaythrough\n    onDurationchange onEmptied onEncrypted onEnded onError onLoadeddata onLoadedmetadata\n    onLoadstart onPause onPlay onPlaying onProgress onRatechange onSeeked onSeeking onStalled onSuspend onTimeupdate onVolumechange onWaiting onLoad onError`,aP=\"\".concat(I2e,\" \").concat(N2e).split(/[\\s\\n]+/),A2e=\"aria-\",D2e=\"data-\";function oP(e,t){return e.indexOf(t)===0}function Jw(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n;t===!1?n={aria:!0,data:!0,attr:!0}:t===!0?n={aria:!0}:n=P({},t);var r={};return Object.keys(e).forEach(function(a){(n.aria&&(a===\"role\"||oP(a,A2e))||n.data&&oP(a,D2e)||n.attr&&(aP.includes(a)||aP.includes(a.toLowerCase())))&&(r[a]=e[a])}),r}function ic(){var e=function t(n){t.current=n};return e}var gg=function(t,n){var r=t.height,a=t.offset,o=t.prefixCls,i=t.onInnerResize,l=n.slots,s,c={},d={display:\"flex\",flexDirection:\"column\"};return a!==void 0&&(c={height:\"\".concat(r,\"px\"),position:\"relative\",overflow:\"hidden\"},d=P(P({},d),{transform:\"translateY(\".concat(a,\"px)\"),position:\"absolute\",left:0,right:0,top:0})),g(\"div\",{style:c},[g(zo,{onResize:function(p){var v=p.offsetHeight;v&&i&&i()}},{default:function(){return[g(\"div\",{style:d,class:Se(V({},\"\".concat(o,\"-holder-inner\"),o))},[(s=l.default)===null||s===void 0?void 0:s.call(l)])]}})])};gg.displayName=\"Filter\";gg.inheritAttrs=!1;gg.props={prefixCls:String,height:Number,offset:Number,onInnerResize:Function};var R2e=gg,tA=function(t,n){var r=t.setRef,a=n.slots,o,i=(o=a.default)===null||o===void 0?void 0:o.call(a);return i&&i.length?hr(i[0],{ref:r}):i};tA.props={setRef:{type:Function,default:function(){}}};var L2e=tA,F2e=20;function iP(e){return\"touches\"in e?e.touches[0].pageY:e.pageY}var B2e=G({name:\"ScrollBar\",inheritAttrs:!1,props:{prefixCls:u.string,scrollTop:u.number,scrollHeight:u.number,height:u.number,count:u.number,onScroll:{type:Function},onStartMove:{type:Function},onStopMove:{type:Function}},setup:function(){return{moveRaf:null,scrollbarRef:ic(),thumbRef:ic(),visibleTimeout:null,state:bt({dragging:!1,pageY:null,startTop:null,visible:!1})}},watch:{scrollTop:{handler:function(){this.delayHidden()},flush:\"post\"}},mounted:function(){this.scrollbarRef.current.addEventListener(\"touchstart\",this.onScrollbarTouchStart,mn?{passive:!1}:!1),this.thumbRef.current.addEventListener(\"touchstart\",this.onMouseDown,mn?{passive:!1}:!1)},beforeUnmount:function(){this.removeEvents(),clearTimeout(this.visibleTimeout)},methods:{delayHidden:function(){var t=this;clearTimeout(this.visibleTimeout),this.state.visible=!0,this.visibleTimeout=setTimeout(function(){t.state.visible=!1},2e3)},onScrollbarTouchStart:function(t){t.preventDefault()},onContainerMouseDown:function(t){t.stopPropagation(),t.preventDefault()},patchEvents:function(){window.addEventListener(\"mousemove\",this.onMouseMove),window.addEventListener(\"mouseup\",this.onMouseUp),this.thumbRef.current.addEventListener(\"touchmove\",this.onMouseMove,mn?{passive:!1}:!1),this.thumbRef.current.addEventListener(\"touchend\",this.onMouseUp)},removeEvents:function(){window.removeEventListener(\"mousemove\",this.onMouseMove),window.removeEventListener(\"mouseup\",this.onMouseUp),this.scrollbarRef.current.removeEventListener(\"touchstart\",this.onScrollbarTouchStart,mn?{passive:!1}:!1),this.thumbRef.current.removeEventListener(\"touchstart\",this.onMouseDown,mn?{passive:!1}:!1),this.thumbRef.current.removeEventListener(\"touchmove\",this.onMouseMove,mn?{passive:!1}:!1),this.thumbRef.current.removeEventListener(\"touchend\",this.onMouseUp),en.cancel(this.moveRaf)},onMouseDown:function(t){var n=this.$props.onStartMove;P(this.state,{dragging:!0,pageY:iP(t),startTop:this.getTop()}),n(),this.patchEvents(),t.stopPropagation(),t.preventDefault()},onMouseMove:function(t){var n=this.state,r=n.dragging,a=n.pageY,o=n.startTop,i=this.$props.onScroll;if(en.cancel(this.moveRaf),r){var l=iP(t)-a,s=o+l,c=this.getEnableScrollRange(),d=this.getEnableHeightRange(),f=d?s/d:0,p=Math.ceil(f*c);this.moveRaf=en(function(){i(p)})}},onMouseUp:function(){var t=this.$props.onStopMove;this.state.dragging=!1,t(),this.removeEvents()},getSpinHeight:function(){var t=this.$props,n=t.height,r=t.count,a=n/r*10;return a=Math.max(a,F2e),a=Math.min(a,n/2),Math.floor(a)},getEnableScrollRange:function(){var t=this.$props,n=t.scrollHeight,r=t.height;return n-r||0},getEnableHeightRange:function(){var t=this.$props.height,n=this.getSpinHeight();return t-n||0},getTop:function(){var t=this.$props.scrollTop,n=this.getEnableScrollRange(),r=this.getEnableHeightRange();if(t===0||n===0)return 0;var a=t/n;return a*r},showScroll:function(){var t=this.$props,n=t.height,r=t.scrollHeight;return r>n}},render:function(){var t=this.state,n=t.dragging,r=t.visible,a=this.$props.prefixCls,o=this.getSpinHeight()+\"px\",i=this.getTop()+\"px\",l=this.showScroll(),s=l&&r;return g(\"div\",{ref:this.scrollbarRef,class:Se(\"\".concat(a,\"-scrollbar\"),V({},\"\".concat(a,\"-scrollbar-show\"),l)),style:{width:\"8px\",top:0,bottom:0,right:0,position:\"absolute\",display:s?void 0:\"none\"},onMousedown:this.onContainerMouseDown,onMousemove:this.delayHidden},[g(\"div\",{ref:this.thumbRef,class:Se(\"\".concat(a,\"-scrollbar-thumb\"),V({},\"\".concat(a,\"-scrollbar-thumb-moving\"),n)),style:{width:\"100%\",height:o,top:i,left:0,position:\"absolute\",background:\"rgba(0, 0, 0, 0.5)\",borderRadius:\"99px\",cursor:\"pointer\",userSelect:\"none\"},onMousedown:this.onMouseDown},null)])}});function V2e(e,t,n){var r=new Map,a=bt({}),o=0;function i(){o+=1;var s=o;Promise.resolve().then(function(){s===o&&r.forEach(function(c,d){if(c&&c.offsetParent){var f=c.offsetHeight;a[d]!==f&&(a[d]=c.offsetHeight)}})})}function l(s,c){var d=e(s),f=r.get(d);c?(r.set(d,c),i()):r.delete(d),!f!=!c&&(c?t==null||t(s):n==null||n(s))}return[l,i,a]}function z2e(e,t,n,r,a,o,i,l){var s=null;return function(c){if(c==null){l();return}en.cancel(s);var d=t.value,f=r.itemHeight;if(typeof c==\"number\")i(c);else if(c&&kt(c)===\"object\"){var p,v=c.align;\"index\"in c?p=c.index:p=d.findIndex(function(C){return a(C)===c.key});var m=c.offset,y=m===void 0?0:m,b=function C(S,w){if(!(S<0||!e.value)){var k=e.value.clientHeight,$=!1,O=w;if(k){for(var T=w||v,_=0,I=0,L=0,j=Math.min(d.length,p),F=0;F<=j;F+=1){var N=a(d[F]);I=_;var D=n[N];L=I+(D===void 0?f:D),_=L,F===p&&D===void 0&&($=!0)}var z=null;switch(T){case\"top\":z=I-y;break;case\"bottom\":z=L-k+y;break;default:{var B=e.value.scrollTop,M=B+k;I<B?O=\"top\":L>M&&(O=\"bottom\")}}z!==null&&z!==e.value.scrollTop&&i(z)}s=en(function(){$&&o(),C(S-1,O)})}};b(3)}}}var H2e=(typeof navigator==\"undefined\"?\"undefined\":kt(navigator))===\"object\"&&/Firefox/i.test(navigator.userAgent),j2e=H2e,nA=function(e,t){var n=!1,r=null;function a(){clearTimeout(r),n=!0,r=setTimeout(function(){n=!1},50)}return function(o){var i=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,l=o<0&&e.value||o>0&&t.value;return i&&l?(clearTimeout(r),n=!1):(!l||n)&&a(),!n&&l}};function K2e(e,t,n,r){var a=0,o=null,i=null,l=!1,s=nA(t,n);function c(f){if(!!e.value){en.cancel(o);var p=f.deltaY;a+=p,i=p,!s(p)&&(j2e||f.preventDefault(),o=en(function(){var v=l?10:1;r(a*v),a=0}))}}function d(f){!e.value||(l=f.detail===i)}return[c,d]}var W2e=14/15;function U2e(e,t,n){var r=!1,a=0,o=null,i=null,l=function(){o&&(o.removeEventListener(\"touchmove\",s,mn?{passive:!1}:!1),o.removeEventListener(\"touchend\",c))},s=function(p){if(r){var v=Math.ceil(p.touches[0].pageY),m=a-v;a=v,n(m)&&p.preventDefault(),clearInterval(i),i=setInterval(function(){m*=W2e,(!n(m,!0)||Math.abs(m)<=.1)&&clearInterval(i)},16)}},c=function(){r=!1,l()},d=function(p){l(),p.touches.length===1&&!r&&(r=!0,a=Math.ceil(p.touches[0].pageY),o=p.target,o.addEventListener(\"touchmove\",s,mn?{passive:!1}:!1),o.addEventListener(\"touchend\",c))};et(function(){ce(e,function(f){t.value.removeEventListener(\"touchstart\",d,mn?{passive:!1}:!1),l(),clearInterval(i),f&&t.value.addEventListener(\"touchstart\",d,mn?{passive:!1}:!1)},{immediate:!0})})}var Y2e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},q2e=[],G2e={overflowY:\"auto\",overflowAnchor:\"none\"};function X2e(e,t,n,r,a,o){var i=o.getKey;return e.slice(t,n+1).map(function(l,s){var c=t+s,d=a(l,c,{}),f=i(l);return g(L2e,{key:f,setRef:function(v){return r(l,v)}},{default:function(){return[d]}})})}var Z2e=G({name:\"List\",inheritAttrs:!1,props:{prefixCls:u.string,data:u.array,height:u.number,itemHeight:u.number,fullHeight:u.looseBool,itemKey:{type:[String,Number,Function],required:!0},component:{type:[String,Object]},virtual:u.looseBool,children:u.func,onScroll:u.func,onMousedown:u.func,onMouseenter:u.func},setup:function(t){var n=x(function(){var M=t.height,E=t.itemHeight,K=t.virtual;return!!(K!==!1&&M&&E)}),r=x(function(){var M=t.height,E=t.itemHeight,K=t.data;return n.value&&K&&E*K.length>M}),a=bt({scrollTop:0,scrollMoving:!1}),o=x(function(){return t.data||q2e}),i=H(),l=H(),s=H(),c=function(E){return typeof t.itemKey==\"function\"?t.itemKey(E):E==null?void 0:E[t.itemKey]},d={getKey:c};function f(M){var E;typeof M==\"function\"?E=M(a.scrollTop):E=M;var K=w(E);i.value&&(i.value.scrollTop=K),a.scrollTop=K}var p=V2e(c,null,null),v=fn(p,3),m=v[0],y=v[1],b=v[2],C=H({});ce([r,n,function(){return a.scrollTop},o,b,function(){return t.height}],function(){Ne(function(){var M;if(!n.value){C.value={scrollHeight:void 0,start:0,end:o.value.length-1,offset:void 0};return}if(!r.value){C.value={scrollHeight:((M=l.value)===null||M===void 0?void 0:M.offsetHeight)||0,start:0,end:o.value.length-1,offset:void 0};return}for(var E=0,K,W,Y,q=o.value.length,J=o.value,ne=0;ne<q;ne+=1){var oe=J[ne],Q=c(oe),ae=b[Q],de=E+(ae===void 0?t.itemHeight:ae);de>=a.scrollTop&&K===void 0&&(K=ne,W=E),de>a.scrollTop+t.height&&Y===void 0&&(Y=ne),E=de}K===void 0&&(K=0,W=0),Y===void 0&&(Y=q-1),Y=Math.min(Y+1,q),C.value={scrollHeight:E,start:K,end:Y,offset:W}})},{immediate:!0,flush:\"post\"});var S=x(function(){return C.value.scrollHeight-t.height});function w(M){var E=M;return Number.isNaN(S.value)||(E=Math.min(E,S.value)),E=Math.max(E,0),E}var k=x(function(){return a.scrollTop<=0}),$=x(function(){return a.scrollTop>=S.value}),O=nA(k,$);function T(M){var E=M;f(E)}function _(M){var E,K=M.currentTarget.scrollTop;Math.abs(K-a.scrollTop)>=1&&f(K),(E=t.onScroll)===null||E===void 0||E.call(t,M)}var I=K2e(n,k,$,function(M){f(function(E){var K=E+M;return K})}),L=fn(I,2),j=L[0],F=L[1];U2e(n,i,function(M,E){return O(M,E)?!1:(j({preventDefault:function(){},deltaY:M}),!0)});function N(M){n.value&&M.preventDefault()}var D=function(){i.value&&(i.value.removeEventListener(\"wheel\",j,mn?{passive:!1}:!1),i.value.removeEventListener(\"DOMMouseScroll\",F),i.value.removeEventListener(\"MozMousePixelScroll\",N))};Wn(function(){Ne(function(){i.value&&(D(),i.value.addEventListener(\"wheel\",j,mn?{passive:!1}:!1),i.value.addEventListener(\"DOMMouseScroll\",F),i.value.addEventListener(\"MozMousePixelScroll\",N))})}),Lt(function(){D()});var z=z2e(i,o,b,t,c,y,f,function(){var M;(M=s.value)===null||M===void 0||M.delayHidden()}),B=x(function(){var M=null;return t.height&&(M=P(V({},t.fullHeight?\"height\":\"maxHeight\",t.height+\"px\"),G2e),n.value&&(M.overflowY=\"hidden\",a.scrollMoving&&(M.pointerEvents=\"none\"))),M});return{state:a,mergedData:o,componentStyle:B,scrollTo:z,onFallbackScroll:_,onScrollBar:T,componentRef:i,useVirtual:n,calRes:C,collectHeight:y,setInstance:m,sharedConfig:d,scrollBarRef:s,fillerInnerRef:l}},render:function(){var t=this,n=P(P({},this.$props),this.$attrs),r=n.prefixCls,a=r===void 0?\"rc-virtual-list\":r,o=n.height;n.itemHeight,n.fullHeight,n.data,n.itemKey,n.virtual;var i=n.component,l=i===void 0?\"div\":i;n.onScroll;var s=n.children,c=n.style,d=n.class,f=Y2e(n,[\"prefixCls\",\"height\",\"itemHeight\",\"fullHeight\",\"data\",\"itemKey\",\"virtual\",\"component\",\"onScroll\",\"children\",\"style\",\"class\"]),p=Se(a,d),v=this.state.scrollTop,m=this.calRes,y=m.scrollHeight,b=m.offset,C=m.start,S=m.end,w=this.componentStyle,k=this.onFallbackScroll,$=this.onScrollBar,O=this.useVirtual,T=this.collectHeight,_=this.sharedConfig,I=this.setInstance,L=this.mergedData,j=X2e(L,C,S,I,s,_);return g(\"div\",le({style:P(P({},c),{position:\"relative\"}),class:p},f),[g(l,{class:\"\".concat(a,\"-holder\"),style:w,ref:\"componentRef\",onScroll:k},{default:function(){return[g(R2e,{prefixCls:a,height:y,offset:b,onInnerResize:T,ref:\"fillerInnerRef\"},{default:function(){return[j]}})]}}),O&&g(B2e,{ref:\"scrollBarRef\",prefixCls:a,scrollTop:v,height:o,scrollHeight:y,count:L.length,onScroll:$,onStartMove:function(){t.state.scrollMoving=!0},onStopMove:function(){t.state.scrollMoving=!1}},null)])}}),J2e=Z2e;function Q2e(e,t,n){var r=H(e());return ce(t,function(a,o){n?n(a,o)&&(r.value=e()):r.value=e()}),r}var eSe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},tSe={prefixCls:u.string,id:u.string,options:u.array,flattenOptions:u.array,height:u.number,itemHeight:u.number,values:u.any,multiple:u.looseBool,open:u.looseBool,defaultActiveFirstOption:u.looseBool,notFoundContent:u.any,menuItemSelectedIcon:u.any,childrenAsData:u.looseBool,searchValue:u.string,virtual:u.looseBool,onSelect:u.func,onToggleOpen:{type:Function},onActiveValue:u.func,onScroll:u.func,onMouseenter:u.func},rA=G({name:\"OptionList\",inheritAttrs:!1,slots:[\"option\"],setup:function(t){var n=x(function(){return\"\".concat(t.prefixCls,\"-item\")}),r=Q2e(function(){return t.flattenOptions},[function(){return t.open},function(){return t.flattenOptions}],function(p){return p[0]}),a=ic(),o=function(v){v.preventDefault()},i=function(v){a.current&&a.current.scrollTo({index:v})},l=function(v){for(var m=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1,y=r.value.length,b=0;b<y;b+=1){var C=(v+b*m+y)%y,S=r.value[C],w=S.group,k=S.data;if(!w&&!k.disabled)return C}return-1},s=bt({activeIndex:l(0)}),c=function(v){var m=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;s.activeIndex=v;var y={source:m?\"keyboard\":\"mouse\"},b=r.value[v];if(!b){t.onActiveValue(null,-1,y);return}t.onActiveValue(b.data.value,v,y)};ce([function(){return r.value.length},function(){return t.searchValue}],function(){c(t.defaultActiveFirstOption!==!1?l(0):-1)},{immediate:!0}),ce(function(){return t.open},function(){if(!t.multiple&&t.open&&t.values.size===1){var p=Array.from(t.values)[0],v=r.value.findIndex(function(m){var y=m.data;return y.value===p});c(v),Ne(function(){i(v)})}t.open&&Ne(function(){var m;(m=a.current)===null||m===void 0||m.scrollTo(void 0)})},{immediate:!0,flush:\"post\"});var d=function(v){v!==void 0&&t.onSelect(v,{selected:!t.values.has(v)}),t.multiple||t.onToggleOpen(!1)};function f(p){var v=r.value[p];if(!v)return null;var m=v.data||{},y=m.value,b=m.label,C=m.children,S=Jw(m,!0),w=t.childrenAsData?C:b;return v?g(\"div\",le(le({\"aria-label\":typeof w==\"string\"?w:void 0},S),{},{key:p,role:\"option\",id:\"\".concat(t.id,\"_list_\").concat(p),\"aria-selected\":t.values.has(y)}),[y]):null}return{memoFlattenOptions:r,renderItem:f,listRef:a,state:s,onListMouseDown:o,itemPrefixCls:n,setActive:c,onSelectValue:d,onKeydown:function(v){var m=v.which;switch(m){case ze.UP:case ze.DOWN:{var y=0;if(m===ze.UP?y=-1:m===ze.DOWN&&(y=1),y!==0){var b=l(s.activeIndex+y,y);i(b),c(b,!0)}break}case ze.ENTER:{var C=r.value[s.activeIndex];C&&!C.data.disabled?d(C.data.value):d(void 0),t.open&&v.preventDefault();break}case ze.ESC:t.onToggleOpen(!1),t.open&&v.stopPropagation()}},onKeyup:function(){},scrollTo:function(v){i(v)}}},render:function(){var t=this.renderItem,n=this.listRef,r=this.onListMouseDown,a=this.itemPrefixCls,o=this.setActive,i=this.onSelectValue,l=this.memoFlattenOptions,s=this.$slots,c=this.$props,d=c.id,f=c.childrenAsData,p=c.values,v=c.height,m=c.itemHeight,y=c.menuItemSelectedIcon,b=c.notFoundContent,C=c.virtual,S=c.onScroll,w=c.onMouseenter,k=s.option,$=this.state.activeIndex;return l.length===0?g(\"div\",{role:\"listbox\",id:\"\".concat(d,\"_list\"),class:\"\".concat(a,\"-empty\"),onMousedown:r},[b]):g(Fe,null,[g(\"div\",{role:\"listbox\",id:\"\".concat(d,\"_list\"),style:{height:0,width:0,overflow:\"hidden\"}},[t($-1),t($),t($+1)]),g(J2e,{itemKey:\"key\",ref:n,data:l,height:v,itemHeight:m,fullHeight:!1,onMousedown:r,onScroll:S,virtual:C,onMouseenter:w,children:function(T,_){var I,L=T.group,j=T.groupOption,F=T.data,N=F.label,D=F.key;if(L)return g(\"div\",{class:Se(a,\"\".concat(a,\"-group\"))},[k?k(F):N!==void 0?N:D]);var z=F.disabled,B=F.value,M=F.title,E=F.children,K=F.style,W=F.class,Y=F.className,q=eSe(F,[\"disabled\",\"value\",\"title\",\"children\",\"style\",\"class\",\"className\"]),J=p.has(B),ne=\"\".concat(a,\"-option\"),oe=Se(a,ne,W,Y,(I={},V(I,\"\".concat(ne,\"-grouped\"),j),V(I,\"\".concat(ne,\"-active\"),$===_&&!z),V(I,\"\".concat(ne,\"-disabled\"),z),V(I,\"\".concat(ne,\"-selected\"),J),I)),Q=f?E:N,ae=!y||typeof y==\"function\"||J,de=Q||B,be=typeof de==\"string\"||typeof de==\"number\"?de.toString():void 0;return M!==void 0&&(be=M),g(\"div\",le(le({},q),{},{\"aria-selected\":J,class:oe,title:be,onMousemove:function(Pe){q.onMousemove&&q.onMousemove(Pe),!($===_||z)&&o(_)},onClick:function(Pe){z||i(B),q.onClick&&q.onClick(Pe)},style:K}),[g(\"div\",{class:\"\".concat(ne,\"-content\")},[k?k(F):de]),zn(y)||J,ae&&g(Lv,{class:\"\".concat(a,\"-option-state\"),customizeIcon:y,customizeIconProps:{isSelected:J}},{default:function(){return[J?\"\\u2713\":null]}})])}},null)])}});rA.props=tSe;var nSe=rA,Qw=function(){return null};Qw.isSelectOption=!0;Qw.displayName=\"ASelectOption\";var aA=Qw,e2=function(){return null};e2.isSelectOptGroup=!0;e2.displayName=\"ASelectOptGroup\";var oA=e2,rSe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function aSe(e){var t=e,n=t.key,r=t.children,a=t.props,o=a.value,i=a.disabled,l=rSe(a,[\"value\",\"disabled\"]),s=r&&r.default?r.default():void 0;return P({key:n,value:o!==void 0?o:n,children:s,disabled:i||i===\"\"},l)}function t2(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n=Un(e).map(function(r,a){var o;if(!zn(r)||!r.type)return null;var i=r.type.isSelectOptGroup,l=r.key,s=r.children,c=r.props;if(t||!i)return aSe(r);var d=s&&s.default?s.default():void 0,f=(c==null?void 0:c.label)||((o=s.label)===null||o===void 0?void 0:o.call(s))||l;return P(P({key:\"__RC_SELECT_GRP__\".concat(l===null?a:String(l),\"__\")},c),{label:f,options:t2(d||[])})}).filter(function(r){return r});return n}function oSe(e){return WI(e)||YI(e)||rg(e)||UI()}function n2(e){return Array.isArray(e)?e:e!==void 0?[e]:[]}function iSe(e,t){var n=t.labelInValue,r=t.combobox,a=new Map;if(e===void 0||e===\"\"&&r)return[[],a];var o=Array.isArray(e)?e:[e],i=o;return n&&(i=o.filter(function(l){return l!==null}).map(function(l){var s=l.key,c=l.value,d=c!==void 0?c:s;return a.set(d,l),d})),[i,a]}function lSe(e,t){var n=t.optionLabelProp,r=t.labelInValue,a=t.prevValueMap,o=t.options,i=t.getLabeledValue,l=e;return r&&(l=l.map(function(s){return i(s,{options:o,prevValueMap:a,labelInValue:r,optionLabelProp:n})})),l}function sSe(e,t){var n=Je(t),r;for(r=e.length-1;r>=0&&e[r].disabled;r-=1);var a=null;return r!==-1&&(a=n[r],n.splice(r,1)),{values:n,removedValue:a}}var uSe=typeof window!=\"undefined\"&&window.document&&window.document.documentElement,cSe=uSe,lP=0;function dSe(){var e;return cSe?(e=lP,lP+=1):e=\"TEST_OR_SSR\",e}function sP(e,t){var n=e.key,r;return\"value\"in e&&(r=e.value),n!=null?n:r!==void 0?r:\"rc-index-key-\".concat(t)}function fSe(e){var t=[];function n(r,a){r.forEach(function(o){a||!(\"options\"in o)?t.push({key:sP(o,t.length),groupOption:a,data:o}):(t.push({key:sP(o,t.length),group:!0,data:o}),n(o.options,!0))})}return n(e,!1),t}function iA(e){var t=P({},e);return\"props\"in t||Object.defineProperty(t,\"props\",{get:function(){return t}}),t}function r2(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.prevValueOptions,a=r===void 0?[]:r,o=new Map;return t.forEach(function(i){if(!i.group){var l=i.data;o.set(l.value,l)}}),e.map(function(i){var l=o.get(i);return l||(l=P({},a.find(function(s){return s._INTERNAL_OPTION_VALUE_===i}))),iA(l)})}var hSe=function(t,n){var r=n.options,a=n.prevValueMap,o=n.labelInValue,i=n.optionLabelProp,l=r2([t],r)[0],s={value:t},c=o?a.get(t):void 0;return c&&kt(c)===\"object\"&&\"label\"in c?(s.label=c.label,l&&typeof c.label==\"string\"&&typeof l[i]==\"string\"&&(c.label.trim(),l[i].trim())):l&&i in l?Array.isArray(l[i])?s.label=rn(l[i][0])?hr(l[i][0]):l[i]:s.label=l[i]:(s.label=t,s.isCacheable=!0),s.key=s.value,s};function uP(e){return n2(e).map(function(t){var n,r;return rn(t)?((n=t==null?void 0:t.el)===null||n===void 0?void 0:n.innerText)||((r=t==null?void 0:t.el)===null||r===void 0?void 0:r.wholeText):t}).join(\"\")}function pSe(e){return function(t,n){var r=t.toLowerCase();if(\"options\"in n)return uP(n.label).toLowerCase().includes(r);var a=n[e],o=uP(a).toLowerCase();return o.includes(r)}}function vSe(e,t,n){var r=n.optionFilterProp,a=n.filterOption,o=[],i;return a===!1?Je(t):(typeof a==\"function\"?i=a:i=pSe(r),t.forEach(function(l){if(\"options\"in l){var s=i(e,l);if(s)o.push(l);else{var c=l.options.filter(function(d){return i(e,d)});c.length&&o.push(P(P({},l),{options:c}))}return}i(e,iA(l))&&o.push(l)}),o)}function mSe(e,t){if(!t||!t.length)return null;var n=!1;function r(o,i){var l=oSe(i),s=l[0],c=l.slice(1);if(!s)return[o];var d=o.split(s);return n=n||d.length>1,d.reduce(function(f,p){return[].concat(Je(f),Je(r(p,c)))},[]).filter(function(f){return f})}var a=r(e,t);return n?a:null}function gSe(e,t){var n=r2([e],t)[0];return n.disabled}function ySe(e,t,n,r){var a=n2(t).slice().sort(),o=Je(e),i=new Set;return e.forEach(function(l){l.options?l.options.forEach(function(s){i.add(s.value)}):i.add(l.value)}),a.forEach(function(l){var s=r?l.value:l;if(!i.has(s)){var c;o.push(r?(c={},V(c,n,l.label),V(c,\"value\",s),c):{value:s})}}),o}function Ot(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!1,a=e;if(Array.isArray(e)&&(a=La(e)[0]),!a)return null;var o=hr(a,t,r);return o.props=n?P(P({},o.props),t):o.props,on(kt(o.props.class)!==\"object\",\"class must be string\"),o}function bSe(e){e.target.composing=!0}function cP(e){!e.target.composing||(e.target.composing=!1,CSe(e.target,\"input\"))}function CSe(e,t){var n=document.createEvent(\"HTMLEvents\");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Ny(e,t,n,r){e.addEventListener(t,n,r)}var wSe={created:function(t,n){(!n.modifiers||!n.modifiers.lazy)&&(Ny(t,\"compositionstart\",bSe),Ny(t,\"compositionend\",cP),Ny(t,\"change\",cP))}},Mi=wSe,SSe=G({name:\"Input\",inheritAttrs:!1,props:{inputRef:u.any,prefixCls:u.string,id:u.string,inputElement:u.any,disabled:u.looseBool,autofocus:u.looseBool,autocomplete:u.string,editable:u.looseBool,accessibilityIndex:u.number,value:u.string,open:u.looseBool,tabindex:u.oneOfType([u.number,u.string]),attrs:u.object,onKeydown:u.func,onMousedown:u.func,onChange:u.func,onPaste:u.func,onCompositionstart:u.func,onCompositionend:u.func,onFocus:u.func,onBlur:u.func},setup:function(t){return{blurTimeout:null,VCSelectContainerEvent:ve(\"VCSelectContainerEvent\")}},render:function(){var t=this,n,r=this.$props,a=r.prefixCls,o=r.id,i=r.inputElement,l=r.disabled,s=r.tabindex,c=r.autofocus,d=r.autocomplete,f=r.editable,p=r.accessibilityIndex,v=r.value,m=r.onKeydown,y=r.onMousedown,b=r.onChange,C=r.onPaste,S=r.onCompositionstart,w=r.onCompositionend,k=r.onFocus,$=r.onBlur,O=r.open,T=r.inputRef,_=r.attrs,I=i||at(g(\"input\",null,null),[[Mi]]),L=I.props||{},j=L.onKeydown,F=L.onInput,N=L.onFocus,D=L.onBlur,z=L.onMousedown,B=L.onCompositionstart,M=L.onCompositionend,E=L.style;return I=Ot(I,P(P(P({id:o,ref:T,disabled:l,tabindex:s,autocomplete:d||\"off\",autofocus:c,class:Se(\"\".concat(a,\"-selection-search-input\"),(n=I==null?void 0:I.props)===null||n===void 0?void 0:n.className),style:P(P({},E),{opacity:f?null:0}),role:\"combobox\",\"aria-expanded\":O,\"aria-haspopup\":\"listbox\",\"aria-owns\":\"\".concat(o,\"_list\"),\"aria-autocomplete\":\"list\",\"aria-controls\":\"\".concat(o,\"_list\"),\"aria-activedescendant\":\"\".concat(o,\"_list_\").concat(p)},_),{value:f?v:\"\",readonly:!f,unselectable:f?null:\"on\",onKeydown:function(W){m(W),j&&j(W)},onMousedown:function(W){y(W),z&&z(W)},onInput:function(W){b(W),F&&F(W)},onCompositionstart:function(W){S(W),B&&B(W)},onCompositionend:function(W){w(W),M&&M(W)},onPaste:C,onFocus:function(){var W;clearTimeout(t.blurTimeout),N&&N(arguments.length<=0?void 0:arguments[0]),k&&k(arguments.length<=0?void 0:arguments[0]),(W=t.VCSelectContainerEvent)===null||W===void 0||W.focus(arguments.length<=0?void 0:arguments[0])},onBlur:function(){for(var W=arguments.length,Y=new Array(W),q=0;q<W;q++)Y[q]=arguments[q];t.blurTimeout=setTimeout(function(){var J;D&&D(Y[0]),$&&$(Y[0]),(J=t.VCSelectContainerEvent)===null||J===void 0||J.blur(Y[0])},200)}}),I.type===\"textarea\"?{}:{type:\"search\"}),!0,!0),I}}),lA=SSe,sA=Symbol(\"OverflowContextProviderKey\"),c1=G({name:\"OverflowContextProvider\",inheritAttrs:!1,props:{value:{type:Object}},setup:function(t,n){var r=n.slots;return ot(sA,x(function(){return t.value})),function(){var a;return(a=r.default)===null||a===void 0?void 0:a.call(r)}}}),kSe=function(){return ve(sA,x(function(){return null}))},$Se=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},js=void 0,Vp=G({name:\"Item\",props:{prefixCls:String,item:u.any,renderItem:Function,responsive:Boolean,itemKey:{type:[String,Number]},registerSize:Function,display:Boolean,order:Number,component:u.any,invalidate:Boolean},setup:function(t,n){var r=n.slots,a=n.expose,o=x(function(){return t.responsive&&!t.display}),i=H();a({itemNodeRef:i});function l(s){t.registerSize(t.itemKey,s)}return Wr(function(){l(null)}),function(){var s,c=t.prefixCls,d=t.invalidate,f=t.item,p=t.renderItem,v=t.responsive;t.registerSize,t.itemKey,t.display;var m=t.order,y=t.component,b=y===void 0?\"div\":y,C=$Se(t,[\"prefixCls\",\"invalidate\",\"item\",\"renderItem\",\"responsive\",\"registerSize\",\"itemKey\",\"display\",\"order\",\"component\"]),S=(s=r.default)===null||s===void 0?void 0:s.call(r),w=p&&f!==js?p(f):S,k;d||(k={opacity:o.value?0:1,height:o.value?0:js,overflowY:o.value?\"hidden\":js,order:v?m:js,pointerEvents:o.value?\"none\":js,position:o.value?\"absolute\":js});var $={};o.value&&($[\"aria-hidden\"]=!0);var O=g(b,le(le(le({class:Se(!d&&c),style:k},$),C),{},{ref:i}),{default:function(){return[w]}});return g(zo,{disabled:!v,onResize:function(_){var I=_.offsetWidth;l(I)}},{default:function(){return[O]}})}}}),Ay=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},OSe=G({name:\"RawItem\",inheritAttrs:!1,props:{component:u.any,title:u.any},setup:function(t,n){var r=n.slots,a=n.attrs,o=kSe();return function(){var i,l;if(!o.value){var s=t.component,c=s===void 0?\"div\":s,d=Ay(t,[\"component\"]);return g(c,le(le({},d),a),{default:function(){return[(i=r.default)===null||i===void 0?void 0:i.call(r)]}})}var f=o.value,p=f.className,v=Ay(f,[\"className\"]),m=a.class,y=Ay(a,[\"class\"]);return g(c1,{value:null},{default:function(){return[g(Vp,le(le(le({class:Se(p,m)},v),y),t),{default:function(){return[(l=r.default)===null||l===void 0?void 0:l.call(r)]}})]}})}}}),PSe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},uA=\"responsive\",cA=\"invalidate\";function TSe(e){return\"+ \".concat(e.length,\" ...\")}var yg=G({name:\"Overflow\",inheritAttrs:!1,props:{prefixCls:String,data:Array,itemKey:[String,Number,Function],itemWidth:{type:Number,default:10},renderItem:Function,renderRawItem:Function,maxCount:[Number,String],renderRest:Function,renderRawRest:Function,suffix:u.any,component:String,itemComponent:u.any,onVisibleChange:Function,ssr:String},emits:[\"visibleChange\"],setup:function(t,n){var r=n.attrs,a=n.emit,o=x(function(){return t.ssr===\"full\"}),i=H(null),l=x(function(){return i.value||0}),s=H(new Map),c=H(0),d=H(0),f=H(0),p=H(null),v=H(null),m=x(function(){return v.value===null&&o.value?Number.MAX_SAFE_INTEGER:v.value||0}),y=H(!1),b=x(function(){return\"\".concat(t.prefixCls,\"-item\")}),C=x(function(){return Math.max(c.value,d.value)}),S=x(function(){return!!(t.data.length&&t.maxCount===uA)}),w=x(function(){return t.maxCount===cA}),k=x(function(){return S.value||typeof t.maxCount==\"number\"&&t.data.length>t.maxCount}),$=x(function(){var z=t.data;return S.value?i.value===null&&o.value?z=t.data:z=t.data.slice(0,Math.min(t.data.length,l.value/t.itemWidth)):typeof t.maxCount==\"number\"&&(z=t.data.slice(0,t.maxCount)),z}),O=x(function(){return S.value?t.data.slice(m.value+1):t.data.slice($.value.length)}),T=function(B,M){var E,K;return typeof t.itemKey==\"function\"?t.itemKey(B):(K=t.itemKey&&((E=B)===null||E===void 0?void 0:E[t.itemKey]))!==null&&K!==void 0?K:M},_=x(function(){return t.renderItem||function(z){return z}}),I=function(B,M){v.value=B,M||(y.value=B<t.data.length-1,a(\"visibleChange\",B))},L=function(B,M){i.value=M.clientWidth},j=function(B,M){var E=new Map(s.value);M===null?E.delete(B):E.set(B,M),s.value=E},F=function(B,M){c.value=d.value,d.value=M},N=function(B,M){f.value=M},D=function(B){return s.value.get(T($.value[B],B))};return ce([l,s,d,f,function(){return t.itemKey},$],function(){if(l.value&&C.value&&$.value){var z=f.value,B=$.value.length,M=B-1;if(!B){I(0),p.value=null;return}for(var E=0;E<B;E+=1){var K=D(E);if(K===void 0){I(E-1,!0);break}if(z+=K,M===0&&z<=l.value||E===M-1&&z+D(M)<=l.value){I(M),p.value=null;break}else if(z+C.value>l.value){I(E-1),p.value=z-K-f.value+d.value;break}}t.suffix&&D(0)+f.value>l.value&&(p.value=null)}}),function(){var z=y.value&&!!O.value.length,B=t.itemComponent,M=t.renderRawItem,E=t.renderRawRest,K=t.renderRest,W=t.prefixCls,Y=W===void 0?\"rc-overflow\":W,q=t.suffix,J=t.component,ne=J===void 0?\"div\":J,oe=r.class,Q=r.style,ae=PSe(r,[\"class\",\"style\"]),de={};p.value!==null&&S.value&&(de={position:\"absolute\",left:\"\".concat(p.value,\"px\"),top:0});var be={prefixCls:b.value,responsive:S.value,component:B,invalidate:w.value},Ee=M?function(ge,ke){var xe=T(ge,ke);return g(c1,{key:xe,value:P(P({},be),{order:ke,item:ge,itemKey:xe,registerSize:j,display:ke<=m.value})},{default:function(){return[M(ge,ke)]}})}:function(ge,ke){var xe=T(ge,ke);return g(Vp,le(le({},be),{},{order:ke,key:xe,item:ge,renderItem:_.value,itemKey:xe,registerSize:j,display:ke<=m.value}),null)},Pe,Be={order:z?m.value:Number.MAX_SAFE_INTEGER,className:\"\".concat(b.value,\"-rest\"),registerSize:F,display:z};if(E)E&&(Pe=g(c1,{value:P(P({},be),Be)},{default:function(){return[E(O.value)]}}));else{var te=K||TSe;Pe=g(Vp,le(le({},be),Be),{default:function(){return[typeof te==\"function\"?te(O.value):te]}})}var ie=g(ne,le({class:Se(!w.value&&Y,oe),style:Q},ae),{default:function(){return[$.value.map(Ee),k.value?Pe:null,q&&g(Vp,le(le({},be),{},{order:m.value,class:\"\".concat(b.value,\"-suffix\"),registerSize:N,display:!0,style:de}),{default:function(){return[q]}})]}});return g(zo,{disabled:!S.value,onResize:L},{default:function(){return[ie]}})}}});yg.Item=OSe;yg.RESPONSIVE=uA;yg.INVALIDATE=cA;var Zl=yg,xSe={id:u.string,prefixCls:u.string,values:u.array,open:u.looseBool,searchValue:u.string,inputRef:u.any,placeholder:u.any,disabled:u.looseBool,mode:u.string,showSearch:u.looseBool,autofocus:u.looseBool,autocomplete:u.string,accessibilityIndex:u.number,tabindex:u.oneOfType([u.number,u.string]),removeIcon:u.VNodeChild,choiceTransitionName:u.string,maxTagCount:u.oneOfType([u.number,u.string]),maxTagTextLength:u.number,maxTagPlaceholder:u.any.def(function(){return function(e){return\"+ \".concat(e.length,\" ...\")}}),tagRender:u.func,onToggleOpen:{type:Function},onSelect:u.func,onInputChange:u.func,onInputPaste:u.func,onInputKeyDown:u.func,onInputMouseDown:u.func,onInputCompositionStart:u.func,onInputCompositionEnd:u.func},dP=function(t){t.preventDefault(),t.stopPropagation()},_Se=G({name:\"MultipleSelectSelector\",inheritAttrs:!1,props:xSe,setup:function(t){var n=H(),r=H(0),a=H(!1),o=x(function(){return\"\".concat(t.prefixCls,\"-selection\")}),i=x(function(){return t.open||t.mode===\"tags\"?t.searchValue:\"\"}),l=x(function(){return t.mode===\"tags\"||t.showSearch&&(t.open||a.value)});et(function(){ce(i,function(){r.value=n.value.scrollWidth},{flush:\"post\",immediate:!0})});function s(p,v,m,y){return g(\"span\",{class:Se(\"\".concat(o.value,\"-item\"),V({},\"\".concat(o.value,\"-item-disabled\"),v))},[g(\"span\",{class:\"\".concat(o.value,\"-item-content\")},[p]),m&&g(Lv,{class:\"\".concat(o.value,\"-item-remove\"),onMousedown:dP,onClick:y,customizeIcon:t.removeIcon},{default:function(){return[yt(\"\\xD7\")]}})])}function c(p,v,m,y,b){var C=function(w){dP(w),t.onToggleOpen(!open)};return g(\"span\",{onMousedown:C},[t.tagRender({label:v,value:p,disabled:m,closable:y,onClose:b})])}function d(p){var v=p.disabled,m=p.label,y=p.value,b=!t.disabled&&!v,C=m;if(typeof t.maxTagTextLength==\"number\"&&(typeof m==\"string\"||typeof m==\"number\")){var S=String(C);S.length>t.maxTagTextLength&&(C=\"\".concat(S.slice(0,t.maxTagTextLength),\"...\"))}var w=function($){$&&$.stopPropagation(),t.onSelect(y,{selected:!1})};return typeof t.tagRender==\"function\"?c(y,C,v,b,w):s(C,v,b,w)}function f(p){var v=t.maxTagPlaceholder,m=v===void 0?function(b){return\"+ \".concat(b.length,\" ...\")}:v,y=typeof m==\"function\"?m(p):m;return s(y,!1)}return function(){var p=t.id,v=t.prefixCls,m=t.values,y=t.open,b=t.inputRef,C=t.placeholder,S=t.disabled,w=t.autofocus,k=t.autocomplete,$=t.accessibilityIndex,O=t.tabindex,T=t.onInputChange,_=t.onInputPaste,I=t.onInputKeyDown,L=t.onInputMouseDown,j=t.onInputCompositionStart,F=t.onInputCompositionEnd,N=g(\"div\",{class:\"\".concat(o.value,\"-search\"),style:{width:r.value+\"px\"},key:\"input\"},[g(lA,{inputRef:b,open:y,prefixCls:v,id:p,inputElement:null,disabled:S,autofocus:w,autocomplete:k,editable:l.value,accessibilityIndex:$,value:i.value,onKeydown:I,onMousedown:L,onChange:T,onPaste:_,onCompositionstart:j,onCompositionend:F,tabindex:O,attrs:Jw(t,!0),onFocus:function(){return a.value=!0},onBlur:function(){return a.value=!1}},null),g(\"span\",{ref:n,class:\"\".concat(o.value,\"-search-mirror\"),\"aria-hidden\":!0},[i.value,yt(\"\\xA0\")])]),D=g(Zl,{prefixCls:\"\".concat(o.value,\"-overflow\"),data:m,renderItem:d,renderRest:f,suffix:N,itemKey:\"key\",maxCount:t.maxTagCount,key:\"overflow\"},null);return g(Fe,null,[D,!m.length&&!i.value&&g(\"span\",{class:\"\".concat(o.value,\"-placeholder\")},[C])])}}}),ESe=_Se,MSe={inputElement:u.any,id:u.string,prefixCls:u.string,values:u.array,open:u.looseBool,searchValue:u.string,inputRef:u.any,placeholder:u.any,disabled:u.looseBool,mode:u.string,showSearch:u.looseBool,autofocus:u.looseBool,autocomplete:u.string,accessibilityIndex:u.number,tabindex:u.oneOfType([u.number,u.string]),activeValue:u.string,backfill:u.looseBool,onInputChange:u.func,onInputPaste:u.func,onInputKeyDown:u.func,onInputMouseDown:u.func,onInputCompositionStart:u.func,onInputCompositionEnd:u.func},a2=G({name:\"SingleSelector\",setup:function(t){var n=H(!1),r=x(function(){return t.mode===\"combobox\"}),a=x(function(){return r.value||t.showSearch}),o=x(function(){var s=t.searchValue||\"\";return r.value&&t.activeValue&&!n.value&&(s=t.activeValue),s});ce([r,function(){return t.activeValue}],function(){r.value&&(n.value=!1)},{immediate:!0});var i=x(function(){return t.mode!==\"combobox\"&&!t.open?!1:!!o.value}),l=x(function(){var s=t.values[0];return s&&(typeof s.label==\"string\"||typeof s.label==\"number\")?s.label.toString():void 0});return function(){var s=t.inputElement,c=t.prefixCls,d=t.id,f=t.values,p=t.inputRef,v=t.disabled,m=t.autofocus,y=t.autocomplete,b=t.accessibilityIndex,C=t.open,S=t.placeholder,w=t.tabindex,k=t.onInputKeyDown,$=t.onInputMouseDown,O=t.onInputChange,T=t.onInputPaste,_=t.onInputCompositionStart,I=t.onInputCompositionEnd,L=f[0];return g(Fe,null,[g(\"span\",{class:\"\".concat(c,\"-selection-search\")},[g(lA,{inputRef:p,prefixCls:c,id:d,open:C,inputElement:s,disabled:v,autofocus:m,autocomplete:y,editable:a.value,accessibilityIndex:b,value:o.value,onKeydown:k,onMousedown:$,onChange:function(F){n.value=!0,O(F)},onPaste:T,onCompositionstart:_,onCompositionend:I,tabindex:w,attrs:Jw(t,!0)},null)]),!r.value&&L&&!i.value&&g(\"span\",{class:\"\".concat(c,\"-selection-item\"),title:l.value},[g(Fe,{key:L.key||L.value},[L.label])]),!L&&!i.value&&g(\"span\",{class:\"\".concat(c,\"-selection-placeholder\")},[S])])}}});a2.props=MSe;a2.inheritAttrs=!1;var ISe=a2;function dA(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:250,t=null,n;wm(function(){window.clearTimeout(n)});function r(a){(a||t===null)&&(t=a),window.clearTimeout(n),n=window.setTimeout(function(){t=null},e)}return[function(){return t},r]}var NSe=G({name:\"Selector\",inheritAttrs:!1,props:{id:u.string,prefixCls:u.string,showSearch:u.looseBool,open:u.looseBool,values:u.array,multiple:u.looseBool,mode:u.string,searchValue:u.string,activeValue:u.string,inputElement:u.any,autofocus:u.looseBool,accessibilityIndex:u.number,tabindex:u.oneOfType([u.number,u.string]),disabled:u.looseBool,placeholder:u.any,removeIcon:u.any,maxTagCount:u.oneOfType([u.number,u.string]),maxTagTextLength:u.number,maxTagPlaceholder:u.any,tagRender:u.func,tokenWithEnter:u.looseBool,choiceTransitionName:u.string,onToggleOpen:{type:Function},onSearch:u.func,onSearchSubmit:u.func,onSelect:u.func,onInputKeyDown:{type:Function},domRef:u.func},setup:function(t){var n=ic(),r=!1,a=dA(0),o=fn(a,2),i=o[0],l=o[1],s=function(w){var k=w.which;(k===ze.UP||k===ze.DOWN)&&w.preventDefault(),t.onInputKeyDown&&t.onInputKeyDown(w),k===ze.ENTER&&t.mode===\"tags\"&&!r&&!t.open&&t.onSearchSubmit(w.target.value),[ze.SHIFT,ze.TAB,ze.BACKSPACE,ze.ESC].includes(k)||t.onToggleOpen(!0)},c=function(){l(!0)},d=null,f=function(w){t.onSearch(w,!0,r)!==!1&&t.onToggleOpen(!0)},p=function(){r=!0},v=function(w){r=!1,t.mode!==\"combobox\"&&f(w.target.value)},m=function(w){var k=w.target.value;if(t.tokenWithEnter&&d&&/[\\r\\n]/.test(d)){var $=d.replace(/[\\r\\n]+$/,\"\").replace(/\\r\\n/g,\" \").replace(/[\\r\\n]/g,\" \");k=k.replace($,d)}d=null,f(k)},y=function(w){var k=w.clipboardData,$=k.getData(\"text\");d=$},b=function(w){var k=w.target;if(k!==n.current){var $=document.body.style.msTouchAction!==void 0;$?setTimeout(function(){n.current.focus()}):n.current.focus()}},C=function(w){var k=i();w.target!==n.current&&!k&&w.preventDefault(),(t.mode!==\"combobox\"&&(!t.showSearch||!k)||!t.open)&&(t.open&&t.onSearch(\"\",!0,!1),t.onToggleOpen())};return{focus:function(){n.current.focus()},blur:function(){n.current.blur()},onMousedown:C,onClick:b,onInputPaste:y,inputRef:n,onInternalInputKeyDown:s,onInternalInputMouseDown:c,onInputChange:m,onInputCompositionEnd:v,onInputCompositionStart:p}},render:function(){var t=this.$props,n=t.prefixCls,r=t.domRef,a=t.multiple,o=this.onMousedown,i=this.onClick,l=this.inputRef,s=this.onInputPaste,c=this.onInternalInputKeyDown,d=this.onInternalInputMouseDown,f=this.onInputChange,p=this.onInputCompositionStart,v=this.onInputCompositionEnd,m={inputRef:l,onInputKeyDown:c,onInputMouseDown:d,onInputChange:f,onInputPaste:s,onInputCompositionStart:p,onInputCompositionEnd:v},y=a?g(ESe,le(le({},this.$props),m),null):g(ISe,le(le({},this.$props),m),null);return g(\"div\",{ref:r,class:\"\".concat(n,\"-selector\"),onClick:i,onMousedown:o},[y])}}),ASe=NSe;function bu(e,t){return e?e.contains(t):!1}var fA=[\"moz\",\"ms\",\"webkit\"];function DSe(){var e=0;return function(t){var n=new Date().getTime(),r=Math.max(0,16-(n-e)),a=window.setTimeout(function(){t(n+r)},r);return e=n+r,a}}function RSe(){if(typeof window==\"undefined\")return function(){};if(window.requestAnimationFrame)return window.requestAnimationFrame.bind(window);var e=fA.filter(function(t){return\"\".concat(t,\"RequestAnimationFrame\")in window})[0];return e?window[\"\".concat(e,\"RequestAnimationFrame\")]:DSe()}function LSe(e){if(typeof window==\"undefined\")return null;if(window.cancelAnimationFrame)return window.cancelAnimationFrame(e);var t=fA.filter(function(n){return\"\".concat(n,\"CancelAnimationFrame\")in window||\"\".concat(n,\"CancelRequestAnimationFrame\")in window})[0];return t?(window[\"\".concat(t,\"CancelAnimationFrame\")]||window[\"\".concat(t,\"CancelRequestAnimationFrame\")]).call(this,e):clearTimeout(e)}var fP=RSe(),o2=function(t){return LSe(t.id)},Fv=function(t,n){var r=Date.now();function a(){Date.now()-r>=n?t.call():o.id=fP(a)}var o={id:fP(a)};return o};function hP(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),n.push.apply(n,r)}return n}function pP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?hP(Object(n),!0).forEach(function(r){FSe(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):hP(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function zp(e){return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?zp=function(t){return typeof t}:zp=function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},zp(e)}function FSe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Kc,BSe={Webkit:\"-webkit-\",Moz:\"-moz-\",ms:\"-ms-\",O:\"-o-\"};function Bv(){if(Kc!==void 0)return Kc;Kc=\"\";var e=document.createElement(\"p\").style,t=\"Transform\";for(var n in BSe)n+t in e&&(Kc=n);return Kc}function hA(){return Bv()?\"\".concat(Bv(),\"TransitionProperty\"):\"transitionProperty\"}function bg(){return Bv()?\"\".concat(Bv(),\"Transform\"):\"transform\"}function vP(e,t){var n=hA();n&&(e.style[n]=t,n!==\"transitionProperty\"&&(e.style.transitionProperty=t))}function Dy(e,t){var n=bg();n&&(e.style[n]=t,n!==\"transform\"&&(e.style.transform=t))}function VSe(e){return e.style.transitionProperty||e.style[hA()]}function zSe(e){var t=window.getComputedStyle(e,null),n=t.getPropertyValue(\"transform\")||t.getPropertyValue(bg());if(n&&n!==\"none\"){var r=n.replace(/[^0-9\\-.,]/g,\"\").split(\",\");return{x:parseFloat(r[12]||r[4],0),y:parseFloat(r[13]||r[5],0)}}return{x:0,y:0}}var HSe=/matrix\\((.*)\\)/,jSe=/matrix3d\\((.*)\\)/;function KSe(e,t){var n=window.getComputedStyle(e,null),r=n.getPropertyValue(\"transform\")||n.getPropertyValue(bg());if(r&&r!==\"none\"){var a,o=r.match(HSe);if(o)o=o[1],a=o.split(\",\").map(function(l){return parseFloat(l,10)}),a[4]=t.x,a[5]=t.y,Dy(e,\"matrix(\".concat(a.join(\",\"),\")\"));else{var i=r.match(jSe)[1];a=i.split(\",\").map(function(l){return parseFloat(l,10)}),a[12]=t.x,a[13]=t.y,Dy(e,\"matrix3d(\".concat(a.join(\",\"),\")\"))}}else Dy(e,\"translateX(\".concat(t.x,\"px) translateY(\").concat(t.y,\"px) translateZ(0)\"))}var WSe=/[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source,Ff;function mP(e){var t=e.style.display;e.style.display=\"none\",e.offsetHeight,e.style.display=t}function Au(e,t,n){var r=n;if(zp(t)===\"object\"){for(var a in t)t.hasOwnProperty(a)&&Au(e,a,t[a]);return}if(typeof r!=\"undefined\"){typeof r==\"number\"&&(r=\"\".concat(r,\"px\")),e.style[t]=r;return}return Ff(e,t)}function USe(e){var t,n,r,a=e.ownerDocument,o=a.body,i=a&&a.documentElement;return t=e.getBoundingClientRect(),n=Math.floor(t.left),r=Math.floor(t.top),n-=i.clientLeft||o.clientLeft||0,r-=i.clientTop||o.clientTop||0,{left:n,top:r}}function pA(e,t){var n=e[\"page\".concat(t?\"Y\":\"X\",\"Offset\")],r=\"scroll\".concat(t?\"Top\":\"Left\");if(typeof n!=\"number\"){var a=e.document;n=a.documentElement[r],typeof n!=\"number\"&&(n=a.body[r])}return n}function vA(e){return pA(e)}function mA(e){return pA(e,!0)}function sf(e){var t=USe(e),n=e.ownerDocument,r=n.defaultView||n.parentWindow;return t.left+=vA(r),t.top+=mA(r),t}function i2(e){return e!=null&&e==e.window}function gA(e){return i2(e)?e.document:e.nodeType===9?e:e.ownerDocument}function YSe(e,t,n){var r=n,a=\"\",o=gA(e);return r=r||o.defaultView.getComputedStyle(e,null),r&&(a=r.getPropertyValue(t)||r[t]),a}var qSe=new RegExp(\"^(\".concat(WSe,\")(?!px)[a-z%]+$\"),\"i\"),GSe=/^(top|right|bottom|left)$/,Ry=\"currentStyle\",Ly=\"runtimeStyle\",Pl=\"left\",XSe=\"px\";function ZSe(e,t){var n=e[Ry]&&e[Ry][t];if(qSe.test(n)&&!GSe.test(t)){var r=e.style,a=r[Pl],o=e[Ly][Pl];e[Ly][Pl]=e[Ry][Pl],r[Pl]=t===\"fontSize\"?\"1em\":n||0,n=r.pixelLeft+XSe,r[Pl]=a,e[Ly][Pl]=o}return n===\"\"?\"auto\":n}typeof window!=\"undefined\"&&(Ff=window.getComputedStyle?YSe:ZSe);function gh(e,t){return e===\"left\"?t.useCssRight?\"right\":e:t.useCssBottom?\"bottom\":e}function gP(e){if(e===\"left\")return\"right\";if(e===\"right\")return\"left\";if(e===\"top\")return\"bottom\";if(e===\"bottom\")return\"top\"}function yP(e,t,n){Au(e,\"position\")===\"static\"&&(e.style.position=\"relative\");var r=-999,a=-999,o=gh(\"left\",n),i=gh(\"top\",n),l=gP(o),s=gP(i);o!==\"left\"&&(r=999),i!==\"top\"&&(a=999);var c=\"\",d=sf(e);(\"left\"in t||\"top\"in t)&&(c=VSe(e)||\"\",vP(e,\"none\")),\"left\"in t&&(e.style[l]=\"\",e.style[o]=\"\".concat(r,\"px\")),\"top\"in t&&(e.style[s]=\"\",e.style[i]=\"\".concat(a,\"px\")),mP(e);var f=sf(e),p={};for(var v in t)if(t.hasOwnProperty(v)){var m=gh(v,n),y=v===\"left\"?r:a,b=d[v]-f[v];m===v?p[m]=y+b:p[m]=y-b}Au(e,p),mP(e),(\"left\"in t||\"top\"in t)&&vP(e,c);var C={};for(var S in t)if(t.hasOwnProperty(S)){var w=gh(S,n),k=t[S]-d[S];S===w?C[w]=p[w]+k:C[w]=p[w]-k}Au(e,C)}function JSe(e,t){var n=sf(e),r=zSe(e),a={x:r.x,y:r.y};\"left\"in t&&(a.x=r.x+t.left-n.left),\"top\"in t&&(a.y=r.y+t.top-n.top),KSe(e,a)}function QSe(e,t,n){if(n.ignoreShake){var r=sf(e),a=r.left.toFixed(0),o=r.top.toFixed(0),i=t.left.toFixed(0),l=t.top.toFixed(0);if(a===i&&o===l)return}n.useCssRight||n.useCssBottom?yP(e,t,n):n.useCssTransform&&bg()in document.body.style?JSe(e,t):yP(e,t,n)}function l2(e,t){for(var n=0;n<e.length;n++)t(e[n])}function yA(e){return Ff(e,\"boxSizing\")===\"border-box\"}var eke=[\"margin\",\"border\",\"padding\"],d1=-1,tke=2,f1=1,nke=0;function rke(e,t,n){var r={},a=e.style,o;for(o in t)t.hasOwnProperty(o)&&(r[o]=a[o],a[o]=t[o]);n.call(e);for(o in t)t.hasOwnProperty(o)&&(a[o]=r[o])}function ad(e,t,n){var r=0,a,o,i;for(o=0;o<t.length;o++)if(a=t[o],a)for(i=0;i<n.length;i++){var l=void 0;a===\"border\"?l=\"\".concat(a).concat(n[i],\"Width\"):l=a+n[i],r+=parseFloat(Ff(e,l))||0}return r}var _o={getParent:function(t){var n=t;do n.nodeType===11&&n.host?n=n.host:n=n.parentNode;while(n&&n.nodeType!==1&&n.nodeType!==9);return n}};l2([\"Width\",\"Height\"],function(e){_o[\"doc\".concat(e)]=function(t){var n=t.document;return Math.max(n.documentElement[\"scroll\".concat(e)],n.body[\"scroll\".concat(e)],_o[\"viewport\".concat(e)](n))},_o[\"viewport\".concat(e)]=function(t){var n=\"client\".concat(e),r=t.document,a=r.body,o=r.documentElement,i=o[n];return r.compatMode===\"CSS1Compat\"&&i||a&&a[n]||i}});function bP(e,t,n){var r=n;if(i2(e))return t===\"width\"?_o.viewportWidth(e):_o.viewportHeight(e);if(e.nodeType===9)return t===\"width\"?_o.docWidth(e):_o.docHeight(e);var a=t===\"width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"],o=Math.floor(t===\"width\"?e.getBoundingClientRect().width:e.getBoundingClientRect().height),i=yA(e),l=0;(o==null||o<=0)&&(o=void 0,l=Ff(e,t),(l==null||Number(l)<0)&&(l=e.style[t]||0),l=parseFloat(l)||0),r===void 0&&(r=i?f1:d1);var s=o!==void 0||i,c=o||l;return r===d1?s?c-ad(e,[\"border\",\"padding\"],a):l:s?r===f1?c:c+(r===tke?-ad(e,[\"border\"],a):ad(e,[\"margin\"],a)):l+ad(e,eke.slice(r),a)}var ake={position:\"absolute\",visibility:\"hidden\",display:\"block\"};function CP(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r,a=t[0];return a.offsetWidth!==0?r=bP.apply(void 0,t):rke(a,ake,function(){r=bP.apply(void 0,t)}),r}l2([\"width\",\"height\"],function(e){var t=e.charAt(0).toUpperCase()+e.slice(1);_o[\"outer\".concat(t)]=function(r,a){return r&&CP(r,e,a?nke:f1)};var n=e===\"width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"];_o[e]=function(r,a){var o=a;if(o!==void 0){if(r){var i=yA(r);return i&&(o+=ad(r,[\"padding\",\"border\"],n)),Au(r,e,o)}return}return r&&CP(r,e,d1)}});function bA(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}var jt={getWindow:function(t){if(t&&t.document&&t.setTimeout)return t;var n=t.ownerDocument||t;return n.defaultView||n.parentWindow},getDocument:gA,offset:function(t,n,r){if(typeof n!=\"undefined\")QSe(t,n,r||{});else return sf(t)},isWindow:i2,each:l2,css:Au,clone:function(t){var n,r={};for(n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);var a=t.overflow;if(a)for(n in t)t.hasOwnProperty(n)&&(r.overflow[n]=t.overflow[n]);return r},mix:bA,getWindowScrollLeft:function(t){return vA(t)},getWindowScrollTop:function(t){return mA(t)},merge:function(){for(var t={},n=0;n<arguments.length;n++)jt.mix(t,n<0||arguments.length<=n?void 0:arguments[n]);return t},viewportWidth:0,viewportHeight:0};bA(jt,_o);var Fy=jt.getParent;function h1(e){if(jt.isWindow(e)||e.nodeType===9)return null;var t=jt.getDocument(e),n=t.body,r,a=jt.css(e,\"position\"),o=a===\"fixed\"||a===\"absolute\";if(!o)return e.nodeName.toLowerCase()===\"html\"?null:Fy(e);for(r=Fy(e);r&&r!==n&&r.nodeType!==9;r=Fy(r))if(a=jt.css(r,\"position\"),a!==\"static\")return r;return null}var wP=jt.getParent;function oke(e){if(jt.isWindow(e)||e.nodeType===9)return!1;var t=jt.getDocument(e),n=t.body,r=null;for(r=wP(e);r&&r!==n&&r!==t;r=wP(r)){var a=jt.css(r,\"position\");if(a===\"fixed\")return!0}return!1}function s2(e,t){for(var n={left:0,right:1/0,top:0,bottom:1/0},r=h1(e),a=jt.getDocument(e),o=a.defaultView||a.parentWindow,i=a.body,l=a.documentElement;r;){if((navigator.userAgent.indexOf(\"MSIE\")===-1||r.clientWidth!==0)&&r!==i&&r!==l&&jt.css(r,\"overflow\")!==\"visible\"){var s=jt.offset(r);s.left+=r.clientLeft,s.top+=r.clientTop,n.top=Math.max(n.top,s.top),n.right=Math.min(n.right,s.left+r.clientWidth),n.bottom=Math.min(n.bottom,s.top+r.clientHeight),n.left=Math.max(n.left,s.left)}else if(r===i||r===l)break;r=h1(r)}var c=null;if(!jt.isWindow(e)&&e.nodeType!==9){c=e.style.position;var d=jt.css(e,\"position\");d===\"absolute\"&&(e.style.position=\"fixed\")}var f=jt.getWindowScrollLeft(o),p=jt.getWindowScrollTop(o),v=jt.viewportWidth(o),m=jt.viewportHeight(o),y=l.scrollWidth,b=l.scrollHeight,C=window.getComputedStyle(i);if(C.overflowX===\"hidden\"&&(y=o.innerWidth),C.overflowY===\"hidden\"&&(b=o.innerHeight),e.style&&(e.style.position=c),t||oke(e))n.left=Math.max(n.left,f),n.top=Math.max(n.top,p),n.right=Math.min(n.right,f+v),n.bottom=Math.min(n.bottom,p+m);else{var S=Math.max(y,f+v);n.right=Math.min(n.right,S);var w=Math.max(b,p+m);n.bottom=Math.min(n.bottom,w)}return n.top>=0&&n.left>=0&&n.bottom>n.top&&n.right>n.left?n:null}function ike(e,t,n,r){var a=jt.clone(e),o={width:t.width,height:t.height};return r.adjustX&&a.left<n.left&&(a.left=n.left),r.resizeWidth&&a.left>=n.left&&a.left+o.width>n.right&&(o.width-=a.left+o.width-n.right),r.adjustX&&a.left+o.width>n.right&&(a.left=Math.max(n.right-o.width,n.left)),r.adjustY&&a.top<n.top&&(a.top=n.top),r.resizeHeight&&a.top>=n.top&&a.top+o.height>n.bottom&&(o.height-=a.top+o.height-n.bottom),r.adjustY&&a.top+o.height>n.bottom&&(a.top=Math.max(n.bottom-o.height,n.top)),jt.mix(a,o)}function u2(e){var t,n,r;if(!jt.isWindow(e)&&e.nodeType!==9)t=jt.offset(e),n=jt.outerWidth(e),r=jt.outerHeight(e);else{var a=jt.getWindow(e);t={left:jt.getWindowScrollLeft(a),top:jt.getWindowScrollTop(a)},n=jt.viewportWidth(a),r=jt.viewportHeight(a)}return t.width=n,t.height=r,t}function SP(e,t){var n=t.charAt(0),r=t.charAt(1),a=e.width,o=e.height,i=e.left,l=e.top;return n===\"c\"?l+=o/2:n===\"b\"&&(l+=o),r===\"c\"?i+=a/2:r===\"r\"&&(i+=a),{left:i,top:l}}function yh(e,t,n,r,a){var o=SP(t,n[1]),i=SP(e,n[0]),l=[i.left-o.left,i.top-o.top];return{left:Math.round(e.left-l[0]+r[0]-a[0]),top:Math.round(e.top-l[1]+r[1]-a[1])}}function kP(e,t,n){return e.left<n.left||e.left+t.width>n.right}function $P(e,t,n){return e.top<n.top||e.top+t.height>n.bottom}function lke(e,t,n){return e.left>n.right||e.left+t.width<n.left}function ske(e,t,n){return e.top>n.bottom||e.top+t.height<n.top}function bh(e,t,n){var r=[];return jt.each(e,function(a){r.push(a.replace(t,function(o){return n[o]}))}),r}function Ch(e,t){return e[t]=-e[t],e}function OP(e,t){var n;return/%$/.test(e)?n=parseInt(e.substring(0,e.length-1),10)/100*t:n=parseInt(e,10),n||0}function PP(e,t){e[0]=OP(e[0],t.width),e[1]=OP(e[1],t.height)}function CA(e,t,n,r){var a=n.points,o=n.offset||[0,0],i=n.targetOffset||[0,0],l=n.overflow,s=n.source||e;o=[].concat(o),i=[].concat(i),l=l||{};var c={},d=0,f=!!(l&&l.alwaysByViewport),p=s2(s,f),v=u2(s);PP(o,v),PP(i,t);var m=yh(v,t,a,o,i),y=jt.merge(v,m);if(p&&(l.adjustX||l.adjustY)&&r){if(l.adjustX&&kP(m,v,p)){var b=bh(a,/[lr]/gi,{l:\"r\",r:\"l\"}),C=Ch(o,0),S=Ch(i,0),w=yh(v,t,b,C,S);lke(w,v,p)||(d=1,a=b,o=C,i=S)}if(l.adjustY&&$P(m,v,p)){var k=bh(a,/[tb]/gi,{t:\"b\",b:\"t\"}),$=Ch(o,1),O=Ch(i,1),T=yh(v,t,k,$,O);ske(T,v,p)||(d=1,a=k,o=$,i=O)}d&&(m=yh(v,t,a,o,i),jt.mix(y,m));var _=kP(m,v,p),I=$P(m,v,p);if(_||I){var L=a;_&&(L=bh(a,/[lr]/gi,{l:\"r\",r:\"l\"})),I&&(L=bh(a,/[tb]/gi,{t:\"b\",b:\"t\"})),a=L,o=n.offset||[0,0],i=n.targetOffset||[0,0]}c.adjustX=l.adjustX&&_,c.adjustY=l.adjustY&&I,(c.adjustX||c.adjustY)&&(y=ike(m,v,p,c))}return y.width!==v.width&&jt.css(s,\"width\",jt.width(s)+y.width-v.width),y.height!==v.height&&jt.css(s,\"height\",jt.height(s)+y.height-v.height),jt.offset(s,{left:y.left,top:y.top},{useCssRight:n.useCssRight,useCssBottom:n.useCssBottom,useCssTransform:n.useCssTransform,ignoreShake:n.ignoreShake}),{points:a,offset:o,targetOffset:i,overflow:c}}function uke(e,t){var n=s2(e,t),r=u2(e);return!n||r.left+r.width<=n.left||r.top+r.height<=n.top||r.left>=n.right||r.top>=n.bottom}function c2(e,t,n){var r=n.target||t,a=u2(r),o=!uke(r,n.overflow&&n.overflow.alwaysByViewport);return CA(e,a,n,o)}c2.__getOffsetParent=h1;c2.__getVisibleRectForElement=s2;function cke(e,t,n){var r,a,o=jt.getDocument(e),i=o.defaultView||o.parentWindow,l=jt.getWindowScrollLeft(i),s=jt.getWindowScrollTop(i),c=jt.viewportWidth(i),d=jt.viewportHeight(i);\"pageX\"in t?r=t.pageX:r=l+t.clientX,\"pageY\"in t?a=t.pageY:a=s+t.clientY;var f={left:r,top:a,width:0,height:0},p=r>=0&&r<=l+c&&a>=0&&a<=s+d,v=[n.points[0],\"cc\"];return CA(e,f,pP(pP({},n),{},{points:v}),p)}var dke=function(e){if(!e)return!1;if(e.offsetParent)return!0;if(e.getBBox){var t=e.getBBox();if(t.width||t.height)return!0}if(e.getBoundingClientRect){var n=e.getBoundingClientRect();if(n.width||n.height)return!0}return!1};function fke(e,t){return e===t?!0:!e||!t?!1:\"pageX\"in t&&\"pageY\"in t?e.pageX===t.pageX&&e.pageY===t.pageY:\"clientX\"in t&&\"clientY\"in t?e.clientX===t.clientX&&e.clientY===t.clientY:!1}function hke(e,t){e!==document.activeElement&&bu(t,e)&&typeof e.focus==\"function\"&&e.focus()}function TP(e,t){var n=null,r=null;function a(i){var l=fn(i,1),s=l[0].target;if(!!document.documentElement.contains(s)){var c=s.getBoundingClientRect(),d=c.width,f=c.height,p=Math.floor(d),v=Math.floor(f);(n!==p||r!==v)&&Promise.resolve().then(function(){t({width:p,height:v})}),n=p,r=v}}var o=new ng(a);return e&&o.observe(e),function(){o.disconnect()}}var pke=function(e,t){var n=!1,r=null;function a(){window.clearTimeout(r)}function o(i){if(!n||i===!0){if(e()===!1)return;n=!0,a(),r=window.setTimeout(function(){n=!1},t.value)}else a(),r=window.setTimeout(function(){n=!1,o()},t.value)}return[o,function(){n=!1,a()}]},vke={align:Object,target:[Object,Function],onAlign:Function,monitorBufferTime:Number,monitorWindowResize:Boolean,disabled:Boolean};function xP(e){return typeof e!=\"function\"?null:e()}function _P(e){return kt(e)!==\"object\"||!e?null:e}var EP=G({name:\"Align\",props:vke,emits:[\"align\"],setup:function(t,n){var r=n.expose,a=n.slots,o=H({}),i=H(),l=x(function(){return{disabled:t.disabled,target:t.target,onAlign:t.onAlign}}),s=pke(function(){var b=l.value,C=b.disabled,S=b.target,w=b.onAlign;if(!C&&S&&i.value&&i.value.$el){var k=i.value.$el,$,O=xP(S),T=_P(S);o.value.element=O,o.value.point=T;var _=document,I=_.activeElement;return O&&dke(O)?$=c2(k,O,t.align):T&&($=cke(k,T,t.align)),hke(I,k),w&&$&&w(k,$),!0}return!1},x(function(){return t.monitorBufferTime})),c=fn(s,2),d=c[0],f=c[1],p=H({cancel:function(){}}),v=H({cancel:function(){}}),m=function(){var C=t.target,S=xP(C),w=_P(C);i.value&&i.value.$el!==v.value.element&&(v.value.cancel(),v.value.element=i.value.$el,v.value.cancel=TP(i.value.$el,d)),(o.value.element!==S||!fke(o.value.point,w))&&(d(),p.value.element!==S&&(p.value.cancel(),p.value.element=S,p.value.cancel=TP(S,d)))};et(function(){m()}),ur(function(){m()}),ce(function(){return t.disabled},function(b){b?f():d()},{flush:\"post\"});var y=H(null);return ce(function(){return t.monitorWindowResize},function(b){b?y.value||(y.value=Kn(window,\"resize\",d)):y.value&&(y.value.remove(),y.value=null)},{flush:\"post\"}),Wr(function(){p.value.cancel(),v.value.cancel(),y.value&&y.value.remove(),f()}),r({forceAlign:function(){return d(!0)}}),function(){var b=a==null?void 0:a.default();return b?Ot(b[0],{ref:i},!0,!0):b&&b[0]}}}),wA={name:\"LazyRenderBox\",props:{visible:u.looseBool,hiddenClassName:u.string},render:function(){var t=this.$props.hiddenClassName,n=ht(this);return t||n&&n.length>1||n&&n[0]&&n[0].type===Fo?g(\"div\",null,[n]):n&&n[0]}},MP={props:{hiddenClassName:u.string.def(\"\"),prefixCls:u.string,visible:u.looseBool},render:function(){var t=this,n,r,a=this.$props,o=a.prefixCls,i=a.visible,l=a.hiddenClassName;return g(\"div\",{class:i?\"\":l},[g(wA,{class:\"\".concat(o,\"-content\"),visible:i},{default:function(){return[(r=(n=t.$slots).default)===null||r===void 0?void 0:r.call(n)]}})])}},nt={methods:{setState:function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0,r=typeof t==\"function\"?t(this.$data,this.$props):t;if(this.getDerivedStateFromProps){var a=this.getDerivedStateFromProps(Qe(this),P(P({},this.$data),r));if(a===null)return;r=P(P({},r),a||{})}P(this.$data,r),this._.isMounted&&this.$forceUpdate(),Ne(function(){n&&n()})},__emit:function(){var t=[].slice.call(arguments,0),n=t[0];n=\"on\".concat(n[0].toUpperCase()).concat(n.substring(1));var r=this.$props[n]||this.$attrs[n];if(t.length&&r)if(Array.isArray(r))for(var a=0,o=r.length;a<o;a++)r[a].apply(r,Je(t.slice(1)));else r.apply(void 0,Je(t.slice(1)))}}};function mke(e,t,n){return n?e[0]===t[0]:e[0]===t[0]&&e[1]===t[1]}function gke(e,t,n){var r=e[t]||{};return P(P({},r),n)}function yke(e,t,n,r){var a=n.points;for(var o in e)if(e.hasOwnProperty(o)&&mke(e[o].points,a,r))return\"\".concat(t,\"-placement-\").concat(o);return\"\"}function wh(){}function IP(e,t){this[e]=t}globalThis&&globalThis.__rest;var Lo=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=P(t?{appear:!0,appearToClass:\"\".concat(t,\"-appear \").concat(t,\"-appear-active\"),enterFromClass:\"\".concat(t,\"-enter \").concat(t,\"-enter-prepare\"),enterToClass:\"\".concat(t,\"-enter \").concat(t,\"-enter-active\"),leaveFromClass:\" \".concat(t,\"-leave\"),leaveActiveClass:\"\".concat(t,\"-leave \").concat(t,\"-leave-active\"),leaveToClass:\"\".concat(t,\"-leave \").concat(t,\"-leave-active\")}:{css:!1},n);return r},d2=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=P(t?{appear:!0,appearActiveClass:\"\".concat(t),appearToClass:\"\".concat(t,\"-appear \").concat(t,\"-appear-active\"),enterFromClass:\"\".concat(t,\"-appear \").concat(t,\"-enter \").concat(t,\"-appear-prepare \").concat(t,\"-enter-prepare\"),enterActiveClass:\"\".concat(t),enterToClass:\"\".concat(t,\"-enter \").concat(t,\"-appear \").concat(t,\"-appear-active \").concat(t,\"-enter-active\"),leaveActiveClass:\"\".concat(t,\" \").concat(t,\"-leave\"),leaveToClass:\"\".concat(t,\"-leave-active\")}:{css:!1},n);return r},no=Vn,f2=e8,NP=function(){return{height:0,opacity:0}},bke=function(t){return{height:\"\".concat(t.scrollHeight,\"px\"),opacity:1}},Cke=function(t){return{height:\"\".concat(t.offsetHeight,\"px\")}},wke=function(t,n){return{name:\"ant-motion-collapse\",appear:!0,css:!0,onBeforeEnter:function(a){n.value=\"ant-motion-collapse\",t.value=NP()},onEnter:function(a){Ne(function(){t.value=bke(a)})},onAfterEnter:function(){n.value=\"\",t.value={}},onBeforeLeave:function(a){n.value=\"ant-motion-collapse\",t.value=Cke(a)},onLeave:function(a){window.setTimeout(function(){t.value=NP()})},onAfterLeave:function(){n.value=\"\",t.value={}}}},Cg=no,Ske={name:\"VCTriggerPopup\",mixins:[nt],inheritAttrs:!1,props:{visible:u.looseBool,getClassNameFromAlign:u.func,getRootDomNode:u.func,align:u.any,destroyPopupOnHide:u.looseBool,prefixCls:u.string,getContainer:u.func,transitionName:u.string,animation:u.any,maskAnimation:u.string,maskTransitionName:u.string,mask:u.looseBool,zIndex:u.number,popupClassName:u.any,popupStyle:u.object.def(function(){return{}}),stretch:u.string,point:u.shape({pageX:u.number,pageY:u.number}).loose},data:function(){return this.domEl=null,this.currentAlignClassName=void 0,this.transitionProps={},this.savePopupRef=IP.bind(this,\"popupInstance\"),this.saveAlignRef=IP.bind(this,\"alignInstance\"),{stretchChecked:!1,targetWidth:void 0,targetHeight:void 0}},mounted:function(){var t=this;this.$nextTick(function(){t.rootNode=t.getPopupDomNode(),t.setStretchSize()})},updated:function(){var t=this;this.$nextTick(function(){t.setStretchSize()})},methods:{onAlign:function(t,n){var r=this.$props,a=r.getClassNameFromAlign(n);this.currentAlignClassName!==a&&(this.currentAlignClassName=a,t.className=this.getClassName(a,t.className));var o=this.$attrs.onaAlign;o&&o(t,n)},setStretchSize:function(){var t=this.$props,n=t.stretch,r=t.getRootDomNode,a=t.visible,o=this.$data,i=o.stretchChecked,l=o.targetHeight,s=o.targetWidth;if(!n||!a){i&&this.setState({stretchChecked:!1});return}var c=r();if(!!c){var d=c.offsetHeight,f=c.offsetWidth;(l!==d||s!==f||!i)&&this.setState({stretchChecked:!0,targetHeight:d,targetWidth:f})}},getPopupDomNode:function(){return Sn(this.popupInstance)},getTargetElement:function(){return this.$props.getRootDomNode()},getAlignTarget:function(){var t=this.$props.point;return t||this.getTargetElement},getMaskTransitionName:function(){var t=this.$props,n=t.maskTransitionName,r=t.maskAnimation;return!n&&r&&(n=\"\".concat(t.prefixCls,\"-\").concat(r)),n},getTransitionName:function(){var t=this.$props,n=t.transitionName,r=t.animation;return n||(typeof r==\"string\"?n=\"\".concat(r):r&&r.props&&r.props.name&&(n=r.props.name)),n},getClassName:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"\",a=[];this.transitionProps&&Object.keys(this.transitionProps).forEach(function(i){typeof n.transitionProps[i]==\"string\"&&a.push.apply(a,Je(n.transitionProps[i].split(\" \")))});var o=r.split(\" \").filter(function(i){return a.indexOf(i)!==-1}).join(\" \");return\"\".concat(this.$props.prefixCls,\" \").concat(this.$attrs.class||\"\",\" \").concat(this.$props.popupClassName,\" \").concat(t,\" \").concat(o)},getPopupElement:function(){var t=this,n,r,a=this.savePopupRef,o=this.$props,i=this.$attrs,l=this.$slots,s=this.getTransitionName,c=this.$data,d=c.stretchChecked,f=c.targetHeight,p=c.targetWidth,v=i.style,m=v===void 0?{}:v,y=If(i).onEvents,b=o.align,C=o.visible,S=o.prefixCls,w=o.animation,k=o.popupStyle,$=o.getClassNameFromAlign,O=o.destroyPopupOnHide,T=o.stretch,_=this.getClassName(this.currentAlignClassName||$(b));C||(this.currentAlignClassName=null);var I={};T&&(T.indexOf(\"height\")!==-1?I.height=typeof f==\"number\"?\"\".concat(f,\"px\"):f:T.indexOf(\"minHeight\")!==-1&&(I.minHeight=typeof f==\"number\"?\"\".concat(f,\"px\"):f),T.indexOf(\"width\")!==-1?I.width=typeof p==\"number\"?\"\".concat(p,\"px\"):p:T.indexOf(\"minWidth\")!==-1&&(I.minWidth=typeof p==\"number\"?\"\".concat(p,\"px\"):p),d||setTimeout(function(){t.alignInstance&&t.alignInstance.forceAlign()},0));var L=P(P({prefixCls:S,visible:C,class:_},y),{ref:a,style:P(P(P(P({},I),k),m),this.getZIndexStyle())}),j=s(),F=!!j,N=Lo(j);return kt(w)===\"object\"&&(F=!0,N=P(P({},N),w)),F||(N={}),this.transitionProps=N,O?g(no,N,{default:function(){return[C?g(EP,{target:t.getAlignTarget(),key:\"popup\",ref:t.saveAlignRef,monitorWindowResize:!0,align:b,onAlign:t.onAlign},{default:function(){return[g(MP,L,{default:function(){return[(n=l.default)===null||n===void 0?void 0:n.call(l)]}})]}}):null]}}):g(no,N,{default:function(){return[at(g(EP,{target:t.getAlignTarget(),key:\"popup\",ref:t.saveAlignRef,monitorWindowResize:!0,disabled:!C,align:b,onAlign:t.onAlign},{default:function(){return[g(MP,L,{default:function(){return[(r=l.default)===null||r===void 0?void 0:r.call(l)]}})]}}),[[_t,C]])]}})},getZIndexStyle:function(){var t={},n=this.$props;return n.zIndex!==void 0&&(t.zIndex=n.zIndex),t},getMaskElement:function(){var t=this.$props,n=null;if(t.mask){var r=this.getMaskTransitionName();if(n=at(g(wA,{style:this.getZIndexStyle(),key:\"mask\",class:\"\".concat(t.prefixCls,\"-mask\"),visible:t.visible},null),[[_t,t.visible]]),r){var a=function(){return n}();n=g(no,{appear:!0,name:r},{default:function(){return[a]}})}}return n}},render:function(){var t=this.getMaskElement,n=this.getPopupElement;return g(\"div\",null,[t(),n()])}},SA=G({name:\"Portal\",props:{getContainer:u.func.isRequired,children:u.any.isRequired,didUpdate:u.func},data:function(){return this._container=null,{}},mounted:function(){this.createContainer()},updated:function(){var t=this,n=this.$props.didUpdate;n&&Ne(function(){n(t.$props)})},beforeUnmount:function(){this.removeContainer()},methods:{createContainer:function(){this._container=this.$props.getContainer(),this.$forceUpdate()},removeContainer:function(){this._container&&this._container.parentNode&&this._container.parentNode.removeChild(this._container)}},render:function(){var t=this;return this._container?g(Ps,{to:this._container},{default:function(){return[t.$props.children]}}):null}});function kke(){return\"\"}function $ke(){return window.document}var Oke=[\"onClick\",\"onMousedown\",\"onTouchstart\",\"onMouseenter\",\"onMouseleave\",\"onFocus\",\"onBlur\",\"onContextmenu\"],Ii=G({name:\"Trigger\",mixins:[nt],inheritAttrs:!1,props:{action:u.oneOfType([u.string,u.arrayOf(u.string)]).def([]),showAction:u.any.def([]),hideAction:u.any.def([]),getPopupClassNameFromAlign:u.any.def(kke),onPopupVisibleChange:u.func.def(wh),afterPopupVisibleChange:u.func.def(wh),popup:u.any,popupStyle:u.object.def(function(){return{}}),prefixCls:u.string.def(\"rc-trigger-popup\"),popupClassName:u.string.def(\"\"),popupPlacement:u.string,builtinPlacements:u.object,popupTransitionName:u.oneOfType([u.string,u.object]),popupAnimation:u.any,mouseEnterDelay:u.number.def(0),mouseLeaveDelay:u.number.def(.1),zIndex:u.number,focusDelay:u.number.def(0),blurDelay:u.number.def(.15),getPopupContainer:u.func,getDocument:u.func.def($ke),forceRender:u.looseBool,destroyPopupOnHide:u.looseBool.def(!1),mask:u.looseBool.def(!1),maskClosable:u.looseBool.def(!0),popupAlign:u.object.def(function(){return{}}),popupVisible:u.looseBool,defaultPopupVisible:u.looseBool.def(!1),maskTransitionName:u.oneOfType([u.string,u.object]),maskAnimation:u.string,stretch:u.string,alignPoint:u.looseBool},setup:function(){return{vcTriggerContext:ve(\"vcTriggerContext\",{}),savePopupRef:ve(\"savePopupRef\",wh),dialogContext:ve(\"dialogContext\",null)}},data:function(){var t=this,n=this.$props,r;return vt(this,\"popupVisible\")?r=!!n.popupVisible:r=!!n.defaultPopupVisible,Oke.forEach(function(a){t[\"fire\".concat(a)]=function(o){t.fireEvents(a,o)}}),this._component=null,this.focusTime=null,this.clickOutsideHandler=null,this.contextmenuOutsideHandler1=null,this.contextmenuOutsideHandler2=null,this.touchOutsideHandler=null,{prevPopupVisible:r,sPopupVisible:r,point:null}},watch:{popupVisible:function(t){t!==void 0&&(this.prevPopupVisible=this.sPopupVisible,this.sPopupVisible=t)}},created:function(){ot(\"vcTriggerContext\",this)},deactivated:function(){this.setPopupVisible(!1)},mounted:function(){var t=this;this.$nextTick(function(){t.updatedCal()})},updated:function(){var t=this;this.$nextTick(function(){t.updatedCal()})},beforeUnmount:function(){this.clearDelayTimer(),this.clearOutsideHandler(),clearTimeout(this.mouseDownTimeout)},methods:{updatedCal:function(){var t=this.$props,n=this.$data;if(n.sPopupVisible){var r;!this.clickOutsideHandler&&(this.isClickToHide()||this.isContextmenuToShow())&&(r=t.getDocument(),this.clickOutsideHandler=Kn(r,\"mousedown\",this.onDocumentClick)),this.touchOutsideHandler||(r=r||t.getDocument(),this.touchOutsideHandler=Kn(r,\"touchstart\",this.onDocumentClick,mn?{passive:!1}:!1)),!this.contextmenuOutsideHandler1&&this.isContextmenuToShow()&&(r=r||t.getDocument(),this.contextmenuOutsideHandler1=Kn(r,\"scroll\",this.onContextmenuClose)),!this.contextmenuOutsideHandler2&&this.isContextmenuToShow()&&(this.contextmenuOutsideHandler2=Kn(window,\"blur\",this.onContextmenuClose))}else this.clearOutsideHandler()},onMouseenter:function(t){var n=this.$props.mouseEnterDelay;this.fireEvents(\"onMouseenter\",t),this.delaySetPopupVisible(!0,n,n?null:t)},onMouseMove:function(t){this.fireEvents(\"onMousemove\",t),this.setPoint(t)},onMouseleave:function(t){this.fireEvents(\"onMouseleave\",t),this.delaySetPopupVisible(!1,this.$props.mouseLeaveDelay)},onPopupMouseenter:function(){this.clearDelayTimer()},onPopupMouseleave:function(t){t&&t.relatedTarget&&!t.relatedTarget.setTimeout&&this._component&&this._component.getPopupDomNode&&bu(this._component.getPopupDomNode(),t.relatedTarget)||this.delaySetPopupVisible(!1,this.$props.mouseLeaveDelay)},onFocus:function(t){this.fireEvents(\"onFocus\",t),this.clearDelayTimer(),this.isFocusToShow()&&(this.focusTime=Date.now(),this.delaySetPopupVisible(!0,this.$props.focusDelay))},onMousedown:function(t){this.fireEvents(\"onMousedown\",t),this.preClickTime=Date.now()},onTouchstart:function(t){this.fireEvents(\"onTouchstart\",t),this.preTouchTime=Date.now()},onBlur:function(t){bu(t.target,t.relatedTarget||document.activeElement)||(this.fireEvents(\"onBlur\",t),this.clearDelayTimer(),this.isBlurToHide()&&this.delaySetPopupVisible(!1,this.$props.blurDelay))},onContextmenu:function(t){t.preventDefault(),this.fireEvents(\"onContextmenu\",t),this.setPopupVisible(!0,t)},onContextmenuClose:function(){this.isContextmenuToShow()&&this.close()},onClick:function(t){if(this.fireEvents(\"onClick\",t),this.focusTime){var n;if(this.preClickTime&&this.preTouchTime?n=Math.min(this.preClickTime,this.preTouchTime):this.preClickTime?n=this.preClickTime:this.preTouchTime&&(n=this.preTouchTime),Math.abs(n-this.focusTime)<20)return;this.focusTime=0}this.preClickTime=0,this.preTouchTime=0,this.isClickToShow()&&(this.isClickToHide()||this.isBlurToHide())&&t&&t.preventDefault&&t.preventDefault(),t&&t.domEvent&&t.domEvent.preventDefault();var r=!this.$data.sPopupVisible;(this.isClickToHide()&&!r||r&&this.isClickToShow())&&this.setPopupVisible(!this.$data.sPopupVisible,t)},onPopupMouseDown:function(){var t=this,n=this.vcTriggerContext,r=n===void 0?{}:n;this.hasPopupMouseDown=!0,clearTimeout(this.mouseDownTimeout),this.mouseDownTimeout=setTimeout(function(){t.hasPopupMouseDown=!1},0),r.onPopupMouseDown&&r.onPopupMouseDown.apply(r,arguments)},onDocumentClick:function(t){if(!(this.$props.mask&&!this.$props.maskClosable)){var n=t.target,r=Sn(this);!bu(r,n)&&!this.hasPopupMouseDown&&this.close()}},getPopupDomNode:function(){return this._component&&this._component.getPopupDomNode?this._component.getPopupDomNode():null},getRootDomNode:function(){return Sn(this)},handleGetPopupClassFromAlign:function(t){var n=[],r=this.$props,a=r.popupPlacement,o=r.builtinPlacements,i=r.prefixCls,l=r.alignPoint,s=r.getPopupClassNameFromAlign;return a&&o&&n.push(yke(o,i,t,l)),s&&n.push(s(t)),n.join(\" \")},getPopupAlign:function(){var t=this.$props,n=t.popupPlacement,r=t.popupAlign,a=t.builtinPlacements;return n&&a?gke(a,n,r):r},savePopup:function(t){this._component=t,this.savePopupRef(t)},getComponent:function(){var t=this,n={};this.isMouseEnterToShow()&&(n.onMouseenter=t.onPopupMouseenter),this.isMouseLeaveToHide()&&(n.onMouseleave=t.onPopupMouseleave),n.onMousedown=this.onPopupMouseDown,n[mn?\"onTouchstartPassive\":\"onTouchstart\"]=this.onPopupMouseDown;var r=t.handleGetPopupClassFromAlign,a=t.getRootDomNode,o=t.getContainer,i=t.$attrs,l=t.$props,s=l.prefixCls,c=l.destroyPopupOnHide,d=l.popupClassName,f=l.action,p=l.popupAnimation,v=l.popupTransitionName,m=l.popupStyle,y=l.mask,b=l.maskAnimation,C=l.maskTransitionName,S=l.zIndex,w=l.stretch,k=l.alignPoint,$=this.$data,O=$.sPopupVisible,T=$.point,_=this.getPopupAlign(),I=P(P({prefixCls:s,destroyPopupOnHide:c,visible:O,point:k?T:null,action:f,align:_,animation:p,getClassNameFromAlign:r,stretch:w,getRootDomNode:a,mask:y,zIndex:S,transitionName:v,maskAnimation:b,maskTransitionName:C,getContainer:o,popupClassName:d,popupStyle:m,onAlign:i.onPopupAlign||wh},n),{ref:this.savePopup});return g(Ske,I,{default:function(){return[We(t,\"popup\")]}})},getContainer:function(){var t=this.$props,n=this.dialogContext,r=document.createElement(\"div\");r.style.position=\"absolute\",r.style.top=\"0\",r.style.left=\"0\",r.style.width=\"100%\";var a=t.getPopupContainer?t.getPopupContainer(Sn(this),n):t.getDocument().body;return a.appendChild(r),this.popupContainer=r,r},setPopupVisible:function(t,n){var r=this.alignPoint,a=this.sPopupVisible,o=this.onPopupVisibleChange;this.clearDelayTimer(),a!==t&&(vt(this,\"popupVisible\")||this.setState({sPopupVisible:t,prevPopupVisible:a}),o&&o(t)),r&&n&&this.setPoint(n)},setPoint:function(t){var n=this.$props.alignPoint;!n||!t||this.setState({point:{pageX:t.pageX,pageY:t.pageY}})},handlePortalUpdate:function(){this.prevPopupVisible!==this.sPopupVisible&&this.afterPopupVisibleChange(this.sPopupVisible)},delaySetPopupVisible:function(t,n,r){var a=this,o=n*1e3;if(this.clearDelayTimer(),o){var i=r?{pageX:r.pageX,pageY:r.pageY}:null;this.delayTimer=Fv(function(){a.setPopupVisible(t,i),a.clearDelayTimer()},o)}else this.setPopupVisible(t,r)},clearDelayTimer:function(){this.delayTimer&&(o2(this.delayTimer),this.delayTimer=null)},clearOutsideHandler:function(){this.clickOutsideHandler&&(this.clickOutsideHandler.remove(),this.clickOutsideHandler=null),this.contextmenuOutsideHandler1&&(this.contextmenuOutsideHandler1.remove(),this.contextmenuOutsideHandler1=null),this.contextmenuOutsideHandler2&&(this.contextmenuOutsideHandler2.remove(),this.contextmenuOutsideHandler2=null),this.touchOutsideHandler&&(this.touchOutsideHandler.remove(),this.touchOutsideHandler=null)},createTwoChains:function(t){var n=function(){},r=nf(this);return this.childOriginEvents[t]&&r[t]?this[\"fire\".concat(t)]:(n=this.childOriginEvents[t]||r[t]||n,n)},isClickToShow:function(){var t=this.$props,n=t.action,r=t.showAction;return n.indexOf(\"click\")!==-1||r.indexOf(\"click\")!==-1},isContextmenuToShow:function(){var t=this.$props,n=t.action,r=t.showAction;return n.indexOf(\"contextmenu\")!==-1||r.indexOf(\"contextmenu\")!==-1},isClickToHide:function(){var t=this.$props,n=t.action,r=t.hideAction;return n.indexOf(\"click\")!==-1||r.indexOf(\"click\")!==-1},isMouseEnterToShow:function(){var t=this.$props,n=t.action,r=t.showAction;return n.indexOf(\"hover\")!==-1||r.indexOf(\"mouseenter\")!==-1},isMouseLeaveToHide:function(){var t=this.$props,n=t.action,r=t.hideAction;return n.indexOf(\"hover\")!==-1||r.indexOf(\"mouseleave\")!==-1},isFocusToShow:function(){var t=this.$props,n=t.action,r=t.showAction;return n.indexOf(\"focus\")!==-1||r.indexOf(\"focus\")!==-1},isBlurToHide:function(){var t=this.$props,n=t.action,r=t.hideAction;return n.indexOf(\"focus\")!==-1||r.indexOf(\"blur\")!==-1},forcePopupAlign:function(){this.$data.sPopupVisible&&this._component&&this._component.alignInstance&&this._component.alignInstance.forceAlign()},fireEvents:function(t,n){this.childOriginEvents[t]&&this.childOriginEvents[t](n);var r=this.$props[t]||this.$attrs[t];r&&r(n)},close:function(){this.setPopupVisible(!1)}},render:function(){var t=this,n=this.sPopupVisible,r=this.$attrs,a=La(ht(this)),o=this.$props,i=o.forceRender,l=o.alignPoint;a.length>1&&on(!1,\"Trigger children just support only one default\",!0);var s=a[0];this.childOriginEvents=nf(s);var c={key:\"trigger\"};this.isContextmenuToShow()?c.onContextmenu=this.onContextmenu:c.onContextmenu=this.createTwoChains(\"onContextmenu\"),this.isClickToHide()||this.isClickToShow()?(c.onClick=this.onClick,c.onMousedown=this.onMousedown,c[mn?\"onTouchstartPassive\":\"onTouchstart\"]=this.onTouchstart):(c.onClick=this.createTwoChains(\"onClick\"),c.onMousedown=this.createTwoChains(\"onMousedown\"),c[mn?\"onTouchstartPassive\":\"onTouchstart\"]=this.createTwoChains(\"onTouchstart\")),this.isMouseEnterToShow()?(c.onMouseenter=this.onMouseenter,l&&(c.onMousemove=this.onMouseMove)):c.onMouseenter=this.createTwoChains(\"onMouseenter\"),this.isMouseLeaveToHide()?c.onMouseleave=this.onMouseleave:c.onMouseleave=this.createTwoChains(\"onMouseleave\"),this.isFocusToShow()||this.isBlurToHide()?(c.onFocus=this.onFocus,c.onBlur=this.onBlur):(c.onFocus=this.createTwoChains(\"onFocus\"),c.onBlur=function(v){v&&(!v.relatedTarget||!bu(v.target,v.relatedTarget))&&t.createTwoChains(\"onBlur\")(v)});var d=Se(s&&s.props&&s.props.class,r.class);d&&(c.class=d);var f=Ot(s,c),p;return(n||this._component||i)&&(p=g(SA,{key:\"portal\",children:this.getComponent(),getContainer:this.getContainer,didUpdate:this.handlePortalUpdate},null)),[p,f]}}),Pke=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},Tke=function(t){var n=typeof t!=\"number\"?0:1;return{bottomLeft:{points:[\"tl\",\"bl\"],offset:[0,4],overflow:{adjustX:n,adjustY:1}},bottomRight:{points:[\"tr\",\"br\"],offset:[0,4],overflow:{adjustX:n,adjustY:1}},topLeft:{points:[\"bl\",\"tl\"],offset:[0,-4],overflow:{adjustX:n,adjustY:1}},topRight:{points:[\"br\",\"tr\"],offset:[0,-4],overflow:{adjustX:n,adjustY:1}}}},kA=G({name:\"SelectTrigger\",inheritAttrs:!1,created:function(){this.popupRef=ic()},methods:{getPopupElement:function(){return this.popupRef.current}},render:function(){var t=this,n=P(P({},this.$props),this.$attrs),r=n.empty,a=r===void 0?!1:r,o=Pke(n,[\"empty\"]),i=o.visible,l=o.dropdownAlign,s=o.prefixCls,c=o.popupElement,d=o.dropdownClassName,f=o.dropdownStyle,p=o.dropdownMatchSelectWidth,v=o.containerWidth,m=o.dropdownRender,y=o.animation,b=o.transitionName,C=o.direction,S=o.getPopupContainer,w=\"\".concat(s,\"-dropdown\"),k=c;m&&(k=m({menuNode:c,props:o}));var $=Tke(p),O=y?\"\".concat(w,\"-\").concat(y):b,T=P({minWidth:\"\".concat(v,\"px\")},f);return typeof p==\"number\"?T.width=\"\".concat(p,\"px\"):p&&(T.width=\"\".concat(v,\"px\")),g(Ii,le(le({},o),{},{showAction:[],hideAction:[],popupPlacement:C===\"rtl\"?\"bottomRight\":\"bottomLeft\",builtinPlacements:$,prefixCls:w,popupTransitionName:O,popup:g(\"div\",{ref:this.popupRef},[k]),popupAlign:l,popupVisible:i,getPopupContainer:S,popupClassName:Se(d,V({},\"\".concat(w,\"-empty\"),a)),popupStyle:T}),{default:function(){return[ht(t)[0]]}})}});kA.props={dropdownAlign:u.object,visible:u.looseBool,disabled:u.looseBool,dropdownClassName:u.string,dropdownStyle:u.object,empty:u.looseBool,prefixCls:u.string,popupClassName:u.string,animation:u.string,transitionName:u.string,getPopupContainer:u.func,dropdownRender:u.func,containerWidth:u.number,dropdownMatchSelectWidth:u.oneOfType([Number,Boolean]).def(!0),popupElement:u.any,direction:u.string,getTriggerDOMNode:u.func};var xke=kA,_ke=\"RC_SELECT_INTERNAL_PROPS_MARK\";function Eke(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:10,t=H(!1),n,r=function(){window.clearTimeout(n)};et(function(){r()});var a=function(i,l){r(),n=window.setTimeout(function(){t.value=i,l&&l()},e)};return[t,a,r]}function Mke(e,t,n){function r(a){var o,i,l,s=a.target;s.shadowRoot&&a.composed&&(s=a.composedPath()[0]||s);var c=[(o=e[0])===null||o===void 0?void 0:o.value,(l=(i=e[1])===null||i===void 0?void 0:i.value)===null||l===void 0?void 0:l.getPopupElement()];t.value&&c.every(function(d){return d&&!d.contains(s)&&d!==s})&&n(!1)}et(function(){window.addEventListener(\"mousedown\",r)}),Lt(function(){window.removeEventListener(\"mousedown\",r)})}function Ike(e){var t=Je(e.value),n=x(function(){var r=new Map;t.forEach(function(o){var i=o.value,l=o.label;i!==l&&r.set(i,l)});var a=e.value.map(function(o){var i=r.get(o.value);return o.isCacheable&&i?P(P({},o),{label:i}):o});return t=a,a});return n}function Nke(e){var t=x(function(){var r=new Map;return e.value.forEach(function(a){var o=a.data.value;r.set(o,a)}),r}),n=function(a){return a.map(function(o){return t.value.get(o)}).filter(Boolean)};return n}var Ake=function(t,n){var r=P({},t);return Object.keys(n).forEach(function(a){var o=r[a];if(o)o.default=n[a];else throw new Error(\"not have \".concat(a,\" prop\"))}),r},Rn=Ake,Dke=function(){if(typeof navigator==\"undefined\"||typeof window==\"undefined\")return!1;var e=navigator.userAgent||navigator.vendor||window.opera;return!!(/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(e==null?void 0:e.substr(0,4)))},Rke=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},Lke=[\"children\",\"removeIcon\",\"placeholder\",\"autofocus\",\"maxTagCount\",\"maxTagTextLength\",\"maxTagPlaceholder\",\"choiceTransitionName\",\"onInputKeyDown\",\"tabindex\"],$A=function(){return{prefixCls:u.string,id:u.string,class:u.string,style:u.any,options:u.array,mode:u.string,value:u.any,defaultValue:u.any,labelInValue:u.looseBool,inputValue:u.string,searchValue:u.string,optionFilterProp:u.string,filterOption:u.any,filterSort:u.func,showSearch:u.looseBool,autoClearSearchValue:u.looseBool,onSearch:u.func,onClear:u.func,allowClear:u.looseBool,clearIcon:u.VNodeChild,showArrow:u.looseBool,inputIcon:u.VNodeChild,removeIcon:u.VNodeChild,menuItemSelectedIcon:u.VNodeChild,open:u.looseBool,defaultOpen:u.looseBool,listHeight:u.number,listItemHeight:u.number,dropdownStyle:u.object,dropdownClassName:u.string,dropdownMatchSelectWidth:an(u.oneOfType([Boolean,Number])),virtual:u.looseBool,dropdownRender:u.func,dropdownAlign:u.any,animation:u.string,transitionName:u.string,getPopupContainer:u.func,direction:u.string,disabled:u.looseBool,loading:u.looseBool,autofocus:u.looseBool,defaultActiveFirstOption:u.looseBool,notFoundContent:u.VNodeChild,placeholder:u.VNodeChild,backfill:u.looseBool,getInputElement:u.func,optionLabelProp:u.string,maxTagTextLength:u.number,maxTagCount:u.oneOfType([u.number,u.string]),maxTagPlaceholder:u.any,tokenSeparators:u.arrayOf(u.string),tagRender:u.func,showAction:u.array,tabindex:u.oneOfType([u.number,u.string]),onKeyup:u.func,onKeydown:u.func,onPopupScroll:u.func,onDropdownVisibleChange:u.func,onSelect:u.func,onDeselect:u.func,onInputKeyDown:{type:Function},onClick:u.func,onChange:u.func,onBlur:u.func,onFocus:u.func,onMousedown:u.func,onMouseenter:u.func,onMouseleave:u.func,choiceTransitionName:u.string,internalProps:u.object,children:u.array}};function Fke(e){var t=e.prefixCls,n=e.components.optionList,r=e.convertChildrenToData,a=e.flattenOptions,o=e.getLabeledValue,i=e.filterOptions,l=e.isValueDisabled,s=e.findValueOption;e.warningProps;var c=e.fillOptionsWithMissingValue,d=e.omitDOMProps,f=G({name:\"Select\",slots:[\"option\"],props:Rn($A(),{}),setup:function(v){var m,y=x(function(){return v.internalProps&&v.internalProps.mark===_ke});on(v.optionFilterProp!==\"children\",\"Select\",\"optionFilterProp not support children, please use label instead\");var b=H(null),C=H(null),S=H(null),w=H(null),k=x(function(){return(v.tokenSeparators||[]).some(function(it){return[`\n`,`\\r\n`].includes(it)})}),$=Eke(),O=fn($,3),T=O[0],_=O[1],I=O[2],L=x(function(){return v.id||\"rc_select_\".concat(dSe())}),j=x(function(){var it=v.optionLabelProp;return it===void 0&&(it=v.options?\"label\":\"children\"),it}),F=x(function(){return v.mode===\"combobox\"?!1:v.labelInValue}),N=x(function(){return v.mode===\"tags\"||v.mode===\"multiple\"}),D=x(function(){return v.showSearch!==void 0?v.showSearch:N.value||v.mode===\"combobox\"}),z=H(!1);et(function(){z.value=Dke()});var B=ic(),M=H(\"\"),E=function(ct){M.value=ct},K=H(v.value!==void 0?v.value:v.defaultValue);ce(function(){return v.value},function(){K.value=v.value,M.value=\"\"});var W=x(function(){return iSe(K.value,{labelInValue:F.value,combobox:v.mode===\"combobox\"})}),Y=x(function(){return W.value[0]}),q=x(function(){return W.value[1]}),J=x(function(){return new Set(Y.value)}),ne=H(null),oe=function(ct){ne.value=ct},Q=x(function(){var it=M.value;return v.mode===\"combobox\"&&K.value!==void 0?it=K.value:v.searchValue!==void 0?it=v.searchValue:v.inputValue&&(it=v.inputValue),it}),ae=x(function(){var it=v.options;return it===void 0&&(it=r(v.children)),v.mode===\"tags\"&&c&&(it=c(it,K.value,j.value,v.labelInValue)),it||[]}),de=x(function(){return a(ae.value,v)}),be=Nke(de),Ee=x(function(){if(!Q.value||!D.value)return Je(ae.value);var it=v.optionFilterProp,ct=it===void 0?\"value\":it,Nt=v.mode,sn=v.filterOption,pn=i(Q.value,ae.value,{optionFilterProp:ct,filterOption:Nt===\"combobox\"&&sn===void 0?function(){return!0}:sn});return Nt===\"tags\"&&pn.every(function($n){return $n[ct]!==Q.value})&&pn.unshift({value:Q.value,label:Q.value,key:\"__RC_SELECT_TAG_PLACEHOLDER__\"}),v.filterSort&&Array.isArray(pn)?Je(pn).sort(v.filterSort):pn}),Pe=x(function(){return a(Ee.value,v)});et(function(){ce(Q,function(){w.value&&w.value.scrollTo&&w.value.scrollTo(0)},{flush:\"post\",immediate:!0})});var Be=x(function(){var it=Y.value.map(function(ct){var Nt=be([ct]),sn=o(ct,{options:Nt,prevValueMap:q.value,labelInValue:F.value,optionLabelProp:j.value});return P(P({},sn),{disabled:l(ct,Nt)})});return!v.mode&&it.length===1&&it[0].value===null&&it[0].label===null?[]:it});Be=Ike(Be);var te=function(ct,Nt,sn){var pn=be([ct]),$n=s([ct],pn)[0],za=v.internalProps,Xn=za===void 0?{}:za;if(!Xn.skipTriggerSelect){var yo=F.value?o(ct,{options:pn,prevValueMap:q.value,labelInValue:F.value,optionLabelProp:j.value}):ct;Nt&&v.onSelect?v.onSelect(yo,$n):!Nt&&v.onDeselect&&v.onDeselect(yo,$n)}y.value&&(Nt&&Xn.onRawSelect?Xn.onRawSelect(ct,$n,sn):!Nt&&Xn.onRawDeselect&&Xn.onRawDeselect(ct,$n,sn))},ie=H([]),ge=function(ct){ie.value=ct},ke=function(ct){if(!(y.value&&v.internalProps&&v.internalProps.skipTriggerChange)){var Nt=be(ct),sn=lSe(Array.from(ct),{labelInValue:F.value,options:Nt,getLabeledValue:o,prevValueMap:q.value,optionLabelProp:j.value}),pn=N.value?sn:sn[0];if(v.onChange&&(Y.value.length!==0||sn.length!==0)){var $n=s(ct,Nt,{prevValueOptions:ie.value});ge($n.map(function(za,Xn){var yo=P({},za);return Object.defineProperty(yo,\"_INTERNAL_OPTION_VALUE_\",{get:function(){return ct[Xn]}}),yo})),v.onChange(pn,N.value?$n:$n[0])}K.value=pn}},xe=function(ct,Nt){var sn=Nt.selected,pn=Nt.source,$n=v.autoClearSearchValue,za=$n===void 0?!0:$n;if(!v.disabled){var Xn;N.value?(Xn=new Set(Y.value),sn?Xn.add(ct):Xn.delete(ct)):(Xn=new Set,Xn.add(ct)),(N.value||!N.value&&Array.from(Y.value)[0]!==ct)&&ke(Array.from(Xn)),te(ct,!N.value||sn,pn),v.mode===\"combobox\"?(E(String(ct)),oe(\"\")):(!N.value||za)&&(E(\"\"),oe(\"\"))}},Ie=function(ct,Nt){xe(ct,P(P({},Nt),{source:\"option\"}))},ye=function(ct,Nt){xe(ct,P(P({},Nt),{source:\"selection\"}))},pe=v.open!==void 0?v.open:v.defaultOpen,ue=H(pe),Ce=H(pe),je=function(ct){ue.value=v.open!==void 0?v.open:ct,Ce.value=ue.value};ce(function(){return v.open},function(){je(v.open)});var ee=x(function(){return!v.notFoundContent&&!Ee.value.length});Wn(function(){Ce.value=ue.value,(v.disabled||ee.value&&Ce.value&&v.mode===\"combobox\")&&(Ce.value=!1)});var me=x(function(){return ee.value?!1:Ce.value}),He=function(ct){var Nt=ct!==void 0?ct:!Ce.value;ue.value!==Nt&&!v.disabled&&(je(Nt),v.onDropdownVisibleChange&&v.onDropdownVisibleChange(Nt))};Mke([b,C],me,He);var lt=function(ct,Nt,sn){var pn=!0,$n=ct,za=Q.value;oe(null);var Xn=sn?null:mSe(ct,v.tokenSeparators),yo=Xn;if(v.mode===\"combobox\")Nt&&ke([$n]);else if(Xn){$n=\"\",v.mode!==\"tags\"&&(yo=Xn.map(function(Ac){var Ck=de.value.find(function(p9){var v9=p9.data;return v9[j.value]===Ac});return Ck?Ck.data.value:null}).filter(function(Ac){return Ac!==null}));var Uo=Array.from(new Set([].concat(Je(Y.value),Je(yo))));ke(Uo),Uo.forEach(function(Ac){te(Ac,!0,\"input\")}),He(!1),pn=!1}return E($n),v.onSearch&&za!==$n&&v.onSearch($n),pn},Ye=function(ct){if(!(!ct||!ct.trim())){var Nt=Array.from(new Set([].concat(Je(Y.value),[ct])));ke(Nt),Nt.forEach(function(sn){te(sn,!0,\"input\")}),E(\"\")}};ce(function(){return v.disabled},function(){ue.value&&!!v.disabled&&je(!1)},{immediate:!0}),ce(Ce,function(){!Ce.value&&!N.value&&v.mode!==\"combobox\"&&lt(\"\",!1,!1)},{immediate:!0});var he=dA(),_e=fn(he,2),$e=_e[0],Ve=_e[1],st=function(ct){var Nt=$e(),sn=ct.which;if(sn===ze.ENTER&&(v.mode!==\"combobox\"&&ct.preventDefault(),Ce.value||He(!0)),Ve(!!Q.value),sn===ze.BACKSPACE&&!Nt&&N.value&&!Q.value&&Y.value.length){var pn=sSe(Be.value,Y.value);pn.removedValue!==null&&(ke(pn.values),te(pn.removedValue,!1,\"input\"))}Ce.value&&w.value&&w.value.onKeydown(ct),v.onKeydown&&v.onKeydown(ct)},Dt=function(ct){Ce.value&&w.value&&w.value.onKeyup(ct),v.onKeyup&&v.onKeyup(ct)},Ut=H(!1),Ft=function(){_(!0),v.disabled||(v.onFocus&&!Ut.value&&v.onFocus(arguments.length<=0?void 0:arguments[0]),v.showAction&&v.showAction.includes(\"focus\")&&He(!0)),Ut.value=!0},Jt=function(){if(_(!1,function(){Ut.value=!1,He(!1)}),!v.disabled){var ct=Q.value;ct&&(v.mode===\"tags\"?(lt(\"\",!1,!1),ke(Array.from(new Set([].concat(Je(Y.value),[ct]))))):v.mode===\"multiple\"&&E(\"\")),v.onBlur&&v.onBlur(arguments.length<=0?void 0:arguments[0])}};ot(\"VCSelectContainerEvent\",{focus:Ft,blur:Jt});var Mn=[];et(function(){Mn.forEach(function(it){return window.clearTimeout(it)}),Mn.splice(0,Mn.length)}),Lt(function(){Mn.forEach(function(it){return window.clearTimeout(it)}),Mn.splice(0,Mn.length)});var tr=function(ct){var Nt=ct.target,sn=C.value&&C.value.getPopupElement();if(sn&&sn.contains(Nt)){var pn=window.setTimeout(function(){var $n=Mn.indexOf(pn);$n!==-1&&Mn.splice($n,1),I(),!z.value&&!sn.contains(document.activeElement)&&S.value.focus()});Mn.push(pn)}v.onMousedown&&v.onMousedown(ct)},nr=H(0),Va=x(function(){return v.defaultActiveFirstOption!==void 0?v.defaultActiveFirstOption:v.mode!==\"combobox\"}),Wo=function(ct,Nt){var sn=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},pn=sn.source,$n=pn===void 0?\"keyboard\":pn;nr.value=Nt,v.backfill&&v.mode===\"combobox\"&&ct!==null&&$n===\"keyboard\"&&oe(String(ct))},Re=H(null);et(function(){ce(me,function(){if(me.value){var it=Math.ceil(b.value.offsetWidth);Re.value!==it&&(Re.value=it)}},{immediate:!0})});var ut=function(){S.value.focus()},Vt=function(){S.value.blur()};return{focus:ut,blur:Vt,scrollTo:(m=w.value)===null||m===void 0?void 0:m.scrollTo,tokenWithEnter:k,mockFocused:T,mergedId:L,containerWidth:Re,onActiveValue:Wo,accessibilityIndex:nr,mergedDefaultActiveFirstOption:Va,onInternalMouseDown:tr,onContainerFocus:Ft,onContainerBlur:Jt,onInternalKeyDown:st,isMultiple:N,mergedOpen:Ce,displayOptions:Ee,displayFlattenOptions:Pe,rawValues:J,onInternalOptionSelect:Ie,onToggleOpen:He,mergedSearchValue:Q,useInternalProps:y,triggerChange:ke,triggerSearch:lt,mergedRawValue:Y,mergedShowSearch:D,onInternalKeyUp:Dt,triggerOpen:me,mergedOptions:ae,onInternalSelectionSelect:ye,selectorDomRef:B,displayValues:Be,activeValue:ne,onSearchSubmit:Ye,containerRef:b,listRef:w,triggerRef:C,selectorRef:S}},methods:{onPopupMouseEnter:function(){this.$forceUpdate()}},render:function(){var v,m=this,y=this.tokenWithEnter,b=this.mockFocused,C=this.mergedId,S=this.containerWidth,w=this.onActiveValue,k=this.accessibilityIndex,$=this.mergedDefaultActiveFirstOption,O=this.onInternalMouseDown,T=this.onInternalKeyDown,_=this.isMultiple,I=this.mergedOpen,L=this.displayOptions,j=this.displayFlattenOptions,F=this.rawValues,N=this.onInternalOptionSelect,D=this.onToggleOpen,z=this.mergedSearchValue,B=this.onPopupMouseEnter,M=this.useInternalProps,E=this.triggerChange,K=this.triggerSearch,W=this.mergedRawValue,Y=this.mergedShowSearch,q=this.onInternalKeyUp,J=this.triggerOpen,ne=this.mergedOptions,oe=this.onInternalSelectionSelect,Q=this.selectorDomRef,ae=this.displayValues,de=this.activeValue,be=this.onSearchSubmit,Ee=this.$slots,Pe=this.$props,Be=Pe.prefixCls,te=Be===void 0?t:Be,ie=Pe.class;Pe.id,Pe.open,Pe.defaultOpen;var ge=Pe.options;Pe.children;var ke=Pe.mode;Pe.value,Pe.defaultValue,Pe.labelInValue,Pe.showSearch,Pe.inputValue,Pe.searchValue,Pe.filterOption,Pe.optionFilterProp,Pe.autoClearSearchValue,Pe.onSearch;var xe=Pe.allowClear,Ie=Pe.clearIcon,ye=Pe.showArrow,pe=Pe.inputIcon,ue=Pe.menuItemSelectedIcon,Ce=Pe.disabled,je=Pe.loading;Pe.defaultActiveFirstOption;var ee=Pe.notFoundContent,me=ee===void 0?\"Not Found\":ee;Pe.optionLabelProp,Pe.backfill;var He=Pe.getInputElement,lt=Pe.getPopupContainer,Ye=Pe.listHeight,he=Ye===void 0?200:Ye,_e=Pe.listItemHeight,$e=_e===void 0?20:_e,Ve=Pe.animation,st=Pe.transitionName,Dt=Pe.virtual,Ut=Pe.dropdownStyle,Ft=Pe.dropdownClassName,Jt=Pe.dropdownMatchSelectWidth,Mn=Pe.dropdownRender,tr=Pe.dropdownAlign;Pe.showAction;var nr=Pe.direction;Pe.tokenSeparators;var Va=Pe.tagRender,Wo=Pe.onPopupScroll;Pe.onDropdownVisibleChange,Pe.onFocus,Pe.onBlur,Pe.onKeyup,Pe.onKeydown,Pe.onMousedown,Pe.onChange,Pe.onSelect,Pe.onDeselect;var Re=Pe.onClear,ut=Pe.internalProps,Vt=ut===void 0?{}:ut,it=Rke(Pe,[\"prefixCls\",\"class\",\"id\",\"open\",\"defaultOpen\",\"options\",\"children\",\"mode\",\"value\",\"defaultValue\",\"labelInValue\",\"showSearch\",\"inputValue\",\"searchValue\",\"filterOption\",\"optionFilterProp\",\"autoClearSearchValue\",\"onSearch\",\"allowClear\",\"clearIcon\",\"showArrow\",\"inputIcon\",\"menuItemSelectedIcon\",\"disabled\",\"loading\",\"defaultActiveFirstOption\",\"notFoundContent\",\"optionLabelProp\",\"backfill\",\"getInputElement\",\"getPopupContainer\",\"listHeight\",\"listItemHeight\",\"animation\",\"transitionName\",\"virtual\",\"dropdownStyle\",\"dropdownClassName\",\"dropdownMatchSelectWidth\",\"dropdownRender\",\"dropdownAlign\",\"showAction\",\"direction\",\"tokenSeparators\",\"tagRender\",\"onPopupScroll\",\"onDropdownVisibleChange\",\"onFocus\",\"onBlur\",\"onKeyup\",\"onKeydown\",\"onMousedown\",\"onChange\",\"onSelect\",\"onDeselect\",\"onClear\",\"internalProps\"]),ct=ke===\"combobox\"&&He&&He()||null,Nt=d?d(it):it;Lke.forEach(function(Uo){delete Nt[Uo]});var sn=g(n,{ref:\"listRef\",prefixCls:te,id:C,open:I,childrenAsData:!ge,options:L,flattenOptions:j,multiple:_,values:F,height:he,itemHeight:$e,onSelect:N,onToggleOpen:D,onActiveValue:w,defaultActiveFirstOption:$,notFoundContent:me,onScroll:Wo,searchValue:z,menuItemSelectedIcon:ue,virtual:Dt!==!1&&Jt!==!1,onMouseenter:B},{option:Ee.option}),pn,$n=function(){M&&Vt.onClear&&Vt.onClear(),Re&&Re(),E([]),K(\"\",!1,!1)};!Ce&&xe&&(W.length||z)&&(pn=g(Lv,{class:\"\".concat(te,\"-clear\"),onMousedown:$n,customizeIcon:Ie},{default:function(){return[yt(\"\\xD7\")]}}));var za=ye!==void 0?ye:je||!_&&ke!==\"combobox\",Xn;za&&(Xn=g(Lv,{class:Se(\"\".concat(te,\"-arrow\"),V({},\"\".concat(te,\"-arrow-loading\"),je)),customizeIcon:pe,customizeIconProps:{loading:je,searchValue:z,open:I,focused:b,showSearch:Y}},null));var yo=Se(te,ie,(v={},V(v,\"\".concat(te,\"-focused\"),b),V(v,\"\".concat(te,\"-multiple\"),_),V(v,\"\".concat(te,\"-single\"),!_),V(v,\"\".concat(te,\"-allow-clear\"),xe),V(v,\"\".concat(te,\"-show-arrow\"),za),V(v,\"\".concat(te,\"-disabled\"),Ce),V(v,\"\".concat(te,\"-loading\"),je),V(v,\"\".concat(te,\"-open\"),I),V(v,\"\".concat(te,\"-customize-input\"),ct),V(v,\"\".concat(te,\"-show-search\"),Y),v));return g(\"div\",le(le({class:yo},Nt),{},{ref:\"containerRef\",onMousedown:O,onKeydown:T,onKeyup:q}),[b&&!I&&g(\"span\",{style:{width:0,height:0,display:\"flex\",overflow:\"hidden\",opacity:0},\"aria-live\":\"polite\"},[\"\".concat(W.join(\", \"))]),g(xke,{ref:\"triggerRef\",disabled:Ce,prefixCls:te,visible:J,popupElement:sn,containerWidth:S,animation:Ve,transitionName:st,dropdownStyle:Ut,dropdownClassName:Ft,direction:nr,dropdownMatchSelectWidth:Jt,dropdownRender:Mn,dropdownAlign:tr,getPopupContainer:lt,empty:!ne.length,getTriggerDOMNode:function(){return Q.current}},{default:function(){return[g(ASe,le(le({},m.$props),{},{domRef:Q,prefixCls:te,inputElement:ct,ref:\"selectorRef\",id:C,showSearch:Y,mode:ke,accessibilityIndex:k,multiple:_,tagRender:Va,values:ae,open:I,onToggleOpen:D,searchValue:z,activeValue:de,onSearch:K,onSearchSubmit:be,onSelect:oe,tokenWithEnter:y}),null)]}}),Xn,pn])}});return f}function Bke(e){var t=e.mode,n=e.options,r=e.children,a=e.backfill,o=e.allowClear,i=e.placeholder,l=e.getInputElement,s=e.showSearch,c=e.onSearch,d=e.defaultOpen,f=e.autofocus,p=e.labelInValue,v=e.value,m=e.inputValue,y=e.optionLabelProp,b=t===\"multiple\"||t===\"tags\",C=s!==void 0?s:b||t===\"combobox\",S=n||t2(r);if(Ua(t!==\"tags\"||S.every(function($){return!$.disabled}),\"Please avoid setting option to disabled in tags mode since user can always type text as tag.\"),Ua(t!==\"combobox\"||!y,\"`combobox` mode not support `optionLabelProp`. Please set `value` on Option directly.\"),Ua(t===\"combobox\"||!a,\"`backfill` only works with `combobox` mode.\"),Ua(t===\"combobox\"||!l,\"`getInputElement` only work with `combobox` mode.\"),tP(t!==\"combobox\"||!l||!o||!i,\"Customize `getInputElement` should customize clear and placeholder logic instead of configuring `allowClear` and `placeholder`.\"),c&&!C&&t!==\"combobox\"&&t!==\"tags\"&&Ua(!1,\"`onSearch` should work with `showSearch` instead of use alone.\"),tP(!d||f,\"`defaultOpen` makes Select open without focus which means it will not close by click outside. You can set `autofocus` if needed.\"),v!=null){var w=n2(v);Ua(!p||w.every(function($){return kt($)===\"object\"&&(\"key\"in $||\"value\"in $)}),\"`value` should in shape of `{ value: string | number, label?: any }` when you set `labelInValue` to `true`\"),Ua(!b||Array.isArray(v),\"`value` should be array when `mode` is `multiple` or `tags`\")}if(r){var k=null;r.some(function($){var O;if(!zn($)||!$.type)return!1;var T=$.type;if(T.isSelectOption)return!1;if(T.isSelectOptGroup){var _=((O=$.children)===null||O===void 0?void 0:O.default())||[],I=_.every(function(L){return!zn(L)||!$.type||L.type.isSelectOption?!0:(k=L.type,!1)});return!I}return k=T,!0}),k&&Ua(!1,\"`children` should be `Select.Option` or `Select.OptGroup` instead of `\".concat(k.displayName||k.name||k,\"`.\")),Ua(m===void 0,\"`inputValue` is deprecated, please use `searchValue` instead.\")}}var OA=Fke({prefixCls:\"rc-select\",components:{optionList:nSe},convertChildrenToData:t2,flattenOptions:fSe,getLabeledValue:hSe,filterOptions:vSe,isValueDisabled:gSe,findValueOption:r2,warningProps:Bke,fillOptionsWithMissingValue:ySe}),Bf=G({setup:function(t,n){var r=n.attrs,a=n.expose,o=n.slots,i=H(null);return a({focus:function(){var s;(s=i.value)===null||s===void 0||s.focus()},blur:function(){var s;(s=i.value)===null||s===void 0||s.blur()}}),function(){var l;return g(OA,le(le(le({ref:i},t),r),{},{children:((l=o.default)===null||l===void 0?void 0:l.call(o))||[]}),o)}}});Bf.inheritAttrs=!1;Bf.props=MC(OA.props,[\"children\"]);Bf.Option=aA;Bf.OptGroup=oA;var Vke=Bf,zke={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z\"}}]},name:\"down\",theme:\"outlined\"},Hke=zke,Sh=2,AP=.16,jke=.05,Kke=.05,Wke=.15,PA=5,TA=4,Uke=[{index:7,opacity:.15},{index:6,opacity:.25},{index:5,opacity:.3},{index:5,opacity:.45},{index:5,opacity:.65},{index:5,opacity:.85},{index:4,opacity:.9},{index:3,opacity:.95},{index:2,opacity:.97},{index:1,opacity:.98}];function DP(e){var t=e.r,n=e.g,r=e.b,a=y0(t,n,r);return{h:a.h*360,s:a.s,v:a.v}}function kh(e){var t=e.r,n=e.g,r=e.b;return\"#\".concat(b0(t,n,r,!1))}function Yke(e,t,n){var r=n/100,a={r:(t.r-e.r)*r+e.r,g:(t.g-e.g)*r+e.g,b:(t.b-e.b)*r+e.b};return a}function RP(e,t,n){var r;return Math.round(e.h)>=60&&Math.round(e.h)<=240?r=n?Math.round(e.h)-Sh*t:Math.round(e.h)+Sh*t:r=n?Math.round(e.h)+Sh*t:Math.round(e.h)-Sh*t,r<0?r+=360:r>=360&&(r-=360),r}function LP(e,t,n){if(e.h===0&&e.s===0)return e.s;var r;return n?r=e.s-AP*t:t===TA?r=e.s+AP:r=e.s+jke*t,r>1&&(r=1),n&&t===PA&&r>.1&&(r=.1),r<.06&&(r=.06),Number(r.toFixed(2))}function FP(e,t,n){var r;return n?r=e.v+Kke*t:r=e.v-Wke*t,r>1&&(r=1),Number(r.toFixed(2))}function p1(e){for(var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=[],r=iu(e),a=PA;a>0;a-=1){var o=DP(r),i=kh(iu({h:RP(o,a,!0),s:LP(o,a,!0),v:FP(o,a,!0)}));n.push(i)}n.push(kh(r));for(var l=1;l<=TA;l+=1){var s=DP(r),c=kh(iu({h:RP(s,l),s:LP(s,l),v:FP(s,l)}));n.push(c)}return t.theme===\"dark\"?Uke.map(function(d){var f=d.index,p=d.opacity,v=kh(Yke(iu(t.backgroundColor||\"#141414\"),iu(n[f]),p*100));return v}):n}var By={red:\"#F5222D\",volcano:\"#FA541C\",orange:\"#FA8C16\",gold:\"#FAAD14\",yellow:\"#FADB14\",lime:\"#A0D911\",green:\"#52C41A\",cyan:\"#13C2C2\",blue:\"#1890FF\",geekblue:\"#2F54EB\",purple:\"#722ED1\",magenta:\"#EB2F96\",grey:\"#666666\"},$r={},Vy={};Object.keys(By).forEach(function(e){$r[e]=p1(By[e]),$r[e].primary=$r[e][5],Vy[e]=p1(By[e],{theme:\"dark\",backgroundColor:\"#141414\"}),Vy[e].primary=Vy[e][5]});$r.red;$r.volcano;$r.gold;$r.orange;$r.yellow;$r.lime;$r.green;$r.cyan;$r.blue;$r.geekblue;$r.purple;$r.magenta;$r.grey;var BP=[],Wc=[],qke=\"insert-css: You need to provide a CSS string. Usage: insertCss(cssString[, options]).\";function Gke(){var e=document.createElement(\"style\");return e.setAttribute(\"type\",\"text/css\"),e}function Xke(e,t){if(t=t||{},e===void 0)throw new Error(qke);var n=t.prepend===!0?\"prepend\":\"append\",r=t.container!==void 0?t.container:document.querySelector(\"head\"),a=BP.indexOf(r);a===-1&&(a=BP.push(r)-1,Wc[a]={});var o;return Wc[a]!==void 0&&Wc[a][n]!==void 0?o=Wc[a][n]:(o=Wc[a][n]=Gke(),n===\"prepend\"?r.insertBefore(o,r.childNodes[0]):r.appendChild(o)),e.charCodeAt(0)===65279&&(e=e.substr(1,e.length)),o.styleSheet?o.styleSheet.cssText+=e:o.textContent+=e,o}function VP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){Zke(e,a,n[a])})}return e}function Zke(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function zP(e){return typeof e==\"object\"&&typeof e.name==\"string\"&&typeof e.theme==\"string\"&&(typeof e.icon==\"object\"||typeof e.icon==\"function\")}function v1(e,t,n){return n?qe(e.tag,VP({key:t},n,e.attrs),(e.children||[]).map(function(r,a){return v1(r,\"\".concat(t,\"-\").concat(e.tag,\"-\").concat(a))})):qe(e.tag,VP({key:t},e.attrs),(e.children||[]).map(function(r,a){return v1(r,\"\".concat(t,\"-\").concat(e.tag,\"-\").concat(a))}))}function xA(e){return p1(e)[0]}function _A(e){return e?Array.isArray(e)?e:[e]:[]}var Jke=`\n.anticon {\n  display: inline-block;\n  color: inherit;\n  font-style: normal;\n  line-height: 0;\n  text-align: center;\n  text-transform: none;\n  vertical-align: -0.125em;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.anticon > * {\n  line-height: 1;\n}\n\n.anticon svg {\n  display: inline-block;\n}\n\n.anticon::before {\n  display: none;\n}\n\n.anticon .anticon-icon {\n  display: block;\n}\n\n.anticon[tabindex] {\n  cursor: pointer;\n}\n\n.anticon-spin::before,\n.anticon-spin {\n  display: inline-block;\n  -webkit-animation: loadingCircle 1s infinite linear;\n  animation: loadingCircle 1s infinite linear;\n}\n\n@-webkit-keyframes loadingCircle {\n  100% {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg);\n  }\n}\n\n@keyframes loadingCircle {\n  100% {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg);\n  }\n}\n`,HP=!1,Qke=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Jke;Ne(function(){HP||(typeof window!=\"undefined\"&&window.document&&window.document.documentElement&&Xke(t,{prepend:!0}),HP=!0)})},e$e=[\"icon\",\"primaryColor\",\"secondaryColor\"];function t$e(e,t){if(e==null)return{};var n=n$e(e,t),r,a;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)r=o[a],!(t.indexOf(r)>=0)&&(!Object.prototype.propertyIsEnumerable.call(e,r)||(n[r]=e[r]))}return n}function n$e(e,t){if(e==null)return{};var n={},r=Object.keys(e),a,o;for(o=0;o<r.length;o++)a=r[o],!(t.indexOf(a)>=0)&&(n[a]=e[a]);return n}function Hp(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){r$e(e,a,n[a])})}return e}function r$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Od={primaryColor:\"#333\",secondaryColor:\"#E6E6E6\",calculated:!1};function a$e(e){var t=e.primaryColor,n=e.secondaryColor;Od.primaryColor=t,Od.secondaryColor=n||xA(t),Od.calculated=!!n}function o$e(){return Hp({},Od)}var Mc=function(t,n){var r=Hp({},t,n.attrs),a=r.icon,o=r.primaryColor,i=r.secondaryColor,l=t$e(r,e$e),s=Od;if(o&&(s={primaryColor:o,secondaryColor:i||xA(o)}),Qke(),zP(a),!zP(a))return null;var c=a;return c&&typeof c.icon==\"function\"&&(c=Hp({},c,{icon:c.icon(s.primaryColor,s.secondaryColor)})),v1(c.icon,\"svg-\".concat(c.name),Hp({},l,{\"data-icon\":c.name,width:\"1em\",height:\"1em\",fill:\"currentColor\",\"aria-hidden\":\"true\"}))};Mc.props={icon:Object,primaryColor:String,secondaryColor:String,focusable:String};Mc.inheritAttrs=!1;Mc.displayName=\"IconBase\";Mc.getTwoToneColors=o$e;Mc.setTwoToneColors=a$e;var h2=Mc;function i$e(e,t){return c$e(e)||u$e(e,t)||s$e(e,t)||l$e()}function l$e(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function s$e(e,t){if(!!e){if(typeof e==\"string\")return jP(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if(n===\"Object\"&&e.constructor&&(n=e.constructor.name),n===\"Map\"||n===\"Set\")return Array.from(e);if(n===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return jP(e,t)}}function jP(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function u$e(e,t){var n=e==null?null:typeof Symbol!=\"undefined\"&&e[Symbol.iterator]||e[\"@@iterator\"];if(n!=null){var r=[],a=!0,o=!1,i,l;try{for(n=n.call(e);!(a=(i=n.next()).done)&&(r.push(i.value),!(t&&r.length===t));a=!0);}catch(s){o=!0,l=s}finally{try{!a&&n.return!=null&&n.return()}finally{if(o)throw l}}return r}}function c$e(e){if(Array.isArray(e))return e}function EA(e){var t=_A(e),n=i$e(t,2),r=n[0],a=n[1];return h2.setTwoToneColors({primaryColor:r,secondaryColor:a})}function d$e(){var e=h2.getTwoToneColors();return e.calculated?[e.primaryColor,e.secondaryColor]:e.primaryColor}var f$e=[\"class\",\"icon\",\"spin\",\"rotate\",\"tabindex\",\"twoToneColor\",\"onClick\"];function h$e(e,t){return g$e(e)||m$e(e,t)||v$e(e,t)||p$e()}function p$e(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function v$e(e,t){if(!!e){if(typeof e==\"string\")return KP(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if(n===\"Object\"&&e.constructor&&(n=e.constructor.name),n===\"Map\"||n===\"Set\")return Array.from(e);if(n===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return KP(e,t)}}function KP(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function m$e(e,t){var n=e==null?null:typeof Symbol!=\"undefined\"&&e[Symbol.iterator]||e[\"@@iterator\"];if(n!=null){var r=[],a=!0,o=!1,i,l;try{for(n=n.call(e);!(a=(i=n.next()).done)&&(r.push(i.value),!(t&&r.length===t));a=!0);}catch(s){o=!0,l=s}finally{try{!a&&n.return!=null&&n.return()}finally{if(o)throw l}}return r}}function g$e(e){if(Array.isArray(e))return e}function WP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){m1(e,a,n[a])})}return e}function m1(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function y$e(e,t){if(e==null)return{};var n=b$e(e,t),r,a;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)r=o[a],!(t.indexOf(r)>=0)&&(!Object.prototype.propertyIsEnumerable.call(e,r)||(n[r]=e[r]))}return n}function b$e(e,t){if(e==null)return{};var n={},r=Object.keys(e),a,o;for(o=0;o<r.length;o++)a=r[o],!(t.indexOf(a)>=0)&&(n[a]=e[a]);return n}EA(\"#1890ff\");var Ic=function(t,n){var r,a=WP({},t,n.attrs),o=a.class,i=a.icon,l=a.spin,s=a.rotate,c=a.tabindex,d=a.twoToneColor,f=a.onClick,p=y$e(a,f$e),v=(r={anticon:!0},m1(r,\"anticon-\".concat(i.name),Boolean(i.name)),m1(r,o,o),r),m=l===\"\"||!!l||i.name===\"loading\"?\"anticon-spin\":\"\",y=c;y===void 0&&f&&(y=-1,p.tabindex=y);var b=s?{msTransform:\"rotate(\".concat(s,\"deg)\"),transform:\"rotate(\".concat(s,\"deg)\")}:void 0,C=_A(d),S=h$e(C,2),w=S[0],k=S[1];return g(\"span\",WP({role:\"img\",\"aria-label\":i.name},p,{onClick:f,class:v}),[g(h2,{class:m,icon:i,primaryColor:w,secondaryColor:k,style:b},null)])};Ic.props={spin:Boolean,rotate:Number,icon:Object,twoToneColor:String};Ic.displayName=\"AntdIcon\";Ic.inheritAttrs=!1;Ic.getTwoToneColor=d$e;Ic.setTwoToneColor=EA;var Et=Ic;function UP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){C$e(e,a,n[a])})}return e}function C$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var p2=function(t,n){var r=UP({},t,n.attrs);return g(Et,UP({},r,{icon:Hke}),null)};p2.displayName=\"DownOutlined\";p2.inheritAttrs=!1;var Rs=p2,w$e={icon:{tag:\"svg\",attrs:{viewBox:\"0 0 1024 1024\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z\"}}]},name:\"loading\",theme:\"outlined\"},S$e=w$e;function YP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){k$e(e,a,n[a])})}return e}function k$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var v2=function(t,n){var r=YP({},t,n.attrs);return g(Et,YP({},r,{icon:S$e}),null)};v2.displayName=\"LoadingOutlined\";v2.inheritAttrs=!1;var co=v2,$$e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z\"}}]},name:\"check\",theme:\"outlined\"},O$e=$$e;function qP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){P$e(e,a,n[a])})}return e}function P$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var m2=function(t,n){var r=qP({},t,n.attrs);return g(Et,qP({},r,{icon:O$e}),null)};m2.displayName=\"CheckOutlined\";m2.inheritAttrs=!1;var wg=m2,T$e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z\"}}]},name:\"close\",theme:\"outlined\"},x$e=T$e;function GP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){_$e(e,a,n[a])})}return e}function _$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var g2=function(t,n){var r=GP({},t,n.attrs);return g(Et,GP({},r,{icon:x$e}),null)};g2.displayName=\"CloseOutlined\";g2.inheritAttrs=!1;var go=g2,E$e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z\"}}]},name:\"close-circle\",theme:\"filled\"},M$e=E$e;function XP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){I$e(e,a,n[a])})}return e}function I$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var y2=function(t,n){var r=XP({},t,n.attrs);return g(Et,XP({},r,{icon:M$e}),null)};y2.displayName=\"CloseCircleFilled\";y2.inheritAttrs=!1;var Yr=y2,N$e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z\"}}]},name:\"search\",theme:\"outlined\"},A$e=N$e;function ZP(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){D$e(e,a,n[a])})}return e}function D$e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var b2=function(t,n){var r=ZP({},t,n.attrs);return g(Et,ZP({},r,{icon:A$e}),null)};b2.displayName=\"SearchOutlined\";b2.inheritAttrs=!1;var Vv=b2;function R$e(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=e.loading,r=e.multiple,a=e.prefixCls,o=e.suffixIcon||t.suffixIcon&&t.suffixIcon(),i=e.clearIcon||t.clearIcon&&t.clearIcon(),l=e.menuItemSelectedIcon||t.menuItemSelectedIcon&&t.menuItemSelectedIcon(),s=e.removeIcon||t.removeIcon&&t.removeIcon(),c=i;i||(c=g(Yr,null,null));var d=null;if(o!==void 0)d=o;else if(n)d=g(co,{spin:!0},null);else{var f=\"\".concat(a,\"-suffix\");d=function(y){var b=y.open,C=y.showSearch;return b&&C?g(Vv,{class:f},null):g(Rs,{class:f},null)}}var p=null;l!==void 0?p=l:r?p=g(wg,null,null):p=null;var v=null;return s!==void 0?v=s:v=g(go,null,null),{clearIcon:c,suffixIcon:d,itemIcon:p,removeIcon:v}}var Sg=function(){return P(P({},bn($A(),[\"inputIcon\",\"mode\",\"getInputElement\",\"backfill\",\"class\",\"style\"])),{value:{type:[Array,Object,String,Number]},defaultValue:{type:[Array,Object,String,Number]},notFoundContent:u.VNodeChild,suffixIcon:u.VNodeChild,itemIcon:u.VNodeChild,size:u.oneOf(rt(\"small\",\"middle\",\"large\",\"default\")),mode:u.oneOf(rt(\"multiple\",\"tags\",\"SECRET_COMBOBOX_MODE_DO_NOT_USE\")),bordered:u.looseBool.def(!0),transitionName:u.string.def(\"slide-up\"),choiceTransitionName:u.string.def(\"\")})},qa=G({name:\"ASelect\",Option:aA,OptGroup:oA,inheritAttrs:!1,props:Sg(),SECRET_COMBOBOX_MODE_DO_NOT_USE:\"SECRET_COMBOBOX_MODE_DO_NOT_USE\",emits:[\"change\",\"update:value\"],slots:[\"notFoundContent\",\"suffixIcon\",\"itemIcon\",\"removeIcon\",\"clearIcon\",\"dropdownRender\",\"option\"],setup:function(t,n){var r=n.attrs,a=n.emit,o=n.slots,i=n.expose,l=H(null),s=function(){l.value&&l.value.focus()},c=function(){l.value&&l.value.blur()},d=x(function(){var C=t.mode;if(C!==\"combobox\")return C===qa.SECRET_COMBOBOX_MODE_DO_NOT_USE?\"combobox\":C}),f=Wt(\"select\",t),p=f.prefixCls,v=f.direction,m=f.configProvider,y=x(function(){var C;return Se((C={},V(C,\"\".concat(p.value,\"-lg\"),t.size===\"large\"),V(C,\"\".concat(p.value,\"-sm\"),t.size===\"small\"),V(C,\"\".concat(p.value,\"-rtl\"),v.value===\"rtl\"),V(C,\"\".concat(p.value,\"-borderless\"),!t.bordered),C))}),b=function(){for(var S=arguments.length,w=new Array(S),k=0;k<S;k++)w[k]=arguments[k];a(\"update:value\",w[0]),a.apply(void 0,[\"change\"].concat(w))};return i({blur:c,focus:s}),function(){var C,S=t.notFoundContent,w=t.listHeight,k=w===void 0?256:w,$=t.listItemHeight,O=$===void 0?24:$,T=t.getPopupContainer,_=t.dropdownClassName,I=t.virtual,L=t.dropdownMatchSelectWidth,j=m.renderEmpty,F=m.getPopupContainer,N=d.value===\"multiple\"||d.value===\"tags\",D;S!==void 0?D=S:o.notFoundContent?D=o.notFoundContent():d.value===\"combobox\"?D=null:D=j(\"Select\");var z=R$e(P(P({},t),{multiple:N,prefixCls:p.value}),o),B=z.suffixIcon,M=z.itemIcon,E=z.removeIcon,K=z.clearIcon,W=bn(t,[\"prefixCls\",\"suffixIcon\",\"itemIcon\",\"removeIcon\",\"clearIcon\",\"size\",\"bordered\"]),Y=Se(_,V({},\"\".concat(p.value,\"-dropdown-\").concat(v.value),v.value===\"rtl\"));return g(Vke,le(le(le({ref:l,virtual:I,dropdownMatchSelectWidth:L},W),r),{},{listHeight:k,listItemHeight:O,mode:d.value,prefixCls:p.value,direction:v.value,inputIcon:B,menuItemSelectedIcon:M,removeIcon:E,clearIcon:K,notFoundContent:D,class:[y.value,r.class],getPopupContainer:T||F,dropdownClassName:Y,onChange:b,dropdownRender:W.dropdownRender||o.dropdownRender}),{default:function(){return[(C=o.default)===null||C===void 0?void 0:C.call(o)]},option:o.option})}}});qa.install=function(e){return e.component(qa.name,qa),e.component(qa.Option.displayName,qa.Option),e.component(qa.OptGroup.displayName,qa.OptGroup),e};var L$e=qa.Option,F$e=qa.OptGroup,dl=qa,Vf={prefixCls:u.string,inputPrefixCls:u.string,defaultValue:u.oneOfType([u.string,u.number]),value:u.oneOfType([u.string,u.number]),placeholder:{type:[String,Number]},type:u.string.def(\"text\"),name:u.string,size:{type:String},disabled:u.looseBool,readonly:u.looseBool,addonBefore:u.VNodeChild,addonAfter:u.VNodeChild,prefix:u.VNodeChild,suffix:u.VNodeChild,autofocus:u.looseBool,allowClear:u.looseBool,lazy:u.looseBool.def(!0),maxlength:u.number,loading:u.looseBool,onPressEnter:u.func,onKeydown:u.func,onKeyup:u.func,onFocus:u.func,onBlur:u.func,onChange:u.func,onInput:u.func,\"onUpdate:value\":u.func};function B$e(e){return!!(We(e,\"prefix\")||We(e,\"suffix\")||e.$props.allowClear)}var JP=[\"text\",\"input\"],V$e=G({name:\"ClearableLabeledInput\",inheritAttrs:!1,props:{prefixCls:u.string,inputType:u.oneOf(rt(\"text\",\"input\")),value:u.any,defaultValue:u.any,allowClear:u.looseBool,element:u.VNodeChild,handleReset:u.func,disabled:u.looseBool,size:u.oneOf(rt(\"small\",\"large\",\"default\")),suffix:u.VNodeChild,prefix:u.VNodeChild,addonBefore:u.VNodeChild,addonAfter:u.VNodeChild,readonly:u.looseBool,isFocused:u.looseBool},methods:{renderClearIcon:function(t){var n=this.$props,r=n.allowClear,a=n.value,o=n.disabled,i=n.readonly,l=n.inputType,s=n.handleReset;if(!r)return null;var c=!o&&!i&&a!==void 0&&a!==null&&a!==\"\",d=l===JP[0]?\"\".concat(t,\"-textarea-clear-icon\"):\"\".concat(t,\"-clear-icon\");return g(Yr,{onClick:s,class:Se(d,V({},\"\".concat(d,\"-hidden\"),!c)),role:\"button\"},null)},renderSuffix:function(t){var n=this.$props,r=n.suffix,a=n.allowClear;return r||a?g(\"span\",{class:\"\".concat(t,\"-suffix\")},[this.renderClearIcon(t),r]):null},renderLabeledIcon:function(t,n){var r,a,o=this.$props,i=this.$attrs.style,l=this.renderSuffix(t);if(!B$e(this))return Ot(n,{value:o.value});var s=o.prefix?g(\"span\",{class:\"\".concat(t,\"-prefix\")},[o.prefix]):null,c=Se((a=this.$attrs)===null||a===void 0?void 0:a.class,\"\".concat(t,\"-affix-wrapper\"),(r={},V(r,\"\".concat(t,\"-affix-wrapper-focused\"),o.isFocused),V(r,\"\".concat(t,\"-affix-wrapper-disabled\"),o.disabled),V(r,\"\".concat(t,\"-affix-wrapper-sm\"),o.size===\"small\"),V(r,\"\".concat(t,\"-affix-wrapper-lg\"),o.size===\"large\"),V(r,\"\".concat(t,\"-affix-wrapper-input-with-clear-btn\"),o.suffix&&o.allowClear&&this.$props.value),r));return g(\"span\",{class:c,style:i},[s,Ot(n,{style:null,value:o.value,class:NA(t,o.size,o.disabled)}),l])},renderInputWithLabel:function(t,n){var r,a=this.$props,o=a.addonBefore,i=a.addonAfter,l=a.size,s=this.$attrs,c=s.style,d=s.class;if(!o&&!i)return n;var f=\"\".concat(t,\"-group\"),p=\"\".concat(f,\"-addon\"),v=o?g(\"span\",{class:p},[o]):null,m=i?g(\"span\",{class:p},[i]):null,y=Se(\"\".concat(t,\"-wrapper\"),V({},f,o||i)),b=Se(d,\"\".concat(t,\"-group-wrapper\"),(r={},V(r,\"\".concat(t,\"-group-wrapper-sm\"),l===\"small\"),V(r,\"\".concat(t,\"-group-wrapper-lg\"),l===\"large\"),r));return g(\"span\",{class:b,style:c},[g(\"span\",{class:y},[v,Ot(n,{style:null}),m])])},renderTextAreaWithClearIcon:function(t,n){var r=this.$props,a=r.value,o=r.allowClear,i=this.$attrs,l=i.style,s=i.class;if(!o)return Ot(n,{value:a});var c=Se(s,\"\".concat(t,\"-affix-wrapper\"),\"\".concat(t,\"-affix-wrapper-textarea-with-clear-btn\"));return g(\"span\",{class:c,style:l},[Ot(n,{style:null,value:a}),this.renderClearIcon(t)])},renderClearableLabeledInput:function(){var t=this.$props,n=t.prefixCls,r=t.inputType,a=t.element;return r===JP[0]?this.renderTextAreaWithClearIcon(n,a):this.renderInputWithLabel(n,this.renderLabeledIcon(n,a))}},render:function(){return this.renderClearableLabeledInput()}}),MA=V$e;function IA(e){return typeof e==\"undefined\"||e===null?\"\":e}function zv(e,t,n){if(n){var r=t;if(t.type===\"click\"){Object.defineProperty(r,\"target\",{writable:!0}),Object.defineProperty(r,\"currentTarget\",{writable:!0}),r.target=e,r.currentTarget=e;var a=e.value;e.value=\"\",n(r),e.value=a;return}n(r)}}function NA(e,t,n){var r;return Se(e,(r={},V(r,\"\".concat(e,\"-sm\"),t===\"small\"),V(r,\"\".concat(e,\"-lg\"),t===\"large\"),V(r,\"\".concat(e,\"-disabled\"),n),r))}var Jn=G({name:\"AInput\",inheritAttrs:!1,props:P({},Vf),setup:function(){return{configProvider:ve(\"configProvider\",St),removePasswordTimeout:void 0,input:null,clearableInput:null}},data:function(){var t=this.$props,n=typeof t.value==\"undefined\"?t.defaultValue:t.value;return{stateValue:typeof n==\"undefined\"?\"\":n,isFocused:!1}},watch:{value:function(t){this.stateValue=t}},mounted:function(){var t=this;Ne(function(){t.clearPasswordValueAttribute()})},beforeUnmount:function(){this.removePasswordTimeout&&clearTimeout(this.removePasswordTimeout)},methods:{handleInputFocus:function(t){this.isFocused=!0,this.onFocus&&this.onFocus(t)},handleInputBlur:function(t){this.isFocused=!1,this.onBlur&&this.onBlur(t)},focus:function(){this.input.focus()},blur:function(){this.input.blur()},select:function(){this.input.select()},saveClearableInput:function(t){this.clearableInput=t},saveInput:function(t){this.input=t},setValue:function(t,n){this.stateValue!==t&&(vt(this,\"value\")?this.$forceUpdate():this.stateValue=t,Ne(function(){n&&n()}))},triggerChange:function(t){this.$emit(\"update:value\",t.target.value),this.$emit(\"change\",t),this.$emit(\"input\",t)},handleReset:function(t){var n=this;this.setValue(\"\",function(){n.focus()}),zv(this.input,t,this.triggerChange)},renderInput:function(t,n){var r=n.addonBefore,a=n.addonAfter,o=bn(this.$props,[\"prefixCls\",\"onPressEnter\",\"addonBefore\",\"addonAfter\",\"prefix\",\"suffix\",\"allowClear\",\"defaultValue\",\"lazy\",\"size\",\"inputPrefixCls\",\"loading\"]),i=this.handleKeyDown,l=this.handleChange,s=this.handleInputFocus,c=this.handleInputBlur,d=this.size,f=this.disabled,p=this.$attrs,v=P(P(P({},o),p),{onKeydown:i,class:Se(NA(t,d,f),V({},p.class,p.class&&!r&&!a)),ref:this.saveInput,key:\"ant-input\",onInput:l,onChange:l,onFocus:s,onBlur:c});v.autofocus||delete v.autofocus;var m=g(\"input\",v,null);return at(m,[[Mi]])},clearPasswordValueAttribute:function(){var t=this;this.removePasswordTimeout=setTimeout(function(){t.input&&t.input.getAttribute&&t.input.getAttribute(\"type\")===\"password\"&&t.input.hasAttribute(\"value\")&&t.input.removeAttribute(\"value\")})},handleChange:function(t){var n=t.target,r=n.value,a=n.composing,o=n.isComposing;(o||a)&&this.lazy||this.stateValue===r||(this.setValue(r,this.clearPasswordValueAttribute),zv(this.input,t,this.triggerChange))},handleKeyDown:function(t){t.keyCode===13&&this.$emit(\"pressEnter\",t),this.$emit(\"keydown\",t)}},render:function(){var t=this.$props.prefixCls,n=this.$data,r=n.stateValue,a=n.isFocused,o=this.configProvider.getPrefixCls,i=o(\"input\",t),l=We(this,\"addonAfter\"),s=We(this,\"addonBefore\"),c=We(this,\"suffix\"),d=We(this,\"prefix\"),f=P(P(P({},this.$attrs),Qe(this)),{prefixCls:i,inputType:\"input\",value:IA(r),element:this.renderInput(i,{addonAfter:l,addonBefore:s}),handleReset:this.handleReset,addonAfter:l,addonBefore:s,suffix:c,prefix:d,isFocused:a});return g(MA,le(le({},f),{},{ref:this.saveClearableInput}),null)}}),AA=G({name:\"AInputGroup\",props:{prefixCls:u.string,size:u.oneOf(rt(\"small\",\"large\",\"default\")),compact:u.looseBool},setup:function(){return{configProvider:ve(\"configProvider\",St)}},computed:{classes:function(){var t,n=this.prefixCls,r=this.size,a=this.compact,o=a===void 0?!1:a,i=this.configProvider,l=i.getPrefixCls,s=l(\"input-group\",n);return t={},V(t,\"\".concat(s),!0),V(t,\"\".concat(s,\"-lg\"),r===\"large\"),V(t,\"\".concat(s,\"-sm\"),r===\"small\"),V(t,\"\".concat(s,\"-compact\"),o),t}},render:function(){return g(\"span\",{class:this.classes},[ht(this)])}}),zy=/iPhone/i,QP=/iPod/i,e3=/iPad/i,Hy=/\\bAndroid(?:.+)Mobile\\b/i,t3=/Android/i,Ks=/\\bAndroid(?:.+)SD4930UR\\b/i,$h=/\\bAndroid(?:.+)(?:KF[A-Z]{2,4})\\b/i,Go=/Windows Phone/i,n3=/\\bWindows(?:.+)ARM\\b/i,r3=/BlackBerry/i,a3=/BB10/i,o3=/Opera Mini/i,i3=/\\b(CriOS|Chrome)(?:.+)Mobile/i,l3=/Mobile(?:.+)Firefox\\b/i;function Ht(e,t){return e.test(t)}function s3(e){var t=e||(typeof navigator!=\"undefined\"?navigator.userAgent:\"\"),n=t.split(\"[FBAN\");if(typeof n[1]!=\"undefined\"){var r=n,a=fn(r,1);t=a[0]}if(n=t.split(\"Twitter\"),typeof n[1]!=\"undefined\"){var o=n,i=fn(o,1);t=i[0]}var l={apple:{phone:Ht(zy,t)&&!Ht(Go,t),ipod:Ht(QP,t),tablet:!Ht(zy,t)&&Ht(e3,t)&&!Ht(Go,t),device:(Ht(zy,t)||Ht(QP,t)||Ht(e3,t))&&!Ht(Go,t)},amazon:{phone:Ht(Ks,t),tablet:!Ht(Ks,t)&&Ht($h,t),device:Ht(Ks,t)||Ht($h,t)},android:{phone:!Ht(Go,t)&&Ht(Ks,t)||!Ht(Go,t)&&Ht(Hy,t),tablet:!Ht(Go,t)&&!Ht(Ks,t)&&!Ht(Hy,t)&&(Ht($h,t)||Ht(t3,t)),device:!Ht(Go,t)&&(Ht(Ks,t)||Ht($h,t)||Ht(Hy,t)||Ht(t3,t))||Ht(/\\bokhttp\\b/i,t)},windows:{phone:Ht(Go,t),tablet:Ht(n3,t),device:Ht(Go,t)||Ht(n3,t)},other:{blackberry:Ht(r3,t),blackberry10:Ht(a3,t),opera:Ht(o3,t),firefox:Ht(l3,t),chrome:Ht(i3,t),device:Ht(r3,t)||Ht(a3,t)||Ht(o3,t)||Ht(l3,t)||Ht(i3,t)},any:null,phone:null,tablet:null};return l.any=l.apple.device||l.android.device||l.windows.device||l.other.device,l.phone=l.apple.phone||l.android.phone||l.windows.phone,l.tablet=l.apple.tablet||l.android.tablet||l.windows.tablet,l}var z$e=P(P({},s3()),{isMobile:s3}),H$e=z$e,jy={transitionstart:{transition:\"transitionstart\",WebkitTransition:\"webkitTransitionStart\",MozTransition:\"mozTransitionStart\",OTransition:\"oTransitionStart\",msTransition:\"MSTransitionStart\"},animationstart:{animation:\"animationstart\",WebkitAnimation:\"webkitAnimationStart\",MozAnimation:\"mozAnimationStart\",OAnimation:\"oAnimationStart\",msAnimation:\"MSAnimationStart\"}},Ky={transitionend:{transition:\"transitionend\",WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"mozTransitionEnd\",OTransition:\"oTransitionEnd\",msTransition:\"MSTransitionEnd\"},animationend:{animation:\"animationend\",WebkitAnimation:\"webkitAnimationEnd\",MozAnimation:\"mozAnimationEnd\",OAnimation:\"oAnimationEnd\",msAnimation:\"MSAnimationEnd\"}},cu=[],du=[];function j$e(){var e=document.createElement(\"div\"),t=e.style;\"AnimationEvent\"in window||(delete jy.animationstart.animation,delete Ky.animationend.animation),\"TransitionEvent\"in window||(delete jy.transitionstart.transition,delete Ky.transitionend.transition);function n(r,a){for(var o in r)if(r.hasOwnProperty(o)){var i=r[o];for(var l in i)if(l in t){a.push(i[l]);break}}}n(jy,cu),n(Ky,du)}typeof window!=\"undefined\"&&typeof document!=\"undefined\"&&j$e();function u3(e,t,n){e.addEventListener(t,n,!1)}function c3(e,t,n){e.removeEventListener(t,n,!1)}var K$e={startEvents:cu,addStartEventListener:function(t,n){if(cu.length===0){window.setTimeout(n,0);return}cu.forEach(function(r){u3(t,r,n)})},removeStartEventListener:function(t,n){cu.length!==0&&cu.forEach(function(r){c3(t,r,n)})},endEvents:du,addEndEventListener:function(t,n){if(du.length===0){window.setTimeout(n,0);return}du.forEach(function(r){u3(t,r,n)})},removeEndEventListener:function(t,n){du.length!==0&&du.forEach(function(r){c3(t,r,n)})}},si=K$e,Li;function d3(e){return!e||e.offsetParent===null}function W$e(e){var t=(e||\"\").match(/rgba?\\((\\d*), (\\d*), (\\d*)(, [\\.\\d]*)?\\)/);return t&&t[1]&&t[2]&&t[3]?!(t[1]===t[2]&&t[2]===t[3]):!0}var C2=G({name:\"Wave\",props:[\"insertExtraNode\"],setup:function(){var t=ve(\"configProvider\",St);return{configProvider:t}},mounted:function(){var t=this;Ne(function(){var n=Sn(t);n.nodeType===1&&(t.instance=t.bindAnimationEvent(n))})},beforeUnmount:function(){this.instance&&this.instance.cancel(),this.clickWaveTimeoutId&&clearTimeout(this.clickWaveTimeoutId)},methods:{onClick:function(t,n){if(!(!t||d3(t)||t.className.indexOf(\"-leave\")>=0)){var r=this.$props.insertExtraNode;this.extraNode=document.createElement(\"div\");var a=this.extraNode;a.className=\"ant-click-animating-node\";var o=this.getAttributeName();t.removeAttribute(o),t.setAttribute(o,\"true\"),Li=Li||document.createElement(\"style\"),n&&n!==\"#ffffff\"&&n!==\"rgb(255, 255, 255)\"&&W$e(n)&&!/rgba\\(\\d*, \\d*, \\d*, 0\\)/.test(n)&&n!==\"transparent\"&&(this.csp&&this.csp.nonce&&(Li.nonce=this.csp.nonce),a.style.borderColor=n,Li.innerHTML=`\n        [ant-click-animating-without-extra-node='true']::after, .ant-click-animating-node {\n          --antd-wave-shadow-color: `.concat(n,`;\n        }`),document.body.contains(Li)||document.body.appendChild(Li)),r&&t.appendChild(a),si.addStartEventListener(t,this.onTransitionStart),si.addEndEventListener(t,this.onTransitionEnd)}},onTransitionStart:function(t){if(!this._.isUnmounted){var n=Sn(this);!t||t.target!==n||this.animationStart||this.resetEffect(n)}},onTransitionEnd:function(t){!t||t.animationName!==\"fadeEffect\"||this.resetEffect(t.target)},getAttributeName:function(){var t=this.$props.insertExtraNode;return t?\"ant-click-animating\":\"ant-click-animating-without-extra-node\"},bindAnimationEvent:function(t){var n=this;if(!(!t||!t.getAttribute||t.getAttribute(\"disabled\")||t.className.indexOf(\"disabled\")>=0)){var r=function(o){if(!(o.target.tagName===\"INPUT\"||d3(o.target))){n.resetEffect(t);var i=getComputedStyle(t).getPropertyValue(\"border-top-color\")||getComputedStyle(t).getPropertyValue(\"border-color\")||getComputedStyle(t).getPropertyValue(\"background-color\");n.clickWaveTimeoutId=window.setTimeout(function(){return n.onClick(t,i)},0),en.cancel(n.animationStartId),n.animationStart=!0,n.animationStartId=en(function(){n.animationStart=!1},10)}};return t.addEventListener(\"click\",r,!0),{cancel:function(){t.removeEventListener(\"click\",r,!0)}}}},resetEffect:function(t){if(!(!t||t===this.extraNode||!(t instanceof Element))){var n=this.$props.insertExtraNode,r=this.getAttributeName();t.setAttribute(r,\"false\"),Li&&(Li.innerHTML=\"\"),n&&this.extraNode&&t.contains(this.extraNode)&&t.removeChild(this.extraNode),si.removeStartEventListener(t,this.onTransitionStart),si.removeEndEventListener(t,this.onTransitionEnd)}}},render:function(){var t,n,r=this.configProvider.csp;return r&&(this.csp=r),(n=(t=this.$slots).default)===null||n===void 0?void 0:n.call(t)[0]}}),U$e=rt(\"default\",\"primary\",\"ghost\",\"dashed\",\"link\",\"text\"),Y$e=rt(\"circle\",\"round\"),q$e=rt(\"submit\",\"button\",\"reset\");function w2(e){return e===\"danger\"?{danger:!0}:{type:e}}var G$e=function(){return{prefixCls:u.string,type:u.oneOf(U$e),htmlType:u.oneOf(q$e).def(\"button\"),shape:u.oneOf(Y$e),size:{type:String},loading:{type:[Boolean,Object],default:function(){return!1}},disabled:u.looseBool,ghost:u.looseBool,block:u.looseBool,danger:u.looseBool,icon:u.VNodeChild,href:u.string,target:u.string,title:u.string,onClick:{type:Function}}},Hv=G$e,uf=function(e,t,n){Ua(e,\"[ant-design-vue: \".concat(t,\"] \").concat(n))},f3=/^[\\u4e00-\\u9fa5]{2}$/,h3=f3.test.bind(f3),X$e=Hv();function Oh(e){return e===\"text\"||e===\"link\"}var Cr=G({name:\"AButton\",inheritAttrs:!1,__ANT_BUTTON:!0,props:X$e,slots:[\"icon\"],emits:[\"click\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.emit,i=Wt(\"btn\",t),l=i.prefixCls,s=i.autoInsertSpaceInButton,c=i.direction,d=H(null),f=H(void 0),p=!1,v=H(!1),m=H(!1),y=x(function(){return s.value!==!1}),b=x(function(){return kt(t.loading)===\"object\"&&t.loading.delay?t.loading.delay||!0:!!t.loading});ce(b,function($){clearTimeout(f.value),typeof b.value==\"number\"?f.value=window.setTimeout(function(){v.value=$},b.value):v.value=$},{immediate:!0});var C=x(function(){var $,O=t.type,T=t.shape,_=t.size,I=t.ghost,L=t.block,j=t.danger,F=l.value,N=\"\";switch(_){case\"large\":N=\"lg\";break;case\"small\":N=\"sm\";break}return $={},V($,\"\".concat(F),!0),V($,\"\".concat(F,\"-\").concat(O),O),V($,\"\".concat(F,\"-\").concat(T),T),V($,\"\".concat(F,\"-\").concat(N),N),V($,\"\".concat(F,\"-loading\"),v.value),V($,\"\".concat(F,\"-background-ghost\"),I&&!Oh(O)),V($,\"\".concat(F,\"-two-chinese-chars\"),m.value&&y.value),V($,\"\".concat(F,\"-block\"),L),V($,\"\".concat(F,\"-dangerous\"),!!j),V($,\"\".concat(F,\"-rtl\"),c.value===\"rtl\"),$}),S=function(){var O=d.value;if(!(!O||s.value===!1)){var T=O.textContent;p&&h3(T)?m.value||(m.value=!0):m.value&&(m.value=!1)}},w=function(O){if(v.value||t.disabled){O.preventDefault();return}o(\"click\",O)},k=function(O,T){var _=T?\" \":\"\";if(O.type===Fo){var I=O.children.trim();return h3(I)&&(I=I.split(\"\").join(_)),g(\"span\",null,[I])}return O};return Wn(function(){uf(!(t.ghost&&Oh(t.type)),\"Button\",\"`link` or `text` button can't be a `ghost` button.\")}),et(S),ur(S),Lt(function(){f.value&&clearTimeout(f.value)}),function(){var $=Un(jn(r,t)),O=jn(r,t,\"icon\");p=$.length===1&&!O&&!Oh(t.type);var T=t.type,_=t.htmlType,I=t.disabled,L=t.href,j=t.title,F=t.target,N=v.value?\"loading\":O,D=P(P({},a),{title:j,disabled:I,class:[C.value,a.class,V({},\"\".concat(l.value,\"-icon-only\"),$.length===0&&!!N)],onClick:w}),z=v.value?g(co,null,null):O,B=$.map(function(E){return k(E,p&&y.value)});if(L!==void 0)return g(\"a\",le(le({},D),{},{href:L,target:F,ref:d}),[z,B]);var M=g(\"button\",le(le({},D),{},{ref:d,type:_}),[z,B]);return Oh(T)?M:g(C2,{ref:\"wave\"},{default:function(){return[M]}})}}}),Z$e={prefixCls:u.string,size:{type:String}},jv=G({name:\"AButtonGroup\",props:Z$e,setup:function(t,n){var r=n.slots,a=Wt(\"btn-group\",t),o=a.prefixCls,i=a.direction,l=x(function(){var s,c=t.size,d=\"\";switch(c){case\"large\":d=\"lg\";break;case\"small\":d=\"sm\";break}return s={},V(s,\"\".concat(o.value),!0),V(s,\"\".concat(o.value,\"-\").concat(d),d),V(s,\"\".concat(o.value,\"-rtl\"),i.value===\"rtl\"),s});return function(){var s;return g(\"div\",{class:l.value},[Un((s=r.default)===null||s===void 0?void 0:s.call(r))])}}});Cr.Group=jv;Cr.install=function(e){return e.component(Cr.name,Cr),e.component(jv.name,jv),e};var J$e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},DA=G({name:\"AInputSearch\",inheritAttrs:!1,props:P(P({},Vf),{enterButton:u.VNodeChild,onSearch:u.func}),setup:function(){return{configProvider:ve(\"configProvider\",St),input:null}},methods:{saveInput:function(t){this.input=t},handleChange:function(t){this.$emit(\"update:value\",t.target.value),t&&t.target&&t.type===\"click\"&&this.$emit(\"search\",t.target.value,t),this.$emit(\"change\",t)},handleSearch:function(t){this.loading||this.disabled||(this.$emit(\"search\",this.input.stateValue,t),H$e.tablet||this.input.focus())},focus:function(){this.input.focus()},blur:function(){this.input.blur()},renderLoading:function(t){var n=this.$props.size,r=We(this,\"enterButton\");return r=r||r===\"\",r?g(Cr,{class:\"\".concat(t,\"-button\"),type:\"primary\",size:n,key:\"enterButton\"},{default:function(){return[g(co,null,null)]}}):g(co,{class:\"\".concat(t,\"-icon\"),key:\"loadingIcon\"},null)},renderSuffix:function(t){var n=this.loading,r=We(this,\"suffix\"),a=We(this,\"enterButton\");if(a=a||a===\"\",n&&!a)return[r,this.renderLoading(t)];if(a)return r;var o=g(Vv,{class:\"\".concat(t,\"-icon\"),key:\"searchIcon\",onClick:this.handleSearch},null);return r?[r,o]:o},renderAddonAfter:function(t){var n=this.size,r=this.disabled,a=this.loading,o=\"\".concat(t,\"-button\"),i=We(this,\"enterButton\");i=i||i===\"\";var l=We(this,\"addonAfter\");if(a&&i)return[this.renderLoading(t),l];if(!i)return l;var s=Array.isArray(i)?i[0]:i,c,d=s.type&&bc(s.type)&&s.type.__ANT_BUTTON;return s.tagName===\"button\"||d?c=Ot(s,P(P({key:\"enterButton\",class:d?o:\"\"},d?{size:n}:{}),{onClick:this.handleSearch})):c=g(Cr,{class:o,type:\"primary\",size:n,disabled:r,key:\"enterButton\",onClick:this.handleSearch},{default:function(){return[i===!0||i===\"\"?g(Vv,null,null):i]}}),l?[c,l]:c}},render:function(){var t=P(P({},Qe(this)),this.$attrs),n=t.prefixCls,r=t.inputPrefixCls,a=t.size,o=t.class,i=J$e(t,[\"prefixCls\",\"inputPrefixCls\",\"size\",\"class\"]);delete i.onSearch,delete i.loading,delete i.enterButton,delete i.addonBefore,delete i[\"onUpdate:value\"];var l=this.configProvider.getPrefixCls,s=l(\"input-search\",n),c=l(\"input\",r),d=We(this,\"enterButton\"),f=We(this,\"addonBefore\");d=d||d===\"\";var p;if(d){var v;p=Se(s,o,(v={},V(v,\"\".concat(s,\"-enter-button\"),!!d),V(v,\"\".concat(s,\"-\").concat(a),!!a),v))}else p=Se(s,o);var m=P(P({},i),{prefixCls:c,size:a,suffix:this.renderSuffix(s),prefix:We(this,\"prefix\"),addonAfter:this.renderAddonAfter(s),addonBefore:f,class:p,onPressEnter:this.handleSearch,onChange:this.handleChange});return g(Jn,le(le({},m),{},{ref:this.saveInput}),null)}}),Q$e=`\n  min-height:0 !important;\n  max-height:none !important;\n  height:0 !important;\n  visibility:hidden !important;\n  overflow:hidden !important;\n  position:absolute !important;\n  z-index:-1000 !important;\n  top:0 !important;\n  right:0 !important\n`,e4e=[\"letter-spacing\",\"line-height\",\"padding-top\",\"padding-bottom\",\"font-family\",\"font-weight\",\"font-size\",\"font-variant\",\"text-rendering\",\"text-transform\",\"width\",\"text-indent\",\"padding-left\",\"padding-right\",\"border-width\",\"box-sizing\"],Wy={},Co;function t4e(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n=e.getAttribute(\"id\")||e.getAttribute(\"data-reactid\")||e.getAttribute(\"name\");if(t&&Wy[n])return Wy[n];var r=window.getComputedStyle(e),a=r.getPropertyValue(\"box-sizing\")||r.getPropertyValue(\"-moz-box-sizing\")||r.getPropertyValue(\"-webkit-box-sizing\"),o=parseFloat(r.getPropertyValue(\"padding-bottom\"))+parseFloat(r.getPropertyValue(\"padding-top\")),i=parseFloat(r.getPropertyValue(\"border-bottom-width\"))+parseFloat(r.getPropertyValue(\"border-top-width\")),l=e4e.map(function(c){return\"\".concat(c,\":\").concat(r.getPropertyValue(c))}).join(\";\"),s={sizingStyle:l,paddingSize:o,borderSize:i,boxSizing:a};return t&&n&&(Wy[n]=s),s}function n4e(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:null,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:null;Co||(Co=document.createElement(\"textarea\"),document.body.appendChild(Co)),e.getAttribute(\"wrap\")?Co.setAttribute(\"wrap\",e.getAttribute(\"wrap\")):Co.removeAttribute(\"wrap\");var a=t4e(e,t),o=a.paddingSize,i=a.borderSize,l=a.boxSizing,s=a.sizingStyle;Co.setAttribute(\"style\",\"\".concat(s,\";\").concat(Q$e)),Co.value=e.value||e.placeholder||\"\";var c=Number.MIN_SAFE_INTEGER,d=Number.MAX_SAFE_INTEGER,f=Co.scrollHeight,p;if(l===\"border-box\"?f+=i:l===\"content-box\"&&(f-=o),n!==null||r!==null){Co.value=\" \";var v=Co.scrollHeight-o;n!==null&&(c=v*n,l===\"border-box\"&&(c=c+o+i),f=Math.max(c,f)),r!==null&&(d=v*r,l===\"border-box\"&&(d=d+o+i),p=f>d?\"\":\"hidden\",f=Math.min(d,f))}return{height:\"\".concat(f,\"px\"),minHeight:\"\".concat(c,\"px\"),maxHeight:\"\".concat(d,\"px\"),overflowY:p,resize:\"none\"}}var Uy=0,p3=1,r4e=2,a4e=P(P({},Vf),{autosize:{type:[Boolean,Object],default:void 0},autoSize:{type:[Boolean,Object],default:void 0},onResize:u.func}),o4e=G({name:\"ResizableTextArea\",mixins:[nt],inheritAttrs:!1,props:a4e,setup:function(){return{nextFrameActionId:void 0,textArea:null,resizeFrameId:void 0}},data:function(){return{textareaStyles:{},resizeStatus:Uy}},watch:{value:function(){var t=this;Ne(function(){t.resizeTextarea()})}},mounted:function(){this.resizeTextarea()},beforeUnmount:function(){en.cancel(this.nextFrameActionId),en.cancel(this.resizeFrameId)},methods:{saveTextArea:function(t){this.textArea=t},handleResize:function(t){var n=this.$data.resizeStatus;n===Uy&&this.$emit(\"resize\",t)},resizeOnNextFrame:function(){en.cancel(this.nextFrameActionId),this.nextFrameActionId=en(this.resizeTextarea)},resizeTextarea:function(){var t=this,n=this.$props.autoSize||this.$props.autosize;if(!(!n||!this.textArea)){var r=n.minRows,a=n.maxRows,o=n4e(this.textArea,!1,r,a);this.setState({textareaStyles:o,resizeStatus:p3},function(){en.cancel(t.resizeFrameId),t.resizeFrameId=en(function(){t.setState({resizeStatus:r4e},function(){t.resizeFrameId=en(function(){t.setState({resizeStatus:Uy}),t.fixFirefoxAutoScroll()})})})})}},fixFirefoxAutoScroll:function(){try{if(document.activeElement===this.textArea){var t=this.textArea.selectionStart,n=this.textArea.selectionEnd;this.textArea.setSelectionRange(t,n)}}catch{}},renderTextArea:function(){var t=this,n=P(P({},Qe(this)),this.$attrs),r=n.prefixCls,a=n.autoSize,o=n.autosize,i=n.disabled,l=n.class,s=this.$data,c=s.textareaStyles,d=s.resizeStatus;on(o===void 0,\"Input.TextArea\",\"autosize is deprecated, please use autoSize instead.\");var f=bn(n,[\"prefixCls\",\"onPressEnter\",\"autoSize\",\"autosize\",\"defaultValue\",\"allowClear\",\"type\",\"lazy\"]),p=Se(r,l,V({},\"\".concat(r,\"-disabled\"),i));\"value\"in f&&(f.value=f.value||\"\");var v=P(P(P({},n.style),c),d===p3?{overflowX:\"hidden\",overflowY:\"hidden\"}:null),m=P(P({},f),{style:v,class:p});return m.autofocus||delete m.autofocus,g(zo,{onResize:this.handleResize,disabled:!(a||o)},{default:function(){return[at(g(\"textarea\",le(le({},m),{},{ref:t.saveTextArea}),null),[[Mi]])]}})}},render:function(){return this.renderTextArea()}}),i4e=o4e,l4e=P(P({},Vf),{autosize:an(u.oneOfType([Object,Boolean])),autoSize:an(u.oneOfType([Object,Boolean])),showCount:u.looseBool,onCompositionstart:u.func,onCompositionend:u.func}),S2=G({name:\"ATextarea\",inheritAttrs:!1,props:P({},l4e),setup:function(){return{configProvider:ve(\"configProvider\",St),resizableTextArea:null,clearableInput:null}},data:function(){var t=typeof this.value==\"undefined\"?this.defaultValue:this.value;return{stateValue:typeof t==\"undefined\"?\"\":t}},watch:{value:function(t){this.stateValue=t}},mounted:function(){Ne(function(){})},methods:{setValue:function(t,n){vt(this,\"value\")?this.$forceUpdate():this.stateValue=t,Ne(function(){n&&n()})},handleKeyDown:function(t){t.keyCode===13&&this.$emit(\"pressEnter\",t),this.$emit(\"keydown\",t)},triggerChange:function(t){this.$emit(\"update:value\",t.target.value),this.$emit(\"change\",t),this.$emit(\"input\",t)},handleChange:function(t){var n=this,r=t.target,a=r.value,o=r.composing,i=r.isComposing;(i||o)&&this.lazy||this.stateValue===a||(this.setValue(t.target.value,function(){var l;(l=n.resizableTextArea)===null||l===void 0||l.resizeTextarea()}),zv(this.resizableTextArea.textArea,t,this.triggerChange))},focus:function(){this.resizableTextArea.textArea.focus()},blur:function(){this.resizableTextArea.textArea.blur()},saveTextArea:function(t){this.resizableTextArea=t},saveClearableInput:function(t){this.clearableInput=t},handleReset:function(t){var n=this;this.setValue(\"\",function(){n.resizableTextArea.renderTextArea(),n.focus()}),zv(this.resizableTextArea.textArea,t,this.triggerChange)},renderTextArea:function(t){var n=Qe(this),r=this.$attrs,a=r.style,o=r.class,i=P(P(P({},n),this.$attrs),{style:!n.showCount&&a,class:!n.showCount&&o,showCount:null,prefixCls:t,onInput:this.handleChange,onChange:this.handleChange,onKeydown:this.handleKeyDown});return g(i4e,le(le({},i),{},{ref:this.saveTextArea}),null)}},render:function(){var t=this.stateValue,n=this.prefixCls,r=this.maxlength,a=this.showCount,o=this.$attrs,i=o.style,l=o.class,s=this.configProvider.getPrefixCls,c=s(\"input\",n),d=IA(t),f=Number(r)>0;d=f?d.slice(0,r):d;var p=P(P(P({},Qe(this)),this.$attrs),{prefixCls:c,inputType:\"text\",element:this.renderTextArea(c),handleReset:this.handleReset}),v=g(MA,le(le({},p),{},{value:d,ref:this.saveClearableInput}),null);if(a){var m=Je(d).length,y=\"\".concat(m).concat(f?\" / \".concat(r):\"\");v=g(\"div\",{class:Se(\"\".concat(c,\"-textarea\"),\"\".concat(c,\"-textarea-show-count\"),l),style:i,\"data-count\":y},[v])}return v}}),s4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z\"}}]},name:\"eye\",theme:\"outlined\"},u4e=s4e;function v3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){c4e(e,a,n[a])})}return e}function c4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var k2=function(t,n){var r=v3({},t,n.attrs);return g(Et,v3({},r,{icon:u4e}),null)};k2.displayName=\"EyeOutlined\";k2.inheritAttrs=!1;var RA=k2,d4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z\"}},{tag:\"path\",attrs:{d:\"M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z\"}}]},name:\"eye-invisible\",theme:\"outlined\"},f4e=d4e;function m3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){h4e(e,a,n[a])})}return e}function h4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var $2=function(t,n){var r=m3({},t,n.attrs);return g(Et,m3({},r,{icon:f4e}),null)};$2.displayName=\"EyeInvisibleOutlined\";$2.inheritAttrs=!1;var p4e=$2,v4e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},m4e={click:\"onClick\",hover:\"onMouseover\"},LA=G({name:\"AInputPassword\",mixins:[nt],inheritAttrs:!1,props:P(P({},Vf),{prefixCls:u.string,inputPrefixCls:u.string,action:u.string.def(\"click\"),visibilityToggle:u.looseBool.def(!0),iconRender:u.func.def(function(e){return g(e?RA:p4e,null,null)})}),setup:function(){return{input:null,configProvider:ve(\"configProvider\",St)}},data:function(){return{visible:!1}},methods:{saveInput:function(t){this.input=t},focus:function(){this.input.focus()},blur:function(){this.input.blur()},onVisibleChange:function(){this.disabled||this.setState({visible:!this.visible})},getIcon:function(t){var n,r=this.$props.action,a=m4e[r]||\"\",o=this.$slots.iconRender||this.$props.iconRender,i=o(this.visible),l=(n={},V(n,a,this.onVisibleChange),V(n,\"onMousedown\",function(c){c.preventDefault()}),V(n,\"onMouseup\",function(c){c.preventDefault()}),V(n,\"class\",\"\".concat(t,\"-icon\")),V(n,\"key\",\"passwordIcon\"),n);return Ot(i,l)}},render:function(){var t=Qe(this),n=t.prefixCls,r=t.inputPrefixCls,a=t.size;t.suffix,t.action;var o=t.visibilityToggle;t.iconRender;var i=v4e(t,[\"prefixCls\",\"inputPrefixCls\",\"size\",\"suffix\",\"action\",\"visibilityToggle\",\"iconRender\"]),l=this.$attrs.class,s=this.configProvider.getPrefixCls,c=s(\"input\",r),d=s(\"input-password\",n),f=o&&this.getIcon(d),p=Se(d,l,V({},\"\".concat(d,\"-\").concat(a),!!a)),v=P(P(P(P({},i),{prefixCls:c,size:a,suffix:f,prefix:We(this,\"prefix\"),addonAfter:We(this,\"addonAfter\"),addonBefore:We(this,\"addonBefore\")}),this.$attrs),{type:this.visible?\"text\":\"password\",class:p,ref:\"input\"});return g(Jn,le(le({},v),{},{ref:this.saveInput}),null)}});Jn.Group=AA;Jn.Search=DA;Jn.TextArea=S2;Jn.Password=LA;Jn.install=function(e){return e.component(Jn.name,Jn),e.component(Jn.Group.name,Jn.Group),e.component(Jn.Search.name,Jn.Search),e.component(Jn.TextArea.name,Jn.TextArea),e.component(Jn.Password.name,Jn.Password),e};var O2=function(){return null};O2.isSelectOption=!0;O2.displayName=\"AAutoCompleteOption\";var jp=O2,P2=function(){return null};P2.isSelectOptGroup=!0;P2.displayName=\"AAutoCompleteOptGroup\";var FA=P2;function g4e(e){var t,n;return((t=e==null?void 0:e.type)===null||t===void 0?void 0:t.isSelectOption)||((n=e==null?void 0:e.type)===null||n===void 0?void 0:n.isSelectOptGroup)}var y4e=P(P({},Sg()),{dataSource:u.array,dropdownMenuStyle:u.style,optionLabelProp:u.string,dropdownMatchSelectWidth:u.looseBool}),b4e=jp,C4e=FA,Hi=G({name:\"AAutoComplete\",inheritAttrs:!1,props:P(P({},y4e),{prefixCls:u.string,showSearch:u.looseBool,transitionName:u.string.def(\"slide-up\"),choiceTransitionName:u.string.def(\"zoom\"),autofocus:u.looseBool,backfill:u.looseBool,optionLabelProp:u.string.def(\"children\"),filterOption:u.oneOfType([u.looseBool,u.func]).def(!1),defaultActiveFirstOption:u.looseBool.def(!0)}),emits:[\"change\",\"select\",\"focus\",\"blur\"],Option:jp,OptGroup:FA,setup:function(t,n){var r=n.slots;return on(!(t.dataSource!==void 0||\"dataSource\"in r),\"AutoComplete\",\"`dataSource` is deprecated, please use `options` instead.\"),{configProvider:ve(\"configProvider\",St),popupRef:null,select:null}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},methods:{savePopupRef:function(t){this.popupRef=t},saveSelect:function(t){this.select=t},getInputElement:function(){var t=ht(this),n=t.length?t[0]:g(Jn,{lazy:!1},null);return n},focus:function(){this.select&&this.select.focus()},blur:function(){this.select&&this.select.blur()}},render:function(){var t,n=this.size,r=this.prefixCls,a=this.dataSource,o,i=this.configProvider.getPrefixCls,l=i(\"select\",r),s=this.$attrs.class,c=(t={},V(t,s,!!s),V(t,\"\".concat(l,\"-lg\"),n===\"large\"),V(t,\"\".concat(l,\"-sm\"),n===\"small\"),V(t,\"\".concat(l,\"-show-search\"),!0),V(t,\"\".concat(l,\"-auto-complete\"),!0),t),d=ht(this,\"dataSource\");\"options\"in this.$slots&&(d=ht(this,\"options\")),d.length&&g4e(d[0])?o=d:o=a?a.map(function(p){if(zn(p))return p;switch(kt(p)){case\"string\":return g(jp,{key:p,value:p},{default:function(){return[p]}});case\"object\":return g(jp,{key:p.value,value:p.value},{default:function(){return[p.text]}});default:throw new Error(\"AutoComplete[dataSource] only supports type `string[] | Object[]`.\")}}):[];var f=P(P(P({},bn(Qe(this),[\"dataSource\",\"optionLabelProp\"])),this.$attrs),{mode:dl.SECRET_COMBOBOX_MODE_DO_NOT_USE,getInputElement:this.getInputElement,notFoundContent:We(this,\"notFoundContent\"),class:c,ref:this.saveSelect});return g(dl,f,{default:function(){return[o]}})}});Hi.install=function(e){return e.component(Hi.name,Hi),e.component(Hi.Option.displayName,Hi.Option),e.component(Hi.OptGroup.displayName,Hi.OptGroup),e};var w4e=Hi,S4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z\"}},{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z\"}}]},name:\"check-circle\",theme:\"outlined\"},k4e=S4e;function g3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){$4e(e,a,n[a])})}return e}function $4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var T2=function(t,n){var r=g3({},t,n.attrs);return g(Et,g3({},r,{icon:k4e}),null)};T2.displayName=\"CheckCircleOutlined\";T2.inheritAttrs=!1;var x2=T2,O4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z\"}},{tag:\"path\",attrs:{d:\"M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z\"}}]},name:\"exclamation-circle\",theme:\"outlined\"},P4e=O4e;function y3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){T4e(e,a,n[a])})}return e}function T4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var _2=function(t,n){var r=y3({},t,n.attrs);return g(Et,y3({},r,{icon:P4e}),null)};_2.displayName=\"ExclamationCircleOutlined\";_2.inheritAttrs=!1;var E2=_2,x4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z\"}},{tag:\"path\",attrs:{d:\"M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z\"}}]},name:\"info-circle\",theme:\"outlined\"},_4e=x4e;function b3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){E4e(e,a,n[a])})}return e}function E4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var M2=function(t,n){var r=b3({},t,n.attrs);return g(Et,b3({},r,{icon:_4e}),null)};M2.displayName=\"InfoCircleOutlined\";M2.inheritAttrs=!1;var I2=M2,M4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z\"}},{tag:\"path\",attrs:{d:\"M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z\"}}]},name:\"close-circle\",theme:\"outlined\"},I4e=M4e;function C3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){N4e(e,a,n[a])})}return e}function N4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var N2=function(t,n){var r=C3({},t,n.attrs);return g(Et,C3({},r,{icon:I4e}),null)};N2.displayName=\"CloseCircleOutlined\";N2.inheritAttrs=!1;var A2=N2,A4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z\"}}]},name:\"check-circle\",theme:\"filled\"},D4e=A4e;function w3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){R4e(e,a,n[a])})}return e}function R4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var D2=function(t,n){var r=w3({},t,n.attrs);return g(Et,w3({},r,{icon:D4e}),null)};D2.displayName=\"CheckCircleFilled\";D2.inheritAttrs=!1;var zf=D2,L4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\"}}]},name:\"exclamation-circle\",theme:\"filled\"},F4e=L4e;function S3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){B4e(e,a,n[a])})}return e}function B4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var R2=function(t,n){var r=S3({},t,n.attrs);return g(Et,S3({},r,{icon:F4e}),null)};R2.displayName=\"ExclamationCircleFilled\";R2.inheritAttrs=!1;var Hf=R2,V4e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\"}}]},name:\"info-circle\",theme:\"filled\"},z4e=V4e;function k3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){H4e(e,a,n[a])})}return e}function H4e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var L2=function(t,n){var r=k3({},t,n.attrs);return g(Et,k3({},r,{icon:z4e}),null)};L2.displayName=\"InfoCircleFilled\";L2.inheritAttrs=!1;var BA=L2;function j4e(){}var K4e={success:zf,info:BA,error:Yr,warning:Hf},W4e={success:x2,info:I2,error:A2,warning:E2},U4e=rt(\"success\",\"info\",\"warning\",\"error\"),Y4e={type:u.oneOf(U4e),closable:u.looseBool,closeText:u.VNodeChild,message:u.VNodeChild,description:u.VNodeChild,afterClose:u.func.def(j4e),showIcon:u.looseBool,prefixCls:u.string,banner:u.looseBool,icon:u.VNodeChild,onClose:u.VNodeChild},q4e=G({name:\"AAlert\",inheritAttrs:!1,props:Y4e,emits:[\"close\"],setup:function(t,n){var r=n.slots,a=n.emit,o=n.attrs,i=n.expose,l=ve(\"configProvider\",St),s=H(!1),c=H(!1),d=H(),f=function(m){m.preventDefault();var y=d.value;y.style.height=\"\".concat(y.offsetHeight,\"px\"),y.style.height=\"\".concat(y.offsetHeight,\"px\"),s.value=!0,a(\"close\",m)},p=function(){var m;s.value=!1,c.value=!0,(m=t.afterClose)===null||m===void 0||m.call(t)};return i({animationEnd:p}),function(){var v,m=t.prefixCls,y=t.banner,b=l.getPrefixCls,C=b(\"alert\",m),S=t.closable,w=t.type,k=t.showIcon,$=jn(r,t,\"closeText\"),O=jn(r,t,\"description\"),T=jn(r,t,\"message\"),_=jn(r,t,\"icon\");k=y&&k===void 0?!0:k,w=y&&w===void 0?\"warning\":w||\"info\";var I=(O?W4e:K4e)[w]||null;$&&(S=!0);var L=Se(C,(v={},V(v,\"\".concat(C,\"-\").concat(w),!0),V(v,\"\".concat(C,\"-closing\"),s.value),V(v,\"\".concat(C,\"-with-description\"),!!O),V(v,\"\".concat(C,\"-no-icon\"),!k),V(v,\"\".concat(C,\"-banner\"),!!y),V(v,\"\".concat(C,\"-closable\"),S),v)),j=S?g(\"button\",{type:\"button\",onClick:f,class:\"\".concat(C,\"-close-icon\"),tabindex:0},[$?g(\"span\",{class:\"\".concat(C,\"-close-text\")},[$]):g(go,null,null)]):null,F=_&&(zn(_)?hr(_,{class:\"\".concat(C,\"-icon\")}):g(\"span\",{class:\"\".concat(C,\"-icon\")},[_]))||g(I,{class:\"\".concat(C,\"-icon\")},null),N=Lo(\"\".concat(C,\"-slide-up\"),{appear:!1,onAfterLeave:p});return c.value?null:g(no,N,{default:function(){return[at(g(\"div\",le(le({},o),{},{class:[o.class,L],\"data-show\":!s.value,ref:d}),[k?F:null,g(\"div\",{class:\"\".concat(C,\"-content\")},[g(\"div\",{class:\"\".concat(C,\"-message\")},[T]),g(\"div\",{class:\"\".concat(C,\"-description\")},[O])]),j]),[[_t,!s.value]])]}})}}}),G4e=kn(q4e),ws=[\"xxl\",\"xl\",\"lg\",\"md\",\"sm\",\"xs\"],Ph={xs:\"(max-width: 575px)\",sm:\"(min-width: 576px)\",md:\"(min-width: 768px)\",lg:\"(min-width: 992px)\",xl:\"(min-width: 1200px)\",xxl:\"(min-width: 1600px)\"},Tl=new Map,Yy=-1,Th={},X4e={matchHandlers:{},dispatch:function(t){return Th=t,Tl.forEach(function(n){return n(Th)}),Tl.size>=1},subscribe:function(t){return Tl.size||this.register(),Yy+=1,Tl.set(Yy,t),t(Th),Yy},unsubscribe:function(t){Tl.delete(t),Tl.size||this.unregister()},unregister:function(){var t=this;Object.keys(Ph).forEach(function(n){var r=Ph[n],a=t.matchHandlers[r];a==null||a.mql.removeListener(a==null?void 0:a.listener)}),Tl.clear()},register:function(){var t=this;Object.keys(Ph).forEach(function(n){var r=Ph[n],a=function(l){var s=l.matches;t.dispatch(P(P({},Th),V({},n,s)))},o=window.matchMedia(r);o.addListener(a),t.matchHandlers[r]={mql:o,listener:a},a(o)})}},lc=X4e;function F2(){var e=H({}),t=null;return et(function(){t=lc.subscribe(function(n){e.value=n})}),Wr(function(){lc.unsubscribe(t)}),e}var VA=Symbol(\"SizeProvider\"),Z4e=function(t){var n=ve(\"configProvider\",St),r=x(function(){return t.size||n.componentSize});return ot(VA,r),r},zA=function(t){var n=t?x(function(){return t.size}):ve(VA,x(function(){return\"default\"}));return n},J4e=Z4e,HA={prefixCls:u.string,shape:u.oneOf(rt(\"circle\",\"square\")).def(\"circle\"),size:{type:[Number,String,Object],default:function(){return\"default\"}},src:u.string,srcset:u.string,icon:u.VNodeChild,alt:u.string,gap:u.number,draggable:u.bool,loadError:{type:Function}},Q4e=G({name:\"AAvatar\",inheritAttrs:!1,props:HA,slots:[\"icon\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=H(!0),i=H(!1),l=H(1),s=H(null),c=H(null),d=Wt(\"avatar\",t),f=d.prefixCls,p=zA(),v=F2(),m=x(function(){if(kt(t.size)===\"object\"){var S=ws.find(function(k){return v.value[k]}),w=t.size[S];return w}}),y=function(w){return m.value?{width:\"\".concat(m.value,\"px\"),height:\"\".concat(m.value,\"px\"),lineHeight:\"\".concat(m.value,\"px\"),fontSize:\"\".concat(w?m.value/2:18,\"px\")}:{}},b=function(){if(!(!s.value||!c.value)){var w=s.value.offsetWidth,k=c.value.offsetWidth;if(w!==0&&k!==0){var $=t.gap,O=$===void 0?4:$;O*2<k&&(l.value=k-O*2<w?(k-O*2)/w:1)}}},C=function(){var w=t.loadError,k=w==null?void 0:w();k!==!1&&(o.value=!1)};return ce(function(){return t.src},function(){Ne(function(){o.value=!0,l.value=1})}),ce(function(){return t.gap},function(){Ne(function(){b()})}),et(function(){Ne(function(){b(),i.value=!0})}),function(){var S,w,k=t.shape,$=t.size,O=t.src,T=t.alt,_=t.srcset,I=t.draggable,L=jn(r,t,\"icon\"),j=f.value,F=$===\"default\"?p.value:$,N=(S={},V(S,\"\".concat(a.class),!!a.class),V(S,j,!0),V(S,\"\".concat(j,\"-lg\"),F===\"large\"),V(S,\"\".concat(j,\"-sm\"),F===\"small\"),V(S,\"\".concat(j,\"-\").concat(k),k),V(S,\"\".concat(j,\"-image\"),O&&o.value),V(S,\"\".concat(j,\"-icon\"),L),S),D=typeof F==\"number\"?{width:\"\".concat(F,\"px\"),height:\"\".concat(F,\"px\"),lineHeight:\"\".concat(F,\"px\"),fontSize:L?\"\".concat(F/2,\"px\"):\"18px\"}:{},z=(w=r.default)===null||w===void 0?void 0:w.call(r),B;if(O&&o.value)B=g(\"img\",{draggable:I,src:O,srcset:_,onError:C,alt:T},null);else if(L)B=L;else if(i.value||l.value!==1){var M=\"scale(\".concat(l.value,\") translateX(-50%)\"),E={msTransform:M,WebkitTransform:M,transform:M},K=typeof F==\"number\"?{lineHeight:\"\".concat(F,\"px\")}:{};B=g(zo,{onResize:b},{default:function(){return[g(\"span\",{class:\"\".concat(j,\"-string\"),ref:s,style:P(P({},K),E)},[z])]}})}else B=g(\"span\",{class:\"\".concat(j,\"-string\"),ref:s,style:{opacity:0}},[z]);return g(\"span\",le(le({},a),{},{ref:c,class:N,style:P(P(P({},D),y(!!L)),a.style)}),[B])}}}),ss=Q4e,Ca={adjustX:1,adjustY:1},wa=[0,0],jA={left:{points:[\"cr\",\"cl\"],overflow:Ca,offset:[-4,0],targetOffset:wa},right:{points:[\"cl\",\"cr\"],overflow:Ca,offset:[4,0],targetOffset:wa},top:{points:[\"bc\",\"tc\"],overflow:Ca,offset:[0,-4],targetOffset:wa},bottom:{points:[\"tc\",\"bc\"],overflow:Ca,offset:[0,4],targetOffset:wa},topLeft:{points:[\"bl\",\"tl\"],overflow:Ca,offset:[0,-4],targetOffset:wa},leftTop:{points:[\"tr\",\"tl\"],overflow:Ca,offset:[-4,0],targetOffset:wa},topRight:{points:[\"br\",\"tr\"],overflow:Ca,offset:[0,-4],targetOffset:wa},rightTop:{points:[\"tl\",\"tr\"],overflow:Ca,offset:[4,0],targetOffset:wa},bottomRight:{points:[\"tr\",\"br\"],overflow:Ca,offset:[0,4],targetOffset:wa},rightBottom:{points:[\"bl\",\"br\"],overflow:Ca,offset:[4,0],targetOffset:wa},bottomLeft:{points:[\"tl\",\"bl\"],overflow:Ca,offset:[0,4],targetOffset:wa},leftBottom:{points:[\"br\",\"bl\"],overflow:Ca,offset:[-4,0],targetOffset:wa}},eOe={name:\"Content\",props:{prefixCls:u.string,overlay:u.any,trigger:u.any,overlayInnerStyle:u.any},updated:function(){var t=this.trigger;t&&t.forcePopupAlign()},render:function(){var t=this.overlay,n=this.prefixCls,r=this.overlayInnerStyle;return g(\"div\",{class:\"\".concat(n,\"-inner\"),role:\"tooltip\",style:r},[typeof t==\"function\"?t():t])}},tOe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function $3(){}var nOe=G({name:\"Tooltip\",inheritAttrs:!1,props:{trigger:u.any.def([\"hover\"]),defaultVisible:u.looseBool,visible:u.looseBool,placement:u.string.def(\"right\"),transitionName:u.oneOfType([u.string,u.object]),animation:u.any,afterVisibleChange:u.func.def(function(){}),overlay:u.any,overlayStyle:u.object,overlayClassName:u.string,prefixCls:u.string.def(\"rc-tooltip\"),mouseEnterDelay:u.number.def(0),mouseLeaveDelay:u.number.def(.1),getTooltipContainer:u.func,destroyTooltipOnHide:u.looseBool.def(!1),align:u.object.def(function(){return{}}),arrowContent:u.any.def(null),tipId:u.string,builtinPlacements:u.object,overlayInnerStyle:u.style},methods:{getPopupElement:function(){var t=this.$props,n=t.prefixCls,r=t.tipId,a=t.overlayInnerStyle;return[g(\"div\",{class:\"\".concat(n,\"-arrow\"),key:\"arrow\"},[We(this,\"arrowContent\")]),g(eOe,{key:\"content\",trigger:this.$refs.trigger,prefixCls:n,id:r,overlay:We(this,\"overlay\"),overlayInnerStyle:a},null)]},getPopupDomNode:function(){return this.$refs.trigger.getPopupDomNode()}},render:function(t){var n=this,r=Qe(this),a=r.overlayClassName,o=r.trigger,i=r.mouseEnterDelay,l=r.mouseLeaveDelay,s=r.overlayStyle,c=r.prefixCls,d=r.afterVisibleChange,f=r.transitionName,p=r.animation,v=r.placement,m=r.align,y=r.destroyTooltipOnHide,b=r.defaultVisible,C=r.getTooltipContainer,S=tOe(r,[\"overlayClassName\",\"trigger\",\"mouseEnterDelay\",\"mouseLeaveDelay\",\"overlayStyle\",\"prefixCls\",\"afterVisibleChange\",\"transitionName\",\"animation\",\"placement\",\"align\",\"destroyTooltipOnHide\",\"defaultVisible\",\"getTooltipContainer\"]),w=P({},S);vt(this,\"visible\")&&(w.popupVisible=this.$props.visible);var k=this.$attrs,$=P(P(P({popupClassName:a,prefixCls:c,action:o,builtinPlacements:jA,popupPlacement:v,popupAlign:m,getPopupContainer:C,afterPopupVisibleChange:d,popupTransitionName:f,popupAnimation:p,defaultPopupVisible:b,destroyPopupOnHide:y,mouseLeaveDelay:l,popupStyle:s,mouseEnterDelay:i},w),k),{onPopupVisibleChange:k.onVisibleChange||$3,onPopupAlign:k.onPopupAlign||$3,ref:\"trigger\",popup:this.getPopupElement()});return g(Ii,$,{default:function(){return[ht(n)[0]]}})}}),rOe={adjustX:1,adjustY:1},O3={adjustX:0,adjustY:0},aOe=[0,0];function P3(e){return typeof e==\"boolean\"?e?rOe:O3:P(P({},O3),e)}function oOe(e){var t=e.arrowWidth,n=t===void 0?5:t,r=e.horizontalArrowShift,a=r===void 0?16:r,o=e.verticalArrowShift,i=o===void 0?12:o,l=e.autoAdjustOverflow,s=l===void 0?!0:l,c={left:{points:[\"cr\",\"cl\"],offset:[-4,0]},right:{points:[\"cl\",\"cr\"],offset:[4,0]},top:{points:[\"bc\",\"tc\"],offset:[0,-4]},bottom:{points:[\"tc\",\"bc\"],offset:[0,4]},topLeft:{points:[\"bl\",\"tc\"],offset:[-(a+n),-4]},leftTop:{points:[\"tr\",\"cl\"],offset:[-4,-(i+n)]},topRight:{points:[\"br\",\"tc\"],offset:[a+n,-4]},rightTop:{points:[\"tl\",\"cr\"],offset:[4,-(i+n)]},bottomRight:{points:[\"tr\",\"bc\"],offset:[a+n,4]},rightBottom:{points:[\"bl\",\"cr\"],offset:[4,i+n]},bottomLeft:{points:[\"tl\",\"bc\"],offset:[-(a+n),4]},leftBottom:{points:[\"br\",\"cl\"],offset:[-4,i+n]}};return Object.keys(c).forEach(function(d){c[d]=e.arrowPointAtCenter?P(P({},c[d]),{overflow:P3(s),targetOffset:aOe}):P(P({},jA[d]),{overflow:P3(s)}),c[d].ignoreShake=!0}),c}var iOe=rt(\"success\",\"processing\",\"error\",\"default\",\"warning\"),B2=rt(\"pink\",\"red\",\"yellow\",\"orange\",\"cyan\",\"green\",\"blue\",\"purple\",\"geekblue\",\"magenta\",\"volcano\",\"gold\",\"lime\"),T3=u.oneOf(rt(\"hover\",\"focus\",\"click\",\"contextmenu\")),kg=function(){return{trigger:u.oneOfType([T3,u.arrayOf(T3)]).def(\"hover\"),visible:u.looseBool,defaultVisible:u.looseBool,placement:u.oneOf(rt(\"top\",\"left\",\"right\",\"bottom\",\"topLeft\",\"topRight\",\"bottomLeft\",\"bottomRight\",\"leftTop\",\"leftBottom\",\"rightTop\",\"rightBottom\")).def(\"top\"),color:u.string,transitionName:u.string.def(\"zoom-big-fast\"),overlayStyle:u.object.def(function(){return{}}),overlayClassName:u.string,openClassName:u.string,prefixCls:u.string,mouseEnterDelay:u.number.def(.1),mouseLeaveDelay:u.number.def(.1),getPopupContainer:u.func,arrowPointAtCenter:u.looseBool.def(!1),autoAdjustOverflow:u.oneOfType([u.looseBool,u.object]).def(!0),destroyTooltipOnHide:u.looseBool.def(!1),align:u.object.def(function(){return{}}),builtinPlacements:u.object,children:u.array,onVisibleChange:u.func,\"onUpdate:visible\":u.func}},lOe=function(t,n){var r={},a=P({},t);return n.forEach(function(o){t&&o in t&&(r[o]=t[o],delete a[o])}),{picked:r,omitted:a}},sOe=kg(),x3=new RegExp(\"^(\".concat(B2.join(\"|\"),\")(-inverse)?$\")),uOe=P(P({},sOe),{title:u.VNodeChild}),cOe=G({name:\"ATooltip\",inheritAttrs:!1,props:uOe,emits:[\"update:visible\",\"visibleChange\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){return{sVisible:!!this.$props.visible||!!this.$props.defaultVisible}},watch:{visible:function(t){this.sVisible=t}},methods:{handleVisibleChange:function(t){vt(this,\"visible\")||(this.sVisible=this.isNoTitle()?!1:t),this.isNoTitle()||(this.$emit(\"update:visible\",t),this.$emit(\"visibleChange\",t))},getPopupDomNode:function(){return this.$refs.tooltip.getPopupDomNode()},getPlacements:function(){var t=this.$props,n=t.builtinPlacements,r=t.arrowPointAtCenter,a=t.autoAdjustOverflow;return n||oOe({arrowPointAtCenter:r,verticalArrowShift:8,autoAdjustOverflow:a})},getDisabledCompatibleChildren:function(t){if((kt(t.type)===\"object\"&&(t.type.__ANT_BUTTON===!0||t.type.__ANT_SWITCH===!0||t.type.__ANT_CHECKBOX===!0)||t.type===\"button\")&&t.props&&(t.props.disabled||t.props.disabled===\"\")){var n=lOe(qI(t),[\"position\",\"left\",\"right\",\"top\",\"bottom\",\"float\",\"display\",\"zIndex\"]),r=n.picked,a=n.omitted,o=P(P({display:\"inline-block\"},r),{cursor:\"not-allowed\",width:t.props&&t.props.block?\"100%\":null}),i=P(P({},a),{pointerEvents:\"none\"}),l=Ot(t,{style:i},!0);return g(\"span\",{style:o},[l])}return t},isNoTitle:function(){var t=We(this,\"title\");return!t&&t!==0},getOverlay:function(){var t=We(this,\"title\");return t===0?t:t||\"\"},onPopupAlign:function(t,n){var r=this.getPlacements(),a=Object.keys(r).filter(function(l){return r[l].points[0]===n.points[0]&&r[l].points[1]===n.points[1]})[0];if(!!a){var o=t.getBoundingClientRect(),i={top:\"50%\",left:\"50%\"};a.indexOf(\"top\")>=0||a.indexOf(\"Bottom\")>=0?i.top=\"\".concat(o.height-n.offset[1],\"px\"):(a.indexOf(\"Top\")>=0||a.indexOf(\"bottom\")>=0)&&(i.top=\"\".concat(-n.offset[1],\"px\")),a.indexOf(\"left\")>=0||a.indexOf(\"Right\")>=0?i.left=\"\".concat(o.width-n.offset[0],\"px\"):(a.indexOf(\"right\")>=0||a.indexOf(\"Left\")>=0)&&(i.left=\"\".concat(-n.offset[0],\"px\")),t.style.transformOrigin=\"\".concat(i.left,\" \").concat(i.top)}}},render:function(){var t,n=this.$props,r=this.$data,a=this.$attrs,o=n.prefixCls,i=n.openClassName,l=n.getPopupContainer,s=n.color,c=n.overlayClassName,d=this.configProvider.getPopupContainer,f=this.configProvider.getPrefixCls,p=f(\"tooltip\",o),v=this.children||La(ht(this));v=v.length===1?v[0]:v;var m=r.sVisible;if(!vt(this,\"visible\")&&this.isNoTitle()&&(m=!1),!v)return null;var y=this.getDisabledCompatibleChildren(zn(v)?v:g(\"span\",null,[v])),b=Se((t={},V(t,i||\"\".concat(p,\"-open\"),m),V(t,y.props&&y.props.class,y.props&&y.props.class),t)),C=Se(c,V({},\"\".concat(p,\"-\").concat(s),s&&x3.test(s))),S,w;s&&!x3.test(s)&&(S={backgroundColor:s},w={backgroundColor:s});var k=P(P(P({},a),n),{prefixCls:p,getTooltipContainer:l||d,builtinPlacements:this.getPlacements(),overlay:this.getOverlay(),visible:m,ref:\"tooltip\",overlayClassName:C,overlayInnerStyle:S,arrowContent:g(\"span\",{class:\"\".concat(p,\"-arrow-content\"),style:w},null),onVisibleChange:this.handleVisibleChange,onPopupAlign:this.onPopupAlign});return g(nOe,k,{default:function(){return[m?Ot(y,{class:b}):y]}})}}),Io=kn(cOe),dOe=kg(),fOe=G({name:\"APopover\",props:P(P({},dOe),{prefixCls:u.string,transitionName:u.string.def(\"zoom-big\"),content:u.any,title:u.any}),setup:function(){return{configProvider:ve(\"configProvider\",St)}},methods:{getPopupDomNode:function(){return this.$refs.tooltip.getPopupDomNode()}},render:function(){var t=this,n=this.title,r=this.prefixCls,a=this.$slots,o=this.configProvider.getPrefixCls,i=o(\"popover\",r),l=Qe(this);delete l.title,delete l.content;var s=P(P({},l),{prefixCls:i,ref:\"tooltip\",title:g(\"div\",null,[(n||a.title)&&g(\"div\",{class:\"\".concat(i,\"-title\")},[We(this,\"title\")]),g(\"div\",{class:\"\".concat(i,\"-inner-content\")},[We(this,\"content\")])])});return g(Io,s,{default:function(){return[ht(t)]}})}}),KA=kn(fOe),hOe={prefixCls:u.string,maxCount:u.number,maxStyle:{type:Object,default:function(){return{}}},maxPopoverPlacement:u.oneOf(rt(\"top\",\"bottom\")).def(\"top\"),size:HA.size},pOe=G({name:\"AAvatarGroup\",inheritAttrs:!1,props:hOe,setup:function(t,n){var r=n.slots,a=n.attrs,o=Wt(\"avatar-group\",t),i=o.prefixCls,l=o.direction;return J4e(t),function(){var s,c=t.maxPopoverPlacement,d=c===void 0?\"top\":c,f=t.maxCount,p=t.maxStyle,v=(s={},V(s,i.value,!0),V(s,\"\".concat(i.value,\"-rtl\"),l.value===\"rtl\"),V(s,\"\".concat(a.class),!!a.class),s),m=jn(r,t),y=Un(m).map(function(w,k){return Ot(w,{key:\"avatar-key-\".concat(k)})}),b=y.length;if(f&&f<b){var C=y.slice(0,f),S=y.slice(f,b);return C.push(g(KA,{key:\"avatar-popover-key\",content:S,trigger:\"hover\",placement:d,overlayClassName:\"\".concat(i.value,\"-popover\")},{default:function(){return[g(ss,{style:p},{default:function(){return[\"+\".concat(b-f)]}})]}})),g(\"div\",le(le({},a),{},{class:v,style:a.style}),[C])}return g(\"div\",le(le({},a),{},{class:v,style:a.style}),[y])}}}),Kv=pOe;ss.Group=Kv;ss.install=function(e){return e.component(ss.name,ss),e.component(Kv.name,Kv),e};var vOe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M859.9 168H164.1c-4.5 0-8.1 3.6-8.1 8v60c0 4.4 3.6 8 8.1 8h695.8c4.5 0 8.1-3.6 8.1-8v-60c0-4.4-3.6-8-8.1-8zM518.3 355a8 8 0 00-12.6 0l-112 141.7a7.98 7.98 0 006.3 12.9h73.9V848c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V509.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 355z\"}}]},name:\"vertical-align-top\",theme:\"outlined\"},mOe=vOe;function _3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){gOe(e,a,n[a])})}return e}function gOe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var V2=function(t,n){var r=_3({},t,n.attrs);return g(Et,_3({},r,{icon:mOe}),null)};V2.displayName=\"VerticalAlignTopOutlined\";V2.inheritAttrs=!1;var yOe=V2,bOe={visibilityHeight:u.number.def(400),duration:u.number.def(450),target:Function,prefixCls:u.string,onClick:u.func},COe=G({name:\"ABackTop\",inheritAttrs:!1,props:bOe,emits:[\"click\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.emit,i=ve(\"configProvider\",St),l=H(),s=bt({visible:!1,scrollEvent:null}),c=function(){return l.value&&l.value.ownerDocument?l.value.ownerDocument:window},d=function(b){var C=t.target,S=C===void 0?c:C,w=t.duration;Zw(0,{getContainer:S,duration:w}),o(\"click\",b)},f=e1(function(y){var b=t.visibilityHeight,C=Xw(y.target,!0);s.visible=C>b}),p=function(){var b=t.target,C=b||c,S=C();s.scrollEvent=Kn(S,\"scroll\",function(w){f(w)}),f({target:S})},v=function(){s.scrollEvent&&s.scrollEvent.remove(),f.cancel()};ce(function(){return t.target},function(){v(),Ne(function(){p()})}),et(function(){Ne(function(){p()})}),O6(function(){Ne(function(){p()})}),P6(function(){v()}),Lt(function(){v()});var m=x(function(){return i.getPrefixCls(\"back-top\",t.prefixCls)});return function(){var y,b,C=g(\"div\",{class:\"\".concat(m.value,\"-content\")},[g(\"div\",{class:\"\".concat(m.value,\"-icon\")},[g(yOe,null,null)])]),S=P(P({},a),{onClick:d,class:(y={},V(y,\"\".concat(m.value),!0),V(y,\"\".concat(a.class),a.class),V(y,\"\".concat(m.value,\"-rtl\"),i.direction===\"rtl\"),y)}),w=s.visible?g(\"div\",le(le({},S),{},{ref:l}),[((b=r.default)===null||b===void 0?void 0:b.call(r))||C]):null,k=Lo(\"fade\");return g(no,k,{default:function(){return[w]}})}}}),wOe=kn(COe);function E3(e){var t=e.prefixCls,n=e.value,r=e.current,a=e.offset,o=a===void 0?0:a,i;return o&&(i={position:\"absolute\",top:\"\".concat(o,\"00%\"),left:0}),g(\"p\",{style:i,class:Se(\"\".concat(t,\"-only-unit\"),{current:r})},[n])}function SOe(e,t,n){for(var r=e,a=0;(r+10)%10!==t;)r+=n,a+=n;return a}var kOe=G({name:\"SingleNumber\",props:{prefixCls:String,value:String,count:Number},setup:function(t){var n=x(function(){return Number(t.value)}),r=x(function(){return Math.abs(t.count)}),a=bt({prevValue:n.value,prevCount:r.value}),o=function(){a.prevValue=n.value,a.prevCount=r.value},i=H();return ce(n,function(){clearTimeout(i.value),i.value=setTimeout(function(){o()},1e3)},{flush:\"post\"}),Wr(function(){clearTimeout(i.value)}),function(){var l,s={},c=n.value;if(a.prevValue===c||Number.isNaN(c)||Number.isNaN(a.prevValue))l=[E3(P(P({},t),{current:!0}))],s={transition:\"none\"};else{l=[];for(var d=c+10,f=[],p=c;p<=d;p+=1)f.push(p);var v=f.findIndex(function(y){return y%10===a.prevValue});l=f.map(function(y,b){var C=y%10;return E3(P(P({},t),{value:C,offset:b-v,current:b===v}))});var m=a.prevCount<r.value?1:-1;s={transform:\"translateY(\".concat(-SOe(a.prevValue,c,m),\"00%)\")}}return g(\"span\",{class:\"\".concat(t.prefixCls,\"-only\"),style:s,onTransitionend:function(){return o()}},[l])}}}),$Oe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},OOe={prefixCls:u.string,count:u.any,component:u.string,title:u.oneOfType([u.number,u.string,null]),show:Boolean},POe=G({name:\"ScrollNumber\",inheritAttrs:!1,props:OOe,setup:function(t,n){var r=n.attrs,a=n.slots,o=Wt(\"scroll-number\",t),i=o.prefixCls;return function(){var l,s=P(P({},t),r);s.prefixCls;var c=s.count,d=s.title;s.show;var f=s.component,p=f===void 0?\"sup\":f,v=s.class,m=s.style,y=$Oe(s,[\"prefixCls\",\"count\",\"title\",\"show\",\"component\",\"class\",\"style\"]),b=P(P({},y),{style:m,\"data-show\":t.show,class:Se(i.value,v),title:d}),C=c;if(c&&Number(c)%1===0){var S=String(c).split(\"\");C=S.map(function(k,$){return g(kOe,{prefixCls:i.value,count:Number(c),value:k,key:S.length-$},null)})}m&&m.borderColor&&(b.style=P(P({},m),{boxShadow:\"0 0 0 1px \".concat(m.borderColor,\" inset\")}));var w=La((l=a.default)===null||l===void 0?void 0:l.call(a));return w&&w.length?Ot(w,{class:Se(\"\".concat(i.value,\"-custom-component\"))},!1):g(p,b,{default:function(){return[C]}})}}});function od(e){return B2.indexOf(e)!==-1}var TOe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},xOe={prefix:u.string,color:{type:String},text:u.any,placement:u.oneOf(rt(\"start\",\"end\")).def(\"end\")},Wv=G({name:\"ABadgeRibbon\",inheritAttrs:!1,props:xOe,slots:[\"text\"],setup:function(t,n){var r=n.attrs,a=n.slots,o=Wt(\"ribbon\",t),i=o.prefixCls,l=o.direction,s=x(function(){return od(t.color)}),c=x(function(){var d;return[i.value,\"\".concat(i.value,\"-placement-\").concat(t.placement),(d={},V(d,\"\".concat(i.value,\"-rtl\"),l.value===\"rtl\"),V(d,\"\".concat(i.value,\"-color-\").concat(t.color),s.value),d)]});return function(){var d,f,p=r.class,v=r.style,m=TOe(r,[\"class\",\"style\"]),y={},b={};return t.color&&!s.value&&(y.background=t.color,b.color=t.color),g(\"div\",le({class:\"\".concat(i.value,\"-wrapper\")},m),[(d=a.default)===null||d===void 0?void 0:d.call(a),g(\"div\",{class:[c.value,p],style:P(P({},y),v)},[g(\"span\",{class:\"\".concat(i.value,\"-text\")},[t.text||((f=a.text)===null||f===void 0?void 0:f.call(a))]),g(\"div\",{class:\"\".concat(i.value,\"-corner\"),style:b},null)])])}}}),_Oe=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},WA=_Oe,EOe={count:u.any,showZero:u.looseBool,overflowCount:u.number.def(99),dot:u.looseBool,prefixCls:u.string,scrollNumberPrefixCls:u.string,status:u.oneOf(rt(\"success\",\"processing\",\"default\",\"error\",\"warning\")),size:u.oneOf(rt(\"default\",\"small\")).def(\"default\"),color:u.string,text:u.VNodeChild,offset:u.arrayOf(u.oneOfType([String,Number])),numberStyle:u.style,title:u.string},Kp=G({name:\"ABadge\",Ribbon:Wv,inheritAttrs:!1,props:EOe,slots:[\"text\",\"count\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=Wt(\"badge\",t),i=o.prefixCls,l=o.direction,s=x(function(){return t.count>t.overflowCount?\"\".concat(t.overflowCount,\"+\"):t.count}),c=x(function(){return t.status!==null&&t.status!==void 0||t.color!==null&&t.color!==void 0}),d=x(function(){return s.value===\"0\"||s.value===0}),f=x(function(){return t.dot&&!d.value||c.value}),p=x(function(){return f.value?\"\":s.value}),v=x(function(){var k=p.value===null||p.value===void 0||p.value===\"\";return(k||d.value&&!t.showZero)&&!f.value}),m=H(t.count),y=H(p.value),b=H(f.value);ce([function(){return t.count},p,f],function(){v.value||(m.value=t.count,y.value=p.value,b.value=f.value)},{immediate:!0});var C=x(function(){var k;return k={},V(k,\"\".concat(i.value,\"-status-dot\"),c.value),V(k,\"\".concat(i.value,\"-status-\").concat(t.status),!!t.status),V(k,\"\".concat(i.value,\"-status-\").concat(t.color),od(t.color)),k}),S=x(function(){return t.color&&!od(t.color)?{background:t.color}:{}}),w=x(function(){var k;return k={},V(k,\"\".concat(i.value,\"-dot\"),b.value),V(k,\"\".concat(i.value,\"-count\"),!b.value),V(k,\"\".concat(i.value,\"-count-sm\"),t.size===\"small\"),V(k,\"\".concat(i.value,\"-multiple-words\"),!b.value&&y.value&&y.value.toString().length>1),V(k,\"\".concat(i.value,\"-status-\").concat(t.status),!!t.status),V(k,\"\".concat(i.value,\"-status-\").concat(t.color),od(t.color)),k});return function(){var k,$,O,T=t.offset,_=t.title,I=t.color,L=a.style,j=jn(r,t,\"text\"),F=i.value,N=m.value,D=Un(($=r.default)===null||$===void 0?void 0:$.call(r));D=D.length?D:null;var z=!!(!v.value||r.count),B=function(){if(!T)return P({},L);var ne={marginTop:WA(T[1])?\"\".concat(T[1],\"px\"):T[1]};return l.value===\"rtl\"?ne.left=\"\".concat(parseInt(T[0],10),\"px\"):ne.right=\"\".concat(-parseInt(T[0],10),\"px\"),P(P({},ne),L)}(),M=_!=null?_:typeof N==\"string\"||typeof N==\"number\"?N:void 0,E=z||!j?null:g(\"span\",{class:\"\".concat(F,\"-status-text\")},[j]),K=kt(N)===\"object\"||N===void 0&&r.count?Ot(N!=null?N:(O=r.count)===null||O===void 0?void 0:O.call(r),{style:B},!1):null,W=Se(F,(k={},V(k,\"\".concat(F,\"-status\"),c.value),V(k,\"\".concat(F,\"-not-a-wrapper\"),!D),V(k,\"\".concat(F,\"-rtl\"),l.value===\"rtl\"),k),a.class);if(!D&&c.value){var Y=B.color;return g(\"span\",le(le({},a),{},{class:W,style:B}),[g(\"span\",{class:C.value,style:S.value},null),g(\"span\",{style:{color:Y},class:\"\".concat(F,\"-status-text\")},[j])])}var q=Lo(D?\"\".concat(F,\"-zoom\"):\"\",{appear:!1}),J=P(P({},B),t.numberStyle);return I&&!od(I)&&(J=J||{},J.background=I),g(\"span\",le(le({},a),{},{class:W}),[D,g(no,q,{default:function(){return[at(g(POe,{prefixCls:t.scrollNumberPrefixCls,show:z,class:w.value,count:y.value,title:M,style:J,key:\"scrollNumber\"},{default:function(){return[K]}}),[[_t,z]])]}}),E])}}});Kp.install=function(e){return e.component(Kp.name,Kp),e.component(Wv.name,Wv),e};var Ws={adjustX:1,adjustY:1},Us=[0,0],MOe={topLeft:{points:[\"bl\",\"tl\"],overflow:Ws,offset:[0,-4],targetOffset:Us},topCenter:{points:[\"bc\",\"tc\"],overflow:Ws,offset:[0,-4],targetOffset:Us},topRight:{points:[\"br\",\"tr\"],overflow:Ws,offset:[0,-4],targetOffset:Us},bottomLeft:{points:[\"tl\",\"bl\"],overflow:Ws,offset:[0,4],targetOffset:Us},bottomCenter:{points:[\"tc\",\"bc\"],overflow:Ws,offset:[0,4],targetOffset:Us},bottomRight:{points:[\"tr\",\"br\"],overflow:Ws,offset:[0,4],targetOffset:Us}},IOe=MOe,NOe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},AOe=G({mixins:[nt],props:{minOverlayWidthMatchTrigger:u.looseBool,prefixCls:u.string.def(\"rc-dropdown\"),transitionName:u.string,overlayClassName:u.string.def(\"\"),openClassName:u.string,animation:u.any,align:u.object,overlayStyle:u.object.def(function(){return{}}),placement:u.string.def(\"bottomLeft\"),overlay:u.any,trigger:u.oneOfType([u.string,u.arrayOf(u.string)]).def(\"hover\"),alignPoint:u.looseBool,showAction:u.array,hideAction:u.array,getPopupContainer:u.func,visible:u.looseBool,defaultVisible:u.looseBool.def(!1),mouseEnterDelay:u.number.def(.15),mouseLeaveDelay:u.number.def(.1)},data:function(){var t=this.defaultVisible;return vt(this,\"visible\")&&(t=this.visible),{sVisible:t}},watch:{visible:function(t){t!==void 0&&this.setState({sVisible:t})}},methods:{onClick:function(t){var n=this.getOverlayElement().props;vt(this,\"visible\")||this.setState({sVisible:!1}),this.__emit(\"overlayClick\",t),n.onClick&&n.onClick(t)},onVisibleChange:function(t){vt(this,\"visible\")||this.setState({sVisible:t}),this.__emit(\"update:visible\",t),this.__emit(\"visibleChange\",t)},getMinOverlayWidthMatchTrigger:function(){var t=Qe(this),n=t.minOverlayWidthMatchTrigger,r=t.alignPoint;return\"minOverlayWidthMatchTrigger\"in t?n:!r},getOverlayElement:function(){var t=We(this,\"overlay\");return Array.isArray(t)?t[0]:t},getMenuElement:function(){var t=this,n=this.onClick,r=this.prefixCls,a=this.getOverlayElement(),o={prefixCls:\"\".concat(r,\"-menu\"),getPopupContainer:function(){return t.getPopupDomNode()},onClick:n};return a&&a.type===Fo&&delete o.prefixCls,Ot(a,o)},getMenuElementOrLambda:function(){var t=this.overlay||this.$slots.overlay;return typeof t==\"function\"?this.getMenuElement:this.getMenuElement()},getPopupDomNode:function(){return this.triggerRef.getPopupDomNode()},getOpenClassName:function(){var t=this.$props,n=t.openClassName,r=t.prefixCls;return n!==void 0?n:\"\".concat(r,\"-open\")},afterVisibleChange:function(t){if(t&&this.getMinOverlayWidthMatchTrigger()){var n=this.getPopupDomNode(),r=Sn(this);r&&n&&r.offsetWidth>n.offsetWidth&&(n.style.minWidth=\"\".concat(r.offsetWidth,\"px\"),this.triggerRef&&this.triggerRef._component&&this.triggerRef._component.alignInstance&&this.triggerRef._component.alignInstance.forceAlign())}},renderChildren:function(){var t=ht(this),n=this.sVisible;return n&&t?Ot(t[0],{class:this.getOpenClassName()},!1):t},saveTrigger:function(t){this.triggerRef=t}},render:function(){var t=this,n=this.$props,r=n.prefixCls,a=n.transitionName,o=n.animation,i=n.align,l=n.placement,s=n.getPopupContainer,c=n.showAction,d=n.hideAction,f=n.overlayClassName,p=n.overlayStyle,v=n.trigger,m=NOe(n,[\"prefixCls\",\"transitionName\",\"animation\",\"align\",\"placement\",\"getPopupContainer\",\"showAction\",\"hideAction\",\"overlayClassName\",\"overlayStyle\",\"trigger\"]),y=d;!y&&v.indexOf(\"contextmenu\")!==-1&&(y=[\"click\"]);var b=P(P({},m),{prefixCls:r,popupClassName:f,popupStyle:p,builtinPlacements:IOe,action:v,showAction:c,hideAction:y||[],popupPlacement:l,popupAlign:i,popupTransitionName:a,popupAnimation:o,popupVisible:this.sVisible,afterPopupVisibleChange:this.afterVisibleChange,getPopupContainer:s,onPopupVisibleChange:this.onVisibleChange,popup:this.getMenuElementOrLambda(),ref:this.saveTrigger});return g(Ii,b,{default:function(){return[t.renderChildren()]}})}}),UA=function(){return{trigger:{type:[Array,String],default:\"hover\"},overlay:u.any,visible:u.looseBool,disabled:u.looseBool,align:u.object,getPopupContainer:u.func,prefixCls:u.string,transitionName:u.string,placement:u.oneOf(rt(\"topLeft\",\"topCenter\",\"topRight\",\"bottomLeft\",\"bottomCenter\",\"bottomRight\")),overlayClassName:u.string,overlayStyle:u.style,forceRender:u.looseBool,mouseEnterDelay:u.number,mouseLeaveDelay:u.number,openClassName:u.string,minOverlayWidthMatchTrigger:u.looseBool}},DOe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z\"}}]},name:\"ellipsis\",theme:\"outlined\"},ROe=DOe;function M3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){LOe(e,a,n[a])})}return e}function LOe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var z2=function(t,n){var r=M3({},t,n.attrs);return g(Et,M3({},r,{icon:ROe}),null)};z2.displayName=\"EllipsisOutlined\";z2.inheritAttrs=!1;var YA=z2,FOe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},BOe=Hv(),I3=UA(),VOe=Cr.Group,zOe=P(P({},I3),{type:u.oneOf(rt(\"primary\",\"ghost\",\"dashed\",\"danger\",\"default\")).def(\"default\"),size:u.oneOf(rt(\"small\",\"large\",\"default\")).def(\"default\"),htmlType:BOe.htmlType,href:u.string,disabled:u.looseBool,prefixCls:u.string,placement:I3.placement.def(\"bottomRight\"),icon:u.any,title:u.string,onClick:u.func,onVisibleChange:u.func,\"onUpdate:visible\":u.func}),cf=G({name:\"ADropdownButton\",inheritAttrs:!1,props:zOe,emits:[\"click\",\"visibleChange\",\"update:visible\"],setup:function(){return{configProvider:ve(\"configProvider\",St),popupRef:null}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},methods:{savePopupRef:function(t){this.popupRef=t},handleClick:function(t){this.$emit(\"click\",t)},handleVisibleChange:function(t){this.$emit(\"update:visible\",t),this.$emit(\"visibleChange\",t)}},render:function(){var t=this,n=P(P({},this.$props),this.$attrs),r=n.type,a=n.disabled;n.onClick;var o=n.htmlType,i=n.class,l=n.prefixCls;n.overlay;var s=n.trigger,c=n.align,d=n.visible;n.onVisibleChange;var f=n.placement,p=n.getPopupContainer,v=n.href,m=n.title,y=FOe(n,[\"type\",\"disabled\",\"onClick\",\"htmlType\",\"class\",\"prefixCls\",\"overlay\",\"trigger\",\"align\",\"visible\",\"onVisibleChange\",\"placement\",\"getPopupContainer\",\"href\",\"title\"]),b=We(this,\"icon\")||g(YA,null,null),C=this.configProvider.getPopupContainer,S=this.configProvider.getPrefixCls,w=S(\"dropdown-button\",l),k={align:c,disabled:a,trigger:a?[]:s,placement:f,getPopupContainer:p||C,onVisibleChange:this.handleVisibleChange};vt(this,\"visible\")&&(k.visible=d);var $=P(P({},y),{class:Se(w,i)});return g(VOe,$,{default:function(){return[g(Cr,{type:r,disabled:a,onClick:t.handleClick,htmlType:o,href:v,title:m},{default:function(){return[ht(t)]}}),g(hi,le(le({},k),{},{overlay:We(t,\"overlay\")}),{default:function(){return[g(Cr,{type:r},{default:function(){return[b]}})]}})]}})}}),HOe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z\"}}]},name:\"right\",theme:\"outlined\"},jOe=HOe;function N3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){KOe(e,a,n[a])})}return e}function KOe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var H2=function(t,n){var r=N3({},t,n.attrs);return g(Et,N3({},r,{icon:jOe}),null)};H2.displayName=\"RightOutlined\";H2.inheritAttrs=!1;var wi=H2,A3=UA(),qA=G({name:\"ADropdown\",inheritAttrs:!1,props:P(P({},A3),{prefixCls:u.string,mouseEnterDelay:u.number.def(.15),mouseLeaveDelay:u.number.def(.1),placement:A3.placement.def(\"bottomLeft\"),onVisibleChange:u.func,\"onUpdate:visible\":u.func}),emits:[\"visibleChange\",\"update:visible\"],setup:function(){return{configProvider:ve(\"configProvider\",St),popupRef:null}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},methods:{savePopupRef:function(t){this.popupRef=t},getTransitionName:function(){var t=this.$props,n=t.placement,r=n===void 0?\"\":n,a=t.transitionName;return a!==void 0?a:r.indexOf(\"top\")>=0?\"slide-down\":\"slide-up\"},renderOverlay:function(t){var n=We(this,\"overlay\"),r=Array.isArray(n)?n[0]:n,a=r&&rr(r),o=a||{},i=o.selectable,l=i===void 0?!1:i,s=o.focusable,c=s===void 0?!0:s,d=function(){return g(\"span\",{class:\"\".concat(t,\"-menu-submenu-arrow\")},[g(wi,{class:\"\".concat(t,\"-menu-submenu-arrow-icon\")},null)])},f=zn(r)?hr(r,{mode:\"vertical\",selectable:l,focusable:c,expandIcon:d}):n;return f},handleVisibleChange:function(t){this.$emit(\"update:visible\",t),this.$emit(\"visibleChange\",t)}},render:function(){var t,n=Qe(this),r=n.prefixCls,a=n.trigger,o=n.disabled,i=n.getPopupContainer,l=this.configProvider.getPopupContainer,s=this.configProvider.getPrefixCls,c=s(\"dropdown\",r),d=ht(this)[0],f=Ot(d,{class:Se((t=d==null?void 0:d.props)===null||t===void 0?void 0:t.class,\"\".concat(c,\"-trigger\")),disabled:o}),p=o?[]:typeof a==\"string\"?[a]:a,v;p&&p.indexOf(\"contextmenu\")!==-1&&(v=!0);var m=P(P(P({alignPoint:v},n),this.$attrs),{prefixCls:c,getPopupContainer:i||l,transitionName:this.getTransitionName(),trigger:p,overlay:this.renderOverlay(c),onVisibleChange:this.handleVisibleChange});return g(AOe,m,{default:function(){return[f]}})}});qA.Button=cf;var hi=qA,WOe={prefixCls:u.string,href:u.string,separator:u.any,overlay:u.any},df=G({name:\"ABreadcrumbItem\",__ANT_BREADCRUMB_ITEM:!0,props:WOe,slots:[\"separator\",\"overlay\"],setup:function(t,n){var r=n.slots,a=Wt(\"breadcrumb\",t),o=a.prefixCls,i=function(s,c){var d=jn(r,t,\"overlay\");return d?g(hi,{overlay:d,placement:\"bottomCenter\"},{default:function(){return[g(\"span\",{class:\"\".concat(c,\"-overlay-link\")},[s,g(Rs,null,null)])]}}):s};return function(){var l,s=(l=jn(r,t,\"separator\"))!==null&&l!==void 0?l:\"/\",c=jn(r,t),d;return t.href!==void 0?d=g(\"a\",{class:\"\".concat(o.value,\"-link\")},[c]):d=g(\"span\",{class:\"\".concat(o.value,\"-link\")},[c]),d=i(d,o.value),c?g(\"span\",null,[d,s&&g(\"span\",{class:\"\".concat(o.value,\"-separator\")},[s])]):null}}});function UOe(e,t,n,r){var a=n?n.call(r,e,t):void 0;if(a!==void 0)return!!a;if(e===t)return!0;if(kt(e)!==\"object\"||!e||kt(t)!==\"object\"||!t)return!1;var o=Object.keys(e),i=Object.keys(t);if(o.length!==i.length)return!1;for(var l=Object.prototype.hasOwnProperty.bind(t),s=0;s<o.length;s++){var c=o[s];if(!l(c))return!1;var d=e[c],f=t[c];if(a=n?n.call(r,d,f,c):void 0,a===!1||a===void 0&&d!==f)return!1}return!0}function Mr(e,t,n,r){return UOe(Gt(e),Gt(t),n,r)}var GA=Symbol(\"menuContextKey\"),XA=function(t){ot(GA,t)},Ni=function(){return ve(GA)},ZA=Symbol(\"menuFirstLevelContextKey\"),JA=function(t){ot(ZA,t)},YOe=function(){return ve(ZA,!0)},Uv=G({name:\"MenuContextProvider\",inheritAttrs:!1,props:{mode:{type:String,default:void 0},overflowDisabled:{type:Boolean,default:void 0},isRootMenu:{type:Boolean,default:void 0}},setup:function(t,n){var r=n.slots,a=Ni(),o=P({},a);return t.mode!==void 0&&(o.mode=yn(t,\"mode\")),t.isRootMenu!==void 0&&(o.isRootMenu=yn(t,\"isRootMenu\")),t.overflowDisabled!==void 0&&(o.overflowDisabled=yn(t,\"overflowDisabled\")),XA(o),function(){var i;return(i=r.default)===null||i===void 0?void 0:i.call(r)}}}),qOe=XA,QA=Symbol(\"siderCollapsed\"),eD=Symbol(\"siderHookProvider\"),tD=Symbol(\"KeyPathContext\"),j2=function(){return ve(tD,{parentEventKeys:x(function(){return[]}),parentKeys:x(function(){return[]}),parentInfo:{}})},GOe=function(t,n,r){var a=j2(),o=a.parentEventKeys,i=a.parentKeys,l=x(function(){return[].concat(Je(o.value),[t])}),s=x(function(){return[].concat(Je(i.value),[n])});return ot(tD,{parentEventKeys:l,parentKeys:s,parentInfo:r}),s},XOe=GOe;function nD(e){var t=Ni(),n=t.mode,r=t.rtl,a=t.inlineIndent;return x(function(){return n.value!==\"inline\"?null:r.value?{paddingRight:\"\".concat(e.value*a.value,\"px\")}:{paddingLeft:\"\".concat(e.value*a.value,\"px\")}})}var ZOe=0,JOe={role:String,disabled:Boolean,danger:Boolean,title:{type:[String,Boolean],default:void 0},icon:u.VNodeChild},fl=G({name:\"AMenuItem\",inheritAttrs:!1,props:JOe,emits:[\"mouseenter\",\"mouseleave\",\"click\",\"keydown\",\"focus\"],slots:[\"icon\",\"title\"],setup:function(t,n){var r=n.slots,a=n.emit,o=n.attrs,i=$t(),l=kt(i.vnode.key)===\"symbol\"?String(i.vnode.key):i.vnode.key;uf(kt(i.vnode.key)!==\"symbol\",\"MenuItem\",'MenuItem `:key=\"'.concat(String(l),'\"` not support Symbol type'));var s=\"menu_item_\".concat(++ZOe,\"_$$_\").concat(l),c=j2(),d=c.parentEventKeys,f=c.parentKeys,p=Ni(),v=p.prefixCls,m=p.activeKeys,y=p.disabled,b=p.changeActiveKeys,C=p.rtl,S=p.inlineCollapsed,w=p.siderCollapsed,k=p.onItemClick,$=p.selectedKeys,O=p.registerMenuInfo,T=p.unRegisterMenuInfo,_=YOe(),I=H(!1),L=x(function(){return[].concat(Je(f.value),[l])}),j={eventKey:s,key:l,parentEventKeys:d,parentKeys:f,isLeaf:!0};O(s,j),Lt(function(){T(s)}),ce(m,function(){I.value=!!m.value.find(function(J){return J===l})},{immediate:!0});var F=x(function(){return y.value||t.disabled}),N=x(function(){return $.value.includes(l)}),D=x(function(){var J,ne=\"\".concat(v.value,\"-item\");return J={},V(J,\"\".concat(ne),!0),V(J,\"\".concat(ne,\"-danger\"),t.danger),V(J,\"\".concat(ne,\"-active\"),I.value),V(J,\"\".concat(ne,\"-selected\"),N.value),V(J,\"\".concat(ne,\"-disabled\"),F.value),J}),z=function(ne){return{key:l,eventKey:s,keyPath:L.value,eventKeyPath:[].concat(Je(d.value),[s]),domEvent:ne,item:P(P({},t),o)}},B=function(ne){if(!F.value){var oe=z(ne);a(\"click\",ne),k(oe)}},M=function(ne){F.value||(b(L.value),a(\"mouseenter\",ne))},E=function(ne){F.value||(b([]),a(\"mouseleave\",ne))},K=function(ne){if(a(\"keydown\",ne),ne.which===ze.ENTER){var oe=z(ne);a(\"click\",ne),k(oe)}},W=function(ne){b(L.value),a(\"focus\",ne)},Y=function(ne,oe){var Q=g(\"span\",{class:\"\".concat(v.value,\"-title-content\")},[oe]);return(!ne||zn(oe)&&oe.type===\"span\")&&oe&&S.value&&_&&typeof oe==\"string\"?g(\"div\",{class:\"\".concat(v.value,\"-inline-collapsed-noicon\")},[oe.charAt(0)]):Q},q=nD(x(function(){return L.value.length}));return function(){var J,ne,oe,Q,ae=(ne=t.title)!==null&&ne!==void 0?ne:(oe=r.title)===null||oe===void 0?void 0:oe.call(r),de=Un((Q=r.default)===null||Q===void 0?void 0:Q.call(r)),be=de.length,Ee=ae;typeof ae==\"undefined\"?Ee=_&&be?de:\"\":ae===!1&&(Ee=\"\");var Pe={title:Ee};!w.value&&!S.value&&(Pe.title=null,Pe.visible=!1);var Be={};t.role===\"option\"&&(Be[\"aria-selected\"]=N.value);var te=jn(r,t,\"icon\");return g(Io,le(le({},Pe),{},{placement:C.value?\"left\":\"right\",overlayClassName:\"\".concat(v.value,\"-inline-collapsed-tooltip\")}),{default:function(){return[g(Zl.Item,le(le(le({component:\"li\"},o),{},{style:P(P({},o.style||{}),q.value),class:[D.value,(J={},V(J,\"\".concat(o.class),!!o.class),V(J,\"\".concat(v.value,\"-item-only-child\"),(te?be+1:be)===1),J)],role:t.role||\"menuitem\",tabindex:t.disabled?null:-1,\"data-menu-id\":l,\"aria-disabled\":t.disabled},Be),{},{onMouseenter:M,onMouseleave:E,onClick:B,onKeydown:K,onFocus:W,title:typeof ae==\"string\"?ae:void 0}),{default:function(){return[Ot(te,{class:\"\".concat(v.value,\"-item-icon\")}),Y(te,de)]}})]}})}}}),Zi={adjustX:1,adjustY:1},QOe={topLeft:{points:[\"bl\",\"tl\"],overflow:Zi,offset:[0,-7]},bottomLeft:{points:[\"tl\",\"bl\"],overflow:Zi,offset:[0,7]},leftTop:{points:[\"tr\",\"tl\"],overflow:Zi,offset:[-4,0]},rightTop:{points:[\"tl\",\"tr\"],overflow:Zi,offset:[4,0]}},ePe={topLeft:{points:[\"bl\",\"tl\"],overflow:Zi,offset:[0,-7]},bottomLeft:{points:[\"tl\",\"bl\"],overflow:Zi,offset:[0,7]},rightTop:{points:[\"tr\",\"tl\"],overflow:Zi,offset:[-4,0]},leftTop:{points:[\"tl\",\"tr\"],overflow:Zi,offset:[4,0]}},tPe={horizontal:\"bottomLeft\",vertical:\"rightTop\",\"vertical-left\":\"rightTop\",\"vertical-right\":\"leftTop\"},D3=G({name:\"PopupTrigger\",inheritAttrs:!1,props:{prefixCls:String,mode:String,visible:Boolean,popupClassName:String,popupOffset:Array,disabled:Boolean,onVisibleChange:Function},slots:[\"popup\"],emits:[\"visibleChange\"],setup:function(t,n){var r=n.slots,a=n.emit,o=H(!1),i=Ni(),l=i.getPopupContainer,s=i.rtl,c=i.subMenuOpenDelay,d=i.subMenuCloseDelay,f=i.builtinPlacements,p=i.triggerSubMenuAction,v=i.isRootMenu,m=x(function(){return s.value?P(P({},ePe),f.value):P(P({},QOe),f.value)}),y=x(function(){return tPe[t.mode]}),b=H();ce(function(){return t.visible},function(S){en.cancel(b.value),b.value=en(function(){o.value=S})},{immediate:!0}),Lt(function(){en.cancel(b.value)});var C=function(w){a(\"visibleChange\",w)};return function(){var S=t.prefixCls,w=t.popupClassName,k=t.mode,$=t.popupOffset,O=t.disabled;return g(Ii,{prefixCls:S,popupClassName:Se(\"\".concat(S,\"-popup\"),V({},\"\".concat(S,\"-rtl\"),s.value),w),stretch:k===\"horizontal\"?\"minWidth\":null,getPopupContainer:v.value?l.value:function(T){return T.parentNode},builtinPlacements:m.value,popupPlacement:y.value,popupVisible:o.value,popupAlign:$&&{offset:$},action:O?[]:[p.value],mouseEnterDelay:c.value,mouseLeaveDelay:d.value,onPopupVisibleChange:C,forceRender:!0},{popup:function(){var _;return(_=r.popup)===null||_===void 0?void 0:_.call(r,{visible:o.value})},default:r.default})}}}),rD=function(t,n){var r=n.slots,a=n.attrs,o,i=Ni(),l=i.prefixCls,s=i.mode;return g(\"ul\",le(le({},a),{},{class:Se(l.value,\"\".concat(l.value,\"-sub\"),\"\".concat(l.value,\"-\").concat(s.value===\"inline\"?\"inline\":\"vertical\")),\"data-menu-list\":!0}),[(o=r.default)===null||o===void 0?void 0:o.call(r)])};rD.displayName=\"SubMenuList\";var aD=rD,nPe=G({name:\"InlineSubMenuList\",inheritAttrs:!1,props:{id:String,open:Boolean,keyPath:Array},setup:function(t,n){var r=n.slots,a=x(function(){return\"inline\"}),o=Ni(),i=o.motion,l=o.mode,s=o.defaultMotions,c=x(function(){return l.value===a.value}),d=H(!c.value),f=x(function(){return c.value?t.open:!1});ce(l,function(){c.value&&(d.value=!1)},{flush:\"post\"});var p=H({}),v=H(\"\"),m=x(function(){var y,b,C=i.value||((y=s.value)===null||y===void 0?void 0:y[a.value])||((b=s.value)===null||b===void 0?void 0:b.other),S=typeof C==\"function\"?C(p,v):C;return P(P({},S),{appear:t.keyPath.length<=1})});return function(){var y;return d.value?null:g(Uv,{mode:a.value},{default:function(){return[g(Cg,m.value,{default:function(){return[at(g(aD,{id:t.id,style:p.value,class:v.value},{default:function(){return[(y=r.default)===null||y===void 0?void 0:y.call(r)]}}),[[_t,f.value]])]}})]}})}}}),R3=0,rPe={icon:u.VNodeChild,title:u.VNodeChild,disabled:Boolean,level:Number,popupClassName:String,popupOffset:Array,internalPopupClose:Boolean,eventKey:String,expandIcon:Function},sc=G({name:\"ASubMenu\",inheritAttrs:!1,props:rPe,slots:[\"icon\",\"title\",\"expandIcon\"],emits:[\"titleClick\",\"mouseenter\",\"mouseleave\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.emit,i,l;JA(!1);var s=$t(),c=kt(s.vnode.key)===\"symbol\"?String(s.vnode.key):s.vnode.key;uf(kt(s.vnode.key)!==\"symbol\",\"SubMenu\",'SubMenu `:key=\"'.concat(String(c),'\"` not support Symbol type'));var d=tf(c)?c:\"sub_menu_\".concat(++R3,\"_$$_not_set_key\"),f=(i=t.eventKey)!==null&&i!==void 0?i:tf(c)?\"sub_menu_\".concat(++R3,\"_$$_\").concat(c):d,p=j2(),v=p.parentEventKeys,m=p.parentInfo,y=p.parentKeys,b=x(function(){return[].concat(Je(y.value),[d])}),C=x(function(){return[].concat(Je(v.value),[f])}),S=H([]),w={eventKey:f,key:d,parentEventKeys:v,childrenEventKeys:S,parentKeys:y};(l=m.childrenEventKeys)===null||l===void 0||l.value.push(f),Lt(function(){var ee;m.childrenEventKeys&&(m.childrenEventKeys.value=(ee=m.childrenEventKeys)===null||ee===void 0?void 0:ee.value.filter(function(me){return me!=f}))}),XOe(f,d,w);var k=Ni(),$=k.prefixCls,O=k.activeKeys,T=k.disabled,_=k.changeActiveKeys,I=k.mode,L=k.inlineCollapsed,j=k.antdMenuTheme,F=k.openKeys,N=k.overflowDisabled,D=k.onOpenChange,z=k.registerMenuInfo,B=k.unRegisterMenuInfo,M=k.selectedSubMenuEventKeys,E=k.motion,K=k.defaultMotions,W=k.expandIcon;z(f,w),Lt(function(){B(f)});var Y=x(function(){return\"\".concat($.value,\"-submenu\")}),q=x(function(){return T.value||t.disabled}),J=H(),ne=H(),oe=x(function(){return F.value.includes(d)}),Q=x(function(){return!N.value&&oe.value}),ae=x(function(){return M.value.includes(f)}),de=H(!1);ce(O,function(){de.value=!!O.value.find(function(ee){return ee===d})},{immediate:!0});var be=function(me){q.value||(o(\"titleClick\",me,d),I.value===\"inline\"&&D(f,!oe.value))},Ee=function(me){q.value||(_(b.value),o(\"mouseenter\",me))},Pe=function(me){q.value||(_([]),o(\"mouseleave\",me))},Be=nD(x(function(){return C.value.length})),te=function(me){I.value!==\"inline\"&&D(f,me)},ie=function(){_(b.value)},ge=f&&\"\".concat(f,\"-popup\"),ke=x(function(){return Se($.value,\"\".concat($.value,\"-\").concat(j.value),t.popupClassName)}),xe=function(me,He){if(!He)return L.value&&!v.value.length&&me&&typeof me==\"string\"?g(\"div\",{class:\"\".concat($.value,\"-inline-collapsed-noicon\")},[me.charAt(0)]):g(\"span\",{class:\"\".concat($.value,\"-title-content\")},[me]);var lt=zn(me)&&me.type===\"span\";return g(Fe,null,[Ot(He,{class:\"\".concat($.value,\"-item-icon\")},!1),lt?me:g(\"span\",{class:\"\".concat($.value,\"-title-content\")},[me])])},Ie=x(function(){return I.value!==\"inline\"&&C.value.length>1?\"vertical\":I.value}),ye=x(function(){return I.value===\"horizontal\"?\"vertical\":I.value}),pe=H({}),ue=H(\"\"),Ce=x(function(){var ee,me,He=E.value||((ee=K.value)===null||ee===void 0?void 0:ee[I.value])||((me=K.value)===null||me===void 0?void 0:me.other),lt=typeof He==\"function\"?He(pe,ue):He;return lt?Lo(lt.name):void 0}),je=x(function(){return Ie.value===\"horizontal\"?\"vertical\":Ie.value});return function(){var ee,me,He=jn(r,t,\"icon\"),lt=xe(jn(r,t,\"title\"),He),Ye=Y.value,he=t.expandIcon||r.expandIcon||W,_e=g(\"div\",{style:Be.value,class:\"\".concat(Ye,\"-title\"),tabindex:q.value?null:-1,ref:J,title:typeof lt==\"string\"?lt:null,\"data-menu-id\":d,\"aria-expanded\":Q.value,\"aria-haspopup\":!0,\"aria-controls\":ge,\"aria-disabled\":q.value,onClick:be,onFocus:ie},[lt,I.value!==\"horizontal\"&&he?he(P(P({},t),{isOpen:Q.value})):g(\"i\",{class:\"\".concat(Ye,\"-arrow\")},null)]);if(!N.value&&I.value!==\"inline\"){var $e=Ie.value,Ve=function(){return _e}();_e=g(D3,{mode:$e,prefixCls:Ye,visible:!t.internalPopupClose&&Q.value,popupClassName:ke.value,popupOffset:t.popupOffset,disabled:q.value,onVisibleChange:te},{default:function(){return[Ve]},popup:function(Ut){var Ft=Ut.visible,Jt;return g(Uv,{mode:je.value,isRootMenu:!1},{default:function(){return[g(Cg,Ce.value,{default:function(){return[at(g(aD,{id:ge,ref:ne},{default:function(){return[(Jt=r.default)===null||Jt===void 0?void 0:Jt.call(r)]}}),[[_t,Ft]])]}})]}})}})}else{var st=function(){return _e}();_e=g(D3,null,{default:function(){return[st]}})}return g(Uv,{mode:ye.value},{default:function(){return[g(Zl.Item,le(le({component:\"li\"},a),{},{role:\"none\",class:Se(Ye,\"\".concat(Ye,\"-\").concat(I.value),a.class,(ee={},V(ee,\"\".concat(Ye,\"-open\"),Q.value),V(ee,\"\".concat(Ye,\"-active\"),de.value),V(ee,\"\".concat(Ye,\"-selected\"),ae.value),V(ee,\"\".concat(Ye,\"-disabled\"),q.value),ee)),onMouseenter:Ee,onMouseleave:Pe,\"data-submenu-id\":d}),{default:function(){return[_e,!N.value&&g(nPe,{id:ge,open:Q.value,keyPath:b.value},{default:function(){return[(me=r.default)===null||me===void 0?void 0:me.call(r)]}})]}})]}})}}}),aPe={prefixCls:String,disabled:Boolean,inlineCollapsed:Boolean,disabledOverflow:Boolean,openKeys:Array,selectedKeys:Array,activeKey:String,selectable:{type:Boolean,default:!0},multiple:{type:Boolean,default:!1},motion:Object,theme:{type:String,default:\"light\"},mode:{type:String,default:\"vertical\"},inlineIndent:{type:Number,default:24},subMenuOpenDelay:{type:Number,default:.1},subMenuCloseDelay:{type:Number,default:.1},builtinPlacements:{type:Object},triggerSubMenuAction:{type:String,default:\"hover\"},getPopupContainer:Function,expandIcon:Function},L3=[],jr=G({name:\"AMenu\",props:aPe,emits:[\"update:openKeys\",\"openChange\",\"select\",\"deselect\",\"update:selectedKeys\",\"click\",\"update:activeKey\"],slots:[\"expandIcon\",\"overflowedIndicator\"],setup:function(t,n){var r=n.slots,a=n.emit,o=Wt(\"menu\",t),i=o.prefixCls,l=o.direction,s=H({}),c=ve(QA,H(void 0)),d=x(function(){return c.value!==void 0?c.value:t.inlineCollapsed}),f=H(!1);et(function(){f.value=!0}),Wn(function(){uf(!(t.inlineCollapsed===!0&&t.mode!==\"inline\"),\"Menu\",\"`inlineCollapsed` should only be used when `mode` is inline.\"),uf(!(c.value!==void 0&&t.inlineCollapsed===!0),\"Menu\",\"`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.\")});var p=H([]),v=H([]),m=H({});ce(s,function(){for(var W={},Y=0,q=Object.values(s.value);Y<q.length;Y++){var J=q[Y];W[J.key]=J}m.value=W},{flush:\"post\"}),Wn(function(){if(t.activeKey!==void 0){var W=[],Y=t.activeKey?m.value[t.activeKey]:void 0;Y&&t.activeKey!==void 0?W=[].concat(Je(Y.parentKeys),[t.activeKey]):W=[],Mr(p.value,W)||(p.value=W)}}),ce(function(){return t.selectedKeys},function(W){v.value=W||v.value},{immediate:!0});var y=H([]);ce([m,v],function(){var W=[];v.value.forEach(function(Y){var q=m.value[Y];if(q){var J;(J=W).push.apply(J,Je(A(q.parentEventKeys)))}}),W=eU(W),Mr(y.value,W)||(y.value=W)},{immediate:!0});var b=function(Y){if(!!t.selectable){var q=Y.key,J=v.value.includes(q),ne;t.multiple?J?ne=v.value.filter(function(Q){return Q!==q}):ne=[].concat(Je(v.value),[q]):ne=[q];var oe=P(P({},Y),{selectedKeys:ne});Mr(ne,v.value)||(t.selectedKeys===void 0&&(v.value=ne),a(\"update:selectedKeys\",ne),J&&t.multiple?a(\"deselect\",oe):a(\"select\",oe)),O.value!==\"inline\"&&!t.multiple&&C.value.length&&I(L3)}},C=H([]);ce(function(){return t.openKeys},function(){var W=arguments.length>0&&arguments[0]!==void 0?arguments[0]:C.value;Mr(C.value,W)||(C.value=W)},{immediate:!0});var S,w=function(Y){window.clearTimeout(S),S=window.setTimeout(function(){t.activeKey===void 0&&(p.value=Y),a(\"update:activeKey\",Y[Y.length-1])})},k=x(function(){return!!t.disabled}),$=x(function(){return l.value===\"rtl\"}),O=H(\"vertical\"),T=H(!1);Wn(function(){(t.mode===\"inline\"||t.mode===\"vertical\")&&d.value?(O.value=\"vertical\",T.value=d.value):(O.value=t.mode,T.value=!1)});var _=x(function(){return O.value===\"inline\"}),I=function(Y){C.value=Y,a(\"update:openKeys\",Y),a(\"openChange\",Y)},L=H(C.value),j=H(!1);ce(C,function(){_.value&&(L.value=C.value)},{immediate:!0}),ce(_,function(){if(!j.value){j.value=!0;return}_.value?C.value=L.value:I(L3)},{immediate:!0});var F=x(function(){var W;return W={},V(W,\"\".concat(i.value),!0),V(W,\"\".concat(i.value,\"-root\"),!0),V(W,\"\".concat(i.value,\"-\").concat(O.value),!0),V(W,\"\".concat(i.value,\"-inline-collapsed\"),T.value),V(W,\"\".concat(i.value,\"-rtl\"),$.value),V(W,\"\".concat(i.value,\"-\").concat(t.theme),!0),W}),N={horizontal:{name:\"ant-slide-up\"},inline:wke,other:{name:\"ant-zoom-big\"}};JA(!0);var D=function W(){var Y=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],q=[],J=s.value;return Y.forEach(function(ne){var oe=J[ne],Q=oe.key,ae=oe.childrenEventKeys;q.push.apply(q,[Q].concat(Je(W(ae))))}),q},z=function(Y){a(\"click\",Y),b(Y)},B=function(Y,q){var J=s.value[Y],ne=J.key,oe=J.childrenEventKeys,Q=C.value.filter(function(de){return de!==ne});if(q)Q.push(ne);else if(O.value!==\"inline\"){var ae=D(oe);Q=Q.filter(function(de){return!ae.includes(de)})}Mr(C,Q)||I(Q)},M=function(Y,q){s.value=P(P({},s.value),V({},Y,q))},E=function(Y){delete s.value[Y],s.value=P({},s.value)},K=H(0);return qOe({store:s,prefixCls:i,activeKeys:p,openKeys:C,selectedKeys:v,changeActiveKeys:w,disabled:k,rtl:$,mode:O,inlineIndent:x(function(){return t.inlineIndent}),subMenuCloseDelay:x(function(){return t.subMenuCloseDelay}),subMenuOpenDelay:x(function(){return t.subMenuOpenDelay}),builtinPlacements:x(function(){return t.builtinPlacements}),triggerSubMenuAction:x(function(){return t.triggerSubMenuAction}),getPopupContainer:x(function(){return t.getPopupContainer}),inlineCollapsed:T,antdMenuTheme:x(function(){return t.theme}),siderCollapsed:c,defaultMotions:x(function(){return f.value?N:null}),motion:x(function(){return f.value?t.motion:null}),overflowDisabled:H(void 0),onOpenChange:B,onItemClick:z,registerMenuInfo:M,unRegisterMenuInfo:E,selectedSubMenuEventKeys:y,isRootMenu:H(!0),expandIcon:t.expandIcon||r.expandIcon}),function(){var W,Y,q=Un((W=r.default)===null||W===void 0?void 0:W.call(r)),J=K.value>=q.length-1||O.value!==\"horizontal\"||t.disabledOverflow,ne=O.value!==\"horizontal\"||t.disabledOverflow?q:q.map(function(Q,ae){return g(Uv,{key:Q.key,overflowDisabled:ae>K.value},{default:function(){return[Q]}})}),oe=((Y=r.overflowedIndicator)===null||Y===void 0?void 0:Y.call(r))||g(YA,null,null);return g(Zl,{prefixCls:\"\".concat(i.value,\"-overflow\"),component:\"ul\",itemComponent:fl,class:F.value,role:\"menu\",data:ne,renderRawItem:function(ae){return ae},renderRawRest:function(ae){var de=ae.length,be=de?q.slice(-de):null;return g(sc,{eventKey:Zl.OVERFLOW_KEY,title:oe,disabled:J,internalPopupClose:de===0},{default:function(){return[be]}})},maxCount:O.value!==\"horizontal\"||t.disabledOverflow?Zl.INVALIDATE:Zl.RESPONSIVE,ssr:\"full\",\"data-menu-list\":!0,onVisibleChange:function(ae){K.value=ae}},null)}}}),oPe={title:u.VNodeChild},Yv=G({name:\"AMenuItemGroup\",inheritAttrs:!1,props:oPe,slots:[\"title\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=Ni(),i=o.prefixCls,l=x(function(){return\"\".concat(i.value,\"-item-group\")});return function(){var s;return g(\"li\",le(le({},a),{},{onClick:function(d){return d.stopPropagation()},class:l.value}),[g(\"div\",{title:typeof t.title==\"string\"?t.title:void 0,class:\"\".concat(l.value,\"-title\")},[jn(r,t,\"title\")]),g(\"ul\",{class:\"\".concat(l.value,\"-list\")},[(s=r.default)===null||s===void 0?void 0:s.call(r)])])}}}),qv=G({name:\"AMenuDivider\",setup:function(){var t=Ni(),n=t.prefixCls;return function(){return g(\"li\",{class:\"\".concat(n.value,\"-item-divider\")},null)}}});jr.install=function(e){return e.component(jr.name,jr),e.component(fl.name,fl),e.component(sc.name,sc),e.component(qv.name,qv),e.component(Yv.name,Yv),e};jr.Item=fl;jr.Divider=qv;jr.SubMenu=sc;jr.ItemGroup=Yv;var iPe={prefixCls:u.string,routes:{type:Array},params:u.any,separator:u.any,itemRender:{type:Function}};function lPe(e,t){if(!e.breadcrumbName)return null;var n=Object.keys(t).join(\"|\"),r=e.breadcrumbName.replace(new RegExp(\":(\".concat(n,\")\"),\"g\"),function(a,o){return t[o]||a});return r}function F3(e){var t=e.route,n=e.params,r=e.routes,a=e.paths,o=r.indexOf(t)===r.length-1,i=lPe(t,n);return o?g(\"span\",null,[i]):g(\"a\",{href:\"#/\".concat(a.join(\"/\"))},[i])}var us=G({name:\"ABreadcrumb\",props:iPe,slots:[\"separator\",\"itemRender\"],setup:function(t,n){var r=n.slots,a=Wt(\"breadcrumb\",t),o=a.prefixCls,i=a.direction,l=function(f,p){return f=(f||\"\").replace(/^\\//,\"\"),Object.keys(p).forEach(function(v){f=f.replace(\":\".concat(v),p[v])}),f},s=function(f){var p=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"\",v=arguments.length>2?arguments[2]:void 0,m=Je(f),y=l(p,v);return y&&m.push(y),m},c=function(f){var p=f.routes,v=p===void 0?[]:p,m=f.params,y=m===void 0?{}:m,b=f.separator,C=f.itemRender,S=C===void 0?F3:C,w=[];return v.map(function(k){var $=l(k.path,y);$&&w.push($);var O=[].concat(w),T=null;return k.children&&k.children.length&&(T=g(jr,null,{default:function(){return[k.children.map(function(I){return g(jr.Item,{key:I.path||I.breadcrumbName},{default:function(){return[S({route:I,params:y,routes:v,paths:s(O,I.path,y)})]}})})]}})),g(df,{overlay:T,separator:b,key:$||k.breadcrumbName},{default:function(){return[S({route:k,params:y,routes:v,paths:O})]}})})};return function(){var d,f,p,v=t.routes,m=t.params,y=m===void 0?{}:m,b=Un(jn(r,t)),C=(f=jn(r,t,\"separator\"))!==null&&f!==void 0?f:\"/\",S=t.itemRender||r.itemRender||F3;v&&v.length>0?p=c({routes:v,params:y,separator:C,itemRender:S}):b.length&&(p=b.map(function(k,$){return on(kt(k.type)===\"object\"&&(k.type.__ANT_BREADCRUMB_ITEM||k.type.__ANT_BREADCRUMB_SEPARATOR),\"Breadcrumb\",\"Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children\"),hr(k,{separator:C,key:$})}));var w=(d={},V(d,o.value,!0),V(d,\"\".concat(o.value,\"-rtl\"),i.value===\"rtl\"),d);return g(\"div\",{class:w},[p])}}}),sPe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},uPe={prefixCls:u.string},Gv=G({name:\"ABreadcrumbSeparator\",__ANT_BREADCRUMB_SEPARATOR:!0,inheritAttrs:!1,props:uPe,setup:function(t,n){var r=n.slots,a=n.attrs,o=Wt(\"breadcrumb\",t),i=o.prefixCls;return function(){var l;a.separator;var s=a.class,c=sPe(a,[\"separator\",\"class\"]),d=Un((l=r.default)===null||l===void 0?void 0:l.call(r));return g(\"span\",le({class:[\"\".concat(i.value,\"-separator\"),s]},c),[d.length>0?d:\"/\"])}}});us.Item=df;us.Separator=Gv;us.install=function(e){return e.component(us.name,us),e.component(df.name,df),e.component(Gv.name,Gv),e};var Vl={DATE_ROW_COUNT:6,DATE_COL_COUNT:7},oD=function(t,n){for(var r=n.attrs,a=r.value,o=a.localeData(),i=r.prefixCls,l=[],s=[],c=o.firstDayOfWeek(),d,f=Ue(),p=0;p<Vl.DATE_COL_COUNT;p++){var v=(c+p)%Vl.DATE_COL_COUNT;f.day(v),l[p]=o.weekdaysMin(f),s[p]=o.weekdaysShort(f)}r.showWeekNumber&&(d=g(\"th\",{role:\"columnheader\",class:\"\".concat(i,\"-column-header \").concat(i,\"-week-number-header\")},[g(\"span\",{class:\"\".concat(i,\"-column-header-inner\")},[yt(\"x\")])]));var m=s.map(function(y,b){return g(\"th\",{key:b,role:\"columnheader\",title:y,class:\"\".concat(i,\"-column-header\")},[g(\"span\",{class:\"\".concat(i,\"-column-header-inner\")},[l[b]])])});return g(\"thead\",null,[g(\"tr\",{role:\"row\"},[d,m])])};oD.inheritAttrs=!1;var cPe=oD,dPe={disabledHours:function(){return[]},disabledMinutes:function(){return[]},disabledSeconds:function(){return[]}};function hl(e){var t=Ue();return t.locale(e.locale()).utcOffset(e.utcOffset()),t}function iD(e){return e.format(\"LL\")}function fPe(e){var t=hl(e);return iD(t)}function lD(e){var t=e.locale(),n=e.localeData();return n[t===\"zh-cn\"?\"months\":\"monthsShort\"](e)}function Sa(e,t){!Ue.isMoment(e)||!Ue.isMoment(t)||(t.hour(e.hour()),t.minute(e.minute()),t.second(e.second()),t.millisecond(e.millisecond()))}function K2(e,t){var n=t?t(e):{};return n=P(P({},dPe),n),n}function hPe(e,t){var n=!1;if(e){var r=e.hour(),a=e.minute(),o=e.second(),i=t.disabledHours();if(i.indexOf(r)===-1){var l=t.disabledMinutes(r);if(l.indexOf(a)===-1){var s=t.disabledSeconds(r,a);n=s.indexOf(o)!==-1}else n=!0}else n=!0}return!n}function pPe(e,t){var n=K2(e,t);return hPe(e,n)}function Xv(e,t,n){return!(t&&t(e)||n&&!pPe(e,n))}function qy(e,t){if(!e)return\"\";if(Array.isArray(t)&&(t=t[0]),typeof t==\"function\"){var n=t(e);if(typeof n==\"string\")return n;throw new Error(\"The function of format does not return a string\")}return e.format(t)}function xh(){}function Uc(e,t){return e&&t&&e.isSame(t,\"day\")}function vPe(e,t){return e.year()<t.year()?1:e.year()===t.year()&&e.month()<t.month()}function mPe(e,t){return e.year()>t.year()?1:e.year()===t.year()&&e.month()>t.month()}function gPe(e){return\"rc-calendar-\".concat(e.year(),\"-\").concat(e.month(),\"-\").concat(e.date())}var yPe={name:\"DateTBody\",inheritAttrs:!1,props:{contentRender:u.func,dateRender:u.func,disabledDate:u.func,prefixCls:u.string,selectedValue:u.any,value:u.object,hoverValue:u.any.def([]),showWeekNumber:u.looseBool},render:function(){var t=Qe(this),n=t.contentRender,r=t.prefixCls,a=t.selectedValue,o=t.value,i=t.showWeekNumber,l=t.dateRender,s=t.disabledDate,c=t.hoverValue,d=this.$attrs,f=d.onSelect,p=f===void 0?xh:f,v=d.onDayHover,m=v===void 0?xh:v,y,b,C,S=[],w=hl(o),k=\"\".concat(r,\"-cell\"),$=\"\".concat(r,\"-week-number-cell\"),O=\"\".concat(r,\"-date\"),T=\"\".concat(r,\"-today\"),_=\"\".concat(r,\"-selected-day\"),I=\"\".concat(r,\"-selected-date\"),L=\"\".concat(r,\"-selected-start-date\"),j=\"\".concat(r,\"-selected-end-date\"),F=\"\".concat(r,\"-in-range-cell\"),N=\"\".concat(r,\"-last-month-cell\"),D=\"\".concat(r,\"-next-month-btn-day\"),z=\"\".concat(r,\"-disabled-cell\"),B=\"\".concat(r,\"-disabled-cell-first-of-row\"),M=\"\".concat(r,\"-disabled-cell-last-of-row\"),E=\"\".concat(r,\"-last-day-of-month\"),K=o.clone();K.date(1);var W=K.day(),Y=(W+7-o.localeData().firstDayOfWeek())%7,q=K.clone();q.add(0-Y,\"days\");var J=0;for(y=0;y<Vl.DATE_ROW_COUNT;y++)for(b=0;b<Vl.DATE_COL_COUNT;b++)C=q,J&&(C=C.clone(),C.add(J,\"days\")),S.push(C),J++;var ne=[];for(J=0,y=0;y<Vl.DATE_ROW_COUNT;y++){var oe,Q=void 0,ae=void 0,de=!1,be=[];for(i&&(ae=g(\"td\",{key:\"week-\".concat(S[J].week()),role:\"gridcell\",class:$},[S[J].week()])),b=0;b<Vl.DATE_COL_COUNT;b++){var Ee=null,Pe=null;C=S[J],b<Vl.DATE_COL_COUNT-1&&(Ee=S[J+1]),b>0&&(Pe=S[J-1]);var Be=k,te=!1,ie=!1;Uc(C,w)&&(Be+=\" \".concat(T),Q=!0);var ge=vPe(C,o),ke=mPe(C,o);if(a&&Array.isArray(a)){var xe=c.length?c:a;if(!ge&&!ke){var Ie=xe[0],ye=xe[1];Ie&&Uc(C,Ie)&&(ie=!0,de=!0,Be+=\" \".concat(L)),(Ie||ye)&&(Uc(C,ye)?(ie=!0,de=!0,Be+=\" \".concat(j)):(Ie==null&&C.isBefore(ye,\"day\")||ye==null&&C.isAfter(Ie,\"day\")||C.isAfter(Ie,\"day\")&&C.isBefore(ye,\"day\"))&&(Be+=\" \".concat(F)))}}else Uc(C,o)&&(ie=!0,de=!0);Uc(C,a)&&(Be+=\" \".concat(I)),ge&&(Be+=\" \".concat(N)),ke&&(Be+=\" \".concat(D)),C.clone().endOf(\"month\").date()===C.date()&&(Be+=\" \".concat(E)),s&&s(C,o)&&(te=!0,(!Pe||!s(Pe,o))&&(Be+=\" \".concat(B)),(!Ee||!s(Ee,o))&&(Be+=\" \".concat(M))),ie&&(Be+=\" \".concat(_)),te&&(Be+=\" \".concat(z));var pe=void 0;if(l)pe=l({current:C,today:o});else{var ue=n?n({current:C,today:o}):C.date();pe=g(\"div\",{key:gPe(C),class:O,\"aria-selected\":ie,\"aria-disabled\":te},[ue])}be.push(g(\"td\",{key:J,onClick:te?xh:p.bind(null,C),onMouseenter:te?xh:m.bind(null,C),role:\"gridcell\",title:iD(C),class:Be},[pe])),J++}ne.push(g(\"tr\",{key:y,role:\"row\",class:Se((oe={},V(oe,\"\".concat(r,\"-current-week\"),Q),V(oe,\"\".concat(r,\"-active-week\"),de),oe))},[ae,be]))}return g(\"tbody\",{class:\"\".concat(r,\"-tbody\")},[ne])}},bPe=yPe,sD=function(t,n){var r=n.attrs,a=r.prefixCls;return g(\"table\",{class:\"\".concat(a,\"-table\"),cellspacing:\"0\",role:\"grid\"},[g(cPe,r,null),g(bPe,r,null)])};sD.inheritAttrs=!1;var W2=sD,CPe=4,wPe=3;function SPe(){}var kPe={name:\"MonthTable\",inheritAttrs:!1,mixins:[nt],props:{cellRender:u.func,prefixCls:u.string,value:u.object,locale:u.any,contentRender:u.any,disabledDate:u.func},data:function(){return{sValue:this.value}},watch:{value:function(t){this.setState({sValue:t})}},methods:{setAndSelectValue:function(t){this.setState({sValue:t}),this.__emit(\"select\",t)},chooseMonth:function(t){var n=this.sValue.clone();n.month(t),this.setAndSelectValue(n)},months:function(){for(var t=this.sValue,n=t.clone(),r=[],a=0,o=0;o<CPe;o++){r[o]=[];for(var i=0;i<wPe;i++){n.month(a);var l=lD(n);r[o][i]={value:a,content:l,title:l},a++}}return r}},render:function(){var t=this,n=this.$props,r=this.sValue,a=hl(r),o=this.months(),i=r.month(),l=n.prefixCls,s=n.locale,c=n.contentRender,d=n.cellRender,f=n.disabledDate,p=o.map(function(v,m){var y=v.map(function(b){var C,S=!1;if(f){var w=r.clone();w.month(b.value),S=f(w)}var k=(C={},V(C,\"\".concat(l,\"-cell\"),1),V(C,\"\".concat(l,\"-cell-disabled\"),S),V(C,\"\".concat(l,\"-selected-cell\"),b.value===i),V(C,\"\".concat(l,\"-current-cell\"),a.year()===r.year()&&b.value===a.month()),C),$;if(d){var O=r.clone();O.month(b.value),$=d({current:O,locale:s})}else{var T;if(c){var _=r.clone();_.month(b.value),T=c({current:_,locale:s})}else T=b.content;$=g(\"a\",{class:\"\".concat(l,\"-month\")},[T])}return g(\"td\",{role:\"gridcell\",key:b.value,onClick:S?SPe:function(){return t.chooseMonth(b.value)},title:b.title,class:k},[$])});return g(\"tr\",{key:m,role:\"row\"},[y])});return g(\"table\",{class:\"\".concat(l,\"-table\"),cellspacing:\"0\",role:\"grid\"},[g(\"tbody\",{class:\"\".concat(l,\"-tbody\")},[p])])}},uD=kPe;function _h(){}function Zv(e){var t;return e?t=hl(e):t=Ue(),t}function $Pe(e){return Array.isArray(e)?e.length===0||e.findIndex(function(t){return t===void 0||Ue.isMoment(t)})!==-1:e===void 0||Ue.isMoment(e)}var B3=u.custom($Pe),OPe={mixins:[nt],inheritAttrs:!1,name:\"CalendarMixinWrapper\",props:{value:B3,defaultValue:B3},data:function(){this.onKeyDown===void 0&&(this.onKeyDown=_h),this.onBlur===void 0&&(this.onBlur=_h);var t=this.$props,n=t.value||t.defaultValue||Zv();return{sValue:n,sSelectedValue:t.selectedValue||t.defaultSelectedValue}},watch:{value:function(t){var n=t||this.defaultValue||Zv(this.sValue);this.setState({sValue:n})},selectedValue:function(t){this.setState({sSelectedValue:t})}},methods:{onSelect:function(t,n){t&&this.setValue(t),this.setSelectedValue(t,n)},renderRoot:function(t){var n,r=P(P({},this.$props),this.$attrs),a=r.prefixCls,o=(n={},V(n,a,1),V(n,\"\".concat(a,\"-hidden\"),!r.visible),V(n,r.class,!!r.class),V(n,t.class,!!t.class),n);return g(\"div\",{ref:this.saveRoot,class:o,tabindex:\"0\",onKeydown:this.onKeyDown||_h,onBlur:this.onBlur||_h},[t.children])},setSelectedValue:function(t,n){vt(this,\"selectedValue\")||this.setState({sSelectedValue:t}),this.__emit(\"select\",t,n)},setValue:function(t){var n=this.sValue;vt(this,\"value\")||this.setState({sValue:t}),(n&&t&&!n.isSame(t)||!n&&t||n&&!t)&&this.__emit(\"change\",t)},isAllowedDate:function(t){var n=this.disabledDate,r=this.disabledTime;return Xv(t,n,r)}}},U2=OPe,$g={methods:{getFormat:function(){var t=this.format,n=this.locale,r=this.timePicker;return t||(r?t=n.dateTimeFormat:t=n.dateFormat),t},focus:function(){this.focusElement?this.focusElement.focus():this.rootInstance&&this.rootInstance.focus()},saveFocusElement:function(t){this.focusElement=t},saveRoot:function(t){this.rootInstance=t}}},PPe={name:\"CalendarHeader\",inheritAttrs:!1,mixins:[nt],props:{value:u.object,locale:u.object,yearSelectOffset:u.number.def(10),yearSelectTotal:u.number.def(20),Select:u.object,prefixCls:u.string,type:u.string,showTypeSwitch:u.looseBool,headerComponents:u.array},methods:{onYearChange:function(t){var n=this.value.clone();n.year(parseInt(t,10)),this.__emit(\"valueChange\",n)},onMonthChange:function(t){var n=this.value.clone();n.month(parseInt(t,10)),this.__emit(\"valueChange\",n)},yearSelectElement:function(t){for(var n=this.yearSelectOffset,r=this.yearSelectTotal,a=this.prefixCls,o=this.Select,i=t-n,l=i+r,s=[],c=function(p){s.push(g(o.Option,{key:\"\".concat(p)},{default:function(){return[function(){return p}()]}}))},d=i;d<l;d++)c(d);return g(o,{class:\"\".concat(a,\"-header-year-select\"),onChange:this.onYearChange,dropdownStyle:{zIndex:2e3},dropdownMenuStyle:{maxHeight:\"250px\",overflow:\"auto\",fontSize:\"12px\"},optionLabelProp:\"children\",value:String(t),showSearch:!1},{default:function(){return[s]}})},monthSelectElement:function(t){for(var n=this.value,r=this.Select,a=this.prefixCls,o=n.clone(),i=[],l=0;l<12;l++)o.month(l),i.push(g(r.Option,{key:\"\".concat(l)},{default:function(){return[function(){return lD(o)}()]}}));return g(r,{class:\"\".concat(a,\"-header-month-select\"),dropdownStyle:{zIndex:2e3},dropdownMenuStyle:{maxHeight:\"250px\",overflow:\"auto\",overflowX:\"hidden\",fontSize:\"12px\"},optionLabelProp:\"children\",value:String(t),showSearch:!1,onChange:this.onMonthChange},{default:function(){return[i]}})},changeTypeToDate:function(){this.__emit(\"typeChange\",\"date\")},changeTypeToMonth:function(){this.__emit(\"typeChange\",\"month\")}},render:function(){var t=this.value,n=this.locale,r=this.prefixCls,a=this.type,o=this.showTypeSwitch,i=this.headerComponents,l=t.year(),s=t.month(),c=this.yearSelectElement(l),d=a===\"month\"?null:this.monthSelectElement(s),f=\"\".concat(r,\"-header-switcher\"),p=o?g(\"span\",{class:f},[a===\"date\"?g(\"span\",{class:\"\".concat(f,\"-focus\")},[n.month]):g(\"span\",{onClick:this.changeTypeToDate,class:\"\".concat(f,\"-normal\")},[n.month]),a===\"month\"?g(\"span\",{class:\"\".concat(f,\"-focus\")},[n.year]):g(\"span\",{onClick:this.changeTypeToMonth,class:\"\".concat(f,\"-normal\")},[n.year])]):null;return g(\"div\",{class:\"\".concat(r,\"-header\")},[p,d,c,i])}},TPe=PPe,xPe=G({name:\"FullCalendar\",mixins:[nt,$g,U2],inheritAttrs:!1,props:{locale:u.object.def(Nf),format:u.oneOfType([u.string,u.array,u.func]),visible:u.looseBool.def(!0),prefixCls:u.string.def(\"rc-calendar\"),defaultType:u.string.def(\"date\"),type:u.string,fullscreen:u.looseBool.def(!1),monthCellRender:u.func,dateCellRender:u.func,showTypeSwitch:u.looseBool.def(!0),Select:u.object.isRequired,headerComponents:u.array,headerComponent:u.object,headerRender:u.func,showHeader:u.looseBool.def(!0),disabledDate:u.func,value:u.object,defaultValue:u.object,selectedValue:u.object,defaultSelectedValue:u.object,renderFooter:u.func.def(function(){return null}),renderSidebar:u.func.def(function(){return null})},data:function(){var t;vt(this,\"type\")?t=this.type:t=this.defaultType;var n=this.$props;return{sType:t,sValue:n.value||n.defaultValue||Ue(),sSelectedValue:n.selectedValue||n.defaultSelectedValue}},watch:{type:function(t){this.setState({sType:t})},value:function(t){var n=t||this.defaultValue||Zv(this.sValue);this.setState({sValue:n})},selectedValue:function(t){this.setState({sSelectedValue:t})}},methods:{onMonthSelect:function(t){this.onSelect(t,{target:\"month\"})},setType:function(t){vt(this,\"type\")||this.setState({sType:t}),this.__emit(\"typeChange\",t)}},render:function(){var t=Qe(this),n=t.locale,r=t.prefixCls,a=t.fullscreen,o=t.showHeader,i=t.headerComponent,l=t.headerRender,s=t.disabledDate,c=this.sValue,d=this.sType,f=null;if(o)if(l)f=l(c,d,n);else{var p=i||TPe,v=P(P(P({},t),this.$attrs),{prefixCls:\"\".concat(r,\"-full\"),type:d,value:c,onTypeChange:this.setType,onValueChange:this.setValue,key:\"calendar-header\"});f=g(p,v,null)}var m=d===\"date\"?g(W2,{dateRender:t.dateCellRender,contentRender:t.dateCellContentRender,locale:n,prefixCls:r,onSelect:this.onSelect,value:c,disabledDate:s},null):g(uD,{cellRender:t.monthCellRender,contentRender:t.monthCellContentRender,locale:n,onSelect:this.onMonthSelect,prefixCls:\"\".concat(r,\"-month-panel\"),value:c,disabledDate:s},null),y=[f,g(\"div\",{key:\"calendar-body\",class:\"\".concat(r,\"-calendar-body\")},[m])],b=[\"\".concat(r,\"-full\")];return a&&b.push(\"\".concat(r,\"-fullscreen\")),this.renderRoot({children:y,class:b.join(\" \")})}}),_Pe=xPe,EPe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},cD=G({name:\"Checkbox\",mixins:[nt],inheritAttrs:!1,props:An({prefixCls:u.string,name:u.string,id:u.string,type:u.string,defaultChecked:an(u.oneOfType([u.number,u.looseBool])),checked:an(u.oneOfType([u.number,u.looseBool])),disabled:u.looseBool,tabindex:u.oneOfType([u.string,u.number]),readonly:u.looseBool,autofocus:u.looseBool,value:u.any},{prefixCls:\"rc-checkbox\",type:\"checkbox\",defaultChecked:!1}),data:function(){var t=vt(this,\"checked\")?this.checked:this.defaultChecked;return{sChecked:t}},watch:{checked:function(t){this.sChecked=t}},mounted:function(){Ne(function(){})},methods:{focus:function(){this.$refs.input.focus()},blur:function(){this.$refs.input.blur()},handleChange:function(t){var n=Qe(this);if(!n.disabled){\"checked\"in n||(this.sChecked=t.target.checked),t.shiftKey=this.eventShiftKey;var r={target:P(P({},n),{checked:t.target.checked}),stopPropagation:function(){t.stopPropagation()},preventDefault:function(){t.preventDefault()},nativeEvent:t};\"checked\"in n&&(this.$refs.input.checked=n.checked),this.__emit(\"change\",r),this.eventShiftKey=!1}},onClick:function(t){this.__emit(\"click\",t),this.eventShiftKey=t.shiftKey}},render:function(){var t,n=Qe(this),r=n.prefixCls,a=n.name,o=n.id,i=n.type,l=n.disabled,s=n.readonly,c=n.tabindex,d=n.autofocus,f=n.value,p=EPe(n,[\"prefixCls\",\"name\",\"id\",\"type\",\"disabled\",\"readonly\",\"tabindex\",\"autofocus\",\"value\"]),v=this.$attrs,m=v.class,y=v.onFocus,b=v.onBlur,C=Object.keys(P(P({},p),this.$attrs)).reduce(function($,O){return(O.substr(0,5)===\"aria-\"||O.substr(0,5)===\"data-\"||O===\"role\")&&($[O]=p[O]),$},{}),S=this.sChecked,w=Se(r,m,(t={},V(t,\"\".concat(r,\"-checked\"),S),V(t,\"\".concat(r,\"-disabled\"),l),t)),k=P(P({name:a,id:o,type:i,readonly:s,disabled:l,tabindex:c,class:\"\".concat(r,\"-input\"),checked:!!S,autofocus:d,value:f},C),{onChange:this.handleChange,onClick:this.onClick,onFocus:y,onBlur:b});return g(\"span\",{class:w},[g(\"input\",le({ref:\"input\"},k),null),g(\"span\",{class:\"\".concat(r,\"-inner\")},null)])}}),MPe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},dD={prefixCls:u.string,defaultChecked:u.looseBool,checked:u.looseBool,disabled:u.looseBool,isGroup:u.looseBool,value:u.any,name:u.string,id:u.string,autofocus:u.looseBool,type:u.string.def(\"radio\"),onChange:u.func,onFocus:u.func,onBlur:u.func},_r=G({name:\"ARadio\",props:dD,emits:[\"update:checked\",\"update:value\",\"change\",\"blur\",\"focus\"],setup:function(){return{configProvider:ve(\"configProvider\",St),radioGroupContext:ve(\"radioGroupContext\",null)}},methods:{focus:function(){this.$refs.vcCheckbox.focus()},blur:function(){this.$refs.vcCheckbox.blur()},handleChange:function(t){var n=t.target.checked;this.$emit(\"update:checked\",n),this.$emit(\"update:value\",n),this.$emit(\"change\",t)},onChange2:function(t){this.$emit(\"change\",t),this.radioGroupContext&&this.radioGroupContext.onRadioChange&&this.radioGroupContext.onRadioChange(t)}},render:function(){var t,n=this.$slots,r=this.radioGroupContext,a=Qe(this),o=a.prefixCls,i=MPe(a,[\"prefixCls\"]),l=this.configProvider.getPrefixCls,s=l(\"radio\",o),c=P({prefixCls:s},i);r?(c.name=r.name,c.onChange=this.onChange2,c.checked=a.value===r.stateValue,c.disabled=a.disabled||r.disabled):c.onChange=this.handleChange;var d=Se((t={},V(t,\"\".concat(s,\"-wrapper\"),!0),V(t,\"\".concat(s,\"-wrapper-checked\"),c.checked),V(t,\"\".concat(s,\"-wrapper-disabled\"),c.disabled),t));return g(\"label\",{class:d},[g(cD,le(le({},c),{},{ref:\"vcCheckbox\"}),null),n.default&&g(\"span\",null,[n.default()])])}}),Y2=G({name:\"ARadioGroup\",props:{prefixCls:u.string,defaultValue:u.any,value:u.any,size:u.oneOf(rt(\"large\",\"default\",\"small\")).def(\"default\"),options:u.array,disabled:u.looseBool,name:u.string,buttonStyle:u.string.def(\"outline\"),onChange:u.func},emits:[\"update:value\",\"change\"],setup:function(){return{updatingValue:!1,configProvider:ve(\"configProvider\",St),radioGroupContext:null}},data:function(){var t=this.value,n=this.defaultValue;return{stateValue:t===void 0?n:t}},watch:{value:function(t){this.updatingValue=!1,this.stateValue=t}},created:function(){this.radioGroupContext=ot(\"radioGroupContext\",this)},methods:{onRadioChange:function(t){var n=this,r=this.stateValue,a=t.target.value;vt(this,\"value\")||(this.stateValue=a),!this.updatingValue&&a!==r&&(this.updatingValue=!0,this.$emit(\"update:value\",a),this.$emit(\"change\",t)),Ne(function(){n.updatingValue=!1})}},render:function(){var t=this,n=Qe(this),r=n.prefixCls,a=n.options,o=n.buttonStyle,i=this.configProvider.getPrefixCls,l=i(\"radio\",r),s=\"\".concat(l,\"-group\"),c=Se(s,\"\".concat(s,\"-\").concat(o),V({},\"\".concat(s,\"-\").concat(n.size),n.size)),d=La(ht(this));return a&&a.length>0&&(d=a.map(function(f){return typeof f==\"string\"?g(_r,{key:f,prefixCls:l,disabled:n.disabled,value:f,checked:t.stateValue===f},{default:function(){return[f]}}):g(_r,{key:\"radio-group-value-options-\".concat(f.value),prefixCls:l,disabled:f.disabled||n.disabled,value:f.value,checked:t.stateValue===f.value},{default:function(){return[f.label]}})})),g(\"div\",{class:c},[d])}}),IPe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},Jv=G({name:\"ARadioButton\",props:P({},dD),setup:function(){return{configProvider:ve(\"configProvider\",St),radioGroupContext:ve(\"radioGroupContext\",{})}},render:function(){var t=this,n=Qe(this),r=n.prefixCls,a=IPe(n,[\"prefixCls\"]),o=this.configProvider.getPrefixCls,i=o(\"radio-button\",r),l=P({prefixCls:i},a);return this.radioGroupContext&&(l.onChange=this.radioGroupContext.onRadioChange,l.checked=n.value===this.radioGroupContext.stateValue,l.disabled=n.disabled||this.radioGroupContext.disabled),g(_r,l,{default:function(){return[ht(t)]}})}});_r.Group=Y2;_r.Button=Jv;_r.install=function(e){return e.component(_r.name,_r),e.component(_r.Group.name,_r.Group),e.component(_r.Button.name,_r.Button),e};function NPe(e){for(var t=e.clone(),n=e.localeData(),r=[],a=0;a<12;a++)t.month(a),r.push(n.monthsShort(t));return r}var APe={prefixCls:u.string,locale:u.any,fullscreen:u.looseBool,yearSelectOffset:u.number,yearSelectTotal:u.number,type:u.string,value:{type:Object},validRange:{type:Array},headerRender:u.func,onValueChange:u.func,onTypeChange:u.func},DPe=G({name:\"CalendarHeader\",inheritAttrs:!1,props:P(P({},APe),{yearSelectOffset:u.number.def(10),yearSelectTotal:u.number.def(20)}),setup:function(){return{configProvider:ve(\"configProvider\",St),calendarHeaderNode:void 0}},methods:{getYearSelectElement:function(t,n){var r=this,a=this.yearSelectOffset,o=this.yearSelectTotal,i=this.locale,l=i===void 0?{}:i,s=this.fullscreen,c=this.validRange,d=n-a,f=d+o;c&&(d=c[0].get(\"year\"),f=c[1].get(\"year\")+1);for(var p=l&&l.year===\"\\u5E74\"?\"\\u5E74\":\"\",v=[],m=d;m<f;m++)v.push({label:\"\".concat(m).concat(p),value:m});return g(dl,{size:s?void 0:\"small\",class:\"\".concat(t,\"-year-select\"),onChange:this.onYearChange,value:n,options:v,getPopupContainer:function(){return r.calendarHeaderNode}},null)},getMonthSelectElement:function(t,n,r){var a=this,o=this.fullscreen,i=this.validRange,l=this.value,s=0,c=11;if(i){var d=fn(i,2),f=d[0],p=d[1],v=l.get(\"year\");p.get(\"year\")===v&&(c=p.get(\"month\")+1),f.get(\"year\")===v&&(s=f.get(\"month\"))}for(var m=[],y=s;y<=c;y+=1)m.push({label:r[y],value:y});return g(dl,{size:o?void 0:\"small\",class:\"\".concat(t,\"-month-select\"),value:n,options:m,onChange:this.onMonthChange,getPopupContainer:function(){return a.calendarHeaderNode}},null)},onYearChange:function(t){var n=this.value,r=this.validRange,a=n.clone();if(a.year(parseInt(t,10)),r){var o=fn(r,2),i=o[0],l=o[1],s=a.get(\"year\"),c=a.get(\"month\");s===l.get(\"year\")&&c>l.get(\"month\")&&a.month(l.get(\"month\")),s===i.get(\"year\")&&c<i.get(\"month\")&&a.month(i.get(\"month\"))}this.$emit(\"valueChange\",a)},onMonthChange:function(t){var n=this.value.clone();n.month(parseInt(t,10)),this.$emit(\"valueChange\",n)},onInternalTypeChange:function(t){this.triggerTypeChange(t.target.value)},triggerTypeChange:function(t){this.$emit(\"typeChange\",t)},getMonthYearSelections:function(t){var n=this.$props,r=n.prefixCls,a=n.type,o=n.value,i=t(\"fullcalendar\",r),l=this.getYearSelectElement(i,o.year()),s=a===\"month\"?this.getMonthSelectElement(i,o.month(),NPe(o)):null;return{yearReactNode:l,monthReactNode:s}},getTypeSwitch:function(){var t=this.$props,n=t.locale,r=n===void 0?{}:n,a=t.type,o=t.fullscreen,i=o?\"default\":\"small\";return g(Y2,{onChange:this.onInternalTypeChange,value:a,size:i},{default:function(){return[g(Jv,{value:\"month\"},{default:function(){return[r.month]}}),g(Jv,{value:\"year\"},{default:function(){return[r.year]}})]}})},triggerValueChange:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.$emit.apply(this,[\"valueChange\"].concat(n))},saveCalendarHeaderNode:function(t){this.calendarHeaderNode=t},headerRenderCustom:function(t){var n=this.$props,r=n.type,a=n.value;return t({value:a,type:r||\"month\",onChange:this.triggerValueChange,onTypeChange:this.triggerTypeChange})}},render:function(){var t=this.prefixCls,n=this.headerRender,r=this.configProvider.getPrefixCls,a=r(\"fullcalendar\",t),o=this.getTypeSwitch(),i=this.getMonthYearSelections(r),l=i.yearReactNode,s=i.monthReactNode;return n?this.headerRenderCustom(n):g(\"div\",{class:\"\".concat(a,\"-header\"),ref:this.saveCalendarHeaderNode},[l,s,o])}}),V3={validator:function(t){return typeof t==\"string\"||ul(t)||Ue.isMoment(t)}},z3={validator:function(t){return Array.isArray(t)?t.length===0||t.findIndex(function(n){return typeof n!=\"string\"})===-1||t.findIndex(function(n){return!ul(n)&&!Ue.isMoment(n)})===-1:typeof t==\"string\"||ul(t)||Ue.isMoment(t)}};function pi(e,t,n,r){var a=Array.isArray(t)?t:[t];a.forEach(function(o){!o||(r&&on(Hr(Ue)(o,r).isValid(),e,\"When set `valueFormat`, `\".concat(n,\"` should provides invalidate string time. \")),!r&&on(Hr(Ue).isMoment(o)&&o.isValid(),e,\"`\".concat(n,\"` provides invalidate moment time. If you want to set empty value, use `null` instead.\")))})}var rl=function(t,n){return Array.isArray(t)?t.map(function(r){return typeof r==\"string\"&&r?Hr(Ue)(r,n):r||null}):typeof t==\"string\"&&t?Hr(Ue)(t,n):t||null},Du=function(t,n){return Array.isArray(t)?t.map(function(r){return Hr(Ue).isMoment(r)?r.format(n):r}):Hr(Ue).isMoment(t)?t.format(n):t};function H3(){return null}function RPe(e){return e<10?\"0\".concat(e):\"\".concat(e)}var LPe=rt(\"month\",\"year\"),FPe={monthCellRender:u.func,dateCellRender:u.func,monthFullCellRender:u.func,dateFullCellRender:u.func,prefixCls:u.string,value:V3,defaultValue:V3,mode:u.oneOf(LPe),fullscreen:u.looseBool.def(!0),locale:u.object.def({}),disabledDate:u.func,validRange:{type:Array},headerRender:u.func,valueFormat:u.string,onPanelChange:u.func,onSelect:u.func,onChange:u.func,\"onUpdate:value\":u.func},BPe=G({name:\"ACalendar\",mixins:[nt],inheritAttrs:!1,props:FPe,setup:function(){return{configProvider:ve(\"configProvider\",St),sPrefixCls:void 0}},data:function(){var t=this.value,n=this.defaultValue,r=this.valueFormat,a=t||n||Hr(Ue)();return pi(\"Calendar\",n,\"defaultValue\",r),pi(\"Calendar\",t,\"value\",r),{sValue:rl(a,r),sMode:this.mode||\"month\"}},watch:{value:function(t){pi(\"Calendar\",t,\"value\",this.valueFormat),this.setState({sValue:rl(t,this.valueFormat)})},mode:function(t){this.setState({sMode:t})}},methods:{onHeaderValueChange:function(t){this.setValue(t,\"changePanel\")},onHeaderTypeChange:function(t){this.sMode=t,this.triggerPanelChange(this.sValue,t)},triggerPanelChange:function(t,n){var r=this.valueFormat?Du(t,this.valueFormat):t;t!==this.sValue&&(this.$emit(\"update:value\",r),this.$emit(\"change\",r)),this.$emit(\"panelChange\",r,n)},triggerSelect:function(t){this.setValue(t,\"select\")},setValue:function(t,n){var r=this.value?rl(this.value,this.valueFormat):this.sValue,a=this.sMode,o=this.valueFormat;if(vt(this,\"value\")||this.setState({sValue:t}),n===\"select\"){var i=o?Du(t,o):t;r&&r.month()!==t.month()?this.triggerPanelChange(t,a):this.$emit(\"update:value\",i),this.$emit(\"select\",i)}else n===\"changePanel\"&&this.triggerPanelChange(t,a)},getDateRange:function(t,n){return function(r){if(!r)return!1;var a=fn(t,2),o=a[0],i=a[1],l=!r.isBetween(o,i,\"days\",\"[]\");return n&&n(r)||l}},getDefaultLocale:function(){var t=P(P({},Ev),this.$props.locale);return t.lang=P(P({},t.lang),(this.$props.locale||{}).lang),t},monthCellRender2:function(t){var n=t.current,r=this.sPrefixCls,a=this.$slots,o=this.monthCellRender||a.monthCellRender||H3;return g(\"div\",{class:\"\".concat(r,\"-month\")},[g(\"div\",{class:\"\".concat(r,\"-value\")},[n.localeData().monthsShort(n)]),g(\"div\",{class:\"\".concat(r,\"-content\")},[o({current:n})])])},dateCellRender2:function(t){var n=t.current,r=this.sPrefixCls,a=this.$slots,o=this.dateCellRender||a.dateCellRender||H3;return g(\"div\",{class:\"\".concat(r,\"-date\")},[g(\"div\",{class:\"\".concat(r,\"-value\")},[RPe(n.date())]),g(\"div\",{class:\"\".concat(r,\"-content\")},[o({current:n})])])},renderCalendar:function(t,n){var r=P(P({},Qe(this)),this.$attrs),a=this.sValue,o=this.sMode,i=this.$slots;a&&n&&a.locale(n);var l=r.prefixCls,s=r.fullscreen,c=r.dateFullCellRender,d=r.monthFullCellRender,f=r.class,p=r.style,v=this.headerRender||i.headerRender,m=this.configProvider.getPrefixCls,y=m(\"fullcalendar\",l);this.sPrefixCls=y;var b=f||\"\";s&&(b+=\" \".concat(y,\"-fullscreen\"));var C=d||i.monthFullCellRender||this.monthCellRender2,S=c||i.dateFullCellRender||this.dateCellRender2,w=r.disabledDate;r.validRange&&(w=this.getDateRange(r.validRange,w));var k=P(P(P({},r),this.$attrs),{Select:{},locale:t.lang,type:o===\"year\"?\"month\":\"date\",prefixCls:y,showHeader:!1,value:a,monthCellRender:C,dateCellRender:S,disabledDate:w,onSelect:this.triggerSelect});return g(\"div\",{class:b,style:p},[g(DPe,{fullscreen:s,type:o,headerRender:v,value:a,locale:t.lang,prefixCls:y,onTypeChange:this.onHeaderTypeChange,onValueChange:this.onHeaderValueChange,validRange:r.validRange},null),g(_Pe,k,null)])}},render:function(){return g(Kr,{componentName:\"Calendar\",defaultLocale:this.getDefaultLocale,children:this.renderCalendar},null)}}),VPe=kn(BPe),zPe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"defs\",attrs:{},children:[{tag:\"style\",attrs:{}}]},{tag:\"path\",attrs:{d:\"M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z\"}},{tag:\"path\",attrs:{d:\"M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z\"}}]},name:\"plus\",theme:\"outlined\"},HPe=zPe;function j3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){jPe(e,a,n[a])})}return e}function jPe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var q2=function(t,n){var r=j3({},t,n.attrs);return g(Et,j3({},r,{icon:HPe}),null)};q2.displayName=\"PlusOutlined\";q2.inheritAttrs=!1;var KPe=q2,Eh={LEFT:37,UP:38,RIGHT:39,DOWN:40},WPe={width:0,height:0,overflow:\"hidden\",position:\"absolute\"},Qv={name:\"Sentinel\",props:{setRef:u.func,prevElement:u.any,nextElement:u.any},methods:{onKeyDown:function(t){var n=t.target,r=t.which,a=t.shiftKey,o=this.$props,i=o.nextElement,l=o.prevElement;r!==ze.TAB||document.activeElement!==n||(!a&&i&&i.focus(),a&&l&&l.focus())}},render:function(){var t=this.$props.setRef;return g(\"div\",{tabindex:0,ref:t,style:WPe,onKeydown:this.onKeyDown,role:\"presentation\"},[ht(this)])}};function UPe(e){var t=[];return e.forEach(function(n){rn(n)&&t.push(n)}),t}function fD(e,t){for(var n=UPe(e),r=0;r<n.length;r++)if(n[r].key===t)return r;return-1}function Wp(e,t){e.transform=t,e.webkitTransform=t,e.mozTransform=t}function hD(e){return(\"transform\"in e||\"webkitTransform\"in e||\"MozTransform\"in e)&&window.atob}function YPe(e){return{transform:e,WebkitTransform:e,MozTransform:e}}function em(e){return e===\"left\"||e===\"right\"}function qPe(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:\"ltr\",r=em(t)?\"translateY\":\"translateX\";return!em(t)&&n===\"rtl\"?\"\".concat(r,\"(\").concat(e*100,\"%) translateZ(0)\"):\"\".concat(r,\"(\").concat(-e*100,\"%) translateZ(0)\")}function GPe(e,t){var n=em(t)?\"marginTop\":\"marginLeft\";return V({},n,\"\".concat(-e*100,\"%\"))}function pD(e,t){return+window.getComputedStyle(e).getPropertyValue(t).replace(\"px\",\"\")}function vD(e){return Object.keys(e).reduce(function(t,n){return(n.substr(0,5)===\"aria-\"||n.substr(0,5)===\"data-\"||n===\"role\")&&(t[n]=e[n]),t},{})}function Yc(e,t){return+e.getPropertyValue(t).replace(\"px\",\"\")}function mD(e,t,n,r,a){var o=pD(a,\"padding-\".concat(e));if(!r||!r.parentNode)return o;var i=r.parentNode.childNodes;return Array.prototype.some.call(i,function(l){if(!l.tagName)return!1;var s=window.getComputedStyle(l);return l!==r?(o+=Yc(s,\"margin-\".concat(e)),o+=l[t],o+=Yc(s,\"margin-\".concat(n)),s.boxSizing===\"content-box\"&&(o+=Yc(s,\"border-\".concat(e,\"-width\"))+Yc(s,\"border-\".concat(n,\"-width\"))),!1):(o+=Yc(s,\"margin-\".concat(e)),!0)}),o}function XPe(e,t){return mD(\"left\",\"offsetWidth\",\"right\",e,t)}function ZPe(e,t){return mD(\"top\",\"offsetHeight\",\"bottom\",e,t)}var JPe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function K3(e){var t,n=e.children;return n.forEach(function(r){r&&!tf(t)&&!r.disabled&&(t=r.key)}),t}function QPe(e,t){var n=e.children,r=n.map(function(a){return a&&a.key});return r.indexOf(t)>=0}var e3e=G({name:\"Tabs\",mixins:[nt],inheritAttrs:!1,props:{destroyInactiveTabPane:u.looseBool,renderTabBar:u.func.isRequired,renderTabContent:u.func.isRequired,navWrapper:u.func.def(function(e){return e}),children:u.any.def([]),prefixCls:u.string.def(\"ant-tabs\"),tabBarPosition:u.string.def(\"top\"),activeKey:u.oneOfType([u.string,u.number]),defaultActiveKey:u.oneOfType([u.string,u.number]),direction:u.string.def(\"ltr\"),tabBarGutter:u.number},setup:function(t){var n;t.activeKey!==void 0?n=t.activeKey:t.defaultActiveKey!==void 0?n=t.defaultActiveKey:n=K3(t);var r=bt({_activeKey:n});return Wn(function(){t.activeKey!==void 0?r._activeKey=t.activeKey:QPe(t,r._activeKey)||(r._activeKey=K3(t))},{flush:\"sync\"}),{state:r}},created:function(){this.panelSentinelStart=void 0,this.panelSentinelEnd=void 0,this.sentinelStart=void 0,this.sentinelEnd=void 0,ot(\"sentinelContext\",this)},beforeUnmount:function(){this.destroy=!0,cancelAnimationFrame(this.sentinelId)},methods:{onTabClick:function(t,n){this.tabBar.props&&this.tabBar.props.onTabClick&&this.tabBar.props.onTabClick(t,n),this.setActiveKey(t)},onNavKeyDown:function(t){var n=t.keyCode;if(n===Eh.RIGHT||n===Eh.DOWN){t.preventDefault();var r=this.getNextActiveKey(!0);this.onTabClick(r)}else if(n===Eh.LEFT||n===Eh.UP){t.preventDefault();var a=this.getNextActiveKey(!1);this.onTabClick(a)}},onScroll:function(t){var n=t.target,r=t.currentTarget;n===r&&n.scrollLeft>0&&(n.scrollLeft=0)},setSentinelStart:function(t){this.sentinelStart=t},setSentinelEnd:function(t){this.sentinelEnd=t},setPanelSentinelStart:function(t){t!==this.panelSentinelStart&&this.updateSentinelContext(),this.panelSentinelStart=t},setPanelSentinelEnd:function(t){t!==this.panelSentinelEnd&&this.updateSentinelContext(),this.panelSentinelEnd=t},setActiveKey:function(t){if(this.state._activeKey!==t){var n=this.$props;n.activeKey===void 0&&(this.state._activeKey=t),this.__emit(\"update:activeKey\",t),this.__emit(\"change\",t)}},getNextActiveKey:function(t){var n=this.state._activeKey,r=[];this.$props.children.forEach(function(i){var l,s;i&&!(!((l=i.props)===null||l===void 0)&&l.disabled)&&((s=i.props)===null||s===void 0?void 0:s.disabled)!==\"\"&&(t?r.push(i):r.unshift(i))});var a=r.length,o=a&&r[0].key;return r.forEach(function(i,l){i.key===n&&(l===a-1?o=r[0].key:o=r[l+1].key)}),o},updateSentinelContext:function(){var t=this;this.destroy||(cancelAnimationFrame(this.sentinelId),this.sentinelId=requestAnimationFrame(function(){t.destroy||t.$forceUpdate()}))}},render:function(){var t,n=this.$props,r=n.prefixCls,a=n.navWrapper,o=n.tabBarPosition,i=n.renderTabContent,l=n.renderTabBar,s=n.destroyInactiveTabPane,c=n.direction,d=n.tabBarGutter,f=this.$attrs,p=f.class;f.onChange;var v=f.style,m=JPe(f,[\"class\",\"onChange\",\"style\"]),y=(t={},V(t,p,p),V(t,r,1),V(t,\"\".concat(r,\"-\").concat(o),1),V(t,\"\".concat(r,\"-rtl\"),c===\"rtl\"),t);this.tabBar=l();var b=Ot(this.tabBar,{prefixCls:r,navWrapper:a,tabBarPosition:o,panels:n.children,activeKey:this.state._activeKey,direction:c,tabBarGutter:d,onKeydown:this.onNavKeyDown,onTabClick:this.onTabClick,key:\"tabBar\"}),C=Ot(i(),{prefixCls:r,tabBarPosition:o,activeKey:this.state._activeKey,destroyInactiveTabPane:s,direction:c,onChange:this.setActiveKey,children:n.children,key:\"tabContent\"}),S=g(Qv,{key:\"sentinelStart\",setRef:this.setSentinelStart,nextElement:this.panelSentinelStart},null),w=g(Qv,{key:\"sentinelEnd\",setRef:this.setSentinelEnd,prevElement:this.panelSentinelEnd},null),k=[];o===\"bottom\"?k.push(S,C,w,b):k.push(b,S,C,w);var $=P(P({},vD(m)),{style:v,onScroll:this.onScroll,class:y});return g(\"div\",$,[k])}}),G2=G({name:\"TabPane\",props:{active:u.looseBool,destroyInactiveTabPane:u.looseBool,forceRender:u.looseBool,placeholder:u.any,rootPrefixCls:u.string,tab:u.any,closable:u.looseBool,disabled:u.looseBool},setup:function(){return{isActived:void 0,sentinelContext:ve(\"sentinelContext\",{})}},render:function(){var t,n=this.$props,r=n.destroyInactiveTabPane,a=n.active,o=n.forceRender,i=n.rootPrefixCls,l=ht(this),s=We(this,\"placeholder\");this.isActived=this.isActived||a;var c=\"\".concat(i,\"-tabpane\"),d=(t={},V(t,c,1),V(t,\"\".concat(c,\"-inactive\"),!a),V(t,\"\".concat(c,\"-active\"),a),t),f=r?a:this.isActived,p=f||o,v=this.sentinelContext,m=v.sentinelStart,y=v.sentinelEnd,b=v.setPanelSentinelStart,C=v.setPanelSentinelEnd,S,w;return a&&p&&(S=g(Qv,{setRef:b,prevElement:m},null),w=g(Qv,{setRef:C,nextElement:y},null)),g(\"div\",{class:d,role:\"tabpanel\",\"aria-hidden\":a?\"false\":\"true\"},[S,p?l:s,w])}}),X2=G({name:\"TabContent\",inheritAttrs:!1,props:{animated:u.looseBool.def(!0),animatedWithMargin:u.looseBool.def(!0),prefixCls:u.string.def(\"ant-tabs\"),activeKey:u.oneOfType([u.string,u.number]),tabBarPosition:u.string,direction:u.string,destroyInactiveTabPane:u.looseBool,children:u.any},computed:{classes:function(){var t,n=this.animated,r=this.prefixCls,a=this.$attrs.class;return t={},V(t,a,!!a),V(t,\"\".concat(r,\"-content\"),!0),V(t,n?\"\".concat(r,\"-content-animated\"):\"\".concat(r,\"-content-no-animated\"),!0),t}},methods:{getTabPanes:function(t){var n=this.$props,r=n.activeKey,a=[];return t.forEach(function(o){if(!!o){var i=o.key,l=r===i;a.push(Ot(o,{active:l,destroyInactiveTabPane:n.destroyInactiveTabPane,rootPrefixCls:n.prefixCls}))}}),a}},render:function(){var t=this.activeKey,n=this.tabBarPosition,r=this.animated,a=this.animatedWithMargin,o=this.direction,i=this.classes,l=this.children,s={};if(r&&l){var c=fD(l,t);if(c!==-1){var d=a?GPe(c,n):YPe(qPe(c,n,o));s=P(P({},this.$attrs.style),d)}else s=P(P({},this.$attrs.style),{display:\"none\"})}return g(\"div\",{class:i,style:s},[this.getTabPanes(l||[])])}}),t3e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z\"}}]},name:\"up\",theme:\"outlined\"},n3e=t3e;function W3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){r3e(e,a,n[a])})}return e}function r3e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Z2=function(t,n){var r=W3({},t,n.attrs);return g(Et,W3({},r,{icon:n3e}),null)};Z2.displayName=\"UpOutlined\";Z2.inheritAttrs=!1;var gD=Z2,a3e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z\"}}]},name:\"left\",theme:\"outlined\"},o3e=a3e;function U3(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){i3e(e,a,n[a])})}return e}function i3e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var J2=function(t,n){var r=U3({},t,n.attrs);return g(Et,U3({},r,{icon:o3e}),null)};J2.displayName=\"LeftOutlined\";J2.inheritAttrs=!1;var uc=J2;function Y3(e,t){var n=e.$props,r=n.styles,a=r===void 0?{}:r,o=n.panels,i=n.activeKey,l=n.direction,s=e.getRef(\"root\"),c=e.getRef(\"nav\")||s,d=e.getRef(\"inkBar\"),f=e.getRef(\"activeTab\"),p=d.style,v=e.$props.tabBarPosition,m=fD(o,i);if(t&&(p.display=\"none\"),f){var y=f,b=hD(p);if(Wp(p,\"\"),p.width=\"\",p.height=\"\",p.left=\"\",p.top=\"\",p.bottom=\"\",p.right=\"\",v===\"top\"||v===\"bottom\"){var C=XPe(y,c),S=y.offsetWidth;S===s.offsetWidth?S=0:a.inkBar&&a.inkBar.width!==void 0&&(S=parseFloat(a.inkBar.width,10),S&&(C+=(y.offsetWidth-S)/2)),l===\"rtl\"&&(C=pD(y,\"margin-left\")-C),b?Wp(p,\"translate3d(\".concat(C,\"px,0,0)\")):p.left=\"\".concat(C,\"px\"),p.width=\"\".concat(S,\"px\")}else{var w=ZPe(y,c),k=y.offsetHeight;a.inkBar&&a.inkBar.height!==void 0&&(k=parseFloat(a.inkBar.height,10),k&&(w+=(y.offsetHeight-k)/2)),b?(Wp(p,\"translate3d(0,\".concat(w,\"px,0)\")),p.top=\"0\"):p.top=\"\".concat(w,\"px\"),p.height=\"\".concat(k,\"px\")}}p.display=m!==-1?\"block\":\"none\"}var l3e={name:\"InkTabBarNode\",mixins:[nt],inheritAttrs:!1,props:{inkBarAnimated:{type:Boolean,default:!0},direction:u.string,prefixCls:String,styles:Object,tabBarPosition:String,saveRef:u.func.def(function(){}),getRef:u.func.def(function(){}),panels:u.array,activeKey:u.oneOfType([u.string,u.number])},updated:function(){var t=this;this.$nextTick(function(){Y3(t)})},mounted:function(){var t=this;this.$nextTick(function(){Y3(t,!0)})},render:function(){var t,n=this.prefixCls,r=this.styles,a=r===void 0?{}:r,o=this.inkBarAnimated,i=\"\".concat(n,\"-ink-bar\"),l=(t={},V(t,i,!0),V(t,o?\"\".concat(i,\"-animated\"):\"\".concat(i,\"-no-animated\"),!0),t);return g(\"div\",{style:a.inkBar,class:l,key:\"inkBar\",ref:this.saveRef(\"inkBar\")},null)}},s3e=function(){},cc=s3e;function Gy(){}var u3e={name:\"TabBarTabsNode\",mixins:[nt],inheritAttrs:!1,props:{activeKey:u.oneOfType([u.string,u.number]),panels:u.any.def([]),prefixCls:u.string.def(\"\"),tabBarGutter:u.any.def(null),onTabClick:u.func,saveRef:u.func.def(Gy),getRef:u.func.def(Gy),renderTabBarNode:u.func,tabBarPosition:u.string,direction:u.string},render:function(){var t=this,n=this.$props,r=n.panels,a=n.activeKey,o=n.prefixCls,i=n.tabBarGutter,l=n.saveRef,s=n.tabBarPosition,c=n.direction,d=[],f=this.renderTabBarNode||this.$slots.renderTabBarNode;return r.forEach(function(p,v){if(!!p){var m=rr(p),y=p.key,b=a===y?\"\".concat(o,\"-tab-active\"):\"\";b+=\" \".concat(o,\"-tab\");var C={},S=m.disabled;S?b+=\" \".concat(o,\"-tab-disabled\"):C.onClick=function(){t.__emit(\"tabClick\",y)};var w=We(p,\"tab\"),k=i&&v===r.length-1?0:i;k=typeof k==\"number\"?\"\".concat(k,\"px\"):k;var $=c===\"rtl\"?\"marginLeft\":\"marginRight\",O=V({},em(s)?\"marginBottom\":$,k),T=g(\"div\",le(le({role:\"tab\",\"aria-disabled\":S?\"true\":\"false\",\"aria-selected\":a===y?\"true\":\"false\"},C),{},{class:b.trim(),key:y,style:O,ref:a===y?l(\"activeTab\"):Gy}),[w]);f&&(T=f(T)),d.push(T)}}),g(\"div\",{ref:this.saveRef(\"navTabsContainer\")},[d])}},c3e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function q3(){}var d3e={name:\"TabBarRootNode\",mixins:[nt],inheritAttrs:!1,props:{saveRef:u.func.def(q3),getRef:u.func.def(q3),prefixCls:u.string.def(\"\"),tabBarPosition:u.string.def(\"top\"),extraContent:u.any},methods:{onKeyDown:function(t){this.__emit(\"keydown\",t)}},render:function(){var t,n=this.prefixCls,r=this.onKeyDown,a=this.tabBarPosition,o=this.extraContent,i=this.$attrs,l=i.class,s=i.style;i.onKeydown;var c=c3e(i,[\"class\",\"style\",\"onKeydown\"]),d=(t={},V(t,\"\".concat(n,\"-bar\"),!0),V(t,l,!!l),t),f=a===\"top\"||a===\"bottom\",p=f?{float:\"right\"}:{},v=ht(this),m=v;return o&&(m=[Ot(o,{key:\"extra\",style:P({},p)}),Ot(v,{key:\"content\"})],m=f?m:m.reverse()),g(\"div\",le({role:\"tablist\",class:d,tabindex:\"0\",onKeydown:r,style:s,ref:this.saveRef(\"root\")},vD(c)),[m])}},f3e={name:\"ScrollableTabBarNode\",mixins:[nt],inheritAttrs:!1,props:{activeKey:u.any,getRef:u.func.def(function(){}),saveRef:u.func.def(function(){}),tabBarPosition:u.oneOf([\"left\",\"right\",\"top\",\"bottom\"]).def(\"left\"),prefixCls:u.string.def(\"\"),scrollAnimated:u.looseBool.def(!0),navWrapper:u.func.def(function(e){return e}),prevIcon:u.any,nextIcon:u.any,direction:u.string},data:function(){return this.offset=0,this.prevProps=P({},this.$props),{next:!1,prev:!1}},watch:{tabBarPosition:function(){var t=this;this.tabBarPositionChange=!0,this.$nextTick(function(){t.setOffset(0)})}},mounted:function(){var t=this;this.$nextTick(function(){t.updatedCal(),t.debouncedResize=Yn(function(){t.setNextPrev(),t.scrollToActiveTab()},200),t.resizeObserver=new ng(t.debouncedResize),t.resizeObserver.observe(t.$props.getRef(\"container\"))})},updated:function(){var t=this;this.$nextTick(function(){t.updatedCal(t.prevProps),t.prevProps=P({},t.$props)})},beforeUnmount:function(){this.resizeObserver&&this.resizeObserver.disconnect(),this.debouncedResize&&this.debouncedResize.cancel&&this.debouncedResize.cancel()},methods:{updatedCal:function(t){var n=this,r=this.$props;if(t&&t.tabBarPosition!==r.tabBarPosition){this.setOffset(0);return}this.isNextPrevShown(this.$data)!==this.isNextPrevShown(this.setNextPrev())?(this.$forceUpdate(),this.$nextTick(function(){n.scrollToActiveTab()})):(!t||r.activeKey!==t.activeKey)&&this.scrollToActiveTab()},setNextPrev:function(){var t=this.$props.getRef(\"nav\"),n=this.$props.getRef(\"navTabsContainer\"),r=this.getScrollWH(n||t),a=this.getOffsetWH(this.$props.getRef(\"container\"))+1,o=this.getOffsetWH(this.$props.getRef(\"navWrap\")),i=this.offset,l=a-r,s=this.next,c=this.prev;if(l>=0)s=!1,this.setOffset(0,!1),i=0;else if(l<i)s=!0;else{s=!1;var d=o-r;this.setOffset(d,!1),i=d}return i<0?c=!0:c=!1,this.setNext(s),this.setPrev(c),{next:s,prev:c}},getOffsetWH:function(t){var n=this.$props.tabBarPosition,r=\"offsetWidth\";return(n===\"left\"||n===\"right\")&&(r=\"offsetHeight\"),t[r]},getScrollWH:function(t){var n=this.tabBarPosition,r=\"scrollWidth\";return(n===\"left\"||n===\"right\")&&(r=\"scrollHeight\"),t[r]},getOffsetLT:function(t){var n=this.$props.tabBarPosition,r=\"left\";return(n===\"left\"||n===\"right\")&&(r=\"top\"),t.getBoundingClientRect()[r]},setOffset:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,r=Math.min(0,t);if(this.offset!==r){this.offset=r;var a={},o=this.$props.tabBarPosition,i=this.$props.getRef(\"nav\").style,l=hD(i);o===\"left\"||o===\"right\"?l?a={value:\"translate3d(0,\".concat(r,\"px,0)\")}:a={name:\"top\",value:\"\".concat(r,\"px\")}:l?(this.$props.direction===\"rtl\"&&(r=-r),a={value:\"translate3d(\".concat(r,\"px,0,0)\")}):a={name:\"left\",value:\"\".concat(r,\"px\")},l?Wp(i,a.value):i[a.name]=a.value,n&&this.setNextPrev()}},setPrev:function(t){this.prev!==t&&(this.prev=t)},setNext:function(t){this.next!==t&&(this.next=t)},isNextPrevShown:function(t){return t?t.next||t.prev:this.next||this.prev},prevTransitionEnd:function(t){if(t.propertyName===\"opacity\"){var n=this.$props.getRef(\"container\");this.scrollToActiveTab({target:n,currentTarget:n})}},scrollToActiveTab:function(t){var n=this.$props.getRef(\"activeTab\"),r=this.$props.getRef(\"navWrap\");if(!(t&&t.target!==t.currentTarget||!n)){var a=this.isNextPrevShown()&&this.lastNextPrevShown;if(this.lastNextPrevShown=this.isNextPrevShown(),!!a){var o=this.getScrollWH(n),i=this.getOffsetWH(r),l=this.offset,s=this.getOffsetLT(r),c=this.getOffsetLT(n);s>c?(l+=s-c,this.setOffset(l)):s+i<c+o&&(l-=c+o-(s+i),this.setOffset(l))}}},prevClick:function(t){this.__emit(\"prevClick\",t);var n=this.$props.getRef(\"navWrap\"),r=this.getOffsetWH(n),a=this.offset;this.setOffset(a+r)},nextClick:function(t){this.__emit(\"nextClick\",t);var n=this.$props.getRef(\"navWrap\"),r=this.getOffsetWH(n),a=this.offset;this.setOffset(a-r)}},render:function(){var t,n,r,a,o=this.next,i=this.prev,l=this.$props,s=l.prefixCls,c=l.scrollAnimated,d=l.navWrapper,f=We(this,\"prevIcon\"),p=We(this,\"nextIcon\"),v=i||o,m=g(\"span\",{onClick:i&&this.prevClick,unselectable:\"unselectable\",class:(t={},V(t,\"\".concat(s,\"-tab-prev\"),1),V(t,\"\".concat(s,\"-tab-btn-disabled\"),!i),V(t,\"\".concat(s,\"-tab-arrow-show\"),v),t),onTransitionend:this.prevTransitionEnd},[f||g(\"span\",{class:\"\".concat(s,\"-tab-prev-icon\")},null)]),y=g(\"span\",{onClick:o&&this.nextClick,unselectable:\"unselectable\",class:(n={},V(n,\"\".concat(s,\"-tab-next\"),1),V(n,\"\".concat(s,\"-tab-btn-disabled\"),!o),V(n,\"\".concat(s,\"-tab-arrow-show\"),v),n)},[p||g(\"span\",{class:\"\".concat(s,\"-tab-next-icon\")},null)]),b=\"\".concat(s,\"-nav\"),C=(r={},V(r,b,!0),V(r,c?\"\".concat(b,\"-animated\"):\"\".concat(b,\"-no-animated\"),!0),r);return g(\"div\",{class:(a={},V(a,\"\".concat(s,\"-nav-container\"),1),V(a,\"\".concat(s,\"-nav-container-scrolling\"),v),a),key:\"container\",ref:this.saveRef(\"container\")},[m,y,g(\"div\",{class:\"\".concat(s,\"-nav-wrap\"),ref:this.saveRef(\"navWrap\")},[g(\"div\",{class:\"\".concat(s,\"-nav-scroll\")},[g(\"div\",{class:C,ref:this.saveRef(\"nav\")},[d(ht(this))])])])])}},h3e={props:{children:u.func.def(function(){return null})},methods:{getRef:function(t){return this[t]},saveRef:function(t){var n=this;return function(r){r&&(n[t]=r)}}},render:function(){var t=this,n=function(o){return t.saveRef(o)},r=function(o){return t.getRef(o)};return this.children(n,r)}},G3=G({name:\"ScrollableInkTabBar\",inheritAttrs:!1,render:function(){var t=this,n=this.$attrs.children;return g(h3e,{children:function(a,o){return g(d3e,le({saveRef:a},t.$attrs),{default:function(){return[g(f3e,le({saveRef:a,getRef:o},t.$attrs),{default:function(){return[g(u3e,le({saveRef:a},P(P({},t.$attrs),{renderTabBarNode:n})),null),g(l3e,le({saveRef:a,getRef:o},t.$attrs),null)]}})]}})}},null)}}),p3e=G({name:\"TabBar\",inheritAttrs:!1,props:{prefixCls:u.string,centered:u.looseBool.def(!1),tabBarStyle:u.style,tabBarExtraContent:u.VNodeChild,type:u.oneOf(rt(\"line\",\"card\",\"editable-card\")),tabPosition:u.oneOf(rt(\"top\",\"right\",\"bottom\",\"left\")).def(\"top\"),tabBarPosition:u.oneOf(rt(\"top\",\"right\",\"bottom\",\"left\")),size:u.oneOf(rt(\"default\",\"small\",\"large\")),animated:{type:[Boolean,Object],default:void 0},renderTabBar:u.func,panels:u.array.def([]),activeKey:u.oneOfType([u.string,u.number]),tabBarGutter:u.number},render:function(){var t,n=this.$props,r=n.centered,a=n.tabBarStyle,o=n.animated,i=o===void 0?!0:o,l=n.renderTabBar,s=n.tabBarExtraContent,c=n.tabPosition,d=n.prefixCls,f=n.type,p=f===void 0?\"line\":f,v=n.size,m=kt(i)===\"object\"?i.inkBar:i,y=c===\"left\"||c===\"right\",b=g(\"span\",{class:\"\".concat(d,\"-tab-prev-icon\")},[y?g(gD,{class:\"\".concat(d,\"-tab-prev-icon-target\")},null):g(uc,{class:\"\".concat(d,\"-tab-prev-icon-target\")},null)]),C=g(\"span\",{class:\"\".concat(d,\"-tab-next-icon\")},[y?g(Rs,{class:\"\".concat(d,\"-tab-next-icon-target\")},null):g(wi,{class:\"\".concat(d,\"-tab-next-icon-target\")},null)]),S=(t={},V(t,this.$attrs.class,this.$attrs.class),V(t,\"\".concat(d,\"-centered-bar\"),r),V(t,\"\".concat(d,\"-\").concat(c,\"-bar\"),!0),V(t,\"\".concat(d,\"-\").concat(v,\"-bar\"),!!v),V(t,\"\".concat(d,\"-card-bar\"),p&&p.indexOf(\"card\")>=0),t),w=P(P(P({},this.$props),this.$attrs),{children:null,inkBarAnimated:m,extraContent:s,prevIcon:b,nextIcon:C,style:a,class:S});return l?l(P(P({},w),{DefaultTabBar:G3})):g(G3,w,null)}}),v3e=p3e,m3e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},$a=G({TabPane:G2,name:\"ATabs\",inheritAttrs:!1,props:{prefixCls:u.string,activeKey:u.oneOfType([u.string,u.number]),defaultActiveKey:u.oneOfType([u.string,u.number]),hideAdd:u.looseBool.def(!1),centered:u.looseBool.def(!1),tabBarStyle:u.object,tabBarExtraContent:u.any,destroyInactiveTabPane:u.looseBool.def(!1),type:u.oneOf(rt(\"line\",\"card\",\"editable-card\")),tabPosition:u.oneOf([\"top\",\"right\",\"bottom\",\"left\"]).def(\"top\"),size:u.oneOf([\"default\",\"small\",\"large\"]),animated:an(u.oneOfType([u.looseBool,u.object])),tabBarGutter:u.number,renderTabBar:u.func,onChange:{type:Function},onTabClick:u.func,onPrevClick:{type:Function},onNextClick:{type:Function},onEdit:{type:Function}},emits:[\"update:activeKey\",\"edit\",\"change\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},methods:{removeTab:function(t,n){n.stopPropagation(),tf(t)&&this.$emit(\"edit\",t,\"remove\")},handleChange:function(t){this.$emit(\"update:activeKey\",t),this.$emit(\"change\",t)},createNewTab:function(t){this.$emit(\"edit\",t,\"add\")}},render:function(){var t,n=this,r,a=Qe(this),o=a.prefixCls,i=a.size,l=a.type,s=l===void 0?\"line\":l,c=a.tabPosition,d=a.animated,f=d===void 0?!0:d,p=a.hideAdd,v=a.renderTabBar,m=this.$attrs,y=m.class,b=m3e(m,[\"class\"]),C=this.configProvider.getPrefixCls,S=C(\"tabs\",o),w=La(ht(this)),k=We(this,\"tabBarExtraContent\"),$=kt(f)===\"object\"?f.tabPane:f;s!==\"line\"&&($=\"animated\"in a?$:!1);var O=(t={},V(t,y,y),V(t,\"\".concat(S,\"-vertical\"),c===\"left\"||c===\"right\"),V(t,\"\".concat(S,\"-\").concat(i),!!i),V(t,\"\".concat(S,\"-card\"),s.indexOf(\"card\")>=0),V(t,\"\".concat(S,\"-\").concat(s),!0),V(t,\"\".concat(S,\"-no-animation\"),!$),t),T=[];s===\"editable-card\"&&(T=[],w.forEach(function(F,N){var D=rr(F),z=D.closable;z=typeof z==\"undefined\"?!0:z;var B=z?g(go,{class:\"\".concat(S,\"-close-x\"),onClick:function(E){return n.removeTab(F.key,E)}},null):null;T.push(Ot(F,{tab:g(\"div\",{class:z?void 0:\"\".concat(S,\"-tab-unclosable\")},[We(F,\"tab\"),B]),key:F.key||N}))}),p||(k=g(\"span\",null,[g(KPe,{class:\"\".concat(S,\"-new-tab\"),onClick:this.createNewTab},null),k]))),k=k?g(\"div\",{class:\"\".concat(S,\"-extra-content\")},[k]):null;var _=v||this.$slots.renderTabBar,I=P(P(P(P({},a),{prefixCls:S,tabBarExtraContent:k,renderTabBar:_}),b),{children:w}),L=(r={},V(r,\"\".concat(S,\"-\").concat(c,\"-content\"),!0),V(r,\"\".concat(S,\"-card-content\"),s.indexOf(\"card\")>=0),r),j=P(P(P(P({},a),{prefixCls:S,tabBarPosition:c,renderTabBar:function(){return g(v3e,le({key:\"tabBar\"},I),null)},renderTabContent:function(){return g(X2,{class:L,animated:$,animatedWithMargin:!0},null)},children:T.length>0?T:w}),b),{onChange:this.handleChange,class:O});return g(e3e,j,null)}});$a.TabPane=P(P({},G2),{name:\"ATabPane\",__ANT_TAB_PANE:!0});$a.TabContent=P(P({},X2),{name:\"ATabContent\"});$a.install=function(e){return e.component($a.name,$a),e.component($a.TabPane.name,$a.TabPane),e.component($a.TabContent.name,$a.TabContent),e};function g3e(){return!!(typeof window!=\"undefined\"&&window.document&&window.document.createElement)}var yD=function(){return g3e()&&window.document.documentElement},bD=function(t){if(yD()){var n=Array.isArray(t)?t:[t],r=window.document.documentElement;return n.some(function(a){return a in r.style})}return!1},Mh,y3e=function(){if(!yD())return!1;if(Mh!==void 0)return Mh;var t=document.createElement(\"div\");return t.style.display=\"flex\",t.style.flexDirection=\"column\",t.style.rowGap=\"1px\",t.appendChild(document.createElement(\"div\")),t.appendChild(document.createElement(\"div\")),document.body.appendChild(t),Mh=t.scrollHeight===1,document.body.removeChild(t),Mh},CD=function(){var e=H(!1);return et(function(){e.value=y3e()}),e},wD=Symbol(\"rowContextKey\"),b3e=function(t){ot(wD,t)},C3e=function(){return ve(wD,{gutter:x(function(){}),wrap:x(function(){}),supportFlexGap:x(function(){})})},w3e=rt(\"top\",\"middle\",\"bottom\",\"stretch\"),S3e=rt(\"start\",\"end\",\"center\",\"space-around\",\"space-between\"),k3e={type:u.oneOf([\"flex\"]),align:u.oneOf(w3e),justify:u.oneOf(S3e),prefixCls:u.string,gutter:u.oneOfType([u.object,u.number,u.array]).def(0),wrap:u.looseBool},$3e=G({name:\"ARow\",props:k3e,setup:function(t,n){var r=n.slots,a=Wt(\"row\",t),o=a.prefixCls,i=a.direction,l,s=H({xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0}),c=CD();et(function(){l=lc.subscribe(function(v){var m=t.gutter||0;(!Array.isArray(m)&&kt(m)===\"object\"||Array.isArray(m)&&(kt(m[0])===\"object\"||kt(m[1])===\"object\"))&&(s.value=v)})}),Lt(function(){lc.unsubscribe(l)});var d=x(function(){var v=[0,0],m=t.gutter,y=m===void 0?0:m,b=Array.isArray(y)?y:[y,0];return b.forEach(function(C,S){if(kt(C)===\"object\")for(var w=0;w<ws.length;w++){var k=ws[w];if(s.value[k]&&C[k]!==void 0){v[S]=C[k];break}}else v[S]=C||0}),v});b3e({gutter:d,supportFlexGap:c,wrap:x(function(){return t.wrap})});var f=x(function(){var v;return Se(o.value,(v={},V(v,\"\".concat(o.value,\"-no-wrap\"),t.wrap===!1),V(v,\"\".concat(o.value,\"-\").concat(t.justify),t.justify),V(v,\"\".concat(o.value,\"-\").concat(t.align),t.align),V(v,\"\".concat(o.value,\"-rtl\"),i.value===\"rtl\"),v))}),p=x(function(){var v=d.value,m={},y=v[0]>0?\"\".concat(v[0]/-2,\"px\"):void 0,b=v[1]>0?\"\".concat(v[1]/-2,\"px\"):void 0;return y&&(m.marginLeft=y,m.marginRight=y),c.value?m.rowGap=\"\".concat(v[1],\"px\"):b&&(m.marginTop=b,m.marginBottom=b),m});return function(){var v;return g(\"div\",{class:f.value,style:p.value},[(v=r.default)===null||v===void 0?void 0:v.call(r)])}}}),Q2=$3e;function O3e(e){return typeof e==\"number\"?\"\".concat(e,\" \").concat(e,\" auto\"):/^\\d+(\\.\\d+)?(px|em|rem|%)$/.test(e)?\"0 0 \".concat(e):e}var Xa=u.oneOfType([u.string,u.number]),P3e=u.shape({span:Xa,order:Xa,offset:Xa,push:Xa,pull:Xa}).loose,Ys=u.oneOfType([u.string,u.number,P3e]),T3e={span:Xa,order:Xa,offset:Xa,push:Xa,pull:Xa,xs:Ys,sm:Ys,md:Ys,lg:Ys,xl:Ys,xxl:Ys,prefixCls:u.string,flex:Xa},Og=G({name:\"ACol\",props:T3e,setup:function(t,n){var r=n.slots,a=C3e(),o=a.gutter,i=a.supportFlexGap,l=a.wrap,s=Wt(\"col\",t),c=s.prefixCls,d=s.direction,f=x(function(){var v,m=t.span,y=t.order,b=t.offset,C=t.push,S=t.pull,w=c.value,k={};return[\"xs\",\"sm\",\"md\",\"lg\",\"xl\",\"xxl\"].forEach(function($){var O,T={},_=t[$];typeof _==\"number\"?T.span=_:kt(_)===\"object\"&&(T=_||{}),k=P(P({},k),(O={},V(O,\"\".concat(w,\"-\").concat($,\"-\").concat(T.span),T.span!==void 0),V(O,\"\".concat(w,\"-\").concat($,\"-order-\").concat(T.order),T.order||T.order===0),V(O,\"\".concat(w,\"-\").concat($,\"-offset-\").concat(T.offset),T.offset||T.offset===0),V(O,\"\".concat(w,\"-\").concat($,\"-push-\").concat(T.push),T.push||T.push===0),V(O,\"\".concat(w,\"-\").concat($,\"-pull-\").concat(T.pull),T.pull||T.pull===0),V(O,\"\".concat(w,\"-rtl\"),d.value===\"rtl\"),O))}),Se(w,(v={},V(v,\"\".concat(w,\"-\").concat(m),m!==void 0),V(v,\"\".concat(w,\"-order-\").concat(y),y),V(v,\"\".concat(w,\"-offset-\").concat(b),b),V(v,\"\".concat(w,\"-push-\").concat(C),C),V(v,\"\".concat(w,\"-pull-\").concat(S),S),v),k)}),p=x(function(){var v=t.flex,m=o.value,y={};if(m&&m[0]>0){var b=\"\".concat(m[0]/2,\"px\");y.paddingLeft=b,y.paddingRight=b}if(m&&m[1]>0&&!i.value){var C=\"\".concat(m[1]/2,\"px\");y.paddingTop=C,y.paddingBottom=C}return v&&(y.flex=O3e(v),v===\"auto\"&&l.value===!1&&!y.minWidth&&(y.minWidth=0)),y});return function(){var v;return g(\"div\",{class:f.value,style:p.value},[(v=r.default)===null||v===void 0?void 0:v.call(r)])}}}),x3e={useBreakpoint:F2},fu=kn(Q2),Ka=kn(Og),_3e=$a.TabPane,E3e={prefixCls:u.string,title:u.VNodeChild,extra:u.VNodeChild,bordered:u.looseBool.def(!0),bodyStyle:u.style,headStyle:u.style,loading:u.looseBool.def(!1),hoverable:u.looseBool.def(!1),type:u.string,size:u.oneOf(rt(\"default\",\"small\")),actions:u.VNodeChild,tabList:{type:Array},tabBarExtraContent:u.VNodeChild,activeTabKey:u.string,defaultActiveTabKey:u.string,cover:u.VNodeChild,onTabChange:{type:Function}},M3e=G({name:\"ACard\",mixins:[nt],props:E3e,setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){return{widerPadding:!1}},methods:{getAction:function(t){var n=t.map(function(r,a){return rn(r)&&!As(r)||!rn(r)?g(\"li\",{style:{width:\"\".concat(100/t.length,\"%\")},key:\"action-\".concat(a)},[g(\"span\",null,[r])]):null});return n},triggerTabChange:function(t){this.$emit(\"tabChange\",t)},isContainGrid:function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],n;return t.forEach(function(r){r&&bc(r.type)&&r.type.__ANT_CARD_GRID&&(n=!0)}),n}},render:function(){var t,n,r=this.$props,a=r.prefixCls,o=r.headStyle,i=o===void 0?{}:o,l=r.bodyStyle,s=l===void 0?{}:l,c=r.loading,d=r.bordered,f=d===void 0?!0:d,p=r.size,v=p===void 0?\"default\":p,m=r.type,y=r.tabList,b=r.hoverable,C=r.activeTabKey,S=r.defaultActiveTabKey,w=this.$slots,k=ht(this),$=this.configProvider.getPrefixCls,O=$(\"card\",a),T=We(this,\"tabBarExtraContent\"),_=(t={},V(t,\"\".concat(O),!0),V(t,\"\".concat(O,\"-loading\"),c),V(t,\"\".concat(O,\"-bordered\"),f),V(t,\"\".concat(O,\"-hoverable\"),!!b),V(t,\"\".concat(O,\"-contain-grid\"),this.isContainGrid(k)),V(t,\"\".concat(O,\"-contain-tabs\"),y&&y.length),V(t,\"\".concat(O,\"-\").concat(v),v!==\"default\"),V(t,\"\".concat(O,\"-type-\").concat(m),!!m),t),I=s.padding===0||s.padding===\"0px\"?{padding:24}:void 0,L=g(\"div\",{class:\"\".concat(O,\"-loading-content\"),style:I},[g(fu,{gutter:8},{default:function(){return[g(Ka,{span:22},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}})]}}),g(fu,{gutter:8},{default:function(){return[g(Ka,{span:8},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}}),g(Ka,{span:15},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}})]}}),g(fu,{gutter:8},{default:function(){return[g(Ka,{span:6},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}}),g(Ka,{span:18},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}})]}}),g(fu,{gutter:8},{default:function(){return[g(Ka,{span:13},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}}),g(Ka,{span:9},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}})]}}),g(fu,{gutter:8},{default:function(){return[g(Ka,{span:4},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}}),g(Ka,{span:3},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}}),g(Ka,{span:16},{default:function(){return[g(\"div\",{class:\"\".concat(O,\"-loading-block\")},null)]}})]}})]),j=C!==void 0,F=(n={size:\"large\"},V(n,j?\"activeKey\":\"defaultActiveKey\",j?C:S),V(n,\"tabBarExtraContent\",T),V(n,\"onChange\",this.triggerTabChange),V(n,\"class\",\"\".concat(O,\"-head-tabs\")),n),N,D=y&&y.length?g($a,F,{default:function(){return[y.map(function(J){var ne=J.tab,oe=J.slots,Q=oe==null?void 0:oe.tab,ae=ne!==void 0?ne:w[Q]?w[Q](J):null;return g(_3e,{tab:ae,key:J.key,disabled:J.disabled},null)})]}}):null,z=We(this,\"title\"),B=We(this,\"extra\");(z||B||D)&&(N=g(\"div\",{class:\"\".concat(O,\"-head\"),style:i},[g(\"div\",{class:\"\".concat(O,\"-head-wrapper\")},[z&&g(\"div\",{class:\"\".concat(O,\"-head-title\")},[z]),B&&g(\"div\",{class:\"\".concat(O,\"-extra\")},[B])]),D]));var M=We(this,\"cover\"),E=M?g(\"div\",{class:\"\".concat(O,\"-cover\")},[M]):null,K=g(\"div\",{class:\"\".concat(O,\"-body\"),style:s},[c?L:k]),W=We(this,\"actions\"),Y=W&&W.length?g(\"ul\",{class:\"\".concat(O,\"-actions\")},[this.getAction(W)]):null;return g(\"div\",{class:_,ref:\"cardContainerRef\"},[N,E,k?K:null,Y])}}),Ru=M3e,tm=G({name:\"ACardMeta\",props:{prefixCls:u.string,title:u.VNodeChild,description:u.VNodeChild,avatar:u.VNodeChild},setup:function(){return{configProvider:ve(\"configProvider\",St)}},render:function(){var t=this.$props.prefixCls,n=this.configProvider.getPrefixCls,r=n(\"card\",t),a=V({},\"\".concat(r,\"-meta\"),!0),o=We(this,\"avatar\"),i=We(this,\"title\"),l=We(this,\"description\"),s=o?g(\"div\",{class:\"\".concat(r,\"-meta-avatar\")},[o]):null,c=i?g(\"div\",{class:\"\".concat(r,\"-meta-title\")},[i]):null,d=l?g(\"div\",{class:\"\".concat(r,\"-meta-description\")},[l]):null,f=c||d?g(\"div\",{class:\"\".concat(r,\"-meta-detail\")},[c,d]):null;return g(\"div\",{class:a},[s,f])}}),nm=G({name:\"ACardGrid\",__ANT_CARD_GRID:!0,props:{prefixCls:u.string,hoverable:u.looseBool},setup:function(){return{configProvider:ve(\"configProvider\",St)}},render:function(){var t,n=this.$props,r=n.prefixCls,a=n.hoverable,o=a===void 0?!0:a,i=this.configProvider.getPrefixCls,l=i(\"card\",r),s=(t={},V(t,\"\".concat(l,\"-grid\"),!0),V(t,\"\".concat(l,\"-grid-hoverable\"),o),t);return g(\"div\",{class:s},[ht(this)])}});Ru.Meta=tm;Ru.Grid=nm;Ru.install=function(e){return e.component(Ru.name,Ru),e.component(tm.name,tm),e.component(nm.name,nm),e};function I3e(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function X3(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function N3e(e,t,n){return t&&X3(e.prototype,t),n&&X3(e,n),Object.defineProperty(e,\"prototype\",{writable:!1}),e}var A3e=/\\s+/,D3e=function(){function e(t){if(I3e(this,e),!t||!t.nodeType)throw new Error(\"A DOM element reference is required\");this.el=t,this.list=t.classList}return N3e(e,[{key:\"array\",value:function(){var n=this.el.getAttribute(\"class\")||\"\",r=n.replace(/^\\s+|\\s+$/g,\"\"),a=r.split(A3e);return a[0]===\"\"&&a.shift(),a}},{key:\"add\",value:function(n){if(this.list)return this.list.add(n),this;var r=this.array(),a=ty(r,n);return~a||r.push(n),this.el.className=r.join(\" \"),this}},{key:\"remove\",value:function(n){if(toString.call(n)===\"[object RegExp]\")return this._removeMatching(n);if(this.list)return this.list.remove(n),this;var r=this.array(),a=ty(r,n);return~a&&r.splice(a,1),this.el.className=r.join(\" \"),this}},{key:\"_removeMatching\",value:function(n){for(var r=this.array(),a=0;a<r.length;a++)n.test(r[a])&&this.remove(r[a]);return this}},{key:\"toggle\",value:function(n,r){return this.list?(typeof r!=\"undefined\"?r!==this.list.toggle(n,r)&&this.list.toggle(n):this.list.toggle(n),this):(typeof r!=\"undefined\"?r?this.add(n):this.remove(n):this.has(n)?this.remove(n):this.add(n),this)}},{key:\"has\",value:function(n){return this.list?this.list.contains(n):!!~ty(this.array(),n)}},{key:\"contains\",value:function(n){return this.has(n)}}]),e}();function g1(e){return new D3e(e)}var SD=si.endEvents.length!==0,R3e=[\"Webkit\",\"Moz\",\"O\",\"ms\"],Z3=[\"-webkit-\",\"-moz-\",\"-o-\",\"ms-\",\"\"];function Ih(e,t){for(var n=window.getComputedStyle(e,null),r=\"\",a=0;a<Z3.length&&(r=n.getPropertyValue(Z3[a]+t),!r);a++);return r}function kD(e){if(SD){var t=parseFloat(Ih(e,\"transition-delay\"))||0,n=parseFloat(Ih(e,\"transition-duration\"))||0,r=parseFloat(Ih(e,\"animation-delay\"))||0,a=parseFloat(Ih(e,\"animation-duration\"))||0,o=Math.max(n+t,a+r);e.rcEndAnimTimeout=setTimeout(function(){e.rcEndAnimTimeout=null,e.rcEndListener&&e.rcEndListener()},o*1e3+200)}}function $D(e){e.rcEndAnimTimeout&&(clearTimeout(e.rcEndAnimTimeout),e.rcEndAnimTimeout=null)}var Pg=function(t,n,r){var a=kt(n)===\"object\",o=a?n.name:n,i=a?n.active:\"\".concat(n,\"-active\"),l=r,s,c,d=g1(t);return r&&Object.prototype.toString.call(r)===\"[object Object]\"&&(l=r.end,s=r.start,c=r.active),t.rcEndListener&&t.rcEndListener(),t.rcEndListener=function(f){f&&f.target!==t||(t.rcAnimTimeout&&(o2(t.rcAnimTimeout),t.rcAnimTimeout=null),$D(t),d.remove(o),d.remove(i),si.removeEndEventListener(t,t.rcEndListener),t.rcEndListener=null,l&&l())},si.addEndEventListener(t,t.rcEndListener),s&&s(),d.add(o),t.rcAnimTimeout=Fv(function(){t.rcAnimTimeout=null,d.add(o),d.add(i),c&&Fv(c,0),kD(t)},30),{stop:function(){t.rcEndListener&&t.rcEndListener()}}};Pg.style=function(e,t,n){e.rcEndListener&&e.rcEndListener(),e.rcEndListener=function(r){r&&r.target!==e||(e.rcAnimTimeout&&(o2(e.rcAnimTimeout),e.rcAnimTimeout=null),$D(e),si.removeEndEventListener(e,e.rcEndListener),e.rcEndListener=null,n&&n())},si.addEndEventListener(e,e.rcEndListener),e.rcAnimTimeout=Fv(function(){for(var r in t)t.hasOwnProperty(r)&&(e.style[r]=t[r]);e.rcAnimTimeout=null,kD(e)},0)};Pg.setTransition=function(e,t,n){var r=t,a=n;n===void 0&&(a=r,r=\"\"),r=r||\"\",R3e.forEach(function(o){e.style[\"\".concat(o,\"Transition\").concat(r)]=a})};Pg.isCssAnimationSupported=SD;var OD=Pg;function J3(e,t,n){var r,a,o;return OD(e,\"ant-motion-collapse-legacy\",{start:function(){o&&cancelAnimationFrame(o),t?(r=e.offsetHeight,r===0?o=requestAnimationFrame(function(){r=e.offsetHeight,e.style.height=\"0px\",e.style.opacity=\"0\"}):(e.style.height=\"0px\",e.style.opacity=\"0\")):(e.style.height=\"\".concat(e.offsetHeight,\"px\"),e.style.opacity=\"1\")},active:function(){a&&cancelAnimationFrame(a),a=requestAnimationFrame(function(){e.style.height=\"\".concat(t?r:0,\"px\"),e.style.opacity=t?\"1\":\"0\"})},end:function(){o&&cancelAnimationFrame(o),a&&cancelAnimationFrame(a),e.style.height=\"\",e.style.opacity=\"\",n&&n()}})}var L3e={onEnter:function(t,n){Ne(function(){J3(t,!0,n)})},onLeave:function(t,n){return J3(t,!1,n)}},PD=L3e,F3e=G({name:\"PanelContent\",props:{prefixCls:u.string,isActive:u.looseBool,destroyInactivePanel:u.looseBool,forceRender:u.looseBool,role:u.any},data:function(){return{_isActive:void 0}},render:function(){var t;if(this._isActive=this.forceRender||this._isActive||this.isActive,!this._isActive)return null;var n=this.$props,r=n.prefixCls,a=n.isActive,o=n.destroyInactivePanel,i=n.forceRender,l=n.role,s=(t={},V(t,\"\".concat(r,\"-content\"),!0),V(t,\"\".concat(r,\"-content-active\"),a),t),c=!i&&!a&&o?null:g(\"div\",{class:\"\".concat(r,\"-content-box\")},[ht(this)]);return g(\"div\",{class:s,role:l},[c])}}),B3e=function(){return{prefixCls:u.string,activeKey:u.oneOfType([u.string,u.number,u.arrayOf(u.oneOfType([u.string,u.number]))]),defaultActiveKey:u.oneOfType([u.string,u.number,u.arrayOf(u.oneOfType([u.string,u.number]))]),accordion:u.looseBool,destroyInactivePanel:u.looseBool,bordered:u.looseBool,expandIcon:u.func,openAnimation:u.object,expandIconPosition:u.oneOf([\"left\",\"right\"]),onChange:u.func}},V3e=function(){return{openAnimation:u.object,prefixCls:u.string,header:u.any,headerClass:u.string,showArrow:u.looseBool,isActive:u.looseBool,destroyInactivePanel:u.looseBool,disabled:u.looseBool,accordion:u.looseBool,forceRender:u.looseBool,expandIcon:u.func,extra:u.any,panelKey:u.any}},z3e=G({name:\"Panel\",mixins:[nt],props:An(V3e(),{showArrow:!0,isActive:!1,destroyInactivePanel:!1,headerClass:\"\",forceRender:!1}),methods:{handleItemClick:function(){this.__emit(\"itemClick\",this.panelKey)},handleKeyPress:function(t){(t.key===\"Enter\"||t.keyCode===13||t.which===13)&&this.handleItemClick()}},render:function(){var t,n,r=this,a=this.$props,o=a.prefixCls,i=a.headerClass,l=a.isActive,s=a.showArrow,c=a.destroyInactivePanel,d=a.disabled,f=a.openAnimation,p=a.accordion,v=a.forceRender,m=a.expandIcon,y=a.extra,b=P({appear:!0,css:!1},f),C=(t={},V(t,\"\".concat(o,\"-header\"),!0),V(t,i,i),t),S=We(this,\"header\"),w=(n={},V(n,\"\".concat(o,\"-item\"),!0),V(n,\"\".concat(o,\"-item-active\"),l),V(n,\"\".concat(o,\"-item-disabled\"),d),n),k=g(\"i\",{class:\"arrow\"},null);s&&typeof m==\"function\"&&(k=m(this.$props));var $=at(g(F3e,{prefixCls:o,isActive:l,destroyInactivePanel:c,forceRender:v,role:p?\"tabpanel\":null},{default:function(){return[ht(r)]}}),[[_t,l]]);return g(\"div\",{class:w,role:\"tablist\"},[g(\"div\",{class:C,onClick:this.handleItemClick,onKeypress:this.handleKeyPress,role:p?\"tab\":\"button\",tabindex:d?-1:0,\"aria-expanded\":l},[s&&k,S,y&&g(\"div\",{class:\"\".concat(o,\"-extra\")},[y])]),g(Cg,b,{default:function(){return[$]}})])}});function Q3(e,t,n,r){var a;return OD(e,n,{start:function(){t?(a=e.offsetHeight,e.style.height=0):e.style.height=\"\".concat(e.offsetHeight,\"px\")},active:function(){e.style.height=\"\".concat(t?a:0,\"px\")},end:function(){e.style.height=\"\",r()}})}function H3e(e){return{onEnter:function(n,r){return Q3(n,!0,\"\".concat(e,\"-anim\"),r)},onLeave:function(n,r){return Q3(n,!1,\"\".concat(e,\"-anim\"),r)}}}function eT(e){var t=e;if(!Array.isArray(t)){var n=kt(t);t=n===\"number\"||n===\"string\"?[t]:[]}return t.map(function(r){return String(r)})}var eS=G({name:\"Collapse\",mixins:[nt],inheritAttrs:!1,props:An(B3e(),{prefixCls:\"rc-collapse\",accordion:!1,destroyInactivePanel:!1}),data:function(){var t=this.$props,n=t.activeKey,r=t.defaultActiveKey,a=t.openAnimation,o=t.prefixCls,i=r;vt(this,\"activeKey\")&&(i=n);var l=a||H3e(o);return{currentOpenAnimations:l,stateActiveKey:eT(i)}},watch:{activeKey:function(t){this.setState({stateActiveKey:eT(t)})},openAnimation:function(t){this.setState({currentOpenAnimations:t})}},methods:{onClickItem:function(t){var n=this.stateActiveKey;if(this.accordion)n=n[0]===t?[]:[t];else{n=Je(n);var r=n.indexOf(t),a=r>-1;a?n.splice(r,1):n.push(t)}this.setActiveKey(n)},getNewChild:function(t,n){var r;if(!As(t)){var a=this.stateActiveKey,o=this.$props,i=o.prefixCls,l=o.accordion,s=o.destroyInactivePanel,c=o.expandIcon,d=String((r=t.key)!==null&&r!==void 0?r:n),f=rr(t),p=f.header,v=f.headerClass,m=f.disabled,y=!1;l?y=a[0]===d:y=a.indexOf(d)>-1;var b={};!m&&m!==\"\"&&(b={onItemClick:this.onClickItem});var C=P({key:d,panelKey:d,header:p,headerClass:v,isActive:y,prefixCls:i,destroyInactivePanel:s,openAnimation:this.currentOpenAnimations,accordion:l,expandIcon:c},b);return Ot(t,C)}},getItems:function(){var t=this,n=[],r=ht(this);return r&&r.forEach(function(a,o){n.push(t.getNewChild(a,o))}),n},setActiveKey:function(t){vt(this,\"activeKey\")||this.setState({stateActiveKey:t}),this.__emit(\"change\",this.accordion?t[0]:t)}},render:function(){var t,n=this.$props,r=n.prefixCls,a=n.accordion,o=this.$attrs,i=o.class,l=o.style,s=(t={},V(t,r,!0),V(t,i,i),t);return g(\"div\",le(le({class:s},eg(this.$attrs)),{},{style:l,role:a?\"tablist\":null}),[this.getItems()])}});eS.Panel=z3e;var j3e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},K3e={prefixCls:u.string,activeKey:{type:[Array,Number,String]},defaultActiveKey:{type:[Array,Number,String]},accordion:u.looseBool,destroyInactivePanel:u.looseBool,bordered:u.looseBool.def(!0),expandIcon:u.func,openAnimation:u.object.def(PD),expandIconPosition:u.oneOf(rt(\"left\",\"right\")).def(\"left\"),\"onUpdate:activeKey\":u.func,onChange:u.func},Pd=G({name:\"ACollapse\",inheritAttrs:!1,props:K3e,setup:function(){return{configProvider:ve(\"configProvider\",St)}},methods:{renderExpandIcon:function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0,r=We(this,\"expandIcon\",t),a=r||g(wi,{rotate:t.isActive?90:void 0},null);return zn(Array.isArray(r)?a[0]:a)?Ot(a,{class:\"\".concat(n,\"-arrow\")}):a},handleChange:function(t){this.$emit(\"update:activeKey\",t),this.$emit(\"change\",t)}},render:function(){var t,n=this,r=this.prefixCls,a=this.bordered,o=this.expandIconPosition,i=this.configProvider.getPrefixCls,l=i(\"collapse\",r),s=this.$attrs,c=s.class,d=j3e(s,[\"class\"]),f=(t={},V(t,c,c),V(t,\"\".concat(l,\"-borderless\"),!a),V(t,\"\".concat(l,\"-icon-position-\").concat(o),!0),t),p=P(P(P(P({},Qe(this)),{prefixCls:l,expandIcon:function(m){return n.renderExpandIcon(m,l)},class:f}),d),{onChange:this.handleChange});return g(eS,p,{default:function(){return[ht(n)]}})}}),W3e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},U3e={openAnimation:u.object,prefixCls:u.string,header:u.VNodeChild,headerClass:u.string,showArrow:u.looseBool,isActive:u.looseBool,destroyInactivePanel:u.looseBool,disabled:u.looseBool,accordion:u.looseBool,forceRender:u.looseBool,expandIcon:u.func,extra:u.VNodeChild,panelKey:u.VNodeChild},rm=G({name:\"ACollapsePanel\",inheritAttrs:!1,props:U3e,setup:function(){return{configProvider:ve(\"configProvider\",St)}},render:function(){var t,n=this,r=this.prefixCls,a=this.showArrow,o=a===void 0?!0:a,i=this.configProvider.getPrefixCls,l=i(\"collapse\",r),s=this.$attrs,c=s.class,d=W3e(s,[\"class\"]),f=(t={},V(t,c,c),V(t,\"\".concat(l,\"-no-arrow\"),!o),t),p=P(P(P({},Qe(this)),{header:We(this,\"header\"),prefixCls:l,extra:We(this,\"extra\"),class:f}),d);return g(eS.Panel,p,{default:function(){return[ht(n)]}})}});Pd.Panel=rm;Pd.install=function(e){return e.component(Pd.name,Pd),e.component(rm.name,rm),e};var Y3e=function(t){return t.replace(/[A-Z]/g,function(n){return\"-\"+n.toLowerCase()}).toLowerCase()},q3e=function(t){var n=/[height|width]$/;return n.test(t)},tT=function(t){var n=\"\",r=Object.keys(t);return r.forEach(function(a,o){var i=t[a];a=Y3e(a),q3e(a)&&typeof i==\"number\"&&(i=i+\"px\"),i===!0?n+=a:i===!1?n+=\"not \"+a:n+=\"(\"+a+\": \"+i+\")\",o<r.length-1&&(n+=\" and \")}),n};function Xy(e){var t=\"\";return typeof e==\"string\"?e:e instanceof Array?(e.forEach(function(n,r){t+=tT(n),r<e.length-1&&(t+=\", \")}),t):tT(e)}var G3e={accessibility:u.looseBool.def(!0),adaptiveHeight:u.looseBool.def(!1),afterChange:u.any.def(null),arrows:u.looseBool.def(!0),autoplay:u.looseBool.def(!1),autoplaySpeed:u.number.def(3e3),beforeChange:u.any.def(null),centerMode:u.looseBool.def(!1),centerPadding:u.string.def(\"50px\"),cssEase:u.string.def(\"ease\"),dots:u.looseBool.def(!1),dotsClass:u.string.def(\"slick-dots\"),draggable:u.looseBool.def(!0),unslick:u.looseBool.def(!1),easing:u.string.def(\"linear\"),edgeFriction:u.number.def(.35),fade:u.looseBool.def(!1),focusOnSelect:u.looseBool.def(!1),infinite:u.looseBool.def(!0),initialSlide:u.number.def(0),lazyLoad:u.any.def(null),verticalSwiping:u.looseBool.def(!1),asNavFor:u.any.def(null),pauseOnDotsHover:u.looseBool.def(!1),pauseOnFocus:u.looseBool.def(!1),pauseOnHover:u.looseBool.def(!0),responsive:u.array,rows:u.number.def(1),rtl:u.looseBool.def(!1),slide:u.string.def(\"div\"),slidesPerRow:u.number.def(1),slidesToScroll:u.number.def(1),slidesToShow:u.number.def(1),speed:u.number.def(500),swipe:u.looseBool.def(!0),swipeEvent:u.any.def(null),swipeToSlide:u.looseBool.def(!1),touchMove:u.looseBool.def(!0),touchThreshold:u.number.def(5),useCSS:u.looseBool.def(!0),useTransform:u.looseBool.def(!0),variableWidth:u.looseBool.def(!1),vertical:u.looseBool.def(!1),waitForAnimate:u.looseBool.def(!0),children:u.array,__propsSymbol__:u.any},TD=G3e,X3e={animating:!1,autoplaying:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,dragging:!1,edgeDragged:!1,initialized:!1,lazyLoadedList:[],listHeight:null,listWidth:null,scrolling:!1,slideCount:null,slideHeight:null,slideWidth:null,swipeLeft:null,swiped:!1,swiping:!1,touchObject:{startX:0,startY:0,curX:0,curY:0},trackStyle:{},trackWidth:0},Z3e=X3e,am=function(t){for(var n=[],r=xD(t),a=_D(t),o=r;o<a;o++)t.lazyLoadedList.indexOf(o)<0&&n.push(o);return n},xD=function(t){return t.currentSlide-J3e(t)},_D=function(t){return t.currentSlide+Q3e(t)},J3e=function(t){return t.centerMode?Math.floor(t.slidesToShow/2)+(parseInt(t.centerPadding)>0?1:0):0},Q3e=function(t){return t.centerMode?Math.floor((t.slidesToShow-1)/2)+1+(parseInt(t.centerPadding)>0?1:0):t.slidesToShow},y1=function(t){return t&&t.offsetWidth||0},tS=function(t){return t&&t.offsetHeight||0},ED=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,r,a=t.startX-t.curX,o=t.startY-t.curY,i=Math.atan2(o,a);return r=Math.round(i*180/Math.PI),r<0&&(r=360-Math.abs(r)),r<=45&&r>=0||r<=360&&r>=315?\"left\":r>=135&&r<=225?\"right\":n===!0?r>=35&&r<=135?\"up\":\"down\":\"vertical\"},Tg=function(t){var n=!0;return t.infinite||(t.centerMode&&t.currentSlide>=t.slideCount-1||t.slideCount<=t.slidesToShow||t.currentSlide>=t.slideCount-t.slidesToShow)&&(n=!1),n},Zy=function(t,n){var r={};return n.forEach(function(a){return r[a]=t[a]}),r},eTe=function(t){var n=t.children.length,r=Math.ceil(y1(t.listRef)),a=Math.ceil(y1(t.trackRef)),o;if(t.vertical)o=r;else{var i=t.centerMode&&parseInt(t.centerPadding)*2;typeof t.centerPadding==\"string\"&&t.centerPadding.slice(-1)===\"%\"&&(i*=r/100),o=Math.ceil((r-i)/t.slidesToShow)}var l=t.listRef&&tS(t.listRef.querySelector('[data-index=\"0\"]')),s=l*t.slidesToShow,c=t.currentSlide===void 0?t.initialSlide:t.currentSlide;t.rtl&&t.currentSlide===void 0&&(c=n-1-t.initialSlide);var d=t.lazyLoadedList||[],f=am({currentSlide:c,lazyLoadedList:d});d.concat(f);var p={slideCount:n,slideWidth:o,listWidth:r,trackWidth:a,currentSlide:c,slideHeight:l,listHeight:s,lazyLoadedList:d};return t.autoplaying===null&&t.autoplay&&(p.autoplaying=\"playing\"),p},tTe=function(t){var n=t.waitForAnimate,r=t.animating,a=t.fade,o=t.infinite,i=t.index,l=t.slideCount,s=t.lazyLoadedList,c=t.lazyLoad,d=t.currentSlide,f=t.centerMode,p=t.slidesToScroll,v=t.slidesToShow,m=t.useCSS;if(n&&r)return{};var y=i,b,C,S,w={},k={};if(a){if(!o&&(i<0||i>=l))return{};i<0?y=i+l:i>=l&&(y=i-l),c&&s.indexOf(y)<0&&s.push(y),w={animating:!0,currentSlide:y,lazyLoadedList:s},k={animating:!1}}else b=y,y<0?(b=y+l,o?l%p!==0&&(b=l-l%p):b=0):!Tg(t)&&y>d?y=b=d:f&&y>=l?(y=o?l:l-1,b=o?0:l-1):y>=l&&(b=y-l,o?l%p!==0&&(b=0):b=l-v),C=hf(P(P({},t),{slideIndex:y})),S=hf(P(P({},t),{slideIndex:b})),o||(C===S&&(y=b),C=S),c&&s.concat(am(P(P({},t),{currentSlide:y}))),m?(w={animating:!0,currentSlide:b,trackStyle:MD(P(P({},t),{left:C})),lazyLoadedList:s},k={animating:!1,currentSlide:b,trackStyle:ff(P(P({},t),{left:S})),swipeLeft:null}):w={currentSlide:b,trackStyle:ff(P(P({},t),{left:S})),lazyLoadedList:s};return{state:w,nextState:k}},nTe=function(t,n){var r,a,o,i=t.slidesToScroll,l=t.slidesToShow,s=t.slideCount,c=t.currentSlide,d=t.lazyLoad,f=t.infinite,p=s%i!==0,v=p?0:(s-c)%i;if(n.message===\"previous\")a=v===0?i:l-v,o=c-a,d&&!f&&(r=c-a,o=r===-1?s-1:r);else if(n.message===\"next\")a=v===0?i:v,o=c+a,d&&!f&&(o=(c+i)%s+v);else if(n.message===\"dots\"){if(o=n.index*n.slidesToScroll,o===n.currentSlide)return null}else if(n.message===\"children\"){if(o=n.index,o===n.currentSlide)return null;if(f){var m=uTe(P(P({},t),{targetSlide:o}));o>n.currentSlide&&m===\"left\"?o=o-s:o<n.currentSlide&&m===\"right\"&&(o=o+s)}}else if(n.message===\"index\"&&(o=Number(n.index),o===n.currentSlide))return null;return o},rTe=function(t,n,r){return t.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||!n?\"\":t.keyCode===37?r?\"next\":\"previous\":t.keyCode===39?r?\"previous\":\"next\":\"\"},aTe=function(t,n,r){return t.target.tagName===\"IMG\"&&t.preventDefault(),!n||!r&&t.type.indexOf(\"mouse\")!==-1?\"\":{dragging:!0,touchObject:{startX:t.touches?t.touches[0].pageX:t.clientX,startY:t.touches?t.touches[0].pageY:t.clientY,curX:t.touches?t.touches[0].pageX:t.clientX,curY:t.touches?t.touches[0].pageY:t.clientY}}},oTe=function(t,n){var r=n.scrolling,a=n.animating,o=n.vertical,i=n.swipeToSlide,l=n.verticalSwiping,s=n.rtl,c=n.currentSlide,d=n.edgeFriction,f=n.edgeDragged,p=n.onEdge,v=n.swiped,m=n.swiping,y=n.slideCount,b=n.slidesToScroll,C=n.infinite,S=n.touchObject,w=n.swipeEvent,k=n.listHeight,$=n.listWidth;if(!r){if(a)return t.preventDefault();o&&i&&l&&t.preventDefault();var O,T={},_=hf(n);S.curX=t.touches?t.touches[0].pageX:t.clientX,S.curY=t.touches?t.touches[0].pageY:t.clientY,S.swipeLength=Math.round(Math.sqrt(Math.pow(S.curX-S.startX,2)));var I=Math.round(Math.sqrt(Math.pow(S.curY-S.startY,2)));if(!l&&!m&&I>10)return{scrolling:!0};l&&(S.swipeLength=I);var L=(s?-1:1)*(S.curX>S.startX?1:-1);l&&(L=S.curY>S.startY?1:-1);var j=Math.ceil(y/b),F=ED(n.touchObject,l),N=S.swipeLength;return C||(c===0&&F===\"right\"||c+1>=j&&F===\"left\"||!Tg(n)&&F===\"left\")&&(N=S.swipeLength*d,f===!1&&p&&(p(F),T.edgeDragged=!0)),!v&&w&&(w(F),T.swiped=!0),o?O=_+N*(k/$)*L:s?O=_-N*L:O=_+N*L,l&&(O=_+N*L),T=P(P({},T),{touchObject:S,swipeLeft:O,trackStyle:ff(P(P({},n),{left:O}))}),Math.abs(S.curX-S.startX)<Math.abs(S.curY-S.startY)*.8||S.swipeLength>10&&(T.swiping=!0,t.preventDefault()),T}},iTe=function(t,n){var r=n.dragging,a=n.swipe,o=n.touchObject,i=n.listWidth,l=n.touchThreshold,s=n.verticalSwiping,c=n.listHeight,d=n.currentSlide,f=n.swipeToSlide,p=n.scrolling,v=n.onSwipe;if(!r)return a&&t.preventDefault(),{};var m=s?c/l:i/l,y=ED(o,s),b={dragging:!1,edgeDragged:!1,scrolling:!1,swiping:!1,swiped:!1,swipeLeft:null,touchObject:{}};if(p||!o.swipeLength)return b;if(o.swipeLength>m){t.preventDefault(),v&&v(y);var C,S;switch(y){case\"left\":case\"up\":S=d+rT(n),C=f?nT(n,S):S,b.currentDirection=0;break;case\"right\":case\"down\":S=d-rT(n),C=f?nT(n,S):S,b.currentDirection=1;break;default:C=d}b.triggerSlideHandler=C}else{var w=hf(n);b.trackStyle=MD(P(P({},n),{left:w}))}return b},lTe=function(t){for(var n=t.infinite?t.slideCount*2:t.slideCount,r=t.infinite?t.slidesToShow*-1:0,a=t.infinite?t.slidesToShow*-1:0,o=[];r<n;)o.push(r),r=a+t.slidesToScroll,a+=Math.min(t.slidesToScroll,t.slidesToShow);return o},nT=function(t,n){var r=lTe(t),a=0;if(n>r[r.length-1])n=r[r.length-1];else for(var o in r){if(n<r[o]){n=a;break}a=r[o]}return n},rT=function(t){var n=t.centerMode?t.slideWidth*Math.floor(t.slidesToShow/2):0;if(t.swipeToSlide){var r,a=t.listRef,o=a.querySelectorAll(\".slick-slide\");if(Array.from(o).every(function(s){if(t.vertical){if(s.offsetTop+tS(s)/2>t.swipeLeft*-1)return r=s,!1}else if(s.offsetLeft-n+y1(s)/2>t.swipeLeft*-1)return r=s,!1;return!0}),!r)return 0;var i=t.rtl===!0?t.slideCount-t.currentSlide:t.currentSlide,l=Math.abs(r.dataset.index-i)||1;return l}else return t.slidesToScroll},nS=function(t,n){return n.reduce(function(r,a){return r&&t.hasOwnProperty(a)},!0)?null:console.error(\"Keys Missing:\",t)},ff=function(t){nS(t,[\"left\",\"variableWidth\",\"slideCount\",\"slidesToShow\",\"slideWidth\"]);var n,r,a=t.slideCount+2*t.slidesToShow;t.vertical?r=a*t.slideHeight:n=sTe(t)*t.slideWidth;var o={opacity:1,transition:\"\",WebkitTransition:\"\"};if(t.useTransform){var i=t.vertical?\"translate3d(0px, \"+t.left+\"px, 0px)\":\"translate3d(\"+t.left+\"px, 0px, 0px)\",l=t.vertical?\"translate3d(0px, \"+t.left+\"px, 0px)\":\"translate3d(\"+t.left+\"px, 0px, 0px)\",s=t.vertical?\"translateY(\"+t.left+\"px)\":\"translateX(\"+t.left+\"px)\";o=P(P({},o),{WebkitTransform:i,transform:l,msTransform:s})}else t.vertical?o.top=t.left:o.left=t.left;return t.fade&&(o={opacity:1}),n&&(o.width=n+\"px\"),r&&(o.height=r+\"px\"),window&&!window.addEventListener&&window.attachEvent&&(t.vertical?o.marginTop=t.left+\"px\":o.marginLeft=t.left+\"px\"),o},MD=function(t){nS(t,[\"left\",\"variableWidth\",\"slideCount\",\"slidesToShow\",\"slideWidth\",\"speed\",\"cssEase\"]);var n=ff(t);return t.useTransform?(n.WebkitTransition=\"-webkit-transform \"+t.speed+\"ms \"+t.cssEase,n.transition=\"transform \"+t.speed+\"ms \"+t.cssEase):t.vertical?n.transition=\"top \"+t.speed+\"ms \"+t.cssEase:n.transition=\"left \"+t.speed+\"ms \"+t.cssEase,n},hf=function(t){if(t.unslick)return 0;nS(t,[\"slideIndex\",\"trackRef\",\"infinite\",\"centerMode\",\"slideCount\",\"slidesToShow\",\"slidesToScroll\",\"slideWidth\",\"listWidth\",\"variableWidth\",\"slideHeight\"]);var n=t.slideIndex,r=t.trackRef,a=t.infinite,o=t.centerMode,i=t.slideCount,l=t.slidesToShow,s=t.slidesToScroll,c=t.slideWidth,d=t.listWidth,f=t.variableWidth,p=t.slideHeight,v=t.fade,m=t.vertical,y=0,b,C,S=0;if(v||t.slideCount===1)return 0;var w=0;if(a?(w=-ui(t),i%s!==0&&n+s>i&&(w=-(n>i?l-(n-i):i%s)),o&&(w+=parseInt(l/2))):(i%s!==0&&n+s>i&&(w=l-i%s),o&&(w=parseInt(l/2))),y=w*c,S=w*p,m?b=n*p*-1+S:b=n*c*-1+y,f===!0){var k,$=r;if(k=n+ui(t),C=$&&$.childNodes[k],b=C?C.offsetLeft*-1:0,o===!0){k=a?n+ui(t):n,C=$&&$.children[k],b=0;for(var O=0;O<k;O++)b-=$&&$.children[O]&&$.children[O].offsetWidth;b-=parseInt(t.centerPadding),b+=C&&(d-C.offsetWidth)/2}}return b},ui=function(t){return t.unslick||!t.infinite?0:t.variableWidth?t.slideCount:t.slidesToShow+(t.centerMode?1:0)},Up=function(t){return t.unslick||!t.infinite?0:t.slideCount},sTe=function(t){return t.slideCount===1?1:ui(t)+t.slideCount+Up(t)},uTe=function(t){return t.targetSlide>t.currentSlide?t.targetSlide>t.currentSlide+cTe(t)?\"left\":\"right\":t.targetSlide<t.currentSlide-dTe(t)?\"right\":\"left\"},cTe=function(t){var n=t.slidesToShow,r=t.centerMode,a=t.rtl,o=t.centerPadding;if(r){var i=(n-1)/2+1;return parseInt(o)>0&&(i+=1),a&&n%2===0&&(i+=1),i}return a?0:n-1},dTe=function(t){var n=t.slidesToShow,r=t.centerMode,a=t.rtl,o=t.centerPadding;if(r){var i=(n-1)/2+1;return parseInt(o)>0&&(i+=1),!a&&n%2===0&&(i+=1),i}return a?n-1:0},aT=function(){return!!(typeof window!=\"undefined\"&&window.document&&window.document.createElement)},Jy=function(t){var n,r,a,o;t.rtl?o=t.slideCount-1-t.index:o=t.index;var i=o<0||o>=t.slideCount;t.centerMode?(a=Math.floor(t.slidesToShow/2),r=(o-t.currentSlide)%t.slideCount===0,o>t.currentSlide-a-1&&o<=t.currentSlide+a&&(n=!0)):n=t.currentSlide<=o&&o<t.currentSlide+t.slidesToShow;var l=o===t.currentSlide;return{\"slick-slide\":!0,\"slick-active\":n,\"slick-center\":r,\"slick-cloned\":i,\"slick-current\":l}},fTe=function(t){var n={};return(t.variableWidth===void 0||t.variableWidth===!1)&&(n.width=t.slideWidth+(typeof t.slideWidth==\"number\"?\"px\":\"\")),t.fade&&(n.position=\"relative\",t.vertical?n.top=-t.index*parseInt(t.slideHeight)+\"px\":n.left=-t.index*parseInt(t.slideWidth)+\"px\",n.opacity=t.currentSlide===t.index?1:0,n.transition=\"opacity \"+t.speed+\"ms \"+t.cssEase+\", visibility \"+t.speed+\"ms \"+t.cssEase,n.WebkitTransition=\"opacity \"+t.speed+\"ms \"+t.cssEase+\", visibility \"+t.speed+\"ms \"+t.cssEase),n},Qy=function(t,n){return t.key||t.key===0&&\"0\"||n},hTe=function(t,n){var r,a=[],o=[],i=[],l=n.length,s=xD(t),c=_D(t);return n.forEach(function(d,f){var p,v={message:\"children\",index:f,slidesToScroll:t.slidesToScroll,currentSlide:t.currentSlide};!t.lazyLoad||t.lazyLoad&&t.lazyLoadedList.indexOf(f)>=0?p=d:p=g(\"div\");var m=fTe(P(P({},t),{index:f})),y=p.props.class||\"\",b=Jy(P(P({},t),{index:f}));if(a.push(Ot(p,{key:\"original\"+Qy(p,f),tabindex:\"-1\",\"data-index\":f,\"aria-hidden\":!b[\"slick-active\"],class:Se(b,y),style:P(P({outline:\"none\"},p.props.style||{}),m),onClick:function(){t.focusOnSelect&&t.focusOnSelect(v)}})),t.infinite&&t.fade===!1){var C=l-f;C<=ui(t)&&l!==t.slidesToShow&&(r=-C,r>=s&&(p=d),b=Jy(P(P({},t),{index:r})),o.push(Ot(p,{key:\"precloned\"+Qy(p,r),class:Se(b,y),tabindex:\"-1\",\"data-index\":r,\"aria-hidden\":!b[\"slick-active\"],style:P(P({},p.props.style||{}),m),onClick:function(){t.focusOnSelect&&t.focusOnSelect(v)}}))),l!==t.slidesToShow&&(r=l+f,r<c&&(p=d),b=Jy(P(P({},t),{index:r})),i.push(Ot(p,{key:\"postcloned\"+Qy(p,r),tabindex:\"-1\",\"data-index\":r,\"aria-hidden\":!b[\"slick-active\"],class:Se(b,y),style:P(P({},p.props.style||{}),m),onClick:function(){t.focusOnSelect&&t.focusOnSelect(v)}})))}}),t.rtl?o.concat(a,i).reverse():o.concat(a,i)},ID=function(t,n){var r=n.attrs,a=n.slots,o=hTe(r,Un(a==null?void 0:a.default())),i=r.onMouseenter,l=r.onMouseover,s=r.onMouseleave,c={onMouseenter:i,onMouseover:l,onMouseleave:s},d=P({class:\"slick-track\",style:r.trackStyle},c);return g(\"div\",d,[o])};ID.inheritAttrs=!1;var pTe=ID,vTe=function(t){var n;return t.infinite?n=Math.ceil(t.slideCount/t.slidesToScroll):n=Math.ceil((t.slideCount-t.slidesToShow)/t.slidesToScroll)+1,n},ND=function(t,n){var r=n.attrs,a=r.slideCount,o=r.slidesToScroll,i=r.slidesToShow,l=r.infinite,s=r.currentSlide,c=r.appendDots,d=r.customPaging,f=r.clickHandler,p=r.dotsClass,v=r.onMouseenter,m=r.onMouseover,y=r.onMouseleave,b=vTe({slideCount:a,slidesToScroll:o,slidesToShow:i,infinite:l}),C={onMouseenter:v,onMouseover:m,onMouseleave:y},S=Array.apply(null,Array(b+1).join(\"0\").split(\"\")).map(function(w,k){var $=k*o,O=k*o+(o-1),T=Se({\"slick-active\":s>=$&&s<=O}),_={message:\"dots\",index:k,slidesToScroll:o,currentSlide:s};function I(L){L&&L.preventDefault(),f(_)}return g(\"li\",{key:k,class:T},[Ot(d({i:k}),{onClick:I})])});return Ot(c({dots:S}),P({class:p},C))};ND.inheritAttrs=!1;var mTe=ND;function AD(){}function DD(e,t,n){n&&n.preventDefault(),t(e,n)}var RD=function(t,n){var r=n.attrs,a=r.clickHandler,o=r.infinite,i=r.currentSlide,l=r.slideCount,s=r.slidesToShow,c={\"slick-arrow\":!0,\"slick-prev\":!0},d=function(y){DD({message:\"previous\"},a,y)};!o&&(i===0||l<=s)&&(c[\"slick-disabled\"]=!0,d=AD);var f={key:\"0\",\"data-role\":\"none\",class:c,style:{display:\"block\"},onClick:d},p={currentSlide:i,slideCount:l},v;return r.prevArrow?v=Ot(r.prevArrow(P(P({},f),p)),{key:\"0\",class:c,style:{display:\"block\"},onClick:d},!1):v=g(\"button\",le({key:\"0\",type:\"button\"},f),[\" \",yt(\"Previous\")]),v};RD.inheritAttrs=!1;var LD=function(t,n){var r=n.attrs,a=r.clickHandler,o=r.currentSlide,i=r.slideCount,l={\"slick-arrow\":!0,\"slick-next\":!0},s=function(v){DD({message:\"next\"},a,v)};Tg(r)||(l[\"slick-disabled\"]=!0,s=AD);var c={key:\"1\",\"data-role\":\"none\",class:Se(l),style:{display:\"block\"},onClick:s},d={currentSlide:o,slideCount:i},f;return r.nextArrow?f=Ot(r.nextArrow(P(P({},c),d)),{key:\"1\",class:Se(l),style:{display:\"block\"},onClick:s},!1):f=g(\"button\",le({key:\"1\",type:\"button\"},c),[\" \",yt(\"Next\")]),f};LD.inheritAttrs=!1;var gTe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function Xr(){}var yTe={name:\"InnerSlider\",inheritAttrs:!1,props:P({},TD),mixins:[nt],data:function(){return this.preProps=P({},this.$props),this.list=null,this.track=null,this.callbackTimers=[],this.clickable=!0,this.debouncedResize=null,P(P({},Z3e),{currentSlide:this.initialSlide,slideCount:this.children.length})},methods:{listRefHandler:function(t){this.list=t},trackRefHandler:function(t){this.track=t},adaptHeight:function(){if(this.adaptiveHeight&&this.list){var t=this.list.querySelector('[data-index=\"'.concat(this.currentSlide,'\"]'));this.list.style.height=tS(t)+\"px\"}},onWindowResized:function(t){var n=this;this.debouncedResize&&this.debouncedResize.cancel(),this.debouncedResize=Yn(function(){return n.resizeWindow(t)},50),this.debouncedResize()},resizeWindow:function(){var t=this,n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!0;if(!!this.track){var r=P(P({listRef:this.list,trackRef:this.track,children:this.children},this.$props),this.$data);this.updateState(r,n,function(){t.autoplay?t.handleAutoPlay(\"update\"):t.pause(\"paused\")}),this.setState({animating:!1}),clearTimeout(this.animationEndCallback),delete this.animationEndCallback}},updateState:function(t,n,r){var a=eTe(t);t=P(P(P({},t),a),{slideIndex:a.currentSlide});var o=hf(t);t=P(P({},t),{left:o});var i=ff(t);(n||this.children.length!==t.children.length)&&(a.trackStyle=i),this.setState(a,r)},ssrInit:function(){var t=this.children;if(this.variableWidth){var n=0,r=0,a=[],o=ui(P(P(P({},this.$props),this.$data),{slideCount:t.length})),i=Up(P(P(P({},this.$props),this.$data),{slideCount:t.length}));t.forEach(function(w){var k,$,O=(($=(k=w.props.style)===null||k===void 0?void 0:k.width)===null||$===void 0?void 0:$.split(\"px\")[0])||0;a.push(O),n+=O});for(var l=0;l<o;l++)r+=a[a.length-1-l],n+=a[a.length-1-l];for(var s=0;s<i;s++)n+=a[s];for(var c=0;c<this.currentSlide;c++)r+=a[c];var d={width:n+\"px\",left:-r+\"px\"};if(this.centerMode){var f=\"\".concat(a[this.currentSlide],\"px\");d.left=\"calc(\".concat(d.left,\" + (100% - \").concat(f,\") / 2 ) \")}this.setState({trackStyle:d});return}var p=t.length,v=P(P(P({},this.$props),this.$data),{slideCount:p}),m=ui(v)+Up(v)+p,y=100/this.slidesToShow*m,b=100/m,C=-b*(ui(v)+this.currentSlide)*y/100;this.centerMode&&(C+=(100-b*y/100)/2);var S={width:y+\"%\",left:C+\"%\"};this.setState({slideWidth:b+\"%\",trackStyle:S})},checkImagesLoad:function(){var t=this,n=document.querySelectorAll(\".slick-slide img\"),r=n.length,a=0;Array.prototype.forEach.call(n,function(o){var i=function(){return++a&&a>=r&&t.onWindowResized()};if(!o.onclick)o.onclick=function(){return o.parentNode.focus()};else{var l=o.onclick;o.onclick=function(){l(),o.parentNode.focus()}}o.onload||(t.$props.lazyLoad?o.onload=function(){t.adaptHeight(),t.callbackTimers.push(setTimeout(t.onWindowResized,t.speed))}:(o.onload=i,o.onerror=function(){i(),t.__emit(\"lazyLoadError\")}))})},progressiveLazyLoad:function(){for(var t=[],n=P(P({},this.$props),this.$data),r=this.currentSlide;r<this.slideCount+Up(n);r++)if(this.lazyLoadedList.indexOf(r)<0){t.push(r);break}for(var a=this.currentSlide-1;a>=-ui(n);a--)if(this.lazyLoadedList.indexOf(a)<0){t.push(a);break}t.length>0?(this.setState(function(o){return{lazyLoadedList:o.lazyLoadedList.concat(t)}}),this.__emit(\"lazyLoad\",t)):this.lazyLoadTimer&&(clearInterval(this.lazyLoadTimer),delete this.lazyLoadTimer)},slideHandler:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,a=this.$props,o=a.asNavFor,i=a.currentSlide,l=a.beforeChange,s=a.speed,c=a.afterChange,d=tTe(P(P(P({index:t},this.$props),this.$data),{trackRef:this.track,useCSS:this.useCSS&&!r})),f=d.state,p=d.nextState;if(!!f){l&&l(i,f.currentSlide);var v=f.lazyLoadedList.filter(function(m){return n.lazyLoadedList.indexOf(m)<0});this.$attrs.onLazyLoad&&v.length>0&&this.__emit(\"lazyLoad\",v),this.setState(f,function(){o&&o.innerSlider.currentSlide!==i&&o.innerSlider.slideHandler(t),p&&(n.animationEndCallback=setTimeout(function(){var m=p.animating,y=gTe(p,[\"animating\"]);n.setState(y,function(){n.callbackTimers.push(setTimeout(function(){return n.setState({animating:m})},10)),c&&c(f.currentSlide),delete n.animationEndCallback})},s))})}},changeSlide:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,r=P(P({},this.$props),this.$data),a=nTe(r,t);a!==0&&!a||(n===!0?this.slideHandler(a,n):this.slideHandler(a))},clickHandler:function(t){this.clickable===!1&&(t.stopPropagation(),t.preventDefault()),this.clickable=!0},keyHandler:function(t){var n=rTe(t,this.accessibility,this.rtl);n!==\"\"&&this.changeSlide({message:n})},selectHandler:function(t){this.changeSlide(t)},disableBodyScroll:function(){var t=function(r){r=r||window.event,r.preventDefault&&r.preventDefault(),r.returnValue=!1};window.ontouchmove=t},enableBodyScroll:function(){window.ontouchmove=null},swipeStart:function(t){this.verticalSwiping&&this.disableBodyScroll();var n=aTe(t,this.swipe,this.draggable);n!==\"\"&&this.setState(n)},swipeMove:function(t){var n=oTe(t,P(P(P({},this.$props),this.$data),{trackRef:this.track,listRef:this.list,slideIndex:this.currentSlide}));!n||(n.swiping&&(this.clickable=!1),this.setState(n))},swipeEnd:function(t){var n=iTe(t,P(P(P({},this.$props),this.$data),{trackRef:this.track,listRef:this.list,slideIndex:this.currentSlide}));if(!!n){var r=n.triggerSlideHandler;delete n.triggerSlideHandler,this.setState(n),r!==void 0&&(this.slideHandler(r),this.$props.verticalSwiping&&this.enableBodyScroll())}},slickPrev:function(){var t=this;this.callbackTimers.push(setTimeout(function(){return t.changeSlide({message:\"previous\"})},0))},slickNext:function(){var t=this;this.callbackTimers.push(setTimeout(function(){return t.changeSlide({message:\"next\"})},0))},slickGoTo:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;if(t=Number(t),isNaN(t))return\"\";this.callbackTimers.push(setTimeout(function(){return n.changeSlide({message:\"index\",index:t,currentSlide:n.currentSlide},r)},0))},play:function(){var t;if(this.rtl)t=this.currentSlide-this.slidesToScroll;else if(Tg(P(P({},this.$props),this.$data)))t=this.currentSlide+this.slidesToScroll;else return!1;this.slideHandler(t)},handleAutoPlay:function(t){this.autoplayTimer&&clearInterval(this.autoplayTimer);var n=this.autoplaying;if(t===\"update\"){if(n===\"hovered\"||n===\"focused\"||n===\"paused\")return}else if(t===\"leave\"){if(n===\"paused\"||n===\"focused\")return}else if(t===\"blur\"&&(n===\"paused\"||n===\"hovered\"))return;this.autoplayTimer=setInterval(this.play,this.autoplaySpeed+50),this.setState({autoplaying:\"playing\"})},pause:function(t){this.autoplayTimer&&(clearInterval(this.autoplayTimer),this.autoplayTimer=null);var n=this.autoplaying;t===\"paused\"?this.setState({autoplaying:\"paused\"}):t===\"focused\"?(n===\"hovered\"||n===\"playing\")&&this.setState({autoplaying:\"focused\"}):n===\"playing\"&&this.setState({autoplaying:\"hovered\"})},onDotsOver:function(){this.autoplay&&this.pause(\"hovered\")},onDotsLeave:function(){this.autoplay&&this.autoplaying===\"hovered\"&&this.handleAutoPlay(\"leave\")},onTrackOver:function(){this.autoplay&&this.pause(\"hovered\")},onTrackLeave:function(){this.autoplay&&this.autoplaying===\"hovered\"&&this.handleAutoPlay(\"leave\")},onSlideFocus:function(){this.autoplay&&this.pause(\"focused\")},onSlideBlur:function(){this.autoplay&&this.autoplaying===\"focused\"&&this.handleAutoPlay(\"blur\")},customPaging:function(t){var n=t.i;return g(\"button\",null,[n+1])},appendDots:function(t){var n=t.dots;return g(\"ul\",{style:{display:\"block\"}},[n])}},beforeMount:function(){if(this.ssrInit(),this.__emit(\"init\"),this.lazyLoad){var t=am(P(P({},this.$props),this.$data));t.length>0&&(this.setState(function(n){return{lazyLoadedList:n.lazyLoadedList.concat(t)}}),this.__emit(\"lazyLoad\",t))}},mounted:function(){var t=this;this.$nextTick(function(){var n=P({listRef:t.list,trackRef:t.track,children:t.children},t.$props);t.updateState(n,!0,function(){t.adaptHeight(),t.autoplay&&t.handleAutoPlay(\"update\")}),t.lazyLoad===\"progressive\"&&(t.lazyLoadTimer=setInterval(t.progressiveLazyLoad,1e3)),t.ro=new ng(function(){t.animating?(t.onWindowResized(!1),t.callbackTimers.push(setTimeout(function(){return t.onWindowResized()},t.speed))):t.onWindowResized()}),t.ro.observe(t.list),Array.prototype.forEach.call(document.querySelectorAll(\".slick-slide\"),function(r){r.onfocus=t.$props.pauseOnFocus?t.onSlideFocus:null,r.onblur=t.$props.pauseOnFocus?t.onSlideBlur:null}),window&&(window.addEventListener?window.addEventListener(\"resize\",t.onWindowResized):window.attachEvent(\"onresize\",t.onWindowResized))})},beforeUnmount:function(){this.animationEndCallback&&clearTimeout(this.animationEndCallback),this.lazyLoadTimer&&clearInterval(this.lazyLoadTimer),this.callbackTimers.length&&(this.callbackTimers.forEach(function(t){return clearTimeout(t)}),this.callbackTimers=[]),window.addEventListener?window.removeEventListener(\"resize\",this.onWindowResized):window.detachEvent(\"onresize\",this.onWindowResized),this.autoplayTimer&&clearInterval(this.autoplayTimer)},updated:function(){if(this.checkImagesLoad(),this.__emit(\"reInit\"),this.lazyLoad){var t=am(P(P({},this.$props),this.$data));t.length>0&&(this.setState(function(n){return{lazyLoadedList:n.lazyLoadedList.concat(t)}}),this.__emit(\"lazyLoad\"))}this.adaptHeight()},watch:{__propsSymbol__:function(){for(var t=this,n=this.$props,r=P(P({listRef:this.list,trackRef:this.track},n),this.$data),a=!1,o=0,i=Object.keys(this.preProps);o<i.length;o++){var l=i[o];if(!n.hasOwnProperty(l)){a=!0;break}if(!(kt(n[l])===\"object\"||typeof n[l]==\"function\"||kt(n[l])===\"symbol\")&&n[l]!==this.preProps[l]){a=!0;break}}this.updateState(r,a,function(){t.currentSlide>=n.children.length&&t.changeSlide({message:\"index\",index:n.children.length-n.slidesToShow,currentSlide:t.currentSlide}),n.autoplay?t.handleAutoPlay(\"update\"):t.pause(\"paused\")}),this.preProps=P({},n)}},render:function(){var t,n=this,r=Se(\"slick-slider\",this.$attrs.class,{\"slick-vertical\":this.vertical,\"slick-initialized\":!0}),a=P(P({},this.$props),this.$data),o=Zy(a,[\"fade\",\"cssEase\",\"speed\",\"infinite\",\"centerMode\",\"focusOnSelect\",\"currentSlide\",\"lazyLoad\",\"lazyLoadedList\",\"rtl\",\"slideWidth\",\"slideHeight\",\"listHeight\",\"vertical\",\"slidesToShow\",\"slidesToScroll\",\"slideCount\",\"trackStyle\",\"variableWidth\",\"unslick\",\"centerPadding\"]),i=this.$props.pauseOnHover;o=P(P({},o),{focusOnSelect:this.focusOnSelect?this.selectHandler:null,ref:this.trackRefHandler,onMouseleave:i?this.onTrackLeave:Xr,onMouseover:i?this.onTrackOver:Xr});var l;if(this.dots===!0&&this.slideCount>=this.slidesToShow){var s=Zy(a,[\"dotsClass\",\"slideCount\",\"slidesToShow\",\"currentSlide\",\"slidesToScroll\",\"clickHandler\",\"children\",\"infinite\",\"appendDots\"]);s.customPaging=this.customPaging,s.appendDots=this.appendDots;var c=this.$slots,d=c.customPaging,f=c.appendDots;d&&(s.customPaging=d),f&&(s.appendDots=f);var p=this.$props.pauseOnDotsHover;s=P(P({},s),{clickHandler:this.changeSlide,onMouseover:p?this.onDotsOver:Xr,onMouseleave:p?this.onDotsLeave:Xr}),l=g(mTe,s,null)}var v,m,y=Zy(a,[\"infinite\",\"centerMode\",\"currentSlide\",\"slideCount\",\"slidesToShow\"]);y.clickHandler=this.changeSlide;var b=this.$slots,C=b.prevArrow,S=b.nextArrow;C&&(y.prevArrow=C),S&&(y.nextArrow=S),this.arrows&&(v=g(RD,y,null),m=g(LD,y,null));var w=null;this.vertical&&(w={height:typeof this.listHeight==\"number\"?\"\".concat(this.listHeight,\"px\"):this.listHeight});var k=null;this.vertical===!1?this.centerMode===!0&&(k={padding:\"0px \"+this.centerPadding}):this.centerMode===!0&&(k={padding:this.centerPadding+\" 0px\"});var $=P(P({},w),k),O=this.touchMove,T=(t={ref:this.listRefHandler,class:\"slick-list\",style:$,onClick:this.clickHandler,onMousedown:O?this.swipeStart:Xr,onMousemove:this.dragging&&O?this.swipeMove:Xr,onMouseup:O?this.swipeEnd:Xr,onMouseleave:this.dragging&&O?this.swipeEnd:Xr},V(t,mn?\"onTouchstartPassive\":\"onTouchstart\",O?this.swipeStart:Xr),V(t,mn?\"onTouchmovePassive\":\"onTouchmove\",this.dragging&&O?this.swipeMove:Xr),V(t,\"onTouchend\",O?this.swipeEnd:Xr),V(t,\"onTouchcancel\",this.dragging&&O?this.swipeEnd:Xr),V(t,\"onKeydown\",this.accessibility?this.keyHandler:Xr),t),_={class:r};return this.unslick&&(T={class:\"slick-list\",ref:this.listRefHandler},_={class:r}),g(\"div\",_,[this.unslick?\"\":v,g(\"div\",T,[g(pTe,o,{default:function(){return[n.children]}})]),this.unslick?\"\":m,this.unslick?\"\":l])}},bTe=G({name:\"Slider\",mixins:[nt],inheritAttrs:!1,props:P({},TD),data:function(){return this._responsiveMediaHandlers=[],{breakpoint:null}},beforeMount:function(){var t=this;if(this.responsive){var n=this.responsive.map(function(a){return a.breakpoint});n.sort(function(a,o){return a-o}),n.forEach(function(a,o){var i;o===0?i=Xy({minWidth:0,maxWidth:a}):i=Xy({minWidth:n[o-1]+1,maxWidth:a}),aT()&&t.media(i,function(){t.setState({breakpoint:a})})});var r=Xy({minWidth:n.slice(-1)[0]});aT()&&this.media(r,function(){t.setState({breakpoint:null})})}},beforeUnmount:function(){this._responsiveMediaHandlers.forEach(function(t){t.mql.removeListener(t.listener)})},methods:{innerSliderRefHandler:function(t){this.innerSlider=t},media:function(t,n){var r=window.matchMedia(t),a=function(i){var l=i.matches;l&&n()};r.addListener(a),a(r),this._responsiveMediaHandlers.push({mql:r,query:t,listener:a})},slickPrev:function(){this.innerSlider.slickPrev()},slickNext:function(){this.innerSlider.slickNext()},slickGoTo:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;this.innerSlider.slickGoTo(t,n)},slickPause:function(){this.innerSlider.pause(\"paused\")},slickPlay:function(){this.innerSlider.handleAutoPlay(\"play\")}},render:function(){var t=this,n,r,a;this.breakpoint?(a=this.responsive.filter(function(y){return y.breakpoint===t.breakpoint}),r=a[0].settings===\"unslick\"?\"unslick\":P(P({},this.$props),a[0].settings)):r=P({},this.$props),r.centerMode&&(r.slidesToScroll>1,r.slidesToScroll=1),r.fade&&(r.slidesToShow>1,r.slidesToScroll>1,r.slidesToShow=1,r.slidesToScroll=1);var o=ht(this)||[];o=o.filter(function(y){return typeof y==\"string\"?!!y.trim():!!y}),r.variableWidth&&(r.rows>1||r.slidesPerRow>1)&&(console.warn(\"variableWidth is not supported in case of rows > 1 or slidesPerRow > 1\"),r.variableWidth=!1);for(var i=[],l=null,s=0;s<o.length;s+=r.rows*r.slidesPerRow){for(var c=[],d=s;d<s+r.rows*r.slidesPerRow;d+=r.slidesPerRow){for(var f=[],p=d;p<d+r.slidesPerRow&&(r.variableWidth&&((n=o[p].props)===null||n===void 0?void 0:n.style)&&(l=o[p].props.style.width),!(p>=o.length));p+=1)f.push(Ot(o[p],{key:100*s+10*d+p,tabindex:-1,style:{width:\"\".concat(100/r.slidesPerRow,\"%\"),display:\"inline-block\"}}));c.push(g(\"div\",{key:10*s+d},[f]))}r.variableWidth?i.push(g(\"div\",{key:s,style:{width:l}},[c])):i.push(g(\"div\",{key:s},[c]))}if(r===\"unslick\"){var v=\"regular slider \"+(this.className||\"\");return g(\"div\",{class:v},[i])}else i.length<=r.slidesToShow&&(r.unslick=!0);var m=P(P(P({},this.$attrs),r),{children:i,ref:this.innerSliderRefHandler});return g(yTe,le(le({},m),{},{__propsSymbol__:[]}),this.$slots)}}),CTe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},wTe={effect:u.oneOf(rt(\"scrollx\",\"fade\")),dots:u.looseBool.def(!0),vertical:u.looseBool,autoplay:u.looseBool,easing:u.string,beforeChange:u.func,afterChange:u.func,prefixCls:u.string,accessibility:u.looseBool,nextArrow:u.VNodeChild,prevArrow:u.VNodeChild,pauseOnHover:u.looseBool,adaptiveHeight:u.looseBool,arrows:u.looseBool.def(!1),autoplaySpeed:u.number,centerMode:u.looseBool,centerPadding:u.string,cssEase:u.string,dotsClass:u.string,draggable:u.looseBool.def(!1),fade:u.looseBool,focusOnSelect:u.looseBool,infinite:u.looseBool,initialSlide:u.number,lazyLoad:u.looseBool,rtl:u.looseBool,slide:u.string,slidesToShow:u.number,slidesToScroll:u.number,speed:u.number,swipe:u.looseBool,swipeToSlide:u.looseBool,touchMove:u.looseBool,touchThreshold:u.number,variableWidth:u.looseBool,useCSS:u.looseBool,slickGoTo:u.number,responsive:u.array,dotPosition:u.oneOf(rt(\"top\",\"bottom\",\"left\",\"right\")),verticalSwiping:u.looseBool.def(!1)},STe=G({name:\"ACarousel\",inheritAttrs:!1,props:wTe,setup:function(){return{configProvider:ve(\"configProvider\",St),slick:void 0,innerSlider:void 0}},beforeMount:function(){this.onWindowResized=Yn(this.onWindowResized,500,{leading:!1})},mounted:function(){rf(this,\"vertical\")&&on(!this.vertical,\"Carousel\",\"`vertical` is deprecated, please use `dotPosition` instead.\");var t=this.autoplay;t&&window.addEventListener(\"resize\",this.onWindowResized),this.innerSlider=this.slick&&this.slick.innerSlider},beforeUnmount:function(){var t=this.autoplay;t&&(window.removeEventListener(\"resize\",this.onWindowResized),this.onWindowResized.cancel())},methods:{getDotPosition:function(){return this.dotPosition?this.dotPosition:rf(this,\"vertical\")&&this.vertical?\"right\":\"bottom\"},saveSlick:function(t){this.slick=t},onWindowResized:function(){var t=this.autoplay;t&&this.slick&&this.slick.innerSlider&&this.slick.innerSlider.autoPlay&&this.slick.innerSlider.autoPlay()},next:function(){this.slick.slickNext()},prev:function(){this.slick.slickPrev()},goTo:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;this.slick.slickGoTo(t,n)}},render:function(){var t,n=P({},this.$props),r=this.$slots;n.effect===\"fade\"&&(n.fade=!0);var a=this.$attrs,o=a.class,i=a.style,l=CTe(a,[\"class\",\"style\"]),s=this.configProvider.getPrefixCls,c=s(\"carousel\",n.prefixCls),d=\"slick-dots\",f=this.getDotPosition();n.vertical=f===\"left\"||f===\"right\",n.dotsClass=Se(\"\".concat(d),\"\".concat(d,\"-\").concat(f||\"bottom\"),V({},\"\".concat(n.dotsClass),!!n.dotsClass)),c=Se((t={},V(t,o,!!o),V(t,c,!!c),V(t,\"\".concat(c,\"-vertical\"),n.vertical),t));var p=P(P(P({},n),l),{nextArrow:We(this,\"nextArrow\"),prevArrow:We(this,\"prevArrow\")});return g(\"div\",{class:c,style:i},[g(bTe,le({ref:this.saveSlick},p),r)])}}),kTe=kn(STe),FD={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(vo,function(){function n(r,a,o){o=o||{},o.childrenKeyName=o.childrenKeyName||\"children\";var i=r||[],l=[],s=0;do{var c=i.filter(function(d){return a(d,s)})[0];if(!c)break;l.push(c),i=c[o.childrenKeyName]||[],s+=1}while(i.length>0);return l}return n})})(FD);var om=FD.exports,$Te={name:\"CascaderMenus\",mixins:[nt],inheritAttrs:!1,props:{value:u.array.def([]),activeValue:u.array.def([]),options:u.array,prefixCls:u.string.def(\"rc-cascader-menus\"),expandTrigger:u.string.def(\"click\"),visible:u.looseBool.def(!1),dropdownMenuColumnStyle:u.object,defaultFieldNames:u.object,fieldNames:u.object,expandIcon:u.any,loadingIcon:u.any},data:function(){return this.menuItems={},{}},watch:{visible:function(t){var n=this;t&&this.$nextTick(function(){n.scrollActiveItemToView()})}},mounted:function(){var t=this;this.$nextTick(function(){t.scrollActiveItemToView()})},methods:{getFieldName:function(t){var n=this.$props,r=n.fieldNames,a=n.defaultFieldNames;return r[t]||a[t]},getOption:function(t,n){var r=this,a=this.prefixCls,o=this.expandTrigger,i=We(this,\"loadingIcon\"),l=We(this,\"expandIcon\"),s=function(S){r.__emit(\"select\",t,n,S)},c=function(S){r.__emit(\"itemDoubleClick\",t,n,S)},d=t[this.getFieldName(\"value\")],f={onClick:s,onDblclick:c},p=\"\".concat(a,\"-menu-item\"),v=null,m=t[this.getFieldName(\"children\")]&&t[this.getFieldName(\"children\")].length>0;(m||t.isLeaf===!1)&&(p+=\" \".concat(a,\"-menu-item-expand\"),t.loading||(v=g(\"span\",{class:\"\".concat(a,\"-menu-item-expand-icon\")},[l]))),o===\"hover\"&&(m||t.isLeaf===!1)&&(f={onMouseenter:this.delayOnSelect.bind(this,s),onMouseleave:this.delayOnSelect.bind(this),onClick:s}),this.isActiveOption(t,n)&&(p+=\" \".concat(a,\"-menu-item-active\"),f.ref=this.saveMenuItem(n)),t.disabled&&(p+=\" \".concat(a,\"-menu-item-disabled\"));var y=null;t.loading&&(p+=\" \".concat(a,\"-menu-item-loading\"),y=i||null);var b=\"\";return t.title?b=t.title:typeof t[this.getFieldName(\"label\")]==\"string\"&&(b=t[this.getFieldName(\"label\")]),g(\"li\",le(le({key:Array.isArray(d)?d.join(\"__ant__\"):d,class:p,title:b},f),{},{role:\"menuitem\",onMousedown:function(S){return S.preventDefault()}}),[t[this.getFieldName(\"label\")],v,y])},getActiveOptions:function(t){var n=this,r=t||this.activeValue,a=this.options;return om(a,function(o,i){return er(o[n.getFieldName(\"value\")],r[i])},{childrenKeyName:this.getFieldName(\"children\")})},getShowOptions:function(){var t=this,n=this.options,r=this.getActiveOptions().map(function(a){return a[t.getFieldName(\"children\")]}).filter(function(a){return!!a});return r.unshift(n),r},delayOnSelect:function(t){for(var n=this,r=arguments.length,a=new Array(r>1?r-1:0),o=1;o<r;o++)a[o-1]=arguments[o];this.delayTimer&&(clearTimeout(this.delayTimer),this.delayTimer=null),typeof t==\"function\"&&(this.delayTimer=setTimeout(function(){t(a),n.delayTimer=null},150))},scrollActiveItemToView:function(){for(var t=this.getShowOptions().length,n=0;n<t;n++){var r=this.menuItems[n];if(r){var a=Sn(r);a.parentNode.scrollTop=a.offsetTop}}},isActiveOption:function(t,n){var r=this.activeValue,a=r===void 0?[]:r;return er(a[n],t[this.getFieldName(\"value\")])},saveMenuItem:function(t){var n=this;return function(r){n.menuItems[t]=r}}},render:function(){var t=this,n=this.prefixCls,r=this.dropdownMenuColumnStyle;return g(\"div\",null,[this.getShowOptions().map(function(a,o){return g(\"ul\",{class:\"\".concat(n,\"-menu\"),key:o,style:r},[a.map(function(i){return t.getOption(i,o)})])})])}};function OTe(e,t){if(e===t)return!0;if(!e||!t)return!1;var n=e.length;if(t.length!==n)return!1;for(var r=0;r<n;r++)if(e[r]!==t[r])return!1;return!0}var PTe=OTe,TTe=PTe,xTe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},_Te={bottomLeft:{points:[\"tl\",\"bl\"],offset:[0,4],overflow:{adjustX:1,adjustY:1}},topLeft:{points:[\"bl\",\"tl\"],offset:[0,-4],overflow:{adjustX:1,adjustY:1}},bottomRight:{points:[\"tr\",\"br\"],offset:[0,4],overflow:{adjustX:1,adjustY:1}},topRight:{points:[\"br\",\"tr\"],offset:[0,-4],overflow:{adjustX:1,adjustY:1}}},ETe=G({name:\"Cascader\",mixins:[nt],inheritAttrs:!1,props:{value:u.array,defaultValue:u.array,options:u.array,popupVisible:u.looseBool,disabled:u.looseBool.def(!1),transitionName:u.string.def(\"\"),popupClassName:u.string.def(\"\"),popupStyle:u.object.def(function(){return{}}),popupPlacement:u.string.def(\"bottomLeft\"),prefixCls:u.string.def(\"rc-cascader\"),dropdownMenuColumnStyle:u.object,builtinPlacements:u.object.def(_Te),loadData:u.func,changeOnSelect:u.looseBool,expandTrigger:u.string.def(\"click\"),fieldNames:u.object.def(function(){return{label:\"label\",value:\"value\",children:\"children\"}}),expandIcon:u.any,loadingIcon:u.any,getPopupContainer:u.func},data:function(){var t=[],n=this.value,r=this.defaultValue,a=this.popupVisible;return vt(this,\"value\")?t=n||[]:vt(this,\"defaultValue\")&&(t=r||[]),this.children=void 0,this.defaultFieldNames={label:\"label\",value:\"value\",children:\"children\"},{sPopupVisible:a,sActiveValue:t,sValue:t}},watch:{value:function(t,n){if(!TTe(t,n)){var r={sValue:t||[]};vt(this,\"loadData\")||(r.sActiveValue=t||[]),this.setState(r)}},popupVisible:function(t){this.setState({sPopupVisible:t})}},methods:{getPopupDOMNode:function(){return this.trigger.getPopupDomNode()},getFieldName:function(t){var n=this.defaultFieldNames,r=this.fieldNames;return r[t]||n[t]},getFieldNames:function(){return this.fieldNames},getCurrentLevelOptions:function(){var t=this,n=this.options,r=n===void 0?[]:n,a=this.sActiveValue,o=a===void 0?[]:a,i=om(r,function(l,s){return er(l[t.getFieldName(\"value\")],o[s])},{childrenKeyName:this.getFieldName(\"children\")});return i[i.length-2]?i[i.length-2][this.getFieldName(\"children\")]:Je(r).filter(function(l){return!l.disabled})},getActiveOptions:function(t){var n=this;return om(this.options||[],function(r,a){return er(r[n.getFieldName(\"value\")],t[a])},{childrenKeyName:this.getFieldName(\"children\")})},setPopupVisible:function(t){vt(this,\"popupVisible\")||this.setState({sPopupVisible:t}),t&&!this.sPopupVisible&&this.setState({sActiveValue:this.sValue}),this.__emit(\"popupVisibleChange\",t)},handleChange:function(t,n,r){var a=this;if(r.type!==\"keydown\"||r.keyCode===ze.ENTER){var o=t.map(function(i){return i[a.getFieldName(\"value\")]});this.__emit(\"change\",o,t),this.setPopupVisible(n.visible)}},handlePopupVisibleChange:function(t){this.setPopupVisible(t)},handleMenuSelect:function(t,n,r){var a=this.trigger.getRootDomNode();a&&a.focus&&a.focus();var o=this.changeOnSelect,i=this.loadData,l=this.expandTrigger;if(!(!t||t.disabled)){var s=this.sActiveValue;s=s.slice(0,n+1),s[n]=t[this.getFieldName(\"value\")];var c=this.getActiveOptions(s);if(t.isLeaf===!1&&!t[this.getFieldName(\"children\")]&&i){o&&this.handleChange(c,{visible:!0},r),this.setState({sActiveValue:s}),i(c);return}var d={};!t[this.getFieldName(\"children\")]||!t[this.getFieldName(\"children\")].length?(this.handleChange(c,{visible:!1},r),d.sValue=s):o&&(r.type===\"click\"||r.type===\"keydown\")&&(l===\"hover\"?this.handleChange(c,{visible:!1},r):this.handleChange(c,{visible:!0},r),d.sValue=s),d.sActiveValue=s,(vt(this,\"value\")||r.type===\"keydown\"&&r.keyCode!==ze.ENTER)&&delete d.sValue,this.setState(d)}},handleItemDoubleClick:function(){var t=this.$props.changeOnSelect;t&&this.setPopupVisible(!1)},handleKeyDown:function(t){var n=this,r=this.children;if(r){var a=nf(r).onKeydown;if(a){a(t);return}}var o=Je(this.sActiveValue),i=o.length-1<0?0:o.length-1,l=this.getCurrentLevelOptions(),s=l.map(function(p){return p[n.getFieldName(\"value\")]}).findIndex(function(p){return er(o[i],p)});if(!(t.keyCode!==ze.DOWN&&t.keyCode!==ze.UP&&t.keyCode!==ze.LEFT&&t.keyCode!==ze.RIGHT&&t.keyCode!==ze.ENTER&&t.keyCode!==ze.SPACE&&t.keyCode!==ze.BACKSPACE&&t.keyCode!==ze.ESC&&t.keyCode!==ze.TAB)){if(!this.sPopupVisible&&t.keyCode!==ze.BACKSPACE&&t.keyCode!==ze.LEFT&&t.keyCode!==ze.RIGHT&&t.keyCode!==ze.ESC&&t.keyCode!==ze.TAB){this.setPopupVisible(!0);return}if(t.keyCode===ze.DOWN||t.keyCode===ze.UP){t.preventDefault();var c=s;c!==-1?t.keyCode===ze.DOWN?(c+=1,c=c>=l.length?0:c):(c-=1,c=c<0?l.length-1:c):c=0,o[i]=l[c][this.getFieldName(\"value\")]}else if(t.keyCode===ze.LEFT||t.keyCode===ze.BACKSPACE)t.preventDefault(),o.splice(o.length-1,1);else if(t.keyCode===ze.RIGHT)t.preventDefault(),l[s]&&l[s][this.getFieldName(\"children\")]&&o.push(l[s][this.getFieldName(\"children\")][0][this.getFieldName(\"value\")]);else if(t.keyCode===ze.ESC||t.keyCode===ze.TAB){this.setPopupVisible(!1);return}(!o||o.length===0)&&this.setPopupVisible(!1);var d=this.getActiveOptions(o),f=d[d.length-1];this.handleMenuSelect(f,d.length-1,t),this.__emit(\"keydown\",t)}},saveTrigger:function(t){this.trigger=t}},render:function(){var t=this.$props,n=this.sActiveValue,r=this.handleMenuSelect,a=this.sPopupVisible,o=this.handlePopupVisibleChange,i=this.handleKeyDown,l=t.prefixCls,s=t.transitionName,c=t.popupClassName,d=t.options,f=d===void 0?[]:d,p=t.disabled,v=t.builtinPlacements,m=t.popupPlacement,y=xTe(t,[\"prefixCls\",\"transitionName\",\"popupClassName\",\"options\",\"disabled\",\"builtinPlacements\",\"popupPlacement\"]),b=g(\"div\",null,null),C=\"\";if(f&&f.length>0){var S=We(this,\"loadingIcon\"),w=We(this,\"expandIcon\")||\">\",k=P(P(P({},t),this.$attrs),{fieldNames:this.getFieldNames(),defaultFieldNames:this.defaultFieldNames,activeValue:n,visible:a,loadingIcon:S,expandIcon:w,onSelect:r,onItemDoubleClick:this.handleItemDoubleClick});b=g($Te,k,null)}else C=\" \".concat(l,\"-menus-empty\");var $=P(P(P({},y),this.$attrs),{disabled:p,popupPlacement:m,builtinPlacements:v,popupTransitionName:s,action:p?[]:[\"click\"],popupVisible:p?!1:a,prefixCls:\"\".concat(l,\"-menus\"),popupClassName:c+C,popup:b,onPopupVisibleChange:o,ref:this.saveTrigger}),O=ht(this);return this.children=O,g(Ii,$,{default:function(){return[O&&Ot(O[0],{onKeydown:i,tabindex:p?void 0:0})]}})}}),MTe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M758.2 839.1C851.8 765.9 912 651.9 912 523.9 912 303 733.5 124.3 512.6 124 291.4 123.7 112 302.8 112 523.9c0 125.2 57.5 236.9 147.6 310.2 3.5 2.8 8.6 2.2 11.4-1.3l39.4-50.5c2.7-3.4 2.1-8.3-1.2-11.1-8.1-6.6-15.9-13.7-23.4-21.2a318.64 318.64 0 01-68.6-101.7C200.4 609 192 567.1 192 523.9s8.4-85.1 25.1-124.5c16.1-38.1 39.2-72.3 68.6-101.7 29.4-29.4 63.6-52.5 101.7-68.6C426.9 212.4 468.8 204 512 204s85.1 8.4 124.5 25.1c38.1 16.1 72.3 39.2 101.7 68.6 29.4 29.4 52.5 63.6 68.6 101.7 16.7 39.4 25.1 81.3 25.1 124.5s-8.4 85.1-25.1 124.5a318.64 318.64 0 01-68.6 101.7c-9.3 9.3-19.1 18-29.3 26L668.2 724a8 8 0 00-14.1 3l-39.6 162.2c-1.2 5 2.6 9.9 7.7 9.9l167 .8c6.7 0 10.5-7.7 6.3-12.9l-37.3-47.9z\"}}]},name:\"redo\",theme:\"outlined\"},ITe=MTe;function oT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){NTe(e,a,n[a])})}return e}function NTe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var rS=function(t,n){var r=oT({},t,n.attrs);return g(Et,oT({},r,{icon:ITe}),null)};rS.displayName=\"RedoOutlined\";rS.inheritAttrs=!1;var ATe=rS,iT=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function lT(){}var DTe={options:{type:Array,default:[]},defaultValue:u.array,value:u.array,displayRender:u.func,transitionName:u.string.def(\"slide-up\"),popupStyle:u.object.def(function(){return{}}),popupClassName:u.string,popupPlacement:u.oneOf(rt(\"bottomLeft\",\"bottomRight\",\"topLeft\",\"topRight\")).def(\"bottomLeft\"),placeholder:u.string.def(\"Please select\"),size:u.oneOf(rt(\"large\",\"default\",\"small\")),disabled:u.looseBool.def(!1),allowClear:u.looseBool.def(!0),showSearch:{type:[Boolean,Object],default:void 0},notFoundContent:u.VNodeChild,loadData:u.func,expandTrigger:u.oneOf(rt(\"click\",\"hover\")),changeOnSelect:u.looseBool,prefixCls:u.string,inputPrefixCls:u.string,getPopupContainer:u.func,popupVisible:u.looseBool,fieldNames:{type:Object},autofocus:u.looseBool,suffixIcon:u.VNodeChild,showSearchRender:u.any,onChange:u.func,onPopupVisibleChange:u.func,onFocus:u.func,onBlur:u.func,onSearch:u.func,\"onUpdate:value\":u.func},RTe=50;function LTe(e,t,n){return t.some(function(r){return r[n.label].indexOf(e)>-1})}function FTe(e,t,n,r){function a(o){return o[r.label].indexOf(n)>-1}return e.findIndex(a)-t.findIndex(a)}function Yp(e){var t=e.fieldNames||{},n={children:t.children||\"children\",label:t.label||\"label\",value:t.value||\"value\"};return n}function b1(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[],r=Yp(t),a=[],o=r.children;return e.forEach(function(i){var l=n.concat(i);(t.changeOnSelect||!i[o]||!i[o].length)&&a.push(l),i[o]&&(a=a.concat(b1(i[o],t,l)))}),a}var BTe=function(t){var n=t.labels;return n.join(\" / \")},VTe=G({name:\"ACascader\",mixins:[nt],inheritAttrs:!1,props:DTe,setup:function(){return{configProvider:ve(\"configProvider\",St),localeData:ve(\"localeData\",{}),cachedOptions:[],popupRef:void 0,input:void 0}},data:function(){var t=this.$props,n=t.value,r=t.defaultValue,a=t.popupVisible,o=t.showSearch,i=t.options;return{sValue:n||r||[],inputValue:\"\",inputFocused:!1,sPopupVisible:a,flattenOptions:o?b1(i,this.$props):void 0}},watch:{value:function(t){this.setState({sValue:t||[]})},popupVisible:function(t){this.setState({sPopupVisible:t})},options:function(t){this.showSearch&&this.setState({flattenOptions:b1(t,this.$props)})}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},methods:{savePopupRef:function(t){this.popupRef=t},highlightKeyword:function(t,n,r){return t.split(n).map(function(a,o){return o===0?a:[g(\"span\",{class:\"\".concat(r,\"-menu-item-keyword\")},[n]),a]})},defaultRenderFilteredOption:function(t){var n=this,r=t.inputValue,a=t.path,o=t.prefixCls,i=t.names;return a.map(function(l,s){var c=l[i.label],d=c.indexOf(r)>-1?n.highlightKeyword(c,r,o):c;return s===0?d:[\" / \",d]})},saveInput:function(t){this.input=t},handleChange:function(t,n){if(this.setState({inputValue:\"\"}),n[0].__IS_FILTERED_OPTION){var r=t[0],a=n[0].path;this.setValue(r,a);return}this.setValue(t,n)},handlePopupVisibleChange:function(t){vt(this,\"popupVisible\")||this.setState(function(n){return{sPopupVisible:t,inputFocused:t,inputValue:t?n.inputValue:\"\"}}),this.$emit(\"popupVisibleChange\",t)},handleInputFocus:function(t){this.$emit(\"focus\",t)},handleInputBlur:function(t){this.setState({inputFocused:!1}),this.$emit(\"blur\",t)},handleInputClick:function(t){var n=this.inputFocused,r=this.sPopupVisible;(n||r)&&(t.stopPropagation(),t.nativeEvent&&t.nativeEvent.stopImmediatePropagation&&t.nativeEvent.stopImmediatePropagation())},handleKeyDown:function(t){(t.keyCode===ze.BACKSPACE||t.keyCode===ze.SPACE)&&t.stopPropagation()},handleInputChange:function(t){var n=t.target.value;this.setState({inputValue:n}),this.$emit(\"search\",n)},setValue:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[];vt(this,\"value\")||this.setState({sValue:t}),this.$emit(\"update:value\",t),this.$emit(\"change\",t,n)},getLabel:function(){var t=this.options,n=Yp(this.$props),r=We(this,\"displayRender\",{},!1)||BTe,a=this.sValue,o=Array.isArray(a[0])?a[0]:a,i=om(t,function(s,c){return s[n.value]===o[c]},{childrenKeyName:n.children}),l=i.map(function(s){return s[n.label]});return r({labels:l,selectedOptions:i})},clearSelection:function(t){t.preventDefault(),t.stopPropagation(),this.inputValue?this.setState({inputValue:\"\"}):(this.setValue([]),this.handlePopupVisibleChange(!1))},generateFilteredOptions:function(t,n){var r,a=this.showSearch,o=this.notFoundContent,i=Yp(this.$props),l=a.filter,s=l===void 0?LTe:l,c=a.sort,d=c===void 0?FTe:c,f=a.limit,p=f===void 0?RTe:f,v=a.render||We(this,\"showSearchRender\")||this.defaultRenderFilteredOption,m=this.$data,y=m.flattenOptions,b=y===void 0?[]:y,C=m.inputValue,S;if(p>0){S=[];var w=0;b.some(function(k){var $=s(C,k,i);return $&&(S.push(k),w+=1),w>=p})}else on(typeof p!=\"number\",\"Cascader\",\"'limit' of showSearch in Cascader should be positive number or false.\"),S=b.filter(function(k){return s(C,k,i)});return S.sort(function(k,$){return d(k,$,C,i)}),S.length>0?S.map(function(k){var $;return $={__IS_FILTERED_OPTION:!0,path:k},V($,i.label,v({inputValue:C,path:k,prefixCls:t,names:i})),V($,i.value,k.map(function(O){return O[i.value]})),V($,\"disabled\",k.some(function(O){return!!O.disabled})),$}):[(r={},V(r,i.label,o||n(\"Cascader\")),V(r,i.value,\"ANT_CASCADER_NOT_FOUND\"),V(r,\"disabled\",!0),r)]},focus:function(){this.input&&this.input.focus()},blur:function(){this.input&&this.input.blur()}},render:function(){var t,n,r,a=this.sPopupVisible,o=this.inputValue,i=this.configProvider,l=this.localeData,s=this.$data,c=s.sValue,d=s.inputFocused,f=Qe(this),p=We(this,\"suffixIcon\");p=Array.isArray(p)?p[0]:p;var v=i.getPopupContainer,m=f,y=m.prefixCls,b=m.inputPrefixCls,C=m.placeholder,S=C===void 0?l.placeholder:C,w=m.size,k=m.disabled,$=m.allowClear,O=m.showSearch,T=O===void 0?!1:O,_=m.notFoundContent,I=iT(m,[\"prefixCls\",\"inputPrefixCls\",\"placeholder\",\"size\",\"disabled\",\"allowClear\",\"showSearch\",\"notFoundContent\"]),L=If(this.$attrs),j=L.onEvents,F=L.extraAttrs,N=F.class,D=F.style,z=iT(F,[\"class\",\"style\"]),B=this.configProvider.getPrefixCls,M=this.configProvider.renderEmpty,E=B(\"cascader\",y),K=B(\"input\",b),W=Se((t={},V(t,\"\".concat(K,\"-lg\"),w===\"large\"),V(t,\"\".concat(K,\"-sm\"),w===\"small\"),t)),Y=$&&!k&&c.length>0||o?g(Yr,{class:\"\".concat(E,\"-picker-clear\"),onClick:this.clearSelection,key:\"clear-icon\"},null):null,q=Se((n={},V(n,\"\".concat(E,\"-picker-arrow\"),!0),V(n,\"\".concat(E,\"-picker-arrow-expand\"),a),n)),J=Se(N,\"\".concat(E,\"-picker\"),(r={},V(r,\"\".concat(E,\"-picker-with-value\"),o),V(r,\"\".concat(E,\"-picker-disabled\"),k),V(r,\"\".concat(E,\"-picker-\").concat(w),!!w),V(r,\"\".concat(E,\"-picker-show-search\"),!!T),V(r,\"\".concat(E,\"-picker-focused\"),d),r)),ne=bn(I,[\"popupStyle\",\"options\",\"popupPlacement\",\"transitionName\",\"displayRender\",\"changeOnSelect\",\"expandTrigger\",\"popupVisible\",\"getPopupContainer\",\"loadData\",\"popupClassName\",\"filterOption\",\"renderFilteredOption\",\"sortFilteredOption\",\"notFoundContent\",\"defaultValue\",\"fieldNames\",\"onChange\",\"onPopupVisibleChange\",\"onFocus\",\"onBlur\",\"onSearch\",\"onUpdate:value\"]),oe=f.options,Q=Yp(this.$props);if(oe&&oe.length>0)o&&(oe=this.generateFilteredOptions(E,M));else{var ae;oe=[(ae={},V(ae,Q.label,_||M(\"Cascader\")),V(ae,Q.value,\"ANT_CASCADER_NOT_FOUND\"),V(ae,\"disabled\",!0),ae)]}a?this.cachedOptions=oe:oe=this.cachedOptions;var de={},be=(oe||[]).length===1&&oe[0].value===\"ANT_CASCADER_NOT_FOUND\";be&&(de.height=\"auto\");var Ee=T.matchInputWidth!==!1;Ee&&(o||be)&&this.input&&(de.width=Sn(this.input.input).offsetWidth+\"px\");var Pe=P(P(P({},z),ne),{prefixCls:K,placeholder:c&&c.length>0?void 0:S,value:o,disabled:k,readonly:!T,autocomplete:\"off\",class:\"\".concat(E,\"-input \").concat(W),onFocus:this.handleInputFocus,onClick:T?this.handleInputClick:lT,onBlur:T?this.handleInputBlur:f.onBlur,onKeydown:this.handleKeyDown,onChange:T?this.handleInputChange:lT}),Be=ht(this),te=p&&(zn(p)?Ot(p,{class:\"\".concat(E,\"-picker-arrow\")}):g(\"span\",{class:\"\".concat(E,\"-picker-arrow\")},[p]))||g(Rs,{class:q},null),ie=Be.length?Be:g(\"span\",{class:J,style:D},[g(\"span\",{class:\"\".concat(E,\"-picker-label\")},[this.getLabel()]),g(Jn,le(le({},Pe),{},{ref:this.saveInput}),null),Y,te]),ge=g(wi,null,null),ke=g(\"span\",{class:\"\".concat(E,\"-menu-item-loading-icon\")},[g(ATe,{spin:!0},null)]),xe=f.getPopupContainer||v,Ie=P(P(P(P({},f),{getPopupContainer:xe,options:oe,prefixCls:E,value:c,popupVisible:a,dropdownMenuColumnStyle:de,expandIcon:ge,loadingIcon:ke}),j),{onPopupVisibleChange:this.handlePopupVisibleChange,onChange:this.handleChange});return g(ETe,Ie,{default:function(){return[ie]}})}}),zTe=kn(VTe),sT=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function uT(){}var ro=G({name:\"ACheckbox\",inheritAttrs:!1,__ANT_CHECKBOX:!0,props:{prefixCls:u.string,defaultChecked:u.looseBool,checked:u.looseBool,disabled:u.looseBool,isGroup:u.looseBool,value:u.any,name:u.string,id:u.string,indeterminate:u.looseBool,type:u.string.def(\"checkbox\"),autofocus:u.looseBool,onChange:u.func,\"onUpdate:checked\":u.func},emits:[\"change\",\"update:checked\"],setup:function(){return{configProvider:ve(\"configProvider\",St),checkboxGroupContext:ve(\"checkboxGroupContext\",void 0)}},watch:{value:function(t,n){var r=this;Ne(function(){var a=r.checkboxGroupContext,o=a===void 0?{}:a;o.registerValue&&o.cancelValue&&(o.cancelValue(n),o.registerValue(t))})}},mounted:function(){var t=this.value,n=this.checkboxGroupContext,r=n===void 0?{}:n;r.registerValue&&r.registerValue(t),on(rf(this,\"checked\")||this.checkboxGroupContext||!rf(this,\"value\"),\"Checkbox\",\"`value` is not validate prop, do you mean `checked`?\")},beforeUnmount:function(){var t=this.value,n=this.checkboxGroupContext,r=n===void 0?{}:n;r.cancelValue&&r.cancelValue(t)},methods:{handleChange:function(t){var n=t.target.checked;this.$emit(\"update:checked\",n),this.$emit(\"change\",t)},focus:function(){this.$refs.vcCheckbox.focus()},blur:function(){this.$refs.vcCheckbox.blur()}},render:function(){var t=this,n,r=Qe(this),a=this.checkboxGroupContext,o=this.$attrs,i=ht(this),l=r.indeterminate,s=r.prefixCls,c=sT(r,[\"indeterminate\",\"prefixCls\"]),d=this.configProvider.getPrefixCls,f=d(\"checkbox\",s),p=o.onMouseenter,v=p===void 0?uT:p,m=o.onMouseleave,y=m===void 0?uT:m;o.onInput;var b=o.class,C=o.style,S=sT(o,[\"onMouseenter\",\"onMouseleave\",\"onInput\",\"class\",\"style\"]),w=P(P(P({},c),{prefixCls:f}),S);a?(w.onChange=function(){for(var O=arguments.length,T=new Array(O),_=0;_<O;_++)T[_]=arguments[_];t.$emit.apply(t,[\"change\"].concat(T)),a.toggleOption({label:i,value:r.value})},w.name=a.name,w.checked=a.sValue.indexOf(r.value)!==-1,w.disabled=r.disabled||a.disabled,w.indeterminate=l):w.onChange=this.handleChange;var k=Se((n={},V(n,\"\".concat(f,\"-wrapper\"),!0),V(n,\"\".concat(f,\"-wrapper-checked\"),w.checked),V(n,\"\".concat(f,\"-wrapper-disabled\"),w.disabled),n),b),$=Se(V({},\"\".concat(f,\"-indeterminate\"),l));return g(\"label\",{class:k,style:C,onMouseenter:v,onMouseleave:y},[g(cD,le(le({},w),{},{class:$,ref:\"vcCheckbox\"}),null),i.length?g(\"span\",null,[i]):null])}});function HTe(){}var im=G({name:\"ACheckboxGroup\",props:{name:u.string,prefixCls:u.string,defaultValue:{type:Array},value:{type:Array},options:{type:Array},disabled:u.looseBool,onChange:u.func},emits:[\"change\",\"update:value\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){var t=this.value,n=this.defaultValue;return{sValue:t||n||[],registeredValues:[]}},watch:{value:function(t){this.sValue=t||[]}},created:function(){ot(\"checkboxGroupContext\",this)},methods:{getOptions:function(){var t=this.options,n=t===void 0?[]:t,r=this.$slots;return n.map(function(a){if(typeof a==\"string\")return{label:a,value:a};var o=a.label;return o===void 0&&r.label&&(o=r.label(a)),P(P({},a),{label:o})})},cancelValue:function(t){this.registeredValues=this.registeredValues.filter(function(n){return n!==t})},registerValue:function(t){this.registeredValues=[].concat(Je(this.registeredValues),[t])},toggleOption:function(t){var n=this.registeredValues,r=this.sValue.indexOf(t.value),a=Je(this.sValue);r===-1?a.push(t.value):a.splice(r,1),rf(this,\"value\")||(this.sValue=a);var o=this.getOptions(),i=a.filter(function(l){return n.indexOf(l)!==-1}).sort(function(l,s){var c=o.findIndex(function(f){return f.value===l}),d=o.findIndex(function(f){return f.value===s});return c-d});this.$emit(\"update:value\",i),this.$emit(\"change\",i)}},render:function(){var t=this.$props,n=this.$data,r=t.prefixCls,a=t.options,o=this.configProvider.getPrefixCls,i=o(\"checkbox\",r),l=ht(this),s=\"\".concat(i,\"-group\");return a&&a.length>0&&(l=this.getOptions().map(function(c){return g(ro,{prefixCls:i,key:c.value.toString(),disabled:\"disabled\"in c?c.disabled:t.disabled,indeterminate:c.indeterminate,value:c.value,checked:n.sValue.indexOf(c.value)!==-1,onChange:c.onChange||HTe,class:\"\".concat(s,\"-item\")},{default:function(){return[c.label]}})})),g(\"div\",{class:s},[l])}});ro.Group=im;ro.install=function(e){return e.component(ro.name,ro),e.component(im.name,im),e};var jTe={actions:u.array,author:u.VNodeChild,avatar:u.VNodeChild,content:u.VNodeChild,prefixCls:u.string,datetime:u.VNodeChild},KTe=G({name:\"AComment\",props:jTe,slots:[\"actions\",\"author\",\"avatar\",\"content\",\"datetime\"],setup:function(t,n){var r=n.slots,a=Wt(\"comment\",t),o=a.prefixCls,i=a.direction,l=function(d,f){return g(\"div\",{class:\"\".concat(d,\"-nested\")},[f])},s=function(d){if(!d||!d.length)return null;var f=d.map(function(p,v){return g(\"li\",{key:\"action-\".concat(v)},[p])});return f};return function(){var c,d,f,p,v,m,y,b,C,S,w,k=o.value,$=(c=t.actions)!==null&&c!==void 0?c:(d=r.actions)===null||d===void 0?void 0:d.call(r),O=(f=t.author)!==null&&f!==void 0?f:(p=r.author)===null||p===void 0?void 0:p.call(r),T=(v=t.avatar)!==null&&v!==void 0?v:(m=r.avatar)===null||m===void 0?void 0:m.call(r),_=(y=t.content)!==null&&y!==void 0?y:(b=r.content)===null||b===void 0?void 0:b.call(r),I=(C=t.datetime)!==null&&C!==void 0?C:(S=r.datetime)===null||S===void 0?void 0:S.call(r),L=g(\"div\",{class:\"\".concat(k,\"-avatar\")},[typeof T==\"string\"?g(\"img\",{src:T,alt:\"comment-avatar\"},null):T]),j=$?g(\"ul\",{class:\"\".concat(k,\"-actions\")},[s(Array.isArray($)?$:[$])]):null,F=g(\"div\",{class:\"\".concat(k,\"-content-author\")},[O&&g(\"span\",{class:\"\".concat(k,\"-content-author-name\")},[O]),I&&g(\"span\",{class:\"\".concat(k,\"-content-author-time\")},[I])]),N=g(\"div\",{class:\"\".concat(k,\"-content\")},[F,g(\"div\",{class:\"\".concat(k,\"-content-detail\")},[_]),j]),D=g(\"div\",{class:\"\".concat(k,\"-inner\")},[L,N]),z=Un((w=r.default)===null||w===void 0?void 0:w.call(r));return g(\"div\",{class:[k,V({},\"\".concat(k,\"-rtl\"),i.value===\"rtl\")]},[D,z&&z.length?l(k,z):null])}}}),WTe=kn(KTe);function cT(e){this.changeYear(e)}function dT(){}var UTe={name:\"MonthPanel\",inheritAttrs:!1,mixins:[nt],props:{value:u.any,defaultValue:u.any,cellRender:u.any,contentRender:u.any,locale:u.any,rootPrefixCls:u.string,disabledDate:u.func,renderFooter:u.func,changeYear:u.func.def(dT)},data:function(){var t=this.value,n=this.defaultValue;return this.nextYear=cT.bind(this,1),this.previousYear=cT.bind(this,-1),{sValue:t||n}},watch:{value:function(t){this.setState({sValue:t})}},methods:{setAndSelectValue:function(t){this.setValue(t),this.__emit(\"select\",t)},setValue:function(t){vt(this,\"value\")&&this.setState({sValue:t})}},render:function(){var t=this.sValue,n=this.cellRender,r=this.contentRender,a=this.locale,o=this.rootPrefixCls,i=this.disabledDate,l=this.renderFooter,s=t.year(),c=\"\".concat(o,\"-month-panel\"),d=l&&l(\"month\");return g(\"div\",{class:c},[g(\"div\",null,[g(\"div\",{class:\"\".concat(c,\"-header\")},[g(\"a\",{class:\"\".concat(c,\"-prev-year-btn\"),role:\"button\",onClick:this.previousYear,title:a.previousYear},null),g(\"a\",{class:\"\".concat(c,\"-year-select\"),role:\"button\",onClick:this.$attrs.onYearPanelShow||dT,title:a.yearSelect},[g(\"span\",{class:\"\".concat(c,\"-year-select-content\")},[s]),g(\"span\",{class:\"\".concat(c,\"-year-select-arrow\")},[yt(\"x\")])]),g(\"a\",{class:\"\".concat(c,\"-next-year-btn\"),role:\"button\",onClick:this.nextYear,title:a.nextYear},null)]),g(\"div\",{class:\"\".concat(c,\"-body\")},[g(uD,{disabledDate:i,onSelect:this.setAndSelectValue,locale:a,value:t,cellRender:n,contentRender:r,prefixCls:c},null)]),d&&g(\"div\",{class:\"\".concat(c,\"-footer\")},[d])])])}},YTe=UTe,qTe=4,GTe=3;function fT(){}function hT(e){var t=this.sValue.clone();t.add(e,\"year\"),this.setState({sValue:t})}function XTe(e){var t=this.sValue.clone();t.year(e),t.month(this.sValue.month()),this.sValue=t,this.__emit(\"select\",t)}var ZTe={name:\"YearPanel\",mixins:[nt],inheritAttrs:!1,props:{rootPrefixCls:u.string,value:u.object,defaultValue:u.object,locale:u.object,renderFooter:u.func},data:function(){return this.nextDecade=hT.bind(this,10),this.previousDecade=hT.bind(this,-10),{sValue:this.value||this.defaultValue}},watch:{value:function(t){this.sValue=t}},methods:{years:function(){for(var t=this.sValue,n=t.year(),r=parseInt(n/10,10)*10,a=r-1,o=[],i=0,l=0;l<qTe;l++){o[l]=[];for(var s=0;s<GTe;s++){var c=a+i,d=String(c);o[l][s]={content:d,year:c,title:d},i++}}return o}},render:function(){var t=this,n=this.sValue,r=this.locale,a=this.renderFooter,o=this.$attrs.onDecadePanelShow||fT,i=this.years(),l=n.year(),s=parseInt(l/10,10)*10,c=s+9,d=\"\".concat(this.rootPrefixCls,\"-year-panel\"),f=i.map(function(v,m){var y=v.map(function(b){var C,S=(C={},V(C,\"\".concat(d,\"-cell\"),1),V(C,\"\".concat(d,\"-selected-cell\"),b.year===l),V(C,\"\".concat(d,\"-last-decade-cell\"),b.year<s),V(C,\"\".concat(d,\"-next-decade-cell\"),b.year>c),C),w=fT;return b.year<s?w=t.previousDecade:b.year>c?w=t.nextDecade:w=XTe.bind(t,b.year),g(\"td\",{role:\"gridcell\",title:b.title,key:b.content,onClick:w,class:S},[g(\"a\",{class:\"\".concat(d,\"-year\")},[b.content])])});return g(\"tr\",{key:m,role:\"row\"},[y])}),p=a&&a(\"year\");return g(\"div\",{class:d},[g(\"div\",null,[g(\"div\",{class:\"\".concat(d,\"-header\")},[g(\"a\",{class:\"\".concat(d,\"-prev-decade-btn\"),role:\"button\",onClick:this.previousDecade,title:r.previousDecade},null),g(\"a\",{class:\"\".concat(d,\"-decade-select\"),role:\"button\",onClick:o,title:r.decadeSelect},[g(\"span\",{class:\"\".concat(d,\"-decade-select-content\")},[s,yt(\"-\"),c]),g(\"span\",{class:\"\".concat(d,\"-decade-select-arrow\")},[yt(\"x\")])]),g(\"a\",{class:\"\".concat(d,\"-next-decade-btn\"),role:\"button\",onClick:this.nextDecade,title:r.nextDecade},null)]),g(\"div\",{class:\"\".concat(d,\"-body\")},[g(\"table\",{class:\"\".concat(d,\"-table\"),cellspacing:\"0\",role:\"grid\"},[g(\"tbody\",{class:\"\".concat(d,\"-tbody\")},[f])])]),p&&g(\"div\",{class:\"\".concat(d,\"-footer\")},[p])])])}},JTe=4,QTe=3;function exe(){}function pT(e){var t=this.sValue.clone();t.add(e,\"years\"),this.setState({sValue:t})}function txe(e,t){var n=this.sValue.clone();n.year(e),n.month(this.sValue.month()),this.__emit(\"select\",n),t.preventDefault()}var nxe={name:\"DecadePanel\",mixins:[nt],inheritAttrs:!1,props:{locale:u.object,value:u.object,defaultValue:u.object,rootPrefixCls:u.string,renderFooter:u.func},data:function(){return this.nextCentury=pT.bind(this,100),this.previousCentury=pT.bind(this,-100),{sValue:this.value||this.defaultValue}},watch:{value:function(t){this.sValue=t}},render:function(){for(var t=this,n=this.sValue,r=this.$props,a=r.locale,o=r.renderFooter,i=n.year(),l=parseInt(i/100,10)*100,s=l-10,c=l+99,d=[],f=0,p=\"\".concat(this.rootPrefixCls,\"-decade-panel\"),v=0;v<JTe;v++){d[v]=[];for(var m=0;m<QTe;m++){var y=s+f*10,b=s+f*10+9;d[v][m]={startDecade:y,endDecade:b},f++}}var C=o&&o(\"decade\"),S=d.map(function(w,k){var $=w.map(function(O){var T,_=O.startDecade,I=O.endDecade,L=_<l,j=I>c,F=(T={},V(T,\"\".concat(p,\"-cell\"),1),V(T,\"\".concat(p,\"-selected-cell\"),_<=i&&i<=I),V(T,\"\".concat(p,\"-last-century-cell\"),L),V(T,\"\".concat(p,\"-next-century-cell\"),j),T),N=\"\".concat(_,\"-\").concat(I),D=exe;return L?D=t.previousCentury:j?D=t.nextCentury:D=txe.bind(t,_),g(\"td\",{key:_,onClick:D,role:\"gridcell\",class:F},[g(\"a\",{class:\"\".concat(p,\"-decade\")},[N])])});return g(\"tr\",{key:k,role:\"row\"},[$])});return g(\"div\",{class:p},[g(\"div\",{class:\"\".concat(p,\"-header\")},[g(\"a\",{class:\"\".concat(p,\"-prev-century-btn\"),role:\"button\",onClick:this.previousCentury,title:a.previousCentury},null),g(\"div\",{class:\"\".concat(p,\"-century\")},[l,yt(\"-\"),c]),g(\"a\",{class:\"\".concat(p,\"-next-century-btn\"),role:\"button\",onClick:this.nextCentury,title:a.nextCentury},null)]),g(\"div\",{class:\"\".concat(p,\"-body\")},[g(\"table\",{class:\"\".concat(p,\"-table\"),cellspacing:\"0\",role:\"grid\"},[g(\"tbody\",{class:\"\".concat(p,\"-tbody\")},[S])])]),C&&g(\"div\",{class:\"\".concat(p,\"-footer\")},[C])])}};function vT(){}function mT(e){var t=this.value.clone();t.add(e,\"months\"),this.__emit(\"valueChange\",t)}function gT(e){var t=this.value.clone();t.add(e,\"years\"),this.__emit(\"valueChange\",t)}function Nh(e,t){return e?t:null}var rxe={name:\"CalendarHeader\",inheritAttrs:!1,mixins:[nt],props:{prefixCls:u.string,value:u.object,showTimePicker:u.looseBool,locale:u.object,enablePrev:u.any.def(1),enableNext:u.any.def(1),disabledMonth:u.func,mode:u.any,monthCellRender:u.func,monthCellContentRender:u.func,renderFooter:u.func},data:function(){return this.nextMonth=mT.bind(this,1),this.previousMonth=mT.bind(this,-1),this.nextYear=gT.bind(this,1),this.previousYear=gT.bind(this,-1),{yearPanelReferer:null}},methods:{onMonthSelect:function(t){this.__emit(\"panelChange\",t,\"date\"),this.$attrs.onMonthSelect?this.__emit(\"monthSelect\",t):this.__emit(\"valueChange\",t)},onYearSelect:function(t){var n=this.yearPanelReferer;this.setState({yearPanelReferer:null}),this.__emit(\"panelChange\",t,n),this.__emit(\"valueChange\",t)},onDecadeSelect:function(t){this.__emit(\"panelChange\",t,\"year\"),this.__emit(\"valueChange\",t)},changeYear:function(t){t>0?this.nextYear():this.previousYear()},monthYearElement:function(t){var n=this,r=this.$props,a=r.prefixCls,o=r.locale,i=r.value,l=i.localeData(),s=o.monthBeforeYear,c=\"\".concat(a,\"-\").concat(s?\"my-select\":\"ym-select\"),d=t?\" \".concat(a,\"-time-status\"):\"\",f=g(\"a\",{class:\"\".concat(a,\"-year-select\").concat(d),role:\"button\",onClick:t?vT:function(){return n.showYearPanel(\"date\")},title:t?null:o.yearSelect},[i.format(o.yearFormat)]),p=g(\"a\",{class:\"\".concat(a,\"-month-select\").concat(d),role:\"button\",onClick:t?vT:this.showMonthPanel,title:t?null:o.monthSelect},[o.monthFormat?i.format(o.monthFormat):l.monthsShort(i)]),v;t&&(v=g(\"a\",{class:\"\".concat(a,\"-day-select\").concat(d),role:\"button\"},[i.format(o.dayFormat)]));var m=[];return s?m=[p,v,f]:m=[f,p,v],g(\"span\",{class:c},[m])},showMonthPanel:function(){this.__emit(\"panelChange\",null,\"month\")},showYearPanel:function(t){this.setState({yearPanelReferer:t}),this.__emit(\"panelChange\",null,\"year\")},showDecadePanel:function(){this.__emit(\"panelChange\",null,\"decade\")}},render:function(){var t=this,n=Qe(this),r=n.prefixCls,a=n.locale,o=n.mode,i=n.value,l=n.showTimePicker,s=n.enableNext,c=n.enablePrev,d=n.disabledMonth,f=n.renderFooter,p=null;return o===\"month\"&&(p=g(YTe,{locale:a,value:i,rootPrefixCls:r,onSelect:this.onMonthSelect,onYearPanelShow:function(){return t.showYearPanel(\"month\")},disabledDate:d,cellRender:n.monthCellRender,contentRender:n.monthCellContentRender,renderFooter:f,changeYear:this.changeYear},null)),o===\"year\"&&(p=g(ZTe,{locale:a,value:i,rootPrefixCls:r,onSelect:this.onYearSelect,onDecadePanelShow:this.showDecadePanel,renderFooter:f},null)),o===\"decade\"&&(p=g(nxe,{locale:a,value:i,rootPrefixCls:r,onSelect:this.onDecadeSelect,renderFooter:f},null)),g(\"div\",{class:\"\".concat(r,\"-header\")},[g(\"div\",{style:{position:\"relative\"}},[Nh(c&&!l,g(\"a\",{class:\"\".concat(r,\"-prev-year-btn\"),role:\"button\",onClick:this.previousYear,title:a.previousYear},null)),Nh(c&&!l,g(\"a\",{class:\"\".concat(r,\"-prev-month-btn\"),role:\"button\",onClick:this.previousMonth,title:a.previousMonth},null)),this.monthYearElement(l),Nh(s&&!l,g(\"a\",{class:\"\".concat(r,\"-next-month-btn\"),onClick:this.nextMonth,title:a.nextMonth},null)),Nh(s&&!l,g(\"a\",{class:\"\".concat(r,\"-next-year-btn\"),onClick:this.nextYear,title:a.nextYear},null))]),p])}},aS=rxe;function axe(){}var BD=function(t,n){var r=n.attrs,a=r.prefixCls,o=r.locale,i=r.value,l=r.timePicker,s=r.disabled,c=r.disabledDate,d=r.onToday,f=r.text,p=(!f&&l?o.now:f)||o.today,v=c&&!Xv(hl(i),c),m=v||s,y=m?\"\".concat(a,\"-today-btn-disabled\"):\"\";return g(\"a\",{class:\"\".concat(a,\"-today-btn \").concat(y),role:\"button\",onClick:m?axe:d,title:fPe(i)},[p])};BD.inheritAttrs=!1;var VD=BD;function oxe(){}var zD=function(t,n){var r=n.attrs,a=r.prefixCls,o=r.locale,i=r.okDisabled,l=r.onOk,s=\"\".concat(a,\"-ok-btn\");return i&&(s+=\" \".concat(a,\"-ok-btn-disabled\")),g(\"a\",{class:s,role:\"button\",onClick:i?oxe:l},[o.ok])};zD.inheritAttrs=!1;var HD=zD;function eb(){}var jD=function(t,n){var r,a=n.attrs,o=a.prefixCls,i=a.locale,l=a.showTimePicker,s=a.timePickerDisabled,c=a.onCloseTimePicker,d=c===void 0?eb:c,f=a.onOpenTimePicker,p=f===void 0?eb:f,v=(r={},V(r,\"\".concat(o,\"-time-picker-btn\"),!0),V(r,\"\".concat(o,\"-time-picker-btn-disabled\"),s),r),m=eb;return s||(m=l?d:p),g(\"a\",{class:v,role:\"button\",onClick:m},[l?i.dateSelect:i.timeSelect])};jD.inheritAttrs=!1;var KD=jD,ixe={name:\"CalendarFooter\",inheritAttrs:!1,mixins:[nt],props:{prefixCls:u.string,showDateInput:u.looseBool,disabledTime:u.any,timePicker:u.any,selectedValue:u.any,showOk:u.looseBool,value:u.object,renderFooter:u.func,defaultValue:u.object,locale:u.object,showToday:u.looseBool,disabledDate:u.func,showTimePicker:u.looseBool,okDisabled:u.looseBool,mode:u.string},methods:{onSelect:function(t){this.__emit(\"select\",t)},getRootDOMNode:function(){return Sn(this)}},render:function(){var t=Qe(this),n=t.value,r=t.prefixCls,a=t.showOk,o=t.timePicker,i=t.renderFooter,l=t.showToday,s=t.mode,c=null,d=i&&i(s);if(l||o||d){var f,p=P(P(P({},t),this.$attrs),{value:n}),v=null;l&&(v=g(VD,le({key:\"todayButton\"},p),null)),delete p.value;var m=null;(a===!0||a!==!1&&!!o)&&(m=g(HD,le({key:\"okButton\"},p),null));var y=null;o&&(y=g(KD,le({key:\"timePickerButton\"},p),null));var b;(v||y||m||d)&&(b=g(\"span\",{class:\"\".concat(r,\"-footer-btn\")},[d,v,y,m]));var C=(f={},V(f,\"\".concat(r,\"-footer\"),!0),V(f,\"\".concat(r,\"-footer-show-ok\"),!!m),f);c=g(\"div\",{class:C},[b])}return c}},WD=ixe,tb,nb,Xo,lxe={name:\"DateInput\",inheritAttrs:!1,mixins:[nt],props:{prefixCls:u.string,timePicker:u.object,value:u.object,disabledTime:u.any,format:u.oneOfType([u.string,u.arrayOf(u.string),u.func]),locale:u.object,disabledDate:u.func,placeholder:u.string,selectedValue:u.object,clearIcon:u.any,inputMode:u.string,inputReadOnly:u.looseBool,disabled:u.looseBool,showClear:u.looseBool},data:function(){var t=this.selectedValue;return{str:qy(t,this.format),invalid:!1,hasFocus:!1}},watch:{selectedValue:function(){this.setState()},format:function(){this.setState()}},updated:function(){var t=this;this.$nextTick(function(){Xo&&t.$data.hasFocus&&!t.invalid&&!(tb===0&&nb===0)&&Xo.setSelectionRange(tb,nb)})},getInstance:function(){return Xo},methods:{getDerivedStateFromProps:function(t,n){var r={};Xo&&(tb=Xo.selectionStart,nb=Xo.selectionEnd);var a=t.selectedValue;return n.hasFocus||(r={str:qy(a,this.format),invalid:!1}),r},onClear:function(){this.setState({str:\"\"}),this.__emit(\"clear\",null)},onInputChange:function(t){var n=t.target,r=n.value,a=n.composing,o=this.str,i=o===void 0?\"\":o;if(!(t.isComposing||a||i===r)){var l=this.$props,s=l.disabledDate,c=l.format,d=l.selectedValue;if(!r){this.__emit(\"change\",null),this.setState({invalid:!1,str:r});return}var f=Ue(r,c,!0);if(!f.isValid()){this.setState({invalid:!0,str:r});return}var p=this.value.clone();if(p.year(f.year()).month(f.month()).date(f.date()).hour(f.hour()).minute(f.minute()).second(f.second()),!p||s&&s(p)){this.setState({invalid:!0,str:r});return}(d!==p||d&&p&&!d.isSame(p))&&(this.setState({invalid:!1,str:r}),this.__emit(\"change\",p))}},onFocus:function(){this.setState({hasFocus:!0})},onBlur:function(){this.setState(function(t,n){return{hasFocus:!1,str:qy(n.value,n.format)}})},onKeyDown:function(t){var n=t.keyCode,r=this.$props,a=r.value,o=r.disabledDate;if(n===ze.ENTER){var i=!o||!o(a);i&&this.__emit(\"select\",a.clone()),t.preventDefault()}},getRootDOMNode:function(){return Sn(this)},focus:function(){Xo&&Xo.focus()},saveDateInput:function(t){Xo=t}},render:function(){var t=this.invalid,n=this.str,r=this.locale,a=this.prefixCls,o=this.placeholder,i=this.disabled,l=this.showClear,s=this.inputMode,c=this.inputReadOnly,d=We(this,\"clearIcon\"),f=t?\"\".concat(a,\"-input-invalid\"):\"\";return g(\"div\",{class:\"\".concat(a,\"-input-wrap\")},[g(\"div\",{class:\"\".concat(a,\"-date-input-wrap\")},[at(g(\"input\",{ref:this.saveDateInput,class:\"\".concat(a,\"-input \").concat(f),value:n,disabled:i,placeholder:o,onInput:this.onInputChange,onChange:this.onInputChange,onKeydown:this.onKeyDown,onFocus:this.onFocus,onBlur:this.onBlur,inputMode:s,readonly:c},null),[[Mi]])]),l?g(\"a\",{role:\"button\",title:r.clear,onClick:this.onClear},[d||g(\"span\",{class:\"\".concat(a,\"-clear-btn\")},null)]):null])}},qp=lxe;function UD(e){return e.clone().startOf(\"month\")}function YD(e){return e.clone().endOf(\"month\")}function ei(e,t,n){return e.clone().add(t,n)}function sxe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0;return e.some(function(r){return r.isSame(t,n)})}var Ah=function(t){return Ue.isMoment(t)&&t.isValid()?t:!1},uxe=G({name:\"Calendar\",mixins:[nt,$g,U2],inheritAttrs:!1,props:{locale:u.object.def(Nf),format:u.oneOfType([u.string,u.arrayOf(u.string),u.func]),visible:u.looseBool.def(!0),prefixCls:u.string.def(\"rc-calendar\"),defaultValue:u.object,value:u.object,selectedValue:u.object,defaultSelectedValue:u.object,mode:u.oneOf([\"time\",\"date\",\"month\",\"year\",\"decade\"]),showDateInput:u.looseBool.def(!0),showWeekNumber:u.looseBool,showToday:u.looseBool.def(!0),showOk:u.looseBool,timePicker:u.any,dateInputPlaceholder:u.any,disabledDate:u.func,disabledTime:u.any,dateRender:u.func,renderFooter:u.func.def(function(){return null}),renderSidebar:u.func.def(function(){return null}),clearIcon:u.any,focusablePanel:u.looseBool.def(!0),inputMode:u.string,inputReadOnly:u.looseBool,monthCellRender:u.func,monthCellContentRender:u.func},data:function(){var t=this.$props;return{sMode:this.mode||\"date\",sValue:Ah(t.value)||Ah(t.defaultValue)||Ue(),sSelectedValue:t.selectedValue||t.defaultSelectedValue}},watch:{mode:function(t){this.setState({sMode:t})},value:function(t){this.setState({sValue:Ah(t)||Ah(this.defaultValue)||Zv(this.sValue)})},selectedValue:function(t){this.setState({sSelectedValue:t})}},mounted:function(){var t=this;this.$nextTick(function(){t.saveFocusElement(qp.getInstance())})},methods:{onPanelChange:function(t,n){var r=this.sValue;vt(this,\"mode\")||this.setState({sMode:n}),this.__emit(\"panelChange\",t||r,n)},onKeyDown:function(t){if(t.target.nodeName.toLowerCase()!==\"input\"){var n=t.keyCode,r=t.ctrlKey||t.metaKey,a=this.disabledDate,o=this.sValue;switch(n){case ze.DOWN:return this.goTime(1,\"weeks\"),t.preventDefault(),1;case ze.UP:return this.goTime(-1,\"weeks\"),t.preventDefault(),1;case ze.LEFT:return r?this.goTime(-1,\"years\"):this.goTime(-1,\"days\"),t.preventDefault(),1;case ze.RIGHT:return r?this.goTime(1,\"years\"):this.goTime(1,\"days\"),t.preventDefault(),1;case ze.HOME:return this.setValue(UD(o)),t.preventDefault(),1;case ze.END:return this.setValue(YD(o)),t.preventDefault(),1;case ze.PAGE_DOWN:return this.goTime(1,\"month\"),t.preventDefault(),1;case ze.PAGE_UP:return this.goTime(-1,\"month\"),t.preventDefault(),1;case ze.ENTER:return(!a||!a(o))&&this.onSelect(o,{source:\"keyboard\"}),t.preventDefault(),1;default:return this.__emit(\"keydown\",t),1}}},onClear:function(){this.onSelect(null),this.__emit(\"clear\")},onOk:function(){var t=this.sSelectedValue;this.isAllowedDate(t)&&this.__emit(\"ok\",t)},onDateInputChange:function(t){this.onSelect(t,{source:\"dateInput\"})},onDateInputSelect:function(t){this.onSelect(t,{source:\"dateInputSelect\"})},onDateTableSelect:function(t){var n=this.timePicker,r=this.sSelectedValue;if(!r&&n){var a=Qe(n),o=a.defaultValue;o&&Sa(o,t)}this.onSelect(t)},onToday:function(){var t=this.sValue,n=hl(t);this.onSelect(n,{source:\"todayButton\"})},onBlur:function(t){var n=this;setTimeout(function(){var r=qp.getInstance(),a=n.rootInstance;!a||a.contains(document.activeElement)||r&&r.contains(document.activeElement)||n.__emit(\"blur\",t)},0)},getRootDOMNode:function(){return Sn(this)},openTimePicker:function(){this.onPanelChange(null,\"time\")},closeTimePicker:function(){this.onPanelChange(null,\"date\")},goTime:function(t,n){this.setValue(ei(this.sValue,t,n))}},render:function(){var t=this.locale,n=this.prefixCls,r=this.disabledDate,a=this.dateInputPlaceholder,o=this.timePicker,i=this.disabledTime,l=this.showDateInput,s=this.sValue,c=this.sSelectedValue,d=this.sMode,f=this.renderFooter,p=this.inputMode,v=this.inputReadOnly,m=this.monthCellRender,y=this.monthCellContentRender,b=this.$props,C=We(this,\"clearIcon\"),S=d===\"time\",w=S&&i&&o?K2(c,i):null,k=null;if(o&&S){var $=Qe(o),O=P(P(P({showHour:!0,showSecond:!0,showMinute:!0},$),w),{value:c,disabledTime:i,onChange:this.onDateInputChange});$.defaultValue!==void 0&&(O.defaultOpenValue=$.defaultValue),k=Ot(o,O)}var T=l?g(qp,{format:this.getFormat(),key:\"date-input\",value:s,locale:t,placeholder:a,showClear:!0,disabledTime:i,disabledDate:r,onClear:this.onClear,prefixCls:n,selectedValue:c,onChange:this.onDateInputChange,clearIcon:C,onSelect:this.onDateInputSelect,inputMode:p,inputReadOnly:v},null):null,_=[];return b.renderSidebar&&_.push(b.renderSidebar()),_.push(g(\"div\",{class:\"\".concat(n,\"-panel\"),key:\"panel\"},[T,g(\"div\",{tabindex:b.focusablePanel?0:void 0,class:\"\".concat(n,\"-date-panel\")},[g(aS,{locale:t,mode:d,value:s,onValueChange:this.setValue,onPanelChange:this.onPanelChange,renderFooter:f,showTimePicker:S,prefixCls:n,monthCellRender:m,monthCellContentRender:y},null),o&&S?g(\"div\",{class:\"\".concat(n,\"-time-picker\")},[g(\"div\",{class:\"\".concat(n,\"-time-picker-panel\")},[k])]):null,g(\"div\",{class:\"\".concat(n,\"-body\")},[g(W2,{locale:t,value:s,selectedValue:c,prefixCls:n,dateRender:b.dateRender,onSelect:this.onDateTableSelect,disabledDate:r,showWeekNumber:b.showWeekNumber},null)]),g(WD,{showOk:b.showOk,mode:d,renderFooter:b.renderFooter,locale:t,prefixCls:n,showToday:b.showToday,disabledTime:i,showTimePicker:S,showDateInput:b.showDateInput,timePicker:o,selectedValue:c,timePickerDisabled:!c,value:s,disabledDate:r,okDisabled:b.showOk!==!1&&(!c||!this.isAllowedDate(c)),onOk:this.onOk,onSelect:this.onSelect,onToday:this.onToday,onOpenTimePicker:this.openTimePicker,onCloseTimePicker:this.closeTimePicker},null)])])),this.renderRoot({children:_,class:b.showWeekNumber?\"\".concat(n,\"-week-number\"):\"\"})}}),qD=uxe,cxe=G({name:\"MonthCalendar\",mixins:[nt,$g,U2],inheritAttrs:!1,props:{locale:u.object.def(Nf),format:u.string,visible:u.looseBool.def(!0),prefixCls:u.string.def(\"rc-calendar\"),monthCellRender:u.func,value:u.object,defaultValue:u.object,selectedValue:u.object,defaultSelectedValue:u.object,disabledDate:u.func,monthCellContentRender:u.func,renderFooter:u.func.def(function(){return null}),renderSidebar:u.func.def(function(){return null})},data:function(){var t=this.$props;return{mode:\"month\",sValue:t.value||t.defaultValue||Ue(),sSelectedValue:t.selectedValue||t.defaultSelectedValue}},methods:{onKeyDown:function(t){var n=t.keyCode,r=t.ctrlKey||t.metaKey,a=this.sValue,o=this.disabledDate,i=a;switch(n){case ze.DOWN:i=a.clone(),i.add(3,\"months\");break;case ze.UP:i=a.clone(),i.add(-3,\"months\");break;case ze.LEFT:i=a.clone(),r?i.add(-1,\"years\"):i.add(-1,\"months\");break;case ze.RIGHT:i=a.clone(),r?i.add(1,\"years\"):i.add(1,\"months\");break;case ze.ENTER:return(!o||!o(a))&&this.onSelect(a),t.preventDefault(),1;default:return}if(i!==a)return this.setValue(i),t.preventDefault(),1},handlePanelChange:function(t,n){n!==\"date\"&&this.setState({mode:n})}},render:function(){var t=this.mode,n=this.sValue,r=this.$props,a=this.$slots,o=r.prefixCls,i=r.locale,l=r.disabledDate,s=this.monthCellRender||a.monthCellRender,c=this.monthCellContentRender||a.monthCellContentRender,d=this.renderFooter||a.renderFooter,f=g(\"div\",{class:\"\".concat(o,\"-month-calendar-content\")},[g(\"div\",{class:\"\".concat(o,\"-month-header-wrap\")},[g(aS,{prefixCls:o,mode:t,value:n,locale:i,disabledMonth:l,monthCellRender:s,monthCellContentRender:c,onMonthSelect:this.onSelect,onValueChange:this.setValue,onPanelChange:this.handlePanelChange},null)]),g(WD,{prefixCls:o,renderFooter:d},null)]);return this.renderRoot({class:\"\".concat(r.prefixCls,\"-month-calendar\"),children:f})}}),GD=cxe;function id(){var e=[].slice.call(arguments,0);return e.length===1?e[0]:function(){for(var n=0;n<e.length;n++)e[n]&&e[n].apply&&e[n].apply(this,arguments)}}var Dh={adjustX:1,adjustY:1},Rh=[0,0],dxe={bottomLeft:{points:[\"tl\",\"tl\"],overflow:Dh,offset:[0,-3],targetOffset:Rh},bottomRight:{points:[\"tr\",\"tr\"],overflow:Dh,offset:[0,-3],targetOffset:Rh},topRight:{points:[\"br\",\"br\"],overflow:Dh,offset:[0,3],targetOffset:Rh},topLeft:{points:[\"bl\",\"bl\"],overflow:Dh,offset:[0,3],targetOffset:Rh}},fxe=dxe,yT={validator:function(t){return Array.isArray(t)?t.length===0||t.findIndex(function(n){return!ul(n)&&!Ue.isMoment(n)})===-1:ul(t)||Ue.isMoment(t)}};function hxe(e,t){this[e]=t}var pxe=G({name:\"Picker\",mixins:[nt],inheritAttrs:!1,props:{animation:u.oneOfType([u.func,u.string]),disabled:u.looseBool,transitionName:u.string,format:u.oneOfType([u.string,u.array,u.func]),getCalendarContainer:u.func,calendar:u.any,open:u.looseBool,defaultOpen:u.looseBool.def(!1),prefixCls:u.string.def(\"rc-calendar-picker\"),placement:u.any.def(\"bottomLeft\"),value:yT,defaultValue:yT,align:u.object.def(function(){return{}}),dropdownClassName:u.string,dateRender:u.func,children:u.func},data:function(){var t=this.$props;this.calendarElement=null,this.saveCalendarRef=hxe.bind(this,\"calendarInstance\");var n;vt(this,\"open\")?n=t.open:n=t.defaultOpen;var r=t.value||t.defaultValue;return{sOpen:n,sValue:r}},watch:{value:function(t){this.setState({sValue:t})},open:function(t){this.setState({sOpen:t})}},mounted:function(){this.preSOpen=this.sOpen},updated:function(){!this.preSOpen&&this.sOpen&&(this.focusTimeout=setTimeout(this.focusCalendar,100)),this.preSOpen=this.sOpen},beforeUnmount:function(){clearTimeout(this.focusTimeout)},methods:{onCalendarKeyDown:function(t){t.keyCode===ze.ESC&&(t.stopPropagation(),this.closeCalendar(this.focus))},onCalendarSelect:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=this.$props;vt(this,\"value\")||this.setState({sValue:t});var a=Qe(r.calendar);(n.source===\"keyboard\"||n.source===\"dateInputSelect\"||!a.timePicker&&n.source!==\"dateInput\"||n.source===\"todayButton\")&&this.closeCalendar(this.focus),this.__emit(\"change\",t)},onKeyDown:function(t){!this.sOpen&&(t.keyCode===ze.DOWN||t.keyCode===ze.ENTER)&&(this.openCalendar(),t.preventDefault())},onCalendarOk:function(){this.closeCalendar(this.focus)},onCalendarClear:function(){this.closeCalendar(this.focus)},onCalendarBlur:function(){this.setOpen(!1)},onVisibleChange:function(t){this.setOpen(t)},getCalendarElement:function(){var t=this.$props,n=Qe(t.calendar),r=nf(t.calendar),a=this.sValue,o=a,i={ref:this.saveCalendarRef,defaultValue:o||n.defaultValue,selectedValue:a,onKeydown:this.onCalendarKeyDown,onOk:id(r.onOk,this.onCalendarOk),onSelect:id(r.onSelect,this.onCalendarSelect),onClear:id(r.onClear,this.onCalendarClear),onBlur:id(r.onBlur,this.onCalendarBlur)};return Ot(t.calendar,i)},setOpen:function(t,n){this.sOpen!==t&&(vt(this,\"open\")||this.setState({sOpen:t},n),this.__emit(\"openChange\",t))},openCalendar:function(t){this.setOpen(!0,t)},closeCalendar:function(t){this.setOpen(!1,t)},focus:function(){this.sOpen||Sn(this).focus()},focusCalendar:function(){this.sOpen&&!!this.calendarInstance&&this.calendarInstance.focus()}},render:function(){var t=this,n=Qe(this),r=n.prefixCls,a=n.placement,o=n.getCalendarContainer,i=n.align,l=n.animation,s=n.disabled,c=n.dropdownClassName,d=n.transitionName,f=this.sValue,p=this.sOpen,v={value:f,open:p},m=this.$slots.default(v);return(this.sOpen||!this.calendarElement)&&(this.calendarElement=this.getCalendarElement()),g(Ii,{popupAlign:i,builtinPlacements:fxe,popupPlacement:a,action:s&&!p?[]:[\"click\"],destroyPopupOnHide:!0,getPopupContainer:o,popupStyle:this.$attrs.style||{},popupAnimation:l,popupTransitionName:d,popupVisible:p,onPopupVisibleChange:this.onVisibleChange,prefixCls:r,popupClassName:c,popup:this.calendarElement},{default:function(){return[Ot(m,{onKeydown:t.onKeyDown})]}})}}),oS=pxe,vxe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z\"}}]},name:\"calendar\",theme:\"outlined\"},mxe=vxe;function bT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){gxe(e,a,n[a])})}return e}function gxe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var iS=function(t,n){var r=bT({},t,n.attrs);return g(Et,bT({},r,{icon:mxe}),null)};iS.displayName=\"CalendarOutlined\";iS.inheritAttrs=!1;var XD=iS;function Cu(e,t){return e?(Array.isArray(t)&&(t=t[0]),typeof t==\"function\"?t(e):e.format(t)):\"\"}function ZD(e,t,n){return G({name:n,mixins:[nt],inheritAttrs:!1,props:P(P({},t),{allowClear:u.looseBool.def(!0),showToday:u.looseBool.def(!0)}),setup:function(){return{configProvider:ve(\"configProvider\",St),input:void 0,sPrefixCls:void 0}},data:function(){var a=this.value||this.defaultValue;return{sValue:a,showDate:a,sOpen:!!this.open}},watch:{open:function(a){var o=Qe(this),i={};i.sOpen=a,\"value\"in o&&!a&&o.value!==this.showDate&&(i.showDate=o.value),this.setState(i)},value:function(a){var o={};o.sValue=a,a!==this.sValue&&(o.showDate=a),this.setState(o)},sOpen:function(a,o){var i=this;Ne(function(){!vt(i,\"open\")&&o&&!a&&i.focus()})}},methods:{saveInput:function(a){this.input=a},clearSelection:function(a){a.preventDefault(),a.stopPropagation(),this.handleChange(null)},handleChange:function(a){vt(this,\"value\")||this.setState({sValue:a,showDate:a}),this.$emit(\"change\",a,Cu(a,this.format))},handleCalendarChange:function(a){this.setState({showDate:a})},handleOpenChange:function(a){var o=Qe(this);\"open\"in o||this.setState({sOpen:a}),this.$emit(\"openChange\",a)},focus:function(){var a;(a=this.input)===null||a===void 0||a.focus()},blur:function(){var a;(a=this.input)===null||a===void 0||a.blur()},renderFooter:function(){var a=this.$slots,o=this.sPrefixCls,i=this.renderExtraFooter||a.renderExtraFooter;return i?g(\"div\",{class:\"\".concat(o,\"-footer-extra\")},[typeof i==\"function\"?i.apply(void 0,arguments):i]):null},onMouseEnter:function(a){this.$emit(\"mouseenter\",a)},onMouseLeave:function(a){this.$emit(\"mouseleave\",a)}},render:function(){var a,o=this,i=this.$slots,l=this.$data,s=l.sValue,c=l.showDate,d=l.sOpen,f=We(this,\"suffixIcon\");f=Array.isArray(f)?f[0]:f;var p=MC(P(P({},Qe(this)),this.$attrs),[\"onChange\"]),v=p.prefixCls,m=p.locale,y=p.localeCode,b=p.inputReadOnly,C=this.configProvider.getPrefixCls,S=C(\"calendar\",v);this.sPrefixCls=S;var w=p.dateRender||i.dateRender,k=p.monthCellContentRender||i.monthCellContentRender,$=\"placeholder\"in p?p.placeholder:m.lang.placeholder,O=p.showTime?p.disabledTime:null,T=Se((a={},V(a,\"\".concat(S,\"-time\"),p.showTime),V(a,\"\".concat(S,\"-month\"),GD===e),a));s&&y&&s.locale(y);var _={},I={},L={};p.showTime?(I.onSelect=this.handleChange,L.minWidth=\"195px\"):_.onChange=this.handleChange,\"mode\"in p&&(I.mode=p.mode);var j=P(P({},I),{disabledDate:p.disabledDate,disabledTime:O,locale:m.lang,timePicker:p.timePicker,defaultValue:p.defaultPickerValue||Hr(Ue)(),dateInputPlaceholder:$,prefixCls:S,dateRender:w,format:p.format,showToday:p.showToday,monthCellContentRender:k,renderFooter:this.renderFooter,value:c,inputReadOnly:b,onOk:p.onOk,onPanelChange:p.onPanelChange,onChange:this.handleCalendarChange,class:T}),F=g(e,j,i),N=!p.disabled&&p.allowClear&&s?g(Yr,{class:\"\".concat(S,\"-picker-clear\"),onClick:this.clearSelection},null):null,D=f&&(zn(f)?Ot(f,{class:\"\".concat(S,\"-picker-icon\")}):g(\"span\",{class:\"\".concat(S,\"-picker-icon\")},[f]))||g(XD,{class:\"\".concat(S,\"-picker-icon\")},null),z=function(E){var K=E.value;return g(\"div\",null,[g(\"input\",{ref:o.saveInput,disabled:p.disabled,onFocus:p.onFocus,onBlur:p.onBlur,readonly:!0,value:Cu(K,o.format),placeholder:$,class:p.pickerInputClass,tabindex:p.tabindex,name:o.name},null),N,D])},B=P(P(P({},p),_),{calendar:F,value:s,prefixCls:\"\".concat(S,\"-picker-container\"),open:d,onOpenChange:this.handleOpenChange,style:p.popupStyle});return g(\"span\",le(le({id:p.id,class:Se(p.class,p.pickerClass),style:P(P({},L),p.style)},eg(this.$attrs)),{},{onMouseenter:this.onMouseEnter,onMouseleave:this.onMouseLeave}),[g(oS,B,P(P({},i),{default:l0e(i.default)?z:i.default}))])}})}var yxe={inheritAttrs:!1,name:\"Header\",mixins:[nt],props:{format:u.string,prefixCls:u.string,disabledDate:u.func,placeholder:u.string,clearText:u.string,value:u.object,inputReadOnly:u.looseBool.def(!1),hourOptions:u.array,minuteOptions:u.array,secondOptions:u.array,disabledHours:u.func,disabledMinutes:u.func,disabledSeconds:u.func,allowEmpty:u.looseBool,defaultOpenValue:u.object,currentSelectPanel:u.string,focusOnOpen:u.looseBool,clearIcon:u.any},data:function(){var t=this.value,n=this.format;return{str:t&&t.format(n)||\"\",invalid:!1}},mounted:function(){var t=this;if(this.focusOnOpen){var n=window.requestAnimationFrame||window.setTimeout;n(function(){t.refInput.focus(),t.refInput.select()})}},watch:{value:function(t){var n=this;this.$nextTick(function(){n.setState({str:t&&t.format(n.format)||\"\",invalid:!1})})}},methods:{onInputChange:function(t){var n=t.target,r=n.value,a=n.composing,o=this.str,i=o===void 0?\"\":o;if(!(t.isComposing||a||i===r)){this.setState({str:r});var l=this.format,s=this.hourOptions,c=this.minuteOptions,d=this.secondOptions,f=this.disabledHours,p=this.disabledMinutes,v=this.disabledSeconds,m=this.value;if(r){var y=this.getProtoValue().clone(),b=Ue(r,l,!0);if(!b.isValid()){this.setState({invalid:!0});return}if(y.hour(b.hour()).minute(b.minute()).second(b.second()),s.indexOf(y.hour())<0||c.indexOf(y.minute())<0||d.indexOf(y.second())<0){this.setState({invalid:!0});return}var C=f(),S=p(y.hour()),w=v(y.hour(),y.minute());if(C&&C.indexOf(y.hour())>=0||S&&S.indexOf(y.minute())>=0||w&&w.indexOf(y.second())>=0){this.setState({invalid:!0});return}if(m){if(m.hour()!==y.hour()||m.minute()!==y.minute()||m.second()!==y.second()){var k=m.clone();k.hour(y.hour()),k.minute(y.minute()),k.second(y.second()),this.__emit(\"change\",k)}}else m!==y&&this.__emit(\"change\",y)}else this.__emit(\"change\",null);this.setState({invalid:!1})}},onKeyDown:function(t){t.keyCode===27&&this.__emit(\"esc\"),this.__emit(\"keydown\",t)},getProtoValue:function(){return this.value||this.defaultOpenValue},getInput:function(){var t=this,n=this.prefixCls,r=this.placeholder,a=this.inputReadOnly,o=this.invalid,i=this.str,l=o?\"\".concat(n,\"-input-invalid\"):\"\";return at(g(\"input\",{class:\"\".concat(n,\"-input \").concat(l),ref:function(c){t.refInput=c},onKeydown:this.onKeyDown,value:i,placeholder:r,onInput:this.onInputChange,onChange:this.onInputChange,readonly:!!a},null),[[Mi]])}},render:function(){var t=this.prefixCls;return g(\"div\",{class:\"\".concat(t,\"-input-wrap\")},[this.getInput()])}},bxe=yxe;function Cxe(){}var wxe=function e(t,n,r){if(r<=0){requestAnimationFrame(function(){t.scrollTop=n});return}var a=n-t.scrollTop,o=a/r*10;requestAnimationFrame(function(){t.scrollTop+=o,t.scrollTop!==n&&e(t,n,r-10)})},Sxe={name:\"Select\",mixins:[nt],inheritAttrs:!1,props:{prefixCls:u.string,options:u.array,selectedIndex:u.number,type:u.string},data:function(){return{active:!1}},mounted:function(){var t=this;this.$nextTick(function(){t.scrollToSelected(0)})},watch:{selectedIndex:function(){var t=this;this.$nextTick(function(){t.scrollToSelected(120)})}},methods:{onSelect:function(t){var n=this.type;this.__emit(\"select\",n,t)},onEsc:function(t){this.__emit(\"esc\",t)},getOptions:function(){var t=this,n=this.options,r=this.selectedIndex,a=this.prefixCls;return n.map(function(o,i){var l,s=Se((l={},V(l,\"\".concat(a,\"-select-option-selected\"),r===i),V(l,\"\".concat(a,\"-select-option-disabled\"),o.disabled),l)),c=o.disabled?Cxe:function(){t.onSelect(o.value)},d=function(p){p.keyCode===13?c():p.keyCode===27&&t.onEsc()};return g(\"li\",{role:\"button\",onClick:c,class:s,key:i,disabled:o.disabled,tabindex:\"0\",onKeydown:d},[o.value])})},handleMouseEnter:function(t){this.setState({active:!0}),this.__emit(\"mouseenter\",t)},handleMouseLeave:function(){this.setState({active:!1})},scrollToSelected:function(t){var n=Sn(this),r=this.$refs.list;if(!!r){var a=this.selectedIndex;a<0&&(a=0);var o=r.children[a],i=o.offsetTop;wxe(n,i,t)}}},render:function(){var t,n=this.prefixCls,r=this.options,a=this.active;if(r.length===0)return null;var o=(t={},V(t,\"\".concat(n,\"-select\"),1),V(t,\"\".concat(n,\"-select-active\"),a),t);return g(\"div\",{class:o,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave},[g(\"ul\",{ref:\"list\"},[this.getOptions()])])}},Lh=Sxe,rb=function(t,n){var r=\"\".concat(t);t<10&&(r=\"0\".concat(t));var a=!1;return n&&n.indexOf(t)>=0&&(a=!0),{value:r,disabled:a}},kxe={inheritAttrs:!1,mixins:[nt],name:\"Combobox\",props:{format:u.string,defaultOpenValue:u.object,prefixCls:u.string,value:u.object,showHour:u.looseBool,showMinute:u.looseBool,showSecond:u.looseBool,hourOptions:u.array,minuteOptions:u.array,secondOptions:u.array,disabledHours:u.func,disabledMinutes:u.func,disabledSeconds:u.func,use12Hours:u.looseBool,isAM:u.looseBool},methods:{onItemChange:function(t,n){var r=this.defaultOpenValue,a=this.use12Hours,o=this.value,i=this.isAM,l=(o||r).clone();if(t===\"hour\")a?i?l.hour(+n%12):l.hour(+n%12+12):l.hour(+n);else if(t===\"minute\")l.minute(+n);else if(t===\"ampm\"){var s=n.toUpperCase();a&&(s===\"PM\"&&l.hour()<12&&l.hour(l.hour()%12+12),s===\"AM\"&&l.hour()>=12&&l.hour(l.hour()-12)),this.__emit(\"amPmChange\",s)}else l.second(+n);this.__emit(\"change\",l)},onEnterSelectPanel:function(t){this.__emit(\"currentSelectPanelChange\",t)},onEsc:function(t){this.__emit(\"esc\",t)},getHourSelect:function(t){var n=this,r=this.prefixCls,a=this.hourOptions,o=this.disabledHours,i=this.showHour,l=this.use12Hours;if(!i)return null;var s=o(),c,d;return l?(c=[12].concat(a.filter(function(f){return f<12&&f>0})),d=t%12||12):(c=a,d=t),g(Lh,{prefixCls:r,options:c.map(function(f){return rb(f,s)}),selectedIndex:c.indexOf(d),type:\"hour\",onSelect:this.onItemChange,onMouseenter:function(){return n.onEnterSelectPanel(\"hour\")},onEsc:this.onEsc},null)},getMinuteSelect:function(t){var n=this,r=this.prefixCls,a=this.minuteOptions,o=this.disabledMinutes,i=this.defaultOpenValue,l=this.showMinute,s=this.value;if(!l)return null;var c=s||i,d=o(c.hour());return g(Lh,{prefixCls:r,options:a.map(function(f){return rb(f,d)}),selectedIndex:a.indexOf(t),type:\"minute\",onSelect:this.onItemChange,onMouseenter:function(){return n.onEnterSelectPanel(\"minute\")},onEsc:this.onEsc},null)},getSecondSelect:function(t){var n=this,r=this.prefixCls,a=this.secondOptions,o=this.disabledSeconds,i=this.showSecond,l=this.defaultOpenValue,s=this.value;if(!i)return null;var c=s||l,d=o(c.hour(),c.minute());return g(Lh,{prefixCls:r,options:a.map(function(f){return rb(f,d)}),selectedIndex:a.indexOf(t),type:\"second\",onSelect:this.onItemChange,onMouseenter:function(){return n.onEnterSelectPanel(\"second\")},onEsc:this.onEsc},null)},getAMPMSelect:function(){var t=this,n=this.prefixCls,r=this.use12Hours,a=this.format,o=this.isAM;if(!r)return null;var i=[\"am\",\"pm\"].map(function(s){return a.match(/\\sA/)?s.toUpperCase():s}).map(function(s){return{value:s}}),l=o?0:1;return g(Lh,{prefixCls:n,options:i,selectedIndex:l,type:\"ampm\",onSelect:this.onItemChange,onMouseenter:function(){return t.onEnterSelectPanel(\"ampm\")},onEsc:this.onEsc},null)}},render:function(){var t=this.prefixCls,n=this.defaultOpenValue,r=this.value,a=r||n;return g(\"div\",{class:\"\".concat(t,\"-combobox\")},[this.getHourSelect(a.hour()),this.getMinuteSelect(a.minute()),this.getSecondSelect(a.second()),this.getAMPMSelect(a.hour())])}},$xe=kxe;function qs(){}function ab(e,t,n){for(var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:1,a=[],o=0;o<e;o+=r)(!t||t.indexOf(o)<0||!n)&&a.push(o);return a}function Oxe(e,t,n,r){var a=t.slice().sort(function(l,s){return Math.abs(e.hour()-l)-Math.abs(e.hour()-s)})[0],o=n.slice().sort(function(l,s){return Math.abs(e.minute()-l)-Math.abs(e.minute()-s)})[0],i=r.slice().sort(function(l,s){return Math.abs(e.second()-l)-Math.abs(e.second()-s)})[0];return Ue(\"\".concat(a,\":\").concat(o,\":\").concat(i),\"HH:mm:ss\")}var Pxe=G({name:\"Panel\",mixins:[nt],inheritAttrs:!1,props:{clearText:u.string,prefixCls:u.string.def(\"rc-time-picker-panel\"),defaultOpenValue:{type:Object,default:function(){return Ue()}},value:u.any,defaultValue:u.any,placeholder:u.string,format:u.string,inputReadOnly:u.looseBool.def(!1),disabledHours:u.func.def(qs),disabledMinutes:u.func.def(qs),disabledSeconds:u.func.def(qs),hideDisabledOptions:u.looseBool,allowEmpty:u.looseBool,showHour:u.looseBool,showMinute:u.looseBool,showSecond:u.looseBool,use12Hours:u.looseBool.def(!1),hourStep:u.number,minuteStep:u.number,secondStep:u.number,addon:u.func.def(qs),focusOnOpen:u.looseBool,clearIcon:u.any},data:function(){return{sValue:this.value,selectionRange:[],currentSelectPanel:\"\"}},watch:{value:function(t){this.setState({sValue:t})}},methods:{onChange:function(t){this.setState({sValue:t}),this.__emit(\"change\",t)},onAmPmChange:function(t){this.__emit(\"amPmChange\",t)},onCurrentSelectPanelChange:function(t){this.setState({currentSelectPanel:t})},close:function(){this.__emit(\"esc\")},onEsc:function(t){this.__emit(\"esc\",t)},disabledHours2:function(){var t=this.use12Hours,n=this.disabledHours,r=n();return t&&Array.isArray(r)&&(this.isAM()?r=r.filter(function(a){return a<12}).map(function(a){return a===0?12:a}):r=r.map(function(a){return a===12?12:a-12})),r},isAM:function(){var t=this.sValue||this.defaultOpenValue;return t.hour()>=0&&t.hour()<12}},render:function(){var t=this.prefixCls,n=this.placeholder,r=this.disabledMinutes,a=this.addon,o=this.disabledSeconds,i=this.hideDisabledOptions,l=this.showHour,s=this.showMinute,c=this.showSecond,d=this.format,f=this.defaultOpenValue,p=this.clearText,v=this.use12Hours,m=this.focusOnOpen,y=this.hourStep,b=this.minuteStep,C=this.secondStep,S=this.inputReadOnly,w=this.sValue,k=this.currentSelectPanel,$=this.$attrs,O=$.class,T=$.onEsc,_=T===void 0?qs:T,I=$.onKeydown,L=I===void 0?qs:I,j=We(this,\"clearIcon\"),F=this.disabledHours2(),N=r(w?w.hour():null),D=o(w?w.hour():null,w?w.minute():null),z=ab(24,F,i,y),B=ab(60,N,i,b),M=ab(60,D,i,C),E=Oxe(f,z,B,M);return g(\"div\",{className:Se(O,\"\".concat(t,\"-inner\"))},[g(bxe,{clearText:p,prefixCls:t,defaultOpenValue:E,value:w,currentSelectPanel:k,onEsc:_,format:d,placeholder:n,hourOptions:z,minuteOptions:B,secondOptions:M,disabledHours:this.disabledHours2,disabledMinutes:r,disabledSeconds:o,onChange:this.onChange,focusOnOpen:m,onKeydown:L,inputReadOnly:S,clearIcon:j},null),g($xe,{prefixCls:t,value:w,defaultOpenValue:E,format:d,onChange:this.onChange,onAmPmChange:this.onAmPmChange,showHour:l,showMinute:s,showSecond:c,hourOptions:z,minuteOptions:B,secondOptions:M,disabledHours:this.disabledHours2,disabledMinutes:r,disabledSeconds:o,onCurrentSelectPanelChange:this.onCurrentSelectPanelChange,use12Hours:v,onEsc:this.onEsc,isAM:this.isAM()},null),a(this)])}}),JD=Pxe,Fh={adjustX:1,adjustY:1},Bh=[0,0],Txe={bottomLeft:{points:[\"tl\",\"tl\"],overflow:Fh,offset:[0,-3],targetOffset:Bh},bottomRight:{points:[\"tr\",\"tr\"],overflow:Fh,offset:[0,-3],targetOffset:Bh},topRight:{points:[\"br\",\"br\"],overflow:Fh,offset:[0,3],targetOffset:Bh},topLeft:{points:[\"bl\",\"bl\"],overflow:Fh,offset:[0,3],targetOffset:Bh}},xxe=Txe;function ob(){}function CT(e,t){this[e]=t}var _xe=G({name:\"VcTimePicker\",mixins:[nt],inheritAttrs:!1,props:An({prefixCls:u.string,clearText:u.string,value:u.any,defaultOpenValue:{type:Object,default:function(){return Ue()}},pickerInputClass:String,inputReadOnly:u.looseBool,disabled:u.looseBool,allowEmpty:u.looseBool,defaultValue:u.any,open:u.looseBool,defaultOpen:u.looseBool,align:u.object,placement:u.any,transitionName:u.string,getPopupContainer:u.func,placeholder:u.string,format:u.string,showHour:u.looseBool,showMinute:u.looseBool,showSecond:u.looseBool,popupClassName:u.string,popupStyle:u.object,disabledHours:u.func,disabledMinutes:u.func,disabledSeconds:u.func,hideDisabledOptions:u.looseBool,name:u.string,autocomplete:u.string,use12Hours:u.looseBool,hourStep:u.number,minuteStep:u.number,secondStep:u.number,focusOnOpen:u.looseBool,autofocus:u.looseBool,id:u.string,inputIcon:u.any,clearIcon:u.any,addon:u.func},{clearText:\"clear\",prefixCls:\"rc-time-picker\",defaultOpen:!1,inputReadOnly:!1,popupClassName:\"\",popupStyle:{},align:{},allowEmpty:!0,showHour:!0,showMinute:!0,showSecond:!0,disabledHours:ob,disabledMinutes:ob,disabledSeconds:ob,hideDisabledOptions:!1,placement:\"bottomLeft\",use12Hours:!1,focusOnOpen:!1}),data:function(){this.saveInputRef=CT.bind(this,\"picker\"),this.savePanelRef=CT.bind(this,\"panelInstance\");var t=this.defaultOpen,n=this.defaultValue,r=this.open,a=r===void 0?t:r,o=this.value,i=o===void 0?n:o;return{sOpen:a,sValue:i}},watch:{value:function(t){this.setState({sValue:t})},open:function(t){t!==void 0&&this.setState({sOpen:t})}},mounted:function(){var t=this;this.$nextTick(function(){t.autofocus&&t.focus()})},methods:{onPanelChange:function(t){this.setValue(t)},onAmPmChange:function(t){this.__emit(\"amPmChange\",t)},onClear:function(t){t.stopPropagation(),this.setValue(null),this.setOpen(!1)},onVisibleChange:function(t){this.setOpen(t)},onEsc:function(){this.setOpen(!1),this.focus()},onKeyDown:function(t){t.keyCode===40&&this.setOpen(!0)},onKeyDown2:function(t){this.__emit(\"keydown\",t)},setValue:function(t){vt(this,\"value\")||this.setState({sValue:t}),this.__emit(\"change\",t)},getFormat:function(){var t=this.format,n=this.showHour,r=this.showMinute,a=this.showSecond,o=this.use12Hours;if(t)return t;if(o){var i=[n?\"h\":\"\",r?\"mm\":\"\",a?\"ss\":\"\"].filter(function(l){return!!l}).join(\":\");return i.concat(\" a\")}return[n?\"HH\":\"\",r?\"mm\":\"\",a?\"ss\":\"\"].filter(function(l){return!!l}).join(\":\")},getPanelElement:function(){var t=this.prefixCls,n=this.placeholder,r=this.disabledHours,a=this.addon,o=this.disabledMinutes,i=this.disabledSeconds,l=this.hideDisabledOptions,s=this.inputReadOnly,c=this.showHour,d=this.showMinute,f=this.showSecond,p=this.defaultOpenValue,v=this.clearText,m=this.use12Hours,y=this.focusOnOpen,b=this.onKeyDown2,C=this.hourStep,S=this.minuteStep,w=this.secondStep,k=this.sValue,$=We(this,\"clearIcon\");return g(JD,{clearText:v,prefixCls:\"\".concat(t,\"-panel\"),ref:this.savePanelRef,value:k,inputReadOnly:s,onChange:this.onPanelChange,onAmPmChange:this.onAmPmChange,defaultOpenValue:p,showHour:c,showMinute:d,showSecond:f,onEsc:this.onEsc,format:this.getFormat(),placeholder:n,disabledHours:r,disabledMinutes:o,disabledSeconds:i,hideDisabledOptions:l,use12Hours:m,hourStep:C,minuteStep:S,secondStep:w,focusOnOpen:y,onKeydown:b,clearIcon:$,addon:a},null)},getPopupClassName:function(){var t=this.showHour,n=this.showMinute,r=this.showSecond,a=this.use12Hours,o=this.prefixCls,i=this.popupClassName,l=0;return t&&(l+=1),n&&(l+=1),r&&(l+=1),a&&(l+=1),Se(i,V({},\"\".concat(o,\"-panel-narrow\"),(!t||!n||!r)&&!a),\"\".concat(o,\"-panel-column-\").concat(l))},setOpen:function(t){this.sOpen!==t&&(vt(this,\"open\")||this.setState({sOpen:t}),t?this.__emit(\"open\",{open:t}):this.__emit(\"close\",{open:t}))},focus:function(){this.picker.focus()},blur:function(){this.picker.blur()},onFocus:function(t){this.__emit(\"focus\",t)},onBlur:function(t){this.__emit(\"blur\",t)},renderClearButton:function(){var t=this,n=this.sValue,r=this.$props,a=r.prefixCls,o=r.allowEmpty,i=r.clearText,l=r.disabled;if(!o||!n||l)return null;var s=We(this,\"clearIcon\");if(zn(s)){var c=nf(s)||{},d=c.onClick;return Ot(s,{onClick:function(){d&&d.apply(void 0,arguments),t.onClear.apply(t,arguments)}})}return g(\"a\",{role:\"button\",class:\"\".concat(a,\"-clear\"),title:i,onClick:this.onClear,tabindex:0},[s||g(\"i\",{class:\"\".concat(a,\"-clear-icon\")},null)])}},render:function(){var t=this,n=this.prefixCls,r=this.placeholder,a=this.placement,o=this.align,i=this.id,l=this.disabled,s=this.transitionName,c=this.getPopupContainer,d=this.name,f=this.autocomplete,p=this.autofocus,v=this.sOpen,m=this.sValue,y=this.onFocus,b=this.onBlur,C=this.popupStyle,S=this.pickerInputClass,w=this.$attrs,k=w.class,$=w.style,O=this.getPopupClassName(),T=We(this,\"inputIcon\");return g(Ii,{prefixCls:\"\".concat(n,\"-panel\"),popupClassName:O,popupStyle:C,popupAlign:o,builtinPlacements:xxe,popupPlacement:a,action:l?[]:[\"click\"],destroyPopupOnHide:!0,getPopupContainer:c,popupTransitionName:s,popupVisible:v,onPopupVisibleChange:this.onVisibleChange,popup:this.getPanelElement()},{default:function(){return[g(\"span\",{class:Se(n,k),style:$},[g(\"input\",{class:S,ref:t.saveInputRef,type:\"text\",placeholder:r,name:d,onKeydown:t.onKeyDown,disabled:l,value:m&&m.format(t.getFormat())||\"\",autocomplete:f,onFocus:y,onBlur:b,autofocus:p,readonly:!0,id:i},null),T||g(\"span\",{class:\"\".concat(n,\"-icon\")},null),t.renderClearButton()])]}})}}),Exe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z\"}},{tag:\"path\",attrs:{d:\"M686.7 638.6L544.1 535.5V288c0-4.4-3.6-8-8-8H488c-4.4 0-8 3.6-8 8v275.4c0 2.6 1.2 5 3.3 6.5l165.4 120.6c3.6 2.6 8.6 1.8 11.2-1.7l28.6-39c2.6-3.7 1.8-8.7-1.8-11.2z\"}}]},name:\"clock-circle\",theme:\"outlined\"},Mxe=Exe;function wT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){Ixe(e,a,n[a])})}return e}function Ixe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var lS=function(t,n){var r=wT({},t,n.attrs);return g(Et,wT({},r,{icon:Mxe}),null)};lS.displayName=\"ClockCircleOutlined\";lS.inheritAttrs=!1;var Nxe=lS;function QD(e){return{showHour:e.indexOf(\"H\")>-1||e.indexOf(\"h\")>-1||e.indexOf(\"k\")>-1,showMinute:e.indexOf(\"m\")>-1,showSecond:e.indexOf(\"s\")>-1}}var Axe=function(){return{size:u.oneOf(rt(\"large\",\"default\",\"small\")),value:z3,defaultValue:z3,open:u.looseBool,format:u.string,disabled:u.looseBool,placeholder:u.string,prefixCls:u.string,hideDisabledOptions:u.looseBool,disabledHours:u.func,disabledMinutes:u.func,disabledSeconds:u.func,getPopupContainer:u.func,use12Hours:u.looseBool,focusOnOpen:u.looseBool,hourStep:u.number,minuteStep:u.number,secondStep:u.number,allowEmpty:u.looseBool,allowClear:u.looseBool,inputReadOnly:u.looseBool,clearText:u.string,defaultOpenValue:u.object,popupClassName:u.string,popupStyle:u.style,suffixIcon:u.any,align:u.object,placement:u.any,transitionName:u.string,autofocus:u.looseBool,addon:u.any,clearIcon:u.any,locale:u.object,valueFormat:u.string,onChange:u.func,onAmPmChange:u.func,onOpen:u.func,onClose:u.func,onFocus:u.func,onBlur:u.func,onKeydown:u.func,onOpenChange:u.func}},Dxe=G({name:\"ATimePicker\",mixins:[nt],inheritAttrs:!1,props:Rn(Axe(),{align:{offset:[0,-2]},disabled:!1,disabledHours:void 0,disabledMinutes:void 0,disabledSeconds:void 0,hideDisabledOptions:!1,placement:\"bottomLeft\",transitionName:\"slide-up\",focusOnOpen:!0,allowClear:!0}),emits:[\"update:value\",\"update:open\",\"change\",\"openChange\",\"focus\",\"blur\",\"keydown\"],setup:function(){return{popupRef:null,timePickerRef:null,configProvider:ve(\"configProvider\",St)}},data:function(){var t=this.value,n=this.defaultValue,r=this.valueFormat;return pi(\"TimePicker\",n,\"defaultValue\",r),pi(\"TimePicker\",t,\"value\",r),on(!vt(this,\"allowEmpty\"),\"TimePicker\",\"`allowEmpty` is deprecated. Please use `allowClear` instead.\"),{sValue:rl(t||n,r)}},watch:{value:function(t){pi(\"TimePicker\",t,\"value\",this.valueFormat),this.setState({sValue:rl(t,this.valueFormat)})}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},methods:{getDefaultFormat:function(){var t=this.format,n=this.use12Hours;return t||(n?\"h:mm:ss a\":\"HH:mm:ss\")},getAllowClear:function(){var t=this.$props,n=t.allowClear,r=t.allowEmpty;return vt(this,\"allowClear\")?n:r},getDefaultLocale:function(){var t=P(P({},_w),this.$props.locale);return t},savePopupRef:function(t){this.popupRef=t},saveTimePicker:function(t){this.timePickerRef=t},handleChange:function(t){vt(this,\"value\")||this.setState({sValue:t});var n=this.format,r=n===void 0?\"HH:mm:ss\":n,a=this.valueFormat?Du(t,this.valueFormat):t;this.$emit(\"update:value\",a),this.$emit(\"change\",a,t&&t.format(r)||\"\")},handleOpenClose:function(t){var n=t.open;this.$emit(\"update:open\",n),this.$emit(\"openChange\",n)},focus:function(){this.timePickerRef.focus()},blur:function(){this.timePickerRef.blur()},renderInputIcon:function(t){var n=We(this,\"suffixIcon\");n=Array.isArray(n)?n[0]:n;var r=n&&zn(n)&&Ot(n,{class:\"\".concat(t,\"-clock-icon\")})||g(Nxe,{class:\"\".concat(t,\"-clock-icon\")},null);return g(\"span\",{class:\"\".concat(t,\"-icon\")},[r])},renderClearIcon:function(t){var n=We(this,\"clearIcon\"),r=\"\".concat(t,\"-clear\");return n&&zn(n)?Ot(n,{class:r}):g(Yr,{class:r},null)},renderTimePicker:function(t){var n,r=Qe(this);r=bn(r,[\"defaultValue\",\"suffixIcon\",\"allowEmpty\",\"allowClear\"]);var a=this.$attrs.class,o=r,i=o.prefixCls,l=o.getPopupContainer,s=o.placeholder,c=o.size,d=this.configProvider.getPrefixCls,f=d(\"time-picker\",i),p=d(\"input\"),v=Se(\"\".concat(f,\"-input\"),p),m=this.getDefaultFormat(),y=(n={},V(n,a,a),V(n,\"\".concat(f,\"-\").concat(c),!!c),n),b=We(this,\"addon\",{},!1),C=function(T){return b?g(\"div\",{class:\"\".concat(f,\"-panel-addon\")},[typeof b==\"function\"?b(T):b]):null},S=this.renderInputIcon(f),w=this.renderClearIcon(f),k=this.configProvider.getPopupContainer,$=P(P(P(P({},QD(m)),r),this.$attrs),{allowEmpty:this.getAllowClear(),prefixCls:f,pickerInputClass:v,getPopupContainer:l||k,format:m,value:this.sValue,placeholder:s===void 0?t.placeholder:s,addon:C,inputIcon:S,clearIcon:w,class:y,ref:this.saveTimePicker,onChange:this.handleChange,onOpen:this.handleOpenClose,onClose:this.handleOpenClose});return g(_xe,$,null)}},render:function(){return g(Kr,{componentName:\"TimePicker\",defaultLocale:this.getDefaultLocale(),children:this.renderTimePicker},null)}}),Rxe=kn(Dxe),Lxe={date:\"YYYY-MM-DD\",dateTime:\"YYYY-MM-DD HH:mm:ss\",week:\"gggg-wo\",month:\"YYYY-MM\"},Fxe={date:\"dateFormat\",dateTime:\"dateTimeFormat\",week:\"weekFormat\",month:\"monthFormat\"};function Bxe(e){var t=e.showHour,n=e.showMinute,r=e.showSecond,a=e.use12Hours,o=0;return t&&(o+=1),n&&(o+=1),r&&(o+=1),a&&(o+=1),o}function xg(e,t,n){return G({name:e.name,inheritAttrs:!1,props:P(P({},t),{transitionName:u.string.def(\"slide-up\"),popupStyle:u.style,locale:u.any.def({})}),emits:[\"update:value\",\"openChange\",\"focus\",\"blur\",\"mouseenter\",\"mouseleave\",\"change\",\"ok\",\"calendarChange\"],setup:function(){return{configProvider:ve(\"configProvider\",St),picker:void 0,popupRef:void 0}},watch:{value:function(a){pi(\"DatePicker\",a,\"value\",this.valueFormat)}},created:function(){ot(\"savePopupRef\",this.savePopupRef)},mounted:function(){var a=this,o=this.$props,i=o.autofocus,l=o.disabled,s=o.value,c=o.defaultValue,d=o.valueFormat;pi(\"DatePicker\",c,\"defaultValue\",d),pi(\"DatePicker\",s,\"value\",d),i&&!l&&Ne(function(){a.focus()})},methods:{savePicker:function(a){this.picker=a},getDefaultLocale:function(){var a=P(P({},Ev),this.locale);return a.lang=P(P({},a.lang),(this.locale||{}).lang),a},savePopupRef:function(a){this.popupRef=a},handleOpenChange:function(a){this.$emit(\"openChange\",a)},handleFocus:function(a){this.$emit(\"focus\",a)},handleBlur:function(a){this.$emit(\"blur\",a)},handleMouseEnter:function(a){this.$emit(\"mouseenter\",a)},handleMouseLeave:function(a){this.$emit(\"mouseleave\",a)},handleChange:function(a,o){var i=this.valueFormat?Du(a,this.valueFormat):a;this.$emit(\"update:value\",i),this.$emit(\"change\",i,o)},handleOk:function(a){this.$emit(\"ok\",this.valueFormat?Du(a,this.valueFormat):a)},handleCalendarChange:function(a,o){this.$emit(\"calendarChange\",this.valueFormat?Du(a,this.valueFormat):a,o)},focus:function(){this.picker.focus()},blur:function(){this.picker.blur()},transformValue:function(a){\"value\"in a&&(a.value=rl(a.value,this.valueFormat)),\"defaultValue\"in a&&(a.defaultValue=rl(a.defaultValue,this.valueFormat)),\"defaultPickerValue\"in a&&(a.defaultPickerValue=rl(a.defaultPickerValue,this.valueFormat))},renderPicker:function(a,o){var i,l=P(P({},Qe(this)),this.$attrs);this.transformValue(l);var s=l.prefixCls,c=l.inputPrefixCls,d=l.getCalendarContainer,f=l.size,p=l.showTime,v=l.disabled,m=l.format,y=p?\"\".concat(n,\"Time\"):n,b=m||a[Fxe[y]]||Lxe[y],C=this.configProvider,S=C.getPrefixCls,w=C.getPopupContainer,k=d||w,$=S(\"calendar\",s),O=S(\"input\",c),T=Se(\"\".concat($,\"-picker\"),V({},\"\".concat($,\"-picker-\").concat(f),!!f)),_=Se(\"\".concat($,\"-picker-input\"),O,(i={},V(i,\"\".concat(O,\"-lg\"),f===\"large\"),V(i,\"\".concat(O,\"-sm\"),f===\"small\"),V(i,\"\".concat(O,\"-disabled\"),v),i)),I=p&&p.format||\"HH:mm:ss\",L=P(P({},QD(I)),{format:I,use12Hours:p&&p.use12Hours}),j=Bxe(L),F=\"\".concat($,\"-time-picker-column-\").concat(j),N=P(P(P({},L),p),{prefixCls:\"\".concat($,\"-time-picker\"),placeholder:a.timePickerLocale.placeholder,transitionName:\"slide-up\",class:F,onEsc:function(){}}),D=p?g(JD,N,null):null,z=P(P({},l),{getCalendarContainer:k,format:b,pickerClass:T,pickerInputClass:_,locale:a,localeCode:o,timePicker:D,onOpenChange:this.handleOpenChange,onFocus:this.handleFocus,onBlur:this.handleBlur,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave,onChange:this.handleChange,onOk:this.handleOk,onCalendarChange:this.handleCalendarChange,ref:this.savePicker});return g(e,z,this.$slots)}},render:function(){return g(Kr,{componentName:\"DatePicker\",defaultLocale:this.getDefaultLocale,children:this.renderPicker},null)}})}function Gs(){}var Vxe={name:\"CalendarPart\",inheritAttrs:!1,mixins:[nt],props:{prefixCls:u.string,value:u.any,hoverValue:u.any,selectedValue:u.any,direction:u.any,locale:u.any,showDateInput:u.looseBool,showTimePicker:u.looseBool,showWeekNumber:u.looseBool,format:u.any,placeholder:u.any,disabledDate:u.any,timePicker:u.any,disabledTime:u.any,disabledMonth:u.any,mode:u.any,timePickerDisabledTime:u.object,enableNext:u.any,enablePrev:u.any,clearIcon:u.any,dateRender:u.func,inputMode:u.string,inputReadOnly:u.looseBool},render:function(){var t=this.$props,n=t.prefixCls,r=t.value,a=t.hoverValue,o=t.selectedValue,i=t.mode,l=t.direction,s=t.locale,c=t.format,d=t.placeholder,f=t.disabledDate,p=t.timePicker,v=t.disabledTime,m=t.timePickerDisabledTime,y=t.showTimePicker,b=t.enablePrev,C=t.enableNext,S=t.disabledMonth,w=t.showDateInput,k=t.dateRender,$=t.showWeekNumber,O=t.showClear,T=t.inputMode,_=t.inputReadOnly,I=We(this,\"clearIcon\"),L=this.$attrs,j=L.onInputChange,F=j===void 0?Gs:j,N=L.onInputSelect,D=N===void 0?Gs:N,z=L.onValueChange,B=z===void 0?Gs:z,M=L.onPanelChange,E=M===void 0?Gs:M,K=L.onSelect,W=K===void 0?Gs:K,Y=L.onDayHover,q=Y===void 0?Gs:Y,J=y&&p,ne=J&&v?K2(o,v):null,oe=\"\".concat(n,\"-range\"),Q={locale:s,value:r,prefixCls:n,showTimePicker:y},ae=l===\"left\"?0:1,de=null;if(J){var be=Qe(p);de=Ot(p,P(P(P(P({showHour:!0,showMinute:!0,showSecond:!0},be),ne),m),{defaultOpenValue:r,value:o[ae],onChange:F}))}var Ee=w&&g(qp,{format:c,locale:s,prefixCls:n,timePicker:p,disabledDate:f,placeholder:d,disabledTime:v,value:r,showClear:O||!1,selectedValue:o[ae],onChange:F,onSelect:D,clearIcon:I,inputMode:T,inputReadOnly:_},null),Pe=P(P({},Q),{mode:i,enableNext:C,enablePrev:b,disabledMonth:S,onValueChange:B,onPanelChange:E}),Be=P(P({},Q),{hoverValue:a,selectedValue:o,dateRender:k,disabledDate:f,showWeekNumber:$,onSelect:W,onDayHover:q});return g(\"div\",{class:\"\".concat(oe,\"-part \").concat(oe,\"-\").concat(l)},[Ee,g(\"div\",{style:{outline:\"none\"}},[g(aS,Pe,null),y?g(\"div\",{class:\"\".concat(n,\"-time-picker\")},[g(\"div\",{class:\"\".concat(n,\"-time-picker-panel\")},[de])]):null,g(\"div\",{class:\"\".concat(n,\"-body\")},[g(W2,Be,null)])])])}},ST=Vxe;function Vh(){}function zxe(e){return Array.isArray(e)&&(e.length===0||e.every(function(t){return!t}))}function kT(e,t){if(e===t)return!0;if(e===null||typeof e==\"undefined\"||t===null||typeof t==\"undefined\"||e.length!==t.length)return!1;for(var n=0;n<e.length;++n)if(e[n]!==t[n])return!1;return!0}function C1(e){var t=fn(e,2),n=t[0],r=t[1];return r&&n==null&&(n=r.clone().subtract(1,\"month\")),n&&r==null&&(r=n.clone().add(1,\"month\")),[n,r]}function $T(e,t){var n=e.selectedValue||t&&e.defaultSelectedValue,r=e.value||t&&e.defaultValue,a=C1(r||n);return zxe(a)?t&&[Ue(),Ue().add(1,\"months\")]:a}function ib(e,t){for(var n=t?t().concat():[],r=0;r<e;r++)n.indexOf(r)===-1&&n.push(r);return n}function zh(e,t,n){if(!!t){var r=this.sSelectedValue,a=r.concat(),o=e===\"left\"?0:1;a[o]=t,a[0]&&this.compare(a[0],a[1])>0&&(a[1-o]=this.sShowTimePicker?a[o]:void 0),this.__emit(\"inputSelect\",a),this.fireSelectValueChange(a,null,n||{source:\"dateInput\"})}}var Hxe=G({name:\"RangeCalendar\",mixins:[nt,$g],inheritAttrs:!1,props:{locale:u.object.def(Nf),visible:u.looseBool.def(!0),prefixCls:u.string.def(\"rc-calendar\"),dateInputPlaceholder:u.any,seperator:u.string.def(\"~\"),defaultValue:u.any,value:u.any,hoverValue:u.any,mode:u.arrayOf(u.oneOf([\"time\",\"date\",\"month\",\"year\",\"decade\"])),showDateInput:u.looseBool.def(!0),timePicker:u.any,showOk:u.looseBool,showToday:u.looseBool.def(!0),defaultSelectedValue:u.array.def([]),selectedValue:u.array,showClear:u.looseBool,showWeekNumber:u.looseBool,format:u.oneOfType([u.string,u.arrayOf(u.string),u.func]),type:u.any.def(\"both\"),disabledDate:u.func,disabledTime:u.func.def(Vh),renderFooter:u.func.def(function(){return null}),renderSidebar:u.func.def(function(){return null}),dateRender:u.func,clearIcon:u.any,inputReadOnly:u.looseBool},data:function(){var t=this.$props,n=t.selectedValue||t.defaultSelectedValue,r=$T(t,1);return{sSelectedValue:n,prevSelectedValue:n,firstSelectedValue:null,sHoverValue:t.hoverValue||[],sValue:r,sShowTimePicker:!1,sMode:t.mode||[\"date\",\"date\"],sPanelTriggerSource:\"\"}},watch:{value:function(){var t={};t.sValue=$T(this.$props,0),this.setState(t)},hoverValue:function(t){kT(this.sHoverValue,t)||this.setState({sHoverValue:t})},selectedValue:function(t){var n={};n.sSelectedValue=t,n.prevSelectedValue=t,this.setState(n)},mode:function(t){kT(this.sMode,t)||this.setState({sMode:t})}},methods:{onDatePanelEnter:function(){this.hasSelectedValue()&&this.fireHoverValueChange(this.sSelectedValue.concat())},onDatePanelLeave:function(){this.hasSelectedValue()&&this.fireHoverValueChange([])},onSelect:function(t){var n=this.type,r=this.sSelectedValue,a=this.prevSelectedValue,o=this.firstSelectedValue,i;if(n===\"both\")o?this.compare(o,t)<0?(Sa(a[1],t),i=[o,t]):(Sa(a[0],t),Sa(a[1],o),i=[t,o]):(Sa(a[0],t),i=[t]);else if(n===\"start\"){Sa(a[0],t);var l=r[1];i=l&&this.compare(l,t)>0?[t,l]:[t]}else{var s=r[0];s&&this.compare(s,t)<=0?(Sa(a[1],t),i=[s,t]):(Sa(a[0],t),i=[t])}this.fireSelectValueChange(i)},onKeyDown:function(t){var n=this;if(t.target.nodeName.toLowerCase()!==\"input\"){var r=t.keyCode,a=t.ctrlKey||t.metaKey,o=this.$data,i=o.sSelectedValue,l=o.sHoverValue,s=o.firstSelectedValue,c=o.sValue,d=this.$props.disabledDate,f=function(m){var y,b,C;if(s?l.length===1?(y=l[0].clone(),b=m(y),C=n.onDayHover(b)):(y=l[0].isSame(s,\"day\")?l[1]:l[0],b=m(y),C=n.onDayHover(b)):(y=l[0]||i[0]||c[0]||Ue(),b=m(y),C=[b],n.fireHoverValueChange(C)),C.length>=2){var S=C.some(function(O){return!sxe(c,O,\"month\")});if(S){var w=C.slice().sort(function(O,T){return O.valueOf()-T.valueOf()});w[0].isSame(w[1],\"month\")&&(w[1]=w[0].clone().add(1,\"month\")),n.fireValueChange(w)}}else if(C.length===1){var k=c.findIndex(function(O){return O.isSame(y,\"month\")});if(k===-1&&(k=0),c.every(function(O){return!O.isSame(b,\"month\")})){var $=c.slice();$[k]=b.clone(),n.fireValueChange($)}}return t.preventDefault(),b};switch(r){case ze.DOWN:f(function(v){return ei(v,1,\"weeks\")});return;case ze.UP:f(function(v){return ei(v,-1,\"weeks\")});return;case ze.LEFT:f(a?function(v){return ei(v,-1,\"years\")}:function(v){return ei(v,-1,\"days\")});return;case ze.RIGHT:f(a?function(v){return ei(v,1,\"years\")}:function(v){return ei(v,1,\"days\")});return;case ze.HOME:f(function(v){return UD(v)});return;case ze.END:f(function(v){return YD(v)});return;case ze.PAGE_DOWN:f(function(v){return ei(v,1,\"month\")});return;case ze.PAGE_UP:f(function(v){return ei(v,-1,\"month\")});return;case ze.ENTER:{var p;l.length===0?p=f(function(v){return v}):l.length===1?p=l[0]:p=l[0].isSame(s,\"day\")?l[1]:l[0],p&&(!d||!d(p))&&this.onSelect(p),t.preventDefault();return}default:this.__emit(\"keydown\",t)}}},onDayHover:function(t){var n=[],r=this.sSelectedValue,a=this.firstSelectedValue,o=this.type;if(o===\"start\"&&r[1])n=this.compare(t,r[1])<0?[t,r[1]]:[t];else if(o===\"end\"&&r[0])n=this.compare(t,r[0])>0?[r[0],t]:[];else{if(!a)return this.sHoverValue.length&&this.setState({sHoverValue:[]}),n;n=this.compare(t,a)<0?[t,a]:[a,t]}return this.fireHoverValueChange(n),n},onToday:function(){var t=hl(this.sValue[0]),n=t.clone().add(1,\"months\");this.setState({sValue:[t,n]})},onOpenTimePicker:function(){this.setState({sShowTimePicker:!0})},onCloseTimePicker:function(){this.setState({sShowTimePicker:!1})},onOk:function(){var t=this.sSelectedValue;this.isAllowedDateAndTime(t)&&this.__emit(\"ok\",t)},onStartInputChange:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];var a=[\"left\"].concat(n);return zh.apply(this,a)},onEndInputChange:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];var a=[\"right\"].concat(n);return zh.apply(this,a)},onStartInputSelect:function(t){var n=[\"left\",t,{source:\"dateInputSelect\"}];return zh.apply(this,n)},onEndInputSelect:function(t){var n=[\"right\",t,{source:\"dateInputSelect\"}];return zh.apply(this,n)},onStartValueChange:function(t){var n=Je(this.sValue);return n[0]=t,this.fireValueChange(n)},onEndValueChange:function(t){var n=Je(this.sValue);return n[1]=t,this.fireValueChange(n)},onStartPanelChange:function(t,n){var r=this.sMode,a=this.sValue,o=[n,r[1]],i=[t||a[0],a[1]];this.__emit(\"panelChange\",i,o);var l={sPanelTriggerSource:\"start\"};vt(this,\"mode\")||(l.sMode=o),this.setState(l)},onEndPanelChange:function(t,n){var r=this.sMode,a=this.sValue,o=[r[0],n],i=[a[0],t||a[1]];this.__emit(\"panelChange\",i,o);var l={sPanelTriggerSource:\"end\"};vt(this,\"mode\")||(l.sMode=o),this.setState(l)},getStartValue:function(){var t=this.$data,n=t.sSelectedValue,r=t.sShowTimePicker,a=t.sValue,o=t.sMode,i=t.sPanelTriggerSource,l=a[0];return n[0]&&this.$props.timePicker&&(l=l.clone(),Sa(n[0],l)),r&&n[0]&&(l=n[0]),i===\"end\"&&o[0]===\"date\"&&o[1]===\"date\"&&l.isSame(a[1],\"month\")&&(l=l.clone().subtract(1,\"month\")),l},getEndValue:function(){var t=this.$data,n=t.sSelectedValue,r=t.sShowTimePicker,a=t.sValue,o=t.sMode,i=t.sPanelTriggerSource,l=a[1]?a[1].clone():a[0].clone().add(1,\"month\");return n[1]&&this.$props.timePicker&&Sa(n[1],l),r&&(l=n[1]?n[1]:this.getStartValue()),!r&&i!==\"end\"&&o[0]===\"date\"&&o[1]===\"date\"&&l.isSame(a[0],\"month\")&&(l=l.clone().add(1,\"month\")),l},getEndDisableTime:function(){var t=this.sSelectedValue,n=this.sValue,r=this.disabledTime,a=r(t,\"end\")||{},o=t&&t[0]||n[0].clone();if(!t[1]||o.isSame(t[1],\"day\")){var i=o.hour(),l=o.minute(),s=o.second(),c=a.disabledHours,d=a.disabledMinutes,f=a.disabledSeconds,p=d?d():[],v=f?f():[];return c=ib(i,c),d=ib(l,d),f=ib(s,f),{disabledHours:function(){return c},disabledMinutes:function(y){return y===i?d:p},disabledSeconds:function(y,b){return y===i&&b===l?f:v}}}return a},isAllowedDateAndTime:function(t){return Xv(t[0],this.disabledDate,this.disabledStartTime)&&Xv(t[1],this.disabledDate,this.disabledEndTime)},isMonthYearPanelShow:function(t){return[\"month\",\"year\",\"decade\"].indexOf(t)>-1},hasSelectedValue:function(){var t=this.sSelectedValue;return!!t[1]&&!!t[0]},compare:function(t,n){return this.timePicker?t.diff(n):t.diff(n,\"days\")},fireSelectValueChange:function(t,n,r){var a=this.timePicker,o=this.prevSelectedValue;if(a){var i=Qe(a);if(i.defaultValue){var l=i.defaultValue;!o[0]&&t[0]&&Sa(l[0],t[0]),!o[1]&&t[1]&&Sa(l[1],t[1])}}if(!this.sSelectedValue[0]||!this.sSelectedValue[1]){var s=t[0]||Ue(),c=t[1]||s.clone().add(1,\"months\");this.setState({sSelectedValue:t,sValue:t&&t.length===2?C1([s,c]):this.sValue})}t[0]&&!t[1]&&(this.setState({firstSelectedValue:t[0]}),this.fireHoverValueChange(t.concat())),this.__emit(\"change\",t),(n||t[0]&&t[1])&&(this.setState({prevSelectedValue:t,firstSelectedValue:null}),this.fireHoverValueChange([]),this.__emit(\"select\",t,r)),vt(this,\"selectedValue\")||this.setState({sSelectedValue:t})},fireValueChange:function(t){vt(this,\"value\")||this.setState({sValue:t}),this.__emit(\"valueChange\",t)},fireHoverValueChange:function(t){vt(this,\"hoverValue\")||this.setState({sHoverValue:t}),this.__emit(\"hoverChange\",t)},clear:function(){this.fireSelectValueChange([],!0),this.__emit(\"clear\")},disabledStartTime:function(t){return this.disabledTime(t,\"start\")},disabledEndTime:function(t){return this.disabledTime(t,\"end\")},disabledStartMonth:function(t){var n=this.sValue;return t.isAfter(n[1],\"month\")},disabledEndMonth:function(t){var n=this.sValue;return t.isBefore(n[0],\"month\")}},render:function(){var t,n,r=Qe(this),a=r.prefixCls,o=r.dateInputPlaceholder,i=r.timePicker,l=r.showOk,s=r.locale,c=r.showClear,d=r.showToday,f=r.type,p=r.seperator,v=We(this,\"clearIcon\"),m=this.sHoverValue,y=this.sSelectedValue,b=this.sMode,C=this.sShowTimePicker,S=this.sValue,w=(t={},V(t,this.$attrs.class,!!this.$attrs.class),V(t,a,1),V(t,\"\".concat(a,\"-hidden\"),!r.visible),V(t,\"\".concat(a,\"-range\"),1),V(t,\"\".concat(a,\"-show-time-picker\"),C),V(t,\"\".concat(a,\"-week-number\"),r.showWeekNumber),t),k=P(P({},r),this.$attrs),$={selectedValue:y,onSelect:this.onSelect,onDayHover:f===\"start\"&&y[1]||f===\"end\"&&y[0]||!!m.length?this.onDayHover:Vh},O,T;if(o)if(Array.isArray(o)){var _=fn(o,2);O=_[0],T=_[1]}else O=T=o;var I=l===!0||l!==!1&&!!i,L=(n={},V(n,\"\".concat(a,\"-footer\"),!0),V(n,\"\".concat(a,\"-range-bottom\"),!0),V(n,\"\".concat(a,\"-footer-show-ok\"),I),n),j=this.getStartValue(),F=this.getEndValue(),N=hl(j),D=N.month(),z=N.year(),B=j.year()===z&&j.month()===D||F.year()===z&&F.month()===D,M=j.clone().add(1,\"months\"),E=M.year()===F.year()&&M.month()===F.month(),K=P(P(P({},k),$),{hoverValue:m,direction:\"left\",disabledTime:this.disabledStartTime,disabledMonth:this.disabledStartMonth,format:this.getFormat(),value:j,mode:b[0],placeholder:O,showDateInput:this.showDateInput,timePicker:i,showTimePicker:C||b[0]===\"time\",enablePrev:!0,enableNext:!E||this.isMonthYearPanelShow(b[1]),clearIcon:v,onInputChange:this.onStartInputChange,onInputSelect:this.onStartInputSelect,onValueChange:this.onStartValueChange,onPanelChange:this.onStartPanelChange}),W=P(P(P({},k),$),{hoverValue:m,direction:\"right\",format:this.getFormat(),timePickerDisabledTime:this.getEndDisableTime(),placeholder:T,value:F,mode:b[1],showDateInput:this.showDateInput,timePicker:i,showTimePicker:C||b[1]===\"time\",disabledTime:this.disabledEndTime,disabledMonth:this.disabledEndMonth,enablePrev:!E||this.isMonthYearPanelShow(b[0]),enableNext:!0,clearIcon:v,onInputChange:this.onEndInputChange,onInputSelect:this.onEndInputSelect,onValueChange:this.onEndValueChange,onPanelChange:this.onEndPanelChange}),Y=null;if(d){var q=P(P({},k),{disabled:B,value:S[0],text:s.backToToday,onToday:this.onToday});Y=g(VD,le({key:\"todayButton\"},q),null)}var J=null;if(r.timePicker){var ne=P(P({},k),{showTimePicker:C||b[0]===\"time\"&&b[1]===\"time\",timePickerDisabled:!this.hasSelectedValue()||m.length,onOpenTimePicker:this.onOpenTimePicker,onCloseTimePicker:this.onCloseTimePicker});J=g(KD,le({key:\"timePickerButton\"},ne),null)}var oe=null;if(I){var Q=P(P({},k),{okDisabled:!this.isAllowedDateAndTime(y)||!this.hasSelectedValue()||m.length,onOk:this.onOk});oe=g(HD,le({key:\"okButtonNode\"},Q),null)}var ae=this.renderFooter(b);return g(\"div\",{ref:\"rootInstance\",class:w,tabindex:\"0\",onKeydown:this.onKeyDown},[r.renderSidebar(),g(\"div\",{class:\"\".concat(a,\"-panel\")},[c&&y[0]&&y[1]?g(\"a\",{role:\"button\",title:s.clear,onClick:this.clear},[v||g(\"span\",{class:\"\".concat(a,\"-clear-btn\")},null)]):null,g(\"div\",{class:\"\".concat(a,\"-date-panel\"),onMouseleave:f!==\"both\"?this.onDatePanelLeave:Vh,onMouseenter:f!==\"both\"?this.onDatePanelEnter:Vh},[g(ST,K,null),g(\"span\",{class:\"\".concat(a,\"-range-middle\")},[p]),g(ST,W,null)]),g(\"div\",{class:L},[d||r.timePicker||I||ae?g(\"div\",{class:\"\".concat(a,\"-footer-btn\")},[ae,Y,J,oe]):null])])])}}),jxe=Hxe,Kxe=G({name:\"ACheckableTag\",props:{prefixCls:u.string,checked:u.looseBool,onChange:{type:Function},onClick:{type:Function}},emits:[\"update:checked\",\"change\",\"click\"],setup:function(t,n){var r=n.slots,a=n.emit,o=Wt(\"tag\",t),i=o.prefixCls,l=function(d){var f=t.checked;a(\"update:checked\",!f),a(\"change\",!f),a(\"click\",d)},s=x(function(){var c;return Se(i.value,(c={},V(c,\"\".concat(i.value,\"-checkable\"),!0),V(c,\"\".concat(i.value,\"-checkable-checked\"),t.checked),c))});return function(){var c;return g(\"span\",{class:s.value,onClick:l},[(c=r.default)===null||c===void 0?void 0:c.call(r)])}}}),lm=Kxe,Wxe=new RegExp(\"^(\".concat(B2.join(\"|\"),\")(-inverse)?$\")),Uxe=new RegExp(\"^(\".concat(iOe.join(\"|\"),\")$\")),Yxe={prefixCls:u.string,color:{type:String},closable:u.looseBool.def(!1),closeIcon:u.VNodeChild,visible:u.looseBool,onClose:{type:Function},icon:u.VNodeChild},Td=G({name:\"ATag\",props:Yxe,emits:[\"update:visible\",\"close\"],slots:[\"closeIcon\",\"icon\"],setup:function(t,n){var r=n.slots,a=n.emit,o=n.attrs,i=Wt(\"tag\",t),l=i.prefixCls,s=i.direction,c=H(!0);Wn(function(){t.visible!==void 0&&(c.value=t.visible)});var d=function(m){m.stopPropagation(),a(\"update:visible\",!1),a(\"close\",m),!m.defaultPrevented&&t.visible===void 0&&(c.value=!1)},f=x(function(){var v=t.color;return v?Wxe.test(v)||Uxe.test(v):!1}),p=x(function(){var v;return Se(l.value,(v={},V(v,\"\".concat(l.value,\"-\").concat(t.color),f.value),V(v,\"\".concat(l.value,\"-has-color\"),t.color&&!f.value),V(v,\"\".concat(l.value,\"-hidden\"),!c.value),V(v,\"\".concat(l.value,\"-rtl\"),s.value===\"rtl\"),v))});return function(){var v,m,y,b=t.icon,C=b===void 0?(v=r.icon)===null||v===void 0?void 0:v.call(r):b,S=t.color,w=t.closeIcon,k=w===void 0?(m=r.closeIcon)===null||m===void 0?void 0:m.call(r):w,$=t.closable,O=$===void 0?!1:$,T=function(){return O?k?g(\"div\",{class:\"\".concat(l.value,\"-close-icon\"),onClick:d},[k]):g(go,{class:\"\".concat(l.value,\"-close-icon\"),onClick:d},null):null},_={backgroundColor:S&&!f.value?S:void 0},I=C||null,L=(y=r.default)===null||y===void 0?void 0:y.call(r),j=I?g(Fe,null,[I,g(\"span\",null,[L])]):L,F=\"onClick\"in o,N=g(\"span\",{class:p.value,style:_},[j,T()]);return F?g(C2,null,{default:function(){return[N]}}):N}}});Td.CheckableTag=lm;Td.install=function(e){return e.component(Td.name,Td),e.component(lm.name,lm),e};var e7=Td,_g={name:u.string,transitionName:u.string,prefixCls:u.string,inputPrefixCls:u.string,format:u.oneOfType([u.string,u.array,u.func]),disabled:u.looseBool,allowClear:u.looseBool,suffixIcon:u.any,popupStyle:u.object,dropdownClassName:u.string,locale:u.any,localeCode:u.string,size:u.oneOf(rt(\"large\",\"small\",\"default\")),getCalendarContainer:u.func,open:u.looseBool,disabledDate:u.func,showToday:u.looseBool,dateRender:u.any,pickerClass:u.string,pickerInputClass:u.string,timePicker:u.any,autofocus:u.looseBool,tagPrefixCls:u.string,tabindex:u.oneOfType([u.string,u.number]),align:u.object.def(function(){return{}}),inputReadOnly:u.looseBool,valueFormat:u.string,onOpenChange:u.func,onFocus:u.func,onBlur:u.func,onMouseenter:u.func,onMouseleave:u.func},sS={value:{type:[String,Object]},defaultValue:{type:[String,Object]},defaultPickerValue:{type:[String,Object]},renderExtraFooter:u.any,placeholder:u.string,onChange:u.func},OT=P(P(P({},_g),sS),{showTime:an(u.oneOfType([u.object,u.looseBool])),open:u.looseBool,disabledTime:u.func,mode:u.oneOf(rt(\"time\",\"date\",\"month\",\"year\",\"decade\")),onOpenChange:u.func,onPanelChange:u.func,onOk:u.func}),PT=P(P(P({},_g),sS),{placeholder:u.string,monthCellContentRender:u.func}),t7=P(P({},_g),{tagPrefixCls:u.string,value:{type:Array},defaultValue:{type:Array},defaultPickerValue:{type:Array},timePicker:u.any,showTime:an(u.oneOfType([u.object,u.looseBool])),ranges:u.object,placeholder:u.arrayOf(String),mode:u.oneOfType([u.string,u.arrayOf(String)]),separator:u.any,disabledTime:u.func,showToday:u.looseBool,renderExtraFooter:u.any,onChange:u.func,onCalendarChange:u.func,onOk:u.func,onPanelChange:u.func,onMouseenter:u.func,onMouseleave:u.func}),n7=P(P(P({},_g),sS),{placeholder:u.string}),r7=function(t,n){var r,a=n.attrs,o,i,l=a.suffixIcon,s=a.prefixCls;return(l&&zn(l)?Ot(l,{class:Se((r={},V(r,(o=l.props)===null||o===void 0?void 0:o.class,(i=l.props)===null||i===void 0?void 0:i.class),V(r,\"\".concat(s,\"-picker-icon\"),!0),r))}):g(\"span\",{class:\"\".concat(s,\"-picker-icon\")},[l]))||g(XD,{class:\"\".concat(s,\"-picker-icon\")},null)};r7.inheritAttrs=!1;var a7=r7;function lb(e,t){var n=fn(e,2),r=n[0],a=n[1];if(!(!r&&!a)){if(t&&t[0]===\"month\")return[r,a];var o=a&&a.isSame(r,\"month\")?a.clone().add(1,\"month\"):a;return[r,o]}}function qxe(e){if(!!e)return Array.isArray(e)?e:[e,e.clone().add(1,\"month\")]}function Gxe(e){return Array.isArray(e)?e.length===0||e.every(function(t){return!t}):!1}function TT(e,t){if(!!t&&!(!e||e.length===0)){var n=fn(e,2),r=n[0],a=n[1];r&&r.locale(t),a&&a.locale(t)}}var Xxe=G({name:\"ARangePicker\",mixins:[nt],inheritAttrs:!1,props:Rn(t7,{allowClear:!0,showToday:!1,separator:\"~\"}),setup:function(){return{configProvider:ve(\"configProvider\",St),picker:null,sTagPrefixCls:void 0,sPrefixCls:\"\"}},data:function(){var t=this.value||this.defaultValue||[],n=fn(t,2),r=n[0],a=n[1];if(r&&!Hr(Ue).isMoment(r)||a&&!Hr(Ue).isMoment(a))throw new Error(\"The value/defaultValue of RangePicker must be a moment object array after `antd@2.0`, see: https://u.ant.design/date-picker-value\");var o=!t||Gxe(t)?this.defaultPickerValue:t;return{sValue:t,sShowDate:qxe(o||Hr(Ue)()),sOpen:this.open,sHoverValue:[]}},watch:{value:function(t){var n=t||[],r={sValue:n};Mr(t,this.sValue)||(r=P(P({},r),{sShowDate:lb(n,this.mode)||this.sShowDate})),this.setState(r)},open:function(t){var n={sOpen:t};this.setState(n)},sOpen:function(t,n){var r=this;Ne(function(){!vt(r,\"open\")&&n&&!t&&r.focus()})}},methods:{setValue:function(t,n){this.handleChange(t),(n||!this.showTime)&&!vt(this,\"open\")&&this.setState({sOpen:!1})},savePicker:function(t){this.picker=t},clearSelection:function(t){t.preventDefault(),t.stopPropagation(),this.setState({sValue:[]}),this.handleChange([])},clearHoverValue:function(){this.setState({sHoverValue:[]})},handleChange:function(t){vt(this,\"value\")||this.setState(function(o){var i=o.sShowDate;return{sValue:t,sShowDate:lb(t)||i}}),t[0]&&t[1]&&t[0].diff(t[1])>0&&(t[1]=void 0);var n=fn(t,2),r=n[0],a=n[1];this.$emit(\"change\",t,[Cu(r,this.format),Cu(a,this.format)])},handleOpenChange:function(t){vt(this,\"open\")||this.setState({sOpen:t}),t===!1&&this.clearHoverValue(),this.$emit(\"openChange\",t)},handleShowDateChange:function(t){this.setState({sShowDate:t})},handleHoverChange:function(t){this.setState({sHoverValue:t})},handleRangeMouseLeave:function(){this.sOpen&&this.clearHoverValue()},handleCalendarInputSelect:function(t){var n=fn(t,1),r=n[0];!r||this.setState(function(a){var o=a.sShowDate;return{sValue:t,sShowDate:lb(t)||o}})},handleRangeClick:function(t){typeof t==\"function\"&&(t=t()),this.setValue(t,!0),this.$emit(\"ok\",t),this.$emit(\"openChange\",!1)},onMouseEnter:function(t){this.$emit(\"mouseenter\",t)},onMouseLeave:function(t){this.$emit(\"mouseleave\",t)},focus:function(){this.picker.focus()},blur:function(){this.picker.blur()},renderFooter:function(){var t=this,n=this.ranges,r=this.$slots,a=this.sPrefixCls,o=this.sTagPrefixCls,i=this.renderExtraFooter||r.renderExtraFooter;if(!n&&!i)return null;var l=i?g(\"div\",{class:\"\".concat(a,\"-footer-extra\"),key:\"extra\"},[typeof i==\"function\"?i():i]):null,s=n&&Object.keys(n).map(function(d){var f=n[d],p=typeof f==\"function\"?f.call(t):f;return g(e7,{key:d,prefixCls:o,color:\"blue\",onClick:function(){return t.handleRangeClick(f)},onMouseenter:function(){return t.setState({sHoverValue:p})},onMouseleave:t.handleRangeMouseLeave},{default:function(){return[d]}})}),c=s&&s.length>0?g(\"div\",{class:\"\".concat(a,\"-footer-extra \").concat(a,\"-range-quick-selector\"),key:\"range\"},[s]):null;return[c,l]}},render:function(){var t,n=this,r=P(P({},Qe(this)),this.$attrs),a=We(this,\"suffixIcon\");a=Array.isArray(a)?a[0]:a;var o=this.sValue,i=this.sShowDate,l=this.sHoverValue,s=this.sOpen,c=this.$slots,d=r.prefixCls,f=r.tagPrefixCls,p=r.popupStyle,v=r.disabledDate,m=r.disabledTime,y=r.showTime,b=r.showToday,C=r.ranges,S=r.locale,w=r.localeCode,k=r.format,$=r.separator,O=r.inputReadOnly,T=r.style,_=r.onCalendarChange,I=r.onOk,L=r.onBlur,j=r.onFocus,F=r.onPanelChange,N=this.configProvider.getPrefixCls,D=N(\"calendar\",d),z=N(\"tag\",f);this.sPrefixCls=D,this.sTagPrefixCls=z;var B=r.dateRender||c.dateRender;TT(o,w),TT(i,w);var M=Se((t={},V(t,\"\".concat(D,\"-time\"),y),V(t,\"\".concat(D,\"-range-with-ranges\"),C),t)),E={onChange:this.handleChange},K={onOk:this.handleChange};r.timePicker?E.onChange=function(Be){return n.handleChange(Be)}:K={},\"mode\"in r&&(K.mode=r.mode);var W=Array.isArray(r.placeholder)?r.placeholder[0]:S.lang.rangePlaceholder[0],Y=Array.isArray(r.placeholder)?r.placeholder[1]:S.lang.rangePlaceholder[1],q=P(P({},K),{separator:$,format:k,prefixCls:D,renderFooter:this.renderFooter,timePicker:r.timePicker,disabledDate:v,disabledTime:m,dateInputPlaceholder:[W,Y],locale:S.lang,dateRender:B,value:i,hoverValue:l,showToday:b,inputReadOnly:O,onChange:_,onOk:I,onValueChange:this.handleShowDateChange,onHoverChange:this.handleHoverChange,onPanelChange:F,onInputSelect:this.handleCalendarInputSelect,class:M}),J=g(jxe,q,c),ne={};r.showTime&&(ne.width=\"350px\");var oe=fn(o,2),Q=oe[0],ae=oe[1],de=!r.disabled&&r.allowClear&&o&&(Q||ae)?g(Yr,{class:\"\".concat(D,\"-picker-clear\"),onClick:this.clearSelection},null):null,be=g(a7,{suffixIcon:a,prefixCls:D},null),Ee=function(te){var ie=te.value,ge=fn(ie,2),ke=ge[0],xe=ge[1];return g(\"span\",{class:r.pickerInputClass},[g(\"input\",{disabled:r.disabled,readonly:!0,value:Cu(ke,r.format),placeholder:W,class:\"\".concat(D,\"-range-picker-input\"),tabindex:-1},null),g(\"span\",{class:\"\".concat(D,\"-range-picker-separator\")},[yt(\" \"),$,yt(\" \")]),g(\"input\",{disabled:r.disabled,readonly:!0,value:Cu(xe,r.format),placeholder:Y,class:\"\".concat(D,\"-range-picker-input\"),tabindex:-1},null),de,be])},Pe=P(P(P({},r),E),{calendar:J,value:o,open:s,prefixCls:\"\".concat(D,\"-picker-container\"),onOpenChange:this.handleOpenChange,style:p});return g(\"span\",le({ref:this.savePicker,id:r.id,class:Se(r.class,r.pickerClass),style:P(P({},ne),T),tabindex:r.disabled?-1:0,onFocus:j,onBlur:L,onMouseenter:this.onMouseEnter,onMouseleave:this.onMouseLeave},eg(r)),[g(oS,Pe,P({default:Ee},c))])}});function Zxe(e,t){return e&&e.format(t)||\"\"}function xT(){}var Jxe=G({name:\"AWeekPicker\",mixins:[nt],inheritAttrs:!1,props:Rn(n7,{allowClear:!0}),setup:function(){return{configProvider:ve(\"configProvider\",St),prevState:{},input:void 0,sPrefixCls:void 0}},data:function(){var t=this.value||this.defaultValue;if(t&&!Hr(Ue).isMoment(t))throw new Error(\"The value/defaultValue of WeekPicker or MonthPicker must be a moment object\");return{_value:t,_open:this.open}},watch:{value:function(t){var n={_value:t};this.setState(n),this.prevState=P(P({},this.$data),n)},open:function(t){var n={_open:t};this.setState(n),this.prevState=P(P({},this.$data),n)},_open:function(t,n){var r=this;Ne(function(){!vt(r,\"open\")&&n&&!t&&r.focus()})}},mounted:function(){this.prevState=P({},this.$data)},updated:function(){var t=this;Ne(function(){!vt(t,\"open\")&&t.prevState._open&&!t._open&&t.focus()})},methods:{saveInput:function(t){this.input=t},weekDateRender:function(t){var n=t.current,r=this.$data._value,a=this.sPrefixCls,o=this.$slots,i=this.dateRender||o.dateRender,l=i?i({current:n}):n.date();return r&&n.year()===r.year()&&n.week()===r.week()?g(\"div\",{class:\"\".concat(a,\"-selected-day\")},[g(\"div\",{class:\"\".concat(a,\"-date\")},[l])]):g(\"div\",{class:\"\".concat(a,\"-date\")},[l])},handleChange:function(t){vt(this,\"value\")||this.setState({_value:t}),this.$emit(\"change\",t,Zxe(t,this.format))},handleOpenChange:function(t){vt(this,\"open\")||this.setState({_open:t}),this.$emit(\"openChange\",t)},clearSelection:function(t){t.preventDefault(),t.stopPropagation(),this.handleChange(null)},focus:function(){this.input.focus()},blur:function(){this.input.blur()},renderFooter:function(){var t=this.sPrefixCls,n=this.$slots,r=this.renderExtraFooter||n.renderExtraFooter;return r?g(\"div\",{class:\"\".concat(t,\"-footer-extra\")},[r.apply(void 0,arguments)]):null}},render:function(){var t=this,n=P(P({},Qe(this)),this.$attrs),r=We(this,\"suffixIcon\");r=Array.isArray(r)?r[0]:r;var a=this.prefixCls,o=this.disabled,i=this.pickerClass,l=this.popupStyle,s=this.pickerInputClass,c=this.format,d=this.allowClear,f=this.locale,p=this.localeCode,v=this.disabledDate,m=this.defaultPickerValue,y=this.$data,b=this.$slots,C=this.configProvider.getPrefixCls,S=C(\"calendar\",a);this.sPrefixCls=S;var w=y._value,k=y._open,$=n.class,O=n.style,T=n.id,_=n.onFocus,I=_===void 0?xT:_,L=n.onBlur,j=L===void 0?xT:L;w&&p&&w.locale(p);var F=vt(this,\"placeholder\")?this.placeholder:f.lang.placeholder,N=this.dateRender||b.dateRender||this.weekDateRender,D=g(qD,{showWeekNumber:!0,dateRender:N,prefixCls:S,format:c,locale:f.lang,showDateInput:!1,showToday:!1,disabledDate:v,renderFooter:this.renderFooter,defaultValue:m},null),z=!o&&d&&y._value?g(Yr,{class:\"\".concat(S,\"-picker-clear\"),onClick:this.clearSelection},null):null,B=g(a7,{suffixIcon:r,prefixCls:S},null),M=function(W){var Y=W.value;return g(\"span\",{style:{display:\"inline-block\",width:\"100%\"}},[g(\"input\",{ref:t.saveInput,disabled:o,readonly:!0,value:Y&&Y.format(c)||\"\",placeholder:F,class:s,onFocus:I,onBlur:j},null),z,B])},E=P(P({},n),{calendar:D,prefixCls:\"\".concat(S,\"-picker-container\"),value:w,open:k,onChange:this.handleChange,onOpenChange:this.handleOpenChange,style:l});return g(\"span\",le({class:Se($,i),style:O,id:T},eg(n)),[g(oS,E,P({default:M},b))])}}),o7=xg(Xxe,t7,\"date\"),i7=xg(Jxe,n7,\"week\"),Ya=xg(ZD(qD,OT,\"ADatePicker\"),OT,\"date\"),l7=xg(ZD(GD,PT,\"AMonthPicker\"),PT,\"month\");P(Ya,{RangePicker:o7,MonthPicker:l7,WeekPicker:i7});Ya.install=function(e){return e.component(Ya.name,Ya),e.component(Ya.RangePicker.name,Ya.RangePicker),e.component(Ya.MonthPicker.name,Ya.MonthPicker),e.component(Ya.WeekPicker.name,Ya.WeekPicker),e};var Qxe=Ya;function Hh(e){return e!=null}var e_e=function(t){var n=t.itemPrefixCls,r=t.component,a=t.span,o=t.labelStyle,i=t.contentStyle,l=t.bordered,s=t.label,c=t.content,d=t.colon,f=r;if(l){var p;return g(f,{class:[(p={},V(p,\"\".concat(n,\"-item-label\"),Hh(s)),V(p,\"\".concat(n,\"-item-content\"),Hh(c)),p)],colSpan:a},{default:function(){return[Hh(s)&&g(\"span\",{style:o},[s]),Hh(c)&&g(\"span\",{style:i},[c])]}})}return g(f,{class:[\"\".concat(n,\"-item\")],colSpan:a},{default:function(){return[g(\"div\",{class:\"\".concat(n,\"-item-container\")},[s&&g(\"span\",{class:[\"\".concat(n,\"-item-label\"),V({},\"\".concat(n,\"-item-no-colon\"),!d)],style:o},[s]),c&&g(\"span\",{class:\"\".concat(n,\"-item-content\"),style:i},[c])])]}})},sb=e_e,t_e=function(t){var n=function(p,v,m){var y=v.colon,b=v.prefixCls,C=v.bordered,S=m.component,w=m.type,k=m.showLabel,$=m.showContent,O=m.labelStyle,T=m.contentStyle;return p.map(function(_,I){var L,j,F=_.props||{},N=F.prefixCls,D=N===void 0?b:N,z=F.span,B=z===void 0?1:z,M=F.labelStyle,E=F.contentStyle,K=F.label,W=K===void 0?(j=(L=_.children)===null||L===void 0?void 0:L.label)===null||j===void 0?void 0:j.call(L):K,Y=ht(_),q=o0e(_),J=qI(_),ne=_.key;return typeof S==\"string\"?g(sb,{key:\"\".concat(w,\"-\").concat(String(ne)||I),class:q,style:J,labelStyle:P(P({},O.value),M),contentStyle:P(P({},T.value),E),span:B,colon:y,component:S,itemPrefixCls:D,bordered:C,label:k?W:null,content:$?Y:null},null):[g(sb,{key:\"label-\".concat(String(ne)||I),class:q,style:P(P(P({},O.value),J),M),span:1,colon:y,component:S[0],itemPrefixCls:D,bordered:C,label:W},null),g(sb,{key:\"content-\".concat(String(ne)||I),class:q,style:P(P(P({},T.value),J),E),span:B*2-1,component:S[1],itemPrefixCls:D,bordered:C,content:Y},null)]})},r=t.prefixCls,a=t.vertical,o=t.row,i=t.index,l=t.bordered,s=ve(c7,{labelStyle:H({}),contentStyle:H({})}),c=s.labelStyle,d=s.contentStyle;return a?g(Fe,null,[g(\"tr\",{key:\"label-\".concat(i),class:\"\".concat(r,\"-row\")},[n(o,t,{component:\"th\",type:\"label\",showLabel:!0,labelStyle:c,contentStyle:d})]),g(\"tr\",{key:\"content-\".concat(i),class:\"\".concat(r,\"-row\")},[n(o,t,{component:\"td\",type:\"content\",showContent:!0,labelStyle:c,contentStyle:d})])]):g(\"tr\",{key:i,class:\"\".concat(r,\"-row\")},[n(o,t,{component:l?[\"th\",\"td\"]:\"td\",type:\"item\",showLabel:!0,showContent:!0,labelStyle:c,contentStyle:d})])},n_e=t_e;u.string,u.any,u.number;var r_e={prefixCls:u.string,label:u.VNodeChild,labelStyle:u.style,contentStyle:u.style,span:u.number.def(1)},s7=G({name:\"ADescriptionsItem\",props:r_e,slots:[\"label\"],setup:function(t,n){var r=n.slots;return function(){var a;return(a=r.default)===null||a===void 0?void 0:a.call(r)}}}),u7={xxl:3,xl:3,lg:3,md:3,sm:2,xs:1};function a_e(e,t){if(typeof e==\"number\")return e;if(kt(e)===\"object\")for(var n=0;n<ws.length;n++){var r=ws[n];if(t[r]&&e[r]!==void 0)return e[r]||u7[r]}return 3}function _T(e,t,n){var r=e;return(t===void 0||t>n)&&(r=Ot(e,{span:n}),on(t===void 0,\"Descriptions\",\"Sum of column `span` in a line not match `column` of Descriptions.\")),r}function o_e(e,t){var n=Un(e),r=[],a=[],o=t;return n.forEach(function(i,l){var s,c=(s=i.props)===null||s===void 0?void 0:s.span,d=c||1;if(l===n.length-1){a.push(_T(i,c,o)),r.push(a);return}d<o?(o-=d,a.push(i)):(a.push(_T(i,d,o)),r.push(a),o=t,a=[])}),r}var i_e={prefixCls:u.string,bordered:u.looseBool,size:u.oneOf(rt(\"default\",\"middle\",\"small\")).def(\"default\"),title:u.VNodeChild,extra:u.VNodeChild,column:{type:[Number,Object],default:function(){return u7}},layout:u.oneOf(rt(\"horizontal\",\"vertical\")),colon:u.looseBool,labelStyle:u.style,contentStyle:u.style},c7=Symbol(\"descriptionsContext\"),hu=G({name:\"ADescriptions\",props:i_e,slots:[\"title\",\"extra\"],Item:s7,setup:function(t,n){var r=n.slots,a=Wt(\"descriptions\",t),o=a.prefixCls,i=a.direction,l,s=H({});et(function(){l=lc.subscribe(function(d){kt(t.column)===\"object\"&&(s.value=d)})}),Lt(function(){lc.unsubscribe(l)}),ot(c7,{labelStyle:yn(t,\"labelStyle\"),contentStyle:yn(t,\"contentStyle\")});var c=x(function(){return a_e(t.column,s.value)});return function(){var d,f,p,v,m=t.size,y=t.bordered,b=y===void 0?!1:y,C=t.layout,S=C===void 0?\"horizontal\":C,w=t.colon,k=w===void 0?!0:w,$=t.title,O=$===void 0?(f=r.title)===null||f===void 0?void 0:f.call(r):$,T=t.extra,_=T===void 0?(p=r.extra)===null||p===void 0?void 0:p.call(r):T,I=(v=r.default)===null||v===void 0?void 0:v.call(r),L=o_e(I,c.value);return g(\"div\",{class:[o.value,(d={},V(d,\"\".concat(o.value,\"-\").concat(m),m!==\"default\"),V(d,\"\".concat(o.value,\"-bordered\"),!!b),V(d,\"\".concat(o.value,\"-rtl\"),i.value===\"rtl\"),d)]},[(O||_)&&g(\"div\",{class:\"\".concat(o.value,\"-header\")},[O&&g(\"div\",{class:\"\".concat(o.value,\"-title\")},[O]),_&&g(\"div\",{class:\"\".concat(o.value,\"-extra\")},[_])]),g(\"div\",{class:\"\".concat(o.value,\"-view\")},[g(\"table\",null,[g(\"tbody\",null,[L.map(function(j,F){return g(n_e,{key:F,index:F,colon:k,prefixCls:o.value,vertical:S===\"vertical\",bordered:b,row:j},null)})])])])])}}});hu.install=function(e){return e.component(hu.name,hu),e.component(hu.Item.name,hu.Item),e};var l_e=hu,s_e={prefixCls:String,type:{type:String,default:\"horizontal\"},dashed:{type:Boolean,default:!1},orientation:{type:String,default:\"center\"},plain:{type:Boolean,default:!1}},u_e=G({name:\"ADivider\",props:s_e,setup:function(t,n){var r=n.slots,a=ve(\"configProvider\",St),o=x(function(){return a.getPrefixCls(\"divider\",t.prefixCls)}),i=x(function(){var s,c=t.type,d=t.dashed,f=t.plain,p=o.value;return s={},V(s,p,!0),V(s,\"\".concat(p,\"-\").concat(c),!0),V(s,\"\".concat(p,\"-dashed\"),!!d),V(s,\"\".concat(p,\"-plain\"),!!f),V(s,\"\".concat(p,\"-rtl\"),a.direction===\"rtl\"),s}),l=x(function(){return t.orientation.length>0?\"-\"+t.orientation:t.orientation});return function(){var s,c=Un((s=r.default)===null||s===void 0?void 0:s.call(r));return g(\"div\",{class:[i.value,c.length?\"\".concat(o.value,\"-with-text \").concat(o.value,\"-with-text\").concat(l.value):\"\"],role:\"separator\"},[c.length?g(\"span\",{class:\"\".concat(o.value,\"-inner-text\")},[c]):null])}}}),c_e=kn(u_e);hi.Button=cf;hi.install=function(e){return e.component(hi.name,hi),e.component(cf.name,cf),e};var ub;function d7(e){if(e||ub===void 0){var t=document.createElement(\"div\");t.style.width=\"100%\",t.style.height=\"200px\";var n=document.createElement(\"div\"),r=n.style;r.position=\"absolute\",r.top=0,r.left=0,r.pointerEvents=\"none\",r.visibility=\"hidden\",r.width=\"200px\",r.height=\"150px\",r.overflow=\"hidden\",n.appendChild(t),document.body.appendChild(n);var a=t.offsetWidth;n.style.overflow=\"scroll\";var o=t.offsetWidth;a===o&&(o=n.clientWidth),document.body.removeChild(n),ub=a-o}return ub}var f7={width:u.any,height:u.any,defaultOpen:u.looseBool,firstEnter:u.looseBool,open:u.looseBool,prefixCls:u.string,placement:u.string,level:u.oneOfType([u.string,u.array]),levelMove:u.oneOfType([u.number,u.func,u.array]),ease:u.string,duration:u.string,handler:u.any,showMask:u.looseBool,maskStyle:u.object,className:u.string,wrapStyle:u.object,maskClosable:u.looseBool,afterVisibleChange:u.func,keyboard:u.looseBool},d_e=P(P({},f7),{wrapperClassName:u.string,forceRender:u.looseBool,getContainer:u.oneOfType([u.string,u.func,u.object,u.looseBool])});P(P({},f7),{getContainer:u.func,getOpenCount:u.func,switchScrollingEffect:u.func});function f_e(e){return Array.isArray(e)?e:[e]}var h7={transition:\"transitionend\",WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"transitionend\",OTransition:\"oTransitionEnd otransitionend\"},p7=Object.keys(h7).filter(function(e){if(typeof document==\"undefined\")return!1;var t=document.getElementsByTagName(\"html\")[0];return e in(t?t.style:{})})[0],ET=h7[p7];function MT(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r):e.attachEvent&&e.attachEvent(\"on\".concat(t),n)}function IT(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r):e.attachEvent&&e.detachEvent(\"on\".concat(t),n)}function h_e(e,t){var n;return typeof e==\"function\"?n=e(t):n=e,Array.isArray(n)?n.length===2?n:[n[0],n[1]]:[n]}var NT=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},p_e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function jh(){}var qc={},Kh=!(typeof window!=\"undefined\"&&window.document&&window.document.createElement),v_e=G({name:\"Drawer\",mixins:[nt],inheritAttrs:!1,props:An(d_e,{prefixCls:\"drawer\",placement:\"left\",getContainer:\"body\",level:\"all\",duration:\".3s\",ease:\"cubic-bezier(0.78, 0.14, 0.15, 0.86)\",firstEnter:!1,showMask:!0,handler:!0,maskStyle:{},wrapperClassName:\"\"}),data:function(){this.levelDom=[],this.contentDom=null,this.maskDom=null,this.handlerdom=null,this.mousePos=null,this.sFirstEnter=this.firstEnter,this.timeout=null,this.children=null,this.dom=null,this.drawerId=Number((Date.now()+Math.random()).toString().replace(\".\",Math.round(Math.random()*9))).toString(16);var t=this.open!==void 0?this.open:!!this.defaultOpen;return qc[this.drawerId]=t,this.orignalOpen=this.open,this.preProps=P({},this.$props),{sOpen:t,isOpenChange:void 0,passive:void 0,container:void 0}},watch:{open:function(e){function t(n){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}(function(e){var t=this;e!==void 0&&e!==this.preProps.open&&(this.isOpenChange=!0,this.container||this.getDefault(this.$props),this.setState({sOpen:open})),this.preProps.open=e,e&&setTimeout(function(){t.domFocus()})}),placement:function(t){t!==this.preProps.placement&&(this.contentDom=null),this.preProps.placement=t},level:function(t){this.preProps.level!==t&&this.getParentAndLevelDom(this.$props),this.preProps.level=t}},mounted:function(){var t=this;Ne(function(){Kh||(t.passive=mn?{passive:!1}:!1);var n=t.getOpen();(t.handler||n||t.sFirstEnter)&&(t.getDefault(t.$props),n&&(t.isOpenChange=!0,Ne(function(){t.domFocus()})),t.$forceUpdate())})},updated:function(){var t=this;Ne(function(){!t.sFirstEnter&&t.container&&(t.$forceUpdate(),t.sFirstEnter=!0)})},beforeUnmount:function(){delete qc[this.drawerId],delete this.isOpenChange,this.container&&(this.sOpen&&this.setLevelDomTransform(!1,!0),document.body.style.overflow=\"\"),this.sFirstEnter=!1,clearTimeout(this.timeout)},methods:{domFocus:function(){this.dom&&this.dom.focus()},onKeyDown:function(t){t.keyCode===ze.ESC&&(t.stopPropagation(),this.__emit(\"close\",t))},onMaskTouchEnd:function(t){this.__emit(\"close\",t),this.onTouchEnd(t,!0)},onIconTouchEnd:function(t){this.__emit(\"handleClick\",t),this.onTouchEnd(t)},onTouchEnd:function(t,n){if(this.open===void 0){var r=n||this.sOpen;this.isOpenChange=!0,this.setState({sOpen:!r})}},onWrapperTransitionEnd:function(t){if(t.target===this.contentWrapper&&t.propertyName.match(/transform$/)){var n=this.getOpen();this.dom.style.transition=\"\",!n&&this.getCurrentDrawerSome()&&(document.body.style.overflowX=\"\",this.maskDom&&(this.maskDom.style.left=\"\",this.maskDom.style.width=\"\")),this.afterVisibleChange&&this.afterVisibleChange(!!n)}},getDefault:function(t){this.getParentAndLevelDom(t),(t.getContainer||t.parent)&&(this.container=this.defaultGetContainer())},getCurrentDrawerSome:function(){return!Object.keys(qc).some(function(t){return qc[t]})},getSelfContainer:function(){return this.container},getParentAndLevelDom:function(t){var n=this;if(!Kh){var r=t.level,a=t.getContainer;if(this.levelDom=[],a){if(typeof a==\"string\"){var o=document.querySelectorAll(a)[0];this.parent=o}typeof a==\"function\"&&(this.parent=a()),kt(a)===\"object\"&&a instanceof window.HTMLElement&&(this.parent=a)}if(!a&&this.container&&(this.parent=this.container.parentNode),r===\"all\"){var i=Array.prototype.slice.call(this.parent.children);i.forEach(function(l){l.nodeName!==\"SCRIPT\"&&l.nodeName!==\"STYLE\"&&l.nodeName!==\"LINK\"&&l!==n.container&&n.levelDom.push(l)})}else r&&f_e(r).forEach(function(l){document.querySelectorAll(l).forEach(function(s){n.levelDom.push(s)})})}},setLevelDomTransform:function(t,n,r,a){var o=this,i=this.$props,l=i.placement,s=i.levelMove,c=i.duration,d=i.ease,f=i.getContainer;if(!Kh&&(this.levelDom.forEach(function(w){if(w&&(o.isOpenChange||n)){w.style.transition=\"transform \".concat(c,\" \").concat(d),MT(w,ET,o.trnasitionEnd);var k=t?a:0;if(s){var $=h_e(s,{target:w,open:t});k=t?$[0]:$[1]||0}var O=typeof k==\"number\"?\"\".concat(k,\"px\"):k,T=l===\"left\"||l===\"top\"?O:\"-\".concat(O);w.style.transform=k?\"\".concat(r,\"(\").concat(T,\")\"):\"\",w.style.msTransform=k?\"\".concat(r,\"(\").concat(T,\")\"):\"\"}}),f===\"body\")){var p=[\"touchstart\"],v=[document.body,this.maskDom,this.handlerdom,this.contentDom],m=document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)&&window.innerWidth>document.body.offsetWidth?d7(1):0,y=\"width \".concat(c,\" \").concat(d),b=\"transform \".concat(c,\" \").concat(d);if(t&&document.body.style.overflow!==\"hidden\"){if(document.body.style.overflow=\"hidden\",m&&(document.body.style.position=\"relative\",document.body.style.width=\"calc(100% - \".concat(m,\"px)\"),clearTimeout(this.timeout),this.dom)){switch(this.dom.style.transition=\"none\",l){case\"right\":this.dom.style.transform=\"translateX(-\".concat(m,\"px)\"),this.dom.style.msTransform=\"translateX(-\".concat(m,\"px)\");break;case\"top\":case\"bottom\":this.dom.style.width=\"calc(100% - \".concat(m,\"px)\"),this.dom.style.transform=\"translateZ(0)\";break}this.timeout=setTimeout(function(){o.dom.style.transition=\"\".concat(b,\",\").concat(y),o.dom.style.width=\"\",o.dom.style.transform=\"\",o.dom.style.msTransform=\"\"})}v.forEach(function(w,k){!w||MT(w,p[k]||\"touchmove\",k?o.removeMoveHandler:o.removeStartHandler,o.passive)})}else if(this.getCurrentDrawerSome()){if(document.body.style.overflow=\"\",(this.isOpenChange||n)&&m&&(document.body.style.position=\"\",document.body.style.width=\"\",p7&&(document.body.style.overflowX=\"hidden\"),l===\"right\"&&this.maskDom&&(this.maskDom.style.left=\"-\".concat(m,\"px\"),this.maskDom.style.width=\"calc(100% + \".concat(m,\"px)\")),clearTimeout(this.timeout),this.dom)){this.dom.style.transition=\"none\";var C;switch(l){case\"right\":{this.dom.style.transform=\"translateX(\".concat(m,\"px)\"),this.dom.style.msTransform=\"translateX(\".concat(m,\"px)\"),this.dom.style.width=\"100%\",y=\"width 0s \".concat(d,\" \").concat(c);break}case\"top\":case\"bottom\":{this.dom.style.width=\"calc(100% + \".concat(m,\"px)\"),this.dom.style.height=\"100%\",this.dom.style.transform=\"translateZ(0)\",C=\"height 0s \".concat(d,\" \").concat(c);break}}this.timeout=setTimeout(function(){o.dom.style.transition=\"\".concat(b,\",\").concat(C?\"\".concat(C,\",\"):\"\").concat(y),o.dom.style.transform=\"\",o.dom.style.msTransform=\"\",o.dom.style.width=\"\",o.dom.style.height=\"\"})}v.forEach(function(w,k){!w||IT(w,p[k]||\"touchmove\",k?o.removeMoveHandler:o.removeStartHandler,o.passive)})}}var S=this.$attrs.onChange;S&&this.isOpenChange&&this.sFirstEnter&&(S(t),this.isOpenChange=!1)},getChildToRender:function(t){var n,r=this,a,o=this.$props,i=o.prefixCls,l=o.placement,s=o.handler,c=o.showMask,d=o.maskStyle,f=o.width,p=o.height,v=o.wrapStyle,m=o.keyboard,y=o.maskClosable,b=this.$attrs,C=b.class,S=b.style,w=p_e(b,[\"class\",\"style\"]),k=ht(this),$=Se(i,(n={},V(n,\"\".concat(i,\"-\").concat(l),!0),V(n,\"\".concat(i,\"-open\"),t),V(n,\"no-mask\",!c),V(n,C,C),n)),O=this.isOpenChange,T=l===\"left\"||l===\"right\",_=\"translate\".concat(T?\"X\":\"Y\"),I=l===\"left\"||l===\"top\"?\"-100%\":\"100%\",L=t?\"\":\"\".concat(_,\"(\").concat(I,\")\");if(O===void 0||O){var j=this.contentDom?this.contentDom.getBoundingClientRect()[T?\"width\":\"height\"]:0,F=(T?f:p)||j;this.setLevelDomTransform(t,!1,_,F)}var N;if(s!==!1){var D=g(\"div\",{class:\"drawer-handle\",onClick:function(){}},[g(\"i\",{class:\"drawer-handle-icon\"},null)]),z=this.handler,B=z||D,M=B.props&&B.props.onClick;N=Ot(B,{onClick:function(Y){M&&M(Y),r.onIconTouchEnd(Y)},ref:function(Y){r.handlerdom=Y}})}var E=P(P({},w),{class:$,onTransitionend:this.onWrapperTransitionEnd,onKeydown:t&&m?this.onKeyDown:jh,style:P(P({},v),S)}),K=(a={},V(a,mn?\"onTouchstartPassive\":\"onTouchstart\",t?this.removeStartHandler:jh),V(a,mn?\"onTouchmovePassive\":\"onTouchmove\",t?this.removeMoveHandler:jh),a);return g(\"div\",le(le({ref:function(Y){r.dom=Y}},E),{},{tabindex:-1}),[c&&g(\"div\",{key:t,class:\"\".concat(i,\"-mask\"),onClick:y?this.onMaskTouchEnd:jh,style:d,ref:function(Y){r.maskDom=Y}},null),g(\"div\",{class:\"\".concat(i,\"-content-wrapper\"),style:{transform:L,msTransform:L,width:NT(f)?\"\".concat(f,\"px\"):f,height:NT(p)?\"\".concat(p,\"px\"):p},ref:function(Y){r.contentWrapper=Y}},[g(\"div\",le({class:\"\".concat(i,\"-content\"),ref:function(Y){r.contentDom=Y}},K),[k]),N])])},getOpen:function(){return this.open!==void 0?this.open:this.sOpen},getTouchParentScroll:function(t,n,r,a){if(!n||n===document)return!1;if(n===t.parentNode)return!0;var o=Math.max(Math.abs(r),Math.abs(a))===Math.abs(a),i=Math.max(Math.abs(r),Math.abs(a))===Math.abs(r),l=n.scrollHeight-n.clientHeight,s=n.scrollWidth-n.clientWidth,c=n.scrollTop,d=n.scrollLeft;n.scrollTo&&n.scrollTo(n.scrollLeft+1,n.scrollTop+1);var f=n.scrollTop,p=n.scrollLeft;return n.scrollTo&&n.scrollTo(n.scrollLeft-1,n.scrollTop-1),o&&(!l||!(f-c)||l&&(n.scrollTop>=l&&a<0||n.scrollTop<=0&&a>0))||i&&(!s||!(p-d)||s&&(n.scrollLeft>=s&&r<0||n.scrollLeft<=0&&r>0))?this.getTouchParentScroll(t,n.parentNode,r,a):!1},removeStartHandler:function(t){t.touches.length>1||(this.startPos={x:t.touches[0].clientX,y:t.touches[0].clientY})},removeMoveHandler:function(t){if(!(t.changedTouches.length>1)){var n=t.currentTarget,r=t.changedTouches[0].clientX-this.startPos.x,a=t.changedTouches[0].clientY-this.startPos.y;(n===this.maskDom||n===this.handlerdom||n===this.contentDom&&this.getTouchParentScroll(n,t.target,r,a))&&t.preventDefault()}},trnasitionEnd:function(t){IT(t.target,ET,this.trnasitionEnd),t.target.style.transition=\"\"},defaultGetContainer:function(){if(Kh)return null;var t=document.createElement(\"div\");return this.parent.appendChild(t),this.wrapperClassName&&(t.className=this.wrapperClassName),t}},render:function(){var t=this,n=this.$props,r=n.getContainer,a=n.wrapperClassName,o=n.handler,i=n.forceRender,l=this.getOpen(),s=null;qc[this.drawerId]=l&&this.container;var c=this.getChildToRender(this.sFirstEnter?l:!1);if(!r)return g(\"div\",{class:a,ref:function(p){t.container=p}},[c]);if(!this.container||!l&&!this.sFirstEnter)return null;var d=!!o||i;return(d||l||this.dom)&&(s=g(Ps,{to:this.getSelfContainer()},{default:function(){return[c]}})),s}}),m_e=v_e,g_e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},y_e=rt(\"top\",\"right\",\"bottom\",\"left\"),b_e=G({name:\"ADrawer\",mixins:[nt],inheritAttrs:!1,props:{closable:u.looseBool.def(!0),destroyOnClose:u.looseBool,getContainer:u.any,maskClosable:u.looseBool.def(!0),mask:u.looseBool.def(!0),maskStyle:u.object,wrapStyle:u.object,bodyStyle:u.object,headerStyle:u.object,drawerStyle:u.object,title:u.VNodeChild,visible:u.looseBool,width:u.oneOfType([u.string,u.number]).def(256),height:u.oneOfType([u.string,u.number]).def(256),zIndex:u.number,prefixCls:u.string,placement:u.oneOf(y_e).def(\"right\"),level:u.any.def(null),wrapClassName:u.string,handle:u.VNodeChild,afterVisibleChange:u.func,keyboard:u.looseBool.def(!0),onClose:u.func,\"onUpdate:visible\":u.func},setup:function(t){var n=ve(\"configProvider\",St);return{configProvider:n,destroyClose:!1,preVisible:t.visible,parentDrawer:ve(\"parentDrawer\",null)}},data:function(){return{sPush:!1}},beforeCreate:function(){ot(\"parentDrawer\",this)},mounted:function(){var t=this.visible;t&&this.parentDrawer&&this.parentDrawer.push()},updated:function(){var t=this;Ne(function(){t.preVisible!==t.visible&&t.parentDrawer&&(t.visible?t.parentDrawer.push():t.parentDrawer.pull()),t.preVisible=t.visible})},beforeUnmount:function(){this.parentDrawer&&this.parentDrawer.pull()},methods:{domFocus:function(){this.$refs.vcDrawer&&this.$refs.vcDrawer.domFocus()},close:function(t){this.$emit(\"update:visible\",!1),this.$emit(\"close\",t)},push:function(){this.setState({sPush:!0})},pull:function(){var t=this;this.setState({sPush:!1},function(){t.domFocus()})},onDestroyTransitionEnd:function(){var t=this.getDestroyOnClose();!t||this.visible||(this.destroyClose=!0,this.$forceUpdate())},getDestroyOnClose:function(){return this.destroyOnClose&&!this.visible},getPushTransform:function(t){if(t===\"left\"||t===\"right\")return\"translateX(\".concat(t===\"left\"?180:-180,\"px)\");if(t===\"top\"||t===\"bottom\")return\"translateY(\".concat(t===\"top\"?180:-180,\"px)\")},getRcDrawerStyle:function(){var t=this.$props,n=t.zIndex,r=t.placement,a=t.wrapStyle,o=this.$data.sPush;return P({zIndex:n,transform:o?this.getPushTransform(r):void 0},a)},renderHeader:function(t){var n=this.$props,r=n.closable,a=n.headerStyle,o=We(this,\"title\");if(!o&&!r)return null;var i=o?\"\".concat(t,\"-header\"):\"\".concat(t,\"-header-no-title\");return g(\"div\",{class:i,style:a},[o&&g(\"div\",{class:\"\".concat(t,\"-title\")},[o]),r?this.renderCloseIcon(t):null])},renderCloseIcon:function(t){var n=this.closable;return n&&g(\"button\",{key:\"closer\",onClick:this.close,\"aria-label\":\"Close\",class:\"\".concat(t,\"-close\")},[g(go,null,null)])},renderBody:function(t){var n,r;if(this.destroyClose&&!this.visible)return null;this.destroyClose=!1;var a=this.$props,o=a.bodyStyle,i=a.drawerStyle,l={},s=this.getDestroyOnClose();return s&&(l.opacity=0,l.transition=\"opacity .3s\"),g(\"div\",{class:\"\".concat(t,\"-wrapper-body\"),style:P(P({},l),i),onTransitionend:this.onDestroyTransitionEnd},[this.renderHeader(t),g(\"div\",{key:\"body\",class:\"\".concat(t,\"-body\"),style:o},[(r=(n=this.$slots).default)===null||r===void 0?void 0:r.call(n)])])}},render:function(){var t,n=this,r=Qe(this),a=r.prefixCls,o=r.width,i=r.height,l=r.visible,s=r.placement,c=r.wrapClassName,d=r.mask,f=g_e(r,[\"prefixCls\",\"width\",\"height\",\"visible\",\"placement\",\"wrapClassName\",\"mask\"]),p=d?\"\":\"no-mask\",v={};s===\"left\"||s===\"right\"?v.width=typeof o==\"number\"?\"\".concat(o,\"px\"):o:v.height=typeof i==\"number\"?\"\".concat(i,\"px\"):i;var m=We(this,\"handle\")||!1,y=this.configProvider.getPrefixCls,b=y(\"drawer\",a),C=this.$attrs.class,S=P(P(P(P(P({},this.$attrs),bn(f,[\"closable\",\"destroyOnClose\",\"drawerStyle\",\"headerStyle\",\"bodyStyle\",\"title\",\"push\",\"visible\",\"getPopupContainer\",\"rootPrefixCls\",\"getPrefixCls\",\"renderEmpty\",\"csp\",\"pageHeader\",\"autoInsertSpaceInButton\"])),{onClose:this.close,handler:m}),v),{prefixCls:b,open:l,showMask:d,placement:s,class:Se((t={},V(t,C,!!C),V(t,c,!!c),V(t,p,!!p),t)),wrapStyle:this.getRcDrawerStyle(),ref:\"vcDrawer\"});return g(m_e,S,{default:function(){return[n.renderBody(b)]}})}}),C_e=kn(b_e),v7={exports:{}};(function(e){var t=function(n){var r=Object.prototype,a=r.hasOwnProperty,o,i=typeof Symbol==\"function\"?Symbol:{},l=i.iterator||\"@@iterator\",s=i.asyncIterator||\"@@asyncIterator\",c=i.toStringTag||\"@@toStringTag\";function d(E,K,W){return Object.defineProperty(E,K,{value:W,enumerable:!0,configurable:!0,writable:!0}),E[K]}try{d({},\"\")}catch{d=function(K,W,Y){return K[W]=Y}}function f(E,K,W,Y){var q=K&&K.prototype instanceof S?K:S,J=Object.create(q.prototype),ne=new z(Y||[]);return J._invoke=j(E,W,ne),J}n.wrap=f;function p(E,K,W){try{return{type:\"normal\",arg:E.call(K,W)}}catch(Y){return{type:\"throw\",arg:Y}}}var v=\"suspendedStart\",m=\"suspendedYield\",y=\"executing\",b=\"completed\",C={};function S(){}function w(){}function k(){}var $={};d($,l,function(){return this});var O=Object.getPrototypeOf,T=O&&O(O(B([])));T&&T!==r&&a.call(T,l)&&($=T);var _=k.prototype=S.prototype=Object.create($);w.prototype=k,d(_,\"constructor\",k),d(k,\"constructor\",w),w.displayName=d(k,c,\"GeneratorFunction\");function I(E){[\"next\",\"throw\",\"return\"].forEach(function(K){d(E,K,function(W){return this._invoke(K,W)})})}n.isGeneratorFunction=function(E){var K=typeof E==\"function\"&&E.constructor;return K?K===w||(K.displayName||K.name)===\"GeneratorFunction\":!1},n.mark=function(E){return Object.setPrototypeOf?Object.setPrototypeOf(E,k):(E.__proto__=k,d(E,c,\"GeneratorFunction\")),E.prototype=Object.create(_),E},n.awrap=function(E){return{__await:E}};function L(E,K){function W(J,ne,oe,Q){var ae=p(E[J],E,ne);if(ae.type===\"throw\")Q(ae.arg);else{var de=ae.arg,be=de.value;return be&&typeof be==\"object\"&&a.call(be,\"__await\")?K.resolve(be.__await).then(function(Ee){W(\"next\",Ee,oe,Q)},function(Ee){W(\"throw\",Ee,oe,Q)}):K.resolve(be).then(function(Ee){de.value=Ee,oe(de)},function(Ee){return W(\"throw\",Ee,oe,Q)})}}var Y;function q(J,ne){function oe(){return new K(function(Q,ae){W(J,ne,Q,ae)})}return Y=Y?Y.then(oe,oe):oe()}this._invoke=q}I(L.prototype),d(L.prototype,s,function(){return this}),n.AsyncIterator=L,n.async=function(E,K,W,Y,q){q===void 0&&(q=Promise);var J=new L(f(E,K,W,Y),q);return n.isGeneratorFunction(K)?J:J.next().then(function(ne){return ne.done?ne.value:J.next()})};function j(E,K,W){var Y=v;return function(J,ne){if(Y===y)throw new Error(\"Generator is already running\");if(Y===b){if(J===\"throw\")throw ne;return M()}for(W.method=J,W.arg=ne;;){var oe=W.delegate;if(oe){var Q=F(oe,W);if(Q){if(Q===C)continue;return Q}}if(W.method===\"next\")W.sent=W._sent=W.arg;else if(W.method===\"throw\"){if(Y===v)throw Y=b,W.arg;W.dispatchException(W.arg)}else W.method===\"return\"&&W.abrupt(\"return\",W.arg);Y=y;var ae=p(E,K,W);if(ae.type===\"normal\"){if(Y=W.done?b:m,ae.arg===C)continue;return{value:ae.arg,done:W.done}}else ae.type===\"throw\"&&(Y=b,W.method=\"throw\",W.arg=ae.arg)}}}function F(E,K){var W=E.iterator[K.method];if(W===o){if(K.delegate=null,K.method===\"throw\"){if(E.iterator.return&&(K.method=\"return\",K.arg=o,F(E,K),K.method===\"throw\"))return C;K.method=\"throw\",K.arg=new TypeError(\"The iterator does not provide a 'throw' method\")}return C}var Y=p(W,E.iterator,K.arg);if(Y.type===\"throw\")return K.method=\"throw\",K.arg=Y.arg,K.delegate=null,C;var q=Y.arg;if(!q)return K.method=\"throw\",K.arg=new TypeError(\"iterator result is not an object\"),K.delegate=null,C;if(q.done)K[E.resultName]=q.value,K.next=E.nextLoc,K.method!==\"return\"&&(K.method=\"next\",K.arg=o);else return q;return K.delegate=null,C}I(_),d(_,c,\"Generator\"),d(_,l,function(){return this}),d(_,\"toString\",function(){return\"[object Generator]\"});function N(E){var K={tryLoc:E[0]};1 in E&&(K.catchLoc=E[1]),2 in E&&(K.finallyLoc=E[2],K.afterLoc=E[3]),this.tryEntries.push(K)}function D(E){var K=E.completion||{};K.type=\"normal\",delete K.arg,E.completion=K}function z(E){this.tryEntries=[{tryLoc:\"root\"}],E.forEach(N,this),this.reset(!0)}n.keys=function(E){var K=[];for(var W in E)K.push(W);return K.reverse(),function Y(){for(;K.length;){var q=K.pop();if(q in E)return Y.value=q,Y.done=!1,Y}return Y.done=!0,Y}};function B(E){if(E){var K=E[l];if(K)return K.call(E);if(typeof E.next==\"function\")return E;if(!isNaN(E.length)){var W=-1,Y=function q(){for(;++W<E.length;)if(a.call(E,W))return q.value=E[W],q.done=!1,q;return q.value=o,q.done=!0,q};return Y.next=Y}}return{next:M}}n.values=B;function M(){return{value:o,done:!0}}return z.prototype={constructor:z,reset:function(E){if(this.prev=0,this.next=0,this.sent=this._sent=o,this.done=!1,this.delegate=null,this.method=\"next\",this.arg=o,this.tryEntries.forEach(D),!E)for(var K in this)K.charAt(0)===\"t\"&&a.call(this,K)&&!isNaN(+K.slice(1))&&(this[K]=o)},stop:function(){this.done=!0;var E=this.tryEntries[0],K=E.completion;if(K.type===\"throw\")throw K.arg;return this.rval},dispatchException:function(E){if(this.done)throw E;var K=this;function W(Q,ae){return J.type=\"throw\",J.arg=E,K.next=Q,ae&&(K.method=\"next\",K.arg=o),!!ae}for(var Y=this.tryEntries.length-1;Y>=0;--Y){var q=this.tryEntries[Y],J=q.completion;if(q.tryLoc===\"root\")return W(\"end\");if(q.tryLoc<=this.prev){var ne=a.call(q,\"catchLoc\"),oe=a.call(q,\"finallyLoc\");if(ne&&oe){if(this.prev<q.catchLoc)return W(q.catchLoc,!0);if(this.prev<q.finallyLoc)return W(q.finallyLoc)}else if(ne){if(this.prev<q.catchLoc)return W(q.catchLoc,!0)}else if(oe){if(this.prev<q.finallyLoc)return W(q.finallyLoc)}else throw new Error(\"try statement without catch or finally\")}}},abrupt:function(E,K){for(var W=this.tryEntries.length-1;W>=0;--W){var Y=this.tryEntries[W];if(Y.tryLoc<=this.prev&&a.call(Y,\"finallyLoc\")&&this.prev<Y.finallyLoc){var q=Y;break}}q&&(E===\"break\"||E===\"continue\")&&q.tryLoc<=K&&K<=q.finallyLoc&&(q=null);var J=q?q.completion:{};return J.type=E,J.arg=K,q?(this.method=\"next\",this.next=q.finallyLoc,C):this.complete(J)},complete:function(E,K){if(E.type===\"throw\")throw E.arg;return E.type===\"break\"||E.type===\"continue\"?this.next=E.arg:E.type===\"return\"?(this.rval=this.arg=E.arg,this.method=\"return\",this.next=\"end\"):E.type===\"normal\"&&K&&(this.next=K),C},finish:function(E){for(var K=this.tryEntries.length-1;K>=0;--K){var W=this.tryEntries[K];if(W.finallyLoc===E)return this.complete(W.completion,W.afterLoc),D(W),C}},catch:function(E){for(var K=this.tryEntries.length-1;K>=0;--K){var W=this.tryEntries[K];if(W.tryLoc===E){var Y=W.completion;if(Y.type===\"throw\"){var q=Y.arg;D(W)}return q}}throw new Error(\"illegal catch attempt\")},delegateYield:function(E,K,W){return this.delegate={iterator:B(E),resultName:K,nextLoc:W},this.method===\"next\"&&(this.arg=o),C}},n}(e.exports);try{regeneratorRuntime=t}catch{typeof globalThis==\"object\"?globalThis.regeneratorRuntime=t:Function(\"r\",\"regeneratorRuntime = r\")(t)}})(v7);var pl=v7.exports;function Jl(){return Jl=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},Jl.apply(this,arguments)}function w_e(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,pf(e,t)}function w1(e){return w1=Object.setPrototypeOf?Object.getPrototypeOf:function(n){return n.__proto__||Object.getPrototypeOf(n)},w1(e)}function pf(e,t){return pf=Object.setPrototypeOf||function(r,a){return r.__proto__=a,r},pf(e,t)}function S_e(){if(typeof Reflect==\"undefined\"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy==\"function\")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Gp(e,t,n){return S_e()?Gp=Reflect.construct:Gp=function(a,o,i){var l=[null];l.push.apply(l,o);var s=Function.bind.apply(a,l),c=new s;return i&&pf(c,i.prototype),c},Gp.apply(null,arguments)}function k_e(e){return Function.toString.call(e).indexOf(\"[native code]\")!==-1}function S1(e){var t=typeof Map==\"function\"?new Map:void 0;return S1=function(r){if(r===null||!k_e(r))return r;if(typeof r!=\"function\")throw new TypeError(\"Super expression must either be null or a function\");if(typeof t!=\"undefined\"){if(t.has(r))return t.get(r);t.set(r,a)}function a(){return Gp(r,arguments,w1(this).constructor)}return a.prototype=Object.create(r.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),pf(a,r)},S1(e)}var $_e=/%[sdj%]/g,O_e=function(){};typeof process!=\"undefined\"&&process.env;function k1(e){if(!e||!e.length)return null;var t={};return e.forEach(function(n){var r=n.field;t[r]=t[r]||[],t[r].push(n)}),t}function da(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=1,a=t[0],o=t.length;if(typeof a==\"function\")return a.apply(null,t.slice(1));if(typeof a==\"string\"){var i=String(a).replace($_e,function(l){if(l===\"%%\")return\"%\";if(r>=o)return l;switch(l){case\"%s\":return String(t[r++]);case\"%d\":return Number(t[r++]);case\"%j\":try{return JSON.stringify(t[r++])}catch{return\"[Circular]\"}break;default:return l}});return i}return a}function P_e(e){return e===\"string\"||e===\"url\"||e===\"hex\"||e===\"email\"||e===\"date\"||e===\"pattern\"}function sr(e,t){return!!(e==null||t===\"array\"&&Array.isArray(e)&&!e.length||P_e(t)&&typeof e==\"string\"&&!e)}function T_e(e,t,n){var r=[],a=0,o=e.length;function i(l){r.push.apply(r,l),a++,a===o&&n(r)}e.forEach(function(l){t(l,i)})}function AT(e,t,n){var r=0,a=e.length;function o(i){if(i&&i.length){n(i);return}var l=r;r=r+1,l<a?t(e[l],o):n([])}o([])}function x_e(e){var t=[];return Object.keys(e).forEach(function(n){t.push.apply(t,e[n])}),t}var DT=function(e){w_e(t,e);function t(n,r){var a;return a=e.call(this,\"Async Validation Error\")||this,a.errors=n,a.fields=r,a}return t}(S1(Error));function __e(e,t,n,r){if(t.first){var a=new Promise(function(f,p){var v=function(b){return r(b),b.length?p(new DT(b,k1(b))):f()},m=x_e(e);AT(m,n,v)});return a.catch(function(f){return f}),a}var o=t.firstFields||[];o===!0&&(o=Object.keys(e));var i=Object.keys(e),l=i.length,s=0,c=[],d=new Promise(function(f,p){var v=function(y){if(c.push.apply(c,y),s++,s===l)return r(c),c.length?p(new DT(c,k1(c))):f()};i.length||(r(c),f()),i.forEach(function(m){var y=e[m];o.indexOf(m)!==-1?AT(y,n,v):T_e(y,n,v)})});return d.catch(function(f){return f}),d}function RT(e){return function(t){return t&&t.message?(t.field=t.field||e.fullField,t):{message:typeof t==\"function\"?t():t,field:t.field||e.fullField}}}function LT(e,t){if(t){for(var n in t)if(t.hasOwnProperty(n)){var r=t[n];typeof r==\"object\"&&typeof e[n]==\"object\"?e[n]=Jl({},e[n],r):e[n]=r}}return e}function m7(e,t,n,r,a,o){e.required&&(!n.hasOwnProperty(e.field)||sr(t,o||e.type))&&r.push(da(a.messages.required,e.fullField))}function E_e(e,t,n,r,a){(/^\\s+$/.test(t)||t===\"\")&&r.push(da(a.messages.whitespace,e.fullField))}var cb={email:/^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/,url:new RegExp(\"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}(?:\\\\.(?:[0-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]+-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]+-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))|localhost)(?::\\\\d{2,5})?(?:(/|\\\\?|#)[^\\\\s]*)?$\",\"i\"),hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},ld={integer:function(t){return ld.number(t)&&parseInt(t,10)===t},float:function(t){return ld.number(t)&&!ld.integer(t)},array:function(t){return Array.isArray(t)},regexp:function(t){if(t instanceof RegExp)return!0;try{return!!new RegExp(t)}catch{return!1}},date:function(t){return typeof t.getTime==\"function\"&&typeof t.getMonth==\"function\"&&typeof t.getYear==\"function\"&&!isNaN(t.getTime())},number:function(t){return isNaN(t)?!1:typeof t==\"number\"},object:function(t){return typeof t==\"object\"&&!ld.array(t)},method:function(t){return typeof t==\"function\"},email:function(t){return typeof t==\"string\"&&!!t.match(cb.email)&&t.length<255},url:function(t){return typeof t==\"string\"&&!!t.match(cb.url)},hex:function(t){return typeof t==\"string\"&&!!t.match(cb.hex)}};function M_e(e,t,n,r,a){if(e.required&&t===void 0){m7(e,t,n,r,a);return}var o=[\"integer\",\"float\",\"array\",\"regexp\",\"object\",\"method\",\"email\",\"number\",\"date\",\"url\",\"hex\"],i=e.type;o.indexOf(i)>-1?ld[i](t)||r.push(da(a.messages.types[i],e.fullField,e.type)):i&&typeof t!==e.type&&r.push(da(a.messages.types[i],e.fullField,e.type))}function I_e(e,t,n,r,a){var o=typeof e.len==\"number\",i=typeof e.min==\"number\",l=typeof e.max==\"number\",s=/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,c=t,d=null,f=typeof t==\"number\",p=typeof t==\"string\",v=Array.isArray(t);if(f?d=\"number\":p?d=\"string\":v&&(d=\"array\"),!d)return!1;v&&(c=t.length),p&&(c=t.replace(s,\"_\").length),o?c!==e.len&&r.push(da(a.messages[d].len,e.fullField,e.len)):i&&!l&&c<e.min?r.push(da(a.messages[d].min,e.fullField,e.min)):l&&!i&&c>e.max?r.push(da(a.messages[d].max,e.fullField,e.max)):i&&l&&(c<e.min||c>e.max)&&r.push(da(a.messages[d].range,e.fullField,e.min,e.max))}var Xs=\"enum\";function N_e(e,t,n,r,a){e[Xs]=Array.isArray(e[Xs])?e[Xs]:[],e[Xs].indexOf(t)===-1&&r.push(da(a.messages[Xs],e.fullField,e[Xs].join(\", \")))}function A_e(e,t,n,r,a){if(e.pattern){if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||r.push(da(a.messages.pattern.mismatch,e.fullField,t,e.pattern));else if(typeof e.pattern==\"string\"){var o=new RegExp(e.pattern);o.test(t)||r.push(da(a.messages.pattern.mismatch,e.fullField,t,e.pattern))}}}var nn={required:m7,whitespace:E_e,type:M_e,range:I_e,enum:N_e,pattern:A_e};function D_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t,\"string\")&&!e.required)return n();nn.required(e,t,r,o,a,\"string\"),sr(t,\"string\")||(nn.type(e,t,r,o,a),nn.range(e,t,r,o,a),nn.pattern(e,t,r,o,a),e.whitespace===!0&&nn.whitespace(e,t,r,o,a))}n(o)}function R_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&nn.type(e,t,r,o,a)}n(o)}function L_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(t===\"\"&&(t=void 0),sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&(nn.type(e,t,r,o,a),nn.range(e,t,r,o,a))}n(o)}function F_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&nn.type(e,t,r,o,a)}n(o)}function B_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),sr(t)||nn.type(e,t,r,o,a)}n(o)}function V_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&(nn.type(e,t,r,o,a),nn.range(e,t,r,o,a))}n(o)}function z_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&(nn.type(e,t,r,o,a),nn.range(e,t,r,o,a))}n(o)}function H_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(t==null&&!e.required)return n();nn.required(e,t,r,o,a,\"array\"),t!=null&&(nn.type(e,t,r,o,a),nn.range(e,t,r,o,a))}n(o)}function j_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&nn.type(e,t,r,o,a)}n(o)}var K_e=\"enum\";function W_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a),t!==void 0&&nn[K_e](e,t,r,o,a)}n(o)}function U_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t,\"string\")&&!e.required)return n();nn.required(e,t,r,o,a),sr(t,\"string\")||nn.pattern(e,t,r,o,a)}n(o)}function Y_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t,\"date\")&&!e.required)return n();if(nn.required(e,t,r,o,a),!sr(t,\"date\")){var l;t instanceof Date?l=t:l=new Date(t),nn.type(e,l,r,o,a),l&&nn.range(e,l.getTime(),r,o,a)}}n(o)}function q_e(e,t,n,r,a){var o=[],i=Array.isArray(t)?\"array\":typeof t;nn.required(e,t,r,o,a,i),n(o)}function db(e,t,n,r,a){var o=e.type,i=[],l=e.required||!e.required&&r.hasOwnProperty(e.field);if(l){if(sr(t,o)&&!e.required)return n();nn.required(e,t,r,i,a,o),sr(t,o)||nn.type(e,t,r,i,a)}n(i)}function G_e(e,t,n,r,a){var o=[],i=e.required||!e.required&&r.hasOwnProperty(e.field);if(i){if(sr(t)&&!e.required)return n();nn.required(e,t,r,o,a)}n(o)}var xd={string:D_e,method:R_e,number:L_e,boolean:F_e,regexp:B_e,integer:V_e,float:z_e,array:H_e,object:j_e,enum:W_e,pattern:U_e,date:Y_e,url:db,hex:db,email:db,required:q_e,any:G_e};function $1(){return{default:\"Validation error on field %s\",required:\"%s is required\",enum:\"%s must be one of %s\",whitespace:\"%s cannot be empty\",date:{format:\"%s date %s is invalid for format %s\",parse:\"%s date could not be parsed, %s is invalid \",invalid:\"%s date %s is invalid\"},types:{string:\"%s is not a %s\",method:\"%s is not a %s (function)\",array:\"%s is not an %s\",object:\"%s is not an %s\",number:\"%s is not a %s\",date:\"%s is not a %s\",boolean:\"%s is not a %s\",integer:\"%s is not an %s\",float:\"%s is not a %s\",regexp:\"%s is not a valid %s\",email:\"%s is not a valid %s\",url:\"%s is not a valid %s\",hex:\"%s is not a valid %s\"},string:{len:\"%s must be exactly %s characters\",min:\"%s must be at least %s characters\",max:\"%s cannot be longer than %s characters\",range:\"%s must be between %s and %s characters\"},number:{len:\"%s must equal %s\",min:\"%s cannot be less than %s\",max:\"%s cannot be greater than %s\",range:\"%s must be between %s and %s\"},array:{len:\"%s must be exactly %s in length\",min:\"%s cannot be less than %s in length\",max:\"%s cannot be greater than %s in length\",range:\"%s must be between %s and %s in length\"},pattern:{mismatch:\"%s value %s does not match pattern %s\"},clone:function(){var t=JSON.parse(JSON.stringify(this));return t.clone=this.clone,t}}}var uS=$1();function al(e){this.rules=null,this._messages=uS,this.define(e)}al.prototype={messages:function(t){return t&&(this._messages=LT($1(),t)),this._messages},define:function(t){if(!t)throw new Error(\"Cannot configure a schema with no rules\");if(typeof t!=\"object\"||Array.isArray(t))throw new Error(\"Rules must be an object\");this.rules={};var n,r;for(n in t)t.hasOwnProperty(n)&&(r=t[n],this.rules[n]=Array.isArray(r)?r:[r])},validate:function(t,n,r){var a=this;n===void 0&&(n={}),r===void 0&&(r=function(){});var o=t,i=n,l=r;if(typeof i==\"function\"&&(l=i,i={}),!this.rules||Object.keys(this.rules).length===0)return l&&l(),Promise.resolve();function s(y){var b,C=[],S={};function w(k){if(Array.isArray(k)){var $;C=($=C).concat.apply($,k)}else C.push(k)}for(b=0;b<y.length;b++)w(y[b]);C.length?S=k1(C):(C=null,S=null),l(C,S)}if(i.messages){var c=this.messages();c===uS&&(c=$1()),LT(c,i.messages),i.messages=c}else i.messages=this.messages();var d,f,p={},v=i.keys||Object.keys(this.rules);v.forEach(function(y){d=a.rules[y],f=o[y],d.forEach(function(b){var C=b;typeof C.transform==\"function\"&&(o===t&&(o=Jl({},o)),f=o[y]=C.transform(f)),typeof C==\"function\"?C={validator:C}:C=Jl({},C),C.validator=a.getValidationMethod(C),C.field=y,C.fullField=C.fullField||y,C.type=a.getType(C),C.validator&&(p[y]=p[y]||[],p[y].push({rule:C,value:f,source:o,field:y}))})});var m={};return __e(p,i,function(y,b){var C=y.rule,S=(C.type===\"object\"||C.type===\"array\")&&(typeof C.fields==\"object\"||typeof C.defaultField==\"object\");S=S&&(C.required||!C.required&&y.value),C.field=y.field;function w(O,T){return Jl({},T,{fullField:C.fullField+\".\"+O})}function k(O){O===void 0&&(O=[]);var T=O;if(Array.isArray(T)||(T=[T]),!i.suppressWarning&&T.length&&al.warning(\"async-validator:\",T),T.length&&C.message!==void 0&&(T=[].concat(C.message)),T=T.map(RT(C)),i.first&&T.length)return m[C.field]=1,b(T);if(!S)b(T);else{if(C.required&&!y.value)return C.message!==void 0?T=[].concat(C.message).map(RT(C)):i.error&&(T=[i.error(C,da(i.messages.required,C.field))]),b(T);var _={};if(C.defaultField)for(var I in y.value)y.value.hasOwnProperty(I)&&(_[I]=C.defaultField);_=Jl({},_,y.rule.fields);for(var L in _)if(_.hasOwnProperty(L)){var j=Array.isArray(_[L])?_[L]:[_[L]];_[L]=j.map(w.bind(null,L))}var F=new al(_);F.messages(i.messages),y.rule.options&&(y.rule.options.messages=i.messages,y.rule.options.error=i.error),F.validate(y.value,y.rule.options||i,function(N){var D=[];T&&T.length&&D.push.apply(D,T),N&&N.length&&D.push.apply(D,N),b(D.length?D:null)})}}var $;C.asyncValidator?$=C.asyncValidator(C,y.value,k,y.source,i):C.validator&&($=C.validator(C,y.value,k,y.source,i),$===!0?k():$===!1?k(C.message||C.field+\" fails\"):$ instanceof Array?k($):$ instanceof Error&&k($.message)),$&&$.then&&$.then(function(){return k()},function(O){return k(O)})},function(y){s(y)})},getType:function(t){if(t.type===void 0&&t.pattern instanceof RegExp&&(t.type=\"pattern\"),typeof t.validator!=\"function\"&&t.type&&!xd.hasOwnProperty(t.type))throw new Error(da(\"Unknown rule type %s\",t.type));return t.type||\"string\"},getValidationMethod:function(t){if(typeof t.validator==\"function\")return t.validator;var n=Object.keys(t),r=n.indexOf(\"message\");return r!==-1&&n.splice(r,1),n.length===1&&n[0]===\"required\"?xd.required:xd[this.getType(t)]||!1}};al.register=function(t,n){if(typeof n!=\"function\")throw new Error(\"Cannot register a validator by type, validator is not a function\");xd[t]=n};al.warning=O_e;al.messages=uS;al.validators=xd;function vi(e){return e==null?[]:Array.isArray(e)?e:[e]}function O1(e){return vi(e)}function X_e(e,t){return e&&e.some(function(n){return J_e(n,t)})}function FT(e){return kt(e)===\"object\"&&e!==null&&Object.getPrototypeOf(e)===Object.prototype}function g7(e,t){var n=Array.isArray(e)?Je(e):P({},e);return t&&Object.keys(t).forEach(function(r){var a=n[r],o=t[r],i=FT(a)&&FT(o);n[r]=i?g7(a,o||{}):o}),n}function Z_e(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return n.reduce(function(a,o){return g7(a,o)},e)}function J_e(e,t){return!e||!t||e.length!==t.length?!1:e.every(function(n,r){return t[r]===n})}var Zr=\"'${name}' is not a valid ${type}\",cS={default:\"Validation error on field '${name}'\",required:\"'${name}' is required\",enum:\"'${name}' must be one of [${enum}]\",whitespace:\"'${name}' cannot be empty\",date:{format:\"'${name}' is invalid for format date\",parse:\"'${name}' could not be parsed as date\",invalid:\"'${name}' is invalid date\"},types:{string:Zr,method:Zr,array:Zr,object:Zr,number:Zr,date:Zr,boolean:Zr,integer:Zr,float:Zr,regexp:Zr,email:Zr,url:Zr,hex:Zr},string:{len:\"'${name}' must be exactly ${len} characters\",min:\"'${name}' must be at least ${min} characters\",max:\"'${name}' cannot be longer than ${max} characters\",range:\"'${name}' must be between ${min} and ${max} characters\"},number:{len:\"'${name}' must equal ${len}\",min:\"'${name}' cannot be less than ${min}\",max:\"'${name}' cannot be greater than ${max}\",range:\"'${name}' must be between ${min} and ${max}\"},array:{len:\"'${name}' must be exactly ${len} in length\",min:\"'${name}' cannot be less than ${min} in length\",max:\"'${name}' cannot be greater than ${max} in length\",range:\"'${name}' must be between ${min} and ${max} in length\"},pattern:{mismatch:\"'${name}' does not match pattern ${pattern}\"}},Eg=globalThis&&globalThis.__awaiter||function(e,t,n,r){function a(o){return o instanceof n?o:new n(function(i){i(o)})}return new(n||(n=Promise))(function(o,i){function l(d){try{c(r.next(d))}catch(f){i(f)}}function s(d){try{c(r.throw(d))}catch(f){i(f)}}function c(d){d.done?o(d.value):a(d.value).then(l,s)}c((r=r.apply(e,t||[])).next())})},Q_e=al;function e6e(e,t){return e.replace(/\\$\\{\\w+\\}/g,function(n){var r=n.slice(2,-1);return t[r]})}function P1(e,t,n,r,a){return Eg(this,void 0,void 0,pl.mark(function o(){var i,l,s,c,d,f,p,v;return pl.wrap(function(y){for(;;)switch(y.prev=y.next){case 0:return i=P({},n),delete i.ruleIndex,l=null,i&&i.type===\"array\"&&i.defaultField&&(l=i.defaultField,delete i.defaultField),s=new Q_e(V({},e,[i])),c=Z_e({},cS,r.validateMessages),s.messages(c),d=[],y.prev=8,y.next=11,Promise.resolve(s.validate(V({},e,t),P({},r)));case 11:y.next=16;break;case 13:y.prev=13,y.t0=y.catch(8),y.t0.errors?d=y.t0.errors.map(function(b,C){var S=b.message;return zn(S)?hr(S,{key:\"error_\".concat(C)}):S}):(console.error(y.t0),d=[c.default()]);case 16:if(!(!d.length&&l)){y.next=21;break}return y.next=19,Promise.all(t.map(function(b,C){return P1(\"\".concat(e,\".\").concat(C),b,l,r,a)}));case 19:return f=y.sent,y.abrupt(\"return\",f.reduce(function(b,C){return[].concat(Je(b),Je(C))},[]));case 21:return p=P(P(P({},n),{name:e,enum:(n.enum||[]).join(\", \")}),a),v=d.map(function(b){return typeof b==\"string\"?e6e(b,p):b}),y.abrupt(\"return\",v);case 24:case\"end\":return y.stop()}},o,null,[[8,13]])}))}function y7(e,t,n,r,a,o){var i=this,l=e.join(\".\"),s=n.map(function(f,p){var v=f.validator,m=P(P({},f),{ruleIndex:p});return v&&(m.validator=function(y,b,C){var S=!1,w=function(){for(var O=arguments.length,T=new Array(O),_=0;_<O;_++)T[_]=arguments[_];Promise.resolve().then(function(){S||C.apply(void 0,T)})},k=v(y,b,w);S=k&&typeof k.then==\"function\"&&typeof k.catch==\"function\",S&&k.then(function(){C()}).catch(function($){C($||\" \")})}),m}).sort(function(f,p){var v=f.warningOnly,m=f.ruleIndex,y=p.warningOnly,b=p.ruleIndex;return!!v==!!y?m-b:v?1:-1}),c;if(a===!0)c=new Promise(function(f,p){return Eg(i,void 0,void 0,pl.mark(function v(){var m,y,b;return pl.wrap(function(S){for(;;)switch(S.prev=S.next){case 0:m=0;case 1:if(!(m<s.length)){S.next=12;break}return y=s[m],S.next=5,P1(l,t,y,r,o);case 5:if(b=S.sent,!b.length){S.next=9;break}return p([{errors:b,rule:y}]),S.abrupt(\"return\");case 9:m+=1,S.next=1;break;case 12:f([]);case 13:case\"end\":return S.stop()}},v)}))});else{var d=s.map(function(f){return P1(l,t,f,r,o).then(function(p){return{errors:p,rule:f}})});c=(a?n6e(d):t6e(d)).then(function(f){return Promise.reject(f)})}return c.catch(function(f){return f}),c}function t6e(e){return Eg(this,void 0,void 0,pl.mark(function t(){return pl.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.abrupt(\"return\",Promise.all(e).then(function(a){var o,i=(o=[]).concat.apply(o,Je(a));return i}));case 1:case\"end\":return r.stop()}},t)}))}function n6e(e){return Eg(this,void 0,void 0,pl.mark(function t(){var n;return pl.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return n=0,a.abrupt(\"return\",new Promise(function(o){e.forEach(function(i){i.then(function(l){l.errors.length&&o([l]),n+=1,n===e.length&&o([])})})}));case 2:case\"end\":return a.stop()}},t)}))}var b7=Symbol(\"formContextKey\"),C7=function(t){ot(b7,t)},dS=function(){return ve(b7,{labelAlign:x(function(){return\"right\"}),vertical:x(function(){return!1}),addField:function(n,r){},removeField:function(n){},model:x(function(){}),rules:x(function(){}),requiredMark:x(function(){return!1})})},w7=Symbol(\"formItemPrefixContextKey\"),r6e=function(t){ot(w7,t)},a6e=function(){return ve(w7,{prefixCls:x(function(){return\"\"})})},fS=function(t,n){var r,a=n.slots,o=n.emit,i=n.attrs,l,s,c,d,f,p=P(P({},t),i),v=p.prefixCls,m=p.htmlFor,y=p.labelCol,b=p.labelAlign,C=p.colon,S=p.required,w=p.requiredMark,k=f0e(\"Form\"),$=fn(k,1),O=$[0],T=(l=t.label)!==null&&l!==void 0?l:(s=a.label)===null||s===void 0?void 0:s.call(a);if(!T)return null;var _=dS(),I=_.vertical,L=_.labelAlign,j=_.labelCol,F=_.colon,N=y||(j==null?void 0:j.value)||{},D=b||(L==null?void 0:L.value),z=\"\".concat(v,\"-item-label\"),B=Se(z,D===\"left\"&&\"\".concat(z,\"-left\"),N.class),M=T,E=C===!0||(F==null?void 0:F.value)!==!1&&C!==!1,K=E&&!I.value;K&&typeof T==\"string\"&&T.trim()!==\"\"&&(M=T.replace(/[:|：]\\s*$/,\"\")),M=g(Fe,null,[M,(c=a.tooltip)===null||c===void 0?void 0:c.call(a,{class:\"\".concat(v,\"-item-tooltip\")})]),w===\"optional\"&&!S&&(M=g(Fe,null,[M,g(\"span\",{class:\"\".concat(v,\"-item-optional\")},[((d=O.value)===null||d===void 0?void 0:d.optional)||((f=lo.Form)===null||f===void 0?void 0:f.optional)])]));var W=Se((r={},V(r,\"\".concat(v,\"-item-required\"),S),V(r,\"\".concat(v,\"-item-required-mark-optional\"),w===\"optional\"),V(r,\"\".concat(v,\"-item-no-colon\"),!E),r));return g(Og,le(le({},N),{},{class:B}),{default:function(){return[g(\"label\",{\"html-for\":m,class:W,title:typeof T==\"string\"?T:\"\",onClick:function(J){return o(\"click\",J)}},[M])]}})};fS.displayName=\"FormItemLabel\";fS.inheritAttrs=!1;var o6e=fS,i6e=G({name:\"ErrorList\",props:[\"errors\",\"help\",\"onDomErrorVisibleChange\"],setup:function(t){var n=Wt(\"\",t),r=n.prefixCls,a=a6e(),o=a.prefixCls,i=a.status,l=H(!!(t.errors&&t.errors.length)),s=H(i.value),c=H(),d=H(Je(t.errors));return ce([function(){return Je(t.errors)},function(){return t.help}],function(f){window.clearTimeout(c.value),t.help?(l.value=!!(t.errors&&t.errors.length),l.value&&(d.value=f[0])):c.value=window.setTimeout(function(){l.value=!!(t.errors&&t.errors.length),l.value&&(d.value=f[0])})}),Lt(function(){window.clearTimeout(c.value)}),ce([l,i],function(){l.value&&i.value&&(s.value=i.value)}),ce(l,function(){var f;l.value&&((f=t.onDomErrorVisibleChange)===null||f===void 0||f.call(t,!0))},{immediate:!0,flush:\"post\"}),function(){var f,p=\"\".concat(o.value,\"-item-explain\"),v=Lo(\"\".concat(r.value,\"-show-help\"),{onAfterLeave:function(){var y;(y=t.onDomErrorVisibleChange)===null||y===void 0||y.call(t,!1)}});return g(Cg,v,{default:function(){return[l.value?g(\"div\",{class:Se(p,V({},\"\".concat(p,\"-\").concat(s.value),s.value)),key:\"help\"},[(f=d.value)===null||f===void 0?void 0:f.map(function(y,b){return g(\"div\",{key:b,role:\"alert\"},[y])})]):null]}})}}}),l6e={success:zf,warning:Hf,error:Yr,validating:co},s6e=G({slots:[\"help\",\"extra\",\"errors\"],inheritAttrs:!1,props:[\"prefixCls\",\"errors\",\"hasFeedback\",\"validateStatus\",\"onDomErrorVisibleChange\",\"wrapperCol\",\"help\",\"extra\",\"status\"],setup:function(t,n){var r=n.slots,a=dS(),o=a.wrapperCol,i=P({},a);return delete i.labelCol,delete i.wrapperCol,C7(i),r6e({prefixCls:x(function(){return t.prefixCls}),status:x(function(){return t.status})}),Wr(function(){t.onDomErrorVisibleChange(!1)}),function(){var l,s,c,d,f=t.prefixCls,p=t.wrapperCol,v=t.help,m=v===void 0?(l=r.help)===null||l===void 0?void 0:l.call(r):v,y=t.errors,b=y===void 0?(s=r.errors)===null||s===void 0?void 0:s.call(r):y,C=t.onDomErrorVisibleChange,S=t.hasFeedback,w=t.validateStatus,k=t.extra,$=k===void 0?(c=r.extra)===null||c===void 0?void 0:c.call(r):k,O=\"\".concat(f,\"-item\"),T=p||(o==null?void 0:o.value)||{},_=Se(\"\".concat(O,\"-control\"),T.class),I=w&&l6e[w],L=S&&I?g(\"span\",{class:\"\".concat(O,\"-children-icon\")},[g(I,null,null)]):null,j=g(\"div\",{class:\"\".concat(O,\"-control-input\")},[g(\"div\",{class:\"\".concat(O,\"-control-input-content\")},[(d=r.default)===null||d===void 0?void 0:d.call(r)]),L]),F=g(i6e,{errors:b,help:m,onDomErrorVisibleChange:C},null),N=$?g(\"div\",{class:\"\".concat(O,\"-extra\")},[$]):null;return g(Og,le(le({},T),{},{class:_}),{default:function(){return[j,F,N]}})}}}),u6e=s6e;rt(\"success\",\"warning\",\"error\",\"validating\",\"\");function fb(e,t,n){var r=e,a=t,o=0;try{for(var i=a.length;o<i-1&&!(!r&&!n);++o){var l=a[o];if(l in r)r=r[l];else{if(n)throw Error(\"please transfer a valid name path to form item!\");break}}if(n&&!r)throw Error(\"please transfer a valid name path to form item!\")}catch{console.error(\"please transfer a valid name path to form item!\")}return{o:r,k:a[o],v:r?r[a[o]]:void 0}}var c6e={id:u.string,htmlFor:u.string,prefixCls:u.string,label:u.VNodeChild,help:u.VNodeChild,extra:u.VNodeChild,labelCol:{type:Object},wrapperCol:{type:Object},hasFeedback:u.looseBool.def(!1),colon:u.looseBool,labelAlign:u.oneOf(rt(\"left\",\"right\")),prop:{type:[String,Number,Array]},name:{type:[String,Number,Array]},rules:u.oneOfType([Array,Object]),autoLink:u.looseBool.def(!0),required:u.looseBool,validateFirst:u.looseBool,validateStatus:u.oneOf(rt(\"\",\"success\",\"warning\",\"error\",\"validating\")),validateTrigger:{type:[String,Array]},messageVariables:{type:Object},hidden:Boolean},d6e=0,S7=G({name:\"AFormItem\",mixins:[nt],inheritAttrs:!1,__ANT_NEW_FORM_ITEM:!0,props:c6e,slots:[\"help\",\"label\",\"extra\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.expose;t.prop;var i=\"form-item-\".concat(++d6e),l=Wt(\"form\",t),s=l.prefixCls,c=dS(),d=x(function(){return t.name||t.prop}),f=H([]),p=H(!1),v=H(!1),m=H(),y=x(function(){var z=d.value;return O1(z)}),b=x(function(){var z=t.id;if(z)return z;if(y.value.length){var B=c.name.value,M=y.value.join(\"_\");return B?\"\".concat(B,\"_\").concat(M):M}else return}),C=x(function(){var z=c.model.value;if(!(!z||!d.value))return fb(z,y.value,!0).v}),S=H(lp(C.value)),w=x(function(){var z=t.validateTrigger!==void 0?t.validateTrigger:c.validateTrigger.value;return z=z===void 0?\"change\":z,vi(z)}),k=x(function(){var z=c.rules.value,B=t.rules,M=t.required!==void 0?{required:!!t.required,trigger:w.value}:[],E=fb(z,y.value);z=z?E.o[E.k]||E.v:[];var K=[].concat(B||z||[]);return aW(K,function(W){return W.required})?K:K.concat(M)}),$=x(function(){var z=k.value,B=!1;return z&&z.length&&z.every(function(M){return M.required?(B=!0,!1):!0}),B||t.required}),O=H();Wn(function(){O.value=t.validateStatus});var T=function(B){var M=t.validateFirst,E=M===void 0?!1:M,K=t.messageVariables,W=B||{},Y=W.triggerName,q=k.value;if(Y&&(q=q.filter(function(ne){var oe=ne.trigger;if(!oe&&!w.value.length)return!0;var Q=vi(oe||w.value);return Q.includes(Y)})),!q.length)return Promise.resolve();var J=y7(y.value,C.value,q,B,E,K);return O.value=\"validating\",f.value=[],J.catch(function(ne){return ne}).then(function(){var ne=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[];if(O.value===\"validating\"){var oe=ne.filter(function(Q){return Q&&Q.errors.length});O.value=oe.length?\"error\":\"success\",f.value=oe.map(function(Q){return Q.errors})}}),J},_=function(){T({triggerName:\"blur\"})},I=function(){if(p.value){p.value=!1;return}T({triggerName:\"change\"})},L=function(){O.value=\"\",p.value=!1,f.value=[]},j=function(){O.value=\"\",p.value=!0,f.value=[];var B=c.model.value||{},M=C.value,E=fb(B,y.value,!0);Array.isArray(M)?E.o[E.k]=[].concat(S.value):E.o[E.k]=S.value,Ne(function(){p.value=!1})},F=function(){var B=b.value;if(!(!B||!m.value)){var M=m.value.$el.querySelector('[id=\"'.concat(B,'\"]'));M&&M.focus&&M.focus()}};o({onFieldBlur:_,onFieldChange:I,clearValidate:L,resetField:j});var N=!1;ce(d,function(z){z?N||(N=!0,c.addField(i,{fieldValue:C,fieldId:b,fieldName:d,resetField:j,clearValidate:L,namePath:y,validateRules:T,rules:k})):(N=!1,c.removeField(i))},{immediate:!0}),Lt(function(){c.removeField(i)});var D=x(function(){var z;return z={},V(z,\"\".concat(s.value,\"-item\"),!0),V(z,\"\".concat(s.value,\"-item-has-feedback\"),O.value&&t.hasFeedback),V(z,\"\".concat(s.value,\"-item-has-success\"),O.value===\"success\"),V(z,\"\".concat(s.value,\"-item-has-warning\"),O.value===\"warning\"),V(z,\"\".concat(s.value,\"-item-has-error\"),O.value===\"error\"),V(z,\"\".concat(s.value,\"-item-is-validating\"),O.value===\"validating\"),V(z,\"\".concat(s.value,\"-item-hidden\"),t.hidden),z});return function(){var z,B,M,E,K,W,Y=(z=t.help)!==null&&z!==void 0?z:r.help?La(r.help()):null,q=Un((B=r.default)===null||B===void 0?void 0:B.call(r)),J=q[0];if(d.value&&t.autoLink&&zn(J)){var ne=J.props||{},oe=ne.onBlur,Q=ne.onChange;J=Ot(J,P(P({},b.value?{id:b.value}:void 0),{onBlur:function(){if(Array.isArray(Q))for(var de=0,be=Q.length;de<be;de++)oe[de].apply(oe,arguments);else oe&&oe.apply(void 0,arguments);_()},onChange:function(){if(Array.isArray(Q))for(var de=0,be=Q.length;de<be;de++)Q[de].apply(Q,arguments);else Q&&Q.apply(void 0,arguments);I()}}))}return g(Q2,le(le({},a),{},{class:[D.value,v.value||!!Y?\"\".concat(s.value,\"-item-with-help\"):\"\",a.class],key:\"row\"}),{default:function(){return[g(o6e,le(le({},t),{},{htmlFor:b.value,required:$.value,requiredMark:c.requiredMark.value,prefixCls:s.value,onClick:F,label:(M=t.label)!==null&&M!==void 0?M:(E=r.label)===null||E===void 0?void 0:E.call(r)}),null),g(u6e,le(le({},t),{},{errors:Y!=null?vi(Y):f.value,prefixCls:s.value,status:O.value,onDomErrorVisibleChange:function(be){return v.value=be},validateStatus:O.value,ref:m,help:Y,extra:(K=t.extra)!==null&&K!==void 0?K:(W=r.extra)===null||W===void 0?void 0:W.call(r)}),{default:function(){return[[J,q.slice(1)]]}})]}})}}});function k7(e){var t=!1,n=e.length,r=[];return e.length?new Promise(function(a,o){e.forEach(function(i,l){i.catch(function(s){return t=!0,s}).then(function(s){n-=1,r[l]=s,!(n>0)&&(t&&o(r),a(r))})})}):Promise.resolve([])}function BT(e){return typeof e==\"object\"&&e!=null&&e.nodeType===1}function VT(e,t){return(!t||e!==\"hidden\")&&e!==\"visible\"&&e!==\"clip\"}function hb(e,t){if(e.clientHeight<e.scrollHeight||e.clientWidth<e.scrollWidth){var n=getComputedStyle(e,null);return VT(n.overflowY,t)||VT(n.overflowX,t)||function(r){var a=function(o){if(!o.ownerDocument||!o.ownerDocument.defaultView)return null;try{return o.ownerDocument.defaultView.frameElement}catch{return null}}(r);return!!a&&(a.clientHeight<r.scrollHeight||a.clientWidth<r.scrollWidth)}(e)}return!1}function Wh(e,t,n,r,a,o,i,l){return o<e&&i>t||o>e&&i<t?0:o<=e&&l<=n||i>=t&&l>=n?o-e-r:i>t&&l<n||o<e&&l>n?i-t+a:0}function zT(e,t){var n=window,r=t.scrollMode,a=t.block,o=t.inline,i=t.boundary,l=t.skipOverflowHiddenElements,s=typeof i==\"function\"?i:function(Ee){return Ee!==i};if(!BT(e))throw new TypeError(\"Invalid target\");for(var c=document.scrollingElement||document.documentElement,d=[],f=e;BT(f)&&s(f);){if((f=f.parentElement)===c){d.push(f);break}f!=null&&f===document.body&&hb(f)&&!hb(document.documentElement)||f!=null&&hb(f,l)&&d.push(f)}for(var p=n.visualViewport?n.visualViewport.width:innerWidth,v=n.visualViewport?n.visualViewport.height:innerHeight,m=window.scrollX||pageXOffset,y=window.scrollY||pageYOffset,b=e.getBoundingClientRect(),C=b.height,S=b.width,w=b.top,k=b.right,$=b.bottom,O=b.left,T=a===\"start\"||a===\"nearest\"?w:a===\"end\"?$:w+C/2,_=o===\"center\"?O+S/2:o===\"end\"?k:O,I=[],L=0;L<d.length;L++){var j=d[L],F=j.getBoundingClientRect(),N=F.height,D=F.width,z=F.top,B=F.right,M=F.bottom,E=F.left;if(r===\"if-needed\"&&w>=0&&O>=0&&$<=v&&k<=p&&w>=z&&$<=M&&O>=E&&k<=B)return I;var K=getComputedStyle(j),W=parseInt(K.borderLeftWidth,10),Y=parseInt(K.borderTopWidth,10),q=parseInt(K.borderRightWidth,10),J=parseInt(K.borderBottomWidth,10),ne=0,oe=0,Q=\"offsetWidth\"in j?j.offsetWidth-j.clientWidth-W-q:0,ae=\"offsetHeight\"in j?j.offsetHeight-j.clientHeight-Y-J:0;if(c===j)ne=a===\"start\"?T:a===\"end\"?T-v:a===\"nearest\"?Wh(y,y+v,v,Y,J,y+T,y+T+C,C):T-v/2,oe=o===\"start\"?_:o===\"center\"?_-p/2:o===\"end\"?_-p:Wh(m,m+p,p,W,q,m+_,m+_+S,S),ne=Math.max(0,ne+y),oe=Math.max(0,oe+m);else{ne=a===\"start\"?T-z-Y:a===\"end\"?T-M+J+ae:a===\"nearest\"?Wh(z,M,N,Y,J+ae,T,T+C,C):T-(z+N/2)+ae/2,oe=o===\"start\"?_-E-W:o===\"center\"?_-(E+D/2)+Q/2:o===\"end\"?_-B+q+Q:Wh(E,B,D,W,q+Q,_,_+S,S);var de=j.scrollLeft,be=j.scrollTop;T+=be-(ne=Math.max(0,Math.min(be+ne,j.scrollHeight-N+ae))),_+=de-(oe=Math.max(0,Math.min(de+oe,j.scrollWidth-D+Q)))}I.push({el:j,top:ne,left:oe})}return I}function $7(e){return e===Object(e)&&Object.keys(e).length!==0}function f6e(e,t){t===void 0&&(t=\"auto\");var n=\"scrollBehavior\"in document.body.style;e.forEach(function(r){var a=r.el,o=r.top,i=r.left;a.scroll&&n?a.scroll({top:o,left:i,behavior:t}):(a.scrollTop=o,a.scrollLeft=i)})}function h6e(e){return e===!1?{block:\"end\",inline:\"nearest\"}:$7(e)?e:{block:\"start\",inline:\"nearest\"}}function p6e(e,t){var n=e.isConnected||e.ownerDocument.documentElement.contains(e);if($7(t)&&typeof t.behavior==\"function\")return t.behavior(n?zT(e,t):[]);if(!!n){var r=h6e(t);return f6e(zT(e,r),r.behavior)}}function HT(e){var t=!1;return e&&e.length&&e.every(function(n){return n.required?(t=!0,!1):!0}),t}function jT(e){return e==null?[]:Array.isArray(e)?e:[e]}function pb(e,t,n){var r=e;t=t.replace(/\\[(\\w+)\\]/g,\".$1\"),t=t.replace(/^\\./,\"\");for(var a=t.split(\".\"),o=0,i=a.length;o<i-1&&!(!r&&!n);++o){var l=a[o];if(l in r)r=r[l];else{if(n)throw new Error(\"please transfer a valid name path to validate!\");break}}return{o:r,k:a[o],v:r?r[a[o]]:null,isValid:r&&a[o]in r}}function v6e(e,t,n){var r=lp(A(e)),a=bt({}),o=x(function(){return t?Object.keys(A(t)):[]});ce(o,function(){var S={};o.value.forEach(function(k){S[k]=a[k]||{autoLink:!1,required:HT(A(t)[k])},delete a[k]});for(var w in a)Object.prototype.hasOwnProperty.call(a,w)&&delete a[w];P(a,S)},{immediate:!0});var i=function(w){P(A(e),P(P({},lp(r)),w)),Ne(function(){Object.keys(a).forEach(function(k){a[k]={autoLink:!1,required:HT(A(t)[k])}})})},l=function(){var w=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],k=arguments.length>1?arguments[1]:void 0;return k.length?w.filter(function($){var O=jT($.trigger||\"change\");return fW(O,k).length}):w},s=null,c=function(w){for(var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},$=arguments.length>2?arguments[2]:void 0,O=[],T={},_=function(D){var z=w[D],B=pb(A(e),z,$);if(!B.isValid)return\"continue\";T[z]=B.v;var M=l(A(t)[z],jT(k&&k.trigger));M.length&&O.push(d(z,B.v,M,k||{}).then(function(){return{name:z,errors:[],warnings:[]}}).catch(function(E){var K=[],W=[];return E.forEach(function(Y){var q=Y.rule.warningOnly,J=Y.errors;q?W.push.apply(W,Je(J)):K.push.apply(K,Je(J))}),K.length?Promise.reject({name:z,errors:K,warnings:W}):{name:z,errors:K,warnings:W}}))},I=0;I<w.length;I++)var L=_(I);var j=k7(O);s=j;var F=j.then(function(){return s===j?Promise.resolve(T):Promise.reject([])}).catch(function(N){var D=N.filter(function(z){return z&&z.errors.length});return Promise.reject({values:T,errorFields:D,outOfDate:s!==j})});return F.catch(function(N){return N}),F},d=function(w,k,$){var O=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},T=y7([w],k,$,P({validateMessages:cS},O),!!O.validateFirst);return a[w]?(a[w].validateStatus=\"validating\",T.catch(function(_){return _}).then(function(){var _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[];if(a[w].validateStatus===\"validating\"){var I=_.filter(function(L){return L&&L.errors.length});a[w].validateStatus=I.length?\"error\":\"success\",a[w].help=I.length?I.map(function(L){return L.errors}):\"\"}}),T):T.catch(function(_){return _})},f=function(w,k){var $=[],O=!0;w?Array.isArray(w)?$=w:$=[w]:(O=!1,$=o.value);var T=c($,k||{},O);return T.catch(function(_){return _}),T},p=function(w){var k=[];w?Array.isArray(w)?k=w:k=[w]:k=o.value,k.forEach(function($){a[$]&&P(a[$],{validateStatus:\"\",help:\"\"})})},v=function(w){for(var k={autoLink:!1},$=[],O=Array.isArray(w)?w:[w],T=0;T<O.length;T++){var _=O[T];(_==null?void 0:_.validateStatus)===\"error\"&&(k.validateStatus=\"error\",_.help&&$.push(_.help)),k.required=k.required||(_==null?void 0:_.required)}return k.help=$,k},m=r,y=!0,b=function(w){var k=[];o.value.forEach(function($){var O=pb(w,$,!1),T=pb(m,$,!1),_=y&&(n==null?void 0:n.immediate)&&O.isValid;(_||!er(O.v,T.v))&&k.push($)}),f(k,{trigger:\"change\"}),y=!1,m=lp(w)},C=n==null?void 0:n.debounce;return ce(e,C&&C.wait?Yn(b,C.wait,MC(C,[\"wait\"])):b,{immediate:n&&!!n.immediate,deep:!0}),ce(t,function(){n&&n.validateOnRuleChange&&f()},{deep:!0}),{modelRef:e,rulesRef:t,initialModel:r,validateInfos:a,resetFields:i,validate:f,validateField:d,mergeValidateInfo:v,clearValidate:p}}var m6e={layout:u.oneOf(rt(\"horizontal\",\"inline\",\"vertical\")),labelCol:{type:Object},wrapperCol:{type:Object},colon:u.looseBool,labelAlign:u.oneOf(rt(\"left\",\"right\")),prefixCls:u.string,requiredMark:{type:[String,Boolean],default:void 0},hideRequiredMark:u.looseBool,model:u.object,rules:{type:Object},validateMessages:u.object,validateOnRuleChange:u.looseBool,scrollToFirstError:{type:[Boolean,Object]},onSubmit:u.func,onFinish:u.func,onFinishFailed:u.func,name:u.string,validateTrigger:{type:[String,Array]},size:{type:String}};function g6e(e,t){return er(vi(e),vi(t))}var y6e=G({name:\"AForm\",inheritAttrs:!1,props:Rn(m6e,{layout:\"horizontal\",hideRequiredMark:!1,colon:!0}),Item:S7,useForm:v6e,emits:[\"finishFailed\",\"submit\",\"finish\"],setup:function(t,n){var r=n.emit,a=n.slots,o=n.expose,i=n.attrs,l=zA(t),s=Wt(\"form\",t),c=s.prefixCls,d=s.direction,f=s.form,p=x(function(){return t.requiredMark===\"\"||t.requiredMark}),v=x(function(){var N;return p.value!==void 0?p.value:f&&((N=f.value)===null||N===void 0?void 0:N.requiredMark)!==void 0?f.value.requiredMark:!t.hideRequiredMark}),m=x(function(){var N;return Se(c.value,(N={},V(N,\"\".concat(c.value,\"-\").concat(t.layout),!0),V(N,\"\".concat(c.value,\"-hide-required-mark\"),v.value===!1),V(N,\"\".concat(c.value,\"-rtl\"),d.value===\"rtl\"),V(N,\"\".concat(c.value,\"-\").concat(l.value),l.value),N))}),y=H(),b={},C=function(D,z){b[D]=z},S=function(D){delete b[D]},w=function(D){var z=!!D,B=z?vi(D).map(O1):[];return z?Object.values(b).filter(function(M){return B.findIndex(function(E){return g6e(E,M.fieldName.value)})>-1}):Object.values(b)},k=function(D){if(!t.model){on(!1,\"Form\",\"model is required for resetFields to work.\");return}w(D).forEach(function(z){z.resetField()})},$=function(D){w(D).forEach(function(z){z.clearValidate()})},O=function(D){var z=t.scrollToFirstError;if(r(\"finishFailed\",D),z&&D.errorFields.length){var B={};kt(z)===\"object\"&&(B=z),_(D.errorFields[0].name,B)}},T=function(){return j.apply(void 0,arguments)},_=function(D){var z=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},B=w(D);if(B.length){var M=B[0].fieldId.value,E=M?document.getElementById(M):null;E&&p6e(E,P({scrollMode:\"if-needed\",block:\"nearest\"},z))}},I=function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!0,z={};if(Object.values(b).forEach(function(M){var E=M.fieldName,K=M.fieldValue;z[E.value]=K.value}),D===!0)return z;var B={};return vi(D).forEach(function(M){return B[M]=z[M]}),B},L=function(D,z){if(on(!(D instanceof Function),\"Form\",\"validateFields/validateField/validate not support callback, please use promise instead\"),!t.model)return on(!1,\"Form\",\"model is required for validateFields to work.\"),Promise.reject(\"Form `model` is required for validateFields to work.\");var B=!!D,M=B?vi(D).map(O1):[],E=[];Object.values(b).forEach(function(Y){var q;if(B||M.push(Y.namePath.value),!!(!((q=Y.rules)===null||q===void 0)&&q.value.length)){var J=Y.namePath.value;if(!B||X_e(M,J)){var ne=Y.validateRules(P({validateMessages:P(P({},cS),t.validateMessages)},z));E.push(ne.then(function(){return{name:J,errors:[],warnings:[]}}).catch(function(oe){var Q=[],ae=[];return oe.forEach(function(de){var be=de.rule.warningOnly,Ee=de.errors;be?ae.push.apply(ae,Je(Ee)):Q.push.apply(Q,Je(Ee))}),Q.length?Promise.reject({name:J,errors:Q,warnings:ae}):{name:J,errors:Q,warnings:ae}}))}}});var K=k7(E);y.value=K;var W=K.then(function(){return y.value===K?Promise.resolve(I(M)):Promise.reject([])}).catch(function(Y){var q=Y.filter(function(J){return J&&J.errors.length});return Promise.reject({values:I(M),errorFields:q,outOfDate:y.value!==K})});return W.catch(function(Y){return Y}),W},j=function(){return L.apply(void 0,arguments)},F=function(D){if(D.preventDefault(),D.stopPropagation(),r(\"submit\",D),t.model){var z=L();z.then(function(B){r(\"finish\",B)}).catch(function(B){O(B)})}};return o({resetFields:k,clearValidate:$,validateFields:L,getFieldsValue:I,validate:T,scrollToField:_}),C7({model:x(function(){return t.model}),name:x(function(){return t.name}),labelAlign:x(function(){return t.labelAlign}),labelCol:x(function(){return t.labelCol}),wrapperCol:x(function(){return t.wrapperCol}),vertical:x(function(){return t.layout===\"vertical\"}),colon:x(function(){return t.colon}),requiredMark:v,validateTrigger:x(function(){return t.validateTrigger}),rules:x(function(){return t.rules}),addField:C,removeField:S}),ce(function(){return t.rules},function(){t.validateOnRuleChange&&L()}),function(){var N;return g(\"form\",le(le({},i),{},{onSubmit:F,class:[m.value,i.class]}),[(N=a.default)===null||N===void 0?void 0:N.call(a)])}}}),pu=y6e;pu.install=function(e){return e.component(pu.name,pu),e.component(pu.Item.name,pu.Item),e};function b6e(){var e=document.documentElement.clientWidth,t=window.innerHeight||document.documentElement.clientHeight;return{width:e,height:t}}function O7(e){var t=e.getBoundingClientRect(),n=document.documentElement;return{left:t.left+(window.pageXOffset||n.scrollLeft)-(n.clientLeft||document.body.clientLeft||0),top:t.top+(window.pageYOffset||n.scrollTop)-(n.clientTop||document.body.clientTop||0)}}var C6e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"defs\",attrs:{},children:[{tag:\"style\",attrs:{}}]},{tag:\"path\",attrs:{d:\"M672 418H144c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H188V494h440v326z\"}},{tag:\"path\",attrs:{d:\"M819.3 328.5c-78.8-100.7-196-153.6-314.6-154.2l-.2-64c0-6.5-7.6-10.1-12.6-6.1l-128 101c-4 3.1-3.9 9.1 0 12.3L492 318.6c5.1 4 12.7.4 12.6-6.1v-63.9c12.9.1 25.9.9 38.8 2.5 42.1 5.2 82.1 18.2 119 38.7 38.1 21.2 71.2 49.7 98.4 84.3 27.1 34.7 46.7 73.7 58.1 115.8a325.95 325.95 0 016.5 140.9h74.9c14.8-103.6-11.3-213-81-302.3z\"}}]},name:\"rotate-left\",theme:\"outlined\"},w6e=C6e;function KT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){S6e(e,a,n[a])})}return e}function S6e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var hS=function(t,n){var r=KT({},t,n.attrs);return g(Et,KT({},r,{icon:w6e}),null)};hS.displayName=\"RotateLeftOutlined\";hS.inheritAttrs=!1;var k6e=hS,$6e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"defs\",attrs:{},children:[{tag:\"style\",attrs:{}}]},{tag:\"path\",attrs:{d:\"M480.5 251.2c13-1.6 25.9-2.4 38.8-2.5v63.9c0 6.5 7.5 10.1 12.6 6.1L660 217.6c4-3.2 4-9.2 0-12.3l-128-101c-5.1-4-12.6-.4-12.6 6.1l-.2 64c-118.6.5-235.8 53.4-314.6 154.2A399.75 399.75 0 00123.5 631h74.9c-.9-5.3-1.7-10.7-2.4-16.1-5.1-42.1-2.1-84.1 8.9-124.8 11.4-42.2 31-81.1 58.1-115.8 27.2-34.7 60.3-63.2 98.4-84.3 37-20.6 76.9-33.6 119.1-38.8z\"}},{tag:\"path\",attrs:{d:\"M880 418H352c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H396V494h440v326z\"}}]},name:\"rotate-right\",theme:\"outlined\"},O6e=$6e;function WT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){P6e(e,a,n[a])})}return e}function P6e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var pS=function(t,n){var r=WT({},t,n.attrs);return g(Et,WT({},r,{icon:O6e}),null)};pS.displayName=\"RotateRightOutlined\";pS.inheritAttrs=!1;var T6e=pS,x6e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M637 443H519V309c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v134H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h118v134c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V519h118c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z\"}}]},name:\"zoom-in\",theme:\"outlined\"},_6e=x6e;function UT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){E6e(e,a,n[a])})}return e}function E6e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var vS=function(t,n){var r=UT({},t,n.attrs);return g(Et,UT({},r,{icon:_6e}),null)};vS.displayName=\"ZoomInOutlined\";vS.inheritAttrs=!1;var M6e=vS,I6e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M637 443H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h312c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z\"}}]},name:\"zoom-out\",theme:\"outlined\"},N6e=I6e;function YT(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){A6e(e,a,n[a])})}return e}function A6e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var mS=function(t,n){var r=YT({},t,n.attrs);return g(Et,YT({},r,{icon:N6e}),null)};mS.displayName=\"ZoomOutOutlined\";mS.inheritAttrs=!1;var D6e=mS,R6e={visible:u.looseBool,hiddenClassName:u.string,forceRender:u.looseBool},qT={props:R6e,render:function(){return g(\"div\",null,[ht(this)])}},sm=function(e){var t=document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)&&window.innerWidth>document.body.offsetWidth;if(!!t){if(e){document.body.style.position=\"\",document.body.style.width=\"\";return}var n=d7();n&&(document.body.style.position=\"relative\",document.body.style.width=\"calc(100% - \".concat(n,\"px)\"))}};function gS(){return{keyboard:u.looseBool,mask:u.looseBool,afterClose:u.func,closable:u.looseBool,maskClosable:u.looseBool,visible:u.looseBool,destroyOnClose:u.looseBool,mousePosition:u.shape({x:u.number,y:u.number}).loose,title:u.any,footer:u.any,transitionName:u.string,maskTransitionName:u.string,animation:u.any,maskAnimation:u.any,wrapStyle:u.object,bodyStyle:u.object,maskStyle:u.object,prefixCls:u.string,wrapClassName:u.string,width:u.oneOfType([u.string,u.number]),height:u.oneOfType([u.string,u.number]),zIndex:u.number,bodyProps:u.any,maskProps:u.any,wrapProps:u.any,getContainer:u.any,dialogStyle:u.object,dialogClass:u.string,closeIcon:u.any,forceRender:u.looseBool,getOpenCount:u.func,focusTriggerAfterClose:u.looseBool,onClose:u.func}}var L6e=gS(),F6e=0;function vb(){}function GT(e,t){var n=e[\"page\".concat(t?\"Y\":\"X\",\"Offset\")],r=\"scroll\".concat(t?\"Top\":\"Left\");if(typeof n!=\"number\"){var a=e.document;n=a.documentElement[r],typeof n!=\"number\"&&(n=a.body[r])}return n}function XT(e,t){var n=e.style;[\"Webkit\",\"Moz\",\"Ms\",\"ms\"].forEach(function(r){n[\"\".concat(r,\"TransformOrigin\")]=t}),n.transformOrigin=t}function B6e(e){var t=e.getBoundingClientRect(),n={left:t.left,top:t.top},r=e.ownerDocument,a=r.defaultView||r.parentWindow;return n.left+=GT(a),n.top+=GT(a,!0),n}var Zo={},ZT=G({name:\"VcDialog\",mixins:[nt],inheritAttrs:!1,props:An(L6e,{mask:!0,visible:!1,keyboard:!0,closable:!0,maskClosable:!0,destroyOnClose:!1,prefixCls:\"rc-dialog\",getOpenCount:function(){return null},focusTriggerAfterClose:!0}),data:function(){return on(!this.dialogClass,\"Modal\",\"dialogClass is deprecated, please use class instead.\"),on(!this.dialogStyle,\"Modal\",\"dialogStyle is deprecated, please use style instead.\"),{inTransition:!1,titleId:\"rcDialogTitle\".concat(F6e++),dialogMouseDown:void 0}},watch:{visible:function(t){var n=this;this.$nextTick(function(){n.updatedCallback(!t)})}},created:function(){ot(\"dialogContext\",this)},mounted:function(){var t=this;this.$nextTick(function(){t.updatedCallback(!1),(t.forceRender||t.getContainer===!1&&!t.visible)&&t.$refs.wrap&&(t.$refs.wrap.style.display=\"none\")})},beforeUnmount:function(){var t=this.visible,n=this.getOpenCount;(t||this.inTransition)&&!n()&&this.switchScrollingEffect(),clearTimeout(this.timeoutId)},methods:{getDialogWrap:function(){return this.$refs.wrap},updatedCallback:function(t){var n=this.mousePosition,r=this.mask,a=this.focusTriggerAfterClose;if(this.visible){if(!t){this.openTime=Date.now(),this.switchScrollingEffect(),this.tryFocus();var o=Sn(this.$refs.dialog);if(n){var i=B6e(o);XT(o,\"\".concat(n.x-i.left,\"px \").concat(n.y-i.top,\"px\"))}else XT(o,\"\")}}else if(t&&(this.inTransition=!0,r&&this.lastOutSideFocusNode&&a)){try{this.lastOutSideFocusNode.focus()}catch{this.lastOutSideFocusNode=null}this.lastOutSideFocusNode=null}},tryFocus:function(){bu(this.$refs.wrap,document.activeElement)||(this.lastOutSideFocusNode=document.activeElement,this.$refs.sentinelStart.focus())},onAnimateLeave:function(){var t=this.afterClose;this.$refs.wrap&&(this.$refs.wrap.style.display=\"none\"),this.inTransition=!1,this.switchScrollingEffect(),t&&t()},onDialogMouseDown:function(){this.dialogMouseDown=!0},onMaskMouseUp:function(){var t=this;this.dialogMouseDown&&(this.timeoutId=setTimeout(function(){t.dialogMouseDown=!1},0))},onMaskClick:function(t){Date.now()-this.openTime<300||t.target===t.currentTarget&&!this.dialogMouseDown&&this.close(t)},onKeydown:function(t){var n=this.$props;if(n.keyboard&&t.keyCode===ze.ESC){t.stopPropagation(),this.close(t);return}if(n.visible&&t.keyCode===ze.TAB){var r=document.activeElement,a=this.$refs.sentinelStart;t.shiftKey?r===a&&this.$refs.sentinelEnd.focus():r===this.$refs.sentinelEnd&&a.focus()}},getDialogElement:function(){var t=this,n=this.closable,r=this.prefixCls,a=this.width,o=this.height,i=this.title,l=this.footer,s=this.bodyStyle,c=this.visible,d=this.bodyProps,f=this.forceRender,p=this.closeIcon,v=this.dialogStyle,m=v===void 0?{}:v,y=this.dialogClass,b=y===void 0?\"\":y,C=P({},m);a!==void 0&&(C.width=typeof a==\"number\"?\"\".concat(a,\"px\"):a),o!==void 0&&(C.height=typeof o==\"number\"?\"\".concat(o,\"px\"):o);var S;l&&(S=g(\"div\",{key:\"footer\",class:\"\".concat(r,\"-footer\"),ref:\"footer\"},[l]));var w;i&&(w=g(\"div\",{key:\"header\",class:\"\".concat(r,\"-header\"),ref:\"header\"},[g(\"div\",{class:\"\".concat(r,\"-title\"),id:this.titleId},[i])]));var k;n&&(k=g(\"button\",{type:\"button\",key:\"close\",onClick:this.close||vb,\"aria-label\":\"Close\",class:\"\".concat(r,\"-close\")},[p||g(\"span\",{class:\"\".concat(r,\"-close-x\")},null)]));var $=this.$attrs,O=$.style,T=$.class,_=P(P({},O),C),I={width:0,height:0,overflow:\"hidden\"},L=[r,T,b],j=this.getTransitionName(),F=at(g(qT,{key:\"dialog-element\",role:\"document\",ref:\"dialog\",style:_,class:L,forceRender:f,onMousedown:this.onDialogMouseDown},{default:function(){return[g(\"div\",{tabindex:0,ref:\"sentinelStart\",style:I,\"aria-hidden\":\"true\"},null),g(\"div\",{class:\"\".concat(r,\"-content\")},[k,w,g(\"div\",le({key:\"body\",class:\"\".concat(r,\"-body\"),style:s,ref:\"body\"},d),[ht(t)]),S]),g(\"div\",{tabindex:0,ref:\"sentinelEnd\",style:I,\"aria-hidden\":\"true\"},null)]}}),[[_t,c]]),N=Lo(j,{onAfterLeave:this.onAnimateLeave});return g(no,le({key:\"dialog\"},N),{default:function(){return[c||!t.destroyOnClose?F:null]}})},getZIndexStyle:function(){var t={},n=this.$props;return n.zIndex!==void 0&&(t.zIndex=n.zIndex),t},getWrapStyle:function(){return P(P({},this.getZIndexStyle()),this.wrapStyle)},getMaskStyle:function(){return P(P({},this.getZIndexStyle()),this.maskStyle)},getMaskElement:function(){var t=this.$props,n;if(t.mask){var r=this.getMaskTransitionName(),a=at(g(qT,le({style:this.getMaskStyle(),key:\"mask\",class:\"\".concat(t.prefixCls,\"-mask\")},t.maskProps||{}),null),[[_t,t.visible]]);if(r){var o=Lo(r);n=g(no,le({key:\"mask\"},o),{default:function(){return[a]}})}else n=a}return n},getMaskTransitionName:function(){var t=this.$props,n=t.maskTransitionName,r=t.maskAnimation;return!n&&r&&(n=\"\".concat(t.prefixCls,\"-\").concat(r)),n},getTransitionName:function(){var t=this.$props,n=t.transitionName,r=t.animation;return!n&&r&&(n=\"\".concat(t.prefixCls,\"-\").concat(r)),n},switchScrollingEffect:function(){var t=this.getOpenCount,n=t();if(n===1){if(Zo.hasOwnProperty(\"overflowX\"))return;Zo={overflowX:document.body.style.overflowX,overflowY:document.body.style.overflowY,overflow:document.body.style.overflow},sm(),document.body.style.overflow=\"hidden\"}else n||(Zo.overflow!==void 0&&(document.body.style.overflow=Zo.overflow),Zo.overflowX!==void 0&&(document.body.style.overflowX=Zo.overflowX),Zo.overflowY!==void 0&&(document.body.style.overflowY=Zo.overflowY),Zo={},sm(!0))},close:function(t){this.__emit(\"close\",t)}},render:function(){var t=this.prefixCls,n=this.maskClosable,r=this.visible,a=this.wrapClassName,o=this.title,i=this.wrapProps,l=this.getWrapStyle();return r&&(l.display=null),g(\"div\",{class:\"\".concat(t,\"-root\")},[this.getMaskElement(),g(\"div\",le({tabindex:-1,onKeydown:this.onKeydown,class:\"\".concat(t,\"-wrap \").concat(a||\"\"),ref:\"wrap\",onClick:n?this.onMaskClick:vb,onMouseup:n?this.onMaskMouseUp:vb,role:\"dialog\",\"aria-labelledby\":o?this.titleId:null,style:l},i),[this.getDialogElement()])])}});function JT(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.element,r=n===void 0?document.body:n,a={},o=Object.keys(e);return o.forEach(function(i){a[i]=r.style[i]}),o.forEach(function(i){r.style[i]=e[i]}),a}var Jr=0,V6e=!(typeof window!=\"undefined\"&&window.document&&window.document.createElement),Uh={},z6e=G({name:\"PortalWrapper\",props:{wrapperClassName:u.string,forceRender:u.looseBool,getContainer:u.any,children:u.func,visible:u.looseBool},data:function(){this._component=null;var t=this.$props.visible;return Jr=t?Jr+1:Jr,{}},watch:{visible:function(t){Jr=t?Jr+1:Jr-1},getContainer:function(t,n){var r=typeof t==\"function\"&&typeof n==\"function\";(r?t.toString()!==n.toString():t!==n)&&this.removeCurrentContainer(!1)}},updated:function(){this.setWrapperClassName()},beforeUnmount:function(){var t=this.$props.visible;Jr=t&&Jr?Jr-1:Jr,this.removeCurrentContainer(t)},methods:{getParent:function(){var t=this.$props.getContainer;if(t){if(typeof t==\"string\")return document.querySelectorAll(t)[0];if(typeof t==\"function\")return t();if(kt(t)===\"object\"&&t instanceof window.HTMLElement)return t}return document.body},getDomContainer:function(){if(V6e)return null;if(!this.container){this.container=document.createElement(\"div\");var t=this.getParent();t&&t.appendChild(this.container)}return this.setWrapperClassName(),this.container},setWrapperClassName:function(){var t=this.$props.wrapperClassName;this.container&&t&&t!==this.container.className&&(this.container.className=t)},savePortal:function(t){this._component=t},removeCurrentContainer:function(){this.container=null,this._component=null},switchScrollingEffect:function(){Jr===1&&!Object.keys(Uh).length?(sm(),Uh=JT({overflow:\"hidden\",overflowX:\"hidden\",overflowY:\"hidden\"})):Jr||(JT(Uh),Uh={},sm(!0))}},render:function(){var t=this.$props,n=t.children,r=t.forceRender,a=t.visible,o=null,i={getOpenCount:function(){return Jr},getContainer:this.getDomContainer,switchScrollingEffect:this.switchScrollingEffect};return(r||a||this._component)&&(o=g(SA,{getContainer:this.getDomContainer,children:n(i),ref:this.savePortal},null)),o}}),QT=gS(),H6e=G({inheritAttrs:!1,props:P(P({},QT),{visible:QT.visible.def(!1)}),render:function(){var t=this,n=this.$props,r=n.visible,a=n.getContainer,o=n.forceRender,i=P(P(P({},this.$props),this.$attrs),{ref:\"_component\",key:\"dialog\"});return a===!1?g(ZT,le(le({},i),{},{getOpenCount:function(){return 2}}),{default:function(){return[ht(t)]}}):g(z6e,{visible:r,forceRender:o,getContainer:a,children:function(s){return i=P(P({},i),s),g(ZT,i,{default:function(){return[ht(t)]}})}},null)}}),P7=H6e;function j6e(e){var t=H(null),n=bt(P({},e)),r=H([]),a=function(i){t.value===null&&(r.value=[],t.value=en(function(){var l;r.value.forEach(function(s){l=P(P({},l),s)}),P(n,l),t.value=null})),r.value.push(i)};return et(function(){t.value&&en.cancel(t.value)}),[n,a]}function ex(e,t,n,r){var a=t+n,o=(n-r)/2;if(n>r){if(t>0)return V({},e,o);if(t<0&&a<r)return V({},e,-o)}else if(t<0||a>r)return V({},e,t<0?o:-o);return{}}function K6e(e,t,n,r){var a=b6e(),o=a.width,i=a.height,l=null;return e<=o&&t<=i?l={x:0,y:0}:(e>o||t>i)&&(l=P(P({},ex(\"x\",n,e,o)),ex(\"y\",r,t,i))),l}var tx=Symbol(\"previewGroupContext\"),yS={provide:function(t){ot(tx,t)},inject:function(){return ve(tx,{isPreviewGroup:H(!1),previewUrls:bt({}),setPreviewUrls:function(){},current:H(null),setCurrent:function(){},setShowPreview:function(){},setMousePosition:function(){},registerImage:null})}},W6e=G({name:\"PreviewGroup\",inheritAttrs:!1,props:{previewPrefixCls:String},setup:function(t,n){var r=n.slots,a=bt({}),o=H(),i=H(!1),l=H(null),s=function(y){P(a,y)},c=function(y){o.value=y},d=function(y){l.value=y},f=function(y){i.value=y},p=function(y,b){return a[y]=b,function(){delete a[y]}},v=function(y){y==null||y.stopPropagation(),i.value=!1,l.value=null};return yS.provide({isPreviewGroup:H(!0),previewUrls:a,setPreviewUrls:s,current:o,setCurrent:c,setShowPreview:f,setMousePosition:d,registerImage:p}),function(){return g(Fe,null,[r.default&&r.default(),g(x7,{\"ria-hidden\":!i.value,visible:i.value,prefixCls:t.previewPrefixCls,onClose:v,mousePosition:l.value,src:a[o.value]},null)])}}}),T7=W6e,U6e=gS(),Yh={x:0,y:0},Y6e=P({src:u.string,alt:u.string},U6e),q6e=G({name:\"Preview\",inheritAttrs:!1,props:Y6e,emits:[\"close\",\"afterClose\"],setup:function(t,n){var r=n.emit,a=n.attrs,o=H(1),i=H(0),l=j6e(Yh),s=fn(l,2),c=s[0],d=s[1],f=function(){return r(\"close\")},p=H(),v=bt({originX:0,originY:0,deltaX:0,deltaY:0}),m=H(!1),y=yS.inject(),b=y.previewUrls,C=y.current,S=y.isPreviewGroup,w=y.setCurrent,k=x(function(){return Object.keys(b).length}),$=x(function(){return Object.keys(b)}),O=x(function(){return $.value.indexOf(String(C.value))}),T=x(function(){return S.value?b[C.value]:t.src}),_=x(function(){return S.value&&k.value>1}),I=function(){o.value=1,i.value=0,d(Yh)},L=function(){o.value++,d(Yh)},j=function(){o.value>1&&o.value--,d(Yh)},F=function(){i.value+=90},N=function(){i.value-=90},D=function(oe){oe.preventDefault(),oe.stopPropagation(),O.value>0&&w($.value[String(O.value-1)])},z=function(oe){oe.preventDefault(),oe.stopPropagation(),O.value<k.value-1&&w($.value[String(O.value+1)])},B=Se(V({},\"\".concat(t.prefixCls,\"-moving\"),m.value)),M=\"\".concat(t.prefixCls,\"-operations-operation\"),E=\"\".concat(t.prefixCls,\"-operations-icon\"),K=[{icon:go,onClick:f,type:\"close\"},{icon:M6e,onClick:L,type:\"zoomIn\"},{icon:D6e,onClick:j,type:\"zoomOut\",disabled:x(function(){return o.value===1})},{icon:T6e,onClick:F,type:\"rotateRight\"},{icon:k6e,onClick:N,type:\"rotateLeft\"}],W=function(){if(t.visible&&m.value){var oe=p.value.offsetWidth*o.value,Q=p.value.offsetHeight*o.value,ae=O7(p.value),de=ae.left,be=ae.top,Ee=i.value%180!==0;m.value=!1;var Pe=K6e(Ee?Q:oe,Ee?oe:Q,de,be);Pe&&d(P({},Pe))}},Y=function(oe){oe.preventDefault(),oe.stopPropagation(),v.deltaX=oe.pageX-c.x,v.deltaY=oe.pageY-c.y,v.originX=c.x,v.originY=c.y,m.value=!0},q=function(oe){t.visible&&m.value&&d({x:oe.pageX-v.deltaX,y:oe.pageY-v.deltaY})},J=function(){};return et(function(){ce([function(){return t.visible},m],function(){J();var ne,oe,Q=Kn(window,\"mouseup\",W,!1),ae=Kn(window,\"mousemove\",q,!1);try{window.top!==window.self&&(ne=Kn(window.top,\"mouseup\",W,!1),oe=Kn(window.top,\"mousemove\",q,!1))}catch{}J=function(){Q.remove(),ae.remove(),ne&&ne.remove(),oe&&oe.remove()}},{flush:\"post\",immediate:!0})}),Wr(function(){J()}),function(){return g(P7,le(le({},a),{},{transitionName:\"zoom\",maskTransitionName:\"fade\",closable:!1,keyboard:!0,prefixCls:t.prefixCls,onClose:f,afterClose:I,visible:t.visible,wrapClassName:B,getContainer:t.getContainer}),{default:function(){return[g(\"ul\",{class:\"\".concat(t.prefixCls,\"-operations\")},[K.map(function(oe){var Q=oe.icon,ae=oe.onClick,de=oe.type,be=oe.disabled;return g(\"li\",{class:Se(M,V({},\"\".concat(t.prefixCls,\"-operations-operation-disabled\"),be&&(be==null?void 0:be.value))),onClick:ae,key:de},[g(Q,{class:E},null)])})]),g(\"div\",{class:\"\".concat(t.prefixCls,\"-img-wrapper\"),style:{transform:\"translate3d(\".concat(c.x,\"px, \").concat(c.y,\"px, 0)\")}},[g(\"img\",{onMousedown:Y,ref:p,class:\"\".concat(t.prefixCls,\"-img\"),src:T.value,alt:t.alt,style:{transform:\"scale3d(\".concat(o.value,\", \").concat(o.value,\", 1) rotate(\").concat(i.value,\"deg)\")}},null)]),_.value&&g(\"div\",{class:Se(\"\".concat(t.prefixCls,\"-switch-left\"),V({},\"\".concat(t.prefixCls,\"-switch-left-disabled\"),O.value<=0)),onClick:D},[g(uc,null,null)]),_.value&&g(\"div\",{class:Se(\"\".concat(t.prefixCls,\"-switch-right\"),V({},\"\".concat(t.prefixCls,\"-switch-right-disabled\"),O.value>=k.value-1)),onClick:z},[g(wi,null,null)])]}})}}}),x7=q6e,_7={src:u.string,wrapperClassName:u.string,wrapperStyle:u.style,prefixCls:u.string,previewPrefixCls:u.string,placeholder:u.VNodeChild,fallback:u.string,preview:u.oneOfType([u.looseBool,u.shape({visible:u.bool,onVisibleChange:u.func,getContainer:u.oneOfType([u.func,u.looseBool,u.string])}).loose]).def(!0)},G6e=function(t,n){var r=P({},t);return Object.keys(n).forEach(function(a){t[a]===void 0&&(r[a]=n[a])}),r},X6e=0,E7=G({name:\"Image\",mixins:[nt],inheritAttrs:!1,props:_7,emits:[\"click\"],setup:function(t,n){var r=n.attrs,a=n.slots,o=n.emit,i=x(function(){return t.prefixCls}),l=x(function(){return\"\".concat(i.value,\"-preview\")}),s=x(function(){var M={visible:void 0,onVisibleChange:function(){},getContainer:void 0};return kt(t.preview)===\"object\"?G6e(t.preview,M):M}),c=x(function(){return t.placeholder&&t.placeholder!==!0||a.placeholder}),d=x(function(){return s.value.visible}),f=x(function(){return s.value.onVisibleChange}),p=x(function(){return s.value.getContainer}),v=x(function(){return d.value!==void 0}),m=H(!!d.value);ce(d,function(){m.value=!!d.value}),ce(m,function(M,E){f.value(M,E)});var y=H(c.value?\"loading\":\"normal\");ce(function(){return t.src},function(){y.value=c.value?\"loading\":\"normal\"});var b=H(null),C=x(function(){return y.value===\"error\"}),S=yS.inject(),w=S.isPreviewGroup,k=S.setCurrent,$=S.setShowPreview,O=S.setMousePosition,T=S.registerImage,_=H(X6e++),I=x(function(){return t.preview&&!C.value}),L=function(){y.value=\"normal\"},j=function(){y.value=\"error\"},F=function(E){if(!v.value){var K=O7(E.target),W=K.left,Y=K.top;w.value?(k(_.value),O({x:W,y:Y})):b.value={x:W,y:Y}}w.value?$(!0):m.value=!0,o(\"click\",E)},N=function(){m.value=!1,v.value||(b.value=null)},D=H(null);ce(function(){return D},function(){y.value===\"loading\"&&D.value.complete&&(D.value.naturalWidth||D.value.naturalHeight)&&L()});var z=function(){};et(function(){ce([function(){return t.src},I],function(){if(z(),!w.value)return function(){};z=T(_.value,t.src),I.value||z()},{flush:\"post\",immediate:!0})});var B=function(E){return vW(E)?E+\"px\":E};return function(){var M=t.prefixCls,E=t.wrapperClassName,K=t.fallback,W=t.src,Y=t.preview,q=t.placeholder,J=t.wrapperStyle,ne=r.width,oe=r.height,Q=r.crossorigin,ae=r.decoding,de=r.alt,be=r.sizes,Ee=r.srcset,Pe=r.usemap,Be=r.class,te=r.style,ie=Se(M,E,V({},\"\".concat(M,\"-error\"),C.value)),ge=C.value&&K?K:W,ke=a.previewMask&&a.previewMask(),xe={crossorigin:Q,decoding:ae,alt:de,sizes:be,srcset:Ee,usemap:Pe,class:Se(\"\".concat(M,\"-img\"),V({},\"\".concat(M,\"-img-placeholder\"),q===!0),Be),style:P({height:oe},te)};return g(Fe,null,[g(\"div\",{class:ie,onClick:Y&&!C.value?F:function(Ie){o(\"click\",Ie)},style:P({width:B(ne),height:B(oe)},J)},[g(\"img\",le(le(le({},xe),C.value&&K?{src:K}:{onLoad:L,onError:j,src:W}),{},{ref:D}),null),y.value===\"loading\"&&g(\"div\",{\"aria-hidden\":\"true\",class:\"\".concat(M,\"-placeholder\")},[q||a.placeholder&&a.placeholder()]),ke&&I.value&&g(\"div\",{class:\"\".concat(M,\"-mask\")},[ke])]),!w.value&&I.value&&g(x7,{\"aria-hidden\":!m.value,visible:m.value,prefixCls:l.value,onClose:N,mousePosition:b.value,src:ge,alt:de,getContainer:p.value},null)])}}});E7.PreviewGroup=T7;var Z6e=E7,J6e=G({name:\"AImagePreviewGroup\",inheritAttrs:!1,props:{previewPrefixCls:u.string},setup:function(t,n){var r=n.attrs,a=n.slots,o=ve(\"configProvider\",St),i=x(function(){return o.getPrefixCls(\"image-preview\",t.previewPrefixCls)});return function(){return g(T7,le(le({},P(P({},r),t)),{},{previewPrefixCls:i.value}),a)}}}),M7=J6e,zl=G({name:\"AImage\",inheritAttrs:!1,props:_7,setup:function(t,n){var r=n.slots,a=n.attrs,o=Wt(\"image\",t),i=o.prefixCls;return function(){return g(Z6e,P(P(P({},a),t),{prefixCls:i.value}),r)}}});zl.PreviewGroup=M7;zl.install=function(e){return e.component(zl.name,zl),e.component(zl.PreviewGroup.name,zl.PreviewGroup),e};var Q6e=zl,e8e={disabled:u.looseBool,activeClassName:u.string,activeStyle:u.any},t8e=G({name:\"TouchFeedback\",mixins:[nt],inheritAttrs:!1,props:An(e8e,{disabled:!1}),data:function(){return this.child=null,{active:!1}},mounted:function(){var t=this;this.$nextTick(function(){t.disabled&&t.active&&t.setState({active:!1})})},methods:{triggerEvent:function(t,n,r){var a=\"on\".concat(t),o=this.child;o.props[a]&&o.props[a](r),n!==this.active&&this.setState({active:n})},onTouchStart:function(t){this.triggerEvent(\"Touchstart\",!0,t)},onTouchMove:function(t){this.triggerEvent(\"Touchmove\",!1,t)},onTouchEnd:function(t){this.triggerEvent(\"Touchend\",!1,t)},onTouchCancel:function(t){this.triggerEvent(\"Touchcancel\",!1,t)},onMouseDown:function(t){this.triggerEvent(\"Mousedown\",!0,t)},onMouseUp:function(t){this.triggerEvent(\"Mouseup\",!1,t)},onMouseLeave:function(t){this.triggerEvent(\"Mouseleave\",!1,t)}},render:function(){var t,n=this.$props,r=n.disabled,a=n.activeClassName,o=a===void 0?\"\":a,i=n.activeStyle,l=i===void 0?{}:i,s=ht(this);if(s.length!==1)return on(!1,\"m-feedback\\u7EC4\\u4EF6\\u53EA\\u80FD\\u5305\\u542B\\u4E00\\u4E2A\\u5B50\\u5143\\u7D20\"),null;var c=r?void 0:(t={},V(t,mn?\"onTouchstartPassive\":\"onTouchstart\",this.onTouchStart),V(t,mn?\"onTouchmovePassive\":\"onTouchmove\",this.onTouchMove),V(t,\"onTouchend\",this.onTouchEnd),V(t,\"onTouchcancel\",this.onTouchCancel),V(t,\"onMousedown\",this.onMouseDown),V(t,\"onMouseup\",this.onMouseUp),V(t,\"onMouseleave\",this.onMouseLeave),t);if(s=s[0],this.child=s,!r&&this.active){var d=s.props,f=d.style,p=d.class;return l!==!1&&(l&&(f=P(P({},f),l)),p=Se(p,o)),Ot(s,P({class:p,style:f},c))}return Ot(s,c)}}),n8e={name:\"InputHandler\",inheritAttrs:!1,props:{prefixCls:u.string,disabled:u.looseBool},render:function(){var t=this,n=this.$props,r=n.prefixCls,a=n.disabled,o={disabled:a,activeClassName:\"\".concat(r,\"-handler-active\")};return g(t8e,o,{default:function(){return[g(\"span\",t.$attrs,[ht(t)])]}})}},nx=n8e;function rx(e){e.preventDefault()}function r8e(e){return e.replace(/[^\\w\\.-]+/g,\"\")}var a8e=200,o8e=600,i8e=Number.MAX_SAFE_INTEGER||Math.pow(2,53)-1,Gc=function(t){return t!=null},mb=function(t,n){return n===t||typeof n==\"number\"&&typeof t==\"number\"&&isNaN(n)&&isNaN(t)},l8e={value:u.oneOfType([u.number,u.string]),defaultValue:u.oneOfType([u.number,u.string]),focusOnUpDown:u.looseBool,autofocus:u.looseBool,prefixCls:u.string,tabindex:u.oneOfType([u.string,u.number]),placeholder:u.string,disabled:u.looseBool,readonly:u.looseBool,max:u.number,min:u.number,step:u.oneOfType([u.number,u.string]),upHandler:u.any,downHandler:u.any,useTouch:u.looseBool,formatter:u.func,parser:u.func,precision:u.number,required:u.looseBool,pattern:u.string,decimalSeparator:u.string,autocomplete:u.string,title:u.string,name:u.string,id:u.string,type:u.string,maxlength:u.any},s8e=G({name:\"VCInputNumber\",mixins:[nt],inheritAttrs:!1,props:An(l8e,{focusOnUpDown:!0,useTouch:!1,prefixCls:\"rc-input-number\",min:-i8e,step:1,parser:r8e,required:!1,autocomplete:\"off\"}),data:function(){var t=Qe(this);this.prevProps=P({},t);var n;\"value\"in t?n=this.value:n=this.defaultValue;var r=this.getValidValue(this.toNumber(n));return{inputValue:this.toPrecisionAsStep(r),sValue:r,focused:this.autofocus}},mounted:function(){var t=this;this.$nextTick(function(){t.updatedFunc()})},updated:function(){var t=this,n=this.$props,r=n.value,a=n.max,o=n.min,i=this.$data.focused,l=this.prevProps,s=Qe(this);if(l){if(!mb(l.value,r)||!mb(l.max,a)||!mb(l.min,o)){var c=i?r:this.getValidValue(r),d;this.pressingUpOrDown?d=c:this.inputting?d=this.rawInput:d=this.toPrecisionAsStep(c),this.setState({sValue:c,inputValue:d})}var f=\"value\"in s?r:this.$data.sValue;\"max\"in s&&l.max!==a&&typeof f==\"number\"&&f>a&&(this.__emit(\"update:value\",a),this.__emit(\"change\",a)),\"min\"in s&&l.min!==o&&typeof f==\"number\"&&f<o&&(this.__emit(\"update:value\",o),this.__emit(\"change\",o))}this.prevProps=P({},s),this.$nextTick(function(){t.updatedFunc()})},beforeUnmount:function(){this.stop()},methods:{updatedFunc:function(){var t=this.inputRef;try{if(this.cursorStart!==void 0&&this.$data.focused){if(!this.partRestoreByAfter(this.cursorAfter)&&this.$data.sValue!==this.value){var n=this.cursorStart+1;this.cursorAfter?this.lastKeyCode===ze.BACKSPACE?n=this.cursorStart-1:this.lastKeyCode===ze.DELETE&&(n=this.cursorStart):n=t.value.length,this.fixCaret(n,n)}else if(this.currentValue===t.value)switch(this.lastKeyCode){case ze.BACKSPACE:this.fixCaret(this.cursorStart-1,this.cursorStart-1);break;case ze.DELETE:this.fixCaret(this.cursorStart+1,this.cursorStart+1);break;default:}}}catch{}this.lastKeyCode=null,this.pressingUpOrDown&&(this.focusOnUpDown&&this.$data.focused&&document.activeElement!==t&&this.focus(),this.pressingUpOrDown=!1)},onKeyDown:function(t){if(t.keyCode===ze.UP){var n=this.getRatio(t);this.up(t,n),this.stop()}else if(t.keyCode===ze.DOWN){var r=this.getRatio(t);this.down(t,r),this.stop()}else t.keyCode===ze.ENTER&&this.__emit(\"pressEnter\",t);this.recordCursorPosition(),this.lastKeyCode=t.keyCode;for(var a=arguments.length,o=new Array(a>1?a-1:0),i=1;i<a;i++)o[i-1]=arguments[i];this.__emit.apply(this,[\"keydown\",t].concat(o))},onKeyUp:function(t){this.stop(),this.recordCursorPosition();for(var n=arguments.length,r=new Array(n>1?n-1:0),a=1;a<n;a++)r[a-1]=arguments[a];this.__emit.apply(this,[\"keyup\",t].concat(r))},onTrigger:function(t){if(t.target.composing)return!1;this.onChange(t)},onChange:function(t){this.$data.focused&&(this.inputting=!0),this.rawInput=this.parser(this.getValueFromEvent(t)),this.setState({inputValue:this.rawInput});var n=this.toNumber(this.rawInput);this.__emit(\"update:value\",n),this.__emit(\"change\",n)},onFocus:function(){this.setState({focused:!0});for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.__emit.apply(this,[\"focus\"].concat(n))},onBlur:function(){this.inputting=!1,this.setState({focused:!1});var t=this.getCurrentValidValue(this.$data.inputValue),n=this.setValue(t);if(this.$attrs.onBlur&&this.inputRef){var r=this.inputRef.value,a=this.getInputDisplayValue({focused:!1,sValue:n});this.inputRef.value=a;for(var o=arguments.length,i=new Array(o),l=0;l<o;l++)i[l]=arguments[l];this.__emit.apply(this,[\"blur\"].concat(i)),this.inputRef.value=r}},getCurrentValidValue:function(t){var n=t;return n===\"\"?n=\"\":this.isNotCompleteNumber(parseFloat(n,10))?n=this.$data.sValue:n=this.getValidValue(n),this.toNumber(n)},getRatio:function(t){var n=1;return t.metaKey||t.ctrlKey?n=.1:t.shiftKey&&(n=10),n},getValueFromEvent:function(t){var n=t.target.value.trim().replace(/。/g,\".\");return Gc(this.decimalSeparator)&&(n=n.replace(this.decimalSeparator,\".\")),n},getValidValue:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.min,r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:this.max,a=parseFloat(t,10);return isNaN(a)?t:(a<n&&(a=n),a>r&&(a=r),a)},setValue:function(t,n){var r=this.$props.precision,a=this.isNotCompleteNumber(parseFloat(t,10))?null:parseFloat(t,10),o=this.$data,i=o.sValue,l=i===void 0?null:i,s=o.inputValue,c=s===void 0?null:s,d=typeof a==\"number\"?a.toFixed(r):\"\".concat(a),f=a!==l||d!==\"\".concat(c);return vt(this,\"value\")?this.setState({inputValue:this.toPrecisionAsStep(this.$data.sValue)},n):this.setState({sValue:a,inputValue:this.toPrecisionAsStep(t)},n),f&&(this.__emit(\"update:value\",a),this.__emit(\"change\",a)),a},getPrecision:function(t){if(Gc(this.precision))return this.precision;var n=t.toString();if(n.indexOf(\"e-\")>=0)return parseInt(n.slice(n.indexOf(\"e-\")+2),10);var r=0;return n.indexOf(\".\")>=0&&(r=n.length-n.indexOf(\".\")-1),r},getMaxPrecision:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;if(Gc(this.precision))return this.precision;var r=this.step,a=this.getPrecision(n),o=this.getPrecision(r),i=this.getPrecision(t);return t?Math.max(i,a+o):a+o},getPrecisionFactor:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1,r=this.getMaxPrecision(t,n);return Math.pow(10,r)},getInputDisplayValue:function(t){var n=t||this.$data,r=n.focused,a=n.inputValue,o=n.sValue,i;r?i=a:i=this.toPrecisionAsStep(o),i==null&&(i=\"\");var l=this.formatWrapper(i);return Gc(this.$props.decimalSeparator)&&(l=l.toString().replace(\".\",this.$props.decimalSeparator)),l},recordCursorPosition:function(){try{var t=this.inputRef;this.cursorStart=t.selectionStart,this.cursorEnd=t.selectionEnd,this.currentValue=t.value,this.cursorBefore=t.value.substring(0,this.cursorStart),this.cursorAfter=t.value.substring(this.cursorEnd)}catch{}},fixCaret:function(t,n){if(!(t===void 0||n===void 0||!this.inputRef||!this.inputRef.value))try{var r=this.inputRef,a=r.selectionStart,o=r.selectionEnd;(t!==a||n!==o)&&r.setSelectionRange(t,n)}catch{}},restoreByAfter:function(t){if(t===void 0)return!1;var n=this.inputRef.value,r=n.lastIndexOf(t);if(r===-1)return!1;var a=this.cursorBefore.length;return this.lastKeyCode===ze.DELETE&&this.cursorBefore.charAt(a-1)===t[0]?(this.fixCaret(a,a),!0):r+t.length===n.length?(this.fixCaret(r,r),!0):!1},partRestoreByAfter:function(t){var n=this;return t===void 0?!1:Array.prototype.some.call(t,function(r,a){var o=t.substring(a);return n.restoreByAfter(o)})},focus:function(){this.inputRef.focus(),this.recordCursorPosition()},blur:function(){this.inputRef.blur()},formatWrapper:function(t){return this.formatter?this.formatter(t):t},toPrecisionAsStep:function(t){if(this.isNotCompleteNumber(t)||t===\"\")return t;var n=Math.abs(this.getMaxPrecision(t));return isNaN(n)?t.toString():Number(t).toFixed(n)},isNotCompleteNumber:function(t){return isNaN(t)||t===\"\"||t===null||t&&t.toString().indexOf(\".\")===t.toString().length-1},toNumber:function(t){var n=this.$props,r=n.precision,a=n.autofocus,o=this.$data.focused,i=o===void 0?a:o,l=t&&t.length>16&&i;return this.isNotCompleteNumber(t)||l?t:Gc(r)?Math.round(t*Math.pow(10,r))/Math.pow(10,r):Number(t)},upStep:function(t,n){var r=this.step,a=this.getPrecisionFactor(t,n),o=Math.abs(this.getMaxPrecision(t,n)),i=((a*t+a*r*n)/a).toFixed(o);return this.toNumber(i)},downStep:function(t,n){var r=this.step,a=this.getPrecisionFactor(t,n),o=Math.abs(this.getMaxPrecision(t,n)),i=((a*t-a*r*n)/a).toFixed(o);return this.toNumber(i)},stepFn:function(t,n){var r=this,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:1,o=arguments.length>3?arguments[3]:void 0;if(this.stop(),n&&n.preventDefault(),!this.disabled){var i=this.max,l=this.min,s=this.getCurrentValidValue(this.$data.inputValue)||0;if(!this.isNotCompleteNumber(s)){var c=this[\"\".concat(t,\"Step\")](s,a),d=c>i||c<l;c>i?c=i:c<l&&(c=l),this.setValue(c),this.setState({focused:!0}),!d&&(this.autoStepTimer=setTimeout(function(){r[t](n,a,!0)},o?a8e:o8e))}}},stop:function(){this.autoStepTimer&&clearTimeout(this.autoStepTimer)},down:function(t,n,r){this.pressingUpOrDown=!0,this.stepFn(\"down\",t,n,r)},up:function(t,n,r){this.pressingUpOrDown=!0,this.stepFn(\"up\",t,n,r)},handleInputClick:function(){this.__emit(\"click\")},saveUp:function(t){this.upHandlerRef=t},saveDown:function(t){this.downHandlerRef=t},saveInput:function(t){this.inputRef=t},onCompositionstart:function(t){t.target.composing=!0},onCompositionend:function(t){this.onChange(t),t.target.composing=!1}},render:function(){var t,n=P(P({},this.$props),this.$attrs),r=n.prefixCls,a=n.disabled,o=n.readonly,i=n.useTouch,l=n.autocomplete,s=n.upHandler,c=n.downHandler,d=n.class,f=Se((t={},V(t,d,d),V(t,r,!0),V(t,\"\".concat(r,\"-disabled\"),a),V(t,\"\".concat(r,\"-focused\"),this.$data.focused),t)),p=\"\",v=\"\",m=this.$data.sValue;if(m||m===0)if(isNaN(m))p=\"\".concat(r,\"-handler-up-disabled\"),v=\"\".concat(r,\"-handler-down-disabled\");else{var y=Number(m);y>=this.max&&(p=\"\".concat(r,\"-handler-up-disabled\")),y<=this.min&&(v=\"\".concat(r,\"-handler-down-disabled\"))}var b={};for(var C in n)n.hasOwnProperty(C)&&(C.substr(0,5)===\"data-\"||C.substr(0,5)===\"aria-\"||C===\"role\")&&(b[C]=n[C]);var S=!this.readonly&&!this.disabled,w=this.getInputDisplayValue(),k,$;if(i){var O,T;k=(O={},V(O,mn?\"onTouchstartPassive\":\"onTouchstart\",S&&!p&&this.up),V(O,\"onTouchend\",this.stop),O),$=(T={},V(T,mn?\"onTouchstartPassive\":\"onTouchstart\",S&&!v&&this.down),V(T,\"onTouchend\",this.stop),T)}else k={onMousedown:S&&!p&&this.up,onMouseup:this.stop,onMouseleave:this.stop},$={onMousedown:S&&!v&&this.down,onMouseup:this.stop,onMouseleave:this.stop};var _=!!p||a||o,I=!!v||a||o,L=P(P({disabled:_,prefixCls:r,unselectable:\"unselectable\",role:\"button\",\"aria-label\":\"Increase Value\",\"aria-disabled\":!!_,class:\"\".concat(r,\"-handler \").concat(r,\"-handler-up \").concat(p)},k),{ref:this.saveUp}),j=P(P({disabled:I,prefixCls:r,unselectable:\"unselectable\",role:\"button\",\"aria-label\":\"Decrease Value\",\"aria-disabled\":!!I,class:\"\".concat(r,\"-handler \").concat(r,\"-handler-down \").concat(v)},$),{ref:this.saveDown});return g(\"div\",{class:f,style:n.style,title:n.title,onMouseenter:n.onMouseenter,onMouseleave:n.onMouseleave,onMouseover:n.onMouseover,onMouseout:n.onMouseout},[g(\"div\",{class:\"\".concat(r,\"-handler-wrap\")},[g(\"span\",null,[g(nx,le(le({},L),{},{key:\"upHandler\"}),{default:function(){return[s||g(\"span\",{unselectable:\"unselectable\",class:\"\".concat(r,\"-handler-up-inner\"),onClick:rx},null)]}})]),g(nx,le(le({},j),{},{key:\"downHandler\"}),{default:function(){return[c||g(\"span\",{unselectable:\"unselectable\",class:\"\".concat(r,\"-handler-down-inner\"),onClick:rx},null)]}})]),g(\"div\",{class:\"\".concat(r,\"-input-wrap\")},[g(\"input\",le({role:\"spinbutton\",\"aria-valuemin\":this.min,\"aria-valuemax\":this.max,\"aria-valuenow\":m,required:this.required,type:n.type,placeholder:this.placeholder,onClick:this.handleInputClick,class:\"\".concat(r,\"-input\"),tabindex:this.tabindex,autocomplete:l,onFocus:this.onFocus,onBlur:this.onBlur,onKeydown:S&&this.onKeyDown,onKeyup:S&&this.onKeyUp,autofocus:this.autofocus,maxlength:this.maxlength,readonly:this.readonly,disabled:this.disabled,max:this.max,min:this.min,step:this.step,name:this.name,title:this.title,id:this.id,onInput:this.onTrigger,onCompositionstart:this.onCompositionstart,onCompositionend:this.onCompositionend,ref:this.saveInput,value:w,pattern:this.pattern},b),null)])])}}),u8e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},c8e={prefixCls:u.string,min:u.number,max:u.number,value:u.oneOfType([u.number,u.string]),step:u.oneOfType([u.number,u.string]).def(1),defaultValue:u.oneOfType([u.number,u.string]),tabindex:u.oneOfType([u.number,u.string]),disabled:u.looseBool,size:u.oneOf(rt(\"large\",\"small\",\"default\")),formatter:u.func,parser:u.func,decimalSeparator:u.string,placeholder:u.string,name:u.string,id:u.string,precision:u.number,autofocus:u.looseBool,onPressEnter:{type:Function},onChange:Function},d8e=G({name:\"AInputNumber\",inheritAttrs:!1,props:c8e,setup:function(t){var n=H(null),r=function(){n.value.focus()},a=function(){n.value.blur()};return et(function(){Ne(function(){})}),{configProvider:ve(\"configProvider\",St),inputNumberRef:n,focus:r,blur:a}},render:function(){var t,n=P(P({},Qe(this)),this.$attrs),r=n.prefixCls,a=n.size,o=n.class,i=u8e(n,[\"prefixCls\",\"size\",\"class\"]),l=this.configProvider.getPrefixCls,s=l(\"input-number\",r),c=Se((t={},V(t,\"\".concat(s,\"-lg\"),a===\"large\"),V(t,\"\".concat(s,\"-sm\"),a===\"small\"),t),o),d=g(gD,{class:\"\".concat(s,\"-handler-up-inner\")},null),f=g(Rs,{class:\"\".concat(s,\"-handler-down-inner\")},null),p=P(P({prefixCls:s,upHandler:d,downHandler:f},i),{class:c});return g(s8e,le(le({},p),{},{ref:\"inputNumberRef\"}),null)}}),f8e=kn(d8e),bS={prefixCls:u.string,hasSider:u.looseBool,tagName:u.string};function Mg(e){var t=e.suffixCls,n=e.tagName,r=e.name;return function(a){var o=G({name:r,props:bS,setup:function(l,s){var c=s.slots,d=Wt(t,l),f=d.prefixCls;return function(){var p,v=P(P({},l),{prefixCls:f.value,tagName:n});return g(a,v,{default:function(){return[(p=c.default)===null||p===void 0?void 0:p.call(c)]}})}}});return o}}var CS=G({props:bS,setup:function(t,n){var r=n.slots;return function(){var a;return g(t.tagName,{class:t.prefixCls},(a=r.default)===null||a===void 0?void 0:a.call(r))}}}),h8e=G({props:bS,setup:function(t,n){var r=n.slots,a=Wt(\"\",t),o=a.direction,i=H([]),l={addSider:function(c){i.value=[].concat(Je(i.value),[c])},removeSider:function(c){i.value=i.value.filter(function(d){return d!==c})}};return ot(eD,l),function(){var s,c,d=t.prefixCls,f=t.hasSider,p=t.tagName,v=Se(d,(s={},V(s,\"\".concat(d,\"-has-sider\"),typeof f==\"boolean\"?f:i.value.length>0),V(s,\"\".concat(d,\"-rtl\"),o.value===\"rtl\"),s));return g(p,{class:v},(c=r.default)===null||c===void 0?void 0:c.call(r))}}}),Ig=Mg({suffixCls:\"layout\",tagName:\"section\",name:\"ALayout\"})(h8e),p8e=Mg({suffixCls:\"layout-header\",tagName:\"header\",name:\"ALayoutHeader\"})(CS),v8e=Mg({suffixCls:\"layout-footer\",tagName:\"footer\",name:\"ALayoutFooter\"})(CS),m8e=Mg({suffixCls:\"layout-content\",tagName:\"main\",name:\"ALayoutContent\"})(CS);Ig.Header=p8e;Ig.Footer=v8e;Ig.Content=m8e;var pr=Ig,g8e={icon:{tag:\"svg\",attrs:{viewBox:\"0 0 1024 1024\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M912 192H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM104 228a56 56 0 10112 0 56 56 0 10-112 0zm0 284a56 56 0 10112 0 56 56 0 10-112 0zm0 284a56 56 0 10112 0 56 56 0 10-112 0z\"}}]},name:\"bars\",theme:\"outlined\"},y8e=g8e;function ax(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){b8e(e,a,n[a])})}return e}function b8e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var wS=function(t,n){var r=ax({},t,n.attrs);return g(Et,ax({},r,{icon:y8e}),null)};wS.displayName=\"BarsOutlined\";wS.inheritAttrs=!1;var C8e=wS,ox={xs:\"479.98px\",sm:\"575.98px\",md:\"767.98px\",lg:\"991.98px\",xl:\"1199.98px\",xxl:\"1599.98px\"},w8e={prefixCls:u.string,collapsible:u.looseBool,collapsed:u.looseBool,defaultCollapsed:u.looseBool,reverseArrow:u.looseBool,zeroWidthTriggerStyle:u.style,trigger:u.VNodeChild,width:u.oneOfType([u.number,u.string]),collapsedWidth:u.oneOfType([u.number,u.string]),breakpoint:u.oneOf(rt(\"xs\",\"sm\",\"md\",\"lg\",\"xl\",\"xxl\")),theme:u.oneOf(rt(\"light\",\"dark\")).def(\"dark\"),onBreakpoint:Function,onCollapse:Function},S8e=function(){var e=0;return function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\";return e+=1,\"\".concat(t).concat(e)}}(),k8e=G({name:\"ALayoutSider\",inheritAttrs:!1,props:Rn(w8e,{collapsible:!1,defaultCollapsed:!1,reverseArrow:!1,width:200,collapsedWidth:80}),emits:[\"breakpoint\",\"update:collapsed\",\"collapse\"],setup:function(t,n){var r=n.emit,a=n.attrs,o=n.slots,i=Wt(\"layout-sider\",t),l=i.prefixCls,s=ve(eD,void 0),c=H(!!(t.collapsed!==void 0?t.collapsed:t.defaultCollapsed)),d=H(!1);ce(function(){return t.collapsed},function(){c.value=!!t.collapsed}),ot(QA,c);var f=function(S,w){t.collapsed===void 0&&(c.value=S),r(\"update:collapsed\",S),r(\"collapse\",S,w)},p=H(function(C){d.value=C.matches,r(\"breakpoint\",C.matches),c.value!==C.matches&&f(C.matches,\"responsive\")}),v;function m(C){return p.value(C)}var y=S8e(\"ant-sider-\");et(function(){if(typeof window!=\"undefined\"){var C=window,S=C.matchMedia;if(S&&t.breakpoint&&t.breakpoint in ox){v=S(\"(max-width: \".concat(ox[t.breakpoint],\")\"));try{v.addEventListener(\"change\",m)}catch{v.addListener(m)}m(v)}}s&&s.addSider(y)}),Lt(function(){try{v==null||v.removeEventListener(\"change\",m)}catch{v==null||v.removeListener(m)}s&&s.removeSider(y)});var b=function(){f(!c.value,\"clickTrigger\")};return function(){var C,S,w=l.value,k=t.collapsedWidth,$=t.width,O=t.reverseArrow,T=t.zeroWidthTriggerStyle,_=t.trigger,I=t.collapsible,L=t.theme,j=c.value?k:$,F=WA(j)?\"\".concat(j,\"px\"):String(j),N=parseFloat(String(k||0))===0?g(\"span\",{onClick:b,class:Se(\"\".concat(w,\"-zero-width-trigger\"),\"\".concat(w,\"-zero-width-trigger-\").concat(O?\"right\":\"left\")),style:T},[_||g(C8e,null,null)]):null,D={expanded:g(O?wi:uc,null,null),collapsed:g(O?uc:wi,null,null)},z=c.value?\"collapsed\":\"expanded\",B=D[z],M=_!==null?N||g(\"div\",{class:\"\".concat(w,\"-trigger\"),onClick:b,style:{width:F}},[_||B]):null,E=P(P({},a.style),{flex:\"0 0 \".concat(F),maxWidth:F,minWidth:F,width:F}),K=Se(w,\"\".concat(w,\"-\").concat(L),(C={},V(C,\"\".concat(w,\"-collapsed\"),!!c.value),V(C,\"\".concat(w,\"-has-trigger\"),I&&_!==null&&!N),V(C,\"\".concat(w,\"-below\"),!!d.value),V(C,\"\".concat(w,\"-zero-width\"),parseFloat(F)===0),C),a.class);return g(\"aside\",le(le({},a),{},{class:K,style:E,ref:H}),[g(\"div\",{class:\"\".concat(w,\"-children\")},[(S=o.default)===null||S===void 0?void 0:S.call(o)]),I||d.value&&N?M:null])}}});pr.Sider=k8e;pr.install=function(e){return e.component(pr.name,pr),e.component(pr.Header.name,pr.Header),e.component(pr.Footer.name,pr.Footer),e.component(pr.Sider.name,pr.Sider),e.component(pr.Content.name,pr.Content),e};var $8e=pr.Header,O8e=pr.Footer,P8e=pr.Sider,T8e=pr.Content,x8e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},_8e=u.oneOf(rt(\"small\",\"default\",\"large\")),I7=function(){return{prefixCls:u.string,spinning:u.looseBool,size:_8e,wrapperClassName:u.string,tip:u.string,delay:u.number,indicator:u.any}},Xp=null;function E8e(e,t){return!!e&&!!t&&!isNaN(Number(t))}function M8e(e){var t=e.indicator;Xp=typeof t==\"function\"?t:function(){return g(t,null,null)}}var ol=G({name:\"ASpin\",mixins:[nt],inheritAttrs:!1,props:Rn(I7(),{size:\"default\",spinning:!0,wrapperClassName:\"\"}),setup:function(){return{originalUpdateSpinning:null,configProvider:ve(\"configProvider\",St)}},data:function(){var t=this.spinning,n=this.delay,r=E8e(t,n);return{sSpinning:t&&!r}},created:function(){this.originalUpdateSpinning=this.updateSpinning,this.debouncifyUpdateSpinning(this.$props)},mounted:function(){this.updateSpinning()},updated:function(){var t=this;Ne(function(){t.debouncifyUpdateSpinning(),t.updateSpinning()})},beforeUnmount:function(){this.cancelExistingSpin()},methods:{debouncifyUpdateSpinning:function(t){var n=t||this.$props,r=n.delay;r&&(this.cancelExistingSpin(),this.updateSpinning=Yn(this.originalUpdateSpinning,r))},updateSpinning:function(){var t=this.spinning,n=this.sSpinning;n!==t&&this.setState({sSpinning:t})},cancelExistingSpin:function(){var t=this.updateSpinning;t&&t.cancel&&t.cancel()},renderIndicator:function(t){var n=\"\".concat(t,\"-dot\"),r=We(this,\"indicator\");return r===null?null:(Array.isArray(r)&&(r=r.length===1?r[0]:r),rn(r)?hr(r,{class:n}):Xp&&rn(Xp())?hr(Xp(),{class:n}):g(\"span\",{class:\"\".concat(n,\" \").concat(t,\"-dot-spin\")},[g(\"i\",{class:\"\".concat(t,\"-dot-item\")},null),g(\"i\",{class:\"\".concat(t,\"-dot-item\")},null),g(\"i\",{class:\"\".concat(t,\"-dot-item\")},null),g(\"i\",{class:\"\".concat(t,\"-dot-item\")},null)]))}},render:function(){var t,n=this.$props,r=n.size,a=n.prefixCls,o=n.tip,i=n.wrapperClassName,l=this.$attrs,s=l.class,c=l.style,d=x8e(l,[\"class\",\"style\"]),f=this.configProvider,p=f.getPrefixCls,v=f.direction,m=p(\"spin\",a),y=this.sSpinning,b=(t={},V(t,m,!0),V(t,\"\".concat(m,\"-sm\"),r===\"small\"),V(t,\"\".concat(m,\"-lg\"),r===\"large\"),V(t,\"\".concat(m,\"-spinning\"),y),V(t,\"\".concat(m,\"-show-text\"),!!o),V(t,\"\".concat(m,\"-rtl\"),v===\"rtl\"),V(t,s,!!s),t),C=g(\"div\",le(le({},d),{},{style:c,class:b}),[this.renderIndicator(m),o?g(\"div\",{class:\"\".concat(m,\"-text\")},[o]):null]),S=ht(this);if(S&&S.length){var w,k=(w={},V(w,\"\".concat(m,\"-container\"),!0),V(w,\"\".concat(m,\"-blur\"),y),w);return g(\"div\",{class:[\"\".concat(m,\"-nested-loading\"),i]},[y&&g(\"div\",{key:\"loading\"},[C]),g(\"div\",{class:k,key:\"container\"},[S])])}return C}});ol.setDefaultIndicator=M8e;ol.install=function(e){return e.component(ol.name,ol),e};var I8e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M272.9 512l265.4-339.1c4.1-5.2.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L186.8 492.3a31.99 31.99 0 000 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H532c6.7 0 10.4-7.7 6.3-12.9L272.9 512zm304 0l265.4-339.1c4.1-5.2.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L490.8 492.3a31.99 31.99 0 000 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H836c6.7 0 10.4-7.7 6.3-12.9L576.9 512z\"}}]},name:\"double-left\",theme:\"outlined\"},N8e=I8e;function ix(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){A8e(e,a,n[a])})}return e}function A8e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var SS=function(t,n){var r=ix({},t,n.attrs);return g(Et,ix({},r,{icon:N8e}),null)};SS.displayName=\"DoubleLeftOutlined\";SS.inheritAttrs=!1;var D8e=SS,R8e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M533.2 492.3L277.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H188c-6.7 0-10.4 7.7-6.3 12.9L447.1 512 181.7 851.1A7.98 7.98 0 00188 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5zm304 0L581.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H492c-6.7 0-10.4 7.7-6.3 12.9L751.1 512 485.7 851.1A7.98 7.98 0 00492 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5z\"}}]},name:\"double-right\",theme:\"outlined\"},L8e=R8e;function lx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){F8e(e,a,n[a])})}return e}function F8e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var kS=function(t,n){var r=lx({},t,n.attrs);return g(Et,lx({},r,{icon:L8e}),null)};kS.displayName=\"DoubleRightOutlined\";kS.inheritAttrs=!1;var B8e=kS,V8e=G({inheritAttrs:!1,props:Sg(),Option:dl.Option,render:function(){var t=this,n=Qe(this),r=P(P(P({},n),{size:\"small\"}),this.$attrs);return g(dl,r,{default:function(){return[ht(t)]}})}}),xl={name:\"Pager\",mixins:[nt],inheritAttrs:!1,props:{rootPrefixCls:u.string,page:u.number,active:u.looseBool,last:u.looseBool,locale:u.object,showTitle:u.looseBool,itemRender:{type:Function,default:function(){}}},methods:{handleClick:function(){this.__emit(\"click\",this.page)},handleKeyPress:function(t){this.__emit(\"keypress\",t,this.handleClick,this.page)}},render:function(){var t,n=this.$attrs,r=n.class,a=n.style,o=this.$props,i=\"\".concat(o.rootPrefixCls,\"-item\"),l=Se(i,\"\".concat(i,\"-\").concat(o.page),(t={},V(t,\"\".concat(i,\"-active\"),o.active),V(t,\"\".concat(i,\"-disabled\"),!o.page),t),r);return g(\"li\",{onClick:this.handleClick,onKeypress:this.handleKeyPress,title:this.showTitle?this.page:null,tabindex:\"0\",class:l,style:a},[this.itemRender({page:this.page,type:\"page\",originalElement:g(\"a\",null,[this.page])})])}},Dl={ZERO:48,NINE:57,NUMPAD_ZERO:96,NUMPAD_NINE:105,BACKSPACE:8,DELETE:46,ENTER:13,ARROW_UP:38,ARROW_DOWN:40},z8e={mixins:[nt],props:{disabled:u.looseBool,changeSize:u.func,quickGo:u.func,selectComponentClass:u.any,current:u.number,pageSizeOptions:u.array.def([\"10\",\"20\",\"30\",\"40\"]),pageSize:u.number,buildOptionText:u.func,locale:u.object,rootPrefixCls:u.string,selectPrefixCls:u.string,goButton:u.any},data:function(){return{goInputText:\"\"}},methods:{getValidValue:function(){var t=this.goInputText,n=this.current;return!t||isNaN(t)?n:Number(t)},defaultBuildOptionText:function(t){return\"\".concat(t.value,\" \").concat(this.locale.items_per_page)},handleChange:function(t){var n=t.target,r=n.value,a=n.composing;t.isComposing||a||this.goInputText===r||this.setState({goInputText:r})},handleBlur:function(t){var n=this.$props,r=n.goButton,a=n.quickGo,o=n.rootPrefixCls;r||t.relatedTarget&&(t.relatedTarget.className.indexOf(\"\".concat(o,\"-prev\"))>=0||t.relatedTarget.className.indexOf(\"\".concat(o,\"-next\"))>=0)||a(this.getValidValue())},go:function(t){var n=this.goInputText;n!==\"\"&&(t.keyCode===Dl.ENTER||t.type===\"click\")&&(this.quickGo(this.getValidValue()),this.setState({goInputText:\"\"}))}},render:function(){var t=this,n=this.rootPrefixCls,r=this.locale,a=this.changeSize,o=this.quickGo,i=this.goButton,l=this.selectComponentClass,s=this.defaultBuildOptionText,c=this.selectPrefixCls,d=this.pageSize,f=this.pageSizeOptions,p=this.goInputText,v=this.disabled,m=\"\".concat(n,\"-options\"),y=null,b=null,C=null;if(!a&&!o)return null;if(a&&l){var S=this.buildOptionText||s,w=f.map(function(k,$){return g(l.Option,{key:$,value:k},{default:function(){return[S({value:k})]}})});y=g(l,{disabled:v,prefixCls:c,showSearch:!1,class:\"\".concat(m,\"-size-changer\"),optionLabelProp:\"children\",value:(d||f[0]).toString(),onChange:function($){return t.changeSize(Number($))},getPopupContainer:function($){return $.parentNode}},{default:function(){return[w]}})}return o&&(i&&(C=typeof i==\"boolean\"?g(\"button\",{type:\"button\",onClick:this.go,onKeyup:this.go,disabled:v},[r.jump_to_confirm]):g(\"span\",{onClick:this.go,onKeyup:this.go},[i])),b=g(\"div\",{class:\"\".concat(m,\"-quick-jumper\")},[r.jump_to,at(g(\"input\",{disabled:v,type:\"text\",value:p,onInput:this.handleChange,onChange:this.handleChange,onKeyup:this.go,onBlur:this.handleBlur},null),[[Mi]]),r.page,C])),g(\"li\",{class:\"\".concat(m)},[y,b])}},H8e={items_per_page:\"\\u6761/\\u9875\",jump_to:\"\\u8DF3\\u81F3\",jump_to_confirm:\"\\u786E\\u5B9A\",page:\"\\u9875\",prev_page:\"\\u4E0A\\u4E00\\u9875\",next_page:\"\\u4E0B\\u4E00\\u9875\",prev_5:\"\\u5411\\u524D 5 \\u9875\",next_5:\"\\u5411\\u540E 5 \\u9875\",prev_3:\"\\u5411\\u524D 3 \\u9875\",next_3:\"\\u5411\\u540E 3 \\u9875\"},j8e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function K8e(){}function W8e(e){return typeof e==\"number\"&&isFinite(e)&&Math.floor(e)===e}function U8e(e){var t=e.originalElement;return t}function Jo(e,t,n){var r=e;return typeof r==\"undefined\"&&(r=t.statePageSize),Math.floor((n.total-1)/r)+1}var Y8e=G({name:\"Pagination\",mixins:[nt],inheritAttrs:!1,props:{disabled:u.looseBool,prefixCls:u.string.def(\"rc-pagination\"),selectPrefixCls:u.string.def(\"rc-select\"),current:u.number,defaultCurrent:u.number.def(1),total:u.number.def(0),pageSize:u.number,defaultPageSize:u.number.def(10),hideOnSinglePage:u.looseBool.def(!1),showSizeChanger:u.looseBool.def(!1),showLessItems:u.looseBool.def(!1),selectComponentClass:u.any,showPrevNextJumpers:u.looseBool.def(!0),showQuickJumper:u.oneOfType([u.looseBool,u.object]).def(!1),showTitle:u.looseBool.def(!0),pageSizeOptions:u.arrayOf(u.string),buildOptionText:u.func,showTotal:u.func,simple:u.looseBool,locale:u.object.def(H8e),itemRender:u.func,prevIcon:u.any,nextIcon:u.any,jumpPrevIcon:u.any,jumpNextIcon:u.any},data:function(){var t=Qe(this),n=this.onChange!==K8e,r=\"current\"in t;r&&!n&&console.warn(\"Warning: You provided a `current` prop to a Pagination component without an `onChange` handler. This will render a read-only component.\");var a=this.defaultCurrent;\"current\"in t&&(a=this.current);var o=this.defaultPageSize;return\"pageSize\"in t&&(o=this.pageSize),a=Math.min(a,Jo(o,void 0,t)),{stateCurrent:a,stateCurrentInputValue:a,statePageSize:o}},watch:{current:function(t){this.setState({stateCurrent:t,stateCurrentInputValue:t})},pageSize:function(t){var n={},r=this.stateCurrent,a=Jo(t,this.$data,this.$props);r=r>a?a:r,vt(this,\"current\")||(n.stateCurrent=r,n.stateCurrentInputValue=r),n.statePageSize=t,this.setState(n)},stateCurrent:function(t,n){var r=this;this.$nextTick(function(){if(r.$refs.paginationNode){var a=r.$refs.paginationNode.querySelector(\".\".concat(r.prefixCls,\"-item-\").concat(n));a&&document.activeElement===a&&a.blur()}})},total:function(){var t={},n=Jo(this.pageSize,this.$data,this.$props);if(vt(this,\"current\")){var r=Math.min(this.current,n);t.stateCurrent=r,t.stateCurrentInputValue=r}else{var a=this.stateCurrent;a===0&&n>0?a=1:a=Math.min(this.stateCurrent,n),t.stateCurrent=a}this.setState(t)}},methods:{getJumpPrevPage:function(){return Math.max(1,this.stateCurrent-(this.showLessItems?3:5))},getJumpNextPage:function(){return Math.min(Jo(void 0,this.$data,this.$props),this.stateCurrent+(this.showLessItems?3:5))},getItemIcon:function(t){var n=this.$props.prefixCls,r=We(this,t,this.$props)||g(\"a\",{class:\"\".concat(n,\"-item-link\")},null);return r},getValidValue:function(t){var n=t.target.value,r=Jo(void 0,this.$data,this.$props),a=this.$data.stateCurrentInputValue,o;return n===\"\"?o=n:isNaN(Number(n))?o=a:n>=r?o=r:o=Number(n),o},isValid:function(t){return W8e(t)&&t!==this.stateCurrent},shouldDisplayQuickJumper:function(){var t=this.$props,n=t.showQuickJumper,r=t.pageSize,a=t.total;return a<=r?!1:n},handleKeyDown:function(t){(t.keyCode===Dl.ARROW_UP||t.keyCode===Dl.ARROW_DOWN)&&t.preventDefault()},handleKeyUp:function(t){if(!(t.isComposing||t.target.composing)){var n=this.getValidValue(t),r=this.stateCurrentInputValue;n!==r&&this.setState({stateCurrentInputValue:n}),t.keyCode===Dl.ENTER?this.handleChange(n):t.keyCode===Dl.ARROW_UP?this.handleChange(n-1):t.keyCode===Dl.ARROW_DOWN&&this.handleChange(n+1)}},changePageSize:function(t){var n=this.stateCurrent,r=n,a=Jo(t,this.$data,this.$props);n=n>a?a:n,a===0&&(n=this.stateCurrent),typeof t==\"number\"&&(vt(this,\"pageSize\")||this.setState({statePageSize:t}),vt(this,\"current\")||this.setState({stateCurrent:n,stateCurrentInputValue:n})),this.__emit(\"update:pageSize\",t),n!==r&&this.__emit(\"update:current\",n),this.__emit(\"showSizeChange\",n,t)},handleChange:function(t){var n=this.$props.disabled,r=t;if(this.isValid(r)&&!n){var a=Jo(void 0,this.$data,this.$props);return r>a?r=a:r<1&&(r=1),vt(this,\"current\")||this.setState({stateCurrent:r,stateCurrentInputValue:r}),this.__emit(\"update:current\",r),this.__emit(\"change\",r,this.statePageSize),r}return this.stateCurrent},prev:function(){this.hasPrev()&&this.handleChange(this.stateCurrent-1)},next:function(){this.hasNext()&&this.handleChange(this.stateCurrent+1)},jumpPrev:function(){this.handleChange(this.getJumpPrevPage())},jumpNext:function(){this.handleChange(this.getJumpNextPage())},hasPrev:function(){return this.stateCurrent>1},hasNext:function(){return this.stateCurrent<Jo(void 0,this.$data,this.$props)},runIfEnter:function(t,n){if(t.key===\"Enter\"||t.charCode===13){for(var r=arguments.length,a=new Array(r>2?r-2:0),o=2;o<r;o++)a[o-2]=arguments[o];n.apply(void 0,a)}},runIfEnterPrev:function(t){this.runIfEnter(t,this.prev)},runIfEnterNext:function(t){this.runIfEnter(t,this.next)},runIfEnterJumpPrev:function(t){this.runIfEnter(t,this.jumpPrev)},runIfEnterJumpNext:function(t){this.runIfEnter(t,this.jumpNext)},handleGoTO:function(t){(t.keyCode===Dl.ENTER||t.type===\"click\")&&this.handleChange(this.stateCurrentInputValue)}},render:function(){var t,n=this.$props,r=n.prefixCls,a=n.disabled,o=If(this.$attrs).extraAttrs,i=o.class,l=j8e(o,[\"class\"]);if(this.hideOnSinglePage===!0&&this.total<=this.statePageSize)return null;var s=this.itemRender||U8e,c=this.$props,d=this.locale,f=Jo(void 0,this.$data,this.$props),p=[],v=null,m=null,y=null,b=null,C=null,S=this.showQuickJumper&&this.showQuickJumper.goButton,w=this.showLessItems?1:2,k=this.stateCurrent,$=this.statePageSize,O=k-1>0?k-1:0,T=k+1<f?k+1:f;if(this.simple){S&&(typeof S==\"boolean\"?C=g(\"button\",{type:\"button\",onClick:this.handleGoTO,onKeyup:this.handleGoTO},[d.jump_to_confirm]):C=g(\"span\",{onClick:this.handleGoTO,onKeyup:this.handleGoTO},[S]),C=g(\"li\",{title:this.showTitle?\"\".concat(d.jump_to).concat(this.stateCurrent,\"/\").concat(f):null,class:\"\".concat(r,\"-simple-pager\")},[C]));var _=this.hasPrev(),I=this.hasNext();return g(\"ul\",le({class:Se(\"\".concat(r,\" \").concat(r,\"-simple\"),i)},l),[g(\"li\",{title:this.showTitle?d.prev_page:null,onClick:this.prev,tabindex:_?0:null,onKeypress:this.runIfEnterPrev,class:\"\".concat(_?\"\":\"\".concat(r,\"-disabled\"),\" \").concat(r,\"-prev\"),\"aria-disabled\":!this.hasPrev()},[s({page:O,type:\"prev\",originalElement:this.getItemIcon(\"prevIcon\")})]),g(\"li\",{title:this.showTitle?\"\".concat(k,\"/\").concat(f):null,class:\"\".concat(r,\"-simple-pager\")},[at(g(\"input\",{type:\"text\",value:this.stateCurrentInputValue,onKeydown:this.handleKeyDown,onKeyup:this.handleKeyUp,onInput:this.handleKeyUp,onChange:this.handleKeyUp,size:\"3\"},null),[[Mi]]),g(\"span\",{class:\"\".concat(r,\"-slash\")},[yt(\"\\uFF0F\")]),f]),g(\"li\",{title:this.showTitle?d.next_page:null,onClick:this.next,tabindex:this.hasNext?0:null,onKeypress:this.runIfEnterNext,class:\"\".concat(I?\"\":\"\".concat(r,\"-disabled\"),\" \").concat(r,\"-next\"),\"aria-disabled\":!this.hasNext()},[s({page:T,type:\"next\",originalElement:this.getItemIcon(\"nextIcon\")})]),C])}if(f<=5+w*2){var L={locale:d,rootPrefixCls:r,showTitle:c.showTitle,itemRender:s,onClick:this.handleChange,onKeypress:this.runIfEnter};f||p.push(g(xl,le(le({},L),{},{key:\"noPager\",page:f,class:\"\".concat(r,\"-disabled\")}),null));for(var j=1;j<=f;j++){var F=k===j;p.push(g(xl,le(le({},L),{},{key:j,page:j,active:F}),null))}}else{var N=this.showLessItems?d.prev_3:d.prev_5,D=this.showLessItems?d.next_3:d.next_5;if(this.showPrevNextJumpers){var z=\"\".concat(r,\"-jump-prev\");c.jumpPrevIcon&&(z+=\" \".concat(r,\"-jump-prev-custom-icon\")),v=g(\"li\",{title:this.showTitle?N:null,key:\"prev\",onClick:this.jumpPrev,tabindex:\"0\",onKeypress:this.runIfEnterJumpPrev,class:z},[s({page:this.getJumpPrevPage(),type:\"jump-prev\",originalElement:this.getItemIcon(\"jumpPrevIcon\")})]);var B=\"\".concat(r,\"-jump-next\");c.jumpNextIcon&&(B+=\" \".concat(r,\"-jump-next-custom-icon\")),m=g(\"li\",{title:this.showTitle?D:null,key:\"next\",tabindex:\"0\",onClick:this.jumpNext,onKeypress:this.runIfEnterJumpNext,class:B},[s({page:this.getJumpNextPage(),type:\"jump-next\",originalElement:this.getItemIcon(\"jumpNextIcon\")})])}b=g(xl,{locale:d,last:!0,rootPrefixCls:r,onClick:this.handleChange,onKeypress:this.runIfEnter,key:f,page:f,active:!1,showTitle:this.showTitle,itemRender:s},null),y=g(xl,{locale:d,rootPrefixCls:r,onClick:this.handleChange,onKeypress:this.runIfEnter,key:1,page:1,active:!1,showTitle:this.showTitle,itemRender:s},null);var M=Math.max(1,k-w),E=Math.min(k+w,f);k-1<=w&&(E=1+w*2),f-k<=w&&(M=f-w*2);for(var K=M;K<=E;K++){var W=k===K;p.push(g(xl,{locale:d,rootPrefixCls:r,onClick:this.handleChange,onKeypress:this.runIfEnter,key:K,page:K,active:W,showTitle:this.showTitle,itemRender:s},null))}k-1>=w*2&&k!==1+2&&(p[0]=g(xl,{locale:d,rootPrefixCls:r,onClick:this.handleChange,onKeypress:this.runIfEnter,key:M,page:M,class:\"\".concat(r,\"-item-after-jump-prev\"),active:!1,showTitle:this.showTitle,itemRender:s},null),p.unshift(v)),f-k>=w*2&&k!==f-2&&(p[p.length-1]=g(xl,{locale:d,rootPrefixCls:r,onClick:this.handleChange,onKeypress:this.runIfEnter,key:E,page:E,class:\"\".concat(r,\"-item-before-jump-next\"),active:!1,showTitle:this.showTitle,itemRender:s},null),p.push(m)),M!==1&&p.unshift(y),E!==f&&p.push(b)}var Y=null;this.showTotal&&(Y=g(\"li\",{class:\"\".concat(r,\"-total-text\")},[this.showTotal(this.total,[this.total===0?0:(k-1)*$+1,k*$>this.total?this.total:k*$])]));var q=!this.hasPrev()||!f,J=!this.hasNext()||!f,ne=this.buildOptionText||this.$slots.buildOptionText;return g(\"ul\",le(le({unselectable:\"unselectable\",ref:\"paginationNode\"},l),{},{class:Se((t={},V(t,\"\".concat(r),!0),V(t,\"\".concat(r,\"-disabled\"),a),t),i)}),[Y,g(\"li\",{title:this.showTitle?d.prev_page:null,onClick:this.prev,tabindex:q?null:0,onKeypress:this.runIfEnterPrev,class:\"\".concat(q?\"\".concat(r,\"-disabled\"):\"\",\" \").concat(r,\"-prev\"),\"aria-disabled\":q},[s({page:O,type:\"prev\",originalElement:this.getItemIcon(\"prevIcon\")})]),p,g(\"li\",{title:this.showTitle?d.next_page:null,onClick:this.next,tabindex:J?null:0,onKeypress:this.runIfEnterNext,class:\"\".concat(J?\"\".concat(r,\"-disabled\"):\"\",\" \").concat(r,\"-next\"),\"aria-disabled\":J},[s({page:T,type:\"next\",originalElement:this.getItemIcon(\"nextIcon\")})]),g(z8e,{disabled:a,locale:d,rootPrefixCls:r,selectComponentClass:this.selectComponentClass,selectPrefixCls:this.selectPrefixCls,changeSize:this.showSizeChanger?this.changePageSize:null,current:k,pageSize:$,pageSizeOptions:this.pageSizeOptions,buildOptionText:ne||null,quickGo:this.shouldDisplayQuickJumper()?this.handleChange:null,goButton:S},null)])}}),q8e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},$S=function(){return{total:u.number,defaultCurrent:u.number,disabled:u.looseBool,current:u.number,defaultPageSize:u.number,pageSize:u.number,hideOnSinglePage:u.looseBool,showSizeChanger:u.looseBool,pageSizeOptions:u.arrayOf(u.oneOfType([u.number,u.string])),buildOptionText:u.func,showSizeChange:u.func,showQuickJumper:an(u.oneOfType([u.looseBool,u.object])),showTotal:u.any,size:u.string,simple:u.looseBool,locale:u.object,prefixCls:u.string,selectPrefixCls:u.string,itemRender:u.func,role:u.string,showLessItems:u.looseBool,onChange:u.func,onShowSizeChange:u.func,\"onUpdate:current\":u.func,\"onUpdate:pageSize\":u.func}},N7=function(){return P(P({},$S()),{position:u.oneOf(rt(\"top\",\"bottom\",\"both\"))})},G8e=G({name:\"APagination\",inheritAttrs:!1,props:P({},$S()),emits:[\"change\",\"showSizeChange\",\"update:current\",\"update:pageSize\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},methods:{getIconsProps:function(t){var n=g(\"a\",{class:\"\".concat(t,\"-item-link\")},[g(uc,null,null)]),r=g(\"a\",{class:\"\".concat(t,\"-item-link\")},[g(wi,null,null)]),a=g(\"a\",{class:\"\".concat(t,\"-item-link\")},[g(\"div\",{class:\"\".concat(t,\"-item-container\")},[g(D8e,{class:\"\".concat(t,\"-item-link-icon\")},null),g(\"span\",{class:\"\".concat(t,\"-item-ellipsis\")},[yt(\"\\u2022\\u2022\\u2022\")])])]),o=g(\"a\",{class:\"\".concat(t,\"-item-link\")},[g(\"div\",{class:\"\".concat(t,\"-item-container\")},[g(B8e,{class:\"\".concat(t,\"-item-link-icon\")},null),g(\"span\",{class:\"\".concat(t,\"-item-ellipsis\")},[yt(\"\\u2022\\u2022\\u2022\")])])]);return{prevIcon:n,nextIcon:r,jumpPrevIcon:a,jumpNextIcon:o}},renderPagination:function(t){var n=Qe(this),r=n.prefixCls,a=n.selectPrefixCls,o=n.buildOptionText,i=n.size,l=n.locale,s=q8e(n,[\"prefixCls\",\"selectPrefixCls\",\"buildOptionText\",\"size\",\"locale\"]),c=this.configProvider.getPrefixCls,d=c(\"pagination\",r),f=c(\"select\",a),p=i===\"small\",v=P(P(P(P(P({prefixCls:d,selectPrefixCls:f},s),this.getIconsProps(d)),{selectComponentClass:p?V8e:dl,locale:P(P({},t),l),buildOptionText:o||this.$slots.buildOptionText}),this.$attrs),{class:Se({mini:p},this.$attrs.class),itemRender:this.itemRender||this.$slots.itemRender});return g(Y8e,v,null)}},render:function(){return g(Kr,{componentName:\"Pagination\",defaultLocale:ZI,children:this.renderPagination},null)}}),OS=kn(G8e),X8e={avatar:u.any,description:u.any,prefixCls:u.string,title:u.any},A7=G({name:\"AListItemMeta\",props:X8e,displayName:\"AListItemMeta\",__ANT_LIST_ITEM_META:!0,slots:[\"avatar\",\"description\",\"title\"],setup:function(t,n){var r=n.slots,a=Wt(\"list\",t),o=a.prefixCls;return function(){var i,l,s,c,d,f,p=\"\".concat(o.value,\"-item-meta\"),v=(i=t.title)!==null&&i!==void 0?i:(l=r.title)===null||l===void 0?void 0:l.call(r),m=(s=t.description)!==null&&s!==void 0?s:(c=r.description)===null||c===void 0?void 0:c.call(r),y=(d=t.avatar)!==null&&d!==void 0?d:(f=r.avatar)===null||f===void 0?void 0:f.call(r),b=g(\"div\",{class:\"\".concat(o.value,\"-item-meta-content\")},[v&&g(\"h4\",{class:\"\".concat(o.value,\"-item-meta-title\")},[v]),m&&g(\"div\",{class:\"\".concat(o.value,\"-item-meta-description\")},[m])]);return g(\"div\",{class:p},[y&&g(\"div\",{class:\"\".concat(o.value,\"-item-meta-avatar\")},[y]),(v||m)&&b])}}}),D7=Symbol(\"ListContextKey\"),Z8e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},J8e={prefixCls:u.string,extra:u.any,actions:u.array,grid:u.any,colStyle:u.style},R7=G({name:\"AListItem\",inheritAttrs:!1,Meta:A7,props:J8e,slots:[\"actions\",\"extra\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=ve(D7,{grid:H(),itemLayout:H()}),i=o.itemLayout,l=o.grid,s=Wt(\"list\",t),c=s.prefixCls,d=function(){var v,m=((v=r.default)===null||v===void 0?void 0:v.call(r))||[],y;return m.forEach(function(b){s0e(b)&&!As(b)&&(y=!0)}),y&&m.length>1},f=function(){var v,m,y=(v=t.extra)!==null&&v!==void 0?v:(m=r.extra)===null||m===void 0?void 0:m.call(r);return i.value===\"vertical\"?!!y:!d()};return function(){var p,v,m,y,b,C=a.class,S=Z8e(a,[\"class\"]),w=c.value,k=(p=t.extra)!==null&&p!==void 0?p:(v=r.extra)===null||v===void 0?void 0:v.call(r),$=(m=r.default)===null||m===void 0?void 0:m.call(r),O=(y=t.actions)!==null&&y!==void 0?y:Un((b=r.actions)===null||b===void 0?void 0:b.call(r));O=O&&!Array.isArray(O)?[O]:O;var T=O&&O.length>0&&g(\"ul\",{class:\"\".concat(w,\"-item-action\"),key:\"actions\"},[O.map(function(L,j){return g(\"li\",{key:\"\".concat(w,\"-item-action-\").concat(j)},[L,j!==O.length-1&&g(\"em\",{class:\"\".concat(w,\"-item-action-split\")},null)])})]),_=l.value?\"div\":\"li\",I=g(_,le(le({},S),{},{class:Se(\"\".concat(w,\"-item\"),V({},\"\".concat(w,\"-item-no-flex\"),!f()),C)}),{default:function(){return[i.value===\"vertical\"&&k?[g(\"div\",{class:\"\".concat(w,\"-item-main\"),key:\"content\"},[$,T]),g(\"div\",{class:\"\".concat(w,\"-item-extra\"),key:\"extra\"},[k])]:[$,T,Ot(k,{key:\"extra\"})]]}});return l.value?g(Og,{flex:1,style:t.colStyle},{default:function(){return[I]}}):I}}}),Q8e={gutter:u.oneOfType([u.number,u.arrayOf(Number)]),column:u.number,xs:u.number,sm:u.number,md:u.number,lg:u.number,xl:u.number,xxl:u.number},eEe=rt(\"small\",\"default\",\"large\"),tEe={bordered:u.looseBool,dataSource:u.array,extra:u.any,grid:u.shape(Q8e).loose,itemLayout:u.oneOf(rt(\"horizontal\",\"vertical\")),loading:an(u.oneOfType([u.looseBool,u.object])),loadMore:u.any,pagination:an(u.oneOfType([u.shape(N7()).loose,u.looseBool])),prefixCls:u.string,rowKey:u.any,renderItem:u.any,size:u.oneOf(eEe),split:u.looseBool,header:u.any,footer:u.any,locale:{type:Object}},ji=G({name:\"AList\",Item:R7,props:Rn(tEe,{dataSource:[],bordered:!1,split:!0,loading:!1,pagination:!1}),slots:[\"extra\",\"loadMore\",\"renderItem\",\"header\",\"footer\"],setup:function(t,n){var r=n.slots,a,o;ot(D7,{grid:yn(t,\"grid\"),itemLayout:yn(t,\"itemLayout\")});var i={current:1,total:0},l=Wt(\"list\",t),s=l.prefixCls,c=l.direction,d=l.renderEmpty,f=x(function(){return t.pagination&&kt(t.pagination)===\"object\"?t.pagination:{}}),p=H((a=f.value.defaultCurrent)!==null&&a!==void 0?a:1),v=H((o=f.value.defaultPageSize)!==null&&o!==void 0?o:10);ce(f,function(){\"current\"in f.value&&(p.value=f.value.current),\"pageSize\"in f.value&&(v.value=f.value.pageSize)});var m=function(N){return function(D,z){p.value=D,v.value=z,f.value[N]&&f.value[N](D,z)}},y=m(\"onChange\"),b=m(\"onShowSizeChange\"),C=function(N){var D;return g(\"div\",{class:\"\".concat(s.value,\"-empty-text\")},[((D=t.locale)===null||D===void 0?void 0:D.emptyText)||N(\"List\")])},S=x(function(){return typeof t.loading==\"boolean\"?{spinning:t.loading}:t.loading}),w=x(function(){return S.value&&S.value.spinning}),k=x(function(){var F=\"\";switch(t.size){case\"large\":F=\"lg\";break;case\"small\":F=\"sm\";break}return F}),$=x(function(){var F;return F={},V(F,\"\".concat(s.value),!0),V(F,\"\".concat(s.value,\"-vertical\"),t.itemLayout===\"vertical\"),V(F,\"\".concat(s.value,\"-\").concat(k.value),k.value),V(F,\"\".concat(s.value,\"-split\"),t.split),V(F,\"\".concat(s.value,\"-bordered\"),t.bordered),V(F,\"\".concat(s.value,\"-loading\"),w.value),V(F,\"\".concat(s.value,\"-grid\"),!!t.grid),V(F,\"\".concat(s.value,\"-rtl\"),c.value===\"rtl\"),F}),O=x(function(){var F=P(P(P({},i),{total:t.dataSource.length,current:p.value,pageSize:v.value}),t.pagination||{}),N=Math.ceil(F.total/F.pageSize);return F.current>N&&(F.current=N),F}),T=x(function(){var F=Je(t.dataSource);return t.pagination&&t.dataSource.length>(O.value.current-1)*O.value.pageSize&&(F=Je(t.dataSource).splice((O.value.current-1)*O.value.pageSize,O.value.pageSize)),F}),_=F2(),I=x(function(){for(var F=0;F<ws.length;F+=1){var N=ws[F];if(_.value[N])return N}}),L=x(function(){if(!!t.grid){var F=I.value&&t.grid[I.value]?t.grid[I.value]:t.grid.column;if(F)return{width:\"\".concat(100/F,\"%\"),maxWidth:\"\".concat(100/F,\"%\")}}}),j=function(N,D,z){var B,M=(B=t.renderItem)!==null&&B!==void 0?B:r.renderItem;if(!M)return null;var E;return typeof t.rowKey==\"function\"?E=t.rowKey(D):typeof t.rowKey==\"string\"?E=D[t.rowKey]:E=D.key,E||(E=\"list-item-\".concat(z)),N[z]=E,M({item:D,index:z})};return function(){var F,N,D,z,B,M,E,K=(F=t.loadMore)!==null&&F!==void 0?F:(N=r.loadMore)===null||N===void 0?void 0:N.call(r),W=(D=t.footer)!==null&&D!==void 0?D:(z=r.footer)===null||z===void 0?void 0:z.call(r),Y=(B=t.header)!==null&&B!==void 0?B:(M=r.header)===null||M===void 0?void 0:M.call(r),q=Un((E=r.default)===null||E===void 0?void 0:E.call(r)),J=[],ne=!!(K||t.pagination||W),oe=P(P({},$.value),V({},\"\".concat(s.value,\"-something-after-last-item\"),ne)),Q=t.pagination?g(\"div\",{class:\"\".concat(s.value,\"-pagination\")},[g(OS,le(le({},O.value),{},{onChange:y,onShowSizeChange:b}),null)]):null,ae=w.value&&g(\"div\",{style:{minHeight:\"53px\"}},null);if(T.value.length>0){var de=T.value.map(function(Pe,Be){return j(J,Pe,Be)}),be=de.map(function(Pe,Be){return g(\"div\",{key:J[Be],style:L.value},[Pe])});ae=t.grid?g(Q2,{gutter:t.grid.gutter},{default:function(){return[be]}}):g(\"ul\",{class:\"\".concat(s.value,\"-items\")},[de])}else!q.length&&!w.value&&(ae=C(d.value));var Ee=O.value.position||\"bottom\";return g(\"div\",{class:oe},[(Ee===\"top\"||Ee===\"both\")&&Q,Y&&g(\"div\",{class:\"\".concat(s.value,\"-header\")},[Y]),g(ol,S.value,{default:function(){return[ae,q]}}),W&&g(\"div\",{class:\"\".concat(s.value,\"-footer\")},[W]),K||(Ee===\"bottom\"||Ee===\"both\")&&Q])}}});ji.install=function(e){return e.component(ji.name,ji),e.component(ji.Item.name,ji.Item),e.component(ji.Item.Meta.name,ji.Item.Meta),e};var nEe=ji,rEe={mixins:[nt],props:{duration:u.number.def(1.5),closable:u.looseBool,prefixCls:u.string,update:u.looseBool,closeIcon:u.any,onClose:u.func},watch:{duration:function(){this.restartCloseTimer()}},mounted:function(){this.startCloseTimer()},updated:function(){this.update&&this.restartCloseTimer()},beforeUnmount:function(){this.clearCloseTimer(),this.willDestroy=!0},methods:{close:function(t){t&&t.stopPropagation(),this.clearCloseTimer(),this.__emit(\"close\")},startCloseTimer:function(){var t=this;this.clearCloseTimer(),!this.willDestroy&&this.duration&&(this.closeTimer=setTimeout(function(){t.close()},this.duration*1e3))},clearCloseTimer:function(){this.closeTimer&&(clearTimeout(this.closeTimer),this.closeTimer=null)},restartCloseTimer:function(){this.clearCloseTimer(),this.startCloseTimer()}},render:function(){var t,n=this.prefixCls,r=this.closable,a=this.clearCloseTimer,o=this.startCloseTimer,i=this.close,l=this.$attrs,s=\"\".concat(n,\"-notice\"),c=(t={},V(t,\"\".concat(s),1),V(t,\"\".concat(s,\"-closable\"),r),t),d=We(this,\"closeIcon\");return g(\"div\",{class:c,style:l.style||{right:\"50%\"},onMouseenter:a,onMouseleave:o},[g(\"div\",{class:\"\".concat(s,\"-content\")},[ht(this)]),r?g(\"a\",{tabindex:\"0\",onClick:i,class:\"\".concat(s,\"-close\")},[d||g(\"span\",{class:\"\".concat(s,\"-close-x\")},null)]):null])}},aEe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function oEe(){}var iEe=0,lEe=Date.now();function sEe(){return\"rcNotification_\".concat(lEe,\"_\").concat(iEe++)}var T1=G({mixins:[nt],props:{prefixCls:u.string.def(\"rc-notification\"),transitionName:u.string,animation:u.oneOfType([u.string,u.object]).def(\"fade\"),maxCount:u.number,closeIcon:u.any},data:function(){return{notices:[]}},methods:{getTransitionName:function(){var t=this.$props,n=t.transitionName;return!n&&t.animation&&(n=\"\".concat(t.prefixCls,\"-\").concat(t.animation)),n},add:function(t){var n=t.key=t.key||sEe(),r=this.$props.maxCount;this.setState(function(a){var o=a.notices,i=o.map(function(s){return s.key}).indexOf(n),l=o.concat();return i!==-1?l.splice(i,1,t):(r&&o.length>=r&&(t.updateKey=l[0].updateKey||l[0].key,l.shift()),l.push(t)),{notices:l}})},remove:function(t){this.setState(function(n){return{notices:n.notices.filter(function(r){return r.key!==t})}})}},render:function(){var t=this,n=this.prefixCls,r=this.notices,a=this.remove,o=this.getTransitionName,i=this.$attrs,l=d2(o()),s=r.map(function(d,f){var p=Boolean(f===r.length-1&&d.updateKey),v=d.updateKey?d.updateKey:d.key,m=d.content,y=d.duration,b=d.closable,C=d.onClose,S=d.style,w=d.class,k=id(a.bind(t,d.key),C),$={prefixCls:n,duration:y,closable:b,update:p,closeIcon:We(t,\"closeIcon\"),onClose:k,onClick:d.onClick||oEe,style:S,class:w,key:v};return g(rEe,$,{default:function(){return[typeof m==\"function\"?m():m]}})}),c=V({},n,1);return g(\"div\",{class:c,style:i.style||{top:\"65px\",left:\"50%\"}},[g(f2,le({tag:\"span\"},l),{default:function(){return[s]}})])}});T1.newInstance=function(t,n){var r=t||{},a=r.getContainer,o=r.style,i=r.class,l=aEe(r,[\"getContainer\",\"style\",\"class\"]),s=document.createElement(\"div\");if(a){var c=a();c.appendChild(s)}else document.body.appendChild(s);var d=$m({mounted:function(){var p=this;this.$nextTick(function(){n({notice:function(m){p.$refs.notification.add(m)},removeNotice:function(m){p.$refs.notification.remove(m)},component:p,destroy:function(){d.unmount(s),s.parentNode&&s.parentNode.removeChild(s)}})})},render:function(){var p=P(P({},l),{ref:\"notification\",style:o,class:i});return g(T1,p,null)}});d.mount(s)};var L7=T1,F7=3,B7,oa,uEe=1,um=\"ant-message\",V7=\"move-up\",z7=function(){return document.body},H7;function cEe(e){if(oa){e(oa);return}L7.newInstance({prefixCls:um,transitionName:V7,style:{top:B7},getContainer:z7,maxCount:H7},function(t){if(oa){e(oa);return}oa=t,e(t)})}var dEe={info:BA,success:zf,error:Yr,warning:Hf,loading:co};function fEe(e){var t=e.duration!==void 0?e.duration:F7,n=dEe[e.type],r=n?g(n,null,null):\"\",a=e.key||uEe++,o=new Promise(function(l){var s=function(){return typeof e.onClose==\"function\"&&e.onClose(),l(!0)};cEe(function(c){c.notice({key:a,duration:t,style:e.style||{},class:e.class,content:function(){return g(\"div\",{class:\"\".concat(um,\"-custom-content\").concat(e.type?\" \".concat(um,\"-\").concat(e.type):\"\")},[e.icon||r,g(\"span\",null,[e.content])])},onClose:s})})}),i=function(){oa&&oa.removeNotice(a)};return i.then=function(l,s){return o.then(l,s)},i.promise=o,i}function hEe(e){return Object.prototype.toString.call(e)===\"[object Object]\"&&!!e.content}var Lu={open:fEe,config:function(t){t.top!==void 0&&(B7=t.top,oa=null),t.duration!==void 0&&(F7=t.duration),t.prefixCls!==void 0&&(um=t.prefixCls),t.getContainer!==void 0&&(z7=t.getContainer),t.transitionName!==void 0&&(V7=t.transitionName,oa=null),t.maxCount!==void 0&&(H7=t.maxCount,oa=null)},destroy:function(){oa&&(oa.destroy(),oa=null)}};[\"success\",\"info\",\"warning\",\"error\",\"loading\"].forEach(function(e){Lu[e]=function(t,n,r){return hEe(t)?Lu.open(P(P({},t),{type:e})):(typeof n==\"function\"&&(r=n,n=void 0),Lu.open({content:t,duration:n,type:e,onClose:r}))}});Lu.warn=Lu.warning;var j7=Lu;function pEe(e){var t=e.selectionStart;return e.value.slice(0,t)}function sx(e){return(e||\"\").toLowerCase()}function vEe(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"\",n=Array.isArray(t)?t:[t];return n.reduce(function(r,a){var o=e.lastIndexOf(a);return o>r.location?{location:o,prefix:a}:r},{location:-1,prefix:\"\"})}function mEe(e,t,n){var r=e[0];if(!r||r===n)return e;for(var a=e,o=t.length,i=0;i<o;i+=1)if(sx(a[i])!==sx(t[i])){a=a.slice(i);break}else i===o-1&&(a=a.slice(o));return a}function gEe(e,t){var n=t.measureLocation,r=t.prefix,a=t.targetText,o=t.selectionStart,i=t.split,l=e.slice(0,n);l[l.length-i.length]===i&&(l=l.slice(0,l.length-i.length)),l&&(l=\"\".concat(l).concat(i));var s=mEe(e.slice(o),a.slice(o-n-r.length),i);s.slice(0,i.length)===i&&(s=s.slice(i.length));var c=\"\".concat(l).concat(r).concat(a).concat(i);return{text:\"\".concat(c).concat(s),selectionLocation:c.length}}function yEe(e,t){e.setSelectionRange(t,t),e.blur(),e.focus()}function bEe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.split;return!n||e.indexOf(n)===-1}function CEe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.value,r=n===void 0?\"\":n,a=e.toLowerCase();return r.toLowerCase().indexOf(a)!==-1}var PS={value:u.string,disabled:u.looseBool,children:u.any},wEe=G({name:\"Option\",props:PS,render:function(){return null}});function ux(){}var SEe={name:\"DropdownMenu\",props:{prefixCls:u.string,options:u.arrayOf(PS)},setup:function(){return{mentionsContext:ve(\"mentionsContext\")}},render:function(){var t=this.mentionsContext,n=t.notFoundContent,r=t.activeIndex,a=t.setActiveIndex,o=t.selectOption,i=t.onFocus,l=i===void 0?ux:i,s=t.onBlur,c=s===void 0?ux:s,d=this.$props,f=d.prefixCls,p=d.options,v=p[r]||{};return g(jr,{prefixCls:\"\".concat(f,\"-menu\"),activeKey:v.value,onSelect:function(y){var b=y.key,C=p.find(function(S){var w=S.value;return w===b});o(C)},onBlur:c,onFocus:l},{default:function(){return[[].concat(Je(p.map(function(y,b){var C=y.value,S=y.disabled,w=y.children;return g(fl,{key:C,disabled:S,onMouseenter:function(){a(b)}},{default:function(){return[w]}})})),[!p.length&&g(fl,{key:\"notFoundContent\",disabled:!0},{default:function(){return[n]}})]).filter(Boolean)]}})}},K7=rt(\"top\",\"bottom\"),kEe={bottomRight:{points:[\"tl\",\"br\"],offset:[0,4],overflow:{adjustX:0,adjustY:1}},topRight:{points:[\"bl\",\"tr\"],offset:[0,-4],overflow:{adjustX:0,adjustY:1}}},$Ee={name:\"KeywordTrigger\",props:{loading:u.looseBool,options:u.arrayOf(PS),prefixCls:u.string,placement:u.oneOf(K7),visible:u.looseBool,transitionName:u.string,getPopupContainer:u.func},methods:{getDropdownPrefix:function(){return\"\".concat(this.$props.prefixCls,\"-dropdown\")},getDropdownElement:function(){var t=this.$props.options;return g(SEe,{prefixCls:this.getDropdownPrefix(),options:t},null)}},render:function(){var t,n=this.$props,r=n.visible,a=n.placement,o=n.transitionName,i=n.getPopupContainer,l=this.$slots,s=(t=l.default)===null||t===void 0?void 0:t.call(l),c=this.getDropdownElement();return g(Ii,{prefixCls:this.getDropdownPrefix(),popupVisible:r,popup:c,popupPlacement:a===\"top\"?\"topRight\":\"bottomRight\",popupTransitionName:o,builtinPlacements:kEe,getPopupContainer:i},{default:function(){return[s]}})}},W7={autofocus:u.looseBool,prefix:u.oneOfType([u.string,u.array]),prefixCls:u.string,value:u.string,defaultValue:u.string,disabled:u.looseBool,notFoundContent:u.VNodeChild,split:u.string,transitionName:u.string,placement:u.oneOf(K7),character:u.any,characterRender:u.func,filterOption:{type:[Boolean,Function]},validateSearch:u.func,getPopupContainer:{type:Function}},U7=P(P({},W7),{children:u.any}),Y7={prefix:\"@\",split:\" \",validateSearch:bEe,filterOption:CEe};An(U7,Y7);var cx=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function dx(){}var OEe={name:\"Mentions\",mixins:[nt],inheritAttrs:!1,props:An(U7,Y7),created:function(){this.mentionsContext=ot(\"mentionsContext\",this)},data:function(){var t=this.$props,n=t.value,r=n===void 0?\"\":n,a=t.defaultValue,o=a===void 0?\"\":a;return cc(this.$props.children),{_value:vt(this,\"value\")?r:o,measuring:!1,measureLocation:0,measureText:null,measurePrefix:\"\",activeIndex:0,isFocus:!1}},watch:{value:function(t){this.$data._value=t}},updated:function(){var t=this;this.$nextTick(function(){var n=t.$data.measuring;n&&(t.$refs.measure.scrollTop=t.$refs.textarea.scrollTop)})},methods:{triggerChange:function(t){var n=Qe(this);\"value\"in n?this.$forceUpdate():this.setState({_value:t}),this.__emit(\"change\",t)},onChange:function(t){var n=t.target,r=n.value,a=n.composing,o=t.isComposing;o||a||this.triggerChange(r)},onKeyDown:function(t){var n=t.which,r=this.$data,a=r.activeIndex,o=r.measuring;if(!!o){if(n===ze.UP||n===ze.DOWN){var i=this.getOptions().length,l=n===ze.UP?-1:1,s=(a+l+i)%i;this.setState({activeIndex:s}),t.preventDefault()}else if(n===ze.ESC)this.stopMeasure();else if(n===ze.ENTER){t.preventDefault();var c=this.getOptions();if(!c.length){this.stopMeasure();return}var d=c[a];this.selectOption(d)}}},onKeyUp:function(t){var n=t.key,r=t.which,a=this.$data,o=a.measureText,i=a.measuring,l=this.$props,s=l.prefix,c=s===void 0?\"\":s,d=l.validateSearch,f=t.target;if(!f.composing){var p=pEe(f),v=vEe(p,c),m=v.location,y=v.prefix;if([ze.ESC,ze.UP,ze.DOWN,ze.ENTER].indexOf(r)===-1)if(m!==-1){var b=p.slice(m+y.length),C=d(b,this.$props),S=!!this.getOptions(b).length;C?(n===y||i||b!==o&&S)&&this.startMeasure(b,y,m):i&&this.stopMeasure(),C&&this.__emit(\"search\",b,y)}else i&&this.stopMeasure()}},onInputFocus:function(t){this.onFocus(t)},onInputBlur:function(t){this.onBlur(t)},onDropdownFocus:function(){this.onFocus()},onDropdownBlur:function(){this.onBlur()},onFocus:function(t){window.clearTimeout(this.focusId);var n=this.$data.isFocus;!n&&t&&this.__emit(\"focus\",t),this.setState({isFocus:!0})},onBlur:function(t){var n=this;this.focusId=window.setTimeout(function(){n.setState({isFocus:!1}),n.stopMeasure(),n.__emit(\"blur\",t)},100)},selectOption:function(t){var n=this,r=this.$data,a=r._value,o=r.measureLocation,i=r.measurePrefix,l=this.$props.split,s=t.value,c=s===void 0?\"\":s,d=gEe(a,{measureLocation:o,targetText:c,prefix:i,selectionStart:this.$refs.textarea.selectionStart,split:l}),f=d.text,p=d.selectionLocation;this.triggerChange(f),this.stopMeasure(function(){yEe(n.$refs.textarea,p)}),this.__emit(\"select\",t,i)},setActiveIndex:function(t){this.setState({activeIndex:t})},getOptions:function(t){var n=t||this.$data.measureText||\"\",r=this.$props,a=r.filterOption,o=r.children,i=o===void 0?[]:o,l=(Array.isArray(i)?i:[i]).map(function(s){var c,d;return P(P({},Qe(s)),{children:(d=(c=s.children).default)===null||d===void 0?void 0:d.call(c)})}).filter(function(s){return a===!1?!0:a(n,s)});return l},startMeasure:function(t,n,r){this.setState({measuring:!0,measureText:t,measurePrefix:n,measureLocation:r,activeIndex:0})},stopMeasure:function(t){this.setState({measuring:!1,measureLocation:0,measureText:null},t)},focus:function(){this.$refs.textarea.focus()},blur:function(){this.$refs.textarea.blur()}},render:function(){var t=this.$data,n=t._value,r=t.measureLocation,a=t.measurePrefix,o=t.measuring,i=Qe(this),l=i.prefixCls,s=i.placement,c=i.transitionName;i.notFoundContent;var d=i.getPopupContainer,f=cx(i,[\"prefixCls\",\"placement\",\"transitionName\",\"notFoundContent\",\"getPopupContainer\"]),p=this.$attrs,v=p.class,m=p.style,y=cx(p,[\"class\",\"style\"]),b=bn(f,[\"value\",\"defaultValue\",\"prefix\",\"split\",\"children\",\"validateSearch\",\"filterOption\"]),C=o?this.getOptions():[],S=P(P(P({},b),y),{onChange:dx,onSelect:dx,value:n,onInput:this.onChange,onBlur:this.onInputBlur,onKeydown:this.onKeyDown,onKeyup:this.onKeyUp,onFocus:this.onInputFocus});return g(\"div\",{class:Se(l,v),style:m},[at(g(\"textarea\",le({ref:\"textarea\"},S),null),[[Mi]]),o&&g(\"div\",{ref:\"measure\",class:\"\".concat(l,\"-measure\")},[n.slice(0,r),g($Ee,{prefixCls:l,transitionName:c,placement:s,options:C,visible:!0,getPopupContainer:d},{default:function(){return[g(\"span\",null,[a])]}}),n.slice(r+a.length)])])}},TS=G(OEe);TS.Option=wEe;var fx=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},hx=TS.Option;function PEe(){return!0}function TEe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",t=arguments.length>1?arguments[1]:void 0,n=t||{},r=n.prefix,a=r===void 0?\"@\":r,o=n.split,i=o===void 0?\" \":o,l=Array.isArray(a)?a:[a];return e.split(i).map(function(){var s=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",c=null;return l.some(function(d){var f=s.slice(0,d.length);return f===d?(c=d,!0):!1}),c!==null?{prefix:c,value:s.slice(c.length)}:null}).filter(function(s){return!!s&&!!s.value})}var xEe=P(P({},W7),{loading:u.looseBool,onFocus:{type:Function},onBlur:{type:Function},onSelect:{type:Function},onChange:{type:Function}}),Hl=G({name:\"AMentions\",mixins:[nt],inheritAttrs:!1,Option:P(P({},hx),{name:\"AMentionsOption\"}),getMentions:TEe,props:xEe,emits:[\"update:value\",\"change\",\"focus\",\"blur\",\"select\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){return{focused:!1}},mounted:function(){Ne(function(){})},methods:{handleFocus:function(t){this.$emit(\"focus\",t),this.setState({focused:!0})},handleBlur:function(t){this.$emit(\"blur\",t),this.setState({focused:!1})},handleSelect:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.$emit.apply(this,[\"select\"].concat(n)),this.setState({focused:!0})},handleChange:function(t){this.$emit(\"update:value\",t),this.$emit(\"change\",t)},getNotFoundContent:function(t){var n=We(this,\"notFoundContent\");return n!==void 0?n:t(\"Select\")},getOptions:function(){var t=this.$props.loading,n=ht(this);return t?g(hx,{value:\"ANTD_SEARCHING\",disabled:!0},{default:function(){return[g(ol,{size:\"small\"},null)]}}):n},getFilterOption:function(){var t=this.$props,n=t.filterOption,r=t.loading;return r?PEe:n},focus:function(){this.$refs.vcMentions.focus()},blur:function(){this.$refs.vcMentions.blur()}},render:function(){var t,n=this.$data.focused,r=this.configProvider,a=r.getPrefixCls,o=r.renderEmpty,i=Qe(this),l=i.prefixCls,s=i.disabled,c=i.getPopupContainer,d=fx(i,[\"prefixCls\",\"disabled\",\"getPopupContainer\"]),f=this.$attrs,p=f.class,v=fx(f,[\"class\"]),m=a(\"mentions\",l),y=bn(d,[\"loading\",\"onUpdate:value\"]),b=Se(p,(t={},V(t,\"\".concat(m,\"-disabled\"),s),V(t,\"\".concat(m,\"-focused\"),n),t)),C=P(P(P(P({prefixCls:m,notFoundContent:this.getNotFoundContent(o)},y),{disabled:s,filterOption:this.getFilterOption(),getPopupContainer:c,children:this.getOptions(),class:b,rows:1}),v),{onChange:this.handleChange,onSelect:this.handleSelect,onFocus:this.handleFocus,onBlur:this.handleBlur,ref:\"vcMentions\"});return g(TS,C,null)}});Hl.install=function(e){return e.component(Hl.name,Hl),e.component(Hl.Option.name,Hl.Option),e};var _Ee=Hl.Option,EEe=Hl,x1=null,MEe=function(t){x1={x:t.pageX,y:t.pageY},setTimeout(function(){return x1=null},100)};typeof window!=\"undefined\"&&window.document&&window.document.documentElement&&Kn(document.documentElement,\"click\",MEe,!0);function IEe(){}var NEe={prefixCls:u.string,visible:u.looseBool,confirmLoading:u.looseBool,title:u.any,closable:u.looseBool,closeIcon:u.any,onOk:{type:Function},onCancel:{type:Function},afterClose:u.func.def(IEe),centered:u.looseBool,width:u.oneOfType([u.string,u.number]),footer:u.any,okText:u.any,okType:{type:String},cancelText:u.any,icon:u.any,maskClosable:u.looseBool,forceRender:u.looseBool,okButtonProps:u.shape(Hv).loose,cancelButtonProps:u.shape(Hv).loose,destroyOnClose:u.looseBool,wrapClassName:u.string,maskTransitionName:u.string,transitionName:u.string,getContainer:u.any,zIndex:u.number,bodyStyle:u.style,maskStyle:u.style,mask:u.looseBool,keyboard:u.looseBool,wrapProps:u.object,focusTriggerAfterClose:u.looseBool},wu=[],cr=G({name:\"AModal\",inheritAttrs:!1,props:Rn(NEe,{width:520,transitionName:\"zoom\",maskTransitionName:\"fade\",confirmLoading:!1,visible:!1,okType:\"primary\"}),emits:[\"update:visible\",\"cancel\",\"change\",\"ok\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){return{sVisible:!!this.visible}},watch:{visible:function(t){this.sVisible=t}},methods:{handleCancel:function(t){this.$emit(\"update:visible\",!1),this.$emit(\"cancel\",t),this.$emit(\"change\",!1)},handleOk:function(t){this.$emit(\"ok\",t)},renderFooter:function(t){var n=this,r=this.okType,a=this.confirmLoading,o=P({onClick:this.handleCancel},this.cancelButtonProps||{}),i=P(P(P({onClick:this.handleOk},w2(r)),{loading:a}),this.okButtonProps||{});return g(\"div\",null,[g(Cr,o,{default:function(){return[We(n,\"cancelText\")||t.cancelText]}}),g(Cr,i,{default:function(){return[We(n,\"okText\")||t.okText]}})])}},render:function(){var t=this.prefixCls,n=this.sVisible,r=this.wrapClassName,a=this.centered,o=this.getContainer,i=this.$attrs,l=ht(this),s=this.configProvider,c=s.getPrefixCls,d=s.getPopupContainer,f=c(\"modal\",t),p=g(Kr,{componentName:\"Modal\",defaultLocale:qN(),children:this.renderFooter},null),v=We(this,\"closeIcon\"),m=g(\"span\",{class:\"\".concat(f,\"-close-x\")},[v||g(go,{class:\"\".concat(f,\"-close-icon\")},null)]),y=We(this,\"footer\"),b=We(this,\"title\"),C=P(P(P({},this.$props),i),{getContainer:o===void 0?d:o,prefixCls:f,wrapClassName:Se(V({},\"\".concat(f,\"-centered\"),!!a),r),title:b,footer:y===void 0?p:y,visible:n,mousePosition:x1,closeIcon:m,onClose:this.handleCancel});return g(P7,C,{default:function(){return[l]}})}}),AEe={type:{type:String},actionFn:u.func,closeModal:u.func,autofocus:u.looseBool,buttonProps:u.object},px=G({mixins:[nt],props:AEe,setup:function(){return{timeoutId:void 0}},data:function(){return{loading:!1}},mounted:function(){var t=this;this.autofocus&&(this.timeoutId=setTimeout(function(){return Sn(t).focus()}))},beforeUnmount:function(){clearTimeout(this.timeoutId)},methods:{onClick:function(){var t=this,n=this.actionFn,r=this.closeModal;if(n){var a;n.length?a=n(r):(a=n(),a||r()),a&&a.then&&(this.setState({loading:!0}),a.then(function(){r.apply(void 0,arguments)},function(o){console.error(o),t.setState({loading:!1})}))}else r()}},render:function(){var t=this,n=this.type,r=this.loading,a=this.buttonProps,o=P(P(P({},w2(n)),{onClick:this.onClick,loading:r}),a);return g(Cr,o,{default:function(){return[ht(t)]}})}});function Xc(e,t){return typeof t==\"function\"?t():t}var q7=function(t){var n=t.icon,r=t.onCancel,a=t.onOk,o=t.close,i=t.closable,l=i===void 0?!1:i,s=t.zIndex,c=t.afterClose,d=t.visible,f=t.keyboard,p=t.centered,v=t.getContainer,m=t.maskStyle,y=t.okButtonProps,b=t.cancelButtonProps,C=t.okType||\"primary\",S=t.prefixCls||\"ant-modal\",w=\"\".concat(S,\"-confirm\"),k=\"okCancel\"in t?t.okCancel:!0,$=t.width||416,O=t.style||{},T=t.mask===void 0?!0:t.mask,_=t.maskClosable===void 0?!1:t.maskClosable,I=qN(),L=Xc(\"okText\",t.okText)||(k?I.okText:I.justOkText),j=Xc(\"cancelText\",t.cancelText)||I.cancelText,F=t.autoFocusButton===null?!1:t.autoFocusButton||\"ok\",N=t.transitionName||\"zoom\",D=t.maskTransitionName||\"fade\",z=Se(w,\"\".concat(w,\"-\").concat(t.type),\"\".concat(S,\"-\").concat(t.type),t.class),B=k&&g(px,{actionFn:r,closeModal:o,autofocus:F===\"cancel\",buttonProps:b},{default:function(){return[j]}});return g(cr,{prefixCls:S,class:z,wrapClassName:Se(V({},\"\".concat(w,\"-centered\"),!!p)),onCancel:function(E){return o({triggerCancel:!0},E)},visible:d,title:\"\",transitionName:N,footer:\"\",maskTransitionName:D,mask:T,maskClosable:_,maskStyle:m,style:O,width:$,zIndex:s,afterClose:c,keyboard:f,centered:p,getContainer:v,closable:l},{default:function(){return[g(\"div\",{class:\"\".concat(w,\"-body-wrapper\")},[g(\"div\",{class:\"\".concat(w,\"-body\")},[Xc(\"icon\",n),t.title===void 0?null:g(\"span\",{class:\"\".concat(w,\"-title\")},[Xc(\"title\",t.title)]),g(\"div\",{class:\"\".concat(w,\"-content\")},[Xc(\"content\",t.content)])]),g(\"div\",{class:\"\".concat(w,\"-btns\")},[B,g(px,{type:C,actionFn:a,closeModal:o,autofocus:F===\"ok\",buttonProps:y},{default:function(){return[L]}})])])]}})};q7.inheritAttrs=!1;var DEe=q7,REe=function(t){var n=document.createElement(\"div\");document.body.appendChild(n);var r=P(P({},bn(t,[\"parentContext\",\"appContext\"])),{close:o,visible:!0}),a=null;function o(){for(var d=arguments.length,f=new Array(d),p=0;p<d;p++)f[p]=arguments[p];r=P(P({},r),{visible:!1,afterClose:l.bind.apply(l,[this].concat(f))}),i(r)}function i(d){r=P(P({},r),d),a&&(P(a.component.props,r),a.component.update())}function l(){a&&n.parentNode&&(P(a.component.props,{vIf:!1}),a.component.update(),a=null,n.parentNode.removeChild(n));for(var d=arguments.length,f=new Array(d),p=0;p<d;p++)f[p]=arguments[p];var v=f.some(function(b){return b&&b.triggerCancel});t.onCancel&&v&&t.onCancel.apply(t,f);for(var m=0;m<wu.length;m++){var y=wu[m];if(y===o){wu.splice(m,1);break}}}var s=function(f){return f.vIf?g(DEe,f,null):null};function c(d){var f=g(s,P(P({},d),{vIf:!0}));return f.appContext=t.parentContext||t.appContext||f.appContext,vs(f,n),f}return a=c(r),wu.push(o),{destroy:o,update:i}},jf=REe,LEe=function(t){var n=P({type:\"info\",icon:function(){return g(I2,null,null)},okCancel:!1},t);return jf(n)},FEe=function(t){var n=P({type:\"success\",icon:function(){return g(x2,null,null)},okCancel:!1},t);return jf(n)},BEe=function(t){var n=P({type:\"error\",icon:function(){return g(A2,null,null)},okCancel:!1},t);return jf(n)},G7=function(t){var n=P({type:\"warning\",icon:function(){return g(E2,null,null)},okCancel:!1},t);return jf(n)},VEe=G7,zEe=function(t){var n=P({type:\"confirm\",okCancel:!0},t);return jf(n)};cr.info=LEe;cr.success=FEe;cr.error=BEe;cr.warning=G7;cr.warn=VEe;cr.confirm=zEe;cr.destroyAll=function(){for(;wu.length;){var t=wu.pop();t&&t()}};cr.install=function(e){return e.component(cr.name,cr),e};var X7=function(t){var n=t.value,r=t.formatter,a=t.precision,o=t.decimalSeparator,i=t.groupSeparator,l=i===void 0?\"\":i,s=t.prefixCls,c;if(typeof r==\"function\")c=r({value:n});else{var d=String(n),f=d.match(/^(-?)(\\d*)(\\.(\\d+))?$/);if(!f)c=d;else{var p=f[1],v=f[2]||\"0\",m=f[4]||\"\";v=v.replace(/\\B(?=(\\d{3})+(?!\\d))/g,l),typeof a==\"number\"&&(m=zW(m,a,\"0\").slice(0,a)),m&&(m=\"\".concat(o).concat(m)),c=[g(\"span\",{key:\"int\",class:\"\".concat(s,\"-content-value-int\")},[p,v]),m&&g(\"span\",{key:\"decimal\",class:\"\".concat(s,\"-content-value-decimal\")},[m])]}}return g(\"span\",{class:\"\".concat(s,\"-content-value\")},[c])};X7.displayName=\"StatisticNumber\";var HEe=X7,Ng=function(){return{prefixCls:u.string,size:u.oneOfType([u.oneOf(rt(\"large\",\"small\",\"default\")),u.number]),shape:u.oneOf(rt(\"circle\",\"square\",\"round\")),active:u.looseBool}},Z7=function(t){var n,r,a=t.prefixCls,o=t.size,i=t.shape,l=Se((n={},V(n,\"\".concat(a,\"-lg\"),o===\"large\"),V(n,\"\".concat(a,\"-sm\"),o===\"small\"),n)),s=Se((r={},V(r,\"\".concat(a,\"-circle\"),i===\"circle\"),V(r,\"\".concat(a,\"-square\"),i===\"square\"),V(r,\"\".concat(a,\"-round\"),i===\"round\"),r)),c=typeof o==\"number\"?{width:\"\".concat(o,\"px\"),height:\"\".concat(o,\"px\"),lineHeight:\"\".concat(o,\"px\")}:{};return g(\"span\",{class:Se(a,l,s),style:c},null)};Z7.displayName=\"SkeletonElement\";var Ag=Z7,J7=Rn(P(P({},Ng()),{shape:u.oneOf(rt(\"circle\",\"square\"))}),{size:\"large\"}),jEe=G({name:\"ASkeletonAvatar\",props:J7,setup:function(t){var n=Wt(\"skeleton\",t),r=n.prefixCls,a=x(function(){return Se(r.value,\"\".concat(r.value,\"-element\"),V({},\"\".concat(r.value,\"-active\"),t.active))});return function(){return g(\"div\",{class:a.value},[g(Ag,le(le({},t),{},{prefixCls:\"\".concat(r.value,\"-avatar\")}),null)])}}}),xS=jEe,Q7={prefixCls:u.string,width:u.oneOfType([u.number,u.string])},KEe=G({name:\"SkeletonTitle\",props:Q7,setup:function(t){return function(){var n=t.prefixCls,r=t.width,a=typeof r==\"number\"?\"\".concat(r,\"px\"):r;return g(\"h3\",{class:n,style:{width:a}},null)}}}),WEe=KEe,vx=u.oneOfType([u.number,u.string]),eR={prefixCls:u.string,width:u.oneOfType([vx,u.arrayOf(vx)]),rows:u.number},UEe=G({name:\"SkeletonParagraph\",props:eR,setup:function(t){var n=function(a){var o=t.width,i=t.rows,l=i===void 0?2:i;if(Array.isArray(o))return o[a];if(l-1===a)return o};return function(){var r=t.prefixCls,a=t.rows,o=Je(Array(a)).map(function(i,l){var s=n(l);return g(\"li\",{key:l,style:{width:typeof s==\"number\"?\"\".concat(s,\"px\"):s}},null)});return g(\"ul\",{class:r},[o])}}}),YEe=UEe,qEe={active:u.looseBool,loading:u.looseBool,prefixCls:u.string,avatar:an(u.oneOfType([u.string,u.shape(bn(J7,[\"active\"])).loose,u.looseBool])),title:an(u.oneOfType([u.looseBool,u.string,u.shape(Q7).loose])),paragraph:an(u.oneOfType([u.looseBool,u.string,u.shape(eR).loose]))};function gb(e){return e&&kt(e)===\"object\"?e:{}}function GEe(e,t){return e&&!t?{size:\"large\",shape:\"square\"}:{size:\"large\",shape:\"circle\"}}function XEe(e,t){return!e&&t?{width:\"38%\"}:e&&t?{width:\"50%\"}:{}}function ZEe(e,t){var n={};return(!e||!t)&&(n.width=\"61%\"),!e&&t?n.rows=3:n.rows=2,n}var JEe=G({name:\"ASkeleton\",props:An(qEe,{avatar:!1,title:!0,paragraph:!0}),setup:function(t,n){var r=n.slots,a=Wt(\"skeleton\",t),o=a.prefixCls,i=a.direction;return function(){var l,s=t.loading,c=t.avatar,d=t.title,f=t.paragraph,p=t.active,v=t.round,m=o.value;if(s||t.loading===void 0){var y,b=!!c||c===\"\",C=!!d||d===\"\",S=!!f||f===\"\",w;if(b){var k=P(P({prefixCls:\"\".concat(m,\"-avatar\")},GEe(C,S)),gb(c));w=g(\"div\",{class:\"\".concat(m,\"-header\")},[g(Ag,k,null)])}var $;if(C||S){var O;if(C){var T=P(P({prefixCls:\"\".concat(m,\"-title\")},XEe(b,S)),gb(d));O=g(WEe,T,null)}var _;if(S){var I=P(P({prefixCls:\"\".concat(m,\"-paragraph\")},ZEe(b,C)),gb(f));_=g(YEe,I,null)}$=g(\"div\",{class:\"\".concat(m,\"-content\")},[O,_])}var L=Se(m,(y={},V(y,\"\".concat(m,\"-with-avatar\"),b),V(y,\"\".concat(m,\"-active\"),p),V(y,\"\".concat(m,\"-rtl\"),i.value===\"rtl\"),V(y,\"\".concat(m,\"-round\"),v),y));return g(\"div\",{class:L},[w,$])}return(l=r.default)===null||l===void 0?void 0:l.call(r)}}}),na=JEe,tR={prefixCls:u.string,decimalSeparator:u.string,groupSeparator:u.string,format:u.string,value:{type:[String,Number,Object]},valueStyle:u.style,valueRender:u.any,formatter:u.any,precision:u.number,prefix:u.VNodeChild,suffix:u.VNodeChild,title:u.VNodeChild,onFinish:u.func,loading:u.looseBool},oi=G({name:\"AStatistic\",props:Rn(tR,{decimalSeparator:\".\",groupSeparator:\",\",loading:!1}),slots:[\"title\",\"prefix\",\"suffix\",\"formatter\"],setup:function(t,n){var r=n.slots,a=Wt(\"statistic\",t),o=a.prefixCls,i=a.direction;return function(){var l,s,c,d,f,p,v,m=t.value,y=m===void 0?0:m,b=t.valueStyle,C=t.valueRender,S=o.value,w=(l=t.title)!==null&&l!==void 0?l:(s=r.title)===null||s===void 0?void 0:s.call(r),k=(c=t.prefix)!==null&&c!==void 0?c:(d=r.prefix)===null||d===void 0?void 0:d.call(r),$=(f=t.suffix)!==null&&f!==void 0?f:(p=r.suffix)===null||p===void 0?void 0:p.call(r),O=(v=t.formatter)!==null&&v!==void 0?v:r.formatter,T=g(HEe,le({\"data-for-update\":Date.now()},P(P({},t),{prefixCls:S,value:y,formatter:O})),null);return C&&(T=C(T)),g(\"div\",{class:[S,V({},\"\".concat(S,\"-rtl\"),i.value===\"rtl\")]},[w&&g(\"div\",{class:\"\".concat(S,\"-title\")},[w]),g(na,{paragraph:!1,loading:t.loading},{default:function(){return[g(\"div\",{style:b,class:\"\".concat(S,\"-content\")},[k&&g(\"span\",{class:\"\".concat(S,\"-content-prefix\")},[k]),T,$&&g(\"span\",{class:\"\".concat(S,\"-content-suffix\")},[$])])]}})])}}}),QEe=[[\"Y\",1e3*60*60*24*365],[\"M\",1e3*60*60*24*30],[\"D\",1e3*60*60*24],[\"H\",1e3*60*60],[\"m\",1e3*60],[\"s\",1e3],[\"S\",1]];function eMe(e,t){var n=e,r=/\\[[^\\]]*]/g,a=(t.match(r)||[]).map(function(s){return s.slice(1,-1)}),o=t.replace(r,\"[]\"),i=QEe.reduce(function(s,c){var d=fn(c,2),f=d[0],p=d[1];if(s.indexOf(f)!==-1){var v=Math.floor(n/p);return n-=v*p,s.replace(new RegExp(\"\".concat(f,\"+\"),\"g\"),function(m){var y=m.length;return HW(v.toString(),y,\"0\")})}return s},o),l=0;return i.replace(r,function(){var s=a[l];return l+=1,s})}function tMe(e,t){var n=t.format,r=n===void 0?\"\":n,a=new Date(e).getTime(),o=Date.now(),i=Math.max(a-o,0);return eMe(i,r)}var nMe=1e3/30;function yb(e){return new Date(e).getTime()}var rMe=G({name:\"AStatisticCountdown\",props:Rn(tR,{format:\"HH:mm:ss\"}),emits:[\"finish\",\"change\"],setup:function(t,n){var r=n.emit,a=H(),o=H(),i=function(){var p=t.value,v=yb(p);v>=Date.now()?l():s()},l=function(){if(!a.value){var p=yb(t.value);a.value=window.setInterval(function(){o.value.$forceUpdate(),p>Date.now()&&r(\"change\",p-Date.now()),i()},nMe)}},s=function(){var p=t.value;if(a.value){clearInterval(a.value),a.value=void 0;var v=yb(p);v<Date.now()&&r(\"finish\")}},c=function(p){var v=p.value,m=p.config,y=t.format;return tMe(v,P(P({},m),{format:y}))},d=function(p){return p};return et(function(){i()}),ur(function(){i()}),Lt(function(){s()}),function(){return g(oi,le({ref:o},P(P({},t),{valueRender:d,formatter:c})),null)}}});oi.Countdown=rMe;oi.install=function(e){return e.component(oi.name,oi),e.component(oi.Countdown.name,oi.Countdown),e};var aMe=oi.Countdown,Ui={},nR=4.5,rR=\"24px\",aR=\"24px\",oR=\"topRight\",iR=function(){return document.body},lR=null;function oMe(e){var t=e.duration,n=e.placement,r=e.bottom,a=e.top,o=e.getContainer,i=e.closeIcon;t!==void 0&&(nR=t),n!==void 0&&(oR=n),r!==void 0&&(aR=typeof r==\"number\"?\"\".concat(r,\"px\"):r),a!==void 0&&(rR=typeof a==\"number\"?\"\".concat(a,\"px\"):a),o!==void 0&&(iR=o),i!==void 0&&(lR=i)}function iMe(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:rR,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:aR,r;switch(e){case\"topLeft\":r={left:\"0px\",top:t,bottom:\"auto\"};break;case\"topRight\":r={right:\"0px\",top:t,bottom:\"auto\"};break;case\"bottomLeft\":r={left:\"0px\",top:\"auto\",bottom:n};break;default:r={right:\"0px\",top:\"auto\",bottom:n};break}return r}function lMe(e,t){var n=e.prefixCls,r=e.placement,a=r===void 0?oR:r,o=e.getContainer,i=o===void 0?iR:o,l=e.top,s=e.bottom,c=e.closeIcon,d=c===void 0?lR:c,f=\"\".concat(n,\"-\").concat(a);if(Ui[f]){t(Ui[f]);return}L7.newInstance({prefixCls:n,class:\"\".concat(n,\"-\").concat(a),style:iMe(a,l,s),getContainer:i,closeIcon:function(){var v=g(\"span\",{class:\"\".concat(n,\"-close-x\")},[d||g(go,{class:\"\".concat(n,\"-close-icon\")},null)]);return v}},function(p){Ui[f]=p,t(p)})}var sMe={success:x2,info:I2,error:A2,warning:E2};function uMe(e){var t=e.icon,n=e.type,r=e.description,a=e.message,o=e.btn,i=e.prefixCls||\"ant-notification\",l=\"\".concat(i,\"-notice\"),s=e.duration===void 0?nR:e.duration,c=null;if(t)c=function(){return g(\"span\",{class:\"\".concat(l,\"-icon\")},[t])};else if(n){var d=sMe[n];c=function(){return g(d,{class:\"\".concat(l,\"-icon \").concat(l,\"-icon-\").concat(n)},null)}}var f=e.placement,p=e.top,v=e.bottom,m=e.getContainer,y=e.closeIcon;lMe({prefixCls:i,placement:f,top:p,bottom:v,getContainer:m,closeIcon:y},function(b){b.notice({content:function(){return g(\"div\",{class:c?\"\".concat(l,\"-with-icon\"):\"\"},[c&&c(),g(\"div\",{class:\"\".concat(l,\"-message\")},[!r&&c?g(\"span\",{class:\"\".concat(l,\"-message-single-line-auto-margin\")},null):null,a]),g(\"div\",{class:\"\".concat(l,\"-description\")},[r]),o?g(\"span\",{class:\"\".concat(l,\"-btn\")},[o]):null])},duration:s,closable:!0,onClose:e.onClose,onClick:e.onClick,key:e.key,style:e.style||{},class:e.class})})}var cMe={open:uMe,close:function(t){Object.keys(Ui).forEach(function(n){return Ui[n].removeNotice(t)})},config:oMe,destroy:function(){Object.keys(Ui).forEach(function(t){Ui[t].destroy(),delete Ui[t]})}},vf=cMe,dMe=[\"success\",\"info\",\"warning\",\"error\"];dMe.forEach(function(e){vf[e]=function(t){return vf.open(P(P({},t),{type:e}))}});vf.warn=vf.warning;var sR=vf,fMe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M872 474H286.9l350.2-304c5.6-4.9 2.2-14-5.2-14h-88.5c-3.9 0-7.6 1.4-10.5 3.9L155 487.8a31.96 31.96 0 000 48.3L535.1 866c1.5 1.3 3.3 2 5.2 2h91.5c7.4 0 10.8-9.2 5.2-14L286.9 550H872c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z\"}}]},name:\"arrow-left\",theme:\"outlined\"},hMe=fMe;function mx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){pMe(e,a,n[a])})}return e}function pMe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var _S=function(t,n){var r=mx({},t,n.attrs);return g(Et,mx({},r,{icon:hMe}),null)};_S.displayName=\"ArrowLeftOutlined\";_S.inheritAttrs=!1;var vMe=_S,mMe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M869 487.8L491.2 159.9c-2.9-2.5-6.6-3.9-10.5-3.9h-88.5c-7.4 0-10.8 9.2-5.2 14l350.2 304H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h585.1L386.9 854c-5.6 4.9-2.2 14 5.2 14h91.5c1.9 0 3.8-.7 5.2-2L869 536.2a32.07 32.07 0 000-48.4z\"}}]},name:\"arrow-right\",theme:\"outlined\"},gMe=mMe;function gx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){yMe(e,a,n[a])})}return e}function yMe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var ES=function(t,n){var r=gx({},t,n.attrs);return g(Et,gx({},r,{icon:gMe}),null)};ES.displayName=\"ArrowRightOutlined\";ES.inheritAttrs=!1;var bMe=ES,CMe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},wMe={border:0,background:\"transparent\",padding:0,lineHeight:\"inherit\",display:\"inline-block\"},SMe=G({name:\"TransButton\",inheritAttrs:!1,props:{noStyle:u.looseBool,onClick:u.func,disabled:u.looseBool,autofocus:u.looseBool},setup:function(t,n){var r=n.slots,a=n.emit,o=n.attrs,i=n.expose,l=H(),s=function(m){var y=m.keyCode;y===ze.ENTER&&m.preventDefault()},c=function(m){var y=m.keyCode;y===ze.ENTER&&a(\"click\",m)},d=function(m){a(\"click\",m)},f=function(){l.value&&l.value.focus()},p=function(){l.value&&l.value.blur()};return et(function(){t.autofocus&&f()}),i({focus:f,blur:p}),function(){var v,m=t.noStyle,y=t.disabled,b=CMe(t,[\"noStyle\",\"disabled\"]),C={};return m||(C=P({},wMe)),y&&(C.pointerEvents=\"none\"),g(\"div\",le(le(le({role:\"button\",tabindex:0,ref:l},b),o),{},{onClick:d,onKeydown:s,onKeyup:c,style:P(P({},C),o.style||{})}),[(v=r.default)===null||v===void 0?void 0:v.call(r)])}}}),cm=SMe,kMe={backIcon:u.VNodeChild,prefixCls:u.string,title:u.VNodeChild,subTitle:u.VNodeChild,breadcrumb:u.object,tags:u.any,footer:u.VNodeChild,extra:u.VNodeChild,avatar:u.object,ghost:u.looseBool,onBack:u.func},$Me=G({name:\"APageHeader\",props:kMe,emits:[\"back\"],slots:[\"backIcon\",\"avatar\",\"breadcrumb\",\"title\",\"subTitle\",\"tags\",\"extra\",\"footer\"],setup:function(t,n){var r=n.emit,a=n.slots,o=Wt(\"page-header\",t),i=o.prefixCls,l=o.direction,s=o.pageHeader,c=H(!1),d=function(w){var k=w.width;c.value=k<768},f=x(function(){var S,w,k;return(k=(S=t.ghost)!==null&&S!==void 0?S:(w=s.value)===null||w===void 0?void 0:w.ghost)!==null&&k!==void 0?k:!0}),p=function(){var w,k,$;return($=(w=t.backIcon)!==null&&w!==void 0?w:(k=a.backIcon)===null||k===void 0?void 0:k.call(a))!==null&&$!==void 0?$:l.value===\"rtl\"?g(bMe,null,null):g(vMe,null,null)},v=function(w){return!w||!t.onBack?null:g(Kr,{componentName:\"PageHeader\",children:function($){var O=$.back;return g(\"div\",{class:\"\".concat(i.value,\"-back\")},[g(cm,{onClick:function(_){r(\"back\",_)},class:\"\".concat(i.value,\"-back-button\"),\"aria-label\":O},{default:function(){return[w]}})])}},null)},m=function(){var w;return t.breadcrumb?g(us,t.breadcrumb,null):(w=a.breadcrumb)===null||w===void 0?void 0:w.call(a)},y=function(){var w,k,$,O,T,_,I,L,j,F=t.avatar,N=(w=t.title)!==null&&w!==void 0?w:(k=a.title)===null||k===void 0?void 0:k.call(a),D=($=t.subTitle)!==null&&$!==void 0?$:(O=a.subTitle)===null||O===void 0?void 0:O.call(a),z=(T=t.tags)!==null&&T!==void 0?T:(_=a.tags)===null||_===void 0?void 0:_.call(a),B=(I=t.extra)!==null&&I!==void 0?I:(L=a.extra)===null||L===void 0?void 0:L.call(a),M=\"\".concat(i.value,\"-heading\"),E=N||D||z||B;if(!E)return null;var K=p(),W=v(K),Y=W||F||E;return g(\"div\",{class:M},[Y&&g(\"div\",{class:\"\".concat(M,\"-left\")},[W,F?g(ss,F,null):(j=a.avatar)===null||j===void 0?void 0:j.call(a),N&&g(\"span\",{class:\"\".concat(M,\"-title\"),title:typeof N==\"string\"?N:void 0},[N]),D&&g(\"span\",{class:\"\".concat(M,\"-sub-title\"),title:typeof D==\"string\"?D:void 0},[D]),z&&g(\"span\",{class:\"\".concat(M,\"-tags\")},[z])]),B&&g(\"span\",{class:\"\".concat(M,\"-extra\")},[B])])},b=function(){var w,k,$=(w=t.footer)!==null&&w!==void 0?w:La((k=a.footer)===null||k===void 0?void 0:k.call(a));return i0e($)?null:g(\"div\",{class:\"\".concat(i.value,\"-footer\")},[$])},C=function(w){return g(\"div\",{class:\"\".concat(i.value,\"-content\")},[w])};return function(){var S,w,k,$=((w=t.breadcrumb)===null||w===void 0?void 0:w.routes)||a.breadcrumb,O=t.footer||a.footer,T=Un((k=a.default)===null||k===void 0?void 0:k.call(a)),_=Se(i.value,(S={\"has-breadcrumb\":$,\"has-footer\":O},V(S,\"\".concat(i.value,\"-ghost\"),f.value),V(S,\"\".concat(i.value,\"-rtl\"),l.value===\"rtl\"),V(S,\"\".concat(i.value,\"-compact\"),c.value),S));return g(zo,{onResize:d},{default:function(){return[g(\"div\",{class:_},[m(),y(),T.length?C(T):null,b()])]}})}}}),OMe=kn($Me),yx=kg(),PMe=G({name:\"APopconfirm\",mixins:[nt],props:P(P({},yx),{prefixCls:u.string,transitionName:u.string.def(\"zoom-big\"),content:u.any,title:u.any,trigger:yx.trigger.def(\"click\"),okType:{type:String,default:\"primary\"},disabled:u.looseBool.def(!1),okText:u.any,cancelText:u.any,icon:u.any,okButtonProps:u.object,cancelButtonProps:u.object,onConfirm:u.func,onCancel:u.func,onVisibleChange:u.func}),emits:[\"update:visible\",\"confirm\",\"cancel\",\"visibleChange\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},data:function(){var t=Qe(this),n={sVisible:!1};return\"visible\"in t&&(n.sVisible=t.visible),\"defaultVisible\"in t&&(n.sVisible=t.defaultVisible),n},watch:{visible:function(t){this.sVisible=t}},methods:{onConfirmHandle:function(t){this.setVisible(!1,t),this.$emit(\"confirm\",t)},onCancelHandle:function(t){this.setVisible(!1,t),this.$emit(\"cancel\",t)},onVisibleChangeHandle:function(t){var n=this.$props.disabled;n||this.setVisible(t)},setVisible:function(t,n){vt(this,\"visible\")||this.setState({sVisible:t}),this.$emit(\"update:visible\",t),this.$emit(\"visibleChange\",t,n)},getPopupDomNode:function(){return this.$refs.tooltip.getPopupDomNode()},renderOverlay:function(t,n){var r=this,a=this.okType,o=this.okButtonProps,i=this.cancelButtonProps,l=We(this,\"icon\")||g(Hf,null,null),s=HO(P({size:\"small\",onClick:this.onCancelHandle},i)),c=HO(P(P(P({},w2(a)),{size:\"small\",onClick:this.onConfirmHandle}),o));return g(\"div\",{class:\"\".concat(t,\"-inner-content\")},[g(\"div\",{class:\"\".concat(t,\"-message\")},[l,g(\"div\",{class:\"\".concat(t,\"-message-title\")},[We(this,\"title\")])]),g(\"div\",{class:\"\".concat(t,\"-buttons\")},[g(Cr,s,{default:function(){return[We(r,\"cancelText\")||n.cancelText]}}),g(Cr,c,{default:function(){return[We(r,\"okText\")||n.okText]}})])])}},render:function(){var t=this,n,r=Qe(this),a=r.prefixCls,o=this.configProvider.getPrefixCls,i=o(\"popover\",a),l=bn(r,[\"title\",\"content\",\"cancelText\",\"okText\",\"onUpdate:visible\"]),s=g(Kr,{componentName:\"Popconfirm\",defaultLocale:lo.Popconfirm,children:function(f){return t.renderOverlay(i,f)}},null),c=P(P({},l),{title:s,prefixCls:i,visible:this.sVisible,ref:\"tooltip\",onVisibleChange:this.onVisibleChangeHandle});return g(Io,c,{default:function(){return[(n=t.$slots)===null||n===void 0?void 0:n.default()]}})}}),TMe=kn(PMe);function cs(e){return!e||e<0?0:e>100?100:e}var xMe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},_Me=function(t){for(var n=[],r=0,a=Object.entries(t);r<a.length;r++){var o=fn(a[r],2),i=o[0],l=o[1],s=parseFloat(i.replace(/%/g,\"\"));if(isNaN(s))return{};n.push({key:s,value:l})}return n=n.sort(function(c,d){return c.key-d.key}),n.map(function(c){var d=c.key,f=c.value;return\"\".concat(f,\" \").concat(d,\"%\")}).join(\", \")},EMe=function(t){var n=t.from,r=n===void 0?\"#1890ff\":n,a=t.to,o=a===void 0?\"#1890ff\":a,i=t.direction,l=i===void 0?\"to right\":i,s=xMe(t,[\"from\",\"to\",\"direction\"]);if(Object.keys(s).length!==0){var c=_Me(s);return{backgroundImage:\"linear-gradient(\".concat(l,\", \").concat(c,\")\")}}return{backgroundImage:\"linear-gradient(\".concat(l,\", \").concat(r,\", \").concat(o,\")\")}},MMe=function(t,n){var r=n.attrs,a=n.slots,o=r.prefixCls,i=r.percent,l=r.successPercent,s=r.strokeWidth,c=r.size,d=r.strokeColor,f=r.strokeLinecap,p=r.trailColor,v;d&&typeof d!=\"string\"?v=EMe(d):v={background:d};var m=p?{style:{backgroundColor:p}}:void 0,y=P({width:\"\".concat(cs(i),\"%\"),height:\"\".concat(s||(c===\"small\"?6:8),\"px\"),background:d,borderRadius:f===\"square\"?0:\"100px\"},v),b={width:\"\".concat(cs(l),\"%\"),height:\"\".concat(s||(c===\"small\"?6:8),\"px\"),borderRadius:f===\"square\"?0:\"\"},C=l!==void 0?g(\"div\",{class:\"\".concat(o,\"-success-bg\"),style:b},null):null;return g(\"div\",null,[g(\"div\",{class:\"\".concat(o,\"-outer\")},[g(\"div\",le({class:\"\".concat(o,\"-inner\")},m),[g(\"div\",{class:\"\".concat(o,\"-bg\"),style:y},null),C])]),a==null?void 0:a.default()])},IMe=MMe;function NMe(e){return P(P({},e),{updated:function(){var n=this,r=Date.now(),a=!1;Object.keys(this.paths).forEach(function(o){var i=n.paths[o];if(!!i){a=!0;var l=i.style;l.transitionDuration=\".3s, .3s, .3s, .06s\",n.prevTimeStamp&&r-n.prevTimeStamp<100&&(l.transitionDuration=\"0s, 0s\")}}),a&&(this.prevTimeStamp=Date.now())}})}var AMe={percent:0,prefixCls:\"rc-progress\",strokeColor:\"#2db7f5\",strokeLinecap:\"round\",strokeWidth:1,trailColor:\"#D9D9D9\",trailWidth:1},qh=u.oneOfType([u.number,u.string]),DMe={percent:u.oneOfType([qh,u.arrayOf(qh)]),prefixCls:u.string,strokeColor:u.oneOfType([u.string,u.arrayOf(u.oneOfType([u.string,u.object])),u.object]),strokeLinecap:u.oneOf([\"butt\",\"round\",\"square\"]),strokeWidth:qh,trailColor:u.string,trailWidth:qh},RMe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},LMe=P(P({},DMe),{gapPosition:u.oneOf([\"top\",\"bottom\",\"left\",\"right\"]),gapDegree:an(u.oneOfType([u.number,u.string,u.looseBool]))}),FMe=P(P({},AMe),{gapPosition:\"top\"}),bx=0;function Cx(e){return+e.replace(\"%\",\"\")}function bb(e){return Array.isArray(e)?e:[e]}function wx(e,t,n,r){var a=arguments.length>4&&arguments[4]!==void 0?arguments[4]:0,o=arguments.length>5?arguments[5]:void 0,i=50-r/2,l=0,s=-i,c=0,d=-2*i;switch(o){case\"left\":l=-i,s=0,c=2*i,d=0;break;case\"right\":l=i,s=0,c=-2*i,d=0;break;case\"bottom\":s=i,d=2*i;break}var f=\"M 50,50 m \".concat(l,\",\").concat(s,`\n   a `).concat(i,\",\").concat(i,\" 0 1 1 \").concat(c,\",\").concat(-d,`\n   a `).concat(i,\",\").concat(i,\" 0 1 1 \").concat(-c,\",\").concat(d),p=Math.PI*2*i,v={stroke:n,strokeDasharray:\"\".concat(t/100*(p-a),\"px \").concat(p,\"px\"),strokeDashoffset:\"-\".concat(a/2+e/100*(p-a),\"px\"),transition:\"stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s\"};return{pathString:f,pathStyle:v}}var BMe=G({name:\"Circle\",props:An(LMe,FMe),created:function(){this.paths={},this.gradientId=bx,bx+=1},methods:{getStokeList:function(){var t=this,n=this.$props,r=n.prefixCls,a=n.percent,o=n.strokeColor,i=n.strokeWidth,l=n.strokeLinecap,s=n.gapDegree,c=n.gapPosition,d=bb(a),f=bb(o),p=0;return d.map(function(v,m){var y=f[m]||f[f.length-1],b=Object.prototype.toString.call(y)===\"[object Object]\"?\"url(#\".concat(r,\"-gradient-\").concat(t.gradientId,\")\"):\"\",C=wx(p,v,y,i,s,c),S=C.pathString,w=C.pathStyle;p+=v;var k={key:m,d:S,stroke:b,\"stroke-linecap\":l,\"stroke-width\":i,opacity:v===0?0:1,\"fill-opacity\":\"0\",class:\"\".concat(r,\"-circle-path\"),style:w};return g(\"path\",le({ref:function(O){return t.paths[m]=O}},k),null)})}},render:function(){var t=this.$props,n=t.prefixCls,r=t.strokeWidth,a=t.trailWidth,o=t.gapDegree,i=t.gapPosition,l=t.trailColor,s=t.strokeLinecap,c=t.strokeColor,d=RMe(t,[\"prefixCls\",\"strokeWidth\",\"trailWidth\",\"gapDegree\",\"gapPosition\",\"trailColor\",\"strokeLinecap\",\"strokeColor\"]),f=wx(0,100,l,r,o,i),p=f.pathString,v=f.pathStyle;delete d.percent;var m=bb(c),y=m.find(function(C){return Object.prototype.toString.call(C)===\"[object Object]\"}),b={d:p,stroke:l,\"stroke-linecap\":s,\"stroke-width\":a||r,\"fill-opacity\":\"0\",class:\"\".concat(n,\"-circle-trail\"),style:v};return g(\"svg\",le({class:\"\".concat(n,\"-circle\"),viewBox:\"0 0 100 100\"},d),[y&&g(\"defs\",null,[g(\"linearGradient\",{id:\"\".concat(n,\"-gradient-\").concat(this.gradientId),x1:\"100%\",y1:\"0%\",x2:\"0%\",y2:\"0%\"},[Object.keys(y).sort(function(C,S){return Cx(C)-Cx(S)}).map(function(C,S){return g(\"stop\",{key:S,offset:C,\"stop-color\":y[C]},null)})])]),g(\"path\",b,null),this.getStokeList().reverse()])}}),VMe=NMe(BMe),uR=rt(\"normal\",\"exception\",\"active\",\"success\"),zMe=u.oneOf(rt(\"line\",\"circle\",\"dashboard\")),HMe=u.oneOf(rt(\"default\",\"small\")),cR={prefixCls:u.string,type:zMe,percent:u.number,successPercent:u.number,format:u.func,status:u.oneOf(uR),showInfo:u.looseBool,strokeWidth:u.number,strokeLinecap:u.oneOf([\"butt\",\"round\",\"square\"]),strokeColor:u.oneOfType([u.string,u.object]),trailColor:u.string,width:u.number,gapDegree:u.number,gapPosition:u.oneOf(rt(\"top\",\"bottom\",\"left\",\"right\")),size:HMe},jMe=P(P({},cR),{progressStatus:u.string}),Sx={normal:\"#108ee9\",exception:\"#ff5500\",success:\"#87d068\"};function KMe(e){var t=e.percent,n=e.successPercent,r=cs(t);if(!n)return r;var a=cs(n);return[n,cs(r-a)]}function WMe(e){var t=e.progressStatus,n=e.successPercent,r=e.strokeColor,a=r||Sx[t];return n?[Sx.success,a]:a}var UMe=G({props:jMe,setup:function(t,n){var r=n.slots;return function(){var a,o=t.prefixCls,i=t.width,l=t.strokeWidth,s=t.trailColor,c=t.strokeLinecap,d=t.gapPosition,f=t.gapDegree,p=t.type,v=i||120,m={width:typeof v==\"number\"?\"\".concat(v,\"px\"):v,height:typeof v==\"number\"?\"\".concat(v,\"px\"):v,fontSize:\"\".concat(v*.15+6,\"px\")},y=l||6,b=d||p===\"dashboard\"&&\"bottom\"||\"top\",C=f||p===\"dashboard\"&&75,S=WMe(t),w=Object.prototype.toString.call(S)===\"[object Object]\",k=(a={},V(a,\"\".concat(o,\"-inner\"),!0),V(a,\"\".concat(o,\"-circle-gradient\"),w),a);return g(\"div\",{class:k,style:m},[g(VMe,{percent:KMe(t),strokeWidth:y,trailWidth:y,strokeColor:S,strokeLinecap:c,trailColor:s,prefixCls:o,gapDegree:C,gapPosition:b},null),r==null?void 0:r.default()])}}}),YMe=UMe,qMe=G({name:\"AProgress\",props:Rn(cR,{type:\"line\",percent:0,showInfo:!0,trailColor:null,size:\"default\",gapDegree:0,strokeLinecap:\"round\"}),setup:function(){return{configProvider:ve(\"configProvider\",St)}},methods:{getPercentNumber:function(){var t=this.$props,n=t.successPercent,r=t.percent,a=r===void 0?0:r;return parseInt(n!==void 0?n.toString():a.toString(),10)},getProgressStatus:function(){var t=this.$props.status;return uR.indexOf(t)<0&&this.getPercentNumber()>=100?\"success\":t||\"normal\"},renderProcessInfo:function(t,n){var r=this.$props,a=r.showInfo,o=r.format,i=r.type,l=r.percent,s=r.successPercent;if(!a)return null;var c,d=o||this.$slots.format||function(p){return\"\".concat(p,\"%\")},f=i===\"line\";return o||this.$slots.format||n!==\"exception\"&&n!==\"success\"?c=d(cs(l),cs(s)):n===\"exception\"?c=g(f?Yr:go,null,null):n===\"success\"&&(c=g(f?zf:wg,null,null)),g(\"span\",{class:\"\".concat(t,\"-text\"),title:typeof c==\"string\"?c:void 0},[c])}},render:function(){var t,n=Qe(this),r=n.prefixCls,a=n.size,o=n.type,i=n.showInfo,l=this.configProvider.getPrefixCls,s=l(\"progress\",r),c=this.getProgressStatus(),d=this.renderProcessInfo(s,c),f;if(o===\"line\"){var p=P(P({},n),{prefixCls:s});f=g(IMe,p,{default:function(){return[d]}})}else if(o===\"circle\"||o===\"dashboard\"){var v=P(P({},n),{prefixCls:s,progressStatus:c});f=g(YMe,v,{default:function(){return[d]}})}var m=Se(s,(t={},V(t,\"\".concat(s,\"-\").concat(o===\"dashboard\"&&\"circle\"||o),!0),V(t,\"\".concat(s,\"-status-\").concat(c),!0),V(t,\"\".concat(s,\"-show-info\"),i),V(t,\"\".concat(s,\"-\").concat(a),a),t)),y={class:m};return g(\"div\",y,[f])}}),dR=kn(qMe);function GMe(e){var t=e.pageXOffset,n=\"scrollLeft\";if(typeof t!=\"number\"){var r=e.document;t=r.documentElement[n],typeof t!=\"number\"&&(t=r.body[n])}return t}function XMe(e){var t,n,r=e.ownerDocument,a=r.body,o=r&&r.documentElement,i=e.getBoundingClientRect();return t=i.left,n=i.top,t-=o.clientLeft||a.clientLeft||0,n-=o.clientTop||a.clientTop||0,{left:t,top:n}}function ZMe(e){var t=XMe(e),n=e.ownerDocument,r=n.defaultView||n.parentWindow;return t.left+=GMe(r),t.left}var JMe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3z\"}}]},name:\"star\",theme:\"filled\"},QMe=JMe;function kx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){e5e(e,a,n[a])})}return e}function e5e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var MS=function(t,n){var r=kx({},t,n.attrs);return g(Et,kx({},r,{icon:QMe}),null)};MS.displayName=\"StarFilled\";MS.inheritAttrs=!1;var t5e=MS,n5e={value:u.number,index:u.number,prefixCls:u.string,allowHalf:u.looseBool,disabled:u.looseBool,character:u.any,characterRender:u.func,focused:u.looseBool,count:u.number,onClick:u.func,onHover:u.func},r5e=G({name:\"Star\",inheritAttrs:!1,props:n5e,emits:[\"hover\",\"click\"],setup:function(t,n){var r=n.slots,a=n.emit,o=function(d){var f=t.index;a(\"hover\",d,f)},i=function(d){var f=t.index;a(\"click\",d,f)},l=function(d){var f=t.index;d.keyCode===13&&a(\"click\",d,f)},s=x(function(){var c=t.prefixCls,d=t.index,f=t.value,p=t.allowHalf,v=t.focused,m=d+1,y=c;return f===0&&d===0&&v?y+=\" \".concat(c,\"-focused\"):p&&f+.5>=m&&f<m?(y+=\" \".concat(c,\"-half \").concat(c,\"-active\"),v&&(y+=\" \".concat(c,\"-focused\"))):(y+=m<=f?\" \".concat(c,\"-full\"):\" \".concat(c,\"-zero\"),m===f&&v&&(y+=\" \".concat(c,\"-focused\"))),y});return function(){var c=t.disabled,d=t.prefixCls,f=t.characterRender,p=t.index,v=t.count,m=t.value,y=jn(r,t,\"character\"),b=g(\"li\",{class:s.value},[g(\"div\",{onClick:c?null:i,onKeydown:c?null:l,onMousemove:c?null:o,role:\"radio\",\"aria-checked\":m>p?\"true\":\"false\",\"aria-posinset\":p+1,\"aria-setsize\":v,tabindex:c?-1:0},[g(\"div\",{class:\"\".concat(d,\"-first\")},[y]),g(\"div\",{class:\"\".concat(d,\"-second\")},[y])])]);return f&&(b=f(b,t)),b}}}),a5e=function(){var t=H({}),n=function(a,o){t.value[o]=a};return wm(function(){t.value={}}),[n,t]},o5e={prefixCls:u.string,count:u.number,value:u.number,allowHalf:u.looseBool,allowClear:u.looseBool,tooltips:u.arrayOf(u.string),disabled:u.looseBool,character:u.any,autofocus:u.looseBool,tabindex:u.oneOfType([u.number,u.string]),direction:u.string},i5e=G({name:\"ARate\",inheritAttrs:!1,props:An(o5e,{value:0,count:5,allowHalf:!1,allowClear:!0,prefixCls:\"ant-rate\",tabindex:0,direction:\"ltr\"}),emits:[\"hoverChange\",\"update:value\",\"change\",\"focus\",\"blur\",\"keydown\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.emit,i=n.expose,l=Wt(\"rate\",t),s=l.prefixCls,c=l.direction,d=H(),f=a5e(),p=fn(f,2),v=p[0],m=p[1],y=bt({value:t.value,focused:!1,cleanedValue:null,hoverValue:void 0});ce(function(){return t.value},function(){y.value=t.value});var b=function(D){return Sn(m.value[D])},C=function(D,z){var B=c.value===\"rtl\",M=D+1;if(t.allowHalf){var E=b(D),K=ZMe(E),W=E.clientWidth;(B&&z-K>W/2||!B&&z-K<W/2)&&(M-=.5)}return M},S=function(D){t.value===void 0&&(y.value=D),o(\"update:value\",D),o(\"change\",D)},w=function(D,z){var B=C(z,D.pageX);B!==y.cleanedValue&&(y.hoverValue=B,y.cleanedValue=null),o(\"hoverChange\",B)},k=function(){y.hoverValue=void 0,y.cleanedValue=null,o(\"hoverChange\",void 0)},$=function(D,z){var B=t.allowClear,M=C(z,D.pageX),E=!1;B&&(E=M===y.value),k(),S(E?0:M),y.cleanedValue=E?M:null},O=function(){y.focused=!0,o(\"focus\")},T=function(){y.focused=!1,o(\"blur\")},_=function(D){var z=D.keyCode,B=t.count,M=t.allowHalf,E=c.value===\"rtl\";z===ze.RIGHT&&y.value<B&&!E?(M?y.value+=.5:y.value+=1,S(y.value),D.preventDefault()):z===ze.LEFT&&y.value>0&&!E||z===ze.RIGHT&&y.value>0&&E?(M?y.value-=.5:y.value-=1,S(y.value),D.preventDefault()):z===ze.LEFT&&y.value<B&&E&&(M?y.value+=.5:y.value+=1,S(y.value),D.preventDefault()),o(\"keydown\",D)},I=function(){t.disabled||d.value.focus()},L=function(){t.disabled||d.value.blur()};i({focus:I,blur:L}),et(function(){var N=t.autofocus,D=t.disabled;N&&!D&&I()});var j=function(D,z){var B=z.index,M=t.tooltips;return M?g(Io,{title:M[B]},{default:function(){return[D]}}):D},F=jn(r,t,\"character\")||g(t5e,null,null);return function(){for(var N=t.count,D=t.allowHalf,z=t.disabled,B=t.tabindex,M=a.class,E=a.style,K=[],W=z?\"\".concat(s.value,\"-disabled\"):\"\",Y=function(oe){K.push(g(r5e,{ref:function(ae){return v(ae,oe)},key:oe,index:oe,count:N,disabled:z,prefixCls:\"\".concat(s.value,\"-star\"),allowHalf:D,value:y.hoverValue===void 0?y.value:y.hoverValue,onClick:$,onHover:w,character:F,characterRender:j,focused:y.focused},null))},q=0;q<N;q++)Y(q);var J=Se(s.value,W,M,V({},\"\".concat(s.value,\"-rtl\"),c.value===\"rtl\"));return g(\"ul\",le(le({},a),{},{class:J,style:E,onMouseleave:z?null:k,tabindex:z?-1:B,onFocus:z?null:O,onBlur:z?null:T,onKeydown:z?null:_,ref:d,role:\"radiogroup\"}),[K])}}}),l5e=kn(i5e),s5e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M955.7 856l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zM480 416c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v184c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V416zm32 352a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\"}}]},name:\"warning\",theme:\"filled\"},u5e=s5e;function $x(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){c5e(e,a,n[a])})}return e}function c5e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var IS=function(t,n){var r=$x({},t,n.attrs);return g(Et,$x({},r,{icon:u5e}),null)};IS.displayName=\"WarningFilled\";IS.inheritAttrs=!1;var d5e=IS,f5e=function(){return g(\"svg\",{width:\"252\",height:\"294\"},[g(\"defs\",null,[g(\"path\",{d:\"M0 .387h251.772v251.772H0z\"},null)]),g(\"g\",{fill:\"none\",\"fill-rule\":\"evenodd\"},[g(\"g\",{transform:\"translate(0 .012)\"},[g(\"mask\",{fill:\"#fff\"},null),g(\"path\",{d:\"M0 127.32v-2.095C0 56.279 55.892.387 124.838.387h2.096c68.946 0 124.838 55.892 124.838 124.838v2.096c0 68.946-55.892 124.838-124.838 124.838h-2.096C55.892 252.16 0 196.267 0 127.321\",fill:\"#E4EBF7\",mask:\"url(#b)\"},null)]),g(\"path\",{d:\"M39.755 130.84a8.276 8.276 0 1 1-16.468-1.66 8.276 8.276 0 0 1 16.468 1.66\",fill:\"#FFF\"},null),g(\"path\",{d:\"M36.975 134.297l10.482 5.943M48.373 146.508l-12.648 10.788\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{d:\"M39.875 159.352a5.667 5.667 0 1 1-11.277-1.136 5.667 5.667 0 0 1 11.277 1.136M57.588 143.247a5.708 5.708 0 1 1-11.358-1.145 5.708 5.708 0 0 1 11.358 1.145M99.018 26.875l29.82-.014a4.587 4.587 0 1 0-.003-9.175l-29.82.013a4.587 4.587 0 1 0 .003 9.176M110.424 45.211l29.82-.013a4.588 4.588 0 0 0-.004-9.175l-29.82.013a4.587 4.587 0 1 0 .004 9.175\",fill:\"#FFF\"},null),g(\"path\",{d:\"M112.798 26.861v-.002l15.784-.006a4.588 4.588 0 1 0 .003 9.175l-15.783.007v-.002a4.586 4.586 0 0 0-.004-9.172M184.523 135.668c-.553 5.485-5.447 9.483-10.931 8.93-5.485-.553-9.483-5.448-8.93-10.932.552-5.485 5.447-9.483 10.932-8.93 5.485.553 9.483 5.447 8.93 10.932\",fill:\"#FFF\"},null),g(\"path\",{d:\"M179.26 141.75l12.64 7.167M193.006 156.477l-15.255 13.011\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{d:\"M184.668 170.057a6.835 6.835 0 1 1-13.6-1.372 6.835 6.835 0 0 1 13.6 1.372M203.34 153.325a6.885 6.885 0 1 1-13.7-1.382 6.885 6.885 0 0 1 13.7 1.382\",fill:\"#FFF\"},null),g(\"path\",{d:\"M151.931 192.324a2.222 2.222 0 1 1-4.444 0 2.222 2.222 0 0 1 4.444 0zM225.27 116.056a2.222 2.222 0 1 1-4.445 0 2.222 2.222 0 0 1 4.444 0zM216.38 151.08a2.223 2.223 0 1 1-4.446-.001 2.223 2.223 0 0 1 4.446 0zM176.917 107.636a2.223 2.223 0 1 1-4.445 0 2.223 2.223 0 0 1 4.445 0zM195.291 92.165a2.223 2.223 0 1 1-4.445 0 2.223 2.223 0 0 1 4.445 0zM202.058 180.711a2.223 2.223 0 1 1-4.446 0 2.223 2.223 0 0 1 4.446 0z\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{stroke:\"#FFF\",\"stroke-width\":\"2\",d:\"M214.404 153.302l-1.912 20.184-10.928 5.99M173.661 174.792l-6.356 9.814h-11.36l-4.508 6.484M174.941 125.168v-15.804M220.824 117.25l-12.84 7.901-15.31-7.902V94.39\"},null),g(\"path\",{d:\"M166.588 65.936h-3.951a4.756 4.756 0 0 1-4.743-4.742 4.756 4.756 0 0 1 4.743-4.743h3.951a4.756 4.756 0 0 1 4.743 4.743 4.756 4.756 0 0 1-4.743 4.742\",fill:\"#FFF\"},null),g(\"path\",{d:\"M174.823 30.03c0-16.281 13.198-29.48 29.48-29.48 16.28 0 29.48 13.199 29.48 29.48 0 16.28-13.2 29.48-29.48 29.48-16.282 0-29.48-13.2-29.48-29.48\",fill:\"#1890FF\"},null),g(\"path\",{d:\"M205.952 38.387c.5.5.785 1.142.785 1.928s-.286 1.465-.785 1.964c-.572.5-1.214.75-2 .75-.785 0-1.429-.285-1.929-.785-.572-.5-.82-1.143-.82-1.929s.248-1.428.82-1.928c.5-.5 1.144-.75 1.93-.75.785 0 1.462.25 1.999.75m4.285-19.463c1.428 1.249 2.143 2.963 2.143 5.142 0 1.712-.427 3.13-1.219 4.25-.067.096-.137.18-.218.265-.416.429-1.41 1.346-2.956 2.699a5.07 5.07 0 0 0-1.428 1.75 5.207 5.207 0 0 0-.536 2.357v.5h-4.107v-.5c0-1.357.215-2.536.714-3.5.464-.964 1.857-2.464 4.178-4.536l.43-.5c.643-.785.964-1.643.964-2.535 0-1.18-.358-2.108-1-2.785-.678-.68-1.643-1.001-2.858-1.001-1.536 0-2.642.464-3.357 1.43-.37.5-.621 1.135-.76 1.904a1.999 1.999 0 0 1-1.971 1.63h-.004c-1.277 0-2.257-1.183-1.98-2.43.337-1.518 1.02-2.78 2.073-3.784 1.536-1.5 3.607-2.25 6.25-2.25 2.32 0 4.214.607 5.642 1.894\",fill:\"#FFF\"},null),g(\"path\",{d:\"M52.04 76.131s21.81 5.36 27.307 15.945c5.575 10.74-6.352 9.26-15.73 4.935-10.86-5.008-24.7-11.822-11.577-20.88\",fill:\"#FFB594\"},null),g(\"path\",{d:\"M90.483 67.504l-.449 2.893c-.753.49-4.748-2.663-4.748-2.663l-1.645.748-1.346-5.684s6.815-4.589 8.917-5.018c2.452-.501 9.884.94 10.7 2.278 0 0 1.32.486-2.227.69-3.548.203-5.043.447-6.79 3.132-1.747 2.686-2.412 3.624-2.412 3.624\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M128.055 111.367c-2.627-7.724-6.15-13.18-8.917-15.478-3.5-2.906-9.34-2.225-11.366-4.187-1.27-1.231-3.215-1.197-3.215-1.197s-14.98-3.158-16.828-3.479c-2.37-.41-2.124-.714-6.054-1.405-1.57-1.907-2.917-1.122-2.917-1.122l-7.11-1.383c-.853-1.472-2.423-1.023-2.423-1.023l-2.468-.897c-1.645 9.976-7.74 13.796-7.74 13.796 1.795 1.122 15.703 8.3 15.703 8.3l5.107 37.11s-3.321 5.694 1.346 9.109c0 0 19.883-3.743 34.921-.329 0 0 3.047-2.546.972-8.806.523-3.01 1.394-8.263 1.736-11.622.385.772 2.019 1.918 3.14 3.477 0 0 9.407-7.365 11.052-14.012-.832-.723-1.598-1.585-2.267-2.453-.567-.736-.358-2.056-.765-2.717-.669-1.084-1.804-1.378-1.907-1.682\",fill:\"#FFF\"},null),g(\"path\",{d:\"M101.09 289.998s4.295 2.041 7.354 1.021c2.821-.94 4.53.668 7.08 1.178 2.55.51 6.874 1.1 11.686-1.26-.103-5.51-6.889-3.98-11.96-6.713-2.563-1.38-3.784-4.722-3.598-8.799h-9.402s-1.392 10.52-1.16 14.573\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M101.067 289.826s2.428 1.271 6.759.653c3.058-.437 3.712.481 7.423 1.031 3.712.55 10.724-.069 11.823-.894.413 1.1-.343 2.063-.343 2.063s-1.512.603-4.812.824c-2.03.136-5.8.291-7.607-.503-1.787-1.375-5.247-1.903-5.728-.241-3.918.95-7.355-.286-7.355-.286l-.16-2.647z\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M108.341 276.044h3.094s-.103 6.702 4.536 8.558c-4.64.618-8.558-2.303-7.63-8.558\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M57.542 272.401s-2.107 7.416-4.485 12.306c-1.798 3.695-4.225 7.492 5.465 7.492 6.648 0 8.953-.48 7.423-6.599-1.53-6.12.266-13.199.266-13.199h-8.669z\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M51.476 289.793s2.097 1.169 6.633 1.169c6.083 0 8.249-1.65 8.249-1.65s.602 1.114-.619 2.165c-.993.855-3.597 1.591-7.39 1.546-4.145-.048-5.832-.566-6.736-1.168-.825-.55-.687-1.58-.137-2.062\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M58.419 274.304s.033 1.519-.314 2.93c-.349 1.42-1.078 3.104-1.13 4.139-.058 1.151 4.537 1.58 5.155.034.62-1.547 1.294-6.427 1.913-7.252.619-.825-4.903-2.119-5.624.15\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M99.66 278.514l13.378.092s1.298-54.52 1.853-64.403c.554-9.882 3.776-43.364 1.002-63.128l-12.547-.644-22.849.78s-.434 3.966-1.195 9.976c-.063.496-.682.843-.749 1.365-.075.585.423 1.354.32 1.966-2.364 14.08-6.377 33.104-8.744 46.677-.116.666-1.234 1.009-1.458 2.691-.04.302.211 1.525.112 1.795-6.873 18.744-10.949 47.842-14.277 61.885l14.607-.014s2.197-8.57 4.03-16.97c2.811-12.886 23.111-85.01 23.111-85.01l3.016-.521 1.043 46.35s-.224 1.234.337 2.02c.56.785-.56 1.123-.392 2.244l.392 1.794s-.449 7.178-.898 11.89c-.448 4.71-.092 39.165-.092 39.165\",fill:\"#7BB2F9\"},null),g(\"path\",{d:\"M76.085 221.626c1.153.094 4.038-2.019 6.955-4.935M106.36 225.142s2.774-1.11 6.103-3.883\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M107.275 222.1s2.773-1.11 6.102-3.884\",stroke:\"#648BD8\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M74.74 224.767s2.622-.591 6.505-3.365M86.03 151.634c-.27 3.106.3 8.525-4.336 9.123M103.625 149.88s.11 14.012-1.293 15.065c-2.219 1.664-2.99 1.944-2.99 1.944M99.79 150.438s.035 12.88-1.196 24.377M93.673 175.911s7.212-1.664 9.431-1.664M74.31 205.861a212.013 212.013 0 0 1-.979 4.56s-1.458 1.832-1.009 3.776c.449 1.944-.947 2.045-4.985 15.355-1.696 5.59-4.49 18.591-6.348 27.597l-.231 1.12M75.689 197.807a320.934 320.934 0 0 1-.882 4.754M82.591 152.233L81.395 162.7s-1.097.15-.5 2.244c.113 1.346-2.674 15.775-5.18 30.43M56.12 274.418h13.31\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M116.241 148.22s-17.047-3.104-35.893.2c.158 2.514-.003 4.15-.003 4.15s14.687-2.818 35.67-.312c.252-2.355.226-4.038.226-4.038\",fill:\"#192064\"},null),g(\"path\",{d:\"M106.322 151.165l.003-4.911a.81.81 0 0 0-.778-.815c-2.44-.091-5.066-.108-7.836-.014a.818.818 0 0 0-.789.815l-.003 4.906a.81.81 0 0 0 .831.813c2.385-.06 4.973-.064 7.73.017a.815.815 0 0 0 .842-.81\",fill:\"#FFF\"},null),g(\"path\",{d:\"M105.207 150.233l.002-3.076a.642.642 0 0 0-.619-.646 94.321 94.321 0 0 0-5.866-.01.65.65 0 0 0-.63.647v3.072a.64.64 0 0 0 .654.644 121.12 121.12 0 0 1 5.794.011c.362.01.665-.28.665-.642\",fill:\"#192064\"},null),g(\"path\",{d:\"M100.263 275.415h12.338M101.436 270.53c.006 3.387.042 5.79.111 6.506M101.451 264.548a915.75 915.75 0 0 0-.015 4.337M100.986 174.965l.898 44.642s.673 1.57-.225 2.692c-.897 1.122 2.468.673.898 2.243-1.57 1.57.897 1.122 0 3.365-.596 1.489-.994 21.1-1.096 35.146\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M46.876 83.427s-.516 6.045 7.223 5.552c11.2-.712 9.218-9.345 31.54-21.655-.786-2.708-2.447-4.744-2.447-4.744s-11.068 3.11-22.584 8.046c-6.766 2.9-13.395 6.352-13.732 12.801M104.46 91.057l.941-5.372-8.884-11.43-5.037 5.372-1.74 7.834a.321.321 0 0 0 .108.32c.965.8 6.5 5.013 14.347 3.544a.332.332 0 0 0 .264-.268\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M93.942 79.387s-4.533-2.853-2.432-6.855c1.623-3.09 4.513 1.133 4.513 1.133s.52-3.642 3.121-3.642c.52-1.04 1.561-4.162 1.561-4.162s11.445 2.601 13.526 3.121c0 5.203-2.304 19.424-7.84 19.861-8.892.703-12.449-9.456-12.449-9.456\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M113.874 73.446c2.601-2.081 3.47-9.722 3.47-9.722s-2.479-.49-6.64-2.05c-4.683-2.081-12.798-4.747-17.48.976-9.668 3.223-2.05 19.823-2.05 19.823l2.713-3.021s-3.935-3.287-2.08-6.243c2.17-3.462 3.92 1.073 3.92 1.073s.637-2.387 3.581-3.342c.355-.71 1.036-2.674 1.432-3.85a1.073 1.073 0 0 1 1.263-.704c2.4.558 8.677 2.019 11.356 2.662.522.125.871.615.82 1.15l-.305 3.248z\",fill:\"#520038\"},null),g(\"path\",{d:\"M104.977 76.064c-.103.61-.582 1.038-1.07.956-.489-.083-.801-.644-.698-1.254.103-.61.582-1.038 1.07-.956.488.082.8.644.698 1.254M112.132 77.694c-.103.61-.582 1.038-1.07.956-.488-.083-.8-.644-.698-1.254.103-.61.582-1.038 1.07-.956.488.082.8.643.698 1.254\",fill:\"#552950\"},null),g(\"path\",{stroke:\"#DB836E\",\"stroke-width\":\"1.118\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",d:\"M110.13 74.84l-.896 1.61-.298 4.357h-2.228\"},null),g(\"path\",{d:\"M110.846 74.481s1.79-.716 2.506.537\",stroke:\"#5C2552\",\"stroke-width\":\"1.118\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M92.386 74.282s.477-1.114 1.113-.716c.637.398 1.274 1.433.558 1.99-.717.556.159 1.67.159 1.67\",stroke:\"#DB836E\",\"stroke-width\":\"1.118\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M103.287 72.93s1.83 1.113 4.137.954\",stroke:\"#5C2552\",\"stroke-width\":\"1.118\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M103.685 81.762s2.227 1.193 4.376 1.193M104.64 84.308s.954.398 1.511.318M94.693 81.205s2.308 7.4 10.424 7.639\",stroke:\"#DB836E\",\"stroke-width\":\"1.118\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M81.45 89.384s.45 5.647-4.935 12.787M69 82.654s-.726 9.282-8.204 14.206\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.101\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M129.405 122.865s-5.272 7.403-9.422 10.768\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M119.306 107.329s.452 4.366-2.127 32.062\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.101\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M150.028 151.232h-49.837a1.01 1.01 0 0 1-1.01-1.01v-31.688c0-.557.452-1.01 1.01-1.01h49.837c.558 0 1.01.453 1.01 1.01v31.688a1.01 1.01 0 0 1-1.01 1.01\",fill:\"#F2D7AD\"},null),g(\"path\",{d:\"M150.29 151.232h-19.863v-33.707h20.784v32.786a.92.92 0 0 1-.92.92\",fill:\"#F4D19D\"},null),g(\"path\",{d:\"M123.554 127.896H92.917a.518.518 0 0 1-.425-.816l6.38-9.113c.193-.277.51-.442.85-.442h31.092l-7.26 10.371z\",fill:\"#F2D7AD\"},null),g(\"path\",{fill:\"#CC9B6E\",d:\"M123.689 128.447H99.25v-.519h24.169l7.183-10.26.424.298z\"},null),g(\"path\",{d:\"M158.298 127.896h-18.669a2.073 2.073 0 0 1-1.659-.83l-7.156-9.541h19.965c.49 0 .95.23 1.244.622l6.69 8.92a.519.519 0 0 1-.415.83\",fill:\"#F4D19D\"},null),g(\"path\",{fill:\"#CC9B6E\",d:\"M157.847 128.479h-19.384l-7.857-10.475.415-.31 7.7 10.266h19.126zM130.554 150.685l-.032-8.177.519-.002.032 8.177z\"},null),g(\"path\",{fill:\"#CC9B6E\",d:\"M130.511 139.783l-.08-21.414.519-.002.08 21.414zM111.876 140.932l-.498-.143 1.479-5.167.498.143zM108.437 141.06l-2.679-2.935 2.665-3.434.41.318-2.397 3.089 2.384 2.612zM116.607 141.06l-.383-.35 2.383-2.612-2.397-3.089.41-.318 2.665 3.434z\"},null),g(\"path\",{d:\"M154.316 131.892l-3.114-1.96.038 3.514-1.043.092c-1.682.115-3.634.23-4.789.23-1.902 0-2.693 2.258 2.23 2.648l-2.645-.596s-2.168 1.317.504 2.3c0 0-1.58 1.217.561 2.58-.584 3.504 5.247 4.058 7.122 3.59 1.876-.47 4.233-2.359 4.487-5.16.28-3.085-.89-5.432-3.35-7.238\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M153.686 133.577s-6.522.47-8.36.372c-1.836-.098-1.904 2.19 2.359 2.264 3.739.15 5.451-.044 5.451-.044\",stroke:\"#DB836E\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M145.16 135.877c-1.85 1.346.561 2.355.561 2.355s3.478.898 6.73.617\",stroke:\"#DB836E\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M151.89 141.71s-6.28.111-6.73-2.132c-.223-1.346.45-1.402.45-1.402M146.114 140.868s-1.103 3.16 5.44 3.533M151.202 129.932v3.477M52.838 89.286c3.533-.337 8.423-1.248 13.582-7.754\",stroke:\"#DB836E\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M168.567 248.318a6.647 6.647 0 0 1-6.647-6.647v-66.466a6.647 6.647 0 1 1 13.294 0v66.466a6.647 6.647 0 0 1-6.647 6.647\",fill:\"#5BA02E\"},null),g(\"path\",{d:\"M176.543 247.653a6.647 6.647 0 0 1-6.646-6.647v-33.232a6.647 6.647 0 1 1 13.293 0v33.232a6.647 6.647 0 0 1-6.647 6.647\",fill:\"#92C110\"},null),g(\"path\",{d:\"M186.443 293.613H158.92a3.187 3.187 0 0 1-3.187-3.187v-46.134a3.187 3.187 0 0 1 3.187-3.187h27.524a3.187 3.187 0 0 1 3.187 3.187v46.134a3.187 3.187 0 0 1-3.187 3.187\",fill:\"#F2D7AD\"},null),g(\"path\",{d:\"M88.979 89.48s7.776 5.384 16.6 2.842\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.101\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null)])])},h5e=f5e,p5e=function(){return g(\"svg\",{width:\"254\",height:\"294\"},[g(\"defs\",null,[g(\"path\",{d:\"M0 .335h253.49v253.49H0z\"},null),g(\"path\",{d:\"M0 293.665h253.49V.401H0z\"},null)]),g(\"g\",{fill:\"none\",\"fill-rule\":\"evenodd\"},[g(\"g\",{transform:\"translate(0 .067)\"},[g(\"mask\",{fill:\"#fff\"},null),g(\"path\",{d:\"M0 128.134v-2.11C0 56.608 56.273.334 125.69.334h2.11c69.416 0 125.69 56.274 125.69 125.69v2.11c0 69.417-56.274 125.69-125.69 125.69h-2.11C56.273 253.824 0 197.551 0 128.134\",fill:\"#E4EBF7\",mask:\"url(#b)\"},null)]),g(\"path\",{d:\"M39.989 132.108a8.332 8.332 0 1 1-16.581-1.671 8.332 8.332 0 0 1 16.58 1.671\",fill:\"#FFF\"},null),g(\"path\",{d:\"M37.19 135.59l10.553 5.983M48.665 147.884l-12.734 10.861\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{d:\"M40.11 160.816a5.706 5.706 0 1 1-11.354-1.145 5.706 5.706 0 0 1 11.354 1.145M57.943 144.6a5.747 5.747 0 1 1-11.436-1.152 5.747 5.747 0 0 1 11.436 1.153M99.656 27.434l30.024-.013a4.619 4.619 0 1 0-.004-9.238l-30.024.013a4.62 4.62 0 0 0 .004 9.238M111.14 45.896l30.023-.013a4.62 4.62 0 1 0-.004-9.238l-30.024.013a4.619 4.619 0 1 0 .004 9.238\",fill:\"#FFF\"},null),g(\"path\",{d:\"M113.53 27.421v-.002l15.89-.007a4.619 4.619 0 1 0 .005 9.238l-15.892.007v-.002a4.618 4.618 0 0 0-.004-9.234M150.167 70.091h-3.979a4.789 4.789 0 0 1-4.774-4.775 4.788 4.788 0 0 1 4.774-4.774h3.979a4.789 4.789 0 0 1 4.775 4.774 4.789 4.789 0 0 1-4.775 4.775\",fill:\"#FFF\"},null),g(\"path\",{d:\"M171.687 30.234c0-16.392 13.289-29.68 29.681-29.68 16.392 0 29.68 13.288 29.68 29.68 0 16.393-13.288 29.681-29.68 29.681s-29.68-13.288-29.68-29.68\",fill:\"#FF603B\"},null),g(\"path\",{d:\"M203.557 19.435l-.676 15.035a1.514 1.514 0 0 1-3.026 0l-.675-15.035a2.19 2.19 0 1 1 4.377 0m-.264 19.378c.513.477.77 1.1.77 1.87s-.257 1.393-.77 1.907c-.55.476-1.21.733-1.943.733a2.545 2.545 0 0 1-1.87-.77c-.55-.514-.806-1.136-.806-1.87 0-.77.256-1.393.806-1.87.513-.513 1.137-.733 1.87-.733.77 0 1.43.22 1.943.733\",fill:\"#FFF\"},null),g(\"path\",{d:\"M119.3 133.275c4.426-.598 3.612-1.204 4.079-4.778.675-5.18-3.108-16.935-8.262-25.118-1.088-10.72-12.598-11.24-12.598-11.24s4.312 4.895 4.196 16.199c1.398 5.243.804 14.45.804 14.45s5.255 11.369 11.78 10.487\",fill:\"#FFB594\"},null),g(\"path\",{d:\"M100.944 91.61s1.463-.583 3.211.582c8.08 1.398 10.368 6.706 11.3 11.368 1.864 1.282 1.864 2.33 1.864 3.496.365.777 1.515 3.03 1.515 3.03s-7.225 1.748-10.954 6.758c-1.399-6.41-6.936-25.235-6.936-25.235\",fill:\"#FFF\"},null),g(\"path\",{d:\"M94.008 90.5l1.019-5.815-9.23-11.874-5.233 5.581-2.593 9.863s8.39 5.128 16.037 2.246\",fill:\"#FFB594\"},null),g(\"path\",{d:\"M82.931 78.216s-4.557-2.868-2.445-6.892c1.632-3.107 4.537 1.139 4.537 1.139s.524-3.662 3.139-3.662c.523-1.046 1.569-4.184 1.569-4.184s11.507 2.615 13.6 3.138c-.001 5.23-2.317 19.529-7.884 19.969-8.94.706-12.516-9.508-12.516-9.508\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M102.971 72.243c2.616-2.093 3.489-9.775 3.489-9.775s-2.492-.492-6.676-2.062c-4.708-2.092-12.867-4.771-17.575.982-9.54 4.41-2.062 19.93-2.062 19.93l2.729-3.037s-3.956-3.304-2.092-6.277c2.183-3.48 3.943 1.08 3.943 1.08s.64-2.4 3.6-3.36c.356-.714 1.04-2.69 1.44-3.872a1.08 1.08 0 0 1 1.27-.707c2.41.56 8.723 2.03 11.417 2.676.524.126.876.619.825 1.156l-.308 3.266z\",fill:\"#520038\"},null),g(\"path\",{d:\"M101.22 76.514c-.104.613-.585 1.044-1.076.96-.49-.082-.805-.646-.702-1.26.104-.613.585-1.044 1.076-.961.491.083.805.647.702 1.26M94.26 75.074c-.104.613-.585 1.044-1.076.96-.49-.082-.805-.646-.702-1.26.104-.613.585-1.044 1.076-.96.491.082.805.646.702 1.26\",fill:\"#552950\"},null),g(\"path\",{stroke:\"#DB836E\",\"stroke-width\":\"1.063\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",d:\"M99.206 73.644l-.9 1.62-.3 4.38h-2.24\"},null),g(\"path\",{d:\"M99.926 73.284s1.8-.72 2.52.54\",stroke:\"#5C2552\",\"stroke-width\":\"1.117\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M81.367 73.084s.48-1.12 1.12-.72c.64.4 1.28 1.44.56 2s.16 1.68.16 1.68\",stroke:\"#DB836E\",\"stroke-width\":\"1.117\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M92.326 71.724s1.84 1.12 4.16.96\",stroke:\"#5C2552\",\"stroke-width\":\"1.117\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M92.726 80.604s2.24 1.2 4.4 1.2M93.686 83.164s.96.4 1.52.32M83.687 80.044s1.786 6.547 9.262 7.954\",stroke:\"#DB836E\",\"stroke-width\":\"1.063\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M95.548 91.663s-1.068 2.821-8.298 2.105c-7.23-.717-10.29-5.044-10.29-5.044\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.136\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M78.126 87.478s6.526 4.972 16.47 2.486c0 0 9.577 1.02 11.536 5.322 5.36 11.77.543 36.835 0 39.962 3.496 4.055-.466 8.483-.466 8.483-15.624-3.548-35.81-.6-35.81-.6-4.849-3.546-1.223-9.044-1.223-9.044L62.38 110.32c-2.485-15.227.833-19.803 3.549-20.743 3.03-1.049 8.04-1.282 8.04-1.282.496-.058 1.08-.076 1.37-.233 2.36-1.282 2.787-.583 2.787-.583\",fill:\"#FFF\"},null),g(\"path\",{d:\"M65.828 89.81s-6.875.465-7.59 8.156c-.466 8.857 3.03 10.954 3.03 10.954s6.075 22.102 16.796 22.957c8.39-2.176 4.758-6.702 4.661-11.42-.233-11.304-7.108-16.897-7.108-16.897s-4.212-13.75-9.789-13.75\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M71.716 124.225s.855 11.264 9.828 6.486c4.765-2.536 7.581-13.828 9.789-22.568 1.456-5.768 2.58-12.197 2.58-12.197l-4.973-1.709s-2.408 5.516-7.769 12.275c-4.335 5.467-9.144 11.11-9.455 17.713\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M108.463 105.191s1.747 2.724-2.331 30.535c2.376 2.216 1.053 6.012-.233 7.51\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M123.262 131.527s-.427 2.732-11.77 1.981c-15.187-1.006-25.326-3.25-25.326-3.25l.933-5.8s.723.215 9.71-.068c11.887-.373 18.714-6.07 24.964-1.022 4.039 3.263 1.489 8.16 1.489 8.16\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M70.24 90.974s-5.593-4.739-11.054 2.68c-3.318 7.223.517 15.284 2.664 19.578-.31 3.729 2.33 4.311 2.33 4.311s.108.895 1.516 2.68c4.078-7.03 6.72-9.166 13.711-12.546-.328-.656-1.877-3.265-1.825-3.767.175-1.69-1.282-2.623-1.282-2.623s-.286-.156-1.165-2.738c-.788-2.313-2.036-5.177-4.895-7.575\",fill:\"#FFF\"},null),g(\"path\",{d:\"M90.232 288.027s4.855 2.308 8.313 1.155c3.188-1.063 5.12.755 8.002 1.331 2.881.577 7.769 1.243 13.207-1.424-.117-6.228-7.786-4.499-13.518-7.588-2.895-1.56-4.276-5.336-4.066-9.944H91.544s-1.573 11.89-1.312 16.47\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M90.207 287.833s2.745 1.437 7.639.738c3.456-.494 3.223.66 7.418 1.282 4.195.621 13.092-.194 14.334-1.126.466 1.242-.388 2.33-.388 2.33s-1.709.682-5.438.932c-2.295.154-8.098.276-10.14-.621-2.02-1.554-4.894-1.515-6.06-.234-4.427 1.075-7.184-.31-7.184-.31l-.181-2.991z\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M98.429 272.257h3.496s-.117 7.574 5.127 9.671c-5.244.7-9.672-2.602-8.623-9.671\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M44.425 272.046s-2.208 7.774-4.702 12.899c-1.884 3.874-4.428 7.854 5.729 7.854 6.97 0 9.385-.503 7.782-6.917-1.604-6.415.279-13.836.279-13.836h-9.088z\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M38.066 290.277s2.198 1.225 6.954 1.225c6.376 0 8.646-1.73 8.646-1.73s.63 1.168-.649 2.27c-1.04.897-3.77 1.668-7.745 1.621-4.347-.05-6.115-.593-7.062-1.224-.864-.577-.72-1.657-.144-2.162\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M45.344 274.041s.035 1.592-.329 3.07c-.365 1.49-1.13 3.255-1.184 4.34-.061 1.206 4.755 1.657 5.403.036.65-1.622 1.357-6.737 2.006-7.602.648-.865-5.14-2.222-5.896.156\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M89.476 277.57l13.899.095s1.349-56.643 1.925-66.909c.576-10.267 3.923-45.052 1.042-65.585l-13.037-.669-23.737.81s-.452 4.12-1.243 10.365c-.065.515-.708.874-.777 1.417-.078.608.439 1.407.332 2.044-2.455 14.627-5.797 32.736-8.256 46.837-.121.693-1.282 1.048-1.515 2.796-.042.314.22 1.584.116 1.865-7.14 19.473-12.202 52.601-15.66 67.19l15.176-.015s2.282-10.145 4.185-18.871c2.922-13.389 24.012-88.32 24.012-88.32l3.133-.954-.158 48.568s-.233 1.282.35 2.098c.583.815-.581 1.167-.408 2.331l.408 1.864s-.466 7.458-.932 12.352c-.467 4.895 1.145 40.69 1.145 40.69\",fill:\"#7BB2F9\"},null),g(\"path\",{d:\"M64.57 218.881c1.197.099 4.195-2.097 7.225-5.127M96.024 222.534s2.881-1.152 6.34-4.034\",stroke:\"#648BD8\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M96.973 219.373s2.882-1.153 6.34-4.034\",stroke:\"#648BD8\",\"stroke-width\":\"1.032\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M63.172 222.144s2.724-.614 6.759-3.496M74.903 146.166c-.281 3.226.31 8.856-4.506 9.478M93.182 144.344s.115 14.557-1.344 15.65c-2.305 1.73-3.107 2.02-3.107 2.02M89.197 144.923s.269 13.144-1.01 25.088M83.525 170.71s6.81-1.051 9.116-1.051M46.026 270.045l-.892 4.538M46.937 263.289l-.815 4.157M62.725 202.503c-.33 1.618-.102 1.904-.449 3.438 0 0-2.756 1.903-2.29 3.923.466 2.02-.31 3.424-4.505 17.252-1.762 5.807-4.233 18.922-6.165 28.278-.03.144-.521 2.646-1.14 5.8M64.158 194.136c-.295 1.658-.6 3.31-.917 4.938M71.33 146.787l-1.244 10.877s-1.14.155-.519 2.33c.117 1.399-2.778 16.39-5.382 31.615M44.242 273.727H58.07\",stroke:\"#648BD8\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M106.18 142.117c-3.028-.489-18.825-2.744-36.219.2a.625.625 0 0 0-.518.644c.063 1.307.044 2.343.015 2.995a.617.617 0 0 0 .716.636c3.303-.534 17.037-2.412 35.664-.266.347.04.66-.214.692-.56.124-1.347.16-2.425.17-3.029a.616.616 0 0 0-.52-.62\",fill:\"#192064\"},null),g(\"path\",{d:\"M96.398 145.264l.003-5.102a.843.843 0 0 0-.809-.847 114.104 114.104 0 0 0-8.141-.014.85.85 0 0 0-.82.847l-.003 5.097c0 .476.388.857.864.845 2.478-.064 5.166-.067 8.03.017a.848.848 0 0 0 .876-.843\",fill:\"#FFF\"},null),g(\"path\",{d:\"M95.239 144.296l.002-3.195a.667.667 0 0 0-.643-.672c-1.9-.061-3.941-.073-6.094-.01a.675.675 0 0 0-.654.672l-.002 3.192c0 .376.305.677.68.669 1.859-.042 3.874-.043 6.02.012.376.01.69-.291.691-.668\",fill:\"#192064\"},null),g(\"path\",{d:\"M90.102 273.522h12.819M91.216 269.761c.006 3.519-.072 5.55 0 6.292M90.923 263.474c-.009 1.599-.016 2.558-.016 4.505M90.44 170.404l.932 46.38s.7 1.631-.233 2.796c-.932 1.166 2.564.7.932 2.33-1.63 1.633.933 1.166 0 3.497-.618 1.546-1.031 21.921-1.138 36.513\",stroke:\"#648BD8\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M73.736 98.665l2.214 4.312s2.098.816 1.865 2.68l.816 2.214M64.297 116.611c.233-.932 2.176-7.147 12.585-10.488M77.598 90.042s7.691 6.137 16.547 2.72\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M91.974 86.954s5.476-.816 7.574-4.545c1.297-.345.72 2.212-.33 3.671-.7.971-1.01 1.554-1.01 1.554s.194.31.155.816c-.053.697-.175.653-.272 1.048-.081.335.108.657 0 1.049-.046.17-.198.5-.382.878-.12.249-.072.687-.2.948-.231.469-1.562 1.87-2.622 2.855-3.826 3.554-5.018 1.644-6.001-.408-.894-1.865-.661-5.127-.874-6.875-.35-2.914-2.622-3.03-1.923-4.429.343-.685 2.87.69 3.263 1.748.757 2.04 2.952 1.807 2.622 1.69\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M99.8 82.429c-.465.077-.35.272-.97 1.243-.622.971-4.817 2.932-6.39 3.224-2.589.48-2.278-1.56-4.254-2.855-1.69-1.107-3.562-.638-1.398 1.398.99.932.932 1.107 1.398 3.205.335 1.506-.64 3.67.7 5.593\",stroke:\"#DB836E\",\"stroke-width\":\".774\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M79.543 108.673c-2.1 2.926-4.266 6.175-5.557 8.762\",stroke:\"#E59788\",\"stroke-width\":\".774\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M87.72 124.768s-2.098-1.942-5.127-2.719c-3.03-.777-3.574-.155-5.516.078-1.942.233-3.885-.932-3.652.7.233 1.63 5.05 1.01 5.206 2.097.155 1.087-6.37 2.796-8.313 2.175-.777.777.466 1.864 2.02 2.175.233 1.554 2.253 1.554 2.253 1.554s.699 1.01 2.641 1.088c2.486 1.32 8.934-.7 10.954-1.554 2.02-.855-.466-5.594-.466-5.594\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M73.425 122.826s.66 1.127 3.167 1.418c2.315.27 2.563.583 2.563.583s-2.545 2.894-9.07 2.272M72.416 129.274s3.826.097 4.933-.718M74.98 130.75s1.961.136 3.36-.505M77.232 131.916s1.748.019 2.914-.505M73.328 122.321s-.595-1.032 1.262-.427c1.671.544 2.833.055 5.128.155 1.389.061 3.067-.297 3.982.15 1.606.784 3.632 2.181 3.632 2.181s10.526 1.204 19.033-1.127M78.864 108.104s-8.39 2.758-13.168 12.12\",stroke:\"#E59788\",\"stroke-width\":\".774\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M109.278 112.533s3.38-3.613 7.575-4.662\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.085\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M107.375 123.006s9.697-2.745 11.445-.88\",stroke:\"#E59788\",\"stroke-width\":\".774\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M194.605 83.656l3.971-3.886M187.166 90.933l3.736-3.655M191.752 84.207l-4.462-4.56M198.453 91.057l-4.133-4.225M129.256 163.074l3.718-3.718M122.291 170.039l3.498-3.498M126.561 163.626l-4.27-4.27M132.975 170.039l-3.955-3.955\",stroke:\"#BFCDDD\",\"stroke-width\":\"2\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M190.156 211.779h-1.604a4.023 4.023 0 0 1-4.011-4.011V175.68a4.023 4.023 0 0 1 4.01-4.01h1.605a4.023 4.023 0 0 1 4.011 4.01v32.088a4.023 4.023 0 0 1-4.01 4.01\",fill:\"#A3B4C6\"},null),g(\"path\",{d:\"M237.824 212.977a4.813 4.813 0 0 1-4.813 4.813h-86.636a4.813 4.813 0 0 1 0-9.626h86.636a4.813 4.813 0 0 1 4.813 4.813\",fill:\"#A3B4C6\"},null),g(\"mask\",{fill:\"#fff\"},null),g(\"path\",{fill:\"#A3B4C6\",mask:\"url(#d)\",d:\"M154.098 190.096h70.513v-84.617h-70.513z\"},null),g(\"path\",{d:\"M224.928 190.096H153.78a3.219 3.219 0 0 1-3.208-3.209V167.92a3.219 3.219 0 0 1 3.208-3.21h71.148a3.219 3.219 0 0 1 3.209 3.21v18.967a3.219 3.219 0 0 1-3.21 3.209M224.928 130.832H153.78a3.218 3.218 0 0 1-3.208-3.208v-18.968a3.219 3.219 0 0 1 3.208-3.209h71.148a3.219 3.219 0 0 1 3.209 3.21v18.967a3.218 3.218 0 0 1-3.21 3.208\",fill:\"#BFCDDD\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M159.563 120.546a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M166.98 120.546a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M174.397 120.546a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M222.539 120.546h-22.461a.802.802 0 0 1-.802-.802v-3.208c0-.443.359-.803.802-.803h22.46c.444 0 .803.36.803.803v3.208c0 .443-.36.802-.802.802\",fill:\"#FFF\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M224.928 160.464H153.78a3.218 3.218 0 0 1-3.208-3.209v-18.967a3.219 3.219 0 0 1 3.208-3.209h71.148a3.219 3.219 0 0 1 3.209 3.209v18.967a3.218 3.218 0 0 1-3.21 3.209\",fill:\"#BFCDDD\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M173.455 130.832h49.301M164.984 130.832h6.089M155.952 130.832h6.75M173.837 160.613h49.3M165.365 160.613h6.089M155.57 160.613h6.751\",stroke:\"#7C90A5\",\"stroke-width\":\"1.124\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M159.563 151.038a2.407 2.407 0 1 1 0-4.814 2.407 2.407 0 0 1 0 4.814M166.98 151.038a2.407 2.407 0 1 1 0-4.814 2.407 2.407 0 0 1 0 4.814M174.397 151.038a2.407 2.407 0 1 1 .001-4.814 2.407 2.407 0 0 1 0 4.814M222.539 151.038h-22.461a.802.802 0 0 1-.802-.802v-3.209c0-.443.359-.802.802-.802h22.46c.444 0 .803.36.803.802v3.209c0 .443-.36.802-.802.802M159.563 179.987a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M166.98 179.987a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M174.397 179.987a2.407 2.407 0 1 1 0-4.813 2.407 2.407 0 0 1 0 4.813M222.539 179.987h-22.461a.802.802 0 0 1-.802-.802v-3.209c0-.443.359-.802.802-.802h22.46c.444 0 .803.36.803.802v3.209c0 .443-.36.802-.802.802\",fill:\"#FFF\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M203.04 221.108h-27.372a2.413 2.413 0 0 1-2.406-2.407v-11.448a2.414 2.414 0 0 1 2.406-2.407h27.372a2.414 2.414 0 0 1 2.407 2.407V218.7a2.413 2.413 0 0 1-2.407 2.407\",fill:\"#BFCDDD\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M177.259 207.217v11.52M201.05 207.217v11.52\",stroke:\"#A3B4C6\",\"stroke-width\":\"1.124\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M162.873 267.894a9.422 9.422 0 0 1-9.422-9.422v-14.82a9.423 9.423 0 0 1 18.845 0v14.82a9.423 9.423 0 0 1-9.423 9.422\",fill:\"#5BA02E\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M171.22 267.83a9.422 9.422 0 0 1-9.422-9.423v-3.438a9.423 9.423 0 0 1 18.845 0v3.438a9.423 9.423 0 0 1-9.422 9.423\",fill:\"#92C110\",mask:\"url(#d)\"},null),g(\"path\",{d:\"M181.31 293.666h-27.712a3.209 3.209 0 0 1-3.209-3.21V269.79a3.209 3.209 0 0 1 3.209-3.21h27.711a3.209 3.209 0 0 1 3.209 3.21v20.668a3.209 3.209 0 0 1-3.209 3.209\",fill:\"#F2D7AD\",mask:\"url(#d)\"},null)])])},v5e=p5e,m5e=function(){return g(\"svg\",{width:\"251\",height:\"294\"},[g(\"g\",{fill:\"none\",\"fill-rule\":\"evenodd\"},[g(\"path\",{d:\"M0 129.023v-2.084C0 58.364 55.591 2.774 124.165 2.774h2.085c68.574 0 124.165 55.59 124.165 124.165v2.084c0 68.575-55.59 124.166-124.165 124.166h-2.085C55.591 253.189 0 197.598 0 129.023\",fill:\"#E4EBF7\"},null),g(\"path\",{d:\"M41.417 132.92a8.231 8.231 0 1 1-16.38-1.65 8.231 8.231 0 0 1 16.38 1.65\",fill:\"#FFF\"},null),g(\"path\",{d:\"M38.652 136.36l10.425 5.91M49.989 148.505l-12.58 10.73\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{d:\"M41.536 161.28a5.636 5.636 0 1 1-11.216-1.13 5.636 5.636 0 0 1 11.216 1.13M59.154 145.261a5.677 5.677 0 1 1-11.297-1.138 5.677 5.677 0 0 1 11.297 1.138M100.36 29.516l29.66-.013a4.562 4.562 0 1 0-.004-9.126l-29.66.013a4.563 4.563 0 0 0 .005 9.126M111.705 47.754l29.659-.013a4.563 4.563 0 1 0-.004-9.126l-29.66.013a4.563 4.563 0 1 0 .005 9.126\",fill:\"#FFF\"},null),g(\"path\",{d:\"M114.066 29.503V29.5l15.698-.007a4.563 4.563 0 1 0 .004 9.126l-15.698.007v-.002a4.562 4.562 0 0 0-.004-9.122M185.405 137.723c-.55 5.455-5.418 9.432-10.873 8.882-5.456-.55-9.432-5.418-8.882-10.873.55-5.455 5.418-9.432 10.873-8.882 5.455.55 9.432 5.418 8.882 10.873\",fill:\"#FFF\"},null),g(\"path\",{d:\"M180.17 143.772l12.572 7.129M193.841 158.42L178.67 171.36\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{d:\"M185.55 171.926a6.798 6.798 0 1 1-13.528-1.363 6.798 6.798 0 0 1 13.527 1.363M204.12 155.285a6.848 6.848 0 1 1-13.627-1.375 6.848 6.848 0 0 1 13.626 1.375\",fill:\"#FFF\"},null),g(\"path\",{d:\"M152.988 194.074a2.21 2.21 0 1 1-4.42 0 2.21 2.21 0 0 1 4.42 0zM225.931 118.217a2.21 2.21 0 1 1-4.421 0 2.21 2.21 0 0 1 4.421 0zM217.09 153.051a2.21 2.21 0 1 1-4.421 0 2.21 2.21 0 0 1 4.42 0zM177.84 109.842a2.21 2.21 0 1 1-4.422 0 2.21 2.21 0 0 1 4.421 0zM196.114 94.454a2.21 2.21 0 1 1-4.421 0 2.21 2.21 0 0 1 4.421 0zM202.844 182.523a2.21 2.21 0 1 1-4.42 0 2.21 2.21 0 0 1 4.42 0z\",stroke:\"#FFF\",\"stroke-width\":\"2\"},null),g(\"path\",{stroke:\"#FFF\",\"stroke-width\":\"2\",d:\"M215.125 155.262l-1.902 20.075-10.87 5.958M174.601 176.636l-6.322 9.761H156.98l-4.484 6.449M175.874 127.28V111.56M221.51 119.404l-12.77 7.859-15.228-7.86V96.668\"},null),g(\"path\",{d:\"M180.68 29.32C180.68 13.128 193.806 0 210 0c16.193 0 29.32 13.127 29.32 29.32 0 16.194-13.127 29.322-29.32 29.322-16.193 0-29.32-13.128-29.32-29.321\",fill:\"#A26EF4\"},null),g(\"path\",{d:\"M221.45 41.706l-21.563-.125a1.744 1.744 0 0 1-1.734-1.754l.071-12.23a1.744 1.744 0 0 1 1.754-1.734l21.562.125c.964.006 1.74.791 1.735 1.755l-.071 12.229a1.744 1.744 0 0 1-1.754 1.734\",fill:\"#FFF\"},null),g(\"path\",{d:\"M215.106 29.192c-.015 2.577-2.049 4.654-4.543 4.64-2.494-.014-4.504-2.115-4.489-4.693l.04-6.925c.016-2.577 2.05-4.654 4.543-4.64 2.494.015 4.504 2.116 4.49 4.693l-.04 6.925zm-4.53-14.074a6.877 6.877 0 0 0-6.916 6.837l-.043 7.368a6.877 6.877 0 0 0 13.754.08l.042-7.368a6.878 6.878 0 0 0-6.837-6.917zM167.566 68.367h-3.93a4.73 4.73 0 0 1-4.717-4.717 4.73 4.73 0 0 1 4.717-4.717h3.93a4.73 4.73 0 0 1 4.717 4.717 4.73 4.73 0 0 1-4.717 4.717\",fill:\"#FFF\"},null),g(\"path\",{d:\"M168.214 248.838a6.611 6.611 0 0 1-6.61-6.611v-66.108a6.611 6.611 0 0 1 13.221 0v66.108a6.611 6.611 0 0 1-6.61 6.61\",fill:\"#5BA02E\"},null),g(\"path\",{d:\"M176.147 248.176a6.611 6.611 0 0 1-6.61-6.61v-33.054a6.611 6.611 0 1 1 13.221 0v33.053a6.611 6.611 0 0 1-6.61 6.611\",fill:\"#92C110\"},null),g(\"path\",{d:\"M185.994 293.89h-27.376a3.17 3.17 0 0 1-3.17-3.17v-45.887a3.17 3.17 0 0 1 3.17-3.17h27.376a3.17 3.17 0 0 1 3.17 3.17v45.886a3.17 3.17 0 0 1-3.17 3.17\",fill:\"#F2D7AD\"},null),g(\"path\",{d:\"M81.972 147.673s6.377-.927 17.566-1.28c11.729-.371 17.57 1.086 17.57 1.086s3.697-3.855.968-8.424c1.278-12.077 5.982-32.827.335-48.273-1.116-1.339-3.743-1.512-7.536-.62-1.337.315-7.147-.149-7.983-.1l-15.311-.347s-3.487-.17-8.035-.508c-1.512-.113-4.227-1.683-5.458-.338-.406.443-2.425 5.669-1.97 16.077l8.635 35.642s-3.141 3.61 1.219 7.085\",fill:\"#FFF\"},null),g(\"path\",{d:\"M75.768 73.325l-.9-6.397 11.982-6.52s7.302-.118 8.038 1.205c.737 1.324-5.616.993-5.616.993s-1.836 1.388-2.615 2.5c-1.654 2.363-.986 6.471-8.318 5.986-1.708.284-2.57 2.233-2.57 2.233\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M52.44 77.672s14.217 9.406 24.973 14.444c1.061.497-2.094 16.183-11.892 11.811-7.436-3.318-20.162-8.44-21.482-14.496-.71-3.258 2.543-7.643 8.401-11.76M141.862 80.113s-6.693 2.999-13.844 6.876c-3.894 2.11-10.137 4.704-12.33 7.988-6.224 9.314 3.536 11.22 12.947 7.503 6.71-2.651 28.999-12.127 13.227-22.367\",fill:\"#FFB594\"},null),g(\"path\",{d:\"M76.166 66.36l3.06 3.881s-2.783 2.67-6.31 5.747c-7.103 6.195-12.803 14.296-15.995 16.44-3.966 2.662-9.754 3.314-12.177-.118-3.553-5.032.464-14.628 31.422-25.95\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M64.674 85.116s-2.34 8.413-8.912 14.447c.652.548 18.586 10.51 22.144 10.056 5.238-.669 6.417-18.968 1.145-20.531-.702-.208-5.901-1.286-8.853-2.167-.87-.26-1.611-1.71-3.545-.936l-1.98-.869zM128.362 85.826s5.318 1.956 7.325 13.734c-.546.274-17.55 12.35-21.829 7.805-6.534-6.94-.766-17.393 4.275-18.61 4.646-1.121 5.03-1.37 10.23-2.929\",fill:\"#FFF\"},null),g(\"path\",{d:\"M78.18 94.656s.911 7.41-4.914 13.078\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M87.397 94.68s3.124 2.572 10.263 2.572c7.14 0 9.074-3.437 9.074-3.437\",stroke:\"#E4EBF7\",\"stroke-width\":\".932\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M117.184 68.639l-6.781-6.177s-5.355-4.314-9.223-.893c-3.867 3.422 4.463 2.083 5.653 4.165 1.19 2.082.848 1.143-2.083.446-5.603-1.331-2.082.893 2.975 5.355 2.091 1.845 6.992.955 6.992.955l2.467-3.851z\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M105.282 91.315l-.297-10.937-15.918-.027-.53 10.45c-.026.403.17.788.515.999 2.049 1.251 9.387 5.093 15.799.424.287-.21.443-.554.431-.91\",fill:\"#FFB594\"},null),g(\"path\",{d:\"M107.573 74.24c.817-1.147.982-9.118 1.015-11.928a1.046 1.046 0 0 0-.965-1.055l-4.62-.365c-7.71-1.044-17.071.624-18.253 6.346-5.482 5.813-.421 13.244-.421 13.244s1.963 3.566 4.305 6.791c.756 1.041.398-3.731 3.04-5.929 5.524-4.594 15.899-7.103 15.899-7.103\",fill:\"#5C2552\"},null),g(\"path\",{d:\"M88.426 83.206s2.685 6.202 11.602 6.522c7.82.28 8.973-7.008 7.434-17.505l-.909-5.483c-6.118-2.897-15.478.54-15.478.54s-.576 2.044-.19 5.504c-2.276 2.066-1.824 5.618-1.824 5.618s-.905-1.922-1.98-2.321c-.86-.32-1.897.089-2.322 1.98-1.04 4.632 3.667 5.145 3.667 5.145\",fill:\"#FFC6A0\"},null),g(\"path\",{stroke:\"#DB836E\",\"stroke-width\":\"1.145\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",d:\"M100.843 77.099l1.701-.928-1.015-4.324.674-1.406\"},null),g(\"path\",{d:\"M105.546 74.092c-.022.713-.452 1.279-.96 1.263-.51-.016-.904-.607-.882-1.32.021-.713.452-1.278.96-1.263.51.016.904.607.882 1.32M97.592 74.349c-.022.713-.452 1.278-.961 1.263-.509-.016-.904-.607-.882-1.32.022-.713.452-1.279.961-1.263.51.016.904.606.882 1.32\",fill:\"#552950\"},null),g(\"path\",{d:\"M91.132 86.786s5.269 4.957 12.679 2.327\",stroke:\"#DB836E\",\"stroke-width\":\"1.145\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M99.776 81.903s-3.592.232-1.44-2.79c1.59-1.496 4.897-.46 4.897-.46s1.156 3.906-3.457 3.25\",fill:\"#DB836E\"},null),g(\"path\",{d:\"M102.88 70.6s2.483.84 3.402.715M93.883 71.975s2.492-1.144 4.778-1.073\",stroke:\"#5C2552\",\"stroke-width\":\"1.526\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M86.32 77.374s.961.879 1.458 2.106c-.377.48-1.033 1.152-.236 1.809M99.337 83.719s1.911.151 2.509-.254\",stroke:\"#DB836E\",\"stroke-width\":\"1.145\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M87.782 115.821l15.73-3.012M100.165 115.821l10.04-2.008\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M66.508 86.763s-1.598 8.83-6.697 14.078\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.114\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M128.31 87.934s3.013 4.121 4.06 11.785\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M64.09 84.816s-6.03 9.912-13.607 9.903\",stroke:\"#DB836E\",\"stroke-width\":\".795\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M112.366 65.909l-.142 5.32s5.993 4.472 11.945 9.202c4.482 3.562 8.888 7.455 10.985 8.662 4.804 2.766 8.9 3.355 11.076 1.808 4.071-2.894 4.373-9.878-8.136-15.263-4.271-1.838-16.144-6.36-25.728-9.73\",fill:\"#FFC6A0\"},null),g(\"path\",{d:\"M130.532 85.488s4.588 5.757 11.619 6.214\",stroke:\"#DB836E\",\"stroke-width\":\".75\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M121.708 105.73s-.393 8.564-1.34 13.612\",stroke:\"#E4EBF7\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M115.784 161.512s-3.57-1.488-2.678-7.14\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M101.52 290.246s4.326 2.057 7.408 1.03c2.842-.948 4.564.673 7.132 1.186 2.57.514 6.925 1.108 11.772-1.269-.104-5.551-6.939-4.01-12.048-6.763-2.582-1.39-3.812-4.757-3.625-8.863h-9.471s-1.402 10.596-1.169 14.68\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M101.496 290.073s2.447 1.281 6.809.658c3.081-.44 3.74.485 7.479 1.039 3.739.554 10.802-.07 11.91-.9.415 1.108-.347 2.077-.347 2.077s-1.523.608-4.847.831c-2.045.137-5.843.293-7.663-.507-1.8-1.385-5.286-1.917-5.77-.243-3.947.958-7.41-.288-7.41-.288l-.16-2.667z\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M108.824 276.19h3.116s-.103 6.751 4.57 8.62c-4.673.624-8.62-2.32-7.686-8.62\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M57.65 272.52s-2.122 7.47-4.518 12.396c-1.811 3.724-4.255 7.548 5.505 7.548 6.698 0 9.02-.483 7.479-6.648-1.541-6.164.268-13.296.268-13.296H57.65z\",fill:\"#CBD1D1\"},null),g(\"path\",{d:\"M51.54 290.04s2.111 1.178 6.682 1.178c6.128 0 8.31-1.662 8.31-1.662s.605 1.122-.624 2.18c-1 .862-3.624 1.603-7.444 1.559-4.177-.049-5.876-.57-6.786-1.177-.831-.554-.692-1.593-.138-2.078\",fill:\"#2B0849\"},null),g(\"path\",{d:\"M58.533 274.438s.034 1.529-.315 2.95c-.352 1.431-1.087 3.127-1.139 4.17-.058 1.16 4.57 1.592 5.194.035.623-1.559 1.303-6.475 1.927-7.306.622-.831-4.94-2.135-5.667.15\",fill:\"#A4AABA\"},null),g(\"path\",{d:\"M100.885 277.015l13.306.092s1.291-54.228 1.843-64.056c.552-9.828 3.756-43.13.997-62.788l-12.48-.64-22.725.776s-.433 3.944-1.19 9.921c-.062.493-.677.838-.744 1.358-.075.582.42 1.347.318 1.956-2.35 14.003-6.343 32.926-8.697 46.425-.116.663-1.227 1.004-1.45 2.677-.04.3.21 1.516.112 1.785-6.836 18.643-10.89 47.584-14.2 61.551l14.528-.014s2.185-8.524 4.008-16.878c2.796-12.817 22.987-84.553 22.987-84.553l3-.517 1.037 46.1s-.223 1.228.334 2.008c.558.782-.556 1.117-.39 2.233l.39 1.784s-.446 7.14-.892 11.826c-.446 4.685-.092 38.954-.092 38.954\",fill:\"#7BB2F9\"},null),g(\"path\",{d:\"M77.438 220.434c1.146.094 4.016-2.008 6.916-4.91M107.55 223.931s2.758-1.103 6.069-3.862\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M108.459 220.905s2.759-1.104 6.07-3.863\",stroke:\"#648BD8\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M76.099 223.557s2.608-.587 6.47-3.346M87.33 150.82c-.27 3.088.297 8.478-4.315 9.073M104.829 149.075s.11 13.936-1.286 14.983c-2.207 1.655-2.975 1.934-2.975 1.934M101.014 149.63s.035 12.81-1.19 24.245M94.93 174.965s7.174-1.655 9.38-1.655M75.671 204.754c-.316 1.55-.64 3.067-.973 4.535 0 0-1.45 1.822-1.003 3.756.446 1.934-.943 2.034-4.96 15.273-1.686 5.559-4.464 18.49-6.313 27.447-.078.38-4.018 18.06-4.093 18.423M77.043 196.743a313.269 313.269 0 0 1-.877 4.729M83.908 151.414l-1.19 10.413s-1.091.148-.496 2.23c.111 1.34-2.66 15.692-5.153 30.267M57.58 272.94h13.238\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null),g(\"path\",{d:\"M117.377 147.423s-16.955-3.087-35.7.199c.157 2.501-.002 4.128-.002 4.128s14.607-2.802 35.476-.31c.251-2.342.226-4.017.226-4.017\",fill:\"#192064\"},null),g(\"path\",{d:\"M107.511 150.353l.004-4.885a.807.807 0 0 0-.774-.81c-2.428-.092-5.04-.108-7.795-.014a.814.814 0 0 0-.784.81l-.003 4.88c0 .456.371.82.827.808a140.76 140.76 0 0 1 7.688.017.81.81 0 0 0 .837-.806\",fill:\"#FFF\"},null),g(\"path\",{d:\"M106.402 149.426l.002-3.06a.64.64 0 0 0-.616-.643 94.135 94.135 0 0 0-5.834-.009.647.647 0 0 0-.626.643l-.001 3.056c0 .36.291.648.651.64 1.78-.04 3.708-.041 5.762.012.36.009.662-.279.662-.64\",fill:\"#192064\"},null),g(\"path\",{d:\"M101.485 273.933h12.272M102.652 269.075c.006 3.368.04 5.759.11 6.47M102.667 263.125c-.009 1.53-.015 2.98-.016 4.313M102.204 174.024l.893 44.402s.669 1.561-.224 2.677c-.892 1.116 2.455.67.893 2.231-1.562 1.562.893 1.116 0 3.347-.592 1.48-.988 20.987-1.09 34.956\",stroke:\"#648BD8\",\"stroke-width\":\"1.051\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\"},null)])])},g5e=m5e,y5e={success:zf,error:Yr,info:Hf,warning:d5e},Kf={\"404\":h5e,\"500\":v5e,\"403\":g5e},b5e=Object.keys(Kf),C5e={prefixCls:u.string,icon:u.any,status:u.oneOf(rt(\"success\",\"error\",\"info\",\"warning\",\"404\",\"403\",\"500\")).def(\"info\"),title:u.any,subTitle:u.any,extra:u.any},w5e=function(t,n){var r=n.status,a=n.icon;if(b5e.includes(\"\".concat(r))){var o=Kf[r];return g(\"div\",{class:\"\".concat(t,\"-icon \").concat(t,\"-image\")},[g(o,null,null)])}var i=y5e[r],l=a||g(i,null,null);return g(\"div\",{class:\"\".concat(t,\"-icon\")},[l])},S5e=function(t,n){return n&&g(\"div\",{class:\"\".concat(t,\"-extra\")},[n])},ds=G({name:\"AResult\",props:C5e,slots:[\"title\",\"subTitle\",\"icon\",\"extra\"],setup:function(t,n){var r=n.slots,a=Wt(\"result\",t),o=a.prefixCls,i=a.direction,l=x(function(){return Se(o.value,\"\".concat(o.value,\"-\").concat(t.status),V({},\"\".concat(o.value,\"-rtl\"),i.value===\"rtl\"))});return function(){var s,c,d,f,p,v,m,y,b=(s=t.title)!==null&&s!==void 0?s:(c=r.title)===null||c===void 0?void 0:c.call(r),C=(d=t.subTitle)!==null&&d!==void 0?d:(f=r.subTitle)===null||f===void 0?void 0:f.call(r),S=(p=t.icon)!==null&&p!==void 0?p:(v=r.icon)===null||v===void 0?void 0:v.call(r),w=(m=t.extra)!==null&&m!==void 0?m:(y=r.extra)===null||y===void 0?void 0:y.call(r),k=o.value;return g(\"div\",{class:l.value},[w5e(k,{status:t.status,icon:S}),g(\"div\",{class:\"\".concat(k,\"-title\")},[b]),C&&g(\"div\",{class:\"\".concat(k,\"-subtitle\")},[C]),S5e(k,w),r.default&&g(\"div\",{class:\"\".concat(k,\"-content\")},[r.default()])])}}});ds.PRESENTED_IMAGE_403=Kf[403];ds.PRESENTED_IMAGE_404=Kf[404];ds.PRESENTED_IMAGE_500=Kf[500];ds.install=function(e){return e.component(ds.name,ds),e};var k5e=ds,$5e=G({name:\"ASkeletonButton\",props:P(P({},Ng()),{size:u.oneOf(rt(\"large\",\"small\",\"default\"))}),setup:function(t){var n=Wt(\"skeleton\",t),r=n.prefixCls,a=x(function(){return Se(r.value,\"\".concat(r.value,\"-element\"),V({},\"\".concat(r.value,\"-active\"),t.active))});return function(){return g(\"div\",{class:a.value},[g(Ag,le(le({},t),{},{prefixCls:\"\".concat(r.value,\"-button\")}),null)])}}}),NS=$5e,O5e=G({name:\"ASkeletonInput\",props:P(P({},bn(Ng(),\"shape\")),{size:u.oneOf(rt(\"large\",\"small\",\"default\"))}),setup:function(t){var n=Wt(\"skeleton\",t),r=n.prefixCls,a=x(function(){return Se(r.value,\"\".concat(r.value,\"-element\"),V({},\"\".concat(r.value,\"-active\"),t.active))});return function(){return g(\"div\",{class:a.value},[g(Ag,le(le({},t),{},{prefixCls:\"\".concat(r.value,\"-input\")}),null)])}}}),AS=O5e,P5e=\"M365.714286 329.142857q0 45.714286-32.036571 77.677714t-77.677714 32.036571-77.677714-32.036571-32.036571-77.677714 32.036571-77.677714 77.677714-32.036571 77.677714 32.036571 32.036571 77.677714zM950.857143 548.571429l0 256-804.571429 0 0-109.714286 182.857143-182.857143 91.428571 91.428571 292.571429-292.571429zM1005.714286 146.285714l-914.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 694.857143q0 7.460571 5.412571 12.873143t12.873143 5.412571l914.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143l0-694.857143q0-7.460571-5.412571-12.873143t-12.873143-5.412571zM1097.142857 164.571429l0 694.857143q0 37.741714-26.843429 64.585143t-64.585143 26.843429l-914.285714 0q-37.741714 0-64.585143-26.843429t-26.843429-64.585143l0-694.857143q0-37.741714 26.843429-64.585143t64.585143-26.843429l914.285714 0q37.741714 0 64.585143 26.843429t26.843429 64.585143z\",T5e=G({name:\"ASkeletonImage\",props:Ng(),setup:function(t){var n=Wt(\"skeleton\",t),r=n.prefixCls,a=x(function(){return Se(r.value,\"\".concat(r.value,\"-element\"))});return function(){return g(\"div\",{class:a.value},[g(\"div\",{class:\"\".concat(r.value,\"-image\")},[g(\"svg\",{viewBox:\"0 0 1098 1024\",xmlns:\"http://www.w3.org/2000/svg\",class:\"\".concat(r.value,\"-image-svg\")},[g(\"path\",{d:P5e,class:\"\".concat(r.value,\"-image-path\")},null)])])])}}}),DS=T5e;na.Button=NS;na.Avatar=xS;na.Input=AS;na.Image=DS;na.install=function(e){return e.component(na.name,na),e.component(na.Button.name,NS),e.component(na.Avatar.name,xS),e.component(na.Input.name,AS),e.component(na.Image.name,DS),e};var fR=function(t,n){var r,a,o=n.attrs,i=o.included,l=o.vertical,s=o.offset,c=o.length,d=o.reverse,f=o.style,p=o.class,v=l?(r={},V(r,d?\"top\":\"bottom\",\"\".concat(s,\"%\")),V(r,d?\"bottom\":\"top\",\"auto\"),V(r,\"height\",\"\".concat(c,\"%\")),r):(a={},V(a,d?\"right\":\"left\",\"\".concat(s,\"%\")),V(a,d?\"left\":\"right\",\"auto\"),V(a,\"width\",\"\".concat(c,\"%\")),a),m=P(P({},f),v);return i?g(\"div\",{class:p,style:m},null):null};fR.inheritAttrs=!1;var hR=fR,x5e=function(t,n,r,a,o,i){on(r?a>0:!0,\"Slider\",\"`Slider[step]` should be a positive number in order to make Slider[dots] work.\");var l=Object.keys(n).map(parseFloat).sort(function(c,d){return c-d});if(r&&a)for(var s=o;s<=i;s+=a)l.indexOf(s)===-1&&l.push(s);return l},pR=function(t,n){var r=n.attrs,a=r.prefixCls,o=r.vertical,i=r.reverse,l=r.marks,s=r.dots,c=r.step,d=r.included,f=r.lowerBound,p=r.upperBound,v=r.max,m=r.min,y=r.dotStyle,b=r.activeDotStyle,C=v-m,S=x5e(o,l,s,c,m,v).map(function(w){var k,$=\"\".concat(Math.abs(w-m)/C*100,\"%\"),O=!d&&w===p||d&&w<=p&&w>=f,T=o?P(P({},y),V({},i?\"top\":\"bottom\",$)):P(P({},y),V({},i?\"right\":\"left\",$));O&&(T=P(P({},T),b));var _=Se((k={},V(k,\"\".concat(a,\"-dot\"),!0),V(k,\"\".concat(a,\"-dot-active\"),O),V(k,\"\".concat(a,\"-dot-reverse\"),i),k));return g(\"span\",{class:_,style:T,key:w},null)});return g(\"div\",{class:\"\".concat(a,\"-step\")},[S])};pR.inheritAttrs=!1;var _5e=pR,vR=function(t,n){var r=n.attrs,a=r.class,o=r.vertical,i=r.reverse,l=r.marks,s=r.included,c=r.upperBound,d=r.lowerBound,f=r.max,p=r.min,v=r.onClickLabel,m=Object.keys(l),y=f-p,b=m.map(parseFloat).sort(function(C,S){return C-S}).map(function(C){var S,w=typeof l[C]==\"function\"?l[C](h):l[C],k=kt(w)===\"object\"&&!zn(w),$=k?w.label:w;if(!$&&$!==0)return null;var O=!s&&C===c||s&&C<=c&&C>=d,T=Se((S={},V(S,\"\".concat(a,\"-text\"),!0),V(S,\"\".concat(a,\"-text-active\"),O),S)),_=V({marginBottom:\"-50%\"},i?\"top\":\"bottom\",\"\".concat((C-p)/y*100,\"%\")),I=V({transform:\"translateX(-50%)\",msTransform:\"translateX(-50%)\"},i?\"right\":\"left\",i?\"\".concat((C-p/4)/y*100,\"%\"):\"\".concat((C-p)/y*100,\"%\")),L=o?_:I,j=k?P(P({},L),w.style):L,F=V({},mn?\"onTouchstartPassive\":\"onTouchstart\",function(N){return v(N,C)});return g(\"span\",le({class:T,style:j,key:C,onMousedown:function(D){return v(D,C)}},F),[$])});return g(\"div\",{class:a},[b])};vR.inheritAttrs=!1;var E5e=vR,mR=G({name:\"Handle\",mixins:[nt],inheritAttrs:!1,props:{prefixCls:u.string,vertical:u.looseBool,offset:u.number,disabled:u.looseBool,min:u.number,max:u.number,value:u.number,tabindex:u.oneOfType([u.number,u.string]),reverse:u.looseBool},data:function(){return{clickFocused:!1}},mounted:function(){this.onMouseUpListener=Kn(document,\"mouseup\",this.handleMouseUp)},beforeUnmount:function(){this.onMouseUpListener&&this.onMouseUpListener.remove()},methods:{setHandleRef:function(t){this.handle=t},setClickFocus:function(t){this.setState({clickFocused:t})},handleMouseUp:function(){document.activeElement===this.handle&&this.setClickFocus(!0)},handleBlur:function(t){this.setClickFocus(!1),this.__emit(\"blur\",t)},handleKeyDown:function(){this.setClickFocus(!1)},clickFocus:function(){this.setClickFocus(!0),this.focus()},focus:function(){this.handle.focus()},blur:function(){this.handle.blur()},handleMousedown:function(t){this.focus(),this.__emit(\"mousedown\",t)}},render:function(){var t,n,r=Qe(this),a=r.prefixCls,o=r.vertical,i=r.reverse,l=r.offset,s=r.disabled,c=r.min,d=r.max,f=r.value,p=r.tabindex,v=Se(this.$attrs.class,V({},\"\".concat(a,\"-handle-click-focused\"),this.clickFocused)),m=o?(t={},V(t,i?\"top\":\"bottom\",\"\".concat(l,\"%\")),V(t,i?\"bottom\":\"top\",\"auto\"),V(t,\"transform\",\"translateY(+50%)\"),t):(n={},V(n,i?\"right\":\"left\",\"\".concat(l,\"%\")),V(n,i?\"left\":\"right\",\"auto\"),V(n,\"transform\",\"translateX(\".concat(i?\"+\":\"-\",\"50%)\")),n),y={\"aria-valuemin\":c,\"aria-valuemax\":d,\"aria-valuenow\":f,\"aria-disabled\":!!s},b=P(P({},this.$attrs.style),m),C=p||0;(s||p===null)&&(C=null);var S=P(P(P(P({},this.$attrs),{role:\"slider\",tabindex:C}),y),{class:v,onBlur:this.handleBlur,onKeydown:this.handleKeyDown,onMousedown:this.handleMousedown,ref:this.setHandleRef,style:b});return g(\"div\",S,null)}});function Gh(e,t){try{return Object.keys(t).some(function(n){return e.target===Sn(t[n])||e.target===t[n]})}catch{return!1}}function gR(e,t){var n=t.min,r=t.max;return e<n||e>r}function Ox(e){return e.touches.length>1||e.type.toLowerCase()===\"touchend\"&&e.touches.length>0}function Px(e,t){var n=t.marks,r=t.step,a=t.min,o=t.max,i=Object.keys(n).map(parseFloat);if(r!==null){var l=Math.pow(10,yR(r)),s=Math.floor((o*l-a*l)/(r*l)),c=Math.min((e-a)/r,s),d=Math.round(c)*r+a;i.push(d)}var f=i.map(function(p){return Math.abs(e-p)});return i[f.indexOf(Math.min.apply(Math,Je(f)))]}function yR(e){var t=e.toString(),n=0;return t.indexOf(\".\")>=0&&(n=t.length-t.indexOf(\".\")-1),n}function Tx(e,t){var n=1;return window.visualViewport&&(n=+(window.visualViewport.width/document.body.getBoundingClientRect().width).toFixed(2)),(e?t.clientY:t.pageX)/n}function xx(e,t){var n=1;return window.visualViewport&&(n=+(window.visualViewport.width/document.body.getBoundingClientRect().width).toFixed(2)),(e?t.touches[0].clientY:t.touches[0].pageX)/n}function Cb(e,t){var n=t.getBoundingClientRect();return e?n.top+n.height*.5:window.pageXOffset+n.left+n.width*.5}function RS(e,t){var n=t.max,r=t.min;return e<=r?r:e>=n?n:e}function bR(e,t){var n=t.step,r=isFinite(Px(e,t))?Px(e,t):0;return n===null?r:parseFloat(r.toFixed(yR(n)))}function fs(e){e.stopPropagation(),e.preventDefault()}function M5e(e,t,n){var r={increase:function(l,s){return l+s},decrease:function(l,s){return l-s}},a=r[e](Object.keys(n.marks).indexOf(JSON.stringify(t)),1),o=Object.keys(n.marks)[a];return n.step?r[e](t,n.step):!!Object.keys(n.marks).length&&!!n.marks[o]?n.marks[o]:t}function CR(e,t,n){var r=\"increase\",a=\"decrease\",o=r;switch(e.keyCode){case ze.UP:o=t&&n?a:r;break;case ze.RIGHT:o=!t&&n?a:r;break;case ze.DOWN:o=t&&n?r:a;break;case ze.LEFT:o=!t&&n?r:a;break;case ze.END:return function(i,l){return l.max};case ze.HOME:return function(i,l){return l.min};case ze.PAGE_UP:return function(i,l){return i+l.step*2};case ze.PAGE_DOWN:return function(i,l){return i-l.step*2};default:return}return function(i,l){return M5e(o,i,l)}}var I5e=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function _l(){}function wR(e){var t={min:u.number,max:u.number,step:u.number,marks:u.object,included:u.looseBool,prefixCls:u.string,disabled:u.looseBool,handle:u.func,dots:u.looseBool,vertical:u.looseBool,reverse:u.looseBool,minimumTrackStyle:u.object,maximumTrackStyle:u.object,handleStyle:u.oneOfType([u.object,u.arrayOf(u.object)]),trackStyle:u.oneOfType([u.object,u.arrayOf(u.object)]),railStyle:u.object,dotStyle:u.object,activeDotStyle:u.object,autofocus:u.looseBool};return G({name:\"CreateSlider\",mixins:[nt,e],inheritAttrs:!1,props:An(t,{prefixCls:\"rc-slider\",min:0,max:100,step:1,marks:{},included:!0,disabled:!1,dots:!1,vertical:!1,reverse:!1,trackStyle:[{}],handleStyle:[{}],railStyle:{},dotStyle:{},activeDotStyle:{}}),data:function(){var r=this.step,a=this.max,o=this.min,i=isFinite(a-o)?(a-o)%r===0:!0;return on(r&&Math.floor(r)===r?i:!0,\"Slider\",\"Slider[max] - Slider[min] (%s) should be a multiple of Slider[step] (%s)\",a-o,r),this.handlesRefs={},{}},mounted:function(){var r=this;this.$nextTick(function(){r.document=r.sliderRef&&r.sliderRef.ownerDocument;var a=r.autofocus,o=r.disabled;a&&!o&&r.focus()})},beforeUnmount:function(){var r=this;this.$nextTick(function(){r.removeDocumentEvents()})},methods:{defaultHandle:function(r){var a=r.index;r.directives;var o=r.className,i=r.style,l=I5e(r,[\"index\",\"directives\",\"className\",\"style\"]);if(delete l.dragging,l.value===null)return null;var s=P(P({},l),{class:o,style:i,key:a});return g(mR,s,null)},onMouseDown:function(r){if(r.button===0){var a=this.vertical,o=Tx(a,r);if(!Gh(r,this.handlesRefs))this.dragOffset=0;else{var i=Cb(a,r.target);this.dragOffset=o-i,o=i}this.removeDocumentEvents(),this.onStart(o),this.addDocumentMouseEvents(),fs(r)}},onTouchStart:function(r){if(!Ox(r)){var a=this.vertical,o=xx(a,r);if(!Gh(r,this.handlesRefs))this.dragOffset=0;else{var i=Cb(a,r.target);this.dragOffset=o-i,o=i}this.onStart(o),this.addDocumentTouchEvents(),fs(r)}},onFocus:function(r){var a=this.vertical;if(Gh(r,this.handlesRefs)){var o=Cb(a,r.target);this.dragOffset=0,this.onStart(o),fs(r),this.__emit(\"focus\",r)}},onBlur:function(r){this.onEnd(),this.__emit(\"blur\",r)},onMouseUp:function(){this.handlesRefs[this.prevMovedHandleIndex]&&this.handlesRefs[this.prevMovedHandleIndex].clickFocus()},onMouseMove:function(r){if(!this.sliderRef){this.onEnd();return}var a=Tx(this.vertical,r);this.onMove(r,a-this.dragOffset)},onTouchMove:function(r){if(Ox(r)||!this.sliderRef){this.onEnd();return}var a=xx(this.vertical,r);this.onMove(r,a-this.dragOffset)},onKeyDown:function(r){this.sliderRef&&Gh(r,this.handlesRefs)&&this.onKeyboard(r)},onClickMarkLabel:function(r,a){var o=this;r.stopPropagation(),this.onChange({sValue:a}),this.setState({sValue:a},function(){return o.onEnd(!0)})},getSliderStart:function(){var r=this.sliderRef,a=this.vertical,o=this.reverse,i=r.getBoundingClientRect();return a?o?i.bottom:i.top:window.pageXOffset+(o?i.right:i.left)},getSliderLength:function(){var r=this.sliderRef;if(!r)return 0;var a=r.getBoundingClientRect();return this.vertical?a.height:a.width},addDocumentTouchEvents:function(){this.onTouchMoveListener=Kn(this.document,\"touchmove\",this.onTouchMove),this.onTouchUpListener=Kn(this.document,\"touchend\",this.onEnd)},addDocumentMouseEvents:function(){this.onMouseMoveListener=Kn(this.document,\"mousemove\",this.onMouseMove),this.onMouseUpListener=Kn(this.document,\"mouseup\",this.onEnd)},removeDocumentEvents:function(){this.onTouchMoveListener&&this.onTouchMoveListener.remove(),this.onTouchUpListener&&this.onTouchUpListener.remove(),this.onMouseMoveListener&&this.onMouseMoveListener.remove(),this.onMouseUpListener&&this.onMouseUpListener.remove()},focus:function(){this.disabled||this.handlesRefs[0].focus()},blur:function(){var r=this;this.disabled||Object.keys(this.handlesRefs).forEach(function(a){r.handlesRefs[a]&&r.handlesRefs[a].blur&&r.handlesRefs[a].blur()})},calcValue:function(r){var a=this.vertical,o=this.min,i=this.max,l=Math.abs(Math.max(r,0)/this.getSliderLength()),s=a?(1-l)*(i-o)+o:l*(i-o)+o;return s},calcValueByPos:function(r){var a=this.reverse?-1:1,o=a*(r-this.getSliderStart()),i=this.trimAlignValue(this.calcValue(o));return i},calcOffset:function(r){var a=this.min,o=this.max,i=(r-a)/(o-a);return i*100},saveSlider:function(r){this.sliderRef=r},saveHandle:function(r,a){this.handlesRefs[r]=a}},render:function(){var r,a=this.prefixCls,o=this.marks,i=this.dots,l=this.step,s=this.included,c=this.disabled,d=this.vertical,f=this.reverse,p=this.min,v=this.max,m=this.maximumTrackStyle,y=this.railStyle,b=this.dotStyle,C=this.activeDotStyle,S=this.$attrs,w=S.class,k=S.style,$=S.id,O=this.renderSlider(),T=O.tracks,_=O.handles,I=Se(a,w,(r={},V(r,\"\".concat(a,\"-with-marks\"),Object.keys(o).length),V(r,\"\".concat(a,\"-disabled\"),c),V(r,\"\".concat(a,\"-vertical\"),d),r)),L={vertical:d,marks:o,included:s,lowerBound:this.getLowerBound(),upperBound:this.getUpperBound(),max:v,min:p,reverse:f,class:\"\".concat(a,\"-mark\"),onClickLabel:c?_l:this.onClickMarkLabel},j=V({},mn?\"onTouchstartPassive\":\"onTouchstart\",c?_l:this.onTouchStart);return g(\"div\",le(le({id:$,ref:this.saveSlider,tabindex:\"-1\",class:I},j),{},{onMousedown:c?_l:this.onMouseDown,onMouseup:c?_l:this.onMouseUp,onKeydown:c?_l:this.onKeyDown,onFocus:c?_l:this.onFocus,onBlur:c?_l:this.onBlur,style:k}),[g(\"div\",{class:\"\".concat(a,\"-rail\"),style:P(P({},m),y)},null),T,g(_5e,{prefixCls:a,vertical:d,reverse:f,marks:o,dots:i,step:l,included:s,lowerBound:this.getLowerBound(),upperBound:this.getUpperBound(),max:v,min:p,dotStyle:b,activeDotStyle:C},null),_,g(E5e,L,null),ht(this)])}})}var N5e=G({name:\"Slider\",mixins:[nt],inheritAttrs:!1,props:{defaultValue:u.number,value:u.number,disabled:u.looseBool,autofocus:u.looseBool,tabindex:u.oneOfType([u.number,u.string]),reverse:u.looseBool,min:u.number,max:u.number},data:function(){var t=this.defaultValue!==void 0?this.defaultValue:this.min,n=this.value!==void 0?this.value:t;return{sValue:this.trimAlignValue(n),dragging:!1}},watch:{value:{handler:function(t){this.setChangeValue(t)},deep:!0},min:function(){var t=this.sValue;this.setChangeValue(t)},max:function(){var t=this.sValue;this.setChangeValue(t)}},methods:{setChangeValue:function(t){var n=t!==void 0?t:this.sValue,r=this.trimAlignValue(n,this.$props);r!==this.sValue&&(this.setState({sValue:r}),gR(n,this.$props)&&this.__emit(\"change\",r))},onChange:function(t){var n=!vt(this,\"value\"),r=t.sValue>this.max?P(P({},t),{sValue:this.max}):t;n&&this.setState(r);var a=r.sValue;this.__emit(\"change\",a)},onStart:function(t){this.setState({dragging:!0});var n=this.sValue;this.__emit(\"beforeChange\",n);var r=this.calcValueByPos(t);this.startValue=r,this.startPosition=t,r!==n&&(this.prevMovedHandleIndex=0,this.onChange({sValue:r}))},onEnd:function(t){var n=this.dragging;this.removeDocumentEvents(),(n||t)&&this.__emit(\"afterChange\",this.sValue),this.setState({dragging:!1})},onMove:function(t,n){fs(t);var r=this.sValue,a=this.calcValueByPos(n);a!==r&&this.onChange({sValue:a})},onKeyboard:function(t){var n=this.$props,r=n.reverse,a=n.vertical,o=CR(t,a,r);if(o){fs(t);var i=this.sValue,l=o(i,this.$props),s=this.trimAlignValue(l);if(s===i)return;this.onChange({sValue:s}),this.__emit(\"afterChange\",s),this.onEnd()}},getLowerBound:function(){return this.min},getUpperBound:function(){return this.sValue},trimAlignValue:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(t===null)return null;var r=P(P({},this.$props),n),a=RS(t,r);return bR(a,r)},getTrack:function(t){var n=t.prefixCls,r=t.reverse,a=t.vertical,o=t.included,i=t.offset,l=t.minimumTrackStyle,s=t._trackStyle;return g(hR,{class:\"\".concat(n,\"-track\"),vertical:a,included:o,offset:0,reverse:r,length:i,style:P(P({},l),s)},null)},renderSlider:function(){var t=this,n=this.prefixCls,r=this.vertical,a=this.included,o=this.disabled,i=this.minimumTrackStyle,l=this.trackStyle,s=this.handleStyle,c=this.tabindex,d=this.min,f=this.max,p=this.reverse,v=this.handle,m=this.defaultHandle,y=v||m,b=this.sValue,C=this.dragging,S=this.calcOffset(b),w=y({class:\"\".concat(n,\"-handle\"),prefixCls:n,vertical:r,offset:S,value:b,dragging:C,disabled:o,min:d,max:f,reverse:p,index:0,tabindex:c,style:s[0]||s,ref:function(O){return t.saveHandle(0,O)},onFocus:this.onFocus,onBlur:this.onBlur}),k=l[0]||l;return{tracks:this.getTrack({prefixCls:n,reverse:p,vertical:r,included:a,offset:S,minimumTrackStyle:i,_trackStyle:k}),handles:w}}}}),A5e=wR(N5e),Xh=function(t){var n=t.value,r=t.handle,a=t.bounds,o=t.props,i=o.allowCross,l=o.pushable,s=Number(l),c=RS(n,o),d=c;return!i&&r!=null&&a!==void 0&&(r>0&&c<=a[r-1]+s&&(d=a[r-1]+s),r<a.length-1&&c>=a[r+1]-s&&(d=a[r+1]-s)),bR(d,o)},D5e={defaultValue:u.arrayOf(u.number),value:u.arrayOf(u.number),count:u.number,pushable:an(u.oneOfType([u.looseBool,u.number])),allowCross:u.looseBool,disabled:u.looseBool,reverse:u.looseBool,tabindex:u.arrayOf(u.number),prefixCls:u.string,min:u.number,max:u.number,autofocus:u.looseBool},R5e={name:\"Range\",inheritAttrs:!1,displayName:\"Range\",mixins:[nt],props:An(D5e,{count:1,allowCross:!0,pushable:!1,tabindex:[]}),data:function(){var t=this,n=this.count,r=this.min,a=this.max,o=Array.apply(void 0,Je(Array(n+1))).map(function(){return r}),i=vt(this,\"defaultValue\")?this.defaultValue:o,l=this.value;l===void 0&&(l=i);var s=l.map(function(d,f){return Xh({value:d,handle:f,props:t.$props})}),c=s[0]===a?0:s.length-1;return{sHandle:null,recent:c,bounds:s}},watch:{value:{handler:function(t){var n=this.bounds;this.setChangeValue(t||n)},deep:!0},min:function(){var t=this.value;this.setChangeValue(t||this.bounds)},max:function(){var t=this.value;this.setChangeValue(t||this.bounds)}},methods:{setChangeValue:function(t){var n=this,r=this.bounds,a=t.map(function(i,l){return Xh({value:i,handle:l,bounds:r,props:n.$props})});if(!(a.length===r.length&&a.every(function(i,l){return i===r[l]}))&&(this.setState({bounds:a}),t.some(function(i){return gR(i,n.$props)}))){var o=t.map(function(i){return RS(i,n.$props)});this.__emit(\"change\",o)}},onChange:function(t){var n=!vt(this,\"value\");if(n)this.setState(t);else{var r={};[\"sHandle\",\"recent\"].forEach(function(i){t[i]!==void 0&&(r[i]=t[i])}),Object.keys(r).length&&this.setState(r)}var a=P(P({},this.$data),t),o=a.bounds;this.__emit(\"change\",o)},onStart:function(t){var n=this.bounds;this.__emit(\"beforeChange\",n);var r=this.calcValueByPos(t);this.startValue=r,this.startPosition=t;var a=this.getClosestBound(r);this.prevMovedHandleIndex=this.getBoundNeedMoving(r,a),this.setState({sHandle:this.prevMovedHandleIndex,recent:this.prevMovedHandleIndex});var o=n[this.prevMovedHandleIndex];if(r!==o){var i=Je(n);i[this.prevMovedHandleIndex]=r,this.onChange({bounds:i})}},onEnd:function(t){var n=this.sHandle;this.removeDocumentEvents(),(n!==null||t)&&this.__emit(\"afterChange\",this.bounds),this.setState({sHandle:null})},onMove:function(t,n){fs(t);var r=this.bounds,a=this.sHandle,o=this.calcValueByPos(n),i=r[a];o!==i&&this.moveTo(o)},onKeyboard:function(t){var n=this.$props,r=n.reverse,a=n.vertical,o=CR(t,a,r);if(o){fs(t);var i=this.bounds,l=this.sHandle,s=i[l===null?this.recent:l],c=o(s,this.$props),d=Xh({value:c,handle:l,bounds:i,props:this.$props});if(d===s)return;var f=!0;this.moveTo(d,f)}},getClosestBound:function(t){for(var n=this.bounds,r=0,a=1;a<n.length-1;++a)t>n[a]&&(r=a);return Math.abs(n[r+1]-t)<Math.abs(n[r]-t)&&(r+=1),r},getBoundNeedMoving:function(t,n){var r=this.bounds,a=this.recent,o=n,i=r[n+1]===r[n];return i&&r[a]===r[n]&&(o=a),i&&t!==r[n+1]&&(o=t<r[n+1]?n:n+1),o},getLowerBound:function(){return this.bounds[0]},getUpperBound:function(){var t=this.bounds;return t[t.length-1]},getPoints:function(){var t=this.marks,n=this.step,r=this.min,a=this.max,o=this._getPointsCache;if(!o||o.marks!==t||o.step!==n){var i=P({},t);if(n!==null)for(var l=r;l<=a;l+=n)i[l]=l;var s=Object.keys(i).map(parseFloat);s.sort(function(c,d){return c-d}),this._getPointsCache={marks:t,step:n,points:s}}return this._getPointsCache.points},moveTo:function(t,n){var r=this,a=Je(this.bounds),o=this.sHandle,i=this.recent,l=o===null?i:o;a[l]=t;var s=l;this.$props.pushable!==!1?this.pushSurroundingHandles(a,s):this.$props.allowCross&&(a.sort(function(c,d){return c-d}),s=a.indexOf(t)),this.onChange({recent:s,sHandle:s,bounds:a}),n&&(this.__emit(\"afterChange\",a),this.setState({},function(){r.handlesRefs[s].focus()}),this.onEnd())},pushSurroundingHandles:function(t,n){var r=t[n],a=this.pushable;a=Number(a);var o=0;if(t[n+1]-r<a&&(o=1),r-t[n-1]<a&&(o=-1),o!==0){var i=n+o,l=o*(t[i]-r);this.pushHandle(t,i,o,a-l)||(t[n]=t[i]-o*a)}},pushHandle:function(t,n,r,a){for(var o=t[n],i=t[n];r*(i-o)<a;){if(!this.pushHandleOnePoint(t,n,r))return t[n]=o,!1;i=t[n]}return!0},pushHandleOnePoint:function(t,n,r){var a=this.getPoints(),o=a.indexOf(t[n]),i=o+r;if(i>=a.length||i<0)return!1;var l=n+r,s=a[i],c=this.pushable,d=r*(t[l]-s);return this.pushHandle(t,l,r,c-d)?(t[n]=s,!0):!1},trimAlignValue:function(t){var n=this.sHandle,r=this.bounds;return Xh({value:t,handle:n,bounds:r,props:this.$props})},ensureValueNotConflict:function(t,n,r){var a=r.allowCross,o=r.pushable,i=this.$data||{},l=i.bounds;if(t=t===void 0?i.sHandle:t,o=Number(o),!a&&t!=null&&l!==void 0){if(t>0&&n<=l[t-1]+o)return l[t-1]+o;if(t<l.length-1&&n>=l[t+1]-o)return l[t+1]-o}return n},getTrack:function(t){var n=t.bounds,r=t.prefixCls,a=t.reverse,o=t.vertical,i=t.included,l=t.offsets,s=t.trackStyle;return n.slice(0,-1).map(function(c,d){var f,p=d+1,v=Se((f={},V(f,\"\".concat(r,\"-track\"),!0),V(f,\"\".concat(r,\"-track-\").concat(p),!0),f));return g(hR,{class:v,vertical:o,reverse:a,included:i,offset:l[p-1],length:l[p]-l[p-1],style:s[d],key:p},null)})},renderSlider:function(){var t=this,n=this.sHandle,r=this.bounds,a=this.prefixCls,o=this.vertical,i=this.included,l=this.disabled,s=this.min,c=this.max,d=this.reverse,f=this.handle,p=this.defaultHandle,v=this.trackStyle,m=this.handleStyle,y=this.tabindex,b=f||p,C=r.map(function(k){return t.calcOffset(k)}),S=\"\".concat(a,\"-handle\"),w=r.map(function(k,$){var O,T=y[$]||0;return(l||y[$]===null)&&(T=null),b({class:Se((O={},V(O,S,!0),V(O,\"\".concat(S,\"-\").concat($+1),!0),O)),prefixCls:a,vertical:o,offset:C[$],value:k,dragging:n===$,index:$,tabindex:T,min:s,max:c,reverse:d,disabled:l,style:m[$],ref:function(I){return t.saveHandle($,I)},onFocus:t.onFocus,onBlur:t.onBlur})});return{tracks:this.getTrack({bounds:r,prefixCls:a,reverse:d,vertical:o,included:i,offsets:C,trackStyle:v}),handles:w}}}},L5e=wR(R5e),_x=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},F5e=kg(),B5e=function(){return{prefixCls:u.string,tooltipPrefixCls:u.string,range:u.looseBool,reverse:u.looseBool,min:u.number,max:u.number,step:u.any,marks:u.object,dots:u.looseBool,value:u.oneOfType([u.number,u.arrayOf(u.number)]),defaultValue:u.oneOfType([u.number,u.arrayOf(u.number)]),included:u.looseBool,disabled:u.looseBool,vertical:u.looseBool,tipFormatter:u.oneOfType([u.func,u.object]),tooltipVisible:u.looseBool,tooltipPlacement:F5e.placement,getTooltipPopupContainer:u.func,onChange:u.func,onAfterChange:u.func}},V5e=function(t){return t.toString()},z5e=G({name:\"ASlider\",mixins:[nt],inheritAttrs:!1,props:P({},B5e()),emits:[\"update:value\",\"change\"],setup:function(){return{vcSlider:null,configProvider:ve(\"configProvider\",St)}},data:function(){return{visibles:{}}},methods:{toggleTooltipVisible:function(t,n){this.setState(function(r){var a=r.visibles;return{visibles:P(P({},a),V({},t,n))}})},handleWithTooltip:function(t,n,r){var a=this,o=r.value,i=r.dragging,l=r.index,s=_x(r,[\"value\",\"dragging\",\"index\"]),c=this.$props,d=c.tipFormatter,f=d===void 0?V5e:d,p=c.tooltipVisible,v=c.tooltipPlacement,m=c.getTooltipPopupContainer,y=this.visibles,b=f?y[l]||i:!1,C=p||p===void 0&&b,S={prefixCls:t,title:f?f(o):\"\",visible:C,placement:v||\"top\",transitionName:\"zoom-down\",overlayClassName:\"\".concat(n,\"-tooltip\"),getPopupContainer:m||function(){return document.body},key:l},w=P(P({value:o},s),{onMouseenter:function(){return a.toggleTooltipVisible(l,!0)},onMouseleave:function(){return a.toggleTooltipVisible(l,!1)}});return g(Io,S,{default:function(){return[g(mR,w,null)]}})},saveSlider:function(t){this.vcSlider=t},focus:function(){this.vcSlider.focus()},blur:function(){this.vcSlider.blur()},handleChange:function(t){this.$emit(\"update:value\",t),this.$emit(\"change\",t)}},render:function(){var t=this,n=P(P({},Qe(this)),this.$attrs),r=n.range,a=n.prefixCls,o=n.tooltipPrefixCls,i=_x(n,[\"range\",\"prefixCls\",\"tooltipPrefixCls\"]),l=this.configProvider.getPrefixCls,s=l(\"slider\",a),c=l(\"tooltip\",o);if(r){var d=P(P({},i),{prefixCls:s,tooltipPrefixCls:c,handle:function(v){return t.handleWithTooltip(c,s,v)},ref:this.saveSlider,onChange:this.handleChange});return g(L5e,d,null)}var f=P(P({},i),{prefixCls:s,tooltipPrefixCls:c,handle:function(v){return t.handleWithTooltip(c,s,v)},ref:this.saveSlider,onChange:this.handleChange});return g(A5e,f,null)}}),H5e=kn(z5e),j5e={small:8,middle:16,large:24},K5e={prefixCls:u.string,size:{type:[String,Number,Array]},direction:u.oneOf(rt(\"horizontal\",\"vertical\")).def(\"horizontal\"),align:u.oneOf(rt(\"start\",\"end\",\"center\",\"baseline\")),wrap:u.looseBool};function W5e(e){return typeof e==\"string\"?j5e[e]:e||0}var U5e=G({name:\"ASpace\",props:K5e,slots:[\"split\"],setup:function(t,n){var r=n.slots,a=Wt(\"space\",t),o=a.prefixCls,i=a.space,l=a.direction,s=CD(),c=x(function(){var b;return t.size||((b=i.value)===null||b===void 0?void 0:b.size)||\"small\"}),d=H(),f=H();ce(c,function(){var b=(Array.isArray(c.value)?c.value:[c.value,c.value]).map(function(S){return W5e(S)}),C=fn(b,2);d.value=C[0],f.value=C[1]},{immediate:!0});var p=x(function(){return t.align===void 0&&t.direction===\"horizontal\"?\"center\":t.align}),v=x(function(){var b;return Se(o.value,\"\".concat(o.value,\"-\").concat(t.direction),(b={},V(b,\"\".concat(o.value,\"-rtl\"),l.value===\"rtl\"),V(b,\"\".concat(o.value,\"-align-\").concat(p.value),p.value),b))}),m=x(function(){return l.value===\"rtl\"?\"marginLeft\":\"marginRight\"}),y=x(function(){var b={};return s.value&&(b.columnGap=\"\".concat(d.value,\"px\"),b.rowGap=\"\".concat(f.value,\"px\")),P(P({},b),t.wrap&&{flexWrap:\"wrap\",marginBottom:\"\".concat(-f.value,\"px\")})});return function(){var b,C,S=t.wrap,w=t.direction,k=w===void 0?\"horizontal\":w,$=La((b=r.default)===null||b===void 0?void 0:b.call(r)),O=$.length;if(O===0)return null;var T=(C=r.split)===null||C===void 0?void 0:C.call(r),_=\"\".concat(o.value,\"-item\"),I=d.value,L=O-1;return g(\"div\",{class:v.value,style:y.value},[$.map(function(j,F){var N={};return s.value||(k===\"vertical\"?F<L&&(N={marginBottom:\"\".concat(I/(T?2:1),\"px\")}):N=P(P({},F<L&&V({},m.value,\"\".concat(I/(T?2:1),\"px\"))),S&&{paddingBottom:\"\".concat(f.value,\"px\")})),g(Fe,null,[g(\"div\",{class:_,style:N},[j]),F<L&&T&&g(\"span\",{class:\"\".concat(_,\"-split\"),style:N},[T])])})])}}}),Y5e=kn(U5e);function Ex(){if(typeof window!=\"undefined\"&&window.document&&window.document.documentElement){var e=window.document.documentElement;return\"flex\"in e.style||\"webkitFlex\"in e.style||\"Flex\"in e.style||\"msFlex\"in e.style}return!1}var _1=G({name:\"Steps\",mixins:[nt],props:{type:u.string.def(\"default\"),prefixCls:u.string.def(\"rc-steps\"),iconPrefix:u.string.def(\"rc\"),direction:u.string.def(\"horizontal\"),labelPlacement:u.string.def(\"horizontal\"),status:u.string.def(\"process\"),size:u.string.def(\"\"),progressDot:an(u.oneOfType([u.looseBool,u.func])),initial:u.number.def(0),current:u.number.def(0),icons:u.shape({finish:u.any,error:u.any}).loose,canClick:u.looseBool},data:function(){return this.calcStepOffsetWidth=Yn(this.calcStepOffsetWidth,150),{flexSupported:!0,lastStepOffsetWidth:0}},mounted:function(){var t=this;this.$nextTick(function(){t.calcStepOffsetWidth(),Ex()||t.setState({flexSupported:!1})})},updated:function(){var t=this;this.$nextTick(function(){t.calcStepOffsetWidth()})},beforeUnmount:function(){this.calcTimeout&&clearTimeout(this.calcTimeout),this.calcStepOffsetWidth&&this.calcStepOffsetWidth.cancel&&this.calcStepOffsetWidth.cancel()},methods:{onStepClick:function(t){var n=this.$props.current;n!==t&&this.__emit(\"change\",t)},calcStepOffsetWidth:function(){var t=this;if(!Ex()){var n=this.$data.lastStepOffsetWidth,r=this.$refs.vcStepsRef;r.children.length>0&&(this.calcTimeout&&clearTimeout(this.calcTimeout),this.calcTimeout=setTimeout(function(){var a=(r.lastChild.offsetWidth||0)+1;n===a||Math.abs(n-a)<=3||t.setState({lastStepOffsetWidth:a})}))}}},render:function(){var t,n=this,r=this.prefixCls,a=this.direction,o=this.type,i=this.labelPlacement,l=this.iconPrefix,s=this.status,c=this.size,d=this.current,f=this.progressDot,p=this.initial,v=this.icons,m=this.canClick,y=o===\"navigation\",b=this.lastStepOffsetWidth,C=this.flexSupported,S=ht(this),w=S.length-1,k=f?\"vertical\":i,$=(t={},V(t,r,!0),V(t,\"\".concat(r,\"-\").concat(a),!0),V(t,\"\".concat(r,\"-\").concat(c),c),V(t,\"\".concat(r,\"-label-\").concat(k),a===\"horizontal\"),V(t,\"\".concat(r,\"-dot\"),!!f),V(t,\"\".concat(r,\"-navigation\"),y),V(t,\"\".concat(r,\"-flex-not-supported\"),!C),t),O={class:$,ref:\"vcStepsRef\"};return g(\"div\",O,[S.map(function(T,_){var I=rr(T),L=p+_,j=P({stepNumber:\"\".concat(L+1),stepIndex:L,prefixCls:r,iconPrefix:l,progressDot:f,icons:v},I);return m&&(j.onStepClick=n.onStepClick),!C&&a!==\"vertical\"&&(y?(j.itemWidth=\"\".concat(100/(w+1),\"%\"),j.adjustMarginRight=0):_!==w&&(j.itemWidth=\"\".concat(100/w,\"%\"),j.adjustMarginRight=\"\".concat(-Math.round(b/w+1),\"px\"))),s===\"error\"&&_===d-1&&(j.class=\"\".concat(r,\"-next-error\")),I.status||(L===d?j.status=s:L<d?j.status=\"finish\":j.status=\"wait\"),j.active=L===d,Ot(T,j)})])}});function Mx(e){return typeof e==\"string\"}function q5e(){}var G5e=G({name:\"Step\",mixins:[nt],props:{prefixCls:u.string,wrapperStyle:u.object,itemWidth:u.string,active:u.looseBool,disabled:u.looseBool,status:u.string,iconPrefix:u.string,icon:u.any,adjustMarginRight:u.string,stepNumber:u.string,stepIndex:u.number,description:u.any,title:u.any,subTitle:u.any,progressDot:an(u.oneOfType([u.looseBool,u.func])),tailContent:u.any,icons:u.shape({finish:u.any,error:u.any}).loose,onClick:u.func,onStepClick:u.func},methods:{onItemClick:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.__emit.apply(this,[\"click\"].concat(n)),this.__emit(\"stepClick\",this.stepIndex)},renderIconNode:function(){var t,n=Qe(this),r=n.prefixCls,a=n.stepNumber,o=n.status,i=n.iconPrefix,l=n.icons,s=n.progressDot,c=We(this,\"icon\"),d=We(this,\"title\"),f=We(this,\"description\"),p,v=(t={},V(t,\"\".concat(r,\"-icon\"),!0),V(t,\"\".concat(i,\"icon\"),!0),V(t,\"\".concat(i,\"icon-\").concat(c),c&&Mx(c)),V(t,\"\".concat(i,\"icon-check\"),!c&&o===\"finish\"&&l&&!l.finish),V(t,\"\".concat(i,\"icon-close\"),!c&&o===\"error\"&&l&&!l.error),t),m=g(\"span\",{class:\"\".concat(r,\"-icon-dot\")},null);return s?typeof s==\"function\"?p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[s({index:a-1,status:o,title:d,description:f,prefixCls:r})]):p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[m]):c&&!Mx(c)?p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[c]):l&&l.finish&&o===\"finish\"?p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[l.finish]):l&&l.error&&o===\"error\"?p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[l.error]):c||o===\"finish\"||o===\"error\"?p=g(\"span\",{class:v},null):p=g(\"span\",{class:\"\".concat(r,\"-icon\")},[a]),p}},render:function(){var t,n=Qe(this),r=n.prefixCls,a=n.itemWidth,o=n.active,i=n.status,l=i===void 0?\"wait\":i,s=n.tailContent,c=n.adjustMarginRight,d=n.disabled,f=n.onClick,p=n.onStepClick,v=We(this,\"title\"),m=We(this,\"subTitle\"),y=We(this,\"description\"),b=(t={},V(t,\"\".concat(r,\"-item\"),!0),V(t,\"\".concat(r,\"-item-\").concat(l),!0),V(t,\"\".concat(r,\"-item-custom\"),We(this,\"icon\")),V(t,\"\".concat(r,\"-item-active\"),o),V(t,\"\".concat(r,\"-item-disabled\"),d===!0),t),C={class:b},S={};a&&(S.width=a),c&&(S.marginRight=c);var w={onClick:f||q5e};return p&&!d&&(w.role=\"button\",w.tabindex=0,w.onClick=this.onItemClick),g(\"div\",le(le({},C),{},{style:S}),[g(\"div\",le(le({},w),{},{class:\"\".concat(r,\"-item-container\")}),[g(\"div\",{class:\"\".concat(r,\"-item-tail\")},[s]),g(\"div\",{class:\"\".concat(r,\"-item-icon\")},[this.renderIconNode()]),g(\"div\",{class:\"\".concat(r,\"-item-content\")},[g(\"div\",{class:\"\".concat(r,\"-item-title\")},[v,m&&g(\"div\",{title:m,class:\"\".concat(r,\"-item-subtitle\")},[m])]),y&&g(\"div\",{class:\"\".concat(r,\"-item-description\")},[y])])])])}});_1.Step=G5e;var X5e={prefixCls:u.string,iconPrefix:u.string,current:u.number,initial:u.number,labelPlacement:u.oneOf(rt(\"horizontal\",\"vertical\")).def(\"horizontal\"),status:u.oneOf(rt(\"wait\",\"process\",\"finish\",\"error\")),size:u.oneOf(rt(\"default\",\"small\")),direction:u.oneOf(rt(\"horizontal\",\"vertical\")),progressDot:an(u.oneOfType([u.looseBool,u.func])),type:u.oneOf(rt(\"default\",\"navigation\")),onChange:u.func,\"onUpdate:current\":u.func},jl=G({name:\"ASteps\",inheritAttrs:!1,props:Rn(X5e,{current:0}),emits:[\"update:current\",\"change\"],setup:function(){return{configProvider:ve(\"configProvider\",St)}},Step:P(P({},_1.Step),{name:\"AStep\"}),methods:{handleChange:function(t){this.$emit(\"update:current\",t),this.$emit(\"change\",t)}},render:function(){var t=this,n=P(P({},Qe(this)),this.$attrs),r=n.prefixCls,a=n.iconPrefix,o=this.configProvider.getPrefixCls,i=o(\"steps\",r),l=o(\"\",a),s=We(this,\"progressDot\",this,!1),c={finish:g(wg,{class:\"\".concat(i,\"-finish-icon\")},null),error:g(go,{class:\"\".concat(i,\"-error-icon\")},null)},d=P(P({icons:c,iconPrefix:l,prefixCls:i,progressDot:s},n),{canClick:!!(this.onChange||this[\"onUpdate:current\"]),onChange:this.handleChange});return g(_1,d,{default:function(){return[ht(t)]}})}});jl.install=function(e){return e.component(jl.name,jl),e.component(jl.Step.name,jl.Step),e};var Z5e=jl.Step,J5e=jl,Q5e=rt(\"small\",\"default\"),eIe={prefixCls:u.string,size:u.oneOf(Q5e),disabled:u.looseBool,checkedChildren:u.VNodeChild,unCheckedChildren:u.VNodeChild,tabindex:u.oneOfType([u.string,u.number]),autofocus:u.looseBool,loading:u.looseBool,checked:u.oneOfType([u.string,u.number,u.looseBool]),checkedValue:u.oneOfType([u.string,u.number,u.looseBool]).def(!0),unCheckedValue:u.oneOfType([u.string,u.number,u.looseBool]).def(!1),onChange:{type:Function},onClick:{type:Function},onKeydown:{type:Function},onMouseup:{type:Function},\"onUpdate:checked\":{type:Function}},tIe=G({name:\"ASwitch\",__ANT_SWITCH:!0,inheritAttrs:!1,props:eIe,slots:[\"checkedChildren\",\"unCheckedChildren\"],emits:[\"update:checked\",\"mouseup\",\"change\",\"click\",\"keydown\"],setup:function(t,n){var r=n.attrs,a=n.slots,o=n.expose,i=n.emit;hc(function(){on(!(\"defaultChecked\"in r),\"Switch\",\"'defaultChecked' is deprecated, please use 'v-model:checked'\"),on(!(\"value\"in r),\"Switch\",\"`value` is not validate prop, do you mean `checked`?\")});var l=H(t.checked!==void 0?t.checked:r.defaultChecked),s=x(function(){return l.value===t.checkedValue});ce(function(){return t.checked},function(){l.value=t.checked});var c=Wt(\"switch\",t),d=c.prefixCls,f=H(),p=function(){var k;(k=f.value)===null||k===void 0||k.focus()},v=function(){var k;(k=f.value)===null||k===void 0||k.blur()};o({focus:p,blur:v}),et(function(){Ne(function(){t.autofocus&&!t.disabled&&f.value.focus()})});var m=function(k,$){t.disabled||(i(\"update:checked\",k),i(\"change\",k,$))},y=function(k){p();var $=s.value?t.unCheckedValue:t.checkedValue;m($,k),i(\"click\",$,k)},b=function(k){k.keyCode===ze.LEFT?m(t.unCheckedValue,k):k.keyCode===ze.RIGHT&&m(t.checkedValue,k),i(\"keydown\",k)},C=function(k){var $;($=f.value)===null||$===void 0||$.blur(),i(\"mouseup\",k)},S=x(function(){var w;return w={},V(w,\"\".concat(d.value,\"-small\"),t.size===\"small\"),V(w,\"\".concat(d.value,\"-loading\"),t.loading),V(w,\"\".concat(d.value,\"-checked\"),s.value),V(w,\"\".concat(d.value,\"-disabled\"),t.disabled),V(w,d.value,!0),w});return function(){return g(C2,{insertExtraNode:!0},{default:function(){return[g(\"button\",le(le(le({},bn(t,[\"prefixCls\",\"checkedChildren\",\"unCheckedChildren\",\"checked\",\"autofocus\",\"defaultChecked\",\"checkedValue\",\"unCheckedValue\"])),r),{},{onKeydown:b,onClick:y,onMouseup:C,type:\"button\",role:\"switch\",\"aria-checked\":l.value,disabled:t.disabled||t.loading,class:[r.class,S.value],ref:f}),[t.loading?g(co,{class:\"\".concat(d.value,\"-loading-icon\")},null):null,g(\"span\",{class:\"\".concat(d.value,\"-inner\")},[s.value?jn(a,t,\"checkedChildren\"):jn(a,t,\"unCheckedChildren\")])])]}})}}}),nIe=kn(tIe),rIe={icon:{tag:\"svg\",attrs:{viewBox:\"0 0 1024 1024\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z\"}}]},name:\"caret-up\",theme:\"filled\"},aIe=rIe;function Ix(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){oIe(e,a,n[a])})}return e}function oIe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var LS=function(t,n){var r=Ix({},t,n.attrs);return g(Et,Ix({},r,{icon:aIe}),null)};LS.displayName=\"CaretUpFilled\";LS.inheritAttrs=!1;var iIe=LS,lIe={icon:{tag:\"svg\",attrs:{viewBox:\"0 0 1024 1024\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z\"}}]},name:\"caret-down\",theme:\"filled\"},sIe=lIe;function Nx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){uIe(e,a,n[a])})}return e}function uIe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var FS=function(t,n){var r=Nx({},t,n.attrs);return g(Et,Nx({},r,{icon:sIe}),null)};FS.displayName=\"CaretDownFilled\";FS.inheritAttrs=!1;var SR=FS,wb,Sb,Ax={position:\"absolute\",top:\"-9999px\",width:\"50px\",height:\"50px\"},kR=\"RC_TABLE_INTERNAL_COL_DEFINE\";function Dx(e){var t=e.direction,n=t===void 0?\"vertical\":t,r=e.prefixCls;if(typeof document==\"undefined\"||typeof window==\"undefined\")return 0;var a=n===\"vertical\";if(a&&wb)return wb;if(!a&&Sb)return Sb;var o=document.createElement(\"div\");Object.keys(Ax).forEach(function(l){o.style[l]=Ax[l]}),o.className=\"\".concat(r,\"-hide-scrollbar scroll-div-append-to-body\"),a?o.style.overflowY=\"scroll\":o.style.overflowX=\"scroll\",document.body.appendChild(o);var i=0;return a?(i=o.offsetWidth-o.clientWidth,wb=i):(i=o.offsetHeight-o.clientHeight,Sb=i),document.body.removeChild(o),i}function cIe(e,t,n){var r;function a(){for(var o=arguments.length,i=new Array(o),l=0;l<o;l++)i[l]=arguments[l];var s=this;i[0]&&i[0].persist&&i[0].persist();var c=function(){r=null,n||e.apply(s,i)},d=n&&!r;clearTimeout(r),r=setTimeout(c,t),d&&e.apply(s,i)}return a.cancel=function(){r&&(clearTimeout(r),r=null)},a}function dIe(e,t){var n=e.indexOf(t),r=e.slice(0,n),a=e.slice(n+1,e.length);return r.concat(a)}function fIe(e){return Object.keys(e).reduce(function(t,n){return(n.substr(0,5)===\"data-\"||n.substr(0,5)===\"aria-\")&&(t[n]=e[n]),t},{})}function hIe(e){var t=[];return e.forEach(function(n){var r=n||{},a=r.key,o=r.dataIndex;t.push(a!==void 0?a:o)}),t}function pIe(e){return e!=null}var vIe={name:\"ColGroup\",inheritAttrs:!1,props:{fixed:u.string,columns:u.array},setup:function(){return{table:ve(\"table\",{}),store:ve(\"table-store\",function(){return{}})}},render:function(){var t=this.fixed,n=this.table,r=n.prefixCls,a=n.expandIconAsCell,o=n.onColumnResize,i=[];a&&t!==\"right\"&&i.push(g(\"col\",{class:\"\".concat(r,\"-expand-icon-col\"),key:\"rc-table-expand-icon-col\"},null));var l,s=this.store.columnManager;return t===\"left\"?l=s.leftLeafColumns:t===\"right\"?l=s.rightLeafColumns:l=s.leafColumns,i=i.concat(l.map(function(c){var d=c.key,f=c.dataIndex,p=c.width,v=c[kR],m=d!==void 0?d:f,y=typeof p==\"number\"?\"\".concat(p,\"px\"):p;return g(zo,{onResize:function(C){var S=C.offsetWidth;o(m,S)}},{default:function(){return[g(\"col\",le({\"data-key\":m,key:m,style:{width:y,minWidth:y}},v),null)]}})})),g(\"colgroup\",null,[i])}};function $R(e,t,n,r,a){var o=n[e]||{},i=n[t]||{},l,s;o.fixed===\"left\"?l=r.left[e]:i.fixed===\"right\"&&(s=r.right[t]);var c=!1,d=!1,f=!1,p=!1,v=n[t+1],m=n[e-1];if(a===\"rtl\"){if(l!==void 0){var y=m&&m.fixed===\"left\";p=!y}else if(s!==void 0){var b=v&&v.fixed===\"right\";f=!b}}else if(l!==void 0){var C=v&&v.fixed===\"left\";c=!C}else if(s!==void 0){var S=m&&m.fixed===\"right\";d=!S}return{fixLeft:l,fixRight:s,lastFixLeft:c,firstFixRight:d,lastFixRight:f,firstFixLeft:p,isSticky:r.isSticky}}var mIe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},gIe={name:\"TableHeaderRow\",inheritAttrs:!1,props:{index:u.number,fixed:u.string,columns:u.array,rows:u.array,row:u.array,components:u.object,customHeaderRow:u.func,prefixCls:u.prefixCls},setup:function(t){var n=ve(\"table-store\",function(){return{}});return{height:x(function(){var r=n.fixedColumnsHeadRowsHeight,a=t.columns,o=t.rows,i=t.fixed,l=r[0];return i&&l&&a?l===\"auto\"?\"auto\":\"\".concat(l/o.length,\"px\"):null}),store:n}},render:function(){var t=this.row,n=this.index,r=this.height,a=this.components,o=this.customHeaderRow,i=this.prefixCls,l=a.header.row,s=a.header.cell,c=o(t.map(function(y){return y.column}),n),d=c?c.style:{},f=P({height:r},d);f.height===null&&delete f.height;var p=this.store,v=p.stickyOffsets,m=p.columnManager;return g(l,le(le({},c),{},{style:f}),{default:function(){return[t.map(function(b,C){var S,w=b.column,k=b.isLast,$=b.children;b.className;var O=mIe(b,[\"column\",\"isLast\",\"children\",\"className\"]),T=$R(b.colStart,b.colEnd,m.leafColumns,v),_=w.customHeaderCell?w.customHeaderCell(w):{},I=P(P(P({},O),_),{key:w.key||w.dataIndex||C});if(I.colSpan===0)return null;w.align&&(I.style=P(P({},_.style),{textAlign:w.align}));var L=T.fixLeft,j=T.fixRight,F=T.firstFixLeft,N=T.lastFixLeft,D=T.firstFixRight,z=T.lastFixRight,B={},M=typeof L==\"number\",E=typeof j==\"number\";return M&&(B.position=\"sticky\",B.left=\"\".concat(L,\"px\")),E&&(B.position=\"sticky\",B.right=\"\".concat(j,\"px\")),I.class=Se(_.class,_.className,w.class,w.className,(S={},V(S,\"\".concat(i,\"-align-\").concat(w.align),!!w.align),V(S,\"\".concat(i,\"-row-cell-ellipsis\"),!!w.ellipsis),V(S,\"\".concat(i,\"-row-cell-break-word\"),!!w.width),V(S,\"\".concat(i,\"-row-cell-last\"),k),V(S,\"\".concat(i,\"-cell-fix-left\"),M),V(S,\"\".concat(i,\"-cell-fix-left-first\"),F),V(S,\"\".concat(i,\"-cell-fix-left-last\"),N),V(S,\"\".concat(i,\"-cell-fix-right\"),E),V(S,\"\".concat(i,\"-cell-fix-right-first\"),D),V(S,\"\".concat(i,\"-cell-fix-right-last\"),z),S)),I.style=P(P({},I.style||{}),B),typeof s==\"function\"?s(I,$):g(s,I,{default:function(){return[$]}})})]}})}},yIe=gIe;function bIe(e){var t=[];function n(i,l){var s=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0;t[s]=t[s]||[];var c=l,d=i.filter(Boolean).map(function(f){var p={key:f.key,className:f.className||f.class||\"\",children:f.title,column:f,colStart:c},v=1,m=f.children;return m&&m.length>0&&(v=n(m,c,s+1).reduce(function(y,b){return y+b},0),p.hasSubColumns=!0),\"colSpan\"in f&&(v=f.colSpan),\"rowSpan\"in f&&(p.rowSpan=f.rowSpan),p.colSpan=v,p.colEnd=p.colStart+v-1,t[s].push(p),c+=v,v});return d}n(e,0);for(var r=t.length,a=function(l){t[l].forEach(function(s){!(\"rowSpan\"in s)&&!s.hasSubColumns&&(s.rowSpan=r-l)})},o=0;o<r;o+=1)a(o);return t}var CIe={name:\"TableHeader\",inheritAttrs:!1,props:{fixed:u.string,columns:u.array.isRequired,expander:u.object.isRequired},setup:function(){return{table:ve(\"table\",{})}},render:function(){var t=this.table,n=t.sComponents,r=t.prefixCls,a=t.showHeader,o=t.customHeaderRow,i=this.expander,l=this.columns,s=this.fixed;if(!a)return null;var c=bIe(this.columns);i.renderExpandIndentCell(c,s);var d=n.header.wrapper;return g(d,{class:\"\".concat(r,\"-thead\")},{default:function(){return[c.map(function(p,v){return g(yIe,{prefixCls:r,key:v,index:v,fixed:s,columns:l,rows:c,row:p,components:n,customHeaderRow:o},null)})]}})}};function Rx(e){return e&&!zn(e)&&Object.prototype.toString.call(e)===\"[object Object]\"}var wIe={name:\"TableCell\",inheritAttrs:!1,props:{record:u.object,prefixCls:u.string,index:u.number,indent:u.number,indentSize:u.number,column:u.object,expandIcon:u.any,component:u.any,colIndex:u.number},setup:function(){return{table:ve(\"table\",{}),store:ve(\"table-store\",{})}},methods:{handleClick:function(t){var n=this.record,r=this.column.onCellClick;r&&r(n,t)}},render:function(){var t,n=this.record,r=this.indentSize,a=this.prefixCls,o=this.indent,i=this.index,l=this.expandIcon,s=this.column,c=this.component,d=this.store.fixedInfoList||[],f=d[this.colIndex]||{},p=f.fixLeft,v=f.fixRight,m=f.firstFixLeft,y=f.lastFixLeft,b=f.firstFixRight,C=f.lastFixRight,S={},w=typeof p==\"number\",k=typeof v==\"number\";w&&(S.position=\"sticky\",S.left=\"\".concat(p,\"px\")),k&&(S.position=\"sticky\",S.right=\"\".concat(v,\"px\"));var $=s.dataIndex,O=s.customRender,T=s.className,_=T===void 0?\"\":T,I=this.table,L=I.transformCellText,j=I.prefixCls,F;typeof $==\"number\"?F=vn(n,$):!$||$.length===0?F=n:F=vn(n,$);var N={onClick:this.handleClick},D,z;if(O&&(F=O({text:F,record:n,index:i,column:s}),Rx(F))){N=F.props||F.attrs||N;var B=N;D=B.colSpan,z=B.rowSpan,F=F.children}s.customCell&&(N=P(P({},N),s.customCell(n,i))),Rx(F)&&(F=null),L&&(F=L({text:F,column:s,record:n,index:i}));var M=l?g(\"span\",{style:{paddingLeft:\"\".concat(r*o,\"px\")},class:\"\".concat(a,\"-indent indent-level-\").concat(o)},null):null;if(z===0||D===0)return null;s.align&&(N.style=P({textAlign:s.align},N.style));var E=Se(_,s.class,(t={},V(t,\"\".concat(a,\"-cell-ellipsis\"),!!s.ellipsis),V(t,\"\".concat(a,\"-cell-break-word\"),!!s.width),V(t,\"\".concat(j,\"-cell-fix-left\"),w),V(t,\"\".concat(j,\"-cell-fix-left-first\"),m),V(t,\"\".concat(j,\"-cell-fix-left-last\"),y),V(t,\"\".concat(j,\"-cell-fix-right\"),k),V(t,\"\".concat(j,\"-cell-fix-right-first\"),b),V(t,\"\".concat(j,\"-cell-fix-right-last\"),C),t));return s.ellipsis&&typeof F==\"string\"&&(N.title=F),g(c,le(le({class:E},N),{},{style:P(P({},N.style||{}),S)}),{default:function(){return[M,l,Gt(F)]}})}},SIe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function Zs(){}var kIe={name:\"TableRow\",inheritAttrs:!1,mixins:[nt],props:An({customRow:u.func,record:u.object,prefixCls:u.string,columns:u.array,index:u.number,rowKey:u.oneOfType([u.string,u.number]).isRequired,className:u.string,indent:u.number,indentSize:u.number,hasExpandIcon:u.func,fixed:an(u.oneOfType([u.string,u.looseBool])),renderExpandIcon:u.func,renderExpandIconCell:u.func,components:u.any,expandedRow:u.looseBool,isAnyColumnsFixed:u.looseBool,ancestorKeys:u.array.isRequired,expandIconColumnIndex:u.number,expandRowByClick:u.looseBool},{hasExpandIcon:function(){},renderExpandIcon:function(){},renderExpandIconCell:function(){}}),setup:function(t){var n=ve(\"table-store\",function(){return{}}),r=x(function(){var i=n.expandedRowKeys,l=t.ancestorKeys;return!!(l.length===0||l.every(function(s){return i.includes(s)}))}),a=x(function(){var i=n.expandedRowsHeight,l=n.fixedColumnsBodyRowsHeight,s=t.fixed,c=t.rowKey;return s?i[c]?i[c]:l[c]?l[c]:null:null}),o=x(function(){var i=n.currentHoverKey,l=t.rowKey;return i===l});return{store:n,visible:r,hovered:o,height:a}},data:function(){return this.rowRef=null,{shouldRender:this.visible}},mounted:function(){var t=this;this.shouldRender&&this.$nextTick(function(){t.saveRowRef()})},watch:{visible:function(t){t&&(this.shouldRender=!0)}},updated:function(){var t=this;this.shouldRender&&!this.rowRef&&this.$nextTick(function(){t.saveRowRef()})},methods:{onRowClick:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Zs,r=this.record,a=this.index;this.__emit(\"rowClick\",r,a,t),n(t)},onRowDoubleClick:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Zs,r=this.record,a=this.index;this.__emit(\"rowDoubleClick\",r,a,t),n(t)},onContextMenu:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Zs,r=this.record,a=this.index;this.__emit(\"rowContextmenu\",r,a,t),n(t)},onMouseEnter:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Zs,r=this.record,a=this.index,o=this.rowKey;this.__emit(\"hover\",!0,o),this.__emit(\"rowMouseenter\",r,a,t),n(t)},onMouseLeave:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Zs,r=this.record,a=this.index,o=this.rowKey;this.__emit(\"hover\",!1,o),this.__emit(\"rowMouseleave\",r,a,t),n(t)},setExpandedRowHeight:function(){var t=this.store,n=this.rowKey,r=t.expandedRowsHeight,a=this.rowRef.getBoundingClientRect().height;r=P(P({},r),V({},n,a)),t.expandedRowsHeight=r},setRowHeight:function(){var t=this.store,n=this.rowKey,r=t.fixedColumnsBodyRowsHeight,a=this.rowRef.getBoundingClientRect().height;t.fixedColumnsBodyRowsHeight=P(P({},r),V({},n,a))},getStyle:function(){var t=this.height,n=this.visible,r=this.$attrs.style||{};return t&&(r=P(P({},r),{height:t})),!n&&!r.display&&(r=P(P({},r),{display:\"none\"})),r},saveRowRef:function(){this.rowRef=Sn(this);var t=this.isAnyColumnsFixed,n=this.fixed,r=this.expandedRow,a=this.ancestorKeys;!t||(!n&&r&&this.setExpandedRowHeight(),!n&&a.length>=0&&this.setRowHeight())}},render:function(){var t=this;if(!this.shouldRender)return null;var n=this.prefixCls,r=this.columns,a=this.record,o=this.rowKey,i=this.index,l=this.customRow,s=l===void 0?Zs:l,c=this.indent,d=this.indentSize,f=this.hovered,p=this.height,v=this.visible,m=this.components,y=this.hasExpandIcon,b=this.renderExpandIcon,C=this.renderExpandIconCell,S=m.body.row,w=m.body.cell,k=this.$attrs.class||\"\";f&&(k+=\" \".concat(n,\"-hover\"));var $=[];C($);for(var O=0;O<r.length;O+=1){var T=r[O];on(T.onCellClick===void 0,\"column[onCellClick] is deprecated, please use column[customCell] instead.\"),$.push(g(wIe,{prefixCls:n,record:a,indentSize:d,indent:c,index:i,colIndex:O,column:T,key:T.key||T.dataIndex,expandIcon:y(O)&&b(),component:w},null))}var _=s(a,i)||{},I=_.class,L=_.className,j=_.style,F=SIe(_,[\"class\",\"className\",\"style\"]),N={height:typeof p==\"number\"?\"\".concat(p,\"px\"):p};v||(N.display=\"none\"),N=P(P({},N),j);var D=Se(n,k,\"\".concat(n,\"-level-\").concat(c),L,I),z=P(P({},F),{style:N,onClick:function(M){t.onRowClick(M,F.onClick)},onDblclick:function(M){t.onRowDoubleClick(M,F.onDblclick)},onMouseenter:function(M){t.onMouseEnter(M,F.onMouseenter)},onMouseleave:function(M){t.onMouseLeave(M,F.onMouseleave)},onContextmenu:function(M){t.onContextMenu(M,F.onContextmenu)},class:D,\"data-row-key\":o});return g(S,z,{default:function(){return[$]}})}},OR=kIe,$Ie={name:\"ExpandIcon\",mixins:[nt],inheritAttrs:!1,props:{record:u.object,prefixCls:u.string,expandable:u.any,expanded:u.looseBool,needIndentSpaced:u.looseBool},methods:{onExpand:function(t){this.__emit(\"expand\",this.record,t)}},render:function(){var t=this.expandable,n=this.prefixCls,r=this.onExpand,a=this.needIndentSpaced,o=this.expanded;if(t){var i=o?\"expanded\":\"collapsed\";return g(\"span\",{class:\"\".concat(n,\"-expand-icon \").concat(n,\"-\").concat(i),onClick:r},null)}return a?g(\"span\",{class:\"\".concat(n,\"-expand-icon \").concat(n,\"-spaced\")},null):null}},OIe={mixins:[nt],name:\"ExpandableRow\",inheritAttrs:!1,props:{prefixCls:u.string.isRequired,rowKey:u.oneOfType([u.string,u.number]).isRequired,fixed:an(u.oneOfType([u.string,u.looseBool])),record:u.oneOfType([u.object,u.array]).isRequired,indentSize:u.number,needIndentSpaced:u.looseBool.isRequired,expandRowByClick:u.looseBool,expandIconAsCell:u.looseBool,expandIconColumnIndex:u.number,childrenColumnName:u.string,expandedRowRender:u.func,expandIcon:u.func},setup:function(t){var n=ve(\"table-store\",function(){return{}});return{expanded:x(function(){return n.expandedRowKeys.includes(t.rowKey)})}},beforeUnmount:function(){this.handleDestroy()},methods:{hasExpandIcon:function(t){var n=this.$props,r=n.expandRowByClick,a=n.expandIcon;return this.tempExpandIconAsCell||t!==this.tempExpandIconColumnIndex?!1:!!a||!r},handleExpandChange:function(t,n){var r=this.expanded,a=this.rowKey;this.__emit(\"expandedChange\",!r,t,n,a)},handleDestroy:function(){var t=this.rowKey,n=this.record;this.__emit(\"expandedChange\",!1,n,null,t,!0)},handleRowClick:function(t,n,r){var a=this.expandRowByClick;a&&this.handleExpandChange(t,r),this.__emit(\"rowClick\",t,n,r)},renderExpandIcon:function(){var t=this.prefixCls,n=this.expanded,r=this.record,a=this.needIndentSpaced,o=this.expandIcon;return o?o({prefixCls:t,expanded:n,record:r,needIndentSpaced:a,expandable:this.expandable,onExpand:this.handleExpandChange}):g($Ie,{expandable:this.expandable,prefixCls:t,onExpand:this.handleExpandChange,needIndentSpaced:a,expanded:n,record:r},null)},renderExpandIconCell:function(t){if(!!this.tempExpandIconAsCell){var n=this.prefixCls;t.push(g(\"td\",{class:\"\".concat(n,\"-expand-icon-cell\"),key:\"rc-table-expand-icon-cell\"},[this.renderExpandIcon()]))}}},render:function(){var t=this.childrenColumnName,n=this.expandedRowRender,r=this.indentSize,a=this.record,o=this.fixed,i=this.expanded;this.tempExpandIconAsCell=o!==\"right\"?this.expandIconAsCell:!1,this.tempExpandIconColumnIndex=o!==\"right\"?this.expandIconColumnIndex:-1;var l=a[t];this.expandable=!!(l||n);var s={indentSize:r,expanded:i,hasExpandIcon:this.hasExpandIcon,renderExpandIcon:this.renderExpandIcon,renderExpandIconCell:this.renderExpandIconCell,onRowClick:this.handleRowClick};return ht(this,\"default\",s)}},PIe=OIe;function Js(){}var TIe={name:\"BaseTable\",inheritAttrs:!1,props:{fixed:an(u.oneOfType([u.string,u.looseBool])),columns:u.array.isRequired,tableClassName:u.string.isRequired,hasHead:u.looseBool.isRequired,hasBody:u.looseBool.isRequired,expander:u.object.isRequired,getRowKey:u.func,isAnyColumnsFixed:u.looseBool},setup:function(){return{table:ve(\"table\",function(){return{}}),store:ve(\"table-store\",function(){return{}})}},methods:{getColumns:function(t){var n=this.$props.columns,r=n===void 0?[]:n;return(t||r).map(function(a){return P(P({},a),{className:Se(a.className,a.class)})})},handleRowHover:function(t,n){this.store.currentHoverKey=t?n:null},renderRows:function(t,n){for(var r=this,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[],o=P(P(P({},this.table.$attrs),this.table.$props),this.table.$data),i=o.sComponents,l=o.prefixCls,s=o.childrenColumnName,c=o.rowClassName,d=o.customRow,f=d===void 0?Js:d,p=o.onRowClick,v=p===void 0?Js:p,m=o.onRowDoubleClick,y=m===void 0?Js:m,b=o.onRowContextMenu,C=b===void 0?Js:b,S=o.onRowMouseEnter,w=S===void 0?Js:S,k=o.onRowMouseLeave,$=k===void 0?Js:k,O=o.rowRef,T=this.store.columnManager,_=this.getRowKey,I=this.fixed,L=this.expander,j=this.isAnyColumnsFixed,F=[],N=function(B){var M=t[B],E=_(M,B),K=typeof c==\"string\"?c:c(M,B,n),W={};T.isAnyColumnsFixed&&(W.onHover=r.handleRowHover);var Y=void 0;I===\"left\"?Y=T.leftLeafColumns:I===\"right\"?Y=T.rightLeafColumns:Y=r.getColumns(T.leafColumns);var q=\"\".concat(l,\"-row\"),J=P(P({},L.props),{fixed:I,index:B,prefixCls:q,record:M,rowKey:E,needIndentSpaced:L.needIndentSpaced,key:E,onRowClick:v,onExpandedChange:L.handleExpandChange}),ne=g(PIe,J,{default:function(Q){var ae=P(P(P({fixed:I,indent:n,record:M,index:B,prefixCls:q,childrenColumnName:s,columns:Y,rowKey:E,ancestorKeys:a,components:i,isAnyColumnsFixed:j,customRow:f,onRowDoubleClick:y,onRowContextMenu:C,onRowMouseEnter:w,onRowMouseLeave:$},W),{class:K,ref:O(M,B,n)}),Q);return g(OR,ae,null)}});F.push(ne),L.renderRows(r.renderRows,F,M,B,n,I,E,a)},D=0;D<t.length;D+=1)N(D);return F}},render:function(){var t=this,n=this.table,r=n.sComponents,a=n.prefixCls,o=n.scroll,i=n.data,l=this.$props,s=l.expander,c=l.tableClassName,d=l.hasHead,f=l.hasBody,p=l.fixed,v=this.getColumns(),m={};if(!p&&o.x&&(m.width=o.x===!0?\"auto\":o.x,m.width=typeof m.width==\"number\"?\"\".concat(m.width,\"px\"):m.width),p){var y=v.reduce(function(w,k){var $=k.width;return w+parseFloat($,10)},0);y>0&&(m.width=y+\"px\")}var b=f?r.table:\"table\",C=r.body.wrapper,S;return f&&(S=g(C,{class:\"\".concat(a,\"-tbody\")},{default:function(){return[t.renderRows(i,0)]}})),g(b,{class:c,style:m,key:\"table\"},{default:function(){return[g(vIe,{columns:v,fixed:p},null),d&&g(CIe,{expander:s,columns:v,fixed:p},null),S]}})}},PR=TIe,xIe={name:\"HeadTable\",inheritAttrs:!1,props:{fixed:an(u.oneOfType([u.string,u.looseBool])),columns:u.array.isRequired,tableClassName:u.string.isRequired,handleBodyScrollLeft:u.func.isRequired,expander:u.object.isRequired},setup:function(){return{table:ve(\"table\",{})}},render:function(){var t=this.columns,n=this.fixed,r=this.tableClassName,a=this.handleBodyScrollLeft,o=this.expander,i=this.table,l=i.prefixCls,s=i.scroll,c=i.showHeader,d=i.saveRef,f=i.useFixedHeader,p={},v=Dx({direction:\"vertical\"});if(s.y){f=!0;var m=Dx({direction:\"horizontal\",prefixCls:l});m>0&&!n&&(p.marginBottom=\"-\".concat(m,\"px\"),p.paddingBottom=\"0px\",p.minWidth=\"\".concat(v,\"px\"),p.overflowX=\"scroll\",p.overflowY=v===0?\"hidden\":\"scroll\")}return!f||!c?null:g(\"div\",{key:\"headTable\",ref:n?function(){}:d(\"headTable\"),class:Se(\"\".concat(l,\"-header\"),V({},\"\".concat(l,\"-hide-scrollbar\"),v>0)),style:p,onScroll:a},[g(PR,{tableClassName:r,hasHead:!0,hasBody:!1,fixed:n,columns:t,expander:o},null)])}},_Ie={name:\"BodyTable\",inheritAttrs:!1,props:{columns:u.array.isRequired,tableClassName:u.string.isRequired,handleBodyScroll:u.func.isRequired,handleWheel:u.func.isRequired,getRowKey:u.func.isRequired,expander:u.object.isRequired,isAnyColumnsFixed:u.looseBool},setup:function(){return{table:ve(\"table\",{})}},render:function(){var t=this.table,n=t.prefixCls,r=t.scroll,a=this.columns,o=this.tableClassName,i=this.getRowKey,l=this.handleBodyScroll,s=this.handleWheel,c=this.expander,d=this.isAnyColumnsFixed,f=this.table,p=f.useFixedHeader,v=f.saveRef,m=P({},this.table.bodyStyle);if(r.y){var y=m.maxHeight||r.y;y=typeof y==\"number\"?\"\".concat(y,\"px\"):y,m.maxHeight=y,m.overflowY=m.overflowY||\"scroll\",p=!0}r.x&&(m.overflowX=m.overflowX||\"auto\",m.WebkitTransform=\"translate3d (0, 0, 0)\",r.y||(m.overflowY=\"hidden\"));var b=g(PR,{tableClassName:o,hasHead:!p,hasBody:!0,columns:a,expander:c,getRowKey:i,isAnyColumnsFixed:d},null),C=r&&(r.x||r.y);return g(\"div\",{tabindex:C?-1:void 0,key:\"bodyTable\",class:\"\".concat(n,\"-body\"),style:m,ref:v(\"bodyTable\"),onWheel:s,onScroll:l},[b])}},EIe=function(){return{expandIconAsCell:u.looseBool,expandRowByClick:u.looseBool,expandedRowKeys:u.array,expandedRowClassName:u.func,defaultExpandAllRows:u.looseBool,defaultExpandedRowKeys:u.array,expandIconColumnIndex:u.number,expandedRowRender:u.func,expandIcon:u.func,childrenColumnName:u.string,indentSize:u.number,columnManager:u.object.isRequired,prefixCls:u.string.isRequired,data:u.array,getRowKey:u.func}},MIe={name:\"ExpandableTable\",inheritAttrs:!1,mixins:[nt],props:An(EIe(),{expandIconAsCell:!1,expandedRowClassName:function(){return\"\"},expandIconColumnIndex:0,defaultExpandAllRows:!1,defaultExpandedRowKeys:[],childrenColumnName:\"children\",indentSize:15}),setup:function(t){var n=ve(\"table-store\",function(){return{}}),r=t.data,a=t.childrenColumnName,o=t.defaultExpandAllRows,i=t.expandedRowKeys,l=t.defaultExpandedRowKeys,s=t.getRowKey,c=[],d=Je(r);if(o)for(var f=0;f<d.length;f+=1){var p=d[f];c.push(s(p,f)),d=d.concat(p[a]||[])}else c=i||l;return P(n,{expandedRowsHeight:{},expandedRowKeys:c}),{store:n}},mounted:function(){this.handleUpdated()},updated:function(){this.handleUpdated()},watch:{expandedRowKeys:function(t){var n=this;this.$nextTick(function(){n.store.expandedRowKeys=t})}},methods:{handleUpdated:function(){this.latestExpandedRows=null},handleExpandChange:function(t,n,r,a){var o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!1;r&&(r.preventDefault(),r.stopPropagation());var i=this.store.expandedRowKeys;if(t)i=[].concat(Je(i),[a]);else{var l=i.indexOf(a);l!==-1&&(i=dIe(i,a))}this.expandedRowKeys||(this.store.expandedRowKeys=i),(!this.latestExpandedRows||!Mr(this.latestExpandedRows,i))&&(this.latestExpandedRows=i,this.__emit(\"expandedRowsChange\",i)),o||this.__emit(\"expand\",t,n)},renderExpandIndentCell:function(t,n){var r=this.prefixCls,a=this.expandIconAsCell;if(!(!a||n===\"right\"||!t.length)){var o={key:\"rc-table-expand-icon-cell\",className:\"\".concat(r,\"-expand-icon-th\"),title:\"\",rowSpan:t.length};t[0].unshift(P(P({},o),{column:o}))}},renderExpandedRow:function(t,n,r,a,o,i,l){var s=this,c=this.prefixCls,d=this.expandIconAsCell,f=this.indentSize,p=o[o.length-1],v=\"\".concat(p,\"-extra-row\"),m={body:{row:\"tr\",cell:\"td\"}},y;l===\"left\"?y=this.columnManager.leftLeafColumns.value.length:l===\"right\"?y=this.columnManager.rightLeafColumns.value.length:y=this.columnManager.leafColumns.value.length;var b=[{key:\"extra-row\",customRender:function(){var S=s.store.expandedRowKeys,w=S.includes(p);return{props:{colSpan:y},children:l!==\"right\"?r({record:t,index:n,indent:i,expanded:w}):\"&nbsp;\"}}}];return d&&l!==\"right\"&&b.unshift({key:\"expand-icon-placeholder\",customRender:function(){return null}}),g(OR,{key:v,columns:b,class:a,rowKey:v,ancestorKeys:o,prefixCls:\"\".concat(c,\"-expanded-row\"),indentSize:f,indent:i,fixed:l,components:m,expandedRow:!0,hasExpandIcon:function(){}},null)},renderRows:function(t,n,r,a,o,i,l,s){var c=this.expandedRowClassName,d=this.expandedRowRender,f=this.childrenColumnName,p=r[f],v=[].concat(Je(s),[l]),m=o+1;d&&n.push(this.renderExpandedRow(r,a,d,c(r,a,o),v,m,i)),p&&n.push.apply(n,Je(t(p,m,v)))}},render:function(){var t=this.data,n=this.childrenColumnName,r=Qe(this),a=t.some(function(o){return o[n]});return ht(this,\"default\",{props:P(P({},r),this.$attrs),needIndentSpaced:a,renderRows:this.renderRows,handleExpandChange:this.handleExpandChange,renderExpandIndentCell:this.renderExpandIndentCell})}},IIe=MIe;function NIe(e){var t=H(e),n=t.value,r=[],a=H();function o(i){en.cancel(a.value),r.push(i),a.value=en(function(){var l=r;r=[],l.forEach(function(s){n=s(n)}),t.value=n})}return Lt(function(){en.cancel(a.value)}),[t,o]}function AIe(e){var t=function f(p){var v=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,m=[];return p.forEach(function(y){y.fixed=v||y.fixed,y.children?m.push.apply(m,Je(f(y.children,y.fixed))):m.push(y)}),m},n=x(function(){var f=function p(v){var m=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},b=arguments.length>3&&arguments[3]!==void 0?arguments[3]:[],C=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!1;b[m]=b[m]||[];var S=[],w=function($){var O=b.length-m;$&&!$.children&&O>1&&(!$.rowSpan||$.rowSpan<O)&&($.rowSpan=O)};return v.forEach(function(k,$){var O=P({},k);O.fixed=C||k.fixed,b[m].push(O),y.colSpan=y.colSpan||0,O.children&&O.children.length>0?(O.children=p(O.children,m+1,O,b,O.fixed),y.colSpan+=O.colSpan):y.colSpan+=1;for(var T=0;T<b[m].length-1;T+=1)w(b[m][T]);$+1===v.length&&w(O),S.push(O)}),S};return f(e.value)}),r=x(function(){return e.value.some(function(f){return!!f.fixed})}),a=x(function(){return e.value.some(function(f){return f.fixed===\"left\"||f.fixed===!0})}),o=x(function(){return e.value.some(function(f){return f.fixed===\"right\"})}),i=x(function(){return n.value.filter(function(f){return f.fixed===\"left\"||f.fixed===!0})}),l=x(function(){return n.value.filter(function(f){return f.fixed===\"right\"})}),s=x(function(){return t(e.value)}),c=x(function(){return t(i.value)}),d=x(function(){return t(l.value)});return{groupedColumns:n,isAnyColumnsFixed:r,isAnyColumnsLeftFixed:a,isAnyColumnsRightFixed:o,leftColumns:i,rightColumns:l,leafColumns:s,leftLeafColumns:c,rightLeafColumns:d}}function DIe(e,t){var n=H({left:[],right:[]}),r=H();return ce(t,function(){r.value=t.value.length},{immediate:!0}),ce([e,r],function(){for(var a=[],o=[],i=0,l=0,s=0;s<r.value;s+=1){a[s]=i,i+=e.value[s]||0;var c=r.value-s-1;o[c]=l,l+=e.value[c]||0}n.value={left:a,right:o}}),n}var RIe=G({name:\"Table\",mixins:[nt],inheritAttrs:!1,props:An({data:u.array,useFixedHeader:u.looseBool,columns:u.array,prefixCls:u.string,bodyStyle:u.object,rowKey:u.oneOfType([u.string,u.func]),rowClassName:u.oneOfType([u.string,u.func]),customRow:u.func,customHeaderRow:u.func,showHeader:u.looseBool,title:u.func,id:u.string,footer:u.func,emptyText:u.any,scroll:u.object,rowRef:u.func,components:u.shape({table:u.any,header:u.shape({wrapper:u.any,row:u.any,cell:u.any}).loose,body:u.shape({wrapper:u.any,row:u.any,cell:u.any}).loose}).loose,expandIconAsCell:u.looseBool,expandedRowKeys:u.array,expandedRowClassName:u.func,defaultExpandAllRows:u.looseBool,defaultExpandedRowKeys:u.array,expandIconColumnIndex:u.number,expandedRowRender:u.func,childrenColumnName:u.string,indentSize:u.number,expandRowByClick:u.looseBool,expandIcon:u.func,tableLayout:u.string,transformCellText:u.func},{data:[],useFixedHeader:!1,rowKey:\"key\",rowClassName:function(){return\"\"},prefixCls:\"rc-table\",bodyStyle:{},showHeader:!0,scroll:{},rowRef:function(){return null},emptyText:function(){return\"No Data\"},customHeaderRow:function(){}}),setup:function(t){var n=AIe(yn(t,\"columns\")),r=x(function(){return hIe(n.leafColumns.value)}),a=NIe(new Map),o=fn(a,2),i=o[0],l=o[1],s=x(function(){return r.value.map(function(w){return i.value.get(w)})}),c=DIe(s,n.leafColumns),d=function(k,$){l(function(O){if(O.get(k)!==$){var T=new Map(O);return T.set(k,$),T}return O})},f=x(function(){return n.leafColumns.value.map(function(w,k){return $R(k,k,n.leafColumns.value,c.value)})}),p=bt({currentHoverKey:null,fixedColumnsHeadRowsHeight:[],fixedColumnsBodyRowsHeight:{},expandedRowsHeight:{},expandedRowKeys:[],columnManager:n,fixedInfoList:f,stickyOffsets:c});ot(\"table-store\",p);var v=H(),m=H(!1),y=H(!1),b=x(function(){return t.scroll&&pIe(t.scroll.x)}),C=function(k){var $=k.scrollWidth,O=k.clientWidth,T=k.scrollLeft;m.value=T>0,y.value=T<$-O};ur(function(){Ne(function(){b.value&&C(v.value.$el)})}),et(function(){Ne(function(){b.value&&C(v.value.$el)})});var S=function(){b.value&&C(v.value.$el)};return{bodyRef:v,store:p,onColumnResize:d,columnManager:n,onScroll:C,pingedLeft:m,pingedRight:y,onFullTableResize:S}},data:function(){return this.preData=Je(this.data),{sComponents:ps(L$({table:\"table\",header:{wrapper:\"thead\",row:\"tr\",cell:\"th\"},body:{wrapper:\"tbody\",row:\"tr\",cell:\"td\"}},this.components))}},computed:{dataLen:function(){return this.$props.data.length}},watch:{components:function(){this._components=L$({table:\"table\",header:{wrapper:\"thead\",row:\"tr\",cell:\"th\"},body:{wrapper:\"tbody\",row:\"tr\",cell:\"td\"}},this.components)},dataLen:function(t,n){var r=this;(t===0||n===0)&&this.hasScrollX()&&Ne(function(){r.resetScrollX()})}},created:function(){ot(\"table\",this),this.setScrollPosition(\"left\"),this.debouncedWindowResize=cIe(this.handleWindowResize,150)},mounted:function(){var t=this;this.$nextTick(function(){t.columnManager.isAnyColumnsFixed.value&&(t.handleWindowResize(),t.resizeEvent=Kn(window,\"resize\",t.debouncedWindowResize)),t.ref_headTable&&(t.ref_headTable.scrollLeft=0),t.ref_bodyTable&&(t.ref_bodyTable.scrollLeft=0)})},updated:function(){var t=this;this.$nextTick(function(){t.columnManager.isAnyColumnsFixed.value&&(t.handleWindowResize(),t.resizeEvent||(t.resizeEvent=Kn(window,\"resize\",t.debouncedWindowResize)))})},beforeUnmount:function(){this.resizeEvent&&this.resizeEvent.remove(),this.debouncedWindowResize&&this.debouncedWindowResize.cancel()},methods:{getRowKey:function(t,n){var r=this.rowKey,a=typeof r==\"function\"?r(t,n):t[r];return on(a!==void 0,\"Each record in table should have a unique `key` prop,or set `rowKey` to an unique primary key.\"),a===void 0?n:a},setScrollPosition:function(t){if(this.scrollPosition=t,this.tableNode){var n=this.prefixCls;t===\"both\"?g1(this.tableNode).remove(new RegExp(\"^\".concat(n,\"-scroll-position-.+$\"))).add(\"\".concat(n,\"-scroll-position-left\")).add(\"\".concat(n,\"-scroll-position-right\")):g1(this.tableNode).remove(new RegExp(\"^\".concat(n,\"-scroll-position-.+$\"))).add(\"\".concat(n,\"-scroll-position-\").concat(t))}},setScrollPositionClassName:function(){var t=this.ref_bodyTable,n=t.scrollLeft===0,r=t.scrollLeft+1>=t.children[0].getBoundingClientRect().width-t.getBoundingClientRect().width;n&&r?this.setScrollPosition(\"both\"):n?this.setScrollPosition(\"left\"):r?this.setScrollPosition(\"right\"):this.scrollPosition!==\"middle\"&&this.setScrollPosition(\"middle\")},isTableLayoutFixed:function(){var t=this.$props,n=t.tableLayout,r=t.columns,a=r===void 0?[]:r,o=t.useFixedHeader,i=t.scroll,l=i===void 0?{}:i;return typeof n!=\"undefined\"?n===\"fixed\":!!(a.some(function(s){var c=s.ellipsis;return!!c})||o||l.y||l.x&&l.x!==!0&&l.x!==\"max-content\")},handleWindowResize:function(){this.syncFixedTableRowHeight(),this.setScrollPositionClassName()},syncFixedTableRowHeight:function(){var t=this.tableNode.getBoundingClientRect();if(!(t.height!==void 0&&t.height<=0)){var n=this.prefixCls,r=this.ref_headTable?this.ref_headTable.querySelectorAll(\"thead\"):this.ref_bodyTable.querySelectorAll(\"thead\"),a=this.ref_bodyTable.querySelectorAll(\".\".concat(n,\"-row\"))||[],o=[].map.call(r,function(s){return s.getBoundingClientRect().height?s.getBoundingClientRect().height-.5:\"auto\"}),i=this.store,l=[].reduce.call(a,function(s,c){var d=c.getAttribute(\"data-row-key\"),f=c.getBoundingClientRect().height||i.fixedColumnsBodyRowsHeight[d]||\"auto\";return s[d]=f,s},{});Mr(i.fixedColumnsHeadRowsHeight,o)&&Mr(i.fixedColumnsBodyRowsHeight,l)||(this.store.fixedColumnsHeadRowsHeight=o,this.store.fixedColumnsBodyRowsHeight=l)}},resetScrollX:function(){this.ref_headTable&&(this.ref_headTable.scrollLeft=0),this.ref_bodyTable&&(this.ref_bodyTable.scrollLeft=0)},hasScrollX:function(){var t=this.scroll,n=t===void 0?{}:t;return\"x\"in n},handleBodyScrollLeft:function(t){var n=t.target,r=this.scroll,a=r===void 0?{}:r,o=this.ref_headTable,i=this.ref_bodyTable;n.scrollLeft!==this.lastScrollLeft&&a.x&&(n===i&&o?o.scrollLeft=n.scrollLeft:n===o&&i&&(i.scrollLeft=n.scrollLeft),this.setScrollPositionClassName()),this.lastScrollLeft=n.scrollLeft},handleBodyScrollTop:function(t){var n=t.target;if(t.currentTarget===n){var r=this.scroll,a=r===void 0?{}:r,o=this.ref_headTable,i=this.ref_bodyTable,l=this.ref_fixedColumnsBodyLeft,s=this.ref_fixedColumnsBodyRight;if(n.scrollTop!==this.lastScrollTop&&a.y&&n!==o){var c=n.scrollTop;l&&n!==l&&(l.scrollTop=c),s&&n!==s&&(s.scrollTop=c),i&&n!==i&&(i.scrollTop=c)}this.lastScrollTop=n.scrollTop}},handleBodyScroll:function(t){this.onScroll(t.target),this.handleBodyScrollLeft(t),this.handleBodyScrollTop(t)},handleWheel:function(t){var n=this.$props.scroll,r=n===void 0?{}:n;if(window.navigator.userAgent.match(/Trident\\/7\\./)&&r.y){t.preventDefault();var a=t.deltaY,o=t.target,i=this.ref_bodyTable,l=this.ref_fixedColumnsBodyLeft,s=this.ref_fixedColumnsBodyRight,c=0;this.lastScrollTop?c=this.lastScrollTop+a:c=a,l&&o!==l&&(l.scrollTop=c),s&&o!==s&&(s.scrollTop=c),i&&o!==i&&(i.scrollTop=c)}},saveRef:function(t){var n=this;return function(r){n[\"ref_\".concat(t)]=r}},saveTableNodeRef:function(t){this.tableNode=t},renderMainTable:function(){var t=this.scroll,n=this.prefixCls,r=this.columnManager.isAnyColumnsFixed.value,a=r||t.x||t.y,o=[this.renderTable({columns:this.columnManager.groupedColumns.value,isAnyColumnsFixed:r}),this.renderEmptyText(),this.renderFooter()];return a?g(zo,{onResize:this.onFullTableResize},{default:function(){return[g(\"div\",{class:\"\".concat(n,\"-scroll\")},[o])]}}):o},renderTable:function(t){var n=t.columns,r=t.isAnyColumnsFixed,a=this.prefixCls,o=this.scroll,i=o===void 0?{}:o,l=i.x?\"\".concat(a,\"-fixed\"):\"\",s=g(xIe,{key:\"head\",columns:n,tableClassName:l,handleBodyScrollLeft:this.handleBodyScrollLeft,expander:this.expander},null),c=g(_Ie,{key:\"body\",columns:n,tableClassName:l,getRowKey:this.getRowKey,handleWheel:this.handleWheel,handleBodyScroll:this.handleBodyScroll,expander:this.expander,isAnyColumnsFixed:r,ref:\"bodyRef\"},null);return[s,c]},renderTitle:function(){var t=this.title,n=this.prefixCls,r=this.data;return t?g(\"div\",{class:\"\".concat(n,\"-title\"),key:\"title\"},[t(r)]):null},renderFooter:function(){var t=this.footer,n=this.prefixCls,r=this.data;return t?g(\"div\",{class:\"\".concat(n,\"-footer\"),key:\"footer\"},[t(r)]):null},renderEmptyText:function(){var t=this.emptyText,n=this.prefixCls,r=this.data;if(r.length)return null;var a=\"\".concat(n,\"-placeholder\");return g(\"div\",{class:a,key:\"emptyText\"},[typeof t==\"function\"?t():t])}},render:function(){var t,n=this,r=P(P({},Qe(this)),this.$attrs),a=this.columnManager,o=this.getRowKey,i=r.prefixCls,l=Se(r.prefixCls,r.class,(t={},V(t,\"\".concat(i,\"-fixed-header\"),r.useFixedHeader||r.scroll&&r.scroll.y),V(t,\"\".concat(i,\"-scroll-position-left \").concat(i,\"-scroll-position-right\"),this.scrollPosition===\"both\"),V(t,\"\".concat(i,\"-scroll-position-\").concat(this.scrollPosition),this.scrollPosition!==\"both\"),V(t,\"\".concat(i,\"-layout-fixed\"),this.isTableLayoutFixed()),V(t,\"\".concat(i,\"-ping-left\"),this.pingedLeft),V(t,\"\".concat(i,\"-ping-right\"),this.pingedRight),t)),s=fIe(r),c=P(P({},r),{columnManager:a,getRowKey:o});return g(IIe,c,{default:function(f){return n.expander=f,g(\"div\",le({ref:n.saveTableNodeRef,class:l,style:r.style,id:r.id},s),[n.renderTitle(),g(\"div\",{class:\"\".concat(i,\"-content\")},[n.renderMainTable()])])}})}}),LIe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M349 838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V642H349v196zm531.1-684H143.9c-24.5 0-39.8 26.7-27.5 48l221.3 376h348.8l221.3-376c12.1-21.3-3.2-48-27.7-48z\"}}]},name:\"filter\",theme:\"filled\"},FIe=LIe;function Lx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){BIe(e,a,n[a])})}return e}function BIe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var BS=function(t,n){var r=Lx({},t,n.attrs);return g(Et,Lx({},r,{icon:FIe}),null)};BS.displayName=\"FilterFilled\";BS.inheritAttrs=!1;var VIe=BS,TR=function(t,n){var r=n.slots,a;return g(\"div\",{class:t.class,onClick:function(i){return i.stopPropagation()}},[(a=r.default)===null||a===void 0?void 0:a.call(r)])};TR.inheritAttrs=!1;var Fx=TR;$S();var zIe=u.shape({text:u.string,value:u.string,children:u.array}).loose,HIe={title:u.VNodeChild,key:u.oneOfType([u.string,u.number]),dataIndex:u.string,customRender:u.func,customCell:u.func,customHeaderCell:u.func,align:u.oneOf(rt(\"left\",\"right\",\"center\")),ellipsis:u.looseBool,filters:u.arrayOf(zIe),onFilter:{type:Function},filterMultiple:u.looseBool,filterDropdown:u.any,filterDropdownVisible:u.looseBool,onFilterDropdownVisibleChange:{type:Function},sorter:u.oneOfType([u.looseBool,u.func]),defaultSortOrder:u.oneOf(rt(\"ascend\",\"descend\")),colSpan:u.number,width:u.oneOfType([u.string,u.number]),className:u.string,fixed:an(u.oneOfType([u.looseBool,u.oneOf(rt(\"left\",\"right\"))])),filterIcon:u.any,filteredValue:u.array,filtered:u.looseBool,defaultFilteredValue:u.array,sortOrder:an(u.oneOfType([u.looseBool,u.oneOf(rt(\"ascend\",\"descend\"))])),sortDirections:u.array},xR=u.shape({filterTitle:u.string,filterConfirm:u.any,filterReset:u.any,emptyText:u.any,selectAll:u.any,selectInvert:u.any,sortTitle:u.string,expand:u.string,collapse:u.string}).loose,_R=u.oneOf(rt(\"checkbox\",\"radio\")),jIe={type:_R,selectedRowKeys:u.array,getCheckboxProps:u.func,selections:an(u.oneOfType([u.array,u.looseBool])),hideDefaultSelections:u.looseBool,fixed:u.looseBool,columnWidth:u.oneOfType([u.string,u.number]),selectWay:u.oneOf(rt(\"onSelect\",\"onSelectMultiple\",\"onSelectAll\",\"onSelectInvert\")),columnTitle:u.any},KIe=N7(),WIe={prefixCls:u.string,dropdownPrefixCls:u.string,rowSelection:u.oneOfType([u.shape(jIe).loose,Object]),pagination:an(u.oneOfType([u.shape(KIe).loose,u.looseBool])),size:u.oneOf(rt(\"default\",\"middle\",\"small\",\"large\")),dataSource:u.array,components:u.object,columns:{type:Array},rowKey:u.oneOfType([u.string,u.func]),rowClassName:u.func,expandedRowRender:u.any,defaultExpandAllRows:u.looseBool,defaultExpandedRowKeys:u.array,expandedRowKeys:u.array,expandIconAsCell:u.looseBool,expandIconColumnIndex:u.number,expandRowByClick:u.looseBool,loading:u.oneOfType([u.shape(I7()).loose,u.looseBool]),locale:xR,indentSize:u.number,customRow:u.func,customHeaderRow:u.func,useFixedHeader:u.looseBool,bordered:u.looseBool,showHeader:u.looseBool,footer:u.func,title:u.func,scroll:{type:Object},childrenColumnName:u.oneOfType([u.array,u.string]),bodyStyle:u.style,sortDirections:{type:Array},tableLayout:u.string,getPopupContainer:u.func,expandIcon:u.func,transformCellText:u.func,onExpandedRowsChange:u.func,onExpand:u.func,onChange:u.func,onRowClick:u.func},UIe={propsSymbol:u.any,store:u.any,locale:u.any,disabled:u.looseBool,getCheckboxPropsByItem:u.func,getRecordKey:u.func,data:u.array,prefixCls:u.string,hideDefaultSelections:u.looseBool,selections:u.oneOfType([u.array,u.looseBool]),getPopupContainer:u.func,onSelect:u.func},YIe={store:u.any,type:_R,defaultSelection:u.array,rowIndex:u.oneOfType([u.string,u.number]),name:u.string,disabled:u.looseBool,id:u.string},qIe={locale:xR,selectedKeys:u.array,column:u.object,confirmFilter:u.func,prefixCls:u.string,dropdownPrefixCls:u.string,getPopupContainer:u.func,handleFilter:u.func},GIe={methods:{setState:function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0,r=typeof t==\"function\"?t(this,this.$props):t;if(this.getDerivedStateFromProps){var a=this.getDerivedStateFromProps(Qe(this),P(P({},this),r));if(a===null)return;r=P(P({},r),a||{})}P(this,r),this._.isMounted&&this.$forceUpdate(),Ne(function(){n&&n()})},__emit:function(){var t=[].slice.call(arguments,0),n=t[0];n=\"on\".concat(n[0].toUpperCase()).concat(n.substring(1));var r=this.$props[n]||this.$attrs[n];if(t.length&&r)if(Array.isArray(r))for(var a=0,o=r.length;a<o;a++)r[a].apply(r,Je(t.slice(1)));else r.apply(void 0,Je(t.slice(1)))}}};function Bx(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:\"children\",n=[],r=function a(o){o.forEach(function(i){if(i[t]){var l=P({},i);delete l[t],n.push(l),i[t].length>0&&a(i[t])}else n.push(i)})};return r(e),n}function Zp(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:\"children\";return e.map(function(r,a){var o={};return r[n]&&(o[n]=Zp(r[n],t,n)),P(P({},t(r,a)),o)})}function _d(e,t){return e.reduce(function(n,r){if(t(r)&&n.push(r),r.children){var a=_d(r.children,t);n.push.apply(n,Je(a))}return n},[])}function ER(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return(e||[]).forEach(function(n){var r=n.value,a=n.children;t[r.toString()]=r,ER(a,t)}),t}function kb(e){e.stopPropagation()}var XIe=G({name:\"FilterMenu\",mixins:[GIe],inheritAttrs:!1,props:Rn(qIe,{column:{}}),setup:function(t){var n=x(function(){return t.selectedKeys}),r=x(function(){return\"filterDropdownVisible\"in t.column?t.column.filterDropdownVisible:!1}),a=x(function(){return ER(t.column.filters)}),o=bt({neverShown:!1,sSelectedKeys:n.value,sKeyPathOfSelectedItem:{},sVisible:r.value,sValueKeys:a.value});return ce(n,function(){o.sSelectedKeys=n.value}),ce(r,function(){o.sVisible=r.value}),ce(a,function(){o.sValueKeys=a.value}),o},methods:{getDropdownVisible:function(){return!!this.sVisible},setSelectedKeys:function(t){var n=t.selectedKeys;this.setState({sSelectedKeys:n})},setVisible:function(t){var n=this.column;\"filterDropdownVisible\"in n||this.setState({sVisible:t}),n.onFilterDropdownVisibleChange&&n.onFilterDropdownVisibleChange(t)},handleClearFilters:function(){this.setState({sSelectedKeys:[]},this.handleConfirm)},handleConfirm:function(){this.setVisible(!1),this.$forceUpdate(),Ne(this.confirmFilter2)},onVisibleChange:function(t){this.setVisible(t);var n=this.$props.column;!t&&!(n.filterDropdown instanceof Function)&&this.confirmFilter2()},handleMenuItemClick:function(t){var n=this.sSelectedKeys;if(!(!t.keyPath||t.keyPath.length<=1)){var r=this.sKeyPathOfSelectedItem;n&&n.indexOf(t.key)>=0?delete r[t.key]:r[t.key]=t.keyPath,this.setState({sKeyPathOfSelectedItem:r})}},hasSubMenu:function(){var t=this.column.filters,n=t===void 0?[]:t;return n.some(function(r){return!!(r.children&&r.children.length>0)})},confirmFilter2:function(){var t=this.$props,n=t.column,r=t.selectedKeys,a=t.confirmFilter,o=this.sSelectedKeys,i=this.sValueKeys,l=n.filterDropdown;Mr(o,r)||a(n,l?o:o.map(function(s){return i[s]}).filter(function(s){return s!==void 0}))},renderMenus:function(t){var n=this,r=this.$props,a=r.dropdownPrefixCls,o=r.prefixCls;return t.map(function(i){if(i.children&&i.children.length>0){var l=n.sKeyPathOfSelectedItem,s=Object.keys(l).some(function(d){return l[d].indexOf(i.value)>=0}),c=Se(\"\".concat(o,\"-dropdown-submenu\"),V({},\"\".concat(a,\"-submenu-contain-selected\"),s));return g(sc,{title:i.text,popupClassName:c,key:i.value},{default:function(){return[n.renderMenus(i.children)]}})}return n.renderMenuItem(i)})},renderFilterIcon:function(){var t,n,r,a=this.column,o=this.locale,i=this.prefixCls,l=this.selectedKeys,s=l&&l.length>0,c=a.filterIcon;typeof c==\"function\"&&(c=c({filtered:s,column:a}));var d=Se((t={},V(t,\"\".concat(i,\"-selected\"),\"filtered\"in a?a.filtered:s),V(t,\"\".concat(i,\"-open\"),this.getDropdownVisible()),t));return c?c.length===1&&zn(c[0])?Ot(c[0],{title:((n=c.props)===null||n===void 0?void 0:n.title)||o.filterTitle,onClick:kb,class:Se(\"\".concat(i,\"-icon\"),d,(r=c.props)===null||r===void 0?void 0:r.class)}):g(\"span\",{class:Se(\"\".concat(i,\"-icon\"),d),onClick:kb},[c]):g(VIe,{title:o.filterTitle,class:d,onClick:kb},null)},renderMenuItem:function(t){var n=this.column,r=this.sSelectedKeys,a=\"filterMultiple\"in n?n.filterMultiple:!0,o=a?g(ro,{checked:r&&r.indexOf(t.value)>=0},null):g(_r,{checked:r&&r.indexOf(t.value)>=0},null);return g(fl,{key:t.value},{default:function(){return[o,g(\"span\",null,[t.text])]}})}},render:function(){var t=this,n=this.sSelectedKeys,r=this.column,a=this.locale,o=this.prefixCls,i=this.dropdownPrefixCls,l=this.getPopupContainer,s=\"filterMultiple\"in r?r.filterMultiple:!0,c=Se(V({},\"\".concat(i,\"-menu-without-submenu\"),!this.hasSubMenu())),d=r.filterDropdown;d instanceof Function&&(d=d({prefixCls:\"\".concat(i,\"-custom\"),setSelectedKeys:function(v){return t.setSelectedKeys({selectedKeys:v})},selectedKeys:n,confirm:this.handleConfirm,clearFilters:this.handleClearFilters,filters:r.filters,visible:this.getDropdownVisible(),column:r}));var f=d?g(Fx,{class:\"\".concat(o,\"-dropdown\")},{default:function(){return[d]}}):g(Fx,{class:\"\".concat(o,\"-dropdown\")},{default:function(){return[g(jr,{multiple:s,onClick:t.handleMenuItemClick,prefixCls:\"\".concat(i,\"-menu\"),class:c,onSelect:t.setSelectedKeys,onDeselect:t.setSelectedKeys,selectedKeys:n,getPopupContainer:l},{default:function(){return[t.renderMenus(r.filters)]}}),g(\"div\",{class:\"\".concat(o,\"-dropdown-btns\")},[g(\"a\",{class:\"\".concat(o,\"-dropdown-link confirm\"),onClick:t.handleConfirm},[a.filterConfirm]),g(\"a\",{class:\"\".concat(o,\"-dropdown-link clear\"),onClick:t.handleClearFilters},[a.filterReset])])]}});return g(hi,{trigger:[\"click\"],placement:\"bottomRight\",visible:this.getDropdownVisible(),onVisibleChange:this.onVisibleChange,getPopupContainer:l,forceRender:!0,overlay:f},{default:function(){return[t.renderFilterIcon()]}})}}),ZIe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},JIe=G({name:\"SelectionBox\",mixins:[nt],inheritAttrs:!1,props:YIe,setup:function(t){return{checked:x(function(){var n=t.store,r=t.defaultSelection,a=t.rowIndex,o=!1;return n.selectionDirty?o=n.selectedRowKeys.indexOf(a)>=0:o=n.selectedRowKeys.indexOf(a)>=0||r.indexOf(a)>=0,o})}},render:function(){var t=P(P({},Qe(this)),this.$attrs),n=t.type,r=t.rowIndex,a=ZIe(t,[\"type\",\"rowIndex\"]),o=this.checked,i=P({checked:o},a);return n===\"radio\"?(i.value=r,g(_r,i,null)):g(ro,i,null)}});function Ql(e){var t=e.store,n=e.getCheckboxPropsByItem,r=e.getRecordKey,a=e.data,o=e.type,i=e.byDefaultChecked;return i?a[o](function(l,s){return n(l,s).defaultChecked}):a[o](function(l,s){return t.selectedRowKeys.indexOf(r(l,s))>=0})}function QIe(e){var t=e.store,n=e.data;if(!n.length)return!1;var r=Ql(P(P({},e),{data:n,type:\"some\",byDefaultChecked:!1}))&&!Ql(P(P({},e),{data:n,type:\"every\",byDefaultChecked:!1})),a=Ql(P(P({},e),{data:n,type:\"some\",byDefaultChecked:!0}))&&!Ql(P(P({},e),{data:n,type:\"every\",byDefaultChecked:!0}));return t.selectionDirty?r:r||a}function eNe(e){var t=e.store,n=e.data;return n.length?t.selectionDirty?Ql(P(P({},e),{data:n,type:\"every\",byDefaultChecked:!1})):Ql(P(P({},e),{data:n,type:\"every\",byDefaultChecked:!1}))||Ql(P(P({},e),{data:n,type:\"every\",byDefaultChecked:!0})):!1}var tNe=G({name:\"SelectionCheckboxAll\",mixins:[nt],inheritAttrs:!1,props:UIe,setup:function(t){return{defaultSelections:[],checked:x(function(){return eNe(t)}),indeterminate:x(function(){return QIe(t)})}},created:function(){var t=this.$props;this.defaultSelections=t.hideDefaultSelections?[]:[{key:\"all\",text:t.locale.selectAll},{key:\"invert\",text:t.locale.selectInvert}]},methods:{handleSelectAllChange:function(t){var n=t.target.checked;this.$emit(\"select\",n?\"all\":\"removeAll\",0,null)},renderMenus:function(t){var n=this;return t.map(function(r,a){return g(jr.Item,{key:r.key||a},{default:function(){return[g(\"div\",{onClick:function(){n.$emit(\"select\",r.key,a,r.onSelect)}},[r.text])]}})})}},render:function(){var t=this,n=this.disabled,r=this.prefixCls,a=this.selections,o=this.getPopupContainer,i=this.checked,l=this.indeterminate,s=\"\".concat(r,\"-selection\"),c=null;if(a){var d=Array.isArray(a)?this.defaultSelections.concat(a):this.defaultSelections,f=g(jr,{class:\"\".concat(s,\"-menu\"),selectedKeys:[]},{default:function(){return[t.renderMenus(d)]}});c=d.length>0?g(hi,{getPopupContainer:o,overlay:f},{default:function(){return[g(\"div\",{class:\"\".concat(s,\"-down\")},[g(Rs,null,null)])]}}):null}return g(\"div\",{class:s},[g(ro,{class:Se(V({},\"\".concat(s,\"-select-all-custom\"),c)),checked:i,indeterminate:l,disabled:n,onChange:this.handleSelectAllChange},null),c])}}),nNe=G({name:\"ATableColumn\",props:HIe,render:function(){return null}}),rNe=G({name:\"ATableColumnGroup\",props:{fixed:an(u.oneOfType([u.looseBool,u.oneOf(rt(\"left\",\"right\"))])),title:u.any},__ANT_TABLE_COLUMN_GROUP:!0,render:function(){return null}}),aNe={store:u.object,rowKey:u.oneOfType([u.string,u.number]),prefixCls:u.string};function oNe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"tr\",t=G({name:\"BodyRow\",inheritAttrs:!1,props:aNe,setup:function(r){return{selected:x(function(){var a;return((a=r.store)===null||a===void 0?void 0:a.selectedRowKeys.indexOf(r.rowKey))>=0})}},render:function(){var r,a=this,o=bn(P(P({},this.$props),this.$attrs),[\"prefixCls\",\"rowKey\",\"store\",\"class\"]),i=(r={},V(r,\"\".concat(this.prefixCls,\"-row-selected\"),this.selected),V(r,this.$attrs.class,!!this.$attrs.class),r);return g(e,le({class:i},o),{default:function(){return[ht(a)]}})}});return t}var Vx=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function zx(){}function iNe(e){e.stopPropagation()}function Zh(e){return e.rowSelection||{}}function Wa(e,t){return e.key||e.dataIndex||t}function Hx(e,t){return e&&t&&e.key&&e.key===t.key?!0:e===t||Mr(e,t,function(n,r){if(typeof n==\"function\"&&typeof r==\"function\")return n===r||n.toString()===r.toString();if(Array.isArray(n)&&Array.isArray(r))return n===r||Mr(n,r)})}var jx={onChange:zx,onShowSizeChange:zx},lNe={},Kx=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=t&&t.body&&t.body.row;return P(P({},t),{body:P(P({},t.body),{row:oNe(n)})})};function sNe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return e===t||[\"table\",\"header\",\"body\"].every(function(n){return Mr(e[n],t[n])})}function E1(e,t){return _d(t||(e||{}).columns||[],function(n){return typeof n.filteredValue!=\"undefined\"})}function Wx(e,t){var n={};return E1(e,t).forEach(function(r){var a=Wa(r);n[a]=r.filteredValue}),n}function uNe(e,t){return Object.keys(t).length!==Object.keys(e.filters).length?!0:Object.keys(t).some(function(n){return t[n]!==e.filters[n]})}var MR=Rn(WIe,{dataSource:[],useFixedHeader:!1,size:\"default\",loading:!1,bordered:!1,indentSize:20,locale:{},rowKey:\"key\",showHeader:!0,sortDirections:[\"ascend\",\"descend\"],childrenColumnName:\"children\"}),$b=G({name:\"Table\",mixins:[nt],inheritAttrs:!1,Column:nNe,ColumnGroup:rNe,props:MR,setup:function(t){var n=bt({selectedRowKeys:Zh(t).selectedRowKeys||[],selectionDirty:!1});return{vcTable:null,checkboxPropsCache:{},store:n,configProvider:ve(\"configProvider\",St)}},data:function(){var t=Qe(this);on(!t.expandedRowRender||!(\"scroll\"in t),\"`expandedRowRender` and `scroll` are not compatible. Please use one of them at one time.\");var n=this.getDefaultSortOrder,r=this.getDefaultFilters,a=this.getDefaultPagination;return P(P({},n(t.columns||[])),{sFilters:r(t.columns),sPagination:a(this.$props),pivot:void 0,sComponents:ps(Kx(this.components)),filterDataCnt:0})},watch:{pagination:{handler:function(t){this.setState(function(n){var r=P(P(P({},jx),n.sPagination),t);return r.current=r.current||1,r.pageSize=r.pageSize||10,{sPagination:t!==!1?r:lNe}})},deep:!0},rowSelection:{handler:function(t,n){if(t&&\"selectedRowKeys\"in t){this.store.selectedRowKeys=t.selectedRowKeys||[];var r=this.rowSelection;r&&t.getCheckboxProps!==r.getCheckboxProps&&(this.checkboxPropsCache={})}else n&&!t&&(this.store.selectedRowKeys=[])},deep:!0},dataSource:function(){this.store.selectionDirty=!1,this.checkboxPropsCache={}},columns:function(t){var n=E1({columns:t},t);if(n.length>0){var r=Wx({columns:t},t),a=P({},this.sFilters);Object.keys(r).forEach(function(o){a[o]=r[o]}),uNe({filters:this.sFilters},a)&&this.setState({sFilters:a})}},components:{handler:function(t,n){if(!sNe(t,n)){var r=Kx(t);this.setState({sComponents:r})}},deep:!0}},updated:function(){var t=this.columns,n=this.sSortColumn,r=this.sSortOrder;if(this.getSortOrderColumns(t).length>0){var a=this.getSortStateFromColumns(t);(!Hx(a.sSortColumn,n)||a.sSortOrder!==r)&&this.setState(a)}},methods:{setTableRef:function(t){this.vcTable=t},getCheckboxPropsByItem:function(t,n){var r=Zh(this.$props);if(!r.getCheckboxProps)return{};var a=this.getRecordKey(t,n);return this.checkboxPropsCache[a]||(this.checkboxPropsCache[a]=r.getCheckboxProps(t)||{}),this.checkboxPropsCache[a]},getDefaultSelection:function(){var t=this,n=Zh(this.$props);return n.getCheckboxProps?this.getFlatData().filter(function(r,a){return t.getCheckboxPropsByItem(r,a).defaultChecked}).map(function(r,a){return t.getRecordKey(r,a)}):[]},getDefaultPagination:function(t){var n=kt(t.pagination)===\"object\"?t.pagination:{},r;\"current\"in n?r=n.current:\"defaultCurrent\"in n&&(r=n.defaultCurrent);var a;return\"pageSize\"in n?a=n.pageSize:\"defaultPageSize\"in n&&(a=n.defaultPageSize),this.hasPagination(t)?P(P(P({},jx),n),{current:r||1,pageSize:a||10}):{}},getSortOrderColumns:function(t){return _d(t||this.columns||[],function(n){return\"sortOrder\"in n})},getDefaultFilters:function(t){var n=Wx({columns:this.columns},t),r=_d(t||[],function(o){return typeof o.defaultFilteredValue!=\"undefined\"}),a=r.reduce(function(o,i){var l=Wa(i);return o[l]=i.defaultFilteredValue,o},{});return P(P({},a),n)},getDefaultSortOrder:function(t){var n=this.getSortStateFromColumns(t),r=_d(t||[],function(a){return a.defaultSortOrder!=null})[0];return r&&!n.sortColumn?{sSortColumn:r,sSortOrder:r.defaultSortOrder}:n},getSortStateFromColumns:function(t){var n=this.getSortOrderColumns(t).filter(function(r){return r.sortOrder})[0];return n?{sSortColumn:n,sSortOrder:n.sortOrder}:{sSortColumn:null,sSortOrder:null}},getMaxCurrent:function(t){var n=this.sPagination,r=n.current,a=n.pageSize;return(r-1)*a>=t?Math.floor((t-1)/a)+1:r},getRecordKey:function(t,n){var r=this.rowKey,a=typeof r==\"function\"?r(t,n):t[r];return on(a!==void 0,\"Table\",\"Each record in dataSource of table should have a unique `key` prop, or set `rowKey` of Table to an unique primary key, \"),a===void 0?n:a},getSorterFn:function(t){var n=t||this.$data,r=n.sSortOrder,a=n.sSortColumn;if(!(!r||!a||typeof a.sorter!=\"function\"))return function(o,i){var l=a.sorter(o,i,r);return l!==0?r===\"descend\"?-l:l:0}},getCurrentPageData:function(){var t=this.getLocalData();this.filterDataCnt=t.length;var n,r,a=this.sPagination;return this.hasPagination()?(r=a.pageSize,n=this.getMaxCurrent(a.total||t.length)):(r=Number.MAX_VALUE,n=1),(t.length>r||r===Number.MAX_VALUE)&&(t=t.slice((n-1)*r,n*r)),t},getFlatData:function(){var t=this.$props.childrenColumnName;return Bx(this.getLocalData(null,!1),t)},getFlatCurrentPageData:function(){var t=this.$props.childrenColumnName;return Bx(this.getCurrentPageData(),t)},getLocalData:function(t){var n=this,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,a=t||this.$data,o=a.sFilters,i=this.$props.dataSource,l=i||[];l=l.slice(0);var s=this.getSorterFn(a);return s&&(l=this.recursiveSort(Je(l),s)),r&&o&&Object.keys(o).forEach(function(c){var d=n.findColumn(c);if(!!d){var f=o[c]||[];if(f.length!==0){var p=d.onFilter;l=p?l.filter(function(v){return f.some(function(m){return p(m,v)})}):l}}}),l},onRow:function(t,n,r){var a=this.customRow,o=a?a(n,r):{};return P(P({},o),{prefixCls:t,store:this.store,rowKey:this.getRecordKey(n,r)})},setSelectedRowKeys:function(t,n){var r=this,a=n.selectWay,o=n.record,i=n.checked,l=n.changeRowKeys,s=n.nativeEvent,c=Zh(this.$props);c&&!(\"selectedRowKeys\"in c)&&(this.store.selectedRowKeys=t);var d=this.getFlatData();if(!(!c.onChange&&!c[a])){var f=d.filter(function(m,y){return t.indexOf(r.getRecordKey(m,y))>=0});if(c.onChange&&c.onChange(t,f),a===\"onSelect\"&&c.onSelect)c.onSelect(o,i,f,s);else if(a===\"onSelectMultiple\"&&c.onSelectMultiple){var p=d.filter(function(m,y){return l.indexOf(r.getRecordKey(m,y))>=0});c.onSelectMultiple(i,f,p)}else if(a===\"onSelectAll\"&&c.onSelectAll){var v=d.filter(function(m,y){return l.indexOf(r.getRecordKey(m,y))>=0});c.onSelectAll(i,f,v)}else a===\"onSelectInvert\"&&c.onSelectInvert&&c.onSelectInvert(t)}},generatePopupContainerFunc:function(t){var n=this.$props.scroll,r=this.vcTable;return t||(n&&r?function(){return r.tableNode}:void 0)},scrollToFirstRow:function(){var t=this,n=this.$props.scroll;n&&n.scrollToFirstRowOnChange!==!1&&Zw(0,{getContainer:function(){return t.vcTable.ref_bodyTable}})},isSameColumn:function(t,n){return t&&n&&t.key&&t.key===n.key?!0:t===n||Mr(t,n,function(r,a){if(typeof r==\"function\"&&typeof a==\"function\")return r===a||r.toString()===a.toString()})},handleFilter:function(t,n){var r=this,a=this.$props,o=P({},this.sPagination),i=P(P({},this.sFilters),V({},Wa(t),n)),l=[];Zp(this.columns,function(d){d.children||l.push(Wa(d))}),Object.keys(i).forEach(function(d){l.indexOf(d)<0&&delete i[d]}),a.pagination&&(o.current=1,o.onChange(o.current));var s={sPagination:o,sFilters:{}},c=P({},i);E1({columns:a.columns}).forEach(function(d){var f=Wa(d);f&&delete c[f]}),Object.keys(c).length>0&&(s.sFilters=c),kt(a.pagination)===\"object\"&&\"current\"in a.pagination&&(s.sPagination=P(P({},o),{current:this.sPagination.current})),this.setState(s,function(){r.scrollToFirstRow(),r.store.selectionDirty=!1,r.$emit.apply(r,[\"change\"].concat(Je(r.prepareParamsArguments(P(P({},r.$data),{sSelectionDirty:!1,sFilters:i,sPagination:o})))))})},handleSelect:function(t,n,r){var a=this,o=r.target.checked,i=r.nativeEvent,l=this.store.selectionDirty?[]:this.getDefaultSelection(),s=this.store.selectedRowKeys.concat(l),c=this.getRecordKey(t,n),d=this.$data.pivot,f=this.getFlatCurrentPageData(),p=n;if(this.$props.expandedRowRender&&(p=f.findIndex(function(S){return a.getRecordKey(S,n)===c})),i.shiftKey&&d!==void 0&&p!==d){for(var v=[],m=Math.sign(d-p),y=Math.abs(d-p),b=0,C=function(){var w=p+b*m;b+=1;var k=f[w],$=a.getRecordKey(k,w),O=a.getCheckboxPropsByItem(k,w);O.disabled||(s.includes($)?o||(s=s.filter(function(T){return $!==T}),v.push($)):o&&(s.push($),v.push($)))};b<=y;)C();this.setState({pivot:p}),this.store.selectionDirty=!0,this.setSelectedRowKeys(s,{selectWay:\"onSelectMultiple\",record:t,checked:o,changeRowKeys:v,nativeEvent:i})}else o?s.push(this.getRecordKey(t,p)):s=s.filter(function(S){return c!==S}),this.setState({pivot:p}),this.store.selectionDirty=!0,this.setSelectedRowKeys(s,{selectWay:\"onSelect\",record:t,checked:o,changeRowKeys:void 0,nativeEvent:i})},handleRadioSelect:function(t,n,r){var a=r.target.checked,o=r.nativeEvent,i=this.getRecordKey(t,n),l=[i];this.store.selectionDirty=!0,this.setSelectedRowKeys(l,{selectWay:\"onSelect\",record:t,checked:a,changeRowKeys:void 0,nativeEvent:o})},handleSelectRow:function(t,n,r){var a=this,o=this.getFlatCurrentPageData(),i=this.store.selectionDirty?[]:this.getDefaultSelection(),l=this.store.selectedRowKeys.concat(i),s=o.filter(function(m,y){return!a.getCheckboxPropsByItem(m,y).disabled}).map(function(m,y){return a.getRecordKey(m,y)}),c=[],d=\"onSelectAll\",f;switch(t){case\"all\":s.forEach(function(m){l.indexOf(m)<0&&(l.push(m),c.push(m))}),d=\"onSelectAll\",f=!0;break;case\"removeAll\":s.forEach(function(m){l.indexOf(m)>=0&&(l.splice(l.indexOf(m),1),c.push(m))}),d=\"onSelectAll\",f=!1;break;case\"invert\":s.forEach(function(m){l.indexOf(m)<0?l.push(m):l.splice(l.indexOf(m),1),c.push(m),d=\"onSelectInvert\"});break}this.store.selectionDirty=!0;var p=this.rowSelection,v=2;if(p&&p.hideDefaultSelections&&(v=0),n>=v&&typeof r==\"function\")return r(s);this.setSelectedRowKeys(l,{selectWay:d,checked:f,changeRowKeys:c})},handlePageChange:function(t){var n=this.$props,r=P({},this.sPagination);t?r.current=t:r.current=r.current||1;for(var a=arguments.length,o=new Array(a>1?a-1:0),i=1;i<a;i++)o[i-1]=arguments[i];r.onChange.apply(r,[r.current].concat(o));var l={sPagination:r};n.pagination&&kt(n.pagination)===\"object\"&&\"current\"in n.pagination&&(l.sPagination=P(P({},r),{current:this.sPagination.current})),this.setState(l,this.scrollToFirstRow),this.store.selectionDirty=!1,this.$emit.apply(this,[\"change\"].concat(Je(this.prepareParamsArguments(P(P({},this.$data),{sSelectionDirty:!1,sPagination:r})))))},handleShowSizeChange:function(t,n){var r=this.sPagination;r.onShowSizeChange(t,n);var a=P(P({},r),{pageSize:n,current:t});this.setState({sPagination:a},this.scrollToFirstRow),this.$emit.apply(this,[\"change\"].concat(Je(this.prepareParamsArguments(P(P({},this.$data),{sPagination:a})))))},toggleSortOrder:function(t){var n=t.sortDirections||this.sortDirections,r=this.sSortOrder,a=this.sSortColumn,o;if(Hx(a,t)&&r!==void 0){var i=n.indexOf(r)+1;o=i===n.length?void 0:n[i]}else o=n[0];var l={sSortOrder:o,sSortColumn:o?t:null};this.getSortOrderColumns().length===0&&this.setState(l,this.scrollToFirstRow),this.$emit.apply(this,[\"change\"].concat(Je(this.prepareParamsArguments(P(P({},this.$data),l),t))))},hasPagination:function(t){return(t||this.$props).pagination!==!1},isSortColumn:function(t){var n=this.sSortColumn;return!t||!n?!1:Wa(n)===Wa(t)},prepareParamsArguments:function(t,n){var r=P({},t.sPagination);delete r.onChange,delete r.onShowSizeChange;var a=t.sFilters,o={},i=n;t.sSortColumn&&t.sSortOrder&&(i=t.sSortColumn,o.column=t.sSortColumn,o.order=t.sSortOrder),i&&(o.field=i.dataIndex,o.columnKey=Wa(i));var l={currentDataSource:this.getLocalData(t)};return[r,a,o,l]},findColumn:function(t){var n;return Zp(this.columns,function(r){Wa(r)===t&&(n=r)}),n},recursiveSort:function(t,n){var r=this,a=this.childrenColumnName,o=a===void 0?\"children\":a;return t.sort(n).map(function(i){return i[o]?P(P({},i),V({},o,r.recursiveSort(Je(i[o]),n))):i})},renderExpandIcon:function(t){return this.expandIcon?this.expandIcon:function(n){var r=n.expandable,a=n.expanded,o=n.needIndentSpaced,i=n.record,l=n.onExpand;return r?g(Kr,{componentName:\"Table\",defaultLocale:lo.Table,children:function(c){var d;return g(cm,{class:Se(\"\".concat(t,\"-row-expand-icon\"),(d={},V(d,\"\".concat(t,\"-row-collapsed\"),!a),V(d,\"\".concat(t,\"-row-expanded\"),a),d)),onClick:function(p){l(i,p)},\"aria-label\":a?c.collapse:c.expand,noStyle:!0},null)}},null):o?g(\"span\",{class:\"\".concat(t,\"-row-expand-icon \").concat(t,\"-row-spaced\")},null):null}},renderPagination:function(t,n){if(!this.hasPagination())return null;var r=\"default\",a=this.sPagination;a.size?r=a.size:(this.size===\"middle\"||this.size===\"small\")&&(r=\"small\");var o=a.position||\"bottom\",i=a.total||this.filterDataCnt,l=a.class,s=a.style;a.onChange,a.onShowSizeChange;var c=Vx(a,[\"class\",\"style\",\"onChange\",\"onShowSizeChange\"]),d=P(P({key:\"pagination-\".concat(n),class:Se(l,\"\".concat(t,\"-pagination\"))},c),{total:i,size:r,current:this.getMaxCurrent(i),style:s,onChange:this.handlePageChange,onShowSizeChange:this.handleShowSizeChange});return i>0&&(o===n||o===\"both\")?g(OS,d,null):null},renderSelectionBox:function(t){var n=this;return function(r){var a=r.record,o=r.index,i=n.getRecordKey(a,o),l=n.getCheckboxPropsByItem(a,o),s=function(f){t===\"radio\"?n.handleRadioSelect(a,o,f):n.handleSelect(a,o,f)},c=P({type:t,store:n.store,rowIndex:i,defaultSelection:n.getDefaultSelection(),onChange:s},l);return g(\"span\",{onClick:iNe},[g(JIe,c,null)])}},renderRowSelection:function(t){var n=this,r=t.prefixCls,a=t.locale,o=t.getPopupContainer,i=this.rowSelection,l=this.columns.concat();if(i){var s=this.getFlatCurrentPageData().filter(function(p,v){return i.getCheckboxProps?!n.getCheckboxPropsByItem(p,v).disabled:!0}),c=Se(\"\".concat(r,\"-selection-column\"),V({},\"\".concat(r,\"-selection-column-custom\"),i.selections)),d=V({key:\"selection-column\",customRender:this.renderSelectionBox(i.type),className:c,fixed:i.fixed,width:i.columnWidth,title:i.columnTitle},kR,{class:\"\".concat(r,\"-selection-col\")});if(i.type!==\"radio\"){var f=s.every(function(p,v){return n.getCheckboxPropsByItem(p,v).disabled});d.title=d.title||g(tNe,{store:this.store,locale:a,data:s,getCheckboxPropsByItem:this.getCheckboxPropsByItem,getRecordKey:this.getRecordKey,disabled:f,prefixCls:r,onSelect:this.handleSelectRow,selections:i.selections,hideDefaultSelections:i.hideDefaultSelections,getPopupContainer:this.generatePopupContainerFunc(o),propsSymbol:Symbol()},null)}\"fixed\"in i?d.fixed=i.fixed:l.some(function(p){return p.fixed===\"left\"||p.fixed===!0})&&(d.fixed=\"left\"),l[0]&&l[0].key===\"selection-column\"?l[0]=d:l.unshift(d)}return l},renderColumnsDropdown:function(t){var n=this,r=t.prefixCls,a=t.dropdownPrefixCls,o=t.columns,i=t.locale,l=t.getPopupContainer,s=this.sSortOrder,c=this.sFilters;return Zp(o,function(d,f){var p,v=Wa(d,f),m,y,b=d.customHeaderCell,C=n.isSortColumn(d);if(d.filters&&d.filters.length>0||d.filterDropdown){var S=v in c?c[v]:[];m=g(XIe,{locale:i,column:d,selectedKeys:S,confirmFilter:n.handleFilter,prefixCls:\"\".concat(r,\"-filter\"),dropdownPrefixCls:a||\"ant-dropdown\",getPopupContainer:n.generatePopupContainerFunc(l),key:\"filter-dropdown\"},null)}if(d.sorter){var w=d.sortDirections||n.sortDirections,k=C&&s===\"ascend\",$=C&&s===\"descend\",O=w.indexOf(\"ascend\")!==-1&&g(iIe,{class:\"\".concat(r,\"-column-sorter-up \").concat(k?\"on\":\"off\"),key:\"caret-up\"},null),T=w.indexOf(\"descend\")!==-1&&g(SR,{class:\"\".concat(r,\"-column-sorter-down \").concat($?\"on\":\"off\"),key:\"caret-down\"},null);y=g(\"div\",{title:i.sortTitle,class:Se(\"\".concat(r,\"-column-sorter-inner\"),O&&T&&\"\".concat(r,\"-column-sorter-inner-full\")),key:\"sorter\"},[O,T]),b=function(I){var L={};d.customHeaderCell&&(L=P({},d.customHeaderCell(I)));var j=L.onClick;return L.onClick=function(){n.toggleSortOrder(d),j&&j.apply(void 0,arguments)},L}}return P(P({},d),{className:Se(d.className,(p={},V(p,\"\".concat(r,\"-column-has-actions\"),y||m),V(p,\"\".concat(r,\"-column-has-filters\"),m),V(p,\"\".concat(r,\"-column-has-sorters\"),y),V(p,\"\".concat(r,\"-column-sort\"),C&&s),p)),title:[g(\"span\",{key:\"title\",class:\"\".concat(r,\"-header-column\")},[g(\"div\",{class:y?\"\".concat(r,\"-column-sorters\"):void 0},[g(\"span\",{class:\"\".concat(r,\"-column-title\")},[n.renderColumnTitle(d.title)]),g(\"span\",{class:\"\".concat(r,\"-column-sorter\")},[y])])]),m],customHeaderCell:b})})},renderColumnTitle:function(t){var n=this.$data,r=n.sFilters,a=n.sSortOrder,o=n.sSortColumn;return t instanceof Function?t({filters:r,sortOrder:a,sortColumn:o}):t},renderTable:function(t){var n,r=this,a=t.prefixCls,o=t.renderEmpty,i=t.dropdownPrefixCls,l=t.contextLocale,s=t.getPopupContainer,c=t.transformCellText,d=P(P({},Qe(this)),this.$attrs),f=d.showHeader,p=d.locale,v=d.getPopupContainer;d.style;var m=Vx(d,[\"showHeader\",\"locale\",\"getPopupContainer\",\"style\"]),y=this.getCurrentPageData(),b=this.expandedRowRender&&this.expandIconAsCell!==!1,C=v||s,S=P(P({},l),p);(!p||!p.emptyText)&&(S.emptyText=o(\"Table\"));var w=Se((n={},V(n,\"\".concat(a,\"-\").concat(this.size),!0),V(n,\"\".concat(a,\"-bordered\"),this.bordered),V(n,\"\".concat(a,\"-empty\"),!y.length),V(n,\"\".concat(a,\"-without-column-header\"),!f),n)),k=this.renderRowSelection({prefixCls:a,locale:S,getPopupContainer:C}),$=this.renderColumnsDropdown({columns:k,prefixCls:a,dropdownPrefixCls:i,locale:S,getPopupContainer:C}).map(function(_,I){var L=P({},_);return L.key=Wa(L,I),L}),O=$[0]&&$[0].key===\"selection-column\"?1:0;\"expandIconColumnIndex\"in m&&(O=m.expandIconColumnIndex);var T=P(P({key:\"table\",expandIcon:this.renderExpandIcon(a)},m),{customRow:function(I,L){return r.onRow(a,I,L)},components:this.sComponents,prefixCls:a,data:y,columns:$,showHeader:f,expandIconColumnIndex:O,expandIconAsCell:b,emptyText:S.emptyText,transformCellText:c,class:w,ref:this.setTableRef});return g(RIe,T,null)}},render:function(){var t=this,n=this.prefixCls,r=this.dropdownPrefixCls,a=this.transformCellText,o=this.getCurrentPageData(),i=this.configProvider,l=i.getPopupContainer,s=i.transformCellText,c=this.getPopupContainer||l,d=a||s,f=this.loading;typeof f==\"boolean\"&&(f={spinning:f});var p=this.configProvider.getPrefixCls,v=this.configProvider.renderEmpty,m=p(\"table\",n),y=p(\"dropdown\",r),b=g(Kr,{componentName:\"Table\",defaultLocale:lo.Table,children:function(T){return t.renderTable({prefixCls:m,renderEmpty:v,dropdownPrefixCls:y,contextLocale:T,getPopupContainer:c,transformCellText:d})}},null),C=this.hasPagination()&&o&&o.length!==0?\"\".concat(m,\"-with-pagination\"):\"\".concat(m,\"-without-pagination\"),S=P(P({},f),{class:f&&f.spinning?\"\".concat(C,\" \").concat(m,\"-spin-holder\"):\"\"}),w=this.$attrs,k=w.class,$=w.style;return g(\"div\",{class:Se(\"\".concat(m,\"-wrapper\"),k),style:$},[g(ol,S,{default:function(){return[t.renderPagination(m,\"top\"),b,t.renderPagination(m,\"bottom\")]}})])}}),Ux=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},So=G({name:\"ATable\",Column:$b.Column,ColumnGroup:$b.ColumnGroup,inheritAttrs:!1,props:MR,methods:{normalize:function(){var t=this,n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],r=Un(n),a=[];return r.forEach(function(o){var i,l,s,c;if(!!o){var d=a0e(o),f=((i=o.props)===null||i===void 0?void 0:i.style)||{},p=((l=o.props)===null||l===void 0?void 0:l.class)||\"\",v=rr(o),m=o.children||{},y=m.default,b=Ux(m,[\"default\"]),C=P(P(P({},b),v),{style:f,class:p});if(d&&(C.key=d),!((s=o.type)===null||s===void 0)&&s.__ANT_TABLE_COLUMN_GROUP)C.children=t.normalize(typeof y==\"function\"?y():y);else{var S=(c=o.children)===null||c===void 0?void 0:c.default;C.customRender=C.customRender||S}a.push(C)}}),a},updateColumns:function(){var t=this,n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],r=[],a=this.$slots;return n.forEach(function(o){var i=o.slots,l=i===void 0?{}:i,s=Ux(o,[\"slots\"]),c=P({},s);Object.keys(l).forEach(function(d){var f=l[d];c[d]===void 0&&a[f]&&(c[d]=a[f])}),o.children&&(c.children=t.updateColumns(c.children)),r.push(c)}),r}},render:function(){var t=this.normalize,n=this.$slots,r=P(P({},Qe(this)),this.$attrs),a=r.columns?this.updateColumns(r.columns):t(ht(this)),o=r.title,i=r.footer,l=n.title,s=n.footer,c=n.expandedRowRender,d=c===void 0?r.expandedRowRender:c,f=n.expandIcon;o=o||l,i=i||s;var p=P(P({},r),{columns:a,title:o,footer:i,expandedRowRender:d,expandIcon:this.$props.expandIcon||f});return g($b,le(le({},p),{},{ref:\"table\"}),null)}});So.install=function(e){return e.component(So.name,So),e.component(So.Column.name,So.Column),e.component(So.ColumnGroup.name,So.ColumnGroup),e};var cNe=So.Column,dNe=So.ColumnGroup,fNe=So,hNe={prefixCls:u.string,placeholder:u.string,value:u.any,handleClear:u.func,disabled:u.looseBool,onChange:u.func},pNe=G({name:\"Search\",inheritAttrs:!1,props:Rn(hNe,{placeholder:\"\"}),methods:{handleChange:function(t){this.$emit(\"change\",t)},handleClear2:function(t){t.preventDefault();var n=this.$props,r=n.handleClear,a=n.disabled;!a&&r&&r(t)}},render:function(){var t=Qe(this),n=t.placeholder,r=t.value,a=t.prefixCls,o=t.disabled,i=r&&r.length>0?g(\"a\",{href:\"#\",class:\"\".concat(a,\"-action\"),onClick:this.handleClear2},[g(Yr,null,null)]):g(\"span\",{class:\"\".concat(a,\"-action\")},[g(Vv,null,null)]);return g(Fe,null,[g(Jn,{placeholder:n,class:a,value:r,onChange:this.handleChange,disabled:o},null),i])}}),Ob=function(t,n){var r=\"\";return typeof getComputedStyle!=\"undefined\"?r=window.getComputedStyle(t,null).getPropertyValue(n):r=t.style[n],r},vNe=function(t){return Ob(t,\"overflow\")+Ob(t,\"overflow-y\")+Ob(t,\"overflow-x\")},mNe=function(t){if(!(t instanceof window.HTMLElement))return window;for(var n=t;n&&!(n===document.body||n===document.documentElement||!n.parentNode);){if(/(scroll|auto)/.test(vNe(n)))return n;n=n.parentNode}return window},gNe=mNe;function Yx(e){var t=e.getBoundingClientRect();return{top:t.top+window.pageYOffset,left:t.left+window.pageXOffset}}var yNe=function(t){return t.offsetParent===null};function bNe(e,t,n){if(yNe(e))return!1;var r,a,o,i;if(typeof t==\"undefined\"||t===window)r=window.pageYOffset,o=window.pageXOffset,a=r+window.innerHeight,i=o+window.innerWidth;else{var l=Yx(t);r=l.top,o=l.left,a=r+t.offsetHeight,i=o+t.offsetWidth}var s=Yx(e);return r<=s.top+e.offsetHeight+n.top&&a>=s.top-n.bottom&&o<=s.left+e.offsetWidth+n.left&&i>=s.left-n.right}var CNe={debounce:u.looseBool,elementType:u.string,height:u.oneOfType([u.string,u.number]),offset:u.number,offsetBottom:u.number,offsetHorizontal:u.number,offsetLeft:u.number,offsetRight:u.number,offsetTop:u.number,offsetVertical:u.number,threshold:u.number,throttle:u.number,width:u.oneOfType([u.string,u.number])},wNe=G({name:\"LazyLoad\",mixins:[nt],inheritAttrs:!1,props:An(CNe,{elementType:\"div\",debounce:!0,offset:0,offsetBottom:0,offsetHorizontal:0,offsetLeft:0,offsetRight:0,offsetTop:0,offsetVertical:0,throttle:250}),data:function(){return this.throttle>0&&(this.debounce?this.lazyLoadHandler=Yn(this.lazyLoadHandler,this.throttle):this.lazyLoadHandler=Qi(this.lazyLoadHandler,this.throttle)),{visible:!1}},mounted:function(){var t=this;this.$nextTick(function(){Wn(function(){t.visible||t.lazyLoadHandler(t.$props)});var n=t.getEventNode();t.lazyLoadHandler.flush&&t.lazyLoadHandler.flush(),t.resizeHander=Kn(window,\"resize\",t.lazyLoadHandler),t.scrollHander=Kn(n,\"scroll\",t.lazyLoadHandler)})},beforeUnmount:function(){this.lazyLoadHandler.cancel&&this.lazyLoadHandler.cancel(),this.detachListeners()},methods:{getEventNode:function(){return gNe(Sn(this))},getOffset:function(){var t=this.$props,n=t.offset,r=t.offsetVertical,a=t.offsetHorizontal,o=t.offsetTop,i=t.offsetBottom,l=t.offsetLeft,s=t.offsetRight,c=t.threshold,d=c||n,f=r||d,p=a||d;return{top:o||f,bottom:i||f,left:l||p,right:s||p}},lazyLoadHandler:function(){var t=this;if(!!this._.isMounted){var n=this.getOffset(),r=Sn(this),a=this.getEventNode();bNe(r,a,n)&&(this.setState({visible:!0},function(){t.__emit(\"contentVisible\")}),this.detachListeners())}},detachListeners:function(){this.resizeHander&&this.resizeHander.remove(),this.scrollHander&&this.scrollHander.remove()}},render:function(){var t=ht(this);if(t.length!==1)return on(!1,\"lazyLoad\\u7EC4\\u4EF6\\u53EA\\u80FD\\u5305\\u542B\\u4E00\\u4E2A\\u5B50\\u5143\\u7D20\"),null;var n=this.$props,r=n.height,a=n.width,o=n.elementType,i=this.visible,l=this.$attrs.class,s={height:typeof r==\"number\"?r+\"px\":r,width:typeof a==\"number\"?a+\"px\":a},c=V({LazyLoad:!0,\"is-visible\":i},l,l);return g(o,{class:c,style:s},{default:function(){return[i?t[0]:null]}})}});function SNe(){}var kNe=G({name:\"ListItem\",inheritAttrs:!1,props:{renderedText:u.any,renderedEl:u.any,item:u.any,lazy:an(u.oneOfType([u.looseBool,u.object])),checked:u.looseBool,prefixCls:u.string,disabled:u.looseBool,onClick:u.func},render:function(){var t,n=this,r=this.$props,a=r.renderedText,o=r.renderedEl,i=r.item,l=r.lazy,s=r.checked,c=r.disabled,d=r.prefixCls,f=Se((t={},V(t,\"\".concat(d,\"-content-item\"),!0),V(t,\"\".concat(d,\"-content-item-disabled\"),c||i.disabled),t)),p;(typeof a==\"string\"||typeof a==\"number\")&&(p=String(a));var v=g(\"li\",{class:f,title:p,onClick:c||i.disabled?SNe:function(){n.$emit(\"click\",i)}},[g(ro,{checked:s,disabled:c||i.disabled},null),g(\"span\",{class:\"\".concat(d,\"-content-item-text\")},[o])]),m=null;if(l){var y=P({height:32,offset:500,throttle:0,debounce:!1},l);m=g(wNe,y,{default:function(){return[v]}})}else m=v;return m}}),$Ne=G({name:\"ListBody\",inheritAttrs:!1,props:{prefixCls:u.string,filteredRenderItems:u.array.def([]),lazy:an(u.oneOfType([u.looseBool,u.object])),selectedKeys:u.array,disabled:u.looseBool,onItemSelect:u.func,onItemSelectAll:u.func,onScroll:u.func},setup:function(){return{mountId:null,lazyId:null}},data:function(){return{mounted:!1}},computed:{itemsLength:function(){return this.filteredRenderItems?this.filteredRenderItems.length:0}},watch:{itemsLength:function(){var t=this;Ne(function(){var n=t.$props.lazy;if(n!==!1){var r=Sn(t);en.cancel(t.lazyId),t.lazyId=en(function(){if(r){var a=new Event(\"scroll\",{bubbles:!0});r.dispatchEvent(a)}})}})}},mounted:function(){var t=this;this.mountId=en(function(){t.mounted=!0})},beforeUnmount:function(){en.cancel(this.mountId),en.cancel(this.lazyId)},methods:{handleItemSelect:function(t){var n=this.$props.selectedKeys,r=n.indexOf(t.key)>=0;this.$emit(\"itemSelect\",t.key,!r)},handleScroll:function(t){this.$emit(\"scroll\",t)}},render:function(){var t=this,n=this.$data.mounted,r=this.$props,a=r.prefixCls,o=r.filteredRenderItems,i=r.lazy,l=r.selectedKeys,s=r.disabled,c=o.map(function(f){var p=f.renderedEl,v=f.renderedText,m=f.item,y=m.disabled,b=l.indexOf(m.key)>=0;return g(kNe,{disabled:s||y,key:m.key,item:m,lazy:i,renderedText:v,renderedEl:p,checked:b,prefixCls:a,onClick:t.handleItemSelect},null)}),d=d2(n?\"\".concat(a,\"-content-item-highlight\"):\"\",{tag:\"ul\",class:\"\".concat(a,\"-content\"),onScroll:this.handleScroll});return g(f2,d,{default:function(){return[c]}})}}),ONe=function(e){return g($Ne,e,null)};function PNe(e,t){if(\"createEvent\"in document){var n=document.createEvent(\"HTMLEvents\");n.initEvent(t,!1,!0),e.dispatchEvent(n)}}var TNe=function(){return null},xNe={key:u.string,title:u.string,description:u.string,disabled:u.looseBool};function _Ne(e){return e&&!zn(e)&&Object.prototype.toString.call(e)===\"[object Object]\"}var ENe={prefixCls:u.string,titleText:u.string,dataSource:u.arrayOf(u.shape(xNe).loose),filter:u.string,filterOption:u.func,checkedKeys:u.arrayOf(u.string),handleFilter:u.func,handleSelect:u.func,handleSelectAll:u.func,handleClear:u.func,renderItem:u.func,showSearch:u.looseBool,searchPlaceholder:u.string,notFoundContent:u.any,itemUnit:u.string,itemsUnit:u.string,body:u.any,renderList:u.any,footer:u.any,lazy:an(u.oneOfType([u.looseBool,u.object])),disabled:u.looseBool,direction:u.string,showSelectAll:u.looseBool,onItemSelect:u.func,onItemSelectAll:u.func,onScroll:u.func};function MNe(e,t){var n=e?e(t):null,r=!!n&&La(n).length>0;return r||(n=ONe(t)),{customize:r,bodyContent:n}}var qx=G({name:\"TransferList\",mixins:[nt],inheritAttrs:!1,props:Rn(ENe,{dataSource:[],titleText:\"\",showSearch:!1,lazy:{}}),setup:function(){return{timer:null,triggerScrollTimer:null,scrollEvent:null}},data:function(){return{filterValue:\"\"}},beforeUnmount:function(){clearTimeout(this.triggerScrollTimer)},updated:function(){var t=this;Ne(function(){t.scrollEvent&&t.scrollEvent.remove()})},methods:{handleScroll:function(t){this.$emit(\"scroll\",t)},getCheckStatus:function(t){var n=this.$props.checkedKeys;return n.length===0?\"none\":t.every(function(r){return n.indexOf(r.key)>=0||!!r.disabled})?\"all\":\"part\"},getFilteredItems:function(t,n){var r=this,a=[],o=[];return t.forEach(function(i){var l=r.renderItemHtml(i),s=l.renderedText;if(n&&n.trim()&&!r.matchFilter(s,i))return null;a.push(i),o.push(l)}),{filteredItems:a,filteredRenderItems:o}},getListBody:function(t,n,r,a,o,i,l,s,c,d,f){var p=d?g(\"div\",{class:\"\".concat(t,\"-body-search-wrapper\")},[g(pNe,{prefixCls:\"\".concat(t,\"-search\"),onChange:this._handleFilter,handleClear:this._handleClear,placeholder:n,value:r,disabled:f},null)]):null,v=i;if(!v){var m,y=If(this.$attrs),b=y.onEvents,C=MNe(c,P(P(P({},this.$props),{filteredItems:a,filteredRenderItems:l,selectedKeys:s}),b)),S=C.bodyContent,w=C.customize;w?m=g(\"div\",{class:\"\".concat(t,\"-body-customize-wrapper\")},[S]):m=a.length?S:g(\"div\",{class:\"\".concat(t,\"-body-not-found\")},[o]),v=g(\"div\",{class:Se(d?\"\".concat(t,\"-body \").concat(t,\"-body-with-search\"):\"\".concat(t,\"-body\"))},[p,m])}return v},getCheckBox:function(t,n,r){var a=this,o=this.getCheckStatus(t),i=o===\"all\",l=n!==!1&&g(ro,{disabled:r,checked:i,indeterminate:o===\"part\",onChange:function(){a.$emit(\"itemSelectAll\",t.filter(function(c){return!c.disabled}).map(function(c){var d=c.key;return d}),!i)}},null);return l},_handleSelect:function(t){var n=this.$props.checkedKeys,r=n.some(function(a){return a===t.key});this.handleSelect(t,!r)},_handleFilter:function(t){var n=this,r=this.$props.handleFilter,a=t.target.value;this.setState({filterValue:a}),r(t),a&&(this.triggerScrollTimer=setTimeout(function(){var o=Sn(n),i=o.querySelectorAll(\".ant-transfer-list-content\")[0];i&&PNe(i,\"scroll\")},0))},_handleClear:function(t){this.setState({filterValue:\"\"}),this.handleClear(t)},matchFilter:function(t,n){var r=this.$data.filterValue,a=this.$props.filterOption;return a?a(r,n):t.indexOf(r)>=0},renderItemHtml:function(t){var n=this.$props.renderItem,r=n===void 0?TNe:n,a=r(t),o=_Ne(a);return{renderedText:o?a.value:a,renderedEl:o?a.label:a,item:t}},filterNull:function(t){return t.filter(function(n){return n!==null})}},render:function(){var t=this.$data.filterValue,n=this.$props,r=n.prefixCls,a=n.dataSource,o=n.titleText,i=n.checkedKeys,l=n.disabled,s=n.body,c=n.footer,d=n.showSearch,f=n.searchPlaceholder,p=n.notFoundContent,v=n.itemUnit,m=n.itemsUnit,y=n.renderList,b=n.showSelectAll,C=c&&c(P({},this.$props)),S=s&&s(P({},this.$props)),w=Se(r,V({},\"\".concat(r,\"-with-footer\"),!!C)),k=this.getFilteredItems(a,t),$=k.filteredItems,O=k.filteredRenderItems,T=a.length>1?m:v,_=this.getListBody(r,f,t,$,p,S,O,i,y,d,l),I=C?g(\"div\",{class:\"\".concat(r,\"-footer\")},[C]):null,L=this.getCheckBox($,b,l);return g(\"div\",{class:w,style:this.$attrs.style},[g(\"div\",{class:\"\".concat(r,\"-header\")},[L,g(\"span\",{class:\"\".concat(r,\"-header-selected\")},[g(\"span\",null,[(i.length>0?\"\".concat(i.length,\"/\"):\"\")+$.length,\" \",T]),g(\"span\",{class:\"\".concat(r,\"-header-title\")},[o])])]),_,I])}});function Gx(){}var IR=function(t){var n=t.disabled,r=t.moveToLeft,a=r===void 0?Gx:r,o=t.moveToRight,i=o===void 0?Gx:o,l=t.leftArrowText,s=l===void 0?\"\":l,c=t.rightArrowText,d=c===void 0?\"\":c,f=t.leftActive,p=t.rightActive,v=t.class,m=t.style;return g(\"div\",{class:v,style:m},[g(Cr,{type:\"primary\",size:\"small\",disabled:n||!p,onClick:i,icon:g(wi,null,null)},{default:function(){return[d]}}),g(Cr,{type:\"primary\",size:\"small\",disabled:n||!f,onClick:a,icon:g(uc,null,null)},{default:function(){return[s]}})])};IR.inheritAttrs=!1;var INe=IR,NNe={key:u.string,title:u.string,description:u.string,disabled:u.looseBool},ANe={prefixCls:u.string,dataSource:u.arrayOf(u.shape(NNe).loose),disabled:u.looseBool,targetKeys:u.arrayOf(u.string),selectedKeys:u.arrayOf(u.string),render:u.func,listStyle:u.oneOfType([u.func,u.object]),operationStyle:u.object,titles:u.arrayOf(u.string),operations:u.arrayOf(u.string),showSearch:u.looseBool,filterOption:u.func,searchPlaceholder:u.string,notFoundContent:u.any,locale:u.object,rowKey:u.func,lazy:u.oneOfType([u.object,u.looseBool]),showSelectAll:u.looseBool,children:u.any,onChange:u.func,onSelectChange:u.func,onSearchChange:u.func,onSearch:u.func,onScroll:u.func},DNe=G({name:\"ATransfer\",mixins:[nt],inheritAttrs:!1,props:Rn(ANe,{dataSource:[],locale:{},showSearch:!1,listStyle:function(){}}),setup:function(){return{separatedDataSource:null,configProvider:ve(\"configProvider\",St)}},data:function(){var t=this.selectedKeys,n=t===void 0?[]:t,r=this.targetKeys,a=r===void 0?[]:r;return{leftFilter:\"\",rightFilter:\"\",sourceSelectedKeys:n.filter(function(o){return a.indexOf(o)===-1}),targetSelectedKeys:n.filter(function(o){return a.indexOf(o)>-1})}},watch:{targetKeys:function(){if(this.updateState(),this.selectedKeys){var t=this.targetKeys||[];this.setState({sourceSelectedKeys:this.selectedKeys.filter(function(n){return!t.includes(n)}),targetSelectedKeys:this.selectedKeys.filter(function(n){return t.includes(n)})})}},dataSource:function(){this.updateState()},selectedKeys:function(){if(this.selectedKeys){var t=this.targetKeys||[];this.setState({sourceSelectedKeys:this.selectedKeys.filter(function(n){return!t.includes(n)}),targetSelectedKeys:this.selectedKeys.filter(function(n){return t.includes(n)})})}}},mounted:function(){},methods:{getSelectedKeysName:function(t){return t===\"left\"?\"sourceSelectedKeys\":\"targetSelectedKeys\"},getTitles:function(t){return this.titles?this.titles:t.titles||[\"\",\"\"]},getLocale:function(t,n){var r={notFoundContent:n(\"Transfer\")},a=We(this,\"notFoundContent\");return a&&(r.notFoundContent=a),vt(this,\"searchPlaceholder\")&&(r.searchPlaceholder=this.$props.searchPlaceholder),P(P(P({},t),r),this.$props.locale)},updateState:function(){var t=this.sourceSelectedKeys,n=this.targetSelectedKeys;if(this.separatedDataSource=null,!this.selectedKeys){var r=this.dataSource,a=this.targetKeys,o=a===void 0?[]:a,i=[],l=[];r.forEach(function(s){var c=s.key;t.includes(c)&&!o.includes(c)&&i.push(c),n.includes(c)&&o.includes(c)&&l.push(c)}),this.setState({sourceSelectedKeys:i,targetSelectedKeys:l})}},moveTo:function(t){var n=this.$props,r=n.targetKeys,a=r===void 0?[]:r,o=n.dataSource,i=o===void 0?[]:o,l=this.sourceSelectedKeys,s=this.targetSelectedKeys,c=t===\"right\"?l:s,d=c.filter(function(v){return!i.some(function(m){return!!(v===m.key&&m.disabled)})}),f=t===\"right\"?d.concat(a):a.filter(function(v){return d.indexOf(v)===-1}),p=t===\"right\"?\"left\":\"right\";this.setState(V({},this.getSelectedKeysName(p),[])),this.handleSelectChange(p,[]),this.$emit(\"change\",f,t,d)},moveToLeft:function(){this.moveTo(\"left\")},moveToRight:function(){this.moveTo(\"right\")},onItemSelectAll:function(t,n,r){var a=this.$data[this.getSelectedKeysName(t)]||[],o=[];r?o=Array.from(new Set([].concat(Je(a),Je(n)))):o=a.filter(function(i){return n.indexOf(i)===-1}),this.handleSelectChange(t,o),this.$props.selectedKeys||this.setState(V({},this.getSelectedKeysName(t),o))},handleSelectAll:function(t,n,r){this.onItemSelectAll(t,n.map(function(a){var o=a.key;return o}),!r)},handleLeftSelectAll:function(t,n){return this.handleSelectAll(\"left\",t,!n)},handleRightSelectAll:function(t,n){return this.handleSelectAll(\"right\",t,!n)},onLeftItemSelectAll:function(t,n){return this.onItemSelectAll(\"left\",t,n)},onRightItemSelectAll:function(t,n){return this.onItemSelectAll(\"right\",t,n)},handleFilter:function(t,n){var r=n.target.value;this.$emit(\"search\",t,r)},handleLeftFilter:function(t){this.handleFilter(\"left\",t)},handleRightFilter:function(t){this.handleFilter(\"right\",t)},handleClear:function(t){this.$emit(\"search\",t,\"\")},handleLeftClear:function(){this.handleClear(\"left\")},handleRightClear:function(){this.handleClear(\"right\")},onItemSelect:function(t,n,r){var a=this.sourceSelectedKeys,o=this.targetSelectedKeys,i=Je(t===\"left\"?a:o),l=i.indexOf(n);l>-1&&i.splice(l,1),r&&i.push(n),this.handleSelectChange(t,i),this.selectedKeys||this.setState(V({},this.getSelectedKeysName(t),i))},onLeftItemSelect:function(t,n){return this.onItemSelect(\"left\",t,n)},onRightItemSelect:function(t,n){return this.onItemSelect(\"right\",t,n)},handleScroll:function(t,n){this.$emit(\"scroll\",t,n)},handleLeftScroll:function(t){this.handleScroll(\"left\",t)},handleRightScroll:function(t){this.handleScroll(\"right\",t)},handleSelectChange:function(t,n){var r=this.sourceSelectedKeys,a=this.targetSelectedKeys;t===\"left\"?this.$emit(\"selectChange\",n,a):this.$emit(\"selectChange\",r,n)},handleListStyle:function(t,n){return typeof t==\"function\"?t({direction:n}):t},separateDataSource:function(){var t=this.$props,n=t.dataSource,r=t.rowKey,a=t.targetKeys,o=a===void 0?[]:a,i=[],l=new Array(o.length);return n.forEach(function(s){r&&(s.key=r(s));var c=o.indexOf(s.key);c!==-1?l[c]=s:i.push(s)}),{leftDataSource:i,rightDataSource:l}},renderTransfer:function(t){var n,r=Qe(this),a=r.prefixCls,o=r.disabled,i=r.operations,l=i===void 0?[]:i,s=r.showSearch,c=r.listStyle,d=r.operationStyle,f=r.filterOption,p=r.lazy,v=r.showSelectAll,m=this.$attrs,y=m.class,b=m.style,C=We(this,\"children\",{},!1),S=this.configProvider.getPrefixCls,w=S(\"transfer\",a),k=this.configProvider.renderEmpty,$=this.getLocale(t,k),O=this.sourceSelectedKeys,T=this.targetSelectedKeys,_=this.$slots,I=_.body,L=_.footer,j=r.render||this.$slots.render,F=this.separateDataSource(),N=F.leftDataSource,D=F.rightDataSource,z=T.length>0,B=O.length>0,M=Se(w,y,(n={},V(n,\"\".concat(w,\"-disabled\"),o),V(n,\"\".concat(w,\"-customize-list\"),!!C),n)),E=this.getTitles($);return g(\"div\",{class:M,style:b},[g(qx,{key:\"leftList\",prefixCls:\"\".concat(w,\"-list\"),titleText:E[0],dataSource:N,filterOption:f,style:this.handleListStyle(c,\"left\"),checkedKeys:O,handleFilter:this.handleLeftFilter,handleClear:this.handleLeftClear,handleSelectAll:this.handleLeftSelectAll,onItemSelect:this.onLeftItemSelect,onItemSelectAll:this.onLeftItemSelectAll,renderItem:j,showSearch:s,body:I,renderList:C,footer:L,lazy:p,onScroll:this.handleLeftScroll,disabled:o,direction:\"left\",showSelectAll:v,itemUnit:$.itemUnit,itemsUnit:$.itemsUnit,notFoundContent:$.notFoundContent,searchPlaceholder:$.searchPlaceholder},null),g(INe,{key:\"operation\",class:\"\".concat(w,\"-operation\"),rightActive:B,rightArrowText:l[0],moveToRight:this.moveToRight,leftActive:z,leftArrowText:l[1],moveToLeft:this.moveToLeft,style:d,disabled:o},null),g(qx,{key:\"rightList\",prefixCls:\"\".concat(w,\"-list\"),titleText:E[1],dataSource:D,filterOption:f,style:this.handleListStyle(c,\"right\"),checkedKeys:T,handleFilter:this.handleRightFilter,handleClear:this.handleRightClear,handleSelectAll:this.handleRightSelectAll,onItemSelect:this.onRightItemSelect,onItemSelectAll:this.onRightItemSelectAll,renderItem:j,showSearch:s,body:I,renderList:C,footer:L,lazy:p,onScroll:this.handleRightScroll,disabled:o,direction:\"right\",showSelectAll:v,itemUnit:$.itemUnit,itemsUnit:$.itemsUnit,notFoundContent:$.notFoundContent,searchPlaceholder:$.searchPlaceholder},null)])}},render:function(){return g(Kr,{componentName:\"Transfer\",defaultLocale:lo.Transfer,children:this.renderTransfer},null)}}),RNe=kn(DNe),LNe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z\"}}]},name:\"file\",theme:\"outlined\"},FNe=LNe;function Xx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){BNe(e,a,n[a])})}return e}function BNe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var VS=function(t,n){var r=Xx({},t,n.attrs);return g(Et,Xx({},r,{icon:FNe}),null)};VS.displayName=\"FileOutlined\";VS.inheritAttrs=!1;var zS=VS,VNe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M328 544h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z\"}},{tag:\"path\",attrs:{d:\"M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z\"}}]},name:\"minus-square\",theme:\"outlined\"},zNe=VNe;function Zx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){HNe(e,a,n[a])})}return e}function HNe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var HS=function(t,n){var r=Zx({},t,n.attrs);return g(Et,Zx({},r,{icon:zNe}),null)};HS.displayName=\"MinusSquareOutlined\";HS.inheritAttrs=!1;var jNe=HS,KNe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M328 544h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8z\"}},{tag:\"path\",attrs:{d:\"M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z\"}}]},name:\"plus-square\",theme:\"outlined\"},WNe=KNe;function Jx(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){UNe(e,a,n[a])})}return e}function UNe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var jS=function(t,n){var r=Jx({},t,n.attrs);return g(Et,Jx({},r,{icon:WNe}),null)};jS.displayName=\"PlusSquareOutlined\";jS.inheritAttrs=!1;var YNe=jS;function M1(e,t){var n=typeof Symbol!=\"undefined\"&&e[Symbol.iterator]||e[\"@@iterator\"];if(!n){if(Array.isArray(e)||(n=rg(e))||t&&e&&typeof e.length==\"number\"){n&&(e=n);var r=0,a=function(){};return{s:a,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(c){throw c},f:a}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var o=!0,i=!1,l;return{s:function(){n=n.call(e)},n:function(){var c=n.next();return o=c.done,c},e:function(c){i=!0,l=c},f:function(){try{!o&&n.return!=null&&n.return()}finally{if(i)throw l}}}}function Qs(){}var Qx=\"open\",e_=\"close\",qNe=\"---\",NR=G({name:\"TreeNode\",mixins:[nt],inheritAttrs:!1,__ANT_TREE_NODE:!0,props:An({eventKey:u.oneOfType([u.string,u.number]),prefixCls:u.string,root:u.object,expanded:u.looseBool,selected:u.looseBool,checked:u.looseBool,loaded:u.looseBool,loading:u.looseBool,halfChecked:u.looseBool,title:u.any,pos:u.string,dragOver:u.looseBool,dragOverGapTop:u.looseBool,dragOverGapBottom:u.looseBool,isLeaf:u.looseBool,checkable:u.looseBool,selectable:u.looseBool,disabled:u.looseBool,disableCheckbox:u.looseBool,icon:u.any,dataRef:u.object,switcherIcon:u.any,label:u.any,value:u.any},{}),setup:function(){return{vcTree:ve(\"vcTree\",{}),vcTreeNode:ve(\"vcTreeNode\",{})}},data:function(){return this.children=null,{dragNodeHighlight:!1}},created:function(){ot(\"vcTreeNode\",this)},mounted:function(){var t=this.eventKey,n=this.vcTree.registerTreeNode;this.syncLoadData(this.$props),n&&n(t,this)},updated:function(){this.syncLoadData(this.$props)},beforeUnmount:function(){var t=this.eventKey,n=this.vcTree.registerTreeNode;n&&n(t,null)},methods:{onSelectorClick:function(t){var n=this.vcTree.onNodeClick;n(t,this),this.isSelectable()?this.onSelect(t):this.onCheck(t)},onSelectorDoubleClick:function(t){var n=this.vcTree.onNodeDoubleClick;n(t,this)},onSelect:function(t){if(!this.isDisabled()){var n=this.vcTree.onNodeSelect;t.preventDefault(),n(t,this)}},onCheck:function(t){if(!this.isDisabled()){var n=this.disableCheckbox,r=this.checked,a=this.vcTree.onNodeCheck;if(!(!this.isCheckable()||n)){t.preventDefault();var o=!r;a(t,this,o)}}},onMouseEnter:function(t){var n=this.vcTree.onNodeMouseEnter;n(t,this)},onMouseLeave:function(t){var n=this.vcTree.onNodeMouseLeave;n(t,this)},onContextMenu:function(t){var n=this.vcTree.onNodeContextMenu;n(t,this)},onDragStart:function(t){var n=this.vcTree.onNodeDragStart;t.stopPropagation(),this.setState({dragNodeHighlight:!0}),n(t,this);try{t.dataTransfer.setData(\"text/plain\",\"\")}catch{}},onDragEnter:function(t){var n=this.vcTree.onNodeDragEnter;t.preventDefault(),t.stopPropagation(),n(t,this)},onDragOver:function(t){var n=this.vcTree.onNodeDragOver;t.preventDefault(),t.stopPropagation(),n(t,this)},onDragLeave:function(t){var n=this.vcTree.onNodeDragLeave;t.stopPropagation(),n(t,this)},onDragEnd:function(t){var n=this.vcTree.onNodeDragEnd;t.stopPropagation(),this.setState({dragNodeHighlight:!1}),n(t,this)},onDrop:function(t){var n=this.vcTree.onNodeDrop;t.preventDefault(),t.stopPropagation(),this.setState({dragNodeHighlight:!1}),n(t,this)},onExpand:function(t){var n=this.vcTree.onNodeExpand;n(t,this)},setSelectHandle:function(t){this.selectHandle=t},getNodeChildren:function(){var t=this.children,n=KS(t);return t.length,n.length,n},getNodeState:function(){var t=this.expanded;return this.isLeaf2()?null:t?Qx:e_},isLeaf2:function(){var t=this.isLeaf,n=this.loaded,r=this.vcTree.loadData,a=this.getNodeChildren().length!==0;return t===!1?!1:t||!r&&!a||r&&n&&!a},isDisabled:function(){var t=this.disabled,n=this.vcTree.disabled;return t===!1?!1:!!(n||t)},isCheckable:function(){var t=this.$props.checkable,n=this.vcTree.checkable;return!n||t===!1?!1:n},syncLoadData:function(t){var n=t.expanded,r=t.loading,a=t.loaded,o=this.vcTree,i=o.loadData,l=o.onNodeLoad;if(!r&&i&&n&&!this.isLeaf2()){var s=this.getNodeChildren().length!==0;!s&&!a&&l(this)}},isSelectable:function(){var t=this.selectable,n=this.vcTree.selectable;return typeof t==\"boolean\"?t:n},renderSwitcher:function(){var t=this.expanded,n=this.vcTree.prefixCls,r=We(this,\"switcherIcon\",{},!1)||We(this.vcTree,\"switcherIcon\",{},!1);if(this.isLeaf2())return g(\"span\",{key:\"switcher\",class:Se(\"\".concat(n,\"-switcher\"),\"\".concat(n,\"-switcher-noop\"))},[typeof r==\"function\"?r(P(P(P({},this.$props),this.$props.dataRef),{isLeaf:!0})):r]);var a=Se(\"\".concat(n,\"-switcher\"),\"\".concat(n,\"-switcher_\").concat(t?Qx:e_));return g(\"span\",{key:\"switcher\",onClick:this.onExpand,class:a},[typeof r==\"function\"?r(P(P(P({},this.$props),this.$props.dataRef),{isLeaf:!1})):r])},renderCheckbox:function(){var t=this.checked,n=this.halfChecked,r=this.disableCheckbox,a=this.vcTree.prefixCls,o=this.isDisabled(),i=this.isCheckable();if(!i)return null;var l=typeof i!=\"boolean\"?i:null;return g(\"span\",{key:\"checkbox\",class:Se(\"\".concat(a,\"-checkbox\"),t&&\"\".concat(a,\"-checkbox-checked\"),!t&&n&&\"\".concat(a,\"-checkbox-indeterminate\"),(o||r)&&\"\".concat(a,\"-checkbox-disabled\")),onClick:this.onCheck},[l])},renderIcon:function(){var t=this.loading,n=this.vcTree.prefixCls;return g(\"span\",{key:\"icon\",class:Se(\"\".concat(n,\"-iconEle\"),\"\".concat(n,\"-icon__\").concat(this.getNodeState()||\"docu\"),t&&\"\".concat(n,\"-icon_loading\"))},null)},renderSelector:function(){var t=this.selected,n=this.loading,r=this.dragNodeHighlight,a=We(this,\"icon\",{},!1),o=this.vcTree,i=o.prefixCls,l=o.showIcon,s=o.icon,c=o.draggable,d=o.loadData,f=this.isDisabled(),p=We(this,\"title\",{},!1),v=\"\".concat(i,\"-node-content-wrapper\"),m;if(l){var y=a||s;m=y?g(\"span\",{class:Se(\"\".concat(i,\"-iconEle\"),\"\".concat(i,\"-icon__customize\"))},[typeof y==\"function\"?y(P(P({},this.$props),this.$props.dataRef)):y]):this.renderIcon()}else d&&n&&(m=this.renderIcon());var b=p,C=b?g(\"span\",{class:\"\".concat(i,\"-title\")},[typeof b==\"function\"?b(P(P({},this.$props),this.$props.dataRef)):b]):g(\"span\",{class:\"\".concat(i,\"-title\")},[qNe]);return g(\"span\",{key:\"selector\",ref:this.setSelectHandle,title:typeof p==\"string\"?p:\"\",class:Se(\"\".concat(v),\"\".concat(v,\"-\").concat(this.getNodeState()||\"normal\"),!f&&(t||r)&&\"\".concat(i,\"-node-selected\"),!f&&c&&\"draggable\"),draggable:!f&&c||void 0,\"aria-grabbed\":!f&&c||void 0,onMouseenter:this.onMouseEnter,onMouseleave:this.onMouseLeave,onContextmenu:this.onContextMenu,onClick:this.onSelectorClick,onDblclick:this.onSelectorDoubleClick,onDragstart:c?this.onDragStart:Qs},[m,C])},renderChildren:function(){var t=this.expanded,n=this.pos,r=this.vcTree,a=r.prefixCls,o=r.openTransitionName,i=r.openAnimation,l=r.renderTreeNode,s={};o?s=Lo(o):kt(i)===\"object\"&&(s=P(P(P({},i),{css:!1}),s));var c=this.getNodeChildren();if(c.length===0)return null;var d;return t&&(d=g(\"ul\",{class:Se(\"\".concat(a,\"-child-tree\"),t&&\"\".concat(a,\"-child-tree-open\")),\"data-expanded\":t,role:\"group\"},[LR(c,function(f,p){return l(f,p,n)})])),g(no,s,{default:function(){return[d]}})}},render:function(){var t;this.children=ht(this);var n=this.$props,r=n.dragOver,a=n.dragOverGapTop,o=n.dragOverGapBottom,i=n.isLeaf,l=n.expanded,s=n.selected,c=n.checked,d=n.halfChecked,f=n.loading,p=this.vcTree,v=p.prefixCls,m=p.filterTreeNode,y=p.draggable,b=this.isDisabled(),C=US(P(P({},this.$props),this.$attrs)),S=this.$attrs,w=S.class,k=S.style;return g(\"li\",le({class:(t={},V(t,w,w),V(t,\"\".concat(v,\"-treenode-disabled\"),b),V(t,\"\".concat(v,\"-treenode-switcher-\").concat(l?\"open\":\"close\"),!i),V(t,\"\".concat(v,\"-treenode-checkbox-checked\"),c),V(t,\"\".concat(v,\"-treenode-checkbox-indeterminate\"),d),V(t,\"\".concat(v,\"-treenode-selected\"),s),V(t,\"\".concat(v,\"-treenode-loading\"),f),V(t,\"drag-over\",!b&&r),V(t,\"drag-over-gap-top\",!b&&a),V(t,\"drag-over-gap-bottom\",!b&&o),V(t,\"filter-node\",m&&m(this)),t),style:k,role:\"treeitem\",onDragenter:y?this.onDragEnter:Qs,onDragover:y?this.onDragOver:Qs,onDragleave:y?this.onDragLeave:Qs,onDrop:y?this.onDrop:Qs,onDragend:y?this.onDragEnd:Qs},C),[this.renderSwitcher(),this.renderCheckbox(),this.renderSelector(),this.renderChildren()])}});NR.isTreeNode=1;var AR=NR,GNe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},XNe=.25,ZNe=2;function eu(e,t){var n=e.slice(),r=n.indexOf(t);return r>=0&&n.splice(r,1),n}function tu(e,t){var n=e.slice();return n.indexOf(t)===-1&&n.push(t),n}function JNe(e){return e.split(\"-\")}function DR(e,t){return\"\".concat(e,\"-\").concat(t)}function QNe(e){return e.type&&e.type.isTreeNode}function KS(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[];return e.filter(QNe)}function Zc(e){var t=Qe(e)||{},n=t.disabled,r=t.disableCheckbox,a=t.checkable;return!!(n||r)||a===!1}function RR(e,t){function n(r,a,o){var i=r?ht(r):e,l=r?DR(o.pos,a):0,s=KS(i);if(r){var c=r.key;!c&&c==null&&(c=l);var d={node:r,index:a,pos:l,key:c,parentPos:o.node?o.pos:null};t(d)}s.forEach(function(f,p){n(f,p,{node:r,pos:l})})}n(null)}function LR(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t=arguments.length>1?arguments[1]:void 0,n=e.map(t);return n.length===1?n[0]:n}function eAe(e,t){var n=Qe(t),r=n.eventKey,a=n.pos,o=[];return RR(e,function(i){var l=i.key;o.push(l)}),o.push(r||a),o}function t_(e,t){var n=e.clientY,r=t.selectHandle.getBoundingClientRect(),a=r.top,o=r.bottom,i=r.height,l=Math.max(i*XNe,ZNe);return n<=a+l?-1:n>=o-l?1:0}function n_(e,t){if(!!e){var n=t.multiple;return n?e.slice():e.length?[e[0]]:e}}var tAe=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return P(P({},t),{class:t.class||t.className,style:t.style,key:t.key})};function WS(e,t){if(!e)return[];var n=t||{},r=n.processProps,a=r===void 0?tAe:r,o=Array.isArray(e)?e:[e];return o.map(function(i){var l=i.children,s=GNe(i,[\"children\"]),c=WS(l,t);return g(AR,a(s),{default:function(){return[c]}})})}function Dg(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.initWrapper,r=t.processEntity,a=t.onProcessFinished,o=new Map,i=new Map,l={posEntities:o,keyEntities:i};return n&&(l=n(l)||l),RR(e,function(s){var c=s.node,d=s.index,f=s.pos,p=s.key,v=s.parentPos,m={node:c,index:d,key:p,pos:f};o.set(f,m),i.set(p,m),m.parent=o.get(v),m.parent&&(m.parent.children=m.parent.children||[],m.parent.children.push(m)),r&&r(m,l)}),a&&a(l),l}function Pb(e){if(!e)return null;var t;if(Array.isArray(e))t={checkedKeys:e,halfCheckedKeys:void 0};else if(kt(e)===\"object\")t={checkedKeys:e.checked||void 0,halfCheckedKeys:e.halfChecked||void 0};else return null;return t}function I1(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},a=new Map,o=new Map;(r.checkedKeys||[]).forEach(function($){a.set($,!0)}),(r.halfCheckedKeys||[]).forEach(function($){o.set($,!0)});function i($){if(a.get($)!==t){var O=n.get($);if(!!O){var T=O.children,_=O.parent,I=O.node;if(!Zc(I)){var L=!0,j=!1;(T||[]).filter(function(F){return!Zc(F.node)}).forEach(function(F){var N=F.key,D=a.get(N),z=o.get(N);(D||z)&&(j=!0),D||(L=!1)}),t?a.set($,L):a.set($,!1),o.set($,j),_&&i(_.key)}}}}function l($){if(a.get($)!==t){var O=n.get($);if(!!O){var T=O.children,_=O.node;Zc(_)||(a.set($,t),(T||[]).forEach(function(I){l(I.key)}))}}}function s($){var O=n.get($);if(!!O){var T=O.children,_=O.parent,I=O.node;a.set($,t),!Zc(I)&&((T||[]).filter(function(L){return!Zc(L.node)}).forEach(function(L){l(L.key)}),_&&i(_.key))}}(e||[]).forEach(function($){s($)});var c=[],d=[],f=M1(a),p;try{for(f.s();!(p=f.n()).done;){var v=fn(p.value,2),m=v[0],y=v[1];y&&c.push(m)}}catch($){f.e($)}finally{f.f()}var b=M1(o),C;try{for(b.s();!(C=b.n()).done;){var S=fn(C.value,2),w=S[0],k=S[1];!a.get(w)&&k&&d.push(w)}}catch($){b.e($)}finally{b.f()}return{checkedKeys:c,halfCheckedKeys:d}}function N1(e,t){var n=new Map;function r(a){if(!n.get(a)){var o=t.get(a);if(!!o){n.set(a,!0);var i=o.parent,l=o.node,s=Qe(l);s&&s.disabled||i&&r(i.key)}}}return(e||[]).forEach(function(a){r(a)}),Je(n.keys())}function US(e){return Object.keys(e).reduce(function(t,n){return(n.substr(0,5)===\"data-\"||n.substr(0,5)===\"aria-\")&&(t[n]=e[n]),t},{})}function nAe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t={};return e.forEach(function(n){t[n]={handler:function(){this.needSyncKeys[n]=!0},flush:\"sync\"}}),t}var rAe=G({name:\"Tree\",mixins:[nt],provide:function(){return{vcTree:this}},inheritAttrs:!1,props:An({prefixCls:u.string,tabindex:u.oneOfType([u.string,u.number]),children:u.any,treeData:u.array,showLine:u.looseBool,showIcon:u.looseBool,icon:u.oneOfType([u.object,u.func]),focusable:u.looseBool,selectable:u.looseBool,disabled:u.looseBool,multiple:u.looseBool,checkable:an(u.oneOfType([u.object,u.looseBool])),checkStrictly:u.looseBool,draggable:u.looseBool,defaultExpandParent:u.looseBool,autoExpandParent:u.looseBool,defaultExpandAll:u.looseBool,defaultExpandedKeys:u.array,expandedKeys:u.array,defaultCheckedKeys:u.array,checkedKeys:u.oneOfType([u.array,u.object]),defaultSelectedKeys:u.array,selectedKeys:u.array,loadData:u.func,loadedKeys:u.array,filterTreeNode:u.func,openTransitionName:u.string,openAnimation:u.oneOfType([u.string,u.object]),switcherIcon:u.any,__propsSymbol__:u.any},{prefixCls:\"rc-tree\",showLine:!1,showIcon:!0,selectable:!0,multiple:!1,checkable:!1,disabled:!1,checkStrictly:!1,draggable:!1,defaultExpandParent:!0,autoExpandParent:!1,defaultExpandAll:!1,defaultExpandedKeys:[],defaultCheckedKeys:[],defaultSelectedKeys:[]}),data:function(){cc(this.$props.__propsSymbol__),cc(this.$props.children),this.needSyncKeys={},this.domTreeNodes={};var t={_posEntities:new Map,_keyEntities:new Map,_expandedKeys:[],_selectedKeys:[],_checkedKeys:[],_halfCheckedKeys:[],_loadedKeys:[],_loadingKeys:[],_treeNode:[],_prevProps:null,_dragOverNodeKey:\"\",_dropPosition:null,_dragNodesKeys:[]};return P(P({},t),this.getDerivedState(Qe(this),t))},watch:P(P({},nAe([\"treeData\",\"children\",\"expandedKeys\",\"autoExpandParent\",\"selectedKeys\",\"checkedKeys\",\"loadedKeys\"])),{__propsSymbol__:function(){this.setState(this.getDerivedState(Qe(this),this.$data)),this.needSyncKeys={}}}),methods:{getDerivedState:function(t,n){var r=n._prevProps,a={_prevProps:P({},t)},o=this;function i(C){return!r&&C in t||r&&o.needSyncKeys[C]}var l=null;if(i(\"treeData\")?l=WS(t.treeData):i(\"children\")&&(l=t.children),l){a._treeNode=l;var s=Dg(l);a._keyEntities=s.keyEntities}var c=a._keyEntities||n._keyEntities;if(i(\"expandedKeys\")||r&&i(\"autoExpandParent\")?a._expandedKeys=t.autoExpandParent||!r&&t.defaultExpandParent?N1(t.expandedKeys,c):t.expandedKeys:!r&&t.defaultExpandAll?a._expandedKeys=Je(c.keys()):!r&&t.defaultExpandedKeys&&(a._expandedKeys=t.autoExpandParent||t.defaultExpandParent?N1(t.defaultExpandedKeys,c):t.defaultExpandedKeys),t.selectable&&(i(\"selectedKeys\")?a._selectedKeys=n_(t.selectedKeys,t):!r&&t.defaultSelectedKeys&&(a._selectedKeys=n_(t.defaultSelectedKeys,t))),t.checkable){var d;if(i(\"checkedKeys\")?d=Pb(t.checkedKeys)||{}:!r&&t.defaultCheckedKeys?d=Pb(t.defaultCheckedKeys)||{}:l&&(d=Pb(t.checkedKeys)||{checkedKeys:n._checkedKeys,halfCheckedKeys:n._halfCheckedKeys}),d){var f=d,p=f.checkedKeys,v=p===void 0?[]:p,m=f.halfCheckedKeys,y=m===void 0?[]:m;if(!t.checkStrictly){var b=I1(v,!0,c);v=b.checkedKeys,y=b.halfCheckedKeys}a._checkedKeys=v,a._halfCheckedKeys=y}}return i(\"loadedKeys\")&&(a._loadedKeys=t.loadedKeys),a},onNodeDragStart:function(t,n){var r=this.$data._expandedKeys,a=n.eventKey,o=ht(n);this.dragNode=n,this.setState({_dragNodesKeys:eAe(typeof o==\"function\"?o():o,n),_expandedKeys:eu(r,a)}),this.__emit(\"dragstart\",{event:t,node:n})},onNodeDragEnter:function(t,n){var r=this,a=this.$data._expandedKeys,o=n.pos,i=n.eventKey;if(!(!this.dragNode||!n.selectHandle)){var l=t_(t,n);if(this.dragNode.eventKey===i&&l===0){this.setState({_dragOverNodeKey:\"\",_dropPosition:null});return}setTimeout(function(){r.setState({_dragOverNodeKey:i,_dropPosition:l}),r.delayedDragEnterLogic||(r.delayedDragEnterLogic={}),Object.keys(r.delayedDragEnterLogic).forEach(function(s){clearTimeout(r.delayedDragEnterLogic[s])}),r.delayedDragEnterLogic[o]=setTimeout(function(){var s=tu(a,i);vt(r,\"expandedKeys\")||r.setState({_expandedKeys:s}),r.__emit(\"dragenter\",{event:t,node:n,expandedKeys:s})},400)},0)}},onNodeDragOver:function(t,n){var r=n.eventKey,a=this.$data,o=a._dragOverNodeKey,i=a._dropPosition;if(this.dragNode&&r===o&&n.selectHandle){var l=t_(t,n);if(l===i)return;this.setState({_dropPosition:l})}this.__emit(\"dragover\",{event:t,node:n})},onNodeDragLeave:function(t,n){this.setState({_dragOverNodeKey:\"\"}),this.__emit(\"dragleave\",{event:t,node:n})},onNodeDragEnd:function(t,n){this.setState({_dragOverNodeKey:\"\"}),this.__emit(\"dragend\",{event:t,node:n}),this.dragNode=null},onNodeDrop:function(t,n){var r=this.$data,a=r._dragNodesKeys,o=a===void 0?[]:a,i=r._dropPosition,l=n.eventKey,s=n.pos;if(this.setState({_dragOverNodeKey:\"\"}),o.indexOf(l)===-1){var c=JNe(s),d={event:t,node:n,dragNode:this.dragNode,dragNodesKeys:o.slice(),dropPosition:i+Number(c[c.length-1]),dropToGap:!1};i!==0&&(d.dropToGap=!0),this.__emit(\"drop\",d),this.dragNode=null}},onNodeClick:function(t,n){this.__emit(\"click\",t,n)},onNodeDoubleClick:function(t,n){this.__emit(\"dblclick\",t,n)},onNodeSelect:function(t,n){var r=this.$data._selectedKeys,a=this.$data._keyEntities,o=this.$props.multiple,i=Qe(n),l=i.selected,s=i.eventKey,c=!l;c?o?r=tu(r,s):r=[s]:r=eu(r,s);var d=r.map(function(p){var v=a.get(p);return v?v.node:null}).filter(function(p){return p});this.setUncontrolledState({_selectedKeys:r});var f={event:\"select\",selected:c,node:n,selectedNodes:d,nativeEvent:t};this.__emit(\"select\",r,f)},onNodeCheck:function(t,n,r){var a=this.$data,o=a._keyEntities,i=a._checkedKeys,l=a._halfCheckedKeys,s=this.$props.checkStrictly,c=Qe(n),d=c.eventKey,f,p={event:\"check\",node:n,checked:r,nativeEvent:t};if(s){var v=r?tu(i,d):eu(i,d),m=eu(l,d);f={checked:v,halfChecked:m},p.checkedNodes=v.map(function(S){return o.get(S)}).filter(function(S){return S}).map(function(S){return S.node}),this.setUncontrolledState({_checkedKeys:v})}else{var y=I1([d],r,o,{checkedKeys:i,halfCheckedKeys:l}),b=y.checkedKeys,C=y.halfCheckedKeys;f=b,p.checkedNodes=[],p.checkedNodesPositions=[],p.halfCheckedKeys=C,b.forEach(function(S){var w=o.get(S);if(!!w){var k=w.node,$=w.pos;p.checkedNodes.push(k),p.checkedNodesPositions.push({node:k,pos:$})}}),this.setUncontrolledState({_checkedKeys:b,_halfCheckedKeys:C})}this.__emit(\"check\",f,p)},onNodeLoad:function(t){var n=this;return new Promise(function(r){n.setState(function(a){var o=a._loadedKeys,i=o===void 0?[]:o,l=a._loadingKeys,s=l===void 0?[]:l,c=n.$props.loadData,d=Qe(t),f=d.eventKey;if(!c||i.indexOf(f)!==-1||s.indexOf(f)!==-1)return{};var p=c(t);return p.then(function(){var v=n.$data,m=v._loadedKeys,y=v._loadingKeys,b=tu(m,f),C=eu(y,f);n.__emit(\"load\",b,{event:\"load\",node:t}),n.setUncontrolledState({_loadedKeys:b}),n.setState({_loadingKeys:C}),r()}),{_loadingKeys:tu(s,f)}})})},onNodeExpand:function(t,n){var r=this,a=this.$data._expandedKeys,o=this.$props.loadData,i=Qe(n),l=i.eventKey,s=i.expanded;a.indexOf(l);var c=!s;if(c?a=tu(a,l):a=eu(a,l),this.setUncontrolledState({_expandedKeys:a}),this.__emit(\"expand\",a,{node:n,expanded:c,nativeEvent:t}),c&&o){var d=this.onNodeLoad(n);return d?d.then(function(){r.setUncontrolledState({_expandedKeys:a})}):null}return null},onNodeMouseEnter:function(t,n){this.__emit(\"mouseenter\",{event:t,node:n})},onNodeMouseLeave:function(t,n){this.__emit(\"mouseleave\",{event:t,node:n})},onNodeContextMenu:function(t,n){t.preventDefault(),this.__emit(\"rightClick\",{event:t,node:n})},setUncontrolledState:function(t){var n=!1,r={},a=Qe(this);Object.keys(t).forEach(function(o){o.replace(\"_\",\"\")in a||(n=!0,r[o]=t[o])}),n&&this.setState(r)},registerTreeNode:function(t,n){n?this.domTreeNodes[t]=n:delete this.domTreeNodes[t]},isKeyChecked:function(t){var n=this.$data._checkedKeys,r=n===void 0?[]:n;return r.indexOf(t)!==-1},renderTreeNode:function(t,n){var r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,a=this.$data,o=a._keyEntities,i=a._expandedKeys,l=i===void 0?[]:i,s=a._selectedKeys,c=s===void 0?[]:s,d=a._halfCheckedKeys,f=d===void 0?[]:d,p=a._loadedKeys,v=p===void 0?[]:p,m=a._loadingKeys,y=m===void 0?[]:m,b=a._dragOverNodeKey,C=a._dropPosition,S=DR(r,n),w=t.key;return!w&&w==null&&(w=S),o.get(w)?Ot(t,{eventKey:w,expanded:l.indexOf(w)!==-1,selected:c.indexOf(w)!==-1,loaded:v.indexOf(w)!==-1,loading:y.indexOf(w)!==-1,checked:this.isKeyChecked(w),halfChecked:f.indexOf(w)!==-1,pos:S,dragOver:b===w&&C===0,dragOverGapTop:b===w&&C===-1,dragOverGapBottom:b===w&&C===1,key:w}):null}},render:function(){var t=this,n=this.$data._treeNode,r=this.$props,a=r.prefixCls,o=r.focusable,i=r.showLine,l=r.tabindex,s=l===void 0?0:l,c=US(P(P({},this.$props),this.$attrs)),d=this.$attrs,f=d.class,p=d.style;return g(\"ul\",le(le({},c),{},{class:Se(a,f,V({},\"\".concat(a,\"-show-line\"),i)),style:p,role:\"tree\",unselectable:\"on\",tabindex:o?s:null}),[LR(n,function(v,m){return t.renderTreeNode(v,m)})])}}),Wf=rAe;Wf.TreeNode=AR;var r_=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},aAe=Wf.TreeNode;function FR(){return{showLine:u.looseBool,multiple:u.looseBool,autoExpandParent:u.looseBool,checkStrictly:u.looseBool,checkable:u.looseBool,disabled:u.looseBool,defaultExpandAll:u.looseBool,defaultExpandParent:u.looseBool,defaultExpandedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),expandedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),checkedKeys:u.oneOfType([u.arrayOf(u.oneOfType([u.string,u.number])),u.shape({checked:u.arrayOf(u.oneOfType([u.string,u.number])),halfChecked:u.arrayOf(u.oneOfType([u.string,u.number]))}).loose]),defaultCheckedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),selectedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),defaultSelectedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),selectable:u.looseBool,filterAntTreeNode:u.func,loadData:u.func,loadedKeys:u.arrayOf(u.oneOfType([u.string,u.number])),draggable:u.looseBool,showIcon:u.looseBool,icon:u.func,switcherIcon:u.any,prefixCls:u.string,filterTreeNode:u.func,openAnimation:u.any,treeData:{type:Array},replaceFields:u.object,blockNode:u.looseBool,onExpand:u.func,onCheck:u.func,onSelect:u.func,onClick:u.func,onDoubleclick:u.func,onDblclick:u.func,\"onUpdate:selectedKeys\":u.func,\"onUpdate:checkedKeys\":u.func,\"onUpdate:expandedKeys\":u.func}}var Po=G({name:\"ATree\",inheritAttrs:!1,props:Rn(FR(),{checkable:!1,showIcon:!1,openAnimation:P(P({},PD),{appear:null}),blockNode:!1}),setup:function(){return{tree:null,configProvider:ve(\"configProvider\",St)}},TreeNode:aAe,methods:{renderSwitcherIcon:function(t,n,r){var a=r.isLeaf,o=r.loading,i=r.expanded,l=this.$props.showLine;if(o)return g(co,{class:\"\".concat(t,\"-switcher-loading-icon\")},null);if(a)return l?g(zS,{class:\"\".concat(t,\"-switcher-line-icon\")},null):null;var s=\"\".concat(t,\"-switcher-icon\");return n?Ot(n,{class:s}):l?i?g(jNe,{class:\"\".concat(t,\"-switcher-line-icon\")},null):g(YNe,{class:\"\".concat(t,\"-switcher-line-icon\")},null):g(SR,{class:s},null)},updateTreeData:function(t){var n=this,r=this.$slots,a={children:\"children\",title:\"title\",key:\"key\"},o=P(P({},a),this.$props.replaceFields);return t.map(function(i){var l=i[o.key],s=i[o.children],c=i.slots,d=c===void 0?{}:c,f=i.class,p=i.style,v=r_(i,[\"slots\",\"class\",\"style\"]),m=P(P({},v),{icon:r[d.icon]||v.icon,switcherIcon:r[d.switcherIcon]||v.switcherIcon,title:r[d.title]||r.title||v[o.title],dataRef:i,key:l,class:f,style:p});return s?P(P({},m),{children:n.updateTreeData(s)}):m})},setTreeRef:function(t){this.tree=t},handleCheck:function(t,n){this.$emit(\"update:checkedKeys\",t),this.$emit(\"check\",t,n)},handleExpand:function(t,n){this.$emit(\"update:expandedKeys\",t),this.$emit(\"expand\",t,n)},handleSelect:function(t,n){this.$emit(\"update:selectedKeys\",t),this.$emit(\"select\",t,n)}},render:function(){var t=this,n,r=Qe(this),a=r.prefixCls,o=r.showIcon,i=r.treeNodes,l=r.blockNode,s=this.configProvider.getPrefixCls,c=s(\"tree\",a),d=We(this,\"switcherIcon\"),f=r.checkable,p=r.treeData||i;p&&(p=this.updateTreeData(p));var v=this.$attrs,m=v.class,y=r_(v,[\"class\"]),b=P(P(P(P({},r),{prefixCls:c,checkable:f&&g(\"span\",{class:\"\".concat(c,\"-checkbox-inner\")},null),children:ht(this),switcherIcon:function(S){return t.renderSwitcherIcon(c,d,S)},ref:this.setTreeRef}),y),{class:Se(m,(n={},V(n,\"\".concat(c,\"-icon-hide\"),!o),V(n,\"\".concat(c,\"-block-node\"),l),n)),onCheck:this.handleCheck,onExpand:this.handleExpand,onSelect:this.handleSelect});return p&&(b.treeData=p),g(Wf,le(le({},b),{},{__propsSymbol__:[]}),null)}}),oAe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M928 444H820V330.4c0-17.7-14.3-32-32-32H473L355.7 186.2a8.15 8.15 0 00-5.5-2.2H96c-17.7 0-32 14.3-32 32v592c0 17.7 14.3 32 32 32h698c13 0 24.8-7.9 29.7-20l134-332c1.5-3.8 2.3-7.9 2.3-12 0-17.7-14.3-32-32-32zM136 256h188.5l119.6 114.4H748V444H238c-13 0-24.8 7.9-29.7 20L136 643.2V256zm635.3 512H159l103.3-256h612.4L771.3 768z\"}}]},name:\"folder-open\",theme:\"outlined\"},iAe=oAe;function a_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){lAe(e,a,n[a])})}return e}function lAe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var YS=function(t,n){var r=a_({},t,n.attrs);return g(Et,a_({},r,{icon:iAe}),null)};YS.displayName=\"FolderOpenOutlined\";YS.inheritAttrs=!1;var sAe=YS,uAe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M880 298.4H521L403.7 186.2a8.15 8.15 0 00-5.5-2.2H144c-17.7 0-32 14.3-32 32v592c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V330.4c0-17.7-14.3-32-32-32zM840 768H184V256h188.5l119.6 114.4H840V768z\"}}]},name:\"folder\",theme:\"outlined\"},cAe=uAe;function o_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){dAe(e,a,n[a])})}return e}function dAe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var qS=function(t,n){var r=o_({},t,n.attrs);return g(Et,o_({},r,{icon:cAe}),null)};qS.displayName=\"FolderOutlined\";qS.inheritAttrs=!1;var fAe=qS,ni;(function(e){e[e.None=0]=\"None\",e[e.Start=1]=\"Start\",e[e.End=2]=\"End\"})(ni||(ni={}));function GS(e,t){var n=KS(e)||[];function r(a){var o=a.key,i=ht(a);t(o,a)!==!1&&GS(i,t)}n.forEach(r)}function hAe(e){var t=Dg(e),n=t.keyEntities;return Je(n.keys())}function pAe(e,t,n,r){var a=[],o=ni.None;if(n&&n===r)return[n];if(!n||!r)return[];function i(l){return l===n||l===r}return GS(e,function(l){if(o===ni.End)return!1;if(i(l)){if(a.push(l),o===ni.None)o=ni.Start;else if(o===ni.Start)return o=ni.End,!1}else o===ni.Start&&a.push(l);return t.indexOf(l)!==-1}),a}function i_(e,t){var n=Je(t),r=[];return GS(e,function(a,o){var i=n.indexOf(a);return i!==-1&&(r.push(o),n.splice(i,1)),!!n.length}),r}function BR(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=[],r=t.key,a=r===void 0?\"key\":r,o=t.children,i=o===void 0?\"children\":o;return(e||[]).forEach(function(l){n.push(l[a]),l[i]&&(n=[].concat(Je(n),Je(BR(l[i],t))))}),n}var l_=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function vAe(e){var t=e.isLeaf,n=e.expanded;return g(t?zS:n?sAe:fAe,null,null)}var dm=G({name:\"ADirectoryTree\",mixins:[nt],inheritAttrs:!1,props:Rn(P(P({},FR()),{expandAction:u.oneOf([!1,\"click\",\"doubleclick\",\"dblclick\"])}),{showIcon:!0,expandAction:\"click\"}),setup:function(){return{children:null,onDebounceExpand:null,tree:null,lastSelectedKey:\"\",cachedSelectedKeys:[],configProvider:ve(\"configProvider\",St)}},data:function(){var t=Qe(this),n=t.defaultExpandAll,r=t.defaultExpandParent,a=t.expandedKeys,o=t.defaultExpandedKeys,i=ht(this),l=Dg(i),s=l.keyEntities,c={};return c._selectedKeys=t.selectedKeys||t.defaultSelectedKeys||[],n?t.treeData?c._expandedKeys=BR(t.treeData,t.replaceFields):c._expandedKeys=hAe(i):r?c._expandedKeys=N1(a||o,s):c._expandedKeys=a||o,P({_selectedKeys:[],_expandedKeys:[]},c)},watch:{expandedKeys:function(t){this.setState({_expandedKeys:t})},selectedKeys:function(t){this.setState({_selectedKeys:t})}},created:function(){this.onDebounceExpand=Yn(this.expandFolderNode,200,{leading:!0})},methods:{handleExpand:function(t,n){this.setUncontrolledState({_expandedKeys:t}),this.$emit(\"update:expandedKeys\",t),this.$emit(\"expand\",t,n)},handleClick:function(t,n){var r=this.$props.expandAction;r===\"click\"&&this.onDebounceExpand(t,n),this.$emit(\"click\",t,n)},handleDoubleClick:function(t,n){var r=this.$props.expandAction;(r===\"dblclick\"||r===\"doubleclick\")&&this.onDebounceExpand(t,n),this.$emit(\"doubleclick\",t,n),this.$emit(\"dblclick\",t,n)},hanldeSelect:function(t,n){var r=this.$props.multiple,a=this.children||[],o=this.$data._expandedKeys,i=o===void 0?[]:o,l=n.node,s=n.nativeEvent,c=l.eventKey,d=c===void 0?\"\":c,f={},p=P(P({},n),{selected:!0}),v=s.ctrlKey||s.metaKey,m=s.shiftKey,y;r&&v?(y=t,this.lastSelectedKey=d,this.cachedSelectedKeys=y,p.selectedNodes=i_(a,y)):r&&m?(y=Array.from(new Set([].concat(Je(this.cachedSelectedKeys||[]),Je(pAe(a,i,d,this.lastSelectedKey))))),p.selectedNodes=i_(a,y)):(y=[d],this.lastSelectedKey=d,this.cachedSelectedKeys=y,p.selectedNodes=[n.node]),f._selectedKeys=y,this.$emit(\"update:selectedKeys\",y),this.$emit(\"select\",y,p),this.setUncontrolledState(f)},setTreeRef:function(t){this.tree=t},expandFolderNode:function(t,n){var r=n.isLeaf;if(!(r||t.shiftKey||t.metaKey||t.ctrlKey)&&this.tree.tree){var a=this.tree.tree;a.onNodeExpand(t,n)}},setUncontrolledState:function(t){var n=bn(t,Object.keys(Qe(this)).map(function(r){return\"_\".concat(r)}));Object.keys(n).length&&this.setState(n)},handleCheck:function(t,n){this.$emit(\"update:checkedKeys\",t),this.$emit(\"check\",t,n)}},render:function(){var t=this;this.children=ht(this);var n=Qe(this),r=n.prefixCls,a=l_(n,[\"prefixCls\"]),o=this.configProvider.getPrefixCls,i=o(\"tree\",r),l=this.$data,s=l._expandedKeys,c=l._selectedKeys,d=this.$attrs,f=d.class,p=l_(d,[\"class\"]),v=Se(\"\".concat(i,\"-directory\"),f),m=P(P(P({icon:vAe},p),bn(a,[\"onUpdate:selectedKeys\",\"onUpdate:checkedKeys\",\"onUpdate:expandedKeys\"])),{prefixCls:i,expandedKeys:s,selectedKeys:c,switcherIcon:We(this,\"switcherIcon\"),ref:this.setTreeRef,class:v,onSelect:this.hanldeSelect,onClick:this.handleClick,onDblclick:this.handleDoubleClick,onExpand:this.handleExpand,onCheck:this.handleCheck});return g(Po,m,le({default:function(){return[t.children]}},bn(this.$slots,[\"default\"])))}});Po.TreeNode.name=\"ATreeNode\";Po.DirectoryTree=dm;Po.install=function(e){return e.component(Po.name,Po),e.component(Po.TreeNode.name,Po.TreeNode),e.component(dm.name,dm),e};var mAe=Po.TreeNode;function Jp(e){return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?Jp=function(t){return typeof t}:Jp=function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},Jp(e)}function gAe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s_(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),n.push.apply(n,r)}return n}function yAe(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?s_(n,!0).forEach(function(r){gAe(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):s_(n).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}var bAe=/[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source;function CAe(e){var t,n,r,a=e.ownerDocument,o=a.body,i=a&&a.documentElement;return t=e.getBoundingClientRect(),n=t.left,r=t.top,n-=i.clientLeft||o.clientLeft||0,r-=i.clientTop||o.clientTop||0,{left:n,top:r}}function VR(e,t){var n=e[\"page\".concat(t?\"Y\":\"X\",\"Offset\")],r=\"scroll\".concat(t?\"Top\":\"Left\");if(typeof n!=\"number\"){var a=e.document;n=a.documentElement[r],typeof n!=\"number\"&&(n=a.body[r])}return n}function A1(e){return VR(e)}function D1(e){return VR(e,!0)}function zR(e){var t=CAe(e),n=e.ownerDocument,r=n.defaultView||n.parentWindow;return t.left+=A1(r),t.top+=D1(r),t}function wAe(e,t,n){var r=\"\",a=e.ownerDocument,o=n||a.defaultView.getComputedStyle(e,null);return o&&(r=o.getPropertyValue(t)||o[t]),r}var SAe=new RegExp(\"^(\".concat(bAe,\")(?!px)[a-z%]+$\"),\"i\"),kAe=/^(top|right|bottom|left)$/,Tb=\"currentStyle\",xb=\"runtimeStyle\",El=\"left\",$Ae=\"px\";function OAe(e,t){var n=e[Tb]&&e[Tb][t];if(SAe.test(n)&&!kAe.test(t)){var r=e.style,a=r[El],o=e[xb][El];e[xb][El]=e[Tb][El],r[El]=t===\"fontSize\"?\"1em\":n||0,n=r.pixelLeft+$Ae,r[El]=a,e[xb][El]=o}return n===\"\"?\"auto\":n}var Ss;typeof window!=\"undefined\"&&(Ss=window.getComputedStyle?wAe:OAe);function XS(e,t){for(var n=0;n<e.length;n++)t(e[n])}function HR(e){return Ss(e,\"boxSizing\")===\"border-box\"}var PAe=[\"margin\",\"border\",\"padding\"],R1=-1,TAe=2,L1=1,xAe=0;function _Ae(e,t,n){var r={},a=e.style,o;for(o in t)t.hasOwnProperty(o)&&(r[o]=a[o],a[o]=t[o]);n.call(e);for(o in t)t.hasOwnProperty(o)&&(a[o]=r[o])}function sd(e,t,n){var r=0,a,o,i;for(o=0;o<t.length;o++)if(a=t[o],a)for(i=0;i<n.length;i++){var l=void 0;a===\"border\"?l=\"\".concat(a+n[i],\"Width\"):l=a+n[i],r+=parseFloat(Ss(e,l))||0}return r}function Qp(e){return e!=null&&e==e.window}var Eo={};XS([\"Width\",\"Height\"],function(e){Eo[\"doc\".concat(e)]=function(t){var n=t.document;return Math.max(n.documentElement[\"scroll\".concat(e)],n.body[\"scroll\".concat(e)],Eo[\"viewport\".concat(e)](n))},Eo[\"viewport\".concat(e)]=function(t){var n=\"client\".concat(e),r=t.document,a=r.body,o=r.documentElement,i=o[n];return r.compatMode===\"CSS1Compat\"&&i||a&&a[n]||i}});function u_(e,t,n){if(Qp(e))return t===\"width\"?Eo.viewportWidth(e):Eo.viewportHeight(e);if(e.nodeType===9)return t===\"width\"?Eo.docWidth(e):Eo.docHeight(e);var r=t===\"width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"],a=t===\"width\"?e.offsetWidth:e.offsetHeight;Ss(e);var o=HR(e),i=0;(a==null||a<=0)&&(a=void 0,i=Ss(e,t),(i==null||Number(i)<0)&&(i=e.style[t]||0),i=parseFloat(i)||0),n===void 0&&(n=o?L1:R1);var l=a!==void 0||o,s=a||i;if(n===R1)return l?s-sd(e,[\"border\",\"padding\"],r):i;if(l){var c=n===TAe?-sd(e,[\"border\"],r):sd(e,[\"margin\"],r);return s+(n===L1?0:c)}return i+sd(e,PAe.slice(n),r)}var EAe={position:\"absolute\",visibility:\"hidden\",display:\"block\"};function c_(e){var t,n=arguments;return e.offsetWidth!==0?t=u_.apply(void 0,n):_Ae(e,EAe,function(){t=u_.apply(void 0,n)}),t}function Fu(e,t,n){var r=n;if(Jp(t)===\"object\"){for(var a in t)t.hasOwnProperty(a)&&Fu(e,a,t[a]);return}if(typeof r!=\"undefined\"){typeof r==\"number\"&&(r+=\"px\"),e.style[t]=r;return}return Ss(e,t)}XS([\"width\",\"height\"],function(e){var t=e.charAt(0).toUpperCase()+e.slice(1);Eo[\"outer\".concat(t)]=function(r,a){return r&&c_(r,e,a?xAe:L1)};var n=e===\"width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"];Eo[e]=function(r,a){if(a!==void 0){if(r){Ss(r);var o=HR(r);return o&&(a+=sd(r,[\"padding\",\"border\"],n)),Fu(r,e,a)}return}return r&&c_(r,e,R1)}});function MAe(e,t){Fu(e,\"position\")===\"static\"&&(e.style.position=\"relative\");var n=zR(e),r={},a,o;for(o in t)t.hasOwnProperty(o)&&(a=parseFloat(Fu(e,o))||0,r[o]=a+t[o]-n[o]);Fu(e,r)}var On=yAe({getWindow:function(t){var n=t.ownerDocument||t;return n.defaultView||n.parentWindow},offset:function(t,n){if(typeof n!=\"undefined\")MAe(t,n);else return zR(t)},isWindow:Qp,each:XS,css:Fu,clone:function(t){var n={};for(var r in t)t.hasOwnProperty(r)&&(n[r]=t[r]);var a=t.overflow;if(a)for(var o in t)t.hasOwnProperty(o)&&(n.overflow[o]=t.overflow[o]);return n},scrollLeft:function(t,n){if(Qp(t)){if(n===void 0)return A1(t);window.scrollTo(n,D1(t))}else{if(n===void 0)return t.scrollLeft;t.scrollLeft=n}},scrollTop:function(t,n){if(Qp(t)){if(n===void 0)return D1(t);window.scrollTo(A1(t),n)}else{if(n===void 0)return t.scrollTop;t.scrollTop=n}},viewportWidth:0,viewportHeight:0},Eo);function IAe(e,t,n){n=n||{},t.nodeType===9&&(t=On.getWindow(t));var r=n.allowHorizontalScroll,a=n.onlyScrollIfNeeded,o=n.alignWithTop,i=n.alignWithLeft,l=n.offsetTop||0,s=n.offsetLeft||0,c=n.offsetBottom||0,d=n.offsetRight||0;r=r===void 0?!0:r;var f=On.isWindow(t),p=On.offset(e),v=On.outerHeight(e),m=On.outerWidth(e),y,b,C,S,w,k,$,O,T,_;f?($=t,_=On.height($),T=On.width($),O={left:On.scrollLeft($),top:On.scrollTop($)},w={left:p.left-O.left-s,top:p.top-O.top-l},k={left:p.left+m-(O.left+T)+d,top:p.top+v-(O.top+_)+c},S=O):(y=On.offset(t),b=t.clientHeight,C=t.clientWidth,S={left:t.scrollLeft,top:t.scrollTop},w={left:p.left-(y.left+(parseFloat(On.css(t,\"borderLeftWidth\"))||0))-s,top:p.top-(y.top+(parseFloat(On.css(t,\"borderTopWidth\"))||0))-l},k={left:p.left+m-(y.left+C+(parseFloat(On.css(t,\"borderRightWidth\"))||0))+d,top:p.top+v-(y.top+b+(parseFloat(On.css(t,\"borderBottomWidth\"))||0))+c}),w.top<0||k.top>0?o===!0?On.scrollTop(t,S.top+w.top):o===!1?On.scrollTop(t,S.top+k.top):w.top<0?On.scrollTop(t,S.top+w.top):On.scrollTop(t,S.top+k.top):a||(o=o===void 0?!0:!!o,o?On.scrollTop(t,S.top+w.top):On.scrollTop(t,S.top+k.top)),r&&(w.left<0||k.left>0?i===!0?On.scrollLeft(t,S.left+w.left):i===!1?On.scrollLeft(t,S.left+k.left):w.left<0?On.scrollLeft(t,S.left+w.left):On.scrollLeft(t,S.left+k.left):a||(i=i===void 0?!0:!!i,i?On.scrollLeft(t,S.left+w.left):On.scrollLeft(t,S.left+k.left)))}function NAe(e,t){if(e.classList)return e.classList.contains(t);var n=e.className;return\" \".concat(n,\" \").indexOf(\" \".concat(t,\" \"))>-1}var ZS=\"SHOW_ALL\",Rg=\"SHOW_PARENT\",mf=\"SHOW_CHILD\";function AAe(e,t){for(var n=e;n;){if(NAe(n,t))return n;n=n.parentNode}return null}function jR(e){return typeof e==\"string\"?e:null}function DAe(e){return e==null?[]:Array.isArray(e)?e:[e]}function Si(){var e=function(n){e.current=n};return e}var RAe={userSelect:\"none\",WebkitUserSelect:\"none\"},LAe={unselectable:\"unselectable\"};function F1(e){if(!e.length)return[];var t={},n={},r=e.slice().map(function(a){var o=P(P({},a),{fields:a.pos.split(\"-\")});return delete o.children,o});return r.forEach(function(a){n[a.pos]=a}),r.sort(function(a,o){return a.fields.length-o.fields.length}),r.forEach(function(a){var o=a.fields.slice(0,-1).join(\"-\"),i=n[o];i?(i.children=i.children||[],i.children.push(a)):t[a.pos]=a,delete a.key,delete a.fields}),Object.keys(t).map(function(a){return t[a]})}var d_=0;function FAe(e){return d_+=1,\"\".concat(e,\"_\").concat(d_)}function KR(e){var t=e.treeCheckable,n=e.treeCheckStrictly,r=e.labelInValue;return t&&n?!0:r||!1}function BAe(e,t){var n=t.id,r=t.pId,a=t.rootPId,o={},i=[],l=e.map(function(s){var c=P({},s),d=c[n];return o[d]=c,c.key=c.key||d,c});return l.forEach(function(s){var c=s[r],d=o[c];d&&(d.children=d.children||[],d.children.push(s)),(c===a||!d&&a===null)&&i.push(s)}),i}function VAe(e,t){for(var n=e.split(\"-\"),r=t.split(\"-\"),a=Math.min(n.length,r.length),o=0;o<a;o+=1)if(n[o]!==r[o])return!1;return!0}function WR(e){var t=e.node,n=e.pos,r=e.children,a={node:t,pos:n};return r&&(a.children=r.map(WR)),a}function f_(e,t,n,r,a){if(!t)return null;function o(i){if(!i||As(i))return null;var l=!1;n(t,i)&&(l=!0);var s=ht(i);return s=((typeof s==\"function\"?s():s)||[]).map(o).filter(function(c){return c}),s.length||l?g(a,le(le({},i.props),{},{key:r[rr(i).value].key}),{default:function(){return[s]}}):null}return e.map(o).filter(function(i){return i})}function h_(e,t){var n=DAe(e);return KR(t)?n.map(function(r){return kt(r)!==\"object\"||!r?{value:\"\",label:\"\"}:r}):n.map(function(r){return{value:r}})}function _b(e,t,n){if(e.label)return e.label;if(t){var r=rr(t.node);if(Object.keys(r).length)return r[n]}return e.value}function Eb(e,t,n){var r=t.treeNodeLabelProp,a=t.treeCheckable,o=t.treeCheckStrictly,i=t.showCheckedStrategy;if(a&&!o){var l={};e.forEach(function(f){l[f.value]=f});var s=F1(e.map(function(f){var p=f.value;return n[p]}));if(i===Rg)return s.map(function(f){var p=f.node,v=rr(p).value;return{label:_b(l[v],n[v],r),value:v}});if(i===mf){var c=[],d=function f(p){var v=p.node,m=p.children,y=rr(v).value;if(!m||m.length===0){c.push({label:_b(l[y],n[y],r),value:y});return}m.forEach(function(b){f(b)})};return s.forEach(function(f){d(f)}),c}}return e.map(function(f){return{label:_b(f,n[f.value],r),value:f.value}})}function zAe(e){var t=e.title,n=e.label,r=e.key,a=e.value,o=P({},e);return n&&!t&&(o.title=n),!r&&r==null&&(o.key=a),o}function p_(e){return WS(e,{processProps:zAe})}function HAe(e){return P(P({},e),{valueEntities:{}})}function jAe(e,t){var n=rr(e.node).value;e.value=n;var r=t.valueEntities[n];r&&cc(!1,\"Conflict! value of node '\".concat(e.key,\"' (\").concat(n,\") has already used by node '\").concat(r.key,\"'.\")),t.valueEntities[n]=e}function KAe(e){return Dg(e,{initWrapper:HAe,processEntity:jAe})}function v_(e,t){var n={};return e.forEach(function(r){var a=r.value;n[a]=!1}),e.forEach(function(r){for(var a=r.value,o=t[a];o&&o.parent;){var i=o.parent.value;if(i in n)break;n[i]=!0,o=o.parent}}),Object.keys(n).filter(function(r){return n[r]}).map(function(r){return t[r].key})}var Jh=I1,WAe={bottomLeft:{points:[\"tl\",\"bl\"],offset:[0,4],overflow:{adjustX:0,adjustY:1},ignoreShake:!0},topLeft:{points:[\"bl\",\"tl\"],offset:[0,-4],overflow:{adjustX:0,adjustY:1},ignoreShake:!0}},UAe={name:\"SelectTrigger\",inheritAttrs:!1,props:{disabled:u.looseBool,showSearch:u.looseBool,prefixCls:u.string,dropdownPopupAlign:u.object,dropdownClassName:u.string,dropdownStyle:u.object,transitionName:u.string,animation:u.string,getPopupContainer:u.func,dropdownMatchSelectWidth:u.looseBool,isMultiple:u.looseBool,dropdownPrefixCls:u.string,dropdownVisibleChange:u.func,popupElement:u.any,open:u.looseBool},created:function(){this.triggerRef=Si()},methods:{getDropdownTransitionName:function(){var t=this.$props,n=t.transitionName,r=t.animation,a=t.dropdownPrefixCls;return!n&&r?\"\".concat(a,\"-\").concat(r):n},forcePopupAlign:function(){var t=this.triggerRef.current;t&&t.forcePopupAlign()}},render:function(){var t,n=this,r=this.$props,a=r.disabled,o=r.isMultiple,i=r.dropdownPopupAlign,l=r.dropdownMatchSelectWidth,s=r.dropdownClassName,c=r.dropdownStyle,d=r.dropdownVisibleChange,f=r.getPopupContainer,p=r.dropdownPrefixCls,v=r.popupElement,m=r.open,y;return l!==!1&&(y=l?\"width\":\"minWidth\"),g(Ii,{ref:this.triggerRef,action:a?[]:[\"click\"],popupPlacement:\"bottomLeft\",builtinPlacements:WAe,popupAlign:i,prefixCls:p,popupTransitionName:this.getDropdownTransitionName(),onPopupVisibleChange:d,popup:v,popupVisible:m,getPopupContainer:f,stretch:y,popupClassName:Se(s,(t={},V(t,\"\".concat(p,\"--multiple\"),o),V(t,\"\".concat(p,\"--single\"),!o),t)),popupStyle:c},{default:function(){return[ht(n)]}})}},YAe=UAe,JS=function(){return{prefixCls:u.string,open:u.looseBool,selectorValueList:u.array,allowClear:u.looseBool,showArrow:u.looseBool,removeSelected:u.func,choiceTransitionName:u.string,ariaId:u.string,inputIcon:u.any,clearIcon:u.any,removeIcon:u.any,placeholder:u.any,disabled:u.looseBool,focused:u.looseBool,isMultiple:u.looseBool,showSearch:u.looseBool,searchValue:u.string}};function qAe(){}function UR(){var e={name:\"BaseSelector\",inheritAttrs:!1,mixins:[nt],props:An(P(P({},JS()),{renderSelection:u.func.isRequired,renderPlaceholder:u.func,tabindex:u.oneOfType([u.number,u.string])}),{tabindex:0}),setup:function(){return{vcTreeSelect:ve(\"vcTreeSelect\",{})}},created:function(){this.domRef=Si()},methods:{onFocus:function(n){var r=this.$props.focused,a=this.vcTreeSelect.onSelectorFocus;r||a(),this.__emit(\"focus\",n)},onBlur:function(n){var r=this.vcTreeSelect.onSelectorBlur;r(),this.__emit(\"blur\",n)},focus:function(){this.domRef.current.focus()},blur:function(){this.domRef.current.blur()},renderClear:function(){var n=this.$props,r=n.prefixCls,a=n.allowClear,o=n.selectorValueList,i=this.vcTreeSelect.onSelectorClear;if(!a||!o.length)return null;var l=We(this,\"clearIcon\");return g(\"span\",{key:\"clear\",unselectable:\"on\",\"aria-hidden\":\"true\",style:\"user-select: none;\",class:\"\".concat(r,\"-clear\"),onClick:i},[l])},renderArrow:function(){var n=this.$props,r=n.prefixCls,a=n.showArrow;if(!a)return null;var o=We(this,\"inputIcon\");return g(\"span\",{key:\"arrow\",class:\"\".concat(r,\"-arrow\"),style:{outline:\"none\",userSelect:\"none\"}},[o])}},render:function(){var n,r=this.$props,a=r.prefixCls,o=r.open,i=r.focused,l=r.disabled,s=r.allowClear,c=r.ariaId,d=r.renderSelection,f=r.renderPlaceholder,p=r.tabindex,v=r.isMultiple,m=r.showArrow,y=r.showSearch,b=this.$attrs,C=b.class,S=b.style,w=b.onClick,k=w===void 0?qAe:w,$=this.vcTreeSelect.onSelectorKeyDown,O=p;l&&(O=null);var T=Se(a,C,(n={},V(n,\"\".concat(a,\"-focused\"),o||i),V(n,\"\".concat(a,\"-multiple\"),v),V(n,\"\".concat(a,\"-single\"),!v),V(n,\"\".concat(a,\"-allow-clear\"),s),V(n,\"\".concat(a,\"-show-arrow\"),m),V(n,\"\".concat(a,\"-disabled\"),l),V(n,\"\".concat(a,\"-open\"),o),V(n,\"\".concat(a,\"-show-search\"),y),n));return g(\"div\",{style:S,onClick:k,class:T,ref:this.domRef,role:\"combobox\",\"aria-expanded\":o,\"aria-owns\":o?c:void 0,\"aria-controls\":o?c:void 0,\"aria-haspopup\":\"listbox\",\"aria-disabled\":l,tabindex:O,onFocus:this.onFocus,onBlur:this.onBlur,onKeydown:$},[g(\"span\",{class:\"\".concat(a,\"-selector\")},[d(),f&&f()]),this.renderArrow(),this.renderClear()])}};return e}var GAe=G({props:{value:u.string.def(\"\")},emits:[\"change\",\"input\"],setup:function(t,n){var r=n.emit,a=H(null),o=function(l){var s=l.target.composing;l.isComposing||s?r(\"input\",l):(r(\"input\",l),r(\"change\",l))};return{inputRef:a,focus:function(){a.value&&a.value.focus()},blur:function(){a.value&&a.value.blur()},handleChange:o}},render:function(){return at(g(\"input\",le(le(le({},this.$props),this.$attrs),{},{onInput:this.handleChange,onChange:this.handleChange,ref:\"inputRef\"}),null),[[Mi]])}}),XAe=GAe,ZAe={name:\"SearchInput\",inheritAttrs:!1,props:{open:u.looseBool,searchValue:u.string,prefixCls:u.string,disabled:u.looseBool,renderPlaceholder:u.func,needAlign:u.looseBool,ariaId:u.string,isMultiple:u.looseBool.def(!0),showSearch:u.looseBool},emits:[\"mirrorSearchValueChange\"],setup:function(t,n){var r=n.emit,a=H(),o=H(0),i=H(t.searchValue);return ce(x(function(){return t.searchValue}),function(){i.value=t.searchValue}),ce(i,function(){r(\"mirrorSearchValueChange\",i.value)},{immediate:!0}),et(function(){t.isMultiple&&ce(i,function(){o.value=a.value.scrollWidth},{flush:\"post\",immediate:!0})}),{measureRef:a,inputWidth:o,vcTreeSelect:ve(\"vcTreeSelect\",{}),mirrorSearchValue:i}},created:function(){this.inputRef=Si(),this.prevProps=P({},this.$props)},mounted:function(){var t=this;this.$nextTick(function(){var n=t.$props.open;n&&t.focus(!0)})},updated:function(){var t=this,n=this.$props.open,r=this.prevProps;this.$nextTick(function(){n&&r.open!==n&&t.focus(),t.prevProps=P({},t.$props)})},methods:{focus:function(t){var n=this;this.inputRef.current&&(t?setTimeout(function(){n.inputRef.current.focus()},0):this.inputRef.current.focus())},blur:function(){this.inputRef.current&&this.inputRef.current.blur()},handleInputChange:function(t){var n=t.target,r=n.value,a=n.composing,o=this.searchValue,i=o===void 0?\"\":o;if(t.isComposing||a||i===r){this.mirrorSearchValue=r;return}this.vcTreeSelect.onSearchInputChange(t)}},render:function(){var t=this.$props,n=t.searchValue,r=t.prefixCls,a=t.disabled,o=t.renderPlaceholder,i=t.open,l=t.ariaId,s=t.isMultiple,c=t.showSearch,d=this.vcTreeSelect.onSearchInputKeyDown,f=this.handleInputChange,p=this.mirrorSearchValue,v=this.inputWidth;return g(Fe,null,[g(\"span\",{class:\"\".concat(r,\"-selection-search\"),style:s?{width:v+\"px\"}:{}},[g(XAe,{type:\"text\",ref:this.inputRef,onChange:f,onKeydown:d,value:n,disabled:a,readonly:!c,class:\"\".concat(r,\"-selection-search-input\"),\"aria-label\":\"filter select\",\"aria-autocomplete\":\"list\",\"aria-controls\":i?l:void 0,\"aria-multiline\":\"false\"},null),s?g(\"span\",{ref:\"measureRef\",class:\"\".concat(r,\"-selection-search-mirror\"),\"aria-hidden\":!0},[p,yt(\"\\xA0\")]):null]),o&&!p?o():null])}},B1=ZAe,JAe=UR(),QAe={name:\"SingleSelector\",inheritAttrs:!1,props:JS(),created:function(){this.selectorRef=Si(),this.inputRef=Si()},data:function(){return{mirrorSearchValue:this.searchValue}},watch:{searchValue:function(t){this.mirrorSearchValue=t}},methods:{onPlaceholderClick:function(){this.inputRef.current.focus()},focus:function(){this.selectorRef.current.focus()},blur:function(){this.selectorRef.current.blur()},_renderPlaceholder:function(){var t=this.$props,n=t.prefixCls,r=t.placeholder,a=t.searchPlaceholder,o=t.selectorValueList,i=r||a;if(!i)return null;var l=this.mirrorSearchValue||o.length;return g(\"span\",{style:{display:l?\"none\":\"block\"},onClick:this.onPlaceholderClick,class:\"\".concat(n,\"-selection-placeholder\")},[i])},onMirrorSearchValueChange:function(t){this.mirrorSearchValue=t},renderSelection:function(){var t=this.$props,n=t.selectorValueList,r=t.prefixCls,a=[];if(n.length&&!this.mirrorSearchValue){var o=n[0],i=o.label,l=o.value;a.push(g(\"span\",{key:l,title:jR(i),class:\"\".concat(r,\"-selection-item\")},[i||l]))}return a.push(g(B1,le(le(le({},this.$props),this.$attrs),{},{ref:this.inputRef,isMultiple:!1,onMirrorSearchValueChange:this.onMirrorSearchValueChange}),null)),a}},render:function(){var t=P(P(P({},Qe(this)),this.$attrs),{renderSelection:this.renderSelection,renderPlaceholder:this._renderPlaceholder,ref:this.selectorRef});return g(JAe,t,null)}},eDe=QAe,tDe={mixins:[nt],inheritAttrs:!1,props:{prefixCls:u.string,maxTagTextLength:u.number,label:u.any,value:u.oneOfType([u.string,u.number]),removeIcon:u.any},methods:{onRemove:function(t){var n=this.$props.value;this.__emit(\"remove\",t,n),t.stopPropagation()}},render:function(){var t=this.$props,n=t.prefixCls,r=t.maxTagTextLength,a=t.label,o=t.value,i=a||o;r&&typeof i==\"string\"&&i.length>r&&(i=\"\".concat(i.slice(0,r),\"...\"));var l=this.$attrs,s=l.class,c=l.style,d=l.onRemove;return g(\"span\",le(le({style:P(P({},RAe),c)},LAe),{},{role:\"menuitem\",class:Se(\"\".concat(n,\"-selection-item\"),s),title:jR(a)}),[g(\"span\",{class:\"\".concat(n,\"-selection-item-content\")},[i]),d&&g(\"span\",{class:\"\".concat(n,\"-selection-item-remove\"),onClick:this.onRemove},[We(this,\"removeIcon\")])])}},m_=tDe,nDe=\"RC_TREE_SELECT_EMPTY_VALUE_KEY\",rDe=UR(),aDe={name:\"MultipleSelector\",mixins:[nt],inheritAttrs:!1,props:P(P(P({},JS()),B1.props),{selectorValueList:u.array,disabled:u.looseBool,labelInValue:u.looseBool,maxTagCount:u.number,maxTagPlaceholder:u.any}),setup:function(){return{vcTreeSelect:ve(\"vcTreeSelect\",{})}},created:function(){this.inputRef=Si()},methods:{onPlaceholderClick:function(){this.inputRef.current.focus()},focus:function(){this.inputRef.current.focus()},blur:function(){this.inputRef.current.blur()},_renderPlaceholder:function(){var t=this.$props,n=t.prefixCls,r=t.placeholder,a=t.searchPlaceholder,o=t.searchValue,i=t.selectorValueList,l=r||a;if(!l)return null;var s=o||i.length;return g(\"span\",{style:{display:s?\"none\":\"block\"},onClick:this.onPlaceholderClick,class:\"\".concat(n,\"-selection-placeholder\")},[l])},onChoiceAnimationLeave:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.__emit.apply(this,[\"choiceAnimationLeave\"].concat(n))},renderSelection:function(){var t=this,n=this.$props,r=n.selectorValueList,a=n.labelInValue,o=n.maxTagCount,i=ht(this),l=this.vcTreeSelect.onMultipleSelectorRemove,s=r;o>=0&&(s=r.slice(0,o));var c=s.map(function(m){var y=m.label,b=m.value;return g(m_,le(le({},P(P({},t.$props),{label:y,value:b,onRemove:l})),{},{key:b||nDe}),{default:function(){return[i]}})});if(o>=0&&o<r.length){var d=\"+ \".concat(r.length-o,\" ...\"),f=We(this,\"maxTagPlaceholder\",{},!1);if(typeof f==\"string\")d=f;else if(typeof f==\"function\"){var p=r.slice(o);d=f(a?p:p.map(function(m){var y=m.value;return y}))}var v=g(m_,le(le({},P(P({},this.$props),{label:d,value:null})),{},{key:\"rc-tree-select-internal-max-tag-counter\"}),{default:function(){return[i]}});c.push(v)}return c.push(g(B1,le(le(le({key:\"SearchInput\"},this.$props),this.$attrs),{},{ref:this.inputRef}),{default:function(){return[i]}})),c}},render:function(){var t=this;return g(rDe,P(P(P({},this.$props),this.$attrs),{tabindex:-1,showArrow:!1,renderSelection:this.renderSelection,renderPlaceholder:this._renderPlaceholder}),{default:function(){return[ht(t)]}})}},oDe=aDe,iDe=Wf.TreeNode;function ks(e,t){var n=t.attrs,r=t.slots;return g(iDe,n,r)}ks.isTreeNode=!0;ks.inheritAttrs=!1;ks.displayName=\"ATreeSelectNode\";function g_(e,t){var n=t||{},r=n._prevProps,a=r===void 0?{}:r,o=n._loadedKeys,i=n._expandedKeyList,l=n._cachedExpandedKeyList,s=e.valueList,c=e.valueEntities,d=e.keyEntities,f=e.treeExpandedKeys,p=e.filteredTreeNodes,v=e.upperSearchValue,m={_prevProps:P({},e)};return s!==a.valueList&&(m._keyList=s.map(function(y){var b=y.value;return c[b]}).filter(function(y){return y}).map(function(y){var b=y.key;return b})),!f&&p&&p.length&&p!==a.filteredTreeNodes&&(m._expandedKeyList=Je(d.keys())),v&&!a.upperSearchValue?m._cachedExpandedKeyList=i:!v&&a.upperSearchValue&&!f&&(m._expandedKeyList=l||[],m._cachedExpandedKeyList=[]),a.treeExpandedKeys!==f&&(m._expandedKeyList=f),e.loadData&&(m._loadedKeys=o.filter(function(y){return d.has(y)})),m}var lDe={mixins:[nt],inheritAttrs:!1,name:\"BasePopup\",props:{prefixCls:u.string,upperSearchValue:u.string,valueList:u.array,searchHalfCheckedKeys:u.array,valueEntities:u.object,keyEntities:Map,treeIcon:u.looseBool,treeLine:u.looseBool,treeNodeFilterProp:u.string,treeCheckable:u.any,treeCheckStrictly:u.looseBool,treeDefaultExpandAll:u.looseBool,treeDefaultExpandedKeys:u.array,treeExpandedKeys:u.array,loadData:u.func,multiple:u.looseBool,searchValue:u.string,treeNodes:u.any,filteredTreeNodes:u.any,notFoundContent:u.any,ariaId:u.string,switcherIcon:u.any,renderSearch:u.func,__propsSymbol__:u.any},setup:function(){return{vcTreeSelect:ve(\"vcTreeSelect\",{})}},watch:{__propsSymbol__:function(){var t=g_(this.$props,this.$data);this.setState(t)}},data:function(){this.treeRef=Si(),cc(this.$props.__propsSymbol__);var t=this.$props,n=t.treeDefaultExpandAll,r=t.treeDefaultExpandedKeys,a=t.keyEntities,o=r;n&&(o=Je(a.keys()));var i={_keyList:[],_expandedKeyList:o,_cachedExpandedKeyList:[],_loadedKeys:[],_prevProps:{}};return P(P({},i),g_(this.$props,i))},methods:{onTreeExpand:function(t){var n=this,r=this.$props.treeExpandedKeys;r||this.setState({_expandedKeyList:t},function(){n.__emit(\"treeExpanded\")}),this.__emit(\"treeExpand\",t)},onLoad:function(t){this.setState({_loadedKeys:t})},getTree:function(){return this.treeRef.current},getLoadData:function(){var t=this.$props,n=t.loadData,r=t.upperSearchValue;return r?null:n},filterTreeNode:function(t){var n=this.$props,r=n.upperSearchValue,a=n.treeNodeFilterProp,o=t[a];return typeof o==\"string\"?r&&o.toUpperCase().indexOf(r)!==-1:!1},renderNotFound:function(){var t=this.$props,n=t.prefixCls,r=t.notFoundContent;return g(\"span\",{class:\"\".concat(n,\"-not-found\")},[r])}},render:function(){var t=this.$data,n=t._keyList,r=t._expandedKeyList,a=t._loadedKeys,o=this.$props,i=o.prefixCls,l=o.treeNodes,s=o.filteredTreeNodes,c=o.treeIcon,d=o.treeLine,f=o.treeCheckable,p=o.treeCheckStrictly,v=o.multiple,m=o.ariaId,y=o.renderSearch,b=o.switcherIcon,C=o.searchHalfCheckedKeys,S=this.vcTreeSelect,w=S.onPopupKeyDown,k=S.onTreeNodeSelect,$=S.onTreeNodeCheck,O=this.getLoadData(),T={};f?T.checkedKeys=n:T.selectedKeys=n;var _,I;s?s.length?(T.checkStrictly=!0,I=s,f&&!p&&(T.checkedKeys={checked:n,halfChecked:C})):_=this.renderNotFound():!l||!l.length?_=this.renderNotFound():I=l;var L;if(_)L=_;else{var j=P(P({prefixCls:\"\".concat(i,\"-tree\"),showIcon:c,showLine:d,selectable:!f,checkable:f,checkStrictly:p,multiple:v,loadData:O,loadedKeys:a,expandedKeys:r,filterTreeNode:this.filterTreeNode,switcherIcon:b},T),{children:I,onSelect:k,onCheck:$,onExpand:this.onTreeExpand,onLoad:this.onLoad});L=g(Wf,le(le({},j),{},{ref:this.treeRef,__propsSymbol__:[]}),null)}return g(\"div\",{role:\"listbox\",id:m,onKeydown:w,tabindex:-1},[y?y():null,L])}},sDe=lDe;function uDe(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t={};return e.forEach(function(n){t[n]=function(){this.needSyncKeys[n]=!0}}),t}var Nc=G({name:\"Select\",mixins:[nt],inheritAttrs:!1,props:An({prefixCls:u.string,prefixAria:u.string,multiple:u.looseBool,showArrow:u.looseBool,open:u.looseBool,value:u.any,autofocus:u.looseBool,defaultOpen:u.looseBool,defaultValue:u.any,showSearch:u.looseBool,placeholder:u.any,inputValue:u.string,searchValue:u.string,autoClearSearchValue:u.looseBool,searchPlaceholder:u.any,disabled:u.looseBool,children:u.any,labelInValue:u.looseBool,maxTagCount:u.number,maxTagPlaceholder:u.any,maxTagTextLength:u.number,showCheckedStrategy:u.oneOf([ZS,Rg,mf]),dropdownClassName:u.string,dropdownStyle:u.object,dropdownVisibleChange:u.func,dropdownMatchSelectWidth:u.looseBool,treeData:u.array,treeDataSimpleMode:an(u.oneOfType([u.looseBool,u.object])),treeNodeFilterProp:u.string,treeNodeLabelProp:u.string,treeCheckable:u.any,treeCheckStrictly:u.looseBool,treeIcon:u.looseBool,treeLine:u.looseBool,treeDefaultExpandAll:u.looseBool,treeDefaultExpandedKeys:u.array,treeExpandedKeys:u.array,loadData:u.func,filterTreeNode:an(u.oneOfType([u.func,u.looseBool])),notFoundContent:u.any,getPopupContainer:u.func,allowClear:u.looseBool,transitionName:u.string,animation:u.string,choiceTransitionName:u.string,inputIcon:u.any,clearIcon:u.any,removeIcon:u.any,switcherIcon:u.any,__propsSymbol__:u.any},{prefixCls:\"rc-tree-select\",prefixAria:\"rc-tree-select\",showArrow:!0,showSearch:!0,autoClearSearchValue:!0,showCheckedStrategy:mf,treeNodeFilterProp:\"value\",treeNodeLabelProp:\"title\",treeIcon:!1,notFoundContent:\"Not Found\",dropdownStyle:{},dropdownVisibleChange:function(){return!0}}),data:function(){cc(this.$props.__propsSymbol__);var t=this.$props,n=t.prefixAria,r=t.defaultOpen,a=t.open;this.needSyncKeys={},this.selectorRef=Si(),this.selectTriggerRef=Si(),this.ariaId=FAe(\"\".concat(n,\"-list\"));var o={_open:a||r,_valueList:[],_searchHalfCheckedKeys:[],_missValueList:[],_selectorValueList:[],_valueEntities:{},_posEntities:new Map,_keyEntities:new Map,_searchValue:\"\",_prevProps:{},_init:!0,_focused:void 0,_treeNodes:void 0,_filteredTreeNodes:void 0},i=this.getDerivedState(this.$props,o);return P(P({},o),i)},watch:P(P({},uDe([\"treeData\",\"defaultValue\",\"value\"])),{__propsSymbol__:function(){var t=this.getDerivedState(this.$props,this.$data);this.setState(t),this.needSyncKeys={}},_valueList:function(){var t=this;this.$nextTick(function(){t.forcePopupAlign()})},_open:function(t){var n=this;this.$nextTick(function(){!t&&!n.isSearchValueControlled()&&n.setState({_searchValue:\"\"}),t&&!n.$data._searchValue&&n.setState({_filteredTreeNodes:null});var r=n.$props.prefixCls,a=n.$data,o=a._selectorValueList,i=a._valueEntities,l=n.isMultiple();if(!l&&o.length&&t&&n.popup){var s=o[0].value,c=n.popup.getTree(),d=c.domTreeNodes,f=i[s]||{},p=f.key,v=d[p];if(v){var m=Sn(v);requestAnimationFrame(function(){var y=Sn(n.popup),b=AAe(y,\"\".concat(r,\"-dropdown\"));m&&b&&IAe(m,b,{onlyScrollIfNeeded:!0,offsetTop:0})})}}})}}),created:function(){ot(\"vcTreeSelect\",{onSelectorFocus:this.onSelectorFocus,onSelectorBlur:this.onSelectorBlur,onSelectorKeyDown:this.onComponentKeyDown,onSelectorClear:this.onSelectorClear,onMultipleSelectorRemove:this.onMultipleSelectorRemove,onTreeNodeSelect:this.onTreeNodeSelect,onTreeNodeCheck:this.onTreeNodeCheck,onPopupKeyDown:this.onComponentKeyDown,onSearchInputChange:this.onSearchInputChange,onSearchInputKeyDown:this.onSearchInputKeyDown})},mounted:function(){var t=this;this.$nextTick(function(){var n=t.$props,r=n.autofocus,a=n.disabled;r&&!a&&t.focus()})},methods:{getDerivedState:function(t,n){var r=n._prevProps,a=r===void 0?{}:r,o=t.treeCheckable,i=t.treeCheckStrictly,l=t.filterTreeNode,s=t.treeNodeFilterProp,c=t.treeDataSimpleMode,d={_prevProps:P({},t),_init:!1},f=this;function p(N,D){return a[N]!==t[N]||f.needSyncKeys[N]?(D(t[N],a[N]),!0):!1}var v=!1;p(\"open\",function(N){d._open=N});var m,y=!1,b=!1;if(p(\"treeData\",function(N){m=p_(N),y=!0}),p(\"treeDataSimpleMode\",function(N,D){if(!!N){var z=!D||D===!0?{}:D;Mr(N,z)||(b=!0)}}),c&&(y||b)){var C=P({id:\"id\",pId:\"pId\",rootPId:null},c!==!0?c:{});m=p_(BAe(t.treeData,C))}if(t.treeData||(m=this.children||[]),m){var S=KAe(m);d._treeNodes=m,d._posEntities=S.posEntities,d._valueEntities=S.valueEntities,d._keyEntities=S.keyEntities,v=!0}if(n._init&&p(\"defaultValue\",function(N){d._valueList=h_(N,t),v=!0}),p(\"value\",function(N){d._valueList=h_(N,t),v=!0}),v){var w=[],k=[],$=[],O=d._valueList;O||(O=[].concat(Je(n._valueList),Je(n._missValueList)));var T={};if(O.forEach(function(N){var D=N.value,z=N.label,B=(d._valueEntities||n._valueEntities)[D];if(T[D]=z,B){$.push(B.key),k.push(N);return}w.push(N)}),o&&!i){var _=Jh($,!0,d._keyEntities||n._keyEntities),I=_.checkedKeys;d._valueList=I.map(function(N){var D=(d._keyEntities||n._keyEntities).get(N).value,z={value:D};return T[D]!==void 0&&(z.label=T[D]),z})}else d._valueList=k;d._missValueList=w,d._selectorValueList=Eb(d._valueList,t,d._valueEntities||n._valueEntities)}if(p(\"inputValue\",function(N){N!==null&&(d._searchValue=N)}),p(\"searchValue\",function(N){d._searchValue=N}),d._searchValue!==void 0||n._searchValue&&m){var L=d._searchValue!==void 0?d._searchValue:n._searchValue,j=String(L).toUpperCase(),F=l;l===!1?F=function(){return!0}:typeof F!=\"function\"&&(F=function(D,z){var B=String(rr(z)[s]).toUpperCase();return B.indexOf(j)!==-1}),d._filteredTreeNodes=f_(d._treeNodes||n._treeNodes,L,F,d._valueEntities||n._valueEntities,ks)}return v&&o&&!i&&(d._searchValue||n._searchValue)&&(d._searchHalfCheckedKeys=v_(d._valueList,d._valueEntities||n._valueEntities)),p(\"showCheckedStrategy\",function(){d._selectorValueList=d._selectorValueList||Eb(d._valueList||n._valueList,t,d._valueEntities||n._valueEntities)}),d},onSelectorFocus:function(){this.setState({_focused:!0})},onSelectorBlur:function(){this.setState({_focused:!1})},onComponentKeyDown:function(t){var n=this.$data._open,r=t.keyCode;n?ze.ESC===r?this.setOpenState(!1):[ze.UP,ze.DOWN,ze.LEFT,ze.RIGHT].indexOf(r)!==-1&&t.stopPropagation():[ze.ENTER,ze.DOWN].indexOf(r)!==-1&&this.setOpenState(!0)},onDeselect:function(t,n,r){this.__emit(\"deselect\",t,n,r)},onSelectorClear:function(t){var n=this.$props.disabled;n||(this.triggerChange([],[]),this.isSearchValueControlled()||this.setUncontrolledState({_searchValue:\"\",_filteredTreeNodes:null}),t.stopPropagation())},onMultipleSelectorRemove:function(t,n){t.stopPropagation();var r=this.$data,a=r._valueList,o=r._missValueList,i=r._valueEntities,l=this.$props,s=l.treeCheckable,c=l.treeCheckStrictly,d=l.treeNodeLabelProp,f=l.disabled;if(!f){var p=i[n],v=a;p&&(s&&!c?v=a.filter(function(k){var $=k.value,O=i[$];return!VAe(O.pos,p.pos)}):v=a.filter(function(k){var $=k.value;return $!==n}));var m=p?p.node:null,y={triggerValue:n,triggerNode:m},b={node:m};if(s){var C=v.map(function(k){var $=k.value;return i[$]});b.event=\"check\",b.checked=!1,b.checkedNodes=C.map(function(k){var $=k.node;return $}),b.checkedNodesPositions=C.map(function(k){var $=k.node,O=k.pos;return{node:$,pos:O}}),c?y.allCheckedNodes=b.checkedNodes:y.allCheckedNodes=F1(C).map(function(k){var $=k.node;return $})}else b.event=\"select\",b.selected=!1,b.selectedNodes=v.map(function(k){var $=k.value;return(i[$]||{}).node});var S=o.filter(function(k){var $=k.value;return $!==n}),w;this.isLabelInValue()?w={label:m?rr(m)[d]:null,value:n}:w=n,this.onDeselect(w,m,b),this.triggerChange(S,v,y)}},onValueTrigger:function(t,n,r,a){var o=r.node,i=o.$props.value,l=this.$data,s=l._missValueList,c=l._valueEntities,d=l._keyEntities,f=l._searchValue,p=this.$props,v=p.disabled,m=p.inputValue,y=p.treeNodeLabelProp,b=p.treeCheckable,C=p.treeCheckStrictly,S=p.autoClearSearchValue,w=o.$props[y];if(!v){var k;this.isLabelInValue()?k={value:i,label:w}:k=i,t?this.__emit(\"select\",k,o,r):this.__emit(\"deselect\",k,o,r);var $=n.map(function(_){var I=rr(_);return{value:I.value,label:I[y]}});if(b&&!C){var O=$.map(function(_){var I=_.value;return c[I].key});t?O=Jh(O,!0,d).checkedKeys:O=Jh([c[i].key],!1,d,{checkedKeys:O}).checkedKeys,$=O.map(function(_){var I=rr(d.get(_).node);return{value:I.value,label:I[y]}})}(S||m===null)&&(this.isSearchValueControlled()||this.setUncontrolledState({_searchValue:\"\",_filteredTreeNodes:null}),f&&f.length&&this.__emit(\"search\",\"\"));var T=P(P({},a),{triggerValue:i,triggerNode:o});this.triggerChange(s,$,T)}},onTreeNodeSelect:function(t,n){var r=this.$data,a=r._valueList,o=r._valueEntities,i=this.$props,l=i.treeCheckable,s=i.multiple;if(!l){s||this.setOpenState(!1);var c=n.selected,d=n.node.$props.value,f;s?(f=a.filter(function(v){var m=v.value;return m!==d}),c&&f.push({value:d})):f=[{value:d}];var p=f.map(function(v){var m=v.value;return o[m]}).filter(function(v){return v}).map(function(v){var m=v.node;return m});this.onValueTrigger(c,p,n,{selected:c})}},onTreeNodeCheck:function(t,n){var r=this.$data,a=r._searchValue,o=r._keyEntities,i=r._valueEntities,l=r._valueList,s=this.$props.treeCheckStrictly,c=n.checkedNodes,d=n.checkedNodesPositions,f=n.checked,p={checked:f},v=c;if(a){var m=l.map(function(b){var C=b.value;return i[C]}).filter(function(b){return b}).map(function(b){var C=b.key;return C}),y;f?y=Array.from(new Set([].concat(Je(m),Je(v.map(function(b){var C=rr(b),S=C.value;return i[S].key}))))):y=Jh([rr(n.node).eventKey],!1,o,{checkedKeys:m}).checkedKeys,v=y.map(function(b){return o.get(b).node}),p.allCheckedNodes=y.map(function(b){return WR(o.get(b))})}else s?p.allCheckedNodes=n.checkedNodes:p.allCheckedNodes=F1(d);this.onValueTrigger(f,v,n,p)},onDropdownVisibleChange:function(t){var n=this.$props,r=n.multiple,a=n.treeCheckable,o=this.$data._searchValue;t&&!r&&!a&&o&&this.setUncontrolledState({_searchValue:\"\",_filteredTreeNodes:null}),this.setOpenState(t,!0)},onSearchInputChange:function(t){var n=t.target.value,r=this.$data,a=r._treeNodes,o=r._valueEntities,i=this.$props,l=i.filterTreeNode,s=i.treeNodeFilterProp;this.__emit(\"search\",n);var c=!1;if(this.isSearchValueControlled()||(c=this.setUncontrolledState({_searchValue:n}),this.setOpenState(!0)),c){var d=String(n).toUpperCase(),f=l;l===!1?f=function(){return!0}:f||(f=function(v,m){var y=String(rr(m)[s]).toUpperCase();return y.indexOf(d)!==-1}),this.setState({_filteredTreeNodes:f_(a,n,f,o,ks)})}},onSearchInputKeyDown:function(t){var n=this.$data,r=n._searchValue,a=n._valueList,o=n._valueEntities,i=t.keyCode;if(ze.BACKSPACE===i&&this.isMultiple()&&!r&&a.length){var l=a[a.length-1].value,s=this.$props.treeCheckStrictly;s||function(){for(var c=o[l];c;)a.some(function(d){return d.value===c.value})?(l=c.value,c=c.parent):c=null}(),this.onMultipleSelectorRemove(t,l)}},onChoiceAnimationLeave:function(){var t=this;requestAnimationFrame(function(){t.forcePopupAlign()})},setPopupRef:function(t){this.popup=t},setUncontrolledState:function(t){var n=!1,r={},a=Qe(this);return Object.keys(t).forEach(function(o){o.slice(1)in a||(n=!0,r[o]=t[o])}),n&&this.setState(r),n},setOpenState:function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,r=this.$props.dropdownVisibleChange;r&&r(t,{documentClickClose:!t&&n})===!1||this.setUncontrolledState({_open:t})},isMultiple:function(){var t=this.$props,n=t.multiple,r=t.treeCheckable;return!!(n||r)},isLabelInValue:function(){return KR(this.$props)},isSearchValueControlled:function(){var t=Qe(this),n=t.inputValue;return\"searchValue\"in t?!0:\"inputValue\"in t&&n!==null},forcePopupAlign:function(){var t=this.selectTriggerRef.current;t&&t.forcePopupAlign()},delayForcePopupAlign:function(){var t=this;requestAnimationFrame(function(){requestAnimationFrame(t.forcePopupAlign)})},triggerChange:function(t,n){var r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=this.$data,o=a._valueEntities,i=a._searchValue,l=a._selectorValueList,s=Qe(this),c=s.disabled,d=s.treeCheckable,f=s.treeCheckStrictly;if(!c){var p=P({preValue:l.map(function(S){var w=S.label,k=S.value;return{label:w,value:k}})},r),v=Eb(n,s,o);if(!(\"value\"in s)){var m={_missValueList:t,_valueList:n,_selectorValueList:v};i&&d&&!f&&(m._searchHalfCheckedKeys=v_(n,o)),this.setState(m)}if(this.$attrs.onChange){var y;this.isMultiple()?y=[].concat(Je(t),Je(v)):y=v.slice(0,1);var b=null,C;this.isLabelInValue()?C=y.map(function(S){var w=S.label,k=S.value;return{label:w,value:k}}):(b=[],C=y.map(function(S){var w=S.label,k=S.value;return b.push(w),k})),this.isMultiple()||(C=C[0]),this.__emit(\"change\",C,b,p)}}},focus:function(){this.selectorRef.current.focus()},blur:function(){this.selectorRef.current.blur()}},render:function(){var t=this.$data,n=t._valueList,r=t._missValueList,a=t._selectorValueList,o=t._searchHalfCheckedKeys,i=t._valueEntities,l=t._keyEntities,s=t._searchValue,c=t._open,d=t._focused,f=t._treeNodes,p=t._filteredTreeNodes,v=Qe(this),m=v.prefixCls,y=v.treeExpandedKeys,b=this.isMultiple(),C=P(P(P({},v),this.$attrs),{isMultiple:b,valueList:n,searchHalfCheckedKeys:o,selectorValueList:[].concat(Je(r),Je(a)),valueEntities:i,keyEntities:l,searchValue:s,upperSearchValue:(s||\"\").toUpperCase(),open:c,focused:d,dropdownPrefixCls:\"\".concat(m,\"-dropdown\"),ariaId:this.ariaId,onChoiceAnimationLeave:this.onChoiceAnimationLeave,vSlots:this.$slots}),S=P(P({},C),{treeNodes:f,filteredTreeNodes:p,treeExpandedKeys:y,onTreeExpanded:this.delayForcePopupAlign,ref:this.setPopupRef}),w=g(sDe,le(le({},S),{},{__propsSymbol__:[]}),null),k=b?oDe:eDe,$=g(k,le(le({},C),{},{isMultiple:b,ref:this.selectorRef}),null),O=P(P({},C),{popupElement:w,dropdownVisibleChange:this.onDropdownVisibleChange,ref:this.selectTriggerRef});return g(YAe,O,{default:function(){return[$]}})}});Nc.TreeNode=ks;Nc.SHOW_ALL=ZS;Nc.SHOW_PARENT=Rg;Nc.SHOW_CHILD=mf;Nc.name=\"TreeSelect\";var cDe=Nc,dDe=ks;u.shape({key:u.string,value:u.string,label:u.VNodeChild,slots:u.object,children:u.array}).loose;var fDe=function(){return P(P({},Sg()),{autofocus:u.looseBool,dropdownStyle:u.object,filterTreeNode:an(u.oneOfType([Function,Boolean])),getPopupContainer:u.func,labelInValue:u.looseBool,loadData:u.func,maxTagCount:u.number,maxTagPlaceholder:u.VNodeChild,value:u.oneOfType([u.string,u.object,u.array,u.number]),defaultValue:u.oneOfType([u.string,u.object,u.array,u.number]),multiple:u.looseBool,notFoundContent:u.VNodeChild,searchPlaceholder:u.string,searchValue:u.string,showCheckedStrategy:u.oneOf(rt(\"SHOW_ALL\",\"SHOW_PARENT\",\"SHOW_CHILD\")),suffixIcon:u.VNodeChild,treeCheckable:u.looseBool,treeCheckStrictly:u.looseBool,treeData:u.arrayOf(Object),treeDataSimpleMode:an(u.oneOfType([u.looseBool,Object])),dropdownClassName:u.string,dropdownMatchSelectWidth:u.looseBool,treeDefaultExpandAll:u.looseBool,treeExpandedKeys:u.array,treeIcon:u.looseBool,treeDefaultExpandedKeys:u.array,treeNodeFilterProp:u.string,treeNodeLabelProp:u.string,replaceFields:u.object.def({}),clearIcon:u.VNodeChild,removeIcon:u.VNodeChild,onSelect:u.func,onChange:u.func,onSearch:u.func,onTreeExpand:u.func,\"onUpdate:treeExpandedKeys\":u.func,\"onUpdate:searchValue\":u.func,\"onUpdate:value\":u.func})},hDe={icon:{tag:\"svg\",attrs:{viewBox:\"0 0 1024 1024\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z\"}}]},name:\"caret-down\",theme:\"outlined\"},pDe=hDe;function y_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){vDe(e,a,n[a])})}return e}function vDe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var QS=function(t,n){var r=y_({},t,n.attrs);return g(Et,y_({},r,{icon:pDe}),null)};QS.displayName=\"CaretDownOutlined\";QS.inheritAttrs=!1;var mDe=QS,b_=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n};function YR(e){return Un(e).map(function(t){if(!zn(t)||!t.type)return null;var n=t.children||{},r=n.default,a=b_(n,[\"default\"]),o=r?r():[],i=t.key,l=t.props,s=l.value,c=b_(l,[\"value\"]),d=P({key:i,value:s},c);Object.keys(a).forEach(function(p){typeof a[p]==\"function\"&&(d[p]=g(Fe,null,[a[p]()]))});var f=YR(o);return f.length&&(d.children=f),d}).filter(function(t){return t})}var gDe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},Kl=G({TreeNode:dDe,SHOW_ALL:ZS,SHOW_PARENT:Rg,SHOW_CHILD:mf,name:\"ATreeSelect\",inheritAttrs:!1,props:Rn(fDe(),{transitionName:\"slide-up\",choiceTransitionName:\"\"}),setup:function(){return{vcTreeSelect:null,configProvider:ve(\"configProvider\",St)}},created:function(){on(this.multiple!==!1||!this.treeCheckable,\"TreeSelect\",\"`multiple` will alway be `true` when `treeCheckable` is true\")},methods:{saveTreeSelect:function(t){this.vcTreeSelect=t},focus:function(){this.vcTreeSelect.focus()},blur:function(){this.vcTreeSelect.blur()},renderSwitcherIcon:function(t,n){var r=n.isLeaf,a=n.loading;return a?g(co,{class:\"\".concat(t,\"-switcher-loading-icon\")},null):r?null:g(mDe,{class:\"\".concat(t,\"-switcher-icon\")},null)},handleChange:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.$emit(\"update:value\",n[0]),this.$emit.apply(this,[\"change\"].concat(n))},handleTreeExpand:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.$emit(\"update:treeExpandedKeys\",n[0]),this.$emit.apply(this,[\"treeExpand\"].concat(n))},handleSearch:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];this.$emit(\"update:searchValue\",n[0]),this.$emit.apply(this,[\"search\"].concat(n))},updateTreeData:function(t){var n=this,r=this.$slots,a={children:\"children\",title:\"title\",key:\"key\",label:\"label\",value:\"value\"},o=P(P({},a),this.$props.replaceFields);return t.map(function(i){var l=i.slots,s=l===void 0?{}:l,c=i[o.label],d=i[o.title],f=i[o.value],p=i[o.key],v=i[o.children],m=typeof c==\"function\"?c():c,y=typeof d==\"function\"?d():d;!m&&s.label&&r[s.label]&&(m=g(Fe,null,[r[s.label](i)])),!y&&s.title&&r[s.title]&&(y=g(Fe,null,[r[s.title](i)]));var b=P(P({},i),{title:y||m,value:f,dataRef:i,key:p});return v?P(P({},b),{children:n.updateTreeData(v)}):b})}},render:function(){var t,n=this,r=Qe(this),a=r.prefixCls,o=r.size,i=r.dropdownStyle,l=r.dropdownClassName,s=r.getPopupContainer,c=gDe(r,[\"prefixCls\",\"size\",\"dropdownStyle\",\"dropdownClassName\",\"getPopupContainer\"]),d=this.$attrs.class,f=this.configProvider,p=f.renderEmpty,v=f.getPrefixCls,m=v(\"select\",a),y=We(this,\"notFoundContent\"),b=We(this,\"removeIcon\"),C=We(this,\"clearIcon\"),S=this.configProvider.getPopupContainer,w=bn(c,[\"inputIcon\",\"removeIcon\",\"clearIcon\",\"switcherIcon\",\"suffixIcon\"]),k=We(this,\"suffixIcon\");k=Array.isArray(k)?k[0]:k;var $=r.treeData;$&&($=this.updateTreeData($));var O=(t={},V(t,\"\".concat(m,\"-lg\"),o===\"large\"),V(t,\"\".concat(m,\"-sm\"),o===\"small\"),V(t,d,d),t),T=c.showSearch;\"showSearch\"in c||(T=!!(c.multiple||c.treeCheckable));var _=We(this,\"treeCheckable\");_&&(_=g(\"span\",{class:\"\".concat(m,\"-tree-checkbox-inner\")},null));var I=k||g(Rs,{class:\"\".concat(m,\"-arrow-icon\")},null),L=b||g(go,{class:\"\".concat(m,\"-remove-icon\")},null),j=C||g(Yr,{class:\"\".concat(m,\"-clear-icon\")},null),F=P(P(P(P({},this.$attrs),{switcherIcon:function(D){return n.renderSwitcherIcon(m,D)},inputIcon:I,removeIcon:L,clearIcon:j}),w),{showSearch:T,getPopupContainer:s||S,dropdownClassName:Se(l,\"\".concat(m,\"-tree-dropdown\")),prefixCls:m,dropdownStyle:P({maxHeight:\"100vh\",overflow:\"auto\"},i),treeCheckable:_,notFoundContent:y||p(\"Select\"),class:O,onChange:this.handleChange,onSearch:this.handleSearch,onTreeExpand:this.handleTreeExpand,ref:this.saveTreeSelect,treeData:$||YR(ht(this))});return g(cDe,le(le({},F),{},{__propsSymbol__:[]}),bn(this.$slots,[\"default\"]))}});Kl.install=function(e){return e.component(Kl.name,Kl),e.component(Kl.TreeNode.displayName,Kl.TreeNode),e};var yDe=Kl.TreeNode,bDe=Kl,CDe={prefixCls:u.string,color:u.string,dot:u.any,pending:u.looseBool,position:u.oneOf(rt(\"left\",\"right\",\"\")).def(\"\")},gf=G({name:\"ATimelineItem\",props:Rn(CDe,{color:\"blue\",pending:!1}),setup:function(){return{configProvider:ve(\"configProvider\",St)}},render:function(){var t,n,r,a,o=Qe(this),i=o.prefixCls,l=o.color,s=l===void 0?\"\":l,c=o.pending,d=this.configProvider.getPrefixCls,f=d(\"timeline\",i),p=We(this,\"dot\"),v=Se((t={},V(t,\"\".concat(f,\"-item\"),!0),V(t,\"\".concat(f,\"-item-pending\"),c),t)),m=Se((n={},V(n,\"\".concat(f,\"-item-head\"),!0),V(n,\"\".concat(f,\"-item-head-custom\"),p),V(n,\"\".concat(f,\"-item-head-\").concat(s),!0),n));return g(\"li\",{class:v},[g(\"div\",{class:\"\".concat(f,\"-item-tail\")},null),g(\"div\",{class:m,style:{borderColor:/blue|red|green|gray/.test(s)?void 0:s}},[p]),g(\"div\",{class:\"\".concat(f,\"-item-content\")},[(a=(r=this.$slots).default)===null||a===void 0?void 0:a.call(r)])])}}),wDe={prefixCls:u.string,pending:u.any,pendingDot:u.string,reverse:u.looseBool,mode:u.oneOf(rt(\"left\",\"alternate\",\"right\",\"\"))},Ed=G({name:\"ATimeline\",props:Rn(wDe,{reverse:!1,mode:\"\"}),setup:function(){return{configProvider:ve(\"configProvider\",St)}},render:function(){var t,n,r,a=Qe(this),o=a.prefixCls,i=a.reverse,l=a.mode,s=this.configProvider.getPrefixCls,c=s(\"timeline\",o),d=We(this,\"pendingDot\"),f=We(this,\"pending\"),p=typeof f==\"boolean\"?null:f,v=Se(c,(t={},V(t,\"\".concat(c,\"-pending\"),!!f),V(t,\"\".concat(c,\"-reverse\"),!!i),V(t,\"\".concat(c,\"-\").concat(l),!!l),t)),m=La((r=(n=this.$slots).default)===null||r===void 0?void 0:r.call(n)),y=f?g(gf,{pending:!!f,dot:d||g(co,null,null)},{default:function(){return[p]}}):null,b=i?[y].concat(Je(m.reverse())):[].concat(Je(m),[y]),C=function(T,_){var I=rr(T);return l===\"alternate\"?I.position===\"right\"?\"\".concat(c,\"-item-right\"):I.position===\"left\"||_%2===0?\"\".concat(c,\"-item-left\"):\"\".concat(c,\"-item-right\"):l===\"left\"?\"\".concat(c,\"-item-left\"):l===\"right\"||I.position===\"right\"?\"\".concat(c,\"-item-right\"):\"\"},S=b.filter(function(O){return!!O}),w=S.length,k=\"\".concat(c,\"-item-last\"),$=S.map(function(O,T){var _=T===w-2?k:\"\",I=T===w-1?k:\"\";return hr(O,{class:Se([!i&&!!f?_:I,C(O,T)])})});return g(\"ul\",{class:v},[$])}});Ed.Item=gf;Ed.install=function(e){return e.component(Ed.name,Ed),e.component(gf.name,gf),e};var SDe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 000 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8z\"}}]},name:\"enter\",theme:\"outlined\"},kDe=SDe;function C_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){$De(e,a,n[a])})}return e}function $De(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var ek=function(t,n){var r=C_({},t,n.attrs);return g(Et,C_({},r,{icon:kDe}),null)};ek.displayName=\"EnterOutlined\";ek.inheritAttrs=!1;var ODe=ek,PDe=G({name:\"Editable\",props:{prefixCls:u.string,value:u.string,maxlength:u.number,autoSize:u.oneOfType([u.looseBool,u.object]),onSave:u.func,onCancel:u.func,onEnd:u.func,onChange:u.func,originContent:u.string},emits:[\"save\",\"cancel\",\"end\",\"change\"],setup:function(t,n){var r=n.emit,a=bt({current:t.value||\"\",lastKeyCode:void 0,inComposition:!1,cancelFlag:!1});ce(function(){return t.value},function(m){a.current=m});var o=H();et(function(){var m;if(o.value){var y=(m=o.value)===null||m===void 0?void 0:m.resizableTextArea,b=y==null?void 0:y.textArea;b.focus();var C=b.value.length;b.setSelectionRange(C,C)}});function i(m){o.value=m}function l(m){var y=m.target.value;a.current=y.replace(/[\\r\\n]/g,\"\"),r(\"change\",a.current)}function s(){a.inComposition=!0}function c(){a.inComposition=!1}function d(m){var y=m.keyCode;y===ze.ENTER&&m.preventDefault(),!a.inComposition&&(a.lastKeyCode=y)}function f(m){var y=m.keyCode,b=m.ctrlKey,C=m.altKey,S=m.metaKey,w=m.shiftKey;a.lastKeyCode===y&&!a.inComposition&&!b&&!C&&!S&&!w&&(y===ze.ENTER?(v(),r(\"end\")):y===ze.ESC&&(a.current=t.originContent,r(\"cancel\")))}function p(){v(),r(\"end\")}function v(){r(\"save\",a.current.trim())}return function(){return g(\"div\",{class:\"\".concat(t.prefixCls,\" \").concat(t.prefixCls,\"-edit-content\")},[g(S2,{ref:i,maxlength:t.maxlength,value:a.current,onChange:l,onKeydown:d,onKeyup:f,onCompositionstart:s,onCompositionend:c,onBlur:p,autoSize:t.autoSize===void 0||t.autoSize},null),g(ODe,{class:\"\".concat(t.prefixCls,\"-edit-content-confirm\")},null)])}}}),TDe=PDe,xDe=3,_De=8,Ln,Mb={padding:0,margin:0,display:\"inline\",lineHeight:\"inherit\"};function Ib(e){if(!e)return 0;var t=e.match(/^\\d*(\\.\\d*)?/);return t?Number(t[0]):0}function EDe(e){var t=Array.prototype.slice.apply(e);return t.map(function(n){return\"\".concat(n,\": \").concat(e.getPropertyValue(n),\";\")}).join(\"\")}var MDe=function(e,t,n,r,a){Ln||(Ln=document.createElement(\"div\"),Ln.setAttribute(\"aria-hidden\",\"true\"),document.body.appendChild(Ln));var o=t.rows,i=t.suffix,l=i===void 0?\"\":i,s=window.getComputedStyle(e),c=EDe(s),d=Ib(s.lineHeight),f=Math.round(d*(o+1)+Ib(s.paddingTop)+Ib(s.paddingBottom));Ln.setAttribute(\"style\",c),Ln.style.position=\"fixed\",Ln.style.left=\"0\",Ln.style.height=\"auto\",Ln.style.minHeight=\"auto\",Ln.style.maxHeight=\"auto\",Ln.style.top=\"-999999px\",Ln.style.zIndex=\"-1000\",Ln.style.textOverflow=\"clip\",Ln.style.whiteSpace=\"normal\",Ln.style.webkitLineClamp=\"none\";var p=$m({render:function(){return g(\"div\",{style:Mb},[g(\"span\",{style:Mb},[n,l]),g(\"span\",{style:Mb},[r])])}});p.mount(Ln);function v(){return Ln.offsetHeight<f}if(v())return p.unmount(),{content:n,text:Ln.innerHTML,ellipsis:!1};var m=Array.prototype.slice.apply(Ln.childNodes[0].childNodes[0].cloneNode(!0).childNodes).filter(function(O){var T=O.nodeType,_=O.data;return T!==_De&&_!==\"\"}),y=Array.prototype.slice.apply(Ln.childNodes[0].childNodes[1].cloneNode(!0).childNodes);p.unmount();var b=[];Ln.innerHTML=\"\";var C=document.createElement(\"span\");Ln.appendChild(C);var S=document.createTextNode(a+l);C.appendChild(S),y.forEach(function(O){Ln.appendChild(O)});function w(O){C.insertBefore(O,S)}function k(O,T){var _=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,I=arguments.length>3&&arguments[3]!==void 0?arguments[3]:T.length,L=arguments.length>4&&arguments[4]!==void 0?arguments[4]:0,j=Math.floor((_+I)/2),F=T.slice(0,j);if(O.textContent=F,_>=I-1)for(var N=I;N>=_;N-=1){var D=T.slice(0,N);if(O.textContent=D,v()||!D)return N===T.length?{finished:!1,vNode:T}:{finished:!0,vNode:D}}return v()?k(O,T,j,I,j):k(O,T,_,j,L)}function $(O){var T=O.nodeType;if(T===xDe){var _=O.textContent||\"\",I=document.createTextNode(_);return w(I),k(I,_)}return{finished:!1,vNode:null}}return m.some(function(O){var T=$(O),_=T.finished,I=T.vNode;return I&&b.push(I),_}),{content:b,text:Ln.innerHTML,ellipsis:!0}},IDe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},qR=G({name:\"ATypography\",inheritAttrs:!1,setup:function(t,n){var r=n.slots,a=n.attrs,o=Wt(\"typography\",t),i=o.prefixCls;return function(){var l,s=P(P({},t),a);s.prefixCls,s.class;var c=s.component,d=c===void 0?\"article\":c,f=IDe(s,[\"prefixCls\",\"class\",\"component\"]);return g(d,le({class:Se(i.value,a.class)},f),{default:function(){return[(l=r.default)===null||l===void 0?void 0:l.call(r)]}})}}});qR.props={prefixCls:u.string,component:u.string};var Fr=qR,NDe=function(){var t=document.getSelection();if(!t.rangeCount)return function(){};for(var n=document.activeElement,r=[],a=0;a<t.rangeCount;a++)r.push(t.getRangeAt(a));switch(n.tagName.toUpperCase()){case\"INPUT\":case\"TEXTAREA\":n.blur();break;default:n=null;break}return t.removeAllRanges(),function(){t.type===\"Caret\"&&t.removeAllRanges(),t.rangeCount||r.forEach(function(o){t.addRange(o)}),n&&n.focus()}},ADe=NDe,w_={\"text/plain\":\"Text\",\"text/html\":\"Url\",default:\"Text\"},DDe=\"Copy to clipboard: #{key}, Enter\";function RDe(e){var t=(/mac os x/i.test(navigator.userAgent)?\"\\u2318\":\"Ctrl\")+\"+C\";return e.replace(/#{\\s*key\\s*}/g,t)}function LDe(e,t){var n,r,a,o,i,l=!1;t||(t={});var s=t.debug||!1;try{r=ADe(),a=document.createRange(),o=document.getSelection(),i=document.createElement(\"span\"),i.textContent=e,i.style.all=\"unset\",i.style.position=\"fixed\",i.style.top=0,i.style.clip=\"rect(0, 0, 0, 0)\",i.style.whiteSpace=\"pre\",i.style.webkitUserSelect=\"text\",i.style.MozUserSelect=\"text\",i.style.msUserSelect=\"text\",i.style.userSelect=\"text\",i.addEventListener(\"copy\",function(d){if(d.stopPropagation(),t.format)if(d.preventDefault(),typeof d.clipboardData==\"undefined\"){s&&console.warn(\"unable to use e.clipboardData\"),s&&console.warn(\"trying IE specific stuff\"),window.clipboardData.clearData();var f=w_[t.format]||w_.default;window.clipboardData.setData(f,e)}else d.clipboardData.clearData(),d.clipboardData.setData(t.format,e);t.onCopy&&(d.preventDefault(),t.onCopy(d.clipboardData))}),document.body.appendChild(i),a.selectNodeContents(i),o.addRange(a);var c=document.execCommand(\"copy\");if(!c)throw new Error(\"copy command was unsuccessful\");l=!0}catch(d){s&&console.error(\"unable to copy using execCommand: \",d),s&&console.warn(\"trying IE specific stuff\");try{window.clipboardData.setData(t.format||\"text\",e),t.onCopy&&t.onCopy(window.clipboardData),l=!0}catch(f){s&&console.error(\"unable to copy using clipboardData: \",f),s&&console.error(\"falling back to prompt\"),n=RDe(\"message\"in t?t.message:DDe),window.prompt(n,e)}}finally{o&&(typeof o.removeRange==\"function\"?o.removeRange(a):o.removeAllRanges()),i&&document.body.removeChild(i),r()}return l}var FDe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z\"}}]},name:\"copy\",theme:\"outlined\"},BDe=FDe;function S_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){VDe(e,a,n[a])})}return e}function VDe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var tk=function(t,n){var r=S_({},t,n.attrs);return g(Et,S_({},r,{icon:BDe}),null)};tk.displayName=\"CopyOutlined\";tk.inheritAttrs=!1;var zDe=tk,HDe={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z\"}}]},name:\"edit\",theme:\"outlined\"},jDe=HDe;function k_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){KDe(e,a,n[a])})}return e}function KDe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var nk=function(t,n){var r=k_({},t,n.attrs);return g(Et,k_({},r,{icon:jDe}),null)};nk.displayName=\"EditOutlined\";nk.inheritAttrs=!1;var WDe=nk,UDe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},YDe=bD(\"webkitLineClamp\"),qDe=bD(\"textOverflow\"),$_=\"...\",GR=G({name:\"Base\",inheritAttrs:!1,emits:[\"update:content\"],setup:function(t,n){var r=n.slots,a=n.attrs,o=n.emit,i=Wt(\"typography\",t),l=i.prefixCls,s=bt({edit:!1,copied:!1,ellipsisText:\"\",ellipsisContent:null,isEllipsis:!1,expanded:!1,clientRendered:!1,expandStr:\"\",copyStr:\"\",copiedStr:\"\",editStr:\"\",copyId:void 0,rafId:void 0,prevProps:void 0,originContent:\"\"}),c=H(),d=H(),f=x(function(){var D=t.ellipsis;return D?P({rows:1,expandable:!1},kt(D)===\"object\"?D:null):{}});et(function(){s.clientRendered=!0}),Lt(function(){window.clearTimeout(s.copyId),en.cancel(s.rafId)}),ce([function(){return f.value.rows},function(){return t.content}],function(){Ne(function(){$()})},{flush:\"post\",deep:!0,immediate:!0}),Wn(function(){t.content===void 0&&(on(!t.editable,\"Typography\",\"When `editable` is enabled, please use `content` instead of children\"),on(!t.ellipsis,\"Typography\",\"When `ellipsis` is enabled, please use `content` instead of children\"))});function p(){var D,z;return t.ellipsis||t.editable?t.content:(z=(D=c.value)===null||D===void 0?void 0:D.$el)===null||z===void 0?void 0:z.innerText}function v(D){var z=f.value.onExpand;s.expanded=!0,z==null||z(D)}function m(D){D.preventDefault(),s.originContent=t.content,k(!0)}function y(D){b(D),k(!1)}function b(D){var z=w.value.onChange;D!==t.content&&(o(\"update:content\",D),z==null||z(D))}function C(){var D,z;(z=(D=w.value).onCancel)===null||z===void 0||z.call(D),k(!1)}function S(D){D.preventDefault();var z=t.copyable,B=P({},kt(z)===\"object\"?z:null);B.text===void 0&&(B.text=p()),LDe(B.text||\"\"),s.copied=!0,Ne(function(){B.onCopy&&B.onCopy(),s.copyId=window.setTimeout(function(){s.copied=!1},3e3)})}var w=x(function(){var D=t.editable;return D?P({editing:s.edit},kt(D)===\"object\"?D:null):{editing:s.edit}});function k(D){var z=w.value.onStart;D&&z&&z(),s.edit=D,Ne(function(){var B;D||(B=d.value)===null||B===void 0||B.focus()})}function $(){en.cancel(s.rafId),s.rafId=en(function(){T()})}var O=x(function(){var D=f.value,z=D.rows,B=D.expandable,M=D.suffix,E=D.onEllipsis,K=D.tooltip;return M||K||t.editable||t.copyable||B||E?!1:z===1?qDe:YDe}),T=function(){var z,B,M=s.ellipsisText,E=s.isEllipsis,K=f.value,W=K.rows,Y=K.suffix,q=K.onEllipsis;if(!(!W||W<0||!(!((z=c.value)===null||z===void 0)&&z.$el)||s.expanded||t.content===void 0)&&!O.value){var J=MDe((B=c.value)===null||B===void 0?void 0:B.$el,{rows:W,suffix:Y},t.content,N(!0),$_),ne=J.content,oe=J.text,Q=J.ellipsis;(M!==oe||s.isEllipsis!==Q)&&(s.ellipsisText=oe,s.ellipsisContent=ne,s.isEllipsis=Q,E!==Q&&q&&q(Q))}};function _(D,z){var B=D.mark,M=D.code,E=D.underline,K=D.delete,W=D.strong,Y=D.keyboard,q=z;function J(ne,oe){if(!!ne){var Q=function(){return q}();q=g(oe,null,{default:function(){return[Q]}})}}return J(W,\"strong\"),J(E,\"u\"),J(K,\"del\"),J(M,\"code\"),J(B,\"mark\"),J(Y,\"kbd\"),q}function I(D){var z=f.value,B=z.expandable,M=z.symbol;if(!B||!D&&(s.expanded||!s.isEllipsis))return null;var E=(r.ellipsisSymbol?r.ellipsisSymbol():M)||s.expandStr;return g(\"a\",{key:\"expand\",class:\"\".concat(l.value,\"-expand\"),onClick:v,\"aria-label\":s.expandStr},[E])}function L(){if(!!t.editable){var D=t.editable.tooltip,z=r.editableIcon?r.editableIcon():g(WDe,{role:\"button\"},null),B=r.editableTooltip?r.editableTooltip():s.editStr,M=typeof B==\"string\"?B:\"\";return g(Io,{key:\"edit\",title:D===!1?\"\":B},{default:function(){return[g(cm,{ref:d,class:\"\".concat(l.value,\"-edit\"),onClick:m,\"aria-label\":M},{default:function(){return[z]}})]}})}}function j(){if(!!t.copyable){var D=t.copyable.tooltip,z=s.copied?s.copiedStr:s.copyStr,B=r.copyableTooltip?r.copyableTooltip({copied:s.copied}):z,M=typeof B==\"string\"?B:\"\",E=s.copied?g(wg,null,null):g(zDe,null,null),K=r.copyableIcon?r.copyableIcon({copied:!!s.copied}):E;return g(Io,{key:\"copy\",title:D===!1?\"\":B},{default:function(){return[g(cm,{class:[\"\".concat(l.value,\"-copy\"),V({},\"\".concat(l.value,\"-copy-success\"),s.copied)],onClick:S,\"aria-label\":M},{default:function(){return[K]}})]}})}}function F(){var D=a.class,z=a.style,B=w.value,M=B.maxlength,E=B.autoSize,K=B.onEnd;return g(TDe,{class:D,style:z,prefixCls:l.value,value:t.content,originContent:s.originContent,maxlength:M,autoSize:E,onSave:y,onChange:b,onCancel:C,onEnd:K},null)}function N(D){return[I(D),L(),j()].filter(function(z){return z})}return function(){var D,z=w.value.editing,B=t.ellipsis||t.editable?t.content!==void 0?t.content:(D=r.default)===null||D===void 0?void 0:D.call(r):r.default?r.default():t.content;return z?F():g(Kr,{componentName:\"Text\",children:function(E){var K,W=P(P({},t),a),Y=W.type,q=W.disabled;W.content;var J=W.class,ne=W.style,oe=UDe(W,[\"type\",\"disabled\",\"content\",\"class\",\"style\"]),Q=f.value,ae=Q.rows,de=Q.suffix,be=Q.tooltip,Ee=E.edit,Pe=E.copy,Be=E.copied,te=E.expand;s.editStr=Ee,s.copyStr=Pe,s.copiedStr=Be,s.expandStr=te;var ie=bn(oe,[\"prefixCls\",\"editable\",\"copyable\",\"ellipsis\",\"mark\",\"code\",\"delete\",\"underline\",\"strong\",\"keyboard\"]),ge=O.value,ke=ae===1&&ge,xe=ae&&ae>1&&ge,Ie=B,ye;if(ae&&s.isEllipsis&&!s.expanded&&!ge){var pe=oe.title,ue=pe||\"\";!pe&&(typeof B==\"string\"||typeof B==\"number\")&&(ue=String(B)),ue=ue==null?void 0:ue.slice(String(s.ellipsisContent||\"\").length),Ie=g(Fe,null,[Gt(s.ellipsisContent),g(\"span\",{title:ue,\"aria-hidden\":\"true\"},[$_]),de])}else Ie=g(Fe,null,[B,de]);Ie=_(t,Ie);var Ce=be&&ae&&s.isEllipsis&&!s.expanded&&!ge,je=r.ellipsisTooltip?r.ellipsisTooltip():be;return g(zo,{onResize:$,disabled:!ae},{default:function(){return[g(Fr,le({ref:c,class:[(K={},V(K,\"\".concat(l.value,\"-\").concat(Y),Y),V(K,\"\".concat(l.value,\"-disabled\"),q),V(K,\"\".concat(l.value,\"-ellipsis\"),ae),V(K,\"\".concat(l.value,\"-single-line\"),ae===1),V(K,\"\".concat(l.value,\"-ellipsis-single-line\"),ke),V(K,\"\".concat(l.value,\"-ellipsis-multiple-line\"),xe),K),J],style:P(P({},ne),{WebkitLineClamp:xe?ae:void 0}),\"aria-label\":ye},ie),{default:function(){return[Ce?g(Io,{title:be===!0?B:je},{default:function(){return[g(\"span\",null,[Ie])]}}):Ie,N()]}})]}})}},null)}}}),Uf=function(){return{editable:u.oneOfType([u.looseBool,u.object]),copyable:u.oneOfType([u.looseBool,u.object]),prefixCls:u.string,component:u.string,type:u.oneOf([\"secondary\",\"success\",\"danger\",\"warning\"]),disabled:u.looseBool,ellipsis:u.oneOfType([u.looseBool,u.object]),code:u.looseBool,mark:u.looseBool,underline:u.looseBool,delete:u.looseBool,strong:u.looseBool,keyboard:u.looseBool,content:u.string}};GR.props=Uf();var Yf=GR,GDe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},Lg=function(t,n){var r=n.slots,a=n.attrs,o=P(P({},t),a),i=o.ellipsis,l=o.rel,s=GDe(o,[\"ellipsis\",\"rel\"]);on(kt(i)!==\"object\",\"Typography.Link\",\"`ellipsis` only supports boolean value.\");var c=P(P({},s),{rel:l===void 0&&s.target===\"_blank\"?\"noopener noreferrer\":l,ellipsis:!!i,component:\"a\"});return delete c.navigate,g(Yf,c,r)};Lg.displayName=\"ATypographyLink\";Lg.inheritAttrs=!1;Lg.props=bn(P(P({},Uf()),{ellipsis:u.looseBool}),[\"component\"]);var rk=Lg,Fg=function(t,n){var r=n.slots,a=n.attrs,o=P(P(P({},t),{component:\"div\"}),a);return g(Yf,o,r)};Fg.displayName=\"ATypographyParagraph\";Fg.inheritAttrs=!1;Fg.props=bn(Uf(),[\"component\"]);var ak=Fg,Bg=function(t,n){var r=n.slots,a=n.attrs,o=t.ellipsis;on(kt(o)!==\"object\"||!o||!(\"expandable\"in o)&&!(\"rows\"in o),\"Typography.Text\",\"`ellipsis` do not support `expandable` or `rows` props.\");var i=P(P(P({},t),{ellipsis:o&&kt(o)===\"object\"?bn(o,[\"expandable\",\"rows\"]):o,component:\"span\"}),a);return g(Yf,i,r)};Bg.displayName=\"ATypographyText\";Bg.inheritAttrs=!1;Bg.props=bn(Uf(),[\"component\"]);var ok=Bg,XDe=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},ZDe=u0e(1,2,3,4,5),Vg=function(t,n){var r=n.slots,a=n.attrs,o=t.level,i=o===void 0?1:o,l=XDe(t,[\"level\"]),s;ZDe.indexOf(i)!==-1?s=\"h\".concat(i):(on(!1,\"Typography\",\"Title only accept `1 | 2 | 3 | 4 | 5` as `level` value.\"),s=\"h1\");var c=P(P(P({},l),{component:s}),a);return g(Yf,c,r)};Vg.displayName=\"ATypographyTitle\";Vg.inheritAttrs=!1;Vg.props=bn(P(P({},Uf()),{level:u.number}),[\"component\",\"strong\"]);var ik=Vg;Fr.Text=ok;Fr.Title=ik;Fr.Paragraph=ak;Fr.Link=rk;Fr.Base=Yf;Fr.install=function(e){return e.component(Fr.name,Fr),e.component(Fr.Text.displayName,ok),e.component(Fr.Title.displayName,ik),e.component(Fr.Paragraph.displayName,ak),e.component(Fr.Link.displayName,rk),e};function JDe(e,t){var n=\"cannot \".concat(e.method,\" \").concat(e.action,\" \").concat(t.status,\"'\"),r=new Error(n);return r.status=t.status,r.method=e.method,r.url=e.action,r}function O_(e){var t=e.responseText||e.response;if(!t)return t;try{return JSON.parse(t)}catch{return t}}function QDe(e){var t=new window.XMLHttpRequest;e.onProgress&&t.upload&&(t.upload.onprogress=function(i){i.total>0&&(i.percent=i.loaded/i.total*100),e.onProgress(i)});var n=new window.FormData;e.data&&Object.keys(e.data).forEach(function(o){var i=e.data[o];if(Array.isArray(i)){i.forEach(function(l){n.append(\"\".concat(o,\"[]\"),l)});return}n.append(o,e.data[o])}),n.append(e.filename,e.file),t.onerror=function(i){e.onError(i)},t.onload=function(){if(t.status<200||t.status>=300)return e.onError(JDe(e,t),O_(t));e.onSuccess(O_(t),t)},t.open(e.method,e.action,!0),e.withCredentials&&\"withCredentials\"in t&&(t.withCredentials=!0);var r=e.headers||{};r[\"X-Requested-With\"]!==null&&t.setRequestHeader(\"X-Requested-With\",\"XMLHttpRequest\");for(var a in r)r.hasOwnProperty(a)&&r[a]!==null&&t.setRequestHeader(a,r[a]);return t.send(n),{abort:function(){t.abort()}}}var e7e=+new Date,t7e=0;function ev(){return\"vc-upload-\".concat(e7e,\"-\").concat(++t7e)}function n7e(e,t){return e.indexOf(t,e.length-t.length)!==-1}var P_=function(e,t){if(e&&t){var n=Array.isArray(t)?t:t.split(\",\"),r=e.name||\"\",a=e.type||\"\",o=a.replace(/\\/.*$/,\"\");return n.some(function(i){var l=i.trim();return l.charAt(0)===\".\"?n7e(r.toLowerCase(),l.toLowerCase()):/\\/\\*$/.test(l)?o===l.replace(/\\/.*$/,\"\"):a===l})}return!0};function r7e(e,t){var n=e.createReader(),r=[];function a(){n.readEntries(function(o){var i=Array.prototype.slice.apply(o);r=r.concat(i);var l=!i.length;l?t(r):a()})}a()}var a7e=function(t,n,r){var a=function s(c,d){d=d||\"\",c.isFile?c.file(function(f){r(f)&&(c.fullPath&&!f.webkitRelativePath&&(Object.defineProperties(f,{webkitRelativePath:{writable:!0}}),f.webkitRelativePath=c.fullPath.replace(/^\\//,\"\"),Object.defineProperties(f,{webkitRelativePath:{writable:!1}})),n([f]))}):c.isDirectory&&r7e(c,function(f){f.forEach(function(p){s(p,\"\".concat(d).concat(c.name,\"/\"))})})},o=M1(t),i;try{for(o.s();!(i=o.n()).done;){var l=i.value;a(l.webkitGetAsEntry())}}catch(s){o.e(s)}finally{o.f()}},o7e=a7e,i7e={componentTag:u.string,prefixCls:u.string,name:u.string,multiple:u.looseBool,directory:u.looseBool,disabled:u.looseBool,accept:u.string,data:u.oneOfType([u.object,u.func]),action:u.oneOfType([u.string,u.func]),headers:u.object,beforeUpload:u.func,customRequest:u.func,withCredentials:u.looseBool,openFileDialogOnClick:u.looseBool,transformFile:u.func,method:u.string},l7e={inheritAttrs:!1,name:\"ajaxUploader\",mixins:[nt],props:i7e,data:function(){return this.reqs={},{uid:ev()}},mounted:function(){this._isMounted=!0},beforeUnmount:function(){this._isMounted=!1,this.abort()},methods:{onChange:function(t){var n=t.target.files;this.uploadFiles(n),this.reset()},onClick:function(){var t=this.$refs.fileInputRef;!t||t.click()},onKeyDown:function(t){t.key===\"Enter\"&&this.onClick()},onFileDrop:function(t){var n=this,r=this.$props.multiple;if(t.preventDefault(),t.type!==\"dragover\")if(this.directory)o7e(t.dataTransfer.items,this.uploadFiles,function(l){return P_(l,n.accept)});else{var a=KW(Array.prototype.slice.call(t.dataTransfer.files),function(l){return P_(l,n.accept)}),o=a[0],i=a[1];r===!1&&(o=o.slice(0,1)),this.uploadFiles(o),i.length&&this.__emit(\"reject\",i)}},uploadFiles:function(t){var n=this,r=Array.prototype.slice.call(t);r.map(function(a){return a.uid=ev(),a}).forEach(function(a){n.upload(a,r)})},upload:function(t,n){var r=this;if(!this.beforeUpload)return setTimeout(function(){return r.post(t)},0);var a=this.beforeUpload(t,n);a&&a.then?a.then(function(o){var i=Object.prototype.toString.call(o);return i===\"[object File]\"||i===\"[object Blob]\"?r.post(o):r.post(t)}).catch(function(o){console&&console.log(o)}):a!==!1&&setTimeout(function(){return r.post(t)},0)},post:function(t){var n=this;if(!!this._isMounted){var r=this.$props,a=r.data,o=r.transformFile,i=o===void 0?function(l){return l}:o;new Promise(function(l){var s=n.action;if(typeof s==\"function\")return l(s(t));l(s)}).then(function(l){var s=t.uid,c=n.customRequest||QDe,d=Promise.resolve(i(t)).catch(function(f){console.error(f)});d.then(function(f){typeof a==\"function\"&&(a=a(t));var p={action:l,filename:n.name,data:a,file:f,headers:n.headers,withCredentials:n.withCredentials,method:r.method||\"post\",onProgress:function(m){n.__emit(\"progress\",m,t)},onSuccess:function(m,y){delete n.reqs[s],n.__emit(\"success\",m,t,y)},onError:function(m,y){delete n.reqs[s],n.__emit(\"error\",m,y,t)}};n.reqs[s]=c(p),n.__emit(\"start\",t)})})}},reset:function(){this.setState({uid:ev()})},abort:function(t){var n=this.reqs;if(t){var r=t;t&&t.uid&&(r=t.uid),n[r]&&n[r].abort&&n[r].abort(),delete n[r]}else Object.keys(n).forEach(function(a){n[a]&&n[a].abort&&n[a].abort(),delete n[a]})}},render:function(){var t,n=this,r=this.$props,a=this.$attrs,o=r.componentTag,i=r.prefixCls,l=r.disabled,s=r.multiple,c=r.accept,d=r.directory,f=r.openFileDialogOnClick,p=a.class,v=a.style,m=a.id,y=Se((t={},V(t,i,!0),V(t,\"\".concat(i,\"-disabled\"),l),V(t,p,p),t)),b=l?{}:{onClick:f?this.onClick:function(){},onKeydown:f?this.onKeyDown:function(){},onDrop:this.onFileDrop,onDragover:this.onFileDrop},C=P(P({},b),{role:\"button\",tabindex:l?null:\"0\",class:y,style:v});return g(o,C,{default:function(){return[g(\"input\",{id:m,type:\"file\",ref:\"fileInputRef\",onClick:function(k){return k.stopPropagation()},key:n.uid,style:{display:\"none\"},accept:c,directory:d?\"directory\":null,webkitdirectory:d?\"webkitdirectory\":null,multiple:s,onChange:n.onChange},null),ht(n)]}})}},s7e=l7e,u7e={position:\"absolute\",top:0,opacity:0,filter:\"alpha(opacity=0)\",left:0,zIndex:9999},c7e={name:\"IframeUploader\",mixins:[nt],props:{componentTag:u.string,disabled:u.looseBool,prefixCls:u.string,accept:u.string,multiple:u.looseBool,data:u.oneOfType([u.object,u.func]),action:u.oneOfType([u.string,u.func]),name:u.string},data:function(){return this.file={},{uploading:!1}},methods:{onLoad:function(){if(!!this.uploading){var t=this.file,n;try{var r=this.getIframeDocument(),a=r.getElementsByTagName(\"script\")[0];a&&a.parentNode===r.body&&r.body.removeChild(a),n=r.body.innerHTML,this.__emit(\"success\",n,t)}catch(o){on(!1,\"cross domain error for Upload. Maybe server should return document.domain script. see Note from https://github.com/react-component/upload\"),n=\"cross-domain\",this.__emit(\"error\",o,null,t)}this.endUpload()}},onChange:function(){var t=this,n=this.getFormInputNode(),r=this.file={uid:ev(),name:n.value&&n.value.substring(n.value.lastIndexOf(\"\\\\\")+1,n.value.length)};this.startUpload();var a=this.$props;if(!a.beforeUpload)return this.post(r);var o=a.beforeUpload(r);o&&o.then?o.then(function(){t.post(r)},function(){t.endUpload()}):o!==!1?this.post(r):this.endUpload()},getIframeNode:function(){return this.$refs.iframeRef},getIframeDocument:function(){return this.getIframeNode().contentDocument},getFormNode:function(){return this.getIframeDocument().getElementById(\"form\")},getFormInputNode:function(){return this.getIframeDocument().getElementById(\"input\")},getFormDataNode:function(){return this.getIframeDocument().getElementById(\"data\")},getFileForMultiple:function(t){return this.multiple?[t]:t},getIframeHTML:function(t){var n=\"\",r=\"\";if(t){var a=\"script\";n=\"<\".concat(a,'>document.domain=\"').concat(t,'\";</').concat(a,\">\"),r='<input name=\"_documentDomain\" value=\"'.concat(t,'\" />')}return`\n      <!DOCTYPE html>\n      <html>\n      <head>\n      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n      <style>\n      body,html {padding:0;margin:0;border:0;overflow:hidden;}\n      </style>\n      `.concat(n,`\n      </head>\n      <body>\n      <form method=\"post\"\n      encType=\"multipart/form-data\"\n      action=\"\" id=\"form\"\n      style=\"display:block;height:9999px;position:relative;overflow:hidden;\">\n      <input id=\"input\" type=\"file\"\n       name=\"`).concat(this.name,`\"\n       style=\"position:absolute;top:0;right:0;height:9999px;font-size:9999px;cursor:pointer;\"/>\n      `).concat(r,`\n      <span id=\"data\"></span>\n      </form>\n      </body>\n      </html>\n      `)},initIframeSrc:function(){this.domain&&(this.getIframeNode().src=`javascript:void((function(){\n          var d = document;\n          d.open();\n          d.domain='`.concat(this.domain,`';\n          d.write('');\n          d.close();\n        })())`))},initIframe:function(){var t=this.getIframeNode(),n=t.contentWindow,r;this.domain=this.domain||\"\",this.initIframeSrc();try{r=n.document}catch{this.domain=document.domain,this.initIframeSrc(),n=t.contentWindow,r=n.document}r.open(\"text/html\",\"replace\"),r.write(this.getIframeHTML(this.domain)),r.close(),this.getFormInputNode().onchange=this.onChange},endUpload:function(){this.uploading&&(this.file={},this.uploading=!1,this.setState({uploading:!1}),this.initIframe())},startUpload:function(){this.uploading||(this.uploading=!0,this.setState({uploading:!0}))},updateIframeWH:function(){var t=Sn(this),n=this.getIframeNode();n.style.height=\"\".concat(t.offsetHeight,\"px\"),n.style.width=\"\".concat(t.offsetWidth,\"px\")},abort:function(t){if(t){var n=t;t&&t.uid&&(n=t.uid),n===this.file.uid&&this.endUpload()}else this.endUpload()},post:function(t){var n=this,r=this.getFormNode(),a=this.getFormDataNode(),o=this.$props.data;typeof o==\"function\"&&(o=o(t));var i=document.createDocumentFragment();for(var l in o)if(o.hasOwnProperty(l)){var s=document.createElement(\"input\");s.setAttribute(\"name\",l),s.value=o[l],i.appendChild(s)}a.appendChild(i),new Promise(function(c){var d=n.action;if(typeof d==\"function\")return c(d(t));c(d)}).then(function(c){r.setAttribute(\"action\",c),r.submit(),a.innerHTML=\"\",n.__emit(\"start\",t)})}},mounted:function(){var t=this;this.$nextTick(function(){t.updateIframeWH(),t.initIframe()})},updated:function(){var t=this;this.$nextTick(function(){t.updateIframeWH()})},render:function(){var t,n=this,r=this.$props,a=r.componentTag,o=r.disabled,i=r.prefixCls,l=this.$attrs,s=l.class,c=l.style,d=P(P({},u7e),{display:this.uploading||o?\"none\":\"\"}),f=Se((t={},V(t,i,!0),V(t,\"\".concat(i,\"-disabled\"),o),V(t,s,s),t));return g(a,{class:f,style:P({position:\"relative\",zIndex:0},c)},{default:function(){return[g(\"iframe\",{ref:\"iframeRef\",onLoad:n.onLoad,style:d},null),ht(n)]}})}},d7e=c7e;function Jc(){}var f7e={componentTag:u.string,prefixCls:u.string,action:u.oneOfType([u.string,u.func]),name:u.string,multipart:u.looseBool,directory:u.looseBool,onError:u.func,onSuccess:u.func,onProgress:u.func,onStart:u.func,data:u.oneOfType([u.object,u.func]),headers:u.object,accept:u.string,multiple:u.looseBool,disabled:u.looseBool,beforeUpload:u.func,customRequest:u.func,onReady:u.func,withCredentials:u.looseBool,supportServerRender:u.looseBool,openFileDialogOnClick:u.looseBool,method:u.string},T_=G({name:\"Upload\",mixins:[nt],inheritAttrs:!1,props:An(f7e,{componentTag:\"span\",prefixCls:\"rc-upload\",data:{},headers:{},name:\"file\",multipart:!1,onReady:Jc,onStart:Jc,onError:Jc,onSuccess:Jc,supportServerRender:!1,multiple:!1,beforeUpload:Jc,withCredentials:!1,openFileDialogOnClick:!0}),data:function(){return this.Component=null,{}},mounted:function(){var t=this;this.$nextTick(function(){t.supportServerRender&&(t.Component=t.getComponent(),t.$forceUpdate(),Ne(function(){t.__emit(\"ready\")}))})},methods:{getComponent:function(){return typeof File!=\"undefined\"?s7e:d7e},abort:function(t){this.$refs.uploaderRef.abort(t)}},render:function(){var t=this,n=P(P(P({},this.$props),{ref:\"uploaderRef\"}),this.$attrs);if(this.supportServerRender){var r=this.Component;return r?g(r,n,{default:function(){return[ht(t)]}}):null}var a=this.getComponent();return g(a,n,{default:function(){return[ht(t)]}})}});u.oneOf(rt(\"error\",\"success\",\"done\",\"uploading\",\"removed\"));function dc(e){var t=e.uid,n=e.name;return!(!t&&t!==0||![\"string\",\"number\"].includes(kt(t))||n===\"\"||typeof n!=\"string\")}u.custom(dc),u.arrayOf(u.custom(dc)),u.object;var h7e=u.shape({showRemoveIcon:u.looseBool,showPreviewIcon:u.looseBool}).loose,XR=u.shape({uploading:u.string,removeFile:u.string,downloadFile:u.string,uploadError:u.string,previewFile:u.string}).loose,ZR={type:u.oneOf(rt(\"drag\",\"select\")),name:u.string,defaultFileList:u.arrayOf(u.custom(dc)),fileList:u.arrayOf(u.custom(dc)),action:u.oneOfType([u.string,u.func]),directory:u.looseBool,data:u.oneOfType([u.object,u.func]),method:u.oneOf(rt(\"POST\",\"PUT\",\"PATCH\",\"post\",\"put\",\"patch\")),headers:u.object,showUploadList:u.oneOfType([u.looseBool,h7e]),multiple:u.looseBool,accept:u.string,beforeUpload:u.func,listType:u.oneOf(rt(\"text\",\"picture\",\"picture-card\")),remove:u.func,supportServerRender:u.looseBool,disabled:u.looseBool,prefixCls:u.string,customRequest:u.func,withCredentials:u.looseBool,openFileDialogOnClick:u.looseBool,locale:XR,height:u.number,id:u.string,previewFile:u.func,transformFile:u.func,onChange:u.func,onPreview:u.func,onRemove:u.func,onDownload:u.func,\"onUpdate:fileList\":u.func};u.arrayOf(u.custom(dc)),u.string;var p7e={listType:u.oneOf(rt(\"text\",\"picture\",\"picture-card\")),items:u.arrayOf(u.custom(dc)),progressAttr:u.object,prefixCls:u.string,showRemoveIcon:u.looseBool,showDownloadIcon:u.looseBool,showPreviewIcon:u.looseBool,locale:XR,previewFile:u.func,onPreview:u.func,onRemove:u.func,onDownload:u.func},x_=globalThis&&globalThis.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)t.indexOf(r[a])<0&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n},yf=G({name:\"AUploadDragger\",inheritAttrs:!1,props:ZR,render:function(){var t=this,n=Qe(this),r=n.height,a=x_(n,[\"height\"]),o=this.$attrs,i=o.style,l=x_(o,[\"style\"]),s=P(P(P({},a),l),{type:\"drag\",style:P(P({},i),{height:r})});return g(Bu,s,{default:function(){return[ht(t)]}})}});function v7e(){return!0}function __(e){return P(P({},e),{lastModified:e.lastModified,lastModifiedDate:e.lastModifiedDate,name:e.name,size:e.size,type:e.type,uid:e.uid,percent:0,originFileObj:e})}function m7e(){var e=.1,t=.01,n=.98;return function(r){var a=r;return a>=n||(a+=e,e=e-t,e<.001&&(e=.001)),a}}function Nb(e,t){var n=e.uid!==void 0?\"uid\":\"name\";return t.filter(function(r){return r[n]===e[n]})[0]}function g7e(e,t){var n=e.uid!==void 0?\"uid\":\"name\",r=t.filter(function(a){return a[n]!==e[n]});return r.length===t.length?null:r}var y7e=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:\"\",n=t.split(\"/\"),r=n[n.length-1],a=r.split(/#|\\?/)[0];return(/\\.[^./\\\\]*$/.exec(a)||[\"\"])[0]},JR=function(t){return!!t&&t.indexOf(\"image/\")===0},b7e=function(t){if(JR(t.type))return!0;var n=t.thumbUrl||t.url,r=y7e(n);return/^data:image\\//.test(n)||/(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico)$/i.test(r)?!0:!(/^data:/.test(n)||r)},Fi=200;function C7e(e){return new Promise(function(t){if(!JR(e.type)){t(\"\");return}var n=document.createElement(\"canvas\");n.width=Fi,n.height=Fi,n.style.cssText=\"position: fixed; left: 0; top: 0; width: \".concat(Fi,\"px; height: \").concat(Fi,\"px; z-index: 9999; display: none;\"),document.body.appendChild(n);var r=n.getContext(\"2d\"),a=new Image;a.onload=function(){var o=a.width,i=a.height,l=Fi,s=Fi,c=0,d=0;o<i?(s=i*(Fi/o),d=-(s-l)/2):(l=o*(Fi/i),c=-(l-s)/2),r.drawImage(a,c,d,l,s);var f=n.toDataURL();document.body.removeChild(n),t(f)},a.src=window.URL.createObjectURL(e)})}var w7e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z\"}}]},name:\"paper-clip\",theme:\"outlined\"},S7e=w7e;function E_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){k7e(e,a,n[a])})}return e}function k7e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var lk=function(t,n){var r=E_({},t,n.attrs);return g(Et,E_({},r,{icon:S7e}),null)};lk.displayName=\"PaperClipOutlined\";lk.inheritAttrs=!1;var $7e=lk,O7e={icon:function(t,n){return{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zm-40 632H136v-39.9l138.5-164.3 150.1 178L658.1 489 888 761.6V792zm0-129.8L664.2 396.8c-3.2-3.8-9-3.8-12.2 0L424.6 666.4l-144-170.7c-3.2-3.8-9-3.8-12.2 0L136 652.7V232h752v430.2z\",fill:t}},{tag:\"path\",attrs:{d:\"M424.6 765.8l-150.1-178L136 752.1V792h752v-30.4L658.1 489z\",fill:n}},{tag:\"path\",attrs:{d:\"M136 652.7l132.4-157c3.2-3.8 9-3.8 12.2 0l144 170.7L652 396.8c3.2-3.8 9-3.8 12.2 0L888 662.2V232H136v420.7zM304 280a88 88 0 110 176 88 88 0 010-176z\",fill:n}},{tag:\"path\",attrs:{d:\"M276 368a28 28 0 1056 0 28 28 0 10-56 0z\",fill:n}},{tag:\"path\",attrs:{d:\"M304 456a88 88 0 100-176 88 88 0 000 176zm0-116c15.5 0 28 12.5 28 28s-12.5 28-28 28-28-12.5-28-28 12.5-28 28-28z\",fill:t}}]}},name:\"picture\",theme:\"twotone\"},P7e=O7e;function M_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){T7e(e,a,n[a])})}return e}function T7e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var sk=function(t,n){var r=M_({},t,n.attrs);return g(Et,M_({},r,{icon:P7e}),null)};sk.displayName=\"PictureTwoTone\";sk.inheritAttrs=!1;var x7e=sk,_7e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z\"}}]},name:\"delete\",theme:\"outlined\"},E7e=_7e;function I_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){M7e(e,a,n[a])})}return e}function M7e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var uk=function(t,n){var r=I_({},t,n.attrs);return g(Et,I_({},r,{icon:E7e}),null)};uk.displayName=\"DeleteOutlined\";uk.inheritAttrs=!1;var I7e=uk,N7e={icon:{tag:\"svg\",attrs:{viewBox:\"64 64 896 896\",focusable:\"false\"},children:[{tag:\"path\",attrs:{d:\"M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z\"}}]},name:\"download\",theme:\"outlined\"},A7e=N7e;function N_(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},r=Object.keys(n);typeof Object.getOwnPropertySymbols==\"function\"&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(a){return Object.getOwnPropertyDescriptor(n,a).enumerable}))),r.forEach(function(a){D7e(e,a,n[a])})}return e}function D7e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var ck=function(t,n){var r=N_({},t,n.attrs);return g(Et,N_({},r,{icon:A7e}),null)};ck.displayName=\"DownloadOutlined\";ck.inheritAttrs=!1;var R7e=ck,L7e=G({name:\"AUploadList\",mixins:[nt],props:An(p7e,{listType:\"text\",progressAttr:{strokeWidth:2,showInfo:!1},showRemoveIcon:!0,showDownloadIcon:!1,showPreviewIcon:!0,previewFile:C7e}),setup:function(){return{configProvider:ve(\"configProvider\",St)}},updated:function(){var t=this;Ne(function(){var n=t.$props,r=n.listType,a=n.items,o=n.previewFile;r!==\"picture\"&&r!==\"picture-card\"||(a||[]).forEach(function(i){typeof document==\"undefined\"||typeof window==\"undefined\"||!window.FileReader||!window.File||!(i.originFileObj instanceof File||i.originFileObj instanceof Blob)||i.thumbUrl!==void 0||(i.thumbUrl=\"\",o&&o(i.originFileObj).then(function(l){i.thumbUrl=l||\"\",t.$forceUpdate()}))})})},methods:{handlePreview:function(t,n){var r=this.$props.onPreview;if(!!r)return n.preventDefault(),this.$emit(\"preview\",t)},handleDownload:function(t){var n=this.$props.onDownload;typeof n==\"function\"?this.$emit(\"download\",t):t.url&&window.open(t.url)},handleClose:function(t){this.$emit(\"remove\",t)}},render:function(){var t=this,n,r=Qe(this),a=r.prefixCls,o=r.items,i=o===void 0?[]:o,l=r.listType,s=r.showPreviewIcon,c=r.showRemoveIcon,d=r.showDownloadIcon,f=r.locale,p=r.progressAttr,v=this.configProvider.getPrefixCls,m=v(\"upload\",a),y=i.map(function(w){var k,$,O,T=w.status===\"uploading\"?g(co,null,null):g($7e,null,null);if(l===\"picture\"||l===\"picture-card\")if(l===\"picture-card\"&&w.status===\"uploading\")T=g(\"div\",{class:\"\".concat(m,\"-list-item-uploading-text\")},[f.uploading]);else if(!w.thumbUrl&&!w.url)T=g(x7e,{class:\"\".concat(m,\"-list-item-thumbnail\")},null);else{var _=b7e(w)?g(\"img\",{src:w.thumbUrl||w.url,alt:w.name,class:\"\".concat(m,\"-list-item-image\")},null):g(zS,{class:\"\".concat(m,\"-list-item-icon\")},null);T=g(\"a\",{class:\"\".concat(m,\"-list-item-thumbnail\"),onClick:function(ae){return t.handlePreview(w,ae)},href:w.url||w.thumbUrl,target:\"_blank\",rel:\"noopener noreferrer\"},[_])}if(w.status===\"uploading\"){var I=P(P({},p),{type:\"line\",percent:w.percent}),L=\"percent\"in w?g(dR,I,null):null;O=g(\"div\",{class:\"\".concat(m,\"-list-item-progress\"),key:\"progress\"},[L])}var j=Se((k={},V(k,\"\".concat(m,\"-list-item\"),!0),V(k,\"\".concat(m,\"-list-item-\").concat(w.status),!0),V(k,\"\".concat(m,\"-list-item-list-type-\").concat(l),!0),k)),F=typeof w.linkProps==\"string\"?JSON.parse(w.linkProps):w.linkProps,N=c?g(I7e,{title:f.removeFile,onClick:function(){return t.handleClose(w)}},null):null,D=d&&w.status===\"done\"?g(R7e,{title:f.downloadFile,onClick:function(){return t.handleDownload(w)}},null):null,z=l!==\"picture-card\"&&g(\"span\",{key:\"download-delete\",class:\"\".concat(m,\"-list-item-card-actions \").concat(l===\"picture\"?\"picture\":\"\")},[D&&g(\"a\",{title:f.downloadFile},[D]),N&&g(\"a\",{title:f.removeFile},[N])]),B=Se(($={},V($,\"\".concat(m,\"-list-item-name\"),!0),V($,\"\".concat(m,\"-list-item-name-icon-count-\").concat([D,N].filter(function(Q){return Q}).length),!0),$)),M=w.url?[g(\"a\",le(le({target:\"_blank\",rel:\"noopener noreferrer\",class:B,title:w.name},F),{},{href:w.url,onClick:function(ae){return t.handlePreview(w,ae)}}),[w.name]),z]:[g(\"span\",{key:\"view\",class:\"\".concat(m,\"-list-item-name\"),onClick:function(ae){return t.handlePreview(w,ae)},title:w.name},[w.name]),z],E=w.url||w.thumbUrl?void 0:{pointerEvents:\"none\",opacity:.5},K=s?g(\"a\",{href:w.url||w.thumbUrl,target:\"_blank\",rel:\"noopener noreferrer\",style:E,onClick:function(ae){return t.handlePreview(w,ae)},title:f.previewFile},[g(RA,null,null)]):null,W=l===\"picture-card\"&&w.status!==\"uploading\"&&g(\"span\",{class:\"\".concat(m,\"-list-item-actions\")},[K,w.status===\"done\"&&D,N]),Y;w.response&&typeof w.response==\"string\"?Y=w.response:Y=w.error&&w.error.statusText||f.uploadError;var q=g(\"span\",null,[T,M]),J=Lo(\"fade\"),ne=g(\"div\",{class:j,key:w.uid},[g(\"div\",{class:\"\".concat(m,\"-list-item-info\")},[q]),W,g(no,J,{default:function(){return[O]}})]),oe=Se(V({},\"\".concat(m,\"-list-picture-card-container\"),l===\"picture-card\"));return g(\"div\",{key:w.uid,class:oe},[w.status===\"error\"?g(Io,{title:Y},{default:function(){return[ne]}}):g(\"span\",null,[ne])])}),b=Se((n={},V(n,\"\".concat(m,\"-list\"),!0),V(n,\"\".concat(m,\"-list-\").concat(l),!0),n)),C=l===\"picture-card\"?\"animate-inline\":\"animate\",S=P(P({},d2(\"\".concat(m,\"-\").concat(C))),{class:b});return g(f2,le(le({},S),{},{tag:\"div\"}),{default:function(){return[y]}})}}),Bu=G({name:\"AUpload\",mixins:[nt],inheritAttrs:!1,Dragger:yf,props:Rn(ZR,{type:\"select\",multiple:!1,action:\"\",data:{},accept:\"\",beforeUpload:v7e,showUploadList:!0,listType:\"text\",disabled:!1,supportServerRender:!0}),setup:function(){return{upload:null,progressTimer:null,configProvider:ve(\"configProvider\",St)}},data:function(){return{sFileList:this.fileList||this.defaultFileList||[],dragState:\"drop\"}},watch:{fileList:function(t){this.sFileList=t||[]}},beforeUnmount:function(){this.clearProgressTimer()},methods:{onStart:function(t){var n=__(t);n.status=\"uploading\";var r=this.sFileList.concat(),a=U8(r,function(o){var i=o.uid;return i===n.uid});a===-1?r.push(n):r[a]=n,this.handleChange({file:n,fileList:r}),(!window.File||(typeof process==\"undefined\"?\"undefined\":kt(process))===\"object\"&&{}.TEST_IE)&&this.autoUpdateProgress(0,n)},onSuccess:function(t,n,r){this.clearProgressTimer();try{typeof t==\"string\"&&(t=JSON.parse(t))}catch{}var a=this.sFileList,o=Nb(n,a);!o||(o.status=\"done\",o.response=t,o.xhr=r,this.handleChange({file:P({},o),fileList:a}))},onProgress:function(t,n){var r=this.sFileList,a=Nb(n,r);!a||(a.percent=t.percent,this.handleChange({event:t,file:P({},a),fileList:this.sFileList}))},onError:function(t,n,r){this.clearProgressTimer();var a=this.sFileList,o=Nb(r,a);!o||(o.error=t,o.response=n,o.status=\"error\",this.handleChange({file:P({},o),fileList:a}))},onReject:function(t){this.$emit(\"reject\",t)},handleRemove:function(t){var n=this,r=this.remove,a=this.$data.sFileList;Promise.resolve(typeof r==\"function\"?r(t):r).then(function(o){if(o!==!1){var i=g7e(t,a);i&&(t.status=\"removed\",n.upload&&n.upload.abort(t),n.handleChange({file:t,fileList:i}))}})},handleManualRemove:function(t){this.$refs.uploadRef&&this.$refs.uploadRef.abort(t),this.handleRemove(t)},handleChange:function(t){vt(this,\"fileList\")||this.setState({sFileList:t.fileList}),this.$emit(\"update:fileList\",t.fileList),this.$emit(\"change\",t)},onFileDrop:function(t){this.setState({dragState:t.type})},reBeforeUpload:function(t,n){var r=this.$props.beforeUpload,a=this.$data.sFileList;if(!r)return!0;var o=r(t,n);return o===!1?(this.handleChange({file:t,fileList:tU(a.concat(n.map(__)),function(i){return i.uid})}),!1):o&&o.then?o:!0},clearProgressTimer:function(){clearInterval(this.progressTimer)},autoUpdateProgress:function(t,n){var r=this,a=m7e(),o=0;this.clearProgressTimer(),this.progressTimer=setInterval(function(){o=a(o),r.onProgress({percent:o*100},n)},200)},renderUploadList:function(t){var n=Qe(this),r=n.showUploadList,a=r===void 0?{}:r,o=n.listType,i=n.previewFile,l=n.disabled,s=n.locale,c=a.showRemoveIcon,d=a.showPreviewIcon,f=a.showDownloadIcon,p=this.$data.sFileList,v=this.$props,m=v.onDownload,y=v.onPreview,b={listType:o,items:p,previewFile:i,showRemoveIcon:!l&&c,showPreviewIcon:d,showDownloadIcon:f,locale:P(P({},t),s),onRemove:this.handleManualRemove,onDownload:m,onPreview:y};return g(L7e,b,null)}},render:function(){var t,n=Qe(this),r=n.prefixCls,a=n.showUploadList,o=n.listType,i=n.type,l=n.disabled,s=this.$data,c=s.sFileList,d=s.dragState,f=this.$attrs,p=f.class,v=f.style,m=this.configProvider.getPrefixCls,y=m(\"upload\",r),b=P(P({},this.$props),{prefixCls:y,beforeUpload:this.reBeforeUpload,onStart:this.onStart,onError:this.onError,onProgress:this.onProgress,onSuccess:this.onSuccess,onReject:this.onReject,ref:\"uploadRef\"}),C=a?g(Kr,{componentName:\"Upload\",defaultLocale:lo.Upload,children:this.renderUploadList},null):null,S=ht(this);if(i===\"drag\"){var w,k=Se(y,(w={},V(w,\"\".concat(y,\"-drag\"),!0),V(w,\"\".concat(y,\"-drag-uploading\"),c.some(function(T){return T.status===\"uploading\"})),V(w,\"\".concat(y,\"-drag-hover\"),d===\"dragover\"),V(w,\"\".concat(y,\"-disabled\"),l),w));return g(\"span\",le({class:p},US(this.$attrs)),[g(\"div\",{class:k,onDrop:this.onFileDrop,onDragover:this.onFileDrop,onDragleave:this.onFileDrop,style:v},[g(T_,le(le({},b),{},{class:\"\".concat(y,\"-btn\")}),{default:function(){return[g(\"div\",{class:\"\".concat(y,\"-drag-container\")},[S])]}})]),C])}var $=Se(y,(t={},V(t,\"\".concat(y,\"-select\"),!0),V(t,\"\".concat(y,\"-select-\").concat(o),!0),V(t,\"\".concat(y,\"-disabled\"),l),t));(!S.length||l)&&delete b.id;var O=g(\"div\",{class:$,style:S.length?void 0:{display:\"none\"}},[g(T_,b,{default:function(){return[S]}})]);return o===\"picture-card\"?g(\"span\",{class:Se(\"\".concat(y,\"-picture-card-wrapper\"),p)},[C,O]):g(\"span\",{class:p},[O,C])}});Bu.Dragger=yf;Bu.install=function(e){return e.component(Bu.name,Bu),e.component(yf.name,yf),e};var F7e=yf,A_=Object.freeze(Object.defineProperty({__proto__:null,Affix:ZN,Anchor:Bl,AnchorLink:eA,AutoComplete:w4e,AutoCompleteOptGroup:C4e,AutoCompleteOption:b4e,Alert:G4e,Avatar:ss,AvatarGroup:Kv,BackTop:wOe,Badge:Kp,BadgeRibbon:Wv,Breadcrumb:us,BreadcrumbItem:df,BreadcrumbSeparator:Gv,Button:Cr,ButtonGroup:jv,Calendar:VPe,Card:Ru,CardGrid:nm,CardMeta:tm,Collapse:Pd,CollapsePanel:rm,Carousel:kTe,Cascader:zTe,Checkbox:ro,CheckboxGroup:im,Col:Ka,Comment:WTe,ConfigProvider:S2e,DatePicker:Qxe,RangePicker:o7,MonthPicker:l7,WeekPicker:i7,Descriptions:l_e,DescriptionsItem:s7,Divider:c_e,Dropdown:hi,DropdownButton:cf,Drawer:C_e,Empty:su,Form:pu,FormItem:S7,Grid:x3e,Input:Jn,InputGroup:AA,InputPassword:LA,InputSearch:DA,Textarea:S2,Image:Q6e,ImagePreviewGroup:M7,InputNumber:f8e,Layout:pr,LayoutHeader:$8e,LayoutSider:P8e,LayoutFooter:O8e,LayoutContent:T8e,List:nEe,ListItem:R7,ListItemMeta:A7,message:j7,Menu:jr,MenuDivider:qv,MenuItem:fl,MenuItemGroup:Yv,SubMenu:sc,Mentions:EEe,MentionsOption:_Ee,Modal:cr,Statistic:oi,StatisticCountdown:aMe,notification:sR,PageHeader:OMe,Pagination:OS,Popconfirm:TMe,Popover:KA,Progress:dR,Radio:_r,RadioButton:Jv,RadioGroup:Y2,Rate:l5e,Result:k5e,Row:fu,Select:dl,SelectOptGroup:F$e,SelectOption:L$e,Skeleton:na,SkeletonButton:NS,SkeletonAvatar:xS,SkeletonInput:AS,SkeletonImage:DS,Slider:H5e,Space:Y5e,Spin:ol,Steps:J5e,Step:Z5e,Switch:nIe,Table:fNe,TableColumn:cNe,TableColumnGroup:dNe,Transfer:RNe,Tree:Po,TreeNode:mAe,DirectoryTree:dm,TreeSelect:bDe,TreeSelectNode:yDe,Tabs:$a,TabPane:G2,TabContent:X2,Tag:e7,CheckableTag:lm,TimePicker:Rxe,Timeline:Ed,TimelineItem:gf,Tooltip:Io,Typography:Fr,TypographyLink:rk,TypographyParagraph:ak,TypographyText:ok,TypographyTitle:ik,Upload:Bu,UploadDragger:F7e,LocaleProvider:XN},Symbol.toStringTag,{value:\"Module\"}));const B7e=\"ant-design-vue\",V7e=\"2.2.8\",z7e=\"Ant Design Vue\",H7e=\"An enterprise-class UI design language and Vue-based implementation\",j7e=[\"vue\",\"vue3\",\"ant\",\"design\",\"antd\",\"vueComponent\",\"component\",\"components\",\"ui\",\"framework\",\"frontend\"],K7e=\"lib/index.js\",W7e=\"es/index.js\",U7e=\"dist/antd.min.js\",Y7e=\"lib/index.d.ts\",q7e=[\"dist\",\"lib\",\"es\",\"scripts\",\"vetur\"],G7e={dev:\"webpack serve\",test:\"cross-env NODE_ENV=test WORKFLOW=true jest --config .jest.js\",\"test:dev\":\"cross-env NODE_ENV=test jest --config .jest.js\",compile:\"node antd-tools/cli/run.js compile\",\"generator-webtypes\":\"tsc -p antd-tools/generator-types/tsconfig.json && node antd-tools/generator-types/index.js\",pub:\"node --max_old_space_size=8192 antd-tools/cli/run.js pub\",\"pub-with-ci\":\"node antd-tools/cli/run.js pub-with-ci\",prepublishOnly:\"node antd-tools/cli/run.js guard\",\"pre-publish\":\"node ./scripts/prepub && npm run generator-webtypes\",prettier:\"prettier -c --write '**/*'\",\"pretty-quick\":\"pretty-quick\",dist:\"node --max_old_space_size=8192 antd-tools/cli/run.js dist\",lint:\"eslint -c ./.eslintrc --fix --ext .jsx,.js,.vue,.ts,.tsx ./components\",\"lint:style\":'stylelint \"{site,components}/**/*.less\" --syntax less',codecov:\"codecov\"},X7e={type:\"git\",url:\"git+https://github.com/vueComponent/ant-design-vue.git\"},Z7e=\"MIT\",J7e={type:\"opencollective\",url:\"https://opencollective.com/ant-design-vue\"},Q7e={url:\"https://github.com/vueComponent/ant-design-vue/issues\"},eRe=\"https://www.antdv.com/\",tRe={\"@vue/compiler-sfc\":\">=3.1.0\",vue:\">=3.1.0\"},nRe={\"@babel/cli\":\"^7.8.4\",\"@babel/core\":\"^7.10.5\",\"@babel/plugin-proposal-class-properties\":\"^7.8.3\",\"@babel/plugin-proposal-export-default-from\":\"^7.8.3\",\"@babel/plugin-proposal-export-namespace-from\":\"^7.12.1\",\"@babel/plugin-proposal-object-rest-spread\":\"^7.9.6\",\"@babel/plugin-proposal-optional-chaining\":\"^7.10.1\",\"@babel/plugin-syntax-dynamic-import\":\"^7.8.3\",\"@babel/plugin-transform-member-expression-literals\":\"^7.8.3\",\"@babel/plugin-transform-object-assign\":\"^7.8.3\",\"@babel/plugin-transform-property-literals\":\"^7.8.3\",\"@babel/plugin-transform-runtime\":\"^7.10.5\",\"@babel/plugin-transform-template-literals\":\"^7.8.3\",\"@babel/plugin-transform-typescript\":\"^7.12.1\",\"@babel/polyfill\":\"^7.8.7\",\"@babel/preset-env\":\"^7.9.6\",\"@babel/preset-typescript\":\"^7.10.4\",\"@commitlint/cli\":\"^12.0.0\",\"@commitlint/config-conventional\":\"^12.0.0\",\"@octokit/rest\":\"^18.0.0\",\"@types/fs-extra\":\"^9.0.8\",\"@types/lodash-es\":\"^4.17.3\",\"@types/raf\":\"^3.4.0\",\"@typescript-eslint/eslint-plugin\":\"^4.1.0\",\"@typescript-eslint/parser\":\"^4.1.0\",\"@vue/babel-plugin-jsx\":\"^1.0.0\",\"@vue/cli-plugin-eslint\":\"^5.0.0-0\",\"@vue/compiler-sfc\":\"^3.1.0\",\"@vue/eslint-config-prettier\":\"^6.0.0\",\"@vue/eslint-config-typescript\":\"^7.0.0\",\"@vue/test-utils\":\"^2.0.0-0\",\"@webpack-cli/serve\":\"^1.3.1\",acorn:\"^8.0.0\",autoprefixer:\"^10.2.0\",axios:\"^0.21.0\",\"babel-eslint\":\"^10.0.1\",\"babel-jest\":\"^26.1.0\",\"babel-loader\":\"^8.0.0\",\"babel-plugin-import\":\"^1.1.1\",\"babel-plugin-inline-import-data-uri\":\"^1.0.1\",\"babel-plugin-istanbul\":\"^6.0.0\",\"case-sensitive-paths-webpack-plugin\":\"^2.1.2\",chalk:\"^4.1.0\",cheerio:\"^1.0.0-rc.2\",codecov:\"^3.0.0\",colorful:\"^2.1.0\",commander:\"^7.2.0\",\"compare-versions\":\"^3.3.0\",\"cross-env\":\"^7.0.0\",\"css-loader\":\"^5.0.0\",\"css-minimizer-webpack-plugin\":\"^3.0.0\",\"deep-assign\":\"^3.0.0\",\"docsearch.js\":\"^2.6.3\",\"enquire-js\":\"^0.2.1\",eslint:\"^7.25.0\",\"eslint-config-prettier\":\"^8.0.0\",\"eslint-plugin-html\":\"^6.0.0\",\"eslint-plugin-jest\":\"^24.3.6\",\"eslint-plugin-markdown\":\"^2.0.0-alpha.0\",\"eslint-plugin-prettier\":\"^3.1.4\",\"eslint-plugin-vue\":\"^7.1.0\",\"fetch-jsonp\":\"^1.1.3\",\"fs-extra\":\"^10.0.0\",glob:\"^7.1.2\",gulp:\"^4.0.1\",\"gulp-babel\":\"^8.0.0\",\"gulp-strip-code\":\"^0.1.4\",\"gulp-typescript\":\"^6.0.0-alpha.1\",\"html-webpack-plugin\":\"^5.3.1\",husky:\"^4.0.0\",\"ignore-emit-webpack-plugin\":\"^2.0.6\",jest:\"^26.0.0\",\"jest-environment-jsdom-fifteen\":\"^1.0.2\",\"jest-serializer-vue\":\"^2.0.0\",\"jest-transform-stub\":\"^2.0.0\",\"js-base64\":\"^3.0.0\",\"json-templater\":\"^1.2.0\",jsonp:\"^0.2.1\",less:\"^4.0.0\",\"less-loader\":\"^10.0.0\",\"less-plugin-npm-import\":\"^2.1.0\",\"less-vars-to-js\":\"^1.3.0\",\"lint-staged\":\"^11.0.0\",marked:\"0.3.18\",merge2:\"^1.2.1\",\"mini-css-extract-plugin\":\"^1.5.0\",minimist:\"^1.2.0\",mkdirp:\"^0.5.1\",mockdate:\"^2.0.2\",nprogress:\"^0.2.0\",\"object-assign\":\"^4.1.1\",postcss:\"^8.2.12\",\"postcss-loader\":\"^6.0.0\",prettier:\"^2.2.0\",\"pretty-quick\":\"^3.0.0\",prismjs:\"^1.20.0\",querystring:\"^0.2.0\",\"raw-loader\":\"^4.0.2\",reqwest:\"^2.0.5\",rimraf:\"^3.0.0\",\"rucksack-css\":\"^1.0.2\",\"selenium-server\":\"^3.0.1\",semver:\"^7.0.0\",\"style-loader\":\"^3.0.0\",stylelint:\"^13.0.0\",\"stylelint-config-prettier\":\"^8.0.0\",\"stylelint-config-rational-order\":\"^0.1.2\",\"stylelint-config-standard\":\"^22.0.0\",\"stylelint-declaration-block-no-ignored-properties\":\"^2.1.0\",\"stylelint-order\":\"^4.0.0\",\"terser-webpack-plugin\":\"^5.1.1\",through2:\"^3.0.0\",\"ts-jest\":\"^26.4.1\",\"ts-loader\":\"^9.1.0\",typescript:\"~4.3.5\",\"umi-mock-middleware\":\"^1.0.0\",\"umi-request\":\"^1.3.5\",\"url-loader\":\"^3.0.0\",vue:\"^3.1.0\",\"vue-antd-md-loader\":\"^1.2.1-beta.1\",\"vue-clipboard2\":\"0.3.1\",\"vue-draggable-resizable\":\"^2.1.0\",\"vue-eslint-parser\":\"^7.0.0\",\"vue-i18n\":\"^9.1.7\",\"vue-infinite-scroll\":\"^2.0.2\",\"vue-jest\":\"^5.0.0-alpha.3\",\"vue-loader\":\"^16.1.1\",\"vue-request\":\"^1.0.2\",\"vue-router\":\"^4.0.0\",\"vue-server-renderer\":\"^2.6.11\",\"vue-style-loader\":\"^4.1.2\",vuex:\"^4.0.0-beta.2\",webpack:\"^5.0.0\",\"webpack-bundle-analyzer\":\"^4.0.0\",\"webpack-cli\":\"^4.6.0\",\"webpack-dev-server\":\"^4.0.0\",\"webpack-merge\":\"^5.0.0\",webpackbar:\"^5.0.0-3\",\"xhr-mock\":\"^2.5.1\"},rRe={\"@ant-design/icons-vue\":\"^6.0.0\",\"@babel/runtime\":\"^7.10.5\",\"@simonwep/pickr\":\"~1.8.0\",\"array-tree-filter\":\"^2.1.0\",\"async-validator\":\"^3.3.0\",\"dom-align\":\"^1.12.1\",\"dom-scroll-into-view\":\"^2.0.0\",lodash:\"^4.17.21\",\"lodash-es\":\"^4.17.15\",moment:\"^2.27.0\",\"omit.js\":\"^2.0.0\",\"resize-observer-polyfill\":\"^1.5.1\",\"scroll-into-view-if-needed\":\"^2.2.25\",\"shallow-equal\":\"^1.0.0\",\"vue-types\":\"^3.0.0\",warning:\"^4.0.0\"},aRe=[\"site/*\",\"components/style.ts\",\"components/**/style/*\",\"*.vue\",\"*.md\",\"dist/*\",\"es/**/style/*\",\"lib/**/style/*\",\"*.less\"],oRe={tags:\"vetur/tags.json\",attributes:\"vetur/attributes.json\"};var iRe={name:B7e,version:V7e,title:z7e,description:H7e,keywords:j7e,main:K7e,module:W7e,unpkg:U7e,typings:Y7e,files:q7e,scripts:G7e,repository:X7e,license:Z7e,funding:J7e,bugs:Q7e,homepage:eRe,peerDependencies:tRe,devDependencies:nRe,dependencies:rRe,sideEffects:aRe,vetur:oRe,\"web-types\":\"vetur/web-types.json\"},lRe=iRe.version,sRe=lRe,uRe=function(t){return Object.keys(A_).forEach(function(n){var r=A_[n];r.install&&t.use(r)}),t.config.globalProperties.$message=j7,t.config.globalProperties.$notification=sR,t.config.globalProperties.$info=cr.info,t.config.globalProperties.$success=cr.success,t.config.globalProperties.$error=cr.error,t.config.globalProperties.$warning=cr.warning,t.config.globalProperties.$confirm=cr.confirm,t.config.globalProperties.$destroyAll=cr.destroyAll,t},cRe={version:sRe,install:uRe},dk={exports:{}},QR=function(t,n){return function(){for(var a=new Array(arguments.length),o=0;o<a.length;o++)a[o]=arguments[o];return t.apply(n,a)}},dRe=QR,bl=Object.prototype.toString;function fk(e){return Array.isArray(e)}function V1(e){return typeof e==\"undefined\"}function fRe(e){return e!==null&&!V1(e)&&e.constructor!==null&&!V1(e.constructor)&&typeof e.constructor.isBuffer==\"function\"&&e.constructor.isBuffer(e)}function e9(e){return bl.call(e)===\"[object ArrayBuffer]\"}function hRe(e){return bl.call(e)===\"[object FormData]\"}function pRe(e){var t;return typeof ArrayBuffer!=\"undefined\"&&ArrayBuffer.isView?t=ArrayBuffer.isView(e):t=e&&e.buffer&&e9(e.buffer),t}function vRe(e){return typeof e==\"string\"}function mRe(e){return typeof e==\"number\"}function t9(e){return e!==null&&typeof e==\"object\"}function tv(e){if(bl.call(e)!==\"[object Object]\")return!1;var t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}function gRe(e){return bl.call(e)===\"[object Date]\"}function yRe(e){return bl.call(e)===\"[object File]\"}function bRe(e){return bl.call(e)===\"[object Blob]\"}function n9(e){return bl.call(e)===\"[object Function]\"}function CRe(e){return t9(e)&&n9(e.pipe)}function wRe(e){return bl.call(e)===\"[object URLSearchParams]\"}function SRe(e){return e.trim?e.trim():e.replace(/^\\s+|\\s+$/g,\"\")}function kRe(){return typeof navigator!=\"undefined\"&&(navigator.product===\"ReactNative\"||navigator.product===\"NativeScript\"||navigator.product===\"NS\")?!1:typeof window!=\"undefined\"&&typeof document!=\"undefined\"}function hk(e,t){if(!(e===null||typeof e==\"undefined\"))if(typeof e!=\"object\"&&(e=[e]),fk(e))for(var n=0,r=e.length;n<r;n++)t.call(null,e[n],n,e);else for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.call(null,e[a],a,e)}function z1(){var e={};function t(a,o){tv(e[o])&&tv(a)?e[o]=z1(e[o],a):tv(a)?e[o]=z1({},a):fk(a)?e[o]=a.slice():e[o]=a}for(var n=0,r=arguments.length;n<r;n++)hk(arguments[n],t);return e}function $Re(e,t,n){return hk(t,function(a,o){n&&typeof a==\"function\"?e[o]=dRe(a,n):e[o]=a}),e}function ORe(e){return e.charCodeAt(0)===65279&&(e=e.slice(1)),e}var qr={isArray:fk,isArrayBuffer:e9,isBuffer:fRe,isFormData:hRe,isArrayBufferView:pRe,isString:vRe,isNumber:mRe,isObject:t9,isPlainObject:tv,isUndefined:V1,isDate:gRe,isFile:yRe,isBlob:bRe,isFunction:n9,isStream:CRe,isURLSearchParams:wRe,isStandardBrowserEnv:kRe,forEach:hk,merge:z1,extend:$Re,trim:SRe,stripBOM:ORe},nu=qr;function D_(e){return encodeURIComponent(e).replace(/%3A/gi,\":\").replace(/%24/g,\"$\").replace(/%2C/gi,\",\").replace(/%20/g,\"+\").replace(/%5B/gi,\"[\").replace(/%5D/gi,\"]\")}var r9=function(t,n,r){if(!n)return t;var a;if(r)a=r(n);else if(nu.isURLSearchParams(n))a=n.toString();else{var o=[];nu.forEach(n,function(s,c){s===null||typeof s==\"undefined\"||(nu.isArray(s)?c=c+\"[]\":s=[s],nu.forEach(s,function(f){nu.isDate(f)?f=f.toISOString():nu.isObject(f)&&(f=JSON.stringify(f)),o.push(D_(c)+\"=\"+D_(f))}))}),a=o.join(\"&\")}if(a){var i=t.indexOf(\"#\");i!==-1&&(t=t.slice(0,i)),t+=(t.indexOf(\"?\")===-1?\"?\":\"&\")+a}return t},PRe=qr;function zg(){this.handlers=[]}zg.prototype.use=function(t,n,r){return this.handlers.push({fulfilled:t,rejected:n,synchronous:r?r.synchronous:!1,runWhen:r?r.runWhen:null}),this.handlers.length-1};zg.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)};zg.prototype.forEach=function(t){PRe.forEach(this.handlers,function(r){r!==null&&t(r)})};var TRe=zg,xRe=qr,_Re=function(t,n){xRe.forEach(t,function(a,o){o!==n&&o.toUpperCase()===n.toUpperCase()&&(t[n]=a,delete t[o])})},a9=function(t,n,r,a,o){return t.config=n,r&&(t.code=r),t.request=a,t.response=o,t.isAxiosError=!0,t.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code,status:this.response&&this.response.status?this.response.status:null}},t},o9={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},ERe=a9,i9=function(t,n,r,a,o){var i=new Error(t);return ERe(i,n,r,a,o)},MRe=i9,IRe=function(t,n,r){var a=r.config.validateStatus;!r.status||!a||a(r.status)?t(r):n(MRe(\"Request failed with status code \"+r.status,r.config,null,r.request,r))},Qh=qr,NRe=Qh.isStandardBrowserEnv()?function(){return{write:function(n,r,a,o,i,l){var s=[];s.push(n+\"=\"+encodeURIComponent(r)),Qh.isNumber(a)&&s.push(\"expires=\"+new Date(a).toGMTString()),Qh.isString(o)&&s.push(\"path=\"+o),Qh.isString(i)&&s.push(\"domain=\"+i),l===!0&&s.push(\"secure\"),document.cookie=s.join(\"; \")},read:function(n){var r=document.cookie.match(new RegExp(\"(^|;\\\\s*)(\"+n+\")=([^;]*)\"));return r?decodeURIComponent(r[3]):null},remove:function(n){this.write(n,\"\",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}(),ARe=function(t){return/^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(t)},DRe=function(t,n){return n?t.replace(/\\/+$/,\"\")+\"/\"+n.replace(/^\\/+/,\"\"):t},RRe=ARe,LRe=DRe,FRe=function(t,n){return t&&!RRe(n)?LRe(t,n):n},Ab=qr,BRe=[\"age\",\"authorization\",\"content-length\",\"content-type\",\"etag\",\"expires\",\"from\",\"host\",\"if-modified-since\",\"if-unmodified-since\",\"last-modified\",\"location\",\"max-forwards\",\"proxy-authorization\",\"referer\",\"retry-after\",\"user-agent\"],VRe=function(t){var n={},r,a,o;return t&&Ab.forEach(t.split(`\n`),function(l){if(o=l.indexOf(\":\"),r=Ab.trim(l.substr(0,o)).toLowerCase(),a=Ab.trim(l.substr(o+1)),r){if(n[r]&&BRe.indexOf(r)>=0)return;r===\"set-cookie\"?n[r]=(n[r]?n[r]:[]).concat([a]):n[r]=n[r]?n[r]+\", \"+a:a}}),n},R_=qr,zRe=R_.isStandardBrowserEnv()?function(){var t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement(\"a\"),r;function a(o){var i=o;return t&&(n.setAttribute(\"href\",i),i=n.href),n.setAttribute(\"href\",i),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,\"\"):\"\",host:n.host,search:n.search?n.search.replace(/^\\?/,\"\"):\"\",hash:n.hash?n.hash.replace(/^#/,\"\"):\"\",hostname:n.hostname,port:n.port,pathname:n.pathname.charAt(0)===\"/\"?n.pathname:\"/\"+n.pathname}}return r=a(window.location.href),function(i){var l=R_.isString(i)?a(i):i;return l.protocol===r.protocol&&l.host===r.host}}():function(){return function(){return!0}}();function pk(e){this.message=e}pk.prototype.toString=function(){return\"Cancel\"+(this.message?\": \"+this.message:\"\")};pk.prototype.__CANCEL__=!0;var Hg=pk,ep=qr,HRe=IRe,jRe=NRe,KRe=r9,WRe=FRe,URe=VRe,YRe=zRe,Db=i9,qRe=o9,GRe=Hg,L_=function(t){return new Promise(function(r,a){var o=t.data,i=t.headers,l=t.responseType,s;function c(){t.cancelToken&&t.cancelToken.unsubscribe(s),t.signal&&t.signal.removeEventListener(\"abort\",s)}ep.isFormData(o)&&delete i[\"Content-Type\"];var d=new XMLHttpRequest;if(t.auth){var f=t.auth.username||\"\",p=t.auth.password?unescape(encodeURIComponent(t.auth.password)):\"\";i.Authorization=\"Basic \"+btoa(f+\":\"+p)}var v=WRe(t.baseURL,t.url);d.open(t.method.toUpperCase(),KRe(v,t.params,t.paramsSerializer),!0),d.timeout=t.timeout;function m(){if(!!d){var b=\"getAllResponseHeaders\"in d?URe(d.getAllResponseHeaders()):null,C=!l||l===\"text\"||l===\"json\"?d.responseText:d.response,S={data:C,status:d.status,statusText:d.statusText,headers:b,config:t,request:d};HRe(function(k){r(k),c()},function(k){a(k),c()},S),d=null}}if(\"onloadend\"in d?d.onloadend=m:d.onreadystatechange=function(){!d||d.readyState!==4||d.status===0&&!(d.responseURL&&d.responseURL.indexOf(\"file:\")===0)||setTimeout(m)},d.onabort=function(){!d||(a(Db(\"Request aborted\",t,\"ECONNABORTED\",d)),d=null)},d.onerror=function(){a(Db(\"Network Error\",t,null,d)),d=null},d.ontimeout=function(){var C=t.timeout?\"timeout of \"+t.timeout+\"ms exceeded\":\"timeout exceeded\",S=t.transitional||qRe;t.timeoutErrorMessage&&(C=t.timeoutErrorMessage),a(Db(C,t,S.clarifyTimeoutError?\"ETIMEDOUT\":\"ECONNABORTED\",d)),d=null},ep.isStandardBrowserEnv()){var y=(t.withCredentials||YRe(v))&&t.xsrfCookieName?jRe.read(t.xsrfCookieName):void 0;y&&(i[t.xsrfHeaderName]=y)}\"setRequestHeader\"in d&&ep.forEach(i,function(C,S){typeof o==\"undefined\"&&S.toLowerCase()===\"content-type\"?delete i[S]:d.setRequestHeader(S,C)}),ep.isUndefined(t.withCredentials)||(d.withCredentials=!!t.withCredentials),l&&l!==\"json\"&&(d.responseType=t.responseType),typeof t.onDownloadProgress==\"function\"&&d.addEventListener(\"progress\",t.onDownloadProgress),typeof t.onUploadProgress==\"function\"&&d.upload&&d.upload.addEventListener(\"progress\",t.onUploadProgress),(t.cancelToken||t.signal)&&(s=function(b){!d||(a(!b||b&&b.type?new GRe(\"canceled\"):b),d.abort(),d=null)},t.cancelToken&&t.cancelToken.subscribe(s),t.signal&&(t.signal.aborted?s():t.signal.addEventListener(\"abort\",s))),o||(o=null),d.send(o)})},vr=qr,F_=_Re,XRe=a9,ZRe=o9,JRe={\"Content-Type\":\"application/x-www-form-urlencoded\"};function B_(e,t){!vr.isUndefined(e)&&vr.isUndefined(e[\"Content-Type\"])&&(e[\"Content-Type\"]=t)}function QRe(){var e;return(typeof XMLHttpRequest!=\"undefined\"||typeof process!=\"undefined\"&&Object.prototype.toString.call(process)===\"[object process]\")&&(e=L_),e}function e9e(e,t,n){if(vr.isString(e))try{return(t||JSON.parse)(e),vr.trim(e)}catch(r){if(r.name!==\"SyntaxError\")throw r}return(n||JSON.stringify)(e)}var jg={transitional:ZRe,adapter:QRe(),transformRequest:[function(t,n){return F_(n,\"Accept\"),F_(n,\"Content-Type\"),vr.isFormData(t)||vr.isArrayBuffer(t)||vr.isBuffer(t)||vr.isStream(t)||vr.isFile(t)||vr.isBlob(t)?t:vr.isArrayBufferView(t)?t.buffer:vr.isURLSearchParams(t)?(B_(n,\"application/x-www-form-urlencoded;charset=utf-8\"),t.toString()):vr.isObject(t)||n&&n[\"Content-Type\"]===\"application/json\"?(B_(n,\"application/json\"),e9e(t)):t}],transformResponse:[function(t){var n=this.transitional||jg.transitional,r=n&&n.silentJSONParsing,a=n&&n.forcedJSONParsing,o=!r&&this.responseType===\"json\";if(o||a&&vr.isString(t)&&t.length)try{return JSON.parse(t)}catch(i){if(o)throw i.name===\"SyntaxError\"?XRe(i,this,\"E_JSON_PARSE\"):i}return t}],timeout:0,xsrfCookieName:\"XSRF-TOKEN\",xsrfHeaderName:\"X-XSRF-TOKEN\",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:\"application/json, text/plain, */*\"}}};vr.forEach([\"delete\",\"get\",\"head\"],function(t){jg.headers[t]={}});vr.forEach([\"post\",\"put\",\"patch\"],function(t){jg.headers[t]=vr.merge(JRe)});var vk=jg,t9e=qr,n9e=vk,r9e=function(t,n,r){var a=this||n9e;return t9e.forEach(r,function(i){t=i.call(a,t,n)}),t},l9=function(t){return!!(t&&t.__CANCEL__)},V_=qr,Rb=r9e,a9e=l9,o9e=vk,i9e=Hg;function Lb(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new i9e(\"canceled\")}var l9e=function(t){Lb(t),t.headers=t.headers||{},t.data=Rb.call(t,t.data,t.headers,t.transformRequest),t.headers=V_.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),V_.forEach([\"delete\",\"get\",\"head\",\"post\",\"put\",\"patch\",\"common\"],function(a){delete t.headers[a]});var n=t.adapter||o9e.adapter;return n(t).then(function(a){return Lb(t),a.data=Rb.call(t,a.data,a.headers,t.transformResponse),a},function(a){return a9e(a)||(Lb(t),a&&a.response&&(a.response.data=Rb.call(t,a.response.data,a.response.headers,t.transformResponse))),Promise.reject(a)})},Qr=qr,s9=function(t,n){n=n||{};var r={};function a(d,f){return Qr.isPlainObject(d)&&Qr.isPlainObject(f)?Qr.merge(d,f):Qr.isPlainObject(f)?Qr.merge({},f):Qr.isArray(f)?f.slice():f}function o(d){if(Qr.isUndefined(n[d])){if(!Qr.isUndefined(t[d]))return a(void 0,t[d])}else return a(t[d],n[d])}function i(d){if(!Qr.isUndefined(n[d]))return a(void 0,n[d])}function l(d){if(Qr.isUndefined(n[d])){if(!Qr.isUndefined(t[d]))return a(void 0,t[d])}else return a(void 0,n[d])}function s(d){if(d in n)return a(t[d],n[d]);if(d in t)return a(void 0,t[d])}var c={url:i,method:i,data:i,baseURL:l,transformRequest:l,transformResponse:l,paramsSerializer:l,timeout:l,timeoutMessage:l,withCredentials:l,adapter:l,responseType:l,xsrfCookieName:l,xsrfHeaderName:l,onUploadProgress:l,onDownloadProgress:l,decompress:l,maxContentLength:l,maxBodyLength:l,transport:l,httpAgent:l,httpsAgent:l,cancelToken:l,socketPath:l,responseEncoding:l,validateStatus:s};return Qr.forEach(Object.keys(t).concat(Object.keys(n)),function(f){var p=c[f]||o,v=p(f);Qr.isUndefined(v)&&p!==s||(r[f]=v)}),r},u9={version:\"0.26.1\"},s9e=u9.version,mk={};[\"object\",\"boolean\",\"number\",\"function\",\"string\",\"symbol\"].forEach(function(e,t){mk[e]=function(r){return typeof r===e||\"a\"+(t<1?\"n \":\" \")+e}});var z_={};mk.transitional=function(t,n,r){function a(o,i){return\"[Axios v\"+s9e+\"] Transitional option '\"+o+\"'\"+i+(r?\". \"+r:\"\")}return function(o,i,l){if(t===!1)throw new Error(a(i,\" has been removed\"+(n?\" in \"+n:\"\")));return n&&!z_[i]&&(z_[i]=!0,console.warn(a(i,\" has been deprecated since v\"+n+\" and will be removed in the near future\"))),t?t(o,i,l):!0}};function u9e(e,t,n){if(typeof e!=\"object\")throw new TypeError(\"options must be an object\");for(var r=Object.keys(e),a=r.length;a-- >0;){var o=r[a],i=t[o];if(i){var l=e[o],s=l===void 0||i(l,o,e);if(s!==!0)throw new TypeError(\"option \"+o+\" must be \"+s);continue}if(n!==!0)throw Error(\"Unknown option \"+o)}}var c9e={assertOptions:u9e,validators:mk},c9=qr,d9e=r9,H_=TRe,j_=l9e,Kg=s9,d9=c9e,ru=d9.validators;function qf(e){this.defaults=e,this.interceptors={request:new H_,response:new H_}}qf.prototype.request=function(t,n){typeof t==\"string\"?(n=n||{},n.url=t):n=t||{},n=Kg(this.defaults,n),n.method?n.method=n.method.toLowerCase():this.defaults.method?n.method=this.defaults.method.toLowerCase():n.method=\"get\";var r=n.transitional;r!==void 0&&d9.assertOptions(r,{silentJSONParsing:ru.transitional(ru.boolean),forcedJSONParsing:ru.transitional(ru.boolean),clarifyTimeoutError:ru.transitional(ru.boolean)},!1);var a=[],o=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen==\"function\"&&v.runWhen(n)===!1||(o=o&&v.synchronous,a.unshift(v.fulfilled,v.rejected))});var i=[];this.interceptors.response.forEach(function(v){i.push(v.fulfilled,v.rejected)});var l;if(!o){var s=[j_,void 0];for(Array.prototype.unshift.apply(s,a),s=s.concat(i),l=Promise.resolve(n);s.length;)l=l.then(s.shift(),s.shift());return l}for(var c=n;a.length;){var d=a.shift(),f=a.shift();try{c=d(c)}catch(p){f(p);break}}try{l=j_(c)}catch(p){return Promise.reject(p)}for(;i.length;)l=l.then(i.shift(),i.shift());return l};qf.prototype.getUri=function(t){return t=Kg(this.defaults,t),d9e(t.url,t.params,t.paramsSerializer).replace(/^\\?/,\"\")};c9.forEach([\"delete\",\"get\",\"head\",\"options\"],function(t){qf.prototype[t]=function(n,r){return this.request(Kg(r||{},{method:t,url:n,data:(r||{}).data}))}});c9.forEach([\"post\",\"put\",\"patch\"],function(t){qf.prototype[t]=function(n,r,a){return this.request(Kg(a||{},{method:t,url:n,data:r}))}});var f9e=qf,h9e=Hg;function fc(e){if(typeof e!=\"function\")throw new TypeError(\"executor must be a function.\");var t;this.promise=new Promise(function(a){t=a});var n=this;this.promise.then(function(r){if(!!n._listeners){var a,o=n._listeners.length;for(a=0;a<o;a++)n._listeners[a](r);n._listeners=null}}),this.promise.then=function(r){var a,o=new Promise(function(i){n.subscribe(i),a=i}).then(r);return o.cancel=function(){n.unsubscribe(a)},o},e(function(a){n.reason||(n.reason=new h9e(a),t(n.reason))})}fc.prototype.throwIfRequested=function(){if(this.reason)throw this.reason};fc.prototype.subscribe=function(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]};fc.prototype.unsubscribe=function(t){if(!!this._listeners){var n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}};fc.source=function(){var t,n=new fc(function(a){t=a});return{token:n,cancel:t}};var p9e=fc,v9e=function(t){return function(r){return t.apply(null,r)}},m9e=qr,g9e=function(t){return m9e.isObject(t)&&t.isAxiosError===!0},K_=qr,y9e=QR,nv=f9e,b9e=s9,C9e=vk;function f9(e){var t=new nv(e),n=y9e(nv.prototype.request,t);return K_.extend(n,nv.prototype,t),K_.extend(n,t),n.create=function(a){return f9(b9e(e,a))},n}var Ko=f9(C9e);Ko.Axios=nv;Ko.Cancel=Hg;Ko.CancelToken=p9e;Ko.isCancel=l9;Ko.VERSION=u9.version;Ko.all=function(t){return Promise.all(t)};Ko.spread=v9e;Ko.isAxiosError=g9e;dk.exports=Ko;dk.exports.default=Ko;var w9e=dk.exports,h9={exports:{}};/*!\n * \n * js-audio-recorder - js audio recorder plugin\n * \n * @version v0.5.7\n * @homepage https://github.com/2fps/recorder\n * @author 2fps <echoweb@126.com> (https://www.zhuyuntao.cn)\n * @license MIT\n *         \n */(function(e,t){(function(n,r){e.exports=r()})(vo,function(){return function(n){var r={};function a(o){if(r[o])return r[o].exports;var i=r[o]={i:o,l:!1,exports:{}};return n[o].call(i.exports,i,i.exports,a),i.l=!0,i.exports}return a.m=n,a.c=r,a.d=function(o,i,l){a.o(o,i)||Object.defineProperty(o,i,{enumerable:!0,get:l})},a.r=function(o){typeof Symbol!=\"undefined\"&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(o,\"__esModule\",{value:!0})},a.t=function(o,i){if(1&i&&(o=a(o)),8&i||4&i&&typeof o==\"object\"&&o&&o.__esModule)return o;var l=Object.create(null);if(a.r(l),Object.defineProperty(l,\"default\",{enumerable:!0,value:o}),2&i&&typeof o!=\"string\")for(var s in o)a.d(l,s,function(c){return o[c]}.bind(null,s));return l},a.n=function(o){var i=o&&o.__esModule?function(){return o.default}:function(){return o};return a.d(i,\"a\",i),i},a.o=function(o,i){return Object.prototype.hasOwnProperty.call(o,i)},a.p=\"\",a(a.s=0)}([function(n,r,a){Object.defineProperty(r,\"__esModule\",{value:!0});var o=function(){function l(s){s===void 0&&(s={}),this.isplaying=!1,this.lBuffer=[],this.rBuffer=[],this.tempPCM=[],this.inputSampleBits=16,this.playStamp=0,this.playTime=0,this.totalPlayTime=0,this.offset=0,this.fileSize=0;var c,d=new(window.AudioContext||window.webkitAudioContext);this.inputSampleRate=d.sampleRate,this.config={sampleBits:~[8,16].indexOf(s.sampleBits)?s.sampleBits:16,sampleRate:~[8e3,11025,16e3,22050,24e3,44100,48e3].indexOf(s.sampleRate)?s.sampleRate:this.inputSampleRate,numChannels:~[1,2].indexOf(s.numChannels)?s.numChannels:1,compiling:!!s.compiling||!1},this.outputSampleRate=this.config.sampleRate,this.oututSampleBits=this.config.sampleBits,this.littleEdian=(c=new ArrayBuffer(2),new DataView(c).setInt16(0,256,!0),new Int16Array(c)[0]===256),l.initUserMedia()}return l.prototype.initRecorder=function(){var s=this;this.context&&this.destroy(),this.context=new(window.AudioContext||window.webkitAudioContext),this.analyser=this.context.createAnalyser(),this.analyser.fftSize=2048;var c=this.context.createScriptProcessor||this.context.createJavaScriptNode;this.recorder=c.apply(this.context,[4096,this.config.numChannels,this.config.numChannels]),this.recorder.onaudioprocess=function(d){if(s.isrecording&&!s.ispause){var f,p=d.inputBuffer.getChannelData(0),v=null;if(s.lBuffer.push(new Float32Array(p)),s.size+=p.length,s.config.numChannels===2&&(v=d.inputBuffer.getChannelData(1),s.rBuffer.push(new Float32Array(v)),s.size+=v.length),s.config.compiling){var m=s.transformIntoPCM(p,v);s.tempPCM.push(m),s.fileSize=m.byteLength*s.tempPCM.length}else s.fileSize=Math.floor(s.size/Math.max(s.inputSampleRate/s.outputSampleRate,1))*(s.oututSampleBits/8);f=100*Math.max.apply(Math,p),s.duration+=4096/s.inputSampleRate,s.onprocess&&s.onprocess(s.duration),s.onprogress&&s.onprogress({duration:s.duration,fileSize:s.fileSize,vol:f,data:s.tempPCM})}}},l.prototype.start=function(){var s=this;if(!this.isrecording)return this.clear(),this.initRecorder(),this.isrecording=!0,navigator.mediaDevices.getUserMedia({audio:!0}).then(function(c){s.audioInput=s.context.createMediaStreamSource(c),s.stream=c}).then(function(){s.audioInput.connect(s.analyser),s.analyser.connect(s.recorder),s.recorder.connect(s.context.destination)})},l.prototype.pause=function(){this.isrecording&&!this.ispause&&(this.ispause=!0)},l.prototype.resume=function(){this.isrecording&&this.ispause&&(this.ispause=!1)},l.prototype.stop=function(){this.isrecording=!1,this.audioInput&&this.audioInput.disconnect(),this.recorder.disconnect()},l.prototype.play=function(){this.stop(),this.source&&this.source.stop(),this.isplaying=!0,this.playTime=0,this.playAudioData()},l.prototype.getPlayTime=function(){var s=0;return(s=this.isplaying?this.context.currentTime-this.playStamp+this.playTime:this.playTime)>=this.totalPlayTime&&(s=this.totalPlayTime),s},l.prototype.pausePlay=function(){!this.isrecording&&this.isplaying&&(this.source&&this.source.disconnect(),this.playTime+=this.context.currentTime-this.playStamp,this.isplaying=!1)},l.prototype.resumePlay=function(){this.isrecording||this.isplaying||this.playTime===0||(this.isplaying=!0,this.playAudioData())},l.prototype.stopPlay=function(){this.isrecording||(this.playTime=0,this.isplaying=!1,this.source&&this.source.stop())},l.prototype.getWholeData=function(){return this.tempPCM},l.prototype.getNextData=function(){var s=this.tempPCM.length,c=this.tempPCM.slice(this.offset);return this.offset=s,c},l.prototype.playAudioData=function(){var s=this;this.context.decodeAudioData(this.getWAV().buffer,function(c){s.source=s.context.createBufferSource(),s.source.buffer=c,s.totalPlayTime=s.source.buffer.duration,s.source.connect(s.analyser),s.analyser.connect(s.context.destination),s.source.start(0,s.playTime),s.playStamp=s.context.currentTime},function(c){l.throwError(c)})},l.prototype.getRecordAnalyseData=function(){if(this.ispause)return this.prevDomainData;var s=new Uint8Array(this.analyser.frequencyBinCount);return this.analyser.getByteTimeDomainData(s),this.prevDomainData=s},l.prototype.getPlayAnalyseData=function(){return this.getRecordAnalyseData()},l.prototype.getPCM=function(){if(this.tempPCM.length){var s=new ArrayBuffer(this.tempPCM.length*this.tempPCM[0].byteLength),c=new DataView(s),d=0;this.tempPCM.forEach(function(p){for(var v=0,m=p.byteLength;v<m;++v)c.setInt8(d,p.getInt8(v)),d++}),this.PCM=c,this.tempPCM=[]}if(this.PCM)return this.PCM;var f=this.flat();return f=l.compress(f,this.inputSampleRate,this.outputSampleRate),this.PCM=l.encodePCM(f,this.oututSampleBits,this.littleEdian)},l.prototype.getPCMBlob=function(){return this.stop(),new Blob([this.getPCM()])},l.prototype.downloadPCM=function(s){s===void 0&&(s=\"recorder\");var c=this.getPCMBlob();this.download(c,s,\"pcm\")},l.prototype.getWAV=function(){var s=this.getPCM();return l.encodeWAV(s,this.inputSampleRate,this.outputSampleRate,this.config.numChannels,this.oututSampleBits,this.littleEdian)},l.prototype.getWAVBlob=function(){return this.stop(),new Blob([this.getWAV()],{type:\"audio/wav\"})},l.prototype.downloadWAV=function(s){s===void 0&&(s=\"recorder\");var c=this.getWAVBlob();this.download(c,s,\"wav\")},l.prototype.transformIntoPCM=function(s,c){var d=new Float32Array(s),f=new Float32Array(c),p=l.compress({left:d,right:f},this.inputSampleRate,this.outputSampleRate);return l.encodePCM(p,this.oututSampleBits,this.littleEdian)},l.prototype.destroy=function(){return this.stopStream(),this.closeAudioContext()},l.prototype.stopStream=function(){this.stream&&this.stream.getTracks&&(this.stream.getTracks().forEach(function(s){return s.stop()}),this.stream=null)},l.prototype.closeAudioContext=function(){return this.context&&this.context.close&&this.context.state!==\"closed\"?this.context.close():new Promise(function(s){s()})},l.prototype.download=function(s,c,d){try{var f=document.createElement(\"a\");f.href=window.URL.createObjectURL(s),f.download=c+\".\"+d,f.click()}catch(p){l.throwError(p)}},l.prototype.clear=function(){this.lBuffer.length=0,this.rBuffer.length=0,this.size=0,this.fileSize=0,this.PCM=null,this.audioInput=null,this.duration=0,this.ispause=!1,this.isplaying=!1,this.playTime=0,this.totalPlayTime=0,this.source&&(this.source.stop(),this.source=null)},l.prototype.flat=function(){var s=null,c=new Float32Array(0);this.config.numChannels===1?s=new Float32Array(this.size):(s=new Float32Array(this.size/2),c=new Float32Array(this.size/2));for(var d=0,f=0;f<this.lBuffer.length;f++)s.set(this.lBuffer[f],d),d+=this.lBuffer[f].length;for(d=0,f=0;f<this.rBuffer.length;f++)c.set(this.rBuffer[f],d),d+=this.rBuffer[f].length;return{left:s,right:c}},l.playAudio=function(s){var c=document.createElement(\"audio\");c.src=window.URL.createObjectURL(s),c.play()},l.compress=function(s,c,d){for(var f=c/d,p=Math.max(f,1),v=s.left,m=s.right,y=Math.floor((v.length+m.length)/f),b=new Float32Array(y),C=0,S=0;C<y;){var w=Math.floor(S);b[C]=v[w],C++,m.length&&(b[C]=m[w],C++),S+=p}return b},l.encodePCM=function(s,c,d){d===void 0&&(d=!0);var f=0,p=s.length*(c/8),v=new ArrayBuffer(p),m=new DataView(v);if(c===8)for(var y=0;y<s.length;y++,f++){var b=(C=Math.max(-1,Math.min(1,s[y])))<0?128*C:127*C;b=+b+128,m.setInt8(f,b)}else for(y=0;y<s.length;y++,f+=2){var C=Math.max(-1,Math.min(1,s[y]));m.setInt16(f,C<0?32768*C:32767*C,d)}return m},l.encodeWAV=function(s,c,d,f,p,v){v===void 0&&(v=!0);var m=d>c?c:d,y=p,b=new ArrayBuffer(44+s.byteLength),C=new DataView(b),S=f,w=0;i(C,w,\"RIFF\"),w+=4,C.setUint32(w,36+s.byteLength,v),i(C,w+=4,\"WAVE\"),i(C,w+=4,\"fmt \"),w+=4,C.setUint32(w,16,v),w+=4,C.setUint16(w,1,v),w+=2,C.setUint16(w,S,v),w+=2,C.setUint32(w,m,v),w+=4,C.setUint32(w,S*m*(y/8),v),w+=4,C.setUint16(w,S*(y/8),v),w+=2,C.setUint16(w,y,v),i(C,w+=2,\"data\"),w+=4,C.setUint32(w,s.byteLength,v),w+=4;for(var k=0;k<s.byteLength;)C.setUint8(w,s.getUint8(k)),w++,k++;return C},l.throwError=function(s){throw new Error(s)},l.initUserMedia=function(){navigator.mediaDevices===void 0&&(navigator.mediaDevices={}),navigator.mediaDevices.getUserMedia===void 0&&(navigator.mediaDevices.getUserMedia=function(s){var c=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return c?new Promise(function(d,f){c.call(navigator,s,d,f)}):Promise.reject(new Error(\"\\u6D4F\\u89C8\\u5668\\u4E0D\\u652F\\u6301 getUserMedia !\"))})},l.getPermission=function(){return this.initUserMedia(),navigator.mediaDevices.getUserMedia({audio:!0}).then(function(s){s.getTracks().forEach(function(c){return c.stop()})})},l}();function i(l,s,c){for(var d=0;d<c.length;d++)l.setUint8(s+d,c.charCodeAt(d))}r.default=o}]).default})})(h9);var Gf=h9.exports,gk=(e,t)=>{const n=e.__vccOpts||e;for(const[r,a]of t)n[r]=a;return n};new(window.AudioContext||window.webkitAudioContext)({latencyHint:\"interactive\",sampleRate:24e3});new Gf({sampleBits:16,sampleRate:16e3,numChannels:1,compiling:!0});new AudioContext({latencyHint:\"interactive\",sampleRate:24e3});const tp=new Gf({sampleBits:16,sampleRate:16e3,numChannels:1,compiling:!0}),S9e={data(){return{onReco:!1,asrResult:\"\",wsUrl:\"127.0.0.1:8090/paddlespeech/asr/streaming\",ws:\"\"}},methods:{connectServer(){if(this.wsUrl){console.log(\"wsUrl\",this.wsUrl),this.ws=new WebSocket(\"ws://\"+this.wsUrl);var e=this;this.ws.addEventListener(\"message\",function(t){var n=JSON.parse(t.data);n.result&&n.result!=e.streamAsrResult&&(e.asrResult=n.result,e.$nextTick(()=>{}))}),this.ws.addEventListener(\"open\",function(){e.$message.success(\"Websocket\\u5EFA\\u7ACB\\u8FDE\\u63A5\\u6210\\u529F\")}),this.ws.addEventListener(\"error\",function(){e.$message.error(\"Websocket\\u8FDE\\u63A5\\u5931\\u8D25\")})}else{this.$message.error(\"\\u8BF7\\u8F93\\u5165URL\\u5730\\u5740\");return}},startRecorder(){if(!this.ws){this.$message.error(\"\\u8BF7\\u5148\\u8FDE\\u63A5\\u540E\\u7AEF\\u670D\\u52A1\");return}if(this.ws.readyState!=1){this.$message.error(\"WebSocket\\u672A\\u80FD\\u6210\\u529F\\u8FDE\\u63A5\\uFF0C\\u8BF7\\u68C0\\u67E5\\u670D\\u52A1\\u662F\\u5426\\u6B63\\u786E\");return}this.onReco=!0;var e=JSON.stringify({name:\"test.wav\",nbest:5,signal:\"start\"});this.ws.send(e),tp.start().then(()=>{setInterval(()=>{let t=tp.getNextData();!t.length||this.uploadChunk(t)},300)},t=>{console.log(\"\\u5F55\\u97F3\\u51FA\\u9519\")})},endRecorder(){tp.stop(),this.onReco=!1,tp.clear()},uploadChunk(e){e.forEach(t=>{this.ws.send(t)})}}},Wg=e=>(rC(\"data-v-1bbbdb64\"),e=e(),aC(),e),k9e={class:\"server_input\"},$9e=yt(\"ws://\"),O9e=yt(\"\\u8FDE\\u63A5\"),P9e={class:\"realTime\"},T9e={class:\"public_recognition_speech\"},x9e={key:0},_9e=Wg(()=>Z(\"div\",{class:\"endToEndIdentification_end_recorder_img_back\"},null,-1)),E9e=[_9e],M9e={key:1},I9e={class:\"endToEndIdentification_prompt\"},N9e={key:0},A9e={key:1},D9e=Wg(()=>Z(\"div\",{class:\"speech_text_prompt\"},\" \\u5B9E\\u65F6\\u5F97\\u5230\\u8BC6\\u522B\\u7ED3\\u679C \",-1)),R9e=Wg(()=>Z(\"div\",{class:\"public_recognition_point_to\"},null,-1)),L9e={class:\"public_recognition_result\"},F9e=Wg(()=>Z(\"div\",null,\"\\u8BC6\\u522B\\u7ED3\\u679C\",-1));function B9e(e,t,n,r,a,o){const i=we(\"el-input\"),l=we(\"el-button\");return R(),X(Fe,null,[Z(\"div\",k9e,[g(i,{class:\"serverAddress\",modelValue:a.wsUrl,\"onUpdate:modelValue\":t[0]||(t[0]=s=>a.wsUrl=s),placeholder:\"Please input\"},{prepend:re(()=>[$9e]),_:1},8,[\"modelValue\"]),g(l,{class:\"serverConnect\",type:\"primary\",onClick:t[1]||(t[1]=s=>o.connectServer())},{default:re(()=>[O9e]),_:1})]),Z(\"div\",P9e,[Z(\"div\",T9e,[a.onReco?(R(),X(\"div\",x9e,[Z(\"div\",{onClick:t[2]||(t[2]=s=>o.endRecorder()),class:\"endToEndIdentification_end_recorder_img\"},E9e)])):(R(),X(\"div\",M9e,[Z(\"div\",{onClick:t[3]||(t[3]=s=>o.startRecorder()),class:\"endToEndIdentification_start_recorder_img\"})])),Z(\"div\",I9e,[a.onReco?(R(),X(\"div\",N9e,\" \\u7ED3\\u675F\\u8BC6\\u522B \")):(R(),X(\"div\",A9e,\" \\u5F00\\u59CB\\u8BC6\\u522B \"))]),D9e]),R9e,Z(\"div\",L9e,[F9e,Z(\"div\",null,Me(a.asrResult),1)])])],64)}var V9e=gk(S9e,[[\"render\",B9e],[\"__scopeId\",\"data-v-1bbbdb64\"]]);new Gf({sampleBits:16,sampleRate:16e3,numChannels:1,compiling:!0});const z9e=e=>(rC(\"data-v-02a5e0f4\"),e=e(),aC(),e),H9e={class:\"speech_recognition\"},j9e={class:\"speech_recognition_tabs\"},K9e=z9e(()=>Z(\"div\",{class:\"frame\"},null,-1)),W9e={},U9e=Object.assign(W9e,{setup(e){return(t,n)=>{const r=we(\"el-tab-pane\"),a=we(\"el-tabs\");return R(),X(\"div\",H9e,[Z(\"div\",j9e,[K9e,g(a,{class:\"speech_recognition_mytabs\",type:\"border-card\"},{default:re(()=>[g(r,{label:\"\\u5B9E\\u65F6\\u8BED\\u97F3\\u8BC6\\u522B\",key:\"1\"},{default:re(()=>[g(V9e)]),_:1})]),_:1})])])}}});var Y9e=gk(U9e,[[\"__scopeId\",\"data-v-02a5e0f4\"]]);new(window.AudioContext||window.webkitAudioContext)({latencyHint:\"interactive\"});new Gf({sampleBits:16,sampleRate:16e3,numChannels:1,compiling:!0});new AudioContext({latencyHint:\"interactive\",sampleRate:16e3});new Gf({sampleBits:16,sampleRate:16e3,numChannels:1,compiling:!0});const q9e={className:\"experience\"},G9e={className:\"experience_wrapper\"},X9e=Z(\"div\",{className:\"experience_title\"},\" \\u529F\\u80FD\\u4F53\\u9A8C \",-1),Z9e=Z(\"div\",{className:\"experience_describe\"},\" \\u4F53\\u9A8C\\u524D\\uFF0C\\u8BF7\\u5141\\u8BB8\\u6D4F\\u89C8\\u5668\\u83B7\\u53D6\\u9EA6\\u514B\\u98CE\\u6743\\u9650 \",-1),J9e={className:\"experience_content\"},Q9e={setup(e){return(t,n)=>{const r=we(\"el-tab-pane\"),a=we(\"el-tabs\");return R(),X(\"div\",q9e,[Z(\"div\",G9e,[X9e,Z9e,Z(\"div\",J9e,[g(a,{className:\"experience_tabs\",type:\"border-card\"},{default:re(()=>[g(r,{label:\"\\u8BED\\u97F3\\u8BC6\\u522B\",key:\"3\"},{default:re(()=>[g(Y9e)]),_:1})]),_:1})])])])}}},eLe={name:\"Header\"},yk=e=>(rC(\"data-v-e2003d16\"),e=e(),aC(),e),tLe={className:\"speech_header\"},nLe=yk(()=>Z(\"div\",{className:\"speech_header_title\"},\" \\u98DE\\u6868-PaddleSpeech \",-1)),rLe=yk(()=>Z(\"div\",{className:\"speech_header_describe\"},\" PaddleSpeech \\u662F\\u57FA\\u4E8E\\u98DE\\u6868 PaddlePaddle \\u7684\\u8BED\\u97F3\\u65B9\\u5411\\u7684\\u5F00\\u6E90\\u6A21\\u578B\\u5E93\\uFF0C\\u7528\\u4E8E\\u8BED\\u97F3\\u548C\\u97F3\\u9891\\u4E2D\\u7684\\u5404\\u79CD\\u5173\\u952E\\u4EFB\\u52A1\\u7684\\u5F00\\u53D1\\uFF0C\\u6B22\\u8FCE\\u5927\\u5BB6Star\\u6536\\u85CF\\u9F13\\u52B1 \",-1)),aLe=yk(()=>Z(\"div\",{className:\"speech_header_link_box\"},[Z(\"a\",{href:\"https://github.com/PaddlePaddle/PaddleSpeech\",className:\"speech_header_link\",target:\"_blank\",rel:\"noreferrer\",key:\"{index}\"},\" \\u524D\\u5F80Github \")],-1)),oLe=[nLe,rLe,aLe];function iLe(e,t,n,r,a,o){return R(),X(\"div\",tLe,oLe)}var lLe=gk(eLe,[[\"render\",iLe],[\"__scopeId\",\"data-v-e2003d16\"]]);const sLe={class:\"app\"},uLe={setup(e){return(t,n)=>(R(),X(\"div\",sLe,[g(lLe),g(Q9e)]))}},bk=$m(uLe);bk.config.globalProperties.$http=w9e;bk.use(ibe).use(cRe);bk.mount(\"#app\")});export default cLe();\n\n</script>\n    <style type=\"text/css\">\n@charset \"UTF-8\";:root{--el-color-white:#ffffff;--el-color-black:#000000;--el-color-primary-rgb:64,158,255;--el-color-success-rgb:103,194,58;--el-color-warning-rgb:230,162,60;--el-color-danger-rgb:245,108,108;--el-color-error-rgb:245,108,108;--el-color-info-rgb:144,147,153;--el-font-size-extra-large:20px;--el-font-size-large:18px;--el-font-size-medium:16px;--el-font-size-base:14px;--el-font-size-small:13px;--el-font-size-extra-small:12px;--el-font-family:\"Helvetica Neue\",Helvetica,\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",\"\\5fae\\8f6f\\96c5\\9ed1\",Arial,sans-serif;--el-font-weight-primary:500;--el-font-line-height-primary:24px;--el-index-normal:1;--el-index-top:1000;--el-index-popper:2000;--el-border-radius-base:4px;--el-border-radius-small:2px;--el-border-radius-round:20px;--el-border-radius-circle:100%;--el-transition-duration:.3s;--el-transition-duration-fast:.2s;--el-transition-function-ease-in-out-bezier:cubic-bezier(.645, .045, .355, 1);--el-transition-function-fast-bezier:cubic-bezier(.23, 1, .32, 1);--el-transition-all:all var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier);--el-transition-fade:opacity var(--el-transition-duration) var(--el-transition-function-fast-bezier);--el-transition-md-fade:transform var(--el-transition-duration) var(--el-transition-function-fast-bezier),opacity var(--el-transition-duration) var(--el-transition-function-fast-bezier);--el-transition-fade-linear:opacity var(--el-transition-duration-fast) linear;--el-transition-border:border-color var(--el-transition-duration-fast) var(--el-transition-function-ease-in-out-bezier);--el-transition-box-shadow:box-shadow var(--el-transition-duration-fast) var(--el-transition-function-ease-in-out-bezier);--el-transition-color:color var(--el-transition-duration-fast) var(--el-transition-function-ease-in-out-bezier)}:root{color-scheme:light;--el-color-white:#ffffff;--el-color-black:#000000;--el-color-primary:#409eff;--el-color-primary-light-3:#79bbff;--el-color-primary-light-5:#a0cfff;--el-color-primary-light-7:#c6e2ff;--el-color-primary-light-8:#d9ecff;--el-color-primary-light-9:#ecf5ff;--el-color-primary-dark-2:#337ecc;--el-color-success:#67c23a;--el-color-success-light-3:#95d475;--el-color-success-light-5:#b3e19d;--el-color-success-light-7:#d1edc4;--el-color-success-light-8:#e1f3d8;--el-color-success-light-9:#f0f9eb;--el-color-success-dark-2:#529b2e;--el-color-warning:#e6a23c;--el-color-warning-light-3:#eebe77;--el-color-warning-light-5:#f3d19e;--el-color-warning-light-7:#f8e3c5;--el-color-warning-light-8:#faecd8;--el-color-warning-light-9:#fdf6ec;--el-color-warning-dark-2:#b88230;--el-color-danger:#f56c6c;--el-color-danger-light-3:#f89898;--el-color-danger-light-5:#fab6b6;--el-color-danger-light-7:#fcd3d3;--el-color-danger-light-8:#fde2e2;--el-color-danger-light-9:#fef0f0;--el-color-danger-dark-2:#c45656;--el-color-error:#f56c6c;--el-color-error-light-3:#f89898;--el-color-error-light-5:#fab6b6;--el-color-error-light-7:#fcd3d3;--el-color-error-light-8:#fde2e2;--el-color-error-light-9:#fef0f0;--el-color-error-dark-2:#c45656;--el-color-info:#909399;--el-color-info-light-3:#b1b3b8;--el-color-info-light-5:#c8c9cc;--el-color-info-light-7:#dedfe0;--el-color-info-light-8:#e9e9eb;--el-color-info-light-9:#f4f4f5;--el-color-info-dark-2:#73767a;--el-bg-color:#ffffff;--el-bg-color-page:#ffffff;--el-bg-color-overlay:#ffffff;--el-text-color-primary:#303133;--el-text-color-regular:#606266;--el-text-color-secondary:#909399;--el-text-color-placeholder:#a8abb2;--el-text-color-disabled:#c0c4cc;--el-border-color:#dcdfe6;--el-border-color-light:#e4e7ed;--el-border-color-lighter:#ebeef5;--el-border-color-extra-light:#f2f6fc;--el-border-color-dark:#d4d7de;--el-border-color-darker:#cdd0d6;--el-fill-color:#f0f2f5;--el-fill-color-light:#f5f7fa;--el-fill-color-lighter:#fafafa;--el-fill-color-extra-light:#fafcff;--el-fill-color-dark:#ebedf0;--el-fill-color-darker:#e6e8eb;--el-fill-color-blank:#ffffff;--el-box-shadow:0px 12px 32px 4px rgba(0, 0, 0, .04),0px 8px 20px rgba(0, 0, 0, .08);--el-box-shadow-light:0px 0px 12px rgba(0, 0, 0, .12);--el-box-shadow-lighter:0px 0px 6px rgba(0, 0, 0, .12);--el-box-shadow-dark:0px 16px 48px 16px rgba(0, 0, 0, .08),0px 12px 32px rgba(0, 0, 0, .12),0px 8px 16px -8px rgba(0, 0, 0, .16);--el-disabled-bg-color:var(--el-fill-color-light);--el-disabled-text-color:var(--el-text-color-placeholder);--el-disabled-border-color:var(--el-border-color-light);--el-overlay-color:rgba(0, 0, 0, .8);--el-overlay-color-light:rgba(0, 0, 0, .7);--el-overlay-color-lighter:rgba(0, 0, 0, .5);--el-mask-color:rgba(255, 255, 255, .9);--el-mask-color-extra-light:rgba(255, 255, 255, .3);--el-border-width:1px;--el-border-style:solid;--el-border-color-hover:var(--el-text-color-disabled);--el-border:var(--el-border-width) var(--el-border-style) var(--el-border-color);--el-svg-monochrome-grey:var(--el-border-color)}.fade-in-linear-enter-active,.fade-in-linear-leave-active{transition:var(--el-transition-fade-linear)}.fade-in-linear-enter-from,.fade-in-linear-leave-to{opacity:0}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{transition:var(--el-transition-fade-linear)}.el-fade-in-linear-enter-from,.el-fade-in-linear-leave-to{opacity:0}.el-fade-in-enter-active,.el-fade-in-leave-active{transition:all var(--el-transition-duration) cubic-bezier(.55,0,.1,1)}.el-fade-in-enter-from,.el-fade-in-leave-active{opacity:0}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{transition:all var(--el-transition-duration) cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter-from,.el-zoom-in-center-leave-active{opacity:0;transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;transform:scaleY(1);transition:var(--el-transition-md-fade);transform-origin:center top}.el-zoom-in-top-enter-active[data-popper-placement^=top],.el-zoom-in-top-leave-active[data-popper-placement^=top]{transform-origin:center bottom}.el-zoom-in-top-enter-from,.el-zoom-in-top-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;transform:scaleY(1);transition:var(--el-transition-md-fade);transform-origin:center bottom}.el-zoom-in-bottom-enter-from,.el-zoom-in-bottom-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;transform:scale(1);transition:var(--el-transition-md-fade);transform-origin:top left}.el-zoom-in-left-enter-from,.el-zoom-in-left-leave-active{opacity:0;transform:scale(.45)}.collapse-transition{transition:var(--el-transition-duration) height ease-in-out,var(--el-transition-duration) padding-top ease-in-out,var(--el-transition-duration) padding-bottom ease-in-out}.el-collapse-transition-enter-active,.el-collapse-transition-leave-active{transition:var(--el-transition-duration) max-height ease-in-out,var(--el-transition-duration) padding-top ease-in-out,var(--el-transition-duration) padding-bottom ease-in-out}.horizontal-collapse-transition{transition:var(--el-transition-duration) width ease-in-out,var(--el-transition-duration) padding-left ease-in-out,var(--el-transition-duration) padding-right ease-in-out}.el-list-enter-active,.el-list-leave-active{transition:all 1s}.el-list-enter-from,.el-list-leave-to{opacity:0;transform:translateY(-30px)}.el-list-leave-active{position:absolute!important}.el-opacity-transition{transition:opacity var(--el-transition-duration) cubic-bezier(.55,0,.1,1)}.el-icon-loading{animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.el-icon{--color:inherit;height:1em;width:1em;line-height:1em;display:inline-flex;justify-content:center;align-items:center;position:relative;fill:currentColor;color:var(--color);font-size:inherit}.el-icon.is-loading{animation:rotating 2s linear infinite}.el-icon svg{height:1em;width:1em}.el-affix--fixed{position:fixed}.el-alert{--el-alert-padding:8px 16px;--el-alert-border-radius-base:var(--el-border-radius-base);--el-alert-title-font-size:13px;--el-alert-description-font-size:12px;--el-alert-close-font-size:12px;--el-alert-close-customed-font-size:13px;--el-alert-icon-size:16px;--el-alert-icon-large-size:28px;width:100%;padding:var(--el-alert-padding);margin:0;box-sizing:border-box;border-radius:var(--el-alert-border-radius-base);position:relative;background-color:var(--el-color-white);overflow:hidden;opacity:1;display:flex;align-items:center;transition:opacity var(--el-transition-duration-fast)}.el-alert.is-light .el-alert__close-btn{color:var(--el-text-color-placeholder)}.el-alert.is-dark .el-alert__close-btn,.el-alert.is-dark .el-alert__description{color:var(--el-color-white)}.el-alert.is-center{justify-content:center}.el-alert--success{--el-alert-bg-color:var(--el-color-success-light-9)}.el-alert--success.is-light{background-color:var(--el-alert-bg-color);color:var(--el-color-success)}.el-alert--success.is-light .el-alert__description{color:var(--el-color-success)}.el-alert--success.is-dark{background-color:var(--el-color-success);color:var(--el-color-white)}.el-alert--info{--el-alert-bg-color:var(--el-color-info-light-9)}.el-alert--info.is-light{background-color:var(--el-alert-bg-color);color:var(--el-color-info)}.el-alert--info.is-light .el-alert__description{color:var(--el-color-info)}.el-alert--info.is-dark{background-color:var(--el-color-info);color:var(--el-color-white)}.el-alert--warning{--el-alert-bg-color:var(--el-color-warning-light-9)}.el-alert--warning.is-light{background-color:var(--el-alert-bg-color);color:var(--el-color-warning)}.el-alert--warning.is-light .el-alert__description{color:var(--el-color-warning)}.el-alert--warning.is-dark{background-color:var(--el-color-warning);color:var(--el-color-white)}.el-alert--error{--el-alert-bg-color:var(--el-color-error-light-9)}.el-alert--error.is-light{background-color:var(--el-alert-bg-color);color:var(--el-color-error)}.el-alert--error.is-light .el-alert__description{color:var(--el-color-error)}.el-alert--error.is-dark{background-color:var(--el-color-error);color:var(--el-color-white)}.el-alert__content{display:table-cell;padding:0 8px}.el-alert .el-alert__icon{font-size:var(--el-alert-icon-size);width:var(--el-alert-icon-size)}.el-alert .el-alert__icon.is-big{font-size:var(--el-alert-icon-large-size);width:var(--el-alert-icon-large-size)}.el-alert__title{font-size:var(--el-alert-title-font-size);line-height:18px;vertical-align:text-top}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:var(--el-alert-description-font-size);margin:5px 0 0}.el-alert .el-alert__close-btn{font-size:var(--el-alert-close-font-size);opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.el-alert .el-alert__close-btn.is-customed{font-style:normal;font-size:var(--el-alert-close-customed-font-size);top:9px}.el-alert-fade-enter-from,.el-alert-fade-leave-active{opacity:0}.el-aside{--el-aside-width:300px;overflow:auto;box-sizing:border-box;flex-shrink:0;width:var(--el-aside-width)}.el-autocomplete{position:relative;display:inline-block}.el-autocomplete__popper.el-popper[role=tooltip]{background:#fff;border:1px solid var(--el-border-color-light);box-shadow:var(--el-box-shadow-light)}.el-autocomplete__popper.el-popper[role=tooltip] .el-popper__arrow:before{border:1px solid var(--el-border-color-light)}.el-autocomplete__popper.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-autocomplete__popper.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-autocomplete__popper.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-autocomplete__popper.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-autocomplete-suggestion{border-radius:var(--el-border-radius-base);box-sizing:border-box}.el-autocomplete-suggestion__wrap{max-height:280px;padding:10px 0;box-sizing:border-box}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-autocomplete-suggestion li{padding:0 20px;margin:0;line-height:34px;cursor:pointer;color:var(--el-text-color-regular);font-size:var(--el-font-size-base);list-style:none;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li:hover,.el-autocomplete-suggestion li.highlighted{background-color:var(--el-fill-color-light)}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid var(--el-color-black)}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:var(--el-text-color-secondary)}.el-autocomplete-suggestion.is-loading li:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-autocomplete-suggestion.is-loading li:hover{background-color:var(--el-color-white)}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-avatar{--el-avatar-text-color:var(--el-color-white);--el-avatar-bg-color:var(--el-text-color-disabled);--el-avatar-text-size:14px;--el-avatar-icon-size:18px;--el-avatar-border-radius:var(--el-border-radius-base);--el-avatar-size-large:56px;--el-avatar-size-default:40px;--el-avatar-size-small:24px;--el-avatar-size:40px;display:inline-flex;justify-content:center;align-items:center;box-sizing:border-box;text-align:center;overflow:hidden;color:var(--el-avatar-text-color);background:var(--el-avatar-bg-color);width:var(--el-avatar-size);height:var(--el-avatar-size);font-size:var(--el-avatar-text-size)}.el-avatar>img{display:block;height:100%}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:var(--el-avatar-border-radius)}.el-avatar--icon{font-size:var(--el-avatar-icon-size)}.el-avatar--small{--el-avatar-size:24px}.el-avatar--large{--el-avatar-size:56px}.el-backtop{--el-backtop-bg-color:var(--el-bg-color-overlay);--el-backtop-text-color:var(--el-color-primary);--el-backtop-hover-bg-color:var(--el-border-color-extra-light);position:fixed;background-color:var(--el-backtop-bg-color);width:40px;height:40px;border-radius:50%;color:var(--el-backtop-text-color);display:flex;align-items:center;justify-content:center;font-size:20px;box-shadow:var(--el-box-shadow-lighter);cursor:pointer;z-index:5}.el-backtop:hover{background-color:var(--el-backtop-hover-bg-color)}.el-backtop__icon{font-size:20px}.el-badge{--el-badge-bg-color:var(--el-color-danger);--el-badge-radius:10px;--el-badge-font-size:12px;--el-badge-padding:6px;--el-badge-size:18px;position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:var(--el-badge-bg-color);border-radius:var(--el-badge-radius);color:var(--el-color-white);display:inline-block;font-size:var(--el-badge-font-size);height:var(--el-badge-size);line-height:var(--el-badge-size);padding:0 var(--el-badge-padding);text-align:center;white-space:nowrap;border:1px solid var(--el-color-white)}.el-badge__content.is-fixed{position:absolute;top:0;right:calc(1px + var(--el-badge-size)/ 2);transform:translateY(-50%) translate(100%)}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}.el-badge__content--primary{background-color:var(--el-color-primary)}.el-badge__content--success{background-color:var(--el-color-success)}.el-badge__content--warning{background-color:var(--el-color-warning)}.el-badge__content--info{background-color:var(--el-color-info)}.el-badge__content--danger{background-color:var(--el-color-danger)}.el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb:after,.el-breadcrumb:before{display:table;content:\"\"}.el-breadcrumb:after{clear:both}.el-breadcrumb__separator{margin:0 9px;font-weight:700;color:var(--el-text-color-placeholder)}.el-breadcrumb__separator.el-icon{margin:0 6px;font-weight:400}.el-breadcrumb__separator.el-icon svg{vertical-align:middle}.el-breadcrumb__item{float:left;display:flex;align-items:center}.el-breadcrumb__inner{color:var(--el-text-color-regular)}.el-breadcrumb__inner a,.el-breadcrumb__inner.is-link{font-weight:700;text-decoration:none;transition:var(--el-transition-color);color:var(--el-text-color-primary)}.el-breadcrumb__inner a:hover,.el-breadcrumb__inner.is-link:hover{color:var(--el-color-primary);cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{font-weight:400;color:var(--el-text-color-regular);cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group:after,.el-button-group:before{display:table;content:\"\"}.el-button-group:after{clear:both}.el-button-group>.el-button{float:left;position:relative}.el-button-group>.el-button+.el-button{margin-left:0}.el-button-group>.el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group>.el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group>.el-button:first-child:last-child{border-top-right-radius:var(--el-border-radius-base);border-bottom-right-radius:var(--el-border-radius-base);border-top-left-radius:var(--el-border-radius-base);border-bottom-left-radius:var(--el-border-radius-base)}.el-button-group>.el-button:first-child:last-child.is-round{border-radius:var(--el-border-radius-round)}.el-button-group>.el-button:first-child:last-child.is-circle{border-radius:50%}.el-button-group>.el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group>.el-button:not(:last-child){margin-right:-1px}.el-button-group>.el-button:active,.el-button-group>.el-button:focus,.el-button-group>.el-button:hover{z-index:1}.el-button-group>.el-button.is-active{z-index:1}.el-button-group>.el-dropdown>.el-button{border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--primary:first-child{border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--primary:last-child{border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:var(--el-button-divide-border-color);border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--success:first-child{border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--success:last-child{border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:var(--el-button-divide-border-color);border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--warning:first-child{border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--warning:last-child{border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:var(--el-button-divide-border-color);border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--danger:first-child{border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--danger:last-child{border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:var(--el-button-divide-border-color);border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--info:first-child{border-right-color:var(--el-button-divide-border-color)}.el-button-group .el-button--info:last-child{border-left-color:var(--el-button-divide-border-color)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:var(--el-button-divide-border-color);border-right-color:var(--el-button-divide-border-color)}.el-button{--el-button-font-weight:var(--el-font-weight-primary);--el-button-border-color:var(--el-border-color);--el-button-bg-color:var(--el-fill-color-blank);--el-button-text-color:var(--el-text-color-regular);--el-button-disabled-text-color:var(--el-disabled-text-color);--el-button-disabled-bg-color:var(--el-fill-color-blank);--el-button-disabled-border-color:var(--el-border-color-light);--el-button-divide-border-color:rgba(255, 255, 255, .5);--el-button-hover-text-color:var(--el-color-primary);--el-button-hover-bg-color:var(--el-color-primary-light-9);--el-button-hover-border-color:var(--el-color-primary-light-7);--el-button-active-text-color:var(--el-button-hover-text-color);--el-button-active-border-color:var(--el-color-primary);--el-button-active-bg-color:var(--el-button-hover-bg-color)}.el-button{display:inline-flex;justify-content:center;align-items:center;line-height:1;height:32px;white-space:nowrap;cursor:pointer;background-color:var(--el-button-bg-color);border:var(--el-border);border-color:var(--el-button-border-color);color:var(--el-button-text-color);-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;transition:.1s;font-weight:var(--el-button-font-weight);-webkit-user-select:none;user-select:none;vertical-align:middle;padding:8px 15px;font-size:var(--el-font-size-base);border-radius:var(--el-border-radius-base)}.el-button>span{display:inline-flex;align-items:center}.el-button+.el-button{margin-left:12px}.el-button.is-round{padding:8px 15px}.el-button:focus,.el-button:hover{color:var(--el-button-hover-text-color);border-color:var(--el-button-hover-border-color);background-color:var(--el-button-hover-bg-color);outline:0}.el-button:active{color:var(--el-button-active-text-color);border-color:var(--el-button-active-border-color);background-color:var(--el-button-active-bg-color);outline:0}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon]+span{margin-left:6px}.el-button [class*=el-icon] svg{vertical-align:bottom}.el-button.is-plain{--el-button-hover-text-color:var(--el-color-primary);--el-button-hover-bg-color:var(--el-fill-color-blank);--el-button-hover-border-color:var(--el-color-primary)}.el-button.is-active{color:var(--el-button-active-text-color);border-color:var(--el-button-active-border-color);background-color:var(--el-button-active-bg-color);outline:0}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:var(--el-button-disabled-text-color);cursor:not-allowed;background-image:none;background-color:var(--el-button-disabled-bg-color);border-color:var(--el-button-disabled-border-color)}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{z-index:1;pointer-events:none;content:\"\";position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:var(--el-mask-color-extra-light)}.el-button.is-round{border-radius:var(--el-border-radius-round)}.el-button.is-circle{border-radius:50%;padding:8px}.el-button__text--expand{letter-spacing:.3em;margin-right:-.3em}.el-button--primary{--el-button-text-color:var(--el-color-white);--el-button-bg-color:var(--el-color-primary);--el-button-border-color:var(--el-color-primary);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-primary-light-3);--el-button-hover-border-color:var(--el-color-primary-light-3);--el-button-active-bg-color:var(--el-color-primary-dark-2);--el-button-active-border-color:var(--el-color-primary-dark-2);--el-button-disabled-text-color:var(--el-color-white);--el-button-disabled-bg-color:var(--el-color-primary-light-5);--el-button-disabled-border-color:var(--el-color-primary-light-5)}.el-button--primary.is-plain{--el-button-text-color:var(--el-color-primary);--el-button-bg-color:var(--el-color-primary-light-9);--el-button-border-color:var(--el-color-primary-light-5);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-primary);--el-button-hover-border-color:var(--el-color-primary);--el-button-active-text-color:var(--el-color-white)}.el-button--primary.is-plain.is-disabled,.el-button--primary.is-plain.is-disabled:active,.el-button--primary.is-plain.is-disabled:focus,.el-button--primary.is-plain.is-disabled:hover{color:var(--el-color-primary-light-5);background-color:var(--el-color-primary-light-9);border-color:var(--el-color-primary-light-8)}.el-button--success{--el-button-text-color:var(--el-color-white);--el-button-bg-color:var(--el-color-success);--el-button-border-color:var(--el-color-success);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-success-light-3);--el-button-hover-border-color:var(--el-color-success-light-3);--el-button-active-bg-color:var(--el-color-success-dark-2);--el-button-active-border-color:var(--el-color-success-dark-2);--el-button-disabled-text-color:var(--el-color-white);--el-button-disabled-bg-color:var(--el-color-success-light-5);--el-button-disabled-border-color:var(--el-color-success-light-5)}.el-button--success.is-plain{--el-button-text-color:var(--el-color-success);--el-button-bg-color:var(--el-color-success-light-9);--el-button-border-color:var(--el-color-success-light-5);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-success);--el-button-hover-border-color:var(--el-color-success);--el-button-active-text-color:var(--el-color-white)}.el-button--success.is-plain.is-disabled,.el-button--success.is-plain.is-disabled:active,.el-button--success.is-plain.is-disabled:focus,.el-button--success.is-plain.is-disabled:hover{color:var(--el-color-success-light-5);background-color:var(--el-color-success-light-9);border-color:var(--el-color-success-light-8)}.el-button--warning{--el-button-text-color:var(--el-color-white);--el-button-bg-color:var(--el-color-warning);--el-button-border-color:var(--el-color-warning);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-warning-light-3);--el-button-hover-border-color:var(--el-color-warning-light-3);--el-button-active-bg-color:var(--el-color-warning-dark-2);--el-button-active-border-color:var(--el-color-warning-dark-2);--el-button-disabled-text-color:var(--el-color-white);--el-button-disabled-bg-color:var(--el-color-warning-light-5);--el-button-disabled-border-color:var(--el-color-warning-light-5)}.el-button--warning.is-plain{--el-button-text-color:var(--el-color-warning);--el-button-bg-color:var(--el-color-warning-light-9);--el-button-border-color:var(--el-color-warning-light-5);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-warning);--el-button-hover-border-color:var(--el-color-warning);--el-button-active-text-color:var(--el-color-white)}.el-button--warning.is-plain.is-disabled,.el-button--warning.is-plain.is-disabled:active,.el-button--warning.is-plain.is-disabled:focus,.el-button--warning.is-plain.is-disabled:hover{color:var(--el-color-warning-light-5);background-color:var(--el-color-warning-light-9);border-color:var(--el-color-warning-light-8)}.el-button--danger{--el-button-text-color:var(--el-color-white);--el-button-bg-color:var(--el-color-danger);--el-button-border-color:var(--el-color-danger);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-danger-light-3);--el-button-hover-border-color:var(--el-color-danger-light-3);--el-button-active-bg-color:var(--el-color-danger-dark-2);--el-button-active-border-color:var(--el-color-danger-dark-2);--el-button-disabled-text-color:var(--el-color-white);--el-button-disabled-bg-color:var(--el-color-danger-light-5);--el-button-disabled-border-color:var(--el-color-danger-light-5)}.el-button--danger.is-plain{--el-button-text-color:var(--el-color-danger);--el-button-bg-color:var(--el-color-danger-light-9);--el-button-border-color:var(--el-color-danger-light-5);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-danger);--el-button-hover-border-color:var(--el-color-danger);--el-button-active-text-color:var(--el-color-white)}.el-button--danger.is-plain.is-disabled,.el-button--danger.is-plain.is-disabled:active,.el-button--danger.is-plain.is-disabled:focus,.el-button--danger.is-plain.is-disabled:hover{color:var(--el-color-danger-light-5);background-color:var(--el-color-danger-light-9);border-color:var(--el-color-danger-light-8)}.el-button--info{--el-button-text-color:var(--el-color-white);--el-button-bg-color:var(--el-color-info);--el-button-border-color:var(--el-color-info);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-info-light-3);--el-button-hover-border-color:var(--el-color-info-light-3);--el-button-active-bg-color:var(--el-color-info-dark-2);--el-button-active-border-color:var(--el-color-info-dark-2);--el-button-disabled-text-color:var(--el-color-white);--el-button-disabled-bg-color:var(--el-color-info-light-5);--el-button-disabled-border-color:var(--el-color-info-light-5)}.el-button--info.is-plain{--el-button-text-color:var(--el-color-info);--el-button-bg-color:var(--el-color-info-light-9);--el-button-border-color:var(--el-color-info-light-5);--el-button-hover-text-color:var(--el-color-white);--el-button-hover-bg-color:var(--el-color-info);--el-button-hover-border-color:var(--el-color-info);--el-button-active-text-color:var(--el-color-white)}.el-button--info.is-plain.is-disabled,.el-button--info.is-plain.is-disabled:active,.el-button--info.is-plain.is-disabled:focus,.el-button--info.is-plain.is-disabled:hover{color:var(--el-color-info-light-5);background-color:var(--el-color-info-light-9);border-color:var(--el-color-info-light-8)}.el-button--large{--el-button-size:40px;height:var(--el-button-size);padding:12px 19px;font-size:var(--el-font-size-base);border-radius:var(--el-border-radius-base)}.el-button--large [class*=el-icon]+span{margin-left:8px}.el-button--large.is-round{padding:12px 19px}.el-button--large.is-circle{width:var(--el-button-size);padding:12px}.el-button--small{--el-button-size:24px;height:var(--el-button-size);padding:5px 11px;font-size:12px;border-radius:calc(var(--el-border-radius-base) - 1px)}.el-button--small [class*=el-icon]+span{margin-left:4px}.el-button--small.is-round{padding:5px 11px}.el-button--small.is-circle{width:var(--el-button-size);padding:5px}.el-button--text{border-color:transparent;color:var(--el-color-primary);background:0 0;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:var(--el-color-primary-light-3);border-color:transparent;background-color:transparent}.el-button--text:active{color:var(--el-color-primary-dark-2);border-color:transparent;background-color:transparent}.el-button--text.is-disabled,.el-button--text.is-disabled:focus,.el-button--text.is-disabled:hover{border-color:transparent}.el-calendar{--el-calendar-border:var(--el-table-border, 1px solid var(--el-border-color-lighter));--el-calendar-header-border-bottom:var(--el-calendar-border);--el-calendar-selected-bg-color:var(--el-color-primary-light-9);--el-calendar-cell-width:85px;background-color:var(--el-fill-color-blank)}.el-calendar__header{display:flex;justify-content:space-between;padding:12px 20px;border-bottom:var(--el-calendar-header-border-bottom)}.el-calendar__title{color:var(--el-text-color);align-self:center}.el-calendar__body{padding:12px 20px 35px}.el-calendar-table{table-layout:fixed;width:100%}.el-calendar-table thead th{padding:12px 0;color:var(--el-text-color-regular);font-weight:400}.el-calendar-table:not(.is-range) td.next,.el-calendar-table:not(.is-range) td.prev{color:var(--el-text-color-placeholder)}.el-calendar-table td{border-bottom:var(--el-calendar-border);border-right:var(--el-calendar-border);vertical-align:top;transition:background-color var(--el-transition-duration-fast) ease}.el-calendar-table td.is-selected{background-color:var(--el-calendar-selected-bg-color)}.el-calendar-table td.is-today{color:var(--el-color-primary)}.el-calendar-table tr:first-child td{border-top:var(--el-calendar-border)}.el-calendar-table tr td:first-child{border-left:var(--el-calendar-border)}.el-calendar-table tr.el-calendar-table__row--hide-border td{border-top:none}.el-calendar-table .el-calendar-day{box-sizing:border-box;padding:8px;height:var(--el-calendar-cell-width)}.el-calendar-table .el-calendar-day:hover{cursor:pointer;background-color:var(--el-calendar-selected-bg-color)}.el-card{--el-card-border-color:var(--el-border-color-light);--el-card-border-radius:4px;--el-card-padding:20px;--el-card-bg-color:var(--el-fill-color-blank)}.el-card{border-radius:var(--el-card-border-radius);border:1px solid var(--el-card-border-color);background-color:var(--el-card-bg-color);overflow:hidden;color:var(--el-text-color-primary);transition:var(--el-transition-duration)}.el-card.is-always-shadow{box-shadow:var(--el-box-shadow-light)}.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{box-shadow:var(--el-box-shadow-light)}.el-card__header{padding:calc(var(--el-card-padding) - 2px) var(--el-card-padding);border-bottom:1px solid var(--el-card-border-color);box-sizing:border-box}.el-card__body{padding:var(--el-card-padding)}.el-carousel__item{position:absolute;top:0;left:0;width:100%;height:100%;display:inline-block;overflow:hidden;z-index:calc(var(--el-index-normal) - 1)}.el-carousel__item.is-active{z-index:calc(var(--el-index-normal) - 1)}.el-carousel__item.is-animating{transition:transform .4s ease-in-out}.el-carousel__item--card{width:50%;transition:transform .4s ease-in-out}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:var(--el-index-normal)}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:calc(var(--el-index-normal) + 1)}.el-carousel__mask{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.24;transition:var(--el-transition-duration-fast)}.el-carousel{--el-carousel-arrow-font-size:12px;--el-carousel-arrow-size:36px;--el-carousel-arrow-background:rgba(31, 45, 61, .11);--el-carousel-arrow-hover-background:rgba(31, 45, 61, .23);--el-carousel-indicator-width:30px;--el-carousel-indicator-height:2px;--el-carousel-indicator-padding-horizontal:4px;--el-carousel-indicator-padding-vertical:12px;--el-carousel-indicator-out-color:var(--el-border-color-hover);position:relative}.el-carousel--horizontal{overflow-x:hidden}.el-carousel--vertical{overflow-y:hidden}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;outline:0;padding:0;margin:0;height:var(--el-carousel-arrow-size);width:var(--el-carousel-arrow-size);cursor:pointer;transition:var(--el-transition-duration);border-radius:50%;background-color:var(--el-carousel-arrow-background);color:#fff;position:absolute;top:50%;z-index:10;transform:translateY(-50%);text-align:center;font-size:var(--el-carousel-arrow-font-size);display:inline-flex;justify-content:center;align-items:center}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:var(--el-carousel-arrow-hover-background)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{position:absolute;list-style:none;margin:0;padding:0;z-index:calc(var(--el-index-normal) + 1)}.el-carousel__indicators--horizontal{bottom:0;left:50%;transform:translate(-50%)}.el-carousel__indicators--vertical{right:0;top:50%;transform:translateY(-50%)}.el-carousel__indicators--outside{bottom:calc(var(--el-carousel-indicator-height) + var(--el-carousel-indicator-padding-vertical) * 2);text-align:center;position:static;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:var(--el-carousel-indicator-out-color);opacity:.24}.el-carousel__indicators--labels{left:0;right:0;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{background-color:transparent;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator--horizontal{display:inline-block;padding:var(--el-carousel-indicator-padding-vertical) var(--el-carousel-indicator-padding-horizontal)}.el-carousel__indicator--vertical{padding:var(--el-carousel-indicator-padding-horizontal) var(--el-carousel-indicator-padding-vertical)}.el-carousel__indicator--vertical .el-carousel__button{width:var(--el-carousel-indicator-height);height:calc(var(--el-carousel-indicator-width)/ 2)}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:var(--el-carousel-indicator-width);height:var(--el-carousel-indicator-height);background-color:#fff;border:none;outline:0;padding:0;margin:0;cursor:pointer;transition:var(--el-transition-duration)}.carousel-arrow-left-enter-from,.carousel-arrow-left-leave-active{transform:translateY(-50%) translate(-10px);opacity:0}.carousel-arrow-right-enter-from,.carousel-arrow-right-leave-active{transform:translateY(-50%) translate(10px);opacity:0}.el-cascader-panel{--el-cascader-menu-text-color:var(--el-text-color-regular);--el-cascader-menu-selected-text-color:var(--el-color-primary);--el-cascader-menu-fill:var(--el-bg-color-overlay);--el-cascader-menu-font-size:var(--el-font-size-base);--el-cascader-menu-radius:var(--el-border-radius-base);--el-cascader-menu-border:solid 1px var(--el-border-color-light);--el-cascader-menu-shadow:var(--el-box-shadow-light);--el-cascader-node-background-hover:var(--el-fill-color-light);--el-cascader-node-color-disabled:var(--el-text-color-placeholder);--el-cascader-color-empty:var(--el-text-color-placeholder);--el-cascader-tag-background:var(--el-fill-color)}.el-cascader-panel{display:flex;border-radius:var(--el-cascader-menu-radius);font-size:var(--el-cascader-menu-font-size)}.el-cascader-panel.is-bordered{border:var(--el-cascader-menu-border);border-radius:var(--el-cascader-menu-radius)}.el-cascader-menu{min-width:180px;box-sizing:border-box;color:var(--el-cascader-menu-text-color);border-right:var(--el-cascader-menu-border)}.el-cascader-menu:last-child{border-right:none}.el-cascader-menu:last-child .el-cascader-node{padding-right:20px}.el-cascader-menu__wrap.el-scrollbar__wrap{height:204px}.el-cascader-menu__list{position:relative;min-height:100%;margin:0;padding:6px 0;list-style:none;box-sizing:border-box}.el-cascader-menu__hover-zone{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.el-cascader-menu__empty-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:center;color:var(--el-cascader-color-empty)}.el-cascader-menu__empty-text .is-loading{margin-right:2px}.el-cascader-node{position:relative;display:flex;align-items:center;padding:0 30px 0 20px;height:34px;line-height:34px;outline:0}.el-cascader-node.is-selectable.in-active-path{color:var(--el-cascader-menu-text-color)}.el-cascader-node.in-active-path,.el-cascader-node.is-active,.el-cascader-node.is-selectable.in-checked-path{color:var(--el-cascader-menu-selected-text-color);font-weight:700}.el-cascader-node:not(.is-disabled){cursor:pointer}.el-cascader-node:not(.is-disabled):focus,.el-cascader-node:not(.is-disabled):hover{background:var(--el-cascader-node-background-hover)}.el-cascader-node.is-disabled{color:var(--el-cascader-node-color-disabled);cursor:not-allowed}.el-cascader-node__prefix{position:absolute;left:10px}.el-cascader-node__postfix{position:absolute;right:10px}.el-cascader-node__label{flex:1;text-align:left;padding:0 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-cascader-node>.el-radio{margin-right:0}.el-cascader-node>.el-radio .el-radio__label{padding-left:0}.el-cascader{--el-cascader-menu-text-color:var(--el-text-color-regular);--el-cascader-menu-selected-text-color:var(--el-color-primary);--el-cascader-menu-fill:var(--el-bg-color-overlay);--el-cascader-menu-font-size:var(--el-font-size-base);--el-cascader-menu-radius:var(--el-border-radius-base);--el-cascader-menu-border:solid 1px var(--el-border-color-light);--el-cascader-menu-shadow:var(--el-box-shadow-light);--el-cascader-node-background-hover:var(--el-fill-color-light);--el-cascader-node-color-disabled:var(--el-text-color-placeholder);--el-cascader-color-empty:var(--el-text-color-placeholder);--el-cascader-tag-background:var(--el-fill-color);display:inline-block;position:relative;font-size:var(--el-font-size-base);line-height:32px;outline:0}.el-cascader:not(.is-disabled):hover .el-input__inner{cursor:pointer;box-shadow:0 0 0 1px var(--el-input-hover-border-color) inset}.el-cascader .el-input{cursor:pointer}.el-cascader .el-input .el-input__inner{text-overflow:ellipsis}.el-cascader .el-input .el-input__inner:focus{box-shadow:0 0 0 1px var(--el-input-focus-border-color,var(--el-color-primary)) inset}.el-cascader .el-input .el-input__suffix-inner .el-icon{height:calc(100% - 2px)}.el-cascader .el-input .el-input__suffix-inner .el-icon svg{vertical-align:middle}.el-cascader .el-input .icon-arrow-down{transition:transform var(--el-transition-duration);font-size:14px}.el-cascader .el-input .icon-arrow-down.is-reverse{transform:rotate(180deg)}.el-cascader .el-input .icon-circle-close:hover{color:var(--el-input-clear-hover-color,var(--el-text-color-secondary))}.el-cascader .el-input.is-focus .el-input__inner{box-shadow:0 0 0 1px var(--el-input-focus-border-color,var(--el-color-primary)) inset}.el-cascader--large{font-size:14px;line-height:40px}.el-cascader--small{font-size:12px;line-height:24px}.el-cascader.is-disabled .el-cascader__label{z-index:calc(var(--el-index-normal) + 1);color:var(--el-disabled-text-color)}.el-cascader__dropdown{--el-cascader-menu-text-color:var(--el-text-color-regular);--el-cascader-menu-selected-text-color:var(--el-color-primary);--el-cascader-menu-fill:var(--el-bg-color-overlay);--el-cascader-menu-font-size:var(--el-font-size-base);--el-cascader-menu-radius:var(--el-border-radius-base);--el-cascader-menu-border:solid 1px var(--el-border-color-light);--el-cascader-menu-shadow:var(--el-box-shadow-light);--el-cascader-node-background-hover:var(--el-fill-color-light);--el-cascader-node-color-disabled:var(--el-text-color-placeholder);--el-cascader-color-empty:var(--el-text-color-placeholder);--el-cascader-tag-background:var(--el-fill-color)}.el-cascader__dropdown{font-size:var(--el-cascader-menu-font-size);border-radius:var(--el-cascader-menu-radius)}.el-cascader__dropdown.el-popper[role=tooltip]{background:var(--el-cascader-menu-fill);border:var(--el-cascader-menu-border);box-shadow:var(--el-cascader-menu-shadow)}.el-cascader__dropdown.el-popper[role=tooltip] .el-popper__arrow:before{border:var(--el-cascader-menu-border)}.el-cascader__dropdown.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-cascader__dropdown.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-cascader__dropdown.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-cascader__dropdown.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-cascader__dropdown.el-popper{box-shadow:var(--el-cascader-menu-shadow)}.el-cascader__tags{position:absolute;left:0;right:30px;top:50%;transform:translateY(-50%);display:flex;flex-wrap:wrap;line-height:normal;text-align:left;box-sizing:border-box}.el-cascader__tags .el-tag{display:inline-flex;align-items:center;max-width:100%;margin:2px 0 2px 6px;text-overflow:ellipsis;background:var(--el-cascader-tag-background)}.el-cascader__tags .el-tag:not(.is-hit){border-color:transparent}.el-cascader__tags .el-tag>span{flex:1;overflow:hidden;text-overflow:ellipsis}.el-cascader__tags .el-tag .el-icon-close{flex:none;background-color:var(--el-text-color-placeholder);color:var(--el-color-white)}.el-cascader__tags .el-tag .el-icon-close:hover{background-color:var(--el-text-color-secondary)}.el-cascader__collapse-tags{white-space:normal;z-index:var(--el-index-normal);display:flex;align-items:center;flex-wrap:wrap}.el-cascader__collapse-tag{line-height:inherit;height:inherit;display:flex}.el-cascader__suggestion-panel{border-radius:var(--el-cascader-menu-radius)}.el-cascader__suggestion-list{max-height:204px;margin:0;padding:6px 0;font-size:var(--el-font-size-base);color:var(--el-cascader-menu-text-color);text-align:center}.el-cascader__suggestion-item{display:flex;justify-content:space-between;align-items:center;height:34px;padding:0 15px;text-align:left;outline:0;cursor:pointer}.el-cascader__suggestion-item:focus,.el-cascader__suggestion-item:hover{background:var(--el-cascader-node-background-hover)}.el-cascader__suggestion-item.is-checked{color:var(--el-cascader-menu-selected-text-color);font-weight:700}.el-cascader__suggestion-item>span{margin-right:10px}.el-cascader__empty-text{margin:10px 0;color:var(--el-cascader-color-empty)}.el-cascader__search-input{flex:1;height:24px;min-width:60px;margin:2px 0 2px 11px;padding:0;color:var(--el-cascader-menu-text-color);border:none;outline:0;box-sizing:border-box}.el-cascader__search-input::placeholder{color:var(--el-text-color-placeholder)}.el-check-tag{background-color:var(--el-color-info-light-9);border-radius:var(--el-border-radius-base);color:var(--el-color-info);cursor:pointer;display:inline-block;font-size:var(--el-font-size-base);line-height:var(--el-font-size-base);padding:7px 15px;transition:var(--el-transition-all);font-weight:700}.el-check-tag:hover{background-color:var(--el-color-info-light-7)}.el-check-tag.is-checked{background-color:var(--el-color-primary-light-8);color:var(--el-color-primary-light-1)}.el-check-tag.is-checked:hover{background-color:var(--el-color-primary-light-7)}.el-checkbox-button{--el-checkbox-button-checked-bg-color:var(--el-color-primary);--el-checkbox-button-checked-text-color:var(--el-color-white);--el-checkbox-button-checked-border-color:var(--el-color-primary)}.el-checkbox-button{position:relative;display:inline-block}.el-checkbox-button__inner{display:inline-block;line-height:1;font-weight:var(--el-checkbox-font-weight);white-space:nowrap;vertical-align:middle;cursor:pointer;background:var(--el-button-bg-color,var(--el-fill-color-blank));border:var(--el-border);border-left:0;color:var(--el-button-text-color,var(--el-text-color-regular));-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;position:relative;transition:var(--el-transition-all);-webkit-user-select:none;user-select:none;padding:8px 15px;font-size:var(--el-font-size-base);border-radius:0}.el-checkbox-button__inner.is-round{padding:8px 15px}.el-checkbox-button__inner:hover{color:var(--el-color-primary)}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;z-index:-1}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:var(--el-checkbox-button-checked-text-color);background-color:var(--el-checkbox-button-checked-bg-color);border-color:var(--el-checkbox-button-checked-border-color);box-shadow:-1px 0 0 0 var(--el-color-primary-light-7)}.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner{border-left-color:var(--el-checkbox-button-checked-border-color)}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:var(--el-disabled-text-color);cursor:not-allowed;background-image:none;background-color:var(--el-button-disabled-bg-color,var(--el-fill-color-blank));border-color:var(--el-button-disabled-border-color,var(--el-border-color-light));box-shadow:none}.el-checkbox-button.is-disabled:first-child .el-checkbox-button__inner{border-left-color:var(--el-button-disabled-border-color,var(--el-border-color-light))}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:var(--el-border);border-radius:var(--el-border-radius-base) 0 0 var(--el-border-radius-base);box-shadow:none!important}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:var(--el-checkbox-button-checked-border-color)}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 var(--el-border-radius-base) var(--el-border-radius-base) 0}.el-checkbox-button--large .el-checkbox-button__inner{padding:12px 19px;font-size:var(--el-font-size-base);border-radius:0}.el-checkbox-button--large .el-checkbox-button__inner.is-round{padding:12px 19px}.el-checkbox-button--small .el-checkbox-button__inner{padding:5px 11px;font-size:12px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:5px 11px}.el-checkbox-group{font-size:0;line-height:0}.el-checkbox{--el-checkbox-font-size:14px;--el-checkbox-font-weight:var(--el-font-weight-primary);--el-checkbox-text-color:var(--el-text-color-regular);--el-checkbox-input-height:14px;--el-checkbox-input-width:14px;--el-checkbox-border-radius:var(--el-border-radius-small);--el-checkbox-bg-color:var(--el-fill-color-blank);--el-checkbox-input-border:var(--el-border);--el-checkbox-disabled-border-color:var(--el-border-color);--el-checkbox-disabled-input-fill:var(--el-fill-color-light);--el-checkbox-disabled-icon-color:var(--el-text-color-placeholder);--el-checkbox-disabled-checked-input-fill:var(--el-border-color-extra-light);--el-checkbox-disabled-checked-input-border-color:var(--el-border-color);--el-checkbox-disabled-checked-icon-color:var(--el-text-color-placeholder);--el-checkbox-checked-text-color:var(--el-color-primary);--el-checkbox-checked-input-border-color:var(--el-color-primary);--el-checkbox-checked-bg-color:var(--el-color-primary);--el-checkbox-checked-icon-color:var(--el-color-white);--el-checkbox-input-border-color-hover:var(--el-color-primary)}.el-checkbox{color:var(--el-checkbox-text-color);font-weight:var(--el-checkbox-font-weight);font-size:var(--el-font-size-base);position:relative;cursor:pointer;display:inline-flex;align-items:center;white-space:nowrap;-webkit-user-select:none;user-select:none;margin-right:30px;height:32px}.el-checkbox.is-bordered{padding:0 15px 0 9px;border-radius:var(--el-border-radius-base);border:var(--el-border);box-sizing:border-box}.el-checkbox.is-bordered.is-checked{border-color:var(--el-color-primary)}.el-checkbox.is-bordered.is-disabled{border-color:var(--el-border-color-lighter);cursor:not-allowed}.el-checkbox.is-bordered.el-checkbox--large{padding:0 19px 0 11px;border-radius:var(--el-border-radius-base)}.el-checkbox.is-bordered.el-checkbox--large .el-checkbox__label{font-size:var(--el-font-size-base)}.el-checkbox.is-bordered.el-checkbox--large .el-checkbox__inner{height:14px;width:14px}.el-checkbox.is-bordered.el-checkbox--small{padding:0 11px 0 7px;border-radius:calc(var(--el-border-radius-base) - 1px)}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{font-size:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner:after{height:6px;width:2px}.el-checkbox__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-flex;position:relative}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:var(--el-checkbox-disabled-input-fill);border-color:var(--el-checkbox-disabled-border-color);cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner:after{cursor:not-allowed;border-color:var(--el-checkbox-disabled-icon-color)}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:var(--el-checkbox-disabled-checked-input-fill);border-color:var(--el-checkbox-disabled-checked-input-border-color)}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner:after{border-color:var(--el-checkbox-disabled-checked-icon-color)}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:var(--el-checkbox-disabled-checked-input-fill);border-color:var(--el-checkbox-disabled-checked-input-border-color)}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner:before{background-color:var(--el-checkbox-disabled-checked-icon-color);border-color:var(--el-checkbox-disabled-checked-icon-color)}.el-checkbox__input.is-disabled+span.el-checkbox__label{color:var(--el-disabled-text-color);cursor:not-allowed}.el-checkbox__input.is-checked .el-checkbox__inner{background-color:var(--el-checkbox-checked-bg-color);border-color:var(--el-checkbox-checked-input-border-color)}.el-checkbox__input.is-checked .el-checkbox__inner:after{transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-checked+.el-checkbox__label{color:var(--el-checkbox-checked-text-color)}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:var(--el-checkbox-input-border-color-hover)}.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:var(--el-checkbox-checked-bg-color);border-color:var(--el-checkbox-checked-input-border-color)}.el-checkbox__input.is-indeterminate .el-checkbox__inner:before{content:\"\";position:absolute;display:block;background-color:var(--el-checkbox-checked-icon-color);height:2px;transform:scale(.5);left:0;right:0;top:5px}.el-checkbox__input.is-indeterminate .el-checkbox__inner:after{display:none}.el-checkbox__inner{display:inline-block;position:relative;border:var(--el-checkbox-input-border);border-radius:var(--el-checkbox-border-radius);box-sizing:border-box;width:var(--el-checkbox-input-width);height:var(--el-checkbox-input-height);background-color:var(--el-checkbox-bg-color);z-index:var(--el-index-normal);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:var(--el-checkbox-input-border-color-hover)}.el-checkbox__inner:after{box-sizing:content-box;content:\"\";border:1px solid var(--el-checkbox-checked-icon-color);border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;transform:rotate(45deg) scaleY(0);width:3px;transition:transform .15s ease-in 50ms;transform-origin:center}.el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;z-index:-1}.el-checkbox__label{display:inline-block;padding-left:8px;line-height:1;font-size:var(--el-checkbox-font-size)}.el-checkbox.el-checkbox--large{height:40px}.el-checkbox.el-checkbox--large .el-checkbox__label{font-size:14px}.el-checkbox.el-checkbox--large .el-checkbox__inner{width:14px;height:14px}.el-checkbox.el-checkbox--small{height:24px}.el-checkbox.el-checkbox--small .el-checkbox__label{font-size:12px}.el-checkbox.el-checkbox--small .el-checkbox__inner{width:12px;height:12px}.el-checkbox.el-checkbox--small .el-checkbox__input.is-indeterminate .el-checkbox__inner:before{top:4px}.el-checkbox.el-checkbox--small .el-checkbox__inner:after{width:2px;height:6px}.el-checkbox:last-of-type{margin-right:0}[class*=el-col-]{float:left;box-sizing:border-box}[class*=el-col-].is-guttered{display:block;min-height:1px}.el-col-0,.el-col-0.is-guttered{display:none}.el-col-0{max-width:0%;flex:0 0 0%}.el-col-offset-0{margin-left:0}.el-col-pull-0{position:relative;right:0}.el-col-push-0{position:relative;left:0}.el-col-1{max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-offset-1{margin-left:4.1666666667%}.el-col-pull-1{position:relative;right:4.1666666667%}.el-col-push-1{position:relative;left:4.1666666667%}.el-col-2{max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-offset-2{margin-left:8.3333333333%}.el-col-pull-2{position:relative;right:8.3333333333%}.el-col-push-2{position:relative;left:8.3333333333%}.el-col-3{max-width:12.5%;flex:0 0 12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{position:relative;right:12.5%}.el-col-push-3{position:relative;left:12.5%}.el-col-4{max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-offset-4{margin-left:16.6666666667%}.el-col-pull-4{position:relative;right:16.6666666667%}.el-col-push-4{position:relative;left:16.6666666667%}.el-col-5{max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-offset-5{margin-left:20.8333333333%}.el-col-pull-5{position:relative;right:20.8333333333%}.el-col-push-5{position:relative;left:20.8333333333%}.el-col-6{max-width:25%;flex:0 0 25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{position:relative;right:25%}.el-col-push-6{position:relative;left:25%}.el-col-7{max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-offset-7{margin-left:29.1666666667%}.el-col-pull-7{position:relative;right:29.1666666667%}.el-col-push-7{position:relative;left:29.1666666667%}.el-col-8{max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-offset-8{margin-left:33.3333333333%}.el-col-pull-8{position:relative;right:33.3333333333%}.el-col-push-8{position:relative;left:33.3333333333%}.el-col-9{max-width:37.5%;flex:0 0 37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{position:relative;right:37.5%}.el-col-push-9{position:relative;left:37.5%}.el-col-10{max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-offset-10{margin-left:41.6666666667%}.el-col-pull-10{position:relative;right:41.6666666667%}.el-col-push-10{position:relative;left:41.6666666667%}.el-col-11{max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-offset-11{margin-left:45.8333333333%}.el-col-pull-11{position:relative;right:45.8333333333%}.el-col-push-11{position:relative;left:45.8333333333%}.el-col-12{max-width:50%;flex:0 0 50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{position:relative;left:50%}.el-col-13{max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-offset-13{margin-left:54.1666666667%}.el-col-pull-13{position:relative;right:54.1666666667%}.el-col-push-13{position:relative;left:54.1666666667%}.el-col-14{max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-offset-14{margin-left:58.3333333333%}.el-col-pull-14{position:relative;right:58.3333333333%}.el-col-push-14{position:relative;left:58.3333333333%}.el-col-15{max-width:62.5%;flex:0 0 62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{position:relative;right:62.5%}.el-col-push-15{position:relative;left:62.5%}.el-col-16{max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-offset-16{margin-left:66.6666666667%}.el-col-pull-16{position:relative;right:66.6666666667%}.el-col-push-16{position:relative;left:66.6666666667%}.el-col-17{max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-offset-17{margin-left:70.8333333333%}.el-col-pull-17{position:relative;right:70.8333333333%}.el-col-push-17{position:relative;left:70.8333333333%}.el-col-18{max-width:75%;flex:0 0 75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{position:relative;right:75%}.el-col-push-18{position:relative;left:75%}.el-col-19{max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-offset-19{margin-left:79.1666666667%}.el-col-pull-19{position:relative;right:79.1666666667%}.el-col-push-19{position:relative;left:79.1666666667%}.el-col-20{max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-offset-20{margin-left:83.3333333333%}.el-col-pull-20{position:relative;right:83.3333333333%}.el-col-push-20{position:relative;left:83.3333333333%}.el-col-21{max-width:87.5%;flex:0 0 87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{position:relative;right:87.5%}.el-col-push-21{position:relative;left:87.5%}.el-col-22{max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-offset-22{margin-left:91.6666666667%}.el-col-pull-22{position:relative;right:91.6666666667%}.el-col-push-22{position:relative;left:91.6666666667%}.el-col-23{max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-offset-23{margin-left:95.8333333333%}.el-col-pull-23{position:relative;right:95.8333333333%}.el-col-push-23{position:relative;left:95.8333333333%}.el-col-24{max-width:100%;flex:0 0 100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{position:relative;right:100%}.el-col-push-24{position:relative;left:100%}@media only screen and (max-width:768px){.el-col-xs-0,.el-col-xs-0.is-guttered{display:none}.el-col-xs-0{max-width:0%;flex:0 0 0%}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{display:block;max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-xs-offset-1{margin-left:4.1666666667%}.el-col-xs-pull-1{position:relative;right:4.1666666667%}.el-col-xs-push-1{position:relative;left:4.1666666667%}.el-col-xs-2{display:block;max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-xs-offset-2{margin-left:8.3333333333%}.el-col-xs-pull-2{position:relative;right:8.3333333333%}.el-col-xs-push-2{position:relative;left:8.3333333333%}.el-col-xs-3{display:block;max-width:12.5%;flex:0 0 12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{display:block;max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-xs-offset-4{margin-left:16.6666666667%}.el-col-xs-pull-4{position:relative;right:16.6666666667%}.el-col-xs-push-4{position:relative;left:16.6666666667%}.el-col-xs-5{display:block;max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-xs-offset-5{margin-left:20.8333333333%}.el-col-xs-pull-5{position:relative;right:20.8333333333%}.el-col-xs-push-5{position:relative;left:20.8333333333%}.el-col-xs-6{display:block;max-width:25%;flex:0 0 25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{display:block;max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-xs-offset-7{margin-left:29.1666666667%}.el-col-xs-pull-7{position:relative;right:29.1666666667%}.el-col-xs-push-7{position:relative;left:29.1666666667%}.el-col-xs-8{display:block;max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-xs-offset-8{margin-left:33.3333333333%}.el-col-xs-pull-8{position:relative;right:33.3333333333%}.el-col-xs-push-8{position:relative;left:33.3333333333%}.el-col-xs-9{display:block;max-width:37.5%;flex:0 0 37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{display:block;max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-xs-offset-10{margin-left:41.6666666667%}.el-col-xs-pull-10{position:relative;right:41.6666666667%}.el-col-xs-push-10{position:relative;left:41.6666666667%}.el-col-xs-11{display:block;max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-xs-offset-11{margin-left:45.8333333333%}.el-col-xs-pull-11{position:relative;right:45.8333333333%}.el-col-xs-push-11{position:relative;left:45.8333333333%}.el-col-xs-12{display:block;max-width:50%;flex:0 0 50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{display:block;max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-xs-offset-13{margin-left:54.1666666667%}.el-col-xs-pull-13{position:relative;right:54.1666666667%}.el-col-xs-push-13{position:relative;left:54.1666666667%}.el-col-xs-14{display:block;max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-xs-offset-14{margin-left:58.3333333333%}.el-col-xs-pull-14{position:relative;right:58.3333333333%}.el-col-xs-push-14{position:relative;left:58.3333333333%}.el-col-xs-15{display:block;max-width:62.5%;flex:0 0 62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{display:block;max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-xs-offset-16{margin-left:66.6666666667%}.el-col-xs-pull-16{position:relative;right:66.6666666667%}.el-col-xs-push-16{position:relative;left:66.6666666667%}.el-col-xs-17{display:block;max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-xs-offset-17{margin-left:70.8333333333%}.el-col-xs-pull-17{position:relative;right:70.8333333333%}.el-col-xs-push-17{position:relative;left:70.8333333333%}.el-col-xs-18{display:block;max-width:75%;flex:0 0 75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{display:block;max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-xs-offset-19{margin-left:79.1666666667%}.el-col-xs-pull-19{position:relative;right:79.1666666667%}.el-col-xs-push-19{position:relative;left:79.1666666667%}.el-col-xs-20{display:block;max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-xs-offset-20{margin-left:83.3333333333%}.el-col-xs-pull-20{position:relative;right:83.3333333333%}.el-col-xs-push-20{position:relative;left:83.3333333333%}.el-col-xs-21{display:block;max-width:87.5%;flex:0 0 87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{display:block;max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-xs-offset-22{margin-left:91.6666666667%}.el-col-xs-pull-22{position:relative;right:91.6666666667%}.el-col-xs-push-22{position:relative;left:91.6666666667%}.el-col-xs-23{display:block;max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-xs-offset-23{margin-left:95.8333333333%}.el-col-xs-pull-23{position:relative;right:95.8333333333%}.el-col-xs-push-23{position:relative;left:95.8333333333%}.el-col-xs-24{display:block;max-width:100%;flex:0 0 100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media only screen and (min-width:768px){.el-col-sm-0,.el-col-sm-0.is-guttered{display:none}.el-col-sm-0{max-width:0%;flex:0 0 0%}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{display:block;max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-sm-offset-1{margin-left:4.1666666667%}.el-col-sm-pull-1{position:relative;right:4.1666666667%}.el-col-sm-push-1{position:relative;left:4.1666666667%}.el-col-sm-2{display:block;max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-sm-offset-2{margin-left:8.3333333333%}.el-col-sm-pull-2{position:relative;right:8.3333333333%}.el-col-sm-push-2{position:relative;left:8.3333333333%}.el-col-sm-3{display:block;max-width:12.5%;flex:0 0 12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{display:block;max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-sm-offset-4{margin-left:16.6666666667%}.el-col-sm-pull-4{position:relative;right:16.6666666667%}.el-col-sm-push-4{position:relative;left:16.6666666667%}.el-col-sm-5{display:block;max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-sm-offset-5{margin-left:20.8333333333%}.el-col-sm-pull-5{position:relative;right:20.8333333333%}.el-col-sm-push-5{position:relative;left:20.8333333333%}.el-col-sm-6{display:block;max-width:25%;flex:0 0 25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{display:block;max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-sm-offset-7{margin-left:29.1666666667%}.el-col-sm-pull-7{position:relative;right:29.1666666667%}.el-col-sm-push-7{position:relative;left:29.1666666667%}.el-col-sm-8{display:block;max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-sm-offset-8{margin-left:33.3333333333%}.el-col-sm-pull-8{position:relative;right:33.3333333333%}.el-col-sm-push-8{position:relative;left:33.3333333333%}.el-col-sm-9{display:block;max-width:37.5%;flex:0 0 37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{display:block;max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-sm-offset-10{margin-left:41.6666666667%}.el-col-sm-pull-10{position:relative;right:41.6666666667%}.el-col-sm-push-10{position:relative;left:41.6666666667%}.el-col-sm-11{display:block;max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-sm-offset-11{margin-left:45.8333333333%}.el-col-sm-pull-11{position:relative;right:45.8333333333%}.el-col-sm-push-11{position:relative;left:45.8333333333%}.el-col-sm-12{display:block;max-width:50%;flex:0 0 50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{display:block;max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-sm-offset-13{margin-left:54.1666666667%}.el-col-sm-pull-13{position:relative;right:54.1666666667%}.el-col-sm-push-13{position:relative;left:54.1666666667%}.el-col-sm-14{display:block;max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-sm-offset-14{margin-left:58.3333333333%}.el-col-sm-pull-14{position:relative;right:58.3333333333%}.el-col-sm-push-14{position:relative;left:58.3333333333%}.el-col-sm-15{display:block;max-width:62.5%;flex:0 0 62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{display:block;max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-sm-offset-16{margin-left:66.6666666667%}.el-col-sm-pull-16{position:relative;right:66.6666666667%}.el-col-sm-push-16{position:relative;left:66.6666666667%}.el-col-sm-17{display:block;max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-sm-offset-17{margin-left:70.8333333333%}.el-col-sm-pull-17{position:relative;right:70.8333333333%}.el-col-sm-push-17{position:relative;left:70.8333333333%}.el-col-sm-18{display:block;max-width:75%;flex:0 0 75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{display:block;max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-sm-offset-19{margin-left:79.1666666667%}.el-col-sm-pull-19{position:relative;right:79.1666666667%}.el-col-sm-push-19{position:relative;left:79.1666666667%}.el-col-sm-20{display:block;max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-sm-offset-20{margin-left:83.3333333333%}.el-col-sm-pull-20{position:relative;right:83.3333333333%}.el-col-sm-push-20{position:relative;left:83.3333333333%}.el-col-sm-21{display:block;max-width:87.5%;flex:0 0 87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{display:block;max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-sm-offset-22{margin-left:91.6666666667%}.el-col-sm-pull-22{position:relative;right:91.6666666667%}.el-col-sm-push-22{position:relative;left:91.6666666667%}.el-col-sm-23{display:block;max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-sm-offset-23{margin-left:95.8333333333%}.el-col-sm-pull-23{position:relative;right:95.8333333333%}.el-col-sm-push-23{position:relative;left:95.8333333333%}.el-col-sm-24{display:block;max-width:100%;flex:0 0 100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media only screen and (min-width:992px){.el-col-md-0,.el-col-md-0.is-guttered{display:none}.el-col-md-0{max-width:0%;flex:0 0 0%}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{display:block;max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-md-offset-1{margin-left:4.1666666667%}.el-col-md-pull-1{position:relative;right:4.1666666667%}.el-col-md-push-1{position:relative;left:4.1666666667%}.el-col-md-2{display:block;max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-md-offset-2{margin-left:8.3333333333%}.el-col-md-pull-2{position:relative;right:8.3333333333%}.el-col-md-push-2{position:relative;left:8.3333333333%}.el-col-md-3{display:block;max-width:12.5%;flex:0 0 12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{display:block;max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-md-offset-4{margin-left:16.6666666667%}.el-col-md-pull-4{position:relative;right:16.6666666667%}.el-col-md-push-4{position:relative;left:16.6666666667%}.el-col-md-5{display:block;max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-md-offset-5{margin-left:20.8333333333%}.el-col-md-pull-5{position:relative;right:20.8333333333%}.el-col-md-push-5{position:relative;left:20.8333333333%}.el-col-md-6{display:block;max-width:25%;flex:0 0 25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{display:block;max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-md-offset-7{margin-left:29.1666666667%}.el-col-md-pull-7{position:relative;right:29.1666666667%}.el-col-md-push-7{position:relative;left:29.1666666667%}.el-col-md-8{display:block;max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-md-offset-8{margin-left:33.3333333333%}.el-col-md-pull-8{position:relative;right:33.3333333333%}.el-col-md-push-8{position:relative;left:33.3333333333%}.el-col-md-9{display:block;max-width:37.5%;flex:0 0 37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{display:block;max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-md-offset-10{margin-left:41.6666666667%}.el-col-md-pull-10{position:relative;right:41.6666666667%}.el-col-md-push-10{position:relative;left:41.6666666667%}.el-col-md-11{display:block;max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-md-offset-11{margin-left:45.8333333333%}.el-col-md-pull-11{position:relative;right:45.8333333333%}.el-col-md-push-11{position:relative;left:45.8333333333%}.el-col-md-12{display:block;max-width:50%;flex:0 0 50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{display:block;max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-md-offset-13{margin-left:54.1666666667%}.el-col-md-pull-13{position:relative;right:54.1666666667%}.el-col-md-push-13{position:relative;left:54.1666666667%}.el-col-md-14{display:block;max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-md-offset-14{margin-left:58.3333333333%}.el-col-md-pull-14{position:relative;right:58.3333333333%}.el-col-md-push-14{position:relative;left:58.3333333333%}.el-col-md-15{display:block;max-width:62.5%;flex:0 0 62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{display:block;max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-md-offset-16{margin-left:66.6666666667%}.el-col-md-pull-16{position:relative;right:66.6666666667%}.el-col-md-push-16{position:relative;left:66.6666666667%}.el-col-md-17{display:block;max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-md-offset-17{margin-left:70.8333333333%}.el-col-md-pull-17{position:relative;right:70.8333333333%}.el-col-md-push-17{position:relative;left:70.8333333333%}.el-col-md-18{display:block;max-width:75%;flex:0 0 75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{display:block;max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-md-offset-19{margin-left:79.1666666667%}.el-col-md-pull-19{position:relative;right:79.1666666667%}.el-col-md-push-19{position:relative;left:79.1666666667%}.el-col-md-20{display:block;max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-md-offset-20{margin-left:83.3333333333%}.el-col-md-pull-20{position:relative;right:83.3333333333%}.el-col-md-push-20{position:relative;left:83.3333333333%}.el-col-md-21{display:block;max-width:87.5%;flex:0 0 87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{display:block;max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-md-offset-22{margin-left:91.6666666667%}.el-col-md-pull-22{position:relative;right:91.6666666667%}.el-col-md-push-22{position:relative;left:91.6666666667%}.el-col-md-23{display:block;max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-md-offset-23{margin-left:95.8333333333%}.el-col-md-pull-23{position:relative;right:95.8333333333%}.el-col-md-push-23{position:relative;left:95.8333333333%}.el-col-md-24{display:block;max-width:100%;flex:0 0 100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media only screen and (min-width:1200px){.el-col-lg-0,.el-col-lg-0.is-guttered{display:none}.el-col-lg-0{max-width:0%;flex:0 0 0%}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{display:block;max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-lg-offset-1{margin-left:4.1666666667%}.el-col-lg-pull-1{position:relative;right:4.1666666667%}.el-col-lg-push-1{position:relative;left:4.1666666667%}.el-col-lg-2{display:block;max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-lg-offset-2{margin-left:8.3333333333%}.el-col-lg-pull-2{position:relative;right:8.3333333333%}.el-col-lg-push-2{position:relative;left:8.3333333333%}.el-col-lg-3{display:block;max-width:12.5%;flex:0 0 12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{display:block;max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-lg-offset-4{margin-left:16.6666666667%}.el-col-lg-pull-4{position:relative;right:16.6666666667%}.el-col-lg-push-4{position:relative;left:16.6666666667%}.el-col-lg-5{display:block;max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-lg-offset-5{margin-left:20.8333333333%}.el-col-lg-pull-5{position:relative;right:20.8333333333%}.el-col-lg-push-5{position:relative;left:20.8333333333%}.el-col-lg-6{display:block;max-width:25%;flex:0 0 25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{display:block;max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-lg-offset-7{margin-left:29.1666666667%}.el-col-lg-pull-7{position:relative;right:29.1666666667%}.el-col-lg-push-7{position:relative;left:29.1666666667%}.el-col-lg-8{display:block;max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-lg-offset-8{margin-left:33.3333333333%}.el-col-lg-pull-8{position:relative;right:33.3333333333%}.el-col-lg-push-8{position:relative;left:33.3333333333%}.el-col-lg-9{display:block;max-width:37.5%;flex:0 0 37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{display:block;max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-lg-offset-10{margin-left:41.6666666667%}.el-col-lg-pull-10{position:relative;right:41.6666666667%}.el-col-lg-push-10{position:relative;left:41.6666666667%}.el-col-lg-11{display:block;max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-lg-offset-11{margin-left:45.8333333333%}.el-col-lg-pull-11{position:relative;right:45.8333333333%}.el-col-lg-push-11{position:relative;left:45.8333333333%}.el-col-lg-12{display:block;max-width:50%;flex:0 0 50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{display:block;max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-lg-offset-13{margin-left:54.1666666667%}.el-col-lg-pull-13{position:relative;right:54.1666666667%}.el-col-lg-push-13{position:relative;left:54.1666666667%}.el-col-lg-14{display:block;max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-lg-offset-14{margin-left:58.3333333333%}.el-col-lg-pull-14{position:relative;right:58.3333333333%}.el-col-lg-push-14{position:relative;left:58.3333333333%}.el-col-lg-15{display:block;max-width:62.5%;flex:0 0 62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{display:block;max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-lg-offset-16{margin-left:66.6666666667%}.el-col-lg-pull-16{position:relative;right:66.6666666667%}.el-col-lg-push-16{position:relative;left:66.6666666667%}.el-col-lg-17{display:block;max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-lg-offset-17{margin-left:70.8333333333%}.el-col-lg-pull-17{position:relative;right:70.8333333333%}.el-col-lg-push-17{position:relative;left:70.8333333333%}.el-col-lg-18{display:block;max-width:75%;flex:0 0 75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{display:block;max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-lg-offset-19{margin-left:79.1666666667%}.el-col-lg-pull-19{position:relative;right:79.1666666667%}.el-col-lg-push-19{position:relative;left:79.1666666667%}.el-col-lg-20{display:block;max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-lg-offset-20{margin-left:83.3333333333%}.el-col-lg-pull-20{position:relative;right:83.3333333333%}.el-col-lg-push-20{position:relative;left:83.3333333333%}.el-col-lg-21{display:block;max-width:87.5%;flex:0 0 87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{display:block;max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-lg-offset-22{margin-left:91.6666666667%}.el-col-lg-pull-22{position:relative;right:91.6666666667%}.el-col-lg-push-22{position:relative;left:91.6666666667%}.el-col-lg-23{display:block;max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-lg-offset-23{margin-left:95.8333333333%}.el-col-lg-pull-23{position:relative;right:95.8333333333%}.el-col-lg-push-23{position:relative;left:95.8333333333%}.el-col-lg-24{display:block;max-width:100%;flex:0 0 100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}@media only screen and (min-width:1920px){.el-col-xl-0,.el-col-xl-0.is-guttered{display:none}.el-col-xl-0{max-width:0%;flex:0 0 0%}.el-col-xl-offset-0{margin-left:0}.el-col-xl-pull-0{position:relative;right:0}.el-col-xl-push-0{position:relative;left:0}.el-col-xl-1{display:block;max-width:4.1666666667%;flex:0 0 4.1666666667%}.el-col-xl-offset-1{margin-left:4.1666666667%}.el-col-xl-pull-1{position:relative;right:4.1666666667%}.el-col-xl-push-1{position:relative;left:4.1666666667%}.el-col-xl-2{display:block;max-width:8.3333333333%;flex:0 0 8.3333333333%}.el-col-xl-offset-2{margin-left:8.3333333333%}.el-col-xl-pull-2{position:relative;right:8.3333333333%}.el-col-xl-push-2{position:relative;left:8.3333333333%}.el-col-xl-3{display:block;max-width:12.5%;flex:0 0 12.5%}.el-col-xl-offset-3{margin-left:12.5%}.el-col-xl-pull-3{position:relative;right:12.5%}.el-col-xl-push-3{position:relative;left:12.5%}.el-col-xl-4{display:block;max-width:16.6666666667%;flex:0 0 16.6666666667%}.el-col-xl-offset-4{margin-left:16.6666666667%}.el-col-xl-pull-4{position:relative;right:16.6666666667%}.el-col-xl-push-4{position:relative;left:16.6666666667%}.el-col-xl-5{display:block;max-width:20.8333333333%;flex:0 0 20.8333333333%}.el-col-xl-offset-5{margin-left:20.8333333333%}.el-col-xl-pull-5{position:relative;right:20.8333333333%}.el-col-xl-push-5{position:relative;left:20.8333333333%}.el-col-xl-6{display:block;max-width:25%;flex:0 0 25%}.el-col-xl-offset-6{margin-left:25%}.el-col-xl-pull-6{position:relative;right:25%}.el-col-xl-push-6{position:relative;left:25%}.el-col-xl-7{display:block;max-width:29.1666666667%;flex:0 0 29.1666666667%}.el-col-xl-offset-7{margin-left:29.1666666667%}.el-col-xl-pull-7{position:relative;right:29.1666666667%}.el-col-xl-push-7{position:relative;left:29.1666666667%}.el-col-xl-8{display:block;max-width:33.3333333333%;flex:0 0 33.3333333333%}.el-col-xl-offset-8{margin-left:33.3333333333%}.el-col-xl-pull-8{position:relative;right:33.3333333333%}.el-col-xl-push-8{position:relative;left:33.3333333333%}.el-col-xl-9{display:block;max-width:37.5%;flex:0 0 37.5%}.el-col-xl-offset-9{margin-left:37.5%}.el-col-xl-pull-9{position:relative;right:37.5%}.el-col-xl-push-9{position:relative;left:37.5%}.el-col-xl-10{display:block;max-width:41.6666666667%;flex:0 0 41.6666666667%}.el-col-xl-offset-10{margin-left:41.6666666667%}.el-col-xl-pull-10{position:relative;right:41.6666666667%}.el-col-xl-push-10{position:relative;left:41.6666666667%}.el-col-xl-11{display:block;max-width:45.8333333333%;flex:0 0 45.8333333333%}.el-col-xl-offset-11{margin-left:45.8333333333%}.el-col-xl-pull-11{position:relative;right:45.8333333333%}.el-col-xl-push-11{position:relative;left:45.8333333333%}.el-col-xl-12{display:block;max-width:50%;flex:0 0 50%}.el-col-xl-offset-12{margin-left:50%}.el-col-xl-pull-12{position:relative;right:50%}.el-col-xl-push-12{position:relative;left:50%}.el-col-xl-13{display:block;max-width:54.1666666667%;flex:0 0 54.1666666667%}.el-col-xl-offset-13{margin-left:54.1666666667%}.el-col-xl-pull-13{position:relative;right:54.1666666667%}.el-col-xl-push-13{position:relative;left:54.1666666667%}.el-col-xl-14{display:block;max-width:58.3333333333%;flex:0 0 58.3333333333%}.el-col-xl-offset-14{margin-left:58.3333333333%}.el-col-xl-pull-14{position:relative;right:58.3333333333%}.el-col-xl-push-14{position:relative;left:58.3333333333%}.el-col-xl-15{display:block;max-width:62.5%;flex:0 0 62.5%}.el-col-xl-offset-15{margin-left:62.5%}.el-col-xl-pull-15{position:relative;right:62.5%}.el-col-xl-push-15{position:relative;left:62.5%}.el-col-xl-16{display:block;max-width:66.6666666667%;flex:0 0 66.6666666667%}.el-col-xl-offset-16{margin-left:66.6666666667%}.el-col-xl-pull-16{position:relative;right:66.6666666667%}.el-col-xl-push-16{position:relative;left:66.6666666667%}.el-col-xl-17{display:block;max-width:70.8333333333%;flex:0 0 70.8333333333%}.el-col-xl-offset-17{margin-left:70.8333333333%}.el-col-xl-pull-17{position:relative;right:70.8333333333%}.el-col-xl-push-17{position:relative;left:70.8333333333%}.el-col-xl-18{display:block;max-width:75%;flex:0 0 75%}.el-col-xl-offset-18{margin-left:75%}.el-col-xl-pull-18{position:relative;right:75%}.el-col-xl-push-18{position:relative;left:75%}.el-col-xl-19{display:block;max-width:79.1666666667%;flex:0 0 79.1666666667%}.el-col-xl-offset-19{margin-left:79.1666666667%}.el-col-xl-pull-19{position:relative;right:79.1666666667%}.el-col-xl-push-19{position:relative;left:79.1666666667%}.el-col-xl-20{display:block;max-width:83.3333333333%;flex:0 0 83.3333333333%}.el-col-xl-offset-20{margin-left:83.3333333333%}.el-col-xl-pull-20{position:relative;right:83.3333333333%}.el-col-xl-push-20{position:relative;left:83.3333333333%}.el-col-xl-21{display:block;max-width:87.5%;flex:0 0 87.5%}.el-col-xl-offset-21{margin-left:87.5%}.el-col-xl-pull-21{position:relative;right:87.5%}.el-col-xl-push-21{position:relative;left:87.5%}.el-col-xl-22{display:block;max-width:91.6666666667%;flex:0 0 91.6666666667%}.el-col-xl-offset-22{margin-left:91.6666666667%}.el-col-xl-pull-22{position:relative;right:91.6666666667%}.el-col-xl-push-22{position:relative;left:91.6666666667%}.el-col-xl-23{display:block;max-width:95.8333333333%;flex:0 0 95.8333333333%}.el-col-xl-offset-23{margin-left:95.8333333333%}.el-col-xl-pull-23{position:relative;right:95.8333333333%}.el-col-xl-push-23{position:relative;left:95.8333333333%}.el-col-xl-24{display:block;max-width:100%;flex:0 0 100%}.el-col-xl-offset-24{margin-left:100%}.el-col-xl-pull-24{position:relative;right:100%}.el-col-xl-push-24{position:relative;left:100%}}.el-collapse{--el-collapse-border-color:var(--el-border-color-lighter);--el-collapse-header-height:48px;--el-collapse-header-bg-color:var(--el-fill-color-blank);--el-collapse-header-text-color:var(--el-text-color-primary);--el-collapse-header-font-size:13px;--el-collapse-content-bg-color:var(--el-fill-color-blank);--el-collapse-content-font-size:13px;--el-collapse-content-text-color:var(--el-text-color-primary);border-top:1px solid var(--el-collapse-border-color);border-bottom:1px solid var(--el-collapse-border-color)}.el-collapse-item.is-disabled .el-collapse-item__header{color:var(--el-text-color-disabled);cursor:not-allowed}.el-collapse-item__header{display:flex;align-items:center;height:var(--el-collapse-header-height);line-height:var(--el-collapse-header-height);background-color:var(--el-collapse-header-bg-color);color:var(--el-collapse-header-text-color);cursor:pointer;border-bottom:1px solid var(--el-collapse-border-color);font-size:var(--el-collapse-header-font-size);font-weight:500;transition:border-bottom-color var(--el-transition-duration);outline:0}.el-collapse-item__arrow{margin:0 8px 0 auto;transition:transform var(--el-transition-duration);font-weight:300}.el-collapse-item__arrow.is-active{transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:var(--el-color-primary)}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{will-change:height;background-color:var(--el-collapse-content-bg-color);overflow:hidden;box-sizing:border-box;border-bottom:1px solid var(--el-collapse-border-color)}.el-collapse-item__content{padding-bottom:25px;font-size:var(--el-collapse-content-font-size);color:var(--el-collapse-content-text-color);line-height:1.7692307692}.el-collapse-item:last-child{margin-bottom:-1px}.el-color-predefine{display:flex;font-size:12px;margin-top:8px;width:280px}.el-color-predefine__colors{display:flex;flex:1;flex-wrap:wrap}.el-color-predefine__color-selector{margin:0 0 8px 8px;width:20px;height:20px;border-radius:4px;cursor:pointer}.el-color-predefine__color-selector:nth-child(10n+1){margin-left:0}.el-color-predefine__color-selector.selected{box-shadow:0 0 3px 2px var(--el-color-primary)}.el-color-predefine__color-selector>div{display:flex;height:100%;border-radius:3px}.el-color-predefine__color-selector.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-hue-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px;float:right}.el-color-hue-slider__bar{position:relative;background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid var(--el-border-color-lighter);box-shadow:0 0 2px #0009;z-index:1}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:linear-gradient(to right,#fff,rgba(255,255,255,0))}.el-color-svpanel__black{background:linear-gradient(to top,#000,rgba(0,0,0,0))}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px #0000004d,0 0 1px 2px #0006;border-radius:50%;transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider__bar{position:relative;background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid var(--el-border-color-lighter);box-shadow:0 0 2px #0009;z-index:1}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:linear-gradient(to bottom,rgba(255,255,255,0) 0,#fff 100%)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper:after{content:\"\";display:table;clear:both}.el-color-dropdown__btns{margin-top:12px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#000;width:160px}.el-color-picker{display:inline-block;position:relative;line-height:normal}.el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.el-color-picker--large{height:40px}.el-color-picker--large .el-color-picker__trigger{height:40px;width:40px}.el-color-picker--large .el-color-picker__mask{height:38px;width:38px}.el-color-picker--small{height:24px}.el-color-picker--small .el-color-picker__trigger{height:24px;width:24px}.el-color-picker--small .el-color-picker__mask{height:22px;width:22px}.el-color-picker--small .el-color-picker__empty,.el-color-picker--small .el-color-picker__icon{transform:scale(.8)}.el-color-picker__mask{height:38px;width:38px;border-radius:4px;position:absolute;top:1px;left:1px;z-index:1;cursor:not-allowed;background-color:#ffffffb3}.el-color-picker__trigger{display:inline-flex;justify-content:center;align-items:center;box-sizing:border-box;height:32px;width:32px;padding:4px;border:1px solid var(--el-border-color);border-radius:4px;font-size:0;position:relative;cursor:pointer}.el-color-picker__color{position:relative;display:block;box-sizing:border-box;border:1px solid var(--el-text-color-secondary);border-radius:var(--el-border-radius-small);width:100%;height:100%;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{display:inline-flex;justify-content:center;align-items:center;width:100%;height:100%}.el-color-picker .el-color-picker__empty{font-size:12px;color:var(--el-text-color-secondary)}.el-color-picker .el-color-picker__icon{display:inline-flex;justify-content:center;align-items:center;color:#fff;font-size:12px}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;box-sizing:content-box;background-color:#fff;border-radius:var(--el-border-radius-base);box-shadow:var(--el-box-shadow-light)}.el-color-picker__panel.el-popper{border:1px solid var(--el-border-color-lighter)}.el-container{display:flex;flex-direction:row;flex:1;flex-basis:auto;box-sizing:border-box;min-width:0}.el-container.is-vertical{flex-direction:column}.el-date-table{font-size:12px;-webkit-user-select:none;user-select:none}.el-date-table.is-week-mode .el-date-table__row:hover .el-date-table-cell{background-color:var(--el-datepicker-inrange-bg-color)}.el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:var(--el-datepicker-text-color)}.el-date-table.is-week-mode .el-date-table__row:hover td:first-child .el-date-table-cell{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table.is-week-mode .el-date-table__row:hover td:last-child .el-date-table-cell{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table.is-week-mode .el-date-table__row.current .el-date-table-cell{background-color:var(--el-datepicker-inrange-bg-color)}.el-date-table td{width:32px;height:30px;padding:4px 0;box-sizing:border-box;text-align:center;cursor:pointer;position:relative}.el-date-table td .el-date-table-cell{height:30px;padding:3px 0;box-sizing:border-box}.el-date-table td .el-date-table-cell .el-date-table-cell__text{width:24px;height:24px;display:block;margin:0 auto;line-height:24px;position:absolute;left:50%;transform:translate(-50%);border-radius:50%}.el-date-table td.next-month,.el-date-table td.prev-month{color:var(--el-datepicker-off-text-color)}.el-date-table td.today{position:relative}.el-date-table td.today .el-date-table-cell__text{color:var(--el-color-primary);font-weight:700}.el-date-table td.today.end-date .el-date-table-cell__text,.el-date-table td.today.start-date .el-date-table-cell__text{color:#fff}.el-date-table td.available:hover{color:var(--el-datepicker-hover-text-color)}.el-date-table td.in-range .el-date-table-cell{background-color:var(--el-datepicker-inrange-bg-color)}.el-date-table td.in-range .el-date-table-cell:hover{background-color:var(--el-datepicker-inrange-hover-bg-color)}.el-date-table td.current:not(.disabled) .el-date-table-cell__text{color:#fff;background-color:var(--el-datepicker-active-color)}.el-date-table td.end-date .el-date-table-cell,.el-date-table td.start-date .el-date-table-cell{color:#fff}.el-date-table td.end-date .el-date-table-cell__text,.el-date-table td.start-date .el-date-table-cell__text{background-color:var(--el-datepicker-active-color)}.el-date-table td.start-date .el-date-table-cell{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table td.end-date .el-date-table-cell{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td.disabled .el-date-table-cell{background-color:var(--el-fill-color-light);opacity:1;cursor:not-allowed;color:var(--el-text-color-placeholder)}.el-date-table td.selected .el-date-table-cell{margin-left:5px;margin-right:5px;background-color:var(--el-datepicker-inrange-bg-color);border-radius:15px}.el-date-table td.selected .el-date-table-cell:hover{background-color:var(--el-datepicker-inrange-hover-bg-color)}.el-date-table td.selected .el-date-table-cell__text{background-color:var(--el-datepicker-active-color);color:#fff;border-radius:15px}.el-date-table td.week{font-size:80%;color:var(--el-datepicker-header-text-color)}.el-date-table th{padding:5px;color:var(--el-datepicker-header-text-color);font-weight:400;border-bottom:solid 1px var(--el-border-color-lighter)}.el-month-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-month-table td{text-align:center;padding:8px 0;cursor:pointer}.el-month-table td div{height:48px;padding:6px 0;box-sizing:border-box}.el-month-table td.today .cell{color:var(--el-color-primary);font-weight:700}.el-month-table td.today.end-date .cell,.el-month-table td.today.start-date .cell{color:#fff}.el-month-table td.disabled .cell{background-color:var(--el-fill-color-light);cursor:not-allowed;color:var(--el-text-color-placeholder)}.el-month-table td.disabled .cell:hover{color:var(--el-text-color-placeholder)}.el-month-table td .cell{width:60px;height:36px;display:block;line-height:36px;color:var(--el-datepicker-text-color);margin:0 auto;border-radius:18px}.el-month-table td .cell:hover{color:var(--el-datepicker-hover-text-color)}.el-month-table td.in-range div{background-color:var(--el-datepicker-inrange-bg-color)}.el-month-table td.in-range div:hover{background-color:var(--el-datepicker-inrange-hover-bg-color)}.el-month-table td.end-date div,.el-month-table td.start-date div{color:#fff}.el-month-table td.end-date .cell,.el-month-table td.start-date .cell{color:#fff;background-color:var(--el-datepicker-active-color)}.el-month-table td.start-date div{border-top-left-radius:24px;border-bottom-left-radius:24px}.el-month-table td.end-date div{border-top-right-radius:24px;border-bottom-right-radius:24px}.el-month-table td.current:not(.disabled) .cell{color:var(--el-datepicker-active-color)}.el-year-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-year-table .el-icon{color:var(--el-datepicker-icon-color)}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td.today .cell{color:var(--el-color-primary);font-weight:700}.el-year-table td.disabled .cell{background-color:var(--el-fill-color-light);cursor:not-allowed;color:var(--el-text-color-placeholder)}.el-year-table td.disabled .cell:hover{color:var(--el-text-color-placeholder)}.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:var(--el-datepicker-text-color);margin:0 auto}.el-year-table td .cell:hover{color:var(--el-datepicker-hover-text-color)}.el-year-table td.current:not(.disabled) .cell{color:var(--el-datepicker-active-color)}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.el-time-spinner__wrapper{max-height:192px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper.el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__wrapper.is-arrow{box-sizing:border-box;text-align:center;overflow:hidden}.el-time-spinner__wrapper.is-arrow .el-time-spinner__list{transform:translateY(-32px)}.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.is-disabled):not(.is-active){background:#fff;cursor:default}.el-time-spinner__arrow{font-size:12px;color:var(--el-text-color-secondary);position:absolute;left:0;width:100%;z-index:var(--el-index-normal);text-align:center;height:30px;line-height:30px;cursor:pointer}.el-time-spinner__arrow:hover{color:var(--el-color-primary)}.el-time-spinner__arrow.arrow-up{top:10px}.el-time-spinner__arrow.arrow-down{bottom:10px}.el-time-spinner__input.el-input{width:70%}.el-time-spinner__input.el-input .el-input__inner{padding:0;text-align:center}.el-time-spinner__list{padding:0;margin:0;list-style:none;text-align:center}.el-time-spinner__list:after,.el-time-spinner__list:before{content:\"\";display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:var(--el-text-color-regular)}.el-time-spinner__item:hover:not(.is-disabled):not(.is-active){background:var(--el-fill-color-light);cursor:pointer}.el-time-spinner__item.is-active:not(.is-disabled){color:var(--el-text-color-primary);font-weight:700}.el-time-spinner__item.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-picker__popper{--el-datepicker-border-color:var(--el-disabled-border-color)}.el-picker__popper.el-popper[role=tooltip]{background:var(--el-bg-color-overlay);border:1px solid var(--el-datepicker-border-color);box-shadow:var(--el-box-shadow-light)}.el-picker__popper.el-popper[role=tooltip] .el-popper__arrow:before{border:1px solid var(--el-datepicker-border-color)}.el-picker__popper.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-picker__popper.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-picker__popper.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-picker__popper.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-date-editor{--el-date-editor-width:220px;--el-date-editor-monthrange-width:300px;--el-date-editor-daterange-width:350px;--el-date-editor-datetimerange-width:400px;--el-input-text-color:var(--el-text-color-regular);--el-input-border:var(--el-border);--el-input-hover-border:var(--el-border-color-hover);--el-input-focus-border:var(--el-color-primary);--el-input-transparent-border:0 0 0 1px transparent inset;--el-input-border-color:var(--el-border-color);--el-input-border-radius:var(--el-border-radius-base);--el-input-bg-color:var(--el-fill-color-blank);--el-input-icon-color:var(--el-text-color-placeholder);--el-input-placeholder-color:var(--el-text-color-placeholder);--el-input-hover-border-color:var(--el-border-color-hover);--el-input-clear-hover-color:var(--el-text-color-secondary);--el-input-focus-border-color:var(--el-color-primary);position:relative;display:inline-block;text-align:left}.el-date-editor.el-input,.el-date-editor.el-input__inner{width:var(--el-date-editor-width)}.el-date-editor--monthrange.el-input,.el-date-editor--monthrange.el-input__inner{width:var(--el-date-editor-monthrange-width)}.el-date-editor--daterange.el-input,.el-date-editor--daterange.el-input__inner,.el-date-editor--timerange.el-input,.el-date-editor--timerange.el-input__inner{width:var(--el-date-editor-daterange-width)}.el-date-editor--datetimerange.el-input,.el-date-editor--datetimerange.el-input__inner{width:var(--el-date-editor-datetimerange-width)}.el-date-editor--dates .el-input__inner{text-overflow:ellipsis;white-space:nowrap}.el-date-editor .close-icon,.el-date-editor .clear-icon{cursor:pointer}.el-date-editor .clear-icon:hover{color:var(--el-text-color-secondary)}.el-date-editor .el-range__icon{height:inherit;font-size:14px;color:var(--el-text-color-placeholder);float:left}.el-date-editor .el-range__icon svg{vertical-align:middle}.el-date-editor .el-range-input{-webkit-appearance:none;appearance:none;border:none;outline:0;display:inline-block;height:100%;margin:0;padding:0;width:39%;text-align:center;font-size:var(--el-font-size-base);color:var(--el-text-color-regular);background-color:transparent}.el-date-editor .el-range-input::placeholder{color:var(--el-text-color-placeholder)}.el-date-editor .el-range-separator{flex:1;display:inline-flex;justify-content:center;align-items:center;height:100%;padding:0 5px;margin:0;font-size:14px;word-break:keep-all;color:var(--el-text-color-primary)}.el-date-editor .el-range__close-icon{font-size:14px;color:var(--el-text-color-placeholder);height:inherit;width:unset;cursor:pointer}.el-date-editor .el-range__close-icon:hover{color:var(--el-text-color-secondary)}.el-date-editor .el-range__close-icon svg{vertical-align:middle}.el-date-editor .el-range__close-icon--hidden{opacity:0;visibility:hidden}.el-range-editor.el-input__inner{display:inline-flex;align-items:center;padding:3px 10px}.el-range-editor .el-range-input{line-height:1}.el-range-editor.is-active,.el-range-editor.is-active:hover{box-shadow:0 0 0 1px var(--el-input-focus-border-color) inset}.el-range-editor--large{line-height:40px}.el-range-editor--large.el-input__inner{height:40px}.el-range-editor--large .el-range-separator{line-height:40px;font-size:14px}.el-range-editor--large .el-range-input{font-size:14px}.el-range-editor--small{line-height:24px}.el-range-editor--small.el-input__inner{height:24px}.el-range-editor--small .el-range-separator{line-height:24px;font-size:12px}.el-range-editor--small .el-range-input{font-size:12px}.el-range-editor.is-disabled{background-color:var(--el-disabled-bg-color);border-color:var(--el-disabled-border-color);color:var(--el-disabled-text-color);cursor:not-allowed}.el-range-editor.is-disabled:focus,.el-range-editor.is-disabled:hover{border-color:var(--el-disabled-border-color)}.el-range-editor.is-disabled input{background-color:var(--el-disabled-bg-color);color:var(--el-disabled-text-color);cursor:not-allowed}.el-range-editor.is-disabled input::placeholder{color:var(--el-text-color-placeholder)}.el-range-editor.is-disabled .el-range-separator{color:var(--el-disabled-text-color)}.el-picker-panel{color:var(--el-text-color-regular);background:var(--el-bg-color-overlay);border-radius:var(--el-border-radius-base);line-height:30px}.el-picker-panel .el-time-panel{margin:5px 0;border:solid 1px var(--el-datepicker-border-color);background-color:var(--el-color-white);box-shadow:var(--el-box-shadow-light)}.el-picker-panel__body-wrapper:after,.el-picker-panel__body:after{content:\"\";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid var(--el-datepicker-inner-border-color);padding:4px 12px;text-align:right;background-color:var(--el-bg-color-overlay);position:relative;font-size:0}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:var(--el-datepicker-text-color);padding-left:12px;text-align:left;outline:0;cursor:pointer}.el-picker-panel__shortcut:hover{color:var(--el-datepicker-hover-text-color)}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:var(--el-datepicker-active-color)}.el-picker-panel__btn{border:1px solid var(--el-fill-color-darker);color:var(--el-text-color-primary);line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-picker-panel__btn[disabled]{color:var(--el-text-color-disabled);cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:var(--el-datepicker-icon-color);border:0;background:0 0;cursor:pointer;outline:0;margin-top:8px}.el-picker-panel__icon-btn:hover{color:var(--el-datepicker-hover-text-color)}.el-picker-panel__icon-btn.is-disabled{color:var(--el-text-color-disabled)}.el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.el-picker-panel__icon-btn .el-icon{cursor:pointer;font-size:inherit}.el-picker-panel__link-btn{vertical-align:middle}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid var(--el-datepicker-inner-border-color);box-sizing:border-box;padding-top:6px;background-color:var(--el-bg-color-overlay);overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-date-picker{--el-datepicker-text-color:var(--el-text-color-regular);--el-datepicker-off-text-color:var(--el-text-color-placeholder);--el-datepicker-header-text-color:var(--el-text-color-regular);--el-datepicker-icon-color:var(--el-text-color-primary);--el-datepicker-border-color:var(--el-disabled-border-color);--el-datepicker-inner-border-color:var(--el-border-color-light);--el-datepicker-inrange-bg-color:var(--el-border-color-extra-light);--el-datepicker-inrange-hover-bg-color:var(--el-border-color-extra-light);--el-datepicker-active-color:var(--el-color-primary);--el-datepicker-hover-text-color:var(--el-color-primary)}.el-date-picker{width:322px}.el-date-picker.has-sidebar.has-time{width:434px}.el-date-picker.has-sidebar{width:438px}.el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.el-date-picker .el-picker-panel__content{width:292px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid var(--el-datepicker-inner-border-color);font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:solid 1px var(--el-border-color-lighter)}.el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:var(--el-text-color-regular)}.el-date-picker__header-label:hover{color:var(--el-datepicker-hover-text-color)}.el-date-picker__header-label.active{color:var(--el-datepicker-active-color)}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.el-date-picker .el-time-panel{position:absolute}.el-date-range-picker{--el-datepicker-text-color:var(--el-text-color-regular);--el-datepicker-off-text-color:var(--el-text-color-placeholder);--el-datepicker-header-text-color:var(--el-text-color-regular);--el-datepicker-icon-color:var(--el-text-color-primary);--el-datepicker-border-color:var(--el-disabled-border-color);--el-datepicker-inner-border-color:var(--el-border-color-light);--el-datepicker-inrange-bg-color:var(--el-border-color-extra-light);--el-datepicker-inrange-hover-bg-color:var(--el-border-color-extra-light);--el-datepicker-active-color:var(--el-color-primary);--el-datepicker-hover-text-color:var(--el-color-primary)}.el-date-range-picker{width:646px}.el-date-range-picker.has-sidebar{width:756px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header [class*=arrow-left]{float:left}.el-date-range-picker__header [class*=arrow-right]{float:right}.el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-left{border-right:1px solid var(--el-datepicker-inner-border-color)}.el-date-range-picker__content .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__editors-wrap{box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid var(--el-datepicker-inner-border-color);font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:var(--el-datepicker-icon-color)}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#fff}.el-date-range-picker__time-picker-wrap .el-time-panel{position:absolute}.el-time-range-picker{width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px;z-index:1}.el-time-range-picker__cell{box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-time-range-picker__body{border-radius:2px;border:1px solid var(--el-datepicker-border-color)}.el-time-panel{border-radius:2px;position:relative;width:180px;left:0;z-index:var(--el-index-top);-webkit-user-select:none;user-select:none;box-sizing:content-box}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content:after,.el-time-panel__content:before{content:\"\";top:50%;position:absolute;margin-top:-16px;height:32px;z-index:-1;left:0;right:0;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid var(--el-border-color-light);border-bottom:1px solid var(--el-border-color-light)}.el-time-panel__content:after{left:50%;margin-left:12%;margin-right:12%}.el-time-panel__content:before{padding-left:50%;margin-right:12%;margin-left:12%}.el-time-panel__content.has-seconds:after{left:66.6666666667%}.el-time-panel__content.has-seconds:before{padding-left:33.3333333333%}.el-time-panel__footer{border-top:1px solid var(--el-timepicker-inner-border-color,var(--el-border-color-light));padding:4px;height:36px;line-height:25px;text-align:right;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:var(--el-text-color-primary)}.el-time-panel__btn.confirm{font-weight:800;color:var(--el-timepicker-active-color,var(--el-color-primary))}.el-descriptions{--el-descriptions-table-border:1px solid var(--el-border-color-lighter);--el-descriptions-item-bordered-label-background:var(--el-fill-color-light);box-sizing:border-box;font-size:var(--el-font-size-base);color:var(--el-text-color-primary)}.el-descriptions__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.el-descriptions__title{color:var(--el-text-color-primary);font-size:16px;font-weight:700}.el-descriptions__body{background-color:var(--el-fill-color-blank)}.el-descriptions__body .el-descriptions__table{border-collapse:collapse;width:100%}.el-descriptions__body .el-descriptions__table .el-descriptions__cell{box-sizing:border-box;text-align:left;font-weight:400;line-height:23px;font-size:14px}.el-descriptions__body .el-descriptions__table .el-descriptions__cell.is-left{text-align:left}.el-descriptions__body .el-descriptions__table .el-descriptions__cell.is-center{text-align:center}.el-descriptions__body .el-descriptions__table .el-descriptions__cell.is-right{text-align:right}.el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell{border:var(--el-descriptions-table-border);padding:8px 11px}.el-descriptions__body .el-descriptions__table:not(.is-bordered) .el-descriptions__cell{padding-bottom:12px}.el-descriptions--large{font-size:14px}.el-descriptions--large .el-descriptions__header{margin-bottom:20px}.el-descriptions--large .el-descriptions__header .el-descriptions__title{font-size:16px}.el-descriptions--large .el-descriptions__body .el-descriptions__table .el-descriptions__cell{font-size:14px}.el-descriptions--large .el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell{padding:12px 15px}.el-descriptions--large .el-descriptions__body .el-descriptions__table:not(.is-bordered) .el-descriptions__cell{padding-bottom:16px}.el-descriptions--small{font-size:12px}.el-descriptions--small .el-descriptions__header{margin-bottom:12px}.el-descriptions--small .el-descriptions__header .el-descriptions__title{font-size:14px}.el-descriptions--small .el-descriptions__body .el-descriptions__table .el-descriptions__cell{font-size:12px}.el-descriptions--small .el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell{padding:4px 7px}.el-descriptions--small .el-descriptions__body .el-descriptions__table:not(.is-bordered) .el-descriptions__cell{padding-bottom:8px}.el-descriptions__label.el-descriptions__cell.is-bordered-label{font-weight:700;color:var(--el-text-color-regular);background:var(--el-descriptions-item-bordered-label-background)}.el-descriptions__label:not(.is-bordered-label){color:var(--el-text-color-primary);margin-right:16px}.el-descriptions__label.el-descriptions__cell:not(.is-bordered-label).is-vertical-label{padding-bottom:6px}.el-descriptions__content.el-descriptions__cell.is-bordered-content{color:var(--el-text-color-primary)}.el-descriptions__content:not(.is-bordered-label){color:var(--el-text-color-regular)}.el-descriptions--large .el-descriptions__label:not(.is-bordered-label){margin-right:16px}.el-descriptions--large .el-descriptions__label.el-descriptions__cell:not(.is-bordered-label).is-vertical-label{padding-bottom:8px}.el-descriptions--small .el-descriptions__label:not(.is-bordered-label){margin-right:12px}.el-descriptions--small .el-descriptions__label.el-descriptions__cell:not(.is-bordered-label).is-vertical-label{padding-bottom:4px}:root{--el-popup-modal-bg-color:var(--el-color-black);--el-popup-modal-opacity:.5}.v-modal-enter{animation:v-modal-in var(--el-transition-duration-fast) ease}.v-modal-leave{animation:v-modal-out var(--el-transition-duration-fast) ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{to{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:var(--el-popup-modal-opacity);background:var(--el-popup-modal-bg-color)}.el-popup-parent--hidden{overflow:hidden}.el-dialog{--el-dialog-width:50%;--el-dialog-margin-top:15vh;--el-dialog-bg-color:var(--el-bg-color);--el-dialog-box-shadow:var(--el-box-shadow);--el-dialog-title-font-size:var(--el-font-size-large);--el-dialog-content-font-size:14px;--el-dialog-font-line-height:var(--el-font-line-height-primary);--el-dialog-padding-primary:20px;--el-dialog-border-radius:var(--el-border-radius-small);position:relative;margin:var(--el-dialog-margin-top,15vh) auto 50px;background:var(--el-dialog-bg-color);border-radius:var(--el-dialog-border-radius);box-shadow:var(--el-dialog-box-shadow);box-sizing:border-box;width:var(--el-dialog-width,50%)}.el-dialog.is-fullscreen{--el-dialog-width:100%;--el-dialog-margin-top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.el-dialog.is-draggable .el-dialog__header{cursor:move;-webkit-user-select:none;user-select:none}.el-dialog__header{padding:var(--el-dialog-padding-primary);padding-bottom:10px;margin-right:16px;word-break:break-all}.el-dialog__headerbtn{position:absolute;top:6px;right:0;padding:0;width:54px;height:54px;background:0 0;border:none;outline:0;cursor:pointer;font-size:var(--el-message-close-size,16px)}.el-dialog__headerbtn .el-dialog__close{color:var(--el-color-info);font-size:inherit}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:var(--el-color-primary)}.el-dialog__title{line-height:var(--el-dialog-font-line-height);font-size:var(--el-dialog-title-font-size);color:var(--el-text-color-primary)}.el-dialog__body{padding:calc(var(--el-dialog-padding-primary) + 10px) var(--el-dialog-padding-primary);color:var(--el-text-color-regular);font-size:var(--el-dialog-content-font-size);word-break:break-all}.el-dialog__footer{padding:var(--el-dialog-padding-primary);padding-top:10px;text-align:right;box-sizing:border-box}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{text-align:initial;padding:25px calc(var(--el-dialog-padding-primary) + 5px) 30px}.el-dialog--center .el-dialog__footer{text-align:inherit}.el-overlay-dialog{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto}.dialog-fade-enter-active{animation:modal-fade-in var(--el-transition-duration)}.dialog-fade-enter-active .el-overlay-dialog{animation:dialog-fade-in var(--el-transition-duration)}.dialog-fade-leave-active{animation:modal-fade-out var(--el-transition-duration)}.dialog-fade-leave-active .el-overlay-dialog{animation:dialog-fade-out var(--el-transition-duration)}@keyframes dialog-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes dialog-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}@keyframes modal-fade-in{0%{opacity:0}to{opacity:1}}@keyframes modal-fade-out{0%{opacity:1}to{opacity:0}}.el-divider{position:relative}.el-divider--horizontal{display:block;height:1px;width:100%;margin:24px 0;border-top:1px var(--el-border-color) var(--el-border-style)}.el-divider--vertical{display:inline-block;width:1px;height:1em;margin:0 8px;vertical-align:middle;position:relative;border-left:1px var(--el-border-color) var(--el-border-style)}.el-divider__text{position:absolute;background-color:var(--el-bg-color);padding:0 20px;font-weight:500;color:var(--el-text-color-primary);font-size:14px}.el-divider__text.is-left{left:20px;transform:translateY(-50%)}.el-divider__text.is-center{left:50%;transform:translate(-50%) translateY(-50%)}.el-divider__text.is-right{right:20px;transform:translateY(-50%)}.el-drawer{--el-drawer-bg-color:var(--el-dialog-bg-color, var(--el-bg-color));--el-drawer-padding-primary:var(--el-dialog-padding-primary, 20px)}.el-drawer{position:absolute;box-sizing:border-box;background-color:var(--el-drawer-bg-color);display:flex;flex-direction:column;box-shadow:var(--el-box-shadow-dark);overflow:hidden;transition:all var(--el-transition-duration)}.el-drawer .rtl,.el-drawer .ltr,.el-drawer .ttb,.el-drawer .btt{transform:translate(0)}.el-drawer__header{align-items:center;color:#72767b;display:flex;margin-bottom:32px;padding:var(--el-drawer-padding-primary);padding-bottom:0}.el-drawer__header>:first-child{flex:1}.el-drawer__title{margin:0;flex:1;line-height:inherit;font-size:1rem}.el-drawer__footer{padding:var(--el-drawer-padding-primary);padding-top:10px;text-align:right}.el-drawer__close-btn{border:none;cursor:pointer;font-size:var(--el-font-size-extra-large);color:inherit;background-color:transparent;outline:0}.el-drawer__close-btn:hover i{color:var(--el-color-primary)}.el-drawer__close-btn .el-icon{font-size:inherit;vertical-align:text-bottom}.el-drawer__body{flex:1;padding:var(--el-drawer-padding-primary);overflow:auto}.el-drawer__body>*{box-sizing:border-box}.el-drawer.ltr,.el-drawer.rtl{height:100%;top:0;bottom:0}.el-drawer.btt,.el-drawer.ttb{width:100%;left:0;right:0}.el-drawer.ltr{left:0}.el-drawer.rtl{right:0}.el-drawer.ttb{top:0}.el-drawer.btt{bottom:0}.el-drawer-fade-enter-active,.el-drawer-fade-leave-active{transition:all var(--el-transition-duration)}.el-drawer-fade-enter-active,.el-drawer-fade-enter-from,.el-drawer-fade-enter-to,.el-drawer-fade-leave-active,.el-drawer-fade-leave-from,.el-drawer-fade-leave-to{overflow:hidden!important}.el-drawer-fade-enter-from,.el-drawer-fade-leave-to{opacity:0}.el-drawer-fade-enter-to,.el-drawer-fade-leave-from{opacity:1}.el-drawer-fade-enter-from .rtl,.el-drawer-fade-leave-to .rtl{transform:translate(100%)}.el-drawer-fade-enter-from .ltr,.el-drawer-fade-leave-to .ltr{transform:translate(-100%)}.el-drawer-fade-enter-from .ttb,.el-drawer-fade-leave-to .ttb{transform:translateY(-100%)}.el-drawer-fade-enter-from .btt,.el-drawer-fade-leave-to .btt{transform:translateY(100%)}.el-dropdown{--el-dropdown-menu-box-shadow:var(--el-box-shadow-light);--el-dropdown-menuItem-hover-fill:var(--el-color-primary-light-9);--el-dropdown-menuItem-hover-color:var(--el-color-primary-light-3);--el-dropdown-menu-index:10;display:inline-flex;position:relative;color:var(--el-text-color-regular);font-size:var(--el-font-size-base);line-height:1;vertical-align:top}.el-dropdown.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-dropdown__popper{--el-dropdown-menu-box-shadow:var(--el-box-shadow-light);--el-dropdown-menuItem-hover-fill:var(--el-color-primary-light-9);--el-dropdown-menuItem-hover-color:var(--el-color-primary-light-3);--el-dropdown-menu-index:10}.el-dropdown__popper.el-popper[role=tooltip]{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light);box-shadow:var(--el-dropdown-menu-box-shadow)}.el-dropdown__popper.el-popper[role=tooltip] .el-popper__arrow:before{border:1px solid var(--el-border-color-light)}.el-dropdown__popper.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-dropdown__popper.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-dropdown__popper.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-dropdown__popper.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-dropdown__popper .el-dropdown-menu{border:none}.el-dropdown__popper .el-dropdown__popper-selfdefine{outline:0}.el-dropdown__popper .el-scrollbar__bar{z-index:calc(var(--el-dropdown-menu-index) + 1)}.el-dropdown__popper .el-dropdown__list{list-style:none;padding:0;margin:0;box-sizing:border-box}.el-dropdown .el-dropdown__caret-button{padding-left:0;padding-right:0;display:inline-flex;justify-content:center;align-items:center;width:32px;border-left:none}.el-dropdown .el-dropdown__caret-button>span{display:inline-flex}.el-dropdown .el-dropdown__caret-button:before{content:\"\";position:absolute;display:block;width:1px;top:5px;bottom:5px;left:0;background:var(--el-overlay-color-lighter)}.el-dropdown .el-dropdown__caret-button.el-button:before{background:var(--el-border-color);opacity:.5}.el-dropdown .el-dropdown__caret-button:hover:before{top:0;bottom:0}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{font-size:inherit;padding-left:0}.el-dropdown .el-dropdown-selfdefine{outline:0}.el-dropdown--large .el-dropdown__caret-button{width:40px}.el-dropdown--small .el-dropdown__caret-button{width:24px}.el-dropdown-menu{position:relative;top:0;left:0;z-index:var(--el-dropdown-menu-index);padding:5px 0;margin:0;background-color:var(--el-bg-color-overlay);border:none;border-radius:var(--el-border-radius-base);box-shadow:none;list-style:none}.el-dropdown-menu__item{display:flex;align-items:center;white-space:nowrap;list-style:none;line-height:22px;padding:5px 16px;margin:0;font-size:var(--el-font-size-base);color:var(--el-text-color-regular);cursor:pointer;outline:0}.el-dropdown-menu__item:not(.is-disabled):focus{background-color:var(--el-dropdown-menuItem-hover-fill);color:var(--el-dropdown-menuItem-hover-color)}.el-dropdown-menu__item i{margin-right:5px}.el-dropdown-menu__item--divided{margin:6px 0;border-top:1px solid var(--el-border-color-lighter)}.el-dropdown-menu__item.is-disabled{cursor:not-allowed;color:var(--el-text-color-disabled)}.el-dropdown-menu--large{padding:7px 0}.el-dropdown-menu--large .el-dropdown-menu__item{padding:7px 20px;line-height:22px;font-size:14px}.el-dropdown-menu--large .el-dropdown-menu__item--divided{margin:8px 0}.el-dropdown-menu--small{padding:3px 0}.el-dropdown-menu--small .el-dropdown-menu__item{padding:2px 12px;line-height:20px;font-size:12px}.el-dropdown-menu--small .el-dropdown-menu__item--divided{margin:4px 0}.el-empty{--el-empty-padding:40px 0;--el-empty-image-width:160px;--el-empty-description-margin-top:20px;--el-empty-bottom-margin-top:20px;--el-empty-fill-color-0:var(--el-color-white);--el-empty-fill-color-1:#fcfcfd;--el-empty-fill-color-2:#f8f9fb;--el-empty-fill-color-3:#f7f8fc;--el-empty-fill-color-4:#eeeff3;--el-empty-fill-color-5:#edeef2;--el-empty-fill-color-6:#e9ebef;--el-empty-fill-color-7:#e5e7e9;--el-empty-fill-color-8:#e0e3e9;--el-empty-fill-color-9:#d5d7de;display:flex;justify-content:center;align-items:center;flex-direction:column;text-align:center;box-sizing:border-box;padding:var(--el-empty-padding)}.el-empty__image{width:var(--el-empty-image-width)}.el-empty__image img{-webkit-user-select:none;user-select:none;width:100%;height:100%;vertical-align:top;object-fit:contain}.el-empty__image svg{color:var(--el-svg-monochrome-grey);fill:currentColor;width:100%;height:100%;vertical-align:top}.el-empty__description{margin-top:var(--el-empty-description-margin-top)}.el-empty__description p{margin:0;font-size:var(--el-font-size-base);color:var(--el-text-color-secondary)}.el-empty__bottom{margin-top:var(--el-empty-bottom-margin-top)}.el-footer{--el-footer-padding:0 20px;--el-footer-height:60px;padding:var(--el-footer-padding);box-sizing:border-box;flex-shrink:0;height:var(--el-footer-height)}.el-form{--el-form-label-font-size:var(--el-font-size-base)}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item{display:block}.el-form--label-top .el-form-item .el-form-item__label{display:block;text-align:left;margin-bottom:8px;line-height:22px}.el-form--inline .el-form-item{display:inline-flex;vertical-align:middle;margin-right:32px}.el-form--inline.el-form--label-top{display:flex;flex-wrap:wrap}.el-form--inline.el-form--label-top .el-form-item{display:block}.el-form--large.el-form--label-top .el-form-item .el-form-item__label{margin-bottom:12px;line-height:22px}.el-form--default.el-form--label-top .el-form-item .el-form-item__label{margin-bottom:8px;line-height:22px}.el-form--small.el-form--label-top .el-form-item .el-form-item__label{margin-bottom:4px;line-height:20px}.el-form-item{display:flex;--font-size:14px;margin-bottom:18px}.el-form-item .el-form-item{margin-bottom:0}.el-form-item .el-input__validateIcon{display:none}.el-form-item--large{--font-size:14px;--el-form-label-font-size:var(--font-size);margin-bottom:22px}.el-form-item--large .el-form-item__label,.el-form-item--large .el-form-item__content{line-height:40px}.el-form-item--large .el-form-item__error{padding-top:4px}.el-form-item--default{--font-size:14px;--el-form-label-font-size:var(--font-size);margin-bottom:18px}.el-form-item--default .el-form-item__label,.el-form-item--default .el-form-item__content{line-height:32px}.el-form-item--default .el-form-item__error{padding-top:2px}.el-form-item--small{--font-size:12px;--el-form-label-font-size:var(--font-size);margin-bottom:18px}.el-form-item--small .el-form-item__label,.el-form-item--small .el-form-item__content{line-height:24px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item__label-wrap{display:flex}.el-form-item__label-wrap .el-form-item__label{display:inline-block}.el-form-item__label{flex:0 0 auto;text-align:right;font-size:var(--el-form-label-font-size);color:var(--el-text-color-regular);line-height:32px;padding:0 12px 0 0;box-sizing:border-box}.el-form-item__content{display:flex;flex-wrap:wrap;align-items:center;flex:1;line-height:32px;position:relative;font-size:var(--font-size);min-width:0}.el-form-item__content .el-input-group{vertical-align:top}.el-form-item__error{color:var(--el-color-danger);font-size:12px;line-height:1;padding-top:2px;position:absolute;top:100%;left:0}.el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label-wrap>.el-form-item__label:before,.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{content:\"*\";color:var(--el-color-danger);margin-right:4px}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-select-v2__wrapper,.el-form-item.is-error .el-select-v2__wrapper:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus{box-shadow:0 0 0 1px var(--el-color-danger) inset}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{box-shadow:0 0 0 1px transparent inset}.el-form-item.is-error .el-input__validateIcon{color:var(--el-color-danger)}.el-form-item--feedback .el-input__validateIcon{display:inline-flex}.el-header{--el-header-padding:0 20px;--el-header-height:60px;padding:var(--el-header-padding);box-sizing:border-box;flex-shrink:0;height:var(--el-header-height)}.el-image-viewer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0}.el-image-viewer__btn{position:absolute;z-index:1;display:flex;align-items:center;justify-content:center;border-radius:50%;opacity:.8;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none}.el-image-viewer__btn .el-icon{font-size:inherit;cursor:pointer}.el-image-viewer__close{top:40px;right:40px;width:40px;height:40px;font-size:40px}.el-image-viewer__canvas{width:100%;height:100%;display:flex;justify-content:center;align-items:center;-webkit-user-select:none;user-select:none}.el-image-viewer__actions{left:50%;bottom:30px;transform:translate(-50%);width:282px;height:44px;padding:0 23px;background-color:var(--el-text-color-regular);border-color:#fff;border-radius:22px}.el-image-viewer__actions__inner{width:100%;height:100%;text-align:justify;cursor:default;font-size:23px;color:#fff;display:flex;align-items:center;justify-content:space-around}.el-image-viewer__prev{top:50%;transform:translateY(-50%);left:40px;width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__next{top:50%;transform:translateY(-50%);right:40px;text-indent:2px;width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__close{width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__mask{position:absolute;width:100%;height:100%;top:0;left:0;opacity:.5;background:#000}.viewer-fade-enter-active{animation:viewer-fade-in var(--el-transition-duration)}.viewer-fade-leave-active{animation:viewer-fade-out var(--el-transition-duration)}@keyframes viewer-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes viewer-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-image__error,.el-image__inner,.el-image__placeholder{width:100%;height:100%}.el-image{position:relative;display:inline-block;overflow:hidden}.el-image__inner{vertical-align:top}.el-image__placeholder{background:var(--el-fill-color-light)}.el-image__error{display:flex;justify-content:center;align-items:center;font-size:14px;background:var(--el-fill-color-light);color:var(--el-text-color-placeholder);vertical-align:middle}.el-image__preview{cursor:pointer}.el-input-number{position:relative;display:inline-block;width:150px;line-height:30px}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;-moz-appearance:textfield;padding-left:42px;padding-right:42px;text-align:center}.el-input-number .el-input__inner::-webkit-inner-spin-button,.el-input-number .el-input__inner::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.el-input-number__decrease,.el-input-number__increase{display:flex;justify-content:center;align-items:center;height:auto;position:absolute;z-index:1;top:1px;bottom:1px;width:32px;background:var(--el-fill-color-light);color:var(--el-text-color-regular);cursor:pointer;font-size:13px;-webkit-user-select:none;user-select:none}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:var(--el-color-primary)}.el-input-number__decrease:hover~.el-input:not(.is-disabled) .el-input__inner,.el-input-number__increase:hover~.el-input:not(.is-disabled) .el-input__inner{box-shadow:0 0 0 1px var(--el-input-focus-border-color,var(--el-color-primary)) inset}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:var(--el-disabled-text-color);cursor:not-allowed}.el-input-number__increase{right:1px;border-radius:0 var(--el-border-radius-base) var(--el-border-radius-base) 0;border-left:var(--el-border)}.el-input-number__decrease{left:1px;border-radius:var(--el-border-radius-base) 0 0 var(--el-border-radius-base);border-right:var(--el-border)}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:var(--el-disabled-border-color);color:var(--el-disabled-border-color)}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:var(--el-disabled-border-color);cursor:not-allowed}.el-input-number--large{width:180px;line-height:38px}.el-input-number--large .el-input-number__decrease,.el-input-number--large .el-input-number__increase{width:40px;font-size:14px}.el-input-number--large .el-input__inner{padding-left:47px;padding-right:47px}.el-input-number--small{width:120px;line-height:22px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{width:24px;font-size:12px}.el-input-number--small .el-input__inner{padding-left:31px;padding-right:31px}.el-input-number--small .el-input-number__decrease [class*=el-icon],.el-input-number--small .el-input-number__increase [class*=el-icon]{transform:scale(.9)}.el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:42px}.el-input-number.is-controls-right .el-input-number__decrease,.el-input-number.is-controls-right .el-input-number__increase{--el-input-number-controls-height:15px;height:var(--el-input-number-controls-height);line-height:var(--el-input-number-controls-height)}.el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{transform:scale(.8)}.el-input-number.is-controls-right .el-input-number__increase{bottom:auto;left:auto;border-radius:0 var(--el-border-radius-base) 0 0;border-bottom:var(--el-border)}.el-input-number.is-controls-right .el-input-number__decrease{right:1px;top:auto;left:auto;border-right:none;border-left:var(--el-border);border-radius:0 0 var(--el-border-radius-base) 0}.el-input-number.is-controls-right[class*=large] [class*=decrease],.el-input-number.is-controls-right[class*=large] [class*=increase]{--el-input-number-controls-height:19px}.el-input-number.is-controls-right[class*=small] [class*=decrease],.el-input-number.is-controls-right[class*=small] [class*=increase]{--el-input-number-controls-height:11px}.el-textarea{--el-input-text-color:var(--el-text-color-regular);--el-input-border:var(--el-border);--el-input-hover-border:var(--el-border-color-hover);--el-input-focus-border:var(--el-color-primary);--el-input-transparent-border:0 0 0 1px transparent inset;--el-input-border-color:var(--el-border-color);--el-input-border-radius:var(--el-border-radius-base);--el-input-bg-color:var(--el-fill-color-blank);--el-input-icon-color:var(--el-text-color-placeholder);--el-input-placeholder-color:var(--el-text-color-placeholder);--el-input-hover-border-color:var(--el-border-color-hover);--el-input-clear-hover-color:var(--el-text-color-secondary);--el-input-focus-border-color:var(--el-color-primary)}.el-textarea{position:relative;display:inline-block;width:100%;vertical-align:bottom;font-size:var(--el-font-size-base)}.el-textarea__inner{position:relative;display:block;resize:vertical;padding:5px 15px;line-height:1.5;box-sizing:border-box;width:100%;font-size:inherit;font-family:inherit;color:var(--el-input-text-color,var(--el-text-color-regular));background-color:var(--el-input-bg-color,var(--el-fill-color-blank));background-image:none;-webkit-appearance:none;box-shadow:0 0 0 1px var(--el-input-border-color,var(--el-border-color)) inset;border-radius:var(--el-input-border-radius,var(--el-border-radius-base));transition:var(--el-transition-box-shadow);border:none}.el-textarea__inner::placeholder{color:var(--el-input-placeholder-color,var(--el-text-color-placeholder))}.el-textarea__inner:hover{box-shadow:0 0 0 1px var(--el-input-hover-border-color) inset}.el-textarea__inner:focus{outline:0;box-shadow:0 0 0 1px var(--el-input-focus-border-color) inset}.el-textarea .el-input__count{color:var(--el-color-info);background:var(--el-fill-color-blank);position:absolute;font-size:12px;line-height:14px;bottom:5px;right:10px}.el-textarea.is-disabled .el-textarea__inner{background-color:var(--el-disabled-bg-color);border-color:var(--el-disabled-border-color);color:var(--el-disabled-text-color);cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:var(--el-text-color-placeholder)}.el-textarea.is-exceed .el-textarea__inner{border-color:var(--el-color-danger)}.el-textarea.is-exceed .el-input__count{color:var(--el-color-danger)}.el-input{--el-input-text-color:var(--el-text-color-regular);--el-input-border:var(--el-border);--el-input-hover-border:var(--el-border-color-hover);--el-input-focus-border:var(--el-color-primary);--el-input-transparent-border:0 0 0 1px transparent inset;--el-input-border-color:var(--el-border-color);--el-input-border-radius:var(--el-border-radius-base);--el-input-bg-color:var(--el-fill-color-blank);--el-input-icon-color:var(--el-text-color-placeholder);--el-input-placeholder-color:var(--el-text-color-placeholder);--el-input-hover-border-color:var(--el-border-color-hover);--el-input-clear-hover-color:var(--el-text-color-secondary);--el-input-focus-border-color:var(--el-color-primary);position:relative;font-size:var(--el-font-size-base);display:inline-flex;width:100%;line-height:32px}.el-input::-webkit-scrollbar{z-index:11;width:6px}.el-input::-webkit-scrollbar:horizontal{height:6px}.el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:var(--el-text-color-disabled)}.el-input::-webkit-scrollbar-corner{background:var(--el-fill-color-blank)}.el-input::-webkit-scrollbar-track{background:var(--el-fill-color-blank)}.el-input::-webkit-scrollbar-track-piece{background:var(--el-fill-color-blank);width:6px}.el-input .el-input__clear{color:var(--el-input-icon-color);font-size:14px;cursor:pointer;transition:var(--el-transition-color);margin-left:8px}.el-input .el-input__clear:hover{color:var(--el-input-clear-hover-color)}.el-input .el-input__count{height:100%;display:inline-flex;align-items:center;color:var(--el-color-info);font-size:12px}.el-input .el-input__count .el-input__count-inner{background:var(--el-fill-color-blank);line-height:initial;display:inline-block;padding:0 5px}.el-input__inner{position:relative;-webkit-appearance:none;background-color:var(--el-input-bg-color,var(--el-fill-color-blank));background-image:none;border-radius:var(--el-input-border-radius,var(--el-border-radius-base));box-sizing:border-box;color:var(--el-input-text-color,var(--el-text-color-regular));display:inline-block;font-size:inherit;height:32px;line-height:32px;outline:0;padding:0 11px;transition:var(--el-transition-box-shadow);width:100%;box-shadow:0 0 0 1px var(--el-input-border-color,var(--el-border-color)) inset;border:none}.el-input__inner::placeholder{color:var(--el-input-placeholder-color,var(--el-text-color-placeholder))}.el-input__inner:hover{box-shadow:0 0 0 1px var(--el-input-hover-border-color) inset}.el-input__inner:focus{outline:0;box-shadow:0 0 0 1px var(--el-input-focus-border-color) inset}.el-input__inner[type=password]::-ms-reveal{display:none}.el-input__suffix{display:inline-flex;position:absolute;height:100%;right:12px;top:0;text-align:center;color:var(--el-input-icon-color,var(--el-text-color-placeholder));transition:all var(--el-transition-duration);pointer-events:none}.el-input__suffix-inner{pointer-events:all;display:inline-flex}.el-input__prefix{display:inline-flex;position:absolute;height:100%;left:12px;top:0;text-align:center;color:var(--el-input-icon-color,var(--el-text-color-placeholder));transition:all var(--el-transition-duration)}.el-input__prefix-inner{pointer-events:all;display:inline-flex}.el-input .el-input__icon{height:inherit;display:flex;justify-content:center;align-items:center;transition:all var(--el-transition-duration)}.el-input__validateIcon{pointer-events:none}.el-input.is-active .el-input__inner{outline:0;box-shadow:0 0 0 1px var(--el-input-focus-border,) inset}.el-input.is-disabled .el-input__inner{background-color:var(--el-disabled-bg-color);box-shadow:0 0 0 1px var(--el-disabled-border-color) inset;color:var(--el-disabled-text-color);cursor:not-allowed}.el-input.is-disabled .el-input__inner::placeholder{color:var(--el-text-color-placeholder)}.el-input.is-disabled .el-input__icon{cursor:not-allowed}.el-input.is-exceed .el-input__inner{box-shadow:0 0 0 1px var(--el-color-danger) inset}.el-input.is-exceed .el-input__suffix .el-input__count{color:var(--el-color-danger)}.el-input--suffix .el-input__inner{padding-right:31px}.el-input--suffix--password-clear .el-input__inner{padding-right:55px}.el-input--prefix .el-input__inner{padding-left:31px}.el-input--large{font-size:14px;line-height:38px}.el-input--large .el-input__inner{height:40px;line-height:40px;padding:0 15px}.el-input--large .el-input__icon{line-height:40px}.el-input--large.el-input--prefix .el-input__inner{padding-left:35px}.el-input--large.el-input--suffix .el-input__inner{padding-right:35px}.el-input--large .el-input__prefix{left:16px}.el-input--large .el-input__suffix{right:16px}.el-input--small{font-size:12px;line-height:22px}.el-input--small .el-input__inner{height:24px;line-height:24px;padding:0 7px}.el-input--small .el-input__icon{line-height:24px}.el-input--small.el-input--prefix .el-input__inner{padding-left:25px}.el-input--small.el-input--suffix .el-input__inner{padding-right:25px}.el-input--small .el-input__prefix{left:8px}.el-input--small .el-input__suffix{right:8px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate;border-spacing:0}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:var(--el-fill-color-light);color:var(--el-color-info);vertical-align:middle;display:table-cell;position:relative;border-radius:var(--el-input-border-radius);padding:0 20px;width:1px;white-space:nowrap}.el-input-group__append:focus,.el-input-group__prepend:focus{outline:0}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:inline-block;margin:0 -20px}.el-input-group__append button.el-button,.el-input-group__append button.el-button:hover,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend button.el-button:hover,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0;box-shadow:1px 0 0 0 var(--el-input-border-color) inset,0 1px 0 0 var(--el-input-border-color) inset,0 -1px 0 0 var(--el-input-border-color) inset}.el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;box-shadow:0 1px 0 0 var(--el-input-border-color) inset,0 -1px 0 0 var(--el-input-border-color) inset,-1px 0 0 0 var(--el-input-border-color) inset}.el-input-group--prepend .el-input__inner{box-shadow:1px 0 0 0 var(--el-input-border-color) inset,0 1px 0 0 var(--el-input-border-color) inset,0 -1px 0 0 var(--el-input-border-color) inset}.el-input-group--prepend>.el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0;box-shadow:0 0 0 1px var(--el-input-border-color) inset}.el-input-group--prepend>.el-input__inner:hover{box-shadow:0 0 0 1px var(--el-input-hover-border-color) inset}.el-input-group--prepend>.el-input__inner:focus{outline:0;box-shadow:0 0 0 1px var(--el-input-focus-border-color) inset}.el-input-group--prepend .el-input-group__prepend .el-select .el-input .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group--prepend .el-input-group__prepend .el-select .el-input .el-input__inner:focus{outline:0;z-index:2;box-shadow:1px 0 0 0 var(--el-input-focus-border-color) inset,1px 0 0 0 var(--el-input-focus-border-color),0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important}.el-input-group--prepend .el-input-group__prepend .el-select .el-input.is-focus .el-input__inner{box-shadow:1px 0 0 0 var(--el-input-focus-border-color) inset,1px 0 0 0 var(--el-input-focus-border-color),0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important;z-index:2}.el-input-group--prepend .el-input-group__prepend .el-select .el-input.is-focus .el-input__inner:focus{outline:0;z-index:2;box-shadow:1px 0 0 0 var(--el-input-focus-border-color) inset,1px 0 0 0 var(--el-input-focus-border-color),0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important}.el-input-group--prepend .el-input-group__prepend .el-select:hover .el-input__inner{z-index:1;box-shadow:1px 0 0 0 var(--el-input-hover-border-color) inset,1px 0 0 0 var(--el-input-hover-border-color),0 1px 0 0 var(--el-input-hover-border-color) inset,0 -1px 0 0 var(--el-input-hover-border-color) inset!important}.el-input-group--append>.el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group--append .el-input-group__append .el-select .el-input .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0;box-shadow:-1px 0 0 0 var(--el-input-border-color),-1px 0 0 0 var(--el-input-border-color) inset,0 1px 0 0 var(--el-input-border-color) inset,0 -1px 0 0 var(--el-input-border-color) inset!important}.el-input-group--append .el-input-group__append .el-select .el-input .el-input__inner:focus{outline:0;z-index:2;box-shadow:-1px 0 0 0 var(--el-input-focus-border-color),-1px 0 0 0 var(--el-input-focus-border-color) inset,0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important}.el-input-group--append .el-input-group__append .el-select .el-input.is-focus .el-input__inner{outline:0;z-index:2;box-shadow:-1px 0 0 0 var(--el-input-focus-border-color),-1px 0 0 0 var(--el-input-focus-border-color) inset,0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important}.el-input-group--append .el-input-group__append .el-select .el-input.is-focus .el-input__inner:focus{outline:0;z-index:2;box-shadow:-1px 0 0 0 var(--el-input-focus-border-color),-1px 0 0 0 var(--el-input-focus-border-color) inset,0 1px 0 0 var(--el-input-focus-border-color) inset,0 -1px 0 0 var(--el-input-focus-border-color) inset!important}.el-input-group--append .el-input-group__append .el-select:hover .el-input__inner{z-index:1;box-shadow:-1px 0 0 0 var(--el-input-hover-border-color),-1px 0 0 0 var(--el-input-hover-border-color) inset,0 1px 0 0 var(--el-input-hover-border-color) inset,0 -1px 0 0 var(--el-input-hover-border-color) inset!important}.el-link{--el-link-font-size:var(--el-font-size-base);--el-link-font-weight:var(--el-font-weight-primary);--el-link-text-color:var(--el-text-color-regular);--el-link-hover-text-color:var(--el-color-primary);--el-link-disabled-text-color:var(--el-text-color-placeholder)}.el-link{display:inline-flex;flex-direction:row;align-items:center;justify-content:center;vertical-align:middle;position:relative;text-decoration:none;outline:0;cursor:pointer;padding:0;font-size:var(--el-link-font-size);font-weight:var(--el-link-font-weight);color:var(--el-link-text-color)}.el-link:hover{color:var(--el-link-hover-text-color)}.el-link.is-underline:hover:after{content:\"\";position:absolute;left:0;right:0;height:0;bottom:0;border-bottom:1px solid var(--el-link-hover-text-color)}.el-link.is-disabled{color:var(--el-link-disabled-text-color);cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default:after{border-color:var(--el-link-hover-text-color)}.el-link__inner{display:inline-flex;justify-content:center;align-items:center}.el-link.el-link--primary{--el-link-text-color:var(--el-color-primary);--el-link-hover-text-color:var(--el-color-primary-light-3);--el-link-disabled-text-color:var(--el-color-primary-light-5)}.el-link.el-link--primary:after{border-color:var(--el-link-text-color)}.el-link.el-link--primary.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--success{--el-link-text-color:var(--el-color-success);--el-link-hover-text-color:var(--el-color-success-light-3);--el-link-disabled-text-color:var(--el-color-success-light-5)}.el-link.el-link--success:after{border-color:var(--el-link-text-color)}.el-link.el-link--success.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--warning{--el-link-text-color:var(--el-color-warning);--el-link-hover-text-color:var(--el-color-warning-light-3);--el-link-disabled-text-color:var(--el-color-warning-light-5)}.el-link.el-link--warning:after{border-color:var(--el-link-text-color)}.el-link.el-link--warning.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--danger{--el-link-text-color:var(--el-color-danger);--el-link-hover-text-color:var(--el-color-danger-light-3);--el-link-disabled-text-color:var(--el-color-danger-light-5)}.el-link.el-link--danger:after{border-color:var(--el-link-text-color)}.el-link.el-link--danger.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--error{--el-link-text-color:var(--el-color-error);--el-link-hover-text-color:var(--el-color-error-light-3);--el-link-disabled-text-color:var(--el-color-error-light-5)}.el-link.el-link--error:after{border-color:var(--el-link-text-color)}.el-link.el-link--error.is-underline:hover:after{border-color:var(--el-link-text-color)}.el-link.el-link--info{--el-link-text-color:var(--el-color-info);--el-link-hover-text-color:var(--el-color-info-light-3);--el-link-disabled-text-color:var(--el-color-info-light-5)}.el-link.el-link--info:after{border-color:var(--el-link-text-color)}.el-link.el-link--info.is-underline:hover:after{border-color:var(--el-link-text-color)}:root{--el-loading-spinner-size:42px;--el-loading-fullscreen-spinner-size:50px}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:var(--el-mask-color);margin:0;top:0;right:0;bottom:0;left:0;transition:opacity var(--el-transition-duration)}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:calc((0px - var(--el-loading-fullscreen-spinner-size))/ 2)}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:var(--el-loading-fullscreen-spinner-size);width:var(--el-loading-fullscreen-spinner-size)}.el-loading-spinner{top:50%;margin-top:calc((0px - var(--el-loading-spinner-size))/ 2);width:100%;text-align:center;position:absolute}.el-loading-spinner .el-loading-text{color:var(--el-color-primary);margin:3px 0;font-size:14px}.el-loading-spinner .circular{display:inline;height:var(--el-loading-spinner-size);width:var(--el-loading-spinner-size);animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:var(--el-color-primary);stroke-linecap:round}.el-loading-spinner i{color:var(--el-color-primary)}.el-loading-fade-enter-from,.el-loading-fade-leave-to{opacity:0}@keyframes loading-rotate{to{transform:rotate(360deg)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}to{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-main{--el-main-padding:20px;display:block;flex:1;flex-basis:auto;overflow:auto;box-sizing:border-box;padding:var(--el-main-padding)}.el-menu{--el-menu-active-color:var(--el-color-primary);--el-menu-text-color:var(--el-text-color-primary);--el-menu-hover-text-color:var(--el-text-color-primary);--el-menu-bg-color:var(--el-fill-color-blank);--el-menu-hover-bg-color:var(--el-color-primary-light-9);--el-menu-item-height:56px;--el-menu-item-font-size:var(--el-font-size-base);--el-menu-item-hover-fill:var(--el-color-primary-light-9);--el-menu-border-color:var(--el-border-color);border-right:solid 1px var(--el-menu-border-color);list-style:none;position:relative;margin:0;padding-left:0;background-color:var(--el-menu-bg-color);box-sizing:border-box}.el-menu--horizontal{display:flex;flex-wrap:nowrap;border-bottom:solid 1px var(--el-menu-border-color);border-right:none}.el-menu--horizontal>.el-menu-item{display:inline-flex;justify-content:center;align-items:center;height:100%;margin:0;border-bottom:2px solid transparent;color:var(--el-menu-text-color)}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover{background-color:#fff}.el-menu--horizontal>.el-sub-menu:focus,.el-menu--horizontal>.el-sub-menu:hover{outline:0}.el-menu--horizontal>.el-sub-menu:hover .el-sub-menu__title{color:var(--el-menu-hover-text-color)}.el-menu--horizontal>.el-sub-menu.is-active .el-sub-menu__title{border-bottom:2px solid var(--el-menu-active-color);color:var(--el-menu-active-color)}.el-menu--horizontal>.el-sub-menu .el-sub-menu__title{height:100%;border-bottom:2px solid transparent;color:var(--el-menu-text-color)}.el-menu--horizontal>.el-sub-menu .el-sub-menu__title:hover{background-color:var(--el-bg-color-overlay)}.el-menu--horizontal>.el-sub-menu .el-sub-menu__icon-arrow{position:static;vertical-align:middle;margin-left:8px;margin-top:-3px}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-sub-menu__title{background-color:var(--el-menu-bg-color);display:flex;align-items:center;height:36px;padding:0 10px;color:var(--el-menu-text-color)}.el-menu--horizontal .el-menu .el-sub-menu__title{padding-right:40px}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-sub-menu.is-active>.el-sub-menu__title{color:var(--el-menu-active-color)}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{outline:0;color:var(--el-menu-hover-text-color);background-color:var(--el-menu-hover-bg-color)}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid var(--el-menu-active-color);color:var(--el-menu-active-color)!important}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon],.el-menu--collapse>.el-sub-menu>.el-sub-menu__title [class^=el-icon]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-sub-menu__icon-arrow,.el-menu--collapse>.el-sub-menu>.el-sub-menu__title .el-sub-menu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item>span,.el-menu--collapse>.el-sub-menu>.el-sub-menu__title>span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-menu .el-sub-menu{min-width:200px}.el-menu--collapse .el-sub-menu{position:relative}.el-menu--collapse .el-sub-menu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;z-index:10;border:1px solid var(--el-border-color-light);border-radius:var(--el-border-radius-small);box-shadow:var(--el-box-shadow-light)}.el-menu--collapse .el-sub-menu.is-opened>.el-sub-menu__title .el-sub-menu__icon-arrow{transform:none}.el-menu--collapse .el-sub-menu.is-active .el-sub-menu__title{color:var(--el-menu-active-color)}.el-menu--popup{z-index:100;min-width:200px;border:none;padding:5px 0;border-radius:var(--el-border-radius-small);box-shadow:var(--el-box-shadow-light)}.el-menu .el-icon{flex-shrink:0}.el-menu-item{display:flex;align-items:center;height:var(--el-menu-item-height);line-height:var(--el-menu-item-height);font-size:var(--el-menu-item-font-size);color:var(--el-menu-text-color);padding:0 20px;list-style:none;cursor:pointer;position:relative;transition:border-color var(--el-transition-duration),background-color var(--el-transition-duration),color var(--el-transition-duration);box-sizing:border-box;white-space:nowrap}.el-menu-item *{vertical-align:bottom}.el-menu-item i{color:inherit}.el-menu-item:focus,.el-menu-item:hover{outline:0}.el-menu-item:hover{background-color:var(--el-menu-hover-bg-color)}.el-menu-item.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-menu-item [class^=el-icon]{margin-right:5px;width:24px;text-align:center;font-size:18px;vertical-align:middle}.el-menu-item.is-active{color:var(--el-menu-active-color)}.el-menu-item.is-active i{color:inherit}.el-menu-item .el-menu-tooltip__trigger{position:absolute;left:0;top:0;height:100%;width:100%;display:inline-flex;align-items:center;box-sizing:border-box;padding:0 20px}.el-sub-menu{list-style:none;margin:0;padding-left:0}.el-sub-menu__title{display:flex;align-items:center;height:var(--el-menu-item-height);line-height:var(--el-menu-item-height);font-size:var(--el-menu-item-font-size);color:var(--el-menu-text-color);padding:0 20px;list-style:none;cursor:pointer;position:relative;transition:border-color var(--el-transition-duration),background-color var(--el-transition-duration),color var(--el-transition-duration);box-sizing:border-box;white-space:nowrap}.el-sub-menu__title *{vertical-align:bottom}.el-sub-menu__title i{color:inherit}.el-sub-menu__title:focus,.el-sub-menu__title:hover{outline:0}.el-sub-menu__title.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-sub-menu__title:hover{background-color:var(--el-menu-hover-bg-color)}.el-sub-menu .el-menu{border:none}.el-sub-menu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-sub-menu__hide-arrow .el-sub-menu__icon-arrow{display:none!important}.el-sub-menu.is-active .el-sub-menu__title{border-bottom-color:var(--el-menu-active-color)}.el-sub-menu.is-opened>.el-sub-menu__title .el-sub-menu__icon-arrow{transform:rotate(180deg)}.el-sub-menu.is-disabled .el-menu-item,.el-sub-menu.is-disabled .el-sub-menu__title{opacity:.25;cursor:not-allowed;background:0 0!important}.el-sub-menu .el-icon{vertical-align:middle;margin-right:5px;width:24px;text-align:center;font-size:18px}.el-sub-menu .el-icon.el-sub-menu__icon-more{margin-right:0!important}.el-sub-menu .el-sub-menu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;transition:transform var(--el-transition-duration);font-size:12px;margin-right:0;width:inherit}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding:7px 0 7px 20px;line-height:normal;font-size:12px;color:var(--el-text-color-secondary)}.horizontal-collapse-transition .el-sub-menu__title .el-sub-menu__icon-arrow{transition:var(--el-transition-duration-fast);opacity:0}.el-message-box{--el-messagebox-title-color:var(--el-text-color-primary);--el-messagebox-width:420px;--el-messagebox-border-radius:4px;--el-messagebox-font-size:var(--el-font-size-large);--el-messagebox-content-font-size:var(--el-font-size-base);--el-messagebox-content-color:var(--el-text-color-regular);--el-messagebox-error-font-size:12px;--el-messagebox-padding-primary:15px}.el-message-box{display:inline-block;width:var(--el-messagebox-width);padding-bottom:10px;vertical-align:middle;background-color:var(--el-bg-color);border-radius:var(--el-messagebox-border-radius);border:1px solid var(--el-border-color-lighter);font-size:var(--el-messagebox-font-size);box-shadow:var(--el-box-shadow-light);text-align:left;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-overlay.is-message-box .el-overlay-message-box{text-align:center;position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto}.el-overlay.is-message-box .el-overlay-message-box:after{content:\"\";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box.is-draggable .el-message-box__header{cursor:move;-webkit-user-select:none;user-select:none}.el-message-box__header{position:relative;padding:var(--el-messagebox-padding-primary);padding-bottom:10px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:var(--el-messagebox-font-size);line-height:1;color:var(--el-messagebox-title-color)}.el-message-box__headerbtn{position:absolute;top:var(--el-messagebox-padding-primary);right:var(--el-messagebox-padding-primary);padding:0;border:none;outline:0;background:0 0;font-size:var(--el-message-close-size,16px);cursor:pointer}.el-message-box__headerbtn .el-message-box__close{color:var(--el-color-info);font-size:inherit}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:var(--el-color-primary)}.el-message-box__content{padding:10px var(--el-messagebox-padding-primary);color:var(--el-messagebox-content-color);font-size:var(--el-messagebox-content-font-size)}.el-message-box__container{position:relative}.el-message-box__input{padding-top:15px}.el-message-box__input div.invalid>input{border-color:var(--el-color-error)}.el-message-box__input div.invalid>input:focus{border-color:var(--el-color-error)}.el-message-box__status{position:absolute;top:50%;transform:translateY(-50%);font-size:24px!important}.el-message-box__status:before{padding-left:1px}.el-message-box__status.el-icon{position:absolute}.el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px;word-break:break-word}.el-message-box__status.el-message-box-icon--success{--el-messagebox-color:var(--el-color-success);color:var(--el-messagebox-color)}.el-message-box__status.el-message-box-icon--info{--el-messagebox-color:var(--el-color-info);color:var(--el-messagebox-color)}.el-message-box__status.el-message-box-icon--warning{--el-messagebox-color:var(--el-color-warning);color:var(--el-messagebox-color)}.el-message-box__status.el-message-box-icon--error{--el-messagebox-color:var(--el-color-error);color:var(--el-messagebox-color)}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:24px}.el-message-box__errormsg{color:var(--el-color-error);font-size:var(--el-messagebox-error-font-size);min-height:18px;margin-top:2px}.el-message-box__btns{padding:5px 15px 0;display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{flex-direction:row-reverse}.el-message-box--center .el-message-box__title{position:relative;display:flex;align-items:center;justify-content:center}.el-message-box--center .el-message-box__status{position:relative;top:auto;padding-right:5px;text-align:center;transform:translateY(-1px)}.el-message-box--center .el-message-box__message{margin-left:0}.el-message-box--center .el-message-box__btns{justify-content:center}.el-message-box--center .el-message-box__content{padding-left:calc(var(--el-messagebox-padding-primary) + 12px);padding-right:calc(var(--el-messagebox-padding-primary) + 12px);text-align:center}.fade-in-linear-enter-active .el-overlay-message-box{animation:msgbox-fade-in var(--el-transition-duration)}.fade-in-linear-leave-active .el-overlay-message-box{animation:msgbox-fade-in var(--el-transition-duration) reverse}@keyframes msgbox-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes msgbox-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-message{--el-message-min-width:380px;--el-message-bg-color:var(--el-color-info-light-9);--el-message-border-color:var(--el-border-color-lighter);--el-message-padding:15px 15px 15px 20px;--el-message-close-size:16px;--el-message-close-icon-color:var(--el-text-color-placeholder);--el-message-close-hover-color:var(--el-text-color-secondary)}.el-message{min-width:var(--el-message-min-width);box-sizing:border-box;border-radius:var(--el-border-radius-base);border-width:var(--el-border-width-base);border-style:var(--el-border-style-base);border-color:var(--el-message-border-color);position:fixed;left:50%;top:20px;transform:translate(-50%);transition:opacity .3s,transform .4s,top .4s;background-color:var(--el-message-bg-color);transition:opacity var(--el-transition-duration),transform .4s,top .4s;padding:var(--el-message-padding);display:flex;align-items:center}.el-message.is-center{justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--success{--el-message-bg-color:var(--el-color-success-light-9);--el-message-border-color:var(--el-color-success-light-8);--el-message-text-color:var(--el-color-success)}.el-message--success .el-message__content,.el-message .el-message-icon--success{color:var(--el-message-text-color)}.el-message--info{--el-message-bg-color:var(--el-color-info-light-9);--el-message-border-color:var(--el-color-info-light-8);--el-message-text-color:var(--el-color-info)}.el-message--info .el-message__content,.el-message .el-message-icon--info{color:var(--el-message-text-color)}.el-message--warning{--el-message-bg-color:var(--el-color-warning-light-9);--el-message-border-color:var(--el-color-warning-light-8);--el-message-text-color:var(--el-color-warning)}.el-message--warning .el-message__content,.el-message .el-message-icon--warning{color:var(--el-message-text-color)}.el-message--error{--el-message-bg-color:var(--el-color-error-light-9);--el-message-border-color:var(--el-color-error-light-8);--el-message-text-color:var(--el-color-error)}.el-message--error .el-message__content,.el-message .el-message-icon--error{color:var(--el-message-text-color)}.el-message__icon{margin-right:10px}.el-message .el-message__badge{position:absolute;top:-8px;right:-8px}.el-message__content{padding:0;font-size:14px;line-height:1}.el-message__content:focus{outline-width:0}.el-message .el-message__closeBtn{position:absolute;top:50%;right:15px;transform:translateY(-50%);cursor:pointer;color:var(--el-message-close-icon-color);font-size:var(--el-message-close-size)}.el-message .el-message__closeBtn:focus{outline-width:0}.el-message .el-message__closeBtn:hover{color:var(--el-message-close-hover-color)}.el-message-fade-enter-from,.el-message-fade-leave-to{opacity:0;transform:translate(-50%,-100%)}.el-notification{--el-notification-width:330px;--el-notification-padding:14px 26px 14px 13px;--el-notification-radius:8px;--el-notification-shadow:var(--el-box-shadow-light);--el-notification-border-color:var(--el-border-color-lighter);--el-notification-icon-size:24px;--el-notification-close-font-size:var(--el-message-close-size, 16px);--el-notification-group-margin-left:13px;--el-notification-group-margin-right:8px;--el-notification-content-font-size:var(--el-font-size-base);--el-notification-content-color:var(--el-text-color-regular);--el-notification-title-font-size:16px;--el-notification-title-color:var(--el-text-color-primary);--el-notification-close-color:var(--el-text-color-secondary);--el-notification-close-hover-color:var(--el-text-color-regular)}.el-notification{display:flex;width:var(--el-notification-width);padding:var(--el-notification-padding);border-radius:var(--el-notification-radius);box-sizing:border-box;border:1px solid var(--el-notification-border-color);position:fixed;background-color:var(--el-bg-color-overlay);box-shadow:var(--el-notification-shadow);transition:opacity var(--el-transition-duration),transform var(--el-transition-duration),left var(--el-transition-duration),right var(--el-transition-duration),top .4s,bottom var(--el-transition-duration);overflow-wrap:anywhere;overflow:hidden;z-index:9999}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:var(--el-notification-group-margin-left);margin-right:var(--el-notification-group-margin-right)}.el-notification__title{font-weight:700;font-size:var(--el-notification-title-font-size);line-height:var(--el-notification-icon-size);color:var(--el-notification-title-color);margin:0}.el-notification__content{font-size:var(--el-notification-content-font-size);line-height:24px;margin:6px 0 0;color:var(--el-notification-content-color);text-align:justify}.el-notification__content p{margin:0}.el-notification .el-notification__icon{height:var(--el-notification-icon-size);width:var(--el-notification-icon-size);font-size:var(--el-notification-icon-size)}.el-notification .el-notification__closeBtn{position:absolute;top:18px;right:15px;cursor:pointer;color:var(--el-notification-close-color);font-size:var(--el-notification-close-font-size)}.el-notification .el-notification__closeBtn:hover{color:var(--el-notification-close-hover-color)}.el-notification .el-notification--success{--el-notification-icon-color:var(--el-color-success);color:var(--el-notification-icon-color)}.el-notification .el-notification--info{--el-notification-icon-color:var(--el-color-info);color:var(--el-notification-icon-color)}.el-notification .el-notification--warning{--el-notification-icon-color:var(--el-color-warning);color:var(--el-notification-icon-color)}.el-notification .el-notification--error{--el-notification-icon-color:var(--el-color-error);color:var(--el-notification-icon-color)}.el-notification-fade-enter-from.right{right:0;transform:translate(100%)}.el-notification-fade-enter-from.left{left:0;transform:translate(-100%)}.el-notification-fade-leave-to{opacity:0}.el-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:2000;height:100%;background-color:var(--el-overlay-color-lighter);overflow:auto}.el-overlay .el-overlay-root{height:0}.el-page-header{display:flex;line-height:24px}.el-page-header__left{display:flex;cursor:pointer;margin-right:40px;position:relative}.el-page-header__left:after{content:\"\";position:absolute;width:1px;height:16px;right:-20px;top:50%;transform:translateY(-50%);background-color:var(--el-border-color)}.el-page-header__icon{font-size:18px;margin-right:6px;display:flex;align-items:center}.el-page-header__icon .el-icon{font-size:inherit}.el-page-header__title{font-size:14px;font-weight:500}.el-page-header__content{font-size:18px;color:var(--el-text-color-primary)}.el-pagination{--el-pagination-font-size:14px;--el-pagination-bg-color:var(--el-fill-color-blank);--el-pagination-text-color:var(--el-text-color-primary);--el-pagination-border-radius:3px;--el-pagination-button-color:var(--el-text-color-primary);--el-pagination-button-width:32px;--el-pagination-button-height:32px;--el-pagination-button-disabled-color:var(--el-text-color-placeholder);--el-pagination-button-disabled-bg-color:var(--el-fill-color-blank);--el-pagination-button-bg-color:var(--el-fill-color);--el-pagination-hover-color:var(--el-color-primary);--el-pagination-height-extra-small:24px;--el-pagination-line-height-extra-small:var(--el-pagination-height-extra-small);white-space:nowrap;padding:2px 5px;color:var(--el-pagination-text-color);font-weight:400;display:flex;align-items:center}.el-pagination:after,.el-pagination:before{display:table;content:\"\"}.el-pagination:after{clear:both}.el-pagination button,.el-pagination span:not([class*=suffix]){display:flex;justify-content:center;align-items:center;font-size:var(--el-pagination-font-size);min-width:var(--el-pagination-button-width);height:var(--el-pagination-button-height);line-height:var(--el-pagination-button-height);box-sizing:border-box}.el-pagination .el-input__inner{text-align:center;-moz-appearance:textfield;line-height:normal}.el-pagination .el-select .el-input{width:128px}.el-pagination button{border:none;padding:0 6px;background:0 0}.el-pagination button:focus{outline:0}.el-pagination button:hover{color:var(--el-pagination-hover-color)}.el-pagination button:disabled{color:var(--el-pagination-button-disabled-color);background-color:var(--el-pagination-button-disabled-bg-color);cursor:not-allowed}.el-pagination .btn-next,.el-pagination .btn-prev{background:center center no-repeat;background-size:16px;background-color:var(--el-pagination-bg-color);cursor:pointer;margin:0;color:var(--el-pagination-button-color)}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px;font-weight:700;width:inherit}.el-pagination .el-pager li.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li.btn-quicknext,.el-pagination--small .el-pager li.btn-quickprev,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:var(--el-font-size-extra-small);line-height:var(--el-pagination-line-height-extra-small);height:var(--el-pagination-height-extra-small);min-width:24px}.el-pagination--small .arrow.is-disabled{visibility:hidden}.el-pagination--small .more:before,.el-pagination--small li.more:before{line-height:var(--el-pagination-line-height-extra-small)}.el-pagination--small button,.el-pagination--small span:not([class*=suffix]){height:var(--el-pagination-height-extra-small);line-height:var(--el-pagination-line-height-extra-small);font-size:var(--el-font-size-extra-small)}.el-pagination--small .el-pagination__editor{height:var(--el-pagination-line-height-extra-small)}.el-pagination--small .el-pagination__editor.el-input .el-input__inner{height:var(--el-pagination-height-extra-small)}.el-pagination--small .el-input--small,.el-pagination--small .el-input__inner{height:var(--el-pagination-height-extra-small)!important;line-height:var(--el-pagination-line-height-extra-small)}.el-pagination--small .el-input__suffix,.el-pagination--small .el-input__suffix .el-input__suffix-inner,.el-pagination--small .el-input__suffix .el-input__suffix-inner i.el-select__caret{line-height:var(--el-pagination-line-height-extra-small)}.el-pagination--small .el-select .el-input{width:100px}.el-pagination__sizes{margin:0 16px 0 0;font-weight:400;color:var(--el-text-color-regular)}.el-pagination__sizes+button.btn-prev[type=button]{margin-left:0}.el-pagination__sizes+.el-pager .number:first-child{margin-left:0}.el-pagination__sizes+.el-pager .number:last-child{margin-right:0}.el-pagination__total{margin-right:16px;font-weight:400;color:var(--el-text-color-regular)}.el-pagination__total+button.btn-prev[type=button]{margin-left:0}.el-pagination__total+.el-pager .number:first-child{margin-left:0}.el-pagination__total+.el-pager .number:last-child{margin-right:0}.el-pagination__total[disabled=true]{color:var(--el-text-color-placeholder)}.el-pagination__jump{margin-left:16px;font-weight:400;color:var(--el-text-color-regular)}.el-pagination__jump .el-input__inner{padding:0 3px}.el-pagination__jump[disabled=true]{color:var(--el-text-color-placeholder)}.el-pagination__rightwrapper{flex:1;display:flex;align-items:center;justify-content:flex-end}.el-pagination__editor{line-height:18px;margin:0 8px;height:var(--el-pagination-button-height);min-width:56px;text-align:center;box-sizing:border-box;border-radius:var(--el-pagination-border-radius)}.el-pagination__editor.el-input{width:50px}.el-pagination__editor.el-input .el-input__inner{height:var(--el-pagination-button-height)}.el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev,.el-pagination.is-background .el-pager li{margin:0 4px;background-color:var(--el-pagination-button-bg-color);color:var(--el-text-color-regular);min-width:32px;border-radius:2px}.el-pagination.is-background .btn-next.is-disabled,.el-pagination.is-background .btn-prev.is-disabled,.el-pagination.is-background .el-pager li.is-disabled{color:var(--el-text-color-placeholder);background-color:var(--el-disabled-bg-color)}.el-pagination.is-background .btn-next.is-first,.el-pagination.is-background .btn-prev.is-first,.el-pagination.is-background .el-pager li.is-first{margin-left:0}.el-pagination.is-background .btn-next.is-last,.el-pagination.is-background .btn-prev.is-last,.el-pagination.is-background .el-pager li.is-last{margin-right:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev{padding:0}.el-pagination.is-background .btn-next:disabled,.el-pagination.is-background .btn-prev:disabled{color:var(--el-text-color-placeholder);background-color:var(--el-disabled-bg-color)}.el-pagination.is-background .btn-next:hover:not([disabled]),.el-pagination.is-background .btn-prev:hover:not([disabled]){color:var(--el-pagination-hover-color)}.el-pagination.is-background .el-pager li:not(.is-disabled):hover{color:var(--el-pagination-hover-color)}.el-pagination.is-background .el-pager li:not(.is-disabled).is-active{background-color:var(--el-color-primary);color:var(--el-color-white);font-weight:700}.el-pagination.is-background.el-pagination--small .btn-next,.el-pagination.is-background.el-pagination--small .btn-prev,.el-pagination.is-background.el-pagination--small .el-pager li{min-width:24px}.el-pager{-webkit-user-select:none;user-select:none;list-style:none;font-size:0;padding:0;margin:0;display:flex;align-items:center}.el-pager li{padding:0 4px;background:var(--el-pagination-bg-color);display:flex;justify-content:center;align-items:center;font-size:var(--el-pagination-font-size);min-width:var(--el-pagination-button-width);height:var(--el-pagination-button-height);line-height:var(--el-pagination-button-height);box-sizing:border-box;cursor:pointer;text-align:center}.el-pager li.btn-quickprev:hover,.el-pager li.btn-quicknext:hover{cursor:pointer}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:32px;color:var(--el-pagination-button-color)}.el-pager li.btn-quicknext.is-disabled,.el-pager li.btn-quickprev.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-pager li.btn-quicknext svg,.el-pager li.btn-quickprev svg{pointer-events:none}.el-pager li.is-active+li{border-left:0}.el-pager li:focus-visible{outline:1px solid var(--el-pagination-hover-color)}.el-pager li:hover{color:var(--el-pagination-hover-color)}.el-pager li.is-active{color:var(--el-pagination-hover-color);cursor:default}.el-pager+button.btn-next[type=button]{margin-right:0}.el-popconfirm__main{display:flex;align-items:center}.el-popconfirm__icon{margin-right:5px}.el-popconfirm__action{text-align:right;margin-top:8px}.el-popover{--el-popover-bg-color:var(--el-color-white);--el-popover-font-size:var(--el-font-size-base);--el-popover-border-color:var(--el-border-color-lighter);--el-popover-padding:12px;--el-popover-padding-large:18px 20px;--el-popover-title-font-size:16px;--el-popover-title-text-color:var(--el-text-color-primary);--el-popover-border-radius:4px}.el-popover.el-popper{background:var(--el-popover-bg-color);min-width:150px;border-radius:var(--el-popover-border-radius);border:1px solid var(--el-popover-border-color);padding:var(--el-popover-padding);z-index:var(--el-index-popper);color:var(--el-text-color-regular);line-height:1.4;text-align:justify;font-size:var(--el-popover-font-size);box-shadow:var(--el-box-shadow-light);word-break:break-all}.el-popover.el-popper--plain{padding:var(--el-popover-padding-large)}.el-popover__title{color:var(--el-popover-title-text-color);font-size:var(--el-popover-title-font-size);line-height:1;margin-bottom:12px}.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing){outline-width:0}.el-popover.el-popper:focus,.el-popover.el-popper:focus:active{outline-width:0}.el-progress{position:relative;line-height:1;display:flex;align-items:center}.el-progress__text{font-size:14px;color:var(--el-text-color-regular);margin-left:5px;min-width:50px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle,.el-progress--dashboard{display:inline-block}.el-progress--circle .el-progress__text,.el-progress--dashboard .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;transform:translateY(-50%)}.el-progress--circle .el-progress__text i,.el-progress--dashboard .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:var(--el-color-success)}.el-progress.is-success .el-progress__text{color:var(--el-color-success)}.el-progress.is-warning .el-progress-bar__inner{background-color:var(--el-color-warning)}.el-progress.is-warning .el-progress__text{color:var(--el-color-warning)}.el-progress.is-exception .el-progress-bar__inner{background-color:var(--el-color-danger)}.el-progress.is-exception .el-progress__text{color:var(--el-color-danger)}.el-progress-bar{flex-grow:1;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:var(--el-border-color-lighter);overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:var(--el-color-primary);text-align:right;border-radius:100px;line-height:1;white-space:nowrap;transition:width .6s ease}.el-progress-bar__inner:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-progress-bar__inner--indeterminate{transform:translateZ(0);animation:indeterminate 3s infinite}.el-progress-bar__innerText{display:inline-block;vertical-align:middle;color:#fff;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}to{background-position:32px 0}}@keyframes indeterminate{0%{left:-100%}to{left:100%}}.el-radio-button{--el-radio-button-checked-bg-color:var(--el-color-primary);--el-radio-button-checked-text-color:var(--el-color-white);--el-radio-button-checked-border-color:var(--el-color-primary);--el-radio-button-disabled-checked-fill:var(--el-border-color-extra-light)}.el-radio-button{position:relative;display:inline-block;outline:0}.el-radio-button__inner{display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;background:var(--el-button-bg-color,var(--el-fill-color-blank));border:var(--el-border);font-weight:var(--el-button-font-weight,var(--el-font-weight-primary));border-left:0;color:var(--el-button-text-color,var(--el-text-color-regular));-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;position:relative;cursor:pointer;transition:var(--el-transition-all);-webkit-user-select:none;user-select:none;padding:8px 15px;font-size:var(--el-font-size-base);border-radius:0}.el-radio-button__inner.is-round{padding:8px 15px}.el-radio-button__inner:hover{color:var(--el-color-primary)}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:var(--el-border);border-radius:var(--el-border-radius-base) 0 0 var(--el-border-radius-base);box-shadow:none!important}.el-radio-button__original-radio{opacity:0;outline:0;position:absolute;z-index:-1}.el-radio-button__original-radio:checked+.el-radio-button__inner{color:var(--el-radio-button-checked-text-color,var(--el-color-white));background-color:var(--el-radio-button-checked-bg-color,var(--el-color-primary));border-color:var(--el-radio-button-checked-border-color,var(--el-color-primary));box-shadow:-1px 0 0 0 var(--el-radio-button-checked-border-color,var(--el-color-primary))}.el-radio-button__original-radio:disabled+.el-radio-button__inner{color:var(--el-disabled-text-color);cursor:not-allowed;background-image:none;background-color:var(--el-button-disabled-bg-color,var(--el-fill-color-blank));border-color:var(--el-button-disabled-border-color,var(--el-border-color-light));box-shadow:none}.el-radio-button__original-radio:disabled:checked+.el-radio-button__inner{background-color:var(--el-radio-button-disabled-checked-fill)}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 var(--el-border-radius-base) var(--el-border-radius-base) 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:var(--el-border-radius-base)}.el-radio-button--large .el-radio-button__inner{padding:12px 19px;font-size:var(--el-font-size-base);border-radius:0}.el-radio-button--large .el-radio-button__inner.is-round{padding:12px 19px}.el-radio-button--small .el-radio-button__inner{padding:5px 11px;font-size:12px;border-radius:0}.el-radio-button--small .el-radio-button__inner.is-round{padding:5px 11px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){box-shadow:0 0 2px 2px var(--el-radio-button-checked-border-color)}.el-radio-group{display:inline-flex;align-items:center;flex-wrap:wrap;font-size:0}.el-radio{--el-radio-font-size:var(--el-font-size-base);--el-radio-text-color:var(--el-text-color-regular);--el-radio-font-weight:var(--el-font-weight-primary);--el-radio-input-height:14px;--el-radio-input-width:14px;--el-radio-input-border-radius:var(--el-border-radius-circle);--el-radio-input-bg-color:var(--el-fill-color-blank);--el-radio-input-border:var(--el-border);--el-radio-input-border-color:var(--el-border-color);--el-radio-input-border-color-hover:var(--el-color-primary)}.el-radio{color:var(--el-radio-text-color);font-weight:var(--el-radio-font-weight);position:relative;cursor:pointer;display:inline-flex;align-items:center;white-space:nowrap;outline:0;font-size:var(--el-font-size-base);-webkit-user-select:none;user-select:none;margin-right:32px;height:32px}.el-radio.el-radio--large{height:40px}.el-radio.el-radio--small{height:24px}.el-radio.is-bordered{padding:0 15px 0 9px;border-radius:var(--el-border-radius-base);border:var(--el-border);box-sizing:border-box}.el-radio.is-bordered.is-checked{border-color:var(--el-color-primary)}.el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:var(--el-border-color-lighter)}.el-radio.is-bordered.el-radio--large{padding:0 19px 0 11px;border-radius:var(--el-border-radius-base)}.el-radio.is-bordered.el-radio--large .el-radio__label{font-size:var(--el-font-size-base)}.el-radio.is-bordered.el-radio--large .el-radio__inner{height:14px;width:14px}.el-radio.is-bordered.el-radio--small{padding:0 11px 0 7px;border-radius:var(--el-border-radius-base)}.el-radio.is-bordered.el-radio--small .el-radio__label{font-size:12px}.el-radio.is-bordered.el-radio--small .el-radio__inner{height:12px;width:12px}.el-radio:last-child{margin-right:0}.el-radio__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-flex;position:relative;vertical-align:middle}.el-radio__input.is-disabled .el-radio__inner{background-color:var(--el-disabled-bg-color);border-color:var(--el-disabled-border-color);cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner:after{cursor:not-allowed;background-color:var(--el-disabled-bg-color)}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:var(--el-disabled-bg-color);border-color:var(--el-disabled-border-color)}.el-radio__input.is-disabled.is-checked .el-radio__inner:after{background-color:var(--el-text-color-placeholder)}.el-radio__input.is-disabled+span.el-radio__label{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{border-color:var(--el-color-primary);background:var(--el-color-primary)}.el-radio__input.is-checked .el-radio__inner:after{transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:var(--el-color-primary)}.el-radio__input.is-focus .el-radio__inner{border-color:var(--el-radio-input-border-color-hover)}.el-radio__inner{border:var(--el-radio-input-border);border-radius:var(--el-radio-input-border-radius);width:var(--el-radio-input-width);height:var(--el-radio-input-height);background-color:var(--el-radio-input-bg-color);position:relative;cursor:pointer;display:inline-block;box-sizing:border-box}.el-radio__inner:hover{border-color:var(--el-radio-input-border-color-hover)}.el-radio__inner:after{width:4px;height:4px;border-radius:var(--el-radio-input-border-radius);background-color:var(--el-color-white);content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) scale(0);transition:transform .15s ease-in}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{box-shadow:0 0 2px 2px var(--el-radio-input-border-color-hover)}.el-radio__label{font-size:var(--el-radio-font-size);padding-left:8px}.el-radio.el-radio--large .el-radio__label{font-size:14px}.el-radio.el-radio--large .el-radio__inner{width:14px;height:14px}.el-radio.el-radio--small .el-radio__label{font-size:12px}.el-radio.el-radio--small .el-radio__inner{width:12px;height:12px}.el-rate{--el-rate-height:20px;--el-rate-font-size:var(--el-font-size-base);--el-rate-icon-size:18px;--el-rate-icon-margin:6px;--el-rate-void-color:var(--el-border-color-darker);--el-rate-fill-color:#f7ba2a;--el-rate-disabled-void-color:var(--el-fill-color);--el-rate-text-color:var(--el-text-color-primary)}.el-rate{display:inline-flex;align-items:center;height:32px}.el-rate:active,.el-rate:focus{outline-width:0}.el-rate__item{cursor:pointer;display:inline-block;position:relative;font-size:0;vertical-align:middle;color:var(--el-rate-void-color)}.el-rate .el-rate__icon{position:relative;display:inline-block;font-size:var(--el-rate-icon-size);margin-right:var(--el-rate-icon-margin);transition:var(--el-transition-duration)}.el-rate .el-rate__icon.hover{transform:scale(1.15)}.el-rate .el-rate__icon .path2{position:absolute;left:0;top:0}.el-rate .el-rate__icon.is-active{color:var(--el-rate-fill-color)}.el-rate__decimal{position:absolute;top:0;left:0;display:inline-block;overflow:hidden;color:var(--el-rate-fill-color)}.el-rate__text{font-size:var(--el-rate-font-size);vertical-align:middle;color:var(--el-rate-text-color)}.el-rate--large{height:40px}.el-rate--small{height:24px}.el-rate.is-disabled .el-rate__item{cursor:auto;color:var(--el-rate-disabled-void-color)}.el-result{--el-result-padding:40px 30px;--el-result-icon-font-size:64px;--el-result-title-font-size:20px;--el-result-title-margin-top:20px;--el-result-subtitle-margin-top:10px;--el-result-extra-margin-top:30px}.el-result{display:flex;justify-content:center;align-items:center;flex-direction:column;text-align:center;box-sizing:border-box;padding:var(--el-result-padding)}.el-result__icon svg{width:var(--el-result-icon-font-size);height:var(--el-result-icon-font-size)}.el-result__title{margin-top:var(--el-result-title-margin-top)}.el-result__title p{margin:0;font-size:var(--el-result-title-font-size);color:var(--el-text-color-primary);line-height:1.3}.el-result__subtitle{margin-top:var(--el-result-subtitle-margin-top)}.el-result__subtitle p{margin:0;font-size:var(--el-font-size-base);color:var(--el-text-color-regular);line-height:1.3}.el-result__extra{margin-top:var(--el-result-extra-margin-top)}.el-result .icon-success{--el-result-color:var(--el-color-success);color:var(--el-result-color)}.el-result .icon-warning{--el-result-color:var(--el-color-warning);color:var(--el-result-color)}.el-result .icon-danger{--el-result-color:var(--el-color-danger);color:var(--el-result-color)}.el-result .icon-info{--el-result-color:var(--el-color-info);color:var(--el-result-color)}.el-result .icon-error{--el-result-color:var(--el-color-error);color:var(--el-result-color)}.el-row{display:flex;flex-wrap:wrap;position:relative;box-sizing:border-box}.el-row.is-justify-center{justify-content:center}.el-row.is-justify-end{justify-content:flex-end}.el-row.is-justify-space-between{justify-content:space-between}.el-row.is-justify-space-around{justify-content:space-around}.el-row.is-justify-space-evenly{justify-content:space-evenly}.el-row.is-align-middle{align-items:center}.el-row.is-align-bottom{align-items:flex-end}.el-scrollbar{--el-scrollbar-opacity:.3;--el-scrollbar-bg-color:var(--el-text-color-secondary);--el-scrollbar-hover-opacity:.5;--el-scrollbar-hover-bg-color:var(--el-text-color-secondary)}.el-scrollbar{overflow:hidden;position:relative;height:100%}.el-scrollbar__wrap{overflow:auto;height:100%}.el-scrollbar__wrap--hidden-default{scrollbar-width:none}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{display:none}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:var(--el-scrollbar-bg-color,var(--el-text-color-secondary));transition:var(--el-transition-duration) background-color;opacity:var(--el-scrollbar-opacity,.3)}.el-scrollbar__thumb:hover{background-color:var(--el-scrollbar-hover-bg-color,var(--el-text-color-secondary));opacity:var(--el-scrollbar-hover-opacity,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-scrollbar-fade-enter-active{transition:opacity .34s ease-out}.el-scrollbar-fade-leave-active{transition:opacity .12s ease-out}.el-scrollbar-fade-enter-from,.el-scrollbar-fade-leave-active{opacity:0}.el-select-dropdown__option-item:hover:not(.hover){background-color:transparent}.el-select-dropdown__list{list-style:none;margin:6px 0!important;padding:0!important;box-sizing:border-box}.el-select-dropdown__option-item{font-size:var(--el-select-font-size);padding:0 32px 0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--el-text-color-regular);height:34px;line-height:34px;box-sizing:border-box;cursor:pointer}.el-select-dropdown__option-item.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-select-dropdown__option-item.is-disabled:hover{background-color:var(--el-color-white)}.el-select-dropdown__option-item.is-selected{background-color:var(--el-fill-color-light);font-weight:700}.el-select-dropdown__option-item.is-selected:not(.is-multiple){color:var(--el-color-primary)}.el-select-dropdown__option-item.hover{background-color:var(--el-fill-color-light)!important}.el-select-dropdown__option-item:hover{background-color:var(--el-fill-color-light)}.el-select-dropdown.is-multiple .el-select-dropdown__option-item.is-selected{color:var(--el-color-primary);background-color:var(--el-bg-color-overlay)}.el-select-dropdown.is-multiple .el-select-dropdown__option-item.is-selected .el-icon{position:absolute;right:20px;top:0;height:inherit;font-size:12px}.el-select-dropdown.is-multiple .el-select-dropdown__option-item.is-selected .el-icon svg{height:inherit;vertical-align:middle}.el-select-group{margin:0;padding:0}.el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type):after{content:\"\";position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:var(--el-border-color-light)}.el-select-group__split-dash{position:absolute;left:20px;right:20px;height:1px;background:var(--el-border-color-light)}.el-select-group__title{padding-left:20px;font-size:12px;color:var(--el-color-info);line-height:30px}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select-v2{--el-select-border-color-hover:var(--el-border-color-hover);--el-select-disabled-border:var(--el-disabled-border-color);--el-select-font-size:var(--el-font-size-base);--el-select-close-hover-color:var(--el-text-color-secondary);--el-select-input-color:var(--el-text-color-placeholder);--el-select-multiple-input-color:var(--el-text-color-regular);--el-select-input-focus-border-color:var(--el-color-primary);--el-select-input-font-size:14px}.el-select-v2{display:inline-block;position:relative;vertical-align:middle;font-size:14px}.el-select-v2__wrapper{display:flex;align-items:center;flex-wrap:wrap;box-sizing:border-box;cursor:pointer;padding:1px 30px 1px 0;border:1px solid var(--el-border-color);border-radius:var(--el-border-radius-base);transition:border-color var(--el-transition-duration-fast) var(--el-ease-in-out-bezier-function)}.el-select-v2__wrapper:hover{border-color:var(--el-text-color-placeholder)}.el-select-v2__wrapper.is-filterable{cursor:text}.el-select-v2__wrapper.is-focused{border-color:var(--el-color-primary)}.el-select-v2__wrapper.is-hovering:not(.is-focused){border-color:var(--el-text-color-placeholder)}.el-select-v2__wrapper.is-disabled{cursor:not-allowed;background-color:var(--el-fill-color-light);color:var(--el-text-color-placeholder);border-color:var(--el-select-disabled-border)}.el-select-v2__wrapper.is-disabled:hover{border-color:var(--el-select-disabled-border)}.el-select-v2__wrapper.is-disabled.is-focus{border-color:var(--el-input-focus-border-color)}.el-select-v2__wrapper.is-disabled .is-transparent{opacity:1;-webkit-user-select:none;user-select:none}.el-select-v2__wrapper.is-disabled .el-select-v2__caret,.el-select-v2__wrapper.is-disabled .el-select-v2__combobox-input{cursor:not-allowed}.el-select-v2__wrapper .el-select-v2__input-wrapper{box-sizing:border-box;position:relative;margin-inline-start:12px;max-width:100%;overflow:hidden}.el-select-v2__wrapper,.el-select-v2__wrapper .el-select-v2__input-wrapper{line-height:32px}.el-select-v2__wrapper .el-select-v2__input-wrapper input{line-height:24px;height:24px;min-width:4px;width:100%;background-color:transparent;-webkit-appearance:none;appearance:none;background:0 0;border:none;margin:2px 0;outline:0;padding:0}.el-select-v2 .el-select-v2__tags-text{text-overflow:ellipsis;display:inline-flex;justify-content:center;align-items:center;overflow:hidden}.el-select-v2__empty{padding:10px 0;margin:0;text-align:center;color:var(--el-text-color-secondary);font-size:14px}.el-select-v2__popper.el-popper[role=tooltip]{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light);box-shadow:var(--el-box-shadow-light)}.el-select-v2__popper.el-popper[role=tooltip] .el-popper__arrow:before{border:1px solid var(--el-border-color-light)}.el-select-v2__popper.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-select-v2__popper.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-select-v2__popper.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-select-v2__popper.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-select-v2--large .el-select-v2__wrapper .el-select-v2__combobox-input{height:32px}.el-select-v2--large .el-select-v2__caret,.el-select-v2--large .el-select-v2__suffix{height:40px}.el-select-v2--large .el-select-v2__placeholder{font-size:14px;line-height:40px}.el-select-v2--small .el-select-v2__wrapper .el-select-v2__combobox-input{height:16px}.el-select-v2--small .el-select-v2__caret,.el-select-v2--small .el-select-v2__suffix{height:24px}.el-select-v2--small .el-select-v2__placeholder{font-size:12px;line-height:24px}.el-select-v2 .el-select-v2__selection>span{display:inline-block}.el-select-v2:hover .el-select-v2__combobox-input{border-color:var(--el-select-border-color-hover)}.el-select-v2 .el-select__selection-text{text-overflow:ellipsis;display:inline-block;overflow-x:hidden;vertical-align:bottom}.el-select-v2 .el-select-v2__combobox-input{padding-right:35px;display:block}.el-select-v2 .el-select-v2__combobox-input:focus{border-color:var(--el-select-input-focus-border-color)}.el-select-v2__input{border:none;outline:0;padding:0;margin-left:15px;color:var(--el-select-multiple-input-color);font-size:var(--el-select-font-size);-webkit-appearance:none;appearance:none;height:28px}.el-select-v2__input.is-small{height:14px}.el-select-v2__close{cursor:pointer;position:absolute;top:8px;z-index:var(--el-index-top);right:25px;color:var(--el-select-input-color);line-height:18px;font-size:var(--el-select-input-font-size)}.el-select-v2__close:hover{color:var(--el-select-close-hover-color)}.el-select-v2__suffix{display:inline-flex;position:absolute;right:12px;height:32px;top:50%;transform:translateY(-50%);color:var(--el-input-icon-color,var(--el-text-color-placeholder))}.el-select-v2__caret{color:var(--el-select-input-color);font-size:var(--el-select-input-font-size);transition:transform var(--el-transition-duration);transform:rotate(180deg);cursor:pointer}.el-select-v2__caret.is-reverse{transform:rotate(0)}.el-select-v2__caret.is-show-close{font-size:var(--el-select-font-size);text-align:center;transform:rotate(180deg);border-radius:var(--el-border-radius-circle);color:var(--el-select-input-color);transition:var(--el-transition-color)}.el-select-v2__caret.is-show-close:hover{color:--el-select-close-hover-color}.el-select-v2__caret.el-icon{height:inherit}.el-select-v2__caret.el-icon svg{vertical-align:middle}.el-select-v2__selection{white-space:normal;z-index:var(--el-index-normal);display:flex;align-items:center;flex-wrap:wrap}.el-select-v2__wrapper{background-color:var(--el-fill-color-blank);border:1px solid var(--el-border-color);border-radius:var(--el-border-radius-base);position:relative;transition:all var(--el-transition-duration) var(--el-ease-in-out-bezier-function)}.el-select-v2__input-calculator{left:0;position:absolute;top:0;visibility:hidden;white-space:pre;z-index:999}.el-select-v2__selected-item{line-height:inherit;height:inherit;-webkit-user-select:none;user-select:none;display:flex}.el-select-v2__placeholder{position:absolute;top:50%;transform:translateY(-50%);margin-inline-start:12px;width:calc(100% - 52px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--el-input-text-color,var(--el-text-color-regular))}.el-select-v2__placeholder.is-transparent{color:var(--el-text-color-placeholder)}.el-select-v2 .el-select-v2__selection .el-tag{box-sizing:border-box;border-color:transparent;margin:2px 0 2px 6px;background-color:var(--el-fill-color)}.el-select-v2 .el-select-v2__selection .el-tag .el-icon-close{background-color:var(--el-text-color-placeholder);right:-7px;color:var(--el-color-white)}.el-select-v2 .el-select-v2__selection .el-tag .el-icon-close:hover{background-color:var(--el-text-color-secondary)}.el-select-v2 .el-select-v2__selection .el-tag .el-icon-close:before{display:block;transform:translateY(.5px)}.el-select-v2.el-select-v2--small .el-select-v2__selection .el-tag{margin:1px 0 1px 6px;height:18px}.el-select-dropdown{z-index:calc(var(--el-index-top) + 1);border-radius:var(--el-border-radius-base);box-sizing:border-box}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:var(--el-color-primary);background-color:var(--el-bg-color-overlay)}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:var(--el-fill-color-light)}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected:after{content:\"\";position:absolute;top:50%;right:20px;border-top:none;border-right:none;background-repeat:no-repeat;background-position:center;background-color:var(--el-color-primary);-webkit-mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;mask-size:100% 100%;-webkit-mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;-webkit-mask-size:100% 100%;transform:translateY(-50%);width:12px;height:12px}.el-select-dropdown .el-select-dropdown__option-item.is-selected:after{content:\"\";position:absolute;top:50%;right:20px;border-top:none;border-right:none;background-repeat:no-repeat;background-position:center;background-color:var(--el-color-primary);-webkit-mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;mask-size:100% 100%;-webkit-mask:url(\"data:image/svg+xml;utf8,%3Csvg class='icon' width='200' height='200' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='currentColor' d='M406.656 706.944L195.84 496.256a32 32 0 10-45.248 45.248l256 256 512-512a32 32 0 00-45.248-45.248L406.592 706.944z'%3E%3C/path%3E%3C/svg%3E\") no-repeat;-webkit-mask-size:100% 100%;transform:translateY(-50%);width:12px;height:12px}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:var(--el-text-color-secondary);font-size:var(--el-select-font-size)}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;box-sizing:border-box}.el-select{--el-select-border-color-hover:var(--el-border-color-hover);--el-select-disabled-border:var(--el-disabled-border-color);--el-select-font-size:var(--el-font-size-base);--el-select-close-hover-color:var(--el-text-color-secondary);--el-select-input-color:var(--el-text-color-placeholder);--el-select-multiple-input-color:var(--el-text-color-regular);--el-select-input-focus-border-color:var(--el-color-primary);--el-select-input-font-size:14px}.el-select{display:inline-block;position:relative;line-height:32px}.el-select__popper.el-popper[role=tooltip]{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light);box-shadow:var(--el-box-shadow-light)}.el-select__popper.el-popper[role=tooltip] .el-popper__arrow:before{border:1px solid var(--el-border-color-light)}.el-select__popper.el-popper[role=tooltip][data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent;border-left-color:transparent}.el-select__popper.el-popper[role=tooltip][data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent;border-right-color:transparent}.el-select__popper.el-popper[role=tooltip][data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent;border-bottom-color:transparent}.el-select__popper.el-popper[role=tooltip][data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent;border-top-color:transparent}.el-select .el-select-tags-wrapper.has-prefix{margin-left:6px}.el-select--large{line-height:40px}.el-select--large .el-select-tags-wrapper.has-prefix{margin-left:8px}.el-select--small{line-height:24px}.el-select--small .el-select-tags-wrapper.has-prefix{margin-left:4px}.el-select .el-select__tags>span{display:inline-block}.el-select:hover:not(.el-select--disabled) .el-input__inner{box-shadow:0 0 0 1px var(--el-select-border-color-hover) inset}.el-select .el-select__tags-text{text-overflow:ellipsis;display:inline-flex;justify-content:center;align-items:center;overflow:hidden}.el-select .el-input__inner{cursor:pointer;display:inline-flex}.el-select .el-input__inner:focus{box-shadow:0 0 0 1px var(--el-select-input-focus-border-color) inset!important}.el-select .el-input{display:flex}.el-select .el-input .el-select__caret{color:var(--el-select-input-color);font-size:var(--el-select-input-font-size);transition:transform var(--el-transition-duration);transform:rotate(180deg);cursor:pointer}.el-select .el-input .el-select__caret.is-reverse{transform:rotate(0)}.el-select .el-input .el-select__caret.is-show-close{font-size:var(--el-select-font-size);text-align:center;transform:rotate(180deg);border-radius:var(--el-border-radius-circle);color:var(--el-select-input-color);transition:var(--el-transition-color)}.el-select .el-input .el-select__caret.is-show-close:hover{color:var(--el-select-close-hover-color)}.el-select .el-input .el-select__caret.el-icon{position:relative;height:inherit;z-index:2}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{box-shadow:0 0 0 1px var(--el-select-disabled-border) inset}.el-select .el-input.is-disabled .el-select__caret{cursor:not-allowed}.el-select .el-input.is-focus .el-input__inner{box-shadow:0 0 0 1px var(--el-select-input-focus-border-color) inset!important}.el-select__input{border:none;outline:0;padding:0;margin-left:15px;color:var(--el-select-multiple-input-color);font-size:var(--el-select-font-size);-webkit-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:var(--el-index-top);right:25px;color:var(--el-select-input-color);line-height:18px;font-size:var(--el-select-input-font-size)}.el-select__close:hover{color:var(--el-select-close-hover-color)}.el-select__tags{position:absolute;line-height:normal;top:50%;transform:translateY(-50%);white-space:normal;z-index:var(--el-index-normal);display:flex;align-items:center;flex-wrap:wrap}.el-select__collapse-tags{white-space:normal;z-index:var(--el-index-normal);display:flex;align-items:center;flex-wrap:wrap}.el-select__collapse-tag{line-height:inherit;height:inherit;display:flex}.el-select .el-select__tags .el-tag{box-sizing:border-box;border-color:transparent;margin:2px 6px 2px 0}.el-select .el-select__tags .el-tag:last-child{margin-right:0}.el-select .el-select__tags .el-tag .el-icon-close{background-color:var(--el-text-color-placeholder);right:-7px;top:0;color:#fff}.el-select .el-select__tags .el-tag .el-icon-close:hover{background-color:var(--el-text-color-secondary)}.el-select .el-select__tags .el-tag .el-icon-close:before{display:block;transform:translateY(.5px)}.el-select .el-select__tags .el-tag--info{background-color:var(--el-fill-color)}.el-skeleton{--el-skeleton-circle-size:var(--el-avatar-size)}.el-skeleton__item{background:var(--el-skeleton-color);display:inline-block;height:16px;border-radius:var(--el-border-radius-base);width:100%}.el-skeleton__circle{border-radius:50%;width:var(--el-skeleton-circle-size);height:var(--el-skeleton-circle-size);line-height:var(--el-skeleton-circle-size)}.el-skeleton__button{height:40px;width:64px;border-radius:4px}.el-skeleton__p{width:100%}.el-skeleton__p.is-last{width:61%}.el-skeleton__p.is-first{width:33%}.el-skeleton__text{width:100%;height:var(--el-font-size-small)}.el-skeleton__caption{height:var(--el-font-size-extra-small)}.el-skeleton__h1{height:var(--el-font-size-extra-large)}.el-skeleton__h3{height:var(--el-font-size-large)}.el-skeleton__h5{height:var(--el-font-size-medium)}.el-skeleton__image{width:unset;display:flex;align-items:center;justify-content:center;border-radius:0}.el-skeleton__image svg{color:var(--el-svg-monochrome-grey);fill:currentColor;width:22%;height:22%}.el-skeleton{--el-skeleton-color:var(--el-fill-color);--el-skeleton-to-color:var(--el-fill-color-darker)}@keyframes el-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.el-skeleton{width:100%}.el-skeleton__first-line,.el-skeleton__paragraph{height:16px;margin-top:16px;background:var(--el-skeleton-color)}.el-skeleton.is-animated .el-skeleton__item{background:linear-gradient(90deg,var(--el-skeleton-color) 25%,var(--el-skeleton-to-color) 37%,var(--el-skeleton-color) 63%);background-size:400% 100%;animation:el-skeleton-loading 1.4s ease infinite}.el-slider{--el-slider-main-bg-color:var(--el-color-primary);--el-slider-runway-bg-color:var(--el-border-color-light);--el-slider-stop-bg-color:var(--el-color-white);--el-slider-disabled-color:var(--el-text-color-placeholder);--el-slider-border-radius:3px;--el-slider-height:6px;--el-slider-button-size:20px;--el-slider-button-wrapper-size:36px;--el-slider-button-wrapper-offset:-15px}.el-slider{width:100%;height:32px;display:flex;align-items:center}.el-slider__runway{flex:1;height:var(--el-slider-height);background-color:var(--el-slider-runway-bg-color);border-radius:var(--el-slider-border-radius);position:relative;cursor:pointer}.el-slider__runway.show-input{margin-right:30px;width:auto}.el-slider__runway.is-disabled{cursor:default}.el-slider__runway.is-disabled .el-slider__bar{background-color:var(--el-slider-disabled-color)}.el-slider__runway.is-disabled .el-slider__button{border-color:var(--el-slider-disabled-color)}.el-slider__runway.is-disabled .el-slider__button-wrapper.hover,.el-slider__runway.is-disabled .el-slider__button-wrapper:hover,.el-slider__runway.is-disabled .el-slider__button-wrapper.dragging{cursor:not-allowed}.el-slider__runway.is-disabled .el-slider__button.dragging,.el-slider__runway.is-disabled .el-slider__button.hover,.el-slider__runway.is-disabled .el-slider__button:hover{transform:scale(1)}.el-slider__runway.is-disabled .el-slider__button.hover,.el-slider__runway.is-disabled .el-slider__button:hover,.el-slider__runway.is-disabled .el-slider__button.dragging{cursor:not-allowed}.el-slider__input{flex-shrink:0;width:130px}.el-slider__bar{height:var(--el-slider-height);background-color:var(--el-slider-main-bg-color);border-top-left-radius:var(--el-slider-border-radius);border-bottom-left-radius:var(--el-slider-border-radius);position:absolute}.el-slider__button-wrapper{height:var(--el-slider-button-wrapper-size);width:var(--el-slider-button-wrapper-size);position:absolute;z-index:1;top:var(--el-slider-button-wrapper-offset);transform:translate(-50%);background-color:transparent;text-align:center;-webkit-user-select:none;user-select:none;line-height:normal;outline:0}.el-slider__button-wrapper:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:grab}.el-slider__button-wrapper.dragging{cursor:grabbing}.el-slider__button{display:inline-block;width:var(--el-slider-button-size);height:var(--el-slider-button-size);vertical-align:middle;border:solid 2px var(--el-slider-main-bg-color);background-color:var(--el-color-white);border-radius:50%;box-sizing:border-box;transition:var(--el-transition-duration-fast);-webkit-user-select:none;user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{transform:scale(1.2)}.el-slider__button.hover,.el-slider__button:hover{cursor:grab}.el-slider__button.dragging{cursor:grabbing}.el-slider__stop{position:absolute;height:var(--el-slider-height);width:var(--el-slider-height);border-radius:var(--el-border-radius-circle);background-color:var(--el-slider-stop-bg-color);transform:translate(-50%)}.el-slider__marks{top:0;left:12px;width:18px;height:100%}.el-slider__marks-text{position:absolute;transform:translate(-50%);font-size:14px;color:var(--el-color-info);margin-top:15px}.el-slider.is-vertical{position:relative;height:100%;flex:0}.el-slider.is-vertical .el-slider__runway{width:var(--el-slider-height);height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:var(--el-slider-height);height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:var(--el-slider-button-wrapper-offset);transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{transform:translateY(50%)}.el-slider.is-vertical .el-slider__marks-text{margin-top:0;left:15px;transform:translateY(50%)}.el-slider--large{height:40px}.el-slider--small{height:24px}.el-space{display:inline-flex;vertical-align:top}.el-space__item{display:flex;flex-wrap:wrap}.el-space__item>*{flex:1}.el-space--vertical{flex-direction:column}.el-time-spinner{width:100%;white-space:nowrap}.el-spinner{display:inline-block;vertical-align:middle}.el-spinner-inner{animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:var(--el-border-color-lighter);stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{to{transform:rotate(360deg)}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-step{position:relative;flex-shrink:1}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{flex-basis:auto!important;flex-shrink:0;flex-grow:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{color:var(--el-text-color-primary);border-color:var(--el-text-color-primary)}.el-step__head.is-wait{color:var(--el-text-color-placeholder);border-color:var(--el-text-color-placeholder)}.el-step__head.is-success{color:var(--el-color-success);border-color:var(--el-color-success)}.el-step__head.is-error{color:var(--el-color-danger);border-color:var(--el-color-danger)}.el-step__head.is-finish{color:var(--el-color-primary);border-color:var(--el-color-primary)}.el-step__icon{position:relative;z-index:1;display:inline-flex;justify-content:center;align-items:center;width:24px;height:24px;font-size:14px;box-sizing:border-box;background:var(--el-bg-color-overlay);transition:.15s ease-out}.el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{display:inline-block;-webkit-user-select:none;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{transform:translateY(1px)}.el-step__line{position:absolute;border-color:inherit;background-color:var(--el-text-color-placeholder)}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;transition:.15s ease-out;box-sizing:border-box;width:0;height:0}.el-step__main{white-space:normal;text-align:left}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{font-weight:700;color:var(--el-text-color-primary)}.el-step__title.is-wait{color:var(--el-text-color-placeholder)}.el-step__title.is-success{color:var(--el-color-success)}.el-step__title.is-error{color:var(--el-color-danger)}.el-step__title.is-finish{color:var(--el-color-primary)}.el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.el-step__description.is-process{color:var(--el-text-color-primary)}.el-step__description.is-wait{color:var(--el-text-color-placeholder)}.el-step__description.is-success{color:var(--el-color-success)}.el-step__description.is-error{color:var(--el-color-danger)}.el-step__description.is-finish{color:var(--el-color-primary)}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.el-step.is-vertical{display:flex}.el-step.is-vertical .el-step__head{flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{padding-left:10px;flex-grow:1}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{display:flex;align-items:center}.el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.el-step.is-simple .el-step__icon{background:0 0;width:16px;height:16px;font-size:12px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{position:relative;display:flex;align-items:stretch;flex-grow:1}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{flex-grow:1;display:flex;align-items:center;justify-content:center}.el-step.is-simple .el-step__arrow:after,.el-step.is-simple .el-step__arrow:before{content:\"\";display:inline-block;position:absolute;height:15px;width:1px;background:var(--el-text-color-placeholder)}.el-step.is-simple .el-step__arrow:before{transform:rotate(-45deg) translateY(-4px);transform-origin:0 0}.el-step.is-simple .el-step__arrow:after{transform:rotate(45deg) translateY(4px);transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none}.el-steps{display:flex}.el-steps--simple{padding:13px 8%;border-radius:4px;background:var(--el-fill-color-light)}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{height:100%;flex-flow:column}.el-switch{--el-switch-on-color:var(--el-color-primary);--el-switch-off-color:var(--el-border-color);--el-switch-core-border-radius:10px;--el-switch-width:40px;--el-switch-height:20px;--el-switch-button-size:16px}.el-switch{display:inline-flex;align-items:center;position:relative;font-size:14px;line-height:var(--el-switch-height);height:32px;vertical-align:middle}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{transition:var(--el-transition-duration-fast);height:var(--el-switch-height);display:inline-block;font-size:14px;font-weight:500;cursor:pointer;vertical-align:middle;color:var(--el-text-color-primary)}.el-switch__label.is-active{color:var(--el-color-primary)}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{line-height:1;font-size:14px;display:inline-block}.el-switch__label .el-icon{height:inherit}.el-switch__label .el-icon svg{vertical-align:middle}.el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.el-switch__core{margin:0;display:inline-block;position:relative;width:var(--el-switch-width);height:var(--el-switch-height);border:1px solid var(--el-switch-off-color);outline:0;border-radius:var(--el-switch-core-border-radius);box-sizing:border-box;background:var(--el-switch-off-color);cursor:pointer;transition:border-color var(--el-transition-duration),background-color var(--el-transition-duration);vertical-align:middle}.el-switch__core .el-switch__inner{position:absolute;top:1px;left:1px;transition:all var(--el-transition-duration);width:var(--el-switch-button-size);height:var(--el-switch-button-size);display:flex;justify-content:center;align-items:center;left:50%;white-space:nowrap}.el-switch__core .el-switch__inner .is-icon,.el-switch__core .el-switch__inner .is-text{color:var(--el-color-white);transition:opacity var(--el-transition-duration);position:absolute;-webkit-user-select:none;user-select:none}.el-switch__core .el-switch__action{position:absolute;top:1px;left:1px;border-radius:var(--el-border-radius-circle);transition:all var(--el-transition-duration);width:var(--el-switch-button-size);height:var(--el-switch-button-size);background-color:var(--el-color-white);display:flex;justify-content:center;align-items:center;color:var(--el-switch-off-color)}.el-switch__core .el-switch__action .is-icon,.el-switch__core .el-switch__action .is-text{transition:opacity var(--el-transition-duration);position:absolute;-webkit-user-select:none;user-select:none}.el-switch__core .is-text{font-size:12px}.el-switch__core .is-show{opacity:1}.el-switch__core .is-hide{opacity:0}.el-switch.is-checked .el-switch__core{border-color:var(--el-switch-on-color);background-color:var(--el-switch-on-color)}.el-switch.is-checked .el-switch__core .el-switch__action{left:100%;margin-left:calc(-1px - var(--el-switch-button-size));color:var(--el-switch-on-color)}.el-switch.is-checked .el-switch__core .el-switch__inner{left:50%;white-space:nowrap;margin-left:calc(-1px - var(--el-switch-button-size))}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter-from,.el-switch .label-fade-leave-active{opacity:0}.el-switch--large{font-size:14px;height:40px}.el-switch--large .el-switch__label,.el-switch--large .el-switch__label *{font-size:14px}.el-switch--small{font-size:12px;height:24px}.el-switch--small .el-switch__label,.el-switch--small .el-switch__label *{font-size:12px}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:solid 1px var(--el-border-color-lighter);border-radius:2px;background-color:#fff;box-shadow:var(--el-box-shadow-light);box-sizing:border-box}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:var(--el-font-size-base)}.el-table-filter__list-item:hover{background-color:var(--el-color-primary-light-9);color:var(--el-color-primary-light-3)}.el-table-filter__list-item.is-active{background-color:var(--el-color-primary);color:#fff}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid var(--el-border-color-lighter);padding:8px}.el-table-filter__bottom button{background:0 0;border:none;color:var(--el-text-color-regular);cursor:pointer;font-size:var(--el-font-size-small);padding:0 3px}.el-table-filter__bottom button:hover{color:var(--el-color-primary)}.el-table-filter__bottom button:focus{outline:0}.el-table-filter__bottom button.is-disabled{color:var(--el-disabled-text-color);cursor:not-allowed}.el-table-filter__wrap{max-height:280px}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:flex;align-items:center;margin-right:5px;margin-bottom:12px;margin-left:5px;height:unset}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-table{--el-table-border-color:var(--el-border-color-lighter);--el-table-border:1px solid var(--el-table-border-color);--el-table-text-color:var(--el-text-color-regular);--el-table-header-text-color:var(--el-text-color-secondary);--el-table-row-hover-bg-color:var(--el-fill-color-light);--el-table-current-row-bg-color:var(--el-color-primary-light-9);--el-table-header-bg-color:var(--el-fill-color-blank);--el-table-fixed-box-shadow:var(--el-box-shadow-light);--el-table-bg-color:var(--el-fill-color-blank);--el-table-tr-bg-color:var(--el-fill-color-blank);--el-table-expanded-cell-bg-color:var(--el-fill-color-blank);--el-table-fixed-left-column:inset 10px 0 10px -10px rgba(0, 0, 0, .15);--el-table-fixed-right-column:inset -10px 0 10px -10px rgba(0, 0, 0, .15)}.el-table{position:relative;overflow:hidden;box-sizing:border-box;height:-moz-fit-content;height:fit-content;width:100%;max-width:100%;background-color:var(--el-table-bg-color);font-size:14px;color:var(--el-table-text-color)}.el-table__inner-wrapper{position:relative}.el-table__inner-wrapper:before{left:0;bottom:0;width:100%;height:1px;z-index:3}.el-table.has-footer .el-table__inner-wrapper:before{bottom:1px}.el-table__empty-block{position:sticky;left:0;min-height:60px;text-align:center;width:100%;display:flex;justify-content:center;align-items:center}.el-table__empty-text{line-height:60px;width:50%;color:var(--el-text-color-secondary)}.el-table__expand-column .cell{padding:0;text-align:center;-webkit-user-select:none;user-select:none}.el-table__expand-icon{position:relative;cursor:pointer;color:var(--el-text-color-regular);font-size:12px;transition:transform var(--el-transition-duration-fast) ease-in-out;height:20px}.el-table__expand-icon--expanded{transform:rotate(90deg)}.el-table__expand-icon>.el-icon{font-size:12px}.el-table__expanded-cell{background-color:var(--el-table-expanded-cell-bg-color)}.el-table__expanded-cell[class*=cell]{padding:20px 50px}.el-table__expanded-cell:hover{background-color:transparent!important}.el-table__placeholder{display:inline-block;width:20px}.el-table__append-wrapper{overflow:hidden}.el-table--fit{border-right:0;border-bottom:0}.el-table--fit .el-table__cell.gutter{border-right-width:1px}.el-table thead{color:var(--el-table-header-text-color);font-weight:500}.el-table thead.is-group th.el-table__cell{background:var(--el-fill-color-light)}.el-table .el-table__cell{padding:8px 0;min-width:0;box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;position:relative;text-align:left;z-index:1}.el-table .el-table__cell.is-center{text-align:center}.el-table .el-table__cell.is-right{text-align:right}.el-table .el-table__cell.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table .el-table__cell.is-hidden>*{visibility:hidden}.el-table .cell{box-sizing:border-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;word-break:break-all;line-height:23px;padding:0 12px}.el-table .cell.el-tooltip{white-space:nowrap;min-width:50px}.el-table--large{font-size:var(--el-font-size-base)}.el-table--large .el-table__cell{padding:12px 0}.el-table--large .cell{padding:0 16px}.el-table--small{font-size:12px}.el-table--small .el-table__cell{padding:4px 0}.el-table--small .cell{padding:0 8px}.el-table tr{background-color:var(--el-table-tr-bg-color)}.el-table tr input[type=checkbox]{margin:0}.el-table td.el-table__cell,.el-table th.el-table__cell.is-leaf{border-bottom:var(--el-table-border)}.el-table th.el-table__cell.is-sortable{cursor:pointer}.el-table th.el-table__cell{-webkit-user-select:none;user-select:none;background-color:var(--el-table-header-bg-color)}.el-table th.el-table__cell>.cell{display:inline-block;box-sizing:border-box;position:relative;vertical-align:middle;width:100%}.el-table th.el-table__cell>.cell.highlight{color:var(--el-color-primary)}.el-table th.el-table__cell.required>div:before{display:inline-block;content:\"\";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table td.el-table__cell div{box-sizing:border-box}.el-table td.el-table__cell.gutter{width:0}.el-table--border .el-table__footer-wrapper tr:first-child td:first-child,.el-table--border .el-table__footer-wrapper tr:first-child th:first-child,.el-table--border .el-table__inner-wrapper tr:first-child td:first-child,.el-table--border .el-table__inner-wrapper tr:first-child th:first-child,.el-table--group .el-table__footer-wrapper tr:first-child td:first-child,.el-table--group .el-table__footer-wrapper tr:first-child th:first-child,.el-table--group .el-table__inner-wrapper tr:first-child td:first-child,.el-table--group .el-table__inner-wrapper tr:first-child th:first-child{border-left:var(--el-table-border)}.el-table--border .el-table__footer-wrapper,.el-table--group .el-table__footer-wrapper{border-top:var(--el-table-border)}.el-table--border .el-table__inner-wrapper:after,.el-table--border:after,.el-table--border:before,.el-table__inner-wrapper:before{content:\"\";position:absolute;background-color:var(--el-table-border-color);z-index:3}.el-table--border .el-table__inner-wrapper:after{left:0;top:0;width:100%;height:1px;z-index:3}.el-table--border:before{top:-1px;left:0;width:1px;height:100%;z-index:3}.el-table--border:after{top:-1px;right:0;width:1px;height:100%;z-index:3}.el-table--border .el-table__inner-wrapper{border-right:none;border-bottom:none}.el-table--border .el-table__footer-wrapper{position:relative}.el-table--border .el-table__footer-wrapper{margin-top:-2px}.el-table--border .el-table__cell{border-right:var(--el-table-border)}.el-table--border .el-table__cell:first-child .cell{padding-left:10px}.el-table--border th.el-table__cell.gutter:last-of-type{border-bottom:var(--el-table-border);border-bottom-width:1px}.el-table--border th.el-table__cell{border-bottom:var(--el-table-border)}.el-table--hidden{visibility:hidden}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__body-wrapper tr td.el-table-fixed-column--left,.el-table__body-wrapper tr td.el-table-fixed-column--right,.el-table__body-wrapper tr th.el-table-fixed-column--left,.el-table__body-wrapper tr th.el-table-fixed-column--right,.el-table__footer-wrapper tr td.el-table-fixed-column--left,.el-table__footer-wrapper tr td.el-table-fixed-column--right,.el-table__footer-wrapper tr th.el-table-fixed-column--left,.el-table__footer-wrapper tr th.el-table-fixed-column--right,.el-table__header-wrapper tr td.el-table-fixed-column--left,.el-table__header-wrapper tr td.el-table-fixed-column--right,.el-table__header-wrapper tr th.el-table-fixed-column--left,.el-table__header-wrapper tr th.el-table-fixed-column--right{position:sticky!important;z-index:2;background:var(--el-bg-color)}.el-table__body-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__body-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__body-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__body-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--right.is-first-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--right.is-last-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--right.is-first-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--right.is-last-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--right.is-first-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--right.is-last-column:before{content:\"\";position:absolute;top:0;width:10px;bottom:-1px;overflow-x:hidden;overflow-y:hidden;box-shadow:none;touch-action:none;pointer-events:none}.el-table__body-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__body-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--right.is-first-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--right.is-first-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--left.is-first-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--right.is-first-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--left.is-first-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--right.is-first-column:before{left:-10px}.el-table__body-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__body-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__body-wrapper tr th.el-table-fixed-column--right.is-last-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__footer-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__footer-wrapper tr th.el-table-fixed-column--right.is-last-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--left.is-last-column:before,.el-table__header-wrapper tr td.el-table-fixed-column--right.is-last-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--left.is-last-column:before,.el-table__header-wrapper tr th.el-table-fixed-column--right.is-last-column:before{right:-10px;box-shadow:none}.el-table__body-wrapper tr td.el-table__fixed-right-patch,.el-table__body-wrapper tr th.el-table__fixed-right-patch,.el-table__footer-wrapper tr td.el-table__fixed-right-patch,.el-table__footer-wrapper tr th.el-table__fixed-right-patch,.el-table__header-wrapper tr td.el-table__fixed-right-patch,.el-table__header-wrapper tr th.el-table__fixed-right-patch{position:sticky!important;z-index:2;background:#fff;right:0}.el-table__header-wrapper tr th.el-table-fixed-column--left,.el-table__header-wrapper tr th.el-table-fixed-column--right{background-color:var(--el-table-header-bg-color)}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed;border-collapse:separate}.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table__footer-wrapper tbody td.el-table__cell,.el-table__header-wrapper tbody td.el-table__cell{background-color:var(--el-table-row-hover-bg-color);color:var(--el-table-text-color)}.el-table__body-wrapper .el-table-column--selection .el-checkbox,.el-table__header-wrapper .el-table-column--selection .el-checkbox{height:unset}.el-table.is-scrolling-left .el-table-fixed-column--right.is-first-column:before{box-shadow:var(--el-table-fixed-right-column)}.el-table.is-scrolling-left.el-table--border .el-table-fixed-column--left.is-last-column.el-table__cell{border-right:var(--el-table-border)}.el-table.is-scrolling-left th.el-table-fixed-column--left{background-color:var(--el-table-header-bg-color)}.el-table.is-scrolling-right .el-table-fixed-column--left.is-last-column:before{box-shadow:var(--el-table-fixed-left-column)}.el-table.is-scrolling-right .el-table-fixed-column--left.is-last-column.el-table__cell{border-right:none}.el-table.is-scrolling-right th.el-table-fixed-column--right{background-color:var(--el-table-header-bg-color)}.el-table.is-scrolling-middle .el-table-fixed-column--left.is-last-column.el-table__cell{border-right:none}.el-table.is-scrolling-middle .el-table-fixed-column--right.is-first-column:before{box-shadow:var(--el-table-fixed-right-column)}.el-table.is-scrolling-middle .el-table-fixed-column--left.is-last-column:before{box-shadow:var(--el-table-fixed-left-column)}.el-table.is-scrolling-none .el-table-fixed-column--left.is-first-column:before,.el-table.is-scrolling-none .el-table-fixed-column--left.is-last-column:before,.el-table.is-scrolling-none .el-table-fixed-column--right.is-first-column:before,.el-table.is-scrolling-none .el-table-fixed-column--right.is-last-column:before{box-shadow:none}.el-table.is-scrolling-none th.el-table-fixed-column--left,.el-table.is-scrolling-none th.el-table-fixed-column--right{background-color:var(--el-table-header-bg-color)}.el-table__body-wrapper{overflow:hidden;position:relative}.el-table__body-wrapper .el-scrollbar__bar{z-index:2}.el-table .caret-wrapper{display:inline-flex;flex-direction:column;align-items:center;height:14px;width:24px;vertical-align:middle;cursor:pointer;overflow:initial;position:relative}.el-table .sort-caret{width:0;height:0;border:solid 5px transparent;position:absolute;left:7px}.el-table .sort-caret.ascending{border-bottom-color:var(--el-text-color-placeholder);top:-5px}.el-table .sort-caret.descending{border-top-color:var(--el-text-color-placeholder);bottom:-3px}.el-table .ascending .sort-caret.ascending{border-bottom-color:var(--el-color-primary)}.el-table .descending .sort-caret.descending{border-top-color:var(--el-color-primary)}.el-table .hidden-columns{visibility:hidden;position:absolute;z-index:-1}.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{background:var(--el-fill-color-lighter)}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td.el-table__cell{background-color:var(--el-table-current-row-bg-color)}.el-table__body tr.hover-row.current-row>td.el-table__cell,.el-table__body tr.hover-row.el-table__row--striped.current-row>td.el-table__cell,.el-table__body tr.hover-row.el-table__row--striped>td.el-table__cell,.el-table__body tr.hover-row>td.el-table__cell{background-color:var(--el-table-row-hover-bg-color)}.el-table__body tr.current-row>td.el-table__cell{background-color:var(--el-table-current-row-bg-color)}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:var(--el-table-border);z-index:10}.el-table__column-filter-trigger{display:inline-block;cursor:pointer}.el-table__column-filter-trigger i{color:var(--el-color-info);font-size:14px;vertical-align:middle}.el-table__border-left-patch{top:0;left:0;width:1px;height:100%;z-index:3;position:absolute;background-color:var(--el-table-border-color)}.el-table__border-bottom-patch{left:0;height:1px;z-index:3;position:absolute;background-color:var(--el-table-border-color)}.el-table__border-right-patch{top:0;height:100%;width:1px;z-index:3;position:absolute;background-color:var(--el-table-border-color)}.el-table--enable-row-transition .el-table__body td.el-table__cell{transition:background-color .25s ease}.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell{background-color:var(--el-table-row-hover-bg-color)}.el-table [class*=el-table__row--level] .el-table__expand-icon{display:inline-block;width:12px;line-height:12px;height:12px;text-align:center;margin-right:8px}.el-tabs__header{padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:2px;background-color:var(--el-color-primary);z-index:1;transition:width var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier),transform var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier);list-style:none}.el-tabs__new-tab{display:flex;align-items:center;justify-content:center;float:right;border:1px solid var(--el-border-color);height:20px;width:20px;line-height:20px;margin:10px 0 10px 10px;border-radius:3px;text-align:center;font-size:12px;color:var(--el-text-color-primary);cursor:pointer;transition:all .15s}.el-tabs__new-tab .is-icon-plus{height:inherit;width:inherit;transform:scale(.8)}.el-tabs__new-tab .is-icon-plus svg{vertical-align:middle}.el-tabs__new-tab:hover{color:var(--el-color-primary)}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap:after{content:\"\";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:var(--el-border-color-light);z-index:var(--el-index-normal)}.el-tabs__nav-wrap.is-scrollable{padding:0 20px;box-sizing:border-box}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:var(--el-text-color-secondary)}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{white-space:nowrap;position:relative;transition:transform var(--el-transition-duration);float:left;z-index:calc(var(--el-index-normal) + 1)}.el-tabs__nav.is-stretch{min-width:100%;display:flex}.el-tabs__nav.is-stretch>*{flex:1;text-align:center}.el-tabs__item{padding:0 20px;height:40px;box-sizing:border-box;line-height:40px;display:inline-block;list-style:none;font-size:14px;font-weight:500;color:var(--el-text-color-primary);position:relative}.el-tabs__item:focus,.el-tabs__item:focus:active{outline:0}.el-tabs__item .is-icon-close{border-radius:50%;text-align:center;transition:all var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier);margin-left:5px}.el-tabs__item .is-icon-close:before{transform:scale(.9);display:inline-block}.el-tabs__item .is-icon-close:hover{background-color:var(--el-text-color-placeholder);color:#fff}.el-tabs__item .is-icon-close svg{margin-top:1px}.el-tabs__item.is-active{color:var(--el-color-primary)}.el-tabs__item:hover{color:var(--el-color-primary);cursor:pointer}.el-tabs__item.is-disabled{color:var(--el-disabled-text-color);cursor:default}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header{border-bottom:1px solid var(--el-border-color-light)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid var(--el-border-color-light);border-bottom:none;border-radius:4px 4px 0 0;box-sizing:border-box}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tabs--card>.el-tabs__header .el-tabs__item .is-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid var(--el-border-color-light);transition:color var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier),padding var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier)}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .is-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#fff}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .is-icon-close{width:14px}.el-tabs--border-card{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color)}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:var(--el-fill-color-light);border-bottom:1px solid var(--el-border-color-light);margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--border-card>.el-tabs__header .el-tabs__item{transition:all var(--el-transition-duration) var(--el-transition-function-ease-in-out-bezier);border:1px solid transparent;margin-top:-1px;color:var(--el-text-color-secondary)}.el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item+.el-tabs__item{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{color:var(--el-color-primary);background-color:var(--el-bg-color-overlay);border-right-color:var(--el-border-color);border-left-color:var(--el-border-color)}.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover{color:var(--el-color-primary)}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-disabled{color:var(--el-disabled-text-color)}.el-tabs--border-card>.el-tabs__header .is-scrollable .el-tabs__item:first-child{margin-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:nth-child(2),.el-tabs--bottom .el-tabs__item.is-top:nth-child(2),.el-tabs--top .el-tabs__item.is-bottom:nth-child(2),.el-tabs--top .el-tabs__item.is-top:nth-child(2){padding-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:last-child,.el-tabs--bottom .el-tabs__item.is-top:last-child,.el-tabs--top .el-tabs__item.is-bottom:last-child,.el-tabs--top .el-tabs__item.is-top:last-child{padding-right:0}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding-left:20px}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{padding-right:20px}.el-tabs--bottom .el-tabs__header.is-bottom{margin-bottom:0;margin-top:10px}.el-tabs--bottom.el-tabs--border-card .el-tabs__header.is-bottom{border-bottom:0;border-top:1px solid var(--el-border-color)}.el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap.is-bottom{margin-top:-1px;margin-bottom:0}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom:not(.is-active){border:1px solid transparent}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom{margin:0 -1px -1px}.el-tabs--left,.el-tabs--right{overflow:hidden}.el-tabs--left .el-tabs__header.is-left,.el-tabs--left .el-tabs__header.is-right,.el-tabs--left .el-tabs__nav-scroll,.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__header.is-left,.el-tabs--right .el-tabs__header.is-right,.el-tabs--right .el-tabs__nav-scroll,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{height:100%}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__active-bar.is-right,.el-tabs--right .el-tabs__active-bar.is-left,.el-tabs--right .el-tabs__active-bar.is-right{top:0;bottom:auto;width:2px;height:auto}.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{margin-bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{height:30px;line-height:30px;width:100%;text-align:center;cursor:pointer}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i{transform:rotate(90deg)}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{left:auto;top:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next{right:auto;bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--left .el-tabs__nav-wrap.is-right.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-right.is-scrollable{padding:30px 0}.el-tabs--left .el-tabs__nav-wrap.is-left:after,.el-tabs--left .el-tabs__nav-wrap.is-right:after,.el-tabs--right .el-tabs__nav-wrap.is-left:after,.el-tabs--right .el-tabs__nav-wrap.is-right:after{height:100%;width:2px;bottom:auto;top:0}.el-tabs--left .el-tabs__nav.is-left,.el-tabs--left .el-tabs__nav.is-right,.el-tabs--right .el-tabs__nav.is-left,.el-tabs--right .el-tabs__nav.is-right{float:none}.el-tabs--left .el-tabs__item.is-left,.el-tabs--left .el-tabs__item.is-right,.el-tabs--right .el-tabs__item.is-left,.el-tabs--right .el-tabs__item.is-right{display:block}.el-tabs--left .el-tabs__header.is-left{float:left;margin-bottom:0;margin-right:10px}.el-tabs--left .el-tabs__nav-wrap.is-left{margin-right:-1px}.el-tabs--left .el-tabs__nav-wrap.is-left:after{left:auto;right:0}.el-tabs--left .el-tabs__active-bar.is-left{right:0;left:auto}.el-tabs--left .el-tabs__item.is-left{text-align:right}.el-tabs--left.el-tabs--card .el-tabs__active-bar.is-left{display:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left{border-left:none;border-right:1px solid var(--el-border-color-light);border-bottom:none;border-top:1px solid var(--el-border-color-light);text-align:left}.el-tabs--left.el-tabs--card .el-tabs__item.is-left:first-child{border-right:1px solid var(--el-border-color-light);border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active{border:1px solid var(--el-border-color-light);border-right-color:#fff;border-left:none;border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:first-child{border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:last-child{border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__nav{border-radius:4px 0 0 4px;border-bottom:1px solid var(--el-border-color-light);border-right:none}.el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left{border-right:1px solid var(--el-border-color)}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left{border:1px solid transparent;margin:-1px 0 -1px -1px}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.el-tabs--right .el-tabs__header.is-right{float:right;margin-bottom:0;margin-left:10px}.el-tabs--right .el-tabs__nav-wrap.is-right{margin-left:-1px}.el-tabs--right .el-tabs__nav-wrap.is-right:after{left:0;right:auto}.el-tabs--right .el-tabs__active-bar.is-right{left:0}.el-tabs--right.el-tabs--card .el-tabs__active-bar.is-right{display:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right{border-bottom:none;border-top:1px solid var(--el-border-color-light)}.el-tabs--right.el-tabs--card .el-tabs__item.is-right:first-child{border-left:1px solid var(--el-border-color-light);border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active{border:1px solid var(--el-border-color-light);border-left-color:#fff;border-right:none;border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:first-child{border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:last-child{border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__nav{border-radius:0 4px 4px 0;border-bottom:1px solid var(--el-border-color-light);border-left:none}.el-tabs--right.el-tabs--border-card .el-tabs__header.is-right{border-left:1px solid var(--el-border-color)}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right{border:1px solid transparent;margin:-1px -1px -1px 0}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.slideInLeft-transition,.slideInRight-transition{display:inline-block}.slideInRight-enter{animation:slideInRight-enter var(--el-transition-duration)}.slideInRight-leave{position:absolute;left:0;right:0;animation:slideInRight-leave var(--el-transition-duration)}.slideInLeft-enter{animation:slideInLeft-enter var(--el-transition-duration)}.slideInLeft-leave{position:absolute;left:0;right:0;animation:slideInLeft-leave var(--el-transition-duration)}@keyframes slideInRight-enter{0%{opacity:0;transform-origin:0 0;transform:translate(100%)}to{opacity:1;transform-origin:0 0;transform:translate(0)}}@keyframes slideInRight-leave{0%{transform-origin:0 0;transform:translate(0);opacity:1}to{transform-origin:0 0;transform:translate(100%);opacity:0}}@keyframes slideInLeft-enter{0%{opacity:0;transform-origin:0 0;transform:translate(-100%)}to{opacity:1;transform-origin:0 0;transform:translate(0)}}@keyframes slideInLeft-leave{0%{transform-origin:0 0;transform:translate(0);opacity:1}to{transform-origin:0 0;transform:translate(-100%);opacity:0}}.el-tag{--el-tag-font-size:12px;--el-tag-border-radius:4px;--el-tag-border-radius-rounded:9999px}.el-tag{--el-tag-bg-color:var(--el-color-primary-light-9);--el-tag-border-color:var(--el-color-primary-light-8);--el-tag-text-color:var(--el-color-primary);--el-tag-hover-color:var(--el-color-primary);background-color:var(--el-tag-bg-color);border-color:var(--el-tag-border-color);color:var(--el-tag-text-color);display:inline-flex;justify-content:center;align-items:center;height:24px;padding:0 9px;font-size:var(--el-tag-font-size);line-height:1;border-width:1px;border-style:solid;border-radius:var(--el-tag-border-radius);box-sizing:border-box;white-space:nowrap;--el-icon-size:14px}.el-tag.el-tag--success{--el-tag-bg-color:var(--el-color-success-light-9);--el-tag-border-color:var(--el-color-success-light-8);--el-tag-text-color:var(--el-color-success);--el-tag-hover-color:var(--el-color-success)}.el-tag.el-tag--warning{--el-tag-bg-color:var(--el-color-warning-light-9);--el-tag-border-color:var(--el-color-warning-light-8);--el-tag-text-color:var(--el-color-warning);--el-tag-hover-color:var(--el-color-warning)}.el-tag.el-tag--danger{--el-tag-bg-color:var(--el-color-danger-light-9);--el-tag-border-color:var(--el-color-danger-light-8);--el-tag-text-color:var(--el-color-danger);--el-tag-hover-color:var(--el-color-danger)}.el-tag.el-tag--info{--el-tag-bg-color:var(--el-color-info-light-9);--el-tag-border-color:var(--el-color-info-light-8);--el-tag-text-color:var(--el-color-info);--el-tag-hover-color:var(--el-color-info)}.el-tag.el-tag--error{--el-tag-bg-color:var(--el-color-error-light-9);--el-tag-border-color:var(--el-color-error-light-8);--el-tag-text-color:var(--el-color-error);--el-tag-hover-color:var(--el-color-error)}.el-tag.is-hit{border-color:var(--el-color-primary)}.el-tag.is-round{border-radius:var(--el-tag-border-radius-rounded)}.el-tag .el-tag__close{color:var(--el-tag-text-color)}.el-tag .el-tag__close:hover{color:var(--el-color-white);background-color:var(--el-tag-hover-color)}.el-tag .el-icon{border-radius:50%;cursor:pointer;font-size:calc(var(--el-icon-size) - 2px);height:var(--el-icon-size);width:var(--el-icon-size)}.el-tag .el-tag__close{margin-left:6px}.el-tag--dark{--el-tag-bg-color:var(--el-color-primary);--el-tag-border-color:var(--el-color-primary);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-primary-light-3)}.el-tag--dark.el-tag--success{--el-tag-bg-color:var(--el-color-success);--el-tag-border-color:var(--el-color-success);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-success-light-3)}.el-tag--dark.el-tag--warning{--el-tag-bg-color:var(--el-color-warning);--el-tag-border-color:var(--el-color-warning);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-warning-light-3)}.el-tag--dark.el-tag--danger{--el-tag-bg-color:var(--el-color-danger);--el-tag-border-color:var(--el-color-danger);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-danger-light-3)}.el-tag--dark.el-tag--info{--el-tag-bg-color:var(--el-color-info);--el-tag-border-color:var(--el-color-info);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-info-light-3)}.el-tag--dark.el-tag--error{--el-tag-bg-color:var(--el-color-error);--el-tag-border-color:var(--el-color-error);--el-tag-text-color:var(--el-color-white);--el-tag-hover-color:var(--el-color-error-light-3)}.el-tag--plain{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-primary-light-5);--el-tag-text-color:var(--el-color-primary);--el-tag-hover-color:var(--el-color-primary)}.el-tag--plain.el-tag--success{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-success-light-5);--el-tag-text-color:var(--el-color-success);--el-tag-hover-color:var(--el-color-success)}.el-tag--plain.el-tag--warning{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-warning-light-5);--el-tag-text-color:var(--el-color-warning);--el-tag-hover-color:var(--el-color-warning)}.el-tag--plain.el-tag--danger{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-danger-light-5);--el-tag-text-color:var(--el-color-danger);--el-tag-hover-color:var(--el-color-danger)}.el-tag--plain.el-tag--info{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-info-light-5);--el-tag-text-color:var(--el-color-info);--el-tag-hover-color:var(--el-color-info)}.el-tag--plain.el-tag--error{--el-tag-bg-color:var(--el-color-white);--el-tag-border-color:var(--el-color-error-light-5);--el-tag-text-color:var(--el-color-error);--el-tag-hover-color:var(--el-color-error)}.el-tag.is-closable{padding-right:5px}.el-tag--large{padding:0 11px;height:32px;--el-icon-size:16px}.el-tag--large .el-tag__close{margin-left:8px}.el-tag--large.is-closable{padding-right:7px}.el-tag--small{padding:0 7px;height:20px;--el-icon-size:12px}.el-tag--small .el-tag__close{margin-left:4px}.el-tag--small.is-closable{padding-right:3px}.el-tag--small .el-icon-close{transform:scale(.8)}.el-tag.el-tag--success.is-hit{border-color:var(--el-color-success)}.el-tag.el-tag--warning.is-hit{border-color:var(--el-color-warning)}.el-tag.el-tag--danger.is-hit{border-color:var(--el-color-danger)}.el-tag.el-tag--info.is-hit{border-color:var(--el-color-info)}.el-tag.el-tag--error.is-hit{border-color:var(--el-color-error)}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px;line-height:20px}.time-select-item.disabled{color:var(--el-datepicker-border-color);cursor:not-allowed}.time-select-item:hover{background-color:var(--el-fill-color-light);font-weight:700;cursor:pointer}.time-select .time-select-item.selected:not(.disabled){color:var(--el-color-primary);font-weight:700}.el-timeline-item{position:relative;padding-bottom:20px}.el-timeline-item__wrapper{position:relative;padding-left:28px;top:-3px}.el-timeline-item__tail{position:absolute;left:4px;height:100%;border-left:2px solid var(--el-timeline-node-color)}.el-timeline-item .el-timeline-item__icon{color:var(--el-color-white);font-size:var(--el-font-size-small)}.el-timeline-item__node{position:absolute;background-color:var(--el-timeline-node-color);border-color:var(--el-timeline-node-color);border-radius:50%;box-sizing:border-box;display:flex;justify-content:center;align-items:center}.el-timeline-item__node--normal{left:-1px;width:var(--el-timeline-node-size-normal);height:var(--el-timeline-node-size-normal)}.el-timeline-item__node--large{left:-2px;width:var(--el-timeline-node-size-large);height:var(--el-timeline-node-size-large)}.el-timeline-item__node.is-hollow{background:var(--el-color-white);border-style:solid;border-width:2px}.el-timeline-item__node--primary{background-color:var(--el-color-primary);border-color:var(--el-color-primary)}.el-timeline-item__node--success{background-color:var(--el-color-success);border-color:var(--el-color-success)}.el-timeline-item__node--warning{background-color:var(--el-color-warning);border-color:var(--el-color-warning)}.el-timeline-item__node--danger{background-color:var(--el-color-danger);border-color:var(--el-color-danger)}.el-timeline-item__node--info{background-color:var(--el-color-info);border-color:var(--el-color-info)}.el-timeline-item__dot{position:absolute;display:flex;justify-content:center;align-items:center}.el-timeline-item__content{color:var(--el-text-color-primary)}.el-timeline-item__timestamp{color:var(--el-text-color-secondary);line-height:1;font-size:var(--el-font-size-small)}.el-timeline-item__timestamp.is-top{margin-bottom:8px;padding-top:4px}.el-timeline-item__timestamp.is-bottom{margin-top:8px}.el-timeline{--el-timeline-node-size-normal:12px;--el-timeline-node-size-large:14px;--el-timeline-node-color:var(--el-border-color-light)}.el-timeline{margin:0;font-size:var(--el-font-size-base);list-style:none}.el-timeline .el-timeline-item:last-child .el-timeline-item__tail{display:none}.el-timeline .el-timeline-item__center{display:flex;align-items:center}.el-timeline .el-timeline-item__center .el-timeline-item__wrapper{width:100%}.el-timeline .el-timeline-item__center .el-timeline-item__tail{top:0}.el-timeline .el-timeline-item__center:first-child .el-timeline-item__tail{height:calc(50% + 10px);top:calc(50% - 10px)}.el-timeline .el-timeline-item__center:last-child .el-timeline-item__tail{display:block;height:calc(50% - 10px)}.el-tooltip-v2__content{--el-tooltip-v2-padding:5px 10px;--el-tooltip-v2-border-radius:4px;--el-tooltip-v2-border-color:var(--el-border-color);border-radius:var(--el-tooltip-v2-border-radius);color:var(--el-color-black);background-color:var(--el-color-white);padding:var(--el-tooltip-v2-padding);border:1px solid var(--el-border-color)}.el-tooltip-v2__arrow{position:absolute;color:var(--el-color-white);width:var(--el-tooltip-v2-arrow-width);height:var(--el-tooltip-v2-arrow-height);pointer-events:none;left:var(--el-tooltip-v2-arrow-x);top:var(--el-tooltip-v2-arrow-y)}.el-tooltip-v2__arrow:before{content:\"\";width:0;height:0;border:var(--el-tooltip-v2-arrow-border-width) solid transparent;position:absolute}.el-tooltip-v2__arrow:after{content:\"\";width:0;height:0;border:var(--el-tooltip-v2-arrow-border-width) solid transparent;position:absolute}.el-tooltip-v2__content[data-side^=top] .el-tooltip-v2__arrow{bottom:0}.el-tooltip-v2__content[data-side^=top] .el-tooltip-v2__arrow:before{border-top-color:var(--el-color-white);border-top-width:var(--el-tooltip-v2-arrow-border-width);border-bottom:0;top:calc(100% - 1px)}.el-tooltip-v2__content[data-side^=top] .el-tooltip-v2__arrow:after{border-top-color:var(--el-border-color);border-top-width:var(--el-tooltip-v2-arrow-border-width);border-bottom:0;top:100%;z-index:-1}.el-tooltip-v2__content[data-side^=bottom] .el-tooltip-v2__arrow{top:0}.el-tooltip-v2__content[data-side^=bottom] .el-tooltip-v2__arrow:before{border-bottom-color:var(--el-color-white);border-bottom-width:var(--el-tooltip-v2-arrow-border-width);border-top:0;bottom:calc(100% - 1px)}.el-tooltip-v2__content[data-side^=bottom] .el-tooltip-v2__arrow:after{border-bottom-color:var(--el-border-color);border-bottom-width:var(--el-tooltip-v2-arrow-border-width);border-top:0;bottom:100%;z-index:-1}.el-tooltip-v2__content[data-side^=left] .el-tooltip-v2__arrow{right:0}.el-tooltip-v2__content[data-side^=left] .el-tooltip-v2__arrow:before{border-left-color:var(--el-color-white);border-left-width:var(--el-tooltip-v2-arrow-border-width);border-right:0;left:calc(100% - 1px)}.el-tooltip-v2__content[data-side^=left] .el-tooltip-v2__arrow:after{border-left-color:var(--el-border-color);border-left-width:var(--el-tooltip-v2-arrow-border-width);border-right:0;left:100%;z-index:-1}.el-tooltip-v2__content[data-side^=right] .el-tooltip-v2__arrow{left:0}.el-tooltip-v2__content[data-side^=right] .el-tooltip-v2__arrow:before{border-right-color:var(--el-color-white);border-right-width:var(--el-tooltip-v2-arrow-border-width);border-left:0;right:calc(100% - 1px)}.el-tooltip-v2__content[data-side^=right] .el-tooltip-v2__arrow:after{border-right-color:var(--el-border-color);border-right-width:var(--el-tooltip-v2-arrow-border-width);border-left:0;right:100%;z-index:-1}.el-tooltip-v2__content.is-dark{--el-tooltip-v2-border-color:transparent;background-color:var(--el-color-black);color:var(--el-color-white);border-color:transparent}.el-tooltip-v2__content.is-dark .el-tooltip-v2__arrow{background-color:var(--el-color-black);border-color:transparent}.el-transfer{--el-transfer-border-color:var(--el-border-color-lighter);--el-transfer-border-radius:var(--el-border-radius-base);--el-transfer-panel-width:200px;--el-transfer-panel-header-height:40px;--el-transfer-panel-header-bg-color:var(--el-fill-color-light);--el-transfer-panel-footer-height:40px;--el-transfer-panel-body-height:278px;--el-transfer-item-height:30px;--el-transfer-filter-height:32px}.el-transfer{font-size:var(--el-font-size-base)}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 30px}.el-transfer__button{vertical-align:top}.el-transfer__button:nth-child(2){margin:0 0 0 10px}.el-transfer__button i,.el-transfer__button span{font-size:14px}.el-transfer__button .el-icon+span{margin-left:0}.el-transfer-panel{overflow:hidden;background:var(--el-bg-color-overlay);display:inline-block;text-align:left;vertical-align:middle;width:var(--el-transfer-panel-width);max-height:100%;box-sizing:border-box;position:relative}.el-transfer-panel__body{height:var(--el-transfer-panel-body-height);border-left:1px solid var(--el-transfer-border-color);border-right:1px solid var(--el-transfer-border-color);border-bottom:1px solid var(--el-transfer-border-color);border-bottom-left-radius:var(--el-transfer-border-radius);border-bottom-right-radius:var(--el-transfer-border-radius);overflow:hidden}.el-transfer-panel__body.is-with-footer{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:var(--el-transfer-panel-body-height);overflow:auto;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:calc(100% - var(--el-transfer-filter-height) - 30px);padding-top:0}.el-transfer-panel__item{height:var(--el-transfer-item-height);line-height:var(--el-transfer-item-height);padding-left:15px;display:block!important}.el-transfer-panel__item+.el-transfer-panel__item{margin-left:0}.el-transfer-panel__item.el-checkbox{color:var(--el-text-color-regular)}.el-transfer-panel__item:hover{color:var(--el-color-primary)}.el-transfer-panel__item.el-checkbox .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;box-sizing:border-box;padding-left:22px;line-height:var(--el-transfer-item-height)}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.el-transfer-panel__filter{text-align:center;margin:15px;box-sizing:border-box;width:auto}.el-transfer-panel__filter .el-input__inner{height:var(--el-transfer-filter-height);width:100%;font-size:12px;display:inline-block;box-sizing:border-box;border-radius:calc(var(--el-transfer-filter-height)/ 2)}.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.el-transfer-panel .el-transfer-panel__header{display:flex;align-items:center;height:var(--el-transfer-panel-header-height);background:var(--el-transfer-panel-header-bg-color);margin:0;padding-left:15px;border:1px solid var(--el-transfer-border-color);border-top-left-radius:var(--el-transfer-border-radius);border-top-right-radius:var(--el-transfer-border-radius);box-sizing:border-box;color:var(--el-color-black)}.el-transfer-panel .el-transfer-panel__header .el-checkbox{position:relative;display:flex;width:100%;align-items:center}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{font-size:16px;color:var(--el-text-color-primary);font-weight:400}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{position:absolute;right:15px;top:50%;transform:translate3d(0,-50%,0);color:var(--el-text-color-secondary);font-size:12px;font-weight:400}.el-transfer-panel .el-transfer-panel__footer{height:var(--el-transfer-panel-footer-height);background:var(--el-bg-color-overlay);margin:0;padding:0;border:1px solid var(--el-transfer-border-color);border-bottom-left-radius:var(--el-transfer-border-radius);border-bottom-right-radius:var(--el-transfer-border-radius)}.el-transfer-panel .el-transfer-panel__footer:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:var(--el-text-color-regular)}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:var(--el-transfer-item-height);line-height:var(--el-transfer-item-height);padding:6px 15px 0;color:var(--el-text-color-secondary);text-align:center}.el-transfer-panel .el-checkbox__label{padding-left:8px}.el-transfer-panel .el-checkbox__inner{height:14px;width:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner:after{height:6px;width:3px;left:4px}.el-tree{--el-tree-node-hover-bg-color:var(--el-fill-color-light);--el-tree-text-color:var(--el-text-color-regular);--el-tree-expand-icon-color:var(--el-text-color-placeholder)}.el-tree{position:relative;cursor:default;background:var(--el-fill-color-blank);color:var(--el-tree-text-color)}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:var(--el-text-color-secondary);font-size:var(--el-font-size-base)}.el-tree__drop-indicator{position:absolute;left:0;right:0;height:1px;background-color:var(--el-color-primary)}.el-tree-node{white-space:nowrap;outline:0}.el-tree-node:focus>.el-tree-node__content{background-color:var(--el-tree-node-hover-bg-color)}.el-tree-node.is-drop-inner>.el-tree-node__content .el-tree-node__label{background-color:var(--el-color-primary);color:#fff}.el-tree-node__content{display:flex;align-items:center;height:26px;cursor:pointer}.el-tree-node__content>.el-tree-node__expand-icon{padding:6px;box-sizing:content-box}.el-tree-node__content>label.el-checkbox{margin-right:8px}.el-tree-node__content:hover{background-color:var(--el-tree-node-hover-bg-color)}.el-tree.is-dragging .el-tree-node__content{cursor:move}.el-tree.is-dragging .el-tree-node__content *{pointer-events:none}.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content{cursor:not-allowed}.el-tree-node__expand-icon{cursor:pointer;color:var(--el-tree-expand-icon-color);font-size:12px;transform:rotate(0);transition:transform var(--el-transition-duration) ease-in-out}.el-tree-node__expand-icon.expanded{transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.el-tree-node__expand-icon.is-hidden{visibility:hidden}.el-tree-node__label{font-size:var(--el-font-size-base)}.el-tree-node__loading-icon{margin-right:8px;font-size:var(--el-font-size-base);color:var(--el-tree-expand-icon-color)}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:var(--el-color-primary-light-9)}.el-tree-select{--el-tree-node-hover-bg-color:var(--el-fill-color-light);--el-tree-text-color:var(--el-text-color-regular);--el-tree-expand-icon-color:var(--el-text-color-placeholder)}.el-tree-select__popper .el-tree-node__expand-icon{margin-left:8px}.el-tree-select__popper .el-tree-node.is-checked>.el-tree-node__content .el-select-dropdown__item.selected:after{content:none}.el-tree-select__popper .el-select-dropdown__item{flex:1;background:0 0!important;padding-left:0;height:20px;line-height:20px}.el-upload{display:inline-flex;justify-content:center;align-items:center;cursor:pointer;outline:0}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:var(--el-text-color-regular);margin-top:7px}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0}.el-upload--picture-card{--el-upload-picture-card-size:148px;background-color:var(--el-fill-color-lighter);border:1px dashed var(--el-border-color-darker);border-radius:6px;box-sizing:border-box;width:var(--el-upload-picture-card-size);height:var(--el-upload-picture-card-size);cursor:pointer;vertical-align:top;display:inline-flex;justify-content:center;align-items:center}.el-upload--picture-card i{font-size:28px;color:var(--el-text-color-secondary)}.el-upload--picture-card:hover{border-color:var(--el-color-primary);color:var(--el-color-primary)}.el-upload:focus{border-color:var(--el-color-primary);color:var(--el-color-primary)}.el-upload:focus .el-upload-dragger{border-color:var(--el-color-primary)}.el-upload-dragger{background-color:var(--el-fill-color-blank);border:1px dashed var(--el-border-color);border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;cursor:pointer;position:relative;overflow:hidden}.el-upload-dragger .el-icon--upload{font-size:67px;color:var(--el-text-color-placeholder);margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:var(--el-border);margin-top:7px;padding-top:5px}.el-upload-dragger .el-upload__text{color:var(--el-text-color-regular);font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:var(--el-color-primary);font-style:normal}.el-upload-dragger:hover{border-color:var(--el-color-primary)}.el-upload-dragger.is-dragover{background-color:var(--el-color-primary-light-9);border:2px dashed var(--el-color-primary)}.el-upload-list{margin:10px 0 0;padding:0;list-style:none;position:relative}.el-upload-list__item{transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:var(--el-text-color-regular);margin-bottom:5px;position:relative;box-sizing:border-box;border-radius:4px;width:100%}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item .el-icon--upload-success{color:var(--el-color-success)}.el-upload-list__item .el-icon--close{display:none;position:absolute;right:5px;top:50%;cursor:pointer;opacity:.75;color:var(--el-text-color-regular);transition:opacity var(--el-transition-duration);transform:translateY(-50%)}.el-upload-list__item .el-icon--close:hover{opacity:1;color:var(--el-color-primary)}.el-upload-list__item .el-icon--close-tip{display:none;position:absolute;right:5px;font-size:12px;cursor:pointer;opacity:1;color:var(--el-color-primary);transform:translateY(-50%)}.el-upload-list__item:hover{background-color:var(--el-fill-color-light)}.el-upload-list__item:hover .el-icon--close{display:inline-flex}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item .el-upload-list__item-info{display:inline-flex;justify-content:center;flex-direction:column;width:100%;margin-left:4px}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:inline-flex}.el-upload-list__item.is-success .el-upload-list__item-name:focus,.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:var(--el-color-primary);cursor:pointer}.el-upload-list__item.is-success:focus:not(:hover) .el-icon-close-tip{display:inline-block}.el-upload-list__item.is-success:active,.el-upload-list__item.is-success:not(.focusing):focus{outline-width:0}.el-upload-list__item.is-success:active .el-icon--close-tip,.el-upload-list__item.is-success:not(.focusing):focus .el-icon--close-tip{display:none}.el-upload-list__item.is-success:hover .el-upload-list__item-status-label{display:none;opacity:0}.el-upload-list.is-disabled .el-upload-list__item-status-label,.el-upload-list.is-disabled .el-upload-list__item:hover{display:block}.el-upload-list__item-name{color:var(--el-text-color-regular);display:inline-flex;text-align:center;align-items:center;padding:0 4px;overflow:hidden;text-overflow:ellipsis;transition:color var(--el-transition-duration);white-space:nowrap;font-size:var(--el-font-size-base)}.el-upload-list__item-name .el-icon{margin-right:6px;color:var(--el-text-color-secondary)}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none;height:100%;justify-content:center;align-items:center;transition:opacity var(--el-transition-duration)}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:var(--el-text-color-regular);display:none}.el-upload-list__item-delete:hover{color:var(--el-color-primary)}.el-upload-list--picture-card{--el-upload-list-picture-card-size:148px;display:inline-flex;flex-wrap:wrap;margin:0}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:var(--el-fill-color-blank);border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;width:var(--el-upload-list-picture-card-size);height:var(--el-upload-list-picture-card-size);margin:0 8px 8px 0;padding:0;display:inline-flex}.el-upload-list--picture-card .el-upload-list__item .el-icon--check,.el-upload-list--picture-card .el-upload-list__item .el-icon--circle-check{color:#fff}.el-upload-list--picture-card .el-upload-list__item .el-icon--close{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{opacity:0;display:block}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%;object-fit:contain}.el-upload-list--picture-card .el-upload-list__item-status-label{right:-15px;top:-6px;width:40px;height:24px;background:var(--el-color-success);text-align:center;transform:rotate(45deg)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;transform:rotate(-45deg)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;display:inline-flex;justify-content:center;align-items:center;color:#fff;opacity:0;font-size:20px;background-color:var(--el-overlay-color-lighter);transition:opacity var(--el-transition-duration)}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:1rem}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-flex}.el-upload-list--picture-card .el-progress{top:50%;left:50%;transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;z-index:0;background-color:var(--el-fill-color-blank);border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;margin-top:10px;padding:10px}.el-upload-list--picture .el-upload-list__item .el-icon--check,.el-upload-list--picture .el-upload-list__item .el-icon--circle-check{color:#fff}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{opacity:0;display:block}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item .el-icon--close{top:5px;transform:translateY(0)}.el-upload-list--picture .el-upload-list__item-thumbnail{display:inline-flex;justify-content:center;align-items:center;width:70px;height:70px;object-fit:contain;position:relative;z-index:1;background-color:var(--el-color-white)}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:var(--el-color-success);text-align:center;transform:rotate(45deg)}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;transform:rotate(-45deg)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover__label{right:-15px;top:-6px;width:40px;height:24px;background:var(--el-color-success);text-align:center;transform:rotate(45deg)}.el-upload-cover__label i{font-size:12px;margin-top:11px;transform:rotate(-45deg);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:var(--el-overlay-color-light);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#fff;font-size:14px;cursor:pointer;vertical-align:middle;transition:var(--el-transition-md-fade);margin-top:60px}.el-upload-cover__interact .btn i{margin-top:0}.el-upload-cover__interact .btn span{opacity:0;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#fff;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:var(--el-text-color-primary)}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-vl__wrapper{position:relative}.el-vl__wrapper:hover .el-virtual-scrollbar,.el-vl__wrapper.always-on .el-virtual-scrollbar{opacity:1}.el-vl__window{scrollbar-width:none}.el-vl__window::-webkit-scrollbar{display:none}.el-virtual-scrollbar{opacity:0;transition:opacity .34s ease-out}.el-vg__wrapper{position:relative}.el-popper{--el-popper-border-radius:var(--el-popover-border-radius, 4px)}.el-popper{position:absolute;border-radius:var(--el-popper-border-radius);padding:5px 11px;z-index:2000;font-size:12px;line-height:20px;min-width:10px;word-wrap:break-word;visibility:visible}.el-popper.is-dark{color:var(--el-bg-color);background:var(--el-text-color-primary);border:1px solid var(--el-text-color-primary)}.el-popper.is-dark .el-popper__arrow:before{border:1px solid var(--el-text-color-primary);background:var(--el-text-color-primary);right:0}.el-popper.is-light{background:var(--el-bg-color-overlay);border:1px solid var(--el-border-color-light)}.el-popper.is-light .el-popper__arrow:before{border:1px solid var(--el-border-color-light);background:var(--el-bg-color-overlay);right:0}.el-popper.is-pure{padding:0}.el-popper__arrow{position:absolute;width:10px;height:10px;z-index:-1}.el-popper__arrow:before{position:absolute;width:10px;height:10px;z-index:-1;content:\" \";transform:rotate(45deg);background:var(--el-text-color-primary);box-sizing:border-box}.el-popper[data-popper-placement^=top]>.el-popper__arrow{bottom:-5px}.el-popper[data-popper-placement^=top]>.el-popper__arrow:before{border-bottom-right-radius:2px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow{top:-5px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow:before{border-top-left-radius:2px}.el-popper[data-popper-placement^=left]>.el-popper__arrow{right:-5px}.el-popper[data-popper-placement^=left]>.el-popper__arrow:before{border-top-right-radius:2px}.el-popper[data-popper-placement^=right]>.el-popper__arrow{left:-5px}.el-popper[data-popper-placement^=right]>.el-popper__arrow:before{border-bottom-left-radius:2px}.el-popper[data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent!important;border-left-color:transparent!important}.el-popper[data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent!important;border-right-color:transparent!important}.el-popper[data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent!important;border-bottom-color:transparent!important}.el-popper[data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent!important;border-top-color:transparent!important}.el-select-dropdown__item{font-size:var(--el-font-size-base);padding:0 32px 0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--el-text-color-regular);height:34px;line-height:34px;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.is-disabled{color:var(--el-text-color-placeholder);cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:var(--el-color-white)}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:var(--el-fill-color-light)}.el-select-dropdown__item.selected{color:var(--el-color-primary);font-weight:700}/*!\n* \n* ant-design-vue v2.2.8\n*\n* Copyright 2017-present, ant-design-vue.\n* All rights reserved.\n*\n*/[class^=ant-]::-ms-clear,[class*=ant-]::-ms-clear,[class^=ant-] input::-ms-clear,[class*=ant-] input::-ms-clear,[class^=ant-] input::-ms-reveal,[class*=ant-] input::-ms-reveal{display:none}[class^=ant-],[class*=ant-],[class^=ant-] *,[class*=ant-] *,[class^=ant-] *:before,[class*=ant-] *:before,[class^=ant-] *:after,[class*=ant-] *:after{box-sizing:border-box}html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width}body{margin:0;color:#000000d9;font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";font-variant:tabular-nums;line-height:1.5715;background-color:#fff;font-feature-settings:\"tnum\"}[tabindex=\"-1\"]:focus{outline:none!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;color:#000000d9;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#1890ff;text-decoration:none;background-color:transparent;outline:none;cursor:pointer;transition:color .3s;-webkit-text-decoration-skip:objects}a:hover{color:#40a9ff}a:active{color:#096dd9}a:active,a:hover{text-decoration:none;outline:0}a:focus{text-decoration:none;outline:0}a[disabled]{color:#00000040;cursor:not-allowed}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}a,area,button,[role=button],input:not([type=\"range\"]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;color:#00000073;text-align:left;caption-side:bottom}th{text-align:inherit}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}::-moz-selection{color:#fff;background:#1890ff}::selection{color:#fff;background:#1890ff}.clearfix:before,.clearfix:after{display:table;content:\"\"}.clearfix:after{clear:both}.anticon{display:inline-block;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.anticon>*{line-height:1}.anticon svg{display:inline-block}.anticon:before{display:none}.anticon .anticon-icon{display:block}.anticon[tabindex]{cursor:pointer}.anticon-spin:before{display:inline-block;-webkit-animation:loadingCircle 1s infinite linear;animation:loadingCircle 1s infinite linear}.anticon-spin{display:inline-block;-webkit-animation:loadingCircle 1s infinite linear;animation:loadingCircle 1s infinite linear}.ant-fade-enter,.ant-fade-appear,.ant-fade-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-fade-enter.ant-fade-enter-active,.ant-fade-appear.ant-fade-appear-active{-webkit-animation-name:antFadeIn;animation-name:antFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-fade-leave.ant-fade-leave-active{-webkit-animation-name:antFadeOut;animation-name:antFadeOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-fade-enter,.ant-fade-appear{opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}.ant-fade-leave{-webkit-animation-timing-function:linear;animation-timing-function:linear}.fade-enter,.fade-appear,.fade-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-enter.fade-enter-active,.fade-appear.fade-appear-active{-webkit-animation-name:antFadeIn;animation-name:antFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.fade-leave.fade-leave-active{-webkit-animation-name:antFadeOut;animation-name:antFadeOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.fade-enter,.fade-appear{opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}.fade-leave{-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes antFadeIn{0%{opacity:0}to{opacity:1}}@keyframes antFadeIn{0%{opacity:0}to{opacity:1}}@-webkit-keyframes antFadeOut{0%{opacity:1}to{opacity:0}}@keyframes antFadeOut{0%{opacity:1}to{opacity:0}}.ant-move-up-enter,.ant-move-up-appear,.ant-move-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-move-up-enter.ant-move-up-enter-active,.ant-move-up-appear.ant-move-up-appear-active{-webkit-animation-name:antMoveUpIn;animation-name:antMoveUpIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-move-up-leave.ant-move-up-leave-active{-webkit-animation-name:antMoveUpOut;animation-name:antMoveUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-move-up-enter,.ant-move-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-move-up-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-up-enter,.move-up-appear,.move-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-enter.move-up-enter-active,.move-up-appear.move-up-appear-active{-webkit-animation-name:antMoveUpIn;animation-name:antMoveUpIn;-webkit-animation-play-state:running;animation-play-state:running}.move-up-leave.move-up-leave-active{-webkit-animation-name:antMoveUpOut;animation-name:antMoveUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-up-enter,.move-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-up-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.ant-move-down-enter,.ant-move-down-appear,.ant-move-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-move-down-enter.ant-move-down-enter-active,.ant-move-down-appear.ant-move-down-appear-active{-webkit-animation-name:antMoveDownIn;animation-name:antMoveDownIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-move-down-leave.ant-move-down-leave-active{-webkit-animation-name:antMoveDownOut;animation-name:antMoveDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-move-down-enter,.ant-move-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-move-down-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-down-enter,.move-down-appear,.move-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-enter.move-down-enter-active,.move-down-appear.move-down-appear-active{-webkit-animation-name:antMoveDownIn;animation-name:antMoveDownIn;-webkit-animation-play-state:running;animation-play-state:running}.move-down-leave.move-down-leave-active{-webkit-animation-name:antMoveDownOut;animation-name:antMoveDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-down-enter,.move-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-down-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.ant-move-left-enter,.ant-move-left-appear,.ant-move-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-move-left-enter.ant-move-left-enter-active,.ant-move-left-appear.ant-move-left-appear-active{-webkit-animation-name:antMoveLeftIn;animation-name:antMoveLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-move-left-leave.ant-move-left-leave-active{-webkit-animation-name:antMoveLeftOut;animation-name:antMoveLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-move-left-enter,.ant-move-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-move-left-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-left-enter,.move-left-appear,.move-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-enter.move-left-enter-active,.move-left-appear.move-left-appear-active{-webkit-animation-name:antMoveLeftIn;animation-name:antMoveLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.move-left-leave.move-left-leave-active{-webkit-animation-name:antMoveLeftOut;animation-name:antMoveLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-left-enter,.move-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-left-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.ant-move-right-enter,.ant-move-right-appear,.ant-move-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-move-right-enter.ant-move-right-enter-active,.ant-move-right-appear.ant-move-right-appear-active{-webkit-animation-name:antMoveRightIn;animation-name:antMoveRightIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-move-right-leave.ant-move-right-leave-active{-webkit-animation-name:antMoveRightOut;animation-name:antMoveRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-move-right-enter,.ant-move-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-move-right-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-right-enter,.move-right-appear,.move-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-enter.move-right-enter-active,.move-right-appear.move-right-appear-active{-webkit-animation-name:antMoveRightIn;animation-name:antMoveRightIn;-webkit-animation-play-state:running;animation-play-state:running}.move-right-leave.move-right-leave-active{-webkit-animation-name:antMoveRightOut;animation-name:antMoveRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-right-enter,.move-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-right-leave{-webkit-animation-timing-function:cubic-bezier(.6,.04,.98,.34);animation-timing-function:cubic-bezier(.6,.04,.98,.34)}@-webkit-keyframes antMoveDownIn{0%{transform:translateY(100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@keyframes antMoveDownIn{0%{transform:translateY(100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveDownOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(100%);transform-origin:0 0;opacity:0}}@keyframes antMoveDownOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(100%);transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveLeftIn{0%{transform:translate(-100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@keyframes antMoveLeftIn{0%{transform:translate(-100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveLeftOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(-100%);transform-origin:0 0;opacity:0}}@keyframes antMoveLeftOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(-100%);transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveRightIn{0%{transform:translate(100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@keyframes antMoveRightIn{0%{transform:translate(100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveRightOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(100%);transform-origin:0 0;opacity:0}}@keyframes antMoveRightOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(100%);transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveUpIn{0%{transform:translateY(-100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@keyframes antMoveUpIn{0%{transform:translateY(-100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveUpOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(-100%);transform-origin:0 0;opacity:0}}@keyframes antMoveUpOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(-100%);transform-origin:0 0;opacity:0}}@-webkit-keyframes loadingCircle{to{transform:rotate(360deg)}}@keyframes loadingCircle{to{transform:rotate(360deg)}}[ant-click-animating=true],[ant-click-animating-without-extra-node=true]{position:relative}html{--antd-wave-shadow-color: #1890ff;--scroll-bar: 0}[ant-click-animating-without-extra-node=true]:after,.ant-click-animating-node{position:absolute;top:0;right:0;bottom:0;left:0;display:block;border-radius:inherit;box-shadow:0 0 #1890ff;box-shadow:0 0 0 0 var(--antd-wave-shadow-color);opacity:.2;-webkit-animation:fadeEffect 2s cubic-bezier(.08,.82,.17,1),waveEffect .4s cubic-bezier(.08,.82,.17,1);animation:fadeEffect 2s cubic-bezier(.08,.82,.17,1),waveEffect .4s cubic-bezier(.08,.82,.17,1);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;content:\"\";pointer-events:none}@-webkit-keyframes waveEffect{to{box-shadow:0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@keyframes waveEffect{to{box-shadow:0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@-webkit-keyframes fadeEffect{to{opacity:0}}@keyframes fadeEffect{to{opacity:0}}.slide-up-enter,.slide-up-appear,.slide-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-enter.slide-up-enter-active,.slide-up-appear.slide-up-appear-active{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-up-leave.slide-up-leave-active{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-up-enter,.slide-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-up-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-down-enter,.slide-down-appear,.slide-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-enter.slide-down-enter-active,.slide-down-appear.slide-down-appear-active{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-down-leave.slide-down-leave-active{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-down-enter,.slide-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-down-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-left-enter,.slide-left-appear,.slide-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-enter.slide-left-enter-active,.slide-left-appear.slide-left-appear-active{-webkit-animation-name:antSlideLeftIn;animation-name:antSlideLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-left-leave.slide-left-leave-active{-webkit-animation-name:antSlideLeftOut;animation-name:antSlideLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-left-enter,.slide-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-left-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-right-enter,.slide-right-appear,.slide-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-enter.slide-right-enter-active,.slide-right-appear.slide-right-appear-active{-webkit-animation-name:antSlideRightIn;animation-name:antSlideRightIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-right-leave.slide-right-leave-active{-webkit-animation-name:antSlideRightOut;animation-name:antSlideRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-right-enter,.slide-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-right-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.ant-slide-up-enter,.ant-slide-up-appear,.ant-slide-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-slide-up-enter.ant-slide-up-enter-active,.ant-slide-up-appear.ant-slide-up-appear-active{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-slide-up-leave.ant-slide-up-leave-active{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-slide-up-enter,.ant-slide-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.ant-slide-up-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.ant-slide-down-enter,.ant-slide-down-appear,.ant-slide-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-slide-down-enter.ant-slide-down-enter-active,.ant-slide-down-appear.ant-slide-down-appear-active{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-slide-down-leave.ant-slide-down-leave-active{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-slide-down-enter,.ant-slide-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.ant-slide-down-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.ant-slide-left-enter,.ant-slide-left-appear,.ant-slide-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-slide-left-enter.ant-slide-left-enter-active,.ant-slide-left-appear.ant-slide-left-appear-active{-webkit-animation-name:antSlideLeftIn;animation-name:antSlideLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-slide-left-leave.ant-slide-left-leave-active{-webkit-animation-name:antSlideLeftOut;animation-name:antSlideLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-slide-left-enter,.ant-slide-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.ant-slide-left-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.ant-slide-right-enter,.ant-slide-right-appear,.ant-slide-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-slide-right-enter.ant-slide-right-enter-active,.ant-slide-right-appear.ant-slide-right-appear-active{-webkit-animation-name:antSlideRightIn;animation-name:antSlideRightIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-slide-right-leave.ant-slide-right-leave-active{-webkit-animation-name:antSlideRightOut;animation-name:antSlideRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-slide-right-enter,.ant-slide-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.23,1,.32,1);animation-timing-function:cubic-bezier(.23,1,.32,1)}.ant-slide-right-leave{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}@-webkit-keyframes antSlideUpIn{0%{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@keyframes antSlideUpIn{0%{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}}@keyframes antSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideDownIn{0%{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}to{transform:scaleY(1);transform-origin:100% 100%;opacity:1}}@keyframes antSlideDownIn{0%{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}to{transform:scaleY(1);transform-origin:100% 100%;opacity:1}}@-webkit-keyframes antSlideDownOut{0%{transform:scaleY(1);transform-origin:100% 100%;opacity:1}to{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}}@keyframes antSlideDownOut{0%{transform:scaleY(1);transform-origin:100% 100%;opacity:1}to{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}}@-webkit-keyframes antSlideLeftIn{0%{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleX(1);transform-origin:0% 0%;opacity:1}}@keyframes antSlideLeftIn{0%{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleX(1);transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideLeftOut{0%{transform:scaleX(1);transform-origin:0% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}}@keyframes antSlideLeftOut{0%{transform:scaleX(1);transform-origin:0% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideRightIn{0%{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}to{transform:scaleX(1);transform-origin:100% 0%;opacity:1}}@keyframes antSlideRightIn{0%{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}to{transform:scaleX(1);transform-origin:100% 0%;opacity:1}}@-webkit-keyframes antSlideRightOut{0%{transform:scaleX(1);transform-origin:100% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}}@keyframes antSlideRightOut{0%{transform:scaleX(1);transform-origin:100% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}}.ant-zoom-enter,.ant-zoom-appear,.ant-zoom-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-enter.ant-zoom-enter-active,.ant-zoom-appear.ant-zoom-appear-active{-webkit-animation-name:antZoomIn;animation-name:antZoomIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-leave.ant-zoom-leave-active{-webkit-animation-name:antZoomOut;animation-name:antZoomOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-enter,.ant-zoom-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-enter-prepare,.ant-zoom-appear-prepare{transform:none}.ant-zoom-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-enter,.zoom-appear,.zoom-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-enter.zoom-enter-active,.zoom-appear.zoom-appear-active{-webkit-animation-name:antZoomIn;animation-name:antZoomIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-leave.zoom-leave-active{-webkit-animation-name:antZoomOut;animation-name:antZoomOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-enter,.zoom-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-enter-prepare,.zoom-appear-prepare{transform:none}.zoom-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-big-enter,.ant-zoom-big-appear,.ant-zoom-big-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-big-enter.ant-zoom-big-enter-active,.ant-zoom-big-appear.ant-zoom-big-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-big-leave.ant-zoom-big-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-big-enter,.ant-zoom-big-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-big-enter-prepare,.ant-zoom-big-appear-prepare{transform:none}.ant-zoom-big-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-big-enter,.zoom-big-appear,.zoom-big-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-enter.zoom-big-enter-active,.zoom-big-appear.zoom-big-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-leave.zoom-big-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-enter,.zoom-big-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-big-enter-prepare,.zoom-big-appear-prepare{transform:none}.zoom-big-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-big-fast-enter,.ant-zoom-big-fast-appear,.ant-zoom-big-fast-leave{-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-big-fast-enter.ant-zoom-big-fast-enter-active,.ant-zoom-big-fast-appear.ant-zoom-big-fast-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-big-fast-leave.ant-zoom-big-fast-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-big-fast-enter,.ant-zoom-big-fast-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-big-fast-enter-prepare,.ant-zoom-big-fast-appear-prepare{transform:none}.ant-zoom-big-fast-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-big-fast-enter,.zoom-big-fast-appear,.zoom-big-fast-leave{-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-enter.zoom-big-fast-enter-active,.zoom-big-fast-appear.zoom-big-fast-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-fast-leave.zoom-big-fast-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-fast-enter,.zoom-big-fast-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-big-fast-enter-prepare,.zoom-big-fast-appear-prepare{transform:none}.zoom-big-fast-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-up-enter,.ant-zoom-up-appear,.ant-zoom-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-up-enter.ant-zoom-up-enter-active,.ant-zoom-up-appear.ant-zoom-up-appear-active{-webkit-animation-name:antZoomUpIn;animation-name:antZoomUpIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-up-leave.ant-zoom-up-leave-active{-webkit-animation-name:antZoomUpOut;animation-name:antZoomUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-up-enter,.ant-zoom-up-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-up-enter-prepare,.ant-zoom-up-appear-prepare{transform:none}.ant-zoom-up-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-up-enter,.zoom-up-appear,.zoom-up-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-enter.zoom-up-enter-active,.zoom-up-appear.zoom-up-appear-active{-webkit-animation-name:antZoomUpIn;animation-name:antZoomUpIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-up-leave.zoom-up-leave-active{-webkit-animation-name:antZoomUpOut;animation-name:antZoomUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-up-enter,.zoom-up-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-up-enter-prepare,.zoom-up-appear-prepare{transform:none}.zoom-up-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-down-enter,.ant-zoom-down-appear,.ant-zoom-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-down-enter.ant-zoom-down-enter-active,.ant-zoom-down-appear.ant-zoom-down-appear-active{-webkit-animation-name:antZoomDownIn;animation-name:antZoomDownIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-down-leave.ant-zoom-down-leave-active{-webkit-animation-name:antZoomDownOut;animation-name:antZoomDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-down-enter,.ant-zoom-down-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-down-enter-prepare,.ant-zoom-down-appear-prepare{transform:none}.ant-zoom-down-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-down-enter,.zoom-down-appear,.zoom-down-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-enter.zoom-down-enter-active,.zoom-down-appear.zoom-down-appear-active{-webkit-animation-name:antZoomDownIn;animation-name:antZoomDownIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-down-leave.zoom-down-leave-active{-webkit-animation-name:antZoomDownOut;animation-name:antZoomDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-down-enter,.zoom-down-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-down-enter-prepare,.zoom-down-appear-prepare{transform:none}.zoom-down-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-left-enter,.ant-zoom-left-appear,.ant-zoom-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-left-enter.ant-zoom-left-enter-active,.ant-zoom-left-appear.ant-zoom-left-appear-active{-webkit-animation-name:antZoomLeftIn;animation-name:antZoomLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-left-leave.ant-zoom-left-leave-active{-webkit-animation-name:antZoomLeftOut;animation-name:antZoomLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-left-enter,.ant-zoom-left-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-left-enter-prepare,.ant-zoom-left-appear-prepare{transform:none}.ant-zoom-left-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-left-enter,.zoom-left-appear,.zoom-left-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-enter.zoom-left-enter-active,.zoom-left-appear.zoom-left-appear-active{-webkit-animation-name:antZoomLeftIn;animation-name:antZoomLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-left-leave.zoom-left-leave-active{-webkit-animation-name:antZoomLeftOut;animation-name:antZoomLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-left-enter,.zoom-left-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-left-enter-prepare,.zoom-left-appear-prepare{transform:none}.zoom-left-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.ant-zoom-right-enter,.ant-zoom-right-appear,.ant-zoom-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-zoom-right-enter.ant-zoom-right-enter-active,.ant-zoom-right-appear.ant-zoom-right-appear-active{-webkit-animation-name:antZoomRightIn;animation-name:antZoomRightIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-zoom-right-leave.ant-zoom-right-leave-active{-webkit-animation-name:antZoomRightOut;animation-name:antZoomRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-zoom-right-enter,.ant-zoom-right-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.ant-zoom-right-enter-prepare,.ant-zoom-right-appear-prepare{transform:none}.ant-zoom-right-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-right-enter,.zoom-right-appear,.zoom-right-leave{-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-enter.zoom-right-enter-active,.zoom-right-appear.zoom-right-appear-active{-webkit-animation-name:antZoomRightIn;animation-name:antZoomRightIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-right-leave.zoom-right-leave-active{-webkit-animation-name:antZoomRightOut;animation-name:antZoomRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-right-enter,.zoom-right-appear{transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(.08,.82,.17,1);animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-right-enter-prepare,.zoom-right-appear-prepare{transform:none}.zoom-right-leave{-webkit-animation-timing-function:cubic-bezier(.78,.14,.15,.86);animation-timing-function:cubic-bezier(.78,.14,.15,.86)}@-webkit-keyframes antZoomIn{0%{transform:scale(.2);opacity:0}to{transform:scale(1);opacity:1}}@keyframes antZoomIn{0%{transform:scale(.2);opacity:0}to{transform:scale(1);opacity:1}}@-webkit-keyframes antZoomOut{0%{transform:scale(1)}to{transform:scale(.2);opacity:0}}@keyframes antZoomOut{0%{transform:scale(1)}to{transform:scale(.2);opacity:0}}@-webkit-keyframes antZoomBigIn{0%{transform:none;opacity:0}5%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@keyframes antZoomBigIn{0%{transform:none;opacity:0}5%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@-webkit-keyframes antZoomBigOut{0%{transform:scale(1)}to{transform:scale(.8);opacity:0}}@keyframes antZoomBigOut{0%{transform:scale(1)}to{transform:scale(.8);opacity:0}}@-webkit-keyframes antZoomUpIn{0%{transform:scale(.8);transform-origin:50% 0%;opacity:0}to{transform:scale(1);transform-origin:50% 0%}}@keyframes antZoomUpIn{0%{transform:scale(.8);transform-origin:50% 0%;opacity:0}to{transform:scale(1);transform-origin:50% 0%}}@-webkit-keyframes antZoomUpOut{0%{transform:scale(1);transform-origin:50% 0%}to{transform:scale(.8);transform-origin:50% 0%;opacity:0}}@keyframes antZoomUpOut{0%{transform:scale(1);transform-origin:50% 0%}to{transform:scale(.8);transform-origin:50% 0%;opacity:0}}@-webkit-keyframes antZoomLeftIn{0%{transform:scale(.8);transform-origin:0% 50%;opacity:0}to{transform:scale(1);transform-origin:0% 50%}}@keyframes antZoomLeftIn{0%{transform:scale(.8);transform-origin:0% 50%;opacity:0}to{transform:scale(1);transform-origin:0% 50%}}@-webkit-keyframes antZoomLeftOut{0%{transform:scale(1);transform-origin:0% 50%}to{transform:scale(.8);transform-origin:0% 50%;opacity:0}}@keyframes antZoomLeftOut{0%{transform:scale(1);transform-origin:0% 50%}to{transform:scale(.8);transform-origin:0% 50%;opacity:0}}@-webkit-keyframes antZoomRightIn{0%{transform:scale(.8);transform-origin:100% 50%;opacity:0}to{transform:scale(1);transform-origin:100% 50%}}@keyframes antZoomRightIn{0%{transform:scale(.8);transform-origin:100% 50%;opacity:0}to{transform:scale(1);transform-origin:100% 50%}}@-webkit-keyframes antZoomRightOut{0%{transform:scale(1);transform-origin:100% 50%}to{transform:scale(.8);transform-origin:100% 50%;opacity:0}}@keyframes antZoomRightOut{0%{transform:scale(1);transform-origin:100% 50%}to{transform:scale(.8);transform-origin:100% 50%;opacity:0}}@-webkit-keyframes antZoomDownIn{0%{transform:scale(.8);transform-origin:50% 100%;opacity:0}to{transform:scale(1);transform-origin:50% 100%}}@keyframes antZoomDownIn{0%{transform:scale(.8);transform-origin:50% 100%;opacity:0}to{transform:scale(1);transform-origin:50% 100%}}@-webkit-keyframes antZoomDownOut{0%{transform:scale(1);transform-origin:50% 100%}to{transform:scale(.8);transform-origin:50% 100%;opacity:0}}@keyframes antZoomDownOut{0%{transform:scale(1);transform-origin:50% 100%}to{transform:scale(.8);transform-origin:50% 100%;opacity:0}}.ant-motion-collapse-legacy{overflow:hidden}.ant-motion-collapse-legacy-active{transition:height .2s cubic-bezier(.645,.045,.355,1),opacity .2s cubic-bezier(.645,.045,.355,1)!important}.ant-motion-collapse{overflow:hidden;transition:height .2s cubic-bezier(.645,.045,.355,1),opacity .2s cubic-bezier(.645,.045,.355,1)!important}.ant-affix{position:fixed;z-index:10}.ant-alert{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:flex;align-items:center;padding:8px 15px;word-wrap:break-word;border-radius:2px}.ant-alert-content{flex:1;min-width:0}.ant-alert-icon{margin-right:8px}.ant-alert-description{display:none;font-size:14px;line-height:22px}.ant-alert-success{background-color:#f6ffed;border:1px solid #b7eb8f}.ant-alert-success .ant-alert-icon{color:#52c41a}.ant-alert-info{background-color:#e6f7ff;border:1px solid #91d5ff}.ant-alert-info .ant-alert-icon{color:#1890ff}.ant-alert-warning{background-color:#fffbe6;border:1px solid #ffe58f}.ant-alert-warning .ant-alert-icon{color:#faad14}.ant-alert-error{background-color:#fff2f0;border:1px solid #ffccc7}.ant-alert-error .ant-alert-icon{color:#ff4d4f}.ant-alert-close-icon{margin-left:8px;padding:0;overflow:hidden;font-size:12px;line-height:12px;background-color:transparent;border:none;outline:none;cursor:pointer}.ant-alert-close-icon .anticon-close{color:#00000073;transition:color .3s}.ant-alert-close-icon .anticon-close:hover{color:#000000bf}.ant-alert-close-text{color:#00000073;transition:color .3s}.ant-alert-close-text:hover{color:#000000bf}.ant-alert-with-description{align-items:flex-start;padding:15px}.ant-alert-with-description.ant-alert-no-icon{padding:15px}.ant-alert-with-description .ant-alert-icon{margin-right:15px;font-size:24px}.ant-alert-with-description .ant-alert-message{display:block;margin-bottom:4px;color:#000000d9;font-size:16px}.ant-alert-message{color:#000000d9}.ant-alert-with-description .ant-alert-description{display:block}.ant-alert.ant-alert-closing{height:0!important;margin:0;padding-top:0;padding-bottom:0;transform-origin:50% 0;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-alert-slide-up-leave{-webkit-animation:antAlertSlideUpOut .3s cubic-bezier(.78,.14,.15,.86);animation:antAlertSlideUpOut .3s cubic-bezier(.78,.14,.15,.86);-webkit-animation-fill-mode:both;animation-fill-mode:both}.ant-alert-banner{margin-bottom:0;border:0;border-radius:0}@-webkit-keyframes antAlertSlideUpIn{0%{transform:scaleY(0);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@keyframes antAlertSlideUpIn{0%{transform:scaleY(0);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antAlertSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(0);transform-origin:0% 0%;opacity:0}}@keyframes antAlertSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(0);transform-origin:0% 0%;opacity:0}}.ant-anchor{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;padding:0 0 0 2px}.ant-anchor-wrapper{margin-left:-4px;padding-left:4px;overflow:auto;background-color:transparent}.ant-anchor-ink{position:absolute;top:0;left:0;height:100%}.ant-anchor-ink:before{position:relative;display:block;width:2px;height:100%;margin:0 auto;background-color:#f0f0f0;content:\" \"}.ant-anchor-ink-ball{position:absolute;left:50%;display:none;width:8px;height:8px;background-color:#fff;border:2px solid #1890ff;border-radius:8px;transform:translate(-50%);transition:top .3s ease-in-out}.ant-anchor-ink-ball.visible{display:inline-block}.ant-anchor.fixed .ant-anchor-ink .ant-anchor-ink-ball{display:none}.ant-anchor-link{padding:7px 0 7px 16px;line-height:1.143}.ant-anchor-link-title{position:relative;display:block;margin-bottom:6px;overflow:hidden;color:#000000d9;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-anchor-link-title:only-child{margin-bottom:0}.ant-anchor-link-active>.ant-anchor-link-title{color:#1890ff}.ant-anchor-link .ant-anchor-link{padding-top:5px;padding-bottom:5px}.ant-anchor-rtl{direction:rtl}.ant-anchor-rtl.ant-anchor-wrapper{margin-right:-4px;margin-left:0;padding-right:4px;padding-left:0}.ant-anchor-rtl .ant-anchor-ink{right:0;left:auto}.ant-anchor-rtl .ant-anchor-ink-ball{right:50%;left:0;transform:translate(50%)}.ant-anchor-rtl .ant-anchor-link{padding:7px 16px 7px 0}.ant-select-auto-complete{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-select-auto-complete .ant-select-clear{right:13px}.ant-select-single .ant-select-selector{display:flex}.ant-select-single .ant-select-selector .ant-select-selection-search{position:absolute;top:0;right:11px;bottom:0;left:11px}.ant-select-single .ant-select-selector .ant-select-selection-search-input{width:100%}.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{padding:0;line-height:30px;transition:all .3s}@supports (-moz-appearance: meterbar){.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{line-height:30px}}.ant-select-single .ant-select-selector .ant-select-selection-item{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-select-single .ant-select-selector .ant-select-selection-placeholder{pointer-events:none}.ant-select-single .ant-select-selector:after,.ant-select-single .ant-select-selector .ant-select-selection-item:after,.ant-select-single .ant-select-selector .ant-select-selection-placeholder:after{display:inline-block;width:0;visibility:hidden;content:\"\\a0\"}.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:25px}.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:18px}.ant-select-single.ant-select-open .ant-select-selection-item{color:#bfbfbf}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{width:100%;height:32px;padding:0 11px}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{height:30px}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector:after{line-height:30px}.ant-select-single.ant-select-customize-input .ant-select-selector:after{display:none}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-search{position:static;width:100%}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder{position:absolute;right:0;left:0;padding:0 11px}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder:after{display:none}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{height:40px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector:after,.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:38px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:38px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{height:24px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector:after,.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selection-search{right:7px;left:7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{padding:0 7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:28px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:21px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{padding:0 11px}.ant-select-selection-overflow{position:relative;display:flex;flex:auto;flex-wrap:wrap;max-width:100%}.ant-select-selection-overflow-item{flex:none;align-self:center;max-width:100%}.ant-select-multiple .ant-select-selector{display:flex;flex-wrap:wrap;align-items:center;padding:1px 4px}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-disabled.ant-select-multiple .ant-select-selector{background:#f5f5f5;cursor:not-allowed}.ant-select-multiple .ant-select-selector:after{display:inline-block;width:0;margin:2px 0;line-height:24px;content:\"\\a0\"}.ant-select-multiple.ant-select-show-arrow .ant-select-selector,.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:24px}.ant-select-multiple .ant-select-selection-item{position:relative;display:flex;flex:none;box-sizing:border-box;max-width:100%;height:24px;margin-top:2px;margin-bottom:2px;line-height:22px;background:#f5f5f5;border:1px solid #f0f0f0;border-radius:2px;cursor:default;transition:font-size .3s,line-height .3s,height .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-margin-end:4px;margin-inline-end:4px;-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:4px;padding-inline-end:4px}.ant-select-disabled.ant-select-multiple .ant-select-selection-item{color:#bfbfbf;border-color:#d9d9d9;cursor:not-allowed}.ant-select-multiple .ant-select-selection-item-content{display:inline-block;margin-right:4px;overflow:hidden;white-space:pre;text-overflow:ellipsis}.ant-select-multiple .ant-select-selection-item-remove{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;color:#00000073;font-weight:700;font-size:10px;line-height:inherit;cursor:pointer}.ant-select-multiple .ant-select-selection-item-remove>*{line-height:1}.ant-select-multiple .ant-select-selection-item-remove svg{display:inline-block}.ant-select-multiple .ant-select-selection-item-remove:before{display:none}.ant-select-multiple .ant-select-selection-item-remove .ant-select-multiple .ant-select-selection-item-remove-icon{display:block}.ant-select-multiple .ant-select-selection-item-remove>.anticon{vertical-align:-.2em}.ant-select-multiple .ant-select-selection-item-remove:hover{color:#000000bf}.ant-select-multiple .ant-select-selection-overflow-item+.ant-select-selection-overflow-item .ant-select-selection-search{-webkit-margin-start:0;margin-inline-start:0}.ant-select-multiple .ant-select-selection-search{position:relative;max-width:100%;margin-top:2px;margin-bottom:2px;-webkit-margin-start:7px;margin-inline-start:7px}.ant-select-multiple .ant-select-selection-search-input,.ant-select-multiple .ant-select-selection-search-mirror{height:24px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";line-height:24px;transition:all .3s}.ant-select-multiple .ant-select-selection-search-input{width:100%;min-width:4.1px}.ant-select-multiple .ant-select-selection-search-mirror{position:absolute;top:0;left:0;z-index:999;white-space:pre;visibility:hidden}.ant-select-multiple .ant-select-selection-placeholder{position:absolute;top:50%;right:11px;left:11px;transform:translateY(-50%);transition:all .3s}.ant-select-multiple.ant-select-lg .ant-select-selector:after{line-height:32px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:30px}.ant-select-multiple.ant-select-lg .ant-select-selection-search{height:32px;line-height:32px}.ant-select-multiple.ant-select-lg .ant-select-selection-search-input,.ant-select-multiple.ant-select-lg .ant-select-selection-search-mirror{height:32px;line-height:30px}.ant-select-multiple.ant-select-sm .ant-select-selector:after{line-height:16px}.ant-select-multiple.ant-select-sm .ant-select-selection-item{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-search{height:16px;line-height:16px}.ant-select-multiple.ant-select-sm .ant-select-selection-search-input,.ant-select-multiple.ant-select-sm .ant-select-selection-search-mirror{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{left:7px}.ant-select-multiple.ant-select-sm .ant-select-selection-search{-webkit-margin-start:3px;margin-inline-start:3px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:32px}.ant-select-disabled .ant-select-selection-item-remove{display:none}.ant-select{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;cursor:pointer}.ant-select:not(.ant-select-customize-input) .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-select:not(.ant-select-customize-input) .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select:not(.ant-select-customize-input) .ant-select-selector{cursor:text}.ant-select-show-search.ant-select:not(.ant-select-customize-input) .ant-select-selector input{cursor:auto}.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-select-multiple.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector{background:#f5f5f5}.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector input{cursor:not-allowed}.ant-select:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{margin:0;padding:0;background:transparent;border:none;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.ant-select:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input::-webkit-search-cancel-button{display:none;-webkit-appearance:none}.ant-select:not(.ant-select-disabled):hover .ant-select-selector{border-color:#40a9ff;border-right-width:1px!important}.ant-select-selection-item{flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media all and (-ms-high-contrast: none){.ant-select-selection-item *::-ms-backdrop,.ant-select-selection-item{flex:auto}}.ant-select-selection-placeholder{flex:1;overflow:hidden;color:#bfbfbf;white-space:nowrap;text-overflow:ellipsis;pointer-events:none}@media all and (-ms-high-contrast: none){.ant-select-selection-placeholder *::-ms-backdrop,.ant-select-selection-placeholder{flex:auto}}.ant-select-arrow{display:inline-block;color:inherit;font-style:normal;line-height:0;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:53%;right:11px;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;line-height:1;text-align:center;pointer-events:none}.ant-select-arrow>*{line-height:1}.ant-select-arrow svg{display:inline-block}.ant-select-arrow:before{display:none}.ant-select-arrow .ant-select-arrow-icon{display:block}.ant-select-arrow .anticon{vertical-align:top;transition:transform .3s}.ant-select-arrow .anticon>svg{vertical-align:top}.ant-select-arrow .anticon:not(.ant-select-suffix){pointer-events:auto}.ant-select-disabled .ant-select-arrow{cursor:not-allowed}.ant-select-clear{position:absolute;top:50%;right:11px;z-index:1;display:inline-block;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;font-style:normal;line-height:1;text-align:center;text-transform:none;background:#fff;cursor:pointer;opacity:0;transition:color .3s ease,opacity .15s ease;text-rendering:auto}.ant-select-clear:before{display:block}.ant-select-clear:hover{color:#00000073}.ant-select:hover .ant-select-clear{opacity:1}.ant-select-dropdown{margin:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;top:-9999px;left:-9999px;z-index:1050;box-sizing:border-box;padding:4px 0;overflow:hidden;font-size:14px;font-variant:initial;background-color:#fff;border-radius:2px;outline:none;box-shadow:0 2px 8px #00000026}.ant-select-dropdown.ant-slide-up-enter.ant-slide-up-enter-active.ant-select-dropdown-placement-bottomLeft,.ant-select-dropdown.ant-slide-up-appear.ant-slide-up-appear-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-select-dropdown.ant-slide-up-enter.ant-slide-up-enter-active.ant-select-dropdown-placement-topLeft,.ant-select-dropdown.ant-slide-up-appear.ant-slide-up-appear-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-select-dropdown.ant-slide-up-leave.ant-slide-up-leave-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-select-dropdown.ant-slide-up-leave.ant-slide-up-leave-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-select-dropdown-hidden{display:none}.ant-select-dropdown-empty{color:#00000040}.ant-select-item-empty{position:relative;display:block;min-height:32px;padding:5px 12px;color:#000000d9;font-weight:400;font-size:14px;line-height:22px;color:#00000040}.ant-select-item{position:relative;display:block;min-height:32px;padding:5px 12px;color:#000000d9;font-weight:400;font-size:14px;line-height:22px;cursor:pointer;transition:background .3s ease}.ant-select-item-group{color:#00000073;font-size:12px;cursor:default}.ant-select-item-option{display:flex}.ant-select-item-option-content{flex:auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-item-option-state{flex:none}.ant-select-item-option-active:not(.ant-select-item-option-disabled){background-color:#f5f5f5}.ant-select-item-option-selected:not(.ant-select-item-option-disabled){color:#000000d9;font-weight:600;background-color:#e6f7ff}.ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state{color:#1890ff}.ant-select-item-option-disabled{color:#00000040;cursor:not-allowed}.ant-select-item-option-grouped{padding-left:24px}.ant-select-lg{font-size:16px}.ant-select-borderless .ant-select-selector{background-color:transparent!important;border-color:transparent!important;box-shadow:none!important}.ant-select-rtl{direction:rtl}.ant-select-rtl .ant-select-arrow,.ant-select-rtl .ant-select-clear{right:initial;left:11px}.ant-select-dropdown-rtl{direction:rtl}.ant-select-dropdown-rtl .ant-select-item-option-grouped{padding-right:24px;padding-left:12px}.ant-select-rtl.ant-select-multiple.ant-select-show-arrow .ant-select-selector,.ant-select-rtl.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:4px;padding-left:24px}.ant-select-rtl.ant-select-multiple .ant-select-selection-item{text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-item-content{margin-right:0;margin-left:4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-search-mirror{right:0;left:auto}.ant-select-rtl.ant-select-multiple .ant-select-selection-placeholder{right:11px;left:auto}.ant-select-rtl.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{right:7px}.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-placeholder{right:0;left:9px;text-align:right}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:11px;left:25px}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:18px}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:6px}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:21px}.ant-empty{margin:0 8px;font-size:14px;line-height:1.5715;text-align:center}.ant-empty-image{height:100px;margin-bottom:8px}.ant-empty-image img{height:100%}.ant-empty-image svg{height:100%;margin:auto}.ant-empty-footer{margin-top:16px}.ant-empty-normal{margin:32px 0;color:#00000040}.ant-empty-normal .ant-empty-image{height:40px}.ant-empty-small{margin:8px 0;color:#00000040}.ant-empty-small .ant-empty-image{height:35px}.ant-empty-img-default-ellipse{fill:#f5f5f5;fill-opacity:.8}.ant-empty-img-default-path-1{fill:#aeb8c2}.ant-empty-img-default-path-2{fill:url(#linearGradient-1)}.ant-empty-img-default-path-3{fill:#f5f5f7}.ant-empty-img-default-path-4,.ant-empty-img-default-path-5{fill:#dce0e6}.ant-empty-img-default-g{fill:#fff}.ant-empty-img-simple-ellipse{fill:#f5f5f5}.ant-empty-img-simple-g{stroke:#d9d9d9}.ant-empty-img-simple-path{fill:#fafafa}.ant-empty-rtl{direction:rtl}.ant-input-affix-wrapper{position:relative;display:inline-block;width:100%;padding:4px 11px;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s;display:inline-flex}.ant-input-affix-wrapper::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-input-affix-wrapper:-ms-input-placeholder{color:#bfbfbf}.ant-input-affix-wrapper::-webkit-input-placeholder{color:#bfbfbf}.ant-input-affix-wrapper:-moz-placeholder-shown{text-overflow:ellipsis}.ant-input-affix-wrapper:-ms-input-placeholder{text-overflow:ellipsis}.ant-input-affix-wrapper:placeholder-shown{text-overflow:ellipsis}.ant-input-affix-wrapper:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-input-affix-wrapper[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-affix-wrapper[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input-affix-wrapper{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-affix-wrapper-disabled .ant-input[disabled]{background:transparent}.ant-input-affix-wrapper>input.ant-input{padding:0;border:none;outline:none}.ant-input-affix-wrapper>input.ant-input:focus{box-shadow:none}.ant-input-affix-wrapper:before{width:0;visibility:hidden;content:\"\\a0\"}.ant-input-prefix,.ant-input-suffix{display:flex;flex:none;align-items:center}.ant-input-prefix{margin-right:4px}.ant-input-suffix{margin-left:4px}.ant-input{box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;width:100%;padding:4px 11px;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s}.ant-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-input:-ms-input-placeholder{color:#bfbfbf}.ant-input::-webkit-input-placeholder{color:#bfbfbf}.ant-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-input:placeholder-shown{text-overflow:ellipsis}.ant-input:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-input:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-lg{padding:6.5px 11px;font-size:16px}.ant-input-sm{padding:0 7px}.ant-input-group{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:table;width:100%;border-collapse:separate;border-spacing:0}.ant-input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.ant-input-group>[class*=col-]{padding-right:8px}.ant-input-group>[class*=col-]:last-child{padding-right:0}.ant-input-group-addon,.ant-input-group-wrap,.ant-input-group>.ant-input{display:table-cell}.ant-input-group-addon:not(:first-child):not(:last-child),.ant-input-group-wrap:not(:first-child):not(:last-child),.ant-input-group>.ant-input:not(:first-child):not(:last-child){border-radius:0}.ant-input-group-addon,.ant-input-group-wrap{width:1px;white-space:nowrap;vertical-align:middle}.ant-input-group-wrap>*{display:block!important}.ant-input-group .ant-input{float:left;width:100%;margin-bottom:0;text-align:inherit}.ant-input-group .ant-input:focus{z-index:1;border-right-width:1px}.ant-input-group .ant-input:hover{z-index:1;border-right-width:1px}.ant-input-group-addon{position:relative;padding:0 11px;color:#000000d9;font-weight:400;font-size:14px;text-align:center;background-color:#fafafa;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s}.ant-input-group-addon .ant-select{margin:-5px -11px}.ant-input-group-addon .ant-select.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{background-color:inherit;border:1px solid transparent;box-shadow:none}.ant-input-group-addon .ant-select-open .ant-select-selector,.ant-input-group-addon .ant-select-focused .ant-select-selector{color:#1890ff}.ant-input-group-addon>i:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;content:\"\"}.ant-input-group>.ant-input:first-child,.ant-input-group-addon:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group>.ant-input:first-child .ant-select .ant-select-selector,.ant-input-group-addon:first-child .ant-select .ant-select-selector{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group>.ant-input-affix-wrapper:not(:first-child) .ant-input{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group>.ant-input-affix-wrapper:not(:last-child) .ant-input{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group-addon:first-child{border-right:0}.ant-input-group-addon:last-child{border-left:0}.ant-input-group>.ant-input:last-child,.ant-input-group-addon:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group>.ant-input:last-child .ant-select .ant-select-selector,.ant-input-group-addon:last-child .ant-select .ant-select-selector{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group-lg .ant-input,.ant-input-group-lg>.ant-input-group-addon{padding:6.5px 11px;font-size:16px}.ant-input-group-sm .ant-input,.ant-input-group-sm>.ant-input-group-addon{padding:0 7px}.ant-input-group-lg .ant-select-single .ant-select-selector{height:40px}.ant-input-group-sm .ant-select-single .ant-select-selector{height:24px}.ant-input-group.ant-input-group-compact{display:block}.ant-input-group.ant-input-group-compact:before,.ant-input-group.ant-input-group-compact:after{display:table;content:\"\"}.ant-input-group.ant-input-group-compact:after{clear:both}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child),.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child),.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child){border-right-width:1px}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child):hover,.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child):hover,.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child):hover{z-index:1}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child):focus,.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child):focus,.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child):focus{z-index:1}.ant-input-group.ant-input-group-compact>*{display:inline-block;float:none;vertical-align:top;border-radius:0}.ant-input-group.ant-input-group-compact>.ant-input-affix-wrapper{display:inline-flex}.ant-input-group.ant-input-group-compact>*:not(:last-child){margin-right:-1px;border-right-width:1px}.ant-input-group.ant-input-group-compact .ant-input{float:none}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input{border-right-width:1px;border-radius:0}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector:hover,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor:hover,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input:hover,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input:hover{z-index:1}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector:focus,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor:focus,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input:focus,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input:focus{z-index:1}.ant-input-group.ant-input-group-compact>.ant-select-focused{z-index:1}.ant-input-group.ant-input-group-compact>*:first-child,.ant-input-group.ant-input-group-compact>.ant-select:first-child>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:first-child .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker:first-child .ant-time-picker-input{border-top-left-radius:2px;border-bottom-left-radius:2px}.ant-input-group.ant-input-group-compact>*:last-child,.ant-input-group.ant-input-group-compact>.ant-select:last-child>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker-focused:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:last-child .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker:last-child .ant-time-picker-input{border-right-width:1px;border-top-right-radius:2px;border-bottom-right-radius:2px}.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input{vertical-align:top}.ant-input-group-wrapper{display:inline-block;width:100%;text-align:start;vertical-align:top}.ant-input-affix-wrapper{box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-flex;border:1px solid #d9d9d9;border-radius:2px;padding:4px 11px;width:100%;text-align:start;background-color:#fff;background-image:none;color:#000000d9;font-size:14px;line-height:1.5715}.ant-input-affix-wrapper:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-input-affix-wrapper-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-affix-wrapper-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input-affix-wrapper-focused{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-input-affix-wrapper-lg{padding:6.5px 11px;font-size:16px}.ant-input-affix-wrapper-sm{padding:0 7px}.ant-input-affix-wrapper .ant-input{position:relative;text-align:inherit;border:none;padding:0}.ant-input-affix-wrapper .ant-input:focus{border:none;outline:none;box-shadow:none}.ant-input-affix-wrapper .ant-input-prefix,.ant-input-affix-wrapper .ant-input-suffix{display:flex;align-items:center;color:#000000d9;white-space:nowrap}.ant-input-affix-wrapper .ant-input-prefix :not(.anticon),.ant-input-affix-wrapper .ant-input-suffix :not(.anticon){line-height:1.5715}.ant-input-affix-wrapper .ant-input-disabled~.ant-input-suffix .anticon{color:#00000040;cursor:not-allowed}.ant-input-affix-wrapper .ant-input-prefix{margin-right:4px}.ant-input-affix-wrapper .ant-input-suffix{margin-left:4px}.ant-input-password-icon{color:#00000073;cursor:pointer;transition:all .3s}.ant-input-password-icon:hover{color:#000000d9}.ant-input-clear-icon{color:#00000040;font-size:12px;cursor:pointer;transition:color .3s;margin:0 4px;vertical-align:0}.ant-input-clear-icon:hover{color:#00000073}.ant-input-clear-icon:active{color:#000000d9}.ant-input-clear-icon+i{margin-left:6px}.ant-input-clear-icon-hidden,.ant-input-textarea-clear-icon-hidden{visibility:hidden}.ant-input-affix-wrapper-textarea-with-clear-btn{padding:0!important}.ant-input-affix-wrapper-textarea-with-clear-btn .ant-input{padding:4px 11px}.ant-input-textarea-clear-icon{color:#00000040;font-size:12px;cursor:pointer;transition:color .3s;position:absolute;top:0;right:0;margin:8px 8px 0 0}.ant-input-textarea-clear-icon:hover{color:#00000073}.ant-input-textarea-clear-icon:active{color:#000000d9}.ant-input-textarea-clear-icon+i{margin-left:6px}.ant-input-textarea-show-count:after{display:block;color:#00000073;text-align:right;content:attr(data-count)}.ant-input-search-icon{color:#00000073;cursor:pointer;transition:all .3s}.ant-input-search-icon:hover{color:#000000d9}.ant-input-search-enter-button input{border-right:0}.ant-input-search-enter-button+.ant-input-group-addon,.ant-input-search-enter-button input+.ant-input-group-addon{padding:0;border:0}.ant-input-search-enter-button+.ant-input-group-addon .ant-input-search-button,.ant-input-search-enter-button input+.ant-input-group-addon .ant-input-search-button{border-top-left-radius:0;border-bottom-left-radius:0}.ant-btn{line-height:1.5715;position:relative;display:inline-block;font-weight:400;white-space:nowrap;text-align:center;background-image:none;border:1px solid transparent;box-shadow:0 2px #00000004;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;touch-action:manipulation;height:32px;padding:4px 15px;font-size:14px;border-radius:2px;color:#000000d9;background:#fff;border-color:#d9d9d9}.ant-btn>.anticon{line-height:1}.ant-btn,.ant-btn:active,.ant-btn:focus{outline:0}.ant-btn:not([disabled]):hover{text-decoration:none}.ant-btn:not([disabled]):active{outline:0;box-shadow:none}.ant-btn[disabled]{cursor:not-allowed}.ant-btn[disabled]>*{pointer-events:none}.ant-btn-lg{height:40px;padding:6.4px 15px;font-size:16px;border-radius:2px}.ant-btn-sm{height:24px;padding:0 7px;font-size:14px;border-radius:2px}.ant-btn>a:only-child{color:currentColor}.ant-btn>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn:hover,.ant-btn:focus{color:#40a9ff;background:#fff;border-color:#40a9ff}.ant-btn:hover>a:only-child,.ant-btn:focus>a:only-child{color:currentColor}.ant-btn:hover>a:only-child:after,.ant-btn:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn:active{color:#096dd9;background:#fff;border-color:#096dd9}.ant-btn:active>a:only-child{color:currentColor}.ant-btn:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn[disabled],.ant-btn[disabled]:hover,.ant-btn[disabled]:focus,.ant-btn[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn[disabled]>a:only-child,.ant-btn[disabled]:hover>a:only-child,.ant-btn[disabled]:focus>a:only-child,.ant-btn[disabled]:active>a:only-child{color:currentColor}.ant-btn[disabled]>a:only-child:after,.ant-btn[disabled]:hover>a:only-child:after,.ant-btn[disabled]:focus>a:only-child:after,.ant-btn[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn:hover,.ant-btn:focus,.ant-btn:active{text-decoration:none;background:#fff}.ant-btn>span{display:inline-block}.ant-btn-primary{color:#fff;background:#1890ff;border-color:#1890ff;text-shadow:0 -1px 0 rgba(0,0,0,.12);box-shadow:0 2px #0000000b}.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-primary:hover,.ant-btn-primary:focus{color:#fff;background:#40a9ff;border-color:#40a9ff}.ant-btn-primary:hover>a:only-child,.ant-btn-primary:focus>a:only-child{color:currentColor}.ant-btn-primary:hover>a:only-child:after,.ant-btn-primary:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-primary:active{color:#fff;background:#096dd9;border-color:#096dd9}.ant-btn-primary:active>a:only-child{color:currentColor}.ant-btn-primary:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-primary[disabled],.ant-btn-primary[disabled]:hover,.ant-btn-primary[disabled]:focus,.ant-btn-primary[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-primary[disabled]>a:only-child,.ant-btn-primary[disabled]:hover>a:only-child,.ant-btn-primary[disabled]:focus>a:only-child,.ant-btn-primary[disabled]:active>a:only-child{color:currentColor}.ant-btn-primary[disabled]>a:only-child:after,.ant-btn-primary[disabled]:hover>a:only-child:after,.ant-btn-primary[disabled]:focus>a:only-child:after,.ant-btn-primary[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-group .ant-btn-primary:not(:first-child):not(:last-child){border-right-color:#40a9ff;border-left-color:#40a9ff}.ant-btn-group .ant-btn-primary:not(:first-child):not(:last-child):disabled{border-color:#d9d9d9}.ant-btn-group .ant-btn-primary:first-child:not(:last-child){border-right-color:#40a9ff}.ant-btn-group .ant-btn-primary:first-child:not(:last-child)[disabled]{border-right-color:#d9d9d9}.ant-btn-group .ant-btn-primary:last-child:not(:first-child),.ant-btn-group .ant-btn-primary+.ant-btn-primary{border-left-color:#40a9ff}.ant-btn-group .ant-btn-primary:last-child:not(:first-child)[disabled],.ant-btn-group .ant-btn-primary+.ant-btn-primary[disabled]{border-left-color:#d9d9d9}.ant-btn-ghost{color:#000000d9;background:transparent;border-color:#d9d9d9}.ant-btn-ghost>a:only-child{color:currentColor}.ant-btn-ghost>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-ghost:hover,.ant-btn-ghost:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-ghost:hover>a:only-child,.ant-btn-ghost:focus>a:only-child{color:currentColor}.ant-btn-ghost:hover>a:only-child:after,.ant-btn-ghost:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-ghost:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-ghost:active>a:only-child{color:currentColor}.ant-btn-ghost:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-ghost[disabled],.ant-btn-ghost[disabled]:hover,.ant-btn-ghost[disabled]:focus,.ant-btn-ghost[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-ghost[disabled]>a:only-child,.ant-btn-ghost[disabled]:hover>a:only-child,.ant-btn-ghost[disabled]:focus>a:only-child,.ant-btn-ghost[disabled]:active>a:only-child{color:currentColor}.ant-btn-ghost[disabled]>a:only-child:after,.ant-btn-ghost[disabled]:hover>a:only-child:after,.ant-btn-ghost[disabled]:focus>a:only-child:after,.ant-btn-ghost[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dashed{color:#000000d9;background:#fff;border-color:#d9d9d9;border-style:dashed}.ant-btn-dashed>a:only-child{color:currentColor}.ant-btn-dashed>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dashed:hover,.ant-btn-dashed:focus{color:#40a9ff;background:#fff;border-color:#40a9ff}.ant-btn-dashed:hover>a:only-child,.ant-btn-dashed:focus>a:only-child{color:currentColor}.ant-btn-dashed:hover>a:only-child:after,.ant-btn-dashed:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dashed:active{color:#096dd9;background:#fff;border-color:#096dd9}.ant-btn-dashed:active>a:only-child{color:currentColor}.ant-btn-dashed:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dashed[disabled],.ant-btn-dashed[disabled]:hover,.ant-btn-dashed[disabled]:focus,.ant-btn-dashed[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-dashed[disabled]>a:only-child,.ant-btn-dashed[disabled]:hover>a:only-child,.ant-btn-dashed[disabled]:focus>a:only-child,.ant-btn-dashed[disabled]:active>a:only-child{color:currentColor}.ant-btn-dashed[disabled]>a:only-child:after,.ant-btn-dashed[disabled]:hover>a:only-child:after,.ant-btn-dashed[disabled]:focus>a:only-child:after,.ant-btn-dashed[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-danger{color:#fff;background:#ff7875;border-color:#ff7875;text-shadow:0 -1px 0 rgba(0,0,0,.12);box-shadow:0 2px #0000000b}.ant-btn-danger>a:only-child{color:currentColor}.ant-btn-danger>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-danger:hover,.ant-btn-danger:focus{color:#fff;background:#ffa39e;border-color:#ffa39e}.ant-btn-danger:hover>a:only-child,.ant-btn-danger:focus>a:only-child{color:currentColor}.ant-btn-danger:hover>a:only-child:after,.ant-btn-danger:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-danger:active{color:#fff;background:#d9595b;border-color:#d9595b}.ant-btn-danger:active>a:only-child{color:currentColor}.ant-btn-danger:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-danger[disabled],.ant-btn-danger[disabled]:hover,.ant-btn-danger[disabled]:focus,.ant-btn-danger[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-danger[disabled]>a:only-child,.ant-btn-danger[disabled]:hover>a:only-child,.ant-btn-danger[disabled]:focus>a:only-child,.ant-btn-danger[disabled]:active>a:only-child{color:currentColor}.ant-btn-danger[disabled]>a:only-child:after,.ant-btn-danger[disabled]:hover>a:only-child:after,.ant-btn-danger[disabled]:focus>a:only-child:after,.ant-btn-danger[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-link{color:#1890ff;background:transparent;border-color:transparent;box-shadow:none}.ant-btn-link>a:only-child{color:currentColor}.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-link:hover,.ant-btn-link:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-link:hover>a:only-child,.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-link:hover>a:only-child:after,.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-link:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-link:active>a:only-child{color:currentColor}.ant-btn-link:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-link[disabled],.ant-btn-link[disabled]:hover,.ant-btn-link[disabled]:focus,.ant-btn-link[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-link:hover{background:transparent}.ant-btn-link:hover,.ant-btn-link:focus,.ant-btn-link:active{border-color:transparent}.ant-btn-link[disabled],.ant-btn-link[disabled]:hover,.ant-btn-link[disabled]:focus,.ant-btn-link[disabled]:active{color:#00000040;background:transparent;border-color:transparent;text-shadow:none;box-shadow:none}.ant-btn-link[disabled]>a:only-child,.ant-btn-link[disabled]:hover>a:only-child,.ant-btn-link[disabled]:focus>a:only-child,.ant-btn-link[disabled]:active>a:only-child{color:currentColor}.ant-btn-link[disabled]>a:only-child:after,.ant-btn-link[disabled]:hover>a:only-child:after,.ant-btn-link[disabled]:focus>a:only-child:after,.ant-btn-link[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-text{color:#000000d9;background:transparent;border-color:transparent;box-shadow:none}.ant-btn-text>a:only-child{color:currentColor}.ant-btn-text>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-text:hover,.ant-btn-text:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-text:hover>a:only-child,.ant-btn-text:focus>a:only-child{color:currentColor}.ant-btn-text:hover>a:only-child:after,.ant-btn-text:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-text:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-text:active>a:only-child{color:currentColor}.ant-btn-text:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-text[disabled],.ant-btn-text[disabled]:hover,.ant-btn-text[disabled]:focus,.ant-btn-text[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-text:hover,.ant-btn-text:focus{color:#000000d9;background:rgba(0,0,0,.018);border-color:transparent}.ant-btn-text:active{color:#000000d9;background:rgba(0,0,0,.028);border-color:transparent}.ant-btn-text[disabled],.ant-btn-text[disabled]:hover,.ant-btn-text[disabled]:focus,.ant-btn-text[disabled]:active{color:#00000040;background:transparent;border-color:transparent;text-shadow:none;box-shadow:none}.ant-btn-text[disabled]>a:only-child,.ant-btn-text[disabled]:hover>a:only-child,.ant-btn-text[disabled]:focus>a:only-child,.ant-btn-text[disabled]:active>a:only-child{color:currentColor}.ant-btn-text[disabled]>a:only-child:after,.ant-btn-text[disabled]:hover>a:only-child:after,.ant-btn-text[disabled]:focus>a:only-child:after,.ant-btn-text[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous{color:#ff4d4f;background:#fff;border-color:#ff4d4f}.ant-btn-dangerous>a:only-child{color:currentColor}.ant-btn-dangerous>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous:hover,.ant-btn-dangerous:focus{color:#ff7875;background:#fff;border-color:#ff7875}.ant-btn-dangerous:hover>a:only-child,.ant-btn-dangerous:focus>a:only-child{color:currentColor}.ant-btn-dangerous:hover>a:only-child:after,.ant-btn-dangerous:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous:active{color:#d9363e;background:#fff;border-color:#d9363e}.ant-btn-dangerous:active>a:only-child{color:currentColor}.ant-btn-dangerous:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous[disabled],.ant-btn-dangerous[disabled]:hover,.ant-btn-dangerous[disabled]:focus,.ant-btn-dangerous[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-dangerous[disabled]>a:only-child,.ant-btn-dangerous[disabled]:hover>a:only-child,.ant-btn-dangerous[disabled]:focus>a:only-child,.ant-btn-dangerous[disabled]:active>a:only-child{color:currentColor}.ant-btn-dangerous[disabled]>a:only-child:after,.ant-btn-dangerous[disabled]:hover>a:only-child:after,.ant-btn-dangerous[disabled]:focus>a:only-child:after,.ant-btn-dangerous[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-primary{color:#fff;background:#ff7875;border-color:#ff7875;text-shadow:0 -1px 0 rgba(0,0,0,.12);box-shadow:0 2px #0000000b}.ant-btn-dangerous.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-primary:hover,.ant-btn-dangerous.ant-btn-primary:focus{color:#fff;background:#ffa39e;border-color:#ffa39e}.ant-btn-dangerous.ant-btn-primary:hover>a:only-child,.ant-btn-dangerous.ant-btn-primary:focus>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-primary:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-primary:active{color:#fff;background:#d9595b;border-color:#d9595b}.ant-btn-dangerous.ant-btn-primary:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-primary[disabled],.ant-btn-dangerous.ant-btn-primary[disabled]:hover,.ant-btn-dangerous.ant-btn-primary[disabled]:focus,.ant-btn-dangerous.ant-btn-primary[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-dangerous.ant-btn-primary[disabled]>a:only-child,.ant-btn-dangerous.ant-btn-primary[disabled]:hover>a:only-child,.ant-btn-dangerous.ant-btn-primary[disabled]:focus>a:only-child,.ant-btn-dangerous.ant-btn-primary[disabled]:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary[disabled]>a:only-child:after,.ant-btn-dangerous.ant-btn-primary[disabled]:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-primary[disabled]:focus>a:only-child:after,.ant-btn-dangerous.ant-btn-primary[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-link{color:#ff4d4f;background:transparent;border-color:transparent;box-shadow:none}.ant-btn-dangerous.ant-btn-link>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-dangerous.ant-btn-link:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-dangerous.ant-btn-link:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-dangerous.ant-btn-link[disabled],.ant-btn-dangerous.ant-btn-link[disabled]:hover,.ant-btn-dangerous.ant-btn-link[disabled]:focus,.ant-btn-dangerous.ant-btn-link[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-dangerous.ant-btn-link:focus{color:#ff7875;background:transparent;border-color:transparent}.ant-btn-dangerous.ant-btn-link:hover>a:only-child,.ant-btn-dangerous.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-link:active{color:#d9363e;background:transparent;border-color:transparent}.ant-btn-dangerous.ant-btn-link:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-link[disabled],.ant-btn-dangerous.ant-btn-link[disabled]:hover,.ant-btn-dangerous.ant-btn-link[disabled]:focus,.ant-btn-dangerous.ant-btn-link[disabled]:active{color:#00000040;background:transparent;border-color:transparent;text-shadow:none;box-shadow:none}.ant-btn-dangerous.ant-btn-link[disabled]>a:only-child,.ant-btn-dangerous.ant-btn-link[disabled]:hover>a:only-child,.ant-btn-dangerous.ant-btn-link[disabled]:focus>a:only-child,.ant-btn-dangerous.ant-btn-link[disabled]:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link[disabled]>a:only-child:after,.ant-btn-dangerous.ant-btn-link[disabled]:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-link[disabled]:focus>a:only-child:after,.ant-btn-dangerous.ant-btn-link[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-text{color:#ff4d4f;background:transparent;border-color:transparent;box-shadow:none}.ant-btn-dangerous.ant-btn-text>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-text>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-text:hover,.ant-btn-dangerous.ant-btn-text:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-dangerous.ant-btn-text:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-dangerous.ant-btn-text[disabled],.ant-btn-dangerous.ant-btn-text[disabled]:hover,.ant-btn-dangerous.ant-btn-text[disabled]:focus,.ant-btn-dangerous.ant-btn-text[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-dangerous.ant-btn-text:hover,.ant-btn-dangerous.ant-btn-text:focus{color:#ff7875;background:rgba(0,0,0,.018);border-color:transparent}.ant-btn-dangerous.ant-btn-text:hover>a:only-child,.ant-btn-dangerous.ant-btn-text:focus>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-text:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-text:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-text:active{color:#d9363e;background:rgba(0,0,0,.028);border-color:transparent}.ant-btn-dangerous.ant-btn-text:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-text:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-dangerous.ant-btn-text[disabled],.ant-btn-dangerous.ant-btn-text[disabled]:hover,.ant-btn-dangerous.ant-btn-text[disabled]:focus,.ant-btn-dangerous.ant-btn-text[disabled]:active{color:#00000040;background:transparent;border-color:transparent;text-shadow:none;box-shadow:none}.ant-btn-dangerous.ant-btn-text[disabled]>a:only-child,.ant-btn-dangerous.ant-btn-text[disabled]:hover>a:only-child,.ant-btn-dangerous.ant-btn-text[disabled]:focus>a:only-child,.ant-btn-dangerous.ant-btn-text[disabled]:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-text[disabled]>a:only-child:after,.ant-btn-dangerous.ant-btn-text[disabled]:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-text[disabled]:focus>a:only-child:after,.ant-btn-dangerous.ant-btn-text[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-icon-only{width:32px;height:32px;padding:2.4px 0;font-size:16px;border-radius:2px;vertical-align:-1px}.ant-btn-icon-only>*{font-size:16px}.ant-btn-icon-only.ant-btn-lg{width:40px;height:40px;padding:4.9px 0;font-size:18px;border-radius:2px}.ant-btn-icon-only.ant-btn-lg>*{font-size:18px}.ant-btn-icon-only.ant-btn-sm{width:24px;height:24px;padding:0;font-size:14px;border-radius:2px}.ant-btn-icon-only.ant-btn-sm>*{font-size:14px}.ant-btn-round{height:32px;padding:4px 16px;font-size:14px;border-radius:32px}.ant-btn-round.ant-btn-lg{height:40px;padding:6.4px 20px;font-size:16px;border-radius:40px}.ant-btn-round.ant-btn-sm{height:24px;padding:0 12px;font-size:14px;border-radius:24px}.ant-btn-round.ant-btn-icon-only{width:auto}.ant-btn-circle{min-width:32px;padding-right:0;padding-left:0;text-align:center;border-radius:50%}.ant-btn-circle.ant-btn-lg{min-width:40px;border-radius:50%}.ant-btn-circle.ant-btn-sm{min-width:24px;border-radius:50%}.ant-btn:before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:1;display:none;background:#fff;border-radius:inherit;opacity:.35;transition:opacity .2s;content:\"\";pointer-events:none}.ant-btn .anticon{transition:margin-left .3s cubic-bezier(.645,.045,.355,1)}.ant-btn .anticon.anticon-plus>svg,.ant-btn .anticon.anticon-minus>svg{shape-rendering:optimizeSpeed}.ant-btn.ant-btn-loading{position:relative}.ant-btn.ant-btn-loading:not([disabled]){pointer-events:none}.ant-btn.ant-btn-loading:before{display:block}.ant-btn.ant-btn-loading:not(.ant-btn-circle):not(.ant-btn-circle-outline):not(.ant-btn-icon-only){padding-left:29px}.ant-btn.ant-btn-loading:not(.ant-btn-circle):not(.ant-btn-circle-outline):not(.ant-btn-icon-only) .anticon:not(:last-child){margin-left:-14px}.ant-btn-sm.ant-btn-loading:not(.ant-btn-circle):not(.ant-btn-circle-outline):not(.ant-btn-icon-only){padding-left:24px}.ant-btn-sm.ant-btn-loading:not(.ant-btn-circle):not(.ant-btn-circle-outline):not(.ant-btn-icon-only) .anticon{margin-left:-17px}.ant-btn-group{position:relative;display:inline-flex}.ant-btn-group>.ant-btn,.ant-btn-group>span>.ant-btn{position:relative}.ant-btn-group>.ant-btn:hover,.ant-btn-group>span>.ant-btn:hover,.ant-btn-group>.ant-btn:focus,.ant-btn-group>span>.ant-btn:focus,.ant-btn-group>.ant-btn:active,.ant-btn-group>span>.ant-btn:active{z-index:2}.ant-btn-group>.ant-btn[disabled],.ant-btn-group>span>.ant-btn[disabled]{z-index:0}.ant-btn-group .ant-btn-icon-only{font-size:14px}.ant-btn-group-lg>.ant-btn,.ant-btn-group-lg>span>.ant-btn{height:40px;padding:6.4px 15px;font-size:16px;border-radius:0}.ant-btn-group-lg .ant-btn.ant-btn-icon-only{width:40px;height:40px;padding-right:0;padding-left:0}.ant-btn-group-sm>.ant-btn,.ant-btn-group-sm>span>.ant-btn{height:24px;padding:0 7px;font-size:14px;border-radius:0}.ant-btn-group-sm>.ant-btn>.anticon,.ant-btn-group-sm>span>.ant-btn>.anticon{font-size:14px}.ant-btn-group-sm .ant-btn.ant-btn-icon-only{width:24px;height:24px;padding-right:0;padding-left:0}.ant-btn-group .ant-btn+.ant-btn,.ant-btn+.ant-btn-group,.ant-btn-group span+.ant-btn,.ant-btn-group .ant-btn+span,.ant-btn-group>span+span,.ant-btn-group+.ant-btn,.ant-btn-group+.ant-btn-group{margin-left:-1px}.ant-btn-group .ant-btn-primary+.ant-btn:not(.ant-btn-primary):not([disabled]){border-left-color:transparent}.ant-btn-group .ant-btn{border-radius:0}.ant-btn-group>.ant-btn:first-child,.ant-btn-group>span:first-child>.ant-btn{margin-left:0}.ant-btn-group>.ant-btn:only-child{border-radius:2px}.ant-btn-group>span:only-child>.ant-btn{border-radius:2px}.ant-btn-group>.ant-btn:first-child:not(:last-child),.ant-btn-group>span:first-child:not(:last-child)>.ant-btn{border-top-left-radius:2px;border-bottom-left-radius:2px}.ant-btn-group>.ant-btn:last-child:not(:first-child),.ant-btn-group>span:last-child:not(:first-child)>.ant-btn{border-top-right-radius:2px;border-bottom-right-radius:2px}.ant-btn-group-sm>.ant-btn:only-child{border-radius:2px}.ant-btn-group-sm>span:only-child>.ant-btn{border-radius:2px}.ant-btn-group-sm>.ant-btn:first-child:not(:last-child),.ant-btn-group-sm>span:first-child:not(:last-child)>.ant-btn{border-top-left-radius:2px;border-bottom-left-radius:2px}.ant-btn-group-sm>.ant-btn:last-child:not(:first-child),.ant-btn-group-sm>span:last-child:not(:first-child)>.ant-btn{border-top-right-radius:2px;border-bottom-right-radius:2px}.ant-btn-group>.ant-btn-group{float:left}.ant-btn-group>.ant-btn-group:not(:first-child):not(:last-child)>.ant-btn{border-radius:0}.ant-btn-group>.ant-btn-group:first-child:not(:last-child)>.ant-btn:last-child{padding-right:8px;border-top-right-radius:0;border-bottom-right-radius:0}.ant-btn-group>.ant-btn-group:last-child:not(:first-child)>.ant-btn:first-child{padding-left:8px;border-top-left-radius:0;border-bottom-left-radius:0}.ant-btn-rtl.ant-btn-group .ant-btn+.ant-btn,.ant-btn-rtl.ant-btn+.ant-btn-group,.ant-btn-rtl.ant-btn-group span+.ant-btn,.ant-btn-rtl.ant-btn-group .ant-btn+span,.ant-btn-rtl.ant-btn-group>span+span,.ant-btn-rtl.ant-btn-group+.ant-btn,.ant-btn-rtl.ant-btn-group+.ant-btn-group,.ant-btn-group-rtl.ant-btn-group .ant-btn+.ant-btn,.ant-btn-group-rtl.ant-btn+.ant-btn-group,.ant-btn-group-rtl.ant-btn-group span+.ant-btn,.ant-btn-group-rtl.ant-btn-group .ant-btn+span,.ant-btn-group-rtl.ant-btn-group>span+span,.ant-btn-group-rtl.ant-btn-group+.ant-btn,.ant-btn-group-rtl.ant-btn-group+.ant-btn-group{margin-right:-1px;margin-left:auto}.ant-btn-group.ant-btn-group-rtl{direction:rtl}.ant-btn-group-rtl.ant-btn-group>.ant-btn:first-child:not(:last-child),.ant-btn-group-rtl.ant-btn-group>span:first-child:not(:last-child)>.ant-btn{border-radius:0 2px 2px 0}.ant-btn-group-rtl.ant-btn-group>.ant-btn:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group>span:last-child:not(:first-child)>.ant-btn{border-radius:2px 0 0 2px}.ant-btn-group-rtl.ant-btn-group-sm>.ant-btn:first-child:not(:last-child),.ant-btn-group-rtl.ant-btn-group-sm>span:first-child:not(:last-child)>.ant-btn{border-radius:0 2px 2px 0}.ant-btn-group-rtl.ant-btn-group-sm>.ant-btn:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group-sm>span:last-child:not(:first-child)>.ant-btn{border-radius:2px 0 0 2px}.ant-btn:focus>span,.ant-btn:active>span{position:relative}.ant-btn>.anticon+span,.ant-btn>span+.anticon{margin-left:8px}.ant-btn-background-ghost{color:#fff;background:transparent!important;border-color:#fff}.ant-btn-background-ghost.ant-btn-primary{color:#1890ff;background:transparent;border-color:#1890ff;text-shadow:none}.ant-btn-background-ghost.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-primary:hover,.ant-btn-background-ghost.ant-btn-primary:focus{color:#40a9ff;background:transparent;border-color:#40a9ff}.ant-btn-background-ghost.ant-btn-primary:hover>a:only-child,.ant-btn-background-ghost.ant-btn-primary:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-primary:active{color:#096dd9;background:transparent;border-color:#096dd9}.ant-btn-background-ghost.ant-btn-primary:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-primary[disabled],.ant-btn-background-ghost.ant-btn-primary[disabled]:hover,.ant-btn-background-ghost.ant-btn-primary[disabled]:focus,.ant-btn-background-ghost.ant-btn-primary[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-background-ghost.ant-btn-primary[disabled]>a:only-child,.ant-btn-background-ghost.ant-btn-primary[disabled]:hover>a:only-child,.ant-btn-background-ghost.ant-btn-primary[disabled]:focus>a:only-child,.ant-btn-background-ghost.ant-btn-primary[disabled]:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary[disabled]>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary[disabled]:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary[disabled]:focus>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-danger{color:#ff7875;background:transparent;border-color:#ff7875;text-shadow:none}.ant-btn-background-ghost.ant-btn-danger>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-danger:hover,.ant-btn-background-ghost.ant-btn-danger:focus{color:#ffa39e;background:transparent;border-color:#ffa39e}.ant-btn-background-ghost.ant-btn-danger:hover>a:only-child,.ant-btn-background-ghost.ant-btn-danger:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-danger:active{color:#d9595b;background:transparent;border-color:#d9595b}.ant-btn-background-ghost.ant-btn-danger:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-danger[disabled],.ant-btn-background-ghost.ant-btn-danger[disabled]:hover,.ant-btn-background-ghost.ant-btn-danger[disabled]:focus,.ant-btn-background-ghost.ant-btn-danger[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-background-ghost.ant-btn-danger[disabled]>a:only-child,.ant-btn-background-ghost.ant-btn-danger[disabled]:hover>a:only-child,.ant-btn-background-ghost.ant-btn-danger[disabled]:focus>a:only-child,.ant-btn-background-ghost.ant-btn-danger[disabled]:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger[disabled]>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger[disabled]:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger[disabled]:focus>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous{color:#ff7875;background:transparent;border-color:#ff7875;text-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous:hover,.ant-btn-background-ghost.ant-btn-dangerous:focus{color:#ffa39e;background:transparent;border-color:#ffa39e}.ant-btn-background-ghost.ant-btn-dangerous:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous:active{color:#d9595b;background:transparent;border-color:#d9595b}.ant-btn-background-ghost.ant-btn-dangerous:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous[disabled],.ant-btn-background-ghost.ant-btn-dangerous[disabled]:hover,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:focus,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous[disabled]>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:focus>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous[disabled]>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:focus>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link{color:#ff7875;background:transparent;border-color:transparent;text-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus{color:#ffa39e;background:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active{color:#d9595b;background:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled],.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:focus,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:focus>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:focus>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-btn-two-chinese-chars:first-letter{letter-spacing:.34em}.ant-btn-two-chinese-chars>*:not(.anticon){margin-right:-.34em;letter-spacing:.34em}.ant-btn-block{width:100%}.ant-btn:empty{display:inline-block;width:0;visibility:hidden;content:\"\\a0\"}a.ant-btn{padding-top:.01px!important;line-height:30px}a.ant-btn-lg{line-height:38px}a.ant-btn-sm{line-height:22px}.ant-btn-rtl{direction:rtl}.ant-btn-group-rtl.ant-btn-group .ant-btn-primary:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group .ant-btn-primary+.ant-btn-primary{border-right-color:#40a9ff;border-left-color:#d9d9d9}.ant-btn-group-rtl.ant-btn-group .ant-btn-primary:last-child:not(:first-child)[disabled],.ant-btn-group-rtl.ant-btn-group .ant-btn-primary+.ant-btn-primary[disabled]{border-right-color:#d9d9d9;border-left-color:#40a9ff}.ant-btn-rtl.ant-btn>.ant-btn-loading-icon .anticon{padding-right:0;padding-left:8px}.ant-btn>.ant-btn-loading-icon:only-child .anticon{padding-right:0;padding-left:0}.ant-btn-rtl.ant-btn>.anticon+span,.ant-btn-rtl.ant-btn>span+.anticon{margin-right:8px;margin-left:0}.ant-avatar{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;overflow:hidden;color:#fff;white-space:nowrap;text-align:center;vertical-align:middle;background:#ccc;width:32px;height:32px;line-height:32px;border-radius:50%}.ant-avatar-image{background:transparent}.ant-avatar .ant-image-img{display:block}.ant-avatar-string{position:absolute;left:50%;transform-origin:0 center}.ant-avatar.ant-avatar-icon{font-size:18px}.ant-avatar.ant-avatar-icon>.anticon{margin:0}.ant-avatar-lg{width:40px;height:40px;line-height:40px;border-radius:50%}.ant-avatar-lg-string{position:absolute;left:50%;transform-origin:0 center}.ant-avatar-lg.ant-avatar-icon{font-size:24px}.ant-avatar-lg.ant-avatar-icon>.anticon{margin:0}.ant-avatar-sm{width:24px;height:24px;line-height:24px;border-radius:50%}.ant-avatar-sm-string{position:absolute;left:50%;transform-origin:0 center}.ant-avatar-sm.ant-avatar-icon{font-size:14px}.ant-avatar-sm.ant-avatar-icon>.anticon{margin:0}.ant-avatar-square{border-radius:2px}.ant-avatar>img{display:block;width:100%;height:100%;-o-object-fit:cover;object-fit:cover}.ant-avatar-group{display:inline-flex}.ant-avatar-group .ant-avatar{border:1px solid #fff}.ant-avatar-group .ant-avatar:not(:first-child){margin-left:-8px}.ant-avatar-group-popover .ant-avatar+.ant-avatar{margin-left:3px}.ant-avatar-group-rtl .ant-avatar:not(:first-child){margin-right:-8px;margin-left:0}.ant-avatar-group-popover.ant-popover-rtl .ant-avatar+.ant-avatar{margin-right:3px;margin-left:0}.ant-back-top{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:fixed;right:100px;bottom:50px;z-index:10;width:40px;height:40px;cursor:pointer}.ant-back-top:empty{display:none}.ant-back-top-rtl{right:auto;left:100px;direction:rtl}.ant-back-top-content{width:40px;height:40px;overflow:hidden;color:#fff;text-align:center;background-color:#00000073;border-radius:20px;transition:all .3s}.ant-back-top-content:hover{background-color:#000000d9;transition:all .3s}.ant-back-top-icon{font-size:24px;line-height:40px}@media screen and (max-width: 768px){.ant-back-top{right:60px}}@media screen and (max-width: 480px){.ant-back-top{right:20px}}.ant-badge{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;line-height:1}.ant-badge-count{z-index:1;min-width:20px;height:20px;padding:0 6px;color:#fff;font-weight:400;font-size:12px;line-height:20px;white-space:nowrap;text-align:center;background:#ff4d4f;border-radius:10px;box-shadow:0 0 0 1px #fff}.ant-badge-count a,.ant-badge-count a:hover{color:#fff}.ant-badge-count-sm{min-width:14px;height:14px;padding:0;font-size:12px;line-height:14px;border-radius:7px}.ant-badge-multiple-words{padding:0 8px}.ant-badge-dot{z-index:1;width:6px;min-width:6px;height:6px;background:#ff4d4f;border-radius:100%;box-shadow:0 0 0 1px #fff}.ant-badge-count,.ant-badge-dot,.ant-badge .ant-scroll-number-custom-component{position:absolute;top:0;right:0;transform:translate(50%,-50%);transform-origin:100% 0%}.ant-badge-count.anticon-spin,.ant-badge-dot.anticon-spin,.ant-badge .ant-scroll-number-custom-component.anticon-spin{-webkit-animation:antBadgeLoadingCircle 1s infinite linear;animation:antBadgeLoadingCircle 1s infinite linear}.ant-badge-status{line-height:inherit;vertical-align:baseline}.ant-badge-status-dot{position:relative;top:-1px;display:inline-block;width:6px;height:6px;vertical-align:middle;border-radius:50%}.ant-badge-status-success{background-color:#52c41a}.ant-badge-status-processing{position:relative;background-color:#1890ff}.ant-badge-status-processing:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:50%;-webkit-animation:antStatusProcessing 1.2s infinite ease-in-out;animation:antStatusProcessing 1.2s infinite ease-in-out;content:\"\"}.ant-badge-status-default{background-color:#d9d9d9}.ant-badge-status-error{background-color:#ff4d4f}.ant-badge-status-warning{background-color:#faad14}.ant-badge-status-pink,.ant-badge-status-magenta{background:#eb2f96}.ant-badge-status-red{background:#f5222d}.ant-badge-status-volcano{background:#fa541c}.ant-badge-status-orange{background:#fa8c16}.ant-badge-status-yellow{background:#fadb14}.ant-badge-status-gold{background:#faad14}.ant-badge-status-cyan{background:#13c2c2}.ant-badge-status-lime{background:#a0d911}.ant-badge-status-green{background:#52c41a}.ant-badge-status-blue{background:#1890ff}.ant-badge-status-geekblue{background:#2f54eb}.ant-badge-status-purple{background:#722ed1}.ant-badge-status-text{margin-left:8px;color:#000000d9;font-size:14px}.ant-badge-zoom-appear,.ant-badge-zoom-enter{-webkit-animation:antZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46);animation:antZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46);-webkit-animation-fill-mode:both;animation-fill-mode:both}.ant-badge-zoom-leave{-webkit-animation:antZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6);animation:antZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6);-webkit-animation-fill-mode:both;animation-fill-mode:both}.ant-badge-not-a-wrapper .ant-badge-zoom-appear,.ant-badge-not-a-wrapper .ant-badge-zoom-enter{-webkit-animation:antNoWrapperZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46);animation:antNoWrapperZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46)}.ant-badge-not-a-wrapper .ant-badge-zoom-leave{-webkit-animation:antNoWrapperZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6);animation:antNoWrapperZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6)}.ant-badge-not-a-wrapper:not(.ant-badge-status){vertical-align:middle}.ant-badge-not-a-wrapper .ant-scroll-number-custom-component{transform:none}.ant-badge-not-a-wrapper .ant-scroll-number-custom-component,.ant-badge-not-a-wrapper .ant-scroll-number{position:relative;top:auto;display:block;transform-origin:50% 50%}@-webkit-keyframes antStatusProcessing{0%{transform:scale(.8);opacity:.5}to{transform:scale(2.4);opacity:0}}@keyframes antStatusProcessing{0%{transform:scale(.8);opacity:.5}to{transform:scale(2.4);opacity:0}}.ant-scroll-number{overflow:hidden}.ant-scroll-number-only{position:relative;display:inline-block;height:20px;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-transform-style:preserve-3d;-webkit-backface-visibility:hidden}.ant-scroll-number-only>p.ant-scroll-number-only-unit{height:20px;margin:0;-webkit-transform-style:preserve-3d;-webkit-backface-visibility:hidden}.ant-scroll-number-symbol{vertical-align:top}@-webkit-keyframes antZoomBadgeIn{0%{transform:scale(0) translate(50%,-50%);opacity:0}to{transform:scale(1) translate(50%,-50%)}}@keyframes antZoomBadgeIn{0%{transform:scale(0) translate(50%,-50%);opacity:0}to{transform:scale(1) translate(50%,-50%)}}@-webkit-keyframes antZoomBadgeOut{0%{transform:scale(1) translate(50%,-50%)}to{transform:scale(0) translate(50%,-50%);opacity:0}}@keyframes antZoomBadgeOut{0%{transform:scale(1) translate(50%,-50%)}to{transform:scale(0) translate(50%,-50%);opacity:0}}@-webkit-keyframes antNoWrapperZoomBadgeIn{0%{transform:scale(0);opacity:0}to{transform:scale(1)}}@keyframes antNoWrapperZoomBadgeIn{0%{transform:scale(0);opacity:0}to{transform:scale(1)}}@-webkit-keyframes antNoWrapperZoomBadgeOut{0%{transform:scale(1)}to{transform:scale(0);opacity:0}}@keyframes antNoWrapperZoomBadgeOut{0%{transform:scale(1)}to{transform:scale(0);opacity:0}}@-webkit-keyframes antBadgeLoadingCircle{0%{transform-origin:50%}to{transform:translate(50%,-50%) rotate(360deg);transform-origin:50%}}@keyframes antBadgeLoadingCircle{0%{transform-origin:50%}to{transform:translate(50%,-50%) rotate(360deg);transform-origin:50%}}.ant-ribbon-wrapper{position:relative}.ant-ribbon{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;top:8px;height:22px;padding:0 8px;color:#fff;line-height:22px;white-space:nowrap;background-color:#1890ff;border-radius:2px}.ant-ribbon-text{color:#fff}.ant-ribbon-corner{position:absolute;top:100%;width:8px;height:8px;color:currentColor;border:4px solid;transform:scaleY(.75);transform-origin:top}.ant-ribbon-corner:after{position:absolute;top:-4px;left:-4px;width:inherit;height:inherit;color:#00000040;border:inherit;content:\"\"}.ant-ribbon-color-pink,.ant-ribbon-color-magenta{color:#eb2f96;background:#eb2f96}.ant-ribbon-color-red{color:#f5222d;background:#f5222d}.ant-ribbon-color-volcano{color:#fa541c;background:#fa541c}.ant-ribbon-color-orange{color:#fa8c16;background:#fa8c16}.ant-ribbon-color-yellow{color:#fadb14;background:#fadb14}.ant-ribbon-color-gold{color:#faad14;background:#faad14}.ant-ribbon-color-cyan{color:#13c2c2;background:#13c2c2}.ant-ribbon-color-lime{color:#a0d911;background:#a0d911}.ant-ribbon-color-green{color:#52c41a;background:#52c41a}.ant-ribbon-color-blue{color:#1890ff;background:#1890ff}.ant-ribbon-color-geekblue{color:#2f54eb;background:#2f54eb}.ant-ribbon-color-purple{color:#722ed1;background:#722ed1}.ant-ribbon.ant-ribbon-placement-end{right:-8px;border-bottom-right-radius:0}.ant-ribbon.ant-ribbon-placement-end .ant-ribbon-corner{right:0;border-color:currentColor transparent transparent currentColor}.ant-ribbon.ant-ribbon-placement-start{left:-8px;border-bottom-left-radius:0}.ant-ribbon.ant-ribbon-placement-start .ant-ribbon-corner{left:0;border-color:currentColor currentColor transparent transparent}.ant-badge-rtl{direction:rtl}.ant-badge-rtl .ant-badge-count,.ant-badge-rtl .ant-badge-dot,.ant-badge-rtl .ant-badge .ant-scroll-number-custom-component{right:auto;left:0;direction:ltr;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl.ant-badge .ant-scroll-number-custom-component{right:auto;left:0;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl .ant-badge-status-text{margin-right:8px;margin-left:0}.ant-badge-rtl .ant-badge-zoom-appear,.ant-badge-rtl .ant-badge-zoom-enter{-webkit-animation-name:antZoomBadgeInRtl;animation-name:antZoomBadgeInRtl}.ant-badge-rtl .ant-badge-zoom-leave{-webkit-animation-name:antZoomBadgeOutRtl;animation-name:antZoomBadgeOutRtl}.ant-badge-not-a-wrapper .ant-badge-count{transform:none}.ant-ribbon-rtl{direction:rtl}.ant-ribbon-rtl.ant-ribbon-placement-end{right:unset;left:-8px;border-bottom-right-radius:2px;border-bottom-left-radius:0}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner{right:unset;left:0;border-color:currentColor currentColor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner:after{border-color:currentColor currentColor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-start{right:-8px;left:unset;border-bottom-right-radius:0;border-bottom-left-radius:2px}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner{right:0;left:unset;border-color:currentColor transparent transparent currentColor}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner:after{border-color:currentColor transparent transparent currentColor}@-webkit-keyframes antZoomBadgeInRtl{0%{transform:scale(0) translate(-50%,-50%);opacity:0}to{transform:scale(1) translate(-50%,-50%)}}@keyframes antZoomBadgeInRtl{0%{transform:scale(0) translate(-50%,-50%);opacity:0}to{transform:scale(1) translate(-50%,-50%)}}@-webkit-keyframes antZoomBadgeOutRtl{0%{transform:scale(1) translate(-50%,-50%)}to{transform:scale(0) translate(-50%,-50%);opacity:0}}@keyframes antZoomBadgeOutRtl{0%{transform:scale(1) translate(-50%,-50%)}to{transform:scale(0) translate(-50%,-50%);opacity:0}}.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";color:#00000073;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#00000073;transition:color .3s}.ant-breadcrumb a:hover{color:#40a9ff}.ant-breadcrumb>span:last-child{color:#000000d9}.ant-breadcrumb>span:last-child a{color:#000000d9}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#00000073}.ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-link>.anticon+a{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before,.ant-breadcrumb-rtl:after{display:table;content:\"\"}.ant-breadcrumb-rtl:after{clear:both}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+a{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.ant-menu-item-danger.ant-menu-item,.ant-menu-item-danger.ant-menu-item:hover,.ant-menu-item-danger.ant-menu-item-active{color:#ff4d4f}.ant-menu-item-danger.ant-menu-item:active{background:#fff1f0}.ant-menu-item-danger.ant-menu-item-selected{color:#ff4d4f}.ant-menu-item-danger.ant-menu-item-selected>a,.ant-menu-item-danger.ant-menu-item-selected>a:hover{color:#ff4d4f}.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-danger.ant-menu-item-selected{background-color:#fff1f0}.ant-menu-inline .ant-menu-item-danger.ant-menu-item:after{border-right-color:#ff4d4f}.ant-menu-dark .ant-menu-item-danger.ant-menu-item,.ant-menu-dark .ant-menu-item-danger.ant-menu-item:hover,.ant-menu-dark .ant-menu-item-danger.ant-menu-item>a{color:#ff4d4f}.ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-danger.ant-menu-item-selected{color:#fff;background-color:#ff4d4f}.ant-menu{box-sizing:border-box;margin:0;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:\"tnum\";padding:0;color:#000000d9;font-size:14px;line-height:0;text-align:left;list-style:none;background:#fff;outline:none;box-shadow:0 2px 8px #00000026;transition:background .3s,width .3s cubic-bezier(.2,0,0,1) 0s}.ant-menu:before,.ant-menu:after{display:table;content:\"\"}.ant-menu:after{clear:both}.ant-menu.ant-menu-root:focus-visible{box-shadow:0 0 0 2px #1890ff33}.ant-menu ul,.ant-menu ol{margin:0;padding:0;list-style:none}.ant-menu-overflow{display:flex}.ant-menu-overflow-item{flex:none}.ant-menu-hidden,.ant-menu-submenu-hidden{display:none}.ant-menu-item-group-title{height:1.5715;padding:8px 16px;color:#00000073;font-size:14px;line-height:1.5715;transition:all .3s}.ant-menu-horizontal .ant-menu-submenu{transition:border-color .3s cubic-bezier(.645,.045,.355,1),background .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu,.ant-menu-submenu-inline{transition:border-color .3s cubic-bezier(.645,.045,.355,1),background .3s cubic-bezier(.645,.045,.355,1),padding .15s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-selected{color:#1890ff}.ant-menu-item:active,.ant-menu-submenu-title:active{background:#e6f7ff}.ant-menu-submenu .ant-menu-sub{cursor:initial;transition:background .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-item a{color:#000000d9}.ant-menu-item a:hover{color:#1890ff}.ant-menu-item a:before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:transparent;content:\"\"}.ant-menu-item>.ant-badge a{color:#000000d9}.ant-menu-item>.ant-badge a:hover{color:#1890ff}.ant-menu-item-divider{height:1px;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-menu-horizontal .ant-menu-item,.ant-menu-horizontal .ant-menu-submenu{margin-top:-1px}.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-submenu .ant-menu-submenu-title:hover{background-color:transparent}.ant-menu-item-selected,.ant-menu-item-selected a,.ant-menu-item-selected a:hover{color:#1890ff}.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{background-color:#e6f7ff}.ant-menu-inline,.ant-menu-vertical,.ant-menu-vertical-left{border-right:1px solid #f0f0f0}.ant-menu-vertical-right{border-left:1px solid #f0f0f0}.ant-menu-vertical.ant-menu-sub,.ant-menu-vertical-left.ant-menu-sub,.ant-menu-vertical-right.ant-menu-sub{min-width:160px;max-height:calc(100vh - 100px);padding:0;overflow:hidden;border-right:0}.ant-menu-vertical.ant-menu-sub:not([class*=\"-active\"]),.ant-menu-vertical-left.ant-menu-sub:not([class*=\"-active\"]),.ant-menu-vertical-right.ant-menu-sub:not([class*=\"-active\"]){overflow-x:hidden;overflow-y:auto}.ant-menu-vertical.ant-menu-sub .ant-menu-item,.ant-menu-vertical-left.ant-menu-sub .ant-menu-item,.ant-menu-vertical-right.ant-menu-sub .ant-menu-item{left:0;margin-left:0;border-right:0}.ant-menu-vertical.ant-menu-sub .ant-menu-item:after,.ant-menu-vertical-left.ant-menu-sub .ant-menu-item:after,.ant-menu-vertical-right.ant-menu-sub .ant-menu-item:after{border-right:0}.ant-menu-vertical.ant-menu-sub>.ant-menu-item,.ant-menu-vertical-left.ant-menu-sub>.ant-menu-item,.ant-menu-vertical-right.ant-menu-sub>.ant-menu-item,.ant-menu-vertical.ant-menu-sub>.ant-menu-submenu,.ant-menu-vertical-left.ant-menu-sub>.ant-menu-submenu,.ant-menu-vertical-right.ant-menu-sub>.ant-menu-submenu{transform-origin:0 0}.ant-menu-horizontal.ant-menu-sub{min-width:114px}.ant-menu-horizontal .ant-menu-item,.ant-menu-horizontal .ant-menu-submenu-title{transition:border-color .3s,background .3s}.ant-menu-item,.ant-menu-submenu-title{position:relative;display:block;margin:0;padding:0 20px;white-space:nowrap;cursor:pointer;transition:border-color .3s,background .3s,padding .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-item .ant-menu-item-icon,.ant-menu-submenu-title .ant-menu-item-icon,.ant-menu-item .anticon,.ant-menu-submenu-title .anticon{min-width:14px;font-size:14px;transition:font-size .15s cubic-bezier(.215,.61,.355,1),margin .3s cubic-bezier(.645,.045,.355,1),color .3s}.ant-menu-item .ant-menu-item-icon+span,.ant-menu-submenu-title .ant-menu-item-icon+span,.ant-menu-item .anticon+span,.ant-menu-submenu-title .anticon+span{margin-left:10px;opacity:1;transition:opacity .3s cubic-bezier(.645,.045,.355,1),margin .3s,color .3s}.ant-menu-item .ant-menu-item-icon.svg,.ant-menu-submenu-title .ant-menu-item-icon.svg{vertical-align:-.125em}.ant-menu-item.ant-menu-item-only-child>.anticon,.ant-menu-submenu-title.ant-menu-item-only-child>.anticon,.ant-menu-item.ant-menu-item-only-child>.ant-menu-item-icon,.ant-menu-submenu-title.ant-menu-item-only-child>.ant-menu-item-icon{margin-right:0}.ant-menu-item:focus-visible,.ant-menu-submenu-title:focus-visible{box-shadow:0 0 0 2px #1890ff33}.ant-menu>.ant-menu-item-divider{height:1px;margin:1px 0;padding:0;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-menu-submenu-popup{position:absolute;z-index:1050;background:transparent;border-radius:2px;box-shadow:none;transform-origin:0 0}.ant-menu-submenu-popup:before{position:absolute;top:-7px;right:0;bottom:0;left:0;z-index:-1;width:100%;height:100%;opacity:.0001;content:\" \"}.ant-menu-submenu-placement-rightTop:before{top:0;left:-7px}.ant-menu-submenu>.ant-menu{background-color:#fff;border-radius:2px}.ant-menu-submenu>.ant-menu-submenu-title:after{transition:transform .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-popup>.ant-menu{background-color:#fff}.ant-menu-submenu-expand-icon,.ant-menu-submenu-arrow{position:absolute;top:50%;right:16px;width:10px;color:#000000d9;transform:translateY(-50%);transition:transform .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-arrow:before,.ant-menu-submenu-arrow:after{position:absolute;width:6px;height:1.5px;background-color:currentColor;border-radius:2px;transition:background .3s cubic-bezier(.645,.045,.355,1),transform .3s cubic-bezier(.645,.045,.355,1),top .3s cubic-bezier(.645,.045,.355,1),color .3s cubic-bezier(.645,.045,.355,1);content:\"\"}.ant-menu-submenu-arrow:before{transform:rotate(45deg) translateY(-2.5px)}.ant-menu-submenu-arrow:after{transform:rotate(-45deg) translateY(2.5px)}.ant-menu-submenu:hover>.ant-menu-submenu-title>.ant-menu-submenu-expand-icon,.ant-menu-submenu:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow{color:#1890ff}.ant-menu-inline-collapsed .ant-menu-submenu-arrow:before,.ant-menu-submenu-inline .ant-menu-submenu-arrow:before{transform:rotate(-45deg) translate(2.5px)}.ant-menu-inline-collapsed .ant-menu-submenu-arrow:after,.ant-menu-submenu-inline .ant-menu-submenu-arrow:after{transform:rotate(45deg) translate(-2.5px)}.ant-menu-submenu-horizontal .ant-menu-submenu-arrow{display:none}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title>.ant-menu-submenu-arrow{transform:translateY(-2px)}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after{transform:rotate(-45deg) translate(-2.5px)}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before{transform:rotate(45deg) translate(2.5px)}.ant-menu-vertical .ant-menu-submenu-selected,.ant-menu-vertical-left .ant-menu-submenu-selected,.ant-menu-vertical-right .ant-menu-submenu-selected{color:#1890ff}.ant-menu-horizontal{line-height:46px;border:0;border-bottom:1px solid #f0f0f0;box-shadow:none}.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu{margin-top:-1px;margin-bottom:0;padding:0 20px}.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item:hover,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu:hover,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-active,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-active,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-open,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-open,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-selected,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-selected{color:#1890ff}.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item:hover:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu:hover:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-active:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-active:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-open:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-open:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-item-selected:after,.ant-menu-horizontal:not(.ant-menu-dark)>.ant-menu-submenu-selected:after{border-bottom:2px solid #1890ff}.ant-menu-horizontal>.ant-menu-item,.ant-menu-horizontal>.ant-menu-submenu{position:relative;top:1px;display:inline-block;vertical-align:bottom}.ant-menu-horizontal>.ant-menu-item:after,.ant-menu-horizontal>.ant-menu-submenu:after{position:absolute;right:20px;bottom:0;left:20px;border-bottom:2px solid transparent;transition:border-color .3s cubic-bezier(.645,.045,.355,1);content:\"\"}.ant-menu-horizontal>.ant-menu-submenu>.ant-menu-submenu-title{padding:0}.ant-menu-horizontal>.ant-menu-item a{color:#000000d9}.ant-menu-horizontal>.ant-menu-item a:hover{color:#1890ff}.ant-menu-horizontal>.ant-menu-item a:before{bottom:-2px}.ant-menu-horizontal>.ant-menu-item-selected a{color:#1890ff}.ant-menu-horizontal:after{display:block;clear:both;height:0;content:\" \"}.ant-menu-vertical .ant-menu-item,.ant-menu-vertical-left .ant-menu-item,.ant-menu-vertical-right .ant-menu-item,.ant-menu-inline .ant-menu-item{position:relative}.ant-menu-vertical .ant-menu-item:after,.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-vertical-right .ant-menu-item:after,.ant-menu-inline .ant-menu-item:after{position:absolute;top:0;right:0;bottom:0;border-right:3px solid #1890ff;transform:scaleY(.0001);opacity:0;transition:transform .15s cubic-bezier(.215,.61,.355,1),opacity .15s cubic-bezier(.215,.61,.355,1);content:\"\"}.ant-menu-vertical .ant-menu-item,.ant-menu-vertical-left .ant-menu-item,.ant-menu-vertical-right .ant-menu-item,.ant-menu-inline .ant-menu-item,.ant-menu-vertical .ant-menu-submenu-title,.ant-menu-vertical-left .ant-menu-submenu-title,.ant-menu-vertical-right .ant-menu-submenu-title,.ant-menu-inline .ant-menu-submenu-title{height:40px;margin-top:4px;margin-bottom:4px;padding:0 16px;overflow:hidden;line-height:40px;text-overflow:ellipsis}.ant-menu-vertical .ant-menu-submenu,.ant-menu-vertical-left .ant-menu-submenu,.ant-menu-vertical-right .ant-menu-submenu,.ant-menu-inline .ant-menu-submenu{padding-bottom:.02px}.ant-menu-vertical .ant-menu-item:not(:last-child),.ant-menu-vertical-left .ant-menu-item:not(:last-child),.ant-menu-vertical-right .ant-menu-item:not(:last-child),.ant-menu-inline .ant-menu-item:not(:last-child){margin-bottom:8px}.ant-menu-vertical>.ant-menu-item,.ant-menu-vertical-left>.ant-menu-item,.ant-menu-vertical-right>.ant-menu-item,.ant-menu-inline>.ant-menu-item,.ant-menu-vertical>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-vertical-left>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-vertical-right>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title{height:40px;line-height:40px}.ant-menu-vertical .ant-menu-item-group-list .ant-menu-submenu-title,.ant-menu-vertical .ant-menu-submenu-title{padding-right:34px}.ant-menu-inline{width:100%}.ant-menu-inline .ant-menu-selected:after,.ant-menu-inline .ant-menu-item-selected:after{transform:scaleY(1);opacity:1;transition:transform .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1)}.ant-menu-inline .ant-menu-item,.ant-menu-inline .ant-menu-submenu-title{width:calc(100% + 1px)}.ant-menu-inline .ant-menu-item-group-list .ant-menu-submenu-title,.ant-menu-inline .ant-menu-submenu-title{padding-right:34px}.ant-menu-inline.ant-menu-root .ant-menu-item,.ant-menu-inline.ant-menu-root .ant-menu-submenu-title{display:flex;align-items:center;transition:border-color .3s,background .3s,padding .1s cubic-bezier(.215,.61,.355,1)}.ant-menu-inline.ant-menu-root .ant-menu-item>.ant-menu-title-content,.ant-menu-inline.ant-menu-root .ant-menu-submenu-title>.ant-menu-title-content{flex:auto;min-width:0;overflow:hidden;text-overflow:ellipsis}.ant-menu-inline.ant-menu-root .ant-menu-item>*,.ant-menu-inline.ant-menu-root .ant-menu-submenu-title>*{flex:none}.ant-menu.ant-menu-inline-collapsed{width:80px}.ant-menu.ant-menu-inline-collapsed>.ant-menu-item,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title{left:0;padding:0 calc(50% - 8px);text-overflow:clip}.ant-menu.ant-menu-inline-collapsed>.ant-menu-item .ant-menu-submenu-arrow,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .ant-menu-submenu-arrow,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-submenu-arrow{opacity:0}.ant-menu.ant-menu-inline-collapsed>.ant-menu-item .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item .anticon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .anticon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .anticon,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .anticon{margin:0;font-size:16px;line-height:40px}.ant-menu.ant-menu-inline-collapsed>.ant-menu-item .ant-menu-item-icon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .ant-menu-item-icon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-item-icon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-item-icon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item .anticon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .anticon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .anticon+span,.ant-menu.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .anticon+span{display:inline-block;opacity:0}.ant-menu.ant-menu-inline-collapsed .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed .anticon{display:inline-block}.ant-menu.ant-menu-inline-collapsed-tooltip{pointer-events:none}.ant-menu.ant-menu-inline-collapsed-tooltip .ant-menu-item-icon,.ant-menu.ant-menu-inline-collapsed-tooltip .anticon{display:none}.ant-menu.ant-menu-inline-collapsed-tooltip a{color:#ffffffd9}.ant-menu.ant-menu-inline-collapsed .ant-menu-item-group-title{padding-right:4px;padding-left:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-menu-item-group-list{margin:0;padding:0}.ant-menu-item-group-list .ant-menu-item,.ant-menu-item-group-list .ant-menu-submenu-title{padding:0 16px 0 28px}.ant-menu-root.ant-menu-vertical,.ant-menu-root.ant-menu-vertical-left,.ant-menu-root.ant-menu-vertical-right,.ant-menu-root.ant-menu-inline{box-shadow:none}.ant-menu-root.ant-menu-inline-collapsed .ant-menu-item>.ant-menu-inline-collapsed-noicon,.ant-menu-root.ant-menu-inline-collapsed .ant-menu-submenu .ant-menu-submenu-title>.ant-menu-inline-collapsed-noicon{font-size:16px;text-align:center}.ant-menu-sub.ant-menu-inline{padding:0;background:#fafafa;border:0;border-radius:0;box-shadow:none}.ant-menu-sub.ant-menu-inline>.ant-menu-item,.ant-menu-sub.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title{height:40px;line-height:40px;list-style-position:inside;list-style-type:disc}.ant-menu-sub.ant-menu-inline .ant-menu-item-group-title{padding-left:32px}.ant-menu-item-disabled,.ant-menu-submenu-disabled{color:#00000040!important;background:none;cursor:not-allowed}.ant-menu-item-disabled:after,.ant-menu-submenu-disabled:after{border-color:transparent!important}.ant-menu-item-disabled a,.ant-menu-submenu-disabled a{color:#00000040!important;pointer-events:none}.ant-menu-item-disabled>.ant-menu-submenu-title,.ant-menu-submenu-disabled>.ant-menu-submenu-title{color:#00000040!important;cursor:not-allowed}.ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after{background:rgba(0,0,0,.25)!important}.ant-layout-header .ant-menu{line-height:inherit}.ant-menu-light .ant-menu-item:hover,.ant-menu-light .ant-menu-item-active,.ant-menu-light .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,.ant-menu-light .ant-menu-submenu-active,.ant-menu-light .ant-menu-submenu-title:hover{color:#1890ff}.ant-menu.ant-menu-dark,.ant-menu-dark .ant-menu-sub,.ant-menu.ant-menu-dark .ant-menu-sub{color:#ffffffa6;background:#001529}.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow{opacity:.45;transition:all .3s}.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:before{background:#fff}.ant-menu-dark.ant-menu-submenu-popup{background:transparent}.ant-menu-dark .ant-menu-inline.ant-menu-sub{background:#000c17}.ant-menu-dark.ant-menu-horizontal{border-bottom:0}.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu{top:0;margin-top:0;padding:0 20px;border-color:#001529;border-bottom:0}.ant-menu-dark.ant-menu-horizontal>.ant-menu-item:hover{background-color:#1890ff}.ant-menu-dark.ant-menu-horizontal>.ant-menu-item>a:before{bottom:0}.ant-menu-dark .ant-menu-item,.ant-menu-dark .ant-menu-item-group-title,.ant-menu-dark .ant-menu-item>a,.ant-menu-dark .ant-menu-item>span>a{color:#ffffffa6}.ant-menu-dark.ant-menu-inline,.ant-menu-dark.ant-menu-vertical,.ant-menu-dark.ant-menu-vertical-left,.ant-menu-dark.ant-menu-vertical-right{border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item,.ant-menu-dark.ant-menu-vertical .ant-menu-item,.ant-menu-dark.ant-menu-vertical-left .ant-menu-item,.ant-menu-dark.ant-menu-vertical-right .ant-menu-item{left:0;margin-left:0;border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical-right .ant-menu-item:after{border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item,.ant-menu-dark.ant-menu-inline .ant-menu-submenu-title{width:100%}.ant-menu-dark .ant-menu-item:hover,.ant-menu-dark .ant-menu-item-active,.ant-menu-dark .ant-menu-submenu-active,.ant-menu-dark .ant-menu-submenu-open,.ant-menu-dark .ant-menu-submenu-selected,.ant-menu-dark .ant-menu-submenu-title:hover{color:#fff;background-color:transparent}.ant-menu-dark .ant-menu-item:hover>a,.ant-menu-dark .ant-menu-item-active>a,.ant-menu-dark .ant-menu-submenu-active>a,.ant-menu-dark .ant-menu-submenu-open>a,.ant-menu-dark .ant-menu-submenu-selected>a,.ant-menu-dark .ant-menu-submenu-title:hover>a,.ant-menu-dark .ant-menu-item:hover>span>a,.ant-menu-dark .ant-menu-item-active>span>a,.ant-menu-dark .ant-menu-submenu-active>span>a,.ant-menu-dark .ant-menu-submenu-open>span>a,.ant-menu-dark .ant-menu-submenu-selected>span>a,.ant-menu-dark .ant-menu-submenu-title:hover>span>a{color:#fff}.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow{opacity:1}.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before{background:#fff}.ant-menu-dark .ant-menu-item:hover{background-color:transparent}.ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-selected{background-color:#1890ff}.ant-menu-dark .ant-menu-item-selected{color:#fff;border-right:0}.ant-menu-dark .ant-menu-item-selected:after{border-right:0}.ant-menu-dark .ant-menu-item-selected>a,.ant-menu-dark .ant-menu-item-selected>span>a,.ant-menu-dark .ant-menu-item-selected>a:hover,.ant-menu-dark .ant-menu-item-selected>span>a:hover{color:#fff}.ant-menu-dark .ant-menu-item-selected .ant-menu-item-icon,.ant-menu-dark .ant-menu-item-selected .anticon{color:#fff}.ant-menu-dark .ant-menu-item-selected .ant-menu-item-icon+span,.ant-menu-dark .ant-menu-item-selected .anticon+span{color:#fff}.ant-menu.ant-menu-dark .ant-menu-item-selected,.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected{background-color:#1890ff}.ant-menu-dark .ant-menu-item-disabled,.ant-menu-dark .ant-menu-submenu-disabled,.ant-menu-dark .ant-menu-item-disabled>a,.ant-menu-dark .ant-menu-submenu-disabled>a,.ant-menu-dark .ant-menu-item-disabled>span>a,.ant-menu-dark .ant-menu-submenu-disabled>span>a{color:#ffffff59!important;opacity:.8}.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title{color:#ffffff59!important}.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after{background:rgba(255,255,255,.35)!important}.ant-menu.ant-menu-rtl{direction:rtl;text-align:right}.ant-menu-rtl .ant-menu-item-group-title{text-align:right}.ant-menu-rtl.ant-menu-inline,.ant-menu-rtl.ant-menu-vertical{border-right:none;border-left:1px solid #f0f0f0}.ant-menu-rtl.ant-menu-dark.ant-menu-inline,.ant-menu-rtl.ant-menu-dark.ant-menu-vertical{border-left:none}.ant-menu-rtl.ant-menu-vertical.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical-left.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical-right.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical.ant-menu-sub>.ant-menu-submenu,.ant-menu-rtl.ant-menu-vertical-left.ant-menu-sub>.ant-menu-submenu,.ant-menu-rtl.ant-menu-vertical-right.ant-menu-sub>.ant-menu-submenu{transform-origin:top right}.ant-menu-rtl .ant-menu-item .ant-menu-item-icon,.ant-menu-rtl .ant-menu-submenu-title .ant-menu-item-icon,.ant-menu-rtl .ant-menu-item .anticon,.ant-menu-rtl .ant-menu-submenu-title .anticon{margin-right:auto;margin-left:10px}.ant-menu-rtl .ant-menu-item.ant-menu-item-only-child>.ant-menu-item-icon,.ant-menu-rtl .ant-menu-submenu-title.ant-menu-item-only-child>.ant-menu-item-icon,.ant-menu-rtl .ant-menu-item.ant-menu-item-only-child>.anticon,.ant-menu-rtl .ant-menu-submenu-title.ant-menu-item-only-child>.anticon{margin-left:0}.ant-menu-submenu-rtl.ant-menu-submenu-popup{transform-origin:100% 0}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow{right:auto;left:16px}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(-45deg) translateY(-2px)}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(45deg) translateY(2px)}.ant-menu-rtl.ant-menu-vertical .ant-menu-item:after,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-item:after,.ant-menu-rtl.ant-menu-inline .ant-menu-item:after{right:auto;left:0}.ant-menu-rtl.ant-menu-vertical .ant-menu-item,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-item,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-item,.ant-menu-rtl.ant-menu-inline .ant-menu-item,.ant-menu-rtl.ant-menu-vertical .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-inline .ant-menu-submenu-title{text-align:right}.ant-menu-rtl.ant-menu-inline .ant-menu-submenu-title{padding-right:0;padding-left:34px}.ant-menu-rtl.ant-menu-vertical .ant-menu-submenu-title{padding-right:16px;padding-left:34px}.ant-menu-rtl.ant-menu-inline-collapsed.ant-menu-vertical .ant-menu-submenu-title{padding:0 calc(50% - 8px)}.ant-menu-rtl .ant-menu-item-group-list .ant-menu-item,.ant-menu-rtl .ant-menu-item-group-list .ant-menu-submenu-title{padding:0 28px 0 16px}.ant-menu-sub.ant-menu-inline{border:0}.ant-menu-rtl.ant-menu-sub.ant-menu-inline .ant-menu-item-group-title{padding-right:32px;padding-left:0}.ant-tooltip{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;z-index:1060;display:block;max-width:250px;visibility:visible}.ant-tooltip-hidden{display:none}.ant-tooltip-placement-top,.ant-tooltip-placement-topLeft,.ant-tooltip-placement-topRight{padding-bottom:8px}.ant-tooltip-placement-right,.ant-tooltip-placement-rightTop,.ant-tooltip-placement-rightBottom{padding-left:8px}.ant-tooltip-placement-bottom,.ant-tooltip-placement-bottomLeft,.ant-tooltip-placement-bottomRight{padding-top:8px}.ant-tooltip-placement-left,.ant-tooltip-placement-leftTop,.ant-tooltip-placement-leftBottom{padding-right:8px}.ant-tooltip-inner{min-width:30px;min-height:32px;padding:6px 8px;color:#fff;text-align:left;text-decoration:none;word-wrap:break-word;background-color:#000000bf;border-radius:2px;box-shadow:0 2px 8px #00000026}.ant-tooltip-arrow{position:absolute;display:block;width:13.07106781px;height:13.07106781px;overflow:hidden;background:transparent;pointer-events:none}.ant-tooltip-arrow-content{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:5px;height:5px;margin:auto;background-color:#000000bf;content:\"\";pointer-events:auto}.ant-tooltip-placement-top .ant-tooltip-arrow,.ant-tooltip-placement-topLeft .ant-tooltip-arrow,.ant-tooltip-placement-topRight .ant-tooltip-arrow{bottom:-5.07106781px}.ant-tooltip-placement-top .ant-tooltip-arrow-content,.ant-tooltip-placement-topLeft .ant-tooltip-arrow-content,.ant-tooltip-placement-topRight .ant-tooltip-arrow-content{box-shadow:3px 3px 7px #00000012;transform:translateY(-6.53553391px) rotate(45deg)}.ant-tooltip-placement-top .ant-tooltip-arrow{left:50%;transform:translate(-50%)}.ant-tooltip-placement-topLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-topRight .ant-tooltip-arrow{right:13px}.ant-tooltip-placement-right .ant-tooltip-arrow,.ant-tooltip-placement-rightTop .ant-tooltip-arrow,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{left:-5.07106781px}.ant-tooltip-placement-right .ant-tooltip-arrow-content,.ant-tooltip-placement-rightTop .ant-tooltip-arrow-content,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow-content{box-shadow:-3px 3px 7px #00000012;transform:translate(6.53553391px) rotate(45deg)}.ant-tooltip-placement-right .ant-tooltip-arrow{top:50%;transform:translateY(-50%)}.ant-tooltip-placement-rightTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-left .ant-tooltip-arrow,.ant-tooltip-placement-leftTop .ant-tooltip-arrow,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{right:-5.07106781px}.ant-tooltip-placement-left .ant-tooltip-arrow-content,.ant-tooltip-placement-leftTop .ant-tooltip-arrow-content,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow-content{box-shadow:3px -3px 7px #00000012;transform:translate(-6.53553391px) rotate(45deg)}.ant-tooltip-placement-left .ant-tooltip-arrow{top:50%;transform:translateY(-50%)}.ant-tooltip-placement-leftTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-bottom .ant-tooltip-arrow,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{top:-5.07106781px}.ant-tooltip-placement-bottom .ant-tooltip-arrow-content,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow-content,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow-content{box-shadow:-3px -3px 7px #00000012;transform:translateY(6.53553391px) rotate(45deg)}.ant-tooltip-placement-bottom .ant-tooltip-arrow{left:50%;transform:translate(-50%)}.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{right:13px}.ant-tooltip-pink .ant-tooltip-inner,.ant-tooltip-pink .ant-tooltip-arrow-content,.ant-tooltip-magenta .ant-tooltip-inner,.ant-tooltip-magenta .ant-tooltip-arrow-content{background-color:#eb2f96}.ant-tooltip-red .ant-tooltip-inner,.ant-tooltip-red .ant-tooltip-arrow-content{background-color:#f5222d}.ant-tooltip-volcano .ant-tooltip-inner,.ant-tooltip-volcano .ant-tooltip-arrow-content{background-color:#fa541c}.ant-tooltip-orange .ant-tooltip-inner,.ant-tooltip-orange .ant-tooltip-arrow-content{background-color:#fa8c16}.ant-tooltip-yellow .ant-tooltip-inner,.ant-tooltip-yellow .ant-tooltip-arrow-content{background-color:#fadb14}.ant-tooltip-gold .ant-tooltip-inner,.ant-tooltip-gold .ant-tooltip-arrow-content{background-color:#faad14}.ant-tooltip-cyan .ant-tooltip-inner,.ant-tooltip-cyan .ant-tooltip-arrow-content{background-color:#13c2c2}.ant-tooltip-lime .ant-tooltip-inner,.ant-tooltip-lime .ant-tooltip-arrow-content{background-color:#a0d911}.ant-tooltip-green .ant-tooltip-inner,.ant-tooltip-green .ant-tooltip-arrow-content{background-color:#52c41a}.ant-tooltip-blue .ant-tooltip-inner,.ant-tooltip-blue .ant-tooltip-arrow-content{background-color:#1890ff}.ant-tooltip-geekblue .ant-tooltip-inner,.ant-tooltip-geekblue .ant-tooltip-arrow-content{background-color:#2f54eb}.ant-tooltip-purple .ant-tooltip-inner,.ant-tooltip-purple .ant-tooltip-arrow-content{background-color:#722ed1}.ant-dropdown-menu-item.ant-dropdown-menu-item-danger{color:#ff4d4f}.ant-dropdown-menu-item.ant-dropdown-menu-item-danger:hover{color:#fff;background-color:#ff4d4f}.ant-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;top:-9999px;left:-9999px;z-index:1050;display:block}.ant-dropdown:before{position:absolute;top:-4px;right:0;bottom:-4px;left:-7px;z-index:-9999;opacity:.0001;content:\" \"}.ant-dropdown-wrap{position:relative}.ant-dropdown-wrap .ant-btn>.anticon-down{display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0)}:root .ant-dropdown-wrap .ant-btn>.anticon-down{font-size:12px}.ant-dropdown-wrap .anticon-down:before{transition:transform .2s}.ant-dropdown-wrap-open .anticon-down:before{transform:rotate(180deg)}.ant-dropdown-hidden,.ant-dropdown-menu-hidden{display:none}.ant-dropdown-menu{position:relative;margin:0;padding:4px 0;text-align:left;list-style-type:none;background-color:#fff;background-clip:padding-box;border-radius:2px;outline:none;box-shadow:0 2px 8px #00000026;-webkit-transform:translate3d(0,0,0)}.ant-dropdown-menu-item-group-title{padding:5px 12px;color:#00000073;transition:all .3s}.ant-dropdown-menu-submenu-popup{position:absolute;z-index:1050;background:transparent;box-shadow:none;transform-origin:0 0}.ant-dropdown-menu-submenu-popup>.ant-dropdown-menu{transform-origin:0 0}.ant-dropdown-menu-submenu-popup ul,.ant-dropdown-menu-submenu-popup li{list-style:none}.ant-dropdown-menu-submenu-popup ul{margin-right:.3em;margin-left:.3em}.ant-dropdown-menu-item,.ant-dropdown-menu-submenu-title{clear:both;margin:0;padding:5px 12px;color:#000000d9;font-weight:400;font-size:14px;line-height:22px;white-space:nowrap;cursor:pointer;transition:all .3s}.ant-dropdown-menu-item>.anticon:first-child,.ant-dropdown-menu-submenu-title>.anticon:first-child,.ant-dropdown-menu-item>span>.anticon:first-child,.ant-dropdown-menu-submenu-title>span>.anticon:first-child{min-width:12px;margin-right:8px;font-size:12px}.ant-dropdown-menu-item>a,.ant-dropdown-menu-submenu-title>a{display:block;margin:-5px -12px;padding:5px 12px;color:#000000d9;transition:all .3s}.ant-dropdown-menu-item>a:hover,.ant-dropdown-menu-submenu-title>a:hover{color:#000000d9}.ant-dropdown-menu-item-selected,.ant-dropdown-menu-submenu-title-selected,.ant-dropdown-menu-item-selected>a,.ant-dropdown-menu-submenu-title-selected>a{color:#1890ff;background-color:#e6f7ff}.ant-dropdown-menu-item:hover,.ant-dropdown-menu-submenu-title:hover{background-color:#f5f5f5}.ant-dropdown-menu-item-disabled,.ant-dropdown-menu-submenu-title-disabled{color:#00000040;cursor:not-allowed}.ant-dropdown-menu-item-disabled:hover,.ant-dropdown-menu-submenu-title-disabled:hover{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-dropdown-menu-item-divider,.ant-dropdown-menu-submenu-title-divider{height:1px;margin:4px 0;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow,.ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow{position:absolute;right:8px}.ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow-icon,.ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{color:#00000073;font-style:normal;display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0)}:root .ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow-icon,:root .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{font-size:12px}.ant-dropdown-menu-item-group-list{margin:0 8px;padding:0;list-style:none}.ant-dropdown-menu-submenu-title{padding-right:26px}.ant-dropdown-menu-submenu-vertical{position:relative}.ant-dropdown-menu-submenu-vertical>.ant-dropdown-menu{position:absolute;top:0;left:100%;min-width:100%;margin-left:4px;transform-origin:0 0}.ant-dropdown-menu-submenu.ant-dropdown-menu-submenu-disabled .ant-dropdown-menu-submenu-title,.ant-dropdown-menu-submenu.ant-dropdown-menu-submenu-disabled .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-dropdown-menu-submenu-selected .ant-dropdown-menu-submenu-title{color:#1890ff}.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomRight,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomRight{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topRight,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topRight{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomRight{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topRight{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-dropdown-trigger>.anticon.anticon-down,.ant-dropdown-link>.anticon.anticon-down{display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0)}:root .ant-dropdown-trigger>.anticon.anticon-down,:root .ant-dropdown-link>.anticon.anticon-down{font-size:12px}.ant-dropdown-button{white-space:nowrap}.ant-dropdown-button.ant-btn-group>.ant-btn:last-child:not(:first-child){padding-right:8px;padding-left:8px}.ant-dropdown-button .anticon.anticon-down{display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0)}:root .ant-dropdown-button .anticon.anticon-down{font-size:12px}.ant-dropdown-menu-dark,.ant-dropdown-menu-dark .ant-dropdown-menu{background:#001529}.ant-dropdown-menu-dark .ant-dropdown-menu-item,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a{color:#ffffffa6}.ant-dropdown-menu-dark .ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow:after,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow:after,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a .ant-dropdown-menu-submenu-arrow:after{color:#ffffffa6}.ant-dropdown-menu-dark .ant-dropdown-menu-item:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a:hover{color:#fff;background:transparent}.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected,.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected>a{color:#fff;background:#1890ff}.ant-fullcalendar{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";border-top:1px solid #d9d9d9;outline:none}.ant-select.ant-fullcalendar-year-select{min-width:80px}.ant-select.ant-fullcalendar-year-select.ant-select-sm{min-width:70px}.ant-select.ant-fullcalendar-month-select{min-width:80px;margin-left:8px}.ant-select.ant-fullcalendar-month-select.ant-select-sm{min-width:70px}.ant-fullcalendar-header{padding:11px 16px 11px 0;text-align:right}.ant-fullcalendar-header .ant-select-dropdown{text-align:left}.ant-fullcalendar-header .ant-radio-group{margin-left:8px;text-align:left}.ant-fullcalendar-header label.ant-radio-button{height:22px;padding:0 10px;line-height:20px}.ant-fullcalendar-date-panel{position:relative;outline:none}.ant-fullcalendar-calendar-body{padding:8px 12px}.ant-fullcalendar table{width:100%;max-width:100%;height:256px;background-color:transparent;border-collapse:collapse}.ant-fullcalendar table,.ant-fullcalendar th,.ant-fullcalendar td{border:0}.ant-fullcalendar td{position:relative}.ant-fullcalendar-calendar-table{margin-bottom:0;border-spacing:0}.ant-fullcalendar-column-header{width:33px;padding:0;line-height:18px;text-align:center}.ant-fullcalendar-column-header .ant-fullcalendar-column-header-inner{display:block;font-weight:400}.ant-fullcalendar-week-number-header .ant-fullcalendar-column-header-inner{display:none}.ant-fullcalendar-month,.ant-fullcalendar-date{text-align:center;transition:all .3s}.ant-fullcalendar-value{display:block;width:24px;height:24px;margin:0 auto;padding:0;color:#000000d9;line-height:24px;background:transparent;border-radius:2px;transition:all .3s}.ant-fullcalendar-value:hover{background:#f5f5f5;cursor:pointer}.ant-fullcalendar-value:active{color:#fff;background:#1890ff}.ant-fullcalendar-month-panel-cell .ant-fullcalendar-value{width:48px}.ant-fullcalendar-today .ant-fullcalendar-value,.ant-fullcalendar-month-panel-current-cell .ant-fullcalendar-value{box-shadow:0 0 0 1px #1890ff inset}.ant-fullcalendar-selected-day .ant-fullcalendar-value,.ant-fullcalendar-month-panel-selected-cell .ant-fullcalendar-value{color:#fff;background:#1890ff}.ant-fullcalendar-disabled-cell-first-of-row .ant-fullcalendar-value{border-top-left-radius:2px;border-bottom-left-radius:2px}.ant-fullcalendar-disabled-cell-last-of-row .ant-fullcalendar-value{border-top-right-radius:2px;border-bottom-right-radius:2px}.ant-fullcalendar-last-month-cell .ant-fullcalendar-value,.ant-fullcalendar-next-month-btn-day .ant-fullcalendar-value{color:#00000040}.ant-fullcalendar-month-panel-table{width:100%;table-layout:fixed;border-collapse:separate}.ant-fullcalendar-content{position:absolute;bottom:-9px;left:0;width:100%}.ant-fullcalendar-fullscreen{border-top:0}.ant-fullcalendar-fullscreen .ant-fullcalendar-table{table-layout:fixed}.ant-fullcalendar-fullscreen .ant-fullcalendar-header .ant-radio-group{margin-left:16px}.ant-fullcalendar-fullscreen .ant-fullcalendar-header label.ant-radio-button{height:32px;line-height:30px}.ant-fullcalendar-fullscreen .ant-fullcalendar-month,.ant-fullcalendar-fullscreen .ant-fullcalendar-date{display:block;height:116px;margin:0 4px;padding:4px 8px;color:#000000d9;text-align:left;border-top:2px solid #f0f0f0;transition:background .3s}.ant-fullcalendar-fullscreen .ant-fullcalendar-month:hover,.ant-fullcalendar-fullscreen .ant-fullcalendar-date:hover{background:#f5f5f5;cursor:pointer}.ant-fullcalendar-fullscreen .ant-fullcalendar-month:active,.ant-fullcalendar-fullscreen .ant-fullcalendar-date:active{background:#bae7ff}.ant-fullcalendar-fullscreen .ant-fullcalendar-column-header{padding-right:12px;padding-bottom:5px;text-align:right}.ant-fullcalendar-fullscreen .ant-fullcalendar-value{width:auto;text-align:right;background:transparent}.ant-fullcalendar-fullscreen .ant-fullcalendar-today .ant-fullcalendar-value{color:#000000d9}.ant-fullcalendar-fullscreen .ant-fullcalendar-month-panel-current-cell .ant-fullcalendar-month,.ant-fullcalendar-fullscreen .ant-fullcalendar-today .ant-fullcalendar-date{background:transparent;border-top-color:#1890ff}.ant-fullcalendar-fullscreen .ant-fullcalendar-month-panel-current-cell .ant-fullcalendar-value,.ant-fullcalendar-fullscreen .ant-fullcalendar-today .ant-fullcalendar-value{box-shadow:none}.ant-fullcalendar-fullscreen .ant-fullcalendar-month-panel-selected-cell .ant-fullcalendar-month,.ant-fullcalendar-fullscreen .ant-fullcalendar-selected-day .ant-fullcalendar-date{background:#e6f7ff}.ant-fullcalendar-fullscreen .ant-fullcalendar-month-panel-selected-cell .ant-fullcalendar-value,.ant-fullcalendar-fullscreen .ant-fullcalendar-selected-day .ant-fullcalendar-value{color:#1890ff}.ant-fullcalendar-fullscreen .ant-fullcalendar-last-month-cell .ant-fullcalendar-date,.ant-fullcalendar-fullscreen .ant-fullcalendar-next-month-btn-day .ant-fullcalendar-date{color:#00000040}.ant-fullcalendar-fullscreen .ant-fullcalendar-content{position:static;width:auto;height:88px;overflow-y:auto}.ant-fullcalendar-disabled-cell .ant-fullcalendar-date,.ant-fullcalendar-disabled-cell .ant-fullcalendar-date:hover{cursor:not-allowed}.ant-fullcalendar-disabled-cell:not(.ant-fullcalendar-today) .ant-fullcalendar-date,.ant-fullcalendar-disabled-cell:not(.ant-fullcalendar-today) .ant-fullcalendar-date:hover{background:transparent}.ant-fullcalendar-disabled-cell .ant-fullcalendar-value{width:auto;color:#00000040;border-radius:0;cursor:not-allowed}.ant-radio-group{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block}.ant-radio-wrapper{box-sizing:border-box;margin:0 8px 0 0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;white-space:nowrap;cursor:pointer}.ant-radio{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;line-height:1;white-space:nowrap;vertical-align:sub;outline:none;cursor:pointer}.ant-radio-wrapper:hover .ant-radio,.ant-radio:hover .ant-radio-inner,.ant-radio-input:focus+.ant-radio-inner{border-color:#1890ff}.ant-radio-input:focus+.ant-radio-inner{box-shadow:0 0 0 3px #1890ff14}.ant-radio-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:50%;visibility:hidden;-webkit-animation:antRadioEffect .36s ease-in-out;animation:antRadioEffect .36s ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both;content:\"\"}.ant-radio:hover:after,.ant-radio-wrapper:hover .ant-radio:after{visibility:visible}.ant-radio-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border-color:#d9d9d9;border-style:solid;border-width:1px;border-radius:100px;transition:all .3s}.ant-radio-inner:after{position:absolute;top:3px;left:3px;display:table;width:8px;height:8px;background-color:#1890ff;border-top:0;border-left:0;border-radius:8px;transform:scale(0);opacity:0;transition:all .3s cubic-bezier(.78,.14,.15,.86);content:\" \"}.ant-radio-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;cursor:pointer;opacity:0}.ant-radio-checked .ant-radio-inner{border-color:#1890ff}.ant-radio-checked .ant-radio-inner:after{transform:scale(1);opacity:1;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-radio-disabled .ant-radio-inner{background-color:#f5f5f5;border-color:#d9d9d9!important;cursor:not-allowed}.ant-radio-disabled .ant-radio-inner:after{background-color:#0003}.ant-radio-disabled .ant-radio-input{cursor:not-allowed}.ant-radio-disabled+span{color:#00000040;cursor:not-allowed}span.ant-radio+*{padding-right:8px;padding-left:8px}.ant-radio-button-wrapper{position:relative;display:inline-block;height:32px;margin:0;padding:0 15px;color:#000000d9;line-height:30px;background:#fff;border:1px solid #d9d9d9;border-top-width:1.02px;border-left:0;cursor:pointer;transition:color .3s,background .3s,border-color .3s,box-shadow .3s}.ant-radio-button-wrapper a{color:#000000d9}.ant-radio-button-wrapper>.ant-radio-button{display:block;width:0;height:0;margin-left:0}.ant-radio-group-large .ant-radio-button-wrapper{height:40px;font-size:16px;line-height:38px}.ant-radio-group-small .ant-radio-button-wrapper{height:24px;padding:0 7px;line-height:22px}.ant-radio-button-wrapper:not(:first-child):before{position:absolute;top:-1px;left:-1px;display:block;box-sizing:content-box;width:1px;height:100%;padding:1px 0;background-color:#d9d9d9;transition:background-color .3s;content:\"\"}.ant-radio-button-wrapper:first-child{border-left:1px solid #d9d9d9;border-radius:2px 0 0 2px}.ant-radio-button-wrapper:last-child{border-radius:0 2px 2px 0}.ant-radio-button-wrapper:first-child:last-child{border-radius:2px}.ant-radio-button-wrapper:hover{position:relative;color:#1890ff}.ant-radio-button-wrapper:focus-within{box-shadow:0 0 0 3px #1890ff14}.ant-radio-button-wrapper .ant-radio-inner,.ant-radio-button-wrapper input[type=checkbox],.ant-radio-button-wrapper input[type=radio]{width:0;height:0;opacity:0;pointer-events:none}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){z-index:1;color:#1890ff;background:#fff;border-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):before{background-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):first-child{border-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#40a9ff;border-color:#40a9ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover:before{background-color:#40a9ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#096dd9;border-color:#096dd9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active:before{background-color:#096dd9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{box-shadow:0 0 0 3px #1890ff14}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){color:#fff;background:#1890ff;border-color:#1890ff}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#fff;background:#40a9ff;border-color:#40a9ff}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#fff;background:#096dd9;border-color:#096dd9}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{box-shadow:0 0 0 3px #1890ff14}.ant-radio-button-wrapper-disabled{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-radio-button-wrapper-disabled:first-child,.ant-radio-button-wrapper-disabled:hover{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9}.ant-radio-button-wrapper-disabled:first-child{border-left-color:#d9d9d9}.ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked{color:#00000040;background-color:#e6e6e6;border-color:#d9d9d9;box-shadow:none}@-webkit-keyframes antRadioEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@keyframes antRadioEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@supports (-moz-appearance: meterbar) and (background-blend-mode: difference,normal){.ant-radio{vertical-align:text-bottom}}.ant-card{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;background:#fff;border-radius:2px;transition:all .3s}.ant-card-hoverable{cursor:pointer;transition:box-shadow .3s border-color .3s}.ant-card-hoverable:hover{border-color:#00000017;box-shadow:0 2px 8px #00000017}.ant-card-bordered{border:1px solid #f0f0f0}.ant-card-head{min-height:48px;margin-bottom:-1px;padding:0 24px;color:#000000d9;font-weight:500;font-size:16px;background:transparent;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-card-head:before,.ant-card-head:after{display:table;content:\"\"}.ant-card-head:after{clear:both}.ant-card-head-wrapper{display:flex;align-items:center}.ant-card-head-title{display:inline-block;flex:1;padding:16px 0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-card-head .ant-tabs{clear:both;margin-bottom:-17px;color:#000000d9;font-weight:400;font-size:14px}.ant-card-head .ant-tabs-bar{border-bottom:1px solid #f0f0f0}.ant-card-extra{float:right;margin-left:auto;padding:16px 0;color:#000000d9;font-weight:400;font-size:14px}.ant-card-body{padding:24px}.ant-card-body:before,.ant-card-body:after{display:table;content:\"\"}.ant-card-body:after{clear:both}.ant-card-contain-grid:not(.ant-card-loading) .ant-card-body{margin:-1px 0 0 -1px;padding:0}.ant-card-grid{float:left;width:33.33%;padding:24px;border:0;border-radius:0;box-shadow:1px 0 #f0f0f0,0 1px #f0f0f0,1px 1px #f0f0f0,1px 0 #f0f0f0 inset,0 1px #f0f0f0 inset;transition:all .3s}.ant-card-grid-hoverable:hover{position:relative;z-index:1;box-shadow:0 2px 8px #00000026}.ant-card-contain-tabs>.ant-card-head .ant-card-head-title{min-height:32px;padding-bottom:0}.ant-card-contain-tabs>.ant-card-head .ant-card-extra{padding-bottom:0}.ant-card-cover>*{display:block;width:100%}.ant-card-cover img{border-radius:2px 2px 0 0}.ant-card-actions{margin:0;padding:0;list-style:none;background:#fafafa;border-top:1px solid #f0f0f0}.ant-card-actions:before,.ant-card-actions:after{display:table;content:\"\"}.ant-card-actions:after{clear:both}.ant-card-actions>li{float:left;margin:12px 0;color:#00000073;text-align:center}.ant-card-actions>li>span{position:relative;display:block;min-width:32px;font-size:14px;line-height:22px;cursor:pointer}.ant-card-actions>li>span:hover{color:#1890ff;transition:color .3s}.ant-card-actions>li>span a:not(.ant-btn),.ant-card-actions>li>span>.anticon{display:inline-block;width:100%;color:#00000073;line-height:22px;transition:color .3s}.ant-card-actions>li>span a:not(.ant-btn):hover,.ant-card-actions>li>span>.anticon:hover{color:#1890ff}.ant-card-actions>li>span>.anticon{font-size:16px;line-height:22px}.ant-card-actions>li:not(:last-child){border-right:1px solid #f0f0f0}.ant-card-type-inner .ant-card-head{padding:0 24px;background:#fafafa}.ant-card-type-inner .ant-card-head-title{padding:12px 0;font-size:14px}.ant-card-type-inner .ant-card-body{padding:16px 24px}.ant-card-type-inner .ant-card-extra{padding:13.5px 0}.ant-card-meta{margin:-4px 0}.ant-card-meta:before,.ant-card-meta:after{display:table;content:\"\"}.ant-card-meta:after{clear:both}.ant-card-meta-avatar{float:left;padding-right:16px}.ant-card-meta-detail{overflow:hidden}.ant-card-meta-detail>div:not(:last-child){margin-bottom:8px}.ant-card-meta-title{overflow:hidden;color:#000000d9;font-weight:500;font-size:16px;white-space:nowrap;text-overflow:ellipsis}.ant-card-meta-description{color:#00000073}.ant-card-loading{overflow:hidden}.ant-card-loading .ant-card-body{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-card-loading-content p{margin:0}.ant-card-loading-block{height:14px;margin:4px 0;background:linear-gradient(90deg,rgba(207,216,220,.2),rgba(207,216,220,.4),rgba(207,216,220,.2));background-size:600% 600%;border-radius:2px;-webkit-animation:card-loading 1.4s ease infinite;animation:card-loading 1.4s ease infinite}@-webkit-keyframes card-loading{0%,to{background-position:0 50%}50%{background-position:100% 50%}}@keyframes card-loading{0%,to{background-position:0 50%}50%{background-position:100% 50%}}.ant-card-small>.ant-card-head{min-height:36px;padding:0 12px;font-size:14px}.ant-card-small>.ant-card-head>.ant-card-head-wrapper>.ant-card-head-title{padding:8px 0}.ant-card-small>.ant-card-head>.ant-card-head-wrapper>.ant-card-extra{padding:8px 0;font-size:14px}.ant-card-small>.ant-card-body{padding:12px}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-nav-container{height:40px}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-ink-bar{visibility:hidden}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab{height:40px;margin:0 2px 0 0;padding:0 16px;line-height:38px;background:#fafafa;border:1px solid #f0f0f0;border-radius:2px 2px 0 0;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-active{height:40px;color:#1890ff;background:#fff;border-color:#f0f0f0;border-bottom:1px solid #fff}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-active:before{border-top:2px solid transparent}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-disabled{color:#1890ff;color:#00000040}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-inactive{padding:0}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-nav-wrap{margin-bottom:0}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab .ant-tabs-close-x{width:16px;height:16px;height:14px;margin-right:-5px;margin-left:3px;overflow:hidden;color:#00000073;font-size:12px;vertical-align:middle;transition:all .3s}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab .ant-tabs-close-x:hover{color:#000000d9}.ant-tabs.ant-tabs-card .ant-tabs-card-content>.ant-tabs-tabpane,.ant-tabs.ant-tabs-editable-card .ant-tabs-card-content>.ant-tabs-tabpane{transition:none!important}.ant-tabs.ant-tabs-card .ant-tabs-card-content>.ant-tabs-tabpane-inactive,.ant-tabs.ant-tabs-editable-card .ant-tabs-card-content>.ant-tabs-tabpane-inactive{overflow:hidden}.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab:hover .anticon-close{opacity:1}.ant-tabs-extra-content{line-height:46.001px}.ant-tabs-extra-content .ant-tabs-new-tab{position:relative;width:20px;height:20px;color:#000000d9;font-size:12px;line-height:20px;text-align:center;border:1px solid #f0f0f0;border-radius:2px;cursor:pointer;transition:all .3s}.ant-tabs-extra-content .ant-tabs-new-tab:hover{color:#1890ff;border-color:#1890ff}.ant-tabs-extra-content .ant-tabs-new-tab svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-tabs.ant-tabs-large .ant-tabs-extra-content{line-height:57.144px}.ant-tabs.ant-tabs-small .ant-tabs-extra-content{line-height:38.001px}.ant-tabs.ant-tabs-card .ant-tabs-extra-content{line-height:40px}.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-nav-container,.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-nav-container{height:100%}.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-tab,.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-tab{margin-bottom:8px;border-bottom:1px solid #f0f0f0}.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-tab-active,.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-tab-active{padding-bottom:4px}.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-tab:last-child,.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-tab:last-child{margin-bottom:8px}.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-new-tab,.ant-tabs-vertical.ant-tabs-card .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-new-tab{width:90%}.ant-tabs-vertical.ant-tabs-card.ant-tabs-left .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-nav-wrap{margin-right:0}.ant-tabs-vertical.ant-tabs-card.ant-tabs-left .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-tab{margin-right:1px;border-right:0;border-radius:2px 0 0 2px}.ant-tabs-vertical.ant-tabs-card.ant-tabs-left .ant-tabs-card-bar.ant-tabs-left-bar .ant-tabs-tab-active{margin-right:-1px;padding-right:18px}.ant-tabs-vertical.ant-tabs-card.ant-tabs-right .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-nav-wrap{margin-left:0}.ant-tabs-vertical.ant-tabs-card.ant-tabs-right .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-tab{margin-left:1px;border-left:0;border-radius:0 2px 2px 0}.ant-tabs-vertical.ant-tabs-card.ant-tabs-right .ant-tabs-card-bar.ant-tabs-right-bar .ant-tabs-tab-active{margin-left:-1px;padding-left:18px}.ant-tabs .ant-tabs-card-bar.ant-tabs-bottom-bar .ant-tabs-tab{height:auto;border-top:0;border-bottom:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-tabs .ant-tabs-card-bar.ant-tabs-bottom-bar .ant-tabs-tab-active{padding-top:1px;padding-bottom:0;color:#1890ff}.ant-tabs{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;overflow:hidden}.ant-tabs:before,.ant-tabs:after{display:table;content:\"\"}.ant-tabs:after{clear:both}.ant-tabs-ink-bar{position:absolute;bottom:1px;left:0;z-index:1;box-sizing:border-box;width:0;height:2px;background-color:#1890ff;transform-origin:0 0}.ant-tabs-bar{margin:0 0 16px;border-bottom:1px solid #f0f0f0;outline:none;transition:padding .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-nav-container{position:relative;box-sizing:border-box;margin-bottom:-1px;overflow:hidden;font-size:14px;line-height:1.5715;white-space:nowrap;transition:padding .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-nav-container:before,.ant-tabs-nav-container:after{display:table;content:\"\"}.ant-tabs-nav-container:after{clear:both}.ant-tabs-nav-container-scrolling{padding-right:32px;padding-left:32px}.ant-tabs-bottom .ant-tabs-bottom-bar{margin-top:16px;margin-bottom:0;border-top:1px solid #f0f0f0;border-bottom:none}.ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar{top:1px;bottom:auto}.ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-nav-container{margin-top:-1px;margin-bottom:0}.ant-tabs-tab-prev,.ant-tabs-tab-next{position:absolute;z-index:2;width:0;height:100%;color:#00000073;text-align:center;background-color:transparent;border:0;cursor:pointer;opacity:0;transition:width .3s cubic-bezier(.645,.045,.355,1),opacity .3s cubic-bezier(.645,.045,.355,1),color .3s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.ant-tabs-tab-prev.ant-tabs-tab-arrow-show,.ant-tabs-tab-next.ant-tabs-tab-arrow-show{width:32px;height:100%;opacity:1;pointer-events:auto}.ant-tabs-tab-prev:hover,.ant-tabs-tab-next:hover{color:#000000d9}.ant-tabs-tab-prev-icon,.ant-tabs-tab-next-icon{position:absolute;top:50%;left:50%;font-weight:700;font-style:normal;font-variant:normal;line-height:inherit;text-align:center;text-transform:none;transform:translate(-50%,-50%)}.ant-tabs-tab-prev-icon-target,.ant-tabs-tab-next-icon-target{display:block;display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0)}:root .ant-tabs-tab-prev-icon-target,:root .ant-tabs-tab-next-icon-target{font-size:12px}.ant-tabs-tab-btn-disabled{cursor:not-allowed}.ant-tabs-tab-btn-disabled,.ant-tabs-tab-btn-disabled:hover{color:#00000040}.ant-tabs-tab-next{right:2px}.ant-tabs-tab-prev{left:0}:root .ant-tabs-tab-prev{filter:none}.ant-tabs-nav-wrap{margin-bottom:-1px;overflow:hidden}.ant-tabs-nav-scroll{overflow:hidden;white-space:nowrap}.ant-tabs-nav{position:relative;display:inline-block;box-sizing:border-box;margin:0;padding-left:0;list-style:none;transition:transform .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-nav:before,.ant-tabs-nav:after{display:table;content:\" \"}.ant-tabs-nav:after{clear:both}.ant-tabs-nav .ant-tabs-tab{position:relative;display:inline-block;box-sizing:border-box;height:100%;margin:0 32px 0 0;padding:12px 16px;text-decoration:none;cursor:pointer;transition:color .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-nav .ant-tabs-tab:before{position:absolute;top:-1px;left:0;width:100%;border-top:2px solid transparent;border-radius:2px 2px 0 0;transition:all .3s;content:\"\";pointer-events:none}.ant-tabs-nav .ant-tabs-tab:last-child{margin-right:0}.ant-tabs-nav .ant-tabs-tab:hover{color:#40a9ff}.ant-tabs-nav .ant-tabs-tab:active{color:#096dd9}.ant-tabs-nav .ant-tabs-tab .anticon{margin-right:8px}.ant-tabs-nav .ant-tabs-tab-active{color:#1890ff;text-shadow:0 0 .25px currentColor}.ant-tabs-nav .ant-tabs-tab-disabled,.ant-tabs-nav .ant-tabs-tab-disabled:hover{color:#00000040;cursor:not-allowed}.ant-tabs .ant-tabs-large-bar .ant-tabs-nav-container{font-size:16px}.ant-tabs .ant-tabs-large-bar .ant-tabs-tab{padding:16px}.ant-tabs .ant-tabs-small-bar .ant-tabs-nav-container{font-size:14px}.ant-tabs .ant-tabs-small-bar .ant-tabs-tab{padding:8px 16px}.ant-tabs .ant-tabs-centered-bar .ant-tabs-nav-wrap{text-align:center}.ant-tabs-content:before{display:block;overflow:hidden;content:\"\"}.ant-tabs .ant-tabs-top-content,.ant-tabs .ant-tabs-bottom-content{width:100%}.ant-tabs .ant-tabs-top-content>.ant-tabs-tabpane,.ant-tabs .ant-tabs-bottom-content>.ant-tabs-tabpane{flex-shrink:0;width:100%;-webkit-backface-visibility:hidden;opacity:1;transition:opacity .45s}.ant-tabs .ant-tabs-top-content>.ant-tabs-tabpane-inactive,.ant-tabs .ant-tabs-bottom-content>.ant-tabs-tabpane-inactive{height:0;padding:0!important;overflow:hidden;opacity:0;pointer-events:none}.ant-tabs .ant-tabs-top-content>.ant-tabs-tabpane-inactive input,.ant-tabs .ant-tabs-bottom-content>.ant-tabs-tabpane-inactive input{visibility:hidden}.ant-tabs .ant-tabs-top-content.ant-tabs-content-animated,.ant-tabs .ant-tabs-bottom-content.ant-tabs-content-animated{display:flex;flex-direction:row;transition:margin-left .3s cubic-bezier(.645,.045,.355,1);will-change:margin-left}.ant-tabs .ant-tabs-left-bar,.ant-tabs .ant-tabs-right-bar{height:100%;border-bottom:0}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab-arrow-show,.ant-tabs .ant-tabs-right-bar .ant-tabs-tab-arrow-show{width:100%;height:32px}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab,.ant-tabs .ant-tabs-right-bar .ant-tabs-tab{display:block;float:none;margin:0 0 16px;padding:8px 24px}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab:last-child,.ant-tabs .ant-tabs-right-bar .ant-tabs-tab:last-child{margin-bottom:0}.ant-tabs .ant-tabs-left-bar .ant-tabs-extra-content,.ant-tabs .ant-tabs-right-bar .ant-tabs-extra-content{text-align:center}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-scroll,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-scroll{width:auto}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-container,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-container,.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-wrap,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-wrap{height:100%}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-container,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-container{margin-bottom:0}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-container.ant-tabs-nav-container-scrolling,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-container.ant-tabs-nav-container-scrolling{padding:32px 0}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-wrap,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-wrap{margin-bottom:0}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav{width:100%}.ant-tabs .ant-tabs-left-bar .ant-tabs-ink-bar,.ant-tabs .ant-tabs-right-bar .ant-tabs-ink-bar{top:0;bottom:auto;left:auto;width:2px;height:0}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab-next,.ant-tabs .ant-tabs-right-bar .ant-tabs-tab-next{right:0;bottom:0;width:100%;height:32px}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab-prev,.ant-tabs .ant-tabs-right-bar .ant-tabs-tab-prev{top:0;width:100%;height:32px}.ant-tabs .ant-tabs-left-content,.ant-tabs .ant-tabs-right-content{width:auto;margin-top:0!important;overflow:hidden}.ant-tabs .ant-tabs-left-bar{float:left;margin-right:-1px;margin-bottom:0;border-right:1px solid #f0f0f0}.ant-tabs .ant-tabs-left-bar .ant-tabs-tab{text-align:right}.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-container,.ant-tabs .ant-tabs-left-bar .ant-tabs-nav-wrap{margin-right:-1px}.ant-tabs .ant-tabs-left-bar .ant-tabs-ink-bar{right:1px}.ant-tabs .ant-tabs-left-content{padding-left:24px;border-left:1px solid #f0f0f0}.ant-tabs .ant-tabs-right-bar{float:right;margin-bottom:0;margin-left:-1px;border-left:1px solid #f0f0f0}.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-container,.ant-tabs .ant-tabs-right-bar .ant-tabs-nav-wrap{margin-left:-1px}.ant-tabs .ant-tabs-right-bar .ant-tabs-ink-bar{left:1px}.ant-tabs .ant-tabs-right-content{padding-right:24px;border-right:1px solid #f0f0f0}.ant-tabs-top .ant-tabs-ink-bar-animated,.ant-tabs-bottom .ant-tabs-ink-bar-animated{transition:transform .3s cubic-bezier(.645,.045,.355,1),width .2s cubic-bezier(.645,.045,.355,1),left .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-left .ant-tabs-ink-bar-animated,.ant-tabs-right .ant-tabs-ink-bar-animated{transition:transform .3s cubic-bezier(.645,.045,.355,1),height .2s cubic-bezier(.645,.045,.355,1),top .3s cubic-bezier(.645,.045,.355,1)}.no-flex>.ant-tabs-content>.ant-tabs-content-animated,.ant-tabs-no-animation>.ant-tabs-content>.ant-tabs-content-animated{margin-left:0!important;transform:none!important}.no-flex>.ant-tabs-content>.ant-tabs-tabpane-inactive,.ant-tabs-no-animation>.ant-tabs-content>.ant-tabs-tabpane-inactive{height:0;padding:0!important;overflow:hidden;opacity:0;pointer-events:none}.no-flex>.ant-tabs-content>.ant-tabs-tabpane-inactive input,.ant-tabs-no-animation>.ant-tabs-content>.ant-tabs-tabpane-inactive input{visibility:hidden}.ant-tabs-left-content>.ant-tabs-content-animated,.ant-tabs-right-content>.ant-tabs-content-animated{margin-left:0!important;transform:none!important}.ant-tabs-left-content>.ant-tabs-tabpane-inactive,.ant-tabs-right-content>.ant-tabs-tabpane-inactive{height:0;padding:0!important;overflow:hidden;opacity:0;pointer-events:none}.ant-tabs-left-content>.ant-tabs-tabpane-inactive input,.ant-tabs-right-content>.ant-tabs-tabpane-inactive input{visibility:hidden}.ant-row{display:flex;flex-flow:row wrap}.ant-row:before,.ant-row:after{display:flex}.ant-row-no-wrap{flex-wrap:nowrap}.ant-row-start{justify-content:flex-start}.ant-row-center{justify-content:center}.ant-row-end{justify-content:flex-end}.ant-row-space-between{justify-content:space-between}.ant-row-space-around{justify-content:space-around}.ant-row-top{align-items:flex-start}.ant-row-middle{align-items:center}.ant-row-bottom{align-items:flex-end}.ant-col{position:relative;max-width:100%;min-height:1px}.ant-col-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-push-24{left:100%}.ant-col-pull-24{right:100%}.ant-col-offset-24{margin-left:100%}.ant-col-order-24{order:24}.ant-col-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-push-23{left:95.83333333%}.ant-col-pull-23{right:95.83333333%}.ant-col-offset-23{margin-left:95.83333333%}.ant-col-order-23{order:23}.ant-col-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-push-22{left:91.66666667%}.ant-col-pull-22{right:91.66666667%}.ant-col-offset-22{margin-left:91.66666667%}.ant-col-order-22{order:22}.ant-col-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-push-21{left:87.5%}.ant-col-pull-21{right:87.5%}.ant-col-offset-21{margin-left:87.5%}.ant-col-order-21{order:21}.ant-col-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-push-20{left:83.33333333%}.ant-col-pull-20{right:83.33333333%}.ant-col-offset-20{margin-left:83.33333333%}.ant-col-order-20{order:20}.ant-col-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-push-19{left:79.16666667%}.ant-col-pull-19{right:79.16666667%}.ant-col-offset-19{margin-left:79.16666667%}.ant-col-order-19{order:19}.ant-col-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-push-18{left:75%}.ant-col-pull-18{right:75%}.ant-col-offset-18{margin-left:75%}.ant-col-order-18{order:18}.ant-col-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-push-17{left:70.83333333%}.ant-col-pull-17{right:70.83333333%}.ant-col-offset-17{margin-left:70.83333333%}.ant-col-order-17{order:17}.ant-col-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-push-16{left:66.66666667%}.ant-col-pull-16{right:66.66666667%}.ant-col-offset-16{margin-left:66.66666667%}.ant-col-order-16{order:16}.ant-col-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-push-15{left:62.5%}.ant-col-pull-15{right:62.5%}.ant-col-offset-15{margin-left:62.5%}.ant-col-order-15{order:15}.ant-col-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-push-14{left:58.33333333%}.ant-col-pull-14{right:58.33333333%}.ant-col-offset-14{margin-left:58.33333333%}.ant-col-order-14{order:14}.ant-col-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-push-13{left:54.16666667%}.ant-col-pull-13{right:54.16666667%}.ant-col-offset-13{margin-left:54.16666667%}.ant-col-order-13{order:13}.ant-col-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-push-12{left:50%}.ant-col-pull-12{right:50%}.ant-col-offset-12{margin-left:50%}.ant-col-order-12{order:12}.ant-col-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-push-11{left:45.83333333%}.ant-col-pull-11{right:45.83333333%}.ant-col-offset-11{margin-left:45.83333333%}.ant-col-order-11{order:11}.ant-col-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-push-10{left:41.66666667%}.ant-col-pull-10{right:41.66666667%}.ant-col-offset-10{margin-left:41.66666667%}.ant-col-order-10{order:10}.ant-col-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-push-9{left:37.5%}.ant-col-pull-9{right:37.5%}.ant-col-offset-9{margin-left:37.5%}.ant-col-order-9{order:9}.ant-col-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-push-8{left:33.33333333%}.ant-col-pull-8{right:33.33333333%}.ant-col-offset-8{margin-left:33.33333333%}.ant-col-order-8{order:8}.ant-col-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-push-7{left:29.16666667%}.ant-col-pull-7{right:29.16666667%}.ant-col-offset-7{margin-left:29.16666667%}.ant-col-order-7{order:7}.ant-col-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-push-6{left:25%}.ant-col-pull-6{right:25%}.ant-col-offset-6{margin-left:25%}.ant-col-order-6{order:6}.ant-col-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-push-5{left:20.83333333%}.ant-col-pull-5{right:20.83333333%}.ant-col-offset-5{margin-left:20.83333333%}.ant-col-order-5{order:5}.ant-col-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-push-4{left:16.66666667%}.ant-col-pull-4{right:16.66666667%}.ant-col-offset-4{margin-left:16.66666667%}.ant-col-order-4{order:4}.ant-col-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-push-3{left:12.5%}.ant-col-pull-3{right:12.5%}.ant-col-offset-3{margin-left:12.5%}.ant-col-order-3{order:3}.ant-col-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-push-2{left:8.33333333%}.ant-col-pull-2{right:8.33333333%}.ant-col-offset-2{margin-left:8.33333333%}.ant-col-order-2{order:2}.ant-col-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-push-1{left:4.16666667%}.ant-col-pull-1{right:4.16666667%}.ant-col-offset-1{margin-left:4.16666667%}.ant-col-order-1{order:1}.ant-col-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-offset-0{margin-left:0}.ant-col-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-offset-0.ant-col-rtl{margin-right:0}.ant-col-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}.ant-col-xs-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xs-push-24{left:100%}.ant-col-xs-pull-24{right:100%}.ant-col-xs-offset-24{margin-left:100%}.ant-col-xs-order-24{order:24}.ant-col-xs-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xs-push-23{left:95.83333333%}.ant-col-xs-pull-23{right:95.83333333%}.ant-col-xs-offset-23{margin-left:95.83333333%}.ant-col-xs-order-23{order:23}.ant-col-xs-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xs-push-22{left:91.66666667%}.ant-col-xs-pull-22{right:91.66666667%}.ant-col-xs-offset-22{margin-left:91.66666667%}.ant-col-xs-order-22{order:22}.ant-col-xs-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xs-push-21{left:87.5%}.ant-col-xs-pull-21{right:87.5%}.ant-col-xs-offset-21{margin-left:87.5%}.ant-col-xs-order-21{order:21}.ant-col-xs-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xs-push-20{left:83.33333333%}.ant-col-xs-pull-20{right:83.33333333%}.ant-col-xs-offset-20{margin-left:83.33333333%}.ant-col-xs-order-20{order:20}.ant-col-xs-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xs-push-19{left:79.16666667%}.ant-col-xs-pull-19{right:79.16666667%}.ant-col-xs-offset-19{margin-left:79.16666667%}.ant-col-xs-order-19{order:19}.ant-col-xs-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xs-push-18{left:75%}.ant-col-xs-pull-18{right:75%}.ant-col-xs-offset-18{margin-left:75%}.ant-col-xs-order-18{order:18}.ant-col-xs-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xs-push-17{left:70.83333333%}.ant-col-xs-pull-17{right:70.83333333%}.ant-col-xs-offset-17{margin-left:70.83333333%}.ant-col-xs-order-17{order:17}.ant-col-xs-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xs-push-16{left:66.66666667%}.ant-col-xs-pull-16{right:66.66666667%}.ant-col-xs-offset-16{margin-left:66.66666667%}.ant-col-xs-order-16{order:16}.ant-col-xs-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xs-push-15{left:62.5%}.ant-col-xs-pull-15{right:62.5%}.ant-col-xs-offset-15{margin-left:62.5%}.ant-col-xs-order-15{order:15}.ant-col-xs-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xs-push-14{left:58.33333333%}.ant-col-xs-pull-14{right:58.33333333%}.ant-col-xs-offset-14{margin-left:58.33333333%}.ant-col-xs-order-14{order:14}.ant-col-xs-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xs-push-13{left:54.16666667%}.ant-col-xs-pull-13{right:54.16666667%}.ant-col-xs-offset-13{margin-left:54.16666667%}.ant-col-xs-order-13{order:13}.ant-col-xs-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xs-push-12{left:50%}.ant-col-xs-pull-12{right:50%}.ant-col-xs-offset-12{margin-left:50%}.ant-col-xs-order-12{order:12}.ant-col-xs-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xs-push-11{left:45.83333333%}.ant-col-xs-pull-11{right:45.83333333%}.ant-col-xs-offset-11{margin-left:45.83333333%}.ant-col-xs-order-11{order:11}.ant-col-xs-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xs-push-10{left:41.66666667%}.ant-col-xs-pull-10{right:41.66666667%}.ant-col-xs-offset-10{margin-left:41.66666667%}.ant-col-xs-order-10{order:10}.ant-col-xs-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xs-push-9{left:37.5%}.ant-col-xs-pull-9{right:37.5%}.ant-col-xs-offset-9{margin-left:37.5%}.ant-col-xs-order-9{order:9}.ant-col-xs-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xs-push-8{left:33.33333333%}.ant-col-xs-pull-8{right:33.33333333%}.ant-col-xs-offset-8{margin-left:33.33333333%}.ant-col-xs-order-8{order:8}.ant-col-xs-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xs-push-7{left:29.16666667%}.ant-col-xs-pull-7{right:29.16666667%}.ant-col-xs-offset-7{margin-left:29.16666667%}.ant-col-xs-order-7{order:7}.ant-col-xs-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xs-push-6{left:25%}.ant-col-xs-pull-6{right:25%}.ant-col-xs-offset-6{margin-left:25%}.ant-col-xs-order-6{order:6}.ant-col-xs-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xs-push-5{left:20.83333333%}.ant-col-xs-pull-5{right:20.83333333%}.ant-col-xs-offset-5{margin-left:20.83333333%}.ant-col-xs-order-5{order:5}.ant-col-xs-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xs-push-4{left:16.66666667%}.ant-col-xs-pull-4{right:16.66666667%}.ant-col-xs-offset-4{margin-left:16.66666667%}.ant-col-xs-order-4{order:4}.ant-col-xs-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xs-push-3{left:12.5%}.ant-col-xs-pull-3{right:12.5%}.ant-col-xs-offset-3{margin-left:12.5%}.ant-col-xs-order-3{order:3}.ant-col-xs-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xs-push-2{left:8.33333333%}.ant-col-xs-pull-2{right:8.33333333%}.ant-col-xs-offset-2{margin-left:8.33333333%}.ant-col-xs-order-2{order:2}.ant-col-xs-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xs-push-1{left:4.16666667%}.ant-col-xs-pull-1{right:4.16666667%}.ant-col-xs-offset-1{margin-left:4.16666667%}.ant-col-xs-order-1{order:1}.ant-col-xs-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xs-push-0{left:auto}.ant-col-xs-pull-0{right:auto}.ant-col-xs-offset-0{margin-left:0}.ant-col-xs-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xs-push-0.ant-col-rtl{right:auto}.ant-col-xs-pull-0.ant-col-rtl{left:auto}.ant-col-xs-offset-0.ant-col-rtl{margin-right:0}.ant-col-xs-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xs-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xs-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xs-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xs-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xs-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xs-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xs-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xs-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xs-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xs-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xs-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xs-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xs-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xs-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xs-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xs-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xs-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xs-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xs-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xs-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xs-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xs-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xs-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xs-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xs-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xs-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xs-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xs-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xs-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xs-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xs-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xs-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xs-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xs-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xs-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xs-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xs-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xs-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xs-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xs-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xs-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xs-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xs-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xs-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xs-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xs-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xs-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xs-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xs-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xs-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xs-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xs-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xs-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xs-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xs-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xs-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xs-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xs-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xs-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xs-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xs-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xs-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xs-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xs-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xs-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xs-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xs-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xs-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xs-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xs-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xs-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}@media (min-width: 576px){.ant-col-sm-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-sm-push-24{left:100%}.ant-col-sm-pull-24{right:100%}.ant-col-sm-offset-24{margin-left:100%}.ant-col-sm-order-24{order:24}.ant-col-sm-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-sm-push-23{left:95.83333333%}.ant-col-sm-pull-23{right:95.83333333%}.ant-col-sm-offset-23{margin-left:95.83333333%}.ant-col-sm-order-23{order:23}.ant-col-sm-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-sm-push-22{left:91.66666667%}.ant-col-sm-pull-22{right:91.66666667%}.ant-col-sm-offset-22{margin-left:91.66666667%}.ant-col-sm-order-22{order:22}.ant-col-sm-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-sm-push-21{left:87.5%}.ant-col-sm-pull-21{right:87.5%}.ant-col-sm-offset-21{margin-left:87.5%}.ant-col-sm-order-21{order:21}.ant-col-sm-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-sm-push-20{left:83.33333333%}.ant-col-sm-pull-20{right:83.33333333%}.ant-col-sm-offset-20{margin-left:83.33333333%}.ant-col-sm-order-20{order:20}.ant-col-sm-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-sm-push-19{left:79.16666667%}.ant-col-sm-pull-19{right:79.16666667%}.ant-col-sm-offset-19{margin-left:79.16666667%}.ant-col-sm-order-19{order:19}.ant-col-sm-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-sm-push-18{left:75%}.ant-col-sm-pull-18{right:75%}.ant-col-sm-offset-18{margin-left:75%}.ant-col-sm-order-18{order:18}.ant-col-sm-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-sm-push-17{left:70.83333333%}.ant-col-sm-pull-17{right:70.83333333%}.ant-col-sm-offset-17{margin-left:70.83333333%}.ant-col-sm-order-17{order:17}.ant-col-sm-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-sm-push-16{left:66.66666667%}.ant-col-sm-pull-16{right:66.66666667%}.ant-col-sm-offset-16{margin-left:66.66666667%}.ant-col-sm-order-16{order:16}.ant-col-sm-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-sm-push-15{left:62.5%}.ant-col-sm-pull-15{right:62.5%}.ant-col-sm-offset-15{margin-left:62.5%}.ant-col-sm-order-15{order:15}.ant-col-sm-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-sm-push-14{left:58.33333333%}.ant-col-sm-pull-14{right:58.33333333%}.ant-col-sm-offset-14{margin-left:58.33333333%}.ant-col-sm-order-14{order:14}.ant-col-sm-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-sm-push-13{left:54.16666667%}.ant-col-sm-pull-13{right:54.16666667%}.ant-col-sm-offset-13{margin-left:54.16666667%}.ant-col-sm-order-13{order:13}.ant-col-sm-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-sm-push-12{left:50%}.ant-col-sm-pull-12{right:50%}.ant-col-sm-offset-12{margin-left:50%}.ant-col-sm-order-12{order:12}.ant-col-sm-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-sm-push-11{left:45.83333333%}.ant-col-sm-pull-11{right:45.83333333%}.ant-col-sm-offset-11{margin-left:45.83333333%}.ant-col-sm-order-11{order:11}.ant-col-sm-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-sm-push-10{left:41.66666667%}.ant-col-sm-pull-10{right:41.66666667%}.ant-col-sm-offset-10{margin-left:41.66666667%}.ant-col-sm-order-10{order:10}.ant-col-sm-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-sm-push-9{left:37.5%}.ant-col-sm-pull-9{right:37.5%}.ant-col-sm-offset-9{margin-left:37.5%}.ant-col-sm-order-9{order:9}.ant-col-sm-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-sm-push-8{left:33.33333333%}.ant-col-sm-pull-8{right:33.33333333%}.ant-col-sm-offset-8{margin-left:33.33333333%}.ant-col-sm-order-8{order:8}.ant-col-sm-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-sm-push-7{left:29.16666667%}.ant-col-sm-pull-7{right:29.16666667%}.ant-col-sm-offset-7{margin-left:29.16666667%}.ant-col-sm-order-7{order:7}.ant-col-sm-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-sm-push-6{left:25%}.ant-col-sm-pull-6{right:25%}.ant-col-sm-offset-6{margin-left:25%}.ant-col-sm-order-6{order:6}.ant-col-sm-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-sm-push-5{left:20.83333333%}.ant-col-sm-pull-5{right:20.83333333%}.ant-col-sm-offset-5{margin-left:20.83333333%}.ant-col-sm-order-5{order:5}.ant-col-sm-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-sm-push-4{left:16.66666667%}.ant-col-sm-pull-4{right:16.66666667%}.ant-col-sm-offset-4{margin-left:16.66666667%}.ant-col-sm-order-4{order:4}.ant-col-sm-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-sm-push-3{left:12.5%}.ant-col-sm-pull-3{right:12.5%}.ant-col-sm-offset-3{margin-left:12.5%}.ant-col-sm-order-3{order:3}.ant-col-sm-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-sm-push-2{left:8.33333333%}.ant-col-sm-pull-2{right:8.33333333%}.ant-col-sm-offset-2{margin-left:8.33333333%}.ant-col-sm-order-2{order:2}.ant-col-sm-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-sm-push-1{left:4.16666667%}.ant-col-sm-pull-1{right:4.16666667%}.ant-col-sm-offset-1{margin-left:4.16666667%}.ant-col-sm-order-1{order:1}.ant-col-sm-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-sm-push-0{left:auto}.ant-col-sm-pull-0{right:auto}.ant-col-sm-offset-0{margin-left:0}.ant-col-sm-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-sm-push-0.ant-col-rtl{right:auto}.ant-col-sm-pull-0.ant-col-rtl{left:auto}.ant-col-sm-offset-0.ant-col-rtl{margin-right:0}.ant-col-sm-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-sm-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-sm-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-sm-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-sm-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-sm-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-sm-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-sm-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-sm-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-sm-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-sm-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-sm-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-sm-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-sm-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-sm-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-sm-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-sm-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-sm-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-sm-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-sm-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-sm-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-sm-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-sm-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-sm-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-sm-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-sm-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-sm-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-sm-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-sm-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-sm-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-sm-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-sm-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-sm-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-sm-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-sm-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-sm-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-sm-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-sm-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-sm-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-sm-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-sm-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-sm-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-sm-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-sm-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-sm-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-sm-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-sm-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-sm-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-sm-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-sm-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-sm-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-sm-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-sm-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-sm-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-sm-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-sm-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-sm-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-sm-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-sm-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-sm-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-sm-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-sm-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-sm-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-sm-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-sm-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-sm-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-sm-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-sm-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-sm-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-sm-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-sm-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-sm-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 768px){.ant-col-md-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-md-push-24{left:100%}.ant-col-md-pull-24{right:100%}.ant-col-md-offset-24{margin-left:100%}.ant-col-md-order-24{order:24}.ant-col-md-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-md-push-23{left:95.83333333%}.ant-col-md-pull-23{right:95.83333333%}.ant-col-md-offset-23{margin-left:95.83333333%}.ant-col-md-order-23{order:23}.ant-col-md-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-md-push-22{left:91.66666667%}.ant-col-md-pull-22{right:91.66666667%}.ant-col-md-offset-22{margin-left:91.66666667%}.ant-col-md-order-22{order:22}.ant-col-md-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-md-push-21{left:87.5%}.ant-col-md-pull-21{right:87.5%}.ant-col-md-offset-21{margin-left:87.5%}.ant-col-md-order-21{order:21}.ant-col-md-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-md-push-20{left:83.33333333%}.ant-col-md-pull-20{right:83.33333333%}.ant-col-md-offset-20{margin-left:83.33333333%}.ant-col-md-order-20{order:20}.ant-col-md-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-md-push-19{left:79.16666667%}.ant-col-md-pull-19{right:79.16666667%}.ant-col-md-offset-19{margin-left:79.16666667%}.ant-col-md-order-19{order:19}.ant-col-md-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-md-push-18{left:75%}.ant-col-md-pull-18{right:75%}.ant-col-md-offset-18{margin-left:75%}.ant-col-md-order-18{order:18}.ant-col-md-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-md-push-17{left:70.83333333%}.ant-col-md-pull-17{right:70.83333333%}.ant-col-md-offset-17{margin-left:70.83333333%}.ant-col-md-order-17{order:17}.ant-col-md-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-md-push-16{left:66.66666667%}.ant-col-md-pull-16{right:66.66666667%}.ant-col-md-offset-16{margin-left:66.66666667%}.ant-col-md-order-16{order:16}.ant-col-md-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-md-push-15{left:62.5%}.ant-col-md-pull-15{right:62.5%}.ant-col-md-offset-15{margin-left:62.5%}.ant-col-md-order-15{order:15}.ant-col-md-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-md-push-14{left:58.33333333%}.ant-col-md-pull-14{right:58.33333333%}.ant-col-md-offset-14{margin-left:58.33333333%}.ant-col-md-order-14{order:14}.ant-col-md-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-md-push-13{left:54.16666667%}.ant-col-md-pull-13{right:54.16666667%}.ant-col-md-offset-13{margin-left:54.16666667%}.ant-col-md-order-13{order:13}.ant-col-md-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-md-push-12{left:50%}.ant-col-md-pull-12{right:50%}.ant-col-md-offset-12{margin-left:50%}.ant-col-md-order-12{order:12}.ant-col-md-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-md-push-11{left:45.83333333%}.ant-col-md-pull-11{right:45.83333333%}.ant-col-md-offset-11{margin-left:45.83333333%}.ant-col-md-order-11{order:11}.ant-col-md-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-md-push-10{left:41.66666667%}.ant-col-md-pull-10{right:41.66666667%}.ant-col-md-offset-10{margin-left:41.66666667%}.ant-col-md-order-10{order:10}.ant-col-md-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-md-push-9{left:37.5%}.ant-col-md-pull-9{right:37.5%}.ant-col-md-offset-9{margin-left:37.5%}.ant-col-md-order-9{order:9}.ant-col-md-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-md-push-8{left:33.33333333%}.ant-col-md-pull-8{right:33.33333333%}.ant-col-md-offset-8{margin-left:33.33333333%}.ant-col-md-order-8{order:8}.ant-col-md-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-md-push-7{left:29.16666667%}.ant-col-md-pull-7{right:29.16666667%}.ant-col-md-offset-7{margin-left:29.16666667%}.ant-col-md-order-7{order:7}.ant-col-md-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-md-push-6{left:25%}.ant-col-md-pull-6{right:25%}.ant-col-md-offset-6{margin-left:25%}.ant-col-md-order-6{order:6}.ant-col-md-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-md-push-5{left:20.83333333%}.ant-col-md-pull-5{right:20.83333333%}.ant-col-md-offset-5{margin-left:20.83333333%}.ant-col-md-order-5{order:5}.ant-col-md-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-md-push-4{left:16.66666667%}.ant-col-md-pull-4{right:16.66666667%}.ant-col-md-offset-4{margin-left:16.66666667%}.ant-col-md-order-4{order:4}.ant-col-md-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-md-push-3{left:12.5%}.ant-col-md-pull-3{right:12.5%}.ant-col-md-offset-3{margin-left:12.5%}.ant-col-md-order-3{order:3}.ant-col-md-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-md-push-2{left:8.33333333%}.ant-col-md-pull-2{right:8.33333333%}.ant-col-md-offset-2{margin-left:8.33333333%}.ant-col-md-order-2{order:2}.ant-col-md-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-md-push-1{left:4.16666667%}.ant-col-md-pull-1{right:4.16666667%}.ant-col-md-offset-1{margin-left:4.16666667%}.ant-col-md-order-1{order:1}.ant-col-md-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-md-push-0{left:auto}.ant-col-md-pull-0{right:auto}.ant-col-md-offset-0{margin-left:0}.ant-col-md-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-md-push-0.ant-col-rtl{right:auto}.ant-col-md-pull-0.ant-col-rtl{left:auto}.ant-col-md-offset-0.ant-col-rtl{margin-right:0}.ant-col-md-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-md-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-md-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-md-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-md-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-md-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-md-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-md-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-md-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-md-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-md-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-md-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-md-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-md-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-md-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-md-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-md-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-md-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-md-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-md-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-md-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-md-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-md-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-md-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-md-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-md-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-md-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-md-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-md-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-md-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-md-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-md-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-md-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-md-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-md-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-md-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-md-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-md-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-md-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-md-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-md-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-md-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-md-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-md-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-md-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-md-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-md-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-md-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-md-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-md-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-md-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-md-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-md-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-md-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-md-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-md-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-md-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-md-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-md-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-md-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-md-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-md-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-md-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-md-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-md-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-md-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-md-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-md-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-md-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-md-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-md-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-md-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 992px){.ant-col-lg-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-lg-push-24{left:100%}.ant-col-lg-pull-24{right:100%}.ant-col-lg-offset-24{margin-left:100%}.ant-col-lg-order-24{order:24}.ant-col-lg-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-lg-push-23{left:95.83333333%}.ant-col-lg-pull-23{right:95.83333333%}.ant-col-lg-offset-23{margin-left:95.83333333%}.ant-col-lg-order-23{order:23}.ant-col-lg-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-lg-push-22{left:91.66666667%}.ant-col-lg-pull-22{right:91.66666667%}.ant-col-lg-offset-22{margin-left:91.66666667%}.ant-col-lg-order-22{order:22}.ant-col-lg-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-lg-push-21{left:87.5%}.ant-col-lg-pull-21{right:87.5%}.ant-col-lg-offset-21{margin-left:87.5%}.ant-col-lg-order-21{order:21}.ant-col-lg-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-lg-push-20{left:83.33333333%}.ant-col-lg-pull-20{right:83.33333333%}.ant-col-lg-offset-20{margin-left:83.33333333%}.ant-col-lg-order-20{order:20}.ant-col-lg-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-lg-push-19{left:79.16666667%}.ant-col-lg-pull-19{right:79.16666667%}.ant-col-lg-offset-19{margin-left:79.16666667%}.ant-col-lg-order-19{order:19}.ant-col-lg-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-lg-push-18{left:75%}.ant-col-lg-pull-18{right:75%}.ant-col-lg-offset-18{margin-left:75%}.ant-col-lg-order-18{order:18}.ant-col-lg-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-lg-push-17{left:70.83333333%}.ant-col-lg-pull-17{right:70.83333333%}.ant-col-lg-offset-17{margin-left:70.83333333%}.ant-col-lg-order-17{order:17}.ant-col-lg-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-lg-push-16{left:66.66666667%}.ant-col-lg-pull-16{right:66.66666667%}.ant-col-lg-offset-16{margin-left:66.66666667%}.ant-col-lg-order-16{order:16}.ant-col-lg-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-lg-push-15{left:62.5%}.ant-col-lg-pull-15{right:62.5%}.ant-col-lg-offset-15{margin-left:62.5%}.ant-col-lg-order-15{order:15}.ant-col-lg-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-lg-push-14{left:58.33333333%}.ant-col-lg-pull-14{right:58.33333333%}.ant-col-lg-offset-14{margin-left:58.33333333%}.ant-col-lg-order-14{order:14}.ant-col-lg-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-lg-push-13{left:54.16666667%}.ant-col-lg-pull-13{right:54.16666667%}.ant-col-lg-offset-13{margin-left:54.16666667%}.ant-col-lg-order-13{order:13}.ant-col-lg-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-lg-push-12{left:50%}.ant-col-lg-pull-12{right:50%}.ant-col-lg-offset-12{margin-left:50%}.ant-col-lg-order-12{order:12}.ant-col-lg-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-lg-push-11{left:45.83333333%}.ant-col-lg-pull-11{right:45.83333333%}.ant-col-lg-offset-11{margin-left:45.83333333%}.ant-col-lg-order-11{order:11}.ant-col-lg-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-lg-push-10{left:41.66666667%}.ant-col-lg-pull-10{right:41.66666667%}.ant-col-lg-offset-10{margin-left:41.66666667%}.ant-col-lg-order-10{order:10}.ant-col-lg-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-lg-push-9{left:37.5%}.ant-col-lg-pull-9{right:37.5%}.ant-col-lg-offset-9{margin-left:37.5%}.ant-col-lg-order-9{order:9}.ant-col-lg-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-lg-push-8{left:33.33333333%}.ant-col-lg-pull-8{right:33.33333333%}.ant-col-lg-offset-8{margin-left:33.33333333%}.ant-col-lg-order-8{order:8}.ant-col-lg-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-lg-push-7{left:29.16666667%}.ant-col-lg-pull-7{right:29.16666667%}.ant-col-lg-offset-7{margin-left:29.16666667%}.ant-col-lg-order-7{order:7}.ant-col-lg-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-lg-push-6{left:25%}.ant-col-lg-pull-6{right:25%}.ant-col-lg-offset-6{margin-left:25%}.ant-col-lg-order-6{order:6}.ant-col-lg-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-lg-push-5{left:20.83333333%}.ant-col-lg-pull-5{right:20.83333333%}.ant-col-lg-offset-5{margin-left:20.83333333%}.ant-col-lg-order-5{order:5}.ant-col-lg-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-lg-push-4{left:16.66666667%}.ant-col-lg-pull-4{right:16.66666667%}.ant-col-lg-offset-4{margin-left:16.66666667%}.ant-col-lg-order-4{order:4}.ant-col-lg-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-lg-push-3{left:12.5%}.ant-col-lg-pull-3{right:12.5%}.ant-col-lg-offset-3{margin-left:12.5%}.ant-col-lg-order-3{order:3}.ant-col-lg-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-lg-push-2{left:8.33333333%}.ant-col-lg-pull-2{right:8.33333333%}.ant-col-lg-offset-2{margin-left:8.33333333%}.ant-col-lg-order-2{order:2}.ant-col-lg-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-lg-push-1{left:4.16666667%}.ant-col-lg-pull-1{right:4.16666667%}.ant-col-lg-offset-1{margin-left:4.16666667%}.ant-col-lg-order-1{order:1}.ant-col-lg-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-lg-push-0{left:auto}.ant-col-lg-pull-0{right:auto}.ant-col-lg-offset-0{margin-left:0}.ant-col-lg-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-lg-push-0.ant-col-rtl{right:auto}.ant-col-lg-pull-0.ant-col-rtl{left:auto}.ant-col-lg-offset-0.ant-col-rtl{margin-right:0}.ant-col-lg-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-lg-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-lg-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-lg-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-lg-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-lg-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-lg-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-lg-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-lg-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-lg-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-lg-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-lg-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-lg-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-lg-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-lg-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-lg-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-lg-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-lg-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-lg-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-lg-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-lg-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-lg-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-lg-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-lg-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-lg-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-lg-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-lg-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-lg-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-lg-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-lg-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-lg-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-lg-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-lg-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-lg-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-lg-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-lg-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-lg-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-lg-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-lg-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-lg-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-lg-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-lg-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-lg-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-lg-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-lg-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-lg-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-lg-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-lg-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-lg-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-lg-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-lg-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-lg-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-lg-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-lg-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-lg-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-lg-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-lg-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-lg-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-lg-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-lg-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-lg-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-lg-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-lg-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-lg-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-lg-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-lg-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-lg-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-lg-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-lg-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-lg-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-lg-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-lg-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 1200px){.ant-col-xl-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xl-push-24{left:100%}.ant-col-xl-pull-24{right:100%}.ant-col-xl-offset-24{margin-left:100%}.ant-col-xl-order-24{order:24}.ant-col-xl-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xl-push-23{left:95.83333333%}.ant-col-xl-pull-23{right:95.83333333%}.ant-col-xl-offset-23{margin-left:95.83333333%}.ant-col-xl-order-23{order:23}.ant-col-xl-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xl-push-22{left:91.66666667%}.ant-col-xl-pull-22{right:91.66666667%}.ant-col-xl-offset-22{margin-left:91.66666667%}.ant-col-xl-order-22{order:22}.ant-col-xl-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xl-push-21{left:87.5%}.ant-col-xl-pull-21{right:87.5%}.ant-col-xl-offset-21{margin-left:87.5%}.ant-col-xl-order-21{order:21}.ant-col-xl-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xl-push-20{left:83.33333333%}.ant-col-xl-pull-20{right:83.33333333%}.ant-col-xl-offset-20{margin-left:83.33333333%}.ant-col-xl-order-20{order:20}.ant-col-xl-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xl-push-19{left:79.16666667%}.ant-col-xl-pull-19{right:79.16666667%}.ant-col-xl-offset-19{margin-left:79.16666667%}.ant-col-xl-order-19{order:19}.ant-col-xl-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xl-push-18{left:75%}.ant-col-xl-pull-18{right:75%}.ant-col-xl-offset-18{margin-left:75%}.ant-col-xl-order-18{order:18}.ant-col-xl-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xl-push-17{left:70.83333333%}.ant-col-xl-pull-17{right:70.83333333%}.ant-col-xl-offset-17{margin-left:70.83333333%}.ant-col-xl-order-17{order:17}.ant-col-xl-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xl-push-16{left:66.66666667%}.ant-col-xl-pull-16{right:66.66666667%}.ant-col-xl-offset-16{margin-left:66.66666667%}.ant-col-xl-order-16{order:16}.ant-col-xl-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xl-push-15{left:62.5%}.ant-col-xl-pull-15{right:62.5%}.ant-col-xl-offset-15{margin-left:62.5%}.ant-col-xl-order-15{order:15}.ant-col-xl-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xl-push-14{left:58.33333333%}.ant-col-xl-pull-14{right:58.33333333%}.ant-col-xl-offset-14{margin-left:58.33333333%}.ant-col-xl-order-14{order:14}.ant-col-xl-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xl-push-13{left:54.16666667%}.ant-col-xl-pull-13{right:54.16666667%}.ant-col-xl-offset-13{margin-left:54.16666667%}.ant-col-xl-order-13{order:13}.ant-col-xl-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xl-push-12{left:50%}.ant-col-xl-pull-12{right:50%}.ant-col-xl-offset-12{margin-left:50%}.ant-col-xl-order-12{order:12}.ant-col-xl-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xl-push-11{left:45.83333333%}.ant-col-xl-pull-11{right:45.83333333%}.ant-col-xl-offset-11{margin-left:45.83333333%}.ant-col-xl-order-11{order:11}.ant-col-xl-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xl-push-10{left:41.66666667%}.ant-col-xl-pull-10{right:41.66666667%}.ant-col-xl-offset-10{margin-left:41.66666667%}.ant-col-xl-order-10{order:10}.ant-col-xl-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xl-push-9{left:37.5%}.ant-col-xl-pull-9{right:37.5%}.ant-col-xl-offset-9{margin-left:37.5%}.ant-col-xl-order-9{order:9}.ant-col-xl-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xl-push-8{left:33.33333333%}.ant-col-xl-pull-8{right:33.33333333%}.ant-col-xl-offset-8{margin-left:33.33333333%}.ant-col-xl-order-8{order:8}.ant-col-xl-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xl-push-7{left:29.16666667%}.ant-col-xl-pull-7{right:29.16666667%}.ant-col-xl-offset-7{margin-left:29.16666667%}.ant-col-xl-order-7{order:7}.ant-col-xl-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xl-push-6{left:25%}.ant-col-xl-pull-6{right:25%}.ant-col-xl-offset-6{margin-left:25%}.ant-col-xl-order-6{order:6}.ant-col-xl-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xl-push-5{left:20.83333333%}.ant-col-xl-pull-5{right:20.83333333%}.ant-col-xl-offset-5{margin-left:20.83333333%}.ant-col-xl-order-5{order:5}.ant-col-xl-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xl-push-4{left:16.66666667%}.ant-col-xl-pull-4{right:16.66666667%}.ant-col-xl-offset-4{margin-left:16.66666667%}.ant-col-xl-order-4{order:4}.ant-col-xl-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xl-push-3{left:12.5%}.ant-col-xl-pull-3{right:12.5%}.ant-col-xl-offset-3{margin-left:12.5%}.ant-col-xl-order-3{order:3}.ant-col-xl-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xl-push-2{left:8.33333333%}.ant-col-xl-pull-2{right:8.33333333%}.ant-col-xl-offset-2{margin-left:8.33333333%}.ant-col-xl-order-2{order:2}.ant-col-xl-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xl-push-1{left:4.16666667%}.ant-col-xl-pull-1{right:4.16666667%}.ant-col-xl-offset-1{margin-left:4.16666667%}.ant-col-xl-order-1{order:1}.ant-col-xl-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xl-push-0{left:auto}.ant-col-xl-pull-0{right:auto}.ant-col-xl-offset-0{margin-left:0}.ant-col-xl-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xl-push-0.ant-col-rtl{right:auto}.ant-col-xl-pull-0.ant-col-rtl{left:auto}.ant-col-xl-offset-0.ant-col-rtl{margin-right:0}.ant-col-xl-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xl-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xl-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xl-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xl-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xl-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xl-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xl-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xl-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xl-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xl-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xl-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xl-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xl-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xl-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xl-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xl-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xl-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xl-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xl-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xl-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xl-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xl-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xl-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xl-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xl-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xl-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xl-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xl-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xl-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xl-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xl-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xl-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xl-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xl-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xl-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xl-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xl-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xl-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xl-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xl-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xl-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xl-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xl-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xl-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xl-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xl-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xl-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xl-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xl-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xl-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xl-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xl-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xl-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xl-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xl-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xl-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xl-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xl-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xl-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xl-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xl-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xl-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xl-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xl-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xl-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xl-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xl-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xl-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xl-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xl-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xl-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 1600px){.ant-col-xxl-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xxl-push-24{left:100%}.ant-col-xxl-pull-24{right:100%}.ant-col-xxl-offset-24{margin-left:100%}.ant-col-xxl-order-24{order:24}.ant-col-xxl-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xxl-push-23{left:95.83333333%}.ant-col-xxl-pull-23{right:95.83333333%}.ant-col-xxl-offset-23{margin-left:95.83333333%}.ant-col-xxl-order-23{order:23}.ant-col-xxl-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xxl-push-22{left:91.66666667%}.ant-col-xxl-pull-22{right:91.66666667%}.ant-col-xxl-offset-22{margin-left:91.66666667%}.ant-col-xxl-order-22{order:22}.ant-col-xxl-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xxl-push-21{left:87.5%}.ant-col-xxl-pull-21{right:87.5%}.ant-col-xxl-offset-21{margin-left:87.5%}.ant-col-xxl-order-21{order:21}.ant-col-xxl-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xxl-push-20{left:83.33333333%}.ant-col-xxl-pull-20{right:83.33333333%}.ant-col-xxl-offset-20{margin-left:83.33333333%}.ant-col-xxl-order-20{order:20}.ant-col-xxl-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xxl-push-19{left:79.16666667%}.ant-col-xxl-pull-19{right:79.16666667%}.ant-col-xxl-offset-19{margin-left:79.16666667%}.ant-col-xxl-order-19{order:19}.ant-col-xxl-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xxl-push-18{left:75%}.ant-col-xxl-pull-18{right:75%}.ant-col-xxl-offset-18{margin-left:75%}.ant-col-xxl-order-18{order:18}.ant-col-xxl-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xxl-push-17{left:70.83333333%}.ant-col-xxl-pull-17{right:70.83333333%}.ant-col-xxl-offset-17{margin-left:70.83333333%}.ant-col-xxl-order-17{order:17}.ant-col-xxl-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xxl-push-16{left:66.66666667%}.ant-col-xxl-pull-16{right:66.66666667%}.ant-col-xxl-offset-16{margin-left:66.66666667%}.ant-col-xxl-order-16{order:16}.ant-col-xxl-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xxl-push-15{left:62.5%}.ant-col-xxl-pull-15{right:62.5%}.ant-col-xxl-offset-15{margin-left:62.5%}.ant-col-xxl-order-15{order:15}.ant-col-xxl-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xxl-push-14{left:58.33333333%}.ant-col-xxl-pull-14{right:58.33333333%}.ant-col-xxl-offset-14{margin-left:58.33333333%}.ant-col-xxl-order-14{order:14}.ant-col-xxl-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xxl-push-13{left:54.16666667%}.ant-col-xxl-pull-13{right:54.16666667%}.ant-col-xxl-offset-13{margin-left:54.16666667%}.ant-col-xxl-order-13{order:13}.ant-col-xxl-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xxl-push-12{left:50%}.ant-col-xxl-pull-12{right:50%}.ant-col-xxl-offset-12{margin-left:50%}.ant-col-xxl-order-12{order:12}.ant-col-xxl-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xxl-push-11{left:45.83333333%}.ant-col-xxl-pull-11{right:45.83333333%}.ant-col-xxl-offset-11{margin-left:45.83333333%}.ant-col-xxl-order-11{order:11}.ant-col-xxl-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xxl-push-10{left:41.66666667%}.ant-col-xxl-pull-10{right:41.66666667%}.ant-col-xxl-offset-10{margin-left:41.66666667%}.ant-col-xxl-order-10{order:10}.ant-col-xxl-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xxl-push-9{left:37.5%}.ant-col-xxl-pull-9{right:37.5%}.ant-col-xxl-offset-9{margin-left:37.5%}.ant-col-xxl-order-9{order:9}.ant-col-xxl-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xxl-push-8{left:33.33333333%}.ant-col-xxl-pull-8{right:33.33333333%}.ant-col-xxl-offset-8{margin-left:33.33333333%}.ant-col-xxl-order-8{order:8}.ant-col-xxl-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xxl-push-7{left:29.16666667%}.ant-col-xxl-pull-7{right:29.16666667%}.ant-col-xxl-offset-7{margin-left:29.16666667%}.ant-col-xxl-order-7{order:7}.ant-col-xxl-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xxl-push-6{left:25%}.ant-col-xxl-pull-6{right:25%}.ant-col-xxl-offset-6{margin-left:25%}.ant-col-xxl-order-6{order:6}.ant-col-xxl-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xxl-push-5{left:20.83333333%}.ant-col-xxl-pull-5{right:20.83333333%}.ant-col-xxl-offset-5{margin-left:20.83333333%}.ant-col-xxl-order-5{order:5}.ant-col-xxl-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xxl-push-4{left:16.66666667%}.ant-col-xxl-pull-4{right:16.66666667%}.ant-col-xxl-offset-4{margin-left:16.66666667%}.ant-col-xxl-order-4{order:4}.ant-col-xxl-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xxl-push-3{left:12.5%}.ant-col-xxl-pull-3{right:12.5%}.ant-col-xxl-offset-3{margin-left:12.5%}.ant-col-xxl-order-3{order:3}.ant-col-xxl-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xxl-push-2{left:8.33333333%}.ant-col-xxl-pull-2{right:8.33333333%}.ant-col-xxl-offset-2{margin-left:8.33333333%}.ant-col-xxl-order-2{order:2}.ant-col-xxl-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xxl-push-1{left:4.16666667%}.ant-col-xxl-pull-1{right:4.16666667%}.ant-col-xxl-offset-1{margin-left:4.16666667%}.ant-col-xxl-order-1{order:1}.ant-col-xxl-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xxl-push-0{left:auto}.ant-col-xxl-pull-0{right:auto}.ant-col-xxl-offset-0{margin-left:0}.ant-col-xxl-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xxl-push-0.ant-col-rtl{right:auto}.ant-col-xxl-pull-0.ant-col-rtl{left:auto}.ant-col-xxl-offset-0.ant-col-rtl{margin-right:0}.ant-col-xxl-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xxl-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xxl-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xxl-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xxl-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xxl-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xxl-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xxl-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xxl-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xxl-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xxl-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xxl-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xxl-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xxl-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xxl-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xxl-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xxl-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xxl-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xxl-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xxl-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xxl-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xxl-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xxl-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xxl-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xxl-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xxl-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xxl-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xxl-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xxl-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xxl-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xxl-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xxl-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xxl-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xxl-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xxl-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xxl-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xxl-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xxl-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xxl-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xxl-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xxl-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xxl-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xxl-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xxl-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xxl-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xxl-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xxl-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xxl-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xxl-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xxl-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xxl-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xxl-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xxl-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xxl-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xxl-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xxl-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xxl-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xxl-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xxl-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xxl-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xxl-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xxl-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xxl-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xxl-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xxl-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xxl-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xxl-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xxl-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xxl-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xxl-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xxl-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xxl-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}.ant-row-rtl{direction:rtl}.ant-carousel{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-carousel .slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-touch-callout:none;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.ant-carousel .slick-list{position:relative;display:block;margin:0;padding:0;overflow:hidden}.ant-carousel .slick-list:focus{outline:none}.ant-carousel .slick-list.dragging{cursor:pointer}.ant-carousel .slick-list .slick-slide{pointer-events:none}.ant-carousel .slick-list .slick-slide input.ant-radio-input,.ant-carousel .slick-list .slick-slide input.ant-checkbox-input{visibility:hidden}.ant-carousel .slick-list .slick-slide.slick-active{pointer-events:auto}.ant-carousel .slick-list .slick-slide.slick-active input.ant-radio-input,.ant-carousel .slick-list .slick-slide.slick-active input.ant-checkbox-input{visibility:visible}.ant-carousel .slick-slider .slick-track,.ant-carousel .slick-slider .slick-list{transform:translateZ(0)}.ant-carousel .slick-track{position:relative;top:0;left:0;display:block}.ant-carousel .slick-track:before,.ant-carousel .slick-track:after{display:table;content:\"\"}.ant-carousel .slick-track:after{clear:both}.slick-loading .ant-carousel .slick-track{visibility:hidden}.ant-carousel .slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .ant-carousel .slick-slide{float:right}.ant-carousel .slick-slide img{display:block}.ant-carousel .slick-slide.slick-loading img{display:none}.ant-carousel .slick-slide.dragging img{pointer-events:none}.ant-carousel .slick-initialized .slick-slide{display:block}.ant-carousel .slick-loading .slick-slide{visibility:hidden}.ant-carousel .slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.ant-carousel .slick-arrow.slick-hidden{display:none}.ant-carousel .slick-prev,.ant-carousel .slick-next{position:absolute;top:50%;display:block;width:20px;height:20px;margin-top:-10px;padding:0;color:transparent;font-size:0;line-height:0;background:transparent;border:0;outline:none;cursor:pointer}.ant-carousel .slick-prev:hover,.ant-carousel .slick-next:hover,.ant-carousel .slick-prev:focus,.ant-carousel .slick-next:focus{color:transparent;background:transparent;outline:none}.ant-carousel .slick-prev:hover:before,.ant-carousel .slick-next:hover:before,.ant-carousel .slick-prev:focus:before,.ant-carousel .slick-next:focus:before{opacity:1}.ant-carousel .slick-prev.slick-disabled:before,.ant-carousel .slick-next.slick-disabled:before{opacity:.25}.ant-carousel .slick-prev{left:-25px}.ant-carousel .slick-prev:before{content:\"\\2190\"}.ant-carousel .slick-next{right:-25px}.ant-carousel .slick-next:before{content:\"\\2192\"}.ant-carousel .slick-dots{position:absolute;display:block;width:100%;height:3px;margin:0;padding:0;text-align:center;list-style:none}.ant-carousel .slick-dots-bottom{bottom:12px}.ant-carousel .slick-dots-top{top:12px}.ant-carousel .slick-dots li{position:relative;display:inline-block;margin:0 2px;padding:0;text-align:center;vertical-align:top}.ant-carousel .slick-dots li button{display:block;width:16px;height:3px;padding:0;color:transparent;font-size:0;background:#fff;border:0;border-radius:1px;outline:none;cursor:pointer;opacity:.3;transition:all .5s}.ant-carousel .slick-dots li button:hover,.ant-carousel .slick-dots li button:focus{opacity:.75}.ant-carousel .slick-dots li.slick-active button{width:24px;background:#fff;opacity:1}.ant-carousel .slick-dots li.slick-active button:hover,.ant-carousel .slick-dots li.slick-active button:focus{opacity:1}.ant-carousel-vertical .slick-dots{top:50%;bottom:auto;width:3px;height:auto;transform:translateY(-50%)}.ant-carousel-vertical .slick-dots-left{left:12px}.ant-carousel-vertical .slick-dots-right{right:12px}.ant-carousel-vertical .slick-dots li{margin:0 2px;vertical-align:baseline}.ant-carousel-vertical .slick-dots li button{width:3px;height:16px}.ant-carousel-vertical .slick-dots li.slick-active button{width:3px;height:24px}.ant-cascader{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-cascader-input.ant-input{position:static;width:100%;padding-right:24px;background-color:transparent!important;cursor:pointer}.ant-cascader-picker-show-search .ant-cascader-input.ant-input{position:relative}.ant-cascader-picker{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;background-color:#fff;border-radius:2px;outline:0;cursor:pointer;transition:color .3s}.ant-cascader-picker-with-value .ant-cascader-picker-label{color:transparent}.ant-cascader-picker-disabled{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-cascader-picker-disabled .ant-cascader-input{cursor:not-allowed}.ant-cascader-picker:focus .ant-cascader-input{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-cascader-picker-show-search.ant-cascader-picker-focused{color:#00000040}.ant-cascader-picker-label{position:absolute;top:50%;left:0;width:100%;height:20px;margin-top:-10px;padding:0 20px 0 12px;overflow:hidden;line-height:20px;white-space:nowrap;text-overflow:ellipsis}.ant-cascader-picker-clear{position:absolute;top:50%;right:12px;z-index:2;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;line-height:12px;background:#fff;cursor:pointer;opacity:0;transition:color .3s ease,opacity .15s ease}.ant-cascader-picker-clear:hover{color:#00000073}.ant-cascader-picker:hover .ant-cascader-picker-clear{opacity:1}.ant-cascader-picker-arrow{position:absolute;top:50%;right:12px;z-index:1;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;line-height:12px;transition:transform .2s}.ant-cascader-picker-arrow.ant-cascader-picker-arrow-expand{transform:rotate(180deg)}.ant-cascader-picker-label:hover+.ant-cascader-input{border-color:#40a9ff;border-right-width:1px!important}.ant-cascader-picker-small .ant-cascader-picker-clear,.ant-cascader-picker-small .ant-cascader-picker-arrow{right:8px}.ant-cascader-menus{position:absolute;z-index:1050;font-size:14px;white-space:nowrap;background:#fff;border-radius:2px;box-shadow:0 2px 8px #00000026}.ant-cascader-menus ul,.ant-cascader-menus ol{margin:0;list-style:none}.ant-cascader-menus-empty,.ant-cascader-menus-hidden{display:none}.ant-cascader-menus.slide-up-enter.slide-up-enter-active.ant-cascader-menus-placement-bottomLeft,.ant-cascader-menus.slide-up-appear.slide-up-appear-active.ant-cascader-menus-placement-bottomLeft{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-cascader-menus.slide-up-enter.slide-up-enter-active.ant-cascader-menus-placement-topLeft,.ant-cascader-menus.slide-up-appear.slide-up-appear-active.ant-cascader-menus-placement-topLeft{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-cascader-menus.slide-up-leave.slide-up-leave-active.ant-cascader-menus-placement-bottomLeft{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-cascader-menus.slide-up-leave.slide-up-leave-active.ant-cascader-menus-placement-topLeft{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-cascader-menu{display:inline-block;min-width:111px;height:180px;margin:0;padding:4px 0;overflow:auto;vertical-align:top;list-style:none;border-right:1px solid #f0f0f0;-ms-overflow-style:-ms-autohiding-scrollbar}.ant-cascader-menu:first-child{border-radius:2px 0 0 2px}.ant-cascader-menu:last-child{margin-right:-1px;border-right-color:transparent;border-radius:0 2px 2px 0}.ant-cascader-menu:only-child{border-radius:2px}.ant-cascader-menu-item{padding:5px 12px;line-height:22px;white-space:nowrap;cursor:pointer;transition:all .3s}.ant-cascader-menu-item:hover{background:#f5f5f5}.ant-cascader-menu-item-disabled{color:#00000040;cursor:not-allowed}.ant-cascader-menu-item-disabled:hover{background:transparent}.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled),.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled):hover{font-weight:600;background-color:#e6f7ff}.ant-cascader-menu-item-expand{position:relative;padding-right:24px}.ant-cascader-menu-item-expand .ant-cascader-menu-item-expand-icon,.ant-cascader-menu-item-loading-icon{display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);position:absolute;right:12px;color:#00000073}:root .ant-cascader-menu-item-expand .ant-cascader-menu-item-expand-icon,:root .ant-cascader-menu-item-loading-icon{font-size:12px}.ant-cascader-menu-item-disabled.ant-cascader-menu-item-expand .ant-cascader-menu-item-expand-icon,.ant-cascader-menu-item-disabled.ant-cascader-menu-item-loading-icon{color:#00000040}.ant-cascader-menu-item .ant-cascader-menu-item-keyword{color:#ff4d4f}@-webkit-keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}.ant-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-checkbox-wrapper:hover .ant-checkbox-inner,.ant-checkbox:hover .ant-checkbox-inner,.ant-checkbox-input:focus+.ant-checkbox-inner{border-color:#1890ff}.ant-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:2px;visibility:hidden;-webkit-animation:antCheckboxEffect .36s ease-in-out;animation:antCheckboxEffect .36s ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;content:\"\"}.ant-checkbox:hover:after,.ant-checkbox-wrapper:hover .ant-checkbox:after{visibility:visible}.ant-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;border-collapse:separate;transition:all .3s}.ant-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5.71428571px;height:9.14285714px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:\" \"}.ant-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-checkbox-checked .ant-checkbox-inner:after{position:absolute;display:table;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(1) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:\" \"}.ant-checkbox-checked .ant-checkbox-inner{background-color:#1890ff;border-color:#1890ff}.ant-checkbox-disabled{cursor:not-allowed}.ant-checkbox-disabled.ant-checkbox-checked .ant-checkbox-inner:after{border-color:#00000040;-webkit-animation-name:none;animation-name:none}.ant-checkbox-disabled .ant-checkbox-input{cursor:not-allowed}.ant-checkbox-disabled .ant-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-checkbox-disabled .ant-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;-webkit-animation-name:none;animation-name:none}.ant-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-checkbox-disabled:hover:after,.ant-checkbox-wrapper:hover .ant-checkbox-disabled:after{visibility:hidden}.ant-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block;line-height:unset;cursor:pointer}.ant-checkbox-wrapper.ant-checkbox-wrapper-disabled{cursor:not-allowed}.ant-checkbox-wrapper+.ant-checkbox-wrapper{margin-left:8px}.ant-checkbox+span{padding-right:8px;padding-left:8px}.ant-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block}.ant-checkbox-group-item{display:inline-block;margin-right:8px}.ant-checkbox-group-item:last-child{margin-right:0}.ant-checkbox-group-item+.ant-checkbox-group-item{margin-left:0}.ant-checkbox-indeterminate .ant-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-checkbox-indeterminate .ant-checkbox-inner:after{top:50%;left:50%;width:8px;height:8px;background-color:#1890ff;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;content:\" \"}.ant-checkbox-indeterminate.ant-checkbox-disabled .ant-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-collapse{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";background-color:#fafafa;border:1px solid #d9d9d9;border-bottom:0;border-radius:2px}.ant-collapse>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse>.ant-collapse-item:last-child,.ant-collapse>.ant-collapse-item:last-child>.ant-collapse-header{border-radius:0 0 2px 2px}.ant-collapse>.ant-collapse-item>.ant-collapse-header{position:relative;padding:12px 16px 12px 40px;color:#000000d9;line-height:22px;cursor:pointer;transition:all .3s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:50%;left:16px;display:inline-block;font-size:12px;transform:translateY(-50%)}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow>*{line-height:1}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{display:inline-block}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow:before{display:none}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow .ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow-icon{display:block}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transition:transform .24s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{float:right}.ant-collapse>.ant-collapse-item>.ant-collapse-header:focus{outline:none}.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-left:12px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header{padding:12px 40px 12px 16px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{right:16px;left:auto}.ant-collapse-anim-active{transition:height .2s cubic-bezier(.215,.61,.355,1)}.ant-collapse-content{overflow:hidden;color:#000000d9;background-color:#fff;border-top:1px solid #d9d9d9}.ant-collapse-content>.ant-collapse-content-box{padding:16px}.ant-collapse-content-inactive{display:none}.ant-collapse-item:last-child>.ant-collapse-content{border-radius:0 0 2px 2px}.ant-collapse-borderless{background-color:#fafafa;border:0}.ant-collapse-borderless>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse-borderless>.ant-collapse-item:last-child,.ant-collapse-borderless>.ant-collapse-item:last-child .ant-collapse-header{border-radius:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:4px}.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#00000040;cursor:not-allowed}.ant-color-picker{box-sizing:border-box;margin:0;padding:0;color:#000000a6;font-size:14px;font-variant:tabular-nums;line-height:1.5;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;outline:none;cursor:pointer;transition:opacity .3s;min-width:55px}.ant-color-picker .pickr{display:inline-block}.ant-color-picker .pickr .pcr-button{width:18px;height:18px;margin-left:7px}.ant-color-picker .pickr .pcr-button:focus{box-shadow:none}.ant-color-picker.ant-color-picker-disabled{cursor:not-allowed}.ant-color-picker.ant-color-picker-disabled .ant-color-picker-selection{background:#f5f5f5;box-shadow:none;border:1px solid #d9d9d9}.ant-color-picker.ant-color-picker-disabled .ant-color-picker-selection:hover,.ant-color-picker.ant-color-picker-disabled .ant-color-picker-selection:focus,.ant-color-picker.ant-color-picker-disabled .ant-color-picker-selection:active{border:1px solid #d9d9d9;box-shadow:none}.ant-color-picker.ant-color-picker-disabled.ant-color-picker-open .ant-color-picker-icon svg{transform:none}.ant-color-picker-open .ant-color-picker-icon svg{transform:rotate(180deg)}.ant-color-picker-open .ant-color-picker-selection{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-color-picker-selection{display:block;box-sizing:border-box;background-color:#fff;border:1px solid #d9d9d9;border-top-width:1.02px;border-radius:2px;outline:none;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;height:32px;cursor:inherit}.ant-color-picker-selection:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-color-picker-icon{display:inline-block;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:50%;right:8px;margin-top:-6px;color:#00000040;font-size:12px;line-height:1;transform-origin:50% 50%}.ant-color-picker-icon>*{line-height:1}.ant-color-picker-icon svg{display:inline-block}.ant-color-picker-icon:before{display:none}.ant-color-picker-icon .ant-color-picker-icon-icon{display:block}.ant-color-picker-icon svg{transition:transform .3s}.ant-color-picker-lg{font-size:16px}.ant-color-picker-lg .ant-color-picker-selection{line-height:28px;height:40px}.ant-color-picker-lg .ant-color-picker-icon{top:20px}.ant-color-picker-sm .ant-color-picker-selection{line-height:12px;height:24px}.ant-color-picker-sm .pickr .pcr-button{width:14px;height:14px}.ant-color-picker-sm .ant-color-picker-icon{right:10px;top:12px;font-size:10px}.ant-comment{position:relative;background-color:inherit}.ant-comment-inner{display:flex;padding:16px 0}.ant-comment-avatar{position:relative;flex-shrink:0;margin-right:12px;cursor:pointer}.ant-comment-avatar img{width:32px;height:32px;border-radius:50%}.ant-comment-content{position:relative;flex:1 1 auto;min-width:1px;font-size:14px;word-wrap:break-word}.ant-comment-content-author{display:flex;flex-wrap:wrap;justify-content:flex-start;margin-bottom:4px;font-size:14px}.ant-comment-content-author>a,.ant-comment-content-author>span{padding-right:8px;font-size:12px;line-height:18px}.ant-comment-content-author-name{color:#00000073;font-size:14px;transition:color .3s}.ant-comment-content-author-name>*{color:#00000073}.ant-comment-content-author-name>*:hover{color:#00000073}.ant-comment-content-author-time{color:#ccc;white-space:nowrap;cursor:auto}.ant-comment-content-detail p{margin-bottom:inherit;white-space:pre-wrap}.ant-comment-actions{margin-top:12px;margin-bottom:inherit;padding-left:0}.ant-comment-actions>li{display:inline-block;color:#00000073}.ant-comment-actions>li>span{margin-right:10px;color:#00000073;font-size:12px;cursor:pointer;transition:color .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-comment-actions>li>span:hover{color:#595959}.ant-comment-nested{margin-left:44px}.ant-comment-rtl{direction:rtl}.ant-comment-rtl .ant-comment-avatar{margin-right:0;margin-left:12px}.ant-comment-rtl .ant-comment-content-author>a,.ant-comment-rtl .ant-comment-content-author>span{padding-right:0;padding-left:8px}.ant-comment-rtl .ant-comment-actions{padding-right:0}.ant-comment-rtl .ant-comment-actions>li>span{margin-right:0;margin-left:10px}.ant-comment-rtl .ant-comment-nested{margin-right:44px;margin-left:0}.ant-calendar-picker-container{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;z-index:1050;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}.ant-calendar-picker-container.slide-up-enter.slide-up-enter-active.ant-calendar-picker-container-placement-topLeft,.ant-calendar-picker-container.slide-up-enter.slide-up-enter-active.ant-calendar-picker-container-placement-topRight,.ant-calendar-picker-container.slide-up-appear.slide-up-appear-active.ant-calendar-picker-container-placement-topLeft,.ant-calendar-picker-container.slide-up-appear.slide-up-appear-active.ant-calendar-picker-container-placement-topRight{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-calendar-picker-container.slide-up-enter.slide-up-enter-active.ant-calendar-picker-container-placement-bottomLeft,.ant-calendar-picker-container.slide-up-enter.slide-up-enter-active.ant-calendar-picker-container-placement-bottomRight,.ant-calendar-picker-container.slide-up-appear.slide-up-appear-active.ant-calendar-picker-container-placement-bottomLeft,.ant-calendar-picker-container.slide-up-appear.slide-up-appear-active.ant-calendar-picker-container-placement-bottomRight{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-calendar-picker-container.slide-up-leave.slide-up-leave-active.ant-calendar-picker-container-placement-topLeft,.ant-calendar-picker-container.slide-up-leave.slide-up-leave-active.ant-calendar-picker-container-placement-topRight{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-calendar-picker-container.slide-up-leave.slide-up-leave-active.ant-calendar-picker-container-placement-bottomLeft,.ant-calendar-picker-container.slide-up-leave.slide-up-leave-active.ant-calendar-picker-container-placement-bottomRight{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-calendar-picker{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;outline:none;cursor:text;transition:opacity .3s}.ant-calendar-picker-input{outline:none}.ant-calendar-picker-input.ant-input{line-height:1.5715}.ant-calendar-picker-input.ant-input-sm{padding-top:0;padding-bottom:0}.ant-calendar-picker:hover .ant-calendar-picker-input:not(.ant-input-disabled){border-color:#40a9ff}.ant-calendar-picker:focus .ant-calendar-picker-input:not(.ant-input-disabled){border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-calendar-picker-clear,.ant-calendar-picker-icon{position:absolute;top:50%;right:12px;z-index:1;width:14px;height:14px;margin-top:-7px;font-size:12px;line-height:14px;transition:all .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-calendar-picker-clear{z-index:2;color:#00000040;font-size:14px;background:#fff;cursor:pointer;opacity:0;pointer-events:none}.ant-calendar-picker-clear:hover{color:#00000073}.ant-calendar-picker:hover .ant-calendar-picker-clear{opacity:1;pointer-events:auto}.ant-calendar-picker-icon{display:inline-block;color:#00000040;font-size:14px;line-height:1}.ant-input-disabled+.ant-calendar-picker-icon{cursor:not-allowed}.ant-calendar-picker-small .ant-calendar-picker-clear,.ant-calendar-picker-small .ant-calendar-picker-icon{right:8px}.ant-calendar{position:relative;width:280px;font-size:14px;line-height:1.5715;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #fff;border-radius:2px;outline:none;box-shadow:0 2px 8px #00000026}.ant-calendar-input-wrap{height:34px;padding:6px 10px;border-bottom:1px solid #f0f0f0}.ant-calendar-input{width:100%;height:22px;color:#000000d9;background:#fff;border:0;outline:0;cursor:auto}.ant-calendar-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-calendar-input:-ms-input-placeholder{color:#bfbfbf}.ant-calendar-input::-webkit-input-placeholder{color:#bfbfbf}.ant-calendar-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-calendar-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-calendar-input:placeholder-shown{text-overflow:ellipsis}.ant-calendar-week-number{width:286px}.ant-calendar-week-number-cell{text-align:center}.ant-calendar-header{height:40px;line-height:40px;text-align:center;border-bottom:1px solid #f0f0f0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-calendar-header a:hover{color:#40a9ff}.ant-calendar-header .ant-calendar-century-select,.ant-calendar-header .ant-calendar-decade-select,.ant-calendar-header .ant-calendar-year-select,.ant-calendar-header .ant-calendar-month-select{display:inline-block;padding:0 2px;color:#000000d9;font-weight:500;line-height:40px}.ant-calendar-header .ant-calendar-century-select-arrow,.ant-calendar-header .ant-calendar-decade-select-arrow,.ant-calendar-header .ant-calendar-year-select-arrow,.ant-calendar-header .ant-calendar-month-select-arrow{display:none}.ant-calendar-header .ant-calendar-prev-century-btn,.ant-calendar-header .ant-calendar-next-century-btn,.ant-calendar-header .ant-calendar-prev-decade-btn,.ant-calendar-header .ant-calendar-next-decade-btn,.ant-calendar-header .ant-calendar-prev-month-btn,.ant-calendar-header .ant-calendar-next-month-btn,.ant-calendar-header .ant-calendar-prev-year-btn,.ant-calendar-header .ant-calendar-next-year-btn{position:absolute;top:0;display:inline-block;padding:0 5px;color:#00000073;font-size:16px;font-family:Arial,Hiragino Sans GB,Microsoft Yahei,\"Microsoft Sans Serif\",sans-serif;line-height:40px}.ant-calendar-header .ant-calendar-prev-century-btn,.ant-calendar-header .ant-calendar-prev-decade-btn,.ant-calendar-header .ant-calendar-prev-year-btn{left:7px;height:100%}.ant-calendar-header .ant-calendar-prev-century-btn:before,.ant-calendar-header .ant-calendar-prev-decade-btn:before,.ant-calendar-header .ant-calendar-prev-year-btn:before,.ant-calendar-header .ant-calendar-prev-century-btn:after,.ant-calendar-header .ant-calendar-prev-decade-btn:after,.ant-calendar-header .ant-calendar-prev-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-header .ant-calendar-prev-century-btn:hover:before,.ant-calendar-header .ant-calendar-prev-decade-btn:hover:before,.ant-calendar-header .ant-calendar-prev-year-btn:hover:before,.ant-calendar-header .ant-calendar-prev-century-btn:hover:after,.ant-calendar-header .ant-calendar-prev-decade-btn:hover:after,.ant-calendar-header .ant-calendar-prev-year-btn:hover:after{border-color:#000000d9}.ant-calendar-header .ant-calendar-prev-century-btn:after,.ant-calendar-header .ant-calendar-prev-decade-btn:after,.ant-calendar-header .ant-calendar-prev-year-btn:after{display:none}.ant-calendar-header .ant-calendar-prev-century-btn:after,.ant-calendar-header .ant-calendar-prev-decade-btn:after,.ant-calendar-header .ant-calendar-prev-year-btn:after{position:relative;left:-3px;display:inline-block}.ant-calendar-header .ant-calendar-next-century-btn,.ant-calendar-header .ant-calendar-next-decade-btn,.ant-calendar-header .ant-calendar-next-year-btn{right:7px;height:100%}.ant-calendar-header .ant-calendar-next-century-btn:before,.ant-calendar-header .ant-calendar-next-decade-btn:before,.ant-calendar-header .ant-calendar-next-year-btn:before,.ant-calendar-header .ant-calendar-next-century-btn:after,.ant-calendar-header .ant-calendar-next-decade-btn:after,.ant-calendar-header .ant-calendar-next-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-header .ant-calendar-next-century-btn:hover:before,.ant-calendar-header .ant-calendar-next-decade-btn:hover:before,.ant-calendar-header .ant-calendar-next-year-btn:hover:before,.ant-calendar-header .ant-calendar-next-century-btn:hover:after,.ant-calendar-header .ant-calendar-next-decade-btn:hover:after,.ant-calendar-header .ant-calendar-next-year-btn:hover:after{border-color:#000000d9}.ant-calendar-header .ant-calendar-next-century-btn:after,.ant-calendar-header .ant-calendar-next-decade-btn:after,.ant-calendar-header .ant-calendar-next-year-btn:after{display:none}.ant-calendar-header .ant-calendar-next-century-btn:before,.ant-calendar-header .ant-calendar-next-decade-btn:before,.ant-calendar-header .ant-calendar-next-year-btn:before,.ant-calendar-header .ant-calendar-next-century-btn:after,.ant-calendar-header .ant-calendar-next-decade-btn:after,.ant-calendar-header .ant-calendar-next-year-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-header .ant-calendar-next-century-btn:before,.ant-calendar-header .ant-calendar-next-decade-btn:before,.ant-calendar-header .ant-calendar-next-year-btn:before{position:relative;left:3px}.ant-calendar-header .ant-calendar-next-century-btn:after,.ant-calendar-header .ant-calendar-next-decade-btn:after,.ant-calendar-header .ant-calendar-next-year-btn:after{display:inline-block}.ant-calendar-header .ant-calendar-prev-month-btn{left:29px;height:100%}.ant-calendar-header .ant-calendar-prev-month-btn:before,.ant-calendar-header .ant-calendar-prev-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-header .ant-calendar-prev-month-btn:hover:before,.ant-calendar-header .ant-calendar-prev-month-btn:hover:after{border-color:#000000d9}.ant-calendar-header .ant-calendar-prev-month-btn:after{display:none}.ant-calendar-header .ant-calendar-next-month-btn{right:29px;height:100%}.ant-calendar-header .ant-calendar-next-month-btn:before,.ant-calendar-header .ant-calendar-next-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-header .ant-calendar-next-month-btn:hover:before,.ant-calendar-header .ant-calendar-next-month-btn:hover:after{border-color:#000000d9}.ant-calendar-header .ant-calendar-next-month-btn:after{display:none}.ant-calendar-header .ant-calendar-next-month-btn:before,.ant-calendar-header .ant-calendar-next-month-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-body{padding:8px 12px}.ant-calendar table{width:100%;max-width:100%;background-color:transparent;border-collapse:collapse}.ant-calendar table,.ant-calendar th,.ant-calendar td{text-align:center;border:0}.ant-calendar-calendar-table{margin-bottom:0;border-spacing:0}.ant-calendar-column-header{width:33px;padding:6px 0;line-height:18px;text-align:center}.ant-calendar-column-header .ant-calendar-column-header-inner{display:block;font-weight:400}.ant-calendar-week-number-header .ant-calendar-column-header-inner{display:none}.ant-calendar-cell{height:30px;padding:3px 0}.ant-calendar-date{display:block;width:24px;height:24px;margin:0 auto;padding:0;color:#000000d9;line-height:22px;text-align:center;background:transparent;border:1px solid transparent;border-radius:2px;transition:background .3s ease}.ant-calendar-date-panel{position:relative;outline:none}.ant-calendar-date:hover{background:#f5f5f5;cursor:pointer}.ant-calendar-date:active{color:#fff;background:#40a9ff}.ant-calendar-today .ant-calendar-date{color:#1890ff;font-weight:700;border-color:#1890ff}.ant-calendar-selected-day .ant-calendar-date{background:#bae7ff}.ant-calendar-last-month-cell .ant-calendar-date,.ant-calendar-next-month-btn-day .ant-calendar-date,.ant-calendar-last-month-cell .ant-calendar-date:hover,.ant-calendar-next-month-btn-day .ant-calendar-date:hover{color:#00000040;background:transparent;border-color:transparent}.ant-calendar-disabled-cell .ant-calendar-date{position:relative;width:auto;color:#00000040;background:#f5f5f5;border:1px solid transparent;border-radius:0;cursor:not-allowed}.ant-calendar-disabled-cell .ant-calendar-date:hover{background:#f5f5f5}.ant-calendar-disabled-cell.ant-calendar-selected-day .ant-calendar-date:before{position:absolute;top:-1px;left:5px;width:24px;height:24px;background:rgba(0,0,0,.1);border-radius:2px;content:\"\"}.ant-calendar-disabled-cell.ant-calendar-today .ant-calendar-date{position:relative;padding-right:5px;padding-left:5px}.ant-calendar-disabled-cell.ant-calendar-today .ant-calendar-date:before{position:absolute;top:-1px;left:5px;width:24px;height:24px;border:1px solid rgba(0,0,0,.25);border-radius:2px;content:\" \"}.ant-calendar-disabled-cell-first-of-row .ant-calendar-date{border-top-left-radius:4px;border-bottom-left-radius:4px}.ant-calendar-disabled-cell-last-of-row .ant-calendar-date{border-top-right-radius:4px;border-bottom-right-radius:4px}.ant-calendar-footer{padding:0 12px;line-height:38px;border-top:1px solid #f0f0f0}.ant-calendar-footer:empty{border-top:0}.ant-calendar-footer-btn{display:block;text-align:center}.ant-calendar-footer-extra{text-align:left}.ant-calendar .ant-calendar-today-btn,.ant-calendar .ant-calendar-clear-btn{display:inline-block;margin:0 0 0 8px;text-align:center}.ant-calendar .ant-calendar-today-btn-disabled,.ant-calendar .ant-calendar-clear-btn-disabled{color:#00000040;cursor:not-allowed}.ant-calendar .ant-calendar-today-btn:only-child,.ant-calendar .ant-calendar-clear-btn:only-child{margin:0}.ant-calendar .ant-calendar-clear-btn{position:absolute;top:7px;right:5px;display:none;width:20px;height:20px;margin:0;overflow:hidden;line-height:20px;text-align:center;text-indent:-76px}.ant-calendar .ant-calendar-clear-btn:after{display:inline-block;width:20px;color:#00000040;font-size:14px;line-height:1;text-indent:43px;transition:color .3s ease}.ant-calendar .ant-calendar-clear-btn:hover:after{color:#00000073}.ant-calendar .ant-calendar-ok-btn{position:relative;display:inline-block;font-weight:400;white-space:nowrap;text-align:center;background-image:none;border:1px solid transparent;box-shadow:0 2px #00000004;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;touch-action:manipulation;height:32px;color:#fff;background:#1890ff;border-color:#1890ff;text-shadow:0 -1px 0 rgba(0,0,0,.12);box-shadow:0 2px #0000000b;height:24px;padding:0 7px;font-size:14px;border-radius:2px;line-height:22px}.ant-calendar .ant-calendar-ok-btn>.anticon{line-height:1}.ant-calendar .ant-calendar-ok-btn,.ant-calendar .ant-calendar-ok-btn:active,.ant-calendar .ant-calendar-ok-btn:focus{outline:0}.ant-calendar .ant-calendar-ok-btn:not([disabled]):hover{text-decoration:none}.ant-calendar .ant-calendar-ok-btn:not([disabled]):active{outline:0;box-shadow:none}.ant-calendar .ant-calendar-ok-btn[disabled]{cursor:not-allowed}.ant-calendar .ant-calendar-ok-btn[disabled]>*{pointer-events:none}.ant-calendar .ant-calendar-ok-btn-lg{height:40px;padding:6.4px 15px;font-size:16px;border-radius:2px}.ant-calendar .ant-calendar-ok-btn-sm{height:24px;padding:0 7px;font-size:14px;border-radius:2px}.ant-calendar .ant-calendar-ok-btn>a:only-child{color:currentColor}.ant-calendar .ant-calendar-ok-btn>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-calendar .ant-calendar-ok-btn:hover,.ant-calendar .ant-calendar-ok-btn:focus{color:#fff;background:#40a9ff;border-color:#40a9ff}.ant-calendar .ant-calendar-ok-btn:hover>a:only-child,.ant-calendar .ant-calendar-ok-btn:focus>a:only-child{color:currentColor}.ant-calendar .ant-calendar-ok-btn:hover>a:only-child:after,.ant-calendar .ant-calendar-ok-btn:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-calendar .ant-calendar-ok-btn:active{color:#fff;background:#096dd9;border-color:#096dd9}.ant-calendar .ant-calendar-ok-btn:active>a:only-child{color:currentColor}.ant-calendar .ant-calendar-ok-btn:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-calendar .ant-calendar-ok-btn[disabled],.ant-calendar .ant-calendar-ok-btn[disabled]:hover,.ant-calendar .ant-calendar-ok-btn[disabled]:focus,.ant-calendar .ant-calendar-ok-btn[disabled]:active{color:#00000040;background:#f5f5f5;border-color:#d9d9d9;text-shadow:none;box-shadow:none}.ant-calendar .ant-calendar-ok-btn[disabled]>a:only-child,.ant-calendar .ant-calendar-ok-btn[disabled]:hover>a:only-child,.ant-calendar .ant-calendar-ok-btn[disabled]:focus>a:only-child,.ant-calendar .ant-calendar-ok-btn[disabled]:active>a:only-child{color:currentColor}.ant-calendar .ant-calendar-ok-btn[disabled]>a:only-child:after,.ant-calendar .ant-calendar-ok-btn[disabled]:hover>a:only-child:after,.ant-calendar .ant-calendar-ok-btn[disabled]:focus>a:only-child:after,.ant-calendar .ant-calendar-ok-btn[disabled]:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:\"\"}.ant-calendar-range-picker-input{width:44%;height:99%;text-align:center;background-color:transparent;border:0;outline:0}.ant-calendar-range-picker-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-calendar-range-picker-input:-ms-input-placeholder{color:#bfbfbf}.ant-calendar-range-picker-input::-webkit-input-placeholder{color:#bfbfbf}.ant-calendar-range-picker-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-calendar-range-picker-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-calendar-range-picker-input:placeholder-shown{text-overflow:ellipsis}.ant-calendar-range-picker-input[disabled]{cursor:not-allowed}.ant-calendar-range-picker-separator{display:inline-block;min-width:10px;height:100%;color:#00000073;white-space:nowrap;text-align:center;vertical-align:top;pointer-events:none}.ant-input-disabled .ant-calendar-range-picker-separator{color:#00000040}.ant-calendar-range{width:552px;overflow:hidden}.ant-calendar-range .ant-calendar-date-panel:after{display:block;clear:both;height:0;visibility:hidden;content:\".\"}.ant-calendar-range-part{position:relative;width:50%}.ant-calendar-range-left{float:left}.ant-calendar-range-left .ant-calendar-time-picker-inner{border-right:1px solid #f0f0f0}.ant-calendar-range-right{float:right}.ant-calendar-range-right .ant-calendar-time-picker-inner{border-left:1px solid #f0f0f0}.ant-calendar-range-middle{position:absolute;left:50%;z-index:1;height:34px;margin:1px 0 0;padding:0 200px 0 0;color:#00000073;line-height:34px;text-align:center;transform:translate(-50%);pointer-events:none}.ant-calendar-range-right .ant-calendar-date-input-wrap{margin-left:-90px}.ant-calendar-range.ant-calendar-time .ant-calendar-range-middle{padding:0 10px 0 0;transform:translate(-50%)}.ant-calendar-range .ant-calendar-today :not(.ant-calendar-disabled-cell) :not(.ant-calendar-last-month-cell) :not(.ant-calendar-next-month-btn-day) .ant-calendar-date{color:#1890ff;background:#bae7ff;border-color:#1890ff}.ant-calendar-range .ant-calendar-selected-start-date .ant-calendar-date,.ant-calendar-range .ant-calendar-selected-end-date .ant-calendar-date{color:#fff;background:#1890ff;border:1px solid transparent}.ant-calendar-range .ant-calendar-selected-start-date .ant-calendar-date:hover,.ant-calendar-range .ant-calendar-selected-end-date .ant-calendar-date:hover{background:#1890ff}.ant-calendar-range.ant-calendar-time .ant-calendar-range-right .ant-calendar-date-input-wrap{margin-left:0}.ant-calendar-range .ant-calendar-input-wrap{position:relative;height:34px}.ant-calendar-range .ant-calendar-input,.ant-calendar-range .ant-calendar-time-picker-input{position:relative;display:inline-block;width:100%;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s;height:24px;padding:4px 0;line-height:24px;border:0;box-shadow:none}.ant-calendar-range .ant-calendar-input::-moz-placeholder,.ant-calendar-range .ant-calendar-time-picker-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-calendar-range .ant-calendar-input:-ms-input-placeholder,.ant-calendar-range .ant-calendar-time-picker-input:-ms-input-placeholder{color:#bfbfbf}.ant-calendar-range .ant-calendar-input::-webkit-input-placeholder,.ant-calendar-range .ant-calendar-time-picker-input::-webkit-input-placeholder{color:#bfbfbf}.ant-calendar-range .ant-calendar-input:-moz-placeholder-shown,.ant-calendar-range .ant-calendar-time-picker-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-calendar-range .ant-calendar-input:-ms-input-placeholder,.ant-calendar-range .ant-calendar-time-picker-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-calendar-range .ant-calendar-input:placeholder-shown,.ant-calendar-range .ant-calendar-time-picker-input:placeholder-shown{text-overflow:ellipsis}.ant-calendar-range .ant-calendar-input:hover,.ant-calendar-range .ant-calendar-time-picker-input:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-calendar-range .ant-calendar-input:focus,.ant-calendar-range .ant-calendar-time-picker-input:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-calendar-range .ant-calendar-input-disabled,.ant-calendar-range .ant-calendar-time-picker-input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-calendar-range .ant-calendar-input-disabled:hover,.ant-calendar-range .ant-calendar-time-picker-input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-calendar-range .ant-calendar-input[disabled],.ant-calendar-range .ant-calendar-time-picker-input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-calendar-range .ant-calendar-input[disabled]:hover,.ant-calendar-range .ant-calendar-time-picker-input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-calendar-range .ant-calendar-input,textarea.ant-calendar-range .ant-calendar-time-picker-input{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-calendar-range .ant-calendar-input-lg,.ant-calendar-range .ant-calendar-time-picker-input-lg{padding:6.5px 11px;font-size:16px}.ant-calendar-range .ant-calendar-input-sm,.ant-calendar-range .ant-calendar-time-picker-input-sm{padding:0 7px}.ant-calendar-range .ant-calendar-input:focus,.ant-calendar-range .ant-calendar-time-picker-input:focus{box-shadow:none}.ant-calendar-range .ant-calendar-time-picker-icon{display:none}.ant-calendar-range.ant-calendar-week-number{width:574px}.ant-calendar-range.ant-calendar-week-number .ant-calendar-range-part{width:286px}.ant-calendar-range .ant-calendar-year-panel,.ant-calendar-range .ant-calendar-month-panel,.ant-calendar-range .ant-calendar-decade-panel{top:34px}.ant-calendar-range .ant-calendar-month-panel .ant-calendar-year-panel{top:0}.ant-calendar-range .ant-calendar-decade-panel-table,.ant-calendar-range .ant-calendar-year-panel-table,.ant-calendar-range .ant-calendar-month-panel-table{height:208px}.ant-calendar-range .ant-calendar-in-range-cell{position:relative;border-radius:0}.ant-calendar-range .ant-calendar-in-range-cell>div{position:relative;z-index:1}.ant-calendar-range .ant-calendar-in-range-cell:before{position:absolute;top:4px;right:0;bottom:4px;left:0;display:block;background:#e6f7ff;border:0;border-radius:0;content:\"\"}.ant-calendar-range .ant-calendar-footer-extra{float:left}div.ant-calendar-range-quick-selector{text-align:left}div.ant-calendar-range-quick-selector>a{margin-right:8px}.ant-calendar-range .ant-calendar-header,.ant-calendar-range .ant-calendar-month-panel-header,.ant-calendar-range .ant-calendar-year-panel-header,.ant-calendar-range .ant-calendar-decade-panel-header{border-bottom:0}.ant-calendar-range .ant-calendar-body,.ant-calendar-range .ant-calendar-month-panel-body,.ant-calendar-range .ant-calendar-year-panel-body,.ant-calendar-range .ant-calendar-decade-panel-body{border-top:1px solid #f0f0f0}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker{top:68px;z-index:2;width:100%;height:207px}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker-panel{height:267px;margin-top:-34px}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker-inner{height:100%;padding-top:40px;background:none}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker-combobox{display:inline-block;height:100%;background-color:#fff;border-top:1px solid #f0f0f0}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker-select{height:100%}.ant-calendar-range.ant-calendar-time .ant-calendar-time-picker-select ul{max-height:100%}.ant-calendar-range.ant-calendar-time .ant-calendar-footer .ant-calendar-time-picker-btn{margin-right:8px}.ant-calendar-range.ant-calendar-time .ant-calendar-today-btn{height:22px;margin:8px 12px;line-height:22px}.ant-calendar-range-with-ranges.ant-calendar-time .ant-calendar-time-picker{height:233px}.ant-calendar-range.ant-calendar-show-time-picker .ant-calendar-body{border-top-color:transparent}.ant-calendar-time-picker{position:absolute;top:40px;width:100%;background-color:#fff}.ant-calendar-time-picker-panel{position:absolute;z-index:1050;width:100%}.ant-calendar-time-picker-inner{position:relative;display:inline-block;width:100%;overflow:hidden;font-size:14px;line-height:1.5;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;outline:none}.ant-calendar-time-picker-combobox,.ant-calendar-time-picker-column-1,.ant-calendar-time-picker-column-1 .ant-calendar-time-picker-select{width:100%}.ant-calendar-time-picker-column-2 .ant-calendar-time-picker-select{width:50%}.ant-calendar-time-picker-column-3 .ant-calendar-time-picker-select{width:33.33%}.ant-calendar-time-picker-column-4 .ant-calendar-time-picker-select{width:25%}.ant-calendar-time-picker-input-wrap{display:none}.ant-calendar-time-picker-select{position:relative;float:left;height:226px;overflow:hidden;font-size:14px;border-right:1px solid #f0f0f0}.ant-calendar-time-picker-select:hover{overflow-y:auto}.ant-calendar-time-picker-select:first-child{margin-left:0;border-left:0}.ant-calendar-time-picker-select:last-child{border-right:0}.ant-calendar-time-picker-select ul{width:100%;max-height:206px;margin:0;padding:0;list-style:none}.ant-calendar-time-picker-select li{width:100%;height:24px;margin:0;line-height:24px;text-align:center;list-style:none;cursor:pointer;transition:all .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-calendar-time-picker-select li:last-child:after{display:block;height:202px;content:\"\"}.ant-calendar-time-picker-select li:hover{background:#f5f5f5}.ant-calendar-time-picker-select li:focus{color:#1890ff;font-weight:600;outline:none}li.ant-calendar-time-picker-select-option-selected{font-weight:600;background:#f5f5f5}li.ant-calendar-time-picker-select-option-disabled{color:#00000040}li.ant-calendar-time-picker-select-option-disabled:hover{background:transparent;cursor:not-allowed}.ant-calendar-time .ant-calendar-day-select{display:inline-block;padding:0 2px;color:#000000d9;font-weight:500;line-height:34px}.ant-calendar-time .ant-calendar-footer{position:relative;height:auto}.ant-calendar-time .ant-calendar-footer-btn{text-align:right}.ant-calendar-time .ant-calendar-footer .ant-calendar-today-btn{float:left;margin:0}.ant-calendar-time .ant-calendar-footer .ant-calendar-time-picker-btn{display:inline-block;margin-right:8px}.ant-calendar-time .ant-calendar-footer .ant-calendar-time-picker-btn-disabled{color:#00000040}.ant-calendar-month-panel{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;background:#fff;border-radius:2px;outline:none}.ant-calendar-month-panel>div{display:flex;flex-direction:column;height:100%}.ant-calendar-month-panel-hidden{display:none}.ant-calendar-month-panel-header{height:40px;line-height:40px;text-align:center;border-bottom:1px solid #f0f0f0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative}.ant-calendar-month-panel-header a:hover{color:#40a9ff}.ant-calendar-month-panel-header .ant-calendar-month-panel-century-select,.ant-calendar-month-panel-header .ant-calendar-month-panel-decade-select,.ant-calendar-month-panel-header .ant-calendar-month-panel-year-select,.ant-calendar-month-panel-header .ant-calendar-month-panel-month-select{display:inline-block;padding:0 2px;color:#000000d9;font-weight:500;line-height:40px}.ant-calendar-month-panel-header .ant-calendar-month-panel-century-select-arrow,.ant-calendar-month-panel-header .ant-calendar-month-panel-decade-select-arrow,.ant-calendar-month-panel-header .ant-calendar-month-panel-year-select-arrow,.ant-calendar-month-panel-header .ant-calendar-month-panel-month-select-arrow{display:none}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn{position:absolute;top:0;display:inline-block;padding:0 5px;color:#00000073;font-size:16px;font-family:Arial,Hiragino Sans GB,Microsoft Yahei,\"Microsoft Sans Serif\",sans-serif;line-height:40px}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn{left:7px;height:100%}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:hover:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:hover:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:hover:after{border-color:#000000d9}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:after{display:none}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-year-btn:after{position:relative;left:-3px;display:inline-block}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn{right:7px;height:100%}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:hover:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:hover:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:hover:after{border-color:#000000d9}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:after{display:none}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:before{position:relative;left:3px}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-century-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-decade-btn:after,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-year-btn:after{display:inline-block}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn{left:29px;height:100%}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn:hover:after{border-color:#000000d9}.ant-calendar-month-panel-header .ant-calendar-month-panel-prev-month-btn:after{display:none}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn{right:29px;height:100%}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:hover:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:hover:after{border-color:#000000d9}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:after{display:none}.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:before,.ant-calendar-month-panel-header .ant-calendar-month-panel-next-month-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-month-panel-body{flex:1}.ant-calendar-month-panel-footer{border-top:1px solid #f0f0f0}.ant-calendar-month-panel-footer .ant-calendar-footer-extra{padding:0 12px}.ant-calendar-month-panel-table{width:100%;height:100%;table-layout:fixed;border-collapse:separate}.ant-calendar-month-panel-selected-cell .ant-calendar-month-panel-month,.ant-calendar-month-panel-selected-cell .ant-calendar-month-panel-month:hover{color:#fff;background:#1890ff}.ant-calendar-month-panel-cell{text-align:center}.ant-calendar-month-panel-cell-disabled .ant-calendar-month-panel-month,.ant-calendar-month-panel-cell-disabled .ant-calendar-month-panel-month:hover{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-calendar-month-panel-month{display:inline-block;height:24px;margin:0 auto;padding:0 8px;color:#000000d9;line-height:24px;text-align:center;background:transparent;border-radius:2px;transition:background .3s ease}.ant-calendar-month-panel-month:hover{background:#f5f5f5;cursor:pointer}.ant-calendar-year-panel{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;background:#fff;border-radius:2px;outline:none}.ant-calendar-year-panel>div{display:flex;flex-direction:column;height:100%}.ant-calendar-year-panel-hidden{display:none}.ant-calendar-year-panel-header{height:40px;line-height:40px;text-align:center;border-bottom:1px solid #f0f0f0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative}.ant-calendar-year-panel-header a:hover{color:#40a9ff}.ant-calendar-year-panel-header .ant-calendar-year-panel-century-select,.ant-calendar-year-panel-header .ant-calendar-year-panel-decade-select,.ant-calendar-year-panel-header .ant-calendar-year-panel-year-select,.ant-calendar-year-panel-header .ant-calendar-year-panel-month-select{display:inline-block;padding:0 2px;color:#000000d9;font-weight:500;line-height:40px}.ant-calendar-year-panel-header .ant-calendar-year-panel-century-select-arrow,.ant-calendar-year-panel-header .ant-calendar-year-panel-decade-select-arrow,.ant-calendar-year-panel-header .ant-calendar-year-panel-year-select-arrow,.ant-calendar-year-panel-header .ant-calendar-year-panel-month-select-arrow{display:none}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn{position:absolute;top:0;display:inline-block;padding:0 5px;color:#00000073;font-size:16px;font-family:Arial,Hiragino Sans GB,Microsoft Yahei,\"Microsoft Sans Serif\",sans-serif;line-height:40px}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn{left:7px;height:100%}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:hover:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:hover:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:hover:after{border-color:#000000d9}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:after{display:none}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-year-btn:after{position:relative;left:-3px;display:inline-block}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn{right:7px;height:100%}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:hover:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:hover:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:hover:after{border-color:#000000d9}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:after{display:none}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:before{position:relative;left:3px}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-century-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-decade-btn:after,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-year-btn:after{display:inline-block}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn{left:29px;height:100%}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn:hover:after{border-color:#000000d9}.ant-calendar-year-panel-header .ant-calendar-year-panel-prev-month-btn:after{display:none}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn{right:29px;height:100%}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:hover:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:hover:after{border-color:#000000d9}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:after{display:none}.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:before,.ant-calendar-year-panel-header .ant-calendar-year-panel-next-month-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-year-panel-body{flex:1}.ant-calendar-year-panel-footer{border-top:1px solid #f0f0f0}.ant-calendar-year-panel-footer .ant-calendar-footer-extra{padding:0 12px}.ant-calendar-year-panel-table{width:100%;height:100%;table-layout:fixed;border-collapse:separate}.ant-calendar-year-panel-cell{text-align:center}.ant-calendar-year-panel-year{display:inline-block;height:24px;margin:0 auto;padding:0 8px;color:#000000d9;line-height:24px;text-align:center;background:transparent;border-radius:2px;transition:background .3s ease}.ant-calendar-year-panel-year:hover{background:#f5f5f5;cursor:pointer}.ant-calendar-year-panel-selected-cell .ant-calendar-year-panel-year,.ant-calendar-year-panel-selected-cell .ant-calendar-year-panel-year:hover{color:#fff;background:#1890ff}.ant-calendar-year-panel-last-decade-cell .ant-calendar-year-panel-year,.ant-calendar-year-panel-next-decade-cell .ant-calendar-year-panel-year{color:#00000040;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-calendar-decade-panel{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;display:flex;flex-direction:column;background:#fff;border-radius:2px;outline:none}.ant-calendar-decade-panel-hidden{display:none}.ant-calendar-decade-panel-header{height:40px;line-height:40px;text-align:center;border-bottom:1px solid #f0f0f0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative}.ant-calendar-decade-panel-header a:hover{color:#40a9ff}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-century-select,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-decade-select,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-year-select,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-month-select{display:inline-block;padding:0 2px;color:#000000d9;font-weight:500;line-height:40px}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-century-select-arrow,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-decade-select-arrow,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-year-select-arrow,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-month-select-arrow{display:none}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn{position:absolute;top:0;display:inline-block;padding:0 5px;color:#00000073;font-size:16px;font-family:Arial,Hiragino Sans GB,Microsoft Yahei,\"Microsoft Sans Serif\",sans-serif;line-height:40px}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn{left:7px;height:100%}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:hover:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:hover:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:hover:after{border-color:#000000d9}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:after{display:none}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-year-btn:after{position:relative;left:-3px;display:inline-block}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn{right:7px;height:100%}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:hover:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:hover:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:hover:after{border-color:#000000d9}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:after{display:none}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:before{position:relative;left:3px}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-century-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-decade-btn:after,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-year-btn:after{display:inline-block}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn{left:29px;height:100%}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn:hover:after{border-color:#000000d9}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-prev-month-btn:after{display:none}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn{right:29px;height:100%}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:after{position:relative;top:-1px;display:inline-block;width:8px;height:8px;vertical-align:middle;border:0 solid #aaa;border-width:1.5px 0 0 1.5px;border-radius:1px;transform:rotate(-45deg) scale(.8);transition:all .3s;content:\"\"}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:hover:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:hover:after{border-color:#000000d9}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:after{display:none}.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:before,.ant-calendar-decade-panel-header .ant-calendar-decade-panel-next-month-btn:after{transform:rotate(135deg) scale(.8)}.ant-calendar-decade-panel-body{flex:1}.ant-calendar-decade-panel-footer{border-top:1px solid #f0f0f0}.ant-calendar-decade-panel-footer .ant-calendar-footer-extra{padding:0 12px}.ant-calendar-decade-panel-table{width:100%;height:100%;table-layout:fixed;border-collapse:separate}.ant-calendar-decade-panel-cell{white-space:nowrap;text-align:center}.ant-calendar-decade-panel-decade{display:inline-block;height:24px;margin:0 auto;padding:0 6px;color:#000000d9;line-height:24px;text-align:center;background:transparent;border-radius:2px;transition:background .3s ease}.ant-calendar-decade-panel-decade:hover{background:#f5f5f5;cursor:pointer}.ant-calendar-decade-panel-selected-cell .ant-calendar-decade-panel-decade,.ant-calendar-decade-panel-selected-cell .ant-calendar-decade-panel-decade:hover{color:#fff;background:#1890ff}.ant-calendar-decade-panel-last-century-cell .ant-calendar-decade-panel-decade,.ant-calendar-decade-panel-next-century-cell .ant-calendar-decade-panel-decade{color:#00000040;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-calendar-month .ant-calendar-month-header-wrap{position:relative;height:288px}.ant-calendar-month .ant-calendar-month-panel,.ant-calendar-month .ant-calendar-year-panel{top:0;height:100%}.ant-calendar-week-number-cell{opacity:.5}.ant-calendar-week-number .ant-calendar-body tr{cursor:pointer;transition:all .3s}.ant-calendar-week-number .ant-calendar-body tr:hover{background:#e6f7ff}.ant-calendar-week-number .ant-calendar-body tr.ant-calendar-active-week{font-weight:700;background:#bae7ff}.ant-calendar-week-number .ant-calendar-body tr .ant-calendar-selected-day .ant-calendar-date,.ant-calendar-week-number .ant-calendar-body tr .ant-calendar-selected-day:hover .ant-calendar-date{color:#000000d9;background:transparent}.ant-time-picker-panel{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;z-index:1050;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}.ant-time-picker-panel-inner{position:relative;left:-2px;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border-radius:2px;outline:none;box-shadow:0 2px 8px #00000026}.ant-time-picker-panel-input{background:#fff;width:100%;max-width:154px;margin:0;padding:0;line-height:normal;border:0;outline:0;cursor:auto}.ant-time-picker-panel-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-time-picker-panel-input:-ms-input-placeholder{color:#bfbfbf}.ant-time-picker-panel-input::-webkit-input-placeholder{color:#bfbfbf}.ant-time-picker-panel-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-time-picker-panel-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-time-picker-panel-input:placeholder-shown{text-overflow:ellipsis}.ant-time-picker-panel-input-wrap{position:relative;padding:7px 2px 7px 12px;border-bottom:1px solid #f0f0f0}.ant-time-picker-panel-input-invalid{border-color:#ff4d4f}.ant-time-picker-panel-narrow .ant-time-picker-panel-input-wrap{max-width:112px}.ant-time-picker-panel-select{position:relative;float:left;width:56px;max-height:192px;overflow:hidden;font-size:14px;border-left:1px solid #f0f0f0}.ant-time-picker-panel-select:hover{overflow-y:auto}.ant-time-picker-panel-select:first-child{margin-left:0;border-left:0}.ant-time-picker-panel-select:last-child{border-right:0}.ant-time-picker-panel-select:only-child{width:100%}.ant-time-picker-panel-select ul{width:56px;margin:0;padding:0 0 160px;list-style:none}.ant-time-picker-panel-select li{width:100%;height:32px;margin:0;padding:0 0 0 12px;line-height:32px;text-align:left;list-style:none;cursor:pointer;transition:all .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-time-picker-panel-select li:focus{color:#1890ff;font-weight:600;outline:none}.ant-time-picker-panel-select li:hover{background:#f5f5f5}li.ant-time-picker-panel-select-option-selected{font-weight:600;background:#f5f5f5}li.ant-time-picker-panel-select-option-selected:hover{background:#f5f5f5}li.ant-time-picker-panel-select-option-disabled{color:#00000040}li.ant-time-picker-panel-select-option-disabled:hover{background:transparent;cursor:not-allowed}li.ant-time-picker-panel-select-option-disabled:focus{color:#00000040;font-weight:inherit}.ant-time-picker-panel-combobox:before,.ant-time-picker-panel-combobox:after{display:table;content:\"\"}.ant-time-picker-panel-combobox:after{clear:both}.ant-time-picker-panel-addon{padding:8px;border-top:1px solid #f0f0f0}.ant-time-picker-panel.slide-up-enter.slide-up-enter-active.ant-time-picker-panel-placement-topLeft,.ant-time-picker-panel.slide-up-enter.slide-up-enter-active.ant-time-picker-panel-placement-topRight,.ant-time-picker-panel.slide-up-appear.slide-up-appear-active.ant-time-picker-panel-placement-topLeft,.ant-time-picker-panel.slide-up-appear.slide-up-appear-active.ant-time-picker-panel-placement-topRight{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-time-picker-panel.slide-up-enter.slide-up-enter-active.ant-time-picker-panel-placement-bottomLeft,.ant-time-picker-panel.slide-up-enter.slide-up-enter-active.ant-time-picker-panel-placement-bottomRight,.ant-time-picker-panel.slide-up-appear.slide-up-appear-active.ant-time-picker-panel-placement-bottomLeft,.ant-time-picker-panel.slide-up-appear.slide-up-appear-active.ant-time-picker-panel-placement-bottomRight{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-time-picker-panel.slide-up-leave.slide-up-leave-active.ant-time-picker-panel-placement-topLeft,.ant-time-picker-panel.slide-up-leave.slide-up-leave-active.ant-time-picker-panel-placement-topRight{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-time-picker-panel.slide-up-leave.slide-up-leave-active.ant-time-picker-panel-placement-bottomLeft,.ant-time-picker-panel.slide-up-leave.slide-up-leave-active.ant-time-picker-panel-placement-bottomRight{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-time-picker{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;width:128px;outline:none;cursor:text;transition:opacity .3s}.ant-time-picker-input{position:relative;display:inline-block;width:100%;padding:4px 11px;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s}.ant-time-picker-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-time-picker-input:-ms-input-placeholder{color:#bfbfbf}.ant-time-picker-input::-webkit-input-placeholder{color:#bfbfbf}.ant-time-picker-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-time-picker-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-time-picker-input:placeholder-shown{text-overflow:ellipsis}.ant-time-picker-input:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-time-picker-input:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-time-picker-input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-time-picker-input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-time-picker-input{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-time-picker-input-lg{padding:6.5px 11px;font-size:16px}.ant-time-picker-input-sm{padding:0 7px}.ant-time-picker-input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-time-picker-input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-time-picker-open{opacity:0}.ant-time-picker-icon,.ant-time-picker-clear{position:absolute;top:50%;right:11px;z-index:1;width:14px;height:14px;margin-top:-7px;color:#00000040;line-height:14px;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-time-picker-icon .ant-time-picker-clock-icon,.ant-time-picker-clear .ant-time-picker-clock-icon{display:block;color:#00000040;line-height:1}.ant-time-picker-clear{z-index:2;background:#fff;opacity:0;pointer-events:none}.ant-time-picker-clear:hover{color:#00000073}.ant-time-picker:hover .ant-time-picker-clear{opacity:1;pointer-events:auto}.ant-time-picker-large .ant-time-picker-input{padding:6.5px 11px;font-size:16px}.ant-time-picker-small .ant-time-picker-input{padding:0 7px}.ant-time-picker-small .ant-time-picker-icon,.ant-time-picker-small .ant-time-picker-clear{right:7px}@media not all and (-webkit-min-device-pixel-ratio: 0),not all and (min-resolution: .001dpcm){@supports (-webkit-appearance: none) and (stroke-color: transparent){.ant-input{line-height:1.5715}}}.ant-tag{box-sizing:border-box;margin:0 8px 0 0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block;height:auto;padding:0 7px;font-size:12px;line-height:20px;white-space:nowrap;background:#fafafa;border:1px solid #d9d9d9;border-radius:2px;opacity:1;transition:all .3s}.ant-tag,.ant-tag a,.ant-tag a:hover{color:#000000d9}.ant-tag>a:first-child:last-child{display:inline-block;margin:0 -8px;padding:0 8px}.ant-tag-close-icon{margin-left:3px;color:#00000073;font-size:10px;cursor:pointer;transition:all .3s}.ant-tag-close-icon:hover{color:#000000d9}.ant-tag-has-color{border-color:transparent}.ant-tag-has-color,.ant-tag-has-color a,.ant-tag-has-color a:hover,.ant-tag-has-color .anticon-close,.ant-tag-has-color .anticon-close:hover{color:#fff}.ant-tag-checkable{background-color:transparent;border-color:transparent;cursor:pointer}.ant-tag-checkable:not(.ant-tag-checkable-checked):hover{color:#1890ff}.ant-tag-checkable:active,.ant-tag-checkable-checked{color:#fff}.ant-tag-checkable-checked{background-color:#1890ff}.ant-tag-checkable:active{background-color:#096dd9}.ant-tag-hidden{display:none}.ant-tag-pink{color:#c41d7f;background:#fff0f6;border-color:#ffadd2}.ant-tag-pink-inverse{color:#fff;background:#eb2f96;border-color:#eb2f96}.ant-tag-magenta{color:#c41d7f;background:#fff0f6;border-color:#ffadd2}.ant-tag-magenta-inverse{color:#fff;background:#eb2f96;border-color:#eb2f96}.ant-tag-red{color:#cf1322;background:#fff1f0;border-color:#ffa39e}.ant-tag-red-inverse{color:#fff;background:#f5222d;border-color:#f5222d}.ant-tag-volcano{color:#d4380d;background:#fff2e8;border-color:#ffbb96}.ant-tag-volcano-inverse{color:#fff;background:#fa541c;border-color:#fa541c}.ant-tag-orange{color:#d46b08;background:#fff7e6;border-color:#ffd591}.ant-tag-orange-inverse{color:#fff;background:#fa8c16;border-color:#fa8c16}.ant-tag-yellow{color:#d4b106;background:#feffe6;border-color:#fffb8f}.ant-tag-yellow-inverse{color:#fff;background:#fadb14;border-color:#fadb14}.ant-tag-gold{color:#d48806;background:#fffbe6;border-color:#ffe58f}.ant-tag-gold-inverse{color:#fff;background:#faad14;border-color:#faad14}.ant-tag-cyan{color:#08979c;background:#e6fffb;border-color:#87e8de}.ant-tag-cyan-inverse{color:#fff;background:#13c2c2;border-color:#13c2c2}.ant-tag-lime{color:#7cb305;background:#fcffe6;border-color:#eaff8f}.ant-tag-lime-inverse{color:#fff;background:#a0d911;border-color:#a0d911}.ant-tag-green{color:#389e0d;background:#f6ffed;border-color:#b7eb8f}.ant-tag-green-inverse{color:#fff;background:#52c41a;border-color:#52c41a}.ant-tag-blue{color:#096dd9;background:#e6f7ff;border-color:#91d5ff}.ant-tag-blue-inverse{color:#fff;background:#1890ff;border-color:#1890ff}.ant-tag-geekblue{color:#1d39c4;background:#f0f5ff;border-color:#adc6ff}.ant-tag-geekblue-inverse{color:#fff;background:#2f54eb;border-color:#2f54eb}.ant-tag-purple{color:#531dab;background:#f9f0ff;border-color:#d3adf7}.ant-tag-purple-inverse{color:#fff;background:#722ed1;border-color:#722ed1}.ant-tag-success{color:#52c41a;background:#f6ffed;border-color:#b7eb8f}.ant-tag-processing{color:#1890ff;background:#e6f7ff;border-color:#91d5ff}.ant-tag-error{color:#f5222d;background:#fff1f0;border-color:#ffa39e}.ant-tag-warning{color:#fa8c16;background:#fff7e6;border-color:#ffd591}.ant-tag>.anticon+span,.ant-tag>span+.anticon{margin-left:7px}.ant-tag.ant-tag-rtl{margin-right:0;margin-left:8px;direction:rtl;text-align:right}.ant-tag-rtl .ant-tag-close-icon{margin-right:3px;margin-left:0}.ant-tag-rtl.ant-tag>.anticon+span,.ant-tag-rtl.ant-tag>span+.anticon{margin-right:7px;margin-left:0}.ant-descriptions-header{display:flex;align-items:center;margin-bottom:20px}.ant-descriptions-title{flex:auto;overflow:hidden;color:#000000d9;font-weight:700;font-size:16px;line-height:1.5715;white-space:nowrap;text-overflow:ellipsis}.ant-descriptions-extra{margin-left:auto;color:#000000d9;font-size:14px}.ant-descriptions-view{width:100%;overflow:hidden;border-radius:2px}.ant-descriptions-view table{width:100%;table-layout:fixed}.ant-descriptions-row>th,.ant-descriptions-row>td{padding-bottom:16px}.ant-descriptions-row:last-child{border-bottom:none}.ant-descriptions-item-label{color:#000000d9;font-weight:400;font-size:14px;line-height:1.5715;text-align:start}.ant-descriptions-item-label:after{content:\":\";position:relative;top:-.5px;margin:0 8px 0 2px}.ant-descriptions-item-label.ant-descriptions-item-no-colon:after{content:\" \"}.ant-descriptions-item-no-label:after{margin:0;content:\"\"}.ant-descriptions-item-content{display:table-cell;flex:1;color:#000000d9;font-size:14px;line-height:1.5715;word-break:break-word;overflow-wrap:break-word}.ant-descriptions-item{padding-bottom:0;vertical-align:top}.ant-descriptions-item-container{display:flex}.ant-descriptions-item-container .ant-descriptions-item-label,.ant-descriptions-item-container .ant-descriptions-item-content{display:inline-flex;align-items:baseline}.ant-descriptions-middle .ant-descriptions-row>th,.ant-descriptions-middle .ant-descriptions-row>td{padding-bottom:12px}.ant-descriptions-small .ant-descriptions-row>th,.ant-descriptions-small .ant-descriptions-row>td{padding-bottom:8px}.ant-descriptions-bordered .ant-descriptions-view{border:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-view>table{table-layout:auto}.ant-descriptions-bordered .ant-descriptions-item-label,.ant-descriptions-bordered .ant-descriptions-item-content{padding:16px 24px;border-right:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-item-label:last-child,.ant-descriptions-bordered .ant-descriptions-item-content:last-child{border-right:none}.ant-descriptions-bordered .ant-descriptions-item-label{background-color:#fafafa}.ant-descriptions-bordered .ant-descriptions-item-label:after{display:none}.ant-descriptions-bordered .ant-descriptions-row{border-bottom:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-row:last-child{border-bottom:none}.ant-descriptions-bordered.ant-descriptions-middle .ant-descriptions-item-label,.ant-descriptions-bordered.ant-descriptions-middle .ant-descriptions-item-content{padding:12px 24px}.ant-descriptions-bordered.ant-descriptions-small .ant-descriptions-item-label,.ant-descriptions-bordered.ant-descriptions-small .ant-descriptions-item-content{padding:8px 16px}.ant-descriptions-rtl{direction:rtl}.ant-descriptions-rtl .ant-descriptions-item-label:after{margin:0 2px 0 8px}.ant-descriptions-rtl.ant-descriptions-bordered .ant-descriptions-item-label,.ant-descriptions-rtl.ant-descriptions-bordered .ant-descriptions-item-content{border-right:none;border-left:1px solid #f0f0f0}.ant-descriptions-rtl.ant-descriptions-bordered .ant-descriptions-item-label:last-child,.ant-descriptions-rtl.ant-descriptions-bordered .ant-descriptions-item-content:last-child{border-left:none}.ant-divider{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";border-top:1px solid rgba(0,0,0,.06)}.ant-divider-vertical{position:relative;top:-.06em;display:inline-block;height:.9em;margin:0 8px;vertical-align:middle;border-top:0;border-left:1px solid rgba(0,0,0,.06)}.ant-divider-horizontal{display:flex;clear:both;width:100%;min-width:100%;margin:24px 0}.ant-divider-horizontal.ant-divider-with-text{display:flex;margin:16px 0;color:#000000d9;font-weight:500;font-size:16px;white-space:nowrap;text-align:center;border-top:0;border-top-color:#0000000f}.ant-divider-horizontal.ant-divider-with-text:before,.ant-divider-horizontal.ant-divider-with-text:after{position:relative;top:50%;width:50%;border-top:1px solid transparent;border-top-color:inherit;border-bottom:0;transform:translateY(50%);content:\"\"}.ant-divider-horizontal.ant-divider-with-text-left:before{top:50%;width:5%}.ant-divider-horizontal.ant-divider-with-text-left:after{top:50%;width:95%}.ant-divider-horizontal.ant-divider-with-text-right:before{top:50%;width:95%}.ant-divider-horizontal.ant-divider-with-text-right:after{top:50%;width:5%}.ant-divider-inner-text{display:inline-block;padding:0 1em}.ant-divider-dashed{background:none;border-color:#0000000f;border-style:dashed;border-width:1px 0 0}.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed{border-top:0}.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed:before,.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed:after{border-style:dashed none none}.ant-divider-vertical.ant-divider-dashed{border-width:0 0 0 1px}.ant-divider-plain.ant-divider-with-text{color:#000000d9;font-weight:400;font-size:14px}.ant-divider-rtl{direction:rtl}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-left:before{width:95%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-left:after{width:5%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-right:before{width:5%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-right:after{width:95%}.ant-drawer{position:fixed;z-index:1000;width:0%;height:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1),height 0s ease .3s,width 0s ease .3s}.ant-drawer>*{transition:transform .3s cubic-bezier(.7,.3,.1,1),box-shadow .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-content-wrapper{position:absolute}.ant-drawer .ant-drawer-content{width:100%;height:100%}.ant-drawer-left,.ant-drawer-right{top:0;width:0%;height:100%}.ant-drawer-left .ant-drawer-content-wrapper,.ant-drawer-right .ant-drawer-content-wrapper{height:100%}.ant-drawer-left.ant-drawer-open,.ant-drawer-right.ant-drawer-open{width:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-left.ant-drawer-open.no-mask,.ant-drawer-right.ant-drawer-open.no-mask{width:0%}.ant-drawer-left.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:2px 0 8px #00000026}.ant-drawer-right,.ant-drawer-right .ant-drawer-content-wrapper{right:0}.ant-drawer-right.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:-2px 0 8px #00000026}.ant-drawer-right.ant-drawer-open.no-mask{right:1px;transform:translate(1px)}.ant-drawer-top,.ant-drawer-bottom{left:0;width:100%;height:0%}.ant-drawer-top .ant-drawer-content-wrapper,.ant-drawer-bottom .ant-drawer-content-wrapper{width:100%}.ant-drawer-top.ant-drawer-open,.ant-drawer-bottom.ant-drawer-open{height:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-top.ant-drawer-open.no-mask,.ant-drawer-bottom.ant-drawer-open.no-mask{height:0%}.ant-drawer-top{top:0}.ant-drawer-top.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:0 2px 8px #00000026}.ant-drawer-bottom,.ant-drawer-bottom .ant-drawer-content-wrapper{bottom:0}.ant-drawer-bottom.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:0 -2px 8px #00000026}.ant-drawer-bottom.ant-drawer-open.no-mask{bottom:1px;transform:translateY(1px)}.ant-drawer.ant-drawer-open .ant-drawer-mask{height:100%;opacity:1;transition:none;-webkit-animation:antdDrawerFadeIn .3s cubic-bezier(.7,.3,.1,1);animation:antdDrawerFadeIn .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-title{margin:0;color:#000000d9;font-weight:500;font-size:16px;line-height:22px}.ant-drawer-content{position:relative;z-index:1;overflow:auto;background-color:#fff;background-clip:padding-box;border:0}.ant-drawer-close{position:absolute;top:0;right:0;z-index:10;display:block;width:56px;height:56px;padding:0;color:#00000073;font-weight:700;font-size:16px;font-style:normal;line-height:56px;text-align:center;text-transform:none;text-decoration:none;background:transparent;border:0;outline:0;cursor:pointer;transition:color .3s;text-rendering:auto}.ant-drawer-close:focus,.ant-drawer-close:hover{color:#000000bf;text-decoration:none}.ant-drawer-header{position:relative;padding:16px 24px;color:#000000d9;background:#fff;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-drawer-header-no-title{color:#000000d9;background:#fff}.ant-drawer-body{padding:24px;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-drawer-wrapper-body{height:100%;overflow:auto}.ant-drawer-mask{position:absolute;top:0;left:0;width:100%;height:0;background-color:#00000073;opacity:0;filter:alpha(opacity=45);transition:opacity .3s linear,height 0s ease .3s}.ant-drawer-open-content{box-shadow:0 4px 12px #00000026}@-webkit-keyframes antdDrawerFadeIn{0%{opacity:0}to{opacity:1}}@keyframes antdDrawerFadeIn{0%{opacity:0}to{opacity:1}}.ant-form-item .ant-mentions,.ant-form-item textarea.ant-input{height:auto}.ant-form-item .ant-upload{background:transparent}.ant-form-item .ant-upload.ant-upload-drag{background:#fafafa}.ant-form-item input[type=radio],.ant-form-item input[type=checkbox]{width:14px;height:14px}.ant-form-item .ant-radio-inline,.ant-form-item .ant-checkbox-inline{display:inline-block;margin-left:8px;font-weight:400;vertical-align:middle;cursor:pointer}.ant-form-item .ant-radio-inline:first-child,.ant-form-item .ant-checkbox-inline:first-child{margin-left:0}.ant-form-item .ant-checkbox-vertical,.ant-form-item .ant-radio-vertical{display:block}.ant-form-item .ant-checkbox-vertical+.ant-checkbox-vertical,.ant-form-item .ant-radio-vertical+.ant-radio-vertical{margin-left:0}.ant-form-item .ant-input-number+.ant-form-text{margin-left:8px}.ant-form-item .ant-input-number-handler-wrap{z-index:2}.ant-form-item .ant-select,.ant-form-item .ant-cascader-picker{width:100%}.ant-form-item .ant-picker-calendar-year-select,.ant-form-item .ant-picker-calendar-month-select,.ant-form-item .ant-input-group .ant-select,.ant-form-item .ant-input-group .ant-cascader-picker{width:auto}.ant-form-inline{display:flex;flex-wrap:wrap}.ant-form-inline .ant-form-item{flex:none;flex-wrap:nowrap;margin-right:16px;margin-bottom:0}.ant-form-inline .ant-form-item-with-help{margin-bottom:24px}.ant-form-inline .ant-form-item>.ant-form-item-label,.ant-form-inline .ant-form-item>.ant-form-item-control{display:inline-block;vertical-align:top}.ant-form-inline .ant-form-item>.ant-form-item-label{flex:none}.ant-form-inline .ant-form-item .ant-form-text,.ant-form-inline .ant-form-item .ant-form-item-has-feedback{display:inline-block}.ant-form-horizontal .ant-form-item-label{flex-grow:0}.ant-form-horizontal .ant-form-item-control{flex:1 1 0}.ant-form-vertical .ant-form-item{flex-direction:column}.ant-form-vertical .ant-form-item-label>label{height:auto}.ant-form-vertical .ant-form-item-label,.ant-col-24.ant-form-item-label,.ant-col-xl-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-form-vertical .ant-form-item-label>label,.ant-col-24.ant-form-item-label>label,.ant-col-xl-24.ant-form-item-label>label{margin:0}.ant-form-vertical .ant-form-item-label>label:after,.ant-col-24.ant-form-item-label>label:after,.ant-col-xl-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-form-vertical .ant-form-item-label,.ant-form-rtl.ant-col-24.ant-form-item-label,.ant-form-rtl.ant-col-xl-24.ant-form-item-label{text-align:right}@media (max-width: 575px){.ant-form-item .ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-form-item .ant-form-item-label>label{margin:0}.ant-form-item .ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-form-item .ant-form-item-label{text-align:right}.ant-form .ant-form-item{flex-wrap:wrap}.ant-form .ant-form-item .ant-form-item-label,.ant-form .ant-form-item .ant-form-item-control{flex:0 0 100%;max-width:100%}.ant-col-xs-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-xs-24.ant-form-item-label>label{margin:0}.ant-col-xs-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-col-xs-24.ant-form-item-label{text-align:right}}@media (max-width: 767px){.ant-col-sm-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-sm-24.ant-form-item-label>label{margin:0}.ant-col-sm-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-col-sm-24.ant-form-item-label{text-align:right}}@media (max-width: 991px){.ant-col-md-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-md-24.ant-form-item-label>label{margin:0}.ant-col-md-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-col-md-24.ant-form-item-label{text-align:right}}@media (max-width: 1199px){.ant-col-lg-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-lg-24.ant-form-item-label>label{margin:0}.ant-col-lg-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-col-lg-24.ant-form-item-label{text-align:right}}@media (max-width: 1599px){.ant-col-xl-24.ant-form-item-label{padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-xl-24.ant-form-item-label>label{margin:0}.ant-col-xl-24.ant-form-item-label>label:after{display:none}.ant-form-rtl.ant-col-xl-24.ant-form-item-label{text-align:right}}.ant-form-item-explain.ant-form-item-explain-error{color:#ff4d4f}.ant-form-item-explain.ant-form-item-explain-warning{color:#faad14}.ant-form-item-has-feedback .ant-input{padding-right:24px}.ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input-suffix{padding-right:18px}.ant-form-item-has-feedback .ant-input-search:not(.ant-input-search-enter-button) .ant-input-suffix{right:28px}.ant-form-item-has-feedback .ant-switch{margin:2px 0 4px}.ant-form-item-has-feedback>.ant-select .ant-select-arrow,.ant-form-item-has-feedback>.ant-select .ant-select-clear,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-arrow,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-clear{right:32px}.ant-form-item-has-feedback>.ant-select .ant-select-selection-selected-value,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection-selected-value{padding-right:42px}.ant-form-item-has-feedback .ant-cascader-picker-arrow{margin-right:19px}.ant-form-item-has-feedback .ant-cascader-picker-clear{right:32px}.ant-form-item-has-feedback .ant-picker,.ant-form-item-has-feedback .ant-picker-large{padding-right:29.2px}.ant-form-item-has-feedback .ant-picker-small{padding-right:25.2px}.ant-form-item-has-feedback.ant-form-item-has-success .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-has-warning .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-has-error .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-is-validating .ant-form-item-children-icon{position:absolute;top:50%;right:0;z-index:1;width:32px;height:20px;margin-top:-10px;font-size:14px;line-height:20px;text-align:center;visibility:visible;-webkit-animation:zoomIn .3s cubic-bezier(.12,.4,.29,1.46);animation:zoomIn .3s cubic-bezier(.12,.4,.29,1.46);pointer-events:none}.ant-form-item-has-success.ant-form-item-has-feedback .ant-form-item-children-icon{color:#52c41a;-webkit-animation-name:diffZoomIn1!important;animation-name:diffZoomIn1!important}.ant-form-item-has-warning .ant-form-item-split{color:#faad14}.ant-form-item-has-warning .ant-input,.ant-form-item-has-warning .ant-input-affix-wrapper,.ant-form-item-has-warning .ant-input:hover,.ant-form-item-has-warning .ant-input-affix-wrapper:hover{background-color:#fff;border-color:#faad14}.ant-form-item-has-warning .ant-input:focus,.ant-form-item-has-warning .ant-input-affix-wrapper:focus,.ant-form-item-has-warning .ant-input-focused,.ant-form-item-has-warning .ant-input-affix-wrapper-focused{border-color:#ffc53d;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #faad1433}.ant-form-item-has-warning .ant-input-disabled,.ant-form-item-has-warning .ant-input-disabled:hover,.ant-form-item-has-warning .ant-input-affix-wrapper-disabled,.ant-form-item-has-warning .ant-input-affix-wrapper-disabled:hover{background-color:#f5f5f5;border-color:#d9d9d9}.ant-form-item-has-warning .ant-input-affix-wrapper-disabled input:focus,.ant-form-item-has-warning .ant-input-affix-wrapper-disabled:hover input:focus{box-shadow:none!important}.ant-form-item-has-warning .ant-calendar-picker-open .ant-calendar-picker-input{border-color:#ffc53d;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #faad1433}.ant-form-item-has-warning .ant-input-prefix{color:#faad14}.ant-form-item-has-warning .ant-input-group-addon{color:#faad14;border-color:#faad14}.ant-form-item-has-warning .has-feedback{color:#faad14}.ant-form-item-has-warning.ant-form-item-has-feedback .ant-form-item-children-icon{color:#faad14;-webkit-animation-name:diffZoomIn3!important;animation-name:diffZoomIn3!important}.ant-form-item-has-warning .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input) .ant-select-selector{background-color:#fff;border-color:#faad14!important}.ant-form-item-has-warning .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input).ant-select-open .ant-select-selector,.ant-form-item-has-warning .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input).ant-select-focused .ant-select-selector{border-color:#ffc53d;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #faad1433}.ant-form-item-has-warning .ant-input-number,.ant-form-item-has-warning .ant-picker{background-color:#fff;border-color:#faad14}.ant-form-item-has-warning .ant-input-number-focused,.ant-form-item-has-warning .ant-picker-focused,.ant-form-item-has-warning .ant-input-number:focus,.ant-form-item-has-warning .ant-picker:focus{border-color:#ffc53d;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #faad1433}.ant-form-item-has-warning .ant-input-number:not([disabled]):hover,.ant-form-item-has-warning .ant-picker:not([disabled]):hover{background-color:#fff;border-color:#faad14}.ant-form-item-has-warning .ant-cascader-picker:focus .ant-cascader-input{border-color:#ffc53d;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #faad1433}.ant-form-item-has-error .ant-form-item-split{color:#ff4d4f}.ant-form-item-has-error .ant-input,.ant-form-item-has-error .ant-input-affix-wrapper,.ant-form-item-has-error .ant-input:hover,.ant-form-item-has-error .ant-input-affix-wrapper:hover{background-color:#fff;border-color:#ff4d4f}.ant-form-item-has-error .ant-input:focus,.ant-form-item-has-error .ant-input-affix-wrapper:focus,.ant-form-item-has-error .ant-input-focused,.ant-form-item-has-error .ant-input-affix-wrapper-focused{border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-input-disabled,.ant-form-item-has-error .ant-input-disabled:hover,.ant-form-item-has-error .ant-input-affix-wrapper-disabled,.ant-form-item-has-error .ant-input-affix-wrapper-disabled:hover{background-color:#f5f5f5;border-color:#d9d9d9}.ant-form-item-has-error .ant-input-affix-wrapper-disabled input:focus,.ant-form-item-has-error .ant-input-affix-wrapper-disabled:hover input:focus{box-shadow:none!important}.ant-form-item-has-error .ant-calendar-picker-open .ant-calendar-picker-input{border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-input-prefix{color:#ff4d4f}.ant-form-item-has-error .ant-input-group-addon{color:#ff4d4f;border-color:#ff4d4f}.ant-form-item-has-error .has-feedback{color:#ff4d4f}.ant-form-item-has-error.ant-form-item-has-feedback .ant-form-item-children-icon{color:#ff4d4f;-webkit-animation-name:diffZoomIn2!important;animation-name:diffZoomIn2!important}.ant-form-item-has-error .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input) .ant-select-selector{background-color:#fff;border-color:#ff4d4f!important}.ant-form-item-has-error .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input).ant-select-open .ant-select-selector,.ant-form-item-has-error .ant-select:not(.ant-select-disabled):not(.ant-select-customize-input).ant-select-focused .ant-select-selector{border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-input-group-addon .ant-select.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{background-color:inherit;border:0;box-shadow:none}.ant-form-item-has-error .ant-select.ant-select-auto-complete .ant-input:focus{border-color:#ff4d4f}.ant-form-item-has-error .ant-input-number,.ant-form-item-has-error .ant-picker{background-color:#fff;border-color:#ff4d4f}.ant-form-item-has-error .ant-input-number-focused,.ant-form-item-has-error .ant-picker-focused,.ant-form-item-has-error .ant-input-number:focus,.ant-form-item-has-error .ant-picker:focus{border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-input-number:not([disabled]):hover,.ant-form-item-has-error .ant-picker:not([disabled]):hover{background-color:#fff;border-color:#ff4d4f}.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor,.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor:not([disabled]):hover{background-color:#fff;border-color:#ff4d4f}.ant-form-item-has-error .ant-mention-wrapper.ant-mention-active:not([disabled]) .ant-mention-editor,.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor:not([disabled]):focus{border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-cascader-picker:hover .ant-cascader-picker-label:hover+.ant-cascader-input.ant-input{border-color:#ff4d4f}.ant-form-item-has-error .ant-cascader-picker:focus .ant-cascader-input{background-color:#fff;border-color:#ff7875;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #ff4d4f33}.ant-form-item-has-error .ant-transfer-list{border-color:#ff4d4f}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]){border-color:#d9d9d9}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]):hover{border-color:#40a9ff;border-right-width:1px!important}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]):focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-form-item-has-error .ant-radio-button-wrapper{border-color:#ff4d4f!important}.ant-form-item-has-error .ant-radio-button-wrapper:not(:first-child):before{background-color:#ff4d4f}.ant-form-item-is-validating.ant-form-item-has-feedback .ant-form-item-children-icon{display:inline-block;color:#1890ff}.ant-form{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-form legend{display:block;width:100%;margin-bottom:20px;padding:0;color:#00000073;font-size:16px;line-height:inherit;border:0;border-bottom:1px solid #d9d9d9}.ant-form label{font-size:14px}.ant-form input[type=search]{box-sizing:border-box}.ant-form input[type=radio],.ant-form input[type=checkbox]{line-height:normal}.ant-form input[type=file]{display:block}.ant-form input[type=range]{display:block;width:100%}.ant-form select[multiple],.ant-form select[size]{height:auto}.ant-form input[type=file]:focus,.ant-form input[type=radio]:focus,.ant-form input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.ant-form output{display:block;padding-top:15px;color:#000000d9;font-size:14px;line-height:1.5715}.ant-form .ant-form-text{display:inline-block;padding-right:8px}.ant-form-small .ant-form-item-label>label{height:24px}.ant-form-small .ant-form-item-control-input{min-height:24px}.ant-form-large .ant-form-item-label>label{height:40px}.ant-form-large .ant-form-item-control-input{min-height:40px}.ant-form-item{box-sizing:border-box;margin:0 0 24px;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";vertical-align:top}.ant-form-item-with-help{margin-bottom:0}.ant-form-item-hidden,.ant-form-item-hidden.ant-row{display:none}.ant-form-item-label{display:inline-block;flex-grow:0;overflow:hidden;white-space:nowrap;text-align:right;vertical-align:middle}.ant-form-item-label-left{text-align:left}.ant-form-item-label>label{position:relative;display:inline-flex;align-items:center;height:32px;color:#000000d9;font-size:14px}.ant-form-item-label>label>.anticon{font-size:14px;vertical-align:top}.ant-form-item-label>label.ant-form-item-required:not(.ant-form-item-required-mark-optional):before{display:inline-block;margin-right:4px;color:#ff4d4f;font-size:14px;font-family:SimSun,sans-serif;line-height:1;content:\"*\"}.ant-form-hide-required-mark .ant-form-item-label>label.ant-form-item-required:not(.ant-form-item-required-mark-optional):before{display:none}.ant-form-item-label>label .ant-form-item-optional{display:inline-block;margin-left:4px;color:#00000073}.ant-form-hide-required-mark .ant-form-item-label>label .ant-form-item-optional{display:none}.ant-form-item-label>label .ant-form-item-tooltip{color:#00000073;cursor:help;-ms-writing-mode:lr-tb;writing-mode:horizontal-tb;-webkit-margin-start:4px;margin-inline-start:4px}.ant-form-item-label>label:after{content:\":\";position:relative;top:-.5px;margin:0 8px 0 2px}.ant-form-item-label>label.ant-form-item-no-colon:after{content:\" \"}.ant-form-item-control{display:flex;flex-direction:column;flex-grow:1}.ant-form-item-control:first-child:not([class^=\"ant-col-\"]):not([class*=\" ant-col-\"]){width:100%}.ant-form-item-control-input{position:relative;display:flex;align-items:center;min-height:32px}.ant-form-item-control-input-content{flex:auto;max-width:100%}.ant-form-item-explain,.ant-form-item-extra{clear:both;min-height:24px;color:#00000073;font-size:14px;line-height:1.5715;transition:color .3s cubic-bezier(.215,.61,.355,1)}.ant-form-item .ant-input-textarea-show-count:after{margin-bottom:-22px}.ant-show-help-enter,.ant-show-help-appear,.ant-show-help-leave{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-show-help-enter.ant-show-help-enter-active,.ant-show-help-appear.ant-show-help-appear-active{-webkit-animation-name:antShowHelpIn;animation-name:antShowHelpIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-show-help-leave.ant-show-help-leave-active{-webkit-animation-name:antShowHelpOut;animation-name:antShowHelpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.ant-show-help-enter,.ant-show-help-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-timing-function:cubic-bezier(.645,.045,.355,1)}.ant-show-help-leave{-webkit-animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-timing-function:cubic-bezier(.645,.045,.355,1)}@-webkit-keyframes antShowHelpIn{0%{transform:translateY(-5px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes antShowHelpIn{0%{transform:translateY(-5px);opacity:0}to{transform:translateY(0);opacity:1}}@-webkit-keyframes antShowHelpOut{to{transform:translateY(-5px);opacity:0}}@keyframes antShowHelpOut{to{transform:translateY(-5px);opacity:0}}@-webkit-keyframes diffZoomIn1{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes diffZoomIn1{0%{transform:scale(0)}to{transform:scale(1)}}@-webkit-keyframes diffZoomIn2{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes diffZoomIn2{0%{transform:scale(0)}to{transform:scale(1)}}@-webkit-keyframes diffZoomIn3{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes diffZoomIn3{0%{transform:scale(0)}to{transform:scale(1)}}.ant-form-rtl{direction:rtl}.ant-form-rtl .ant-form-item-label{text-align:left}.ant-form-rtl .ant-form-item-label>label.ant-form-item-required:before{margin-right:0;margin-left:4px}.ant-form-rtl .ant-form-item-label>label:after{margin:0 2px 0 8px}.ant-form-rtl .ant-form-item-label>label .ant-form-item-optional{margin-right:4px;margin-left:0}.ant-col-rtl .ant-form-item-control:first-child{width:100%}.ant-form-rtl .ant-form-item-has-feedback .ant-input{padding-right:11px;padding-left:24px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input-suffix{padding-right:11px;padding-left:18px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input{padding:0}.ant-form-rtl .ant-form-item-has-feedback .ant-input-search:not(.ant-input-search-enter-button) .ant-input-suffix{right:auto;left:28px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-number{padding-left:18px}.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-arrow,.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-clear,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-arrow,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-clear{right:auto;left:32px}.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-selection-selected-value,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection-selected-value{padding-right:0;padding-left:42px}.ant-form-rtl .ant-form-item-has-feedback .ant-cascader-picker-arrow{margin-right:0;margin-left:19px}.ant-form-rtl .ant-form-item-has-feedback .ant-cascader-picker-clear{right:auto;left:32px}.ant-form-rtl .ant-form-item-has-feedback .ant-picker,.ant-form-rtl .ant-form-item-has-feedback .ant-picker-large{padding-right:11px;padding-left:29.2px}.ant-form-rtl .ant-form-item-has-feedback .ant-picker-small{padding-right:7px;padding-left:25.2px}.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-success .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-warning .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-error .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-is-validating .ant-form-item-children-icon{right:auto;left:0}.ant-form-rtl.ant-form-inline .ant-form-item{margin-right:0;margin-left:16px}.ant-image{position:relative;display:inline-block}.ant-image-img{width:100%;height:auto}.ant-image-img-placeholder{background-color:#f5f5f5;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTQuNSAyLjVoLTEzQS41LjUgMCAwIDAgMSAzdjEwYS41LjUgMCAwIDAgLjUuNWgxM2EuNS41IDAgMCAwIC41LS41VjNhLjUuNSAwIDAgMC0uNS0uNXpNNS4yODEgNC43NWExIDEgMCAwIDEgMCAyIDEgMSAwIDAgMSAwLTJ6bTguMDMgNi44M2EuMTI3LjEyNyAwIDAgMS0uMDgxLjAzSDIuNzY5YS4xMjUuMTI1IDAgMCAxLS4wOTYtLjIwN2wyLjY2MS0zLjE1NmEuMTI2LjEyNiAwIDAgMSAuMTc3LS4wMTZsLjAxNi4wMTZMNy4wOCAxMC4wOWwyLjQ3LTIuOTNhLjEyNi4xMjYgMCAwIDEgLjE3Ny0uMDE2bC4wMTUuMDE2IDMuNTg4IDQuMjQ0YS4xMjcuMTI3IDAgMCAxLS4wMi4xNzV6IiBmaWxsPSIjOEM4QzhDIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=);background-repeat:no-repeat;background-position:center center;background-size:30%}.ant-image-placeholder{position:absolute;top:0;right:0;bottom:0;left:0}.ant-image-preview{pointer-events:none;height:100%;text-align:center}.ant-image-preview.zoom-enter,.ant-image-preview.zoom-appear{transform:none;opacity:0;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-image-preview-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;height:100%;background-color:#00000073}.ant-image-preview-mask-hidden{display:none}.ant-image-preview-wrap{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;outline:0;-webkit-overflow-scrolling:touch}.ant-image-preview-body{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden}.ant-image-preview-img{max-width:100%;max-height:100%;vertical-align:middle;transform:scaleZ(1);cursor:-webkit-grab;cursor:grab;transition:transform .3s cubic-bezier(.215,.61,.355,1) 0s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:auto}.ant-image-preview-img-wrapper{position:absolute;top:0;right:0;bottom:0;left:0;transition:transform .3s cubic-bezier(.215,.61,.355,1) 0s}.ant-image-preview-img-wrapper:before{display:inline-block;width:1px;height:50%;margin-right:-1px;content:\"\"}.ant-image-preview-moving .ant-image-preview-img{cursor:-webkit-grabbing;cursor:grabbing}.ant-image-preview-moving .ant-image-preview-img-wrapper{transition-duration:0s}.ant-image-preview-wrap{z-index:1080}.ant-image-preview-operations{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:\"tnum\";position:absolute;top:0;right:0;z-index:1;display:flex;flex-direction:row-reverse;align-items:center;width:100%;color:#ffffffd9;list-style:none;background:rgba(0,0,0,.1);pointer-events:auto}.ant-image-preview-operations-operation{margin-left:12px;padding:12px;cursor:pointer}.ant-image-preview-operations-operation-disabled{color:#ffffff73;pointer-events:none}.ant-image-preview-operations-operation:last-of-type{margin-left:0}.ant-image-preview-operations-icon{font-size:18px}.ant-image-preview-switch-left,.ant-image-preview-switch-right{position:absolute;top:50%;right:10px;z-index:1;display:flex;align-items:center;justify-content:center;width:44px;height:44px;margin-top:-22px;color:#ffffffd9;background:rgba(0,0,0,.1);border-radius:50%;cursor:pointer;pointer-events:auto}.ant-image-preview-switch-left-disabled,.ant-image-preview-switch-right-disabled{color:#ffffff73;cursor:not-allowed}.ant-image-preview-switch-left-disabled>.anticon,.ant-image-preview-switch-right-disabled>.anticon{cursor:not-allowed}.ant-image-preview-switch-left>.anticon,.ant-image-preview-switch-right>.anticon{font-size:18px}.ant-image-preview-switch-left{left:10px}.ant-image-preview-switch-right{right:10px}.ant-input-number{box-sizing:border-box;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";position:relative;width:100%;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;transition:all .3s;display:inline-block;width:90px;margin:0;padding:0;border:1px solid #d9d9d9;border-radius:2px}.ant-input-number::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-input-number:-ms-input-placeholder{color:#bfbfbf}.ant-input-number::-webkit-input-placeholder{color:#bfbfbf}.ant-input-number:-moz-placeholder-shown{text-overflow:ellipsis}.ant-input-number:-ms-input-placeholder{text-overflow:ellipsis}.ant-input-number:placeholder-shown{text-overflow:ellipsis}.ant-input-number:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-input-number[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-number[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input-number{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-number-lg{padding:6.5px 11px;font-size:16px}.ant-input-number-sm{padding:0 7px}.ant-input-number-handler{position:relative;display:block;width:100%;height:50%;overflow:hidden;color:#00000073;font-weight:700;line-height:0;text-align:center;transition:all .1s linear}.ant-input-number-handler:active{background:#f4f4f4}.ant-input-number-handler:hover .ant-input-number-handler-up-inner,.ant-input-number-handler:hover .ant-input-number-handler-down-inner{color:#40a9ff}.ant-input-number-handler-up-inner,.ant-input-number-handler-down-inner{display:inline-block;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;right:4px;width:12px;height:12px;color:#00000073;line-height:12px;transition:all .1s linear;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-input-number-handler-up-inner>*,.ant-input-number-handler-down-inner>*{line-height:1}.ant-input-number-handler-up-inner svg,.ant-input-number-handler-down-inner svg{display:inline-block}.ant-input-number-handler-up-inner:before,.ant-input-number-handler-down-inner:before{display:none}.ant-input-number-handler-up-inner .ant-input-number-handler-up-inner-icon,.ant-input-number-handler-up-inner .ant-input-number-handler-down-inner-icon,.ant-input-number-handler-down-inner .ant-input-number-handler-up-inner-icon,.ant-input-number-handler-down-inner .ant-input-number-handler-down-inner-icon{display:block}.ant-input-number:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-input-number-focused{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-input-number-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-number-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input-number-disabled .ant-input-number-input{cursor:not-allowed}.ant-input-number-disabled .ant-input-number-handler-wrap{display:none}.ant-input-number-input{width:100%;height:30px;padding:0 11px;text-align:left;background-color:transparent;border:0;border-radius:2px;outline:0;transition:all .3s linear;-moz-appearance:textfield!important}.ant-input-number-input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-input-number-input:-ms-input-placeholder{color:#bfbfbf}.ant-input-number-input::-webkit-input-placeholder{color:#bfbfbf}.ant-input-number-input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-input-number-input:-ms-input-placeholder{text-overflow:ellipsis}.ant-input-number-input:placeholder-shown{text-overflow:ellipsis}.ant-input-number-input[type=number]::-webkit-inner-spin-button,.ant-input-number-input[type=number]::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.ant-input-number-lg{padding:0;font-size:16px}.ant-input-number-lg input{height:38px}.ant-input-number-sm{padding:0}.ant-input-number-sm input{height:22px;padding:0 7px}.ant-input-number-handler-wrap{position:absolute;top:0;right:0;width:22px;height:100%;background:#fff;border-left:1px solid #d9d9d9;border-radius:0 2px 2px 0;opacity:0;transition:opacity .24s linear .1s}.ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-up-inner,.ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-down-inner{display:inline-block;font-size:12px;font-size:7px \\\t;transform:scale(.58333333) rotate(0);min-width:auto;margin-right:0}:root .ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-up-inner,:root .ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-down-inner{font-size:12px}.ant-input-number-handler-wrap:hover .ant-input-number-handler{height:40%}.ant-input-number:hover .ant-input-number-handler-wrap{opacity:1}.ant-input-number-handler-up{border-top-right-radius:2px;cursor:pointer}.ant-input-number-handler-up-inner{top:50%;margin-top:-5px;text-align:center}.ant-input-number-handler-up:hover{height:60%!important}.ant-input-number-handler-down{top:0;border-top:1px solid #d9d9d9;border-bottom-right-radius:2px;cursor:pointer}.ant-input-number-handler-down-inner{top:50%;margin-top:-6px;text-align:center}.ant-input-number-handler-down:hover{height:60%!important}.ant-input-number-handler-up-disabled,.ant-input-number-handler-down-disabled{cursor:not-allowed}.ant-input-number-handler-up-disabled:hover .ant-input-number-handler-up-inner,.ant-input-number-handler-down-disabled:hover .ant-input-number-handler-down-inner{color:#00000040}.ant-layout{display:flex;flex:auto;flex-direction:column;min-height:0;background:#f0f2f5}.ant-layout,.ant-layout *{box-sizing:border-box}.ant-layout.ant-layout-has-sider{flex-direction:row}.ant-layout.ant-layout-has-sider>.ant-layout,.ant-layout.ant-layout-has-sider>.ant-layout-content{width:0}.ant-layout-header,.ant-layout-footer{flex:0 0 auto}.ant-layout-header{height:64px;padding:0 50px;color:#000000d9;line-height:64px;background:#001529}.ant-layout-footer{padding:24px 50px;color:#000000d9;font-size:14px;background:#f0f2f5}.ant-layout-content{flex:auto;min-height:0}.ant-layout-sider{position:relative;min-width:0;background:#001529;transition:all .2s}.ant-layout-sider-children{height:100%;margin-top:-.1px;padding-top:.1px}.ant-layout-sider-children .ant-menu.ant-menu-inline-collapsed{width:auto}.ant-layout-sider-has-trigger{padding-bottom:48px}.ant-layout-sider-right{order:1}.ant-layout-sider-trigger{position:fixed;bottom:0;z-index:1;height:48px;color:#fff;line-height:48px;text-align:center;background:#002140;cursor:pointer;transition:all .2s}.ant-layout-sider-zero-width>*{overflow:hidden}.ant-layout-sider-zero-width-trigger{position:absolute;top:64px;right:-36px;z-index:1;width:36px;height:42px;color:#fff;font-size:18px;line-height:42px;text-align:center;background:#001529;border-radius:0 2px 2px 0;cursor:pointer;transition:background .3s ease}.ant-layout-sider-zero-width-trigger:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;transition:all .3s;content:\"\"}.ant-layout-sider-zero-width-trigger:hover:after{background:rgba(255,255,255,.1)}.ant-layout-sider-zero-width-trigger-right{left:-36px;border-radius:2px 0 0 2px}.ant-layout-sider-light{background:#fff}.ant-layout-sider-light .ant-layout-sider-trigger,.ant-layout-sider-light .ant-layout-sider-zero-width-trigger{color:#000000d9;background:#fff}.ant-layout-rtl{direction:rtl}.ant-list{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative}.ant-list *{outline:none}.ant-list-pagination{margin-top:24px;text-align:right}.ant-list-pagination .ant-pagination-options{text-align:left}.ant-list-more{margin-top:12px;text-align:center}.ant-list-more button{padding-right:32px;padding-left:32px}.ant-list-spin{min-height:40px;text-align:center}.ant-list-empty-text{padding:16px;color:#00000040;font-size:14px;text-align:center}.ant-list-items{margin:0;padding:0;list-style:none}.ant-list-item{display:flex;align-items:center;justify-content:space-between;padding:12px 0;color:#000000d9}.ant-list-item-meta{display:flex;flex:1;align-items:flex-start;max-width:100%}.ant-list-item-meta-avatar{margin-right:16px}.ant-list-item-meta-content{flex:1 0;width:0;color:#000000d9}.ant-list-item-meta-title{margin-bottom:4px;color:#000000d9;font-size:14px;line-height:1.5715}.ant-list-item-meta-title>a{color:#000000d9;transition:all .3s}.ant-list-item-meta-title>a:hover{color:#1890ff}.ant-list-item-meta-description{color:#00000073;font-size:14px;line-height:1.5715}.ant-list-item-action{flex:0 0 auto;margin-left:48px;padding:0;font-size:0;list-style:none}.ant-list-item-action>li{position:relative;display:inline-block;padding:0 8px;color:#00000073;font-size:14px;line-height:1.5715;text-align:center}.ant-list-item-action>li:first-child{padding-left:0}.ant-list-item-action-split{position:absolute;top:50%;right:0;width:1px;height:14px;margin-top:-7px;background-color:#f0f0f0}.ant-list-header,.ant-list-footer{background:transparent}.ant-list-header,.ant-list-footer{padding-top:12px;padding-bottom:12px}.ant-list-empty{padding:16px 0;color:#00000073;font-size:12px;text-align:center}.ant-list-split .ant-list-item{border-bottom:1px solid #f0f0f0}.ant-list-split .ant-list-item:last-child{border-bottom:none}.ant-list-split .ant-list-header{border-bottom:1px solid #f0f0f0}.ant-list-split.ant-list-empty .ant-list-footer{border-top:1px solid #f0f0f0}.ant-list-loading .ant-list-spin-nested-loading{min-height:32px}.ant-list-split.ant-list-something-after-last-item .ant-spin-container>.ant-list-items>.ant-list-item:last-child{border-bottom:1px solid #f0f0f0}.ant-list-lg .ant-list-item{padding:16px 24px}.ant-list-sm .ant-list-item{padding:8px 16px}.ant-list-vertical .ant-list-item{align-items:initial}.ant-list-vertical .ant-list-item-main{display:block;flex:1}.ant-list-vertical .ant-list-item-extra{margin-left:40px}.ant-list-vertical .ant-list-item-meta{margin-bottom:16px}.ant-list-vertical .ant-list-item-meta-title{margin-bottom:12px;color:#000000d9;font-size:16px;line-height:24px}.ant-list-vertical .ant-list-item-action{margin-top:16px;margin-left:auto}.ant-list-vertical .ant-list-item-action>li{padding:0 16px}.ant-list-vertical .ant-list-item-action>li:first-child{padding-left:0}.ant-list-grid .ant-col>.ant-list-item{display:block;max-width:100%;margin-bottom:16px;padding-top:0;padding-bottom:0;border-bottom:none}.ant-list-item-no-flex{display:block}.ant-list:not(.ant-list-vertical) .ant-list-item-no-flex .ant-list-item-action{float:right}.ant-list-bordered{border:1px solid #d9d9d9;border-radius:2px}.ant-list-bordered .ant-list-header,.ant-list-bordered .ant-list-footer,.ant-list-bordered .ant-list-item{padding-right:24px;padding-left:24px}.ant-list-bordered .ant-list-pagination{margin:16px 24px}.ant-list-bordered.ant-list-sm .ant-list-item,.ant-list-bordered.ant-list-sm .ant-list-header,.ant-list-bordered.ant-list-sm .ant-list-footer{padding:8px 16px}.ant-list-bordered.ant-list-lg .ant-list-item,.ant-list-bordered.ant-list-lg .ant-list-header,.ant-list-bordered.ant-list-lg .ant-list-footer{padding:16px 24px}@media screen and (max-width: 768px){.ant-list-item-action,.ant-list-vertical .ant-list-item-extra{margin-left:24px}}@media screen and (max-width: 576px){.ant-list-item{flex-wrap:wrap}.ant-list-item-action{margin-left:12px}.ant-list-vertical .ant-list-item{flex-wrap:wrap-reverse}.ant-list-vertical .ant-list-item-main{min-width:220px}.ant-list-vertical .ant-list-item-extra{margin:auto auto 16px}}.ant-list-rtl{direction:rtl;text-align:right}.ant-list-rtl .ReactVirtualized__List .ant-list-item{direction:rtl}.ant-list-rtl .ant-list-pagination{text-align:left}.ant-list-rtl .ant-list-item-meta-avatar{margin-right:0;margin-left:16px}.ant-list-rtl .ant-list-item-action{margin-right:48px;margin-left:0}.ant-list.ant-list-rtl .ant-list-item-action>li:first-child{padding-right:0;padding-left:16px}.ant-list-rtl .ant-list-item-action-split{right:auto;left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-extra{margin-right:40px;margin-left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-action{margin-right:auto}.ant-list-rtl .ant-list-vertical .ant-list-item-action>li:first-child{padding-right:0;padding-left:16px}.ant-list-rtl .ant-list:not(.ant-list-vertical) .ant-list-item-no-flex .ant-list-item-action{float:left}@media screen and (max-width: 768px){.ant-list-rtl .ant-list-item-action,.ant-list-rtl .ant-list-vertical .ant-list-item-extra{margin-right:24px;margin-left:0}}@media screen and (max-width: 576px){.ant-list-rtl .ant-list-item-action{margin-right:22px;margin-left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-extra{margin:auto auto 16px}}.ant-spin{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;display:none;color:#1890ff;text-align:center;vertical-align:middle;opacity:0;transition:transform .3s cubic-bezier(.78,.14,.15,.86)}.ant-spin-spinning{position:static;display:inline-block;opacity:1}.ant-spin-nested-loading{position:relative}.ant-spin-nested-loading>div>.ant-spin{position:absolute;top:0;left:0;z-index:4;display:block;width:100%;height:100%;max-height:400px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-dot{position:absolute;top:50%;left:50%;margin:-10px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-text{position:absolute;top:50%;width:100%;padding-top:5px;text-shadow:0 1px 2px #fff}.ant-spin-nested-loading>div>.ant-spin.ant-spin-show-text .ant-spin-dot{margin-top:-20px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-dot{margin:-7px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-text{padding-top:2px}.ant-spin-nested-loading>div>.ant-spin-sm.ant-spin-show-text .ant-spin-dot{margin-top:-17px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-dot{margin:-16px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-text{padding-top:11px}.ant-spin-nested-loading>div>.ant-spin-lg.ant-spin-show-text .ant-spin-dot{margin-top:-26px}.ant-spin-container{position:relative;transition:opacity .3s}.ant-spin-container:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;display:none \\\t;width:100%;height:100%;background:#fff;opacity:0;transition:all .3s;content:\"\";pointer-events:none}.ant-spin-blur{clear:both;overflow:hidden;opacity:.5;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.ant-spin-blur:after{opacity:.4;pointer-events:auto}.ant-spin-tip{color:#00000073}.ant-spin-dot{position:relative;display:inline-block;font-size:20px;width:1em;height:1em}.ant-spin-dot-item{position:absolute;display:block;width:9px;height:9px;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;-webkit-animation:antSpinMove 1s infinite linear alternate;animation:antSpinMove 1s infinite linear alternate}.ant-spin-dot-item:nth-child(1){top:0;left:0}.ant-spin-dot-item:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.ant-spin-dot-item:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.ant-spin-dot-item:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}.ant-spin-dot-spin{transform:rotate(45deg);-webkit-animation:antRotate 1.2s infinite linear;animation:antRotate 1.2s infinite linear}.ant-spin-sm .ant-spin-dot{font-size:14px}.ant-spin-sm .ant-spin-dot i{width:6px;height:6px}.ant-spin-lg .ant-spin-dot{font-size:32px}.ant-spin-lg .ant-spin-dot i{width:14px;height:14px}.ant-spin.ant-spin-show-text .ant-spin-text{display:block}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.ant-spin-blur{background:#fff;opacity:.5}}@-webkit-keyframes antSpinMove{to{opacity:1}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antRotate{to{transform:rotate(405deg)}}@keyframes antRotate{to{transform:rotate(405deg)}}.ant-spin-rtl{direction:rtl}.ant-spin-rtl .ant-spin-dot-spin{transform:rotate(-45deg);-webkit-animation-name:antRotateRtl;animation-name:antRotateRtl}@-webkit-keyframes antRotateRtl{to{transform:rotate(-405deg)}}@keyframes antRotateRtl{to{transform:rotate(-405deg)}}.ant-pagination{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-pagination ul,.ant-pagination ol{margin:0;padding:0;list-style:none}.ant-pagination:after{display:block;clear:both;height:0;overflow:hidden;visibility:hidden;content:\" \"}.ant-pagination-total-text{display:inline-block;height:32px;margin-right:8px;line-height:30px;vertical-align:middle}.ant-pagination-item{display:inline-block;min-width:32px;height:32px;margin-right:8px;font-family:Arial;line-height:30px;text-align:center;vertical-align:middle;list-style:none;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;outline:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-pagination-item a{display:block;padding:0 6px;color:#000000d9;transition:none}.ant-pagination-item a:hover{text-decoration:none}.ant-pagination-item:focus,.ant-pagination-item:hover{border-color:#1890ff;transition:all .3s}.ant-pagination-item:focus a,.ant-pagination-item:hover a{color:#1890ff}.ant-pagination-item-active{font-weight:500;background:#fff;border-color:#1890ff}.ant-pagination-item-active a{color:#1890ff}.ant-pagination-item-active:focus,.ant-pagination-item-active:hover{border-color:#40a9ff}.ant-pagination-item-active:focus a,.ant-pagination-item-active:hover a{color:#40a9ff}.ant-pagination-jump-prev,.ant-pagination-jump-next{outline:0}.ant-pagination-jump-prev .ant-pagination-item-container,.ant-pagination-jump-next .ant-pagination-item-container{position:relative}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-link-icon,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-link-icon{display:inline-block;font-size:12px;font-size:12px \\\t;transform:scale(1) rotate(0);color:#1890ff;letter-spacing:-1px;opacity:0;transition:all .2s}:root .ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-link-icon,:root .ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-link-icon{font-size:12px}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-link-icon-svg,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-link-icon-svg{top:0;right:0;bottom:0;left:0;margin:auto}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-ellipsis,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-ellipsis{position:absolute;top:0;right:0;bottom:0;left:0;display:block;margin:auto;color:#00000040;letter-spacing:2px;text-align:center;text-indent:.13em;opacity:1;transition:all .2s}.ant-pagination-jump-prev:focus .ant-pagination-item-link-icon,.ant-pagination-jump-next:focus .ant-pagination-item-link-icon,.ant-pagination-jump-prev:hover .ant-pagination-item-link-icon,.ant-pagination-jump-next:hover .ant-pagination-item-link-icon{opacity:1}.ant-pagination-jump-prev:focus .ant-pagination-item-ellipsis,.ant-pagination-jump-next:focus .ant-pagination-item-ellipsis,.ant-pagination-jump-prev:hover .ant-pagination-item-ellipsis,.ant-pagination-jump-next:hover .ant-pagination-item-ellipsis{opacity:0}.ant-pagination-prev,.ant-pagination-jump-prev,.ant-pagination-jump-next{margin-right:8px}.ant-pagination-prev,.ant-pagination-next,.ant-pagination-jump-prev,.ant-pagination-jump-next{display:inline-block;min-width:32px;height:32px;color:#000000d9;font-family:Arial;line-height:32px;text-align:center;vertical-align:middle;list-style:none;border-radius:2px;cursor:pointer;transition:all .3s}.ant-pagination-prev,.ant-pagination-next{outline:0}.ant-pagination-prev a,.ant-pagination-next a{color:#000000d9;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-pagination-prev:hover a,.ant-pagination-next:hover a{border-color:#40a9ff}.ant-pagination-prev .ant-pagination-item-link,.ant-pagination-next .ant-pagination-item-link{display:block;height:100%;font-size:12px;text-align:center;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;outline:none;transition:all .3s}.ant-pagination-prev:focus .ant-pagination-item-link,.ant-pagination-next:focus .ant-pagination-item-link,.ant-pagination-prev:hover .ant-pagination-item-link,.ant-pagination-next:hover .ant-pagination-item-link{color:#1890ff;border-color:#1890ff}.ant-pagination-disabled,.ant-pagination-disabled:hover,.ant-pagination-disabled:focus{cursor:not-allowed}.ant-pagination-disabled a,.ant-pagination-disabled:hover a,.ant-pagination-disabled:focus a,.ant-pagination-disabled .ant-pagination-item-link,.ant-pagination-disabled:hover .ant-pagination-item-link,.ant-pagination-disabled:focus .ant-pagination-item-link{color:#00000040;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination-slash{margin:0 10px 0 5px}.ant-pagination-options{display:inline-block;margin-left:16px;vertical-align:middle}.ant-pagination-options-size-changer.ant-select{display:inline-block;width:auto;margin-right:8px}.ant-pagination-options-quick-jumper{display:inline-block;height:32px;line-height:32px;vertical-align:top}.ant-pagination-options-quick-jumper input{position:relative;display:inline-block;width:100%;padding:4px 11px;color:#000000d9;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s;width:50px;margin:0 8px}.ant-pagination-options-quick-jumper input::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-pagination-options-quick-jumper input:-ms-input-placeholder{color:#bfbfbf}.ant-pagination-options-quick-jumper input::-webkit-input-placeholder{color:#bfbfbf}.ant-pagination-options-quick-jumper input:-moz-placeholder-shown{text-overflow:ellipsis}.ant-pagination-options-quick-jumper input:-ms-input-placeholder{text-overflow:ellipsis}.ant-pagination-options-quick-jumper input:placeholder-shown{text-overflow:ellipsis}.ant-pagination-options-quick-jumper input:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-pagination-options-quick-jumper input:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-pagination-options-quick-jumper input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-pagination-options-quick-jumper input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-pagination-options-quick-jumper input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-pagination-options-quick-jumper input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-pagination-options-quick-jumper input{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-pagination-options-quick-jumper input-lg{padding:6.5px 11px;font-size:16px}.ant-pagination-options-quick-jumper input-sm{padding:0 7px}.ant-pagination-simple .ant-pagination-prev,.ant-pagination-simple .ant-pagination-next{height:24px;line-height:24px;vertical-align:top}.ant-pagination-simple .ant-pagination-prev .ant-pagination-item-link,.ant-pagination-simple .ant-pagination-next .ant-pagination-item-link{height:24px;border:0}.ant-pagination-simple .ant-pagination-prev .ant-pagination-item-link:after,.ant-pagination-simple .ant-pagination-next .ant-pagination-item-link:after{height:24px;line-height:24px}.ant-pagination-simple .ant-pagination-simple-pager{display:inline-block;height:24px;margin-right:8px}.ant-pagination-simple .ant-pagination-simple-pager input{box-sizing:border-box;height:100%;margin-right:8px;padding:0 6px;text-align:center;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;outline:none;transition:border-color .3s}.ant-pagination-simple .ant-pagination-simple-pager input:hover{border-color:#1890ff}.ant-pagination.mini .ant-pagination-total-text,.ant-pagination.mini .ant-pagination-simple-pager{height:24px;line-height:24px}.ant-pagination.mini .ant-pagination-item{min-width:24px;height:24px;margin:0;line-height:22px}.ant-pagination.mini .ant-pagination-item:not(.ant-pagination-item-active){background:transparent;border-color:transparent}.ant-pagination.mini .ant-pagination-prev,.ant-pagination.mini .ant-pagination-next{min-width:24px;height:24px;margin:0;line-height:24px}.ant-pagination.mini .ant-pagination-prev .ant-pagination-item-link,.ant-pagination.mini .ant-pagination-next .ant-pagination-item-link{background:transparent;border-color:transparent}.ant-pagination.mini .ant-pagination-prev .ant-pagination-item-link:after,.ant-pagination.mini .ant-pagination-next .ant-pagination-item-link:after{height:24px;line-height:24px}.ant-pagination.mini .ant-pagination-jump-prev,.ant-pagination.mini .ant-pagination-jump-next{height:24px;margin-right:0;line-height:24px}.ant-pagination.mini .ant-pagination-options{margin-left:2px}.ant-pagination.mini .ant-pagination-options-quick-jumper{height:24px;line-height:24px}.ant-pagination.mini .ant-pagination-options-quick-jumper input{padding:0 7px;width:44px}.ant-pagination.ant-pagination-disabled{cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item{background:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item a{color:#00000040;background:transparent;border:none;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item-active{background:#dbdbdb;border-color:transparent}.ant-pagination.ant-pagination-disabled .ant-pagination-item-active a{color:#fff}.ant-pagination.ant-pagination-disabled .ant-pagination-item-link,.ant-pagination.ant-pagination-disabled .ant-pagination-item-link:hover,.ant-pagination.ant-pagination-disabled .ant-pagination-item-link:focus{color:#00000073;background:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:focus .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:focus .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:hover .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:hover .ant-pagination-item-link-icon{opacity:0}.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:focus .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:focus .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:hover .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:hover .ant-pagination-item-ellipsis{opacity:1}@media only screen and (max-width: 992px){.ant-pagination-item-after-jump-prev,.ant-pagination-item-before-jump-next{display:none}}@media only screen and (max-width: 576px){.ant-pagination-options{display:none}}.ant-mentions{box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";width:100%;color:#000000d9;font-size:14px;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:2px;transition:all .3s;position:relative;display:inline-block;height:auto;padding:0;overflow:hidden;line-height:1.5715;white-space:pre-wrap;vertical-align:bottom}.ant-mentions::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-mentions:-ms-input-placeholder{color:#bfbfbf}.ant-mentions::-webkit-input-placeholder{color:#bfbfbf}.ant-mentions:-moz-placeholder-shown{text-overflow:ellipsis}.ant-mentions:-ms-input-placeholder{text-overflow:ellipsis}.ant-mentions:placeholder-shown{text-overflow:ellipsis}.ant-mentions:hover{border-color:#40a9ff;border-right-width:1px!important}.ant-mentions:focus{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-mentions-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-mentions[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-mentions{max-width:100%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-mentions-lg{padding:6.5px 11px;font-size:16px}.ant-mentions-sm{padding:0 7px}.ant-mentions-disabled>textarea{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions-disabled>textarea:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-mentions-focused{border-color:#40a9ff;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-mentions>textarea,.ant-mentions-measure{min-height:30px;margin:0;padding:4px 11px;overflow:inherit;overflow-x:hidden;overflow-y:auto;font-weight:inherit;font-size:inherit;font-family:inherit;font-style:inherit;font-variant:inherit;font-size-adjust:inherit;font-stretch:inherit;line-height:inherit;direction:inherit;letter-spacing:inherit;white-space:inherit;text-align:inherit;vertical-align:top;word-wrap:break-word;word-break:inherit;-moz-tab-size:inherit;-o-tab-size:inherit;tab-size:inherit}.ant-mentions>textarea{width:100%;border:none;outline:none;resize:none}.ant-mentions>textarea::-moz-placeholder{color:#bfbfbf;opacity:1}.ant-mentions>textarea:-ms-input-placeholder{color:#bfbfbf}.ant-mentions>textarea::-webkit-input-placeholder{color:#bfbfbf}.ant-mentions>textarea:-moz-placeholder-shown{text-overflow:ellipsis}.ant-mentions>textarea:-ms-input-placeholder{text-overflow:ellipsis}.ant-mentions>textarea:placeholder-shown{text-overflow:ellipsis}.ant-mentions>textarea:-moz-read-only{cursor:default}.ant-mentions>textarea:read-only{cursor:default}.ant-mentions-measure{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;color:transparent;pointer-events:none}.ant-mentions-measure>span{display:inline-block;min-height:1em}.ant-mentions-dropdown{margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;top:-9999px;left:-9999px;z-index:1050;box-sizing:border-box;font-size:14px;font-variant:initial;background-color:#fff;border-radius:2px;outline:none;box-shadow:0 2px 8px #00000026}.ant-mentions-dropdown-hidden{display:none}.ant-mentions-dropdown-menu{max-height:250px;margin-bottom:0;padding-left:0;overflow:auto;list-style:none;outline:none}.ant-mentions-dropdown-menu-item{position:relative;display:block;min-width:100px;padding:5px 12px;overflow:hidden;color:#000000d9;font-weight:400;line-height:22px;white-space:nowrap;text-overflow:ellipsis;cursor:pointer;transition:background .3s ease}.ant-mentions-dropdown-menu-item:hover{background-color:#f5f5f5}.ant-mentions-dropdown-menu-item:first-child{border-radius:2px 2px 0 0}.ant-mentions-dropdown-menu-item:last-child{border-radius:0 0 2px 2px}.ant-mentions-dropdown-menu-item-disabled{color:#00000040;cursor:not-allowed}.ant-mentions-dropdown-menu-item-disabled:hover{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-mentions-dropdown-menu-item-selected{color:#000000d9;font-weight:600;background-color:#fafafa}.ant-mentions-dropdown-menu-item-active{background-color:#e6f7ff}.ant-message{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:fixed;top:16px;left:0;z-index:1010;width:100%;pointer-events:none}.ant-message-notice{padding:8px;text-align:center}.ant-message-notice:first-child{margin-top:-8px}.ant-message-notice-content{display:inline-block;padding:10px 16px;background:#fff;border-radius:2px;box-shadow:0 4px 12px #00000026;pointer-events:all}.ant-message-success .anticon{color:#52c41a}.ant-message-error .anticon{color:#ff4d4f}.ant-message-warning .anticon{color:#faad14}.ant-message-info .anticon,.ant-message-loading .anticon{color:#1890ff}.ant-message .anticon{position:relative;top:1px;margin-right:8px;font-size:16px}.ant-message-notice.move-up-leave.move-up-leave-active{overflow:hidden;-webkit-animation-name:MessageMoveOut;animation-name:MessageMoveOut;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}@keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}.ant-modal{box-sizing:border-box;padding:0 0 24px;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;top:100px;width:auto;margin:0 auto;pointer-events:none}.ant-modal-wrap{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;outline:0;-webkit-overflow-scrolling:touch}.ant-modal-title{margin:0;color:#000000d9;font-weight:500;font-size:16px;line-height:22px;word-wrap:break-word}.ant-modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:0;border-radius:2px;box-shadow:0 4px 12px #00000026;pointer-events:auto}.ant-modal-close{position:absolute;top:0;right:0;z-index:10;padding:0;color:#00000073;font-weight:700;line-height:1;text-decoration:none;background:transparent;border:0;outline:0;cursor:pointer;transition:color .3s}.ant-modal-close-x{display:block;width:56px;height:56px;font-size:16px;font-style:normal;line-height:56px;text-align:center;text-transform:none;text-rendering:auto}.ant-modal-close:focus,.ant-modal-close:hover{color:#000000bf;text-decoration:none}.ant-modal-header{padding:16px 24px;color:#000000d9;background:#fff;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-modal-body{padding:24px;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-modal-footer{padding:10px 16px;text-align:right;background:transparent;border-top:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-modal-footer button+button{margin-bottom:0;margin-left:8px}.ant-modal.zoom-enter,.ant-modal.zoom-appear{transform:none;opacity:0;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-modal-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;height:100%;background-color:#00000073;filter:alpha(opacity=50)}.ant-modal-mask-hidden{display:none}.ant-modal-open{overflow:hidden}.ant-modal-centered{text-align:center}.ant-modal-centered:before{display:inline-block;width:0;height:100%;vertical-align:middle;content:\"\"}.ant-modal-centered .ant-modal{top:0;display:inline-block;text-align:left;vertical-align:middle}@media (max-width: 767px){.ant-modal{max-width:calc(100vw - 16px);margin:8px auto}.ant-modal-centered .ant-modal{flex:1}}.ant-modal-confirm .ant-modal-header{display:none}.ant-modal-confirm .ant-modal-body{padding:32px 32px 24px}.ant-modal-confirm-body-wrapper:before,.ant-modal-confirm-body-wrapper:after{display:table;content:\"\"}.ant-modal-confirm-body-wrapper:after{clear:both}.ant-modal-confirm-body .ant-modal-confirm-title{display:block;overflow:hidden;color:#000000d9;font-weight:500;font-size:16px;line-height:1.4}.ant-modal-confirm-body .ant-modal-confirm-content{margin-top:8px;color:#000000d9;font-size:14px}.ant-modal-confirm-body>.anticon{float:left;margin-right:16px;font-size:22px}.ant-modal-confirm-body>.anticon+.ant-modal-confirm-title+.ant-modal-confirm-content{margin-left:38px}.ant-modal-confirm .ant-modal-confirm-btns{float:right;margin-top:24px}.ant-modal-confirm .ant-modal-confirm-btns button+button{margin-bottom:0;margin-left:8px}.ant-modal-confirm-error .ant-modal-confirm-body>.anticon{color:#ff4d4f}.ant-modal-confirm-warning .ant-modal-confirm-body>.anticon,.ant-modal-confirm-confirm .ant-modal-confirm-body>.anticon{color:#faad14}.ant-modal-confirm-info .ant-modal-confirm-body>.anticon{color:#1890ff}.ant-modal-confirm-success .ant-modal-confirm-body>.anticon{color:#52c41a}.ant-notification{box-sizing:border-box;margin:0 24px 0 0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:fixed;z-index:1010;width:384px;max-width:calc(100vw - 32px)}.ant-notification-topLeft,.ant-notification-bottomLeft{margin-right:0;margin-left:24px}.ant-notification-topLeft .ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-bottomLeft .ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-topLeft .ant-notification-fade-appear.ant-notification-fade-appear-active,.ant-notification-bottomLeft .ant-notification-fade-appear.ant-notification-fade-appear-active{-webkit-animation-name:NotificationLeftFadeIn;animation-name:NotificationLeftFadeIn}.ant-notification-close-icon{font-size:14px;cursor:pointer}.ant-notification-notice{position:relative;margin-bottom:16px;padding:16px 24px;overflow:hidden;line-height:1.5;background:#fff;border-radius:2px;box-shadow:0 4px 12px #00000026}.ant-notification-notice-message{display:inline-block;margin-bottom:8px;color:#000000d9;font-size:16px;line-height:24px}.ant-notification-notice-message-single-line-auto-margin{display:block;width:calc(264px - 100%);max-width:4px;background-color:transparent;pointer-events:none}.ant-notification-notice-message-single-line-auto-margin:before{display:block;content:\"\"}.ant-notification-notice-description{font-size:14px}.ant-notification-notice-closable .ant-notification-notice-message{padding-right:24px}.ant-notification-notice-with-icon .ant-notification-notice-message{margin-bottom:4px;margin-left:48px;font-size:16px}.ant-notification-notice-with-icon .ant-notification-notice-description{margin-left:48px;font-size:14px}.ant-notification-notice-icon{position:absolute;margin-left:4px;font-size:24px;line-height:24px}.anticon.ant-notification-notice-icon-success{color:#52c41a}.anticon.ant-notification-notice-icon-info{color:#1890ff}.anticon.ant-notification-notice-icon-warning{color:#faad14}.anticon.ant-notification-notice-icon-error{color:#ff4d4f}.ant-notification-notice-close{position:absolute;top:16px;right:22px;color:#00000073;outline:none}.ant-notification-notice-close:hover{color:#000000ab}.ant-notification-notice-btn{float:right;margin-top:16px}.ant-notification .notification-fade-effect{-webkit-animation-duration:.24s;animation-duration:.24s;-webkit-animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-timing-function:cubic-bezier(.645,.045,.355,1);-webkit-animation-fill-mode:both;animation-fill-mode:both}.ant-notification-fade-enter,.ant-notification-fade-appear{opacity:0;-webkit-animation-duration:.24s;animation-duration:.24s;-webkit-animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-timing-function:cubic-bezier(.645,.045,.355,1);-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-notification-fade-leave{-webkit-animation-duration:.24s;animation-duration:.24s;-webkit-animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-timing-function:cubic-bezier(.645,.045,.355,1);-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-play-state:paused;animation-play-state:paused}.ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-fade-appear.ant-notification-fade-appear-active{-webkit-animation-name:NotificationFadeIn;animation-name:NotificationFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.ant-notification-fade-leave.ant-notification-fade-leave-active{-webkit-animation-name:NotificationFadeOut;animation-name:NotificationFadeOut;-webkit-animation-play-state:running;animation-play-state:running}@-webkit-keyframes NotificationFadeIn{0%{left:384px;opacity:0}to{left:0;opacity:1}}@keyframes NotificationFadeIn{0%{left:384px;opacity:0}to{left:0;opacity:1}}@-webkit-keyframes NotificationLeftFadeIn{0%{right:384px;opacity:0}to{right:0;opacity:1}}@keyframes NotificationLeftFadeIn{0%{right:384px;opacity:0}to{right:0;opacity:1}}@-webkit-keyframes NotificationFadeOut{0%{max-height:150px;margin-bottom:16px;padding-top:16px 24px;padding-bottom:16px 24px;opacity:1}to{max-height:0;margin-bottom:0;padding-top:0;padding-bottom:0;opacity:0}}@keyframes NotificationFadeOut{0%{max-height:150px;margin-bottom:16px;padding-top:16px 24px;padding-bottom:16px 24px;opacity:1}to{max-height:0;margin-bottom:0;padding-top:0;padding-bottom:0;opacity:0}}.ant-page-header{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;padding:16px 24px;background-color:#fff}.ant-page-header-ghost{background-color:inherit}.ant-page-header.has-breadcrumb{padding-top:12px}.ant-page-header.has-footer{padding-bottom:0}.ant-page-header-back{margin-right:16px;font-size:16px;line-height:1}.ant-page-header-back-button{color:#1890ff;text-decoration:none;outline:none;transition:color .3s;color:#000;cursor:pointer}.ant-page-header-back-button:focus,.ant-page-header-back-button:hover{color:#40a9ff}.ant-page-header-back-button:active{color:#096dd9}.ant-page-header .ant-divider-vertical{height:14px;margin:0 12px;vertical-align:middle}.ant-breadcrumb+.ant-page-header-heading{margin-top:8px}.ant-page-header-heading{display:flex;justify-content:space-between}.ant-page-header-heading-left{display:flex;align-items:center;margin:4px 0;overflow:hidden}.ant-page-header-heading-title{margin-right:12px;margin-bottom:0;color:#000000d9;font-weight:600;font-size:20px;line-height:32px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-page-header-heading .ant-avatar{margin-right:12px}.ant-page-header-heading-sub-title{margin-right:12px;color:#00000073;font-size:14px;line-height:1.5715;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-page-header-heading-extra{margin:4px 0;white-space:nowrap}.ant-page-header-heading-extra>*{margin-left:12px;white-space:unset}.ant-page-header-heading-extra>*:first-child{margin-left:0}.ant-page-header-content{padding-top:12px}.ant-page-header-footer{margin-top:16px}.ant-page-header-footer .ant-tabs>.ant-tabs-nav{margin:0}.ant-page-header-footer .ant-tabs>.ant-tabs-nav:before{border:none}.ant-page-header-footer .ant-tabs .ant-tabs-tab{padding-top:8px;padding-bottom:8px;font-size:16px}.ant-page-header-compact .ant-page-header-heading{flex-wrap:wrap}.ant-page-header-rtl{direction:rtl}.ant-page-header-rtl .ant-page-header-back{float:right;margin-right:0;margin-left:16px}.ant-page-header-rtl .ant-page-header-heading-title,.ant-page-header-rtl .ant-page-header-heading .ant-avatar{margin-right:0;margin-left:12px}.ant-page-header-rtl .ant-page-header-heading-sub-title{float:right;margin-right:0;margin-left:12px}.ant-page-header-rtl .ant-page-header-heading-tags{float:right}.ant-page-header-rtl .ant-page-header-heading-extra{float:left}.ant-page-header-rtl .ant-page-header-heading-extra>*{margin-right:12px;margin-left:0}.ant-page-header-rtl .ant-page-header-heading-extra>*:first-child{margin-right:0}.ant-page-header-rtl .ant-page-header-footer .ant-tabs-bar .ant-tabs-nav{float:right}.ant-popover{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:absolute;top:0;left:0;z-index:1030;font-weight:400;white-space:normal;text-align:left;cursor:auto;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ant-popover:after{position:absolute;background:rgba(255,255,255,.01);content:\"\"}.ant-popover-hidden{display:none}.ant-popover-placement-top,.ant-popover-placement-topLeft,.ant-popover-placement-topRight{padding-bottom:10px}.ant-popover-placement-right,.ant-popover-placement-rightTop,.ant-popover-placement-rightBottom{padding-left:10px}.ant-popover-placement-bottom,.ant-popover-placement-bottomLeft,.ant-popover-placement-bottomRight{padding-top:10px}.ant-popover-placement-left,.ant-popover-placement-leftTop,.ant-popover-placement-leftBottom{padding-right:10px}.ant-popover-inner{background-color:#fff;background-clip:padding-box;border-radius:2px;box-shadow:0 2px 8px #00000026;box-shadow:0 0 8px #00000026 \\\t}@media screen and (-ms-high-contrast: active),(-ms-high-contrast: none){.ant-popover-inner{box-shadow:0 2px 8px #00000026}}.ant-popover-title{min-width:177px;min-height:32px;margin:0;padding:5px 16px 4px;color:#000000d9;font-weight:500;border-bottom:1px solid #f0f0f0}.ant-popover-inner-content{padding:12px 16px;color:#000000d9}.ant-popover-message{position:relative;padding:4px 0 12px;color:#000000d9;font-size:14px}.ant-popover-message>.anticon{position:absolute;top:8px;color:#faad14;font-size:14px}.ant-popover-message-title{padding-left:22px}.ant-popover-buttons{margin-bottom:4px;text-align:right}.ant-popover-buttons button{margin-left:8px}.ant-popover-arrow{position:absolute;display:block;width:8.48528137px;height:8.48528137px;background:transparent;border-style:solid;border-width:4.24264069px;transform:rotate(45deg)}.ant-popover-placement-top>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-topLeft>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-topRight>.ant-popover-content>.ant-popover-arrow{bottom:6.2px;border-top-color:transparent;border-right-color:#fff;border-bottom-color:#fff;border-left-color:transparent;box-shadow:3px 3px 7px #00000012}.ant-popover-placement-top>.ant-popover-content>.ant-popover-arrow{left:50%;transform:translate(-50%) rotate(45deg)}.ant-popover-placement-topLeft>.ant-popover-content>.ant-popover-arrow{left:16px}.ant-popover-placement-topRight>.ant-popover-content>.ant-popover-arrow{right:16px}.ant-popover-placement-right>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-rightTop>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-rightBottom>.ant-popover-content>.ant-popover-arrow{left:6px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:#fff;border-left-color:#fff;box-shadow:-3px 3px 7px #00000012}.ant-popover-placement-right>.ant-popover-content>.ant-popover-arrow{top:50%;transform:translateY(-50%) rotate(45deg)}.ant-popover-placement-rightTop>.ant-popover-content>.ant-popover-arrow{top:12px}.ant-popover-placement-rightBottom>.ant-popover-content>.ant-popover-arrow{bottom:12px}.ant-popover-placement-bottom>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-bottomLeft>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-bottomRight>.ant-popover-content>.ant-popover-arrow{top:6px;border-top-color:#fff;border-right-color:transparent;border-bottom-color:transparent;border-left-color:#fff;box-shadow:-2px -2px 5px #0000000f}.ant-popover-placement-bottom>.ant-popover-content>.ant-popover-arrow{left:50%;transform:translate(-50%) rotate(45deg)}.ant-popover-placement-bottomLeft>.ant-popover-content>.ant-popover-arrow{left:16px}.ant-popover-placement-bottomRight>.ant-popover-content>.ant-popover-arrow{right:16px}.ant-popover-placement-left>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-leftTop>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-leftBottom>.ant-popover-content>.ant-popover-arrow{right:6px;border-top-color:#fff;border-right-color:#fff;border-bottom-color:transparent;border-left-color:transparent;box-shadow:3px -3px 7px #00000012}.ant-popover-placement-left>.ant-popover-content>.ant-popover-arrow{top:50%;transform:translateY(-50%) rotate(45deg)}.ant-popover-placement-leftTop>.ant-popover-content>.ant-popover-arrow{top:12px}.ant-popover-placement-leftBottom>.ant-popover-content>.ant-popover-arrow{bottom:12px}.ant-progress{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block}.ant-progress-line{position:relative;width:100%;font-size:14px}.ant-progress-small.ant-progress-line,.ant-progress-small.ant-progress-line .ant-progress-text .anticon{font-size:12px}.ant-progress-outer{display:inline-block;width:100%;margin-right:0;padding-right:0}.ant-progress-show-info .ant-progress-outer{margin-right:calc(-2em - 8px);padding-right:calc(2em + 8px)}.ant-progress-inner{position:relative;display:inline-block;width:100%;overflow:hidden;vertical-align:middle;background-color:#f5f5f5;border-radius:100px}.ant-progress-circle-trail{stroke:#f5f5f5}.ant-progress-circle-path{-webkit-animation:ant-progress-appear .3s;animation:ant-progress-appear .3s}.ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#1890ff}.ant-progress-success-bg,.ant-progress-bg{position:relative;background-color:#1890ff;border-radius:100px;transition:all .4s cubic-bezier(.08,.82,.17,1) 0s}.ant-progress-success-bg{position:absolute;top:0;left:0;background-color:#52c41a}.ant-progress-text{display:inline-block;width:2em;margin-left:8px;color:#00000073;font-size:1em;line-height:1;white-space:nowrap;text-align:left;vertical-align:middle;word-break:normal}.ant-progress-text .anticon{font-size:14px}.ant-progress-status-active .ant-progress-bg:before{position:absolute;top:0;right:0;bottom:0;left:0;background:#fff;border-radius:10px;opacity:0;-webkit-animation:ant-progress-active 2.4s cubic-bezier(.23,1,.32,1) infinite;animation:ant-progress-active 2.4s cubic-bezier(.23,1,.32,1) infinite;content:\"\"}.ant-progress-status-exception .ant-progress-bg{background-color:#ff4d4f}.ant-progress-status-exception .ant-progress-text{color:#ff4d4f}.ant-progress-status-exception .ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#ff4d4f}.ant-progress-status-success .ant-progress-bg{background-color:#52c41a}.ant-progress-status-success .ant-progress-text{color:#52c41a}.ant-progress-status-success .ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#52c41a}.ant-progress-circle .ant-progress-inner{position:relative;line-height:1;background-color:transparent}.ant-progress-circle .ant-progress-text{position:absolute;top:50%;left:50%;width:100%;margin:0;padding:0;color:#000000d9;line-height:1;white-space:normal;text-align:center;transform:translate(-50%,-50%)}.ant-progress-circle .ant-progress-text .anticon{font-size:1.16666667em}.ant-progress-circle.ant-progress-status-exception .ant-progress-text{color:#ff4d4f}.ant-progress-circle.ant-progress-status-success .ant-progress-text{color:#52c41a}@-webkit-keyframes ant-progress-active{0%{width:0;opacity:.1}20%{width:0;opacity:.5}to{width:100%;opacity:0}}@keyframes ant-progress-active{0%{width:0;opacity:.1}20%{width:0;opacity:.5}to{width:100%;opacity:0}}.ant-rate{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:\"tnum\";display:inline-block;margin:0;padding:0;color:#fadb14;font-size:20px;line-height:unset;list-style:none;outline:none}.ant-rate-disabled .ant-rate-star{cursor:default}.ant-rate-disabled .ant-rate-star:hover{transform:scale(1)}.ant-rate-star{position:relative;display:inline-block;color:inherit;cursor:pointer}.ant-rate-star:not(:last-child){margin-right:8px}.ant-rate-star>div{transition:all .3s}.ant-rate-star>div:hover,.ant-rate-star>div:focus-visible{transform:scale(1.1)}.ant-rate-star>div:focus:not(:focus-visible){outline:0}.ant-rate-star-first,.ant-rate-star-second{color:#f0f0f0;transition:all .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-rate-star-first .anticon,.ant-rate-star-second .anticon{vertical-align:middle}.ant-rate-star-first{position:absolute;top:0;left:0;width:50%;height:100%;overflow:hidden;opacity:0}.ant-rate-star-half .ant-rate-star-first,.ant-rate-star-half .ant-rate-star-second{opacity:1}.ant-rate-star-half .ant-rate-star-first,.ant-rate-star-full .ant-rate-star-second{color:inherit}.ant-rate-text{display:inline-block;margin:0 8px;font-size:14px}.ant-rate-rtl{direction:rtl}.ant-rate-rtl .ant-rate-star:not(:last-child){margin-right:0;margin-left:8px}.ant-rate-rtl .ant-rate-star-first{right:0;left:auto}.ant-result{padding:48px 32px}.ant-result-success .ant-result-icon>.anticon{color:#52c41a}.ant-result-error .ant-result-icon>.anticon{color:#ff4d4f}.ant-result-info .ant-result-icon>.anticon{color:#1890ff}.ant-result-warning .ant-result-icon>.anticon{color:#faad14}.ant-result-image{width:250px;height:295px;margin:auto}.ant-result-icon{margin-bottom:24px;text-align:center}.ant-result-icon>.anticon{font-size:72px}.ant-result-title{color:#000000d9;font-size:24px;line-height:1.8;text-align:center}.ant-result-subtitle{color:#00000073;font-size:14px;line-height:1.6;text-align:center}.ant-result-extra{margin:24px 0 0;text-align:center}.ant-result-extra>*{margin-right:8px}.ant-result-extra>*:last-child{margin-right:0}.ant-result-content{margin-top:24px;padding:24px 40px;background-color:#fafafa}.ant-result-rtl{direction:rtl}.ant-result-rtl .ant-result-extra>*{margin-right:0;margin-left:8px}.ant-result-rtl .ant-result-extra>*:last-child{margin-left:0}.ant-skeleton{display:table;width:100%}.ant-skeleton-header{display:table-cell;padding-right:16px;vertical-align:top}.ant-skeleton-header .ant-skeleton-avatar{display:inline-block;vertical-align:top;background:rgba(190,190,190,.2);width:32px;height:32px;line-height:32px}.ant-skeleton-header .ant-skeleton-avatar.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-header .ant-skeleton-avatar-lg{width:40px;height:40px;line-height:40px}.ant-skeleton-header .ant-skeleton-avatar-lg.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-header .ant-skeleton-avatar-sm{width:24px;height:24px;line-height:24px}.ant-skeleton-header .ant-skeleton-avatar-sm.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-content{display:table-cell;width:100%;vertical-align:top}.ant-skeleton-content .ant-skeleton-title{width:100%;height:16px;margin-top:16px;background:rgba(190,190,190,.2);border-radius:4px}.ant-skeleton-content .ant-skeleton-title+.ant-skeleton-paragraph{margin-top:24px}.ant-skeleton-content .ant-skeleton-paragraph{padding:0}.ant-skeleton-content .ant-skeleton-paragraph>li{width:100%;height:16px;list-style:none;background:rgba(190,190,190,.2);border-radius:4px}.ant-skeleton-content .ant-skeleton-paragraph>li:last-child:not(:first-child):not(:nth-child(2)){width:61%}.ant-skeleton-content .ant-skeleton-paragraph>li+li{margin-top:16px}.ant-skeleton-with-avatar .ant-skeleton-content .ant-skeleton-title{margin-top:12px}.ant-skeleton-with-avatar .ant-skeleton-content .ant-skeleton-title+.ant-skeleton-paragraph{margin-top:28px}.ant-skeleton-round .ant-skeleton-content .ant-skeleton-title,.ant-skeleton-round .ant-skeleton-content .ant-skeleton-paragraph>li{border-radius:100px}.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-title,.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-paragraph>li{background:linear-gradient(90deg,rgba(190,190,190,.2) 25%,rgba(129,129,129,.24) 37%,rgba(190,190,190,.2) 63%);background-size:400% 100%;-webkit-animation:ant-skeleton-loading 1.4s ease infinite;animation:ant-skeleton-loading 1.4s ease infinite}.ant-skeleton.ant-skeleton-active .ant-skeleton-avatar,.ant-skeleton.ant-skeleton-active .ant-skeleton-button,.ant-skeleton.ant-skeleton-active .ant-skeleton-input,.ant-skeleton.ant-skeleton-active .ant-skeleton-image{background:linear-gradient(90deg,rgba(190,190,190,.2) 25%,rgba(129,129,129,.24) 37%,rgba(190,190,190,.2) 63%);background-size:400% 100%;-webkit-animation:ant-skeleton-loading 1.4s ease infinite;animation:ant-skeleton-loading 1.4s ease infinite}.ant-skeleton-element{display:inline-block;width:auto}.ant-skeleton-element .ant-skeleton-button{display:inline-block;vertical-align:top;background:rgba(190,190,190,.2);border-radius:2px;width:64px;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-button.ant-skeleton-button-circle{width:32px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button.ant-skeleton-button-round{border-radius:32px}.ant-skeleton-element .ant-skeleton-button-lg{width:80px;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-button-lg.ant-skeleton-button-circle{width:40px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button-lg.ant-skeleton-button-round{border-radius:40px}.ant-skeleton-element .ant-skeleton-button-sm{width:48px;height:24px;line-height:24px}.ant-skeleton-element .ant-skeleton-button-sm.ant-skeleton-button-circle{width:24px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button-sm.ant-skeleton-button-round{border-radius:24px}.ant-skeleton-element .ant-skeleton-avatar{display:inline-block;vertical-align:top;background:rgba(190,190,190,.2);width:32px;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-avatar.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-avatar-lg{width:40px;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-avatar-lg.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-avatar-sm{width:24px;height:24px;line-height:24px}.ant-skeleton-element .ant-skeleton-avatar-sm.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-input{display:inline-block;vertical-align:top;background:rgba(190,190,190,.2);width:100%;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-input-lg{width:100%;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-input-sm{width:100%;height:24px;line-height:24px}.ant-skeleton-element .ant-skeleton-image{display:flex;align-items:center;justify-content:center;vertical-align:top;background:rgba(190,190,190,.2);width:96px;height:96px;line-height:96px}.ant-skeleton-element .ant-skeleton-image.ant-skeleton-image-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-image-path{fill:#bfbfbf}.ant-skeleton-element .ant-skeleton-image-svg{width:48px;height:48px;line-height:48px;max-width:192px;max-height:192px}.ant-skeleton-element .ant-skeleton-image-svg.ant-skeleton-image-circle{border-radius:50%}@-webkit-keyframes ant-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}@keyframes ant-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.ant-skeleton-rtl{direction:rtl}.ant-skeleton-rtl .ant-skeleton-header{padding-right:0;padding-left:16px}.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-title,.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-paragraph>li{-webkit-animation-name:ant-skeleton-loading-rtl;animation-name:ant-skeleton-loading-rtl}.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-avatar{-webkit-animation-name:ant-skeleton-loading-rtl;animation-name:ant-skeleton-loading-rtl}@-webkit-keyframes ant-skeleton-loading-rtl{0%{background-position:0% 50%}to{background-position:100% 50%}}@keyframes ant-skeleton-loading-rtl{0%{background-position:0% 50%}to{background-position:100% 50%}}.ant-slider{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;height:12px;margin:14px 6px 10px;padding:4px 0;cursor:pointer;touch-action:none}.ant-slider-vertical{width:12px;height:100%;margin:6px 10px;padding:0 4px}.ant-slider-vertical .ant-slider-rail{width:4px;height:100%}.ant-slider-vertical .ant-slider-track{width:4px}.ant-slider-vertical .ant-slider-handle{margin-top:-6px;margin-left:-5px}.ant-slider-vertical .ant-slider-mark{top:0;left:12px;width:18px;height:100%}.ant-slider-vertical .ant-slider-mark-text{left:4px;white-space:nowrap}.ant-slider-vertical .ant-slider-step{width:4px;height:100%}.ant-slider-vertical .ant-slider-dot{top:auto;left:2px;margin-bottom:-4px}.ant-slider-tooltip .ant-tooltip-inner{min-width:unset}.ant-slider-with-marks{margin-bottom:28px}.ant-slider-rail{position:absolute;width:100%;height:4px;background-color:#f5f5f5;border-radius:2px;transition:background-color .3s}.ant-slider-track{position:absolute;height:4px;background-color:#91d5ff;border-radius:2px;transition:background-color .3s}.ant-slider-handle{position:absolute;width:14px;height:14px;margin-top:-5px;background-color:#fff;border:solid 2px #91d5ff;border-radius:50%;box-shadow:0;cursor:pointer;transition:border-color .3s,box-shadow .6s,transform .3s cubic-bezier(.18,.89,.32,1.28)}.ant-slider-handle:focus{border-color:#46a6ff;outline:none;box-shadow:0 0 0 5px #1890ff33}.ant-slider-handle.ant-tooltip-open{border-color:#1890ff}.ant-slider:hover .ant-slider-rail{background-color:#e1e1e1}.ant-slider:hover .ant-slider-track{background-color:#69c0ff}.ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open){border-color:#69c0ff}.ant-slider-mark{position:absolute;top:14px;left:0;width:100%;font-size:14px}.ant-slider-mark-text{position:absolute;display:inline-block;color:#00000073;text-align:center;word-break:keep-all;cursor:pointer}.ant-slider-mark-text-active{color:#000000d9}.ant-slider-step{position:absolute;width:100%;height:4px;background:transparent}.ant-slider-dot{position:absolute;top:-2px;width:8px;height:8px;margin-left:-4px;background-color:#fff;border:2px solid #f0f0f0;border-radius:50%;cursor:pointer}.ant-slider-dot:first-child{margin-left:-4px}.ant-slider-dot:last-child{margin-left:-4px}.ant-slider-dot-active{border-color:#8cc8ff}.ant-slider-disabled{cursor:not-allowed}.ant-slider-disabled .ant-slider-track{background-color:#00000040!important}.ant-slider-disabled .ant-slider-handle,.ant-slider-disabled .ant-slider-dot{background-color:#fff;border-color:#00000040!important;box-shadow:none;cursor:not-allowed}.ant-slider-disabled .ant-slider-mark-text,.ant-slider-disabled .ant-slider-dot{cursor:not-allowed!important}.ant-space{display:inline-flex}.ant-space-vertical{flex-direction:column}.ant-space-align-center{align-items:center}.ant-space-align-start{align-items:flex-start}.ant-space-align-end{align-items:flex-end}.ant-space-align-baseline{align-items:baseline}.ant-space-item:empty{display:none}.ant-space-rtl{direction:rtl}.ant-statistic{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-statistic-title{margin-bottom:4px;color:#00000073;font-size:14px}.ant-statistic-content{color:#000000d9;font-size:24px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}.ant-statistic-content-value{display:inline-block;direction:ltr}.ant-statistic-content-prefix,.ant-statistic-content-suffix{display:inline-block}.ant-statistic-content-prefix{margin-right:4px}.ant-statistic-content-suffix{margin-left:4px}.ant-statistic-rtl{direction:rtl}.ant-statistic-rtl .ant-statistic-content-prefix{margin-right:0;margin-left:4px}.ant-statistic-rtl .ant-statistic-content-suffix{margin-right:4px;margin-left:0}.ant-steps{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:flex;width:100%;font-size:0}.ant-steps-item{position:relative;display:inline-block;flex:1;overflow:hidden;vertical-align:top}.ant-steps-item-container{outline:none}.ant-steps-item:last-child{flex:none}.ant-steps-item:last-child>.ant-steps-item-container>.ant-steps-item-tail,.ant-steps-item:last-child>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-item-icon,.ant-steps-item-content{display:inline-block;vertical-align:top}.ant-steps-item-icon{width:32px;height:32px;margin-right:8px;font-size:16px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";line-height:32px;text-align:center;border:1px solid rgba(0,0,0,.25);border-radius:32px;transition:background-color .3s,border-color .3s}.ant-steps-item-icon>.ant-steps-icon{position:relative;top:-1px;color:#1890ff;line-height:1}.ant-steps-item-tail{position:absolute;top:12px;left:0;width:100%;padding:0 10px}.ant-steps-item-tail:after{display:inline-block;width:100%;height:1px;background:#f0f0f0;border-radius:1px;transition:background .3s;content:\"\"}.ant-steps-item-title{position:relative;display:inline-block;padding-right:16px;color:#000000d9;font-size:16px;line-height:32px}.ant-steps-item-title:after{position:absolute;top:16px;left:100%;display:block;width:9999px;height:1px;background:#f0f0f0;content:\"\"}.ant-steps-item-subtitle{display:inline;margin-left:8px;color:#00000073;font-weight:400;font-size:14px}.ant-steps-item-description{color:#00000073;font-size:14px}.ant-steps-item-wait .ant-steps-item-icon{background-color:#fff;border-color:#00000040}.ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon{color:#00000040}.ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:rgba(0,0,0,.25)}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#00000073}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#00000073}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item-process .ant-steps-item-icon{background-color:#fff;border-color:#1890ff}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#1890ff}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#1890ff}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#000000d9}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#000000d9}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item-process .ant-steps-item-icon{background:#1890ff}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#fff}.ant-steps-item-process .ant-steps-item-title{font-weight:500}.ant-steps-item-finish .ant-steps-item-icon{background-color:#fff;border-color:#1890ff}.ant-steps-item-finish .ant-steps-item-icon>.ant-steps-icon{color:#1890ff}.ant-steps-item-finish .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#1890ff}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#000000d9}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#1890ff}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#00000073}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#1890ff}.ant-steps-item-error .ant-steps-item-icon{background-color:#fff;border-color:#ff4d4f}.ant-steps-item-error .ant-steps-item-icon>.ant-steps-icon{color:#ff4d4f}.ant-steps-item-error .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#ff4d4f}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#ff4d4f}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#ff4d4f}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item.ant-steps-next-error .ant-steps-item-title:after{background:#ff4d4f}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]{cursor:pointer}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-title,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-description,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-icon .ant-steps-icon{transition:color .3s}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-title,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-subtitle,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-description{color:#1890ff}.ant-steps .ant-steps-item:not(.ant-steps-item-active):not(.ant-steps-item-process)>.ant-steps-item-container[role=button]:hover .ant-steps-item-icon{border-color:#1890ff}.ant-steps .ant-steps-item:not(.ant-steps-item-active):not(.ant-steps-item-process)>.ant-steps-item-container[role=button]:hover .ant-steps-item-icon .ant-steps-icon{color:#1890ff}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:16px;white-space:nowrap}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-right:0}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child .ant-steps-item-title{padding-right:0}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item-tail{display:none}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item-description{max-width:140px;white-space:normal}.ant-steps-item-custom .ant-steps-item-icon{height:auto;background:none;border:0}.ant-steps-item-custom .ant-steps-item-icon>.ant-steps-icon{top:0;left:.5px;width:32px;height:32px;font-size:24px;line-height:32px}.ant-steps-item-custom.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#1890ff}.ant-steps:not(.ant-steps-vertical) .ant-steps-item-custom .ant-steps-item-icon{width:auto}.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:12px}.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-right:0}.ant-steps-small .ant-steps-item-icon{width:24px;height:24px;font-size:12px;line-height:24px;text-align:center;border-radius:24px}.ant-steps-small .ant-steps-item-title{padding-right:12px;font-size:14px;line-height:24px}.ant-steps-small .ant-steps-item-title:after{top:12px}.ant-steps-small .ant-steps-item-description{color:#00000073;font-size:14px}.ant-steps-small .ant-steps-item-tail{top:8px}.ant-steps-small .ant-steps-item-custom .ant-steps-item-icon{width:inherit;height:inherit;line-height:inherit;background:none;border:0;border-radius:0}.ant-steps-small .ant-steps-item-custom .ant-steps-item-icon>.ant-steps-icon{font-size:24px;line-height:24px;transform:none}.ant-steps-vertical{display:block}.ant-steps-vertical .ant-steps-item{display:block;overflow:visible}.ant-steps-vertical .ant-steps-item-icon{float:left;margin-right:16px}.ant-steps-vertical .ant-steps-item-content{display:block;min-height:48px;overflow:hidden}.ant-steps-vertical .ant-steps-item-title{line-height:32px}.ant-steps-vertical .ant-steps-item-description{padding-bottom:12px}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{position:absolute;top:0;left:16px;width:1px;height:100%;padding:38px 0 6px}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail:after{width:1px;height:100%}.ant-steps-vertical>.ant-steps-item:not(:last-child)>.ant-steps-item-container>.ant-steps-item-tail{display:block}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-vertical.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{position:absolute;top:0;left:12px;padding:30px 0 6px}.ant-steps-vertical.ant-steps-small .ant-steps-item-container .ant-steps-item-title{line-height:24px}@media (max-width: 480px){.ant-steps-horizontal.ant-steps-label-horizontal{display:block}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item{display:block;overflow:visible}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-icon{float:left;margin-right:16px}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-content{display:block;min-height:48px;overflow:hidden}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-title{line-height:32px}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-description{padding-bottom:12px}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{position:absolute;top:0;left:16px;width:1px;height:100%;padding:38px 0 6px}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail:after{width:1px;height:100%}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item:not(:last-child)>.ant-steps-item-container>.ant-steps-item-tail{display:block}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{position:absolute;top:0;left:12px;padding:30px 0 6px}.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item-container .ant-steps-item-title{line-height:24px}}.ant-steps-label-vertical .ant-steps-item{overflow:visible}.ant-steps-label-vertical .ant-steps-item-tail{margin-left:58px;padding:3.5px 24px}.ant-steps-label-vertical .ant-steps-item-content{display:block;width:116px;margin-top:8px;text-align:center}.ant-steps-label-vertical .ant-steps-item-icon{display:inline-block;margin-left:42px}.ant-steps-label-vertical .ant-steps-item-title{padding-right:0}.ant-steps-label-vertical .ant-steps-item-title:after{display:none}.ant-steps-label-vertical .ant-steps-item-subtitle{display:block;margin-bottom:4px;margin-left:0;line-height:1.5715}.ant-steps-label-vertical.ant-steps-small:not(.ant-steps-dot) .ant-steps-item-icon{margin-left:46px}.ant-steps-dot .ant-steps-item-title,.ant-steps-dot.ant-steps-small .ant-steps-item-title{line-height:1.5715}.ant-steps-dot .ant-steps-item-tail,.ant-steps-dot.ant-steps-small .ant-steps-item-tail{top:2px;width:100%;margin:0 0 0 70px;padding:0}.ant-steps-dot .ant-steps-item-tail:after,.ant-steps-dot.ant-steps-small .ant-steps-item-tail:after{width:calc(100% - 20px);height:3px;margin-left:12px}.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot,.ant-steps-dot.ant-steps-small .ant-steps-item:first-child .ant-steps-icon-dot{left:2px}.ant-steps-dot .ant-steps-item-icon,.ant-steps-dot.ant-steps-small .ant-steps-item-icon{width:8px;height:8px;margin-left:67px;padding-right:0;line-height:8px;background:transparent;border:0}.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot,.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot{position:relative;float:left;width:100%;height:100%;border-radius:100px;transition:all .3s}.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot:after,.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot:after{position:absolute;top:-12px;left:-26px;width:60px;height:32px;background:rgba(0,0,0,.001);content:\"\"}.ant-steps-dot .ant-steps-item-content,.ant-steps-dot.ant-steps-small .ant-steps-item-content{width:140px}.ant-steps-dot .ant-steps-item-process .ant-steps-item-icon,.ant-steps-dot.ant-steps-small .ant-steps-item-process .ant-steps-item-icon{width:10px;height:10px;line-height:10px}.ant-steps-dot .ant-steps-item-process .ant-steps-item-icon .ant-steps-icon-dot,.ant-steps-dot.ant-steps-small .ant-steps-item-process .ant-steps-item-icon .ant-steps-icon-dot{top:-1px}.ant-steps-vertical.ant-steps-dot .ant-steps-item-icon{margin-top:8px;margin-left:0}.ant-steps-vertical.ant-steps-dot .ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{top:2px;left:-9px;margin:0;padding:22px 0 4px}.ant-steps-vertical.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot{left:0}.ant-steps-vertical.ant-steps-dot .ant-steps-item-process .ant-steps-icon-dot{left:-2px}.ant-steps-navigation{padding-top:12px}.ant-steps-navigation.ant-steps-small .ant-steps-item-container{margin-left:-12px}.ant-steps-navigation .ant-steps-item{overflow:visible;text-align:center}.ant-steps-navigation .ant-steps-item-container{display:inline-block;height:100%;margin-left:-16px;padding-bottom:12px;text-align:left;transition:opacity .3s}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-content{max-width:auto}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-title{max-width:100%;padding-right:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-title:after{display:none}.ant-steps-navigation .ant-steps-item:not(.ant-steps-item-active) .ant-steps-item-container[role=button]{cursor:pointer}.ant-steps-navigation .ant-steps-item:not(.ant-steps-item-active) .ant-steps-item-container[role=button]:hover{opacity:.85}.ant-steps-navigation .ant-steps-item:last-child{flex:1}.ant-steps-navigation .ant-steps-item:last-child:after{display:none}.ant-steps-navigation .ant-steps-item:after{position:absolute;top:50%;left:100%;display:inline-block;width:12px;height:12px;margin-top:-14px;margin-left:-2px;border:1px solid rgba(0,0,0,.25);border-bottom:none;border-left:none;transform:rotate(45deg);content:\"\"}.ant-steps-navigation .ant-steps-item:before{position:absolute;bottom:0;left:50%;display:inline-block;width:0;height:3px;background-color:#1890ff;transition:width .3s,left .3s;transition-timing-function:ease-out;content:\"\"}.ant-steps-navigation .ant-steps-item.ant-steps-item-active:before{left:0;width:100%}@media (max-width: 480px){.ant-steps-navigation>.ant-steps-item{margin-right:0!important}.ant-steps-navigation>.ant-steps-item:before{display:none}.ant-steps-navigation>.ant-steps-item.ant-steps-item-active:before{top:0;right:0;left:unset;display:block;width:3px;height:calc(100% - 24px)}.ant-steps-navigation>.ant-steps-item:after{position:relative;top:-2px;left:50%;display:block;width:8px;height:8px;margin-bottom:8px;text-align:center;transform:rotate(135deg)}.ant-steps-navigation>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{visibility:hidden}}.ant-steps-flex-not-supported.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item{margin-left:-16px;padding-left:16px;background:#fff}.ant-steps-flex-not-supported.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item{margin-left:-12px;padding-left:12px}.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item:last-child{overflow:hidden}.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item:last-child .ant-steps-icon-dot:after{right:-200px;width:200px}.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item .ant-steps-icon-dot:before,.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item .ant-steps-icon-dot:after{position:absolute;top:0;left:-10px;width:10px;height:8px;background:#fff;content:\"\"}.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item .ant-steps-icon-dot:after{right:-10px;left:auto}.ant-steps-flex-not-supported.ant-steps-dot .ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#ccc}.ant-switch{margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;box-sizing:border-box;min-width:44px;height:22px;line-height:20px;vertical-align:middle;background-color:#00000040;border:1px solid transparent;border-radius:100px;cursor:pointer;transition:all .36s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-switch-inner{display:block;margin-right:6px;margin-left:24px;color:#fff;font-size:12px}.ant-switch-loading-icon,.ant-switch:after{position:absolute;top:1px;left:1px;width:18px;height:18px;background-color:#fff;border-radius:18px;cursor:pointer;transition:all .36s cubic-bezier(.78,.14,.15,.86);content:\" \"}.ant-switch:after{box-shadow:0 2px 4px #00230b33}.ant-switch:not(.ant-switch-disabled):active:before,.ant-switch:not(.ant-switch-disabled):active:after{width:24px}.ant-switch-loading-icon{z-index:1;display:none;font-size:12px;background:transparent}.ant-switch-loading-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-switch-loading .ant-switch-loading-icon{display:inline-block;color:#000000d9}.ant-switch-checked.ant-switch-loading .ant-switch-loading-icon{color:#1890ff}.ant-switch:focus{outline:0;box-shadow:0 0 0 2px #1890ff33}.ant-switch:focus:hover{box-shadow:none}.ant-switch-small{min-width:28px;height:16px;line-height:14px}.ant-switch-small .ant-switch-inner{margin-right:3px;margin-left:18px;font-size:12px}.ant-switch-small:after{width:12px;height:12px}.ant-switch-small:active:before,.ant-switch-small:active:after{width:16px}.ant-switch-small .ant-switch-loading-icon{width:12px;height:12px}.ant-switch-small.ant-switch-checked .ant-switch-inner{margin-right:18px;margin-left:3px}.ant-switch-small.ant-switch-checked .ant-switch-loading-icon{left:100%;margin-left:-13px}.ant-switch-small.ant-switch-loading .ant-switch-loading-icon{font-weight:700;transform:scale(.66667)}.ant-switch-checked{background-color:#1890ff}.ant-switch-checked .ant-switch-inner{margin-right:24px;margin-left:6px}.ant-switch-checked:after{left:100%;margin-left:-1px;transform:translate(-100%)}.ant-switch-checked .ant-switch-loading-icon{left:100%;margin-left:-19px}.ant-switch-loading,.ant-switch-disabled{cursor:not-allowed;opacity:.4}.ant-switch-loading *,.ant-switch-disabled *{cursor:not-allowed}.ant-switch-loading:before,.ant-switch-disabled:before,.ant-switch-loading:after,.ant-switch-disabled:after{cursor:not-allowed}@-webkit-keyframes AntSwitchSmallLoadingCircle{0%{transform:rotate(0) scale(.66667);transform-origin:50% 50%}to{transform:rotate(360deg) scale(.66667);transform-origin:50% 50%}}@keyframes AntSwitchSmallLoadingCircle{0%{transform:rotate(0) scale(.66667);transform-origin:50% 50%}to{transform:rotate(360deg) scale(.66667);transform-origin:50% 50%}}.ant-table-wrapper:before,.ant-table-wrapper:after{display:table;content:\"\"}.ant-table-wrapper:after{clear:both}.ant-table{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;clear:both;background:#fff}.ant-table-body{transition:opacity .3s}.ant-table-empty .ant-table-body{overflow-x:auto!important;overflow-y:hidden!important}.ant-table table{width:100%;text-align:left;border-radius:2px 2px 0 0;border-collapse:separate;border-spacing:0}.ant-table-layout-fixed table{table-layout:fixed}.ant-table-thead>tr>th{color:#000000d9;font-weight:500;text-align:left;background:#fafafa;border-bottom:1px solid #f0f0f0;transition:background .3s ease}.ant-table-thead>tr>th[colspan]:not([colspan=\"1\"]){text-align:center}.ant-table-thead>tr>th .anticon-filter,.ant-table-thead>tr>th .ant-table-filter-icon{position:absolute;top:0;right:0;width:28px;height:100%;color:#bfbfbf;font-size:12px;text-align:center;cursor:pointer;transition:all .3s}.ant-table-thead>tr>th .anticon-filter>svg,.ant-table-thead>tr>th .ant-table-filter-icon>svg{position:absolute;top:50%;left:50%;margin-top:-5px;margin-left:-6px}.ant-table-thead>tr>th .ant-table-filter-selected.anticon{color:#1890ff}.ant-table-thead>tr>th .ant-table-column-sorter{display:table-cell;vertical-align:middle}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner{height:1em;margin-top:.35em;margin-left:.57142857em;color:#bfbfbf;line-height:1em;text-align:center;transition:all .3s}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-up,.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-down{display:inline-block;font-size:12px;font-size:11px \\\t;transform:scale(.91666667) rotate(0);display:block;height:1em;line-height:1em;transition:all .3s}:root .ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-up,:root .ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-down{font-size:12px}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-up.on,.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner .ant-table-column-sorter-down.on{color:#1890ff}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner-full{margin-top:-.15em}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner-full .ant-table-column-sorter-up,.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner-full .ant-table-column-sorter-down{height:.5em;line-height:.5em}.ant-table-thead>tr>th .ant-table-column-sorter .ant-table-column-sorter-inner-full .ant-table-column-sorter-down{margin-top:.125em}.ant-table-thead>tr>th.ant-table-column-has-actions{position:relative;background-clip:padding-box;-webkit-background-clip:border-box}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters{padding-right:30px!important}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters .anticon-filter.ant-table-filter-open,.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters .ant-table-filter-icon.ant-table-filter-open{color:#00000073;background:#e5e5e5}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters:hover .anticon-filter:hover,.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters:hover .ant-table-filter-icon:hover{color:#00000073;background:#e5e5e5}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters:hover .anticon-filter:active,.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-filters:hover .ant-table-filter-icon:active{color:#000000d9}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters{cursor:pointer}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters:hover{background:#f2f2f2}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters:hover .anticon-filter,.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters:hover .ant-table-filter-icon{background:#f2f2f2}.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters:active .ant-table-column-sorter-up:not(.on),.ant-table-thead>tr>th.ant-table-column-has-actions.ant-table-column-has-sorters:active .ant-table-column-sorter-down:not(.on){color:#00000073}.ant-table-thead>tr>th .ant-table-header-column{display:inline-block;max-width:100%;vertical-align:top}.ant-table-thead>tr>th .ant-table-header-column .ant-table-column-sorters{display:table}.ant-table-thead>tr>th .ant-table-header-column .ant-table-column-sorters>.ant-table-column-title{display:table-cell;vertical-align:middle}.ant-table-thead>tr>th .ant-table-header-column .ant-table-column-sorters>*:not(.ant-table-column-sorter){position:relative}.ant-table-thead>tr>th .ant-table-header-column .ant-table-column-sorters:before{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;transition:all .3s;content:\"\"}.ant-table-thead>tr>th .ant-table-header-column .ant-table-column-sorters:hover:before{background:rgba(0,0,0,.04)}.ant-table-thead>tr>th.ant-table-column-has-sorters{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-table-thead>tr:first-child>th:first-child{border-top-left-radius:2px}.ant-table-thead>tr:first-child>th:last-child{border-top-right-radius:2px}.ant-table-thead>tr:not(:last-child)>th[colspan]{border-bottom:0}.ant-table-tbody>tr>td{border-bottom:1px solid #f0f0f0;transition:background .3s}.ant-table-thead>tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td,.ant-table-tbody>tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td,.ant-table-thead>tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td,.ant-table-tbody>tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td{background:#e6f7ff}.ant-table-thead>tr.ant-table-row-selected>td.ant-table-column-sort,.ant-table-tbody>tr.ant-table-row-selected>td.ant-table-column-sort{background:#e6f7ff}.ant-table-thead>tr:hover.ant-table-row-selected>td,.ant-table-tbody>tr:hover.ant-table-row-selected>td{background:#dcf4ff}.ant-table-thead>tr:hover.ant-table-row-selected>td.ant-table-column-sort,.ant-table-tbody>tr:hover.ant-table-row-selected>td.ant-table-column-sort{background:#e6f7ff}.ant-table-thead>tr:hover{background:none}.ant-table-footer{position:relative;padding:16px;color:#000000d9;background:#fafafa;border-top:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-table-footer:before{position:absolute;top:-1px;left:0;width:100%;height:1px;background:#fafafa;content:\"\"}.ant-table.ant-table-bordered .ant-table-footer{border:1px solid #f0f0f0}.ant-table-title{position:relative;top:1px;padding:16px 0;border-radius:2px 2px 0 0}.ant-table.ant-table-bordered .ant-table-title{padding-right:16px;padding-left:16px;border:1px solid #f0f0f0}.ant-table-title+.ant-table-content{position:relative;border-radius:2px 2px 0 0}.ant-table-bordered .ant-table-title+.ant-table-content,.ant-table-bordered .ant-table-title+.ant-table-content table,.ant-table-bordered .ant-table-title+.ant-table-content .ant-table-thead>tr:first-child>th{border-radius:0}.ant-table-without-column-header .ant-table-title+.ant-table-content,.ant-table-without-column-header table{border-radius:0}.ant-table-without-column-header.ant-table-bordered.ant-table-empty .ant-table-placeholder{border-top:1px solid #f0f0f0;border-radius:2px}.ant-table-tbody>tr.ant-table-row-selected td{color:inherit;background:#e6f7ff}.ant-table-thead>tr>th.ant-table-column-sort{background:#f5f5f5}.ant-table-tbody>tr>td.ant-table-column-sort{background:rgba(0,0,0,.01)}.ant-table-thead>tr>th,.ant-table-tbody>tr>td{padding:16px;overflow-wrap:break-word}.ant-table-expand-icon-th,.ant-table-row-expand-icon-cell{width:50px;min-width:50px;text-align:center}.ant-table-header{overflow:hidden;background:#fafafa}.ant-table-header table{border-radius:2px 2px 0 0}.ant-table-loading{position:relative}.ant-table-loading .ant-table-body{background:#fff;opacity:.5}.ant-table-loading .ant-table-spin-holder{position:absolute;top:50%;left:50%;height:20px;margin-left:-30px;line-height:20px}.ant-table-loading .ant-table-with-pagination{margin-top:-20px}.ant-table-loading .ant-table-without-pagination{margin-top:10px}.ant-table-bordered .ant-table-header>table,.ant-table-bordered .ant-table-body>table,.ant-table-bordered .ant-table-fixed-left table,.ant-table-bordered .ant-table-fixed-right table{border:1px solid #f0f0f0;border-right:0;border-bottom:0}.ant-table-bordered.ant-table-empty .ant-table-placeholder{border-right:1px solid #f0f0f0;border-left:1px solid #f0f0f0}.ant-table-bordered.ant-table-fixed-header .ant-table-header>table{border-bottom:0}.ant-table-bordered.ant-table-fixed-header .ant-table-body>table{border-top-left-radius:0;border-top-right-radius:0}.ant-table-bordered.ant-table-fixed-header .ant-table-header+.ant-table-body>table,.ant-table-bordered.ant-table-fixed-header .ant-table-body-inner>table{border-top:0}.ant-table-bordered .ant-table-thead>tr:not(:last-child)>th{border-bottom:1px solid #f0f0f0}.ant-table-bordered .ant-table-thead>tr>th,.ant-table-bordered .ant-table-tbody>tr>td{border-right:1px solid #f0f0f0}.ant-table-placeholder{position:relative;z-index:1;margin-top:-1px;padding:16px;color:#00000040;font-size:14px;text-align:center;background:#fff;border-top:1px solid #f0f0f0;border-bottom:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-table-pagination.ant-pagination{float:right;margin:16px 0}.ant-table-filter-dropdown{position:relative;min-width:96px;margin-left:-8px;background:#fff;border-radius:2px;box-shadow:0 2px 8px #00000026}.ant-table-filter-dropdown .ant-dropdown-menu{max-height:calc(100vh - 130px);overflow-x:hidden;border:0;border-radius:2px 2px 0 0;box-shadow:none}.ant-table-filter-dropdown .ant-dropdown-menu-item>label+span{padding-right:0}.ant-table-filter-dropdown .ant-dropdown-menu-sub{border-radius:2px;box-shadow:0 2px 8px #00000026}.ant-table-filter-dropdown .ant-dropdown-menu .ant-dropdown-submenu-contain-selected .ant-dropdown-menu-submenu-title:after{color:#1890ff;font-weight:700;text-shadow:0 0 2px #bae7ff}.ant-table-filter-dropdown .ant-dropdown-menu-item{overflow:hidden}.ant-table-filter-dropdown>.ant-dropdown-menu>.ant-dropdown-menu-item:last-child,.ant-table-filter-dropdown>.ant-dropdown-menu>.ant-dropdown-menu-submenu:last-child .ant-dropdown-menu-submenu-title{border-radius:0}.ant-table-filter-dropdown-btns{padding:7px 8px;overflow:hidden;border-top:1px solid #f0f0f0}.ant-table-filter-dropdown-link{color:#1890ff}.ant-table-filter-dropdown-link:hover{color:#40a9ff}.ant-table-filter-dropdown-link:active{color:#096dd9}.ant-table-filter-dropdown-link.confirm{float:left}.ant-table-filter-dropdown-link.clear{float:right}.ant-table-selection{white-space:nowrap}.ant-table-selection-select-all-custom{margin-right:4px!important}.ant-table-selection .anticon-down{color:#bfbfbf;transition:all .3s}.ant-table-selection-menu{min-width:96px;margin-top:5px;margin-left:-30px;background:#fff;border-radius:2px;box-shadow:0 2px 8px #00000026}.ant-table-selection-menu .ant-action-down{color:#bfbfbf}.ant-table-selection-down{display:inline-block;padding:0;line-height:1;cursor:pointer}.ant-table-selection-down:hover .anticon-down{color:#0009}.ant-table-row-expand-icon{color:#1890ff;text-decoration:none;cursor:pointer;transition:color .3s;display:inline-block;width:17px;height:17px;color:inherit;line-height:13px;text-align:center;background:#fff;border:1px solid #f0f0f0;border-radius:2px;outline:none;transition:all .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-table-row-expand-icon:focus,.ant-table-row-expand-icon:hover{color:#40a9ff}.ant-table-row-expand-icon:active{color:#096dd9}.ant-table-row-expand-icon:focus,.ant-table-row-expand-icon:hover,.ant-table-row-expand-icon:active{border-color:currentColor}.ant-table-row-expanded:after{content:\"-\"}.ant-table-row-collapsed:after{content:\"+\"}.ant-table-row-spaced{visibility:hidden}.ant-table-row-spaced:after{content:\".\"}.ant-table-row-cell-ellipsis,.ant-table-row-cell-ellipsis .ant-table-column-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-table-row-cell-ellipsis .ant-table-column-title{display:block}.ant-table-row-cell-break-word{word-wrap:break-word;word-break:break-word}tr.ant-table-expanded-row,tr.ant-table-expanded-row:hover{background:#fbfbfb}tr.ant-table-expanded-row td>.ant-table-wrapper{margin:-16px -16px -17px}.ant-table .ant-table-row-indent+.ant-table-row-expand-icon{margin-right:8px}.ant-table-scroll{overflow:auto;overflow-x:hidden}.ant-table-scroll table{min-width:100%}.ant-table-body-inner{height:100%}.ant-table-fixed-header>.ant-table-content>.ant-table-scroll>.ant-table-body{position:relative;background:#fff}.ant-table-fixed-header .ant-table-body-inner{overflow:scroll}.ant-table-fixed-header .ant-table-scroll .ant-table-header{margin-bottom:-20px;padding-bottom:20px;overflow:scroll;opacity:.9999}.ant-table-fixed-header .ant-table-scroll .ant-table-header::-webkit-scrollbar{border:1px solid #f0f0f0;border-width:0 0 1px 0}.ant-table-hide-scrollbar{scrollbar-color:transparent transparent;min-width:unset}.ant-table-hide-scrollbar::-webkit-scrollbar{min-width:inherit;background-color:transparent}.ant-table-bordered.ant-table-fixed-header .ant-table-scroll .ant-table-header::-webkit-scrollbar{border:1px solid #f0f0f0;border-width:1px 1px 1px 0}.ant-table-bordered.ant-table-fixed-header .ant-table-scroll .ant-table-header.ant-table-hide-scrollbar .ant-table-thead>tr:only-child>th:last-child{border-right-color:transparent}.ant-table-fixed-left,.ant-table-fixed-right{position:absolute;top:0;z-index:1;overflow:hidden;border-radius:0;transition:box-shadow .3s ease}.ant-table-fixed-left table,.ant-table-fixed-right table{width:auto;background:#fff}.ant-table-fixed-header .ant-table-fixed-left .ant-table-body-outer .ant-table-fixed,.ant-table-fixed-header .ant-table-fixed-right .ant-table-body-outer .ant-table-fixed{border-radius:0}.ant-table-fixed-left{left:0;box-shadow:6px 0 6px -4px #00000026}.ant-table-fixed-left .ant-table-header{overflow-y:hidden}.ant-table-fixed-left .ant-table-body-inner{margin-right:-20px;padding-right:20px}.ant-table-fixed-header .ant-table-fixed-left .ant-table-body-inner{padding-right:0}.ant-table-fixed-left,.ant-table-fixed-left table{border-radius:2px 0 0}.ant-table-fixed-left .ant-table-thead>tr>th:last-child{border-top-right-radius:0}.ant-table-fixed-right{right:0;box-shadow:-6px 0 6px -4px #00000026}.ant-table-fixed-right,.ant-table-fixed-right table{border-radius:0 2px 0 0}.ant-table-fixed-right .ant-table-expanded-row{color:transparent;pointer-events:none}.ant-table-fixed-right .ant-table-thead>tr>th:first-child{border-top-left-radius:0}.ant-table.ant-table-scroll-position-left .ant-table-fixed-left,.ant-table.ant-table-scroll-position-right .ant-table-fixed-right{box-shadow:none}.ant-table colgroup>col.ant-table-selection-col{width:60px}.ant-table-thead>tr>th.ant-table-selection-column-custom .ant-table-selection{margin-right:-15px}.ant-table-thead>tr>th.ant-table-selection-column,.ant-table-tbody>tr>td.ant-table-selection-column{text-align:center}.ant-table-thead>tr>th.ant-table-selection-column .ant-radio-wrapper,.ant-table-tbody>tr>td.ant-table-selection-column .ant-radio-wrapper{margin-right:0}.ant-table-row[class*=ant-table-row-level-0] .ant-table-selection-column>span{display:inline-block}.ant-table-cell-fix-left,.ant-table-cell-fix-right{position:sticky!important;z-index:1;background:#fff}.ant-table-cell-fix-left-first:after,.ant-table-cell-fix-left-last:after{position:absolute;top:0;right:0;bottom:-1px;width:30px;transform:translate(100%);transition:box-shadow .3s;content:\"\";pointer-events:none}.ant-table-cell-fix-right-first:after,.ant-table-cell-fix-right-last:after{position:absolute;top:0;bottom:-1px;left:0;width:30px;transform:translate(-100%);transition:box-shadow .3s;content:\"\";pointer-events:none}.ant-table .ant-table-container:before,.ant-table .ant-table-container:after{position:absolute;top:0;bottom:0;z-index:1;width:30px;transition:box-shadow .3s;content:\"\";pointer-events:none}.ant-table .ant-table-container:before{left:0}.ant-table .ant-table-container:after{right:0}.ant-table-ping-left:not(.ant-table-has-fix-left) .ant-table-container{position:relative}.ant-table-ping-left:not(.ant-table-has-fix-left) .ant-table-container:before{box-shadow:inset 10px 0 8px -8px #00000026}.ant-table-ping-left .ant-table-cell-fix-left-first:after,.ant-table-ping-left .ant-table-cell-fix-left-last:after{box-shadow:inset 10px 0 8px -8px #00000026}.ant-table-ping-left .ant-table-cell-fix-left-last:before{background-color:transparent!important}.ant-table-ping-right:not(.ant-table-has-fix-right) .ant-table-container{position:relative}.ant-table-ping-right:not(.ant-table-has-fix-right) .ant-table-container:after{box-shadow:inset -10px 0 8px -8px #00000026}.ant-table-ping-right .ant-table-cell-fix-right-first:after,.ant-table-ping-right .ant-table-cell-fix-right-last:after{box-shadow:inset -10px 0 8px -8px #00000026}.ant-table-filter-dropdown .ant-checkbox-wrapper+span,.ant-table-filter-dropdown-submenu .ant-checkbox-wrapper+span{padding-left:8px}@supports (-moz-appearance: meterbar){.ant-table-thead>tr>th.ant-table-column-has-actions{background-clip:padding-box}}.ant-table.ant-table-middle>.ant-table-title,.ant-table.ant-table-middle>.ant-table-content>.ant-table-footer{padding:12px 8px}.ant-table.ant-table-middle>.ant-table-content>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-body>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-scroll>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-scroll>.ant-table-body>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-left>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-right>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-left>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-right>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-thead>tr>th,.ant-table.ant-table-middle>.ant-table-content>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-body>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-scroll>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-scroll>.ant-table-body>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-left>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-right>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-left>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-tbody>tr>td,.ant-table.ant-table-middle>.ant-table-content>.ant-table-fixed-right>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-tbody>tr>td{padding:12px 8px}.ant-table.ant-table-middle tr.ant-table-expanded-row td>.ant-table-wrapper{margin:-12px -8px -13px}.ant-table.ant-table-small>.ant-table-title,.ant-table.ant-table-small>.ant-table-content>.ant-table-footer{padding:8px}.ant-table.ant-table-small>.ant-table-content>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-body>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-scroll>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-scroll>.ant-table-body>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-left>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-right>.ant-table-header>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-left>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-right>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-thead>tr>th,.ant-table.ant-table-small>.ant-table-content>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-body>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-scroll>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-scroll>.ant-table-body>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-left>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-right>.ant-table-header>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-left>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-tbody>tr>td,.ant-table.ant-table-small>.ant-table-content>.ant-table-fixed-right>.ant-table-body-outer>.ant-table-body-inner>table>.ant-table-tbody>tr>td{padding:8px}.ant-table.ant-table-small tr.ant-table-expanded-row td>.ant-table-wrapper{margin:-8px -8px -9px}.ant-table-small .ant-table-selection-column{width:46px;min-width:46px}.ant-timeline{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:\"tnum\";margin:0;padding:0;list-style:none}.ant-timeline-item{position:relative;margin:0;padding:0 0 20px;font-size:14px;list-style:none}.ant-timeline-item-tail{position:absolute;top:10px;left:4px;height:calc(100% - 10px);border-left:2px solid #f0f0f0}.ant-timeline-item-pending .ant-timeline-item-head{font-size:12px;background-color:transparent}.ant-timeline-item-pending .ant-timeline-item-tail{display:none}.ant-timeline-item-head{position:absolute;width:10px;height:10px;background-color:#fff;border:2px solid transparent;border-radius:100px}.ant-timeline-item-head-blue{color:#1890ff;border-color:#1890ff}.ant-timeline-item-head-red{color:#ff4d4f;border-color:#ff4d4f}.ant-timeline-item-head-green{color:#52c41a;border-color:#52c41a}.ant-timeline-item-head-gray{color:#00000040;border-color:#00000040}.ant-timeline-item-head-custom{position:absolute;top:5.5px;left:5px;width:auto;height:auto;margin-top:0;padding:3px 1px;line-height:1;text-align:center;border:0;border-radius:0;transform:translate(-50%,-50%)}.ant-timeline-item-content{position:relative;top:-7.001px;margin:0 0 0 18px;word-break:break-word}.ant-timeline-item-last>.ant-timeline-item-tail{display:none}.ant-timeline-item-last>.ant-timeline-item-content{min-height:48px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-tail,.ant-timeline.ant-timeline-right .ant-timeline-item-tail,.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-head,.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom{left:50%}.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-head{margin-left:-4px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom{margin-left:1px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-left .ant-timeline-item-content,.ant-timeline.ant-timeline-right .ant-timeline-item-left .ant-timeline-item-content{left:calc(50% - 4px);width:calc(50% - 14px);text-align:left}.ant-timeline.ant-timeline-alternate .ant-timeline-item-right .ant-timeline-item-content,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content{width:calc(50% - 12px);margin:0;text-align:right}.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-tail,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head-custom{left:calc(100% - 6px)}.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content{width:calc(100% - 18px)}.ant-timeline.ant-timeline-pending .ant-timeline-item-last .ant-timeline-item-tail{display:block;height:calc(100% - 14px);border-left:2px dotted #f0f0f0}.ant-timeline.ant-timeline-reverse .ant-timeline-item-last .ant-timeline-item-tail{display:none}.ant-timeline.ant-timeline-reverse .ant-timeline-item-pending .ant-timeline-item-tail{top:15px;display:block;height:calc(100% - 15px);border-left:2px dotted #f0f0f0}.ant-timeline.ant-timeline-reverse .ant-timeline-item-pending .ant-timeline-item-content{min-height:48px}@-webkit-keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}.ant-transfer-customize-list{display:flex}.ant-transfer-customize-list .ant-transfer-operation{flex:none;align-self:center}.ant-transfer-customize-list .ant-transfer-list{flex:auto;width:auto;height:auto;min-height:200px}.ant-transfer-customize-list .ant-transfer-list-body-with-search{padding-top:0}.ant-transfer-customize-list .ant-transfer-list-body-search-wrapper{position:relative;padding-bottom:0}.ant-transfer-customize-list .ant-transfer-list-body-customize-wrapper{padding:12px}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small{border:0;border-radius:0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small>.ant-table-content>.ant-table-body>table>.ant-table-thead>tr>th{background:#fafafa}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small>.ant-table-content .ant-table-row:last-child td{border-bottom:1px solid #f0f0f0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small .ant-table-body{margin:0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-pagination.ant-pagination{margin:16px 0 4px}.ant-transfer{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative}.ant-transfer-disabled .ant-transfer-list{background:#f5f5f5}.ant-transfer-list{position:relative;display:inline-block;width:180px;height:200px;padding-top:40px;vertical-align:middle;border:1px solid #d9d9d9;border-radius:2px}.ant-transfer-list-with-footer{padding-bottom:34px}.ant-transfer-list-search{padding-right:24px;padding-left:8px}.ant-transfer-list-search-action{position:absolute;top:12px;right:12px;bottom:12px;width:28px;color:#00000040;line-height:32px;text-align:center}.ant-transfer-list-search-action .anticon{color:#00000040;transition:all .3s}.ant-transfer-list-search-action .anticon:hover{color:#00000073}span.ant-transfer-list-search-action{pointer-events:none}.ant-transfer-list-header{position:absolute;top:0;left:0;width:100%;padding:7.4995px 12px 8.4995px;overflow:hidden;color:#000000d9;background:#fff;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-transfer-list-header-title{position:absolute;right:12px}.ant-transfer-list-header .ant-checkbox-wrapper+span{padding-left:8px}.ant-transfer-list-body{position:relative;height:100%;font-size:14px}.ant-transfer-list-body-search-wrapper{position:absolute;top:0;left:0;width:100%;padding:12px}.ant-transfer-list-body-with-search{padding-top:56px}.ant-transfer-list-content{height:100%;margin:0;padding:0;overflow:auto;list-style:none}.ant-transfer-list-content>.LazyLoad{-webkit-animation:transferHighlightIn 1s;animation:transferHighlightIn 1s}.ant-transfer-list-content-item{min-height:32px;padding:6px 12px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-transfer-list-content-item>span{padding-right:0}.ant-transfer-list-content-item-text{padding-left:8px}.ant-transfer-list-content-item:not(.ant-transfer-list-content-item-disabled):hover{background-color:#f5f5f5;cursor:pointer}.ant-transfer-list-content-item-disabled{color:#00000040;cursor:not-allowed}.ant-transfer-list-body-not-found{position:absolute;top:50%;width:100%;padding-top:0;color:#00000040;text-align:center;transform:translateY(-50%)}.ant-transfer-list-body-with-search .ant-transfer-list-body-not-found{margin-top:16px}.ant-transfer-list-footer{position:absolute;bottom:0;left:0;width:100%;border-top:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-transfer-operation{display:inline-block;margin:0 8px;overflow:hidden;vertical-align:middle}.ant-transfer-operation .ant-btn{display:block}.ant-transfer-operation .ant-btn:first-child{margin-bottom:4px}.ant-transfer-operation .ant-btn .anticon{font-size:12px}@-webkit-keyframes transferHighlightIn{0%{background:#bae7ff}to{background:transparent}}@keyframes transferHighlightIn{0%{background:#bae7ff}to{background:transparent}}@-webkit-keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}.ant-select-tree-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox-inner,.ant-select-tree-checkbox:hover .ant-select-tree-checkbox-inner,.ant-select-tree-checkbox-input:focus+.ant-select-tree-checkbox-inner{border-color:#1890ff}.ant-select-tree-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:2px;visibility:hidden;-webkit-animation:antCheckboxEffect .36s ease-in-out;animation:antCheckboxEffect .36s ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;content:\"\"}.ant-select-tree-checkbox:hover:after,.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox:after{visibility:visible}.ant-select-tree-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;border-collapse:separate;transition:all .3s}.ant-select-tree-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5.71428571px;height:9.14285714px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:\" \"}.ant-select-tree-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner:after{position:absolute;display:table;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(1) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:\" \"}.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner{background-color:#1890ff;border-color:#1890ff}.ant-select-tree-checkbox-disabled{cursor:not-allowed}.ant-select-tree-checkbox-disabled.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner:after{border-color:#00000040;-webkit-animation-name:none;animation-name:none}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-input{cursor:not-allowed}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;-webkit-animation-name:none;animation-name:none}.ant-select-tree-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-select-tree-checkbox-disabled:hover:after,.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox-disabled:after{visibility:hidden}.ant-select-tree-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block;line-height:unset;cursor:pointer}.ant-select-tree-checkbox-wrapper.ant-select-tree-checkbox-wrapper-disabled{cursor:not-allowed}.ant-select-tree-checkbox-wrapper+.ant-select-tree-checkbox-wrapper{margin-left:8px}.ant-select-tree-checkbox+span{padding-right:8px;padding-left:8px}.ant-select-tree-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block}.ant-select-tree-checkbox-group-item{display:inline-block;margin-right:8px}.ant-select-tree-checkbox-group-item:last-child{margin-right:0}.ant-select-tree-checkbox-group-item+.ant-select-tree-checkbox-group-item{margin-left:0}.ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner:after{top:50%;left:50%;width:8px;height:8px;background-color:#1890ff;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;content:\" \"}.ant-select-tree-checkbox-indeterminate.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-select-tree{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";margin:-4px 0 0;padding:0 4px}.ant-select-tree li{margin:8px 0;padding:0;white-space:nowrap;list-style:none;outline:0}.ant-select-tree li.filter-node>span{font-weight:500}.ant-select-tree li ul{margin:0;padding:0 0 0 18px}.ant-select-tree li .ant-select-tree-node-content-wrapper{display:inline-block;width:calc(100% - 24px);margin:0;padding:3px 5px;color:#000000d9;text-decoration:none;border-radius:2px;cursor:pointer;transition:all .3s}.ant-select-tree li .ant-select-tree-node-content-wrapper:hover{background-color:#f5f5f5}.ant-select-tree li .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected{background-color:#bae7ff}.ant-select-tree li span.ant-select-tree-checkbox{margin:0 4px 0 0}.ant-select-tree li span.ant-select-tree-checkbox+.ant-select-tree-node-content-wrapper{width:calc(100% - 46px)}.ant-select-tree li span.ant-select-tree-switcher,.ant-select-tree li span.ant-select-tree-iconEle{display:inline-block;width:24px;height:24px;margin:0;line-height:22px;text-align:center;vertical-align:middle;border:0 none;outline:none;cursor:pointer}.ant-select-tree li span.ant-select-icon_loading .ant-select-switcher-loading-icon{position:absolute;left:0;display:inline-block;color:#1890ff;font-size:14px;transform:none}.ant-select-tree li span.ant-select-icon_loading .ant-select-switcher-loading-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-select-tree li span.ant-select-tree-switcher{position:relative}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher-noop{cursor:auto}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-tree-switcher-icon,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-select-switcher-icon{font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);display:inline-block;font-weight:700}:root .ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-tree-switcher-icon,:root .ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-select-switcher-icon{font-size:12px}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-tree-switcher-icon svg,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-select-switcher-icon svg{transition:transform .3s}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-tree-switcher-icon,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-icon{font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);display:inline-block;font-weight:700}:root .ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-tree-switcher-icon,:root .ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-icon{font-size:12px}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-tree-switcher-icon svg,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-icon svg{transition:transform .3s}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-icon svg{transform:rotate(-90deg)}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-select-switcher-loading-icon,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-loading-icon{position:absolute;left:0;display:inline-block;width:24px;height:24px;color:#1890ff;font-size:14px;transform:none}.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_open .ant-select-switcher-loading-icon svg,.ant-select-tree li span.ant-select-tree-switcher.ant-select-tree-switcher_close .ant-select-switcher-loading-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-select-tree .ant-select-tree-treenode-loading .ant-select-tree-iconEle,.ant-select-tree-child-tree{display:none}.ant-select-tree-child-tree-open{display:block}li.ant-select-tree-treenode-disabled>span:not(.ant-select-tree-switcher),li.ant-select-tree-treenode-disabled>.ant-select-tree-node-content-wrapper,li.ant-select-tree-treenode-disabled>.ant-select-tree-node-content-wrapper span{color:#00000040;cursor:not-allowed}li.ant-select-tree-treenode-disabled>.ant-select-tree-node-content-wrapper:hover{background:transparent}.ant-select-tree-icon__open,.ant-select-tree-icon__close{margin-right:2px;vertical-align:top}.ant-select-tree-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-select-tree-dropdown .ant-select-dropdown-search{position:sticky;top:0;z-index:1;display:block;padding:4px;background:#fff}.ant-select-tree-dropdown .ant-select-dropdown-search .ant-select-search__field__wrap{width:100%}.ant-select-tree-dropdown .ant-select-dropdown-search .ant-select-search__field{box-sizing:border-box;width:100%;padding:4px 7px;border:1px solid #d9d9d9;border-radius:4px;outline:none}.ant-select-tree-dropdown .ant-select-dropdown-search.ant-select-search--hide{display:none}.ant-select-tree-dropdown .ant-select-not-found{display:block;padding:7px 16px;color:#00000040;cursor:not-allowed}@-webkit-keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}.ant-tree.ant-tree-directory{position:relative}.ant-tree.ant-tree-directory>li span.ant-tree-switcher,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-switcher{position:relative;z-index:1}.ant-tree.ant-tree-directory>li span.ant-tree-switcher.ant-tree-switcher-noop,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-switcher.ant-tree-switcher-noop{pointer-events:none}.ant-tree.ant-tree-directory>li span.ant-tree-checkbox,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-checkbox{position:relative;z-index:1}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper{border-radius:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper:hover,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper:hover{background:transparent}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper:hover:before,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper:hover:before{background:#f5f5f5}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper.ant-tree-node-selected,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper.ant-tree-node-selected{color:#fff;background:transparent}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper:before,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper:before{position:absolute;right:0;left:0;height:24px;transition:all .3s;content:\"\"}.ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper>span,.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper>span{position:relative;z-index:1}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-switcher,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-switcher{color:#fff}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-checkbox .ant-tree-checkbox-inner,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-checkbox .ant-tree-checkbox-inner{border-color:#1890ff}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked:after,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked:after{border-color:#fff}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner{background:#fff}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after{border-color:#1890ff}.ant-tree.ant-tree-directory>li.ant-tree-treenode-selected>span.ant-tree-node-content-wrapper:before,.ant-tree.ant-tree-directory .ant-tree-child-tree>li.ant-tree-treenode-selected>span.ant-tree-node-content-wrapper:before{background:#1890ff}.ant-tree-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-inner,.ant-tree-checkbox:hover .ant-tree-checkbox-inner,.ant-tree-checkbox-input:focus+.ant-tree-checkbox-inner{border-color:#1890ff}.ant-tree-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:2px;visibility:hidden;-webkit-animation:antCheckboxEffect .36s ease-in-out;animation:antCheckboxEffect .36s ease-in-out;-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;content:\"\"}.ant-tree-checkbox:hover:after,.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox:after{visibility:visible}.ant-tree-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;border-collapse:separate;transition:all .3s}.ant-tree-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5.71428571px;height:9.14285714px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:\" \"}.ant-tree-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after{position:absolute;display:table;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(1) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:\" \"}.ant-tree-checkbox-checked .ant-tree-checkbox-inner{background-color:#1890ff;border-color:#1890ff}.ant-tree-checkbox-disabled{cursor:not-allowed}.ant-tree-checkbox-disabled.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after{border-color:#00000040;-webkit-animation-name:none;animation-name:none}.ant-tree-checkbox-disabled .ant-tree-checkbox-input{cursor:not-allowed}.ant-tree-checkbox-disabled .ant-tree-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;-webkit-animation-name:none;animation-name:none}.ant-tree-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-tree-checkbox-disabled:hover:after,.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-disabled:after{visibility:hidden}.ant-tree-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block;line-height:unset;cursor:pointer}.ant-tree-checkbox-wrapper.ant-tree-checkbox-wrapper-disabled{cursor:not-allowed}.ant-tree-checkbox-wrapper+.ant-tree-checkbox-wrapper{margin-left:8px}.ant-tree-checkbox+span{padding-right:8px;padding-left:8px}.ant-tree-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";display:inline-block}.ant-tree-checkbox-group-item{display:inline-block;margin-right:8px}.ant-tree-checkbox-group-item:last-child{margin-right:0}.ant-tree-checkbox-group-item+.ant-tree-checkbox-group-item{margin-left:0}.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner:after{top:50%;left:50%;width:8px;height:8px;background-color:#1890ff;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;content:\" \"}.ant-tree-checkbox-indeterminate.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-tree{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";margin:0;padding:0}.ant-tree-checkbox-checked:after{position:absolute;top:16.67%;left:0;width:100%;height:66.67%}.ant-tree ol,.ant-tree ul{margin:0;padding:0;list-style:none}.ant-tree li{margin:0;padding:4px 0;white-space:nowrap;list-style:none;outline:0}.ant-tree li span[draggable],.ant-tree li span[draggable=true]{line-height:20px;border-top:2px transparent solid;border-bottom:2px transparent solid;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-khtml-user-drag:element;-webkit-user-drag:element}.ant-tree li.drag-over>span[draggable]{color:#fff;background-color:#1890ff;opacity:.8}.ant-tree li.drag-over-gap-top>span[draggable]{border-top-color:#1890ff}.ant-tree li.drag-over-gap-bottom>span[draggable]{border-bottom-color:#1890ff}.ant-tree li.filter-node>span{color:#ff4d4f!important;font-weight:500!important}.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-loading-icon,.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-loading-icon{position:absolute;left:0;display:inline-block;width:24px;height:24px;color:#1890ff;font-size:14px;transform:none}.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-loading-icon svg,.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-loading-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}:root .ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open:after,:root .ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close:after{opacity:0}.ant-tree li ul{margin:0;padding:0 0 0 18px}.ant-tree li .ant-tree-node-content-wrapper{display:inline-block;height:24px;margin:0;padding:0 5px;color:#000000d9;line-height:24px;text-decoration:none;vertical-align:top;border-radius:2px;cursor:pointer;transition:all .3s}.ant-tree li .ant-tree-node-content-wrapper:hover{background-color:#f5f5f5}.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected{background-color:#bae7ff}.ant-tree li span.ant-tree-checkbox{top:initial;height:24px;margin:0 4px 0 2px;padding:4px 0}.ant-tree li span.ant-tree-switcher,.ant-tree li span.ant-tree-iconEle{display:inline-block;width:24px;height:24px;margin:0;line-height:24px;text-align:center;vertical-align:top;border:0 none;outline:none;cursor:pointer}.ant-tree li span.ant-tree-iconEle:empty{display:none}.ant-tree li span.ant-tree-switcher{position:relative}.ant-tree li span.ant-tree-switcher.ant-tree-switcher-noop{cursor:default}.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon,.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon{font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);display:inline-block;font-weight:700}:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon,:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon{font-size:12px}.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon svg,.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon svg{transition:transform .3s}.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon,.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon{font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);display:inline-block;font-weight:700}:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon,:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon{font-size:12px}.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg,.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon svg{transition:transform .3s}.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg{transform:rotate(-90deg)}.ant-tree li:last-child>span.ant-tree-switcher:before,.ant-tree li:last-child>span.ant-tree-iconEle:before{display:none}.ant-tree>li:first-child{padding-top:7px}.ant-tree>li:last-child{padding-bottom:7px}.ant-tree-child-tree>li:first-child{padding-top:8px}.ant-tree-child-tree>li:last-child{padding-bottom:0}li.ant-tree-treenode-disabled>span:not(.ant-tree-switcher),li.ant-tree-treenode-disabled>.ant-tree-node-content-wrapper,li.ant-tree-treenode-disabled>.ant-tree-node-content-wrapper span{color:#00000040;cursor:not-allowed}li.ant-tree-treenode-disabled>.ant-tree-node-content-wrapper:hover{background:transparent}.ant-tree-icon__open,.ant-tree-icon__close{margin-right:2px;vertical-align:top}.ant-tree.ant-tree-show-line li{position:relative}.ant-tree.ant-tree-show-line li span.ant-tree-switcher{color:#00000073;background:#fff}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-tree-switcher-icon,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-select-switcher-icon{display:inline-block;font-weight:400;font-size:12px}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-tree-switcher-icon svg,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-select-switcher-icon svg{transition:transform .3s}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon{display:inline-block;font-weight:400;font-size:12px}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon svg,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon svg{transition:transform .3s}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon{display:inline-block;font-weight:400;font-size:12px}.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg,.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon svg{transition:transform .3s}.ant-tree.ant-tree-show-line li:not(:last-child):before{position:absolute;left:12px;width:1px;height:100%;height:calc(100% - 22px);margin:22px 0 0;border-left:1px solid #d9d9d9;content:\" \"}.ant-tree.ant-tree-icon-hide .ant-tree-treenode-loading .ant-tree-iconEle{display:none}.ant-tree.ant-tree-block-node li .ant-tree-node-content-wrapper{width:calc(100% - 24px)}.ant-tree.ant-tree-block-node li span.ant-tree-checkbox+.ant-tree-node-content-wrapper{width:calc(100% - 46px)}.ant-typography{color:#000000d9;overflow-wrap:break-word}.ant-typography.ant-typography-secondary{color:#00000073}.ant-typography.ant-typography-success{color:#52c41a}.ant-typography.ant-typography-warning{color:#faad14}.ant-typography.ant-typography-danger{color:#ff4d4f}a.ant-typography.ant-typography-danger:active,a.ant-typography.ant-typography-danger:focus,a.ant-typography.ant-typography-danger:hover{color:#ff7875}.ant-typography.ant-typography-disabled{color:#00000040;cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.ant-typography,.ant-typography p{margin-bottom:1em}h1.ant-typography,.ant-typography h1{margin-bottom:.5em;color:#000000d9;font-weight:600;font-size:38px;line-height:1.23}h2.ant-typography,.ant-typography h2{margin-bottom:.5em;color:#000000d9;font-weight:600;font-size:30px;line-height:1.35}h3.ant-typography,.ant-typography h3{margin-bottom:.5em;color:#000000d9;font-weight:600;font-size:24px;line-height:1.35}h4.ant-typography,.ant-typography h4{margin-bottom:.5em;color:#000000d9;font-weight:600;font-size:20px;line-height:1.4}h5.ant-typography,.ant-typography h5{margin-bottom:.5em;color:#000000d9;font-weight:600;font-size:16px;line-height:1.5}.ant-typography+h1.ant-typography,.ant-typography+h2.ant-typography,.ant-typography+h3.ant-typography,.ant-typography+h4.ant-typography,.ant-typography+h5.ant-typography{margin-top:1.2em}.ant-typography div+h1,.ant-typography ul+h1,.ant-typography li+h1,.ant-typography p+h1,.ant-typography h1+h1,.ant-typography h2+h1,.ant-typography h3+h1,.ant-typography h4+h1,.ant-typography h5+h1,.ant-typography div+h2,.ant-typography ul+h2,.ant-typography li+h2,.ant-typography p+h2,.ant-typography h1+h2,.ant-typography h2+h2,.ant-typography h3+h2,.ant-typography h4+h2,.ant-typography h5+h2,.ant-typography div+h3,.ant-typography ul+h3,.ant-typography li+h3,.ant-typography p+h3,.ant-typography h1+h3,.ant-typography h2+h3,.ant-typography h3+h3,.ant-typography h4+h3,.ant-typography h5+h3,.ant-typography div+h4,.ant-typography ul+h4,.ant-typography li+h4,.ant-typography p+h4,.ant-typography h1+h4,.ant-typography h2+h4,.ant-typography h3+h4,.ant-typography h4+h4,.ant-typography h5+h4,.ant-typography div+h5,.ant-typography ul+h5,.ant-typography li+h5,.ant-typography p+h5,.ant-typography h1+h5,.ant-typography h2+h5,.ant-typography h3+h5,.ant-typography h4+h5,.ant-typography h5+h5{margin-top:1.2em}a.ant-typography-ellipsis,span.ant-typography-ellipsis{display:inline-block}a.ant-typography,.ant-typography a{color:#1890ff;outline:none;cursor:pointer;transition:color .3s;text-decoration:none}a.ant-typography:focus,.ant-typography a:focus,a.ant-typography:hover,.ant-typography a:hover{color:#40a9ff}a.ant-typography:active,.ant-typography a:active{color:#096dd9}a.ant-typography:active,.ant-typography a:active,a.ant-typography:hover,.ant-typography a:hover{text-decoration:none}a.ant-typography[disabled],.ant-typography a[disabled],a.ant-typography.ant-typography-disabled,.ant-typography a.ant-typography-disabled{color:#00000040;cursor:not-allowed}a.ant-typography[disabled]:active,.ant-typography a[disabled]:active,a.ant-typography.ant-typography-disabled:active,.ant-typography a.ant-typography-disabled:active,a.ant-typography[disabled]:hover,.ant-typography a[disabled]:hover,a.ant-typography.ant-typography-disabled:hover,.ant-typography a.ant-typography-disabled:hover{color:#00000040}a.ant-typography[disabled]:active,.ant-typography a[disabled]:active,a.ant-typography.ant-typography-disabled:active,.ant-typography a.ant-typography-disabled:active{pointer-events:none}.ant-typography code{margin:0 .2em;padding:.2em .4em .1em;font-size:85%;background:rgba(150,150,150,.1);border:1px solid rgba(100,100,100,.2);border-radius:3px}.ant-typography kbd{margin:0 .2em;padding:.15em .4em .1em;font-size:90%;background:rgba(150,150,150,.06);border:1px solid rgba(100,100,100,.2);border-bottom-width:2px;border-radius:3px}.ant-typography mark{padding:0;background-color:#ffe58f}.ant-typography u,.ant-typography ins{text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.ant-typography s,.ant-typography del{text-decoration:line-through}.ant-typography strong{font-weight:600}.ant-typography-expand,.ant-typography-edit,.ant-typography-copy{color:#1890ff;text-decoration:none;outline:none;cursor:pointer;transition:color .3s;margin-left:4px}.ant-typography-expand:focus,.ant-typography-edit:focus,.ant-typography-copy:focus,.ant-typography-expand:hover,.ant-typography-edit:hover,.ant-typography-copy:hover{color:#40a9ff}.ant-typography-expand:active,.ant-typography-edit:active,.ant-typography-copy:active{color:#096dd9}.ant-typography-copy-success,.ant-typography-copy-success:hover,.ant-typography-copy-success:focus{color:#52c41a}.ant-typography-edit-content{position:relative}div.ant-typography-edit-content{left:-12px;margin-top:-5px;margin-bottom:calc(1em - 5px)}.ant-typography-edit-content-confirm{position:absolute;right:10px;bottom:8px;color:#00000073;pointer-events:none}.ant-typography-edit-content textarea{-moz-transition:none}.ant-typography ul,.ant-typography ol{margin:0 0 1em;padding:0}.ant-typography ul li,.ant-typography ol li{margin:0 0 0 20px;padding:0 0 0 4px}.ant-typography ul{list-style-type:circle}.ant-typography ul ul{list-style-type:disc}.ant-typography ol{list-style-type:decimal}.ant-typography pre,.ant-typography blockquote{margin:1em 0}.ant-typography pre{padding:.4em .6em;white-space:pre-wrap;word-wrap:break-word;background:rgba(150,150,150,.1);border:1px solid rgba(100,100,100,.2);border-radius:3px}.ant-typography pre code{display:inline;margin:0;padding:0;font-size:inherit;font-family:inherit;background:transparent;border:0}.ant-typography blockquote{padding:0 0 0 .6em;border-left:4px solid rgba(100,100,100,.2);opacity:.85}.ant-typography-single-line{white-space:nowrap}.ant-typography-ellipsis-single-line{overflow:hidden;text-overflow:ellipsis}a.ant-typography-ellipsis-single-line,span.ant-typography-ellipsis-single-line{vertical-align:bottom}.ant-typography-ellipsis-multiple-line{display:-webkit-box;overflow:hidden;-webkit-line-clamp:3;-webkit-box-orient:vertical}.ant-typography-rtl{direction:rtl}.ant-typography-rtl .ant-typography-expand,.ant-typography-rtl .ant-typography-edit,.ant-typography-rtl .ant-typography-copy{margin-right:4px;margin-left:0}.ant-typography-rtl .ant-typography-expand{float:left}div.ant-typography-edit-content.ant-typography-rtl{right:-12px;left:auto}.ant-typography-rtl .ant-typography-edit-content-confirm{right:auto;left:10px}.ant-typography-rtl.ant-typography ul li,.ant-typography-rtl.ant-typography ol li{margin:0 20px 0 0;padding:0 4px 0 0}.ant-upload{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\";outline:0}.ant-upload p{margin:0}.ant-upload-btn{display:block;width:100%;outline:none}.ant-upload input[type=file]{cursor:pointer}.ant-upload.ant-upload-select{display:inline-block}.ant-upload.ant-upload-disabled{cursor:not-allowed}.ant-upload.ant-upload-select-picture-card{display:table;float:left;width:104px;height:104px;margin-right:8px;margin-bottom:8px;text-align:center;vertical-align:top;background-color:#fafafa;border:1px dashed #d9d9d9;border-radius:2px;cursor:pointer;transition:border-color .3s ease}.ant-upload.ant-upload-select-picture-card>.ant-upload{display:table-cell;width:100%;height:100%;padding:8px;text-align:center;vertical-align:middle}.ant-upload.ant-upload-select-picture-card:hover{border-color:#1890ff}.ant-upload.ant-upload-drag{position:relative;width:100%;height:100%;text-align:center;background:#fafafa;border:1px dashed #d9d9d9;border-radius:2px;cursor:pointer;transition:border-color .3s}.ant-upload.ant-upload-drag .ant-upload{padding:16px 0}.ant-upload.ant-upload-drag.ant-upload-drag-hover:not(.ant-upload-disabled){border-color:#096dd9}.ant-upload.ant-upload-drag.ant-upload-disabled{cursor:not-allowed}.ant-upload.ant-upload-drag .ant-upload-btn{display:table;height:100%}.ant-upload.ant-upload-drag .ant-upload-drag-container{display:table-cell;vertical-align:middle}.ant-upload.ant-upload-drag:not(.ant-upload-disabled):hover{border-color:#40a9ff}.ant-upload.ant-upload-drag p.ant-upload-drag-icon{margin-bottom:20px}.ant-upload.ant-upload-drag p.ant-upload-drag-icon .anticon{color:#40a9ff;font-size:48px}.ant-upload.ant-upload-drag p.ant-upload-text{margin:0 0 4px;color:#000000d9;font-size:16px}.ant-upload.ant-upload-drag p.ant-upload-hint{color:#00000073;font-size:14px}.ant-upload.ant-upload-drag .anticon-plus{color:#00000040;font-size:30px;transition:all .3s}.ant-upload.ant-upload-drag .anticon-plus:hover,.ant-upload.ant-upload-drag:hover .anticon-plus{color:#00000073}.ant-upload-picture-card-wrapper{display:inline-block;width:100%}.ant-upload-picture-card-wrapper:before,.ant-upload-picture-card-wrapper:after{display:table;content:\"\"}.ant-upload-picture-card-wrapper:after{clear:both}.ant-upload-list{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:\"tnum\"}.ant-upload-list:before,.ant-upload-list:after{display:table;content:\"\"}.ant-upload-list:after{clear:both}.ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-1{padding-right:14px}.ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-2{padding-right:28px}.ant-upload-list-item{position:relative;height:22px;margin-top:8px;font-size:14px}.ant-upload-list-item-name{display:inline-block;width:100%;padding-left:22px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-upload-list-item-name-icon-count-1{padding-right:14px}.ant-upload-list-item-card-actions{position:absolute;right:0;opacity:0}.ant-upload-list-item-card-actions.picture{top:25px;line-height:1;opacity:1}.ant-upload-list-item-card-actions .anticon{padding-right:6px;color:#00000073}.ant-upload-list-item-info{height:100%;padding:0 12px 0 4px;transition:background-color .3s}.ant-upload-list-item-info>span{display:block;width:100%;height:100%}.ant-upload-list-item-info .anticon-loading,.ant-upload-list-item-info .anticon-paper-clip{position:absolute;top:5px;color:#00000073;font-size:14px}.ant-upload-list-item .anticon-close{display:inline-block;font-size:12px;font-size:10px \\\t;transform:scale(.83333333) rotate(0);position:absolute;top:6px;right:4px;color:#00000073;line-height:0;cursor:pointer;opacity:0;transition:all .3s}:root .ant-upload-list-item .anticon-close{font-size:12px}.ant-upload-list-item .anticon-close:hover{color:#000000d9}.ant-upload-list-item:hover .ant-upload-list-item-info{background-color:#f5f5f5}.ant-upload-list-item:hover .anticon-close,.ant-upload-list-item:hover .ant-upload-list-item-card-actions{opacity:1}.ant-upload-list-item-error,.ant-upload-list-item-error .anticon-paper-clip,.ant-upload-list-item-error .ant-upload-list-item-name{color:#ff4d4f}.ant-upload-list-item-error .ant-upload-list-item-card-actions{opacity:1}.ant-upload-list-item-error .ant-upload-list-item-card-actions .anticon{color:#ff4d4f}.ant-upload-list-item-progress{position:absolute;bottom:-12px;width:100%;padding-left:26px;font-size:14px;line-height:0}.ant-upload-list-picture .ant-upload-list-item,.ant-upload-list-picture-card .ant-upload-list-item{position:relative;height:66px;padding:8px;border:1px solid #d9d9d9;border-radius:2px}.ant-upload-list-picture .ant-upload-list-item:hover,.ant-upload-list-picture-card .ant-upload-list-item:hover{background:transparent}.ant-upload-list-picture .ant-upload-list-item-error,.ant-upload-list-picture-card .ant-upload-list-item-error{border-color:#ff4d4f}.ant-upload-list-picture .ant-upload-list-item-info,.ant-upload-list-picture-card .ant-upload-list-item-info{padding:0}.ant-upload-list-picture .ant-upload-list-item:hover .ant-upload-list-item-info,.ant-upload-list-picture-card .ant-upload-list-item:hover .ant-upload-list-item-info{background:transparent}.ant-upload-list-picture .ant-upload-list-item-uploading,.ant-upload-list-picture-card .ant-upload-list-item-uploading{border-style:dashed}.ant-upload-list-picture .ant-upload-list-item-thumbnail,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail{position:absolute;top:8px;left:8px;width:48px;height:48px;font-size:26px;line-height:54px;text-align:center;opacity:.8}.ant-upload-list-picture .ant-upload-list-item-icon,.ant-upload-list-picture-card .ant-upload-list-item-icon{position:absolute;top:50%;left:50%;font-size:26px;transform:translate(-50%,-50%)}.ant-upload-list-picture .ant-upload-list-item-image,.ant-upload-list-picture-card .ant-upload-list-item-image{max-width:100%}.ant-upload-list-picture .ant-upload-list-item-thumbnail img,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail img{display:block;width:48px;height:48px;overflow:hidden}.ant-upload-list-picture .ant-upload-list-item-name,.ant-upload-list-picture-card .ant-upload-list-item-name{display:inline-block;box-sizing:border-box;max-width:100%;margin:0 0 0 8px;padding-right:8px;padding-left:48px;overflow:hidden;line-height:44px;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-upload-list-picture .ant-upload-list-item-name-icon-count-1,.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-1{padding-right:18px}.ant-upload-list-picture .ant-upload-list-item-name-icon-count-2,.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-2{padding-right:36px}.ant-upload-list-picture .ant-upload-list-item-uploading .ant-upload-list-item-name,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-name{line-height:28px}.ant-upload-list-picture .ant-upload-list-item-progress,.ant-upload-list-picture-card .ant-upload-list-item-progress{bottom:14px;width:calc(100% - 24px);margin-top:0;padding-left:56px}.ant-upload-list-picture .anticon-close,.ant-upload-list-picture-card .anticon-close{position:absolute;top:8px;right:8px;line-height:1;opacity:1}.ant-upload-list-picture-card.ant-upload-list:after{display:none}.ant-upload-list-picture-card-container,.ant-upload-list-picture-card .ant-upload-list-item{float:left;width:104px;height:104px;margin:0 8px 8px 0}.ant-upload-list-picture-card .ant-upload-list-item-info{position:relative;height:100%;overflow:hidden}.ant-upload-list-picture-card .ant-upload-list-item-info:before{position:absolute;z-index:1;width:100%;height:100%;background-color:#00000080;opacity:0;transition:all .3s;content:\" \"}.ant-upload-list-picture-card .ant-upload-list-item:hover .ant-upload-list-item-info:before{opacity:1}.ant-upload-list-picture-card .ant-upload-list-item-actions{position:absolute;top:50%;left:50%;z-index:10;white-space:nowrap;transform:translate(-50%,-50%);opacity:0;transition:all .3s}.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-eye,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-download,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-delete{z-index:10;width:16px;margin:0 4px;color:#ffffffd9;font-size:16px;cursor:pointer;transition:all .3s}.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-eye:hover,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-download:hover,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-delete:hover{color:#fff}.ant-upload-list-picture-card .ant-upload-list-item-info:hover+.ant-upload-list-item-actions,.ant-upload-list-picture-card .ant-upload-list-item-actions:hover{opacity:1}.ant-upload-list-picture-card .ant-upload-list-item-thumbnail,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail img{position:static;display:block;width:100%;height:100%;-o-object-fit:cover;object-fit:cover}.ant-upload-list-picture-card .ant-upload-list-item-name{display:none;margin:8px 0 0;padding:0;line-height:1.5715;text-align:center}.ant-upload-list-picture-card .anticon-picture+.ant-upload-list-item-name{position:absolute;bottom:10px;display:block}.ant-upload-list-picture-card .ant-upload-list-item-uploading.ant-upload-list-item{background-color:#fafafa}.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info{height:auto}.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info:before,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info .anticon-eye-o,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info .anticon-delete{display:none}.ant-upload-list-picture-card .ant-upload-list-item-uploading-text{margin-top:18px;color:#00000073}.ant-upload-list-picture-card .ant-upload-list-item-progress{bottom:32px;padding-left:0}.ant-upload-list .ant-upload-success-icon{color:#52c41a;font-weight:700}.ant-upload-list .ant-upload-animate-enter,.ant-upload-list .ant-upload-animate-leave,.ant-upload-list .ant-upload-animate-inline-enter,.ant-upload-list .ant-upload-animate-inline-leave{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:cubic-bezier(.78,.14,.15,.86);animation-fill-mode:cubic-bezier(.78,.14,.15,.86)}.ant-upload-list .ant-upload-animate-enter{-webkit-animation-name:uploadAnimateIn;animation-name:uploadAnimateIn}.ant-upload-list .ant-upload-animate-leave{-webkit-animation-name:uploadAnimateOut;animation-name:uploadAnimateOut}.ant-upload-list .ant-upload-animate-inline-enter{-webkit-animation-name:uploadAnimateInlineIn;animation-name:uploadAnimateInlineIn}.ant-upload-list .ant-upload-animate-inline-leave{-webkit-animation-name:uploadAnimateInlineOut;animation-name:uploadAnimateInlineOut}@-webkit-keyframes uploadAnimateIn{0%{height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateIn{0%{height:0;margin:0;padding:0;opacity:0}}@-webkit-keyframes uploadAnimateOut{to{height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateOut{to{height:0;margin:0;padding:0;opacity:0}}@-webkit-keyframes uploadAnimateInlineIn{0%{width:0;height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateInlineIn{0%{width:0;height:0;margin:0;padding:0;opacity:0}}@-webkit-keyframes uploadAnimateInlineOut{to{width:0;height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateInlineOut{to{width:0;height:0;margin:0;padding:0;opacity:0}}.voice_chat[data-v-1c392dd0]{width:1200px;height:410px;background:#FFFFFF;position:relative}.voice_chat .voice_chat_wrapper[data-v-1c392dd0]{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute}.voice_chat .voice_chat_wrapper .voice_chat_btn[data-v-1c392dd0]{width:116px;height:116px;margin-left:54px;border-radius:50%;cursor:pointer;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAQMElEQVR4nO2de3xU5ZnHv8+ZyYUkJIGEgNwSLpKEKJgMwmqpBlArXW3tVv1Q78qnunbFC9XWlbqrtVpFilY+2lqrYFFWrVK3VUHFLO3qtkguiIaEi5gJF5UQLrmRkJnz7B+TBEJIyFzPGZjvXzNz3ssv+c175r0873uEKKagoDJeEpLHeSEPlQkqmivIKJAU0GSBZIVBQHJHlmaB/QrNIM2gTSC1qG5BdIsDqrWt+fPKyoLDVv5dwSBWC/CHCZN3jHAY5kwVnSHIdGAM4AxxNR5Et6vykYGUeFVKNleM3h3iOsKGrQ11uUrjWs2s2aahs1FmALkWSdmMaomKrEqWutVlZVPaLdJxQmxp6MTJ7gJ1cq0qNwpkWa3nGPYL/FGE5ZVl2R9aLeZYbGPoWNfnaQnqvAW4Aci3WE5/qQKWtYnn2e1l4w5aLQZsYOgE1+5Mp7bfpnA7vg5MNNKoylIx9NGqspwvrRRimaFnTNs+1Otx3IUyD0iySkeIaVbleY/X8fi2jSN3WiEg4oa6XKVxLQz5EcrDHBlOnGwcEljYkmo+WrN2TGskK46oobmumhmGytNEz29ksGwzMOZVlo9aHakKI2LohMk7Rjgc5mLgykjUZ0NeNVXmR2I8G3ZD84rclwgsAzLCXZfNOaiqc6srct4IZyVhM7S4WJ17Gmp/pnA/YISrnihDVVniONx0T7imF8Ni6Bln7xrl9XpeAc4NR/nRjsJ608GcLeuzt4e67JAbml9Yex7onxAGh7rskwpln4hctql89P+GstiQ3goLCmu/g+jqmJn9QBis6PsFhe7LQ1lsyAzNc7mvN0XfAAaEqsxTgARTeCWvyH1zqAoMiaH5Lvcdoiwl9EtZpwIOgd9OLHI/EIrCgjY0v6h2AcqT2GBeOIoRhf+cWFR7X9AFBZM5v9B9HcKyYMuJ0YUienNVWc7vAy0gYCPyityXCqwkdpsNNV5Fr6wuz1kZSOaADM0rrDlHRNZw8qyS2I1DgnwrkCGN34bmF27PRhwVRO/aZbRQb4inqLJsXK0/mfzqFLlcpXGIYwUxMyNBhqmO1woKKuP9yeSXoYfIfJTYdF4EkWlmQspDfuXob8L8KTXfxpS3/MkTIySooXJZZcXoP/cncb/M6YiH3Rib0rOMvYhO6k+8Ur9uuQ6HuThmpqVkimks6k/CE7bQ/CnuCzF5L3hNMYJFlAs2VWR/0Geavi4WFFTGmwkpG7EuYj1Gd7a2Nxw+c9u209t6S9DnLdebmHIvMTPtxOnOtPj5fSXotYV2BHZtJbYcZjdaEB3fWwep1xbqcJh3EzPTjiSpGr220uO20LypOzPE460BUsKlKkZQNHslLmdL2fC9x144fgv1eOYTM9POJDvN9nnHu9CjhXbsAqsB0sOtKlykpxlcODOJ4vMGkD3KSUaGg9ZWZU+dl49LW3m/pIWNn0XtJu1ODiaYZs6GDWMOHP1hD0Pzi9w/AR6LmKwQEh8v3HjtQOZen0pKct9zJv+3rpWFi/ezZZtt9+6eEBG9Z1NZTrcJh56GutyfoRRETlZoGDzYwVOLMimanND12c5dHso3tFG/z0tiosHYMU5cZyXgdPr+7NZW5T8e2sdbq5utkh0sm6rKs7t51c3Qgik7ppqmuS6ymoInOclgxbKhnD4uDoBPPm3jV08doLS85/g7LdVg7vWpXHfVQOLjBVX48b/vZfX7LZGWHRpEXVVlOeWdb7vdl9TUayOvKHgefmBwl5krXmvkmrlfH9dMgIMNJouXHOCmf93D/gMmIvDIgxmMGxsXScmhQ6WbZ12GulylcYrOibyi4Jg2JZGLZvkiYd55t4WHF+7H6z1xvvJP2pj34zra25XEBOGnd0Xnmr3CVS5Xade3scvQVjNrNpBpiaoguGVuKuBreQ89ug/V/uct39DGy682ATD93ERyJ/gVHGALBLJayLyo832Xoaahs62RFDjpaQZnuxIB+OPKJg42mH6X8fyLDXg7sl18QXTGvIkaF3e+Puo3VGdaISYYJp+ZgMPhe13y10MBlVG/z8vGT9s6you+FgqgR3lnAOQW1g5HZYJ1kgIja4ij6/UXNYGPJ2tqPQCMGB61IcYTcwtrh0OHoQY6y1o9gZGWduQG09jk/+22k4MHfXkHDozefclimMXQYaiKzrBUTYCEKlpN8aMnZVPElBnQYagI37BWToxgEWE6gFFQUBmPylirBcUIDoXxLldpnEF8ynhiG45OBpxNMnisYYrGYoZOEpxeZ66hIjFDTxJMMXMNQ2NRfScNYuQaqoywWkeMEKGabSAy0GodMUJGhoGorQ2dc3kKTy7MZGiW48SJw8SFM5N4evEQJoy3+5qpZBiovaP77r5jEBfNSuKyS607Wvf2W9OYcf4ArrrS1t99QAcaKLZW2dTsm2cdadHEuWEcmbTv1GJjEgzE3i20dodvJWTMmJ63O4/nyOv4+MBnduM7gsba2nrO6Q4b6iQx0Xe9dqenx3WbkWD75YVN1b742Ym58T1M+/LrI//go5fS/GV4Rwusq+sZuzLpjCNrpFXV9o/lNVCarBbRF+tKfUe2JyZKjwXoL9xHDJ3aEbngL06nUNgR+vn5Fz3XVM+Z5iu3sdFkU5XtDW0zEBqtVtEXpWVtXUFf50ztbtqWrYfZuctn6r98N7BO06ziAaR3rKv+z996Rj101rm+rK0rVMXGtBmIvVtoY5PJJ5/5QkQumZ2McXTQjMLKP/uCpM+alMAlF/tnalKSMH+eb8fHnjovf/uwu6FFZyUwcoTvdvzh3wMLcYkwDQYqtm6hAG+86fvOjRzh5Jvndt/h+OLLDXy9x9eEH/zZYM4s6F9cUFyc8PjDmYwa6TNsyW8P0npMp2jOFb7+Ymur8s57URGIXW+gantDV73b0hXRd/Wc7qOsQ4eUe++vx+NRBgwQXvzdUL73ne4t+VhGjXSy9NksZpzn+3K890ELK/+7+40qa4iDi2b6ogDfXt1MQwARhRFHqXdkDb9rJnCW1Vr6wuOFQekGhZMTGD3KyYaNbew4agixa7eHHbu8FH9zAAkJwqziJGYVDyApycA0FREYOtTJ2UWJ/PDGVB64b3DX2HLd+lbm37uX9mP6Qwt+OpiC/HhU4f6H9rG3vh/R21ZjyFrJc7nvFeWXVms5EelpBqvfHE5qqsH2mnauuOYrDh3qfossOiuBhb/IYPhpJ56E8HrhpVcaWfTrnpH2U12JLH02CxF4e3UL9yzosa/WpuhPHEOGz88EbL8ForVNaTmknDd9AIPSHQzLcvLB2u4dlS+/8vLK600cOGgyZIiTzIyeY9PGRpN317Rwz4J63lrV3CPSPmOwg+d/k0VyskFTs8ntd9fR1BwdQWSKLJEzimryvcgmq8X0BxF45skhnD/d99v33LIGnlhyoNf0pw1zkpPtZEimg8Ymk7o6L9Vb2vF4jm/QoHSDF36T1bUl4p4Fe3l7dVR0hgBQryNXOs4iaiZK4orS0wxeemEoY3N8U4Gvvt7Eo7/aT9vh4FrR2Jw4nlyYyfiOXWwvvtzIY4v3B603grQnSV2yAOS7ajZHU+R81hAHf3huKKNH+b6D1ZsP88ii/b1uIeyL+HhhzuUp3H5rOklJvqnF11Y28eAj/m18shqB6k3l2fkCkFdU84IgN1otyh/S0wwW/TKTc6cdmT36x8etvPlWMyVrD51wZSQn28m3L0rm+5clc9ow3xfDa8ITSw6wdHlDVJkJgPL7qorsH/paaKH7WoQ/WK3JXxwG/ODKgdx2SxqpqUcGnl4Tamraqd7SzoEDXhqaTOKcQupAg9OGOcjPi+/RYaqsOszDC/ezYaP/rdwOqOjV1WU5KwR8m5UM0V1WiwqUQekGV34/hSu+l9KvIcvRfFzWyorXmlhT0oIZBXMHvaCIjqgqy/myaz0qv8hdTZSf62cYkJ8bz1RXIgUT4xkx3MHYnLiuTUi7dnvYucuDe4eHik/a+Pu6VvYcZ8ksCuk6POPI11m1hCiP0TVN362z8qhlrptvSuXOf/NNwF94adifx2oJgpR0vu764VGRVdbIiREsaphd3nUZOix19CqUr62RFCNQFPYk6d73O993Gbp2rXjU4DVrZMUIFEFfLiub0rW00K1L6PDKctPQ4x4KaCdmFQ/wrYv2Iy5sYu6R9dEHFvTv2PzWVuXlVxrZscv2QWGIwfJu749NkF/k/hQ4I2KK/MTpFMo/Gtl1vFu4eOfdFu6+z/arLD2OhjveoG05Nj680eNR/vSXZv5pamBBYf3B9MK7a+w/KS+iS3t8duwH46dtTY1rj3cTxcerniIc93jVHoEa29ad3qDoM5HTFSMQRPn1sWZCbydaO52Lwd7RgKc4zR4jbsnxLhzX0OqPR9aDPhdeTTGC4JnjnTcPfTwVwlRjERAVwainGM2Gw1zc28VeDd1cMXo3orYPHjvVUOEXlevHfNXb9T43KxmtzY8JVIdeVoyAEN3iOXj4ib6S9GloZWXBYVVsP3N0qmAot/b13DPox+Mmqyqy10BsjtdqRGVFZXlOyYnS9Wt/qKlyF1AftKoYgbJXDfPu/iTsl6GbK0bvxtDr4CQ4tjL6UENlbn+e7gt+PFS9qjTnHVHptbscI0wIC/v7/G3ww1CArLRR94rykf+qYgSGrkui7n5/cvi9BpVfuD0bHOWxZ3KHnXqHw1n42foRO/zJ5PehGVUVY92I+c9A1D5fKgo4ZAiX+WsmBGAoQFX5mH8o/ACw/5J+9OFV9JrKsuwPA8kc8LE21eXZf0G5iVjPN5QoqrdUl+esDLSAoM4pqqrIXi7Iz4IpI8YRVFhQVZHzfDBlhCQwJ9/lvgPliVCVdwqiAj/fVJ79QLAFhcyA/EL3dQjPEyX7TG2EV+HW6vLskKw/h7RF5RW5LxV4FRhwwsQxANpU9erqipw3QlVgyG+RBS73dFN5E8gIddknGfWmwXc3l2aHdKIm5Ic3VpZlf+hwOAtjM0p9oHxsevTsUJsJYTAU4LP1I3ZkpY0uFngQiN5dl6FHVXkqyaibvnljzhfhqCDsvdL8QvcFwEsIQ8Ndl83Zi6HXV5XmvBPOSsJ+Xm5VRfYaDC1E9L/CXZddEZUViE4Kt5kQ4XFjXuGO88Uwn0YpOHHqk4KtKnJbddno9yJVYURPtK6uGPXXJOoKEe7k5A7kbhF4sL3h8JmRNBMsnNmZNGlblscZ9yOFO4E0q3SEmCZVXlDksc0Voy3Z/2/5VF3e1J0Zhsc7T5V5UbzG2ojwjDocj/t2HViH5YZ2Mn7a1tR4T9zNitwQNb+xQqWgyw4723+3bd3pDVbLARsZejQTJ7sL1Mm1mNxgu+GOsk+E10VYHuiaZTixpaGdFBer8+tG97dQYzboTCDfIimbBClRw1w1NCX7vbVrxbYL+7Y29FjyXTWniTJTxZghqt9QGAeE+oFk7QKfq8hHilniMLSkr70kdiOqDD0Wl6s0rkkGj3V4nHlqaC4iEzB1NAZDUDKAFHyGdz49qgloB5oQ6jGpw5Ba1NwsprHF6/RUp+i+7UefKhJt/D+IYnHePFNWNgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:116px 116px;margin-bottom:17px}.voice_chat .voice_chat_wrapper .voice_chat_btn[data-v-1c392dd0]:hover{width:116px;height:116px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAP8UlEQVR4nO2de3hU5Z3HP79zZjLJTC6EIFRYQO4gaOuNeqsVdLXU6urzaJddvFW3cb2gJnENSPvstKsmRAm2VNfauvIs1npF65WqxaqAt/WGV1BAUMFaEiDJTJKZOee3f5zcE0LmlpmJ83mePJPJnPO+v8n3/N7zvr/3955XyGD8fs3ZG2yaJIY5XbCniso0hLEK+YCv7ae47RUgAOxpew0INCnsAN2sGJvVtj4e5s3f4vdLKDXfKH4k1QZEQ9mS4BjDtudiyxxb9ERBJgCuBFcTAd0qKusVXetSWVtT49uZ4DqSRloLWlqq7vyS4DxR5oHMUXRaKuwQZJOKrlWbZwJ7vGvuukvCqbBjIKSloGWVjTNFzAtAfwKMTLU9Pdij8JChxqplS/PWpdqYnqSNoJWV9UURI+cyVbkYmJFqewbIRyK60mWHfrt06fB9qTYG0kDQioqGEeo2rwKuxunAZCDSCPY9tiHVt93s25VSS1JV8TU3NI0ybaMMdCHgTZUdCSYAerfLNm6pqfF+kQoDBl3Q0lJ1FxQ3X6GiN9E5nBhqNAM1hbnear9fWgaz4kEVtPyGxjnYxu1kzj0yXj5VdOHy6vw1g1XhoAjaNn6sVZUfD0Z96Yc+4LKlfDDGs0kXtHxx4EeirFQoSXZdac4+kEtrq72PJLOSpAnq96uroSX4M+DngJGsejIMBV1RmOv7j2SFF5MiaPmS4FgsvR84PhnlDwHeUMz5y6tztya64IQLWlHZfJIa9qMowxNd9pBCqFeMs5dX5b2cyGIT2hSWLw6cpWKvyYo5AJThovZzFYuD5yay2IQJWra46SKUR4C8RJX5DcCjqvdXLAqUJqrAhAhaURm8RlTuIfFTWd8ETIU7yxcF/IkoLG5ByxcFlqjobaRBXDiDEeA/KyoDNySioJgpr2y6EJGV8ZaTpQMVKF1W7ft9rAXELERZZeBMEVaTbWYTjSUiP15W5V0dy8kxCXrt4uBxhurzDJ1ZknSjWcU4PZYhTdSCVixpHq+W/TYZO3eZGQjURdQ48ldL83ZEc15UnaLSUnWrZd9HVsyko1BiiP2g36850ZwXlaD5xYFqsuG8QUPguw3Nzf8V5TkDo3xx4IcoT0ZzTpaEoAhn11b5Hh/IwQMSp2xJcIzYujEb0ksZu22DwweSrzSgJtew7dqsmCllhKFy60AOPKCHVlzf9I9qyLPx25Qlbgw9tfbm/L/0e0h/H/r9moNhrEisVVliRW3+e+FC9fR3TL+C7msOLkrV8oMsvRFkitsXKO//mP1QtiQ4Riz9hOx0WLoRtA0m76+DtF8PlYh9HVkx0xGvYcl+vbRPD71ycUOJR83PcNZZZkk/AhK2Dlm2rHB3zw/69NAczHKyYqYzPnLMhX190MtDKyvri8J4PkMYlmyrkoXPKxw20+TQGSYjSoSCfCEcgX37lC3bLDa+b7HjczvVZsbLPjs3dMht/uK9Xf/Yay4zYuRchmammC4XnPw9N3O+7yLX0/tuUlQojBtrMOckN5s/sXj86TC7vspYYYuMVve/Ad0CDr0EVZULB82kBJKfL1x8vocJ4zvvIvV7lG2fWTQ2KW63MGqkMGG8iWnC1CkmV19h8tDqEG+9E0mh5XGg8hN6CNrtMi67PjhbDH1tUI1KAB6PcPXlHr41yhFz+w6bJ9eE2Lqtt/d5vcKck1ycdIIblwtU4d77W3lnozXYZicE2+Co2272vdX+vlunSAy9YPBNip/55+Z0iLn+lQi/+W1Ln2ICBIPKU2vC3Pn7FgIBRQTmn+th1MjMXK1hWN016/gWpaXqBuYPukVxMnmiyeGzTADeftfi0SdC2AO4LW7bbnPPva1YFrjdcNYZ7iRbmiRE/rVNO6CLoPklwXnAiJQYFQenznW6AcGgsvrxEKoDP3fbZzbrXnHun9Onmow+OCO9dGRhcfC09jcd38B5dExm4fMKkyY43vnqGxGCwSjUbOOFF8MdHv3tw8xEmjdo2MIP2n/vEFTRuakxJ3bGjTMw2r7BBx/G1qlpbNKOMen4cRnpoQAd2hkA118fGA0yNXX2xEZRQWcn/evd0XtnO3/f7Qg6fFjGCnqoo2GboJapp6TWntjwejsFbW6OXdBgs/Oam8FTEWHRk6G9ybVlTiqNiZkEpatpND2pNEXE0dAAUNETUmtOlviREwEMJ5FXJqbanCzxopNLS9VtNLY2TSa74Ggo4Mob1jjRsNXM5gwNEUzTnGYYamcFHSKo6jRDRbKCDhFEZZqBMCbVhmRJDCKMN1AKUm1IlsSgUGJAegt6/LEuLlrgoagwdYveDptpcsmFHg7+VtqHBksM0jy770fzcjh8lskxR6VuZDXvNDczZ5iccGzaj+4KDCS9PbS1xQnLDR+eGg8VgeJixzNbWtM+ROgx0PT20N11zj9x5EG9mzu7y4yZOw7ncZnOxRLpI1dsWJGQ05YPUFefCYKmOV/sdKa2xow2cPUQbe++zlyTwjjuscXFzrkNDb0F6zpH+uXO9E/5NBCaUm1Ef3y6xXHDHDeMH9v9+vv6750CTJoYW7aBacIhbamff/u6t2BTJjvlNrcoX3yZ9oK2GiiNqbaiP7ZssztSRNr/ue3s+sqmfo8j6uyjY2tzZx1q4mubV/3go95ZD1Pb6tyy1R5Q8lmKaTUgvT20pUXZ3pYictQRLqRLy6oKr/+fc+M7ZJzBkd+JTlRPDpxxuvPUmIYG5aNN3QWdcIjB8LbmeNMnGZG322BAensowOtvOKINLxamT+vupS+uC7Ov7d533jk5jBs7sG6BacKC+R5KShzB1jwXJtxjR7Pjv+tcIKGwkyKa9ih1BpL+gr69sTOj73vHdffCUAjueyCEZUFODlz+01xmH9Xdk3tSUiJc/tNcZs5wLo6N71u8/mb3Lm5hoXD4LKeut9+NxJXiMmgY1JnHnbhkLvCdVNvSH7YNPp+zLmVEicH2HXa3IUT9HqWuXpk5w8Ttcu6Lsw418eQItjpjyaIig0kTDE452c25Z3s6mtJPt1j87x+dhOuunHNWDmPHGKjCg6tDNDZmgKDKX12iukn7u5zThBdejHDsMS7y8oSzz3Sz/DcWoS77Krz1ToQ9e20W/LOH4mHC6IONtsTpvjPibRvWbYjwxDO9M+0nTTQ5+gjHO9/ZaGXEcAVARTeZx5+0ZAQZsAQiHIbWEMyYZuLzCcOKhPd75OLu3atseM1pnosKnXWhPWluUTa+Z/GHB0K8+U6kV6Z9Qb5w2aUecj1CS6uyclUrLa3J/GYJRGWFy7LsTYaR9vEFADa8GmHGVJMZ002OPtJFQ4Py1J+792QiEXhpfYSX1kcoHiYcNMKgoEBoaVEaGpWdu+xezWs7Pp9QeomHwrZ834cfDbF3XwY0tW2IYW4Sv19zGlqCATIkr8jnFa76d09HKHDDaxH+9GSoz7BdNIw8yOCiBZ2r2F5aF+FPT2XUVtzhpnqvTwDKFzVtyqTM+cJC4crSXEa0DTm+3GXz2BN9rwc9EC6XMzz5wWk5eNoeZPrq6xEefiy6hU+pRz6urfbOcAGIynoVMkbQhgbl13e0cP78HKZOMRlzsMGVpbl8ssXijTctPvjQOuDMyEEjhCO+7WL20S6KhzkXhm3D038O89eXwxkmJoCug/Zm1tAX2pZ3ZwyBoPK7la2ccKyL0091k5cnTJlkMmWSiW0761V27lICAaW5RTFNyMsViocJY0Y799WufPGlzaOPh/hsR2b0aHuiqi9Am6CmJX+JZEa/qBu2DS9viPDWuxbHzXZx7GzH2wwDRo00GDWA7di3bLVY90qE9z6wMtArO1A15QXosjqkYlHw40x/rp+IM802eaLJP4xx4rAjRwp5uc7XrN+j1Nfb7K5Ttm232fyp1eeUWQbyYW21byZ06dmq6FqUjBZU1Wk6u05znTLHzQ9Pc4ILN9U0p8q0ZLO2/ZfOBb82z6TGlixxI53adQhalOd9BvhbSgzKEg9fN9V5n2t/0yGo3y8RhAdTY1OWWFH0D3fdJR3hsm7RIVFWKfT5UMB0YtahJtOnmv1OkbUzZnRn9/28cwa2BUooDOs2hDMhKQxBVnV/34PyRYH3gFmDZlGUmCZU/cKLmeQHlrz9rsW996d9VL6jd9tOr/itiK5SlaWDZ1N0WBa88VaEKZOSp6ja8O57GfD8P9F7ev6pl6AhT+ud7ubcxen8eNWHVmdU0DxZ7LM94V7bUvaKD63wlzSowR2DY1OWWBHhVz2flQv7eaJ1CKuWNM8G/IYTIGT1uf1Kn4LeXlVYp+jvkmtTllgR5I6+njcP/ewK4bblVmDIxsoymIBh2bX7+3C/gtbU+HYCVUkxKUvMiOqNt9yS/9X+Pu930qww17sU5OPEm5UlNnRzKOhb3t8RB9j7TEKKnfaRo28KBnr5ihXSb7TjgNPay6vznxfRbIw31Yjcd2t1wdoDHTagPAXTkjKBuvityhIju23R6wZy4IAEranx7VThQiD9o9VDD0W4dCC7+0IUm6rXVvmeFmS/3eUsyUJqBrr/NkQhKEBBbt4iYH3UNmWJCYXXmurzfh7NOVEJ6vdLRExjAUJ9dKZliRaBOjHlvK6T1wMh6uTNZTflbceSM4BAtOdmGTDNqHF27U3ez6M9MaZs3Noa76uq/AuQAZOGGYclIucvW5q3LpaTY06vXr7U94SIXkK255tIVIXLllV5V8daQFz58suq8leJ8rN4ysjSFV2yvMp3dzwlJGTpdkVl8BoVXZ6o8r6BKPDL2mqfP96CEiZAeWXThYjcTYasM00jLITLa6t8CZl/TqhHlVUGzhThASCDt7QZVFpBFtRWex9JVIEJbyIrKptPROzHFEoSXfZQQqDOEvmn26q8CQ3UJHwR4bKleevUlCPIRpT2j/C6uIxjEi0mJEFQgNqbvJ8X5npPBn4BZOYK2uSgoL9uqvOeeOuNeduSUUHSe6Vli5pOFeReYFSy60pzdiNcVFvlezqZlSR93fby6vznbYMjQP+Y7LrSFpH7bIPDky0mDPK4sWxx8/dF7duBmQc8eAig6CfAVcur858drDoHPRBQWqruguLmK1T0RtJ8A4M4CAK3hAPeqgPlACWalEV2rruucaTtMq4ArgWKUmVHgmkC/R+XLUvb0mAHnZSH6q5c3FDiUXMhwkKU4am2JzakEbijVSK33F5VmNLcq5QL2s5Cf12hu9VTisrFZM499gNEV4Y9rXet8Jc0pNoYSCNBu1JW2ThTxLwA9GLSbbgj1KvysKHGqljnLJNJWgrajt+vrqbm4Om2wTyUucCMFJnyIbAW4ZlCj/dZv1/SdmI/rQXtybU3BA42bZ2rKnMQOQF0Evt7wnHshEG2oLpe0bUum7X9rSVJNzJK0J6Ulqo7b1jjREPM6Yah09SWqRiME5uDVCjBGRa56RweNQFhoEmUOjX4OzY7VHQTKptttT5u3luwNdrErHTi/wG5jWw4PKXrYgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:116px 116px}.voice_chat .voice_chat_wrapper .voice_chat_btn_title[data-v-1c392dd0]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;letter-spacing:0;text-align:center;line-height:22px;font-weight:500;margin-bottom:10px}.voice_chat .voice_chat_wrapper .voice_chat_btn_prompt[data-v-1c392dd0]{height:24px;font-family:PingFangSC-Regular;font-size:14px;color:#999;letter-spacing:0;text-align:center;line-height:24px;font-weight:400}.voice_chat .voice_chat_wrapper[data-v-1c392dd0]:after{content:\"\";display:block;clear:both;visibility:hidden}.voice_chat .voice_chat_dialog_wrapper[data-v-1c392dd0]{width:1200px;height:410px;background:#FFFFFF;position:relative}.voice_chat .voice_chat_dialog_wrapper .dialog_box[data-v-1c392dd0]{width:100%;height:410px;padding:50px 198px 82px 199px;box-sizing:border-box}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content[data-v-1c392dd0]{width:100%;height:268px;padding:0;overflow:auto}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li[data-v-1c392dd0]{list-style-type:none;margin-bottom:33px;display:flex;align-items:center}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li[data-v-1c392dd0]:last-of-type(1){margin-bottom:0}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li .dialog_content_img_pp[data-v-1c392dd0]{width:60px;height:60px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAeKADAAQAAAABAAAAeAAAAAAI4lXuAAAfOklEQVR4Ae1dC5RcVZU9r7tDYkiHAAEFJD+SdCAQDCBoYMCAP3AYHZcw/mA5o8IILpYgLlFZM3EAYUbAAT8hDooDaw0IistxqSNKAiogEuQTkHyAhJAQ/r8OhJBOv9n7vHtenbr1qruqu6q7Q+ok9e69555zz71n39+771V1Im8AWrQoHbWsW/Zp65GuXpGuBB9JZU80rbM3lc4kkXFIdzItbdIuvdKdinQnbbIRshoH7xlJZGWayIq2VFaM7pCVF38peWVbdw/at+3RFy5Mp2wVORrAzQeAh6IR0wBYB9ICIPm/gpiXhowgViiT6ycCrGU9dO6F4OIddpDFl5wl9ydJUlR8RVkjhcG2jnha8N103IuvyPFw9jEYoUfDxVNZafN0GWBgKpjIt8bFctX46oi+9Z+DzC0of3HbKPn5t85K1qvOCL5YW0dcFa+/Pm2/Y40cszWVk1HJvwe4Y7WSrDERQ2hR8n08Rt6P3lxwkPooE31NbsaUf/UokZ+N1OmcfhlRdNYl6czerfJZOPATvb2yh1bOwAjA5gDGNXcox6BqVvP0N8LejWmb/OCys5Pfx9UazvSIAfjsb6ZzelL5alsiJ2Bdbcud4kDLeYw4vgfTx1XeyQ2Fflub3I66XXDpF5NfldkbpsSwA3zmpemhmOzORfv/FiNz2OvTKBzQ0e4h0OPPkp8tSBJO58NCw+bQcy5Np7+eymUA9ziDlbtcjkAlm07NLSFdJsM8J1eW5/i+vDKZodBP5EGM6jMuPjNZrPUY4ou5c8jMLrgqHfPKC/IVTMNfhtHRHiCtBIBRbELNFBBmMO1Bs7iFqpzJjFD9a0e3yRe/cWaywao6FOGQAvylS9LjsLp+G5unaWbY4+OBUTAzvGyA58DnoFfJV8exMFBR+cOmn8jL2Fz8y9vfKt858cQEt/LNJ/NzUy0tuDwd/2qPLIKzP0pD5nQL6zVuehZuc/qJ3N2xg3z0otOTh+ute73yTQf4nMvTub09cj2G4XRWrmINdDzLY8hha5Uz/htMvxt3DJ+96AvJj9muZpH5sCnln/Of6WnYPl6KITvaNk8GloVqGIDmozGqkYINoTeqPtp1xZjxcuaCf0xeawYIkTsbY+KbV6c7PvuC/AiofUQN4JIDBRMKpudRKCBsclaT7UK/Te6TDvnwRaclj1q7GxWq/xpVGMtZsCiduHmz/BKAHWrl2uiMQ+Z7HtMOayaVvEyc7/MoHOeT52XifJ83nPqw/VRHIseed0ZyD+vRKGJ7G0YAd9KWzXITboG6vKfVqeZJWDMn5543HmQ4FesoNiGEGt0O9OGGlzva5UP/dnqypFGg0HcNoQUL0/23bJX/S3tlLwUJpTqMctA8WN64B3U719/c1i6fPP/05CeNAMb7eMDlAdxDCS4K25mFxOsoefnI1ASFGCknypC2d334phe+OPW8zydXZh4Z+HXQAGNantWzRf6IKuwaV4OFexwtXQZ2rOTSJm8sS28P+mhrb9IuJ/7b55KfWvsHEtJnA6bzF6Z74Tz5doy4SVULcWunX3OryscZ27f+ZgB07GDW5AEDfOH30p03pfIHLLSz82HK0gIgFq1IG4A2tHNBZFgcoUW3d328vfJyMkqOWnBKwleH6ib6sW7iAwN5TW4GRvMMAA1ZkiGDkGuprqsGZpSvhplnOlF+Sz/zH9zzFPw7b8EA7pNLD9bV2zVeNuMxH8AlLgQwD30ceTiKK89j2j7UbenX5D+46c3w208u/1U6GvG6qG6Av35F+jEAc4oBRWtFceNZSDQZ50g3nqZb+rk/vC+9jxjHK55zX1yLY986iS6vmc67Kp0hW+RuTJ2d+fRZoO3zfNyLVuNTxuf5eEsfs6LIieeemtzgfdFXvOYRfBXX3S14KsSXx0E6/Ybu4XsJexveYFAi33pixgmjGImWfskX9fgPI/nK8xal+5g/+wtrBnjdFrkIYL0tB81ABAPfEFDACBqJgcYRUSDJYxxyzFPQW/rwRMkX9FON/hsPJ16bpniHswaiv/ulC69M52LpvAtnzO22htrml8oWt+mUaSMaKOMjkwCbDuUsXiYXCmjpF/sPc/Xnv/bp5LvBTVWDfnsBegq/q7EQJbTraITHdQSCoWFI0wJHMnnWG/MeGWRa+s5ng/QfRsX5eCy7O/3eF/UL8L//UD4D0A6zQmx9tZB8A84ANVmGCrizYnoWUqalXxoY9Ienqv5LZAKOiC/2skVxjK3qdPH/pBN7NskKjOBdKKhTKSKcSj2xEhU8Cjh+S785/sN59VHnfKr6tyk6PFBxfOtm+TpA2oUD0NZHynDERRjrSGWeAck4ieArDwqMk1r6DfRfr1yOZXRutW89BpdnjvfXb12T7tHTI6vxTlV2eqLDN0i4uIJHtuNZOXlenO9kcxnHa+lnHsh905//Evnglz+V/K/5zYdudfRsEYB7Nu65RtMIP1wzLa6bqcAnU/nIt7XU5PK8ln6z/fc1uLiQiEUFce3FocYaDKodNZOji0RpP9Jivgq5i5Uey1XjO1WNVpOrxt+O9THo3nv2SclvYxcUrsFJj3wBmOxoflRgTTNnglEtbrIWVpOrxjc9C6vJVeObnoXV5KrxTc/CanLV+KZnYTW5anzTs7CanOPjXpajuAJgJ5KV9t3r03GvbZZ1GKk7WflFod90VYsX6Rmvmo7nm2xR6OWqxU1vL9wtHjFXZDe8UPTSRpF7lossW4X+GVrfn76V48NqOp5P+X3eKvKOOXiXabzI8y+L/Ol+kUfXYSLECGq0/bYOmXfmx5M7fD0r1uAtW+TDBNeMM7RewND4uiaHPLunZZ6P09Bw6++5m8gJ7xEhyDvgq/gE+b3vFDlkdqluvs4+Ptj6z5ws8sH5eNaHl5lo+y0IP4T0DLz/QjvmG2/Tx+u1D9z+iTqeKgCG0Mm6WYKUN5ZXiCDig/9KtuHKZakX8nMedaxBjId8FtBsfY4eq4dWOFzeCT6pmfbnHZjZiK/kwwVKjbSPWeGEq5bgoZCjMoAv/2mKCUXm6ygNIGgvC7VRPpWZB00CpRTJjiT9XassNBxRO2VbyKw9bBbbET7aRsdjO+tpP/3DabmIyMersY33H5r08gb5O2+zDGC8hvMJNEx5OsoccAom0gw1HtYQNtpkTYYGjIdsdYzlMdT4EOm/gHWviLb0iLyCbwM1q/5s90vdRZazfQDeH887k/nKfEQt49XtP5GTvdVygJHJgm1Ks95sPdeMsQCdWsDwPPJHmv5dD2YbGtbN058fyFLNrP+dwYa3y/idy5rnP2D1voU3lh5C5AB/57p0JjL3s8oYyBYSZMbNIdrbIEy+fYzHMkzPwuHS3/CsyM9vEXn6eZGtGDUcVbcuzXbSrKfVXevHxgWyels4kPqvfEzkN7dj9/xSZpvhb24TWbU2Gwg01XD7qXT0bJbjrR35fTDAOXorGkjEMXsqqXHGXMMZt6TlU57gaoj4SNNf95TI9TexIeU0FPV/GGASUE+0S2qWfQA0H8X/gDZygLED408DlsBDpgKFi+eTx/rFIVjKD3XPZSjY0s98Qx/FfrN0Q/2HwcrySIoHH+p/7wZ993a3DNUs0yQMUF87gsabdZMJsdAr8pRaaIT+BLwJNo6/dRcKo/2t+JWL9U8HnplEney+kyxWcdMmEfwUomzFxsrr11p/3r+Owq7btx+HQfLMC+CRWCcGCPfCfTdDEn6LRLpheyNs422YMv1m+6+jQ/Y99SPJch3B379B9sdRF6oGsjkalWQ9FUNcrNJaMcqFfI0injurCfos8vijAsA0GOip50RuvDmrm9nvHIffPUT/tbXTZHvQGR5/UuT+lSJPPANujfUfH8qz9lt5964QefbFLGVgTcdN5ntwiBITO8Oj67N1vxtgq09rtD9Q/8Mf8IIsp+9oMJueadQ+oZZIZrwQkm035yarPNOzkExQI/RnTK4El2XTyeZ4q8uBMyvBpSy+dytT98pOlt79DoxIdG3TYb7F85BM0Nyuko2Mk22Y7KiT8iSGb5uVxePrGDxw3W+ayMfej/IgMxT+A6jzWQ8dwajcgdqtQmUVlbiWPs1uZbLG97w4z2Qs9LJFvEj/QDg5Jp4pr3nCOR9l4id/ZdbUWLIyzaPCnTAyf3ErHotiZCv5OgX7bwIwPG6M6ZG1Iq+Ge2jL23Nidgxq6aKQs8phB2S2b707kiiwH0mUkl7WuJ7H+hNTkI5gANyV39ciM7RPeyWF2DvzD9PQ0rTleV6D9fd+C76XWnAaxamW9czrgTrtOzUbmWD3S7vvInIMfmTC6/s2soADZuBNQ4z8mO4PDyq8/f0hWyuxE3Km8fq5T8Ekn8T6WOjrlssGGS3HMAn6WHKnLVqacqJCQW34yQVsCEjaESgceoQaYZyUW86SeaeBvCqGQCvQIP23FYzeTVjT9NYjNMb2DQ88LPLXR7N6sv48DuzEceRkdBI6dcc3ZfW26xRM2VP2EHkMa3Nc/1FoE6fVmLiOv4B7afrFt3/xnzMe5ZnXAf2d0TG5LHRNyZYIXxYfdvCp0ivYhFn9ma9lQnew/kdB7clamd723zemuyKxq/UK3s/iv1aSIcl6Tx4nDx9OOZrHdIg3Un+3CSJ8GhTTXx/Jdqixfcpx54qfI9ZDDTwZk+ewEeLjwZ/dLPIkNmUxzbGRFNV/32l4VwlTfkz5zIEMb5/AqG3Y5+5+M2w/+azI7fdhKbglAOkK455gv32a6z9g09W2laMXZKAyYoAyVMACz8fLdJqkT+fHhFeJslHqbfp4lfrT4bfe5dbcUPBbsHZyrYWatpsRArf/9CDgAt4WsZPQL6Rcx8fBjP3H58B34DlwTNMwuivKKtC38ur1PyrY1Ybt9Ew2iMSCWIjFLbRKWJqh9V6LW16j9MdjauUUGhOP/14HWAOxvxHTIafYmHbDekyy9k/D7Y7ec2fs/Go7ZzLqtf/YE5WjmLdgfKrVLP/jj4vMbMN7tRO1YQFkq7wPLZ+h/5iM5TNNsgpbaPlel3GTtfyMk+nPxgiyzmJ8HhY8iOnZyulL3/IYWvkMufuOyTuZeXMKNky8fyVIZpshyYC2thrPh2b/5QLbowGw5VOHZGVZaPkM/cdkLV+VnT7W9oncZHVahiozESqvQSiUBwl0uG4CAo/5TBs1Sn80b08mWamlcM16nAphFOaNRFa99scUrKtWCMvlSdQuBbt2buCYP5j28344pnrrX499jNlObvY6DVAaN4Px6MnBhYwBywaTQqDxRujPmoJdJ7teRA/Y6AXfGkqRWu1TsGjTxlFt7S263eFJ1CPrMkO0xU+99jtxzMrjVk9canhHYLaZ1wj/sRyWif+dDMsAJiM3mAnlaSRLceaFfO/hweqPwu6S97MxbXgGtyd43GZ1U9t12j8Yp0hc9zy99jrOqcPUuQvetCjqAMvXZDtjmBuQ/XaMIr70ZwPC7D+FR5gss5H+8/7HF0zH8Y9JddKI9pw8goagUnq+i5CZ5lDKUYxp5nu+ZmhBA9efjqm5aCrj6NU61Wm/HTMBgeOumIcmMa1Yk4HGaheNXp50Uca3s9b285SBG7iD0LGKXt9Zsbq83Eb4z6aA4CtM0UCZ9285oKx9IN+onMdIkMnz4Z0i/Z0wJX3giOLTICsvDllmTHxQzntK0mH7i0zfO4uXXQv0mM8eXVQm83jcSPBIeiCyZxb310cez3btLOM4tCWeZlW2im2O3GrE9vBlBPObheZb6uX+dYWoqWAvz6/if7S9E31MeswBqgAGe7Mny/c8xmmHspYf68+eVryWUrce4ukUyx47pvTKaT36RbLs1LfdUwKPy4JN/ybPXftDqzPbkzD6d8XBSyNoEzrWbfdm9vryn9ky/1rawv78D70eAtxdVgAsUrGEXimaoYk8rRWFkOfiygj6nGZ5TDdY4lEe711ZRwWhj1FRqy2+cPeHv+A1HhxcsK18SFE0Kzy+Ibt3JfA8dWoE8XaLx5pc+2m8mv8G638tG9hyDc62GASK5B3I1pMImsXjkPnkRfpdU+qbmllMES1fg6JRNu9VuT4Plvj6zl8eKt1usbyuycUzjY3e3XcWmTjI0csZg4c0y3C7xSPU3J+sQIH/yFY+Q7Q/l6/R/0FdAe5WcLwiCiwjgG4bKuWzE0CGYoWGkWFfEykrp48E18B4iuRtxKNYA3nOzac/XDPrJR5t8laE6zhngpcxgkLv1vrzadHMyZWl8mUCvnJLt+yONzqKDkgqtRwHPngdtllnvvBH25s5akFsT3/+U0G7DMD/qppwBLdLt2CnqGBZgQVg50BCRmUho2K8gBHrL8G5rwowI6JYli+gH3tEJITkKoDLNyFpgrdJ/JBi/Qr7mVihfbZD9RGyXB5LFu3al69GfgCCDzf4MRqoffOht28+qiiTxlhBZoBMl/Fa9VF/AIw/lsyCWJYnHbFgWGGWR3480garX/SQnsCueiyzWta4BtvnoUpML+JxIHe4vjOYTDPaP1j/9aHf3YE1d70u9HAcwSSxYQo4Q3zKpueQTznySQrAAPX5JGcynsnGxGNJe6jQLPv8QhqXhphWrAmdeAjaT9uD8V9f+hiI6ztwVrmCz0+5uVKgEVXc2LgQz+/RKEbAETLPpjBEB6zPzRjL90RAuSFptv2imYNr5lqslzTebPuN8F8+KgvwQ96Kjj3Hyqr1r2Aw4i9/6mhF29Tf1rqsrWVguqxshAd06tXnSQ/XwJj41qN9b4h5tOed0Qj7vKctehWIb4oU2Wu0fR1EbBeMxfEG+n9F27x5ySaMyrXaKFw4Qq33IpanbdjqdBL4JstwIPr8cnT20hAtlchGLzlmo9H2i0Yv74+5NAxV+61tA/Vff/r4M/Qrss6SIKKxzMm5YuARVOYbiNqbmQBp5UJ+ximBYmUW6bOMovtavmus3wh0ZRbpa2UGaH88jlD5MntMfEeKZ89D0f7B1L9G/7/y4XfJ+gzCVJazsXRk/gmtV+cGMBknMTBglREuuS7LcTx1GNJeny+7cYMVE3fOWk7IYLxIfzD2uyaV6mL2eRDBc+e8DU20T98Mpv416q/kb2fxqJKj805dB3Dx6wEbaztljkaL0wDlWEkvz4RP96VfNHp5jGcvxpmjzWaj7POBf9FTpcdxwsVdO+2SmmVfy8ZlsP7rT789kTtpSwEe0yFLNmH94bBj+/jxQCGppG3XSyZDZkjmAkzz05c+p0e+cxXTwzaC+tGnntm1UMtCgml+qtlnx7KlQ3UoC2H/Gm5f+maYMiQLLcH0SNDHNL6YddIp+v1HJhvQ6OXaa8lFDa0H5yGFIW0yOsVkovl0Y3n96fObBTHxrQmeE6vDmmSf59lTCh4J8liSDzVqrT/rOJj2N1sf4KZ4r/sW+jhbgxFB4xbTMBdwDRnP+FkYJI2HrMwhxkeG5vWjz4fvRY/dVmP3ypHUTPuTAW7Rrt3PHM20rz4Lfhuo/2rxP8p+4LgjEz3Y1SmaxoDOYoB8mqKUpd08pxJZd7C5z8vQqqV93GSNB/CLHstx55p/z8hkGRbo5zyzRxmv4+NOn6Oz6J6bO3Z7qJD1UBYMarB9LZODwerkbfg6+7jJGq9GfYjr9EwTOcBjR8steBDNM6128xl+qzL3HYWVb8bIAFXlMS/S5wN7vmge01o8d9WHCqHsZth/65uLd+02en2dmmGf5Vf1VZFPKR/5r1Z9LKW/s/awTyi9+7DkOfTy37Gn21prW3nylB9CS3seCzF+NX2OXsp44lsTnJ5J/enH9anHPg9VYuK6+zTWX6tTM+37upodz2PdjF/Nf7W0H7rPT9lFbrK25gCrgTa5mkY0ngVZPOKZjMoRdERYKUtrmCVzHmX4vjFfV/GftU9kz0n70/dl1mufb1Lyu0DeLuN6LFlj/Qdj3+pLH2g5FkGCeUw2sP0/nj07CU+es7LVKC9Ll6Zjn35NnsRcgrMeEC1zXgiB1UunCjIdI+eRb9TSH3L/YZM479jDS79XWTaCDzkkeRXTwE8UOIBj+DFi00NZHECqjMvX3komPppHsF1+Wbyln/nI+Wcw/sMssMqDS9eXAUwGRuw1BiaNceogUDqVIFIWqkIGflbTjNHSL/lpSP2XyDUBkjyoAPh9h8stAPEhA5WStj5onBmgHPwAuoFqsi39zEf0lflE483yX5u8jnOcH9KGpwqAeUCNefxCqxSBJDHtR2/GLTXCZBga+Ba3vJZ+yYf0Ccn8y7j3uY9bXp/+S+VHx8xLwv0INTIK8FkyC5ekaUfPnbISJ0tTKRD2WZppaVO0zZXJ+Pw4jwX4fKZjGZ8f57X0q/pva9IhM9/99uRR+shTxQhm5vwk6YGj+bcKlRjaFGy9yNZc8hm3fMZVz0Jmu/yWfsk/dG4j/AefXlsErpbPSxHt0Sk/gvH1OSAQYpzEQAEN3SOwlU8ZzaMc4vZRvSDIoKUP3zTAf/Bvil/h+wb9W0SFI5iCvFnGS+EXKEBI54fwBM0q5gDUfPADhuWjtqXfPP+JXHfUwQm+q1FMhkdhLt7Ea1uyVO7CQnlQoUA1Jku1RbmaTF/8ln5N/oObuvF0bNYRByU4Dyym/GFDUTZ21L2/vyv9XG+b/AkbrsrOYLugQuUiZsRr6ZemvMg1Bd6OJSjyr32BS4VK0CqKEbnlrnQRJE/hqFRMqOXBCXF9nos8DV3pxm/pN85/cPP9Rx4sB2MQ8l2cqlR1DfYaO4yVr2AtfpbrrG6OCDA++frMOFiWZxso5pOM39Iv+WIw/sM9corvlJ3WH7jqe0Wgn8u82cnzAOkMipWBpowAdABciwqAM56DrRkt/Ub4DzPiwiPnJrcFl/YZhDHWp0ye+cd70v9C4Z/JGYjYTM1pWHulzwxxkynIaulnbsveWHUDw/vK+w8d5L69Jsg7pk5N8MCzf6ppirZi2ibKGajDMuuF5HOEahhukXxellOSsTwLVa+lX7P/MDXj24JyQq3gsuDgXrVR0+X2+9NZeEl8Kb6otqPX1o0UStDexlJDt1M+0pZPHR83o8Zr6YdlrMB/APjj8w5MrjWf1RLWDTAL/dO96Ul4eetqxg1LjYcE6xYTRy1BJJXpIG3yOrKRsLQKh8t2r98m3583JznV+6SWOH09ILpjWXoB/nrXV6nsASM6CkbgM98AMzkzGvMp29Kv9B8c/Lvx7fIB/yqO+qqGi/m6BtFKkTuXpVfipblPM8fAU6kIOT/6ckEoeB0fj3vE9qwPv9w9YQeZP2tWgt8dqJ/o1wETjjLb/7xMfgo8P6iFOJRiUDQLgmX82HJLP5/u1E94L3CHMXL4QTOyl9hjd9WSHhTANLB6dTrmmVflJkzXf8N0DGCcpgzJ86vFYzlVDJdqOp6/LeujHRtGd8jhB85KVvt21xsfNMA0uPSRdKfe1+QXmFoV5Hor0ZKv8MC6DvyRyYNmJ3+tyKmT0RCAaZMj+blX5bp8ukZEF1mrkKUtjPlM+zwf93nV+F4mjvv0CNfHyF2O38t+7wHTE3zXcvDUMIDVh1iT735IrgBQnzFw7f4231GZRXO0hdYWpklBbjvTv3PHRD6w774Jvm/RGDJ3N6a0UMo9y9PzcRjyNSY9fhqHxRy0KvlaTAB6e9GHW37dO0E+csieyava/gZdmgIw6waQPwF0rwBA+OJIMXnwiiX65r4R9HHUy/7+H/gTeufW8nSob49U5jYNYJq679G0q3eLXI8d9hzubkk6eiOrxovDTKNcx2Qsz5dpeRaajE/7eJxveRbG+d6W5Xme6VloMj7t41iGnsVXpk6e05X82mQbHUaubnTx2ebrpdflMpR8Cku3BlqoFtGF89EY1YhypLiDbOv6aNIf3oS/V9nVVfkusza4QZfInQ0qtaCYZavSE3Hq9W0gubuCCctl4AWEjWdFaAV5QX4QycJtVB9T8ma08SL80a/zMCXjSL+5pP5rrolS6biVmrCxRy4AUP8MlPRRpQeNkgFL20SrspeJ833eSNdHo36Ln448fb99klXasCG4DCnA1p6HHk4PxotEC7E2v92QVOCAFqdiHcUOScsz9FWGhRm6iJrMCNVfj6qeOWdGcoP5YKhC+mVYiK/kPrhaPo3nyucC0EkeVAPQYZyDbkASUV/5kaiPKaq7N5HvtHXKN2bvnoQ/3jO07vY+GlrLwRqAHoU/uvFJJL+CzwyyFSxGHOUjkzxF2WWGKGVIw62PKuA33uWycR3y7cmTE/xliOGjYQfYms4R/dAaORF/x/irmM4OID/G0dJlYFsBBaHJW5alm6afyFOwccnEcbJw92EasdZWC9nmEUfLH0sPx/p8EoD+BwA+IZ+L3ZrLShtgfTbA6/h44/RfR4f5JX4R55p9J8svsTPOfx+jz3oNUeaIBNjavipNR29dK8cD5JPAOxb44DvOgQgWyaNscYQWtY1Yns60sg3aYPTx5hJuea4Z2y7X7b13wil5RBLbvU3QqufS8elGORLr69EA7WjcZM1BHAd9qL5Hz+JxaK30fPJq1U9kDaQXw9aSsfjRuEmTqn8fiMWOFGJzt0laty7d9dUeeRccfigw6gJQXWjIPviURnlRywzgojzwMN2m+Pc4yl2BJH+/895RvbJkypRkdRWVEc3eZgEu8io2ah34Ue+peJI1Cw3bEyB1YpTzr6uOA2idWCc7EbYDtG7wN4Lfjds0/tUZ/u2oZ3rbZeXYVFZiysVPpL0x6P8B5j6YDKHy8CEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:60px 60px;margin-right:20px}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li .dialog_content_img_user[data-v-1c392dd0]{width:60px;height:60px;transform:scaleX(-1);background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAeKADAAQAAAABAAAAeAAAAAAI4lXuAAAcv0lEQVR4Ae1dCZhcVZU+r7rTnR1CIIGEDolJiAkgS0QSECEBBhACM/OBwjgug9FvWGYBg1FxHD4/EZBFBZEZRBxxxmHx0yFRYVCCghEQFBjA2MSQkJAQAwkhnbWXevP/p+55feulqrqWV11VbZ+vu+69555z7znnf3ept1UgA4C+87Fw6J9EpqcDmRGmZUbAVGQcXBuFdFSKaVpGSYB/UigdkpKOQKQD9R3gdKB+U1Mg7WFK2lOhtI8XWfl3/xHsVvkG/oCPjUfXLwxndqdlvqRlHhyYHQYyCaClzBmARhAFgEapZcnHAaDVFPMpS18Ex4ushfhvcTA82pySZYvvDFb48o2QN5/q2tYbPxnu39Mt54ahzEfA58PYA4mfEZ2Iysw4r8w5qzM5S0vVx0ywMS2yDCN9WVOzPLDojuBNa6NeU4tB3dl3yz+Erbt2yQKA+hEYdwbSIXEjdSQ69Px8XC5f2dfx8/nkfT7ku3AgPYQA3j1smCz9x1uDPX59veTrDuAbPxEei1HycQzJD6ZD2dcCFQEQH34mwNSri+RdfVT2ZHxVzXt1kXwR+lDbGqTkXozwby/6VvD0Xu3WkEGX6oJu+PvwZGx0rsJIPVXnW1iGvK6XvfMvTDUQzHKbki2lNy5fC30cGD8H2Ndc+W/BL2hKrcnCVDM7brw4PNMBe4IBk2WMD1xWBQrxuniZ8rl41k68Ll6uQB9ALyfQi24PHrTuapHWDOAbLg2Pk275BkbZuzkdkqIRxzz+feOs7MvspQOhqK360X9GmuWyK28LnqK9/U1+DPul75svD/cLd8l1wGIhOuztnzmi6BKtwIcCmmFnfRrgEbOO9bE209w7g2HymSu+GmyJbO6HjMaxH/oBUGHw1UvlIkB6fTotY61jA8ph2zsCwTDMLKWdHKE+6A2lH8jmVEoWX36r3BUEgblc1fBbnKvayW1XhG17dst/AbET2ZFNs0xJEWgOvEI81jW6Psbz461D5UOX3hysoz/VpKoDjO+zZ/WE8l1gOVYdsSHnvKIBPmAGtlaj0uo1Q+YA0Ydfm+HTRy+/NfiJ+lqlD8avKvTo1WHzc1vk2iAtn8KpRNv72DKrQCmYsd4VUPAsNUDNUDfoB4Q+zq2GOB9601H7yWfnXR10x0KRSNHilkhj1sjtl4cT96TlfoAzl7wILBPw09iI1KoYb8Drp+SJ1pScf/FXg/V+aJLIJw7wbf8czuwR+V9Mu225kM2ags2DfAjm4A9Ufbi6rknk9Eu/luwFjUQB/uYV4Rystz8GuJn1Nh+AOYCLDoZCdfnaI9/0LDVZv854hWQK1VVZH/vqzU0pOfuSm4MnratKU7qTCN36qfBMGPgDgDtcg22t2nRrKfi2qTIRphHPk9N6K1vqy6pA5mOg6COGO/FV6rxLbkrmDFgiAH9jUXgBwvw9rLnNGm6AoXig9SjwDox4mey9eH/u+oJzfIF8+LIbg3tc2MpOKgb4m4v1XPISgBSBG22ZnVne4LNNsdYQWI52GsGsEjKD+ohEIN04l33OJddXNpIrAvibnw7noIFHANRwB49hpKkBZymZlmcaFZj3yMD2ZXPxBro+vkbthN+nXPKV8tdkjbMX26Kz3/p0OLMrkMexZoyNgo/WdLplKy7vslE5vgs2EFVuUH/v+OH05pBQTvzEV8rbXTO+JdPtV4UTcQLjCcyrbQqogYmUDfq8vQB1sjYN+7JUHtTPET98hZImmXvxNaV/T8aFjtKIZ6i4W4ZWGzWx41NUmBIcEtYOLWjqylpPAPnv6ik7qJ+JVcH4BdKWwokjxp4xK4UY6pJo5R6cfhSZw1sYIwCR19HneFrHvCvbaPXlB/VLjt/clV1ybUlgZWApXuXOL4RnhT2yFGsuIR2kfo4Agh4GTbJg4ReLv0BRNFB3fSlsS++WZ3HhYGzvd5o8HrJV23nFRQrVmWwhmUJ1fwb6mA03p1rl6Is+X9ylxqKmaF6sT3fiem4KF+oRYJt6/Wk54rMegeZ0bHJRnfEow569tiKZQf2C8UPlWGJBTOx4LpQWBfBd/yoXAYATrUUFD63qxsC1EAFmwBE/B6ACCf6gfgaKiuMHLIhJIWCtzmJu5b3S+64O99su8jIq9AICZ14q2dcbU4iXfT7zBJs0qJ9M/BDKzSNHy6EfuKLwPV5u/Gnsc37sCuQ6gKNTMwW4+yXC9vWGPIKno9nVkWfDlfyoDuxB/UxsKo0fMdnRIdcx1IWIkOSlu78cHodd8xN4wkAHoI4+aOhodVo+jyw2aKPUiURlX9Y69nlJ6Y/A8xBjDxTZD48IjsE/01acTG3Gwy/qiBmWYMqYvLVJ5LEf4jEHPLFk/rELi4fvq9X7PMqWEj/4wl313I98Lv8tuQW/OOOG9G/AgIBHmw+qlc0gphyZZqxmyHSkdWzIyq49FiNehfq4iU2mHCEy4xiAygdH+5l44PBAmn0Knk67L7vzavmvIQVG6O3Y7B57SxbfXo7L/ed14ZnpHvkpgfUPKyooj2ynTRH/MCU/UosyVHBNqUIy+qP3E5k1B+AelhmhNKWWtOk13M5yd//5T19TTfL+v/1M7qtOeUcwpubPGyCaOtCInO6Y2bIDD6cu0YsDj6BThvUO0Gro8yCadZzIkbgRF49y1g3t2Zkxpdr+ay8u/nz0B+UHcwVB7YhXfO/a8GTwHo3zrUwltp35QOq34jpldT6qVH/MAThXelZmnc3XR634K58Teeqhwr1X6n8e/Xkf/uzeD7zlPPaxZlylABawUzHVj5hQLl5MhMVy9SfNEDlhgU5LOVqtPWvPLvhWRAzK9d88jOujzFH8C6u3FBNrNt1zY3gson+qfhmHFo3Vf07BzLvUpl11xmSQRnyTtzorV6A/eRbAPad+wWUkd2OK9uOkeS9u1YofMVPssuHkyplNGLkLDSRNDRCImbHk63dbV2ff6Vjv55PU5ybq+LNd+9km11WpEyO4VvHDWrwwHowsgH96S9gKgD+g4EFSwaK9kFKeG43c9hNMkh2RBix5SetPnI4198zePtlHvRJHcNL+Fxt/vCHoA8TQj00WwNt7ZAHA21fBcyAagFRiXglpNFrJINhO3g4EK1eqP3SEyHv+ItOf9l3nH114U0fN4ieyLzH0Q2SQKQ+j9yMKFkoGlA5UfLCsoCHlCPYBZFn/nQwbS0qf4A7FWahGod2cokFJ+V9q/BXDjAkZOyy/9N/D/QHaGQoUnqFQoNG6Tg8eoFngst7VmXyS+lMOF5k41Sys/5QngLp2A9waxg94nKFYunBFIxivLDoXWA1RoFBpR2A0clFZKE+gI7AT0OfJiyOOr39QfQs5PdtZvprFDxgSS7MrAripSeYrSOAoUJAw0IxPpaw8ZV0L5lDWmutAz9Ihz+mobB79SYdiasb620ik34EZE/hIUr8tBuZzkf5Xoo9ZdL4agI/oRAdml/kacDCz7hVAhRpMo/mPso1y8lk0fpL6049mw41FBJhLVM3jl+oFWI+rH94WzgRYB0ZAIq7ME08bZVllx/eBVjlVyICSJe+O6qi9PvT3n4DtIE5HNhoR4KyYsEjfS/SfflcSP4y6A4kp29ERzCGNZ3rNtsyIZS0R8ckA1GGbqaAhJG9gV6zfhum5EclOU1pMahU/9u+m6RU6ggHOfE4tNIhHm6ZWjvNY7Y5Ik3MNJqbPi/WNSJ3YQddD/PTACmQeY6gjGEYdw92fog2mGsmUEt7QJJDkUVbzKkChDC8Jfe6eeY23EUkBhuG1jB/j5vqfzXzq0e+EuBdCJukumCPTUKIgAXQgsj5XXmVQlZQ+b7HxbUDTDUPRCHYW1yJ+XuwmEdvmnZ0yHeDgJecg/ciAZQOXRkYjliIoK+6OTzWCm5R+I26uGAMS3gWmZPHw48Q4slzt+NEA138Kp8WnN6eH4BX42GFZ52ohPlg24vpsANqIZZ3xKZuUPm+Oa1TyR3Ct4mexY/+4WXJGMzIz7HsbZ2E3iHV6trMyVFIwUalAkuEoyxHwKtVvyboWYr00RtptFxpgrs18Znl/xc+PP/oGwECZ87aBaYYQSYLnG6qjl3wCjVQbs7xruVJ97cOi0kAp49cJgHV6ZCxqFL+s+OsIbpLxtsba8NOFmka6IR0t3M5wjbsD2rbeCgzrQZXo407OhiSCawdnJf5XGj9fH/dMj+cUnfmpGTcizUiNMnhR6gCPDgbW8d+ByrzibzpUtLzJuZlC+yDP+E6W+t1VeaEfO6guZd3JYV2V4X+S8Udbo5oxAkfqba8wyhpXEDl6QRFozliTydTi05xg1uUr0ecVmUYkm55peyX+J6ofyMjMCDZg0DqznGLUSPYGhqvOgA2Wgs46UK58JfqNCjCvA1usKvE/4fiPasaiPEp30UCKjRtgto7oqCQTFM/zINCB7hQr0d8Hzy7yltixuNDQiDT+EJH5B4ls2yzy6go8+rcRXiA+8ZhpgFFFfpLx074yXSqOxA8zM6boJqzB+B0bO+qiXRijDCPUEM8g8ggqMeeOkWRTkhrsDNeKIvUn4K6NmXi6xtpT3Qb7YJz4FY9Xwvj/x+dFXnmxf+KXL/64CW9Usx5hMI6kqDN1ZfJU2QGlYHtHpS9H2XL0h2OL1+jg0vc4TTsSoxm/zrD59Uw8GatqxM/vd6/4o88UhnEHRw4rOXojcnnlc6R6ZcroaHO8SvR5M3sjj9woXjkyXHKqHT/DIhd+xLYZFR0Q0qf3KeyPSj3iyAQplvhgame+fJ4KUU6ZmVIx+iP2Mc2Bl45GVC0efqySjB8B8UIe9cdoYsB28GtShy3QZCooXGAd+crGy1qnY3Kl6vPy4EAlxs4A9n1MMn7WruHkxx8HUkczXkDdgZPSmV2Tk+ZwV9ChxTU4M2ytsrfOjh49HvyDogT9rW+IjBygo3jbWw5gRt/i4/IKPPJRldUz3CXEr5A+lr6OFFGmEBuN/llWJjP6l6nLkc+qtzZK0N+4Blc9GvT0JNwsSOteRnWOmGmcHT+rvoz4FdIntpwtNmV1SJusI1TqBorG8N/jM5/VOOudu75cX/o73sYrfJ51M4XTHwjJ6pdE3sa7OvrynzHTeJUZv4L6wLaZP2uOr8EZ8jrhjEFl+45FAfvKZHU6yllhVKb+pnUi2wH05HeKcNPVOgyB4dMBDUKcgfAD1joIOC2/thIvZMHSw/j0R/yiMMXijxC2N/M36/1NVhZ4KEQgUpmVIGR1SWFKMh0/r3ol6O/CXn7F05m2+LjK1CO06Yb4eBtnr178dcZUiwVHrsbVglTl+Fk31r8eXAQYrxZq59GnRxpsio46aKgwU2ZINBIJi5zbmbF8kvqNdj66q7M3NvUQP8UC+OAbSnvqoOGyEmCl9YgjaCDNx9JoLeE6DDn+E23jJ6lvLzKhLY1Au3e4mNVJ/BQT7F0V2ynzAl4HWaujk8DFAIzAhJBurJhSzslGAHg8q4/aRB2pWP1deHdiNGtkVOv6c8c2Otcbk0r9T0h/LbHNnGZokt/itsrJ2FZnCPOuAo0Sp2AdqaizvAqhoF/YDTzKJqSPn5+VXRgVw0dqTyV93HAxbp1xdzeWpAjhFtxAfOXtpWqJ7MQB6ceCgapl/BQoYEpPuBXABSW8Mgng2JFj067y3Ij261WOmp6On09CfydPoJZBvOxYLpWjy/2LfzcHY5OE/2ynkvgrpmhCR/CQFlnW2ZUdFu1Ah2wvn7xo6qQBrj6L78Qr1ecZrv1xfbVU4sta3ijzJx7fAd1SiV+HCGgUF9dApf5Xqh8OkWU0RUfw7NOCFTByo3/E6AGED103mZJBcnkWyYvWVRvRSJXv1zsdqher/xYumJdzf9ZR7+u1Sfsr8oN+HHVSkcKe2JvuYIrilJD/WfEtMX5YLjbOBaY0k7AoAZRlXEcMNBqs/6hVvitHecqaM8ybnPEr1OfksAXXUkulAybihaDzStXK6PBCfSnEpwl5zdcO6DqKn45e+gIYMoRbLJfpUWhlIgaKgPbKEd/jmZwqUS9e55WL1S93qj3tQhFeZy6WKEudUunNDRkN871e4odQ5wT4ARjYxfXENgmWRtOqG7HGj0a7A49ySerz69IW3ttUIvE054VXiLz7lMwBmk+dgFCGsqWeGuVO/U9r3QCokv8W51Lij1dxdAUt8oD5bKZp+elHwiVgLNhrw4BaTpkU9lMqxXkEPUn95ha8jGVu+W+U5Szw3GMievIfpxRJ3C1zM8b1mlN6ObTqhcwLwKvtP23bqw/wiAMpXodlYunsUwK88DFDWZfbcW34bnwHXcAjx5AkWGyExNQAtLzxKWdqSer3YHe/flXmjkv2VSoRwHKm30L98CoRd/nqJwQ1yFXyv9T4Y1a627edmEQ06mBZiiG+VRkOVV1LkVdnHI955VPQk+OUZ077fOYr0edax6DWA/EG93Ur+9f/YuOHZWYrMfTjlAXw9OkBzJf7CJSBFYHpQCKw/Dc+slHeGq6G/mps+nntuJbUjdlk1fP4+oaLC/3tv4FcKP4Y7fc6DKMwZQFM7pAhcqc1Eo1CAk4kQQRP+QayK6vDlHOyKu/pVKrPJYP3GfMUZi2I13xXo399yJt+9bP/xcSvpUW+HY+NgyCb/fzj4c8Q0FMR07KJDVdDn7+ccgheENSf93HxcuCrfyhtBqmW//kAwQHw8yNPDE6L12dtsqwSg/CadAovBSdC+Sz1+bny4FVDn+d+X8EO9qAp5e+Azc9iUt5pshbgcnq2UaR6uXxmhfGr5H9ks/Xj+sTFomuiOi9DsZz0wvJwOfA9PhqG1qClpmVlS8m3vKX5ePn4pmdpHrlReBvPxHdgWcEjI0kTr2jxNCS/6yqZLZZah1a2lHzLW5qPl49vepbmk3N8DKTlR7w3eC+LccJgzU1YU7/EI1b/nZSuvxA3XlaZzVAespFelfW3Y7/f/jtcXNiYlp6eShaE3hjgRx/l7S1peRkX2/gTOearumdxMD/9cg38t/hj95xz9DqTep2L5158Mnwar4l/N52Mk34/y8GnnF/n5/028vHL0R+6T48M3adbRgxPybBhTdLSEgCYPMb5Rnj5rq607N6dlh07emTHlmbZvQ2nw0D57MzHj+vkk8vHL1k/kGcOnxMcS71clHMNNsGgWS7DG3iewDSdud8Og4Rx41jhiXWSGWrjh2yTURF8MNX6KulrB+hjx04AhH/239qa0v9m4JSCsU24fZQ7fU69adzp38MUo76zE8Du4QyABhzpseHs1lkJ/Grab/Fi94yVlZkv1D/kQgzAyyiWj7SNfJXkr/hNeAfi8Qnm1XF4SmfVCPW6N8/GHEsNVTmf5wSS1ucIbh2F3VdCtGdbs+zBCO4v+y2WpcYP7n5r1nuCTxZy260i+UVGjpDPYABsVnApBissz5SjgqSpK2u9k/PXZBWskr62neRHP9tfavxg3uZRwKYvl/sEuO2wYAsAW0wD+E/wDDQzSgFFT1rn6lXWtU5+NfX7crLUerPXNjFWrjP/FxObvnxD6Psm/pz4y7+TX2K9PTH33Ou1kWOOZifK9ue8iIlK34oy9FtG9UjLyOSm6E48dNm5A4u3szcytUr2l+o/7Hn80GPkJGwkLVoeANnZgpssE2VDf3wh/BCu7OApIjxLbIBYSkFz3ud5ec1aOZ5Wqp+2BtlQ5YQ9ZWYZ8prVrJXjKbvsP/83Nw2RDxUDLs0yU5nvk1Y9G56FWC7FSC5Jr8+Gcwjwx5b5z2d9tmMi6sAZJT7xwNOGPNnP3bDRxOmhnLEQzITo4buGyLr23tWLUzNPpvA0KVOeJuVJln3G4M304/B7xQeg46pHRJfAEGesFkw9OvhJsa4WNYKtMTb8x+fDm3CwLlJ/zCkw7AA2WU1ZzwqfwNOvVuR5+vy9oXXtIhtfxdmjdaXd27xxdQDwAwQ/3pnfcXH57s5ANrzSCy61eDDx/it9ZT/KvBbsE++nHt+G/0NwnvzQzK+Na30J/hcTP+wFbpp6VPHg0gYLsW9vwTzW4+ZVL8pjeDPPXBX0nbDWYK0ZbKn2ZHyng+9wshbXVnmVZsMa6HijsqAROSqPP7dbZh7vfZnNIVMM6w9PNsnyH5V03Gc1y43ZhMki/M2ntmkIMJZyDYv5DGlu2qIDP55naxYnJ6b6KXli6uHyPkzNJW02VJdtlkLr2sOJuI/6CQCC47bXYIJJihxwrdvJENYxz0tvq/5P5KWncHJiG7mVU+sIkfOv7MSjp2ZF6W127grk/htahM8aJUEjRmV+xHrau3DLEaZ3UjwW5Fm8zHIr2/ADf11ri8xtmxGsp3wpVBbA7GDNy+HMsEsex0mQsfFG1FB80FBzyHgE9tnH8DOsCQXRd3bCtFBOv6gLN9Bpb35Vn/l0TyAPf2eIrF8Z96ZP1T4F+PtP78KlgEOPREwwwi0mVKSl8R4tVgo0vu+mWuTEyYdm7nPus7OYQLztWHXh4urfh3Ng4SMweDitZGM0Pso7dfL5vqinHsYVGtx+U02aNCstJ1/QXdJ6zPX7l/c2y6svZa+9SdvJ+67nnIFN2Xi07CPrx8zLQ2onYnnKlFnBk+XaUhHA7HRNe3hmkJYlGMm6cEWjFnXmw3OPizz/K8egUpVp9P4I5Nnd0jaz7zV53R+a5MkfN8m2NyoORVFeMT6HY/dy9MluQEDLYsYGLI9DrTtsknMmzwgeJL9cSsSrte3hBUDzewZyZijj9prtIo/9CDvjteWaV5ne2ImhTDkiLROmpWXkvqHw5wK4E96+FTvllSlZ80IK13wTCUHJhh54iMj7/hJPUGKdtilbZz+0BJC78f/hSTOCe0puOKaQmHfYeJ0JA3+AR0iHs1G+jPNn/50BOdbnYNFFYBjW5lM+mHm3pQUFa/RO/J/XNq2ykRu1Z5kk0tdWhnMA8o83vCJjH7kvc1IiiXYHchu8sf9UgMxbkDAweFHn7IOnl7/mxmOV2Ai2hl/6dXj0g9+X3+zYmlmTjT+Y5o8A3/Y37zx5A9+dT5owubzdcr7WE982HnZ88OxRx8psPFGAk4uDVEwE8FtR2/CmntOTBpd9Jz6CzaGVPw1bf/VbWb62XWYbbzDdOwKHvFOeOeEYee/09+tDB3sLVMipGsBm1/dvCL+yZoUswkWCqvdlfTZCircqhJiSr73wiuCqatrbL0Ff+t3wPRva5SF8XcL1l0Ead7C8NeEQWXDuxcHyakejXwCmE7xp4L6vy7dfeUk+ipeWJL72VztQSbSPVzSmpx4m3z3vn+TjxV7PrbTffgPYDP2fW8JZmzbJktfXyFTj/TmkB02WVeMnyFnnXhLgomj/Ub8DbK4tuSP82PrV8nW8iHS08QZiium448CDZdFfXRbcUQv/agawOXv/7eG/rG+XxXj+F+d1Bg7tN062T5wu1/31xcE1tfSq5gDT+fDqMHX/GPn0lj/JIjwLNLaWAam073ETZcuYcXLzBZ+qLbDmR10AbMYwffie8PwNq+Rq/M9slK9W+L2kcMI0+T12xl887W8CnKStH6o7gC00990SHoDbgr6w9U05H+v0ODxaUle24lUX4f4Hyxu48e6HY/aVq85Y2Pc9yuZbf6Z1FbR8jv9ySThl83r53OYNcvqbr8tEvMKoJl+zcHIifUCbvDZugjy070Fy3UnnBKvz2Vwv/IYA2A8W1+ulE2UBfgzygm1b5QSs2wfhMVK92cCXSyI/eox04bbY10eOlicxDd87eqMsmXd1aTe9JWFHJW00HMC5nH3ga+H4cKicjJv5jtvTKYd37pQpeJfHGNw/3Yon85vxzstm5FP4V3+bcJoQ7yJJ4ypOD26G6wZ4u3Ft9q2hw2V1yxB5Cde0n9mzXR69cHFQ5RuMcnmTLO//ARuOpjxgjP1GAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:60px 60px;margin-left:20px}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li .dialog_content_dialogue_pp[data-v-1c392dd0]{height:50px;background:#F5F5F5;border-radius:25px;font-family:PingFangSC-Regular;font-size:14px;color:#000;line-height:50px;font-weight:400;padding:0 16px;box-sizing:border-box}.voice_chat .voice_chat_dialog_wrapper .dialog_box .dialog_content li .dialog_content_dialogue_user[data-v-1c392dd0]{height:50px;background:rgba(41,50,225,.9);border-radius:25px;font-family:PingFangSC-Regular;font-size:14px;color:#fff;line-height:50px;font-weight:400;padding:0 16px;box-sizing:border-box}.voice_chat .voice_chat_dialog_wrapper .dialog_box .move_dialogue[data-v-1c392dd0]{justify-content:flex-end}.voice_chat .voice_chat_dialog_wrapper .btn_end_dialog[data-v-1c392dd0]{width:124px;height:42px;line-height:42px;background:#FFFFFF;box-shadow:0 4px 16px #00000017;border-radius:21px;padding:0 24px;box-sizing:border-box;position:absolute;left:50%;bottom:40px;transform:translate(-50%);display:flex;justify-content:space-between;align-items:center;cursor:pointer}.voice_chat .voice_chat_dialog_wrapper .btn_end_dialog span[data-v-1c392dd0]{display:inline-block}.voice_chat .voice_chat_dialog_wrapper .btn_end_dialog span[data-v-1c392dd0]:nth-of-type(1){width:16px;height:16px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAByElEQVQ4jZWRMWhTURSGv3NeHDR9NoPZBKuCgw6irYv0XR5dupWKZBFxcBREBHFyEEFaKc52LlYoxU4iCA7pLZhBIrpata6CoMT34pC+exw0xaZJaf/tcP7/47/nCgNkaVrKQ1gv5/kZaTbbg3z6/9BybqqVJI//jSWDkV+VykGAzLmZLEkmBwKyJHkksKgiH/o2gvcmspQ5N7sDkDl3x0SuBTg/5P1CP0Ds/VIB5wyuZs7d2gL8npg4ZvDA4PKw9+uD3gpQ8X5DRS4ZzLTT9CiAFp3ODYHXh71/s1u4q/Lq6lvgRSiKmwBqqpMGizuc1WoHaMRFkfeuDJ6ayDRACbOTCh97TbK8XAAX+7WQovhMFJ0wEAUsqHb2Ur+rIorawCaAIvKFEE7tByBmp4GvAqYSwitEavsCiNTM7CWAborMYzaVp+nYXsLZ+PhZgZpF0RMArXi/YWb3QwgrP507vlv4R5qOmOqKiTwcrtc/AUh32XJuTuC6wd04zxek2dw6rI2OHsjL5SsGc8CzIe9vC9g2AEArSaZFdRazqkAD+GZwhL/f+R2ze/Ha2vNt9+itaSCtJLmgqmNmFotZW6OocahefycQev1/AL5Esl64D4xbAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:16px 16px}.voice_chat .voice_chat_dialog_wrapper .btn_end_dialog span[data-v-1c392dd0]:nth-of-type(2){height:20px;font-family:PingFangSC-Regular;font-size:14px;color:#f33e3e;text-align:center;font-weight:400;line-height:20px;margin-left:4px}.audioFileIdentification[data-v-4bd99869]{width:1106px;height:270px;padding-top:40px;box-sizing:border-box;display:flex}.audioFileIdentification .public_recognition_speech[data-v-4bd99869]{width:295px;height:230px;padding-top:32px;box-sizing:border-box}.audioFileIdentification .public_recognition_speech .upload_img[data-v-4bd99869]{width:116px;height:116px;background:#2932E1;border-radius:50%;margin-left:98px;cursor:pointer;margin-bottom:20px;display:flex;justify-content:center;align-items:center}.audioFileIdentification .public_recognition_speech .upload_img .upload_img_back[data-v-4bd99869]{width:34.38px;height:30.82px;background:#2932E1;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAABnElEQVRoge2Yz0pbQRSHf0dCNnbnVh/BRRdaxS6isXXRtZaCCxfiU7i0+AjFN/APon2AbvoKfYPqzoJKigURPxdOYHK5iUmdm3uN54PAOTeHmd8HkwxcyXEcx3Gc4gE+AW/LzvEsgBXgH3AJzJad578APgaJNi9PBviQkWhzBbwrO19fAMvATY5ELDNXds6eAEsZid9R/Seqr4H5svPmArwHWlHYA2Az6reA06j/CzTKzt0BsJCROAJqwEb0bAOoAycZmcUUGcZSLCKpIelNqA8lfTGzu+yQmd1K+izpe3g0LinJ76WWYhEz+wrcSZqRtJ4nEc3eAquS9iX9MrPdFBmSAoxl+o6j1Wv2uSRdzMzui5jth6QiZeIiVcNFqkbPewSYkrQd2h9mdlh8pI791yQ1Q7tjZmfdZp+6ECckbYX6Ro+39jCZj/b/JqmryOs4Wgk4lvQz1BdFblSoiJm1JLWK3KPNyBwtF6kaLlI1RkZkkL/fJrBXWJJ8+n5lNIjIdPhUkpE5WtbrS6AuaXJIWZ7iPLxOchzHcRynGw8cd1AmwUMUzAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:34.38px 30.82px;cursor:pointer}.audioFileIdentification .public_recognition_speech .upload_img[data-v-4bd99869]:hover{opacity:.9}.audioFileIdentification .public_recognition_speech .speech_text[data-v-4bd99869]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-left:124px;margin-bottom:10px}.audioFileIdentification .public_recognition_speech .speech_text_prompt[data-v-4bd99869]{height:20px;font-family:PingFangSC-Regular;font-size:14px;color:#999;font-weight:400;margin-left:84px}.audioFileIdentification .on_the_cross_speech[data-v-4bd99869]{width:295px;height:230px;padding-top:32px;box-sizing:border-box}.audioFileIdentification .on_the_cross_speech .on_the_upload_img[data-v-4bd99869]{width:116px;height:116px;background:#7278F5;border-radius:50%;margin-left:98px;cursor:pointer;margin-bottom:20px;display:flex;justify-content:center;align-items:center}.audioFileIdentification .on_the_cross_speech .on_the_upload_img .on_the_upload_img_back[data-v-4bd99869]{width:34.38px;height:30.82px;background:#7278F5;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAABnElEQVRoge2Yz0pbQRSHf0dCNnbnVh/BRRdaxS6isXXRtZaCCxfiU7i0+AjFN/APon2AbvoKfYPqzoJKigURPxdOYHK5iUmdm3uN54PAOTeHmd8HkwxcyXEcx3Gc4gE+AW/LzvEsgBXgH3AJzJad578APgaJNi9PBviQkWhzBbwrO19fAMvATY5ELDNXds6eAEsZid9R/Seqr4H5svPmArwHWlHYA2Az6reA06j/CzTKzt0BsJCROAJqwEb0bAOoAycZmcUUGcZSLCKpIelNqA8lfTGzu+yQmd1K+izpe3g0LinJ76WWYhEz+wrcSZqRtJ4nEc3eAquS9iX9MrPdFBmSAoxl+o6j1Wv2uSRdzMzui5jth6QiZeIiVcNFqkbPewSYkrQd2h9mdlh8pI791yQ1Q7tjZmfdZp+6ECckbYX6Ro+39jCZj/b/JqmryOs4Wgk4lvQz1BdFblSoiJm1JLWK3KPNyBwtF6kaLlI1RkZkkL/fJrBXWJJ8+n5lNIjIdPhUkpE5WtbrS6AuaXJIWZ7iPLxOchzHcRynGw8cd1AmwUMUzAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:34.38px 30.82px;cursor:pointer}.audioFileIdentification .on_the_cross_speech .on_the_speech_text[data-v-4bd99869]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-left:124px;margin-bottom:10px;display:flex;align-items:center}.audioFileIdentification .on_the_cross_speech .on_the_speech_text .on_the_speech_loading[data-v-4bd99869]{display:inline-block;width:16px;height:16px;background:#7278F5;margin-right:8px}.audioFileIdentification .public_recognition_speech_start[data-v-4bd99869]{width:295px;height:230px;padding-top:32px;box-sizing:border-box;position:relative}.audioFileIdentification .public_recognition_speech_start .public_recognition_speech_content[data-v-4bd99869]{width:100%;position:absolute;top:40px;left:50%;transform:translate(-50%);display:flex;justify-content:center;align-items:center}.audioFileIdentification .public_recognition_speech_start .public_recognition_speech_content .public_recognition_speech_title[data-v-4bd99869]{height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#000;font-weight:400}.audioFileIdentification .public_recognition_speech_start .public_recognition_speech_content .public_recognition_speech_again[data-v-4bd99869]{height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#2932e1;font-weight:400;margin-left:30px;cursor:pointer}.audioFileIdentification .public_recognition_speech_start .public_recognition_speech_content .public_recognition_speech_play[data-v-4bd99869]{height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#2932e1;font-weight:400;margin-left:20px;cursor:pointer}.audioFileIdentification .public_recognition_speech_start .speech_promp[data-v-4bd99869]{position:absolute;top:112px;left:50%;transform:translate(-50%);width:142px;height:44px;background:#2932E1;border-radius:22px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;text-align:center;line-height:44px;font-weight:500;cursor:pointer}.audioFileIdentification .public_recognition_speech_identify[data-v-4bd99869]{width:295px;height:230px;padding-top:32px;box-sizing:border-box;position:relative}.audioFileIdentification .public_recognition_speech_identify .public_recognition_speech_identify_box[data-v-4bd99869]{width:143px;height:44px;background:#7278F5;border-radius:22px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;justify-content:center;align-items:center;cursor:pointer}.audioFileIdentification .public_recognition_speech_identify .public_recognition_speech_identify_box .public_recognition_speech_identify_back_img[data-v-4bd99869]{width:16px;height:16px}.audioFileIdentification .public_recognition_speech_identify .public_recognition_speech_identify_box .public_recognition__identify_the_promp[data-v-4bd99869]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;margin-left:12px}.audioFileIdentification .public_recognition_speech_identify_ahain[data-v-4bd99869]{width:295px;height:230px;padding-top:32px;box-sizing:border-box;position:relative;cursor:pointer}.audioFileIdentification .public_recognition_speech_identify_ahain .public_recognition_speech_identify_box_btn[data-v-4bd99869]{width:143px;height:44px;background:#2932E1;border-radius:22px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;justify-content:center;align-items:center;cursor:pointer}.audioFileIdentification .public_recognition_speech_identify_ahain .public_recognition_speech_identify_box_btn .public_recognition__identify_the_btn[data-v-4bd99869]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500}.audioFileIdentification .public_recognition_point_to[data-v-4bd99869]{width:47px;height:67px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:47px 67px;margin-top:91px;margin-right:67px}.audioFileIdentification .public_recognition_result[data-v-4bd99869]{width:680px;height:230px;background:#FAFAFA;padding:40px 50px 0}.audioFileIdentification .public_recognition_result div[data-v-4bd99869]:nth-of-type(1){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500;margin-bottom:20px}.audioFileIdentification .public_recognition_result div[data-v-4bd99869]:nth-of-type(2){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500}.server_input[data-v-1bbbdb64]{width:600px}.server_input .serverAddress[data-v-1bbbdb64]{width:400px}.server_input .serverConnect[data-v-1bbbdb64]{margin-left:20px}.realTime[data-v-1bbbdb64]{width:1106px;height:270px;padding-top:40px;box-sizing:border-box;display:flex}.realTime .public_recognition_speech[data-v-1bbbdb64]{width:295px;height:230px;padding-top:0;box-sizing:border-box}.realTime .public_recognition_speech .endToEndIdentification_start_recorder_img[data-v-1bbbdb64]{width:116px;height:116px;background:#2932E1;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAQMElEQVR4nO2de3xU5ZnHv8+ZyYUkJIGEgNwSLpKEKJgMwmqpBlArXW3tVv1Q78qnunbFC9XWlbqrtVpFilY+2lqrYFFWrVK3VUHFLO3qtkguiIaEi5gJF5UQLrmRkJnz7B+TBEJIyFzPGZjvXzNz3ssv+c175r0873uEKKagoDJeEpLHeSEPlQkqmivIKJAU0GSBZIVBQHJHlmaB/QrNIM2gTSC1qG5BdIsDqrWt+fPKyoLDVv5dwSBWC/CHCZN3jHAY5kwVnSHIdGAM4AxxNR5Et6vykYGUeFVKNleM3h3iOsKGrQ11uUrjWs2s2aahs1FmALkWSdmMaomKrEqWutVlZVPaLdJxQmxp6MTJ7gJ1cq0qNwpkWa3nGPYL/FGE5ZVl2R9aLeZYbGPoWNfnaQnqvAW4Aci3WE5/qQKWtYnn2e1l4w5aLQZsYOgE1+5Mp7bfpnA7vg5MNNKoylIx9NGqspwvrRRimaFnTNs+1Otx3IUyD0iySkeIaVbleY/X8fi2jSN3WiEg4oa6XKVxLQz5EcrDHBlOnGwcEljYkmo+WrN2TGskK46oobmumhmGytNEz29ksGwzMOZVlo9aHakKI2LohMk7Rjgc5mLgykjUZ0NeNVXmR2I8G3ZD84rclwgsAzLCXZfNOaiqc6srct4IZyVhM7S4WJ17Gmp/pnA/YISrnihDVVniONx0T7imF8Ni6Bln7xrl9XpeAc4NR/nRjsJ608GcLeuzt4e67JAbml9Yex7onxAGh7rskwpln4hctql89P+GstiQ3goLCmu/g+jqmJn9QBis6PsFhe7LQ1lsyAzNc7mvN0XfAAaEqsxTgARTeCWvyH1zqAoMiaH5Lvcdoiwl9EtZpwIOgd9OLHI/EIrCgjY0v6h2AcqT2GBeOIoRhf+cWFR7X9AFBZM5v9B9HcKyYMuJ0YUienNVWc7vAy0gYCPyityXCqwkdpsNNV5Fr6wuz1kZSOaADM0rrDlHRNZw8qyS2I1DgnwrkCGN34bmF27PRhwVRO/aZbRQb4inqLJsXK0/mfzqFLlcpXGIYwUxMyNBhqmO1woKKuP9yeSXoYfIfJTYdF4EkWlmQspDfuXob8L8KTXfxpS3/MkTIySooXJZZcXoP/cncb/M6YiH3Rib0rOMvYhO6k+8Ur9uuQ6HuThmpqVkimks6k/CE7bQ/CnuCzF5L3hNMYJFlAs2VWR/0Geavi4WFFTGmwkpG7EuYj1Gd7a2Nxw+c9u209t6S9DnLdebmHIvMTPtxOnOtPj5fSXotYV2BHZtJbYcZjdaEB3fWwep1xbqcJh3EzPTjiSpGr220uO20LypOzPE460BUsKlKkZQNHslLmdL2fC9x144fgv1eOYTM9POJDvN9nnHu9CjhXbsAqsB0sOtKlykpxlcODOJ4vMGkD3KSUaGg9ZWZU+dl49LW3m/pIWNn0XtJu1ODiaYZs6GDWMOHP1hD0Pzi9w/AR6LmKwQEh8v3HjtQOZen0pKct9zJv+3rpWFi/ezZZtt9+6eEBG9Z1NZTrcJh56GutyfoRRETlZoGDzYwVOLMimanND12c5dHso3tFG/z0tiosHYMU5cZyXgdPr+7NZW5T8e2sdbq5utkh0sm6rKs7t51c3Qgik7ppqmuS6ymoInOclgxbKhnD4uDoBPPm3jV08doLS85/g7LdVg7vWpXHfVQOLjBVX48b/vZfX7LZGWHRpEXVVlOeWdb7vdl9TUayOvKHgefmBwl5krXmvkmrlfH9dMgIMNJouXHOCmf93D/gMmIvDIgxmMGxsXScmhQ6WbZ12GulylcYrOibyi4Jg2JZGLZvkiYd55t4WHF+7H6z1xvvJP2pj34zra25XEBOGnd0Xnmr3CVS5Xade3scvQVjNrNpBpiaoguGVuKuBreQ89ug/V/uct39DGy682ATD93ERyJ/gVHGALBLJayLyo832Xoaahs62RFDjpaQZnuxIB+OPKJg42mH6X8fyLDXg7sl18QXTGvIkaF3e+Puo3VGdaISYYJp+ZgMPhe13y10MBlVG/z8vGT9s6you+FgqgR3lnAOQW1g5HZYJ1kgIja4ij6/UXNYGPJ2tqPQCMGB61IcYTcwtrh0OHoQY6y1o9gZGWduQG09jk/+22k4MHfXkHDozefclimMXQYaiKzrBUTYCEKlpN8aMnZVPElBnQYagI37BWToxgEWE6gFFQUBmPylirBcUIDoXxLldpnEF8ynhiG45OBpxNMnisYYrGYoZOEpxeZ66hIjFDTxJMMXMNQ2NRfScNYuQaqoywWkeMEKGabSAy0GodMUJGhoGorQ2dc3kKTy7MZGiW48SJw8SFM5N4evEQJoy3+5qpZBiovaP77r5jEBfNSuKyS607Wvf2W9OYcf4ArrrS1t99QAcaKLZW2dTsm2cdadHEuWEcmbTv1GJjEgzE3i20dodvJWTMmJ63O4/nyOv4+MBnduM7gsba2nrO6Q4b6iQx0Xe9dqenx3WbkWD75YVN1b742Ym58T1M+/LrI//go5fS/GV4Rwusq+sZuzLpjCNrpFXV9o/lNVCarBbRF+tKfUe2JyZKjwXoL9xHDJ3aEbngL06nUNgR+vn5Fz3XVM+Z5iu3sdFkU5XtDW0zEBqtVtEXpWVtXUFf50ztbtqWrYfZuctn6r98N7BO06ziAaR3rKv+z996Rj101rm+rK0rVMXGtBmIvVtoY5PJJ5/5QkQumZ2McXTQjMLKP/uCpM+alMAlF/tnalKSMH+eb8fHnjovf/uwu6FFZyUwcoTvdvzh3wMLcYkwDQYqtm6hAG+86fvOjRzh5Jvndt/h+OLLDXy9x9eEH/zZYM4s6F9cUFyc8PjDmYwa6TNsyW8P0npMp2jOFb7+Ymur8s57URGIXW+gantDV73b0hXRd/Wc7qOsQ4eUe++vx+NRBgwQXvzdUL73ne4t+VhGjXSy9NksZpzn+3K890ELK/+7+40qa4iDi2b6ogDfXt1MQwARhRFHqXdkDb9rJnCW1Vr6wuOFQekGhZMTGD3KyYaNbew4agixa7eHHbu8FH9zAAkJwqziJGYVDyApycA0FREYOtTJ2UWJ/PDGVB64b3DX2HLd+lbm37uX9mP6Qwt+OpiC/HhU4f6H9rG3vh/R21ZjyFrJc7nvFeWXVms5EelpBqvfHE5qqsH2mnauuOYrDh3qfossOiuBhb/IYPhpJ56E8HrhpVcaWfTrnpH2U12JLH02CxF4e3UL9yzosa/WpuhPHEOGz88EbL8ForVNaTmknDd9AIPSHQzLcvLB2u4dlS+/8vLK600cOGgyZIiTzIyeY9PGRpN317Rwz4J63lrV3CPSPmOwg+d/k0VyskFTs8ntd9fR1BwdQWSKLJEzimryvcgmq8X0BxF45skhnD/d99v33LIGnlhyoNf0pw1zkpPtZEimg8Ymk7o6L9Vb2vF4jm/QoHSDF36T1bUl4p4Fe3l7dVR0hgBQryNXOs4iaiZK4orS0wxeemEoY3N8U4Gvvt7Eo7/aT9vh4FrR2Jw4nlyYyfiOXWwvvtzIY4v3B603grQnSV2yAOS7ajZHU+R81hAHf3huKKNH+b6D1ZsP88ii/b1uIeyL+HhhzuUp3H5rOklJvqnF11Y28eAj/m18shqB6k3l2fkCkFdU84IgN1otyh/S0wwW/TKTc6cdmT36x8etvPlWMyVrD51wZSQn28m3L0rm+5clc9ow3xfDa8ITSw6wdHlDVJkJgPL7qorsH/paaKH7WoQ/WK3JXxwG/ODKgdx2SxqpqUcGnl4Tamraqd7SzoEDXhqaTOKcQupAg9OGOcjPi+/RYaqsOszDC/ezYaP/rdwOqOjV1WU5KwR8m5UM0V1WiwqUQekGV34/hSu+l9KvIcvRfFzWyorXmlhT0oIZBXMHvaCIjqgqy/myaz0qv8hdTZSf62cYkJ8bz1RXIgUT4xkx3MHYnLiuTUi7dnvYucuDe4eHik/a+Pu6VvYcZ8ksCuk6POPI11m1hCiP0TVN362z8qhlrptvSuXOf/NNwF94adifx2oJgpR0vu764VGRVdbIiREsaphd3nUZOix19CqUr62RFCNQFPYk6d73O993Gbp2rXjU4DVrZMUIFEFfLiub0rW00K1L6PDKctPQ4x4KaCdmFQ/wrYv2Iy5sYu6R9dEHFvTv2PzWVuXlVxrZscv2QWGIwfJu749NkF/k/hQ4I2KK/MTpFMo/Gtl1vFu4eOfdFu6+z/arLD2OhjveoG05Nj680eNR/vSXZv5pamBBYf3B9MK7a+w/KS+iS3t8duwH46dtTY1rj3cTxcerniIc93jVHoEa29ad3qDoM5HTFSMQRPn1sWZCbydaO52Lwd7RgKc4zR4jbsnxLhzX0OqPR9aDPhdeTTGC4JnjnTcPfTwVwlRjERAVwainGM2Gw1zc28VeDd1cMXo3orYPHjvVUOEXlevHfNXb9T43KxmtzY8JVIdeVoyAEN3iOXj4ib6S9GloZWXBYVVsP3N0qmAot/b13DPox+Mmqyqy10BsjtdqRGVFZXlOyYnS9Wt/qKlyF1AftKoYgbJXDfPu/iTsl6GbK0bvxtDr4CQ4tjL6UENlbn+e7gt+PFS9qjTnHVHptbscI0wIC/v7/G3ww1CArLRR94rykf+qYgSGrkui7n5/cvi9BpVfuD0bHOWxZ3KHnXqHw1n42foRO/zJ5PehGVUVY92I+c9A1D5fKgo4ZAiX+WsmBGAoQFX5mH8o/ACw/5J+9OFV9JrKsuwPA8kc8LE21eXZf0G5iVjPN5QoqrdUl+esDLSAoM4pqqrIXi7Iz4IpI8YRVFhQVZHzfDBlhCQwJ9/lvgPliVCVdwqiAj/fVJ79QLAFhcyA/EL3dQjPEyX7TG2EV+HW6vLskKw/h7RF5RW5LxV4FRhwwsQxANpU9erqipw3QlVgyG+RBS73dFN5E8gIddknGfWmwXc3l2aHdKIm5Ic3VpZlf+hwOAtjM0p9oHxsevTsUJsJYTAU4LP1I3ZkpY0uFngQiN5dl6FHVXkqyaibvnljzhfhqCDsvdL8QvcFwEsIQ8Ndl83Zi6HXV5XmvBPOSsJ+Xm5VRfYaDC1E9L/CXZddEZUViE4Kt5kQ4XFjXuGO88Uwn0YpOHHqk4KtKnJbddno9yJVYURPtK6uGPXXJOoKEe7k5A7kbhF4sL3h8JmRNBMsnNmZNGlblscZ9yOFO4E0q3SEmCZVXlDksc0Voy3Z/2/5VF3e1J0Zhsc7T5V5UbzG2ojwjDocj/t2HViH5YZ2Mn7a1tR4T9zNitwQNb+xQqWgyw4723+3bd3pDVbLARsZejQTJ7sL1Mm1mNxgu+GOsk+E10VYHuiaZTixpaGdFBer8+tG97dQYzboTCDfIimbBClRw1w1NCX7vbVrxbYL+7Y29FjyXTWniTJTxZghqt9QGAeE+oFk7QKfq8hHilniMLSkr70kdiOqDD0Wl6s0rkkGj3V4nHlqaC4iEzB1NAZDUDKAFHyGdz49qgloB5oQ6jGpw5Ba1NwsprHF6/RUp+i+7UefKhJt/D+IYnHePFNWNgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:116px 116px;margin-left:98px;cursor:pointer;margin-bottom:20px}.realTime .public_recognition_speech .endToEndIdentification_start_recorder_img[data-v-1bbbdb64]:hover{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAP8UlEQVR4nO2de3hU5Z3HP79zZjLJTC6EIFRYQO4gaOuNeqsVdLXU6urzaJddvFW3cb2gJnENSPvstKsmRAm2VNfauvIs1npF65WqxaqAt/WGV1BAUMFaEiDJTJKZOee3f5zcE0LmlpmJ83mePJPJnPO+v8n3/N7zvr/3955XyGD8fs3ZG2yaJIY5XbCniso0hLEK+YCv7ae47RUgAOxpew0INCnsAN2sGJvVtj4e5s3f4vdLKDXfKH4k1QZEQ9mS4BjDtudiyxxb9ERBJgCuBFcTAd0qKusVXetSWVtT49uZ4DqSRloLWlqq7vyS4DxR5oHMUXRaKuwQZJOKrlWbZwJ7vGvuukvCqbBjIKSloGWVjTNFzAtAfwKMTLU9Pdij8JChxqplS/PWpdqYnqSNoJWV9UURI+cyVbkYmJFqewbIRyK60mWHfrt06fB9qTYG0kDQioqGEeo2rwKuxunAZCDSCPY9tiHVt93s25VSS1JV8TU3NI0ybaMMdCHgTZUdCSYAerfLNm6pqfF+kQoDBl3Q0lJ1FxQ3X6GiN9E5nBhqNAM1hbnear9fWgaz4kEVtPyGxjnYxu1kzj0yXj5VdOHy6vw1g1XhoAjaNn6sVZUfD0Z96Yc+4LKlfDDGs0kXtHxx4EeirFQoSXZdac4+kEtrq72PJLOSpAnq96uroSX4M+DngJGsejIMBV1RmOv7j2SFF5MiaPmS4FgsvR84PhnlDwHeUMz5y6tztya64IQLWlHZfJIa9qMowxNd9pBCqFeMs5dX5b2cyGIT2hSWLw6cpWKvyYo5AJThovZzFYuD5yay2IQJWra46SKUR4C8RJX5DcCjqvdXLAqUJqrAhAhaURm8RlTuIfFTWd8ETIU7yxcF/IkoLG5ByxcFlqjobaRBXDiDEeA/KyoDNySioJgpr2y6EJGV8ZaTpQMVKF1W7ft9rAXELERZZeBMEVaTbWYTjSUiP15W5V0dy8kxCXrt4uBxhurzDJ1ZknSjWcU4PZYhTdSCVixpHq+W/TYZO3eZGQjURdQ48ldL83ZEc15UnaLSUnWrZd9HVsyko1BiiP2g36850ZwXlaD5xYFqsuG8QUPguw3Nzf8V5TkDo3xx4IcoT0ZzTpaEoAhn11b5Hh/IwQMSp2xJcIzYujEb0ksZu22DwweSrzSgJtew7dqsmCllhKFy60AOPKCHVlzf9I9qyLPx25Qlbgw9tfbm/L/0e0h/H/r9moNhrEisVVliRW3+e+FC9fR3TL+C7msOLkrV8oMsvRFkitsXKO//mP1QtiQ4Riz9hOx0WLoRtA0m76+DtF8PlYh9HVkx0xGvYcl+vbRPD71ycUOJR83PcNZZZkk/AhK2Dlm2rHB3zw/69NAczHKyYqYzPnLMhX190MtDKyvri8J4PkMYlmyrkoXPKxw20+TQGSYjSoSCfCEcgX37lC3bLDa+b7HjczvVZsbLPjs3dMht/uK9Xf/Yay4zYuRchmammC4XnPw9N3O+7yLX0/tuUlQojBtrMOckN5s/sXj86TC7vspYYYuMVve/Ad0CDr0EVZULB82kBJKfL1x8vocJ4zvvIvV7lG2fWTQ2KW63MGqkMGG8iWnC1CkmV19h8tDqEG+9E0mh5XGg8hN6CNrtMi67PjhbDH1tUI1KAB6PcPXlHr41yhFz+w6bJ9eE2Lqtt/d5vcKck1ycdIIblwtU4d77W3lnozXYZicE2+Co2272vdX+vlunSAy9YPBNip/55+Z0iLn+lQi/+W1Ln2ICBIPKU2vC3Pn7FgIBRQTmn+th1MjMXK1hWN016/gWpaXqBuYPukVxMnmiyeGzTADeftfi0SdC2AO4LW7bbnPPva1YFrjdcNYZ7iRbmiRE/rVNO6CLoPklwXnAiJQYFQenznW6AcGgsvrxEKoDP3fbZzbrXnHun9Onmow+OCO9dGRhcfC09jcd38B5dExm4fMKkyY43vnqGxGCwSjUbOOFF8MdHv3tw8xEmjdo2MIP2n/vEFTRuakxJ3bGjTMw2r7BBx/G1qlpbNKOMen4cRnpoQAd2hkA118fGA0yNXX2xEZRQWcn/evd0XtnO3/f7Qg6fFjGCnqoo2GboJapp6TWntjwejsFbW6OXdBgs/Oam8FTEWHRk6G9ybVlTiqNiZkEpatpND2pNEXE0dAAUNETUmtOlviREwEMJ5FXJqbanCzxopNLS9VtNLY2TSa74Ggo4Mob1jjRsNXM5gwNEUzTnGYYamcFHSKo6jRDRbKCDhFEZZqBMCbVhmRJDCKMN1AKUm1IlsSgUGJAegt6/LEuLlrgoagwdYveDptpcsmFHg7+VtqHBksM0jy770fzcjh8lskxR6VuZDXvNDczZ5iccGzaj+4KDCS9PbS1xQnLDR+eGg8VgeJixzNbWtM+ROgx0PT20N11zj9x5EG9mzu7y4yZOw7ncZnOxRLpI1dsWJGQ05YPUFefCYKmOV/sdKa2xow2cPUQbe++zlyTwjjuscXFzrkNDb0F6zpH+uXO9E/5NBCaUm1Ef3y6xXHDHDeMH9v9+vv6750CTJoYW7aBacIhbamff/u6t2BTJjvlNrcoX3yZ9oK2GiiNqbaiP7ZssztSRNr/ue3s+sqmfo8j6uyjY2tzZx1q4mubV/3go95ZD1Pb6tyy1R5Q8lmKaTUgvT20pUXZ3pYictQRLqRLy6oKr/+fc+M7ZJzBkd+JTlRPDpxxuvPUmIYG5aNN3QWdcIjB8LbmeNMnGZG322BAensowOtvOKINLxamT+vupS+uC7Ov7d533jk5jBs7sG6BacKC+R5KShzB1jwXJtxjR7Pjv+tcIKGwkyKa9ih1BpL+gr69sTOj73vHdffCUAjueyCEZUFODlz+01xmH9Xdk3tSUiJc/tNcZs5wLo6N71u8/mb3Lm5hoXD4LKeut9+NxJXiMmgY1JnHnbhkLvCdVNvSH7YNPp+zLmVEicH2HXa3IUT9HqWuXpk5w8Ttcu6Lsw418eQItjpjyaIig0kTDE452c25Z3s6mtJPt1j87x+dhOuunHNWDmPHGKjCg6tDNDZmgKDKX12iukn7u5zThBdejHDsMS7y8oSzz3Sz/DcWoS77Krz1ToQ9e20W/LOH4mHC6IONtsTpvjPibRvWbYjwxDO9M+0nTTQ5+gjHO9/ZaGXEcAVARTeZx5+0ZAQZsAQiHIbWEMyYZuLzCcOKhPd75OLu3atseM1pnosKnXWhPWluUTa+Z/GHB0K8+U6kV6Z9Qb5w2aUecj1CS6uyclUrLa3J/GYJRGWFy7LsTYaR9vEFADa8GmHGVJMZ002OPtJFQ4Py1J+792QiEXhpfYSX1kcoHiYcNMKgoEBoaVEaGpWdu+xezWs7Pp9QeomHwrZ834cfDbF3XwY0tW2IYW4Sv19zGlqCATIkr8jnFa76d09HKHDDaxH+9GSoz7BdNIw8yOCiBZ2r2F5aF+FPT2XUVtzhpnqvTwDKFzVtyqTM+cJC4crSXEa0DTm+3GXz2BN9rwc9EC6XMzz5wWk5eNoeZPrq6xEefiy6hU+pRz6urfbOcAGIynoVMkbQhgbl13e0cP78HKZOMRlzsMGVpbl8ssXijTctPvjQOuDMyEEjhCO+7WL20S6KhzkXhm3D038O89eXwxkmJoCug/Zm1tAX2pZ3ZwyBoPK7la2ccKyL0091k5cnTJlkMmWSiW0761V27lICAaW5RTFNyMsViocJY0Y799WufPGlzaOPh/hsR2b0aHuiqi9Am6CmJX+JZEa/qBu2DS9viPDWuxbHzXZx7GzH2wwDRo00GDWA7di3bLVY90qE9z6wMtArO1A15QXosjqkYlHw40x/rp+IM802eaLJP4xx4rAjRwp5uc7XrN+j1Nfb7K5Ttm232fyp1eeUWQbyYW21byZ06dmq6FqUjBZU1Wk6u05znTLHzQ9Pc4ILN9U0p8q0ZLO2/ZfOBb82z6TGlixxI53adQhalOd9BvhbSgzKEg9fN9V5n2t/0yGo3y8RhAdTY1OWWFH0D3fdJR3hsm7RIVFWKfT5UMB0YtahJtOnmv1OkbUzZnRn9/28cwa2BUooDOs2hDMhKQxBVnV/34PyRYH3gFmDZlGUmCZU/cKLmeQHlrz9rsW996d9VL6jd9tOr/itiK5SlaWDZ1N0WBa88VaEKZOSp6ja8O57GfD8P9F7ev6pl6AhT+ud7ubcxen8eNWHVmdU0DxZ7LM94V7bUvaKD63wlzSowR2DY1OWWBHhVz2flQv7eaJ1CKuWNM8G/IYTIGT1uf1Kn4LeXlVYp+jvkmtTllgR5I6+njcP/ewK4bblVmDIxsoymIBh2bX7+3C/gtbU+HYCVUkxKUvMiOqNt9yS/9X+Pu930qww17sU5OPEm5UlNnRzKOhb3t8RB9j7TEKKnfaRo28KBnr5ihXSb7TjgNPay6vznxfRbIw31Yjcd2t1wdoDHTagPAXTkjKBuvityhIju23R6wZy4IAEranx7VThQiD9o9VDD0W4dCC7+0IUm6rXVvmeFmS/3eUsyUJqBrr/NkQhKEBBbt4iYH3UNmWJCYXXmurzfh7NOVEJ6vdLRExjAUJ9dKZliRaBOjHlvK6T1wMh6uTNZTflbceSM4BAtOdmGTDNqHF27U3ez6M9MaZs3Noa76uq/AuQAZOGGYclIucvW5q3LpaTY06vXr7U94SIXkK255tIVIXLllV5V8daQFz58suq8leJ8rN4ysjSFV2yvMp3dzwlJGTpdkVl8BoVXZ6o8r6BKPDL2mqfP96CEiZAeWXThYjcTYasM00jLITLa6t8CZl/TqhHlVUGzhThASCDt7QZVFpBFtRWex9JVIEJbyIrKptPROzHFEoSXfZQQqDOEvmn26q8CQ3UJHwR4bKleevUlCPIRpT2j/C6uIxjEi0mJEFQgNqbvJ8X5npPBn4BZOYK2uSgoL9uqvOeeOuNeduSUUHSe6Vli5pOFeReYFSy60pzdiNcVFvlezqZlSR93fby6vznbYMjQP+Y7LrSFpH7bIPDky0mDPK4sWxx8/dF7duBmQc8eAig6CfAVcur858drDoHPRBQWqruguLmK1T0RtJ8A4M4CAK3hAPeqgPlACWalEV2rruucaTtMq4ArgWKUmVHgmkC/R+XLUvb0mAHnZSH6q5c3FDiUXMhwkKU4am2JzakEbijVSK33F5VmNLcq5QL2s5Cf12hu9VTisrFZM499gNEV4Y9rXet8Jc0pNoYSCNBu1JW2ThTxLwA9GLSbbgj1KvysKHGqljnLJNJWgrajt+vrqbm4Om2wTyUucCMFJnyIbAW4ZlCj/dZv1/SdmI/rQXtybU3BA42bZ2rKnMQOQF0Evt7wnHshEG2oLpe0bUum7X9rSVJNzJK0J6Ulqo7b1jjREPM6Yah09SWqRiME5uDVCjBGRa56RweNQFhoEmUOjX4OzY7VHQTKptttT5u3luwNdrErHTi/wG5jWw4PKXrYgAAAABJRU5ErkJggg==)}.realTime .public_recognition_speech .endToEndIdentification_end_recorder_img[data-v-1bbbdb64]{width:116px;height:116px;background:#2932E1;border-radius:50%;display:flex;justify-content:center;align-items:center;margin-left:98px;margin-bottom:20px;cursor:pointer}.realTime .public_recognition_speech .endToEndIdentification_end_recorder_img .endToEndIdentification_end_recorder_img_back[data-v-1bbbdb64]{width:50px;height:50px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAABU0lEQVRoge3ZPUoEQRCG4bcWfxDNDIzUW4jiegUTMfUICuaeQIz2BOZi4gEEg0XY0NBIcyMR/8DPYCdapnF2u53ugXqSnqAo6puZbgYGnHOuKUk9SXuSVnLPEkXSicauc83QS9RnvVo3EvWbWqog2XmQGJK2JJ1LWkvVcy5VoyldAH3gAzhL0TDXq7U0sUbzPVKa2iCSViUNJV22PdCsQk9kG9gBjiQttzjPzEJBeg1qWiNpX9KxpOAsuY7fxiQtAlfAPPAA3NbVZb/bDSwwDgEQ/LruQpBGPEhpPEhpPEhpPEhpPEiLvoDv6vo1VFT8R6OZfUo6ADaBu1BdKMhP4DoLM7v5qyYU5B4YAo9m9pZ0qn9SG8TMXoDdlmeJ0oXN3ogHifQ+sUbLdfyeAofAIFXDLEHMbASMUvb0PVKaVEGeq/UpUb88qr+6/c7/1XXOudb8AikhXZ/+ExptAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:50px 50px}.realTime .public_recognition_speech .endToEndIdentification_end_recorder_img .endToEndIdentification_end_recorder_img_back[data-v-1bbbdb64]:hover{opacity:.9}.realTime .public_recognition_speech .endToEndIdentification_prompt[data-v-1bbbdb64]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-left:124px;margin-bottom:10px}.realTime .public_recognition_speech .speech_text_prompt[data-v-1bbbdb64]{height:20px;font-family:PingFangSC-Regular;font-size:14px;color:#999;font-weight:400;margin-left:105px}.realTime .public_recognition_point_to[data-v-1bbbdb64]{width:47px;height:67px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:47px 67px;margin-top:91px;margin-right:67px}.realTime .public_recognition_result[data-v-1bbbdb64]{width:680px;height:230px;background:#FAFAFA;padding:40px 50px 0}.realTime .public_recognition_result div[data-v-1bbbdb64]:nth-of-type(1){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500;margin-bottom:20px}.realTime .public_recognition_result div[data-v-1bbbdb64]:nth-of-type(2){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500}.endToEndIdentification[data-v-0190c31b]{width:1106px;height:270px;padding-top:40px;box-sizing:border-box;display:flex}.endToEndIdentification .public_recognition_speech[data-v-0190c31b]{width:295px;height:230px;padding-top:32px;box-sizing:border-box}.endToEndIdentification .public_recognition_speech .endToEndIdentification_start_recorder_img[data-v-0190c31b]{width:116px;height:116px;background:#2932E1;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAQMElEQVR4nO2de3xU5ZnHv8+ZyYUkJIGEgNwSLpKEKJgMwmqpBlArXW3tVv1Q78qnunbFC9XWlbqrtVpFilY+2lqrYFFWrVK3VUHFLO3qtkguiIaEi5gJF5UQLrmRkJnz7B+TBEJIyFzPGZjvXzNz3ssv+c175r0873uEKKagoDJeEpLHeSEPlQkqmivIKJAU0GSBZIVBQHJHlmaB/QrNIM2gTSC1qG5BdIsDqrWt+fPKyoLDVv5dwSBWC/CHCZN3jHAY5kwVnSHIdGAM4AxxNR5Et6vykYGUeFVKNleM3h3iOsKGrQ11uUrjWs2s2aahs1FmALkWSdmMaomKrEqWutVlZVPaLdJxQmxp6MTJ7gJ1cq0qNwpkWa3nGPYL/FGE5ZVl2R9aLeZYbGPoWNfnaQnqvAW4Aci3WE5/qQKWtYnn2e1l4w5aLQZsYOgE1+5Mp7bfpnA7vg5MNNKoylIx9NGqspwvrRRimaFnTNs+1Otx3IUyD0iySkeIaVbleY/X8fi2jSN3WiEg4oa6XKVxLQz5EcrDHBlOnGwcEljYkmo+WrN2TGskK46oobmumhmGytNEz29ksGwzMOZVlo9aHakKI2LohMk7Rjgc5mLgykjUZ0NeNVXmR2I8G3ZD84rclwgsAzLCXZfNOaiqc6srct4IZyVhM7S4WJ17Gmp/pnA/YISrnihDVVniONx0T7imF8Ni6Bln7xrl9XpeAc4NR/nRjsJ608GcLeuzt4e67JAbml9Yex7onxAGh7rskwpln4hctql89P+GstiQ3goLCmu/g+jqmJn9QBis6PsFhe7LQ1lsyAzNc7mvN0XfAAaEqsxTgARTeCWvyH1zqAoMiaH5Lvcdoiwl9EtZpwIOgd9OLHI/EIrCgjY0v6h2AcqT2GBeOIoRhf+cWFR7X9AFBZM5v9B9HcKyYMuJ0YUienNVWc7vAy0gYCPyityXCqwkdpsNNV5Fr6wuz1kZSOaADM0rrDlHRNZw8qyS2I1DgnwrkCGN34bmF27PRhwVRO/aZbRQb4inqLJsXK0/mfzqFLlcpXGIYwUxMyNBhqmO1woKKuP9yeSXoYfIfJTYdF4EkWlmQspDfuXob8L8KTXfxpS3/MkTIySooXJZZcXoP/cncb/M6YiH3Rib0rOMvYhO6k+8Ur9uuQ6HuThmpqVkimks6k/CE7bQ/CnuCzF5L3hNMYJFlAs2VWR/0Geavi4WFFTGmwkpG7EuYj1Gd7a2Nxw+c9u209t6S9DnLdebmHIvMTPtxOnOtPj5fSXotYV2BHZtJbYcZjdaEB3fWwep1xbqcJh3EzPTjiSpGr220uO20LypOzPE460BUsKlKkZQNHslLmdL2fC9x144fgv1eOYTM9POJDvN9nnHu9CjhXbsAqsB0sOtKlykpxlcODOJ4vMGkD3KSUaGg9ZWZU+dl49LW3m/pIWNn0XtJu1ODiaYZs6GDWMOHP1hD0Pzi9w/AR6LmKwQEh8v3HjtQOZen0pKct9zJv+3rpWFi/ezZZtt9+6eEBG9Z1NZTrcJh56GutyfoRRETlZoGDzYwVOLMimanND12c5dHso3tFG/z0tiosHYMU5cZyXgdPr+7NZW5T8e2sdbq5utkh0sm6rKs7t51c3Qgik7ppqmuS6ymoInOclgxbKhnD4uDoBPPm3jV08doLS85/g7LdVg7vWpXHfVQOLjBVX48b/vZfX7LZGWHRpEXVVlOeWdb7vdl9TUayOvKHgefmBwl5krXmvkmrlfH9dMgIMNJouXHOCmf93D/gMmIvDIgxmMGxsXScmhQ6WbZ12GulylcYrOibyi4Jg2JZGLZvkiYd55t4WHF+7H6z1xvvJP2pj34zra25XEBOGnd0Xnmr3CVS5Xade3scvQVjNrNpBpiaoguGVuKuBreQ89ug/V/uct39DGy682ATD93ERyJ/gVHGALBLJayLyo832Xoaahs62RFDjpaQZnuxIB+OPKJg42mH6X8fyLDXg7sl18QXTGvIkaF3e+Puo3VGdaISYYJp+ZgMPhe13y10MBlVG/z8vGT9s6you+FgqgR3lnAOQW1g5HZYJ1kgIja4ij6/UXNYGPJ2tqPQCMGB61IcYTcwtrh0OHoQY6y1o9gZGWduQG09jk/+22k4MHfXkHDozefclimMXQYaiKzrBUTYCEKlpN8aMnZVPElBnQYagI37BWToxgEWE6gFFQUBmPylirBcUIDoXxLldpnEF8ynhiG45OBpxNMnisYYrGYoZOEpxeZ66hIjFDTxJMMXMNQ2NRfScNYuQaqoywWkeMEKGabSAy0GodMUJGhoGorQ2dc3kKTy7MZGiW48SJw8SFM5N4evEQJoy3+5qpZBiovaP77r5jEBfNSuKyS607Wvf2W9OYcf4ArrrS1t99QAcaKLZW2dTsm2cdadHEuWEcmbTv1GJjEgzE3i20dodvJWTMmJ63O4/nyOv4+MBnduM7gsba2nrO6Q4b6iQx0Xe9dqenx3WbkWD75YVN1b742Ym58T1M+/LrI//go5fS/GV4Rwusq+sZuzLpjCNrpFXV9o/lNVCarBbRF+tKfUe2JyZKjwXoL9xHDJ3aEbngL06nUNgR+vn5Fz3XVM+Z5iu3sdFkU5XtDW0zEBqtVtEXpWVtXUFf50ztbtqWrYfZuctn6r98N7BO06ziAaR3rKv+z996Rj101rm+rK0rVMXGtBmIvVtoY5PJJ5/5QkQumZ2McXTQjMLKP/uCpM+alMAlF/tnalKSMH+eb8fHnjovf/uwu6FFZyUwcoTvdvzh3wMLcYkwDQYqtm6hAG+86fvOjRzh5Jvndt/h+OLLDXy9x9eEH/zZYM4s6F9cUFyc8PjDmYwa6TNsyW8P0npMp2jOFb7+Ymur8s57URGIXW+gantDV73b0hXRd/Wc7qOsQ4eUe++vx+NRBgwQXvzdUL73ne4t+VhGjXSy9NksZpzn+3K890ELK/+7+40qa4iDi2b6ogDfXt1MQwARhRFHqXdkDb9rJnCW1Vr6wuOFQekGhZMTGD3KyYaNbew4agixa7eHHbu8FH9zAAkJwqziJGYVDyApycA0FREYOtTJ2UWJ/PDGVB64b3DX2HLd+lbm37uX9mP6Qwt+OpiC/HhU4f6H9rG3vh/R21ZjyFrJc7nvFeWXVms5EelpBqvfHE5qqsH2mnauuOYrDh3qfossOiuBhb/IYPhpJ56E8HrhpVcaWfTrnpH2U12JLH02CxF4e3UL9yzosa/WpuhPHEOGz88EbL8ForVNaTmknDd9AIPSHQzLcvLB2u4dlS+/8vLK600cOGgyZIiTzIyeY9PGRpN317Rwz4J63lrV3CPSPmOwg+d/k0VyskFTs8ntd9fR1BwdQWSKLJEzimryvcgmq8X0BxF45skhnD/d99v33LIGnlhyoNf0pw1zkpPtZEimg8Ymk7o6L9Vb2vF4jm/QoHSDF36T1bUl4p4Fe3l7dVR0hgBQryNXOs4iaiZK4orS0wxeemEoY3N8U4Gvvt7Eo7/aT9vh4FrR2Jw4nlyYyfiOXWwvvtzIY4v3B603grQnSV2yAOS7ajZHU+R81hAHf3huKKNH+b6D1ZsP88ii/b1uIeyL+HhhzuUp3H5rOklJvqnF11Y28eAj/m18shqB6k3l2fkCkFdU84IgN1otyh/S0wwW/TKTc6cdmT36x8etvPlWMyVrD51wZSQn28m3L0rm+5clc9ow3xfDa8ITSw6wdHlDVJkJgPL7qorsH/paaKH7WoQ/WK3JXxwG/ODKgdx2SxqpqUcGnl4Tamraqd7SzoEDXhqaTOKcQupAg9OGOcjPi+/RYaqsOszDC/ezYaP/rdwOqOjV1WU5KwR8m5UM0V1WiwqUQekGV34/hSu+l9KvIcvRfFzWyorXmlhT0oIZBXMHvaCIjqgqy/myaz0qv8hdTZSf62cYkJ8bz1RXIgUT4xkx3MHYnLiuTUi7dnvYucuDe4eHik/a+Pu6VvYcZ8ksCuk6POPI11m1hCiP0TVN362z8qhlrptvSuXOf/NNwF94adifx2oJgpR0vu764VGRVdbIiREsaphd3nUZOix19CqUr62RFCNQFPYk6d73O993Gbp2rXjU4DVrZMUIFEFfLiub0rW00K1L6PDKctPQ4x4KaCdmFQ/wrYv2Iy5sYu6R9dEHFvTv2PzWVuXlVxrZscv2QWGIwfJu749NkF/k/hQ4I2KK/MTpFMo/Gtl1vFu4eOfdFu6+z/arLD2OhjveoG05Nj680eNR/vSXZv5pamBBYf3B9MK7a+w/KS+iS3t8duwH46dtTY1rj3cTxcerniIc93jVHoEa29ad3qDoM5HTFSMQRPn1sWZCbydaO52Lwd7RgKc4zR4jbsnxLhzX0OqPR9aDPhdeTTGC4JnjnTcPfTwVwlRjERAVwainGM2Gw1zc28VeDd1cMXo3orYPHjvVUOEXlevHfNXb9T43KxmtzY8JVIdeVoyAEN3iOXj4ib6S9GloZWXBYVVsP3N0qmAot/b13DPox+Mmqyqy10BsjtdqRGVFZXlOyYnS9Wt/qKlyF1AftKoYgbJXDfPu/iTsl6GbK0bvxtDr4CQ4tjL6UENlbn+e7gt+PFS9qjTnHVHptbscI0wIC/v7/G3ww1CArLRR94rykf+qYgSGrkui7n5/cvi9BpVfuD0bHOWxZ3KHnXqHw1n42foRO/zJ5PehGVUVY92I+c9A1D5fKgo4ZAiX+WsmBGAoQFX5mH8o/ACw/5J+9OFV9JrKsuwPA8kc8LE21eXZf0G5iVjPN5QoqrdUl+esDLSAoM4pqqrIXi7Iz4IpI8YRVFhQVZHzfDBlhCQwJ9/lvgPliVCVdwqiAj/fVJ79QLAFhcyA/EL3dQjPEyX7TG2EV+HW6vLskKw/h7RF5RW5LxV4FRhwwsQxANpU9erqipw3QlVgyG+RBS73dFN5E8gIddknGfWmwXc3l2aHdKIm5Ic3VpZlf+hwOAtjM0p9oHxsevTsUJsJYTAU4LP1I3ZkpY0uFngQiN5dl6FHVXkqyaibvnljzhfhqCDsvdL8QvcFwEsIQ8Ndl83Zi6HXV5XmvBPOSsJ+Xm5VRfYaDC1E9L/CXZddEZUViE4Kt5kQ4XFjXuGO88Uwn0YpOHHqk4KtKnJbddno9yJVYURPtK6uGPXXJOoKEe7k5A7kbhF4sL3h8JmRNBMsnNmZNGlblscZ9yOFO4E0q3SEmCZVXlDksc0Voy3Z/2/5VF3e1J0Zhsc7T5V5UbzG2ojwjDocj/t2HViH5YZ2Mn7a1tR4T9zNitwQNb+xQqWgyw4723+3bd3pDVbLARsZejQTJ7sL1Mm1mNxgu+GOsk+E10VYHuiaZTixpaGdFBer8+tG97dQYzboTCDfIimbBClRw1w1NCX7vbVrxbYL+7Y29FjyXTWniTJTxZghqt9QGAeE+oFk7QKfq8hHilniMLSkr70kdiOqDD0Wl6s0rkkGj3V4nHlqaC4iEzB1NAZDUDKAFHyGdz49qgloB5oQ6jGpw5Ba1NwsprHF6/RUp+i+7UefKhJt/D+IYnHePFNWNgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:116px 116px;margin-left:98px;cursor:pointer;margin-bottom:20px}.endToEndIdentification .public_recognition_speech .endToEndIdentification_start_recorder_img[data-v-0190c31b]:hover{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAP8UlEQVR4nO2de3hU5Z3HP79zZjLJTC6EIFRYQO4gaOuNeqsVdLXU6urzaJddvFW3cb2gJnENSPvstKsmRAm2VNfauvIs1npF65WqxaqAt/WGV1BAUMFaEiDJTJKZOee3f5zcE0LmlpmJ83mePJPJnPO+v8n3/N7zvr/3955XyGD8fs3ZG2yaJIY5XbCniso0hLEK+YCv7ae47RUgAOxpew0INCnsAN2sGJvVtj4e5s3f4vdLKDXfKH4k1QZEQ9mS4BjDtudiyxxb9ERBJgCuBFcTAd0qKusVXetSWVtT49uZ4DqSRloLWlqq7vyS4DxR5oHMUXRaKuwQZJOKrlWbZwJ7vGvuukvCqbBjIKSloGWVjTNFzAtAfwKMTLU9Pdij8JChxqplS/PWpdqYnqSNoJWV9UURI+cyVbkYmJFqewbIRyK60mWHfrt06fB9qTYG0kDQioqGEeo2rwKuxunAZCDSCPY9tiHVt93s25VSS1JV8TU3NI0ybaMMdCHgTZUdCSYAerfLNm6pqfF+kQoDBl3Q0lJ1FxQ3X6GiN9E5nBhqNAM1hbnear9fWgaz4kEVtPyGxjnYxu1kzj0yXj5VdOHy6vw1g1XhoAjaNn6sVZUfD0Z96Yc+4LKlfDDGs0kXtHxx4EeirFQoSXZdac4+kEtrq72PJLOSpAnq96uroSX4M+DngJGsejIMBV1RmOv7j2SFF5MiaPmS4FgsvR84PhnlDwHeUMz5y6tztya64IQLWlHZfJIa9qMowxNd9pBCqFeMs5dX5b2cyGIT2hSWLw6cpWKvyYo5AJThovZzFYuD5yay2IQJWra46SKUR4C8RJX5DcCjqvdXLAqUJqrAhAhaURm8RlTuIfFTWd8ETIU7yxcF/IkoLG5ByxcFlqjobaRBXDiDEeA/KyoDNySioJgpr2y6EJGV8ZaTpQMVKF1W7ft9rAXELERZZeBMEVaTbWYTjSUiP15W5V0dy8kxCXrt4uBxhurzDJ1ZknSjWcU4PZYhTdSCVixpHq+W/TYZO3eZGQjURdQ48ldL83ZEc15UnaLSUnWrZd9HVsyko1BiiP2g36850ZwXlaD5xYFqsuG8QUPguw3Nzf8V5TkDo3xx4IcoT0ZzTpaEoAhn11b5Hh/IwQMSp2xJcIzYujEb0ksZu22DwweSrzSgJtew7dqsmCllhKFy60AOPKCHVlzf9I9qyLPx25Qlbgw9tfbm/L/0e0h/H/r9moNhrEisVVliRW3+e+FC9fR3TL+C7msOLkrV8oMsvRFkitsXKO//mP1QtiQ4Riz9hOx0WLoRtA0m76+DtF8PlYh9HVkx0xGvYcl+vbRPD71ycUOJR83PcNZZZkk/AhK2Dlm2rHB3zw/69NAczHKyYqYzPnLMhX190MtDKyvri8J4PkMYlmyrkoXPKxw20+TQGSYjSoSCfCEcgX37lC3bLDa+b7HjczvVZsbLPjs3dMht/uK9Xf/Yay4zYuRchmammC4XnPw9N3O+7yLX0/tuUlQojBtrMOckN5s/sXj86TC7vspYYYuMVve/Ad0CDr0EVZULB82kBJKfL1x8vocJ4zvvIvV7lG2fWTQ2KW63MGqkMGG8iWnC1CkmV19h8tDqEG+9E0mh5XGg8hN6CNrtMi67PjhbDH1tUI1KAB6PcPXlHr41yhFz+w6bJ9eE2Lqtt/d5vcKck1ycdIIblwtU4d77W3lnozXYZicE2+Co2272vdX+vlunSAy9YPBNip/55+Z0iLn+lQi/+W1Ln2ICBIPKU2vC3Pn7FgIBRQTmn+th1MjMXK1hWN016/gWpaXqBuYPukVxMnmiyeGzTADeftfi0SdC2AO4LW7bbnPPva1YFrjdcNYZ7iRbmiRE/rVNO6CLoPklwXnAiJQYFQenznW6AcGgsvrxEKoDP3fbZzbrXnHun9Onmow+OCO9dGRhcfC09jcd38B5dExm4fMKkyY43vnqGxGCwSjUbOOFF8MdHv3tw8xEmjdo2MIP2n/vEFTRuakxJ3bGjTMw2r7BBx/G1qlpbNKOMen4cRnpoQAd2hkA118fGA0yNXX2xEZRQWcn/evd0XtnO3/f7Qg6fFjGCnqoo2GboJapp6TWntjwejsFbW6OXdBgs/Oam8FTEWHRk6G9ybVlTiqNiZkEpatpND2pNEXE0dAAUNETUmtOlviREwEMJ5FXJqbanCzxopNLS9VtNLY2TSa74Ggo4Mob1jjRsNXM5gwNEUzTnGYYamcFHSKo6jRDRbKCDhFEZZqBMCbVhmRJDCKMN1AKUm1IlsSgUGJAegt6/LEuLlrgoagwdYveDptpcsmFHg7+VtqHBksM0jy770fzcjh8lskxR6VuZDXvNDczZ5iccGzaj+4KDCS9PbS1xQnLDR+eGg8VgeJixzNbWtM+ROgx0PT20N11zj9x5EG9mzu7y4yZOw7ncZnOxRLpI1dsWJGQ05YPUFefCYKmOV/sdKa2xow2cPUQbe++zlyTwjjuscXFzrkNDb0F6zpH+uXO9E/5NBCaUm1Ef3y6xXHDHDeMH9v9+vv6750CTJoYW7aBacIhbamff/u6t2BTJjvlNrcoX3yZ9oK2GiiNqbaiP7ZssztSRNr/ue3s+sqmfo8j6uyjY2tzZx1q4mubV/3go95ZD1Pb6tyy1R5Q8lmKaTUgvT20pUXZ3pYictQRLqRLy6oKr/+fc+M7ZJzBkd+JTlRPDpxxuvPUmIYG5aNN3QWdcIjB8LbmeNMnGZG322BAensowOtvOKINLxamT+vupS+uC7Ov7d533jk5jBs7sG6BacKC+R5KShzB1jwXJtxjR7Pjv+tcIKGwkyKa9ih1BpL+gr69sTOj73vHdffCUAjueyCEZUFODlz+01xmH9Xdk3tSUiJc/tNcZs5wLo6N71u8/mb3Lm5hoXD4LKeut9+NxJXiMmgY1JnHnbhkLvCdVNvSH7YNPp+zLmVEicH2HXa3IUT9HqWuXpk5w8Ttcu6Lsw418eQItjpjyaIig0kTDE452c25Z3s6mtJPt1j87x+dhOuunHNWDmPHGKjCg6tDNDZmgKDKX12iukn7u5zThBdejHDsMS7y8oSzz3Sz/DcWoS77Krz1ToQ9e20W/LOH4mHC6IONtsTpvjPibRvWbYjwxDO9M+0nTTQ5+gjHO9/ZaGXEcAVARTeZx5+0ZAQZsAQiHIbWEMyYZuLzCcOKhPd75OLu3atseM1pnosKnXWhPWluUTa+Z/GHB0K8+U6kV6Z9Qb5w2aUecj1CS6uyclUrLa3J/GYJRGWFy7LsTYaR9vEFADa8GmHGVJMZ002OPtJFQ4Py1J+792QiEXhpfYSX1kcoHiYcNMKgoEBoaVEaGpWdu+xezWs7Pp9QeomHwrZ834cfDbF3XwY0tW2IYW4Sv19zGlqCATIkr8jnFa76d09HKHDDaxH+9GSoz7BdNIw8yOCiBZ2r2F5aF+FPT2XUVtzhpnqvTwDKFzVtyqTM+cJC4crSXEa0DTm+3GXz2BN9rwc9EC6XMzz5wWk5eNoeZPrq6xEefiy6hU+pRz6urfbOcAGIynoVMkbQhgbl13e0cP78HKZOMRlzsMGVpbl8ssXijTctPvjQOuDMyEEjhCO+7WL20S6KhzkXhm3D038O89eXwxkmJoCug/Zm1tAX2pZ3ZwyBoPK7la2ccKyL0091k5cnTJlkMmWSiW0761V27lICAaW5RTFNyMsViocJY0Y799WufPGlzaOPh/hsR2b0aHuiqi9Am6CmJX+JZEa/qBu2DS9viPDWuxbHzXZx7GzH2wwDRo00GDWA7di3bLVY90qE9z6wMtArO1A15QXosjqkYlHw40x/rp+IM802eaLJP4xx4rAjRwp5uc7XrN+j1Nfb7K5Ttm232fyp1eeUWQbyYW21byZ06dmq6FqUjBZU1Wk6u05znTLHzQ9Pc4ILN9U0p8q0ZLO2/ZfOBb82z6TGlixxI53adQhalOd9BvhbSgzKEg9fN9V5n2t/0yGo3y8RhAdTY1OWWFH0D3fdJR3hsm7RIVFWKfT5UMB0YtahJtOnmv1OkbUzZnRn9/28cwa2BUooDOs2hDMhKQxBVnV/34PyRYH3gFmDZlGUmCZU/cKLmeQHlrz9rsW996d9VL6jd9tOr/itiK5SlaWDZ1N0WBa88VaEKZOSp6ja8O57GfD8P9F7ev6pl6AhT+ud7ubcxen8eNWHVmdU0DxZ7LM94V7bUvaKD63wlzSowR2DY1OWWBHhVz2flQv7eaJ1CKuWNM8G/IYTIGT1uf1Kn4LeXlVYp+jvkmtTllgR5I6+njcP/ewK4bblVmDIxsoymIBh2bX7+3C/gtbU+HYCVUkxKUvMiOqNt9yS/9X+Pu930qww17sU5OPEm5UlNnRzKOhb3t8RB9j7TEKKnfaRo28KBnr5ihXSb7TjgNPay6vznxfRbIw31Yjcd2t1wdoDHTagPAXTkjKBuvityhIju23R6wZy4IAEranx7VThQiD9o9VDD0W4dCC7+0IUm6rXVvmeFmS/3eUsyUJqBrr/NkQhKEBBbt4iYH3UNmWJCYXXmurzfh7NOVEJ6vdLRExjAUJ9dKZliRaBOjHlvK6T1wMh6uTNZTflbceSM4BAtOdmGTDNqHF27U3ez6M9MaZs3Noa76uq/AuQAZOGGYclIucvW5q3LpaTY06vXr7U94SIXkK255tIVIXLllV5V8daQFz58suq8leJ8rN4ysjSFV2yvMp3dzwlJGTpdkVl8BoVXZ6o8r6BKPDL2mqfP96CEiZAeWXThYjcTYasM00jLITLa6t8CZl/TqhHlVUGzhThASCDt7QZVFpBFtRWex9JVIEJbyIrKptPROzHFEoSXfZQQqDOEvmn26q8CQ3UJHwR4bKleevUlCPIRpT2j/C6uIxjEi0mJEFQgNqbvJ8X5npPBn4BZOYK2uSgoL9uqvOeeOuNeduSUUHSe6Vli5pOFeReYFSy60pzdiNcVFvlezqZlSR93fby6vznbYMjQP+Y7LrSFpH7bIPDky0mDPK4sWxx8/dF7duBmQc8eAig6CfAVcur858drDoHPRBQWqruguLmK1T0RtJ8A4M4CAK3hAPeqgPlACWalEV2rruucaTtMq4ArgWKUmVHgmkC/R+XLUvb0mAHnZSH6q5c3FDiUXMhwkKU4am2JzakEbijVSK33F5VmNLcq5QL2s5Cf12hu9VTisrFZM499gNEV4Y9rXet8Jc0pNoYSCNBu1JW2ThTxLwA9GLSbbgj1KvysKHGqljnLJNJWgrajt+vrqbm4Om2wTyUucCMFJnyIbAW4ZlCj/dZv1/SdmI/rQXtybU3BA42bZ2rKnMQOQF0Evt7wnHshEG2oLpe0bUum7X9rSVJNzJK0J6Ulqo7b1jjREPM6Yah09SWqRiME5uDVCjBGRa56RweNQFhoEmUOjX4OzY7VHQTKptttT5u3luwNdrErHTi/wG5jWw4PKXrYgAAAABJRU5ErkJggg==)}.endToEndIdentification .public_recognition_speech .endToEndIdentification_end_recorder_img[data-v-0190c31b]{width:116px;height:116px;background:#2932E1;border-radius:50%;display:flex;justify-content:center;align-items:center;margin-left:98px;margin-bottom:20px;cursor:pointer}.endToEndIdentification .public_recognition_speech .endToEndIdentification_end_recorder_img .endToEndIdentification_end_recorder_img_back[data-v-0190c31b]{width:50px;height:50px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAABU0lEQVRoge3ZPUoEQRCG4bcWfxDNDIzUW4jiegUTMfUICuaeQIz2BOZi4gEEg0XY0NBIcyMR/8DPYCdapnF2u53ugXqSnqAo6puZbgYGnHOuKUk9SXuSVnLPEkXSicauc83QS9RnvVo3EvWbWqog2XmQGJK2JJ1LWkvVcy5VoyldAH3gAzhL0TDXq7U0sUbzPVKa2iCSViUNJV22PdCsQk9kG9gBjiQttzjPzEJBeg1qWiNpX9KxpOAsuY7fxiQtAlfAPPAA3NbVZb/bDSwwDgEQ/LruQpBGPEhpPEhpPEhpPEhpPEiLvoDv6vo1VFT8R6OZfUo6ADaBu1BdKMhP4DoLM7v5qyYU5B4YAo9m9pZ0qn9SG8TMXoDdlmeJ0oXN3ogHifQ+sUbLdfyeAofAIFXDLEHMbASMUvb0PVKaVEGeq/UpUb88qr+6/c7/1XXOudb8AikhXZ/+ExptAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:50px 50px}.endToEndIdentification .public_recognition_speech .endToEndIdentification_end_recorder_img .endToEndIdentification_end_recorder_img_back[data-v-0190c31b]:hover{opacity:.9}.endToEndIdentification .public_recognition_speech .endToEndIdentification_prompt[data-v-0190c31b]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-left:124px;margin-bottom:10px}.endToEndIdentification .public_recognition_speech .speech_text_prompt[data-v-0190c31b]{height:20px;font-family:PingFangSC-Regular;font-size:14px;color:#999;font-weight:400;margin-left:90px}.endToEndIdentification .public_recognition_point_to[data-v-0190c31b]{width:47px;height:67px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:47px 67px;margin-top:91px;margin-right:67px}.endToEndIdentification .public_recognition_result[data-v-0190c31b]{width:680px;height:230px;background:#FAFAFA;padding:40px 50px 0}.endToEndIdentification .public_recognition_result div[data-v-0190c31b]:nth-of-type(1){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500;margin-bottom:20px}.endToEndIdentification .public_recognition_result div[data-v-0190c31b]:nth-of-type(2){height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#666;line-height:26px;font-weight:500}.speech_recognition[data-v-02a5e0f4]{width:1200px;height:410px;background:#FFFFFF;padding:40px 50px 50px 44px;position:relative}.speech_recognition .frame[data-v-02a5e0f4]{width:605px;height:50px;border:1px solid #eeeeee;border-radius:25px;position:absolute}.speech_recognition .speech_recognition_mytabs .ant-tabs-tab[data-v-02a5e0f4]{position:relative;display:inline-flex;align-items:center;font-size:14px;background:transparent;border:0;outline:none;cursor:pointer;padding:12px 26px;box-sizing:border-box}.speech_recognition .speech_recognition_mytabs .ant-tabs-tab-active[data-v-02a5e0f4]{height:50px;background:#EEEFFD;border-radius:25px;padding:12px 26px;box-sizing:border-box}.speech_recognition .speech_recognition_mytabs .speech_recognition .speech_recognition_mytabs .ant-tabs-ink-bar[data-v-02a5e0f4],.speech_recognition .speech_recognition_mytabs .ant-tabs-ink-bar[data-v-02a5e0f4]{position:absolute;background:transparent!important;pointer-events:none}.speech_recognition .speech_recognition_mytabs .experience .experience_wrapper .experience_content .experience_tabs .ant-tabs-nav[data-v-02a5e0f4]:before{position:absolute;right:0;left:0;border-bottom:1px solid transparent!important;content:\"\"}.speech_recognition .speech_recognition_mytabs .ant-tabs-top>.ant-tabs-nav[data-v-02a5e0f4]:before,.speech_recognition .speech_recognition_mytabs .ant-tabs-bottom>.ant-tabs-nav[data-v-02a5e0f4]:before,.speech_recognition .speech_recognition_mytabs .ant-tabs-top>div>.ant-tabs-nav[data-v-02a5e0f4]:before,.speech_recognition .speech_recognition_mytabs .ant-tabs-bottom>div>.ant-tabs-nav[data-v-02a5e0f4]:before{position:absolute;right:0;left:0;border-bottom:1px solid transparent!important;content:\"\"}.speech_recognition .speech_recognition_mytabs .ant-tabs-nav[data-v-02a5e0f4]:before{position:absolute;right:0;left:0;border-bottom:1px solid transparent!important;content:\"\"}.speech_recognition[data-v-1ec3a672]{width:1200px;height:410px;background:#FFFFFF;padding:40px 0 50px 50px;box-sizing:border-box;display:flex}.speech_recognition .recognition_text[data-v-1ec3a672]{width:589px;height:320px}.speech_recognition .recognition_text .recognition_text_header[data-v-1ec3a672]{margin-bottom:30px;display:flex;justify-content:space-between;align-items:center}.speech_recognition .recognition_text .recognition_text_header .recognition_text_title[data-v-1ec3a672]{height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#000;letter-spacing:0;line-height:26px;font-weight:500}.speech_recognition .recognition_text .recognition_text_header .recognition_text_random[data-v-1ec3a672]{display:flex;align-items:center;cursor:pointer}.speech_recognition .recognition_text .recognition_text_header .recognition_text_random span[data-v-1ec3a672]{display:inline-block}.speech_recognition .recognition_text .recognition_text_header .recognition_text_random span[data-v-1ec3a672]:nth-of-type(1){width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABpklEQVQ4jZWSvWuTURSHn/PmzRuVxo+hiGATKy+0aVohSRcRIYPi9yCijv4DriJS/AMEoUOXgq4FoZvQvYsItWmEIE2sH/EVLOigHdSSJvfnYqLSpI1nuvzOfR7OuVzooyYmvh3q1fN2g4tF+c34xvNMvn61W9+6hWFufTBO4wJYaMYmgNAdJztbK6eWe04QhmuJsVz0MG6NGsYlcA2kAcEV4KBnehrm1gf/Zvz2IZt9FbhEsCDY2FIw8qZ85AvAWP7DDdAtYMGwB+18m8DtSd6X9L26MnQdzP2ZUWtS7Hy1NFTp+QbHC28PJOS/d7LxWjn1qdvFXuUBBC52Bnj2v3BH4HkMm6zWLzSaj84VCsvxjkDip3D7+oGz2c8DhuaTyYI6AlAJ41Q/AgU/TgMvFxet2RGsrhxbAvMzk/WLu+Ae2JRMs+3k9wTmnOk2zh5lJqPxXvBoLpqWqVktpZ+003++ciYf3QQ3gzHT8mzu9Yv0u6MnP+7dv9kqyuyeQTO2xbVKJf21qwBg5ER92Hy7a3AZOAy0gCXE49UwNce8tXZec9vOO9cvuPyUtrJ2lqQAAAAASUVORK5CYII=) no-repeat;background-position:center;background-size:20px 20px;margin-right:5px}.speech_recognition .recognition_text .recognition_text_header .recognition_text_random span[data-v-1ec3a672]:nth-of-type(2){height:20px;font-family:PingFangSC-Regular;font-size:14px;color:#2932e1;letter-spacing:0;font-weight:400}.speech_recognition .recognition_text .recognition_text_field[data-v-1ec3a672]{width:589px;height:264px;background:#FAFAFA}.speech_recognition .recognition_text .recognition_text_field .textToSpeech_content_show_text[data-v-1ec3a672]{width:100%;height:264px;padding:0 30px 30px 0;box-sizing:border-box}.speech_recognition .recognition_text .recognition_text_field .textToSpeech_content_show_text .ant-input[data-v-1ec3a672]{height:208px;resize:none;padding:21px 20px}.speech_recognition .recognition_point_to[data-v-1ec3a672]{width:47px;height:63px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:47px 63px;margin-right:101px;margin-left:100px;margin-top:164px}.speech_recognition .speech_recognition_new .speech_recognition_title[data-v-1ec3a672]{height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#000;line-height:26px;font-weight:500;margin-left:32px;margin-bottom:96px}.speech_recognition .speech_recognition_new .speech_recognition_streaming[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;text-align:center;line-height:44px;margin-bottom:40px;cursor:pointer}.speech_recognition .speech_recognition_new .speech_recognition_streaming[data-v-1ec3a672]:hover{opacity:.9}.speech_recognition .speech_recognition_new .streaming_ing_box[data-v-1ec3a672]{display:flex;align-items:center;height:44px;margin-bottom:40px}.speech_recognition .speech_recognition_new .streaming_ing_box .streaming_ing[data-v-1ec3a672]{width:136px;height:44px;background:#7278F5;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer}.speech_recognition .speech_recognition_new .streaming_ing_box .streaming_ing .streaming_ing_img[data-v-1ec3a672]{width:16px;height:16px}.speech_recognition .speech_recognition_new .streaming_ing_box .streaming_ing .streaming_ing_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .streaming_ing_box .streaming_time[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#000;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .streaming_suspended_box[data-v-1ec3a672]{display:flex;align-items:center;height:44px;margin-bottom:40px}.speech_recognition .speech_recognition_new .streaming_suspended_box .streaming_suspended[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer}.speech_recognition .speech_recognition_new .streaming_suspended_box .streaming_suspended .streaming_suspended_img[data-v-1ec3a672]{width:16px;height:16px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAMCAYAAABbayygAAAABmJLR0QA/wD/AP+gvaeTAAAAJElEQVQYlWP8////fwYGBgZGRkZGBiwAJs+ETRIbGFU4WBUCAN6ICBTe98fbAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:16px 16px;margin-right:12px}.speech_recognition .speech_recognition_new .streaming_suspended_box .streaming_suspended .streaming_suspended_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .streaming_suspended_box .suspended_time[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#000;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .streaming_continue[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer;margin-bottom:40px}.speech_recognition .speech_recognition_new .streaming_continue .streaming_continue_img[data-v-1ec3a672]{width:16px;height:16px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAMCAYAAABbayygAAAABmJLR0QA/wD/AP+gvaeTAAAAdklEQVQYlY3QsQkCYRAF4SfmRqaCGJvbglXYgqEFWMV1IWhmE0aWYGYoiCCfwXFgIP868bDsvOCMZSr0vNBhWokDd2wxrsSBK9b/iANHLJJkBEXGM8m+uggnzFviDZvWj2/9VJNWzAWr1o4P7Pza70s8YFaU5wOtLPdya6UrCgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:16px 16px;margin-right:12px}.speech_recognition .speech_recognition_new .streaming_continue .streaming_continue_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500}.speech_recognition .speech_recognition_new .speech_recognition_end_to_end[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;text-align:center;line-height:44px;cursor:pointer}.speech_recognition .speech_recognition_new .speech_recognition_end_to_end[data-v-1ec3a672]:hover{opacity:.9}.speech_recognition .speech_recognition_new .end_to_end_ing_box[data-v-1ec3a672]{display:flex;align-items:center;height:44px}.speech_recognition .speech_recognition_new .end_to_end_ing_box .end_to_end_ing[data-v-1ec3a672]{width:136px;height:44px;background:#7278F5;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer}.speech_recognition .speech_recognition_new .end_to_end_ing_box .end_to_end_ing .end_to_end_ing_img[data-v-1ec3a672]{width:16px;height:16px}.speech_recognition .speech_recognition_new .end_to_end_ing_box .end_to_end_ing .end_to_end_ing_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .end_to_end_ing_box .end_to_end_ing_time[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#000;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .end_to_end_suspended_box[data-v-1ec3a672]{display:flex;align-items:center;height:44px}.speech_recognition .speech_recognition_new .end_to_end_suspended_box .end_to_end_suspended[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer}.speech_recognition .speech_recognition_new .end_to_end_suspended_box .end_to_end_suspended .end_to_end_suspended_img[data-v-1ec3a672]{width:16px;height:16px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAMCAYAAABbayygAAAABmJLR0QA/wD/AP+gvaeTAAAAJElEQVQYlWP8////fwYGBgZGRkZGBiwAJs+ETRIbGFU4WBUCAN6ICBTe98fbAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center;background-size:16px 16px;margin-right:12px}.speech_recognition .speech_recognition_new .end_to_end_suspended_box .end_to_end_suspended .end_to_end_suspended_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500}.speech_recognition .speech_recognition_new .end_to_end_suspended_box .end_to_end_ing_suspended_time[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#000;font-weight:500;margin-left:12px}.speech_recognition .speech_recognition_new .end_to_end_continue[data-v-1ec3a672]{width:136px;height:44px;background:#2932E1;border-radius:22px;display:flex;justify-content:center;align-items:center;cursor:pointer}.speech_recognition .speech_recognition_new .end_to_end_continue .end_to_end_continue_img[data-v-1ec3a672]{width:16px;height:16px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAMCAYAAABbayygAAAABmJLR0QA/wD/AP+gvaeTAAAAdklEQVQYlY3QsQkCYRAF4SfmRqaCGJvbglXYgqEFWMV1IWhmE0aWYGYoiCCfwXFgIP868bDsvOCMZSr0vNBhWokDd2wxrsSBK9b/iANHLJJkBEXGM8m+uggnzFviDZvWj2/9VJNWzAWr1o4P7Pza70s8YFaU5wOtLPdya6UrCgAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:16px 16px;margin-right:12px}.speech_recognition .speech_recognition_new .end_to_end_continue .end_to_end_continue_text[data-v-1ec3a672]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;font-weight:500}.voiceprint[data-v-8ecbfa80]{width:1200px;height:410px;background:#FFFFFF;padding:41px 80px 56px;box-sizing:border-box;display:flex}.voiceprint .voiceprint_recording[data-v-8ecbfa80]{width:423px;height:354px;margin-right:66px}.voiceprint .voiceprint_recording .recording_title[data-v-8ecbfa80]{display:flex;align-items:center;margin-bottom:20px}.voiceprint .voiceprint_recording .recording_title div[data-v-8ecbfa80]:nth-of-type(1){width:24px;height:24px;background:rgba(41,50,225,.7);font-family:PingFangSC-Regular;font-size:16px;color:#fff;letter-spacing:0;text-align:center;line-height:24px;font-weight:400;margin-right:16px;border-radius:50%}.voiceprint .voiceprint_recording .recording_title div[data-v-8ecbfa80]:nth-of-type(2){height:26px;font-family:PingFangSC-Regular;font-size:16px;color:#000;line-height:26px;font-weight:400}.voiceprint .voiceprint_recording .recording_btn[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#2932E1;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;margin-bottom:20px;margin-top:10px}.voiceprint .voiceprint_recording .recording_btn[data-v-8ecbfa80]:hover{background:#7278F5}.voiceprint .voiceprint_recording .recording_btn:hover .recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAABcklEQVQ4jbXUsW9PYRTG8ef9pYOQDiJVkXa01ECQYJPoIDGwkyaSbhIdRIiwMBj8BRYsmGwdDCaDpKGxdGp1oIuhWIziY+j7E657b9OKM517nud+c+59z3mTnsAo7uMDvmERF/ve6YPtqoDnOIZ9OI9V3N0O8DbmURr1SXzG1FaBb3CmQ3uI623aoIc5luR9h7aSZO9WgaVH0yX0AbcV/xeIm81T3SwwgZlWYJKrSSaG3iQjPY38qPmpJOe6gG+THK/5WpKDHcBDST7W/ESSxa725/Cs5pfwDjsanqP4iv0YwRoOdwH34MtwC/AUSxV+GreqfqHqs3jd8RW/oFewUHd5gJm6ggt4hCPVdwDrw+c+4ACP6+r99Q9RcBafMNvUW0ekjs5ckhtJlpMsJVnPxgScTPI9ybVSyove7lrAOzGNe/UgLter7N8WAlPouij+iNbBxZ0k47+VdicZw4OG9VUp5cmmwGwM6nij9rLFt9os/AR4hDDbLupsHwAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_recording .recording_btn .recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAABcklEQVQ4jbXUsW9PYRTG8ef9pYOQDiJVkXa01ECQYJPoIDGwkyaSbhIdRIiwMBj8BRYsmGwdDCaDpKGxdGp1oIuhWIziY+j7E657b9OKM517nud+c+59z3mTnsAo7uMDvmERF/ve6YPtqoDnOIZ9OI9V3N0O8DbmURr1SXzG1FaBb3CmQ3uI623aoIc5luR9h7aSZO9WgaVH0yX0AbcV/xeIm81T3SwwgZlWYJKrSSaG3iQjPY38qPmpJOe6gG+THK/5WpKDHcBDST7W/ESSxa725/Cs5pfwDjsanqP4iv0YwRoOdwH34MtwC/AUSxV+GreqfqHqs3jd8RW/oFewUHd5gJm6ggt4hCPVdwDrw+c+4ACP6+r99Q9RcBafMNvUW0ekjs5ckhtJlpMsJVnPxgScTPI9ybVSyove7lrAOzGNe/UgLter7N8WAlPouij+iNbBxZ0k47+VdicZw4OG9VUp5cmmwGwM6nij9rLFt9os/AR4hDDbLupsHwAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_recording .recording_btn .recording_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_recording .recording_btn_the_recording[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#7278F5;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;justify-content:center;margin-bottom:40px}.voiceprint .voiceprint_recording .recording_btn_the_recording .recording_img_the_recording[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAU0lEQVQ4jWNgGNLg////t6ht4H9S9TCRYQn5rsbmQkKuZkJSSPvwIkEM0zEUGggXIzlSCIGRY+BtDBFsMUVOOsQLKErYJABM7xELaFE4kO+aQQsAMeZRmWvp2dEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_recording .recording_btn_the_recording .recording_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_recording .complete_the_recording_btn[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#2932E1;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;margin-bottom:40px}.voiceprint .voiceprint_recording .complete_the_recording_btn[data-v-8ecbfa80]:hover{background:#7278F5}.voiceprint .voiceprint_recording .complete_the_recording_btn:hover .complete_the_recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAU0lEQVQ4jWNgGNLg////t6ht4H9S9TCRYQn5rsbmQkKuZkJSSPvwIkEM0zEUGggXIzlSCIGRY+BtDBFsMUVOOsQLKErYJABM7xELaFE4kO+aQQsAMeZRmWvp2dEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_recording .complete_the_recording_btn .complete_the_recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAU0lEQVQ4jWNgGNLg////t6ht4H9S9TCRYQn5rsbmQkKuZkJSSPvwIkEM0zEUGggXIzlSCIGRY+BtDBFsMUVOOsQLKErYJABM7xELaFE4kO+aQQsAMeZRmWvp2dEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_recording .complete_the_recording_btn .complete_the_recording_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_recording .recording_table[data-v-8ecbfa80]{width:322px}.voiceprint .voiceprint_recording .recording_table .recording_table_box .ant-table-thead>tr>th[data-v-8ecbfa80]{color:#000000d9;font-weight:500;text-align:left;background:rgba(40,50,225,.08);border-bottom:none;transition:background .3s ease;height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#333;font-weight:400}.voiceprint .voiceprint_recording .recording_table .recording_table_box .ant-table-thead>tr>th[data-v-8ecbfa80]:nth-of-type(2){border-left:2px solid white}.voiceprint .voiceprint_recording .recording_table .recording_table_box .ant-table-tbody>tr>td[data-v-8ecbfa80]{border-bottom:1px solid #f0f0f0;transition:background .3s;height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#333;font-weight:400}.voiceprint .voiceprint_recording .recording_input[data-v-8ecbfa80]{width:322px;margin-bottom:20px}.voiceprint .recording_point_to[data-v-8ecbfa80]{width:63px;height:47px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:63px 47px;margin-right:66px;margin-top:198px}.voiceprint .voiceprint_identify[data-v-8ecbfa80]{width:423px;height:354px}.voiceprint .voiceprint_identify .identify_title[data-v-8ecbfa80]{display:flex;align-items:center;margin-bottom:20px}.voiceprint .voiceprint_identify .identify_title div[data-v-8ecbfa80]:nth-of-type(1){width:24px;height:24px;background:rgba(41,50,225,.7);font-family:PingFangSC-Regular;font-size:16px;color:#fff;letter-spacing:0;text-align:center;line-height:24px;font-weight:400;margin-right:16px;border-radius:50%}.voiceprint .voiceprint_identify .identify_title div[data-v-8ecbfa80]:nth-of-type(2){height:26px;font-family:PingFangSC-Regular;font-size:16px;color:#000;line-height:26px;font-weight:400}.voiceprint .voiceprint_identify .identify_btn[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#2932E1;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;margin-bottom:40px;margin-top:10px}.voiceprint .voiceprint_identify .identify_btn[data-v-8ecbfa80]:hover{background:#7278F5}.voiceprint .voiceprint_identify .identify_btn:hover .identify_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAABcklEQVQ4jbXUsW9PYRTG8ef9pYOQDiJVkXa01ECQYJPoIDGwkyaSbhIdRIiwMBj8BRYsmGwdDCaDpKGxdGp1oIuhWIziY+j7E657b9OKM517nud+c+59z3mTnsAo7uMDvmERF/ve6YPtqoDnOIZ9OI9V3N0O8DbmURr1SXzG1FaBb3CmQ3uI623aoIc5luR9h7aSZO9WgaVH0yX0AbcV/xeIm81T3SwwgZlWYJKrSSaG3iQjPY38qPmpJOe6gG+THK/5WpKDHcBDST7W/ESSxa725/Cs5pfwDjsanqP4iv0YwRoOdwH34MtwC/AUSxV+GreqfqHqs3jd8RW/oFewUHd5gJm6ggt4hCPVdwDrw+c+4ACP6+r99Q9RcBafMNvUW0ekjs5ckhtJlpMsJVnPxgScTPI9ybVSyove7lrAOzGNe/UgLter7N8WAlPouij+iNbBxZ0k47+VdicZw4OG9VUp5cmmwGwM6nij9rLFt9os/AR4hDDbLupsHwAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_identify .identify_btn .identify_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAABcklEQVQ4jbXUsW9PYRTG8ef9pYOQDiJVkXa01ECQYJPoIDGwkyaSbhIdRIiwMBj8BRYsmGwdDCaDpKGxdGp1oIuhWIziY+j7E657b9OKM517nud+c+59z3mTnsAo7uMDvmERF/ve6YPtqoDnOIZ9OI9V3N0O8DbmURr1SXzG1FaBb3CmQ3uI623aoIc5luR9h7aSZO9WgaVH0yX0AbcV/xeIm81T3SwwgZlWYJKrSSaG3iQjPY38qPmpJOe6gG+THK/5WpKDHcBDST7W/ESSxa725/Cs5pfwDjsanqP4iv0YwRoOdwH34MtwC/AUSxV+GreqfqHqs3jd8RW/oFewUHd5gJm6ggt4hCPVdwDrw+c+4ACP6+r99Q9RcBafMNvUW0ekjs5ckhtJlpMsJVnPxgScTPI9ybVSyove7lrAOzGNe/UgLter7N8WAlPouij+iNbBxZ0k47+VdicZw4OG9VUp5cmmwGwM6nij9rLFt9os/AR4hDDbLupsHwAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_identify .identify_btn .identify_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_identify .identify_btn_the_recording[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#7278F5;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;justify-content:center;margin-bottom:40px}.voiceprint .voiceprint_identify .identify_btn_the_recording .identify_img_the_recording[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAABcklEQVQ4jbXUsW9PYRTG8ef9pYOQDiJVkXa01ECQYJPoIDGwkyaSbhIdRIiwMBj8BRYsmGwdDCaDpKGxdGp1oIuhWIziY+j7E657b9OKM517nud+c+59z3mTnsAo7uMDvmERF/ve6YPtqoDnOIZ9OI9V3N0O8DbmURr1SXzG1FaBb3CmQ3uI623aoIc5luR9h7aSZO9WgaVH0yX0AbcV/xeIm81T3SwwgZlWYJKrSSaG3iQjPY38qPmpJOe6gG+THK/5WpKDHcBDST7W/ESSxa725/Cs5pfwDjsanqP4iv0YwRoOdwH34MtwC/AUSxV+GreqfqHqs3jd8RW/oFewUHd5gJm6ggt4hCPVdwDrw+c+4ACP6+r99Q9RcBafMNvUW0ekjs5ckhtJlpMsJVnPxgScTPI9ybVSyove7lrAOzGNe/UgLter7N8WAlPouij+iNbBxZ0k47+VdicZw4OG9VUp5cmmwGwM6nij9rLFt9os/AR4hDDbLupsHwAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_identify .identify_btn_the_recording .recording_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_identify .identify_complete_the_recording_btn[data-v-8ecbfa80]{width:143px;height:44px;cursor:pointer;background:#2932E1;padding:0 24px 0 21px;box-sizing:border-box;border-radius:22px;display:flex;align-items:center;margin-bottom:40px}.voiceprint .voiceprint_identify .identify_complete_the_recording_btn[data-v-8ecbfa80]:hover{background:#7278F5}.voiceprint .voiceprint_identify .identify_complete_the_recording_btn:hover .identify_complete_the_recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAU0lEQVQ4jWNgGNLg////t6ht4H9S9TCRYQn5rsbmQkKuZkJSSPvwIkEM0zEUGggXIzlSCIGRY+BtDBFsMUVOOsQLKErYJABM7xELaFE4kO+aQQsAMeZRmWvp2dEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_identify .identify_complete_the_recording_btn .identify_complete_the_recording_img[data-v-8ecbfa80]{width:20px;height:20px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAU0lEQVQ4jWNgGNLg////t6ht4H9S9TCRYQn5rsbmQkKuZkJSSPvwIkEM0zEUGggXIzlSCIGRY+BtDBFsMUVOOsQLKErYJABM7xELaFE4kO+aQQsAMeZRmWvp2dEAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center;background-size:20px 20px;margin-right:8.26px}.voiceprint .voiceprint_identify .identify_complete_the_recording_btn .identify_complete_the_recording_prompt[data-v-8ecbfa80]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#fff;font-weight:400}.voiceprint .voiceprint_identify .identify_result[data-v-8ecbfa80]{width:422px;height:184px;text-align:center;line-height:184px;background:#FAFAFA;position:relative}.voiceprint .voiceprint_identify .identify_result .identify_result_default[data-v-8ecbfa80]{font-family:PingFangSC-Regular;font-size:16px;color:#999;font-weight:400}.voiceprint .voiceprint_identify .identify_result .identify_result_content div[data-v-8ecbfa80]:nth-of-type(1){height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#666;font-weight:400;margin-bottom:10px}.voiceprint .voiceprint_identify .identify_result .identify_result_content div[data-v-8ecbfa80]:nth-of-type(2){height:33px;font-family:PingFangSC-Medium;font-size:24px;color:#000;font-weight:500}.voiceprint .action_btn[data-v-8ecbfa80]{display:inline-block;height:22px;font-family:PingFangSC-Regular;font-size:16px;color:#2932e1;text-align:center;font-weight:400;cursor:pointer}.voice_commands[data-v-4a944260]{width:1200px;height:410px;background:#FFFFFF;padding:40px 50px 50px;box-sizing:border-box;display:flex}.voice_commands .voice_commands_traffic[data-v-4a944260]{width:468px;height:320px}.voice_commands .voice_commands_traffic .voice_commands_traffic_title[data-v-4a944260]{height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#000;letter-spacing:0;line-height:26px;font-weight:500;margin-bottom:30px}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper[data-v-4a944260]{width:465px;height:264px;position:relative}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .voice_commands_traffic_wrapper_move[data-v-4a944260]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_img_btn[data-v-4a944260]{width:116px;height:116px;background:#2932E1;display:flex;justify-content:center;align-items:center;border-radius:50%;cursor:pointer;margin-bottom:20px;margin-left:84px}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_img_btn[data-v-4a944260]:hover{width:116px;height:116px;background:#7278F5}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_img_btn:hover .start_recorder_img[data-v-4a944260]{width:50px;height:50px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAP8UlEQVR4nO2de3hU5Z3HP79zZjLJTC6EIFRYQO4gaOuNeqsVdLXU6urzaJddvFW3cb2gJnENSPvstKsmRAm2VNfauvIs1npF65WqxaqAt/WGV1BAUMFaEiDJTJKZOee3f5zcE0LmlpmJ83mePJPJnPO+v8n3/N7zvr/3955XyGD8fs3ZG2yaJIY5XbCniso0hLEK+YCv7ae47RUgAOxpew0INCnsAN2sGJvVtj4e5s3f4vdLKDXfKH4k1QZEQ9mS4BjDtudiyxxb9ERBJgCuBFcTAd0qKusVXetSWVtT49uZ4DqSRloLWlqq7vyS4DxR5oHMUXRaKuwQZJOKrlWbZwJ7vGvuukvCqbBjIKSloGWVjTNFzAtAfwKMTLU9Pdij8JChxqplS/PWpdqYnqSNoJWV9UURI+cyVbkYmJFqewbIRyK60mWHfrt06fB9qTYG0kDQioqGEeo2rwKuxunAZCDSCPY9tiHVt93s25VSS1JV8TU3NI0ybaMMdCHgTZUdCSYAerfLNm6pqfF+kQoDBl3Q0lJ1FxQ3X6GiN9E5nBhqNAM1hbnear9fWgaz4kEVtPyGxjnYxu1kzj0yXj5VdOHy6vw1g1XhoAjaNn6sVZUfD0Z96Yc+4LKlfDDGs0kXtHxx4EeirFQoSXZdac4+kEtrq72PJLOSpAnq96uroSX4M+DngJGsejIMBV1RmOv7j2SFF5MiaPmS4FgsvR84PhnlDwHeUMz5y6tztya64IQLWlHZfJIa9qMowxNd9pBCqFeMs5dX5b2cyGIT2hSWLw6cpWKvyYo5AJThovZzFYuD5yay2IQJWra46SKUR4C8RJX5DcCjqvdXLAqUJqrAhAhaURm8RlTuIfFTWd8ETIU7yxcF/IkoLG5ByxcFlqjobaRBXDiDEeA/KyoDNySioJgpr2y6EJGV8ZaTpQMVKF1W7ft9rAXELERZZeBMEVaTbWYTjSUiP15W5V0dy8kxCXrt4uBxhurzDJ1ZknSjWcU4PZYhTdSCVixpHq+W/TYZO3eZGQjURdQ48ldL83ZEc15UnaLSUnWrZd9HVsyko1BiiP2g36850ZwXlaD5xYFqsuG8QUPguw3Nzf8V5TkDo3xx4IcoT0ZzTpaEoAhn11b5Hh/IwQMSp2xJcIzYujEb0ksZu22DwweSrzSgJtew7dqsmCllhKFy60AOPKCHVlzf9I9qyLPx25Qlbgw9tfbm/L/0e0h/H/r9moNhrEisVVliRW3+e+FC9fR3TL+C7msOLkrV8oMsvRFkitsXKO//mP1QtiQ4Riz9hOx0WLoRtA0m76+DtF8PlYh9HVkx0xGvYcl+vbRPD71ycUOJR83PcNZZZkk/AhK2Dlm2rHB3zw/69NAczHKyYqYzPnLMhX190MtDKyvri8J4PkMYlmyrkoXPKxw20+TQGSYjSoSCfCEcgX37lC3bLDa+b7HjczvVZsbLPjs3dMht/uK9Xf/Yay4zYuRchmammC4XnPw9N3O+7yLX0/tuUlQojBtrMOckN5s/sXj86TC7vspYYYuMVve/Ad0CDr0EVZULB82kBJKfL1x8vocJ4zvvIvV7lG2fWTQ2KW63MGqkMGG8iWnC1CkmV19h8tDqEG+9E0mh5XGg8hN6CNrtMi67PjhbDH1tUI1KAB6PcPXlHr41yhFz+w6bJ9eE2Lqtt/d5vcKck1ycdIIblwtU4d77W3lnozXYZicE2+Co2272vdX+vlunSAy9YPBNip/55+Z0iLn+lQi/+W1Ln2ICBIPKU2vC3Pn7FgIBRQTmn+th1MjMXK1hWN016/gWpaXqBuYPukVxMnmiyeGzTADeftfi0SdC2AO4LW7bbnPPva1YFrjdcNYZ7iRbmiRE/rVNO6CLoPklwXnAiJQYFQenznW6AcGgsvrxEKoDP3fbZzbrXnHun9Onmow+OCO9dGRhcfC09jcd38B5dExm4fMKkyY43vnqGxGCwSjUbOOFF8MdHv3tw8xEmjdo2MIP2n/vEFTRuakxJ3bGjTMw2r7BBx/G1qlpbNKOMen4cRnpoQAd2hkA118fGA0yNXX2xEZRQWcn/evd0XtnO3/f7Qg6fFjGCnqoo2GboJapp6TWntjwejsFbW6OXdBgs/Oam8FTEWHRk6G9ybVlTiqNiZkEpatpND2pNEXE0dAAUNETUmtOlviREwEMJ5FXJqbanCzxopNLS9VtNLY2TSa74Ggo4Mob1jjRsNXM5gwNEUzTnGYYamcFHSKo6jRDRbKCDhFEZZqBMCbVhmRJDCKMN1AKUm1IlsSgUGJAegt6/LEuLlrgoagwdYveDptpcsmFHg7+VtqHBksM0jy770fzcjh8lskxR6VuZDXvNDczZ5iccGzaj+4KDCS9PbS1xQnLDR+eGg8VgeJixzNbWtM+ROgx0PT20N11zj9x5EG9mzu7y4yZOw7ncZnOxRLpI1dsWJGQ05YPUFefCYKmOV/sdKa2xow2cPUQbe++zlyTwjjuscXFzrkNDb0F6zpH+uXO9E/5NBCaUm1Ef3y6xXHDHDeMH9v9+vv6750CTJoYW7aBacIhbamff/u6t2BTJjvlNrcoX3yZ9oK2GiiNqbaiP7ZssztSRNr/ue3s+sqmfo8j6uyjY2tzZx1q4mubV/3go95ZD1Pb6tyy1R5Q8lmKaTUgvT20pUXZ3pYictQRLqRLy6oKr/+fc+M7ZJzBkd+JTlRPDpxxuvPUmIYG5aNN3QWdcIjB8LbmeNMnGZG322BAensowOtvOKINLxamT+vupS+uC7Ov7d533jk5jBs7sG6BacKC+R5KShzB1jwXJtxjR7Pjv+tcIKGwkyKa9ih1BpL+gr69sTOj73vHdffCUAjueyCEZUFODlz+01xmH9Xdk3tSUiJc/tNcZs5wLo6N71u8/mb3Lm5hoXD4LKeut9+NxJXiMmgY1JnHnbhkLvCdVNvSH7YNPp+zLmVEicH2HXa3IUT9HqWuXpk5w8Ttcu6Lsw418eQItjpjyaIig0kTDE452c25Z3s6mtJPt1j87x+dhOuunHNWDmPHGKjCg6tDNDZmgKDKX12iukn7u5zThBdejHDsMS7y8oSzz3Sz/DcWoS77Krz1ToQ9e20W/LOH4mHC6IONtsTpvjPibRvWbYjwxDO9M+0nTTQ5+gjHO9/ZaGXEcAVARTeZx5+0ZAQZsAQiHIbWEMyYZuLzCcOKhPd75OLu3atseM1pnosKnXWhPWluUTa+Z/GHB0K8+U6kV6Z9Qb5w2aUecj1CS6uyclUrLa3J/GYJRGWFy7LsTYaR9vEFADa8GmHGVJMZ002OPtJFQ4Py1J+792QiEXhpfYSX1kcoHiYcNMKgoEBoaVEaGpWdu+xezWs7Pp9QeomHwrZ834cfDbF3XwY0tW2IYW4Sv19zGlqCATIkr8jnFa76d09HKHDDaxH+9GSoz7BdNIw8yOCiBZ2r2F5aF+FPT2XUVtzhpnqvTwDKFzVtyqTM+cJC4crSXEa0DTm+3GXz2BN9rwc9EC6XMzz5wWk5eNoeZPrq6xEefiy6hU+pRz6urfbOcAGIynoVMkbQhgbl13e0cP78HKZOMRlzsMGVpbl8ssXijTctPvjQOuDMyEEjhCO+7WL20S6KhzkXhm3D038O89eXwxkmJoCug/Zm1tAX2pZ3ZwyBoPK7la2ccKyL0091k5cnTJlkMmWSiW0761V27lICAaW5RTFNyMsViocJY0Y799WufPGlzaOPh/hsR2b0aHuiqi9Am6CmJX+JZEa/qBu2DS9viPDWuxbHzXZx7GzH2wwDRo00GDWA7di3bLVY90qE9z6wMtArO1A15QXosjqkYlHw40x/rp+IM802eaLJP4xx4rAjRwp5uc7XrN+j1Nfb7K5Ttm232fyp1eeUWQbyYW21byZ06dmq6FqUjBZU1Wk6u05znTLHzQ9Pc4ILN9U0p8q0ZLO2/ZfOBb82z6TGlixxI53adQhalOd9BvhbSgzKEg9fN9V5n2t/0yGo3y8RhAdTY1OWWFH0D3fdJR3hsm7RIVFWKfT5UMB0YtahJtOnmv1OkbUzZnRn9/28cwa2BUooDOs2hDMhKQxBVnV/34PyRYH3gFmDZlGUmCZU/cKLmeQHlrz9rsW996d9VL6jd9tOr/itiK5SlaWDZ1N0WBa88VaEKZOSp6ja8O57GfD8P9F7ev6pl6AhT+ud7ubcxen8eNWHVmdU0DxZ7LM94V7bUvaKD63wlzSowR2DY1OWWBHhVz2flQv7eaJ1CKuWNM8G/IYTIGT1uf1Kn4LeXlVYp+jvkmtTllgR5I6+njcP/ewK4bblVmDIxsoymIBh2bX7+3C/gtbU+HYCVUkxKUvMiOqNt9yS/9X+Pu930qww17sU5OPEm5UlNnRzKOhb3t8RB9j7TEKKnfaRo28KBnr5ihXSb7TjgNPay6vznxfRbIw31Yjcd2t1wdoDHTagPAXTkjKBuvityhIju23R6wZy4IAEranx7VThQiD9o9VDD0W4dCC7+0IUm6rXVvmeFmS/3eUsyUJqBrr/NkQhKEBBbt4iYH3UNmWJCYXXmurzfh7NOVEJ6vdLRExjAUJ9dKZliRaBOjHlvK6T1wMh6uTNZTflbceSM4BAtOdmGTDNqHF27U3ez6M9MaZs3Noa76uq/AuQAZOGGYclIucvW5q3LpaTY06vXr7U94SIXkK255tIVIXLllV5V8daQFz58suq8leJ8rN4ysjSFV2yvMp3dzwlJGTpdkVl8BoVXZ6o8r6BKPDL2mqfP96CEiZAeWXThYjcTYasM00jLITLa6t8CZl/TqhHlVUGzhThASCDt7QZVFpBFtRWex9JVIEJbyIrKptPROzHFEoSXfZQQqDOEvmn26q8CQ3UJHwR4bKleevUlCPIRpT2j/C6uIxjEi0mJEFQgNqbvJ8X5npPBn4BZOYK2uSgoL9uqvOeeOuNeduSUUHSe6Vli5pOFeReYFSy60pzdiNcVFvlezqZlSR93fby6vznbYMjQP+Y7LrSFpH7bIPDky0mDPK4sWxx8/dF7duBmQc8eAig6CfAVcur858drDoHPRBQWqruguLmK1T0RtJ8A4M4CAK3hAPeqgPlACWalEV2rruucaTtMq4ArgWKUmVHgmkC/R+XLUvb0mAHnZSH6q5c3FDiUXMhwkKU4am2JzakEbijVSK33F5VmNLcq5QL2s5Cf12hu9VTisrFZM499gNEV4Y9rXet8Jc0pNoYSCNBu1JW2ThTxLwA9GLSbbgj1KvysKHGqljnLJNJWgrajt+vrqbm4Om2wTyUucCMFJnyIbAW4ZlCj/dZv1/SdmI/rQXtybU3BA42bZ2rKnMQOQF0Evt7wnHshEG2oLpe0bUum7X9rSVJNzJK0J6Ulqo7b1jjREPM6Yah09SWqRiME5uDVCjBGRa56RweNQFhoEmUOjX4OzY7VHQTKptttT5u3luwNdrErHTi/wG5jWw4PKXrYgAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:50px 50px}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_img_btn .start_recorder_img[data-v-4a944260]{width:50px;height:50px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAABmJLR0QA/wD/AP+gvaeTAAAQMElEQVR4nO2de3xU5ZnHv8+ZyYUkJIGEgNwSLpKEKJgMwmqpBlArXW3tVv1Q78qnunbFC9XWlbqrtVpFilY+2lqrYFFWrVK3VUHFLO3qtkguiIaEi5gJF5UQLrmRkJnz7B+TBEJIyFzPGZjvXzNz3ssv+c175r0873uEKKagoDJeEpLHeSEPlQkqmivIKJAU0GSBZIVBQHJHlmaB/QrNIM2gTSC1qG5BdIsDqrWt+fPKyoLDVv5dwSBWC/CHCZN3jHAY5kwVnSHIdGAM4AxxNR5Et6vykYGUeFVKNleM3h3iOsKGrQ11uUrjWs2s2aahs1FmALkWSdmMaomKrEqWutVlZVPaLdJxQmxp6MTJ7gJ1cq0qNwpkWa3nGPYL/FGE5ZVl2R9aLeZYbGPoWNfnaQnqvAW4Aci3WE5/qQKWtYnn2e1l4w5aLQZsYOgE1+5Mp7bfpnA7vg5MNNKoylIx9NGqspwvrRRimaFnTNs+1Otx3IUyD0iySkeIaVbleY/X8fi2jSN3WiEg4oa6XKVxLQz5EcrDHBlOnGwcEljYkmo+WrN2TGskK46oobmumhmGytNEz29ksGwzMOZVlo9aHakKI2LohMk7Rjgc5mLgykjUZ0NeNVXmR2I8G3ZD84rclwgsAzLCXZfNOaiqc6srct4IZyVhM7S4WJ17Gmp/pnA/YISrnihDVVniONx0T7imF8Ni6Bln7xrl9XpeAc4NR/nRjsJ608GcLeuzt4e67JAbml9Yex7onxAGh7rskwpln4hctql89P+GstiQ3goLCmu/g+jqmJn9QBis6PsFhe7LQ1lsyAzNc7mvN0XfAAaEqsxTgARTeCWvyH1zqAoMiaH5Lvcdoiwl9EtZpwIOgd9OLHI/EIrCgjY0v6h2AcqT2GBeOIoRhf+cWFR7X9AFBZM5v9B9HcKyYMuJ0YUienNVWc7vAy0gYCPyityXCqwkdpsNNV5Fr6wuz1kZSOaADM0rrDlHRNZw8qyS2I1DgnwrkCGN34bmF27PRhwVRO/aZbRQb4inqLJsXK0/mfzqFLlcpXGIYwUxMyNBhqmO1woKKuP9yeSXoYfIfJTYdF4EkWlmQspDfuXob8L8KTXfxpS3/MkTIySooXJZZcXoP/cncb/M6YiH3Rib0rOMvYhO6k+8Ur9uuQ6HuThmpqVkimks6k/CE7bQ/CnuCzF5L3hNMYJFlAs2VWR/0Geavi4WFFTGmwkpG7EuYj1Gd7a2Nxw+c9u209t6S9DnLdebmHIvMTPtxOnOtPj5fSXotYV2BHZtJbYcZjdaEB3fWwep1xbqcJh3EzPTjiSpGr220uO20LypOzPE460BUsKlKkZQNHslLmdL2fC9x144fgv1eOYTM9POJDvN9nnHu9CjhXbsAqsB0sOtKlykpxlcODOJ4vMGkD3KSUaGg9ZWZU+dl49LW3m/pIWNn0XtJu1ODiaYZs6GDWMOHP1hD0Pzi9w/AR6LmKwQEh8v3HjtQOZen0pKct9zJv+3rpWFi/ezZZtt9+6eEBG9Z1NZTrcJh56GutyfoRRETlZoGDzYwVOLMimanND12c5dHso3tFG/z0tiosHYMU5cZyXgdPr+7NZW5T8e2sdbq5utkh0sm6rKs7t51c3Qgik7ppqmuS6ymoInOclgxbKhnD4uDoBPPm3jV08doLS85/g7LdVg7vWpXHfVQOLjBVX48b/vZfX7LZGWHRpEXVVlOeWdb7vdl9TUayOvKHgefmBwl5krXmvkmrlfH9dMgIMNJouXHOCmf93D/gMmIvDIgxmMGxsXScmhQ6WbZ12GulylcYrOibyi4Jg2JZGLZvkiYd55t4WHF+7H6z1xvvJP2pj34zra25XEBOGnd0Xnmr3CVS5Xade3scvQVjNrNpBpiaoguGVuKuBreQ89ug/V/uct39DGy682ATD93ERyJ/gVHGALBLJayLyo832Xoaahs62RFDjpaQZnuxIB+OPKJg42mH6X8fyLDXg7sl18QXTGvIkaF3e+Puo3VGdaISYYJp+ZgMPhe13y10MBlVG/z8vGT9s6you+FgqgR3lnAOQW1g5HZYJ1kgIja4ij6/UXNYGPJ2tqPQCMGB61IcYTcwtrh0OHoQY6y1o9gZGWduQG09jk/+22k4MHfXkHDozefclimMXQYaiKzrBUTYCEKlpN8aMnZVPElBnQYagI37BWToxgEWE6gFFQUBmPylirBcUIDoXxLldpnEF8ynhiG45OBpxNMnisYYrGYoZOEpxeZ66hIjFDTxJMMXMNQ2NRfScNYuQaqoywWkeMEKGabSAy0GodMUJGhoGorQ2dc3kKTy7MZGiW48SJw8SFM5N4evEQJoy3+5qpZBiovaP77r5jEBfNSuKyS607Wvf2W9OYcf4ArrrS1t99QAcaKLZW2dTsm2cdadHEuWEcmbTv1GJjEgzE3i20dodvJWTMmJ63O4/nyOv4+MBnduM7gsba2nrO6Q4b6iQx0Xe9dqenx3WbkWD75YVN1b742Ym58T1M+/LrI//go5fS/GV4Rwusq+sZuzLpjCNrpFXV9o/lNVCarBbRF+tKfUe2JyZKjwXoL9xHDJ3aEbngL06nUNgR+vn5Fz3XVM+Z5iu3sdFkU5XtDW0zEBqtVtEXpWVtXUFf50ztbtqWrYfZuctn6r98N7BO06ziAaR3rKv+z996Rj101rm+rK0rVMXGtBmIvVtoY5PJJ5/5QkQumZ2McXTQjMLKP/uCpM+alMAlF/tnalKSMH+eb8fHnjovf/uwu6FFZyUwcoTvdvzh3wMLcYkwDQYqtm6hAG+86fvOjRzh5Jvndt/h+OLLDXy9x9eEH/zZYM4s6F9cUFyc8PjDmYwa6TNsyW8P0npMp2jOFb7+Ymur8s57URGIXW+gantDV73b0hXRd/Wc7qOsQ4eUe++vx+NRBgwQXvzdUL73ne4t+VhGjXSy9NksZpzn+3K890ELK/+7+40qa4iDi2b6ogDfXt1MQwARhRFHqXdkDb9rJnCW1Vr6wuOFQekGhZMTGD3KyYaNbew4agixa7eHHbu8FH9zAAkJwqziJGYVDyApycA0FREYOtTJ2UWJ/PDGVB64b3DX2HLd+lbm37uX9mP6Qwt+OpiC/HhU4f6H9rG3vh/R21ZjyFrJc7nvFeWXVms5EelpBqvfHE5qqsH2mnauuOYrDh3qfossOiuBhb/IYPhpJ56E8HrhpVcaWfTrnpH2U12JLH02CxF4e3UL9yzosa/WpuhPHEOGz88EbL8ForVNaTmknDd9AIPSHQzLcvLB2u4dlS+/8vLK600cOGgyZIiTzIyeY9PGRpN317Rwz4J63lrV3CPSPmOwg+d/k0VyskFTs8ntd9fR1BwdQWSKLJEzimryvcgmq8X0BxF45skhnD/d99v33LIGnlhyoNf0pw1zkpPtZEimg8Ymk7o6L9Vb2vF4jm/QoHSDF36T1bUl4p4Fe3l7dVR0hgBQryNXOs4iaiZK4orS0wxeemEoY3N8U4Gvvt7Eo7/aT9vh4FrR2Jw4nlyYyfiOXWwvvtzIY4v3B603grQnSV2yAOS7ajZHU+R81hAHf3huKKNH+b6D1ZsP88ii/b1uIeyL+HhhzuUp3H5rOklJvqnF11Y28eAj/m18shqB6k3l2fkCkFdU84IgN1otyh/S0wwW/TKTc6cdmT36x8etvPlWMyVrD51wZSQn28m3L0rm+5clc9ow3xfDa8ITSw6wdHlDVJkJgPL7qorsH/paaKH7WoQ/WK3JXxwG/ODKgdx2SxqpqUcGnl4Tamraqd7SzoEDXhqaTOKcQupAg9OGOcjPi+/RYaqsOszDC/ezYaP/rdwOqOjV1WU5KwR8m5UM0V1WiwqUQekGV34/hSu+l9KvIcvRfFzWyorXmlhT0oIZBXMHvaCIjqgqy/myaz0qv8hdTZSf62cYkJ8bz1RXIgUT4xkx3MHYnLiuTUi7dnvYucuDe4eHik/a+Pu6VvYcZ8ksCuk6POPI11m1hCiP0TVN362z8qhlrptvSuXOf/NNwF94adifx2oJgpR0vu764VGRVdbIiREsaphd3nUZOix19CqUr62RFCNQFPYk6d73O993Gbp2rXjU4DVrZMUIFEFfLiub0rW00K1L6PDKctPQ4x4KaCdmFQ/wrYv2Iy5sYu6R9dEHFvTv2PzWVuXlVxrZscv2QWGIwfJu749NkF/k/hQ4I2KK/MTpFMo/Gtl1vFu4eOfdFu6+z/arLD2OhjveoG05Nj680eNR/vSXZv5pamBBYf3B9MK7a+w/KS+iS3t8duwH46dtTY1rj3cTxcerniIc93jVHoEa29ad3qDoM5HTFSMQRPn1sWZCbydaO52Lwd7RgKc4zR4jbsnxLhzX0OqPR9aDPhdeTTGC4JnjnTcPfTwVwlRjERAVwainGM2Gw1zc28VeDd1cMXo3orYPHjvVUOEXlevHfNXb9T43KxmtzY8JVIdeVoyAEN3iOXj4ib6S9GloZWXBYVVsP3N0qmAot/b13DPox+Mmqyqy10BsjtdqRGVFZXlOyYnS9Wt/qKlyF1AftKoYgbJXDfPu/iTsl6GbK0bvxtDr4CQ4tjL6UENlbn+e7gt+PFS9qjTnHVHptbscI0wIC/v7/G3ww1CArLRR94rykf+qYgSGrkui7n5/cvi9BpVfuD0bHOWxZ3KHnXqHw1n42foRO/zJ5PehGVUVY92I+c9A1D5fKgo4ZAiX+WsmBGAoQFX5mH8o/ACw/5J+9OFV9JrKsuwPA8kc8LE21eXZf0G5iVjPN5QoqrdUl+esDLSAoM4pqqrIXi7Iz4IpI8YRVFhQVZHzfDBlhCQwJ9/lvgPliVCVdwqiAj/fVJ79QLAFhcyA/EL3dQjPEyX7TG2EV+HW6vLskKw/h7RF5RW5LxV4FRhwwsQxANpU9erqipw3QlVgyG+RBS73dFN5E8gIddknGfWmwXc3l2aHdKIm5Ic3VpZlf+hwOAtjM0p9oHxsevTsUJsJYTAU4LP1I3ZkpY0uFngQiN5dl6FHVXkqyaibvnljzhfhqCDsvdL8QvcFwEsIQ8Ndl83Zi6HXV5XmvBPOSsJ+Xm5VRfYaDC1E9L/CXZddEZUViE4Kt5kQ4XFjXuGO88Uwn0YpOHHqk4KtKnJbddno9yJVYURPtK6uGPXXJOoKEe7k5A7kbhF4sL3h8JmRNBMsnNmZNGlblscZ9yOFO4E0q3SEmCZVXlDksc0Voy3Z/2/5VF3e1J0Zhsc7T5V5UbzG2ojwjDocj/t2HViH5YZ2Mn7a1tR4T9zNitwQNb+xQqWgyw4723+3bd3pDVbLARsZejQTJ7sL1Mm1mNxgu+GOsk+E10VYHuiaZTixpaGdFBer8+tG97dQYzboTCDfIimbBClRw1w1NCX7vbVrxbYL+7Y29FjyXTWniTJTxZghqt9QGAeE+oFk7QKfq8hHilniMLSkr70kdiOqDD0Wl6s0rkkGj3V4nHlqaC4iEzB1NAZDUDKAFHyGdz49qgloB5oQ6jGpw5Ba1NwsprHF6/RUp+i+7UefKhJt/D+IYnHePFNWNgAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:50px 50px}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_prompt[data-v-4a944260]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-bottom:16px;margin-left:110px}.voice_commands .voice_commands_traffic .voice_commands_traffic_wrapper .traffic_btn_list[data-v-4a944260]{height:20px;font-family:PingFangSC-Regular;font-size:12px;color:#999;font-weight:400;width:112%}.voice_commands .voice_point_to[data-v-4a944260]{width:47px;height:63px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABwCAYAAACNSCemAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUqADAAQAAAABAAAAcAAAAAAkHfOMAAAU9UlEQVR4Ae2dW4xkx1nH+5zTvbMXe1nbO9Mzu2vSD3YUZRMUgmISiIQhJBIPIeIh4iIHlJjbQ0SkiBekXAwCxAMWiiwURAARhUSJBIag+AGwklUU2RFyjLETOSEImyyemZ7ddfbqvcx0N7//v6pO95mM7ZnZ6Znu6and6TqnLudU/c+/vu+rr+p013q9Xl7bCzeNQH7q1KkcMBt7gN4klgBYPPfcc/uXlpZu+Vavt+8mLzex1SvD+tj58wfPnTt3eI+dG+eDhnbWarV6qnrx4sXs+vXr+2Dn9OnTpw9s/HKTWyPT0Kb7jTNnztQbjUb92rVrjSKEBqBenZubezHLsu7kQrS+npuRzz//fFn60KFDPYDLALQGnofPnz//w/Pz8wfLAnsHayJgRgJkAwDrV65cqe/fv79RJ9y4caMOkPU8z+udTkcsfXF6eroNxhYDa15tghMrygbQMmHBcO8BaE3MTNiQNIMiet0eOxMi1bgCZLfbNdsEoIa2AB0sDksPkPWGs2fPHierBHmwzKQeV4A8cuRITTJSYIiRCoA3CJgwlmZvoZzetKfZDZE/JCPrHBUA00gyUkp7eXlZclFysgF2heSk5OXKyorkZgP2Uq+ed7s3/vv48eOn+5eczCNp7RrKxqwTIxVMOzGPPw1vQHV+iBslUnneLShycmFh4R7NjsqMCTzI77333lIOyiAXcClMcaChvW9fmjk2MI1WMlhZQ7FbhsJYmUsziIJ3oIxOTCCG7nJFRh4+fNg2JMBkg1obMF24EckoEBU6najVi6LWY7gz/N/abrffBv4JeZebhA8b5KmjGN8+FCOT1oaNZmzEstTkYiVk7AFeBqI1TY86/FG1xVB/N4roeLruJMQa2mU/B2XkICNVII1usZVTwK1blpbsVCGBSmC4H6xPTb0Ldv7kE0880Reqytylwcpm0GmhfqK9a4mRq/sttpIGYCtmp5ipIEamAEEFqv6fPHHixHtxgsymvN0aV6eIOC2mrl6V86KBXIRs9QaaujJVRPMUeTSFGNZ1CFrHyY6J1K13Oc4wi0jDPMowk3oNvB11biLt/uTMzMzXiQXzrgsVZSPjh45mYqRCb2qql2SkE0hCZVtri4cqaxmJdIyyUkObNJUmjU9uAIM99fzxxcUz70N+Tit3twUrm8GhraHL7MYgMb7L/sqGhKg+t1xkSMdh7jSZQbFwDyUe6oMkhjvgdoklDjpNsL9fmv2BBx6oPMTyRmN64KFN29f0R8Zh3dBsZmUlxzMUPEEa0prdaKZD3ULHyxrS3a5mQXXNepSmPOypBjcJwz4Mc9aHEAFZ7wWu//Cdd9754phiV2m2Gfly/kgN3cS6pLVdW3ZkHdFIkC0JsEFjw0oNZ9gJW/MeMjMLQxuGiplmJwVIRHa2YPaHFs6evafSojE9MSPX448U+wDM824YJzb6WAwEz8hEMa3PyqSEmKrDyF5iLNYnLM20ckndGnP2LPvOVKPxhTvuuOPimOIobvQD4EhZWPattiOVjoz0zMcyUoqHYCVDXog7VslmKKyUrOSayE4EpGWkrlLL8nDXnu6uG+a1/OSNGysfwdf5ZpcYw48KkDDNCkMArWVHItPcxWQ76iQpGccMbdmTqm870qX1kTOFtPb29VE8TtNnCCTktYN5Xvzm4uLir4+j87gC5Hr8kanrxJafZqKop4DAtMkDCwWmdh4Ebd2NBrtnRaFsDQlKvk5UJpJU6xhvy+v1PwLQN8SCYxGpL9a8m/FHdruWk2hojHFr7DqGd9e+SnAMhnpRkwxVRiwDbZGPmeQjMSg5n3PkpvAOspNj0rNHL1++8Lm77777+qij6SniZv2RwQkUp4ga1pGY0tpipGCBad5cBNCIw0IWZWRfV3lW344Z+l3ErmuQEI57P3fwllseZIp598gDuRX+yNTJoHAwgTCHZP6Eod3VojgKBqVDgkALMlIWESdBdirRACMMXCBHckh4FFl+rNPt/ily830wOz6qdMfRiU2G1Jyb8UdG+xERhwfIjJQVKZmIToaVZmTVjgy3Jc15AhqpGdR4Hhjp+i7GUfEryM2H5ue//5rU3lGKbZCnBm2FP9LXMiPhD0GD1LSzGRTZaPZJISkfoMVKmUecZYKdKmYk9RniPAYnIzIzhvj1T72wuPiLZMlyGpmQD8kfKbsoyMlVXR20IaXahZtg479lpBDVqWUk+QDKdWSLhoCMkKL64OLi0p+jIOdS+k7HVjatgU1UatAW+iN/wCCXXEReBqKKrPyhgIynQVMDjCXD3Hk905XjwEDJUJCEpm9eXul+nuH+HlXZ6SDzpyiniMPzR9pvKRMJFso/6Rg4mS5qelnIFCLdplADr1s4zmoNELN5xEhuMO9iStnjD1OJmEeCy0mmVPdrnc6hj584cfjcTgFKX/phiP7IeBM0uY+Io9Fe3h3GheFMCqRzECMlRqWGrN0lMEXIEAdmOvuni+KlR+bb7XeFitv/aWUzOLRhyBD9kbIlCUKTMR7MIGloEAMogyyoOAh2pA6jjExAu7IuAq8j4Eha4M5uA+BPzi8sPIjsvFUltjPkKBs13R1M5o/AnMI7roYg752n0ZgaFufayso0x5YBLvMnhuBW4wTSYTsGDoKSjsM1AgBR0fjE99CRqFcyUlqdnKiA4v0jevKZpDv2GasrvHd5pfNljPi3p+ztiM3IHfJHilMGGgPI5k9uewigwNLmDw9KQzuaRAE3QxugEbJ6TIphZ+Alh1Q7vtLpPjy/uPjH27UDJDHSLZMdicbuP2h1dCBouUFsrWnlkLUbZUFIl7H3B1r2px6c8D9MDTVuSxMmWTiMR5DTEOcfxE2ST9Z7aIMxFT6cKz+EGDPkOZedCXAhTXGfp4L0t6f2H/was6Ifi3WHFoVxFy+PAnAHBNY2+yMlL7l3MLJBzTal6CagmGCasW6mS7kcbFaKgC6HuXKV6ISM7oDra7O8OLWw0P4Y5eSgGUqoAAl73Aqe8E74I4VYnK5o3g27ojj00xWplQZ6lIK9FE35YqIZrWQTlSpSRu6OgJYX/iOLi+3H2Nv5umEgWQFyRPyRYBUZSY+BbbDfnCT0SJYyUgBUy0joRwE9DKW7otjqMkrOsregiJ5kVvQ7/fSQe7OfAjJrtVpuUJKR3MR7f3RxtLeXGHSspQaFtNSghS/sZTl041JD8JAH7w+EwG+h4Re7zhWk2xmmfnyodJhvrQ6bwtCOjKRCYB/FjQoJwfwJEKm+WswFfClGN2cKlpHOihirhU6PHzT/ALz9xGJ76VF2z93p3C348BRxdP2R4BcBUV8TOwFD7IoPRDmcWhnBTDNQjygSUYIgHqcU1aDcz8DOZ1hj/1Wd32zIox3p62x2f2RqxDD8kRE8UDOvLQEtI6GjDHIpI4HnoS1AzdVgXKR2BXANHvhbOTlGJfxQp9v79GK7/fClS5duageIR0a6YTLI9TgHtfZ69kdq0NoEGo4/EgpGH2VQJm5yYJjBS4yEnPFccewd3YlDP3IyMTSeQvpfuHzlyjdxgPx8wmKjsQ3yVGnU/ZGxnWFgM2Q9vJUIUGYkcJmdJBHLSHeIjGSIR1amfMoEhqpYNoOS/yKK6K83M8XU0NZVHLZwf6ToqUbGZ57ugJwLLLF8s/DyOR9SOBquGsKc6lgX0NDmMykT+kumR7PyhU2Qi8KIgvqvsr6z7MjVQRkCWbELuXAEmDTu+wFmRc8A5k+trvtK51Y2rVbLDZWMVOHx8EfSeTBPaNIBt10Y0QWdlnYkgKl//kggKkHHCilNx67c670GML+y0G4/SN66XjIQI3tJa3fZQ66g3Wi+KC3QZnyf8KEpIjaQT6MJFOViuXzo9kFGQthp4b5yBhNDq8U2rdNoXZu+inta1emPQhVWfQIx828fqrIVj0/50H8u4HoBPCGisvqQtoHIZl+4gBKVW/nsg6iq1ClB5VTc/jBm0jdg56vuAElN9i3G1x8Z4ekP14AoQs9PS1qdHgooPRfFCuTpIx47wWnOj2U4fj2a/euw86Mc910JrtX/sLJpDQxtCo+pPzJ0iuZzIOkbAEpd1VmZRp7KqajSfaz8eKxyZVkREx8i7PyDdnvpMdj5Wor9QMg1tEn1XZP5Q8Ux9keqLyZg7KxBNboCzIE4gJVYSpWYp/RUTrGeR6ysycE9yM6nFhaWPkieMYs3qZmRu80fSeckI2MfdehOC+CQJnQIKpOYlwBUNR+Tn9JUOpRzvQMIiofaS0v/OviCVmKkrltLc22f8KEWpGPFY+ePHGw83TG71KXYrQSUupk6GjEuy6RLBNCNifOo8rOaYrJOdJ/KVPxzq/2RLCnERxguJ6eFpoHS2HK50RDvj9TyqtJ9zlMnsUYhLRFS0RtXWNkqm+j9kW47qs77WdDH4XJhuCR/pLSuPeT2R8pu5HL80W0uxvCVqiSZTupcjXQukUGDRu407VJDwkdsRgBGdajpqjrkWkQCmjo6cnDlmJfSVZ9whAqfWWif+YmK1t7F/khQAcfQeQE/AJQBcZrTQUdgRaAMpCD1+Rr1eUZfOHRg6mMVIHe7PzKxyegkcAKTDV4AMOSm434dMbfPUo7ngfs9c7Ozv4SSPisgs1ar5ceSZCTo72Z/ZGCcOg4wwiaxT3E6d1rErUynjo7zLP+bfY3662dnZ/+ZJAdPEdPMZnCuzU1e9X3t4e+PZN4Th5Nau5X+SBAJCOgT9AJwAbkAcJC6To8lYd1zRZ69c3Z25v7bb7/9Qv8CtC3akU6bNH+ksDTb6L3BI9a5/+Kx0lGmLGNmD9VqM29sNpuPGqxVHxWtLYOcTfjUDf7IpLXlj5Rm1jQbheyX3nUdKWqzUhsEWCvgpUWWDOL+SL9lo9m0PIladvASaxhLPFqtS/n5a94t/V/Yw6OukYEWlyYmBDUq3Rz8kaiMOOBCfZ26kObyQoYqLkDsAydZYdPiWFV5OiNKxEzM0y3L4OPs21z//uZs87EyfY0DG+QpfZL9kYMABlCzFZ7Mn8w2p98EC18RROGnoa3YYVBGDnrIlZne/DJLTJtXfF97bP2REFij76kir91zbHb29+jvul4EsLJptYLW3vNH1q6j0D7anJl+C69E/4fZtc4PK5uktSfZHwlej/MSy4+ikf8QFrInZ2NBdmQZJtQf+RKK7MOzzZm3Hzt69NkSjA0eWNkMDm0E7cT4I8Hqy0U29cbZ2ek/g4XRSb9BBGNxD22OrfMnxR9JZy8UefFbc7PNdzSbR/5nc9BVa5mRk+SPxMr8UqNenGw2p/+yCsXNnSVG+ipprp0uqWGejhWPuT/yLF91cB/K5N1Hjx59YbBfW3FcUTbYTx7iAnC1HambDfF97aHtjzRIWfYPrN3+CCz87FaAttY1KlPE1f5IbUFBCJf1YKSnitpDrimjgsqIuIrx3fYKpoqupB1qlAnLbszftPmsq2kgWwAQ62EfWSI8Cbn8hThkNdPzi59UkPjn9mqB9qDzrhh3YnDqhvbohkzaqGSqqW6aNlOq221n9eJ3j01PP6K2DjNUGLmb/JHA/fn9U/veOrcNIOoBCcgsmT9JRopi+gYBhXHbH8k6xv8hoX4ZWfih1a4ud2hIH54ippnN4Fyb4TJe/khtuuh1/67bWXkn07uvDgmvl71sRWuPsT/yf5GH9/Gd6Q8cO3bspZft7RAzKspm3PyR2Bh4R/PPNGen/0IDaIg4veqlbZCnUmPmj/xuvV78GrLwEzsNovDT0FbsMCgjV9uRo+KPxLRawUj6q2Zz5v0Y1t9Obd/p2Momae1R90diNT6LTvmNubmZv4WFG3Z1DRNs2bYj/742EwW9Y/e5uZmZfwJAmekjFyrKRv5ILX1pxy7TwfD9kcwa9N5MDOH7IznPGetsAo1bVnoshGnjKNMgp2l6oe+P9MyGaYjMVc1i9L62Zh96X5sBymTHkxRdXO/RaKeJpjFxRqOYDanf5McjPsnvRCyo2KgGK5vBoS1jfHjfHxlf1hSukExTRc0J9FInESATjLei3jVmmJ9iJ8PHRx1ENbuOslHTxYNaMn8Ept7X1tzaLCNv9fvacnAoaI6teTffHxkuwrXEYKXpfe2eN88DC0DhieaA2wXGaYXVgIq/ur+S2cWgafN/Lq+sfHruxIkd+2oFtWcjoX4q/MKSfqPB9Yh7/BaDX+pk15mGnoAuVxFdSIvZQqnTwQ5mjOpbI7VuzXdKxvVtneo7lDKcFr6Avz9SD0yYAaDWtYUzT4GYslrczrPLgPj3LH8+7vuM0UceGekmp7l2an8CMZ0P0x+JKH7y8sWLvz+OIAqfirLRcFWiAJQdmXZaKE1hSPsjLyEk/hEAnw53Gc/PCpDb7o/Mat/gYX2J79m9Op7w9VtdAVIzGykPZKR/z0bKRu/ZkJZqmLHxxPIT8LNcm4KkgtkMpDeP+R5EkZrRGkSfTD/eA0OZSEDig816F5aXbzwCgN9NFx73WH0VmJv6PZvNfH9knu97ambm9q+g8MMvaYw7grH92+aP5IGd58vhP9ts3vEvuw1EYSlGllPEq1evok8aBWZPnWHtX1hChjUOHDjgX1bqdHJGbUc/t1IHFH0LtL+qi2vEb33WNz7XWbZZVqxvgA5fx1UUz+Dy188LjNT8eCsHQ0VGJoOcDvt97aS1N7s/Eivg+8jQrzJHXtrKRo/itYbij0Q1dQHxSaZ2D7PPeteDqAdrZcOaTZ0ZTfmTpxraAKHhrCFb/nCa0hjOTpOiYUewjv2TArgs/IXtlLnAsP/322677fwoMmdYbdoyfyQGD6O4+zQLT/82aSAmRpbK5somvz+SCdJFTJqnYWf4/ZZhPfYRvm5F2WzUH8lcUix8Fo/1aUC0c2OE+zrUpm3aH4mv7EU2ETzO8uf3Jh1EPSHbkcTr/j0b7Ev0Sf69SdHG66VxgRtNE2lWDvblzKlzHLr8pFenYL6tc+UZbMxrTaAvAuB/3XrrrZfWe4NJKVeZ2bBWs+bva4uFzG4Wt3Mvzbg9gIqyYciu5Y+8hBw8gxwsV8DGrZPb0d4KkGhga15A00piB7v83E7tpdmOzm/lPSpAJn8kM5qX8BVeAk+tR+2FdSDgKSLl7I+8cOFCjoPi2smTJ3eVr3AdONx0EWltLYoWuNA6d91111WmeHuycDOwyh/Jn9fmN1N/r05EABAH12H2cNlDYGcR+H83Z8q9vSzjfQAAAABJRU5ErkJggg==) no-repeat;background-position:center;background-size:47px 63px;margin-top:164px;margin-right:82px}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_title[data-v-4a944260]{height:26px;font-family:PingFangSC-Medium;font-size:16px;color:#000;line-height:26px;font-weight:500;margin-bottom:30px}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show[data-v-4a944260]{width:503px;height:264px;background:#FAFAFA;padding:40px 0 0 50px;box-sizing:border-box}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show .voice_commands_IdentifyTheResults_show_title[data-v-4a944260]{height:22px;font-family:PingFangSC-Medium;font-size:16px;color:#000;font-weight:500;margin-bottom:30px}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show .oice_commands_IdentifyTheResults_show_time[data-v-4a944260],.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show .oice_commands_IdentifyTheResults_show_money[data-v-4a944260],.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show .oice_commands_IdentifyTheResults_show_origin[data-v-4a944260]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#666;font-weight:500;margin-bottom:12px}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show .oice_commands_IdentifyTheResults_show_destination[data-v-4a944260]{height:20px;font-family:PingFangSC-Medium;font-size:14px;color:#666;font-weight:500}.voice_commands .voice_commands_IdentifyTheResults .voice_commands_IdentifyTheResults_show_loading[data-v-4a944260]{width:503px;height:264px;background:#FAFAFA;padding:40px 0 0 50px;box-sizing:border-box;display:flex;justify-content:center;align-items:center}.voice_commands .end_recorder_img[data-v-4a944260]{width:50px;height:50px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAABU0lEQVRoge3ZPUoEQRCG4bcWfxDNDIzUW4jiegUTMfUICuaeQIz2BOZi4gEEg0XY0NBIcyMR/8DPYCdapnF2u53ugXqSnqAo6puZbgYGnHOuKUk9SXuSVnLPEkXSicauc83QS9RnvVo3EvWbWqog2XmQGJK2JJ1LWkvVcy5VoyldAH3gAzhL0TDXq7U0sUbzPVKa2iCSViUNJV22PdCsQk9kG9gBjiQttzjPzEJBeg1qWiNpX9KxpOAsuY7fxiQtAlfAPPAA3NbVZb/bDSwwDgEQ/LruQpBGPEhpPEhpPEhpPEhpPEiLvoDv6vo1VFT8R6OZfUo6ADaBu1BdKMhP4DoLM7v5qyYU5B4YAo9m9pZ0qn9SG8TMXoDdlmeJ0oXN3ogHifQ+sUbLdfyeAofAIFXDLEHMbASMUvb0PVKaVEGeq/UpUb88qr+6/c7/1XXOudb8AikhXZ/+ExptAAAAAElFTkSuQmCC) no-repeat;background-position:center;background-size:50px 50px}.voice_commands .end_recorder_img[data-v-4a944260]:hover{opacity:.9}.experience{width:100%;height:709px;background-size:100% 709px;background-position:initial}.experience .experience_wrapper{width:1200px;height:709px;margin:0 auto;padding:0;box-sizing:border-box}.experience .experience_wrapper .experience_title{height:42px;font-family:PingFangSC-Semibold;font-size:30px;color:#000;font-weight:600;line-height:42px;text-align:center;margin-bottom:10px}.experience .experience_wrapper .experience_describe{height:22px;font-family:PingFangSC-Regular;font-size:14px;color:#666;letter-spacing:0;text-align:center;line-height:22px;font-weight:400;margin-bottom:30px}.experience .experience_wrapper .experience_content{width:1200px;margin:0 auto;display:flex;justify-content:center}.experience .experience_wrapper .experience_content .experience_tabs{margin-top:15px}.experience .experience_wrapper .experience_content .experience_tabs>.ant-tabs-nav{margin-bottom:20px}.experience .experience_wrapper .experience_content .experience_tabs>.ant-tabs-nav:before{content:none}.experience .experience_wrapper .experience_content .experience_tabs>.ant-tabs-nav .ant-tabs-nav-wrap{justify-content:center}.experience .experience_wrapper .experience_content .experience_tabs>.ant-tabs-nav .ant-tabs-tab{font-size:20px}.experience .experience_wrapper .experience_content .experience_tabs>.ant-tabs-nav .ant-tabs-nav-list{margin-right:-32px;flex:none}.experience .experience_wrapper .experience_content .experience_tabs .ant-tabs-nav:before{position:absolute;right:0;left:0;border-bottom:1px solid #f6f7fe;content:\"\"}.experience:after{content:\"\";display:block;clear:both;visibility:hidden}.speech_header[data-v-e2003d16]{width:1200px;margin:0 auto;padding-top:50px;box-sizing:border-box}.speech_header[data-v-e2003d16]:after{content:\"\";display:block;clear:both;visibility:hidden}.speech_header .speech_header_title[data-v-e2003d16]{height:57px;font-family:PingFangSC-Medium;font-size:38px;color:#000;letter-spacing:0;line-height:57px;font-weight:500;margin-bottom:15px}.speech_header .speech_header_describe[data-v-e2003d16]{height:26px;font-family:PingFangSC-Regular;font-size:16px;color:#575757;line-height:26px;font-weight:400;margin-bottom:24px}.speech_header .speech_header_link_box[data-v-e2003d16]{height:40px;margin-bottom:40px;display:flex;align-items:center}.speech_header .speech_header_link[data-v-e2003d16]{display:block;background:#2932E1;width:120px;height:40px;line-height:40px;border-radius:20px;font-family:PingFangSC-Medium;font-size:14px;color:#fff;text-align:center;font-weight:500;margin-right:20px}.speech_header .speech_header_link[data-v-e2003d16]:hover{opacity:.9}.speech_header .speech_header_divider[data-v-e2003d16]{width:1200px;height:1px;background:#D1D1D1;margin-bottom:40px}.speech_header .speech_header_content_wrapper[data-v-e2003d16]{width:1200px;margin:0 auto 20px;display:flex;justify-content:space-between;flex-wrap:wrap}.speech_header .speech_header_content_wrapper .speech_header_module[data-v-e2003d16]{width:384px;background:#FFFFFF;border:1px solid #e0e0e0;box-shadow:4px 8px 12px #0000000d;border-radius:16px;padding:30px 34px 0;box-sizing:border-box;display:flex;margin-bottom:40px}.speech_header .speech_header_content_wrapper .speech_header_module .speech_header_background_img[data-v-e2003d16]{width:46px;height:46px;background-size:46px 46px;background-repeat:no-repeat;background-position:center;margin-right:20px}.speech_header .speech_header_content_wrapper .speech_header_module .speech_header_content[data-v-e2003d16]{padding-top:4px;margin-bottom:32px}.speech_header .speech_header_content_wrapper .speech_header_module .speech_header_content .speech_header_module_title[data-v-e2003d16]{height:26px;font-family:PingFangSC-Medium;font-size:20px;color:#000;letter-spacing:0;line-height:26px;font-weight:500;margin-bottom:10px}.speech_header .speech_header_content_wrapper .speech_header_module .speech_header_content .speech_header_module_introduce[data-v-e2003d16]{font-family:PingFangSC-Regular;font-size:16px;color:#666;letter-spacing:0;font-weight:400}.app{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAC0AAAAWKCAYAAABrA+TvAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAALQKADAAQAAAABAAAFigAAAABI7lAXAABAAElEQVR4AezdbW+c5RUE4HvXmxel0IKKxGvb//+rSgstX4AGQhJiO/vUTlRVAiKISNY+M5clhMCxnzPXOJt8mDi7J0+P2/JGgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRKBS4vt3U47GLS//jjtu7fz8lzfnHVz9lu7fcZFZ2fb2u7Wmrcu5fR0cXFWs+ebeudd1LybOvxk2394cFu3bkzP9P169v3j47r7p19REfXP3e++fb5ixeDD/58FvGi8PU3x7VdzbfefXcf8dr97X+O6+Lqdfve3d167735L9wPHx7X9a+r128ffni2dsNfFr77/riePDm+yPOnP+7XgwezO3r8eFsPv3v5mnD9NffBB7NfF54+Pa6vv33Zz3VJn358GP37n4urX4O++uplP9d53n9/v959Z/bX3Of/uLyO8uLt/tXv5T76aPbX3D+/uFiXz///wva3vxzW2ZBIf//8Ys3+avrfV5J/EyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQIWAAXVGzkAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQyBAygM3qUggABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECFgAF0Rc1CEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgQMIDO6FEKAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAhUCBtAVNQtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEPAADqjRykIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIVAgYQFfULCQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBDAED6IwepSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQIWAAXVGzkAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQyBAygM3qUggABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECFgAF0Rc1CEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgQMIDO6FEKAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAhUCBtAVNQtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEPAADqjRykIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIVAgYQFfULCQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBDAED6IwepSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQIWAAXVGzkAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQyBAygM3qUggABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECFgAF0Rc1CEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgQMIDO6FEKAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAhUCBtAVNQtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEPAADqjRykIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIVAgYQFfULCQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBDAED6IwepSBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQIWAAXVGzkAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQyBAygM3qUggABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECFwKEipZAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECPyiwHFba3f8xXfdyv9pAH0ra3EUAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdMIfPHl5Wke9Eaeslv7N/J5fBICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAicQMAA+gTIHkGAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwJsROLyZT+OzECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwQeDsbLe2bZtw6s9ufH5cywD6Zyz+BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFcgU8/mTsh/vdXl2ufW41kBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWMAAOrhc0QgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAikCRhApzUqDwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFgAQPo4HJFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAmYACd1qg8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIFDKCDyxWNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJqAAXRao/IQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBYwgA4uVzQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECaQIG0GmNykOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgWOAQnE00AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm9U4Nn5tr781+Ub/Zw+2W8XuLyiN4D+7V5+JAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQLnAtq11PcL1djMCV/xrfzOP9lQCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAi8voDvAP36Zj6CAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgSGB/dv19h73dBoHtuFsG0LehCTcQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjcWoG/fnbn1t7WdtjDh8e1bwstLwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECcwUMoOd253ICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQIG0HWVC0yAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAB9NzuXE6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTsAAuq5ygQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFTCAntudywkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUCRhA11UuMAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG5AgbQc7tzOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6AQPousoFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDBXwAB6bncuJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFAnYABdV7nABAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOYKGEDP7c7lBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoEDKDrKheYAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwFwBA+i53bmcAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ2AAXRd5QITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQmCtgAD23O5cTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqBMwgK6rXGACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECcwUMoOd253ICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQIG0HWVC0yAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAB9NzuXE6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTsAAuq5ygQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFTCAntudywkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUCRhA11UuMAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG5AgbQc7tzOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6AQPousoFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDBXwAB6bncuJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFAnYABdV7nABAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOYKGEDP7c7lBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoEDKDrKheYAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwFwBA+i53bmcAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ2AAXRd5QITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQmCtgAD23O5cTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqBMwgK6rXGACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECcwUMoOd253ICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQIG0HWVC0yAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAB9NzuXE6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTsAAuq5ygQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFTCAntudywkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUCRhA11UuMAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG5AgbQc7tzOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6AQPousoFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDBXwAB6bncuJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFAnYABdV7nABAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOYKGEDP7c7lBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoEDKDrKheYAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwFwBA+i53bmcAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ2AAXRd5QITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQmCtgAD23O5cTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqBMwgK6rXGACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECcwUMoOd253ICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQIG0HWVC0yAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAB9NzuXE6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTsAAuq5ygQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFTCAntudywkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUCRhA11UuMAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG5AgbQc7tzOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6AQPousoFJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDBXwAB6bncuJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFAnYABdV7nABAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOYKGEDP7c7lBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoEDKDrKheYAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwFwBA+i53bmcAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ2AAXRd5QITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQmCtgAD23O5cTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqBMwgK6rXGACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECcwUMoOd253ICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQIG0HWVC0yAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAB9NzuXE6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTsAAuq5ygQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFTCAntudywkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUCRhA11UuMAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG5AgbQc7tzOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6gUNdYoEJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgROJvDDo+N69uN2sud5ULbA+cW2DKCzO5aOAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIHCjAheXa11cGkDfaAlBD9+2be2D8ohCgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEC4gO8AHV6weAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBUwrs1m7tfYveU5JXPWvbdssAuqpyYQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECb1fgcLVO/exTE9W3q9z72c/Pt2Vf39u/5AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTGCRhAj6vMwQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6BQyge7uXnAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA4AQPocZU5mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECvgAF0b/eSEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgnYAA9rjIHEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgVMIDu7V5yAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuMEDKDHVeZgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAr0CBtC93UtOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYJyAAfS4yhxMgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoFfAALq3e8kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjBMwgB5XmYMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9AoYQPd2LzkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBcQIG0OMqczABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXgED6N7uJSdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwTsAAelxlDiZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQK2AA3du95AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTGCRhAj6vMwQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6BQyge7uXnAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA4AQPocZU5mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECvgAF0b/eSEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgnYAA9rjIHEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgVMIDu7V5yAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuMEDKDHVeZgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAr0CBtC93UtOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYJyAAfS4yhxMgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoFfAALq3e8kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjBMwgB5XmYMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9AoYQPd2LzkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBcQIG0OMqczABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXgED6N7uJSdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwTsAAelxlDiZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQK2AA3du95AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTGCRhAj6vMwQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6BQyge7uXnAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA4AQPocZU5mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECvgAF0b/eSEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgnYAA9rjIHEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgVMIDu7V5yAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuMEDKDHVeZgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAr0CBtC93UtOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYJyAAfS4yhxMgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoFfAALq3e8kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjBMwgB5XmYMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9AoYQPd2LzkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBcQIG0OMqczABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXgED6N7uJSdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwTsAAelxlDiZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQK2AA3du95AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTGCRhAj6vMwQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6BQyge7uXnAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA4AQPocZU5mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECvgAF0b/eSEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgnYAA9rjIHEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgVMIDu7V5yAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuMEDKDHVeZgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAr0CBtC93UtOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYJyAAfS4yhxMgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoFfAALq3e8kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjBMwgB5XmYMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9AoYQPd2LzkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBcQIG0OMqczABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBXgED6N7uJSdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwTsAAelxlDiZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQK2AA3du95AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTGCRhAj6vMwQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6BQyge7uXnAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA4AQPocZU5mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECvgAF0b/eSEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgncDgex93sYAIECBAgQIAAAQIETihwPG7rcNid8IkeRYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBB4tcBh73tAv1rHewgQIECAAAECBAgQWNtm/OzLgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIELg9AubPt6cLlxAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg8CsCh195v3cTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAicUODRD8e185f1nlDcoyYJPH++LQPoSY25lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgX+P7RMT6jgAR+j8D+93ywjyVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMApBXwH6FNqexYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBA4CcCu91aZ76l7U9U/CeBVwsYQL/axnsIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm9d4P79/frkYwvotw7tATECfrbEVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAinP/GgAAQABJREFUAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjIABdEyVghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIFzCAzu9YQgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIxAgbQMVUKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfwAA6v2MJCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMQIGEDHVCkIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwBA+j8jiUkQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECNgAB1TpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8gUMoPM7lpAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAjMBh22KyCEKAAAECBAgQIEDg1gjsdrfmFIcQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBKIEDpeXFtBRjQpDgAABAgQIECBw4wLXf8jw7l0L6BsvwgEECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBApMDhzh3DjMhmhSJAgAABAgQIELgxgfNzf8jwxvA9mAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgX2McnFJAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRiBQ0wSQQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6gePVX9L77Jm/qbeueIGrBQygq+sXngABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIzBa4uNjW1988nx3C9QQIvJbA/rV+tB9MgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBGxTwHaBvEN+jCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdcX2O22td+9/sf5CAIEMgQMoDN6lIIAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECNQIPHiwX9f/eCNAoFPAz/7O3qUmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMFLAAHpkbY4mQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0ClgAN3Zu9QECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERgoYQI+szdEECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEOgUMoDt7l5oAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDASAED6JG1OZoAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAp4ABdGfvUhMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYKWAAPbI2RxMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDoFDCA7uxdagIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIjBQygR9bmaAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKdAgbQnb1LTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGCkgAH0yNocTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBTwAC6s3epCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwUMIAeWdt/2bubJimOKwqg1T01goU/8P//i9pYDtsgZro9hLcpyW6SnJf3HSLkRSGq3j3XIW0uyNEECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEegoYQPfsXWoCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECWwoYQG9Zm6MJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9BQwgO7Zu9QECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEthQwgN6yNkcTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6ClgAN2zd6kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIbClgAL1lbY4mQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0FPAALpn71ITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ2FLAAHrL2hxNgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoKeAAXTP3qUmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgsKWAAfSWtTmaAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQE8BA+ievUtNgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYEsBA+gta3M0AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZ4CBtA9e5eaAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwJYCBtBb1uZoAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAj0FDKB79i41AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgS0FDKC3rM3RBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBHoKGED37F1qAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlsKGEBvWZujCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECPQUMIDu2bvUBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBLYUMIDesjZHEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgpYADds3epCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECGwpYAC9ZW2OJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBTwAC6Z+9SEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIENhSwAB6y9ocTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCngAF0z96lJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQILClgAH0lrU5mgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBPAQPonr1LTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGBLAQPoLWtzNAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGeAgbQPXuXmgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMCWAgbQW9bmaAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQI9BQyge/YuNQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEtBQygt6zN0QQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6ChhA9+xdagIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJbChhAb1mbowkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAj0FDCA7tm71AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgS2FDCA3rI2RxMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDoKWAA3bN3qQkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhsKWAAvWVtjiZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQU8AAumfvUhMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDYUsAAesvaHE2AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgp4ABdM/epSZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCwpYAB9Ja1OZoAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBATwED6J69S02AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgSwED6C1rczQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBngIG0D17l5oAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDAlgIG0FvW5mgCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECPQUMoHv2LjUBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBLQUMoLeszdEECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEegoYQPfsXWoCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECWwoYQG9Zm6MJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9BQwgO7Zu9QECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEthQwgN6yNkcTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6ClgAN2zd6kJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIbClgAL1lbY4mQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0FPgvN/vPZNLTYAAAQIECBAgUEbgcrmUucUhBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECtQXOl5faB7qOAAECBAgQIECggcDlfjyfRtANmhaRAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIPDdAufzs6HJdyt6AQECBAgQIECAwMMCt9txvN78V0keBvQLCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLNBK7N8opLgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMDGAufGtzudAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ+D8F7m//kd5vf/lBgACBXQUMoHdtzt0ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQOABgV/+cTu+/eUHAQIEdhW47nq4uwkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6CfgT4Du17nEBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBM4Pr2x6VeL81Ci0uAQKyAAXRstYIRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIH/Cvz5T9fj219+ECBAIEHAP80SWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBAygE1qUgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEATAQPoJkWLSYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBBwAA6oUUZCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDQRMIBuUrSYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBIEDKATWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBAygE1qUgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEATAQPoJkWLSYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBBwAA6oUUZCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDQRMIBuUrSYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBIEDKATWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBAygE1qUgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEATAQPoJkWLSYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBBwAA6oUUZCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDQRMIBuUrSYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBIEDKATWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBAygE1qUgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEATAQPoJkWLSYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBBwAA6oUUZCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDQRMIBuUrSYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBIEDKATWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBAygE1qUgQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEATAQPoJkWLSYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBBwAA6oUUZCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDQRMIBuUrSYBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBIEDKATWpSBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBMBA+gmRYtJgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIEHAADqhRRkIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINBEwgG5StJgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEEgQMoBNalIEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEwED6CZFi0mAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgQcAAOqFFGQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0ETCAblK0mAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQSBM77PSGGDAQIECBAgACBbgL343K5dAstLwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHj/PzFAtr/DwgQIECAAAECuwmcT8fx/Lzb1e4lQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg8P0C58cP/uTA72f0BgIECBAgQIDAOoGvX/0GtnXavkSAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFBN4PRfTq9WiXsIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPgtgetv/YTnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqCZwVjvIPQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoJLAzz+/HpfLpdJJbiFAgEBrAQPo1vULT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJ/JPD6+u3vuP/R3+bnCRAgQGCRgAH0ImifIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIF9BC7X47g+7XOvSwkQINBJwAC6U9uyEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMD/JPDXv7wtoP0gQIAAgZIC/gldshZHESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwEjCAHql4RoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBASQED6JK1OIoAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZGAAfRIxTMCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBEoKGECXrMVRBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiMBAygRyqeESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQUsAAumQtjiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYCRgAD1S8YwAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZICBtAla3EUAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIjAQPokYpnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUFDCALlmLowgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGAkYQI9UPCNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoKSAAXTJWhxFgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMBIwAB6pOIZAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIlBQygS9biKAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERgIG0CMVzwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKClgAF2yFkcRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDASMIAeqXhGgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBJAQPokrU4igABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBkYAB9EjFMwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIESgoYQJesxVEECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwEDKBHKp4RIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFBSwAC6ZC2OIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgJGAAPVLxjAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBkgIG0CVrcRQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAiMBA+iRimcECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQUMIAuWYujCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYCRhAj1Q8I0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgpIABdMlaHEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwEjAAHqk4hkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAiUFDKBL1uIoAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRGAgbQIxXPCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoKWAAXbIWRxEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMBIwgB6peEaAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEkBA+iStTiKAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGRgAH0SMUzAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRKChhAl6zFUQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjAQMoEcqnhEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUFLAALpkLY4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGAkYAA9UvGMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGSAgbQJWtxFAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECIwED6JGKZwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIlBQwgC5Zi6MIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgJGECPVDwjQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCkgAF0yVocRYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDASMAAeqTiGQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECJQUMoEvW4igCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBEYCBtAjFc8IECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECgpYABdshZHESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwEjCAHql4RoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBASQED6JK1OIoAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZGAAfRIxTMCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBEoKGECXrMVRBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiMBAygRyqeESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQUsAAumQtjiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYCRgAD1S8YwAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZICBtAla3EUAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIjAQPokYpnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUFDCALlmLowgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGAkYQI9UPCNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoKSAAXTJWhxFgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMBIwAB6pOIZAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIlBQygS9biKAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERgIG0CMVzwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKClgAF2yFkcRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDASMIAeqXhGgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBJAQPokrU4igABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBkYAB9EjFMwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIESgqct9u95GGOIkCAAAECBAjMFLheLzNf510ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECLyTwPnvzwbQ72TvswQIECBAgMBCgZ9+uhzP58IP+hQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAj9E4Pz44fpDXuylBAgQIECAAIEKAvf7/fjyq9/wVaELNxAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCYIXA+Pc14jXcQIECAAAECBKoKXAygq1bjLgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIPCPjjnx9A80sIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEHgfgfN9PuurBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAo8PJyP/7+yy0xmkwECBAgUETAALpIEc4gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAgsDr2/b59fM9IYoMBAgQIFBUwAC6aDHOIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwE4C18txXK87XexWAgQIENhVwAB61+bcTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgUICnz5ZPxeqwykECBCIFvBvnOh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgHJSaigAAEAASURBVAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWMICOrlc4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAlkCBtBZfUpDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIFrAADq6XuEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZAkYQGf1KQ0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaAED6Oh6hSNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQJWAAndWnNAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSiBQygo+sVjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECWgAF0Vp/SECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEIgWOG+36HzCESBAgAABAg8KXP02qQfl/DICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBH6kwPnPf1lA/0hg7yZAgAABArsKfPx4OZ7Py67nu5sAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgVCB86dnw6bQbsUiQIAAAQIPCdzux/Hy8vY/fhAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCgwPnhgwF0wV6cRIAAAQIE3k3g69v4+eXl3T7vwwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPhdgevv/qyfJECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQCGBs9AtTiFAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEA7gV+/3o/b/d4ut8AECBAgQOBRAQPoR+X8OgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECEwQ+PL5fnyZ8B6vIECAAAECXQQMoLs0LScBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAqUEnp6O43YpdZJjCBAgQIDAFgIG0FvU5EgCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBNIE/vbpmhZJHgIECBAgsETAv0GXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIzBAygZyh6BwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECSwQMoJcw+wgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAjMEDKBnKHoHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJLBAyglzD7CAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMwQMoGcoegcBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAksEDKCXMPsIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL/Ye8Om+MoriiAzuyOoGJjy/z//xhsnFjC0mqyiYHKBxrQzqr17vRRFSTV1uzcPu9VKh+upWsIKEBfQ9FnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQRUABuguzlxAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgcA0BBehrKPoMAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgS6CChAd2H2EgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEriGgAH0NRZ9BgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAXAQXoLsxeQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDANQQUoK+h6DMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEOgisJxOa5cXeQkBAgQIENi7wPE47/2K7keAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIFXF1j+9W8F6FefggAECBAgsAuBH97O0/G4i6u4BAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMoKLDeLn1ZZdjqCESBAgECEwOP5tyms/j5RxKyEJECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgX2B580YBOn+MbkCAAAECrynw5cs6PTy+ZgLvJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgCh3Gu6qYECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECKQLLOkXkJ8AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgbEEvv2W3nWsS7stAQIECBAg8LuAAvTvFP4LAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIJAp8+nRJiykiAAAECBAi8kIAC9AvB+lgCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBK4rcDxe9/N8GgECBAgQIJApoACdOTepCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAwlMM/T9OMHDeihhu6yBAgQIECgIXBonDsmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAOQEF6HIjEYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZaAAnRLxjkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuUEFKDLjUQgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaAgrQLRnnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUE1CALjcSgQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaAkoQLdknBMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUE5AAbrcSAQiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAloADdknFOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEA5AQXociMRiAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBloACdEvGOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC5QQUoMuNRCACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFoCCtAtGecECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQTUIAuNxKBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBoCShAt2ScEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQTkAButxIBCJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoCWgAN2ScU6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQDkBBehyIxGIAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGWgAJ0S8Y5AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLlBBSgy41EIAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEWgIK0C0Z5wQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIlBNQgC43EoEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGgJKEC3ZJwTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFBOQAG63EgEIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgJaAA3ZJxToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAOQEF6HIjEYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZaAAnRLxjkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuUEFKDLjUQgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaAgrQLRnnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUE1CALjcSgQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaAkoQLdknBMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUE5AAbrcSAQiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAloADdknFOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEA5AQXociMRiAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBloACdEvGOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC5QQUoMuNRCACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFoCCtAtGecECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQTUIAuNxKBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBoCShAt2ScEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQTkAButxIBCJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoCWgAN2ScU6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQDkBBehyIxGIAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGWgAJ0S8Y5AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLlBBSgy41EIAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEWgIK0C0Z5wQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIlBNQgC43EoEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGgJKEC3ZJwTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFBOQAG63EgEIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgJaAA3ZJxToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAOQEF6HIjEYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZaAAnRLxjkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAuUEFKDLjUQgAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaAgrQLRnnBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUE1CALjcSgQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaAkoQLdknBMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUE5AAbrcSAQiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAloADdknFOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEA5AQXociMRiAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBloACdEvGOQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC5QQUoMuNRCACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFoCCtAtGecECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQTUIAuNxKBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBoCShAt2ScEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQTkAButxIBCJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoCWgAN2ScU6AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQDkBBehyIxGIAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGWgAJ0S8Y5AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLlBBSgy41EIAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEWgLL6dT6I+cECBAgQOBlBY7Hl/18n06AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC+xNYPn9+2t+t3IgAAQIEIgRubw/TPEdEFZIAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEiggsh0ORJGIQIECAwDACT/7uzTCzdlECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhcW2B5/14D+tqoPo8AAQIE/lzg40cN6D8X8qcECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0BLQfm7JOCdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoJyAAnS5kQhEgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBLYGn9gXMCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBPIFvj48Tf/8Kf8ebkCAAAECBAgQ+E1AAfo3Cf9JgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYEcC8zxPx8O8oxu5CgECBAgQIEDgm4ACtE0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgsEOB43Gabm8PO7yZKxEgQIAAAQKjC/h/OKNvgPsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBJQgA4alqgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERhdQgB59A9yfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJCAAnTQsEQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLqAAvToG+D+BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIEFKCDhiUqAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdEFFKBH3wD3J0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAkoAAdNCxRCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwuoAA9+ga4PwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEgAQXooGGJSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGB0AQXo0TfA/QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgECShABw1LVAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKjCyhAj74B7k+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgSEABOmhYohIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYXUABevQNcH8CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECQQIK0EHDEpUAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDA6AIK0KNvgPsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBJQgA4alqgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERhdQgB59A9yfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJCAAnTQsEQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLqAAvToG+D+BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIEFKCDhiUqAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdEFFKBH3wD3J0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAkoAAdNCxRCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwuoAA9+ga4PwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEgAQXooGGJSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGB0AQXo0TfA/QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgECShABw1LVAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKjCyhAj74B7k+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgSEABOmhYohIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYXUABevQNcH8CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECQQIK0EHDEpUAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDA6AIK0KNvgPsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBJQgA4alqgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERhdQgB59A9yfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJCAAnTQsEQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLqAAvToG+D+BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIEFKCDhiUqAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdEFFKBH3wD3J0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAkoAAdNCxRCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwuoAA9+ga4PwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEgAQXooGGJSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGB0AQXo0TfA/QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgECShABw1LVAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKjCyhAj74B7k+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgSEABOmhYohIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYXUABevQNcH8CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECQQIK0EHDEpUAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDA6AIK0KNvgPsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBJQgA4alqgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERhdQgB59A9yfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJCAAnTQsEQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLqAAvToG+D+BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIIEFKCDhiUqAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgdEFFKBH3wD3J0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAkoAAdNCxRCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIwuoAA9+ga4PwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEgAQXooGGJSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGB0AQXo0TfA/QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgECShABw1LVAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKjCyhAj74B7k+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgSEABOmhYohIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAYXUABevQNcH8CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECQQIK0EHDEpUAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDA6AIK0KNvgPsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCBJQgA4alqgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIERhdQgB59A9yfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJCAAnTQsEQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLrAcjqNTuD+BAgQyBE4HnOySkqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBF5CYPn589NLfK7PJECAAIErC8znz/vwwQ/uvzKrjyNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMAFNurCBiUuAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgZIHl9r0O9MgL4O4ECNQX+Pp1ne7u1/pBJSRAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAh0EloP+cwdmryBAgMDlAv53+nI7TxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDA/gTUn/c3UzciQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgsFuBZbc3czECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECFwjc3a/T/S/rBU96hAABAgQIECBAoIeAAnQPZe8gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCoLzBP0+HX36e+6j/Xn5eEBAgQIECAwLACCtDDjt7FCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE/l/gZpmnm3fnFrQvAgQIECBAgACB0gK//p210hmFI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwP8EFKAtAgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBiNuxVAABAAElEQVQgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIyAAnTMqAQlQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEAB2g4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAjoAAdMypBCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBQgLYDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjECChAx4xKUAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEFKDtAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECMQIK0DGjEpQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQVoO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQIzA8vi4xoQVlAABAs8RmOd5Oh6f84TvJUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBKoLLJ9+VoCuPiT5CBC4TGA5rtPtrR90f5mepwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQE0BzcCac5GKAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE/EFje/TD/wbEjAgQI5Arc3a3T4yk3v+QECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAW2D57jsF6DaPPyFAIFHg/pd1mhSgE0cnMwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ+EuBw19+h28gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAEYGlSA4xCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEQgXu78+/qdcXAQIECBAgQIAAgU4CCtCdoL2GAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQILA7gXmaDuffP/70tLubuRABAgQIECBAgEBhAQXowsMRjQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQWeDm3Dy5Wc4taF8ECBAgQIAAAQIEOgqc/w6eLwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECGQIKEBnzElKAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTOAgrQ1oAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtB0gQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBGQAE6ZlSCEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAG0HCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCIEVCAjhmVoAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKEDbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEYgQUoGNGJSgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQdoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgRgBBeiYUQlKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMDy+AiBAAEC3wTmeZ2OxxkHAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCswPLTx1PZcIIRINBX4Pvv5+n9OwXovureRoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDxH4PCcb/a9BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQeE2B5c0//LTX1xyAdxN4fYF5+nL39PoxJCBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI/A2B5e1bPwT6bzj5FgK7FVjX6VyA3u31XIwAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDYmYD2884G6joECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE9iyw7Ply7kaAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqCbwdP5NvQ+P53/5IkCAAAECBAgQIEDgIgEF6IvYPESAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQeL7APE/Tuq7Tw8Pzn/UEAQIECBAgQIAAAQLfBBSgbQIBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoJPAzc08/fcfXwQIECBAgAABAgQIXC5wuPxRTxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCvgAJ0X29vI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgg4AC9AY8jxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0FdAAbqvt7cRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQILBBQAF6A55HCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDoK6AA3dfb2wgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ2CCgAL0Bz6MECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECPQVUIDu6+1tBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhsEFCA3oDnUQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE+gooQPf19jYCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBDYIKEBvwPMoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJ9BRSg+3p7GwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECGwQUoDfgeZQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgb4CCtB9vb2NAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIENAgrQG/A8SoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAXwEF6L7e3kaAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwAYBBegNeB4lQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCvgAJ0X29vI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgg4AC9AY8jxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0FdAAbqvt7cRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQILBBQAF6A55HCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDoK6AA3dfb2wgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ2CCgAL0Bz6MECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECPQVUIDu6+1tBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhsEFCA3oDnUQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE+gooQPf19jYCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBDYIKEBvwPMoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJ9BRSg+3p7GwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECGwQUoDfgeZQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgb4CCtB9vb2NAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIENAgrQG/A8SoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg8J/27q7HimqLAmjV6QID0agJ+v9/oKCJDyJ0n2Pz5AfEtO6PrjX3MDEBLrVqrTHrcdqXAAECBAgQIECAAIG5AgrQc729jQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBBgEF6AY8jxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMFdAAXqut7cRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINAgoADdgOdRAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTmCihAz/X2NgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEGgQUoBvwPEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwFwBBei53t5GgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECDgAJ0A55HCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCYK6AAPdfb2wgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaBBQgG7A8ygBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAnMFFKDnensbAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQINAgrQDXgeJUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgroAC9FxvbyNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoEFAAboBz6MECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECMwVUICe6+1tBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAg0CChAN+B5lAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBuQIK0HO9vY0AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgQYBBegGPI8SIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDBXQAF6rre3ESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQIKAA3YDnUQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE5gooQM/19jYCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBBoEFKAb8DxKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMBcAQXoud7eRoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAg4ACdAOeRwkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQmCugAD3X29sIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGgQUIBuwPMoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJzBRSg53p7GwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECDQIK0A14HiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYK6AAvRcb28jQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBBQAG6Ac+jBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjMFVCAnuvtbQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQINAgoQDfgeZQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgbkCCtBzvb2NAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEGAQXoBjyPEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwV0ABeq63txEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0CCgAN2A51ECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOYKKEDP9fY2AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQaBI77h4anPUpgcYHLvm0X/xnB4l+B8wkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGZAse7dxrQM8G9K0vg9at9+/prDeisVF1DgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQInFlAc/PM6diNAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIG/CRwvX+x/+wO/IUDg3wUerrftwQ9O/3ck/ysBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYJDA8d13fgj0IFtjQwV+e3/bfv31GnqdswgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC5xbQfj53PrYjQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQOAvAsdffu2XBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHTCVyvt23f99PtZSECBAgQIECAAAECBJ5HQAH6edy9lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEHiCwKfe8/X66d/bE/62v0KAAAECBAgQIECAwAoCCtArpOxGAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQVODF4Sc/F43O2gQIECBAgAABAgSGCVyGTTaYAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiME1CAHmdrMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnQUUoDuDGkeAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwDgBBehxtiYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINBZQAG6M6hxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiMEzg+3t/GTTeZwD8E7i77dlG7/4eK3xIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDxV4Hj37vrUv+vvEWgW+Oaby/b61d48xwACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE1Bfws3jVzdzUBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBkgLH7ofxlgyu0tK3B6aQZwAAMfdJREFUW6Vt7UqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIHBmgePHH+7OvJ/dAgR+/uW6ffigBR0QpRMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAs8ucHn2DSxAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBJwooQD8Ryl8jQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQOD5BY7nX8EGBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQC+By+OPQnv//tprnDkECBAgQIAAAQIECBA4nYAC9OkisRABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPj/Ai9f7o8Pf/rXPwQIECBAgAABAgQIEMgUePzvPv1DgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBGgIK0DVysiUBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAo8CCtA+AwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEyggoQJeJyqIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECChA+wYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECgjoABdJiqLEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAO0bIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgjIACdJmoLEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgAK0b4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTICCtBlorIoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIK0L4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTKCChAl4nKogQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKED7BggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKCOgAF0mKosSIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIKAA7RsgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCMgAJ0magsSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQICAArRvgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMgIK0GWisigBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQvgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMoIKECXicqiBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgoQPsGCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoI6AAXSYqixIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgoADtGyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoIyAAnSZqCxKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtG+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEyAgrQZaKyKAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECCtC+AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEyggoQJeJyqIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECChA+wYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECgjoABdJiqLEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAO0bIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgjIACdJmoLEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgAK0b4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTICCtBlorIoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIK0L4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTKCChAl4nKogQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKED7BggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKCOgAF0mKosSIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIKAA7RsgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCMgAJ0magsSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQICAArRvgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMgIK0GWisigBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQvgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMoIKECXicqiBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgoQPsGCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoI6AAXSYqixIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgoADtGyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoIyAAnSZqCxKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIACtG+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEyAgrQZaKyKAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECCtC+AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEyggoQJeJyqIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECChA+wYIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECgjoABdJiqLEiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCgAO0bIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgjIACdJmoLEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgAK0b4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTICCtBlorIoAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIK0L4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTKCChAl4nKogQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIKED7BggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKCOgAF0mKosSIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIKAA7RsgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKCMgAJ0magsSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQICAArRvgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMgIK0GWisigBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgrQvgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMoIKECXicqiBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgcH+8hnFnguNu2fT/zhnYjQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgME/gePvTw7y3edN/Fvj++8v21Vca0P8ZzgMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKRApfIqxxFgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECkgAJ0ZKyOIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJApcLx5owN9pmhvt217+/Z6ppXsQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQOA0Asdx7KdZxiLbdr0+NqD9Q4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDAFwX8+OcvsvhDAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTOKHCccSk7ESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBaQL7vt3f+3/rnebtRQQIECBAgAABAgQIEGgUUIBuBPQ4AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECNQWOO4+7b/XPsL2BAgQIECAAAECBAgQWEjgstCtTiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoLiAAnTxAK1PgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYCUBBeiV0nYrAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgeICCtDFA7Q+AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZUEFKBXStutBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIoLKEAXD9D6BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFYSUIBeKW23EiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECguoABdPEDrEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEFhJQAF6pbTdSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKC4gAJ08QCtT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGAlAQXoldJ2KwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHiAgrQxQO0PgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGVBBSgV0rbrQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSKCyhAFw/Q+gQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRWElCAXilttxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoLqAAXTxA6xMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBYSUABeqW03UqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECguIACdPEArU+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgJQEF6JXSdisBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB4gIK0MUDtD4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBlQQUoFdK260ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEigsoQBcP0PoECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEVhJQgF4pbbcSIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKC6gAF08QOsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQWElAAXqltN1KgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoLiAAnTxAK1PgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYCUBBeiV0nYrAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgeICCtDFA7Q+AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZUEFKBXStutBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIoLKEAXD9D6BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFYSUIBeKW23EiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECguoABdPEDrEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEFhJQAF6pbTdSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKC4gAJ08QCtT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGAlAQXoldJ2KwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHiAgrQxQO0PgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGVBBSgV0rbrQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSKCyhAFw/Q+gQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRWElCAXilttxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoLqAAXTxA6xMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBYSUABeqW03UqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECguIACdPEArU+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgJQEF6JXSdisBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB4gIK0MUDtD4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBlQQUoFdK260ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEigsoQBcP0PoECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEVhJQgF4pbbcSIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKC6gAF08QOsTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQWElAAXqltN1KgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoLiAAnTxAK1PgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYCUBBeiV0nYrAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgeICCtDFA7Q+AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZUEFKBXStutBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIoLKEAXD9D6BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFYSUIBeKW23EiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECguoABdPEDrEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEFhJQAF6pbTdSoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKC4gAJ08QCtT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGAlAQXoldJ2KwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHiAgrQxQO0PgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGVBBSgV0rbrQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSKCyhAFw/Q+gQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRWElCAXilttxIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoLqAAXTxA6xMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBYSUABeqW03UqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECguIACdPEArU+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgJQEF6JXSdisBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB4gIK0MUDtD4BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBlQSOjx9vUfe+eLFH3eMYAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgT+FDh+evvw5+8CfvXDm7vtOJSgA6J0AgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHPBC6f/Yk/IECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwEkFFKBPGoy1CBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBD4XOD49tvaHegPv2/bb++vn1/mTwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQiBM4Xr+qXYDebrfHAnRcLg4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQOALAsXbz1+4yB8RIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5AkoQOdl6iICBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECsQIK0LHROowAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAnoACdF6mLiJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQK6AAHRutwwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjkCShA52XqIgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKxAgrQsdE6jAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECegAJ0XqYuIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBAroAAdG63DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQJKEDnZeoiAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABArECCtCx0TqMAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ6AAnRepi4iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgECugAB0brcMIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5An8Ad8CyURGq4jVAAAAAElFTkSuQmCC) no-repeat};{}\n\n</style>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    \n  </body>\n</html>\n"
  },
  {
    "path": "demos/streaming_asr_server/web/readme.md",
    "content": "# paddlespeech serving 网页Demo\n\n![图片](./paddle_web_demo.png)\n\nstep1: 开启流式语音识别服务器端\n\n```\n# 开启流式语音识别服务\ncd PaddleSpeech/demos/streaming_asr_server\npaddlespeech_server start --config_file conf/ws_conformer_wenetspeech_application_faster.yaml\n```\n\nstep2: 谷歌游览器打开 `web`目录下`index.html`\n\nstep3: 点击`连接`，验证WebSocket是否成功连接\n\nstep4：点击开始录音(弹窗询问，允许录音)\n\n\n \n"
  },
  {
    "path": "demos/streaming_tts_server/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Streaming Speech Synthesis Service\n\n## Introduction\nThis demo is an implementation of starting the streaming speech synthesis service and accessing the service. It can be achieved with a single command using `paddlespeech_server` and `paddlespeech_client` or a few lines of code in python.\n\nFor service interface definition, please check:\n- [PaddleSpeech Server RESTful API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-RESTful-API)\n- [PaddleSpeech Streaming Server WebSocket API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-WebSocket-API)\n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nIt is recommended to use **paddlepaddle 2.4rc** or above.\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n**If you install in easy mode, you need to prepare the yaml file by yourself, you can refer to the yaml file in the conf directory.**\n\n### 2. Prepare config File\nThe configuration file can be found in `conf/tts_online_application.yaml`.\n- `protocol` indicates the network protocol used by the streaming TTS service. Currently, both **http and websocket** are supported.\n- `engine_list` indicates the speech engine that will be included in the service to be started, in the format of `<speech task>_<engine type>`.\n    - This demo mainly introduces the streaming speech synthesis service, so the speech task should be set to `tts`.\n    - the engine type supports two forms: **online**  and **online-onnx**. `online` indicates an engine that uses python for dynamic graph inference; `online-onnx` indicates an engine that uses onnxruntime for inference. The inference speed of online-onnx is faster.\n- Streaming TTS engine AM model support: **fastspeech2 and fastspeech2_cnndecoder**; Voc model support: **hifigan and mb_melgan**\n- In streaming am inference, one chunk of data is inferred at a time to achieve a streaming effect. Among them, `am_block` indicates the number of valid frames in the chunk, and `am_pad` indicates the number of frames added before and after am_block in a chunk. The existence of am_pad is used to eliminate errors caused by streaming inference and avoid the influence of streaming inference on the quality of synthesized audio.\n    - fastspeech2 does not support streaming am inference, so am_pad and am_block have no effect on it.\n    - fastspeech2_cnndecoder supports streaming inference. When am_pad=12, streaming inference synthesized audio is consistent with non-streaming synthesized audio.\n- In streaming voc inference, one chunk of data is inferred at a time to achieve a streaming effect. Where `voc_block` indicates the number of valid frames in the chunk, and `voc_pad` indicates the number of frames added before and after the voc_block in a chunk. The existence of voc_pad is used to eliminate errors caused by streaming inference and avoid the influence of streaming inference on the quality of synthesized audio.\n    - Both hifigan and mb_melgan support streaming voc inference.\n    - When the voc model is mb_melgan, when voc_pad=14, the synthetic audio for streaming inference is consistent with the non-streaming synthetic audio; the minimum voc_pad can be set to 7, and the synthetic audio has no abnormal hearing. If the voc_pad is less than 7, the synthetic audio sounds abnormal.\n    - When the voc model is hifigan, when voc_pad=19, the streaming inference synthetic audio is consistent with the non-streaming synthetic audio; when voc_pad=14, the synthetic audio has no abnormal hearing.\n    - Pad calculation method of streaming vocoder in PaddleSpeech: [AIStudio tutorial](https://aistudio.baidu.com/aistudio/projectdetail/4151335)\n- Inference speed: mb_melgan > hifigan; Audio quality: mb_melgan < hifigan\n- **Note:** If the service can be started normally in the container, but the client access IP is unreachable, you can try to replace the `host` address in the configuration file with the local IP address.\n\n### 3. Streaming speech synthesis server and client using http protocol\n#### 3.1 Server Usage\n- Command Line (Recommended)\n\n  Start the service (the configuration file uses http by default):\n  ```bash\n  paddlespeech_server start --config_file ./conf/tts_online_application.yaml\n  ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  Arguments:\n  - `config_file`: yaml file of the app, default: ./conf/tts_online_application.yaml\n  - `log_file`: log file. Default: ./log/paddlespeech.log\n\n  Output:\n  ```text\n  [2022-04-24 20:05:27,887] [    INFO] - The first response time of the 0 warm up: 1.0123658180236816 s\n  [2022-04-24 20:05:28,038] [    INFO] - The first response time of the 1 warm up: 0.15108466148376465 s\n  [2022-04-24 20:05:28,191] [    INFO] - The first response time of the 2 warm up: 0.15317344665527344 s\n  [2022-04-24 20:05:28,192] [    INFO] - **********************************************************************\n  INFO:     Started server process [14638]\n  [2022-04-24 20:05:28] [INFO] [server.py:75] Started server process [14638]\n  INFO:     Waiting for application startup.\n  [2022-04-24 20:05:28] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-24 20:05:28] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-24 20:05:28] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/tts_online_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  Output:\n  ```text\n  [2022-04-24 21:00:16,934] [    INFO] - The first response time of the 0 warm up: 1.268730878829956 s\n  [2022-04-24 21:00:17,046] [    INFO] - The first response time of the 1 warm up: 0.11168622970581055 s\n  [2022-04-24 21:00:17,151] [    INFO] - The first response time of the 2 warm up: 0.10413002967834473 s\n  [2022-04-24 21:00:17,151] [    INFO] - **********************************************************************\n  INFO:     Started server process [320]\n  [2022-04-24 21:00:17] [INFO] [server.py:75] Started server process [320]\n  INFO:     Waiting for application startup.\n  [2022-04-24 21:00:17] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-24 21:00:17] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-24 21:00:17] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n#### 3.2 Streaming TTS client Usage\n- Command Line (Recommended)\n\n    Access http streaming TTS service:\n\n    If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n    ```bash\n    paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n    ```\n\n    Usage:\n  \n    ```bash\n    paddlespeech_client tts_online --help\n    ```\n\n    Arguments:\n    - `server_ip`: erver ip. Default: 127.0.0.1\n    - `port`: server port. Default: 8092\n    - `protocol`: Service protocol, choices: [http, websocket], default: http.\n    - `input`: (required): Input text to generate.\n    - `spk_id`: Speaker id for multi-speaker text to speech. Default: 0\n    - `output`: Client output wave filepath. Default: None, which means not to save the audio to the local.\n    - `play`: Whether to play audio, play while synthesizing, default value: False, which means not playing. **Playing audio needs to rely on the pyaudio library**.\n    - Currently, only the single-speaker model is supported in the code, so `spk_id` does not take effect. Streaming TTS does not support changing sample rate, variable speed and volume.\n    \n    Output:\n    ```text\n    [2022-04-24 21:08:18,559] [    INFO] - tts http client start\n    [2022-04-24 21:08:21,702] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n    [2022-04-24 21:08:21,703] [    INFO] - 首包响应：0.18863153457641602 s\n    [2022-04-24 21:08:21,704] [    INFO] - 尾包响应：3.1427218914031982 s\n    [2022-04-24 21:08:21,704] [    INFO] - 音频时长：3.825 s\n    [2022-04-24 21:08:21,704] [    INFO] - RTF: 0.8216266382753459\n    [2022-04-24 21:08:21,739] [    INFO] - 音频保存至：output.wav\n\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSOnlineClientExecutor\n  import json\n\n  executor = TTSOnlineClientExecutor()\n  executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8092,\n      protocol=\"http\",\n      spk_id=0,\n      output=\"./output.wav\",\n      play=False)\n\n  ```\n\n  Output:\n  ```text\n  [2022-04-24 21:11:13,798] [    INFO] - tts http client start\n  [2022-04-24 21:11:16,800] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n  [2022-04-24 21:11:16,801] [    INFO] - 首包响应：0.18234872817993164 s\n  [2022-04-24 21:11:16,801] [    INFO] - 尾包响应：3.0013909339904785 s\n  [2022-04-24 21:11:16,802] [    INFO] - 音频时长：3.825 s\n  [2022-04-24 21:11:16,802] [    INFO] - RTF: 0.7846773683635238\n  [2022-04-24 21:11:16,837] [    INFO] - 音频保存至：./output.wav\n  ```\n\n### 4. Streaming speech synthesis server and client using websocket protocol\n#### 4.1 Server Usage\n- Command Line (Recommended)\n  First modify the configuration file `conf/tts_online_application.yaml`, **set `protocol` to `websocket`**.\n  Start the service:\n  ```bash\n  paddlespeech_server start --config_file ./conf/tts_online_application.yaml\n  ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  Arguments:\n  - `config_file`: yaml file of the app, default: ./conf/tts_online_application.yaml\n  - `log_file`: log file. Default: ./log/paddlespeech.log\n\n  Output:\n  ```text\n  [2022-04-27 10:18:09,107] [    INFO] - The first response time of the 0 warm up: 1.1551103591918945 s\n  [2022-04-27 10:18:09,219] [    INFO] - The first response time of the 1 warm up: 0.11204338073730469 s\n  [2022-04-27 10:18:09,324] [    INFO] - The first response time of the 2 warm up: 0.1051797866821289 s\n  [2022-04-27 10:18:09,325] [    INFO] - **********************************************************************\n  INFO:     Started server process [17600]\n  [2022-04-27 10:18:09] [INFO] [server.py:75] Started server process [17600]\n  INFO:     Waiting for application startup.\n  [2022-04-27 10:18:09] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-27 10:18:09] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-27 10:18:09] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/tts_online_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  Output:\n  ```text\n  [2022-04-27 10:20:16,660] [    INFO] - The first response time of the 0 warm up: 1.0945196151733398 s\n  [2022-04-27 10:20:16,773] [    INFO] - The first response time of the 1 warm up: 0.11222052574157715 s\n  [2022-04-27 10:20:16,878] [    INFO] - The first response time of the 2 warm up: 0.10494542121887207 s\n  [2022-04-27 10:20:16,878] [    INFO] - **********************************************************************\n  INFO:     Started server process [23466]\n  [2022-04-27 10:20:16] [INFO] [server.py:75] Started server process [23466]\n  INFO:     Waiting for application startup.\n  [2022-04-27 10:20:16] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-27 10:20:16] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-27 10:20:16] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n#### 4.2 Streaming TTS client Usage\n- Command Line (Recommended)\n\n    Access websocket streaming TTS service:\n\n    If `127.0.0.1` is not accessible, you need to use the actual service IP address.\n\n    ```bash\n    paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol websocket --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n    ```\n\n    Usage:\n  \n    ```bash\n    paddlespeech_client tts_online --help\n    ```\n\n    Arguments:\n    - `server_ip`: erver ip. Default: 127.0.0.1\n    - `port`: server port. Default: 8092\n    - `protocol`: Service protocol, choices: [http, websocket], default: http.\n    - `input`: (required): Input text to generate.\n    - `spk_id`: Speaker id for multi-speaker text to speech. Default: 0\n    - `output`: Client output wave filepath. Default: None, which means not to save the audio to the local.\n    - `play`: Whether to play audio, play while synthesizing, default value: False, which means not playing. **Playing audio needs to rely on the pyaudio library**.\n    - Currently, only the single-speaker model is supported in the code, so `spk_id` does not take effect. Streaming TTS does not support changing sample rate, variable speed and volume.\n    \n\n    \n    Output:\n    ```text\n    [2022-04-27 10:21:04,262] [    INFO] - tts websocket client start\n    [2022-04-27 10:21:04,496] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n    [2022-04-27 10:21:04,496] [    INFO] - 首包响应：0.2124948501586914 s\n    [2022-04-27 10:21:07,483] [    INFO] - 尾包响应：3.199106454849243 s\n    [2022-04-27 10:21:07,484] [    INFO] - 音频时长：3.825 s\n    [2022-04-27 10:21:07,484] [    INFO] - RTF: 0.8363677006141812\n    [2022-04-27 10:21:07,516] [    INFO] - 音频保存至：output.wav\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSOnlineClientExecutor\n  import json\n\n  executor = TTSOnlineClientExecutor()\n  executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8092,\n      protocol=\"websocket\",\n      spk_id=0,\n      output=\"./output.wav\",\n      play=False)\n  ```\n\n  Output:\n  ```text\n  [2022-04-27 10:22:48,852] [    INFO] - tts websocket client start\n  [2022-04-27 10:22:49,080] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n  [2022-04-27 10:22:49,080] [    INFO] - 首包响应：0.21017956733703613 s\n  [2022-04-27 10:22:52,100] [    INFO] - 尾包响应：3.2304444313049316 s\n  [2022-04-27 10:22:52,101] [    INFO] - 音频时长：3.825 s\n  [2022-04-27 10:22:52,101] [    INFO] - RTF: 0.8445606356352762\n  [2022-04-27 10:22:52,134] [    INFO] - 音频保存至：./output.wav\n  ```\n"
  },
  {
    "path": "demos/streaming_tts_server/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 流式语音合成服务\n\n## 介绍\n这个 demo 是一个启动流式语音合成服务和访问该服务的实现。 它可以通过使用 `paddlespeech_server` 和 `paddlespeech_client` 的单个命令或 python 的几行代码来实现。\n\n服务接口定义请参考:\n- [PaddleSpeech Server RESTful API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-RESTful-API)\n- [PaddleSpeech Streaming Server WebSocket API](https://github.com/PaddlePaddle/PaddleSpeech/wiki/PaddleSpeech-Server-WebSocket-API)\n## 使用方法\n### 1. 安装\n请看 [安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\n推荐使用 **paddlepaddle 2.4rc** 或以上版本。\n\n你可以从简单，中等，困难 几种方式中选择一种方式安装 PaddleSpeech。\n\n**如果使用简单模式安装，需要自行准备 yaml 文件，可参考 conf 目录下的 yaml 文件。**\n\n### 2. 准备配置文件\n配置文件可参见 `conf/tts_online_application.yaml` 。\n- `protocol` 表示该流式 TTS 服务使用的网络协议，目前支持 **http 和 websocket** 两种。\n- `engine_list` 表示即将启动的服务将会包含的语音引擎，格式为 <语音任务>_<引擎类型>。\n    - 该 demo 主要介绍流式语音合成服务，因此语音任务应设置为 tts。\n    - 目前引擎类型支持两种形式：**online** 表示使用python进行动态图推理的引擎；**online-onnx** 表示使用 onnxruntime 进行推理的引擎。其中，online-onnx 的推理速度更快。\n- 流式 TTS 引擎的 AM 模型支持：**fastspeech2 以及 fastspeech2_cnndecoder**; Voc 模型支持：**hifigan, mb_melgan**\n- 流式 am 推理中，每次会对一个 chunk 的数据进行推理以达到流式的效果。其中 `am_block` 表示 chunk 中的有效帧数，`am_pad` 表示一个 chunk 中 am_block 前后各加的帧数。am_pad 的存在用于消除流式推理产生的误差，避免由流式推理对合成音频质量的影响。\n    - fastspeech2 不支持流式 am 推理，因此 am_pad 与 am_block 对它无效\n    - fastspeech2_cnndecoder 支持流式推理，当 am_pad=12 时，流式推理合成音频与非流式合成音频一致\n- 流式 voc 推理中，每次会对一个 chunk 的数据进行推理以达到流式的效果。其中 `voc_block` 表示 chunk 中的有效帧数，`voc_pad` 表示一个 chunk 中 voc_block 前后各加的帧数。voc_pad 的存在用于消除流式推理产生的误差，避免由流式推理对合成音频质量的影响。\n    - hifigan, mb_melgan 均支持流式 voc 推理\n    - 当 voc 模型为 mb_melgan，当 voc_pad=14 时，流式推理合成音频与非流式合成音频一致；voc_pad 最小可以设置为7，合成音频听感上没有异常，若 voc_pad 小于7，合成音频听感上存在异常。\n    - 当 voc 模型为 hifigan，当 voc_pad=19 时，流式推理合成音频与非流式合成音频一致；当 voc_pad=14 时，合成音频听感上没有异常。\n    - PaddleSpeech 中流式声码器 Pad 计算方法: [AIStudio 教程](https://aistudio.baidu.com/aistudio/projectdetail/4151335)\n- 推理速度：mb_melgan > hifigan; 音频质量：mb_melgan < hifigan\n- **注意：** 如果在容器里可正常启动服务，但客户端访问 ip 不可达，可尝试将配置文件中 `host` 地址换成本地 ip 地址。\n\n\n### 3. 使用 http 协议的流式语音合成服务端及客户端使用方法\n#### 3.1 服务端使用方法\n- 命令行 (推荐使用)\n\n  启动服务（配置文件默认使用http）：\n  ```bash\n  paddlespeech_server start --config_file ./conf/tts_online_application.yaml\n  ```\n\n  使用方法：\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  参数:\n  - `config_file`: 服务的配置文件，默认： ./conf/tts_online_application.yaml\n  - `log_file`: log 文件. 默认：./log/paddlespeech.log\n\n  输出:\n  ```text\n  [2022-04-24 20:05:27,887] [    INFO] - The first response time of the 0 warm up: 1.0123658180236816 s\n  [2022-04-24 20:05:28,038] [    INFO] - The first response time of the 1 warm up: 0.15108466148376465 s\n  [2022-04-24 20:05:28,191] [    INFO] - The first response time of the 2 warm up: 0.15317344665527344 s\n  [2022-04-24 20:05:28,192] [    INFO] - **********************************************************************\n  INFO:     Started server process [14638]\n  [2022-04-24 20:05:28] [INFO] [server.py:75] Started server process [14638]\n  INFO:     Waiting for application startup.\n  [2022-04-24 20:05:28] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-24 20:05:28] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-24 20:05:28] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/tts_online_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  输出:\n  ```text\n  [2022-04-24 21:00:16,934] [    INFO] - The first response time of the 0 warm up: 1.268730878829956 s\n  [2022-04-24 21:00:17,046] [    INFO] - The first response time of the 1 warm up: 0.11168622970581055 s\n  [2022-04-24 21:00:17,151] [    INFO] - The first response time of the 2 warm up: 0.10413002967834473 s\n  [2022-04-24 21:00:17,151] [    INFO] - **********************************************************************\n  INFO:     Started server process [320]\n  [2022-04-24 21:00:17] [INFO] [server.py:75] Started server process [320]\n  INFO:     Waiting for application startup.\n  [2022-04-24 21:00:17] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-24 21:00:17] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-24 21:00:17] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n#### 3.2 客户端使用方法\n- 命令行 (推荐使用)\n\n    访问 http 流式TTS服务：\n\n    若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n    ```bash\n    paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n    ```\n\n    使用帮助:\n  \n    ```bash\n    paddlespeech_client tts_online --help\n    ```\n\n    参数:\n    - `server_ip`: 服务端ip地址，默认: 127.0.0.1。\n    - `port`: 服务端口，默认: 8092。\n    - `protocol`: 服务协议，可选 [http, websocket], 默认: http。\n    - `input`: (必须输入): 待合成的文本。\n    - `spk_id`: 说话人 id，用于多说话人语音合成，默认值： 0。\n    - `output`: 客户端输出音频的路径， 默认值：None，表示不保存音频。\n    - `play`: 是否播放音频，边合成边播放， 默认值：False，表示不播放。**播放音频需要依赖pyaudio库**。\n    - 目前代码中只支持单说话人的模型，因此 spk_id 的选择并不生效。流式 TTS 不支持更换采样率，变速和变音量等功能。\n\n    \n    输出:\n    ```text\n    [2022-04-24 21:08:18,559] [    INFO] - tts http client start\n    [2022-04-24 21:08:21,702] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n    [2022-04-24 21:08:21,703] [    INFO] - 首包响应：0.18863153457641602 s\n    [2022-04-24 21:08:21,704] [    INFO] - 尾包响应：3.1427218914031982 s\n    [2022-04-24 21:08:21,704] [    INFO] - 音频时长：3.825 s\n    [2022-04-24 21:08:21,704] [    INFO] - RTF: 0.8216266382753459\n    [2022-04-24 21:08:21,739] [    INFO] - 音频保存至：output.wav\n\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSOnlineClientExecutor\n  import json\n\n  executor = TTSOnlineClientExecutor()\n  executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8092,\n      protocol=\"http\",\n      spk_id=0,\n      output=\"./output.wav\",\n      play=False)\n\n  ```\n\n  输出:\n  ```bash\n  [2022-04-24 21:11:13,798] [    INFO] - tts http client start\n  [2022-04-24 21:11:16,800] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n  [2022-04-24 21:11:16,801] [    INFO] - 首包响应：0.18234872817993164 s\n  [2022-04-24 21:11:16,801] [    INFO] - 尾包响应：3.0013909339904785 s\n  [2022-04-24 21:11:16,802] [    INFO] - 音频时长：3.825 s\n  [2022-04-24 21:11:16,802] [    INFO] - RTF: 0.7846773683635238\n  [2022-04-24 21:11:16,837] [    INFO] - 音频保存至：./output.wav\n  ```\n \n### 4. 使用 websocket 协议的流式语音合成服务端及客户端使用方法\n#### 4.1 服务端使用方法\n- 命令行 (推荐使用)\n  首先修改配置文件 `conf/tts_online_application.yaml`， **将 `protocol` 设置为 `websocket`**。\n  启动服务：\n  ```bash\n  paddlespeech_server start --config_file ./conf/tts_online_application.yaml\n  ```\n\n  使用方法：\n  \n  ```bash\n  paddlespeech_server start --help\n  ```\n  参数:\n  - `config_file`: 服务的配置文件，默认： ./conf/tts_online_application.yaml\n  - `log_file`: log 文件. 默认：./log/paddlespeech.log\n\n  输出:\n  ```text\n  [2022-04-27 10:18:09,107] [    INFO] - The first response time of the 0 warm up: 1.1551103591918945 s\n  [2022-04-27 10:18:09,219] [    INFO] - The first response time of the 1 warm up: 0.11204338073730469 s\n  [2022-04-27 10:18:09,324] [    INFO] - The first response time of the 2 warm up: 0.1051797866821289 s\n  [2022-04-27 10:18:09,325] [    INFO] - **********************************************************************\n  INFO:     Started server process [17600]\n  [2022-04-27 10:18:09] [INFO] [server.py:75] Started server process [17600]\n  INFO:     Waiting for application startup.\n  [2022-04-27 10:18:09] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-27 10:18:09] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-27 10:18:09] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_server import ServerExecutor\n\n  server_executor = ServerExecutor()\n  server_executor(\n      config_file=\"./conf/tts_online_application.yaml\", \n      log_file=\"./log/paddlespeech.log\")\n  ```\n\n  输出:\n  ```text\n  [2022-04-27 10:20:16,660] [    INFO] - The first response time of the 0 warm up: 1.0945196151733398 s\n  [2022-04-27 10:20:16,773] [    INFO] - The first response time of the 1 warm up: 0.11222052574157715 s\n  [2022-04-27 10:20:16,878] [    INFO] - The first response time of the 2 warm up: 0.10494542121887207 s\n  [2022-04-27 10:20:16,878] [    INFO] - **********************************************************************\n  INFO:     Started server process [23466]\n  [2022-04-27 10:20:16] [INFO] [server.py:75] Started server process [23466]\n  INFO:     Waiting for application startup.\n  [2022-04-27 10:20:16] [INFO] [on.py:45] Waiting for application startup.\n  INFO:     Application startup complete.\n  [2022-04-27 10:20:16] [INFO] [on.py:59] Application startup complete.\n  INFO:     Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  [2022-04-27 10:20:16] [INFO] [server.py:211] Uvicorn running on http://0.0.0.0:8092 (Press CTRL+C to quit)\n  ```\n\n#### 4.2 客户端使用方法\n- 命令行 (推荐使用)\n\n    访问 websocket 流式 TTS 服务：\n\n    若 `127.0.0.1` 不能访问，则需要使用实际服务 IP 地址\n\n    ```bash\n    paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol websocket --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.wav\n    ```\n\n    使用帮助:\n  \n    ```bash\n    paddlespeech_client tts_online --help\n    ```\n\n    参数:\n    - `server_ip`: 服务端ip地址，默认: 127.0.0.1。\n    - `port`: 服务端口，默认: 8092。\n    - `protocol`: 服务协议，可选 [http, websocket], 默认: http。\n    - `input`: (必须输入): 待合成的文本。\n    - `spk_id`: 说话人 id，用于多说话人语音合成，默认值： 0。\n    - `output`: 客户端输出音频的路径， 默认值：None，表示不保存音频。\n    - `play`: 是否播放音频，边合成边播放， 默认值：False，表示不播放。**播放音频需要依赖pyaudio库**。\n    - 目前代码中只支持单说话人的模型，因此 spk_id 的选择并不生效。流式 TTS 不支持更换采样率，变速和变音量等功能。\n\n\n    输出:\n    ```text\n    [2022-04-27 10:21:04,262] [    INFO] - tts websocket client start\n    [2022-04-27 10:21:04,496] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n    [2022-04-27 10:21:04,496] [    INFO] - 首包响应：0.2124948501586914 s\n    [2022-04-27 10:21:07,483] [    INFO] - 尾包响应：3.199106454849243 s\n    [2022-04-27 10:21:07,484] [    INFO] - 音频时长：3.825 s\n    [2022-04-27 10:21:07,484] [    INFO] - RTF: 0.8363677006141812\n    [2022-04-27 10:21:07,516] [    INFO] - 音频保存至：output.wav\n    ```\n\n- Python API\n  ```python\n  from paddlespeech.server.bin.paddlespeech_client import TTSOnlineClientExecutor\n  import json\n\n  executor = TTSOnlineClientExecutor()\n  executor(\n      input=\"您好，欢迎使用百度飞桨语音合成服务。\",\n      server_ip=\"127.0.0.1\",\n      port=8092,\n      protocol=\"websocket\",\n      spk_id=0,\n      output=\"./output.wav\",\n      play=False)\n  ```\n\n  输出:\n  ```text\n    [2022-04-27 10:22:48,852] [    INFO] - tts websocket client start\n    [2022-04-27 10:22:49,080] [    INFO] - 句子：您好，欢迎使用百度飞桨语音合成服务。\n    [2022-04-27 10:22:49,080] [    INFO] - 首包响应：0.21017956733703613 s\n    [2022-04-27 10:22:52,100] [    INFO] - 尾包响应：3.2304444313049316 s\n    [2022-04-27 10:22:52,101] [    INFO] - 音频时长：3.825 s\n    [2022-04-27 10:22:52,101] [    INFO] - RTF: 0.8445606356352762\n    [2022-04-27 10:22:52,134] [    INFO] - 音频保存至：./output.wav\n  ```\n"
  },
  {
    "path": "demos/streaming_tts_server/client.sh",
    "content": "#!/bin/bash\n\n# http client test\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.http.wav\n\n# websocket client test\n# If `127.0.0.1` is not accessible, you need to use the actual service IP address.\npaddlespeech_client tts_online --server_ip 127.0.0.1 --port 8192 --protocol websocket --input \"您好，欢迎使用百度飞桨语音合成服务。\" --output output.ws.wav\n"
  },
  {
    "path": "demos/streaming_tts_server/conf/tts_online_application.yaml",
    "content": "# This is the parameter configuration file for streaming tts server.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8092\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# engine_list choices = ['tts_online', 'tts_online-onnx'], the inference speed of tts_online-onnx is faster than tts_online.\n# protocol choices = ['websocket', 'http'] \nprotocol: 'http'\nengine_list: ['tts_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online #######################\ntts_online: \n    # am (acoustic model) choices=['fastspeech2_csmsc', 'fastspeech2_cnndecoder_csmsc']   \n    # fastspeech2_cnndecoder_csmsc support streaming am infer.     \n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    \n\n    # voc (vocoder) choices=['mb_melgan_csmsc, hifigan_csmsc']\n    # Both mb_melgan_csmsc and hifigan_csmsc support streaming voc inference\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    \n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online-onnx #######################\ntts_online-onnx: \n    # am (acoustic model) choices=['fastspeech2_csmsc_onnx', 'fastspeech2_cnndecoder_csmsc_onnx']\n    # fastspeech2_cnndecoder_csmsc_onnx support streaming am infer.        \n    am: 'fastspeech2_cnndecoder_csmsc_onnx' \n    # am_ckpt is a list, if am is fastspeech2_cnndecoder_csmsc_onnx, am_ckpt = [encoder model, decoder model, postnet model];\n    # if am is fastspeech2_csmsc_onnx, am_ckpt = [ckpt model];\n    am_ckpt:   # list\n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    am_sample_rate: 24000\n    am_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # voc (vocoder) choices=['mb_melgan_csmsc_onnx, hifigan_csmsc_onnx']\n    # Both mb_melgan_csmsc_onnx and hifigan_csmsc_onnx support streaming voc inference\n    voc: 'mb_melgan_csmsc_onnx'\n    voc_ckpt: \n    voc_sample_rate: 24000\n    voc_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # others\n    lang: 'zh'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc_onnx, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc_onnx, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    # voc_upsample should be same as n_shift on voc config.\n    voc_upsample: 300\n    "
  },
  {
    "path": "demos/streaming_tts_server/conf/tts_online_ws_application.yaml",
    "content": "# This is the parameter configuration file for streaming tts server.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8192\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# engine_list choices = ['tts_online', 'tts_online-onnx'], the inference speed of tts_online-onnx is faster than tts_online.\n# protocol choices = ['websocket', 'http'] \nprotocol: 'websocket'\nengine_list: ['tts_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online #######################\ntts_online: \n    # am (acoustic model) choices=['fastspeech2_csmsc', 'fastspeech2_cnndecoder_csmsc']   \n    # fastspeech2_cnndecoder_csmsc support streaming am infer.     \n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n        \n\n    # voc (vocoder) choices=['mb_melgan_csmsc, hifigan_csmsc']\n    # Both mb_melgan_csmsc and hifigan_csmsc support streaming voc inference\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    \n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online-onnx #######################\ntts_online-onnx: \n    # am (acoustic model) choices=['fastspeech2_csmsc_onnx', 'fastspeech2_cnndecoder_csmsc_onnx']\n    # fastspeech2_cnndecoder_csmsc_onnx support streaming am infer.        \n    am: 'fastspeech2_cnndecoder_csmsc_onnx' \n    # am_ckpt is a list, if am is fastspeech2_cnndecoder_csmsc_onnx, am_ckpt = [encoder model, decoder model, postnet model];\n    # if am is fastspeech2_csmsc_onnx, am_ckpt = [ckpt model];\n    am_ckpt:   # list\n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    am_sample_rate: 24000\n    am_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # voc (vocoder) choices=['mb_melgan_csmsc_onnx, hifigan_csmsc_onnx']\n    # Both mb_melgan_csmsc_onnx and hifigan_csmsc_onnx support streaming voc inference\n    voc: 'mb_melgan_csmsc_onnx'\n    voc_ckpt: \n    voc_sample_rate: 24000\n    voc_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # others\n    lang: 'zh'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc_onnx, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc_onnx, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    # voc_upsample should be same as n_shift on voc config.\n    voc_upsample: 300\n    "
  },
  {
    "path": "demos/streaming_tts_server/server.sh",
    "content": "#!/bin/bash\n\n# http server\npaddlespeech_server start --config_file ./conf/tts_online_application.yaml &> tts.http.log &\n\n\n# websocket server\npaddlespeech_server start --config_file ./conf/tts_online_ws_application.yaml &> tts.ws.log &\n\n\n"
  },
  {
    "path": "demos/streaming_tts_serving_fastdeploy/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Streaming Speech Synthesis Service\n\n## Introduction\nThis demo is an implementation of starting the streaming speech synthesis service and accessing the service.\n\n`Server` must be started in the docker, while `Client` does not have to be in the docker.\n\n**The streaming_tts_serving under the path of this article ($PWD) contains the configuration and code of the model, which needs to be mapped to the docker for use.**\n\n## Usage\n### 1. Server\n#### 1.1 Docker\n\n```bash\ndocker pull registry.baidubce.com/paddlepaddle/fastdeploy_serving_cpu_only:22.09\ndocker run -dit  --net=host --name fastdeploy --shm-size=\"1g\" -v $PWD:/models registry.baidubce.com/paddlepaddle/fastdeploy_serving_cpu_only:22.09\ndocker exec -it -u root fastdeploy bash\n```\n\n#### 1.2 Installation(inside the docker)\n```bash\napt-get install build-essential python3-dev libssl-dev libffi-dev libxml2 libxml2-dev libxslt1-dev zlib1g-dev libsndfile1 language-pack-zh-hans wget zip\npip3 install paddlespeech\nexport LC_ALL=\"zh_CN.UTF-8\"\nexport LANG=\"zh_CN.UTF-8\"\nexport LANGUAGE=\"zh_CN:zh:en_US:en\"\n```\n\n#### 1.3 Download models(inside the docker)\n```bash\ncd /models/streaming_tts_serving/1\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip\nunzip fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\nunzip mb_melgan_csmsc_onnx_0.2.0.zip\n```\n**For the convenience of users, we recommend that you use the command `docker -v` to map $PWD (streaming_tts_service and the configuration and code of the model contained therein) to the docker path `/models`. You can also use other methods, but regardless of which method you use, the final model directory and structure in the docker are shown in the following figure.**\n\n<p align=\"center\">\n  <img src=\"./tree.png\" />\n</p>\n\n#### 1.4 Start the server(inside the docker)\n\n```bash\nfastdeployserver --model-repository=/models --model-control-mode=explicit --load-model=streaming_tts_serving\n```\nArguments:\n  - `model-repository`(required): Path of model storage.\n  - `model-control-mode`(required): The mode of loading the model. At present, you can use 'explicit'.\n  - `load-model`(required): Name of the model to be loaded.\n  - `http-port`(optional): Port for http service. Default: `8000`. This is not used in our example.\n  - `grpc-port`(optional): Port for grpc service. Default: `8001`.\n  - `metrics-port`(optional): Port for metrics service. Default: `8002`. This is not used in our example.\n\n### 2. Client\n#### 2.1 Installation\n```bash\npip3 install tritonclient[all]\n```\n\n#### 2.2 Send request\n```bash\npython3 /models/streaming_tts_serving/stream_client.py\n```\n"
  },
  {
    "path": "demos/streaming_tts_serving_fastdeploy/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 流式语音合成服务\n\n## 介绍\n\n本文介绍了使用FastDeploy搭建流式语音合成服务的方法。\n\n`服务端`必须在docker内启动,而`客户端`不是必须在docker容器内.\n\n**本文所在路径`($PWD)下的streaming_tts_serving里包含模型的配置和代码`(服务端会加载模型和代码以启动服务),需要将其映射到docker中使用。**\n\n## 使用\n### 1. 服务端\n#### 1.1 Docker\n```bash\ndocker pull registry.baidubce.com/paddlepaddle/fastdeploy_serving_cpu_only:22.09\ndocker run -dit  --net=host --name fastdeploy --shm-size=\"1g\" -v $PWD:/models registry.baidubce.com/paddlepaddle/fastdeploy_serving_cpu_only:22.09\ndocker exec -it -u root fastdeploy bash\n```\n\n#### 1.2 安装(在docker内)\n```bash\napt-get install build-essential python3-dev libssl-dev libffi-dev libxml2 libxml2-dev libxslt1-dev zlib1g-dev libsndfile1 language-pack-zh-hans wget zip\npip3 install paddlespeech\nexport LC_ALL=\"zh_CN.UTF-8\"\nexport LANG=\"zh_CN.UTF-8\"\nexport LANGUAGE=\"zh_CN:zh:en_US:en\"\n```\n\n#### 1.3 下载模型(在docker内)\n```bash\ncd /models/streaming_tts_serving/1\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip\nunzip fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\nunzip mb_melgan_csmsc_onnx_0.2.0.zip\n```\n**为了方便用户使用，我们推荐用户使用1.1中的`docker -v`命令将`$PWD(streaming_tts_serving及里面包含的模型的配置和代码)映射到了docker内的/models路径`,用户也可以使用其他办法,但无论使用哪种方法,最终在docker内的模型目录及结构如下图所示。**\n\n<p align=\"center\">\n  <img src=\"./tree.png\" />\n</p>\n\n#### 1.4 启动服务端(在docker内)\n```bash\nfastdeployserver --model-repository=/models --model-control-mode=explicit --load-model=streaming_tts_serving\n```\n\n参数:\n  - `model-repository`(required): 整套模型streaming_tts_serving存放的路径.\n  - `model-control-mode`(required): 模型加载的方式,现阶段, 使用'explicit'即可.\n  - `load-model`(required): 需要加载的模型的名称.\n  - `http-port`(optional): HTTP服务的端口号. 默认: `8000`. 本示例中未使用该端口.\n  - `grpc-port`(optional): GRPC服务的端口号. 默认: `8001`.\n  - `metrics-port`(optional): 服务端指标的端口号. 默认: `8002`. 本示例中未使用该端口.\n\n### 2. 客户端\n#### 2.1 安装\n```bash\npip3 install tritonclient[all]\n```\n\n#### 2.2 发送请求\n```bash\npython3 /models/streaming_tts_serving/stream_client.py\n```\n"
  },
  {
    "path": "demos/streaming_tts_serving_fastdeploy/streaming_tts_serving/1/model.py",
    "content": "import codecs\nimport json\nimport math\nimport sys\nimport threading\nimport time\n\nimport numpy as np\nimport onnxruntime as ort\nimport triton_python_backend_utils as pb_utils\n\nfrom paddlespeech.server.utils.util import denorm\nfrom paddlespeech.server.utils.util import get_chunks\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\nvoc_block = 36\nvoc_pad = 14\nam_block = 72\nam_pad = 12\nvoc_upsample = 300\n\n# 模型路径\ndir_name = \"/models/streaming_tts_serving/1/\"\nphones_dict = dir_name + \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/phone_id_map.txt\"\nam_stat_path = dir_name + \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/speech_stats.npy\"\n\nonnx_am_encoder = dir_name + \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_encoder_infer.onnx\"\nonnx_am_decoder = dir_name + \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_decoder.onnx\"\nonnx_am_postnet = dir_name + \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_postnet.onnx\"\nonnx_voc_melgan = dir_name + \"mb_melgan_csmsc_onnx_0.2.0/mb_melgan_csmsc.onnx\"\n\nfrontend = Frontend(phone_vocab_path=phones_dict, tone_vocab_path=None)\nam_mu, am_std = np.load(am_stat_path)\n\n# 用CPU推理\nproviders = ['CPUExecutionProvider']\n\n# 配置ort session\nsess_options = ort.SessionOptions()\n\n# 创建session\nam_encoder_infer_sess = ort.InferenceSession(\n    onnx_am_encoder, providers=providers, sess_options=sess_options)\nam_decoder_sess = ort.InferenceSession(\n    onnx_am_decoder, providers=providers, sess_options=sess_options)\nam_postnet_sess = ort.InferenceSession(\n    onnx_am_postnet, providers=providers, sess_options=sess_options)\nvoc_melgan_sess = ort.InferenceSession(\n    onnx_voc_melgan, providers=providers, sess_options=sess_options)\n\n\ndef depadding(data, chunk_num, chunk_id, block, pad, upsample):\n    \"\"\"\n    Streaming inference removes the result of pad inference\n    \"\"\"\n    front_pad = min(chunk_id * block, pad)\n    # first chunk\n    if chunk_id == 0:\n        data = data[:block * upsample]\n    # last chunk\n    elif chunk_id == chunk_num - 1:\n        data = data[front_pad * upsample:]\n    # middle chunk\n    else:\n        data = data[front_pad * upsample:(front_pad + block) * upsample]\n\n    return data\n\n\nclass TritonPythonModel:\n    \"\"\"Your Python model must use the same class name. Every Python model\n    that is created must have \"TritonPythonModel\" as the class name.\n    \"\"\"\n\n    def initialize(self, args):\n        \"\"\"`initialize` is called only once when the model is being loaded.\n        Implementing `initialize` function is optional. This function allows\n        the model to initialize any state associated with this model.\n        Parameters\n        ----------\n        args : dict\n          Both keys and values are strings. The dictionary keys and values are:\n          * model_config: A JSON string containing the model configuration\n          * model_instance_kind: A string containing model instance kind\n          * model_instance_device_id: A string containing model instance device ID\n          * model_repository: Model repository path\n          * model_version: Model version\n          * model_name: Model name\n        \"\"\"\n        sys.stdout = codecs.getwriter(\"utf-8\")(sys.stdout.detach())\n        print(sys.getdefaultencoding())\n        # You must parse model_config. JSON string is not parsed here\n        self.model_config = model_config = json.loads(args['model_config'])\n        print(\"model_config:\", self.model_config)\n\n        using_decoupled = pb_utils.using_decoupled_model_transaction_policy(\n            model_config)\n\n        if not using_decoupled:\n            raise pb_utils.TritonModelException(\n                \"\"\"the model `{}` can generate any number of responses per request,\n                enable decoupled transaction policy in model configuration to\n                serve this model\"\"\".format(args['model_name']))\n\n        self.input_names = []\n        for input_config in self.model_config[\"input\"]:\n            self.input_names.append(input_config[\"name\"])\n        print(\"input:\", self.input_names)\n\n        self.output_names = []\n        self.output_dtype = []\n        for output_config in self.model_config[\"output\"]:\n            self.output_names.append(output_config[\"name\"])\n            dtype = pb_utils.triton_string_to_numpy(output_config[\"data_type\"])\n            self.output_dtype.append(dtype)\n        print(\"output:\", self.output_names)\n\n        # To keep track of response threads so that we can delay\n        # the finalizing the model until all response threads\n        # have completed.\n        self.inflight_thread_count = 0\n        self.inflight_thread_count_lck = threading.Lock()\n\n    def execute(self, requests):\n        \"\"\"`execute` must be implemented in every Python model. `execute`\n        function receives a list of pb_utils.InferenceRequest as the only\n        argument. This function is called when an inference is requested\n        for this model. Depending on the batching configuration (e.g. Dynamic\n        Batching) used, `requests` may contain multiple requests. Every\n        Python model, must create one pb_utils.InferenceResponse for every\n        pb_utils.InferenceRequest in `requests`. If there is an error, you can\n        set the error argument when creating a pb_utils.InferenceResponse.\n        Parameters\n        ----------\n        requests : list\n          A list of pb_utils.InferenceRequest\n        Returns\n        -------\n        list\n          A list of pb_utils.InferenceResponse. The length of this list must\n          be the same as `requests`\n        \"\"\"\n\n        # This model does not support batching, so 'request_count' should always\n        # be 1.\n        if len(requests) != 1:\n            raise pb_utils.TritonModelException(\"unsupported batch size \" + len(\n                requests))\n\n        input_data = []\n        for idx in range(len(self.input_names)):\n            data = pb_utils.get_input_tensor_by_name(requests[0],\n                                                     self.input_names[idx])\n            data = data.as_numpy()\n            data = data[0].decode('utf-8')\n            input_data.append(data)\n        text = input_data[0]\n\n        # Start a separate thread to send the responses for the request. The\n        # sending back the responses is delegated to this thread.\n        thread = threading.Thread(\n            target=self.response_thread,\n            args=(requests[0].get_response_sender(), text))\n        thread.daemon = True\n        with self.inflight_thread_count_lck:\n            self.inflight_thread_count += 1\n\n        thread.start()\n        # Unlike in non-decoupled model transaction policy, execute function\n        # here returns no response. A return from this function only notifies\n        # Triton that the model instance is ready to receive another request. As\n        # we are not waiting for the response thread to complete here, it is\n        # possible that at any give time the model may be processing multiple\n        # requests. Depending upon the request workload, this may lead to a lot\n        # of requests being processed by a single model instance at a time. In\n        # real-world models, the developer should be mindful of when to return\n        # from execute and be willing to accept next request.\n        return None\n\n    def response_thread(self, response_sender, text):\n        input_ids = frontend.get_input_ids(\n            text, merge_sentences=False, get_tone_ids=False)\n        phone_ids = input_ids[\"phone_ids\"]\n        for i in range(len(phone_ids)):\n            part_phone_ids = phone_ids[i].numpy()\n            voc_chunk_id = 0\n\n            orig_hs = am_encoder_infer_sess.run(\n                None, input_feed={'text': part_phone_ids})\n            orig_hs = orig_hs[0]\n\n            # streaming voc chunk info\n            mel_len = orig_hs.shape[1]\n            voc_chunk_num = math.ceil(mel_len / voc_block)\n            start = 0\n            end = min(voc_block + voc_pad, mel_len)\n\n            # streaming am\n            hss = get_chunks(orig_hs, am_block, am_pad, \"am\")\n            am_chunk_num = len(hss)\n            for i, hs in enumerate(hss):\n                am_decoder_output = am_decoder_sess.run(\n                    None, input_feed={'xs': hs})\n                am_postnet_output = am_postnet_sess.run(\n                    None,\n                    input_feed={\n                        'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                    })\n                am_output_data = am_decoder_output + np.transpose(\n                    am_postnet_output[0], (0, 2, 1))\n                normalized_mel = am_output_data[0][0]\n\n                sub_mel = denorm(normalized_mel, am_mu, am_std)\n                sub_mel = depadding(sub_mel, am_chunk_num, i, am_block, am_pad,\n                                    1)\n\n                if i == 0:\n                    mel_streaming = sub_mel\n                else:\n                    mel_streaming = np.concatenate(\n                        (mel_streaming, sub_mel), axis=0)\n\n                # streaming voc\n                # 当流式AM推理的mel帧数大于流式voc推理的chunk size，开始进行流式voc 推理\n                while (mel_streaming.shape[0] >= end and\n                       voc_chunk_id < voc_chunk_num):\n                    voc_chunk = mel_streaming[start:end, :]\n\n                    sub_wav = voc_melgan_sess.run(\n                        output_names=None, input_feed={'logmel': voc_chunk})\n                    sub_wav = depadding(sub_wav[0], voc_chunk_num, voc_chunk_id,\n                                        voc_block, voc_pad, voc_upsample)\n\n                    output_np = np.array(sub_wav, dtype=self.output_dtype[0])\n                    out_tensor1 = pb_utils.Tensor(self.output_names[0],\n                                                  output_np)\n\n                    status = 0 if voc_chunk_id != (voc_chunk_num - 1) else 1\n                    output_status = np.array(\n                        [status], dtype=self.output_dtype[1])\n                    out_tensor2 = pb_utils.Tensor(self.output_names[1],\n                                                  output_status)\n\n                    inference_response = pb_utils.InferenceResponse(\n                        output_tensors=[out_tensor1, out_tensor2])\n\n                    #yield sub_wav\n                    response_sender.send(inference_response)\n\n                    voc_chunk_id += 1\n                    start = max(0, voc_chunk_id * voc_block - voc_pad)\n                    end = min((voc_chunk_id + 1) * voc_block + voc_pad, mel_len)\n\n        # We must close the response sender to indicate to Triton that we are\n        # done sending responses for the corresponding request. We can't use the\n        # response sender after closing it. The response sender is closed by\n        # setting the TRITONSERVER_RESPONSE_COMPLETE_FINAL.\n        response_sender.send(\n            flags=pb_utils.TRITONSERVER_RESPONSE_COMPLETE_FINAL)\n\n        with self.inflight_thread_count_lck:\n            self.inflight_thread_count -= 1\n\n    def finalize(self):\n        \"\"\"`finalize` is called only once when the model is being unloaded.\n        Implementing `finalize` function is OPTIONAL. This function allows\n        the model to perform any necessary clean ups before exit.\n        Here we will wait for all response threads to complete sending\n        responses.\n        \"\"\"\n        print('Finalize invoked')\n\n        inflight_threads = True\n        cycles = 0\n        logging_time_sec = 5\n        sleep_time_sec = 0.1\n        cycle_to_log = (logging_time_sec / sleep_time_sec)\n        while inflight_threads:\n            with self.inflight_thread_count_lck:\n                inflight_threads = (self.inflight_thread_count != 0)\n                if (cycles % cycle_to_log == 0):\n                    print(\n                        f\"Waiting for {self.inflight_thread_count} response threads to complete...\"\n                    )\n            if inflight_threads:\n                time.sleep(sleep_time_sec)\n                cycles += 1\n\n        print('Finalize complete...')\n"
  },
  {
    "path": "demos/streaming_tts_serving_fastdeploy/streaming_tts_serving/config.pbtxt",
    "content": "name: \"streaming_tts_serving\"\nbackend: \"python\"\nmax_batch_size: 0\nmodel_transaction_policy {\n  decoupled: True\n}\ninput [\n  {\n    name: \"INPUT_0\"\n    data_type: TYPE_STRING\n    dims: [ 1 ]\n  }\n]\n\noutput [\n  {\n    name: \"OUTPUT_0\"\n    data_type: TYPE_FP32\n    dims: [ -1, 1 ]\n  },\n  {\n    name: \"status\"\n    data_type: TYPE_BOOL\n    dims: [ 1 ]\n  }\n]\n\ninstance_group [\n  {\n      count: 1\n      kind: KIND_CPU\n  }\n]\n"
  },
  {
    "path": "demos/streaming_tts_serving_fastdeploy/streaming_tts_serving/stream_client.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport queue\nimport sys\nfrom functools import partial\n\nimport numpy as np\nimport tritonclient.grpc as grpcclient\nfrom tritonclient.utils import *\n\nFLAGS = None\n\n\nclass UserData:\n    def __init__(self):\n        self._completed_requests = queue.Queue()\n\n\n# Define the callback function. Note the last two parameters should be\n# result and error. InferenceServerClient would povide the results of an\n# inference as grpcclient.InferResult in result. For successful\n# inference, error will be None, otherwise it will be an object of\n# tritonclientutils.InferenceServerException holding the error details\ndef callback(user_data, result, error):\n    if error:\n        user_data._completed_requests.put(error)\n    else:\n        user_data._completed_requests.put(result)\n\n\ndef async_stream_send(triton_client, values, request_id, model_name):\n\n    infer_inputs = []\n    outputs = []\n    for idx, data in enumerate(values):\n        data = np.array([data.encode('utf-8')], dtype=np.object_)\n        infer_input = grpcclient.InferInput('INPUT_0', [len(data)], \"BYTES\")\n        infer_input.set_data_from_numpy(data)\n        infer_inputs.append(infer_input)\n\n        outputs.append(grpcclient.InferRequestedOutput('OUTPUT_0'))\n        # Issue the asynchronous sequence inference.\n        triton_client.async_stream_infer(\n            model_name=model_name,\n            inputs=infer_inputs,\n            outputs=outputs,\n            request_id=request_id)\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        '-v',\n        '--verbose',\n        action=\"store_true\",\n        required=False,\n        default=False,\n        help='Enable verbose output')\n    parser.add_argument(\n        '-u',\n        '--url',\n        type=str,\n        required=False,\n        default='localhost:8001',\n        help='Inference server URL and it gRPC port. Default is localhost:8001.')\n\n    FLAGS = parser.parse_args()\n\n    # We use custom \"sequence\" models which take 1 input\n    # value. The output is the accumulated value of the inputs. See\n    # src/custom/sequence.\n    model_name = \"streaming_tts_serving\"\n\n    values = [\"哈哈哈哈\"]\n\n    request_id = \"0\"\n\n    string_result0_list = []\n\n    user_data = UserData()\n\n    # It is advisable to use client object within with..as clause\n    # when sending streaming requests. This ensures the client\n    # is closed when the block inside with exits.\n    with grpcclient.InferenceServerClient(\n            url=FLAGS.url, verbose=FLAGS.verbose) as triton_client:\n        try:\n            # Establish stream\n            triton_client.start_stream(callback=partial(callback, user_data))\n            # Now send the inference sequences...\n            async_stream_send(triton_client, values, request_id, model_name)\n        except InferenceServerException as error:\n            print(error)\n            sys.exit(1)\n\n        # Retrieve results...\n        recv_count = 0\n        result_dict = {}\n        status = True\n        while True:\n            data_item = user_data._completed_requests.get()\n            if type(data_item) == InferenceServerException:\n                raise data_item\n            else:\n                this_id = data_item.get_response().id\n                if this_id not in result_dict.keys():\n                    result_dict[this_id] = []\n                result_dict[this_id].append((recv_count, data_item))\n                sub_wav = data_item.as_numpy('OUTPUT_0')\n                status = data_item.as_numpy('status')\n                print('sub_wav = ', sub_wav, \"subwav.shape = \", sub_wav.shape)\n                print('status = ', status)\n                if status[0] == 1:\n                    break\n            recv_count += 1\n\n    print(\"PASS: stream_client\")\n"
  },
  {
    "path": "demos/style_fs2/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Style FastSpeech2\n## Introduction\n[FastSpeech2](https://arxiv.org/abs/2006.04558)  is a classical acoustic model for Text-to-Speech synthesis, which introduces controllable speech input, including `phoneme duration`、 `energy` and `pitch`. \n\nIn the prediction phase, you can change these controllable variables to get some interesting results.\n\nFor example:\n\n1. The `duration` control in `FastSpeech2` can control the speed of audios will keep the `pitch`. (in some speech tools, increasing the speed will increase the pitch and vice versa.)\n\n2. When we set the `pitch` of one sentence to a mean value and set the `tones` of phones to `1`, we will get a `robot-style` timbre.\n\n3. When we raise the `pitch` of an adult female (with a fixed scale ratio), we will get a `child-style` timbre.\n\nThe `duration` and `pitch` of different phonemes in a sentence can have different scale ratios. You can set different scale ratios to emphasize or weaken the pronunciation of some phonemes.\n## Usage\nRun the following command line to get started:\n```\n./run.sh\n```\nIn `run.sh`, it will execute `source path.sh` firstly, which will set the environment variants.\n\nIf you would like to try your sentence, please replace the sentence in `sentences.txt`.\n\nFor more details, please see `style_syn.py`\n\nThe audio samples are in [style-control-in-fastspeech2](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html#style-control-in-fastspeech2)\n"
  },
  {
    "path": "demos/style_fs2/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# Style FastSpeech2\n\n## 简介\n\n[FastSpeech2](https://arxiv.org/abs/2006.04558)  是用于语音合成的经典声学模型，它引入了可控语音输入，包括 `phoneme duration` 、 `energy` 和 `pitch` 。\n\n在预测阶段，您可以更改这些变量以获得一些有趣的结果。\n\n例如:\n\n1.  `FastSpeech2` 中的 `duration` 可以控制音频的速度 ，并保持 `pitch` 。（在某些语音工具中，增加速度将增加音调，反之亦然。）\n2. 当我们将一个句子的 `pitch` 设置为平均值并将音素的 `tones` 设置为 `1` 时，我们将获得 `robot-style` 的音色。\n3. 当我们提高成年女性的 `pitch` （比例固定）时，我们会得到 `child-style` 的音色。\n\n句子中不同音素的 `duration` 和 `pitch` 可以具有不同的比例。您可以设置不同的音阶比例来强调或削弱某些音素的发音。\n\n## 运行\n\n运行以下命令行开始：\n\n```\n./run.sh\n```\n\n在 `run.sh`, 会首先执行 `source path.sh` 去设置好环境变量。\n\n如果您想尝试您的句子，请替换 `sentences.txt`中的句子。\n\n更多的细节，请查看 `style_syn.py`。\n\n语音样例可以在 [style-control-in-fastspeech2](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html#style-control-in-fastspeech2) 查看。\n"
  },
  {
    "path": "demos/style_fs2/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\nMODEL=fastspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "demos/style_fs2/run.sh",
    "content": "#!/bin/bash\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\n# with the following command, you can choice the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nmkdir -p download\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # download pretrained tts models and unzip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip\n    unzip -d download download/pwg_baker_ckpt_0.4.zip\n    wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip\n    unzip -d download download/fastspeech2_nosil_baker_ckpt_0.4.zip\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # run tts\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    python3 style_syn.py \\\n        --fastspeech2-config=download/fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n        --fastspeech2-checkpoint=download/fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n        --fastspeech2-stat=download/fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy \\\n        --fastspeech2-pitch-stat=download/fastspeech2_nosil_baker_ckpt_0.4/pitch_stats.npy \\\n        --fastspeech2-energy-stat=download/fastspeech2_nosil_baker_ckpt_0.4/energy_stats.npy \\\n        --pwg-config=download/pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --pwg-checkpoint=download/pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --pwg-stat=download/pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --text=./sentences.txt \\\n        --output-dir=output \\\n        --phones-dict=download/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\nfi\n"
  },
  {
    "path": "demos/style_fs2/sentences.txt",
    "content": "000 谁知青蛙一落地，竟变成了一位英俊的王子。于是遵照国王的意思，他做了公主的亲密伴侣。\n"
  },
  {
    "path": "demos/style_fs2/style_syn.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import StyleFastSpeech2Inference\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n\ndef evaluate(args, fastspeech2_config, pwg_config):\n\n    # construct dataset for evaluation\n    sentences = []\n    with open(args.text, 'rt') as f:\n        for line in f:\n            items = line.strip().split()\n            utt_id = items[0]\n            sentence = \"\".join(items[1:])\n            sentences.append((utt_id, sentence))\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = fastspeech2_config.n_mels\n    model = FastSpeech2(\n        idim=vocab_size, odim=odim, **fastspeech2_config[\"model\"])\n\n    model.set_state_dict(\n        paddle.load(args.fastspeech2_checkpoint)[\"main_params\"])\n    model.eval()\n\n    vocoder = PWGGenerator(**pwg_config[\"generator_params\"])\n    vocoder.set_state_dict(paddle.load(args.pwg_checkpoint)[\"generator_params\"])\n    vocoder.remove_weight_norm()\n    vocoder.eval()\n    print(\"model done!\")\n\n    frontend = Frontend(phone_vocab_path=args.phones_dict)\n    print(\"frontend done!\")\n\n    stat = np.load(args.fastspeech2_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    fastspeech2_normalizer = ZScore(mu, std)\n\n    stat = np.load(args.pwg_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    pwg_normalizer = ZScore(mu, std)\n\n    fastspeech2_inference = StyleFastSpeech2Inference(\n        fastspeech2_normalizer, model, args.fastspeech2_pitch_stat,\n        args.fastspeech2_energy_stat)\n    fastspeech2_inference.eval()\n\n    pwg_inference = PWGInference(pwg_normalizer, vocoder)\n    pwg_inference.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    styles = [\"normal\", \"robot\", \"1.2xspeed\", \"0.8xspeed\", \"child_voice\"]\n    for style in styles:\n        robot = False\n        durations = None\n        durations_scale = None\n        durations_bias = None\n        pitch = None\n        pitch_scale = None\n        pitch_bias = None\n        energy = None\n        energy_scale = None\n        energy_bias = None\n        if style == \"robot\":\n            # all tones in phones be `1`\n            # all pitch should be the same, we use mean here\n            robot = True\n        if style == \"1.2xspeed\":\n            durations_scale = 1 / 1.2\n        if style == \"0.8xspeed\":\n            durations_scale = 1 / 0.8\n        if style == \"child_voice\":\n            pitch_scale = 1.3\n        sub_output_dir = output_dir / style\n        sub_output_dir.mkdir(parents=True, exist_ok=True)\n        for utt_id, sentence in sentences:\n            input_ids = frontend.get_input_ids(\n                sentence, merge_sentences=True, robot=robot)\n            phone_ids = input_ids[\"phone_ids\"][0]\n\n            with paddle.no_grad():\n                mel = fastspeech2_inference(\n                    phone_ids,\n                    durations=durations,\n                    durations_scale=durations_scale,\n                    durations_bias=durations_bias,\n                    pitch=pitch,\n                    pitch_scale=pitch_scale,\n                    pitch_bias=pitch_bias,\n                    energy=energy,\n                    energy_scale=energy_scale,\n                    energy_bias=energy_bias,\n                    robot=robot)\n                wav = pwg_inference(mel)\n\n            sf.write(\n                str(sub_output_dir / (utt_id + \".wav\")),\n                wav.numpy(),\n                samplerate=fastspeech2_config.fs)\n            print(f\"{style}_{utt_id} done!\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with fastspeech2 & parallel wavegan.\")\n    parser.add_argument(\n        \"--fastspeech2-config\", type=str, help=\"fastspeech2 config file.\")\n    parser.add_argument(\n        \"--fastspeech2-checkpoint\",\n        type=str,\n        help=\"fastspeech2 checkpoint to load.\")\n    parser.add_argument(\n        \"--fastspeech2-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training fastspeech2.\"\n    )\n    parser.add_argument(\n        \"--fastspeech2-pitch-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize pitch when training fastspeech2\"\n    )\n    parser.add_argument(\n        \"--fastspeech2-energy-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize energy when training fastspeech2.\"\n    )\n    parser.add_argument(\n        \"--pwg-config\", type=str, help=\"parallel wavegan config file.\")\n    parser.add_argument(\n        \"--pwg-checkpoint\",\n        type=str,\n        help=\"parallel wavegan generator parameters to load.\")\n    parser.add_argument(\n        \"--pwg-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training parallel wavegan.\"\n    )\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\"--verbose\", type=int, default=1, help=\"verbose.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.fastspeech2_config) as f:\n        fastspeech2_config = CfgNode(yaml.safe_load(f))\n    with open(args.pwg_config) as f:\n        pwg_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(fastspeech2_config)\n    print(pwg_config)\n\n    evaluate(args, fastspeech2_config, pwg_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "demos/text_to_speech/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# TTS (Text To Speech)\n\n## Introduction\nText-to-speech (TTS) is a natural language modeling process that requires changing units of text into units of speech for audio presentation. \n\nThis demo is an implementation to generate audio from the given text. It can be done by a single command or a few lines in python using `PaddleSpeech`. \n\n## Usage\n### 1. Installation\nsee [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\nYou can choose one way from easy, medium and hard to install paddlespeech.\n\n### 2. Prepare Input\nThe input of this demo should be a text of the specific language that can be passed via argument.\n### 3. Usage\n- Command Line (Recommended)\n    The default acoustic model is `Fastspeech2`, and the default vocoder is `HiFiGAN`, the default inference method is dygraph inference. \n    - Chinese\n        ```bash\n        paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\"\n        ```\n    - Batch Process\n        ```bash\n        echo -e \"1 欢迎光临。\\n2 谢谢惠顾。\" | paddlespeech tts\n        ```\n    - Chinese, use `SpeedySpeech` as the acoustic model\n        ```bash\n        paddlespeech tts --am speedyspeech_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\"\n        ```\n    - Chinese, multi-speaker\n    \n        You can change `spk_id` here.\n        ```bash\n        paddlespeech tts --am fastspeech2_aishell3 --voc pwgan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0\n        ```\n    \n     - English\n        ```bash\n        paddlespeech tts --am fastspeech2_ljspeech --voc pwgan_ljspeech --lang en --input \"hello world\"\n        ```\n    - English, multi-speaker\n    \n        You can change `spk_id` here.\n        ```bash\n        paddlespeech tts --am fastspeech2_vctk --voc pwgan_vctk --input \"hello, boys\" --lang en --spk_id 0\n        ```\n    - Chinese English Mixed, multi-speaker\n        You can change `spk_id` here.\n        ```bash\n        # The `am` must be `fastspeech2_mix`!\n        # The `lang` must be `mix`!\n        # The voc must be chinese datasets' voc now!\n        # spk 174 is csmcc, spk 175 is ljspeech\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_csmsc --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --spk_id 174 --output mix_spk174.wav\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_aishell3 --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --spk_id 174 --output mix_spk174_aishell3.wav\n        paddlespeech tts --am fastspeech2_mix --voc pwgan_csmsc --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --spk_id 175 --output mix_spk175_pwgan.wav\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_csmsc --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --spk_id 175 --output mix_spk175.wav\n        ```\n    - Chinese English Mixed, single male spk\n        ```bash\n        # male mix tts\n        # The `lang` must be `mix`!\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --output male_mix_fs2_pwgan.wav\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --output male_mix_fs2_hifigan.wav\n        ```\n    - Cantonese\n        ```bash\n        paddlespeech tts --am fastspeech2_canton --voc pwgan_aishell3 --input \"各个国家有各个国家嘅国歌\" --lang canton --spk_id 10\n        ```\n    - Use ONNXRuntime infer：\n        ```bash\n        paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output default.wav --use_onnx True\n        paddlespeech tts --am speedyspeech_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output ss.wav --use_onnx True\n        paddlespeech tts --voc mb_melgan_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output mb.wav --use_onnx True\n        paddlespeech tts --voc pwgan_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_aishell3 --voc pwgan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0 --output aishell3_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_aishell3 --voc hifigan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0 --output aishell3_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_ljspeech --voc pwgan_ljspeech --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output lj_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_ljspeech --voc hifigan_ljspeech --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output lj_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_vctk --voc pwgan_vctk --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --lang en --spk_id 0 --output vctk_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_vctk --voc hifigan_vctk --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --lang en --spk_id 0 --output vctk_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang zh --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output male_zh_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output male_en_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output male_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang zh --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output male_zh_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output male_en_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_male --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output male_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_mix --voc pwgan_csmsc --lang mix --spk_id 174 --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output mix_fs2_pwgan_csmsc_spk174.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_canton --voc pwgan_aishell3 --lang canton --spk_id 10 --input \"各个国家有各个国家嘅国歌\" --output output_canton.wav --use_onnx True\n        ```\n\n  Usage:\n  \n  ```bash\n  paddlespeech tts --help\n  ```\n  Arguments:\n  - `input`(required): Input text to generate..\n  - `am`: Acoustic model type of tts task. Default: `fastspeech2_csmsc`.\n  - `am_config`: Config of acoustic model. Use default config when it is None. Default: `None`.\n  - `am_ckpt`: Acoustic model checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `am_stat`: Mean and standard deviation used to normalize spectrogram when training acoustic model. Default: `None`.\n  - `phones_dict`: Phone vocabulary file. Default: `None`.\n  - `tones_dict`: Tone vocabulary file. Default: `None`.\n  - `speaker_dict`: speaker id map file. Default: `None`.\n  - `spk_id`: Speaker id for multi speaker acoustic model. Default: `0`.\n  - `voc`: Vocoder type of tts task. Default: `pwgan_csmsc`.\n  - `voc_config`: Config of vocoder. Use default config when it is None. Default: `None`.\n  - `voc_ckpt`: Vocoder checkpoint. Use pretrained model when it is None. Default: `None`.\n  - `voc_stat`: Mean and standard deviation used to normalize spectrogram when training vocoder. Default: `None`.\n  - `lang`: Language of tts task. Default: `zh`.\n  - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n  - `output`: Output wave filepath. Default: `output.wav`.\n  - `use_onnx`: whether to usen ONNXRuntime inference.\n  - `fs`: sample rate for ONNX models when use specified model files.\n\n  Output:\n  ```bash\n  [2021-12-09 20:49:58,955] [    INFO] [log.py] [L57] - Wave file has been generated: output.wav\n  ```\n\n- Python API\n    - Dygraph infer:\n        ```python\n        import paddle\n        from paddlespeech.cli.tts import TTSExecutor\n        tts_executor = TTSExecutor()\n        wav_file = tts_executor(\n            text='今天的天气不错啊',\n            output='output.wav',\n            am='fastspeech2_csmsc',\n            am_config=None,\n            am_ckpt=None,\n            am_stat=None,\n            spk_id=0,\n            phones_dict=None,\n            tones_dict=None,\n            speaker_dict=None,\n            voc='pwgan_csmsc',\n            voc_config=None,\n            voc_ckpt=None,\n            voc_stat=None,\n            lang='zh',\n            device=paddle.get_device())\n        print('Wave file has been generated: {}'.format(wav_file))\n        ```\n    - ONNXRuntime infer:\n        ```python\n        from paddlespeech.cli.tts import TTSExecutor\n        tts_executor = TTSExecutor()\n        wav_file = tts_executor(\n            text='对数据集进行预处理',\n            output='output.wav',\n            am='fastspeech2_csmsc',\n            voc='hifigan_csmsc',\n            lang='zh',\n            use_onnx=True,\n            cpu_threads=2)\n        ```\n \n  Output:\n  ```bash\n  Wave file has been generated: output.wav\n  ```\n\n### 4. Pretrained Models\nHere is a list of pretrained models released by PaddleSpeech that can be used by command and python API:\n\n- Acoustic model\n  | Model | Language |\n  | :--- | :---: |\n  |      speedyspeech_csmsc      |    zh    |\n  |      fastspeech2_csmsc       |    zh    |\n  |     fastspeech2_ljspeech     |    en    |\n  |     fastspeech2_aishell3     |    zh    |\n  |       fastspeech2_vctk       |    en    |\n  | fastspeech2_cnndecoder_csmsc |    zh    |\n  |       fastspeech2_mix        |   mix    |\n  |       tacotron2_csmsc        |    zh    |\n  |      tacotron2_ljspeech      |    en    |\n  |       fastspeech2_male       |    zh    |\n  |       fastspeech2_male       |    en    |\n  |       fastspeech2_male       |   mix    |\n  |       fastspeech2_canton     |  canton  |\n\n- Vocoder\n  | Model | Language |\n  | :--- | :---: |\n  |         pwgan_csmsc          |    zh    |\n  |        pwgan_ljspeech        |    en    |\n  |        pwgan_aishell3        |    zh    |\n  |          pwgan_vctk          |    en    |\n  |       mb_melgan_csmsc        |    zh    |\n  |      style_melgan_csmsc      |    zh    |\n  |        hifigan_csmsc         |    zh    |\n  |       hifigan_ljspeech       |    en    |\n  |       hifigan_aishell3       |    zh    |\n  |         hifigan_vctk         |    en    |\n  |        wavernn_csmsc         |    zh    |\n  |         pwgan_male           |    zh    |\n  |        hifigan_male          |    zh    |\n"
  },
  {
    "path": "demos/text_to_speech/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# 语音合成\n## 介绍\n语音合成是一种自然语言建模过程，其将文本转换为语音以进行音频演示。\n\n这个 demo 是一个从给定文本生成音频的实现，它可以通过使用 `PaddleSpeech` 的单个命令或 python 中的几行代码来实现。\n## 使用方法\n### 1. 安装\n请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n你可以从 easy，medium，hard 三种方式中选择一种方式安装。\n\n### 2. 准备输入\n\n这个 demo 的输入是通过参数传递的特定语言的文本。\n### 3. 使用方法\n- 命令行 (推荐使用)\n     默认的声学模型是 `Fastspeech2`，默认的声码器是 `HiFiGAN`，默认推理方式是动态图推理。\n    - 中文\n        ```bash\n        paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\"\n        ```\n    - 批处理\n        ```bash\n        echo -e \"1 欢迎光临。\\n2 谢谢惠顾。\" | paddlespeech tts\n        ```\n    - 中文，使用 `SpeedySpeech` 作为声学模型\n        ```bash\n        paddlespeech tts --am speedyspeech_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\"\n        ```\n    - 中文， 多说话人\n    \n        你可以改变 `spk_id`。\n        ```bash\n        paddlespeech tts --am fastspeech2_aishell3 --voc pwgan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0\n        ```\n    \n     - 英文\n        ```bash\n        paddlespeech tts --am fastspeech2_ljspeech --voc pwgan_ljspeech --lang en --input \"hello world\"\n        ```\n    - 英文，多说话人\n    \n        你可以改变 `spk_id`。\n        ```bash\n        paddlespeech tts --am fastspeech2_vctk --voc pwgan_vctk --input \"hello, boys\" --lang en --spk_id 0\n        ```\n    - 中英文混合，多说话人\n        你可以改变 `spk_id`。\n        ```bash\n        # The `am` must be `fastspeech2_mix`!\n        # The `lang` must be `mix`!\n        # The voc must be chinese datasets' voc now!\n        # spk 174 is csmcc, spk 175 is ljspeech\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_csmsc --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --spk_id 174 --output mix_spk174.wav\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_aishell3 --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --spk_id 174 --output mix_spk174_aishell3.wav\n        paddlespeech tts --am fastspeech2_mix --voc pwgan_csmsc --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --spk_id 175 --output mix_spk175_pwgan.wav\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_csmsc --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --spk_id 175 --output mix_spk175.wav\n        ```\n    - 中英文混合，单个男性说话人\n        ```bash\n        # male mix tts\n        # The `lang` must be `mix`!\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --output male_mix_fs2_pwgan.wav\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang mix --input \"我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\" --output male_mix_fs2_hifigan.wav\n        ```\n    - 粤语\n        ```bash\n        paddlespeech tts --am fastspeech2_canton --voc pwgan_aishell3 --input \"各个国家有各个国家嘅国歌\" --lang canton --spk_id 10\n        ```\n    - 使用 ONNXRuntime 推理：\n        ```bash\n        paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output default.wav --use_onnx True\n        paddlespeech tts --am speedyspeech_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output ss.wav --use_onnx True\n        paddlespeech tts --voc mb_melgan_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output mb.wav --use_onnx True\n        paddlespeech tts --voc pwgan_csmsc --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_aishell3 --voc pwgan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0 --output aishell3_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_aishell3 --voc hifigan_aishell3 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --spk_id 0 --output aishell3_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_ljspeech --voc pwgan_ljspeech --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output lj_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_ljspeech --voc hifigan_ljspeech --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output lj_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_vctk --voc pwgan_vctk --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --lang en --spk_id 0 --output vctk_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_vctk --voc hifigan_vctk --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --lang en --spk_id 0 --output vctk_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang zh --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output male_zh_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output male_en_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc pwgan_male --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output male_fs2_pwgan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang zh --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output male_zh_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_male --voc hifigan_male --lang en --input \"Life was like a box of chocolates, you never know what you're gonna get.\" --output male_en_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_mix --voc hifigan_male --lang mix --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output male_fs2_hifigan.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_mix --voc pwgan_csmsc --lang mix --spk_id 174 --input \"热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\" --output mix_fs2_pwgan_csmsc_spk174.wav --use_onnx True\n        paddlespeech tts --am fastspeech2_canton --voc pwgan_aishell3 --lang canton --spk_id 10 --input \"各个国家有各个国家嘅国歌\" --output output_canton.wav --use_onnx True\n        ```\n\n  使用方法：\n  \n  ```bash\n  paddlespeech tts --help\n  ```\n  参数：\n  - `input`(必须输入)：用于合成音频的文本。\n  - `am`：TTS 任务的声学模型， 默认值：`fastspeech2_csmsc`。\n  - `am_config`：声学模型的配置文件，若不设置则使用默认配置，默认值：`None`。\n  - `am_ckpt`：声学模型的参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `am_stat`：训练声学模型时用于正则化 mel 频谱图的均值标准差文件，默认值：`None`。\n  - `phones_dict`：音素词表文件， 默认值：`None`。\n  - `tones_dict`：声调词表文件， 默认值：`None`。\n  - `speaker_dict`：说话人词表文件， 默认值：`None`。\n  - `spk_id`：说话人 id， 默认值： `0`。\n  - `voc`：TTS 任务的声码器， 默认值： `pwgan_csmsc`。\n  - `voc_config`：声码器的配置文件，若不设置则使用默认配置，默认值：`None`。\n  - `voc_ckpt`：声码器的参数文件，若不设置则下载预训练模型使用，默认值：`None`。\n  - `voc_stat`：训练声码器时用于正则化 mel 频谱图的均值标准差文件，默认值：`None`。\n  - `lang`：TTS 任务的语言， 默认值：`zh`。\n  - `device`：执行预测的设备， 默认值：当前系统下 paddlepaddle 的默认 device。\n  - `output`：输出音频的路径， 默认值：`output.wav`。\n  - `use_onnx`: 是否使用 ONNXRuntime 进行推理。\n  - `fs`: 使用特定 ONNX 模型时的采样率。\n\n  输出：\n  ```bash\n  [2021-12-09 20:49:58,955] [    INFO] [log.py] [L57] - Wave file has been generated: output.wav\n  ```\n\n- Python API\n     - 动态图推理:\n        ```python\n        import paddle\n        from paddlespeech.cli.tts import TTSExecutor\n        tts_executor = TTSExecutor()\n        wav_file = tts_executor(\n            text='今天的天气不错啊',\n            output='output.wav',\n            am='fastspeech2_csmsc',\n            am_config=None,\n            am_ckpt=None,\n            am_stat=None,\n            spk_id=0,\n            phones_dict=None,\n            tones_dict=None,\n            speaker_dict=None,\n            voc='pwgan_csmsc',\n            voc_config=None,\n            voc_ckpt=None,\n            voc_stat=None,\n            lang='zh',\n            device=paddle.get_device())\n        print('Wave file has been generated: {}'.format(wav_file))\n        ```\n    -  ONNXRuntime 推理:\n        ```python\n        from paddlespeech.cli.tts import TTSExecutor\n        tts_executor = TTSExecutor()\n        wav_file = tts_executor(\n            text='对数据集进行预处理',\n            output='output.wav',\n            am='fastspeech2_csmsc',\n            voc='hifigan_csmsc',\n            lang='zh',\n            use_onnx=True,\n            cpu_threads=2)\n        ```\n \n  输出：\n  ```bash\n  Wave file has been generated: output.wav\n  ```\n\n### 4. 预训练模型\n以下是 PaddleSpeech 提供的可以被命令行和 python API 使用的预训练模型列表：\n\n- 声学模型\n  | 模型 | 语言 |\n  | :--- | :---: |\n  |      speedyspeech_csmsc      |    zh    |\n  |      fastspeech2_csmsc       |    zh    |\n  |     fastspeech2_ljspeech     |    en    |\n  |     fastspeech2_aishell3     |    zh    |\n  |       fastspeech2_vctk       |    en    |\n  | fastspeech2_cnndecoder_csmsc |    zh    |\n  |       fastspeech2_mix        |   mix    |\n  |       tacotron2_csmsc        |    zh    |\n  |      tacotron2_ljspeech      |    en    |\n  |       fastspeech2_male       |    zh    |\n  |       fastspeech2_male       |    en    |\n  |       fastspeech2_male       |   mix    |\n  |       fastspeech2_canton     |  canton  |\n\n- 声码器\n  | 模型 | 语言 |\n  | :--- | :---: |\n  |         pwgan_csmsc          |    zh    |\n  |        pwgan_ljspeech        |    en    |\n  |        pwgan_aishell3        |    zh    |\n  |          pwgan_vctk          |    en    |\n  |       mb_melgan_csmsc        |    zh    |\n  |      style_melgan_csmsc      |    zh    |\n  |        hifigan_csmsc         |    zh    |\n  |       hifigan_ljspeech       |    en    |\n  |       hifigan_aishell3       |    zh    |\n  |         hifigan_vctk         |    en    |\n  |        wavernn_csmsc         |    zh    |\n  |         pwgan_male           |    zh    |\n  |        hifigan_male          |    zh    |\n"
  },
  {
    "path": "demos/text_to_speech/run.sh",
    "content": "#!/bin/bash\n\n# single process\npaddlespeech tts --input 今天的天气不错啊\n\n# Batch process\necho -e \"1 欢迎光临。\\n2 谢谢惠顾。\" | paddlespeech tts\n\n# Text Frontend\npaddlespeech tts --input 今天是2022/10/29,最低温度是-3℃.\n\n\n\n"
  },
  {
    "path": "demos/whisper/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n## Introduction\nWhisper is a general-purpose speech recognition model. It is trained on a large dataset of diverse audio and is also a multi-task model that can perform multilingual speech recognition as well as speech translation and language identification.\n\nWhisper model trained by OpenAI whisper https://github.com/openai/whisper\n\n## Usage\n ### 1. Installation\n see [installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\n You can choose one way from easy, medium and hard to install paddlespeech.\n\n ### 2. Prepare Input File\n The input of this demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\n Here are sample files for this demo that can be downloaded:\n ```bash\n wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n ```\n\n ### 3. Usage\n - Command Line(Recommended)\n   ```bash\n   # to recognize text \n   paddlespeech whisper --task transcribe --input ./zh.wav\n\n   # to change model English-Only base size model\n   paddlespeech whisper --lang en --size base --task transcribe  --input ./en.wav\n\n   # to recognize text and translate to English\n   paddlespeech whisper --task translate --input ./zh.wav\n   \n   ```\n\n   Usage:\n   ```bash\n   paddlespeech whisper --help\n   ```\n   Arguments:\n   - `input`(required): Audio file to recognize.\n   - `model`: Model type of asr task. Default: `whisper`.\n   - `task`: Output type. Default: `transcribe`.\n   - `lang`: Model language. Default: ``. Use `en` to choice English-only model. Now [medium,base,small,tiny] size can support English-only.\n   - `size`: Model size for decode. Default: `turbo`. Now can support [turbo,large,medium,base,small,tiny].\n   - `language`: Set decode language. Default: `None`. Forcibly set the recognized language, which is determined by the model itself by default. \n   - `sample_rate`: Sample rate of the model. Default: `16000`. Other sampling rates are not supported now.\n   - `config`: Config of asr task. Use pretrained model when it is None. Default: `None`.\n   - `ckpt_path`: Model checkpoint. Use pretrained model when it is None. Default: `None`.\n   - `yes`: No additional parameters required. Once set this parameter, it means accepting the request of the program by default, which includes transforming the audio sample rate. Default: `False`.\n   - `device`: Choose device to execute model inference. Default: default device of paddlepaddle in current environment.\n   - `verbose`: Show the log information.\n\n\n - Python API\n   ```python\n   import paddle\n   from paddlespeech.cli.whisper import WhisperExecutor\n\n   whisper_executor = WhisperExecutor()\n\n   # to recognize text \n   text = whisper_executor(\n       model='whisper',\n       task='transcribe',\n       sample_rate=16000,\n       config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n       ckpt_path=None,\n       audio_file='./zh.wav',\n       device=paddle.get_device())\n   print('ASR Result: \\n{}'.format(text))\n\n   # to recognize text and translate to English\n   feature = whisper_executor(\n       model='whisper',\n       task='translate',\n       size='large', # For the translation function, is it better to use large or medium model\n       sample_rate=16000,\n       config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n       ckpt_path=None,\n       audio_file='./zh.wav',\n       device=paddle.get_device())\n   print('Representation: \\n{}'.format(feature))\n   ```\n\n   Output:\n   ```bash\n   Transcribe Result:\n   Detected language: Chinese\n   [00:00.000 --> 00:05.000] 我认为跑步最重要的就是给我带来了身体健康\n   {'text': '我认为跑步最重要的就是给我带来了身体健康', 'segments': [{'id': 0, 'seek': 0, 'start': 0.0, 'end': 5.0, 'text': '我认为跑步最重要的就是给我带来了身体健康', 'tokens': [50364, 1654, 7422, 97, 13992, 32585, 31429, 8661, 24928, 1546, 5620, 49076, 4845, 99, 34912, 19847, 29485, 44201, 6346, 115, 50614], 'temperature': 0.0, 'avg_logprob': -0.23577967557040128, 'compression_ratio': 0.28169014084507044, 'no_speech_prob': 0.028302080929279327}], 'language': 'zh'}\n\n   Translate Result:\n   Detected language: Chinese\n   [00:00.000 --> 00:05.000]  I think the most important thing about running is that it brings me good health.\n   {'text': ' I think the most important thing about running is that it brings me good health.', 'segments': [{'id': 0, 'seek': 0, 'start': 0.0, 'end': 5.0, 'text': ' I think the most important thing about running is that it brings me good health.', 'tokens': [50364, 286, 519, 264, 881, 1021, 551, 466, 2614, 307, 300, 309, 5607, 385, 665, 1585, 13, 50614], 'temperature': 0.0, 'avg_logprob': -0.47945233395225123, 'compression_ratio': 1.095890410958904, 'no_speech_prob': 0.028302080929279327}], 'language': 'zh'}\n"
  },
  {
    "path": "demos/whisper/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n\n# Whisper模型\n## 介绍\nWhisper是一种通用的语音识别模型。它是在多种音频的大数据集上训练的，也是一个多任务模型，可以执行多语言语音识别以及语音翻译和语言识别。\n\nWhisper模型由OpenAI Whisper训练 https://github.com/openai/whisper\n\n## 使用方法\n### 1. 安装\n 请看[安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)。\n\n 你可以从 easy，medium，hard 三中方式中选择一种方式安装。\n\n### 2. 准备输入\n 这个 demo 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n 可以下载此 demo 的示例音频：\n ```bash\n wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n ```\n\n### 3. 使用方法\n - 命令行 (推荐使用)\n   ```bash\n\n   # 识别文本\n   paddlespeech whisper --task transcribe --input ./zh.wav\n\n   #选择只支持英文的模型，并且更换不同大小的模型\n   paddlespeech whisper --lang en --size base --task transcribe  --input ./en.wav\n\n   # 将语音翻译成英语\n   paddlespeech whisper --task translate --input ./zh.wav\n   ```\n  使用方法：\n   ```bash\n   paddlespeech whisper --help\n   ```\n   参数：\n   - `input`(必须输入)：用于识别的音频文件。\n   - `model`：ASR 任务的模型，默认值：`whisper`。\n   - `task`：输出类别，默认值：`transcribe`。\n   - `lang`: 模型语言，默认值：``，使用`en`选择只支持英文的模型，目前可选择`en`的模型有[medium,base,small,tiny]。\n   - `size`: 模型大小，默认值：`turbo`，目前支持[turbo,large,medium,base,small,tiny]。\n   - `language`：设定解码语言，默认值：`None`，强制设定识别出的语言，默认为模型自行判定。\n   - `sample_rate`：音频采样率，默认值：`16000`，目前Whisper暂不支持其他采样率。\n   - `config`：ASR 任务的参数文件，若不设置则使用预训练模型中的默认配置，默认值：`None`。\n   - `ckpt_path`：模型参数文件，若不设置则下载解码模型使用，默认值：`None`。\n   - `yes`；不需要设置额外的参数，一旦设置了该参数，说明你默认同意程序的所有请求，其中包括自动转换输入音频的采样率。默认值：`False`。\n   - `device`：执行预测的设备，默认值：当前系统下 paddlepaddle 的默认 device。\n   - `verbose`: 如果使用，显示 logger 信息。\n\n\n- Python API\n   ```python\n   import paddle\n   from paddlespeech.cli.whisper import WhisperExecutor\n\n   whisper_executor = WhisperExecutor()\n\n   # 识别文本\n   text = whisper_executor(\n       model='whisper',\n       task='transcribe',\n       sample_rate=16000,\n       config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n       ckpt_path=None,\n       audio_file='./zh.wav',\n       device=paddle.get_device())\n   print('ASR Result: \\n{}'.format(text))\n\n    # 将语音翻译成英语\n   feature = whisper_executor(\n       model='whisper',\n       task='translate',\n       size='large', # For the translation function, is it better to use large or medium model\n       sample_rate=16000,\n       config=None,  # Set `config` and `ckpt_path` to None to use pretrained model.\n       ckpt_path=None,\n       audio_file='./zh.wav',\n       device=paddle.get_device())\n   print('Representation: \\n{}'.format(feature))\n   ```\n\n\n   输出：\n   ```bash\n   Transcribe Result:\n   Detected language: Chinese\n   [00:00.000 --> 00:05.000] 我认为跑步最重要的就是给我带来了身体健康\n   {'text': '我认为跑步最重要的就是给我带来了身体健康', 'segments': [{'id': 0, 'seek': 0, 'start': 0.0, 'end': 5.0, 'text': '我认为跑步最重要的就是给我带来了身体健康', 'tokens': [50364, 1654, 7422, 97, 13992, 32585, 31429, 8661, 24928, 1546, 5620, 49076, 4845, 99, 34912, 19847, 29485, 44201, 6346, 115, 50614], 'temperature': 0.0, 'avg_logprob': -0.23577967557040128, 'compression_ratio': 0.28169014084507044, 'no_speech_prob': 0.028302080929279327}], 'language': 'zh'}\n\n   Translate Result:\n   Detected language: Chinese\n   [00:00.000 --> 00:05.000]  I think the most important thing about running is that it brings me good health.\n   {'text': ' I think the most important thing about running is that it brings me good health.', 'segments': [{'id': 0, 'seek': 0, 'start': 0.0, 'end': 5.0, 'text': ' I think the most important thing about running is that it brings me good health.', 'tokens': [50364, 286, 519, 264, 881, 1021, 551, 466, 2614, 307, 300, 309, 5607, 385, 665, 1585, 13, 50614], 'temperature': 0.0, 'avg_logprob': -0.47945233395225123, 'compression_ratio': 1.095890410958904, 'no_speech_prob': 0.028302080929279327}], 'language': 'zh'}\n"
  },
  {
    "path": "demos/whisper/run.sh",
    "content": "#!/bin/bash\n\n# audio download\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\n\n# to recognize text \npaddlespeech whisper --task transcribe --input ./zh.wav\n\n# to recognize text and translate to English\npaddlespeech whisper --task translate --input ./zh.wav\n\n# to change model English-Only model\npaddlespeech whisper --lang en --size base --task transcribe  --input ./en.wav"
  },
  {
    "path": "docker/ubuntu16-gpu/Dockerfile",
    "content": "FROM nvidia/cuda:11.2.2-cudnn8-runtime-ubuntu16.04\n\nRUN echo \"deb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial universe \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates universe \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial multiverse \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates multiverse \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security universe \\n\\\ndeb [trusted=true] http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security multiverse\" > /etc/apt/sources.list\n\nRUN apt-get update && apt-get install -y inetutils-ping wget vim curl cmake git sox libsndfile1 libpng12-dev \\\n    libpng-dev swig libzip-dev openssl bc libflac* libgdk-pixbuf2.0-dev libpango1.0-dev libcairo2-dev \\\n    libgtk2.0-dev pkg-config zip unzip zlib1g-dev libreadline-dev libbz2-dev liblapack-dev libjpeg-turbo8-dev \\\n    sudo lrzsz libsqlite3-dev libx11-dev libsm6 apt-utils libopencv-dev libavcodec-dev libavformat-dev \\\n    libswscale-dev locales liblzma-dev python-lzma m4 libxext-dev strace libibverbs-dev libpcre3 libpcre3-dev \\\n    build-essential libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev xz-utils \\\n    libfreetype6-dev libxslt1-dev libxml2-dev libgeos-3.5.0 libgeos-dev && apt-get install -y --allow-downgrades \\\n    --allow-change-held-packages libnccl2 libnccl-dev && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata \\\n    && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && dpkg-reconfigure -f noninteractive tzdata && \\\n    cd /usr/lib/x86_64-linux-gnu && ln -s libcudnn.so.8 libcudnn.so && \\\n    cd /usr/local/cuda-11.2/targets/x86_64-linux/lib  && ln -s libcublas.so.11.4.1.1043 libcublas.so && \\\n    ln -s libcusolver.so.11.1.0.152 libcusolver.so && ln -s libcusparse.so.11 libcusparse.so && \\\n    ln -s libcufft.so.10.4.1.152 libcufft.so\n\nRUN echo \"set meta-flag on\" >> /etc/inputrc && echo \"set convert-meta off\" >> /etc/inputrc && \\\n    locale-gen en_US.UTF-8 && /sbin/ldconfig -v && groupadd -g 10001 paddle && \\\n    useradd -m -s /bin/bash -N -u 10001 paddle -g paddle && chmod g+w /etc/passwd && \\\n    echo \"paddle ALL=(ALL) NOPASSWD: ALL\" >> /etc/sudoers\n\nENV LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LANGUAGE=en_US.UTF-8 TZ=Asia/Shanghai\n\n# official download site: https://www.python.org/ftp/python/3.7.13/Python-3.7.13.tgz\nRUN wget https://cdn.npmmirror.com/binaries/python/3.7.13/Python-3.7.13.tgz && tar xvf Python-3.7.13.tgz && \\\n    cd Python-3.7.13 && ./configure --prefix=/home/paddle/python3.7 && make -j8 && make install && \\\n    rm -rf ../Python-3.7.13 ../Python-3.7.13.tgz && chown -R paddle:paddle /home/paddle/python3.7\n\nRUN cd /tmp && wget https://mirrors.sjtug.sjtu.edu.cn/gnu/gmp/gmp-6.1.0.tar.bz2 && tar xvf gmp-6.1.0.tar.bz2 && \\\n    cd gmp-6.1.0 && ./configure --prefix=/usr/local && make -j8 && make install && \\\n    rm -rf ../gmp-6.1.0.tar.bz2 ../gmp-6.1.0 && cd /tmp && \\\n    wget https://www.mpfr.org/mpfr-3.1.4/mpfr-3.1.4.tar.bz2 && tar xvf mpfr-3.1.4.tar.bz2 && cd mpfr-3.1.4 && \\\n    ./configure --prefix=/usr/local && make -j8 && make install && rm -rf ../mpfr-3.1.4.tar.bz2 ../mpfr-3.1.4 && \\\n    cd /tmp && wget https://mirrors.sjtug.sjtu.edu.cn/gnu/mpc/mpc-1.0.3.tar.gz && tar xvf mpc-1.0.3.tar.gz && \\\n    cd mpc-1.0.3 && ./configure --prefix=/usr/local && make -j8 && make install && \\\n    rm -rf ../mpc-1.0.3.tar.gz ../mpc-1.0.3 && cd /tmp && \\\n    wget http://www.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/isl-0.18.tar.bz2 && \\\n    tar xvf isl-0.18.tar.bz2 && cd isl-0.18 && ./configure --prefix=/usr/local && make -j8 && make install \\\n    && rm -rf ../isl-0.18.tar.bz2 ../isl-0.18 && cd /tmp && \\\n    wget http://mirrors.ustc.edu.cn/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz --no-check-certificate && \\\n    tar xvf gcc-8.2.0.tar.gz && cd gcc-8.2.0 && unset LIBRARY_PATH && ./configure --prefix=/home/paddle/gcc82 \\\n    --enable-threads=posix --disable-checking --disable-multilib --enable-languages=c,c++ --with-gmp=/usr/local \\\n    --with-mpfr=/usr/local --with-mpc=/usr/local --with-isl=/usr/local && make -j8 && make install && \\\n    rm -rf ../gcc-8.2.0.tar.gz ../gcc-8.2.0 && chown -R paddle:paddle /home/paddle/gcc82\n\nWORKDIR /home/paddle\nENV PATH=/home/paddle/python3.7/bin:/home/paddle/gcc82/bin:${PATH} \\\n    LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda-11.2/targets/x86_64-linux/lib:${LD_LIBRARY_PATH}\n\nRUN mkdir -p ~/.pip && echo \"[global]\" > ~/.pip/pip.conf && \\\n    echo \"index-url=https://mirror.baidu.com/pypi/simple\" >> ~/.pip/pip.conf && \\\n    echo \"trusted-host=mirror.baidu.com\" >> ~/.pip/pip.conf && \\\n    python3 -m pip install --upgrade pip && \\\n    pip install paddlepaddle-gpu==2.4.0rc0.post112 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html && \\\n    rm -rf ~/.cache/pip\n\nRUN git clone https://github.com/PaddlePaddle/PaddleSpeech.git && cd PaddleSpeech && \\\n    pip3 install pytest-runner paddleaudio -i https://pypi.tuna.tsinghua.edu.cn/simple && \\\n    pip3 install -e .[develop] -i https://pypi.tuna.tsinghua.edu.cn/simple && \\\n    pip3 install importlib-metadata==4.2.0 urllib3==1.25.10 -i https://pypi.tuna.tsinghua.edu.cn/simple && \\\n    rm -rf ~/.cache/pip && \\\n    sudo cp -f /home/paddle/gcc82/lib64/libstdc++.so.6.0.25 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 && \\\n    chown -R paddle:paddle /home/paddle/PaddleSpeech\n\nUSER paddle\nCMD ['bash']\n"
  },
  {
    "path": "docker/ubuntu18-cpu/Dockerfile",
    "content": "FROM registry.baidubce.com/paddlepaddle/paddle:2.2.2\nLABEL maintainer=\"paddlesl@baidu.com\"\n\nRUN apt-get update \\\n  && apt-get install libsndfile-dev libsndfile1 \\\n  && apt-get clean \\\n  && rm -rf /var/lib/apt/lists/*\n\nRUN git clone --depth 1 https://github.com/PaddlePaddle/PaddleSpeech.git /home/PaddleSpeech  \nRUN pip3 uninstall mccabe -y ; exit 0;\nRUN pip3 install multiprocess==0.70.12 importlib-metadata==4.2.0 dill==0.3.4\n\nWORKDIR /home/PaddleSpeech/\nRUN python setup.py bdist_wheel\nRUN pip install dist/*.whl -i https://pypi.tuna.tsinghua.edu.cn/simple\n\nCMD ['bash']\n"
  },
  {
    "path": "docker/ubuntu20-cpu/Dockerfile",
    "content": "FROM registry.baidubce.com/paddlepaddle/paddle:3.0.0b1\nLABEL maintainer=\"ext_paddle_oss@baidu.com\"\n\nRUN apt-get update \\\n  && apt-get install libsndfile-dev libsndfile1 \\\n  && apt-get clean \\\n  && rm -rf /var/lib/apt/lists/*\n\nRUN git clone --depth 1 https://github.com/PaddlePaddle/PaddleSpeech.git /home/PaddleSpeech  \nRUN pip3 uninstall mccabe -y ; exit 0;\nRUN pip3 install multiprocess==0.70.12 importlib-metadata==4.2.0 dill==0.3.4\n\nWORKDIR /home/PaddleSpeech/\nRUN python setup.py bdist_wheel\nRUN pip install dist/*.whl -i https://pypi.tuna.tsinghua.edu.cn/simple\n\nCMD ['bash']\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the environment for the first two.\nSPHINXOPTS    ?=\nSPHINXBUILD   ?= sphinx-build\nSOURCEDIR     = source\nBUILDDIR      = build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n"
  },
  {
    "path": "docs/requirements.txt",
    "content": "braceexpand\neditdistance\ng2p_en\ng2pM\nh5py\ninflect\njsonlines\nkaldiio\nkeyboard\nlibrosa==0.8.1\nloguru\nmatplotlib\nmyst-parser\nnara_wpe\nnumpydoc\nonnxruntime>=1.11.0\nopencc\npaddlenlp\n# use paddlepaddle == 2.3.* according to: https://github.com/PaddlePaddle/Paddle/issues/48243\npaddlepaddle>=2.2.2,<2.4.0\npaddlespeech_ctcdecoders\npaddlespeech_feat\npandas\npattern_singleton\nppdiffusers>=0.9.0\npraatio>=5.0.0, <=5.1.1\nprettytable\npypinyin-dict\npypinyin<=0.44.0\npython-dateutil\npyworld>=0.2.12\nrecommonmark>=0.5.0\nresampy\nsacrebleu\nsphinx\nsphinx-autobuild\nsphinx-markdown-tables\nsphinx_rtd_theme\ntextgrid\ntimer\nToJyutping==0.2.1\ntypeguard==2.13.3\nwebrtcvad\nwebsockets\nyacs~=0.1.8\nzhon\n"
  },
  {
    "path": "docs/source/_static/custom.css",
    "content": ".wy-nav-content {\n    max-width: 80%;\n}\n.table table{ background:#b9b9b9} \n.table table td{ background:#FFF; } \n"
  },
  {
    "path": "docs/source/api/modules.rst",
    "content": "paddlespeech\n============\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.features.layers.rst",
    "content": "paddlespeech.audio.features.layers module\n=========================================\n\n.. automodule:: paddlespeech.audio.features.layers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.features.rst",
    "content": "paddlespeech.audio.features package\n===================================\n\n.. automodule:: paddlespeech.audio.features\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.features.layers\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.io.rst",
    "content": "paddlespeech.audio.io package\n=============================\n\n.. automodule:: paddlespeech.audio.io\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.rst",
    "content": "paddlespeech.audio package\n==========================\n\n.. automodule:: paddlespeech.audio\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.features\n   paddlespeech.audio.functional\n   paddlespeech.audio.io\n   paddlespeech.audio.kaldi\n   paddlespeech.audio.metric\n   paddlespeech.audio.sox_effects\n   paddlespeech.audio.streamdata\n   paddlespeech.audio.text\n   paddlespeech.audio.transform\n   paddlespeech.audio.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.autodecode.rst",
    "content": "paddlespeech.audio.streamdata.autodecode module\n===============================================\n\n.. automodule:: paddlespeech.audio.streamdata.autodecode\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.cache.rst",
    "content": "paddlespeech.audio.streamdata.cache module\n==========================================\n\n.. automodule:: paddlespeech.audio.streamdata.cache\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.compat.rst",
    "content": "paddlespeech.audio.streamdata.compat module\n===========================================\n\n.. automodule:: paddlespeech.audio.streamdata.compat\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.extradatasets.rst",
    "content": "paddlespeech.audio.streamdata.extradatasets module\n==================================================\n\n.. automodule:: paddlespeech.audio.streamdata.extradatasets\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.filters.rst",
    "content": "paddlespeech.audio.streamdata.filters module\n============================================\n\n.. automodule:: paddlespeech.audio.streamdata.filters\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.gopen.rst",
    "content": "paddlespeech.audio.streamdata.gopen module\n==========================================\n\n.. automodule:: paddlespeech.audio.streamdata.gopen\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.handlers.rst",
    "content": "paddlespeech.audio.streamdata.handlers module\n=============================================\n\n.. automodule:: paddlespeech.audio.streamdata.handlers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.mix.rst",
    "content": "paddlespeech.audio.streamdata.mix module\n========================================\n\n.. automodule:: paddlespeech.audio.streamdata.mix\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.paddle_utils.rst",
    "content": "paddlespeech.audio.streamdata.paddle\\_utils module\n==================================================\n\n.. automodule:: paddlespeech.audio.streamdata.paddle_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.pipeline.rst",
    "content": "paddlespeech.audio.streamdata.pipeline module\n=============================================\n\n.. automodule:: paddlespeech.audio.streamdata.pipeline\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.rst",
    "content": "paddlespeech.audio.streamdata package\n=====================================\n\n.. automodule:: paddlespeech.audio.streamdata\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.streamdata.autodecode\n   paddlespeech.audio.streamdata.cache\n   paddlespeech.audio.streamdata.compat\n   paddlespeech.audio.streamdata.extradatasets\n   paddlespeech.audio.streamdata.filters\n   paddlespeech.audio.streamdata.gopen\n   paddlespeech.audio.streamdata.handlers\n   paddlespeech.audio.streamdata.mix\n   paddlespeech.audio.streamdata.paddle_utils\n   paddlespeech.audio.streamdata.pipeline\n   paddlespeech.audio.streamdata.shardlists\n   paddlespeech.audio.streamdata.tariterators\n   paddlespeech.audio.streamdata.utils\n   paddlespeech.audio.streamdata.writer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.shardlists.rst",
    "content": "paddlespeech.audio.streamdata.shardlists module\n===============================================\n\n.. automodule:: paddlespeech.audio.streamdata.shardlists\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.tariterators.rst",
    "content": "paddlespeech.audio.streamdata.tariterators module\n=================================================\n\n.. automodule:: paddlespeech.audio.streamdata.tariterators\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.utils.rst",
    "content": "paddlespeech.audio.streamdata.utils module\n==========================================\n\n.. automodule:: paddlespeech.audio.streamdata.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.streamdata.writer.rst",
    "content": "paddlespeech.audio.streamdata.writer module\n===========================================\n\n.. automodule:: paddlespeech.audio.streamdata.writer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.text.rst",
    "content": "paddlespeech.audio.text package\n===============================\n\n.. automodule:: paddlespeech.audio.text\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.text.text_featurizer\n   paddlespeech.audio.text.utility\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.text.text_featurizer.rst",
    "content": "paddlespeech.audio.text.text\\_featurizer module\n===============================================\n\n.. automodule:: paddlespeech.audio.text.text_featurizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.text.utility.rst",
    "content": "paddlespeech.audio.text.utility module\n======================================\n\n.. automodule:: paddlespeech.audio.text.utility\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.add_deltas.rst",
    "content": "paddlespeech.audio.transform.add\\_deltas module\n===============================================\n\n.. automodule:: paddlespeech.audio.transform.add_deltas\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.channel_selector.rst",
    "content": "paddlespeech.audio.transform.channel\\_selector module\n=====================================================\n\n.. automodule:: paddlespeech.audio.transform.channel_selector\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.cmvn.rst",
    "content": "paddlespeech.audio.transform.cmvn module\n========================================\n\n.. automodule:: paddlespeech.audio.transform.cmvn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.functional.rst",
    "content": "paddlespeech.audio.transform.functional module\n==============================================\n\n.. automodule:: paddlespeech.audio.transform.functional\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.perturb.rst",
    "content": "paddlespeech.audio.transform.perturb module\n===========================================\n\n.. automodule:: paddlespeech.audio.transform.perturb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.rst",
    "content": "paddlespeech.audio.transform package\n====================================\n\n.. automodule:: paddlespeech.audio.transform\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.transform.add_deltas\n   paddlespeech.audio.transform.channel_selector\n   paddlespeech.audio.transform.cmvn\n   paddlespeech.audio.transform.functional\n   paddlespeech.audio.transform.perturb\n   paddlespeech.audio.transform.spec_augment\n   paddlespeech.audio.transform.spectrogram\n   paddlespeech.audio.transform.transform_interface\n   paddlespeech.audio.transform.transformation\n   paddlespeech.audio.transform.wpe\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.spec_augment.rst",
    "content": "paddlespeech.audio.transform.spec\\_augment module\n=================================================\n\n.. automodule:: paddlespeech.audio.transform.spec_augment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.spectrogram.rst",
    "content": "paddlespeech.audio.transform.spectrogram module\n===============================================\n\n.. automodule:: paddlespeech.audio.transform.spectrogram\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.transform_interface.rst",
    "content": "paddlespeech.audio.transform.transform\\_interface module\n========================================================\n\n.. automodule:: paddlespeech.audio.transform.transform_interface\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.transformation.rst",
    "content": "paddlespeech.audio.transform.transformation module\n==================================================\n\n.. automodule:: paddlespeech.audio.transform.transformation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.transform.wpe.rst",
    "content": "paddlespeech.audio.transform.wpe module\n=======================================\n\n.. automodule:: paddlespeech.audio.transform.wpe\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.check_kwargs.rst",
    "content": "paddlespeech.audio.utils.check\\_kwargs module\n=============================================\n\n.. automodule:: paddlespeech.audio.utils.check_kwargs\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.download.rst",
    "content": "paddlespeech.audio.utils.download module\n========================================\n\n.. automodule:: paddlespeech.audio.utils.download\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.dynamic_import.rst",
    "content": "paddlespeech.audio.utils.dynamic\\_import module\n===============================================\n\n.. automodule:: paddlespeech.audio.utils.dynamic_import\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.error.rst",
    "content": "paddlespeech.audio.utils.error module\n=====================================\n\n.. automodule:: paddlespeech.audio.utils.error\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.log.rst",
    "content": "paddlespeech.audio.utils.log module\n===================================\n\n.. automodule:: paddlespeech.audio.utils.log\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.numeric.rst",
    "content": "paddlespeech.audio.utils.numeric module\n=======================================\n\n.. automodule:: paddlespeech.audio.utils.numeric\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.rst",
    "content": "paddlespeech.audio.utils package\n================================\n\n.. automodule:: paddlespeech.audio.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio.utils.check_kwargs\n   paddlespeech.audio.utils.download\n   paddlespeech.audio.utils.dynamic_import\n   paddlespeech.audio.utils.error\n   paddlespeech.audio.utils.log\n   paddlespeech.audio.utils.numeric\n   paddlespeech.audio.utils.sox_utils\n   paddlespeech.audio.utils.tensor_utils\n   paddlespeech.audio.utils.time\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.tensor_utils.rst",
    "content": "paddlespeech.audio.utils.tensor\\_utils module\n=============================================\n\n.. automodule:: paddlespeech.audio.utils.tensor_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.audio.utils.time.rst",
    "content": "paddlespeech.audio.utils.time module\n====================================\n\n.. automodule:: paddlespeech.audio.utils.time\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.asr.infer.rst",
    "content": "paddlespeech.cli.asr.infer module\n=================================\n\n.. automodule:: paddlespeech.cli.asr.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.asr.rst",
    "content": "paddlespeech.cli.asr package\n============================\n\n.. automodule:: paddlespeech.cli.asr\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.asr.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.base_commands.rst",
    "content": "paddlespeech.cli.base\\_commands module\n======================================\n\n.. automodule:: paddlespeech.cli.base_commands\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.cls.infer.rst",
    "content": "paddlespeech.cli.cls.infer module\n=================================\n\n.. automodule:: paddlespeech.cli.cls.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.cls.rst",
    "content": "paddlespeech.cli.cls package\n============================\n\n.. automodule:: paddlespeech.cli.cls\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.cls.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.download.rst",
    "content": "paddlespeech.cli.download module\n================================\n\n.. automodule:: paddlespeech.cli.download\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.entry.rst",
    "content": "paddlespeech.cli.entry module\n=============================\n\n.. automodule:: paddlespeech.cli.entry\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.executor.rst",
    "content": "paddlespeech.cli.executor module\n================================\n\n.. automodule:: paddlespeech.cli.executor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.kws.infer.rst",
    "content": "paddlespeech.cli.kws.infer module\n=================================\n\n.. automodule:: paddlespeech.cli.kws.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.kws.rst",
    "content": "paddlespeech.cli.kws package\n============================\n\n.. automodule:: paddlespeech.cli.kws\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.kws.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.log.rst",
    "content": "paddlespeech.cli.log module\n===========================\n\n.. automodule:: paddlespeech.cli.log\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.rst",
    "content": "paddlespeech.cli package\n========================\n\n.. automodule:: paddlespeech.cli\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.asr\n   paddlespeech.cli.cls\n   paddlespeech.cli.kws\n   paddlespeech.cli.st\n   paddlespeech.cli.text\n   paddlespeech.cli.tts\n   paddlespeech.cli.vector\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.base_commands\n   paddlespeech.cli.download\n   paddlespeech.cli.entry\n   paddlespeech.cli.executor\n   paddlespeech.cli.log\n   paddlespeech.cli.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.st.infer.rst",
    "content": "paddlespeech.cli.st.infer module\n================================\n\n.. automodule:: paddlespeech.cli.st.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.st.rst",
    "content": "paddlespeech.cli.st package\n===========================\n\n.. automodule:: paddlespeech.cli.st\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.st.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.text.infer.rst",
    "content": "paddlespeech.cli.text.infer module\n==================================\n\n.. automodule:: paddlespeech.cli.text.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.text.rst",
    "content": "paddlespeech.cli.text package\n=============================\n\n.. automodule:: paddlespeech.cli.text\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.text.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.tts.infer.rst",
    "content": "paddlespeech.cli.tts.infer module\n=================================\n\n.. automodule:: paddlespeech.cli.tts.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.tts.rst",
    "content": "paddlespeech.cli.tts package\n============================\n\n.. automodule:: paddlespeech.cli.tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.tts.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.utils.rst",
    "content": "paddlespeech.cli.utils module\n=============================\n\n.. automodule:: paddlespeech.cli.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.vector.infer.rst",
    "content": "paddlespeech.cli.vector.infer module\n====================================\n\n.. automodule:: paddlespeech.cli.vector.infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cli.vector.rst",
    "content": "paddlespeech.cli.vector package\n===============================\n\n.. automodule:: paddlespeech.cli.vector\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cli.vector.infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.exps.panns.deploy.rst",
    "content": "paddlespeech.cls.exps.panns.deploy package\n==========================================\n\n.. automodule:: paddlespeech.cls.exps.panns.deploy\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.exps.panns.rst",
    "content": "paddlespeech.cls.exps.panns package\n===================================\n\n.. automodule:: paddlespeech.cls.exps.panns\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cls.exps.panns.deploy\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.exps.rst",
    "content": "paddlespeech.cls.exps package\n=============================\n\n.. automodule:: paddlespeech.cls.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cls.exps.panns\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.models.panns.classifier.rst",
    "content": "paddlespeech.cls.models.panns.classifier module\n===============================================\n\n.. automodule:: paddlespeech.cls.models.panns.classifier\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.models.panns.panns.rst",
    "content": "paddlespeech.cls.models.panns.panns module\n==========================================\n\n.. automodule:: paddlespeech.cls.models.panns.panns\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.models.panns.rst",
    "content": "paddlespeech.cls.models.panns package\n=====================================\n\n.. automodule:: paddlespeech.cls.models.panns\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cls.models.panns.classifier\n   paddlespeech.cls.models.panns.panns\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.models.rst",
    "content": "paddlespeech.cls.models package\n===============================\n\n.. automodule:: paddlespeech.cls.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cls.models.panns\n"
  },
  {
    "path": "docs/source/api/paddlespeech.cls.rst",
    "content": "paddlespeech.cls package\n========================\n\n.. automodule:: paddlespeech.cls\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.cls.exps\n   paddlespeech.cls.models\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.collate.rst",
    "content": "paddlespeech.kws.exps.mdtc.collate module\n=========================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc.collate\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.compute_det.rst",
    "content": "paddlespeech.kws.exps.mdtc.compute\\_det module\n==============================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc.compute_det\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.plot_det_curve.rst",
    "content": "paddlespeech.kws.exps.mdtc.plot\\_det\\_curve module\n==================================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc.plot_det_curve\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.rst",
    "content": "paddlespeech.kws.exps.mdtc package\n==================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.kws.exps.mdtc.collate\n   paddlespeech.kws.exps.mdtc.compute_det\n   paddlespeech.kws.exps.mdtc.score\n   paddlespeech.kws.exps.mdtc.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.score.rst",
    "content": "paddlespeech.kws.exps.mdtc.score module\n=======================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc.score\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.mdtc.train.rst",
    "content": "paddlespeech.kws.exps.mdtc.train module\n=======================================\n\n.. automodule:: paddlespeech.kws.exps.mdtc.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.exps.rst",
    "content": "paddlespeech.kws.exps package\n=============================\n\n.. automodule:: paddlespeech.kws.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.kws.exps.mdtc\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.models.loss.rst",
    "content": "paddlespeech.kws.models.loss module\n===================================\n\n.. automodule:: paddlespeech.kws.models.loss\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.models.mdtc.rst",
    "content": "paddlespeech.kws.models.mdtc module\n===================================\n\n.. automodule:: paddlespeech.kws.models.mdtc\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.models.rst",
    "content": "paddlespeech.kws.models package\n===============================\n\n.. automodule:: paddlespeech.kws.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.kws.models.loss\n   paddlespeech.kws.models.mdtc\n"
  },
  {
    "path": "docs/source/api/paddlespeech.kws.rst",
    "content": "paddlespeech.kws package\n========================\n\n.. automodule:: paddlespeech.kws\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.kws.exps\n   paddlespeech.kws.models\n"
  },
  {
    "path": "docs/source/api/paddlespeech.resource.model_alias.rst",
    "content": "paddlespeech.resource.model\\_alias module\n=========================================\n\n.. automodule:: paddlespeech.resource.model_alias\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.resource.pretrained_models.rst",
    "content": "paddlespeech.resource.pretrained\\_models module\n===============================================\n\n.. automodule:: paddlespeech.resource.pretrained_models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.resource.resource.rst",
    "content": "paddlespeech.resource.resource module\n=====================================\n\n.. automodule:: paddlespeech.resource.resource\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.resource.rst",
    "content": "paddlespeech.resource package\n=============================\n\n.. automodule:: paddlespeech.resource\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.resource.model_alias\n   paddlespeech.resource.pretrained_models\n   paddlespeech.resource.resource\n"
  },
  {
    "path": "docs/source/api/paddlespeech.rst",
    "content": "paddlespeech package\n====================\n\n.. automodule:: paddlespeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.audio\n   paddlespeech.cli\n   paddlespeech.cls\n   paddlespeech.kws\n   paddlespeech.resource\n   paddlespeech.s2t\n   paddlespeech.server\n   paddlespeech.t2s\n   paddlespeech.text\n   paddlespeech.utils\n   paddlespeech.vector\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.version\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.beam_search.batch_beam_search.rst",
    "content": "paddlespeech.s2t.decoders.beam\\_search.batch\\_beam\\_search module\n=================================================================\n\n.. automodule:: paddlespeech.s2t.decoders.beam_search.batch_beam_search\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.beam_search.beam_search.rst",
    "content": "paddlespeech.s2t.decoders.beam\\_search.beam\\_search module\n==========================================================\n\n.. automodule:: paddlespeech.s2t.decoders.beam_search.beam_search\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.beam_search.rst",
    "content": "paddlespeech.s2t.decoders.beam\\_search package\n==============================================\n\n.. automodule:: paddlespeech.s2t.decoders.beam_search\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders.beam_search.batch_beam_search\n   paddlespeech.s2t.decoders.beam_search.beam_search\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.ctcdecoder.decoders_deprecated.rst",
    "content": "paddlespeech.s2t.decoders.ctcdecoder.decoders\\_deprecated module\n================================================================\n\n.. automodule:: paddlespeech.s2t.decoders.ctcdecoder.decoders_deprecated\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.ctcdecoder.rst",
    "content": "paddlespeech.s2t.decoders.ctcdecoder package\n============================================\n\n.. automodule:: paddlespeech.s2t.decoders.ctcdecoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders.ctcdecoder.decoders_deprecated\n   paddlespeech.s2t.decoders.ctcdecoder.swig_wrapper\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.ctcdecoder.swig_wrapper.rst",
    "content": "paddlespeech.s2t.decoders.ctcdecoder.swig\\_wrapper module\n=========================================================\n\n.. automodule:: paddlespeech.s2t.decoders.ctcdecoder.swig_wrapper\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.recog.rst",
    "content": "paddlespeech.s2t.decoders.recog module\n======================================\n\n.. automodule:: paddlespeech.s2t.decoders.recog\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.rst",
    "content": "paddlespeech.s2t.decoders package\n=================================\n\n.. automodule:: paddlespeech.s2t.decoders\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders.beam_search\n   paddlespeech.s2t.decoders.ctcdecoder\n   paddlespeech.s2t.decoders.scorers\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders.recog\n   paddlespeech.s2t.decoders.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.scorers.ctc.rst",
    "content": "paddlespeech.s2t.decoders.scorers.ctc module\n============================================\n\n.. automodule:: paddlespeech.s2t.decoders.scorers.ctc\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.scorers.ctc_prefix_score.rst",
    "content": "paddlespeech.s2t.decoders.scorers.ctc\\_prefix\\_score module\n===========================================================\n\n.. automodule:: paddlespeech.s2t.decoders.scorers.ctc_prefix_score\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.scorers.length_bonus.rst",
    "content": "paddlespeech.s2t.decoders.scorers.length\\_bonus module\n======================================================\n\n.. automodule:: paddlespeech.s2t.decoders.scorers.length_bonus\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.scorers.rst",
    "content": "paddlespeech.s2t.decoders.scorers package\n=========================================\n\n.. automodule:: paddlespeech.s2t.decoders.scorers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders.scorers.ctc\n   paddlespeech.s2t.decoders.scorers.ctc_prefix_score\n   paddlespeech.s2t.decoders.scorers.length_bonus\n   paddlespeech.s2t.decoders.scorers.scorer_interface\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.scorers.scorer_interface.rst",
    "content": "paddlespeech.s2t.decoders.scorers.scorer\\_interface module\n==========================================================\n\n.. automodule:: paddlespeech.s2t.decoders.scorers.scorer_interface\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.decoders.utils.rst",
    "content": "paddlespeech.s2t.decoders.utils module\n======================================\n\n.. automodule:: paddlespeech.s2t.decoders.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.deploy.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.deploy package\n====================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.deploy\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2.bin.deploy.runtime\n   paddlespeech.s2t.exps.deepspeech2.bin.deploy.server\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.deploy.runtime.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.deploy.runtime module\n===========================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.deploy.runtime\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.deploy.server.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.deploy.server module\n==========================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.deploy.server\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.export.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.export module\n===================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.export\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin package\n=============================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2.bin.deploy\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2.bin.export\n   paddlespeech.s2t.exps.deepspeech2.bin.test\n   paddlespeech.s2t.exps.deepspeech2.bin.test_export\n   paddlespeech.s2t.exps.deepspeech2.bin.test_wav\n   paddlespeech.s2t.exps.deepspeech2.bin.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.test.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.test module\n=================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.test\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.test_export.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.test\\_export module\n=========================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.test_export\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.test_wav.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.test\\_wav module\n======================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.test_wav\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.bin.train.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.bin.train module\n==================================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.bin.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.model.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2.model module\n==============================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2.model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.deepspeech2.rst",
    "content": "paddlespeech.s2t.exps.deepspeech2 package\n=========================================\n\n.. automodule:: paddlespeech.s2t.exps.deepspeech2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2.bin\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2.model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.rst",
    "content": "paddlespeech.s2t.exps package\n=============================\n\n.. automodule:: paddlespeech.s2t.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.deepspeech2\n   paddlespeech.s2t.exps.u2\n   paddlespeech.s2t.exps.u2_kaldi\n   paddlespeech.s2t.exps.u2_st\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.alignment.rst",
    "content": "paddlespeech.s2t.exps.u2.bin.alignment module\n=============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin.alignment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.export.rst",
    "content": "paddlespeech.s2t.exps.u2.bin.export module\n==========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin.export\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.rst",
    "content": "paddlespeech.s2t.exps.u2.bin package\n====================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2.bin.alignment\n   paddlespeech.s2t.exps.u2.bin.export\n   paddlespeech.s2t.exps.u2.bin.test\n   paddlespeech.s2t.exps.u2.bin.test_wav\n   paddlespeech.s2t.exps.u2.bin.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.test.rst",
    "content": "paddlespeech.s2t.exps.u2.bin.test module\n========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin.test\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.test_wav.rst",
    "content": "paddlespeech.s2t.exps.u2.bin.test\\_wav module\n=============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin.test_wav\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.bin.train.rst",
    "content": "paddlespeech.s2t.exps.u2.bin.train module\n=========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.bin.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.model.rst",
    "content": "paddlespeech.s2t.exps.u2.model module\n=====================================\n\n.. automodule:: paddlespeech.s2t.exps.u2.model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2.rst",
    "content": "paddlespeech.s2t.exps.u2 package\n================================\n\n.. automodule:: paddlespeech.s2t.exps.u2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2.bin\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2.model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_kaldi.bin.rst",
    "content": "paddlespeech.s2t.exps.u2\\_kaldi.bin package\n===========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_kaldi.bin\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_kaldi.bin.test\n   paddlespeech.s2t.exps.u2_kaldi.bin.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_kaldi.bin.test.rst",
    "content": "paddlespeech.s2t.exps.u2\\_kaldi.bin.test module\n===============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_kaldi.bin.test\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_kaldi.bin.train.rst",
    "content": "paddlespeech.s2t.exps.u2\\_kaldi.bin.train module\n================================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_kaldi.bin.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_kaldi.model.rst",
    "content": "paddlespeech.s2t.exps.u2\\_kaldi.model module\n============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_kaldi.model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_kaldi.rst",
    "content": "paddlespeech.s2t.exps.u2\\_kaldi package\n=======================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_kaldi\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_kaldi.bin\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_kaldi.model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.bin.export.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st.bin.export module\n==============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st.bin.export\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.bin.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st.bin package\n========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st.bin\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_st.bin.export\n   paddlespeech.s2t.exps.u2_st.bin.test\n   paddlespeech.s2t.exps.u2_st.bin.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.bin.test.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st.bin.test module\n============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st.bin.test\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.bin.train.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st.bin.train module\n=============================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st.bin.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.model.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st.model module\n=========================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st.model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.exps.u2_st.rst",
    "content": "paddlespeech.s2t.exps.u2\\_st package\n====================================\n\n.. automodule:: paddlespeech.s2t.exps.u2_st\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_st.bin\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.exps.u2_st.model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.audio.rst",
    "content": "paddlespeech.s2t.frontend.audio module\n======================================\n\n.. automodule:: paddlespeech.s2t.frontend.audio\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.augmentation.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.augmentation module\n=======================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.augmentation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.base.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.base module\n===============================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.base\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.impulse_response.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.impulse\\_response module\n============================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.impulse_response\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.noise_perturb.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.noise\\_perturb module\n=========================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.noise_perturb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.online_bayesian_normalization.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.online\\_bayesian\\_normalization module\n==========================================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.online_bayesian_normalization\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.resample.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.resample module\n===================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.resample\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.rst",
    "content": "paddlespeech.s2t.frontend.augmentor package\n===========================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.frontend.augmentor.augmentation\n   paddlespeech.s2t.frontend.augmentor.base\n   paddlespeech.s2t.frontend.augmentor.impulse_response\n   paddlespeech.s2t.frontend.augmentor.noise_perturb\n   paddlespeech.s2t.frontend.augmentor.online_bayesian_normalization\n   paddlespeech.s2t.frontend.augmentor.resample\n   paddlespeech.s2t.frontend.augmentor.shift_perturb\n   paddlespeech.s2t.frontend.augmentor.spec_augment\n   paddlespeech.s2t.frontend.augmentor.speed_perturb\n   paddlespeech.s2t.frontend.augmentor.volume_perturb\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.shift_perturb.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.shift\\_perturb module\n=========================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.shift_perturb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.spec_augment.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.spec\\_augment module\n========================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.spec_augment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.speed_perturb.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.speed\\_perturb module\n=========================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.speed_perturb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.augmentor.volume_perturb.rst",
    "content": "paddlespeech.s2t.frontend.augmentor.volume\\_perturb module\n==========================================================\n\n.. automodule:: paddlespeech.s2t.frontend.augmentor.volume_perturb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.featurizer.audio_featurizer.rst",
    "content": "paddlespeech.s2t.frontend.featurizer.audio\\_featurizer module\n=============================================================\n\n.. automodule:: paddlespeech.s2t.frontend.featurizer.audio_featurizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.featurizer.rst",
    "content": "paddlespeech.s2t.frontend.featurizer package\n============================================\n\n.. automodule:: paddlespeech.s2t.frontend.featurizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.frontend.featurizer.audio_featurizer\n   paddlespeech.s2t.frontend.featurizer.speech_featurizer\n   paddlespeech.s2t.frontend.featurizer.text_featurizer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.featurizer.speech_featurizer.rst",
    "content": "paddlespeech.s2t.frontend.featurizer.speech\\_featurizer module\n==============================================================\n\n.. automodule:: paddlespeech.s2t.frontend.featurizer.speech_featurizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.featurizer.text_featurizer.rst",
    "content": "paddlespeech.s2t.frontend.featurizer.text\\_featurizer module\n============================================================\n\n.. automodule:: paddlespeech.s2t.frontend.featurizer.text_featurizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.normalizer.rst",
    "content": "paddlespeech.s2t.frontend.normalizer module\n===========================================\n\n.. automodule:: paddlespeech.s2t.frontend.normalizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.rst",
    "content": "paddlespeech.s2t.frontend package\n=================================\n\n.. automodule:: paddlespeech.s2t.frontend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.frontend.augmentor\n   paddlespeech.s2t.frontend.featurizer\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.frontend.audio\n   paddlespeech.s2t.frontend.normalizer\n   paddlespeech.s2t.frontend.speech\n   paddlespeech.s2t.frontend.utility\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.speech.rst",
    "content": "paddlespeech.s2t.frontend.speech module\n=======================================\n\n.. automodule:: paddlespeech.s2t.frontend.speech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.frontend.utility.rst",
    "content": "paddlespeech.s2t.frontend.utility module\n========================================\n\n.. automodule:: paddlespeech.s2t.frontend.utility\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.batchfy.rst",
    "content": "paddlespeech.s2t.io.batchfy module\n==================================\n\n.. automodule:: paddlespeech.s2t.io.batchfy\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.collator.rst",
    "content": "paddlespeech.s2t.io.collator module\n===================================\n\n.. automodule:: paddlespeech.s2t.io.collator\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.converter.rst",
    "content": "paddlespeech.s2t.io.converter module\n====================================\n\n.. automodule:: paddlespeech.s2t.io.converter\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.dataloader.rst",
    "content": "paddlespeech.s2t.io.dataloader module\n=====================================\n\n.. automodule:: paddlespeech.s2t.io.dataloader\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.dataset.rst",
    "content": "paddlespeech.s2t.io.dataset module\n==================================\n\n.. automodule:: paddlespeech.s2t.io.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.reader.rst",
    "content": "paddlespeech.s2t.io.reader module\n=================================\n\n.. automodule:: paddlespeech.s2t.io.reader\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.rst",
    "content": "paddlespeech.s2t.io package\n===========================\n\n.. automodule:: paddlespeech.s2t.io\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.io.batchfy\n   paddlespeech.s2t.io.collator\n   paddlespeech.s2t.io.converter\n   paddlespeech.s2t.io.dataloader\n   paddlespeech.s2t.io.dataset\n   paddlespeech.s2t.io.reader\n   paddlespeech.s2t.io.sampler\n   paddlespeech.s2t.io.utility\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.sampler.rst",
    "content": "paddlespeech.s2t.io.sampler module\n==================================\n\n.. automodule:: paddlespeech.s2t.io.sampler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.io.utility.rst",
    "content": "paddlespeech.s2t.io.utility module\n==================================\n\n.. automodule:: paddlespeech.s2t.io.utility\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.asr_interface.rst",
    "content": "paddlespeech.s2t.models.asr\\_interface module\n=============================================\n\n.. automodule:: paddlespeech.s2t.models.asr_interface\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.ds2.conv.rst",
    "content": "paddlespeech.s2t.models.ds2.conv module\n=======================================\n\n.. automodule:: paddlespeech.s2t.models.ds2.conv\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.ds2.deepspeech2.rst",
    "content": "paddlespeech.s2t.models.ds2.deepspeech2 module\n==============================================\n\n.. automodule:: paddlespeech.s2t.models.ds2.deepspeech2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.ds2.rst",
    "content": "paddlespeech.s2t.models.ds2 package\n===================================\n\n.. automodule:: paddlespeech.s2t.models.ds2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.ds2.conv\n   paddlespeech.s2t.models.ds2.deepspeech2\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.lm.dataset.rst",
    "content": "paddlespeech.s2t.models.lm.dataset module\n=========================================\n\n.. automodule:: paddlespeech.s2t.models.lm.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.lm.rst",
    "content": "paddlespeech.s2t.models.lm package\n==================================\n\n.. automodule:: paddlespeech.s2t.models.lm\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.lm.dataset\n   paddlespeech.s2t.models.lm.transformer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.lm.transformer.rst",
    "content": "paddlespeech.s2t.models.lm.transformer module\n=============================================\n\n.. automodule:: paddlespeech.s2t.models.lm.transformer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.lm_interface.rst",
    "content": "paddlespeech.s2t.models.lm\\_interface module\n============================================\n\n.. automodule:: paddlespeech.s2t.models.lm_interface\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.rst",
    "content": "paddlespeech.s2t.models package\n===============================\n\n.. automodule:: paddlespeech.s2t.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.ds2\n   paddlespeech.s2t.models.lm\n   paddlespeech.s2t.models.u2\n   paddlespeech.s2t.models.u2_st\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.asr_interface\n   paddlespeech.s2t.models.lm_interface\n   paddlespeech.s2t.models.st_interface\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.st_interface.rst",
    "content": "paddlespeech.s2t.models.st\\_interface module\n============================================\n\n.. automodule:: paddlespeech.s2t.models.st_interface\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.u2.rst",
    "content": "paddlespeech.s2t.models.u2 package\n==================================\n\n.. automodule:: paddlespeech.s2t.models.u2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.u2.u2\n   paddlespeech.s2t.models.u2.updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.u2.u2.rst",
    "content": "paddlespeech.s2t.models.u2.u2 module\n====================================\n\n.. automodule:: paddlespeech.s2t.models.u2.u2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.u2.updater.rst",
    "content": "paddlespeech.s2t.models.u2.updater module\n=========================================\n\n.. automodule:: paddlespeech.s2t.models.u2.updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.u2_st.rst",
    "content": "paddlespeech.s2t.models.u2\\_st package\n======================================\n\n.. automodule:: paddlespeech.s2t.models.u2_st\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.models.u2_st.u2_st\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.models.u2_st.u2_st.rst",
    "content": "paddlespeech.s2t.models.u2\\_st.u2\\_st module\n============================================\n\n.. automodule:: paddlespeech.s2t.models.u2_st.u2_st\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.activation.rst",
    "content": "paddlespeech.s2t.modules.activation module\n==========================================\n\n.. automodule:: paddlespeech.s2t.modules.activation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.align.rst",
    "content": "paddlespeech.s2t.modules.align module\n=====================================\n\n.. automodule:: paddlespeech.s2t.modules.align\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.attention.rst",
    "content": "paddlespeech.s2t.modules.attention module\n=========================================\n\n.. automodule:: paddlespeech.s2t.modules.attention\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.cmvn.rst",
    "content": "paddlespeech.s2t.modules.cmvn module\n====================================\n\n.. automodule:: paddlespeech.s2t.modules.cmvn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.conformer_convolution.rst",
    "content": "paddlespeech.s2t.modules.conformer\\_convolution module\n======================================================\n\n.. automodule:: paddlespeech.s2t.modules.conformer_convolution\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.crf.rst",
    "content": "paddlespeech.s2t.modules.crf module\n===================================\n\n.. automodule:: paddlespeech.s2t.modules.crf\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.ctc.rst",
    "content": "paddlespeech.s2t.modules.ctc module\n===================================\n\n.. automodule:: paddlespeech.s2t.modules.ctc\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.decoder.rst",
    "content": "paddlespeech.s2t.modules.decoder module\n=======================================\n\n.. automodule:: paddlespeech.s2t.modules.decoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.decoder_layer.rst",
    "content": "paddlespeech.s2t.modules.decoder\\_layer module\n==============================================\n\n.. automodule:: paddlespeech.s2t.modules.decoder_layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.embedding.rst",
    "content": "paddlespeech.s2t.modules.embedding module\n=========================================\n\n.. automodule:: paddlespeech.s2t.modules.embedding\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.encoder.rst",
    "content": "paddlespeech.s2t.modules.encoder module\n=======================================\n\n.. automodule:: paddlespeech.s2t.modules.encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.encoder_layer.rst",
    "content": "paddlespeech.s2t.modules.encoder\\_layer module\n==============================================\n\n.. automodule:: paddlespeech.s2t.modules.encoder_layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.initializer.rst",
    "content": "paddlespeech.s2t.modules.initializer module\n===========================================\n\n.. automodule:: paddlespeech.s2t.modules.initializer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.loss.rst",
    "content": "paddlespeech.s2t.modules.loss module\n====================================\n\n.. automodule:: paddlespeech.s2t.modules.loss\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.mask.rst",
    "content": "paddlespeech.s2t.modules.mask module\n====================================\n\n.. automodule:: paddlespeech.s2t.modules.mask\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.positionwise_feed_forward.rst",
    "content": "paddlespeech.s2t.modules.positionwise\\_feed\\_forward module\n===========================================================\n\n.. automodule:: paddlespeech.s2t.modules.positionwise_feed_forward\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.rst",
    "content": "paddlespeech.s2t.modules package\n================================\n\n.. automodule:: paddlespeech.s2t.modules\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.modules.activation\n   paddlespeech.s2t.modules.align\n   paddlespeech.s2t.modules.attention\n   paddlespeech.s2t.modules.cmvn\n   paddlespeech.s2t.modules.conformer_convolution\n   paddlespeech.s2t.modules.crf\n   paddlespeech.s2t.modules.ctc\n   paddlespeech.s2t.modules.decoder\n   paddlespeech.s2t.modules.decoder_layer\n   paddlespeech.s2t.modules.embedding\n   paddlespeech.s2t.modules.encoder\n   paddlespeech.s2t.modules.encoder_layer\n   paddlespeech.s2t.modules.initializer\n   paddlespeech.s2t.modules.loss\n   paddlespeech.s2t.modules.mask\n   paddlespeech.s2t.modules.positionwise_feed_forward\n   paddlespeech.s2t.modules.subsampling\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.modules.subsampling.rst",
    "content": "paddlespeech.s2t.modules.subsampling module\n===========================================\n\n.. automodule:: paddlespeech.s2t.modules.subsampling\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.rst",
    "content": "paddlespeech.s2t package\n========================\n\n.. automodule:: paddlespeech.s2t\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.decoders\n   paddlespeech.s2t.exps\n   paddlespeech.s2t.frontend\n   paddlespeech.s2t.io\n   paddlespeech.s2t.models\n   paddlespeech.s2t.modules\n   paddlespeech.s2t.training\n   paddlespeech.s2t.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.cli.rst",
    "content": "paddlespeech.s2t.training.cli module\n====================================\n\n.. automodule:: paddlespeech.s2t.training.cli\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.extensions.evaluator.rst",
    "content": "paddlespeech.s2t.training.extensions.evaluator module\n=====================================================\n\n.. automodule:: paddlespeech.s2t.training.extensions.evaluator\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.extensions.extension.rst",
    "content": "paddlespeech.s2t.training.extensions.extension module\n=====================================================\n\n.. automodule:: paddlespeech.s2t.training.extensions.extension\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.extensions.plot.rst",
    "content": "paddlespeech.s2t.training.extensions.plot module\n================================================\n\n.. automodule:: paddlespeech.s2t.training.extensions.plot\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.extensions.rst",
    "content": "paddlespeech.s2t.training.extensions package\n============================================\n\n.. automodule:: paddlespeech.s2t.training.extensions\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.training.extensions.evaluator\n   paddlespeech.s2t.training.extensions.extension\n   paddlespeech.s2t.training.extensions.plot\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.gradclip.rst",
    "content": "paddlespeech.s2t.training.gradclip module\n=========================================\n\n.. automodule:: paddlespeech.s2t.training.gradclip\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.optimizer.rst",
    "content": "paddlespeech.s2t.training.optimizer module\n==========================================\n\n.. automodule:: paddlespeech.s2t.training.optimizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.reporter.rst",
    "content": "paddlespeech.s2t.training.reporter module\n=========================================\n\n.. automodule:: paddlespeech.s2t.training.reporter\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.rst",
    "content": "paddlespeech.s2t.training package\n=================================\n\n.. automodule:: paddlespeech.s2t.training\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.training.extensions\n   paddlespeech.s2t.training.triggers\n   paddlespeech.s2t.training.updaters\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.training.cli\n   paddlespeech.s2t.training.gradclip\n   paddlespeech.s2t.training.optimizer\n   paddlespeech.s2t.training.reporter\n   paddlespeech.s2t.training.scheduler\n   paddlespeech.s2t.training.timer\n   paddlespeech.s2t.training.trainer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.scheduler.rst",
    "content": "paddlespeech.s2t.training.scheduler module\n==========================================\n\n.. automodule:: paddlespeech.s2t.training.scheduler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.timer.rst",
    "content": "paddlespeech.s2t.training.timer module\n======================================\n\n.. automodule:: paddlespeech.s2t.training.timer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.trainer.rst",
    "content": "paddlespeech.s2t.training.trainer module\n========================================\n\n.. automodule:: paddlespeech.s2t.training.trainer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.compare_value_trigger.rst",
    "content": "paddlespeech.s2t.training.triggers.compare\\_value\\_trigger module\n=================================================================\n\n.. automodule:: paddlespeech.s2t.training.triggers.compare_value_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.interval_trigger.rst",
    "content": "paddlespeech.s2t.training.triggers.interval\\_trigger module\n===========================================================\n\n.. automodule:: paddlespeech.s2t.training.triggers.interval_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.limit_trigger.rst",
    "content": "paddlespeech.s2t.training.triggers.limit\\_trigger module\n========================================================\n\n.. automodule:: paddlespeech.s2t.training.triggers.limit_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.rst",
    "content": "paddlespeech.s2t.training.triggers package\n==========================================\n\n.. automodule:: paddlespeech.s2t.training.triggers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.training.triggers.compare_value_trigger\n   paddlespeech.s2t.training.triggers.interval_trigger\n   paddlespeech.s2t.training.triggers.limit_trigger\n   paddlespeech.s2t.training.triggers.time_trigger\n   paddlespeech.s2t.training.triggers.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.time_trigger.rst",
    "content": "paddlespeech.s2t.training.triggers.time\\_trigger module\n=======================================================\n\n.. automodule:: paddlespeech.s2t.training.triggers.time_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.triggers.utils.rst",
    "content": "paddlespeech.s2t.training.triggers.utils module\n===============================================\n\n.. automodule:: paddlespeech.s2t.training.triggers.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.updaters.rst",
    "content": "paddlespeech.s2t.training.updaters package\n==========================================\n\n.. automodule:: paddlespeech.s2t.training.updaters\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.training.updaters.standard_updater\n   paddlespeech.s2t.training.updaters.updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.updaters.standard_updater.rst",
    "content": "paddlespeech.s2t.training.updaters.standard\\_updater module\n===========================================================\n\n.. automodule:: paddlespeech.s2t.training.updaters.standard_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.training.updaters.updater.rst",
    "content": "paddlespeech.s2t.training.updaters.updater module\n=================================================\n\n.. automodule:: paddlespeech.s2t.training.updaters.updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.asr_utils.rst",
    "content": "paddlespeech.s2t.utils.asr\\_utils module\n========================================\n\n.. automodule:: paddlespeech.s2t.utils.asr_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.bleu_score.rst",
    "content": "paddlespeech.s2t.utils.bleu\\_score module\n=========================================\n\n.. automodule:: paddlespeech.s2t.utils.bleu_score\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.check_kwargs.rst",
    "content": "paddlespeech.s2t.utils.check\\_kwargs module\n===========================================\n\n.. automodule:: paddlespeech.s2t.utils.check_kwargs\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.checkpoint.rst",
    "content": "paddlespeech.s2t.utils.checkpoint module\n========================================\n\n.. automodule:: paddlespeech.s2t.utils.checkpoint\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.cli_readers.rst",
    "content": "paddlespeech.s2t.utils.cli\\_readers module\n==========================================\n\n.. automodule:: paddlespeech.s2t.utils.cli_readers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.cli_utils.rst",
    "content": "paddlespeech.s2t.utils.cli\\_utils module\n========================================\n\n.. automodule:: paddlespeech.s2t.utils.cli_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.cli_writers.rst",
    "content": "paddlespeech.s2t.utils.cli\\_writers module\n==========================================\n\n.. automodule:: paddlespeech.s2t.utils.cli_writers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.ctc_utils.rst",
    "content": "paddlespeech.s2t.utils.ctc\\_utils module\n========================================\n\n.. automodule:: paddlespeech.s2t.utils.ctc_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.dynamic_import.rst",
    "content": "paddlespeech.s2t.utils.dynamic\\_import module\n=============================================\n\n.. automodule:: paddlespeech.s2t.utils.dynamic_import\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.dynamic_pip_install.rst",
    "content": "paddlespeech.s2t.utils.dynamic\\_pip\\_install module\n===================================================\n\n.. automodule:: paddlespeech.s2t.utils.dynamic_pip_install\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.error_rate.rst",
    "content": "paddlespeech.s2t.utils.error\\_rate module\n=========================================\n\n.. automodule:: paddlespeech.s2t.utils.error_rate\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.layer_tools.rst",
    "content": "paddlespeech.s2t.utils.layer\\_tools module\n==========================================\n\n.. automodule:: paddlespeech.s2t.utils.layer_tools\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.log.rst",
    "content": "paddlespeech.s2t.utils.log module\n=================================\n\n.. automodule:: paddlespeech.s2t.utils.log\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.mp_tools.rst",
    "content": "paddlespeech.s2t.utils.mp\\_tools module\n=======================================\n\n.. automodule:: paddlespeech.s2t.utils.mp_tools\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.profiler.rst",
    "content": "paddlespeech.s2t.utils.profiler module\n======================================\n\n.. automodule:: paddlespeech.s2t.utils.profiler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.rst",
    "content": "paddlespeech.s2t.utils package\n==============================\n\n.. automodule:: paddlespeech.s2t.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.s2t.utils.asr_utils\n   paddlespeech.s2t.utils.bleu_score\n   paddlespeech.s2t.utils.check_kwargs\n   paddlespeech.s2t.utils.checkpoint\n   paddlespeech.s2t.utils.cli_readers\n   paddlespeech.s2t.utils.cli_utils\n   paddlespeech.s2t.utils.cli_writers\n   paddlespeech.s2t.utils.ctc_utils\n   paddlespeech.s2t.utils.dynamic_import\n   paddlespeech.s2t.utils.dynamic_pip_install\n   paddlespeech.s2t.utils.error_rate\n   paddlespeech.s2t.utils.layer_tools\n   paddlespeech.s2t.utils.log\n   paddlespeech.s2t.utils.mp_tools\n   paddlespeech.s2t.utils.profiler\n   paddlespeech.s2t.utils.socket_server\n   paddlespeech.s2t.utils.spec_augment\n   paddlespeech.s2t.utils.tensor_utils\n   paddlespeech.s2t.utils.text_grid\n   paddlespeech.s2t.utils.utility\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.socket_server.rst",
    "content": "paddlespeech.s2t.utils.socket\\_server module\n============================================\n\n.. automodule:: paddlespeech.s2t.utils.socket_server\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.spec_augment.rst",
    "content": "paddlespeech.s2t.utils.spec\\_augment module\n===========================================\n\n.. automodule:: paddlespeech.s2t.utils.spec_augment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.tensor_utils.rst",
    "content": "paddlespeech.s2t.utils.tensor\\_utils module\n===========================================\n\n.. automodule:: paddlespeech.s2t.utils.tensor_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.text_grid.rst",
    "content": "paddlespeech.s2t.utils.text\\_grid module\n========================================\n\n.. automodule:: paddlespeech.s2t.utils.text_grid\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.s2t.utils.utility.rst",
    "content": "paddlespeech.s2t.utils.utility module\n=====================================\n\n.. automodule:: paddlespeech.s2t.utils.utility\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.base_commands.rst",
    "content": "paddlespeech.server.base\\_commands module\n=========================================\n\n.. automodule:: paddlespeech.server.base_commands\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.bin.paddlespeech_client.rst",
    "content": "paddlespeech.server.bin.paddlespeech\\_client module\n===================================================\n\n.. automodule:: paddlespeech.server.bin.paddlespeech_client\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.bin.paddlespeech_server.rst",
    "content": "paddlespeech.server.bin.paddlespeech\\_server module\n===================================================\n\n.. automodule:: paddlespeech.server.bin.paddlespeech_server\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.bin.rst",
    "content": "paddlespeech.server.bin package\n===============================\n\n.. automodule:: paddlespeech.server.bin\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.bin.paddlespeech_client\n   paddlespeech.server.bin.paddlespeech_server\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.acs.python.rst",
    "content": "paddlespeech.server.engine.acs.python package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.acs.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.acs.rst",
    "content": "paddlespeech.server.engine.acs package\n======================================\n\n.. automodule:: paddlespeech.server.engine.acs\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.acs.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.ctc_endpoint.rst",
    "content": "paddlespeech.server.engine.asr.online.ctc\\_endpoint module\n==========================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.ctc_endpoint\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.ctc_search.rst",
    "content": "paddlespeech.server.engine.asr.online.ctc\\_search module\n========================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.ctc_search\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.onnx.asr_engine.rst",
    "content": "paddlespeech.server.engine.asr.online.onnx.asr\\_engine module\n=============================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.onnx.asr_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.onnx.rst",
    "content": "paddlespeech.server.engine.asr.online.onnx package\n==================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.onnx\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online.onnx.asr_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.paddleinference.asr_engine.rst",
    "content": "paddlespeech.server.engine.asr.online.paddleinference.asr\\_engine module\n========================================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.paddleinference.asr_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.paddleinference.rst",
    "content": "paddlespeech.server.engine.asr.online.paddleinference package\n=============================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.paddleinference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online.paddleinference.asr_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.python.asr_engine.rst",
    "content": "paddlespeech.server.engine.asr.online.python.asr\\_engine module\n===============================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.python.asr_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.python.rst",
    "content": "paddlespeech.server.engine.asr.online.python package\n====================================================\n\n.. automodule:: paddlespeech.server.engine.asr.online.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online.python.asr_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.online.rst",
    "content": "paddlespeech.server.engine.asr.online package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.asr.online\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online.onnx\n   paddlespeech.server.engine.asr.online.paddleinference\n   paddlespeech.server.engine.asr.online.python\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online.ctc_endpoint\n   paddlespeech.server.engine.asr.online.ctc_search\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.paddleinference.asr_engine.rst",
    "content": "paddlespeech.server.engine.asr.paddleinference.asr\\_engine module\n=================================================================\n\n.. automodule:: paddlespeech.server.engine.asr.paddleinference.asr_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.paddleinference.rst",
    "content": "paddlespeech.server.engine.asr.paddleinference package\n======================================================\n\n.. automodule:: paddlespeech.server.engine.asr.paddleinference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.paddleinference.asr_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.python.asr_engine.rst",
    "content": "paddlespeech.server.engine.asr.python.asr\\_engine module\n========================================================\n\n.. automodule:: paddlespeech.server.engine.asr.python.asr_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.python.rst",
    "content": "paddlespeech.server.engine.asr.python package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.asr.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.python.asr_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.asr.rst",
    "content": "paddlespeech.server.engine.asr package\n======================================\n\n.. automodule:: paddlespeech.server.engine.asr\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.asr.online\n   paddlespeech.server.engine.asr.paddleinference\n   paddlespeech.server.engine.asr.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.base_engine.rst",
    "content": "paddlespeech.server.engine.base\\_engine module\n==============================================\n\n.. automodule:: paddlespeech.server.engine.base_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.cls.paddleinference.cls_engine.rst",
    "content": "paddlespeech.server.engine.cls.paddleinference.cls\\_engine module\n=================================================================\n\n.. automodule:: paddlespeech.server.engine.cls.paddleinference.cls_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.cls.paddleinference.rst",
    "content": "paddlespeech.server.engine.cls.paddleinference package\n======================================================\n\n.. automodule:: paddlespeech.server.engine.cls.paddleinference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.cls.paddleinference.cls_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.cls.python.cls_engine.rst",
    "content": "paddlespeech.server.engine.cls.python.cls\\_engine module\n========================================================\n\n.. automodule:: paddlespeech.server.engine.cls.python.cls_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.cls.python.rst",
    "content": "paddlespeech.server.engine.cls.python package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.cls.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.cls.python.cls_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.cls.rst",
    "content": "paddlespeech.server.engine.cls package\n======================================\n\n.. automodule:: paddlespeech.server.engine.cls\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.cls.paddleinference\n   paddlespeech.server.engine.cls.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.engine_factory.rst",
    "content": "paddlespeech.server.engine.engine\\_factory module\n=================================================\n\n.. automodule:: paddlespeech.server.engine.engine_factory\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.engine_pool.rst",
    "content": "paddlespeech.server.engine.engine\\_pool module\n==============================================\n\n.. automodule:: paddlespeech.server.engine.engine_pool\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.engine_warmup.rst",
    "content": "paddlespeech.server.engine.engine\\_warmup module\n================================================\n\n.. automodule:: paddlespeech.server.engine.engine_warmup\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.rst",
    "content": "paddlespeech.server.engine package\n==================================\n\n.. automodule:: paddlespeech.server.engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.acs\n   paddlespeech.server.engine.asr\n   paddlespeech.server.engine.cls\n   paddlespeech.server.engine.text\n   paddlespeech.server.engine.tts\n   paddlespeech.server.engine.vector\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.base_engine\n   paddlespeech.server.engine.engine_factory\n   paddlespeech.server.engine.engine_pool\n   paddlespeech.server.engine.engine_warmup\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.text.python.rst",
    "content": "paddlespeech.server.engine.text.python package\n==============================================\n\n.. automodule:: paddlespeech.server.engine.text.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.text.python.text_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.text.python.text_engine.rst",
    "content": "paddlespeech.server.engine.text.python.text\\_engine module\n==========================================================\n\n.. automodule:: paddlespeech.server.engine.text.python.text_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.text.rst",
    "content": "paddlespeech.server.engine.text package\n=======================================\n\n.. automodule:: paddlespeech.server.engine.text\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.text.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.online.onnx.rst",
    "content": "paddlespeech.server.engine.tts.online.onnx package\n==================================================\n\n.. automodule:: paddlespeech.server.engine.tts.online.onnx\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.online.onnx.tts_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.online.onnx.tts_engine.rst",
    "content": "paddlespeech.server.engine.tts.online.onnx.tts\\_engine module\n=============================================================\n\n.. automodule:: paddlespeech.server.engine.tts.online.onnx.tts_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.online.python.rst",
    "content": "paddlespeech.server.engine.tts.online.python package\n====================================================\n\n.. automodule:: paddlespeech.server.engine.tts.online.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.online.python.tts_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.online.python.tts_engine.rst",
    "content": "paddlespeech.server.engine.tts.online.python.tts\\_engine module\n===============================================================\n\n.. automodule:: paddlespeech.server.engine.tts.online.python.tts_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.online.rst",
    "content": "paddlespeech.server.engine.tts.online package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.tts.online\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.online.onnx\n   paddlespeech.server.engine.tts.online.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.paddleinference.rst",
    "content": "paddlespeech.server.engine.tts.paddleinference package\n======================================================\n\n.. automodule:: paddlespeech.server.engine.tts.paddleinference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.paddleinference.tts_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.paddleinference.tts_engine.rst",
    "content": "paddlespeech.server.engine.tts.paddleinference.tts\\_engine module\n=================================================================\n\n.. automodule:: paddlespeech.server.engine.tts.paddleinference.tts_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.python.rst",
    "content": "paddlespeech.server.engine.tts.python package\n=============================================\n\n.. automodule:: paddlespeech.server.engine.tts.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.python.tts_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.python.tts_engine.rst",
    "content": "paddlespeech.server.engine.tts.python.tts\\_engine module\n========================================================\n\n.. automodule:: paddlespeech.server.engine.tts.python.tts_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.tts.rst",
    "content": "paddlespeech.server.engine.tts package\n======================================\n\n.. automodule:: paddlespeech.server.engine.tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.tts.online\n   paddlespeech.server.engine.tts.paddleinference\n   paddlespeech.server.engine.tts.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.vector.python.rst",
    "content": "paddlespeech.server.engine.vector.python package\n================================================\n\n.. automodule:: paddlespeech.server.engine.vector.python\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.vector.python.vector_engine\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.vector.python.vector_engine.rst",
    "content": "paddlespeech.server.engine.vector.python.vector\\_engine module\n==============================================================\n\n.. automodule:: paddlespeech.server.engine.vector.python.vector_engine\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.engine.vector.rst",
    "content": "paddlespeech.server.engine.vector package\n=========================================\n\n.. automodule:: paddlespeech.server.engine.vector\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.engine.vector.python\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.entry.rst",
    "content": "paddlespeech.server.entry module\n================================\n\n.. automodule:: paddlespeech.server.entry\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.executor.rst",
    "content": "paddlespeech.server.executor module\n===================================\n\n.. automodule:: paddlespeech.server.executor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.acs_api.rst",
    "content": "paddlespeech.server.restful.acs\\_api module\n===========================================\n\n.. automodule:: paddlespeech.server.restful.acs_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.api.rst",
    "content": "paddlespeech.server.restful.api module\n======================================\n\n.. automodule:: paddlespeech.server.restful.api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.asr_api.rst",
    "content": "paddlespeech.server.restful.asr\\_api module\n===========================================\n\n.. automodule:: paddlespeech.server.restful.asr_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.cls_api.rst",
    "content": "paddlespeech.server.restful.cls\\_api module\n===========================================\n\n.. automodule:: paddlespeech.server.restful.cls_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.request.rst",
    "content": "paddlespeech.server.restful.request module\n==========================================\n\n.. automodule:: paddlespeech.server.restful.request\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.response.rst",
    "content": "paddlespeech.server.restful.response module\n===========================================\n\n.. automodule:: paddlespeech.server.restful.response\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.rst",
    "content": "paddlespeech.server.restful package\n===================================\n\n.. automodule:: paddlespeech.server.restful\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.restful.acs_api\n   paddlespeech.server.restful.api\n   paddlespeech.server.restful.asr_api\n   paddlespeech.server.restful.cls_api\n   paddlespeech.server.restful.request\n   paddlespeech.server.restful.response\n   paddlespeech.server.restful.text_api\n   paddlespeech.server.restful.tts_api\n   paddlespeech.server.restful.vector_api\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.text_api.rst",
    "content": "paddlespeech.server.restful.text\\_api module\n============================================\n\n.. automodule:: paddlespeech.server.restful.text_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.tts_api.rst",
    "content": "paddlespeech.server.restful.tts\\_api module\n===========================================\n\n.. automodule:: paddlespeech.server.restful.tts_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.restful.vector_api.rst",
    "content": "paddlespeech.server.restful.vector\\_api module\n==============================================\n\n.. automodule:: paddlespeech.server.restful.vector_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.rst",
    "content": "paddlespeech.server package\n===========================\n\n.. automodule:: paddlespeech.server\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.bin\n   paddlespeech.server.engine\n   paddlespeech.server.restful\n   paddlespeech.server.tests\n   paddlespeech.server.utils\n   paddlespeech.server.ws\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.base_commands\n   paddlespeech.server.entry\n   paddlespeech.server.executor\n   paddlespeech.server.util\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.tests.asr.offline.http_client.rst",
    "content": "paddlespeech.server.tests.asr.offline.http\\_client module\n=========================================================\n\n.. automodule:: paddlespeech.server.tests.asr.offline.http_client\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.tests.asr.offline.rst",
    "content": "paddlespeech.server.tests.asr.offline package\n=============================================\n\n.. automodule:: paddlespeech.server.tests.asr.offline\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.tests.asr.offline.http_client\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.tests.asr.rst",
    "content": "paddlespeech.server.tests.asr package\n=====================================\n\n.. automodule:: paddlespeech.server.tests.asr\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.tests.asr.offline\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.tests.rst",
    "content": "paddlespeech.server.tests package\n=================================\n\n.. automodule:: paddlespeech.server.tests\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.tests.asr\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.util.rst",
    "content": "paddlespeech.server.util module\n===============================\n\n.. automodule:: paddlespeech.server.util\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.audio_handler.rst",
    "content": "paddlespeech.server.utils.audio\\_handler module\n===============================================\n\n.. automodule:: paddlespeech.server.utils.audio_handler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.audio_process.rst",
    "content": "paddlespeech.server.utils.audio\\_process module\n===============================================\n\n.. automodule:: paddlespeech.server.utils.audio_process\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.buffer.rst",
    "content": "paddlespeech.server.utils.buffer module\n=======================================\n\n.. automodule:: paddlespeech.server.utils.buffer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.config.rst",
    "content": "paddlespeech.server.utils.config module\n=======================================\n\n.. automodule:: paddlespeech.server.utils.config\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.errors.rst",
    "content": "paddlespeech.server.utils.errors module\n=======================================\n\n.. automodule:: paddlespeech.server.utils.errors\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.exception.rst",
    "content": "paddlespeech.server.utils.exception module\n==========================================\n\n.. automodule:: paddlespeech.server.utils.exception\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.onnx_infer.rst",
    "content": "paddlespeech.server.utils.onnx\\_infer module\n============================================\n\n.. automodule:: paddlespeech.server.utils.onnx_infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.paddle_predictor.rst",
    "content": "paddlespeech.server.utils.paddle\\_predictor module\n==================================================\n\n.. automodule:: paddlespeech.server.utils.paddle_predictor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.rst",
    "content": "paddlespeech.server.utils package\n=================================\n\n.. automodule:: paddlespeech.server.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.utils.audio_handler\n   paddlespeech.server.utils.audio_process\n   paddlespeech.server.utils.buffer\n   paddlespeech.server.utils.config\n   paddlespeech.server.utils.errors\n   paddlespeech.server.utils.exception\n   paddlespeech.server.utils.onnx_infer\n   paddlespeech.server.utils.paddle_predictor\n   paddlespeech.server.utils.util\n   paddlespeech.server.utils.vad\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.util.rst",
    "content": "paddlespeech.server.utils.util module\n=====================================\n\n.. automodule:: paddlespeech.server.utils.util\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.utils.vad.rst",
    "content": "paddlespeech.server.utils.vad module\n====================================\n\n.. automodule:: paddlespeech.server.utils.vad\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.ws.api.rst",
    "content": "paddlespeech.server.ws.api module\n=================================\n\n.. automodule:: paddlespeech.server.ws.api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.ws.asr_api.rst",
    "content": "paddlespeech.server.ws.asr\\_api module\n======================================\n\n.. automodule:: paddlespeech.server.ws.asr_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.ws.rst",
    "content": "paddlespeech.server.ws package\n==============================\n\n.. automodule:: paddlespeech.server.ws\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.server.ws.api\n   paddlespeech.server.ws.asr_api\n   paddlespeech.server.ws.tts_api\n"
  },
  {
    "path": "docs/source/api/paddlespeech.server.ws.tts_api.rst",
    "content": "paddlespeech.server.ws.tts\\_api module\n======================================\n\n.. automodule:: paddlespeech.server.ws.tts_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.audio.audio.rst",
    "content": "paddlespeech.t2s.audio.audio module\n===================================\n\n.. automodule:: paddlespeech.t2s.audio.audio\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.audio.codec.rst",
    "content": "paddlespeech.t2s.audio.codec module\n===================================\n\n.. automodule:: paddlespeech.t2s.audio.codec\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.audio.rst",
    "content": "paddlespeech.t2s.audio package\n==============================\n\n.. automodule:: paddlespeech.t2s.audio\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.audio.audio\n   paddlespeech.t2s.audio.codec\n   paddlespeech.t2s.audio.spec_normalizer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.audio.spec_normalizer.rst",
    "content": "paddlespeech.t2s.audio.spec\\_normalizer module\n==============================================\n\n.. automodule:: paddlespeech.t2s.audio.spec_normalizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.am_batch_fn.rst",
    "content": "paddlespeech.t2s.datasets.am\\_batch\\_fn module\n==============================================\n\n.. automodule:: paddlespeech.t2s.datasets.am_batch_fn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.batch.rst",
    "content": "paddlespeech.t2s.datasets.batch module\n======================================\n\n.. automodule:: paddlespeech.t2s.datasets.batch\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.data_table.rst",
    "content": "paddlespeech.t2s.datasets.data\\_table module\n============================================\n\n.. automodule:: paddlespeech.t2s.datasets.data_table\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.dataset.rst",
    "content": "paddlespeech.t2s.datasets.dataset module\n========================================\n\n.. automodule:: paddlespeech.t2s.datasets.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.get_feats.rst",
    "content": "paddlespeech.t2s.datasets.get\\_feats module\n===========================================\n\n.. automodule:: paddlespeech.t2s.datasets.get_feats\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.ljspeech.rst",
    "content": "paddlespeech.t2s.datasets.ljspeech module\n=========================================\n\n.. automodule:: paddlespeech.t2s.datasets.ljspeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.preprocess_utils.rst",
    "content": "paddlespeech.t2s.datasets.preprocess\\_utils module\n==================================================\n\n.. automodule:: paddlespeech.t2s.datasets.preprocess_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.rst",
    "content": "paddlespeech.t2s.datasets package\n=================================\n\n.. automodule:: paddlespeech.t2s.datasets\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.datasets.am_batch_fn\n   paddlespeech.t2s.datasets.batch\n   paddlespeech.t2s.datasets.data_table\n   paddlespeech.t2s.datasets.dataset\n   paddlespeech.t2s.datasets.get_feats\n   paddlespeech.t2s.datasets.ljspeech\n   paddlespeech.t2s.datasets.preprocess_utils\n   paddlespeech.t2s.datasets.sampler\n   paddlespeech.t2s.datasets.vocoder_batch_fn\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.sampler.rst",
    "content": "paddlespeech.t2s.datasets.sampler module\n========================================\n\n.. automodule:: paddlespeech.t2s.datasets.sampler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.datasets.vocoder_batch_fn.rst",
    "content": "paddlespeech.t2s.datasets.vocoder\\_batch\\_fn module\n===================================================\n\n.. automodule:: paddlespeech.t2s.datasets.vocoder_batch_fn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.align.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.align module\n=============================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.align\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.normalize.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.normalize module\n=================================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.preprocess.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.preprocess module\n==================================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat package\n========================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.ernie_sat.align\n   paddlespeech.t2s.exps.ernie_sat.normalize\n   paddlespeech.t2s.exps.ernie_sat.preprocess\n   paddlespeech.t2s.exps.ernie_sat.synthesize\n   paddlespeech.t2s.exps.ernie_sat.synthesize_e2e\n   paddlespeech.t2s.exps.ernie_sat.train\n   paddlespeech.t2s.exps.ernie_sat.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.synthesize.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.synthesize module\n==================================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.synthesize_e2e.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.synthesize\\_e2e module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.synthesize_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.train.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.train module\n=============================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ernie_sat.utils.rst",
    "content": "paddlespeech.t2s.exps.ernie\\_sat.utils module\n=============================================\n\n.. automodule:: paddlespeech.t2s.exps.ernie_sat.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.gen_gta_mel.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2.gen\\_gta\\_mel module\n======================================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2.gen_gta_mel\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.normalize.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2.normalize module\n==================================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.preprocess.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2.preprocess module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2 package\n=========================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.fastspeech2.gen_gta_mel\n   paddlespeech.t2s.exps.fastspeech2.normalize\n   paddlespeech.t2s.exps.fastspeech2.preprocess\n   paddlespeech.t2s.exps.fastspeech2.train\n   paddlespeech.t2s.exps.fastspeech2.vc2_infer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.train.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2.train module\n==============================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.fastspeech2.vc2_infer.rst",
    "content": "paddlespeech.t2s.exps.fastspeech2.vc2\\_infer module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.fastspeech2.vc2_infer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.hifigan.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.hifigan package\n==================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.hifigan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.hifigan.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.hifigan.train.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.hifigan.train module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.hifigan.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.multi\\_band\\_melgan package\n==============================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan.train.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.multi\\_band\\_melgan.train module\n===================================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.normalize.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.normalize module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.parallelwave\\_gan package\n============================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.synthesize_from_wav\n   paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.synthesize_from_wav.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.parallelwave\\_gan.synthesize\\_from\\_wav module\n=================================================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.synthesize_from_wav\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.train.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.parallelwave\\_gan.train module\n=================================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.preprocess.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.preprocess module\n====================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder package\n==========================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.hifigan\n   paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan\n   paddlespeech.t2s.exps.gan_vocoder.parallelwave_gan\n   paddlespeech.t2s.exps.gan_vocoder.style_melgan\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.normalize\n   paddlespeech.t2s.exps.gan_vocoder.preprocess\n   paddlespeech.t2s.exps.gan_vocoder.synthesize\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.style_melgan.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.style\\_melgan package\n========================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.style_melgan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.gan_vocoder.style_melgan.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.style_melgan.train.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.style\\_melgan.train module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.style_melgan.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.gan_vocoder.synthesize.rst",
    "content": "paddlespeech.t2s.exps.gan\\_vocoder.synthesize module\n====================================================\n\n.. automodule:: paddlespeech.t2s.exps.gan_vocoder.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.inference.rst",
    "content": "paddlespeech.t2s.exps.inference module\n======================================\n\n.. automodule:: paddlespeech.t2s.exps.inference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.inference_streaming.rst",
    "content": "paddlespeech.t2s.exps.inference\\_streaming module\n=================================================\n\n.. automodule:: paddlespeech.t2s.exps.inference_streaming\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ort_predict.rst",
    "content": "paddlespeech.t2s.exps.ort\\_predict module\n=========================================\n\n.. automodule:: paddlespeech.t2s.exps.ort_predict\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ort_predict_e2e.rst",
    "content": "paddlespeech.t2s.exps.ort\\_predict\\_e2e module\n==============================================\n\n.. automodule:: paddlespeech.t2s.exps.ort_predict_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.ort_predict_streaming.rst",
    "content": "paddlespeech.t2s.exps.ort\\_predict\\_streaming module\n====================================================\n\n.. automodule:: paddlespeech.t2s.exps.ort_predict_streaming\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.rst",
    "content": "paddlespeech.t2s.exps package\n=============================\n\n.. automodule:: paddlespeech.t2s.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.ernie_sat\n   paddlespeech.t2s.exps.fastspeech2\n   paddlespeech.t2s.exps.gan_vocoder\n   paddlespeech.t2s.exps.speedyspeech\n   paddlespeech.t2s.exps.tacotron2\n   paddlespeech.t2s.exps.transformer_tts\n   paddlespeech.t2s.exps.vits\n   paddlespeech.t2s.exps.waveflow\n   paddlespeech.t2s.exps.wavernn\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.inference\n   paddlespeech.t2s.exps.inference_streaming\n   paddlespeech.t2s.models.vits.monotonic_align\n   paddlespeech.t2s.exps.ort_predict\n   paddlespeech.t2s.exps.ort_predict_e2e\n   paddlespeech.t2s.exps.ort_predict_streaming\n   paddlespeech.t2s.exps.stream_play_tts\n   paddlespeech.t2s.exps.syn_utils\n   paddlespeech.t2s.exps.synthesize\n   paddlespeech.t2s.exps.synthesize_e2e\n   paddlespeech.t2s.exps.synthesize_streaming\n   paddlespeech.t2s.exps.voice_cloning\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.gen_gta_mel.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.gen\\_gta\\_mel module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.gen_gta_mel\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.inference.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.inference module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.inference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.normalize.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.normalize module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.preprocess.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.preprocess module\n====================================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech package\n==========================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.speedyspeech.gen_gta_mel\n   paddlespeech.t2s.exps.speedyspeech.inference\n   paddlespeech.t2s.exps.speedyspeech.normalize\n   paddlespeech.t2s.exps.speedyspeech.preprocess\n   paddlespeech.t2s.exps.speedyspeech.synthesize_e2e\n   paddlespeech.t2s.exps.speedyspeech.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.synthesize_e2e.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.synthesize\\_e2e module\n=========================================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.synthesize_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.speedyspeech.train.rst",
    "content": "paddlespeech.t2s.exps.speedyspeech.train module\n===============================================\n\n.. automodule:: paddlespeech.t2s.exps.speedyspeech.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.stream_play_tts.rst",
    "content": "paddlespeech.t2s.exps.stream\\_play\\_tts module\n==============================================\n\n.. automodule:: paddlespeech.t2s.exps.stream_play_tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.syn_utils.rst",
    "content": "paddlespeech.t2s.exps.syn\\_utils module\n=======================================\n\n.. automodule:: paddlespeech.t2s.exps.syn_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.synthesize.rst",
    "content": "paddlespeech.t2s.exps.synthesize module\n=======================================\n\n.. automodule:: paddlespeech.t2s.exps.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.synthesize_e2e.rst",
    "content": "paddlespeech.t2s.exps.synthesize\\_e2e module\n============================================\n\n.. automodule:: paddlespeech.t2s.exps.synthesize_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.synthesize_streaming.rst",
    "content": "paddlespeech.t2s.exps.synthesize\\_streaming module\n==================================================\n\n.. automodule:: paddlespeech.t2s.exps.synthesize_streaming\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.tacotron2.normalize.rst",
    "content": "paddlespeech.t2s.exps.tacotron2.normalize module\n================================================\n\n.. automodule:: paddlespeech.t2s.exps.tacotron2.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.tacotron2.preprocess.rst",
    "content": "paddlespeech.t2s.exps.tacotron2.preprocess module\n=================================================\n\n.. automodule:: paddlespeech.t2s.exps.tacotron2.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.tacotron2.rst",
    "content": "paddlespeech.t2s.exps.tacotron2 package\n=======================================\n\n.. automodule:: paddlespeech.t2s.exps.tacotron2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.tacotron2.normalize\n   paddlespeech.t2s.exps.tacotron2.preprocess\n   paddlespeech.t2s.exps.tacotron2.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.tacotron2.train.rst",
    "content": "paddlespeech.t2s.exps.tacotron2.train module\n============================================\n\n.. automodule:: paddlespeech.t2s.exps.tacotron2.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.normalize.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts.normalize module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.preprocess.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts.preprocess module\n========================================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts package\n==============================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.transformer_tts.normalize\n   paddlespeech.t2s.exps.transformer_tts.preprocess\n   paddlespeech.t2s.exps.transformer_tts.synthesize\n   paddlespeech.t2s.exps.transformer_tts.synthesize_e2e\n   paddlespeech.t2s.exps.transformer_tts.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.synthesize.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts.synthesize module\n========================================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.synthesize_e2e.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts.synthesize\\_e2e module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts.synthesize_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.transformer_tts.train.rst",
    "content": "paddlespeech.t2s.exps.transformer\\_tts.train module\n===================================================\n\n.. automodule:: paddlespeech.t2s.exps.transformer_tts.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.normalize.rst",
    "content": "paddlespeech.t2s.exps.vits.normalize module\n===========================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.normalize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.preprocess.rst",
    "content": "paddlespeech.t2s.exps.vits.preprocess module\n============================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.rst",
    "content": "paddlespeech.t2s.exps.vits package\n==================================\n\n.. automodule:: paddlespeech.t2s.exps.vits\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.vits.normalize\n   paddlespeech.t2s.exps.vits.preprocess\n   paddlespeech.t2s.exps.vits.synthesize\n   paddlespeech.t2s.exps.vits.synthesize_e2e\n   paddlespeech.t2s.exps.vits.train\n   paddlespeech.t2s.exps.vits.voice_cloning\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.synthesize.rst",
    "content": "paddlespeech.t2s.exps.vits.synthesize module\n============================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.synthesize_e2e.rst",
    "content": "paddlespeech.t2s.exps.vits.synthesize\\_e2e module\n=================================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.synthesize_e2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.train.rst",
    "content": "paddlespeech.t2s.exps.vits.train module\n=======================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.vits.voice_cloning.rst",
    "content": "paddlespeech.t2s.exps.vits.voice\\_cloning module\n================================================\n\n.. automodule:: paddlespeech.t2s.exps.vits.voice_cloning\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.voice_cloning.rst",
    "content": "paddlespeech.t2s.exps.voice\\_cloning module\n===========================================\n\n.. automodule:: paddlespeech.t2s.exps.voice_cloning\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.config.rst",
    "content": "paddlespeech.t2s.exps.waveflow.config module\n============================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow.config\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.ljspeech.rst",
    "content": "paddlespeech.t2s.exps.waveflow.ljspeech module\n==============================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow.ljspeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.preprocess.rst",
    "content": "paddlespeech.t2s.exps.waveflow.preprocess module\n================================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.rst",
    "content": "paddlespeech.t2s.exps.waveflow package\n======================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.waveflow.config\n   paddlespeech.t2s.exps.waveflow.ljspeech\n   paddlespeech.t2s.exps.waveflow.preprocess\n   paddlespeech.t2s.exps.waveflow.synthesize\n   paddlespeech.t2s.exps.waveflow.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.synthesize.rst",
    "content": "paddlespeech.t2s.exps.waveflow.synthesize module\n================================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.waveflow.train.rst",
    "content": "paddlespeech.t2s.exps.waveflow.train module\n===========================================\n\n.. automodule:: paddlespeech.t2s.exps.waveflow.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.wavernn.rst",
    "content": "paddlespeech.t2s.exps.wavernn package\n=====================================\n\n.. automodule:: paddlespeech.t2s.exps.wavernn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.exps.wavernn.synthesize\n   paddlespeech.t2s.exps.wavernn.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.wavernn.synthesize.rst",
    "content": "paddlespeech.t2s.exps.wavernn.synthesize module\n===============================================\n\n.. automodule:: paddlespeech.t2s.exps.wavernn.synthesize\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.exps.wavernn.train.rst",
    "content": "paddlespeech.t2s.exps.wavernn.train module\n==========================================\n\n.. automodule:: paddlespeech.t2s.exps.wavernn.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.arpabet.rst",
    "content": "paddlespeech.t2s.frontend.arpabet module\n========================================\n\n.. automodule:: paddlespeech.t2s.frontend.arpabet\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.g2pw.dataset.rst",
    "content": "paddlespeech.t2s.frontend.g2pw.dataset module\n=============================================\n\n.. automodule:: paddlespeech.t2s.frontend.g2pw.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.g2pw.onnx_api.rst",
    "content": "paddlespeech.t2s.frontend.g2pw.onnx\\_api module\n===============================================\n\n.. automodule:: paddlespeech.t2s.frontend.g2pw.onnx_api\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.g2pw.rst",
    "content": "paddlespeech.t2s.frontend.g2pw package\n======================================\n\n.. automodule:: paddlespeech.t2s.frontend.g2pw\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.frontend.g2pw.dataset\n   paddlespeech.t2s.frontend.g2pw.onnx_api\n   paddlespeech.t2s.frontend.g2pw.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.g2pw.utils.rst",
    "content": "paddlespeech.t2s.frontend.g2pw.utils module\n===========================================\n\n.. automodule:: paddlespeech.t2s.frontend.g2pw.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.generate_lexicon.rst",
    "content": "paddlespeech.t2s.frontend.generate\\_lexicon module\n==================================================\n\n.. automodule:: paddlespeech.t2s.frontend.generate_lexicon\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.mix_frontend.rst",
    "content": "paddlespeech.t2s.frontend.mix\\_frontend module\n==============================================\n\n.. automodule:: paddlespeech.t2s.frontend.mix_frontend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.abbrrviation.rst",
    "content": "paddlespeech.t2s.frontend.normalizer.abbrrviation module\n========================================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer.abbrrviation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.acronyms.rst",
    "content": "paddlespeech.t2s.frontend.normalizer.acronyms module\n====================================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer.acronyms\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.normalizer.rst",
    "content": "paddlespeech.t2s.frontend.normalizer.normalizer module\n======================================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer.normalizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.numbers.rst",
    "content": "paddlespeech.t2s.frontend.normalizer.numbers module\n===================================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer.numbers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.rst",
    "content": "paddlespeech.t2s.frontend.normalizer package\n============================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.frontend.normalizer.abbrrviation\n   paddlespeech.t2s.frontend.normalizer.acronyms\n   paddlespeech.t2s.frontend.normalizer.normalizer\n   paddlespeech.t2s.frontend.normalizer.numbers\n   paddlespeech.t2s.frontend.normalizer.width\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.normalizer.width.rst",
    "content": "paddlespeech.t2s.frontend.normalizer.width module\n=================================================\n\n.. automodule:: paddlespeech.t2s.frontend.normalizer.width\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.phonectic.rst",
    "content": "paddlespeech.t2s.frontend.phonectic module\n==========================================\n\n.. automodule:: paddlespeech.t2s.frontend.phonectic\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.punctuation.rst",
    "content": "paddlespeech.t2s.frontend.punctuation module\n============================================\n\n.. automodule:: paddlespeech.t2s.frontend.punctuation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.rst",
    "content": "paddlespeech.t2s.frontend package\n=================================\n\n.. automodule:: paddlespeech.t2s.frontend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.frontend.g2pw\n   paddlespeech.t2s.frontend.normalizer\n   paddlespeech.t2s.frontend.zh_normalization\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.frontend.arpabet\n   paddlespeech.t2s.frontend.generate_lexicon\n   paddlespeech.t2s.frontend.mix_frontend\n   paddlespeech.t2s.frontend.phonectic\n   paddlespeech.t2s.frontend.punctuation\n   paddlespeech.t2s.frontend.tone_sandhi\n   paddlespeech.t2s.frontend.vocab\n   paddlespeech.t2s.frontend.zh_frontend\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.tone_sandhi.rst",
    "content": "paddlespeech.t2s.frontend.tone\\_sandhi module\n=============================================\n\n.. automodule:: paddlespeech.t2s.frontend.tone_sandhi\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.vocab.rst",
    "content": "paddlespeech.t2s.frontend.vocab module\n======================================\n\n.. automodule:: paddlespeech.t2s.frontend.vocab\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_frontend.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_frontend module\n=============================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_frontend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.char_convert.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.char\\_convert module\n================================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.char_convert\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.chronology.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.chronology module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.chronology\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.constants.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.constants module\n============================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.constants\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.num.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.num module\n======================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.num\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.phonecode.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.phonecode module\n============================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.phonecode\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.quantifier.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.quantifier module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.quantifier\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization package\n===================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.frontend.zh_normalization.char_convert\n   paddlespeech.t2s.frontend.zh_normalization.chronology\n   paddlespeech.t2s.frontend.zh_normalization.constants\n   paddlespeech.t2s.frontend.zh_normalization.num\n   paddlespeech.t2s.frontend.zh_normalization.phonecode\n   paddlespeech.t2s.frontend.zh_normalization.quantifier\n   paddlespeech.t2s.frontend.zh_normalization.text_normlization\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.frontend.zh_normalization.text_normlization.rst",
    "content": "paddlespeech.t2s.frontend.zh\\_normalization.text\\_normlization module\n=====================================================================\n\n.. automodule:: paddlespeech.t2s.frontend.zh_normalization.text_normlization\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.ernie_sat.ernie_sat.rst",
    "content": "paddlespeech.t2s.models.ernie\\_sat.ernie\\_sat module\n====================================================\n\n.. automodule:: paddlespeech.t2s.models.ernie_sat.ernie_sat\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.ernie_sat.ernie_sat_updater.rst",
    "content": "paddlespeech.t2s.models.ernie\\_sat.ernie\\_sat\\_updater module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.models.ernie_sat.ernie_sat_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.ernie_sat.rst",
    "content": "paddlespeech.t2s.models.ernie\\_sat package\n==========================================\n\n.. automodule:: paddlespeech.t2s.models.ernie_sat\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.ernie_sat.ernie_sat\n   paddlespeech.t2s.models.ernie_sat.ernie_sat_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.fastspeech2.fastspeech2.rst",
    "content": "paddlespeech.t2s.models.fastspeech2.fastspeech2 module\n======================================================\n\n.. automodule:: paddlespeech.t2s.models.fastspeech2.fastspeech2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.fastspeech2.fastspeech2_updater.rst",
    "content": "paddlespeech.t2s.models.fastspeech2.fastspeech2\\_updater module\n===============================================================\n\n.. automodule:: paddlespeech.t2s.models.fastspeech2.fastspeech2_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.fastspeech2.rst",
    "content": "paddlespeech.t2s.models.fastspeech2 package\n===========================================\n\n.. automodule:: paddlespeech.t2s.models.fastspeech2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.fastspeech2.fastspeech2\n   paddlespeech.t2s.models.fastspeech2.fastspeech2_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.hifigan.hifigan.rst",
    "content": "paddlespeech.t2s.models.hifigan.hifigan module\n==============================================\n\n.. automodule:: paddlespeech.t2s.models.hifigan.hifigan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.hifigan.hifigan_updater.rst",
    "content": "paddlespeech.t2s.models.hifigan.hifigan\\_updater module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.models.hifigan.hifigan_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.hifigan.rst",
    "content": "paddlespeech.t2s.models.hifigan package\n=======================================\n\n.. automodule:: paddlespeech.t2s.models.hifigan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.hifigan.hifigan\n   paddlespeech.t2s.models.hifigan.hifigan_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.melgan.melgan.rst",
    "content": "paddlespeech.t2s.models.melgan.melgan module\n============================================\n\n.. automodule:: paddlespeech.t2s.models.melgan.melgan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.melgan.multi_band_melgan_updater.rst",
    "content": "paddlespeech.t2s.models.melgan.multi\\_band\\_melgan\\_updater module\n==================================================================\n\n.. automodule:: paddlespeech.t2s.models.melgan.multi_band_melgan_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.melgan.rst",
    "content": "paddlespeech.t2s.models.melgan package\n======================================\n\n.. automodule:: paddlespeech.t2s.models.melgan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.melgan.melgan\n   paddlespeech.t2s.models.melgan.multi_band_melgan_updater\n   paddlespeech.t2s.models.melgan.style_melgan\n   paddlespeech.t2s.models.melgan.style_melgan_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.melgan.style_melgan.rst",
    "content": "paddlespeech.t2s.models.melgan.style\\_melgan module\n===================================================\n\n.. automodule:: paddlespeech.t2s.models.melgan.style_melgan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.melgan.style_melgan_updater.rst",
    "content": "paddlespeech.t2s.models.melgan.style\\_melgan\\_updater module\n============================================================\n\n.. automodule:: paddlespeech.t2s.models.melgan.style_melgan_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan.rst",
    "content": "paddlespeech.t2s.models.parallel\\_wavegan.parallel\\_wavegan module\n==================================================================\n\n.. automodule:: paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan_updater.rst",
    "content": "paddlespeech.t2s.models.parallel\\_wavegan.parallel\\_wavegan\\_updater module\n===========================================================================\n\n.. automodule:: paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.parallel_wavegan.rst",
    "content": "paddlespeech.t2s.models.parallel\\_wavegan package\n=================================================\n\n.. automodule:: paddlespeech.t2s.models.parallel_wavegan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan\n   paddlespeech.t2s.models.parallel_wavegan.parallel_wavegan_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.rst",
    "content": "paddlespeech.t2s.models package\n===============================\n\n.. automodule:: paddlespeech.t2s.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.ernie_sat\n   paddlespeech.t2s.models.fastspeech2\n   paddlespeech.t2s.models.hifigan\n   paddlespeech.t2s.models.melgan\n   paddlespeech.t2s.models.parallel_wavegan\n   paddlespeech.t2s.models.speedyspeech\n   paddlespeech.t2s.models.tacotron2\n   paddlespeech.t2s.models.transformer_tts\n   paddlespeech.t2s.models.vits\n   paddlespeech.t2s.models.wavernn\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.waveflow\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.speedyspeech.rst",
    "content": "paddlespeech.t2s.models.speedyspeech package\n============================================\n\n.. automodule:: paddlespeech.t2s.models.speedyspeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.speedyspeech.speedyspeech\n   paddlespeech.t2s.models.speedyspeech.speedyspeech_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.speedyspeech.speedyspeech.rst",
    "content": "paddlespeech.t2s.models.speedyspeech.speedyspeech module\n========================================================\n\n.. automodule:: paddlespeech.t2s.models.speedyspeech.speedyspeech\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.speedyspeech.speedyspeech_updater.rst",
    "content": "paddlespeech.t2s.models.speedyspeech.speedyspeech\\_updater module\n=================================================================\n\n.. automodule:: paddlespeech.t2s.models.speedyspeech.speedyspeech_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.tacotron2.rst",
    "content": "paddlespeech.t2s.models.tacotron2 package\n=========================================\n\n.. automodule:: paddlespeech.t2s.models.tacotron2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.tacotron2.tacotron2\n   paddlespeech.t2s.models.tacotron2.tacotron2_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.tacotron2.tacotron2.rst",
    "content": "paddlespeech.t2s.models.tacotron2.tacotron2 module\n==================================================\n\n.. automodule:: paddlespeech.t2s.models.tacotron2.tacotron2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.tacotron2.tacotron2_updater.rst",
    "content": "paddlespeech.t2s.models.tacotron2.tacotron2\\_updater module\n===========================================================\n\n.. automodule:: paddlespeech.t2s.models.tacotron2.tacotron2_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.transformer_tts.rst",
    "content": "paddlespeech.t2s.models.transformer\\_tts package\n================================================\n\n.. automodule:: paddlespeech.t2s.models.transformer_tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.transformer_tts.transformer_tts\n   paddlespeech.t2s.models.transformer_tts.transformer_tts_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.transformer_tts.transformer_tts.rst",
    "content": "paddlespeech.t2s.models.transformer\\_tts.transformer\\_tts module\n================================================================\n\n.. automodule:: paddlespeech.t2s.models.transformer_tts.transformer_tts\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.transformer_tts.transformer_tts_updater.rst",
    "content": "paddlespeech.t2s.models.transformer\\_tts.transformer\\_tts\\_updater module\n=========================================================================\n\n.. automodule:: paddlespeech.t2s.models.transformer_tts.transformer_tts_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.duration_predictor.rst",
    "content": "paddlespeech.t2s.models.vits.duration\\_predictor module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.duration_predictor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.flow.rst",
    "content": "paddlespeech.t2s.models.vits.flow module\n========================================\n\n.. automodule:: paddlespeech.t2s.models.vits.flow\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.generator.rst",
    "content": "paddlespeech.t2s.models.vits.generator module\n=============================================\n\n.. automodule:: paddlespeech.t2s.models.vits.generator\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.monotonic_align.core.rst",
    "content": "paddlespeech.t2s.models.vits.monotonic\\_align.core module\n=========================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.monotonic_align.core\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.monotonic_align.rst",
    "content": "paddlespeech.t2s.models.vits.monotonic\\_align package\n=====================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.monotonic_align\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.vits.monotonic_align.core\n   paddlespeech.t2s.models.vits.monotonic_align.setup\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.monotonic_align.setup.rst",
    "content": "paddlespeech.t2s.models.vits.monotonic\\_align.setup module\n==========================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.monotonic_align.setup\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.posterior_encoder.rst",
    "content": "paddlespeech.t2s.models.vits.posterior\\_encoder module\n======================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.posterior_encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.residual_coupling.rst",
    "content": "paddlespeech.t2s.models.vits.residual\\_coupling module\n======================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.residual_coupling\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.rst",
    "content": "paddlespeech.t2s.models.vits package\n====================================\n\n.. automodule:: paddlespeech.t2s.models.vits\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.vits.wavenet\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.vits.duration_predictor\n   paddlespeech.t2s.models.vits.flow\n   paddlespeech.t2s.models.vits.generator\n   paddlespeech.t2s.models.vits.posterior_encoder\n   paddlespeech.t2s.models.vits.residual_coupling\n   paddlespeech.t2s.models.vits.text_encoder\n   paddlespeech.t2s.models.vits.transform\n   paddlespeech.t2s.models.vits.vits\n   paddlespeech.t2s.models.vits.vits_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.text_encoder.rst",
    "content": "paddlespeech.t2s.models.vits.text\\_encoder module\n=================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.text_encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.transform.rst",
    "content": "paddlespeech.t2s.models.vits.transform module\n=============================================\n\n.. automodule:: paddlespeech.t2s.models.vits.transform\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.vits.rst",
    "content": "paddlespeech.t2s.models.vits.vits module\n========================================\n\n.. automodule:: paddlespeech.t2s.models.vits.vits\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.vits_updater.rst",
    "content": "paddlespeech.t2s.models.vits.vits\\_updater module\n=================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.vits_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.wavenet.residual_block.rst",
    "content": "paddlespeech.t2s.models.vits.wavenet.residual\\_block module\n===========================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.wavenet.residual_block\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.wavenet.rst",
    "content": "paddlespeech.t2s.models.vits.wavenet package\n============================================\n\n.. automodule:: paddlespeech.t2s.models.vits.wavenet\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.vits.wavenet.residual_block\n   paddlespeech.t2s.models.vits.wavenet.wavenet\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.vits.wavenet.wavenet.rst",
    "content": "paddlespeech.t2s.models.vits.wavenet.wavenet module\n===================================================\n\n.. automodule:: paddlespeech.t2s.models.vits.wavenet.wavenet\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.waveflow.rst",
    "content": "paddlespeech.t2s.models.waveflow module\n=======================================\n\n.. automodule:: paddlespeech.t2s.models.waveflow\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.wavernn.rst",
    "content": "paddlespeech.t2s.models.wavernn package\n=======================================\n\n.. automodule:: paddlespeech.t2s.models.wavernn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.models.wavernn.wavernn\n   paddlespeech.t2s.models.wavernn.wavernn_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.wavernn.wavernn.rst",
    "content": "paddlespeech.t2s.models.wavernn.wavernn module\n==============================================\n\n.. automodule:: paddlespeech.t2s.models.wavernn.wavernn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.models.wavernn.wavernn_updater.rst",
    "content": "paddlespeech.t2s.models.wavernn.wavernn\\_updater module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.models.wavernn.wavernn_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.activation.rst",
    "content": "paddlespeech.t2s.modules.activation module\n==========================================\n\n.. automodule:: paddlespeech.t2s.modules.activation\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.causal_conv.rst",
    "content": "paddlespeech.t2s.modules.causal\\_conv module\n============================================\n\n.. automodule:: paddlespeech.t2s.modules.causal_conv\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.conformer.convolution.rst",
    "content": "paddlespeech.t2s.modules.conformer.convolution module\n=====================================================\n\n.. automodule:: paddlespeech.t2s.modules.conformer.convolution\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.conformer.encoder_layer.rst",
    "content": "paddlespeech.t2s.modules.conformer.encoder\\_layer module\n========================================================\n\n.. automodule:: paddlespeech.t2s.modules.conformer.encoder_layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.conformer.rst",
    "content": "paddlespeech.t2s.modules.conformer package\n==========================================\n\n.. automodule:: paddlespeech.t2s.modules.conformer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.conformer.convolution\n   paddlespeech.t2s.modules.conformer.encoder_layer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.conv.rst",
    "content": "paddlespeech.t2s.modules.conv module\n====================================\n\n.. automodule:: paddlespeech.t2s.modules.conv\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.geometry.rst",
    "content": "paddlespeech.t2s.modules.geometry module\n========================================\n\n.. automodule:: paddlespeech.t2s.modules.geometry\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.layer_norm.rst",
    "content": "paddlespeech.t2s.modules.layer\\_norm module\n===========================================\n\n.. automodule:: paddlespeech.t2s.modules.layer_norm\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.losses.rst",
    "content": "paddlespeech.t2s.modules.losses module\n======================================\n\n.. automodule:: paddlespeech.t2s.modules.losses\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.masked_fill.rst",
    "content": "paddlespeech.t2s.modules.masked\\_fill module\n============================================\n\n.. automodule:: paddlespeech.t2s.modules.masked_fill\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.nets_utils.rst",
    "content": "paddlespeech.t2s.modules.nets\\_utils module\n===========================================\n\n.. automodule:: paddlespeech.t2s.modules.nets_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.normalizer.rst",
    "content": "paddlespeech.t2s.modules.normalizer module\n==========================================\n\n.. automodule:: paddlespeech.t2s.modules.normalizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.positional_encoding.rst",
    "content": "paddlespeech.t2s.modules.positional\\_encoding module\n====================================================\n\n.. automodule:: paddlespeech.t2s.modules.positional_encoding\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.pqmf.rst",
    "content": "paddlespeech.t2s.modules.pqmf module\n====================================\n\n.. automodule:: paddlespeech.t2s.modules.pqmf\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.predictor.duration_predictor.rst",
    "content": "paddlespeech.t2s.modules.predictor.duration\\_predictor module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.modules.predictor.duration_predictor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.predictor.length_regulator.rst",
    "content": "paddlespeech.t2s.modules.predictor.length\\_regulator module\n===========================================================\n\n.. automodule:: paddlespeech.t2s.modules.predictor.length_regulator\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.predictor.rst",
    "content": "paddlespeech.t2s.modules.predictor package\n==========================================\n\n.. automodule:: paddlespeech.t2s.modules.predictor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.predictor.duration_predictor\n   paddlespeech.t2s.modules.predictor.length_regulator\n   paddlespeech.t2s.modules.predictor.variance_predictor\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.predictor.variance_predictor.rst",
    "content": "paddlespeech.t2s.modules.predictor.variance\\_predictor module\n=============================================================\n\n.. automodule:: paddlespeech.t2s.modules.predictor.variance_predictor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.residual_block.rst",
    "content": "paddlespeech.t2s.modules.residual\\_block module\n===============================================\n\n.. automodule:: paddlespeech.t2s.modules.residual_block\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.residual_stack.rst",
    "content": "paddlespeech.t2s.modules.residual\\_stack module\n===============================================\n\n.. automodule:: paddlespeech.t2s.modules.residual_stack\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.rst",
    "content": "paddlespeech.t2s.modules package\n================================\n\n.. automodule:: paddlespeech.t2s.modules\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.conformer\n   paddlespeech.t2s.modules.predictor\n   paddlespeech.t2s.modules.tacotron2\n   paddlespeech.t2s.modules.transformer\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.activation\n   paddlespeech.t2s.modules.causal_conv\n   paddlespeech.t2s.modules.conv\n   paddlespeech.t2s.modules.geometry\n   paddlespeech.t2s.modules.layer_norm\n   paddlespeech.t2s.modules.losses\n   paddlespeech.t2s.modules.masked_fill\n   paddlespeech.t2s.modules.nets_utils\n   paddlespeech.t2s.modules.normalizer\n   paddlespeech.t2s.modules.positional_encoding\n   paddlespeech.t2s.modules.pqmf\n   paddlespeech.t2s.modules.residual_block\n   paddlespeech.t2s.modules.residual_stack\n   paddlespeech.t2s.modules.style_encoder\n   paddlespeech.t2s.modules.tade_res_block\n   paddlespeech.t2s.modules.upsample\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.style_encoder.rst",
    "content": "paddlespeech.t2s.modules.style\\_encoder module\n==============================================\n\n.. automodule:: paddlespeech.t2s.modules.style_encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.tacotron2.attentions.rst",
    "content": "paddlespeech.t2s.modules.tacotron2.attentions module\n====================================================\n\n.. automodule:: paddlespeech.t2s.modules.tacotron2.attentions\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.tacotron2.decoder.rst",
    "content": "paddlespeech.t2s.modules.tacotron2.decoder module\n=================================================\n\n.. automodule:: paddlespeech.t2s.modules.tacotron2.decoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.tacotron2.encoder.rst",
    "content": "paddlespeech.t2s.modules.tacotron2.encoder module\n=================================================\n\n.. automodule:: paddlespeech.t2s.modules.tacotron2.encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.tacotron2.rst",
    "content": "paddlespeech.t2s.modules.tacotron2 package\n==========================================\n\n.. automodule:: paddlespeech.t2s.modules.tacotron2\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.tacotron2.attentions\n   paddlespeech.t2s.modules.tacotron2.decoder\n   paddlespeech.t2s.modules.tacotron2.encoder\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.tade_res_block.rst",
    "content": "paddlespeech.t2s.modules.tade\\_res\\_block module\n================================================\n\n.. automodule:: paddlespeech.t2s.modules.tade_res_block\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.attention.rst",
    "content": "paddlespeech.t2s.modules.transformer.attention module\n=====================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.attention\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.decoder.rst",
    "content": "paddlespeech.t2s.modules.transformer.decoder module\n===================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.decoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.decoder_layer.rst",
    "content": "paddlespeech.t2s.modules.transformer.decoder\\_layer module\n==========================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.decoder_layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.embedding.rst",
    "content": "paddlespeech.t2s.modules.transformer.embedding module\n=====================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.embedding\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.encoder.rst",
    "content": "paddlespeech.t2s.modules.transformer.encoder module\n===================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.encoder_layer.rst",
    "content": "paddlespeech.t2s.modules.transformer.encoder\\_layer module\n==========================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.encoder_layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.lightconv.rst",
    "content": "paddlespeech.t2s.modules.transformer.lightconv module\n=====================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.lightconv\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.mask.rst",
    "content": "paddlespeech.t2s.modules.transformer.mask module\n================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.mask\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.multi_layer_conv.rst",
    "content": "paddlespeech.t2s.modules.transformer.multi\\_layer\\_conv module\n==============================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.multi_layer_conv\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.positionwise_feed_forward.rst",
    "content": "paddlespeech.t2s.modules.transformer.positionwise\\_feed\\_forward module\n=======================================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.positionwise_feed_forward\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.repeat.rst",
    "content": "paddlespeech.t2s.modules.transformer.repeat module\n==================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.repeat\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.rst",
    "content": "paddlespeech.t2s.modules.transformer package\n============================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.modules.transformer.attention\n   paddlespeech.t2s.modules.transformer.decoder\n   paddlespeech.t2s.modules.transformer.decoder_layer\n   paddlespeech.t2s.modules.transformer.embedding\n   paddlespeech.t2s.modules.transformer.encoder\n   paddlespeech.t2s.modules.transformer.encoder_layer\n   paddlespeech.t2s.modules.transformer.lightconv\n   paddlespeech.t2s.modules.transformer.mask\n   paddlespeech.t2s.modules.transformer.multi_layer_conv\n   paddlespeech.t2s.modules.transformer.positionwise_feed_forward\n   paddlespeech.t2s.modules.transformer.repeat\n   paddlespeech.t2s.modules.transformer.subsampling\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.transformer.subsampling.rst",
    "content": "paddlespeech.t2s.modules.transformer.subsampling module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.modules.transformer.subsampling\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.modules.upsample.rst",
    "content": "paddlespeech.t2s.modules.upsample module\n========================================\n\n.. automodule:: paddlespeech.t2s.modules.upsample\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.rst",
    "content": "paddlespeech.t2s package\n========================\n\n.. automodule:: paddlespeech.t2s\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.audio\n   paddlespeech.t2s.datasets\n   paddlespeech.t2s.exps\n   paddlespeech.t2s.frontend\n   paddlespeech.t2s.models\n   paddlespeech.t2s.modules\n   paddlespeech.t2s.training\n   paddlespeech.t2s.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.cli.rst",
    "content": "paddlespeech.t2s.training.cli module\n====================================\n\n.. automodule:: paddlespeech.t2s.training.cli\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.default_config.rst",
    "content": "paddlespeech.t2s.training.default\\_config module\n================================================\n\n.. automodule:: paddlespeech.t2s.training.default_config\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.experiment.rst",
    "content": "paddlespeech.t2s.training.experiment module\n===========================================\n\n.. automodule:: paddlespeech.t2s.training.experiment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.extension.rst",
    "content": "paddlespeech.t2s.training.extension module\n==========================================\n\n.. automodule:: paddlespeech.t2s.training.extension\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.extensions.evaluator.rst",
    "content": "paddlespeech.t2s.training.extensions.evaluator module\n=====================================================\n\n.. automodule:: paddlespeech.t2s.training.extensions.evaluator\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.extensions.rst",
    "content": "paddlespeech.t2s.training.extensions package\n============================================\n\n.. automodule:: paddlespeech.t2s.training.extensions\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.training.extensions.evaluator\n   paddlespeech.t2s.training.extensions.snapshot\n   paddlespeech.t2s.training.extensions.visualizer\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.extensions.snapshot.rst",
    "content": "paddlespeech.t2s.training.extensions.snapshot module\n====================================================\n\n.. automodule:: paddlespeech.t2s.training.extensions.snapshot\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.extensions.visualizer.rst",
    "content": "paddlespeech.t2s.training.extensions.visualizer module\n======================================================\n\n.. automodule:: paddlespeech.t2s.training.extensions.visualizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.optimizer.rst",
    "content": "paddlespeech.t2s.training.optimizer module\n==========================================\n\n.. automodule:: paddlespeech.t2s.training.optimizer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.reporter.rst",
    "content": "paddlespeech.t2s.training.reporter module\n=========================================\n\n.. automodule:: paddlespeech.t2s.training.reporter\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.rst",
    "content": "paddlespeech.t2s.training package\n=================================\n\n.. automodule:: paddlespeech.t2s.training\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.training.extensions\n   paddlespeech.t2s.training.triggers\n   paddlespeech.t2s.training.updaters\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.training.cli\n   paddlespeech.t2s.training.default_config\n   paddlespeech.t2s.training.experiment\n   paddlespeech.t2s.training.extension\n   paddlespeech.t2s.training.optimizer\n   paddlespeech.t2s.training.reporter\n   paddlespeech.t2s.training.seeding\n   paddlespeech.t2s.training.trainer\n   paddlespeech.t2s.training.trigger\n   paddlespeech.t2s.training.updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.seeding.rst",
    "content": "paddlespeech.t2s.training.seeding module\n========================================\n\n.. automodule:: paddlespeech.t2s.training.seeding\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.trainer.rst",
    "content": "paddlespeech.t2s.training.trainer module\n========================================\n\n.. automodule:: paddlespeech.t2s.training.trainer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.trigger.rst",
    "content": "paddlespeech.t2s.training.trigger module\n========================================\n\n.. automodule:: paddlespeech.t2s.training.trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.triggers.interval_trigger.rst",
    "content": "paddlespeech.t2s.training.triggers.interval\\_trigger module\n===========================================================\n\n.. automodule:: paddlespeech.t2s.training.triggers.interval_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.triggers.limit_trigger.rst",
    "content": "paddlespeech.t2s.training.triggers.limit\\_trigger module\n========================================================\n\n.. automodule:: paddlespeech.t2s.training.triggers.limit_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.triggers.rst",
    "content": "paddlespeech.t2s.training.triggers package\n==========================================\n\n.. automodule:: paddlespeech.t2s.training.triggers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.training.triggers.interval_trigger\n   paddlespeech.t2s.training.triggers.limit_trigger\n   paddlespeech.t2s.training.triggers.time_trigger\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.triggers.time_trigger.rst",
    "content": "paddlespeech.t2s.training.triggers.time\\_trigger module\n=======================================================\n\n.. automodule:: paddlespeech.t2s.training.triggers.time_trigger\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.updater.rst",
    "content": "paddlespeech.t2s.training.updater module\n========================================\n\n.. automodule:: paddlespeech.t2s.training.updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.updaters.rst",
    "content": "paddlespeech.t2s.training.updaters package\n==========================================\n\n.. automodule:: paddlespeech.t2s.training.updaters\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.training.updaters.standard_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.training.updaters.standard_updater.rst",
    "content": "paddlespeech.t2s.training.updaters.standard\\_updater module\n===========================================================\n\n.. automodule:: paddlespeech.t2s.training.updaters.standard_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.checkpoint.rst",
    "content": "paddlespeech.t2s.utils.checkpoint module\n========================================\n\n.. automodule:: paddlespeech.t2s.utils.checkpoint\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.display.rst",
    "content": "paddlespeech.t2s.utils.display module\n=====================================\n\n.. automodule:: paddlespeech.t2s.utils.display\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.error_rate.rst",
    "content": "paddlespeech.t2s.utils.error\\_rate module\n=========================================\n\n.. automodule:: paddlespeech.t2s.utils.error_rate\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.h5_utils.rst",
    "content": "paddlespeech.t2s.utils.h5\\_utils module\n=======================================\n\n.. automodule:: paddlespeech.t2s.utils.h5_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.internals.rst",
    "content": "paddlespeech.t2s.utils.internals module\n=======================================\n\n.. automodule:: paddlespeech.t2s.utils.internals\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.layer_tools.rst",
    "content": "paddlespeech.t2s.utils.layer\\_tools module\n==========================================\n\n.. automodule:: paddlespeech.t2s.utils.layer_tools\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.mp_tools.rst",
    "content": "paddlespeech.t2s.utils.mp\\_tools module\n=======================================\n\n.. automodule:: paddlespeech.t2s.utils.mp_tools\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.profiler.rst",
    "content": "paddlespeech.t2s.utils.profiler module\n======================================\n\n.. automodule:: paddlespeech.t2s.utils.profiler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.rst",
    "content": "paddlespeech.t2s.utils package\n==============================\n\n.. automodule:: paddlespeech.t2s.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.t2s.utils.checkpoint\n   paddlespeech.t2s.utils.display\n   paddlespeech.t2s.utils.error_rate\n   paddlespeech.t2s.utils.h5_utils\n   paddlespeech.t2s.utils.internals\n   paddlespeech.t2s.utils.layer_tools\n   paddlespeech.t2s.utils.mp_tools\n   paddlespeech.t2s.utils.profiler\n   paddlespeech.t2s.utils.scheduler\n"
  },
  {
    "path": "docs/source/api/paddlespeech.t2s.utils.scheduler.rst",
    "content": "paddlespeech.t2s.utils.scheduler module\n=======================================\n\n.. automodule:: paddlespeech.t2s.utils.scheduler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.ernie_linear.avg_model.rst",
    "content": "paddlespeech.text.exps.ernie\\_linear.avg\\_model module\n======================================================\n\n.. automodule:: paddlespeech.text.exps.ernie_linear.avg_model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.ernie_linear.punc_restore.rst",
    "content": "paddlespeech.text.exps.ernie\\_linear.punc\\_restore module\n=========================================================\n\n.. automodule:: paddlespeech.text.exps.ernie_linear.punc_restore\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.ernie_linear.rst",
    "content": "paddlespeech.text.exps.ernie\\_linear package\n============================================\n\n.. automodule:: paddlespeech.text.exps.ernie_linear\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.exps.ernie_linear.avg_model\n   paddlespeech.text.exps.ernie_linear.punc_restore\n   paddlespeech.text.exps.ernie_linear.test\n   paddlespeech.text.exps.ernie_linear.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.ernie_linear.test.rst",
    "content": "paddlespeech.text.exps.ernie\\_linear.test module\n================================================\n\n.. automodule:: paddlespeech.text.exps.ernie_linear.test\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.ernie_linear.train.rst",
    "content": "paddlespeech.text.exps.ernie\\_linear.train module\n=================================================\n\n.. automodule:: paddlespeech.text.exps.ernie_linear.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.exps.rst",
    "content": "paddlespeech.text.exps package\n==============================\n\n.. automodule:: paddlespeech.text.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.exps.ernie_linear\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_crf.model.rst",
    "content": "paddlespeech.text.models.ernie\\_crf.model module\n================================================\n\n.. automodule:: paddlespeech.text.models.ernie_crf.model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_crf.rst",
    "content": "paddlespeech.text.models.ernie\\_crf package\n===========================================\n\n.. automodule:: paddlespeech.text.models.ernie_crf\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.models.ernie_crf.model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_linear.dataset.rst",
    "content": "paddlespeech.text.models.ernie\\_linear.dataset module\n=====================================================\n\n.. automodule:: paddlespeech.text.models.ernie_linear.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_linear.ernie_linear.rst",
    "content": "paddlespeech.text.models.ernie\\_linear.ernie\\_linear module\n===========================================================\n\n.. automodule:: paddlespeech.text.models.ernie_linear.ernie_linear\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_linear.ernie_linear_updater.rst",
    "content": "paddlespeech.text.models.ernie\\_linear.ernie\\_linear\\_updater module\n====================================================================\n\n.. automodule:: paddlespeech.text.models.ernie_linear.ernie_linear_updater\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.ernie_linear.rst",
    "content": "paddlespeech.text.models.ernie\\_linear package\n==============================================\n\n.. automodule:: paddlespeech.text.models.ernie_linear\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.models.ernie_linear.dataset\n   paddlespeech.text.models.ernie_linear.ernie_linear\n   paddlespeech.text.models.ernie_linear.ernie_linear_updater\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.models.rst",
    "content": "paddlespeech.text.models package\n================================\n\n.. automodule:: paddlespeech.text.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.models.ernie_crf\n   paddlespeech.text.models.ernie_linear\n"
  },
  {
    "path": "docs/source/api/paddlespeech.text.rst",
    "content": "paddlespeech.text package\n=========================\n\n.. automodule:: paddlespeech.text\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.text.exps\n   paddlespeech.text.models\n"
  },
  {
    "path": "docs/source/api/paddlespeech.utils.dynamic_import.rst",
    "content": "paddlespeech.utils.dynamic\\_import module\n=========================================\n\n.. automodule:: paddlespeech.utils.dynamic_import\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.utils.env.rst",
    "content": "paddlespeech.utils.env module\n=============================\n\n.. automodule:: paddlespeech.utils.env\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.utils.rst",
    "content": "paddlespeech.utils package\n==========================\n\n.. automodule:: paddlespeech.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.utils.dynamic_import\n   paddlespeech.utils.env\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.cluster.diarization.rst",
    "content": "paddlespeech.vector.cluster.diarization module\n==============================================\n\n.. automodule:: paddlespeech.vector.cluster.diarization\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.cluster.plda.rst",
    "content": "paddlespeech.vector.cluster.plda module\n=======================================\n\n.. automodule:: paddlespeech.vector.cluster.plda\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.cluster.rst",
    "content": "paddlespeech.vector.cluster package\n===================================\n\n.. automodule:: paddlespeech.vector.cluster\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.cluster.diarization\n   paddlespeech.vector.cluster.plda\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.audio_processor.rst",
    "content": "paddlespeech.vector.exps.ge2e.audio\\_processor module\n=====================================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.audio_processor\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.config.rst",
    "content": "paddlespeech.vector.exps.ge2e.config module\n===========================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.config\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.dataset_processors.rst",
    "content": "paddlespeech.vector.exps.ge2e.dataset\\_processors module\n========================================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.dataset_processors\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.inference.rst",
    "content": "paddlespeech.vector.exps.ge2e.inference module\n==============================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.inference\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.preprocess.rst",
    "content": "paddlespeech.vector.exps.ge2e.preprocess module\n===============================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.preprocess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.random_cycle.rst",
    "content": "paddlespeech.vector.exps.ge2e.random\\_cycle module\n==================================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.random_cycle\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.rst",
    "content": "paddlespeech.vector.exps.ge2e package\n=====================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.exps.ge2e.audio_processor\n   paddlespeech.vector.exps.ge2e.config\n   paddlespeech.vector.exps.ge2e.dataset_processors\n   paddlespeech.vector.exps.ge2e.inference\n   paddlespeech.vector.exps.ge2e.preprocess\n   paddlespeech.vector.exps.ge2e.random_cycle\n   paddlespeech.vector.exps.ge2e.speaker_verification_dataset\n   paddlespeech.vector.exps.ge2e.train\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.speaker_verification_dataset.rst",
    "content": "paddlespeech.vector.exps.ge2e.speaker\\_verification\\_dataset module\n===================================================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.speaker_verification_dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.ge2e.train.rst",
    "content": "paddlespeech.vector.exps.ge2e.train module\n==========================================\n\n.. automodule:: paddlespeech.vector.exps.ge2e.train\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.exps.rst",
    "content": "paddlespeech.vector.exps package\n================================\n\n.. automodule:: paddlespeech.vector.exps\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.exps.ge2e\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.augment.rst",
    "content": "paddlespeech.vector.io.augment module\n=====================================\n\n.. automodule:: paddlespeech.vector.io.augment\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.batch.rst",
    "content": "paddlespeech.vector.io.batch module\n===================================\n\n.. automodule:: paddlespeech.vector.io.batch\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.dataset.rst",
    "content": "paddlespeech.vector.io.dataset module\n=====================================\n\n.. automodule:: paddlespeech.vector.io.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.dataset_from_json.rst",
    "content": "paddlespeech.vector.io.dataset\\_from\\_json module\n=================================================\n\n.. automodule:: paddlespeech.vector.io.dataset_from_json\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.embedding_norm.rst",
    "content": "paddlespeech.vector.io.embedding\\_norm module\n=============================================\n\n.. automodule:: paddlespeech.vector.io.embedding_norm\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.rst",
    "content": "paddlespeech.vector.io package\n==============================\n\n.. automodule:: paddlespeech.vector.io\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.io.augment\n   paddlespeech.vector.io.batch\n   paddlespeech.vector.io.dataset\n   paddlespeech.vector.io.dataset_from_json\n   paddlespeech.vector.io.embedding_norm\n   paddlespeech.vector.io.signal_processing\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.io.signal_processing.rst",
    "content": "paddlespeech.vector.io.signal\\_processing module\n================================================\n\n.. automodule:: paddlespeech.vector.io.signal_processing\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.models.ecapa_tdnn.rst",
    "content": "paddlespeech.vector.models.ecapa\\_tdnn module\n=============================================\n\n.. automodule:: paddlespeech.vector.models.ecapa_tdnn\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.models.lstm_speaker_encoder.rst",
    "content": "paddlespeech.vector.models.lstm\\_speaker\\_encoder module\n========================================================\n\n.. automodule:: paddlespeech.vector.models.lstm_speaker_encoder\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.models.rst",
    "content": "paddlespeech.vector.models package\n==================================\n\n.. automodule:: paddlespeech.vector.models\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.models.ecapa_tdnn\n   paddlespeech.vector.models.lstm_speaker_encoder\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.modules.layer.rst",
    "content": "paddlespeech.vector.modules.layer module\n========================================\n\n.. automodule:: paddlespeech.vector.modules.layer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.modules.loss.rst",
    "content": "paddlespeech.vector.modules.loss module\n=======================================\n\n.. automodule:: paddlespeech.vector.modules.loss\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.modules.rst",
    "content": "paddlespeech.vector.modules package\n===================================\n\n.. automodule:: paddlespeech.vector.modules\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.modules.layer\n   paddlespeech.vector.modules.loss\n   paddlespeech.vector.modules.sid_model\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.modules.sid_model.rst",
    "content": "paddlespeech.vector.modules.sid\\_model module\n=============================================\n\n.. automodule:: paddlespeech.vector.modules.sid_model\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.rst",
    "content": "paddlespeech.vector package\n===========================\n\n.. automodule:: paddlespeech.vector\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.cluster\n   paddlespeech.vector.exps\n   paddlespeech.vector.io\n   paddlespeech.vector.models\n   paddlespeech.vector.modules\n   paddlespeech.vector.training\n   paddlespeech.vector.utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.training.rst",
    "content": "paddlespeech.vector.training package\n====================================\n\n.. automodule:: paddlespeech.vector.training\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.training.scheduler\n   paddlespeech.vector.training.seeding\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.training.scheduler.rst",
    "content": "paddlespeech.vector.training.scheduler module\n=============================================\n\n.. automodule:: paddlespeech.vector.training.scheduler\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.training.seeding.rst",
    "content": "paddlespeech.vector.training.seeding module\n===========================================\n\n.. automodule:: paddlespeech.vector.training.seeding\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.utils.rst",
    "content": "paddlespeech.vector.utils package\n=================================\n\n.. automodule:: paddlespeech.vector.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddlespeech.vector.utils.time\n   paddlespeech.vector.utils.vector_utils\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.utils.time.rst",
    "content": "paddlespeech.vector.utils.time module\n=====================================\n\n.. automodule:: paddlespeech.vector.utils.time\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.vector.utils.vector_utils.rst",
    "content": "paddlespeech.vector.utils.vector\\_utils module\n==============================================\n\n.. automodule:: paddlespeech.vector.utils.vector_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/api/paddlespeech.version.rst",
    "content": "paddlespeech.version module\n===========================\n\n.. automodule:: paddlespeech.version\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/asr/PPASR.md",
    "content": "([简体中文](./PPASR_cn.md)|English)\n# PP-ASR\n\n## Catalogue\n- [1. Introduction](#1)\n- [2. Characteristic](#2)\n- [3. Tutorials](#3)\n    - [3.1 Pre-trained Models](#31)\n    - [3.2 Training](#32)\n    - [3.3 Inference](#33)\n    - [3.4 Service Deployment](#33)\n    - [3.5 Customized Auto Speech Recognition and Deployment](#33)\n- [4. Quick Start](#4)\n\n<a name=\"1\"></a>\n## 1. Introduction\n\nPP-ASR is a tool to provide ASR(Automatic speech recognition) function. It provides a variety of Chinese and English models and supports model training. It also supports model inference using the command line. In addition, PP-ASR supports the deployment of streaming models and customized ASR.\n\n<a name=\"2\"></a>\n## 2. Characteristic\nThe basic process of ASR is shown in the figure below:  \n<center><img src=https://user-images.githubusercontent.com/87408988/168259962-cbe2008b-47b6-443d-9566-d77a5ca2eb25.png width=\"800\" ></center>\n\n\nThe main characteristics of PP-ASR are shown below:\n-  Provides pre-trained models on Chinese/English open source datasets: aishell(Chinese), wenetspeech(Chinese) and librispeech(English). The models include deepspeech2 and conformer/transformer.\n-  Support model training on Chinese/English datasets.\n-  Support model inference using the command line. You can use to use `paddlespeech asr --model xxx --input xxx.wav` to use the pre-trained model to do model inference. \n-  Support deployment of streaming ASR server. Besides ASR function, the server supports timestamp function.\n-  Support customized auto speech recognition and deployment.\n\n<a name=\"3\"></a>\n## 3. Tutorials\n\n<a name=\"31\"></a>\n## 3.1 Pre-trained Models\nThe support pre-trained model list: [released_model](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md).  \nThe model with good effect are Ds2 Online Wenetspeech ASR0 Model and Conformer Online Wenetspeech ASR1 Model. Both two models support streaming ASR.  \nFor more information about model design, you can refer to the aistudio tutorial:\n- [Deepspeech2](https://aistudio.baidu.com/aistudio/projectdetail/3866807)\n- [Transformer](https://aistudio.baidu.com/aistudio/projectdetail/3470110)\n\n<a name=\"32\"></a>\n## 3.2 Training\nThe referenced script for model training is stored in [examples](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples) and stored according to \"examples/dataset/model\". The dataset mainly supports aishell and librispeech. The model supports deepspeech2 and u2(conformer/transformer).\nThe specific steps of executing the script are recorded in `run.sh`.\n\nFor more information, you can refer to [asr1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell/asr1)\n\n\n<a name=\"33\"></a>\n## 3.3 Inference\n\nPP-ASR supports use `paddlespeech asr --model xxx --input xxx.wav` to use the pre-trained model to do model inference after install `paddlespeech` by `pip install paddlespeech`.\n\nSpecific supported functions include:\n\n- Prediction of single audio\n- Use the pipe to predict multiple audio\n- Support RTF calculation\n\nFor specific usage, please refer to: [speech_recognition](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/speech_recognition/README_cn.md) \n\n\n<a name=\"34\"></a>\n## 3.4 Service Deployment\n\nPP-ASR supports the service deployment of streaming ASR. Support the simultaneous use of speech recognition and punctuation processing.\n\nDemo of ASR Server: [streaming_asr_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/streaming_asr_server)\n\n![image](https://user-images.githubusercontent.com/87408988/168255342-1fc790c0-16f4-4540-a861-db239076727c.png)\n\nDisplay of using ASR server on Web page: [streaming_asr_demo_video](https://paddlespeech.readthedocs.io/en/latest/streaming_asr_demo_video.html)\n\n\nFor more information about service deployment, you can refer to the aistudio tutorial:\n- [Streaming service - model part](https://aistudio.baidu.com/aistudio/projectdetail/3839884)\n- [Streaming service](https://aistudio.baidu.com/aistudio/projectdetail/4017905)\n\n<a name=\"35\"></a>\n## 3.5 Customized Auto Speech Recognition and Deployment\n\nFor customized auto speech recognition and deployment, PP-ASR provides feature extraction(fbank) => Inference model（Scoring Library）=> C++ program of TLG（WFST, token, lexion, grammer). For specific usage, please refer to: [speechx](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/speechx)   \nIf you want to quickly use it, you can refer to [custom_streaming_asr](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/custom_streaming_asr/README_cn.md)\n\nFor more information about customized auto speech recognition and deployment, you can refer to the aistudio tutorial:\n- [Customized Auto Speech Recognition](https://aistudio.baidu.com/aistudio/projectdetail/4021561)\n\n\n<a name=\"4\"></a>\n\n## 4. Quick Start\n\nTo use PP-ASR, you can see here [install](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md), It supplies three methods to install `paddlespeech`, which are **Easy**, **Medium** and **Hard**. If you want to experience the inference function of paddlespeech, you can use **Easy** installation method.\n"
  },
  {
    "path": "docs/source/asr/PPASR_cn.md",
    "content": "(简体中文|[English](./PPASR.md))\n# PP-ASR\n\n## 目录\n- [1. 简介](#1)\n- [2. 特点](#2)\n- [3. 使用教程](#3)\n    - [3.1 预训练模型](#31)\n    - [3.2 模型训练](#32)\n    - [3.3 模型推理](#33)\n    - [3.4 服务部署](#33)\n    - [3.5 支持个性化场景部署](#33)\n- [4. 快速开始](#4)\n\n<a name=\"1\"></a>\n## 1. 简介\n\nPP-ASR 是一个 提供 ASR 功能的工具。其提供了多种中文和英文的模型，支持模型的训练，并且支持使用命令行的方式进行模型的推理。 PP-ASR 也支持流式模型的部署，以及个性化场景的部署。\n\n<a name=\"2\"></a>\n## 2. 特点\n语音识别的基本流程如下图所示：  \n<center><img src=https://user-images.githubusercontent.com/87408988/168259962-cbe2008b-47b6-443d-9566-d77a5ca2eb25.png width=\"800\" ></center>\n\n\nPP-ASR 的主要特点如下：\n-  提供在中/英文开源数据集 aishell （中文），wenetspeech（中文），librispeech （英文）上的预训练模型。模型包含 deepspeech2 模型以及 conformer/transformer 模型。\n-  支持中/英文的模型训练功能。\n-  支持命令行方式的模型推理，可使用 `paddlespeech asr --model xxx --input xxx.wav` 方式调用各个预训练模型进行推理。\n-  支持流式 ASR 的服务部署，也支持输出时间戳。\n-  支持个性化场景的部署。\n\n<a name=\"3\"></a>\n## 3. 使用教程\n\n<a name=\"31\"></a>\n## 3.1 预训练模型\n支持的预训练模型列表：[released_model](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md)。\n其中效果较好的模型为 Ds2 Online Wenetspeech ASR0 Model 以及 Conformer Online Wenetspeech ASR1 Model。 两个模型都支持流式 ASR。\n更多关于模型设计的部分，可以参考 AIStudio 教程：\n- [Deepspeech2](https://aistudio.baidu.com/aistudio/projectdetail/3866807)\n- [Transformer](https://aistudio.baidu.com/aistudio/projectdetail/3470110)\n\n<a name=\"32\"></a>\n## 3.2 模型训练\n\n模型的训练的参考脚本存放在 [examples](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples) 中，并按照 `examples/数据集/模型` 存放，数据集主要支持 aishell 和 librispeech，模型支持 deepspeech2 模型和 u2 (conformer/transformer) 模型。\n具体的执行脚本的步骤记录在 `run.sh` 当中。具体可参考： [asr1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell/asr1)\n\n\n<a name=\"33\"></a>\n## 3.3 模型推理\n\nPP-ASR 支持在使用`pip install paddlespeech`后 使用命令行的方式来使用预训练模型进行推理。\n\n具体支持的功能包括：\n\n- 对单条音频进行预测\n- 使用管道的方式对多条音频进行预测\n- 支持 RTF 的计算\n\n具体的使用方式可以参考： [speech_recognition](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/speech_recognition/README_cn.md) \n\n\n<a name=\"34\"></a>\n## 3.4 服务部署\n\nPP-ASR 支持流式ASR的服务部署。支持 语音识别 + 标点处理两个功能同时使用。\n\nserver 的 demo： [streaming_asr_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/streaming_asr_server)\n\n![image](https://user-images.githubusercontent.com/87408988/168255342-1fc790c0-16f4-4540-a861-db239076727c.png)\n\n网页上使用 asr server 的效果展示：[streaming_asr_demo_video](https://paddlespeech.readthedocs.io/en/latest/streaming_asr_demo_video.html)\n\n关于服务部署方面的更多资料，可以参考 AIStudio 教程：\n- [流式服务-模型部分](https://aistudio.baidu.com/aistudio/projectdetail/3839884)\n- [流式服务](https://aistudio.baidu.com/aistudio/projectdetail/4017905)\n\n<a name=\"35\"></a>\n## 3.5 支持个性化场景部署\n\n针对个性化场景部署，提供了特征提取（fbank） => 推理模型（打分库）=> TLG（WFST， token, lexion, grammer）的 C++ 程序。具体参考 [speechx](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/speechx)。  \n如果想快速了解和使用，可以参考： [custom_streaming_asr](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/custom_streaming_asr/README_cn.md)\n\n关于支持个性化场景部署的更多资料，可以参考 AIStudio 教程：\n- [定制化识别](https://aistudio.baidu.com/aistudio/projectdetail/4021561)\n\n\n<a name=\"4\"></a>\n\n## 4. 快速开始\n\n关于如果使用 PP-ASR，可以看这里的 [install](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)，其中提供了 **简单**、**中等**、**困难** 三种安装方式。如果想体验 paddlespeech 的推理功能，可以用 **简单** 安装方式。\n"
  },
  {
    "path": "docs/source/asr/data_preparation.md",
    "content": "# Data Preparation\n\n## Generate Manifest\n\n*DeepSpeech2 on PaddlePaddle* accepts a textual **manifest** file as its data set interface. A manifest file summarizes a set of speech data, with each line containing some meta data (e.g. file path, transcription, duration) of one audio clip, in [JSON](http://www.json.org/) format, such as:\n\n```\n{\"audio_filepath\": \"/home/work/.cache/paddle/Libri/134686/1089-134686-0001.flac\", \"duration\": 3.275, \"text\": \"stuff it into you his belly counselled him\"}\n{\"audio_filepath\": \"/home/work/.cache/paddle/Libri/134686/1089-134686-0007.flac\", \"duration\": 4.275, \"text\": \"a cold lucid indifference reigned in his soul\"}\n```\nTo use your custom data, you only need to generate such manifest files to summarize the dataset. Given such summarized manifests, training, inference and all other modules can be aware of where to access the audio files, as well as their meta data including the transcription labels.\n\nFor how to generate such manifest files, please refer to `examples/librispeech/local/librispeech.py`, which will download data and generate manifest files for LibriSpeech dataset.\n\n## Compute Mean & Stddev for Normalizer\n\nTo perform z-score normalization (zero-mean, unit stddev) upon audio features, we have to estimate in advance the mean and standard deviation of the features, with some training samples:\n\n```bash\npython3 utils/compute_mean_std.py \\\n--num_samples 2000 \\\n--spectrum_type linear \\\n--manifest_path examples/librispeech/data/manifest.train \\\n--output_path examples/librispeech/data/mean_std.npz\n```\n\nIt will compute the mean and standard deviations of the power spectrum feature with 2000 random sampled audio clips listed in `examples/librispeech/data/manifest.train` and save the results to `examples/librispeech/data/mean_std.npz` for further usage.\n\n\n## Build Vocabulary\n\nA vocabulary of possible characters is required to convert the transcription into a list of token indices for training, and in decoding, to convert from a list of indices back to the text again. Such a character-based vocabulary can be built with `utils/build_vocab.py`.\n\n```bash\npython3 utils/build_vocab.py \\\n--count_threshold 0 \\\n--vocab_path examples/librispeech/data/eng_vocab.txt \\\n--manifest_paths examples/librispeech/data/manifest.train\n```\n\nIt will write a vocabulary file `examples/librispeech/data/vocab.txt` with all transcription text in `examples/librispeech/data/manifest.train`, without vocabulary truncation (`--count_threshold 0`).\n"
  },
  {
    "path": "docs/source/asr/feature_list.md",
    "content": "# Features\n\n### Dataset\n* Aishell\n* Librispeech\n* THCHS30\n* TIMIT\n\n### Speech Recognition\n\n* Non-Streaming\n  * [Baidu's DeepSpeech2](http://proceedings.mlr.press/v48/amodei16.pdf)\n  * [Transformer](https://arxiv.org/abs/1706.03762)\n  * [Conformer](https://arxiv.org/abs/2005.08100)\n\n* Streaming\n  * [Baidu's DeepSpeech2](http://proceedings.mlr.press/v48/amodei16.pdf)\n  * [U2](https://arxiv.org/pdf/2012.05481.pdf)\n\n### Language Model\n\n* Ngram\n\n### Decoder\n\n* ctc greedy\n* ctc prefix beam search\n* greedy\n* beam search\n* attention rescore\n\n### Deployment\n\n* Paddle Inference\n\n### Aligment  \n\n* MFA  \n* CTC Alignment  \n\n### Speech Frontend\n\n* Audio\n  * Auto Gain\n* Feature\n  * kaldi fbank\n  * kaldi mfcc\n  * linear\n  * delta detla\n\n### Speech Augmentation\n\n* Audio\n  - Volume Perturbation\n  - Speed Perturbation\n  - Shifting Perturbation\n  - Online Bayesian normalization\n  - Noise Perturbation\n  - Impulse Response\n* Spectrum\n  - SpecAugment\n  - Adaptive SpecAugment\n\n### Tokenizer\n\n* Chinese/English Character\n* English Word\n* Sentence Piece\n\n### Word Segmentation\n\n*  [mmseg](http://technology.chtsai.org/mmseg/)\n\n### Grapheme To Phoneme\n\n* syllable\n* phoneme\n"
  },
  {
    "path": "docs/source/asr/models_introduction.md",
    "content": "# Models introduction\n## Streaming DeepSpeech2\nThe implemented architecture of Deepspeech2 online model is based on [Deepspeech2 model](https://arxiv.org/pdf/1512.02595.pdf) with some changes.\nThe model is mainly composed of 2D convolution subsampling layers and stacked single-direction rnn layers.\n\nTo illustrate the model implementation clearly, 3 parts are described in detail.  \n- Data Preparation\n- Encoder\n- Decoder\n\nIn addition, the training process and the testing process are also introduced.\n\nThe architecture of the model is shown in Fig.1.\n\n<p align=\"center\">\n    <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/ds2onlineModel.png\" width=800>\n    <br/>Fig.1 The Arcitecture of deepspeech2 online model\n</p>\n\n\n### Data Preparation\n#### Vocabulary\nFor English data, the vocabulary dictionary is composed of 26 English characters with \" ' \", space, \\<blank\\> and \\<eos\\>. The \\<blank\\> represents the blank label in CTC, the \\<unk\\> represents the unknown character and the \\<eos\\> represents the start and the end characters. For mandarin, the vocabulary dictionary is composed of Chinese characters statistics from the training set, and three additional characters are added. The added characters are \\<blank\\>, \\<unk\\> and \\<eos\\>.  For both English and mandarin data, we set the default indexes that \\<blank\\>=0, \\<unk\\>=1 and \\<eos\\>= last index.\n```\n# The code to build vocabulary\ncd examples/aishell/s0\npython3 ../../../utils/build_vocab.py \\\n    --unit_type=\"char\" \\\n    --count_threshold=0 \\\n    --vocab_path=\"data/vocab.txt\" \\\n    --manifest_paths \"data/manifest.train.raw\" \"data/manifest.dev.raw\"\n\n# vocabulary for aishell dataset (Mandarin)\nvi examples/aishell/s0/data/vocab.txt\n\n# vocabulary for librispeech dataset (English)\nvi examples/librispeech/s0/data/vocab.txt\n```\n\n#### CMVN\nFor CMVN, a subset of or full of the training set is selected and be used to compute the feature mean and std.\n```\n# The code to compute the feature mean and std\ncd examples/aishell/s0\npython3 ../../../utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --spectrum_type=\"linear\" \\\n    --delta_delta=false \\\n    --stride_ms=10.0 \\\n    --window_ms=20.0 \\\n    --sample_rate=16000 \\\n    --use_dB_normalization=True \\\n    --num_samples=2000 \\\n    --num_workers=10 \\\n    --output_path=\"data/mean_std.json\"\n\n```\n\n#### Feature Extraction\nFor feature extraction, three methods are implemented, which are linear (FFT without using filter bank), fbank and mfcc.\nCurrently, the released deepspeech2 online model uses the linear feature extraction method.\n```\nThe code for feature extraction\nvi paddlespeech/s2t/frontend/featurizer/audio_featurizer.py\n```\n\n### Encoder\nThe encoder is composed of two 2D convolution subsampling layers and several stacked single-direction rnn layers. The 2D convolution subsampling layers extract feature representation from the raw audio feature and reduce the length of the audio feature at the same time. After passing through the convolution subsampling layers, then the feature representation is input into the stacked rnn layers. For the stacked rnn layers, LSTM cell and GRU cell are provided to use. Adding one fully connected (fc) layer after the stacked rnn layers are optional. If the number of stacked rnn layers is less than 5, adding one fc layer after stacked rnn layers are recommended.\n\nThe code of Encoder is in:\n```\nvi paddlespeech/s2t/models/ds2_online/deepspeech2.py\n```\n\n### Decoder\nTo get the character possibilities of each frame, the feature representation of each frame output from the encoder is input into a projection layer which is implemented as a dense layer to do feature projection. The output dim of the projection layer is the same as the vocabulary size. After the projection layer, the softmax function is used to transform the frame-level feature representation be the possibilities of characters. While making model inference, the character possibilities of each frame are input into the CTC decoder to get the final speech recognition results.\n\nThe code of the decoder is in:\n```\n# The code of constructing the decoder in model\nvi paddlespeech/s2t/models/ds2_online/deepspeech2.py\n# The code of CTC Decoder\nvi paddlespeech/s2t/modules/ctc.py\n```\n\n### Training Process\nUsing the command below, you can train the deepspeech2 online model.\n```\ncd examples/aishell/s0\nbash run.sh --stage 0 --stop_stage 2 --model_type online --conf_path conf/deepspeech2_online.yaml\n```\nThe detail commands are:\n```  \n# The code for training in the run.sh\nset -e\nsource path.sh\n\ngpus=2,3,5,7\nstage=0\nstop_stage=5\nconf_path=conf/deepspeech2_online.yaml     # conf/deepspeech2.yaml | conf/deepspeech2_online.yaml\navg_num=1\nmodel_type=online    # online | offline\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt} ${model_type}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh exp/${ckpt}/checkpoints ${avg_num}\nfi\n```\nBy using the command above, the training process can be started. There are 5 stages in \"run.sh\", and the first 3 stages are used for the training process. Stage 0 is used for data preparation, in which the dataset will be downloaded, and the manifest files of the datasets, vocabulary dictionary, and CMVN file will be generated in \"./data/\". Stage 1 is used for training the model, the log files and model checkpoint are saved in \"exp/deepspeech2_online/\". Stage 2 is used to generate the final model for predicting by averaging the top-k model parameters based on validation loss.  \n\n### Testing Process\nUsing the command below, you can test the deepspeech2 online model.\n```\nbash run.sh --stage 3 --stop_stage 5 --model_type online --conf_path conf/deepspeech2_online.yaml\n```\nThe detail commands are:\n```\nconf_path=conf/deepspeech2_online.yaml\navg_num=1\nmodel_type=online\navg_ckpt=avg_${avg_num}\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=2 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${model_type}|| exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=5 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # test export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test_export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}|| exit -1\nfi\n```\nAfter the training process, we use stages 3,4,5 for the testing process. Stage 3 is for testing the model generated in stage 2 and provided the CER index of the test set. Stage 4 is for transforming the model from a dynamic graph to a static graph by using \"paddle.jit\" library. Stage 5 is for testing the model in a static graph.\n\n## Non-Streaming DeepSpeech2\nThe deepspeech2 offline model is similar to the deepspeech2 online model. The main difference between them is the offline model uses the stacked bi-directional rnn layers while the online model uses the single direction rnn layers and the fc layer is not used. For the stacked bi-directional rnn layers in the offline model, the rnn cell and gru cell are provided to use.\n\nThe arcitecture of the model is shown in Fig.2.\n<p align=\"center\">\n    <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/ds2offlineModel.png\" width=800>\n    <br/>Fig.2 The Arcitecture of deepspeech2 offline model\n</p>\n\n\nFor data preparation and decoder, the deepspeech2 offline model is the same as the deepspeech2 online model.\n\nThe code of encoder and decoder for deepspeech2 offline model is in:\n```\nvi paddlespeech/s2t/models/ds2/deepspeech2.py\n```\n\nThe training process and testing process of deepspeech2 offline model is very similar to deepspeech2 online model.\nOnly some changes should be noticed.\n\nFor training and testing, the \"model_type\" and the \"conf_path\" must be set.\n```\n# Training offline\ncd examples/aishell/s0\nbash run.sh --stage 0 --stop_stage 2 --model_type offline --conf_path conf/deepspeech2.yaml\n ```\n```\n# Testing offline\ncd examples/aishell/s0\nbash run.sh --stage 3 --stop_stage 5 --model_type offline --conf_path conf/deepspeech2.yaml\n```\n"
  },
  {
    "path": "docs/source/asr/ngram_lm.md",
    "content": "# Ngram LM\n\n## Prepare Language Model\n\nA language model is required to improve the decoder's performance. We have prepared two language models (with lossy compression) for users to download and try. One is for English and the other is for Mandarin. The bash script to download LM is example's `local/download_lm_*.sh`.\n\nFor example, users can simply run this to download the prepared mandarin language models:\n\n```bash\ncd examples/aishell\nsource path.sh\nbash local/download_lm_ch.sh\n```\nIf you wish to train your own better language model, please refer to [KenLM](https://github.com/kpu/kenlm) for tutorials.\nHere we provide some tips to show how we prepare our English and Mandarin language models.\nYou can take it as a reference when you train your own.\n\n### English LM\n\nThe English corpus is from the [Common Crawl Repository](http://commoncrawl.org) and you can download it from [statmt](http://data.statmt.org/ngrams/deduped_en). We use part en.00 to train our English language model. There are some preprocessing steps before training:\n\n  * Characters not in \\['A-Za-z0-9\\s'\\] (\\s represents whitespace characters) are removed and Arabic numbers are converted to English numbers like 1000 to one thousand.\n  * Repeated whitespace characters are squeezed to one and the beginning whitespace characters are removed. Notice that all transcriptions are lowercase, so all characters are converted to lowercase.\n  * Top 400,000 most frequent words are selected to build the vocabulary and the rest are replaced with 'UNKNOWNWORD'.\n\nNow the preprocessing is done and we get a clean corpus to train the language model. Our released language model is trained with arguments '-o 5 --prune 0 1 1 1 1'. '-o 5' means the max order of the language model is 5. '--prune 0 1 1 1 1' represents count thresholds for each order and more specifically it will prune singletons for orders two and higher. To save disk storage we convert the ARPA file to 'trie' binary file with arguments '-a 22 -q 8 -b 8'. '-a' represents the maximum number of leading bits of pointers in 'trie' to chop. '-q -b' are quantization parameters for probability and backoff.\n\n### Mandarin LM\n\nDifferent from the English language model, the Mandarin language model is character-based where each token is a Chinese character. We use the internal corpus to train the released Mandarin language models. The corpus contains billions of tokens. The preprocessing has a tiny difference from the English language model and the main steps include:\n\n  * The beginning and trailing whitespace characters are removed.\n  * English punctuations and Chinese punctuations are removed.\n  * A whitespace character between two tokens is inserted.\n\nPlease notice that the released language models only contain Chinese simplified characters. After preprocessing is done we can begin to train the language model. The key training arguments for small LM are '-o 5 --prune 0 1 2 4 4' and '-o 5' for large LM. Please refer above section for the meaning of each argument. We also convert the ARPA file to a binary file using default settings.\n"
  },
  {
    "path": "docs/source/asr/quick_start.md",
    "content": "# Quick Start of Speech-to-Text\nSeveral shell scripts provided in `./examples/tiny/local` will help us to quickly give it a try, for most major modules, including data preparation, model training, case inference, and model evaluation, with a few public datasets (e.g. [LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)). Reading these examples will also help you to understand how to make it work with your data.\n\nSome of the scripts in `./examples` are not configured with GPUs. If you want to train with 8 GPUs, please modify `CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7`. If you don't have any GPU available, please set `CUDA_VISIBLE_DEVICES=` to use CPUs instead. Besides, if an out-of-memory problem occurs, just reduce `batch_size` to fit.\n\nLet's take a tiny sampled subset of [LibriSpeech dataset](http://www.openslr.org/12/) for instance.\n\n- Go to the directory\n\n    ```bash\n    cd examples/tiny\n    ```\n    Notice that this is only a toy example with a tiny sampled subset of LibriSpeech. If you would like to try with the complete dataset (would take several days for training), please go to `examples/librispeech` instead.\n- Source env\n    ```bash\n    source path.sh\n    ```\n    **Must do this before you start to do anything.**\n    Set `MAIN_ROOT` as project dir. Using the default `deepspeech2` model as `MODEL`, you can change this in the script.\n- Main entry point\n    ```bash\n    bash run.sh\n    ```\n    This is just a demo, please make sure every `step` works well before the next `step`.\n\nMore detailed information is provided in the following sections. Wish you a happy journey with the *DeepSpeech on PaddlePaddle* ASR engine!\n\n## Training a model\nThe key steps of training for the Mandarin language are the same as that of the English language and we have also provided an example for Mandarin training with Aishell in `examples/aishell/local`. As mentioned above, please execute `sh data.sh`, `sh train.sh` and `sh test.sh` to do data preparation, training, and testing correspondingly.\n\n## Evaluate a Model\nTo evaluate a model's performance quantitatively, please run:\n```bash\nCUDA_VISIBLE_DEVICES=0 bash local/test.sh\n```\nThe error rate (default: word error rate; can be set with `error_rate_type`) will be printed.\n\nWe provide two types of CTC decoders: *CTC greedy decoder* and *CTC beam search decoder*. The *CTC greedy decoder* is an implementation of the simple best-path decoding algorithm, selecting at each timestep the most likely token, thus being greedy and locally optimal. The [*CTC beam search decoder*](https://arxiv.org/abs/1408.2873) otherwise utilizes a heuristic breadth-first graph search for reaching near-global optimality; it also requires a pre-trained KenLM language model for better scoring and ranking. The decoder type can be set with the argument `decoding_method`.\n"
  },
  {
    "path": "docs/source/audio/_static/custom.css",
    "content": ".wy-nav-content {\n    max-width: 80%;\n}\n.table table{ background:#b9b9b9} \n.table table td{ background:#FFF; } \n"
  },
  {
    "path": "docs/source/audio/_templates/module.rst_t",
    "content": "{%- if show_headings %}\n{{- basename | e | heading }}\n\n{% endif -%}\n.. automodule:: {{ qualname }}\n{%- for option in automodule_options %}\n   :{{ option }}:\n{%- endfor %}\n\n"
  },
  {
    "path": "docs/source/audio/_templates/package.rst_t",
    "content": "{%- macro automodule(modname, options) -%}\n.. automodule:: {{ modname }}\n{%- for option in options %}\n   :{{ option }}:\n{%- endfor %}\n{%- endmacro %}\n\n{%- macro toctree(docnames) -%}\n.. toctree::\n   :maxdepth: {{ maxdepth }}\n{% for docname in docnames %}\n   {{ docname }}\n{%- endfor %}\n{%- endmacro %}\n\n{%- if is_namespace %}\n{{- [pkgname, \"namespace\"] | join(\" \") | e | heading }}\n{% else %}\n{{- pkgname | e | heading }}\n{% endif %}\n\n{%- if is_namespace %}\n.. py:module:: {{ pkgname }}\n{% endif %}\n\n{%- if modulefirst and not is_namespace %}\n{{ automodule(pkgname, automodule_options) }}\n{% endif %}\n\n{%- if subpackages %}\nSubpackages\n-----------\n\n{{ toctree(subpackages) }}\n{% endif %}\n\n{%- if submodules %}\nSubmodules\n----------\n{% if separatemodules %}\n{{ toctree(submodules) }}\n{% else %}\n{%- for submodule in submodules %}\n{% if show_headings %}\n{{- submodule | e | heading(2) }}\n{% endif %}\n{{ automodule(submodule, automodule_options) }}\n{% endfor %}\n{%- endif %}\n{%- endif %}\n\n{%- if not modulefirst and not is_namespace %}\nModule contents\n---------------\n\n{{ automodule(pkgname, automodule_options) }}\n{% endif %}\n"
  },
  {
    "path": "docs/source/audio/_templates/toc.rst_t",
    "content": "{{ header | heading }}\n\n.. toctree::\n   :maxdepth: {{ maxdepth }}\n{% for docname in docnames %}\n   {{ docname }}\n{%- endfor %}\n\n"
  },
  {
    "path": "docs/source/audio/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Configuration file for the Sphinx documentation builder.\n#\n# This file does only contain a selection of the most common options. For a\n# full list see the documentation:\n# http://www.sphinx-doc.org/en/master/config\n# -- Path setup --------------------------------------------------------------\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\nimport os\nimport sys\nsys.path.insert(0, os.path.abspath('../..'))\n\n# -- Project information -----------------------------------------------------\n\nproject = 'PaddleAudio'\ncopyright = '2022, PaddlePaddle'\nauthor = 'PaddlePaddle'\n\n# The short X.Y version\nversion = ''\n# The full version, including alpha/beta/rc tags\nrelease = '0.2.0'\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.intersphinx',\n    'sphinx.ext.mathjax',\n    'sphinx.ext.viewcode',\n    'sphinx.ext.napoleon',\n]\n\nnapoleon_google_docstring = True\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = []\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = None\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\n\nimport sphinx_rtd_theme\nhtml_theme = 'sphinx_rtd_theme'\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\nsmartquotes = False\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\nhtml_logo = '../images/paddle.png'\nhtml_css_files = [\n    'custom.css',\n]\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n#\n# The default sidebars (for documents that don't match any pattern) are\n# defined by theme itself.  Builtin themes are using these templates by\n# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',\n# 'searchbox.html']``.\n#\n# html_sidebars = {}\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'PaddleAudiodoc'\n\n# -- Options for LaTeX output ------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    # 'papersize': 'letterpaper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    # 'pointsize': '10pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'PaddleAudio.tex', 'PaddleAudio Documentation', 'PaddlePaddle',\n     'manual'),\n]\n\n# -- Options for manual page output ------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [(master_doc, 'paddleaudio', 'PaddleAudio Documentation', [author],\n              1)]\n\n# -- Options for Texinfo output ----------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'PaddleAudio', 'PaddleAudio Documentation', author,\n     'PaddleAudio', 'One line description of project.', 'Miscellaneous'),\n]\n\n# -- Options for Epub output -------------------------------------------------\n\n# Bibliographic Dublin Core info.\nepub_title = project\n\n# The unique identifier of the text. This can be a ISBN number\n# or the project homepage.\n#\n# epub_identifier = ''\n\n# A unique identification for the text.\n#\n# epub_uid = ''\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = ['search.html']\n\n# -- Extension configuration -------------------------------------------------\n\n# -- Options for intersphinx extension ---------------------------------------\n\n# Example configuration for intersphinx: refer to the Python standard library.\nintersphinx_mapping = {'https://docs.python.org/': None}\n"
  },
  {
    "path": "docs/source/audio/index.rst",
    "content": ".. PaddleAudio documentation master file, created by\n   sphinx-quickstart on Tue Mar 22 15:57:16 2022.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to PaddleAudio's documentation!\n=======================================\n\n.. toctree::\n   :maxdepth: 1\n\n   Index <self>\n\n\nAPI References\n--------------\n\n.. toctree::\n   :maxdepth: 2\n   :titlesonly:\n\n   paddleaudio"
  },
  {
    "path": "docs/source/audio_api/modules.rst",
    "content": "audio\n=====\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.common.rst",
    "content": "paddleaudio.backends.common module\n==================================\n\n.. automodule:: paddleaudio.backends.common\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.no_backend.rst",
    "content": "paddleaudio.backends.no\\_backend module\n=======================================\n\n.. automodule:: paddleaudio.backends.no_backend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.rst",
    "content": "paddleaudio.backends package\n============================\n\n.. automodule:: paddleaudio.backends\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.backends.common\n   paddleaudio.backends.no_backend\n   paddleaudio.backends.soundfile_backend\n   paddleaudio.backends.sox_io_backend\n   paddleaudio.backends.utils\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.soundfile_backend.rst",
    "content": "paddleaudio.backends.soundfile\\_backend module\n==============================================\n\n.. automodule:: paddleaudio.backends.soundfile_backend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.sox_io_backend.rst",
    "content": "paddleaudio.backends.sox\\_io\\_backend module\n============================================\n\n.. automodule:: paddleaudio.backends.sox_io_backend\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.backends.utils.rst",
    "content": "paddleaudio.backends.utils module\n=================================\n\n.. automodule:: paddleaudio.backends.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.compliance.kaldi.rst",
    "content": "paddleaudio.compliance.kaldi module\n===================================\n\n.. automodule:: paddleaudio.compliance.kaldi\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.compliance.librosa.rst",
    "content": "paddleaudio.compliance.librosa module\n=====================================\n\n.. automodule:: paddleaudio.compliance.librosa\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.compliance.rst",
    "content": "paddleaudio.compliance package\n==============================\n\n.. automodule:: paddleaudio.compliance\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.compliance.kaldi\n   paddleaudio.compliance.librosa\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.dataset.rst",
    "content": "paddleaudio.datasets.dataset module\n===================================\n\n.. automodule:: paddleaudio.datasets.dataset\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.esc50.rst",
    "content": "paddleaudio.datasets.esc50 module\n=================================\n\n.. automodule:: paddleaudio.datasets.esc50\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.gtzan.rst",
    "content": "paddleaudio.datasets.gtzan module\n=================================\n\n.. automodule:: paddleaudio.datasets.gtzan\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.hey_snips.rst",
    "content": "paddleaudio.datasets.hey\\_snips module\n======================================\n\n.. automodule:: paddleaudio.datasets.hey_snips\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.rirs_noises.rst",
    "content": "paddleaudio.datasets.rirs\\_noises module\n========================================\n\n.. automodule:: paddleaudio.datasets.rirs_noises\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.rst",
    "content": "paddleaudio.datasets package\n============================\n\n.. automodule:: paddleaudio.datasets\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.datasets.dataset\n   paddleaudio.datasets.esc50\n   paddleaudio.datasets.gtzan\n   paddleaudio.datasets.hey_snips\n   paddleaudio.datasets.rirs_noises\n   paddleaudio.datasets.tess\n   paddleaudio.datasets.urban_sound\n   paddleaudio.datasets.voxceleb\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.tess.rst",
    "content": "paddleaudio.datasets.tess module\n================================\n\n.. automodule:: paddleaudio.datasets.tess\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.urban_sound.rst",
    "content": "paddleaudio.datasets.urban\\_sound module\n========================================\n\n.. automodule:: paddleaudio.datasets.urban_sound\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.datasets.voxceleb.rst",
    "content": "paddleaudio.datasets.voxceleb module\n====================================\n\n.. automodule:: paddleaudio.datasets.voxceleb\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.features.layers.rst",
    "content": "paddleaudio.features.layers module\n==================================\n\n.. automodule:: paddleaudio.features.layers\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.features.rst",
    "content": "paddleaudio.features package\n============================\n\n.. automodule:: paddleaudio.features\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.features.layers\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.functional.functional.rst",
    "content": "paddleaudio.functional.functional module\n========================================\n\n.. automodule:: paddleaudio.functional.functional\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.functional.rst",
    "content": "paddleaudio.functional package\n==============================\n\n.. automodule:: paddleaudio.functional\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.functional.functional\n   paddleaudio.functional.window\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.functional.window.rst",
    "content": "paddleaudio.functional.window module\n====================================\n\n.. automodule:: paddleaudio.functional.window\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.kaldi.kaldi.rst",
    "content": "paddleaudio.kaldi.kaldi module\n==============================\n\n.. automodule:: paddleaudio.kaldi.kaldi\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.kaldi.rst",
    "content": "paddleaudio.kaldi package\n=========================\n\n.. automodule:: paddleaudio.kaldi\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.kaldi.kaldi\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.metric.eer.rst",
    "content": "paddleaudio.metric.eer module\n=============================\n\n.. automodule:: paddleaudio.metric.eer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.metric.rst",
    "content": "paddleaudio.metric package\n==========================\n\n.. automodule:: paddleaudio.metric\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.metric.eer\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.rst",
    "content": "paddleaudio package\n===================\n\n.. automodule:: paddleaudio\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubpackages\n-----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.backends\n   paddleaudio.compliance\n   paddleaudio.datasets\n   paddleaudio.features\n   paddleaudio.functional\n   paddleaudio.kaldi\n   paddleaudio.metric\n   paddleaudio.sox_effects\n   paddleaudio.utils\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.sox_effects.rst",
    "content": "paddleaudio.sox\\_effects package\n================================\n\n.. automodule:: paddleaudio.sox_effects\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.sox_effects.sox_effects\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.sox_effects.sox_effects.rst",
    "content": "paddleaudio.sox\\_effects.sox\\_effects module\n============================================\n\n.. automodule:: paddleaudio.sox_effects.sox_effects\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.download.rst",
    "content": "paddleaudio.utils.download module\n=================================\n\n.. automodule:: paddleaudio.utils.download\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.env.rst",
    "content": "paddleaudio.utils.env module\n============================\n\n.. automodule:: paddleaudio.utils.env\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.error.rst",
    "content": "paddleaudio.utils.error module\n==============================\n\n.. automodule:: paddleaudio.utils.error\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.log.rst",
    "content": "paddleaudio.utils.log module\n============================\n\n.. automodule:: paddleaudio.utils.log\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.numeric.rst",
    "content": "paddleaudio.utils.numeric module\n================================\n\n.. automodule:: paddleaudio.utils.numeric\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.rst",
    "content": "paddleaudio.utils package\n=========================\n\n.. automodule:: paddleaudio.utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\nSubmodules\n----------\n\n.. toctree::\n   :maxdepth: 4\n\n   paddleaudio.utils.download\n   paddleaudio.utils.env\n   paddleaudio.utils.error\n   paddleaudio.utils.log\n   paddleaudio.utils.numeric\n   paddleaudio.utils.sox_utils\n   paddleaudio.utils.tensor_utils\n   paddleaudio.utils.time\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.sox_utils.rst",
    "content": "paddleaudio.utils.sox\\_utils module\n===================================\n\n.. automodule:: paddleaudio.utils.sox_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.tensor_utils.rst",
    "content": "paddleaudio.utils.tensor\\_utils module\n======================================\n\n.. automodule:: paddleaudio.utils.tensor_utils\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/audio_api/paddleaudio.utils.time.rst",
    "content": "paddleaudio.utils.time module\n=============================\n\n.. automodule:: paddleaudio.utils.time\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/source/cls/custom_dataset.md",
    "content": "# Customize Dataset for Audio Classification\n\nFollowing this tutorial you can customize your dataset for audio classification task by using `paddlespeech`.\n\nA base class of classification dataset is `paddlespeech.audio.datasets.dataset.AudioClassificationDataset`. To customize your dataset you should write a dataset class derived from `AudioClassificationDataset`. \n\nAssuming you have some wave files that stored in your own directory. You should prepare a meta file with the information of filepaths and labels. For example the absolute path of it is `/PATH/TO/META_FILE.txt`:\n```\n/PATH/TO/WAVE_FILE/1.wav cat\n/PATH/TO/WAVE_FILE/2.wav cat\n/PATH/TO/WAVE_FILE/3.wav dog\n/PATH/TO/WAVE_FILE/4.wav dog\n```\nHere is an example to build your custom dataset in `custom_dataset.py`:\n\n```python\nfrom paddlespeech.audio.datasets.dataset import AudioClassificationDataset\n\nclass CustomDataset(AudioClassificationDataset):\n    meta_file = '/PATH/TO/META_FILE.txt'\n    # List all the class labels\n    label_list = [\n        'cat',\n        'dog',\n    ]\n\n    def __init__(self, **kwargs):\n        files, labels = self._get_data()\n        super(CustomDataset, self).__init__(\n            files=files, labels=labels, feat_type='raw', **kwargs)\n\n    def _get_data(self):\n        '''\n        This method offer information of wave files and labels.\n        '''\n        files = []\n        labels = []\n\n        with open(self.meta_file) as f:\n            for line in f:\n                file, label_str = line.strip().split(' ')\n                files.append(file)\n                labels.append(self.label_list.index(label_str))\n\n        return files, labels\n```\n\nThen you can build dataset and data loader from `CustomDataset`:\n```python\nimport paddle\nfrom paddlespeech.audio.transform.spectrogram import LogMelSpectrogram\n\nfrom custom_dataset import CustomDataset\n\n# Feature config should be align with pretrained model\nsample_rate = 32000\nfeat_conf = {\n  'sr': sample_rate,\n  'n_fft': 1024,\n  'hop_length': 320,\n  'window': 'hann',\n  'win_length': 1024,\n  'f_min': 50.0,\n  'f_max': 14000.0,\n  'n_mels': 64,\n}\n\ntrain_ds = CustomDataset(sample_rate=sample_rate)\nfeature_extractor = LogMelSpectrogram(**feat_conf)\n\ntrain_sampler = paddle.io.DistributedBatchSampler(\n    train_ds, batch_size=4, shuffle=True, drop_last=False)\ntrain_loader = paddle.io.DataLoader(\n    train_ds,\n    batch_sampler=train_sampler,\n    return_list=True,\n    use_buffer_reader=True)\n```\n\nTrain model with `CustomDataset`:\n```python\nfrom paddlespeech.cls.models import cnn14\nfrom paddlespeech.cls.models import SoundClassifier\n\nbackbone = cnn14(pretrained=True, extract_embedding=True)\nmodel = SoundClassifier(backbone, num_class=len(train_ds.label_list))\noptimizer = paddle.optimizer.Adam(\n    learning_rate=1e-6, parameters=model.parameters())\ncriterion = paddle.nn.loss.CrossEntropyLoss()\n\nsteps_per_epoch = len(train_sampler)\nepochs = 10\nfor epoch in range(1, epochs + 1):\n    model.train()\n\n    for batch_idx, batch in enumerate(train_loader):\n        waveforms, labels = batch\n        # Need a padding when lengths of waveforms differ in a batch.\n        feats = feature_extractor(waveforms)        \n        feats = paddle.transpose(feats, [0, 2, 1])\n        logits = model(feats)\n        loss = criterion(logits, labels)\n        loss.backward()\n        optimizer.step()\n        if isinstance(optimizer._learning_rate,\n                        paddle.optimizer.lr.LRScheduler):\n            optimizer._learning_rate.step()\n        optimizer.clear_grad()\n\n        # Calculate loss\n        avg_loss = float(loss)\n\n        # Calculate metrics\n        preds = paddle.argmax(logits, axis=1)\n        num_corrects = (preds == labels).numpy().sum()\n        num_samples = feats.shape[0]\n\n        avg_acc = num_corrects / num_samples\n\n        print_msg = 'Epoch={}/{}, Step={}/{}'.format(\n            epoch, epochs, batch_idx + 1, steps_per_epoch)\n        print_msg += ' loss={:.4f}'.format(avg_loss)\n        print_msg += ' acc={:.4f}'.format(avg_acc)\n        print_msg += ' lr={:.6f}'.format(optimizer.get_lr())\n        print(print_msg)\n```\n\nIf you want to save the checkpoint of model and evaluate from a specific dataset, please see `paddlespeech/cli/exp/panns/train.py` for more details.\n"
  },
  {
    "path": "docs/source/cls/quick_start.md",
    "content": "# Quick Start of Audio Classification\nSeveral shell scripts provided in `./examples/esc50/cls0` will help us to quickly give it a try, for most major modules, including data preparation, model training, model evaluation, with [ESC50](ttps://github.com/karolpiczak/ESC-50) dataset.\n\nSome of the scripts in `./examples` are not configured with GPUs. If you want to train with 8 GPUs, please modify `CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7`. If you don't have any GPU available, please set `CUDA_VISIBLE_DEVICES=` to use CPUs instead.\n\nLet's start a audio classification task with the following steps:\n\n- Go to the directory\n\n    ```bash\n    cd examples/esc50/cls0\n    ```\n\n- Source env\n    ```bash\n    source path.sh\n    ```\n\n- Main entry point\n    ```bash\n    CUDA_VISIBLE_DEVICES=0 ./run.sh 1\n    ```\n\nThis demo includes fine-tuning, evaluating and deploying a audio classificatio model. More detailed information is provided in the following sections. \n\n## Fine-tuning a model\nPANNs([PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition](https://arxiv.org/pdf/1912.10211.pdf)) are pretrained models with [Audioset](https://research.google.com/audioset/). They can be easily used to extract audio embeddings for audio classification task.\n\nTo start a model fine-tuning, please run:\n```bash\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\nfeat_backend=numpy\n./local/train.sh ${ngpu} ${feat_backend}\n```\n\n## Deploy a model\nOnce you save a model checkpoint, you can export it to static graph and deploy by python scirpt:\n\n- Export to a static graph\n    ```bash\n    ./local/export.sh ${ckpt_dir} ./export\n    ```\n    The argument `ckpt_dir` should be a directory in which a model checkpoint stored, for example `checkpoint/epoch_50`.\n\n    The static graph will be exported to `./export`.\n\n- Inference\n    ```bash\n    ./local/static_model_infer.sh ${infer_device} ./export ${audio_file}\n    ```\n    The argument `infer_device` can be `cpu` or `gpu`, and it means which device to be used to infer. And `audio_file` should be a wave file with name `*.wav`.\n"
  },
  {
    "path": "docs/source/conf.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:\n# https://www.sphinx-doc.org/en/master/usage/configuration.html\n# -- Path setup --------------------------------------------------------------\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\nimport os\nimport sys\n\nimport recommonmark.parser\nimport sphinx_rtd_theme\nsys.path.insert(0, os.path.abspath('../..'))\nsys.path.insert(0, os.path.abspath('../../audio'))\n\n\nautodoc_mock_imports = [\"soundfile\", \"librosa\"]\n\n# -- Project information -----------------------------------------------------\n\nproject = 'paddle speech'\ncopyright = '2021, paddlespeech-developers'\nauthor = 'paddlespeech-developers'\n\n# The full version, including alpha/beta/rc tags\nrelease = '2.1'\n\n# -- General configuration ---------------------------------------------------\nsource_parsers = {\n    '.md': recommonmark.parser.CommonMarkParser,\n}\nsource_suffix = ['.rst', '.md']\n\nmaster_doc = 'index'\npygments_style = 'sphinx'\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.viewcode',\n    \"sphinx_rtd_theme\",\n    'sphinx.ext.mathjax',\n    'numpydoc',\n    'sphinx.ext.autosummary',\n    'myst_parser',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = [\n    '_build',\n]\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\n\nhtml_theme = 'sphinx_rtd_theme'\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\nsmartquotes = False\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\nhtml_logo = '../images/paddle.png'\nhtml_css_files = [\n    'custom.css',\n]\n\n# -- Extension configuration -------------------------------------------------\n# numpydoc_show_class_members = False\n"
  },
  {
    "path": "docs/source/demo_video.rst",
    "content": "Demo Video \n==================\n\n.. raw:: html\n    \n    <video controls width=\"1024\">\n\n    <source src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/PaddleSpeech_Demo.mp4\"\n            type=\"video/mp4\">\n\n    Sorry, your browser doesn't support embedded videos.\n    </video>\n\n"
  },
  {
    "path": "docs/source/dependencies.md",
    "content": "# The Dependencies\n## By apt-get\n### The base dependencies:\n```\nbc flac jq vim tig tree pkg-config libsndfile1 libflac-dev libvorbis-dev libboost-dev swig python3-dev\n```\n### The dependencies of kenlm:\n```\nbuild-essential cmake libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev libeigen3-dev zlib1g-dev libbz2-dev liblzma-dev gcc-5 g++-5\n```\n### The dependencies of sox:\n```\nlibvorbis-dev libmp3lame-dev libmad-ocaml-dev\n```\n## By make or setup\n```\nkenlm\nsox\nmfa\nopenblas\nkaldi\nsctk\nAutoLog\nswig-decoder\npython_kaldi_features\n```\n"
  },
  {
    "path": "docs/source/index.rst",
    "content": "Welcome to PaddleSpeech\n==============================================\n\n**PaddleSpeech** is a Speech toolkits implemented by paddlepaddle.\n\n\nContents\n--------\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Introduction\n\n   introduction\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Quick Start\n\n   install\n   asr/quick_start\n   tts/quick_start\n   \n.. toctree::\n   :maxdepth: 1\n   :caption: Speech-to-Text\n\n   asr/models_introduction\n   asr/data_preparation\n   asr/feature_list\n   asr/ngram_lm\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Text-to-Speech\n\n   tts/basic_usage\n   tts/advanced_usage\n   tts/zh_text_frontend\n   tts/models_introduction\n   tts/gan_vocoder\n   tts/demo\n   tts/demo_2\n   \n\n.. toctree::\n   :maxdepth: 1\n   :caption: Released Models\n\n   released_model\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Demos\n\n   demo_video\n   streaming_asr_demo_video\n   tts_demo_video\n   streaming_tts_demo_video\n\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Acknowledgement\n\n   asr/reference\n\n\n.. toctree::\n   :maxdepth: 2\n   :caption: API Reference\n\n   paddleaudio <audio_api/paddleaudio>\n   paddlespeech.audio <api/paddlespeech.audio>\n   paddlespeech.cli <api/paddlespeech.cli>\n   paddlespeech.cls <api/paddlespeech.cls>\n   paddlespeech.kws <api/paddlespeech.kws>\n   paddlespeech.resource <api/paddlespeech.resource>\n   paddlespeech.s2t <api/paddlespeech.s2t>\n   paddlespeech.server <api/paddlespeech.server>\n   paddlespeech.t2s <api/paddlespeech.t2s>\n   paddlespeech.text <api/paddlespeech.text>\n   paddlespeech.utils <api/ppaddlespeech.utils>\n   paddlespeech.vector <api/paddlespeech.vector>\n"
  },
  {
    "path": "docs/source/install.md",
    "content": "([简体中文](./install_cn.md)|English)\n# Installation\nThere are 3 ways to use `PaddleSpeech`. According to the degree of difficulty, the 3 ways can be divided into **Easy**, **Medium**, and **Hard**. You can choose one of the 3 ways to install `PaddleSpeech`.\n\n| Way | Function                                                     | Support|\n|:---- |:----------------------------------------------------------- |:----|\n| Easy     | (1) Use command-line functions of PaddleSpeech. <br> (2) Experience PaddleSpeech on Ai Studio. | Linux, Mac(not support M1 chip)，Windows ( For more information about installation, see [#1195](https://github.com/PaddlePaddle/PaddleSpeech/discussions/1195)) |\n| Medium     | Support major functions ，such as using the` ready-made `examples and using PaddleSpeech to train your model.                                           | Linux, Mac(not support M1 chip, not support training models)，Windows (not support training models) |\n| Hard     | Support full function of Paddlespeech, including using join ctc decoder with kaldi([asr2](../../examples/librispeech/asr2 )), training n-gram language model, Montreal-Forced-Aligner, and so on. And you are more able to be a developer! | Ubuntu |\n\n## Prerequisites\n- Python >= 3.7\n- PaddlePaddle latest version (please refer to the [Installation Guide](https://www.paddlepaddle.org.cn/documentation/docs/en/beginners_guide/index_en.html))\n- C++ compilation environment\n- Tip: For Linux and Mac, do not use command `sh` instead of command `bash` in installation document.\n- Tip: We recommand you to install `paddlepaddle` from https://mirror.baidu.com/pypi/simple and install `paddlespeech` from https://pypi.tuna.tsinghua.edu.cn/simple. \n\n## Easy: Get the Basic Function (Support Linux, Mac, and Windows)\n- If you are newer to `PaddleSpeech` and want to experience it easily without your machine. We recommend you to use [AI Studio](https://aistudio.baidu.com/aistudio/index) to experience it. There is a step-by-step [tutorial](https://aistudio.baidu.com/aistudio/education/group/info/25130) for `PaddleSpeech`, and you can use the basic function of `PaddleSpeech` with a free machine.\n- If you want to use the command line function of Paddlespeech, you need to complete the following steps to install `PaddleSpeech`. For more information about how to use the command line function, you can see the [cli](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/cli).\n### Install Conda\nConda is a management system of the environment. You can go to [miniconda](https://docs.conda.io/en/latest/miniconda.html)  (select a version py>=3.7) to download and install the conda.\nAnd then Install  conda dependencies for `paddlespeech` :\n\n```bash\nconda install -y -c conda-forge sox libsndfile bzip2\n```\n### Install C++ Compilation Environment \n(If you already have C++ compilation environment, you can miss this step.)\n#### Windows\nYou need to install `Visual Studio` to make the C++ compilation environment.\n\nhttps://visualstudio.microsoft.com/visual-cpp-build-tools/\n\nYou can also see [#1195](https://github.com/PaddlePaddle/PaddleSpeech/discussions/1195) for more help.\n\n#### Mac\n```bash\nbrew install gcc\n```\n#### Linux\n```bash\n#  centos\nsudo yum install gcc gcc-c++\n```\n```bash\n# ubuntu\nsudo apt install build-essential\n```\n```bash\n# Others\nconda install -y -c gcc_linux-64=8.4.0 gxx_linux-64=8.4.0\n```\n### Install PaddleSpeech \nSome users may fail to install `kaldiio` due to the default download source, you can install `pytest-runner` at first；\n```bash\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\nThen you can use the following commands:\n```bash\npip install paddlepaddle -i https://mirror.baidu.com/pypi/simple\npip install paddlespeech -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\nYou can also specify the version of paddlepaddle or install the develop version. \n```bash\n# install 2.4.1 version. Note, 2.4.1 is just an example, please follow the minimum dependency of paddlepaddle for your selection\npip install paddlepaddle==2.4.1 -i https://mirror.baidu.com/pypi/simple\n# install develop version\npip install paddlepaddle==0.0.0 -f https://www.paddlepaddle.org.cn/whl/linux/cpu-mkl/develop.html\n```\n> If you encounter problem with downloading **nltk_data** while using paddlespeech, it maybe due to your poor network, we suggest you download the [nltk_data](https://paddlespeech.cdn.bcebos.com/Parakeet/tools/nltk_data.tar.gz) provided by us, and extract it to your `${HOME}`.\n\n> If you fail to install paddlespeech-ctcdecoders, you only can not use deepspeech2 model inference. For other models, it doesn't matter.\n \n## Medium: Get the Major Functions (Support Linux, mac and windows not support training)\nIf you want to get the major function of  `paddlespeech`, you need to do following steps:\n### Git clone PaddleSpeech\nYou need to `git clone` this repository at first.\n```bash\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\ncd PaddleSpeech\n```\n\n### Install Conda\nConda is a management system of the environment. You can go to [minicoda](https://docs.conda.io/en/latest/miniconda.html) to select a version (py>=3.7). For windows, you can follow the installing guide step by step and for linux and mac, you can use the following commands:\n```bash\n# download the miniconda\nwget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -P tools/\n# install the miniconda\nbash tools/Miniconda3-latest-Linux-x86_64.sh -b\n# conda init\n$HOME/miniconda3/bin/conda init\n# activate the conda\nbash\n```\nThen you can create a conda virtual environment using the following command:\n```bash\nconda create -y -p tools/venv python=3.8\n```\nActivate the conda virtual environment:\n```bash\nconda activate tools/venv\n```\nInstall  conda dependencies for `paddlespeech` :\n```bash\nconda install -y -c conda-forge sox libsndfile swig bzip2\n```\n### Install C++ Compilation Environment \n(If you already have C++ compilation environment, you can miss this step.)\nDo not forget to install `gcc` and `gxx` on your system.\nYou can choose to use the scripts below to install them.\n\n```bash\n#  centos\nsudo yum install gcc gcc-c++\n```\n```bash\n# ubuntu\nsudo apt install build-essential\n```\n```bash\n# Others\nconda install -y -c gcc_linux-64=8.4.0 gxx_linux-64=8.4.0\n```\n(Hip: Do not use the last script if you want to install by **Hard** way):\n### Install PaddlePaddle\nYou can choose the `PaddlePaddle` version based on your system. For example, for CUDA 10.2, CuDNN7.6 install paddlepaddle-gpu 2.4.1:\n```bash\n# Note, 2.4.1 is just an example, please follow the minimum dependency of paddlepaddle for your selection\npython3 -m pip install paddlepaddle-gpu==2.4.1 -i https://mirror.baidu.com/pypi/simple\n```\nYou can also install the develop version of paddlepaddle. For example, for CUDA 10.2, CuDNN7.6 install paddlepaddle-gpu develop:\n```bash\npython3 -m pip install paddlepaddle-gpu==0.0.0.post102 -f https://www.paddlepaddle.org.cn/whl/linux/gpu/develop.html\n```\n### Install PaddleSpeech \nYou can install  `paddlespeech`  by the following command，then you can use the `ready-made` examples in `paddlespeech` :\n```bash\n# Some users may fail to install `kaldiio` due to the default download source, you can install `pytest-runner` at first；\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple\n# Make sure you are in the root directory of PaddleSpeech\npip install . -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n\n## Hard: Get the Full Function (Support Ubuntu)\n### Prerequisites\n- Ubuntu >= 16.04.\n- choice 1: working with `Ubuntu` Docker Container.\n- choice 2: working on `Ubuntu` with `root` privilege. \n\nTo avoid the trouble of environment setup, running in a Docker container is highly recommended. Otherwise, if you work on `Ubuntu` with `root` privilege, you can still complete the installation.\n\n### Choice 1: Running in Docker Container (Recommend)\nDocker is an open-source tool to build, ship, and run distributed applications in an isolated environment. If you  do not have a Docker environment, please refer to [Docker](https://www.docker.com/). If you will use GPU version, you also need to install [nvidia-docker](https://github.com/NVIDIA/nvidia-docker).\n\nWe provide docker images containing the latest PaddleSpeech code, and all environment and package dependencies are pre-installed. All you have to do is to **pull and run the docker image**. Then you can enjoy PaddleSpeech without any extra steps.\n\nGet these images and guidance in [docker hub](https://hub.docker.com/repository/docker/paddlecloud/paddlespeech), including CPU, GPU, ROCm environment versions. \n\nIf you have some customized requirements about automatic building docker images, you can get it in github repo [PaddlePaddle/PaddleCloud](https://github.com/PaddlePaddle/PaddleCloud/tree/main/tekton).\n\n### Choice 2: Running in Ubuntu with Root Privilege\n- Install `build-essential` by apt\n```bash\nsudo apt install build-essential\n```\n- Clone this repository\n```bash\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\n# Enter the PaddleSpeech dir\ncd PaddleSpeech\n```\n### Install the Conda\n```bash\n# download the miniconda\nwget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -P tools/\n# install the miniconda\nbash tools/Miniconda3-latest-Linux-x86_64.sh -b\n# conda init\n$HOME/miniconda3/bin/conda init\n# use the \"bash\" command to make the conda environment works\nbash\n# create a conda virtual environment\nconda create -y -p tools/venv python=3.8\n# Activate the conda virtual environment:\nconda activate tools/venv\n# Install the conda packages\nconda install -y -c conda-forge sox libsndfile swig bzip2 libflac bc\n```\n### Install PaddlePaddle\nMake sure you have GPU and the paddlepaddle version is right. For example, for CUDA 10.2, CuDNN7.6 install paddle 2.4.1:\n```bash\n# Note, 2.4 is just an example, please follow the minimum dependency of paddlepaddle for your selection\npython3 -m pip install paddlepaddle-gpu==2.4.1 -i https://mirror.baidu.com/pypi/simple\n```\nYou can also install the develop version of paddlepaddle. For example, for CUDA 10.2, CuDNN7.6 install paddlepaddle-gpu develop:\n```bash\npython3 -m pip install paddlepaddle-gpu==0.0.0.post102 -f https://www.paddlepaddle.org.cn/whl/linux/gpu/develop.html\n```\n### Install PaddleSpeech in Developing Mode\nSome users may fail to install `kaldiio` due to the default download source, you can install `pytest-runner` at first:\n```bash\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\nThen install PaddleSpeech:\n```bash\npip install -e .[develop] -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n### Install the Kaldi (Optional)\n```bash\npushd tools\nbash extras/install_openblas.sh\nbash extras/install_kaldi.sh\npopd\n```\n"
  },
  {
    "path": "docs/source/install_cn.md",
    "content": "(简体中文|[English](./install.md))\n# 安装方法\n`PaddleSpeech` 有三种安装方法。根据安装的难易程度，这三种方法可以分为 **简单**, **中等** 和 **困难**.\n| 方式 | 功能                                                         | 支持系统            |\n| :--- | :----------------------------------------------------------- | :------------------ |\n| 简单 | (1) 使用 PaddleSpeech 的命令行功能. <br> (2) 在 Aistudio上体验 PaddleSpeech. | Linux, Mac(不支持M1芯片)，Windows (安装详情查看[#1195](https://github.com/PaddlePaddle/PaddleSpeech/discussions/1195)) |\n| 中等 | 支持 PaddleSpeech 主要功能，比如使用已有 examples 中的模型和使用 PaddleSpeech 来训练自己的模型. | Linux, Mac(不支持M1芯片，不支持训练), Windows(不支持训练)               |\n| 困难 | 支持 PaddleSpeech 的各项功能，包含结合 kaldi 使用 join ctc decoder 方式解码 ([asr2](../../examples/librispeech/asr2 ))，训练语言模型,使用强制对齐等。并且你更能成为一名开发者！ | Ubuntu              |\n## 先决条件\n- Python >= 3.7\n- 最新版本的 PaddlePaddle (请看 [安装向导](https://www.paddlepaddle.org.cn/documentation/docs/en/beginners_guide/index_en.html))\n- C++ 编译环境\n- 提示: 对于 Linux 和 Mac，请不要使用 `sh` 代替安装文档中的 `bash`\n- 提示: 我们建议在安装 `paddlepaddle` 的时候使用百度源 https://mirror.baidu.com/pypi/simple ，而在安装 `paddlespeech` 的时候使用清华源 https://pypi.tuna.tsinghua.edu.cn/simple 。\n\n## 简单： 获取基本功能(支持 Linux，Mac 和 Windows)\n- 如果你是一个刚刚接触 `PaddleSpeech` 的新人并且想要很方便地体验一下该项目。我们建议你体验一下 [AI Studio](https://aistudio.baidu.com/aistudio/index)。我们在 AI Studio上面建立了一个让你一步一步运行体验来使用 `PaddleSpeech` 的[教程](https://aistudio.baidu.com/aistudio/education/group/info/25130)。\n- 如果你想使用 `PaddleSpeech` 的命令行功能，你需要跟随下面的步骤来安装 `PaddleSpeech`。如果你想了解更多关于使用 `PaddleSpeech` 命令行功能的信息，你可以参考 [cli](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/cli)。\n### 安装 Conda\nConda是一个包管理的环境。你可以前往 [miniconda](https://docs.conda.io/en/latest/miniconda.html) 去下载并安装 conda（请下载 py>=3.7 的版本）。\n然后你需要安装 `paddlespeech` 的 conda 依赖:\n```bash\nconda install -y -c conda-forge sox libsndfile bzip2\n```\n### 安装 C++ 编译环境\n(如果你系统上已经安装了 C++ 编译环境，请忽略这一步。)\n#### Windows\n对于 Windows 系统，需要安装 `Visual Studio` 来完成 C++ 编译环境的安装。\n\nhttps://visualstudio.microsoft.com/visual-cpp-build-tools/\n\n你可以前往讨论区[#1195](https://github.com/PaddlePaddle/PaddleSpeech/discussions/1195)获取更多帮助。\n\n#### Mac\n```bash\nbrew install gcc\n```\n#### Linux\n```bash\n#  centos\nsudo yum install gcc gcc-c++\n```\n```bash\n# ubuntu\nsudo apt install build-essential\n```\n```bash\n# Others\nconda install -y -c gcc_linux-64=8.4.0 gxx_linux-64=8.4.0\n```\n### 安装 PaddleSpeech\n部分用户系统由于默认源的问题，安装中会出现kaldiio安转出错的问题，建议首先安装pytest-runner:\n```bash\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple \n```\n然后你可以使用如下命令：\n```bash\npip install paddlepaddle -i https://mirror.baidu.com/pypi/simple\npip install paddlespeech -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n你也可以安装指定版本的paddlepaddle，或者安装 develop 版本。\n```bash\n# 安装2.3.1版本. 注意：2.3.1只是一个示例，请按照对paddlepaddle的最小依赖进行选择。\npip install paddlepaddle==2.3.1 -i https://mirror.baidu.com/pypi/simple\n# 安装 develop 版本\npip install paddlepaddle==0.0.0 -f https://www.paddlepaddle.org.cn/whl/linux/cpu-mkl/develop.html\n```\n> 如果您在使用 paddlespeech 的过程中遇到关于下载 **nltk_data** 的问题，可能是您的网络不佳，我们建议您下载我们提供的 [nltk_data](https://paddlespeech.cdn.bcebos.com/Parakeet/tools/nltk_data.tar.gz) 并解压缩到您的 `${HOME}` 目录下。\n\n> 如果出现 paddlespeech-ctcdecoders 无法安装的问题，无须担心，这个只影响 deepspeech2 模型的推理，不影响其他模型的使用。\n\n## 中等： 获取主要功能（支持 Linux， Mac 和 Windows 不支持训练）\n如果你想要使用 `paddlespeech` 的主要功能。你需要完成以下几个步骤\n### Git clone PaddleSpeech\n你需要先 git clone 本仓库\n```bash\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\ncd PaddleSpeech\n```\n### 安装 Conda\nConda 是一个包管理的环境。你可以前往 [minicoda](https://docs.conda.io/en/latest/miniconda.html) 去下载并安装 conda（请下载 py>=3.7 的版本）。windows 系统可以使用 conda 的向导安装，linux 和 mac 可以使用以下的命令：\n```bash\n# 下载 miniconda\nwget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -P tools/\n# 安装 miniconda\nbash tools/Miniconda3-latest-Linux-x86_64.sh -b\n# conda 初始化\n$HOME/miniconda3/bin/conda init\n# 激活 conda\nbash\n```\n然后你可以创建一个 conda 的虚拟环境：\n```bash\nconda create -y -p tools/venv python=3.8\n```\n激活 conda 虚拟环境：\n```bash\nconda activate tools/venv\n```\n安装 `paddlespeech` 的 conda 依赖：\n```bash\nconda install -y -c conda-forge sox libsndfile swig bzip2\n```\n### 安装 C++ 编译环境\n(如果你系统上已经安装了 C++ 编译环境，请忽略这一步。)\n你可以使用如下的步骤来安装 C++ 的编译环境 `gcc`  和 `gxx`：\n```bash\n#  centos\nsudo yum install gcc gcc-c++\n```\n```bash\n# ubuntu\nsudo apt install build-essential\n```\n```bash\n# Others\nconda install -y -c gcc_linux-64=8.4.0 gxx_linux-64=8.4.0\n```\n（提示： 如果你想使用**困难**方式完成安装，请不要使用最后一条命令）\n### 安装 PaddlePaddle\n你可以根据系统配置选择 PaddlePaddle 版本，例如系统使用 CUDA 10.2， CuDNN7.6，你可以安装 paddlepaddle-gpu 2.4.1：\n```bash\n# 注意：2.4.1 只是一个示例，请按照对paddlepaddle的最小依赖进行选择。\npython3 -m pip install paddlepaddle-gpu==2.4.1 -i https://mirror.baidu.com/pypi/simple\n```\n你也可以安装 develop 版本的PaddlePaddle. 例如系统使用 CUDA 10.2， CuDNN7.6 ，你可以安装 paddlepaddle-gpu develop:\n```bash\npython3 -m pip install paddlepaddle-gpu==0.0.0.post102 -f https://www.paddlepaddle.org.cn/whl/linux/gpu/develop.html\n```\n### 安装 PaddleSpeech\n最后安装 `paddlespeech`，这样你就可以使用 `paddlespeech` 中已有的 examples：\n```bash\n# 部分用户系统由于默认源的问题，安装中会出现 kaldiio 安转出错的问题，建议首先安装pytest-runner:\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple \n# 请确保目前处于PaddleSpeech项目的根目录\npip install . -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n## 困难： 获取所有功能（支持 Ubuntu）\n### 先决条件\n- Ubuntu >= 16.04\n- 选择 1： 使用`Ubuntu` docker。\n- 选择 2： 使用`Ubuntu` ，并且拥有 root 权限。\n\n为了避免各种环境配置问题，我们非常推荐你使用 docker 容器。如果你不想使用 docker，但是可以使用拥有 root 权限的 Ubuntu 系统，你也可以完成**困难**方式的安装。\n### 选择1： 使用 Docker 容器（推荐）\nDocker 是一种开源工具，用于在和系统本身环境相隔离的环境中构建、发布和运行各类应用程序。如果您没有 Docker 运行环境，请参考 [Docker 官网](https://www.docker.com/)进行安装，如果您准备使用 GPU 版本镜像，还需要提前安装好 [nvidia-docker](https://github.com/NVIDIA/nvidia-docker) 。 \n\n我们提供了包含最新 PaddleSpeech 代码的 docker 镜像，并预先安装好了所有的环境和库依赖，您只需要**拉取并运行 docker 镜像**，无需其他任何额外操作，即可开始享用 PaddleSpeech 的所有功能。\n\n在 [Docker Hub](https://hub.docker.com/repository/docker/paddlecloud/paddlespeech) 中获取这些镜像及相应的使用指南，包括 CPU、GPU、ROCm 版本。\n\n如果您对自动化制作 docker 镜像感兴趣，或有自定义需求，请访问 [PaddlePaddle/PaddleCloud](https://github.com/PaddlePaddle/PaddleCloud/tree/main/tekton) 做进一步了解。\n完成这些以后，你就可以在 docker 容器中执行训练、推理和超参 fine-tune。\n### 选择2： 使用有 root 权限的 Ubuntu\n- 使用apt安装 `build-essential`\n```bash\nsudo apt install build-essential\n```\n- 克隆 `PaddleSpeech` 仓库\n```bash\ngit clone https://github.com/PaddlePaddle/PaddleSpeech.git\n# 进入PaddleSpeech目录\ncd PaddleSpeech\n```\n### 安装 Conda\n```bash\n# 下载 miniconda\nwget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -P tools/\n# 安装 miniconda\nbash tools/Miniconda3-latest-Linux-x86_64.sh -b\n# conda 初始化\n$HOME/miniconda3/bin/conda init\n# 激活 conda\nbash\n# 创建 Conda 虚拟环境\nconda create -y -p tools/venv python=3.8\n# 激活 Conda 虚拟环境:\nconda activate tools/venv\n# 安装 Conda 包\nconda install -y -c conda-forge sox libsndfile swig bzip2 libflac bc\n```\n### 安装 PaddlePaddle\n请确认你系统是否有 GPU，并且使用了正确版本的 paddlepaddle。例如系统使用 CUDA 10.2, CuDNN7.6 ，你可以安装 paddlepaddle-gpu 2.4.1：\n```bash\n# 注意：2.4.1 只是一个示例，请按照对paddlepaddle的最小依赖进行选择。\npython3 -m pip install paddlepaddle-gpu==2.4.1 -i https://mirror.baidu.com/pypi/simple\n```\n你也可以安装 develop 版本的PaddlePaddle. 例如系统使用 CUDA 10.2， CuDNN7.6 ，你可以安装 paddlepaddle-gpu develop:\n```bash\npython3 -m pip install paddlepaddle-gpu==0.0.0.post102 -f https://www.paddlepaddle.org.cn/whl/linux/gpu/develop.html\n```\n### 用开发者模式安装 PaddleSpeech\n部分用户系统由于默认源的问题，安装中会出现 kaldiio 安转出错的问题，建议首先安装 pytest-runner:\n```bash\npip install pytest-runner -i https://pypi.tuna.tsinghua.edu.cn/simple \n```\n然后安装 PaddleSpeech：\n```bash\npip install -e .[develop] -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n### 安装 Kaldi（可选）\n```bash\npushd tools\nbash extras/install_openblas.sh\nbash extras/install_kaldi.sh\npopd\n```\n"
  },
  {
    "path": "docs/source/introduction.md",
    "content": "# PaddleSpeech\n\n## What is PaddleSpeech?\nPaddleSpeech is an open-source toolkit on the PaddlePaddle platform for two critical tasks in Speech -  Speech-to-Text (Automatic Speech Recognition, ASR) and Text-to-Speech Synthesis (TTS), with modules involving state-of-art and influential models.\n\n## What can PaddleSpeech do?\n\n### Speech-to-Text\nPaddleSpeech ASR mainly consists of components below:\n- Implementation of models and commonly used neural network layers.\n- Dataset abstraction and common data preprocessing pipelines.\n- Ready-to-run experiments.\n\nPaddleSpeech ASR provides you with a complete ASR pipeline, including:\n- Data Preparation\n    - Build vocabulary\n    - Compute Cepstral mean and variance normalization (CMVN)\n    - Featrue extraction\n        - linear\n        - fbank (also support kaldi feature)\n        - mfcc\n- Acoustic Models\n    - Deepspeech2 (Streaming and Non-Streaming)\n    - Transformer (Streaming and Non-Streaming)\n    - Conformer (Streaming and Non-Streaming)\n- Decoder\n    - ctc greedy search (used in DeepSpeech2, Transformer and Conformer)\n    - ctc beam search (used in DeepSpeech2, Transformer and Conformer)\n    - attention decoding (used in Transformer and Conformer)\n    - attention rescoring (used in Transformer and Conformer)\n\nSpeech-to-Text helps you train the ASR model very simply.\n\n### Text-to-Speech\nTTS mainly consists of components below:\n- Implementation of models and commonly used neural network layers.\n- Dataset abstraction and common data preprocessing pipelines.\n- Ready-to-run experiments.\n\nPaddleSpeech TTS provides you with a complete TTS pipeline, including:\n- Text FrontEnd\n    - Rule based Chinese frontend.\n- Acoustic Models\n    - FastSpeech2\n    - SpeedySpeech\n    - TransformerTTS\n    - Tacotron2\n- Vocoders\n    - Multi Band MelGAN\n    - Parallel WaveGAN\n    - WaveFlow\n- Voice Cloning\n    - Transfer Learning from Speaker Verification to Multispeaker Text-to-Speech Synthesis\n    - GE2E\n\nText-to-Speech helps you to train TTS models with simple commands.\n"
  },
  {
    "path": "docs/source/reference.md",
    "content": "# Reference\n\nWe borrowed a lot of code from these repos to build `model` and `engine`, thanks for these great works and the open-source community!\n\n* [espnet](https://github.com/espnet/espnet/blob/master/LICENSE)\n- Apache-2.0 License\n- python/shell `utils`\n- kaldi feat preprocessing\n- data pipe line and `transformer`\n- some tts models, like `fastspeech2` and GAN-based `vocoder`\n\n* [wenet](https://github.com/wenet-e2e/wenet/blob/main/LICENSE)\n- Apache-2.0 License\n- U2 model\n- Building TLG based Graph\n- websocket server & client\n\n* [kaldi](https://github.com/kaldi-asr/kaldi/blob/master/COPYING)\n- Apache-2.0 License\n- shell/perl/python utils.\n- feature bins.\n- WFST based decoding for LM integration.\n\n* [delta](https://github.com/Delta-ML/delta/blob/master/LICENSE)\n- Apache-2.0 License\n- `engine` arch\n\n* [speechbrain](https://github.com/speechbrain/speechbrain/blob/develop/LICENSE)\n- Apache-2.0 License\n- ECAPA-TDNN SV model\n- ASR with CTC and pre-trained wav2vec2 models.\n\n\n* [chainer](https://github.com/chainer/chainer/blob/master/LICENSE)\n- MIT License\n- Updater, Trainer, and some utils.\n\n* [librosa](https://github.com/librosa/librosa/blob/main/LICENSE.md)\n- ISC License\n- Audio feature\n\n* [ThreadPool](https://github.com/progschj/ThreadPool/blob/master/COPYING)\n- zlib License\n- ThreadPool\n\n* [g2pW](https://github.com/GitYCC/g2pW/blob/master/LICENCE)\n- Apache-2.0 license\n\n*[transformers](https://github.com/huggingface/transformers)\n- Apache-2.0 License\n- Wav2vec2.0\n"
  },
  {
    "path": "docs/source/released_model.md",
    "content": "# Released Models\n\n> !!! Since PaddlePaddle support 0-D tensor from 2.5.0, PaddleSpeech Static model will not work for it, please re-export static model.\n\n## Speech-to-Text Models\n\n### Speech Recognition Model\nAcoustic Model | Training Data | Token-based | Size | Descriptions | CER | WER | Hours of speech | Example Link | Inference Type | static_model | \n:-------------:| :------------:| :-----: | -----: | :-----: |:-----:| :-----:  | :-----:  | :-----: | :-----: | :-----: |\n[Ds2 Online Wenetspeech ASR0 Model](https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.4.model.tar.gz) | Wenetspeech Dataset | Char-based | 1.2 GB  | 2 Conv + 5 LSTM layers | 0.152 (test\\_net, w/o LM) <br> 0.2417 (test\\_meeting, w/o LM) <br> 0.053 (aishell, w/ LM) |-| 10000 h | - | onnx/inference/python |-|\n[Ds2 Online Aishell ASR0 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_fbank161_ckpt_0.2.1.model.tar.gz) | Aishell Dataset | Char-based | 491 MB  | 2 Conv + 5 LSTM layers | 0.0666 |-| 151 h | [D2 Online Aishell ASR0](../../examples/aishell/asr0) | onnx/inference/python |-|\n[Ds2 Offline Aishell ASR0 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz)| Aishell Dataset | Char-based | 1.4 GB | 2 Conv + 5 bidirectional LSTM layers| 0.0554 |-| 151 h | [Ds2 Offline Aishell ASR0](../../examples/aishell/asr0) | inference/python |-|\n[Conformer Online Wenetspeech ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz) | WenetSpeech Dataset | Char-based | 457 MB  | Encoder:Conformer, Decoder:Transformer, Decoding method: Attention rescoring| 0.11 (test\\_net) 0.1879 (test\\_meeting) |-| 10000 h |- | python |-|\n[Conformer U2PP Online Wenetspeech ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2pp_wenetspeech_ckpt_1.3.0.model.tar.gz) | WenetSpeech Dataset | Char-based | 540 MB  | Encoder:Conformer, Decoder:BiTransformer, Decoding method: Attention rescoring| 0.047198 (aishell test\\_-1) 0.059212 (aishell test\\_16) |-| 10000 h |- | python |[FP32](https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2pp_wenetspeech_ckpt_1.3.0.model.tar.gz) </br>[INT8](https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/static/asr1_chunk_conformer_u2pp_wenetspeech_static_quant_1.3.0.model.tar.gz) |\n[Conformer Online Aishell ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_conformer_aishell_ckpt_1.5.0.model.tar.gz) | Aishell Dataset | Char-based | 189 MB  | Encoder:Conformer, Decoder:Transformer, Decoding method: Attention rescoring| 0.051968 |-| 151 h | [Conformer Online Aishell ASR1](../../examples/aishell/asr1) | python |-|\n[Conformer Offline Aishell ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_conformer_aishell_ckpt_1.0.1.model.tar.gz) | Aishell Dataset | Char-based | 189 MB  | Encoder:Conformer, Decoder:Transformer, Decoding method: Attention rescoring | 0.0460 |-| 151 h | [Conformer Offline Aishell ASR1](../../examples/aishell/asr1) | python |-|\n[Transformer Aishell ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_transformer_aishell_ckpt_0.1.1.model.tar.gz) | Aishell Dataset | Char-based | 128 MB | Encoder:Transformer, Decoder:Transformer, Decoding method: Attention rescoring | 0.0523 || 151 h | [Transformer  Aishell ASR1](../../examples/aishell/asr1) | python |-|\n[Ds2 Offline Librispeech ASR0 Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr0/asr0_deepspeech2_offline_librispeech_ckpt_1.0.1.model.tar.gz)| Librispeech Dataset | Char-based | 1.3 GB | 2 Conv + 5 bidirectional LSTM layers| - |0.0467| 960 h | [Ds2 Offline Librispeech ASR0](../../examples/librispeech/asr0) | inference/python |-|\n[Conformer Librispeech ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr1/asr1_conformer_librispeech_ckpt_0.1.1.model.tar.gz) | Librispeech Dataset | subword-based | 191 MB | Encoder:Conformer, Decoder:Transformer, Decoding method: Attention rescoring |-| 0.0338 | 960 h | [Conformer Librispeech ASR1](../../examples/librispeech/asr1) | python |-|\n[Transformer Librispeech ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr1/asr1_transformer_librispeech_ckpt_0.1.1.model.tar.gz) | Librispeech Dataset | subword-based | 131 MB  | Encoder:Transformer, Decoder:Transformer, Decoding method: Attention rescoring |-| 0.0381 | 960 h | [Transformer Librispeech ASR1](../../examples/librispeech/asr1) | python |-|\n[Transformer Librispeech ASR2 Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr2/asr2_transformer_librispeech_ckpt_0.1.1.model.tar.gz) | Librispeech Dataset | subword-based | 131 MB  | Encoder:Transformer, Decoder:Transformer, Decoding method: JoinCTC w/ LM |-| 0.0240 | 960 h | [Transformer Librispeech ASR2](../../examples/librispeech/asr2) | python |-|\n[Conformer TALCS ASR1 Model](https://paddlespeech.cdn.bcebos.com/s2t/tal_cs/asr1/asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz) | TALCS Dataset | subword-based | 470 MB | Encoder:Conformer, Decoder:Transformer, Decoding method: Attention rescoring |-| 0.0844 | 587 h | [Conformer TALCS ASR1](../../examples/tal_cs/asr1) | python |-|\n\n### Self-Supervised Pre-trained Model\nModel | Pre-Train Method | Pre-Train Data | Finetune Data | Size | Descriptions | CER | WER |  Example Link |\n:-------------:| :------------:| :-----: | -----: | :-----: |:-----:| :-----:  | :-----:  | :-----: | \n[Wav2vec2-large-960h-lv60-self Model](https://paddlespeech.cdn.bcebos.com/wav2vec/wav2vec2-large-960h-lv60-self.pdparams) | wav2vec2 | Librispeech and LV-60k Dataset (5.3w h) | - | 1.18 GB |Pre-trained Wav2vec2.0 Model | - | - | - | \n[Wav2vec2ASR-large-960h-librispeech Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr3/wav2vec2ASR-large-960h-librispeech_ckpt_1.3.1.model.tar.gz) | wav2vec2 | Librispeech and LV-60k Dataset (5.3w h) | Librispeech (960 h) | 718 MB |Encoder: Wav2vec2.0, Decoder: CTC, Decoding method: Greedy search | - | 0.0189 | [Wav2vecASR Librispeech ASR3](../../examples/librispeech/asr3) |\n[Wav2vec2-large-wenetspeech-self Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2-large-wenetspeech-self_ckpt_1.3.0.model.tar.gz) | wav2vec2 | Wenetspeech Dataset (1w h) | - | 714 MB |Pre-trained Wav2vec2.0 Model | - | - | - | \n[Wav2vec2ASR-large-aishell1 Model](https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz) | wav2vec2 | Wenetspeech Dataset (1w h) | aishell1 (train set) | 1.18 GB |Encoder: Wav2vec2.0, Decoder: CTC, Decoding method: Greedy search | 0.0510 | - | - |\n[Hubert-large-lv60 Model](https://paddlespeech.cdn.bcebos.com/hubert/hubert-large-lv60.pdparams) | hubert | LV-60k Dataset | - | 1.18 GB |Pre-trained hubert Model | - | - | - | \n[Hubert-large-100h-librispeech Model](https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr4/hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz) | hubert | LV-60k Dataset | librispeech train-clean-100 | 1.27 GB |Encoder: Hubert, Decoder: Linear + CTC, Decoding method: Greedy search | - | 0.0587 | [HubertASR Librispeech ASR4](../../examples/librispeech/asr4) |\n\n### Whisper Model\nDemo Link | Training Data | Size | Descriptions | CER | Model \n:-----------: | :-----:| :-------: | :-----: | :-----: |:---------:|\n[Whisper](../../demos/whisper) | 680kh from internet | large: 5.8G,</br>medium: 2.9G,</br>small: 923M,</br>base: 277M,</br>tiny: 145M | Encoder:Transformer,</br> Decoder:Transformer, </br>Decoding method: </br>Greedy search | 0.027 </br>(large, Librispeech) | [whisper-large](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-large-model.tar.gz) </br>[whisper-medium](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-medium-model.tar.gz) </br>[whisper-medium-English-only](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-medium-en-model.tar.gz) </br>[whisper-small](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-small-model.tar.gz) </br>[whisper-small-English-only](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-small-en-model.tar.gz) </br>[whisper-base](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-base-model.tar.gz) </br>[whisper-base-English-only](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-base-en-model.tar.gz) </br>[whisper-tiny](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-tiny-model.tar.gz) </br>[whisper-tiny-English-only](https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-tiny-en-model.tar.gz)\n\n### Language Model based on NGram\n|Language Model | Training Data | Token-based | Size | Descriptions|\n| :------------: | :------------: | :------------: | :------------: | :------------: |\n[English LM](https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm) |  [CommonCrawl(en.00)](http://web-language-models.s3-website-us-east-1.amazonaws.com/ngrams/en/deduped/en.00.deduped.xz) | Word-based | 8.3 GB | Pruned with 0 1 1 1 1; <br/> About 1.85 billion n-grams; <br/> 'trie'  binary with '-a 22 -q 8 -b 8'\n[Mandarin LM Small](https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm) | Baidu Internal Corpus | Char-based | 2.8 GB | Pruned with 0 1 2 4 4; <br/> About 0.13 billion n-grams; <br/> 'probing' binary with default settings\n[Mandarin LM Large](https://deepspeech.bj.bcebos.com/zh_lm/zhidao_giga.klm) | Baidu Internal Corpus | Char-based | 70.4 GB | No Pruning; <br/> About 3.7 billion n-grams; <br/> 'probing' binary with default settings\n\n### Speech Translation Models\n\n| Model | Training Data | Token-based | Size | Descriptions | BLEU | Example Link |\n| :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: |\n| (only for CLI)[Transformer FAT-ST MTL En-Zh](https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/st1_transformer_mtl_noam_ted-en-zh_ckpt_0.1.1.model.tar.gz) | Ted-En-Zh| Spm| | Encoder:Transformer, Decoder:Transformer, <br />Decoding method: Attention | 20.80 | [Transformer Ted-En-Zh ST1](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/ted_en_zh/st1) |\n\n## Text-to-Speech Models\n\n### Acoustic Models\nModel Type | Dataset| Example Link | Pretrained Models|Static / ONNX / Paddle-Lite Models|Size (static)\n:-------------:| :------------:| :-----: | :-----:| :-----:| :-----:\nTacotron2|LJSpeech|[tacotron2-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/tts0)|[tacotron2_ljspeech_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_ljspeech_ckpt_0.2.0.zip)|||\nTacotron2|CSMSC|[tacotron2-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts0)|[tacotron2_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_csmsc_ckpt_0.2.0.zip)|[tacotron2_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_csmsc_static_0.2.0.zip)|103MB|\nTransformerTTS| LJSpeech| [transformer-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/tts1)|[transformer_tts_ljspeech_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/transformer_tts/transformer_tts_ljspeech_ckpt_0.4.zip)|||\nSpeedySpeech| CSMSC | [speedyspeech-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts2)|[speedyspeech_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_ckpt_0.2.0.zip)|[speedyspeech_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_static_0.2.0.zip) </br> [speedyspeech_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_onnx_0.2.0.zip) </br> [speedyspeech_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_pdlite_1.3.0.zip)|13MB|\nFastSpeech2| CSMSC |[fastspeech2-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3)|[fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)|[fastspeech2_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_static_0.2.0.zip) </br> [fastspeech2_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip) </br> [fastspeech2_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_pdlite_1.3.0.zip)|157MB|\nFastSpeech2-Conformer| CSMSC |[fastspeech2-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3)|[fastspeech2_conformer_baker_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip)|||\nFastSpeech2-CNNDecoder| CSMSC| [fastspeech2-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3)| [fastspeech2_cnndecoder_csmsc_ckpt_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_ckpt_1.0.0.zip) |  [fastspeech2_cnndecoder_csmsc_static_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_static_1.0.0.zip) </br>[fastspeech2_cnndecoder_csmsc_streaming_static_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_static_1.0.0.zip)  </br>[fastspeech2_cnndecoder_csmsc_onnx_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_onnx_1.0.0.zip)  </br>[fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip)  </br> [fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip) </br> [fastspeech2_cnndecoder_csmsc_streaming_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_pdlite_1.3.0.zip)| 84MB|\nFastSpeech2| AISHELL-3 |[fastspeech2-aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3)|[fastspeech2_aishell3_ckpt_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_1.1.0.zip)|[fastspeech2_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_static_1.1.0.zip) </br> [fastspeech2_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_onnx_1.1.0.zip) </br> [fastspeech2_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_pdlite_1.3.0.zip) |147MB|\nFastSpeech2| LJSpeech |[fastspeech2-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/tts3)|[fastspeech2_nosil_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip)|[fastspeech2_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_static_1.1.0.zip) </br> [fastspeech2_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_onnx_1.1.0.zip) </br> [fastspeech2_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_pdlite_1.3.0.zip)|145MB|\nFastSpeech2| VCTK |[fastspeech2-vctk](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/tts3)|[fastspeech2_vctk_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_ckpt_1.2.0.zip)|[fastspeech2_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_static_1.1.0.zip) </br> [fastspeech2_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_onnx_1.1.0.zip) </br> [fastspeech2_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_pdlite_1.3.0.zip)| 145MB|\nFastSpeech2| ZH_EN |[fastspeech2-zh_en](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/zh_en_tts/tts3)|[fastspeech2_mix_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_1.2.0.zip)|[fastspeech2_mix_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_static_0.2.0.zip) </br> [fastspeech2_mix_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_onnx_0.2.0.zip) | 145MB|\nFastSpeech2| male-zh ||[fastspeech2_male_zh_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_ckpt_1.4.0.zip)|[fastspeech2_male_zh_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_static_1.4.0.zip) </br> [fastspeech2_male_zh_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_onnx_1.4.0.zip) |146MB|\nFastSpeech2| male-en ||[fastspeech2_male_en_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_ckpt_1.4.0.zip)|[fastspeech2_male_en_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_static_1.4.0.zip) </br> [fastspeech2_male_en_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_onnx_1.4.0.zip) |145MB|\nFastSpeech2| male-mix ||[fastspeech2_male_mix_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_ckpt_1.4.0.zip)|[fastspeech2_male_mix_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_static_1.4.0.zip) </br> [fastspeech2_male_mix_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_onnx_1.4.0.zip) |146MB|\nFastSpeech2| Cantonese |[fastspeech2-canton](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/canton/tts3)|[fastspeech2_canton_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_ckpt_1.4.0.zip)|[fastspeech2_canton_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_static_1.4.0.zip)</br>[fastspeech2_canton_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_onnx_1.4.0.zip)|146MB|\n\n### Vocoders\nModel Type | Dataset| Example Link | Pretrained Models| Static / ONNX / Paddle-Lite Models|Size (static)\n:-----:| :-----:| :-----: | :-----:| :-----:| :-----:\nWaveFlow| LJSpeech |[waveflow-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc0)|[waveflow_ljspeech_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/waveflow/waveflow_ljspeech_ckpt_0.3.zip)|||\nParallel WaveGAN| CSMSC |[PWGAN-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1)|[pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip)|[pwg_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_static_0.4.zip) </br> [pwgan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_csmsc_onnx_0.2.0.zip) </br> [pwgan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_csmsc_pdlite_1.3.0.zip)|4.8MB|\nParallel WaveGAN| LJSpeech |[PWGAN-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc1)|[pwg_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_ljspeech_ckpt_0.5.zip)|[pwgan_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_static_1.1.0.zip) </br> [pwgan_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_onnx_1.1.0.zip) </br> [pwgan_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_pdlite_1.3.0.zip)|4.8MB|\nParallel WaveGAN| AISHELL-3 |[PWGAN-aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1)|[pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip)| [pwgan_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_static_1.1.0.zip) </br> [pwgan_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_onnx_1.1.0.zip) </br> [pwgan_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_pdlite_1.3.0.zip)|4.8MB|\nParallel WaveGAN| VCTK |[PWGAN-vctk](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/voc1)|[pwg_vctk_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_vctk_ckpt_0.5.zip)|[pwgan_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_static_1.1.0.zip) </br> [pwgan_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_onnx_1.1.0.zip) </br> [pwgan_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_pdlite_1.3.0.zip)|4.8MB|\n|Multi Band MelGAN | CSMSC |[MB MelGAN-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc3) | [mb_melgan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_ckpt_0.1.1.zip) <br>[mb_melgan_baker_finetune_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_baker_finetune_ckpt_0.5.zip)|[mb_melgan_csmsc_static_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_static_0.1.1.zip) </br> [mb_melgan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip) </br> [mb_melgan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_pdlite_1.3.0.zip)|7.6MB|\nStyle MelGAN | CSMSC |[Style MelGAN-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc4)|[style_melgan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/style_melgan/style_melgan_csmsc_ckpt_0.1.1.zip)| | |\nHiFiGAN | CSMSC |[HiFiGAN-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc5)|[hifigan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_ckpt_0.1.1.zip)|[hifigan_csmsc_static_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_static_0.1.1.zip) </br> [hifigan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_onnx_0.2.0.zip) </br> [hifigan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_pdlite_1.3.0.zip)|46MB|\nHiFiGAN | LJSpeech |[HiFiGAN-ljspeech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc5)|[hifigan_ljspeech_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_ckpt_0.2.0.zip)|[hifigan_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_static_1.1.0.zip) </br> [hifigan_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_onnx_1.1.0.zip) </br> [hifigan_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_pdlite_1.3.0.zip) |49MB|\nHiFiGAN | AISHELL-3 |[HiFiGAN-aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc5)|[hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip)|[hifigan_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_static_1.1.0.zip) </br> [hifigan_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_onnx_1.1.0.zip) </br> [hifigan_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_pdlite_1.3.0.zip)|46MB|\nHiFiGAN | VCTK |[HiFiGAN-vctk](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/voc5)|[hifigan_vctk_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip)|[hifigan_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_static_1.1.0.zip) </br> [hifigan_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_onnx_1.1.0.zip) </br> [hifigan_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_pdlite_1.3.0.zip)|46MB|\nWaveRNN | CSMSC |[WaveRNN-csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc6)|[wavernn_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_ckpt_0.2.0.zip)|[wavernn_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_static_0.2.0.zip)|18MB|\nParallel WaveGAN| Male ||[pwg_male_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_male_ckpt_1.4.0.zip)|[pwgan_male_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_male_static_1.4.0.zip) </br> [pwgan_male_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_male_onnx_1.4.0.zip)|4.8M|\nHiFiGAN| Male ||[hifigan_male_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_ckpt_1.4.0.zip)|[hifigan_male_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_static_1.4.0.zip) </br> [hifigan_male_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_onnx_1.4.0.zip)|46M|\n\n\n### Voice Cloning\nModel Type | Dataset| Example Link | Pretrained Models\n:-------------:| :------------:| :-----: | :-----: | \nGE2E| AISHELL-3, etc. |[ge2e](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/ge2e)|[ge2e_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip)\nGE2E + Tacotron2| AISHELL-3 |[ge2e-Tacotron2-aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc0)|[tacotron2_aishell3_ckpt_vc0_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_aishell3_ckpt_vc0_0.2.0.zip)\nGE2E + FastSpeech2 | AISHELL-3  |[ge2e-fastspeech2-aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc1)|[fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip)\n\n\n## Audio Classification Models\n\nModel Type | Dataset| Example Link | Pretrained Models | Static Models \n:-------------:| :------------:| :-----: | :-----: | :-----:\nPANN | Audioset| [audioset_tagging_cnn](https://github.com/qiuqiangkong/audioset_tagging_cnn) | [panns_cnn6.pdparams](https://bj.bcebos.com/paddleaudio/models/panns_cnn6.pdparams), [panns_cnn10.pdparams](https://bj.bcebos.com/paddleaudio/models/panns_cnn10.pdparams), [panns_cnn14.pdparams](https://bj.bcebos.com/paddleaudio/models/panns_cnn14.pdparams) | [panns_cnn6_static.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn6_static.tar.gz)(18M), [panns_cnn10_static.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn10_static.tar.gz)(19M), [panns_cnn14_static.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn14_static.tar.gz)(289M) \nPANN | ESC-50 |[pann-esc50](../../examples/esc50/cls0)|[esc50_cnn6.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/esc50/esc50_cnn6.tar.gz), [esc50_cnn10.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/esc50/esc50_cnn10.tar.gz), [esc50_cnn14.tar.gz](https://paddlespeech.cdn.bcebos.com/cls/esc50/esc50_cnn14.tar.gz)\n\n## Speaker Verification Models\n\nModel Type | Dataset| Example Link | Pretrained Models | Static Models \n:-------------:| :------------:| :-----: | :-----: | :-----:\nECAPA-TDNN | VoxCeleb| [voxceleb_ecapatdnn](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/voxceleb/sv0) | [ecapatdnn.tar.gz](https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz) | -\n\n## Punctuation Restoration Models\nModel Type | Dataset| Example Link | Pretrained Models\n:-------------:| :------------:| :-----: | :-----:\nErnie Linear | IWLST2012_zh |[iwslt2012_punc0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/iwslt2012/punc0)|[ernie_linear_p3_iwslt2012_zh_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/text/ernie_linear_p3_iwslt2012_zh_ckpt_0.1.1.zip)\n"
  },
  {
    "path": "docs/source/streaming_asr_demo_video.rst",
    "content": "Streaming ASR Demo Video\n==================\n\n.. raw:: html\n     \n    <video controls width=\"1024\">\n\n    <source src=\"https://paddlespeech.cdn.bcebos.com/demos/asr_demos/streaming_ASR_slice.mp4\" type=\"video/mp4\">\n    Sorry, your browser doesn't support embedded videos.\n    </video>\n"
  },
  {
    "path": "docs/source/streaming_tts_demo_video.rst",
    "content": "Streaming TTS Demo Video\n==================\n\n.. raw:: html\n     \n    <video controls width=\"1024\">\n\n    <source src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/streaming_tts_demo.mp4\"\n            type=\"video/mp4\">\n    Sorry, your browser doesn't support embedded videos.\n    </video>\n\n"
  },
  {
    "path": "docs/source/tts/PPTTS.md",
    "content": "([简体中文](./PPTTS_cn.md)|English)\n\n# PPTTS\n\n- [1. Introduction](#1)\n- [2. Characteristic](#2)\n- [3. Benchmark](#3)\n- [4. Demo](#4)\n- [5. Tutorials](#5)\n    - [5.1 Training and Inference Optimization](#51)\n    - [5.2 Characteristic APPs of TTS](#52)\n    - [5.3 TTS Server](#53)\n\n<a name=\"1\"></a>\n## 1. Introduction\n\nPP-TTS is a streaming speech synthesis system developed by PaddleSpeech. Based on the implementation of [SOTA Algorithms](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md#text-to-speech-models), a faster inference engine is used to realize streaming speech synthesis technology to meet the needs of commercial speech interaction scenarios.\n\n#### PP-TTS\nPipline of TTS：\n<center><img src=https://ai-studio-static-online.cdn.bcebos.com/ea69ae1faff84940a59c7079d16b3a8db2741d2c423846f68822f4a7f28726e9 width=\"600\" ></center>\n\nPP-TTS provides a Chinese streaming speech synthesis system based on FastSpeech2 and HiFiGAN by default:\n\n- Text Frontend： The rule-based Chinese text frontend system is adopted to optimize Chinese text such as text normalization, polyphony, and tone sandhi.\n- Acoustic Model: The decoder of FastSpeech2 is improved so that it can be stream synthesized\n- Vocoder: Streaming synthesis of GAN vocoder is supported\n- Inference Engine： Using ONNXRuntime to optimize the inference of TTS models, so that the TTS system can also achieve RTF < 1 on low-voltage, meeting the requirements of streaming synthesis\n\n<a name=\"2\"></a>\n## 2. Characteristic\n- Open source leading Chinese TTS system\n- Using ONNXRuntime to optimize the inference of TTS models\n- The only open-source streaming TTS system\n- Easy disassembly: Developers can easily replace different acoustic models and vocoders in different languages, use different inference engines (Paddle dynamic graph, PaddleInference, ONNXRuntime, etc.), and use different network services (HTTP, WebSocket)\n\n<a name=\"3\"></a>\n## 3. Benchmark\nPaddleSpeech TTS models' benchmark: [TTS-Benchmark](https://github.com/PaddlePaddle/PaddleSpeech/wiki/TTS-Benchmark)。\n\n<a name=\"4\"></a>\n## 4. Demo \nSee: [Streaming TTS Demo Video](https://paddlespeech.readthedocs.io/en/latest/streaming_tts_demo_video.html)\n\n<a name=\"5\"></a>\n## 5. Tutorials\n\n<a name=\"51\"></a>\n### 5.1 Training and Inference Optimization\n\nDefault FastSpeech2: [tts3/run.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/tts3/run.sh)\n\nStreaming FastSpeech2: [tts3/run_cnndecoder.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/tts3/run_cnndecoder.sh)\n\nHiFiGAN：[voc5/run.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/voc5/run.sh)\n\n<a name=\"52\"></a>\n### 5.2 Characteristic APPs of TTS\ntext_to_speech - convert text into speech: [text_to_speech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/text_to_speech)\n\nstyle_fs2 - multi style control for FastSpeech2 model: [style_fs2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/style_fs2)\n\nstory talker - book reader based on OCR and TTS: [story_talker](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/story_talker)\n\nmetaverse - 2D AR with TTS: [metaverse](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/metaverse)\n\n<a name=\"53\"></a>\n### 5.3 TTS Server\n\nNon-streaming TTS Server: [speech_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/speech_server)\n\nStreaming TTS Server: [streaming_tts_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/streaming_tts_server)\n\n\nFor more tutorials please see: [PP-TTS：流式语音合成原理及服务部署\n](https://aistudio.baidu.com/aistudio/projectdetail/3885352)\n"
  },
  {
    "path": "docs/source/tts/PPTTS_cn.md",
    "content": "(简体中文|[English](./PPTTS.md))\n\n# PP-TTS\n\n- [1. 简介](#1)\n- [2. 特性](#2)\n- [3. Benchmark](#3)\n- [4. 效果展示](#4)\n- [5. 使用教程](#5)\n    - [5.1 模型训练与推理优化](#51)\n    - [5.2 语音合成特色应用](#52)\n    - [5.3 语音合成服务搭建](#53)\n\n<a name=\"1\"></a>\n## 1. 简介\n\nPP-TTS 是 PaddleSpeech 自研的流式语音合成系统。在实现[前沿算法](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md#text-to-speech-models)的基础上，使用了更快的推理引擎，实现了流式语音合成技术，使其满足商业语音交互场景的需求。\n\n#### PP-TTS\n语音合成基本流程如下图所示：\n<center><img src=https://ai-studio-static-online.cdn.bcebos.com/ea69ae1faff84940a59c7079d16b3a8db2741d2c423846f68822f4a7f28726e9 width=\"600\" ></center>\n\nPP-TTS 默认提供基于 FastSpeech2 声学模型和 HiFiGAN 声码器的中文流式语音合成系统：\n\n- 文本前端：采用基于规则的中文文本前端系统，对文本正则、多音字、变调等中文文本场景进行了优化。\n- 声学模型：对 FastSpeech2 模型的 Decoder 进行改进，使其可以流式合成\n- 声码器：支持对 GAN Vocoder 的流式合成\n- 推理引擎：使用 ONNXRuntime 推理引擎优化模型推理性能，使得语音合成系统在低压 CPU 上也能达到 RTF<1，满足流式合成的要求\n\n<a name=\"2\"></a>\n## 2. 特性\n- 开源领先的中文语音合成系统\n- 使用 ONNXRuntime 推理引擎优化模型推理性能\n- 唯一开源的流式语音合成系统\n- 易拆卸性：可以很方便地更换不同语种上的不同声学模型和声码器、使用不同的推理引擎（Paddle 动态图、PaddleInference 和 ONNXRuntime 等）、使用不同的网络服务（HTTP、Websocket）\n\n<a name=\"3\"></a>\n## 3. Benchmark\nPaddleSpeech TTS 模型之间的性能对比，请查看 [TTS-Benchmark](https://github.com/PaddlePaddle/PaddleSpeech/wiki/TTS-Benchmark)。\n\n<a name=\"4\"></a>\n## 4. 效果展示 \n请参考：[Streaming TTS Demo Video](https://paddlespeech.readthedocs.io/en/latest/streaming_tts_demo_video.html)\n\n<a name=\"5\"></a>\n## 5. 使用教程\n\n<a name=\"51\"></a>\n### 5.1 模型训练与推理优化\n\nDefault FastSpeech2：[tts3/run.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/tts3/run.sh)\n\n流式 FastSpeech2：[tts3/run_cnndecoder.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/tts3/run_cnndecoder.sh)\n\nHiFiGAN：[voc5/run.sh](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/voc5/run.sh)\n\n<a name=\"52\"></a>\n### 5.2 语音合成特色应用\n一键式实现语音合成：[text_to_speech](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/text_to_speech)\n\n个性化语音合成 - 基于 FastSpeech2 模型的个性化语音合成：[style_fs2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/style_fs2)\n\n会说话的故事书 - 基于 OCR 和语音合成的会说话的故事书：[story_talker](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/story_talker)\n\n元宇宙 - 基于语音合成的 2D 增强现实：[metaverse](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/metaverse)\n\n<a name=\"53\"></a>\n### 5.3 语音合成服务搭建\n\n一键式搭建非流式语音合成服务：[speech_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/speech_server)\n\n一键式搭建流式语音合成服务：[streaming_tts_server](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/streaming_tts_server)\n\n\n更多教程，包括模型设计、模型训练、推理部署等，请参考 AIStudio 教程：[PP-TTS：流式语音合成原理及服务部署\n](https://aistudio.baidu.com/aistudio/projectdetail/3885352)\n"
  },
  {
    "path": "docs/source/tts/README.md",
    "content": "# Parakeet\nParakeet aims to provide a flexible, efficient, and state-of-the-art text-to-speech toolkit for the open-source community. It is built on PaddlePaddle dynamic graph and includes many influential TTS models.  \n\n<div align=\"center\">\n  <img src=\"../../images/logo.png\" width=300 /> <br>\n</div>\n\n## Overview\n\nTo facilitate exploiting the existing TTS models directly and developing the new ones, Parakeet selects typical models and provides their reference implementations in PaddlePaddle. Furthermore, Parakeet abstracts the TTS pipeline and standardizes the procedure of data preprocessing, common modules sharing, model configuration, and the process of training and synthesis. The models supported here include Text FrontEnd, end-to-end Acoustic models, and Vocoders:\n\n- Text FrontEnd\n  - Rule-based Chinese frontend.\n\n- Acoustic Models\n  - [【FastSpeech2】FastSpeech 2: Fast and High-Quality End-to-End Text to Speech](https://arxiv.org/abs/2006.04558)\n  - [【SpeedySpeech】SpeedySpeech: Efficient Neural Speech Synthesis](https://arxiv.org/abs/2008.03802)\n  - [【Transformer TTS】Neural Speech Synthesis with Transformer Network](https://arxiv.org/abs/1809.08895)\n  - [【Tacotron2】Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions](https://arxiv.org/abs/1712.05884)\n- Vocoders\n  - [【Parallel WaveGAN】Parallel WaveGAN: A fast waveform generation model based on generative adversarial networks with multi-resolution spectrogram](https://arxiv.org/abs/1910.11480)\n  - [【WaveFlow】WaveFlow: A Compact Flow-based Model for Raw Audio](https://arxiv.org/abs/1912.01219)\n- Voice Cloning\n  - [Transfer Learning from Speaker Verification to Multispeaker Text-to-Speech Synthesis](https://arxiv.org/pdf/1806.04558v4.pdf)\n  - [【GE2E】Generalized End-to-End Loss for Speaker Verification](https://arxiv.org/abs/1710.10467)\n\n\n\n## Audio samples\n\nCheck our [website](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html) for audio sampels.\n\n## Released Model\n\n### Acoustic Model\n\n#### FastSpeech2/FastPitch\n1. [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/fastspeech2_nosil_baker_ckpt_0.4.zip)\n2. [fastspeech2_nosil_aishell3_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/fastspeech2_nosil_aishell3_ckpt_0.4.zip)\n3. [fastspeech2_nosil_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/fastspeech2_nosil_ljspeech_ckpt_0.5.zip)\n\n#### SpeedySpeech\n1. [speedyspeech_nosil_baker_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/speedyspeech_nosil_baker_ckpt_0.5.zip)\n\n#### TransformerTTS\n\n1. [transformer_tts_ljspeech_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/transformer_tts_ljspeech_ckpt_0.4.zip)\n\n#### Tacotron2\n\n1. [tacotron2_ljspeech_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/tacotron2_ljspeech_ckpt_0.3.zip)\n2. [tacotron2_ljspeech_ckpt_0.3_alternative.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/tacotron2_ljspeech_ckpt_0.3_alternative.zip)\n\n### Vocoder\n\n#### WaveFlow\n\n1. [waveflow_ljspeech_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/waveflow_ljspeech_ckpt_0.3.zip)\n\n#### Parallel WaveGAN\n\n1. [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/pwg_baker_ckpt_0.4.zip)\n2. [pwg_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/pwg_ljspeech_ckpt_0.5.zip)\n\n### Voice Cloning\n\n#### Tacotron2_AISHELL3\n\n1. [tacotron2_aishell3_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/tacotron2_aishell3_ckpt_0.3.zip)\n\n#### GE2E\n\n1. [ge2e_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/ge2e_ckpt_0.3.zip)\n"
  },
  {
    "path": "docs/source/tts/advanced_usage.md",
    "content": "\n# Advanced Usage\nThis section covers how to extend TTS by implementing your models and experiments. Guidelines on implementation are also elaborated.\n\nFor the general deep learning experiment, there are several parts to deal with:\n1. Preprocess the data according to the needs of the model, and iterate the dataset by batch.\n2. Define the model, optimizer, and other components.\n3. Write out the training process (generally including forward / backward calculation, parameter update, log recording, visualization, periodic evaluation, etc.).\n5. Configure and run the experiment.\n\n## PaddleSpeech TTS's Model Components\nTo balance the reusability and function of models, we divide models into several types according to their characteristics.\n\nFor the commonly used modules that can be used as part of other larger models, we try to implement them as simple and universal as possible, because they will be reused. Modules with trainable parameters are generally implemented as subclasses of `paddle.nn.Layer`. Modules without trainable parameters can be directly implemented as a function, and its input and output are `paddle.Tensor`.\n\nModels for a specific task are implemented as subclasses of `paddle.nn.Layer`. Models could be simple, like a single-layer RNN. For complicated models, it is recommended to split the model into different components.\n\nFor a seq-to-seq model, it's natural to split it into encoder and decoder. For a model composed of several similar layers, it's natural to extract the sublayer as a separate layer.\n\nThere are two common ways to define a model which consists of several modules.\n\n1. Define a module given the specifications. Here is an example with a multilayer perceptron.\n    ```python\n    class MLP(nn.Layer):\n        def __init__(self, input_size, hidden_size, output_size):\n            self.linear1 = nn.Linear(input_size, hidden_size)\n            self.linear2 = nn.Linear(hidden_size, output_size)\n\n        def forward(self, x):\n            return self.linear2(paddle.tanh(self.linear1(x))\n\n    module = MLP(16, 32, 4) # intialize a module\n    ```\n    When the module is intended to be a generic and reusable layer that can be integrated into a larger model, we prefer to define it in this way.\n\n    For considerations of readability and usability, we strongly recommend **NOT** to pack specifications into a single object. Here’s an example below.\n    ```python\n    class MLP(nn.Layer):\n        def __init__(self, hparams):\n            self.linear1 = nn.Linear(hparams.input_size, hparams.hidden_size)\n            self.linear2 = nn.Linear(hparams.hidden_size, hparams.output_size)\n\n        def forward(self, x):\n            return self.linear2(paddle.tanh(self.linear1(x))\n    ```\n    For a module defined in this way, it’s harder for the user to initialize an instance. Users have to read the code to check what attributes are used.\n\n    Also, code in this style tends to be abused by passing a huge config object to initialize every module used in an experiment, though each module may not need the whole configuration.\n\n    We prefer to be explicit.\n\n2. Define a module as a combination given its components. Here is an example of a sequence-to-sequence model.\n    ```python\n    class Seq2Seq(nn.Layer):\n        def __init__(self, encoder, decoder):\n            self.encoder = encoder\n            self.decoder = decoder\n\n        def forward(self, x):\n            encoder_output = self.encoder(x)\n            output = self.decoder(encoder_output)\n            return output\n\n    encoder = Encoder(...)\n    decoder = Decoder(...)\n    # compose two components\n    model = Seq2Seq(encoder, decoder)\n    ```\n    When a model is complicated and made up of several components, each of which has a separate functionality, and can be replaced by other components with the same functionality, we prefer to define it in this way.\n\nIn the directory structure of PaddleSpeech TTS, modules with high reusability are placed in `paddlespeech.t2s.modules`, but models for specific tasks are placed in `paddlespeech.t2s.models`. When developing a new model, developers need to consider the feasibility of splitting the modules, and the degree of generality of the modules and place them in appropriate directories.\n\n## PaddleSpeech TTS's Data Components\nAnother critical component for a deep learning project is data.\nPaddleSpeech TTS uses the following methods for training data:\n1. Preprocess the data.\n2. Load the preprocessed data for training.\n\nPreviously, we wrote the preprocessing in the `__getitem__` of the Dataset, which will process when accessing a certain batch sample, but encountered some problems:\n\n1.  Efficiency problem. Even if Paddle has a design to load data asynchronously, when the batch size is large, each sample needs to be preprocessed and set up batches, which takes a lot of time, and may even seriously slow down the training process.\n2. Data filtering problem. Some filtering conditions depend on the features of the processed sample. For example, filtering samples that are too short according to text length. If the text length can only be known after `__getitem__`,  every time you filter, the entire dataset needed to be loaded once!  In addition, if you do not pre-filter, A small exception (such as too short text ) in  `__getitem__` will cause an exception in the entire data flow, which is not feasible, because `collate_fn `  presupposes that the acquisition of each sample can be normal. Even if some special flags, such as `None`, are used to mark data acquisition failures, and skip `collate_fn`, it will change batch_size.\n\nTherefore, it is not realistic to put preprocessing entirely on `__getitem__`. We use the method mentioned above instead.\nDuring preprocessing, we can do filtering, We can also save more intermediate features, such as text length, audio length, etc., which can be used for subsequent filtering. Because of the habit of TTS field, data is stored in multiple files, and the processed results are stored in `npy` format.\n\nUse a list-like way to store metadata and store the file path in it, so that you can not be restricted by the specific storage location of the file. In addition to the file path, other metadata can also be stored in it. For example, the path of the text, the path of the audio, the path of the spectrum, the number of frames, the number of sampling points, and so on.\n\nThen for the path, there are multiple opening methods,  such as `sf.read`, `np.load`, etc., so it's best to use a parameter that can be input, we don't even want to determine the reading method by its extension, it's best to let the users input it, in this way, users can define their method to parse the data.\n\nSo we learned from the design of `DataFrame`, but our construction method is simpler, only need a `list of dicts`, a dict represents a record, and it's convenient to interact with formats such as `json`, `yaml`. For each selected field, we need to give a parser (called `converter` in the interface), and that's it.\n\nThen we need to select a format for saving metadata to the hard disk. There are two square brackets when storing the list of records in `json`, which is not convenient for stream reading and writing, so we use `jsonlines`. We don't use `yaml` because it occupies too many rows when storing the list of records.\n\nMeanwhile, `cache` is added here, and a multi-process Manager is used to share memory between multiple processes. When `num_workers` is used, it is guaranteed that each sub process will not cache a copy.\n\nThe implementation of `DataTable` can be found in `paddlespeech/t2s/datasets/data_table.py`.\n```python\nclass DataTable(Dataset):\n    \"\"\"Dataset to load and convert data for general purpose.\n\n    Parameters\n    ----------\n    data : List[Dict[str, Any]]\n        Metadata, a list of meta datum, each of which is composed of\n        several fields\n    fields : List[str], optional\n        Fields to use, if not specified, all the fields in the data are\n        used, by default None\n    converters : Dict[str, Callable], optional\n        Converters used to process each field, by default None\n    use_cache : bool, optional\n        Whether to use a cache, by default False\n\n    Raises\n    ------\n    ValueError\n        If there is some field that does not exist in data.\n    ValueError\n        If there is some field in converters that does not exist in fields.\n    \"\"\"\n\n    def __init__(self,\n                 data: List[Dict[str, Any]],\n                 fields: List[str]=None,\n                 converters: Dict[str, Callable]=None,\n                 use_cache: bool=False):\n```\nIts `__getitem__` method is to parse each field with their parser and then compose a dictionary to return.\n```python\ndef _convert(self, meta_datum: Dict[str, Any]) -> Dict[str, Any]:\n    \"\"\"Convert a meta datum to an example by applying the corresponding\n    converters to each field requested.\n\n    Parameters\n    ----------\n    meta_datum : Dict[str, Any]\n        Meta datum\n\n    Returns\n    -------\n    Dict[str, Any]\n        Converted example\n    \"\"\"\n    example = {}\n    for field in self.fields:\n        converter = self.converters.get(field, None)\n        meta_datum_field = meta_datum[field]\n        if converter is not None:\n            converted_field = converter(meta_datum_field)\n        else:\n            converted_field = meta_datum_field\n        example[field] = converted_field\n    return example\n```\n\n## PaddleSpeech TTS's Training Components\nA typical training process includes the following processes:\n1. Iterate the dataset.\n2. Process batch data.\n3. Neural network forward/backward calculation.\n4. Parameter update.\n5. Evaluate the model on the validation dataset, when some special conditions are reached.\n6. Write logs, visualize, and in some cases save necessary intermediate results.\n7. Save the state of the model and optimizer.\n\nHere, we mainly introduce the training-related components of TTS in Pa and why we designed it like this.\n### Global Reporter\nWhen training and modifying Deep Learning models，logging is often needed, and it has even become the key to model debugging and modifying. We usually use various visualization tools，such as ,  `visualdl` in `paddle`, `tensorboard` in `tensorflow`  and `vidsom`, `wnb` ,etc. Besides, `logging` and `print` are usually used for a different purpose.\n\nIn these tools, `print` is the simplest，it doesn't have the concept of  `logger` and `handler` in `logging` 、 `summarywriter`  and `logdir` in `tensorboard`, when printing, there is no need for `global_step` ，It's light enough to appear anywhere in the code, and it's printed to a common stdout. Of course, its customizability is limited, for example, it is no longer intuitive when printing dictionaries or more complex objects. And it's fleeting, people need to use redirection to save information.\n\nFor TTS models development，we hope to have a more universal multimedia stdout, which is a tool similar to `tensorboard`, which allows many multimedia forms, but it needs a `summary writer` when using, and a `step` when writing information. If the data are images or voices,  some format control parameters are needed.\n\nThis will destroy the modular design to a certain extent. For example, If my model is composed of multiple sublayers, and I want to record some important information in the forward method of some sublayers. For this reason, I may need to pass the `summary writer` to these sublayers, but for the sublayers, its function is the calculation, it should not have extra considerations, and it's also difficult for us to tolerate that the initialization of an `nn.Linear` has an optional `visualizer` in the method. And, for a calculation module, **HOW** can it know the global step? These are things related to the training process!\n\nTherefore, a more common approach is not to put writing_log_code in the definition of layer, but return it, then obtain them during training, and write them to `summary writer`.  However, the return values need to be modified.  `summary writer ` is a broadcaster at the training level, and then each module transmits information to it by modifying the return values.\n\nWe think this method is a little ugly. We prefer to return the necessary information only rather than change the return values to accommodate visualization and recording.  When you need to report some information, you should be able to report it without difficulty. So we imitate the design of `chainer` and use the `global repoter`.\n\nIt takes advantage of the globality of Python's module-level variables and the effect of context manager.\n\nThere is a module-level variable in  `paddlespeech/t2s/training/reporter.py`  `OBSERVATIONS`，which is a `Dict` to store key-value.\n```python\n# paddlespeech/t2s/training/reporter.py\n\n@contextlib.contextmanager\ndef scope(observations):\n    # make `observation` the target to report to.\n    # it is basically a dictionary that stores temporary observations\n    global OBSERVATIONS\n    old = OBSERVATIONS\n    OBSERVATIONS = observations\n\n    try:\n        yield\n    finally:\n        OBSERVATIONS = old\n```\n\nThen we implement a context manager `scope`, which is used to switch the variables bound by the name of `OBSERVATIONS`. Then a `getter` function is defined to get the dictionary bound by `OBSERVATIONS`.\n```python\ndef get_observations():\n    global OBSERVATIONS\n    return OBSERVATIONS\n```\nThen we define a function to get  the current `OBSERVATIONS`，and write key-value pair into it.\n```python\ndef report(name, value):\n    # a simple function to report named value\n    # you can use it everywhere, it will get the default target and writ to it\n    # you can think of it as std.out\n    observations = get_observations()\n    if observations is None:\n        return\n    else:\n        observations[name] = value\n```\nThe test code following shows the usage method.\n- use `first` as the current `OBSERVATION`, write `first_begin=1`,\n- then, open the second `OBSERVATION`, write `second_begin=2`,\n- then, open the third `OBSERVATION`, write  `third_begin=3`\n- exit the third `OBSERVATION` , we back to the second  `OBSERVATION` automatically\n- write some context in the second `OBSERVATION` , then exit it, and   we back to the first  `OBSERVATION` automatically\n```python\ndef test_reporter_scope():\n    first = {}\n    second = {}\n    third = {}\n\n    with scope(first):\n        report(\"first_begin\", 1)\n        with scope(second):\n            report(\"second_begin\", 2)\n            with scope(third):\n                report(\"third_begin\", 3)\n                report(\"third_end\", 4)\n            report(\"seconf_end\", 5)\n        report(\"first_end\", 6)\n\n    assert first == {'first_begin': 1, 'first_end': 6}\n    assert second == {'second_begin': 2, 'seconf_end': 5}\n    assert third == {'third_begin': 3, 'third_end': 4}\n```\n\nIn this way, when we write modular components, we can directly call `report`.  The caller will decide where to report as long as it's ready for `OBSERVATION`, then it opens a `scope` and calls the component within this `scope`.\n\n The `Trainer` in PaddleSpeech TTS report the information in this way.\n```python\nwhile True:\n    self.observation = {}\n    # set observation as the report target\n    # you can use report freely in Updater.update()\n\n    # updating parameters and state\n    with scope(self.observation):\n        update() # training for a step is defined here\n```\n### Updater: Model Training Process\n\nTo maintain the purity of function and the reusability of code, we abstract the model code into a subclass of  `paddle.nn.Layer`, and write the core computing functions in it.\n\nWe tend to write the forward process of training in `forward()`, but only write to the prediction result, not to the loss. Therefore, this module can be called by a larger module.\n\nHowever, when we compose an experiment, we need to add some other things, such as the training process, evaluation process, checkpoint saving, visualization, and the like. In this process, we will encounter some things that only exist in the training process, such as `optimizer`, `learning rate scheduler`, `visualizer`, etc. These things are not part of the model, they should **NOT** be written in the model code.\n\nWe made an abstraction for these intermediate processes, that is, `Updater`, which takes the `model`, `optimizer`, and `data stream` as input, and its function is training. Since there may be differences in training methods of different models, we tend to write a corresponding `Updater` for each model. But this is different from the final training script, there is still a certain degree of encapsulation, just to extract the details of regular saving, visualization, evaluation, etc., and only retain the most basic function, that is,  training the model.\n\n### Visualizer\nBecause we choose observation as the communication mode, we can simply write the things in observation into `visualizer`.\n\n## PaddleSpeech TTS's Configuration Components\nDeep learning experiments often have many options to configure. These configurations can be roughly divided into several categories.\n1. Data source and data processing mode configuration.\n2. Save path configuration of experimental results.\n3. Data preprocessing mode configuration.\n4. Model structure and hyperparameter configuration.\n5. Training process configuration.\n\nIt’s common to change the running configuration to compare results. To keep track of running configuration, we use `yaml` configuration files.\n\nAlso, we want to interact with command-line options. Some options that usually change according to running environments are provided by command line arguments. In addition, we want to override an option in the config file without editing it.\n\nTaking these requirements into consideration, we use [yacs](https://github.com/rbgirshick/yacs) as a config management tool. Other tools like [omegaconf](https://github.com/omry/omegaconf) are also powerful and have similar functions.\n\nIn each example provided, there is a `config.py`,  the default config is defined at `conf/default.yaml`. If you want to get the default config, import `config.py` and call `get_cfg_defaults()` to get it. Then it can be updated with `yaml` config file or command-line arguments if needed.\n\nFor details about how to use yacs in experiments, see [yacs](https://github.com/rbgirshick/yacs).\n\nThe following is the basic  `ArgumentParser`:\n1. `--config`  is used to support configuration file parsing, and the configuration file itself handles the unique options of each experiment.\n2. `--train-metadata` is the path to the training data.\n3.  `--output-dir` is the dir to save the training results.（if there are checkpoints in  `checkpoints/` of  `--output-dir` , it defaults to reload the newest checkpoint to train)\n4. `--ngpu` determine operation modes，`--ngpu` refers to the number of training processes. If `ngpu` > 0, it means using GPU, else CPU is used.\n\nDevelopers can refer to the examples in `examples` to write the default configuration file when adding new experiments.\n\n## PaddleSpeech TTS's Experiment template\n\nThe experimental codes in PaddleSpeech TTS are generally organized as follows:\n\n```text\n.\n├──  README.md               (help information)\n├──  conf\n│     └── default.yaml       (default config)\n├──  local\n│    ├──  preprocess.sh      (script to call data preprocessing.py)\n│    ├──  synthesize.sh      (script to call synthesis.py)  \n│    ├──  synthesize_e2e.sh  (script to call synthesis_e2e.py)\n│    └──train.sh             (script to call train.py)\n├── path.sh                  (script include paths to be sourced)\n└── run.sh                   (script to call scripts in local)\n```\nThe `*.py` files called by above `*.sh` are located `${BIN_DIR}/`\n\nWe add a named argument. `--output-dir` to each training script to specify the output directory. The directory structure is as follows, developers should follow this specification:\n```text\nexp/default/\n├── checkpoints/\n│   ├── records.jsonl        (record file)\n│   └── snapshot_iter_*.pdz  (checkpoint files)\n├── config.yaml              (config file of this experiment)\n├── vdlrecords.*.log         (visualdl record file)\n├── worker_*.log             (text logging, one file per process)\n├── validation/              (output dir during training, information_iter_*/ is the output of each step, if necessary)\n├── inference/               (output dir of exported static graph model, which is only used in the final stage of training, if implemented)\n└── test/                    (output dir of synthesis results)\n```\n\nYou can view the examples we provide in `examples`. These experiments are provided to users as examples that can be run directly. Users are welcome to add new models and experiments and contribute code to PaddleSpeech.\n"
  },
  {
    "path": "docs/source/tts/demo.rst",
    "content": "Audio Sample \n==================\n\nThe main processes of TTS include:\n\n1. Convert the original text into characters/phonemes, through ``text frontend`` module.\n\n2. Convert characters/phonemes into acoustic features , such as linear spectrogram, mel spectrogram, LPC features, etc. through ``Acoustic models``.\n\n3. Convert acoustic features into waveforms through ``Vocoders``.\n\nWhen training ``Tacotron2``、``TransformerTTS`` and ``WaveFlow``, we use English single speaker TTS dataset `LJSpeech <https://keithito.com/LJ-Speech-Dataset/>`_  by default. However, when training ``SpeedySpeech``, ``FastSpeech2`` and ``ParallelWaveGAN``, we use Chinese single speaker dataset `CSMSC <https://test.data-baker.com/data/index/source/>`_ by default. \n\nIn the future, ``PaddleSpeech TTS`` will mainly use Chinese TTS datasets for default examples.\n\nHere, we will display three types of audio samples:\n\n1. Analysis/synthesis (ground-truth spectrograms + Vocoder)\n\n2. TTS (Acoustic model + Vocoder)\n\n3. Chinese TTS with/without text frontend (mainly tone sandhi)\n\nAnalysis/synthesis\n--------------------------\n\nAudio samples generated from ground-truth spectrograms with a vocoder.\n\n.. raw:: html\n     \n    <b>LJSpeech(English)</b>\n    <br>\n    </br>\n    \n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\"> \n        <tr>\n            <th align=\"center\"> Text </th>\n            <th align=\"center\"> GT </th>\n            <th align=\"center\"> WaveFlow </th>\n        </tr>\n        <tr>\n            <td >Printing, in the only sense with which we are at present concerned, differs from most if not from all the arts and crafts represented in the Exhibition</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/ljspeech_gt/LJ001-0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                \n            \n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/waveflow_res128_ljspeech_samples_1.0/step_2000k_sentence_0.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>in being comparatively modern.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/ljspeech_gt/LJ001-0002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n\n            </td>\n            <td>\n             <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/waveflow_res128_ljspeech_samples_1.0/step_2000k_sentence_1.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n            </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>For although the Chinese took impressions from wood blocks engraved in relief for centuries before the woodcutters of the Netherlands, by a similar process</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/ljspeech_gt/LJ001-0003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/waveflow_res128_ljspeech_samples_1.0/step_2000k_sentence_2.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>produced the block books, which were the immediate predecessors of the true printed book</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/ljspeech_gt/LJ001-0004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/waveflow_res128_ljspeech_samples_1.0/step_2000k_sentence_3.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>the invention of movable metal letters in the middle of the fifteenth century may justly be considered as the invention of the art of printing.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/ljspeech_gt/LJ001-0005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/waveflow_res128_ljspeech_samples_1.0/step_2000k_sentence_4.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n    </table>\n    \n    <br>\n    </br>\n\n    <b>CSMSC(Chinese)</b>\n    <br>\n    </br>\n\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Text </th>\n            <th align=\"center\"> GT (convert to 24k) </th>\n            <th align=\"center\"> ParallelWaveGAN </th>\n        </tr>\n        <tr>\n            <td>昨日，这名“伤者”与医生全部被警方依法刑事拘留</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/baker_gt_24k/009901.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/pwg_baker_ckpt_0.4/009901.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>钱伟长想到上海来办学校是经过深思熟虑的。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/baker_gt_24k/009902.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/pwg_baker_ckpt_0.4/009902.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>她见我一进门就骂，吃饭时也骂，骂得我抬不起头。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/baker_gt_24k/009903.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/pwg_baker_ckpt_0.4/009903.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>李述德在离开之前，只说了一句“柱驼杀父亲了”</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/baker_gt_24k/009904.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/pwg_baker_ckpt_0.4/009904.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n        </tr>\n        <tr>\n            <td>这种车票和保险单捆绑出售属于重复性购买。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/baker_gt_24k/009905.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/pwg_baker_ckpt_0.4/009905.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>  \n        </tr>    \n    </table>\n    </div>\n    <br>\n    <br>\n\nTTS\n-------------------\n\nAudio samples generated by a TTS system. Text is first transformed into spectrogram by a text-to-spectrogram model, then the spectrogram is converted into raw audio by a vocoder.\n\n.. raw:: html\n\n    <b>LJSpeech(English)</b>\n    <br>\n    </br>\n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\"> \n        <tr>\n            <th align=\"center\"> Text </th>\n            <th align=\"center\"> TransformerTTS + WaveFlow </th>\n            <th align=\"center\"> Tacotron2 + WaveFlow </th>\n        </tr>\n        <tr>\n            <td>Life was like a box of chocolates, you never know what you're gonna get.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                        <source\n                            src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/001.wav\"\n                            type=\"audio/wav\">\n                        Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td> \n                <audio controls=\"controls\" style=\"width: 220px;\">\n                        <source\n                            src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_1.wav\"\n                            type=\"audio/wav\">\n                        Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>With great power there must come great responsibility.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                        <source\n                            src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/002.wav\"\n                            type=\"audio/wav\">\n                        Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td> \n            <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_2.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>To be or not to be, that’s a question.</td>\n            <td>\n            <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n            <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_3.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n        <tr>\n            <td>A man can be destroyed but not defeated.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_4.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Do not, for one repulse, give up the purpose that you resolved to effort.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n            <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_5.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Death is just a part of life, something we're all destined to do.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_6.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>I think it's hard winning a war with words. </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n            <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_7.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Don’t argue with the people of strong determination, because they may change the fact!</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_8.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Love you three thousand times.</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/transformer_tts_ljspeech_ckpt_0.4_waveflow_ljspeech_ckpt_0.3/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n\n            <td> \n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/tacotron2_ljspeech_waveflow_samples_0.2/sentence_9.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>   \n    </table>\n    \n    <br>\n    </br>\n\n    <b>CSMSC(Chinese)</b>\n    <br>\n    </br>\n\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\"> \n        <tr>\n            <th align=\"center\"> Text </th>\n            <th align=\"center\"> SpeedySpeech + ParallelWaveGAN </th>\n            <th align=\"center\"> FastSpeech2 + ParallelWaveGAN </th>\n        </tr>\n        <tr>\n            <td>凯莫瑞安联合体的经济崩溃，迫在眉睫。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>对于所有想要离开那片废土，去寻找更美好生活的人来说。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>克哈，是你们所有人安全的港湾。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n        <tr>\n            <td>为了保护尤摩扬人民不受异虫的残害，我所做的，比他们自己的领导委员会都多。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>无论他们如何诽谤我，我将继续为所有泰伦人的最大利益，而努力奋斗。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>身为你们的元首，我带领泰伦人实现了人类统治领地和经济的扩张。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我们将继续成长，用行动回击那些只会说风凉话，不愿意和我们相向而行的害群之马。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>帝国武装力量，无数的优秀儿女，正时刻守卫着我们的家园大门，但是他们孤木难支。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>凡是今天应征入伍者，所获的所有刑罚罪责，减半。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speedyspeech_baker_ckpt_0.4_pwg_baker_ckpt_0.4/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_nosil_baker_ckpt_0.4_parallel_wavegan_baker_ckpt_0.4/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>   \n    </table>\n\n    <br>\n    </br>\n\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\"> \n        <tr>\n            <th align=\"center\"> FastSpeech2-Conformer + </br>ParallelWaveGAN </th>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fastspeech2_conformer_baker_ckpt_0.5_pwg_baker_ckpt_0.4/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>   \n    </table>\n    </div>\n    <br>\n    <br>\n\n\nMulti-Speaker TTS\n-------------------\n\nPaddleSpeech also support Multi-Speaker TTS, we provide the audio demos generated by FastSpeech2 + ParallelWaveGAN, we use AISHELL-3 Multi-Speaker TTS dataset. Each line is a different person.\n\n\n.. raw:: html\n\n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Target Timbre </th>\n            <th align=\"center\"> Generated </th>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/0.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/0_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/1.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/1_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/2.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/2_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/3.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/3_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/4.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/4_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/5.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/5_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/6.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/6_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/7.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/7_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/8.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/8_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/9.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/9_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/10.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/10_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/11.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/11_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/12.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/12_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/13.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/13_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/14.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/14_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/15.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/15_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/16.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/16_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/17.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/17_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/18.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/18_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/target/19.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/fs2_aishell3_demos/generated/19_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n    <table>\n    <div>\n    <br>\n    <br>\n        \n\nStyle control in FastSpeech2\n--------------------------------------\nIn our FastSpeech2, we can control ``duration``, ``pitch`` and ``energy``.\n\nWe provide the audio demos of duration control here. ``duration`` means the duration of phonemes, when we reduce duration, the speed of audios will increase, and when we incerase ``duration``, the speed of audios will reduce.\n\nThe ``duration`` of different phonemes in a sentence can have different scale ratios (when you want to slow down one word and keep the other words' speed in a sentence). Here we use a fixed scale ratio for different phonemes to control the ``speed`` of audios.\n\nThe duration control in FastSpeech2 can control the speed of audios will keep the pitch. (in some speech tool, increase the speed will increase the pitch, and vice versa.)\n\n.. raw:: html\n\n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Speed(0.8x) </th>\n            <th align=\"center\"> Speed(1x) </th>\n            <th align=\"center\"> Speed(1.2x) </th>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n             <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 250px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n    <table>\n    <div>\n    <br>\n    <br>\n\nWe provide the audio demos of pitch control here. \n\nWhen we set pitch of one sentence to a mean value and set ``tones`` of phones to ``1``, we will get a ``robot-style`` timbre.\n\nWhen we raise the pitch of an adult female (with a fixed scale ratio), we will get a ``child-style`` timbre.\n\nThe ``pitch`` of different phonemes in a sentence can also have different scale ratios.\n\nThe nomal audios are in the second column of the previous table.\n\n.. raw:: html\n\n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Robot </th>\n            <th align=\"center\"> Child </th>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice//004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice//005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice//007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice//008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice//009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n    <table>\n    <div>\n    <br>\n    <br>\n\n\nChinese TTS with/without text frontend\n--------------------------------------\n\nWe provide a complete Chinese text frontend module in ``PaddleSpeech TTS``. ``Text Normalization`` and ``G2P`` are the most important modules in text frontend, We assume that the texts are normalized already, and mainly compare ``G2P`` module here.\n\nWe use ``FastSpeech2`` + ``ParallelWaveGAN`` here.\n\n.. raw:: html\n\n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Text</th>\n            <th align=\"center\"> With Text Frontend </th>\n            <th align=\"center\"> Without Text Frontend </th>\n        </tr>\n        <tr>\n            <td>他只是一个纸老虎。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>手表厂有五种好产品。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>老板的轿车需要保养。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我们所有人都好喜欢你呀。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>岂有此理。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>虎骨酒多少钱一瓶。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>这件事情需要冷处理。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>这个老奶奶是个大喇叭。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我喜欢说相声。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>有一天，我路过了一栋楼。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/with_frontend/010.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/without_frontend/010.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n\n    <table>\n    </div>\n    <br>\n    <br> \n\n\nFinetune FastSpeech2 for CSMSC\n--------------------------------------\n\nFinetuning demos of `tts_finetune/tts3 <https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/tts_finetune/tts3>`_  for CSMSC dataset.\n\nWhen finetuning for CSMSC, we thought ``Freeze encoder`` > ``Non Frozen`` > ``Freeze encoder && duration_predictor`` for audio quality.\n\n.. raw:: html\n\n    <div class=\"table\">\n    CSMSC reference audio (fastspeech2_csmsc + hifigan_aishlle3 in CLI): 欢迎使用飞桨语音套件。\n    <br>\n    <br>\n    <audio controls=\"controls\" style=\"width: 220px;\">\n        <source\n            src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/ref_fastspeech2_csmsc_hifigan_aishell3.wav\"\n            type=\"audio/wav\">\n        Your browser does not support the <code>audio</code> element.\n    </audio>\n    <br>\n    <br>\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\">\n        <tr>\n            <th align=\"center\"> Frozen Method</th>\n            <th align=\"center\"> train_num=10, </br> bs=10, </br> epoch=100, </br> lr=1e-4 </th>\n            <th align=\"center\"> train_num=18, </br> bs=18, </br> epoch=100, </br> lr=1e-4 </th>\n            <th align=\"center\"> train_num=97, </br> bs=64, </br> epoch=100, </br> lr=1e-4 </th>\n            <th align=\"center\"> train_num=196, </br> bs=64, </br> epoch=100, </br> lr=1e-4 </th>\n        </tr>\n        <tr>\n            <td>Non Frozen</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train10_bn10_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train18_bn18_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train97_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train196_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Freeze encoder</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train10_fr_encoder_bn10_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train18_fr_encoder_bn18_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train97_fr_encoder_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train196_fr_encoder_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>Freeze encoder && </br> duration_predictor</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train10_fr_encoder_duration_bn10_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train18_fr_encoder_duration_bn18_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train97_fr_encoder_duration_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 150px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/finetune/train196_fr_encoder_duration_bn64_epoch100_lr0.0001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n    <table>\n    </div>\n    <br>\n    <br> \n"
  },
  {
    "path": "docs/source/tts/demo_2.rst",
    "content": "Audio Sample (PaddleSpeech TTS VS Espnet TTS)\n==================\n\nThis is an audio demo page to contrast PaddleSpeech TTS and Espnet TTS, We use their respective modules (Text Frontend, Acoustic model and Vocoder) here.\nWe use Espnet's released models here.\n\nFastSpeech2 + Parallel WaveGAN in CSMSC\n\n.. raw:: html\n     \n    \n    <div class=\"table\">\n    <table border=\"2\" cellspacing=\"1\" cellpadding=\"1\"> \n        <tr>\n            <th align=\"center\"> Text </th>\n            <th align=\"center\"> Espent TTS </th>\n            <th align=\"center\"> PaddleSpeech TTS </th>\n        </tr>\n        <tr>\n            <td>早上好，今天是2020/10/29，最低温度是-3°C。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/001.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>你好，我的编号是37249，很高兴为您服务。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/002.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我们公司有37249个人。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/003.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我出生于2005年10月8日。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/004.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我们习惯在12:30吃中午饭。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/005.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>只要有超过3/4的人投票同意，你就会成为我们的新班长。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/006.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我要买一只价值999.9元的手表。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/007.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>我的手机号是18544139121，欢迎来电。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/008.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>明天有62%的概率降雨。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/009.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>手表厂有五种好产品。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/010.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/010.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>跑马场有五百匹很勇敢的千里马。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/011.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/011.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>有一天，我看到了一栋楼，我顿感不妙，因为我看不清里面有没有人。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/012.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/012.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>史小姐拿着小雨伞去找她的老保姆了。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/013.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/013.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        <tr>\n            <td>不要相信这个老奶奶说的话，她一点儿也不好。</td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/espent/014.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n            <td>\n                <audio controls=\"controls\" style=\"width: 220px;\">\n                    <source\n                        src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/parakeet_espnet_fs2_pwg_demo/tn_g2p/parakeet/014.wav\"\n                        type=\"audio/wav\">\n                    Your browser does not support the <code>audio</code> element.\n                </audio>\n            </td>\n        </tr>\n        </table>\n        </div>\n\n"
  },
  {
    "path": "docs/source/tts/gan_vocoder.md",
    "content": "# GAN Vocoders\nThis is a brief introduction of GAN Vocoders, we mainly introduce the losses of different vocoders here.\n\nModel  | Generator Loss |Discriminator Loss\n:-------------:| :------------:| :-----\nMel GAN | adversial loss <br> Feature Matching  | Multi-Scale Discriminator |\nParallel Wave GAN |adversial loss <br> Multi-resolution STFT loss  | adversial loss|\nMulti-Band Mel GAN | adversial loss <br> full band Multi-resolution STFT loss <br> sub band Multi-resolution STFT loss |Multi-Scale Discriminator|\nHiFi GAN |adversial loss <br> Feature Matching <br>  Mel-Spectrogram Loss | Multi-Scale Discriminator <br> Multi-Period Discriminator|\n"
  },
  {
    "path": "docs/source/tts/models_introduction.md",
    "content": "# Models introduction\nTTS system mainly includes three modules: `Text Frontend`, `Acoustic model` and `Vocoder`. We introduce a rule-based Chinese text frontend in [zh_text_frontend](./zh_text_frontend.md). Here, we will introduce acoustic models and vocoders, which are trainable.\n\nThe main processes of TTS include:\n1. Convert the original text into characters/phonemes, through the `text frontend` module.\n2. Convert characters/phonemes into acoustic features, such as linear spectrogram, mel spectrogram, LPC features, etc. through `Acoustic models`.\n3. Convert acoustic features into waveforms through `Vocoders`.\n\nA simple text frontend module can be implemented by rules. Acoustic models and vocoders need to be trained. The models provided by PaddleSpeech TTS are acoustic models and vocoders.\n\n## Acoustic Models\n### Modeling Objectives of Acoustic Models\nModeling the mapping relationship between text sequences and speech features：\n```text\ntext X = {x1,...,xM}\nspecch Y = {y1,...yN}\n```\nModeling Objectives:\n```text\nΩ = argmax p(Y|X,Ω)\n```\n### Modeling process of Acoustic Models\nAt present, there are two mainstream acoustic model structures.\n\n- Frame level acoustic model:\n   - Duration model (M Tokens - > N Frames).\n   - Acoustic decoder (N Frames - > N Frames).\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/frame_level_am.png\" width=500 /> <br>\n</div>\n\n- Sequence to sequence acoustic model:\n    - M Tokens - > N Frames.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/seq2seq_am.png\" width=500 /> <br>\n</div>\n\n### Tacotron2\n [Tacotron](https://arxiv.org/abs/1703.10135)  is the first end-to-end acoustic model based on deep learning, and it is also the most widely used acoustic model.\n\n[Tacotron2](https://arxiv.org/abs/1712.05884) is the Improvement of Tacotron.\n#### Tacotron\n**Features of Tacotron:**\n- Encoder.\n   - CBHG.\n   - Input: character sequence.\n- Decoder.\n    - Global soft attention.\n    - unidirectional RNN.\n    - Autoregressive teacher force training (input real speech feature).\n    - Multi frame prediction.\n    - CBHG postprocess.\n    - Vocoder: Griffin-Lim.\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/tacotron.png\" width=700 /> <br>\n</div>\n\n**Advantage of Tacotron:**\n- No need for complex text frontend analysis modules.\n- No need for an additional duration model.\n- Greatly simplifies the acoustic model construction process and reduces the dependence of speech synthesis tasks on domain knowledge.\n\n**Disadvantages of Tacotron:**\n- The CBHG  is complex and the amount of parameters is relatively large.\n- Global soft attention.\n- Poor stability for speech synthesis tasks.\n- In training, the less the number of speech frames predicted at each moment, the more difficult it is to train.\n-  Phase problem in Griffin-Lim causes speech distortion during wave reconstruction.\n- The autoregressive decoder cannot be stopped during the generation process.\n\n#### Tacotron2\n**Features of Tacotron2:**\n- Reduction of parameters.\n   - CBHG -> PostNet (3 Conv layers + BLSTM or 5 Conv layers).\n   - remove Attention RNN.\n- Speech distortion caused by Griffin-Lim.\n    - WaveNet.\n- Improvements of PostNet.\n   - CBHG -> 5 Conv layers.\n   -  The input and output of the PostNet calculate `L2` loss with real Mel spectrogram.\n   - Residual connection.\n- Bad stop in an autoregressive decoder.\n   - Predict whether it should stop at each moment of decoding (stop token).\n   - Set a threshold to determine whether to stop generating when decoding.\n- Stability of attention.\n   - Location-aware attention.\n   - The alignment matrix of the previous time is considered at step `t` of the decoder.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/tacotron2.png\" width=500 /> <br>\n</div>\n\nYou can find PaddleSpeech TTS's tacotron2 with LJSpeech dataset example at [examples/ljspeech/tts0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/tts0).\n\n### TransformerTTS\n**Disadvantages of the Tacotrons:**\n- Encoder and decoder are relatively weak at global information modeling\n   - Vanishing gradient of RNN.\n   - Fixed-length context modeling problem in CNN kernel.\n- Training is relatively inefficient.\n- The attention is not robust enough and the stability is poor.\n\nTransformer TTS is a combination of Tacotron2 and Transformer.\n\n#### Transformer\n [Transformer](https://arxiv.org/abs/1706.03762) is a seq2seq model based entirely on an attention mechanism.\n\n**Features of Transformer:**\n- Encoder.\n    - `N` blocks based on self-attention mechanism.\n    - Positional Encoding.\n- Decoder.\n    - `N` blocks based on self-attention mechanism.\n    - Add Mask to the self-attention in blocks to cover up the information after the `t` step.\n    - Attentions between encoder and decoder.\n    - Positional Encoding.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/transformer.png\" width=500 /> <br>\n</div>\n\n#### Transformer TTS\nTransformer TTS is a seq2seq acoustic model based on Transformer and Tacotron2.\n\n**Motivations：**\n- RNNs in Tacotron2  make the inefficiency of training.\n- Vanishing gradient of RNN makes the model's ability to model long-term contexts weak.\n- Self-attention doesn't contain any recursive structure which can be trained in parallel.\n- Self-attention can model global context information well.\n\n**Features of Transformer TTS:**\n- Add conv based PreNet in encoder and decoder.\n- Stop Token in decoder controls when to stop autoregressive generation.\n- Add PostNet after decoder to improve the quality of synthetic speech.\n- Scaled position encoding.\n    - Uniform scale position encoding may have a negative impact on input or output sequences.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/transformer_tts.png\" width=500 /> <br>\n</div>\n\n**Disadvantages of Transformer TTS:**\n- The ability of position encoding for timing information is still relatively weak.\n- The ability to perceive local information is weak, and local information is more related to pronunciation.\n- Stability is worse than Tacotron2.\n\nYou can find PaddleSpeech TTS's Transformer TTS with LJSpeech dataset example at [examples/ljspeech/tts1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/tts1).\n\n\n### FastSpeech2\n**Disadvantage of seq2seq models:**\n- In the seq2seq model based on attention, no matter how to improve the attention mechanism, it's difficult to avoid generation errors in the decoding stage.\n\nFrame-level acoustic models use duration models to determine the pronunciation duration of phonemes, and the frame-level mapping does not have the uncertainty of sequence generation.\n\nIn seq2saq models, the concept of duration models is used as the alignment module of two sequences to replace attention, which can avoid the uncertainty in attention, and significantly improve the stability of the seq2saq models.\n\n#### FastSpeech\nInstead of using the encoder-attention-decoder based architecture as adopted by most seq2seq based autoregressive and non-autoregressive generation, [FastSpeech](https://arxiv.org/abs/1905.09263) is a novel feed-forward structure, which can generate a target mel spectrogram sequence in parallel.\n\n**Features of FastSpeech:**\n- Encoder: based on Transformer.\n- Change `FFN` to `CNN` in self-attention.\n    -  Model local dependency.\n- Length regulator.\n    - Use real phoneme durations to expand the output frame of the encoder during training.\n- Non-autoregressive decode.\n    -  Improve generation efficiency.\n\n**Length predictor:**\n- Pretrain a TransformerTTS model.\n- Get alignment matrix of train data.\n- Calculate the phoneme durations according to the probability of the alignment matrix.\n- Use the output of the encoder to predict the phoneme durations and calculate the MSE loss.\n- Use real phoneme durations to expand the output frame of the encoder during training.\n- Use phoneme durations predicted by the duration model to expand the frame during prediction.\n    - Attentrion can not control phoneme durations. The explicit duration modeling can control durations through duration coefficient (duration coefficient is `1` during training).\n\n**Advantages of non-autoregressive decoder:**\n- The built-in duration model of the seq2seq model has converted the input length `M` to the output length `N`.\n- The length of the output is known, `stop token` is no longer used, avoiding the problem of being unable to stop.\n• Can be generated in parallel (decoding time is less affected by sequence length)\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/fastspeech.png\" width=800 /> <br>\n</div>\n\n#### FastPitch\n[FastPitch](https://arxiv.org/abs/2006.06873) follows FastSpeech. A single pitch value is predicted for every temporal location, which improves the overall quality of synthesized speech.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/fastpitch.png\" width=500 /> <br>\n</div>\n\n#### FastSpeech2\n**Disadvantages of FastSpeech:**\n- The teacher-student distillation pipeline is complicated and time-consuming.\n- The duration extracted from the teacher model is not accurate enough.\n- The target mel spectrograms distilled from the teacher model suffer from information loss due to data simplification.\n\n[FastSpeech2](https://arxiv.org/abs/2006.04558)  addresses the issues in FastSpeech and better solves the one-to-many mapping problem in TTS.\n\n**Features of FastSpeech2:**\n- Directly train the model with the ground-truth target instead of the simplified output from the teacher.\n- Introducing more variation information of speech as conditional inputs, extract `duration`, `pitch`, and `energy` from speech waveform and directly take them as conditional inputs in training and use predicted values in inference.\n\nFastSpeech2 is similar to FastPitch but introduces more variation information of the speech.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/fastspeech2.png\" width=800 /> <br>\n</div>\n\nYou can find PaddleSpeech TTS's FastSpeech2/FastPitch with CSMSC dataset example at [examples/csmsc/tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3), We use token-averaged pitch and energy values introduced in FastPitch rather than frame-level ones in FastSpeech2.\n\n### SpeedySpeech\n[SpeedySpeech](https://arxiv.org/abs/2008.03802) simplify the teacher-student architecture of FastSpeech and provide a fast and stable training procedure.\n\n**Features of SpeedySpeech:**\n- Use a simpler, smaller, and faster-to-train convolutional teacher model ([Deepvoice3](https://arxiv.org/abs/1710.07654) and [DCTTS](https://arxiv.org/abs/1710.08969)) with a single attention layer instead of Transformer used in FastSpeech.  \n- Show that self-attention layers in the student network are not needed for high-quality speech synthesis.\n- Describe a simple data augmentation technique that can be used early in the training to make the teacher network robust to sequential error propagation.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/speedyspeech.png\" width=500 /> <br>\n</div>\n\nYou can find PaddleSpeech TTS's SpeedySpeech with CSMSC dataset example at [examples/csmsc/tts2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts2).\n\n## Vocoders\nIn speech synthesis, the main task of the vocoder is to convert the spectral parameters predicted by the acoustic model into the final speech waveform.\n\nTaking into account the short-term change frequency of the waveform, the acoustic model usually avoids direct modeling of the speech waveform, but firstly models the spectral features extracted from the speech waveform, and then reconstructs the waveform by the decoding part of the vocoder.\n\nA vocoder usually consists of a pair of encoders and decoders for speech analysis and synthesis. The encoder estimates the parameters, and then the decoder restores the speech.\n\nVocoders based on neural networks usually is speech synthesis, which learns the mapping relationship from spectral features to waveforms through training data.\n\n### Categories of neural vocodes\n- Autoregression\n    - WaveNet\n    - WaveRNN\n    - LPCNet\n\n- Flow\n    - **WaveFlow**\n    - WaveGlow\n    - FloWaveNet\n    - Parallel WaveNet\n- GAN\n    - WaveGAN\n    - **Parallel WaveGAN**\n    - **MelGAN**\n    - **Style MelGAN**\n    - **Multi Band MelGAN**\n    - **HiFi GAN**\n- VAE\n    - Wave-VAE\n- Diffusion\n    - WaveGrad\n    - DiffWave\n\n**Motivations of GAN-based vocoders:**\n- Modeling speech signals by estimating probability distribution usually has high requirements for the expression ability of the model itself. In addition, specific assumptions need to be made about the distribution of waveforms.\n- Although autoregressive neural vocoders can obtain high-quality synthetic speech, such models usually have a **slow generation speed**.\n- The training of inverse autoregressive flow vocoders is complex, and they also require the modeling capability of long-term context information.\n- Vocoders based on Bipartite Transformation converge slowly and are complex.\n- GAN-based vocoders don't need to make assumptions about the speech distribution and train through adversarial learning.\n\nHere, we introduce a Flow-based vocoder WaveFlow and a GAN-based vocoder Parallel WaveGAN.\n\n### WaveFlow\n [WaveFlow](https://arxiv.org/abs/1912.01219) is proposed by Baidu Research.\n\n**Features of WaveFlow:**\n- It can synthesize 22.05 kHz high-fidelity speech around 40x faster than real-time on an Nvidia V100 GPU without engineered inference kernels, which is faster than [WaveGlow](https://github.com/NVIDIA/waveglow) and several orders of magnitude faster than WaveNet.\n- It is a small-footprint flow-based model for raw audio. It has only 5.9M parameters, which is 15x smaller than WaveGlow (87.9M).\n- It is directly trained with maximum likelihood without probability density distillation and auxiliary losses as used in [Parallel WaveNet](https://arxiv.org/abs/1711.10433) and [ClariNet](https://openreview.net/pdf?id=HklY120cYm), which simplifies the training pipeline and reduces the cost of development.\n\nYou can find PaddleSpeech TTS's WaveFlow with LJSpeech dataset example at [examples/ljspeech/voc0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc0).\n\n### Parallel WaveGAN\n[Parallel WaveGAN](https://arxiv.org/abs/1910.11480) trains a non-autoregressive WaveNet variant as a generator in a GAN-based training method.\n\n**Features of Parallel WaveGAN:**\n\n- Use non-causal convolution instead of causal convolution.\n- The input is random Gaussian white noise.\n- The model is non-autoregressive both in training and prediction, which is fast\n- Multi-resolution STFT loss.\n\n<div align=\"left\">\n  <img src=\"https://raw.githubusercontent.com/PaddlePaddle/PaddleSpeech/develop/docs/images/pwg.png\" width=600 /> <br>\n</div>\n\nYou can find PaddleSpeech TTS's Parallel WaveGAN with CSMSC example at [examples/csmsc/voc1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1).\n"
  },
  {
    "path": "docs/source/tts/quick_start.md",
    "content": "([简体中文](./quick_start_cn.md)|English)\n# Quick Start of Text-to-Speech\nThe examples in PaddleSpeech are mainly classified by datasets, the TTS datasets we mainly used are:\n* CSMCS (Mandarin single speaker)\n* AISHELL3 (Mandarin multiple speakers)\n* LJSpeech (English single speaker)\n* VCTK (English multiple speakers)\n\nThe models in PaddleSpeech TTS have the following mapping relationship:\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n* voc4 - Style MelGAN\n* voc5 - HiFiGAN\n* vc0 - Tacotron2 Voice Clone with GE2E\n* vc1 - FastSpeech2 Voice Clone with GE2E\n\n## Quick Start\n\nLet's take a FastSpeech2 + Parallel WaveGAN with CSMSC dataset for instance. [examples/csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc)\n\n### Train Parallel WaveGAN with CSMSC\n- Go to the directory\n    ```bash\n    cd examples/csmsc/voc1\n    ```\n- Source env\n    ```bash\n    source path.sh\n    ```\n    **Must do this before you start to do anything.**\n    Set `MAIN_ROOT` as project dir. Using `parallelwave_gan` model as `MODEL`.\n\n- Main entrypoint\n    ```bash\n    bash run.sh\n    ```\n    This is just a demo, please make sure source data have been prepared well and every `step` works well before the next `step`.\n### Train FastSpeech2 with CSMSC\n- Go to the directory\n    ```bash\n    cd examples/csmsc/tts3\n    ```\n- Source env\n    ```bash\n    source path.sh\n    ```\n    **Must do this before you start to do anything.**\n    Set `MAIN_ROOT` as project dir. Using `fastspeech2` model as `MODEL`.\n- Main entry point\n    ```bash\n    bash run.sh\n    ```\n    This is just a demo, please make sure source data have been prepared well and every `step` works well before the next `step`.\n\nThe steps in `run.sh` mainly include:\n- source path.\n- preprocess the dataset,\n- train the model.\n- synthesize waveform from metadata.jsonl.\n- synthesize waveform from a text file. (in acoustic models)\n- inference using a static model. (optional)\n\nFor more details, you can see `README.md` in examples.\n\n## Pipeline of TTS\nThis section shows how to use pretrained models provided by TTS and make an inference with them.\n\nPretrained models in TTS are provided in an archive. Extract it to get a folder like this:\n**Acoustic Models:**\n```text\ncheckpoint_name\n├── default.yaml\n├── snapshot_iter_*.pdz\n├── speech_stats.npy\n├── phone_id_map.txt\n├── spk_id_map.txt (optional)\n└── tone_id_map.txt (optional)\n```\n**Vocoders:**\n```text\ncheckpoint_name\n├── default.yaml  \n├── snapshot_iter_*.pdz\n└── stats.npy  \n```\n- `default.yaml` stores the config used to train the model.\n- `snapshot_iter_*.pdz` is the checkpoint file, where `*` is the steps it has been trained.\n- `*_stats.npy` is the stats file of the feature if it has been normalized before training.\n- `phone_id_map.txt` is the map of phonemes to phoneme_ids.\n- `tone_id_map.txt` is the map of tones to tones_ids, when you split tones and phones before training acoustic models. (for example in our csmsc/speedyspeech example)\n- `spk_id_map.txt` is the map of speakers to spk_ids in multi-spk acoustic models. (for example in our aishell3/fastspeech2 example)\n\nThe example code below shows how to use the models for prediction.\n### Acoustic Models (text to spectrogram)\nThe code below shows how to use a `FastSpeech2` model.  After loading the pretrained model, use it and the normalizer object to construct a prediction object，then use `fastspeech2_inferencet(phone_ids)` to generate spectrograms, which can be further used to synthesize raw audio with a vocoder.\n\n```python\nfrom pathlib import Path\nimport numpy as np\nimport paddle\nimport yaml\nfrom yacs.config import CfgNode\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Inference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n# examples/fastspeech2/baker/frontend.py\nfrom frontend import Frontend\n\n# load the pretrained model\ncheckpoint_dir = Path(\"fastspeech2_nosil_baker_ckpt_0.4\")\nwith open(checkpoint_dir / \"phone_id_map.txt\", \"r\") as f:\n    phn_id = [line.strip().split() for line in f.readlines()]\nvocab_size = len(phn_id)\nwith open(checkpoint_dir / \"default.yaml\") as f:\n    fastspeech2_config = CfgNode(yaml.safe_load(f))\nodim = fastspeech2_config.n_mels\nmodel = FastSpeech2(\n    idim=vocab_size, odim=odim, **fastspeech2_config[\"model\"])\nmodel.set_state_dict(\n    paddle.load(args.fastspeech2_checkpoint)[\"main_params\"])\nmodel.eval()\n\n# load stats file\nstat = np.load(checkpoint_dir / \"speech_stats.npy\")\nmu, std = stat\nmu = paddle.to_tensor(mu)\nstd = paddle.to_tensor(std)\nfastspeech2_normalizer = ZScore(mu, std)\n\n# construct a prediction object\nfastspeech2_inference = FastSpeech2Inference(fastspeech2_normalizer, model)\n\n# load Chinese Frontend\nfrontend = Frontend(checkpoint_dir / \"phone_id_map.txt\")\n\n# text to spectrogram\nsentence = \"你好吗？\"\ninput_ids = frontend.get_input_ids(sentence, merge_sentences=True)\nphone_ids = input_ids[\"phone_ids\"]\nflags = 0\n# The output of Chinese text frontend is segmented\nfor part_phone_ids in phone_ids:\n    with paddle.no_grad():\n        temp_mel = fastspeech2_inference(part_phone_ids)\n        if flags == 0:\n            mel = temp_mel\n            flags = 1\n        else:\n            mel = paddle.concat([mel, temp_mel])\n```\n\n### Vocoder (spectrogram to wave)\nThe code below shows how to use a  ` Parallel WaveGAN` model. Like the example above, after loading the pretrained model, use it and the normalizer object to construct a prediction object，then use `pwg_inference(mel)` to generate raw audio (in wav format).\n\n```python\nfrom pathlib import Path\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n# load the pretrained model\ncheckpoint_dir = Path(\"parallel_wavegan_baker_ckpt_0.4\")\nwith open(checkpoint_dir / \"pwg_default.yaml\") as f:\n    pwg_config = CfgNode(yaml.safe_load(f))\nvocoder = PWGGenerator(**pwg_config[\"generator_params\"])\nvocoder.set_state_dict(paddle.load(args.pwg_params))\nvocoder.remove_weight_norm()\nvocoder.eval()\n\n# load stats file\nstat = np.load(checkpoint_dir / \"pwg_stats.npy\")\nmu, std = stat\nmu = paddle.to_tensor(mu)\nstd = paddle.to_tensor(std)\npwg_normalizer = ZScore(mu, std)\n\n# construct a prediction object\npwg_inference = PWGInference(pwg_normalizer, vocoder)\n\n# spectrogram to wave\nwav = pwg_inference(mel)\nsf.write(\n        audio_path,\n        wav.numpy(),\n        samplerate=fastspeech2_config.fs)\n```\n"
  },
  {
    "path": "docs/source/tts/quick_start_cn.md",
    "content": "(简体中文|[English](./quick_start.md))\n# 语音合成快速开始\n这些PaddleSpeech中的样例主要按数据集分类，我们主要使用的TTS数据集有：\n\n* CSMCS (普通话单发音人)\n* AISHELL3 (普通话多发音人)\n* LJSpeech (英文单发音人)\n* VCTK (英文多发音人)\n\nPaddleSpeech 的 TTS 模型具有以下映射关系：\n\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n* voc4 - Style MelGAN\n* voc5 - HiFiGAN\n* vc0 - Tacotron2 Voice Clone with GE2E\n* vc1 - FastSpeech2 Voice Clone with GE2E\n\n## 快速开始\n\n让我们以 FastSpeech2 + Parallel WaveGAN 和 CSMSC 数据集 为例. [examples/csmsc](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc)\n\n### 用 CSMSC 数据集训练 Parallel WaveGAN\n\n- 进入目录\n    ```bash\n    cd examples/csmsc/voc1\n    ```\n- 设置环境变量\n    ```bash\n    source path.sh\n    ```\n    **在你开始做任何事情之前，必须先做这步**\n    将 `MAIN_ROOT` 设置为项目目录. 使用 `parallelwave_gan` 模型作为 `MODEL`.\n\n- 运行\n    ```bash\n    bash run.sh\n    ```\n    这只是一个演示，请确保源数据已经准备好，并且在下一个 `step` 之前每个 `step` 都运行正常.\n### 用CSMSC数据集训练FastSpeech2\n\n- 进入目录\n    ```bash\n    cd examples/csmsc/tts3\n    ```\n    \n- 设置环境变量\n    ```bash\n    source path.sh\n    ```\n    **在你开始做任何事情之前，必须先做这步**\n    将 `MAIN_ROOT` 设置为项目目录. 使用 `fastspeech2` 模型作为 `MODEL` 。\n    \n- 运行\n    ```bash\n    bash run.sh\n    ```\n    这只是一个演示，请确保源数据已经准备好，并且在下一个 `step` 之前每个 `step` 都运行正常。\n\n`run.sh` 中主要包括以下步骤：\n\n- 设置路径。\n- 预处理数据集，\n- 训练模型。\n- 从 `metadata.jsonl` 中合成波形\n- 从文本文件合成波形。（在声学模型中）\n- 使用静态模型进行推理。（可选）\n\n有关更多详细信息，请参见 examples 中的 `README.md`\n\n## TTS 流水线\n本节介绍如何使用 TTS 提供的预训练模型，并对其进行推理。\n\nTTS中的预训练模型在压缩包中提供。将其解压缩以获得如下文件夹：\n**Acoustic Models:**\n\n```text\ncheckpoint_name\n├── default.yaml\n├── snapshot_iter_*.pdz\n├── speech_stats.npy\n├── phone_id_map.txt\n├── spk_id_map.txt (optional)\n└── tone_id_map.txt (optional)\n```\n**Vocoders:**\n```text\ncheckpoint_name\n├── default.yaml  \n├── snapshot_iter_*.pdz\n└── stats.npy  \n```\n- `default.yaml` 存储用于训练模型的配置。\n- `snapshot_iter_*.pdz` 是检查点文件，其中`*`是它经过训练的步骤。\n- `*_stats.npy` 是特征的统计文件，如果它在训练前已被标准化。\n- `phone_id_map.txt` 是音素到音素 ID 的映射关系。\n- `tone_id_map.txt` 是在训练声学模型之前分割音调和拼音时，音调到音调 ID 的映射关系。（例如在 csmsc/speedyspeech 的示例中）\n- `spk_id_map.txt` 是多发音人声学模型中 \"发音人\" 到 \"spk_ids\" 的映射关系。\n\n下面的示例代码显示了如何使用模型进行预测。\n### Acoustic Models 声学模型（文本到频谱图）\n下面的代码显示了如何使用 `FastSpeech2` 模型。加载预训练模型后，使用它和 normalizer 对象构建预测对象，然后使用 `fastspeech2_inferencet(phone_ids)` 生成频谱图，频谱图可进一步用于使用声码器合成原始音频。\n\n```python\nfrom pathlib import Path\nimport numpy as np\nimport paddle\nimport yaml\nfrom yacs.config import CfgNode\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Inference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n# examples/fastspeech2/baker/frontend.py\nfrom frontend import Frontend\n\n# 加载预训练模型\ncheckpoint_dir = Path(\"fastspeech2_nosil_baker_ckpt_0.4\")\nwith open(checkpoint_dir / \"phone_id_map.txt\", \"r\") as f:\n    phn_id = [line.strip().split() for line in f.readlines()]\nvocab_size = len(phn_id)\nwith open(checkpoint_dir / \"default.yaml\") as f:\n    fastspeech2_config = CfgNode(yaml.safe_load(f))\nodim = fastspeech2_config.n_mels\nmodel = FastSpeech2(\n    idim=vocab_size, odim=odim, **fastspeech2_config[\"model\"])\nmodel.set_state_dict(\n    paddle.load(args.fastspeech2_checkpoint)[\"main_params\"])\nmodel.eval()\n\n# 加载特征文件\nstat = np.load(checkpoint_dir / \"speech_stats.npy\")\nmu, std = stat\nmu = paddle.to_tensor(mu)\nstd = paddle.to_tensor(std)\nfastspeech2_normalizer = ZScore(mu, std)\n\n# 构建预测对象\nfastspeech2_inference = FastSpeech2Inference(fastspeech2_normalizer, model)\n\n# load Chinese Frontend\nfrontend = Frontend(checkpoint_dir / \"phone_id_map.txt\")\n\n# 构建一个中文前端\nsentence = \"你好吗？\"\ninput_ids = frontend.get_input_ids(sentence, merge_sentences=True)\nphone_ids = input_ids[\"phone_ids\"]\nflags = 0\n# 构建预测对象加载中文前端，对中文文本前端的输出进行分段\nfor part_phone_ids in phone_ids:\n    with paddle.no_grad():\n        temp_mel = fastspeech2_inference(part_phone_ids)\n        if flags == 0:\n            mel = temp_mel\n            flags = 1\n        else:\n            mel = paddle.concat([mel, temp_mel])\n```\n\n### Vcoder声码器（谱图到波形）\n下面的代码显示了如何使用 `Parallel WaveGAN` 模型。像上面的例子一样，加载预训练模型后，使用它和 normalizer 对象构建预测对象，然后使用 `pwg_inference(mel)` 生成原始音频（ wav 格式）。\n\n```python\nfrom pathlib import Path\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n# 加载预训练模型\ncheckpoint_dir = Path(\"parallel_wavegan_baker_ckpt_0.4\")\nwith open(checkpoint_dir / \"pwg_default.yaml\") as f:\n    pwg_config = CfgNode(yaml.safe_load(f))\nvocoder = PWGGenerator(**pwg_config[\"generator_params\"])\nvocoder.set_state_dict(paddle.load(args.pwg_params))\nvocoder.remove_weight_norm()\nvocoder.eval()\n\n# 加载特征文件\nstat = np.load(checkpoint_dir / \"pwg_stats.npy\")\nmu, std = stat\nmu = paddle.to_tensor(mu)\nstd = paddle.to_tensor(std)\npwg_normalizer = ZScore(mu, std)\n\n# 加载预训练模型构造预测对象\npwg_inference = PWGInference(pwg_normalizer, vocoder)\n\n# 频谱图到波形\nwav = pwg_inference(mel)\nsf.write(\n        audio_path,\n        wav.numpy(),\n        samplerate=fastspeech2_config.fs)\n```\n"
  },
  {
    "path": "docs/source/tts/svs_music_score.md",
    "content": "本人非音乐专业人士，如文档中有误欢迎指正。\n\n# 一、常见基础\n## 1.1 简谱和音名（note）\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/seven.png\" width=\"300\"/>\n</p>\n\n上图从左往右的黑键音名分别是：C#/Db，D#/Db，F#/Db，G#/Ab，A#/Bb\n钢琴88键如下图，分为大字一组，大字组，小字组，小字一组，小字二组，小字三组，小字四组。分别对应音名的后缀是 1 2 3 4 5 6，例如小字一组（C大调）包含的键分别为： C4，C#4/Db4，D4，D#4/Eb4，E4，F4，F#4/Gb4，G4，G#4/Ab4，A4，A#4/Bb4，B4  \n钢琴八度音就是12345671八个音，最后一个音是高1。**遵循：全全半全全全半** 就会得到 1 2 3 4 5 6 7 (高)1 的音\n\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/piano_88.png\" />\n</p>\n\n## 1.2 十二大调\n“#”表示升调\n\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/up.png\" />\n</p>\n\n“b”表示降调\n\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/down.png\" />\n</p>\n\n什么大调表示Do(简谱1) 这个音从哪个键开始，例如D大调，则用D这个键来表示 Do这个音。\n下图是十二大调下简谱与音名的对应表。\n\n<p align=\"left\">\n  <img src=\"../../../docs/images/note_map.png\" />\n</p>\n\n\n## 1.3 Tempo\nTempo 用于表示速度（Speed of the beat/pulse），一分钟里面有几拍（beats per mimute BPM）\n\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/note_beat.png\" width=\"450\"/>\n</p>\n\nwhole note -->  4 beats</br>\nhalf note --> 2 beats</br>\nquarter note --> 1 beat</br>\neighth note --> 1/2 beat</br>\nsixteenth note --> 1/4 beat</br> \n\n\n# 二、应用试验\n## 2.1 从谱中获取 music scores\nmusic scores 包含：note，note_dur，is_slur\n\n<p align=\"left\">\n  <img src=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/pu.png\" width=\"600\"/>\n</p>\n\n从左上角的谱信息 *bE* 可以得出该谱子是 **降E大调**，可以对应1.2小节十二大调简谱音名对照表根据 简谱获取对应的note\n从左上角的谱信息 *quarter note* 可以得出该谱子的速度是 **一分钟95拍（beat）**，一拍的时长 = **60/95 = 0.631578s**\n从左上角的谱信息 *4/4* 可以得出该谱子表示四分音符为一拍（分母的4），每小节有4拍（分子的4）\n\n从该简谱上可以获取 music score 如下：\n\n|text |phone |简谱（辅助）后面的点表示高八音 |note （从小字组开始算） |几拍（辅助） |note_dur |is_slur|\n:-------------:| :------------:| :-----: | -----: | :-----: |:-----:| :-----:  |\n|小 |x   |5  |A#3/Bb3 |半 |0.315789 |0 |\n|   |iao |5  |A#3/Bb3 |半 |0.315789 |0 |\n|酒 |j   |1. |D#4/Eb4 |半 |0.315789 |0 |\n|   |iu  |1. |D#4/Eb4 |半 |0.315789 |0 |\n|窝 |w   |2. |F4      |半 |0.315789 |0 |\n|   |o   |2. |F4      |半 |0.315789 |0 |\n|长 |ch  |3. |G4      |半 |0.315789 |0 |\n|   |ang |3. |G4      |半 |0.315789 |0 |\n|   |ang |1. |D#4/Eb4 |半 |0.315789 |1 |\n|睫 |j   |1. |D#4/Eb4 |半 |0.315789 |0 |\n|   |ie  |1. |D#4/Eb4 |半 |0.315789 |0 |\n|   |ie  |5  |A#3/Bb3 |半 |0.315789 |1 |\n|毛 |m   |5  |A#3/Bb3 |一 |0.631578 |0 |\n|   |ao  |5  |A#3/Bb3 |一 |0.631578 |0 |\n|是 |sh  |5  |A#3/Bb3 |半 |0.315789 |0 |\n|   |i   |5  |A#3/Bb3 |半 |0.315789 |0 |\n|你 |n   |3. |G4      |半 |0.315789 |0 |\n|   |i   |3. |G4      |半 |0.315789 |0 |\n|最 |z   |2. |F4      |半 |0.315789 |0 |\n|   |ui  |2. |F4      |半 |0.315789 |0 |\n|美 |m   |3. |G4      |半 |0.315789 |0 |\n|   |ei  |3. |G4      |半 |0.315789 |0 |\n|的 |d   |2. |F4      |半 |0.315789 |0 |\n|   |e   |2. |F4      |半 |0.315789 |0 |\n|记 |j   |7  |D4      |半 |0.315789 |0 |\n|   |i   |7  |D4      |半 |0.315789 |0 |\n|号 |h   |5  |A#3/Bb3 |半 |0.315789 |0 |\n|   |ao  |5  |A#3/Bb3 |半 |0.315789 |0 |\n\n\n## 2.2 一些实验\n\n<div align = \"center\">\n<table style=\"width:100%\">\n  <thead>\n    <tr>\n      <th> 序号  </th>\n      <th width=\"500\"> 说明  </th>\n      <th> 合成音频（diffsinger_opencpop + pwgan_opencpop） </th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td > 1 </td>\n      <td > 原始 opencpop 标注的 notes，note_durs，is_slurs，升F大调，起始在小字组（第3组） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test1.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 2 </td>\n      <td > 原始 opencpop 标注的 notes 和 is_slurs，note_durs 改变（从谱子获取） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test2.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 3 </td>\n      <td > 原始 opencpop 标注的 notes 去掉 rest（毛字一拍），is_slurs 和 note_durs 改变（从谱子获取） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test3.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 4 </td>\n      <td > 从谱子获取 notes，note durs，is_slurs，不含 rest（毛字一拍），起始在小字一组（第3组） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test4.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 5 </td>\n      <td > 从谱子获取 notes，note durs，is_slurs，加上 rest （毛字半拍，rest半拍），起始在小字一组（第3组）</td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test5.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 6 </td>\n      <td > 从谱子获取 notes， is_slurs，包含 rest，note_durs 从原始标注获取，起始在小字一组（第3组） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test6.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    <tr>\n      <td > 7 </td>\n      <td > 从谱子获取 notes，note durs，is_slurs，不含 rest（毛字一拍），起始在小字一组（第4组） </td>\n      <td align = \"center\">\n      <a href=\"https://paddlespeech.cdn.bcebos.com/t2s/svs/svs_music_scores/test7.wav\" rel=\"nofollow\">\n            <img align=\"center\" src=\"../../../docs/images/audio_icon.png\" width=\"200 style=\"max-width: 100%;\"></a><br>\n      </td>\n    </tr>\n    \n  </tbody>\n</table>\n\n</div>\n\n\n上述实验表明通过该方法来提取 music score 是可行的，但是在应用中可以**灵活地在歌词中加\"AP\"(用来表示吸气声)和\"SP\"(用来表示停顿声)**，对应的在 **note 上加 rest**，会使得整体的歌声合成更自然。\n除此之外，还要考虑哪一个大调并且以哪一组为起始**得到的 note 在训练数据集中出现过**，如若推理时传入训练数据中没有见过的 note， 合成出来的音频可能不是我们期待的音调。\n\n\n# 三、其他\n## 3.1 读取midi\n\n```python\nimport mido\nmid = mido.MidiFile('2093.midi')\n```\n"
  },
  {
    "path": "docs/source/tts/test_sentence.txt",
    "content": "001 早上好，今天是2020/10/29，最低温度是-3°C。\n002 你好，我的编号是37249，很高兴为您服务。\n003 我们公司有37249个人。\n004 我出生于2005年10月8日。\n005 我们习惯在12:30吃中午饭。\n006 只要有超过3/4的人投票同意，你就会成为我们的新班长。\n007 我要买一只价值999.9元的手表。\n008 我的手机号是18544139121，欢迎来电。\n009 明天有62%的概率降雨。\n010 手表厂有五种好产品。\n011 跑马场有五百匹很勇敢的千里马。\n012 有一天，我看到了一栋楼，我顿感不妙，因为我看不清里面有没有人。\n013 史小姐拿着小雨伞去找她的老保姆了。\n014 不要相信这个老奶奶说的话，她一点儿也不好。"
  },
  {
    "path": "docs/source/tts/tts_datasets.md",
    "content": "# TTS Datasets\n<!--\nsee https://openslr.org/\n-->\n## Mandarin\n- [CSMSC](https://www.data-baker.com/open_source.html): Chinese Standard Mandarin Speech Copus\n    - Duration/h: 12\n    - Number of Sentences: 10,000\n    - Size: 2.14GB\n    - Speaker: 1 female, ages 20 ~30\n    - Sample Rate: 48 kHz、16bit\n    - Mean Words per Clip: 16\n- [AISHELL-3](http://www.aishelltech.com/aishell_3)\n    - Duration/h: 85\n    - Number of Sentences: 88,035\n    - Size: 17.75GB\n    - Speaker: 218\n    - Sample Rate: 44.1 kHz、16bit \n\n## English\n- [LJSpeech](https://keithito.com/LJ-Speech-Dataset/)\n    - Duration/h: 24\n    - Number of Sentences: 13,100\n    - Size: 2.56GB\n    - Speaker: 1, age 20 ~30\n    - Sample Rate: 22050 Hz、16bit\n    - Mean Words per Clip: 17.23\n- [VCTK](https://datashare.ed.ac.uk/handle/10283/3443)\n    - Number of Sentences: 44,583\n    - Size: 10.94GB\n    - Speaker: 110 \n    - Sample Rate: 48 kHz、16bit\n    - Mean Words per Clip: 17.23\n\n## Japanese\n<!--\nsee https://sites.google.com/site/shinnosuketakamichi/publication/corpus\n-->\n\n- [tri-jek](https://sites.google.com/site/shinnosuketakamichi/research-topics/tri-jek_corpus): Japanese-English-Korean tri-lingual corpus\n- [JSSS-misc](https://sites.google.com/site/shinnosuketakamichi/research-topics/jsss-misc_corpus): misc tasks of JSSS corpus\n- [JTubeSpeech](https://github.com/sarulab-speech/jtubespeech): Corpus of Japanese speech collected from YouTube\n- [J-MAC](https://sites.google.com/site/shinnosuketakamichi/research-topics/j-mac_corpus): Japanese multi-speaker audiobook corpus\n- [J-KAC](https://sites.google.com/site/shinnosuketakamichi/research-topics/j-kac_corpus): Japanese Kamishibai and audiobook corpus\n- [JMD](https://sites.google.com/site/shinnosuketakamichi/research-topics/jmd_corpus): Japanese multi-dialect corpus\n- [JSSS](https://sites.google.com/site/shinnosuketakamichi/research-topics/jsss_corpus): Japanese multi-style (summarization and simplification) corpus\n- [RWCP-SSD-Onomatopoeia](https://www.ksuke.net/dataset/rwcp-ssd-onomatopoeia): onomatopoeic word dataset for environmental sounds \n- [Life-m](https://sites.google.com/site/shinnosuketakamichi/research-topics/life-m_corpus): landmark image-themed music corpus\n- [PJS](https://sites.google.com/site/shinnosuketakamichi/research-topics/pjs_corpus): Phoneme-balanced Japanese singing voice corpus\n- [JVS-MuSiC](https://sites.google.com/site/shinnosuketakamichi/research-topics/jvs_music): Japanese multi-speaker singing-voice corpus\n- [JVS](https://sites.google.com/site/shinnosuketakamichi/research-topics/jvs_corpus): Japanese multi-speaker voice corpus\n- [JSUT-book](https://sites.google.com/site/shinnosuketakamichi/publication/jsut-book): audiobook corpus by a single Japanese speaker\n- [JSUT-vi](https://sites.google.com/site/shinnosuketakamichi/publication/jsut-vi): vocal imitation corpus by a single Japanese speaker\n- [JSUT-song](https://sites.google.com/site/shinnosuketakamichi/publication/jsut-song): singing voice corpus by a single Japanese singer\n- [JSUT](https://sites.google.com/site/shinnosuketakamichi/publication/jsut): a large-scaled corpus of reading-style Japanese speech by a single speaker\n\n## Emotions\n### English\n- [CREMA-D](https://github.com/CheyneyComputerScience/CREMA-D)\n- [Seen and Unseen emotional style transfer for voice conversion with a new emotional speech dataset](https://kunzhou9646.github.io/controllable-evc/)\n    - paper : [Seen and Unseen emotional style transfer for voice conversion with a new emotional speech dataset](https://arxiv.org/abs/2010.14794)\n### Mandarin\n- [EMOVIE Dataset](https://viem-ccy.github.io/EMOVIE/dataset_release )\n    - paper: [EMOVIE: A Mandarin Emotion Speech Dataset with a Simple Emotional Text-to-Speech Model](https://arxiv.org/abs/2106.09317)\n- MASC\n    - paper: [MASC: A Speech Corpus in Mandarin for Emotion Analysis and Affective Speaker Recognition](https://ieeexplore.ieee.org/document/4013501)\n### English && Mandarin\n- [Emotional Voice Conversion: Theory, Databases and ESD](https://github.com/HLTSingapore/Emotional-Speech-Data)    \n    - paper: [Emotional Voice Conversion: Theory, Databases and ESD](https://arxiv.org/abs/2105.14762) \n\n## Music\n- [GiantMIDI-Piano](https://github.com/bytedance/GiantMIDI-Piano)\n- [MAESTRO Dataset](https://magenta.tensorflow.org/datasets/maestro)\n     - [tf code](https://www.tensorflow.org/tutorials/audio/music_generation) \n- [Opencpop](https://wenet.org.cn/opencpop/)\n"
  },
  {
    "path": "docs/source/tts/tts_papers.md",
    "content": "# TTS Papers\n## Text Frontend\n### Polyphone\n- [【g2pM】g2pM: A Neural Grapheme-to-Phoneme Conversion Package for Mandarin Chinese Based on a New Open Benchmark Dataset](https://arxiv.org/abs/2004.03136)\n- [Disambiguation of Chinese Polyphones in an End-to-End Framework with Semantic Features Extracted by Pre-trained BERT](https://www1.se.cuhk.edu.hk/~hccl/publications/pub/201909_INTERSPEECH_DongyangDAI.pdf)\n- [Polyphone Disambiguation in Mandarin Chinese with Semi-Supervised Learning](https://www.isca-speech.org/archive/pdfs/interspeech_2021/shi21d_interspeech.pdf)\n  * github: https://github.com/PaperMechanica/SemiPPL\n- [WikipediaHomographData](https://github.com/google-research-datasets/WikipediaHomographData)\n### Text Normalization\n#### English\n- [applenob/text_normalization](https://github.com/applenob/text_normalization)\n### G2P\n#### English\n- [cmusphinx/g2p-seq2seq](https://github.com/cmusphinx/g2p-seq2seq)\n\n## Acoustic Models\n- [【AdaSpeech3】AdaSpeech 3: Adaptive Text to Speech for Spontaneous Style](https://arxiv.org/abs/2107.02530)\n- [【AdaSpeech2】AdaSpeech 2: Adaptive Text to Speech with Untranscribed Data](https://arxiv.org/abs/2104.09715)\n- [【AdaSpeech】AdaSpeech: Adaptive Text to Speech for Custom Voice](https://arxiv.org/abs/2103.00993)\n- [【FastSpeech2】FastSpeech 2: Fast and High-Quality End-to-End Text to Speech](https://arxiv.org/abs/2006.04558)\n- [【FastPitch】FastPitch: Parallel Text-to-speech with Pitch Prediction](https://arxiv.org/abs/2006.06873)\n- [【SpeedySpeech】SpeedySpeech: Efficient Neural Speech Synthesis](https://arxiv.org/abs/2008.03802)\n- [【FastSpeech】FastSpeech: Fast, Robust and Controllable Text to Speech](https://arxiv.org/abs/1905.09263)\n- [【Transformer TTS】Neural Speech Synthesis with Transformer Network](https://arxiv.org/abs/1809.08895)\n- [【Tacotron2】Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions](https://arxiv.org/abs/1712.05884)\n\n## Vocoders\n- [【RefineGAN】RefineGAN: Universally Generating Waveform Better than Ground Truth with Highly Accurate Pitch and Intensity Responses](https://arxiv.org/abs/2111.00962)\n- [【Fre-GAN】Fre-GAN: Adversarial Frequency-consistent Audio Synthesis](https://arxiv.org/abs/2106.02297)\n- [【StyleMelGAN】StyleMelGAN: An Efficient High-Fidelity Adversarial Vocoder with Temporal Adaptive Normalization](https://arxiv.org/abs/2011.01557)\n- [【Multi-band MelGAN】Multi-band MelGAN: Faster Waveform Generation for High-Quality Text-to-Speech](https://arxiv.org/abs/2005.05106)\n- [【HiFi-GAN】HiFi-GAN: Generative Adversarial Networks for Efficient and High Fidelity Speech Synthesis](https://arxiv.org/abs/2010.05646)\n- [【VocGAN】VocGAN: A High-Fidelity Real-time Vocoder with a Hierarchically-nested Adversarial Network](https://arxiv.org/abs/2007.15256)\n- [【Parallel WaveGAN】Parallel WaveGAN: A fast waveform generation model based on generative adversarial networks with multi-resolution spectrogram](https://arxiv.org/abs/1910.11480)\n- [【MelGAN】MelGAN: Generative Adversarial Networks for Conditional Waveform Synthesis](https://arxiv.org/abs/1910.06711)\n- [【WaveFlow】WaveFlow: A Compact Flow-based Model for Raw Audio](https://arxiv.org/abs/1912.01219)\n- [【LPCNet】LPCNet: Improving Neural Speech Synthesis Through Linear Prediction](https://arxiv.org/abs/1810.11846)\n- [【WaveRNN】Efficient Neural Audio Synthesis](https://arxiv.org/abs/1802.08435)\n## GAN TTS\n\n- [【GAN TTS】High Fidelity Speech Synthesis with Adversarial Networks](https://arxiv.org/abs/1909.11646)\n\n## Voice Cloning\n- [【SV2TTS】Transfer Learning from Speaker Verification to Multispeaker Text-to-Speech Synthesis](https://arxiv.org/abs/1806.04558)\n- [【GE2E】Generalized End-to-End Loss for Speaker Verification](https://arxiv.org/abs/1710.10467)\n"
  },
  {
    "path": "docs/source/tts/zh_text_frontend.md",
    "content": "# Chinese Rule-Based Text Frontend\nA TTS system mainly includes three modules: `Text Frontend`, `Acoustic model` and `Vocoder`. We provide a complete Chinese text frontend module in PaddleSpeech TTS, see exapmles in [examples/other/tn](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/tn) and [examples/other/g2p](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/g2p).\n\nA text frontend module mainly includes:\n - Text Segmentation\n - Text Normalization (TN)\n - Word Segmentation (mainly in Chinese)\n - Part-of-Speech\n - Prosody\n - G2P (Grapheme-to-Phoneme, include Polyphone and Tone Sandhi, etc.)\n - Linguistic Features/Charactors/Phonemes\n\n```text\n• text: 90 后为中华人民共和国成立 70 周年准备了大礼\n• Text Normalization: 九零后为中华人民共和国成立七十周年准备了大礼\n• Word Segmentation: 九零后/为/中华人民/共和国/成立/七十/周年/准备/了/大礼\n• G2P:\n    jiu3 ling2 hou4 wei4 zhong1 hua2 ren2 min2 gong4 he2 guo2 ...\n• Prosody (prosodic words #1, prosodic phrases #2, intonation phrases #3, sentence #4):\n    九零后#1为中华人民#1共和国#2成立七十周年#3准备了大礼#4\n```\n\nAmong them, Text Normalization and G2P are the most important modules. We mainly introduce them here.\n\n## Text Normalization\n### Supported NSW (Non-Standard-Word) Normalization\n\n|NSW type|raw|normalized|\n|:--|:-|:-|\n|serial number|电影中梁朝伟扮演的陈永仁的编号27149|电影中梁朝伟扮演的陈永仁的编号二七一四九|\n|cardinal|这块黄金重达324.75克<br>我们班的最高总分为583分|这块黄金重达三百二十四点七五克<br>我们班的最高总分为五百八十三分|\n|numeric range |12\\~23<br>-1.5\\~2|十二到二十三<br>负一点五到二|\n|date|她出生于86年8月18日，她弟弟出生于1995年3月1日|她出生于八六年八月十八日， 她弟弟出生于一九九五年三月一日|\n|time|等会请在12:05请通知我|等会请在十二点零五分请通知我\n|temperature|今天的最低气温达到-10°C|今天的最低气温达到零下十度\n|fraction|现场有7/12的观众投出了赞成票|现场有十二分之七的观众投出了赞成票|\n|percentage|明天有62％的概率降雨|明天有百分之六十二的概率降雨|\n|money|随便来几个价格12块5，34.5元，20.1万|随便来几个价格十二块五，三十四点五元，二十点一万|\n|telephone|这是固话0421-33441122<br>这是手机+86 18544139121|这是固话零四二一三三四四一一二二<br>这是手机八六一八五四四一三九一二一|\n\n\n## Grapheme-to-Phoneme\nIn Chinese, G2P is a very complex module, which mainly includes **polyphone**  and **tone sandhi**.\n\nWe use [g2pM](https://github.com/kakaobrain/g2pM) and [pypinyin](https://github.com/mozillazg/python-pinyin)  as the default g2p tools. They can solve the problem of polyphones to a certain extent. In the future, we intend to use a trainable language model (for example, [BERT](https://arxiv.org/abs/1810.04805)) for polyphones.\n\nHowever, g2pM and pypinyin do not perform well in tone sandhi, we use rules to solve this problem, which requires relevant linguistic knowledge.\n\nThe **tone sandhi** in Chinese mainly include:\n\n - soft tone sandhi (轻声变调)\n - \"一\" \"不\" tone sandhi (\"一\" \"不\" 变调)\n - three tone sandhi  (三声变调)\n\nFor ease of understanding, we list the tone sandhi rules in Chinese here\n### 1. 轻声变调\n|  |cases  |\n|:--|:-|\n| 语气助词“吧、呢、啊”等 | 吃吧、走吗、去呢、跑啊 |\n| 结构助词：“的、地、得”| 我的书、慢慢地走、跑得很快等 |\n|有的轻声音节和非轻声音节构成对比区别意义 |买卖：一指生意；二指买和卖。 <br/> 地道：一指纯粹、真正；二指地下通道。<br> 大意：一指没有注意；二指主要的意思。 <br/>  东西：一指各种事物；二指东面与西面。<br>  言语：一指所说的话；二指开口，招呼。<br/>运气：一指一种锻炼的方法。二指幸运。<br> |\n|名词的后缀：“们、子、头”|你们、房子、石头 |\n|名词或动词的第二个重叠音节 | 奶奶、姐姐、爸爸、试试、看看、说说、问问 |\n|名词后面表示方位的：“上、下、里” |桌上、地下、院里  |\n| 动态助词：“了、着、过” | 走了、看着、去过|\n| 作宾语的人称代词：“我、你、他” | 找我、请你、麻烦他。 |\n| 约定俗成 | 匀称、盘算、枇杷、篱笆、活泼、玄乎。狐狸、学生、拾掇、麻烦、蛤蟆、石榴。玫瑰、凉快、萝卜、朋友、奴才、云彩。脑袋、老爷、老婆、嘴巴、指头、指甲。委屈、喇叭、讲究、打发、打听、喜欢。点心、伙计、打扮、哑巴、女婿、首饰。自在、吓唬、力气、漂亮、队伍、地方。痛快、念叨、笑语、丈夫、志气、钥匙。月亮、正经、位置、秀气、上司、悟性。告示、动静、热闹、屁股、阔气、意思。等 |\n\n\n### 2. \"一\" \"不\" 变调\n#### \"一\" 变调\n|  | 是否变调 | cases|\n|:--|:-|:-|\n| 单独念 | 否 | 第一、一楼|\n| 序数 |否  | |\n| 用在语句末尾 | 否 | |\n| 去声前变阳平（四声前变二声） |  | 一栋yí dòng、一段yí duàn、一律yí lǜ、一路yí lù|\n| 非去声前变去声（非四声前变四声） |  | 阴平（一声）<br>一发yì fā 、一端yì duān、一天yì tiān、一忽yì hū<br>阳平（二声）<br>一叠yì dié 、一同yì tóng 、一头yì tóu 、一条yì tiáo<br>上声（三声）<br>一统yì tǒng、一体yì tǐ、一览yì lǎn、一口yì kǒu|\n|轻读，当“一”嵌在重叠式的动词之间  |  | 听一听 tīng yi tīng|\n\n#### \"不\" 变调\n|  | 是否变调 | cases|\n|:--|:-|:-|\n|单独念|否  | |\n| 用在语句末尾| 否  | 我不|\n|去声前变阳平（四声前变成二声）  |  | 不怕bú pà、不妙bú miào、不犯bú fàn、不忿bú fèn|\n| 轻读，不”夹在重叠动词或重叠形容词之间、夹在动词和补语之间 |  |懂不懂 dǒng bu dǒng 、看不清 kàn bu qīng |\n\n\n### 3. 三声变调\n|  | 子类别| 如何变调|cases|\n|:--|:-|:-|:-|\n|单独念 |  | 否|  |\n|句末 |  | 否|  |\n|在句中停顿并没被后音节影响  |  |否 |  |\n|三声+三声  |  | 二声+三声|保险、保养、党委、尽管、老板、本领、引导、古老、敏感、鼓舞、永远、语法、口语、岛屿、保姆、远景、北海、首长、母语 |\n| 三个三声相连| 双音节+单音节（“双单格”结构）| 前两个变二声|演讲稿、跑马场、展览馆、管理组、水彩笔、蒙古语、选取法、古典舞、虎骨酒、洗脸水、草稿纸|\n|  | 单音节+双音节（“单双格”结构）|第二个变二声|史小姐、党小组、好小伙、跑百米、纸老虎、李厂长、老保姆、冷处理、很友好、小雨伞|\n|  | 单音节+单音节+单音节（“单三格”结构）| 前两个变二声| 软懒散、稳准狠|\n| 更多三声音节相连时|  | 按语意与若干二字组成三字组，然后按以上变调规律处理|岂有 / 此理。<br>请你 / 给我 / 打点儿 / 洗脸水。<br>手表厂 / 有五种 /好产品。|\n\n## References\n\n - [chinese_text_normalization](https://github.com/speechio/chinese_text_normalization)\n - [声调篇｜这些“一、不”变调规律，你不得不知](https://zhuanlan.zhihu.com/p/36156170)\n - [TTS前端模块中的普通话变调规则](https://zhuanlan.zhihu.com/p/65091429)\n - [轻声和变调](https://wenku.baidu.com/view/ad2016d94693daef5ef73db1.html)\n - [必读轻声词语表546条](http://www.chaziwang.com/article-view-504.html)\n"
  },
  {
    "path": "docs/source/tts_demo_video.rst",
    "content": "TTS Demo Video\n==================\n\n.. raw:: html\n     \n    <video controls width=\"1024\">\n\n    <source src=\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/paddle2021_with_me.mp4\"\n            type=\"video/mp4\">\n    Sorry, your browser doesn't support embedded videos.\n    </video>\n\n"
  },
  {
    "path": "docs/source/vpr/PPVPR.md",
    "content": "([简体中文](./PPVPR_cn.md)|English)\n# PP-VPR\n\n## Catalogue\n- [1. Introduction](#1)\n- [2. Characteristic](#2)\n- [3. Tutorials](#3)\n    - [3.1 Pre-trained Models](#31)\n    - [3.2 Training](#32)\n    - [3.3 Inference](#33)\n    - [3.4 Service Deployment](#33)\n- [4. Quick Start](#4)\n\n<a name=\"1\"></a>\n## 1. Introduction\n\nPP-VPR is a tool that provides voice print feature extraction and retrieval functions.  Provides a variety of quasi-industrial solutions, easy to solve the difficult problems in complex scenes, support the use of command line model reasoning.  PP-VPR also supports interface operations and container deployment.  \n\n<a name=\"2\"></a>\n## 2. Characteristic\nThe basic process of VPR is shown in the figure below:  \n<center><img src=https://ai-studio-static-online.cdn.bcebos.com/3aed59b8c8874046ad19fe583d15a8dd53c5b33e68db4383b79706e5add5c2d0 width=\"800\" ></center>\n\n\nThe main characteristics of PP-ASR are shown below:\n-  Provides pre-trained models on Chinese open source datasets: VoxCeleb(English). The models include ecapa-tdnn.\n-  Support model training/evaluation.\n-  Support model inference using the command line. You can use to use `paddlespeech vector --task spk --input xxx.wav` to use the pre-trained model to do model inference. \n-  Support interface operations and container deployment.\n\n<a name=\"3\"></a>\n## 3. Tutorials\n\n<a name=\"31\"></a>\n## 3.1 Pre-trained Models\nThe support pre-trained model list: [released_model](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md).  \nFor more information about model design, you can refer to the aistudio tutorial:\n- [ecapa-tdnn](https://aistudio.baidu.com/aistudio/projectdetail/4027664)\n\n<a name=\"32\"></a>\n## 3.2 Training\nThe referenced script for model training is stored in [examples](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples) and stored according to \"examples/dataset/model\". The dataset mainly supports VoxCeleb. The model supports ecapa-tdnn.\nThe specific steps of executing the script are recorded in `run.sh`.\n\nFor more information, you can refer to [sv0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/voxceleb/sv0)\n\n\n<a name=\"33\"></a>\n## 3.3 Inference\n\nPP-VPR supports use `paddlespeech vector --task spk --input xxx.wav` to use the pre-trained model to do inference after install `paddlespeech` by `pip install paddlespeech`.\n\nSpecific supported functions include:\n\n- Prediction of single audio\n- Score the similarity between the two audios\n- Support RTF calculation\n\nFor specific usage, please refer to: [speaker_verification](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/speaker_verification/README_cn.md) \n\n\n<a name=\"34\"></a>\n## 3.4 Service Deployment\n\nPP-VPR supports Docker containerized service deployment.  Through Milvus, MySQL performs high performance library building search.  \n\nDemo of VPR Server: [audio_searching](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/audio_searching)\n\n![arch](https://ai-studio-static-online.cdn.bcebos.com/7b32dd0200084866863095677e8b40d3b725b867d2e6439e9cf21514e235dfd5)\n\nFor more information about service deployment, you can refer to the aistudio tutorial:\n- [speaker_recognition](https://aistudio.baidu.com/aistudio/projectdetail/4027664)\n\n<a name=\"4\"></a>\n\n## 4. Quick Start\n\nTo use PP-VPR, you can see here [install](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md), It supplies three methods to install `paddlespeech`, which are **Easy**, **Medium** and **Hard**. If you want to experience the inference function of paddlespeech, you can use **Easy** installation method.\n"
  },
  {
    "path": "docs/source/vpr/PPVPR_cn.md",
    "content": "(简体中文|[English](./PPVPR.md))\n# PP-VPR\n\n## 目录\n- [1. 简介](#1)\n- [2. 特点](#2)\n- [3. 使用教程](#3)\n    - [3.1 预训练模型](#31)\n    - [3.2 模型训练](#32)\n    - [3.3 模型推理](#33)\n    - [3.4 服务部署](#33)\n- [4. 快速开始](#4)\n\n<a name=\"1\"></a>\n## 1. 简介\n\nPP-VPR 是一个 提供声纹特征提取，检索功能的工具。提供了多种准工业化的方案，轻松搞定复杂场景中的难题，支持使用命令行的方式进行模型的推理。 PP-VPR 也支持界面化的操作，容器化的部署。\n\n<a name=\"2\"></a>\n## 2. 特点\nVPR 的基本流程如下图所示：  \n<center><img src=https://ai-studio-static-online.cdn.bcebos.com/3aed59b8c8874046ad19fe583d15a8dd53c5b33e68db4383b79706e5add5c2d0 width=\"800\" ></center>\n\n\nPP-VPR 的主要特点如下：\n-  提供在英文开源数据集 VoxCeleb（英文）上的预训练模型，ecapa-tdnn。\n-  支持模型训练评估功能。\n-  支持命令行方式的模型推理，可使用 `paddlespeech vector --task spk --input xxx.wav` 方式调用预训练模型进行推理。\n-  支持 VPR 的服务容器化部署，界面化操作。\n\n\n<a name=\"3\"></a>\n## 3. 使用教程\n\n<a name=\"31\"></a>\n## 3.1 预训练模型\n支持的预训练模型列表：[released_model](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/released_model.md)。\n更多关于模型设计的部分，可以参考 AIStudio 教程：\n- [ecapa-tdnn](https://aistudio.baidu.com/aistudio/projectdetail/4027664)\n\n<a name=\"32\"></a>\n## 3.2 模型训练\n\n模型的训练的参考脚本存放在 [examples](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples) 中，并按照 `examples/数据集/模型` 存放，数据集主要支持 VoxCeleb，模型支持 ecapa-tdnn 模型。\n具体的执行脚本的步骤记录在 `run.sh` 当中。具体可参考： [sv0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/voxceleb/sv0)\n\n\n<a name=\"33\"></a>\n## 3.3 模型推理\n\nPP-VPR 支持在使用`pip install paddlespeech`后 使用命令行的方式来使用预训练模型进行推理。\n\n具体支持的功能包括：\n\n- 对单条音频进行预测\n- 对两条音频进行打分\n- 支持 RTF 的计算\n\n具体的使用方式可以参考： [speaker_verification](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/speaker_verification/README_cn.md) \n\n\n<a name=\"34\"></a>\n## 3.4 服务部署\n\nPP-VPR 支持 Docker 容器化服务部署。通过 Milvus, MySQL 进行高性能建库检索。\n\nserver 的 demo： [audio_searching](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/audio_searching)\n\n![arch](https://ai-studio-static-online.cdn.bcebos.com/7b32dd0200084866863095677e8b40d3b725b867d2e6439e9cf21514e235dfd5)\n\n\n关于服务部署方面的更多资料，可以参考 AIStudio 教程：\n- [speaker_recognition](https://aistudio.baidu.com/aistudio/projectdetail/4027664)\n\n<a name=\"4\"></a>\n\n## 4. 快速开始\n\n关于如何使用 PP-VPR，可以看这里的 [install](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md)，其中提供了 **简单**、**中等**、**困难** 三种安装方式。如果想体验 paddlespeech 的推理功能，可以用 **简单** 安装方式。\n"
  },
  {
    "path": "docs/topic/ctc/ctc_loss.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"piano-accent\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Derivative of CTC Loss\\n\",\n    \"\\n\",\n    \"关于CTC的介绍已经有很多不错的教程了，但是完整的描述CTCLoss的前向和反向过程的很少，而且有些公式推导省略和错误。本文主要关注CTC Loss的梯度是如何计算的，关于CTC的介绍这里不做过多赘述，具体参看文末参考。\\n\",\n    \"\\n\",\n    \"CTC主要应用于语音和OCR中，已语音[Deepspeech2](https://arxiv.org/abs/1512.02595)模型为例，CTC的网络一般如下图所示，包含softmax和CTCLoss两部分。反向传播需要求得loss L相对于logits $u^i$​的梯度。下面先介绍CTCLoss的前向计算。\\n\",\n    \"\\n\",\n    \"> 图片来源于文末参考\\n\",\n    \"\\n\",\n    \"![img](./img/ctc_loss_backward_1.png)\\n\",\n    \"\\n\",\n    \"## CTC Loss 的计算\\n\",\n    \"\\n\",\n    \"CTC中path的定义与概率的计算如下：\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_prob_pi_x.png\\\" alt=\\\"image-20211104200811966\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"path 是 $ L'^T$​​的元素，用 $ \\\\pi $​​表示。 $ \\\\textbf{x} $​​ 是输入特征，$\\\\textbf{y}$​​ 是输出label， 都是序列。 $ L $​​ 是输出的 vocab, L‘ 是 $ L \\\\cup {blank}$​​。 $y_{\\\\pi_{t}}^t$​​ 表示在t时刻，$\\\\pi_{t}$​​ label时的观察概率。其中$\\\\pi_{t}$​​ 表示 $\\\\pi$​​ path在t时刻的label。$\\\\pi$​​ 是 $\\\\textbf{y}$​​ 与 $ \\\\textbf{x}$​​ 的一个alignment，长度是$T$​​，取值空间为$L'$​​​。path也称为alignment。\\n\",\n    \"\\n\",\n    \"公式（2）解释了给定输入 $\\\\textbf{x}$​ ，输出 $ \\\\pi $​  path 的概率，即从时间t=1到T每个时间点的概率 $y_{\\\\pi_{t}}^t$​ 相乘。\\n\",\n    \"\\n\",\n    \"求出单条path后，就可以计算$p(l \\\\mid x)$​ 的概率，计算如下：\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_prob_l_x.png\\\" alt=\\\"image-20211104202358513\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"这里边 $\\\\mathcal{B}$ 就是映射， 即所有多对一的映射（many-to-one mapping )的集合。 这样就算出来对应一个真正的 label $\\\\textbf{l}$ 的概率了，这里是求和。 求和的原因就是 aab 和 abb 都是对应成ab, 所以 aab 的概率 + abb 的概率才是生成ab的概率。 \\n\",\n    \"\\n\",\n    \"公式（3）解释了给定输入 $\\\\mathbf{x}$​​​​​​ ，求输出$\\\\mathbf{l}$​​​​​​ 的概率， 即所有集合 $\\\\mathcal{B}^{-1} (\\\\mathbf{l})$​​​​​​​​​​ 中 path的概率和。\\n\",\n    \"\\n\",\n    \"### CTC forward-backward 算法\\n\",\n    \"\\n\",\n    \"CTC的优化采用算最大似然估计[MLE (maximum likelihood estimation)](https://en.wikipedia.org/wiki/Maximum_likelihood_estimation), 这个和神经网络本身的训练过程是一致的。\\n\",\n    \"\\n\",\n    \"这个CTC 计算过程类似HMM的 [forward-backward algorithm](https://en.wikipedia.org/wiki/Forward%E2%80%93backward_algorithm)，下面就是这个算法的推导过程：\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_alpha_definition.png\\\" alt=\\\"image-20211104203040307\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"上图中的定义很清楚， 但是$ \\\\alpha_{t-1}(s) $ and $ \\\\alpha_{t-1}(s-1)$ 和 $\\\\alpha_t(s)$ 的关系也不那么好看出来，下图给出了具体的关于 $\\\\alpha_t(s)$ 的推导过程：\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_alpha_recurse.png\\\" alt=\\\"image-20211108155714843\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_alpha_recurse_2.png\\\" alt=\\\"image-20211109153011816\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"这里的公式比较适合用下面的图来理解，$\\\\alpha_1(1)$​​​​ 其实对应的就是下图中左上角白色的圆圈。 就是上来第一个是blank 的概率， 而 $\\\\alpha_1(2)$​​​​是label l 的第一个字母。 这里边我们假设每个字母之间都插入了空白，即label l扩展成l'，例如，l=[a, b, b, c]， l'=[-, a, -, b, -, b, -, c, -]。  然后对于其他圆点，在时间是1 的情况下概率都是 0. Figure 3中横轴是时间 t，从左到右是1到T；纵轴是s（sequence），从上到下是 1 到 $\\\\mathbf{\\\\mid l' \\\\mid}$​​​​.\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_cat_lattice.png\\\" alt=\\\"image-20211108155918442\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"接下来我们分析递归公式 (resursion)，更多介绍可以参看 [2]. 公式6分情况考虑:\\n\",\n    \"\\n\",\n    \"* 第一种情况就是当前的label是blank， 或者 $\\\\mathbf{l'}_{s}= \\\\mathbf{l'}_{s-2}$​​​​​​​(相邻是重复字符)：\\n\",\n    \"\\n\",\n    \"  ![img](https://distill.pub/2017/ctc/assets/cost_no_skip.svg)\\n\",\n    \"\\n\",\n    \"  这个时候他的概率来自于过去t-1的两个label 概率， 也就是 $a_{t-1} (s)$​​ 和 $a_{t-1} (s-1)$​​​ 。\\n\",\n    \"\\n\",\n    \"  $ a_{t-1} (s)$​​ 就是说当前的 sequence 已经是s 了，figure 3中表现为横跳， blank -->blank（例如t=3, s=3）；\\n\",\n    \"\\n\",\n    \"  而 $a_{t-1} (s-1) $是说明当前的字符还不够， 需要再加一个， 所以在figure 3中就是斜跳，从黑色圆圈到白色圆圈（例如，t=3, s=5）。\\n\",\n    \"\\n\",\n    \"  仔细观察figure 3， 除了第一排的白色圆圈， 其他白色圆圈都有两个输入， 就是上述的两种情况。  当然判断blank 的方法也可以是判断$I'_{s-2} = I'_{s}$​. 这种情况也是说明$I'_{s}$​​​ 是blank, 因为每一个字符必须用 blank 隔开， 即使是相同字符。\\n\",\n    \"\\n\",\n    \"* 第二章情况 也可以用类似逻辑得出， 只不过当前的状态s 是黑色圆圈， 有三种情况输入。\\n\",\n    \"\\n\",\n    \"  ![img](https://distill.pub/2017/ctc/assets/cost_regular.svg)\\n\",\n    \"\\n\",\n    \"最终的概率就如公式8 所示， 这个计算过程就是 CTC forward algroirthm， 基于 Fig. 3 的左边的初始条件。\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_forward_loss.png\\\" alt=\\\"image-20211108162544982\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"基于Fig. 3 右边的初始条件，我们还是可以计算出一个概率， 那个就是 **CTC backward**. 这里我就不详细介绍了， 直接截图。\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_backward_recurse.png\\\" alt=\\\"image-20211108162859876\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"这样一直做乘法， 数字值越来越小，很快就会underflow。 这个时候就需要做 scaling.\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_rescale_loss.png\\\" alt=\\\"image-20211108163526616\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"算出了forward probability 和 backward probability 有什么用呢， 解释如下图。\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_forward_backward.png\\\" alt=\\\"image-20211108164110404\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"上图是说 forward probability and backward probability 的乘积， 代表了这个 sequence $\\\\mathbf{l}$ t时刻，是s label 的 所有paths 的概率。 这样的话 我们就计算了 Fig. 3 中的每个圆圈的概率。为什么$\\\\alpha_t(s)\\\\beta_t(s)$ 中多出一个 $y^t_{\\\\mathbf{l'_s}}$ ，这是因为它在 $\\\\alpha$  和 $\\\\beta$ 中都包含该项，合并公式后就多出一项。\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_forward_backward_to_loss.png\\\" alt=\\\"image-20211109143104052\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"$p(\\\\mathbf{l}|\\\\mathbf{x})$​  可以通过任意时刻 t 的所有 s 的 foward-backward 概率计算得来。取负对数后就是单个样本的NLL（Negative Log Likelihood）。\\n\",\n    \"\\n\",\n    \"### 总结\\n\",\n    \"\\n\",\n    \"总结一下，根据前向概率计算CTCLoss函数，可以得出如下结论：\\n\",\n    \"\\n\",\n    \"1. 对于时序长度为T的输入序列x和输出序列z，前向概率：\\n\",\n    \"   $$\\n\",\n    \"   \\\\begin{split}\\n\",\n    \"   \\\\alpha_t(s) &= \\\\sum_{ \\\\underset{\\\\pi_t=l'_s}{\\\\pi \\\\in \\\\mathcal{B}^{-1}(z)} } p(\\\\pi_{1:t}|x) \\\\newline\\n\",\n    \"   \\\\alpha_1(1) &= y_{-}^1 ; \\\\quad \\\\alpha_1(2)=y^1_{l'_2}, \\\\quad \\\\alpha_1(s)=0, \\\\forall s > 2  \\\\newline\\n\",\n    \"   \\\\alpha_t(s) &= 0, \\\\quad \\\\forall s < |l'| - 2(T-t) - 1 ,\\\\quad \\\\text{or} \\\\quad \\\\forall s < 1 \\\\newline\\n\",\n    \"   \\\\alpha_t(s) &=\\n\",\n    \"    \\\\begin{cases}\\n\",\n    \"      (\\\\alpha_{t-1}(s) + \\\\alpha_{t-1}(s-1) ) y^t_{l'_s} & \\\\text{if $l'_s=b$ or $l'_{s-2} = l'_s$​}  \\\\newline\\n\",\n    \"      (\\\\alpha_{t-1}(s) + \\\\alpha_{t-1}(s-1) + \\\\alpha_{t-1}(s-2))y^t_{l'_s} & \\\\text{otherwise}\\\\newline\\n\",\n    \"    \\\\end{cases} \\n\",\n    \"   \\\\end{split}\\n\",\n    \"   $$\\n\",\n    \"\\n\",\n    \"2. 利用 $\\\\alpha_t(s)$ 计算CTCLoss：\\n\",\n    \"   $$\\n\",\n    \"   -ln(p(l \\\\mid x)) = -ln(\\\\alpha_{T}(|l'|)+\\\\alpha_{T}(|l'|-1))\\n\",\n    \"   $$\\n\",\n    \"\\n\",\n    \"根据后向概率计算CTCLoss函数，可以得出如下结论：\\n\",\n    \"\\n\",\n    \"1. 对于时序长度为T的输入序列x和输出序列z，后向概率：  \\n\",\n    \"   $$\\n\",\n    \"   \\\\begin{split}\\n\",\n    \"   \\\\beta_t(s) &= \\\\sum_{ \\\\underset{\\\\pi_t=l'_s}{\\\\pi \\\\in \\\\mathcal{B}^{-1}(z)} } p(\\\\pi_{t:T}|x) \\\\newline\\n\",\n    \"   \\\\beta_T(|l'|) &= y_{-}^T ; \\\\quad \\\\beta_T(|l'|-1)=y^T_{l'_{|l'|-1}}, \\\\quad \\\\beta_T(s)=0, \\\\forall s < |l'| - 1  \\\\newline\\n\",\n    \"   \\\\beta_t(s) &= 0, \\\\text{$\\\\forall s > 2t$ or $\\\\forall s < |l'|$} \\\\newline\\n\",\n    \"   \\\\beta_t(s) &=\\n\",\n    \"        \\\\begin{cases}\\n\",\n    \"          (\\\\beta_{t+1}(s) + \\\\beta_{t+1}(s+1) ) y^t_{l'_s} & \\\\text{if $l'_s=b$ or $l'_{s+2} = l'_s$}  \\\\newline\\n\",\n    \"          (\\\\beta_{t+1}(s) + \\\\beta_{t+1}(s+1) + \\\\beta_{t+1}(s+2))y^t_{l'_s} & \\\\text{otherwise}\\\\newline\\n\",\n    \"        \\\\end{cases}\\n\",\n    \"   \\\\end{split}\\n\",\n    \"   $$\\n\",\n    \"\\n\",\n    \" 2. 利用 $\\\\beta_t(s)$计算CTCLoss：\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"-ln(p(l \\\\mid x)) = -ln(\\\\beta_{1}(1)+\\\\beta_{1}(2)) \\\\newline\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"根据任意时刻的前向概率和后向概率计算CTC Loss函数，得到如下结论：\\n\",\n    \"\\n\",\n    \"1. 对于任意时刻t，利用前向概率和后向概率计算CTCLoss：\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"p(l \\\\mid x) = \\\\sum_{s=1}^{|l'|} \\\\frac{\\\\alpha_t(s)\\\\beta_t(s)}{y_{l'_s}^t}  \\\\newline\\n\",\n    \"-ln(p(l \\\\mid x)) = -ln( \\\\sum_{s=1}^{|l'|} \\\\frac{\\\\alpha_t(s) \\\\beta_t(s)}{y_{l'_s}^t} )\\n\",\n    \"$$\\n\",\n    \"我们已经得到CTCLoss的计算方法，接下来对其进行求导。\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"viral-fitting\",\n   \"metadata\": {},\n   \"source\": [\n    \"## CTC梯度计算\\n\",\n    \"\\n\",\n    \"### 微分公式\\n\",\n    \"\\n\",\n    \"在计算梯度前，我们先回顾下基本的微分公式： \\n\",\n    \"$$\\n\",\n    \"C' = 0 \\\\\\\\\\n\",\n    \"x'  = 1 \\\\newline\\n\",\n    \"x^n  =  n \\\\cdot x^{n-1} \\\\newline\\n\",\n    \"(e^x)' =  e^x \\\\newline\\n\",\n    \"log(x)' =  \\\\frac{1}{x} \\\\newline\\n\",\n    \"(u + v)' = u' + v' \\\\newline\\n\",\n    \"(\\\\frac{u}{v})' =  \\\\frac{u'v-uv'}{v^2} \\\\newline\\n\",\n    \"\\\\frac{\\\\mathrm{d}f(g(x))}{\\\\mathrm{d}x} = \\\\frac{\\\\mathrm{d}f(g(x))}{\\\\mathrm{d}g(x)} \\\\cdot \\\\frac{\\\\mathrm{d}g(x)}{\\\\mathrm{d}x}\\n\",\n    \"$$\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"starting-sender\",\n   \"metadata\": {},\n   \"source\": [\n    \"### CTC梯度\\n\",\n    \"\\n\",\n    \"最大似然估计训练就是最大化训练集中每一个分类的对数概率，即最小化Eq. 12。\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_gradient_of_y_hat.png\\\" alt=\\\"image-20211108164206136\\\" style=\\\"zoom:50%;\\\" />\\n\",\n    \"\\n\",\n    \"最后就是算微分了， 整个推导过程就是加法和乘法， 都可以微分。 $\\\\mathit{O}^{ML}$关于神经网络的输出 $y^t_k$的梯度见Eq. 13。因为训练样本是相互独立的，所以可以单独考虑每个样本，公式如Eq.13。\\n\",\n    \"\\n\",\n    \"下面是CTCLoss的梯度计算：\\n\",\n    \"\\n\",\n    \"<img src=\\\"./img/ctc_loss_gradient_with_y.png\\\" alt=\\\"image-20211109143622448\\\" style=\\\"zoom:50%;\\\" />\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"stretch-order\",\n   \"metadata\": {},\n   \"source\": [\n    \"### CTC梯度推导\\n\",\n    \"\\n\",\n    \"回顾下之前的公式，便于理解后续推导过程。  \\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"p(l \\\\mid x) = \\\\sum_{s=1}^{|l'|} \\\\frac{\\\\alpha_t(s)\\\\beta_t(s)}{y_{l'_s}^t}  \\\\\\\\\\n\",\n    \"\\\\begin{equation}\\n\",\n    \"\\\\alpha_t(s) \\\\beta_t(s) = \\\\sum_{ \\\\underset{\\\\pi_t=l'_s}{\\\\pi \\\\in \\\\mathcal{B}^{-1}(l):} }  y^t_{l'_s}  \\\\prod_{t=1}^T y^t_{\\\\pi_t}\\n\",\n    \"\\\\end{equation}\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"其中Eq. 15的计算过程如下：  \\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\begin{align*}\\n\",\n    \"\\\\frac{\\\\partial p(\\n\",\n    \"l \\\\mid x)}{\\\\partial y_k^t}\\n\",\n    \"    & = \\\\sum_{s \\\\in lab(z,k)} \\\\frac{ \\\\partial \\\\frac{ \\\\alpha_t(s) \\\\beta_t(s)}{y_{k}^t}}{\\\\partial y_k^t}  \\n\",\n    \"    \\\\newline\\n\",\n    \"    & = \\\\sum_{s \\\\in lab(z,k)} \\\\frac{(\\\\alpha_t(s)\\\\beta_t(s))’y_k^t - \\\\alpha_t(s)\\\\beta_t(s){y_k^t}'}{{y_k^t}^2}\\n\",\n    \"    \\\\newline\\n\",\n    \"    &= \\\\sum_{s \\\\in lab(z,k)} \\\\frac{(  \\\\prod_{t'=1}^{t-1} y^{t'}_{\\\\pi_{t'}} \\\\cdot y_k^t \\\\cdot y_k^t \\\\cdot   \\\\prod_{t'=t+1}^{T} y^{t'}_{\\\\pi_{t'}}   )’ y_k^t - \\\\alpha_t(s)\\\\beta_t(s){y_k^t}'}{{y_k^t}^2}\\n\",\n    \"    \\\\newline\\n\",\n    \"     &= \\\\sum_{s \\\\in lab(z,k)} \\\\frac{2\\\\alpha_t(s)\\\\beta_t(s) - \\\\alpha_t(s)\\\\beta_t(s)}{{y_k^t}^2}\\n\",\n    \"    \\\\newline\\n\",\n    \"      &= \\\\sum_{s \\\\in lab(z,k)} \\\\frac{\\\\alpha_t(s)\\\\beta_t(s)}{{y_k^t}^2}\\n\",\n    \"      \\\\newline\\n\",\n    \"      &= \\\\frac{1}{{y_k^t}^2}  \\\\sum_{s \\\\in lab(z,k)} \\\\alpha_t(s)\\\\beta_t(s)  \\\\tag{1} \\\\newline\\n\",\n    \"\\\\end{align*}\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"NLL的公式推导如下：\\n\",\n    \"$$\\n\",\n    \"\\\\begin{split}\\n\",\n    \"\\\\frac{\\\\partial {ln(p(l \\\\mid x))} }{ \\\\partial y^t_k }\\n\",\n    \"  &= \\\\frac{1}{p(l \\\\mid x)} \\\\frac{ \\\\partial{p(l \\\\mid x)} }{ \\\\partial y_k^t } \\\\newline\\n\",\n    \"  &= \\\\frac{1}{p(l \\\\mid x) {y^t_k}^2 } \\\\sum_{s \\\\in lab(z,k)} \\\\alpha_t(s)\\\\beta_t(s) \\n\",\n    \"\\\\end{split}\\n\",\n    \"\\\\tag{2}\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"已经算出了CTCLoss对于 $y_k^t$​ 的梯度，接下来我们需要计算 CTCLoss对于$u^t_k$​（logits）的梯度。套用链式法则，并替换$y^t_k$​ 为 $y^t_{k'}$​，结果如下图。图中 $k'$​ 表示vocab中的某一个token，$K$​​ 是vocab的大小。\\n\",\n    \"\\n\",\n    \"![](./img/ctc_loss_backward_2.png)\\n\",\n    \"\\n\",\n    \"图中公式4根据链式法则得到：\\n\",\n    \"$$\\n\",\n    \"- \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial u^t_k }\\n\",\n    \"  = - \\\\sum_{k'=1}^{K} \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial y^t_{k'} } \\\\frac{ \\\\partial y^t_{k'} }{ \\\\partial u^t_k }  \\\\tag{4}\\n\",\n    \"$$\\n\",\n    \"图中公式3是softmax的梯度，参考 [4]，计算过程如下：\\n\",\n    \"$$\\n\",\n    \"softmax(j) = S_j  = \\\\frac{ e^{a_j} }{ \\\\sum_{k=1}^K e^{a_k} }, \\\\enspace \\\\forall j \\\\in 1 \\\\dots K\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"$$\\n\",\n    \"\\\\begin{split}\\n\",\n    \"\\\\frac{ \\\\partial S_i }{ \\\\partial a_j}\\n\",\n    \"  &= \\\\frac{ \\\\partial (\\\\frac{ e^{ a_i } }{ \\\\sum_k e^{ a_k } }) } { \\\\partial a_j }\\n\",\n    \"  \\\\newline\\n\",\n    \"  &= \\n\",\n    \"  \\\\begin{cases}\\n\",\n    \"  \\t\\\\frac{ e^a_i \\\\sum - e^a_j e^a_i }{ \\\\sum^2 } \\n\",\n    \"  \\t&= \\\\frac{ e^a_i }{ \\\\sum } \\\\frac{ \\\\sum - e^a_j }{ \\\\sum } \\\\newline\\n\",\n    \"    &= S_i(1-S_j)   & \\\\text{i = j, $\\\\sum$ stands for $\\\\sum_{k=1}^K e^a_k$} \\n\",\n    \"  \\t\\\\newline\\n\",\n    \"  \\t\\\\frac{ 0 - e^a_j e^a_i }{ \\\\sum^2 }  \\n\",\n    \"  \\t&= - \\\\frac{ e^a_j }{ \\\\sum } \\\\frac{ e^a_i }{ \\\\sum }  \\\\newline\\n\",\n    \"    &= -S_j S_i  & \\\\text{i $\\\\neq$ j, $\\\\sum$ stands for $\\\\sum_{k=1}^K e^a_k$}\\n\",\n    \"  \\\\end{cases}\\n\",\n    \"  \\\\newline\\n\",\n    \"  &= \\n\",\n    \"  \\\\begin{cases}\\n\",\n    \"  S_i(1 - S_j) & \\\\text{$i = j$} \\n\",\n    \"  \\\\newline\\n\",\n    \"  -S_j S_i = S_i (0 - S_j) & \\\\text{$i \\\\neq j$}\\n\",\n    \"  \\\\end{cases}\\n\",\n    \"  \\\\newline\\n\",\n    \"  &= S_i (\\\\delta_{ij} - S_j )\\n\",\n    \"\\\\end{split}\\n\",\n    \"\\\\tag{3}\\n\",\n    \"$$\\n\",\n    \"$$\\n\",\n    \"\\\\delta_{ij} =\\n\",\n    \" \\\\begin{cases}\\n\",\n    \" 1 & \\\\text{if i = j} \\\\newline\\n\",\n    \" 0 & \\\\text{otherwise}\\n\",\n    \" \\\\end{cases}\\n\",\n    \"$$\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"下图中黄色框中的部分表示公式（1），即遍历所有的vocab中的token，其结果是$p(l \\\\mid x)$​。这是因为label $l$​ 中的token一定在vocab中，且 $s \\\\in lab(l, k')$​ 可以是空集。当 $k'$​ 在 l 中，s 则为label中token是$k'$​的概率；当$k'$​​​不在l中，s为空，概率为0。\\n\",\n    \"\\n\",\n    \"![img](./img/ctc_loss_backward_3.png)\\n\",\n    \"\\n\",\n    \"公式（2），（3）带入（4），并结合公式（1）的结果如上图右边，即：\\n\",\n    \"$$\\n\",\n    \"\\\\begin{split}\\n\",\n    \"- \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial u^t_k } &= \\n\",\n    \"\\t- \\\\sum_{k'=1}^K \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial y^t_{k'} }  \\\\frac{ \\\\partial y^t_{k'}}{ \\\\partial u^t_k } \\\\newline\\n\",\n    \"\\t&= - \\\\sum_{k'=1}^K \\\\frac{  y^t_{k'}( \\\\delta_{kk'} -  y^t_k )  }{ p(l \\\\mid x) {y^t_{k'}}^2 } \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) \\\\newline\\n\",\n    \"\\t&= - \\\\sum_{k'=1}^K \\\\frac{  \\\\delta_{kk'} -  y^t_k  }{ p(l \\\\mid x) y^t_{k'} } \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) \\\\newline\\n\",\n    \"\\t&=  \\\\sum_{k'=1}^K \\\\frac{ y^t_k  - \\\\delta_{kk'} }{ p(l \\\\mid x) y^t_{k'} } \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s)   \\\\newline\\n\",\n    \"\\t&= \\\\sum_{k'=1}^K \\\\frac{ y^t }{ p(l \\\\mid x) y^t_{k'} }  \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) - \\\\sum_{k'=1}^K \\\\frac{ \\\\delta_{kk'} }{ p(l \\\\mid x) y^t_{k'} }  \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) \\\\newline\\n\",\n    \"\\t&=  \\\\frac{ y^t_k }{ p(l \\\\mid x) } ( \\\\sum_{k'=1}^K \\\\frac{1}{y^t_{k'}} \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) ) - \\\\sum_{k'=1}^K \\\\frac{ \\\\delta_{kk'} }{ p(l \\\\mid x) y^t_{k'} }  \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) \\\\newline\\n\",\n    \"\\t&=  \\\\frac{ y^t_k }{ p(l \\\\mid x) } p(l \\\\mid x)   - \\\\sum_{k'=1}^K \\\\frac{ \\\\delta_{kk'} }{ p(l \\\\mid x) y^t_{k'} }  \\\\sum_{s \\\\in lab(l, k') } \\\\alpha_t(s) \\\\beta_t(s) \\\\newline\\n\",\n    \"\\t&= y^t_k - \\\\frac{ 1 }{ p(l \\\\mid x) y^t_k } \\\\sum_{s \\\\in lab(l, k)} \\\\alpha_t(s) \\\\beta_t(s)  \\\\newline\\n\",\n    \"\\\\end{split}\\n\",\n    \"$$\\n\",\n    \"最终，为了通过softmax层传播CTCLoss的梯度，需要计算目标函数与 logits $u^t_k$ 的偏微分，即Eq. 16: \\n\",\n    \"    $$\\n\",\n    \"    \\\\begin{align*}\\n\",\n    \"    \\\\hat{\\\\alpha}_t(s) & \\\\overset{def}{=} \\\\frac{ \\\\alpha_t(s) }{ C_t } ,\\\\enspace C_t \\\\overset{def}{=} \\\\sum_s \\\\alpha_t(s) \\n\",\n    \"    \\\\newline\\n\",\n    \"    \\\\hat{\\\\beta}_t(s) & \\\\overset{def}{=} \\\\frac{ \\\\beta_t(s) }{ D_t } ,\\\\enspace D_t \\\\overset{def}{=} \\\\sum_s \\\\beta_t(s) \\n\",\n    \"    \\\\newline\\n\",\n    \"    - \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial u^t_k } &= y^t_k - \\\\frac{1}{y^t_k \\\\sum_{s=1}^{\\\\mid l' \\\\mid} \\\\frac{ \\\\hat{\\\\alpha}_t(s) \\\\hat{\\\\beta}_t(s) }{ y^t_{l'_s} } } \\\\sum_{s \\\\in lab(l, k)} \\\\hat{\\\\alpha}_t(s) \\\\hat{\\\\beta}_t(s) \\\\tag{16} \\n\",\n    \"    \\\\newline\\n\",\n    \"    \\\\end{align*}\\n\",\n    \"    $$\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"informative-maria\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 总结\\n\",\n    \"\\n\",\n    \"* 通过动态规划算法计算$\\\\alpha_t(s)$ 和 $\\\\beta_t(s)$\\n\",\n    \"\\n\",\n    \"* 通过$\\\\alpha_t(s)$ 计算 $p(l \\\\mid x)=\\\\alpha_T(\\\\mid l' \\\\mid) + \\\\alpha_T(\\\\mid l' \\\\mid -1)$\\n\",\n    \"\\n\",\n    \"* 通过$\\\\alpha_t(s)$ 和 $\\\\beta_t(s)$\\n\",\n    \"\\n\",\n    \"* 计算CTcLoss函数的导数:  \\n\",\n    \"    $$\\n\",\n    \"    \\\\begin{split}\\n\",\n    \"    - \\\\frac{ \\\\partial ln(p(l \\\\mid x)) }{ \\\\partial u^t_k } \\n\",\n    \"    &= y^t_k - \\\\frac{ 1 }{ p(l \\\\mid x) y^t_k } \\\\sum_{s \\\\in lab(l, k)} \\\\alpha_t(s) \\\\beta_t(s)  \\n\",\n    \"    \\\\newline\\n\",\n    \"    &= y^t_k - \\\\frac{1}{y^t_k \\\\sum_{s=1}^{\\\\mid l' \\\\mid} \\\\frac{ \\\\hat{\\\\alpha}_t(s) \\\\hat{\\\\beta}_t(s) }{ y^t_{l'_s} } } \\\\sum_{s \\\\in lab(l, k)} \\\\hat{\\\\alpha}_t(s) \\\\hat{\\\\beta}_t(s) \\n\",\n    \"    \\\\newline\\n\",\n    \"    \\\\end{split}\\n\",\n    \"    \\\\tag{16}\\n\",\n    \"    $$\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"41637c03\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Source Code\\n\",\n    \"本人在 [warp-ctc](https://github.com/zh794390558/warp-ctc) 上加了注释，并调整 index 的索引方式，便于理解代码。\\n\",\n    \"对比上面的公式推导和lattice图可以快速理解 ctc 实现。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"coordinated-music\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Reference\\n\",\n    \"\\n\",\n    \"[[1] A. Graves, S. Fernandez, F. Gomez, J. Schmidhuber. Connectionist Temporal lassification: Labeling Unsegmented Sequence Data  with Recurrent Neural Networks. ICML 2006, Pittsburgh, USA,  pp. 369-376.](http://www.cs.toronto.edu/~graves/icml_2006.pdf)\\n\",\n    \"\\n\",\n    \"[[2] Sequence ModelingWith CTC](https://distill.pub/2017/ctc/)\\n\",\n    \"\\n\",\n    \"[[3] NLP 之 CTC Loss 的工作原理](https://www.jianshu.com/p/e073c9d91b20)\\n\",\n    \"\\n\",\n    \"[[4] The Softmax function and its derivative](https://eli.thegreenplace.net/2016/the-softmax-function-and-its-derivative/)\\n\",\n    \"\\n\",\n    \"[[5] CTC Algorithm Explained Part 1：Training the Network（CTC算法详解之训练篇）](https://xiaodu.io/ctc-explained/)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"id\": \"closing-candy\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.0\"\n  },\n  \"toc\": {\n   \"base_numbering\": 1,\n   \"nav_menu\": {},\n   \"number_sections\": true,\n   \"sideBar\": true,\n   \"skip_h1_title\": false,\n   \"title_cell\": \"Table of Contents\",\n   \"title_sidebar\": \"Contents\",\n   \"toc_cell\": false,\n   \"toc_position\": {},\n   \"toc_section_display\": true,\n   \"toc_window_display\": false\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 5\n}\n"
  },
  {
    "path": "docs/topic/ctc/ctc_loss_compare.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"ff6ff1e0\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%load_ext autoreload\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"id\": \"33af5f76\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%autoreload 2\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"id\": \"9b566b73\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"fatal: destination path 'warp-ctc' already exists and is not an empty directory.\\r\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!git clone https://github.com/SeanNaren/warp-ctc.git\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"id\": \"4a087a09\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"%cd warp-ctc\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"id\": \"f55dc29a\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mkdir -p build\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"id\": \"fe79f4cf\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/build\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"cd build\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"id\": \"3d25c718\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"-- cuda found TRUE\\n\",\n      \"-- Building shared library with GPU support\\n\",\n      \"-- Configuring done\\n\",\n      \"-- Generating done\\n\",\n      \"-- Build files have been written to: /workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/build\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!cmake ..\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"id\": \"7a4238f1\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"[ 11%] \\u001b[32m\\u001b[1mLinking CXX shared library libwarpctc.so\\u001b[0m\\n\",\n      \"[ 33%] Built target warpctc\\n\",\n      \"[ 44%] \\u001b[32m\\u001b[1mLinking CXX executable test_cpu\\u001b[0m\\n\",\n      \"[ 55%] \\u001b[32m\\u001b[1mLinking CXX executable test_gpu\\u001b[0m\\n\",\n      \"[ 77%] Built target test_cpu\\n\",\n      \"[100%] Built target test_gpu\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!make -j\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"id\": \"31761a31\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"cd ..\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"id\": \"f53316f6\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/pytorch_binding\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"cd pytorch_binding\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"id\": \"084f1e49\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"running install\\n\",\n      \"running bdist_egg\\n\",\n      \"running egg_info\\n\",\n      \"writing warpctc_pytorch.egg-info/PKG-INFO\\n\",\n      \"writing dependency_links to warpctc_pytorch.egg-info/dependency_links.txt\\n\",\n      \"writing top-level names to warpctc_pytorch.egg-info/top_level.txt\\n\",\n      \"writing manifest file 'warpctc_pytorch.egg-info/SOURCES.txt'\\n\",\n      \"installing library code to build/bdist.linux-x86_64/egg\\n\",\n      \"running install_lib\\n\",\n      \"running build_py\\n\",\n      \"running build_ext\\n\",\n      \"building 'warpctc_pytorch._warp_ctc' extension\\n\",\n      \"Emitting ninja build file /workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/pytorch_binding/build/temp.linux-x86_64-3.9/build.ninja...\\n\",\n      \"Compiling objects...\\n\",\n      \"Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)\\n\",\n      \"ninja: no work to do.\\n\",\n      \"g++ -pthread -B /workspace/zhanghui/DeepSpeech-2.x/tools/venv/compiler_compat -Wl,--sysroot=/ -shared -Wl,-rpath,/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib -Wl,-rpath-link,/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib -L/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib -Wl,-rpath,/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib -Wl,-rpath-link,/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib -L/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib /workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/pytorch_binding/build/temp.linux-x86_64-3.9/src/binding.o -L/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/build -L/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib/python3.9/site-packages/torch/lib -L/usr/local/cuda/lib64 -lwarpctc -lc10 -ltorch -ltorch_cpu -ltorch_python -lcudart -lc10_cuda -ltorch_cuda -o build/lib.linux-x86_64-3.9/warpctc_pytorch/_warp_ctc.cpython-39-x86_64-linux-gnu.so -Wl,-rpath,/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc/build\\n\",\n      \"creating build/bdist.linux-x86_64/egg\\n\",\n      \"creating build/bdist.linux-x86_64/egg/warpctc_pytorch\\n\",\n      \"copying build/lib.linux-x86_64-3.9/warpctc_pytorch/__init__.py -> build/bdist.linux-x86_64/egg/warpctc_pytorch\\n\",\n      \"copying build/lib.linux-x86_64-3.9/warpctc_pytorch/_warp_ctc.cpython-39-x86_64-linux-gnu.so -> build/bdist.linux-x86_64/egg/warpctc_pytorch\\n\",\n      \"byte-compiling build/bdist.linux-x86_64/egg/warpctc_pytorch/__init__.py to __init__.cpython-39.pyc\\n\",\n      \"creating stub loader for warpctc_pytorch/_warp_ctc.cpython-39-x86_64-linux-gnu.so\\n\",\n      \"byte-compiling build/bdist.linux-x86_64/egg/warpctc_pytorch/_warp_ctc.py to _warp_ctc.cpython-39.pyc\\n\",\n      \"creating build/bdist.linux-x86_64/egg/EGG-INFO\\n\",\n      \"copying warpctc_pytorch.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO\\n\",\n      \"copying warpctc_pytorch.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO\\n\",\n      \"copying warpctc_pytorch.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO\\n\",\n      \"copying warpctc_pytorch.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO\\n\",\n      \"writing build/bdist.linux-x86_64/egg/EGG-INFO/native_libs.txt\\n\",\n      \"zip_safe flag not set; analyzing archive contents...\\n\",\n      \"warpctc_pytorch.__pycache__._warp_ctc.cpython-39: module references __file__\\n\",\n      \"creating 'dist/warpctc_pytorch-0.1-py3.9-linux-x86_64.egg' and adding 'build/bdist.linux-x86_64/egg' to it\\n\",\n      \"removing 'build/bdist.linux-x86_64/egg' (and everything under it)\\n\",\n      \"Processing warpctc_pytorch-0.1-py3.9-linux-x86_64.egg\\n\",\n      \"removing '/workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib/python3.9/site-packages/warpctc_pytorch-0.1-py3.9-linux-x86_64.egg' (and everything under it)\\n\",\n      \"creating /workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib/python3.9/site-packages/warpctc_pytorch-0.1-py3.9-linux-x86_64.egg\\n\",\n      \"Extracting warpctc_pytorch-0.1-py3.9-linux-x86_64.egg to /workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib/python3.9/site-packages\\n\",\n      \"warpctc-pytorch 0.1 is already the active version in easy-install.pth\\n\",\n      \"\\n\",\n      \"Installed /workspace/zhanghui/DeepSpeech-2.x/tools/venv/lib/python3.9/site-packages/warpctc_pytorch-0.1-py3.9-linux-x86_64.egg\\n\",\n      \"Processing dependencies for warpctc-pytorch==0.1\\n\",\n      \"Finished processing dependencies for warpctc-pytorch==0.1\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!python setup.py install\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"id\": \"ee4ca9e3\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Python 3.9.5\\r\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!python -V\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"id\": \"59255ed8\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/workspace/zhanghui/DeepSpeech-2.x/docs/topic/ctc/warp-ctc\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"cd ..\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"id\": \"1dae09b9\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import torch\\n\",\n    \"import torch.nn as nn\\n\",\n    \"import torch.nn.functional as F\\n\",\n    \"import warpctc_pytorch as wp\\n\",\n    \"import paddle.nn as pn\\n\",\n    \"import paddle\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"id\": \"83d0762e\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'1.10.0+cu102'\"\n      ]\n     },\n     \"execution_count\": 15,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"torch.__version__\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 16,\n   \"id\": \"62501e2c\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'2.2.1'\"\n      ]\n     },\n     \"execution_count\": 16,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"paddle.__version__\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 17,\n   \"id\": \"9e8e0f40\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"torch.Size([2, 1, 5])\\n\",\n      \"2.4628584384918213\\n\",\n      \"[[[ 0.17703122 -0.70812464  0.17703122  0.17703122  0.17703122]]\\n\",\n      \"\\n\",\n      \" [[ 0.17703122  0.17703122 -0.70812464  0.17703122  0.17703122]]]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# warpctc_pytorch CTCLoss\\n\",\n    \"probs = torch.FloatTensor([[\\n\",\n    \"        [0.1, 0.6, 0.1, 0.1, 0.1], [0.1, 0.1, 0.6, 0.1, 0.1]\\n\",\n    \"    ]]).transpose(0, 1).contiguous()\\n\",\n    \"print(probs.size())\\n\",\n    \"labels = torch.IntTensor([1, 2])\\n\",\n    \"label_sizes = torch.IntTensor([2])\\n\",\n    \"probs_sizes = torch.IntTensor([2])\\n\",\n    \"probs.requires_grad_(True)\\n\",\n    \"bs = probs.size(1)\\n\",\n    \"\\n\",\n    \"ctc_loss = wp.CTCLoss(size_average=False, length_average=False)\\n\",\n    \"cost = ctc_loss(probs, labels, probs_sizes, label_sizes)\\n\",\n    \"cost = cost.sum() / bs\\n\",\n    \"print(cost.item())\\n\",\n    \"cost.backward()\\n\",\n    \"print(probs.grad.numpy())\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"id\": \"2cd46569\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"2.4628584384918213\\n\",\n      \"[[[ 0.1770312 -0.7081248  0.1770312  0.1770312  0.1770312]]\\n\",\n      \"\\n\",\n      \" [[ 0.1770312  0.1770312 -0.7081248  0.1770312  0.1770312]]]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# pytorch CTCLoss\\n\",\n    \"probs = torch.FloatTensor([[\\n\",\n    \"        [0.1, 0.6, 0.1, 0.1, 0.1], [0.1, 0.1, 0.6, 0.1, 0.1]\\n\",\n    \"    ]]).transpose(0, 1).contiguous()\\n\",\n    \"labels = torch.IntTensor([1, 2])\\n\",\n    \"label_sizes = torch.IntTensor([2])\\n\",\n    \"probs_sizes = torch.IntTensor([2])\\n\",\n    \"probs.requires_grad_(True)\\n\",\n    \"bs = probs.size(1)\\n\",\n    \"\\n\",\n    \"log_probs = torch.log_softmax(probs, axis=-1)\\n\",\n    \"\\n\",\n    \"ctc_loss1 = nn.CTCLoss(reduction='none')\\n\",\n    \"cost = ctc_loss1(log_probs, labels, probs_sizes, label_sizes)\\n\",\n    \"cost = cost.sum() / bs\\n\",\n    \"print(cost.item())\\n\",\n    \"cost.backward()\\n\",\n    \"print(probs.grad.numpy())\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 27,\n   \"id\": \"85c3461a\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"[2, 1, 5]\\n\",\n      \"[1, 2]\\n\",\n      \"2.4628584384918213\\n\",\n      \"[[[ 0.17703122 -0.70812464  0.17703122  0.17703122  0.17703122]]\\n\",\n      \"\\n\",\n      \" [[ 0.17703122  0.17703122 -0.70812464  0.17703122  0.17703122]]]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# Paddle CTCLoss\\n\",\n    \"paddle.set_device('cpu')\\n\",\n    \"probs = paddle.to_tensor([[\\n\",\n    \"        [0.1, 0.6, 0.1, 0.1, 0.1], [0.1, 0.1, 0.6, 0.1, 0.1],\\n\",\n    \"    ]]).transpose([1,0,2])\\n\",\n    \"print(probs.shape) # (T, B, D)\\n\",\n    \"labels = paddle.to_tensor([[1, 2]], dtype='int32') #（B，L)\\n\",\n    \"print(labels.shape)\\n\",\n    \"label_sizes = paddle.to_tensor([2], dtype='int64')\\n\",\n    \"probs_sizes = paddle.to_tensor([2], dtype='int64')\\n\",\n    \"bs = paddle.shape(probs)[1]\\n\",\n    \"probs.stop_gradient=False\\n\",\n    \"\\n\",\n    \"ctc_loss = pn.CTCLoss(reduction='none')\\n\",\n    \"cost = ctc_loss(probs, labels, probs_sizes, label_sizes)\\n\",\n    \"cost = cost.sum() / bs\\n\",\n    \"print(cost.item())\\n\",\n    \"cost.backward()\\n\",\n    \"print(probs.grad.numpy())\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"id\": \"8cdf76c2\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"id\": \"2c305eaf\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"torch.Size([2, 1, 5])\\n\",\n      \"2.4628584384918213\\n\",\n      \"[[[ 0.17703117 -0.7081247   0.17703117  0.17703117  0.17703117]]\\n\",\n      \"\\n\",\n      \" [[ 0.17703117  0.17703117 -0.7081247   0.17703117  0.17703117]]]\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# warpctc_pytorch CTCLoss, log_softmax idempotent\\n\",\n    \"probs = torch.FloatTensor([[\\n\",\n    \"        [0.1, 0.6, 0.1, 0.1, 0.1], [0.1, 0.1, 0.6, 0.1, 0.1]\\n\",\n    \"    ]]).transpose(0, 1).contiguous()\\n\",\n    \"print(probs.size())\\n\",\n    \"labels = torch.IntTensor([1, 2])\\n\",\n    \"label_sizes = torch.IntTensor([2])\\n\",\n    \"probs_sizes = torch.IntTensor([2])\\n\",\n    \"probs.requires_grad_(True)\\n\",\n    \"bs = probs.size(1)\\n\",\n    \"\\n\",\n    \"ctc_loss = wp.CTCLoss(size_average=False, length_average=False)\\n\",\n    \"\\n\",\n    \"log_probs = torch.log_softmax(probs, axis=-1)\\n\",\n    \"cost = ctc_loss(log_probs, labels, probs_sizes, label_sizes)\\n\",\n    \"cost = cost.sum() / bs\\n\",\n    \"print(cost.item())\\n\",\n    \"cost.backward()\\n\",\n    \"print(probs.grad.numpy())\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"id\": \"443336f0\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.9.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 5\n}\n"
  },
  {
    "path": "docs/topic/ctc/ctc_loss_speed_compare.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"a1e738e0\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 获取测试的 logit 数据\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"29d3368b\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"hlens.npy\\n\",\n      \"logits.npy\\n\",\n      \"ys_lens.npy\\n\",\n      \"ys_pad.npy\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"!mkdir -p ./test_data\\n\",\n    \"!test -f ./test_data/ctc_loss_compare_data.tgz || wget -P ./test_data https://paddlespeech.cdn.bcebos.com/datasets/unit_test/asr/ctc_loss_compare_data.tgz\\n\",\n    \"!tar xzvf test_data/ctc_loss_compare_data.tgz -C ./test_data\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"id\": \"240caf1d\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import numpy as np\\n\",\n    \"import time\\n\",\n    \"\\n\",\n    \"data_dir=\\\"./test_data\\\"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"id\": \"91bad949\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"logits_np = np.load(os.path.join(data_dir, \\\"logits.npy\\\"))\\n\",\n    \"ys_pad_np = np.load(os.path.join(data_dir, \\\"ys_pad.npy\\\"))\\n\",\n    \"hlens_np = np.load(os.path.join(data_dir, \\\"hlens.npy\\\"))\\n\",\n    \"ys_lens_np = np.load(os.path.join(data_dir, \\\"ys_lens.npy\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"4cef2f15\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 使用 torch 的 ctc loss\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"id\": \"90612004\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'1.10.1+cu102'\"\n      ]\n     },\n     \"execution_count\": 4,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import torch\\n\",\n    \"torch.__version__\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"id\": \"00799f97\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def torch_ctc_loss(use_cpu):\\n\",\n    \"    if use_cpu:\\n\",\n    \"        device = torch.device(\\\"cpu\\\")\\n\",\n    \"    else:\\n\",\n    \"        device = torch.device(\\\"cuda\\\")\\n\",\n    \"\\n\",\n    \"    reduction_type = \\\"sum\\\" \\n\",\n    \"\\n\",\n    \"    ctc_loss = torch.nn.CTCLoss(reduction=reduction_type)\\n\",\n    \"\\n\",\n    \"    ys_hat = torch.tensor(logits_np, device = device)\\n\",\n    \"    ys_pad = torch.tensor(ys_pad_np, device = device)\\n\",\n    \"    hlens = torch.tensor(hlens_np, device = device)\\n\",\n    \"    ys_lens = torch.tensor(ys_lens_np, device = device)\\n\",\n    \"\\n\",\n    \"    ys_hat = ys_hat.transpose(0, 1)\\n\",\n    \"    \\n\",\n    \"    # 开始计算时间\\n\",\n    \"    start_time = time.time()\\n\",\n    \"    ys_hat = ys_hat.log_softmax(2)\\n\",\n    \"    loss = ctc_loss(ys_hat, ys_pad, hlens, ys_lens)\\n\",\n    \"    end_time = time.time()\\n\",\n    \"    \\n\",\n    \"    loss = loss / ys_hat.size(1)\\n\",\n    \"    return end_time - start_time, loss.item()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"ba47b5a4\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 使用 paddle 的 ctc loss\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"id\": \"6882a06e\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'2.2.2'\"\n      ]\n     },\n     \"execution_count\": 6,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import paddle\\n\",\n    \"paddle.__version__\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"id\": \"3cfa3b7c\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def paddle_ctc_loss(use_cpu):    \\n\",\n    \"    import paddle.nn as pn\\n\",\n    \"    if use_cpu:\\n\",\n    \"        device = \\\"cpu\\\"\\n\",\n    \"    else:\\n\",\n    \"        device = \\\"gpu\\\"\\n\",\n    \"\\n\",\n    \"    paddle.set_device(device)\\n\",\n    \"\\n\",\n    \"    logits = paddle.to_tensor(logits_np)\\n\",\n    \"    ys_pad = paddle.to_tensor(ys_pad_np,dtype='int32')\\n\",\n    \"    hlens = paddle.to_tensor(hlens_np, dtype='int64')\\n\",\n    \"    ys_lens = paddle.to_tensor(ys_lens_np, dtype='int64')\\n\",\n    \"\\n\",\n    \"    logits = logits.transpose([1,0,2])\\n\",\n    \"\\n\",\n    \"    ctc_loss = pn.CTCLoss(reduction='sum')\\n\",\n    \"    # 开始计算时间\\n\",\n    \"    start_time = time.time()\\n\",\n    \"    pn_loss = ctc_loss(logits, ys_pad, hlens, ys_lens)\\n\",\n    \"    end_time = time.time()\\n\",\n    \"    \\n\",\n    \"    pn_loss = pn_loss / logits.shape[1]\\n\",\n    \"    return end_time - start_time, pn_loss.item()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"id\": \"40413ef9\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"CPU, iteration 10\\n\",\n      \"torch_ctc_loss 159.17137145996094\\n\",\n      \"paddle_ctc_loss 159.16574096679688\\n\",\n      \"paddle average time 1.718252992630005\\n\",\n      \"torch average time 0.17536230087280275\\n\",\n      \"paddle time / torch time (cpu) 9.798303193320452\\n\",\n      \"\\n\",\n      \"GPU, iteration 10\\n\",\n      \"torch_ctc_loss 159.172119140625\\n\",\n      \"paddle_ctc_loss 159.17205810546875\\n\",\n      \"paddle average time 0.018606925010681154\\n\",\n      \"torch average time 0.0026710033416748047\\n\",\n      \"paddle time / torch time (gpu) 6.966267963938231\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# 使用 CPU\\n\",\n    \"\\n\",\n    \"iteration = 10\\n\",\n    \"use_cpu = True\\n\",\n    \"torch_total_time = 0\\n\",\n    \"paddle_total_time = 0\\n\",\n    \"for _ in range(iteration):\\n\",\n    \"    cost_time, torch_loss = torch_ctc_loss(use_cpu)\\n\",\n    \"    torch_total_time += cost_time\\n\",\n    \"for _ in range(iteration):\\n\",\n    \"    cost_time, paddle_loss = paddle_ctc_loss(use_cpu)\\n\",\n    \"    paddle_total_time += cost_time\\n\",\n    \"print (\\\"CPU, iteration\\\", iteration)\\n\",\n    \"print (\\\"torch_ctc_loss\\\", torch_loss)\\n\",\n    \"print (\\\"paddle_ctc_loss\\\", paddle_loss)\\n\",\n    \"print (\\\"paddle average time\\\", paddle_total_time / iteration)\\n\",\n    \"print (\\\"torch average time\\\", torch_total_time / iteration)\\n\",\n    \"print (\\\"paddle time / torch time (cpu)\\\" , paddle_total_time/ torch_total_time)\\n\",\n    \"\\n\",\n    \"print (\\\"\\\")\\n\",\n    \"\\n\",\n    \"# 使用 GPU\\n\",\n    \"\\n\",\n    \"use_cpu = False\\n\",\n    \"torch_total_time = 0\\n\",\n    \"paddle_total_time = 0\\n\",\n    \"for _ in range(iteration):\\n\",\n    \"    cost_time, torch_loss  = torch_ctc_loss(use_cpu)\\n\",\n    \"    torch_total_time += cost_time\\n\",\n    \"for _ in range(iteration):\\n\",\n    \"    cost_time, paddle_loss = paddle_ctc_loss(use_cpu)\\n\",\n    \"    paddle_total_time += cost_time\\n\",\n    \"print (\\\"GPU, iteration\\\", iteration)\\n\",\n    \"print (\\\"torch_ctc_loss\\\", torch_loss)\\n\",\n    \"print (\\\"paddle_ctc_loss\\\", paddle_loss)\\n\",\n    \"print (\\\"paddle average time\\\", paddle_total_time / iteration)\\n\",\n    \"print (\\\"torch average time\\\", torch_total_time / iteration)\\n\",\n    \"print (\\\"paddle time / torch time (gpu)\\\" , paddle_total_time/ torch_total_time)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"7cdf8697\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 其他: 使用 PaddleSpeech 中的 ctcloss 查一下loss值\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"id\": \"73fad81d\",\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"logits_np = np.load(os.path.join(data_dir, \\\"logits.npy\\\"))\\n\",\n    \"ys_pad_np = np.load(os.path.join(data_dir, \\\"ys_pad.npy\\\"))\\n\",\n    \"hlens_np = np.load(os.path.join(data_dir, \\\"hlens.npy\\\"))\\n\",\n    \"ys_lens_np = np.load(os.path.join(data_dir, \\\"ys_lens.npy\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"id\": \"2b41e45d\",\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"2022-02-25 11:34:34.143 | INFO     | paddlespeech.s2t.modules.loss:__init__:41 - CTCLoss Loss reduction: sum, div-bs: True\\n\",\n      \"2022-02-25 11:34:34.143 | INFO     | paddlespeech.s2t.modules.loss:__init__:42 - CTCLoss Grad Norm Type: instance\\n\",\n      \"2022-02-25 11:34:34.144 | INFO     | paddlespeech.s2t.modules.loss:__init__:73 - CTCLoss() kwargs:{'norm_by_times': True}, not support: {'norm_by_batchsize': False, 'norm_by_total_logits_len': False}\\n\",\n      \"loss 159.17205810546875\\n\"\n     ]\n    },\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"/root/miniconda3/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.float32, but right dtype is paddle.int32, the right dtype will convert to paddle.float32\\n\",\n      \"  format(lhs_dtype, rhs_dtype, lhs_dtype))\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"use_cpu = False\\n\",\n    \"\\n\",\n    \"from paddlespeech.s2t.modules.loss import CTCLoss\\n\",\n    \"\\n\",\n    \"if use_cpu:\\n\",\n    \"    device = \\\"cpu\\\"\\n\",\n    \"else:\\n\",\n    \"    device = \\\"gpu\\\"\\n\",\n    \"\\n\",\n    \"paddle.set_device(device)\\n\",\n    \"\\n\",\n    \"blank_id=0\\n\",\n    \"reduction_type='sum'\\n\",\n    \"batch_average= True\\n\",\n    \"grad_norm_type='instance'\\n\",\n    \"\\n\",\n    \"criterion = CTCLoss(\\n\",\n    \"        blank=blank_id,\\n\",\n    \"        reduction=reduction_type,\\n\",\n    \"        batch_average=batch_average,\\n\",\n    \"        grad_norm_type=grad_norm_type)\\n\",\n    \"\\n\",\n    \"logits = paddle.to_tensor(logits_np)\\n\",\n    \"ys_pad = paddle.to_tensor(ys_pad_np,dtype='int32')\\n\",\n    \"hlens = paddle.to_tensor(hlens_np, dtype='int64')\\n\",\n    \"ys_lens = paddle.to_tensor(ys_lens_np, dtype='int64')\\n\",\n    \"\\n\",\n    \"pn_ctc_loss = criterion(logits, ys_pad, hlens, ys_lens)\\n\",\n    \"print(\\\"loss\\\", pn_ctc_loss.item())\\n\",\n    \"    \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"id\": \"de525d38\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 结论\\n\",\n    \"在 CPU 环境下： torch 的 CTC loss 的计算速度是 paddle 的 9.8 倍  \\n\",\n    \"在 GPU 环境下： torch 的 CTC loss 的计算速度是 paddle 的 6.87 倍\\n\",\n    \"\\n\",\n    \"## 其他结论\\n\",\n    \"torch 的 ctc loss 在 CPU 和 GPU 下 都没有完全对齐。其中CPU的前向对齐精度大约为 1e-2。 GPU 的前向对齐精度大约为 1e-4 。\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.10\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 5\n}\n"
  },
  {
    "path": "docs/topic/frontend/g2p.md",
    "content": "# g2p 字典设计\n<!--\nmodified from https://zhuanlan.zhihu.com/p/349600439\n-->\n本文主要讲语音合成的 g2p (grapheme to phoneme) 部分。\n\n代码: [generate_lexicon.py](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/other/mfa/local/generate_lexicon.py) （代码可能与此处的描述有些许出入，以代码为准，生成的带 tone 带儿化的 pinyin 字典参考 [simple.lexicon](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/csmsc/tts3/local/simple.lexicon)）\n\n## ARPAbet\n对于英文 TTS，常用的 g2p 是通过查询 CMUDict 来实现，而 CMUDict 注音使用的系统是 ARPAbet，具体含义参见 [CMU 发音词典](http://www.speech.cs.cmu.edu/cgi-bin/cmudict/)。\n\n它包含 39 个 phoneme， 不包含音词汇重音的变体:\n\n| Phoneme       | Example | Translation |\n|:-------------:|:-------:|:-----------:|\n|     AA        |  odd    |    AA D     |\n|     AE        |  at     |    AE T     |\n|     AH        |  hut    |    HH AH T  |\n|     AO        |  ought  |    AO T     |\n|     AW        |  cow    |    K AW     |\n|     AY        |  hide   |    HH AY D  |\n|     B         |  be     |    B IY     |\n|     CH        |  cheese |    CH IY Z  |\n|     D         |  dee    |    D IY     |\n|     DH        |  thee   |    DH IY    |\n|     EH        |  Ed     |    EH D     |\n|     ER        |  hurt   |    HH ER T  |\n|     EY        |  ate    |    EY T     |\n|     F         |  fee    |    F IY     |\n|     G         |  green  |    G R IY N |\n|     HH        |  he     |    HH IY    |\n|     IH        |  it     |    IH T     |\n|     IY        |  eat    |    IY T     |\n|     JH        |  gee    |    JH IY    |\n|     K         |  key    |    K IY     |\n|     L         |  lee    |    L IY     |\n|     M         |  me     |    M IY     |\n|     N         |  knee   |    N IY     |\n|     NG        |  ping   |    P IH NG  |\n|     OW        |  oat    |    OW T     |\n|     OY        |  toy    |    T OY     |\n|     P         |  pee    |    P IY     |\n|     R         |  read   |    R IY D   |\n|     S         |  sea    |    S IY     |\n|     SH        |  she    |    SH IY    |\n|     T         |  tea    |    T IY     |\n|     TH        |  theta  |    TH EY T AH|\n|     UH        |  hood   |    HH UH D  |\n|     UW        |  two    |    T UW     |\n|     V         |  vee    |    V IY     |\n|     W         |  we     |    W IY     |\n|     Y         |  yield  |    Y IY L D |\n|     Z         |  zee    |    Z IY     |\n|     ZH        |  seizure|    S IY ZH ER|\n\n另外还包含三个重音标记，\n\n0 — No stress\n1 — Primary stress\n2 — Secondary stress\n\n其中重音标记附在元音后面。当只需要音标而不需要重音标记的时候也可以直接省略。\n\nCMUDict 只是一个词典，当出现了不在词典中的词时（OOV），可以求助其他工具可以根据拼写得到对应的发音，如: \n  - [Lexicon Tool](http://www.speech.cs.cmu.edu/tools)\n  - [g2p-seq2seq](https://github.com/cmusphinx/g2p-seq2seq)\n\n## 中文注音系统\n\n中文普通话的注音系统存在许多套，比如汉语拼音 (pinyin)， 注音符号 (bopomofo)， 国语注音符第二式， 威妥玛拼音等。而且有一些并非注音方案，是拉丁化方案，因此为了符号系统的经济性，会做一些互补符号的简并，比如汉语拼音中的 `i` 的代表了三个音位， `e` 代表了两个音位（单用的情况很少， 单用时写作 `ê`）；也有一些简写，比如 `bpmf` 后的 `o` 是 `uo` 的简写， `ui` 是 `uei` 的简写，` iu` 是 `iou` 的简写， `un` 是 `uen` 的简写， `ao` 是为了书写避免形近而改掉的 `au`， `y` 和 `w` 是为了连续书写时作为分隔而产生的零声母， `ü` 在 `j`、 `q`、 `x` 后面省略两点（中国大陆使用美式键盘打字的时候，一般只有在“女”、 “律”、“略”和“虐”这一类的字里面用 `v` 代替 `ü`，而在 `j`、 `q`、 `x` 后面的时候则仍用 `u` ），有鼻韵母 `uang` 而没有 `ueng`，但是又有 `weng` 这个音节之类的问题， 有 `ong` 韵母但是又没有单用的情形。其实这些都是汉语拼音作为拉丁化方案而做的一系列的修改。\n\n另外，汉语的声调是用了特殊符号来标调型，用字母记录的时候常用 `12345` 或者 `1234`、轻音不标等手段。\n\n另外还有两个比较突出的问题是**儿化**和**变调**（参考 [zh_text_frontend](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/tts/zh_text_frontend.md)）。对于具体的数据集，也可能有不同的标注方案。一般我们为汉字标音是标字调而不标变调，但是**标贝数据集是标变调的**（但是也没有把所有的变调都正确标出来）。儿化在汉语书写和拼音中也是一个比较麻烦的事情，虽然正字法中说到可以用小字号的儿表示儿化，但是这种发音由字号这种排版要素来表达的手法未免过于崎岖，所以鲜见有人真的这么排版，只有在某些书籍中，强调此事的时候见过。另外，在儿化的标音方式上，鼻韵母需要去掉韵尾然后换成 r，这么一来，如果直接抽取拼音的字符串表示，那么可能出现的音节就会超过 1400， 甚至进入一种含糊的状态，不清楚一共有多少个有效音节，即使是韵母，也会因此扩展近一倍。\n\n因为存在这样的情形，再考虑到不同的数据集自带的拼音 transcription 的风格可能不同，所以需要考虑进行转换，在内部转成统一的表示。既然这个过程是必要的，那么我们可以大胆设计一个内部方案。\n\n这里设计的原则是：\n\n1. 有效符号集仅切分为声母和韵母，不作声母，介音，韵腹，韵尾的切分；\n\n2. 尽可能把不同的音用不同的符号表示，比如 `i` 的 `e` 会被拆分为 3 和 2 个符号， `u` 和 `ü` 开头的韵母分开，这是为了 TTS 系统的建议性考虑的，我们选择尽量反映语音的现实情况，而不把注音系统里面的奇怪规则留给模型去学习；\n\n3. 不包含零声母 `y`， `w`之类的形式上的符号，因为如果这些符号不发声或者发声极短，那么可以不加入音符序列中，以期待 attention 更对角；\n\n4. 声调和韵母不结合为一个符号，而是分开，这样可以**减少词汇量**，使得符号的 embedding 得到更充分的训练，也更能反映声调语言的特点（数据集少时推荐这么做）；\n\n5. 儿化的标音方式采用拆分的方式处理， 但是增设一个特殊符号 `&r` 来表示儿化的 `r`，它和一般的 `er` 不同，以区分实际读音的区别。\n\n6. 更加贴近注音符号，把 `in` 写作 `ien`，`ing` 写作 `ieng`， `un` 写作 `uen`， `ong` 写作 `ueng`， `iong` 写作 `üeng`。其中 `in` 和 `ing` 的转写纯属偏好，无论用什么符号写，都可以被转为一个 index， 只要它们的使用情况不发声变化就可以。而 `ong` 写作 `ueng` 则是有实际差别的，如果 `ong` 作为一个韵母，那么 `weng` 经过修改之后会变成 `ueng`， 就会同时有 `ueng` 和 `ong`。而如果不细究音值上的微妙差异，`ong` 就是 `ung` 的一种奇怪表示， 在注意符号中， 它就记作 `ㄨㄥ`。而 `iong` 则是 `ㄩㄥ`。\n\n7. `ui`， `iu` 都展开为 `uei` 和 `iou` ， 纯属偏好，对实际结果没有影响。`bpmf `后的 `o` 展开为 `uo`，这个则是为了和单独的 `o` 区分开（哦， 和波里面的韵母的发音其实不同）。\n\n8. 所有的 `ü `都有 `v` 代替，无论是单独作韵母， 还是复韵母和鼻韵母。\n\n9. 把停顿以 `#1` 等方式纳入其中， 把 `<pad>` `<unk>` `<s>` `</s>` 这些为了处理符号系列的特殊符号也加入其中，多一些特殊词汇并不会对 Embedding 产生什么影响。\n\n于是我们可以的通过一套规则系统，把标贝的**拼音标注**转换成我们需要的形式。（当然，如果是别的数据集的实际标注不同，那么转换规则也要作一些修改)\n\n在实际使用中文数据集时，我们仅使用其提供的**拼音标注**，而不使用**音素标注**（PhoneLabel），因为不同的数据集有不同的标注规则，而且有的数据集是没有**音素标注**的（如，aishell3）\n\n我们的做法和维基百科上的汉语拼音音节列表更接近 [汉语拼音音节列表](https://zh.wikipedia.org/zh-hans/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82%E5%88%97%E8%A1%A8)\n\n转换之后，符号列表是：\n\n声母基本没有什么争议，共 21 个:\n|声母|\n|:--:|\n|b|\n|p|\n|m|\n|f|\n|d|\n|t|\n|n|\n|l|\n|g|\n|k|\n|h|\n|j|\n|q|\n|x|\n|zh|\n|ch|\n|sh|\n|r|\n|z|\n|c|\n|s|\n\n韵母和儿化韵尾（共 41个）\n|韵母|解释|\n|:----:|:-----------: |\n|ii     |`zi`，`ci`， `si` 里面的韵母 `i`|\n|iii    |`zhi`， `chi`， `shi`， `ri` 里面的韵母 `i`|\n|a    |啊，卡|\n|o    |哦|\n|e    |恶，个|\n|ea    |ê|\n|ai    |爱，在|\n|ei    |诶，薇|\n|ao    |奥，脑|\n|ou    |欧，勾|\n|an    |安，单|\n|en    |恩，痕|\n|ang    |盎，刚|\n|eng    |嗯，更|\n|er    |儿|\n|i    |一|\n|ia    |鸦，家|\n|io    |哟|\n|ie    |叶，界|\n|iai    |崖（台语发音）|\n|iao    |要，教|\n|iou    |有，久|\n|ian    |言，眠|\n|ien    |因，新|\n|iang    |样，降|\n|ieng    |英，晶\n|u    |无，卢|\n|ua    |哇，瓜|\n|uo    |我，波|\n|uai    |外，怪|\n|uei    |位，贵|\n|uan    |万，乱|\n|uen    |问，论|\n|uang   |网，光|\n|ueng   |翁，共|\n|v      |玉，曲，`ü`|\n|ve     |月，却|\n|van    |源，倦|\n|ven    |韵，君|\n|veng   |永，炯|\n|&r     |儿化韵尾|\n"
  },
  {
    "path": "docs/topic/gan_vocoder/gan_vocoder.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# GAN Vocoders 总览\\n\",\n    \"\\n\",\n    \"Loss 函数简称与全称的对应关系\\n\",\n    \"\\n\",\n    \"|Short Name|Full Name|\\n\",\n    \":-----:|:-----|\\n\",\n    \"|adv|adversial loss|\\n\",\n    \"|FM|Feature Matching|\\n\",\n    \"|MSD|Multi-Scale Discriminator|\\n\",\n    \"|mr-STFT|Multi-resolution STFT loss|\\n\",\n    \"|fmr-STFT|full band Multi-resolution STFT loss|\\n\",\n    \"|smr-STFT|sub band Multi-resolution STFT loss|\\n\",\n    \"|Mel|Mel-Spectrogram Loss|\\n\",\n    \"|MPD|Multi-Period Discriminator|\\n\",\n    \"|FB-RAWs|Filter Bank Random Window Discriminators|\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"csmsc 数据集上 GAN Vocoder 整体对比如下， \\n \",\n    \"\\n\",\n    \"测试机器：1 x Tesla V100-32G 40 core Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz\\n \",\n    \"\\n\",\n    \"测试环境：Python 3.7.0, paddlepaddle 2.2.0\\n\",\n    \"\\n\",\n    \"Model|Date|Input|Generator<br>Loss|Discriminator<br>Loss|Need<br>Finetune|Training<br>Steps|Finetune<br>Steps|Batch<br>Size|ips<br>(gen only)<br>(gen + dis)|Static Model<br>Size (gen)|RTF<br>(GPU)|\\n\",\n    \":-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|\\n\",\n    \"Mel GAN|9 Dec 2019|mel|adv<br>FM |MSD|——|——|——|——|——|——|——|\\n\",\n    \"Parallel Wave GAN |6 Feb 2020|mel<br>noise|adv<br>mr-STFT|adv|No|40W|——|8|18<br>10|5.1MB|0.01786|\\n\",\n    \"HiFi GAN|23 Oct 2020|mel|adv<br>FM<br>Mel|MSD<br>MPD|Yes|250W|no need|16|——<br>31|50MB|0.00825|\\n\",\n    \"Multi-Band Mel GAN|17 Nov 2020|mel|adv<br>fmr-STFT<br>smr-STFT|MSD|Yes|100W|100W<br><font size=1>(not good enough,<br>need to adjust parameters)</font>|64|305<br>148|8.2MB|0.00457|\\n\",\n    \"Style Mel GAN|12 Feb 2021|mel<br>noise|adv<br>mr-STFT|FB-RAWs|No|150W|——|32|58<br>24|——|0.01343|\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"attachments\": {},\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 网络结构\\n\",\n    \"## Mel GAN\\n\",\n    \"<center><img src=\\\"./imgs/melgan.png\\\"></center>\\n\",\n    \"<br><center>Mel GAN 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"## Parallel Wave GAN\\n\",\n    \"<center><img src=\\\"./imgs/pwg.png\\\"></center>\\n\",\n    \"<br><center>Parallel Wave GAN 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"## HiFi GAN\\n\",\n    \"<center><img src=\\\"./imgs/hifigan_gen.png\\\" width=900></center>\\n\",\n    \"<br><center>HiFi GAN 生成器网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"./imgs/hifigan_dis.png\\\" width=900></center>\\n\",\n    \"<br><center>HiFi GAN 判别器网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"## Multi-Band Mel GAN\\n\",\n    \"<center><img src=\\\"./imgs/mb_melgan.png\\\" width=500></center>\\n\",\n    \"<br><center>Multi-Band Mel GAN 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"## Style Mel GAN\\n\",\n    \"<center><img src=\\\"./imgs/style_melgan_TADE.png\\\" width=500></center>\\n\",\n    \"<br><center>Style Mel GAN TADE 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"./imgs/style_melgan_gen.png\\\" width=500></center>\\n\",\n    \"<br><center>Style Mel GAN 生成器网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"./imgs/style_melgan_dis.png\\\" width=500></center>\\n\",\n    \"<br><center>Style Mel GAN 判别器网络结构图</center></br>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 需要注意的点\\n\",\n    \"## 输入\\n\",\n    \"1. 一般情况下，若训练时输入中没有 `noise`，容易过拟合，需要 finetune\\n\",\n    \"    - 参考 [espent issue](https://github.com/espnet/espnet/issues/3536)\\n\",\n    \"2. 若输入中有 `noise`, 在预测时需要自己在 `inference` 代码中生成 `noise`, 而不能作为参数输入给 `inference`, 否则动转静可能走不通\\n\",\n    \"    - 参考 [pwgan 动转静修复 pr](https://github.com/PaddlePaddle/Parakeet/pull/132/files)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"## 生成器\\n\",\n    \"1. `hop_size` 和 `n_shift` 的含义一样\\n\",\n    \"2. `upsample_scales` 的乘积一定等于 `hop_size`\\n\",\n    \"3. `采样点 = hop_size * 帧数`\\n\",\n    \"4. `librosa 帧数 = 采样点 // hop_size + 1`, 具体要不要 `+1` 看不同的库，看 `center` 这个参数 \\n\",\n    \"5. `Mel GAN` 和 `Multi-Band Mel GAN` 生成器的代码是一样的，只是参数不一样，通道数不一样\\n\",\n    \"6. `Parallel Wave GAN` 的生成器是 `WaveNet` like\\n\",\n    \"    - 用非因果卷积替换了因果卷积\\n\",\n    \"    - 输入是满足高斯分布的随机噪声\\n\",\n    \"    - 训练和预测时都是非自回归的\\n\",\n    \"7. `Style MelGAN` 的 noise 的上采样需要额外注意，输入的长度是固定的\\n\",\n    \"    - `batch_max_steps(24000) == prod(noise_upsample_scales)(80) * prod(upsample_scales)(300, n_shift)`\\n\",\n    \"\\n\",\n    \"## 判别器\\n\",\n    \"1. HiFi GAN 判别器的能力很强\\n\",\n    \"\\n\",\n    \"## 速度\\n\",\n    \"1. 为什么 `Multi-Band Mel GAN` 的预测会更快？因为上采样的倍数变为了原来的 `1/4`\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# FFT 在语音合成声码器上的应用\\n\",\n    \"\\n\",\n    \"语音合成是一种将任意文本转换成语音的技术，目前在深度学习领域，语音合成主要分为 `3` 个模块:\\n\",\n    \"- 文本前端\\n\",\n    \"- 声学模型\\n\",\n    \"- 声码器\\n\",\n    \"\\n\",\n    \"其中，文本前端模块将输入文本转换为音素序列或语言学特征；声学模型将音素序列或语言学特征转换为声学特征，在语音合成领域，常用的声学特征是 mel 频谱；声码器将声学特征转换为语音波形。\\n\",\n    \"\\n\",\n    \"声码器的输入是频域特征 mel 频谱图，输出是对应的语音波形。\\n\",\n    \"\\n\",\n    \"STFT 全称 Short-Time Fourier Transform，短时傅里叶变换，它是用滑动帧 FFT 生成频率与时间的 2D 矩阵，通常被称为频谱图（Spectrogram）, 而人耳对于频率的敏感程度是非线性的，可以通过 mel 三角滤波器对频谱图处理，生成 mel 频谱图。\\n\",\n    \"\\n\",\n    \"生成 mel 频谱图的计算离不开 fft 系列的算子，若模型的输入是 mel 频谱图，可以使用 `librosa` 等科学计算库进行计算再输入模型。然而，现有的大多数基于 `GAN` 的声码器模型，在计算 `loss` 时需要将生成器合成的音频及原始音频转换到频率域再做计算，这时需要用到短时傅里叶变换算子 `stft`，且由于 `stft` 算子出现在了模型图中，其需要参与到模型的前向和反向计算过程中，此时，则需要深度学习框架提供 `stft` 算子。\\n\",\n    \"\\n\",\n    \"最新的 `PaddleSpeech` 语音合成模块的声码器，用到了 paddle 2.2.0 提供的 fft 系列算子 `paddle.signal.stft`。\\n\",\n    \"\\n\",\n    \"`PaddleSpeech` 模型库目前已经实现的基于 `GAN` 的声码器包括 `Parallel WaveGAN`、`Multi Band MelGAN`、`HiFiGAN` 和 `Style MelGAN`，这些模型的 `loss` 中都包含基于 `stft` 算子的 `loss`，其中主要包含 `Multi-resolution STFT loss` 和 `Mel-Spectrogram Loss`。\\n\",\n    \"\\n\",\n    \"`Multi-resolution STFT loss` 公式如下所示：\\n\",\n    \"\\n\",\n    \"![image](./imgs/stft_loss_0.png)\\n\",\n    \"\\n\",\n    \"![image](./imgs/stft_loss_1.png)\\n\",\n    \"\\n\",\n    \"![image](./imgs/stft_loss_2.png)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"`Mel-Spectrogram Loss` 公式如下所示：\\n\",\n    \"\\n\",\n    \"![image](./imgs/mel_loss.png)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"其中 `Φ` 表示将音频转换为对应 mel 频谱的函数。\\n\",\n    \"\\n\",\n    \"如上述公式所示，现在主流的基于 `GAN` 的声码器的 `loss` 设计需要用到 `stft`，在 Paddle 中尚未实现 fft 系列算子时，`PaddleSpeech` 模型库使用基于 `Conv1D` 算子的函数来模拟 `stft` 算子，然而经过计算，该模拟函数前向结果正确，反向梯度计算结果不正确，这导致了模型收敛效果不佳，听感略差于竞品。\\n\",\n    \"\\n\",\n    \"Paddle 主框架中加入 fft 系列算子后，我们将语音合成声码器 loss 模块中的基于 `Conv1D` 的 `stft` 均替换为 `paddle.signal.stft`，在模型收敛效果和合成音频听感上，`paddle.signal.stft` 的效果明显优于基于 `Conv1D` 的 `stft` 实现。\\n\",\n    \"\\n\",\n    \"以 `Parallel WaveGAN` 模型为例，我们复现了基于 `Pytorch` 和基于 `Paddle` 的 `Parallel WaveGAN`，并保持模型结构完全一致，在相同的实验环境下，基于 `Paddle` 的模型收敛速度比基于 `Pytorch` 的模型快 `10.4%`, 而基于 `Conv1D` 的 `stft` 实现的 Paddle 模型的收敛速度和收敛效果和收敛速度差于基于 `Pytorch` 的模型，更明显差于基于 `Paddle` 的模型，所以可以认为 `paddle.signal.stft` 算子大幅度提升了 `Parallel WaveGAN` 模型的效果。\\n\",\n    \"\\n\",\n    \"![image](https://paddlespeech.cdn.bcebos.com/Parakeet/docs/images/pwg_vs.png)\\n\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3.7.0 64-bit ('yt_py37_develop': venv)\",\n   \"language\": \"python\",\n   \"name\": \"python37064bitytpy37developvenv88cd689abeac41d886f9210a708a170b\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.0\"\n  },\n  \"toc\": {\n   \"base_numbering\": 1,\n   \"nav_menu\": {},\n   \"number_sections\": true,\n   \"sideBar\": true,\n   \"skip_h1_title\": false,\n   \"title_cell\": \"Table of Contents\",\n   \"title_sidebar\": \"Contents\",\n   \"toc_cell\": false,\n   \"toc_position\": {},\n   \"toc_section_display\": true,\n   \"toc_window_display\": false\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 4\n}\n"
  },
  {
    "path": "docs/topic/package_release/python_package_release.md",
    "content": "# 简化安装与发包\n\n## 问题：\n\n1. [如何去除 ubuntu 的 apt 安装依赖？](#conda-代替系统依赖)\n2. [如何支持普通用户和开发者两种安装的需求，尽量减少普通用户所需的依赖？](#区分install模式和develop模式)\n3. [如何进行 python 包的动态安装？](#python-包的动态安装)\n4. [如何进行 python 项目编包？](#python-编包方法)\n5. [发包前要有什么准备？](#关于发包前的准备工作)\n6. [发 C++ 包需要注意的东西？](#manylinux)\n\n\n## conda 代替系统依赖\n\nconda 可以用来代替一些 apt-get 安装的系统依赖，这样可以让项目适用于除了 ubuntu 以外的系统。\n\n使用 conda 可以安装 sox、 libsndfile、swig 等 paddlespeech 需要的依赖：\n\n```bash\nconda install -y -c conda-forge sox libsndfile\n```\n\n部分系统会缺少 libbzip2 库，这个 paddlespeech 也是需要的，这也可以用 conda 安装：\n\n```bash\nconda install -y -c bzip2\n```\n\nconda 也可以安装 linux 的 C++ 的依赖：\n\n```bash\nconda install -y -c gcc_linux-64=8.4.0 gxx_linux-64=8.4.0\n```\n\n#### 剩余问题：使用 conda 环境编译 kenlm 失败。目前在 conda 环境下编译 kenlm 会出现链接失败的问题\n\n目前知道需要的依赖：\n\n```bash\nconda install -c conda-forge eigen boost cmake\n```\n\n## 区分install模式和develop模式\n\n可以在 setup.py 中划分 install 的依赖（基本依赖）和 develop 的依赖 （开发者额外依赖）。 setup_info 中 `install_requires` 设置 install 的依赖，而在 `extras_require` 中设置 `develop` key 为 develop 的依赖。\n普通安装可以使用：\n\n```bash\npip install . \n```\n\n另外使用 pip 安装已发的包也是使用普通安装的：\n\n```\npip install paddlespeech\n```\n\n而开发者可以使用如下方式安装，这样不仅会安装 install 的依赖，也会安装 develop 的依赖， 即：最后安装的依赖 = install 依赖 + develop 依赖：\n\n```bash\npip install -e .[develop]\n```\n\n## python 包的动态安装\n\n可以使用 pip 包来实现动态安装：\n\n```python\nimport pip\nif int(pip.__version__.split('.')[0]) > 9:\n        from pip._internal import main\n    else:\n        from pip import main\n    main(['install', package_name])\n```\n\n## python 编包方法\n\n#### 创建 pypi的账号\n\n创建 pypi 账号\n\n#### 下载 twine\n\n```\npip install twine\n```\n\n#### python 编包\n\n编写好 python 包的 setup.py, 然后使用如下命令编 wheel 包：\n\n```bash\npython setup.py bdist_wheel\n```\n\n如果要编源码包，用如下命令：\n\n```bash\npython setup.py sdist\n```\n\n#### 上传包\n\n```bash\ntwine upload dist/wheel包\n```\n\n输入账号和密码后就可以上传 wheel 包了\n\n#### 关于python 包的发包信息\n\n主要可以参考这个[文档](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/?highlight=find_packages)\n\n\n## 关于发包前的准备工作\n\n#### 拉分支\n在发包之前需要拉分支。例如需要发 0.1.0 版本的正式包，则需要拉一个 r0.1 的分支。并且在这个 r0.1 分支的包上面打 0.1.0 的tag。在拉分支之前可以选择性的使用 rc 版本发一个正式版前的试用包，例如0.1.0rc0，等到rc包测试通过后，再拉分支（如果是发 0.1.1 包，则 merge r0.1分支），打tag，完成发包。\n\n关于打tag的命令，可以参考[git 基础](https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE)。使用轻量标签即可:\n```bash\ngit tag r0.1.1 commit_id\n```\n然后使用`git push` 把本地 tag 传到远程 repo 上即可 \n```bash\ngit push origin r0.1.1\n```\n打完 tag 后要记得编写 release note。\n\n最后，发包准备工作的步骤可以总结为：  \n- 用 develop 分支发 rc 包\n- rc 包通过后拉分支\n- 打 tag\n- 发包\n- 编写 release note\n\n\n\n## ManyLinux\n\n为了让有 C++ 依赖的 pip wheel 包可以适用于更多的 linux 系统，需要降低其本身的 glibc 的依赖。这就需要让 pip wheel 包在 manylinux 的 docker 下编包。关于查看系统的 glibc 版本，可以使用命令：`ldd --version`。\n\n### Manylinux\n\n关于 Manylinux，主要可以参考 Github 项目的说明[ github many linux](https://github.com/pypa/manylinux)。\nmanylinux1 支持 Centos5以上， manylinux2010 支持 Centos 6 以上，manylinux2014 支持Centos 7 以上。\n目前使用 manylinux2010 基本可以满足所有的 linux 生产环境需求。（不建议使用manylinux1，系统较老，难度较大）\n\n### 拉取 manylinux2010\n\n```bash\ndocker pull quay.io/pypa/manylinux2010_x86_64\n```\n\n### 使用 manylinux2010\n\n启动 manylinux2010 docker。\n\n```bash\ndocker run -it xxxxxx\n```\n\n在 manylinux2010 的docker环境自带 swig 和各种类型的 python 版本。这里注意不要自己下载 conda 来安装环境来编译 pip 包，要用 docker 本身的环境来编包。\n设置python：\n\n```bash\nexport PATH=\"/opt/python/cp38-cp38/bin/:$PATH\"\n#export PATH=\"/opt/python/cp39-cp39/bin/:$PATH\"\n```\n\n随后正常编包，编包后需要使用 [auditwheel](https://github.com/pypa/auditwheel) 来降低编好的wheel包的版本。\n显示 wheel 包的 glibc 依赖版本\n\n```bash\nauditwheel show wheel包\n```\n\n降低 wheel包的版本\n\n```bash\nauditwheel repair wheel包\n```\n"
  },
  {
    "path": "docs/tutorial/.gitkeep",
    "content": ""
  },
  {
    "path": "docs/tutorial/asr/tutorial_deepspeech2.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"<a href=\\\"https://github.com/PaddlePaddle/PaddleSpeech\\\"><img style=\\\"position: absolute; z-index: 999; top: 0; right: 0; border: 0; width: 128px; height: 128px;\\\" src=\\\"https://nosir.github.io/cleave.js/images/right-graphite@2x.png\\\" alt=\\\"Fork me on GitHub\\\"></a>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# 语音识别——DeepSpeech2\\n\",\n    \"  \\n\",\n    \"# 0. 视频理解与字幕\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 下载demo视频\\n\",\n    \"!test -f work/source/subtitle_demo1.mp4 || wget https://paddlespeech.cdn.bcebos.com/demos/asr_demos/subtitle_demo1.mp4 -P work/source/\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import IPython.display as dp\\n\",\n    \"from IPython.display import HTML\\n\",\n    \"html_str = '''\\n\",\n    \"<video controls width=\\\"600\\\" height=\\\"360\\\" src=\\\"{}\\\">animation</video>\\n\",\n    \"'''.format(\\\"work/source/subtitle_demo1.mp4 \\\")\\n\",\n    \"dp.display(HTML(html_str))\\n\",\n    \"print (\\\"ASR结果为：当我说我可以把三十年的经验变成一个准确的算法他们说不可能当我说我们十个人就能实现对十九个城市变电站七乘二十四小时的实时监管他们说不可能\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"> Demo实现：[Dhttps://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/automatic_video_subtitiles/](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/automatic_video_subtitiles/)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"# 1. 前言\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 1.1 背景知识\\n\",\n    \"语音识别(Automatic Speech Recognition, ASR) 是一项从一段音频中提取出语言文字内容的任务。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/0231a71b0617485d85586d232f65db6379115befdf014068bd90fb15c5786c94\\\"/>\\n\",\n    \"<br>\\n\",\n    \"(出处：DLHLP 李宏毅 语音识别课程PPT)\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"目前该技术已经广泛应用于我们的工作和生活当中，包括生活中使用手机的语音转写，工作上使用的会议记录等等。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 1.2 发展历史\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"* 早期，生成模型流行阶段：GMM-HMM (上世纪90年代)\\n\",\n    \"* 深度学习爆发初期： DNN，CTC[1] （2006）\\n\",\n    \"* RNN流行，Attention提出初期: RNN-T[2]（2013）, DeepSpeech[3] (2014)， DeepSpeech2 [4] (2016)， LAS[5]（2016）\\n\",\n    \"* Attetion is all you need提出开始[6]: Transformer[6]（2017），Transformer-transducer[7]（2020） Conformer[8] （2020\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/d6060426bba341a187422803c0f8ac2e2162c5c5422e4070a3425c09f7801379\\\" height=1300, width=1000 />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"Deepspeech2模型包含了CNN，RNN，CTC等深度学习语音识别的基本技术，因此本教程采用了Deepspeech2作为讲解深度学习语音识别的开篇内容。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 2. 实战：使用 DeepSpeech2 进行语音识别的流程\\n\",\n    \"\\n\",\n    \"Deepspeech2 模型，其主要分为3个部分：\\n\",\n    \"1. 特征提取模块：此处使用 linear 特征，也就是将音频信息由时域转到频域后的信息。\\n\",\n    \"2. Encoder：多层神经网络，用于对特征进行编码。\\n\",\n    \"3. CTC Decoder： 采用了 CTC 损失函数训练；使用 CTC 解码得到结果。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/f7268c47d55e487cbb97f123785cab248f4371072381465a8b43af33f4abdf83\\\" height=1000, width=800/>\\n\",\n    \"</div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 2.1 Deepspeech2 模型结构\\n\",\n    \"\\n\",\n    \"### 2.1.1 Encoder\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"Encoder 主要采用了 2 层降采样的 CNN（subsampling Convolution layer）和多层 RNN（Recurrent Neural Network）层组成。\\n\",\n    \"\\n\",\n    \"其中降采样的 CNN 主要用途在提取局部特征，减少模型输入的帧数，降低计算量，并易于模型收敛。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"  \\n\",\n    \"#### 2.1.1.1 CNN: Receptive field\\n\",\n    \"\\n\",\n    \"假如以 $F_j$ 代表 $L_j$ 的 cnn 滤波器大小, $S_i$ 代表 $L_i$ 的CNN滤波器跳跃长度，并设定 $S_0 = 1$。那么 $L_k$ 的感受野大小可以由以下公式计算：\\n\",\n    \"\\n\",\n    \"$$\\\\boxed{R_k = 1 + \\\\sum_{j=1}^{k} [(F_j - 1) \\\\prod_{i=0}^{j-1} S_i]}$$\\n\",\n    \"在下面的例子中, $F_1 = F_2 = 3$ 并且 $S_1 = S_2 = 2$, 因此可以得到 $R_2 = 1 + 2\\\\cdot 1 + 2\\\\cdot 2 = 7$\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/b3c53b7d1b2944acb91520454f5b27be0e0e0af110e24959942d85e87992d6d0\\\"  />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"  \\n\",\n    \"#### 2.1.1.2 RNN\\n\",\n    \"\\n\",\n    \"  而多层 RNN 的作用在于获取语音的上下文信息，这样可以获得更加准确的信息，并一定程度上进行语义消歧。\\n\",\n    \"  \\n\",\n    \"Deepspeech2 的模型中 RNNCell 可以选用 GRU 或者 LSTM。\\n\",\n    \"  \\n\",\n    \"\\n\",\n    \"#### 2.1.1.3 Softmax\\n\",\n    \"而最后 softmax 层将特征向量映射到为一个字表长度的向量，向量中存储了当前 step 结果预测为字表中每个字的概率。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"### 2.1.2 Decoder\\n\",\n    \"Decoder 的作用主要是将 Encoder 输出的概率解码为最终的文字结果。\\n\",\n    \"\\n\",\n    \"对于 CTC 的解码主要有3种方式：\\n\",\n    \"\\n\",\n    \"* CTC greedy search \\n\",\n    \"\\n\",\n    \"* CTC beam search \\n\",\n    \"\\n\",\n    \"* CTC Prefix beam search\\n\",\n    \"\\n\",\n    \"#### 2.1.2.1 CTC Greedy Search\\n\",\n    \"\\n\",\n    \"在每个时间点选择后验概率最大的 label 加入候选序列中，最后对候选序列进行后处理，就得到解码结果。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/d6e90cf5d20047ddbcdba5ff13c6c96a9ffca20faaa84927a6012fa1927e5b8d\\\" height=800, width=500 />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"#### 2.1.2.2 CTC Beam Search\\n\",\n    \"\\n\",\n    \"CTC Beam Search 的方式是有 beam size 个候选序列，并在每个时间点生成新的最好的 beam size 个候选序列。\\n\",\n    \"最后在 beam size 个候选序列中选择概率最高的序列生成最终结果。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/98560261bc584c209a339396296d56559c6daa9a9bb74532b014c6d7ee4b7a5f\\\" height=1200, width=800 />\\n\",\n    \"  <br>\\n\",\n    \"  引用自[9]\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.1.2.3 CTC Prefix Beam Search\\n\",\n    \"\\n\",\n    \"CTC prefix beam search和 CTC beam search 的主要区别在于：\\n\",\n    \"\\n\",\n    \"CTC beam search 在解码过程中产生的候选有可能产生重复项，而这些重复项在 CTC beam search 的计算过程中是各自独立的，占用了 beam 数，降低解码的多样性和鲁棒性。\\n\",\n    \"\\n\",\n    \"而 CTC prefix beam search 在解码过程中合并了重复项的概率，提升解码的鲁棒性和多样性。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/3d8c949abd0948f1be35ad2b3cf9a0100be1dcc771724d9681b5b31fc1fd4fa6\\\" height=1200, width=800  />\\n\",\n    \"  <br>\\n\",\n    \"  引用自[9]\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"CTC prefix beam search 计算过程如下图所示：\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/7a779a8687054d559515153d9ab35aa5e9f54676f5b64984960c62f6998a0ce3\\\" height=1200, width=800  />\\n\",\n    \"  <br>\\n\",\n    \"  引用自[10]\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"> [CTCLoss](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/topic/ctc/) 相关介绍参看 [Topic](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/topic/) 内容。\\n\",\n    \"\\n\",\n    \"#### 2.1.2.4 使用 N-gram 语言模型\\n\",\n    \"\\n\",\n    \"对于解码的候选结果的打分，除了有声学模型的分数外，还会有额外的语言模型分以及长度惩罚分。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"设定 $W$ 为解码结果，$X$ 为输入语音， $\\\\alpha$ 和 $\\\\beta$ 为设定的超参数。\\n\",\n    \"则最终分数的计算公式为:\\n\",\n    \"$$\\n\",\n    \"score = P_{am}(W \\\\mid X) \\\\cdot P_{lm}(W) ^ \\\\alpha \\\\cdot |W|^\\\\beta\\n\",\n    \"$$\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"## 2.2 准备工作\\n\",\n    \"    \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"### 2.2.1 安装 paddlespeech\\n\",\n    \"    \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!pip install -U pip paddlepaddle-gpu && pip install paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.2.2 准备工作目录\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!mkdir -p ./work/workspace_asr_ds2\\n\",\n    \"%cd ./work/workspace_asr_ds2\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"### 2.2.3 获取预训练模型和相关文件\\n\",\n    \"  \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!test -f ds2.model.tar.gz || wget -nc https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/ds2.model.tar.gz\\n\",\n    \"!tar xzvf ds2.model.tar.gz\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 构建一个数据增强的配置文件，由于预测不需要数据增强，因此文件为空即可\\n\",\n    \"!touch conf/augmentation.json\\n\",\n    \"# 下载语言模型\\n\",\n    \"!mkdir -p data/lm\\n\",\n    \"!test -f ./data/lm/zh_giga.no_cna_cmn.prune01244.klm || wget -nc https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm -P data/lm\\n\",\n    \"# 获取用于预测的音频文件\\n\",\n    \"!test -f ./data/demo_01_03.wav || wget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P ./data/\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import IPython\\n\",\n    \"IPython.display.Audio('./data/demo_01_03.wav')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 快速体验识别结果\\n\",\n    \"!paddlespeech asr --input ./data/demo_01_03.wav\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"\\n\",\n    \"### 2.2.4 导入python包\\n\",\n    \"    \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import paddle\\n\",\n    \"import warnings\\n\",\n    \"warnings.filterwarnings('ignore')\\n\",\n    \"\\n\",\n    \"from yacs.config import CfgNode\\n\",\n    \"\\n\",\n    \"from paddlespeech.s2t.frontend.speech import SpeechSegment\\n\",\n    \"from paddlespeech.s2t.frontend.normalizer import FeatureNormalizer\\n\",\n    \"from paddlespeech.s2t.frontend.featurizer.audio_featurizer import AudioFeaturizer\\n\",\n    \"from paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\\n\",\n    \"\\n\",\n    \"from paddlespeech.s2t.io.collator import SpeechCollator\\n\",\n    \"\\n\",\n    \"from paddlespeech.s2t.models.ds2 import DeepSpeech2Model\\n\",\n    \"\\n\",\n    \"from  matplotlib import pyplot as plt\\n\",\n    \"%matplotlib inline\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"\\n\",\n    \"### 2.2.5 设置预训练模型的路径\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"config_path = \\\"conf/deepspeech2.yaml\\\" \\n\",\n    \"checkpoint_path = \\\"./exp/deepspeech/checkpoints/avg_1.pdparams\\\"\\n\",\n    \"audio_file = \\\"data/demo_01_03.wav\\\"\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# 读取 conf 文件并结构化\\n\",\n    \"ds2_config = CfgNode(new_allowed=True)\\n\",\n    \"ds2_config.merge_from_file(config_path)\\n\",\n    \"print(ds2_config)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"\\n\",\n    \"## 2.3 获取特征\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.3.1 语音特征介绍\\n\",\n    \"  \\n\",\n    \"#### 2.3.1.1 语音特征提取整体流程图\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/54aefbc16dbf4487a7abe38b0210e5dbf1bb0c74fbe4459f94880a06950269f9\\\" height=1200, width=800  />\\n\",\n    \"<br>\\n\",\n    \"由\\\"莊永松、柯上優 DLHLP - HW1 End-to-end Speech Recognition PPT\\\" 修改得\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.3.1.2 fbank 提取过程简化图\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"fbank 特征提取大致可以分为3个步骤：\\n\",\n    \"\\n\",\n    \"1. 语音时域信号经过增强，然后进行分帧。\\n\",\n    \"\\n\",\n    \"2. 每一帧数据加窗后经过离散傅立叶变换（DFT）得到频谱图。\\n\",\n    \"\\n\",\n    \"3. 将频谱图的特征经过 Mel 滤波器得到 logmel fbank 特征。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/08f7ccecc848495599c350aa2c440071b818ba0465734dd29701a2ff149f0a8c\\\" height=1200, width=800 />\\n\",\n    \"<br>\\n\",\n    \"由\\\"DLHLP 李宏毅 语音识别课程PPT\\\" 修改得\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.3.1.3 CMVN 计算过程\\n\",\n    \"\\n\",\n    \"对于所有获取的特征，模型在使用前会使用 CMVN 的方式进行归一化\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"  <img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/46df63199d88481d9a2713a45ce63d00220e8ac42f9940e886282017758b54bf\\\" height=1200, width=800  />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \" \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.3.2 构建音频特征提取对象\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"feat_config = ds2_config.collator\\n\",\n    \"audio_featurizer = AudioFeaturizer(\\n\",\n    \"    spectrum_type=feat_config.spectrum_type,\\n\",\n    \"    feat_dim=feat_config.feat_dim,\\n\",\n    \"    delta_delta=feat_config.delta_delta,\\n\",\n    \"    stride_ms=feat_config.stride_ms,\\n\",\n    \"    window_ms=feat_config.window_ms,\\n\",\n    \"    n_fft=feat_config.n_fft,\\n\",\n    \"    max_freq=feat_config.max_freq,\\n\",\n    \"    target_sample_rate=feat_config.target_sample_rate,\\n\",\n    \"    use_dB_normalization=feat_config.use_dB_normalization,\\n\",\n    \"    target_dB=feat_config.target_dB,\\n\",\n    \"    dither=feat_config.dither)\\n\",\n    \"feature_normalizer = FeatureNormalizer(feat_config.mean_std_filepath) if feat_config.mean_std_filepath else None\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.3.3 提取音频的特征\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 'None' 只是一个占位符，因为预测的时候不需要reference\\n\",\n    \"speech_segment = SpeechSegment.from_file(audio_file, \\\"None\\\")\\n\",\n    \"audio_feature = audio_featurizer.featurize(speech_segment)\\n\",\n    \"audio_feature_i = feature_normalizer.apply(audio_feature)\\n\",\n    \"\\n\",\n    \"audio_len = audio_feature_i.shape[0]\\n\",\n    \"audio_len = paddle.to_tensor(audio_len)\\n\",\n    \"audio_feature = paddle.to_tensor(audio_feature_i, dtype='float32')\\n\",\n    \"audio_feature = paddle.unsqueeze(audio_feature, axis=0)\\n\",\n    \"print(f\\\"shape: {audio_feature.shape}\\\")\\n\",\n    \"\\n\",\n    \"plt.figure()\\n\",\n    \"plt.imshow(audio_feature_i.T, origin='lower')\\n\",\n    \"plt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"## 2.4 使用模型获得结果\\n\",\n    \"    \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.4.1 构建Deepspeech2模型\\n\",\n    \"  \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"model_conf = ds2_config.model\\n\",\n    \"# input dim is feature size\\n\",\n    \"model_conf.input_dim = 161\\n\",\n    \"# output_dim is vocab size\\n\",\n    \"model_conf.output_dim = 4301\\n\",\n    \"model = DeepSpeech2Model.from_config(model_conf)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.4.2 加载预训练的模型\\n\",\n    \"  \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"model_dict = paddle.load(checkpoint_path)\\n\",\n    \"model.set_state_dict(model_dict)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.4.3 进行预测\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"decoding_config = ds2_config.decoding\\n\",\n    \"print (decoding_config)\\n\",\n    \"text_feature = TextFeaturizer(unit_type='char',\\n\",\n    \"                            vocab=ds2_config.collator.vocab_filepath)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"result_transcripts = model.decode(\\n\",\n    \"        audio_feature,\\n\",\n    \"        audio_len,\\n\",\n    \"        text_feature.vocab_list,\\n\",\n    \"        decoding_method=decoding_config.decoding_method,\\n\",\n    \"        lang_model_path=decoding_config.lang_model_path,\\n\",\n    \"        beam_alpha=decoding_config.alpha,\\n\",\n    \"        beam_beta=decoding_config.beta,\\n\",\n    \"        beam_size=decoding_config.beam_size,\\n\",\n    \"        cutoff_prob=decoding_config.cutoff_prob,\\n\",\n    \"        cutoff_top_n=decoding_config.cutoff_top_n,\\n\",\n    \"        num_processes=decoding_config.num_proc_bsearch)\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 16,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"print (\\\"预测结果为:\\\")\\n\",\n    \"print (result_transcripts[0])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"# 3. 总结\\n\",\n    \"\\n\",\n    \"* CTC 帮助模型学习语音和 label 之间的 alignment。\\n\",\n    \"* CTC 可以做到帧同步解码，非常适合做流式模型。\\n\",\n    \"* CTC 的输出是之间是独立的，相对于 Seq2Seq 其建模能力差，一般需要外挂 LM 才能得到好的结果。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# 4. 作业 \\n\",\n    \"1. 使用开发模式安装 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech)  \\n\",\n    \"环境要求：docker, Ubuntu 16.04，root user。  \\n\",\n    \"参考安装方法：[使用Docker安装paddlespeech](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md#hard-get-the-full-funciton-on-your-mechine)\\n\",\n    \"\\n\",\n    \"2. 跑通 example/aishell/asr1 中的 conformer 模型，完成训练和预测。 \\n\",\n    \"\\n\",\n    \"3. 按照 example 的格式使用自己的数据集训练 ASR 模型。 \\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# 5. 关注 PaddleSpeech\\n\",\n    \"\\n\",\n    \"请关注我们的 [Github Repo](https://github.com/PaddlePaddle/PaddleSpeech/)，非常欢迎加入以下微信群参与讨论：\\n\",\n    \"- 扫描二维码\\n\",\n    \"- 添加运营小姐姐微信\\n\",\n    \"- 通过后回复【语音】\\n\",\n    \"- 系统自动邀请加入技术群\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/87bc7da42bcc401bae41d697f13d8b362bfdfd7198f14096b6d46b4004f09613\\\" width=\\\"300\\\" height=\\\"300\\\" ></center>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# 5. 参考文献\\n\",\n    \"\\n\",\n    \"[1] Graves A, Fernández S, Gomez F, et al. Connectionist temporal classification: labelling unsegmented sequence data with recurrent neural networks[C]//Proceedings of the 23rd international conference on Machine learning. 2006: 369-376.\\n\",\n    \"\\n\",\n    \"[2] Graves A, Mohamed A, Hinton G. Speech recognition with deep recurrent neural networks[C]//2013 IEEE international conference on acoustics, speech and signal processing. Ieee, 2013: 6645-6649.\\n\",\n    \"\\n\",\n    \"[3] Hannun A, Case C, Casper J, et al. Deep speech: Scaling up end-to-end speech recognition[J]. arXiv preprint arXiv:1412.5567, 2014.\\n\",\n    \"\\n\",\n    \"[4] Amodei D, Ananthanarayanan S, Anubhai R, et al. Deep speech 2: End-to-end speech recognition in english and mandarin[C]//International conference on machine learning. PMLR, 2016: 173-182.\\n\",\n    \"\\n\",\n    \"[5] Chan W, Jaitly N, Le Q, et al. Listen, attend and spell: A neural network for large vocabulary conversational speech recognition[C]//2016 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2016: 4960-4964.\\n\",\n    \"\\n\",\n    \"[6] Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need[C]//Advances in neural information processing systems. 2017: 5998-6008.\\n\",\n    \"\\n\",\n    \"[7] Zhang Q, Lu H, Sak H, et al. Transformer transducer: A streamable speech recognition model with transformer encoders and rnn-t loss[C]//ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020: 7829-7833.\\n\",\n    \"\\n\",\n    \"[8] Gulati A, Qin J, Chiu C C, et al. Conformer: Convolution-augmented transformer for speech recognition[J]. arXiv preprint arXiv:2005.08100, 2020.\\n\",\n    \"\\n\",\n    \"[9] Retrieved 2021-12-6，from \\\"Sequence Modeling With CTC\\\": https://distill.pub/2017/ctc/#inference\\n\",\n    \"\\n\",\n    \"[10] Hannun A Y, Maas A L, Jurafsky D, et al. First-pass large vocabulary continuous speech recognition using bi-directional recurrent dnns[J]. arXiv preprint arXiv:1408.2873, 2014.\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"py35-paddle1.2.0\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.4\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "docs/tutorial/asr/tutorial_transformer.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"<a href=\\\"https://github.com/PaddlePaddle/PaddleSpeech\\\"><img style=\\\"position: absolute; z-index: 999; top: 0; right: 0; border: 0; width: 128px; height: 128px;\\\" src=\\\"https://nosir.github.io/cleave.js/images/right-graphite@2x.png\\\" alt=\\\"Fork me on GitHub\\\"></a>\\n\",\n    \"  \\n\",\n    \"# 使用 Transformer 进行语音识别\\n\",\n    \"\\n\",\n    \"# 0. 视频理解与字幕\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 下载demo视频\\n\",\n    \"!test -f work/source/subtitle_demo1.mp4 || wget -c https://paddlespeech.cdn.bcebos.com/demos/asr_demos/subtitle_demo1.mp4 -P work/source/\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import IPython.display as dp\\n\",\n    \"from IPython.display import HTML\\n\",\n    \"html_str = '''\\n\",\n    \"<video controls width=\\\"600\\\" height=\\\"360\\\" src=\\\"{}\\\">animation</video>\\n\",\n    \"'''.format(\\\"work/source/subtitle_demo1.mp4 \\\")\\n\",\n    \"dp.display(HTML(html_str))\\n\",\n    \"print (\\\"ASR结果为：当我说我可以把三十年的经验变成一个准确的算法他们说不可能当我说我们十个人就能实现对十九个城市变电站七乘二十四小时的实时监管他们说不可能\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"> Demo实现：[https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/automatic_video_subtitiles/](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/demos/automatic_video_subtitiles/)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 1. 前言\\n\",\n    \"\\n\",\n    \"## 1.1 背景知识\\n\",\n    \"语音识别(Automatic Speech Recognition, ASR) 是一项从一段音频中提取出语言文字内容的任务。  \\n\",\n    \"目前该技术已经广泛应用于我们的工作和生活当中，包括生活中使用手机的语音转写，工作上使用的会议记录等等。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/0231a71b0617485d85586d232f65db6379115befdf014068bd90fb15c5786c94\\\"/>\\n\",\n    \"<br>\\n\",\n    \"(出处：DLHLP 李宏毅 语音识别课程PPT)\\n\",\n    \"</div>\\n\",\n    \"<br></br>\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 1.2 发展历史\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"* 早期，生成模型流行阶段：GMM-HMM (上世纪90年代)\\n\",\n    \"* 深度学习爆发初期： DNN，CTC[1] （2006）\\n\",\n    \"* RNN 流行，Attention 提出初期: RNN-T[2]（2013）, DeepSpeech[3] (2014)， DeepSpeech2 [4] (2016)， LAS[5]（2016）\\n\",\n    \"* Attetion is all you need 提出开始[6]: Transformer[6]（2017），Transformer-transducer[7]（2020） Conformer[8] （2020）\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/d6060426bba341a187422803c0f8ac2e2162c5c5422e4070a3425c09f7801379\\\" height=1300, width=1000 />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"目前 Transformer 和 Conformer 是语音识别领域的主流模型，因此本教程采用了 Transformer 作为讲解的主要内容，并在课后作业中步骤了 Conformer 的相关练习。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"# 2. 实战：使用Transformer进行语音识别的流程\\n\",\n    \"\\n\",\n    \"CTC 的输出相互独立，使得每一帧利用上下文的信息的能力不足。\\n\",\n    \"\\n\",\n    \"而 seq2seq（Transformer，Conformer） 的模型采用自回归的解码方式，所以其建模能力更强，但不便于支持流式。\\n\",\n    \"\\n\",\n    \"对于Transformer模型，它的Encoder可以有效对语音特征的上下文进行建模。而它的Decoder具有语言模型的能力，能够将语言模型融合进整个模型中，是真正意义上的端到端模型。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"下面简单介绍下 Transformer 语音识别模型，其主要分为 2 个部分：\\n\",\n    \"\\n\",\n    \"\\t- Encoder：声学特征会首先进入 Encoder，产生高层特征编码。\\n\",\n    \"\\n\",\n    \"    - Decoder：Decoder 利用 Encoder 产生的特征编码解码得到预测结果。\\n\",\n    \"    \\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/13bec64ab9544a3a91205a9633d9f015f2ddb0c3586d49ffb39307daed0229a0\\\" height=40%, width=50%/>\\n\",\n    \"</div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 2.1 准备工作\\n\",\n    \"\\n\",\n    \"### 2.1.1 安装 paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!pip install -U pip paddlepaddle-gpu && pip install paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.1.2 准备工作目录\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!mkdir -p ./work/workspace_asr\\n\",\n    \"%cd ./work/workspace_asr\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"### 2.1.3 获取预训练模型和音频文件\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 获取模型\\n\",\n    \"!test -f transformer.model.tar.gz || wget -nc https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/transformer.model.tar.gz\\n\",\n    \"!tar xzvf transformer.model.tar.gz\\n\",\n    \"\\n\",\n    \"# 获取用于预测的音频文件\\n\",\n    \"!test -f ./data/demo_01_03.wav || wget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P ./data/\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import IPython\\n\",\n    \"IPython.display.Audio('./data/demo_01_03.wav')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 快速体验识别结果\\n\",\n    \"!paddlespeech asr --input ./data/demo_01_03.wav\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.1.4 导入python包\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import paddle\\n\",\n    \"import soundfile\\n\",\n    \"\\n\",\n    \"import warnings\\n\",\n    \"warnings.filterwarnings('ignore')\\n\",\n    \"\\n\",\n    \"from yacs.config import CfgNode\\n\",\n    \"from paddlespeech.audio.transform.spectrogram import LogMelSpectrogramKaldi\\n\",\n    \"from paddlespeech.audio.transform.cmvn import GlobalCMVN\\n\",\n    \"from paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\\n\",\n    \"from paddlespeech.s2t.models.u2 import U2Model\\n\",\n    \"\\n\",\n    \"from matplotlib import pyplot as plt\\n\",\n    \"%matplotlib inline\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.1.5 设置预训练模型的路径\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"config_path = \\\"conf/transformer.yaml\\\" \\n\",\n    \"checkpoint_path = \\\"./exp/transformer/checkpoints/avg_20.pdparams\\\"\\n\",\n    \"decoding_method = \\\"attention\\\"\\n\",\n    \"audio_file = \\\"data/demo_01_03.wav\\\"\\n\",\n    \"\\n\",\n    \"# 读取 conf 文件并结构化\\n\",\n    \"transformer_config = CfgNode(new_allowed=True)\\n\",\n    \"transformer_config.merge_from_file(config_path)\\n\",\n    \"transformer_config.decoding.decoding_method = decoding_method\\n\",\n    \"print(transformer_config)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 2.2 获取特征\\n\",\n    \"\\n\",\n    \"### 2.2.1 音频特征 logfbank\\n\",\n    \"\\n\",\n    \"#### 2.2.1.1 语音特征提取整体流程图\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/54aefbc16dbf4487a7abe38b0210e5dbf1bb0c74fbe4459f94880a06950269f9\\\" height=1200, width=800 />\\n\",\n    \"<br>\\n\",\n    \"由\\\"莊永松、柯上優 DLHLP - HW1 End-to-end Speech Recognition PPT\\\" 修改得\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.2.1.2 logfbank 提取过程简化图\\n\",\n    \"\\n\",\n    \"logfbank 特征提取大致可以分为 3 个步骤：\\n\",\n    \"\\n\",\n    \"1. 语音时域信号经过预加重（信号高频分量补偿），然后进行分帧。\\n\",\n    \"\\n\",\n    \"2. 每一帧数据加窗后经过离散傅立叶变换（DFT）得到频谱图。\\n\",\n    \"\\n\",\n    \"3. 将频谱图的特征经过 Mel 滤波器得到 logmel fbank 特征。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/08f7ccecc848495599c350aa2c440071b818ba0465734dd29701a2ff149f0a8c\\\"/>\\n\",\n    \"<br>\\n\",\n    \"由\\\"DLHLP 李宏毅 语音识别课程 PPT\\\" 修改得\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.2.1.3 CMVN 计算过程\\n\",\n    \"\\n\",\n    \"对于所有获取的特征，模型在使用前会使用 CMVN 的方式进行归一化\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"  <img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/46df63199d88481d9a2713a45ce63d00220e8ac42f9940e886282017758b54bf\\\"/>\\n\",\n    \"</div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.2.2 构建音频特征提取对象\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 构建 logmel 特征\\n\",\n    \"logmel_kaldi= LogMelSpectrogramKaldi(\\n\",\n    \"            fs= 16000,\\n\",\n    \"            n_mels= 80,\\n\",\n    \"            n_shift= 160,\\n\",\n    \"            win_length= 400,\\n\",\n    \"            dither= True)\\n\",\n    \"\\n\",\n    \"# 特征减均值除以方差\\n\",\n    \"cmvn = GlobalCMVN(\\n\",\n    \"    cmvn_path=\\\"data/mean_std.json\\\"\\n\",\n    \")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.2.3 提取音频的特征\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"array, _ = soundfile.read(audio_file, dtype=\\\"int16\\\")\\n\",\n    \"array = logmel_kaldi(array, train=False)\\n\",\n    \"audio_feature_i = cmvn(array)\\n\",\n    \"audio_len = audio_feature_i.shape[0]\\n\",\n    \"\\n\",\n    \"audio_len = paddle.to_tensor(audio_len)\\n\",\n    \"audio_feature = paddle.to_tensor(audio_feature_i, dtype='float32')\\n\",\n    \"audio_feature = paddle.unsqueeze(audio_feature, axis=0)\\n\",\n    \"print (audio_feature.shape)\\n\",\n    \"\\n\",\n    \"plt.figure()\\n\",\n    \"plt.imshow(audio_feature_i.T, origin='lower')\\n\",\n    \"plt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 2.3 使用模型获得结果\\n\",\n    \"\\n\",\n    \"### 2.3.1 Transofomer 语音识别模型的结构\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"Transformer 模型主要由 2 个部分组成，包括 Transformer Encoder 和 Transformer Decoder。 \\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/1edcd4ef683c4ef981b375ab8df388b40e3afc5f439f47f1a6f2f230908b63b1\\\" height=50%, width=50%  />\\n\",\n    \"</div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.3.2 Transformer Encoder\\n\",\n    \"\\n\",\n    \"Transformer encoder 主要是对音频的原始特征（这里原始特征使用的是 80 维 logfbank）进行特征编码，其输入是 logfbank，输出是特征编码。包含：\\n\",\n    \"\\n\",\n    \"* 位置编码（position encoding）\\n\",\n    \"* 降采样模块(subsampling embedding)： 由2层降采样的 CNN 构成。\\n\",\n    \"* Transformer Encoder Layer  ： \\n\",\n    \"    * self-attention： 主要特点是Q(query), K(key)和V(value)都是用了相同的值\\n\",\n    \"    * Feed forward Layer： 由两层全连接层构建，其特点是保持了输入和输出的特征维度是一致的。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"#### 2.3.2.1 Self-Attention\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/72ffd9016d3841149723be2dde2a48c495ce8a95358946bca3736053812c788c\\\" height=50%, width=50%  />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"其主要步骤可以分为三步：\\n\",\n    \"\\n\",\n    \"1. `Q` 和 `K` 的向量通过求内积的方式计算相似度，经过 scale 和 softmax 后，获得每个 `Q` 和所有`K` 之间的 score。\\n\",\n    \"\\n\",\n    \"2. 将每个 `Q` 和所有 `K` 之间的 score 和 `V` 进行相乘，再将相乘后的结果求和，得到 self-attetion 的输出向量。\\n\",\n    \"\\n\",\n    \"3. 使用多个 Attetion 模块均进行第一步和第二步，并将最后的输出向量进行合并，得到最终 Multi-Head Self-Attention 的输出。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/fcdef1992e6d4c909403d603062d09e4d5adaff0226e4367b35d27aea2da1303\\\" height=30%, width=30%  />\\n\",\n    \"</div>\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.3.3 Transformer Decoder\\n\",\n    \"\\n\",\n    \"Transformer 的 Decoder 用于获取最后的输出结果。其结构和 Encoder 有一定的相似性，也具有 Attention 模块和 Feed forward layer。\\n\",\n    \"主要的不同点有 2 个：\\n\",\n    \"1. Decoder 采用的是一种自回归的方式进行解码。\\n\",\n    \"2. Decoder 在 Multi-head self-attention 和 Feed forward layer 模块之间增加了一层 Multi-head cross-attention 层用于获取 Encoder 得到的特征编码。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"#### 2.3.3.1 Masked Multi-head Self-Attention\\n\",\n    \"细心的同学可能发现了，Decoder 的一个 Multi-head self-attention 前面有一个 mask 。增加了这个 mask 的原因在于进行 Decoder 训练的时候，Decoder 的输入是一句完整的句子，而不是像预测这样一步步输入句子的前缀。\\n\",\n    \"\\n\",\n    \"为了模拟预测的过程，Decoder 训练的时候需要用 mask 遮住句子。 例如 `T=1` 时，就要 mask 输入中除第一个字符以外其他的字符，`T=2` 的时候则需要 mask 除前两个字符以外的其余字符。\\n\",\n    \"\\n\",\n    \"#### 2.3.3.2 Cross Attention\\n\",\n    \"\\n\",\n    \"Decoder 在每一步的解码过程中，都会利用 Encoder 的输出的特征编码进行 cross-attention。\\n\",\n    \"\\n\",\n    \"其中Decoder会将自回结果的编码作为 Attention 中的 `Q` ，而 Encoder 输出的特征编码作为 `K` 和 `V` 来完成 attetion 计算，从而利用 Encoder 提取的音频信息。\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/8e93122eb65344ea885a8af9014de4569b7c9c9f55aa45f7ac17ba2d0b0af260\\\" hegith=30%, width=30% />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"#### 2.3.3.3 Decoder的自回归解码 \\n\",\n    \"\\n\",\n    \"其采用了一种自回归的结构，即 Decoder 的上一个时间点的输出会作为下一个时间点的输入。\\n\",\n    \"\\n\",\n    \"另外，计算的过程中，Decoder 会利用 Encoder 的输出信息。\\n\",\n    \"\\n\",\n    \"如果使用贪心（greedy）的方式，Decoder 的解码过程如下：\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/0acaf9f243304120832018b83a4b7c67b8d578f710ce4eeba6062ab9661ef9e7\\\" hegith=50%, width=50% />\\n\",\n    \"</div>\\n\",\n    \"\\n\",\n    \"使用 greedy 模式解码比较简单，但是很有可能会在解码过程中丢失整体上效果更好的解码结果。\\n\",\n    \"\\n\",\n    \"因此我们实际使用的是 beam search 方式的解码，beam search 模式下的 decoder 的解码过程如下：\\n\",\n    \"\\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/367f8f7cd4b4451ab45dd883045c500d941f0d235fca4ad2a3ccb925ec59aea2\\\" hegith=50%, width=50%/>\\n\",\n    \"</div>\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 2.3.4 模型训练\\n\",\n    \"\\n\",\n    \"模型训练同时使用了 CTC 损失和 cross entropy 交叉熵损失进行损失函数的计算。\\n\",\n    \"\\n\",\n    \"其中 Encoder 输出的特征直接进入 CTC Decoder 得到 CTC 损失。\\n\",\n    \"\\n\",\n    \"而 Decoder 的输出使用 cross entropy 损失。\\n\",\n    \" \\n\",\n    \"<div align=center>\\n\",\n    \"<img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/fe1d3864f18f4df0a9ab3df8dc4e361a693250b387344273952315ca14d30732\\\"/>\\n\",\n    \"  <br>\\n\",\n    \"  (由\\\"莊永松、柯上優 DLHLP - HW1 End-to-end Speech Recognition PPT\\\" 修改得)\\n\",\n    \"</div>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"\\n\",\n    \"### 2.3.5 构建Transformer模型\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"model_conf = transformer_config.model\\n\",\n    \"# input_dim 存储的是特征的纬度\\n\",\n    \"model_conf.input_dim = 80\\n\",\n    \"# output_dim 存储的字表的长度\\n\",\n    \"model_conf.output_dim = 4233 \\n\",\n    \"print (\\\"model_conf\\\", model_conf)\\n\",\n    \"model = U2Model.from_config(model_conf)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"  \\n\",\n    \"### 2.3.6 加载预训练的模型\\n\",\n    \"      \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"model_dict = paddle.load(checkpoint_path)\\n\",\n    \"model.set_state_dict(model_dict)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"\\n\",\n    \"### 2.3.7 进行预测\\n\",\n    \"      \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"decoding_config = transformer_config.decoding\\n\",\n    \"text_feature = TextFeaturizer(unit_type='char',\\n\",\n    \"                            vocab=transformer_config.collator.vocab_filepath)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"result_transcripts = model.decode(\\n\",\n    \"            audio_feature,\\n\",\n    \"            audio_len,\\n\",\n    \"            text_feature=text_feature,\\n\",\n    \"            decoding_method=decoding_config.decoding_method,\\n\",\n    \"            beam_size=decoding_config.beam_size,\\n\",\n    \"            ctc_weight=decoding_config.ctc_weight,\\n\",\n    \"            decoding_chunk_size=decoding_config.decoding_chunk_size,\\n\",\n    \"            num_decoding_left_chunks=decoding_config.num_decoding_left_chunks,\\n\",\n    \"            simulate_streaming=decoding_config.simulate_streaming)\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"print (\\\"预测结果对应的token id为:\\\")\\n\",\n    \"print (result_transcripts[1][0])\\n\",\n    \"print (\\\"预测结果为:\\\")\\n\",\n    \"print (result_transcripts[0][0])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 3. 作业 \\n\",\n    \"1. 使用开发模式安装 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech)  \\n\",\n    \"环境要求：docker, Ubuntu 16.04，root user。  \\n\",\n    \"参考安装方法：[使用Docker安装paddlespeech](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md#hard-get-the-full-funciton-on-your-mechine)\\n\",\n    \"\\n\",\n    \"2. 跑通 example/aishell/asr1 中的 conformer 模型，完成训练和预测。 \\n\",\n    \"\\n\",\n    \"3. 按照 example 的格式使用自己的数据集训练 ASR 模型。      \\n\",\n    \"\\n\",\n    \"# 4. 关注 PaddleSpeech\\n\",\n    \"\\n\",\n    \"请关注我们的 [Github Repo](https://github.com/PaddlePaddle/PaddleSpeech/)，非常欢迎加入以下微信群参与讨论：\\n\",\n    \"- 扫描二维码\\n\",\n    \"- 添加运营小姐姐微信\\n\",\n    \"- 通过后回复【语音】\\n\",\n    \"- 系统自动邀请加入技术群\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/87bc7da42bcc401bae41d697f13d8b362bfdfd7198f14096b6d46b4004f09613\\\" width=\\\"300\\\" height=\\\"300\\\" ></center>\\n\",\n    \"\\n\",\n    \"# 5. 参考文献\\n\",\n    \"\\n\",\n    \"[1] Graves A, Fernández S, Gomez F, et al. Connectionist temporal classification: labelling unsegmented sequence data with recurrent neural networks[C]//Proceedings of the 23rd international conference on Machine learning. 2006: 369-376.\\n\",\n    \"\\n\",\n    \"[2] Graves A, Mohamed A, Hinton G. Speech recognition with deep recurrent neural networks[C]//2013 IEEE international conference on acoustics, speech and signal processing. Ieee, 2013: 6645-6649.\\n\",\n    \"\\n\",\n    \"[3] Hannun A, Case C, Casper J, et al. Deep speech: Scaling up end-to-end speech recognition[J]. arXiv preprint arXiv:1412.5567, 2014.\\n\",\n    \"\\n\",\n    \"[4] Amodei D, Ananthanarayanan S, Anubhai R, et al. Deep speech 2: End-to-end speech recognition in english and mandarin[C]//International conference on machine learning. PMLR, 2016: 173-182.\\n\",\n    \"\\n\",\n    \"[5] Chan W, Jaitly N, Le Q, et al. Listen, attend and spell: A neural network for large vocabulary conversational speech recognition[C]//2016 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2016: 4960-4964.\\n\",\n    \"\\n\",\n    \"[6] Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need[C]//Advances in neural information processing systems. 2017: 5998-6008.\\n\",\n    \"\\n\",\n    \"[7] Zhang Q, Lu H, Sak H, et al. Transformer transducer: A streamable speech recognition model with transformer encoders and rnn-t loss[C]//ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020: 7829-7833.\\n\",\n    \"\\n\",\n    \"[8] Gulati A, Qin J, Chiu C C, et al. Conformer: Convolution-augmented transformer for speech recognition[J]. arXiv preprint arXiv:2005.08100, 2020.\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"py35-paddle1.2.0\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.4\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "docs/tutorial/cls/cls_tutorial.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"<a href=\\\"https://github.com/PaddlePaddle/PaddleSpeech\\\"><img style=\\\"position: absolute; z-index: 999; top: 0; right: 0; border: 0; width: 128px; height: 128px;\\\" src=\\\"https://nosir.github.io/cleave.js/images/right-graphite@2x.png\\\" alt=\\\"Fork me on GitHub\\\"></a>\\n\",\n    \"\\n\",\n    \"# 1. 识别声音\\n\",\n    \"  \\n\",\n    \" 通过听取声音，人的大脑会获取到大量的信息，其中的一个场景是识别和归类，如：识别熟悉的亲人或朋友的声音、识别不同乐器发出的声音和识别不同环境产生的声音，等等。\\n\",\n    \"\\n\",\n    \" 我们可以根据不同声音的特征（频率，音色等）进行区分，这种区分行为的本质，就是对声音进行分类。</font>\\n\",\n    \"\\n\",\n    \"声音分类根据用途还可以继续细分：\\n\",\n    \"\\n\",\n    \"* 副语言识别：说话人识别（Speaker Recognition）, 情绪识别（Speech Emotion Recognition），性别分类（Speaker gender classification）\\n\",\n    \"* 音乐识别：音乐流派分类（Music Genre Classification）\\n\",\n    \"* 场景识别：环境声音分类（Environmental Sound Classification）\\n\",\n    \"* 声音事件检测：各个环境中的声学事件检测\\n\",\n    \" \\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/2b3fdd6dd3b24360ab7448e1aa47bb93d7610aaf79fd4f25aa0a8ff131493261\\\"></center>\\n\",\n    \"<center>图片来源：http://speech.ee.ntu.edu.tw/~tlkagk/courses/DLHLP20/Speaker%20(v3).pdf</center>\\n\",\n    \"\\n\",\n    \"## 1.1 Audio Tagging\\n\",\n    \"使用 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech) 的预训练模型对一段音频做实时的声音检测，结果如下视频所示。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%%HTML\\n\",\n    \"<center><video width=\\\"800\\\" controls>\\n\",\n    \"  <source src=\\\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/audio_tagging_demo.mp4\\\" type=\\\"video/mp4\\\">\\n\",\n    \"</video></center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 2. 音频和特征提取\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 环境准备：安装paddlespeech\\n\",\n    \"!pip install -U pip paddlepaddle-gpu && pip install paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import warnings\\n\",\n    \"warnings.filterwarnings(\\\"ignore\\\")\\n\",\n    \"import IPython\\n\",\n    \"import numpy as np\\n\",\n    \"import matplotlib.pyplot as plt\\n\",\n    \"%matplotlib inline\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"\\n\",\n    \"\\n\",\n    \"## 2.1 数字音频\\n\",\n    \"\\n\",\n    \"### 2.1.1 声音信号和音频文件\\n\",\n    \"  \\n\",\n    \"下面通过一个例子观察音频文件的波形，直观地了解数字音频文件的包含的内容。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 获取示例音频\\n\",\n    \"!test -f ./dog.wav || wget https://paddlespeech.cdn.bcebos.com/PaddleAudio/dog.wav\\n\",\n    \"IPython.display.Audio('./dog.wav')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from paddlespeech.audio.backends import load\\n\",\n    \"data, sr = load(file='./dog.wav', mono=True, dtype='float32')  # 单通道，float32音频样本点\\n\",\n    \"print('wav shape: {}'.format(data.shape))\\n\",\n    \"print('sample rate: {}'.format(sr))\\n\",\n    \"\\n\",\n    \"# 展示音频波形\\n\",\n    \"plt.figure()\\n\",\n    \"plt.plot(data)\\n\",\n    \"plt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!paddlespeech cls --input ./dog.wav\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.2 音频特征提取\\n\",\n    \"\\n\",\n    \"### 2.2.1 短时傅里叶变换\\n\",\n    \"\\n\",\n    \"  对于一段音频，一般会将整段音频进行分帧，每一帧含有一定长度的信号数据，一般使用 `25ms`，帧与帧之间的移动距离称为帧移，一般使用 `10ms`，然后对每一帧的信号数据加窗后，进行短时傅立叶变换（STFT）得到时频谱。\\n\",\n    \"  \\n\",\n    \"通过按照上面的对一段音频进行分帧后，我们可以用傅里叶变换来分析每一帧信号的频率特性。将每一帧的频率信息拼接后，可以获得该音频不同时刻的频率特征——Spectrogram，也称作为语谱图。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/8ef98c95137442a797c9204e1108e585facf7124ee964edc845f2c849a39347f\\\"></center>\\n\",\n    \"<center>图片参考：DLHLP 李宏毅 语音识别课程PPT；https://www.shong.win/2016/04/09/fft/</center>\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"下面例子采用 `paddle.signal.stft` 演示如何提取示例音频的频谱特征，并进行可视化：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import paddle\\n\",\n    \"import numpy as np\\n\",\n    \"\\n\",\n    \"data, sr = load(file='./dog.wav', sr=32000, mono=True, dtype='float32')\\n\",\n    \"x = paddle.to_tensor(data)\\n\",\n    \"n_fft = 1024\\n\",\n    \"win_length = 1024\\n\",\n    \"hop_length = 320\\n\",\n    \"\\n\",\n    \"# [D, T]\\n\",\n    \"spectrogram = paddle.signal.stft(x, n_fft=n_fft, win_length=win_length, hop_length=hop_length, onesided=True)  \\n\",\n    \"print('spectrogram.shape: {}'.format(spectrogram.shape))\\n\",\n    \"print('spectrogram.dtype: {}'.format(spectrogram.dtype))\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"spec = np.log(np.abs(spectrogram.numpy())**2)\\n\",\n    \"plt.figure()\\n\",\n    \"plt.title(\\\"Log Power Spectrogram\\\")\\n\",\n    \"plt.imshow(spec[:100, :], origin='lower')\\n\",\n    \"plt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 2.2.2 LogFBank\\n\",\n    \"\\n\",\n    \"研究表明，人类对声音的感知是非线性的，随着声音频率的增加，人对更高频率的声音的区分度会不断下降。\\n\",\n    \"\\n\",\n    \"例如同样是相差 500Hz 的频率，一般人可以轻松分辨出声音中 500Hz 和 1,000Hz 之间的差异，但是很难分辨出 10,000Hz 和 10,500Hz 之间的差异。\\n\",\n    \"\\n\",\n    \"因此，学者提出了梅尔频率，在该频率计量方式下，人耳对相同数值的频率变化的感知程度是一样的。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/18fac30a88bd46c88a6a8bfdec580b42ff3f6b6ef0b54bb68cb1c217f31c18d7\\\" width=500></center>\\n\",\n    \"<center>图片来源：https://www.researchgate.net/figure/Curve-relationship-between-frequency-signal-with-its-mel-frequency-scale-Algorithm-1_fig3_221910348</center>\\n\",\n    \"\\n\",\n    \"关于梅尔频率的计算，其会对原始频率的低频的部分进行较多的采样，从而对应更多的频率，而对高频的声音进行较少的采样，从而对应较少的频率。使得人耳对梅尔频率的低频和高频的区分性一致。\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/7762cef8fa0e4b10b7f566a0e705609af7704f6a1d2b4e8bac44abe724f9c866\\\" ></center>\\n\",\n    \"<center>图片来源：https://ww2.mathworks.cn/help/audio/ref/mfcc.html</center>\\n\",\n    \"\\n\",\n    \"Mel Fbank 的计算过程如下，而我们一般都是使用 LogFBank 作为识别特征：\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/e7e6c2e221f642af9e618de768dada99258ec5d97b314035b21dd3e217941a67\\\" ></center>\\n\",\n    \"<center>图片来源：https://ww2.mathworks.cn/help/audio/ref/mfcc.html</center>\\n\",\n    \"\\n\",\n    \"<br></br>\\n\",\n    \"下面例子采用 `paddlespeech.audio.transform.spectrogram.LogMelSpectrogram` 演示如何提取示例音频的 LogFBank:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from paddlespeech.audio.transform.spectrogram import LogMelSpectrogram\\n\",\n    \"\\n\",\n    \"f_min=50.0\\n\",\n    \"f_max=14000.0\\n\",\n    \"n_mels=64\\n\",\n    \"\\n\",\n    \"#   - sr: 音频文件的采样率。\\n\",\n    \"#   - n_fft: FFT样本点个数。\\n\",\n    \"#   - hop_length: 音频帧之间的间隔。\\n\",\n    \"#   - win_length: 窗函数的长度。\\n\",\n    \"#   - window: 窗函数种类。\\n\",\n    \"#   - n_mels: 梅尔刻度数量。\\n\",\n    \"feature_extractor2 = LogMelSpectrogram(\\n\",\n    \"    sr=sr, \\n\",\n    \"    n_fft=n_fft, \\n\",\n    \"    hop_length=hop_length, \\n\",\n    \"    win_length=win_length, \\n\",\n    \"    window='hann', \\n\",\n    \"    f_min=f_min,\\n\",\n    \"    f_max=f_max,\\n\",\n    \"    n_mels=n_mels)\\n\",\n    \"\\n\",\n    \"x = paddle.to_tensor(data).unsqueeze(0)     # [B, L]\\n\",\n    \"log_fbank = feature_extractor2(x) # [B, D, T]\\n\",\n    \"log_fbank = log_fbank.squeeze(0) # [D, T]\\n\",\n    \"print('log_fbank.shape: {}'.format(log_fbank.shape))\\n\",\n    \"\\n\",\n    \"plt.figure()\\n\",\n    \"plt.imshow(log_fbank.numpy(), origin='lower')\\n\",\n    \"plt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.3 声音分类方法\\n\",\n    \"\\n\",\n    \"### 2.3.1 传统机器学习方法\\n\",\n    \"在传统的声音和信号的研究领域中，声音特征是一类包含丰富先验知识的手工特征，如频谱图、梅尔频谱和梅尔频率倒谱系数等。\\n\",\n    \"  \\n\",\n    \"因此在一些分类的应用上，可以采用传统的机器学习方法例如决策树、svm和随机森林等方法。\\n\",\n    \"  \\n\",\n    \"一个典型的应用案例是：男声和女声分类。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/943905088eef48b48e4b94f7ff4c475060937868ca474b61bdcc55fc155b283e\\\" width=800></center>\\n\",\n    \"<center>图片来源：https://journals.plos.org/plosone/article/figure?id=10.1371/journal.pone.0179403.g001</center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 2.3.2 深度学习方法\\n\",\n    \"传统机器学习方法可以捕捉声音特征的差异（例如男声和女声的声音在音高上往往差异较大）并实现分类任务。\\n\",\n    \"  \\n\",\n    \"而深度学习方法则可以突破特征的限制，更灵活的组网方式和更深的网络层次，可以更好地提取声音的高层特征，从而获得更好的分类指标。\\n\",\n    \"\\n\",\n    \"随着深度学习算法的快速发展和在分类任务上的优异表现，当下流行的声音分类模型无一不是采用深度学习网络搭建而成的，如 [AudioCLIP[1]](https://arxiv.org/pdf/2106.13043v1.pdf)、[PANNs[2]](https://arxiv.org/pdf/1912.10211v5.pdf) 和 [Audio Spectrogram Transformer[3]](https://arxiv.org/pdf/2104.01778v3.pdf) 等。\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/bc2c0352c4124b1d866696fd5d8165efbdca5d60f21648729258b62981ef600a\\\" ></center>\\n\",\n    \"<center>图片来源：https://towardsdatascience.com/audio-deep-learning-made-simple-sound-classification-step-by-step-cebc936bbe5</center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 2.3.3 Pretrain + Finetune\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"在声音分类和声音检测的场景中（如环境声音分类、情绪识别和音乐流派分类等）由于可获取的据集有限，且语音数据标注的成本高，用户可以收集到的数据集体量往往较小，这种数据量稀少的情况对于模型训练是非常不利的。\\n\",\n    \"\\n\",\n    \"预训练模型能够减少领域数据的需求量，并达到较高的识别准确率。在CV和NLP领域中，有诸如 MobileNet、VGG19、YOLO、BERT 和 ERNIE 等开源的预训练模型，在图像检测、图像分类、文本分类和文本生成等各自领域内的任务中，使用预训练模型在下游任务的数据集上进行 finetune ，往往可以更快和更容易获得较好的效果和指标。\\n\",\n    \"\\n\",\n    \"相较于 CV 领域的 ImageNet 数据集，谷歌在 2017 年开放了一个大规模的音频数据集 [AudioSet[4]](https://ieeexplore.ieee.org/document/7952261)，它是目前最大的用于音频分类任务的数据集。该数据集包含了 632 类的音频类别以及 2084320 条人工标记的每段 10 秒长度的声音剪辑片段（包括 527 个标签），数据总时长为 5,800 小时。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/334a00c3ca4d4feb90982bb882897eeae2c82a6521b54b46bc64cb68289cdd92\\\" width=480></center>\\n\",\n    \"<center>图片来源：https://research.google.com/audioset/ontology/index.html</center>\\n\",\n    \"  \\n\",\n    \"`PANNs`([PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition[2]](https://arxiv.org/pdf/1912.10211.pdf))是基于 AudioSet 数据集训练的声音分类/识别的模型，其中`PANNs-CNN14`在测试集上取得了较好的效果：mAP 为 0.431，AUC 为 0.973，d-prime 为 2.732，经过预训练后，该模型可以用于提取音频的 embbedding ，适合用于声音分类和声音检测等下游任务。本示例将使用 `PANNs` 的预训练模型 Finetune 完成声音分类的任务。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/812d3268cc5b46c88bd23fb9ebaa89196081a14409724b4c87e96498c78c930e\\\" width=480></center>\\n\",\n    \"  \\n\",\n    \"本教程选取 `PANNs` 中的预训练模型 `cnn14` 作为 backbone，用于提取声音的深层特征，`SoundClassifer`创建下游的分类网络，实现对输入音频的分类。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/1954041f63ae49e2bc1f858ca43433140dfc70a513a8479aa9eb5ca8841cb2ac\\\" width=600></center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 3. 实践：环境声音分类\\n\",\n    \"\\n\",\n    \"## 3.1 数据集准备\\n\",\n    \"\\n\",\n    \"此课程选取了[ESC-50: Dataset for Environmental Sound Classification[5]](https://github.com/karolpiczak/ESC-50) 数据集作为示例。\\n\",\n    \"  \\n\",\n    \"ESC-50是一个包含有 2000 个带标签的环境声音样本，音频样本采样率为 44,100Hz 的单通道音频文件，所有样本根据标签被划分为 50 个类别，每个类别有 40 个样本。\\n\",\n    \"\\n\",\n    \"音频样本可分为 5 个主要类别：\\n\",\n    \"  - 动物声音（Animals）\\n\",\n    \"  - 自然界产生的声音和水声（Natural soundscapes & water sounds）\\n\",\n    \"  - 人类发出的非语言声音（Human, non-speech sounds）\\n\",\n    \"  - 室内声音（Interior/domestic sounds）\\n\",\n    \"  - 室外声音和一般噪声（Exterior/urban noises）。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"ESC-50 数据集中的提供的 `meta/esc50.csv` 文件包含的部分信息如下：\\n\",\n    \"```\\n\",\n    \"   filename,fold,target,category,esc10,src_file,take\\n\",\n    \"   1-100038-A-14.wav,1,14,chirping_birds,False,100038,A\\n\",\n    \"   1-100210-A-36.wav,1,36,vacuum_cleaner,False,100210,A\\n\",\n    \"   1-101296-A-19.wav,1,19,thunderstorm,False,101296,A\\n\",\n    \"   ...\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"  - filename: 音频文件名字。 \\n\",\n    \"  - fold: 数据集自身提供的N-Fold验证信息，用于切分训练集和验证集。\\n\",\n    \"  - target: 标签数值。\\n\",\n    \"  - category: 标签文本信息。\\n\",\n    \"  - esc10: 文件是否为ESC-10的数据集子集。\\n\",\n    \"  - src_file: 原始音频文件前缀。\\n\",\n    \"  - take: 原始文件的截取段落信息。\\n\",\n    \"  \\n\",\n    \"在此声音分类的任务中，我们将`target`作为训练过程的分类标签。\\n\",\n    \"\\n\",\n    \"### 3.1.1 数据集初始化\\n\",\n    \"调用以下代码自动下载并读取数据集音频文件，创建训练集和验证集。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from paddlespeech.audio.datasets import ESC50\\n\",\n    \"\\n\",\n    \"train_ds = ESC50(mode='train', sample_rate=sr)\\n\",\n    \"dev_ds = ESC50(mode='dev', sample_rate=sr)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 3.1.2 特征提取\\n\",\n    \"通过下列代码，用 `paddlespeech.audio.transform.spectrogram.LogMelSpectrogram` 初始化一个音频特征提取器，在训练过程中实时提取音频的 LogFBank 特征，其中主要的参数如下：  \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"feature_extractor = LogMelSpectrogram(\\n\",\n    \"    sr=sr, \\n\",\n    \"    n_fft=n_fft, \\n\",\n    \"    hop_length=hop_length, \\n\",\n    \"    win_length=win_length, \\n\",\n    \"    window='hann', \\n\",\n    \"    f_min=f_min,\\n\",\n    \"    f_max=f_max,\\n\",\n    \"    n_mels=n_mels)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 3.2 模型\\n\",\n    \"\\n\",\n    \"### 3.2.1 选取预训练模型\\n\",\n    \"\\n\",\n    \"选取`cnn14`作为 backbone，用于提取音频的特征：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from paddlespeech.cls.models import cnn14\\n\",\n    \"backbone = cnn14(pretrained=True, extract_embedding=True)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 3.2.2 构建分类模型\\n\",\n    \"\\n\",\n    \"`SoundClassifer`接收`cnn14`作为backbone模型，并创建下游的分类网络：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import paddle.nn as nn\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"class SoundClassifier(nn.Layer):\\n\",\n    \"\\n\",\n    \"    def __init__(self, backbone, num_class, dropout=0.1):\\n\",\n    \"        super().__init__()\\n\",\n    \"        self.backbone = backbone\\n\",\n    \"        self.dropout = nn.Dropout(dropout)\\n\",\n    \"        self.fc = nn.Linear(self.backbone.emb_size, num_class)\\n\",\n    \"\\n\",\n    \"    def forward(self, x):\\n\",\n    \"        x = x.unsqueeze(1)\\n\",\n    \"        x = self.backbone(x)\\n\",\n    \"        x = self.dropout(x)\\n\",\n    \"        logits = self.fc(x)\\n\",\n    \"\\n\",\n    \"        return logits\\n\",\n    \"\\n\",\n    \"model = SoundClassifier(backbone, num_class=len(ESC50.label_list))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 3.3 Finetune\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"1. 创建 DataLoader \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"batch_size = 16\\n\",\n    \"train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True)\\n\",\n    \"dev_loader = paddle.io.DataLoader(dev_ds, batch_size=batch_size,)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"2. 定义优化器和 Loss\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"optimizer = paddle.optimizer.Adam(learning_rate=1e-4, parameters=model.parameters())\\n\",\n    \"criterion = paddle.nn.loss.CrossEntropyLoss()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"3. 启动模型训练 \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from paddlespeech.audio.utils import logger\\n\",\n    \"\\n\",\n    \"epochs = 20\\n\",\n    \"steps_per_epoch = len(train_loader)\\n\",\n    \"log_freq = 10\\n\",\n    \"eval_freq = 10\\n\",\n    \"\\n\",\n    \"for epoch in range(1, epochs + 1):\\n\",\n    \"    model.train()\\n\",\n    \"\\n\",\n    \"    avg_loss = 0\\n\",\n    \"    num_corrects = 0\\n\",\n    \"    num_samples = 0\\n\",\n    \"    for batch_idx, batch in enumerate(train_loader):\\n\",\n    \"        waveforms, labels = batch\\n\",\n    \"        feats = feature_extractor(waveforms)\\n\",\n    \"        feats = paddle.transpose(feats, [0, 2, 1])  # [B, N, T] -> [B, T, N]\\n\",\n    \"        logits = model(feats)\\n\",\n    \"\\n\",\n    \"        loss = criterion(logits, labels)\\n\",\n    \"        loss.backward()\\n\",\n    \"        optimizer.step()\\n\",\n    \"        if isinstance(optimizer._learning_rate,\\n\",\n    \"                      paddle.optimizer.lr.LRScheduler):\\n\",\n    \"            optimizer._learning_rate.step()\\n\",\n    \"        optimizer.clear_grad()\\n\",\n    \"\\n\",\n    \"        # Calculate loss\\n\",\n    \"        avg_loss += float(loss)\\n\",\n    \"\\n\",\n    \"        # Calculate metrics\\n\",\n    \"        preds = paddle.argmax(logits, axis=1)\\n\",\n    \"        num_corrects += (preds == labels).numpy().sum()\\n\",\n    \"        num_samples += feats.shape[0]\\n\",\n    \"\\n\",\n    \"        if (batch_idx + 1) % log_freq == 0:\\n\",\n    \"            lr = optimizer.get_lr()\\n\",\n    \"            avg_loss /= log_freq\\n\",\n    \"            avg_acc = num_corrects / num_samples\\n\",\n    \"\\n\",\n    \"            print_msg = 'Epoch={}/{}, Step={}/{}'.format(\\n\",\n    \"                epoch, epochs, batch_idx + 1, steps_per_epoch)\\n\",\n    \"            print_msg += ' loss={:.4f}'.format(avg_loss)\\n\",\n    \"            print_msg += ' acc={:.4f}'.format(avg_acc)\\n\",\n    \"            print_msg += ' lr={:.6f}'.format(lr)\\n\",\n    \"            logger.train(print_msg)\\n\",\n    \"\\n\",\n    \"            avg_loss = 0\\n\",\n    \"            num_corrects = 0\\n\",\n    \"            num_samples = 0\\n\",\n    \"\\n\",\n    \"    if epoch % eval_freq == 0 and batch_idx + 1 == steps_per_epoch:\\n\",\n    \"        model.eval()\\n\",\n    \"        num_corrects = 0\\n\",\n    \"        num_samples = 0\\n\",\n    \"        with logger.processing('Evaluation on validation dataset'):\\n\",\n    \"            for batch_idx, batch in enumerate(dev_loader):\\n\",\n    \"                waveforms, labels = batch\\n\",\n    \"                feats = feature_extractor(waveforms)\\n\",\n    \"                feats = paddle.transpose(feats, [0, 2, 1])\\n\",\n    \"                \\n\",\n    \"                logits = model(feats)\\n\",\n    \"\\n\",\n    \"                preds = paddle.argmax(logits, axis=1)\\n\",\n    \"                num_corrects += (preds == labels).numpy().sum()\\n\",\n    \"                num_samples += feats.shape[0]\\n\",\n    \"\\n\",\n    \"        print_msg = '[Evaluation result]'\\n\",\n    \"        print_msg += ' dev_acc={:.4f}'.format(num_corrects / num_samples)\\n\",\n    \"\\n\",\n    \"        logger.eval(print_msg)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 3.4 音频预测\\n\",\n    \"\\n\",\n    \"执行预测，获取 Top K 分类结果：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"top_k = 10\\n\",\n    \"wav_file = './dog.wav'\\n\",\n    \"\\n\",\n    \"waveform, _ = load(wav_file, sr)\\n\",\n    \"feats = feature_extractor(paddle.to_tensor(paddle.to_tensor(waveform).unsqueeze(0)))\\n\",\n    \"feats = paddle.transpose(feats, [0, 2, 1])  # [B, N, T] -> [B, T, N]\\n\",\n    \"print(feats.shape)\\n\",\n    \"\\n\",\n    \"logits = model(feats)\\n\",\n    \"probs = nn.functional.softmax(logits, axis=1).numpy()\\n\",\n    \"\\n\",\n    \"sorted_indices = probs[0].argsort()\\n\",\n    \"\\n\",\n    \"msg = f'[{wav_file}]\\\\n'\\n\",\n    \"for idx in sorted_indices[-1:-top_k-1:-1]:\\n\",\n    \"    msg += f'{ESC50.label_list[idx]}: {probs[0][idx]:.5f}\\\\n'\\n\",\n    \"print(msg)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 4. 作业\\n\",\n    \"1. 使用开发模式安装 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech)  \\n\",\n    \"环境要求：docker, Ubuntu 16.04，root user。  \\n\",\n    \"参考安装方法：[使用Docker安装paddlespeech](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md#hard-get-the-full-funciton-on-your-mechine)\\n\",\n    \"1. 在 [MusicSpeech](http://marsyas.info/downloads/datasets.html) 数据集上完成 music/speech 二分类。  \\n\",\n    \"2. 在 [GTZAN Genre Collection](http://marsyas.info/downloads/datasets.html) 音乐分类数据集上利用 PANNs 预训练模型实现音乐类别十分类。\\n\",\n    \"\\n\",\n    \"关于如何自定义分类数据集，请参考文档 [PaddleSpeech/docs/source/cls/custom_dataset.md](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/cls/custom_dataset.md)\\n\",\n    \"\\n\",\n    \"# 5. 关注 PaddleSpeech\\n\",\n    \"\\n\",\n    \"请关注我们的 [Github Repo](https://github.com/PaddlePaddle/PaddleSpeech/)，非常欢迎加入以下微信群参与讨论：\\n\",\n    \"- 扫描二维码\\n\",\n    \"- 添加运营小姐姐微信\\n\",\n    \"- 通过后回复【语音】\\n\",\n    \"- 系统自动邀请加入技术群\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/87bc7da42bcc401bae41d697f13d8b362bfdfd7198f14096b6d46b4004f09613\\\" width=\\\"300\\\" height=\\\"300\\\" ></center>\\n\",\n    \"\\n\",\n    \"# 6. 参考文献\\n\",\n    \"\\n\",\n    \"[1] Guzhov, A., Raue, F., Hees, J., & Dengel, A.R. (2021). AudioCLIP: Extending CLIP to Image, Text and Audio. ArXiv, abs/2106.13043.\\n\",\n    \"  \\n\",\n    \"[2] Kong, Q., Cao, Y., Iqbal, T., Wang, Y., Wang, W., & Plumbley, M.D. (2020). PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 28, 2880-2894.\\n\",\n    \"  \\n\",\n    \"[3] Gong, Y., Chung, Y., & Glass, J.R. (2021). AST: Audio Spectrogram Transformer. ArXiv, abs/2104.01778.\\n\",\n    \"  \\n\",\n    \"[4] Gemmeke, J.F., Ellis, D.P., Freedman, D., Jansen, A., Lawrence, W., Moore, R.C., Plakal, M., & Ritter, M. (2017). Audio Set: An ontology and human-labeled dataset for audio events. 2017 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), 776-780.\\n\",\n    \"\\n\",\n    \"[5] Piczak, K.J. (2015). ESC: Dataset for Environmental Sound Classification. Proceedings of the 23rd ACM international conference on Multimedia.\\n\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"py37\",\n   \"language\": \"python\",\n   \"name\": \"py37\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.7\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "docs/tutorial/st/st_tutorial.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"<a href=\\\"https://github.com/PaddlePaddle/PaddleSpeech\\\"><img style=\\\"position: absolute; z-index: 999; top: 0; right: 0; border: 0; width: 128px; height: 128px;\\\" src=\\\"https://nosir.github.io/cleave.js/images/right-graphite@2x.png\\\" alt=\\\"Fork me on GitHub\\\"></a>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# End-to-End Speech (to Text) Translation \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 前言\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 背景知识\\n\",\n    \"语音翻译（ST, Speech Translation）是一项从一段源语言音频中翻译出目标语言的任务。\\n\",\n    \"本章主要针对语音到文本的翻译，比如，从一段英文语音中，得到中文的翻译文本。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## 基本方法\\n\",\n    \"### 级联模型（Cascaded）,  ASR -> MT\\n\",\n    \"级联模型由独立的两个模型，语音识别模型（ASR）和机器翻译模型（MT）组成。先通过 ASR 模型从语音中识别出源语言的相应文本，在利用 MT 模型将相应文本翻译成目标语言。\\n\",\n    \"![cascaded](https://ai-studio-static-online.cdn.bcebos.com/af40e4d580764d1cb07e7f889d31e4e4e2f0839753a543bbad2e6334b48ad8cd)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"### 端到端模型 （End-to-End） \\n\",\n    \"端到端模型不显式对输入语音做文字识别，而直接生成翻译结果。\\n\",\n    \"![e2e](https://ai-studio-static-online.cdn.bcebos.com/2043ffd3d9e34054b542dcd67ebb6e4441d91e8d4bf148a88fdc7ca452356c95)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"相对于端到端模型，级联模型存在以下一些问题:\\n\",\n    \"\\n\",\n    \"1.错误传播（error propagation），由 ASR 识别错误所产生的错误文本，也会传递给 MT 模型，往往会导致生成更糟糕的翻译结果。\\n\",\n    \"\\n\",\n    \"2.时延叠加（latency accumulation），因为使用两个级联的模型，需要对输入数据进行多次处理，实际的时延是两个模型时延的累加，效率低于端到端模型。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 使用Transformer进行端到端语音翻译的基本流程\\n\",\n    \"## 基础模型\\n\",\n    \"由于 ASR 章节已经介绍了 Transformer 以及语音特征抽取，在此便不做过多介绍，感兴趣的同学可以去相关章节进行了解。\\n\",\n    \"\\n\",\n    \"本小节，主要讨论利用 transformer（seq2seq）进行ST与ASR的异同。\\n\",\n    \"\\n\",\n    \"相似之处在于，两者都可以看做是从语音（speech）到文本（text）的任务。将语音作为输入，而将文字作为输出，区别只在于生成结果是对应语言的识别结果，还是另一语言的翻译结果。\\n\",\n    \"\\n\",\n    \"因此，我们只需要将数据中的目标文本替换为翻译文本（$Y$），便可利用 ASR 的模型结构实现语音翻译。\\n\",\n    \"\\n\",\n    \"规范化地讲，对于 ASR，利用包含语音（$S$）和转写文本（$X$）的数据集，训练得到一个模型 $M_{ASR}$，能对任意输入的源语言语音 $\\\\hat{S}$ 进行文字识别，输出结果 $\\\\hat{X}$。\\n\",\n    \"\\n\",\n    \"而ST的语料集，通常包含语音（$S$）、转写文本（$X$）以及翻译文本（$Y$），只需将ASR实践中的转写文本$X$替换为对应的翻译文本 $Y$，便可利用同样的流程得到一个翻译模型 $M_{ST}$，其能对任意输入的源语言语音 $\\\\hat{S}$ 进行翻译，输出结果 $\\\\hat{Y}$\\n\",\n    \"\\n\",\n    \"值得注意的是，相较于 ASR 任务而言，在 ST 中，因为翻译文本与源语音不存在单调对齐（monotonic aligned）的性质，因此 CTC 模块不能将翻译结果作为目标来使用，此处涉及一些学术细节，感兴趣的同学可以自行去了解 [CTC](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/topic/ctc/ctc_loss.ipynb) 的具体内容。\\n\",\n    \"\\n\",\n    \"> 我们会在 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech) 中放一些 Topic 的技术文章（如 [CTC](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/topic/ctc/ctc_loss.ipynb) ），欢迎大家 star 关注。\\n\",\n    \"\\n\",\n    \"## 辅助任务训练，提升效果（ASR MTL）\\n\",\n    \"\\n\",\n    \"相比与 ASR 任务，ST 任务对于数据的标注和获取更加困难，通常很难获取大量的训练数据。\\n\",\n    \"\\n\",\n    \"因此，我们讲讨论如何更有效利用已有数据，提升 ST 模型的效果。\\n\",\n    \"\\n\",\n    \"1.先利用 ASR 对模型进行预训练，得到一个编码器能够有效的捕捉语音中的语义信息，在此基础上再进一步利用翻译数据训练ST模型。\\n\",\n    \"\\n\",\n    \"2.相较于 ASR 任务的二元组数据（$S$,$X$），通常包含三元组数据（$S$,$X$,$Y$）的ST任务能够自然有效的进行多任务学习。\\n\",\n    \"顾名思义，我们可以将ASR任务作为辅助任务，将两个任务进行联合训练，利用ASR任务的辅助提升 ST 模型的效果。\\n\",\n    \"具体上讲，如图所示，可以利用一个共享的编码器对语音进行编码，同时利用两个独立的解码器，分别执行 ASR 和 ST 任务。\\n\",\n    \"![mtl](https://ai-studio-static-online.cdn.bcebos.com/3896f104527947cbba8f459d4477b0a8cb9e4d527d6f4da29bb7792d69b66d3c)\\n\",\n    \"我们将实战中进行演示。\\n\",\n    \"\\n\",\n    \"## 引入预训练模型，提升效果 （FAT-ST PT）\\n\",\n    \"\\n\",\n    \"相比于文本到文本的机器翻译具有充足的语料（通常上百万条），语音到文本的翻译的语料很匮乏。那是否可以将文本到文本的翻译语料利用上来提升 ST 的模型效果呢？答案是肯定的。\\n\",\n    \"\\n\",\n    \"FAT 模型[1],借鉴了 Bert[2] 和 TLM[3]的 masked language model 预训练思路，并将其拓展到语音翻译的跨语言、跨模态（语音和文本）的场景。可以应对三元组（$S$,$X$,$Y$）中任意的单一或组合的数据类型。\\n\",\n    \"举例来说，它可以利用纯语音或文本数据集（$S$|$X$|$Y$），也可以利用 ASR 数据集（$S$,$Y$），甚至文本翻译数据（$X$,$Y$)。在这种预训练模型的基础上进行 ST 的训练，能够有效解决训练数据匮乏的困境，提升最终的翻译效果。\\n\",\n    \"![fat](https://ai-studio-static-online.cdn.bcebos.com/ef4b677e4cdf466fa5264d3b9dc976326e3c2046b1704c7da693015a71fc8a68)\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 实战\\n\",\n    \"## ST 多任务学习，将 ASR 作为辅助任务\\n\",\n    \"### 数据集: [Ted语音翻译数据集](http://www.nlpr.ia.ac.cn/cip/dataset.htm)（英文语音$\\\\rightarrow$中文文本）[4]\\n\",\n    \"## 准备工作\\n\",\n    \"## 特征抽取\\n\",\n    \"参考语音识别的相关章节，略。\\n\",\n    \"## 多任务模型\\n\",\n    \"Transformer 内容参考语音识别的相关章节，略。\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## Stage 1 准备工作\\n\",\n    \"### 安装 paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!pip install -U pip paddlepaddle-gpu && pip install paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 导入 python 包\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import paddle\\n\",\n    \"import numpy as np\\n\",\n    \"import kaldiio\\n\",\n    \"import subprocess\\n\",\n    \"from kaldiio import WriteHelper\\n\",\n    \"from yacs.config import CfgNode\\n\",\n    \"import IPython.display as dp\\n\",\n    \"import warnings\\n\",\n    \"warnings.filterwarnings(\\\"ignore\\\")\\n\",\n    \"\\n\",\n    \"from paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\\n\",\n    \"from paddlespeech.s2t.models.u2_st import U2STModel\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 获取预训练模型和参数并配置\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!wget -nc https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/fat_st_ted-en-zh.tar.gz\\n\",\n    \"!tar xzvf fat_st_ted-en-zh.tar.gz\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"config_path = \\\"conf/transformer_mtl_noam.yaml\\\" \\n\",\n    \"\\n\",\n    \"# 读取 conf 文件并结构化\\n\",\n    \"st_config = CfgNode(new_allowed=True)\\n\",\n    \"st_config.merge_from_file(config_path)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 下载并配置 kaldi 环境\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"!wget -nc https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/kaldi_bins.tar.gz\\n\",\n    \"!tar xzvf kaldi_bins.tar.gz\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"kaldi_bins_path = os.path.abspath('kaldi_bins')\\n\",\n    \"print(kaldi_bins_path)\\n\",\n    \"if 'LD_LIBRARY_PATH' not in os.environ:\\n\",\n    \"    os.environ['LD_LIBRARY_PATH'] = f'{kaldi_bins_path}'\\n\",\n    \"else:\\n\",\n    \"    os.environ['LD_LIBRARY_PATH'] += f':{kaldi_bins_path}'\\n\",\n    \"os.environ['PATH'] += f':{kaldi_bins_path}'\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## Stage 2 获取特征\\n\",\n    \"### 提取 kaldi 特征\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"def get_kaldi_feat(wav_path, config=st_config):\\n\",\n    \"    \\\"\\\"\\\"\\n\",\n    \"        Input preprocess and return paddle.Tensor stored in self.input.\\n\",\n    \"        Input content can be a file(wav).\\n\",\n    \"    \\\"\\\"\\\"\\n\",\n    \"    wav_file = os.path.abspath(wav_path)\\n\",\n    \"    cmvn = config.collator.cmvn_path\\n\",\n    \"    utt_name = '_tmp'\\n\",\n    \"\\n\",\n    \"    # Get the object for feature extraction\\n\",\n    \"    fbank_extract_command = [\\n\",\n    \"        'compute-fbank-feats', '--num-mel-bins=80', '--verbose=2',\\n\",\n    \"        '--sample-frequency=16000', 'scp:-', 'ark:-'\\n\",\n    \"    ]\\n\",\n    \"    fbank_extract_process = subprocess.Popen(fbank_extract_command,\\n\",\n    \"                                                stdin=subprocess.PIPE,\\n\",\n    \"                                                stdout=subprocess.PIPE,\\n\",\n    \"                                                stderr=subprocess.PIPE)\\n\",\n    \"    fbank_extract_process.stdin.write(\\n\",\n    \"        f'{utt_name} {wav_file}'.encode('utf8'))\\n\",\n    \"    fbank_extract_process.stdin.close()\\n\",\n    \"    fbank_feat = dict(kaldiio.load_ark(\\n\",\n    \"        fbank_extract_process.stdout))[utt_name]\\n\",\n    \"\\n\",\n    \"    extract_command = ['compute-kaldi-pitch-feats', 'scp:-', 'ark:-']\\n\",\n    \"    pitch_extract_process = subprocess.Popen(extract_command,\\n\",\n    \"                                                stdin=subprocess.PIPE,\\n\",\n    \"                                                stdout=subprocess.PIPE,\\n\",\n    \"                                                stderr=subprocess.PIPE)\\n\",\n    \"    pitch_extract_process.stdin.write(\\n\",\n    \"        f'{utt_name} {wav_file}'.encode('utf8'))\\n\",\n    \"    process_command = ['process-kaldi-pitch-feats', 'ark:', 'ark:-']\\n\",\n    \"    pitch_process = subprocess.Popen(process_command,\\n\",\n    \"                                        stdin=pitch_extract_process.stdout,\\n\",\n    \"                                        stdout=subprocess.PIPE,\\n\",\n    \"                                        stderr=subprocess.PIPE)\\n\",\n    \"    pitch_extract_process.stdin.close()\\n\",\n    \"    pitch_feat = dict(kaldiio.load_ark(\\n\",\n    \"        pitch_process.stdout))[utt_name]\\n\",\n    \"    concated_feat = np.concatenate((fbank_feat, pitch_feat), axis=1)\\n\",\n    \"    raw_feat = f\\\"{utt_name}.raw\\\"\\n\",\n    \"    with WriteHelper(f'ark,scp:{raw_feat}.ark,{raw_feat}.scp') as writer:\\n\",\n    \"        writer(utt_name, concated_feat)\\n\",\n    \"    cmvn_command = [\\n\",\n    \"        \\\"apply-cmvn\\\", \\\"--norm-vars=true\\\", cmvn, f'scp:{raw_feat}.scp',\\n\",\n    \"        'ark:-'\\n\",\n    \"    ]\\n\",\n    \"    cmvn_process = subprocess.Popen(cmvn_command,\\n\",\n    \"                                    stdout=subprocess.PIPE,\\n\",\n    \"                                    stderr=subprocess.PIPE)\\n\",\n    \"    process_command = ['copy-feats', '--compress=true', 'ark:-', 'ark:-']\\n\",\n    \"    process = subprocess.Popen(process_command,\\n\",\n    \"                                stdin=cmvn_process.stdout,\\n\",\n    \"                                stdout=subprocess.PIPE,\\n\",\n    \"                                stderr=subprocess.PIPE)\\n\",\n    \"    norm_feat = dict(kaldiio.load_ark(process.stdout))[utt_name]\\n\",\n    \"    audio = paddle.to_tensor(norm_feat).unsqueeze(0)\\n\",\n    \"    audio_len = paddle.to_tensor(audio.shape[1], dtype='int64')\\n\",\n    \"    return audio, audio_len\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 构建文本特征提取对象\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"text_feature = TextFeaturizer(\\n\",\n    \"                unit_type=st_config.collator.unit_type,\\n\",\n    \"                vocab=st_config.collator.vocab_filepath,\\n\",\n    \"                spm_model_prefix=st_config.collator.spm_model_prefix)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"## Stage 3 使用模型获得结果\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 构建 ST 模型\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"model_conf = st_config.model\\n\",\n    \"model_conf.input_dim = st_config.collator.feat_dim\\n\",\n    \"model_conf.output_dim = text_feature.vocab_size\\n\",\n    \"print(model_conf)\\n\",\n    \"model = U2STModel.from_config(model_conf)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 加载预训练模型\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"params_path =  \\\"exp/transformer_mtl_noam/checkpoints/fat_st_ted-en-zh.pdparams\\\"\\n\",\n    \"model_dict = paddle.load(params_path)\\n\",\n    \"model.set_state_dict(model_dict)\\n\",\n    \"model.eval()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"### 预测\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# 下载wav\\n\",\n    \"!wget -nc https://paddlespeech.cdn.bcebos.com/PaddleAudio/74109_0147917-0156334.wav\\n\",\n    \"!wget -nc https://paddlespeech.cdn.bcebos.com/PaddleAudio/120221_0278694-0283831.wav\\n\",\n    \"!wget -nc https://paddlespeech.cdn.bcebos.com/PaddleAudio/15427_0822000-0833000.wav\\n\",\n    \"\\n\",\n    \"wav_file = '74109_0147917-0156334.wav'\\n\",\n    \"# wav_file = '120221_0278694-0283831.wav'\\n\",\n    \"# wav_file = '15427_0822000-0833000.wav'\\n\",\n    \"\\n\",\n    \"transcript = \\\"my hair is short like a boy 's and i wear boy 's clothes but i 'm a girl and you know how sometimes you like to wear a pink dress and sometimes you like to wear your comfy jammies\\\"\\n\",\n    \"dp.Audio(wav_file)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"audio, audio_len = get_kaldi_feat(wav_file)\\n\",\n    \"cfg = st_config.decoding\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"res = model.decode(audio,\\n\",\n    \"            audio_len,\\n\",\n    \"            text_feature=text_feature,\\n\",\n    \"            decoding_method=cfg.decoding_method,\\n\",\n    \"            beam_size=cfg.beam_size,\\n\",\n    \"            word_reward=cfg.word_reward,\\n\",\n    \"            decoding_chunk_size=cfg.decoding_chunk_size,\\n\",\n    \"            num_decoding_left_chunks=cfg.num_decoding_left_chunks,\\n\",\n    \"            simulate_streaming=cfg.simulate_streaming)\\n\",\n    \"print(\\\"对应英文: {}\\\".format(transcript))\\n\",\n    \"print(\\\"翻译结果: {}\\\".format(\\\"\\\".join(res[0].split())))\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# 参考文献\\n\",\n    \"\\n\",\n    \"1.Zheng, Renjie, Junkun Chen, Mingbo Ma, and Liang Huang. \\\"Fused acoustic and text encoding for multimodal bilingual pretraining and speech translation.\\\" ICML 2021.\\n\",\n    \"\\n\",\n    \"2.Devlin, Jacob, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. \\\"Bert: Pre-training of deep bidirectional transformers for language understanding.\\\" NAACL 2019.\\n\",\n    \"\\n\",\n    \"3.Conneau, Alexis, and Guillaume Lample. \\\"Cross-lingual language model pretraining.\\\" NIPS 2019.\\n\",\n    \"\\n\",\n    \"4.Liu, Yuchen, Hao Xiong, Zhongjun He, Jiajun Zhang, Hua Wu, Haifeng Wang, and Chengqing Zong. \\\"End-to-end speech translation with knowledge distillation.\\\" Interspeech 2019.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"source\": [\n    \"# PaddleSpeech\\n\",\n    \"\\n\",\n    \"请关注我们的 [Github Repo](https://github.com/PaddlePaddle/PaddleSpeech/)，非常欢迎加入以下微信群参与讨论：\\n\",\n    \"- 扫描二维码\\n\",\n    \"- 添加运营小姐姐微信\\n\",\n    \"- 通过后回复【语音】\\n\",\n    \"- 系统自动邀请加入技术群\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/87bc7da42bcc401bae41d697f13d8b362bfdfd7198f14096b6d46b4004f09613\\\" width=\\\"300\\\" height=\\\"300\\\" ></center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"py35-paddle1.2.0\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.4\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "docs/tutorial/tts/tts_tutorial.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"<a href=\\\"https://github.com/PaddlePaddle/PaddleSpeech\\\"><img style=\\\"position: absolute; z-index: 999; top: 0; right: 0; border: 0; width: 128px; height: 128px;\\\" src=\\\"https://nosir.github.io/cleave.js/images/right-graphite@2x.png\\\" alt=\\\"Fork me on GitHub\\\"></a>\\n\",\n    \"\\n\",\n    \"# 『听』和『说』\\n\",\n    \"人类通过听觉获取的信息大约占所有感知信息的 20% ~ 30%。声音存储了丰富的语义以及时序信息，由专门负责听觉的器官接收信号，产生一系列连锁刺激后，在人类大脑的皮层听区进行处理分析，获取语义和知识。近年来，随着深度学习算法上的进步以及不断丰厚的硬件资源条件，**文本转语音（Text-to-Speech, TTS）** 技术在移动、虚拟娱乐等领域得到了广泛的应用。</font>\\n\",\n    \"## \\\"听\\\"书\\n\",\n    \"使用 [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) 直接获取书籍上的文字。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# download demo sources\\n\",\n    \"!mkdir download\\n\",\n    \"!wget -P download https://paddlespeech.cdn.bcebos.com/tutorial/tts/ocr_result.jpg\\n\",\n    \"!wget -P download https://paddlespeech.cdn.bcebos.com/tutorial/tts/ocr.wav\\n\",\n    \"!wget -P download https://paddlespeech.cdn.bcebos.com/tutorial/tts/tts_lips.mp4\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import IPython.display as dp\\n\",\n    \"from PIL import Image\\n\",\n    \"img_path = 'download/ocr_result.jpg'\\n\",\n    \"im = Image.open(img_path)\\n\",\n    \"dp.display(im)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"使用 [PaddleSpeech](https://github.com/PaddlePaddle/PaddleSpeech)，阅读上一步识别出来的文字。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dp.Audio(\\\"download/ocr.wav\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"具体实现代码详见 [Story Talker](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/story_talker)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 偶像开口说话\\n\",\n    \"*元宇宙来袭，构造你的虚拟人！* 看看 [PaddleGAN](https://github.com/PaddlePaddle/PaddleGAN) 怎样合成唇形，让WiFi之母——海蒂·拉玛说话。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from IPython.display import HTML\\n\",\n    \"html_str = '''\\n\",\n    \"<video controls width=\\\"600\\\" height=\\\"360\\\" src=\\\"{}\\\">animation</video>\\n\",\n    \"'''.format(\\\"download/tts_lips.mp4\\\")\\n\",\n    \"dp.display(HTML(html_str))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"具体实现代码请参考 [Metaverse](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/metaverse)。\\n\",\n    \"\\n\",\n    \"下面让我们来系统地学习语音方面的知识，看看怎样使用 **PaddleSpeech** 实现基本的语音功能，以及怎样结合光学字符识别（Optical Character Recognition，OCR）、自然语言处理（Natural Language Processing，NLP）等技术“听”书、让名人开口说话。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 前言\\n\",\n    \"## 背景知识\\n\",\n    \"为了更好地了解文本转语音任务的要素，我们先简要地回顾一下文本转语音的发展历史。如果你对此已经有所了解，或希望能尽快使用代码实现，请直接跳至[实践](#实践)。\\n\",\n    \"### 定义\\n\",\n    \"<!----\\n\",\n    \"Note: \\n\",\n    \"1.此句抄自 [李沐Dive into Dive Learning](https://zh-v2.d2l.ai/chapter_introduction/index.html)\\n\",\n    \"2.修改参考A survey on Neural Speech Sysnthesis.\\n\",\n    \"---> \\n\",\n    \"文本转语音，又称语音合成（Speech Sysnthesis），指的是将一段文本按照一定需求转化成对应的音频，这种特性决定了的输出数据比输入输入长得多。文本转语音是一项包含了语义学、声学、数字信号处理以及机器学习的等多项学科的交叉任务。虽然辨识低质量音频文件的内容对人类来说很容易，但这对计算机来说并非易事。\\n\",\n    \"\\n\",\n    \"按照不同的应用需求，更广义的语音合成研究包括：*语音转换*，例如说话人转换、语音到歌唱转换、语音情感转换、口音转换等；*歌唱合成*，例如歌词到歌唱转换、可视语音合成等。\\n\",\n    \"\\n\",\n    \"### 发展历史\\n\",\n    \"\\n\",\n    \"<!--\\n\",\n    \"以下摘自维基百科 https://en.wikipedia.org/wiki/Speech_synthesis\\n\",\n    \"--->\\n\",\n    \"\\n\",\n    \"在第二次工业革命之前，语音的合成主要以机械式的音素合成为主。1779年，德裔丹麦科学家 Christian Gottlieb Kratzenstein 建造了人类的声道模型，使其可以产生五个长元音。1791年， Wolfgang von Kempelen 添加了唇和舌的模型，使其能够发出辅音和元音。贝尔实验室于20世纪30年代发明了声码器（Vocoder），将语音自动分解为音调和共振，此项技术由 Homer Dudley 改进为键盘式合成器并于 1939年纽约世界博览会展出。\\n\",\n    \"\\n\",\n    \"第一台基于计算机的语音合成系统起源于20世纪50年代。1961年，IBM 的 John Larry Kelly，以及 Louis Gerstman 使用 IBM 704 计算机合成语音，成为贝尔实验室最著名的成就之一。1975年，第一代语音合成系统之一 —— MUSA（MUltichannel Speaking Automation）问世，其由一个独立的硬件和配套的软件组成。1978年发行的第二个版本也可以进行无伴奏演唱。90 年代的主流是采用 MIT 和贝尔实验室的系统，并结合自然语言处理模型。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/55035de353b042cd8c4468819b2d36e2fcc89bffdf2b442fa4c7b0b5499e1592\\\"></center>\\n\",\n    \"\\n\",\n    \"### 主流方法\\n\",\n    \"\\n\",\n    \"当前的主流方法分为**基于统计参数的语音合成**、**波形拼接语音合成**、**混合方法**以及**端到端神经网络语音合成**。基于参数的语音合成包含隐马尔可夫模型（Hidden Markov Model,HMM）以及深度学习网络（Deep Neural Network，DNN）。端到端的方法保函声学模型+声码器以及“完全”端到端方法。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"## 基于深度学习的语音合成技术\\n\",\n    \"\\n\",\n    \"### 语音合成基本知识\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/10859679d74745ab82fb6f5c9984a95152c25b0e3dce4515b120c8997a6752d8\\\"></center>\\n\",\n    \"<br></br>\\n\",\n    \"\\n\",\n    \"语音合成流水线包含 <font color=\\\"#ff0000\\\">**文本前端（Text Frontend）**</font> 、<font color=\\\"#ff0000\\\">**声学模型（Acoustic Model）**</font> 和 <font color=\\\"#ff0000\\\">**声码器（Vocoder）**</font> 三个主要模块:\\n\",\n    \"- 通过文本前端模块将原始文本转换为字符/音素。\\n\",\n    \"- 通过声学模型将字符/音素转换为声学特征，如线性频谱图、mel 频谱图、LPC 特征等。\\n\",\n    \"- 通过声码器将声学特征转换为波形。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 实践\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 安装 paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!pip install -U pip paddlepaddle-gpu && pip install paddlespeech\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"环境安装请参考 [Installation](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md) 教程。 \\n\",\n    \"下面使用 **PaddleSpeech** 提供的预训练模型合成中文语音。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 数据及模型准备\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 获取PaddlePaddle预训练模型\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip\\n\",\n    \"!unzip -d download download/pwg_baker_ckpt_0.4.zip\\n\",\n    \"!wget -P download https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip\\n\",\n    \"!unzip -d download download/fastspeech2_nosil_baker_ckpt_0.4.zip\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!tree download/pwg_baker_ckpt_0.4\\n\",\n    \"!tree download/fastspeech2_nosil_baker_ckpt_0.4\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 导入 Python 包\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 本项目的依赖需要用到 nltk 包，但是有时会因为网络原因导致不好下载，此处手动下载一下放到百度服务器的包\\n\",\n    \"!wget https://paddlespeech.cdn.bcebos.com/Parakeet/tools/nltk_data.tar.gz\\n\",\n    \"!tar zxvf nltk_data.tar.gz\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 设置 gpu 环境\\n\",\n    \"%env CUDA_VISIBLE_DEVICES=0\\n\",\n    \"\\n\",\n    \"import logging\\n\",\n    \"import sys\\n\",\n    \"import warnings\\n\",\n    \"warnings.filterwarnings(\\\"ignore\\\", category=DeprecationWarning)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import argparse\\n\",\n    \"import os\\n\",\n    \"from pathlib import Path\\n\",\n    \"import IPython.display as dp\\n\",\n    \"import matplotlib.pyplot as plt\\n\",\n    \"import numpy as np\\n\",\n    \"import paddle\\n\",\n    \"import soundfile as sf\\n\",\n    \"import yaml\\n\",\n    \"from paddlespeech.t2s.frontend.zh_frontend import Frontend\\n\",\n    \"from paddlespeech.t2s.models.fastspeech2 import FastSpeech2\\n\",\n    \"from paddlespeech.t2s.models.fastspeech2 import FastSpeech2Inference\\n\",\n    \"from paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\\n\",\n    \"from paddlespeech.t2s.models.parallel_wavegan import PWGInference\\n\",\n    \"from paddlespeech.t2s.modules.normalizer import ZScore\\n\",\n    \"from yacs.config import CfgNode\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 设置预训练模型的路径\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"fastspeech2_config = \\\"download/fastspeech2_nosil_baker_ckpt_0.4/default.yaml\\\"\\n\",\n    \"fastspeech2_checkpoint = \\\"download/fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz\\\"\\n\",\n    \"fastspeech2_stat = \\\"download/fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy\\\"\\n\",\n    \"pwg_config = \\\"download/pwg_baker_ckpt_0.4/pwg_default.yaml\\\"\\n\",\n    \"pwg_checkpoint = \\\"download/pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz\\\"\\n\",\n    \"pwg_stat = \\\"download/pwg_baker_ckpt_0.4/pwg_stats.npy\\\"\\n\",\n    \"phones_dict = \\\"download/fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\\\"\\n\",\n    \"# 读取 conf 配置文件并结构化\\n\",\n    \"with open(fastspeech2_config) as f:\\n\",\n    \"    fastspeech2_config = CfgNode(yaml.safe_load(f))\\n\",\n    \"with open(pwg_config) as f:\\n\",\n    \"    pwg_config = CfgNode(yaml.safe_load(f))\\n\",\n    \"print(\\\"========Config========\\\")\\n\",\n    \"print(fastspeech2_config)\\n\",\n    \"print(\\\"---------------------\\\")\\n\",\n    \"print(pwg_config)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 文本前端（Text Frontend）\\n\",\n    \"\\n\",\n    \"一个文本前端模块主要包含:\\n\",\n    \"- 分段（Text Segmentation）\\n\",\n    \"- 文本正则化（Text Normalization, TN）\\n\",\n    \"- 分词（Word Segmentation, 主要是在中文中）\\n\",\n    \"- 词性标注（Part-of-Speech, PoS）\\n\",\n    \"- 韵律预测（Prosody）\\n\",\n    \"- 字音转换（Grapheme-to-Phoneme，G2P）\\n\",\n    \"<font size=2>（Grapheme: **语言**书写系统的最小有意义单位; Phoneme: 区分单词的最小**语音**单位）</font>\\n\",\n    \"    - 多音字（Polyphone）\\n\",\n    \"    - 变调（Tone Sandhi）\\n\",\n    \"        - “一”、“不”变\\n\",\n    \"        - 三声变调\\n\",\n    \"        - 轻声变调\\n\",\n    \"        - 儿化音\\n\",\n    \"        - 方言\\n\",\n    \"- ...\\n\",\n    \"\\n\",\n    \"（输入给声学模型之前，还需要把音素序列转换为 id）\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"其中最重要的模块是<font color=\\\"#ff0000\\\"> 文本正则化 </font>模块和<font color=\\\"#ff0000\\\"> 字音转换（TTS 中更常用 G2P 代指） </font>模块。\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"各模块输出示例:\\n\",\n    \"```text\\n\",\n    \"• Text: 全国一共有112所211高校\\n\",\n    \"• Text Normalization: 全国一共有一百一十二所二一一高校\\n\",\n    \"• Word Segmentation: 全国/一共/有/一百一十二/所/二一一/高校/\\n\",\n    \"• G2P（注意此句中“一”的读音）:\\n\",\n    \"    quan2 guo2 yi2 gong4 you3 yi4 bai3 yi1 shi2 er4 suo3 er4 yao1 yao1 gao1 xiao4\\n\",\n    \"    （可以进一步把声母和韵母分开）\\n\",\n    \"    q uan2 g uo2 y i2 g ong4 y ou3 y i4 b ai3 y i1 sh i2 er4 s uo3 er4 y ao1 y ao1 g ao1 x iao4\\n\",\n    \"    （把音调和声韵母分开）\\n\",\n    \"    q uan g uo y i g ong y ou y i b ai y i sh i er s uo er y ao y ao g ao x iao\\n\",\n    \"    0 2 0 2 0 2 0 4 0 3 ...\\n\",\n    \"• Prosody (prosodic words #1, prosodic phrases #2, intonation phrases #3, sentence #4):\\n\",\n    \"    全国#2一共有#2一百#1一十二所#2二一一#1高校#4\\n\",\n    \"    （分词的结果一般是固定的，但是不同人习惯不同，可能有不同的韵律）\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"文本前端模块的设计需要结合很多专业的语义学知识和经验。人类在读文本的时候可以自然而然地读出正确的发音，但是这些先验知识计算机并不知晓。\\n\",\n    \"例如，对于一个句子的分词：\\n\",\n    \"\\n\",\n    \"```text\\n\",\n    \"我也想过过过儿过过的生活\\n\",\n    \"我也想/过过/过儿/过过的/生活\\n\",\n    \"\\n\",\n    \"货拉拉拉不拉拉布拉多\\n\",\n    \"货拉拉/拉不拉/拉布拉多\\n\",\n    \"\\n\",\n    \"南京市长江大桥\\n\",\n    \"南京市长/江大桥\\n\",\n    \"南京市/长江大桥\\n\",\n    \"```\\n\",\n    \"或者是词的变调和儿化音：\\n\",\n    \"```\\n\",\n    \"你要不要和我们一起出去玩？\\n\",\n    \"你要不（2声）要和我们一（4声）起出去玩（儿）？\\n\",\n    \"\\n\",\n    \"不好，我要一个人出去。\\n\",\n    \"不（4声）好，我要一（2声）个人出去。\\n\",\n    \"\\n\",\n    \"（以下每个词的所有字都是三声的，请你读一读，体会一下在读的时候，是否每个字都被读成了三声？）\\n\",\n    \"纸老虎、虎骨酒、展览馆、岂有此理、手表厂有五种好产品\\n\",\n    \"```\\n\",\n    \"又或是多音字，这类情况通常需要先正确分词：\\n\",\n    \"```text\\n\",\n    \"人要行，干一行行一行，一行行行行行;\\n\",\n    \"人要是不行，干一行不行一行，一行不行行行不行。\\n\",\n    \"\\n\",\n    \"佟大为妻子产下一女\\n\",\n    \"\\n\",\n    \"海水朝朝朝朝朝朝朝落\\n\",\n    \"浮云长长长长长长长消\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"PaddleSpeech Text-to-Speech的文本前端解决方案:\\n\",\n    \"- [文本正则](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/tn)\\n\",\n    \"- [G2P](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/g2p)\\n\",\n    \"    - 多音字模块: pypinyin/g2pM\\n\",\n    \"    - 变调模块: 用分词 + 规则\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 构造文本前端对象\\n\",\n    \"传入`phones_dict`，把相应的`phones`转换成`phone_ids`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 传入 phones_dict 会把相应的 phones 转换成 phone_ids\\n\",\n    \"frontend = Frontend(phone_vocab_path=phones_dict)\\n\",\n    \"print(\\\"Frontend done!\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 调用文本前端\\n\",\n    \"\\n\",\n    \"文本前端对输入数据进行正则化时会进行分句，若`merge_sentences`设置为`False`，则所有分句的 `phone_ids` 构成一个 `List`；若设置为`True`，`input_ids[\\\"phone_ids\\\"][0]`则表示整句的`phone_ids`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# input = \\\"我每天中午12:00起床\\\"\\n\",\n    \"# input = \\\"我出生于2005/11/08，那天的最低气温达到-10°C\\\"\\n\",\n    \"input = \\\"你好，欢迎使用百度飞桨框架进行深度学习研究！\\\"\\n\",\n    \"input_ids = frontend.get_input_ids(input, merge_sentences=True, print_info=True)\\n\",\n    \"phone_ids = input_ids[\\\"phone_ids\\\"][0]\\n\",\n    \"print(\\\"phone_ids:%s\\\"%phone_ids)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 用深度学习实现文本前端\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/85a5cd8aef1e444cbb980a2f1f184316247bbb7870a34925a77b799802df8ef0\\\"></center>\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 声学模型（Acoustic Model）\\n\",\n    \"\\n\",\n    \"声学模型将字符/音素转换为声学特征，如线性频谱图、mel 频谱图、LPC 特征等，声学特征以 “帧” 为单位，一般一帧是 10ms 左右，一个音素一般对应 5~20 帧左右, 声学模型需要解决的是 <font color=\\\"#ff0000\\\">“不等长序列间的映射问题”</font>，“不等长”是指，同一个人发不同音素的持续时间不同，同一个人在不同时刻说同一句话的语速可能不同，对应各个音素的持续时间不同，不同人说话的特色不同，对应各个音素的持续时间不同。这是一个困难的“一对多”问题。\\n\",\n    \"```\\n\",\n    \"# 卡尔普陪外孙玩滑梯\\n\",\n    \"000001|baker_corpus|sil 20 k 12 a2 4 er2 10 p 12 u3 12 p 9 ei2 9 uai4 15 s 11 uen1 12 uan2 14 h 10 ua2 11 t 15 i1 16 sil 20\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"声学模型主要分为自回归模型和非自回归模型，其中自回归模型在 `t` 时刻的预测需要依赖 `t-1` 时刻的输出作为输入，预测时间长，但是音质相对较好，非自回归模型不存在预测上的依赖关系，预测时间快，音质相对较差。\\n\",\n    \"\\n\",\n    \"主流声学模型发展的脉络:\\n\",\n    \"- 自回归模型:\\n\",\n    \"    - Tacotron\\n\",\n    \"    - Tacotron2\\n\",\n    \"    - Transformer TTS\\n\",\n    \"- 非自回归模型:\\n\",\n    \"    - FastSpeech\\n\",\n    \"    - SpeedySpeech\\n\",\n    \"    - FastPitch\\n\",\n    \"    - FastSpeech2\\n\",\n    \"    - ...\\n\",\n    \" \\n\",\n    \"在本教程中，我们使用 `FastSpeech2` 作为声学模型。\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/6b6d671713ec4d20a0e60653c7a5d4ae3c35b1d1e58b4cc39e0bc82ad4a341d9\\\"></center>\\n\",\n    \"<br><center> FastSpeech2 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"PaddleSpeech TTS 实现的 FastSpeech2 与论文不同的地方在于，我们使用的是 phone 级别的 `pitch` 和 `energy`(与 FastPitch 类似)，这样的合成结果可以更加**稳定**。\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/862c21456c784c41a83a308b7d9707f0810cc3b3c6f94ed48c60f5d32d0072f0\\\"></center>\\n\",\n    \"<br><center> FastPitch 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"更多关于[语音合成模型的发展及改进](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/tts/models_introduction.md)。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 初始化声学模型 FastSpeech2\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with open(phones_dict, \\\"r\\\") as f:\\n\",\n    \"    phn_id = [line.strip().split() for line in f.readlines()]\\n\",\n    \"vocab_size = len(phn_id)\\n\",\n    \"print(\\\"vocab_size:\\\", vocab_size)\\n\",\n    \"odim = fastspeech2_config.n_mels\\n\",\n    \"model = FastSpeech2(\\n\",\n    \"    idim=vocab_size, odim=odim, **fastspeech2_config[\\\"model\\\"])\\n\",\n    \"# 加载预训练模型参数\\n\",\n    \"model.set_state_dict(paddle.load(fastspeech2_checkpoint)[\\\"main_params\\\"])\\n\",\n    \"# 推理阶段不启用 batch norm 和 dropout\\n\",\n    \"model.eval()\\n\",\n    \"stat = np.load(fastspeech2_stat)\\n\",\n    \"# 读取数据预处理阶段数据集的均值和标准差\\n\",\n    \"mu, std = stat\\n\",\n    \"mu, std = paddle.to_tensor(mu), paddle.to_tensor(std)\\n\",\n    \"# 构造归一化的新模型\\n\",\n    \"fastspeech2_normalizer = ZScore(mu, std)\\n\",\n    \"fastspeech2_inference = FastSpeech2Inference(fastspeech2_normalizer, model)\\n\",\n    \"fastspeech2_inference.eval()\\n\",\n    \"print(\\\"FastSpeech2 done!\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 调用声学模型\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with paddle.no_grad():\\n\",\n    \"    mel = fastspeech2_inference(phone_ids)\\n\",\n    \"print(\\\"shepe of mel (n_frames x n_mels):\\\")\\n\",\n    \"print(mel.shape)\\n\",\n    \"# 绘制声学模型输出的 mel 频谱\\n\",\n    \"fig, ax = plt.subplots(figsize=(16, 6))\\n\",\n    \"im = ax.imshow(mel.T, aspect='auto',origin='lower')\\n\",\n    \"plt.title('Mel Spectrogram')\\n\",\n    \"plt.xlabel('Time')\\n\",\n    \"plt.ylabel('Frequency')\\n\",\n    \"plt.tight_layout()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 声码器（Vocoder）\\n\",\n    \"声码器将声学特征转换为波形。声码器需要解决的是 <font color=\\\"#ff0000\\\">“信息缺失的补全问题”</font>。信息缺失是指，在音频波形转换为频谱图的时候，存在**相位信息**的缺失，在频谱图转换为 mel 频谱图的时候，存在**频域压缩**导致的信息缺失；假设音频的采样率是16kHZ, 一帧的音频有 10ms，也就是说，1s 的音频有 16000 个采样点，而 1s 中包含 100 帧，每一帧有 160 个采样点，声码器的作用就是将一个频谱帧变成音频波形的 160 个采样点，所以声码器中一般会包含**上采样**模块。\\n\",\n    \"\\n\",\n    \"与声学模型类似，声码器也分为自回归模型和非自回归模型, 更细致的分类如下:\\n\",\n    \"\\n\",\n    \"- Autoregression\\n\",\n    \"    - WaveNet\\n\",\n    \"    - WaveRNN\\n\",\n    \"    - LPCNet\\n\",\n    \"- Flow\\n\",\n    \"    - <font color=\\\"#ff0000\\\">WaveFlow</font>\\n\",\n    \"    - WaveGlow\\n\",\n    \"    - FloWaveNet\\n\",\n    \"    - Parallel WaveNet\\n\",\n    \"- GAN\\n\",\n    \"\\t- WaveGAN\\n\",\n    \"    - <font color=\\\"#ff0000\\\">Parallel WaveGAN</font>\\n\",\n    \"    - <font color=\\\"#ff0000\\\">MelGAN</font>\\n\",\n    \"    - <font color=\\\"#ff0000\\\">Style MelGAN</font>\\n\",\n    \"    - <font color=\\\"#ff0000\\\">Multi Band MelGAN</font>\\n\",\n    \"    - <font color=\\\"#ff0000\\\">HiFi GAN</font>\\n\",\n    \"- VAE\\n\",\n    \"    - Wave-VAE\\n\",\n    \"- Diffusion\\n\",\n    \"    - WaveGrad\\n\",\n    \"    - DiffWave\\n\",\n    \"\\n\",\n    \"PaddleSpeech TTS 主要实现了百度的 `WaveFlow` 和一些主流的 GAN Vocoder, 在本教程中，我们使用 `Parallel WaveGAN` 作为声码器。\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/9eafa4e5642d45309e6e8883bff46380407b3858d0934bf5896868281316ce94\\\" width=\\\"700\\\"></center>\\n\",\n    \"<br><center>图1：Parallel WaveGAN 网络结构图</center></br>\\n\",\n    \"\\n\",\n    \"各 GAN Vocoder 的生成器和判别器的 Loss 的区别如下表格所示:\\n\",\n    \"\\n\",\n    \"Model  | Generator Loss |Discriminator Loss\\n\",\n    \":-------------:| :------------:| :-----\\n\",\n    \"Mel GAN| adversial loss <br> Feature Matching  | Multi-Scale Discriminator |\\n\",\n    \"Parallel Wave GAN|adversial loss <br> Multi-resolution STFT loss  | adversial loss|\\n\",\n    \"Multi-Band Mel GAN | adversial loss <br> full band Multi-resolution STFT loss <br> sub band Multi-resolution STFT loss |Multi-Scale Discriminator|\\n\",\n    \"HiFi GAN |adversial loss <br> Feature Matching <br>  Mel-Spectrogram Loss | Multi-Scale Discriminator <br> Multi-Period Discriminator| \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 初始化声码器 Parallel WaveGAN\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"vocoder = PWGGenerator(**pwg_config[\\\"generator_params\\\"])\\n\",\n    \"# 模型加载预训练参数\\n\",\n    \"vocoder.set_state_dict(paddle.load(pwg_checkpoint)[\\\"generator_params\\\"])\\n\",\n    \"vocoder.remove_weight_norm()\\n\",\n    \"# 推理阶段不启用 batch norm 和 dropout\\n\",\n    \"vocoder.eval()\\n\",\n    \"# 读取数据预处理阶段数据集的均值和标准差\\n\",\n    \"stat = np.load(pwg_stat)\\n\",\n    \"mu, std = stat\\n\",\n    \"mu, std = paddle.to_tensor(mu), paddle.to_tensor(std)\\n\",\n    \"pwg_normalizer = ZScore(mu, std)\\n\",\n    \"# 构建归一化的模型\\n\",\n    \"pwg_inference = PWGInference(pwg_normalizer, vocoder)\\n\",\n    \"pwg_inference.eval()\\n\",\n    \"print(\\\"Parallel WaveGAN done!\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 调用声码器\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with paddle.no_grad():\\n\",\n    \"    wav = pwg_inference(mel)\\n\",\n    \"print(\\\"shepe of wav (time x n_channels):%s\\\"%wav.shape)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 绘制声码器输出的波形图\\n\",\n    \"wave_data = wav.numpy().T\\n\",\n    \"time = np.arange(0, wave_data.shape[1]) * (1.0 / fastspeech2_config.fs)\\n\",\n    \"fig, ax = plt.subplots(figsize=(16, 6))\\n\",\n    \"plt.plot(time, wave_data[0])\\n\",\n    \"plt.title('Waveform')\\n\",\n    \"plt.xlabel('Time (seconds)')\\n\",\n    \"plt.ylabel('Amplitude (normed)')\\n\",\n    \"plt.tight_layout()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 播放音频\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dp.Audio(wav.numpy().T, rate=fastspeech2_config.fs)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 保存音频\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!mkdir output\\n\",\n    \"sf.write(\\n\",\n    \"    \\\"output/output.wav\\\",\\n\",\n    \"    wav.numpy(),\\n\",\n    \"    samplerate=fastspeech2_config.fs)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 进阶 —— 个性化调节\\n\",\n    \"FastSpeech2 模型可以个性化地调节音素时长、音调和能量，通过一些简单的调节就可以获得一些有意思的效果。\\n\",\n    \"\\n\",\n    \"例如对于以下的原始音频`\\\"凯莫瑞安联合体的经济崩溃，迫在眉睫\\\"`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 原始音频\\n\",\n    \"dp.display(dp.Audio(url=\\\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1_001.wav\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# speed x 1.2\\n\",\n    \"dp.display(dp.Audio(url=\\\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x1.2_001.wav\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# speed x 0.8\\n\",\n    \"dp.display(dp.Audio(url=\\\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/speed/x0.8_001.wav\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# pitch x 1.3(童声)\\n\",\n    \"dp.display(dp.Audio(url=\\\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/child_voice/001.wav\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# robot\\n\",\n    \"dp.display(dp.Audio(url=\\\"https://paddlespeech.cdn.bcebos.com/Parakeet/docs/demos/robot/001.wav\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"具体实现代码请参考 [Style FastSpeech2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/demos/style_fs2)。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 用 PaddleSpeech 训练 TTS 模型\\n\",\n    \"PaddleSpeech 的 examples 是按照 数据集/模型 的结构安排的:\\n\",\n    \"```text\\n\",\n    \"examples   \\n\",\n    \"├── aishell3\\n\",\n    \"│   ├── README.md\\n\",\n    \"│   ├── tts3\\n\",\n    \"│   └── vc0\\n\",\n    \"├── csmsc\\n\",\n    \"│   ├── README.md\\n\",\n    \"│   ├── tts2\\n\",\n    \"│   ├── tts3\\n\",\n    \"│   ├── voc1\\n\",\n    \"│   └── voc3\\n\",\n    \"├── ...\\n\",\n    \"└── ...\\n\",\n    \"```\\n\",\n    \"我们在每个数据集的 README.md 介绍了子目录和模型的对应关系, 在 TTS 中有如下对应关系:\\n\",\n    \"```text\\n\",\n    \"tts0 - Tacotron2\\n\",\n    \"tts1 - TransformerTTS\\n\",\n    \"tts2 - SpeedySpeech\\n\",\n    \"tts3 - FastSpeech2\\n\",\n    \"voc0 - WaveFlow\\n\",\n    \"voc1 - Parallel WaveGAN\\n\",\n    \"voc2 - MelGAN\\n\",\n    \"voc3 - MultiBand MelGAN\\n\",\n    \"```\\n\",\n    \"### 基于 CSMCS 数据集训练 FastSpeech2 模型\\n\",\n    \"```bash\\n\",\n    \"git clone https://github.com/PaddlePaddle/PaddleSpeech.git\\n\",\n    \"cd examples/csmsc/tts3\\n\",\n    \"```\\n\",\n    \"根据 README.md, 下载 CSMCS 数据集和其对应的强制对齐文件, 并放置在对应的位置\\n\",\n    \"```bash\\n\",\n    \"./run.sh\\n\",\n    \"```\\n\",\n    \"`run.sh` 中包含预处理、训练、合成、静态图推理等步骤:\\n\",\n    \"\\n\",\n    \"```bash\\n\",\n    \"#!/bin/bash\\n\",\n    \"set -e\\n\",\n    \"source path.sh\\n\",\n    \"gpus=0,1\\n\",\n    \"stage=0\\n\",\n    \"stop_stage=100\\n\",\n    \"conf_path=conf/default.yaml\\n\",\n    \"train_output_path=exp/default\\n\",\n    \"ckpt_name=snapshot_iter_153.pdz\\n\",\n    \"\\n\",\n    \"# with the following command, you can choice the stage range you want to run\\n\",\n    \"# such as `./run.sh --stage 0 --stop-stage 0`\\n\",\n    \"# this can not be mixed use with `$1`, `$2` ...\\n\",\n    \"source ${MAIN_ROOT}/utils/parse_options.sh || exit 1\\n\",\n    \"\\n\",\n    \"if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\\n\",\n    \"    # prepare data\\n\",\n    \"    bash ./local/preprocess.sh ${conf_path} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\\n\",\n    \"    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\\n\",\n    \"    # synthesize, vocoder is pwgan\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\\n\",\n    \"    # synthesize_e2e, vocoder is pwgan\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\\n\",\n    \"    # inference with static model\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\\n\",\n    \"fi\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"### 基于 CSMCS 数据集训练 Parallel WaveGAN 模型\\n\",\n    \"```bash\\n\",\n    \"git clone https://github.com/PaddlePaddle/PaddleSpeech.git\\n\",\n    \"cd examples/csmsc/voc1\\n\",\n    \"```\\n\",\n    \"根据 README.md, 下载 CSMCS 数据集和其对应的强制对齐文件, 并放置在对应的位置\\n\",\n    \"```bash\\n\",\n    \"./run.sh\\n\",\n    \"```\\n\",\n    \"`run.sh` 中包含预处理、训练、合成等步骤:\\n\",\n    \"```bash\\n\",\n    \"#!/bin/bash\\n\",\n    \"set -e\\n\",\n    \"source path.sh\\n\",\n    \"gpus=0,1\\n\",\n    \"stage=0\\n\",\n    \"stop_stage=100\\n\",\n    \"conf_path=conf/default.yaml\\n\",\n    \"train_output_path=exp/default\\n\",\n    \"ckpt_name=snapshot_iter_5000.pdz\\n\",\n    \"\\n\",\n    \"# with the following command, you can choice the stage range you want to run\\n\",\n    \"# such as `./run.sh --stage 0 --stop-stage 0`\\n\",\n    \"# this can not be mixed use with `$1`, `$2` ...\\n\",\n    \"source ${MAIN_ROOT}/utils/parse_options.sh || exit 1\\n\",\n    \"\\n\",\n    \"if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\\n\",\n    \"    # prepare data\\n\",\n    \"    ./local/preprocess.sh ${conf_path} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\\n\",\n    \"    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\\n\",\n    \"fi\\n\",\n    \"if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\\n\",\n    \"    # synthesize\\n\",\n    \"    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\\n\",\n    \"fi\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# FAQ\\n\",\n    \"\\n\",\n    \"- 需要注意的问题\\n\",\n    \"- 经验与分享\\n\",\n    \"- 用户的其他问题\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 作业\\n\",\n    \"在 CSMSC 数据集上利用 FastSpeech2 和 Parallel WaveGAN 实现一个中文 TTS 系统。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 关注 PaddleSpeech\\n\",\n    \"请关注我们的 [Github Repo](https://github.com/PaddlePaddle/PaddleSpeech/)，非常欢迎加入以下微信群参与讨论：\\n\",\n    \"- 扫描二维码\\n\",\n    \"- 添加运营小姐姐微信\\n\",\n    \"- 通过后回复【语音】\\n\",\n    \"- 系统自动邀请加入技术群\\n\",\n    \"\\n\",\n    \"<center><img src=\\\"https://ai-studio-static-online.cdn.bcebos.com/bca0bc75dce14b53af44e374e64fc91aeeb13c075c894d6aabed033148f65377\\\" ></center>\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.4\"\n  },\n  \"toc\": {\n   \"base_numbering\": 1,\n   \"nav_menu\": {},\n   \"number_sections\": true,\n   \"sideBar\": true,\n   \"skip_h1_title\": false,\n   \"title_cell\": \"Table of Contents\",\n   \"title_sidebar\": \"Contents\",\n   \"toc_cell\": false,\n   \"toc_position\": {},\n   \"toc_section_display\": true,\n   \"toc_window_display\": false\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "examples/aishell/.gitignore",
    "content": "data\nckpt*\ndemo_cache\n*log\n*profile"
  },
  {
    "path": "examples/aishell/README.md",
    "content": "# ASR\n\n* asr0 - deepspeech2 Streaming/Non-Streaming\n* asr1 - transformer/conformer Streaming/Non-Streaming\n* ~~asr2 - transformer/conformer Streaming/Non-Streaming with Kaldi feature~~\n* asr3 - wav2vec2 Non-Streaming\n\n\n## Data\n\n| Data Subset         | Duration in Seconds   |\n| ------------------- | --------------------- |\n| data/manifest.train | 1.23 ~ 14.53125       |\n| data/manifest.dev   | 1.645 ~ 12.533        |\n| data/manifest.test  | 1.859125 ~ 14.6999375 |\n"
  },
  {
    "path": "examples/aishell/asr0/.gitignore",
    "content": "exp\ndata\n*log\n"
  },
  {
    "path": "examples/aishell/asr0/README.md",
    "content": "# DeepSpeech2 offline/online ASR with Aishell\nThis example contains code used to train a DeepSpeech2 offline or online model with [Aishell dataset](http://www.openslr.org/resources/33)\n\n## Overview\nAll the scripts you need are in the `run.sh`. There are several stages in the `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Export the static graph model                                |\n| 5     | Test the static graph model                                  |\n| 6     | Infer the single audio file                                  |\n\nYou can choose to run a range of stages by setting the `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in the `run.sh` in detail.\n## The environment variables\nThe path.sh contains the environment variable. \n```bash\nsource path.sh\n```\nThis script needs to be run first.  \n\nAnd another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n\n## The local variables\nSome local variables are set in the `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`,  it means you only use CPU. \n\n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`model_type` denotes the model type: offline or online\n`audio file` denotes the file path of the single file you want to infer in stage 6\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"deepspeech2\"\n\nYou can set the local variables (except `ckpt`)  when you use the `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 1\n```\n## Stage 0: Data processing\nTo use this example, you need to process data firstly and you can use stage 0 in the `run.sh` to do this. The code is shown below:\n\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model training\nIf you want to train the model. you can use stage 1 in the `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nOr you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\n```\nIf you want to use GPU, you can run these scripts in the command line (suppose you have only 1 GPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES=0 ./local/train.sh conf/deepspeech2.yaml deepspeech2\n```\n\n## Stage 2:  Top-k Models Averaging\nAfter training the model,  we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model.  We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model,  you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it,  you can use the script below to execute stage 0, stage 1,  stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_10\n```\n## Pretrained Model\nYou can get the pretrained models from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz\ntar xzvf asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2  --stop_stage 2\n\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/deepspeech2.yaml exp/deepspeech2/checkpoints/avg_10\n```\nThe performance of the released models are shown in [this](./RESULTS.md)\n## Stage 4: Static graph model Export\nThis stage is to transform dygraph to static graph.\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}\n fi\n```\nIf you already have a dynamic graph model, you can run this script:\n```bash\nsource path.sh\n./local/export.sh conf/deepspeech2.yaml exp/deepspeech2/checkpoints/avg_10 exp/deepspeech2/checkpoints/avg_10.jit\n```\n## Stage 5: Static graph Model Testing\nSimilar to stage 3, the static graph model can also be tested.\n```bash\n if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n     # test export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test_export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}|| exit -1\n fi\n```\nIf you already have exported the static graph, you can run this script:\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_export.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_10.jit\n```\n## Stage 6: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage  5. The code is shown below\n```bash\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${model_type} ${audio_file}\n fi\n```\nyou can train the model by yourself, or you can download the pretrained model by the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz\ntar xzvf asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_10 data/demo_01_03.wav\n```\n"
  },
  {
    "path": "examples/aishell/asr0/RESULTS.md",
    "content": "# Aishell-1\n\n## Deepspeech2 Streaming\n\n| Model | Number of Params | Release | Config | Test set | Valid Loss | CER | \n| --- | --- | --- | --- | --- | --- | --- | \n| DeepSpeech2 | 45.18M | r0.2.0 | conf/deepspeech2_online.yaml + U2 Data pipline and spec aug + fbank161 | test | 6.876979827880859 | 0.0666 |\n| DeepSpeech2 | 45.18M | r0.2.0 | conf/deepspeech2_online.yaml + spec aug + fbank161 | test | 7.679287910461426 | 0.0718 |\n| DeepSpeech2 | 45.18M | r0.2.0 | conf/deepspeech2_online.yaml + spec aug | test | 7.708217620849609| 0.078 |\n| DeepSpeech2 | 45.18M | v2.2.0 | conf/deepspeech2_online.yaml + spec aug | test | 7.994938373565674 | 0.080 |  \n\n## Deepspeech2 Non-Streaming\n\n| Model | Number of Params | Release | Config | Test set | Valid Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- |\n| DeepSpeech2 | 122.3M | r1.0.1 | conf/deepspeech2.yaml + U2 Data pipline and spec aug + fbank161 | test | 5.780756044387817 | 0.055400 | \n| DeepSpeech2 | 58.4M | v2.2.0 | conf/deepspeech2.yaml + spec aug | test | 5.738585948944092 | 0.064000 |  \n| DeepSpeech2 | 58.4M | v2.1.0 | conf/deepspeech2.yaml + spec aug | test | 7.483316898345947 | 0.077860 |  \n| DeepSpeech2 | 58.4M | v2.1.0 | conf/deepspeech2.yaml | test | 7.299022197723389 | 0.078671 |\n| DeepSpeech2 | 58.4M | v2.0.0 | conf/deepspeech2.yaml | test | - | 0.078977 |  \n| --- | --- | --- | --- | --- | --- | --- |  \n| DeepSpeech2 | 58.4M | v1.8.5 | - | test | - | 0.080447 |\n"
  },
  {
    "path": "examples/aishell/asr0/conf/deepspeech2.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nmin_input_len: 0.0\nmax_input_len: 27.0 # second\nmin_output_len: 0.0\nmax_output_len: .inf\nmin_output_input_ratio: 0.00\nmax_output_input_ratio: .inf\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n\n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 5\nrnn_layer_size: 1024\nrnn_direction: bidirect # [forward, bidirect]\nnum_fc_layers: 0\nfc_layers_size_list: -1,\nuse_gru: False \nblank_id: 0\n  \n  \n###########################################\n#                Training                 #\n###########################################\nn_epoch: 50\naccum_grad: 1\nlr: 5.0e-4\nlr_decay: 0.93\nweight_decay: 1.0e-6\nglobal_grad_clip: 3.0\ndist_sampler: False\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n  \n"
  },
  {
    "path": "examples/aishell/asr0/conf/deepspeech2_online.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nmin_input_len: 0.0\nmax_input_len: 27.0 # second\nmin_output_len: 0.0\nmax_output_len: .inf\nmin_output_input_ratio: 0.00\nmax_output_input_ratio: .inf\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n\n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 5\nrnn_layer_size: 1024\nrnn_direction: forward # [forward, bidirect]\nnum_fc_layers: 0\nfc_layers_size_list: -1,\nuse_gru: False \nblank_id: 0\n  \n  \n###########################################\n#                Training                 #\n###########################################\nn_epoch: 30\naccum_grad: 1\nlr: 5.0e-4\nlr_decay: 0.93\nweight_decay: 1.0e-6\nglobal_grad_clip: 3.0\ndist_sampler: False\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n  \n"
  },
  {
    "path": "examples/aishell/asr0/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 161\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/aishell/asr0/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 32\nerror_rate_type: cer \ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/zh_giga.no_cna_cmn.prune01244.klm\nalpha: 2.2 #1.9\nbeta: 4.3\nbeam_size: 500\ncutoff_prob: 0.99\ncutoff_top_n: 40\nnum_proc_bsearch: 10\n"
  },
  {
    "path": "examples/aishell/asr0/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: cer \ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/zh_giga.no_cna_cmn.prune01244.klm\nalpha: 2.2\nbeta: 4.3\nbeam_size: 500\ncutoff_prob: 0.99\ncutoff_top_n: 40\nnum_proc_bsearch: 10\n"
  },
  {
    "path": "examples/aishell/asr0/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\ndict_dir=data/lang_char\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/aishell/aishell.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/aishell\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare Aishell failed. Terminated.\"\n        exit 1\n    fi\n\n    for dataset in train dev test; do\n        mv data/manifest.${dataset} data/manifest.${dataset}.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=161 \\\n    --delta_delta=false \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --sample_rate=16000 \\\n    --use_dB_normalization=False \\\n    --num_samples=2000 \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # download data, generate manifests\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type=\"char\" \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths \"data/manifest.train.raw\" \"data/manifest.dev.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for dataset in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n                --cmvn_path \"data/mean_std.json\" \\\n                --unit_type \"char\" \\\n                --vocab_path=\"${dict_dir}/vocab.txt\" \\\n                --manifest_path=\"data/manifest.${dataset}.raw\" \\\n                --output_path=\"data/manifest.${dataset}\"\n\n        if [ $? -ne 0 ]; then\n                echo \"Formt mnaifest failed. Terminated.\"\n                exit 1\n        fi\n    } &\n    done\n    wait\nfi\n\necho \"Aishell data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/download_lm_ch.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL='https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm'\nMD5=\"29e02312deb2e59b3c8686c7966d4fe3\"\nTARGET=${DIR}/zh_giga.no_cna_cmn.prune01244.klm\n\necho \"Start downloading the language model. The language model is large, please wait for a moment ...\"\ndownload $URL $MD5 $TARGET > /dev/null 2>&1\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nelse\n    echo \"Download the language model sucessfully\"\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nstage=0\nstop_stage=100\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\n# download language model\nbash local/download_lm_ch.sh\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # format the reference test file\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test.raw \\\n        --trans_ref data/manifest.test.text\n\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.rsl \\\n    --checkpoint_path ${ckpt_prefix}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n\n    # format the hyp file\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.rsl \\\n        --trans_hyp ${ckpt_prefix}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test.text ${ckpt_prefix}.rsl.text > ${ckpt_prefix}.error\nfi\n\nif [ ${stage} -le 101 ] && [ ${stop_stage} -ge 101 ]; then\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test.raw \\\n        --trans_ref_sclite data/manifest.test.text.sclite\n\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.rsl \\\n        --trans_hyp_sclite ${ckpt_prefix}.rsl.text.sclite\n\n    mkdir -p ${ckpt_prefix}_sclite\n    sclite -i wsj -r data/manifest.test.text.sclite -h  ${ckpt_prefix}.rsl.text.sclite  -e utf-8 -o all -O ${ckpt_prefix}_sclite -c NOASCII\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/test_export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\njit_model_export_path=$3\n\n# download language model\nbash local/download_lm_ch.sh > /dev/null 2>&1\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\npython3 -u ${BIN_DIR}/test_export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${jit_model_export_path}.rsl \\\n--export_path ${jit_model_export_path}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in evaluation!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\n# download language model\nbash local/download_lm_ch.sh\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\npython3 -u ${BIN_DIR}/test_wav.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${ckpt_prefix}.rsl \\\n--checkpoint_path ${ckpt_prefix} \\\n--audio_file ${audio_file}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in evaluation!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] || [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=10086\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nMODEL=deepspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/aishell/asr0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=100\nconf_path=conf/deepspeech2.yaml    #conf/deepspeech2.yaml or conf/deepspeech2_online.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=10\naudio_file=data/demo_01_03.wav\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}|| exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # test export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test_export.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}.jit|| exit -1\nfi\n\n# Optionally, you can add LM and test it with runtime.\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell/asr1/.gitignore",
    "content": "data\nexp\nlog\n"
  },
  {
    "path": "examples/aishell/asr1/README.md",
    "content": "# Transformer/Conformer ASR with Aishell\nThis example contains code used to train a [u2](https://arxiv.org/pdf/2012.05481.pdf) model (Transformer or [Conformer](https://arxiv.org/pdf/2005.08100.pdf) model) with [Aishell dataset](http://www.openslr.org/resources/33)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Get ctc alignment of test data using the final model         |\n| 5     | Infer the single audio file                                  |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\nsource path.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio_file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"conformer\"\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\n\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the ``data`` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh`is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml exp/conformer/checkpoints/avg_20\n```\n## Pretrained Model\nYou can get the pretrained transformer or conformer from [this](../../../docs/source/released_model.md)\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_transformer_aishell_ckpt_0.1.1.model.tar.gz\ntar xzvf asr1_transformer_aishell_ckpt_0.1.1.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer.yaml exp/transformer/checkpoints/avg_20\n```\n[The performance of the released models](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/aishell/asr1/RESULTS.md)\n## Stage 4: CTC Alignment \nIf you want to get the alignment between the audio and the text, you can use the ctc alignment. The code of this stage is shown below:\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # ctc alignment of test data\n     CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train the model, test it and do the alignment, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 4\n```\nor if you only need to train a model and do the alignment, you can use these scripts to escape stage 3(test stage):\n```bash\nbash run.sh --stage 0 --stop_stage 2\nbash run.sh --stage 4 --stop_stage 4\n```\nor you can also use these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\n# test stage is optional\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml exp/conformer/checkpoints/avg_20\nCUDA_VISIBLE_DEVICES= ./local/align.sh conf/conformer.yaml exp/conformer/checkpoints/avg_20\n```\n## Stage 5: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_transformer_aishell_ckpt_0.1.1.model.tar.gz\ntar xzvf transformer.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/transformer.yaml exp/transformer/checkpoints/avg_20 data/demo_01_03.wav\n```\n"
  },
  {
    "path": "examples/aishell/asr1/RESULTS.md",
    "content": "# Aishell\n\n## RoFormer Streaming\npaddle version: 2.5.0  \npaddlespeech version: 1.5.0\n\nTesla V100-SXM2-32GB: 1 node, 4 card\nGlobal BachSize: 32 * 4\nTraining Done: 1 day, 12:56:39.639646\n### `decoding.decoding_chunk_size=16`\n\n> chunk_size=16, ((16 - 1) * 4 + 7) * 10ms = (16 * 4 + 3) * 10ms = 670ms\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size & Left Chunks | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | attention | 16, -1 | - |  5.63 |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | ctc_greedy_search | 16, -1 | - | 6.13 |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | ctc_prefix_beam_search | 16, -1 | - | 6.13 |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | attention_rescoring | 16, -1 |  - | 5.44 |  \n\n### `decoding.decoding_chunk_size=-1`\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size & Left Chunks | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | attention | -1, -1 | - | 5.39 |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | ctc_greedy_search | -1, -1 | - |  5.51 |  \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | ctc_prefix_beam_search | -1, -1 | - | 5.51 | \n| roformer | 44.80M | conf/chunk_roformer.yaml | spec_aug | test | attention_rescoring | -1, -1 |  - | 4.99 |  \n\n\n## Conformer Streaming\npaddle version: 2.2.2  \npaddlespeech version: 1.4.1  \nNeed set `decoding.decoding_chunk_size=16` when decoding.\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size & Left Chunks | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- |  \n| conformer | 47.06M | conf/chunk_conformer.yaml | spec_aug | test | attention | 16, -1 | - | 0.056102 |  \n| conformer | 47.06M | conf/chunk_conformer.yaml | spec_aug | test | ctc_greedy_search | 16, -1 | - | 0.058160 |  \n| conformer | 47.06M | conf/chunk_conformer.yaml | spec_aug | test | ctc_prefix_beam_search | 16, -1 | - | 0.058160 |  \n| conformer | 47.06M | conf/chunk_conformer.yaml | spec_aug | test | attention_rescoring | 16, -1 |  - | 0.051968 |  \n\n\n## Conformer\npaddle version: 2.2.2  \npaddlespeech version: 1.0.1\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | CER |\n| --- | --- | --- | --- | --- | --- | --- | --- | \n| conformer | 47.07M  | conf/conformer.yaml | spec_aug | test | attention | - | 0.0522 |\n| conformer | 47.07M  | conf/conformer.yaml | spec_aug | test | ctc_greedy_search | - | 0.0481 |\n| conformer | 47.07M  | conf/conformer.yaml | spec_aug | test | ctc_prefix_beam_search | - | 0.0480 | \n| conformer | 47.07M  | conf/conformer.yaml | spec_aug | test | attention_rescoring | - | 0.0460 | \n\n\n## Transformer \n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |  \n| transformer | 31.95M  | conf/transformer.yaml | spec_aug | test | attention | 3.8103787302970886 | 0.056588 |  \n| transformer | 31.95M  | conf/transformer.yaml | spec_aug | test | ctc_greedy_search | 3.8103787302970886 | 0.059932 |  \n| transformer | 31.95M  | conf/transformer.yaml | spec_aug | test | ctc_prefix_beam_search | 3.8103787302970886 | 0.059989 |  \n| transformer | 31.95M  | conf/transformer.yaml | spec_aug | test | attention_rescoring | 3.8103787302970886 | 0.052273 |  \n"
  },
  {
    "path": "examples/aishell/asr1/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.9,\n      \"max_speed_rate\": 1.1,\n      \"num_rates\": 3\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 0,\n      \"warp_mode\": \"PIL\",\n      \"F\": 10,\n      \"n_freq_masks\": 2,\n      \"T\": 50,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": true\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/aishell/asr1/conf/chunk_conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1   # sublayer output dropout\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\n\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0\nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 240 \naccum_grad: 1\nglobal_grad_clip: 5.0\ndist_sampler: True\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/chunk_roformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1   # sublayer output dropout\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rope_pos' # abs_pos, rel_pos, rope_pos\n    selfattention_layer_type: 'rel_selfattn' # unused\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: transformer # transformer, bitransformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    r_num_blocks: 0    # only for bitransformer\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    reverse_weight: 0.0 # only for bitransformer\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\n\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0\nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 240 \naccum_grad: 1\nglobal_grad_clip: 5.0\ndist_sampler: True\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/chunk_roformer_bidecoder.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1   # sublayer output dropout\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rope_pos' # abs_pos, rel_pos, rope_pos\n    selfattention_layer_type: 'rel_selfattn' # unused\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: bitransformer # transformer, bitransformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 3\n    r_num_blocks: 3    # only for bitransformer\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    reverse_weight: 0.3 # only for bitransformer\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\n\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0\nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 240 \naccum_grad: 1\nglobal_grad_clip: 5.0\ndist_sampler: True\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/chunk_squeezeformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: squeezeformer\nencoder_conf:\n    encoder_dim: 256    # dimension of attention\n    output_size: 256    # dimension of output\n    attention_heads: 4\n    num_blocks: 12      # the number of encoder blocks\n    reduce_idx: 5\n    recover_idx: 11\n    feed_forward_expansion_factor: 8\n    input_dropout_rate: 0.1\n    feed_forward_dropout_rate: 0.1\n    attention_dropout_rate: 0.1\n    adaptive_scale: true\n    cnn_module_kernel: 31\n    normalize_before: false\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    time_reduction_layer_type: 'stream'\n    causal: true\n    use_dynamic_chunk: true\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\n\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0\nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 240 \naccum_grad: 1\nglobal_grad_clip: 5.0\ndist_sampler: True\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 150 \naccum_grad: 8\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/aishell/asr1/conf/squeezeformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: squeezeformer\nencoder_conf:\n    encoder_dim: 256    # dimension of attention\n    output_size: 256    # dimension of output\n    attention_heads: 4\n    num_blocks: 12      # the number of encoder blocks\n    reduce_idx: 5\n    recover_idx: 11\n    feed_forward_expansion_factor: 8\n    input_dropout_rate: 0.1\n    feed_forward_dropout_rate: 0.1\n    attention_dropout_rate: 0.1\n    adaptive_scale: true\n    cnn_module_kernel: 31\n    normalize_before: false\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    time_reduction_layer_type: 'conv1d'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 150 \naccum_grad: 8\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/transformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1   # sublayer output dropout\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                   Data                  #\n###########################################\n# https://yaml.org/type/float.html\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nunit_type: 'char'\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64 \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config: conf/preprocess.yaml \nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 30\naccum_grad: 2\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr1/conf/tuning/chunk_decode.yaml",
    "content": "beam_size: 10\ndecode_batch_size: 128\nerror_rate_type: cer \ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: 16 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: True  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/aishell/asr1/conf/tuning/decode.yaml",
    "content": "beam_size: 10\ndecode_batch_size: 128\nerror_rate_type: cer \ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/aishell/asr1/local/aishell_train_lms.sh",
    "content": "#!/bin/bash\n\n# To be run from one directory above this script.\n. ./path.sh\n\ntext=data/local/lm/text\nlexicon=data/local/dict/lexicon.txt\n\nfor f in \"$text\" \"$lexicon\"; do\n  [ ! -f $x ] && echo \"$0: No such file $f\" && exit 1;\ndone\n\n# Check SRILM tools\nif ! which ngram-count > /dev/null; then\n    echo \"srilm tools are not found, please download it and install it from: \"\n    echo \"http://www.speech.sri.com/projects/srilm/download.html\"\n    echo \"Then add the tools to your PATH\"\n    exit 1\nfi\n\n# This script takes no arguments.  It assumes you have already run\n# aishell_data_prep.sh.\n# It takes as input the files\n# data/local/lm/text\n# data/local/dict/lexicon.txt\ndir=data/local/lm\nmkdir -p $dir\n\n\ncleantext=$dir/text.no_oov\n\ncat $text | awk -v lex=$lexicon 'BEGIN{while((getline<lex) >0){ seen[$1]=1; } }\n  {for(n=1; n<=NF;n++) {  if (seen[$n]) { printf(\"%s \", $n); } else {printf(\"<SPOKEN_NOISE> \");} } printf(\"\\n\");}' \\\n  > $cleantext || exit 1;\n\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | sort | uniq -c | \\\n   sort -nr > $dir/word.counts || exit 1;\n\n# Get counts from acoustic training transcripts, and add  one-count\n# for each word in the lexicon (but not silence, we don't want it\n# in the LM-- we'll add it optionally later).\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | \\\n  cat - <(grep -w -v '!SIL' $lexicon | awk '{print $1}') | \\\n   sort | uniq -c | sort -nr > $dir/unigram.counts || exit 1;\n\ncat $dir/unigram.counts | awk '{print $2}' | cat - <(echo \"<s>\"; echo \"</s>\" ) > $dir/wordlist\n\nheldout_sent=10000 # Don't change this if you want result to be comparable with\n    # kaldi_lm results\nmkdir -p $dir\ncat $cleantext | awk '{for(n=2;n<=NF;n++){ printf $n; if(n<NF) printf \" \"; else print \"\"; }}' | \\\n  head -$heldout_sent > $dir/heldout\ncat $cleantext | awk '{for(n=2;n<=NF;n++){ printf $n; if(n<NF) printf \" \"; else print \"\"; }}' | \\\n  tail -n +$heldout_sent > $dir/train\n\nngram-count -text $dir/train -order 3 -limit-vocab -vocab $dir/wordlist -unk \\\n  -map-unk \"<UNK>\" -kndiscount -interpolate -lm $dir/lm.arpa\nngram -lm $dir/lm.arpa -ppl $dir/heldout"
  },
  {
    "path": "examples/aishell/asr1/local/align.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/alignment.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/aishell/aishell.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/aishell\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare Aishell failed. Terminated.\"\n        exit 1\n    fi\n\n    for dataset in train dev test; do\n        mv data/manifest.${dataset} data/manifest.${dataset}.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --sample_rate=16000 \\\n    --use_dB_normalization=False \\\n    --num_samples=-1 \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # download data, generate manifests\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type=\"char\" \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths \"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for dataset in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n            --cmvn_path \"data/mean_std.json\" \\\n            --unit_type \"char\" \\\n            --vocab_path=\"${dict_dir}/vocab.txt\" \\\n            --manifest_path=\"data/manifest.${dataset}.raw\" \\\n            --output_path=\"data/manifest.${dataset}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    } &\n    done\n    wait\nfi\n\necho \"Aishell data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nstage=0\nstop_stage=100\n\nsource utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # format the reference test file\n    python ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test.raw \\\n        --trans_ref data/manifest.test.text\n\n    for type in attention ctc_greedy_search; do\n        echo \"decoding ${type}\"\n        if [ ${chunk_mode} == true ];then\n            # stream decoding only support batchsize=1\n            batch_size=1\n        else\n            batch_size=64\n        fi\n        output_dir=${ckpt_prefix}\n        mkdir -p ${output_dir}\n        python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${output_dir}/${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n\n        fi\n        # format the hyp file\n        python ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${output_dir}/${type}.rsl \\\n            --trans_hyp ${output_dir}/${type}.rsl.text\n        python ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n            data/manifest.test.text ${output_dir}/${type}.rsl.text > ${output_dir}/${type}.error \n\n    done\n\n    for type in ctc_prefix_beam_search attention_rescoring; do\n        echo \"decoding ${type}\"\n        batch_size=1\n        output_dir=${ckpt_prefix}\n        mkdir -p ${output_dir}\n        python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${output_dir}/${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n        python ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${output_dir}/${type}.rsl \\\n            --trans_hyp ${output_dir}/${type}.rsl.text\n        python ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n            data/manifest.test.text ${output_dir}/${type}.rsl.text > ${output_dir}/${type}.error \n    done\nfi\n\nif [ ${stage} -le 101 ] && [ ${stop_stage} -ge 101 ]; then\n    echo \"using sclite to compute cer...\"\n    # format the reference test file for sclite\n    python ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test.raw \\\n        --trans_ref_sclite data/manifest.test.text.sclite\n    \n    output_dir=${ckpt_prefix}\n    for type in attention ctc_greedy_search ctc_prefix_beam_search attention_rescoring; do\n        python ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${output_dir}/${type}.rsl \\\n            --trans_hyp_sclite ${output_dir}/${type}.rsl.text.sclite\n\n        mkdir -p ${output_dir}/${type}_sclite\n        sclite -i wsj -r data/manifest.test.text.sclite -h  ${output_dir}/${type}.rsl.text.sclite  -e utf-8 -o all -O ${output_dir}/${type}_sclite -c NOASCII\n    done\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in  attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/tlg.sh",
    "content": "#!/bin/bash\n\nset -eo pipefail\n\nstage=-1\nstop_stage=100\ncorpus=aishell\nlmtype=srilm\n\nsource utils/parse_options.sh\n\ndata=${MAIN_ROOT}/dataset/${corpus}\nlexicon=$data/resource_aishell/lexicon.txt\ntext=$data/data_aishell/transcript/aishell_transcript_v0.8.txt\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # 7.1 Prepare dict\n    unit_file=data/vocab.txt\n    mkdir -p data/local/dict\n    cp $unit_file data/local/dict/units.txt\n    utils/fst/prepare_dict.py \\\n        --unit_file $unit_file \\\n        --in_lexicon ${lexicon} \\\n        --out_lexicon data/local/dict/lexicon.txt\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # 7.2 Train lm\n    lm=data/local/lm\n    mkdir -p data/train\n    mkdir -p $lm\n    utils/manifest_key_value.py \\\n        --manifest_path data/manifest.train \\\n        --output_path data/train\n    utils/filter_scp.pl data/train/text \\\n        $text > $lm/text\n    if [ $lmtype == 'srilm' ];then\n        local/aishell_train_lms.sh\n    else\n        utils/ngram_train.sh --order 3 $lm/text $lm/lm.arpa\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then \n    # 7.3 Build decoding TLG\n    utils/fst/compile_lexicon_token_fst.sh \\\n        data/local/dict data/local/tmp data/local/lang\n    utils/fst/make_tlg.sh data/local/lm data/local/lang data/lang_test || exit 1;\nfi\n\necho \"Aishell build TLG done.\"\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nprofiler_options=\nbenchmark_batch_size=0\nbenchmark_max_step=0\n\n# seed may break model convergence\nseed=0\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\n    echo \"using seed $seed & FLAGS_cudnn_deterministic=True ...\"\nfi\n\nif [ $# -lt 2 ] || [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\necho ${ips_config}\n\nmkdir -p exp\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nfi\n\n\nif [ ${seed} != 0  ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n# model exp\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n\n\n# srilm\nexport LIBLBFGS=${MAIN_ROOT}/tools/liblbfgs-1.10\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:${LIBLBFGS}/lib/.libs\nexport SRILM=${MAIN_ROOT}/tools/srilm\nexport PATH=${PATH}:${SRILM}/bin:${SRILM}/bin/i686-m64\n\n# Kaldi\nexport KALDI_ROOT=${MAIN_ROOT}/tools/kaldi\n[ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh\nexport PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH\n[ ! -f $KALDI_ROOT/tools/config/common_path.sh ] && echo >&2 \"The standard file $KALDI_ROOT/tools/config/common_path.sh is not present, can not using Kaldi!\"\n[ -f $KALDI_ROOT/tools/config/common_path.sh ] && . $KALDI_ROOT/tools/config/common_path.sh\n"
  },
  {
    "path": "examples/aishell/asr1/run.sh",
    "content": "#!/bin/bash\nsource path.sh\nset -e\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/conformer.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=30\naudio_file=data/demo_01_03.wav\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\n# Optionally, you can add LM and test it with runtime.\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n\n# Not supported at now!!!\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\n# Need further installation! Read the install.md to complete further installation\nif [ ${stage} -le 101 ] && [ ${stop_stage} -ge 101 ]; then\n    echo \"warning: deps on kaldi and srilm, please make sure installed.\"\n    # train lm and build TLG\n    ./local/tlg.sh --corpus aishell --lmtype srilm\nfi\n"
  },
  {
    "path": "examples/aishell/asr3/README.md",
    "content": "# Wav2vec2ASR with Aishell\nThis example contains code used to finetune [wav2vec2.0](https://https://arxiv.org/pdf/2006.11477.pdf) model with [Aishell dataset](http://www.openslr.org/resources/33)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Download the pretrained wav2vec2 model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Infer the single audio file                                  |\n\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"wav2vec2ASR\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n|-- train.meta\n|-- train.csv\n|-- dev.csv\n|-- test.csv\n```\n\nStage 0 also downloads the Chinese pre-trained [wav2vec2](https://paddlespeech.cdn.bcebos.com/wav2vec/chinese-wav2vec2-large.pdparams) model.\n```bash\nmkdir -p exp/wav2vec2\nwget -P exp/wav2vec2 https://paddlespeech.cdn.bcebos.com/wav2vec/chinese-wav2vec2-large.pdparams\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below. Note: We only train one epoch for wav2vec2ASR, thus the `avg_num` is set to 1.\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\navg.sh best exp/wav2vec2ASR/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\navg.sh best exp/wav2vec2ASR/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1\n```\n## Pretrained Model\nYou can get the pretrained wav2vec2ASR from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz\ntar xzvf wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n\n## Stage 4: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz\ntar xzvf wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1 data/demo_01_03.wav\n```\n"
  },
  {
    "path": "examples/aishell/asr3/RESULT.md",
    "content": "# AISHELL\n\n## Version\n\n* paddle version: develop (commit id: daea892c67e85da91906864de40ce9f6f1b893ae)\n* paddlespeech version: develop (commit id: c14b4238b256693281e59605abff7c9435b3e2b2)\n* paddlenlp version: 2.5.2 \n\n## Device\n* python: 3.7\n* cuda: 10.2\n* cudnn: 7.6\n\n## Result\ntrain: Epoch 80, 2*V100-32G, batchsize:5\n| Model | Params | Config | Augmentation| Test set | Decode method | WER |  \n| --- | --- | --- | --- | --- | --- | --- |\n| wav2vec2ASR | 324.49 M | conf/wav2vec2ASR.yaml | spec_aug | test-set | greedy search | 5.1009 |  \n"
  },
  {
    "path": "examples/aishell/asr3/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/aishell/asr3/conf/preprocess.yaml",
    "content": "process:\n    # use raw audio\n  - type: wav_process\n"
  },
  {
    "path": "examples/aishell/asr3/conf/train_with_wav2vec.yaml",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/recipes/AISHELL-1/ASR/CTC/hparams/train_with_wav2vec.yaml)\n\n# ############################################################################\n# Model: CTC-wav2vec2\n# Encoder: wav2vec2\n# Decoder: -\n# Tokens: Char\n# losses: CTC\n# Training: AISHELL-1\n# Authors:  Yingzhi WANG 2022\n# ############################################################################\n\noutput_folder: !ref data\ncer_file: !ref <output_folder>/cer.txt\nsave_folder: !ref <output_folder>/save\ntrain_log: !ref <output_folder>/train_log.txt\n\n# Data files\ndata_folder: data/aishell # e,g./path/to/aishell\n\nskip_prep: False\nckpt_interval_minutes: 15 # save checkpoint every N min\ntrain_data: !ref <output_folder>/train.csv\nvalid_data: !ref <output_folder>/dev.csv\ntest_data: !ref <output_folder>/test.csv\n\nwav2vec2_hub: TencentGameMate/chinese-wav2vec2-large\n\n# Training parameters\nnumber_of_epochs: 80\nlr: 1.0\nlr_wav2vec: 0.0001\nsorting: ascending\nauto_mix_prec: False\nsample_rate: 16000\n\n# With data_parallel batch_size is split into N jobs\n# With DDP batch_size is multiplied by N jobs\n# Must be 8 per GPU to fit 32GB of VRAM\nbatch_size: 5\ntest_batch_size: 1 # need set to 1 when decoding\n\ndynamic_batching: False\ndynamic_batch_sampler:\n   feats_hop_size: 0.01\n   max_batch_len: 15 # in terms of \"duration\" in annotations by default, second here\n   left_bucket_len: 200 # old implementation attributs\n   multiplier: 1.1 # old implementation attributs\n   shuffle_ex: False # if true re-creates batches at each epoch shuffling examples.\n   num_buckets: 10 # floor(log(max_batch_len/left_bucket_len, multiplier)) + 1\n   batch_ordering: ascending\n\nnum_workers: 6\n\n# Dataloader options\ntrain_dataloader_opts:\n   batch_size: !ref <batch_size>\n   num_workers: !ref <num_workers>\nvalid_dataloader_opts:\n   batch_size: !ref <test_batch_size>\n   num_workers: !ref <num_workers>\ntest_dataloader_opts:\n   batch_size: !ref <test_batch_size>\n   num_workers: !ref <num_workers>\n\nwav2vec_output_dim: 1024\ndnn_neurons: 1024\nfreeze_wav2vec: False\ndropout: 0.15\n\ntokenizer: !apply:paddlenlp.transformers.AutoTokenizer.from_pretrained\n   pretrained_model_name_or_path: bert-base-chinese\n# bert-base-chinese tokens length\noutput_neurons: 21128\n\n# Decoding parameters\n# Be sure that the bos and eos index match with the BPEs ones\nblank_index: 0\n\n# AISHELL-1 has spaces between words in the transcripts,\n# which Chinese writing normally does not do.\n# If remove_spaces, spaces are removed\n# from the transcript before computing CER.\n# (e.g., 祝 可爱 的 你 —> 祝可爱的你)\nremove_spaces: True\nsplit_tokens: !apply:operator.not_ [!ref <remove_spaces>]\n"
  },
  {
    "path": "examples/aishell/asr3/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 1\nerror_rate_type: cer\ndecoding_method: ctc_greedy_search  # 'ctc_greedy_search', 'ctc_prefix_beam_search'\nbeam_size: 10\n"
  },
  {
    "path": "examples/aishell/asr3/conf/wav2vec2ASR.yaml",
    "content": "############################################\n#          Network Architecture           #\n############################################\nfreeze_wav2vec2: False\nnormalize_wav: True\noutput_norm: True\ninit_type: 'kaiming_uniform' # !Warning: need to convergence\nenc:\n  input_shape: 1024\n  dnn_blocks: 3\n  dnn_neurons: 1024\n  activation: True\n  normalization: True\n  dropout_rate: [0.15, 0.15, 0.0]\nctc:\n  enc_n_units: 1024\n  blank_id: 0\n  dropout_rate: 0.0\n\naudio_augment:\n  speeds: [90, 100, 110]\n\nspec_augment:\n  time_warp: True\n  time_warp_window: 5\n  time_warp_mode: bicubic\n  freq_mask: True\n  n_freq_mask: 2\n  time_mask: True\n  n_time_mask: 2\n  replace_with_zero: False\n  freq_mask_width: 30\n  time_mask_width: 40\nwav2vec2_params_path: exp/wav2vec2/chinese-wav2vec2-large.pdparams\n\n\n############################################\n#               Wav2Vec2.0                 #\n############################################\n# vocab_size: 1000000\nhidden_size: 1024\nnum_hidden_layers: 24\nnum_attention_heads: 16\nintermediate_size: 4096\nhidden_act: gelu\nhidden_dropout: 0.1\nactivation_dropout: 0.0\nattention_dropout: 0.1\nfeat_proj_dropout: 0.1\nfeat_quantizer_dropout: 0.0\nfinal_dropout: 0.0\nlayerdrop: 0.1\ninitializer_range: 0.02\nlayer_norm_eps: 1e-5\nfeat_extract_norm: layer\nfeat_extract_activation: gelu\nconv_dim: [512, 512, 512, 512, 512, 512, 512]\nconv_stride: [5, 2, 2, 2, 2, 2, 2]\nconv_kernel: [10, 3, 3, 3, 3, 2, 2]\nconv_bias: True\nnum_conv_pos_embeddings: 128\nnum_conv_pos_embedding_groups: 16\ndo_stable_layer_norm: True\napply_spec_augment: False\nmask_channel_length: 10\nmask_channel_min_space: 1\nmask_channel_other: 0.0\nmask_channel_prob: 0.0\nmask_channel_selection: static\nmask_feature_length: 10\nmask_feature_min_masks: 0\nmask_feature_prob: 0.0\nmask_time_length: 10\nmask_time_min_masks: 2\nmask_time_min_space: 1\nmask_time_other: 0.0\nmask_time_prob: 0.075\nmask_time_selection: static\nnum_codevectors_per_group: 320\nnum_codevector_groups: 2\ncontrastive_logits_temperature: 0.1\nnum_negatives: 100\ncodevector_dim: 256\nproj_codevector_dim: 256\ndiversity_loss_weight: 0.1\nuse_weighted_layer_sum: False\n# pad_token_id: 0\n# bos_token_id: 1\n# eos_token_id: 2\nadd_adapter: False\nadapter_kernel_size: 3\nadapter_stride: 2\nnum_adapter_layers: 3\noutput_hidden_size: None\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nvocab_filepath: data/lang_char/vocab.txt \n\n###########################################\n#              Dataloader                 #\n###########################################\n\nunit_type: 'char'\ntokenizer: bert-base-chinese\nmean_std_filepath: \npreprocess_config: conf/preprocess.yaml\nsortagrad: -1 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 5  # Different batch_size may cause large differences in results\nmaxlen_in: 51200000000  # if input length  > maxlen-in batchsize is automatically reduced\nmaxlen_out: 1500000  # if output length > maxlen-out batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 6\nsubsampling_factor: 1\nnum_encs: 1\ndist_sampler: True\nshortest_first: True\nreturn_lens_rate: True\n\n###########################################\n#        use speechbrain dataloader       #\n###########################################\nuse_sb_pipeline: True  # whether use speechbrain pipeline. Default is True.\nsb_pipeline_conf: conf/train_with_wav2vec.yaml\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 80\naccum_grad: 1\nglobal_grad_clip: 5.0\n\nmodel_optim: sgd\nmodel_optim_conf:\n  lr: 1.0\n  weight_decay: 0.0\n\nwav2vec2_optim: adam\nwav2vec2_optim_conf:\n  lr: 0.0001\n  weight_decay: 0.0\n\nmodel_scheduler: newbobscheduler\nmodel_scheduler_conf:\n  improvement_threshold: 0.0025\n  annealing_factor: 0.8\n  patient: 0\nwav2vec2_scheduler: newbobscheduler\nwav2vec2_scheduler_conf:\n  improvement_threshold: 0.0025\n  annealing_factor: 0.9\n  patient: 0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n"
  },
  {
    "path": "examples/aishell/asr3/conf/wav2vec2ASR_adadelta.yaml",
    "content": "############################################\n#          Network Architecture           #\n############################################\nfreeze_wav2vec2: False\nnormalize_wav: True\noutput_norm: True\ninit_type: 'kaiming_uniform' # !Warning: need to convergence\nenc:\n  input_shape: 1024\n  dnn_blocks: 3\n  dnn_neurons: 1024\n  activation: True\n  normalization: True\n  dropout_rate: [0.15, 0.15, 0.0]\nctc:\n  enc_n_units: 1024\n  blank_id: 0\n  dropout_rate: 0.0\n\naudio_augment:\n  speeds: [90, 100, 110]\n\nspec_augment:\n  time_warp: True\n  time_warp_window: 5\n  time_warp_mode: bicubic\n  freq_mask: True\n  n_freq_mask: 2\n  time_mask: True\n  n_time_mask: 2\n  replace_with_zero: False\n  freq_mask_width: 30\n  time_mask_width: 40\nwav2vec2_params_path: exp/wav2vec2/chinese-wav2vec2-large.pdparams\n\n\n############################################\n#               Wav2Vec2.0                 #\n############################################\n# vocab_size: 1000000\nhidden_size: 1024\nnum_hidden_layers: 24\nnum_attention_heads: 16\nintermediate_size: 4096\nhidden_act: gelu\nhidden_dropout: 0.1\nactivation_dropout: 0.0\nattention_dropout: 0.1\nfeat_proj_dropout: 0.1\nfeat_quantizer_dropout: 0.0\nfinal_dropout: 0.0\nlayerdrop: 0.1\ninitializer_range: 0.02\nlayer_norm_eps: 1e-5\nfeat_extract_norm: layer\nfeat_extract_activation: gelu\nconv_dim: [512, 512, 512, 512, 512, 512, 512]\nconv_stride: [5, 2, 2, 2, 2, 2, 2]\nconv_kernel: [10, 3, 3, 3, 3, 2, 2]\nconv_bias: True\nnum_conv_pos_embeddings: 128\nnum_conv_pos_embedding_groups: 16\ndo_stable_layer_norm: True\napply_spec_augment: False\nmask_channel_length: 10\nmask_channel_min_space: 1\nmask_channel_other: 0.0\nmask_channel_prob: 0.0\nmask_channel_selection: static\nmask_feature_length: 10\nmask_feature_min_masks: 0\nmask_feature_prob: 0.0\nmask_time_length: 10\nmask_time_min_masks: 2\nmask_time_min_space: 1\nmask_time_other: 0.0\nmask_time_prob: 0.075\nmask_time_selection: static\nnum_codevectors_per_group: 320\nnum_codevector_groups: 2\ncontrastive_logits_temperature: 0.1\nnum_negatives: 100\ncodevector_dim: 256\nproj_codevector_dim: 256\ndiversity_loss_weight: 0.1\nuse_weighted_layer_sum: False\n# pad_token_id: 0\n# bos_token_id: 1\n# eos_token_id: 2\nadd_adapter: False\nadapter_kernel_size: 3\nadapter_stride: 2\nnum_adapter_layers: 3\noutput_hidden_size: None\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nvocab_filepath: data/lang_char/vocab.txt \n\n###########################################\n#              Dataloader                 #\n###########################################\n\nunit_type: 'char'\ntokenizer: bert-base-chinese\nmean_std_filepath: \npreprocess_config: conf/preprocess.yaml\nsortagrad: -1 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 5  # Different batch_size may cause large differences in results\nmaxlen_in: 51200000000  # if input length  > maxlen-in batchsize is automatically reduced\nmaxlen_out: 1500000  # if output length > maxlen-out batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 6\nsubsampling_factor: 1\nnum_encs: 1\ndist_sampler: True\nshortest_first: True\nreturn_lens_rate: True\n\n###########################################\n#        use speechbrain dataloader       #\n###########################################\nuse_sb_pipeline: True  # whether use speechbrain pipeline. Default is True.\nsb_pipeline_conf: conf/train_with_wav2vec.yaml\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 80\naccum_grad: 1\nglobal_grad_clip: 5.0\n\nmodel_optim: adadelta\nmodel_optim_conf:\n  lr: 1.0\n  weight_decay: 0.0\n  rho: 0.95\n  epsilon: 1.0e-8\n\nwav2vec2_optim: adam\nwav2vec2_optim_conf:\n  lr: 0.0001\n  weight_decay: 0.0\n\nmodel_scheduler: newbobscheduler\nmodel_scheduler_conf:\n  improvement_threshold: 0.0025\n  annealing_factor: 0.8\n  patient: 0\nwav2vec2_scheduler: newbobscheduler\nwav2vec2_scheduler_conf:\n  improvement_threshold: 0.0025\n  annealing_factor: 0.9\n  patient: 0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/aishell/asr3/local/aishell_prepare.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# Modified from speechbrain 2023\n# (https://github.com/speechbrain/speechbrain/blob/develop/recipes/AISHELL-1/aishell_prepare.py)\nimport argparse\nimport csv\nimport glob\nimport logging\nimport os\n\nfrom paddlespeech.s2t.io.speechbrain.dataio import read_audio\n\nlogger = logging.getLogger(__name__)\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--data_folder\",\n    default=DATA_HOME + \"/Aishell\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--save_folder\",\n    default=\"data/\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nparser.add_argument(\n    \"--skip_prep\",\n    default=False,\n    type=bool,\n    help=\"If True, skip data preparation. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef prepare_aishell(data_folder, save_folder, skip_prep=False):\n    \"\"\"\n    This function prepares the AISHELL-1 dataset.\n    If the folder does not exist, the zip file will be extracted. If the zip file does not exist, it will be downloaded.\n    data_folder : path to AISHELL-1 dataset.\n    save_folder: path where to store the manifest csv files.\n    skip_prep: If True, skip data preparation.\n    \"\"\"\n    if skip_prep:\n        return\n\n    # Create filename-to-transcript dictionary\n    filename2transcript = {}\n    with open(\n            os.path.join(data_folder,\n                         \"data_aishell/transcript/aishell_transcript_v0.8.txt\"),\n            \"r\", ) as f:\n        lines = f.readlines()\n        for line in lines:\n            key = line.split()[0]\n            value = \" \".join(line.split()[1:])\n            filename2transcript[key] = value\n\n    splits = [\n        \"train\",\n        \"dev\",\n        \"test\",\n    ]\n    ID_start = 0  # needed to have a unique ID for each audio\n    for split in splits:\n        new_filename = os.path.join(save_folder, split) + \".csv\"\n        if os.path.exists(new_filename):\n            continue\n        logger.info(\"Preparing %s...\" % new_filename)\n\n        csv_output = [[\"ID\", \"duration\", \"wav\", \"transcript\"]]\n        entry = []\n\n        all_wavs = glob.glob(\n            os.path.join(data_folder, \"data_aishell/wav\") + \"/\" + split +\n            \"/*/*.wav\")\n        for i in range(len(all_wavs)):\n            filename = all_wavs[i].split(\"/\")[-1].split(\".wav\")[0]\n            if filename not in filename2transcript:\n                continue\n            signal = read_audio(all_wavs[i])\n            duration = signal.shape[0] / 16000\n            transcript_ = filename2transcript[filename]\n            csv_line = [\n                ID_start + i,\n                str(duration),\n                all_wavs[i],\n                transcript_,\n            ]\n            entry.append(csv_line)\n\n        csv_output = csv_output + entry\n\n        with open(new_filename, mode=\"w\") as csv_f:\n            csv_writer = csv.writer(\n                csv_f, delimiter=\",\", quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            for line in csv_output:\n                csv_writer.writerow(line)\n\n        msg = \"\\t%s successfully created!\" % (new_filename)\n        logger.info(msg)\n\n        ID_start += len(all_wavs)\n\n\ndef main():\n    if args.data_folder.startswith('~'):\n        args.data_folder = os.path.expanduser(args.data_folder)\n\n    prepare_aishell(args.data_folder, args.save_folder, skip_prep=False)\n\n    print(\"Data csv prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "examples/aishell/asr3/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=3\ndict_dir=data/lang_char\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/aishell/aishell.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/aishell\"\n\n    #generate csv file for speechbrain dataloader\n    python3 local/aishell_prepare.py \\\n    --data_folder=\"${TARGET_DIR}/aishell\" \\\n    --save_folder=\"data/\"\n\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare Aishell failed. Terminated.\"\n        exit 1\n    fi\n\n    for dataset in train dev test; do\n        mv data/manifest.${dataset} data/manifest.${dataset}.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --sample_rate=16000 \\\n    --use_dB_normalization=False \\\n    --num_samples=-1 \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # download data, generate manifests\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type=\"char\" \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths \"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for dataset in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n            --cmvn_path \"data/mean_std.json\" \\\n            --unit_type \"char\" \\\n            --vocab_path=\"${dict_dir}/vocab.txt\" \\\n            --manifest_path=\"data/manifest.${dataset}.raw\" \\\n            --output_path=\"data/manifest.${dataset}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    } &\n    done\n    wait\nfi\necho \"Aishell data preparation done.\"\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    mkdir -p exp/wav2vec2\n    echo \"Pretrained wav2vec2 model download\"\n    wget -P exp/wav2vec2 https://paddlespeech.cdn.bcebos.com/wav2vec/chinese-wav2vec2-large.pdparams\nfi\n\nexit 0\n\n"
  },
  {
    "path": "examples/aishell/asr3/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nexpdir=exp\ndatadir=data\n\ntrain_set=train\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\npython3 ${MAIN_ROOT}/utils/format_rsl.py \\\n    --origin_ref data/manifest.test.raw \\\n    --trans_ref data/manifest.test.text\n\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\nfor type in ctc_prefix_beam_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr3/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr3/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] || [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nresume=$3\nips=$4\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=2\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# export FLAGS_cudnn_exhaustive_search=true\n# export FLAGS_conv_workspace_size_limit=4000\n# export FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nelse\npython3 -m paddle.distributed.launch --log_dir=${ckpt_name} --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/aishell/asr3/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=wav2vec2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/aishell/asr3/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2,3\nstage=0\nstop_stage=4\nconf_path=conf/wav2vec2ASR.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=1\nresume=         # xx e.g. 30\nexport FLAGS_cudnn_deterministic=1\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\naudio_file=data/demo_01_03.wav\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\" \n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${resume} ${ips} \nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh last exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # greedy search decoder\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/README.md",
    "content": "# Aishell3\n\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n* vc0 - Tacotron2 Voice Cloning with GE2E\n* vc1 - FastSpeech2 Voice Cloning with GE2E\n* vc2 - FastSpeech2 Voice Cloning with ECAPA-TDNN\n* ernie_sat - ERNIE-SAT\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/README.md",
    "content": "# ERNIE-SAT with AISHELL-3 dataset\n[ERNIE-SAT](https://arxiv.org/abs/2211.03545) speech-text joint pretraining framework, which achieves SOTA results in cross-lingual multi-speaker speech synthesis and cross-lingual speech editing tasks, It can be applied to a series of scenarios such as Speech Editing, personalized Speech Synthesis, and Voice Cloning.\n\n## Model Framework\nIn ERNIE-SAT, we propose two innovations:\n- In the pretraining process, the phonemes corresponding to Chinese and English are used as input to achieve cross-language and personalized soft phoneme mapping\n- The joint mask learning of speech and text is used to realize the alignment of speech and text\n\n<p align=\"center\">\n    <img src=\"https://user-images.githubusercontent.com/24568452/186110814-1b9c6618-a0ab-4c0c-bb3d-3d860b0e8cc2.png\" />\n</p>\n\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [HiFiGAN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc5) as the neural vocoder.\n\nDownload pretrained HiFiGAN model from [hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip) and unzip it.\n```bash\nunzip hifigan_aishell3_ckpt_0.2.0.zip\n```\nHiFiGAN checkpoint contains files listed below.\n```text\nhifigan_aishell3_ckpt_0.2.0\n├── default.yaml                    # default config used to train HiFiGAN\n├── feats_stats.npy                 # statistics used to normalize spectrogram when training HiFiGAN\n└── snapshot_iter_2500000.pdz       # generator parameters of HiFiGAN\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n##  Speech Synthesis and Speech Editing\n### Prepare\n**prepare aligner**\n```bash\nmkdir -p tools/aligner\ncd tools\n# download MFA\nwget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz\n# extract MFA\ntar xvf montreal-forced-aligner_linux.tar.gz\n# fix .so of MFA\ncd montreal-forced-aligner/lib\nln -snf libpython3.6m.so.1.0 libpython3.6m.so\ncd -\n# download align models and dicts\ncd aligner\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/aishell3_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/simple.lexicon\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/vctk_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/cmudict-0.7b\ncd ../../\n```\n**prepare pretrained FastSpeech2 models**\n\nERNIE-SAT use FastSpeech2 as phoneme duration predictor:\n```bash\nmkdir download\ncd download\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip\nunzip fastspeech2_conformer_baker_ckpt_0.5.zip\nunzip fastspeech2_nosil_ljspeech_ckpt_0.5.zip\ncd ../\n```\n**prepare source data**\n```bash\nmkdir source\ncd source\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540307.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540428.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/LJ050-0278.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p243_313.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p299_096.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/this_was_not_the_show_for_me.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/README.md\ncd ../\n```\n\nYou can check the text of downloaded wavs in `source/README.md`.\n### Speech Synthesis and Speech Editing\n```bash\n./run.sh --stage 3 --stop-stage 3 --gpus 0\n```\n`stage 3` of `run.sh` calls `local/synthesize_e2e.sh`. `synthesize_e2e.sh` is a script for performing both **Speech Synthesis** and **Speech Editing** tasks by default. It converts input text into speech for synthesis and modifies existing speech based on new text content for editing.\n\nYou can modify `--wav_path`、`--old_str` and `--new_str` yourself, `--old_str`  should be the text corresponding to the audio of  `--wav_path`, `--new_str` should be designed according to `--task_name`, both `--source_lang` and `--target_lang` should be `zh` for model trained with AISHELL3 dataset.\n## Pretrained Model\nPretrained ErnieSAT model:\n- [erniesat_aishell3_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_aishell3_ckpt_1.2.0.zip)\n\nModel | Step | eval/mlm_loss | eval/loss\n:-------------:| :------------:| :-----: | :-----:\ndefault| 8(gpu) x 289500|51.723782|51.723782\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/conf/default.yaml",
    "content": "# This configuration tested on 8 GPUs (A100) with 80GB GPU memory.\n# It takes around 3 days to finish the training,You can adjust\n# batch_size、num_workers here and ngpu in local/train.sh for your machine\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\nmean_phn_span: 8\nmlm_prob: 0.8\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 40\nnum_workers: 8\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    text_masking: false\n    postnet_layers: 5\n    postnet_filts: 5\n    postnet_chans: 256\n    encoder_type: conformer\n    decoder_type: conformer\n    enc_input_layer: sega_mlm\n    enc_pre_speech_layer: 0\n    enc_cnn_module_kernel: 7\n    enc_attention_dim: 384\n    enc_attention_heads: 2\n    enc_linear_units: 1536\n    enc_num_blocks: 4\n    enc_dropout_rate: 0.2\n    enc_positional_dropout_rate: 0.2\n    enc_attention_dropout_rate: 0.2\n    enc_normalize_before: true\n    enc_macaron_style: true\n    enc_use_cnn_module: true\n    enc_selfattention_layer_type: legacy_rel_selfattn\n    enc_activation_type: swish\n    enc_pos_enc_layer_type: legacy_rel_pos\n    enc_positionwise_layer_type: conv1d\n    enc_positionwise_conv_kernel_size: 3\n    dec_cnn_module_kernel: 31\n    dec_attention_dim: 384\n    dec_attention_heads: 2\n    dec_linear_units: 1536\n    dec_num_blocks: 4\n    dec_dropout_rate: 0.2\n    dec_positional_dropout_rate: 0.2\n    dec_attention_dropout_rate: 0.2\n    dec_macaron_style: true\n    dec_use_cnn_module: true\n    dec_selfattention_layer_type: legacy_rel_selfattn\n    dec_activation_type: swish\n    dec_pos_enc_layer_type: legacy_rel_pos\n    dec_positionwise_layer_type: conv1d\n    dec_positionwise_conv_kernel_size: 3\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\nscheduler_params:\n    d_model: 384\n    warmup_steps: 4000\ngrad_clip: 1.0\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1500\nnum_snapshots: 50\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 0\n\ntoken_list:\n- <blank>\n- <unk>\n- d\n- sp\n- sh\n- ii\n- j\n- zh\n- l\n- x\n- b\n- g\n- uu\n- e5\n- h\n- q\n- m\n- i1\n- t\n- z\n- ch\n- f\n- s\n- u4\n- ix4\n- i4\n- n\n- i3\n- iu3\n- vv\n- ian4\n- ix2\n- r\n- e4\n- ai4\n- k\n- ing2\n- a1\n- en2\n- ui4\n- ong1\n- uo3\n- u2\n- u3\n- ao4\n- ee\n- p\n- an1\n- eng2\n- i2\n- in1\n- c\n- ai2\n- ian2\n- e2\n- an4\n- ing4\n- v4\n- ai3\n- a5\n- ian3\n- eng1\n- ong4\n- ang4\n- ian1\n- ing1\n- iy4\n- ao3\n- ang1\n- uo4\n- u1\n- iao4\n- iu4\n- a4\n- van2\n- ie4\n- ang2\n- ou4\n- iang4\n- ix1\n- er4\n- iy1\n- e1\n- en1\n- ui2\n- an3\n- ei4\n- ong2\n- uo1\n- ou3\n- uo2\n- iao1\n- ou1\n- an2\n- uan4\n- ia4\n- ia1\n- ang3\n- v3\n- iu2\n- iao3\n- in4\n- a3\n- ei3\n- iang3\n- v2\n- eng4\n- en3\n- aa\n- uan1\n- v1\n- ao1\n- ve4\n- ie3\n- ai1\n- ing3\n- iang1\n- a2\n- ui1\n- en4\n- en5\n- in3\n- uan3\n- e3\n- ie1\n- ve2\n- ei2\n- in2\n- ix3\n- uan2\n- iang2\n- ie2\n- ua4\n- ou2\n- uai4\n- er2\n- eng3\n- uang3\n- un1\n- ong3\n- uang4\n- vn4\n- un2\n- iy3\n- iz4\n- ui3\n- iao2\n- iong4\n- un4\n- van4\n- ao2\n- uang1\n- iy5\n- o2\n- ei1\n- ua1\n- iu1\n- uang2\n- er5\n- o1\n- un3\n- vn1\n- vn2\n- o4\n- ve1\n- van3\n- ua2\n- er3\n- iong3\n- van1\n- ia2\n- iy2\n- ia3\n- iong1\n- uo5\n- oo\n- ve3\n- ou5\n- uai3\n- ian5\n- iong2\n- uai2\n- uai1\n- ua3\n- vn3\n- ia5\n- ie5\n- ueng1\n- o5\n- o3\n- iang5\n- ei5\n- <sos/eos>\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# hifigan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --erniesat_config=${config_path} \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo 'speech synthesize !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=synthesize \\\n        --wav_path=source/SSB03540307.wav \\\n        --old_str='请播放歌曲小苹果' \\\n        --new_str='歌曲真好听' \\\n        --source_lang=zh \\\n        --target_lang=zh \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_gen.wav\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo 'speech edit !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=edit \\\n        --wav_path=source/SSB03540428.wav \\\n        --old_str='今天天气很好' \\\n        --new_str='今天心情很好' \\\n        --source_lang=zh \\\n        --target_lang=zh \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_edit.wav\nfi\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=8 \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/aishell3/ernie_sat/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=ernie_sat\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/aishell3/ernie_sat/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3,4,5,6,7\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_289500.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/tts3/README.md",
    "content": "# FastSpeech2 with AISHELL-3\nThis example contains code used to train a [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [AISHELL-3](http://www.aishelltech.com/aishell_3).\n\nAISHELL-3 is a large-scale and high-fidelity multi-speaker Mandarin speech corpus that could be used to train multi-speaker Text-to-Speech (TTS) systems.\n\nWe use AISHELL-3 to train a multi-speaker fastspeech2 model here.\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n \n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, a path of energy features, speaker, and id of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n6. `--speaker-dict` is the path of the speaker id map file when training a multi-speaker FastSpeech2.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the neural vocoder.\nDownload the pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat`, `--phones_dict` `--speaker_dict` are arguments for acoustic model, which correspond to the 5 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_aishell3_ckpt_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_1.1.0.zip)\n- [fastspeech2_conformer_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_aishell3_ckpt_0.2.0.zip) (Thanks for [@awmmmm](https://github.com/awmmmm)'s contribution)\n\nThe static model can be downloaded here:\n- [fastspeech2_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_static_1.1.0.zip)\n\nThe PIR static model can be downloaded here:\n- [fastspeech2_aishell3_static_pir_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_static_pir_1.1.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [fastspeech2_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [fastspeech2_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_pdlite_1.3.0.zip)\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_aishell3_ckpt_1.1.0\n├── default.yaml            # default config used to train fastspeech2\n├── energy_stats.npy        # statistics used to normalize energy when training fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── pitch_stats.npy         # statistics used to normalize pitch when training fastspeech2\n├── snapshot_iter_96400.pdz # model parameters and optimizer states\n├── speaker_id_map.txt      # speaker id map file when training a multi-speaker fastspeech2\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../../assets/sentences.txt` using pretrained fastspeech2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_aishell3 \\\n  --am_config=fastspeech2_aishell3_ckpt_1.1.0/default.yaml \\\n  --am_ckpt=fastspeech2_aishell3_ckpt_1.1.0/snapshot_iter_96400.pdz \\\n  --am_stat=fastspeech2_aishell3_ckpt_1.1.0/speech_stats.npy \\\n  --voc=pwgan_aishell3 \\\n  --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n  --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n  --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n  --lang=zh \\\n  --text=${BIN_DIR}/../../assets/sentences.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=fastspeech2_aishell3_ckpt_1.1.0/phone_id_map.txt \\\n  --speaker_dict=fastspeech2_aishell3_ckpt_1.1.0/speaker_id_map.txt \\\n  --spk_id=0 \\\n  --inference_dir=exp/default/inference\n```\n"
  },
  {
    "path": "examples/aishell3/tts3/conf/conformer.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Maximum f0 for pitch extraction.\nf0max: 400         # Minimum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 32\nnum_workers: 4\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    encoder_type: conformer           # encoder type\n    decoder_type: conformer           # decoder type\n    conformer_pos_enc_layer_type: rel_pos        # conformer positional encoding type\n    conformer_self_attn_layer_type: rel_selfattn # conformer self-attention type\n    conformer_activation_type: swish             # conformer activation type\n    use_macaron_style_in_conformer: true         # whether to use macaron style in conformer\n    use_cnn_in_conformer: true                   # whether to use CNN in conformer\n    conformer_enc_kernel_size: 7                 # kernel size in CNN module of conformer-based encoder\n    conformer_dec_kernel_size: 31                # kernel size in CNN module of conformer-based decoder\n    init_type: xavier_uniform         # initialization type\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: true   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: false # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/aishell3/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam               # optimizer type\n    learning_rate: 0.001      # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/aishell3/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_aishell3 \\\n        --voc=pwgan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_aishell3 \\\n        --voc=hifigan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0\nfi\n"
  },
  {
    "path": "examples/aishell3/tts3/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_aishell3 \\\n        --voc=pwgan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_aishell3 \\\n        --voc=hifigan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0\nfi\n"
  },
  {
    "path": "examples/aishell3/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_aishell3 \\\n        --voc=pwgan_aishell3 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --spk_id=0\n\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_aishell3 \\\n        --voc=hifigan_aishell3 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --spk_id=0\nfi\n"
  },
  {
    "path": "examples/aishell3/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/tts3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_aishell3 \\\n        --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n        --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n        --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n\n"
  },
  {
    "path": "examples/aishell3/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_aishell3 \\\n        --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n        --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n        --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --inference_dir=${train_output_path}/inference\n    fi\n"
  },
  {
    "path": "examples/aishell3/tts3/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=2 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --speaker-dict=dump/speaker_id_map.txt\n"
  },
  {
    "path": "examples/aishell3/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_482.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_aishell3\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_aishell3\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_aishell3\n    \nfi\n\n# inference with onnxruntime, use fastspeech2 + pwgan by default\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite fastspeech2_aishell3 x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_aishell3 x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_aishell3 x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/vc0/README.md",
    "content": "# Tacotron2 + AISHELL-3 Voice Cloning\nThis example contains code used to train a [Tacotron2](https://arxiv.org/abs/1712.05884) model with [AISHELL-3](http://www.aishelltech.com/aishell_3). The trained model can be used in Voice Cloning Task, We refer to the model structure of  [Transfer Learning from Speaker Veriﬁcation to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/pdf/1806.04558.pdf). The general steps are as follows:\n1. Speaker Encoder: We use Speaker Verification to train a speaker encoder. Datasets used in this task are different from those used in `Tacotron2` because the transcriptions are not needed, we use more datasets, refer to  [ge2e](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/ge2e).\n2. Synthesizer: We use the trained speaker encoder to generate speaker embedding for each sentence in AISHELL-3. This embedding is an extra input of  `Tacotron2` which will be concated with encoder outputs.\n3. Vocoder: We use [Parallel Wave GAN](http://arxiv.org/abs/1910.11480) as the neural Vocoder, refer to [voc1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1).\n\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for Tacotron2, the durations of MFA are not needed here.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Pretrained GE2E Model\nWe use pretrained GE2E model to generate speaker embedding for each sentence.\n\nDownload pretrained GE2E model from here [ge2e_ckpt_0.3.zip](https://bj.bcebos.com/paddlespeech/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip), and `unzip` it.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nAssume the path to the pretrained ge2e model is `./ge2e_ckpt_0.3`.\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize waveform from `metadata.jsonl`.\n5. start a voice cloning inference.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${ge2e_ckpt_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── embed\n│   ├── SSB0005\n│   ├── SSB0009\n│   ├── ...\n│   └── ...\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └──  raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe `embed` contains the generated speaker embedding for each sentence in AISHELL-3, which has the same file structure with wav files and the format is  `.npy`.\n\nThe computing time of utterance embedding can be x hours.\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and id of each utterance.\n\nThe preprocessing step is very similar to that one of [tts0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts0), but there is one more `ge2e/inference` step here.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nThe training step is very similar to that one of [tts0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts0), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\nThe synthesizing step is very similar to that one of [tts0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts0), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/../synthesize.py`.\n\n### Voice Cloning\nAssume there are some  reference audios in `./ref_audio`\n```text\nref_audio\n├── 001238.wav\n├── LJ015-0254.wav\n└── audio_self_test.mp3\n```\n`./local/voice_cloning.sh` calls `${BIN_DIR}/../voice_cloning.py`\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${ref_audio_dir}\n```\n\n## Pretrained Model\n- [tacotron2_aishell3_ckpt_vc0_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_aishell3_ckpt_vc0_0.2.0.zip)\n\n\nModel | Step | eval/loss | eval/l1_loss | eval/mse_loss | eval/bce_loss| eval/attn_loss\n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 2(gpu) x 37596|0.58704|0.39623|0.15073|0.039|1.9981e-04|\n\nTacotron2 checkpoint contains files listed below.\n(There is no need for `speaker_id_map.txt` here )\n\n```text\ntacotron2_aishell3_ckpt_vc0_0.2.0\n├── default.yaml            # default config used to train tacotron2\n├── phone_id_map.txt        # phone vocabulary file when training tacotron2\n├── snapshot_iter_37596.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training tacotron2\n```\n\n## More\nWe strongly recommend that you use [FastSpeech2 + AISHELL-3 Voice Cloning](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc1) which works better.\n"
  },
  {
    "path": "examples/aishell3/vc0/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:                          # keyword arguments for the selected model\n    embed_dim: 512               # char or phn embedding dimension\n    elayers: 1                   # number of blstm layers in encoder\n    eunits: 512                  # number of blstm units\n    econv_layers: 3              # number of convolutional layers in encoder\n    econv_chans: 512             # number of channels in convolutional layer\n    econv_filts: 5               # filter size of convolutional layer\n    atype: location              # attention function type\n    adim: 512                    # attention dimension\n    aconv_chans: 32              # number of channels in convolutional layer of attention\n    aconv_filts: 15              # filter size of convolutional layer of attention\n    cumulate_att_w: True         # whether to cumulate attention weight\n    dlayers: 2                   # number of lstm layers in decoder\n    dunits: 1024                 # number of lstm units in decoder\n    prenet_layers: 2             # number of layers in prenet\n    prenet_units: 256            # number of units in prenet\n    postnet_layers: 5            # number of layers in postnet\n    postnet_chans: 512           # number of channels in postnet\n    postnet_filts: 5             # filter size of postnet layer\n    output_activation: null      # activation function for the final output\n    use_batch_norm: True         # whether to use batch normalization in encoder\n    use_concate: True            # whether to concatenate encoder embedding with decoder outputs\n    use_residual: False          # whether to use residual connection in encoder\n    dropout_rate: 0.5            # dropout rate\n    zoneout_rate: 0.1            # zoneout rate\n    reduction_factor: 1          # reduction factor\n    spk_embed_dim: 256           # speaker embedding dimension\n    spk_embed_integration_type: concat # how to integrate speaker embedding\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True            # whether to apply masking for padded part in loss calculation\n    bce_pos_weight: 5.0          # weight of positive sample in binary cross entropy calculation\n    use_guided_attn_loss: True   # whether to use guided attention loss\n    guided_attn_loss_sigma: 0.4  # sigma of guided attention loss\n    guided_attn_loss_lambda: 1.0 # strength of guided attention loss\n\n\n##########################################################\n#                  OPTIMIZER SETTING                     #\n##########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 1.0e-03   # learning rate\n    epsilon: 1.0e-06         # epsilon\n    weight_decay: 0.0        # weight decay coefficient\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 100\nnum_snapshots: 5\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 42"
  },
  {
    "path": "examples/aishell3/vc0/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\nge2e_ckpt_path=$2\n\n# gen speaker embedding\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${MAIN_ROOT}/paddlespeech/vector/exps/ge2e/inference.py \\\n        --input=~/datasets/data_aishell3/train/wav/ \\\n        --output=dump/embed \\\n        --checkpoint_path=${ge2e_ckpt_path}\nfi\n\n# copy from tts3/preprocess\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --spk_emb_dir=dump/embed\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # normalize and covert phone to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/vc0/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\npython3 ${BIN_DIR}/../synthesize.py \\\n    --am=tacotron2_aishell3 \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_aishell3 \\\n    --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n    --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n    --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n    --test_metadata=dump/test/norm/metadata.jsonl \\\n    --output_dir=${train_output_path}/test \\\n    --phones_dict=dump/phone_id_map.txt \\\n    --speaker_dict=dump/speaker_id_map.txt \\\n    --voice-cloning=True\n"
  },
  {
    "path": "examples/aishell3/vc0/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=2 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --voice-cloning=True"
  },
  {
    "path": "examples/aishell3/vc0/local/voice_cloning.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nge2e_params_path=$4\nref_audio_dir=$5\n\npython3 ${BIN_DIR}/../voice_cloning.py \\\n    --am=tacotron2_aishell3 \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_aishell3 \\\n    --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n    --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n    --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n    --ge2e_params_path=${ge2e_params_path} \\\n    --text=\"凯莫瑞安联合体的经济崩溃迫在眉睫。\" \\\n    --input-dir=${ref_audio_dir} \\\n    --output-dir=${train_output_path}/vc_syn \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/aishell3/vc0/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_482.pdz\nref_audio_dir=ref_audio\n\n# not include \".pdparams\" here\nge2e_ckpt_path=./ge2e_ckpt_0.3/step-3000000\n\n# include \".pdparams\" here\nge2e_params_path=${ge2e_ckpt_path}.pdparams\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${ge2e_ckpt_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${ref_audio_dir} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/vc1/README.md",
    "content": "# FastSpeech2 + AISHELL-3 Voice Cloning\nThis example contains code used to train a [FastSpeech2](https://arxiv.org/abs/2006.04558) model with [AISHELL-3](http://www.aishelltech.com/aishell_3). The trained model can be used in Voice Cloning Task, We refer to the model structure of  [Transfer Learning from Speaker Veriﬁcation to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/pdf/1806.04558.pdf). The general steps are as follows:\n1. Speaker Encoder: We use Speaker Verification to train a speaker encoder. Datasets used in this task are different from those used in `FastSpeech2` because the transcriptions are not needed, we use more datasets, refer to  [ge2e](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/ge2e).\n2. Synthesizer: We use the trained speaker encoder to generate speaker embedding for each sentence in AISHELL-3. This embedding is an extra input of  `FastSpeech2` which will be concated with encoder outputs.\n3. Vocoder: We use [Parallel Wave GAN](http://arxiv.org/abs/1910.11480) as the neural Vocoder, refer to [voc1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1).\n\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Pretrained GE2E Model\nWe use pretrained GE2E model to generate speaker embedding for each sentence.\n\nDownload pretrained GE2E model from here [ge2e_ckpt_0.3.zip](https://bj.bcebos.com/paddlespeech/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip), and `unzip` it.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nAssume the path to the pretrained ge2e model is `./ge2e_ckpt_0.3`.\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize waveform from `metadata.jsonl`.\n5. start a voice cloning inference.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${ge2e_ckpt_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── embed\n│   ├── SSB0005\n│   ├── SSB0009\n│   ├── ...\n│   └── ...\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └──  raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe `embed` contains the generated speaker embedding for each sentence in AISHELL-3, which has the same file structure with wav files and the format is  `.npy`.\n\nThe computing time of utterance embedding can be x hours.\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and id of each utterance.\n\nThe preprocessing step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but there is one more `ge2e/inference` step here.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nThe training step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\nThe synthesizing step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/../synthesize.py`.\n\n### Voice Cloning\nAssume there are some reference audios in `./ref_audio`\n```text\nref_audio\n├── 001238.wav\n├── LJ015-0254.wav\n└── audio_self_test.mp3\n```\n`./local/voice_cloning.sh` calls `${BIN_DIR}/../voice_cloning.py`\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${ref_audio_dir}\n```\n## Pretrained Model\n- [fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_aishell3_vc1_ckpt_0.5.zip)\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/pitch_loss| eval/energy_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault|2(gpu) x 96400|0.99699|0.62013|0.053057|0.11954| 0.20426|\n\nFastSpeech2 checkpoint contains files listed below.\n(There is no need for `speaker_id_map.txt` here )\n\n```text\nfastspeech2_nosil_aishell3_ckpt_vc1_0.5\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_96400.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n"
  },
  {
    "path": "examples/aishell3/vc1/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n  optim: adam               # optimizer type\n  learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/aishell3/vc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\nge2e_ckpt_path=$2\n\n# gen speaker embedding\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${MAIN_ROOT}/paddlespeech/vector/exps/ge2e/inference.py \\\n        --input=~/datasets/data_aishell3/train/wav/ \\\n        --output=dump/embed \\\n        --checkpoint_path=${ge2e_ckpt_path}\nfi\n\n# copy from tts3/preprocess\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --spk_emb_dir=dump/embed\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/vc1/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\npython3 ${BIN_DIR}/../synthesize.py \\\n    --am=fastspeech2_aishell3 \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_aishell3 \\\n    --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n    --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n    --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n    --test_metadata=dump/test/norm/metadata.jsonl \\\n    --output_dir=${train_output_path}/test \\\n    --phones_dict=dump/phone_id_map.txt \\\n    --speaker_dict=dump/speaker_id_map.txt \\\n    --voice-cloning=True\n"
  },
  {
    "path": "examples/aishell3/vc1/local/voice_cloning.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nge2e_params_path=$4\nref_audio_dir=$5\n\npython3 ${BIN_DIR}/../voice_cloning.py \\\n    --am=fastspeech2_aishell3 \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_aishell3 \\\n    --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n    --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n    --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n    --ge2e_params_path=${ge2e_params_path} \\\n    --text=\"凯莫瑞安联合体的经济崩溃迫在眉睫。\" \\\n    --input-dir=${ref_audio_dir} \\\n    --output-dir=${train_output_path}/vc_syn \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/aishell3/vc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_482.pdz\nref_audio_dir=ref_audio\n\n# not include \".pdparams\" here\nge2e_ckpt_path=./ge2e_ckpt_0.3/step-3000000\n\n# include \".pdparams\" here\nge2e_params_path=${ge2e_ckpt_path}.pdparams\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${ge2e_ckpt_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${ref_audio_dir} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/vc2/README.md",
    "content": "# FastSpeech2 + AISHELL-3 Voice Cloning (ECAPA-TDNN)\nThis example contains code used to train a [FastSpeech2](https://arxiv.org/abs/2006.04558) model with [AISHELL-3](http://www.aishelltech.com/aishell_3). The trained model can be used in Voice Cloning Task, We refer to the model structure of  [Transfer Learning from Speaker Veriﬁcation to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/pdf/1806.04558.pdf). The general steps are as follows:\n1. Speaker Encoder: We use Speaker Verification to train a speaker encoder. Datasets used in this task are different from those used in `FastSpeech2` because the transcriptions are not needed, we use more datasets, refer to  [ECAPA-TDNN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/voxceleb/sv0).\n2. Synthesizer: We use the trained speaker encoder to generate speaker embedding for each sentence in AISHELL-3. This embedding is an extra input of  `FastSpeech2` which will be concated with encoder outputs.\n3. Vocoder: We use [Parallel Wave GAN](http://arxiv.org/abs/1910.11480) as the neural Vocoder, refer to [voc1](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1).\n\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize waveform from `metadata.jsonl`.\n5. start a voice cloning inference.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── embed\n│   ├── SSB0005\n│   ├── SSB0009\n│   ├── ...\n│   └── ...\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └──  raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe `embed` contains the generated speaker embedding for each sentence in AISHELL-3, which has the same file structure with wav files and the format is  `.npy`.\n\nThe computing time of utterance embedding can be x hours.\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and id of each utterance.\n\nThe preprocessing step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but there is one more `ECAPA-TDNN/inference` step here.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nThe training step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\nThe synthesizing step is very similar to that one of [tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/../synthesize.py`.\n\n### Voice Cloning\nAssume there are some reference audios in `./ref_audio` (the format must be wav here)\n```text\nref_audio\n├── 001238.wav\n├── LJ015-0254.wav\n└── audio_self_test.wav\n```\n`./local/voice_cloning.sh` calls `${BIN_DIR}/../voice_cloning.py`\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ref_audio_dir}\n```\n## Pretrained Model\n- [fastspeech2_aishell3_ckpt_vc2_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_vc2_1.2.0.zip)\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/pitch_loss| eval/energy_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault|2(gpu) x 96400|0.991855|0.599517|0.052142|0.094877| 0.245318|\n\nFastSpeech2 checkpoint contains files listed below.\n(There is no need for `speaker_id_map.txt` here )\n\n```text\nfastspeech2_aishell3_ckpt_vc2_1.2.0\n├── default.yaml            # default config used to train fastspeech2\n├── energy_stats.npy        # statistics used to normalize energy when training fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── pitch_stats.npy         # statistics used to normalize pitch when training fastspeech2\n├── snapshot_iter_96400.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n"
  },
  {
    "path": "examples/aishell3/vc2/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 192                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n  optim: adam               # optimizer type\n  learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/aishell3/vc2/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\n# gen speaker embedding\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/vc2_infer.py \\\n        --input=~/datasets/data_aishell3/train/wav/ \\\n        --output=dump/embed \\\n        --num-cpu=20\nfi\n\n# copy from tts3/preprocess\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --spk_emb_dir=dump/embed\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3/vc2/local/voice_cloning.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nref_audio_dir=$4\n\npython3 ${BIN_DIR}/../voice_cloning.py \\\n    --am=fastspeech2_aishell3 \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_aishell3 \\\n    --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n    --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n    --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n    --text=\"凯莫瑞安联合体的经济崩溃迫在眉睫。\" \\\n    --input-dir=${ref_audio_dir} \\\n    --output-dir=${train_output_path}/vc_syn \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --use_ecapa=True\n"
  },
  {
    "path": "examples/aishell3/vc2/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_96400.pdz\nref_audio_dir=ref_audio\n\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ref_audio_dir} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/vits/README.md",
    "content": "# VITS with AISHELL-3\nThis example contains code used to train a [VITS](https://arxiv.org/abs/2106.06103) model with [AISHELL-3](http://www.aishelltech.com/aishell_3).\n\nAISHELL-3 is a large-scale and high-fidelity multi-speaker Mandarin speech corpus that could be used to train multi-speaker Text-to-Speech (TTS) systems.\n\nWe use AISHELL-3 to train a multi-speaker VITS model here.\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for VITS, the durations of MFA are not needed here.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── feats_stats.npy\n    ├── norm\n    └── raw\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains wave and linear spectrogram of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, feats, feats_lengths, the path of linear spectrogram features, the path of raw waves, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a VITS model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       config file to overwrite default config.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n6. `--speaker-dict` is the path of the speaker id map file when training a multi-speaker VITS.\n\n### Synthesizing\n\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--config CONFIG] [--ckpt CKPT]\n                     [--phones_dict PHONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with VITS\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Config of VITS.\n  --ckpt CKPT           Checkpoint file of VITS.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h] [--config CONFIG] [--ckpt CKPT]\n                         [--phones_dict PHONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with VITS\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Config of VITS.\n  --ckpt CKPT           Checkpoint file of VITS.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--config`, `--ckpt`, `--phones_dict` and `--speaker_dict` are arguments for acoustic model, which correspond to the 3 files in the VITS pretrained model.\n2. `--lang` is the model language, which can be `zh` or `en`.\n3. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n4. `--text` is the text file, which contains sentences to synthesize.\n5. `--output_dir` is the directory to save synthesized audio files.\n6. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n<!-- TODO display these after we trained the model -->\n<!-- \n## Pretrained Model\n\nThe pretrained model can be downloaded here:\n\n- [vits_aishell3_ckpt_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/vits/vits_aishell3_ckpt_1.1.0.zip) (add_blank=true)\n\nVITS checkpoint contains files listed below.\n```text\nvits_aishell3_ckpt_1.1.0\n├── default.yaml              # default config used to train vitx\n├── phone_id_map.txt          # phone vocabulary file when training vits\n├── speaker_id_map.txt        # speaker id map file when training a multi-speaker vits\n└── snapshot_iter_333000.pdz  # model parameters and optimizer states\n```\n\nps: This ckpt is not good enough, a better result is training\n\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences.txt` using pretrained VITS.\n\n```bash\nsource path.sh\nadd_blank=true\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize_e2e.py \\\n    --config=vits_aishell3_ckpt_1.1.0/default.yaml \\\n    --ckpt=vits_aishell3_ckpt_1.1.0/snapshot_iter_333000.pdz \\\n    --phones_dict=vits_aishell3_ckpt_1.1.0/phone_id_map.txt \\\n    --speaker_dict=vits_aishell3_ckpt_1.1.0/speaker_id_map.txt \\\n    --output_dir=exp/default/test_e2e \\\n    --text=${BIN_DIR}/../../assets/sentences.txt \\\n    --add-blank=${add_blank} \n```\n-->\n"
  },
  {
    "path": "examples/aishell3/vits/conf/default.yaml",
    "content": "# This configuration tested on 4 GPUs (V100) with 32GB GPU\n# memory. It takes around 2 weeks to finish the training\n# but 100k iters model should generate reasonable results.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 22050         # sr\nn_fft: 1024        # FFT size (samples).\nn_shift: 256       # Hop size (samples). 12.5ms\nwin_length: null   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n\n##########################################################\n#                  TTS MODEL SETTING                     #\n##########################################################\nmodel:\n    # generator related\n    generator_type: vits_generator\n    generator_params:\n        hidden_channels: 192\n        global_channels: 256\n        segment_size: 32\n        text_encoder_attention_heads: 2\n        text_encoder_ffn_expand: 4\n        text_encoder_blocks: 6\n        text_encoder_positionwise_layer_type: \"conv1d\"\n        text_encoder_positionwise_conv_kernel_size: 3\n        text_encoder_positional_encoding_layer_type: \"rel_pos\"\n        text_encoder_self_attention_layer_type: \"rel_selfattn\"\n        text_encoder_activation_type: \"swish\"\n        text_encoder_normalize_before: True\n        text_encoder_dropout_rate: 0.1\n        text_encoder_positional_dropout_rate: 0.0\n        text_encoder_attention_dropout_rate: 0.1\n        use_macaron_style_in_text_encoder: True\n        use_conformer_conv_in_text_encoder: False\n        text_encoder_conformer_kernel_size: -1\n        decoder_kernel_size: 7\n        decoder_channels: 512\n        decoder_upsample_scales: [8, 8, 2, 2]\n        decoder_upsample_kernel_sizes: [16, 16, 4, 4]\n        decoder_resblock_kernel_sizes: [3, 7, 11]\n        decoder_resblock_dilations: [[1, 3, 5], [1, 3, 5], [1, 3, 5]]\n        use_weight_norm_in_decoder: True\n        posterior_encoder_kernel_size: 5\n        posterior_encoder_layers: 16\n        posterior_encoder_stacks: 1\n        posterior_encoder_base_dilation: 1\n        posterior_encoder_dropout_rate: 0.0\n        use_weight_norm_in_posterior_encoder: True\n        flow_flows: 4\n        flow_kernel_size: 5\n        flow_base_dilation: 1\n        flow_layers: 4\n        flow_dropout_rate: 0.0\n        use_weight_norm_in_flow: True\n        use_only_mean_in_flow: True\n        stochastic_duration_predictor_kernel_size: 3\n        stochastic_duration_predictor_dropout_rate: 0.5\n        stochastic_duration_predictor_flows: 4\n        stochastic_duration_predictor_dds_conv_layers: 3\n    # discriminator related\n    discriminator_type: hifigan_multi_scale_multi_period_discriminator\n    discriminator_params:\n        scales: 1\n        scale_downsample_pooling: \"AvgPool1D\"\n        scale_downsample_pooling_params:\n            kernel_size: 4\n            stride: 2\n            padding: 2\n        scale_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [15, 41, 5, 3]\n            channels: 128\n            max_downsample_channels: 1024\n            max_groups: 16\n            bias: True\n            downsample_scales: [2, 2, 4, 4, 1]\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n        follow_official_norm: False\n        periods: [2, 3, 5, 7, 11]\n        period_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [5, 3]\n            channels: 32\n            downsample_scales: [3, 3, 3, 3, 1]\n            max_downsample_channels: 1024\n            bias: True\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n    # others\n    sampling_rate: 22050          # needed in the inference for saving wav\n    cache_generator_outputs: True # whether to cache generator outputs in the training\n          \n###########################################################\n#                        LOSS SETTING                     #\n###########################################################\n# loss function related\ngenerator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\nfeat_match_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    average_by_layers: False         # whether to average loss value by #layers of each discriminator\n    include_final_outputs: True      # whether to include final outputs for loss calculation\nmel_loss_params:\n    fs: 22050          # must be the same as the training data\n    fft_size: 1024        # fft points\n    hop_size: 256    # hop size\n    win_length: null   # window length\n    window: hann       # window type\n    num_mels: 80         # number of Mel basis\n    fmin: 0            # minimum frequency for Mel basis\n    fmax: null         # maximum frequency for Mel basis\n    log_base: null     # null represent natural log\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 1.0        # loss scaling coefficient for adversarial loss\nlambda_mel: 45.0       # loss scaling coefficient for Mel loss\nlambda_feat_match: 2.0 # loss scaling coefficient for feat match loss\nlambda_dur: 1.0        # loss scaling coefficient for duration loss\nlambda_kl: 1.0         # loss scaling coefficient for KL divergence loss\n# others\nsampling_rate: 22050          # needed in the inference for saving wav\ncache_generator_outputs: True # whether to cache generator outputs in the training\n\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 50              # Batch size.\nnum_workers: 4              # Number of workers in DataLoader.\n\n##########################################################\n#            OPTIMIZER & SCHEDULER SETTING               #\n##########################################################\n# optimizer setting for generator\ngenerator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ngenerator_scheduler: exponential_decay\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4\n    gamma: 0.999875                   \n\n# optimizer setting for discriminator\ndiscriminator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ndiscriminator_scheduler: exponential_decay\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4          \n    gamma: 0.999875\ngenerator_first: False # whether to start updating generator first\n\n##########################################################\n#                OTHER TRAINING SETTING                  #\n##########################################################\nnum_snapshots: 10            # max number of snapshots to keep while training\ntrain_max_steps: 350000      # Number of training steps. == total_iters / ngpus, total_iters = 1000000\nsave_interval_steps: 1000    # Interval steps to save checkpoint.\neval_interval_steps: 250     # Interval steps to evaluate the network.\nseed: 777                    # random seed number\n"
  },
  {
    "path": "examples/aishell3/vits/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\nadd_blank=$2\n\n# copy from tts3/preprocess\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/aishell3/vits/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test\nfi\n"
  },
  {
    "path": "examples/aishell3/vits/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nadd_blank=$4\n\nstage=0\nstop_stage=0\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --am=vits_aishell3 \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --add-blank=${add_blank}\nfi\n"
  },
  {
    "path": "examples/aishell3/vits/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\n# install monotonic_align\ncd ${MAIN_ROOT}/paddlespeech/t2s/models/vits/monotonic_align\npython3 setup.py build_ext --inplace\ncd -\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=4 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --speaker-dict=dump/speaker_id_map.txt\n"
  },
  {
    "path": "examples/aishell3/vits/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=vits\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/aishell3/vits/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\nadd_blank=true\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} ${add_blank}|| exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} ${add_blank}|| exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/vits-vc/README.md",
    "content": "# VITS with AISHELL-3\nThis example contains code used to train a [VITS](https://arxiv.org/abs/2106.06103) model with [AISHELL-3](http://www.aishelltech.com/aishell_3). The trained model can be used in Voice Cloning Task, We refer to the model structure of  [Transfer Learning from Speaker Veriﬁcation to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/pdf/1806.04558.pdf). The general steps are as follows:\n1. Speaker Encoder: We use Speaker Verification to train a speaker encoder. Datasets used in this task are different from those used in `VITS` because the transcriptions are not needed, we use more datasets, refer to  [ge2e](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/ge2e).\n2. Synthesizer and Vocoder: We use the trained speaker encoder to generate speaker embedding for each sentence in AISHELL-3. This embedding is an extra input of `VITS` which will be concated with encoder outputs. The vocoder is part of `VITS` due to its special structure.\n\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for VITS, the durations of MFA are not needed here.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Pretrained GE2E Model\nWe use pretrained GE2E model to generate speaker embedding for each sentence.\n\nDownload pretrained GE2E model from here [ge2e_ckpt_0.3.zip](https://bj.bcebos.com/paddlespeech/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip), and `unzip` it.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nAssume the path to the pretrained ge2e model is `./ge2e_ckpt_0.3`.\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize waveform from `metadata.jsonl`.\n5. start a voice cloning inference.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n\n### Data Preprocessing\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${ge2e_ckpt_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── embed\n│   ├── SSB0005\n│   ├── SSB0009\n│   ├── ...\n│   └── ...\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── feats_stats.npy\n    ├── norm\n    └── raw\n```\nThe `embed` contains the generated speaker embedding for each sentence in AISHELL-3, which has the same file structure with wav files and the format is  `.npy`.\n\nThe computing time of utterance embedding can be x hours.\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains wave and linear spectrogram of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, feats, feats_lengths, the path of linear spectrogram features, the path of raw waves, speaker, and the id of each utterance.\n\nThe preprocessing step is very similar to that one of [vits](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vits), but there is one more `ge2e/inference` step here.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nThe training step is very similar to that one of [vits](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vits), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/train.py`.\n\n### Synthesizing\n\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--config CONFIG] [--ckpt CKPT]\n                     [--phones_dict PHONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with VITS\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Config of VITS.\n  --ckpt CKPT           Checkpoint file of VITS.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\nThe synthesizing step is very similar to that one of [vits](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vits), but we should set `--voice-cloning=True` when calling `${BIN_DIR}/../synthesize.py`.\n\n### Voice Cloning\nAssume there are some  reference audios in `./ref_audio`\n```text\nref_audio\n├── 001238.wav\n├── LJ015-0254.wav\n└── audio_self_test.mp3\n```\n`./local/voice_cloning.sh` calls `${BIN_DIR}/voice_cloning.py`\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${add_blank} ${ref_audio_dir}\n```\n\nIf you want to convert a speaker audio file to refered speaker, run:\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} ${ge2e_params_path} ${add_blank} ${ref_audio_dir} ${src_audio_path}\n```\n\n<!-- TODO display these after we trained the model -->\n<!-- \n## Pretrained Model\n\nThe pretrained model can be downloaded here:\n\n- [vits_vc_aishell3_ckpt_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/vits/vits_vc_aishell3_ckpt_1.1.0.zip) (add_blank=true)\n\nVITS checkpoint contains files listed below.\n(There is no need for `speaker_id_map.txt` here )\n\n```text\nvits_vc_aishell3_ckpt_1.1.0\n├── default.yaml              # default config used to train vitx\n├── phone_id_map.txt          # phone vocabulary file when training vits\n└── snapshot_iter_333000.pdz  # model parameters and optimizer states\n```\n\nps: This ckpt is not good enough, a better result is training\n\n-->\n"
  },
  {
    "path": "examples/aishell3/vits-vc/conf/default.yaml",
    "content": "# This configuration tested on 4 GPUs (V100) with 32GB GPU\n# memory. It takes around 2 weeks to finish the training\n# but 100k iters model should generate reasonable results.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 22050         # sr\nn_fft: 1024        # FFT size (samples).\nn_shift: 256       # Hop size (samples). 12.5ms\nwin_length: null   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n\n##########################################################\n#                  TTS MODEL SETTING                     #\n##########################################################\nmodel:\n    # generator related\n    generator_type: vits_generator\n    generator_params:\n        hidden_channels: 192\n        spk_embed_dim: 256\n        global_channels: 256\n        segment_size: 32\n        text_encoder_attention_heads: 2\n        text_encoder_ffn_expand: 4\n        text_encoder_blocks: 6\n        text_encoder_positionwise_layer_type: \"conv1d\"\n        text_encoder_positionwise_conv_kernel_size: 3\n        text_encoder_positional_encoding_layer_type: \"rel_pos\"\n        text_encoder_self_attention_layer_type: \"rel_selfattn\"\n        text_encoder_activation_type: \"swish\"\n        text_encoder_normalize_before: True\n        text_encoder_dropout_rate: 0.1\n        text_encoder_positional_dropout_rate: 0.0\n        text_encoder_attention_dropout_rate: 0.1\n        use_macaron_style_in_text_encoder: True\n        use_conformer_conv_in_text_encoder: False\n        text_encoder_conformer_kernel_size: -1\n        decoder_kernel_size: 7\n        decoder_channels: 512\n        decoder_upsample_scales: [8, 8, 2, 2]\n        decoder_upsample_kernel_sizes: [16, 16, 4, 4]\n        decoder_resblock_kernel_sizes: [3, 7, 11]\n        decoder_resblock_dilations: [[1, 3, 5], [1, 3, 5], [1, 3, 5]]\n        use_weight_norm_in_decoder: True\n        posterior_encoder_kernel_size: 5\n        posterior_encoder_layers: 16\n        posterior_encoder_stacks: 1\n        posterior_encoder_base_dilation: 1\n        posterior_encoder_dropout_rate: 0.0\n        use_weight_norm_in_posterior_encoder: True\n        flow_flows: 4\n        flow_kernel_size: 5\n        flow_base_dilation: 1\n        flow_layers: 4\n        flow_dropout_rate: 0.0\n        use_weight_norm_in_flow: True\n        use_only_mean_in_flow: True\n        stochastic_duration_predictor_kernel_size: 3\n        stochastic_duration_predictor_dropout_rate: 0.5\n        stochastic_duration_predictor_flows: 4\n        stochastic_duration_predictor_dds_conv_layers: 3\n    # discriminator related\n    discriminator_type: hifigan_multi_scale_multi_period_discriminator\n    discriminator_params:\n        scales: 1\n        scale_downsample_pooling: \"AvgPool1D\"\n        scale_downsample_pooling_params:\n            kernel_size: 4\n            stride: 2\n            padding: 2\n        scale_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [15, 41, 5, 3]\n            channels: 128\n            max_downsample_channels: 1024\n            max_groups: 16\n            bias: True\n            downsample_scales: [2, 2, 4, 4, 1]\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n        follow_official_norm: False\n        periods: [2, 3, 5, 7, 11]\n        period_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [5, 3]\n            channels: 32\n            downsample_scales: [3, 3, 3, 3, 1]\n            max_downsample_channels: 1024\n            bias: True\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n    # others\n    sampling_rate: 22050          # needed in the inference for saving wav\n    cache_generator_outputs: True # whether to cache generator outputs in the training\n          \n###########################################################\n#                        LOSS SETTING                     #\n###########################################################\n# loss function related\ngenerator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\nfeat_match_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    average_by_layers: False         # whether to average loss value by #layers of each discriminator\n    include_final_outputs: True      # whether to include final outputs for loss calculation\nmel_loss_params:\n    fs: 22050          # must be the same as the training data\n    fft_size: 1024        # fft points\n    hop_size: 256    # hop size\n    win_length: null   # window length\n    window: hann       # window type\n    num_mels: 80         # number of Mel basis\n    fmin: 0            # minimum frequency for Mel basis\n    fmax: null         # maximum frequency for Mel basis\n    log_base: null     # null represent natural log\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 1.0        # loss scaling coefficient for adversarial loss\nlambda_mel: 45.0       # loss scaling coefficient for Mel loss\nlambda_feat_match: 2.0 # loss scaling coefficient for feat match loss\nlambda_dur: 1.0        # loss scaling coefficient for duration loss\nlambda_kl: 1.0         # loss scaling coefficient for KL divergence loss\n# others\nsampling_rate: 22050          # needed in the inference for saving wav\ncache_generator_outputs: True # whether to cache generator outputs in the training\n\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 50              # Batch size.\nnum_workers: 4              # Number of workers in DataLoader.\n\n##########################################################\n#            OPTIMIZER & SCHEDULER SETTING               #\n##########################################################\n# optimizer setting for generator\ngenerator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ngenerator_scheduler: exponential_decay\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4\n    gamma: 0.999875                   \n\n# optimizer setting for discriminator\ndiscriminator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ndiscriminator_scheduler: exponential_decay\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4          \n    gamma: 0.999875\ngenerator_first: False # whether to start updating generator first\n\n##########################################################\n#                OTHER TRAINING SETTING                  #\n##########################################################\nnum_snapshots: 10            # max number of snapshots to keep while training\ntrain_max_steps: 350000      # Number of training steps. == total_iters / ngpus, total_iters = 1000000\nsave_interval_steps: 1000    # Interval steps to save checkpoint.\neval_interval_steps: 250     # Interval steps to evaluate the network.\nseed: 777                    # random seed number\n"
  },
  {
    "path": "examples/aishell3/vits-vc/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\nadd_blank=$2\nge2e_ckpt_path=$3\n\n# gen speaker embedding\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${MAIN_ROOT}/paddlespeech/vector/exps/ge2e/inference.py \\\n        --input=~/datasets/data_aishell3/train/wav/ \\\n        --output=dump/embed \\\n        --checkpoint_path=${ge2e_ckpt_path}\nfi\n\n# copy from tts3/preprocess\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --spk_emb_dir=dump/embed\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/aishell3/vits-vc/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --voice-cloning=True\nfi\n"
  },
  {
    "path": "examples/aishell3/vits-vc/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\n# install monotonic_align\ncd ${MAIN_ROOT}/paddlespeech/t2s/models/vits/monotonic_align\npython3 setup.py build_ext --inplace\ncd -\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=4 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --voice-cloning=True\n"
  },
  {
    "path": "examples/aishell3/vits-vc/local/voice_cloning.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nge2e_params_path=$4\nadd_blank=$5\nref_audio_dir=$6\nsrc_audio_path=$7\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/voice_cloning.py \\\n    --config=${config_path} \\\n    --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --ge2e_params_path=${ge2e_params_path} \\\n    --phones_dict=dump/phone_id_map.txt \\\n    --text=\"凯莫瑞安联合体的经济崩溃迫在眉睫。\" \\\n    --audio-path=${src_audio_path} \\\n    --input-dir=${ref_audio_dir} \\\n    --output-dir=${train_output_path}/vc_syn \\\n    --add-blank=${add_blank}\n"
  },
  {
    "path": "examples/aishell3/vits-vc/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=vits\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/aishell3/vits-vc/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\nadd_blank=true\nref_audio_dir=ref_audio\nsrc_audio_path=''\n\n# not include \".pdparams\" here\nge2e_ckpt_path=./ge2e_ckpt_0.3/step-3000000\n\n# include \".pdparams\" here\nge2e_params_path=${ge2e_ckpt_path}.pdparams\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/preprocess.sh ${conf_path} ${add_blank}  ${ge2e_ckpt_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/voice_cloning.sh ${conf_path} ${train_output_path} ${ckpt_name} \\\n        ${ge2e_params_path} ${add_blank} ${ref_audio_dir} ${src_audio_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/voc1/README.md",
    "content": "# Parallel WaveGAN with AISHELL-3\nThis example contains code used to train a [parallel wavegan](http://arxiv.org/abs/1910.11480) model with [AISHELL-3](http://www.aishelltech.com/aishell_3).\n\nAISHELL-3 is a large-scale and high-fidelity multi-speaker Mandarin speech corpus that could be used to train multi-speaker Text-to-Speech (TTS) systems.\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, run the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER]\n                [--run-benchmark RUN_BENCHMARK]\n                [--profiler_options PROFILER_OPTIONS]\n\nTrain a ParallelWaveGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       ParallelWaveGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n\nbenchmark:\n  arguments related to benchmark.\n\n  --batch-size BATCH_SIZE\n                        batch size.\n  --max-iter MAX_ITER   train max steps.\n  --run-benchmark RUN_BENCHMARK\n                        runing benchmark or not, if True, use the --batch-size\n                        and --max-iter.\n  --profiler_options PROFILER_OPTIONS\n                        The option of profiler, which should be in format\n                        \"key1=value1;key2=value2;key3=value3\".\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory. If you use the pretrained model, use the `snapshot_iter_1000000.pdz `.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nPretrained models can be downloaded here:\n- [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip)\n\nThe static model can be downloaded here:\n- [pwgan_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_static_1.1.0.zip)\n\nThe PIR static model can be downloaded here:\n- [pwgan_aishell3_static_pir_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_static_pir_1.1.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [pwgan_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [pwgan_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/log_stft_magnitude_loss:| eval/spectral_convergence_loss \n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 400000|1.968762|0.759008|0.218524\n\nParallel WaveGAN checkpoint contains files listed below.\n\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/aishell3/voc1/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for Parallel WaveGAN.\n# Please make sure this is adjusted for the VCTK corpus. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires 12 GB GPU memory and takes ~3 days on RTX TITAN.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples). \nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Kernel size of dilated convolution.\n    layers: 30            # Number of residual block layers.\n    stacks: 3             # Number of stacks i.e., dilation cycles.\n    residual_channels: 64 # Number of channels in residual conv.\n    gate_channels: 128    # Number of channels in gated conv.\n    skip_channels: 64     # Number of channels in skip conv.\n    aux_channels: 80      # Number of channels for auxiliary feature conv.\n                          # Must be the same as num_mels.\n    aux_context_window: 2 # Context window size for auxiliary feature.\n                          # If set to 2, previous 2 and future 2 frames will be considered.\n    dropout: 0.0          # Dropout rate. 0.0 means no dropout applied.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    upsample_scales: [4, 5, 3, 5]     # Upsampling scales. prod(upsample_scales) == n_shift\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Number of output channels.\n    layers: 10            # Number of conv layers.\n    conv_channels: 64     # Number of chnn layers.\n    bias: True            # Whether to use bias parameter in conv.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear function after each conv.\n    nonlinear_activation_params:      # Nonlinear function parameters\n        negative_slope: 0.2           # Alpha in leakyrelu.\n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 4.0  # Loss balancing coefficient.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 8              # Batch size.\nbatch_max_steps: 24000     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-6            # Generator's epsilon.\n    weight_decay: 0.0      # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 0.0001             # Generator's learning rate.\n    step_size: 200000      # Generator's scheduler step size.\n    gamma: 0.5             # Generator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ngenerator_grad_norm: 10    # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-6            # Discriminator's epsilon.\n    weight_decay: 0.0      # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 0.00005            # Discriminator's learning rate. \n    step_size: 200000      # Discriminator's scheduler step size.\n    gamma: 0.5             # Discriminator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ndiscriminator_grad_norm: 1 # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 1000000                # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_save_intermediate_results: 4  # Number of results to be saved as intermediate results.\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/aishell3/voc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../preprocess.py \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dataset=aishell3 \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --cut-sil=True \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/aishell3/voc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3/voc5/README.md",
    "content": "# HiFiGAN with AISHELL-3\nThis example contains code used to train a [HiFiGAN](https://arxiv.org/abs/2010.05646) model with [AISHELL-3](http://www.aishelltech.com/aishell_3).\n\nAISHELL-3 is a large-scale and high-fidelity multi-speaker Mandarin speech corpus that could be used to train multi-speaker Text-to-Speech (TTS) systems.\n## Dataset\n### Download and Extract\nDownload AISHELL-3 from it's [Official Website](http://www.aishelltech.com/aishell_3) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/data_aishell3`.\n### Get MFA Result and Extract\nWe use [MFA2.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for aishell3_fastspeech2.\nYou can download from here [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/data_aishell3`.\nAssume the path to the MFA result of AISHELL-3 is `./aishell3_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, run the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a HiFiGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       HiFiGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [hifigan_aishell3_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_static_1.1.0.zip)\n\nThe PIR static model can be downloaded here:\n- [hifigan_aishell3_static_pir_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_static_pir_1.1.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [hifigan_aishell3_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [hifigan_aishell3_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/mel_loss| eval/feature_matching_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 2500000|24.060|0.1068|7.499\n\nHiFiGAN checkpoint contains files listed below.\n\n```text\nhifigan_aishell3_ckpt_0.2.0\n├── default.yaml                  # default config used to train hifigan\n├── feats_stats.npy               # statistics used to normalize spectrogram when training hifigan\n└── snapshot_iter_2500000.pdz     # generator parameters of hifigan\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/aishell3/voc5/conf/default.yaml",
    "content": "# This is the configuration file for AISHELL-3 dataset.\n# This configuration is based on HiFiGAN V1, which is\n# an official configuration. But I found that the optimizer\n# setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales\n# is also modified from the original 256 shift setting.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [5, 5, 4, 3]         # Upsampling scales.\n    upsample_kernel_sizes: [10, 10, 8, 6] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 2048\n    hop_size: 300\n    win_length: 1200\n    window: \"hann\"\n    num_mels: 80\n    fmin: 0\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/aishell3/voc5/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/aishell3_vctk/README.md",
    "content": "# Mixed Chinese and English TTS with AISHELL3 and VCTK datasets\n* ernie_sat - ERNIE-SAT\n"
  },
  {
    "path": "examples/aishell3_vctk/ernie_sat/README.md",
    "content": "# ERNIE-SAT with AISHELL-3 and VCTK dataset\n[ERNIE-SAT](https://arxiv.org/abs/2211.03545) speech-text joint pretraining framework, which achieves SOTA results in cross-lingual multi-speaker speech synthesis and cross-lingual speech editing tasks, It can be applied to a series of scenarios such as Speech Editing, personalized Speech Synthesis, and Voice Cloning.\n\n## Model Framework\nIn ERNIE-SAT, we propose two innovations:\n- In the pretraining process, the phonemes corresponding to Chinese and English are used as input to achieve cross-language and personalized soft phoneme mapping\n- The joint mask learning of speech and text is used to realize the alignment of speech and text\n\n<p align=\"center\">\n    <img src=\"https://user-images.githubusercontent.com/24568452/186110814-1b9c6618-a0ab-4c0c-bb3d-3d860b0e8cc2.png\" />\n</p>\n\n## Dataset\n### Download and Extract\nDownload all datasets and extract it to `~/datasets`:\n- The aishell3 dataset is in the directory `~/datasets/data_aishell3`\n- The vctk dataset is in the directory `~/datasets/VCTK-Corpus-0.92`\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for the fastspeech2 training.\nYou can download from here:\n- [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz) \n- [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz)\n\nOr train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the paths to the datasets are:\n- `~/datasets/data_aishell3` \n- `~/datasets/VCTK-Corpus-0.92`\n\nAssume the path to the MFA results of the datasets are:\n- `./aishell3_alignment_tone`\n- `./vctk_alignment`\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [HiFiGAN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc5) as the neural vocoder.\n\nDownload pretrained HiFiGAN model from [hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip) and unzip it.\n```bash\nunzip hifigan_aishell3_ckpt_0.2.0.zip\n```\nHiFiGAN checkpoint contains files listed below.\n```text\nhifigan_aishell3_ckpt_0.2.0\n├── default.yaml                    # default config used to train HiFiGAN\n├── feats_stats.npy                 # statistics used to normalize spectrogram when training HiFiGAN\n└── snapshot_iter_2500000.pdz       # generator parameters of HiFiGAN\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\nsynthesize, vocoder is `hifigan`\n\n##  Speech Synthesis and Speech Editing\n### Prepare\n\n**prepare aligner**\n```bash\nmkdir -p tools/aligner\ncd tools\n# download MFA\nwget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz\n# extract MFA\ntar xvf montreal-forced-aligner_linux.tar.gz\n# fix .so of MFA\ncd montreal-forced-aligner/lib\nln -snf libpython3.6m.so.1.0 libpython3.6m.so\ncd -\n# download align models and dicts\ncd aligner\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/aishell3_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/simple.lexicon\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/vctk_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/cmudict-0.7b\ncd ../../\n```\n**prepare pretrained FastSpeech2 models**\n\nERNIE-SAT use FastSpeech2 as phoneme duration predictor:\n```bash\nmkdir download\ncd download\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip\nunzip fastspeech2_conformer_baker_ckpt_0.5.zip\nunzip fastspeech2_nosil_ljspeech_ckpt_0.5.zip\ncd ../\n```\n**prepare source data**\n```bash\nmkdir source\ncd source\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540307.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540428.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/LJ050-0278.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p243_313.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p299_096.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/this_was_not_the_show_for_me.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/README.md\ncd ../\n```\nYou can check the text of downloaded wavs in `source/README.md`.\n### Cross Language Voice Cloning\n```bash\n./run.sh --stage 3 --stop-stage 3 --gpus 0\n```\n`stage 3` of `run.sh` calls `local/synthesize_e2e.sh`. `synthesize_e2e.sh` is a script for end-to-end speech synthesis, supporting cross-language speech synthesis tasks, including English-to-Chinese (en → zh) and Chinese-to-English (zh → en).\n\nYou can modify  `--wav_path`、`--old_str` and `--new_str` yourself, `--old_str` should be the text corresponding to the audio of  `--wav_path`, `--new_str` should be designed according to `--task_name`, `--source_lang` and `--target_lang` should be different in this example.\n## Pretrained Model\nPretrained ErnieSAT model:\n- [erniesat_aishell3_vctk_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_aishell3_vctk_ckpt_1.2.0.zip)\n\nModel | Step | eval/text_mlm_loss | eval/mlm_loss | eval/loss\n:-------------:| :------------:| :-----: | :-----:| :-----:\ndefault| 8(gpu) x 489000|0.000001|52.477642 |52.477642\n"
  },
  {
    "path": "examples/aishell3_vctk/ernie_sat/conf/default.yaml",
    "content": "# This configuration tested on 8 GPUs (A100) with 80GB GPU memory.\n# It takes around 4 days to finish the training,You can adjust\n# batch_size、num_workers here and ngpu in local/train.sh for your machine\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\nmean_phn_span: 8\nmlm_prob: 0.8\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 40\nnum_workers: 8\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    text_masking: true\n    postnet_layers: 5\n    postnet_filts: 5\n    postnet_chans: 256\n    encoder_type: conformer\n    decoder_type: conformer\n    enc_input_layer: sega_mlm\n    enc_pre_speech_layer: 0\n    enc_cnn_module_kernel: 7\n    enc_attention_dim: 384\n    enc_attention_heads: 2\n    enc_linear_units: 1536\n    enc_num_blocks: 4\n    enc_dropout_rate: 0.2\n    enc_positional_dropout_rate: 0.2\n    enc_attention_dropout_rate: 0.2\n    enc_normalize_before: true\n    enc_macaron_style: true\n    enc_use_cnn_module: true\n    enc_selfattention_layer_type: legacy_rel_selfattn\n    enc_activation_type: swish\n    enc_pos_enc_layer_type: legacy_rel_pos\n    enc_positionwise_layer_type: conv1d\n    enc_positionwise_conv_kernel_size: 3\n    dec_cnn_module_kernel: 31\n    dec_attention_dim: 384\n    dec_attention_heads: 2\n    dec_linear_units: 1536\n    dec_num_blocks: 4\n    dec_dropout_rate: 0.2\n    dec_positional_dropout_rate: 0.2\n    dec_attention_dropout_rate: 0.2\n    dec_macaron_style: true\n    dec_use_cnn_module: true\n    dec_selfattention_layer_type: legacy_rel_selfattn\n    dec_activation_type: swish\n    dec_pos_enc_layer_type: legacy_rel_pos\n    dec_positionwise_layer_type: conv1d\n    dec_positionwise_conv_kernel_size: 3\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\nscheduler_params:\n    d_model: 384\n    warmup_steps: 4000\ngrad_clip: 1.0\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1500\nnum_snapshots: 50\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 0\n\ntoken_list:\n- <blank>\n- <unk>\n- AH0\n- T\n- N\n- sp\n- S\n- R\n- D\n- L\n- Z\n- DH\n- IH1\n- K\n- W\n- M\n- EH1\n- AE1\n- ER0\n- B\n- IY1\n- P\n- V\n- IY0\n- F\n- HH\n- AA1\n- AY1\n- AH1\n- EY1\n- IH0\n- AO1\n- OW1\n- UW1\n- G\n- NG\n- SH\n- Y\n- TH\n- ER1\n- JH\n- UH1\n- AW1\n- CH\n- IH2\n- OW0\n- OW2\n- EY2\n- EH2\n- UW0\n- OY1\n- ZH\n- EH0\n- AY2\n- AW2\n- AA2\n- AE2\n- IY2\n- AH2\n- AE0\n- AO2\n- AY0\n- AO0\n- UW2\n- UH2\n- AA0\n- EY0\n- AW0\n- UH0\n- ER2\n- OY2\n- OY0\n- d\n- sh\n- ii\n- j\n- zh\n- l\n- x\n- b\n- g\n- uu\n- e5\n- h\n- q\n- m\n- i1\n- t\n- z\n- ch\n- f\n- s\n- u4\n- ix4\n- i4\n- n\n- i3\n- iu3\n- vv\n- ian4\n- ix2\n- r\n- e4\n- ai4\n- k\n- ing2\n- a1\n- en2\n- ui4\n- ong1\n- uo3\n- u2\n- u3\n- ao4\n- ee\n- p\n- an1\n- eng2\n- i2\n- in1\n- c\n- ai2\n- ian2\n- e2\n- an4\n- ing4\n- v4\n- ai3\n- a5\n- ian3\n- eng1\n- ong4\n- ang4\n- ian1\n- ing1\n- iy4\n- ao3\n- ang1\n- uo4\n- u1\n- iao4\n- iu4\n- a4\n- van2\n- ie4\n- ang2\n- ou4\n- iang4\n- ix1\n- er4\n- iy1\n- e1\n- en1\n- ui2\n- an3\n- ei4\n- ong2\n- uo1\n- ou3\n- uo2\n- iao1\n- ou1\n- an2\n- uan4\n- ia4\n- ia1\n- ang3\n- v3\n- iu2\n- iao3\n- in4\n- a3\n- ei3\n- iang3\n- v2\n- eng4\n- en3\n- aa\n- uan1\n- v1\n- ao1\n- ve4\n- ie3\n- ai1\n- ing3\n- iang1\n- a2\n- ui1\n- en4\n- en5\n- in3\n- uan3\n- e3\n- ie1\n- ve2\n- ei2\n- in2\n- ix3\n- uan2\n- iang2\n- ie2\n- ua4\n- ou2\n- uai4\n- er2\n- eng3\n- uang3\n- un1\n- ong3\n- uang4\n- vn4\n- un2\n- iy3\n- iz4\n- ui3\n- iao2\n- iong4\n- un4\n- van4\n- ao2\n- uang1\n- iy5\n- o2\n- ei1\n- ua1\n- iu1\n- uang2\n- er5\n- o1\n- un3\n- vn1\n- vn2\n- o4\n- ve1\n- van3\n- ua2\n- er3\n- iong3\n- van1\n- ia2\n- iy2\n- ia3\n- iong1\n- uo5\n- oo\n- ve3\n- ou5\n- uai3\n- ian5\n- iong2\n- uai2\n- uai1\n- ua3\n- vn3\n- ia5\n- ie5\n- ueng1\n- o5\n- o3\n- iang5\n- ei5\n- <sos/eos>\n"
  },
  {
    "path": "examples/aishell3_vctk/ernie_sat/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results for aishell3 ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./aishell3_alignment_tone \\\n        --output durations_aishell3.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results for vctk ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./vctk_alignment \\\n        --output durations_vctk.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get durations from MFA's result\n    echo \"concat durations_aishell3.txt and durations_vctk.txt to durations.txt\"\n    cat durations_aishell3.txt durations_vctk.txt > durations.txt\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=~/datasets/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=vctk \\\n        --rootdir=~/datasets/VCTK-Corpus-0.92/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\nfi\n\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/aishell3_vctk/ernie_sat/local/synthesize_e2e.sh",
    "content": "# not ready yet\n#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo 'speech cross language from en to zh !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=synthesize \\\n        --wav_path=source/p243_313.wav \\\n        --old_str='For that reason cover should not be given' \\\n        --new_str='今天天气很好' \\\n        --source_lang=en \\\n        --target_lang=zh \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_clone_en_zh.wav\nfi\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo 'speech cross language from zh to en !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=synthesize \\\n        --wav_path=source/SSB03540307.wav \\\n        --old_str='请播放歌曲小苹果' \\\n        --new_str=\"Thank you\" \\\n        --source_lang=zh \\\n        --target_lang=en \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_clone_zh_en.wav\nfi\n\n"
  },
  {
    "path": "examples/aishell3_vctk/ernie_sat/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3,4,5,6,7\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_489000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is hifigan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, run both speech synthesis from Chinese to English and English to Chinese\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/ami/README.md",
    "content": "# Speaker Diarization on AMI corpus\n\n* sd0 - speaker diarization by AHC,SC base on embeddings\n"
  },
  {
    "path": "examples/ami/sd0/.gitignore",
    "content": "results"
  },
  {
    "path": "examples/ami/sd0/README.md",
    "content": "# Speaker Diarization on AMI corpus\n\n## About the AMI corpus:\n\"The AMI Meeting Corpus consists of 100 hours of meeting recordings. The recordings use a range of signals synchronized to a common timeline. These include close-talking and far-field microphones, individual and room-view video cameras, and output from a slide projector and an electronic whiteboard. During the meetings, the participants also have unsynchronized pens available to them that record what is written. The meetings were recorded in English using three different rooms with different acoustic properties, and include mostly non-native speakers.\" See [ami overview](http://groups.inf.ed.ac.uk/ami/corpus/overview.shtml) for more details.\n\n## About the example\nThe script performs diarization using x-vectors(TDNN,ECAPA-TDNN) on the AMI mix-headset data. We demonstrate the use of different clustering methods: AHC, spectral.\n\n## How to Run\n### prepare annotations and audios\nDownload AMI corpus, You need around 10GB of free space to get whole data\nThe signals are too large to package in this way, so you need to use the chooser to indicate which ones you wish to download\n\n```bash\n## download  annotations\nwget http://groups.inf.ed.ac.uk/ami/AMICorpusAnnotations/ami_public_manual_1.6.2.zip && unzip ami_public_manual_1.6.2.zip\n```\n\nthen please follow https://groups.inf.ed.ac.uk/ami/download/ to download the Signals:\n1) Select one or more AMI meetings: the IDs please follow ./ami_split.py\n2) Select media streams: Just select Headset mix\n\n### start running\nUse the following command to run diarization on AMI corpus.\n```bash\n./run.sh  --data_folder ./amicorpus  --manual_annot_folder ./ami_public_manual_1.6.2\n```\n\n## Best performance in terms of Diarization Error Rate (DER).\n  | System | Mic. |Orcl. (Dev)|Orcl. (Eval)| Est. (Dev) |Est. (Eval)|\n  | --------|-------- | ---------|----------- | --------|-----------|\n  | ECAPA-TDNN + SC  | HeadsetMix| 1.54 % | 3.07 %| 1.56 %| 3.28 %  |\n"
  },
  {
    "path": "examples/ami/sd0/conf/ecapa_tdnn.yaml",
    "content": "###########################################################\n#                AMI DATA PREPARE SETTING               #\n###########################################################\nsplit_type: 'full_corpus_asr'\nskip_TNO: True\n# Options for mic_type: 'Mix-Lapel', 'Mix-Headset', 'Array1', 'Array1-01', 'BeamformIt'\nmic_type: 'Mix-Headset'\nvad_type: 'oracle'\nmax_subseg_dur: 3.0\noverlap: 1.5\n# Some more exp folders (for cleaner structure).\nembedding_dir: emb #!ref <save_folder>/emb\nmeta_data_dir: metadata #!ref <save_folder>/metadata\nref_rttm_dir: ref_rttms #!ref <save_folder>/ref_rttms\nsys_rttm_dir: sys_rttms #!ref <save_folder>/sys_rttms\nder_dir: DER #!ref <save_folder>/DER\n\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n# currently, we only support fbank\nsr: 16000           # sample rate\nn_mels: 80\nwindow_size: 400     #25ms, sample rate 16000, 25 * 16000 / 1000 = 400 \nhop_size: 160        #10ms, sample rate 16000, 10 * 16000 / 1000 = 160\n#left_frames: 0\n#right_frames: 0\n#deltas: False\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\n# currently, we only support ecapa-tdnn in the ecapa_tdnn.yaml\n# if we want use another model, please choose another configuration yaml file\nseed: 1234\nemb_dim: 192\nbatch_size: 16\nmodel:\n  input_size: 80\n  channels: [1024, 1024, 1024, 1024, 3072]\n  kernel_sizes: [5, 3, 3, 3, 1]\n  dilations: [1, 2, 3, 4, 1]\n  attention_channels: 128\n  lin_neurons: 192\n# Will automatically download ECAPA-TDNN model (best).\n\n###########################################################\n#               SPECTRAL CLUSTERING SETTING               #\n###########################################################\nbackend: 'SC' # options: 'kmeans' # Note: kmeans goes only with cos affinity\naffinity: 'cos'  # options: cos, nn\nmax_num_spkrs: 10\noracle_n_spkrs: True\n\n\n###########################################################\n#                  DER EVALUATION SETTING                 #\n###########################################################\nignore_overlap: True\nforgiveness_collar: 0.25\n"
  },
  {
    "path": "examples/ami/sd0/local/ami_prepare.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nData preparation.\n\nDownload: http://groups.inf.ed.ac.uk/ami/download/\n\nPrepares metadata files (JSON) from manual annotations \"segments/\" using RTTM format (Oracle VAD).\n\"\"\"\nimport argparse\nimport glob\nimport json\nimport logging\nimport os\nimport xml.etree.ElementTree as et\n\nfrom ami_splits import get_AMI_split\nfrom dataio import load_pkl\nfrom dataio import save_pkl\n\nfrom paddlespeech.utils.argparse import strtobool\n\nlogger = logging.getLogger(__name__)\nSAMPLERATE = 16000\n\n\ndef prepare_ami(\n        data_folder,\n        manual_annot_folder,\n        save_folder,\n        ref_rttm_dir,\n        meta_data_dir,\n        split_type=\"full_corpus_asr\",\n        skip_TNO=True,\n        mic_type=\"Mix-Headset\",\n        vad_type=\"oracle\",\n        max_subseg_dur=3.0,\n        overlap=1.5, ):\n    \"\"\"\n    Prepares reference RTTM and JSON files for the AMI dataset.\n\n    Arguments\n    ---------\n    data_folder : str\n        Path to the folder where the original amicorpus is stored.\n    manual_annot_folder : str\n        Directory where the manual annotations are stored.\n    save_folder : str\n        The save directory in results.\n    ref_rttm_dir : str\n        Directory to store reference RTTM files.\n    meta_data_dir : str\n        Directory to store the meta data (json) files.\n    split_type : str\n        Standard dataset split. See ami_splits.py for more information.\n        Allowed split_type: \"scenario_only\", \"full_corpus\" or \"full_corpus_asr\"\n    skip_TNO: bool\n        Skips TNO meeting recordings if True.\n    mic_type : str\n        Type of microphone to be used.\n    vad_type : str\n        Type of VAD. Kept for future when VAD will be added.\n    max_subseg_dur : float\n        Duration in seconds of a subsegments to be prepared from larger segments.\n    overlap : float\n        Overlap duration in seconds between adjacent subsegments\n\n    Example\n    -------\n    >>> from dataset.ami.ami_prepare import prepare_ami\n    >>> data_folder = '/home/data/ami/amicorpus/'\n    >>> manual_annot_folder = '/home/data/ami/ami_public_manual/'\n    >>> save_folder = './results/\n    >>> split_type = 'full_corpus_asr'\n    >>> mic_type = 'Mix-Headset'\n    >>> prepare_ami(data_folder, manual_annot_folder, save_folder, split_type, mic_type)\n    \"\"\"\n\n    # Meta files\n    meta_files = [\n        os.path.join(meta_data_dir, \"ami_train.\" + mic_type + \".subsegs.json\"),\n        os.path.join(meta_data_dir, \"ami_dev.\" + mic_type + \".subsegs.json\"),\n        os.path.join(meta_data_dir, \"ami_eval.\" + mic_type + \".subsegs.json\"),\n    ]\n\n    # Create configuration for easily skipping data_preparation stage\n    conf = {\n        \"data_folder\": data_folder,\n        \"save_folder\": save_folder,\n        \"ref_rttm_dir\": ref_rttm_dir,\n        \"meta_data_dir\": meta_data_dir,\n        \"split_type\": split_type,\n        \"skip_TNO\": skip_TNO,\n        \"mic_type\": mic_type,\n        \"vad\": vad_type,\n        \"max_subseg_dur\": max_subseg_dur,\n        \"overlap\": overlap,\n        \"meta_files\": meta_files,\n    }\n\n    if not os.path.exists(save_folder):\n        os.makedirs(save_folder)\n\n    # Setting output option files.\n    opt_file = \"opt_ami_prepare.\" + mic_type + \".pkl\"\n\n    # Check if this phase is already done (if so, skip it)\n    if skip(save_folder, conf, meta_files, opt_file):\n        logger.info(\n            \"Skipping data preparation, as it was completed in previous run.\")\n        return\n\n    msg = \"\\tCreating meta-data file for the AMI Dataset..\"\n    logger.debug(msg)\n\n    # Get the split\n    train_set, dev_set, eval_set = get_AMI_split(split_type)\n\n    # Prepare RTTM from XML(manual annot) and store are groundtruth\n    # Create ref_RTTM directory\n    if not os.path.exists(ref_rttm_dir):\n        os.makedirs(ref_rttm_dir)\n\n    # Create reference RTTM files\n    splits = [\"train\", \"dev\", \"eval\"]\n    for i in splits:\n        rttm_file = ref_rttm_dir + \"/fullref_ami_\" + i + \".rttm\"\n        if i == \"train\":\n            prepare_segs_for_RTTM(\n                train_set,\n                rttm_file,\n                data_folder,\n                manual_annot_folder,\n                i,\n                skip_TNO, )\n        if i == \"dev\":\n            prepare_segs_for_RTTM(\n                dev_set,\n                rttm_file,\n                data_folder,\n                manual_annot_folder,\n                i,\n                skip_TNO, )\n        if i == \"eval\":\n            prepare_segs_for_RTTM(\n                eval_set,\n                rttm_file,\n                data_folder,\n                manual_annot_folder,\n                i,\n                skip_TNO, )\n\n    # Create meta_files for splits\n    meta_data_dir = meta_data_dir\n    if not os.path.exists(meta_data_dir):\n        os.makedirs(meta_data_dir)\n\n    for i in splits:\n        rttm_file = ref_rttm_dir + \"/fullref_ami_\" + i + \".rttm\"\n        meta_filename_prefix = \"ami_\" + i\n        prepare_metadata(\n            rttm_file,\n            meta_data_dir,\n            data_folder,\n            meta_filename_prefix,\n            max_subseg_dur,\n            overlap,\n            mic_type, )\n\n    save_opt_file = os.path.join(save_folder, opt_file)\n    save_pkl(conf, save_opt_file)\n\n\ndef get_RTTM_per_rec(segs, spkrs_list, rec_id):\n    \"\"\"Prepares rttm for each recording\n    \"\"\"\n\n    rttm = []\n\n    # Prepare header\n    for spkr_id in spkrs_list:\n        # e.g. SPKR-INFO ES2008c 0 <NA> <NA> <NA> unknown ES2008c.A_PM <NA> <NA>\n        line = (\"SPKR-INFO \" + rec_id + \" 0 <NA> <NA> <NA> unknown \" + spkr_id +\n                \" <NA> <NA>\")\n        rttm.append(line)\n\n    # Append remaining lines\n    for row in segs:\n        # e.g. SPEAKER ES2008c 0 37.880 0.590 <NA> <NA> ES2008c.A_PM <NA> <NA>\n\n        if float(row[1]) < float(row[0]):\n            msg1 = (\n                \"Possibly Incorrect Annotation Found!! transcriber_start (%s) > transcriber_end (%s)\"\n                % (row[0], row[1]))\n            msg2 = (\n                \"Excluding this incorrect row from the RTTM : %s, %s, %s, %s\" %\n                (rec_id, row[0], str(round(float(row[1]) - float(row[0]), 4)),\n                 str(row[2]), ))\n            logger.info(msg1)\n            logger.info(msg2)\n            continue\n\n        line = (\"SPEAKER \" + rec_id + \" 0 \" + str(round(float(row[0]), 4)) + \" \"\n                + str(round(float(row[1]) - float(row[0]), 4)) + \" <NA> <NA> \" +\n                str(row[2]) + \" <NA> <NA>\")\n        rttm.append(line)\n\n    return rttm\n\n\ndef prepare_segs_for_RTTM(list_ids, out_rttm_file, audio_dir, annot_dir,\n                          split_type, skip_TNO):\n\n    RTTM = []  # Stores all RTTMs clubbed together for a given dataset split\n\n    for main_meet_id in list_ids:\n\n        # Skip TNO meetings from dev and eval sets\n        if (main_meet_id.startswith(\"TS\") and split_type != \"train\" and\n                skip_TNO is True):\n            msg = (\"Skipping TNO meeting in AMI \" + str(split_type) + \" set : \"\n                   + str(main_meet_id))\n            logger.info(msg)\n            continue\n\n        list_sessions = glob.glob(audio_dir + \"/\" + main_meet_id + \"*\")\n        list_sessions.sort()\n\n        for sess in list_sessions:\n            rec_id = os.path.basename(sess)\n            path = annot_dir + \"/segments/\" + rec_id\n            f = path + \".*.segments.xml\"\n            list_spkr_xmls = glob.glob(f)\n            list_spkr_xmls.sort()  # A, B, C, D, E etc (Speakers)\n            segs = []\n            spkrs_list = (\n                [])  # Since non-scenario recordings contains 3-5 speakers\n\n            for spkr_xml_file in list_spkr_xmls:\n\n                # Speaker ID\n                spkr = os.path.basename(spkr_xml_file).split(\".\")[1]\n                spkr_ID = rec_id + \".\" + spkr\n                spkrs_list.append(spkr_ID)\n\n                # Parse xml tree\n                tree = et.parse(spkr_xml_file)\n                root = tree.getroot()\n\n                # Start, end and speaker_ID from xml file\n                segs = segs + [[\n                    elem.attrib[\"transcriber_start\"],\n                    elem.attrib[\"transcriber_end\"],\n                    spkr_ID,\n                ] for elem in root.iter(\"segment\")]\n\n            # Sort rows as per the start time (per recording)\n            segs.sort(key=lambda x: float(x[0]))\n\n            rttm_per_rec = get_RTTM_per_rec(segs, spkrs_list, rec_id)\n            RTTM = RTTM + rttm_per_rec\n\n    # Write one RTTM as groundtruth. For example, \"fullref_eval.rttm\"\n    with open(out_rttm_file, \"w\") as f:\n        for item in RTTM:\n            f.write(\"%s\\n\" % item)\n\n\ndef is_overlapped(end1, start2):\n    \"\"\"Returns True if the two segments overlap\n\n    Arguments\n    ---------\n    end1 : float\n        End time of the first segment.\n    start2 : float\n        Start time of the second segment.\n    \"\"\"\n\n    if start2 > end1:\n        return False\n    else:\n        return True\n\n\ndef merge_rttm_intervals(rttm_segs):\n    \"\"\"Merges adjacent segments in rttm if they overlap.\n    \"\"\"\n    # For one recording\n    # rec_id = rttm_segs[0][1]\n    rttm_segs.sort(key=lambda x: float(x[3]))\n\n    # first_seg = rttm_segs[0] # first interval.. as it is\n    merged_segs = [rttm_segs[0]]\n    strt = float(rttm_segs[0][3])\n    end = float(rttm_segs[0][3]) + float(rttm_segs[0][4])\n\n    for row in rttm_segs[1:]:\n        s = float(row[3])\n        e = float(row[3]) + float(row[4])\n\n        if is_overlapped(end, s):\n            # Update only end. The strt will be same as in last segment\n            # Just update last row in the merged_segs\n            end = max(end, e)\n            merged_segs[-1][3] = str(round(strt, 4))\n            merged_segs[-1][4] = str(round((end - strt), 4))\n            merged_segs[-1][7] = \"overlap\"  # previous_row[7] + '-'+ row[7]\n        else:\n            # Add a new disjoint segment\n            strt = s\n            end = e\n            merged_segs.append(row)  # this will have 1 spkr ID\n\n    return merged_segs\n\n\ndef get_subsegments(merged_segs, max_subseg_dur=3.0, overlap=1.5):\n    \"\"\"Divides bigger segments into smaller sub-segments\n    \"\"\"\n\n    shift = max_subseg_dur - overlap\n    subsegments = []\n\n    # These rows are in RTTM format\n    for row in merged_segs:\n        seg_dur = float(row[4])\n        rec_id = row[1]\n\n        if seg_dur > max_subseg_dur:\n            num_subsegs = int(seg_dur / shift)\n            # Taking 0.01 sec as small step\n            seg_start = float(row[3])\n            seg_end = seg_start + seg_dur\n\n            # Now divide this segment (new_row) in smaller subsegments\n            for i in range(num_subsegs):\n                subseg_start = seg_start + i * shift\n                subseg_end = min(subseg_start + max_subseg_dur - 0.01, seg_end)\n                subseg_dur = subseg_end - subseg_start\n\n                new_row = [\n                    \"SPEAKER\",\n                    rec_id,\n                    \"0\",\n                    str(round(float(subseg_start), 4)),\n                    str(round(float(subseg_dur), 4)),\n                    \"<NA>\",\n                    \"<NA>\",\n                    row[7],\n                    \"<NA>\",\n                    \"<NA>\",\n                ]\n\n                subsegments.append(new_row)\n\n                # Break if exceeding the boundary\n                if subseg_end >= seg_end:\n                    break\n        else:\n            subsegments.append(row)\n\n    return subsegments\n\n\ndef prepare_metadata(rttm_file, save_dir, data_dir, filename, max_subseg_dur,\n                     overlap, mic_type):\n    # Read RTTM, get unique meeting_IDs (from RTTM headers)\n    # For each MeetingID. select that meetID -> merge -> subsegment -> json -> append\n\n    # Read RTTM\n    RTTM = []\n    with open(rttm_file, \"r\") as f:\n        for line in f:\n            entry = line[:-1]\n            RTTM.append(entry)\n\n    spkr_info = filter(lambda x: x.startswith(\"SPKR-INFO\"), RTTM)\n    rec_ids = list(set([row.split(\" \")[1] for row in spkr_info]))\n    rec_ids.sort()  # sorting just to make JSON look in proper sequence\n\n    # For each recording merge segments and then perform subsegmentation\n    MERGED_SEGMENTS = []\n    SUBSEGMENTS = []\n    for rec_id in rec_ids:\n        segs_iter = filter(lambda x: x.startswith(\"SPEAKER \" + str(rec_id)),\n                           RTTM)\n        gt_rttm_segs = [row.split(\" \") for row in segs_iter]\n\n        # Merge, subsegment and then convert to json format.\n        merged_segs = merge_rttm_intervals(\n            gt_rttm_segs)  # We lose speaker_ID after merging\n        MERGED_SEGMENTS = MERGED_SEGMENTS + merged_segs\n\n        # Divide segments into smaller sub-segments\n        subsegs = get_subsegments(merged_segs, max_subseg_dur, overlap)\n        SUBSEGMENTS = SUBSEGMENTS + subsegs\n\n    # Write segment AND sub-segments (in RTTM format)\n    segs_file = save_dir + \"/\" + filename + \".segments.rttm\"\n    subsegment_file = save_dir + \"/\" + filename + \".subsegments.rttm\"\n\n    with open(segs_file, \"w\") as f:\n        for row in MERGED_SEGMENTS:\n            line_str = \" \".join(row)\n            f.write(\"%s\\n\" % line_str)\n\n    with open(subsegment_file, \"w\") as f:\n        for row in SUBSEGMENTS:\n            line_str = \" \".join(row)\n            f.write(\"%s\\n\" % line_str)\n\n    # Create JSON from subsegments\n    json_dict = {}\n    for row in SUBSEGMENTS:\n        rec_id = row[1]\n        strt = str(round(float(row[3]), 4))\n        end = str(round((float(row[3]) + float(row[4])), 4))\n        subsegment_ID = rec_id + \"_\" + strt + \"_\" + end\n        dur = row[4]\n        start_sample = int(float(strt) * SAMPLERATE)\n        end_sample = int(float(end) * SAMPLERATE)\n\n        # If multi-mic audio is selected\n        if mic_type == \"Array1\":\n            wav_file_base_path = (data_dir + \"/\" + rec_id + \"/audio/\" + rec_id +\n                                  \".\" + mic_type + \"-\")\n\n            f = []  # adding all 8 mics\n            for i in range(8):\n                f.append(wav_file_base_path + str(i + 1).zfill(2) + \".wav\")\n            audio_files_path_list = f\n\n            # Note: key \"files\" with 's' is used for multi-mic\n            json_dict[subsegment_ID] = {\n                \"wav\": {\n                    \"files\": audio_files_path_list,\n                    \"duration\": float(dur),\n                    \"start\": int(start_sample),\n                    \"stop\": int(end_sample),\n                },\n            }\n        else:\n            # Single mic audio\n            wav_file_path = (data_dir + \"/\" + rec_id + \"/audio/\" + rec_id + \".\"\n                             + mic_type + \".wav\")\n\n            # Note: key \"file\" without 's' is used for single-mic\n            json_dict[subsegment_ID] = {\n                \"wav\": {\n                    \"file\": wav_file_path,\n                    \"duration\": float(dur),\n                    \"start\": int(start_sample),\n                    \"stop\": int(end_sample),\n                },\n            }\n\n    out_json_file = save_dir + \"/\" + filename + \".\" + mic_type + \".subsegs.json\"\n    with open(out_json_file, mode=\"w\") as json_f:\n        json.dump(json_dict, json_f, indent=2)\n\n    msg = \"%s JSON prepared\" % (out_json_file)\n    logger.debug(msg)\n\n\ndef skip(save_folder, conf, meta_files, opt_file):\n    \"\"\"\n    Detects if the AMI data_preparation has been already done.\n    If the preparation has been done, we can skip it.\n\n    Returns\n    -------\n    bool\n        if True, the preparation phase can be skipped.\n        if False, it must be done.\n    \"\"\"\n    # Checking if meta (json) files are available\n    skip = True\n    for file_path in meta_files:\n        if not os.path.isfile(file_path):\n            skip = False\n\n    # Checking saved options\n    save_opt_file = os.path.join(save_folder, opt_file)\n    if skip is True:\n        if os.path.isfile(save_opt_file):\n            opts_old = load_pkl(save_opt_file)\n            if opts_old == conf:\n                skip = True\n            else:\n                skip = False\n        else:\n            skip = False\n\n    return skip\n\n\nif __name__ == '__main__':\n\n    parser = argparse.ArgumentParser(\n        prog='python ami_prepare.py  --data_folder /home/data/ami/amicorpus \\\n            --manual_annot_folder /home/data/ami/ami_public_manual_1.6.2 \\\n            --save_folder ./results/ --ref_rttm_dir ./results/ref_rttms \\\n            --meta_data_dir ./results/metadata',\n        description='AMI Data preparation')\n    parser.add_argument(\n        '--data_folder',\n        required=True,\n        help='Path to the folder where the original amicorpus is stored')\n    parser.add_argument(\n        '--manual_annot_folder',\n        required=True,\n        help='Directory where the manual annotations are stored')\n    parser.add_argument(\n        '--save_folder', required=True, help='The save directory in results')\n    parser.add_argument(\n        '--ref_rttm_dir',\n        required=True,\n        help='Directory to store reference RTTM files')\n    parser.add_argument(\n        '--meta_data_dir',\n        required=True,\n        help='Directory to store the meta data (json) files')\n    parser.add_argument(\n        '--split_type',\n        default=\"full_corpus_asr\",\n        help='Standard dataset split. See ami_splits.py for more information')\n    parser.add_argument(\n        '--skip_TNO',\n        default=True,\n        type=strtobool,\n        help='Skips TNO meeting recordings if True')\n    parser.add_argument(\n        '--mic_type',\n        default=\"Mix-Headset\",\n        help='Type of microphone to be used')\n    parser.add_argument(\n        '--vad_type',\n        default=\"oracle\",\n        help='Type of VAD. Kept for future when VAD will be added')\n    parser.add_argument(\n        '--max_subseg_dur',\n        default=3.0,\n        type=float,\n        help='Duration in seconds of a subsegments to be prepared from larger segments'\n    )\n    parser.add_argument(\n        '--overlap',\n        default=1.5,\n        type=float,\n        help='Overlap duration in seconds between adjacent subsegments')\n\n    args = parser.parse_args()\n\n    prepare_ami(args.data_folder, args.manual_annot_folder, args.save_folder,\n                args.ref_rttm_dir, args.meta_data_dir)\n"
  },
  {
    "path": "examples/ami/sd0/local/ami_splits.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAMI corpus contained 100 hours of meeting recording.\nThis script returns the standard train, dev and eval split for AMI corpus.\nFor more information on dataset please refer to http://groups.inf.ed.ac.uk/ami/corpus/datasets.shtml\n\"\"\"\n\nALLOWED_OPTIONS = [\"scenario_only\", \"full_corpus\", \"full_corpus_asr\"]\n\n\ndef get_AMI_split(split_option):\n    \"\"\"\n    Prepares train, dev, and test sets for given split_option\n\n    Arguments\n    ---------\n    split_option: str\n        The standard split option.\n        Allowed options: \"scenario_only\", \"full_corpus\", \"full_corpus_asr\"\n\n    Returns\n    -------\n        Meeting IDs for train, dev, and test sets for given split_option\n    \"\"\"\n\n    if split_option not in ALLOWED_OPTIONS:\n        print(\n            f'Invalid split \"{split_option}\" requested!\\nValid split_options are: ',\n            ALLOWED_OPTIONS, )\n        return\n\n    if split_option == \"scenario_only\":\n\n        train_set = [\n            \"ES2002\",\n            \"ES2005\",\n            \"ES2006\",\n            \"ES2007\",\n            \"ES2008\",\n            \"ES2009\",\n            \"ES2010\",\n            \"ES2012\",\n            \"ES2013\",\n            \"ES2015\",\n            \"ES2016\",\n            \"IS1000\",\n            \"IS1001\",\n            \"IS1002\",\n            \"IS1003\",\n            \"IS1004\",\n            \"IS1005\",\n            \"IS1006\",\n            \"IS1007\",\n            \"TS3005\",\n            \"TS3008\",\n            \"TS3009\",\n            \"TS3010\",\n            \"TS3011\",\n            \"TS3012\",\n        ]\n\n        dev_set = [\n            \"ES2003\",\n            \"ES2011\",\n            \"IS1008\",\n            \"TS3004\",\n            \"TS3006\",\n        ]\n\n        test_set = [\n            \"ES2004\",\n            \"ES2014\",\n            \"IS1009\",\n            \"TS3003\",\n            \"TS3007\",\n        ]\n\n    if split_option == \"full_corpus\":\n        # List of train: SA (TRAINING PART OF SEEN DATA)\n        train_set = [\n            \"ES2002\",\n            \"ES2005\",\n            \"ES2006\",\n            \"ES2007\",\n            \"ES2008\",\n            \"ES2009\",\n            \"ES2010\",\n            \"ES2012\",\n            \"ES2013\",\n            \"ES2015\",\n            \"ES2016\",\n            \"IS1000\",\n            \"IS1001\",\n            \"IS1002\",\n            \"IS1003\",\n            \"IS1004\",\n            \"IS1005\",\n            \"IS1006\",\n            \"IS1007\",\n            \"TS3005\",\n            \"TS3008\",\n            \"TS3009\",\n            \"TS3010\",\n            \"TS3011\",\n            \"TS3012\",\n            \"EN2001\",\n            \"EN2003\",\n            \"EN2004\",\n            \"EN2005\",\n            \"EN2006\",\n            \"EN2009\",\n            \"IN1001\",\n            \"IN1002\",\n            \"IN1005\",\n            \"IN1007\",\n            \"IN1008\",\n            \"IN1009\",\n            \"IN1012\",\n            \"IN1013\",\n            \"IN1014\",\n            \"IN1016\",\n        ]\n\n        # List of dev: SB (DEV PART OF SEEN DATA)\n        dev_set = [\n            \"ES2003\",\n            \"ES2011\",\n            \"IS1008\",\n            \"TS3004\",\n            \"TS3006\",\n            \"IB4001\",\n            \"IB4002\",\n            \"IB4003\",\n            \"IB4004\",\n            \"IB4010\",\n            \"IB4011\",\n        ]\n\n        # List of test: SC (UNSEEN DATA FOR EVALUATION)\n        # Note that IB4005 does not appear because it has speakers in common with two sets of data.\n        test_set = [\n            \"ES2004\",\n            \"ES2014\",\n            \"IS1009\",\n            \"TS3003\",\n            \"TS3007\",\n            \"EN2002\",\n        ]\n\n    if split_option == \"full_corpus_asr\":\n        train_set = [\n            \"ES2002\",\n            \"ES2003\",\n            \"ES2005\",\n            \"ES2006\",\n            \"ES2007\",\n            \"ES2008\",\n            \"ES2009\",\n            \"ES2010\",\n            \"ES2012\",\n            \"ES2013\",\n            \"ES2014\",\n            \"ES2015\",\n            \"ES2016\",\n            \"IS1000\",\n            \"IS1001\",\n            \"IS1002\",\n            \"IS1003\",\n            \"IS1004\",\n            \"IS1005\",\n            \"IS1006\",\n            \"IS1007\",\n            \"TS3005\",\n            \"TS3006\",\n            \"TS3007\",\n            \"TS3008\",\n            \"TS3009\",\n            \"TS3010\",\n            \"TS3011\",\n            \"TS3012\",\n            \"EN2001\",\n            \"EN2003\",\n            \"EN2004\",\n            \"EN2005\",\n            \"EN2006\",\n            \"EN2009\",\n            \"IN1001\",\n            \"IN1002\",\n            \"IN1005\",\n            \"IN1007\",\n            \"IN1008\",\n            \"IN1009\",\n            \"IN1012\",\n            \"IN1013\",\n            \"IN1014\",\n            \"IN1016\",\n        ]\n\n        dev_set = [\n            \"ES2011\",\n            \"IS1008\",\n            \"TS3004\",\n            \"IB4001\",\n            \"IB4002\",\n            \"IB4003\",\n            \"IB4004\",\n            \"IB4010\",\n            \"IB4011\",\n        ]\n\n        test_set = [\n            \"ES2004\",\n            \"IS1009\",\n            \"TS3003\",\n            \"EN2002\",\n        ]\n\n    return train_set, dev_set, test_set\n"
  },
  {
    "path": "examples/ami/sd0/local/compute_embdding.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport json\nimport os\nimport pickle\nimport sys\n\nimport numpy as np\nimport paddle\nfrom paddle.io import BatchSampler\nfrom paddle.io import DataLoader\nfrom tqdm.contrib import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.cluster.diarization import EmbeddingMeta\nfrom paddlespeech.vector.io.batch import batch_feature_normalize\nfrom paddlespeech.vector.io.dataset_from_json import JSONDataset\nfrom paddlespeech.vector.models.ecapa_tdnn import EcapaTdnn\nfrom paddlespeech.vector.modules.sid_model import SpeakerIdetification\nfrom paddlespeech.vector.training.seeding import seed_everything\n\n# Logger setup\nlogger = Log(__name__).getlog()\n\n\ndef prepare_subset_json(full_meta_data, rec_id, out_meta_file):\n    \"\"\"Prepares metadata for a given recording ID.\n\n    Arguments\n    ---------\n    full_meta_data : json\n        Full meta (json) containing all the recordings\n    rec_id : str\n        The recording ID for which meta (json) has to be prepared\n    out_meta_file : str\n        Path of the output meta (json) file.\n    \"\"\"\n\n    subset = {}\n    for key in full_meta_data:\n        k = str(key)\n        if k.startswith(rec_id):\n            subset[key] = full_meta_data[key]\n\n    with open(out_meta_file, mode=\"w\") as json_f:\n        json.dump(subset, json_f, indent=2)\n\n\ndef create_dataloader(json_file, batch_size):\n    \"\"\"Creates the datasets and their data processing pipelines.\n    This is used for multi-mic processing.\n    \"\"\"\n\n    # create datasets\n    dataset = JSONDataset(\n        json_file=json_file,\n        feat_type='melspectrogram',\n        n_mels=config.n_mels,\n        window_size=config.window_size,\n        hop_length=config.hop_size)\n\n    # create dataloader\n    batch_sampler = BatchSampler(dataset, batch_size=batch_size, shuffle=True)\n    dataloader = DataLoader(dataset,\n                            batch_sampler=batch_sampler,\n                            collate_fn=lambda x: batch_feature_normalize(\n                                x, mean_norm=True, std_norm=False),\n                            return_list=True)\n\n    return dataloader\n\n\ndef main(args, config):\n    # set the training device, cpu or gpu\n    paddle.set_device(args.device)\n    # set the random seed\n    seed_everything(config.seed)\n\n    # stage1: build the dnn backbone model network\n    ecapa_tdnn = EcapaTdnn(**config.model)\n\n    # stage2: build the speaker verification eval instance with backbone model\n    model = SpeakerIdetification(backbone=ecapa_tdnn, num_class=1)\n\n    # stage3: load the pre-trained model\n    #         we get the last model from the epoch and save_interval\n    args.load_checkpoint = os.path.abspath(\n        os.path.expanduser(args.load_checkpoint))\n\n    # load model checkpoint to sid model\n    state_dict = paddle.load(\n        os.path.join(args.load_checkpoint, 'model.pdparams'))\n    model.set_state_dict(state_dict)\n    logger.info(f'Checkpoint loaded from {args.load_checkpoint}')\n\n    # set the model to eval mode\n    model.eval()\n\n    # load meta data\n    meta_file = os.path.join(\n        args.data_dir,\n        config.meta_data_dir,\n        \"ami_\" + args.dataset + \".\" + config.mic_type + \".subsegs.json\", )\n    with open(meta_file, \"r\") as f:\n        full_meta = json.load(f)\n\n    # get all the recording IDs in this dataset.\n    all_keys = full_meta.keys()\n    A = [word.rstrip().split(\"_\")[0] for word in all_keys]\n    all_rec_ids = list(set(A[1:]))\n    all_rec_ids.sort()\n    split = \"AMI_\" + args.dataset\n    i = 1\n\n    msg = \"Extra embdding for \" + args.dataset + \" set\"\n    logger.info(msg)\n\n    if len(all_rec_ids) <= 0:\n        msg = \"No recording IDs found! Please check if meta_data json file is properly generated.\"\n        logger.error(msg)\n        sys.exit()\n\n    # extra different recordings embdding in a dataset.\n    for rec_id in tqdm(all_rec_ids):\n        # This tag will be displayed in the log.\n        tag = (\"[\" + str(args.dataset) + \": \" + str(i) + \"/\" +\n               str(len(all_rec_ids)) + \"]\")\n        i = i + 1\n\n        # log message.\n        msg = \"Embdding %s : %s \" % (tag, rec_id)\n        logger.debug(msg)\n\n        # embedding directory.\n        if not os.path.exists(\n                os.path.join(args.data_dir, config.embedding_dir, split)):\n            os.makedirs(\n                os.path.join(args.data_dir, config.embedding_dir, split))\n\n        # file to store embeddings.\n        emb_file_name = rec_id + \".\" + config.mic_type + \".emb_stat.pkl\"\n        diary_stat_emb_file = os.path.join(args.data_dir, config.embedding_dir,\n                                           split, emb_file_name)\n\n        # prepare a metadata (json) for one recording. This is basically a subset of full_meta.\n        # lets keep this meta-info in embedding directory itself.\n        json_file_name = rec_id + \".\" + config.mic_type + \".json\"\n        meta_per_rec_file = os.path.join(args.data_dir, config.embedding_dir,\n                                         split, json_file_name)\n\n        # write subset (meta for one recording) json metadata.\n        prepare_subset_json(full_meta, rec_id, meta_per_rec_file)\n\n        # prepare data loader.\n        diary_set_loader = create_dataloader(meta_per_rec_file,\n                                             config.batch_size)\n\n        # extract embeddings (skip if already done).\n        if not os.path.isfile(diary_stat_emb_file):\n            logger.debug(\"Extracting deep embeddings\")\n            embeddings = np.empty(shape=[0, config.emb_dim], dtype=np.float64)\n            segset = []\n\n            for batch_idx, batch in enumerate(tqdm(diary_set_loader)):\n                # extrac the audio embedding\n                ids, feats, lengths = batch['ids'], batch['feats'], batch[\n                    'lengths']\n                seg = [x for x in ids]\n                segset = segset + seg\n                emb = model.backbone(feats, lengths).squeeze(\n                    -1).numpy()  # (N, emb_size, 1) -> (N, emb_size)\n                embeddings = np.concatenate((embeddings, emb), axis=0)\n\n            segset = np.array(segset, dtype=\"|O\")\n            stat_obj = EmbeddingMeta(\n                segset=segset,\n                stats=embeddings, )\n            logger.debug(\"Saving Embeddings...\")\n            with open(diary_stat_emb_file, \"wb\") as output:\n                pickle.dump(stat_obj, output)\n\n        else:\n            logger.debug(\"Skipping embedding extraction (as already present).\")\n\n\n# Begin experiment!\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\n        '--device',\n        default=\"gpu\",\n        help=\"Select which device to perform diarization, defaults to gpu.\")\n    parser.add_argument(\n        \"--config\", default=None, type=str, help=\"configuration file\")\n    parser.add_argument(\n        \"--data-dir\",\n        default=\"../save/\",\n        type=str,\n        help=\"processsed data directory\")\n    parser.add_argument(\n        \"--dataset\",\n        choices=['dev', 'eval'],\n        default=\"dev\",\n        type=str,\n        help=\"Select which dataset to extra embdding, defaults to dev\")\n    parser.add_argument(\n        \"--load-checkpoint\",\n        type=str,\n        default='',\n        help=\"Directory to load model checkpoint to compute embeddings.\")\n    args = parser.parse_args()\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n\n    main(args, config)\n"
  },
  {
    "path": "examples/ami/sd0/local/dataio.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nData reading and writing.\n\"\"\"\nimport os\nimport pickle\n\n\ndef save_pkl(obj, file):\n    \"\"\"Save an object in pkl format.\n\n    Arguments\n    ---------\n    obj : object\n        Object to save in pkl format\n    file : str\n        Path to the output file\n    sampling_rate : int\n        Sampling rate of the audio file, TODO: this is not used?\n\n    Example\n    -------\n    >>> tmpfile = os.path.join(getfixture('tmpdir'), \"example.pkl\")\n    >>> save_pkl([1, 2, 3, 4, 5], tmpfile)\n    >>> load_pkl(tmpfile)\n    [1, 2, 3, 4, 5]\n    \"\"\"\n    with open(file, \"wb\") as f:\n        pickle.dump(obj, f)\n\n\ndef load_pickle(pickle_path):\n    \"\"\"Utility function for loading .pkl pickle files.\n\n    Arguments\n    ---------\n    pickle_path : str\n        Path to pickle file.\n\n    Returns\n    -------\n    out : object\n        Python object loaded from pickle.\n    \"\"\"\n    with open(pickle_path, \"rb\") as f:\n        out = pickle.load(f)\n    return out\n\n\ndef load_pkl(file):\n    \"\"\"Loads a pkl file.\n\n    For an example, see `save_pkl`.\n\n    Arguments\n    ---------\n    file : str\n        Path to the input pkl file.\n\n    Returns\n    -------\n    The loaded object.\n    \"\"\"\n\n    # Deals with the situation where two processes are trying\n    # to access the same label dictionary by creating a lock\n    count = 100\n    while count > 0:\n        if os.path.isfile(file + \".lock\"):\n            time.sleep(1)\n            count -= 1\n        else:\n            break\n\n    try:\n        open(file + \".lock\", \"w\").close()\n        with open(file, \"rb\") as f:\n            return pickle.load(f)\n    finally:\n        if os.path.isfile(file + \".lock\"):\n            os.remove(file + \".lock\")\n"
  },
  {
    "path": "examples/ami/sd0/local/experiment.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport glob\nimport json\nimport os\nimport pickle\nimport shutil\nimport sys\n\nimport numpy as np\nfrom tqdm.contrib import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.cluster import diarization as diar\nfrom utils.DER import DER\n\n# Logger setup\nlogger = Log(__name__).getlog()\n\n\ndef diarize_dataset(\n        full_meta,\n        split_type,\n        n_lambdas,\n        pval,\n        save_dir,\n        config,\n        n_neighbors=10, ):\n    \"\"\"This function diarizes all the recordings in a given dataset. It performs\n    computation of embedding and clusters them using spectral clustering (or other backends).\n    The output speaker boundary file is stored in the RTTM format.\n    \"\"\"\n\n    # prepare `spkr_info` only once when Oracle num of speakers is selected.\n    # spkr_info is essential to obtain number of speakers from groundtruth.\n    if config.oracle_n_spkrs is True:\n        full_ref_rttm_file = os.path.join(save_dir, config.ref_rttm_dir,\n                                          \"fullref_ami_\" + split_type + \".rttm\")\n        rttm = diar.read_rttm(full_ref_rttm_file)\n\n        spkr_info = list(  # noqa F841\n            filter(lambda x: x.startswith(\"SPKR-INFO\"), rttm))\n\n    # get all the recording IDs in this dataset.\n    all_keys = full_meta.keys()\n    A = [word.rstrip().split(\"_\")[0] for word in all_keys]\n    all_rec_ids = list(set(A[1:]))\n    all_rec_ids.sort()\n    split = \"AMI_\" + split_type\n    i = 1\n\n    # adding tag for directory path.\n    type_of_num_spkr = \"oracle\" if config.oracle_n_spkrs else \"est\"\n    tag = (type_of_num_spkr + \"_\" + str(config.affinity) + \"_\" + config.backend)\n\n    # make out rttm dir\n    out_rttm_dir = os.path.join(save_dir, config.sys_rttm_dir, config.mic_type,\n                                split, tag)\n    if not os.path.exists(out_rttm_dir):\n        os.makedirs(out_rttm_dir)\n\n    # diarizing different recordings in a dataset.\n    for rec_id in tqdm(all_rec_ids):\n        # this tag will be displayed in the log.\n        tag = (\"[\" + str(split_type) + \": \" + str(i) + \"/\" +\n               str(len(all_rec_ids)) + \"]\")\n        i = i + 1\n\n        # log message.\n        msg = \"Diarizing %s : %s \" % (tag, rec_id)\n        logger.debug(msg)\n\n        # load embeddings.\n        emb_file_name = rec_id + \".\" + config.mic_type + \".emb_stat.pkl\"\n        diary_stat_emb_file = os.path.join(save_dir, config.embedding_dir,\n                                           split, emb_file_name)\n        if not os.path.isfile(diary_stat_emb_file):\n            msg = \"Embdding file %s not found! Please check if embdding file is properly generated.\" % (\n                diary_stat_emb_file)\n            logger.error(msg)\n            sys.exit()\n        with open(diary_stat_emb_file, \"rb\") as in_file:\n            diary_obj = pickle.load(in_file)\n\n        out_rttm_file = out_rttm_dir + \"/\" + rec_id + \".rttm\"\n\n        # processing starts from here.\n        if config.oracle_n_spkrs is True:\n            # oracle num of speakers.\n            num_spkrs = diar.get_oracle_num_spkrs(rec_id, spkr_info)\n        else:\n            if config.affinity == \"nn\":\n                # num of speakers tunned on dev set (only for nn affinity).\n                num_spkrs = n_lambdas\n            else:\n                # num of speakers will be estimated using max eigen gap for cos based affinity.\n                # so adding None here. Will use this None later-on.\n                num_spkrs = None\n\n        if config.backend == \"kmeans\":\n            diar.do_kmeans_clustering(\n                diary_obj,\n                out_rttm_file,\n                rec_id,\n                num_spkrs,\n                pval, )\n\n        if config.backend == \"SC\":\n            # go for Spectral Clustering (SC).\n            diar.do_spec_clustering(\n                diary_obj,\n                out_rttm_file,\n                rec_id,\n                num_spkrs,\n                pval,\n                config.affinity,\n                n_neighbors, )\n\n        # can used for AHC later. Likewise one can add different backends here.\n        if config.backend == \"AHC\":\n            # call AHC\n            threshold = pval  # pval for AHC is nothing but threshold.\n            diar.do_AHC(diary_obj, out_rttm_file, rec_id, num_spkrs, threshold)\n\n    # once all RTTM outputs are generated, concatenate individual RTTM files to obtain single RTTM file.\n    # this is not needed but just staying with the standards.\n    concate_rttm_file = out_rttm_dir + \"/sys_output.rttm\"\n    logger.debug(\"Concatenating individual RTTM files...\")\n    with open(concate_rttm_file, \"w\") as cat_file:\n        for f in glob.glob(out_rttm_dir + \"/*.rttm\"):\n            if f == concate_rttm_file:\n                continue\n            with open(f, \"r\") as indi_rttm_file:\n                shutil.copyfileobj(indi_rttm_file, cat_file)\n\n    msg = \"The system generated RTTM file for %s set : %s\" % (\n        split_type, concate_rttm_file, )\n    logger.debug(msg)\n\n    return concate_rttm_file\n\n\ndef dev_pval_tuner(full_meta, save_dir, config):\n    \"\"\"Tuning p_value for affinity matrix.\n    The p_value used so that only p% of the values in each row is retained.\n    \"\"\"\n\n    DER_list = []\n    prange = np.arange(0.002, 0.015, 0.001)\n\n    n_lambdas = None  # using it as flag later.\n    for p_v in prange:\n        # Process whole dataset for value of p_v.\n        concate_rttm_file = diarize_dataset(full_meta, \"dev\", n_lambdas, p_v,\n                                            save_dir, config)\n\n        ref_rttm_file = os.path.join(save_dir, config.ref_rttm_dir,\n                                     \"fullref_ami_dev.rttm\")\n        sys_rttm_file = concate_rttm_file\n        [MS, FA, SER, DER_] = DER(\n            ref_rttm_file,\n            sys_rttm_file,\n            config.ignore_overlap,\n            config.forgiveness_collar, )\n\n        DER_list.append(DER_)\n\n        if config.oracle_n_spkrs is True and config.backend == \"kmeans\":\n            # no need of p_val search. Note p_val is needed for SC for both oracle and est num of speakers.\n            # p_val is needed in oracle_n_spkr=False when using kmeans backend.\n            break\n\n    # Take p_val that gave minmum DER on Dev dataset.\n    tuned_p_val = prange[DER_list.index(min(DER_list))]\n\n    return tuned_p_val\n\n\ndef dev_ahc_threshold_tuner(full_meta, save_dir, config):\n    \"\"\"Tuning threshold for affinity matrix. This function is called when AHC is used as backend.\n    \"\"\"\n\n    DER_list = []\n    prange = np.arange(0.0, 1.0, 0.1)\n\n    n_lambdas = None  # using it as flag later.\n\n    # Note: p_val is threshold in case of AHC.\n    for p_v in prange:\n        # Process whole dataset for value of p_v.\n        concate_rttm_file = diarize_dataset(full_meta, \"dev\", n_lambdas, p_v,\n                                            save_dir, config)\n\n        ref_rttm = os.path.join(save_dir, config.ref_rttm_dir,\n                                \"fullref_ami_dev.rttm\")\n        sys_rttm = concate_rttm_file\n        [MS, FA, SER, DER_] = DER(\n            ref_rttm,\n            sys_rttm,\n            config.ignore_overlap,\n            config.forgiveness_collar, )\n\n        DER_list.append(DER_)\n\n        if config.oracle_n_spkrs is True:\n            break  # no need of threshold search.\n\n    # Take p_val that gave minmum DER on Dev dataset.\n    tuned_p_val = prange[DER_list.index(min(DER_list))]\n\n    return tuned_p_val\n\n\ndef dev_nn_tuner(full_meta, split_type, save_dir, config):\n    \"\"\"Tuning n_neighbors on dev set. Assuming oracle num of speakers.\n    This is used when nn based affinity is selected.\n    \"\"\"\n\n    DER_list = []\n    pval = None\n\n    # Now assumming oracle num of speakers.\n    n_lambdas = 4\n\n    for nn in range(5, 15):\n\n        # Process whole dataset for value of n_lambdas.\n        concate_rttm_file = diarize_dataset(full_meta, \"dev\", n_lambdas, p_v,\n                                            save_dir, config, nn)\n\n        ref_rttm = os.path.join(save_dir, config.ref_rttm_dir,\n                                \"fullref_ami_dev.rttm\")\n        sys_rttm = concate_rttm_file\n        [MS, FA, SER, DER_] = DER(\n            ref_rttm,\n            sys_rttm,\n            config.ignore_overlap,\n            config.forgiveness_collar, )\n\n        DER_list.append([nn, DER_])\n\n        if config.oracle_n_spkrs is True and config.backend == \"kmeans\":\n            break\n\n    DER_list.sort(key=lambda x: x[1])\n    tunned_nn = DER_list[0]\n\n    return tunned_nn[0]\n\n\ndef dev_tuner(full_meta, split_type, save_dir, config):\n    \"\"\"Tuning n_components on dev set. Used for nn based affinity matrix.\n    Note: This is a very basic tunning for nn based affinity.\n    This is work in progress till we find a better way.\n    \"\"\"\n\n    DER_list = []\n    pval = None\n    for n_lambdas in range(1, config.max_num_spkrs + 1):\n\n        # Process whole dataset for value of n_lambdas.\n        concate_rttm_file = diarize_dataset(full_meta, \"dev\", n_lambdas, p_v,\n                                            save_dir, config)\n\n        ref_rttm = os.path.join(save_dir, config.ref_rttm_dir,\n                                \"fullref_ami_dev.rttm\")\n        sys_rttm = concate_rttm_file\n        [MS, FA, SER, DER_] = DER(\n            ref_rttm,\n            sys_rttm,\n            config.ignore_overlap,\n            config.forgiveness_collar, )\n\n        DER_list.append(DER_)\n\n    # Take n_lambdas with minmum DER.\n    tuned_n_lambdas = DER_list.index(min(DER_list)) + 1\n\n    return tuned_n_lambdas\n\n\ndef main(args, config):\n    # AMI Dev Set: Tune hyperparams on dev set.\n    # Read the embdding file for dev set generated during embdding compute\n    dev_meta_file = os.path.join(\n        args.data_dir,\n        config.meta_data_dir,\n        \"ami_dev.\" + config.mic_type + \".subsegs.json\", )\n    with open(dev_meta_file, \"r\") as f:\n        meta_dev = json.load(f)\n\n    full_meta = meta_dev\n\n    # Processing starts from here\n    # Following few lines selects option for different backend and affinity matrices. Finds best values for hyperameters using dev set.\n    ref_rttm_file = os.path.join(args.data_dir, config.ref_rttm_dir,\n                                 \"fullref_ami_dev.rttm\")\n    best_nn = None\n    if config.affinity == \"nn\":\n        logger.info(\"Tuning for nn (Multiple iterations over AMI Dev set)\")\n        best_nn = dev_nn_tuner(full_meta, args.data_dir, config)\n\n    n_lambdas = None\n    best_pval = None\n\n    if config.affinity == \"cos\" and (config.backend == \"SC\" or\n                                     config.backend == \"kmeans\"):\n        # oracle num_spkrs or not, doesn't matter for kmeans and SC backends\n        # cos: Tune for the best pval for SC /kmeans (for unknown num of spkrs)\n        logger.info(\n            \"Tuning for p-value for SC (Multiple iterations over AMI Dev set)\")\n        best_pval = dev_pval_tuner(full_meta, args.data_dir, config)\n\n    elif config.backend == \"AHC\":\n        logger.info(\"Tuning for threshold-value for AHC\")\n        best_threshold = dev_ahc_threshold_tuner(full_meta, args.data_dir,\n                                                 config)\n        best_pval = best_threshold\n    else:\n        # NN for unknown num of speakers (can be used in future)\n        if config.oracle_n_spkrs is False:\n            # nn: Tune num of number of components (to be updated later)\n            logger.info(\n                \"Tuning for number of eigen components for NN (Multiple iterations over AMI Dev set)\"\n            )\n            # dev_tuner used for tuning num of components in NN. Can be used in future.\n            n_lambdas = dev_tuner(full_meta, args.data_dir, config)\n\n    # load 'dev' and 'eval' metadata files.\n    full_meta_dev = full_meta  # current full_meta is for 'dev'\n    eval_meta_file = os.path.join(\n        args.data_dir,\n        config.meta_data_dir,\n        \"ami_eval.\" + config.mic_type + \".subsegs.json\", )\n    with open(eval_meta_file, \"r\") as f:\n        full_meta_eval = json.load(f)\n\n    # tag to be appended to final output DER files. Writing DER for individual files.\n    type_of_num_spkr = \"oracle\" if config.oracle_n_spkrs else \"est\"\n    tag = (\n        type_of_num_spkr + \"_\" + str(config.affinity) + \".\" + config.mic_type)\n\n    # perform final diarization on 'dev' and 'eval' with best hyperparams.\n    final_DERs = {}\n    out_der_dir = os.path.join(args.data_dir, config.der_dir)\n    if not os.path.exists(out_der_dir):\n        os.makedirs(out_der_dir)\n\n    for split_type in [\"dev\", \"eval\"]:\n        if split_type == \"dev\":\n            full_meta = full_meta_dev\n        else:\n            full_meta = full_meta_eval\n\n        # performing diarization.\n        msg = \"Diarizing using best hyperparams: \" + split_type + \" set\"\n        logger.info(msg)\n        out_boundaries = diarize_dataset(\n            full_meta,\n            split_type,\n            n_lambdas=n_lambdas,\n            pval=best_pval,\n            n_neighbors=best_nn,\n            save_dir=args.data_dir,\n            config=config)\n\n        # computing DER.\n        msg = \"Computing DERs for \" + split_type + \" set\"\n        logger.info(msg)\n        ref_rttm = os.path.join(args.data_dir, config.ref_rttm_dir,\n                                \"fullref_ami_\" + split_type + \".rttm\")\n        sys_rttm = out_boundaries\n        [MS, FA, SER, DER_vals] = DER(\n            ref_rttm,\n            sys_rttm,\n            config.ignore_overlap,\n            config.forgiveness_collar,\n            individual_file_scores=True, )\n\n        # writing DER values to a file. Append tag.\n        der_file_name = split_type + \"_DER_\" + tag\n        out_der_file = os.path.join(out_der_dir, der_file_name)\n        msg = \"Writing DER file to: \" + out_der_file\n        logger.info(msg)\n        diar.write_ders_file(ref_rttm, DER_vals, out_der_file)\n\n        msg = (\"AMI \" + split_type + \" set DER = %s %%\\n\" %\n               (str(round(DER_vals[-1], 2))))\n        logger.info(msg)\n        final_DERs[split_type] = round(DER_vals[-1], 2)\n\n    # final print DERs\n    msg = (\n        \"Final Diarization Error Rate (%%) on AMI corpus: Dev = %s %% | Eval = %s %%\\n\"\n        % (str(final_DERs[\"dev\"]), str(final_DERs[\"eval\"])))\n    logger.info(msg)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\n        \"--config\", default=None, type=str, help=\"configuration file\")\n    parser.add_argument(\n        \"--data-dir\",\n        default=\"../data/\",\n        type=str,\n        help=\"processsed data directory\")\n    args = parser.parse_args()\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n\n    main(args, config)\n"
  },
  {
    "path": "examples/ami/sd0/local/process.sh",
    "content": "#!/bin/bash\n\nstage=0\nset=L\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\nset -o pipefail\n\ndata_folder=$1\nmanual_annot_folder=$2\nsave_folder=$3\npretrained_model_dir=$4\nconf_path=$5\ndevice=$6\n\nref_rttm_dir=${save_folder}/ref_rttms\nmeta_data_dir=${save_folder}/metadata\n\nif [ ${stage} -le 0 ]; then\n    echo \"AMI Data preparation\"\n    python local/ami_prepare.py  --data_folder ${data_folder} \\\n            --manual_annot_folder ${manual_annot_folder} \\\n            --save_folder ${save_folder} --ref_rttm_dir ${ref_rttm_dir} \\\n            --meta_data_dir ${meta_data_dir} \n    \n    if [ $? -ne 0 ]; then\n        echo \"Prepare AMI failed. Please check log message.\"\n        exit 1\n    fi\n    echo \"AMI data preparation done.\"           \nfi\n\nif [ ${stage} -le 1 ]; then\n    # extra embddings for dev and eval dataset\n    for name in dev eval; do\n        python local/compute_embdding.py --config ${conf_path} \\\n                --data-dir ${save_folder} \\\n                --device ${device} \\\n                --dataset ${name} \\\n                --load-checkpoint ${pretrained_model_dir}\n    done\nfi\n\nif [ ${stage} -le 2 ]; then\n    # tune hyperparams on dev set\n    # perform final diarization on 'dev' and 'eval' with best hyperparams\n    python local/experiment.py --config ${conf_path} \\\n            --data-dir ${save_folder}\nfi\n"
  },
  {
    "path": "examples/ami/sd0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n# model exp\n#MODEL=ECAPA_TDNN\n#export BIN_DIR=${MAIN_ROOT}/paddlespeech/vector/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/ami/sd0/run.sh",
    "content": "#!/bin/bash\n\n. ./path.sh || exit 1;\nset -e\n\nstage=0\n\n#TARGET_DIR=${MAIN_ROOT}/dataset/ami\nTARGET_DIR=/home/dataset/AMI\ndata_folder=${TARGET_DIR}/amicorpus #e.g., /path/to/amicorpus/\nmanual_annot_folder=${TARGET_DIR}/ami_public_manual_1.6.2 #e.g., /path/to/ami_public_manual_1.6.2/\n\nsave_folder=./save\npretraind_model_dir=${save_folder}/sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_1/model\nconf_path=conf/ecapa_tdnn.yaml\ndevice=gpu\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nif [ $stage -le 1 ]; then\n    # Download the pretrained model\n    wget https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_1.tar.gz\n    mkdir -p ${save_folder} && tar -xvf sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_1.tar.gz -C ${save_folder}\n    rm -rf sv0_ecapa_tdnn_voxceleb12_ckpt_0_1_1.tar.gz\n    echo \"download the pretrained ECAPA-TDNN Model to path: \"${pretraind_model_dir}\nfi\n\nif [ $stage -le 2 ]; then\n    # Tune hyperparams on dev set and perform final diarization on dev and eval with best hyperparams.\n    echo ${data_folder} ${manual_annot_folder} ${save_folder} ${pretraind_model_dir} ${conf_path}\n    bash ./local/process.sh ${data_folder} ${manual_annot_folder} \\\n        ${save_folder} ${pretraind_model_dir} ${conf_path} ${device} || exit 1\nfi\n\n"
  },
  {
    "path": "examples/callcenter/README.md",
    "content": "# Callcenter 8k sample rate\n\nThis recipe only has model/data config for 8k ASR, user need to prepare data and generate manifest metafile. You can see Aishell or Libripseech.\n"
  },
  {
    "path": "examples/callcenter/asr1/.gitignore",
    "content": "data\nexp\n*.profile\n"
  },
  {
    "path": "examples/callcenter/asr1/RESULTS.md",
    "content": "# MandarinK8\n\n## Conformer\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |  \n| conformer | 45.73 M | conf/conformer.yaml | spec_aug + shift | test | attention | 2.1794936656951904 | 0.102304 |  \n| conformer | 45.73 M | conf/conformer.yaml | spec_aug + shift | test | ctc_greedy_search | 2.1794936656951904 | 0.084295 |  \n| conformer | 45.73 M | conf/conformer.yaml | spec_aug + shift | test | ctc_prefix_beam_search | 2.1794936656951904 | 0.084340 |  \n| conformer | 45.73 M | conf/conformer.yaml | spec_aug + shift | test | attention_rescoring | 2.1794936656951904 | 0.081675 |  \n\n\n## Chunk Conformer\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size & Left Chunks | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- |  \n| conformer | 45.73 M | conf/chunk_conformer.yaml | spec_aug + shift | test | attention | 16, -1 | 2.23287845  | 0.087982 |  \n| conformer | 45.73 M | conf/chunk_conformer.yaml | spec_aug + shift | test | ctc_greedy_search | 16, -1 | 2.23287845  | 0.086962 |  \n| conformer | 45.73 M | conf/chunk_conformer.yaml | spec_aug + shift | test | ctc_prefix_beam_search | 16, -1 | 2.23287845 | 0.086741 |  \n| conformer | 45.73 M | conf/chunk_conformer.yaml | spec_aug + shift | test | attention_rescoring | 16, -1 | 2.23287845 | 0.083495 |\n"
  },
  {
    "path": "examples/callcenter/asr1/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.9,\n      \"max_speed_rate\": 1.1,\n      \"num_rates\": 3\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"F\": 10,\n      \"T\": 50,\n      \"n_freq_masks\": 2,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"W\": 80,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": true\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/callcenter/asr1/conf/chunk_conformer.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n  \n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'char'\nspm_model_prefix: ''\npreprocess_config: conf/preprocess.yaml\nbatch_size: 32\nraw_wav: True  # use raw_wav or kaldi feature\nspectrum_type: fbank #linear, mfcc, fbank\nfeat_dim: 80\ndelta_delta: False\ndither: 1.0\ntarget_sample_rate: 8000\nmax_freq: None\nn_fft: None\nstride_ms: 10.0\nwindow_ms: 25.0\nuse_dB_normalization: True \ntarget_dB: -20\nrandom_seed: 0\nkeep_transcription_text: False\nsortagrad: True \nshuffle_method: batch_shuffle\nnum_workers: 2\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 240\naccum_grad: 4\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/callcenter/asr1/conf/conformer.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'char'\nspm_model_prefix: ''\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 100 # 50 will be lowest \naccum_grad: 4\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/callcenter/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 8000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n\n\n\n\n"
  },
  {
    "path": "examples/callcenter/asr1/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: cer \ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: true  # simulate streaming inference. Defaults to False."
  },
  {
    "path": "examples/callcenter/asr1/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: cer \ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n\n\n"
  },
  {
    "path": "examples/callcenter/asr1/local/align.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nckpt_name=$(basename ${ckpt_prefxi})\n\nmkdir -p exp\n\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/alignment.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/local/data.sh",
    "content": "#! /usr/bin/env bash\n\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nmkdir -p ${dict_dir}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    for dataset in train dev test; do\n        mv data/manifest.${dataset} data/manifest.${dataset}.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --sample_rate=8000 \\\n    --use_dB_normalization=False \\\n    --num_samples=-1 \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # download data, generate manifests\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type=\"char\" \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths \"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for dataset in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n            --cmvn_path \"data/mean_std.json\" \\\n            --unit_type \"char\" \\\n            --vocab_path=\"${dict_dir}/vocab.txt\" \\\n            --manifest_path=\"data/manifest.${dataset}.raw\" \\\n            --output_path=\"data/manifest.${dataset}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    } &\n    done\n    wait\nfi\n\necho \"data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/local/download_lm_ch.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL='https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm'\nMD5=\"29e02312deb2e59b3c8686c7966d4fe3\"\nTARGET=${DIR}/zh_giga.no_cna_cmn.prune01244.klm\n\n\necho \"Download language model ...\"\ndownload $URL $MD5 $TARGET\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/local/export.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/local/test.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\n\nckpt_name=$(basename ${ckpt_prefxi})\n\nmkdir -p exp\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nfor type in attention ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nfor type in ctc_prefix_beam_search attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/local/train.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\necho \"using ${device}...\"\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/callcenter/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/callcenter/asr1/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/conformer.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=20\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n"
  },
  {
    "path": "examples/canton/tts3/README.md",
    "content": "# FastSpeech2 with Cantonese language\n\n## Dataset\n### Download and Extract\nIf you don't have the Cantonese datasets mentioned above, please download and unzip  [Guangzhou_Cantonese_Scripted_Speech_Corpus_Daily_Use_Sentence](https://magichub.com/datasets/guangzhou-cantonese-scripted-speech-corpus-daily-use-sentence/) and [Guangzhou_Cantonese_Scripted_Speech_Corpus_in_Vehicle](https://magichub.com/datasets/guangzhou-cantonese-scripted-speech-corpus-in-the-vehicle/) under `~/datasets/`.\n\nTo obtain better performance, please combine these two datasets together as follows:\n\n```bash\nmkdir -p ~/datasets/canton_all/WAV\ncp -r ~/datasets/Guangzhou_Cantonese_Scripted_Speech_Corpus_Daily_Use_Sentence/WAV/* ~/datasets/canton_all/WAV\ncp -r ~/datasets/Guangzhou_Cantonese_Scripted_Speech_Corpus_in_Vehicle/WAV/* ~/datasets/canton_all/WAV\n```\n\nAfter that, it should be look like:\n```\n~/datasets/canton_all\n│   └── WAV\n│       └──G0001\n│       └──G0002\n│       ...\n│       └──G0071\n│       └──G0072\n```\n\n\n### Get MFA Result and Extract\nWe use [MFA1.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for canton_fastspeech2.\nYou can train your MFA model reference to [canton_mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\nWe here provide the MFA results of these two datasets. [canton_alignment.zip](https://paddlespeech.cdn.bcebos.com/MFA/Canton/canton_alignment.zip)\n\n## Get Started\nAssume the path to the Cantonese MFA result of the two datsets mentioned above is `./canton_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - `--stage` controls the vocoder model during synthesis (0 = pwgan, 1 = hifigan).\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, a path of energy features, speaker, and id of each utterance.\n\n### Training details can refer to the script of [examples/aishell3/tts3](../../aishell3/tts3).\n\n## Pretrained Model\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_canton_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_ckpt_1.4.0.zip)\n\nThe static model can be downloaded here:\n- [fastspeech2_canton_static_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_static_1.4.0.zip)\n\nThe ONNX model can be downloaded here:  \n- [fastspeech2_canton_onnx_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_onnx_1.4.0.zip)\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_canton_ckpt_1.4.0\n├── default.yaml            # default config used to train fastspeech2\n├── energy_stats.npy        # statistics used to normalize energy when training fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── pitch_stats.npy         # statistics used to normalize pitch when training fastspeech2\n├── snapshot_iter_140000.pdz # model parameters and optimizer states\n├── speaker_id_map.txt      # speaker id map file when training a multi-speaker fastspeech2\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the neural vocoder.\nDownload the pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\n\nYou can use the following scripts to synthesize for `${BIN_DIR}/../../assets/sentences_canton.txt` using pretrained fastspeech2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_aishell3 \\\n  --am_config=fastspeech2_canton_ckpt_1.4.0/default.yaml \\\n  --am_ckpt=fastspeech2_canton_ckpt_1.4.0/snapshot_iter_140000.pdz \\\n  --am_stat=fastspeech2_canton_ckpt_1.4.0/speech_stats.npy \\\n  --voc=pwgan_aishell3 \\\n  --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n  --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n  --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n  --lang=canton \\\n  --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=fastspeech2_canton_ckpt_1.4.0/phone_id_map.txt \\\n  --speaker_dict=fastspeech2_canton_ckpt_1.4.0/speaker_id_map.txt \\\n  --spk_id=10 \\\n  --inference_dir=exp/default/inference\n```\n"
  },
  {
    "path": "examples/canton/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\n# The canton datasets we use are different from others like Databaker or LJSpeech, \n# we set it to 110 to avoid too many zero-pitch problem. \n# Reference: https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder/issues/38\nf0min: 110          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 32\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam               # optimizer type\n    learning_rate: 0.001      # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/canton/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_canton \\\n        --voc=pwgan_aishell3 \\\n        --spk_id=10 \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_canton \\\n        --voc=mb_melgan_csmsc \\\n        --spk_id=10 \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_canton \\\n        --voc=hifigan_csmsc \\\n        --spk_id=10 \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton\nfi\n\n# wavernn\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_canton \\\n        --voc=wavernn_csmsc \\\n        --spk_id=10 \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton\nfi\n"
  },
  {
    "path": "examples/canton/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_canton \\\n        --voc=pwgan_aishell3 \\\n        --spk_id=10 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_canton \\\n        --voc=mb_melgan_csmsc \\\n        --spk_id=10 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_canton \\\n        --voc=hifigan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=canton \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n"
  },
  {
    "path": "examples/canton/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./canton_alignment \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=canton \\\n        --rootdir=~/datasets/canton_all \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/canton/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_canton \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_aishell3 \\\n        --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n        --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n        --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n        --lang=canton \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=10 \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_canton \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --lang=canton \\\n        --text=${BIN_DIR}/../../assets/sentences_canton.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=10 \\\n        --inference_dir=${train_output_path}/inference\n    fi\n"
  },
  {
    "path": "examples/canton/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\n\nckpt_name=snapshot_iter_140000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# we have only tested the following models so far\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ../../csmsc/tts3/local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_canton\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_csmsc\n    ../../csmsc/tts3/local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_aishell3 \n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\n    \nfi\n\n# inference with onnxruntime\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n"
  },
  {
    "path": "examples/csmsc/README.md",
    "content": "\n# CSMSC\n\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* tts3_rhy - Using prosody labels in FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n* voc4 - Style MelGAN\n* voc5 - HiFiGAN\n* voc6 - WaveRNN\n"
  },
  {
    "path": "examples/csmsc/jets/README.md",
    "content": "# JETS with CSMSC\nThis example contains code used to train a [JETS](https://arxiv.org/abs/2203.16852v1) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\nThe structure of the folder is listed below.\n\n```text\n└─ Wave\n    └─ .wav files (audio speech)\n└─ PhoneLabeling\n    └─ .interval files (alignment between phoneme and duration)\n└─ ProsodyLabeling\n   └─ 000001-010000.txt (text with prosodic by pinyin)\n```\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes and durations for JETS.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── feats_stats.npy\n    ├── norm\n    └── raw\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains wave、mel spectrogram、speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, the path of feats, feats_lengths, the path of pitch features, the path of energy features, the path of raw waves, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n\nTrain a JETS model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       config file to overwrite default config.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\n\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n\n## Pretrained Model\n\nThe pretrained model can be downloaded here:\n\n- [jets_csmsc_ckpt_1.5.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/jets_csmsc_ckpt_1.5.0.zip)\n\nThe static model can be downloaded here:\n\n- [jets_csmsc_static_1.5.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/jets_csmsc_static_1.5.0.zip)\n"
  },
  {
    "path": "examples/csmsc/jets/conf/default.yaml",
    "content": "# This configuration tested on 4 GPUs (V100) with 32GB GPU\n# memory. It takes around 2 weeks to finish the training\n# but 100k iters model should generate reasonable results.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nn_mels: 80\nfs: 22050         # sr\nn_fft: 1024        # FFT size (samples).\nn_shift: 256       # Hop size (samples). 12.5ms\nwin_length: null   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\nfmin: 0            # minimum frequency for Mel basis\nfmax: null         # maximum frequency for Mel basis\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n##########################################################\n#                  TTS MODEL SETTING                     #\n##########################################################\nmodel:\n    # generator related\n    generator_type: jets_generator\n    generator_params:\n        adim: 256         # attention dimension\n        aheads: 2         # number of attention heads\n        elayers: 4        # number of encoder layers\n        eunits: 1024      # number of encoder ff units\n        dlayers: 4        # number of decoder layers\n        dunits: 1024      # number of decoder ff units\n        positionwise_layer_type: conv1d   # type of position-wise layer\n        positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n        duration_predictor_layers: 2      # number of layers of duration predictor\n        duration_predictor_chans: 256     # number of channels of duration predictor\n        duration_predictor_kernel_size: 3 # filter size of duration predictor\n        use_masking: True                 # whether to apply masking for padded part in loss calculation\n        encoder_normalize_before: True    # whether to perform layer normalization before the input\n        decoder_normalize_before: True    # whether to perform layer normalization before the input\n        encoder_type: transformer           # encoder type\n        decoder_type: transformer           # decoder type\n        conformer_rel_pos_type: latest               # relative positional encoding type\n        conformer_pos_enc_layer_type: rel_pos        # conformer positional encoding type\n        conformer_self_attn_layer_type: rel_selfattn # conformer self-attention type\n        conformer_activation_type: swish             # conformer activation type\n        use_macaron_style_in_conformer: true         # whether to use macaron style in conformer\n        use_cnn_in_conformer: true                   # whether to use CNN in conformer\n        conformer_enc_kernel_size: 7                 # kernel size in CNN module of conformer-based encoder\n        conformer_dec_kernel_size: 31                # kernel size in CNN module of conformer-based decoder\n        init_type: xavier_uniform                    # initialization type\n        init_enc_alpha: 1.0                          # initial value of alpha for encoder\n        init_dec_alpha: 1.0                          # initial value of alpha for decoder\n        transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n        transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n        transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n        transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n        transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n        transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n        pitch_predictor_layers: 5                    # number of conv layers in pitch predictor\n        pitch_predictor_chans: 256                   # number of channels of conv layers in pitch predictor\n        pitch_predictor_kernel_size: 5               # kernel size of conv layers in pitch predictor\n        pitch_predictor_dropout: 0.5                 # dropout rate in pitch predictor\n        pitch_embed_kernel_size: 1                   # kernel size of conv embedding layer for pitch\n        pitch_embed_dropout: 0.0                     # dropout rate after conv embedding layer for pitch\n        stop_gradient_from_pitch_predictor: true     # whether to stop the gradient from pitch predictor to encoder\n        energy_predictor_layers: 2                   # number of conv layers in energy predictor\n        energy_predictor_chans: 256                  # number of channels of conv layers in energy predictor\n        energy_predictor_kernel_size: 3              # kernel size of conv layers in energy predictor\n        energy_predictor_dropout: 0.5                # dropout rate in energy predictor\n        energy_embed_kernel_size: 1                  # kernel size of conv embedding layer for energy\n        energy_embed_dropout: 0.0                    # dropout rate after conv embedding layer for energy\n        stop_gradient_from_energy_predictor: false   # whether to stop the gradient from energy predictor to encoder\n        generator_out_channels: 1\n        generator_channels: 512\n        generator_global_channels: -1\n        generator_kernel_size: 7\n        generator_upsample_scales: [8, 8, 2, 2]\n        generator_upsample_kernel_sizes: [16, 16, 4, 4]\n        generator_resblock_kernel_sizes: [3, 7, 11]\n        generator_resblock_dilations: [[1, 3, 5], [1, 3, 5], [1, 3, 5]]\n        generator_use_additional_convs: true\n        generator_bias: true\n        generator_nonlinear_activation: \"leakyrelu\"\n        generator_nonlinear_activation_params:\n            negative_slope: 0.1\n        generator_use_weight_norm: true\n        segment_size: 64              # segment size for random windowed discriminator\n\n    # discriminator related\n    discriminator_type: hifigan_multi_scale_multi_period_discriminator\n    discriminator_params:\n        scales: 1\n        scale_downsample_pooling: \"AvgPool1D\"\n        scale_downsample_pooling_params:\n            kernel_size: 4\n            stride: 2\n            padding: 2\n        scale_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [15, 41, 5, 3]\n            channels: 128\n            max_downsample_channels: 1024\n            max_groups: 16\n            bias: True\n            downsample_scales: [2, 2, 4, 4, 1]\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n        follow_official_norm: False\n        periods: [2, 3, 5, 7, 11]\n        period_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [5, 3]\n            channels: 32\n            downsample_scales: [3, 3, 3, 3, 1]\n            max_downsample_channels: 1024\n            bias: True\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n    # others\n    sampling_rate: 22050          # needed in the inference for saving wav\n    cache_generator_outputs: True # whether to cache generator outputs in the training\nuse_alignment_module: False       # whether to use alignment module\n      \n###########################################################\n#                        LOSS SETTING                     #\n###########################################################\n# loss function related\ngenerator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\nfeat_match_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    average_by_layers: False         # whether to average loss value by #layers of each discriminator\n    include_final_outputs: True      # whether to include final outputs for loss calculation\nmel_loss_params:\n    fs: 22050          # must be the same as the training data\n    fft_size: 1024        # fft points\n    hop_size: 256    # hop size\n    win_length: null   # window length\n    window: hann       # window type\n    num_mels: 80         # number of Mel basis\n    fmin: 0            # minimum frequency for Mel basis\n    fmax: null         # maximum frequency for Mel basis\n    log_base: null     # null represent natural log\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 1.0        # loss scaling coefficient for adversarial loss\nlambda_mel: 45.0       # loss scaling coefficient for Mel loss\nlambda_feat_match: 2.0 # loss scaling coefficient for feat match loss\nlambda_var: 1.0        # loss scaling coefficient for duration loss\nlambda_align: 2.0         # loss scaling coefficient for KL divergence loss\n# others\nsampling_rate: 22050          # needed in the inference for saving wav\ncache_generator_outputs: True # whether to cache generator outputs in the training\n\n\n# extra module for additional inputs\npitch_extract: dio           # pitch extractor type\npitch_extract_conf:\n    reduction_factor: 1\n    use_token_averaged_f0: false\npitch_normalize: global_mvn  # normalizer for the pitch feature\nenergy_extract: energy       # energy extractor type\nenergy_extract_conf:\n    reduction_factor: 1\n    use_token_averaged_energy: false\nenergy_normalize: global_mvn # normalizer for the energy feature\n\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 32              # Batch size.\nnum_workers: 4              # Number of workers in DataLoader.\n\n##########################################################\n#            OPTIMIZER & SCHEDULER SETTING               #\n##########################################################\n# optimizer setting for generator\ngenerator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ngenerator_scheduler: exponential_decay\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4\n    gamma: 0.999875                   \n\n# optimizer setting for discriminator\ndiscriminator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ndiscriminator_scheduler: exponential_decay\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4          \n    gamma: 0.999875\ngenerator_first: True # whether to start updating generator first\n\n##########################################################\n#                OTHER TRAINING SETTING                  #\n##########################################################\nnum_snapshots: 10            # max number of snapshots to keep while training\ntrain_max_steps: 350000      # Number of training steps. == total_iters / ngpus, total_iters = 1000000\nsave_interval_steps: 1000    # Interval steps to save checkpoint.\neval_interval_steps: 250     # Interval steps to evaluate the network.\nseed: 777                    # random seed number\n"
  },
  {
    "path": "examples/csmsc/jets/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=jets_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/jets/local/preprocess.sh",
    "content": "#!/bin/bash\nset -e\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --token_average=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\n\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/jets/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test\nfi\n"
  },
  {
    "path": "examples/csmsc/jets/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --am=jets_csmsc \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --inference_dir=${train_output_path}/inference\nfi\n"
  },
  {
    "path": "examples/csmsc/jets/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/csmsc/jets/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=jets\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/csmsc/jets/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_150000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path}|| exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n"
  },
  {
    "path": "examples/csmsc/tts0/README.md",
    "content": "# Tacotron2 with CSMSC\nThis example contains code used to train a [Tacotron2](https://arxiv.org/abs/1712.05884) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [Official Website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for Tacotron2, the durations of MFA are not needed here.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n\nTrain a Tacotron2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       tacotron2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip) and unzip it.\n```bash\nunzip pwg_baker_ckpt_0.4.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml               # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz   # model parameters of parallel wavegan\n└── pwg_stats.npy                  # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0-4` to select the vocoder in {`pwgan`, `multi band melgan`, `style melgan`, ` hifigan`, `wavernn`}\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0,1,3,4` to select the vocoder in {`pwgan`, `multi band melgan`, `hifigan`, `wavernn`}\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the Tacotron2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n\n## Pretrained Model\nPretrained Tacotron2 model with no silence in the edge of audios:\n- [tacotron2_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_csmsc_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [tacotron2_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_csmsc_static_0.2.0.zip)\n\n\nModel | Step | eval/loss | eval/l1_loss | eval/mse_loss | eval/bce_loss| eval/attn_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 1(gpu) x 30600|0.57185|0.39614|0.14642|0.029|5.8e-05|\n\nTacotron2 checkpoint contains files listed below.\n```text\ntacotron2_csmsc_ckpt_0.2.0\n├── default.yaml            # default config used to train Tacotron2\n├── phone_id_map.txt        # phone vocabulary file when training Tacotron2\n├── snapshot_iter_30600.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training Tacotron2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../../assets/sentences.txt` using pretrained Tacotron2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=tacotron2_csmsc \\\n  --am_config=tacotron2_csmsc_ckpt_0.2.0/default.yaml \\\n  --am_ckpt=tacotron2_csmsc_ckpt_0.2.0/snapshot_iter_30600.pdz \\\n  --am_stat=tacotron2_csmsc_ckpt_0.2.0/speech_stats.npy  \\\n  --voc=pwgan_csmsc \\\n  --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n  --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n  --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n  --lang=zh \\\n  --text=${BIN_DIR}/../../assets/sentences.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference \\\n  --phones_dict=tacotron2_csmsc_ckpt_0.2.0/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/csmsc/tts0/conf/default.yaml",
    "content": "# This configuration is for Paddle to train Tacotron 2. Compared to the\n# original paper, this configuration additionally use the guided attention\n# loss to accelerate the learning of the diagonal attention. It requires\n# only a single GPU with 12 GB memory and it takes ~1 days to finish the\n# training on Titan V.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:                          # keyword arguments for the selected model\n    embed_dim: 512               # char or phn embedding dimension\n    elayers: 1                   # number of blstm layers in encoder\n    eunits: 512                  # number of blstm units\n    econv_layers: 3              # number of convolutional layers in encoder\n    econv_chans: 512             # number of channels in convolutional layer\n    econv_filts: 5               # filter size of convolutional layer\n    atype: location              # attention function type\n    adim: 512                    # attention dimension\n    aconv_chans: 32              # number of channels in convolutional layer of attention\n    aconv_filts: 15              # filter size of convolutional layer of attention\n    cumulate_att_w: True         # whether to cumulate attention weight\n    dlayers: 2                   # number of lstm layers in decoder\n    dunits: 1024                 # number of lstm units in decoder\n    prenet_layers: 2             # number of layers in prenet\n    prenet_units: 256            # number of units in prenet\n    postnet_layers: 5            # number of layers in postnet\n    postnet_chans: 512           # number of channels in postnet\n    postnet_filts: 5             # filter size of postnet layer\n    output_activation: null      # activation function for the final output\n    use_batch_norm: True         # whether to use batch normalization in encoder\n    use_concate: True            # whether to concatenate encoder embedding with decoder outputs\n    use_residual: False          # whether to use residual connection in encoder\n    dropout_rate: 0.5            # dropout rate\n    zoneout_rate: 0.1            # zoneout rate\n    reduction_factor: 1          # reduction factor\n    spk_embed_dim: null          # speaker embedding dimension\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True            # whether to apply masking for padded part in loss calculation\n    bce_pos_weight: 5.0          # weight of positive sample in binary cross entropy calculation\n    use_guided_attn_loss: True   # whether to use guided attention loss\n    guided_attn_loss_sigma: 0.4  # sigma of guided attention loss\n    guided_attn_loss_lambda: 1.0 # strength of guided attention loss\n\n\n##########################################################\n#                  OPTIMIZER SETTING                     #\n##########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 1.0e-03   # learning rate\n    epsilon: 1.0e-06         # epsilon\n    weight_decay: 0.0        # weight decay coefficient\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 42"
  },
  {
    "path": "examples/csmsc/tts0/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=tacotron2_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=tacotron2_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=tacotron2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi"
  },
  {
    "path": "examples/csmsc/tts0/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts0/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts0/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# TODO: tacotron2 动转静的结果没有动态图的响亮, 可能还是 decode 的时候某个函数动静不对齐\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\n        \nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=tacotron2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts0/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --phones-dict=dump/phone_id_map.txt"
  },
  {
    "path": "examples/csmsc/tts0/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=tacotron2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/csmsc/tts0/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0\n    # use 1-4 to select the vocoder in {multi band melgan, style melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0\n    # use 1,3,4 to select the vocoder in {multi band melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/README.md",
    "content": "# SpeedySpeech with CSMSC\nThis example contains code used to train a [SpeedySpeech](http://arxiv.org/abs/2008.03802) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html). NOTE that we only implement the student part of the Speedyspeech model. The ground truth alignment used to train the model is extracted from the dataset using [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [Official Website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\nThe structure of the folder is listed below.\n\n```text\n└─ Wave\n    └─ .wav files (audio speech)\n└─ PhoneLabeling\n    └─ .interval files (alignment between phoneme and duration)\n└─ ProsodyLabeling\n   └─ 000001-010000.txt (text with prosodic by pinyin)\n```\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for SPEEDYSPEECH.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to  [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n5. inference using the static model.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, run the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, tones, durations, the path of the spectrogram, and the id of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\n```\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--use-relative-path USE_RELATIVE_PATH]\n                [--phones-dict PHONES_DICT] [--tones-dict TONES_DICT]\n\nTrain a Speedyspeech model with a single speaker dataset.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --use-relative-path USE_RELATIVE_PATH\n                        whether use relative path in metadata\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --tones-dict TONES_DICT\n                        tone vocabulary file.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n6. `--tones-dict` is the path of the tone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip) and unzip it.\n```bash\nunzip pwg_baker_ckpt_0.4.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml               # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz   # model parameters of parallel wavegan\n└── pwg_stats.npy                  # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0-4` to select the vocoder in {`pwgan`, `multi band melgan`, `style melgan`, `hifigan`, `wavernn`}\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0,1,3,4` to select the vocoder in {`pwgan`, `multi band melgan`, `hifigan`, `wavernn`}\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat`, `--phones_dict` and `--tones_dict` are arguments for acoustic model, which correspond to the 5 files in the speedyspeech pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Inferencing\nAfter synthesizing, we will get static models of speedyspeech and pwgan in `${train_output_path}/inference`.\n`./local/inference.sh` calls `${BIN_DIR}/inference.py`, which provides a paddle static model inference example for speedyspeech + pwgan synthesize.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path}\n```\n\n## Pretrained Model\nPretrained SpeedySpeech model with no silence in the edge of audios:\n- [speedyspeech_nosil_baker_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_nosil_baker_ckpt_0.5.zip)\n- [speedyspeech_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [speedyspeech_nosil_baker_static_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_nosil_baker_static_0.5.zip)\n- [speedyspeech_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_static_0.2.0.zip)\n\nThe ONNX model can be downloaded here:\n- [speedyspeech_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_onnx_0.2.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [speedyspeech_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_pdlite_1.3.0.zip)\n\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/ssim_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:|:--------:\ndefault| 1(gpu) x 11400|0.79532|0.400246|0.030259| 0.36482\n\nSpeedySpeech checkpoint contains files listed below.\n\n```text\nspeedyspeech_csmsc_ckpt_0.2.0\n├── default.yaml            # default config used to train speedyspeech\n├── feats_stats.npy         # statistics used to normalize spectrogram when training speedyspeech\n├── phone_id_map.txt        # phone vocabulary file when training speedyspeech\n├── snapshot_iter_30600.pdz # model parameters and optimizer states\n└── tone_id_map.txt         # tone vocabulary file when training speedyspeech\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../../assets/sentences.txt` using pretrained speedyspeech and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=speedyspeech_csmsc \\\n  --am_config=speedyspeech_csmsc_ckpt_0.2.0/default.yaml \\\n  --am_ckpt=speedyspeech_csmsc_ckpt_0.2.0/snapshot_iter_30600.pdz \\\n  --am_stat=speedyspeech_csmsc_ckpt_0.2.0/feats_stats.npy \\\n  --voc=pwgan_csmsc \\\n  --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n  --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n  --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n  --lang=zh \\\n  --text=${BIN_DIR}/../../assets/sentences.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference \\\n  --phones_dict=speedyspeech_csmsc_ckpt_0.2.0/phone_id_map.txt \\\n  --tones_dict=speedyspeech_csmsc_ckpt_0.2.0/tone_id_map.txt\n```\n"
  },
  {
    "path": "examples/csmsc/tts2/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000           # Sampling rate.\nn_fft: 2048         # FFT size (samples).\nn_shift: 300        # Hop size (samples). 12.5ms\nwin_length: 1200    # Window length (samples). 50ms\n                    # If set to null, it will be the same as fft_size.\nwindow: \"hann\"      # Window function.\nn_mels: 80          # Number of mel basis.\nfmin: 80            # Minimum freq in mel basis calculation.\nfmax: 7600          # Maximum frequency in mel basis calculation.\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 4\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    encoder_hidden_size: 128\n    encoder_kernel_size: 3\n    encoder_dilations: [1, 3, 9, 27, 1, 3, 9, 27, 1, 1]\n    duration_predictor_hidden_size: 128\n    decoder_hidden_size: 128\n    decoder_output_size: 80\n    decoder_kernel_size: 3\n    decoder_dilations: [1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 1]\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 0.002     # learning rate\n    max_grad_norm: 1\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086"
  },
  {
    "path": "examples/csmsc/tts2/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/inference_mlu.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device mlu\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device mlu\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/inference_npu.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device npu\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device npu\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device npu\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/inference_xpu.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device xpu\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device xpu\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device xpu\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=speedyspeech_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=speedyspeech_csmsc \\\n        --voc=pwgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=speedyspeech_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\n# synthesize from metadata\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    python3 ${BIN_DIR}/../ort_predict.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=speedyspeech_csmsc \\\n        --voc=hifigan_csmsc \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/onnx_infer_out \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/preprocess.sh",
    "content": "#!/bin/bash\n\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --use-relative-path=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\" \\\n        --use-relative-path=True\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/tone to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --tones-dict=dump/tone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --use-relative-path=True\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --tones-dict=dump/tone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --use-relative-path=True\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --tones-dict=dump/tone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --use-relative-path=True\n\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_e2e_mlu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n\n# wavernn\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_e2e_npu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nnpu=1\n\n\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_e2e_xpu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_mlu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n\n# style melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n\n# wavernn\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nmlu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_npu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nnpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/synthesize_xpu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=speedyspeech_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/feats_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --tones_dict=dump/tone_id_map.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/local/train.sh",
    "content": "\n#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --tones-dict=dump/tone_id_map.txt \\\n    --use-relative-path=True\n"
  },
  {
    "path": "examples/csmsc/tts2/local/train_mlu.sh",
    "content": "\n#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n# export MLU_VISIBLE_DEVICES=8\npython ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=0 \\\n    --nmlu=2 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --tones-dict=dump/tone_id_map.txt \\\n    --use-relative-path=True\n"
  },
  {
    "path": "examples/csmsc/tts2/local/train_npu.sh",
    "content": "\n#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=0 \\\n    --nnpu=1 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --tones-dict=dump/tone_id_map.txt \\\n    --use-relative-path=True\n"
  },
  {
    "path": "examples/csmsc/tts2/local/train_xpu.sh",
    "content": "\n#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=0 \\\n    --nxpu=1 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --tones-dict=dump/tone_id_map.txt \\\n    --use-relative-path=True\n"
  },
  {
    "path": "examples/csmsc/tts2/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=speedyspeech\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/csmsc/tts2/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_76.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0\n    # use 1-4 to select the vocoder to use {multi band melgan, style melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0\n    # use 1,3,4 to select the vocoder to use {multi band melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# we have only tested the following models so far\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx speedyspeech_csmsc\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\nfi\n\n# inference with onnxruntime\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite speedyspeech_csmsc x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite mb_melgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_csmsc x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 9 ] && [ ${stop_stage} -ge 9 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} speedyspeech_csmsc || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/run_mlu.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\nexport CUSTOM_DEVICE_BLACK_LIST=elementwise_max\nmlus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_30600.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    FLAGS_selected_mlus=${mlus} ./local/train_mlu.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    FLAGS_selected_mlus=${mlus} ./local/synthesize_mlu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    FLAGS_selected_mlus=${mlus} ./local/synthesize_e2e_mlu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model\n    FLAGS_selected_mlus=${mlus} ./local/inference_mlu.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# we have only tested the following models so far\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx speedyspeech_csmsc\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\nfi\n\n# inference with onnxruntime\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite speedyspeech_csmsc x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite mb_melgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_csmsc x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 9 ] && [ ${stop_stage} -ge 9 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} speedyspeech_csmsc || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/run_npu.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\nnpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_76.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run_xpu.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    FLAGS_selected_npus=${npus} ./local/train_npu.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    FLAGS_selected_npus=${npus} ./local/synthesize_npu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    FLAGS_selected_npus=${npus} ./local/synthesize_e2e_npu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model\n    FLAGS_selected_npus=${npus} ./local/inference_npu.sh ${train_output_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts2/run_xpu.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\nxpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_76.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run_xpu.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    FLAGS_selected_xpus=${xpus} ./local/train_xpu.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    FLAGS_selected_xpus=${xpus} ./local/synthesize_xpu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    FLAGS_selected_xpus=${xpus} ./local/synthesize_e2e_xpu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model\n    FLAGS_selected_xpus=${xpus} ./local/inference_xpu.sh ${train_output_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# FastSpeech2 with CSMSC\nThis example contains code used to train a [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [Official Website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for fastspeech2.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n5. inference using the static model.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip) and unzip it.\n```bash\nunzip pwg_baker_ckpt_0.4.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml               # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz   # model parameters of parallel wavegan\n└── pwg_stats.npy                  # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0-4` to select the vocoder in {`pwgan`, `multi band melgan`, `style melgan`, `hifigan`, `wavernn`}\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can use `0,1,3,4` to select the vocoder in {`pwgan`, `multi band melgan`, `hifigan`, `wavernn`}\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Inferencing\nAfter synthesizing, we will get static models of fastspeech2 and pwgan in `${train_output_path}/inference`.\n`./local/inference.sh` calls `${BIN_DIR}/inference.py`, which provides a paddle static model inference example for fastspeech2 + pwgan synthesize.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path}\n```\n\n## Pretrained Model\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)\n- [fastspeech2_conformer_baker_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip)\n- [fastspeech2_cnndecoder_csmsc_ckpt_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_ckpt_1.0.0.zip)\n\nThe static model can be downloaded here:\n- [fastspeech2_nosil_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip)\n- [fastspeech2_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_static_0.2.0.zip)\n- [fastspeech2_cnndecoder_csmsc_static_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_static_1.0.0.zip)\n- [fastspeech2_cnndecoder_csmsc_streaming_static_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_static_1.0.0.zip)\n\nThe ONNX model can be downloaded here:\n- [fastspeech2_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip)\n- [fastspeech2_cnndecoder_csmsc_onnx_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_onnx_1.0.0.zip)\n- [fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n> please compile develop version of Paddle-Lite to export and run TTS models, cause TTS models are supported by https://github.com/PaddlePaddle/Paddle-Lite/pull/9587 and https://github.com/PaddlePaddle/Paddle-Lite/pull/9706\n- [fastspeech2_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_pdlite_1.3.0.zip)\n- [fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_pdlite_1.3.0.zip)\n- [fastspeech2_cnndecoder_csmsc_streaming_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_pdlite_1.3.0.zip)\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/pitch_loss| eval/energy_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 2(gpu) x 76000|1.0991|0.59132|0.035815|0.31915|0.15287|\nconformer| 2(gpu) x 76000|1.0675|0.56103|0.035869|0.31553|0.15509|\ncnndecoder| 1(gpu) x 153000|1.1153|0.61475|0.03380|0.30414|0.14707|\n\nFastSpeech2 checkpoint contains files listed below.\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../../assets/sentences.txt` using pretrained fastspeech2 and parallel wavegan models.\n\nIf you want to use fastspeech2_conformer, you must delete this line `--inference_dir=exp/default/inference \\` to skip the step of dygraph to static graph, cause we haven't tested dygraph to static graph for fastspeech2_conformer till now.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_csmsc \\\n  --am_config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n  --am_ckpt=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n  --am_stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy  \\\n  --voc=pwgan_csmsc \\\n  --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n  --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n  --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n  --lang=zh \\\n  --text=${BIN_DIR}/../../assets/sentences.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference \\\n  --phones_dict=fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/csmsc/tts3/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n# 用 CSMSC 数据集训练 FastSpeech2 模型\n\n本用例包含用于训练 [Fastspeech2](https://arxiv.org/abs/2006.04558) 模型的代码，使用 [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html) 数据集。\n\n## 数据集\n### 下载并解压\n从 [官方网站](https://test.data-baker.com/data/index/TNtts/) 下载数据集\n\n### 获取MFA结果并解压\n我们使用 [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) 去获得 fastspeech2 的音素持续时间。\n你们可以从这里下载 [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), 或参考 [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) 训练你自己的模型。\n\n## 开始\n假设数据集的路径是 `~/datasets/BZNSYP`.\n假设CSMSC的MFA结果路径为 `./baker_alignment_tone`.\n运行下面的命令会进行如下操作：\n\n1. **设置原路径**。\n2. 对数据集进行预处理。\n3. 训练模型\n4. 合成波形\n    - 从 `metadata.jsonl` 合成波形。\n    - 从文本文件合成波形。\n5. 使用静态模型进行推理。\n```bash\n./run.sh\n```\n您可以选择要运行的一系列阶段，或者将 `stage` 设置为 `stop-stage` 以仅使用一个阶段，例如，运行以下命令只会预处理数据集。\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### 数据预处理\n```bash\n./local/preprocess.sh ${conf_path}\n```\n当它完成时。将在当前目录中创建 `dump` 文件夹。转储文件夹的结构如下所示。\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\n\n数据集分为三个部分，即 `train` 、 `dev` 和 `test` ，每个部分都包含一个 `norm` 和 `raw` 子文件夹。原始文件夹包含每个话语的语音、音调和能量特征，而 `norm` 文件夹包含规范化的特征。用于规范化特征的统计数据是从 `dump/train/*_stats.npy` 中的训练集计算出来的。\n\n此外，还有一个 `metadata.jsonl` 在每个子文件夹中。它是一个类似表格的文件，包含音素、文本长度、语音长度、持续时间、语音特征路径、音调特征路径、能量特征路径、说话人和每个话语的 id。\n\n### 模型训练\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` 调用 `${BIN_DIR}/train.py` 。\n以下是完整的帮助信息。\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` 是一个 yaml 格式的配置文件，用于覆盖默认配置，位于 `conf/default.yaml`.\n2. `--train-metadata` 和 `--dev-metadata` 应为 `dump` 文件夹中 `train` 和 `dev` 下的规范化元数据文件\n3. `--output-dir` 是保存结果的目录。 检查点保存在此目录中的 `checkpoints/` 目录下。\n4. `--ngpu` 要使用的 GPU 数，如果 ngpu==0，则使用 cpu 。\n5. `--phones-dict` 是音素词汇表文件的路径。\n\n### 合成\n我们使用 [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1) 作为神经声码器（vocoder）。\n从 [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip) 下载预训练的 parallel wavegan 模型并将其解压。\n\n```bash\nunzip pwg_baker_ckpt_0.4.zip\n```\nParallel WaveGAN 检查点包含如下文件。\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml               # 用于训练 parallel wavegan 的默认配置\n├── pwg_snapshot_iter_400000.pdz   # parallel wavegan 的模型参数\n└── pwg_stats.npy                  # 训练平行波形时用于规范化谱图的统计数据\n```\n`./local/synthesize.sh` 调用 `${BIN_DIR}/../synthesize.py` 即可从 `metadata.jsonl`中合成波形。\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\n最后一位参数 `0` 用于控制合成过程中使用的声码器模型。该参数的取值范围为 `0-4`，分别对应以下五种声码器模型：`pwgan`、`multi band melgan`、`style melgan`、`hifigan` 和 `wavernn`。\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` 调用 `${BIN_DIR}/../synthesize_e2e.py`，即可从文本文件中合成波形。\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\n最后一位参数 `0` 用于控制合成过程中使用的声码器模型。该参数的取值范围为 {`0,1,3,4`}，分别对应以下四种声码器模型：`pwgan`、`multi band melgan`、`hifigan` 和 `wavernn`。\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` 声学模型格式是否符合 {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` 和 `--phones_dict` 是声学模型的参数，对应于 fastspeech2 预训练模型中的 4 个文件。\n3. `--voc` 声码器(vocoder)格式是否符合 {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` 是声码器的参数，对应于 parallel wavegan 预训练模型中的 3 个文件。\n5. `--lang` 对应模型的语言可以是 `zh` 或 `en` 。\n6. `--test_metadata` 应为 `dump` 文件夹中 `test` 下的规范化元数据文件、\n7. `--text` 是文本文件，其中包含要合成的句子。\n8. `--output_dir` 是保存合成音频文件的目录。\n9. `--ngpu` 要使用的GPU数，如果 ngpu==0，则使用 cpu 。\n\n### 推理\n在合成之后，我们将在 `${train_output_path}/inference` 中得到 fastspeech2 和 pwgan 的静态模型\n`./local/inference.sh` 调用 `${BIN_DIR}/inference.py` 为 fastspeech2 + pwgan 综合提供了一个 paddle 静态模型推理示例。\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path}\n```\n\n## 预训练模型\n预先训练的 FastSpeech2 模型，在音频边缘没有空白音频：\n- [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)\n- [fastspeech2_conformer_baker_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip)\n\n静态模型可以在这里下载 [fastspeech2_nosil_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip).\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/pitch_loss| eval/energy_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 2(gpu) x 76000|1.0991|0.59132|0.035815|0.31915|0.15287|\nconformer| 2(gpu) x 76000|1.0675|0.56103|0.035869|0.31553|0.15509|\n\nFastSpeech2检查点包含下列文件。\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # 用于训练 fastspeech2 的默认配置\n├── phone_id_map.txt        # 训练 fastspeech2 时的音素词汇文件\n├── snapshot_iter_76000.pdz # 模型参数和优化器状态\n└── speech_stats.npy        # 训练 fastspeech2 时用于规范化频谱图的统计数据\n```\n您可以使用以下脚本通过使用预训练的 fastspeech2 和 parallel wavegan 模型为 `${BIN_DIR}/../../assets/sentences.txt` 合成句子\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_csmsc \\\n  --am_config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n  --am_ckpt=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n  --am_stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy  \\\n  --voc=pwgan_csmsc \\\n  --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n  --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n  --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n  --lang=zh \\\n  --text=${BIN_DIR}/../../assets/sentences.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference \\\n  --phones_dict=fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/csmsc/tts3/conf/cnndecoder.yaml",
    "content": "# use CNND\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 4\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    encoder_type: transformer           # encoder type\n    decoder_type: cnndecoder           # decoder type\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    cnn_dec_dropout_rate: 0.2                    # dropout rate for cnn decoder layer\n    cnn_postnet_dropout_rate: 0.2\n    cnn_postnet_resblock_kernel_sizes: [256, 256] # kernel sizes for residual block of cnn_postnet\n    cnn_postnet_kernel_size: 5                   # kernel size of cnn_postnet\n    cnn_decoder_embedding_dim: 256\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n  optim: adam              # optimizer type\n  learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/csmsc/tts3/conf/conformer.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 4\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    encoder_type: conformer           # encoder type\n    decoder_type: conformer           # decoder type\n    conformer_pos_enc_layer_type: rel_pos        # conformer positional encoding type\n    conformer_self_attn_layer_type: rel_selfattn # conformer self-attention type\n    conformer_activation_type: swish             # conformer activation type\n    use_macaron_style_in_conformer: True         # whether to use macaron style in conformer\n    use_cnn_in_conformer: True                   # whether to use CNN in conformer\n    conformer_enc_kernel_size: 7                 # kernel size in CNN module of conformer-based encoder\n    conformer_dec_kernel_size: 31                # kernel size in CNN module of conformer-based decoder\n    init_type: xavier_uniform         # initialization type\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n  optim: adam              # optimizer type\n  learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/csmsc/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 4\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/csmsc/tts3/local/PTQ_dynamic.sh",
    "content": "train_output_path=$1\nmodel_name=$2\nweight_bits=$3\n\npython3 ${BIN_DIR}/../PTQ_dynamic.py \\\n    --inference_dir ${train_output_path}/inference \\\n    --model_name ${model_name} \\\n    --weight_bits ${weight_bits}"
  },
  {
    "path": "examples/csmsc/tts3/local/PTQ_static.sh",
    "content": "train_output_path=$1\nmodel_name=$2\n\npython3 ${BIN_DIR}/../PTQ_static.py \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --inference_dir ${train_output_path}/inference \\\n    --model_name ${model_name} \\\n    --onnx_format=True"
  },
  {
    "path": "examples/csmsc/tts3/local/export2lite.sh",
    "content": "train_output_path=$1\nmodel_dir=$2\noutput_dir=$3\nmodel=$4\nvalid_targets=$5\n\nmodel_name=${model%_*}\necho model_name: ${model_name}\n\nsuffix=${valid_targets%,*}\n\nmkdir -p ${train_output_path}/${output_dir}\n\npaddle_lite_opt \\\n    --model_file ${train_output_path}/${model_dir}/${model}.pdmodel \\\n    --param_file  ${train_output_path}/${model_dir}/${model}.pdiparams \\\n    --optimize_out ${train_output_path}/${output_dir}/${model}_${suffix} \\\n    --valid_targets ${valid_targets}\n"
  },
  {
    "path": "examples/csmsc/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# wavernn\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=wavernn_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi"
  },
  {
    "path": "examples/csmsc/tts3/local/inference_streaming.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference_streaming.py \\\n        --inference_dir=${train_output_path}/inference_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference_streaming.py \\\n        --inference_dir=${train_output_path}/inference_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference_streaming.py \\\n        --inference_dir=${train_output_path}/inference_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n"
  },
  {
    "path": "examples/csmsc/tts3/local/inference_xpu.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device xpu\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device xpu\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device xpu\nfi\n\n# wavernn\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_csmsc \\\n        --voc=wavernn_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device xpu\nfi"
  },
  {
    "path": "examples/csmsc/tts3/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_csmsc \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/lite_predict_streaming.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict_streaming.py \\\n        --inference_dir=${train_output_path}/pdlite_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict_streaming.py \\\n        --inference_dir=${train_output_path}/pdlite_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n# hifigan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../lite_predict_streaming.py \\\n        --inference_dir=${train_output_path}/pdlite_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n"
  },
  {
    "path": "examples/csmsc/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_csmsc \\\n        --voc=pwgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_csmsc \\\n        --voc=mb_melgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2\nfi\n\n# synthesize from metadata, take hifigan as an example\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    python3 ${BIN_DIR}/../ort_predict.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_csmsc \\\n        --voc=hifigan_csmsc \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/onnx_infer_out \\\n        --device=cpu \\\n        --cpu_threads=2\nfi"
  },
  {
    "path": "examples/csmsc/tts3/local/ort_predict_streaming.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_streaming.py \\\n        --inference_dir=${train_output_path}/inference_onnx_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_streaming \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --am_streaming=True\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_streaming.py \\\n        --inference_dir=${train_output_path}/inference_onnx_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_streaming \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --am_streaming=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../ort_predict_streaming.py \\\n        --inference_dir=${train_output_path}/inference_onnx_streaming \\\n        --am=fastspeech2_csmsc \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_streaming \\\n        --text=${BIN_DIR}/../../assets/csmsc_test.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --am_streaming=True\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/paddle2onnx.sh",
    "content": "train_output_path=$1\nmodel_dir=$2\noutput_dir=$3\nmodel=$4\n\nenable_dev_version=True\n\nmodel_name=${model%_*}\necho model_name: ${model_name}\n\nif [ ${model_name} = 'mb_melgan' ] ;then\n    enable_dev_version=False\nfi\n\nmkdir -p ${train_output_path}/${output_dir}\n\npaddle2onnx \\\n    --model_dir ${train_output_path}/${model_dir} \\\n    --model_filename ${model}.pdmodel \\\n    --params_filename ${model}.pdiparams \\\n    --save_file ${train_output_path}/${output_dir}/${model}.onnx \\\n    --opset_version 11 \\\n    --enable_dev_version ${enable_dev_version}"
  },
  {
    "path": "examples/csmsc/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/simple.lexicon",
    "content": "a1  a1\na2  a2\na3  a3\na4  a4\na5  a5\nar1  ar1\nar2  ar2\nar3  ar3\nar4  ar4\nar5  ar5\nai1  ai1\nai2  ai2\nai3  ai3\nai4  ai4\nai5  ai5\nair1  air1\nair2  air2\nair3  air3\nair4  air4\nair5  air5\nao1  ao1\nao2  ao2\nao3  ao3\nao4  ao4\nao5  ao5\naor1  aor1\naor2  aor2\naor3  aor3\naor4  aor4\naor5  aor5\nan1  an1\nan2  an2\nan3  an3\nan4  an4\nan5  an5\nanr1  anr1\nanr2  anr2\nanr3  anr3\nanr4  anr4\nanr5  anr5\nang1  ang1\nang2  ang2\nang3  ang3\nang4  ang4\nang5  ang5\nangr1  angr1\nangr2  angr2\nangr3  angr3\nangr4  angr4\nangr5  angr5\ne1  e1\ne2  e2\ne3  e3\ne4  e4\ne5  e5\ner1  er1\ner2  er2\ner3  er3\ner4  er4\ner5  er5\nei1  ei1\nei2  ei2\nei3  ei3\nei4  ei4\nei5  ei5\neir1  eir1\neir2  eir2\neir3  eir3\neir4  eir4\neir5  eir5\nen1  en1\nen2  en2\nen3  en3\nen4  en4\nen5  en5\nenr1  enr1\nenr2  enr2\nenr3  enr3\nenr4  enr4\nenr5  enr5\neng1  eng1\neng2  eng2\neng3  eng3\neng4  eng4\neng5  eng5\nengr1  engr1\nengr2  engr2\nengr3  engr3\nengr4  engr4\nengr5  engr5\no1  o1\no2  o2\no3  o3\no4  o4\no5  o5\nor1  or1\nor2  or2\nor3  or3\nor4  or4\nor5  or5\nou1  ou1\nou2  ou2\nou3  ou3\nou4  ou4\nou5  ou5\nour1  our1\nour2  our2\nour3  our3\nour4  our4\nour5  our5\nong1  ong1\nong2  ong2\nong3  ong3\nong4  ong4\nong5  ong5\nongr1  ongr1\nongr2  ongr2\nongr3  ongr3\nongr4  ongr4\nongr5  ongr5\nyi1  i1\nyi2  i2\nyi3  i3\nyi4  i4\nyi5  i5\nyir1  ir1\nyir2  ir2\nyir3  ir3\nyir4  ir4\nyir5  ir5\nya1  ia1\nya2  ia2\nya3  ia3\nya4  ia4\nya5  ia5\nyar1  iar1\nyar2  iar2\nyar3  iar3\nyar4  iar4\nyar5  iar5\nyao1  iao1\nyao2  iao2\nyao3  iao3\nyao4  iao4\nyao5  iao5\nyaor1  iaor1\nyaor2  iaor2\nyaor3  iaor3\nyaor4  iaor4\nyaor5  iaor5\nyan1  ian1\nyan2  ian2\nyan3  ian3\nyan4  ian4\nyan5  ian5\nyanr1  ianr1\nyanr2  ianr2\nyanr3  ianr3\nyanr4  ianr4\nyanr5  ianr5\nyang1  iang1\nyang2  iang2\nyang3  iang3\nyang4  iang4\nyang5  iang5\nyangr1  iangr1\nyangr2  iangr2\nyangr3  iangr3\nyangr4  iangr4\nyangr5  iangr5\nye1  ie1\nye2  ie2\nye3  ie3\nye4  ie4\nye5  ie5\nyer1  ier1\nyer2  ier2\nyer3  ier3\nyer4  ier4\nyer5  ier5\nyo1  io1\nyo2  io2\nyo3  io3\nyo4  io4\nyo5  io5\nyor1  ior1\nyor2  ior2\nyor3  ior3\nyor4  ior4\nyor5  ior5\nyou1  iou1\nyou2  iou2\nyou3  iou3\nyou4  iou4\nyou5  iou5\nyour1  iour1\nyour2  iour2\nyour3  iour3\nyour4  iour4\nyour5  iour5\nyong1  iong1\nyong2  iong2\nyong3  iong3\nyong4  iong4\nyong5  iong5\nyongr1  iongr1\nyongr2  iongr2\nyongr3  iongr3\nyongr4  iongr4\nyongr5  iongr5\nyin1  in1\nyin2  in2\nyin3  in3\nyin4  in4\nyin5  in5\nyinr1  inr1\nyinr2  inr2\nyinr3  inr3\nyinr4  inr4\nyinr5  inr5\nying1  ing1\nying2  ing2\nying3  ing3\nying4  ing4\nying5  ing5\nyingr1  ingr1\nyingr2  ingr2\nyingr3  ingr3\nyingr4  ingr4\nyingr5  ingr5\nwu1  u1\nwu2  u2\nwu3  u3\nwu4  u4\nwu5  u5\nwur1  ur1\nwur2  ur2\nwur3  ur3\nwur4  ur4\nwur5  ur5\nwa1  ua1\nwa2  ua2\nwa3  ua3\nwa4  ua4\nwa5  ua5\nwar1  uar1\nwar2  uar2\nwar3  uar3\nwar4  uar4\nwar5  uar5\nwai1  uai1\nwai2  uai2\nwai3  uai3\nwai4  uai4\nwai5  uai5\nwair1  uair1\nwair2  uair2\nwair3  uair3\nwair4  uair4\nwair5  uair5\nwan1  uan1\nwan2  uan2\nwan3  uan3\nwan4  uan4\nwan5  uan5\nwanr1  uanr1\nwanr2  uanr2\nwanr3  uanr3\nwanr4  uanr4\nwanr5  uanr5\nwang1  uang1\nwang2  uang2\nwang3  uang3\nwang4  uang4\nwang5  uang5\nwangr1  uangr1\nwangr2  uangr2\nwangr3  uangr3\nwangr4  uangr4\nwangr5  uangr5\nwei1  uei1\nwei2  uei2\nwei3  uei3\nwei4  uei4\nwei5  uei5\nweir1  ueir1\nweir2  ueir2\nweir3  ueir3\nweir4  ueir4\nweir5  ueir5\nwo1  uo1\nwo2  uo2\nwo3  uo3\nwo4  uo4\nwo5  uo5\nwor1  uor1\nwor2  uor2\nwor3  uor3\nwor4  uor4\nwor5  uor5\nwen1  uen1\nwen2  uen2\nwen3  uen3\nwen4  uen4\nwen5  uen5\nwenr1  uenr1\nwenr2  uenr2\nwenr3  uenr3\nwenr4  uenr4\nwenr5  uenr5\nweng1  ueng1\nweng2  ueng2\nweng3  ueng3\nweng4  ueng4\nweng5  ueng5\nwengr1  uengr1\nwengr2  uengr2\nwengr3  uengr3\nwengr4  uengr4\nwengr5  uengr5\nyu1  v1\nyu2  v2\nyu3  v3\nyu4  v4\nyu5  v5\nyur1  vr1\nyur2  vr2\nyur3  vr3\nyur4  vr4\nyur5  vr5\nyue1  ve1\nyue2  ve2\nyue3  ve3\nyue4  ve4\nyue5  ve5\nyuer1  ver1\nyuer2  ver2\nyuer3  ver3\nyuer4  ver4\nyuer5  ver5\nyuan1  van1\nyuan2  van2\nyuan3  van3\nyuan4  van4\nyuan5  van5\nyuanr1  vanr1\nyuanr2  vanr2\nyuanr3  vanr3\nyuanr4  vanr4\nyuanr5  vanr5\nyun1  vn1\nyun2  vn2\nyun3  vn3\nyun4  vn4\nyun5  vn5\nyunr1  vnr1\nyunr2  vnr2\nyunr3  vnr3\nyunr4  vnr4\nyunr5  vnr5\nba1 b a1\nba2 b a2\nba3 b a3\nba4 b a4\nba5 b a5\nbar1 b ar1\nbar2 b ar2\nbar3 b ar3\nbar4 b ar4\nbar5 b ar5\nbai1 b ai1\nbai2 b ai2\nbai3 b ai3\nbai4 b ai4\nbai5 b ai5\nbair1 b air1\nbair2 b air2\nbair3 b air3\nbair4 b air4\nbair5 b air5\nbao1 b ao1\nbao2 b ao2\nbao3 b ao3\nbao4 b ao4\nbao5 b ao5\nbaor1 b aor1\nbaor2 b aor2\nbaor3 b aor3\nbaor4 b aor4\nbaor5 b aor5\nban1 b an1\nban2 b an2\nban3 b an3\nban4 b an4\nban5 b an5\nbanr1 b anr1\nbanr2 b anr2\nbanr3 b anr3\nbanr4 b anr4\nbanr5 b anr5\nbang1 b ang1\nbang2 b ang2\nbang3 b ang3\nbang4 b ang4\nbang5 b ang5\nbangr1 b angr1\nbangr2 b angr2\nbangr3 b angr3\nbangr4 b angr4\nbangr5 b angr5\nbe1 b e1\nbe2 b e2\nbe3 b e3\nbe4 b e4\nbe5 b e5\nber1 b er1\nber2 b er2\nber3 b er3\nber4 b er4\nber5 b er5\nbei1 b ei1\nbei2 b ei2\nbei3 b ei3\nbei4 b ei4\nbei5 b ei5\nbeir1 b eir1\nbeir2 b eir2\nbeir3 b eir3\nbeir4 b eir4\nbeir5 b eir5\nben1 b en1\nben2 b en2\nben3 b en3\nben4 b en4\nben5 b en5\nbenr1 b enr1\nbenr2 b enr2\nbenr3 b enr3\nbenr4 b enr4\nbenr5 b enr5\nbeng1 b eng1\nbeng2 b eng2\nbeng3 b eng3\nbeng4 b eng4\nbeng5 b eng5\nbengr1 b engr1\nbengr2 b engr2\nbengr3 b engr3\nbengr4 b engr4\nbengr5 b engr5\nbo1 b o1\nbo2 b o2\nbo3 b o3\nbo4 b o4\nbo5 b o5\nbor1 b or1\nbor2 b or2\nbor3 b or3\nbor4 b or4\nbor5 b or5\nbou1 b ou1\nbou2 b ou2\nbou3 b ou3\nbou4 b ou4\nbou5 b ou5\nbour1 b our1\nbour2 b our2\nbour3 b our3\nbour4 b our4\nbour5 b our5\nbi1 b i1\nbi2 b i2\nbi3 b i3\nbi4 b i4\nbi5 b i5\nbir1 b ir1\nbir2 b ir2\nbir3 b ir3\nbir4 b ir4\nbir5 b ir5\nbia1 b ia1\nbia2 b ia2\nbia3 b ia3\nbia4 b ia4\nbia5 b ia5\nbiar1 b iar1\nbiar2 b iar2\nbiar3 b iar3\nbiar4 b iar4\nbiar5 b iar5\nbiao1 b iao1\nbiao2 b iao2\nbiao3 b iao3\nbiao4 b iao4\nbiao5 b iao5\nbiaor1 b iaor1\nbiaor2 b iaor2\nbiaor3 b iaor3\nbiaor4 b iaor4\nbiaor5 b iaor5\nbian1 b ian1\nbian2 b ian2\nbian3 b ian3\nbian4 b ian4\nbian5 b ian5\nbianr1 b ianr1\nbianr2 b ianr2\nbianr3 b ianr3\nbianr4 b ianr4\nbianr5 b ianr5\nbiang1 b iang1\nbiang2 b iang2\nbiang3 b iang3\nbiang4 b iang4\nbiang5 b iang5\nbiangr1 b iangr1\nbiangr2 b iangr2\nbiangr3 b iangr3\nbiangr4 b iangr4\nbiangr5 b iangr5\nbie1 b ie1\nbie2 b ie2\nbie3 b ie3\nbie4 b ie4\nbie5 b ie5\nbier1 b ier1\nbier2 b ier2\nbier3 b ier3\nbier4 b ier4\nbier5 b ier5\nbio1 b io1\nbio2 b io2\nbio3 b io3\nbio4 b io4\nbio5 b io5\nbior1 b ior1\nbior2 b ior2\nbior3 b ior3\nbior4 b ior4\nbior5 b ior5\nbiu1 b iou1\nbiu2 b iou2\nbiu3 b iou3\nbiu4 b iou4\nbiu5 b iou5\nbiur1 b iour1\nbiur2 b iour2\nbiur3 b iour3\nbiur4 b iour4\nbiur5 b iour5\nbiong1 b iong1\nbiong2 b iong2\nbiong3 b iong3\nbiong4 b iong4\nbiong5 b iong5\nbiongr1 b iongr1\nbiongr2 b iongr2\nbiongr3 b iongr3\nbiongr4 b iongr4\nbiongr5 b iongr5\nbin1 b in1\nbin2 b in2\nbin3 b in3\nbin4 b in4\nbin5 b in5\nbinr1 b inr1\nbinr2 b inr2\nbinr3 b inr3\nbinr4 b inr4\nbinr5 b inr5\nbing1 b ing1\nbing2 b ing2\nbing3 b ing3\nbing4 b ing4\nbing5 b ing5\nbingr1 b ingr1\nbingr2 b ingr2\nbingr3 b ingr3\nbingr4 b ingr4\nbingr5 b ingr5\nbu1 b u1\nbu2 b u2\nbu3 b u3\nbu4 b u4\nbu5 b u5\nbur1 b ur1\nbur2 b ur2\nbur3 b ur3\nbur4 b ur4\nbur5 b ur5\npa1 p a1\npa2 p a2\npa3 p a3\npa4 p a4\npa5 p a5\npar1 p ar1\npar2 p ar2\npar3 p ar3\npar4 p ar4\npar5 p ar5\npai1 p ai1\npai2 p ai2\npai3 p ai3\npai4 p ai4\npai5 p ai5\npair1 p air1\npair2 p air2\npair3 p air3\npair4 p air4\npair5 p air5\npao1 p ao1\npao2 p ao2\npao3 p ao3\npao4 p ao4\npao5 p ao5\npaor1 p aor1\npaor2 p aor2\npaor3 p aor3\npaor4 p aor4\npaor5 p aor5\npan1 p an1\npan2 p an2\npan3 p an3\npan4 p an4\npan5 p an5\npanr1 p anr1\npanr2 p anr2\npanr3 p anr3\npanr4 p anr4\npanr5 p anr5\npang1 p ang1\npang2 p ang2\npang3 p ang3\npang4 p ang4\npang5 p ang5\npangr1 p angr1\npangr2 p angr2\npangr3 p angr3\npangr4 p angr4\npangr5 p angr5\npe1 p e1\npe2 p e2\npe3 p e3\npe4 p e4\npe5 p e5\nper1 p er1\nper2 p er2\nper3 p er3\nper4 p er4\nper5 p er5\npei1 p ei1\npei2 p ei2\npei3 p ei3\npei4 p ei4\npei5 p ei5\npeir1 p eir1\npeir2 p eir2\npeir3 p eir3\npeir4 p eir4\npeir5 p eir5\npen1 p en1\npen2 p en2\npen3 p en3\npen4 p en4\npen5 p en5\npenr1 p enr1\npenr2 p enr2\npenr3 p enr3\npenr4 p enr4\npenr5 p enr5\npeng1 p eng1\npeng2 p eng2\npeng3 p eng3\npeng4 p eng4\npeng5 p eng5\npengr1 p engr1\npengr2 p engr2\npengr3 p engr3\npengr4 p engr4\npengr5 p engr5\npo1 p o1\npo2 p o2\npo3 p o3\npo4 p o4\npo5 p o5\npor1 p or1\npor2 p or2\npor3 p or3\npor4 p or4\npor5 p or5\npou1 p ou1\npou2 p ou2\npou3 p ou3\npou4 p ou4\npou5 p ou5\npour1 p our1\npour2 p our2\npour3 p our3\npour4 p our4\npour5 p our5\npi1 p i1\npi2 p i2\npi3 p i3\npi4 p i4\npi5 p i5\npir1 p ir1\npir2 p ir2\npir3 p ir3\npir4 p ir4\npir5 p ir5\npia1 p ia1\npia2 p ia2\npia3 p ia3\npia4 p ia4\npia5 p ia5\npiar1 p iar1\npiar2 p iar2\npiar3 p iar3\npiar4 p iar4\npiar5 p iar5\npiao1 p iao1\npiao2 p iao2\npiao3 p iao3\npiao4 p iao4\npiao5 p iao5\npiaor1 p iaor1\npiaor2 p iaor2\npiaor3 p iaor3\npiaor4 p iaor4\npiaor5 p iaor5\npian1 p ian1\npian2 p ian2\npian3 p ian3\npian4 p ian4\npian5 p ian5\npianr1 p ianr1\npianr2 p ianr2\npianr3 p ianr3\npianr4 p ianr4\npianr5 p ianr5\npiang1 p iang1\npiang2 p iang2\npiang3 p iang3\npiang4 p iang4\npiang5 p iang5\npiangr1 p iangr1\npiangr2 p iangr2\npiangr3 p iangr3\npiangr4 p iangr4\npiangr5 p iangr5\npie1 p ie1\npie2 p ie2\npie3 p ie3\npie4 p ie4\npie5 p ie5\npier1 p ier1\npier2 p ier2\npier3 p ier3\npier4 p ier4\npier5 p ier5\npio1 p io1\npio2 p io2\npio3 p io3\npio4 p io4\npio5 p io5\npior1 p ior1\npior2 p ior2\npior3 p ior3\npior4 p ior4\npior5 p ior5\npiu1 p iou1\npiu2 p iou2\npiu3 p iou3\npiu4 p iou4\npiu5 p iou5\npiur1 p iour1\npiur2 p iour2\npiur3 p iour3\npiur4 p iour4\npiur5 p iour5\npiong1 p iong1\npiong2 p iong2\npiong3 p iong3\npiong4 p iong4\npiong5 p iong5\npiongr1 p iongr1\npiongr2 p iongr2\npiongr3 p iongr3\npiongr4 p iongr4\npiongr5 p iongr5\npin1 p in1\npin2 p in2\npin3 p in3\npin4 p in4\npin5 p in5\npinr1 p inr1\npinr2 p inr2\npinr3 p inr3\npinr4 p inr4\npinr5 p inr5\nping1 p ing1\nping2 p ing2\nping3 p ing3\nping4 p ing4\nping5 p ing5\npingr1 p ingr1\npingr2 p ingr2\npingr3 p ingr3\npingr4 p ingr4\npingr5 p ingr5\npu1 p u1\npu2 p u2\npu3 p u3\npu4 p u4\npu5 p u5\npur1 p ur1\npur2 p ur2\npur3 p ur3\npur4 p ur4\npur5 p ur5\nma1 m a1\nma2 m a2\nma3 m a3\nma4 m a4\nma5 m a5\nmar1 m ar1\nmar2 m ar2\nmar3 m ar3\nmar4 m ar4\nmar5 m ar5\nmai1 m ai1\nmai2 m ai2\nmai3 m ai3\nmai4 m ai4\nmai5 m ai5\nmair1 m air1\nmair2 m air2\nmair3 m air3\nmair4 m air4\nmair5 m air5\nmao1 m ao1\nmao2 m ao2\nmao3 m ao3\nmao4 m ao4\nmao5 m ao5\nmaor1 m aor1\nmaor2 m aor2\nmaor3 m aor3\nmaor4 m aor4\nmaor5 m aor5\nman1 m an1\nman2 m an2\nman3 m an3\nman4 m an4\nman5 m an5\nmanr1 m anr1\nmanr2 m anr2\nmanr3 m anr3\nmanr4 m anr4\nmanr5 m anr5\nmang1 m ang1\nmang2 m ang2\nmang3 m ang3\nmang4 m ang4\nmang5 m ang5\nmangr1 m angr1\nmangr2 m angr2\nmangr3 m angr3\nmangr4 m angr4\nmangr5 m angr5\nme1 m e1\nme2 m e2\nme3 m e3\nme4 m e4\nme5 m e5\nmer1 m er1\nmer2 m er2\nmer3 m er3\nmer4 m er4\nmer5 m er5\nmei1 m ei1\nmei2 m ei2\nmei3 m ei3\nmei4 m ei4\nmei5 m ei5\nmeir1 m eir1\nmeir2 m eir2\nmeir3 m eir3\nmeir4 m eir4\nmeir5 m eir5\nmen1 m en1\nmen2 m en2\nmen3 m en3\nmen4 m en4\nmen5 m en5\nmenr1 m enr1\nmenr2 m enr2\nmenr3 m enr3\nmenr4 m enr4\nmenr5 m enr5\nmeng1 m eng1\nmeng2 m eng2\nmeng3 m eng3\nmeng4 m eng4\nmeng5 m eng5\nmengr1 m engr1\nmengr2 m engr2\nmengr3 m engr3\nmengr4 m engr4\nmengr5 m engr5\nmo1 m o1\nmo2 m o2\nmo3 m o3\nmo4 m o4\nmo5 m o5\nmor1 m or1\nmor2 m or2\nmor3 m or3\nmor4 m or4\nmor5 m or5\nmou1 m ou1\nmou2 m ou2\nmou3 m ou3\nmou4 m ou4\nmou5 m ou5\nmour1 m our1\nmour2 m our2\nmour3 m our3\nmour4 m our4\nmour5 m our5\nmi1 m i1\nmi2 m i2\nmi3 m i3\nmi4 m i4\nmi5 m i5\nmir1 m ir1\nmir2 m ir2\nmir3 m ir3\nmir4 m ir4\nmir5 m ir5\nmia1 m ia1\nmia2 m ia2\nmia3 m ia3\nmia4 m ia4\nmia5 m ia5\nmiar1 m iar1\nmiar2 m iar2\nmiar3 m iar3\nmiar4 m iar4\nmiar5 m iar5\nmiao1 m iao1\nmiao2 m iao2\nmiao3 m iao3\nmiao4 m iao4\nmiao5 m iao5\nmiaor1 m iaor1\nmiaor2 m iaor2\nmiaor3 m iaor3\nmiaor4 m iaor4\nmiaor5 m iaor5\nmian1 m ian1\nmian2 m ian2\nmian3 m ian3\nmian4 m ian4\nmian5 m ian5\nmianr1 m ianr1\nmianr2 m ianr2\nmianr3 m ianr3\nmianr4 m ianr4\nmianr5 m ianr5\nmiang1 m iang1\nmiang2 m iang2\nmiang3 m iang3\nmiang4 m iang4\nmiang5 m iang5\nmiangr1 m iangr1\nmiangr2 m iangr2\nmiangr3 m iangr3\nmiangr4 m iangr4\nmiangr5 m iangr5\nmie1 m ie1\nmie2 m ie2\nmie3 m ie3\nmie4 m ie4\nmie5 m ie5\nmier1 m ier1\nmier2 m ier2\nmier3 m ier3\nmier4 m ier4\nmier5 m ier5\nmio1 m io1\nmio2 m io2\nmio3 m io3\nmio4 m io4\nmio5 m io5\nmior1 m ior1\nmior2 m ior2\nmior3 m ior3\nmior4 m ior4\nmior5 m ior5\nmiu1 m iou1\nmiu2 m iou2\nmiu3 m iou3\nmiu4 m iou4\nmiu5 m iou5\nmiur1 m iour1\nmiur2 m iour2\nmiur3 m iour3\nmiur4 m iour4\nmiur5 m iour5\nmiong1 m iong1\nmiong2 m iong2\nmiong3 m iong3\nmiong4 m iong4\nmiong5 m iong5\nmiongr1 m iongr1\nmiongr2 m iongr2\nmiongr3 m iongr3\nmiongr4 m iongr4\nmiongr5 m iongr5\nmin1 m in1\nmin2 m in2\nmin3 m in3\nmin4 m in4\nmin5 m in5\nminr1 m inr1\nminr2 m inr2\nminr3 m inr3\nminr4 m inr4\nminr5 m inr5\nming1 m ing1\nming2 m ing2\nming3 m ing3\nming4 m ing4\nming5 m ing5\nmingr1 m ingr1\nmingr2 m ingr2\nmingr3 m ingr3\nmingr4 m ingr4\nmingr5 m ingr5\nmu1 m u1\nmu2 m u2\nmu3 m u3\nmu4 m u4\nmu5 m u5\nmur1 m ur1\nmur2 m ur2\nmur3 m ur3\nmur4 m ur4\nmur5 m ur5\nfa1 f a1\nfa2 f a2\nfa3 f a3\nfa4 f a4\nfa5 f a5\nfar1 f ar1\nfar2 f ar2\nfar3 f ar3\nfar4 f ar4\nfar5 f ar5\nfai1 f ai1\nfai2 f ai2\nfai3 f ai3\nfai4 f ai4\nfai5 f ai5\nfair1 f air1\nfair2 f air2\nfair3 f air3\nfair4 f air4\nfair5 f air5\nfao1 f ao1\nfao2 f ao2\nfao3 f ao3\nfao4 f ao4\nfao5 f ao5\nfaor1 f aor1\nfaor2 f aor2\nfaor3 f aor3\nfaor4 f aor4\nfaor5 f aor5\nfan1 f an1\nfan2 f an2\nfan3 f an3\nfan4 f an4\nfan5 f an5\nfanr1 f anr1\nfanr2 f anr2\nfanr3 f anr3\nfanr4 f anr4\nfanr5 f anr5\nfang1 f ang1\nfang2 f ang2\nfang3 f ang3\nfang4 f ang4\nfang5 f ang5\nfangr1 f angr1\nfangr2 f angr2\nfangr3 f angr3\nfangr4 f angr4\nfangr5 f angr5\nfe1 f e1\nfe2 f e2\nfe3 f e3\nfe4 f e4\nfe5 f e5\nfer1 f er1\nfer2 f er2\nfer3 f er3\nfer4 f er4\nfer5 f er5\nfei1 f ei1\nfei2 f ei2\nfei3 f ei3\nfei4 f ei4\nfei5 f ei5\nfeir1 f eir1\nfeir2 f eir2\nfeir3 f eir3\nfeir4 f eir4\nfeir5 f eir5\nfen1 f en1\nfen2 f en2\nfen3 f en3\nfen4 f en4\nfen5 f en5\nfenr1 f enr1\nfenr2 f enr2\nfenr3 f enr3\nfenr4 f enr4\nfenr5 f enr5\nfeng1 f eng1\nfeng2 f eng2\nfeng3 f eng3\nfeng4 f eng4\nfeng5 f eng5\nfengr1 f engr1\nfengr2 f engr2\nfengr3 f engr3\nfengr4 f engr4\nfengr5 f engr5\nfo1 f o1\nfo2 f o2\nfo3 f o3\nfo4 f o4\nfo5 f o5\nfor1 f or1\nfor2 f or2\nfor3 f or3\nfor4 f or4\nfor5 f or5\nfou1 f ou1\nfou2 f ou2\nfou3 f ou3\nfou4 f ou4\nfou5 f ou5\nfour1 f our1\nfour2 f our2\nfour3 f our3\nfour4 f our4\nfour5 f our5\nfu1 f u1\nfu2 f u2\nfu3 f u3\nfu4 f u4\nfu5 f u5\nfur1 f ur1\nfur2 f ur2\nfur3 f ur3\nfur4 f ur4\nfur5 f ur5\nda1 d a1\nda2 d a2\nda3 d a3\nda4 d a4\nda5 d a5\ndar1 d ar1\ndar2 d ar2\ndar3 d ar3\ndar4 d ar4\ndar5 d ar5\ndai1 d ai1\ndai2 d ai2\ndai3 d ai3\ndai4 d ai4\ndai5 d ai5\ndair1 d air1\ndair2 d air2\ndair3 d air3\ndair4 d air4\ndair5 d air5\ndao1 d ao1\ndao2 d ao2\ndao3 d ao3\ndao4 d ao4\ndao5 d ao5\ndaor1 d aor1\ndaor2 d aor2\ndaor3 d aor3\ndaor4 d aor4\ndaor5 d aor5\ndan1 d an1\ndan2 d an2\ndan3 d an3\ndan4 d an4\ndan5 d an5\ndanr1 d anr1\ndanr2 d anr2\ndanr3 d anr3\ndanr4 d anr4\ndanr5 d anr5\ndang1 d ang1\ndang2 d ang2\ndang3 d ang3\ndang4 d ang4\ndang5 d ang5\ndangr1 d angr1\ndangr2 d angr2\ndangr3 d angr3\ndangr4 d angr4\ndangr5 d angr5\nde1 d e1\nde2 d e2\nde3 d e3\nde4 d e4\nde5 d e5\nder1 d er1\nder2 d er2\nder3 d er3\nder4 d er4\nder5 d er5\ndei1 d ei1\ndei2 d ei2\ndei3 d ei3\ndei4 d ei4\ndei5 d ei5\ndeir1 d eir1\ndeir2 d eir2\ndeir3 d eir3\ndeir4 d eir4\ndeir5 d eir5\nden1 d en1\nden2 d en2\nden3 d en3\nden4 d en4\nden5 d en5\ndenr1 d enr1\ndenr2 d enr2\ndenr3 d enr3\ndenr4 d enr4\ndenr5 d enr5\ndeng1 d eng1\ndeng2 d eng2\ndeng3 d eng3\ndeng4 d eng4\ndeng5 d eng5\ndengr1 d engr1\ndengr2 d engr2\ndengr3 d engr3\ndengr4 d engr4\ndengr5 d engr5\ndou1 d ou1\ndou2 d ou2\ndou3 d ou3\ndou4 d ou4\ndou5 d ou5\ndour1 d our1\ndour2 d our2\ndour3 d our3\ndour4 d our4\ndour5 d our5\ndong1 d ong1\ndong2 d ong2\ndong3 d ong3\ndong4 d ong4\ndong5 d ong5\ndongr1 d ongr1\ndongr2 d ongr2\ndongr3 d ongr3\ndongr4 d ongr4\ndongr5 d ongr5\ndi1 d i1\ndi2 d i2\ndi3 d i3\ndi4 d i4\ndi5 d i5\ndir1 d ir1\ndir2 d ir2\ndir3 d ir3\ndir4 d ir4\ndir5 d ir5\ndia1 d ia1\ndia2 d ia2\ndia3 d ia3\ndia4 d ia4\ndia5 d ia5\ndiar1 d iar1\ndiar2 d iar2\ndiar3 d iar3\ndiar4 d iar4\ndiar5 d iar5\ndiao1 d iao1\ndiao2 d iao2\ndiao3 d iao3\ndiao4 d iao4\ndiao5 d iao5\ndiaor1 d iaor1\ndiaor2 d iaor2\ndiaor3 d iaor3\ndiaor4 d iaor4\ndiaor5 d iaor5\ndian1 d ian1\ndian2 d ian2\ndian3 d ian3\ndian4 d ian4\ndian5 d ian5\ndianr1 d ianr1\ndianr2 d ianr2\ndianr3 d ianr3\ndianr4 d ianr4\ndianr5 d ianr5\ndiang1 d iang1\ndiang2 d iang2\ndiang3 d iang3\ndiang4 d iang4\ndiang5 d iang5\ndiangr1 d iangr1\ndiangr2 d iangr2\ndiangr3 d iangr3\ndiangr4 d iangr4\ndiangr5 d iangr5\ndie1 d ie1\ndie2 d ie2\ndie3 d ie3\ndie4 d ie4\ndie5 d ie5\ndier1 d ier1\ndier2 d ier2\ndier3 d ier3\ndier4 d ier4\ndier5 d ier5\ndio1 d io1\ndio2 d io2\ndio3 d io3\ndio4 d io4\ndio5 d io5\ndior1 d ior1\ndior2 d ior2\ndior3 d ior3\ndior4 d ior4\ndior5 d ior5\ndiu1 d iou1\ndiu2 d iou2\ndiu3 d iou3\ndiu4 d iou4\ndiu5 d iou5\ndiur1 d iour1\ndiur2 d iour2\ndiur3 d iour3\ndiur4 d iour4\ndiur5 d iour5\ndiong1 d iong1\ndiong2 d iong2\ndiong3 d iong3\ndiong4 d iong4\ndiong5 d iong5\ndiongr1 d iongr1\ndiongr2 d iongr2\ndiongr3 d iongr3\ndiongr4 d iongr4\ndiongr5 d iongr5\ndin1 d in1\ndin2 d in2\ndin3 d in3\ndin4 d in4\ndin5 d in5\ndinr1 d inr1\ndinr2 d inr2\ndinr3 d inr3\ndinr4 d inr4\ndinr5 d inr5\nding1 d ing1\nding2 d ing2\nding3 d ing3\nding4 d ing4\nding5 d ing5\ndingr1 d ingr1\ndingr2 d ingr2\ndingr3 d ingr3\ndingr4 d ingr4\ndingr5 d ingr5\ndu1 d u1\ndu2 d u2\ndu3 d u3\ndu4 d u4\ndu5 d u5\ndur1 d ur1\ndur2 d ur2\ndur3 d ur3\ndur4 d ur4\ndur5 d ur5\nduan1 d uan1\nduan2 d uan2\nduan3 d uan3\nduan4 d uan4\nduan5 d uan5\nduanr1 d uanr1\nduanr2 d uanr2\nduanr3 d uanr3\nduanr4 d uanr4\nduanr5 d uanr5\ndui1 d uei1\ndui2 d uei2\ndui3 d uei3\ndui4 d uei4\ndui5 d uei5\nduir1 d ueir1\nduir2 d ueir2\nduir3 d ueir3\nduir4 d ueir4\nduir5 d ueir5\nduo1 d uo1\nduo2 d uo2\nduo3 d uo3\nduo4 d uo4\nduo5 d uo5\nduor1 d uor1\nduor2 d uor2\nduor3 d uor3\nduor4 d uor4\nduor5 d uor5\ndun1 d uen1\ndun2 d uen2\ndun3 d uen3\ndun4 d uen4\ndun5 d uen5\ndunr1 d uenr1\ndunr2 d uenr2\ndunr3 d uenr3\ndunr4 d uenr4\ndunr5 d uenr5\nta1 t a1\nta2 t a2\nta3 t a3\nta4 t a4\nta5 t a5\ntar1 t ar1\ntar2 t ar2\ntar3 t ar3\ntar4 t ar4\ntar5 t ar5\ntai1 t ai1\ntai2 t ai2\ntai3 t ai3\ntai4 t ai4\ntai5 t ai5\ntair1 t air1\ntair2 t air2\ntair3 t air3\ntair4 t air4\ntair5 t air5\ntao1 t ao1\ntao2 t ao2\ntao3 t ao3\ntao4 t ao4\ntao5 t ao5\ntaor1 t aor1\ntaor2 t aor2\ntaor3 t aor3\ntaor4 t aor4\ntaor5 t aor5\ntan1 t an1\ntan2 t an2\ntan3 t an3\ntan4 t an4\ntan5 t an5\ntanr1 t anr1\ntanr2 t anr2\ntanr3 t anr3\ntanr4 t anr4\ntanr5 t anr5\ntang1 t ang1\ntang2 t ang2\ntang3 t ang3\ntang4 t ang4\ntang5 t ang5\ntangr1 t angr1\ntangr2 t angr2\ntangr3 t angr3\ntangr4 t angr4\ntangr5 t angr5\nte1 t e1\nte2 t e2\nte3 t e3\nte4 t e4\nte5 t e5\nter1 t er1\nter2 t er2\nter3 t er3\nter4 t er4\nter5 t er5\ntei1 t ei1\ntei2 t ei2\ntei3 t ei3\ntei4 t ei4\ntei5 t ei5\nteir1 t eir1\nteir2 t eir2\nteir3 t eir3\nteir4 t eir4\nteir5 t eir5\nten1 t en1\nten2 t en2\nten3 t en3\nten4 t en4\nten5 t en5\ntenr1 t enr1\ntenr2 t enr2\ntenr3 t enr3\ntenr4 t enr4\ntenr5 t enr5\nteng1 t eng1\nteng2 t eng2\nteng3 t eng3\nteng4 t eng4\nteng5 t eng5\ntengr1 t engr1\ntengr2 t engr2\ntengr3 t engr3\ntengr4 t engr4\ntengr5 t engr5\ntou1 t ou1\ntou2 t ou2\ntou3 t ou3\ntou4 t ou4\ntou5 t ou5\ntour1 t our1\ntour2 t our2\ntour3 t our3\ntour4 t our4\ntour5 t our5\ntong1 t ong1\ntong2 t ong2\ntong3 t ong3\ntong4 t ong4\ntong5 t ong5\ntongr1 t ongr1\ntongr2 t ongr2\ntongr3 t ongr3\ntongr4 t ongr4\ntongr5 t ongr5\nti1 t i1\nti2 t i2\nti3 t i3\nti4 t i4\nti5 t i5\ntir1 t ir1\ntir2 t ir2\ntir3 t ir3\ntir4 t ir4\ntir5 t ir5\ntia1 t ia1\ntia2 t ia2\ntia3 t ia3\ntia4 t ia4\ntia5 t ia5\ntiar1 t iar1\ntiar2 t iar2\ntiar3 t iar3\ntiar4 t iar4\ntiar5 t iar5\ntiao1 t iao1\ntiao2 t iao2\ntiao3 t iao3\ntiao4 t iao4\ntiao5 t iao5\ntiaor1 t iaor1\ntiaor2 t iaor2\ntiaor3 t iaor3\ntiaor4 t iaor4\ntiaor5 t iaor5\ntian1 t ian1\ntian2 t ian2\ntian3 t ian3\ntian4 t ian4\ntian5 t ian5\ntianr1 t ianr1\ntianr2 t ianr2\ntianr3 t ianr3\ntianr4 t ianr4\ntianr5 t ianr5\ntiang1 t iang1\ntiang2 t iang2\ntiang3 t iang3\ntiang4 t iang4\ntiang5 t iang5\ntiangr1 t iangr1\ntiangr2 t iangr2\ntiangr3 t iangr3\ntiangr4 t iangr4\ntiangr5 t iangr5\ntie1 t ie1\ntie2 t ie2\ntie3 t ie3\ntie4 t ie4\ntie5 t ie5\ntier1 t ier1\ntier2 t ier2\ntier3 t ier3\ntier4 t ier4\ntier5 t ier5\ntio1 t io1\ntio2 t io2\ntio3 t io3\ntio4 t io4\ntio5 t io5\ntior1 t ior1\ntior2 t ior2\ntior3 t ior3\ntior4 t ior4\ntior5 t ior5\ntiu1 t iou1\ntiu2 t iou2\ntiu3 t iou3\ntiu4 t iou4\ntiu5 t iou5\ntiur1 t iour1\ntiur2 t iour2\ntiur3 t iour3\ntiur4 t iour4\ntiur5 t iour5\ntiong1 t iong1\ntiong2 t iong2\ntiong3 t iong3\ntiong4 t iong4\ntiong5 t iong5\ntiongr1 t iongr1\ntiongr2 t iongr2\ntiongr3 t iongr3\ntiongr4 t iongr4\ntiongr5 t iongr5\ntin1 t in1\ntin2 t in2\ntin3 t in3\ntin4 t in4\ntin5 t in5\ntinr1 t inr1\ntinr2 t inr2\ntinr3 t inr3\ntinr4 t inr4\ntinr5 t inr5\nting1 t ing1\nting2 t ing2\nting3 t ing3\nting4 t ing4\nting5 t ing5\ntingr1 t ingr1\ntingr2 t ingr2\ntingr3 t ingr3\ntingr4 t ingr4\ntingr5 t ingr5\ntu1 t u1\ntu2 t u2\ntu3 t u3\ntu4 t u4\ntu5 t u5\ntur1 t ur1\ntur2 t ur2\ntur3 t ur3\ntur4 t ur4\ntur5 t ur5\ntuan1 t uan1\ntuan2 t uan2\ntuan3 t uan3\ntuan4 t uan4\ntuan5 t uan5\ntuanr1 t uanr1\ntuanr2 t uanr2\ntuanr3 t uanr3\ntuanr4 t uanr4\ntuanr5 t uanr5\ntui1 t uei1\ntui2 t uei2\ntui3 t uei3\ntui4 t uei4\ntui5 t uei5\ntuir1 t ueir1\ntuir2 t ueir2\ntuir3 t ueir3\ntuir4 t ueir4\ntuir5 t ueir5\ntuo1 t uo1\ntuo2 t uo2\ntuo3 t uo3\ntuo4 t uo4\ntuo5 t uo5\ntuor1 t uor1\ntuor2 t uor2\ntuor3 t uor3\ntuor4 t uor4\ntuor5 t uor5\ntun1 t uen1\ntun2 t uen2\ntun3 t uen3\ntun4 t uen4\ntun5 t uen5\ntunr1 t uenr1\ntunr2 t uenr2\ntunr3 t uenr3\ntunr4 t uenr4\ntunr5 t uenr5\nna1 n a1\nna2 n a2\nna3 n a3\nna4 n a4\nna5 n a5\nnar1 n ar1\nnar2 n ar2\nnar3 n ar3\nnar4 n ar4\nnar5 n ar5\nnai1 n ai1\nnai2 n ai2\nnai3 n ai3\nnai4 n ai4\nnai5 n ai5\nnair1 n air1\nnair2 n air2\nnair3 n air3\nnair4 n air4\nnair5 n air5\nnao1 n ao1\nnao2 n ao2\nnao3 n ao3\nnao4 n ao4\nnao5 n ao5\nnaor1 n aor1\nnaor2 n aor2\nnaor3 n aor3\nnaor4 n aor4\nnaor5 n aor5\nnan1 n an1\nnan2 n an2\nnan3 n an3\nnan4 n an4\nnan5 n an5\nnanr1 n anr1\nnanr2 n anr2\nnanr3 n anr3\nnanr4 n anr4\nnanr5 n anr5\nnang1 n ang1\nnang2 n ang2\nnang3 n ang3\nnang4 n ang4\nnang5 n ang5\nnangr1 n angr1\nnangr2 n angr2\nnangr3 n angr3\nnangr4 n angr4\nnangr5 n angr5\nne1 n e1\nne2 n e2\nne3 n e3\nne4 n e4\nne5 n e5\nner1 n er1\nner2 n er2\nner3 n er3\nner4 n er4\nner5 n er5\nnei1 n ei1\nnei2 n ei2\nnei3 n ei3\nnei4 n ei4\nnei5 n ei5\nneir1 n eir1\nneir2 n eir2\nneir3 n eir3\nneir4 n eir4\nneir5 n eir5\nnen1 n en1\nnen2 n en2\nnen3 n en3\nnen4 n en4\nnen5 n en5\nnenr1 n enr1\nnenr2 n enr2\nnenr3 n enr3\nnenr4 n enr4\nnenr5 n enr5\nneng1 n eng1\nneng2 n eng2\nneng3 n eng3\nneng4 n eng4\nneng5 n eng5\nnengr1 n engr1\nnengr2 n engr2\nnengr3 n engr3\nnengr4 n engr4\nnengr5 n engr5\nnou1 n ou1\nnou2 n ou2\nnou3 n ou3\nnou4 n ou4\nnou5 n ou5\nnour1 n our1\nnour2 n our2\nnour3 n our3\nnour4 n our4\nnour5 n our5\nnong1 n ong1\nnong2 n ong2\nnong3 n ong3\nnong4 n ong4\nnong5 n ong5\nnongr1 n ongr1\nnongr2 n ongr2\nnongr3 n ongr3\nnongr4 n ongr4\nnongr5 n ongr5\nni1 n i1\nni2 n i2\nni3 n i3\nni4 n i4\nni5 n i5\nnir1 n ir1\nnir2 n ir2\nnir3 n ir3\nnir4 n ir4\nnir5 n ir5\nnia1 n ia1\nnia2 n ia2\nnia3 n ia3\nnia4 n ia4\nnia5 n ia5\nniar1 n iar1\nniar2 n iar2\nniar3 n iar3\nniar4 n iar4\nniar5 n iar5\nniao1 n iao1\nniao2 n iao2\nniao3 n iao3\nniao4 n iao4\nniao5 n iao5\nniaor1 n iaor1\nniaor2 n iaor2\nniaor3 n iaor3\nniaor4 n iaor4\nniaor5 n iaor5\nnian1 n ian1\nnian2 n ian2\nnian3 n ian3\nnian4 n ian4\nnian5 n ian5\nnianr1 n ianr1\nnianr2 n ianr2\nnianr3 n ianr3\nnianr4 n ianr4\nnianr5 n ianr5\nniang1 n iang1\nniang2 n iang2\nniang3 n iang3\nniang4 n iang4\nniang5 n iang5\nniangr1 n iangr1\nniangr2 n iangr2\nniangr3 n iangr3\nniangr4 n iangr4\nniangr5 n iangr5\nnie1 n ie1\nnie2 n ie2\nnie3 n ie3\nnie4 n ie4\nnie5 n ie5\nnier1 n ier1\nnier2 n ier2\nnier3 n ier3\nnier4 n ier4\nnier5 n ier5\nnio1 n io1\nnio2 n io2\nnio3 n io3\nnio4 n io4\nnio5 n io5\nnior1 n ior1\nnior2 n ior2\nnior3 n ior3\nnior4 n ior4\nnior5 n ior5\nniu1 n iou1\nniu2 n iou2\nniu3 n iou3\nniu4 n iou4\nniu5 n iou5\nniur1 n iour1\nniur2 n iour2\nniur3 n iour3\nniur4 n iour4\nniur5 n iour5\nniong1 n iong1\nniong2 n iong2\nniong3 n iong3\nniong4 n iong4\nniong5 n iong5\nniongr1 n iongr1\nniongr2 n iongr2\nniongr3 n iongr3\nniongr4 n iongr4\nniongr5 n iongr5\nnin1 n in1\nnin2 n in2\nnin3 n in3\nnin4 n in4\nnin5 n in5\nninr1 n inr1\nninr2 n inr2\nninr3 n inr3\nninr4 n inr4\nninr5 n inr5\nning1 n ing1\nning2 n ing2\nning3 n ing3\nning4 n ing4\nning5 n ing5\nningr1 n ingr1\nningr2 n ingr2\nningr3 n ingr3\nningr4 n ingr4\nningr5 n ingr5\nnu1 n u1\nnu2 n u2\nnu3 n u3\nnu4 n u4\nnu5 n u5\nnur1 n ur1\nnur2 n ur2\nnur3 n ur3\nnur4 n ur4\nnur5 n ur5\nnuan1 n uan1\nnuan2 n uan2\nnuan3 n uan3\nnuan4 n uan4\nnuan5 n uan5\nnuanr1 n uanr1\nnuanr2 n uanr2\nnuanr3 n uanr3\nnuanr4 n uanr4\nnuanr5 n uanr5\nnui1 n uei1\nnui2 n uei2\nnui3 n uei3\nnui4 n uei4\nnui5 n uei5\nnuir1 n ueir1\nnuir2 n ueir2\nnuir3 n ueir3\nnuir4 n ueir4\nnuir5 n ueir5\nnuo1 n uo1\nnuo2 n uo2\nnuo3 n uo3\nnuo4 n uo4\nnuo5 n uo5\nnuor1 n uor1\nnuor2 n uor2\nnuor3 n uor3\nnuor4 n uor4\nnuor5 n uor5\nnun1 n uen1\nnun2 n uen2\nnun3 n uen3\nnun4 n uen4\nnun5 n uen5\nnunr1 n uenr1\nnunr2 n uenr2\nnunr3 n uenr3\nnunr4 n uenr4\nnunr5 n uenr5\nnv1 n v1\nnv2 n v2\nnv3 n v3\nnv4 n v4\nnv5 n v5\nnvr1 n vr1\nnvr2 n vr2\nnvr3 n vr3\nnvr4 n vr4\nnvr5 n vr5\nnve1 n ve1\nnve2 n ve2\nnve3 n ve3\nnve4 n ve4\nnve5 n ve5\nnver1 n ver1\nnver2 n ver2\nnver3 n ver3\nnver4 n ver4\nnver5 n ver5\nla1 l a1\nla2 l a2\nla3 l a3\nla4 l a4\nla5 l a5\nlar1 l ar1\nlar2 l ar2\nlar3 l ar3\nlar4 l ar4\nlar5 l ar5\nlai1 l ai1\nlai2 l ai2\nlai3 l ai3\nlai4 l ai4\nlai5 l ai5\nlair1 l air1\nlair2 l air2\nlair3 l air3\nlair4 l air4\nlair5 l air5\nlao1 l ao1\nlao2 l ao2\nlao3 l ao3\nlao4 l ao4\nlao5 l ao5\nlaor1 l aor1\nlaor2 l aor2\nlaor3 l aor3\nlaor4 l aor4\nlaor5 l aor5\nlan1 l an1\nlan2 l an2\nlan3 l an3\nlan4 l an4\nlan5 l an5\nlanr1 l anr1\nlanr2 l anr2\nlanr3 l anr3\nlanr4 l anr4\nlanr5 l anr5\nlang1 l ang1\nlang2 l ang2\nlang3 l ang3\nlang4 l ang4\nlang5 l ang5\nlangr1 l angr1\nlangr2 l angr2\nlangr3 l angr3\nlangr4 l angr4\nlangr5 l angr5\nle1 l e1\nle2 l e2\nle3 l e3\nle4 l e4\nle5 l e5\nler1 l er1\nler2 l er2\nler3 l er3\nler4 l er4\nler5 l er5\nlei1 l ei1\nlei2 l ei2\nlei3 l ei3\nlei4 l ei4\nlei5 l ei5\nleir1 l eir1\nleir2 l eir2\nleir3 l eir3\nleir4 l eir4\nleir5 l eir5\nlen1 l en1\nlen2 l en2\nlen3 l en3\nlen4 l en4\nlen5 l en5\nlenr1 l enr1\nlenr2 l enr2\nlenr3 l enr3\nlenr4 l enr4\nlenr5 l enr5\nleng1 l eng1\nleng2 l eng2\nleng3 l eng3\nleng4 l eng4\nleng5 l eng5\nlengr1 l engr1\nlengr2 l engr2\nlengr3 l engr3\nlengr4 l engr4\nlengr5 l engr5\nlo1 l o1\nlo2 l o2\nlo3 l o3\nlo4 l o4\nlo5 l o5\nlor1 l or1\nlor2 l or2\nlor3 l or3\nlor4 l or4\nlor5 l or5\nlou1 l ou1\nlou2 l ou2\nlou3 l ou3\nlou4 l ou4\nlou5 l ou5\nlour1 l our1\nlour2 l our2\nlour3 l our3\nlour4 l our4\nlour5 l our5\nlong1 l ong1\nlong2 l ong2\nlong3 l ong3\nlong4 l ong4\nlong5 l ong5\nlongr1 l ongr1\nlongr2 l ongr2\nlongr3 l ongr3\nlongr4 l ongr4\nlongr5 l ongr5\nli1 l i1\nli2 l i2\nli3 l i3\nli4 l i4\nli5 l i5\nlir1 l ir1\nlir2 l ir2\nlir3 l ir3\nlir4 l ir4\nlir5 l ir5\nlia1 l ia1\nlia2 l ia2\nlia3 l ia3\nlia4 l ia4\nlia5 l ia5\nliar1 l iar1\nliar2 l iar2\nliar3 l iar3\nliar4 l iar4\nliar5 l iar5\nliao1 l iao1\nliao2 l iao2\nliao3 l iao3\nliao4 l iao4\nliao5 l iao5\nliaor1 l iaor1\nliaor2 l iaor2\nliaor3 l iaor3\nliaor4 l iaor4\nliaor5 l iaor5\nlian1 l ian1\nlian2 l ian2\nlian3 l ian3\nlian4 l ian4\nlian5 l ian5\nlianr1 l ianr1\nlianr2 l ianr2\nlianr3 l ianr3\nlianr4 l ianr4\nlianr5 l ianr5\nliang1 l iang1\nliang2 l iang2\nliang3 l iang3\nliang4 l iang4\nliang5 l iang5\nliangr1 l iangr1\nliangr2 l iangr2\nliangr3 l iangr3\nliangr4 l iangr4\nliangr5 l iangr5\nlie1 l ie1\nlie2 l ie2\nlie3 l ie3\nlie4 l ie4\nlie5 l ie5\nlier1 l ier1\nlier2 l ier2\nlier3 l ier3\nlier4 l ier4\nlier5 l ier5\nlio1 l io1\nlio2 l io2\nlio3 l io3\nlio4 l io4\nlio5 l io5\nlior1 l ior1\nlior2 l ior2\nlior3 l ior3\nlior4 l ior4\nlior5 l ior5\nliu1 l iou1\nliu2 l iou2\nliu3 l iou3\nliu4 l iou4\nliu5 l iou5\nliur1 l iour1\nliur2 l iour2\nliur3 l iour3\nliur4 l iour4\nliur5 l iour5\nliong1 l iong1\nliong2 l iong2\nliong3 l iong3\nliong4 l iong4\nliong5 l iong5\nliongr1 l iongr1\nliongr2 l iongr2\nliongr3 l iongr3\nliongr4 l iongr4\nliongr5 l iongr5\nlin1 l in1\nlin2 l in2\nlin3 l in3\nlin4 l in4\nlin5 l in5\nlinr1 l inr1\nlinr2 l inr2\nlinr3 l inr3\nlinr4 l inr4\nlinr5 l inr5\nling1 l ing1\nling2 l ing2\nling3 l ing3\nling4 l ing4\nling5 l ing5\nlingr1 l ingr1\nlingr2 l ingr2\nlingr3 l ingr3\nlingr4 l ingr4\nlingr5 l ingr5\nlu1 l u1\nlu2 l u2\nlu3 l u3\nlu4 l u4\nlu5 l u5\nlur1 l ur1\nlur2 l ur2\nlur3 l ur3\nlur4 l ur4\nlur5 l ur5\nluan1 l uan1\nluan2 l uan2\nluan3 l uan3\nluan4 l uan4\nluan5 l uan5\nluanr1 l uanr1\nluanr2 l uanr2\nluanr3 l uanr3\nluanr4 l uanr4\nluanr5 l uanr5\nlui1 l uei1\nlui2 l uei2\nlui3 l uei3\nlui4 l uei4\nlui5 l uei5\nluir1 l ueir1\nluir2 l ueir2\nluir3 l ueir3\nluir4 l ueir4\nluir5 l ueir5\nluo1 l uo1\nluo2 l uo2\nluo3 l uo3\nluo4 l uo4\nluo5 l uo5\nluor1 l uor1\nluor2 l uor2\nluor3 l uor3\nluor4 l uor4\nluor5 l uor5\nlun1 l uen1\nlun2 l uen2\nlun3 l uen3\nlun4 l uen4\nlun5 l uen5\nlunr1 l uenr1\nlunr2 l uenr2\nlunr3 l uenr3\nlunr4 l uenr4\nlunr5 l uenr5\nlv1 l v1\nlv2 l v2\nlv3 l v3\nlv4 l v4\nlv5 l v5\nlvr1 l vr1\nlvr2 l vr2\nlvr3 l vr3\nlvr4 l vr4\nlvr5 l vr5\nlve1 l ve1\nlve2 l ve2\nlve3 l ve3\nlve4 l ve4\nlve5 l ve5\nlver1 l ver1\nlver2 l ver2\nlver3 l ver3\nlver4 l ver4\nlver5 l ver5\nga1 g a1\nga2 g a2\nga3 g a3\nga4 g a4\nga5 g a5\ngar1 g ar1\ngar2 g ar2\ngar3 g ar3\ngar4 g ar4\ngar5 g ar5\ngai1 g ai1\ngai2 g ai2\ngai3 g ai3\ngai4 g ai4\ngai5 g ai5\ngair1 g air1\ngair2 g air2\ngair3 g air3\ngair4 g air4\ngair5 g air5\ngao1 g ao1\ngao2 g ao2\ngao3 g ao3\ngao4 g ao4\ngao5 g ao5\ngaor1 g aor1\ngaor2 g aor2\ngaor3 g aor3\ngaor4 g aor4\ngaor5 g aor5\ngan1 g an1\ngan2 g an2\ngan3 g an3\ngan4 g an4\ngan5 g an5\nganr1 g anr1\nganr2 g anr2\nganr3 g anr3\nganr4 g anr4\nganr5 g anr5\ngang1 g ang1\ngang2 g ang2\ngang3 g ang3\ngang4 g ang4\ngang5 g ang5\ngangr1 g angr1\ngangr2 g angr2\ngangr3 g angr3\ngangr4 g angr4\ngangr5 g angr5\nge1 g e1\nge2 g e2\nge3 g e3\nge4 g e4\nge5 g e5\nger1 g er1\nger2 g er2\nger3 g er3\nger4 g er4\nger5 g er5\ngei1 g ei1\ngei2 g ei2\ngei3 g ei3\ngei4 g ei4\ngei5 g ei5\ngeir1 g eir1\ngeir2 g eir2\ngeir3 g eir3\ngeir4 g eir4\ngeir5 g eir5\ngen1 g en1\ngen2 g en2\ngen3 g en3\ngen4 g en4\ngen5 g en5\ngenr1 g enr1\ngenr2 g enr2\ngenr3 g enr3\ngenr4 g enr4\ngenr5 g enr5\ngeng1 g eng1\ngeng2 g eng2\ngeng3 g eng3\ngeng4 g eng4\ngeng5 g eng5\ngengr1 g engr1\ngengr2 g engr2\ngengr3 g engr3\ngengr4 g engr4\ngengr5 g engr5\ngou1 g ou1\ngou2 g ou2\ngou3 g ou3\ngou4 g ou4\ngou5 g ou5\ngour1 g our1\ngour2 g our2\ngour3 g our3\ngour4 g our4\ngour5 g our5\ngong1 g ong1\ngong2 g ong2\ngong3 g ong3\ngong4 g ong4\ngong5 g ong5\ngongr1 g ongr1\ngongr2 g ongr2\ngongr3 g ongr3\ngongr4 g ongr4\ngongr5 g ongr5\ngu1 g u1\ngu2 g u2\ngu3 g u3\ngu4 g u4\ngu5 g u5\ngur1 g ur1\ngur2 g ur2\ngur3 g ur3\ngur4 g ur4\ngur5 g ur5\ngua1 g ua1\ngua2 g ua2\ngua3 g ua3\ngua4 g ua4\ngua5 g ua5\nguar1 g uar1\nguar2 g uar2\nguar3 g uar3\nguar4 g uar4\nguar5 g uar5\nguai1 g uai1\nguai2 g uai2\nguai3 g uai3\nguai4 g uai4\nguai5 g uai5\nguair1 g uair1\nguair2 g uair2\nguair3 g uair3\nguair4 g uair4\nguair5 g uair5\nguan1 g uan1\nguan2 g uan2\nguan3 g uan3\nguan4 g uan4\nguan5 g uan5\nguanr1 g uanr1\nguanr2 g uanr2\nguanr3 g uanr3\nguanr4 g uanr4\nguanr5 g uanr5\nguang1 g uang1\nguang2 g uang2\nguang3 g uang3\nguang4 g uang4\nguang5 g uang5\nguangr1 g uangr1\nguangr2 g uangr2\nguangr3 g uangr3\nguangr4 g uangr4\nguangr5 g uangr5\ngui1 g uei1\ngui2 g uei2\ngui3 g uei3\ngui4 g uei4\ngui5 g uei5\nguir1 g ueir1\nguir2 g ueir2\nguir3 g ueir3\nguir4 g ueir4\nguir5 g ueir5\nguo1 g uo1\nguo2 g uo2\nguo3 g uo3\nguo4 g uo4\nguo5 g uo5\nguor1 g uor1\nguor2 g uor2\nguor3 g uor3\nguor4 g uor4\nguor5 g uor5\ngun1 g uen1\ngun2 g uen2\ngun3 g uen3\ngun4 g uen4\ngun5 g uen5\ngunr1 g uenr1\ngunr2 g uenr2\ngunr3 g uenr3\ngunr4 g uenr4\ngunr5 g uenr5\nka1 k a1\nka2 k a2\nka3 k a3\nka4 k a4\nka5 k a5\nkar1 k ar1\nkar2 k ar2\nkar3 k ar3\nkar4 k ar4\nkar5 k ar5\nkai1 k ai1\nkai2 k ai2\nkai3 k ai3\nkai4 k ai4\nkai5 k ai5\nkair1 k air1\nkair2 k air2\nkair3 k air3\nkair4 k air4\nkair5 k air5\nkao1 k ao1\nkao2 k ao2\nkao3 k ao3\nkao4 k ao4\nkao5 k ao5\nkaor1 k aor1\nkaor2 k aor2\nkaor3 k aor3\nkaor4 k aor4\nkaor5 k aor5\nkan1 k an1\nkan2 k an2\nkan3 k an3\nkan4 k an4\nkan5 k an5\nkanr1 k anr1\nkanr2 k anr2\nkanr3 k anr3\nkanr4 k anr4\nkanr5 k anr5\nkang1 k ang1\nkang2 k ang2\nkang3 k ang3\nkang4 k ang4\nkang5 k ang5\nkangr1 k angr1\nkangr2 k angr2\nkangr3 k angr3\nkangr4 k angr4\nkangr5 k angr5\nke1 k e1\nke2 k e2\nke3 k e3\nke4 k e4\nke5 k e5\nker1 k er1\nker2 k er2\nker3 k er3\nker4 k er4\nker5 k er5\nkei1 k ei1\nkei2 k ei2\nkei3 k ei3\nkei4 k ei4\nkei5 k ei5\nkeir1 k eir1\nkeir2 k eir2\nkeir3 k eir3\nkeir4 k eir4\nkeir5 k eir5\nken1 k en1\nken2 k en2\nken3 k en3\nken4 k en4\nken5 k en5\nkenr1 k enr1\nkenr2 k enr2\nkenr3 k enr3\nkenr4 k enr4\nkenr5 k enr5\nkeng1 k eng1\nkeng2 k eng2\nkeng3 k eng3\nkeng4 k eng4\nkeng5 k eng5\nkengr1 k engr1\nkengr2 k engr2\nkengr3 k engr3\nkengr4 k engr4\nkengr5 k engr5\nkou1 k ou1\nkou2 k ou2\nkou3 k ou3\nkou4 k ou4\nkou5 k ou5\nkour1 k our1\nkour2 k our2\nkour3 k our3\nkour4 k our4\nkour5 k our5\nkong1 k ong1\nkong2 k ong2\nkong3 k ong3\nkong4 k ong4\nkong5 k ong5\nkongr1 k ongr1\nkongr2 k ongr2\nkongr3 k ongr3\nkongr4 k ongr4\nkongr5 k ongr5\nku1 k u1\nku2 k u2\nku3 k u3\nku4 k u4\nku5 k u5\nkur1 k ur1\nkur2 k ur2\nkur3 k ur3\nkur4 k ur4\nkur5 k ur5\nkua1 k ua1\nkua2 k ua2\nkua3 k ua3\nkua4 k ua4\nkua5 k ua5\nkuar1 k uar1\nkuar2 k uar2\nkuar3 k uar3\nkuar4 k uar4\nkuar5 k uar5\nkuai1 k uai1\nkuai2 k uai2\nkuai3 k uai3\nkuai4 k uai4\nkuai5 k uai5\nkuair1 k uair1\nkuair2 k uair2\nkuair3 k uair3\nkuair4 k uair4\nkuair5 k uair5\nkuan1 k uan1\nkuan2 k uan2\nkuan3 k uan3\nkuan4 k uan4\nkuan5 k uan5\nkuanr1 k uanr1\nkuanr2 k uanr2\nkuanr3 k uanr3\nkuanr4 k uanr4\nkuanr5 k uanr5\nkuang1 k uang1\nkuang2 k uang2\nkuang3 k uang3\nkuang4 k uang4\nkuang5 k uang5\nkuangr1 k uangr1\nkuangr2 k uangr2\nkuangr3 k uangr3\nkuangr4 k uangr4\nkuangr5 k uangr5\nkui1 k uei1\nkui2 k uei2\nkui3 k uei3\nkui4 k uei4\nkui5 k uei5\nkuir1 k ueir1\nkuir2 k ueir2\nkuir3 k ueir3\nkuir4 k ueir4\nkuir5 k ueir5\nkuo1 k uo1\nkuo2 k uo2\nkuo3 k uo3\nkuo4 k uo4\nkuo5 k uo5\nkuor1 k uor1\nkuor2 k uor2\nkuor3 k uor3\nkuor4 k uor4\nkuor5 k uor5\nkun1 k uen1\nkun2 k uen2\nkun3 k uen3\nkun4 k uen4\nkun5 k uen5\nkunr1 k uenr1\nkunr2 k uenr2\nkunr3 k uenr3\nkunr4 k uenr4\nkunr5 k uenr5\nha1 h a1\nha2 h a2\nha3 h a3\nha4 h a4\nha5 h a5\nhar1 h ar1\nhar2 h ar2\nhar3 h ar3\nhar4 h ar4\nhar5 h ar5\nhai1 h ai1\nhai2 h ai2\nhai3 h ai3\nhai4 h ai4\nhai5 h ai5\nhair1 h air1\nhair2 h air2\nhair3 h air3\nhair4 h air4\nhair5 h air5\nhao1 h ao1\nhao2 h ao2\nhao3 h ao3\nhao4 h ao4\nhao5 h ao5\nhaor1 h aor1\nhaor2 h aor2\nhaor3 h aor3\nhaor4 h aor4\nhaor5 h aor5\nhan1 h an1\nhan2 h an2\nhan3 h an3\nhan4 h an4\nhan5 h an5\nhanr1 h anr1\nhanr2 h anr2\nhanr3 h anr3\nhanr4 h anr4\nhanr5 h anr5\nhang1 h ang1\nhang2 h ang2\nhang3 h ang3\nhang4 h ang4\nhang5 h ang5\nhangr1 h angr1\nhangr2 h angr2\nhangr3 h angr3\nhangr4 h angr4\nhangr5 h angr5\nhe1 h e1\nhe2 h e2\nhe3 h e3\nhe4 h e4\nhe5 h e5\nher1 h er1\nher2 h er2\nher3 h er3\nher4 h er4\nher5 h er5\nhei1 h ei1\nhei2 h ei2\nhei3 h ei3\nhei4 h ei4\nhei5 h ei5\nheir1 h eir1\nheir2 h eir2\nheir3 h eir3\nheir4 h eir4\nheir5 h eir5\nhen1 h en1\nhen2 h en2\nhen3 h en3\nhen4 h en4\nhen5 h en5\nhenr1 h enr1\nhenr2 h enr2\nhenr3 h enr3\nhenr4 h enr4\nhenr5 h enr5\nheng1 h eng1\nheng2 h eng2\nheng3 h eng3\nheng4 h eng4\nheng5 h eng5\nhengr1 h engr1\nhengr2 h engr2\nhengr3 h engr3\nhengr4 h engr4\nhengr5 h engr5\nhou1 h ou1\nhou2 h ou2\nhou3 h ou3\nhou4 h ou4\nhou5 h ou5\nhour1 h our1\nhour2 h our2\nhour3 h our3\nhour4 h our4\nhour5 h our5\nhong1 h ong1\nhong2 h ong2\nhong3 h ong3\nhong4 h ong4\nhong5 h ong5\nhongr1 h ongr1\nhongr2 h ongr2\nhongr3 h ongr3\nhongr4 h ongr4\nhongr5 h ongr5\nhu1 h u1\nhu2 h u2\nhu3 h u3\nhu4 h u4\nhu5 h u5\nhur1 h ur1\nhur2 h ur2\nhur3 h ur3\nhur4 h ur4\nhur5 h ur5\nhua1 h ua1\nhua2 h ua2\nhua3 h ua3\nhua4 h ua4\nhua5 h ua5\nhuar1 h uar1\nhuar2 h uar2\nhuar3 h uar3\nhuar4 h uar4\nhuar5 h uar5\nhuai1 h uai1\nhuai2 h uai2\nhuai3 h uai3\nhuai4 h uai4\nhuai5 h uai5\nhuair1 h uair1\nhuair2 h uair2\nhuair3 h uair3\nhuair4 h uair4\nhuair5 h uair5\nhuan1 h uan1\nhuan2 h uan2\nhuan3 h uan3\nhuan4 h uan4\nhuan5 h uan5\nhuanr1 h uanr1\nhuanr2 h uanr2\nhuanr3 h uanr3\nhuanr4 h uanr4\nhuanr5 h uanr5\nhuang1 h uang1\nhuang2 h uang2\nhuang3 h uang3\nhuang4 h uang4\nhuang5 h uang5\nhuangr1 h uangr1\nhuangr2 h uangr2\nhuangr3 h uangr3\nhuangr4 h uangr4\nhuangr5 h uangr5\nhui1 h uei1\nhui2 h uei2\nhui3 h uei3\nhui4 h uei4\nhui5 h uei5\nhuir1 h ueir1\nhuir2 h ueir2\nhuir3 h ueir3\nhuir4 h ueir4\nhuir5 h ueir5\nhuo1 h uo1\nhuo2 h uo2\nhuo3 h uo3\nhuo4 h uo4\nhuo5 h uo5\nhuor1 h uor1\nhuor2 h uor2\nhuor3 h uor3\nhuor4 h uor4\nhuor5 h uor5\nhun1 h uen1\nhun2 h uen2\nhun3 h uen3\nhun4 h uen4\nhun5 h uen5\nhunr1 h uenr1\nhunr2 h uenr2\nhunr3 h uenr3\nhunr4 h uenr4\nhunr5 h uenr5\nzha1 zh a1\nzha2 zh a2\nzha3 zh a3\nzha4 zh a4\nzha5 zh a5\nzhar1 zh ar1\nzhar2 zh ar2\nzhar3 zh ar3\nzhar4 zh ar4\nzhar5 zh ar5\nzhai1 zh ai1\nzhai2 zh ai2\nzhai3 zh ai3\nzhai4 zh ai4\nzhai5 zh ai5\nzhair1 zh air1\nzhair2 zh air2\nzhair3 zh air3\nzhair4 zh air4\nzhair5 zh air5\nzhao1 zh ao1\nzhao2 zh ao2\nzhao3 zh ao3\nzhao4 zh ao4\nzhao5 zh ao5\nzhaor1 zh aor1\nzhaor2 zh aor2\nzhaor3 zh aor3\nzhaor4 zh aor4\nzhaor5 zh aor5\nzhan1 zh an1\nzhan2 zh an2\nzhan3 zh an3\nzhan4 zh an4\nzhan5 zh an5\nzhanr1 zh anr1\nzhanr2 zh anr2\nzhanr3 zh anr3\nzhanr4 zh anr4\nzhanr5 zh anr5\nzhang1 zh ang1\nzhang2 zh ang2\nzhang3 zh ang3\nzhang4 zh ang4\nzhang5 zh ang5\nzhangr1 zh angr1\nzhangr2 zh angr2\nzhangr3 zh angr3\nzhangr4 zh angr4\nzhangr5 zh angr5\nzhe1 zh e1\nzhe2 zh e2\nzhe3 zh e3\nzhe4 zh e4\nzhe5 zh e5\nzher1 zh er1\nzher2 zh er2\nzher3 zh er3\nzher4 zh er4\nzher5 zh er5\nzhei1 zh ei1\nzhei2 zh ei2\nzhei3 zh ei3\nzhei4 zh ei4\nzhei5 zh ei5\nzheir1 zh eir1\nzheir2 zh eir2\nzheir3 zh eir3\nzheir4 zh eir4\nzheir5 zh eir5\nzhen1 zh en1\nzhen2 zh en2\nzhen3 zh en3\nzhen4 zh en4\nzhen5 zh en5\nzhenr1 zh enr1\nzhenr2 zh enr2\nzhenr3 zh enr3\nzhenr4 zh enr4\nzhenr5 zh enr5\nzheng1 zh eng1\nzheng2 zh eng2\nzheng3 zh eng3\nzheng4 zh eng4\nzheng5 zh eng5\nzhengr1 zh engr1\nzhengr2 zh engr2\nzhengr3 zh engr3\nzhengr4 zh engr4\nzhengr5 zh engr5\nzhou1 zh ou1\nzhou2 zh ou2\nzhou3 zh ou3\nzhou4 zh ou4\nzhou5 zh ou5\nzhour1 zh our1\nzhour2 zh our2\nzhour3 zh our3\nzhour4 zh our4\nzhour5 zh our5\nzhong1 zh ong1\nzhong2 zh ong2\nzhong3 zh ong3\nzhong4 zh ong4\nzhong5 zh ong5\nzhongr1 zh ongr1\nzhongr2 zh ongr2\nzhongr3 zh ongr3\nzhongr4 zh ongr4\nzhongr5 zh ongr5\nzhi1 zh iii1\nzhi2 zh iii2\nzhi3 zh iii3\nzhi4 zh iii4\nzhi5 zh iii5\nzhir1 zh iiir1\nzhir2 zh iiir2\nzhir3 zh iiir3\nzhir4 zh iiir4\nzhir5 zh iiir5\nzhu1 zh u1\nzhu2 zh u2\nzhu3 zh u3\nzhu4 zh u4\nzhu5 zh u5\nzhur1 zh ur1\nzhur2 zh ur2\nzhur3 zh ur3\nzhur4 zh ur4\nzhur5 zh ur5\nzhua1 zh ua1\nzhua2 zh ua2\nzhua3 zh ua3\nzhua4 zh ua4\nzhua5 zh ua5\nzhuar1 zh uar1\nzhuar2 zh uar2\nzhuar3 zh uar3\nzhuar4 zh uar4\nzhuar5 zh uar5\nzhuai1 zh uai1\nzhuai2 zh uai2\nzhuai3 zh uai3\nzhuai4 zh uai4\nzhuai5 zh uai5\nzhuair1 zh uair1\nzhuair2 zh uair2\nzhuair3 zh uair3\nzhuair4 zh uair4\nzhuair5 zh uair5\nzhuan1 zh uan1\nzhuan2 zh uan2\nzhuan3 zh uan3\nzhuan4 zh uan4\nzhuan5 zh uan5\nzhuanr1 zh uanr1\nzhuanr2 zh uanr2\nzhuanr3 zh uanr3\nzhuanr4 zh uanr4\nzhuanr5 zh uanr5\nzhuang1 zh uang1\nzhuang2 zh uang2\nzhuang3 zh uang3\nzhuang4 zh uang4\nzhuang5 zh uang5\nzhuangr1 zh uangr1\nzhuangr2 zh uangr2\nzhuangr3 zh uangr3\nzhuangr4 zh uangr4\nzhuangr5 zh uangr5\nzhui1 zh uei1\nzhui2 zh uei2\nzhui3 zh uei3\nzhui4 zh uei4\nzhui5 zh uei5\nzhuir1 zh ueir1\nzhuir2 zh ueir2\nzhuir3 zh ueir3\nzhuir4 zh ueir4\nzhuir5 zh ueir5\nzhuo1 zh uo1\nzhuo2 zh uo2\nzhuo3 zh uo3\nzhuo4 zh uo4\nzhuo5 zh uo5\nzhuor1 zh uor1\nzhuor2 zh uor2\nzhuor3 zh uor3\nzhuor4 zh uor4\nzhuor5 zh uor5\nzhun1 zh uen1\nzhun2 zh uen2\nzhun3 zh uen3\nzhun4 zh uen4\nzhun5 zh uen5\nzhunr1 zh uenr1\nzhunr2 zh uenr2\nzhunr3 zh uenr3\nzhunr4 zh uenr4\nzhunr5 zh uenr5\ncha1 ch a1\ncha2 ch a2\ncha3 ch a3\ncha4 ch a4\ncha5 ch a5\nchar1 ch ar1\nchar2 ch ar2\nchar3 ch ar3\nchar4 ch ar4\nchar5 ch ar5\nchai1 ch ai1\nchai2 ch ai2\nchai3 ch ai3\nchai4 ch ai4\nchai5 ch ai5\nchair1 ch air1\nchair2 ch air2\nchair3 ch air3\nchair4 ch air4\nchair5 ch air5\nchao1 ch ao1\nchao2 ch ao2\nchao3 ch ao3\nchao4 ch ao4\nchao5 ch ao5\nchaor1 ch aor1\nchaor2 ch aor2\nchaor3 ch aor3\nchaor4 ch aor4\nchaor5 ch aor5\nchan1 ch an1\nchan2 ch an2\nchan3 ch an3\nchan4 ch an4\nchan5 ch an5\nchanr1 ch anr1\nchanr2 ch anr2\nchanr3 ch anr3\nchanr4 ch anr4\nchanr5 ch anr5\nchang1 ch ang1\nchang2 ch ang2\nchang3 ch ang3\nchang4 ch ang4\nchang5 ch ang5\nchangr1 ch angr1\nchangr2 ch angr2\nchangr3 ch angr3\nchangr4 ch angr4\nchangr5 ch angr5\nche1 ch e1\nche2 ch e2\nche3 ch e3\nche4 ch e4\nche5 ch e5\ncher1 ch er1\ncher2 ch er2\ncher3 ch er3\ncher4 ch er4\ncher5 ch er5\nchei1 ch ei1\nchei2 ch ei2\nchei3 ch ei3\nchei4 ch ei4\nchei5 ch ei5\ncheir1 ch eir1\ncheir2 ch eir2\ncheir3 ch eir3\ncheir4 ch eir4\ncheir5 ch eir5\nchen1 ch en1\nchen2 ch en2\nchen3 ch en3\nchen4 ch en4\nchen5 ch en5\nchenr1 ch enr1\nchenr2 ch enr2\nchenr3 ch enr3\nchenr4 ch enr4\nchenr5 ch enr5\ncheng1 ch eng1\ncheng2 ch eng2\ncheng3 ch eng3\ncheng4 ch eng4\ncheng5 ch eng5\nchengr1 ch engr1\nchengr2 ch engr2\nchengr3 ch engr3\nchengr4 ch engr4\nchengr5 ch engr5\nchou1 ch ou1\nchou2 ch ou2\nchou3 ch ou3\nchou4 ch ou4\nchou5 ch ou5\nchour1 ch our1\nchour2 ch our2\nchour3 ch our3\nchour4 ch our4\nchour5 ch our5\nchong1 ch ong1\nchong2 ch ong2\nchong3 ch ong3\nchong4 ch ong4\nchong5 ch ong5\nchongr1 ch ongr1\nchongr2 ch ongr2\nchongr3 ch ongr3\nchongr4 ch ongr4\nchongr5 ch ongr5\nchi1 ch iii1\nchi2 ch iii2\nchi3 ch iii3\nchi4 ch iii4\nchi5 ch iii5\nchir1 ch iiir1\nchir2 ch iiir2\nchir3 ch iiir3\nchir4 ch iiir4\nchir5 ch iiir5\nchu1 ch u1\nchu2 ch u2\nchu3 ch u3\nchu4 ch u4\nchu5 ch u5\nchur1 ch ur1\nchur2 ch ur2\nchur3 ch ur3\nchur4 ch ur4\nchur5 ch ur5\nchua1 ch ua1\nchua2 ch ua2\nchua3 ch ua3\nchua4 ch ua4\nchua5 ch ua5\nchuar1 ch uar1\nchuar2 ch uar2\nchuar3 ch uar3\nchuar4 ch uar4\nchuar5 ch uar5\nchuai1 ch uai1\nchuai2 ch uai2\nchuai3 ch uai3\nchuai4 ch uai4\nchuai5 ch uai5\nchuair1 ch uair1\nchuair2 ch uair2\nchuair3 ch uair3\nchuair4 ch uair4\nchuair5 ch uair5\nchuan1 ch uan1\nchuan2 ch uan2\nchuan3 ch uan3\nchuan4 ch uan4\nchuan5 ch uan5\nchuanr1 ch uanr1\nchuanr2 ch uanr2\nchuanr3 ch uanr3\nchuanr4 ch uanr4\nchuanr5 ch uanr5\nchuang1 ch uang1\nchuang2 ch uang2\nchuang3 ch uang3\nchuang4 ch uang4\nchuang5 ch uang5\nchuangr1 ch uangr1\nchuangr2 ch uangr2\nchuangr3 ch uangr3\nchuangr4 ch uangr4\nchuangr5 ch uangr5\nchui1 ch uei1\nchui2 ch uei2\nchui3 ch uei3\nchui4 ch uei4\nchui5 ch uei5\nchuir1 ch ueir1\nchuir2 ch ueir2\nchuir3 ch ueir3\nchuir4 ch ueir4\nchuir5 ch ueir5\nchuo1 ch uo1\nchuo2 ch uo2\nchuo3 ch uo3\nchuo4 ch uo4\nchuo5 ch uo5\nchuor1 ch uor1\nchuor2 ch uor2\nchuor3 ch uor3\nchuor4 ch uor4\nchuor5 ch uor5\nchun1 ch uen1\nchun2 ch uen2\nchun3 ch uen3\nchun4 ch uen4\nchun5 ch uen5\nchunr1 ch uenr1\nchunr2 ch uenr2\nchunr3 ch uenr3\nchunr4 ch uenr4\nchunr5 ch uenr5\nsha1 sh a1\nsha2 sh a2\nsha3 sh a3\nsha4 sh a4\nsha5 sh a5\nshar1 sh ar1\nshar2 sh ar2\nshar3 sh ar3\nshar4 sh ar4\nshar5 sh ar5\nshai1 sh ai1\nshai2 sh ai2\nshai3 sh ai3\nshai4 sh ai4\nshai5 sh ai5\nshair1 sh air1\nshair2 sh air2\nshair3 sh air3\nshair4 sh air4\nshair5 sh air5\nshao1 sh ao1\nshao2 sh ao2\nshao3 sh ao3\nshao4 sh ao4\nshao5 sh ao5\nshaor1 sh aor1\nshaor2 sh aor2\nshaor3 sh aor3\nshaor4 sh aor4\nshaor5 sh aor5\nshan1 sh an1\nshan2 sh an2\nshan3 sh an3\nshan4 sh an4\nshan5 sh an5\nshanr1 sh anr1\nshanr2 sh anr2\nshanr3 sh anr3\nshanr4 sh anr4\nshanr5 sh anr5\nshang1 sh ang1\nshang2 sh ang2\nshang3 sh ang3\nshang4 sh ang4\nshang5 sh ang5\nshangr1 sh angr1\nshangr2 sh angr2\nshangr3 sh angr3\nshangr4 sh angr4\nshangr5 sh angr5\nshe1 sh e1\nshe2 sh e2\nshe3 sh e3\nshe4 sh e4\nshe5 sh e5\nsher1 sh er1\nsher2 sh er2\nsher3 sh er3\nsher4 sh er4\nsher5 sh er5\nshei1 sh ei1\nshei2 sh ei2\nshei3 sh ei3\nshei4 sh ei4\nshei5 sh ei5\nsheir1 sh eir1\nsheir2 sh eir2\nsheir3 sh eir3\nsheir4 sh eir4\nsheir5 sh eir5\nshen1 sh en1\nshen2 sh en2\nshen3 sh en3\nshen4 sh en4\nshen5 sh en5\nshenr1 sh enr1\nshenr2 sh enr2\nshenr3 sh enr3\nshenr4 sh enr4\nshenr5 sh enr5\nsheng1 sh eng1\nsheng2 sh eng2\nsheng3 sh eng3\nsheng4 sh eng4\nsheng5 sh eng5\nshengr1 sh engr1\nshengr2 sh engr2\nshengr3 sh engr3\nshengr4 sh engr4\nshengr5 sh engr5\nshou1 sh ou1\nshou2 sh ou2\nshou3 sh ou3\nshou4 sh ou4\nshou5 sh ou5\nshour1 sh our1\nshour2 sh our2\nshour3 sh our3\nshour4 sh our4\nshour5 sh our5\nshi1 sh iii1\nshi2 sh iii2\nshi3 sh iii3\nshi4 sh iii4\nshi5 sh iii5\nshir1 sh iiir1\nshir2 sh iiir2\nshir3 sh iiir3\nshir4 sh iiir4\nshir5 sh iiir5\nshu1 sh u1\nshu2 sh u2\nshu3 sh u3\nshu4 sh u4\nshu5 sh u5\nshur1 sh ur1\nshur2 sh ur2\nshur3 sh ur3\nshur4 sh ur4\nshur5 sh ur5\nshua1 sh ua1\nshua2 sh ua2\nshua3 sh ua3\nshua4 sh ua4\nshua5 sh ua5\nshuar1 sh uar1\nshuar2 sh uar2\nshuar3 sh uar3\nshuar4 sh uar4\nshuar5 sh uar5\nshuai1 sh uai1\nshuai2 sh uai2\nshuai3 sh uai3\nshuai4 sh uai4\nshuai5 sh uai5\nshuair1 sh uair1\nshuair2 sh uair2\nshuair3 sh uair3\nshuair4 sh uair4\nshuair5 sh uair5\nshuan1 sh uan1\nshuan2 sh uan2\nshuan3 sh uan3\nshuan4 sh uan4\nshuan5 sh uan5\nshuanr1 sh uanr1\nshuanr2 sh uanr2\nshuanr3 sh uanr3\nshuanr4 sh uanr4\nshuanr5 sh uanr5\nshuang1 sh uang1\nshuang2 sh uang2\nshuang3 sh uang3\nshuang4 sh uang4\nshuang5 sh uang5\nshuangr1 sh uangr1\nshuangr2 sh uangr2\nshuangr3 sh uangr3\nshuangr4 sh uangr4\nshuangr5 sh uangr5\nshui1 sh uei1\nshui2 sh uei2\nshui3 sh uei3\nshui4 sh uei4\nshui5 sh uei5\nshuir1 sh ueir1\nshuir2 sh ueir2\nshuir3 sh ueir3\nshuir4 sh ueir4\nshuir5 sh ueir5\nshuo1 sh uo1\nshuo2 sh uo2\nshuo3 sh uo3\nshuo4 sh uo4\nshuo5 sh uo5\nshuor1 sh uor1\nshuor2 sh uor2\nshuor3 sh uor3\nshuor4 sh uor4\nshuor5 sh uor5\nshun1 sh uen1\nshun2 sh uen2\nshun3 sh uen3\nshun4 sh uen4\nshun5 sh uen5\nshunr1 sh uenr1\nshunr2 sh uenr2\nshunr3 sh uenr3\nshunr4 sh uenr4\nshunr5 sh uenr5\nra1 r a1\nra2 r a2\nra3 r a3\nra4 r a4\nra5 r a5\nrar1 r ar1\nrar2 r ar2\nrar3 r ar3\nrar4 r ar4\nrar5 r ar5\nrai1 r ai1\nrai2 r ai2\nrai3 r ai3\nrai4 r ai4\nrai5 r ai5\nrair1 r air1\nrair2 r air2\nrair3 r air3\nrair4 r air4\nrair5 r air5\nrao1 r ao1\nrao2 r ao2\nrao3 r ao3\nrao4 r ao4\nrao5 r ao5\nraor1 r aor1\nraor2 r aor2\nraor3 r aor3\nraor4 r aor4\nraor5 r aor5\nran1 r an1\nran2 r an2\nran3 r an3\nran4 r an4\nran5 r an5\nranr1 r anr1\nranr2 r anr2\nranr3 r anr3\nranr4 r anr4\nranr5 r anr5\nrang1 r ang1\nrang2 r ang2\nrang3 r ang3\nrang4 r ang4\nrang5 r ang5\nrangr1 r angr1\nrangr2 r angr2\nrangr3 r angr3\nrangr4 r angr4\nrangr5 r angr5\nre1 r e1\nre2 r e2\nre3 r e3\nre4 r e4\nre5 r e5\nrer1 r er1\nrer2 r er2\nrer3 r er3\nrer4 r er4\nrer5 r er5\nrei1 r ei1\nrei2 r ei2\nrei3 r ei3\nrei4 r ei4\nrei5 r ei5\nreir1 r eir1\nreir2 r eir2\nreir3 r eir3\nreir4 r eir4\nreir5 r eir5\nren1 r en1\nren2 r en2\nren3 r en3\nren4 r en4\nren5 r en5\nrenr1 r enr1\nrenr2 r enr2\nrenr3 r enr3\nrenr4 r enr4\nrenr5 r enr5\nreng1 r eng1\nreng2 r eng2\nreng3 r eng3\nreng4 r eng4\nreng5 r eng5\nrengr1 r engr1\nrengr2 r engr2\nrengr3 r engr3\nrengr4 r engr4\nrengr5 r engr5\nrou1 r ou1\nrou2 r ou2\nrou3 r ou3\nrou4 r ou4\nrou5 r ou5\nrour1 r our1\nrour2 r our2\nrour3 r our3\nrour4 r our4\nrour5 r our5\nrong1 r ong1\nrong2 r ong2\nrong3 r ong3\nrong4 r ong4\nrong5 r ong5\nrongr1 r ongr1\nrongr2 r ongr2\nrongr3 r ongr3\nrongr4 r ongr4\nrongr5 r ongr5\nri1 r iii1\nri2 r iii2\nri3 r iii3\nri4 r iii4\nri5 r iii5\nrir1 r iiir1\nrir2 r iiir2\nrir3 r iiir3\nrir4 r iiir4\nrir5 r iiir5\nru1 r u1\nru2 r u2\nru3 r u3\nru4 r u4\nru5 r u5\nrur1 r ur1\nrur2 r ur2\nrur3 r ur3\nrur4 r ur4\nrur5 r ur5\nruan1 r uan1\nruan2 r uan2\nruan3 r uan3\nruan4 r uan4\nruan5 r uan5\nruanr1 r uanr1\nruanr2 r uanr2\nruanr3 r uanr3\nruanr4 r uanr4\nruanr5 r uanr5\nrui1 r uei1\nrui2 r uei2\nrui3 r uei3\nrui4 r uei4\nrui5 r uei5\nruir1 r ueir1\nruir2 r ueir2\nruir3 r ueir3\nruir4 r ueir4\nruir5 r ueir5\nruo1 r uo1\nruo2 r uo2\nruo3 r uo3\nruo4 r uo4\nruo5 r uo5\nruor1 r uor1\nruor2 r uor2\nruor3 r uor3\nruor4 r uor4\nruor5 r uor5\nrun1 r uen1\nrun2 r uen2\nrun3 r uen3\nrun4 r uen4\nrun5 r uen5\nrunr1 r uenr1\nrunr2 r uenr2\nrunr3 r uenr3\nrunr4 r uenr4\nrunr5 r uenr5\nza1 z a1\nza2 z a2\nza3 z a3\nza4 z a4\nza5 z a5\nzar1 z ar1\nzar2 z ar2\nzar3 z ar3\nzar4 z ar4\nzar5 z ar5\nzai1 z ai1\nzai2 z ai2\nzai3 z ai3\nzai4 z ai4\nzai5 z ai5\nzair1 z air1\nzair2 z air2\nzair3 z air3\nzair4 z air4\nzair5 z air5\nzao1 z ao1\nzao2 z ao2\nzao3 z ao3\nzao4 z ao4\nzao5 z ao5\nzaor1 z aor1\nzaor2 z aor2\nzaor3 z aor3\nzaor4 z aor4\nzaor5 z aor5\nzan1 z an1\nzan2 z an2\nzan3 z an3\nzan4 z an4\nzan5 z an5\nzanr1 z anr1\nzanr2 z anr2\nzanr3 z anr3\nzanr4 z anr4\nzanr5 z anr5\nzang1 z ang1\nzang2 z ang2\nzang3 z ang3\nzang4 z ang4\nzang5 z ang5\nzangr1 z angr1\nzangr2 z angr2\nzangr3 z angr3\nzangr4 z angr4\nzangr5 z angr5\nze1 z e1\nze2 z e2\nze3 z e3\nze4 z e4\nze5 z e5\nzer1 z er1\nzer2 z er2\nzer3 z er3\nzer4 z er4\nzer5 z er5\nzei1 z ei1\nzei2 z ei2\nzei3 z ei3\nzei4 z ei4\nzei5 z ei5\nzeir1 z eir1\nzeir2 z eir2\nzeir3 z eir3\nzeir4 z eir4\nzeir5 z eir5\nzen1 z en1\nzen2 z en2\nzen3 z en3\nzen4 z en4\nzen5 z en5\nzenr1 z enr1\nzenr2 z enr2\nzenr3 z enr3\nzenr4 z enr4\nzenr5 z enr5\nzeng1 z eng1\nzeng2 z eng2\nzeng3 z eng3\nzeng4 z eng4\nzeng5 z eng5\nzengr1 z engr1\nzengr2 z engr2\nzengr3 z engr3\nzengr4 z engr4\nzengr5 z engr5\nzou1 z ou1\nzou2 z ou2\nzou3 z ou3\nzou4 z ou4\nzou5 z ou5\nzour1 z our1\nzour2 z our2\nzour3 z our3\nzour4 z our4\nzour5 z our5\nzong1 z ong1\nzong2 z ong2\nzong3 z ong3\nzong4 z ong4\nzong5 z ong5\nzongr1 z ongr1\nzongr2 z ongr2\nzongr3 z ongr3\nzongr4 z ongr4\nzongr5 z ongr5\nzi1 z ii1\nzi2 z ii2\nzi3 z ii3\nzi4 z ii4\nzi5 z ii5\nzir1 z iir1\nzir2 z iir2\nzir3 z iir3\nzir4 z iir4\nzir5 z iir5\nzu1 z u1\nzu2 z u2\nzu3 z u3\nzu4 z u4\nzu5 z u5\nzur1 z ur1\nzur2 z ur2\nzur3 z ur3\nzur4 z ur4\nzur5 z ur5\nzuan1 z uan1\nzuan2 z uan2\nzuan3 z uan3\nzuan4 z uan4\nzuan5 z uan5\nzuanr1 z uanr1\nzuanr2 z uanr2\nzuanr3 z uanr3\nzuanr4 z uanr4\nzuanr5 z uanr5\nzui1 z uei1\nzui2 z uei2\nzui3 z uei3\nzui4 z uei4\nzui5 z uei5\nzuir1 z ueir1\nzuir2 z ueir2\nzuir3 z ueir3\nzuir4 z ueir4\nzuir5 z ueir5\nzuo1 z uo1\nzuo2 z uo2\nzuo3 z uo3\nzuo4 z uo4\nzuo5 z uo5\nzuor1 z uor1\nzuor2 z uor2\nzuor3 z uor3\nzuor4 z uor4\nzuor5 z uor5\nzun1 z uen1\nzun2 z uen2\nzun3 z uen3\nzun4 z uen4\nzun5 z uen5\nzunr1 z uenr1\nzunr2 z uenr2\nzunr3 z uenr3\nzunr4 z uenr4\nzunr5 z uenr5\nca1 c a1\nca2 c a2\nca3 c a3\nca4 c a4\nca5 c a5\ncar1 c ar1\ncar2 c ar2\ncar3 c ar3\ncar4 c ar4\ncar5 c ar5\ncai1 c ai1\ncai2 c ai2\ncai3 c ai3\ncai4 c ai4\ncai5 c ai5\ncair1 c air1\ncair2 c air2\ncair3 c air3\ncair4 c air4\ncair5 c air5\ncao1 c ao1\ncao2 c ao2\ncao3 c ao3\ncao4 c ao4\ncao5 c ao5\ncaor1 c aor1\ncaor2 c aor2\ncaor3 c aor3\ncaor4 c aor4\ncaor5 c aor5\ncan1 c an1\ncan2 c an2\ncan3 c an3\ncan4 c an4\ncan5 c an5\ncanr1 c anr1\ncanr2 c anr2\ncanr3 c anr3\ncanr4 c anr4\ncanr5 c anr5\ncang1 c ang1\ncang2 c ang2\ncang3 c ang3\ncang4 c ang4\ncang5 c ang5\ncangr1 c angr1\ncangr2 c angr2\ncangr3 c angr3\ncangr4 c angr4\ncangr5 c angr5\nce1 c e1\nce2 c e2\nce3 c e3\nce4 c e4\nce5 c e5\ncer1 c er1\ncer2 c er2\ncer3 c er3\ncer4 c er4\ncer5 c er5\ncei1 c ei1\ncei2 c ei2\ncei3 c ei3\ncei4 c ei4\ncei5 c ei5\nceir1 c eir1\nceir2 c eir2\nceir3 c eir3\nceir4 c eir4\nceir5 c eir5\ncen1 c en1\ncen2 c en2\ncen3 c en3\ncen4 c en4\ncen5 c en5\ncenr1 c enr1\ncenr2 c enr2\ncenr3 c enr3\ncenr4 c enr4\ncenr5 c enr5\nceng1 c eng1\nceng2 c eng2\nceng3 c eng3\nceng4 c eng4\nceng5 c eng5\ncengr1 c engr1\ncengr2 c engr2\ncengr3 c engr3\ncengr4 c engr4\ncengr5 c engr5\ncou1 c ou1\ncou2 c ou2\ncou3 c ou3\ncou4 c ou4\ncou5 c ou5\ncour1 c our1\ncour2 c our2\ncour3 c our3\ncour4 c our4\ncour5 c our5\ncong1 c ong1\ncong2 c ong2\ncong3 c ong3\ncong4 c ong4\ncong5 c ong5\ncongr1 c ongr1\ncongr2 c ongr2\ncongr3 c ongr3\ncongr4 c ongr4\ncongr5 c ongr5\nci1 c ii1\nci2 c ii2\nci3 c ii3\nci4 c ii4\nci5 c ii5\ncir1 c iir1\ncir2 c iir2\ncir3 c iir3\ncir4 c iir4\ncir5 c iir5\ncu1 c u1\ncu2 c u2\ncu3 c u3\ncu4 c u4\ncu5 c u5\ncur1 c ur1\ncur2 c ur2\ncur3 c ur3\ncur4 c ur4\ncur5 c ur5\ncuan1 c uan1\ncuan2 c uan2\ncuan3 c uan3\ncuan4 c uan4\ncuan5 c uan5\ncuanr1 c uanr1\ncuanr2 c uanr2\ncuanr3 c uanr3\ncuanr4 c uanr4\ncuanr5 c uanr5\ncui1 c uei1\ncui2 c uei2\ncui3 c uei3\ncui4 c uei4\ncui5 c uei5\ncuir1 c ueir1\ncuir2 c ueir2\ncuir3 c ueir3\ncuir4 c ueir4\ncuir5 c ueir5\ncuo1 c uo1\ncuo2 c uo2\ncuo3 c uo3\ncuo4 c uo4\ncuo5 c uo5\ncuor1 c uor1\ncuor2 c uor2\ncuor3 c uor3\ncuor4 c uor4\ncuor5 c uor5\ncun1 c uen1\ncun2 c uen2\ncun3 c uen3\ncun4 c uen4\ncun5 c uen5\ncunr1 c uenr1\ncunr2 c uenr2\ncunr3 c uenr3\ncunr4 c uenr4\ncunr5 c uenr5\nsa1 s a1\nsa2 s a2\nsa3 s a3\nsa4 s a4\nsa5 s a5\nsar1 s ar1\nsar2 s ar2\nsar3 s ar3\nsar4 s ar4\nsar5 s ar5\nsai1 s ai1\nsai2 s ai2\nsai3 s ai3\nsai4 s ai4\nsai5 s ai5\nsair1 s air1\nsair2 s air2\nsair3 s air3\nsair4 s air4\nsair5 s air5\nsao1 s ao1\nsao2 s ao2\nsao3 s ao3\nsao4 s ao4\nsao5 s ao5\nsaor1 s aor1\nsaor2 s aor2\nsaor3 s aor3\nsaor4 s aor4\nsaor5 s aor5\nsan1 s an1\nsan2 s an2\nsan3 s an3\nsan4 s an4\nsan5 s an5\nsanr1 s anr1\nsanr2 s anr2\nsanr3 s anr3\nsanr4 s anr4\nsanr5 s anr5\nsang1 s ang1\nsang2 s ang2\nsang3 s ang3\nsang4 s ang4\nsang5 s ang5\nsangr1 s angr1\nsangr2 s angr2\nsangr3 s angr3\nsangr4 s angr4\nsangr5 s angr5\nse1 s e1\nse2 s e2\nse3 s e3\nse4 s e4\nse5 s e5\nser1 s er1\nser2 s er2\nser3 s er3\nser4 s er4\nser5 s er5\nsei1 s ei1\nsei2 s ei2\nsei3 s ei3\nsei4 s ei4\nsei5 s ei5\nseir1 s eir1\nseir2 s eir2\nseir3 s eir3\nseir4 s eir4\nseir5 s eir5\nsen1 s en1\nsen2 s en2\nsen3 s en3\nsen4 s en4\nsen5 s en5\nsenr1 s enr1\nsenr2 s enr2\nsenr3 s enr3\nsenr4 s enr4\nsenr5 s enr5\nseng1 s eng1\nseng2 s eng2\nseng3 s eng3\nseng4 s eng4\nseng5 s eng5\nsengr1 s engr1\nsengr2 s engr2\nsengr3 s engr3\nsengr4 s engr4\nsengr5 s engr5\nsou1 s ou1\nsou2 s ou2\nsou3 s ou3\nsou4 s ou4\nsou5 s ou5\nsour1 s our1\nsour2 s our2\nsour3 s our3\nsour4 s our4\nsour5 s our5\nsong1 s ong1\nsong2 s ong2\nsong3 s ong3\nsong4 s ong4\nsong5 s ong5\nsongr1 s ongr1\nsongr2 s ongr2\nsongr3 s ongr3\nsongr4 s ongr4\nsongr5 s ongr5\nsi1 s ii1\nsi2 s ii2\nsi3 s ii3\nsi4 s ii4\nsi5 s ii5\nsir1 s iir1\nsir2 s iir2\nsir3 s iir3\nsir4 s iir4\nsir5 s iir5\nsu1 s u1\nsu2 s u2\nsu3 s u3\nsu4 s u4\nsu5 s u5\nsur1 s ur1\nsur2 s ur2\nsur3 s ur3\nsur4 s ur4\nsur5 s ur5\nsuan1 s uan1\nsuan2 s uan2\nsuan3 s uan3\nsuan4 s uan4\nsuan5 s uan5\nsuanr1 s uanr1\nsuanr2 s uanr2\nsuanr3 s uanr3\nsuanr4 s uanr4\nsuanr5 s uanr5\nsui1 s uei1\nsui2 s uei2\nsui3 s uei3\nsui4 s uei4\nsui5 s uei5\nsuir1 s ueir1\nsuir2 s ueir2\nsuir3 s ueir3\nsuir4 s ueir4\nsuir5 s ueir5\nsuo1 s uo1\nsuo2 s uo2\nsuo3 s uo3\nsuo4 s uo4\nsuo5 s uo5\nsuor1 s uor1\nsuor2 s uor2\nsuor3 s uor3\nsuor4 s uor4\nsuor5 s uor5\nsun1 s uen1\nsun2 s uen2\nsun3 s uen3\nsun4 s uen4\nsun5 s uen5\nsunr1 s uenr1\nsunr2 s uenr2\nsunr3 s uenr3\nsunr4 s uenr4\nsunr5 s uenr5\nji1 j i1\nji2 j i2\nji3 j i3\nji4 j i4\nji5 j i5\njir1 j ir1\njir2 j ir2\njir3 j ir3\njir4 j ir4\njir5 j ir5\njia1 j ia1\njia2 j ia2\njia3 j ia3\njia4 j ia4\njia5 j ia5\njiar1 j iar1\njiar2 j iar2\njiar3 j iar3\njiar4 j iar4\njiar5 j iar5\njiao1 j iao1\njiao2 j iao2\njiao3 j iao3\njiao4 j iao4\njiao5 j iao5\njiaor1 j iaor1\njiaor2 j iaor2\njiaor3 j iaor3\njiaor4 j iaor4\njiaor5 j iaor5\njian1 j ian1\njian2 j ian2\njian3 j ian3\njian4 j ian4\njian5 j ian5\njianr1 j ianr1\njianr2 j ianr2\njianr3 j ianr3\njianr4 j ianr4\njianr5 j ianr5\njiang1 j iang1\njiang2 j iang2\njiang3 j iang3\njiang4 j iang4\njiang5 j iang5\njiangr1 j iangr1\njiangr2 j iangr2\njiangr3 j iangr3\njiangr4 j iangr4\njiangr5 j iangr5\njie1 j ie1\njie2 j ie2\njie3 j ie3\njie4 j ie4\njie5 j ie5\njier1 j ier1\njier2 j ier2\njier3 j ier3\njier4 j ier4\njier5 j ier5\njio1 j io1\njio2 j io2\njio3 j io3\njio4 j io4\njio5 j io5\njior1 j ior1\njior2 j ior2\njior3 j ior3\njior4 j ior4\njior5 j ior5\njiu1 j iou1\njiu2 j iou2\njiu3 j iou3\njiu4 j iou4\njiu5 j iou5\njiur1 j iour1\njiur2 j iour2\njiur3 j iour3\njiur4 j iour4\njiur5 j iour5\njiong1 j iong1\njiong2 j iong2\njiong3 j iong3\njiong4 j iong4\njiong5 j iong5\njiongr1 j iongr1\njiongr2 j iongr2\njiongr3 j iongr3\njiongr4 j iongr4\njiongr5 j iongr5\njin1 j in1\njin2 j in2\njin3 j in3\njin4 j in4\njin5 j in5\njinr1 j inr1\njinr2 j inr2\njinr3 j inr3\njinr4 j inr4\njinr5 j inr5\njing1 j ing1\njing2 j ing2\njing3 j ing3\njing4 j ing4\njing5 j ing5\njingr1 j ingr1\njingr2 j ingr2\njingr3 j ingr3\njingr4 j ingr4\njingr5 j ingr5\nju1 j v1\nju2 j v2\nju3 j v3\nju4 j v4\nju5 j v5\njur1 j vr1\njur2 j vr2\njur3 j vr3\njur4 j vr4\njur5 j vr5\njue1 j ve1\njue2 j ve2\njue3 j ve3\njue4 j ve4\njue5 j ve5\njuer1 j ver1\njuer2 j ver2\njuer3 j ver3\njuer4 j ver4\njuer5 j ver5\njuan1 j van1\njuan2 j van2\njuan3 j van3\njuan4 j van4\njuan5 j van5\njuanr1 j vanr1\njuanr2 j vanr2\njuanr3 j vanr3\njuanr4 j vanr4\njuanr5 j vanr5\njun1 j vn1\njun2 j vn2\njun3 j vn3\njun4 j vn4\njun5 j vn5\njunr1 j vnr1\njunr2 j vnr2\njunr3 j vnr3\njunr4 j vnr4\njunr5 j vnr5\nqi1 q i1\nqi2 q i2\nqi3 q i3\nqi4 q i4\nqi5 q i5\nqir1 q ir1\nqir2 q ir2\nqir3 q ir3\nqir4 q ir4\nqir5 q ir5\nqia1 q ia1\nqia2 q ia2\nqia3 q ia3\nqia4 q ia4\nqia5 q ia5\nqiar1 q iar1\nqiar2 q iar2\nqiar3 q iar3\nqiar4 q iar4\nqiar5 q iar5\nqiao1 q iao1\nqiao2 q iao2\nqiao3 q iao3\nqiao4 q iao4\nqiao5 q iao5\nqiaor1 q iaor1\nqiaor2 q iaor2\nqiaor3 q iaor3\nqiaor4 q iaor4\nqiaor5 q iaor5\nqian1 q ian1\nqian2 q ian2\nqian3 q ian3\nqian4 q ian4\nqian5 q ian5\nqianr1 q ianr1\nqianr2 q ianr2\nqianr3 q ianr3\nqianr4 q ianr4\nqianr5 q ianr5\nqiang1 q iang1\nqiang2 q iang2\nqiang3 q iang3\nqiang4 q iang4\nqiang5 q iang5\nqiangr1 q iangr1\nqiangr2 q iangr2\nqiangr3 q iangr3\nqiangr4 q iangr4\nqiangr5 q iangr5\nqie1 q ie1\nqie2 q ie2\nqie3 q ie3\nqie4 q ie4\nqie5 q ie5\nqier1 q ier1\nqier2 q ier2\nqier3 q ier3\nqier4 q ier4\nqier5 q ier5\nqio1 q io1\nqio2 q io2\nqio3 q io3\nqio4 q io4\nqio5 q io5\nqior1 q ior1\nqior2 q ior2\nqior3 q ior3\nqior4 q ior4\nqior5 q ior5\nqiu1 q iou1\nqiu2 q iou2\nqiu3 q iou3\nqiu4 q iou4\nqiu5 q iou5\nqiur1 q iour1\nqiur2 q iour2\nqiur3 q iour3\nqiur4 q iour4\nqiur5 q iour5\nqiong1 q iong1\nqiong2 q iong2\nqiong3 q iong3\nqiong4 q iong4\nqiong5 q iong5\nqiongr1 q iongr1\nqiongr2 q iongr2\nqiongr3 q iongr3\nqiongr4 q iongr4\nqiongr5 q iongr5\nqin1 q in1\nqin2 q in2\nqin3 q in3\nqin4 q in4\nqin5 q in5\nqinr1 q inr1\nqinr2 q inr2\nqinr3 q inr3\nqinr4 q inr4\nqinr5 q inr5\nqing1 q ing1\nqing2 q ing2\nqing3 q ing3\nqing4 q ing4\nqing5 q ing5\nqingr1 q ingr1\nqingr2 q ingr2\nqingr3 q ingr3\nqingr4 q ingr4\nqingr5 q ingr5\nqu1 q v1\nqu2 q v2\nqu3 q v3\nqu4 q v4\nqu5 q v5\nqur1 q vr1\nqur2 q vr2\nqur3 q vr3\nqur4 q vr4\nqur5 q vr5\nque1 q ve1\nque2 q ve2\nque3 q ve3\nque4 q ve4\nque5 q ve5\nquer1 q ver1\nquer2 q ver2\nquer3 q ver3\nquer4 q ver4\nquer5 q ver5\nquan1 q van1\nquan2 q van2\nquan3 q van3\nquan4 q van4\nquan5 q van5\nquanr1 q vanr1\nquanr2 q vanr2\nquanr3 q vanr3\nquanr4 q vanr4\nquanr5 q vanr5\nqun1 q vn1\nqun2 q vn2\nqun3 q vn3\nqun4 q vn4\nqun5 q vn5\nqunr1 q vnr1\nqunr2 q vnr2\nqunr3 q vnr3\nqunr4 q vnr4\nqunr5 q vnr5\nxi1 x i1\nxi2 x i2\nxi3 x i3\nxi4 x i4\nxi5 x i5\nxir1 x ir1\nxir2 x ir2\nxir3 x ir3\nxir4 x ir4\nxir5 x ir5\nxia1 x ia1\nxia2 x ia2\nxia3 x ia3\nxia4 x ia4\nxia5 x ia5\nxiar1 x iar1\nxiar2 x iar2\nxiar3 x iar3\nxiar4 x iar4\nxiar5 x iar5\nxiao1 x iao1\nxiao2 x iao2\nxiao3 x iao3\nxiao4 x iao4\nxiao5 x iao5\nxiaor1 x iaor1\nxiaor2 x iaor2\nxiaor3 x iaor3\nxiaor4 x iaor4\nxiaor5 x iaor5\nxian1 x ian1\nxian2 x ian2\nxian3 x ian3\nxian4 x ian4\nxian5 x ian5\nxianr1 x ianr1\nxianr2 x ianr2\nxianr3 x ianr3\nxianr4 x ianr4\nxianr5 x ianr5\nxiang1 x iang1\nxiang2 x iang2\nxiang3 x iang3\nxiang4 x iang4\nxiang5 x iang5\nxiangr1 x iangr1\nxiangr2 x iangr2\nxiangr3 x iangr3\nxiangr4 x iangr4\nxiangr5 x iangr5\nxie1 x ie1\nxie2 x ie2\nxie3 x ie3\nxie4 x ie4\nxie5 x ie5\nxier1 x ier1\nxier2 x ier2\nxier3 x ier3\nxier4 x ier4\nxier5 x ier5\nxio1 x io1\nxio2 x io2\nxio3 x io3\nxio4 x io4\nxio5 x io5\nxior1 x ior1\nxior2 x ior2\nxior3 x ior3\nxior4 x ior4\nxior5 x ior5\nxiu1 x iou1\nxiu2 x iou2\nxiu3 x iou3\nxiu4 x iou4\nxiu5 x iou5\nxiur1 x iour1\nxiur2 x iour2\nxiur3 x iour3\nxiur4 x iour4\nxiur5 x iour5\nxiong1 x iong1\nxiong2 x iong2\nxiong3 x iong3\nxiong4 x iong4\nxiong5 x iong5\nxiongr1 x iongr1\nxiongr2 x iongr2\nxiongr3 x iongr3\nxiongr4 x iongr4\nxiongr5 x iongr5\nxin1 x in1\nxin2 x in2\nxin3 x in3\nxin4 x in4\nxin5 x in5\nxinr1 x inr1\nxinr2 x inr2\nxinr3 x inr3\nxinr4 x inr4\nxinr5 x inr5\nxing1 x ing1\nxing2 x ing2\nxing3 x ing3\nxing4 x ing4\nxing5 x ing5\nxingr1 x ingr1\nxingr2 x ingr2\nxingr3 x ingr3\nxingr4 x ingr4\nxingr5 x ingr5\nxu1 x v1\nxu2 x v2\nxu3 x v3\nxu4 x v4\nxu5 x v5\nxur1 x vr1\nxur2 x vr2\nxur3 x vr3\nxur4 x vr4\nxur5 x vr5\nxue1 x ve1\nxue2 x ve2\nxue3 x ve3\nxue4 x ve4\nxue5 x ve5\nxuer1 x ver1\nxuer2 x ver2\nxuer3 x ver3\nxuer4 x ver4\nxuer5 x ver5\nxuan1 x van1\nxuan2 x van2\nxuan3 x van3\nxuan4 x van4\nxuan5 x van5\nxuanr1 x vanr1\nxuanr2 x vanr2\nxuanr3 x vanr3\nxuanr4 x vanr4\nxuanr5 x vanr5\nxun1 x vn1\nxun2 x vn2\nxun3 x vn3\nxun4 x vn4\nxun5 x vn5\nxunr1 x vnr1\nxunr2 x vnr2\nxunr3 x vnr3\nxunr4 x vnr4\nxunr5 x vnr5\n"
  },
  {
    "path": "examples/csmsc/tts3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt || exit -1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/synthesize_e2e_xpu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/synthesize_streaming.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_streaming.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True \\\n        --inference_dir=${train_output_path}/inference_streaming\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_streaming.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True \\\n        --inference_dir=${train_output_path}/inference_streaming\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_streaming.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_streaming.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e_streaming \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --am_streaming=True \\\n        --inference_dir=${train_output_path}/inference_streaming\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/synthesize_xpu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# style melgan\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --ngpu=0 \\\n        --nxpu=1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --phones-dict=dump/phone_id_map.txt"
  },
  {
    "path": "examples/csmsc/tts3/local/train_xpu.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=0 \\\n    --nxpu=1 \\\n    --phones-dict=dump/phone_id_map.txt"
  },
  {
    "path": "examples/csmsc/tts3/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=fastspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/csmsc/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0\n    # use 1-4 to select the vocoder in {multi band melgan, style melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0\n    # use 1,3,4 to select the vocoder in {multi band melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# we have only tested the following models so far\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_csmsc\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\n    \nfi\n\n# inference with onnxruntime\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    # NOTE by yuantian 2022.11.21: please compile develop version of Paddle-Lite to export and run TTS models,\n    #                   cause TTS models are supported by https://github.com/PaddlePaddle/Paddle-Lite/pull/9587 \n    #                   and https://github.com/PaddlePaddle/Paddle-Lite/pull/9706\n    ./local/export2lite.sh ${train_output_path} inference pdlite fastspeech2_csmsc x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite mb_melgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_csmsc x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n\n# PTQ_dynamic\nif [ ${stage} -le 9 ] && [ ${stop_stage} -ge 9 ]; then\n    ./local/PTQ_dynamic.sh  ${train_output_path} fastspeech2_csmsc 8\n    # ./local/PTQ_dynamic.sh  ${train_output_path} pwgan_csmsc 8\n    # ./local/PTQ_dynamic.sh  ${train_output_path} mb_melgan_csmsc 8\n    # ./local/PTQ_dynamic.sh  ${train_output_path} hifigan_csmsc 8\nfi\n\n# PTQ_static\nif [ ${stage} -le 10 ] && [ ${stop_stage} -ge 10 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} fastspeech2_csmsc || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3/run_cnndecoder.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/cnndecoder.yaml\ntrain_output_path=exp/cnndecoder\nckpt_name=snapshot_iter_153.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# synthesize_e2e non-streaming\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# inference non-streaming\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n# synthesize_e2e streaming\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_streaming.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# inference streaming\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference_streaming.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx non streaming\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_csmsc\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\nfi\n\n# onnxruntime non streaming\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# paddle2onnx streaming\nif [ ${stage} -le 9 ] && [ ${stop_stage} -ge 9 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    # streaming acoustic model\n    ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming fastspeech2_csmsc_am_encoder_infer\n    ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming fastspeech2_csmsc_am_decoder\n    ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming fastspeech2_csmsc_am_postnet\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming pwgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming mb_melgan_csmsc\n    # ./local/paddle2onnx.sh ${train_output_path} inference_streaming inference_onnx_streaming hifigan_csmsc\nfi\n\n# onnxruntime streaming\nif [ ${stage} -le 10 ] && [ ${stop_stage} -ge 10 ]; then\n    ./local/ort_predict_streaming.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 11 ] && [ ${stop_stage} -ge 11 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite fastspeech2_csmsc x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite mb_melgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_csmsc x86\nfi\n\nif [ ${stage} -le 12 ] && [ ${stop_stage} -ge 12 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n\n# must run after stage 5 (which stage generated static models)\nif [ ${stage} -le 13 ] && [ ${stop_stage} -ge 13 ]; then\n    # streaming acoustic model\n    ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming fastspeech2_csmsc_am_encoder_infer x86\n    ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming fastspeech2_csmsc_am_decoder x86\n    ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming fastspeech2_csmsc_am_postnet x86\n    ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming pwgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming mb_melgan_csmsc x86\n    # ./local/export2lite.sh ${train_output_path} inference_streaming pdlite_streaming hifigan_csmsc x86\nfi\n\nif [ ${stage} -le 14 ] && [ ${stop_stage} -ge 14 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict_streaming.sh ${train_output_path} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 15 ] && [ ${stop_stage} -ge 15 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} fastspeech2_csmsc || exit -1\nfi"
  },
  {
    "path": "examples/csmsc/tts3/run_xpu.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\nxpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    FLAGS_selected_xpus=${xpus} ./local/train_xpu.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    FLAGS_selected_xpus=${xpus} ./local/synthesize_xpu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    FLAGS_selected_xpus=${xpus} ./local/synthesize_e2e_xpu.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    FLAGS_selected_xpus=${xpus} ./local/inference_xpu.sh ${train_output_path} || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3_rhy/README.md",
    "content": "# This example mainly follows the FastSpeech2 with CSMSC\nThis example contains code used to train a rhythm version of [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [Official Website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for fastspeech2.\nYou can directly download the rhythm version of MFA result from here [baker_alignment_tone.zip](https://paddlespeech.cdn.bcebos.com/Rhy_e2e/baker_alignment_tone.zip), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\nRemember in our repo, you should add `--rhy-with-duration` flag to obtain the rhythm information.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n5. inference using the static model.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and the id of each utterance.\n\n# For more details, You can refer to [FastSpeech2 with CSMSC](../tts3)\n\n## Pretrained Model\nPretrained FastSpeech2 model for end-to-end rhythm version:\n- [fastspeech2_rhy_csmsc_ckpt_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_rhy_csmsc_ckpt_1.3.0.zip)\n\nThis FastSpeech2 checkpoint contains files listed below.\n```text\nfastspeech2_rhy_csmsc_ckpt_1.3.0\n├── default.yaml             # default config used to train fastspeech2\n├── phone_id_map.txt         # phone vocabulary file when training fastspeech2\n├── snapshot_iter_153000.pdz # model parameters and optimizer states\n├── durations.txt            # the intermediate output of preprocess.sh\n├── energy_stats.npy\n├── pitch_stats.npy\n└── speech_stats.npy         # statistics used to normalize spectrogram when training fastspeech2\n```\n"
  },
  {
    "path": "examples/csmsc/tts3_rhy/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_csmsc \\\n        --voc_config=pwg_baker_ckpt_0.4/pwg_default.yaml \\\n        --voc_ckpt=pwg_baker_ckpt_0.4/pwg_snapshot_iter_400000.pdz \\\n        --voc_stat=pwg_baker_ckpt_0.4/pwg_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --use_rhy=True\nfi\n\n# for more GAN Vocoders\n# multi band melgan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=mb_melgan_csmsc \\\n        --voc_config=mb_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=mb_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1000000.pdz\\\n        --voc_stat=mb_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --use_rhy=True\nfi\n\n# the pretrained models haven't release now\n# style melgan\n# style melgan's Dygraph to Static Graph is not ready now\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=style_melgan_csmsc \\\n        --voc_config=style_melgan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=style_melgan_csmsc_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=style_melgan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --use_rhy=True\n        # --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --use_rhy=True\nfi\n\n\n# wavernn\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"in wavernn syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_csmsc \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=wavernn_csmsc \\\n        --voc_config=wavernn_csmsc_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=wavernn_csmsc_ckpt_0.2.0/snapshot_iter_400000.pdz \\\n        --voc_stat=wavernn_csmsc_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --inference_dir=${train_output_path}/inference \\\n        --use_rhy=True\nfi\n"
  },
  {
    "path": "examples/csmsc/tts3_rhy/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ### please place the mfa result of rhythm here\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0\n    # use 1-4 to select the vocoder in {multi band melgan, style melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0\n    # use 1,3,4 to select the vocoder in {multi band melgan, hifigan, wavernn}\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/vits/README.md",
    "content": "# VITS with CSMSC\nThis example contains code used to train a [VITS](https://arxiv.org/abs/2106.06103) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [Official Website](https://test.data-baker.com/data/index/source).\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for VITS, the durations of MFA are not needed here.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── feats_stats.npy\n    ├── norm\n    └── raw\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains wave and linear spectrogram of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, feats, feats_lengths, the path of linear spectrogram features, the path of raw waves, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n\nTrain a VITS model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       config file to overwrite default config.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\n\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--config CONFIG] [--ckpt CKPT]\n                     [--phones_dict PHONES_DICT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with VITS\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Config of VITS.\n  --ckpt CKPT           Checkpoint file of VITS.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h] [--config CONFIG] [--ckpt CKPT]\n                         [--phones_dict PHONES_DICT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with VITS\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Config of VITS.\n  --ckpt CKPT           Checkpoint file of VITS.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--config`, `--ckpt`, and `--phones_dict` are arguments for acoustic model, which correspond to the 3 files in the VITS pretrained model.\n2. `--lang` is the model language, which can be `zh` or `en`.\n3. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n4. `--text` is the text file, which contains sentences to synthesize.\n5. `--output_dir` is the directory to save synthesized audio files.\n6. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\n\nThe pretrained model can be downloaded here:\n\n- [vits_csmsc_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/vits/vits_csmsc_ckpt_1.4.0.zip) (add_blank=true)\n\nVITS checkpoint contains files listed below.\n```text\nvits_csmsc_ckpt_1.4.0\n├── default.yaml                    # default config used to train vitx\n├── phone_id_map.txt                # phone vocabulary file when training vits\n└── snapshot_iter_150000.pdz  # model parameters and optimizer states\n```\n\nps: This ckpt is not good enough, a better result is training\n\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences.txt` using pretrained VITS.\n\n```bash\nsource path.sh\nadd_blank=true\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize_e2e.py \\\n    --config=vits_csmsc_ckpt_1.4.0/default.yaml \\\n    --ckpt=vits_csmsc_ckpt_1.4.0/snapshot_iter_150000.pdz \\\n    --phones_dict=vits_csmsc_ckpt_1.4.0/phone_id_map.txt \\\n    --output_dir=exp/default/test_e2e \\\n    --text=${BIN_DIR}/../../assets/sentences.txt \\\n    --add-blank=${add_blank} \n```\n"
  },
  {
    "path": "examples/csmsc/vits/conf/default.yaml",
    "content": "# This configuration tested on 4 GPUs (V100) with 32GB GPU\n# memory. It takes around 2 weeks to finish the training\n# but 100k iters model should generate reasonable results.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 22050         # sr\nn_fft: 1024        # FFT size (samples).\nn_shift: 256       # Hop size (samples). 12.5ms\nwin_length: null   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n\n##########################################################\n#                  TTS MODEL SETTING                     #\n##########################################################\nmodel:\n    # generator related\n    generator_type: vits_generator\n    generator_params:\n        hidden_channels: 192\n        spks: -1\n        global_channels: -1\n        segment_size: 32\n        text_encoder_attention_heads: 2\n        text_encoder_ffn_expand: 4\n        text_encoder_blocks: 6\n        text_encoder_positionwise_layer_type: \"conv1d\"\n        text_encoder_positionwise_conv_kernel_size: 3\n        text_encoder_positional_encoding_layer_type: \"rel_pos\"\n        text_encoder_self_attention_layer_type: \"rel_selfattn\"\n        text_encoder_activation_type: \"swish\"\n        text_encoder_normalize_before: True\n        text_encoder_dropout_rate: 0.1\n        text_encoder_positional_dropout_rate: 0.0\n        text_encoder_attention_dropout_rate: 0.1\n        use_macaron_style_in_text_encoder: True\n        use_conformer_conv_in_text_encoder: False\n        text_encoder_conformer_kernel_size: -1\n        decoder_kernel_size: 7\n        decoder_channels: 512\n        decoder_upsample_scales: [8, 8, 2, 2]\n        decoder_upsample_kernel_sizes: [16, 16, 4, 4]\n        decoder_resblock_kernel_sizes: [3, 7, 11]\n        decoder_resblock_dilations: [[1, 3, 5], [1, 3, 5], [1, 3, 5]]\n        use_weight_norm_in_decoder: True\n        posterior_encoder_kernel_size: 5\n        posterior_encoder_layers: 16\n        posterior_encoder_stacks: 1\n        posterior_encoder_base_dilation: 1\n        posterior_encoder_dropout_rate: 0.0\n        use_weight_norm_in_posterior_encoder: True\n        flow_flows: 4\n        flow_kernel_size: 5\n        flow_base_dilation: 1\n        flow_layers: 4\n        flow_dropout_rate: 0.0\n        use_weight_norm_in_flow: True\n        use_only_mean_in_flow: True\n        stochastic_duration_predictor_kernel_size: 3\n        stochastic_duration_predictor_dropout_rate: 0.5\n        stochastic_duration_predictor_flows: 4\n        stochastic_duration_predictor_dds_conv_layers: 3\n    # discriminator related\n    discriminator_type: hifigan_multi_scale_multi_period_discriminator\n    discriminator_params:\n        scales: 1\n        scale_downsample_pooling: \"AvgPool1D\"\n        scale_downsample_pooling_params:\n            kernel_size: 4\n            stride: 2\n            padding: 2\n        scale_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [15, 41, 5, 3]\n            channels: 128\n            max_downsample_channels: 1024\n            max_groups: 16\n            bias: True\n            downsample_scales: [2, 2, 4, 4, 1]\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n        follow_official_norm: False\n        periods: [2, 3, 5, 7, 11]\n        period_discriminator_params:\n            in_channels: 1\n            out_channels: 1\n            kernel_sizes: [5, 3]\n            channels: 32\n            downsample_scales: [3, 3, 3, 3, 1]\n            max_downsample_channels: 1024\n            bias: True\n            nonlinear_activation: \"leakyrelu\"\n            nonlinear_activation_params:\n                negative_slope: 0.1\n            use_weight_norm: True\n            use_spectral_norm: False\n    # others\n    sampling_rate: 22050          # needed in the inference for saving wav\n    cache_generator_outputs: True # whether to cache generator outputs in the training\n          \n###########################################################\n#                        LOSS SETTING                     #\n###########################################################\n# loss function related\ngenerator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    loss_type: mse                   # loss type, \"mse\" or \"hinge\"\nfeat_match_loss_params:\n    average_by_discriminators: False # whether to average loss value by #discriminators\n    average_by_layers: False         # whether to average loss value by #layers of each discriminator\n    include_final_outputs: True      # whether to include final outputs for loss calculation\nmel_loss_params:\n    fs: 22050          # must be the same as the training data\n    fft_size: 1024        # fft points\n    hop_size: 256    # hop size\n    win_length: null   # window length\n    window: hann       # window type\n    num_mels: 80         # number of Mel basis\n    fmin: 0            # minimum frequency for Mel basis\n    fmax: null         # maximum frequency for Mel basis\n    log_base: null     # null represent natural log\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 1.0        # loss scaling coefficient for adversarial loss\nlambda_mel: 45.0       # loss scaling coefficient for Mel loss\nlambda_feat_match: 2.0 # loss scaling coefficient for feat match loss\nlambda_dur: 1.0        # loss scaling coefficient for duration loss\nlambda_kl: 1.0         # loss scaling coefficient for KL divergence loss\n# others\nsampling_rate: 22050          # needed in the inference for saving wav\ncache_generator_outputs: True # whether to cache generator outputs in the training\n\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 64              # Batch size.\nnum_workers: 4              # Number of workers in DataLoader.\n\n##########################################################\n#            OPTIMIZER & SCHEDULER SETTING               #\n##########################################################\n# optimizer setting for generator\ngenerator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ngenerator_scheduler: exponential_decay\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4\n    gamma: 0.999875                   \n\n# optimizer setting for discriminator\ndiscriminator_optimizer_params:\n    beta1: 0.8\n    beta2: 0.99\n    epsilon: 1.0e-9\n    weight_decay: 0.0\ndiscriminator_scheduler: exponential_decay\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4          \n    gamma: 0.999875\ngenerator_first: False # whether to start updating generator first\n\n##########################################################\n#                OTHER TRAINING SETTING                  #\n##########################################################\nnum_snapshots: 10            # max number of snapshots to keep while training\nmax_epoch: 1000              # Number of training epochs.\nsave_interval_epochs: 1      # Interval epochs to save checkpoint.\neval_interval_epochs: 1      # Interval steps to evaluate the network.\nseed: 777                    # random seed number\n"
  },
  {
    "path": "examples/csmsc/vits/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\nadd_blank=$2\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=vits_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --add-blank=${add_blank}\nfi"
  },
  {
    "path": "examples/csmsc/vits/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\nadd_blank=$2\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=vits_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --add-blank=${add_blank}\nfi\n\n"
  },
  {
    "path": "examples/csmsc/vits/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\nadd_blank=$2\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --feats-stats=dump/train/feats_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt \\\n        --add-blank=${add_blank} \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/csmsc/vits/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test\nfi\n"
  },
  {
    "path": "examples/csmsc/vits/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nadd_blank=$4\n\nstage=0\nstop_stage=0\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --am=vits_csmsc \\\n        --config=${config_path} \\\n        --ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --add-blank=${add_blank} #\\\n        # --inference_dir=${train_output_path}/inference\nfi\n"
  },
  {
    "path": "examples/csmsc/vits/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\n# install monotonic_align\ncd ${MAIN_ROOT}/paddlespeech/t2s/models/vits/monotonic_align\npython3 setup.py build_ext --inplace\ncd -\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=4 \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/csmsc/vits/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=vits\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/csmsc/vits/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_153.pdz\nadd_blank=true\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} ${add_blank}|| exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} ${add_blank}|| exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} ${add_blank}|| exit -1\nfi\n\n# # not ready yet for operator missing in Paddle2ONNX\n# # paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# # we have only tested the following models so far\n# if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n#     # install paddle2onnx\n#     pip install paddle2onnx --upgrade\n#     ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx vits_csmsc\n# fi\n\n# # inference with onnxruntime\n# if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n#     ./local/ort_predict.sh ${train_output_path}\n# fi\n\n# not ready yet for operator missing in Paddle-Lite\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    # NOTE by yuantian 2022.11.21: please compile develop version of Paddle-Lite to export and run TTS models,\n    #                   cause TTS models are supported by https://github.com/PaddlePaddle/Paddle-Lite/pull/10128\n    # vits can only run in arm\n    ./local/export2lite.sh ${train_output_path} inference pdlite vits_csmsc arm\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi\n\n"
  },
  {
    "path": "examples/csmsc/voc1/README.md",
    "content": "# Parallel WaveGAN with CSMSC\nThis example contains code used to train a [parallel wavegan](http://arxiv.org/abs/1910.11480) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\nAfter processing the data, the ``BZNSYP`` directory will look like this:\n```text\nBZNSYP\n├── Wave\n│    └─ *.wav files (audio speech)\n├── PhoneLabeling\n│    └─ *.interval files (alignment between phoneme and duration)\n└── ProsodyLabeling\n     └─ 000001-010000.txt (text with prosodic by pinyin)\n```\nThis experiment only uses *.wav files from the Wave file\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut silence at the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to  [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER]\n                [--run-benchmark RUN_BENCHMARK]\n                [--profiler_options PROFILER_OPTIONS]\n\nTrain a ParallelWaveGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       ParallelWaveGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n\nbenchmark:\n  arguments related to benchmark.\n\n  --batch-size BATCH_SIZE\n                        batch size.\n  --max-iter MAX_ITER   train max steps.\n  --run-benchmark RUN_BENCHMARK\n                        runing benchmark or not, if True, use the --batch-size\n                        and --max-iter.\n  --profiler_options PROFILER_OPTIONS\n                        The option of profiler, which should be in format\n                        \"key1=value1;key2=value2;key3=value3\".\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip) and unzip it.\n```bash\nunzip pwg_baker_ckpt_0.4.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml               # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz   # model parameters of parallel wavegan\n└── pwg_stats.npy                  # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\nWe use [Fastspeech2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3) as the acoustic model.\nDownload pretrained fastspeech2_nosil model from [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)and unzip it.\n```bash\nunzip fastspeech2_nosil_baker_ckpt_0.4.zip\n```\nFastspeech2 checkpoint contains files listed below.\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [pwg_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip)\n- [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)\n\nThe static model can be downloaded here:\n- [pwg_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_static_0.4.zip)\n- [fastspeech2_nosil_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip)\n\nThe ONNX model can be downloaded here:\n- [pwgan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_csmsc_onnx_0.2.0.zip)\n- [fastspeech2_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [pwgan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_csmsc_pdlite_1.3.0.zip)\n- [fastspeech2_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/log_stft_magnitude_loss| eval/spectral_convergence_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 400000|1.948763|0.670098|0.248882\n\nParallel WaveGAN checkpoint contains files listed below.\n\n```text\npwg_baker_ckpt_0.4\n├── pwg_default.yaml              # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz  # generator parameters of parallel wavegan\n└── pwg_stats.npy                 # statistics used to normalize spectrogram when training parallel wavegan\n```\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/csmsc/voc1/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for Parallel WaveGAN.\n# Please make sure this is adjusted for the CSMSC dataset. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires 12 GB GPU memory and takes ~3 days on RTX TITAN.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Kernel size of dilated convolution.\n    layers: 30            # Number of residual block layers.\n    stacks: 3             # Number of stacks i.e., dilation cycles.\n    residual_channels: 64 # Number of channels in residual conv.\n    gate_channels: 128    # Number of channels in gated conv.\n    skip_channels: 64     # Number of channels in skip conv.\n    aux_channels: 80      # Number of channels for auxiliary feature conv.\n                          # Must be the same as num_mels.\n    aux_context_window: 2 # Context window size for auxiliary feature.\n                          # If set to 2, previous 2 and future 2 frames will be considered.\n    dropout: 0.0          # Dropout rate. 0.0 means no dropout applied.\n    bias: True            # use bias in residual blocks\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    use_causal_conv: False               # use causal conv in residual blocks and upsample layers\n    upsample_scales: [4, 5, 3, 5]     # Upsampling scales. Prodcut of these must be the same as hop size.\n    interpolate_mode: \"nearest\" # upsample net interpolate mode\n    freq_axis_kernel_size: 1 # upsamling net: convolution kernel size in frequencey axis\n    nonlinear_activation: null\n    nonlinear_activation_params: {}\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Number of output channels.\n    layers: 10            # Number of conv layers.\n    conv_channels: 64     # Number of chnn layers.\n    bias: True            # Whether to use bias parameter in conv.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear function after each conv.\n    nonlinear_activation_params:      # Nonlinear function parameters\n        negative_slope: 0.2           # Alpha in leakyrelu.\n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"         # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 4.0  # Loss balancing coefficient.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 8              # Batch size.\nbatch_max_steps: 25500     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-6        # Generator's epsilon.\n    weight_decay: 0.0      # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 0.0001  # Generator's learning rate.\n    step_size: 200000      # Generator's scheduler step size.\n    gamma: 0.5             # Generator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ngenerator_grad_norm: 10    # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-6            # Discriminator's epsilon.\n    weight_decay: 0.0          # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 0.00005     # Discriminator's learning rate.\n    step_size: 200000          # Discriminator's scheduler step size.\n    gamma: 0.5                 # Discriminator's scheduler gamma.\n                               # At each step size, lr will be multiplied by this parameter.\ndiscriminator_grad_norm: 1     # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 400000                 # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_save_intermediate_results: 4  # Number of results to be saved as intermediate results.\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc1/local/PTQ_static.sh",
    "content": "train_output_path=$1\nmodel_name=$2\n\npython3 ${BIN_DIR}/../../PTQ_static.py \\\n    --dev-metadata=dump/dev/raw/metadata.jsonl \\\n    --inference_dir ${train_output_path}/inference \\\n    --model_name ${model_name} \\\n    --onnx_format=True "
  },
  {
    "path": "examples/csmsc/voc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../preprocess.py \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dataset=baker \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --cut-sil=True \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n        \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/csmsc/voc1/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test \\\n    --generator-type=pwgan || exit -1\n"
  },
  {
    "path": "examples/csmsc/voc1/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../../synthesize_e2e.py \\\n    --am=fastspeech2_csmsc \\\n    --am_config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n    --am_ckpt=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n    --am_stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy \\\n    --voc=pwgan_csmsc \\\n    --voc_config=${config_path} \\\n    --voc_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --voc_stat=dump/train/feats_stats.npy \\\n    --lang=zh \\\n    --text=${BIN_DIR}/../../../assets/sentences.txt \\\n    --output_dir=${train_output_path}/test_e2e \\\n    --phones_dict=fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt \\\n    --inference_dir=${train_output_path}/inference || exit -1\n"
  },
  {
    "path": "examples/csmsc/voc1/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\nFLAGS_cudnn_exhaustive_search=true \\\nFLAGS_conv_workspace_size_limit=4000 \\\npython ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1\n"
  },
  {
    "path": "examples/csmsc/voc1/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=parallelwave_gan\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/gan_vocoder/${MODEL}"
  },
  {
    "path": "examples/csmsc/voc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} pwgan_csmsc || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/voc3/README.md",
    "content": "# Multi Band MelGAN with CSMSC\nThis example contains code used to train a [Multi Band MelGAN](https://arxiv.org/abs/2005.05106) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a Multi-Band MelGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Multi-Band MelGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\nWe use [MultiBand MelGAN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc3) as the neural vocoder.\n\nDownload pretrained MultiBand MelGAN model from [mb_melgan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_ckpt_0.1.1.zip) and unzip it.\n```bash\nunzip mb_melgan_csmsc_ckpt_0.1.1.zip\n```\nMultiBand MelGAN checkpoint contains files listed below.\n```text\nmb_melgan_csmsc_ckpt_0.1.1\n├── default.yaml                    # default config used to train MultiBand MelGAN\n├── feats_stats.npy                 # statistics used to normalize spectrogram when training MultiBand MelGAN\n└── snapshot_iter_1000000.pdz       # generator parameters of MultiBand MelGAN\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` multi band melgan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\nWe use [Fastspeech2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3) as the acoustic model.\nDownload pretrained fastspeech2_nosil model from [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)and unzip it.\n```bash\nunzip fastspeech2_nosil_baker_ckpt_0.4.zip\n```\nFastspeech2 checkpoint contains files listed below.\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\nSynthesize with acoustic model & vocoder\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Fine-tuning\nSince there is no `noise` in the input of Multi-Band MelGAN, the audio quality is not so good (see [espnet issue](https://github.com/espnet/espnet/issues/3536#issuecomment-916035415)), we refer to the method proposed in [HiFiGAN](https://arxiv.org/abs/2010.05646),  finetune Multi-Band MelGAN with the predicted mel-spectrogram from `FastSpeech2`.\n\nThe length of mel-spectrograms should align with the length of wavs, so we should generate mels using ground truth alignment.\n\nBut since we are fine-tuning, we should use the statistics computed during the training step.\n\nYou should first download pretrained `FastSpeech2` model from [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip) and `unzip` it.\n\nAssume the path to the dump-dir of training step is `dump`.\nAssume the path to the duration result of CSMSC is `durations.txt` (generated during the training step's preprocessing).\nAssume the path to the pretrained `FastSpeech2` model is `fastspeech2_nosil_baker_ckpt_0.4`.\n\\\nThe `finetune.sh` can\n1. **source path**.\n2. generate ground truth alignment mels.\n3. link `*_wave.npy` from `dump` to `dump_finetune` (because we only use new mels, the wavs are the ones used during the training step).\n4. copy features' stats from `dump` to `dump_finetune`.\n5. normalize the ground truth alignment mels.\n6. finetune the model.\n\nBefore finetune, make sure that the pretrained model is in `finetune.sh` 's `${output-dir}/checkpoints`, and there is a `records.jsonl` in it to refer to this pretrained model\n```text\nexp/finetune/checkpoints\n├── records.jsonl\n└── snapshot_iter_1000000.pdz\n```\nThe content of `records.jsonl` should be as follows (change `\"path\"` to your ckpt path):\n```\n{\"time\": \"2021-11-21 15:11:20.337311\", \"path\": \"~/PaddleSpeech/examples/csmsc/voc3/exp/finetune/checkpoints/snapshot_iter_1000000.pdz\", \"iteration\": 1000000}\n```\nRun the command below \n```bash\n./finetune.sh\n```\nBy default, `finetune.sh` will use `conf/finetune.yaml` as config, the dump-dir is `dump_finetune`, the experiment dir is `exp/finetune`.\n\nTODO: \nThe hyperparameter of `finetune.yaml` is not good enough, a smaller `learning_rate` should be used (more `milestones` should be set).\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [mb_melgan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_ckpt_0.1.1.zip)\n- [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)\n\nThe finetuned model can be downloaded here:\n- [mb_melgan_baker_finetune_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_baker_finetune_ckpt_0.5.zip)\n\nThe static model can be downloaded here:\n- [mb_melgan_csmsc_static_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_static_0.1.1.zip)\n- [fastspeech2_nosil_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip)\n\nThe PIR static model can be downloaded here:\n- [mb_melgan_csmsc_static_pir_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_static_pir_0.1.1.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [mb_melgan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip)\n- [fastspeech2_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [mb_melgan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_pdlite_1.3.0.zip)\n- [fastspeech2_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/log_stft_magnitude_loss|eval/spectral_convergence_loss |eval/sub_log_stft_magnitude_loss|eval/sub_spectral_convergence_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:| :--------:| :--------:\ndefault| 1(gpu) x 1000000| 2.4851|0.71778 |0.2761 |0.66334 |0.2777|\nfinetune| 1(gpu) x 1000000|3.196967|0.977804| 0.778484| 0.889576 |0.776756 |\n\nMulti Band MelGAN checkpoint contains files listed below.\n\n```text\nmb_melgan_csmsc_ckpt_0.1.1\n├── default.yaml                  # default config used to train multi band melgan\n├── feats_stats.npy               # statistics used to normalize spectrogram when training multi band melgan\n└── snapshot_iter_1000000.pdz     # generator parameters of multi band melgan\n```\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/csmsc/voc3/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for MelGAN.\n# Please make sure this is adjusted for the CSMSC dataset. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires ~ 8GB memory and will finish within 7 days on Titan V.\n\n# This configuration is based on full-band MelGAN but the hop size and sampling\n# rate is different from the paper (16kHz vs 24kHz). The number of iterations\n# is not shown in the paper so currently we train 1M iterations (not sure enough\n# to converge).\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80               # Number of input channels.\n    out_channels: 4               # Number of output channels.\n    kernel_size: 7                # Kernel size of initial and final conv layers.\n    channels: 384                 # Initial number of channels for conv layers.\n    upsample_scales: [5, 5, 3]    # List of Upsampling scales. prod(upsample_scales) x out_channels == n_shift\n    stack_kernel_size: 3          # Kernel size of dilated conv layers in residual stack.\n    stacks: 4                     # Number of stacks in a single residual stack module.\n    use_weight_norm: True         # Whether to use weight normalization.\n    use_causal_conv: False        # Whether to use causal convolution.\n    use_final_nonlinear_activation: True\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1                    # Number of input channels.\n    out_channels: 1                   # Number of output channels.\n    scales: 3                         # Number of multi-scales.\n    downsample_pooling: \"AvgPool1D\"   # Pooling type for the input downsampling.\n    downsample_pooling_params:        # Parameters of the above pooling function.\n        kernel_size: 4\n        stride: 2\n        padding: 1\n        exclusive: True\n    kernel_sizes: [5, 3]              # List of kernel size.\n    channels: 16                      # Number of channels of the initial conv layer.\n    max_downsample_channels: 512      # Maximum number of channels of downsampling layers.\n    downsample_scales: [4, 4, 4]      # List of downsampling scales.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear activation function.\n    nonlinear_activation_params:      # Parameters of nonlinear activation function.\n        negative_slope: 0.2\n    use_weight_norm: True             # Whether to use weight norm.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: True\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss.\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\nuse_subband_stft_loss: True\nsubband_stft_loss_params:\n    fft_sizes: [384, 683, 171]  # List of FFT size for STFT-based loss.\n    hop_sizes: [30, 60, 10]     # List of hop size for STFT-based loss\n    win_lengths: [150, 300, 60] # List of window length for STFT-based loss.\n    window: \"hann\"              # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nuse_feat_match_loss: False # Whether to use feature matching loss.\nlambda_adv: 2.5            # Loss balancing coefficient for adversarial loss.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 64             # Batch size.\nbatch_max_steps: 16200     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-7                     # Generator's epsilon.\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\n\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ngenerator_scheduler_params:\n    learning_rate: 1.0e-3               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 100000\n        - 200000\n        - 300000\n        - 400000\n        - 500000\n        - 600000\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-7                         # Discriminator's epsilon.\n    weight_decay: 0.0                       # Discriminator's weight decay coefficient.\n  \ndiscriminator_grad_norm: -1                 # Discriminator's gradient norm.\ndiscriminator_scheduler_params:\n    learning_rate: 1.0e-3                   # Discriminator's learning rate.\n    gamma: 0.5                              # Discriminator's scheduler gamma.\n    milestones:                             # At each milestone, lr will be multiplied by gamma.\n        - 100000\n        - 200000\n        - 300000\n        - 400000\n        - 500000\n        - 600000\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 200000 # Number of steps to start to train discriminator.\ntrain_max_steps: 1000000                # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc3/conf/finetune.yaml",
    "content": "# This is the hyperparameter configuration file for MelGAN.\n# Please make sure this is adjusted for the CSMSC dataset. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires ~ 8GB memory and will finish within 7 days on Titan V.\n\n# This configuration is based on full-band MelGAN but the hop size and sampling\n# rate is different from the paper (16kHz vs 24kHz). The number of iterations\n# is not shown in the paper so currently we train 1M iterations (not sure enough\n# to converge). \n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80               # Number of input channels.\n    out_channels: 4               # Number of output channels.\n    kernel_size: 7                # Kernel size of initial and final conv layers.\n    channels: 384                 # Initial number of channels for conv layers.\n    upsample_scales: [5, 5, 3]    # List of Upsampling scales. prod(upsample_scales) x out_channels == n_shift\n    stack_kernel_size: 3          # Kernel size of dilated conv layers in residual stack.\n    stacks: 4                     # Number of stacks in a single residual stack module.\n    use_weight_norm: True         # Whether to use weight normalization.\n    use_causal_conv: False        # Whether to use causal convolution.\n    use_final_nonlinear_activation: True\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1                    # Number of input channels.\n    out_channels: 1                   # Number of output channels.\n    scales: 3                         # Number of multi-scales.\n    downsample_pooling: \"AvgPool1D\"   # Pooling type for the input downsampling.\n    downsample_pooling_params:        # Parameters of the above pooling function.\n        kernel_size: 4\n        stride: 2\n        padding: 1\n        exclusive: True\n    kernel_sizes: [5, 3]              # List of kernel size.\n    channels: 16                      # Number of channels of the initial conv layer.\n    max_downsample_channels: 512      # Maximum number of channels of downsampling layers.\n    downsample_scales: [4, 4, 4]      # List of downsampling scales.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear activation function.\n    nonlinear_activation_params:      # Parameters of nonlinear activation function.\n        negative_slope: 0.2\n    use_weight_norm: True             # Whether to use weight norm.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: True\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\nuse_subband_stft_loss: True\nsubband_stft_loss_params:\n    fft_sizes: [384, 683, 171]  # List of FFT size for STFT-based loss.\n    hop_sizes: [30, 60, 10]     # List of hop size for STFT-based loss.\n    win_lengths: [150, 300, 60] # List of window length for STFT-based loss.\n    window: \"hann\"              # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nuse_feat_match_loss: False # Whether to use feature matching loss.\nlambda_adv: 2.5            # Loss balancing coefficient for adversarial loss.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 64             # Batch size.\nbatch_max_steps: 16200     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-7                     # Generator's epsilon.\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\n\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ngenerator_scheduler_params:\n    learning_rate: 1.0e-3               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 100000\n        - 200000\n        - 300000\n        - 400000\n        - 500000\n        - 600000\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-7                         # Discriminator's epsilon.\n    weight_decay: 0.0                       # Discriminator's weight decay coefficient.\n  \ndiscriminator_grad_norm: -1                 # Discriminator's gradient norm.\ndiscriminator_scheduler_params:\n    learning_rate: 1.0e-3                   # Discriminator's learning rate.\n    gamma: 0.5                              # Discriminator's scheduler gamma.\n    milestones:                             # At each milestone, lr will be multiplied by gamma.\n        - 100000\n        - 200000\n        - 300000\n        - 400000\n        - 500000\n        - 600000\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 200000 # Number of steps to start to train discriminator.\ntrain_max_steps: 2000000                # Number of training steps.\nsave_interval_steps: 1000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test \\\n    --generator-type=mb_melgan\n"
  },
  {
    "path": "examples/csmsc/voc3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../../synthesize_e2e.py \\\n    --am=fastspeech2_csmsc \\\n    --am_config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n    --am_ckpt=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n    --am_stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy \\\n    --voc=mb_melgan_csmsc \\\n    --voc_config=${config_path} \\\n    --voc_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --voc_stat=dump/train/feats_stats.npy \\\n    --lang=zh \\\n    --text=${BIN_DIR}/../../assets/sentences.txt \\\n    --output_dir=${train_output_path}/test_e2e \\\n    --phones_dict=dump/phone_id_map.txt \\\n    --inference_dir=${train_output_path}/inference"
  },
  {
    "path": "examples/csmsc/voc3/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=multi_band_melgan\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/gan_vocoder/${MODEL}"
  },
  {
    "path": "examples/csmsc/voc3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_50000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is MultiBand MelGAN by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} mb_melgan_csmsc || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/voc4/README.md",
    "content": "# Style MelGAN with CSMSC\nThis example contains code used to train a [Style MelGAN](https://arxiv.org/abs/2011.01557) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a Style MelGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Style MelGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` style melgan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [style_melgan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/style_melgan/style_melgan_csmsc_ckpt_0.1.1.zip)\n\nThe static model of Style MelGAN is not available now.\n\nStyle MelGAN checkpoint contains files listed below.\n\n```text\nhifigan_csmsc_ckpt_0.1.1\n├── default.yaml                    # default config used to train style melgan\n├── feats_stats.npy                  # statistics used to normalize spectrogram when training style melgan \n└── snapshot_iter_1500000.pdz     # generator parameters of style melgan\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/csmsc/voc4/conf/default.yaml",
    "content": "# This is the configuration file for CSMSC dataset.This configuration is based \n# on StyleMelGAN paper but uses MSE loss instead of Hinge loss. And I found that\n# batch_size = 8 is also working good. So maybe if you want to accelerate the training, \n# you can reduce the batch size (e.g. 8 or 16). Upsampling scales is modified to \n# fit the shift size 300 pt.\n# NOTE: batch_max_steps(24000) == prod(noise_upsample_scales)(80) * prod(upsample_scales)(300)\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 128              # Number of input channels.\n    aux_channels: 80\n    channels: 64                  # Initial number of channels for conv layers.\n    out_channels: 1               # Number of output channels.\n    kernel_size: 9                # Kernel size of initial and final conv layers.\n    dilation: 2\n    bias: True\n    noise_upsample_scales: [10, 2, 2, 2]\n    noise_upsample_activation: \"leakyrelu\"\n    noise_upsample_activation_params:\n        negative_slope: 0.2\n    upsample_scales: [5, 1, 5, 1, 3, 1, 2, 2, 1] # List of Upsampling scales. prod(upsample_scales) == n_shift\n    upsample_mode: \"nearest\"\n    gated_function: \"softmax\"\n    use_weight_norm: True                        # Whether to use weight normalization.\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    repeats: 4\n    window_sizes: [512, 1024, 2048, 4096]\n    pqmf_params:\n        - [1, None, None, None]\n        - [2, 62, 0.26700, 9.0]\n        - [4, 62, 0.14200, 9.0]\n        - [8, 62, 0.07949, 9.0]\n    discriminator_params:\n        out_channels: 1               # Number of output channels.\n        kernel_sizes: [5, 3]          # List of kernel size.\n        channels: 16                  # Number of channels of the initial conv layer.\n        max_downsample_channels: 512  # Maximum number of channels of downsampling layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 1]   # List of downsampling scales.\n        nonlinear_activation: \"leakyrelu\" # Nonlinear activation function.\n        nonlinear_activation_params:      # Parameters of nonlinear activation function.\n            negative_slope: 0.2\n    use_weight_norm: True                 # Whether to use weight norm.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: True\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\nlambda_aux: 1.0                   # Loss balancing coefficient for aux loss.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 1.0 # Loss balancing coefficient for adv loss.\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 32              # Batch size.\n# batch_max_steps(24000) == prod(noise_upsample_scales)(80) * prod(upsample_scales)(300, n_shift)\nbatch_max_steps: 24000      # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                       # Generator's weight decay coefficient.\ngenerator_scheduler_params:  \n    learning_rate: 1.0e-4                   # Generator's learning rate.\n    gamma: 0.5                              # Generator's scheduler gamma.\n    milestones:                             # At each milestone, lr will be multiplied by gamma.\n        - 100000\n        - 300000\n        - 500000\n        - 700000\n        - 900000\ngenerator_grad_norm: -1                     # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                       # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4                   # Discriminator's learning rate.\n    gamma: 0.5                              # Discriminator's scheduler gamma.\n    milestones:                             # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ndiscriminator_grad_norm: -1                 # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 1500000                # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc4/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test \\\n    --generator-type=style_melgan\n"
  },
  {
    "path": "examples/csmsc/voc4/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=style_melgan\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/gan_vocoder/${MODEL}"
  },
  {
    "path": "examples/csmsc/voc4/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_50000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/csmsc/voc5/README.md",
    "content": "# HiFiGAN with CSMSC\nThis example contains code used to train a [HiFiGAN](https://arxiv.org/abs/2010.05646) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\nThe structure of the folder is listed below.\n\n```text\n└─ Wave\n    └─ .wav files (audio speech)\n└─ PhoneLabeling\n    └─ .interval files (alignment between phoneme and duration)\n└─ ProsodyLabeling\n   └─ 000001-010000.txt (text with prosodic by pinyin)\n```\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut silence at the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a HiFiGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       HiFiGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\nWe use [HiFiGAN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/voc5) as the neural vocoder.\n\nDownload pretrained HiFiGAN model from [hifigan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_ckpt_0.1.1.zip) and unzip it.\n```bash\nunzip hifigan_csmsc_ckpt_0.1.1.zip\n```\nHiFiGAN checkpoint contains files listed below.\n```text\nhifigan_csmsc_ckpt_0.1.1\n├── default.yaml                    # default config used to train HiFiGAN\n├── feats_stats.npy                 # statistics used to normalize spectrogram when training HiFiGAN\n└── snapshot_iter_2500000.pdz       # generator parameters of HiFiGAN\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\nWe use [Fastspeech2](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/csmsc/tts3) as the acoustic model.\nDownload pretrained fastspeech2_nosil model from [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)and unzip it.\n```bash\nunzip fastspeech2_nosil_baker_ckpt_0.4.zip\n```\nFastspeech2 checkpoint contains files listed below.\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\nSynthesize with acoustic model & vocoder\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [hifigan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_ckpt_0.1.1.zip)\n- [fastspeech2_nosil_baker_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip)\n\nThe static model can be downloaded here:\n- [hifigan_csmsc_static_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_static_0.1.1.zip)\n- [fastspeech2_nosil_baker_static_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip)\n\nThe PIR static model can be downloaded here:\n- [hifigan_csmsc_static_pir_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_static_pir_0.1.1.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [hifigan_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_onnx_0.2.0.zip)\n- [fastspeech2_csmsc_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [hifigan_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_pdlite_1.3.0.zip)\n- [fastspeech2_csmsc_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/mel_loss| eval/feature_matching_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 2500000|24.927|0.1262|7.554\n\nHiFiGAN checkpoint contains files listed below.\n\n```text\nhifigan_csmsc_ckpt_0.1.1\n├── default.yaml                  # default config used to train hifigan\n├── feats_stats.npy               # statistics used to normalize spectrogram when training hifigan\n└── snapshot_iter_2500000.pdz     # generator parameters of hifigan\n```\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_nosil_baker_ckpt_0.4\n├── default.yaml            # default config used to train fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── snapshot_iter_76000.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/csmsc/voc5/conf/default.yaml",
    "content": "# This is the configuration file for CSMSC dataset.\n# This configuration is based on HiFiGAN V1, which is an official configuration. \n# But I found that the optimizer setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [5, 5, 4, 3]         # Upsampling scales.\n    upsample_kernel_sizes: [10, 10, 8, 6] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 2048\n    hop_size: 300\n    win_length: 1200\n    window: \"hann\"\n    num_mels: 80\n    fmin: 0\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc5/conf/finetune.yaml",
    "content": "# This is the configuration file for CSMSC dataset.\n# This configuration is based on HiFiGAN V1, which is an official configuration. \n# But I found that the optimizer setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [5, 5, 4, 3]         # Upsampling scales.\n    upsample_kernel_sizes: [10, 10, 8, 6] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 2048\n    hop_size: 300\n    win_length: 1200\n    window: \"hann\"\n    num_mels: 80\n    fmin: 0\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 10000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\nlog_interval_steps: 100            # Interval steps to record the training log.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc5/conf/iSTFT.yaml",
    "content": "# This is the configuration file for CSMSC dataset.\r\n# This configuration is based on HiFiGAN V1, which is an official configuration. \r\n# But I found that the optimizer setting does not work well with my implementation.\r\n# So I changed optimizer settings as follows:\r\n# - AdamW -> Adam\r\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\r\n# - Scheduler: ExponentialLR -> MultiStepLR\r\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\r\n\r\n###########################################################\r\n#                FEATURE EXTRACTION SETTING               #\r\n###########################################################\r\nfs: 24000                # Sampling rate.\r\nn_fft: 2048              # FFT size (samples).\r\nn_shift: 300             # Hop size (samples). 12.5ms\r\nwin_length: 1200         # Window length (samples). 50ms\r\n                         # If set to null, it will be the same as fft_size.\r\nwindow: \"hann\"           # Window function.\r\nn_mels: 80               # Number of mel basis.\r\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\r\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\r\n\r\n###########################################################\r\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\r\n###########################################################\r\ngenerator_params:\r\n    use_istft: True                       # Use iSTFTNet.\r\n    istft_layer_id: 2                     # Use istft after istft_layer_id layers of upsample layer if use_istft=True.\r\n    n_fft: 2048                           # FFT size (samples) in feature extraction.\r\n    win_length: 1200                      # Window length (samples) in feature extraction.\r\n    in_channels: 80                       # Number of input channels.\r\n    out_channels: 1                       # Number of output channels.\r\n    channels: 512                         # Number of initial channels.\r\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\r\n    upsample_scales:  [5, 5, 4, 3]        # Upsampling scales.\r\n    upsample_kernel_sizes: [10, 10, 8, 6] # Kernel size for upsampling layers.\r\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\r\n    resblock_dilations:                   # Dilations for residual blocks.\r\n        - [1, 3, 5]\r\n        - [1, 3, 5]\r\n        - [1, 3, 5]\r\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\r\n    bias: True                            # Whether to use bias parameter in conv.\r\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\r\n    nonlinear_activation_params:          # Nonlinear activation parameters.\r\n        negative_slope: 0.1\r\n    use_weight_norm: True                 # Whether to apply weight normalization.\r\n\r\n\r\n\r\n\r\n\r\n###########################################################\r\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\r\n###########################################################\r\ndiscriminator_params:\r\n    scales: 3                              # Number of multi-scale discriminator.\r\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\r\n    scale_downsample_pooling_params:\r\n        kernel_size: 4                     # Pooling kernel size.\r\n        stride: 2                          # Pooling stride.\r\n        padding: 2                         # Padding size.\r\n    scale_discriminator_params:\r\n        in_channels: 1                     # Number of input channels.\r\n        out_channels: 1                    # Number of output channels.\r\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\r\n        channels: 128                      # Initial number of channels.\r\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\r\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\r\n        bias: True\r\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\r\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\r\n        nonlinear_activation_params:\r\n            negative_slope: 0.1\r\n    follow_official_norm: True             # Whether to follow the official norm setting.\r\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\r\n    period_discriminator_params:\r\n        in_channels: 1                     # Number of input channels.\r\n        out_channels: 1                    # Number of output channels.\r\n        kernel_sizes: [5, 3]               # List of kernel sizes.\r\n        channels: 32                       # Initial number of channels.\r\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\r\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\r\n        bias: True                         # Whether to use bias parameter in conv layer.\"\r\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\r\n        nonlinear_activation_params:       # Nonlinear activation parameters.\r\n            negative_slope: 0.1\r\n        use_weight_norm: True              # Whether to apply weight normalization.\r\n        use_spectral_norm: False           # Whether to apply spectral normalization.\r\n    \r\n\r\n###########################################################\r\n#                   STFT LOSS SETTING                     #\r\n###########################################################\r\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\r\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\r\nmel_loss_params:\r\n    fs: 24000\r\n    fft_size: 2048\r\n    hop_size: 300\r\n    win_length: 1200\r\n    window: \"hann\"\r\n    num_mels: 80\r\n    fmin: 0\r\n    fmax: 12000\r\n    log_base: null\r\ngenerator_adv_loss_params:\r\n    average_by_discriminators: False # Whether to average loss by #discriminators.\r\ndiscriminator_adv_loss_params:\r\n    average_by_discriminators: False # Whether to average loss by #discriminators.\r\nuse_feat_match_loss: True\r\nfeat_match_loss_params:\r\n    average_by_discriminators: False # Whether to average loss by #discriminators.\r\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\r\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\r\n\r\n###########################################################\r\n#               ADVERSARIAL LOSS SETTING                  #\r\n###########################################################\r\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\r\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\r\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\r\n\r\n###########################################################\r\n#                  DATA LOADER SETTING                    #\r\n###########################################################\r\nbatch_size: 16              # Batch size.\r\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\r\nnum_workers: 2              # Number of workers in DataLoader.\r\n\r\n###########################################################\r\n#             OPTIMIZER & SCHEDULER SETTING               #\r\n###########################################################\r\ngenerator_optimizer_params:\r\n    beta1: 0.5\r\n    beta2: 0.9\r\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\r\ngenerator_scheduler_params:\r\n    learning_rate: 2.0e-4               # Generator's learning rate.\r\n    gamma: 0.5                          # Generator's scheduler gamma.\r\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\r\n        - 200000\r\n        - 400000\r\n        - 600000\r\n        - 800000\r\ngenerator_grad_norm: -1                 # Generator's gradient norm.\r\ndiscriminator_optimizer_params:\r\n    beta1: 0.5\r\n    beta2: 0.9\r\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\r\ndiscriminator_scheduler_params:\r\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\r\n    gamma: 0.5                          # Discriminator's scheduler gamma.\r\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\r\n        - 200000\r\n        - 400000\r\n        - 600000\r\n        - 800000    \r\ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \r\n\r\n###########################################################\r\n#                    INTERVAL SETTING                     #\r\n###########################################################\r\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\r\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\r\ntrain_max_steps: 2500000          # Number of training steps.\r\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\r\neval_interval_steps: 1000          # Interval steps to evaluate the network.\r\n\r\n###########################################################\r\n#                     OTHER SETTING                       #\r\n###########################################################\r\nnum_snapshots: 10                 # max number of snapshots to keep while training\r\nseed: 42                          # random seed for paddle, random, and np.random\r\n"
  },
  {
    "path": "examples/csmsc/voc5/finetune.sh",
    "content": "#!/bin/bash\n\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${MAIN_ROOT}/paddlespeech/t2s/exps/fastspeech2/gen_gta_mel.py \\\n        --fastspeech2-config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n        --fastspeech2-checkpoint=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n        --fastspeech2-stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy \\\n        --dur-file=durations.txt \\\n        --output-dir=dump_finetune \\\n        --phones-dict=fastspeech2_nosil_baker_ckpt_0.4/phone_id_map.txt \\\n        --dataset=baker \\\n        --rootdir=~/datasets/BZNSYP/\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${MAIN_ROOT}/utils/link_wav.py \\\n        --old-dump-dir=dump \\\n        --dump-dir=dump_finetune\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    cp dump/train/feats_stats.npy dump_finetune/train/\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/train/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/train/norm \\\n        --stats=dump_finetune/train/feats_stats.npy \\\n        --skip-wav-copy\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/dev/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/dev/norm \\\n        --stats=dump_finetune/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/test/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/test/norm \\\n        --stats=dump_finetune/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    FLAGS_cudnn_exhaustive_search=true \\\n    FLAGS_conv_workspace_size_limit=4000 \\\n    python ${BIN_DIR}/train.py \\\n        --train-metadata=dump_finetune/train/norm/metadata.jsonl \\\n        --dev-metadata=dump_finetune/dev/norm/metadata.jsonl \\\n        --config=conf/finetune.yaml \\\n        --output-dir=exp/finetune \\\n        --ngpu=1\nfi "
  },
  {
    "path": "examples/csmsc/voc5/iSTFTNet.md",
    "content": "# iSTFTNet with CSMSC\n\nThis example contains code used to train a [iSTFTNet](https://arxiv.org/abs/2203.02395) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\nThe structure of the folder is listed below.\n\n```text\n└─ Wave\n    └─ .wav files (audio speech)\n└─ PhoneLabeling\n    └─ .interval files (alignment between phoneme and duration)\n└─ ProsodyLabeling\n   └─ 000001-010000.txt (text with prosodic by pinyin)\n```\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut silence at the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a HiFiGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       HiFiGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/iSTFT.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\n\nThe pretrained model can be downloaded here:\n\n- [iSTFTNet_csmsc_ckpt.zip](https://pan.baidu.com/s/1SNDlRWOGOcbbrKf5w-TJaA?pwd=r1e5)\n\niSTFTNet checkpoint contains files listed below.\n\n```text\niSTFTNet_csmsc_ckpt\n├── iSTFT.yaml                    # config used to train iSTFTNet\n├── feats_stats.npy               # statistics used to normalize spectrogram when training hifigan\n└── snapshot_iter_50000.pdz       # generator parameters of hifigan\n```\n\nA Comparison between iSTFTNet and Hifigan\n|  Model   |      Step      | eval/generator_loss | eval/mel_loss | eval/feature_matching_loss |  rtf   |\n|:--------:|:--------------:|:-------------------:|:-------------:|:--------------------------:| :---: |\n| hifigan  | 1(gpu) x 50000 |       13.989        |    0.14683    |           1.3484           |  0.01767   |\n| istftNet | 1(gpu) x 50000 |       13.319        |    0.14818    |           1.1069           |  0.01069   |\n\n> Rtf is tested on the CSMSC test dataset, and the test environment is aistudio v100 16G 1GPU, the test command is `./run.sh --stage 2 --stop-stage 2`\n\nThe pretained hifigan model int the comparison  can be downloaded here:\n\n- [hifigan_csmsc_ckpt.zip](https://pan.baidu.com/s/1pGY6RYV7yEB_5hRI_JoWig?pwd=tcaj)\n\n## Acknowledgement\n\nWe adapted some code from https://github.com/rishikksh20/iSTFTNet-pytorch.git.\n"
  },
  {
    "path": "examples/csmsc/voc5/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test \\\n    --generator-type=hifigan\n"
  },
  {
    "path": "examples/csmsc/voc5/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../../synthesize_e2e.py \\\n    --am=fastspeech2_csmsc \\\n    --am_config=fastspeech2_nosil_baker_ckpt_0.4/default.yaml \\\n    --am_ckpt=fastspeech2_nosil_baker_ckpt_0.4/snapshot_iter_76000.pdz \\\n    --am_stat=fastspeech2_nosil_baker_ckpt_0.4/speech_stats.npy \\\n    --voc=hifigan_csmsc \\\n    --voc_config=${config_path} \\\n    --voc_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --voc_stat=dump/train/feats_stats.npy \\\n    --lang=zh \\\n    --text=${BIN_DIR}/../../assets/sentences.txt \\\n    --output_dir=${train_output_path}/test_e2e \\\n    --phones_dict=dump/phone_id_map.txt \\\n    --inference_dir=${train_output_path}/inference"
  },
  {
    "path": "examples/csmsc/voc5/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=hifigan\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/gan_vocoder/${MODEL}"
  },
  {
    "path": "examples/csmsc/voc5/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_50000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is hifigan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} hifigan_csmsc || exit -1\nfi"
  },
  {
    "path": "examples/csmsc/voc6/README.md",
    "content": "# WaveRNN with CSMSC\nThis example contains code used to train a [WaveRNN](https://arxiv.org/abs/1802.08435) model with [Chinese Standard Mandarin Speech Copus](https://www.data-baker.com/open_source.html).\n## Dataset\n### Download and Extract\nDownload CSMSC from it's [official website](https://test.data-baker.com/data/index/TNtts/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/BZNSYP`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut silence at the edge of audio.\nYou can download from here [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz), or train your MFA model reference to  [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/BZNSYP`.\nAssume the path to the MFA result of CSMSC is `./baker_alignment_tone`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a WaveRNN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       WaveRNN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--config CONFIG] [--checkpoint CHECKPOINT]\n                     [--test-metadata TEST_METADATA] [--output-dir OUTPUT_DIR]\n                     [--ngpu NGPU]\n\nSynthesize with WaveRNN.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       Vocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` wavernn config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [wavernn_csmsc_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [wavernn_csmsc_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_static_0.2.0.zip)\n- [wavernn_csmsc_static_1.0.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_static_1.0.0.zip) (fix bug for paddle 2.3)\n\nModel | Step | eval/loss\n:-------------:|:------------:| :------------:\ndefault| 1(gpu) x 400000|2.602768\n\nWaveRNN checkpoint contains files listed below.\n\n```text\nwavernn_csmsc_ckpt_0.2.0\n├── default.yaml                   # default config used to train wavernn\n├── feats_stats.npy                # statistics used to normalize spectrogram when training wavernn\n└── snapshot_iter_400000.pdz       # parameters of wavernn\n```\n"
  },
  {
    "path": "examples/csmsc/voc6/conf/default.yaml",
    "content": "\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\nmu_law: True             # Recommended to suppress noise if using raw bitsexit()\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    rnn_dims: 512                     # Hidden dims of RNN Layers.\n    fc_dims: 512\n    bits: 9                           # Bit depth of signal\n    aux_context_window: 2             # Context window size for auxiliary feature.\n                                      # If set to 2, previous 2 and future 2 frames will be considered.\n    aux_channels: 80                  # Number of channels for auxiliary feature conv.\n                                      # Must be the same as num_mels.\n    upsample_scales: [4, 5, 3, 5]     # Upsampling scales. Prodcut of these must be the same as hop size, same with pwgan here\n    compute_dims: 128                 # Dims of Conv1D in MelResNet.\n    res_out_dims: 128                 # Dims of output in MelResNet.\n    res_blocks: 10                    # Number of residual blocks.\n    mode: RAW                         # either 'raw'(softmax on raw bits) or 'mold' (sample from mixture of logistics)\ninference:\n    gen_batched: True                 # whether to genenate sample in batch mode\n    target: 12000                     # target number of samples to be generated in each batch entry\n    overlap: 600                      # number of samples for crossfading between batches\n\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 64              # Batch size.\nbatch_max_steps: 4500       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\ngrad_clip: 4.0\nlearning_rate: 1.0e-4                \n\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\n\ntrain_max_steps: 400000               # Number of training steps.\nsave_interval_steps: 5000             # Interval steps to save checkpoint.\neval_interval_steps: 1000             # Interval steps to evaluate the network.\ngen_eval_samples_interval_steps: 5000 # the iteration interval of generating valid samples\ngenerate_num: 5                       # number of samples to generate at each checkpoint\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/csmsc/voc6/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./baker_alignment_tone \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../gan_vocoder/preprocess.py \\\n        --rootdir=~/datasets/BZNSYP/ \\\n        --dataset=baker \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --cut-sil=True \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../gan_vocoder/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/../gan_vocoder/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../gan_vocoder/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/csmsc/voc6/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test\n"
  },
  {
    "path": "examples/csmsc/voc6/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=wavernn\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/csmsc/voc6/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\ntest_input=dump/dump_gta_test\nckpt_name=snapshot_iter_100000.pdz\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # prepare data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/esc50/README.md",
    "content": "# 声音分类\n\n声音分类和检测是声音算法的一个热门研究方向。  \n\n对于声音分类任务，传统机器学习的一个常用做法是首先人工提取音频的时域和频域的多种特征并做特征选择、组合、变换等，然后基于SVM或决策树进行分类。而端到端的深度学习则通常利用深度网络如RNN，CNN等直接对声间波形(waveform)或时频特征(time-frequency)进行特征学习(representation learning)和分类预测。\n\n在IEEE ICASSP 2017 大会上，谷歌开放了一个大规模的音频数据集[Audioset](https://research.google.com/audioset/)。该数据集包含了 632 类的音频类别以及 2,084,320 条人工标记的每段 **10 秒**长度的声音剪辑片段（来源于YouTube视频）。目前该数据集已经有 210万 个已标注的视频数据，5800 小时的音频数据，经过标记的声音样本的标签类别为 527。\n\n`PANNs`([PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition](https://arxiv.org/pdf/1912.10211.pdf))是基于Audioset数据集训练的声音分类/识别的模型。经过预训练后，模型可以用于提取音频的embbedding。本示例将使用`PANNs`的预训练模型Finetune完成声音分类的任务。\n\n\n## 模型简介\n\nPaddleAudio提供了PANNs的CNN14、CNN10和CNN6的预训练模型，可供用户选择使用：\n- CNN14: 该模型主要包含12个卷积层和2个全连接层，模型参数的数量为 79.6M，embbedding维度是 2048。\n- CNN10: 该模型主要包含8个卷积层和2个全连接层，模型参数的数量为 4.9M，embbedding维度是 512。\n- CNN6: 该模型主要包含4个卷积层和2个全连接层，模型参数的数量为 4.5M，embbedding维度是 512。\n\n\n## 数据集\n\n[ESC-50: Dataset for Environmental Sound Classification](https://github.com/karolpiczak/ESC-50) 是一个包含有 2000 个带标签的时长为 **5 秒**的环境声音样本，音频样本采样率为 44,100Hz 的单通道音频文件，所有样本根据标签被划分为 50 个类别，每个类别有 40 个样本。\n\n## 模型指标\n\n根据 `ESC-50` 提供的fold信息，对数据集进行 5-fold 的 fine-tune 训练和评估，平均准确率如下：\n\n|Model|Acc|\n|--|--|\n|CNN14| 0.9500\n|CNN10| 0.8975\n|CNN6| 0.8825\n\n## 快速开始\n\n### 模型训练\n\n运行下面的命令，可在训练集上进行模型的finetune，支持单机的单卡训练和多卡训练。\n\n启动训练:\n```shell\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 1 conf/panns.yaml\n```\n\n训练的参数可在 `conf/panns.yaml` 的 `training` 中配置，其中：\n- `epochs`: 训练轮次，默认为 50。\n- `learning_rate`: Fine-tune的学习率；默认为5e-5。\n- `batch_size`: 批处理大小，请结合显存情况进行调整，若出现显存不足，请适当调低这一参数；默认为 16。\n- `num_workers`: Dataloader获取数据的子进程数。默认为0，加载数据的流程在主进程执行。\n- `checkpoint_dir`: 模型参数文件和optimizer参数文件的保存目录，默认为`./checkpoint`。\n- `save_freq`: 训练过程中的模型保存频率，默认为 10。\n- `log_freq`: 训练过程中的信息打印频率，默认为 10。\n\n示例代码中使用的预训练模型为`CNN14`，如果想更换为其他预训练模型，可通过修改 `conf/panns.yaml` 的 `model` 中配置：\n```yaml\n# CNN14\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n```\n```yaml\n# CNN10\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn10'\n```\n```yaml\n# CNN6\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn6'\n```\n\n### 模型预测\n\n```shell\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 2 conf/panns.yaml\n```\n\n训练的参数可在 `conf/panns.yaml` 的 `predicting` 中配置，其中：\n- `audio_file`: 指定预测的音频文件。\n- `top_k`: 预测显示的top k标签的得分，默认为 1。\n- `checkpoint`: 模型参数checkpoint文件。\n\n输出的预测结果如下：\n```\n[/audio/dog.wav]\nDog: 0.9999538660049438\nClock tick: 1.3341237718123011e-05\nCat: 6.579841738130199e-06\n```\n\n### 模型部署\n\n#### 1. 动转静\n\n模型训练结束后，可以将已保存的动态图参数导出成静态图的模型和参数，然后实施静态图的部署。\n\n```shell\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 3 ./checkpoint/epoch_50/model.pdparams ./export\n```\n\n`paddlespeech/cls/exps/panns/export_model.py` 脚本中可支持配置的参数：\n- `checkpoint`: 模型参数checkpoint文件。\n- `output_dir`: 导出静态图模型和参数文件的保存目录。\n\n导出的静态图模型和参数文件如下：\n```sh\n$ tree export\nexport\n├── inference.pdiparams\n├── inference.pdiparams.info\n└── inference.pdmodel\n```\n\n#### 2. 模型部署和预测\n\n`paddlespeech/cls/exps/panns/deploy/predict.py` 脚本使用了`paddle.inference`模块下的api，提供了python端部署的示例：\n\n```shell\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 4 cpu ./export /audio/dog.wav\n```\n\n`paddlespeech/cls/exps/panns/deploy/predict.py` 脚本中可支持配置的主要参数：\n- `device`: 指定模型预测时使用的设备。\n- `model_dir`: 导出静态图模型和参数文件的保存目录。\n- `wav`: 指定预测的音频文件。\n\n## Reference\n* [PANNs(PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition)](https://arxiv.org/abs/1912.10211)\n"
  },
  {
    "path": "examples/esc50/RESULTS.md",
    "content": "## Metrics\n\n5-fold cross validation accuracy on [ESC-50](https://github.com/karolpiczak/ESC-50) dataset:\n\n|Model|Acc|\n|--|--|\n|CNN14| 0.9500\n|CNN10| 0.8975\n|CNN6| 0.8825\n"
  },
  {
    "path": "examples/esc50/cls0/conf/panns.yaml",
    "content": "data:\n  dataset: 'paddle.audio.datasets:ESC50'\n  num_classes: 50\n  train:\n    mode: 'train'\n    split: 1\n  dev:\n    mode: 'dev'\n    split: 1\n\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n\nfeature:\n  sr: 32000\n  n_fft: 1024\n  hop_length: 320\n  window: 'hann'\n  win_length: 1024\n  f_min: 50.0\n  f_max: 14000.0\n  n_mels: 64\n\ntraining:\n  epochs: 50\n  learning_rate: 0.00005\n  num_workers: 2\n  batch_size: 16\n  checkpoint_dir: './checkpoint'\n  save_freq: 10\n  log_freq: 10\n\npredicting:\n  audio_file: '/audio/dog.wav'\n  top_k: 10\n  checkpoint: './checkpoint/epoch_50/model.pdparams'\n"
  },
  {
    "path": "examples/esc50/cls0/local/export.sh",
    "content": "#!/bin/bash\n\nckpt=$1\noutput_dir=$2\n\npython3 ${BIN_DIR}/export_model.py \\\n--checkpoint ${ckpt} \\\n--output_dir ${output_dir}\n"
  },
  {
    "path": "examples/esc50/cls0/local/infer.sh",
    "content": "#!/bin/bash\n\npython3 ${BIN_DIR}/predict.py \\\n--cfg_path=$1\n"
  },
  {
    "path": "examples/esc50/cls0/local/static_model_infer.sh",
    "content": "#!/bin/bash\n\ndevice=$1\nmodel_dir=$2\naudio_file=$3\n\npython3 ${BIN_DIR}/deploy/predict.py \\\n--device ${device} \\\n--model_dir ${model_dir} \\\n--wav ${audio_file} \n"
  },
  {
    "path": "examples/esc50/cls0/local/train.sh",
    "content": "#!/bin/bash\n\nngpu=$1\ncfg_path=$2\n\nif [ ${ngpu} -gt 0 ]; then\n    python3 -m paddle.distributed.launch --gpus $CUDA_VISIBLE_DEVICES ${BIN_DIR}/train.py \\\n    --cfg_path ${cfg_path}\nelse\n    python3 ${BIN_DIR}/train.py \\\n    --cfg_path ${cfg_path}\nfi\n"
  },
  {
    "path": "examples/esc50/cls0/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=panns\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/cls/exps/${MODEL}"
  },
  {
    "path": "examples/esc50/cls0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\n\nstage=$1\nstop_stage=100\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    cfg_path=$2\n    ./local/train.sh ${ngpu} ${cfg_path} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    cfg_path=$2\n    ./local/infer.sh ${cfg_path} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    ckpt=$2\n    output_dir=$3\n    ./local/export.sh ${ckpt} ${output_dir} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    infer_device=$2\n    graph_dir=$3\n    audio_file=$4\n    ./local/static_model_infer.sh ${infer_device} ${graph_dir} ${audio_file} || exit -1\n    exit 0\nfi\n"
  },
  {
    "path": "examples/hey_snips/README.md",
    "content": "\n## Metrics\n\nWe mesure FRRs with fixing false alarms in one hour:\nthe release model: https://paddlespeech.cdn.bcebos.com/kws/heysnips/kws0_mdtc_heysnips_ckpt.tar.gz \n|Model|False Alarm| False Reject Rate|\n|--|--|--|\n|MDTC| 1| 0.003559 |\n"
  },
  {
    "path": "examples/hey_snips/kws0/README.md",
    "content": "# MDTC Keyword Spotting with HeySnips Dataset\n\n## Dataset\n\nBefore running scripts, you **MUST** follow this instruction to download the dataset: https://github.com/sonos/keyword-spotting-research-datasets\n\nAfter you download and decompress the dataset archive, you should **REPLACE** the value of `data_dir` in `conf/*.yaml` to complete dataset config.\n\n## Get Started\n\nIn this section, we will train the [MDTC](https://arxiv.org/pdf/2102.13552.pdf) model and evaluate on \"Hey Snips\" dataset.\n\n```sh\nCUDA_VISIBLE_DEVICES=0,1 ./run.sh conf/mdtc.yaml\n```\n\nThis script contains training and scoring steps. You can just set the `CUDA_VISIBLE_DEVICES` environment var to run on single gpu or multi-gpus.\n\nThe vars `stage` and `stop_stage` in `./run.sh` controls the running steps:\n- stage 1: Training from scratch.\n- stage 2: Evaluating model on test dataset and computing detection error tradeoff(DET) of all trigger thresholds.\n- stage 3: Plotting the DET cruve for visualizaiton.\n"
  },
  {
    "path": "examples/hey_snips/kws0/conf/mdtc.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ndataset: 'paddleaudio.datasets:HeySnips'\ndata_dir: '../tests/hey_snips_research_6k_en_train_eval_clean_ter'\n\n############################################\n#           Network Architecture           #\n############################################\nbackbone: 'paddlespeech.kws.models:MDTC'\nnum_keywords: 1\nstack_num: 3\nstack_size: 4\nin_channels: 80\nres_channels: 32\nkernel_size: 5\n\n###########################################\n#                Feature                  #\n###########################################\nfeat_type: 'kaldi_fbank'\nsample_rate: 16000\nframe_shift: 10\nframe_length: 25\nn_mels: 80\n\n###########################################\n#                Training                 #\n###########################################\nepochs: 100\nnum_workers: 16\nbatch_size: 100\ncheckpoint_dir: './checkpoint'\nsave_freq: 10\nlog_freq: 10\nlearning_rate: 0.001\nweight_decay: 0.00005\ngrad_clip: 5.0\n\n###########################################\n#                Scoring                  #\n###########################################\nbatch_size: 100\nnum_workers: 16\ncheckpoint: './checkpoint/epoch_100/model.pdparams'\nscore_file: './scores.txt'\nstats_file: './stats.0.txt'\nimg_file: './det.png'\n"
  },
  {
    "path": "examples/hey_snips/kws0/local/plot.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path checkpoint output_file\"\n    exit -1\nfi\n\nkeyword=$1\nstats_file=$2\nimg_file=$3\n\npython3 ${BIN_DIR}/plot_det_curve.py --keyword_label ${keyword} --stats_file ${stats_file} --img_file ${img_file}\n"
  },
  {
    "path": "examples/hey_snips/kws0/local/score.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} checkpoint score_file stats_file\"\n    exit -1\nfi\n\ncfg_path=$1\nckpt=$2\nscore_file=$3\nstats_file=$4\n\npython3 ${BIN_DIR}/score.py --config ${cfg_path} --ckpt ${ckpt} --score_file ${score_file} || exit -1\npython3 ${BIN_DIR}/compute_det.py --config ${cfg_path} --score_file ${score_file} --stats_file ${stats_file} || exit -1\n"
  },
  {
    "path": "examples/hey_snips/kws0/local/train.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nif [ $# != 2 ];then\n    echo \"usage: ${0} num_gpus config_path\"\n    exit -1\nfi\n\nngpu=$1\ncfg_path=$2\n\nif [ ${ngpu} -gt 0 ]; then\n    python3 -m paddle.distributed.launch --gpus $CUDA_VISIBLE_DEVICES ${BIN_DIR}/train.py \\\n    --config ${cfg_path}\nelse\n    echo \"set CUDA_VISIBLE_DEVICES to enable multi-gpus trainning.\"\n    python3 ${BIN_DIR}/train.py \\\n    --config ${cfg_path}\nfi\n"
  },
  {
    "path": "examples/hey_snips/kws0/path.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nMODEL=mdtc\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/kws/exps/${MODEL}"
  },
  {
    "path": "examples/hey_snips/kws0/run.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -e\nsource path.sh\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\n\nif [ $# != 1 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path\"\n    exit -1\nfi\n\nstage=1\nstop_stage=3\n\ncfg_path=$1\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ./local/train.sh ${ngpu} ${cfg_path} || exit -1\nfi\n\nckpt=./checkpoint/epoch_100/model.pdparams\nscore_file=./scores.txt\nstats_file=./stats.0.txt\nimg_file=./det.png\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    ./local/score.sh ${cfg_path} ${ckpt} ${score_file} ${stats_file} || exit -1\nfi\n\nkeyword=HeySnips\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    ./local/plot.sh ${keyword} ${stats_file} ${img_file} || exit -1\nfi"
  },
  {
    "path": "examples/iwslt2012/punc0/README.md",
    "content": "# Punctuation Restoration with IWLST2012-Zh\n\n## Get Started\n### Data Preprocessing\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Model Training\n```bash\n./run.sh --stage 1 --stop-stage 1\n```\n### Testing\n```bash\n./run.sh --stage 2 --stop-stage 2\n```\n### Punctuation Restoration\n```bash\n./run.sh --stage 3 --stop-stage 3\n```\n## Pretrained Model\nThe pretrained model can be downloaded here:\n\n[ernie_linear_p3_iwslt2012_zh_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/text/ernie_linear_p3_iwslt2012_zh_ckpt_0.1.1.zip)\n\n[ernie-3.0-base.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-3.0-base.tar.gz)\n\n[ernie-3.0-medium.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-3.0-medium.tar.gz)\n\n[ernie-3.0-micro.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-3.0-micro.tar.gz)\n\n[ernie-mini.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-mini.tar.gz)\n\n[ernie-nano.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-nano.tar.gz)\n\n[ernie-tiny.tar.gz](https://paddlespeech.cdn.bcebos.com/punc_restore/ernie-tiny.tar.gz)\n\n### Test Result\n- Ernie 1.0\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.510955  |0.526462  |0.820755  |0.619391|\n    |Recall     |0.517433  |0.564179  |0.861386  |0.647666|\n    |F1         |0.514173  |0.544669  |0.840580  |0.633141|\n- Ernie-tiny\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.733177  |0.721448  |0.754717  |0.736447|\n    |Recall     |0.380740  |0.524646  |0.733945  |0.546443|\n    |F1         |0.501204  |0.607506  |0.744186  |0.617632|\n- Ernie-3.0-base-zh\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.805947  |0.764160  |0.858491  |0.809532|\n    |Recall     |0.399070  |0.567978  |0.850467  |0.605838|\n    |F1         |0.533817  |0.651623  |0.854460  |0.679967|\n- Ernie-3.0-medium-zh\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.730829  |0.699164  |0.707547  |0.712514|\n    |Recall     |0.388196  |0.533286  |0.797872  |0.573118|\n    |F1         |0.507058  |0.605062  |0.750000  |0.620707|\n- Ernie-3.0-mini-zh\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.757433  |0.708449  |0.707547  |0.724477|\n    |Recall     |0.355752  |0.506977  |0.735294  |0.532674|\n    |F1         |0.484121  |0.591015  |0.721154  |0.598763|\n- Ernie-3.0-micro-zh\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.733959  |0.679666  |0.726415  |0.713347|\n    |Recall     |0.332742  |0.483487  |0.712963  |0.509731|\n    |F1         |0.457896  |0.565033  |0.719626  |0.580852|\n- Ernie-3.0-nano-zh\n    |       |COMMA  |  PERIOD | QUESTION | OVERALL|\n    |:-----:|:-----:|:-----:|:-----:|:-----:|  \n    |Precision  |0.693271  |0.682451  |0.754717  |0.710146|\n    |Recall     |0.327784  |0.491968  |0.666667  |0.495473|\n    |F1         |0.445114  |0.571762  |0.707965  |0.574947|\n"
  },
  {
    "path": "examples/iwslt2012/punc0/RESULTS.md",
    "content": "# iwslt2012\n\n## Ernie\n\n|       |COMMA  |  PERIOD | QUESTION | OVERALL|\n|:-----:|:-----:|:-----:|:-----:|:-----:|  \n|Precision  |0.510955  |0.526462  |0.820755  |0.619391|\n|Recall     |0.517433  |0.564179  |0.861386  |0.647666|\n|F1         |0.514173  |0.544669  |0.840580  |0.633141|\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/default.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-1.0\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-1.0\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/ernie-3.0-base.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-3.0-base-zh\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-3.0-base-zh\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/ernie-3.0-medium.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-3.0-medium-zh\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-3.0-medium-zh\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/ernie-3.0-mini.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-3.0-mini-zh\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-3.0-mini-zh\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/ernie-3.0-nano-zh.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-3.0-nano-zh\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-3.0-nano-zh\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/conf/ernie-tiny.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/iwslt2012_zh/train.txt\ndev_path: data/iwslt2012_zh/dev.txt\ntest_path: data/iwslt2012_zh/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-tiny\n    punc_path: data/iwslt2012_zh/punc_vocab\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-tiny\n    num_classes: 4\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/iwslt2012/punc0/local/data.sh",
    "content": "#!/bin/bash\n\nif [ ! -d data ]; then\n    wget -c https://paddlespeech.cdn.bcebos.com/datasets/iwslt2012.tar.gz\n    tar -xzf iwslt2012.tar.gz\nfi\n\necho \"Finish data preparation.\"\nexit 0\n"
  },
  {
    "path": "examples/iwslt2012/punc0/local/preprocess.py",
    "content": "import argparse\n\n\ndef process_sentence(line):\n    if line == '':\n        return ''\n    res = line[0]\n    for i in range(1, len(line)):\n        res += (' ' + line[i])\n    return res\n\n\nif __name__ == \"__main__\":\n    paser = argparse.ArgumentParser(description=\"Input filename\")\n    paser.add_argument('-input_file')\n    paser.add_argument('-output_file')\n    sentence_cnt = 0\n    args = paser.parse_args()\n    with open(args.input_file, 'r') as f:\n        with open(args.output_file, 'w') as write_f:\n            while True:\n                line = f.readline()\n                if line:\n                    sentence_cnt += 1\n                    write_f.write(process_sentence(line))\n                else:\n                    break\n    print('preprocess over')\n    print('total sentences number:', sentence_cnt)\n"
  },
  {
    "path": "examples/iwslt2012/punc0/local/punc_restore.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\ntext=$4\nckpt_prefix=${ckpt_name%.*}\n\npython3 ${BIN_DIR}/punc_restore.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --text=${text}\n"
  },
  {
    "path": "examples/iwslt2012/punc0/local/test.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nckpt_prefix=${ckpt_name%.*}\n\npython3 ${BIN_DIR}/test.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name}\n"
  },
  {
    "path": "examples/iwslt2012/punc0/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1\n"
  },
  {
    "path": "examples/iwslt2012/punc0/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=${PWD}/../../../\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nMODEL=ernie_linear\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/text/exps/${MODEL}\n"
  },
  {
    "path": "examples/iwslt2012/punc0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_12840.pdz\ntext=今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/data.sh\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n   CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n   CUDA_VISIBLE_DEVICES=${gpus} ./local/punc_restore.sh ${conf_path} ${train_output_path} ${ckpt_name} ${text}|| exit -1\nfi"
  },
  {
    "path": "examples/librispeech/.gitignore",
    "content": "data\nexp\nlog\nckpt*\n"
  },
  {
    "path": "examples/librispeech/README.md",
    "content": "# ASR\n\n* asr0 - deepspeech2 Streaming/Non-Streaming\n* asr1 - transformer/conformer Streaming/Non-Streaming\n* asr2 - transformer/conformer Streaming/Non-Streaming with Kaldi feature\n* asr3 - wav2vecASR, ASR model with pre-trained wav2vec2 and CTC\n\n## Data\n| Data Subset | Duration in Seconds |\n| --- | --- |\n| data/manifest.train |  0.83s ~ 29.735s |\n| data/manifest.dev | 1.065 ~ 35.155s |  \n| data/manifest.test-clean | 1.285s ~ 34.955s |\n"
  },
  {
    "path": "examples/librispeech/asr0/README.md",
    "content": "# DeepSpeech2 offline/online ASR with Librispeech\nThis example contains code used to train a DeepSpeech2 offline or online model with [[Librispeech dataset](http://www.openslr.org/resources/12)](http://www.openslr.org/resources/33)\n## Overview\nAll the scripts you need are in the `run.sh`. There are several stages in the `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Export the static graph model     |\n| 5      | Test the static graph model      |\n| 6     | Infer the single audio file                                  |\n\nYou can choose to run a range of stages by setting the `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in the `run.sh` in detail.\n## The environment variables\nThe path.sh contains the environment variable. \n```bash\nsource path.sh\n```\nThis script needs to be run first.  \n\nAnd another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The local variables\nSome local variables are set in the `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`,  it means you only use CPU. \n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of stages you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`model_type` denotes the model type: offline or online\n`audio file` denotes the file path of the single file you want to infer in stage 6\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"deepspeech2\"\n\nYou can set the local variables (except `ckpt`)  when you use the `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 1\n```\n## Stage 0: Data processing\nTo use this example, you need to process data firstly and  you can use stage 0 in the `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model training\nIf you want to train the model. you can use stage 1 in the `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\n```\n## Stage 2:  Top-k Models Averaging\nAfter training the model,  we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model.  We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model,  you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it,  you can use the script below to execute stage 0, stage 1,  stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_1\n```\n## Stage 4: Static graph model Export\nThis stage is to transform dygraph to static graph.\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}\n fi\n```\nIf you already have a dynamic graph model, you can run this script:\n```bash\nsource path.sh\n./local/export.sh deepspeech2.yaml exp/deepspeech2/checkpoints/avg_1 exp/deepspeech2/checkpoints/avg_1.jit offline\n```\n## Stage 5: Static graph Model Testing\nSimilar to stage 3, the static graph model can also be tested.\n```bash\n if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n     # test export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test_export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}|| exit -1\n fi\n```\nIf you already have exported the static graph, you can run this script:\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_export.sh conf/deepspeech2.yaml exp/deepspeech2/checkpoints/avg_1.jit offline\n```\n## Stage 6: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage  5. The code is shown below\n```bash\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${model_type} ${audio_file}\n fi\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\n```\nYou can train a model by yourself, then you need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_1 data/demo_002_en.wav\n```\n"
  },
  {
    "path": "examples/librispeech/asr0/RESULTS.md",
    "content": "# LibriSpeech\n\n## Deepspeech2 Non-Streaming\n| Model | Params | release |  Config | Test set | Loss | WER |  \n| --- | --- | --- | --- | --- | --- | --- |  \n| DeepSpeech2 | 113.96M | r1.0.1 | conf/deepspeech2.yaml + U2 Data pipline and spec aug + fbank161 | test-clean | 10.76069622039795 | 0.046700 | \n| DeepSpeech2 | 42.96M | 2.2.0 | conf/deepspeech2.yaml + spec_aug | test-clean | 14.49190807 | 0.067283 |  \n| DeepSpeech2 | 42.96M | 2.1.0 | conf/deepspeech2.yaml | test-clean | 15.184467315673828 | 0.072154 |  \n| DeepSpeech2 | 42.96M | 2.0.0 | conf/deepspeech2.yaml | test-clean | - | 0.073973 |  \n| DeepSpeech2 | 42.96M | 1.8.5 | - | test-clean | - | 0.074939 |  \n"
  },
  {
    "path": "examples/librispeech/asr0/conf/deepspeech2.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev-clean\ntest_manifest: data/manifest.test-clean\nmin_input_len: 0.0\nmax_input_len: 30.0 # second\nmin_output_len: 0.0\nmax_output_len: .inf\nmin_output_input_ratio: 0.00\nmax_output_input_ratio: .inf\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n\n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 5\nrnn_layer_size: 1024\nrnn_direction: bidirect\nnum_fc_layers: 0\nfc_layers_size_list: -1\nuse_gru: False \nblank_id: 0\n  \n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 15\naccum_grad: 1\nlr: 5.0e-4\nlr_decay: 0.93\nweight_decay: 1.0e-6\nglobal_grad_clip: 5.0\ndist_sampler: False\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/librispeech/asr0/conf/deepspeech2_online.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev-clean\ntest_manifest: data/manifest.test-clean\nmin_input_len: 0.0\nmax_input_len: 30.0 # second\nmin_output_len: 0.0\nmax_output_len: .inf\nmin_output_input_ratio: 0.00\nmax_output_input_ratio: .inf\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n\n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 5\nrnn_layer_size: 1024\nrnn_direction: forward\nnum_fc_layers: 0\nfc_layers_size_list: -1\nuse_gru: False \nblank_id: 0\n  \n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 65\naccum_grad: 1\nlr: 5.0e-4\nlr_decay: 0.93\nweight_decay: 1.0e-6\nglobal_grad_clip: 5.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/librispeech/asr0/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 161\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/librispeech/asr0/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: wer\ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/common_crawl_00.prune01111.trie.klm\nalpha: 1.9\nbeta: 0.3\nbeam_size: 500\ncutoff_prob: 1.0\ncutoff_top_n: 40\nnum_proc_bsearch: 8"
  },
  {
    "path": "examples/librispeech/asr0/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: wer\ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/common_crawl_00.prune01111.trie.klm\nalpha: 1.9\nbeta: 0.3\nbeam_size: 500\ncutoff_prob: 1.0\ncutoff_top_n: 40\nnum_proc_bsearch: 8"
  },
  {
    "path": "examples/librispeech/asr0/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\nunit_type=char\ndict_dir=data/lang_char\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"True\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for set in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do\n        mv data/manifest.${set} data/manifest.${set}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for set in train-clean-100 train-clean-360 train-other-500; do\n        cat data/manifest.${set}.raw >> data/manifest.train.raw\n    done\n\n    for set in dev-clean dev-other; do\n        cat data/manifest.${set}.raw >> data/manifest.dev.raw\n    done\n\n    for set in test-clean test-other; do\n        cat data/manifest.${set}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=2000 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=161 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test dev-clean dev-other test-clean test-other; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type ${unit_type} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest.${set} failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"LibriSpeech Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/local/download_lm_en.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL=https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm\nMD5=\"099a601759d467cd0a8523ff939819c5\"\nTARGET=${DIR}/common_crawl_00.prune01111.trie.klm\n\necho \"Start downloading the language model. The language model is large, please wait for a moment ...\"\ndownload $URL $MD5 $TARGET > /dev/null 2>&1\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nelse\n    echo \"Download the language model sucessfully\"\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\nstage=0\nstop_stage=100\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\n# download language model\nbash local/download_lm_en.sh\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # format the reference test file\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test-clean.raw \\\n        --trans_ref data/manifest.test-clean.text\n\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.rsl \\\n    --checkpoint_path ${ckpt_prefix}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.rsl \\\n        --trans_hyp ${ckpt_prefix}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.rsl.text > ${ckpt_prefix}.error\nfi\n\nif [ ${stage} -le 101 ] && [ ${stop_stage} -ge 101 ]; then\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test-clean.raw \\\n        --trans_ref_sclite data/manifest.test.text-clean.sclite\n\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.rsl \\\n        --trans_hyp_sclite ${ckpt_prefix}.rsl.text.sclite\n\n    mkdir -p ${ckpt_prefix}_sclite\n    sclite -i wsj -r data/manifest.test-clean.text.sclite -h  ${ckpt_prefix}.rsl.text.sclite  -e utf-8 -o all -O ${ckpt_prefix}_sclite -c NOASCII\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\n# download language model\nbash local/download_lm_en.sh\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\npython3 -u ${BIN_DIR}/test_wav.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${ckpt_prefix}.rsl \\\n--checkpoint_path ${ckpt_prefix} \\\n--audio_file ${audio_file}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in evaluation!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=deepspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/librispeech/asr0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=100\nconf_path=conf/deepspeech2.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=5\naudio_file=data/demo_002_en.wav\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}|| exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # test export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test_export.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}.jit|| exit -1\nfi\n\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr1/.gitignore",
    "content": "data\nexp\nlog\n*.profile\n"
  },
  {
    "path": "examples/librispeech/asr1/README.md",
    "content": "# Transformer/Conformer ASR with Librispeech\nThis example contains code used to train [u2](https://arxiv.org/pdf/2012.05481.pdf) model (Transformer or [Conformer](https://arxiv.org/pdf/2005.08100.pdf) model) with [Librispeech dataset](http://www.openslr.org/resources/12)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Get the sentencepiece model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Get ctc alignment of test data using the final model         |\n| 5     | Infer the single audio file                                  |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"conformer\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- bpe_unigram_5000.model\n|   `-- bpe_unigram_5000.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_20\n```\n## Pretrained Model\nYou can get the pretrained transformer or conformer from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr1/asr1_conformer_librispeech_ckpt_0.1.1.model.tar.gz\ntar xzvf asr1_conformer_librispeech_ckpt_0.1.1.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_20\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n## Stage 4: CTC Alignment \nIf you want to get the alignment between the audio and the text, you can use the ctc alignment. The code of this stage is shown below:\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # ctc alignment of test data\n     CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train the model, test it and do the alignment, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 4\n```\nor if you only need to train a model and do the alignment, you can use these scripts to escape stage 3(test stage):\n```bash\nbash run.sh --stage 0 --stop_stage 2\nbash run.sh --stage 4 --stop_stage 4\n```\nor you can also use these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 20\n# test stage is optional\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_20\nCUDA_VISIBLE_DEVICES= ./local/align.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_20\n```\n## Stage 5: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr1/asr1_conformer_librispeech_ckpt_0.1.1.model.tar.gz\ntar xzvf asr1_conformer_librispeech_ckpt_0.1.1.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_20 data/demo_002_en.wav\n```\n"
  },
  {
    "path": "examples/librispeech/asr1/RESULTS.md",
    "content": "# LibriSpeech\n\n## Conformer\ntrain: Epoch 70, 4 V100-32G, best avg: 20\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | WER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-clean | attention | 6.433612394332886 | 0.039771 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-clean | ctc_greedy_search | 6.433612394332886 | 0.040342 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-clean | ctc_prefix_beam_search | 6.433612394332886 | 0.040342 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-clean | attention_rescoring | 6.433612394332886 | 0.033761 |  \n\n\n## Conformer Streaming\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size & Left Chunks | Loss | WER |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- |  \n| conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug + shift | test-clean | attention | 16, -1 | 7.11 | 0.063193 |  \n| conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug + shift | test-clean | ctc_greedy_search | 16, -1 | 7.11 | 0.082394 |  \n| conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug + shift | test-clean | ctc_prefix_beam_search | 16, -1 | 7.11 | 0.082156 |  \n| conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug + shift | test-clean | attention_rescoring | 16, -1 | 7.11 | 0.071000 |  \n\n\n## Transformer\n\ntrain: Epoch 120, 4 V100-32G, 27 Day, best avg: 10\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | WER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| transformer | 32.52 M | conf/transformer.yaml | spec_aug  | test-clean | attention | 6.382194232940674 | 0.049661 |  \n| transformer | 32.52 M | conf/transformer.yaml | spec_aug  | test-clean | ctc_greedy_search | 6.382194232940674 | 0.049566 |  \n| transformer | 32.52 M | conf/transformer.yaml | spec_aug  | test-clean | ctc_prefix_beam_search | 6.382194232940674 | 0.049585 |  \n| transformer | 32.52 M | conf/transformer.yaml | spec_aug  | test-clean | attention_rescoring | 6.382194232940674 | 0.038135 |\n"
  },
  {
    "path": "examples/librispeech/asr1/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.9,\n      \"max_speed_rate\": 1.1,\n      \"num_rates\": 3\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 0,\n      \"warp_mode\": \"PIL\",\n      \"F\": 10,\n      \"n_freq_masks\": 2,\n      \"T\": 50,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": true\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/chunk_conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n    causal: True\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_5000'\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 16\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0 \nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 120\naccum_grad: 8\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-06 \nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n\n\n\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/chunk_transformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n    use_dynamic_chunk: true\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_5000'\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 120\naccum_grad: 1\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/librispeech/asr1/conf/conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    ctc_grad_norm_type: null \n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_5000'\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 16\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n  \n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 70\naccum_grad: 8\nglobal_grad_clip: 3.0\noptim: adam\noptim_conf:\n  lr: 0.004\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/transformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt\nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_5000'\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32 \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 120 \naccum_grad: 4\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.004\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: true  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/librispeech/asr1/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 64\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/librispeech/asr1/local/align.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/alignment.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\nbpeprefix=\"${dict_dir}/bpe_${bpemode}_${nbpe}\"\n\nstride_ms=10\nwindow_ms=25\nsample_rate=16000\nfeat_dim=80\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"True\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for sub in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do\n        mv data/manifest.${sub} data/manifest.${sub}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for sub in train-clean-100 train-clean-360 train-other-500; do\n        cat data/manifest.${sub}.raw >> data/manifest.train.raw\n    done\n\n    for sub in dev-clean dev-other; do\n        cat data/manifest.${sub}.raw >> data/manifest.dev.raw\n    done\n\n    for sub in test-clean test-other; do\n        cat data/manifest.${sub}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=-1 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=${feat_dim} \\\n    --delta_delta=false \\\n    --sample_rate=${sample_rate} \\\n    --stride_ms=${stride_ms} \\\n    --window_ms=${window_ms} \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type \"spm\" \\\n    --spm_vocab_size=${nbpe} \\\n    --spm_mode ${bpemode} \\\n    --spm_model_prefix ${bpeprefix} \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for sub in train dev test dev-clean dev-other test-clean test-other; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type \"spm\" \\\n        --spm_model_prefix ${bpeprefix} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${sub}.raw\" \\\n        --output_path=\"data/manifest.${sub}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\n\n    for sub in train dev; do\n        mv data/manifest.${sub} data/manifest.${sub}.fmt\n    done\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    for sub in train dev; do\n        remove_longshortdata.py --maxframes 3000 --maxchars 400 --stride_ms ${stride_ms} data/manifest.${sub}.fmt data/manifest.${sub}\n    done\nfi\n\necho \"LibriSpeech Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/download_lm_en.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL=https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm\nMD5=\"099a601759d467cd0a8523ff939819c5\"\nTARGET=${DIR}/common_crawl_00.prune01111.trie.klm\n\necho \"Download language model ...\"\ndownload $URL $MD5 $TARGET\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nexpdir=exp\ndatadir=data\nnj=32\n\nlmtag=\n\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\n\nstage=0\nstop_stage=100\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\necho \"chunk mode ${chunk_mode}\"\n\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # format the reference test file\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test-clean.raw \\\n        --trans_ref data/manifest.test-clean.text\n\n    for type in attention; do\n        echo \"decoding ${type}\"\n        if [ ${chunk_mode} == true ];then\n            # stream decoding only support batchsize=1\n            batch_size=1\n        else\n            batch_size=64\n        fi\n        python3 -u ${BIN_DIR}/test.py \\\n            --ngpu ${ngpu} \\\n            --config ${config_path} \\\n            --decode_cfg ${decode_config_path} \\\n            --result_file ${ckpt_prefix}.${type}.rsl \\\n            --checkpoint_path ${ckpt_prefix} \\\n            --opts decode.decoding_method ${type} \\\n            --opts decode.decode_batch_size ${batch_size}\n\n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n        python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n            --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n        python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n            data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n        echo \"decoding ${type} done.\"\n    done\n\n    for type in ctc_greedy_search; do\n        echo \"decoding ${type}\"\n        if [ ${chunk_mode} == true ];then\n            # stream decoding only support batchsize=1\n            batch_size=1\n        else\n            batch_size=64\n        fi\n        python3 -u ${BIN_DIR}/test.py \\\n            --ngpu ${ngpu} \\\n            --config ${config_path} \\\n            --decode_cfg ${decode_config_path} \\\n            --result_file ${ckpt_prefix}.${type}.rsl \\\n            --checkpoint_path ${ckpt_prefix} \\\n            --opts decode.decoding_method ${type} \\\n            --opts decode.decode_batch_size ${batch_size}\n\n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n        python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n            --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n        python3 utils/compute-wer.py --char=1 --v=1 \\\n            data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n        echo \"decoding ${type} done.\"\n    done\n\n\n\n    for type in ctc_prefix_beam_search attention_rescoring; do\n        echo \"decoding ${type}\"\n        batch_size=1\n        python3 -u ${BIN_DIR}/test.py \\\n            --ngpu ${ngpu} \\\n            --config ${config_path} \\\n            --decode_cfg ${decode_config_path} \\\n            --result_file ${ckpt_prefix}.${type}.rsl \\\n            --checkpoint_path ${ckpt_prefix} \\\n            --opts decode.decoding_method ${type} \\\n            --opts decode.decode_batch_size ${batch_size}\n\n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n        python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n            --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n        python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n            data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n        echo \"decoding ${type} done.\"\n    done\nfi\n\nif [ ${stage} -le 101 ] && [ ${stop_stage} -ge 101 ]; then\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_ref data/manifest.test-clean.raw \\\n        --trans_ref_sclite data/manifest.test.text-clean.sclite\n\n\n    output_dir=${ckpt_prefix}\n    for type in attention ctc_greedy_search ctc_prefix_beam_search attention_rescoring; do\n        python ${MAIN_ROOT}/utils/format_rsl.py \\\n            --origin_hyp ${output_dir}/${type}.rsl \\\n            --trans_hyp_sclite ${output_dir}/${type}.rsl.text.sclite\n\n        mkdir -p ${output_dir}/${type}_sclite\n        sclite -i wsj -r data/manifest.test-clean.text.sclite -h  ${output_dir}/${type}.rsl.text.sclite  -e utf-8 -o all -O ${output_dir}/${type}_sclite -c NOASCII\n    done\nfi\n\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\nbpeprefix=\"data/bpe_${bpemode}_${nbpe}\"\nbpemodel=${bpeprefix}.model\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nfor type in attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    #score_sclite.sh --bpe ${nbpe} --bpemodel ${bpemodel}.model --wer true ${expdir}/${decode_dir} ${dict}\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# export FLAGS_cudnn_exhaustive_search=true\n# export FLAGS_conv_workspace_size_limit=4000\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/librispeech/asr1/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/transformer.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=30\naudio_file=data/demo_002_en.wav\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n"
  },
  {
    "path": "examples/librispeech/asr2/.gitignore",
    "content": "dump\nfbank\nexp\ndata\n"
  },
  {
    "path": "examples/librispeech/asr2/README.md",
    "content": "# Transformer/Conformer ASR with Librispeech ASR2\n\nThis example contains code used to train a [u2](https://arxiv.org/pdf/2012.05481.pdf) model (Transformer or [Conformer](https://arxiv.org/pdf/2005.08100.pdf) model) with [Librispeech dataset](http://www.openslr.org/resources/12) and use some functions in kaldi.\n\nTo use this example, you need to install Kaldi first.\n\n## Overview\n\nAll the scripts you need are in ```run.sh```. There are several stages in ```run.sh```, and each stage has its function.\n\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Get the sentencepiece model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Join ctc decoder and use transformer language model to score |\n| 5     | Get ctc alignment of test data using the final model         |\n| 6     | Calculate the perplexity of transformer language model        |\n\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`dict_path` denotes the path of the vocabulary file.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"transformer\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 10\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in ```run.sh```to do this. The code is shown below:\n\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\n\nYou can also just run these scripts in your command line.\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\n\nAfter processing the data, the ``data`` directory will look like this:\n\n```bash\ndata/\n├── dev\n├── dev_clean\n├── dev-clean.meta\n├── dev_org\n├── dev_other\n├── dev-other.meta\n├── lang_char\n├── manifest.dev\n├── manifest.dev-clean\n├── manifest.dev-clean.raw\n├── manifest.dev-other\n├── manifest.dev-other.raw\n├── manifest.dev.raw\n├── manifest.test-clean\n├── manifest.test-clean.raw\n├── manifest.test-other\n├── manifest.test-other.raw\n├── manifest.test.raw\n├── manifest.train\n├── manifest.train-clean-100.raw\n├── manifest.train-clean-360.raw\n├── manifest.train-other-500.raw\n├── manifest.train.raw\n├── temp1\n├── temp2\n├── temp3\n├── test_clean\n├── test-clean.meta\n├── test_other\n├── test-other.meta\n├── train_960\n├── train_960_org\n├── train_clean_100\n├── train-clean-100.meta\n├── train_clean_360\n├── train-clean-360.meta\n├── train_other_500\n├── train-other-500.meta\n├── train_sp\n└── train_sp_org\n```\n\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in ```run.sh```. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the last K models and average the parameters of the models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh latest exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 10\n```\n## Stage 3: Model Testing\nStage 3 is to evaluate the model performance with an attention rescore decoder. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # attetion resocre decoder\n    ./local/test.sh ${conf_path} ${dict_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh latest exp/transformer/checkpoints 10\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer.yaml data/train_960_unigram5000_units.txt exp/transformer/checkpoints/avg_10\n```\n## Stage 4: Model Testing with Join CTC Decoder\nStage 4 is to evaluate the model performance with the join ctc decoder. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # join ctc decoder, use transformerlm to score\n    ./local/recog.sh  --ckpt_prefix exp/${ckpt}/checkpoints/${avg_ckpt}\nfi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 4 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\nbash run.sh --stage 4 --stop_stage 4\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh latest exp/transformer/checkpoints 10\n./local/recog.sh  --ckpt_prefix exp/transformer/checkpoints/avg_10\n```\n## Pretrained Model\nYou can get the pretrained models from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr2/asr2_transformer_librispeech_ckpt_0.1.1.model.tar.gz\ntar xzvf asr2_transformer_librispeech_ckpt_0.1.1.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\n\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer.yaml exp/ctc/checkpoints/avg_10\n```\nThe performance of the released models are shown [here](./RESULTS.md).\n\nCompare with [ESPNET](https://github.com/espnet/espnet/blob/master/egs/librispeech/asr1/RESULTS.md#pytorch-large-transformer-with-specaug-4-gpus--transformer-lm-4-gpus) we using 8gpu, but the model size (aheads4-adim256) small than it.\n## Stage 5: CTC Alignment \nIf you want to get the alignment between the audio and the text, you can use the ctc alignment. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${dict_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n```\nIf you want to train the model, test it and do the alignment, you can use the script below to execute stage 0, stage 1, stage 2, stage 3, stage 4, and stage 5:\n```bash\nbash run.sh --stage 0 --stop_stage 5\n```\nor if you only need to train a model and do the alignment, you can use these scripts to escape stage 3(test stage):\n```bash\nbash run.sh --stage 0 --stop_stage 2\nbash run.sh --stage 5 --stop_stage 5\n```\nor you can also use these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 20\nCUDA_VISIBLE_DEVICES= ./local/align.sh conf/transformer.yaml data/train_960_unigram5000_units.txt exp/transformer/checkpoints/avg_10\n```\n## Stage 6: Perplexity Calculation \nThis stage is for calculating the perplexity of the transformer language model. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/cacu_perplexity.sh || exit -1\nfi\n```\nIf you only want to calculate the perplexity of the transformer language model, you can use this script:\n\n```bash\nbash run.sh --stage 6 --stop_stage 6\n```\n"
  },
  {
    "path": "examples/librispeech/asr2/RESULTS.md",
    "content": "# LibriSpeech\n\n\n## Transformer\n\n| Model | Params | GPUS | Averaged Model | Config | Augmentation| Loss |  \n| :-: | :-: | :------------: | :------------: | :-: | :-: | :-: |     \n| transformer | 32.52M | 8 Tesla V100-SXM2-32GB | 10-best val_loss | conf/transformer.yaml | spec_aug | 6.3197922706604 |  \n\n### Attention Rescore\n\n| Test Set | Decode Method | #Snt | #Wrd | Corr | Sub | Del | Ins | Err | S.Err |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| test-clean | attention | 2620 | 52576 | 96.4 | 2.5 | 1.1 | 0.4 | 4.0 | 34.7 |  \n| test-clean | ctc_greedy_search | 2620 | 52576 | 95.9 | 3.7 | 0.4 | 0.5 | 4.6 | 48.0 |  \n| test-clean | ctc_prefix_beamsearch | 2620 | 52576 | 95.9 | 3.7 | 0.4 | 0.5 | 4.6 | 47.6 |  \n| test-clean | attention_rescore | 2620 | 52576 | 96.8 | 2.9 | 0.3 | 0.4 | 3.7 | 38.0 |  \n\n### JoinCTC\n\n| Test Set | Decode Method | #Snt | #Wrd | Corr | Sub | Del | Ins | Err | S.Err |  \n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| test-clean | join_ctc_only_att | 2620 | 52576 | 96.1 | 2.5 | 1.4 | 0.4 | 4.4 | 34.7 |  \n| test-clean | join_ctc_w/o_lm | 2620 | 52576 | 97.2 | 2.6 | 0.3 | 0.4 | 3.2 | 34.9 |  \n| test-clean | join_ctc_w_lm | 2620 | 52576 | 97.9 | 1.8 | 0.2 | 0.3 | 2.4 | 27.8 |  \n\nCompare with [ESPNET](https://github.com/espnet/espnet/blob/master/egs/librispeech/asr1/RESULTS.md#pytorch-large-transformer-with-specaug-4-gpus--transformer-lm-4-gpus)\nwe using 8gpu, but model size (aheads4-adim256) small than it.\n"
  },
  {
    "path": "examples/librispeech/asr2/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 5,\n      \"warp_mode\": \"PIL\",\n      \"F\": 30,\n      \"n_freq_masks\": 2,\n      \"T\": 40,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": false\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/decode/decode.yaml",
    "content": "batchsize: 0\nbeam-size: 60\nctc-weight: 0.4\nlm-weight: 0.6\nmaxlenratio: 0.0\nminlenratio: 0.0\npenalty: 0.0\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/decode/decode_att.yaml",
    "content": "batchsize: 0\nbeam-size: 60\nctc-weight: 0.0\nlm-weight: 0.0\nmaxlenratio: 0.0\nminlenratio: 0.0\npenalty: 0.0\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/decode/decode_base.yaml",
    "content": "decode_batch_size: 1\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/decode/decode_ctc.yaml",
    "content": "batchsize: 0\nbeam-size: 60\nctc-weight: 0.4\nlm-weight: 0.0\nmaxlenratio: 0.0\nminlenratio: 0.0\npenalty: 0.0\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/decode/decode_wo_lm.yaml",
    "content": "batchsize: 0\nbeam-size: 60\nctc-weight: 0.4\nlm-weight: 0.0\nmaxlenratio: 0.0\nminlenratio: 0.0\npenalty: 0.0"
  },
  {
    "path": "examples/librispeech/asr2/conf/fbank.conf",
    "content": "--sample-frequency=16000 \n--num-mel-bins=80\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/lm/transformer.yaml",
    "content": "model_module: transformer\n\ndata:\n    unit_type: spm\n\nmodel:\n    n_vocab: 5002\n    pos_enc: null\n    embed_unit: 128\n    att_unit: 512\n    head: 8\n    unit: 2048\n    layer: 16\n    dropout_rate: 0.5\n    emb_dropout_rate: 0.0\n    att_dropout_rate: 0.0\n    tie_weights: False \n\ndecoding:\n    batch_size: 30\n    num_workers: 2\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/pitch.conf",
    "content": "--sample-frequency=16000\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/preprocess.yaml",
    "content": "process:\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/librispeech/asr2/conf/transformer.yaml",
    "content": "# https://yaml.org/type/float.html\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file:  \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/train_960_unigram5000_units.txt\nunit_type: spm\nspm_model_prefix: data/lang_char/train_960_unigram5000\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 30 \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config: conf/preprocess.yaml \nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 120\naccum_grad: 2\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\noptim: adam\noptim_conf:\n  global_grad_clip: 5.0\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  lr: 0.004\n  warmup_steps: 25000\n  lr_decay: 1.0\n\n\n\n"
  },
  {
    "path": "examples/librispeech/asr2/local/align.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path dict_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\ndict_path=$3\nckpt_prefix=$4\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/test.py \\\n--model-name 'u2_kaldi' \\\n--run-mode 'align' \\\n--dict-path ${dict_path} \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result-file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/cacu_perplexity.sh",
    "content": "#!/bin/bash\n\nset -e\n\nstage=-1\nstop_stage=100\n\nexpdir=exp\ndatadir=data\n\nngpu=0\n\n# lm params\nrnnlm_config_path=conf/lm/transformer.yaml\nlmexpdir=exp/lm/transformer\nlang_model=transformerLM.pdparams\n\n#data path\ntest_set=${datadir}/test_clean/text\ntest_set_lower=${datadir}/test_clean/text_lower\ntrain_set=train_960\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\nbpeprefix=${datadir}/lang_char/${train_set}_${bpemode}${nbpe}\nbpemodel=${bpeprefix}.model\n\nvocabfile=${bpeprefix}_units.txt\nvocabfile_lower=${bpeprefix}_units_lower.txt\n\noutput_dir=${expdir}/lm/transformer/perplexity\n\nmkdir -p ${output_dir}\n\n# Transform the data upper case to lower\nif [ -f ${vocabfile} ]; then\n    tr A-Z a-z < ${vocabfile} > ${vocabfile_lower}\nfi\n\nif [ -f ${test_set} ]; then\n    tr A-Z a-z < ${test_set} > ${test_set_lower}\nfi\n\npython ${LM_BIN_DIR}/cacu_perplexity.py \\\n    --rnnlm ${lmexpdir}/${lang_model} \\\n    --rnnlm-conf ${rnnlm_config_path} \\\n    --vocab_path ${vocabfile_lower} \\\n    --bpeprefix ${bpeprefix} \\\n    --text_path ${test_set_lower} \\\n    --output_dir ${output_dir} \\\n    --ngpu ${ngpu}\n\n"
  },
  {
    "path": "examples/librispeech/asr2/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\nnj=32\ndebugmode=1\ndumpdir=dump   # directory to dump full features\nN=0            # number of minibatches to be used (mainly for debugging). \"0\" uses all minibatches.\nverbose=0      # verbose option\nresume=        # Resume the training from snapshot\n\n# feature configuration\ndo_delta=false\n\n# Set this to somewhere where you want to put your data, or where\n# someone else has already put it.  You'll want to change this\n# if you're not on the CLSP grid.\ndatadir=${MAIN_ROOT}/dataset/\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\n# Set bash to 'debug' mode, it will exit on :\n# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands',\nset -e\nset -u\nset -o pipefail\n\ntrain_set=train_960\ntrain_sp=train_sp\ntrain_dev=dev\nrecog_set=\"test_clean test_other dev_clean dev_other\"\n\n\nmkdir -p data\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"True\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for set in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do\n        mv data/manifest.${set} data/manifest.${set}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for set in train-clean-100 train-clean-360 train-other-500; do\n        cat data/manifest.${set}.raw >> data/manifest.train.raw\n    done\n\n    for set in dev-clean dev-other; do\n        cat data/manifest.${set}.raw >> data/manifest.dev.raw\n    done\n\n    for set in test-clean test-other; do\n        cat data/manifest.${set}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    ### Task dependent. You have to make data the following preparation part by yourself.\n    ### But you can utilize Kaldi recipes in most cases\n    echo \"stage 0: Data preparation\"\n    for part in dev-clean test-clean dev-other test-other train-clean-100 train-clean-360 train-other-500; do\n        # use underscore-separated names in data directories.\n        local/data_prep.sh ${datadir}/librispeech/${part}/LibriSpeech/${part} data/${part//-/_}\n    done\nfi\n\nfeat_tr_dir=${dumpdir}/${train_set}/delta${do_delta}; mkdir -p ${feat_tr_dir}\nfeat_sp_dir=${dumpdir}/${train_sp}/delta${do_delta}; mkdir -p ${feat_sp_dir}\nfeat_dt_dir=${dumpdir}/${train_dev}/delta${do_delta}; mkdir -p ${feat_dt_dir}\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ### Task dependent. You have to design training and dev sets by yourself.\n    ### But you can utilize Kaldi recipes in most cases\n    echo \"stage 1: Feature Generation\"\n    fbankdir=fbank\n    # Generate the fbank features; by default 80-dimensional fbanks with pitch on each frame\n    for x in dev_clean test_clean dev_other test_other train_clean_100 train_clean_360 train_other_500; do\n        steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj ${nj} --write_utt2num_frames true \\\n            data/${x} exp/make_fbank/${x} ${fbankdir}\n        utils/fix_data_dir.sh data/${x}\n    done\n\n    utils/combine_data.sh --extra_files utt2num_frames data/${train_set}_org data/train_clean_100 data/train_clean_360 data/train_other_500\n    utils/combine_data.sh --extra_files utt2num_frames data/${train_dev}_org data/dev_clean data/dev_other\n    utils/perturb_data_dir_speed.sh 0.9  data/${train_set}_org  data/temp1\n    utils/perturb_data_dir_speed.sh 1.0  data/${train_set}_org  data/temp2\n    utils/perturb_data_dir_speed.sh 1.1  data/${train_set}_org  data/temp3\n\n    utils/combine_data.sh --extra-files utt2uniq data/${train_sp}_org data/temp1 data/temp2 data/temp3\n\n    # remove utt having more than 3000 frames\n    # remove utt having more than 400 characters\n    remove_longshortdata.sh --maxframes 3000 --maxchars 400 data/${train_set}_org data/${train_set}\n    remove_longshortdata.sh --maxframes 3000 --maxchars 400 data/${train_sp}_org data/${train_sp}\n    remove_longshortdata.sh --maxframes 3000 --maxchars 400 data/${train_dev}_org data/${train_dev}\n    steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj $nj  --write_utt2num_frames true \\\n            data/train_sp  exp/make_fbank/train_sp  ${fbankdir}\n    utils/fix_data_dir.sh data/train_sp\n    # compute global CMVN\n    compute-cmvn-stats scp:data/${train_sp}/feats.scp data/${train_sp}/cmvn.ark\n\n    # dump features for training\n    dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta ${do_delta} \\\n        data/${train_sp}/feats.scp data/${train_sp}/cmvn.ark exp/dump_feats/train ${feat_sp_dir}\n    dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta ${do_delta} \\\n        data/${train_dev}/feats.scp data/${train_sp}/cmvn.ark exp/dump_feats/dev ${feat_dt_dir}\n    for rtask in ${recog_set}; do\n        feat_recog_dir=${dumpdir}/${rtask}/delta${do_delta}; mkdir -p ${feat_recog_dir}\n        dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta ${do_delta} \\\n            data/${rtask}/feats.scp data/${train_sp}/cmvn.ark exp/dump_feats/recog/${rtask} \\\n            ${feat_recog_dir}\n    done\nfi\n\ndict=data/lang_char/${train_set}_${bpemode}${nbpe}_units.txt\nbpemodel=data/lang_char/${train_set}_${bpemode}${nbpe}\necho \"dictionary: ${dict}\"\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    ### Task dependent. You have to check non-linguistic symbols used in the corpus.\n    echo \"stage 2: Dictionary and Json Data Preparation\"\n    mkdir -p data/lang_char/\n    echo \"<unk> 1\" > ${dict} # <unk> must be 1, 0 will be used for \"blank\" in CTC\n    cut -f 2- -d\" \" data/${train_set}/text > data/lang_char/input.txt\n    spm_train --input=data/lang_char/input.txt --vocab_size=${nbpe} --model_type=${bpemode} --model_prefix=${bpemodel} --input_sentence_size=100000000\n    spm_encode --model=${bpemodel}.model --output_format=piece < data/lang_char/input.txt | tr ' ' '\\n' | sort | uniq | awk '{print $0 \" \" NR+1}' >> ${dict}\n    wc -l ${dict}\n\n    # make json labels\n    data2json.sh --nj ${nj} --feat ${feat_sp_dir}/feats.scp --bpecode ${bpemodel}.model \\\n        data/${train_sp} ${dict} > ${feat_sp_dir}/data_${bpemode}${nbpe}.json\n    data2json.sh --nj ${nj} --feat ${feat_dt_dir}/feats.scp --bpecode ${bpemodel}.model \\\n        data/${train_dev} ${dict} > ${feat_dt_dir}/data_${bpemode}${nbpe}.json\n\n    for rtask in ${recog_set}; do\n        feat_recog_dir=${dumpdir}/${rtask}/delta${do_delta}\n        data2json.sh --nj ${nj} --feat ${feat_recog_dir}/feats.scp --bpecode ${bpemodel}.model \\\n            data/${rtask} ${dict} > ${feat_recog_dir}/data_${bpemode}${nbpe}.json\n    done\nfi\n\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # make json labels\n    python3 local/espnet_json_to_manifest.py --json-file ${feat_sp_dir}/data_${bpemode}${nbpe}.json --manifest-file data/manifest.train\n    python3 local/espnet_json_to_manifest.py --json-file ${feat_dt_dir}/data_${bpemode}${nbpe}.json --manifest-file data/manifest.dev\n\n    for rtask in ${recog_set}; do\n        feat_recog_dir=${dumpdir}/${rtask}/delta${do_delta}\n        python3 local/espnet_json_to_manifest.py --json-file ${feat_recog_dir}/data_${bpemode}${nbpe}.json --manifest-file data/manifest.${rtask//_/-}\n    done\nfi\n\necho \"LibriSpeech Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/data_prep.sh",
    "content": "#!/usr/bin/env bash\n\n# Copyright 2014  Vassil Panayotov\n#           2014  Johns Hopkins University (author: Daniel Povey)\n# Apache 2.0\n\nif [ \"$#\" -ne 2 ]; then\n  echo \"Usage: $0 <src-dir> <dst-dir>\"\n  echo \"e.g.: $0 /export/a15/vpanayotov/data/LibriSpeech/dev-clean data/dev-clean\"\n  exit 1\nfi\n\nsrc=$1\ndst=$2\n\n# all utterances are FLAC compressed\nif ! which flac >&/dev/null; then\n   echo \"Please install 'flac' on ALL worker nodes!\"\n   exit 1\nfi\n\nspk_file=$src/../SPEAKERS.TXT\n\nmkdir -p $dst || exit 1\n\n[ ! -d $src ] && echo \"$0: no such directory $src\" && exit 1\n[ ! -f $spk_file ] && echo \"$0: expected file $spk_file to exist\" && exit 1\n\n\nwav_scp=$dst/wav.scp; [[ -f \"$wav_scp\" ]] && rm $wav_scp\ntrans=$dst/text; [[ -f \"$trans\" ]] && rm $trans\nutt2spk=$dst/utt2spk; [[ -f \"$utt2spk\" ]] && rm $utt2spk\nspk2gender=$dst/spk2gender; [[ -f $spk2gender ]] && rm $spk2gender\n\nfor reader_dir in $(find -L $src -mindepth 1 -maxdepth 1 -type d | sort); do\n  reader=$(basename $reader_dir)\n  if ! [ $reader -eq $reader ]; then  # not integer.\n    echo \"$0: unexpected subdirectory name $reader\"\n    exit 1\n  fi\n\n  reader_gender=$(egrep \"^$reader[ ]+\\|\" $spk_file | awk -F'|' '{gsub(/[ ]+/, \"\"); print tolower($2)}')\n  if [ \"$reader_gender\" != 'm' ] && [ \"$reader_gender\" != 'f' ]; then\n    echo \"Unexpected gender: '$reader_gender'\"\n    exit 1\n  fi\n\n  for chapter_dir in $(find -L $reader_dir/ -mindepth 1 -maxdepth 1 -type d | sort); do\n    chapter=$(basename $chapter_dir)\n    if ! [ \"$chapter\" -eq \"$chapter\" ]; then\n      echo \"$0: unexpected chapter-subdirectory name $chapter\"\n      exit 1\n    fi\n\n    find -L $chapter_dir/ -iname \"*.flac\" | sort | xargs -I% basename % .flac | \\\n      awk -v \"dir=$chapter_dir\" '{printf \"%s flac -c -d -s %s/%s.flac |\\n\", $0, dir, $0}' >>$wav_scp|| exit 1\n\n    chapter_trans=$chapter_dir/${reader}-${chapter}.trans.txt\n    [ ! -f  $chapter_trans ] && echo \"$0: expected file $chapter_trans to exist\" && exit 1\n    cat $chapter_trans >>$trans\n\n    # NOTE: For now we are using per-chapter utt2spk. That is each chapter is considered\n    #       to be a different speaker. This is done for simplicity and because we want\n    #       e.g. the CMVN to be calculated per-chapter\n    awk -v \"reader=$reader\" -v \"chapter=$chapter\" '{printf \"%s %s-%s\\n\", $1, reader, chapter}' \\\n      <$chapter_trans >>$utt2spk || exit 1\n\n    # reader -> gender map (again using per-chapter granularity)\n    echo \"${reader}-${chapter} $reader_gender\" >>$spk2gender\n  done\ndone\n\nspk2utt=$dst/spk2utt\nutils/utt2spk_to_spk2utt.pl <$utt2spk >$spk2utt || exit 1\n\nntrans=$(wc -l <$trans)\nnutt2spk=$(wc -l <$utt2spk)\n! [ \"$ntrans\" -eq \"$nutt2spk\" ] && \\\n  echo \"Inconsistent #transcripts($ntrans) and #utt2spk($nutt2spk)\" && exit 1\n\nutils/validate_data_dir.sh --no-feats $dst || exit 1\n\necho \"$0: successfully prepared data in $dst\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/download_lm_en.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL=https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm\nMD5=\"099a601759d467cd0a8523ff939819c5\"\nTARGET=${DIR}/common_crawl_00.prune01111.trie.klm\n\necho \"Download language model ...\"\ndownload $URL $MD5 $TARGET\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/espnet_json_to_manifest.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport json\n\n\ndef main(args):\n    with open(args.json_file, 'r') as fin:\n        data_json = json.load(fin)\n\n    # manifest format:\n    # {\"input\": [\n    #       {\"feat\": \"dev/deltafalse/feats.1.ark:842920\", \"name\": \"input1\", \"shape\": [349, 83]}\n    #  ], \n    #  \"output\": [\n    #       {\"name\": \"target1\", \"shape\": [12, 5002], \"text\": \"NO APOLLO\", \"token\": \"▁NO ▁A PO LL O\", \"tokenid\": \"3144 482 352 269 317\"}\n    #  ], \n    #  \"utt2spk\": \"116-288045\", \n    #  \"utt\": \"116-288045-0019\"}\n    with open(args.manifest_file, 'w') as fout:\n        for key, value in data_json['utts'].items():\n            value['utt'] = key\n            fout.write(json.dumps(value, ensure_ascii=False))\n            fout.write(\"\\n\")\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        '--json-file', type=str, default=None, help=\"espnet data json file.\")\n    parser.add_argument(\n        '--manifest-file',\n        type=str,\n        default='maniefst.train',\n        help='manifest data json line file.')\n    args = parser.parse_args()\n    main(args)\n"
  },
  {
    "path": "examples/librispeech/asr2/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/test.py \\\n--model-name 'u2_kaldi' \\\n--run-mode 'export' \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/recog.sh",
    "content": "#!/bin/bash\n\nset -e\n\nexpdir=exp\ndatadir=data\nnj=32\ntag=\n\n# decode config\ndecode_config=conf/decode/decode.yaml\n\n# lm params\nrnnlm_config_path=conf/lm/transformer.yaml\nlmexpdir=exp/lm\nlang_model=rnnlm.pdparams\nlmtag='transformer'\n\ntrain_set=train_960\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\nbpeprefix=data/lang_char/${train_set}_${bpemode}${nbpe}\nbpemodel=${bpeprefix}.model\n\n# bin params\nconfig_path=conf/transformer.yaml\ndict=data/lang_char/${train_set}_${bpemode}${nbpe}_units.txt\nckpt_prefix=\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nif [ -z ${ckpt_prefix} ]; then\n    echo \"usage: $0 --ckpt_prefix ckpt_prefix\"\n    exit 1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nckpt_dir=$(dirname `dirname ${ckpt_prefix}`)\necho \"ckpt dir: ${ckpt_dir}\"\n\nckpt_tag=$(basename ${ckpt_prefix})\necho \"ckpt tag: ${ckpt_tag}\"\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\necho \"chunk mode: ${chunk_mode}\"\necho \"decode conf: ${decode_config}\"\necho \"lm conf: ${rnnlm_config_path}\"\necho \"lm model: ${lmexpdir}/${lang_model}\"\n\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\n# download rnnlm\nmkdir -p ${lmexpdir}\nif [ ! -f ${lmexpdir}/${lang_model} ]; then\n    wget -c -O ${lmexpdir}/${lang_model} https://deepspeech.bj.bcebos.com/transformer_lm/transformerLM.pdparams\nfi\n\n\npids=() # initialize pids\n\nfor dmethd in join_ctc; do\n(\n    echo \"${dmethd} decoding\"\n    for rtask in ${recog_set}; do\n    (\n        echo \"${rtask} dataset\"\n        decode_dir=${ckpt_dir}/decode/decode_${rtask/-/_}_${dmethd}_$(basename ${config_path%.*})_${lmtag}_${ckpt_tag}_${tag}\n        feat_recog_dir=${datadir}\n        mkdir -p ${decode_dir}\n        mkdir -p ${feat_recog_dir}\n\n        # split data\n        split_json.sh manifest.${rtask} ${nj}\n\n        #### use CPU for decoding\n        ngpu=0\n\n        # set batchsize 0 to disable batch decoding\n        ${decode_cmd} JOB=1:${nj} ${decode_dir}/log/decode.JOB.log \\\n            python3 -u ${BIN_DIR}/recog.py \\\n                --api v2 \\\n                --config ${decode_config} \\\n                --ngpu ${ngpu} \\\n                --batchsize 0 \\\n                --checkpoint_path ${ckpt_prefix} \\\n                --dict-path ${dict} \\\n                --recog-json ${feat_recog_dir}/split${nj}/JOB/manifest.${rtask} \\\n                --result-label ${decode_dir}/data.JOB.json \\\n                --model-conf ${config_path} \\\n                --model ${ckpt_prefix}.pdparams \\\n                --rnnlm-conf ${rnnlm_config_path} \\\n                --rnnlm ${lmexpdir}/${lang_model}\n\n        score_sclite.sh --bpe ${nbpe} --bpemodel ${bpemodel} --wer false ${decode_dir} ${dict}\n\n    ) &\n    pids+=($!) # store background pids\n    i=0; for pid in \"${pids[@]}\"; do wait ${pid} || ((++i)); done\n    [ ${i} -gt 0 ] && echo \"$0: ${i} background jobs are failed.\" || true\n    done\n)\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nexpdir=exp\ndatadir=data\nnj=32\n\nlmtag='nolm'\n\ntrain_set=train_960\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\n# bpemode (unigram or bpe)\nnbpe=5000\nbpemode=unigram\nbpeprefix=data/lang_char/${train_set}_${bpemode}${nbpe}\nbpemodel=${bpeprefix}.model\n\nconfig_path=conf/transformer.yaml\ndecode_config_path=conf/decode/decode_base.yaml\ndict=data/lang_char/${train_set}_${bpemode}${nbpe}_units.txt\nckpt_prefix=\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nif [ -z ${ckpt_prefix} ]; then\n    echo \"usage: $0 --ckpt_prefix ckpt_prefix\"\n    exit 1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nckpt_dir=$(dirname `dirname ${ckpt_prefix}`)\necho \"ckpt dir: ${ckpt_dir}\"\n\nckpt_tag=$(basename ${ckpt_prefix})\necho \"ckpt tag: ${ckpt_tag}\"\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\necho \"chunk mode: ${chunk_mode}\"\n\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\npids=() # initialize pids\n\nfor dmethd in attention ctc_greedy_search ctc_prefix_beam_search attention_rescoring; do\n(\n    echo \"decode method: ${dmethd}\"\n    for rtask in ${recog_set}; do\n    (\n        echo \"dataset: ${rtask}\"\n        decode_dir=${ckpt_dir}/decode/decode_${rtask/-/_}_${dmethd}_$(basename ${config_path%.*})_${lmtag}_${ckpt_tag}\n        feat_recog_dir=${datadir}\n        mkdir -p ${decode_dir}\n        mkdir -p ${feat_recog_dir}\n\n        # split data\n        split_json.sh manifest.${rtask} ${nj}\n\n        #### use CPU for decoding\n        ngpu=0\n\n        # set batchsize 0 to disable batch decoding\n        batch_size=1\n        ${decode_cmd} JOB=1:${nj} ${decode_dir}/log/decode.JOB.log \\\n            python3 -u ${BIN_DIR}/test.py \\\n            --model-name u2_kaldi \\\n            --run-mode test \\\n            --ngpu ${ngpu} \\\n            --dict-path ${dict} \\\n            --config ${config_path} \\\n            --decode_cfg ${decode_config_path} \\\n            --checkpoint_path ${ckpt_prefix} \\\n            --result-file ${decode_dir}/data.JOB.json \\\n            --opts decode.decoding_method ${dmethd} \\\n            --opts decode.decode_batch_size ${batch_size} \\\n            --opts test_manifest ${feat_recog_dir}/split${nj}/JOB/manifest.${rtask}\n\n        score_sclite.sh --bpe ${nbpe} --bpemodel ${bpemodel} --wer false ${decode_dir} ${dict}\n\n    ) &\n    pids+=($!) # store background pids\n    i=0; for pid in \"${pids[@]}\"; do wait ${pid} || ((++i)); done\n    [ ${i} -gt 0 ] && echo \"$0: ${i} background jobs are failed.\" || true\n    done\n)\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--model-name u2_kaldi \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--model-name u2_kaldi \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr2/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${MAIN_ROOT}/utils:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2_kaldi\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n\nLM_MODEL=transformer\nexport LM_BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/lm/${LM_MODEL}/bin\n\n\n# srilm\nexport LIBLBFGS=${MAIN_ROOT}/tools/liblbfgs-1.10\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:${LIBLBFGS}/lib/.libs\nexport SRILM=${MAIN_ROOT}/tools/srilm\nexport PATH=${PATH}:${SRILM}/bin:${SRILM}/bin/i686-m64\n\n# Kaldi\nexport KALDI_ROOT=${MAIN_ROOT}/tools/kaldi\n[ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh\nexport PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH\n[ ! -f $KALDI_ROOT/tools/config/common_path.sh ] && echo >&2 \"The standard file $KALDI_ROOT/tools/config/common_path.sh is not present, can not using Kaldi!\"\n[ -f $KALDI_ROOT/tools/config/common_path.sh ] && . $KALDI_ROOT/tools/config/common_path.sh\n"
  },
  {
    "path": "examples/librispeech/asr2/run.sh",
    "content": "#!/bin/bash\n\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2,3,4,5,6,7\nstage=0\nstop_stage=50\nconf_path=conf/transformer.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/decode/decode_base.yaml\ndict_path=data/lang_char/train_960_unigram5000_units.txt\navg_num=10\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh latest exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # attetion resocre decoder\n    ./local/test.sh ${conf_path} ${decode_conf_path} ${dict_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # join ctc decoder, use transformerlm to score\n    ./local/recog.sh  --ckpt_prefix exp/${ckpt}/checkpoints/${avg_ckpt}\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} ${dict_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/cacu_perplexity.sh || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n    # export ckpt avg_n\n    ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\n\n"
  },
  {
    "path": "examples/librispeech/asr3/README.md",
    "content": "# Wav2vec2ASR with Librispeech\nThis example contains code used to finetune [wav2vec2.0](https://https://arxiv.org/pdf/2006.11477.pdf) model with [Librispeech dataset](http://www.openslr.org/resources/12)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Download the pretrained wav2vec2 model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Infer the single audio file                                  |\n\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"wav2vec2ASR\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- bpe_unigram_5000.model\n|   `-- bpe_unigram_5000.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n\nStage 0 also downloads the pre-trained [wav2vec2](https://paddlespeech.cdn.bcebos.com/wav2vec/wav2vec2-large-960h-lv60-self.pdparams) model.\n```bash\nmkdir -p exp/wav2vec2\nwget -P exp/wav2vec2 https://paddlespeech.cdn.bcebos.com/wav2vec/wav2vec2-large-960h-lv60-self.pdparams\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below. Note: We only train one epoch for wav2vec2ASR, thus the `avg_num` is set to 1.\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\navg.sh best exp/wav2vec2ASR/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wav2vec2ASR.yaml wav2vec2ASR\navg.sh best exp/wav2vec2ASR/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1\n```\n## Pretrained Model\nYou can get the pretrained wav2vec2ASR from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr3/wav2vec2ASR-large-960h-librispeech_ckpt_1.3.0.model.tar.gz\ntar xzvf wav2vec2ASR-large-960h-librispeech_ckpt_1.3.0.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n\n## Stage 4: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr3/wav2vec2ASR-large-960h-librispeech_ckpt_1.3.0.model.tar.gz\ntar xzvf wav2vec2ASR-large-960h-librispeech_ckpt_1.3.0.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/wav2vec2ASR.yaml conf/tuning/decode.yaml exp/wav2vec2ASR/checkpoints/avg_1 data/demo_002_en.wav\n```\n"
  },
  {
    "path": "examples/librispeech/asr3/RESULTS.md",
    "content": "# LibriSpeech\n\n## Wav2VecASR\ntrain: Epoch 1, 1*V100-32G, batchsize: 6\n\n| Model | Params | Config | Augmentation| Test set | Decode method | WER |  \n| --- | --- | --- | --- | --- | --- | --- |\n| wav2vec2ASR | 302.86 M | conf/wav2vec2ASR.yaml | spec_aug | test-clean | greedy search | 0.018906 |  \n"
  },
  {
    "path": "examples/librispeech/asr3/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr3/conf/preprocess.yaml",
    "content": "process:\n    # use raw audio\n  - type: wav_process\n"
  },
  {
    "path": "examples/librispeech/asr3/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 1\nerror_rate_type: wer\ndecoding_method: ctc_greedy_search  # 'ctc_greedy_search', 'ctc_prefix_beam_search'\nbeam_size: 10\n"
  },
  {
    "path": "examples/librispeech/asr3/conf/wav2vec2ASR.yaml",
    "content": "############################################\n#          Network Architecture           #\n############################################\nfreeze_wav2vec2: True\nnormalize_wav: True\noutput_norm: True\ninit_type: 'kaiming_uniform' # !Warning: need to convergence\nenc:\n  input_shape: 1024\n  dnn_blocks: 2\n  dnn_neurons: 1024\n  activation: True\nctc:\n  enc_n_units: 1024\n  blank_id: 0\n  dropout_rate: 0.0\nwav2vec2_params_path: \"exp/wav2vec2/wav2vec2-large-960h-lv60-self.pdparams\"\n\n############################################\n#               Wav2Vec2.0                 #\n############################################\nhidden_size: 1024\nnum_hidden_layers: 24\nnum_attention_heads: 16\nintermediate_size: 4096\nhidden_act: \"gelu\"\nhidden_dropout: 0.1\nactivation_dropout: 0.1\nattention_dropout: 0.1\nfeat_proj_dropout: 0.1\nfeat_quantizer_dropout: 0.0\nfinal_dropout: 0.1\nlayerdrop: 0.1\ninitializer_range: 0.02\nlayer_norm_eps: 1e-5\nfeat_extract_norm: \"layer\"\nfeat_extract_activation: \"gelu\"\nconv_dim: [512, 512, 512, 512, 512, 512, 512]\nconv_stride: [5, 2, 2, 2, 2, 2, 2]\nconv_kernel: [10, 3, 3, 3, 3, 2, 2]\nconv_bias: True\nnum_conv_pos_embeddings: 128\nnum_conv_pos_embedding_groups: 16\ndo_stable_layer_norm: True\napply_spec_augment: False\nmask_time_prob: 0.05\nmask_time_length: 10\nmask_time_min_masks: 2\nmask_feature_prob: 0.0\nmask_feature_length: 10\nmask_feature_min_masks: 0\nnum_codevectors_per_group: 320\nnum_codevector_groups: 2\ncontrastive_logits_temperature: 0.1\nnum_negatives: 100\ncodevector_dim: 256\nproj_codevector_dim: 256\ndiversity_loss_weight: 0.1\nctc_loss_reduction: \"sum\"\nctc_zero_infinity: False\nuse_weighted_layer_sum: False\nadd_adapter: False\nadapter_kernel_size: 3\nadapter_stride: 2\nnum_adapter_layers: 3\noutput_hidden_size: None\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'char'\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nsortagrad: -1 # Feed samples from shortest to longest ; -1: enabled for all epochs 0: disabled other: enabled for 'other' epochs \nbatch_size: 6  # Different batch_size may cause large differences in results\nmaxlen_in: 51200000000  # if input length  > maxlen-in batchsize is automatically reduced\nmaxlen_out: 1500000  # if output length > maxlen-out batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\ndist_sampler: True\nshortest_first: True\nreturn_lens_rate: True\n  \n############################################\n#             Data Augmentation            #\n############################################\naudio_augment:  # for raw audio \n  sample_rate: 16000\n  speeds: [95, 100, 105]\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 1\naccum_grad: 1\nglobal_grad_clip: 5.0\nmodel_optim: adadelta\nmodel_optim_conf:\n  lr: 0.9\n  epsilon: 1.0e-6\n  rho: 0.95\nmodel_scheduler: constantlr    \nmodel_scheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nwav2vec2_optim: adadelta\nwav2vec2_optim_conf:\n  lr: 0.9\n  epsilon: 1.0e-6\n  rho: 0.95\nwav2vec2_scheduler: constantlr    \nwav2vec2_scheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/librispeech/asr3/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\nunit_type=char\ndict_dir=data/lang_char\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"True\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for set in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do\n        mv data/manifest.${set} data/manifest.${set}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for set in train-clean-100 train-clean-360 train-other-500; do\n        cat data/manifest.${set}.raw >> data/manifest.train.raw\n    done\n\n    for set in dev-clean dev-other; do\n        cat data/manifest.${set}.raw >> data/manifest.dev.raw\n    done\n\n    for set in test-clean test-other; do\n        cat data/manifest.${set}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=2000 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=161 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test dev-clean dev-other test-clean test-other; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type ${unit_type} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest.${set} failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"LibriSpeech Data preparation done.\"\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    mkdir -p exp/wav2vec2\n    echo \"Pretrained wav2vec2 model download\"\n    wget -P exp/wav2vec2 https://paddlespeech.cdn.bcebos.com/wav2vec/wav2vec2-large-960h-lv60-self.pdparams\nfi\n\nexit 0"
  },
  {
    "path": "examples/librispeech/asr3/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nexpdir=exp\ndatadir=data\n\ntrain_set=train_960\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\npython3 ${MAIN_ROOT}/utils/format_rsl.py \\\n    --origin_ref data/manifest.test-clean.raw \\\n    --trans_ref data/manifest.test-clean.text\n\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=16\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\nfor type in ctc_prefix_beam_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr3/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr3/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nresume=$3\nips=$4\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=1988\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# export FLAGS_cudnn_exhaustive_search=true\n# export FLAGS_conv_workspace_size_limit=4000\nexport FLAGS_allocator_strategy=naive_best_fit\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr3/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/wav2vec2/bin\n"
  },
  {
    "path": "examples/librispeech/asr3/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0\nstage=0\nstop_stage=4\nconf_path=conf/wav2vec2ASR.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=1\nresume=         # xx e.g. 30\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\naudio_file=data/demo_002_en.wav\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${resume} ${ips} \nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # greedy search decoder\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi"
  },
  {
    "path": "examples/librispeech/asr4/README.md",
    "content": "# Hubert2ASR with Librispeech\nThis example contains code used to finetune [hubert](https://arxiv.org/abs/2106.07447) model with [Librispeech dataset](http://www.openslr.org/resources/12)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Download the pretrained wav2vec2 model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Infer the single audio file                                  |\n\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"hubertASR\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- bpe_unigram_5000.model\n|   `-- bpe_unigram_5000.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n\nStage 0 also downloads the pre-trained [hubert](https://paddlespeech.cdn.bcebos.com/hubert/hubert-large-lv60.pdparams) model.\n```bash\nmkdir -p exp/hubert\nwget -P exp/hubert https://paddlespeech.cdn.bcebos.com/hubert/hubert-large-lv60.pdparams\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/hubertASR.yaml hubertASR\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below. Note: We only train one epoch for hubertASR, thus the `avg_num` is set to 1.\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/hubertASR.yaml hubertASR\navg.sh best exp/hubertASR/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/hubertASR.yaml hubertASR\navg.sh best exp/hubertASR/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/hubertASR.yaml conf/tuning/decode.yaml exp/hubertASR/checkpoints/avg_1\n```\n## Pretrained Model\nYou can get the pretrained hubertASR from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/hubert/hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz\ntar xzvf hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/hubertASR.yaml conf/tuning/decode.yaml exp/hubertASR/checkpoints/avg_1\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n\n## Stage 4: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/hubert/hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz\ntar xzvf hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/hubertASR.yaml conf/tuning/decode.yaml exp/hubertASR/checkpoints/avg_1 data/demo_002_en.wav\n```\n"
  },
  {
    "path": "examples/librispeech/asr4/RESULTS.md",
    "content": "# LibriSpeech\n\n## hubertASR\nFintuning on train-clean-100\ntrain: Epoch 3, 1*V100-32G, batchsize: 4, accum_grad: 8\n\n| Model | Params | Config | Augmentation| Test set | Decode method | WER |  \n| --- | --- | --- | --- | --- | --- | --- |\n| hubertASR | 326.16M | conf/hubertASR.yaml | spec_aug | test-clean | greedy search | 0.05868 |  \n"
  },
  {
    "path": "examples/librispeech/asr4/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr4/conf/config.json",
    "content": "{\n  \"_name_or_path\": \"facebook/hubert-large-ll60k\",\n  \"activation_dropout\": 0.0,\n  \"apply_spec_augment\": true,\n  \"architectures\": [\n    \"HubertModel\"\n  ],\n  \"attention_dropout\": 0.1,\n  \"bos_token_id\": 1,\n  \"conv_bias\": true,\n  \"conv_dim\": [\n    512,\n    512,\n    512,\n    512,\n    512,\n    512,\n    512\n  ],\n  \"conv_kernel\": [\n    10,\n    3,\n    3,\n    3,\n    3,\n    2,\n    2\n  ],\n  \"conv_stride\": [\n    5,\n    2,\n    2,\n    2,\n    2,\n    2,\n    2\n  ],\n  \"ctc_loss_reduction\": \"sum\",\n  \"ctc_zero_infinity\": false,\n  \"do_stable_layer_norm\": true,\n  \"eos_token_id\": 2,\n  \"feat_extract_activation\": \"gelu\",\n  \"feat_extract_dropout\": 0.0,\n  \"feat_extract_norm\": \"layer\",\n  \"feat_proj_dropout\": 0.1,\n  \"final_dropout\": 0.0,\n  \"gradient_checkpointing\": false,\n  \"hidden_act\": \"gelu\",\n  \"hidden_dropout\": 0.1,\n  \"hidden_size\": 1024,\n  \"initializer_range\": 0.02,\n  \"intermediate_size\": 4096,\n  \"layer_norm_eps\": 1e-05,\n  \"layerdrop\": 0.1,\n  \"mask_channel_length\": 10,\n  \"mask_channel_min_space\": 1,\n  \"mask_channel_other\": 0.0,\n  \"mask_channel_prob\": 0.0,\n  \"mask_channel_selection\": \"static\",\n  \"mask_feature_length\": 10,\n  \"mask_feature_prob\": 0.0,\n  \"mask_time_length\": 10,\n  \"mask_time_min_space\": 1,\n  \"mask_time_other\": 0.0,\n  \"mask_time_prob\": 0.075,\n  \"mask_time_selection\": \"static\",\n  \"model_type\": \"hubert\",\n  \"num_attention_heads\": 16,\n  \"num_conv_pos_embedding_groups\": 16,\n  \"num_conv_pos_embeddings\": 128,\n  \"num_feat_extract_layers\": 7,\n  \"num_hidden_layers\": 24,\n  \"pad_token_id\": 0,\n  \"transformers_version\": \"4.10.0.dev0\",\n  \"vocab_size\": 32,\n  \"tokenizer_class\": \"Wav2Vec2CTCTokenizer\"\n}\n"
  },
  {
    "path": "examples/librispeech/asr4/conf/hubertASR.yaml",
    "content": "############################################\n#          Network Architecture           #\n############################################\nfreeze_hubert: False\nnormalize_wav: True\noutput_norm: True\ninit_type: kaiming_uniform # !Warning: need to convergence\nenc:\n  input_shape: 1024\n  dnn_blocks: 2\n  dnn_neurons: 1024\n  activation: True\nctc:\n  enc_n_units: 1024\n  blank_id: 0\n  dropout_rate: 0.0\nhubert_params_path: \"exp/hubert/hubert-large-lv60.pdparams\"\n\n\ntask_cfg:\n  label_rate: 50.0\n  sample_rate: 16000\n  normalize: True\n  enable_padding: False\n  max_keep_size: None\n  max_sample_size: 250000\n  min_sample_size: 32000\n  single_target: False\n  random_crop: True\n  pad_audio: False\n\nmodel_cfg:\n  dropout_input: 0.0\n  final_dropout: 0.0\n  dropout: 0.0\n  attention_dropout: 0.0\n  activation_dropout: 0.1\n  apply_mask: True\n  mask_length: 10\n  mask_prob: 0.5\n  mask_selection: static\n  mask_other: 0.0\n  no_mask_overlap: False\n  mask_channel_length: 64\n  mask_channel_prob: 0.25\n  mask_channel_selection: static\n  mask_channel_other: 0.0\n  no_mask_channel_overlap: False\n  feature_grad_mult: 0.0\n  layerdrop: 0.1\n  normalize: True\n  fp16: True\n  label_rate: 50\n  extractor_mode: layer_norm\n  encoder_layers: 24\n  encoder_embed_dim: 1024\n  encoder_ffn_embed_dim: 4096\n  encoder_attention_heads: 16\n  activation_fn: gelu\n  encoder_layerdrop: 0.1\n  dropout_features: 0.0\n  final_dim: 768\n  untie_final_proj: True\n  layer_norm_first: True\n  conv_feature_layers: \"[(512,10,5)] + [(512,3,2)] * 4 + [(512,2,2)] * 2\"\n  conv_bias: False\n  logit_temp: 0.1\n  target_glu: False\n  mask_min_space: 1\n  mask_channel_min_space: 1\n  conv_pos: 128\n  conv_pos_groups: 16\n  latent_temp: [2.0, 0.5, 0.999995]\n  skip_masked: False\n  skip_nomask: True\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train-clean-100\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: char\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nsortagrad: -1 # Feed samples from shortest to longest ; -1: enabled for all epochs 0: disabled other: enabled for other epochs \nbatch_size: 4  # Different batch_size may cause large differences in results\nmaxlen_in: 1500  # if input length  > maxlen-in batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\ndist_sampler: True\nshortest_first: True\nreturn_lens_rate: True\n  \n############################################\n#             Data Augmentation            #\n############################################\naudio_augment:  # for raw audio \n  sample_rate: 16000\n  speeds: [95, 100, 105]\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 3\naccum_grad: 8\nglobal_grad_clip: 5.0\nmodel_optim: adadelta\nmodel_optim_conf:\n  lr: 1.0\n  epsilon: 1.0e-6\n  rho: 0.95\nmodel_scheduler: constantlr    \nmodel_scheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nhubert_optim: adadelta\nhubert_optim_conf:\n  lr: 0.95\n  epsilon: 1.0e-6\n  rho: 0.95\nhubert_scheduler: constantlr    \nhubert_scheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/librispeech/asr4/conf/preprocess.yaml",
    "content": "process:\n    # use raw audio\n  - type: wav_process\n"
  },
  {
    "path": "examples/librispeech/asr4/conf/preprocessor_config.json",
    "content": "{\n  \"do_normalize\": true,\n  \"feature_extractor_type\": \"Wav2Vec2FeatureExtractor\",\n  \"feature_size\": 1,\n  \"padding_side\": \"right\",\n  \"padding_value\": 0,\n  \"return_attention_mask\": true,\n  \"sampling_rate\": 16000\n}\n"
  },
  {
    "path": "examples/librispeech/asr4/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 1\nerror_rate_type: wer\ndecoding_method: ctc_greedy_search  # 'ctc_greedy_search', 'ctc_prefix_beam_search'\nbeam_size: 10\n"
  },
  {
    "path": "examples/librispeech/asr4/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\nunit_type=char\ndict_dir=data/lang_char\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"True\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for set in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do\n        mv data/manifest.${set} data/manifest.${set}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for set in train-clean-100 train-clean-360 train-other-500; do\n        cat data/manifest.${set}.raw >> data/manifest.train.raw\n    done\n\n    for set in dev-clean dev-other; do\n        cat data/manifest.${set}.raw >> data/manifest.dev.raw\n    done\n\n    for set in test-clean test-other; do\n        cat data/manifest.${set}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=2000 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=161 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test dev-clean dev-other test-clean test-other; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type ${unit_type} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest.${set} failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"LibriSpeech Data preparation done.\"\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    mkdir -p exp/hubert\n    echo \"Pretrained hubert model download\"\n    wget -P exp/hubert https://paddlespeech.cdn.bcebos.com/hubert/hubert-large-lv60.pdparams\nfi\n\nexit 0"
  },
  {
    "path": "examples/librispeech/asr4/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nexpdir=exp\ndatadir=data\n\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\npython3 ${MAIN_ROOT}/utils/format_rsl.py \\\n    --origin_ref data/manifest.test-clean.raw \\\n    --trans_ref data/manifest.test-clean.text\n\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=16\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\nfor type in ctc_prefix_beam_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 ${MAIN_ROOT}/utils/compute-wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr4/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr4/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nresume=$3\nips=$4\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=1988\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# export FLAGS_cudnn_exhaustive_search=true\n# export FLAGS_conv_workspace_size_limit=4000\nexport FLAGS_allocator_strategy=naive_best_fit\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr4/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/hubert/bin\n"
  },
  {
    "path": "examples/librispeech/asr4/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0\nstage=0\nstop_stage=0\nconf_path=conf/hubertASR.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=1\nresume=         # xx e.g. 30\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\naudio_file=data/demo_002_en.wav\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${resume} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # greedy search decoder\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr5/README.md",
    "content": "# WavLM2ASR with Librispeech\nThis example contains code used to finetune [WavLM](https://arxiv.org/abs/2110.13900) model with [Librispeech dataset](http://www.openslr.org/resources/12)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Download the pretrained wav2vec2 model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Infer the single audio file                                  |\n\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"WavLMASR\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 20\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- bpe_unigram_5000.model\n|   `-- bpe_unigram_5000.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n\nStage 0 also downloads the pre-trained [wavlm](https://paddlespeech.cdn.bcebos.com/wavlm/wavlm-base-plus.pdparams) model.\n```bash\nmkdir -p exp/wavlm\nwget -P exp/wavlm https://paddlespeech.cdn.bcebos.com/wavlm/wavlm-base-plus.pdparams\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wavlmASR.yaml wavlmASR\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below. Note: We only train one epoch for wavlmASR, thus the `avg_num` is set to 1.\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wavlmASR.yaml wavlmASR\navg.sh best exp/wavlmASR/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/wavlmASR.yaml wavlmASR\navg.sh best exp/wavlmASR/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wavlmASR.yaml conf/tuning/decode.yaml exp/wavlmASR/checkpoints/avg_1\n```\n## Pretrained Model\nYou can get the pretrained wavlmASR from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/wavlm/wavlmASR-base-100h-librispeech_ckpt_1.4.0.model.tar.gz\ntar xzvf wavlmASR-base-100h-librispeech_ckpt_1.4.0.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/wavlmASR.yaml conf/tuning/decode.yaml exp/wavlmASR/checkpoints/avg_1\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n\n## Stage 4: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/wavlm/wavlm_baseplus_libriclean_100h.tar.gz\ntar xzvf wavlm_baseplus_libriclean_100h.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/wavlmASR.yaml conf/tuning/decode.yaml exp/wavlmASR/checkpoints/avg_1 data/demo_002_en.wav\n```\n"
  },
  {
    "path": "examples/librispeech/asr5/RESULTS.md",
    "content": "# LibriSpeech\n\n## WavLMASR\nFintuning on train-clean-100\ntrain: Epoch 16, 4*A800-80G, batchsize: 16, accum_grad: 8\n\n| Model | Params | Config | Augmentation| Test set | Decode method | WER |  \n| --- | --- | --- | --- | --- | --- | --- |\n| WavLMASR | 326.16M | conf/wavlmasr.yaml | spec_aug | test-clean | greedy search | 0.0561 |  \n"
  },
  {
    "path": "examples/librispeech/asr5/avg.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ]; then\n    echo \"usage: ${0} [best|latest] ckpt_dir avg_num\"\n    exit -1\nfi\n\navg_mode=${1} # best,latest\nckpt_dir=${2}\naverage_num=${3}\ndecode_checkpoint=${ckpt_dir}/avg_${average_num}.pdparams\n\nif [ $avg_mode == best ];then\n    # best\n    python avg_model.py \\\n    --dst_model ${decode_checkpoint} \\\n    --ckpt_dir ${ckpt_dir}  \\\n    --num ${average_num} \\\n    --val_best\nelse\n    # latest\n    python avg_model.py \\\n    --dst_model ${decode_checkpoint} \\\n    --ckpt_dir ${ckpt_dir}  \\\n    --num ${average_num}\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in avg ckpt!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr5/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/librispeech/asr5/compute_wer.py",
    "content": "# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n# flake8: noqa\nimport codecs\nimport re\nimport sys\nimport unicodedata\n\nremove_tag = True\nspacelist = [' ', '\\t', '\\r', '\\n']\npuncts = [\n    '!', ',', '?', '、', '。', '！', '，', '；', '？', '：', '「', '」', '︰', '『', '』',\n    '《', '》'\n]\n\n\ndef characterize(string):\n    res = []\n    i = 0\n    while i < len(string):\n        char = string[i]\n        if char in puncts:\n            i += 1\n            continue\n        cat1 = unicodedata.category(char)\n        #https://unicodebook.readthedocs.io/unicode.html#unicode-categories\n        if cat1 == 'Zs' or cat1 == 'Cn' or char in spacelist:  # space or not assigned\n            i += 1\n            continue\n        if cat1 == 'Lo':  # letter-other\n            res.append(char)\n            i += 1\n        else:\n            # some input looks like: <unk><noise>, we want to separate it to two words.\n            sep = ' '\n            if char == '<': sep = '>'\n            j = i + 1\n            while j < len(string):\n                c = string[j]\n                if ord(c) >= 128 or (c in spacelist) or (c == sep):\n                    break\n                j += 1\n            if j < len(string) and string[j] == '>':\n                j += 1\n            res.append(string[i:j])\n            i = j\n    return res\n\n\ndef stripoff_tags(x):\n    if not x: return ''\n    chars = []\n    i = 0\n    T = len(x)\n    while i < T:\n        if x[i] == '<':\n            while i < T and x[i] != '>':\n                i += 1\n            i += 1\n        else:\n            chars.append(x[i])\n            i += 1\n    return ''.join(chars)\n\n\ndef normalize(sentence, ignore_words, cs, split=None):\n    \"\"\" sentence, ignore_words are both in unicode\n    \"\"\"\n    new_sentence = []\n    for token in sentence:\n        x = token\n        if not cs:\n            x = x.upper()\n        if x in ignore_words:\n            continue\n        if remove_tag:\n            x = stripoff_tags(x)\n        if not x:\n            continue\n        if split and x in split:\n            new_sentence += split[x]\n        else:\n            new_sentence.append(x)\n    return new_sentence\n\n\nclass Calculator:\n    def __init__(self):\n        self.data = {}\n        self.space = []\n        self.cost = {}\n        self.cost['cor'] = 0\n        self.cost['sub'] = 1\n        self.cost['del'] = 1\n        self.cost['ins'] = 1\n\n    def calculate(self, lab, rec):\n        # Initialization\n        lab.insert(0, '')\n        rec.insert(0, '')\n        while len(self.space) < len(lab):\n            self.space.append([])\n        for row in self.space:\n            for element in row:\n                element['dist'] = 0\n                element['error'] = 'non'\n            while len(row) < len(rec):\n                row.append({'dist': 0, 'error': 'non'})\n        for i in range(len(lab)):\n            self.space[i][0]['dist'] = i\n            self.space[i][0]['error'] = 'del'\n        for j in range(len(rec)):\n            self.space[0][j]['dist'] = j\n            self.space[0][j]['error'] = 'ins'\n        self.space[0][0]['error'] = 'non'\n        for token in lab:\n            if token not in self.data and len(token) > 0:\n                self.data[token] = {\n                    'all': 0,\n                    'cor': 0,\n                    'sub': 0,\n                    'ins': 0,\n                    'del': 0\n                }\n        for token in rec:\n            if token not in self.data and len(token) > 0:\n                self.data[token] = {\n                    'all': 0,\n                    'cor': 0,\n                    'sub': 0,\n                    'ins': 0,\n                    'del': 0\n                }\n        # Computing edit distance\n        for i, lab_token in enumerate(lab):\n            for j, rec_token in enumerate(rec):\n                if i == 0 or j == 0:\n                    continue\n                min_dist = sys.maxsize\n                min_error = 'none'\n                dist = self.space[i - 1][j]['dist'] + self.cost['del']\n                error = 'del'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                dist = self.space[i][j - 1]['dist'] + self.cost['ins']\n                error = 'ins'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                if lab_token == rec_token:\n                    dist = self.space[i - 1][j - 1]['dist'] + self.cost['cor']\n                    error = 'cor'\n                else:\n                    dist = self.space[i - 1][j - 1]['dist'] + self.cost['sub']\n                    error = 'sub'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                self.space[i][j]['dist'] = min_dist\n                self.space[i][j]['error'] = min_error\n        # Tracing back\n        result = {\n            'lab': [],\n            'rec': [],\n            'all': 0,\n            'cor': 0,\n            'sub': 0,\n            'ins': 0,\n            'del': 0\n        }\n        i = len(lab) - 1\n        j = len(rec) - 1\n        while True:\n            if self.space[i][j]['error'] == 'cor':  # correct\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['cor'] = self.data[lab[i]]['cor'] + 1\n                    result['all'] = result['all'] + 1\n                    result['cor'] = result['cor'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, rec[j])\n                i = i - 1\n                j = j - 1\n            elif self.space[i][j]['error'] == 'sub':  # substitution\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['sub'] = self.data[lab[i]]['sub'] + 1\n                    result['all'] = result['all'] + 1\n                    result['sub'] = result['sub'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, rec[j])\n                i = i - 1\n                j = j - 1\n            elif self.space[i][j]['error'] == 'del':  # deletion\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['del'] = self.data[lab[i]]['del'] + 1\n                    result['all'] = result['all'] + 1\n                    result['del'] = result['del'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, \"\")\n                i = i - 1\n            elif self.space[i][j]['error'] == 'ins':  # insertion\n                if len(rec[j]) > 0:\n                    self.data[rec[j]]['ins'] = self.data[rec[j]]['ins'] + 1\n                    result['ins'] = result['ins'] + 1\n                result['lab'].insert(0, \"\")\n                result['rec'].insert(0, rec[j])\n                j = j - 1\n            elif self.space[i][j]['error'] == 'non':  # starting point\n                break\n            else:  # shouldn't reach here\n                print(\n                    'this should not happen , i = {i} , j = {j} , error = {error}'.\n                    format(i=i, j=j, error=self.space[i][j]['error']))\n        return result\n\n    def overall(self):\n        result = {'all': 0, 'cor': 0, 'sub': 0, 'ins': 0, 'del': 0}\n        for token in self.data:\n            result['all'] = result['all'] + self.data[token]['all']\n            result['cor'] = result['cor'] + self.data[token]['cor']\n            result['sub'] = result['sub'] + self.data[token]['sub']\n            result['ins'] = result['ins'] + self.data[token]['ins']\n            result['del'] = result['del'] + self.data[token]['del']\n        return result\n\n    def cluster(self, data):\n        result = {'all': 0, 'cor': 0, 'sub': 0, 'ins': 0, 'del': 0}\n        for token in data:\n            if token in self.data:\n                result['all'] = result['all'] + self.data[token]['all']\n                result['cor'] = result['cor'] + self.data[token]['cor']\n                result['sub'] = result['sub'] + self.data[token]['sub']\n                result['ins'] = result['ins'] + self.data[token]['ins']\n                result['del'] = result['del'] + self.data[token]['del']\n        return result\n\n    def keys(self):\n        return list(self.data.keys())\n\n\ndef width(string):\n    return sum(1 + (unicodedata.east_asian_width(c) in \"AFW\") for c in string)\n\n\ndef default_cluster(word):\n    unicode_names = [unicodedata.name(char) for char in word]\n    for i in reversed(range(len(unicode_names))):\n        if unicode_names[i].startswith('DIGIT'):  # 1\n            unicode_names[i] = 'Number'  # 'DIGIT'\n        elif (unicode_names[i].startswith('CJK UNIFIED IDEOGRAPH') or\n              unicode_names[i].startswith('CJK COMPATIBILITY IDEOGRAPH')):\n            # 明 / 郎\n            unicode_names[i] = 'Mandarin'  # 'CJK IDEOGRAPH'\n        elif (unicode_names[i].startswith('LATIN CAPITAL LETTER') or\n              unicode_names[i].startswith('LATIN SMALL LETTER')):\n            # A / a\n            unicode_names[i] = 'English'  # 'LATIN LETTER'\n        elif unicode_names[i].startswith('HIRAGANA LETTER'):  # は こ め\n            unicode_names[i] = 'Japanese'  # 'GANA LETTER'\n        elif (unicode_names[i].startswith('AMPERSAND') or\n              unicode_names[i].startswith('APOSTROPHE') or\n              unicode_names[i].startswith('COMMERCIAL AT') or\n              unicode_names[i].startswith('DEGREE CELSIUS') or\n              unicode_names[i].startswith('EQUALS SIGN') or\n              unicode_names[i].startswith('FULL STOP') or\n              unicode_names[i].startswith('HYPHEN-MINUS') or\n              unicode_names[i].startswith('LOW LINE') or\n              unicode_names[i].startswith('NUMBER SIGN') or\n              unicode_names[i].startswith('PLUS SIGN') or\n              unicode_names[i].startswith('SEMICOLON')):\n            # & / ' / @ / ℃ / = / . / - / _ / # / + / ;\n            del unicode_names[i]\n        else:\n            return 'Other'\n    if len(unicode_names) == 0:\n        return 'Other'\n    if len(unicode_names) == 1:\n        return unicode_names[0]\n    for i in range(len(unicode_names) - 1):\n        if unicode_names[i] != unicode_names[i + 1]:\n            return 'Other'\n    return unicode_names[0]\n\n\ndef usage():\n    print(\n        \"compute-wer.py : compute word error rate (WER) and align recognition results and references.\"\n    )\n    print(\n        \"         usage : python compute-wer.py [--cs={0,1}] [--cluster=foo] [--ig=ignore_file] [--char={0,1}] [--v={0,1}] [--padding-symbol={space,underline}] test.ref test.hyp > test.wer\"\n    )\n\n\ndef main():\n    # python utils/compute-wer.py --char=1 --v=1 ref hyp > rsl.error\n    if len(sys.argv) == 1:\n        usage()\n        sys.exit(0)\n    calculator = Calculator()\n    cluster_file = ''\n    ignore_words = set()\n    tochar = False\n    verbose = 1\n    padding_symbol = ' '\n    case_sensitive = False\n    max_words_per_line = sys.maxsize\n    split = None\n    while len(sys.argv) > 3:\n        a = '--maxw='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):]\n            del sys.argv[1]\n            max_words_per_line = int(b)\n            continue\n        a = '--rt='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            remove_tag = (b == 'true') or (b != '0')\n            continue\n        a = '--cs='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            case_sensitive = (b == 'true') or (b != '0')\n            continue\n        a = '--cluster='\n        if sys.argv[1].startswith(a):\n            cluster_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            continue\n        a = '--splitfile='\n        if sys.argv[1].startswith(a):\n            split_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            split = dict()\n            with codecs.open(split_file, 'r', 'utf-8') as fh:\n                for line in fh:  # line in unicode\n                    words = line.strip().split()\n                    if len(words) >= 2:\n                        split[words[0]] = words[1:]\n            continue\n        a = '--ig='\n        if sys.argv[1].startswith(a):\n            ignore_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            with codecs.open(ignore_file, 'r', 'utf-8') as fh:\n                for line in fh:  # line in unicode\n                    line = line.strip()\n                    if len(line) > 0:\n                        ignore_words.add(line)\n            continue\n        a = '--char='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            tochar = (b == 'true') or (b != '0')\n            continue\n        a = '--v='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            verbose = 0\n            try:\n                verbose = int(b)\n            except:\n                if b == 'true' or b != '0':\n                    verbose = 1\n            continue\n        a = '--padding-symbol='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            if b == 'space':\n                padding_symbol = ' '\n            elif b == 'underline':\n                padding_symbol = '_'\n            continue\n        if True or sys.argv[1].startswith('-'):\n            #ignore invalid switch\n            del sys.argv[1]\n            continue\n\n    if not case_sensitive:\n        ig = set([w.upper() for w in ignore_words])\n        ignore_words = ig\n\n    default_clusters = {}\n    default_words = {}\n\n    ref_file = sys.argv[1]\n    hyp_file = sys.argv[2]\n    rec_set = {}\n    if split and not case_sensitive:\n        newsplit = dict()\n        for w in split:\n            words = split[w]\n            for i in range(len(words)):\n                words[i] = words[i].upper()\n            newsplit[w.upper()] = words\n        split = newsplit\n\n    with codecs.open(hyp_file, 'r', 'utf-8') as fh:\n        for line in fh:\n            if tochar:\n                array = characterize(line)\n            else:\n                array = line.strip().split()\n            if len(array) == 0: continue\n            fid = array[0]\n            rec_set[fid] = normalize(array[1:], ignore_words, case_sensitive,\n                                     split)\n\n    # compute error rate on the interaction of reference file and hyp file\n    for line in open(ref_file, 'r', encoding='utf-8'):\n        if tochar:\n            array = characterize(line)\n        else:\n            array = line.rstrip('\\n').split()\n        if len(array) == 0: continue\n        fid = array[0]\n        if fid not in rec_set:\n            continue\n        lab = normalize(array[1:], ignore_words, case_sensitive, split)\n        rec = rec_set[fid]\n        if verbose:\n            print('\\nutt: %s' % fid)\n\n        for word in rec + lab:\n            if word not in default_words:\n                default_cluster_name = default_cluster(word)\n                if default_cluster_name not in default_clusters:\n                    default_clusters[default_cluster_name] = {}\n                if word not in default_clusters[default_cluster_name]:\n                    default_clusters[default_cluster_name][word] = 1\n                default_words[word] = default_cluster_name\n\n        result = calculator.calculate(lab, rec)\n        if verbose:\n            if result['all'] != 0:\n                wer = float(result['ins'] + result['sub'] + result[\n                    'del']) * 100.0 / result['all']\n            else:\n                wer = 0.0\n            print('WER: %4.2f %%' % wer, end=' ')\n            print('N=%d C=%d S=%d D=%d I=%d' %\n                  (result['all'], result['cor'], result['sub'], result['del'],\n                   result['ins']))\n            space = {}\n            space['lab'] = []\n            space['rec'] = []\n            for idx in range(len(result['lab'])):\n                len_lab = width(result['lab'][idx])\n                len_rec = width(result['rec'][idx])\n                length = max(len_lab, len_rec)\n                space['lab'].append(length - len_lab)\n                space['rec'].append(length - len_rec)\n            upper_lab = len(result['lab'])\n            upper_rec = len(result['rec'])\n            lab1, rec1 = 0, 0\n            while lab1 < upper_lab or rec1 < upper_rec:\n                if verbose > 1:\n                    print('lab(%s):' % fid.encode('utf-8'), end=' ')\n                else:\n                    print('lab:', end=' ')\n                lab2 = min(upper_lab, lab1 + max_words_per_line)\n                for idx in range(lab1, lab2):\n                    token = result['lab'][idx]\n                    print('{token}'.format(token=token), end='')\n                    for n in range(space['lab'][idx]):\n                        print(padding_symbol, end='')\n                    print(' ', end='')\n                print()\n                if verbose > 1:\n                    print('rec(%s):' % fid.encode('utf-8'), end=' ')\n                else:\n                    print('rec:', end=' ')\n                rec2 = min(upper_rec, rec1 + max_words_per_line)\n                for idx in range(rec1, rec2):\n                    token = result['rec'][idx]\n                    print('{token}'.format(token=token), end='')\n                    for n in range(space['rec'][idx]):\n                        print(padding_symbol, end='')\n                    print(' ', end='')\n                print('\\n', end='\\n')\n                lab1 = lab2\n                rec1 = rec2\n\n    if verbose:\n        print(\n            '==========================================================================='\n        )\n        print()\n\n    result = calculator.overall()\n    if result['all'] != 0:\n        wer = float(result['ins'] + result['sub'] + result[\n            'del']) * 100.0 / result['all']\n    else:\n        wer = 0.0\n    print('Overall -> %4.2f %%' % wer, end=' ')\n    print('N=%d C=%d S=%d D=%d I=%d' %\n          (result['all'], result['cor'], result['sub'], result['del'],\n           result['ins']))\n    if not verbose:\n        print()\n\n    if verbose:\n        for cluster_id in default_clusters:\n            result = calculator.cluster(\n                [k for k in default_clusters[cluster_id]])\n            if result['all'] != 0:\n                wer = float(result['ins'] + result['sub'] + result[\n                    'del']) * 100.0 / result['all']\n            else:\n                wer = 0.0\n            print('%s -> %4.2f %%' % (cluster_id, wer), end=' ')\n            print('N=%d C=%d S=%d D=%d I=%d' %\n                  (result['all'], result['cor'], result['sub'], result['del'],\n                   result['ins']))\n        if len(cluster_file) > 0:  # compute separated WERs for word clusters\n            cluster_id = ''\n            cluster = []\n            for line in open(cluster_file, 'r', encoding='utf-8'):\n                for token in line.decode('utf-8').rstrip('\\n').split():\n                    # end of cluster reached, like </Keyword>\n                    if token[0:2] == '</' and token[len(token)-1] == '>' and \\\n                       token.lstrip('</').rstrip('>') == cluster_id :\n                        result = calculator.cluster(cluster)\n                        if result['all'] != 0:\n                            wer = float(result['ins'] + result['sub'] + result[\n                                'del']) * 100.0 / result['all']\n                        else:\n                            wer = 0.0\n                        print('%s -> %4.2f %%' % (cluster_id, wer), end=' ')\n                        print('N=%d C=%d S=%d D=%d I=%d' %\n                              (result['all'], result['cor'], result['sub'],\n                               result['del'], result['ins']))\n                        cluster_id = ''\n                        cluster = []\n                    # begin of cluster reached, like <Keyword>\n                    elif token[0] == '<' and token[len(token)-1] == '>' and \\\n                         cluster_id == '' :\n                        cluster_id = token.lstrip('<').rstrip('>')\n                        cluster = []\n                    # general terms, like WEATHER / CAR / ...\n                    else:\n                        cluster.append(token)\n        print()\n        print(\n            '==========================================================================='\n        )\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "examples/librispeech/asr5/conf/preprocess.yaml",
    "content": "process:\n    # use raw audio\n  - type: wav_process\n"
  },
  {
    "path": "examples/librispeech/asr5/conf/preprocessor_config.json",
    "content": "{\n  \"do_normalize\": true,\n  \"feature_extractor_type\": \"Wav2Vec2FeatureExtractor\",\n  \"feature_size\": 1,\n  \"padding_side\": \"right\",\n  \"padding_value\": 0,\n  \"return_attention_mask\": true,\n  \"sampling_rate\": 16000\n}\n"
  },
  {
    "path": "examples/librispeech/asr5/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 1\nerror_rate_type: wer\ndecoding_method: \"ctc_greedy_search\"  # 'ctc_greedy_search', 'ctc_prefix_beam_search'\nbeam_size: 10\n"
  },
  {
    "path": "examples/librispeech/asr5/conf/wavlmASR.yaml",
    "content": "############################################\n#          Network Architecture           #\n############################################\nfreeze_wavlm: False\nnormalize_wav: True\noutput_norm: True\ninit_type: kaiming_uniform # !Warning: need to convergence\nenc:\n  input_shape: 768\n  dnn_blocks: 2\n  dnn_neurons: 768\n  activation: True\n  normalization: True\n  dropout_rate: [0.15, 0]\nctc:\n  enc_n_units: 768\n  blank_id: 0\n  dropout_rate: 0.0\nwavlm_params_path: exp/wavlm/wavlm-base-plus.pdparams\n\n\ntask_cfg:\n  label_rate: 50.0\n  sample_rate: 16000\n  normalize: True\n  enable_padding: False\n  max_keep_size: None\n  max_sample_size: 250000\n  min_sample_size: 32000\n  dropout_input: 0.1\n  final_dropout: 0.0\n  dropout: 0.1\n  attention_dropout: 0.0\n  activation_dropout: 0.1\n  apply_mask: True\n  mask_length: 10\n  mask_prob: 0.5\n  mask_selection: static\n  mask_other: 0.0\n  no_mask_overlap: False\n  mask_channel_length: 10\n  mask_channel_prob: 0.0\n  mask_channel_selection: static\n  mask_channel_other: 0.0\n  no_mask_channel_overlap: False\n  feature_grad_mult: 0.0\n  layerdrop: 0.1\n  fp16: True\n  extractor_mode: layer_norm\n  encoder_layers: 12\n  encoder_embed_dim: 768\n  encoder_ffn_embed_dim: 3072\n  encoder_attention_heads: 12\n  activation_fn: gelu\n  encoder_layerdrop: 0.0\n  dropout_features: 0.0\n  final_dim: 768\n  untie_final_proj: True\n  layer_norm_first: True\n  conv_feature_layers: \"[(512,10,5)] + [(512,3,2)] * 4 + [(512,2,2)] * 2\"\n  conv_bias: False\n  logit_temp: 0.1\n  target_glu: False\n  mask_min_space: 1\n  mask_channel_min_space: 1\n  conv_pos: 128\n  conv_pos_groups: 16\n  latent_temp: [2.0, 0.5, 0.999995]\n  skip_masked: False\n  skip_nomask: True\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test-clean\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: char\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs 0: disabled other: enabled for other epochs \nbatch_size: 8  # Different batch_size may cause large differences in results\nmaxlen_in: 51200000000  # if input length  > maxlen-in batchsize is automatically reduced\nmaxlen_out: 160000\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\ndist_sampler: True\nshortest_first: False\nreturn_lens_rate: True\n  \n############################################\n#             Data Augmentation            #\n############################################\naudio_augment:  # for raw audio \n  sample_rate: 16000\n  speeds: [90, 100, 110]\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 10\naccum_grad: 8\nglobal_grad_clip: 5.0\nmodel_scheduler: newbobscheduler\nmodel_scheduler_conf:\n  improvement_threshold: 0.0025\n  annealing_factor: 0.8\n  patient: 0\nmodel_optim: adam\nmodel_optim_conf:\n  lr: 0.0001\n  weight_decay: 0.0\n# I changed this\nwavlm_optim: adam\nwavlm_optim_conf:\n  lr: 0.00005\n  weight_decay: 0.0\nwavlm_scheduler: constantlr    \nwavlm_scheduler_conf:\n  warmup_steps: 1000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/librispeech/asr5/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\nunit_type=char\ndict_dir=data/lang_char\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"False\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n\n    for set in train-clean-100 dev-clean test-clean; do\n        mv data/manifest.${set} data/manifest.${set}.raw\n    done\n\n    rm -rf data/manifest.train.raw data/manifest.dev.raw  data/manifest.test.raw\n    for set in train-clean-100; do\n        cat data/manifest.${set}.raw >> data/manifest.train.raw\n    done\n\n    for set in dev-clean; do\n        cat data/manifest.${set}.raw >> data/manifest.dev.raw\n    done\n\n    for set in test-clean; do\n        cat data/manifest.${set}.raw >> data/manifest.test.raw\n    done\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=2000 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=161 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test dev-clean test-clean; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type ${unit_type} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt manifest.${set} failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"LibriSpeech Data preparation done.\"\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    mkdir -p exp/wavlm\n    echo \"Pretrained wavlm model download\"\n    wget -P exp/wavlm https://paddlespeech.cdn.bcebos.com/wavlm/wavlm-base-plus.pdparams\nfi\n\nexit 0"
  },
  {
    "path": "examples/librispeech/asr5/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nexpdir=exp\ndatadir=data\n\nrecog_set=\"test-clean test-other dev-clean dev-other\"\nrecog_set=\"test-clean\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\npython3 ${MAIN_ROOT}/utils/format_rsl.py \\\n    --origin_ref data/manifest.test-clean.raw \\\n    --trans_ref data/manifest.test-clean.text\n\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=16\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 compute_wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\nfor type in ctc_prefix_beam_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    python3 ${MAIN_ROOT}/utils/format_rsl.py \\\n        --origin_hyp ${ckpt_prefix}.${type}.rsl \\\n        --trans_hyp ${ckpt_prefix}.${type}.rsl.text\n\n    python3 compute_wer.py --char=1 --v=1 \\\n        data/manifest.test-clean.text ${ckpt_prefix}.${type}.rsl.text > ${ckpt_prefix}.${type}.error\n    echo \"decoding ${type} done.\"\ndone\n\necho \"Finished\"\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr5/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/en/demo_002_en.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr5/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nresume=$3\nips=$4\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=1988\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# export FLAGS_cudnn_exhaustive_search=true\n# export FLAGS_conv_workspace_size_limit=4000\nexport FLAGS_allocator_strategy=naive_best_fit\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed} \\\n--resume ${resume}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/librispeech/asr5/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/tools/sctk/bin:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\n# export PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/wavlm/bin\n"
  },
  {
    "path": "examples/librispeech/asr5/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2\nstage=0\nstop_stage=3\nconf_path=conf/wavlmASR.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=3\nresume=         # xx e.g. 30\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\naudio_file=data/demo_002_en.wav\n\n# avg_ckpt=avg_${avg_num}\navg_ckpt=4\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${resume} ${ips}\nfi\n\n# if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n#     # avg n best model\n#     ./avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n# fi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # greedy search decoder\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n"
  },
  {
    "path": "examples/ljspeech/README.md",
    "content": "\n# LJSpeech\n\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n"
  },
  {
    "path": "examples/ljspeech/tts0/README.md",
    "content": "# Tacotron2 with LJSpeech-1.1\nThis example contains code used to train a [Tacotron2](https://arxiv.org/abs/1712.05884) model with [LJSpeech-1.1](https://keithito.com/LJ-Speech-Dataset/)\n\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get phonemes for Tacotron2, the durations of MFA are not needed here.\nYou can download from here [ljspeech_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1`.\nAssume the path to the MFA result of LJSpeech-1.1 is `./ljspeech_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from a text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and the id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n\nTrain a Tacotron2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       tacotron2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_ljspeech_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_ljspeech_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_ljspeech_ckpt_0.5\n├── pwg_default.yaml              # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz  # generator parameters of parallel wavegan\n└── pwg_stats.npy                 # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the Tacotron2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n\n## Pretrained Model\nPretrained Tacotron2 model with no silence in the edge of audios:\n- [tacotron2_ljspeech_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_ljspeech_ckpt_0.2.0.zip)\n\n\nModel | Step | eval/loss | eval/l1_loss | eval/mse_loss | eval/bce_loss| eval/attn_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 1(gpu) x 60300|0.554092|0.394260|0.141046|0.018747|3.8e-05|\n\nTacotron2 checkpoint contains files listed below.\n```text\ntacotron2_ljspeech_ckpt_0.2.0\n├── default.yaml            # default config used to train Tacotron2\n├── phone_id_map.txt        # phone vocabulary file when training Tacotron2\n├── snapshot_iter_60300.pdz # model parameters and optimizer states\n└── speech_stats.npy        # statistics used to normalize spectrogram when training Tacotron2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences_en.txt` using pretrained Tacotron2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=tacotron2_ljspeech \\\n  --am_config=tacotron2_ljspeech_ckpt_0.2.0/default.yaml \\\n  --am_ckpt=tacotron2_ljspeech_ckpt_0.2.0/snapshot_iter_60300.pdz \\\n  --am_stat=tacotron2_ljspeech_ckpt_0.2.0/speech_stats.npy  \\\n  --voc=pwgan_ljspeech\\\n  --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n  --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n  --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n  --lang=en \\\n  --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=tacotron2_ljspeech_ckpt_0.2.0/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/ljspeech/tts0/conf/default.yaml",
    "content": "# This configuration is for Paddle to train Tacotron 2. Compared to the\n# original paper, this configuration additionally use the guided attention\n# loss to accelerate the learning of the diagonal attention. It requires\n# only a single GPU with 12 GB memory and it takes ~1 days to finish the\n# training on Titan V.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 22050                # Sampling rate.\nn_fft: 1024              # FFT size (samples).\nn_shift: 256             # Hop size (samples). 11.6ms\nwin_length: null         # Window length (samples).\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:                          # keyword arguments for the selected model\n    embed_dim: 512               # char or phn embedding dimension\n    elayers: 1                   # number of blstm layers in encoder\n    eunits: 512                  # number of blstm units\n    econv_layers: 3              # number of convolutional layers in encoder\n    econv_chans: 512             # number of channels in convolutional layer\n    econv_filts: 5               # filter size of convolutional layer\n    atype: location              # attention function type\n    adim: 512                    # attention dimension\n    aconv_chans: 32              # number of channels in convolutional layer of attention\n    aconv_filts: 15              # filter size of convolutional layer of attention\n    cumulate_att_w: True         # whether to cumulate attention weight\n    dlayers: 2                   # number of lstm layers in decoder\n    dunits: 1024                 # number of lstm units in decoder\n    prenet_layers: 2             # number of layers in prenet\n    prenet_units: 256            # number of units in prenet\n    postnet_layers: 5            # number of layers in postnet\n    postnet_chans: 512           # number of channels in postnet\n    postnet_filts: 5             # filter size of postnet layer\n    output_activation: null      # activation function for the final output\n    use_batch_norm: True         # whether to use batch normalization in encoder\n    use_concate: True            # whether to concatenate encoder embedding with decoder outputs\n    use_residual: False          # whether to use residual connection in encoder\n    dropout_rate: 0.5            # dropout rate\n    zoneout_rate: 0.1            # zoneout rate\n    reduction_factor: 1          # reduction factor\n    spk_embed_dim: null          # speaker embedding dimension\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True            # whether to apply masking for padded part in loss calculation\n    bce_pos_weight: 5.0          # weight of positive sample in binary cross entropy calculation\n    use_guided_attn_loss: True   # whether to use guided attention loss\n    guided_attn_loss_sigma: 0.4  # sigma of guided attention loss\n    guided_attn_loss_lambda: 1.0 # strength of guided attention loss\n\n\n##########################################################\n#                  OPTIMIZER SETTING                     #\n##########################################################\noptimizer:\n    optim: adam              # optimizer type\n    learning_rate: 1.0e-03   # learning rate\n    epsilon: 1.0e-06         # epsilon\n    weight_decay: 0.0        # weight decay coefficient\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 300\nnum_snapshots: 5\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 42\n"
  },
  {
    "path": "examples/ljspeech/tts0/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./ljspeech_alignment \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=ljspeech \\\n        --rootdir=~/datasets/LJSpeech-1.1/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts0/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize.py \\\n    --am=tacotron2_ljspeech \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_ljspeech \\\n    --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n    --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n    --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n    --test_metadata=dump/test/norm/metadata.jsonl \\\n    --output_dir=${train_output_path}/test \\\n    --phones_dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/ljspeech/tts0/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n# TODO: dygraph to static graph is not good for tacotron2_ljspeech now\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n    --am=tacotron2_ljspeech \\\n    --am_config=${config_path} \\\n    --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --am_stat=dump/train/speech_stats.npy \\\n    --voc=pwgan_ljspeech \\\n    --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n    --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n    --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n    --lang=en \\\n    --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n    --output_dir=${train_output_path}/test_e2e \\\n    --phones_dict=dump/phone_id_map.txt \\\n    # --inference_dir=${train_output_path}/inference"
  },
  {
    "path": "examples/ljspeech/tts0/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_201.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts1/README.md",
    "content": "# TransformerTTS with LJSpeech\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1` and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│ ├── norm\n│ └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│  ├── norm\n│  └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains the speech feature of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/speech_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, the path of speech features, speaker, and id of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n\nTrain a TransformerTTS model with LJSpeech TTS dataset.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       TransformerTTS config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n## Synthesizing\nWe use [waveflow](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc0) as the neural vocoder.\nDownload Pretrained WaveFlow Model with residual channel equals 128 from [waveflow_ljspeech_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/waveflow/waveflow_ljspeech_ckpt_0.3.zip) and unzip it.\n```bash\nunzip waveflow_ljspeech_ckpt_0.3.zip\n```\nWaveFlow checkpoint contains files listed below.\n```text\nwaveflow_ljspeech_ckpt_0.3\n├── config.yaml           # default config used to train waveflow\n└── step-2000000.pdparams # model parameters of waveflow\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--transformer-tts-config TRANSFORMER_TTS_CONFIG]\n                     [--transformer-tts-checkpoint TRANSFORMER_TTS_CHECKPOINT]\n                     [--transformer-tts-stat TRANSFORMER_TTS_STAT]\n                     [--waveflow-config WAVEFLOW_CONFIG]\n                     [--waveflow-checkpoint WAVEFLOW_CHECKPOINT]\n                     [--phones-dict PHONES_DICT]\n                     [--test-metadata TEST_METADATA] [--output-dir OUTPUT_DIR]\n                     [--ngpu NGPU]\n\nSynthesize with transformer tts & waveflow.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --transformer-tts-config TRANSFORMER_TTS_CONFIG\n                        transformer tts config file.\n  --transformer-tts-checkpoint TRANSFORMER_TTS_CHECKPOINT\n                        transformer tts checkpoint to load.\n  --transformer-tts-stat TRANSFORMER_TTS_STAT\n                        mean and standard deviation used to normalize\n                        spectrogram when training transformer tts.\n  --waveflow-config WAVEFLOW_CONFIG\n                        waveflow config file.\n  --waveflow-checkpoint WAVEFLOW_CHECKPOINT\n                        waveflow checkpoint to load.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --test-metadata TEST_METADATA\n                        test metadata.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--transformer-tts-config TRANSFORMER_TTS_CONFIG]\n                         [--transformer-tts-checkpoint TRANSFORMER_TTS_CHECKPOINT]\n                         [--transformer-tts-stat TRANSFORMER_TTS_STAT]\n                         [--waveflow-config WAVEFLOW_CONFIG]\n                         [--waveflow-checkpoint WAVEFLOW_CHECKPOINT]\n                         [--phones-dict PHONES_DICT] [--text TEXT]\n                         [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with transformer tts & waveflow.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --transformer-tts-config TRANSFORMER_TTS_CONFIG\n                        transformer tts config file.\n  --transformer-tts-checkpoint TRANSFORMER_TTS_CHECKPOINT\n                        transformer tts checkpoint to load.\n  --transformer-tts-stat TRANSFORMER_TTS_STAT\n                        mean and standard deviation used to normalize\n                        spectrogram when training transformer tts.\n  --waveflow-config WAVEFLOW_CONFIG\n                        waveflow config file.\n  --waveflow-checkpoint WAVEFLOW_CHECKPOINT\n                        waveflow checkpoint to load.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n1. `--transformer-tts-config`, `--transformer-tts-checkpoint`, `--transformer-tts-stat` and `--phones-dict` are arguments for transformer_tts, which correspond to the 4 files in the transformer_tts pretrained model.\n2. `--waveflow-config`, `--waveflow-checkpoint` are arguments for waveflow, which correspond to the 2 files in the waveflow pretrained model.\n3. `--test-metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n4. `--text` is the text file, which contains sentences to synthesize.\n5. `--output-dir` is the directory to save synthesized audio files.\n6. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained Model can be downloaded here:\n- [transformer_tts_ljspeech_ckpt_0.4.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/transformer_tts/transformer_tts_ljspeech_ckpt_0.4.zip)\n\nTransformerTTS  checkpoint contains files listed below.\n```text\ntransformer_tts_ljspeech_ckpt_0.4\n├── default.yaml             # default config used to train transformer_tts\n├── phone_id_map.txt         # phone vocabulary file when training transformer_tts\n├── snapshot_iter_201500.pdz # model parameters and optimizer states\n└── speech_stats.npy         # statistics used to normalize spectrogram when training transformer_tts\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences_en.txt` using pretrained transformer_tts  and waveflow models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize_e2e.py \\\n  --transformer-tts-config=transformer_tts_ljspeech_ckpt_0.4/default.yaml \\\n  --transformer-tts-checkpoint=transformer_tts_ljspeech_ckpt_0.4/snapshot_iter_201500.pdz \\\n  --transformer-tts-stat=transformer_tts_ljspeech_ckpt_0.4/speech_stats.npy \\\n  --waveflow-config=waveflow_ljspeech_ckpt_0.3/config.yaml \\\n  --waveflow-checkpoint=waveflow_ljspeech_ckpt_0.3/step-2000000.pdparams \\\n  --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n  --output-dir=exp/default/test_e2e \\\n  --phones-dict=transformer_tts_ljspeech_ckpt_0.4/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/ljspeech/tts1/conf/default.yaml",
    "content": "\nfs : 22050              # Hz, sample rate\nn_fft : 1024            # FFT size (samples). \nwin_length : 1024       # Window length (samples). 46.4ms\nn_shift : 256           # Hop size (samples). 11.6ms\nfmin : 0                # Hz, min frequency when converting to mel\nfmax : 8000             # Hz, max frequency when converting to mel\nn_mels : 80             # mel bands\nwindow: \"hann\"          # Window function.\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 16\nnum_workers: 2\n\n##########################################################\n#                  TTS MODEL SETTING                     #\n##########################################################\ntts: transformertts        # model architecture\nmodel:                     # keyword arguments for the selected model\n    embed_dim: 0           # embedding dimension in encoder prenet\n    eprenet_conv_layers: 0 # number of conv layers in encoder prenet\n                           # if set to 0, no encoder prenet will be used\n    eprenet_conv_filts: 0  # filter size of conv layers in encoder prenet\n    eprenet_conv_chans: 0  # number of channels of conv layers in encoder prenet\n    dprenet_layers: 2      # number of layers in decoder prenet\n    dprenet_units: 256     # number of units in decoder prenet\n    adim: 512              # attention dimension\n    aheads: 8              # number of attention heads\n    elayers: 6             # number of encoder layers\n    eunits: 1024           # number of encoder ff units\n    dlayers: 6             # number of decoder layers\n    dunits: 1024           # number of decoder ff units\n    positionwise_layer_type: conv1d  # type of position-wise layer\n    positionwise_conv_kernel_size: 1 # kernel size of position wise conv layer\n    postnet_layers: 5                # number of layers of postnet\n    postnet_filts: 5                 # filter size of conv layers in postnet\n    postnet_chans: 256               # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True         # whether to use scaled positional encoding\n    encoder_normalize_before: True   # whether to perform layer normalization before the input\n    decoder_normalize_before: True   # whether to perform layer normalization before the input\n    reduction_factor: 1              # reduction factor\n    init_type: xavier_uniform        # initialization type\n    init_enc_alpha: 1.0              # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0              # initial value of alpha of decoder scaled position encoding\n    eprenet_dropout_rate: 0.0        # dropout rate for encoder prenet\n    dprenet_dropout_rate: 0.5        # dropout rate for decoder prenet\n    postnet_dropout_rate: 0.5        # dropout rate for postnet\n    transformer_enc_dropout_rate: 0.1                # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.1     # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.1           # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.1                # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.1     # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.1           # dropout rate for transformer decoder attention layer\n    transformer_enc_dec_attn_dropout_rate: 0.1       # dropout rate for transformer encoder-decoder attention layer\n    num_heads_applied_guided_attn: 2                 # number of heads to apply guided attention loss\n    num_layers_applied_guided_attn: 2                # number of layers to apply guided attention loss  \n    \n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                  # whether to apply masking for padded part in loss calculation\n    loss_type: L1\n    use_guided_attn_loss: True         # whether to use guided attention loss\n    guided_attn_loss_sigma: 0.4        # sigma in guided attention loss\n    guided_attn_loss_lambda: 10.0      # lambda in guided attention loss\n    modules_applied_guided_attn: [\"encoder-decoder\"] # modules to apply guided attention loss\n    bce_pos_weight: 5.0              # weight of positive sample in binary cross entropy calculation\n\n\n##########################################################\n#            OPTIMIZER & SCHEDULER SETTING               #\n##########################################################\noptimizer:\n    optim: adam               # optimizer type\n    learning_rate: 0.001      # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 500\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086"
  },
  {
    "path": "examples/ljspeech/tts1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=1\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py  \\\n        --dataset=ljspeech \\\n        --rootdir=~/datasets/LJSpeech-1.1/ \\\n        --dumpdir=dump \\\n        --config-path=conf/default.yaml \\\n        --num-cpu=8\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts1/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize.py \\\n    --transformer-tts-config=${config_path} \\\n    --transformer-tts-checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --transformer-tts-stat=dump/train/speech_stats.npy \\\n    --waveflow-config=waveflow_ljspeech_ckpt_0.3/config.yaml \\\n    --waveflow-checkpoint=waveflow_ljspeech_ckpt_0.3/step-2000000.pdparams \\\n    --test-metadata=dump/test/norm/metadata.jsonl \\\n    --output-dir=${train_output_path}/test \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/ljspeech/tts1/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/synthesize_e2e.py \\\n    --transformer-tts-config=${config_path} \\\n    --transformer-tts-checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --transformer-tts-stat=dump/train/speech_stats.npy \\\n    --waveflow-config=waveflow_ljspeech_ckpt_0.3/config.yaml \\\n    --waveflow-checkpoint=waveflow_ljspeech_ckpt_0.3/step-2000000.pdparams \\\n    --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n    --output-dir=${train_output_path}/test_e2e \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/ljspeech/tts1/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=2 \\\n    --phones-dict=dump/phone_id_map.txt\n"
  },
  {
    "path": "examples/ljspeech/tts1/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=transformer_tts\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/ljspeech/tts1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_403.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/README.md",
    "content": "# FastSpeech2 with LJSpeech-1.1\nThis example contains code used to train a [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [LJSpeech-1.1](https://keithito.com/LJ-Speech-Dataset/).\n\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for fastspeech2.\nYou can download from here [ljspeech_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1`.\nAssume the path to the MFA result of LJSpeech-1.1 is `./ljspeech_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and id of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/ljspeech/voc1) as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwg_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_ljspeech_ckpt_0.5.zip) and unzip it.\n```bash\nunzip pwg_ljspeech_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_ljspeech_ckpt_0.5\n├── pwg_default.yaml              # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz  # generator parameters of parallel wavegan\n└── pwg_stats.npy                 # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_nosil_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip)\n\nThe static model can be downloaded here:\n- [fastspeech2_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_static_1.1.0.zip)\n\nThe ONNX model can be downloaded here:\n- [fastspeech2_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [fastspeech2_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_pdlite_1.3.0.zip)\n\n\nModel | Step | eval/loss | eval/l1_loss | eval/duration_loss | eval/pitch_loss| eval/energy_loss \n:-------------:| :------------:| :-----: | :-----: | :--------: |:--------:|:---------:\ndefault| 2(gpu) x 100000| 1.505682|0.612104| 0.045505| 0.62792| 0.220147\n\n\nFastSpeech2 checkpoint contains files listed below.\n```text\nfastspeech2_nosil_ljspeech_ckpt_0.5\n├── default.yaml             # default config used to train fastspeech2\n├── phone_id_map.txt         # phone vocabulary file when training fastspeech2\n├── snapshot_iter_100000.pdz # model parameters and optimizer states\n└── speech_stats.npy         # statistics used to normalize spectrogram when training fastspeech2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences_en.txt` using pretrained fastspeech2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_ljspeech \\\n  --am_config=fastspeech2_nosil_ljspeech_ckpt_0.5/default.yaml \\\n  --am_ckpt=fastspeech2_nosil_ljspeech_ckpt_0.5/snapshot_iter_100000.pdz \\\n  --am_stat=fastspeech2_nosil_ljspeech_ckpt_0.5/speech_stats.npy \\\n  --voc=pwgan_ljspeech\\\n  --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n  --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n  --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n  --lang=en \\\n  --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference \\\n  --phones_dict=fastspeech2_nosil_ljspeech_ckpt_0.5/phone_id_map.txt\n```\n"
  },
  {
    "path": "examples/ljspeech/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 22050          # sr\nn_fft: 1024        # FFT size (samples). \nn_shift: 256       # Hop size (samples). 11.6ms\nwin_length: null   # Window length (samples).\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 4\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n  optim: adam               # optimizer type\n  learning_rate: 0.001     # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1000\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_ljspeech \\\n        --voc=pwgan_ljspeech \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --lang=en\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_ljspeech \\\n        --voc=hifigan_ljspeech \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_ljspeech \\\n        --voc=pwgan_ljspeech \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --lang=en\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_ljspeech \\\n        --voc=hifigan_ljspeech \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_ljspeech \\\n        --voc=pwgan_ljspeech\\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt  \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --lang=en\n\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_ljspeech \\\n        --voc=hifigan_ljspeech \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt  \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./ljspeech_alignment \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=ljspeech \\\n        --rootdir=~/datasets/LJSpeech-1.1/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=8 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_ljspeech \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_ljspeech \\\n        --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n        --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n        --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_ljspeech \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_ljspeech \\\n        --voc_config=hifigan_ljspeech_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_ljspeech_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_ljspeech_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n"
  },
  {
    "path": "examples/ljspeech/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_ljspeech \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_ljspeech \\\n        --voc_config=pwg_ljspeech_ckpt_0.5/pwg_default.yaml \\\n        --voc_ckpt=pwg_ljspeech_ckpt_0.5/pwg_snapshot_iter_400000.pdz  \\\n        --voc_stat=pwg_ljspeech_ckpt_0.5/pwg_stats.npy \\\n        --lang=en \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --inference_dir=${train_output_path}/inference \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_ljspeech \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_ljspeech \\\n        --voc_config=hifigan_ljspeech_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_ljspeech_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_ljspeech_ckpt_0.2.0/feats_stats.npy \\\n        --lang=en \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --inference_dir=${train_output_path}/inference \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/ljspeech/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_201.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\n# paddle2onnx, please make sure the static models are in ${train_output_path}/inference first\n# we have only tested the following models so far\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_ljspeech\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_ljspeech\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_ljspeech\nfi\n\n# inference with onnxruntime, use fastspeech2 + pwgan by default\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite fastspeech2_ljspeech x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_ljspeech x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_ljspeech x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi"
  },
  {
    "path": "examples/ljspeech/voc0/README.md",
    "content": "# WaveFlow with LJSpeech\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1`.\nAssume the path to the Tacotron2 generated mels is `../tts0/output/test`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs from mels.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${preprocess_path}\n```\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${preprocess_path} ${train_output_path}\n```\nThe training script requires 4 command line arguments.\n1. `--data` is the path of the training dataset.\n2. `--output` is the path of the output directory.\n3. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\nIf you want distributed training, set a larger `--ngpu` (e.g. 4). Note that distributed training with cpu is not supported yet.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/synthesize.py`, which can synthesize waveform from mels.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${input_mel_path} ${train_output_path} ${ckpt_name}\n```\n\nSynthesize waveform.\n1. We assume the `--input` is a directory containing several mel spectrograms(log magnitude) in `.npy` format.\n2. The output would be saved in the `--output` directory, containing several `.wav` files, each with the same name as the mel spectrogram does.\n3. `--checkpoint_path` should be the path of the parameter file (`.pdparams`) to load. Note that the extention name `.pdparmas` is not included here.\n6. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained Model with residual channel equals 128 can be downloaded here:\n- [waveflow_ljspeech_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/waveflow/waveflow_ljspeech_ckpt_0.3.zip)\n"
  },
  {
    "path": "examples/ljspeech/voc0/local/preprocess.sh",
    "content": "#!/bin/bash\n\npreprocess_path=$1\n\npython3 ${BIN_DIR}/preprocess.py \\\n    --input=~/datasets/LJSpeech-1.1 \\\n    --output=${preprocess_path}"
  },
  {
    "path": "examples/ljspeech/voc0/local/synthesize.sh",
    "content": "#!/bin/bash\n\ninput_mel_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\npython ${BIN_DIR}/synthesize.py \\\n    --input=${input_mel_path} \\\n    --output=${train_output_path}/wavs/ \\\n    --checkpoint_path=${train_output_path}/checkpoints/${ckpt_name} \\\n    --ngpu=1"
  },
  {
    "path": "examples/ljspeech/voc0/local/train.sh",
    "content": "#!/bin/bash\n\npreprocess_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --data=${preprocess_path} \\\n    --output=${train_output_path} \\\n    --ngpu=1"
  },
  {
    "path": "examples/ljspeech/voc0/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=waveflow\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}"
  },
  {
    "path": "examples/ljspeech/voc0/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\npreprocess_path=preprocessed_ljspeech\ntrain_output_path=output\n# mel generated by Tacotron2\ninput_mel_path=${preprocess_path}/mel_test\nckpt_name=step-10000\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${preprocess_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${preprocess_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    mkdir -p ${preprocess_path}/mel_test\n    cp ${preprocess_path}/mel/LJ050-001*.npy ${preprocess_path}/mel_test/\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${input_mel_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/ljspeech/voc1/README.md",
    "content": "# Parallel WaveGAN with the LJSpeech-1.1\nThis example contains code used to train a [parallel wavegan](http://arxiv.org/abs/1910.11480) model with [LJSpeech-1.1](https://keithito.com/LJ-Speech-Dataset/).\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [ljspeech_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1`.\nAssume the path to the MFA result of LJSpeech-1.1 is `./ljspeech_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER]\n                [--run-benchmark RUN_BENCHMARK]\n                [--profiler_options PROFILER_OPTIONS]\n\nTrain a ParallelWaveGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       ParallelWaveGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n\nbenchmark:\n  arguments related to benchmark.\n\n  --batch-size BATCH_SIZE\n                        batch size.\n  --max-iter MAX_ITER   train max steps.\n  --run-benchmark RUN_BENCHMARK\n                        runing benchmark or not, if True, use the --batch-size\n                        and --max-iter.\n  --profiler_options PROFILER_OPTIONS\n                        The option of profiler, which should be in format\n                        \"key1=value1;key2=value2;key3=value3\".\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained models can be downloaded here:\n- [pwg_ljspeech_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_ljspeech_ckpt_0.5.zip)\n\nThe static model can be downloaded here:\n- [pwgan_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_static_1.1.0.zip)\n\nThe ONNX model can be downloaded here:\n- [pwgan_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [pwgan_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_pdlite_1.3.0.zip)\n\n\nParallel WaveGAN checkpoint contains files listed below.\n\n```text\npwg_ljspeech_ckpt_0.5\n├── pwg_default.yaml              # default config used to train parallel wavegan\n├── pwg_snapshot_iter_400000.pdz  # generator parameters of parallel wavegan\n└── pwg_stats.npy                 # statistics used to normalize spectrogram when training parallel wavegan\n```\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/ljspeech/voc1/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for Parallel WaveGAN.\n# Please make sure this is adjusted for the LJSpeech dataset. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires 12 GB GPU memory and takes ~3 days on TITAN V.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 22050                # Sampling rate.\nn_fft: 1024              # FFT size (samples).\nn_shift: 256             # Hop size (samples). 11.6ms\nwin_length: null         # Window length (samples).\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Kernel size of dilated convolution.\n    layers: 30            # Number of residual block layers.\n    stacks: 3             # Number of stacks i.e., dilation cycles.\n    residual_channels: 64 # Number of channels in residual conv.\n    gate_channels: 128    # Number of channels in gated conv.\n    skip_channels: 64     # Number of channels in skip conv.\n    aux_channels: 80      # Number of channels for auxiliary feature conv.\n                          # Must be the same as num_mels.\n    aux_context_window: 2 # Context window size for auxiliary feature.\n                          # If set to 2, previous 2 and future 2 frames will be considered.\n    dropout: 0.0          # Dropout rate. 0.0 means no dropout applied.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    upsample_scales: [4, 4, 4, 4]     # Upsampling scales. prod(upsample_scales) == n_shift\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Number of output channels.\n    layers: 10            # Number of conv layers.\n    conv_channels: 64     # Number of chnn layers.\n    bias: True            # Whether to use bias parameter in conv.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear function after each conv.\n    nonlinear_activation_params:      # Nonlinear function parameters\n        negative_slope: 0.2           # Alpha in leakyrelu.\n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 4.0  # Loss balancing coefficient.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 8              # Batch size.\nbatch_max_steps: 25600     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-6        # Generator's epsilon.\n    weight_decay: 0.0      # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 0.0001  # Generator's learning rate.\n    step_size: 200000      # Generator's scheduler step size.\n    gamma: 0.5             # Generator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ngenerator_grad_norm: 10    # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-6         # Discriminator's epsilon.\n    weight_decay: 0.0       # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 0.00005  # Discriminator's learning rate.\n    step_size: 200000       # Discriminator's scheduler step size.\n    gamma: 0.5              # Discriminator's scheduler gamma.\n                            # At each step size, lr will be multiplied by this parameter.\ndiscriminator_grad_norm: 1  # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 400000                 # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_save_intermediate_results: 4  # Number of results to be saved as intermediate results.\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random"
  },
  {
    "path": "examples/ljspeech/voc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./ljspeech_alignment \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../preprocess.py \\\n        --rootdir=~/datasets/LJSpeech-1.1/ \\\n        --dataset=ljspeech \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --cut-sil=True \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/ljspeech/voc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/ljspeech/voc5/README.md",
    "content": "# HiFiGAN with the LJSpeech-1.1\nThis example contains code used to train a [HiFiGAN](https://arxiv.org/abs/2010.05646) model with [LJSpeech-1.1](https://keithito.com/LJ-Speech-Dataset/).\n## Dataset\n### Download and Extract\nDownload LJSpeech-1.1 from it's [Official Website](https://keithito.com/LJ-Speech-Dataset/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/LJSpeech-1.1`.\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [ljspeech_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/LJSpeech-1.1`.\nAssume the path to the MFA result of LJSpeech-1.1 is `./ljspeech_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a HiFiGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       HiFiGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nThe pretrained model can be downloaded here:\n- [hifigan_ljspeech_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [hifigan_ljspeech_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_static_1.1.0.zip)\n\nThe ONNX model can be downloaded here:\n- [hifigan_ljspeech_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [hifigan_ljspeech_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_pdlite_1.3.0.zip)\n\nModel | Step | eval/generator_loss | eval/mel_loss| eval/feature_matching_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 2500000|24.492|0.115|7.227\n\nHiFiGAN checkpoint contains files listed below.\n\n```text\nhifigan_ljspeech_ckpt_0.2.0\n├── default.yaml                  # default config used to train hifigan\n├── feats_stats.npy               # statistics used to normalize spectrogram when training hifigan\n└── snapshot_iter_2500000.pdz     # generator parameters of hifigan\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/ljspeech/voc5/conf/default.yaml",
    "content": "# This is the configuration file for LJSpeech dataset.\n# This configuration is based on HiFiGAN V1, which is an official configuration. \n# But I found that the optimizer setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 22050                # Sampling rate.\nn_fft: 1024              # FFT size (samples).\nn_shift: 256             # Hop size (samples). 11.6ms\nwin_length: null         # Window length (samples).\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [8, 8, 2, 2]         # Upsampling scales.\n    upsample_kernel_sizes: [16, 16, 4, 4] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 22050\n    fft_size: 1024\n    hop_size: 256\n    win_length: null\n    window: \"hann\"\n    num_mels: 80\n    fmin: 0\n    fmax: 11025\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8192       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/ljspeech/voc5/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/mustc/st1/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/mustc/st1/conf/fbank.conf",
    "content": "--sample-frequency=16000 \n--num-mel-bins=80\n"
  },
  {
    "path": "examples/mustc/st1/conf/pitch.conf",
    "content": "--sample-frequency=16000\n"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_de.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.de.train\ndev_manifest: data/manifest.de.dev\ntest_manifest: data/manifest.de.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-de.de_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-de.de_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_es.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.es.train\ndev_manifest: data/manifest.es.dev\ntest_manifest: data/manifest.es.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-es.es_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-es.es_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_fr.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.fr.train\ndev_manifest: data/manifest.fr.dev\ntest_manifest: data/manifest.fr.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-fr.fr_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-fr.fr_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_it.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.it.train\ndev_manifest: data/manifest.it.dev\ntest_manifest: data/manifest.it.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-it.it_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-it.it_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_nl.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.nl.train\ndev_manifest: data/manifest.nl.dev\ntest_manifest: data/manifest.nl.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-nl.nl_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-nl.nl_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_pt.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.pt.train\ndev_manifest: data/manifest.pt.dev\ntest_manifest: data/manifest.pt.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-pt.pt_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-pt.pt_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_ro.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.ro.train\ndev_manifest: data/manifest.ro.dev\ntest_manifest: data/manifest.ro.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-ro.ro_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-ro.ro_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/conf/transformer_ru.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.ru.train\ndev_manifest: data/manifest.ru.dev\ntest_manifest: data/manifest.ru.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_1spm/train_sp.en-ru.ru_bpe8000_units_tc.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_1spm/train_sp.en-ru.ru_bpe8000_tc\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5"
  },
  {
    "path": "examples/mustc/st1/local/augmentation.json",
    "content": "[\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 5,\n      \"warp_mode\": \"PIL\",\n      \"F\": 30,\n      \"n_freq_masks\": 2,\n      \"T\": 40,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": false\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/mustc/st1/local/data.sh",
    "content": "#!/bin/bash\n\n# Copyright 2019 Kyoto University (Hirofumi Inaguma)\n#           2021 PaddlePaddle\n#  Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\n\nset -e\nset -u\n\nstage=-1\nstop_stage=10\n\n# bpemode (unigram or bpe)\ntgt_lang=\nnbpe=8000\nbpemode=bpe\nmust_c=\ndumpdir=data/dump\ndo_delta=false\ntgt_case=tc\nsrc_case=lc.rm\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nTARGET_DIR=${MAIN_ROOT}/examples/dataset\nmkdir -p ${TARGET_DIR}\nmkdir -p data\n\ntrain_set=train_sp.en-${tgt_lang}.${tgt_lang}\ntrain_dev=dev.en-${tgt_lang}.${tgt_lang}\ntrans_set=\"\"\nfor lang in $(echo ${tgt_lang} | tr '_' ' '); do\n    trans_set=\"${trans_set} tst-COMMON.en-${lang}.${lang}\"\ndone\n\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    if [ ! -e ${must_c} ]; then\n        echo \"Error: Dataset is not avaiable. Please download and unzip the dataset\"\n        echo \"Link of Must-c v1, https://ict.fbk.eu/must-c/.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"stage 0: Data Preparation\"\n    for lang in $(echo ${tgt_lang} | tr '_' ' '); do\n        local/data_prep.sh ${must_c} ${lang}\n    done\nfi\n\nfeat_tr_dir=${dumpdir}/${train_set}/delta${do_delta}; mkdir -p ${feat_tr_dir}\nfeat_dt_dir=${dumpdir}/${train_dev}/delta${do_delta}; mkdir -p ${feat_dt_dir}\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ### Task dependent. You have to design training and dev sets by yourself.\n    ### But you can utilize Kaldi recipes in most cases\n    echo \"stage 1: Feature Generation\"\n    fbankdir=fbank\n    # Generate the fbank features; by default 80-dimensional fbanks with pitch on each frame\n    for lang in $(echo ${tgt_lang} | tr '_' ' '); do\n        for x in train.en-${tgt_lang} dev.en-${tgt_lang} tst-COMMON.en-${tgt_lang} tst-HE.en-${tgt_lang}; do\n            steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj 32 --write_utt2num_frames true \\\n                data/${x} data/make_fbank/${x} ${fbankdir}\n        done\n    done\n\n    # speed-perturbed\n    utils/perturb_data_dir_speed.sh 0.9 data/train.en-${tgt_lang} data/temp1.${tgt_lang}\n    utils/perturb_data_dir_speed.sh 1.0 data/train.en-${tgt_lang} data/temp2.${tgt_lang}\n    utils/perturb_data_dir_speed.sh 1.1 data/train.en-${tgt_lang} data/temp3.${tgt_lang}\n    utils/combine_data.sh --extra-files utt2uniq data/train_sp.en-${tgt_lang} \\\n        data/temp1.${tgt_lang} data/temp2.${tgt_lang} data/temp3.${tgt_lang}\n    rm -r data/temp1.${tgt_lang} data/temp2.${tgt_lang} data/temp3.${tgt_lang}\n    utils/fix_data_dir.sh data/train_sp.en-${tgt_lang}\n    steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj 32 --write_utt2num_frames true \\\n        data/train_sp.en-${tgt_lang} data/make_fbank/train_sp.en-${tgt_lang} ${fbankdir}\n    for lang in en ${tgt_lang}; do\n        awk -v p=\"sp0.9-\" '{printf(\"%s %s%s\\n\", $1, p, $1);}' data/train.en-${tgt_lang}/utt2spk > data/train_sp.en-${tgt_lang}/utt_map\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.tc.${lang} >data/train_sp.en-${tgt_lang}/text.tc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.${lang} >data/train_sp.en-${tgt_lang}/text.lc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.rm.${lang} >data/train_sp.en-${tgt_lang}/text.lc.rm.${lang}\n        awk -v p=\"sp1.0-\" '{printf(\"%s %s%s\\n\", $1, p, $1);}' data/train.en-${tgt_lang}/utt2spk > data/train_sp.en-${tgt_lang}/utt_map\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.tc.${lang} >>data/train_sp.en-${tgt_lang}/text.tc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.${lang} >>data/train_sp.en-${tgt_lang}/text.lc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.rm.${lang} >>data/train_sp.en-${tgt_lang}/text.lc.rm.${lang}\n        awk -v p=\"sp1.1-\" '{printf(\"%s %s%s\\n\", $1, p, $1);}' data/train.en-${tgt_lang}/utt2spk > data/train_sp.en-${tgt_lang}/utt_map\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.tc.${lang} >>data/train_sp.en-${tgt_lang}/text.tc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.${lang} >>data/train_sp.en-${tgt_lang}/text.lc.${lang}\n        utils/apply_map.pl -f 1 data/train_sp.en-${tgt_lang}/utt_map <data/train.en-${tgt_lang}/text.lc.rm.${lang} >>data/train_sp.en-${tgt_lang}/text.lc.rm.${lang}\n    done\n\n    # Divide into source and target languages\n    for x in train_sp.en-${tgt_lang} dev.en-${tgt_lang} tst-COMMON.en-${tgt_lang} tst-HE.en-${tgt_lang}; do\n        local/divide_lang.sh ${x} ${tgt_lang}\n    done\n\n    for x in train_sp.en-${tgt_lang} dev.en-${tgt_lang}; do\n        # remove utt having more than 3000 frames\n        # remove utt having more than 400 characters\n        for lang in ${tgt_lang} en; do\n            remove_longshortdata.sh --maxframes 3000 --maxchars 400 data/${x}.${lang} data/${x}.${lang}.tmp\n        done\n\n        # Match the number of utterances between source and target languages\n        # extract commocn lines\n        cut -f 1 -d \" \" data/${x}.en.tmp/text > data/${x}.${tgt_lang}.tmp/reclist1\n        cut -f 1 -d \" \" data/${x}.${tgt_lang}.tmp/text > data/${x}.${tgt_lang}.tmp/reclist2\n        comm -12 data/${x}.${tgt_lang}.tmp/reclist1 data/${x}.${tgt_lang}.tmp/reclist2 > data/${x}.en.tmp/reclist\n\n        for lang in ${tgt_lang} en; do\n            reduce_data_dir.sh data/${x}.${lang}.tmp data/${x}.en.tmp/reclist data/${x}.${lang}\n            utils/fix_data_dir.sh --utt_extra_files \"text.tc text.lc text.lc.rm\" data/${x}.${lang}\n        done\n        rm -rf data/${x}.*.tmp\n    done\n\n    # compute global CMVN\n    compute-cmvn-stats scp:data/${train_set}/feats.scp data/${train_set}/cmvn.ark\n\n    # dump features for training\n    if [[ $(hostname -f) == *.clsp.jhu.edu ]] && [ ! -d ${feat_tr_dir}/storage ]; then\n      utils/create_split_dir.pl \\\n          /export/b{14,15,16,17}/${USER}/espnet-data/egs/must_c/st1/dump/${train_set}/delta${do_delta}/storage \\\n          ${feat_tr_dir}/storage\n    fi\n    if [[ $(hostname -f) == *.clsp.jhu.edu ]] && [ ! -d ${feat_dt_dir}/storage ]; then\n      utils/create_split_dir.pl \\\n          /export/b{14,15,16,17}/${USER}/espnet-data/egs/must_c/st1/dump/${train_dev}/delta${do_delta}/storage \\\n          ${feat_dt_dir}/storage\n    fi\n    dump.sh --cmd \"$train_cmd\" --nj 80 --do_delta $do_delta \\\n        data/${train_set}/feats.scp data/${train_set}/cmvn.ark data/dump_feats/${train_set} ${feat_tr_dir}\n    dump.sh --cmd \"$train_cmd\" --nj 32 --do_delta $do_delta \\\n        data/${train_dev}/feats.scp data/${train_set}/cmvn.ark data/dump_feats/${train_dev} ${feat_dt_dir}\n    for ttask in ${trans_set}; do\n        feat_trans_dir=${dumpdir}/${ttask}/delta${do_delta}; mkdir -p ${feat_trans_dir}\n        dump.sh --cmd \"$train_cmd\" --nj 32 --do_delta $do_delta \\\n            data/${ttask}/feats.scp data/${train_set}/cmvn.ark data/dump_feats/trans/${ttask} \\\n            ${feat_trans_dir}\n    done\nfi\n\ndict=data/lang_1spm/${train_set}_${bpemode}${nbpe}_units_${tgt_case}.txt\nnlsyms=data/lang_1spm/${train_set}_non_lang_syms_${tgt_case}.txt\nbpemodel=data/lang_1spm/${train_set}_${bpemode}${nbpe}_${tgt_case}\necho \"dictionary: ${dict}\"\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    ### Task dependent. You have to check non-linguistic symbols used in the corpus.\n    echo \"stage 2: Dictionary and Json Data Preparation\"\n    mkdir -p data/lang_1spm/\n    export LC_ALL=C.UTF-8\n\n    echo \"make a non-linguistic symbol list for all languages\"\n    grep sp1.0 data/train_sp.en-${tgt_lang}.*/text.${tgt_case} | cut -f 2- -d' ' | grep -o -P '&[^;]*;'| sort | uniq > ${nlsyms}\n    cat ${nlsyms}\n\n    echo \"make a joint source and target dictionary\"\n    echo \"<unk> 1\" > ${dict} # <unk> must be 1, 0 will be used for \"blank\" in CTC\n    offset=$(wc -l < ${dict})\n    grep sp1.0 data/train_sp.en-${tgt_lang}.${tgt_lang}/text.${tgt_case} | cut -f 2- -d' ' | grep -v -e '^\\s*$' > data/lang_1spm/input_${tgt_lang}.txt\n    grep sp1.0 data/train_sp.en-${tgt_lang}.en/text.${src_case} | cut -f 2- -d' ' | grep -v -e '^\\s*$' >> data/lang_1spm/input_${tgt_lang}.txt\n    spm_train --user_defined_symbols=\"$(tr \"\\n\" \",\" < ${nlsyms})\" --input=data/lang_1spm/input_${tgt_lang}.txt --vocab_size=${nbpe} --model_type=${bpemode} --model_prefix=${bpemodel} --input_sentence_size=100000000 --character_coverage=1.0\n    spm_encode --model=${bpemodel}.model --output_format=piece < data/lang_1spm/input_${tgt_lang}.txt | tr ' ' '\\n' | sort | uniq | awk -v offset=${offset} '{print $0 \" \" NR+offset}' >> ${dict}\n    wc -l ${dict}\n\n    echo \"make json files\"\n    data2json.sh --nj 16 --feat ${feat_tr_dir}/feats.scp --text data/${train_set}/text.${tgt_case} --bpecode ${bpemodel}.model --lang ${tgt_lang} \\\n        data/${train_set} ${dict} > ${feat_tr_dir}/data_${bpemode}${nbpe}.${tgt_case}.json\n    data2json.sh --feat ${feat_dt_dir}/feats.scp --text data/${train_dev}/text.${tgt_case} --bpecode ${bpemodel}.model --lang ${tgt_lang} \\\n        data/${train_dev} ${dict} > ${feat_dt_dir}/data_${bpemode}${nbpe}.${tgt_case}.json\n    for ttask in ${trans_set}; do\n        feat_trans_dir=${dumpdir}/${ttask}/delta${do_delta}\n        data2json.sh --feat ${feat_trans_dir}/feats.scp --text data/${ttask}/text.${tgt_case} --bpecode ${bpemodel}.model --lang ${tgt_lang} \\\n            data/${ttask} ${dict} > ${feat_trans_dir}/data_${bpemode}${nbpe}.${tgt_case}.json\n    done\n    echo \"update json (add source references)\"\n    # update json (add source references)\n    for x in ${train_set} ${train_dev}; do\n        feat_dir=${dumpdir}/${x}/delta${do_delta}\n        data_dir=data/$(echo ${x} | cut -f 1 -d \".\").en-${tgt_lang}.en\n        update_json.sh --text ${data_dir}/text.${src_case} --bpecode ${bpemodel}.model \\\n            ${feat_dir}/data_${bpemode}${nbpe}.${tgt_case}.json ${data_dir} ${dict}\n    done\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    x=(${train_set} ${train_dev} ${trans_set})\n    y=(train dev test)\n    for (( i=0; i<${#x[*]}; ++i)); do\n        echo ${x[$i]} ${y[$i]}\n        feat_dir=${dumpdir}/${x[$i]}/delta${do_delta}\n        data_dir=data/$(echo ${x[$i]} | cut -f 1 -d \".\").en-${tgt_lang}.en\n        python3 ${MAIN_ROOT}/utils/espnet_json_to_manifest.py \\\n                --json-file ${feat_dir}/data_${bpemode}${nbpe}.${tgt_case}.json \\\n                --manifest-file data/manifest.${tgt_lang}.${y[$i]}\n        echo \"Process done for ${y[$i]} set from ${x[$i]}\"\n    done\nfi\n\n\necho \"MuST-C ${tgt_lang} Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/mustc/st1/local/data_prep.sh",
    "content": "#!/bin/bash\n\n# Copyright 2019 Kyoto University (Hirofumi Inaguma)\n#  Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\n\nexport LC_ALL=C\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nif [ \"$#\" -ne 2 ]; then\n    echo \"Usage: $0 <src-dir>\"\n    echo \"e.g.: $0 /n/rd11/corpora_8/MUSTC_v1.0 target_lang\"\n    exit 1;\nfi\n\ntgt_lang=$2\n\nfor set in train dev tst-COMMON tst-HE; do\n    src=$1/en-${tgt_lang}/data/${set}\n    dst=data/local/en-${tgt_lang}/${set}\n\n    [ ! -d ${src} ] && echo \"$0: no such directory ${src}\" && exit 1;\n\n    wav_dir=${src}/wav\n    trans_dir=${src}/txt\n    yml=${trans_dir}/${set}.yaml\n    en=${trans_dir}/${set}.en\n    tgt=${trans_dir}/${set}.${tgt_lang}\n\n    mkdir -p ${dst} || exit 1;\n\n    [ ! -d ${wav_dir} ] && echo \"$0: no such directory ${wav_dir}\" && exit 1;\n    [ ! -d ${trans_dir} ] && echo \"$0: no such directory ${trans_dir}\" && exit 1;\n    [ ! -f ${yml} ] && echo \"$0: expected file ${yml} to exist\" && exit 1;\n    [ ! -f ${en} ] && echo \"$0: expected file ${en} to exist\" && exit 1;\n    [ ! -f ${tgt} ] && echo \"$0: expected file ${tgt} to exist\" && exit 1;\n\n    wav_scp=${dst}/wav.scp; [[ -f \"${wav_scp}\" ]] && rm ${wav_scp}\n    trans_en=${dst}/text.en; [[ -f \"${trans_en}\" ]] && rm ${trans_en}\n    trans_tgt=${dst}/text.${tgt_lang}; [[ -f \"${trans_tgt}\" ]] && rm ${trans_tgt}\n    utt2spk=${dst}/utt2spk; [[ -f \"${utt2spk}\" ]] && rm ${utt2spk}\n    spk2utt=${dst}/spk2utt; [[ -f \"${spk2utt}\" ]] && rm ${spk2utt}\n    segments=${dst}/segments; [[ -f \"${segments}\" ]] && rm ${segments}\n\n    # error check\n    n=$(cat ${yml} | grep duration | wc -l)\n    n_en=$(cat ${en} | wc -l)\n    n_tgt=$(cat ${tgt} | wc -l)\n    [ ${n} -ne ${n_en} ] && echo \"Warning: expected ${n} data data files, found ${n_en}\" && exit 1;\n    [ ${n} -ne ${n_tgt} ] && echo \"Warning: expected ${n} data data files, found ${n_tgt}\" && exit 1;\n\n    # (1a) Transcriptions and translations preparation\n    # make basic transcription file (add segments info)\n    cp ${yml} ${dst}/.yaml0\n    grep duration ${dst}/.yaml0 > ${dst}/.yaml1\n    awk '{\n        duration=$3; offset=$5; spkid=$7;\n        gsub(\",\",\"\",duration);\n        gsub(\",\",\"\",offset);\n        gsub(\",\",\"\",spkid);\n        gsub(\"spk.\",\"\",spkid);\n        duration=sprintf(\"%.7f\", duration);\n        if ( duration < 0.2 ) extendt=sprintf(\"%.7f\", (0.2-duration)/2);\n        else extendt=0;\n        offset=sprintf(\"%.7f\", offset);\n        startt=offset-extendt;\n        endt=offset+duration+extendt;\n        printf(\"ted_%05d_%07.0f_%07.0f\\n\", spkid, int(1000*startt+0.5), int(1000*endt+0.5));\n    }' ${dst}/.yaml1 > ${dst}/.yaml2\n    # NOTE: Extend the lengths of short utterances (< 0.2s) rather than exclude them\n\n    cp ${en} ${dst}/en.org\n    cp ${tgt} ${dst}/${tgt_lang}.org\n\n    for lang in en ${tgt_lang}; do\n        # normalize punctuation\n        normalize-punctuation.perl -l ${lang} < ${dst}/${lang}.org > ${dst}/${lang}.norm\n\n        # lowercasing\n        lowercase.perl < ${dst}/${lang}.norm > ${dst}/${lang}.norm.lc\n        cp ${dst}/${lang}.norm ${dst}/${lang}.norm.tc\n\n        # remove punctuation\n        local/remove_punctuation.pl < ${dst}/${lang}.norm.lc > ${dst}/${lang}.norm.lc.rm\n\n        # tokenization\n        tokenizer.perl -l ${lang} -q < ${dst}/${lang}.norm.tc > ${dst}/${lang}.norm.tc.tok\n        tokenizer.perl -l ${lang} -q < ${dst}/${lang}.norm.lc > ${dst}/${lang}.norm.lc.tok\n        tokenizer.perl -l ${lang} -q < ${dst}/${lang}.norm.lc.rm > ${dst}/${lang}.norm.lc.rm.tok\n\n        paste -d \" \" ${dst}/.yaml2 ${dst}/${lang}.norm.tc.tok | sort > ${dst}/text.tc.${lang}\n        paste -d \" \" ${dst}/.yaml2 ${dst}/${lang}.norm.lc.tok | sort > ${dst}/text.lc.${lang}\n        paste -d \" \" ${dst}/.yaml2 ${dst}/${lang}.norm.lc.rm.tok | sort > ${dst}/text.lc.rm.${lang}\n\n        # save original and cleaned punctuation\n        lowercase.perl < ${dst}/${lang}.org | text2token.py -s 0 -n 1 | tr \" \" \"\\n\" \\\n            | sort | uniq | grep -v -e '^\\s*$' | awk '{print $0 \" \" NR+1}' > ${dst}/punctuation.${lang}\n        lowercase.perl < ${dst}/${lang}.norm.tc | text2token.py -s 0 -n 1 | tr \" \" \"\\n\" \\\n            | sort | uniq | grep -v -e '^\\s*$' | awk '{print $0 \" \" NR+1}' > ${dst}/punctuation.clean.${lang}\n    done\n\n\n    # error check\n    n=$(cat ${dst}/.yaml2 | wc -l)\n    n_en=$(cat ${dst}/en.norm.tc.tok | wc -l)\n    n_tgt=$(cat ${dst}/${tgt_lang}.norm.tc.tok | wc -l)\n    [ ${n} -ne ${n_en} ] && echo \"Warning: expected ${n} data data files, found ${n_en}\" && exit 1;\n    [ ${n} -ne ${n_tgt} ] && echo \"Warning: expected ${n} data data files, found ${n_tgt}\" && exit 1;\n\n\n    # (1c) Make segments files from transcript\n    #segments file format is: utt-id start-time end-time, e.g.:\n    #ted_00001_0003501_0003684 ted_0001 003.501 0003.684\n    awk '{\n        segment=$1; split(segment,S,\"[_]\");\n        spkid=S[1] \"_\" S[2]; startf=S[3]; endf=S[4];\n        printf(\"%s %s %.2f %.2f\\n\", segment, spkid, startf/1000, endf/1000);\n    }' < ${dst}/text.tc.${tgt_lang} | uniq | sort > ${dst}/segments\n\n    awk '{\n        segment=$1; split(segment,S,\"[_]\");\n        spkid=S[1] \"_\" S[2];\n        printf(\"%s cat '${wav_dir}'/%s_%d.wav |\\n\", spkid, S[1], S[2]);\n    }' < ${dst}/text.tc.${tgt_lang} | uniq | sort > ${dst}/wav.scp\n\n    awk '{\n        segment=$1; split(segment,S,\"[_]\");\n        spkid=S[1] \"_\" S[2]; print $1 \" \" spkid\n    }' ${dst}/segments | uniq | sort > ${dst}/utt2spk\n\n    cat ${dst}/utt2spk | utils/utt2spk_to_spk2utt.pl | sort > ${dst}/spk2utt\n\n    # error check\n    n_en=$(cat ${dst}/text.tc.en | wc -l)\n    n_tgt=$(cat ${dst}/text.tc.${tgt_lang} | wc -l)\n    [ ${n_en} -ne ${n_tgt} ] && echo \"Warning: expected ${n_en} data data files, found ${n_tgt}\" && exit 1;\n\n    # Copy stuff intoc its final locations [this has been moved from the format_data script]\n    mkdir -p data/${set}.en-${tgt_lang}\n\n    # remove duplicated utterances (the same offset)\n    echo \"remove duplicate lines...\"\n    cut -d ' ' -f 1 ${dst}/text.tc.en | sort | uniq -c | sort -n -k1 -r | grep -v '1 ted' \\\n        | sed 's/^[ \\t]*//' > ${dst}/duplicate_lines\n    cut -d ' ' -f 1 ${dst}/text.tc.en | sort | uniq -c | sort -n -k1 -r | grep '1 ted' \\\n        | cut -d '1' -f 2- | sed 's/^[ \\t]*//' > ${dst}/reclist\n    reduce_data_dir.sh ${dst} ${dst}/reclist data/${set}.en-${tgt_lang}\n    for l in en ${tgt_lang}; do\n        for case in tc lc lc.rm; do\n            cp ${dst}/text.${case}.${l} data/${set}.en-${tgt_lang}/text.${case}.${l}\n        done\n    done\n    utils/fix_data_dir.sh --utt_extra_files \\\n        \"text.tc.en text.lc.en text.lc.rm.en text.tc.${tgt_lang} text.lc.${tgt_lang} text.lc.rm.${tgt_lang}\" \\\n        data/${set}.en-${tgt_lang}\n\n    # error check\n    n_seg=$(cat data/${set}.en-${tgt_lang}/segments | wc -l)\n    n_text=$(cat data/${set}.en-${tgt_lang}/text.tc.${tgt_lang} | wc -l)\n    [ ${n_seg} -ne ${n_text} ] && echo \"Warning: expected ${n_seg} data data files, found ${n_text}\" && exit 1;\n\n    echo \"$0: successfully prepared data in ${dst}\"\ndone\n"
  },
  {
    "path": "examples/mustc/st1/local/divide_lang.sh",
    "content": "#!/bin/bash\n\n# Copyright 2019 Kyoto University (Hirofumi Inaguma)\n#  Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\n\n. ./path.sh\n\nif [ \"$#\" -ne 2 ]; then\n    echo \"Usage: $0 <set> <lang>>\"\n    echo \"e.g.: $0 dev\"\n    exit 1\nfi\n\nset=$1\nlang=$2\nexport LC_ALL=en_US.UTF-8\n# Copy stuff intoc its final locations [this has been moved from the format_data script]\n# for En\nmkdir -p data/${set}.en\nfor f in spk2utt utt2spk segments wav.scp feats.scp utt2num_frames; do\n    if [ -f data/${set}/${f} ]; then\n        sort data/${set}/${f} > data/${set}.en/${f}\n    fi\ndone\nsort data/${set}/text.lc.rm.en | sed $'s/[^[:print:]]//g' > data/${set}.en/text  # dummy\nsort data/${set}/text.tc.en | sed $'s/[^[:print:]]//g' > data/${set}.en/text.tc\nsort data/${set}/text.lc.en | sed $'s/[^[:print:]]//g' > data/${set}.en/text.lc\nsort data/${set}/text.lc.rm.en | sed $'s/[^[:print:]]//g' > data/${set}.en/text.lc.rm\nutils/fix_data_dir.sh --utt_extra_files \"text.tc text.lc text.lc.rm\" data/${set}.en\nif [ -f data/${set}.en/feats.scp ]; then\n    utils/validate_data_dir.sh data/${set}.en || exit 1;\nelse\n    utils/validate_data_dir.sh --no-feats --no-wav data/${set}.en || exit 1;\nfi\n\n# for target language\nmkdir -p data/${set}.${lang}\nfor f in spk2utt utt2spk segments wav.scp feats.scp utt2num_frames; do\n    if [ -f data/${set}/${f} ]; then\n        sort data/${set}/${f} > data/${set}.${lang}/${f}\n    fi\ndone\nsort data/${set}/text.tc.${lang} | sed $'s/[^[:print:]]//g' > data/${set}.${lang}/text  # dummy\nsort data/${set}/text.tc.${lang} | sed $'s/[^[:print:]]//g' > data/${set}.${lang}/text.tc\nsort data/${set}/text.lc.${lang} | sed $'s/[^[:print:]]//g' > data/${set}.${lang}/text.lc\nsort data/${set}/text.lc.rm.${lang} | sed $'s/[^[:print:]]//g' > data/${set}.${lang}/text.lc.rm\nutils/fix_data_dir.sh --utt_extra_files \"text.tc text.lc text.lc.rm\" data/${set}.${lang}\nif [ -f data/${set}.${lang}/feats.scp ]; then\n    utils/validate_data_dir.sh data/${set}.${lang} || exit 1;\nelse\n    utils/validate_data_dir.sh --no-feats --no-wav data/${set}.${lang} || exit 1;\nfi\n"
  },
  {
    "path": "examples/mustc/st1/local/remove_punctuation.pl",
    "content": "#!/usr/bin/perl\n\nuse warnings;\nuse strict;\n\nbinmode(STDIN,\":utf8\");\nbinmode(STDOUT,\":utf8\");\n\nwhile(<STDIN>) {\n  $_ = \" $_ \";\n\n  # remove punctuation except apostrophe\n  s/<space>/spacemark/g;  # for scoring\n  s/'/apostrophe/g;\n  s/[[:punct:]]//g;\n  s/apostrophe/'/g;\n  s/spacemark/<space>/g;  # for scoring\n\n  # remove whitespace\n  s/\\s+/ /g;\n  s/^\\s+//;\n  s/\\s+$//;\n\n  print \"$_\\n\";\n}\n"
  },
  {
    "path": "examples/mustc/st1/local/test.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix lang\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\ntgt_lang=$4\n\nfor type in fullsentence; do\n    echo \"decoding ${type}\"\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\n    echo $PATH\n    python3 ${MAIN_ROOT}/utils/rsl2trn.py --rsl ${ckpt_prefix}.${type}.rsl \\\n                            --hyp ${ckpt_prefix}.${type}.hyp \\\n                            --ref ${ckpt_prefix}.${type}.ref\n    if ! which tokenizer.perl > /dev/null; then\n    echo \"Error: it seems that moses is not installed.\" >&2\n    echo \"Error: please install moses as follows.\" >&2\n    echo \"Error: cd ${MAIN_ROOT}/tools && make moses.done\" >&2\n    return 1\n    fi\n    detokenizer.perl -l ${tgt_lang} -q < ${ckpt_prefix}.${type}.hyp > ${ckpt_prefix}.${type}.hyp.detok\n    detokenizer.perl -l ${tgt_lang} -q < ${ckpt_prefix}.${type}.ref > ${ckpt_prefix}.${type}.ref.detok\n    echo \"Detokenized BLEU:\"\n    sacrebleu ${ckpt_prefix}.${type}.ref.detok -i ${ckpt_prefix}.${type}.hyp.detok\n\n\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/mustc/st1/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 3 ] && [ $# -gt 4 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ckpt_path ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nckpt_path=$3\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--checkpoint_path \"${ckpt_path}\" \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--checkpoint_path \"${ckpt_path}\" \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/mustc/st1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${MAIN_ROOT}/tools/moses/scripts/tokenizer:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nif ! which tokenizer.perl > /dev/null; then\n    echo \"Error: moses is required in this example.\" >&2\n    echo \"Error: it seems that moses is not installed.\" >&2\n    echo \"Error: please install moses as follows.\" >&2\n    echo \"Error: cd ${MAIN_ROOT}/tools && git clone https://github.com/moses-smt/mosesdecoder.git moses\" >&2\n    return 1\nfi\n\nMODEL=u2_st\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n\n# Kaldi\nexport KALDI_ROOT=${MAIN_ROOT}/tools/kaldi\n[ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh\nexport PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH\n[ ! -f $KALDI_ROOT/tools/config/common_path.sh ] && echo >&2 \"The standard file $KALDI_ROOT/tools/config/common_path.sh is not present, can not using Kaldi!\"\n[ -f $KALDI_ROOT/tools/config/common_path.sh ] && . $KALDI_ROOT/tools/config/common_path.sh"
  },
  {
    "path": "examples/mustc/st1/run.sh",
    "content": "#!/bin/bash\nset -e\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2,3\nstage=0\nstop_stage=3\nconf_path=conf/transformer_es.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\nmust_c_path=\nlang=es\navg_num=5\nckpt_path= #  (finetune from FAT-ST or ASR pretrained model)\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh --tgt_lang ${lang} --must_c ${must_c_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt} \"${ckpt_path}\" ${ips} \nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num} \nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${lang} || exit -1\nfi\n"
  },
  {
    "path": "examples/opencpop/README.md",
    "content": "\n# Opencpop\n\n* svs1 - DiffSinger\n* voc1 - Parallel WaveGAN\n* voc5 - HiFiGAN\n"
  },
  {
    "path": "examples/opencpop/svs1/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n# DiffSinger with Opencpop\nThis example contains code used to train a [DiffSinger](https://arxiv.org/abs/2105.02446) model with [Mandarin singing corpus](https://wenet.org.cn/opencpop/).\n\n## Dataset\n### Download and Extract\nDownload Opencpop from it's [Official Website](https://wenet.org.cn/opencpop/download/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/Opencpop`.\n\n### pip install\n<!-- Comment: Cause ppdiffusers will install newest huggingface_hub, but cached_download function has been removed, So need to install the specified version.>\n<!-- TODO: If the corresponding dependency library is OK, it needs to be deleted.-->\n```shell\npip install huggingface_hub==0.25.2\n```\n\n\n\n## Get Started\nAssume the path to the dataset is `~/datasets/Opencpop`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - (Supporting) synthesize waveform from a text file. \n5. (Supporting) inference using the static model.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    ├── speech_stats.npy\n    └── speech_stretchs.npy\n\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech, pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`. `speech_stretchs.npy` contains the minimum and maximum values of each dimension of the mel spectrum, which is used for linear stretching before training/inference of the diffusion module.\nNote: Since the training effect of non-norm features is due to norm, the features saved under `norm` are features that have not been normed.\n\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains utterance id, speaker id, phones, text_lengths, speech_lengths, phone durations, the path of speech features, the path of pitch features, the path of energy features, note, note durations, slur.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--speech-stretchs SPEECH_STRETCHS]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       diffsinger config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --speech-stretchs SPEECH_STRETCHS\n                        min amd max mel for stretching.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n6. `--speech-stretchs` is the path of mel's min-max data file.\n\n### Synthesizing\nWe use parallel wavegan as the neural vocoder.\nDownload pretrained parallel wavegan model from [pwgan_opencpop_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/svs/opencpop/pwgan_opencpop_ckpt_1.4.0.zip) and unzip it.\n```bash\nunzip pwgan_opencpop_ckpt_1.4.0.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwgan_opencpop_ckpt_1.4.0.zip\n├── default.yaml                   # default config used to train parallel wavegan\n├── snapshot_iter_100000.pdz       # model parameters of parallel wavegan\n└── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\nuse `pwgan` model as vocoder.\n\n```text\nusage: synthesize.py [-h]\n                     [--am {diffsinger_opencpop}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--voc {pwgan_opencpop}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n                     [--speech_stretchs SPEECH_STRETCHS]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n       {diffsinger_opencpop} Choose acoustic model type of svs task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n        {pwgan_opencpop, hifigan_opencpop} Choose vocoder type of svs task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n  --speech-stretchs     SPEECH_STRETCHS\n                        The min and max values of the mel spectrum, using on diffusion of diffsinger.\n```\n\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file. \n`local/pinyin_to_phone.txt` comes from the readme of the opencpop dataset, indicating the mapping from pinyin to phonemes in opencpop.\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n                         [--pinyin_phone PINYIN_PHONE]\n                         [--speech_stretchs SPEECH_STRETCHS]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n       {diffsinger_opencpop} Choose acoustic model type of svs task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n        {pwgan_opencpop, hifigan_opencpop} Choose vocoder type of svs task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           {zh, en, mix, canton} Choose language type of tts task.\n                        {sing} Choose language type of svs task.\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize file, a 'utt_id sentence' pair per line for tts task.\n                        A '{ utt_id input_type (is word) text notes note_durs}' or '{utt_id input_type (is phoneme) phones notes note_durs is_slurs}' pair per line for svs task.\n  --output_dir OUTPUT_DIR\n                        output dir.\n  --pinyin_phone PINYIN_PHONE\n                        pinyin to phone map file, using on sing_frontend.\n  --speech_stretchs SPEECH_STRETCHS\n                        The min and max values of the mel spectrum, using on diffusion of diffsinger.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` and `--phones_dict` are arguments for acoustic model, which correspond to the 4 files in the diffsinger pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is language. `zh`, `en`, `mix` and `canton` for tts task. `sing` for tts task.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n10. `--inference_dir` is the directory to save static models. If this line is not added, it will not be generated and saved as a static model.\n11. `--pinyin_phone` pinyin to phone map file, using on sing_frontend.\n12. `--speech_stretchs` The min and max values of the mel spectrum, using on diffusion of diffsinger.\n\nNote: At present, the diffsinger model does not support dynamic to static, so do not add `--inference_dir`.\n\n\n## Pretrained Model\nPretrained DiffSinger model:\n- [diffsinger_opencpop_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/svs/opencpop/diffsinger_opencpop_ckpt_1.4.0.zip)\n\nDiffSinger checkpoint contains files listed below.\n```text\ndiffsinger_opencpop_ckpt_1.4.0.zip\n├── default.yaml             # default config used to train diffsinger\n├── energy_stats.npy         # statistics used to normalize energy when training diffsinger if norm is needed\n├── phone_id_map.txt         # phone vocabulary file when training diffsinger\n├── pinyin_to_phone.txt      # pinyin-to-phoneme mapping file when training diffsinger\n├── pitch_stats.npy          # statistics used to normalize pitch when training diffsinger if norm is needed \n├── snapshot_iter_160000.pdz # model parameters of diffsinger\n├── speech_stats.npy         # statistics used to normalize mel when training diffsinger if norm is needed\n└── speech_stretchs.npy      # min and max values to use for mel spectral stretching before training diffusion\n\n```\n\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences_sing.txt` using pretrained diffsinger and parallel wavegan models.\n\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=diffsinger_opencpop \\\n  --am_config=diffsinger_opencpop_ckpt_1.4.0/default.yaml \\\n  --am_ckpt=diffsinger_opencpop_ckpt_1.4.0/snapshot_iter_160000.pdz \\\n  --am_stat=diffsinger_opencpop_ckpt_1.4.0/speech_stats.npy  \\\n  --voc=pwgan_opencpop \\\n  --voc_config=pwgan_opencpop_ckpt_1.4.0/default.yaml \\\n  --voc_ckpt=pwgan_opencpop_ckpt_1.4.0/snapshot_iter_100000.pdz \\\n  --voc_stat=pwgan_opencpop_ckpt_1.4.0/feats_stats.npy \\\n  --lang=sing \\\n  --text=${BIN_DIR}/../../assets/sentences_sing.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=diffsinger_opencpop_ckpt_1.4.0/phone_id_map.txt \\\n  --pinyin_phone=diffsinger_opencpop_ckpt_1.4.0/pinyin_to_phone.txt \\\n  --speech_stretchs=diffsinger_opencpop_ckpt_1.4.0/speech_stretchs.npy\n  \n```\n"
  },
  {
    "path": "examples/opencpop/svs1/README_cn.md",
    "content": "(简体中文|[English](./README.md))\n# 用 Opencpop 数据集训练 DiffSinger 模型\n\n本用例包含用于训练 [DiffSinger](https://arxiv.org/abs/2105.02446) 模型的代码，使用 [Mandarin singing corpus](https://wenet.org.cn/opencpop/) 数据集。\n\n## 数据集\n### 下载并解压\n从 [官方网站](https://wenet.org.cn/opencpop/download/) 下载数据集\n\n### pip 安装\n<!-- 注释: 因为ppdiffusion会安装最新的huggingface_hub，但cached_download功能已被删除，所以需要安装指定的版本。>\n<!-- 待完成: 如果相应的依赖库正常，则将其删除。-->\n```shell\npip install huggingface_hub==0.25.2\n```\n\n## 开始\n假设数据集的路径是 `~/datasets/Opencpop`.\n运行下面的命令会进行如下操作：\n\n1. **设置原路径**。\n2. 对数据集进行预处理。\n3. 训练模型\n4. 合成波形\n    - 从 `metadata.jsonl` 合成波形。\n    - （支持中）从文本文件合成波形。\n5. （支持中）使用静态模型进行推理。\n```bash\n./run.sh\n```\n您可以选择要运行的一系列阶段，或者将 `stage` 设置为 `stop-stage` 以仅使用一个阶段，例如，运行以下命令只会预处理数据集。\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### 数据预处理\n```bash\n./local/preprocess.sh ${conf_path}\n```\n当它完成时。将在当前目录中创建 `dump` 文件夹。转储文件夹的结构如下所示。\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    ├── speech_stats.npy\n    └── speech_stretchs.npy\n```\n\n数据集分为三个部分，即 `train` 、 `dev` 和 `test` ，每个部分都包含一个 `norm` 和 `raw` 子文件夹。原始文件夹包含每个话语的语音、音调和能量特征，而 `norm` 文件夹包含规范化的特征。用于规范化特征的统计数据是从 `dump/train/*_stats.npy` 中的训练集计算出来的。`speech_stretchs.npy` 中包含 mel谱每个维度上的最小值和最大值，用于 diffusion 模块训练/推理前的线性拉伸。\n注意：由于非 norm 特征训练效果由于 norm，因此 `norm` 下保存的特征是未经过 norm 的特征。\n\n\n此外，还有一个 `metadata.jsonl` 在每个子文件夹中。它是一个类似表格的文件，包含话语id，音色id，音素、文本长度、语音长度、音素持续时间、语音特征路径、音调特征路径、能量特征路径、音调，音调持续时间，是否为转音。\n\n### 模型训练\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` 调用 `${BIN_DIR}/train.py` 。\n以下是完整的帮助信息。\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--speech-stretchs SPEECH_STRETCHS]\n\nTrain a DiffSinger model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       diffsinger config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --speech-stretchs SPEECH_STRETCHS\n                        min amd max mel for stretching.\n```\n1. `--config` 是一个 yaml 格式的配置文件，用于覆盖默认配置，位于 `conf/default.yaml`.\n2. `--train-metadata` 和 `--dev-metadata` 应为 `dump` 文件夹中 `train` 和 `dev` 下的规范化元数据文件\n3. `--output-dir` 是保存结果的目录。 检查点保存在此目录中的 `checkpoints/` 目录下。\n4. `--ngpu` 要使用的 GPU 数，如果 ngpu==0，则使用 cpu 。\n5. `--phones-dict` 是音素词汇表文件的路径。\n6. `--speech-stretchs` mel的最小最大值数据的文件路径。\n\n### 合成\n我们使用 parallel opencpop 作为神经声码器（vocoder）。\n从 [pwgan_opencpop_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/svs/opencpop/pwgan_opencpop_ckpt_1.4.0.zip) 下载预训练的 parallel wavegan 模型并将其解压。\n\n```bash\nunzip pwgan_opencpop_ckpt_1.4.0.zip\n```\nParallel WaveGAN 检查点包含如下文件。\n```text\npwgan_opencpop_ckpt_1.4.0.zip\n├── default.yaml               # 用于训练 parallel wavegan 的默认配置\n├── snapshot_iter_100000.pdz   # parallel wavegan 的模型参数\n└── feats_stats.npy            # 训练平行波形时用于规范化谱图的统计数据\n```\n`./local/synthesize.sh` 调用 `${BIN_DIR}/../synthesize.py` 即可从 `metadata.jsonl`中合成波形。\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n使用 `pwgan` 模型作为声码器。\n\n```text\nusage: synthesize.py [-h]\n                     [--am {diffsinger_opencpop}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--voc {pwgan_opencpop}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n                     [--speech_stretchs SPEECH_STRETCHS]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n       {diffsinger_opencpop} Choose acoustic model type of svs task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n        {pwgan_opencpop, hifigan_opencpop} Choose vocoder type of svs task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n  --speech-stretchs     SPEECH_STRETCHS\n                        The min and max values of the mel spectrum, using on diffusion of diffsinger.\n```\n\n`./local/synthesize_e2e.sh` 调用 `${BIN_DIR}/../synthesize_e2e.py`，即可从文本文件中合成波形。\n`local/pinyin_to_phone.txt`来源于opencpop数据集中的README，表示opencpop中拼音到音素的映射。\n\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\n最后一位参数 `0` 用于选择合成时使用的声码器模型，取值为 `0` 或 `1`，分别对应使用 `pwgan` 或 `hifigan` 模型作为声码器。\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n                         [--pinyin_phone PINYIN_PHONE]\n                         [--speech_stretchs SPEECH_STRETCHS]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n       {diffsinger_opencpop} Choose acoustic model type of svs task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n        {pwgan_opencpop, hifigan_opencpop} Choose vocoder type of svs task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           {zh, en, mix, canton} Choose language type of tts task.\n                        {sing} Choose language type of svs task.\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize file, a 'utt_id sentence' pair per line for tts task.\n                        A '{ utt_id input_type (is word) text notes note_durs}' or '{utt_id input_type (is phoneme) phones notes note_durs is_slurs}' pair per line for svs task.\n  --output_dir OUTPUT_DIR\n                        output dir.\n  --pinyin_phone PINYIN_PHONE\n                        pinyin to phone map file, using on sing_frontend.\n  --speech_stretchs SPEECH_STRETCHS\n                        The min and max values of the mel spectrum, using on diffusion of diffsinger.\n```\n1. `--am` 声学模型格式是否符合 {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat` 和 `--phones_dict` 是声学模型的参数，对应于 diffsinger 预训练模型中的 4 个文件。\n3. `--voc` 声码器(vocoder)格式是否符合 {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` 是声码器的参数，对应于 parallel wavegan 预训练模型中的 3 个文件。\n5. `--lang` tts对应模型的语言可以是 `zh`、`en`、`mix`和`canton`。 svs 对应的语言是 `sing` 。\n6. `--test_metadata` 应为 `dump` 文件夹中 `test` 下的规范化元数据文件、\n7. `--text` 是文本文件，其中包含要合成的句子。\n8. `--output_dir` 是保存合成音频文件的目录。\n9. `--ngpu` 要使用的GPU数，如果 ngpu==0，则使用 cpu。\n10. `--inference_dir` 静态模型保存的目录。如果不加这一行，就不会生并保存成静态模型。\n11. `--pinyin_phone` 拼音到音素的映射文件。\n12. `--speech_stretchs` mel谱的最大最小值用于diffsinger中diffusion之前的线性拉伸。\n\n注意： 目前 diffsinger 模型还不支持动转静，所以不要加 `--inference_dir`。\n\n\n## 预训练模型\n预先训练的 DiffSinger 模型：\n- [diffsinger_opencpop_ckpt_1.4.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/svs/opencpop/diffsinger_opencpop_ckpt_1.4.0.zip)\n\n\nDiffSinger 检查点包含下列文件。\n```text\ndiffsinger_opencpop_ckpt_1.4.0.zip\n├── default.yaml             # 用于训练 diffsinger 的默认配置\n├── energy_stats.npy         # 训练 diffsinger 时如若需要 norm energy 会使用到的统计数据 \n├── phone_id_map.txt         # 训练 diffsinger 时的音素词汇文件\n├── pinyin_to_phone.txt      # 训练 diffsinger 时的拼音到音素映射文件\n├── pitch_stats.npy          # 训练 diffsinger 时如若需要 norm pitch 会使用到的统计数据 \n├── snapshot_iter_160000.pdz # 模型参数和优化器状态\n├── speech_stats.npy         # 训练 diffsinger 时用于规范化频谱图的统计数据\n└── speech_stretchs.npy      # 训练 diffusion 前用于 mel 谱拉伸的最小及最大值\n\n```\n您可以使用以下脚本通过使用预训练的 diffsinger 和 parallel wavegan 模型为 `${BIN_DIR}/../sentences_sing.txt` 合成句子\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=diffsinger_opencpop \\\n  --am_config=diffsinger_opencpop_ckpt_1.4.0/default.yaml \\\n  --am_ckpt=diffsinger_opencpop_ckpt_1.4.0/snapshot_iter_160000.pdz \\\n  --am_stat=diffsinger_opencpop_ckpt_1.4.0/speech_stats.npy  \\\n  --voc=pwgan_opencpop \\\n  --voc_config=pwgan_opencpop_ckpt_1.4.0/default.yaml \\\n  --voc_ckpt=pwgan_opencpop_ckpt_1.4.0/snapshot_iter_100000.pdz \\\n  --voc_stat=pwgan_opencpop_ckpt_1.4.0/feats_stats.npy \\\n  --lang=sing \\\n  --text=${BIN_DIR}/../../assets/sentences_sing.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=diffsinger_opencpop_ckpt_1.4.0/phone_id_map.txt \\\n  --pinyin_phone=diffsinger_opencpop_ckpt_1.4.0/pinyin_to_phone.txt \\\n  --speech_stretchs=diffsinger_opencpop_ckpt_1.4.0/speech_stretchs.npy\n  \n```\n"
  },
  {
    "path": "examples/opencpop/svs1/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 512         # FFT size (samples).\nn_shift: 128       # Hop size (samples). 12.5ms\nwin_length: 512    # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 30           # Minimum frequency of Mel basis.\nfmax: 12000        # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 750         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 48     # batch size\nnum_workers: 1     # number of gpu\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    # music score related\n    note_num: 300                                     # number of note\n    is_slur_num: 2                                    # number of slur\n    # fastspeech2 module options\n    use_energy_pred: False                            # whether use energy predictor\n    use_postnet: False                                # whether use postnet\n\n    # fastspeech2 module\n    fastspeech2_params:\n        adim: 256                                     # attention dimension\n        aheads: 2                                     # number of attention heads\n        elayers: 4                                    # number of encoder layers\n        eunits: 1024                                  # number of encoder ff units\n        dlayers: 4                                    # number of decoder layers\n        dunits: 1024                                  # number of decoder ff units\n        positionwise_layer_type: conv1d-linear        # type of position-wise layer\n        positionwise_conv_kernel_size: 9              # kernel size of position wise conv layer\n        transformer_enc_dropout_rate: 0.1             # dropout rate for transformer encoder layer\n        transformer_enc_positional_dropout_rate: 0.1  # dropout rate for transformer encoder positional encoding\n        transformer_enc_attn_dropout_rate: 0.0        # dropout rate for transformer encoder attention layer\n        transformer_activation_type: \"gelu\"           # Activation function type in transformer.\n        encoder_normalize_before: True                # whether to perform layer normalization before the input\n        decoder_normalize_before: True                # whether to perform layer normalization before the input\n        reduction_factor: 1                           # reduction factor\n        init_type: xavier_uniform                     # initialization type\n        init_enc_alpha: 1.0                           # initial value of alpha of encoder scaled position encoding\n        init_dec_alpha: 1.0                           # initial value of alpha of decoder scaled position encoding\n        use_scaled_pos_enc: True                      # whether to use scaled positional encoding\n        transformer_dec_dropout_rate: 0.1             # dropout rate for transformer decoder layer\n        transformer_dec_positional_dropout_rate: 0.1  # dropout rate for transformer decoder positional encoding\n        transformer_dec_attn_dropout_rate: 0.0        # dropout rate for transformer decoder attention layer\n        duration_predictor_layers: 5                  # number of layers of duration predictor\n        duration_predictor_chans: 256                 # number of channels of duration predictor\n        duration_predictor_kernel_size: 3             # filter size of duration predictor\n        duration_predictor_dropout_rate: 0.5          # dropout rate in energy predictor\n        pitch_predictor_layers: 5                     # number of conv layers in pitch predictor\n        pitch_predictor_chans: 256                    # number of channels of conv layers in pitch predictor\n        pitch_predictor_kernel_size: 5                # kernel size of conv layers in pitch predictor\n        pitch_predictor_dropout: 0.5                  # dropout rate in pitch predictor\n        pitch_embed_kernel_size: 1                    # kernel size of conv embedding layer for pitch\n        pitch_embed_dropout: 0.0                      # dropout rate after conv embedding layer for pitch\n        stop_gradient_from_pitch_predictor: True      # whether to stop the gradient from pitch predictor to encoder\n        energy_predictor_layers: 2                    # number of conv layers in energy predictor\n        energy_predictor_chans: 256                   # number of channels of conv layers in energy predictor\n        energy_predictor_kernel_size: 3               # kernel size of conv layers in energy predictor\n        energy_predictor_dropout: 0.5                 # dropout rate in energy predictor\n        energy_embed_kernel_size: 1                   # kernel size of conv embedding layer for energy\n        energy_embed_dropout: 0.0                     # dropout rate after conv embedding layer for energy\n        stop_gradient_from_energy_predictor: False    # whether to stop the gradient from energy predictor to encoder\n        postnet_layers: 5                             # number of layers of postnet\n        postnet_filts: 5                              # filter size of conv layers in postnet\n        postnet_chans: 256                            # number of channels of conv layers in postnet\n        postnet_dropout_rate: 0.5                     # dropout rate for postnet\n \n    # denoiser module\n    denoiser_params:\n        in_channels: 80                               # Number of channels of the input mel-spectrogram\n        out_channels: 80                              # Number of channels of the output mel-spectrogram\n        kernel_size: 3                                # Kernel size of the residual blocks inside                           \n        layers: 20                                    # Number of residual blocks inside\n        stacks: 5                                     # The number of groups to split the residual blocks into\n        residual_channels: 256                        # Residual channel of the residual blocks\n        gate_channels: 512                            # Gate channel of the residual blocks\n        skip_channels: 256                            # Skip channel of the residual blocks\n        aux_channels: 256                             # Auxiliary channel of the residual blocks\n        dropout: 0.1                                  # Dropout of the residual blocks\n        bias: True                                    # Whether to use bias in residual blocks\n        use_weight_norm: False                        # Whether to use weight norm in all convolutions\n        init_type: \"kaiming_normal\"                   # Type of initialize weights of a neural network module\n\n\n    diffusion_params:\n        num_train_timesteps: 100                      # The number of timesteps between the noise and the real during training\n        beta_start: 0.0001                            # beta start parameter for the scheduler\n        beta_end: 0.06                                # beta end parameter for the scheduler\n        beta_schedule: \"linear\"                       # beta schedule parameter for the scheduler\n        num_max_timesteps: 100                        # The max timestep transition from real to noise\n        stretch: True                                 # whether to stretch before diffusion\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nfs2_updater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\nds_updater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\n# fastspeech2 optimizer\nfs2_optimizer:\n    optim: adam              # optimizer type\n    learning_rate: 0.001     # learning rate\n\n# diffusion optimizer\nds_optimizer_params:\n    beta1: 0.9\n    beta2: 0.98\n    weight_decay: 0.0\n\nds_scheduler_params:\n    learning_rate: 0.001              \n    gamma: 0.5                          \n    step_size: 50000\nds_grad_norm: 1\n\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\nonly_train_diffusion: True                 # Whether to freeze fastspeech2 parameters when training diffusion\nds_train_start_steps: 160000              # Number of steps to start to train diffusion module.\ntrain_max_steps: 320000                   # Number of training steps.\nsave_interval_steps: 2000                 # Interval steps to save checkpoint.\neval_interval_steps: 2000                 # Interval steps to evaluate the network.\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/opencpop/svs1/local/pinyin_to_phone.txt",
    "content": "a|a\nai|ai\nan|an\nang|ang\nao|ao\nba|b a\nbai|b ai\nban|b an\nbang|b ang\nbao|b ao\nbei|b ei\nben|b en\nbeng|b eng\nbi|b i\nbian|b ian\nbiao|b iao\nbie|b ie\nbin|b in\nbing|b ing\nbo|b o\nbu|b u\nca|c a\ncai|c ai\ncan|c an\ncang|c ang\ncao|c ao\nce|c e\ncei|c ei\ncen|c en\nceng|c eng\ncha|ch a\nchai|ch ai\nchan|ch an\nchang|ch ang\nchao|ch ao\nche|ch e\nchen|ch en\ncheng|ch eng\nchi|ch i\nchong|ch ong\nchou|ch ou\nchu|ch u\nchua|ch ua\nchuai|ch uai\nchuan|ch uan\nchuang|ch uang\nchui|ch ui\nchun|ch un\nchuo|ch uo\nci|c i\ncong|c ong\ncou|c ou\ncu|c u\ncuan|c uan\ncui|c ui\ncun|c un\ncuo|c uo\nda|d a\ndai|d ai\ndan|d an\ndang|d ang\ndao|d ao\nde|d e\ndei|d ei\nden|d en\ndeng|d eng\ndi|d i\ndia|d ia\ndian|d ian\ndiao|d iao\ndie|d ie\nding|d ing\ndiu|d iu\ndong|d ong\ndou|d ou\ndu|d u\nduan|d uan\ndui|d ui\ndun|d un\nduo|d uo\ne|e\nei|ei\nen|en\neng|eng\ner|er\nfa|f a\nfan|f an\nfang|f ang\nfei|f ei\nfen|f en\nfeng|f eng\nfo|f o\nfou|f ou\nfu|f u\nga|g a\ngai|g ai\ngan|g an\ngang|g ang\ngao|g ao\nge|g e\ngei|g ei\ngen|g en\ngeng|g eng\ngong|g ong\ngou|g ou\ngu|g u\ngua|g ua\nguai|g uai\nguan|g uan\nguang|g uang\ngui|g ui\ngun|g un\nguo|g uo\nha|h a\nhai|h ai\nhan|h an\nhang|h ang\nhao|h ao\nhe|h e\nhei|h ei\nhen|h en\nheng|h eng\nhm|h m\nhng|h ng\nhong|h ong\nhou|h ou\nhu|h u\nhua|h ua\nhuai|h uai\nhuan|h uan\nhuang|h uang\nhui|h ui\nhun|h un\nhuo|h uo\nji|j i\njia|j ia\njian|j ian\njiang|j iang\njiao|j iao\njie|j ie\njin|j in\njing|j ing\njiong|j iong\njiu|j iu\nju|j v\njuan|j van\njue|j ve\njun|j vn\nka|k a\nkai|k ai\nkan|k an\nkang|k ang\nkao|k ao\nke|k e\nkei|k ei\nken|k en\nkeng|k eng\nkong|k ong\nkou|k ou\nku|k u\nkua|k ua\nkuai|k uai\nkuan|k uan\nkuang|k uang\nkui|k ui\nkun|k un\nkuo|k uo\nla|l a\nlai|l ai\nlan|l an\nlang|l ang\nlao|l ao\nle|l e\nlei|l ei\nleng|l eng\nli|l i\nlia|l ia\nlian|l ian\nliang|l iang\nliao|l iao\nlie|l ie\nlin|l in\nling|l ing\nliu|l iu\nlo|l o\nlong|l ong\nlou|l ou\nlu|l u\nluan|l uan\nlun|l un\nluo|l uo\nlv|l v\nlve|l ve\nm|m\nma|m a\nmai|m ai\nman|m an\nmang|m ang\nmao|m ao\nme|m e\nmei|m ei\nmen|m en\nmeng|m eng\nmi|m i\nmian|m ian\nmiao|m iao\nmie|m ie\nmin|m in\nming|m ing\nmiu|m iu\nmo|m o\nmou|m ou\nmu|m u\nn|n\nna|n a\nnai|n ai\nnan|n an\nnang|n ang\nnao|n ao\nne|n e\nnei|n ei\nnen|n en\nneng|n eng\nng|n g\nni|n i\nnian|n ian\nniang|n iang\nniao|n iao\nnie|n ie\nnin|n in\nning|n ing\nniu|n iu\nnong|n ong\nnou|n ou\nnu|n u\nnuan|n uan\nnun|n un\nnuo|n uo\nnv|n v\nnve|n ve\no|o\nou|ou\npa|p a\npai|p ai\npan|p an\npang|p ang\npao|p ao\npei|p ei\npen|p en\npeng|p eng\npi|p i\npian|p ian\npiao|p iao\npie|p ie\npin|p in\nping|p ing\npo|p o\npou|p ou\npu|p u\nqi|q i\nqia|q ia\nqian|q ian\nqiang|q iang\nqiao|q iao\nqie|q ie\nqin|q in\nqing|q ing\nqiong|q iong\nqiu|q iu\nqu|q v\nquan|q van\nque|q ve\nqun|q vn\nran|r an\nrang|r ang\nrao|r ao\nre|r e\nren|r en\nreng|r eng\nri|r i\nrong|r ong\nrou|r ou\nru|r u\nrua|r ua\nruan|r uan\nrui|r ui\nrun|r un\nruo|r uo\nsa|s a\nsai|s ai\nsan|s an\nsang|s ang\nsao|s ao\nse|s e\nsen|s en\nseng|s eng\nsha|sh a\nshai|sh ai\nshan|sh an\nshang|sh ang\nshao|sh ao\nshe|sh e\nshei|sh ei\nshen|sh en\nsheng|sh eng\nshi|sh i\nshou|sh ou\nshu|sh u\nshua|sh ua\nshuai|sh uai\nshuan|sh uan\nshuang|sh uang\nshui|sh ui\nshun|sh un\nshuo|sh uo\nsi|s i\nsong|s ong\nsou|s ou\nsu|s u\nsuan|s uan\nsui|s ui\nsun|s un\nsuo|s uo\nta|t a\ntai|t ai\ntan|t an\ntang|t ang\ntao|t ao\nte|t e\ntei|t ei\nteng|t eng\nti|t i\ntian|t ian\ntiao|t iao\ntie|t ie\nting|t ing\ntong|t ong\ntou|t ou\ntu|t u\ntuan|t uan\ntui|t ui\ntun|t un\ntuo|t uo\nwa|w a\nwai|w ai\nwan|w an\nwang|w ang\nwei|w ei\nwen|w en\nweng|w eng\nwo|w o\nwu|w u\nxi|x i\nxia|x ia\nxian|x ian\nxiang|x iang\nxiao|x iao\nxie|x ie\nxin|x in\nxing|x ing\nxiong|x iong\nxiu|x iu\nxu|x v\nxuan|x van\nxue|x ve\nxun|x vn\nya|y a\nyan|y an\nyang|y ang\nyao|y ao\nye|y e\nyi|y i\nyin|y in\nying|y ing\nyo|y o\nyong|y ong\nyou|y ou\nyu|y v\nyuan|y van\nyue|y ve\nyun|y vn\nza|z a\nzai|z ai\nzan|z an\nzang|z ang\nzao|z ao\nze|z e\nzei|z ei\nzen|z en\nzeng|z eng\nzha|zh a\nzhai|zh ai\nzhan|zh an\nzhang|zh ang\nzhao|zh ao\nzhe|zh e\nzhei|zh ei\nzhen|zh en\nzheng|zh eng\nzhi|zh i\nzhong|zh ong\nzhou|zh ou\nzhu|zh u\nzhua|zh ua\nzhuai|zh uai\nzhuan|zh uan\nzhuang|zh uang\nzhui|zh ui\nzhun|zh un\nzhuo|zh uo\nzi|z i\nzong|z ong\nzou|z ou\nzu|z u\nzuan|z uan\nzui|z ui\nzun|z un\nzuo|z uo"
  },
  {
    "path": "examples/opencpop/svs1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=opencpop \\\n        --rootdir=~/datasets/Opencpop/segments \\\n        --dumpdir=dump \\\n        --label-file=~/datasets/Opencpop/segments/transcriptions.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # Get feature(mel) extremum for diffusion stretch\n    echo \"Get feature(mel) extremum  ...\"\n    python3 ${BIN_DIR}/get_minmax.py \\\n        --metadata=dump/train/norm/metadata.jsonl \\\n        --speech-stretchs=dump/train/speech_stretchs.npy\nfi\n"
  },
  {
    "path": "examples/opencpop/svs1/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=diffsinger_opencpop \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_opencpop \\\n        --voc_config=pwgan_opencpop_ckpt_1.4.0/default.yaml \\\n        --voc_ckpt=pwgan_opencpop_ckpt_1.4.0/snapshot_iter_100000.pdz \\\n        --voc_stat=pwgan_opencpop_ckpt_1.4.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n\t--speech_stretchs=dump/train/speech_stretchs.npy\nfi\n\n"
  },
  {
    "path": "examples/opencpop/svs1/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=diffsinger_opencpop \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_opencpop \\\n        --voc_config=pwgan_opencpop_ckpt_1.4.0/default.yaml \\\n        --voc_ckpt=pwgan_opencpop_ckpt_1.4.0/snapshot_iter_100000.pdz \\\n        --voc_stat=pwgan_opencpop_ckpt_1.4.0/feats_stats.npy \\\n        --lang=sing \\\n        --text=${BIN_DIR}/../../assets/sentences_sing.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speech_stretchs=dump/train/speech_stretchs.npy \\\n        --pinyin_phone=local/pinyin_to_phone.txt\nfi\n\n# for more GAN Vocoders\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=diffsinger_opencpop \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_opencpop \\\n        --voc_config=hifigan_opencpop_ckpt_1.4.0/default.yaml \\\n        --voc_ckpt=hifigan_opencpop_ckpt_1.4.0/snapshot_iter_625000.pdz \\\n        --voc_stat=hifigan_opencpop_ckpt_1.4.0/feats_stats.npy \\\n        --lang=sing \\\n        --text=${BIN_DIR}/../../assets/sentences_sing.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speech_stretchs=dump/train/speech_stretchs.npy \\\n        --pinyin_phone=local/pinyin_to_phone.txt\n        \nfi\n"
  },
  {
    "path": "examples/opencpop/svs1/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --phones-dict=dump/phone_id_map.txt \\\n    --speech-stretchs=dump/train/speech_stretchs.npy\n"
  },
  {
    "path": "examples/opencpop/svs1/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=diffsinger\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/opencpop/svs1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_320000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n"
  },
  {
    "path": "examples/opencpop/voc1/README.md",
    "content": "# Parallel WaveGAN with Opencpop\nThis example contains code used to train a [parallel wavegan](http://arxiv.org/abs/1910.11480) model with [Mandarin singing corpus](https://wenet.org.cn/opencpop/).\n\n## Dataset\n### Download and Extract\nDownload Opencpop from it's [Official Website](https://wenet.org.cn/opencpop/download/) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/Opencpop`.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/Opencpop`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER]\n                [--run-benchmark RUN_BENCHMARK]\n                [--profiler_options PROFILER_OPTIONS]\n\nTrain a ParallelWaveGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       ParallelWaveGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n\nbenchmark:\n  arguments related to benchmark.\n\n  --batch-size BATCH_SIZE\n                        batch size.\n  --max-iter MAX_ITER   train max steps.\n  --run-benchmark RUN_BENCHMARK\n                        runing benchmark or not, if True, use the --batch-size\n                        and --max-iter.\n  --profiler_options PROFILER_OPTIONS\n                        The option of profiler, which should be in format\n                        \"key1=value1;key2=value2;key3=value3\".\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Models\nThe pretrained model can be downloaded here:\n- [pwgan_opencpop_ckpt_1.4.0](https://paddlespeech.cdn.bcebos.com/t2s/svs/opencpop/pwgan_opencpop_ckpt_1.4.0.zip)\n\n\nParallel WaveGAN checkpoint contains files listed below.\n\n```text\npwgan_opencpop_ckpt_1.4.0\n├── default.yaml                    # default config used to train parallel wavegan\n├── snapshot_iter_100000.pdz        # generator parameters of parallel wavegan\n└── feats_stats.npy                 # statistics used to normalize spectrogram when training parallel wavegan\n```\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/opencpop/voc1/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for Parallel WaveGAN.\n# Please make sure this is adjusted for the CSMSC dataset. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires 12 GB GPU memory and takes ~3 days on RTX TITAN.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 512              # FFT size (samples).\nn_shift: 128             # Hop size (samples). 12.5ms\nwin_length: 512         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 30                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 12000               # Maximum frequency in mel basis calculation. (Hz)\n\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Kernel size of dilated convolution.\n    layers: 30            # Number of residual block layers.\n    stacks: 3             # Number of stacks i.e., dilation cycles.\n    residual_channels: 64 # Number of channels in residual conv.\n    gate_channels: 128    # Number of channels in gated conv.\n    skip_channels: 64     # Number of channels in skip conv.\n    aux_channels: 80      # Number of channels for auxiliary feature conv.\n                          # Must be the same as num_mels.\n    aux_context_window: 2 # Context window size for auxiliary feature.\n                          # If set to 2, previous 2 and future 2 frames will be considered.\n    dropout: 0.0          # Dropout rate. 0.0 means no dropout applied.\n    bias: True            # use bias in residual blocks\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    use_causal_conv: False               # use causal conv in residual blocks and upsample layers\n    upsample_scales: [8, 4, 2, 2]     # Upsampling scales. Prodcut of these must be the same as hop size.\n    interpolate_mode: \"nearest\" # upsample net interpolate mode\n    freq_axis_kernel_size: 1 # upsamling net: convolution kernel size in frequencey axis\n    nonlinear_activation: null\n    nonlinear_activation_params: {}\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Number of output channels.\n    layers: 10            # Number of conv layers.\n    conv_channels: 64     # Number of chnn layers.\n    bias: True            # Whether to use bias parameter in conv.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear function after each conv.\n    nonlinear_activation_params:      # Nonlinear function parameters\n        negative_slope: 0.2           # Alpha in leakyrelu.\n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"         # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 4.0  # Loss balancing coefficient.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 8              # Batch size.\nbatch_max_steps: 25500     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 1             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-6        # Generator's epsilon.\n    weight_decay: 0.0      # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 0.0001  # Generator's learning rate.\n    step_size: 200000      # Generator's scheduler step size.\n    gamma: 0.5             # Generator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ngenerator_grad_norm: 10    # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-6            # Discriminator's epsilon.\n    weight_decay: 0.0          # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 0.00005     # Discriminator's learning rate.\n    step_size: 200000          # Discriminator's scheduler step size.\n    gamma: 0.5                 # Discriminator's scheduler gamma.\n                               # At each step size, lr will be multiplied by this parameter.\ndiscriminator_grad_norm: 1     # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 400000                 # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_save_intermediate_results: 4  # Number of results to be saved as intermediate results.\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/opencpop/voc1/local/dygraph_to_static.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../../dygraph_to_static.py \\\n    --type=voc \\\n    --voc=pwgan_opencpop \\\n    --voc_config=${config_path} \\\n    --voc_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --voc_stat=dump/train/feats_stats.npy \\\n    --inference_dir=exp/default/inference/\n"
  },
  {
    "path": "examples/opencpop/voc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../preprocess.py \\\n        --rootdir=~/datasets/Opencpop/segments/ \\\n        --dataset=opencpop \\\n        --dumpdir=dump \\\n        --dur-file=~/datasets/Opencpop/segments/transcriptions.txt \\\n        --config=${config_path} \\\n        --cut-sil=False \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy\nfi\n"
  },
  {
    "path": "examples/opencpop/voc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_100000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# dygraph to static\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/dygraph_to_static.sh  ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} pwgan_opencpop || exit -1\nfi\n"
  },
  {
    "path": "examples/opencpop/voc5/conf/default.yaml",
    "content": "# This is the configuration file for CSMSC dataset.\n# This configuration is based on HiFiGAN V1, which is an official configuration. \n# But I found that the optimizer setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 512              # FFT size (samples).\nn_shift: 128             # Hop size (samples). 12.5ms\nwin_length: 512         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 12000               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [8, 4, 2, 2]         # Upsampling scales.\n    upsample_kernel_sizes: [16, 8, 4, 4] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 512\n    hop_size: 128\n    win_length: 512\n    window: \"hann\"\n    num_mels: 80\n    fmin: 30\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 1              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 4                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/opencpop/voc5/conf/finetune.yaml",
    "content": "# This is the configuration file for CSMSC dataset.\n# This configuration is based on HiFiGAN V1, which is an official configuration. \n# But I found that the optimizer setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales is also modified from the original 256 shift setting.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 512              # FFT size (samples).\nn_shift: 128             # Hop size (samples). 12.5ms\nwin_length: 512         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 12000               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [8, 4, 2, 2]         # Upsampling scales.\n    upsample_kernel_sizes: [16, 8, 4, 4] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 512\n    hop_size: 128\n    win_length: 512\n    window: \"hann\"\n    num_mels: 80\n    fmin: 30\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\n#batch_size: 16              # Batch size.\nbatch_size: 1              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 1              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2600000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 4                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/opencpop/voc5/finetune.sh",
    "content": "#!/bin/bash\n\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${MAIN_ROOT}/paddlespeech/t2s/exps/diffsinger/gen_gta_mel.py \\\n        --diffsinger-config=diffsinger_opencpop_ckpt_1.4.0/default.yaml \\\n        --diffsinger-checkpoint=diffsinger_opencpop_ckpt_1.4.0/snapshot_iter_160000.pdz \\\n        --diffsinger-stat=diffsinger_opencpop_ckpt_1.4.0/speech_stats.npy \\\n        --diffsinger-stretch=diffsinger_opencpop_ckpt_1.4.0/speech_stretchs.npy \\\n        --dur-file=~/datasets/Opencpop/segments/transcriptions.txt \\\n        --output-dir=dump_finetune \\\n        --phones-dict=diffsinger_opencpop_ckpt_1.4.0/phone_id_map.txt \\\n        --dataset=opencpop \\\n        --rootdir=~/datasets/Opencpop/segments/\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${MAIN_ROOT}/utils/link_wav.py \\\n        --old-dump-dir=dump \\\n        --dump-dir=dump_finetune\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    cp dump/train/feats_stats.npy dump_finetune/train/\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/train/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/train/norm \\\n        --stats=dump_finetune/train/feats_stats.npy\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/dev/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/dev/norm \\\n        --stats=dump_finetune/train/feats_stats.npy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump_finetune/test/raw/metadata.jsonl \\\n        --dumpdir=dump_finetune/test/norm \\\n        --stats=dump_finetune/train/feats_stats.npy\nfi\n\n# create finetune env\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"create finetune env\"\n    python3 local/prepare_env.py \\\n        --pretrained_model_dir=exp/default/checkpoints/ \\\n        --output_dir=exp/finetune/\nfi \n\n# finetune\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} \\\n    FLAGS_cudnn_exhaustive_search=true \\\n    FLAGS_conv_workspace_size_limit=4000 \\\n    python ${BIN_DIR}/train.py \\\n        --train-metadata=dump_finetune/train/norm/metadata.jsonl \\\n        --dev-metadata=dump_finetune/dev/norm/metadata.jsonl \\\n        --config=conf/finetune.yaml \\\n        --output-dir=exp/finetune \\\n        --ngpu=1\nfi \n"
  },
  {
    "path": "examples/opencpop/voc5/local/dygraph_to_static.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../../dygraph_to_static.py \\\n    --type=voc \\\n    --voc=hifigan_opencpop \\\n    --voc_config=${config_path} \\\n    --voc_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n    --voc_stat=dump/train/feats_stats.npy \\\n    --inference_dir=exp/default/inference/\n"
  },
  {
    "path": "examples/opencpop/voc5/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_2500000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# dygraph to static\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/dygraph_to_static.sh  ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\n# PTQ_static\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/PTQ_static.sh  ${train_output_path} hifigan_opencpop || exit -1\nfi\n"
  },
  {
    "path": "examples/other/augmentation/augmentation.json",
    "content": "[\n  {\n    \"type\": \"noise\",\n    \"params\": {\n      \"min_snr_dB\": 40,\n      \"max_snr_dB\": 50,\n      \"noise_manifest_path\": \"datasets/manifest.noise\"\n    },\n    \"prob\": 0.6\n  },\n  {\n    \"type\": \"impulse\",\n    \"params\": {\n      \"impulse_manifest_path\": \"datasets/manifest.impulse\"\n    },\n    \"prob\": 0.5\n  },\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.95,\n      \"max_speed_rate\": 1.05,\n      \"num_rates\": 3\n    },\n    \"prob\": 0.5\n  },\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"volume\",\n    \"params\": {\n      \"min_gain_dBFS\": -10,\n      \"max_gain_dBFS\": 10\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"bayesian_normal\",\n    \"params\": {\n      \"target_db\": -20,\n      \"prior_db\": -20,\n      \"prior_samples\": 100\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 80,\n      \"warp_mode\": \"PIL\",\n      \"F\": 10,\n      \"n_freq_masks\": 2,\n      \"T\": 50,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": false\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/other/cc-cedict/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "examples/other/cc-cedict/README.md",
    "content": "# [CC-CEDICT](https://cc-cedict.org/wiki/)\n\nWhat is CC-CEDICT?\nCC-CEDICT is a continuation of the CEDICT project.\nThe objective of the CEDICT project was to create an online, downloadable (as opposed to searchable-only) public-domain Chinese-English dictionary.\nCEDICT was started by Paul Andrew Denisowski in October 1997.\nFor the most part, the project is modeled on Jim Breen's highly successful EDICT (Japanese-English dictionary) project and is intended to be a collaborative effort,\nwith users providing entries and corrections to the main file.\n\n\n## Parse CC-CEDICT to Json format\n\n1. Parse to Json\n\n```\nrun.sh\n```\n\n2. Result\n\n```\nexp/\n|-- cedict\n`-- cedict.json\n\n0 directories, 2 files\n```\n\n```\n4c4bffc84e24467fe1b2ea9ba37ed6b6  exp/cedict\n3adf504dacd13886f88cc9fe3b37c75d  exp/cedict.json\n```\n\n```\n==> exp/cedict <==\n# CC-CEDICT\n# Community maintained free Chinese-English dictionary.\n#\n# Published by MDBG\n#\n# License:\n# Creative Commons Attribution-ShareAlike 4.0 International License\n# https://creativecommons.org/licenses/by-sa/4.0/\n#\n# Referenced works:\n\n==> exp/cedict.json <==\n{\"traditional\": \"2019\\u51a0\\u72c0\\u75c5\\u6bd2\\u75c5\", \"simplified\": \"2019\\u51a0\\u72b6\\u75c5\\u6bd2\\u75c5\", \"pinyin\": \"er4 ling2 yi1 jiu3 guan1 zhuang4 bing4 du2 bing4\", \"english\": \"COVID-19, the coronavirus disease identified in 2019\"}\n{\"traditional\": \"21\\u4e09\\u9ad4\\u7d9c\\u5408\\u75c7\", \"simplified\": \"21\\u4e09\\u4f53\\u7efc\\u5408\\u75c7\", \"pinyin\": \"er4 shi2 yi1 san1 ti3 zong1 he2 zheng4\", \"english\": \"trisomy\"}\n{\"traditional\": \"3C\", \"simplified\": \"3C\", \"pinyin\": \"san1 C\", \"english\": \"abbr. for computers, communications, and consumer electronics\"}\n{\"traditional\": \"3P\", \"simplified\": \"3P\", \"pinyin\": \"san1 P\", \"english\": \"(slang) threesome\"}\n{\"traditional\": \"3Q\", \"simplified\": \"3Q\", \"pinyin\": \"san1 Q\", \"english\": \"(Internet slang) thank you (loanword)\"}\n{\"traditional\": \"421\", \"simplified\": \"421\", \"pinyin\": \"si4 er4 yi1\", \"english\": \"four grandparents, two parents and an only child\"}\n{\"traditional\": \"502\\u81a0\", \"simplified\": \"502\\u80f6\", \"pinyin\": \"wu3 ling2 er4 jiao1\", \"english\": \"cyanoacrylate glue\"}\n{\"traditional\": \"88\", \"simplified\": \"88\", \"pinyin\": \"ba1 ba1\", \"english\": \"(Internet slang) bye-bye (alternative for \\u62dc\\u62dc[bai2 bai2])\"}\n{\"traditional\": \"996\", \"simplified\": \"996\", \"pinyin\": \"jiu3 jiu3 liu4\", \"english\": \"9am-9pm, six days a week (work schedule)\"}\n{\"traditional\": \"A\", \"simplified\": \"A\", \"pinyin\": \"A\", \"english\": \"(slang) (Tw) to steal\"}\n```\n"
  },
  {
    "path": "examples/other/cc-cedict/local/parser.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# https://github.com/rubber-duck-dragon/rubber-duck-dragon.github.io/blob/master/cc-cedict_parser/parser.py\n#A parser for the CC-Cedict. Convert the Chinese-English dictionary into a list of python dictionaries with \"traditional\",\"simplified\", \"pinyin\", and \"english\" keys.\n#Make sure that the cedict_ts.u8 file is in the same folder as this file, and that the name matches the file name on line 13.\n#Before starting, open the CEDICT text file and delete the copyright information at the top. Otherwise the program will try to parse it and you will get an error message.\n#Characters that are commonly used as surnames have two entries in CC-CEDICT. This program will remove the surname entry if there is another entry for the character. If you want to include the surnames, simply delete lines 59 and 60.\n#This code was written by Franki Allegra in February 2020.\nimport json\nimport sys\n\n# usage: bin ccedict dump.json\n\nwith open(sys.argv[1], 'rt') as file:\n    text = file.read()\n    lines = text.split('\\n')\n    dict_lines = list(lines)\n\n    def parse_line(line):\n        parsed = {}\n        if line == '':\n            dict_lines.remove(line)\n            return 0\n        if line.startswith('#'):\n            return 0\n        if line.startswith('%'):\n            return 0\n        line = line.rstrip('/')\n        line = line.split('/')\n        if len(line) <= 1:\n            return 0\n        english = line[1]\n        char_and_pinyin = line[0].split('[')\n        characters = char_and_pinyin[0]\n        characters = characters.split()\n        traditional = characters[0]\n        simplified = characters[1]\n        pinyin = char_and_pinyin[1]\n        pinyin = pinyin.rstrip()\n        pinyin = pinyin.rstrip(\"]\")\n        parsed['traditional'] = traditional\n        parsed['simplified'] = simplified\n        parsed['pinyin'] = pinyin\n        parsed['english'] = english\n        list_of_dicts.append(parsed)\n\n    def remove_surnames():\n        for x in range(len(list_of_dicts) - 1, -1, -1):\n            if \"surname \" in list_of_dicts[x]['english']:\n                if list_of_dicts[x]['traditional'] == list_of_dicts[x + 1][\n                        'traditional']:\n                    list_of_dicts.pop(x)\n\n    def main():\n\n        #make each line into a dictionary\n        print(\"Parsing dictionary . . .\")\n        for line in dict_lines:\n            parse_line(line)\n\n        #remove entries for surnames from the data (optional):\n        print(\"Removing Surnames . . .\")\n        remove_surnames()\n\n        print(\"Saving to database (this may take a few minutes) . . .\")\n        with open(sys.argv[2], 'wt') as fout:\n            for one_dict in list_of_dicts:\n                json_str = json.dumps(one_dict)\n                fout.write(json_str + \"\\n\")\n        print('Done!')\n\n\nlist_of_dicts = []\nparsed_dict = main()\n"
  },
  {
    "path": "examples/other/cc-cedict/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=/usr/local/lib/:${LD_LIBRARY_PATH}\n"
  },
  {
    "path": "examples/other/cc-cedict/run.sh",
    "content": "#!/bin/bash\n\n# CC-CEDICT download: https://www.mdbg.net/chinese/dictionary?page=cc-cedict\n# The word dictionary of this website is based on CC-CEDICT.\n# CC-CEDICT is a continuation of the CEDICT project started by Paul Denisowski in 1997 with the\n# aim to provide a complete downloadable Chinese to English dictionary with pronunciation in pinyin for the Chinese characters.\n# This website allows you to easily add new entries or correct existing entries in CC-CEDICT.\n# Submitted entries will be checked and processed frequently and released for download in CEDICT format on this page.\n\nset -e\nsource path.sh\n\nstage=-1\nstop_stage=100\n\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit -1\n\n\ncedict_url=https://www.mdbg.net/chinese/export/cedict/cedict_1_0_ts_utf-8_mdbg.zip\ncedict=cedict_1_0_ts_utf-8_mdbg.zip\n\nmkdir -p data\n\nif [ $stage -le -1 ] && [ $stop_stage -ge -1 ];then\n    test -f data/${cedict} || wget -O data/${cedict} ${cedict_url}\n    pushd data\n    unzip ${cedict}\n    popd\n\nfi\n\nmkdir -p exp\n\nif [ $stage -le 0 ] && [ $stop_stage -ge 0 ];then\n    cp data/cedict_ts.u8 exp/cedict\n    python3 local/parser.py exp/cedict exp/cedict.json\nfi\n\n"
  },
  {
    "path": "examples/other/g2p/README.md",
    "content": "# G2P\nFor g2p, we use BZNSYP's phone label as the ground truth and we delete silence tokens in labels and predicted phones.\n\nYou should Download BZNSYP from its [Official Website](https://test.data-baker.com/data/index/source) and extract it. Assume the path to the dataset is `~/datasets/BZNSYP`.\n\nWe use `WER` as an evaluation criterion.\n\n# Start\nRun the command below to get the results of the test.\n\n```bash\ncd ../../../tools\nbash extras/install_sclite.sh\ncd -\n./run.sh\n```\n\nThe `avg WER` of g2p is: 0.024075726733983775\n\n```text\n     ,--------------------------------------------------------------------.\n     |                         ./exp/g2p/text.g2p                         |\n     |--------------------------------------------------------------------|\n     | SPKR   | # Snt    # Wrd  | Corr    Sub    Del    Ins    Err  S.Err |\n     | Sum/Avg|  9996   299181  | 97.6    2.4    0.0    0.0    2.4   49.0 |\n     `--------------------------------------------------------------------'\n```\n"
  },
  {
    "path": "examples/other/g2p/compare_badcase.py",
    "content": "# -*- encoding:utf-8 -*-\nimport re\nimport sys\n'''\n@arthur: david_95\n\nAssum you executed g2p test twice, the WER rate have some gap, you would like to see what sentences error cause your rate up.\nso you may get test result ( exp/g2p )into two directories, as exp/prefolder and exp/curfolder\nrun this program as  \"python compare_badcase.py prefolder curfolder\"\nthen you will get diffrences between two run, uuid, phonetics, chinese samples\n\nexamples: python compare_badcase.py  exp/g2p_laotouzi  exp/g2p\nin this example:  exp/g2p_laotouzi  and  exp/g2p  are two folders with two g2p tests result\n\n'''\n\n\ndef compare(prefolder, curfolder):\n    '''\n    compare file of text.g2p.pra in two folders\n    result P1 will be prefolder ; P2 will be curfolder, just about the sequence you input in argvs\n    '''\n\n    linecnt = 0\n    pre_block = []\n    cur_block = []\n    zh_lines = []\n    with open(prefolder + \"/text.g2p.pra\", \"r\") as pre_file, open(\n            curfolder + \"/text.g2p.pra\", \"r\") as cur_file:\n        for pre_line, cur_line in zip(pre_file, cur_file):\n            linecnt += 1\n\n            if linecnt < 11:  #skip non-data head in files\n                continue\n            else:\n                pre_block.append(pre_line.strip())\n                cur_block.append(cur_line.strip())\n                if pre_line.strip().startswith(\n                        \"Eval:\") and pre_line.strip() != cur_line.strip():\n                    uuid = pre_block[-5].replace(\"id: (baker_\", \"\").replace(\")\",\n                                                                            \"\")\n                    with open(\"data/g2p/text\", 'r') as txt:\n                        conlines = txt.readlines()\n\n                        for line in conlines:\n                            if line.strip().startswith(uuid.strip()):\n                                print(line)\n                                zh_lines.append(re.sub(r\"#[1234]\", \"\", line))\n                                break\n\n                    print(\"*\" + cur_block[-3])  # ref\n                    print(\"P1 \" + pre_block[-2])\n                    print(\"P2 \" + cur_block[-2])\n                    print(\"P1 \" + pre_block[-1])\n                    print(\"P2 \" + cur_block[-1] + \"\\n\\n\")\n                    pre_block = []\n                    cur_block = []\n\n    print(\"\\n\")\n    print(str.join(\"\\n\", zh_lines))\n\n\nif __name__ == '__main__':\n    assert len(\n        sys.argv) == 3, \"Usage: python compare_badcase.py %prefolder %curfolder\"\n    compare(sys.argv[1], sys.argv[2])\n"
  },
  {
    "path": "examples/other/g2p/get_g2p_data.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom collections import defaultdict\nfrom pathlib import Path\n\nfrom praatio import textgrid\n\n\ndef get_baker_data(root_dir):\n    alignment_files = sorted(\n        list((root_dir / \"PhoneLabeling\").rglob(\"*.interval\")))\n    text_file = root_dir / \"ProsodyLabeling/000001-010000.txt\"\n    text_file = Path(text_file).expanduser()\n    # filter out several files that have errors in annotation\n    exclude = {'000611', '000662', '002365', '005107'}\n    alignment_files = [f for f in alignment_files if f.stem not in exclude]\n    data_dict = defaultdict(dict)\n    for alignment_fp in alignment_files:\n        alignment = textgrid.openTextgrid(\n            alignment_fp, includeEmptyIntervals=True)\n        # only with baker's annotation\n        utt_id = alignment.tierNameList[0].split(\".\")[0]\n        intervals = alignment.getTier(alignment.tierNameList[0]).entries\n        phones = []\n        for interval in intervals:\n            label = interval.label\n            phones.append(label)\n        data_dict[utt_id][\"phones\"] = phones\n    for line in open(text_file, \"r\"):\n        if line.startswith(\"0\"):\n            utt_id, raw_text = line.strip().split()\n            if utt_id in data_dict:\n                data_dict[utt_id]['text'] = raw_text\n        else:\n            pinyin = line.strip().split()\n            if utt_id in data_dict:\n                data_dict[utt_id]['pinyin'] = pinyin\n    return data_dict\n\n\ndef get_g2p_phones(data_dict, frontend):\n    for utt_id in data_dict:\n        g2p_phones = frontend.get_phonemes(data_dict[utt_id]['text'])\n        data_dict[utt_id][\"g2p_phones\"] = g2p_phones\n    return data_dict\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"g2p example.\")\n    parser.add_argument(\n        \"--root-dir\",\n        default=None,\n        type=str,\n        help=\"directory to baker dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        default=\"data/g2p\",\n        type=str,\n        help=\"directory to output.\")\n\n    args = parser.parse_args()\n    root_dir = Path(args.root_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    assert root_dir.is_dir()\n    data_dict = get_baker_data(root_dir)\n    raw_path = output_dir / \"text\"\n    ref_path = output_dir / \"text.ref\"\n    wf_raw = open(raw_path, \"w\")\n    wf_ref = open(ref_path, \"w\")\n    for utt_id in data_dict:\n        wf_raw.write(utt_id + \" \" + data_dict[utt_id]['text'] + \"\\n\")\n        wf_ref.write(utt_id + \" \" + \" \".join(data_dict[utt_id]['phones']) +\n                     \"\\n\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/g2p/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n"
  },
  {
    "path": "examples/other/g2p/run.sh",
    "content": "#!/bin/bash\n\nsource path.sh\nUSE_SCLITE=true\n\n# test g2p\nif [ ! -d ~/datasets/BZNSYP ];then\n    echo \"Please download BZNSYP dataset\"\n    exit\nfi\necho \"Start get g2p test data ...\"\npython3 get_g2p_data.py --root-dir=~/datasets/BZNSYP --output-dir=data/g2p\necho \"Start test g2p ...\"\npython3 test_g2p.py --input-dir=data/g2p --output-dir=exp/g2p\n\n# whether use sclite to get more detail information of WER\nif [ \"$USE_SCLITE\" = true ];then\n    echo \"Start sclite g2p ...\"\n    ${MAIN_ROOT}/tools/extras/sctk/bin/sclite -i wsj -r ./exp/g2p/text.ref.clean trn -h ./exp/g2p/text.g2p trn -e utf-8 -o all\nfi\n"
  },
  {
    "path": "examples/other/g2p/test_g2p.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport re\nfrom pathlib import Path\n\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend as zhFrontend\nfrom paddlespeech.t2s.utils.error_rate import word_errors\n\nSILENCE_TOKENS = {\"sp\", \"sil\", \"sp1\", \"spl\"}\n\n\ndef text_cleaner(raw_text):\n    text = re.sub('#[1-4]|“|”|（|）', '', raw_text)\n    text = text.replace(\"…。\", \"。\")\n    text = re.sub('：|；|——|……|、|…|—', '，', text)\n    return text\n\n\ndef get_avg_wer(raw_dict, ref_dict, frontend, output_dir):\n    edit_distances = []\n    ref_lens = []\n    wf_g2p = open(output_dir / \"text.g2p\", \"w\")\n    wf_ref = open(output_dir / \"text.ref.clean\", \"w\")\n    for utt_id in raw_dict:\n        if utt_id not in ref_dict:\n            continue\n        raw_text = raw_dict[utt_id]\n        text = text_cleaner(raw_text)\n        g2p_phones = frontend.get_phonemes(text)\n        g2p_phones = sum(g2p_phones, [])\n        gt_phones = ref_dict[utt_id].split(\" \")\n        # delete silence tokens in predicted phones and ground truth phones\n        g2p_phones = [phn for phn in g2p_phones if phn not in SILENCE_TOKENS]\n        gt_phones = [phn for phn in gt_phones if phn not in SILENCE_TOKENS]\n        gt_phones = \" \".join(gt_phones)\n        g2p_phones = \" \".join(g2p_phones)\n        wf_ref.write(gt_phones + \"(baker_\" + utt_id + \")\" + \"\\n\")\n        wf_g2p.write(g2p_phones + \"(baker_\" + utt_id + \")\" + \"\\n\")\n        edit_distance, ref_len = word_errors(gt_phones, g2p_phones)\n        edit_distances.append(edit_distance)\n        ref_lens.append(ref_len)\n\n    return sum(edit_distances) / sum(ref_lens)\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"g2p example.\")\n    parser.add_argument(\n        \"--input-dir\",\n        default=\"data/g2p\",\n        type=str,\n        help=\"directory to preprocessed test data.\")\n    parser.add_argument(\n        \"--output-dir\",\n        default=\"exp/g2p\",\n        type=str,\n        help=\"directory to save g2p results.\")\n\n    args = parser.parse_args()\n    input_dir = Path(args.input_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    assert input_dir.is_dir()\n    raw_dict, ref_dict = dict(), dict()\n    raw_path = input_dir / \"text\"\n    ref_path = input_dir / \"text.ref\"\n\n    with open(raw_path, \"r\") as rf:\n        for line in rf:\n            line = line.strip()\n            line_list = line.split(\" \")\n            utt_id, raw_text = line_list[0], \" \".join(line_list[1:])\n            raw_dict[utt_id] = raw_text\n    with open(ref_path, \"r\") as rf:\n        for line in rf:\n            line = line.strip()\n            line_list = line.split(\" \")\n            utt_id, phones = line_list[0], \" \".join(line_list[1:])\n            ref_dict[utt_id] = phones\n    frontend = zhFrontend()\n    avg_wer = get_avg_wer(raw_dict, ref_dict, frontend, output_dir)\n    print(\"The avg WER of g2p is:\", avg_wer)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/ge2e/README.md",
    "content": "# Speaker Encoder\nThis experiment trains a speaker encoder with speaker verification as to its task. It is done as a part of the experiment of transfer learning from speaker verification to multispeaker text-to-speech synthesis, which can be found at [examples/aishell3/vc0](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/vc0). The trained speaker encoder is used to extract utterance embeddings from utterances.\n## Model\nThe model used in this experiment is the speaker encoder with text-independent speaker verification task in [GENERALIZED END-TO-END LOSS FOR SPEAKER VERIFICATION](https://arxiv.org/pdf/1710.10467.pdf). GE2E-softmax loss is used.\n\n## Download Datasets\nCurrently supported datasets are  Librispeech-other-500, VoxCeleb, VoxCeleb2,ai-datatang-200zh, magicdata, which can be downloaded from the corresponding webpage.\n\n1. Librispeech/train-other-500\n   An English multispeaker dataset，[URL](https://www.openslr.org/resources/12/train-other-500.tar.gz)，only the `train-other-500` subset is used.\n2. VoxCeleb1\n   An English multispeaker dataset，[URL](https://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1.html), Audio Files from Dev A to Dev D should be downloaded, combined, and extracted.\n3. VoxCeleb2\n   An English multispeaker dataset，[URL](https://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1.html), Audio Files from Dev A to Dev H should be downloaded, combined, and extracted.\n4. Aidatatang-200zh\n   A Mandarin Chinese multispeaker dataset ，[URL](https://www.openslr.org/62/).\n5. magicdata\n   A Mandarin Chinese multispeaker dataset ，[URL](https://www.openslr.org/68/).\n\nIf you want to use other datasets, you can also download and preprocess them as long as they meet the requirements described below.\n\n## Get Started\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n`./local/preprocess.sh` calls `${BIN_DIR}/preprocess.py`.\n```bash\n./local/preprocess.sh ${datasets_root} ${preprocess_path} ${dataset_names}\n```\nAssume datasets_root is `~/datasets/GE2E`, and it has the following structure（We only use `train-other-500` for simplicity）:\n```Text\nGE2E\n├── LibriSpeech\n└── (other datasets)\n```\nMultispeaker datasets are used as training data, though the transcriptions are not used. To enlarge the amount of data used for training, several multispeaker datasets are combined. The preprocessed datasets are organized in a file structure described below. The mel spectrogram of each utterance is saved in `.npy` format. The dataset is 2-stratified (speaker-utterance). Since multiple datasets are combined, to avoid conflict in speaker id, the dataset name is prepended to the speaker ids.\n\n```text\ndataset_root\n├── dataset01_speaker01/\n│   ├── utterance01.npy\n│   ├── utterance02.npy\n│   └── utterance03.npy\n├── dataset01_speaker02/\n│   ├── utterance01.npy\n│   ├── utterance02.npy\n│   └── utterance03.npy\n├── dataset02_speaker01/\n│   ├── utterance01.npy\n│   ├── utterance02.npy\n│   └── utterance03.npy\n└── dataset02_speaker02/\n    ├── utterance01.npy\n    ├── utterance02.npy\n    └── utterance03.npy\n```\nIn `${BIN_DIR}/preprocess.py`:\n1. `--datasets_root` is the directory that contains several extracted dataset\n2.  `--output_dir` is the directory to save the preprocessed dataset\n3.  `--dataset_names` is the dataset to preprocess. If there are multiple datasets in `--datasets_root` to preprocess, the names can be joined with a comma. Currently supported dataset names are  librispeech_other, voxceleb1, voxceleb2, aidatatang_200zh, and magicdata.\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${preprocess_path} ${train_output_path}\n```\nIn `${BIN_DIR}/train.py`:\n1. `--data` is the path to the preprocessed dataset.\n2. `--output` is the directory to save results，usually a subdirectory of `runs`. It contains visualdl log files, text log files, config files, and a `checkpoints` directory, which contains parameter files and optimizer state files. If `--output` already has some training results in it, the most recent parameter file and optimizer state file are loaded before training.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `CUDA_VISIBLE_DEVICES` can be used to specify visible devices with cuda.\n\nOther options are described below.\n\n- `--config` is a `.yaml` config file used to override the default config(which is coded in `config.py`).\n- `--opts` is a command-line option to further override config files. It should be the last command-line options passed with multiple key-value pairs separated by spaces.\n- `--checkpoint_path` specifies the checkpoint to load before training, extension is not included. A parameter file ( `.pdparams`) and an optimizer state file ( `.pdopt`) with the same name is used. This option has a higher priority than auto-resuming from the `--output` directory.\n\n###  Inferencing\nWhen training is done, run the command below to generate utterance embedding for each utterance in a dataset.\n`./local/inference.sh` calls `${BIN_DIR}/inference.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${infer_input} ${infer_output} ${train_output_path} ${ckpt_name}\n```\nIn `${BIN_DIR}/inference.py`:\n1. `--input` is the path of the dataset used for inference.\n2. `--output` is the directory to save the processed results. It has the same file structure as the input dataset. Each utterance in the dataset has a corresponding utterance embedding file in the `*.npy` format.\n3. `--checkpoint_path` is the path of the checkpoint to use, extension not included.\n4. `--pattern` is the wildcard pattern to filter audio files for inference, defaults to `*.wav`.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nThe pretrained model is first trained to 1560k steps at Librispeech-other-500 and voxceleb1. Then trained at aidatatang_200h and magic_data to 3000k steps.\n\nDownload URL [ge2e_ckpt_0.3.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ge2e/ge2e_ckpt_0.3.zip).\n\n## References\n\n1. [Generalized End-to-end Loss for Speaker Verification](https://arxiv.org/pdf/1710.10467.pdf)\n2. [Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/pdf/1806.04558.pdf)\n"
  },
  {
    "path": "examples/other/ge2e/local/inference.sh",
    "content": "#!/bin/bash\n\n#generate utterance embedding for each utterance in a dataset.\ninfer_input=$1\ninfer_output=$2\ntrain_output_path=$3\nckpt_name=$4\n\npython3 ${BIN_DIR}/inference.py \\\n    --input=${infer_input} \\\n    --output=${infer_output} \\\n    --checkpoint_path=${train_output_path}/checkpoints/${ckpt_name} \\\n    --ngpu=1\n\n"
  },
  {
    "path": "examples/other/ge2e/local/preprocess.sh",
    "content": "#!/bin/bash\ndatasets_root=$1\npreprocess_path=$2\ndataset_names=$3\n\npython3 ${BIN_DIR}/preprocess.py \\\n    --datasets_root=${datasets_root} \\\n    --output_dir=${preprocess_path} \\\n    --dataset_names=${dataset_names}"
  },
  {
    "path": "examples/other/ge2e/local/train.sh",
    "content": "#!/bin/bash\n\npreprocess_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --data=${preprocess_path} \\\n    --output=${train_output_path} \\\n    --ngpu=1"
  },
  {
    "path": "examples/other/ge2e/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=ge2e\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/vector/exps/${MODEL}\n"
  },
  {
    "path": "examples/other/ge2e/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\ndatasets_root=~/datasets/GE2E\npreprocess_path=dump\ndataset_names=librispeech_other\ntrain_output_path=output\ninfer_input=infer_input\ninfer_output=infer_output\nckpt_name=step-10000\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${datasets_root} ${preprocess_path} ${dataset_names} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${preprocess_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${infer_input} ${infer_output} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/other/mfa/README.md",
    "content": "# Use Montreal-Forced-Aligner\nHere is an example to use [MFA1.x](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner).\nRun the following script to get started, for more detail, please see `run.sh`.\n```bash\n./run.sh\n```\n# Rhythm tags for MFA\nIf you want to get rhythm tags with duration through MFA tool, you may add flag `--rhy-with-duration` in the first two commands in `run.sh`\nNote that only CSMSC dataset is supported so far, and we replace `#` with `sp` in rhythm tags for MFA.\n\n# MFA for Cantonese language\nFirst, go download these datasets [Guangzhou_Cantonese_Scripted_Speech_Corpus_Daily_Use_Sentence](https://magichub.com/datasets/guangzhou-cantonese-scripted-speech-corpus-daily-use-sentence/) and [Guangzhou_Cantonese_Scripted_Speech_Corpus_in_Vehicle](https://magichub.com/datasets/guangzhou-cantonese-scripted-speech-corpus-in-the-vehicle/) under `~/datasets/`.\nThen,\n```bash\n./run_canton.sh\n```\n"
  },
  {
    "path": "examples/other/mfa/local/detect_oov.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nfrom collections import OrderedDict\nfrom pathlib import Path\n\n\ndef detect_oov(corpus_dir, lexicon_path, transcription_pattern=\"*.lab\"):\n    corpus_dir = Path(corpus_dir)\n\n    lexicon = OrderedDict()\n    with open(lexicon_path, 'rt') as f:\n        for line in f:\n            syllable, phonemes = line.split(maxsplit=1)\n            lexicon[syllable] = phonemes\n\n    for fp in corpus_dir.glob(transcription_pattern):\n        syllables = fp.read_text().strip().split()\n        for s in syllables:\n            if s not in lexicon:\n                logging.warning(f\"{fp.relative_to(corpus_dir)} has OOV {s} .\")\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"detect oov in a corpus given a lexicon\")\n    parser.add_argument(\n        \"corpus_dir\", type=str, help=\"corpus dir for MFA alignment.\")\n    parser.add_argument(\"lexicon_path\", type=str, help=\"dictionary to use.\")\n    parser.add_argument(\n        \"--pattern\", type=str, default=\"*.lab\", help=\"dictionary to use.\")\n    args = parser.parse_args()\n    print(args)\n\n    detect_oov(args.corpus_dir, args.lexicon_path, args.pattern)\n"
  },
  {
    "path": "examples/other/mfa/local/generate_canton_lexicon_wavlabs.py",
    "content": "import argparse\nimport os\nimport re\nimport shutil\n\nimport ToJyutping\n\n\ndef check(str):\n    my_re = re.compile(r'[A-Za-z]', re.S)\n    res = re.findall(my_re, str)\n    if len(res):\n        return True\n    else:\n        return False\n\n\nINITIALS = [\n    'aa', 'aai', 'aak', 'aap', 'aat', 'aau', 'ai', 'au', 'ap', 'at', 'ak', 'a',\n    'p', 'b', 'e', 'ts', 't', 'dz', 'd', 'kw', 'k', 'gw', 'g', 'f', 'h', 'l',\n    'm', 'ng', 'n', 's', 'y', 'w', 'c', 'z', 'j', 'ong', 'on', 'ou', 'oi', 'ok',\n    'o', 'uk', 'ung'\n]\n\n\ndef get_lines(canton):\n    for init in INITIALS:\n        if canton.startswith(init):\n            c, v = canton[:len(init)], canton[len(init):]\n            return canton + ' ' + c + ' ' + v\n    return canton + ' ' + canton\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Generate lexicon for Cantonese pinyin to phoneme for MFA\")\n    parser.add_argument(\n        \"--output_lexicon\", type=str, help=\"Path to save lexicon.\")\n    parser.add_argument(\n        \"--output_wavlabs\",\n        type=str,\n        help=\"Path of wavs and labs for MFA training.\")\n    parser.add_argument(\n        \"--inputs\", type=str, nargs=\"+\", help=\"Path to the cantonese datasets.\")\n    args = parser.parse_args()\n\n    os.mkdir(args.output_wavlabs)\n\n    utterance_info = []\n    all_canton = []\n    for input_ in args.inputs:\n        utt = \"UTTRANSINFO.txt\" if \"Guangzhou_Cantonese_Scripted_Speech_Corpus_Daily_Use_Sentence\" in input_ else \"UTTERANCEINFO.txt\"\n        input_utttxt = os.path.join(input_, utt)\n\n        with open(input_utttxt, 'r') as f:\n            utterance_info = f.readlines()[1:]\n\n        for utterance_line in utterance_info:\n            _, wav_name, spk, _, text = utterance_line.split('\\t')\n            text = text.strip().replace(' ', '')\n            # check the characters and drop the short text.\n            if not check(text) and len(text) > 2:\n                source_path = os.path.join(input_, 'WAV', spk, wav_name)\n                out_spk_path = os.path.join(args.output_wavlabs, spk)\n                os.makedirs(out_spk_path, exist_ok=True)\n                target_path = os.path.join(out_spk_path, wav_name)\n\n                shutil.copy(source_path, target_path)\n\n                lab_name = wav_name.split('.')[0] + '.lab'\n                lab_target_path = os.path.join(out_spk_path, lab_name)\n                canton_list = ToJyutping.get_jyutping_text(text)\n                with open(lab_target_path, 'w') as f:\n                    f.write(canton_list)\n\n                canton_list = canton_list.split(' ')\n                all_canton.extend(canton_list)\n    all_canton = sorted(list(set(all_canton)))\n\n    with open(args.output_lexicon, 'w') as f:\n        for canton in all_canton:\n            f.write(get_lines(canton) + '\\n')\n"
  },
  {
    "path": "examples/other/mfa/local/generate_lexicon.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generate lexicon and symbols for Mandarin Chinese phonology.\nThe lexicon is used for Montreal Force Aligner.\n\nNote that syllables are used as word in this lexicon. Since syllables rather \nthan words are used in transcriptions produced by `reorganize_baker.py`.\n\nWe make this choice to better leverage other software for chinese text to \npinyin tools like pypinyin. This is the convention for G2P in Chinese.\n\"\"\"\nimport argparse\nimport re\nfrom collections import OrderedDict\n\nINITIALS = [\n    'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'zh', 'ch', 'sh',\n    'r', 'z', 'c', 's', 'j', 'q', 'x'\n]\n\nFINALS = [\n    'a', 'ai', 'ao', 'an', 'ang', 'e', 'er', 'ei', 'en', 'eng', 'o', 'ou',\n    'ong', 'ii', 'iii', 'i', 'ia', 'iao', 'ian', 'iang', 'ie', 'io', 'iou',\n    'iong', 'in', 'ing', 'u', 'ua', 'uai', 'uan', 'uang', 'uei', 'uo', 'uen',\n    'ueng', 'v', 've', 'van', 'vn'\n]\n\nSPECIALS = ['sil', 'sp']\n\n\ndef rule(C, V, R, T):\n    \"\"\"Generate a syllable given the initial, the final, erhua indicator, and tone.\n    Orthographical rules for pinyin are applied. (special case for y, w, ui, un, iu)\n    \n    Note that in this system, 'ü' is alway written as 'v' when appeared in phoneme, but converted to \n    'u' in syllables when certain conditions are satisfied.\n    \n    'i' is distinguished when appeared in phonemes, and separated into 3 categories, 'i', 'ii' and 'iii'.\n\n    Erhua is possibly applied to every finals, except for finals that already ends with 'r'.\n\n    When a syllable is impossible or does not have any characters with this pronunciation, return None\n    to filter it out.\n    \"\"\"\n\n    # 不可拼的音节, ii 只能和 z, c, s 拼\n    if V in [\"ii\"] and (C not in ['z', 'c', 's']):\n        return None\n    # iii 只能和 zh, ch, sh, r 拼\n    if V in ['iii'] and (C not in ['zh', 'ch', 'sh', 'r']):\n        return None\n\n    # 齐齿呼或者撮口呼不能和 f, g, k, h, zh, ch, sh, r, z, c, s\n    if (V not in ['ii', 'iii']) and V[0] in ['i', 'v'] and (\n            C in ['f', 'g', 'k', 'h', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's']):\n        return None\n\n    # 撮口呼只能和 j, q, x l, n 拼\n    if V.startswith(\"v\"):\n        # v, ve 只能和 j ,q , x, n, l 拼\n        if V in ['v', 've']:\n            if C not in ['j', 'q', 'x', 'n', 'l', '']:\n                return None\n        # 其他只能和 j, q, x 拼\n        else:\n            if C not in ['j', 'q', 'x', '']:\n                return None\n\n    # j, q, x 只能和齐齿呼或者撮口呼拼\n    if (C in ['j', 'q', 'x']) and not (\n        (V not in ['ii', 'iii']) and V[0] in ['i', 'v']):\n        return None\n\n    # b, p ,m, f 不能和合口呼拼，除了 u 之外\n    # bm p, m, f 不能和撮口呼拼\n    if (C in ['b', 'p', 'm', 'f']) and ((V[0] in ['u', 'v'] and V != \"u\") or\n                                        V == 'ong'):\n        return None\n\n    # ua, uai, uang 不能和 d, t, n, l, r, z, c, s 拼\n    if V in ['ua', 'uai',\n             'uang'] and C in ['d', 't', 'n', 'l', 'r', 'z', 'c', 's']:\n        return None\n\n    # sh 和 ong 不能拼\n    if V == 'ong' and C in ['sh']:\n        return None\n\n    # o 和 gkh, zh ch sh r z c s 不能拼\n    if V == \"o\" and C in [\n            'd', 't', 'n', 'g', 'k', 'h', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's'\n    ]:\n        return None\n\n    # ueng 只是 weng 这个 ad-hoc 其他情况下都是 ong\n    if V == 'ueng' and C != '':\n        return\n\n    # 非儿化的 er 只能单独存在\n    if V == 'er' and C != '':\n        return None\n\n    if C == '':\n        if V in [\"i\", \"in\", \"ing\"]:\n            C = 'y'\n        elif V == 'u':\n            C = 'w'\n        elif V.startswith('i') and V not in [\"ii\", \"iii\"]:\n            C = 'y'\n            V = V[1:]\n        elif V.startswith('u'):\n            C = 'w'\n            V = V[1:]\n        elif V.startswith('v'):\n            C = 'yu'\n            V = V[1:]\n    else:\n        if C in ['j', 'q', 'x']:\n            if V.startswith('v'):\n                V = re.sub('v', 'u', V)\n        if V == 'iou':\n            V = 'iu'\n        elif V == 'uei':\n            V = 'ui'\n        elif V == 'uen':\n            V = 'un'\n    result = C + V\n\n    # Filter  er 不能再儿化\n    if result.endswith('r') and R == 'r':\n        return None\n\n    # ii and iii, change back to i\n    result = re.sub(r'i+', 'i', result)\n\n    result = result + R + T\n    return result\n\n\ndef generate_lexicon(with_tone=False, with_erhua=False):\n    \"\"\"Generate lexicon for Mandarin Chinese.\"\"\"\n    syllables = OrderedDict()\n\n    for C in [''] + INITIALS:\n        for V in FINALS:\n            for R in [''] if not with_erhua else ['', 'r']:\n                for T in [''] if not with_tone else ['1', '2', '3', '4', '5']:\n                    result = rule(C, V, R, T)\n                    if result:\n                        syllables[result] = f'{C} {V}{R}{T}'\n    return syllables\n\n\ndef generate_symbols(lexicon):\n    \"\"\"Generate phoneme list for a lexicon.\"\"\"\n    symbols = set()\n    for p in SPECIALS:\n        symbols.add(p)\n    for syllable, phonemes in lexicon.items():\n        phonemes = phonemes.split()\n        for p in phonemes:\n            symbols.add(p)\n    return sorted(list(symbols))\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Generate lexicon for Chinese pinyin to phoneme for MFA\")\n    parser.add_argument(\"output\", type=str, help=\"Path to save lexicon.\")\n    parser.add_argument(\n        \"--with-tone\", action=\"store_true\", help=\"whether to consider tone.\")\n    parser.add_argument(\n        \"--with-r\", action=\"store_true\", help=\"whether to consider erhua.\")\n    parser.add_argument(\n        \"--rhy-with-duration\",\n        action=\"store_true\", )\n    args = parser.parse_args()\n\n    lexicon = generate_lexicon(args.with_tone, args.with_r)\n    symbols = generate_symbols(lexicon)\n\n    with open(args.output + \".lexicon\", 'wt') as f:\n        if args.rhy_with_duration:\n            f.write(\"sp1 sp1\\nsp2 sp2\\nsp3 sp3\\nsp4 sp4\\n\")\n        for k, v in lexicon.items():\n            f.write(f\"{k} {v}\\n\")\n\n    with open(args.output + \".symbols\", 'wt') as f:\n        for s in symbols:\n            f.write(s + \"\\n\")\n\n    print(\"Done!\")\n"
  },
  {
    "path": "examples/other/mfa/local/reorganize_aishell3.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script to reorganize AISHELL-3 dataset so as to use Montreal Force\nAligner to align transcription and audio.\n\nPlease refer to https://montreal-forced-aligner.readthedocs.io/en/latest/data_prep.html\nfor more details about Montreal Force Aligner's requirements on cotpus.\n\nFor scripts to reorganize other corpus, please refer to \n https://github.com/MontrealCorpusTools/MFA-reorganization-scripts\nfor more details.\n\"\"\"\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Union\n\n\ndef link_wav(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    for sub_set in {'train', 'test'}:\n        wav_dir = root_dir / sub_set / 'wav'\n        new_dir = output_dir / sub_set\n        new_dir.mkdir(parents=True, exist_ok=True)\n\n        for spk_dir in os.listdir(wav_dir):\n            sub_dir = wav_dir / spk_dir\n            new_sub_dir = new_dir / spk_dir\n            os.symlink(sub_dir, new_sub_dir)\n\n\ndef write_lab(root_dir: Union[str, Path],\n              output_dir: Union[str, Path],\n              script_type='pinyin'):\n    for sub_set in {'train', 'test'}:\n        text_path = root_dir / sub_set / 'content.txt'\n        new_dir = output_dir / sub_set\n\n        with open(text_path, 'r') as rf:\n            for line in rf:\n                wav_id, context = line.strip().split('\\t')\n                spk_id = wav_id[:7]\n                transcript_name = wav_id.split('.')[0] + '.lab'\n                transcript_path = new_dir / spk_id / transcript_name\n                context_list = context.split()\n                word_list = context_list[0:-1:2]\n                pinyin_list = context_list[1::2]\n                wf = open(transcript_path, 'w')\n                if script_type == 'word':\n                    # add space between chinese char\n                    new_context = ' '.join(word_list)\n                elif script_type == 'pinyin':\n                    new_context = ' '.join(pinyin_list)\n                wf.write(new_context + '\\n')\n\n\ndef reorganize_aishell3(root_dir: Union[str, Path],\n                        output_dir: Union[str, Path],\n                        script_type='pinyin'):\n    output_dir.mkdir(parents=True, exist_ok=True)\n    link_wav(root_dir, output_dir)\n    write_lab(root_dir, output_dir, script_type)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Reorganize AISHELL-3 dataset for MFA\")\n    parser.add_argument(\n        \"--root-dir\", type=str, default=\"\", help=\"path to AISHELL-3 dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        help=\"path to save outputs (audio and transcriptions)\")\n    parser.add_argument(\n        \"--script-type\",\n        type=str,\n        default=\"pinyin\",\n        help=\"type of lab ('word'/'pinyin')\")\n\n    args = parser.parse_args()\n    root_dir = Path(args.root_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    reorganize_aishell3(root_dir, output_dir, args.script_type)\n"
  },
  {
    "path": "examples/other/mfa/local/reorganize_baker.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script to reorganize Baker dataset so as to use Montreal Force\nAligner to align transcription and audio.\n\nPlease refer to https://montreal-forced-aligner.readthedocs.io/en/latest/data_prep.html\nfor more details about Montreal Force Aligner's requirements on cotpus.\n\nFor scripts to reorganize other corpus, please refer to \n https://github.com/MontrealCorpusTools/MFA-reorganization-scripts\nfor more details.\n\"\"\"\nimport argparse\nimport os\nimport re\nimport shutil\nfrom concurrent.futures import ThreadPoolExecutor\nfrom pathlib import Path\nfrom typing import Union\n\nimport librosa\nimport soundfile as sf\nfrom tqdm import tqdm\n\nrepalce_dict = {\n    \"；\": \"\",\n    \"。\": \"\",\n    \"：\": \"\",\n    \"—\": \"\",\n    \"）\": \"\",\n    \"，\": \"\",\n    \"“\": \"\",\n    \"（\": \"\",\n    \"、\": \"\",\n    \"…\": \"\",\n    \"！\": \"\",\n    \"？\": \"\",\n    \"”\": \"\"\n}\n\n\ndef get_transcripts(path: Union[str, Path]):\n    transcripts = {}\n\n    with open(path) as f:\n        lines = f.readlines()\n\n    for i in range(0, len(lines), 2):\n        sentence_id = lines[i].split()[0]\n        transcription = lines[i + 1].strip()\n        transcripts[sentence_id] = transcription\n\n    return transcripts\n\n\ndef resample_and_save(source, target, sr=16000):\n    wav, _ = librosa.load(str(source), sr=sr)\n    sf.write(str(target), wav, samplerate=sr, subtype='PCM_16')\n    return target\n\n\ndef reorganize_baker(root_dir: Union[str, Path],\n                     output_dir: Union[str, Path]=None,\n                     resample_audio=False,\n                     rhy_dur=False):\n    root_dir = Path(root_dir).expanduser()\n    if rhy_dur:\n        transcript_path = root_dir / \"ProsodyLabeling\" / \"000001-010000_rhy.txt\"\n    else:\n        transcript_path = root_dir / \"ProsodyLabeling\" / \"000001-010000.txt\"\n    transcriptions = get_transcripts(transcript_path)\n\n    wave_dir = root_dir / \"Wave\"\n    wav_paths = sorted(list(wave_dir.glob(\"*.wav\")))\n    output_dir = Path(output_dir).expanduser()\n    assert wave_dir != output_dir, \"Don't use an the original wav's directory as output_dir\"\n\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    if resample_audio:\n        with ThreadPoolExecutor(os.cpu_count()) as pool:\n            with tqdm(total=len(wav_paths), desc=\"resampling\") as pbar:\n                futures = []\n                for wav_path in wav_paths:\n                    future = pool.submit(resample_and_save, wav_path,\n                                         output_dir / wav_path.name)\n                    future.add_done_callback(lambda p: pbar.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    results.append(ft.result())\n    else:\n        for wav_path in tqdm(wav_paths, desc=\"copying\"):\n            shutil.copyfile(wav_path, output_dir / wav_path.name)\n\n    for sentence_id, transcript in tqdm(\n            transcriptions.items(), desc=\"transcription process\"):\n        with open(output_dir / (sentence_id + \".lab\"), 'wt') as f:\n            f.write(transcript)\n            f.write('\\n')\n    print(\"Done!\")\n\n\ndef insert_rhy(sentence_first, sentence_second):\n    sub = '#'\n    return_words = []\n    sentence_first = sentence_first.translate(str.maketrans(repalce_dict))\n    rhy_idx = [substr.start() for substr in re.finditer(sub, sentence_first)]\n    re_rhy_idx = []\n    sentence_first_ = sentence_first.replace(\"#1\", \"\").replace(\n        \"#2\", \"\").replace(\"#3\", \"\").replace(\"#4\", \"\")\n    sentence_seconds = sentence_second.split(\" \")\n    for i, w in enumerate(rhy_idx):\n        re_rhy_idx.append(w - i * 2)\n    i = 0\n    # print(\"re_rhy_idx: \", re_rhy_idx)\n    for sentence_s in (sentence_seconds):\n        return_words.append(sentence_s)\n        if i < len(re_rhy_idx) and len(return_words) - i == re_rhy_idx[i]:\n            return_words.append(\"sp\" + sentence_first[rhy_idx[i] + 1:rhy_idx[i]\n                                                      + 2])\n            i = i + 1\n    return return_words\n\n\ndef normalize_rhy(root_dir: Union[str, Path]):\n    root_dir = Path(root_dir).expanduser()\n    transcript_path = root_dir / \"ProsodyLabeling\" / \"000001-010000.txt\"\n    target_transcript_path = root_dir / \"ProsodyLabeling\" / \"000001-010000_rhy.txt\"\n\n    with open(transcript_path) as f:\n        lines = f.readlines()\n\n    with open(target_transcript_path, 'wt') as f:\n        for i in range(0, len(lines), 2):\n            sentence_first = lines[i]  #第一行直接保存\n            f.write(sentence_first)\n            transcription = lines[i + 1].strip()\n            f.write(\"\\t\" + \" \".join(\n                insert_rhy(sentence_first.split('\\t')[1], transcription)) +\n                    \"\\n\")\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Reorganize Baker dataset for MFA\")\n    parser.add_argument(\"--root-dir\", type=str, help=\"path to baker dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        help=\"path to save outputs (audio and transcriptions)\")\n    parser.add_argument(\n        \"--resample-audio\",\n        action=\"store_true\",\n        help=\"To resample audio files or just copy them\")\n    parser.add_argument(\n        \"--rhy-with-duration\",\n        action=\"store_true\", )\n    args = parser.parse_args()\n\n    if args.rhy_with_duration:\n        normalize_rhy(args.root_dir)\n    reorganize_baker(args.root_dir, args.output_dir, args.resample_audio,\n                     args.rhy_with_duration)\n"
  },
  {
    "path": "examples/other/mfa/local/reorganize_ljspeech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script to reorganize LJSpeech-1.1 dataset so as to use Montreal Force\nAligner to align transcription and audio.\n\nPlease refer to https://montreal-forced-aligner.readthedocs.io/en/latest/data_prep.html\nfor more details about Montreal Force Aligner's requirements on cotpus.\n\nFor scripts to reorganize other corpus, please refer to \n https://github.com/MontrealCorpusTools/MFA-reorganization-scripts\nfor more details.\n\"\"\"\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Union\n\n\ndef link_wav(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    wav_dir = root_dir / 'wavs'\n    for spk_dir in os.listdir(wav_dir):\n        sub_dir = wav_dir / spk_dir\n        new_sub_dir = output_dir / spk_dir\n        os.symlink(sub_dir, new_sub_dir)\n\n\ndef write_lab(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n\n    text_path = root_dir / 'metadata.csv'\n    with open(text_path, 'r') as rf:\n        for line in rf:\n            line_list = line.strip().split('|')\n            utt = line_list[0]\n            raw_text = line_list[-1]\n            transcript_name = utt + '.lab'\n            transcript_path = output_dir / transcript_name\n            with open(transcript_path, 'w') as wf:\n                wf.write(raw_text + '\\n')\n\n\ndef reorganize_ljspeech(root_dir: Union[str, Path],\n                        output_dir: Union[str, Path]):\n\n    link_wav(root_dir, output_dir)\n    write_lab(root_dir, output_dir)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Reorganize LJSpeech-1.1 dataset for MFA\")\n    parser.add_argument(\n        \"--root-dir\", type=str, help=\"path to LJSpeech-1.1 dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        help=\"path to save outputs (audio and transcriptions)\")\n    args = parser.parse_args()\n    root_dir = Path(args.root_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    reorganize_ljspeech(root_dir, output_dir)\n"
  },
  {
    "path": "examples/other/mfa/local/reorganize_vctk.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script to reorganize VCTK dataset so as to use Montreal Force\nAligner to align transcription and audio.\n\nPlease refer to https://montreal-forced-aligner.readthedocs.io/en/latest/data_prep.html\nfor more details about Montreal Force Aligner's requirements on cotpus.\n\nFor scripts to reorganize other corpus, please refer to \n https://github.com/MontrealCorpusTools/MFA-reorganization-scripts\nfor more details.\n\"\"\"\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom pathlib import Path\nfrom typing import Union\n\nimport librosa\nimport soundfile as sf\nfrom tqdm import tqdm\n\n\ndef resample_and_save(source, target, sr=16000):\n    wav, _ = librosa.load(str(source), sr=sr)\n    sf.write(str(target), wav, samplerate=sr, subtype='PCM_16')\n    return target\n\n\ndef write_wav(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    wav_paths = []\n    new_wav_paths = []\n\n    wav_dir = root_dir / 'wav48_silence_trimmed'\n    new_dir = output_dir\n    new_dir.mkdir(parents=True, exist_ok=True)\n\n    for spk_dir in os.listdir(wav_dir):\n        # no txt for p315\n        # no mic2 for p280 and p362\n        if spk_dir not in {'log.txt', 'p315', 'p280', 'p362'}:\n            sub_dir = wav_dir / spk_dir\n            new_sub_dir = new_dir / spk_dir\n            new_sub_dir.mkdir(parents=True, exist_ok=True)\n            for wav_name in os.listdir(sub_dir):\n                # mic1 have very low frequency noises\n                pre_wav_name = \"_\".join(wav_name.split(\"_\")[:2])\n                if \"mic2\" in wav_name:\n                    wav_paths.append(str(sub_dir / wav_name))\n                    # remove \"_mic2\" in wav_name and replace \".flac\" with \".wav\"\n                    new_wav_name = pre_wav_name + \".wav\"\n                    new_wav_paths.append(str(new_sub_dir / new_wav_name))\n\n    assert len(new_wav_paths) == len(wav_paths)\n\n    with ThreadPoolExecutor(os.cpu_count()) as pool:\n        with tqdm(total=len(wav_paths), desc=\"resampling\") as pbar:\n            futures = []\n            for i, wav_path in enumerate(wav_paths):\n                future = pool.submit(resample_and_save, wav_path,\n                                     new_wav_paths[i])\n                future.add_done_callback(lambda p: pbar.update())\n                futures.append(future)\n\n            results = []\n            for ft in futures:\n                results.append(ft.result())\n\n\ndef write_txt(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    txt_dir = root_dir / 'txt'\n\n    new_dir = output_dir\n    new_dir.mkdir(parents=True, exist_ok=True)\n    for spk_dir in os.listdir(txt_dir):\n        # no txt for p315\n        if spk_dir not in {'log.txt', 'p315', 'p280', 'p362'}:\n            sub_dir = txt_dir / spk_dir\n            new_sub_dir = new_dir / spk_dir\n            for txt_name in os.listdir(sub_dir):\n                rf = open(sub_dir / txt_name, \"r\")\n                wf = open(new_sub_dir / txt_name, \"w\")\n                for line in rf:\n                    wf.write(line)\n\n\ndef reorganize_vctk(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    output_dir.mkdir(parents=True, exist_ok=True)\n    write_wav(root_dir, output_dir)\n    write_txt(root_dir, output_dir)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Reorganize VCTK-Corpus-0.92 dataset for MFA\")\n    parser.add_argument(\n        \"--root-dir\",\n        type=str,\n        default=\"\",\n        help=\"path to VCTK-Corpus-0.92 dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        help=\"path to save outputs (audio and transcriptions)\")\n\n    args = parser.parse_args()\n    root_dir = Path(args.root_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    reorganize_vctk(root_dir, output_dir)\n"
  },
  {
    "path": "examples/other/mfa/run.sh",
    "content": "exp=exp\ndata=data\n\nmkdir -p $exp\nmkdir -p $data\n\nLEXICON_NAME='simple'\nMFA_DOWNLOAD_DIR=local/\n\nif [ ! -f \"$exp/$LEXICON_NAME.lexicon\" ]; then\n    echo \"generating lexicon...\"\n    python local/generate_lexicon.py \"$exp/$LEXICON_NAME\" --with-r --with-tone\n    echo \"lexicon done\"\nfi\n\nif [ ! -d $exp/baker_corpus ]; then\n    echo \"reorganizing baker corpus...\"\n    python local/reorganize_baker.py --root-dir=~/datasets/BZNSYP --output-dir=$exp/baker_corpus --resample-audio\n    echo \"reorganization done. Check output in $exp/baker_corpus.\"\n    echo \"audio files are resampled to 16kHz\"\n    echo \"transcription for each audio file is saved with the same namd in $exp/baker_corpus \"\nfi\n\n\necho \"detecting oov...\"\npython local/detect_oov.py $exp/baker_corpus $exp/\"$LEXICON_NAME.lexicon\"\necho \"detecting oov done. you may consider regenerate lexicon if there is unexpected OOVs.\"\n\n\nif [ ! -f \"$MFA_DOWNLOAD_DIR/montreal-forced-aligner_linux.tar.gz\" ]; then\n    echo \"downloading mfa...\"\n    (cd $MFA_DOWNLOAD_DIR && wget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz)\n    echo \"download mfa done!\"\nfi\n\nif [ ! -d \"$MFA_DOWNLOAD_DIR/montreal-forced-aligner\" ]; then\n    echo \"extracting mfa...\"\n    (cd $MFA_DOWNLOAD_DIR && tar xvf \"montreal-forced-aligner_linux.tar.gz\")\n    echo \"extraction done!\"\nfi\n\nexport PATH=\"$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin\"\n\nif [ ! -d \"$exp/baker_alignment\" ]; then\n    echo \"Start MFA training...\"\n    PATH=$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin/:$PATH \\\n    LD_LIBRARY_PATH=$MFA_DOWNLOAD_DIR/montreal-forced-aligner/lib/:$LD_LIBRARY_PATH \\\n    ./$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin/mfa_train_and_align \\\n        $exp/baker_corpus \"$exp/$LEXICON_NAME.lexicon\" $exp/baker_alignment -o $exp/baker_model --clean --verbose -j 10 --temp_directory $exp/.mfa_train_and_align\n    echo \"training done!\"\n    echo \"results: $exp/baker_alignment\"\n    echo \"model: $exp/baker_model\"\nfi\n\n"
  },
  {
    "path": "examples/other/mfa/run_canton.sh",
    "content": "exp=exp\n\nmkdir -p $exp\nLEXICON_NAME='canton'\nMFA_DOWNLOAD_DIR=local/\n\nif [ ! -f \"$exp/$LEXICON_NAME.lexicon\" ]; then\n    echo \"generating lexicon and training data...\"\n    python local/generate_canton_lexicon_wavlabs.py --output_lexicon \"$exp/$LEXICON_NAME.lexicon\" --output_wavlabs \"$exp/$LEXICON_NAME\"_wavlabs --inputs ~/datasets/Guangzhou_Cantonese_Scripted_Speech_Corpus_Daily_Use_Sentence ~/datasets/Guangzhou_Cantonese_Scripted_Speech_Corpus_in_Vehicle\n    echo \"lexicon and training data done\"\nfi\n\nif [ ! -f \"$MFA_DOWNLOAD_DIR/montreal-forced-aligner_linux.tar.gz\" ]; then\n    echo \"downloading mfa...\"\n    (cd $MFA_DOWNLOAD_DIR && wget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz)\n    echo \"download mfa done!\"\nfi\n\nif [ ! -d \"$MFA_DOWNLOAD_DIR/montreal-forced-aligner\" ]; then\n    echo \"extracting mfa...\"\n    (cd $MFA_DOWNLOAD_DIR && tar xvf \"montreal-forced-aligner_linux.tar.gz\")\n    echo \"extraction done!\"\nfi\n\nexport PATH=\"$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin\"\nif [ ! -d \"$exp/canton_alignment\" ]; then\n    echo \"Start MFA training...\"\n    PATH=$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin/:$PATH \\\n    LD_LIBRARY_PATH=$MFA_DOWNLOAD_DIR/montreal-forced-aligner/lib/:$LD_LIBRARY_PATH \\\n    ./$MFA_DOWNLOAD_DIR/montreal-forced-aligner/bin/mfa_train_and_align \\\n        \"$exp/$LEXICON_NAME\"_wavlabs \"$exp/$LEXICON_NAME.lexicon\" $exp/canton_alignment -o $exp/canton_model --clean --verbose -j 10 --temp_directory $exp/.mfa_train_and_align\n    echo \"training done!\"\n    echo \"results: $exp/canton_alignment\"\n    echo \"model: $exp/canton_model\"\nfi\n\n"
  },
  {
    "path": "examples/other/ngram_lm/.gitignore",
    "content": "exp/\n"
  },
  {
    "path": "examples/other/ngram_lm/README.md",
    "content": "# Ngram LM\n\n* s0 - kenlm ngram lm\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/.gitignore",
    "content": "data/lm\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/README.md",
    "content": "# Ngram LM\n\nTrain chinese chararctor ngram lm by [kenlm](https://github.com/kpu/kenlm).\n\n## Run\n```\n. path.sh\nbash run.sh\n```\n\n## Results\n\n```\nexp/\n|-- text\n|-- text.char.tn\n|-- text.word.tn\n|-- text_zh_char_o5_p0_1_2_4_4_a22_q8_b8.arpa\n|-- text_zh_char_o5_p0_1_2_4_4_a22_q8_b8.arpa.klm.bin\n|-- text_zh_word_o3_p0_0_0_a22_q8_b8.arpa\n`-- text_zh_word_o3_p0_0_0_a22_q8_b8.arpa.klm.bin\n\n0 directories, 7 files\n```\n\n```\n3ae083627b9b6cef1a82d574d8483f97  exp/text\nd97da252d2a63a662af22f98af30cb8c  exp/text.char.tn\nc18b03005bd094dbfd9b46442be361fd  exp/text.word.tn\n73dbf50097896eda33985e11e1ba9a3a  exp/text_zh_char_o5_p0_1_2_4_4_a22_q8_b8.arpa\n01334e2044c474b99c4f2ffbed790626  exp/text_zh_char_o5_p0_1_2_4_4_a22_q8_b8.arpa.klm.bin\n36a42de548045b54662411ae7982c77f  exp/text_zh_word_o3_p0_0_0_a22_q8_b8.arpa\n332422803ffd73dd7ffd16cd2b0abcd5  exp/text_zh_word_o3_p0_0_0_a22_q8_b8.arpa.klm.bin\n```\n\n```\n==> exp/text <==\n少先队员因该为老人让坐\n祛痘印可以吗？有效果吗？\n不知这款牛奶口感怎样？ 小孩子喝行吗！\n是转基因油?\n我家宝宝13斤用多大码的\n会起坨吗？\n请问给送上楼吗？\n亲是送赁上门吗\n送货时候有外包装没有还是直接发货过来\n会不会有坏的？\n\n==> exp/text.char.tn <==\n少 先 队 员 因 该 为 老 人 让 坐\n祛 痘 印 可 以 吗 有 效 果 吗\n不 知 这 款 牛 奶 口 感 怎 样 小 孩 子 喝 行 吗\n是 转 基 因 油\n我 家 宝 宝 十 三 斤 用 多 大 码 的\n会 起 坨 吗\n请 问 给 送 上 楼 吗\n亲 是 送 赁 上 门 吗\n送 货 时 候 有 外 包 装 没 有 还 是 直 接 发 货 过 来\n会 不 会 有 坏 的\n\n==> exp/text.word.tn <==\n少先队员 因该 为 老人 让 坐\n祛痘 印 可以 吗 有 效果 吗\n不知 这 款 牛奶 口感 怎样 小孩子 喝行 吗\n是 转基因 油\n我家 宝宝 十三斤 用多大码 的\n会起 坨 吗\n请问 给 送 上楼 吗\n亲是 送赁 上门 吗\n送货 时候 有 外包装 没有 还是 直接 发货 过来\n会 不会 有坏 的\n\n==> exp/text_zh_char_o5_p0_1_2_4_4_a22_q8_b8.arpa <==\n\\data\\\nngram 1=587\nngram 2=395\nngram 3=100\nngram 4=2\nngram 5=0\n\n\\1-grams:\n-3.272324       <unk>   0\n0       <s>     -0.36706257\n\n==> exp/text_zh_word_o3_p0_0_0_a22_q8_b8.arpa <==\n\\data\\\nngram 1=689\nngram 2=1398\nngram 3=1506\n\n\\1-grams:\n-3.1755018      <unk>   0\n0       <s>     -0.23069073\n-1.2318869      </s>    0\n-3.067262       少先队员        -0.051341705\n```\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/data/README.md",
    "content": "text_correct.txt: https://github.com/shibing624/pycorrector/raw/master/tests/test_file.txt\ncustom_confusion.txt: https://github.com/shibing624/pycorrector/raw/master/tests/custom_confusion.txt\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/data/custom_confusion.txt",
    "content": "#变体\t本体\t本体词词频（可省略）\n兴高彩列\t兴高采烈\t100\n吹唐人\t吹糖人\t100\n百年家具\t百年家居\n泄药\t泻药\n称做\t称作\t100\n化学成份\t化学成分\t100\n天地无垠\t天地无限\t100\n欲妄\t欲望\n满头大汉\t满头大汗\n一阙\t一阕\t300\n斗音\t抖音\t100\n人材\t人才\t100\n微亅信\t微信\t100\n微·信\t微信\t1000\n一毛不陪\t一毛不赔\t200\n无线大\t无限大\t1\n正加\t增加\n相对得\t相对地\n越来越底\t越来越低\n个纾\t个数\n曾加\t增加\n情怳\t情况\n持续的\t持续地\n不断的\t不断地\n成现\t呈现\n家重\t加重\n中国子\t中国字\n计录\t记录\n一落千仗\t一落千丈\n婴而\t婴儿\n负贵\t富贵\n旁遍\t旁边\n续承\t继承\n约来越晚\t越来越晚\n提共\t提供\n行成\t形成\n读哩\t独立\n忙绿\t忙碌\n年经人\t年轻人\n智识\t知识\n一但\t一旦\n指摘\t指责\n懹人民自己选择\t让人民自己选择\n紧裤\t辛苦\n放心地生活\t放心的生活\n但靠一份收入\t单靠一份收入\n多付出地几十倍\t多付出的几十倍\n化钱\t花钱\n依些\t一些\n耐心的教育\t耐心地教育\n多某些人来说\t对某些人来说\n列子\t例子\n普便\t普遍\n单纯的说\t单纯地说\n相对得坏处\t相对的坏处\n改很多幼稚园\t盖很多幼稚园\n不断的增加\t不断地增加\n谈讨\t探讨\n小还\t小孩\n未普边\t未普遍\n考良\t考量\n过的不错\t过得不错\n手医学治疗\t受医学治疗\n数为至少四个人\t数位至少四个人\n小子化\t少子化\n间直\t简直\n每办法\t没办法\n青跨\t情况\n最总\t最终\n僱佣\t僱用\n渐渐的形成\t渐渐地形成\n渐渐的增加\t渐渐地增加\n不断的改变\t不断地改变\n不断的提高\t不断地提高\n莫些年\t某些年\n成工\t成功\n线然\t显然\n一长争段\t一长争短\n在加上\t再加上\n一后\t以后\n自起\t自己\n年轻得夫妇\t年轻的夫妇\n真的事对\t真的是对\n养小还\t养小孩\n不彷\t不妨\n疏缓\t舒缓\n上叙\t上述\n或着市\t或者是\n学习地意愿\t学习的意愿\n按部就班\t按步就班\n全面的规划\t全面地规划\n纾缓\t舒缓\n年少气胜\t年少气盛\n新家坡\t新加坡\n变的很轻松\t变得很轻松\n我门\t我们\n月来越好\t越来越好\n发生国\t发生过\n以开发国家\t已开发国家\n以开发\t已开发\n赛翁失马\t塞翁失马\n非常的宝贵\t非常地宝贵\n列如\t例如\n非常的珍贵\t非常地珍贵\n二零五龄年\t二零五零年\n証明\t证明\n一间一间的关必\t一间一间地关闭\n缠能收割\t才能收割\n朗朗称道\t琅琅称道\n缠能拯救\t才能拯救\n付其责\t负其责\n还而\t孩儿\n自然而然的\t自然而然地\n现再\t现在\n一间一间的在建造\t一间一间地在建造\n惰胎\t堕胎\n给与\t给予\n少字化\t少子化\n狂大\t广大\n至到\t直到\n作些政策\t做些政策\n想望\t向往\n低免\t抵免\n展生\t产生\n源料\t原料\n好好的准备\t好好地准备\n庄况\t状况\n因发\t引发\n自记\t自己\n桃论\t讨论\n负单\t负担\n而以\t而已\n政符\t政府\n邀情\t邀请\n郑加\t增加\n全心全力的\t全心全力地\n进一份力\t尽一份力\n不断的努力\t不断地努力\n厉害关系\t利害关系\n相像\t现象\n题及\t提及\n剥歇\t剥削\n下起\t下去\n了所学校\t各所学校\n很好得一份工作\t很好的一份工作\n来的这么快\t来得这么快\n言前\t眼前\n所担任的是有限\t所担任的事有限\n放面\t方面\n办发\t办法\n有趣的说到\t有趣地说到\n坚帧不移\t坚贞不移\n心力绞碎\t心力交瘁\n开发看经济\t开发和经济\n有效的规划\t有效地规划\n流守\t留守\n生济\t生计\n带欠缺\t但欠缺\n堆动\t推动\n表达的是\t表达的事\n所以问题\t所有问题\n由其固定的速度\t有其固定的速度\n乐与减少\t乐于减少\n变的困难\t变得困难\n多馀\t多于\n长远的看\t长远地看\n血浓与水\t血浓于水\n表面的看\t表面地看\n推称出新\t推陈出新\n脱离萍\t脱离贫\n时间一天一天的过去\t时间一天一天地过去\n提昌\t提倡\n续多\t许多\n现进\t先进\n销费率\t消费率\n直接的被感受\t直接地被感受\n陪养\t培养\n主在乡下\t住在乡下\n弄多的很快\t弄多得很快\n他门\t他们\n持续的下降\t持续地下降\n相对的减少\t相对地减少\n相对的提高\t相对地提高\n适当的生育\t适当地生育\n成功的制定\t成功地制定\n青少年门\t青少年们\n慎重的希望\t慎重地希望\n娇傲\t骄傲\n亲爱的少年门\t亲爱的少年们\n少子华\t少子化\n生上\t身上\n不断的鼓励\t不断地鼓励\n具造\t制造\n单初\t当初\n发掌\t发展\n大幅度的提升\t大幅度地提升\n负担地因素\t负担的因素\n亘多医疗费用\t更多医疗费用\n餵了\t为了\n照成\t造成\n教育基精\t教育基金\n装造性\t创造性\n观察关\t观察官\n怎么形成地\t怎么形成的\n比年长者来的多\t比年长者来得多\n不单\t不但\n变的更良好\t变得更良好\n变的更大\t变得更大\n壤大众理解\t让大众理解\n上免得分析\t上面的分析\n已经再发生了\t已经在发生了\n带来得危机\t带来的危机\n恶讯循环\t恶性循环\n他得生活费\t他的生活费\n以开发地区\t已开发地区\n长其\t长期\n经额\t金额\n在过几十年\t再过几十年\n作为探讨\t做为探讨\n系根据\t是根据\n位于\t为于\n份公司\t分公司\n要作塑胶袋\t要做塑胶袋\n还不过\t还不够\n逃战\t挑战\n再服务业\t在服务业\n招莫\t招募\n坐者\t坐着\n仔细的观察\t仔细地观察\n三个凑皮匠\t三个臭皮匠\n个中各样\t各种各样\n不啻\t不是\n即史\t即使\n岂有此里\t岂有此理\n组宠物的人\t租宠物的人\n浅溥\t浅薄\n处里\t处理\n他们得不负责任的态度\t他们的不负责任的态度\n出租得事\t出租的事\n这样以来\t这样一来\n题高\t提高\n厌力\t压力\n事情阿\t事情啊\n又意思\t有意思\n建慷\t健康\n真恭喜妳阿\t真恭喜妳啊\n抱见阿\t抱歉啊\n幸苦\t辛苦\n参家\t参加\n回来台湾\t会来台湾\n生体\t身体\n总视\t总是\n一把很大的化\t一把很大的花\n出你\t祝你\n高心\t高兴\n应为\t因为\n洗碗\t希望\n那理\t那里\n根她坐公共汽车\t跟她坐公共汽车\n公克\t功课\n根林美美去\t跟林美美去\n一前\t以前\n傍边\t旁边\n总明\t聪明\n最难得课\t最难的课\n在马上去\t再马上去\n建在\t现在\n事等我女朋友的\t是等我女朋友的\n客爱\t可爱\n象片\t相片\n也雪\t也许\n录的\t绿的\n纲来\t刚来\n让后\t然后\n真得是坏人\t真的是坏人\n提以\t提议\n大的家\t他的家\n从是\t总是\n有处\t有趣\n课目\t科目\n看得是美国电影\t看的是美国电影\n兴奋得\t兴奋地\n控的时间\t空的时间\n内容懂不清楚\t内容都不清楚\n谊起\t一起\n打公车\t搭公车\n近去\t进去\n林美妹\t林美美\n唷意思\t有意思\n蔘加\t参加\n再开一个好把\t再开一个好吧\n兴起不好\t心情不好\n庆祝地会\t庆祝的会\n漂漂亮亮地风景\t漂漂亮亮的风景\n再庆祝一次把\t再庆祝一次吧\n找的时间\t找个时间\n间妈妈\t见妈妈\n无会\t舞会\n解我的朋友\t请我的朋友\n日字\t日子\n但然\t当然\n障爱文\t张爱文\n已定\t一定\n澳是\t要是\n长爱文\t张爱文\n理物\t礼物\n延后\t然后\n合问她\t和问她\n恨高兴\t很高兴\n一让\t一样\n帮别的学生的芒\t帮别的学生的忙\n沾着\t站着\n怒朋友\t女朋友\n下明\t小明\n老师文学生\t老师问学生\n他清她吃饭\t他请她吃饭\n还没作\t还没做\n座公车\t坐公车\n打篹\t打算\n沾起来\t站起来\n再起床呢\t在起床呢\n再黑板写的东西\t在黑板写的东西\n不输服\t不舒服\n很哩\t很累\n警张\t紧张\n劳天\t聊天\n很来\t很累\n多要\t都要\n奴朋友\t女朋友\n高兴的不得了\t高兴得不得了\n里学校很近\t离学校很近\n音龠\t音乐\n合唱父系语法\t和常复习语法\n税觉\t睡觉\n觉得贰\t觉得饿\n对不气\t对不起\n情你去吃饭\t请你去吃饭\n不局道\t不知道\n你好马\t你好吗\n岑么样\t怎么样\n可以马\t可以吗\n我想情你\t我想请你\n火者站\t火车站\n聊体\t聊天\n最前的子\t最前的字\n座捷运\t坐捷运\n哪哩\t哪里\n十只路口\t十字路口\n不智道\t不知道\n怎门办\t怎么办\n点视机\t电视机\n已后\t以后\n妳会时后\t妳回时候\n漂凉\t漂亮\n票凉\t漂亮\n又漂亮的衣服\t有漂亮的衣服\n清卖给我\t请买给我\n红虹\t红红\n待你的国家\t到你的国家\n太样兵\t太阳饼\n不拘导\t不知道\n不咀导\t不知道\n这哩\t这里\n成市\t城市\n发山\t爬山\n风镜\t风景\n他杏林\t他姓林\n痕累\t很累\n方假\t放假\n风京\t风景\n座火车\t坐火车\n他的华\t他的话\n户然\t忽然\n理面\t里面\n做回去\t坐回去\n出们\t出门\n愿赖\t原来\n吧手\t把手\n厅路上\t听路上\n定车\t停车\n高现\t高兴\n排照\t拍照\n他的婉\t他的腕\n原意\t愿意\n没人琣他\t没人陪他\n歹去\t带去\n自即\t自己\n开是\t开始\n和一点饮料\t喝一点饮料\n录行\t旅行\n谈着谈者\t谈着谈着\n漂亮的术\t漂亮的树\n戴我\t载我\n作天\t昨天\n很日\t很热\n照篇\t照片\n我借你们\t我接你们\n握着我的朋友\t我找我的朋友\n台配种战\t台北总站\n来我的家完\t来我的家玩\n营为\t因为\n她门\t她们\n些日会\t生日会\n右遍\t右边\n开时\t开始\n做八八的公车\t坐八八的公车\n对们\t对门\n学玩了\t学完了\n票漂亮亮\t漂漂亮亮\n喜暗\t喜欢\n括大风\t刮大风\n批具\t啤酒\n骠了\t漂亮\n瞅天\t秋天\n难德\t南德\n不太施\t不太湿\n冬天件\t冬天间\n愁天\t秋天\n塞太阳\t晒太阳\n跟美\t很美\n单让\t当然\n感在\t改在\n有孔\t有空\n吃葚么\t吃什么\n西欢\t喜欢\n泰泰\t太太\n词反\t吃饭\n其末考\t期末考\n台湾采\t台湾菜\n他们的采\t他们的菜\n设么\t什么\n共喜\t恭喜\n日本蔡\t日本菜\n餐订\t餐厅\n公课\t功课\n大们口\t大门口\n有没有控\t有没有空\n刘信\t留信\n六根礼拜日\t六跟礼拜日\n永敢\t勇敢\n辛亏\t幸亏\n估停站\t古亭站\n异子\t椅子\n胡涂\t糊涂\n真巧呕\t真巧喔\n奴生\t女生\n好朋有\t好朋友\n莫斯汉堡\t摩斯汉堡\n不可望\t不可忘\n中文壳\t中文课\n棒他\t帮他\n怎嚜走\t怎么走\n吃凉\t吃惊\n冈来\t刚来\n勇敢得\t勇敢地\n风友\t朋友\n走天\t昨天\n湖涂\t糊涂\n怎嚜\t怎么\n真得\t值得\n哪理\t哪里\n票亮\t漂亮\n又高又受\t又高又瘦\n化了半个小时\t花了半个小时\n杆快\t赶快\n学习的很愉快\t学习得很愉快\n怎吗\t怎么\n十子路口\t十字路口\n开方\t开放\n息缓\t喜欢\n交相机\t照相机\n请办我\t请帮我\n爬上\t爬山\n录色\t绿色\n各我妈妈\t给我妈妈\n交马上停车\t叫马上停车\n米了\t迷了\n交到了\t就到了\n号吗\t号码\n很葬\t很脏\n换给\t还给\n清流\t请留\n名子\t名字\n把输给弄丢\t把书给弄丢\n播爱\t博爱\n大搂\t大楼\n逃论室\t讨论室\n坻里\t地理\n奇给我\t寄给我\n座飞机\t坐飞机\n再机场\t在机场\n便很帅\t变很帅\n腾她\t等她\n路行\t旅行\n梅天\t每天\n她九打电话\t她就打电话\n美邦法\t没办法\n不好以时\t不好意思\n有疑点藤\t有一点疼\n里拜四\t礼拜四\n李佬时\t李老师\n工课\t功课\n身提\t身体\n可使\t可是\n靠事\t考试\n重要得东西\t重要的东西\n寮解\t了解\n情你\t请你\n而截\t而且\n昭显机\t照相机\n够猫\t狗猫\n最有名的采\t最有名的菜\n波澜\t波兰\n西办加话\t西班牙话\n东四\t东西\n台弯\t台湾\n学子\t学字\n银董\t运动\n而接\t而且\n有控\t有空\n陆行\t旅行\n忍识\t认识\n式式看\t试试看\n拨兰\t波兰\n一支狗\t一只狗\n管哩\t管理\n将学金\t奖学金\n再波兰\t在波兰\n下了可\t下了课\n回越南得时候\t回越南的时候\n台湾得风景\t台湾的风景\n朋有\t朋友\n气个月\t七个月\n从德国莱\t从德国来\n文花\t文化\n吃部下\t吃不下\n清假\t请假\n烤试\t考试\n血绿\t血缘\n我票告诉您\t我要告诉您\n候天\t后天\n惜来看\t借来看\n上果\t上课\n吗吗\t妈妈\n师什么公车\t是什么公车\n岗来\t刚来\n挑了\t跳了\n座７１６号的公车\t坐７１６号的公车\n三十分锺\t三十分钟\n七点锺\t七点钟\n公车佔\t公车站\n邓的时候\t等的时候\n依服\t衣服\n睡过偷\t睡过头\n佑对\t有对\n乎很大的吸\t呼很大的吸\n一整天水乐\t一整天睡了\n等以等\t等一等\n只有妳\t只有你\n可况\t何况\n学姣\t学校\n跳无\t跳舞\n恨情张\t很紧张\n恨票亮\t很漂亮\n俩个\t两个\n悾怕\t恐怕\n北老师骂他\t怕老师骂他\n十五分种\t十五分钟\n必较多\t比较多\n睡过头把\t睡过头吧\n我要座得巴士\t我要坐的巴士\n来不起\t来不及\n才陪吵醒\t才被吵醒\n撘公车\t搭公车\n眼靓\t眼睛\n台我无聊\t太过无聊\n大明哏他朋友\t大明跟他朋友\n跳五\t跳舞\n３０份钟\t３０分钟\n座呢个公车\t坐那个公车\n热恼\t热闹\n手摽\t手表\n苏嘉\t暑假\n不好亿思\t不好意思\n怎么杨\t怎么样\n妳怎么了\t你怎么了\n没有控\t没有空\n根冒\t感冒\n卧是李\t我是李\n即然\t既然\n台杯\t台北\n里拜\t礼拜\n希冠\t希望\n开兴\t开心\n烤师\t考试\n热心的不得了\t热心得不得了\n结昏\t结婚\n边请卡\t邀请卡\n注在\t住在\n密鲁\t秘鲁\n过的很开心\t过得很开心\n寰麟\t婚礼\n我回想妳们\t我会想你们\n绍待卡\t招待卡\n妳们\t你们\n幸福快乐的过\t幸福快乐地过\n公司排我\t公司派我\n常不一样\t穿不一样\n做二九七的公车\t坐二九七的公车\n几希\t继续\n今天得计画\t今天的计画\n开心得\t开心地\n钟就\t终究\n共车\t公车\n兔然\t突然\n林雨\t淋雨\n做公车\t坐公车\n好好地经验\t好好的经验\n涂然\t突然\n讨润以下\t讨论一下\n去万\t去玩\n高兴得\t高兴地\n考食物\t烤食物\n在考\t在烤\n美里\t美丽\n交他的朋友\t教他的朋友\n休葸\t休息\n拟越来越漂亮\t妳越来越漂亮\n对阿\t对啊\n一扁吃\t一边吃\n高高兴兴的\t高高兴兴地\n修系\t休息\n搜已\t所以\n早藏\t早上\n玩的横高兴\t玩得很高兴\n做神马\t做什么\n努生\t女生\n高行\t高兴\n一点鹅\t一点饿\n点蔡\t点菜\n交弮\t交卷\n贵定\t规定\n公作\t工作\n炽爱\t挚爱\n系望\t希望\n你道德地旁\t你到的地方\n除去完\t出去玩\n里拜天\t礼拜天\n暱友打算\t你有打算\n新家波\t新加坡\n考利以下\t考虑一下\n一起去把\t一起去吧\n寄怪\t奇怪\n休息一点\t休息一天\n我要会我的国家\t我要回我的国家\n四班牙\t西班牙\n完五月\t玩五月\n踏青我们\t他请我们\n是天两夜\t四天两夜\n忆起去\t一起去\n好久没间\t好久没见\n放便\t方便\n玩着玩者\t玩着玩着\n裁板\t裁判\n清等我\t请等我\n座一下\t坐一下\n请座\t请坐\n板球\t棒球\n测天\t这天\n馔衣服\t穿衣服\n情坐\t请坐\n经张\t紧张\n辕动比赛\t运动比赛\n埤酒\t啤酒\n看般球\t看棒球\n餲得不得了\t渴得不得了\n絣干\t饼干\n形像代言人 形象代言人\n化夏子孙 华夏子孙\n华为泡影 化为泡影\n秘密歪斜 秘密外泄\n计画 计划\n忠于等到了 终于等到了\n未日来临 末日来临\n眼晴 眼睛\n游刀有余 游刃有余\n唐僧帅徒 唐僧师徒\n太概 大概\n一揽子货币 一篮子货币\n举足无措 手足无措\n凭藉 凭借\n令人發指 令人髮指\n绅仕 绅士\n粘豆包 黏豆包\n磬竹难书 罄竹难书\n严惩不怠 严惩不贷\n戮力同心 勠力同心\n罚角球 发角球\n综合症 综合征\n单独二胎 单独二孩\n蛰人 蜇人\n泄秘 泄密\n伏法 服法\n羊羯子 羊蝎子\n泻湖 潟湖\n家俱 家具\n精萃 精粹\n兴亡周期率 兴亡周期律\n震憾 震撼\n中华人名共和国 中华人民共和国\n大人常委会 人大常委会\n中国共产常 中国共产党\n科学发展现 科学发展观\n扶贪 扶贫\n严谨公款吃喝 严禁公款吃喝\n按纳\t按捺\n案语\t按语\n百废具兴\t百废俱兴\n百页窗\t百叶窗\n班白\t斑白\n颁白\t斑白\n班驳\t斑驳\n胞子\t孢子\n保镳\t保镖\n保母\t保姆\n褓姆\t保姆\n辈份\t辈分\n本份\t本分\n笔划\t笔画\n必恭必敬\t毕恭毕敬\n编者案\t编者按\n萹豆\t扁豆\n稨豆\t扁豆\n藊豆\t扁豆\n标识\t标志\n鬓脚\t鬓角\n禀承\t秉承\n补靪\t补丁\n补钉\t补丁\n参预\t参与\n惨澹\t惨淡\n差迟\t差池\n搀和\t掺和\n搀假\t掺假\n搀杂\t掺杂\n刬除\t铲除\n倘佯\t徜徉\n车箱\t车厢\n澈底\t彻底\n沈思\t沉思\n趁心\t称心\n成份\t成分\n澄彻\t澄澈\n侈糜\t侈靡\n筹画\t筹划\n筹马\t筹码\n踌蹰\t踌躇\n出谋画策\t出谋划策\n喘嘘嘘\t喘吁吁\n磁器\t瓷器\n赐与\t赐予\n粗卤\t粗鲁\n搭当\t搭档\n搭挡\t搭档\n搭赸\t搭讪\n答讪\t搭讪\n答覆\t答复\n带孝\t戴孝\n耽心\t担心\n耽忧\t担忧\n担搁\t耽搁\n澹泊\t淡泊\n澹然\t淡然\n倒楣\t倒霉\n低徊\t低回\n雕敝\t凋敝\n雕弊\t凋敝\n雕零\t凋零\n雕落\t凋落\n雕谢\t凋谢\n跌荡\t跌宕\n跌交\t跌跤\n蹀血\t喋血\n丁宁\t叮咛\n定单\t订单\n定户\t订户\n定婚\t订婚\n定货\t订货\n定阅\t订阅\n枓拱\t斗拱\n枓栱\t斗拱\n逗遛\t逗留\n斗趣儿\t逗趣儿\n独脚戏\t独角戏\n端五\t端午\n二簧\t二黄\n贰心\t二心\n发人深醒\t发人深省\n蕃衍\t繁衍\n分付\t吩咐\n份量\t分量\n份内\t分内\n份外\t分外\n忿忿\t愤愤\n丰富多采\t丰富多彩\n疯瘫\t风瘫\n疯颠\t疯癫\n疯疯颠颠\t疯疯癫癫\n锋铓\t锋芒\n伏侍\t服侍\n服事\t服侍\n伏输\t服输\n伏罪\t服罪\n负嵎顽抗\t负隅顽抗\n傅会\t附会\n覆信\t复信\n复辙\t覆辙\n干与\t干预\n告戒\t告诫\n梗直\t耿直\n鲠直\t耿直\n恭惟\t恭维\n勾划\t勾画\n勾联\t勾连\n孤苦零丁\t孤苦伶仃\n孤负\t辜负\n骨董\t古董\n股分\t股份\n骨瘦如豺\t骨瘦如柴\n关连\t关联\n光采\t光彩\n归根结柢\t归根结底\n规戒\t规诫\n鬼哭狼嗥\t鬼哭狼嚎\n过份\t过分\n虾蟆\t蛤蟆\n含胡\t含糊\n涵蓄\t含蓄\n寒伧\t寒碜\n喝采\t喝彩\n喝倒采\t喝倒彩\n哄动\t轰动\n宏扬\t弘扬\n红通通\t红彤彤\n弘论\t宏论\n弘图\t宏图\n鸿图\t宏图\n弘愿\t宏愿\n弘旨\t宏旨\n鸿福\t洪福\n胡臭\t狐臭\n胡蝶\t蝴蝶\n胡涂\t糊涂\n虎魄\t琥珀\n花着\t花招\n豁拳\t划拳\n搳拳\t划拳\n恍忽\t恍惚\n晖映\t辉映\n混水摸鱼\t浑水摸鱼\n火伴\t伙伴\n机伶\t机灵\n激忿\t激愤\n计画\t计划\n记念\t纪念\n寄与\t寄予\n茄克\t夹克\n佳宾\t嘉宾\n驾御\t驾驭\n架式\t架势\n嫁装\t嫁妆\n简炼\t简练\n骄奢淫佚\t骄奢淫逸\n脚门\t角门\n狡滑\t狡猾\n脚根\t脚跟\n叫化子\t叫花子\n精采\t精彩\n鸠合\t纠合\n鸠集\t纠集\n脚色\t角色\n刻期\t克期\n刻日\t克日\n刻划\t刻画\n阔老\t阔佬\n蓝缕\t褴褛\n烂缦\t烂漫\n烂熳\t烂漫\n狼籍\t狼藉\n狼头\t榔头\n累坠\t累赘\n黎黑\t黧黑\n联贯\t连贯\n联接\t连接\n联绵\t连绵\n联缀\t连缀\n连袂\t联袂\n连翩\t联翩\n踉蹡\t踉跄\n嘹喨\t嘹亮\n撩乱\t缭乱\n零丁\t伶仃\n囹圉\t囹圄\n蹓跶\t溜达\n留连\t流连\n喽罗\t喽啰\n卤莽\t鲁莽\n录象\t录像\n录相\t录像\n落腮胡子\t络腮胡子\n落漠\t落寞\n落莫\t落寞\n痲痹\t麻痹\n痲风\t麻风\n痲疹\t麻疹\n蚂蜂\t马蜂\n马糊\t马虎\n门坎\t门槛\n糜费\t靡费\n绵联\t绵连\n摹仿\t模仿\n模胡\t模糊\n摹拟\t模拟\n模写\t摹写\n磨擦\t摩擦\n磨拳擦掌\t摩拳擦掌\n魔难\t磨难\n眽眽\t脉脉\n谋画\t谋划\n那末\t那么\n内哄\t内讧\n凝炼\t凝练\n牛崽裤\t牛仔裤\n钮扣\t纽扣\n掱手\t扒手\n蟠根错节\t盘根错节\n盘据\t盘踞\n蟠踞\t盘踞\n蟠据\t盘踞\n蟠曲\t盘曲\n盘陁\t盘陀\n盘石\t磐石\n蟠石\t磐石\n盘跚\t蹒跚\n旁皇\t彷徨\n披星带月\t披星戴月\n疲塌\t疲沓\n飘泊\t漂泊\n飘流\t漂流\n漂零\t飘零\n飘飖\t飘摇\n平空\t凭空\n牵联\t牵连\n蕉萃\t憔悴\n清彻\t清澈\n情素\t情愫\n惓惓\t拳拳\n劝戒\t劝诫\n热呼呼\t热乎乎\n热呼\t热乎\n热中\t热衷\n人材\t人才\n日蚀\t日食\n入坐\t入座\n色采\t色彩\n杀一警百\t杀一儆百\n沙鱼\t鲨鱼\n山查\t山楂\n舢舨\t舢板\n梢公\t艄公\n奢糜\t奢靡\n伸雪\t申雪\n神彩\t神采\n湿渌渌\t湿漉漉\n十锦\t什锦\n收伏\t收服\n首坐\t首座\n书柬\t书简\n思惟\t思维\n死心踏地\t死心塌地\n塌实\t踏实\n菾菜\t甜菜\n挺而走险\t铤而走险\n透澈\t透彻\n图象\t图像\n推委\t推诿\n玩艺儿\t玩意儿\n委过\t诿过\n污七八糟\t乌七八糟\n无动于中\t无动于衷\n无宁\t毋宁\n无庸\t毋庸\n五采缤纷\t五彩缤纷\n五痨七伤\t五劳七伤\n瘜肉\t息肉\n希罕\t稀罕\n希奇\t稀奇\n希少\t稀少\n希世\t稀世\n希有\t稀有\n噏动\t翕动\n洗炼\t洗练\n贤慧\t贤惠\n香纯\t香醇\n香菰\t香菇\n像貌\t相貌\n萧洒\t潇洒\n小题大作\t小题大做\n卸傤\t卸载\n信口开合\t信口开河\n惺松\t惺忪\n秀外惠中\t秀外慧中\n叙文\t序文\n叙言\t序言\n训戒\t训诫\n压伏\t压服\n压韵\t押韵\n雅片\t鸦片\n洋琴\t扬琴\n要末\t要么\n夜消\t夜宵\n一槌定音\t一锤定音\n一古脑儿\t一股脑儿\n衣衿\t衣襟\n衣著\t衣着\n义无返顾\t义无反顾\n霪雨\t淫雨\n赢余\t盈余\n影象\t影像\n余辉\t余晖\n鱼具\t渔具\n鱼网\t渔网\n预会\t与会\n预闻\t与闻\n御手\t驭手\n豫备\t预备\n元来\t原来\n元煤\t原煤\n源源本本\t原原本本\n元元本本\t原原本本\n原故\t缘故\n原由\t缘由\n月蚀\t月食\n月芽\t月牙\n云豆\t芸豆\n杂遝\t杂沓\n再接再砺\t再接再厉\n斩新\t崭新\n展转\t辗转\n颤栗\t战栗\n帐本\t账本\n折衷\t折中\n这末\t这么\n正经八摆\t正经八百\n脂麻\t芝麻\n支解\t肢解\n枝解\t肢解\n直捷了当\t直截了当\n直接了当\t直截了当\n指手划脚\t指手画脚\n赒济\t周济\n转游\t转悠\n装璜\t装潢\n姿式\t姿势\n子细\t仔细\n自各儿\t自个儿\n左证\t佐证\n安份守己\t安分守己\n暗度陈仓\t暗渡陈仓\n把势\t把式\n班配\t般配\n棒锤\t棒槌\n棒棰\t棒槌\n暴光\t曝光\n报导\t报道\n悲忿\t悲愤\n背理\t悖理\n比画\t比划\n笔心\t笔芯\n荜路蓝缕\t筚路蓝缕\n辨白\t辩白\n辩辞\t辩词\n波浪鼓\t拨浪鼓\n泼浪鼓\t拨浪鼓\n部份\t部分\n菜子\t菜籽\n仓惶\t仓皇\n仓黄\t仓皇\n仓遑\t仓皇\n策画\t策划\n常年累月\t长年累月\n唱工\t唱功\n潮呼呼\t潮乎乎\n潮忽忽\t潮乎乎\n撤消\t撤销\n承上起下\t承上启下\n吃里扒外\t吃里爬外\n踟躇\t踟蹰\n串连\t串联\n辞汇\t词汇\n词令\t辞令\n搭拉\t耷拉\n答理\t搭理\n哒哒\t嗒嗒\n搭裢\t褡裢\n搭连\t褡裢\n褡连\t褡裢\n褡联\t褡裢\n打冷颤\t打冷战\n大放厥辞\t大放厥词\n铛铛\t当当\n当做\t当作\n捣腾\t倒腾\n悼辞\t悼词\n得意扬扬\t得意洋洋\n灯心\t灯芯\n滴里嘟噜\t嘀里嘟噜\n掉包\t调包\n钉梢\t盯梢\n丢三拉四\t丢三落四\n掉换\t调换\n东不拉\t冬不拉\n遁辞\t遁词\n哆唆\t哆嗦\n峨嵋山\t峨眉山\n发楞\t发愣\n翻然醒悟\t幡然醒悟\n反覆\t反复\n忿恨\t愤恨\n忿怒\t愤怒\n夫倡妇随\t夫唱妇随\n浮图\t浮屠\n辐凑\t辐辏\n福份\t福分\n俯首贴耳\t俯首帖耳\n赋与\t赋予\n夹肢窝\t胳肢窝\n格登\t咯噔\n根柢\t根底\n梗咽\t哽咽\n宫庭\t宫廷\n钩勒\t勾勒\n勾针\t钩针\n够戗\t够呛\n孤另另\t孤零零\n孤伶伶\t孤零零\n轱轳\t轱辘\n毂辘\t轱辘\n固步自封\t故步自封\n故技\t故伎\n锢疾\t痼疾\n固疾\t痼疾\n刮刮叫\t呱呱叫\n呵腰\t哈腰\n寒颤\t寒战\n嚎啕\t号啕\n号咷\t号啕\n嚎咷\t号啕\n好高务远\t好高骛远\n和事老\t和事佬\n贺辞\t贺词\n黑鼓隆咚\t黑咕隆咚\n黑古龙冬\t黑咕隆咚\n黑鸦鸦\t黑压压\n轰堂大笑\t哄堂大笑\n轰笑\t哄笑\n宏亮\t洪亮\n呼嗤\t呼哧\n呼蚩\t呼哧\n呼吃\t呼哧\n花狸狐哨\t花里胡哨\n花梢\t花哨\n花稍\t花哨\n花消\t花销\n黄历\t皇历\n混身\t浑身\n浑沌\t混沌\n辑逸\t辑佚\n给与\t给予\n记录片\t纪录片\n记要\t纪要\n趼子\t茧子\n交待\t交代\n脚鸭子\t脚丫子\n脚指\t脚趾\n叫真\t较真\n菁华\t精华\n警省\t警醒\n酒钟\t酒盅\n倔犟\t倔强\n开消\t开销\n砍大山\t侃大山\n看做\t看作\n夸大其辞\t夸大其词\n宽洪大量\t宽宏大量\n老趼\t老茧\n乐和和\t乐呵呵\n乐孜孜\t乐滋滋\n利害 厉害\n伶牙利齿\t伶牙俐齿\n流言飞语\t流言蜚语\n蹓弯儿\t遛弯儿\n乱烘烘\t乱哄哄\n罗纹\t螺纹\n慢道\t漫道\n慢说\t漫说\n毛骨耸然\t毛骨悚然\n毛骨竦然\t毛骨悚然\n冒然\t贸然\n棉子\t棉籽\n藐小\t渺小\n渺视\t藐视\n渺远\t邈远\n溟溟\t冥冥\n摸棱两可\t模棱两可\n秣马利兵\t秣马厉兵\n秣马砺兵\t秣马厉兵\n木犀\t木樨\n闹轰轰\t闹哄哄\n闹烘烘\t闹哄哄\n粘稠\t黏稠\n粘糊\t黏糊\n粘土\t黏土\n粘性\t黏性\n粘液\t黏液\n念道\t念叨\n暖呼呼\t暖乎乎\n扒犁\t爬犁\n判辞\t判词\n皮簧\t皮黄\n慓悍\t剽悍\n飘渺\t缥缈\n漂渺\t缥缈\n飘眇\t缥缈\n飘邈\t缥缈\n凭白无故\t平白无故\n匍伏\t匍匐\n起程\t启程\n启锚\t起锚\n起迄\t起讫\n气门心\t气门芯\n牵就\t迁就\n遣辞\t遣词\n枪枝\t枪支\n情份\t情分\n屈伏\t屈服\n取销\t取消\n雀瘢\t雀斑\n热剌剌\t热辣辣\n如雷灌耳\t如雷贯耳\n散逸\t散佚\n沙锅\t砂锅\n沙壶\t砂壶\n沙浆\t砂浆\n沙糖\t砂糖\n杀风景\t煞风景\n杀尾\t煞尾\n刹时\t霎时\n山颠\t山巅\n扇风点火\t煽风点火\n闪烁其辞\t闪烁其词\n上方宝剑\t尚方宝剑\n深醒\t深省\n甚么\t什么\n神甫\t神父\n省分\t省份\n拾遗补阙\t拾遗补缺\n士女画\t仕女画\n视阈\t视域\n誓辞\t誓词\n授与\t授予\n摔交\t摔跤\n水份\t水分\n水长船高\t水涨船高\n思辩\t思辨\n死气白赖\t死乞白赖\n宿愿\t夙愿\n夙来\t素来\n夙敌\t宿敌\n夙儒\t宿儒\n夙怨\t宿怨\n梯己 体己\n题辞\t题词\n俶傥\t倜傥\n瞳人\t瞳仁\n产玲\t产龄\n退色\t褪色\n托咐\t托付\n顽耍\t玩耍\n玩皮\t顽皮\n惟独\t唯独\n惟恐\t唯恐\n惟利是图\t唯利是图\n惟命是从\t唯命是从\n惟其\t唯其\n惟我独尊\t唯我独尊\n惟一\t唯一\n萎顿\t委顿\n委宛\t委婉\n委罪\t诿罪\n委靡\t萎靡\n委谢\t萎谢\n文彩\t文采\n无精打彩\t无精打采\n无尚\t无上\n欷歔\t唏嘘\n喜孜孜\t喜滋滋\n陷井\t陷阱\n项练\t项链\n销歇\t消歇\n消魂\t销魂\n兴高彩烈\t兴高采烈\n雄纠纠\t雄赳赳\n旋涡\t漩涡\n薰陶\t熏陶\n丫鬟\t丫环\n压宝\t押宝\n哑吧\t哑巴\n哑叭\t哑巴\n言不由中\t言不由衷\n一倡百和\t一唱百和\n一蹋糊涂\t一塌糊涂\n一榻糊涂\t一塌糊涂\n一相情愿\t一厢情愿\n引伸\t引申\n硬梆梆\t硬邦邦\n硬帮帮\t硬邦邦\n渔汛\t鱼汛\n鱼鼓\t渔鼓\n约莫\t约摸\n殒落\t陨落\n在坐\t在座\n糟踏\t糟蹋\n糟塌\t糟蹋\n张惶\t张皇\n照像\t照相\n珍羞\t珍馐\n真象\t真相\n枝梧\t支吾\n枝捂\t支吾\n装聋做哑\t装聋作哑\n妆束\t装束\n装做\t装作\n子畜\t仔畜\n子猪\t仔猪\n子粒\t籽粒\n子棉\t籽棉\n子实\t籽实\n走露\t走漏\n做弊\t作弊\n做美\t作美\n做弄\t作弄\n做声\t作声\n做秀\t作秀\n座落\t坐落\n坐次\t座次\n坐位\t座位\n旁证博引 旁征博引\n谈笑风声 谈笑风生\n美仑美幻 美轮美奂\n坐阵 坐镇\n不径而走 不胫而走\n飘亮  漂亮\n青纯  清纯\n体晾 体谅\n发杨广大 发扬光大\n浪废水 浪费水\n通货膨涨 通货膨胀\n迫不急待 迫不及待\n堵注  赌注"
  },
  {
    "path": "examples/other/ngram_lm/s0/data/text_correct.txt",
    "content": "少先队员因该为老人让坐\n祛痘印可以吗？有效果吗？\n不知这款牛奶口感怎样？ 小孩子喝行吗！\n是转基因油?\n我家宝宝13斤用多大码的\n会起坨吗？\n请问给送上楼吗？\n亲是送赁上门吗\n送货时候有外包装没有还是直接发货过来\n会不会有坏的？\n这个米煮粥好还煮饭好吃\n有送的马克杯吗？\n这纸尿裤分男孩女孩使用吗\n买的路由器老是断网，拔了跳过路由器就可以用了\n能泡开不？辣度几\n请问这个米蒸出来是一粒一粒的还是一坨一坨的？\n水和其他商品一样送货上门，还是自提呀？\n快两个月的孩子 要穿什么码的\n买回来会不会过期？\n洗的还干净把吧\n路由器怎么样啊，掉线严重吗？\n你好这米是五斤还是十斤\n收安费不\n给送开果器吗\n这纸好用吗？我看有不少的差评\n自用好用吗\n请问袜子穿久了会往下掉吗？\n每一卷是独立包装的吗？\n这个火龙果口味怎么样？甜不甜？\n买这个送红杯吗？\n一袋子多少斤\n这款拉拉裤有味道吗？超市买的没有味道，不知道这个怎么样\n我想问下拉拉裤上面那个贴的用来干嘛的，怎么用\n这里边有没有枣核\n玫瑰和薰衣草哪个好闻\n这个冰糖质量怎么样，有杂质吗\n倒水的时候漏吗\n请问大家，这个水壶烧出来的水有异味吗？因为给宝宝用所以很在意，谢谢大家\n这米煮出来糯吗？\n这在款子好用吗？有香味吗？\n到底是棉花的材质还是化纤的无纺布啊 求问？\n我用360手机能充电几次\n亲这纸好用吗？值得买吗？\n24瓶？还是12瓶\n是否是真的纸？\n适用机洗吗?\n好吃不好吃啊\n真的好用吗？我也想买 \n你们拿到是什么版本的\n这水和超市一样吗？质量保证吗？\n可以丢进马桶冲吗？\n纸会不会粗？\n这个翠的还不是不催的呀。。没有吃的那种不脆\n这个好用吗\n这纸有香味的吗？\n是最近的生产日期吗\n赠品是什么呀\n这是两瓶还是一瓶的价格？\n请问这是硬壳还是软壳？\n亲，苹果收到后有坏的吗？\n适合两人用吗\n这个直接喝好不好喝   还是要热一下\n纸有木有刺鼻气味？\n酸不酸？？？\n这啤好渴吗?\n跟安慕希哪个比较好喝？\n好用么，主要是带宝宝出去玩的时候用的多？\n刚出生的宝宝用什么码？\n能当洗手液吗？\n是不是很小包的那一种？50块有24包便宜的有点不敢相信\n好用吗，会不会起会不会起坨？\n这个口可以直接放饮水机上用吗？\n这种纸掉粉末吗\n手机好用吗？会卡吗\n开盖里面是拉环的吗？\n这个电池真的需要一直换吗？\n好用吗？是不是正品？\n请问有尿显吗\n容易发烫吗\n苹果有腊吗\n这油有这么好吗？不是过期的吧\n这个夏天用会不会红屁股？透气性好吗\n你好。 我想问下这个是尿不湿吗 ？\n这奶为啥这么便宜？\n你们买的酱油会没有颜色吗，像水一样，看着都没胃口\n这个是机诜，还是手洗\n这个卫生巾带香味吗？\n这种洗发水好用吗\n有餡嗎？好不好吃\n纸质不会好差吗？\n亲们，此米是真空包装吗？\n是软毛的吗？！！\n请问大家德运牌子的好喝还是安佳的？\n这纸好用吗，薄嘛\n这壶保温吗\n这个威露士货到了就是跟图片上的一样吗？只要是图片上显示的都有吗？\n你们买的牛奶是最近日期吗\n这个除菌液，是单独放在滚筒洗衣机除菌液格，还是与洗衣液混合放在洗衣液格？\n请问你们的三只松鼠寄回来的时候是用袋子装着的吗\n1kg是不是两斤？\n洗衣皂怎么样啊，味道重吗，用之后好不好清洗啊。\n我要请问你这个是不是那个拉拉裤吗？这个花纹是不是拉拉裤？\n好多人都说小米运动升级后手环就连不上了，你们有没有这种情况？\n这部手机运行速度快不快？\n新生儿可以用吗 抽一张会带出来很多张吗\n洗后有香味吗\n体验装有多少片\n银装怎么样？会漏尿吗？你们都是多久换一次的？？（我家大概2-3个小时左右，宝宝醒一回换一次）\n声音大吗？好用不？\n抽纸有味吗\n苹果好吃吗？打过蜡吗？是不是坏的很多？\n70g和80g得区别是啥？\n袋装的和瓶装的洗衣液是一样的么？\n噪音很大吗\n烧出来的水会不会很多一块一块的东西\n这个吹风真心好用吗？我今晚下单什么时候到\n请问各位宝妈 这个乳垫的背胶粘吗\nM号的你们给宝宝用到多大啊？几个月？我家宝宝3个月5㎏重，用花王的M号觉得小了。不知道这个怎么样？\n这个喝了能找到女朋友吗\n这袜子耐不耐穿\n请问好用么  是正品么\n怎么储藏 我买了两天在常温阴凉处放着下层有些化了 需要放冰箱冷冻吗\n这批苏打水是否有股消毒水的味道？\n质量怎么样，看到那么多差评，我不敢买了。\n会不会有烂的\n为什么我买的用完之后没香味\n甜吗？？？？\n我看到评论里的差评说大米里有虫，是真的吗？\n要放冰箱冷藏吗\n好不好吃啊\n这油怎么样   炒菜香不香\n这纸擦手时有屑吗？\n是正品的吗？\n好用吗\n这个特浓的苦不苦\n这个好用吗？\n米里真的有虫吗\n是金装的吗？\n双内胆有什么区别，两个一样的吗？\n请问这款水可以降尿酸吗？\n好用吗这个\n购物袋结实吗，能放重东西吗\n你好，请问这款可以剃头发刮光头吗\n这个纸巾质量如何？好用吗？\n好用吗？小孩子喜欢吗？\n亲。煮面时会糊锅不\n包邮吗运费多少\n会一抽就两三张一起抽起来吗？\n一箱几桶油呀\n这个吹风机分冷风和热风吗\n发什么快递呢\n请问一下，有些枸杞说是不要洗，你们的是否建议洗呢？\n请问纸有异味吗？我以前买过一箱就是这个居然有异味。\n这是6个么  怎么觉得有好多\n我买的荣耀10横滑home键进入后台这个操作成功率特别低，你们也是这样吗？\n你们的有塑料味吗，机械的\n小米路由器真心说的有这么差吗\n请问大家这款刮的干净吗？谢谢\n会有塑料味吗\n质量真的很差吗？不敢买\n这纸有气味吗\n我买两箱怎么要运费\n这个标准果好吃吗，酸不酸\n稀吗？是不是有种兑了水的感觉？\n威露士和滴露的消毒液哪个更好用呢？\n曰期是几月份的\n手机容易折弯吗？\n我家宝宝25斤XL会紧吗？\n这款200克一箱的纸张和10卷手提的价格相差那么多 质量一样吗？\n豆浆可以打吗\n电量有百分比吗\n用快递送过来瓶子会不会打破\n是三相电吗，有空调摇控器吧\n拿它送人，有问题吗？？\n安幕希好喝吗？\n这款纸尿裤好用吗？和尤妮佳比较哪个好用些？\n2层厚吗？是不是一到水就烂了\n为什么我宝宝拉粑粑后面总是漏出来我已经贴的很牢了，10斤的宝宝用S号也不小啊你们用了没这种情况吗？\n这个产品好用吗？\n刷毛柔软度咋样，这么便宜，会不会是很小个的\n会不会有过敏的情况呀\n请问是辣条吗\n这种米只能煮粥不能煮饭吗\n可以开袋即食吗？\n这米好吃吗？\n这个充电宝充满电需要多久\n这个奶开了可以保质喝两天吗\n这种薰衣草的洗衣液怎么样\n你们的小米六边框掉漆了吗？？？\n这个是机洗用还是手洗用的啊\n厚度怎么样、起球吗感谢大哥大姐们\n这个好喝还是康师傅红茶好喝\n这种洁面膏会不会过敏，我上次用的火山岩冰感洁面啫喱对那种过敏，但听别人说那种稀的本来就特别容易过敏，不知道这种洁面膏会不会过敏！\n这杯那么多差评，是真的吗，吓得我都不敢买了\n枣是免洗的吗？\n这个尿不湿尿过会起坨吗\n感觉和苏菲比哪个更好用呢？\n煮出来的饭香吗？\n你好！请问这个水壶烧水开了是自动切电吗？\n这个跟 原木纯品 那个啥区别？不是原木纸浆做的？\n能放冰箱吗\n纸有味道吗？\n2016全国高考卷答题模板\n2016全国大考卷答题模板\n2016全国低考卷答题模板\n床前明月光，疑是地上霜\n床前星星光，疑是地上霜\n床前白月光，疑是地上霜\n落霞与孤鹜齐飞，秋水共长天一色\n落霞与孤鹜齐跑，秋水共长天一色\n落霞与孤鹜双飞，秋水共长天一色\n众里寻他千百度，蓦然回首，那人却在，灯火阑珊处\n众里寻她千百度，蓦然回首，那人却在，灯火阑珊处\n众里寻ta千百度，蓦然回首，那人却在，灯火阑珊处\n吸烟的人容*得癌症\n就只听着我*妈所说的话，\n就接受环境污*用化肥和农药，\n是或者接受环境污染用化肥和农药，\n现在的香港比从前的*荣很多。\n现在的香港比*前的饭荣很多。\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/local/build_zh_lm.sh",
    "content": "#!/bin/bash\nset -e\n\nstage=0\nstop_stage=100\n\norder=5\nmem=80%\nprune=0\na=22\nq=8\nb=8\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nif [ $# != 3 ]; then\n    echo \"$0 token_type exp/text exp/text.arpa\"\n    echo $@\n    exit 1\nfi\n\n# char or word\ntype=$1\ntext=$2\narpa=$3\n\nif [ $stage -le 0 ] && [ $stop_stage -ge 0 ];then\n    # text tn & wordseg preprocess\n    echo \"process text.\"\n    python3 ${MAIN_ROOT}/utils/zh_tn.py --token_type ${type} ${text} ${text}.${type}.tn\nfi\n\nif [ $stage -le 1 ] && [ $stop_stage -ge 1 ];then\n    # train ngram lm\n    echo \"build lm.\"\n    bash ${MAIN_ROOT}/utils/ngram_train.sh --order ${order} --mem ${mem} --prune \"${prune}\" ${text}.${type}.tn ${arpa}\nfi"
  },
  {
    "path": "examples/other/ngram_lm/s0/local/download_lm_zh.sh",
    "content": "#! /usr/bin/env bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL='https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm'\nMD5=\"29e02312deb2e59b3c8686c7966d4fe3\"\nTARGET=${DIR}/zh_giga.no_cna_cmn.prune01244.klm\n\n\nif [ -e $TARGET ];then\n    echo \"already have lm\"\n    exit 0;\nfi\n\necho \"Download language model ...\"\ndownload $URL $MD5 $TARGET\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/local/kenlm_score_test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\nimport time\n\nimport jieba\nimport kenlm\n\nlanguage_model_path = sys.argv[1]\nassert os.path.exists(language_model_path)\n\nstart = time.time()\nmodel = kenlm.Model(language_model_path)\nprint(f\"load kenLM cost: {time.time() - start}s\")\n\nsentence = '盘点不怕被税的海淘网站❗️海淘向来便宜又保真！'\nsentence_char_split = ' '.join(list(sentence))\nsentence_word_split = ' '.join(jieba.lcut(sentence))\n\n\ndef test_score():\n    print('Loaded language model: %s' % language_model_path)\n\n    print(sentence)\n    print(model.score(sentence))\n    print(list(model.full_scores(sentence)))\n    for i, v in enumerate(model.full_scores(sentence)):\n        print(i, v)\n\n    print(sentence_char_split)\n    print(model.score(sentence_char_split))\n    print(list(model.full_scores(sentence_char_split)))\n    split_size = 0\n    for i, v in enumerate(model.full_scores(sentence_char_split)):\n        print(i, v)\n        split_size += 1\n    assert split_size == len(\n        sentence_char_split.split()) + 1, \"error split size.\"\n\n    print(sentence_word_split)\n    print(model.score(sentence_word_split))\n    print(list(model.full_scores(sentence_word_split)))\n    for i, v in enumerate(model.full_scores(sentence_word_split)):\n        print(i, v)\n\n\ndef test_full_scores_chars():\n    print('Loaded language model: %s' % language_model_path)\n    print(sentence_char_split)\n    # Show scores and n-gram matches\n    words = ['<s>'] + list(sentence) + ['</s>']\n    for i, (prob, length,\n            oov) in enumerate(model.full_scores(sentence_char_split)):\n        print('{0} {1}: {2}'.format(prob, length, ' '.join(words[i + 2 - length:\n                                                                 i + 2])))\n        if oov:\n            print('\\t\"{0}\" is an OOV'.format(words[i + 1]))\n\n    print(\"-\" * 42)\n    # Find out-of-vocabulary words\n    oov = []\n    for w in words:\n        if w not in model:\n            print('\"{0}\" is an OOV'.format(w))\n            oov.append(w)\n    assert oov == [\"❗\", \"️\", \"！\"], 'error oov'\n\n\ndef test_full_scores_words():\n    print('Loaded language model: %s' % language_model_path)\n    print(sentence_word_split)\n    # Show scores and n-gram matches\n    words = ['<s>'] + sentence_word_split.split() + ['</s>']\n    for i, (prob, length,\n            oov) in enumerate(model.full_scores(sentence_word_split)):\n        print('{0} {1}: {2}'.format(prob, length, ' '.join(words[i + 2 - length:\n                                                                 i + 2])))\n        if oov:\n            print('\\t\"{0}\" is an OOV'.format(words[i + 1]))\n\n    print(\"-\" * 42)\n    # Find out-of-vocabulary words\n    oov = []\n    for w in words:\n        if w not in model:\n            print('\"{0}\" is an OOV'.format(w))\n            oov.append(w)\n    # zh_giga.no_cna_cmn.prune01244.klm is chinese character LM \n    assert oov == [\"盘点\", \"不怕\", \"网站\", \"❗\", \"️\", \"海淘\", \"向来\", \"便宜\", \"保真\",\n                   \"！\"], 'error oov'\n\n\ndef test_full_scores_chars_length():\n    \"\"\"test bos eos size\"\"\"\n    print('Loaded language model: %s' % language_model_path)\n    r = list(model.full_scores(sentence_char_split))\n    n = list(model.full_scores(sentence_char_split, bos=False, eos=False))\n    print(r)\n    print(n)\n    assert len(r) == len(n) + 1\n\n    # bos=False, eos=False, input len == output len\n    print(len(n), len(sentence_char_split.split()))\n    assert len(n) == len(sentence_char_split.split())\n\n    k = list(model.full_scores(sentence_char_split, bos=False, eos=True))\n    print(k, len(k))\n\n\ndef test_ppl_sentence():\n    \"\"\"测试句子粒度的ppl得分\"\"\"\n    sentence_char_split1 = ' '.join('先救挨饿的人，然后治疗病人。')\n    sentence_char_split2 = ' '.join('先就挨饿的人，然后治疗病人。')\n    n = model.perplexity(sentence_char_split1)\n    print('1', n)\n    n = model.perplexity(sentence_char_split2)\n    print(n)\n\n    part_char_split1 = ' '.join('先救挨饿的人')\n    part_char_split2 = ' '.join('先就挨饿的人')\n    n = model.perplexity(part_char_split1)\n    print('2', n)\n    n = model.perplexity(part_char_split2)\n    print(n)\n\n    part_char_split1 = '先救挨'\n    part_char_split2 = '先就挨'\n    n1 = model.perplexity(part_char_split1)\n    print('3', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n    assert n1 == n2\n\n    part_char_split1 = '先 救 挨'\n    part_char_split2 = '先 就 挨'\n    n1 = model.perplexity(part_char_split1)\n    print('4', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n\n    part_char_split1 = '先 救 挨 饿 的 人'\n    part_char_split2 = '先 就 挨 饿 的 人'\n    n1 = model.perplexity(part_char_split1)\n    print('5', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n\n    part_char_split1 = '先 救 挨 饿 的 人 ，'\n    part_char_split2 = '先 就 挨 饿 的 人 ，'\n    n1 = model.perplexity(part_char_split1)\n    print('6', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n\n    part_char_split1 = '先 救 挨 饿 的 人 ， 然 后 治 疗 病 人'\n    part_char_split2 = '先 就 挨 饿 的 人 ， 然 后 治 疗 病 人'\n    n1 = model.perplexity(part_char_split1)\n    print('7', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n\n    part_char_split1 = '先 救 挨 饿 的 人 ， 然 后 治 疗 病 人 。'\n    part_char_split2 = '先 就 挨 饿 的 人 ， 然 后 治 疗 病 人 。'\n    n1 = model.perplexity(part_char_split1)\n    print('8', n1)\n    n2 = model.perplexity(part_char_split2)\n    print(n2)\n\n\nif __name__ == '__main__':\n    test_score()\n    test_full_scores_chars()\n    test_full_scores_words()\n    test_full_scores_chars_length()\n    test_ppl_sentence()\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=/usr/local/lib/:${LD_LIBRARY_PATH}\n"
  },
  {
    "path": "examples/other/ngram_lm/s0/requirements.txt",
    "content": "jieba>=0.39"
  },
  {
    "path": "examples/other/ngram_lm/s0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\nstage=0\nstop_stage=100\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit -1\n\npython3 -c 'import kenlm;' || { echo \"kenlm package not install!\"; exit -1; }\n\nif [ $stage -le 0 ] && [ $stop_stage -ge 0 ];then\n    # case 1, test kenlm\n    # download language model\n    bash local/download_lm_zh.sh\n    if [ $? -ne 0 ]; then\n       exit 1\n    fi\n\n    # test kenlm `score` and `full_score`\n    python local/kenlm_score_test.py data/lm/zh_giga.no_cna_cmn.prune01244.klm\nfi\n\nmkdir -p exp\ncp data/text_correct.txt exp/text\n\nif [ $stage -le 1 ] && [ $stop_stage -ge 1 ];then\n    # case 2, chinese chararctor ngram lm build\n    # output: xxx.arpa xxx.kenlm.bin\n    input=exp/text\n    token_type=char\n    lang=zh\n    order=5\n    prune=\"0 1 2 4 4\"\n    a=22\n    q=8\n    b=8\n    output=${input}_${lang}_${token_type}_o${order}_p${prune// /_}_a${a}_q${q}_b${b}.arpa\n    echo \"build ${token_type} lm.\"\n    bash local/build_zh_lm.sh --order ${order} --prune \"${prune}\" --a ${a} --q ${a} --b ${b} ${token_type} ${input} ${output}\nfi\n\nif [ $stage -le 2 ] && [ $stop_stage -ge 2 ];then\n    # case 2, chinese chararctor ngram lm build\n    # output: xxx.arpa xxx.kenlm.bin\n    input=exp/text\n    token_type=word\n    lang=zh\n    order=3\n    prune=\"0 0 0\"\n    a=22\n    q=8\n    b=8\n    output=${input}_${lang}_${token_type}_o${order}_p${prune// /_}_a${a}_q${q}_b${b}.arpa\n    echo \"build ${token_type} lm.\"\n    bash local/build_zh_lm.sh --order ${order} --prune \"${prune}\" --a ${a} --q ${a} --b ${b} ${token_type} ${input} ${output}\nfi\n"
  },
  {
    "path": "examples/other/punctuation_restoration/README.md",
    "content": "# Punctation Restoration\n\nPlease using [PaddleSpeechTask](https://github.com/745165806/PaddleSpeechTask) to do this task.\n"
  },
  {
    "path": "examples/other/rhy/README.md",
    "content": "# Prosody Prediction with CSMSC and AISHELL-3\n\n## Get Started\n### Data Preprocessing\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Model Training\n```bash\n./run.sh --stage 1 --stop-stage 1\n```\n### Testing\n```bash\n./run.sh --stage 2 --stop-stage 2\n```\n### Prosody Prediction\n```bash\n./run.sh --stage 3 --stop-stage 3\n```\n## Pretrained Model\nThe pretrained model can be downloaded here:\n\n[ernie-1.0_aishellcsmsc_ckpt_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/rhy_predict/ernie-1.0_aishellcsmsc_ckpt_1.3.0.zip)\n\nAnd you should put it into `exp/${YOUREXP}/checkpoints` folder.\n\n## Rhythm mapping\nFour punctuation marks are used to denote the rhythm marks respectively:\n|ryh_token|csmsc|aishll3|\n|:---: |:---: |:---: |\n|%|#1|%|\n|`|#2||\n|~|#3||\n|$|#4|$|\n\n## Prediction Results\n|       |  #1  |  #2 |  #3  |  #4  |\n|:-----:|:-----:|:-----:|:-----:|:-----:|  \n|Precision  |0.90  |0.66  |0.91  |0.90|\n|Recall     |0.92  |0.62  |0.83  |0.85|\n|F1         |0.91  |0.64  |0.87  |0.87|\n"
  },
  {
    "path": "examples/other/rhy/conf/default.yaml",
    "content": "###########################################################\n#                       DATA SETTING                      #\n###########################################################\ndataset_type: Ernie\ntrain_path: data/train.txt\ndev_path: data/dev.txt\ntest_path: data/test.txt\nbatch_size: 64\nnum_workers: 2\ndata_params: \n    pretrained_token: ernie-1.0\n    punc_path: data/rhy_token\n    seq_len: 100\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel_type: ErnieLinear\nmodel:\n    pretrained_token: ernie-1.0\n    num_classes: 5\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer_params:\n    weight_decay: 1.0e-6               # weight decay coefficient.\n\nscheduler_params:\n    learning_rate: 1.0e-5               # learning rate.\n    gamma: 0.9999                          # scheduler gamma must between(0.0, 1.0) and closer to 1.0 is better.\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 20\nnum_snapshots: 5\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/other/rhy/data/rhy_token",
    "content": "%\n`\n~\n$"
  },
  {
    "path": "examples/other/rhy/local/data.sh",
    "content": "#!/bin/bash\n\nif [ ! -f 000001-010000.txt ]; then\n    wget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/rhy_predict/000001-010000.txt\nfi\n\nif [ ! -f label_train-set.txt ]; then\n    wget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/rhy_predict/label_train-set.txt\nfi\n\n\naishell_data=$1\ncsmsc_data=$2\nprocessed_path=$3\n\npython3 ./local/pre_for_sp_csmsc.py \\\n    --data=${csmsc_data} \\\n    --processed_path=${processed_path}\n\npython3 ./local/pre_for_sp_aishell.py \\\n    --data=${aishell_data} \\\n    --processed_path=${processed_path}\n\n\necho \"Finish data preparation.\"\nexit 0\n"
  },
  {
    "path": "examples/other/rhy/local/pre_for_sp_aishell.py",
    "content": "#!/usr/bin/env python3\nimport argparse\nimport os\nimport re\n\n# This is the replacement for rhythm labels to predict.\n# 韵律标签的代替\nreplace_ = {\"#1\": \"%\", \"#2\": \"`\", \"#3\": \"~\", \"#4\": \"$\"}\n\n\ndef replace_rhy_with_punc(line):\n    # r'[：、，；。？！,.:;\"?!”’《》【】<=>{}()（）#&@“”^_|…\\\\]%*$', '', line)     #参考check_oov.py,\n    line = re.sub(r'[：、，；。？！,.:;\"?!’《》【】<=>{}()（）#&@“”^_|…\\\\]%*$', '', line)\n    for r in replace_.keys():\n        if r in line:\n            line = line.replace(r, replace_[r])\n    return line\n\n\ndef pre_and_write(data, file):\n    with open(file, 'a') as rf:\n        for d in data:\n            d = d.split('|')[2].strip()\n            # d = replace_rhy_with_punc(d)\n            d = ' '.join(d) + ' \\n'\n            rf.write(d)\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Train a Rhy prediction model.\")\n    parser.add_argument(\"--data\", type=str, default=\"label_train-set.txt\")\n    parser.add_argument(\n        \"--processed_path\", type=str, default=\"../data/rhy_predict\")\n    args = parser.parse_args()\n    os.makedirs(args.processed_path, exist_ok=True)\n\n    with open(args.data) as rf:\n        text = rf.readlines()[5:]\n    len_ = len(text)\n    lens = [int(len_ * 0.9), int(len_ * 0.05), int(len_ * 0.05)]\n    files = ['train.txt', 'test.txt', 'dev.txt']\n\n    i = 0\n    for l_, file in zip(lens, files):\n        file = os.path.join(args.processed_path, file)\n        pre_and_write(text[i:i + l_], file)\n        i = i + l_\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/rhy/local/pre_for_sp_csmsc.py",
    "content": "#!/usr/bin/env python3\nimport argparse\nimport os\nimport re\n\nreplace_ = {\"#1\": \"%\", \"#2\": \"`\", \"#3\": \"~\", \"#4\": \"$\"}\n\n\ndef replace_rhy_with_punc(line):\n    # r'[：、，；。？！,.:;\"?!”’《》【】<=>{}()（）#&@“”^_|…\\\\]%*$', '', line)     #参考check_oov.py,\n    line = re.sub(r'^$\\*%', '', line)\n    for r in replace_.keys():\n        if r in line:\n            line = line.replace(r, replace_[r])\n    return line\n\n\ndef pre_and_write(data, file):\n    with open(file, 'w') as rf:\n        for d in data:\n            d = d.split('\\t')[1].strip()\n            d = replace_rhy_with_punc(d)\n            d = ' '.join(d) + ' \\n'\n            rf.write(d)\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Train a Rhy prediction model.\")\n    parser.add_argument(\"--data\", type=str, default=\"label_train-set.txt\")\n    parser.add_argument(\n        \"--processed_path\", type=str, default=\"../data/rhy_predict\")\n    args = parser.parse_args()\n    print(args.data, args.processed_path)\n    os.makedirs(args.processed_path, exist_ok=True)\n\n    with open(args.data) as rf:\n        rf = rf.readlines()\n    text = rf[0::2]\n    len_ = len(text)\n    lens = [int(len_ * 0.9), int(len_ * 0.05), int(len_ * 0.05)]\n    files = ['train.txt', 'test.txt', 'dev.txt']\n\n    i = 0\n    for l_, file in zip(lens, files):\n        file = os.path.join(args.processed_path, file)\n        pre_and_write(text[i:i + l_], file)\n        i = i + l_\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/rhy/local/rhy_predict.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\ntext=$4\nckpt_prefix=${ckpt_name%.*}\n\npython3 ${BIN_DIR}/punc_restore.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --text=${text}\n"
  },
  {
    "path": "examples/other/rhy/local/test.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\nprint_eval=$4\n\nckpt_prefix=${ckpt_name%.*}\n\npython3 ${BIN_DIR}/test.py \\\n    --config=${config_path} \\\n    --checkpoint=${train_output_path}/checkpoints/${ckpt_name} \\\n    --print_eval=${print_eval}"
  },
  {
    "path": "examples/other/rhy/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1\n"
  },
  {
    "path": "examples/other/rhy/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=${PWD}/../../../\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nMODEL=ernie_linear\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/text/exps/${MODEL}\n"
  },
  {
    "path": "examples/other/rhy/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\ndata=data\nmkdir -p $data\n\naishell_data=label_train-set.txt\ncsmsc_data=000001-010000.txt\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_4680.pdz\ntext=我们城市的复苏有赖于他强有力的政策。\nprint_eval=false\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/data.sh ${aishell_data} ${csmsc_data} ${data}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n   CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${train_output_path} ${ckpt_name} ${print_eval} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n   CUDA_VISIBLE_DEVICES=${gpus} ./local/rhy_predict.sh ${conf_path} ${train_output_path} ${ckpt_name} ${text}|| exit -1\nfi"
  },
  {
    "path": "examples/other/spm/.gitignore",
    "content": "data\n"
  },
  {
    "path": "examples/other/spm/README.md",
    "content": "# [SentencePiece Model](https://github.com/google/sentencepiece)\n\n## Run\nTrain a `spm` model for English tokenizer.\n\n```\n. path.sh\nbash run.sh\n```\n\n## Results\n\n```\ndata/\n└── lang_char\n    ├── input.bpe\n    ├── input.decode\n    ├── input.txt\n    ├── train_unigram100.model\n    ├── train_unigram100_units.txt\n    └── train_unigram100.vocab\n\n1 directory, 6 files\n```\n\n```\nb5a230c26c61db5c36f34e503102f936  data/lang_char/input.bpe\nec5a9b24acc35469229e41256ceaf77d  data/lang_char/input.decode\nec5a9b24acc35469229e41256ceaf77d  data/lang_char/input.txt\n124bf3fe7ce3b73b1994234c15268577  data/lang_char/train_unigram100.model\n0df2488cc8eaace95eb12713facb5cf0  data/lang_char/train_unigram100_units.txt\n46360cac35c751310e8e8ffd3a034cb5  data/lang_char/train_unigram100.vocab\n```\n\n```\n==> data/lang_char/input.txt <==\nmister quilter is the apostle of the middle classes and we are glad to welcome his gospel\nnor is mister quilter's manner less interesting than his matter\nhe tells us that at this festive season of the year with christmas and roast beef looming before us similes drawn from eating and its results occur most readily to the mind\nhe has grave doubts whether sir frederick leighton's work is really greek after all and can discover in it but little of rocky ithaca\nlinnell's pictures are a sort of up guards and at em paintings and mason's exquisite idylls are as national as a jingo poem mister birket foster's landscapes smile at one much in the same way that mister carker used to flash his teeth and mister john collier gives his sitter a cheerful slap on the back before he says like a shampooer in a turkish bath next man\nit is obviously unnecessary for us to point out how luminous these criticisms are how delicate in expression\non the general principles of art mister quilter writes with equal lucidity\npainting he tells us is of a different quality to mathematics and finish in art is adding more fact\nas for etchings they are of two kinds british and foreign\nhe laments most bitterly the divorce that has been made between decorative art and what we usually call pictures makes the customary appeal to the last judgment and reminds us that in the great days of art michael angelo was the furnishing upholsterer\n\n==> data/lang_char/input.bpe <==\n▁mi ster ▁quilter ▁ is ▁the ▁a p ost le ▁o f ▁the ▁mi d d le ▁c las s es ▁ and ▁we ▁ar e ▁g l a d ▁ to ▁we l c om e ▁h is ▁g o s pe l\n▁ n or ▁ is ▁mi ster ▁quilter ' s ▁ma nne r ▁ l ess ▁in ter es t ing ▁tha n ▁h is ▁ma t ter\n▁h e ▁ t e ll s ▁us ▁tha t ▁ at ▁ t h is ▁f es t ive ▁ s e ason ▁o f ▁the ▁ y e ar ▁w ith ▁ ch r is t m a s ▁ and ▁ro a s t ▁be e f ▁ l o om ing ▁be fore ▁us ▁ s i mile s ▁d r a w n ▁f r om ▁ e at ing ▁ and ▁it s ▁re s u l t s ▁o c c ur ▁m ost ▁re a di l y ▁ to ▁the ▁ mind\n▁h e ▁ ha s ▁g r a v e ▁d o u b t s ▁w h e t h er ▁ s i r ▁f r e d er ic k ▁ l eig h to n ' s ▁w or k ▁ is ▁re all y ▁gre e k ▁a f ter ▁ all ▁ and ▁c a n ▁di s c o v er ▁in ▁it ▁b u t ▁li t t le ▁o f ▁ro ck y ▁it ha c a\n▁li nne ll ' s ▁ p ic tur es ▁ar e ▁a ▁ s or t ▁o f ▁ u p ▁g u ar d s ▁ and ▁ at ▁ em ▁painting s ▁ and ▁m ason ' s ▁ e x q u is i t e ▁ i d y ll s ▁ar e ▁a s ▁ n at ion a l ▁a s ▁a ▁ j ing o ▁ p o em ▁mi ster ▁b i r k e t ▁f o ster ' s ▁ l and s c a pe s ▁ s mile ▁ at ▁on e ▁m u ch ▁in ▁the ▁ s a m e ▁w a y ▁tha t ▁mi ster ▁c ar k er ▁us e d ▁ to ▁f las h ▁h is ▁ t e e t h ▁ and ▁mi ster ▁ j o h n ▁c o ll i er ▁g ive s ▁h is ▁ s i t ter ▁a ▁ ch e er f u l ▁ s l a p ▁on ▁the ▁b a ck ▁be fore ▁h\ne ▁ s a y s ▁li k e ▁a ▁ s ha m p o o er ▁in ▁a ▁ tur k is h ▁b at h ▁ n e x t ▁ma n\n▁it ▁ is ▁o b v i o u s l y ▁ u nne c ess ar y ▁for ▁us ▁ to ▁ p o i n t ▁o u t ▁h o w ▁ l u m i n o u s ▁the s e ▁c rit ic is m s ▁ar e ▁h o w ▁d e l ic at e ▁in ▁ e x p r ess ion\n▁on ▁the ▁g e n er a l ▁ p r i n c i p l es ▁o f ▁ar t ▁mi ster ▁quilter ▁w rit es ▁w ith ▁ e qual ▁ l u c i di t y\n▁painting ▁h e ▁ t e ll s ▁us ▁ is ▁o f ▁a ▁di f f er e n t ▁ qual i t y ▁ to ▁ma t h em at ic s ▁ and ▁f i nish ▁in ▁ar t ▁ is ▁a d d ing ▁m or e ▁f a c t\n▁a s ▁for ▁ e t ch ing s ▁the y ▁ar e ▁o f ▁ t w o ▁ k i n d s ▁b rit is h ▁ and ▁for eig n\n▁h e ▁ l a ment s ▁m ost ▁b i t ter l y ▁the ▁di v or c e ▁tha t ▁ ha s ▁be e n ▁ma d e ▁be t w e e n ▁d e c or at ive ▁ar t ▁ and ▁w ha t ▁we ▁us u all y ▁c all ▁ p ic tur es ▁ma k es ▁the ▁c u s t om ar y ▁a p pe a l ▁ to ▁the ▁ las t ▁ j u d g ment ▁ and ▁re mind s ▁us ▁tha t ▁in ▁the ▁gre at ▁d a y s ▁o f ▁ar t ▁mi c ha e l ▁a n g e l o ▁w a s ▁the ▁f ur nish ing ▁ u p h o l ster er\n\n==> data/lang_char/input.decode <==\nmister quilter is the apostle of the middle classes and we are glad to welcome his gospel\nnor is mister quilter's manner less interesting than his matter\nhe tells us that at this festive season of the year with christmas and roast beef looming before us similes drawn from eating and its results occur most readily to the mind\nhe has grave doubts whether sir frederick leighton's work is really greek after all and can discover in it but little of rocky ithaca\nlinnell's pictures are a sort of up guards and at em paintings and mason's exquisite idylls are as national as a jingo poem mister birket foster's landscapes smile at one much in the same way that mister carker used to flash his teeth and mister john collier gives his sitter a cheerful slap on the back before he says like a shampooer in a turkish bath next man\nit is obviously unnecessary for us to point out how luminous these criticisms are how delicate in expression\non the general principles of art mister quilter writes with equal lucidity\npainting he tells us is of a different quality to mathematics and finish in art is adding more fact\nas for etchings they are of two kinds british and foreign\nhe laments most bitterly the divorce that has been made between decorative art and what we usually call pictures makes the customary appeal to the last judgment and reminds us that in the great days of art michael angelo was the furnishing upholsterer\n\n\n==> data/lang_char/train_unigram100_units.txt <==\n<blank> 0\n<unk> 1\n' 2\na 3\nall 4\nand 5\nar 6\nason 7\nat 8\nb 9\n\n==> data/lang_char/train_unigram100.vocab <==\n<unk>   0\n<s>     0\n</s>    0\n▁       -2.01742\ne       -2.7203\ns       -2.82989\nt       -2.99689\nl       -3.53267\nn       -3.84935\no       -3.88229\n```\n"
  },
  {
    "path": "examples/other/spm/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n"
  },
  {
    "path": "examples/other/spm/run.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nsource path.sh\n\n\nstage=0\nstop_stage=100\n# bpemode (unigram or bpe)\nnbpe=100\nbpemode=unigram\n\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\ntrain_set=train\ndict=data/lang_char/${train_set}_${bpemode}${nbpe}_units.txt\nbpemodel=data/lang_char/${train_set}_${bpemode}${nbpe}\n\necho \"dictionary: ${dict}\"\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    ### Task dependent. You have to check non-linguistic symbols used in the corpus.\n    echo \"stage 2: Dictionary and Json Data Preparation\"\n    mkdir -p data/lang_char/\n\n    echo \"<blank> 0\" > ${dict} # 0 will be used for \"blank\" in CTC\n    echo \"<unk> 1\" >> ${dict} # <unk> must be 1\n\n    # we borrowed these code and scripts which are related bpe from ESPnet.\n    cut -f 2- -d\" \" text > data/lang_char/input.txt\n    ${MAIN_ROOT}/utils/spm_train --input=data/lang_char/input.txt --vocab_size=${nbpe} --model_type=${bpemode} --model_prefix=${bpemodel} --input_sentence_size=100000000\n    ${MAIN_ROOT}/utils/spm_encode --model=${bpemodel}.model --output_format=piece < data/lang_char/input.txt | tr ' ' '\\n' | sort | uniq | awk '{print $0 \" \" NR+1}' >> ${dict}\n    num_token=$(cat $dict | wc -l)\n    echo \"<sos/eos> $num_token\" >> $dict # <eos>\n    wc -l ${dict}\nfi\n\n${MAIN_ROOT}/utils/spm_encode --model=${bpemodel}.model --output_format=piece < data/lang_char/input.txt > data/lang_char/input.bpe\n${MAIN_ROOT}/utils/spm_decode --model=${bpemodel}.model --input_format=piece < data/lang_char/input.bpe | sed -e \"s/▁/ /g\" > data/lang_char/input.decode\n"
  },
  {
    "path": "examples/other/spm/text",
    "content": "text-1 mister quilter is the apostle of the middle classes and we are glad to welcome his gospel\ntest-2 nor is mister quilter's manner less interesting than his matter\ntest-3 he tells us that at this festive season of the year with christmas and roast beef looming before us similes drawn from eating and its results occur most readily to the mind\ntest-4 he has grave doubts whether sir frederick leighton's work is really greek after all and can discover in it but little of rocky ithaca\ntest-5 linnell's pictures are a sort of up guards and at em paintings and mason's exquisite idylls are as national as a jingo poem mister birket foster's landscapes smile at one much in the same way that mister carker used to flash his teeth and mister john collier gives his sitter a cheerful slap on the back before he says like a shampooer in a turkish bath next man\ntest-6 it is obviously unnecessary for us to point out how luminous these criticisms are how delicate in expression\ntest-7 on the general principles of art mister quilter writes with equal lucidity\ntest-8 painting he tells us is of a different quality to mathematics and finish in art is adding more fact\ntest-9 as for etchings they are of two kinds british and foreign\ntest-10 he laments most bitterly the divorce that has been made between decorative art and what we usually call pictures makes the customary appeal to the last judgment and reminds us that in the great days of art michael angelo was the furnishing upholsterer\n"
  },
  {
    "path": "examples/other/tn/README.md",
    "content": "# Text Normalization\nFor text normalization, the test data is  `data/textnorm_test_cases.txt`, we use `|` as the separator of raw_data and normed_data.\n\nWe use `CER` as an evaluation criterion.\n## Start\nRun the command below to get the results of the test.\n```bash\ncd ../../../tools\nbash extras/install_sclite.sh\ncd -\n./run.sh\n```\nThe `avg CER` of text normalization is: 0.00730093543235227\n```text\n      ,-----------------------------------------------------------------.\n      |        | # Snt  # Wrd | Corr    Sub    Del    Ins    Err  S.Err |\n      |--------+--------------+-----------------------------------------|\n      | Sum/Avg|  125    2254 | 99.4    0.1    0.5    0.2    0.8    4.8 |\n      `-----------------------------------------------------------------'\n```\n"
  },
  {
    "path": "examples/other/tn/data/textnorm_test_cases.txt",
    "content": "今天的最低气温达到-10°C.|今天的最低气温达到零下十度.\n只要有33/4的人同意，就可以通过决议。|只要有四分之三十三的人同意，就可以通过决议。\n1945年5月2日，苏联士兵在德国国会大厦上升起了胜利旗，象征着攻占柏林并战胜了纳粹德国。|一九四五年五月二日，苏联士兵在德国国会大厦上升起了胜利旗，象征着攻占柏林并战胜了纳粹德国。\n4月16日，清晨的战斗以炮击揭幕，数以千计的大炮和喀秋莎火箭炮开始炮轰德军阵地，炮击持续了数天之久。|四月十六日，清晨的战斗以炮击揭幕，数以千计的大炮和喀秋莎火箭炮开始炮轰德军阵地，炮击持续了数天之久。\n如果剩下的30.6%是过去，那么还有69.4%.|如果剩下的百分之三十点六是过去，那么还有百分之六十九点四.\n事情发生在2020/03/31的上午8:00.|事情发生在二零二零年三月三十一日的上午八点.\n警方正在找一支.22口径的手枪。|警方正在找一支零点二二口径的手枪。\n欢迎致电中国联通，北京2022年冬奥会官方合作伙伴为您服务|欢迎致电中国联通，北京二零二二年冬奥会官方合作伙伴为您服务\n充值缴费请按1，查询话费及余量请按2，跳过本次提醒请按井号键。|充值缴费请按一，查询话费及余量请按二，跳过本次提醒请按井号键。\n快速解除流量封顶请按星号键，腾讯王卡产品介绍、使用说明、特权及活动请按9，查询话费、套餐余量、积分及活动返款请按1，手机上网流量开通及取消请按2，查询本机号码及本号所使用套餐请按4，密码修改及重置请按5，紧急开机请按6，挂失请按7，查询充值记录请按8，其它自助服务及人工服务请按0|快速解除流量封顶请按星号键，腾讯王卡产品介绍、使用说明、特权及活动请按九，查询话费、套餐余量、积分及活动返款请按一，手机上网流量开通及取消请按二，查询本机号码及本号所使用套餐请按四，密码修改及重置请按五，紧急开机请按六，挂失请按七，查询充值记录请按八，其它自助服务及人工服务请按零\n智能客服助理快速查话费、查流量请按9，了解北京联通业务请按1，宽带IPTV新装、查询请按2，障碍报修请按3，充值缴费请按4，投诉建议请按5，政企业务请按7，人工服务请按0，for english severice press star key|智能客服助理快速查话费、查流量请按九，了解北京联通业务请按一，宽带IPTV新装、查询请按二，障碍报修请按三，充值缴费请按四，投诉建议请按五，政企业务请按七，人工服务请按零，for english severice press star key\n您的帐户当前可用余额为63.89元，本月消费为2.17元。您的消费、套餐余量和其它信息将以短信形式下发，请您注意查收。谢谢使用，再见！。|您的帐户当前可用余额为六十三点八九元，本月消费为二点一七元。您的消费、套餐余量和其它信息将以短信形式下发，请您注意查收。谢谢使用，再见！。\n您的帐户当前可用余额为负15.5元，本月消费为59.6元。您的消费、套餐余量和其它信息将以短信形式下发，请您注意查收。谢谢使用，再见！。|您的帐户当前可用余额为负十五点五元，本月消费为五十九点六元。您的消费、套餐余量和其它信息将以短信形式下发，请您注意查收。谢谢使用，再见！。\n尊敬的客户，您目前的话费余额为负14.60元，已低于10元，为保证您的通信畅通，请及时缴纳费用。|尊敬的客户，您目前的话费余额为负十四点六元，已低于十元，为保证您的通信畅通，请及时缴纳费用。\n您的流量已用完，为避免您产生额外费用，建议您根据需求开通一个流量包以作补充。|您的流量已用完，为避免您产生额外费用，建议您根据需求开通一个流量包以作补充。\n您可以直接说，查询话费及余量、开通流量包、缴费，您也可以说出其它需求，请问有什么可以帮您？|您可以直接说，查询话费及余量、开通流量包、缴费，您也可以说出其它需求，请问有什么可以帮您？\n您的账户当前可用余额为负36.00元，本月消费36.00元。|您的账户当前可用余额为负三十六元，本月消费三十六元。\n请问你是电话13985608526的机主吗？|请问你是电话一三九八五六零八五二六的机主吗？\n如您对处理结果不满意，可拨打中国联通集团投诉电话10015进行投诉，按本地通话费收费，返回自助服务请按井号键|如您对处理结果不满意，可拨打中国联通集团投诉电话一零零一五进行投诉，按本地通话费收费，返回自助服务请按井号键\n“26314”号VIP客服代表为您服务。|“二六三一四”号VIP客服代表为您服务。\n尊敬的5G用户，欢迎您致电中国联通|尊敬的五G用户，欢迎您致电中国联通\n首先是应用了M1芯片的iPad Pro，新款的iPad Pro支持5G，这也是苹果的第二款5G产品线。|首先是应用了M一芯片的iPad Pro，新款的iPad Pro支持五G，这也是苹果的第二款五G产品线。\n除此之外，摄像头方面再次升级，增加了前摄全新超广角摄像头，支持人物居中功能，搭配超广角可实现视频中始终让人物居中效果。|除此之外，摄像头方面再次升级，增加了前摄全新超广角摄像头，支持人物居中功能，搭配超广角可实现视频中始终让人物居中效果。\n屏幕方面，iPad Pro 12.9版本支持XDR体验的Mini-LEDS显示屏，支持HDR10、杜比视界，还支持杜比全景声。|屏幕方面，iPad Pro 十二点九版本支持XDR体验的Mini-LEDS显示屏，支持HDR十、杜比视界，还支持杜比全景声。\niPad Pro的秒控键盘这次也推出白色版本。|iPad Pro的秒控键盘这次也推出白色版本。\n售价方面，11英寸版本售价799美元起，12.9英寸售价1099美元起。|售价方面，十一英寸版本售价七百九十九美元起，十二点九英寸售价一千零九十九美元起。\n这块黄金重达324.75克|这块黄金重达三百二十四点七五克\n她出生于86年8月18日，她弟弟出生于1995年3月1日|她出生于八六年八月十八日，她弟弟出生于一九九五年三月一日\n电影中梁朝伟扮演的陈永仁的编号27149|电影中梁朝伟扮演的陈永仁的编号二七一四九\n现场有7/12的观众投出了赞成票|现场有十二分之七的观众投出了赞成票\n随便来几个价格12块5，34.5元，20.1万|随便来几个价格十二块五，三十四点五元，二十点一万\n明天有62%的概率降雨|明天有百分之六十二的概率降雨\n这是固话0421-33441122|这是固话零四二一三三四四一一二二\n这是手机+86 18544139121|这是手机八六一八五四四一三九一二一\n小王的身高是153.5cm,梦想是打篮球!我觉得有0.1%的可能性。|小王的身高是一百五十三点五厘米,梦想是打篮球!我觉得有百分之零点一的可能性。\n不管三七二十一|不管三七二十一\n九九八十一难|九九八十一难\n2018年5月23号上午10点10分|二零一八年五月二十三号上午十点十分\n10076|一零零七六\n32.68%|百分之三十二点六八\n比分测试17:16|比分测试十七比十六\n比分测试37:16|比分测试三十七比十六\n1.1|一点一\n一点一滴|一点一滴\n八九十|八九十\n1个人一定要|一个人一定要\n10000棵树|一万棵树\n1234个人|一千二百三十四个人\n35553座楼|三万五千五百五十三座楼\n15873690|一五八七三六九零\n27930122|二七九三零一二二\n85307499|八五三零七四九九\n26149787|二六一四九七八七\n15964862|一五九六四八六二\n45698723|四五六九八七二三\n48615964|四八六一五九六四\n17864589|一七八六四五八九\n123加456|一百二十三加四百五十六\n9786加3384|九千七百八十六加三千三百八十四\n发电站每天发电30029度电|发电站每天发电三万零二十九度电\n银行月交易总额七千九百零三亿元|银行月交易总额七千九百零三亿元\n深圳每月平均工资在13000元|深圳每月平均工资在一万三千元\n每月房租要交1500元|每月房租要交一千五百元\n我每月交通费用在400元左右|我每月交通费用在四百元左右\n本月开销费用是51328元|本月开销费用是五万一千三百二十八元\n如果你中了五千万元奖金会分我一半吗|如果你中了五千万元奖金会分我一半吗\n这个月工资我发了3529元|这个月工资我发了三千五百二十九元\n学会了这个技能你至少可以涨薪5000元|学会了这个技能你至少可以涨薪五千元\n我们的会议时间定在9点25分开始|我们的会议时间定在九点二十五分开始\n上课时间是8点15分请不要迟到|上课时间是八点十五分请不要迟到\n昨天你9点21分才到教室|昨天你九点二十一分才到教室\n今天是2019年1月31号|今天是二零一九年一月三十一号\n今年的除夕夜是2019年2月4号|今年的除夕夜是二零一九年二月四号\n这根水管的长度不超过35米|这根水管的长度不超过三十五米\n400米是最短的长跑距离|四百米是最短的长跑距离\n最高的撑杆跳为11米|最高的撑杆跳为十一米\n等会请在12:05请通知我|等会请在十二点零五分请通知我\n23点15分开始|二十三点十五分开始\n你生日那天我会送你999朵玫瑰|你生日那天我会送你九百九十九朵玫瑰\n给我1双鞋我可以跳96米远|给我一双鞋我可以跳九十六米远\n虽然我们的身高相差356毫米也不影响我们交往|虽然我们的身高相差三百五十六毫米也不影响我们交往\n我们班的最高总分为583分|我们班的最高总分为五百八十三分\n今天考试老师多扣了我21分|今天考试老师多扣了我二十一分\n我量过这张桌子总长为1.37米|我量过这张桌子总长为一点三七米\n乘务员身高必须超过185公分|乘务员身高必须超过一百八十五公分\n这台电脑分辨率为1024|这台电脑分辨率为一零二四\n手机价格不超过1500元|手机价格不超过一千五百元\n101.23|一百零一点二三\n123.116|一百二十三点一一六\n456.147|四百五十六点一四七\n0.1594|零点一五九四\n3.1415|三点一四一五\n0.112233|零点一一二二三三\n0.1|零点一\n40001.987|四万零一点九八七\n56.878|五十六点八七八\n0.00123|零点零零一二三\n0.0001|零点零零零一\n0.92015|零点九二零一五\n999.0001|九百九十九点零零零一\n10000.123|一万点一二三\n666.555|六百六十六点五五五\n444.789|四百四十四点七八九\n789.666|七百八十九点六六六\n0.12345|零点一二三四五\n1.05649|一点零五六四九\n环比上调1.86%|环比上调百分之一点八六\n环比分别下跌3.46%及微涨0.70%|环比分别下跌百分之三点四六及微涨百分之零点七\n单价在30000元的二手房购房个案当中|单价在三万元的二手房购房个案当中\n6月仍有7%单价在30000元的房源|六月仍有百分之七单价在三万元的房源\n最终也只是以总积分1分之差屈居第2|最终也只是以总积分一分之差屈居第二\n中新网8月29日电今日|中新网八月二十九日电今日\n自6月底呼和浩特市率先宣布取消限购后|自六月底呼和浩特市率先宣布取消限购后\n仅1个多月的时间里|仅一个多月的时间里\n除了北京上海广州深圳4个一线城市和三亚之外|除了北京上海广州深圳四个一线城市和三亚之外\n46个限购城市当中|四十六个限购城市当中\n41个已正式取消或变相放松了限购|四十一个已正式取消或变相放松了限购\n其中包括对拥有一套住房并已结清相应购房贷款的家庭|其中包括对拥有一套住房并已结清相应购房贷款的家庭\n这个后来被称为930新政策的措施|这个后来被称为九三零新政策的措施\n今年有望超三百亿美元|今年有望超三百亿美元\n就连一向看多的任志强|就连一向看多的任志强\n近期也一反常态地发表看空言论|近期也一反常态地发表看空言论\n985|九八五\n12~23|十二到二十三\n12-23|十二到二十三\n25cm²|二十五平方厘米\n25m|米\n"
  },
  {
    "path": "examples/other/tn/get_textnorm_data.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"text normalization example.\")\n    parser.add_argument(\n        \"--test-file\",\n        default=\"data/textnorm_test_cases.txt\",\n        type=str,\n        help=\"path of text normalization test file.\")\n    parser.add_argument(\n        \"--output-dir\",\n        default=\"data/textnorm\",\n        type=str,\n        help=\"directory to output.\")\n\n    args = parser.parse_args()\n    test_file = Path(args.test_file).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    raw_path = output_dir / \"text\"\n    ref_path = output_dir / \"text.ref\"\n    wf_raw = open(raw_path, \"w\")\n    wf_ref = open(ref_path, \"w\")\n\n    with open(test_file, \"r\") as rf:\n        for i, line in enumerate(rf):\n            raw_text, normed_text = line.strip().split(\"|\")\n            wf_raw.write(\"utt_\" + str(i) + \" \" + raw_text + \"\\n\")\n            wf_ref.write(\"utt_\" + str(i) + \" \" + normed_text + \"\\n\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/tn/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n"
  },
  {
    "path": "examples/other/tn/run.sh",
    "content": "#!/bin/bash\n\nsource path.sh\n\nUSE_SCLITE=true\n\n# test text normalization\necho \"Start get text normalization test data ...\"\npython3 get_textnorm_data.py --test-file=data/textnorm_test_cases.txt --output-dir=data/textnorm\necho \"Start test text normalization ...\"\npython3 test_textnorm.py --input-dir=data/textnorm --output-dir=exp/textnorm\n\n# whether use sclite to get more detail information of WER\nif [ \"$USE_SCLITE\" = true ];then\n    echo \"Start sclite textnorm ...\"\n    ${MAIN_ROOT}/tools/sctk/bin/sclite -i wsj -r ./exp/textnorm/text.ref.clean trn -h ./exp/textnorm/text.tn trn -e utf-8 -o all\nfi"
  },
  {
    "path": "examples/other/tn/test_textnorm.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport re\nfrom pathlib import Path\n\nfrom paddlespeech.t2s.frontend.zh_normalization.text_normlization import TextNormalizer\nfrom paddlespeech.t2s.utils.error_rate import char_errors\n\n\n# delete english characters\n# e.g. \"你好aBC\" -> \"你 好\"\ndef del_en_add_space(input: str):\n    output = re.sub('[a-zA-Z]', '', input)\n    output = [char + \" \" for char in output]\n    output = \"\".join(output).strip()\n    return output\n\n\ndef get_avg_cer(raw_dict, ref_dict, text_normalizer, output_dir):\n    edit_distances = []\n    ref_lens = []\n    wf_ref = open(output_dir / \"text.ref.clean\", \"w\")\n    wf_tn = open(output_dir / \"text.tn\", \"w\")\n    for text_id in raw_dict:\n        if text_id not in ref_dict:\n            continue\n        raw_text = raw_dict[text_id]\n        gt_text = ref_dict[text_id]\n        textnorm_text = text_normalizer.normalize_sentence(raw_text)\n\n        gt_text = del_en_add_space(gt_text)\n        textnorm_text = del_en_add_space(textnorm_text)\n        wf_ref.write(gt_text + \"(\" + text_id + \")\" + \"\\n\")\n        wf_tn.write(textnorm_text + \"(\" + text_id + \")\" + \"\\n\")\n        edit_distance, ref_len = char_errors(gt_text, textnorm_text)\n        edit_distances.append(edit_distance)\n        ref_lens.append(ref_len)\n\n    return sum(edit_distances) / sum(ref_lens)\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"text normalization example.\")\n    parser.add_argument(\n        \"--input-dir\",\n        default=\"data/textnorm\",\n        type=str,\n        help=\"directory to preprocessed test data.\")\n    parser.add_argument(\n        \"--output-dir\",\n        default=\"exp/textnorm\",\n        type=str,\n        help=\"directory to save textnorm results.\")\n\n    args = parser.parse_args()\n    input_dir = Path(args.input_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    assert input_dir.is_dir()\n    raw_dict, ref_dict = dict(), dict()\n    raw_path = input_dir / \"text\"\n    ref_path = input_dir / \"text.ref\"\n\n    with open(raw_path, \"r\") as rf:\n        for line in rf:\n            line = line.strip()\n            line_list = line.split(\" \")\n            text_id, raw_text = line_list[0], \" \".join(line_list[1:])\n            raw_dict[text_id] = raw_text\n    with open(ref_path, \"r\") as rf:\n        for line in rf:\n            line = line.strip()\n            line_list = line.split(\" \")\n            text_id, normed_text = line_list[0], \" \".join(line_list[1:])\n            ref_dict[text_id] = normed_text\n\n    text_normalizer = TextNormalizer()\n\n    avg_cer = get_avg_cer(raw_dict, ref_dict, text_normalizer, output_dir)\n    print(\"The avg CER of text normalization is:\", avg_cer)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/README.md",
    "content": "# Finetune your own AM based on FastSpeech2 with multi-speakers dataset.\nThis example shows how to finetune your own AM based on FastSpeech2 with multi-speakers dataset. For finetuning Chinese data, we use part of csmsc's data (top 200) and Fastspeech2 pretrained model with AISHELL-3. For finetuning English data, we use part of ljspeech's data (top 200) and Fastspeech2 pretrained model with VCTK. The example is implemented according to this [discussion](https://github.com/PaddlePaddle/PaddleSpeech/discussions/1842). Thanks to the developer for the idea.\n\nFor more information on training Fastspeech2 with AISHELL-3, You can refer [examples/aishell3/tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/tts3). For more information on training Fastspeech2 with VCTK, You can refer [examples/vctk/tts3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/tts3).\n\n\n## Prepare \n### Download Pretrained model\nAssume the path to the model is `./pretrained_models`. </br>\nIf you want to finetune Chinese pretrained model, you need to download Fastspeech2 pretrained model with AISHELL-3: [fastspeech2_aishell3_ckpt_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_1.1.0.zip) for finetuning. Download HiFiGAN pretrained model with aishell3: [hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip) for synthesis.\n\n```bash\nmkdir -p pretrained_models && cd pretrained_models\n# pretrained fastspeech2 model\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_ckpt_1.1.0.zip \nunzip fastspeech2_aishell3_ckpt_1.1.0.zip\n# pretrained hifigan model\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip\nunzip hifigan_aishell3_ckpt_0.2.0.zip\ncd ../\n```\n\n\nIf you want to finetune English pretrained model, you need to download Fastspeech2 pretrained model with VCTK: [fastspeech2_vctk_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_ckpt_1.2.0.zip) for finetuning. Download HiFiGAN pretrained model with VCTK: [hifigan_vctk_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip) for synthesis.\n\n```bash\nmkdir -p pretrained_models && cd pretrained_models\n# pretrained fastspeech2 model\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_ckpt_1.2.0.zip \nunzip fastspeech2_vctk_ckpt_1.2.0.zip\n# pretrained hifigan model\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip\nunzip hifigan_vctk_ckpt_0.2.0.zip\ncd ../\n```\n\nIf you want to finetune Chinese-English Mixed pretrained model, you need to download Fastspeech2 pretrained model with mix datasets: [fastspeech2_mix_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_1.2.0.zip) for finetuning. Download HiFiGAN pretrained model with aishell3: [hifigan_aishell3_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip) for synthesis.\n\n```bash\nmkdir -p pretrained_models && cd pretrained_models\n# pretrained fastspeech2 model\nwget https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_1.2.0.zip\nunzip fastspeech2_mix_ckpt_1.2.0.zip\n# pretrained hifigan model\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip\nunzip hifigan_aishell3_ckpt_0.2.0.zip\ncd ../\n```\n\n### Prepare your data\nAssume the path to the dataset is `./input` which contains a speaker folder. Speaker folder contains audio files (*.wav) and label file (labels.txt). The format of the audio file is wav. The format of the label file is: utt_id|pronunciation. </br>\n\nIf you want to finetune Chinese pretrained model, you need to prepare Chinese data. Chinese label example: \n```\n000001|ka2 er2 pu3 pei2 wai4 sun1 wan2 hua2 ti1\n```\n\nHere is a Chinese data example of the first 200 data of csmsc.\n\n```bash\nmkdir -p input && cd input\nwget https://paddlespeech.cdn.bcebos.com/datasets/csmsc_mini.zip\nunzip csmsc_mini.zip\ncd ../\n```\n\nIf you want to finetune English pretrained model, you need to prepare English data. English label example: \n```\nLJ001-0001|Printing, in the only sense with which we are at present concerned, differs from most if not from all the arts and crafts represented in the Exhibition\n```\n\nHere is an English data example of the first 200 data of ljspeech.\n\n```bash\nmkdir -p input && cd input\nwget https://paddlespeech.cdn.bcebos.com/datasets/ljspeech_mini.zip\nunzip ljspeech_mini.zip\ncd ../\n```\n\nIf you want to finetune Chinese-English Mixed pretrained model, you need to prepare Chinese data or English data. Here is a Chinese data example of the first 12 data of SSB0005 (the speaker of aishell3).\n\n```bash\nmkdir -p input && cd input\nwget https://paddlespeech.cdn.bcebos.com/datasets/SSB0005_mini.zip\nunzip SSB0005_mini.zip\ncd ../\n```\n\n### Download MFA tools and pretrained model\nAssume the path to the MFA tool is `./tools`. Download [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz).\n\n```bash\nmkdir -p tools && cd tools\n# mfa tool\nwget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz\ntar xvf montreal-forced-aligner_linux.tar.gz\ncp montreal-forced-aligner/lib/libpython3.6m.so.1.0 montreal-forced-aligner/lib/libpython3.6m.so\nmkdir -p aligner && cd aligner\n```\n\nIf you want to get mfa result of Chinese data, you need to download pretrained MFA models with aishell3: [aishell3_model.zip](https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/aishell3_model.zip) and unzip it.\n\n```bash\n# pretrained mfa model for Chinese data\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/aishell3_model.zip\nunzip aishell3_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/simple.lexicon\ncd ../../\n```\n\nIf you want to get mfa result of English data, you need to download pretrained MFA models with vctk: [vctk_model.zip](https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/vctk_model.zip) and unzip it.\n\n```bash\n# pretrained mfa model for English data\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/vctk_model.zip\nunzip vctk_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/cmudict-0.7b\ncd ../../\n```\n\nWhen \"Prepare\" done. The structure of the current directory is similar to the following.\n```text\n├── input\n│   ├── csmsc_mini\n│   │   ├── 000001.wav\n│   │   ├── 000002.wav\n│   │   ├── 000003.wav\n│   │   ├── ...\n│   │   ├── 000200.wav\n│   │   ├── labels.txt\n│   └── csmsc_mini.zip\n├── pretrained_models\n│   ├── fastspeech2_aishell3_ckpt_1.1.0\n│   │   ├── default.yaml\n│   │   ├── energy_stats.npy\n│   │   ├── phone_id_map.txt\n│   │   ├── pitch_stats.npy\n│   │   ├── snapshot_iter_96400.pdz\n│   │   ├── speaker_id_map.txt\n│   │   └── speech_stats.npy\n│   ├── fastspeech2_aishell3_ckpt_1.1.0.zip\n│   ├── hifigan_aishell3_ckpt_0.2.0    \n│   │   ├── default.yaml\n│   │   ├── feats_stats.npy\n│   │   └── snapshot_iter_2500000.pdz\n│   └── hifigan_aishell3_ckpt_0.2.0.zip\n└── tools\n    ├── aligner\n    │   ├── aishell3_model\n    │   ├── aishell3_model.zip\n    │   └── simple.lexicon\n    ├── montreal-forced-aligner\n    │   ├── bin\n    │   ├── lib\n    │   └── pretrained_models\n    └── montreal-forced-aligner_linux.tar.gz\n    ...\n\n```\n\n### Set finetune.yaml\n`conf/finetune.yaml` contains some configurations for fine-tuning. You can try various options to fine better result. The value of frozen_layers can be change according `conf/fastspeech2_layers.txt` which is the model layer of fastspeech2.\n\nArguments:\n  - `batch_size`: finetune batch size which should be less than or equal to the number of training samples. Default: -1, means 64 which same to pretrained model\n  - `learning_rate`: learning rate. Default: 0.0001\n  - `num_snapshots`: number of save models. Default: -1, means 5 which same to pretrained model\n  - `frozen_layers`: frozen layers. must be a list. If you don't want to frozen any layer, set []. \n\n\n## Get Started\nFor finetuning Chinese pretrained model, execute `./run.sh`. For finetuning English pretrained model, execute `./run_en.sh`. For finetuning Chinese-English Mixed pretrained model, execute `./run_mix.sh`. </br>\nRun the command below to\n1. **source path**.\n2. finetune the model. \n3. synthesize wavs.\n    - synthesize waveform from text file.\n\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to run only one stage.\n\n### Model Finetune\n\nFinetune a FastSpeech2 model. \n\n```bash\n./run.sh --stage 0 --stop-stage 5\n```\n`stage 5` of `run.sh` calls `local/finetune.py`, here's the complete help message.\n\n```text\nusage: finetune.py [-h] [--pretrained_model_dir PRETRAINED_MODEL_DIR]\n                [--dump_dir DUMP_DIR] [--output_dir OUTPUT_DIR] [--ngpu NGPU]\n                [--epoch EPOCH] [--finetune_config FINETUNE_CONFIG]\n\noptional arguments:\n  -h, --help           Show this help message and exit\n  --pretrained_model_dir PRETRAINED_MODEL_DIR\n                       Path to pretrained model\n  --dump_dir DUMP_DIR\n                       directory to save feature files and metadata\n  --output_dir OUTPUT_DIR      \n                       Directory to save finetune model \n  --ngpu NGPU          The number of gpu, if ngpu=0, use cpu\n  --epoch EPOCH        The epoch of finetune\n  --finetune_config FINETUNE_CONFIG        \n                       Path to finetune config file\n```\n\n1. `--pretrained_model_dir` is the directory incluing pretrained fastspeech2_aishell3 model.\n2. `--dump_dir` is the directory including audio feature and metadata.\n3. `--output_dir` is the directory to save finetune model.\n4. `--ngpu` is the number of gpu, if ngpu=0, use cpu\n5. `--epoch` is the epoch of finetune.\n6. `--finetune_config` is the path to finetune config file\n \n\n### Synthesizing\nTo synthesize Chinese audio, We use [HiFiGAN with aishell3](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc5) as the neural vocoder.\nAssume the path to the hifigan model is `./pretrained_models`. Download the pretrained HiFiGAN model from [hifigan_aishell3_ckpt_0.2.0](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip) and unzip it.\n\nTo synthesize English audio, We use [HiFiGAN with vctk](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/voc5) as the neural vocoder.\nAssume the path to the hifigan model is `./pretrained_models`. Download the pretrained HiFiGAN model from [hifigan_vctk_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip) and unzip it.\n\n\nModify `ckpt` in `run.sh` to the final model in `exp/default/checkpoints`.\n```bash\n./run.sh --stage 6 --stop-stage 6\n```\n`stage 6` of `run.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {fastspeech2_aishell3,fastspeech2_vctk}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_aishell3, pwgan_vctk, hifigan_aishell3, hifigan_vctk}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {fastspeech2_aishell3, fastspeech2_vctk}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_aishell3, pwgan_vctk, hifigan_aishell3, hifigan_vctk}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat`, `--phones_dict` `--speaker_dict` are arguments for acoustic model, which correspond to the 5 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--text` is the text file, which contains sentences to synthesize.\n7.  `--output_dir` is the directory to save synthesized audio files.\n8. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n\n### Tips\nIf you want to get better audio quality, you can use more audios to finetune or change configuration parameters in `conf/finetune.yaml`.</br>\nMore finetune results can be found on [finetune-fastspeech2-for-csmsc](https://paddlespeech.readthedocs.io/en/latest/tts/demo.html#finetune-fastspeech2-for-csmsc).</br>\nThe results show the effect on csmsc_mini: Freeze encoder > Non Frozen > Freeze encoder && duration_predictor.\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/conf/fastspeech2_layers.txt",
    "content": "epoch\niteration\nmain_params\nmain_optimizer\nspk_embedding_table.weight\nencoder.embed.0.weight\nencoder.embed.1.alpha\nencoder.encoders.0.self_attn.linear_q.weight\nencoder.encoders.0.self_attn.linear_q.bias\nencoder.encoders.0.self_attn.linear_k.weight\nencoder.encoders.0.self_attn.linear_k.bias\nencoder.encoders.0.self_attn.linear_v.weight\nencoder.encoders.0.self_attn.linear_v.bias\nencoder.encoders.0.self_attn.linear_out.weight\nencoder.encoders.0.self_attn.linear_out.bias\nencoder.encoders.0.feed_forward.w_1.weight\nencoder.encoders.0.feed_forward.w_1.bias\nencoder.encoders.0.feed_forward.w_2.weight\nencoder.encoders.0.feed_forward.w_2.bias\nencoder.encoders.0.norm1.weight\nencoder.encoders.0.norm1.bias\nencoder.encoders.0.norm2.weight\nencoder.encoders.0.norm2.bias\nencoder.encoders.1.self_attn.linear_q.weight\nencoder.encoders.1.self_attn.linear_q.bias\nencoder.encoders.1.self_attn.linear_k.weight\nencoder.encoders.1.self_attn.linear_k.bias\nencoder.encoders.1.self_attn.linear_v.weight\nencoder.encoders.1.self_attn.linear_v.bias\nencoder.encoders.1.self_attn.linear_out.weight\nencoder.encoders.1.self_attn.linear_out.bias\nencoder.encoders.1.feed_forward.w_1.weight\nencoder.encoders.1.feed_forward.w_1.bias\nencoder.encoders.1.feed_forward.w_2.weight\nencoder.encoders.1.feed_forward.w_2.bias\nencoder.encoders.1.norm1.weight\nencoder.encoders.1.norm1.bias\nencoder.encoders.1.norm2.weight\nencoder.encoders.1.norm2.bias\nencoder.encoders.2.self_attn.linear_q.weight\nencoder.encoders.2.self_attn.linear_q.bias\nencoder.encoders.2.self_attn.linear_k.weight\nencoder.encoders.2.self_attn.linear_k.bias\nencoder.encoders.2.self_attn.linear_v.weight\nencoder.encoders.2.self_attn.linear_v.bias\nencoder.encoders.2.self_attn.linear_out.weight\nencoder.encoders.2.self_attn.linear_out.bias\nencoder.encoders.2.feed_forward.w_1.weight\nencoder.encoders.2.feed_forward.w_1.bias\nencoder.encoders.2.feed_forward.w_2.weight\nencoder.encoders.2.feed_forward.w_2.bias\nencoder.encoders.2.norm1.weight\nencoder.encoders.2.norm1.bias\nencoder.encoders.2.norm2.weight\nencoder.encoders.2.norm2.bias\nencoder.encoders.3.self_attn.linear_q.weight\nencoder.encoders.3.self_attn.linear_q.bias\nencoder.encoders.3.self_attn.linear_k.weight\nencoder.encoders.3.self_attn.linear_k.bias\nencoder.encoders.3.self_attn.linear_v.weight\nencoder.encoders.3.self_attn.linear_v.bias\nencoder.encoders.3.self_attn.linear_out.weight\nencoder.encoders.3.self_attn.linear_out.bias\nencoder.encoders.3.feed_forward.w_1.weight\nencoder.encoders.3.feed_forward.w_1.bias\nencoder.encoders.3.feed_forward.w_2.weight\nencoder.encoders.3.feed_forward.w_2.bias\nencoder.encoders.3.norm1.weight\nencoder.encoders.3.norm1.bias\nencoder.encoders.3.norm2.weight\nencoder.encoders.3.norm2.bias\nencoder.after_norm.weight\nencoder.after_norm.bias\nspk_projection.weight\nspk_projection.bias\nduration_predictor.conv.0.0.weight\nduration_predictor.conv.0.0.bias\nduration_predictor.conv.0.2.weight\nduration_predictor.conv.0.2.bias\nduration_predictor.conv.1.0.weight\nduration_predictor.conv.1.0.bias\nduration_predictor.conv.1.2.weight\nduration_predictor.conv.1.2.bias\nduration_predictor.linear.weight\nduration_predictor.linear.bias\npitch_predictor.conv.0.0.weight\npitch_predictor.conv.0.0.bias\npitch_predictor.conv.0.2.weight\npitch_predictor.conv.0.2.bias\npitch_predictor.conv.1.0.weight\npitch_predictor.conv.1.0.bias\npitch_predictor.conv.1.2.weight\npitch_predictor.conv.1.2.bias\npitch_predictor.conv.2.0.weight\npitch_predictor.conv.2.0.bias\npitch_predictor.conv.2.2.weight\npitch_predictor.conv.2.2.bias\npitch_predictor.conv.3.0.weight\npitch_predictor.conv.3.0.bias\npitch_predictor.conv.3.2.weight\npitch_predictor.conv.3.2.bias\npitch_predictor.conv.4.0.weight\npitch_predictor.conv.4.0.bias\npitch_predictor.conv.4.2.weight\npitch_predictor.conv.4.2.bias\npitch_predictor.linear.weight\npitch_predictor.linear.bias\npitch_embed.0.weight\npitch_embed.0.bias\nenergy_predictor.conv.0.0.weight\nenergy_predictor.conv.0.0.bias\nenergy_predictor.conv.0.2.weight\nenergy_predictor.conv.0.2.bias\nenergy_predictor.conv.1.0.weight\nenergy_predictor.conv.1.0.bias\nenergy_predictor.conv.1.2.weight\nenergy_predictor.conv.1.2.bias\nenergy_predictor.linear.weight\nenergy_predictor.linear.bias\nenergy_embed.0.weight\nenergy_embed.0.bias\ndecoder.embed.0.alpha\ndecoder.encoders.0.self_attn.linear_q.weight\ndecoder.encoders.0.self_attn.linear_q.bias\ndecoder.encoders.0.self_attn.linear_k.weight\ndecoder.encoders.0.self_attn.linear_k.bias\ndecoder.encoders.0.self_attn.linear_v.weight\ndecoder.encoders.0.self_attn.linear_v.bias\ndecoder.encoders.0.self_attn.linear_out.weight\ndecoder.encoders.0.self_attn.linear_out.bias\ndecoder.encoders.0.feed_forward.w_1.weight\ndecoder.encoders.0.feed_forward.w_1.bias\ndecoder.encoders.0.feed_forward.w_2.weight\ndecoder.encoders.0.feed_forward.w_2.bias\ndecoder.encoders.0.norm1.weight\ndecoder.encoders.0.norm1.bias\ndecoder.encoders.0.norm2.weight\ndecoder.encoders.0.norm2.bias\ndecoder.encoders.1.self_attn.linear_q.weight\ndecoder.encoders.1.self_attn.linear_q.bias\ndecoder.encoders.1.self_attn.linear_k.weight\ndecoder.encoders.1.self_attn.linear_k.bias\ndecoder.encoders.1.self_attn.linear_v.weight\ndecoder.encoders.1.self_attn.linear_v.bias\ndecoder.encoders.1.self_attn.linear_out.weight\ndecoder.encoders.1.self_attn.linear_out.bias\ndecoder.encoders.1.feed_forward.w_1.weight\ndecoder.encoders.1.feed_forward.w_1.bias\ndecoder.encoders.1.feed_forward.w_2.weight\ndecoder.encoders.1.feed_forward.w_2.bias\ndecoder.encoders.1.norm1.weight\ndecoder.encoders.1.norm1.bias\ndecoder.encoders.1.norm2.weight\ndecoder.encoders.1.norm2.bias\ndecoder.encoders.2.self_attn.linear_q.weight\ndecoder.encoders.2.self_attn.linear_q.bias\ndecoder.encoders.2.self_attn.linear_k.weight\ndecoder.encoders.2.self_attn.linear_k.bias\ndecoder.encoders.2.self_attn.linear_v.weight\ndecoder.encoders.2.self_attn.linear_v.bias\ndecoder.encoders.2.self_attn.linear_out.weight\ndecoder.encoders.2.self_attn.linear_out.bias\ndecoder.encoders.2.feed_forward.w_1.weight\ndecoder.encoders.2.feed_forward.w_1.bias\ndecoder.encoders.2.feed_forward.w_2.weight\ndecoder.encoders.2.feed_forward.w_2.bias\ndecoder.encoders.2.norm1.weight\ndecoder.encoders.2.norm1.bias\ndecoder.encoders.2.norm2.weight\ndecoder.encoders.2.norm2.bias\ndecoder.encoders.3.self_attn.linear_q.weight\ndecoder.encoders.3.self_attn.linear_q.bias\ndecoder.encoders.3.self_attn.linear_k.weight\ndecoder.encoders.3.self_attn.linear_k.bias\ndecoder.encoders.3.self_attn.linear_v.weight\ndecoder.encoders.3.self_attn.linear_v.bias\ndecoder.encoders.3.self_attn.linear_out.weight\ndecoder.encoders.3.self_attn.linear_out.bias\ndecoder.encoders.3.feed_forward.w_1.weight\ndecoder.encoders.3.feed_forward.w_1.bias\ndecoder.encoders.3.feed_forward.w_2.weight\ndecoder.encoders.3.feed_forward.w_2.bias\ndecoder.encoders.3.norm1.weight\ndecoder.encoders.3.norm1.bias\ndecoder.encoders.3.norm2.weight\ndecoder.encoders.3.norm2.bias\ndecoder.after_norm.weight\ndecoder.after_norm.bias\nfeat_out.weight\nfeat_out.bias\npostnet.postnet.0.0.weight\npostnet.postnet.0.1.weight\npostnet.postnet.0.1.bias\npostnet.postnet.0.1._mean\npostnet.postnet.0.1._variance\npostnet.postnet.1.0.weight\npostnet.postnet.1.1.weight\npostnet.postnet.1.1.bias\npostnet.postnet.1.1._mean\npostnet.postnet.1.1._variance\npostnet.postnet.2.0.weight\npostnet.postnet.2.1.weight\npostnet.postnet.2.1.bias\npostnet.postnet.2.1._mean\npostnet.postnet.2.1._variance\npostnet.postnet.3.0.weight\npostnet.postnet.3.1.weight\npostnet.postnet.3.1.bias\npostnet.postnet.3.1._mean\npostnet.postnet.3.1._variance\npostnet.postnet.4.0.weight\npostnet.postnet.4.1.weight\npostnet.postnet.4.1.bias\npostnet.postnet.4.1._mean\npostnet.postnet.4.1._variance\n\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/conf/finetune.yaml",
    "content": "###########################################################\n#                 PARAS SETTING               #\n###########################################################\n# Set to -1 to indicate that the parameter is the same as the pretrained model configuration\n\nbatch_size: -1\nlearning_rate: 0.0001     # learning rate\nnum_snapshots: -1\n\n# frozen_layers should be a list\n# if you don't need to freeze, set frozen_layers to []\n# fastspeech2 layers can be found on conf/fastspeech2_layers.txt\n# example: frozen_layers: [\"encoder\", \"duration_predictor\"]\nfrozen_layers: [\"encoder\"]\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/check_oov.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport re\nfrom pathlib import Path\nfrom typing import Dict\nfrom typing import List\nfrom typing import Union\n\nDICT_EN = 'tools/aligner/cmudict-0.7b'\nDICT_ZH = 'tools/aligner/simple.lexicon'\nMODEL_DIR_EN = 'tools/aligner/vctk_model.zip'\nMODEL_DIR_ZH = 'tools/aligner/aishell3_model.zip'\nMFA_PHONE_EN = 'tools/aligner/vctk_model/meta.yaml'\nMFA_PHONE_ZH = 'tools/aligner/aishell3_model/meta.yaml'\nMFA_PATH = 'tools/montreal-forced-aligner/bin'\nos.environ['PATH'] = MFA_PATH + '/:' + os.environ['PATH']\n\n\ndef check_phone(label_file: Union[str, Path],\n                pronunciation_phones: Dict[str, str],\n                mfa_phones: List[str],\n                am_phones: List[str],\n                oov_record: str=\"./oov_info.txt\",\n                lang: str=\"zh\"):\n    \"\"\"Check whether the phoneme corresponding to the audio text content \n    is in the phoneme list of the pretrained mfa model to ensure that the alignment is normal.\n    Check whether the phoneme corresponding to the audio text content \n    is in the phoneme list of the pretrained am model to ensure finetune (normalize) is normal.\n\n    Args:\n        label_file (Union[str, Path]): label file, format: utt_id|phone seq\n        pronunciation_phones (dict): pronunciation to phones map dict\n        mfa_phones (list): the phone list of pretrained mfa model\n        am_phones (list): the phone list of pretrained mfa model\n\n    Returns:\n        oov_words (list): oov words\n        oov_files (list): utt id list that exist oov\n        oov_file_words (dict): the oov file and oov phone in this file\n    \"\"\"\n    oov_words = []\n    oov_files = []\n    oov_file_words = {}\n\n    with open(label_file, \"r\") as f:\n        for line in f.readlines():\n            utt_id = line.split(\"|\")[0]\n            transcription = line.strip().split(\"|\")[1]\n            transcription = re.sub(\n                r'[：、，；。？！,.:;\"?!”’《》【】<=>{}()（）#&@“”^_|…\\\\]', '',\n                transcription)\n            if lang == \"en\":\n                transcription = transcription.upper()\n            flag = 0\n            temp_oov_words = []\n            for word in transcription.split(\" \"):\n                if word not in pronunciation_phones.keys():\n                    temp_oov_words.append(word)\n                    flag = 1\n                    if word not in oov_words:\n                        oov_words.append(word)\n                else:\n                    for p in pronunciation_phones[word]:\n                        if p not in mfa_phones or p not in am_phones:\n                            temp_oov_words.append(word)\n                            flag = 1\n                            if word not in oov_words:\n                                oov_words.append(word)\n            if flag == 1:\n                oov_files.append(utt_id)\n                oov_file_words[utt_id] = temp_oov_words\n\n    if oov_record is not None:\n        with open(oov_record, \"w\") as fw:\n            fw.write(\"oov_words: \" + str(oov_words) + \"\\n\")\n            fw.write(\"oov_files: \" + str(oov_files) + \"\\n\")\n            fw.write(\"oov_file_words: \" + str(oov_file_words) + \"\\n\")\n\n    return oov_words, oov_files, oov_file_words\n\n\ndef get_pronunciation_phones(lexicon_file: Union[str, Path]):\n    # pronunciation to phones\n    pronunciation_phones = {}\n    with open(lexicon_file, \"r\") as f2:\n        for line in f2.readlines():\n            line_list = line.strip().split(\" \")\n            pronunciation = line_list[0]\n            if line_list[1] == '':\n                phones = line_list[2:]\n            else:\n                phones = line_list[1:]\n            pronunciation_phones[pronunciation] = phones\n\n    return pronunciation_phones\n\n\ndef get_mfa_phone(mfa_phone_file: Union[str, Path]):\n    # get phones from pretrained mfa model (meta.yaml)\n    mfa_phones = []\n    with open(mfa_phone_file, \"r\") as f:\n        for line in f.readlines():\n            if line.startswith(\"-\"):\n                phone = line.strip().split(\" \")[-1]\n                mfa_phones.append(phone)\n\n    return mfa_phones\n\n\ndef get_am_phone(am_phone_file: Union[str, Path]):\n    # get phones from pretrained am model (phone_id_map.txt)\n    am_phones = []\n    with open(am_phone_file, \"r\") as f:\n        for line in f.readlines():\n            phone = line.strip().split(\" \")[0]\n            am_phones.append(phone)\n\n    return am_phones\n\n\ndef get_check_result(label_file: Union[str, Path],\n                     am_phone_file: Union[str, Path],\n                     input_dir: Union[str, Path],\n                     newdir_name: str=\"newdir\",\n                     lang: str=\"zh\"):\n    \"\"\"Check if there is any audio in the input that contains the oov word according to label_file.\n       Copy audio that does not contain oov word to input_dir / newdir_name.\n       Generate label file and save to input_dir / newdir_name.\n\n\n    Args:\n        label_file (Union[str, Path]): input audio label file, format: utt|pronunciation \n        am_phone_file (Union[str, Path]): pretrained am model phone file\n        input_dir (Union[str, Path]): input dir\n        newdir_name (str): directory name saved after checking oov\n        lang (str): input audio language\n    \"\"\"\n\n    if lang == 'en':\n        lexicon_file = DICT_EN\n        mfa_phone_file = MFA_PHONE_EN\n    elif lang == 'zh':\n        lexicon_file = DICT_ZH\n        mfa_phone_file = MFA_PHONE_ZH\n    else:\n        print('please input right lang!!')\n\n    pronunciation_phones = get_pronunciation_phones(lexicon_file)\n    mfa_phones = get_mfa_phone(mfa_phone_file)\n    am_phones = get_am_phone(am_phone_file)\n    oov_words, oov_files, oov_file_words = check_phone(\n        label_file=label_file,\n        pronunciation_phones=pronunciation_phones,\n        mfa_phones=mfa_phones,\n        am_phones=am_phones,\n        oov_record=\"./oov_info.txt\",\n        lang=lang)\n\n    input_dir = Path(input_dir).expanduser()\n    new_dir = input_dir / newdir_name\n    new_dir.mkdir(parents=True, exist_ok=True)\n    with open(label_file, \"r\") as f:\n        for line in f.readlines():\n            utt_id = line.split(\"|\")[0]\n            if utt_id not in oov_files:\n                transcription = line.split(\"|\")[1].strip()\n                wav_file = str(input_dir) + \"/\" + utt_id + \".wav\"\n                new_wav_file = str(new_dir) + \"/\" + utt_id + \".wav\"\n                os.system(\"cp %s %s\" % (wav_file, new_wav_file))\n                single_file = str(new_dir) + \"/\" + utt_id + \".txt\"\n                with open(single_file, \"w\") as fw:\n                    fw.write(transcription)\n\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--input_dir\",\n        type=str,\n        default=\"./input/csmsc_mini\",\n        help=\"directory containing audio and label file\")\n\n    parser.add_argument(\n        \"--pretrained_model_dir\",\n        type=str,\n        default=\"./pretrained_models/fastspeech2_aishell3_ckpt_1.1.0\",\n        help=\"Path to pretrained model\")\n\n    parser.add_argument(\n        \"--newdir_name\",\n        type=str,\n        default=\"newdir\",\n        help=\"directory name saved after checking oov\")\n\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        choices=['zh', 'en'],\n        help='Choose input audio language. zh or en')\n\n    args = parser.parse_args()\n\n    # if args.lang == 'en':\n    #     lexicon_file = DICT_EN\n    #     mfa_phone_file = MFA_PHONE_EN\n    # elif args.lang == 'zh':\n    #     lexicon_file = DICT_ZH\n    #     mfa_phone_file = MFA_PHONE_ZH\n    # else:\n    #     print('please input right lang!!')\n    assert args.lang == \"zh\" or args.lang == \"en\", \"please input right lang! zh or en\"\n\n    input_dir = Path(args.input_dir).expanduser()\n    pretrained_model_dir = Path(args.pretrained_model_dir).expanduser()\n    am_phone_file = pretrained_model_dir / \"phone_id_map.txt\"\n    label_file = input_dir / \"labels.txt\"\n\n    get_check_result(\n        label_file=label_file,\n        am_phone_file=am_phone_file,\n        input_dir=input_dir,\n        newdir_name=args.newdir_name,\n        lang=args.lang)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/extract_feature.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Dict\nfrom typing import Union\n\nimport jsonlines\nimport numpy as np\nimport yaml\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.get_feats import Energy\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.get_feats import Pitch\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.exps.fastspeech2.preprocess import process_sentences\n\n\ndef read_stats(stats_file: Union[str, Path]):\n    scaler = StandardScaler()\n    scaler.mean_ = np.load(stats_file)[0]\n    scaler.scale_ = np.load(stats_file)[1]\n    scaler.n_features_in_ = scaler.mean_.shape[0]\n    return scaler\n\n\ndef get_stats(pretrained_model_dir: Path):\n    speech_stats_file = pretrained_model_dir / \"speech_stats.npy\"\n    pitch_stats_file = pretrained_model_dir / \"pitch_stats.npy\"\n    energy_stats_file = pretrained_model_dir / \"energy_stats.npy\"\n    speech_scaler = read_stats(speech_stats_file)\n    pitch_scaler = read_stats(pitch_stats_file)\n    energy_scaler = read_stats(energy_stats_file)\n\n    return speech_scaler, pitch_scaler, energy_scaler\n\n\ndef get_map(duration_file: Union[str, Path],\n            dump_dir: Path,\n            pretrained_model_dir: Path,\n            replace_spkid: int=0):\n    \"\"\"get phone map and speaker map, save on dump_dir\n\n    Args:\n        duration_file (str): durantions.txt\n        dump_dir (Path): dump dir\n        pretrained_model_dir (Path): pretrained model dir\n        replace_spkid (int): replace spk id \n    \"\"\"\n    # copy phone map file from pretrained model path\n    phones_dict = dump_dir / \"phone_id_map.txt\"\n    os.system(\"cp %s %s\" %\n              (pretrained_model_dir / \"phone_id_map.txt\", phones_dict))\n\n    # create a new speaker map file, replace the previous speakers.\n    sentences, speaker_set = get_phn_dur(duration_file)\n    merge_silence(sentences)\n    speakers = sorted(list(speaker_set))\n    num = len(speakers)\n    speaker_dict = dump_dir / \"speaker_id_map.txt\"\n    spk_dict = {}\n    # get raw spkid-spk dict \n    with open(pretrained_model_dir / \"speaker_id_map.txt\", 'r') as fr:\n        for line in fr.readlines():\n            spk = line.strip().split(\" \")[0]\n            spk_id = line.strip().split(\" \")[1]\n            spk_dict[spk_id] = spk\n\n    # replace spk on spkid-spk dict\n    assert replace_spkid + num - 1 < len(\n        spk_dict), \"Please set correct replace spk id.\"\n    for i, spk in enumerate(speakers):\n        spk_dict[str(replace_spkid + i)] = spk\n\n    # write a new spk map file\n    with open(speaker_dict, 'w') as f:\n        for spk_id in spk_dict.keys():\n            f.write(spk_dict[spk_id] + ' ' + spk_id + '\\n')\n\n    vocab_phones = {}\n    with open(phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    return sentences, vocab_phones, vocab_speaker\n\n\ndef get_extractor(config):\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n    pitch_extractor = Pitch(\n        sr=config.fs,\n        hop_length=config.n_shift,\n        f0min=config.f0min,\n        f0max=config.f0max)\n    energy_extractor = Energy(\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window)\n\n    return mel_extractor, pitch_extractor, energy_extractor\n\n\ndef normalize(speech_scaler,\n              pitch_scaler,\n              energy_scaler,\n              vocab_phones: Dict,\n              vocab_speaker: Dict,\n              raw_dump_dir: Path,\n              type: str):\n\n    dumpdir = raw_dump_dir / type / \"norm\"\n    dumpdir = Path(dumpdir).expanduser()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    metadata_file = raw_dump_dir / type / \"raw\" / \"metadata.jsonl\"\n    with jsonlines.open(metadata_file, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        converters={\n            \"speech\": np.load,\n            \"pitch\": np.load,\n            \"energy\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n        pitch = item['pitch']\n        energy = item['energy']\n        # normalize\n        speech = speech_scaler.transform(speech)\n        speech_dir = dumpdir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        pitch = pitch_scaler.transform(pitch)\n        pitch_dir = dumpdir / \"data_pitch\"\n        pitch_dir.mkdir(parents=True, exist_ok=True)\n        pitch_path = pitch_dir / f\"{utt_id}_pitch.npy\"\n        np.save(pitch_path, pitch.astype(np.float32), allow_pickle=False)\n\n        energy = energy_scaler.transform(energy)\n        energy_dir = dumpdir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / f\"{utt_id}_energy.npy\"\n        np.save(energy_path, energy.astype(np.float32), allow_pickle=False)\n\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"speech_lengths\": item['speech_lengths'],\n            \"durations\": item['durations'],\n            \"speech\": str(speech_path),\n            \"pitch\": str(pitch_path),\n            \"energy\": str(energy_path)\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\ndef extract_feature(duration_file: str,\n                    config,\n                    input_dir: Path,\n                    dump_dir: Path,\n                    pretrained_model_dir: Path,\n                    replace_spkid: int=0):\n\n    sentences, vocab_phones, vocab_speaker = get_map(\n        duration_file, dump_dir, pretrained_model_dir, replace_spkid)\n    mel_extractor, pitch_extractor, energy_extractor = get_extractor(config)\n\n    wav_files = sorted(list((input_dir).rglob(\"*.wav\")))\n    # split data into 3 sections, train: len(wav_files) - 2, dev: 1, test: 1\n    num_train = len(wav_files) - 2\n    num_dev = 1\n    print(num_train, num_dev)\n\n    train_wav_files = wav_files[:num_train]\n    dev_wav_files = wav_files[num_train:num_train + num_dev]\n    test_wav_files = wav_files[num_train + num_dev:]\n\n    train_dump_dir = dump_dir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dump_dir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dump_dir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # process for the 3 sections\n    num_cpu = 4\n    cut_sil = True\n    spk_emb_dir = None\n    write_metadata_method = \"w\"\n    speech_scaler, pitch_scaler, energy_scaler = get_stats(pretrained_model_dir)\n\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=num_cpu,\n            cut_sil=cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=write_metadata_method)\n        # norm\n        normalize(speech_scaler, pitch_scaler, energy_scaler, vocab_phones,\n                  vocab_speaker, dump_dir, \"train\")\n\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=num_cpu,\n            cut_sil=cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=write_metadata_method)\n        # norm\n        normalize(speech_scaler, pitch_scaler, energy_scaler, vocab_phones,\n                  vocab_speaker, dump_dir, \"dev\")\n\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=num_cpu,\n            cut_sil=cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=write_metadata_method)\n\n        # norm\n        normalize(speech_scaler, pitch_scaler, energy_scaler, vocab_phones,\n                  vocab_speaker, dump_dir, \"test\")\n\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--duration_file\",\n        type=str,\n        default=\"./durations.txt\",\n        help=\"duration file\")\n\n    parser.add_argument(\n        \"--input_dir\",\n        type=str,\n        default=\"./input/baker_mini/newdir\",\n        help=\"directory containing audio and label file\")\n\n    parser.add_argument(\n        \"--dump_dir\", type=str, default=\"./dump\", help=\"dump dir\")\n\n    parser.add_argument(\n        \"--pretrained_model_dir\",\n        type=str,\n        default=\"./pretrained_models/fastspeech2_aishell3_ckpt_1.1.0\",\n        help=\"Path to pretrained model\")\n\n    parser.add_argument(\n        \"--replace_spkid\", type=int, default=0, help=\"replace spk id\")\n\n    args = parser.parse_args()\n\n    input_dir = Path(args.input_dir).expanduser()\n    dump_dir = Path(args.dump_dir).expanduser()\n    dump_dir.mkdir(parents=True, exist_ok=True)\n    pretrained_model_dir = Path(args.pretrained_model_dir).expanduser()\n\n    # read config\n    config_file = pretrained_model_dir / \"default.yaml\"\n    with open(config_file) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    extract_feature(\n        duration_file=args.duration_file,\n        config=config,\n        input_dir=input_dir,\n        dump_dir=dump_dir,\n        pretrained_model_dir=pretrained_model_dir,\n        replace_spkid=args.replace_spkid)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/finetune.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\nfrom typing import List\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import fastspeech2_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import fastspeech2_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Evaluator\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Updater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\nclass TrainArgs():\n    def __init__(self,\n                 ngpu,\n                 config_file,\n                 dump_dir: Path,\n                 output_dir: Path,\n                 frozen_layers: List[str]):\n        # config: fastspeech2 config file.\n        self.config = str(config_file)\n        self.train_metadata = str(dump_dir / \"train/norm/metadata.jsonl\")\n        self.dev_metadata = str(dump_dir / \"dev/norm/metadata.jsonl\")\n        # model output dir.\n        self.output_dir = str(output_dir)\n        self.ngpu = ngpu\n        self.phones_dict = str(dump_dir / \"phone_id_map.txt\")\n        self.speaker_dict = str(dump_dir / \"speaker_id_map.txt\")\n        self.voice_cloning = False\n        # frozen layers\n        self.frozen_layers = frozen_layers\n\n\ndef freeze_layer(model, layers: List[str]):\n    \"\"\"freeze layers\n\n    Args:\n        layers (List[str]): frozen layers\n    \"\"\"\n    for layer in layers:\n        for param in eval(\"model.\" + layer + \".parameters()\"):\n            param.trainable = False\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n    fields = [\n        \"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"durations\",\n        \"pitch\", \"energy\"\n    ]\n    converters = {\"speech\": np.load, \"pitch\": np.load, \"energy\": np.load}\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker fastspeech2!\")\n        collate_fn = fastspeech2_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Training voice cloning!\")\n        collate_fn = fastspeech2_multi_spk_batch_fn\n        fields += [\"spk_emb\"]\n        converters[\"spk_emb\"] = np.load\n    else:\n        print(\"single speaker fastspeech2!\")\n        collate_fn = fastspeech2_single_spk_batch_fn\n    print(\"spk_num:\", spk_num)\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    train_batch_size = min(len(train_metadata), config.batch_size)\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=train_batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    model = FastSpeech2(\n        idim=vocab_size, odim=odim, spk_num=spk_num, **config[\"model\"])\n\n    # freeze layer\n    if args.frozen_layers != []:\n        freeze_layer(model, args.frozen_layers)\n\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    optimizer = build_optimizers(model, **config[\"optimizer\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = FastSpeech2Updater(\n        model=model,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir,\n        **config[\"updater\"])\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = FastSpeech2Evaluator(\n        model, dev_dataloader, output_dir=output_dir, **config[\"updater\"])\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--pretrained_model_dir\",\n        type=str,\n        default=\"./pretrained_models/fastspeech2_aishell3_ckpt_1.1.0\",\n        help=\"Path to pretrained model\")\n\n    parser.add_argument(\n        \"--dump_dir\",\n        type=str,\n        default=\"./dump\",\n        help=\"directory to save feature files and metadata.\")\n\n    parser.add_argument(\n        \"--output_dir\",\n        type=str,\n        default=\"./exp/default/\",\n        help=\"directory to save finetune model.\")\n\n    parser.add_argument(\n        \"--ngpu\", type=int, default=2, help=\"if ngpu=0, use cpu.\")\n\n    parser.add_argument(\"--epoch\", type=int, default=100, help=\"finetune epoch\")\n    parser.add_argument(\n        \"--finetune_config\",\n        type=str,\n        default=\"./finetune.yaml\",\n        help=\"Path to finetune config file\")\n\n    args = parser.parse_args()\n\n    dump_dir = Path(args.dump_dir).expanduser()\n    dump_dir.mkdir(parents=True, exist_ok=True)\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    pretrained_model_dir = Path(args.pretrained_model_dir).expanduser()\n\n    # read config\n    config_file = pretrained_model_dir / \"default.yaml\"\n    with open(config_file) as f:\n        config = CfgNode(yaml.safe_load(f))\n    config.max_epoch = config.max_epoch + args.epoch\n\n    with open(args.finetune_config) as f2:\n        finetune_config = CfgNode(yaml.safe_load(f2))\n    config.batch_size = finetune_config.batch_size if finetune_config.batch_size > 0 else config.batch_size\n    config.optimizer.learning_rate = finetune_config.learning_rate if finetune_config.learning_rate > 0 else config.optimizer.learning_rate\n    config.num_snapshots = finetune_config.num_snapshots if finetune_config.num_snapshots > 0 else config.num_snapshots\n    frozen_layers = finetune_config.frozen_layers\n    assert type(frozen_layers) == list, \"frozen_layers should be set a list.\"\n\n    # create a new args for training\n    train_args = TrainArgs(args.ngpu, config_file, dump_dir, output_dir,\n                           frozen_layers)\n\n    # finetune models\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (train_args, config), nprocs=args.ngpu)\n    else:\n        train_sp(train_args, config)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/generate_duration.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nfrom utils.gen_duration_from_textgrid import gen_duration_from_textgrid\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--mfa_dir\",\n        type=str,\n        default=\"./mfa_result\",\n        help=\"directory to save aligned files\")\n\n    args = parser.parse_args()\n\n    fs = 24000\n    n_shift = 300\n    duration_file = \"./durations.txt\"\n    mfa_dir = Path(args.mfa_dir).expanduser()\n    mfa_dir.mkdir(parents=True, exist_ok=True)\n\n    gen_duration_from_textgrid(mfa_dir, duration_file, fs, n_shift)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/get_mfa_result.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Union\n\nDICT_EN = 'tools/aligner/cmudict-0.7b'\nDICT_ZH = 'tools/aligner/simple.lexicon'\nMODEL_DIR_EN = 'tools/aligner/vctk_model.zip'\nMODEL_DIR_ZH = 'tools/aligner/aishell3_model.zip'\nMFA_PHONE_EN = 'tools/aligner/vctk_model/meta.yaml'\nMFA_PHONE_ZH = 'tools/aligner/aishell3_model/meta.yaml'\nMFA_PATH = 'tools/montreal-forced-aligner/bin'\nos.environ['PATH'] = MFA_PATH + '/:' + os.environ['PATH']\n\n\ndef get_mfa_result(\n        input_dir: Union[str, Path],\n        mfa_dir: Union[str, Path],\n        lang: str='en', ):\n    \"\"\"get mfa result\n\n    Args:\n        input_dir (Union[str, Path]): input dir including wav file and label\n        mfa_dir (Union[str, Path]): mfa result dir\n        lang (str, optional): input audio language. Defaults to 'en'.\n    \"\"\"\n    # MFA\n    if lang == 'en':\n        DICT = DICT_EN\n        MODEL_DIR = MODEL_DIR_EN\n\n    elif lang == 'zh':\n        DICT = DICT_ZH\n        MODEL_DIR = MODEL_DIR_ZH\n    else:\n        print('please input right lang!!')\n\n    CMD = 'mfa_align' + ' ' + str(\n        input_dir) + ' ' + DICT + ' ' + MODEL_DIR + ' ' + str(mfa_dir)\n    os.system(CMD)\n\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--input_dir\",\n        type=str,\n        default=\"./input/baker_mini/newdir\",\n        help=\"directory containing audio and label file\")\n\n    parser.add_argument(\n        \"--mfa_dir\",\n        type=str,\n        default=\"./mfa_result\",\n        help=\"directory to save aligned files\")\n\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        choices=['zh', 'en'],\n        help='Choose input audio language. zh or en')\n\n    args = parser.parse_args()\n\n    get_mfa_result(\n        input_dir=args.input_dir, mfa_dir=args.mfa_dir, lang=args.lang)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/local/prepare_env.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\n\ndef generate_finetune_env(output_dir: Path, pretrained_model_dir: Path):\n\n    output_dir = output_dir / \"checkpoints/\"\n    output_dir = output_dir.resolve()\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    model_path = sorted(list((pretrained_model_dir).rglob(\"*.pdz\")))[0]\n    model_path = model_path.resolve()\n    iter = int(str(model_path).split(\"_\")[-1].split(\".\")[0])\n    model_file = str(model_path).split(\"/\")[-1]\n\n    os.system(\"cp %s %s\" % (model_path, output_dir))\n\n    records_file = output_dir / \"records.jsonl\"\n    with open(records_file, \"w\") as f:\n        line = \"\\\"time\\\": \\\"2022-08-06 07:51:53.463650\\\", \\\"path\\\": \\\"%s\\\", \\\"iteration\\\": %d\" % (\n            str(output_dir / model_file), iter)\n        f.write(\"{\" + line + \"}\" + \"\\n\")\n\n\nif __name__ == '__main__':\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--pretrained_model_dir\",\n        type=str,\n        default=\"./pretrained_models/fastspeech2_aishell3_ckpt_1.1.0\",\n        help=\"Path to pretrained model\")\n\n    parser.add_argument(\n        \"--output_dir\",\n        type=str,\n        default=\"./exp/default/\",\n        help=\"directory to save finetune model.\")\n\n    args = parser.parse_args()\n\n    output_dir = Path(args.output_dir).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    pretrained_model_dir = Path(args.pretrained_model_dir).expanduser()\n\n    generate_finetune_env(output_dir, pretrained_model_dir)\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=fastspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\n\ninput_dir=./input/csmsc_mini\nnewdir_name=\"newdir\"\nnew_dir=${input_dir}/${newdir_name}\npretrained_model_dir=./pretrained_models/fastspeech2_aishell3_ckpt_1.1.0\nmfa_dir=./mfa_result\ndump_dir=./dump\noutput_dir=./exp/default\nlang=zh\nngpu=1\nfinetune_config=./conf/finetune.yaml\nreplace_spkid=0\n\nckpt=snapshot_iter_96699\n\ngpus=1\nCUDA_VISIBLE_DEVICES=${gpus}\nstage=0\nstop_stage=100\n\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\n# check oov\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"check oov\"\n    python3 local/check_oov.py \\\n        --input_dir=${input_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --newdir_name=${newdir_name} \\\n        --lang=${lang}\nfi\n\n# get mfa result\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"get mfa result\"\n    python3 local/get_mfa_result.py \\\n        --input_dir=${new_dir} \\\n        --mfa_dir=${mfa_dir} \\\n        --lang=${lang}\nfi\n\n# generate durations.txt\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"generate durations.txt\"\n    python3 local/generate_duration.py \\\n        --mfa_dir=${mfa_dir} \nfi\n\n# extract feature\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"extract feature\"\n    python3 local/extract_feature.py \\\n        --duration_file=\"./durations.txt\" \\\n        --input_dir=${new_dir} \\\n        --dump_dir=${dump_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --replace_spkid=$replace_spkid\nfi\n\n# create finetune env\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"create finetune env\"\n    python3 local/prepare_env.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --output_dir=${output_dir}\nfi\n\n# finetune\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    echo \"finetune...\"\n    python3 local/finetune.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --dump_dir=${dump_dir} \\\n        --output_dir=${output_dir} \\\n        --ngpu=${ngpu} \\\n        --epoch=100 \\\n        --finetune_config=${finetune_config}\nfi\n\n# synthesize e2e\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    echo \"in hifigan syn_e2e\"\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${pretrained_model_dir}/default.yaml \\\n        --am_ckpt=${output_dir}/checkpoints/${ckpt}.pdz \\\n        --am_stat=${pretrained_model_dir}/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=pretrained_models/hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=pretrained_models/hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=pretrained_models/hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --lang=zh \\\n        --text=${BIN_DIR}/../../assets/sentences.txt \\\n        --output_dir=./test_e2e/ \\\n        --phones_dict=${dump_dir}/phone_id_map.txt \\\n        --speaker_dict=${dump_dir}/speaker_id_map.txt \\\n        --spk_id=$replace_spkid\nfi\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/run_en.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ninput_dir=./input/ljspeech_mini\nnewdir_name=\"newdir\"\nnew_dir=${input_dir}/${newdir_name}\npretrained_model_dir=./pretrained_models/fastspeech2_vctk_ckpt_1.2.0\nmfa_dir=./mfa_result\ndump_dir=./dump\noutput_dir=./exp/default\nlang=en\nngpu=1\nfinetune_config=./conf/finetune.yaml\nreplace_spkid=0\n\nckpt=snapshot_iter_66300\n\ngpus=1\nCUDA_VISIBLE_DEVICES=${gpus}\nstage=0\nstop_stage=100\n\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\n# check oov\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"check oov\"\n    python3 local/check_oov.py \\\n        --input_dir=${input_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --newdir_name=${newdir_name} \\\n        --lang=${lang}\nfi\n\n# get mfa result\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"get mfa result\"\n    python3 local/get_mfa_result.py \\\n        --input_dir=${new_dir} \\\n        --mfa_dir=${mfa_dir} \\\n        --lang=${lang}\nfi\n\n# generate durations.txt\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"generate durations.txt\"\n    python3 local/generate_duration.py \\\n        --mfa_dir=${mfa_dir} \nfi\n\n# extract feature\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"extract feature\"\n    python3 local/extract_feature.py \\\n        --duration_file=\"./durations.txt\" \\\n        --input_dir=${new_dir} \\\n        --dump_dir=${dump_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --replace_spkid=$replace_spkid\nfi\n\n# create finetune env\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"create finetune env\"\n    python3 local/prepare_env.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --output_dir=${output_dir}\nfi\n\n# finetune\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    echo \"finetune...\"\n    python3 local/finetune.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --dump_dir=${dump_dir} \\\n        --output_dir=${output_dir} \\\n        --ngpu=${ngpu} \\\n        --epoch=100 \\\n        --finetune_config=${finetune_config}\nfi\n\n# synthesize e2e\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    echo \"in hifigan syn_e2e\"\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_vctk \\\n        --am_config=${pretrained_model_dir}/default.yaml \\\n        --am_ckpt=${output_dir}/checkpoints/${ckpt}.pdz \\\n        --am_stat=${pretrained_model_dir}/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=pretrained_models/hifigan_vctk_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=pretrained_models/hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=pretrained_models/hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --lang=en \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=./test_e2e/ \\\n        --phones_dict=${dump_dir}/phone_id_map.txt \\\n        --speaker_dict=${dump_dir}/speaker_id_map.txt \\\n        --spk_id=$replace_spkid\nfi\n"
  },
  {
    "path": "examples/other/tts_finetune/tts3/run_mix.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\n\ninput_dir=./input/SSB0005_mini\nnewdir_name=\"newdir\"\nnew_dir=${input_dir}/${newdir_name}\npretrained_model_dir=./pretrained_models/fastspeech2_mix_ckpt_1.2.0\nmfa_dir=./mfa_result\ndump_dir=./dump\noutput_dir=./exp/default\nlang=zh\nngpu=1\nfinetune_config=./conf/finetune.yaml\nreplace_spkid=174  # csmsc: 174, ljspeech: 175, aishell3: 0~173, vctk: 176\n\nckpt=snapshot_iter_99300\n\ngpus=1\nCUDA_VISIBLE_DEVICES=${gpus}\nstage=0\nstop_stage=100\n\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\n# check oov\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"check oov\"\n    python3 local/check_oov.py \\\n        --input_dir=${input_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --newdir_name=${newdir_name} \\\n        --lang=${lang}\nfi\n\n# get mfa result\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"get mfa result\"\n    python3 local/get_mfa_result.py \\\n        --input_dir=${new_dir} \\\n        --mfa_dir=${mfa_dir} \\\n        --lang=${lang}\nfi\n\n# generate durations.txt\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"generate durations.txt\"\n    python3 local/generate_duration.py \\\n        --mfa_dir=${mfa_dir} \nfi\n\n# extract feature\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"extract feature\"\n    python3 local/extract_feature.py \\\n        --duration_file=\"./durations.txt\" \\\n        --input_dir=${new_dir} \\\n        --dump_dir=${dump_dir} \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --replace_spkid=$replace_spkid\n\nfi\n\n# create finetune env\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    echo \"create finetune env\"\n    python3 local/prepare_env.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --output_dir=${output_dir}\nfi\n\n# finetune\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    echo \"finetune...\"\n    python3 local/finetune.py \\\n        --pretrained_model_dir=${pretrained_model_dir} \\\n        --dump_dir=${dump_dir} \\\n        --output_dir=${output_dir} \\\n        --ngpu=${ngpu} \\\n        --epoch=100 \\\n        --finetune_config=${finetune_config}\nfi\n\n# synthesize e2e\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    echo \"in hifigan syn_e2e\"\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_aishell3 \\\n        --am_config=${pretrained_model_dir}/default.yaml \\\n        --am_ckpt=${output_dir}/checkpoints/${ckpt}.pdz \\\n        --am_stat=${pretrained_model_dir}/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=pretrained_models/hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=pretrained_models/hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=pretrained_models/hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --lang=mix \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=./test_e2e/ \\\n        --phones_dict=${dump_dir}/phone_id_map.txt \\\n        --speaker_dict=${dump_dir}/speaker_id_map.txt \\\n        --spk_id=$replace_spkid\nfi\n\n\n"
  },
  {
    "path": "examples/tal_cs/asr1/README.md",
    "content": "# Transformer/Conformer ASR with TALCS\nThis example contains code used to train [u2](https://arxiv.org/pdf/2012.05481.pdf) model (Transformer or [Conformer](https://arxiv.org/pdf/2005.08100.pdf) model) with [TALCS dataset](https://ai.100tal.com/dataset)\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Get the sentencepiece model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Get ctc alignment of test data using the final model         |\n| 5     | Infer the single audio file                                  |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"conformer\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line:\n```bash\nbash run.sh --gpus 0,1 --avg_num 10\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev_set.meta\n|-- lang_char\n|   `-- bpe_bpe_11297.model\n|   `-- bpe_bpe_11297.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test_set.meta\n`-- train_set.meta\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 10\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/conformer.yaml conformer\navg.sh best exp/conformer/checkpoints 10\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_10\n```\n## Pretrained Model\nYou can get the pretrained transformer or conformer from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/tal_cs/asr1/asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz\ntar xzvf asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz\nsource path.sh\n# If you have process the data and get the manifest file， you can skip the following 2 steps\nbash local/data.sh --stage -1 --stop_stage -1\nbash local/data.sh --stage 2 --stop_stage 2\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_10\n```\nThe performance of the released models are shown in [here](./RESULTS.md).\n\n## Stage 5: Single Audio File Inference\nIn some situations, you want to use the trained model to do the inference for the single audio file. You can use stage 5. The code is shown below\n```bash\n if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n     # test a single .wav file\n     CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\n fi\n```\nyou can train the model by yourself using ```bash run.sh --stage 0 --stop_stage 3```, or you can download the pretrained model through the script below:\n```bash\nwget https://paddlespeech.cdn.bcebos.com/s2t/tal_cs/asr1/asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz\ntar xzvf asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz\n```\nYou can download the audio demo:\n```bash\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\n```\nYou need to prepare an audio file or use the audio demo above, please confirm the sample rate of the audio is 16K. You can get the result of the audio demo by running the script below.\n```bash\nCUDA_VISIBLE_DEVICES= ./local/test_wav.sh conf/conformer.yaml conf/tuning/decode.yaml exp/conformer/checkpoints/avg_10 data/demo_01_03.wav\n```\n"
  },
  {
    "path": "examples/tal_cs/asr1/RESULTS.md",
    "content": "# TALCS\n2023.1.6, commit id: fa724285f3b799b97b4348ad3b1084afc0764f9b (conformer)\n2025.8.11, commit id: 4f62ff05b7c9974d5642b26306ff3c7140c84312 (chunk_conformer)\n\n## Conformer\ntrain: Epoch 100, 3 V100-32G, best avg: 10\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | MER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-set | attention | 9.85091028213501 | 0.102786 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-set | ctc_greedy_search | 9.85091028213501 | 0.103538 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-set | ctc_prefix_beam_search | 9.85091028213501 | 0.103317 |  \n| conformer | 47.63 M | conf/conformer.yaml | spec_aug | test-set | attention_rescoring | 9.85091028213501 | 0.084374 | \n| chunk_conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug | test-set | attention | 9.897139549255371 | 0.080488 |\n| chunk_conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug | test-set | ctc_greedy_search | 9.897139549255371 | 0.093244 |\n| chunk_conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug | test-set | ctc_prefix_beam_search | 9.897139549255371 | 0.093251 |\n| chunk_conformer | 47.63 M | conf/chunk_conformer.yaml | spec_aug | test-set | attention_rescoring | 9.897139549255371 | 0.079193 | \n"
  },
  {
    "path": "examples/tal_cs/asr1/conf/chunk_conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 512    # dimension of attention\n    attention_heads: 8\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1   # sublayer output dropout\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 8\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1  # sublayer output dropout\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\n\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n\n###########################################\n#              Dataloader                 #\n###########################################\n\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: 'data/lang_char/bpe_bpe_11297'\nunit_type: 'spm'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 20.0\nwindow_ms: 30.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0\nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 100 \naccum_grad: 4\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/tal_cs/asr1/conf/conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 512    # dimension of attention\n    attention_heads: 8\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    cnn_module_kernel: 15\n    use_cnn_module: True\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 8\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: 'data/lang_char/bpe_bpe_11297'\nunit_type: 'spm'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 20.0\nwindow_ms: 30.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 5\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 2\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 100 \naccum_grad: 4\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/tal_cs/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 1.0\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n\n\n\n\n"
  },
  {
    "path": "examples/tal_cs/asr1/conf/tuning/chunk_decode.yaml",
    "content": "beam_size: 10\ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\nreverse_weight: 0.3 # reverse weight for attention rescoring decode mode.\ndecoding_chunk_size: 16 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: True  # simulate streaming inference. Defaults to False.\ndecode_batch_size: 128\nerror_rate_type: cer \n"
  },
  {
    "path": "examples/tal_cs/asr1/conf/tuning/decode.yaml",
    "content": "beam_size: 10\ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\n#reverse_weight: 0.3 # reverse weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\ndecode_batch_size: 1\nerror_rate_type: cer \n"
  },
  {
    "path": "examples/tal_cs/asr1/local/data.sh",
    "content": "#!/bin/bash\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\n# bpemode (unigram or bpe)\nnbpe=11297\nbpemode=bpe\nbpeprefix=\"${dict_dir}/bpe_${bpemode}_${nbpe}\"\n\nstride_ms=20\nwindow_ms=30\nsample_rate=16000\nfeat_dim=80\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\n#prepare data\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    if [ ! -d \"${MAIN_ROOT}/dataset/tal_cs/TALCS_corpus\" ]; then\n        echo \"${MAIN_ROOT}/dataset/tal_cs/TALCS_corpus does not exist. Please download tal_cs data and unpack it from https://ai.100tal.com/dataset first.\"\n        echo \"data md5 reference: 4c879b3c9c05365fc9dee1fc68713afe\"\n        exit\n    fi\n    # create manifest json file from TALCS_corpus\n    python ${MAIN_ROOT}/dataset/tal_cs/tal_cs.py --target_dir ${MAIN_ROOT}/dataset/tal_cs/TALCS_corpus/ --manifest_prefix data/\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=-1 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=${feat_dim}  \\\n    --delta_delta=false \\\n    --sample_rate=${sample_rate} \\\n    --stride_ms=${stride_ms} \\\n    --window_ms=${window_ms} \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n    echo \"compute mean and stddev done.\"\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    #use train_set build dict\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type 'spm' \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\"  \\\n    --manifest_paths=\"data/manifest.train.raw\"  \\\n    --spm_mode=${bpemode} \\\n    --spm_vocab_size=${nbpe}  \\\n    --spm_model_prefix=${bpeprefix} \\\n    --spm_character_coverage=1 \n    echo \"build dict done.\"\nfi\n\n#use new dict format data\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for sub in train dev test ; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type \"spm\" \\\n        --spm_model_prefix ${bpeprefix} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${sub}.raw\" \\\n        --output_path=\"data/manifest.${sub}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\n    echo \"format data done.\"\nfi\n"
  },
  {
    "path": "examples/tal_cs/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nfor type in attention ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    if [ ${chunk_mode} == true ];then\n        # stream decoding only support batchsize=1\n        batch_size=1\n    else\n        batch_size=64\n    fi\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nfor type in ctc_prefix_beam_search attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/tal_cs/asr1/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in  attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/tal_cs/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nprofiler_options=\nbenchmark_batch_size=0\nbenchmark_max_step=0\n\n# seed may break model convergence\nseed=0\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\n    echo \"using seed $seed & FLAGS_cudnn_deterministic=True ...\"\nfi\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\necho ${ips_config}\n\nmkdir -p exp\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nfi\n\n\nif [ ${seed} != 0  ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/tal_cs/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n# model exp\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/tal_cs/asr1/run.sh",
    "content": "#!/bin/bash\nsource path.sh || exit 1;\nset -e\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/conformer.yaml\nips=  #xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx\ndecode_conf_path=conf/tuning/decode.yaml\naverage_checkpoint=true\navg_num=10\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\naudio_file=\"data/demo_01_03.wav\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n\n# Not supported at now!!!\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi"
  },
  {
    "path": "examples/ted_en_zh/README.md",
    "content": "# TED En -> Zh\n\n* st0 - conformer/transformer speech translation\n"
  },
  {
    "path": "examples/ted_en_zh/st0/.gitignore",
    "content": "TED-En-Zh\ndata\nexp\n"
  },
  {
    "path": "examples/ted_en_zh/st0/README.md",
    "content": "\n# Transformer/Conformer ST0 with TED_En_Zh\nThis example contains code used to train a Transformer or [Conformer](http://arxiv.org/abs/2008.03802) model with TED_EN_Zh\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n\nYou need to download TED_En_Zh dataset by yourself.\n\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Calculate the CMVN of the train dataset <br>       (2) Get the vocabulary file <br>       (3) Get the manifest files of the train, development and test dataset<br> |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run ```stage 0```, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\nsource path.h\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop_stage` denotes the number of stages you want to end at in the experiments. \n`conf_path`denotes the config path of the model.\n`data_path` denotes the path of the dataset.\n`avg_num`denotes the number K of top-K models you want to average to get the final model.\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"transformer_mtl_noam\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 5\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in ```run.sh```to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.h\nbash ./local/data.sh\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in ```run.sh```. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.h\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model,  we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model.  We can use stage 2 to do this, and the code is shown below:\n```bash\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n```\nThe ```avg.sh```is in the ```../../../utils/```which is define in the ```path.sh```.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.h\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam\navg.sh best exp/transformer_mtl_noam/checkpoints 5\n```\n## Stage 3: Model Testing\nThe  stage 3 is to evaluate the model performance. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.h\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam\navg.sh latest exp/transformer_mtl_noam/checkpoints 5\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer_mtl_noam.yaml conf/tuning/decode.yaml exp/transformer_mtl_noam/checkpoints/avg_5\n```\nThe performance of the released models are shown below:\n### Transformer\n| Model               | Params | Config                           | Char-BLEU |\n| ------------------- | ------ | -------------------------------- | --------- |\n| Transformer+ASR MTL | 50.26M | conf/transformer_joint_noam.yaml | 17.38     |\n"
  },
  {
    "path": "examples/ted_en_zh/st0/RESULTS.md",
    "content": "\n# TED En-Zh\n\n## Dataset\n\n| Data Subset | Duration in Seconds |\n| --- | --- |\n| data/manifest.train | 0.942 ~ 60   |\n| data/manifest.dev   | 1.151 ~ 39   |\n| data/manifest.test  | 1.1 ~ 42.746 |\n\n## Transformer\n| Model | Params | Config | Char-BLEU |\n| --- | --- | --- | --- |\n| Transformer+ASR MTL | 50.26M | conf/transformer_joint_noam.yaml | 17.38 |\n"
  },
  {
    "path": "examples/ted_en_zh/st0/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/ted_en_zh/st0/conf/transformer.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nmin_input_len: 0.05  # second\nmax_input_len: 30.0 # second\nmin_output_len: 0.0 # tokens\nmax_output_len: 400.0 # tokens\nmin_output_input_ratio: 0.01\nmax_output_input_ratio: 20.0\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_char/bpe_unigram_8000\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nbatch_size: 16\nmaxlen_in: 5  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nraw_wav: True  # use raw_wav or kaldi feature\nspectrum_type: fbank #linear, mfcc, fbank\nfeat_dim: 80\ndelta_delta: False\ndither: 1.0\ntarget_sample_rate: 16000\nmax_freq: None\nn_fft: None\nstride_ms: 10.0\nwindow_ms: 25.0\nuse_dB_normalization: True\ntarget_dB: -20\nrandom_seed: 0\nkeep_transcription_text: False\nsortagrad: True \nshuffle_method: batch_shuffle\nnum_workers: 2\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \"data/mean_std.json\"\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 120\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 1.0e-06\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/ted_en_zh/st0/conf/transformer_mtl_noam.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\nmin_input_len: 0.05  # second\nmax_input_len: 30.0 # second\nmin_output_len: 0.0 # tokens\nmax_output_len: 400.0 # tokens\nmin_output_input_ratio: 0.01\nmax_output_input_ratio: 20.0\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_char/bpe_unigram_8000\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nbatch_size: 16\nmaxlen_in: 5  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nraw_wav: True  # use raw_wav or kaldi feature\nspectrum_type: fbank #linear, mfcc, fbank\nfeat_dim: 80\ndelta_delta: False\ndither: 1.0\ntarget_sample_rate: 16000\nmax_freq: None\nn_fft: None\nstride_ms: 10.0\nwindow_ms: 25.0\nuse_dB_normalization: True\ntarget_dB: -20\nrandom_seed: 0\nkeep_transcription_text: False\nsortagrad: True \nshuffle_method: batch_shuffle\nnum_workers: 2\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \"data/mean_std.json\"\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.5\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 120\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 1.0e-06\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n\n\n"
  },
  {
    "path": "examples/ted_en_zh/st0/conf/tuning/decode.yaml",
    "content": "batch_size: 1\nerror_rate_type: char-bleu\ndecoding_method: fullsentence  # 'fullsentence', 'simultaneous'\nbeam_size: 10\nword_reward: 0.7\nmaxlenratio: 0.3\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False."
  },
  {
    "path": "examples/ted_en_zh/st0/local/data.sh",
    "content": "#!/bin/bash\n\nset -e\n\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\n# bpemode (unigram or bpe)\nnbpe=8000\nbpemode=unigram\nbpeprefix=\"${dict_dir}/bpe_${bpemode}_${nbpe}\"\ndata_dir=./TED-En-Zh\n\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\n\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\nmkdir -p data\nmkdir -p ${dict_dir}\n\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    if [ ! -e ${data_dir} ]; then\n        echo \"Error: ${data_dir} Dataset is not avaiable. Please download and unzip the dataset\"\n        echo \"Download Link: https://pan.baidu.com/s/18L-59wgeS96WkObISrytQQ Passwd: bva0\"\n        echo \"The tree of the directory should be:\"\n        echo \".\"\n        echo \"|-- En-Zh\"\n        echo \"|-- test-segment\"\n        echo \"    |-- tst2010\"\n        echo \"    |-- ...\"\n        echo \"|-- train-split\"\n        echo \"    |-- train-segment\"\n        echo \"|-- README.md\"\n\n        exit 1\n    fi\n\n    # generate manifests\n    python3 ${TARGET_DIR}/ted_en_zh/ted_en_zh.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --src-dir=\"${data_dir}\"\n\n    echo \"Complete raw data pre-process.\"\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=-1 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type \"spm\" \\\n    --spm_vocab_size=${nbpe} \\\n    --spm_mode ${bpemode} \\\n    --spm_model_prefix ${bpeprefix} \\\n    --spm_character_coverage 1. \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --text_keys 'text' \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type \"spm\" \\\n        --spm_model_prefix ${bpeprefix} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"Ted En-Zh Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st0/local/test.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nfor type in fullsentence; do\n    echo \"decoding ${type}\"\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st0/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2_st\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/ted_en_zh/st0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/transformer_mtl_noam.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=5\ndata_path=./TED_EnZh # path to unzipped data\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh --data_dir ${data_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n"
  },
  {
    "path": "examples/ted_en_zh/st1/.gitignore",
    "content": "TED_EnZh\ndata\nexp\n"
  },
  {
    "path": "examples/ted_en_zh/st1/README.md",
    "content": "# Transformer/Conformer ST1 with TED_En_Zh\nThis example contains code used to train a Transformer or [Conformer](http://arxiv.org/abs/2008.03802) model with TED_EN_Zh.\n\nTo use this example, you need to install Kaldi first.\n\nThe main difference between st0 and st1 is that st1 uses kaldi feature.\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n\nYou need to download TED_En_Zh dataset by yourself.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Calculate the CMVN of the train dataset <br>       (2) Get the vocabulary file <br>       (3) Get the manifest files of the train, development and test dataset<br> |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in ```run.sh```in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n. ./cmd.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n `stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`data_path` denotes the path of the dataset.\n`avg_num`denotes the number K of top-K models you want to average to get the final model.\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"transformer_mtl_noam\"\n\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 5\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in ```run.sh```to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in ```run.sh```. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    if [ -n \"${ckpt_path}\" ]; then\n        echo \"Finetune from Pretrained Model\" ${ckpt_path}\n        ./local/download_pretrain.sh || exit -1\n    fi \n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} \"${ckpt_path}\"\nfi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam \"\"\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model,  we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model.  We can use stage 2 to do this, and the code is shown below:\n```bash\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n```\nThe ```avg.sh```is in the ```../../../utils/```which is define in the ```path.sh```.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam\navg.sh best exp/transformer_mtl_noam/checkpoints 5\n```\n## Stage 3: Model Testing\nThe  stage 3 is to evaluate the model performance. The code of this stage is shown below:\n```bash\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\n. ./cmd.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer_mtl_noam.yaml transformer_mtl_noam\navg.sh latest exp/transformer_mtl_noam/checkpoints 5\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer_mtl_noam.yaml exp/transformer_mtl_noam/checkpoints/avg_5\n```\nThe performance of the released models are shown below:\n### Transformer\n| Model | Params | Config | Val loss | Char-BLEU |\n| --- | --- | --- | --- | --- |\n| FAT + Transformer+ASR MTL | 50.26M | conf/transformer_mtl_noam.yaml | 62.86 | 19.45 |\n| FAT + Transformer+ASR MTL with word reward | 50.26M | conf/transformer_mtl_noam.yaml | 62.86 | 20.80 |\n"
  },
  {
    "path": "examples/ted_en_zh/st1/RESULTS.md",
    "content": "\n# TED En-Zh\n\n## Dataset\n\n| Data Subset | Duration in Frames |\n| --- | --- |\n| data/manifest.train | 94.2 ~ 6000   |\n| data/manifest.dev   | 115.1 ~ 3900   |\n| data/manifest.test  | 110 ~ 4274.6 |\n\n## Transformer\n| Model | Params | Config | Val loss | Char-BLEU |\n| --- | --- | --- | --- | --- |\n| FAT + Transformer+ASR MTL | 50.26M | conf/transformer_mtl_noam.yaml | 69.91 | 20.26 |\n| FAT + Transformer+ASR MTL with word reward | 50.26M | conf/transformer_mtl_noam.yaml | 62.86 | 20.80 |\n"
  },
  {
    "path": "examples/ted_en_zh/st1/cmd.sh",
    "content": "# ====== About run.pl, queue.pl, slurm.pl, and ssh.pl ======\n# Usage: <cmd>.pl [options] JOB=1:<nj> <log> <command...>\n# e.g.\n#   run.pl --mem 4G JOB=1:10 echo.JOB.log echo JOB\n#\n# Options:\n#   --time <time>: Limit the maximum time to execute.\n#   --mem <mem>: Limit the maximum memory usage.\n#   -–max-jobs-run <njob>: Limit the number parallel jobs. This is ignored for non-array jobs.\n#   --num-threads <ngpu>: Specify the number of CPU core.\n#   --gpu <ngpu>: Specify the number of GPU devices.\n#   --config: Change the configuration file from default.\n#\n# \"JOB=1:10\" is used for \"array jobs\" and it can control the number of parallel jobs.\n# The left string of \"=\", i.e. \"JOB\", is replaced by <N>(Nth job) in the command and the log file name,\n# e.g. \"echo JOB\" is changed to \"echo 3\" for the 3rd job and \"echo 8\" for 8th job respectively.\n# Note that the number must start with a positive number, so you can't use \"JOB=0:10\" for example.\n#\n# run.pl, queue.pl, slurm.pl, and ssh.pl have unified interface, not depending on its backend.\n# These options are mapping to specific options for each backend and\n# it is configured by \"conf/queue.conf\" and \"conf/slurm.conf\" by default.\n# If jobs failed, your configuration might be wrong for your environment.\n#\n#\n# The official documentation for run.pl, queue.pl, slurm.pl, and ssh.pl:\n#   \"Parallelization in Kaldi\": http://kaldi-asr.org/doc/queue.html\n# =========================================================~\n\n\n# Select the backend used by run.sh from \"local\", \"sge\", \"slurm\", or \"ssh\"\ncmd_backend='local'\n\n# Local machine, without any Job scheduling system\nif [ \"${cmd_backend}\" = local ]; then\n\n    # The other usage\n    export train_cmd=\"run.pl\"\n    # Used for \"*_train.py\": \"--gpu\" is appended optionally by run.sh\n    export cuda_cmd=\"run.pl\"\n    # Used for \"*_recog.py\"\n    export decode_cmd=\"run.pl\"\n\n# \"qsub\" (SGE, Torque, PBS, etc.)\nelif [ \"${cmd_backend}\" = sge ]; then\n    # The default setting is written in conf/queue.conf.\n    # You must change \"-q g.q\" for the \"queue\" for your environment.\n    # To know the \"queue\" names, type \"qhost -q\"\n    # Note that to use \"--gpu *\", you have to setup \"complex_value\" for the system scheduler.\n\n    export train_cmd=\"queue.pl\"\n    export cuda_cmd=\"queue.pl\"\n    export decode_cmd=\"queue.pl\"\n\n# \"sbatch\" (Slurm)\nelif [ \"${cmd_backend}\" = slurm ]; then\n    # The default setting is written in conf/slurm.conf.\n    # You must change \"-p cpu\" and \"-p gpu\" for the \"partition\" for your environment.\n    # To know the \"partition\" names, type \"sinfo\".\n    # You can use \"--gpu * \" by default for slurm and it is interpreted as \"--gres gpu:*\"\n    # The devices are allocated exclusively using \"${CUDA_VISIBLE_DEVICES}\".\n\n    export train_cmd=\"slurm.pl\"\n    export cuda_cmd=\"slurm.pl\"\n    export decode_cmd=\"slurm.pl\"\n\nelif [ \"${cmd_backend}\" = ssh ]; then\n    # You have to create \".queue/machines\" to specify the host to execute jobs.\n    # e.g. .queue/machines\n    #   host1\n    #   host2\n    #   host3\n    # Assuming you can login them without any password, i.e. You have to set ssh keys.\n\n    export train_cmd=\"ssh.pl\"\n    export cuda_cmd=\"ssh.pl\"\n    export decode_cmd=\"ssh.pl\"\n\n# This is an example of specifying several unique options in the JHU CLSP cluster setup.\n# Users can modify/add their own command options according to their cluster environments.\nelif [ \"${cmd_backend}\" = jhu ]; then\n\n    export train_cmd=\"queue.pl --mem 2G\"\n    export cuda_cmd=\"queue-freegpu.pl --mem 2G --gpu 1 --config conf/gpu.conf\"\n    export decode_cmd=\"queue.pl --mem 4G\"\n\nelse\n    echo \"$0: Error: Unknown cmd_backend=${cmd_backend}\" 1>&2\n    return 1\nfi\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/fbank.conf",
    "content": "--sample-frequency=16000 \n--num-mel-bins=80\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/pitch.conf",
    "content": "--sample-frequency=16000\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/preprocess.yaml",
    "content": "process:\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/transformer.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/ted_en_zh_bpe8000.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_char/ted_en_zh_bpe8000\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.0\n    ctc_weight: 0.0\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/transformer_mtl_noam.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/ted_en_zh_bpe8000.txt\nunit_type: 'spm'\nspm_model_prefix: data/lang_char/ted_en_zh_bpe8000\nmean_std_filepath: \"\"\n# preprocess_config: conf/augmentation.json\nbatch_size: 20\nfeat_dim: 83\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config:\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: None\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    asr_weight: 0.5\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 40\naccum_grad: 2\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 2.5\n  weight_decay: 0.\nscheduler: noam    \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 50\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/ted_en_zh/st1/conf/tuning/decode.yaml",
    "content": "\nbatch_size: 1\nerror_rate_type: char-bleu\ndecoding_method: fullsentence  # 'fullsentence', 'simultaneous'\nbeam_size: 10\nword_reward: 0.7\nmaxlenratio: 0.3\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False."
  },
  {
    "path": "examples/ted_en_zh/st1/local/convert_torch_to_paddle.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport paddle\nimport torch\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\ndef torch2paddle(args):\n    paddle.set_device('cpu')\n    paddle_model_dict = {}\n    torch_model = torch.load(args.torch_ckpt, map_location='cpu')\n    cnt = 0\n    for k, v in torch_model['model'].items():\n        # encoder.embed.* --> encoder.embed.*\n        if k.startswith('encoder.embed'):\n            if v.ndim == 2:\n                v = v.transpose(0, 1)\n            paddle_model_dict[k] = v.numpy()\n            cnt += 1\n            logger.info(\n                f\"Convert torch weight: {k} to paddlepaddle weight: {k}, shape is {v.shape}\"\n            )\n\n        # encoder.after_norm.* --> encoder.after_norm.*\n        # encoder.after_norm.* --> decoder.after_norm.*\n        # encoder.after_norm.* --> st_decoder.after_norm.*\n        if k.startswith('encoder.after_norm'):\n            paddle_model_dict[k] = v.numpy()\n            cnt += 1\n            paddle_model_dict[k.replace('en', 'de')] = v.numpy()\n            logger.info(\n                f\"Convert torch weight: {k} to paddlepaddle weight: {k.replace('en','de')}, shape is {v.shape}\"\n            )\n            paddle_model_dict['st_' + k.replace('en', 'de')] = v.numpy()\n            logger.info(\n                f\"Convert torch weight: {k} to paddlepaddle weight: {'st_'+ k.replace('en','de')}, shape is {v.shape}\"\n            )\n            cnt += 2\n\n        # encoder.encoders.* --> encoder.encoders.*\n        # encoder.encoders.* (last six layers) --> decoder.encoders.* (first six layers)\n        # encoder.encoders.* (last six layers) --> st_decoder.encoders.* (first six layers)\n        if k.startswith('encoder.encoders'):\n            if v.ndim == 2:\n                v = v.transpose(0, 1)\n            paddle_model_dict[k] = v.numpy()\n            logger.info(\n                f\"Convert torch weight: {k} to paddlepaddle weight: {k}, shape is {v.shape}\"\n            )\n            cnt += 1\n            origin_k = k\n            k_split = k.split('.')\n            if int(k_split[2]) >= 6:\n                k = k.replace(k_split[2], str(int(k_split[2]) - 6))\n                paddle_model_dict[k.replace('en', 'de')] = v.numpy()\n                logger.info(\n                    f\"Convert torch weight: {origin_k} to paddlepaddle weight: {k.replace('en','de')}, shape is {v.shape}\"\n                )\n                paddle_model_dict['st_' + k.replace('en', 'de')] = v.numpy()\n                logger.info(\n                    f\"Convert torch weight: {origin_k} to paddlepaddle weight: {'st_'+ k.replace('en','de')}, shape is {v.shape}\"\n                )\n                cnt += 2\n    logger.info(f\"Convert {cnt} weights totally from torch to paddlepaddle\")\n    paddle.save(paddle_model_dict, args.paddle_ckpt)\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        '--torch_ckpt',\n        type=str,\n        default='/home/snapshot.ep.98',\n        help=\"Path to torch checkpoint.\")\n    parser.add_argument(\n        '--paddle_ckpt',\n        type=str,\n        default='paddle.98.pdparams',\n        help=\"Path to save paddlepaddle checkpoint.\")\n    args = parser.parse_args()\n    torch2paddle(args)\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/data.sh",
    "content": "#!/bin/bash\n\nset -e\n\nstage=-1\nstop_stage=100\ndict_dir=data/lang_char\n\n# bpemode (unigram or bpe)\nnbpe=8000\nbpemode=bpe\nbpeprefix=\"${dict_dir}/bpe_${bpemode}_${nbpe}\"\ndata_dir=./TED_EnZh\ntarget_dir=data/ted_en_zh\ndumpdir=data/dump\ndo_delta=false\nnj=20\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\nmkdir -p data\nmkdir -p ${dict_dir}\n\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    if [ ! -e ${data_dir} ]; then\n        echo \"Error: Dataset is not avaiable. Please download and unzip the dataset\"\n        echo \"Download Link: https://pan.baidu.com/s/18L-59wgeS96WkObISrytQQ Passwd: bva0\"\n        echo \"The tree of the directory should be:\"\n        echo \".\"\n        echo \"|-- En-Zh\"\n        echo \"|-- test-segment\"\n        echo \"    |-- tst2010\"\n        echo \"    |-- ...\"\n        echo \"|-- train-split\"\n        echo \"    |-- train-segment\"\n        echo \"|-- README.md\"\n\n        exit 1\n    fi\n\n    # extract data \n    echo \"data Extraction\"\n    python3 local/ted_en_zh.py \\\n    --tgt-dir=${target_dir} \\\n    --src-dir=${data_dir}\n\nfi\nprep_dir=${target_dir}/data_prep \nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    ### Task dependent. You have to make data the following preparation part by yourself.\n    ### But you can utilize Kaldi recipes in most cases\n    echo \"stage 0: Data preparation\"\n    for set in train dev test; do\n    # for set in train; do\n        dst=${target_dir}/${set}\n        for lang in en zh; do\n\n            if [ ${lang} = 'en' ]; then\n                echo \"remove punctuation $lang\"\n                # remove punctuation\n                local/remove_punctuation.pl < ${dst}/${lang}.org > ${dst}/${lang}.raw\n            else\n                cp ${dst}/${lang}.org ${dst}/${lang}.raw\n            fi\n\n            paste -d \" \" ${dst}/.yaml ${dst}/${lang}.raw | sort > ${dst}/text.${lang}\n\n\n        done\n        # error check\n        n=$(cat ${dst}/.yaml | wc -l)\n        n_en=$(cat ${dst}/en.raw | wc -l)\n        n_tgt=$(cat ${dst}/zh.raw | wc -l)\n        [ ${n} -ne ${n_en} ] && echo \"Warning: expected ${n} data data files, found ${n_en}\" && exit 1;\n        [ ${n} -ne ${n_tgt} ] && echo \"Warning: expected ${n} data data files, found ${n_tgt}\" && exit 1;\n\n        echo \"done text processing\"\n        cat ${dst}/wav.scp.org | uniq | sort -k1,1 -u > ${dst}/wav.scp\n        cat ${dst}/utt2spk.org | uniq | sort -k1,1 -u > ${dst}/utt2spk\n\n        cat ${dst}/utt2spk | utils/utt2spk_to_spk2utt.pl | sort -k1,1 -u > ${dst}/spk2utt\n        rm -rf ${prep_dir}/${set}.en-zh\n        mkdir -p ${prep_dir}/${set}.en-zh\n        echo \"remove duplicate lines...\"\n        cut -d ' ' -f 1 ${dst}/text.en | sort | uniq -c | sort -n -k1 -r | grep -v '1 ted-en-zh' \\\n            | sed 's/^[ \\t]*//' > ${dst}/duplicate_lines\n        cut -d ' ' -f 1 ${dst}/text.en | sort | uniq -c | sort -n -k1 -r | grep '1 ted-en-zh' \\\n            | cut -d '1' -f 2- | sed 's/^[ \\t]*//' > ${dst}/reclist\n        reduce_data_dir.sh ${dst} ${dst}/reclist ${prep_dir}/${set}.en-zh\n        echo \"done wav processing\"\n        for l in en zh; do\n            cp ${dst}/text.${l} ${prep_dir}/${set}.en-zh/text.${l}\n        done\n        utils/fix_data_dir.sh --utt_extra_files \\\n        \"text.en text.zh\" \\\n        ${prep_dir}/${set}.en-zh\n    done\nfi\n\nfeat_tr_dir=${dumpdir}/train_sp/delta${do_delta}; mkdir -p ${feat_tr_dir}\nfeat_dt_dir=${dumpdir}/dev/delta${do_delta}; mkdir -p ${feat_dt_dir}\nfeat_trans_dir=${dumpdir}/test/delta${do_delta}; mkdir -p ${feat_trans_dir}\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ### Task dependent. You have to design training and dev sets by yourself.\n    ### But you can utilize Kaldi recipes in most cases\n    echo \"stage 1: Feature Generation\"\n    fbankdir=data/fbank\n    # Generate the fbank features; by default 80-dimensional fbanks with pitch on each frame\n    for x in train dev test; do\n        steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj ${nj} --write_utt2num_frames true \\\n            ${prep_dir}/${x}.en-zh data/make_fbank/${x} ${fbankdir}\n    done\n    \n    echo \"speed perturbation\"\n    utils/perturb_data_dir_speed.sh 0.9 ${prep_dir}/train.en-zh ${prep_dir}/temp1.en-zh\n    utils/perturb_data_dir_speed.sh 1.0 ${prep_dir}/train.en-zh ${prep_dir}/temp2.en-zh\n    utils/perturb_data_dir_speed.sh 1.1 ${prep_dir}/train.en-zh ${prep_dir}/temp3.en-zh\n\n    utils/combine_data.sh --extra-files utt2uniq ${prep_dir}/train_sp.en-zh \\\n    ${prep_dir}/temp1.en-zh ${prep_dir}/temp2.en-zh ${prep_dir}/temp3.en-zh\n    rm -r ${prep_dir}/temp*.en-zh \n    utils/fix_data_dir.sh ${prep_dir}/train_sp.en-zh\n\n    steps/make_fbank_pitch.sh --cmd \"$train_cmd\" --nj ${nj} --write_utt2num_frames true \\\n        ${prep_dir}/train_sp.en-zh exp/make_fbank/train_sp.en-zh ${fbankdir}\n\n    for lang in en zh; do\n        cat /dev/null > ${prep_dir}/train_sp.en-zh/text.${lang}\n        for p in \"sp0.9-\" \"sp1.0-\" \"sp1.1-\"; do\n            awk -v p=${p} '{printf(\"%s %s%s\\n\", $1, p, $1);}' ${prep_dir}/train.en-zh/utt2spk > ${prep_dir}/train_sp.en-zh/utt_map\n            utils/apply_map.pl -f 1 ${prep_dir}/train_sp.en-zh/utt_map < ${prep_dir}/train.en-zh/text.${lang} >>${prep_dir}/train_sp.en-zh/text.${lang}\n        done\n    done\n\n    for x in train_sp dev test; do\n        local/divide_lang.sh ${prep_dir}/${x}.en-zh zh\n    done\n\n    for x in train_sp dev; do\n        # remove utt having more than 3000 frames\n        # remove utt having more than 400 characters\n        for lang in zh en; do\n            remove_longshortdata.sh --maxframes 3000 --maxchars 400 ${prep_dir}/${x}.en-zh.${lang} ${prep_dir}/${x}.en-zh.${lang}.tmp\n        done\n        cut -f 1 -d \" \" ${prep_dir}/${x}.en-zh.en.tmp/text > ${prep_dir}/${x}.en-zh.${lang}.tmp/reclist1\n        cut -f 1 -d \" \" ${prep_dir}/${x}.en-zh.${lang}.tmp/text > ${prep_dir}/${x}.en-zh.${lang}.tmp/reclist2\n        comm -12 ${prep_dir}/${x}.en-zh.${lang}.tmp/reclist1 ${prep_dir}/${x}.en-zh.${lang}.tmp/reclist2 > ${prep_dir}/${x}.en-zh.en.tmp/reclist\n\n        for lang in zh en; do\n            reduce_data_dir.sh ${prep_dir}/${x}.en-zh.${lang}.tmp ${prep_dir}/${x}.en-zh.en.tmp/reclist ${prep_dir}/${x}.en-zh.${lang}\n            utils/fix_data_dir.sh  ${prep_dir}/${x}.en-zh.${lang}\n        done\n        rm -rf ${prep_dir}/${x}.en-zh.*.tmp\n    done\n\n    compute-cmvn-stats scp:${prep_dir}/train_sp.en-zh.zh/feats.scp ${prep_dir}/train_sp.en-zh.zh/cmvn.ark\n\n    dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta $do_delta \\\n        ${prep_dir}/train_sp.en-zh.zh/feats.scp ${prep_dir}/train_sp.en-zh.zh/cmvn.ark ${prep_dir}/dump_feats/train_sp.en-zh.zh ${feat_tr_dir}\n    dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta $do_delta \\\n        ${prep_dir}/dev.en-zh.zh/feats.scp ${prep_dir}/train_sp.en-zh.zh/cmvn.ark ${prep_dir}/dump_feats/dev.en-zh.zh ${feat_dt_dir}\n    dump.sh --cmd \"$train_cmd\" --nj ${nj} --do_delta $do_delta \\\n        ${prep_dir}/test.en-zh.zh/feats.scp ${prep_dir}/train_sp.en-zh.zh/cmvn.ark ${prep_dir}/dump_feats/test.en-zh.zh ${feat_trans_dir}\nfi\n\ndict=${dict_dir}/ted_en_zh_${bpemode}${nbpe}.txt\nnlsyms=${dict_dir}/ted_en_zh_non_lang_syms.txt\nbpemodel=${dict_dir}/ted_en_zh_${bpemode}${nbpe}\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"stage 2: Dictionary and Json Data Preparation\"\n\n    echo \"make a joint source and target dictionary\"\n    echo \"<unk> 1\" > ${dict} # <unk> must be 1, 0 will be used for \"blank\" in CTC\n    offset=$(wc -l < ${dict})\n    grep sp1.0 ${prep_dir}/train_sp.en-zh.*/text | cut -f 2- -d' ' | grep -v -e '^\\s*$' > ${dict_dir}/input.txt\n    spm_train  --input=${dict_dir}/input.txt --vocab_size=${nbpe} --model_type=${bpemode} --model_prefix=${bpemodel} --input_sentence_size=100000000 --character_coverage=1.0\n    spm_encode --model=${bpemodel}.model --output_format=piece < ${dict_dir}/input.txt | tr ' ' '\\n' | sort | uniq | awk -v offset=${offset} '{print $0 \" \" NR+offset}' >> ${dict}\n    wc -l ${dict}\n\n    echo \"make json files\"\n    data2json.sh --nj ${nj} --feat ${feat_tr_dir}/feats.scp --text ${prep_dir}/train_sp.en-zh.zh/text --bpecode ${bpemodel}.model --lang zh \\\n        ${prep_dir}/train_sp.en-zh.zh ${dict} > ${feat_tr_dir}/data_${bpemode}${nbpe}.json\n    data2json.sh --feat ${feat_dt_dir}/feats.scp --text ${prep_dir}/dev.en-zh.zh/text --bpecode ${bpemodel}.model --lang zh \\\n        ${prep_dir}/dev.en-zh.zh ${dict} > ${feat_dt_dir}/data_${bpemode}${nbpe}.json\n    data2json.sh --feat ${feat_trans_dir}/feats.scp --text ${prep_dir}/test.en-zh.zh/text --bpecode ${bpemodel}.model --lang zh \\\n        ${prep_dir}/test.en-zh.zh ${dict} > ${feat_trans_dir}/data_${bpemode}${nbpe}.json\n    echo \"update json (add source references)\"\n    # update json (add source references)\n    for x in train_sp dev; do\n        feat_dir=${dumpdir}/${x}/delta${do_delta}\n        data_dir=${prep_dir}/$(echo ${x} | cut -f 1 -d \".\").en-zh.en\n        update_json.sh --text ${data_dir}/text --bpecode ${bpemodel}.model \\\n            ${feat_dir}/data_${bpemode}${nbpe}.json ${data_dir} ${dict}\n    done\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    x=(${feat_tr_dir} ${feat_dt_dir} ${feat_trans_dir})\n    y=(train dev test)\n    echo \"stage 3: Format the Json Data\"\n    for (( i=0; i<${#x[*]}; ++i)); do\n        python3 ${MAIN_ROOT}/utils/espnet_json_to_manifest.py \\\n         --json-file ${x[$i]}/data_${bpemode}${nbpe}.json \\\n         --manifest-file data/manifest.${y[$i]}\n    done\nfi\necho \"Ted En-Zh Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/divide_lang.sh",
    "content": "#!/bin/bash\n\n# Copyright 2019 Kyoto University (Hirofumi Inaguma)\n#           2021 PaddlePaddle\n#  Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\n\n. ./path.sh\n\nif [ \"$#\" -ne 2 ]; then\n    echo \"Usage: $0 <set> <lang>>\"\n    echo \"e.g.: $0 dev\"\n    exit 1\nfi\n\nset=$1\nlang=$2\nexport LC_ALL=en_US.UTF-8\n# Copy stuff intoc its final locations [this has been moved from the format_data script]\n# for En\nmkdir -p ${set}.en\nfor f in spk2utt utt2spk segments wav.scp feats.scp utt2num_frames; do\n    if [ -f ${set}/${f} ]; then\n        sort ${set}/${f} > ${set}.en/${f}\n    fi\ndone\nsort ${set}/text.en | sed $'s/[^[:print:]]//g' > ${set}.en/text \n\nutils/fix_data_dir.sh ${set}.en\nif [ -f ${set}.en/feats.scp ]; then\n    utils/validate_data_dir.sh ${set}.en || exit 1;\nelse\n    utils/validate_data_dir.sh --no-feats --no-wav ${set}.en || exit 1;\nfi\n\n# for target language\nmkdir -p ${set}.${lang}\nfor f in spk2utt utt2spk segments wav.scp feats.scp utt2num_frames; do\n    if [ -f ${set}/${f} ]; then\n        sort ${set}/${f} > ${set}.${lang}/${f}\n    fi\ndone\nsort ${set}/text.${lang} | sed $'s/[^[:print:]]//g' > ${set}.${lang}/text \nutils/fix_data_dir.sh  ${set}.${lang}\nif [ -f ${set}.${lang}/feats.scp ]; then\n    utils/validate_data_dir.sh ${set}.${lang} || exit 1;\nelse\n    utils/validate_data_dir.sh --no-feats --no-wav ${set}.${lang} || exit 1;\nfi\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/download_pretrain.sh",
    "content": "#!/bin/bash\n\n# download pytorch weight\nwget https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/snapshot.ep.98 --no-check-certificate\n\n# convert pytorch weight to paddlepaddle\npython local/convert_torch_to_paddle.py \\\n--torch_ckpt snapshot.ep.98 \\\n--paddle_ckpt paddle.98.pdparams\n\n# Or you can download converted weights\n# wget https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/paddle.98.pdparams --no-check-certificate\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in downloading and coverting!\"\n    exit 1\nfi\n\nexit 0"
  },
  {
    "path": "examples/ted_en_zh/st1/local/remove_punctuation.pl",
    "content": "#!/usr/bin/perl\n\nuse warnings;\nuse strict;\n\nbinmode(STDIN,\":utf8\");\nbinmode(STDOUT,\":utf8\");\n\nwhile(<STDIN>) {\n  $_ = \" $_ \";\n\n  # remove punctuation except apostrophe\n  s/<space>/spacemark/g;  # for scoring\n  s/'/apostrophe/g;\n  s/[[:punct:]]//g;\n  s/apostrophe/'/g;\n  s/spacemark/<space>/g;  # for scoring\n\n  # remove whitespace\n  s/\\s+/ /g;\n  s/^\\s+//;\n  s/\\s+$//;\n\n  print \"$_\\n\";\n}\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/ted_en_zh.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport codecs\nimport os\n\n\n# org_split = 'train-split/train-segment'\n# text_file = 'En-Zh/train.en-zh'\n# data_split = 'train'\ndef data_process(src_dir, tgt_dir, wav_dir_list, text_file_list,\n                 data_split_list):\n\n    for org_split, text_file, data_split in zip(wav_dir_list, text_file_list,\n                                                data_split_list):\n        local_data_split_dir = os.path.join(tgt_dir, data_split)\n\n        os.makedirs(local_data_split_dir, exist_ok=True)\n        utts = []\n        utt2spk = {}\n        with open(os.path.join(local_data_split_dir, 'wav.scp.org'), 'w') as wav_wf, \\\n            open(os.path.join(local_data_split_dir, 'utt2spk.org'), 'w') as utt2spk_wf:\n            for files in os.listdir(os.path.join(src_dir, org_split)):\n                files = files.strip()\n                file_path = os.path.join(src_dir, org_split, files)\n                size = os.path.getsize(file_path)\n                if size <= 30000:\n                    continue\n                utt = files.split('.')[0]\n                audio_name = utt.split('_')[0]\n                #format the name of utterance \n                while len(audio_name) < 6:\n                    utt = '0' + utt\n                    audio_name = '0' + audio_name\n                utt = 'ted-en-zh-' + utt\n                utts.append(utt)\n                spk = utt.split('_')[0]\n                utt2spk[utt] = spk\n                assert len(spk) == 16, \"%r\" % spk\n                print(utt, 'cat', os.path.abspath(file_path), '|', file=wav_wf)\n            for utt in sorted(utts):\n                print(utt, utt2spk[utt], file=utt2spk_wf)\n\n        with open(os.path.join(local_data_split_dir, 'en.org'), 'w') as en_wf, \\\n            open(os.path.join(local_data_split_dir, 'zh.org'), 'w') as zh_wf, \\\n            open(os.path.join(local_data_split_dir, '.yaml'), 'w') as yaml_wf, \\\n            codecs.open(os.path.join(src_dir, text_file), 'r', encoding='utf-8',\n                        errors='ignore') as rf:\n            count = 0\n            for line in rf:\n                line = line.strip()\n                line_spl = line.split('\\t')\n                assert len(line_spl) == 3, \"%r\" % line\n                wav, en, zh = line_spl\n                assert wav.endswith('wav'), \"%r\" % wav[-3:]\n                utt = wav.split('.')[0]\n                audio_name = utt.split('_')[0]\n                while len(audio_name) < 6:\n                    utt = '0' + utt\n                    audio_name = '0' + audio_name\n                utt = 'ted-en-zh-' + utt\n                print(utt, file=yaml_wf)\n                print(en.lower(), file=en_wf)\n                print(zh, file=zh_wf)\n                count += 1\n            print('%s set lines count: %d' % (data_split, count))\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description=__doc__)\n\n    parser.add_argument(\n        \"--src-dir\",\n        default=\"\",\n        type=str,\n        help=\"Directory to kaldi splited data. (default: %(default)s)\")\n    parser.add_argument(\n        \"--tgt-dir\",\n        default=\"local/ted_en_zh\",\n        type=str,\n        help=\"Directory to save processed data. (default: %(default)s)\")\n    args = parser.parse_args()\n\n    wav_dir_list = [\n        'train-split/train-segment', 'test-segment/tst2014',\n        'test-segment/tst2015'\n    ]\n    text_file_list = [\n        'En-Zh/train.en-zh', 'En-Zh/tst2014.en-zh', 'En-Zh/tst2015.en-zh'\n    ]\n    data_split_list = ['train', 'dev', 'test']\n    data_process(args.src_dir, args.tgt_dir, wav_dir_list, text_file_list,\n                 data_split_list)\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/test.sh",
    "content": "#! /usr/bin/env bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nfor type in fullsentence; do\n    echo \"decoding ${type}\"\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st1/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# -lt 3 ] && [ $# -gt 4 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\nckpt_path=$3\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0 ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--checkpoint_path \"${ckpt_path}\" \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--checkpoint_path \"${ckpt_path}\" \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/ted_en_zh/st1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PWD}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2_st\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n\n# Kaldi\nexport KALDI_ROOT=${MAIN_ROOT}/tools/kaldi\n[ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh\nexport PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH\n[ ! -f $KALDI_ROOT/tools/config/common_path.sh ] && echo >&2 \"The standard file $KALDI_ROOT/tools/config/common_path.sh is not present, can not using Kaldi!\"\n[ -f $KALDI_ROOT/tools/config/common_path.sh ] && . $KALDI_ROOT/tools/config/common_path.sh"
  },
  {
    "path": "examples/ted_en_zh/st1/run.sh",
    "content": "#!/bin/bash\nset -e\n. ./path.sh || exit 1;\n. ./cmd.sh || exit 1;\n\ngpus=0,1,2,3\nstage=1\nstop_stage=4\nconf_path=conf/transformer_mtl_noam.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\nckpt_path= # paddle.98 # (finetune from FAT-ST pretrained model)\navg_num=5\ndata_path=./TED_EnZh # path to unzipped data\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh --data_dir ${data_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    if [ -n \"${ckpt_path}\" ]; then\n        echo \"Finetune from Pretrained Model\" ${ckpt_path}\n        ./local/download_pretrain.sh || exit -1\n    fi\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} \"${ckpt_path}\" ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n"
  },
  {
    "path": "examples/tess/README.md",
    "content": "# 背景\n\nTESS音频情绪分类任务。\n从而校验和测试 paddle.audio 的feature, backend等相关模块。\n\n本实验采用了PaddleSpeech提供了PANNs的CNN14的预训练模型进行finetune：\n- CNN14: 该模型主要包含12个卷积层和2个全连接层，模型参数的数量为 79.6M，embbedding维度是 2048。\n\n`PANNs`([PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition](https://arxiv.org/pdf/1912.10211.pdf))是基于Audioset数据集训练的声音分类/识别的模型。经过预训练后，模型可以用于提取音频的embbedding。本示例将使用`PANNs`的预训练模型Finetune完成声音分类的任务。\n\n## 数据集\n\n[TESS: Toronto emotional speech set](https://tspace.library.utoronto.ca/handle/1807/24487) 是一个包含有 200 个目标词的时长为 2 ~ 3 秒的音频,七种情绪的数据集。由两个女演员录制(24岁和64岁),其中情绪分别是愤怒,恶心,害怕,高兴,惊喜,伤心,平淡。\n\n## 模型指标\n\n根据 `TESS` 提供的fold信息，对数据集进行 5-fold 的 fine-tune 训练和评估，dev准确率如下：\n\n|Model|feat_type|Acc| note |\n|--|--|--| -- |\n|CNN14| mfcc | 0.9929 |3 epoch |\n|CNN14| logmelspectrogram | 0.9983 | 3 epoch |\n|CNN14| spectrogram| 0.95 | 11 epoch |\n|CNN14| melspectrogram| 0.9375 | 17 epoch |\n\n### 模型训练\n\n启动训练:\n```shell\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 1 conf/panns_mfcc.yaml\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 1 conf/panns_logmelspectrogram.yaml\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 1 conf/panns_melspectrogram.yaml\n$ CUDA_VISIBLE_DEVICES=0 ./run.sh 1 conf/panns_spectrogram.yaml\n```\n"
  },
  {
    "path": "examples/tess/cls0/conf/panns_logmelspectrogram.yaml",
    "content": "data:\n  dataset: 'paddle.audio.datasets:TESS'\n  num_classes: 7\n  train:\n    mode: 'train'\n    split: 1\n    feat_type: 'logmelspectrogram'\n  dev:\n    mode: 'dev'\n    split: 1\n    feat_type: 'logmelspectrogram'\n\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n\nfeature:\n  n_fft: 1024\n  hop_length: 320\n  window: 'hann'\n  win_length: 1024\n  f_min: 50.0\n  f_max: 14000.0\n  n_mels: 64\n\ntraining:\n  epochs: 5\n  learning_rate: 0.0005\n  num_workers: 2\n  batch_size: 128\n  checkpoint_dir: './checkpoint_logmelspectrogram'\n  save_freq: 1\n  log_freq: 1\n"
  },
  {
    "path": "examples/tess/cls0/conf/panns_melspectrogram.yaml",
    "content": "data:\n  dataset: 'paddle.audio.datasets:TESS'\n  num_classes: 7\n  train:\n    mode: 'train'\n    split: 1\n    feat_type: 'melspectrogram'\n  dev:\n    mode: 'dev'\n    split: 1\n    feat_type: 'melspectrogram'\n\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n\nfeature:\n  n_fft: 1024\n  hop_length: 320\n  window: 'hann'\n  win_length: 1024\n  f_min: 50.0\n  f_max: 14000.0\n  n_mels: 64\n\ntraining:\n  epochs: 10\n  learning_rate: 0.0005\n  num_workers: 2\n  batch_size: 128\n  checkpoint_dir: './checkpoint_melspectrogram'\n  save_freq: 1\n  log_freq: 1\n"
  },
  {
    "path": "examples/tess/cls0/conf/panns_mfcc.yaml",
    "content": "data:\n  dataset: 'paddle.audio.datasets:TESS'\n  num_classes: 7\n  train:\n    mode: 'train'\n    split: 1\n    feat_type: 'mfcc'\n  dev:\n    mode: 'dev'\n    split: 1\n    feat_type: 'mfcc'\n\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n\nfeature:\n  n_fft: 1024\n  hop_length: 320\n  window: 'hann'\n  win_length: 1024\n  f_min: 50.0\n  f_max: 14000.0\n  n_mfcc: 64\n  n_mels: 64\n\ntraining:\n  epochs: 5\n  learning_rate: 0.0005\n  num_workers: 2\n  batch_size: 128\n  checkpoint_dir: './checkpoint_mfcc'\n  save_freq: 1\n  log_freq: 1\n"
  },
  {
    "path": "examples/tess/cls0/conf/panns_spectrogram.yaml",
    "content": "data:\n  dataset: 'paddle.audio.datasets:TESS'\n  num_classes: 7\n  train:\n    mode: 'train'\n    split: 1\n    feat_type: 'spectrogram'\n  dev:\n    mode: 'dev'\n    split: 1\n    feat_type: 'spectrogram'\n\nmodel:\n  backbone: 'paddlespeech.cls.models:cnn14'\n\nfeature:\n  n_fft: 126\n  hop_length: 320\n  window: 'hann'\n\ntraining:\n  epochs: 10\n  learning_rate: 0.0005\n  num_workers: 2\n  batch_size: 128\n  checkpoint_dir: './checkpoint_spectrogram'\n  save_freq: 1\n  log_freq: 1\n"
  },
  {
    "path": "examples/tess/cls0/local/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport paddle\nimport yaml\n\nfrom paddlespeech.audio.utils import logger\nfrom paddlespeech.audio.utils.time import Timer\nfrom paddlespeech.cls.models import SoundClassifier\nfrom paddlespeech.utils.dynamic_import import dynamic_import\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument(\"--cfg_path\", type=str, required=True)\nargs = parser.parse_args()\n# yapf: enable\n\n\ndef _collate_features(batch):\n    # (feat, label)\n    # (( n_mels, length), label)\n    feats = []\n    labels = []\n    lengths = []\n    for sample in batch:\n        feats.append(paddle.transpose(sample[0], perm=[1, 0]))\n        lengths.append(sample[0].shape[1])\n        labels.append(sample[1])\n\n    max_length = max(lengths)\n    for i in range(len(feats)):\n        feats[i] = paddle.nn.functional.pad(\n            feats[i], [0, max_length - feats[i].shape[0], 0, 0],\n            data_format='NLC')\n\n    return paddle.stack(feats), paddle.to_tensor(labels), paddle.to_tensor(\n        lengths)\n\n\nif __name__ == \"__main__\":\n    nranks = paddle.distributed.get_world_size()\n    if paddle.distributed.get_world_size() > 1:\n        paddle.distributed.init_parallel_env()\n    local_rank = paddle.distributed.get_rank()\n\n    args.cfg_path = os.path.abspath(os.path.expanduser(args.cfg_path))\n    with open(args.cfg_path, 'r') as f:\n        config = yaml.safe_load(f)\n\n    model_conf = config['model']\n    data_conf = config['data']\n    feat_conf = config['feature']\n    feat_type = data_conf['train']['feat_type']\n    training_conf = config['training']\n\n    # Dataset\n\n    # set audio backend, make sure paddleaudio >= 1.0.2 installed.\n    paddle.audio.backends.set_backend('soundfile')\n\n    ds_class = dynamic_import(data_conf['dataset'])\n    train_ds = ds_class(**data_conf['train'], **feat_conf)\n    dev_ds = ds_class(**data_conf['dev'], **feat_conf)\n    train_sampler = paddle.io.DistributedBatchSampler(\n        train_ds,\n        batch_size=training_conf['batch_size'],\n        shuffle=True,\n        drop_last=False)\n    train_loader = paddle.io.DataLoader(\n        train_ds,\n        batch_sampler=train_sampler,\n        num_workers=training_conf['num_workers'],\n        return_list=True,\n        use_buffer_reader=True,\n        collate_fn=_collate_features)\n\n    # Model\n    backbone_class = dynamic_import(model_conf['backbone'])\n    backbone = backbone_class(pretrained=True, extract_embedding=True)\n    model = SoundClassifier(backbone, num_class=data_conf['num_classes'])\n    model = paddle.DataParallel(model)\n    optimizer = paddle.optimizer.Adam(\n        learning_rate=training_conf['learning_rate'],\n        parameters=model.parameters())\n    criterion = paddle.nn.loss.CrossEntropyLoss()\n\n    steps_per_epoch = len(train_sampler)\n    timer = Timer(steps_per_epoch * training_conf['epochs'])\n    timer.start()\n\n    for epoch in range(1, training_conf['epochs'] + 1):\n        model.train()\n\n        avg_loss = 0\n        num_corrects = 0\n        num_samples = 0\n        for batch_idx, batch in enumerate(train_loader):\n            feats, labels, length = batch  # feats-->(N, length, n_mels)\n\n            logits = model(feats)\n\n            loss = criterion(logits, labels)\n            loss.backward()\n            optimizer.step()\n            if isinstance(optimizer._learning_rate,\n                          paddle.optimizer.lr.LRScheduler):\n                optimizer._learning_rate.step()\n            optimizer.clear_grad()\n\n            # Calculate loss\n            avg_loss += float(loss)\n\n            # Calculate metrics\n            preds = paddle.argmax(logits, axis=1)\n            num_corrects += (preds == labels).numpy().sum()\n            num_samples += feats.shape[0]\n\n            timer.count()\n\n            if (batch_idx + 1\n                ) % training_conf['log_freq'] == 0 and local_rank == 0:\n                lr = optimizer.get_lr()\n                avg_loss /= training_conf['log_freq']\n                avg_acc = num_corrects / num_samples\n\n                print_msg = feat_type + ' Epoch={}/{}, Step={}/{}'.format(\n                    epoch, training_conf['epochs'], batch_idx + 1,\n                    steps_per_epoch)\n                print_msg += ' loss={:.4f}'.format(avg_loss)\n                print_msg += ' acc={:.4f}'.format(avg_acc)\n                print_msg += ' lr={:.6f} step/sec={:.2f} | ETA {}'.format(\n                    lr, timer.timing, timer.eta)\n                logger.train(print_msg)\n\n                avg_loss = 0\n                num_corrects = 0\n                num_samples = 0\n\n        if epoch % training_conf[\n                'save_freq'] == 0 and batch_idx + 1 == steps_per_epoch and local_rank == 0:\n            dev_sampler = paddle.io.BatchSampler(\n                dev_ds,\n                batch_size=training_conf['batch_size'],\n                shuffle=False,\n                drop_last=False)\n            dev_loader = paddle.io.DataLoader(\n                dev_ds,\n                batch_sampler=dev_sampler,\n                num_workers=training_conf['num_workers'],\n                return_list=True,\n                use_buffer_reader=True,\n                collate_fn=_collate_features)\n\n            model.eval()\n            num_corrects = 0\n            num_samples = 0\n            with logger.processing('Evaluation on validation dataset'):\n                for batch_idx, batch in enumerate(dev_loader):\n                    feats, labels, length = batch\n                    logits = model(feats)\n\n                    preds = paddle.argmax(logits, axis=1)\n                    num_corrects += (preds == labels).numpy().sum()\n                    num_samples += feats.shape[0]\n\n            print_msg = '[Evaluation result] ' + str(feat_type)\n            print_msg += ' dev_acc={:.4f}'.format(num_corrects / num_samples)\n\n            logger.eval(print_msg)\n\n            # Save model\n            save_dir = os.path.join(training_conf['checkpoint_dir'],\n                                    'epoch_{}'.format(epoch))\n            logger.info('Saving model checkpoint to {}'.format(save_dir))\n            paddle.save(model.state_dict(),\n                        os.path.join(save_dir, 'model.pdparams'))\n            paddle.save(optimizer.state_dict(),\n                        os.path.join(save_dir, 'model.pdopt'))\n"
  },
  {
    "path": "examples/tess/cls0/local/train.sh",
    "content": "#!/bin/bash\n\nngpu=$1\ncfg_path=$2\n\nif [ ${ngpu} -gt 0 ]; then\n    python3 -m paddle.distributed.launch --gpus $CUDA_VISIBLE_DEVICES local/train.py \\\n    --cfg_path ${cfg_path}\nelse\n    python3 local/train.py \\\n    --cfg_path ${cfg_path}\nfi\n"
  },
  {
    "path": "examples/tess/cls0/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=panns\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/cls/exps/${MODEL}"
  },
  {
    "path": "examples/tess/cls0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\n\nstage=$1\nstop_stage=100\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    cfg_path=$2\n    ./local/train.sh ${ngpu} ${cfg_path} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    cfg_path=$2\n    ./local/infer.sh ${cfg_path} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    ckpt=$2\n    output_dir=$3\n    ./local/export.sh ${ckpt} ${output_dir} || exit -1\n    exit 0\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    infer_device=$2\n    graph_dir=$3\n    audio_file=$4\n    ./local/static_model_infer.sh ${infer_device} ${graph_dir} ${audio_file} || exit -1\n    exit 0\nfi\n"
  },
  {
    "path": "examples/thchs30/README.md",
    "content": "# thchs30\n\n* align0 - mfa alignment\n"
  },
  {
    "path": "examples/thchs30/align0/README.md",
    "content": "# THCHS-30 数据集强制对齐实验\n-----\n本实验对 THCHS-30 中文数据集用 [Montreal-Forced-Aligner](https://montreal-forced-aligner.readthedocs.io/en/latest/index.html) 进行强制对齐。\nTHCHS-30 的文本标注数据分为：\n 1. 汉字级别（word），该数据集用空格对词进行了划分，我们在使用时按照将不同字之间按空格划分\n 2. 音节级别（syllable），即汉语中的一个拼音\n 3. 音素级别（phone），一个拼音有多个音素组成，汉语的声母韵母可以理解为音素，不同的数据集有各自的音素标准，THCHS-30 数据集与标贝 BZNSYP 数据集的音素标准略有不同\n\n 数据 A11_0 文本示例如下：\n```\n绿 是 阳春 烟 景 大块 文章 的 底色 四月 的 林 峦 更是 绿 得 鲜活 秀媚 诗意 盎然↩\nlv4 shi4 yang2 chun1 yan1 jing3 da4 kuai4 wen2 zhang1 de5 di3 se4 si4 yue4 de5 lin2 luan2 geng4 shi4 lv4 de5 xian1 huo2 xiu4 mei4 shi1 yi4 ang4 ran2↩\nl v4 sh ix4 ii iang2 ch un1 ii ian1 j ing3 d a4 k uai4 uu un2 zh ang1 d e5 d i3 s e4 s iy4 vv ve4 d e5 l in2 l uan2 g eng4 sh ix4 l v4 d e5 x ian1 h uo2 x iu4 m ei4 sh ix1 ii i4 aa ang4 r an2\n```\n## 开始实验\n---\n在本项目的 根目录/tools 执行\n```\nmake\n```\n下载 MFA 的可执行包（也会同时下载本项目所需的其他工具）\n执行如下命令：\n```\ncd a0\n./run.sh\n```\n应用程序会自动下载 THCHS-30数据集，处理成 MFA 所需的文件格式并开始训练，您可以修改 `run.sh` 中的参数 `LEXICON_NAME` 来决定您需要强制对齐的级别（word、syllable 和 phone）\n## MFA 所使用的字典\n---\nMFA 字典的格式请参考: [MFA 官方文档](https://montreal-forced-aligner.readthedocs.io/en/latest/)\nphone.lexicon 直接使用的是 `THCHS-30/data_thchs30/lm_phone/lexicon.txt`\nword.lexicon 考虑到了中文的多音字，使用**带概率的字典**, 生成规则请参考 `local/gen_word2phone.py`\n`syllable.lexicon` 获取自 [DNSun/thchs30-pinyin2tone](https://github.com/DNSun/thchs30-pinyin2tone)\n## 对齐结果\n---\n我们提供了三种级别 MFA \b训练好的对齐结果、模型和字典（`syllable.lexicon`  在 `data/dict` 中，`phone.lexicon` 和` word.lexicon` 运行数据预处理代码后会自动从原始数据集复制或生成）\n\n**phone 级别：** [phone.lexicon](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/phone/phone.lexicon)、 [对齐结果](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/phone/thchs30_alignment.tar.gz)、[模型](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/phone/thchs30_model.zip)\n**syllabel 级别：** [syllable.lexicon](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/syllable/syllable.lexicon)、[对齐结果](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/syllable/thchs30_alignment.tar.gz)、[模型](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/syllable/thchs30_model.zip)\n**word 级别：** [word.lexicon](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/word/word.lexicon)、[对齐结果](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/word/thchs30_alignment.tar.gz)、[模型](https://paddlespeech.cdn.bcebos.com/MFA/THCHS30/word/thchs30_model.zip)\n\n随后，您可以参考 [MFA 官方文档](https://montreal-forced-aligner.readthedocs.io/en/latest/) 使用我们给您提供好的模型直接对自己的数据集进行强制对齐，注意，您需要使用和模型对应的 lexicon 文件，当文本是汉字时，您需要用空格把不同的**汉字**（而不是词语）分开\n"
  },
  {
    "path": "examples/thchs30/align0/data/dict/syllable.lexicon",
    "content": "A0 aa a0\nA1 aa a1\nA2 aa a2\nA3 aa a3\nA4 aa a4\nAI0 aa ai0\nAI1 aa ai1\nAI2 aa ai2\nAI3 aa ai3\nAI4 aa ai4\nAN0 aa an0\nAN1 aa an1\nAN2 aa an2\nAN3 aa an3\nAN4 aa an4\nANG0 aa ang0\nANG1 aa ang1\nANG2 aa ang2\nANG3 aa ang3\nANG4 aa ang4\nAO0 aa ao0\nAO1 aa ao1\nAO2 aa ao2\nAO3 aa ao3\nAO4 aa ao4\nBA0 b a0\nBA1 b a1\nBA2 b a2\nBA3 b a3\nBA4 b a4\nBAI0 b ai0\nBAI1 b ai1\nBAI2 b ai2\nBAI3 b ai3\nBAI4 b ai4\nBAN0 b an0\nBAN1 b an1\nBAN2 b an2\nBAN3 b an3\nBAN4 b an4\nBANG0 b ang0\nBANG1 b ang1\nBANG2 b ang2\nBANG3 b ang3\nBANG4 b ang4\nBAO0 b ao0\nBAO1 b ao1\nBAO2 b ao2\nBAO3 b ao3\nBAO4 b ao4\nBEI0 b ei0\nBEI1 b ei1\nBEI2 b ei2\nBEI3 b ei3\nBEI4 b ei4\nBEN0 b en0\nBEN1 b en1\nBEN2 b en2\nBEN3 b en3\nBEN4 b en4\nBENG0 b eng0\nBENG1 b eng1\nBENG2 b eng2\nBENG3 b eng3\nBENG4 b eng4\nBI0 b i0\nBI1 b i1\nBI2 b i2\nBI3 b i3\nBI4 b i4\nBIAN0 b ian0\nBIAN1 b ian1\nBIAN2 b ian2\nBIAN3 b ian3\nBIAN4 b ian4\nBIAO0 b iao0\nBIAO1 b iao1\nBIAO2 b iao2\nBIAO3 b iao3\nBIAO4 b iao4\nBIE0 b ie0\nBIE1 b ie1\nBIE2 b ie2\nBIE3 b ie3\nBIE4 b ie4\nBIN0 b in0\nBIN1 b in1\nBIN2 b in2\nBIN3 b in3\nBIN4 b in4\nBING0 b ing0\nBING1 b ing1\nBING2 b ing2\nBING3 b ing3\nBING4 b ing4\nBO0 b o0\nBO1 b o1\nBO2 b o2\nBO3 b o3\nBO4 b o4\nBU0 b u0\nBU1 b u1\nBU2 b u2\nBU3 b u3\nBU4 b u4\nCA0 c a0\nCA1 c a1\nCA2 c a2\nCA3 c a3\nCA4 c a4\nCAI0 c ai0\nCAI1 c ai1\nCAI2 c ai2\nCAI3 c ai3\nCAI4 c ai4\nCAN0 c an0\nCAN1 c an1\nCAN2 c an2\nCAN3 c an3\nCAN4 c an4\nCANG0 c ang0\nCANG1 c ang1\nCANG2 c ang2\nCANG3 c ang3\nCANG4 c ang4\nCAO0 c ao0\nCAO1 c ao1\nCAO2 c ao2\nCAO3 c ao3\nCAO4 c ao4\nCE0 c e0\nCE1 c e1\nCE2 c e2\nCE3 c e3\nCE4 c e4\nCEN0 c en0\nCEN1 c en1\nCEN2 c en2\nCEN3 c en3\nCEN4 c en4\nCENG0 c eng0\nCENG1 c eng1\nCENG2 c eng2\nCENG3 c eng3\nCENG4 c eng4\nCHA0 ch a0\nCHA1 ch a1\nCHA2 ch a2\nCHA3 ch a3\nCHA4 ch a4\nCHAI0 ch ai0\nCHAI1 ch ai1\nCHAI2 ch ai2\nCHAI3 ch ai3\nCHAI4 ch ai4\nCHAN0 ch an0\nCHAN1 ch an1\nCHAN2 ch an2\nCHAN3 ch an3\nCHAN4 ch an4\nCHANG0 ch ang0\nCHANG1 ch ang1\nCHANG2 ch ang2\nCHANG3 ch ang3\nCHANG4 ch ang4\nCHAO0 ch ao0\nCHAO1 ch ao1\nCHAO2 ch ao2\nCHAO3 ch ao3\nCHAO4 ch ao4\nCHE0 ch e0\nCHE1 ch e1\nCHE2 ch e2\nCHE3 ch e3\nCHE4 ch e4\nCHEN0 ch en0\nCHEN1 ch en1\nCHEN2 ch en2\nCHEN3 ch en3\nCHEN4 ch en4\nCHENG0 ch eng0\nCHENG1 ch eng1\nCHENG2 ch eng2\nCHENG3 ch eng3\nCHENG4 ch eng4\nCHI0 ch ix0\nCHI1 ch ix1\nCHI2 ch ix2\nCHI3 ch ix3\nCHI4 ch ix4\nCHONG0 ch ong0\nCHONG1 ch ong1\nCHONG2 ch ong2\nCHONG3 ch ong3\nCHONG4 ch ong4\nCHOU0 ch ou0\nCHOU1 ch ou1\nCHOU2 ch ou2\nCHOU3 ch ou3\nCHOU4 ch ou4\nCHU0 ch u0\nCHU1 ch u1\nCHU2 ch u2\nCHU3 ch u3\nCHU4 ch u4\nCHUAI0 ch uai0\nCHUAI1 ch uai1\nCHUAI2 ch uai2\nCHUAI3 ch uai3\nCHUAI4 ch uai4\nCHUAN0 ch uan0\nCHUAN1 ch uan1\nCHUAN2 ch uan2\nCHUAN3 ch uan3\nCHUAN4 ch uan4\nCHUANG0 ch uang0\nCHUANG1 ch uang1\nCHUANG2 ch uang2\nCHUANG3 ch uang3\nCHUANG4 ch uang4\nCHUI0 ch ui0\nCHUI1 ch ui1\nCHUI2 ch ui2\nCHUI3 ch ui3\nCHUI4 ch ui4\nCHUN0 ch un0\nCHUN1 ch un1\nCHUN2 ch un2\nCHUN3 ch un3\nCHUN4 ch un4\nCHUO0 ch uo0\nCHUO1 ch uo1\nCHUO2 ch uo2\nCHUO3 ch uo3\nCHUO4 ch uo4\nCI0 c iy0\nCI1 c iy1\nCI2 c iy2\nCI3 c iy3\nCI4 c iy4\nCONG0 c ong0\nCONG1 c ong1\nCONG2 c ong2\nCONG3 c ong3\nCONG4 c ong4\nCOU0 c ou0\nCOU1 c ou1\nCOU2 c ou2\nCOU3 c ou3\nCOU4 c ou4\nCU0 c u0\nCU1 c u1\nCU2 c u2\nCU3 c u3\nCU4 c u4\nCUAN0 c uan0\nCUAN1 c uan1\nCUAN2 c uan2\nCUAN3 c uan3\nCUAN4 c uan4\nCUI0 c ui0\nCUI1 c ui1\nCUI2 c ui2\nCUI3 c ui3\nCUI4 c ui4\nCUN0 c un0\nCUN1 c un1\nCUN2 c un2\nCUN3 c un3\nCUN4 c un4\nCUO0 c uo0\nCUO1 c uo1\nCUO2 c uo2\nCUO3 c uo3\nCUO4 c uo4\nDA0 d a0\nDA1 d a1\nDA2 d a2\nDA3 d a3\nDA4 d a4\nDAI0 d ai0\nDAI1 d ai1\nDAI2 d ai2\nDAI3 d ai3\nDAI4 d ai4\nDAN0 d an0\nDAN1 d an1\nDAN2 d an2\nDAN3 d an3\nDAN4 d an4\nDANG0 d ang0\nDANG1 d ang1\nDANG2 d ang2\nDANG3 d ang3\nDANG4 d ang4\nDAO0 d ao0\nDAO1 d ao1\nDAO2 d ao2\nDAO3 d ao3\nDAO4 d ao4\nDE0 d e0\nDE1 d e1\nDE2 d e2\nDE3 d e3\nDE4 d e4\nDEI0 d ei0\nDEI1 d ei1\nDEI2 d ei2\nDEI3 d ei3\nDEI4 d ei4\nDEN0 d en0\nDEN1 d en1\nDEN2 d en2\nDEN3 d en3\nDEN4 d en4\nDENG0 d eng0\nDENG1 d eng1\nDENG2 d eng2\nDENG3 d eng3\nDENG4 d eng4\nDI0 d i0\nDI1 d i1\nDI2 d i2\nDI3 d i3\nDI4 d i4\nDIA0 d ia0\nDIA1 d ia1\nDIA2 d ia2\nDIA3 d ia3\nDIA4 d ia4\nDIAN0 d ian0\nDIAN1 d ian1\nDIAN2 d ian2\nDIAN3 d ian3\nDIAN4 d ian4\nDIAO0 d iao0\nDIAO1 d iao1\nDIAO2 d iao2\nDIAO3 d iao3\nDIAO4 d iao4\nDIE0 d ie0\nDIE1 d ie1\nDIE2 d ie2\nDIE3 d ie3\nDIE4 d ie4\nDING0 d ing0\nDING1 d ing1\nDING2 d ing2\nDING3 d ing3\nDING4 d ing4\nDIU0 d iu0\nDIU1 d iu1\nDIU2 d iu2\nDIU3 d iu3\nDIU4 d iu4\nDONG0 d ong0\nDONG1 d ong1\nDONG2 d ong2\nDONG3 d ong3\nDONG4 d ong4\nDOU0 d ou0\nDOU1 d ou1\nDOU2 d ou2\nDOU3 d ou3\nDOU4 d ou4\nDU0 d u0\nDU1 d u1\nDU2 d u2\nDU3 d u3\nDU4 d u4\nDUAN0 d uan0\nDUAN1 d uan1\nDUAN2 d uan2\nDUAN3 d uan3\nDUAN4 d uan4\nDUI0 d ui0\nDUI1 d ui1\nDUI2 d ui2\nDUI3 d ui3\nDUI4 d ui4\nDUN0 d un0\nDUN1 d un1\nDUN2 d un2\nDUN3 d un3\nDUN4 d un4\nDUO0 d uo0\nDUO1 d uo1\nDUO2 d uo2\nDUO3 d uo3\nDUO4 d uo4\nE0 ee e0\nE1 ee e1\nE2 ee e2\nE3 ee e3\nE4 ee e4\nEN0 ee en0\nEN1 ee en1\nEN2 ee en2\nEN3 ee en3\nEN4 ee en4\nER0 ee er0\nER1 ee er1\nER2 ee er2\nER3 ee er3\nER4 ee er4\nFA0 f a0\nFA1 f a1\nFA2 f a2\nFA3 f a3\nFA4 f a4\nFAN0 f an0\nFAN1 f an1\nFAN2 f an2\nFAN3 f an3\nFAN4 f an4\nFANG0 f ang0\nFANG1 f ang1\nFANG2 f ang2\nFANG3 f ang3\nFANG4 f ang4\nFEI0 f ei0\nFEI1 f ei1\nFEI2 f ei2\nFEI3 f ei3\nFEI4 f ei4\nFEN0 f en0\nFEN1 f en1\nFEN2 f en2\nFEN3 f en3\nFEN4 f en4\nFENG0 f eng0\nFENG1 f eng1\nFENG2 f eng2\nFENG3 f eng3\nFENG4 f eng4\nFO0 f o0\nFO1 f o1\nFO2 f o2\nFO3 f o3\nFO4 f o4\nFOU0 f ou0\nFOU1 f ou1\nFOU2 f ou2\nFOU3 f ou3\nFOU4 f ou4\nFU0 f u0\nFU1 f u1\nFU2 f u2\nFU3 f u3\nFU4 f u4\nGA0 g a0\nGA1 g a1\nGA2 g a2\nGA3 g a3\nGA4 g a4\nGAI0 g ai0\nGAI1 g ai1\nGAI2 g ai2\nGAI3 g ai3\nGAI4 g ai4\nGAN0 g an0\nGAN1 g an1\nGAN2 g an2\nGAN3 g an3\nGAN4 g an4\nGANG0 g ang0\nGANG1 g ang1\nGANG2 g ang2\nGANG3 g ang3\nGANG4 g ang4\nGAO0 g ao0\nGAO1 g ao1\nGAO2 g ao2\nGAO3 g ao3\nGAO4 g ao4\nGE0 g e0\nGE1 g e1\nGE2 g e2\nGE3 g e3\nGE4 g e4\nGEI0 g ei0\nGEI1 g ei1\nGEI2 g ei2\nGEI3 g ei3\nGEI4 g ei4\nGEN0 g en0\nGEN1 g en1\nGEN2 g en2\nGEN3 g en3\nGEN4 g en4\nGENG0 g eng0\nGENG1 g eng1\nGENG2 g eng2\nGENG3 g eng3\nGENG4 g eng4\nGONG0 g ong0\nGONG1 g ong1\nGONG2 g ong2\nGONG3 g ong3\nGONG4 g ong4\nGOU0 g ou0\nGOU1 g ou1\nGOU2 g ou2\nGOU3 g ou3\nGOU4 g ou4\nGU0 g u0\nGU1 g u1\nGU2 g u2\nGU3 g u3\nGU4 g u4\nGUA0 g ua0\nGUA1 g ua1\nGUA2 g ua2\nGUA3 g ua3\nGUA4 g ua4\nGUAI0 g uai0\nGUAI1 g uai1\nGUAI2 g uai2\nGUAI3 g uai3\nGUAI4 g uai4\nGUAN0 g uan0\nGUAN1 g uan1\nGUAN2 g uan2\nGUAN3 g uan3\nGUAN4 g uan4\nGUANG0 g uang0\nGUANG1 g uang1\nGUANG2 g uang2\nGUANG3 g uang3\nGUANG4 g uang4\nGUI0 g ui0\nGUI1 g ui1\nGUI2 g ui2\nGUI3 g ui3\nGUI4 g ui4\nGUN0 g un0\nGUN1 g un1\nGUN2 g un2\nGUN3 g un3\nGUN4 g un4\nGUO0 g uo0\nGUO1 g uo1\nGUO2 g uo2\nGUO3 g uo3\nGUO4 g uo4\nHA0 h a0\nHA1 h a1\nHA2 h a2\nHA3 h a3\nHA4 h a4\nHAI0 h ai0\nHAI1 h ai1\nHAI2 h ai2\nHAI3 h ai3\nHAI4 h ai4\nHAN0 h an0\nHAN1 h an1\nHAN2 h an2\nHAN3 h an3\nHAN4 h an4\nHANG0 h ang0\nHANG1 h ang1\nHANG2 h ang2\nHANG3 h ang3\nHANG4 h ang4\nHAO0 h ao0\nHAO1 h ao1\nHAO2 h ao2\nHAO3 h ao3\nHAO4 h ao4\nHE0 h e0\nHE1 h e1\nHE2 h e2\nHE3 h e3\nHE4 h e4\nHEI0 h ei0\nHEI1 h ei1\nHEI2 h ei2\nHEI3 h ei3\nHEI4 h ei4\nHEN0 h en0\nHEN1 h en1\nHEN2 h en2\nHEN3 h en3\nHEN4 h en4\nHENG0 h eng0\nHENG1 h eng1\nHENG2 h eng2\nHENG3 h eng3\nHENG4 h eng4\nHONG0 h ong0\nHONG1 h ong1\nHONG2 h ong2\nHONG3 h ong3\nHONG4 h ong4\nHOU0 h ou0\nHOU1 h ou1\nHOU2 h ou2\nHOU3 h ou3\nHOU4 h ou4\nHU0 h u0\nHU1 h u1\nHU2 h u2\nHU3 h u3\nHU4 h u4\nHUA0 h ua0\nHUA1 h ua1\nHUA2 h ua2\nHUA3 h ua3\nHUA4 h ua4\nHUAI0 h uai0\nHUAI1 h uai1\nHUAI2 h uai2\nHUAI3 h uai3\nHUAI4 h uai4\nHUAN0 h uan0\nHUAN1 h uan1\nHUAN2 h uan2\nHUAN3 h uan3\nHUAN4 h uan4\nHUANG0 h uang0\nHUANG1 h uang1\nHUANG2 h uang2\nHUANG3 h uang3\nHUANG4 h uang4\nHUI0 h ui0\nHUI1 h ui1\nHUI2 h ui2\nHUI3 h ui3\nHUI4 h ui4\nHUN0 h un0\nHUN1 h un1\nHUN2 h un2\nHUN3 h un3\nHUN4 h un4\nHUO0 h uo0\nHUO1 h uo1\nHUO2 h uo2\nHUO3 h uo3\nHUO4 h uo4\nJI0 j i0\nJI1 j i1\nJI2 j i2\nJI3 j i3\nJI4 j i4\nJIA0 j ia0\nJIA1 j ia1\nJIA2 j ia2\nJIA3 j ia3\nJIA4 j ia4\nJIAN0 j ian0\nJIAN1 j ian1\nJIAN2 j ian2\nJIAN3 j ian3\nJIAN4 j ian4\nJIANG0 j iang0\nJIANG1 j iang1\nJIANG2 j iang2\nJIANG3 j iang3\nJIANG4 j iang4\nJIAO0 j iao0\nJIAO1 j iao1\nJIAO2 j iao2\nJIAO3 j iao3\nJIAO4 j iao4\nJIE0 j ie0\nJIE1 j ie1\nJIE2 j ie2\nJIE3 j ie3\nJIE4 j ie4\nJIN0 j in0\nJIN1 j in1\nJIN2 j in2\nJIN3 j in3\nJIN4 j in4\nJING0 j ing0\nJING1 j ing1\nJING2 j ing2\nJING3 j ing3\nJING4 j ing4\nJIONG0 j iong0\nJIONG1 j iong1\nJIONG2 j iong2\nJIONG3 j iong3\nJIONG4 j iong4\nJIU0 j iu0\nJIU1 j iu1\nJIU2 j iu2\nJIU3 j iu3\nJIU4 j iu4\nJU0 j v0\nJU1 j v1\nJU2 j v2\nJU3 j v3\nJU4 j v4\nJUAN0 j van0\nJUAN1 j van1\nJUAN2 j van2\nJUAN3 j van3\nJUAN4 j van4\nJUE0 j ve0\nJUE1 j ve1\nJUE2 j ve2\nJUE3 j ve3\nJUE4 j ve4\nJUN0 j vn0\nJUN1 j vn1\nJUN2 j vn2\nJUN3 j vn3\nJUN4 j vn4\nKA0 k a0\nKA1 k a1\nKA2 k a2\nKA3 k a3\nKA4 k a4\nKAI0 k ai0\nKAI1 k ai1\nKAI2 k ai2\nKAI3 k ai3\nKAI4 k ai4\nKAN0 k an0\nKAN1 k an1\nKAN2 k an2\nKAN3 k an3\nKAN4 k an4\nKANG0 k ang0\nKANG1 k ang1\nKANG2 k ang2\nKANG3 k ang3\nKANG4 k ang4\nKAO0 k ao0\nKAO1 k ao1\nKAO2 k ao2\nKAO3 k ao3\nKAO4 k ao4\nKE0 k e0\nKE1 k e1\nKE2 k e2\nKE3 k e3\nKE4 k e4\nKEI0 k ei0\nKEI1 k ei1\nKEI2 k ei2\nKEI3 k ei3\nKEI4 k ei4\nKEN0 k en0\nKEN1 k en1\nKEN2 k en2\nKEN3 k en3\nKEN4 k en4\nKENG0 k eng0\nKENG1 k eng1\nKENG2 k eng2\nKENG3 k eng3\nKENG4 k eng4\nKONG0 k ong0\nKONG1 k ong1\nKONG2 k ong2\nKONG3 k ong3\nKONG4 k ong4\nKOU0 k ou0\nKOU1 k ou1\nKOU2 k ou2\nKOU3 k ou3\nKOU4 k ou4\nKU0 k u0\nKU1 k u1\nKU2 k u2\nKU3 k u3\nKU4 k u4\nKUA0 k ua0\nKUA1 k ua1\nKUA2 k ua2\nKUA3 k ua3\nKUA4 k ua4\nKUAI0 k uai0\nKUAI1 k uai1\nKUAI2 k uai2\nKUAI3 k uai3\nKUAI4 k uai4\nKUAN0 k uan0\nKUAN1 k uan1\nKUAN2 k uan2\nKUAN3 k uan3\nKUAN4 k uan4\nKUANG0 k uang0\nKUANG1 k uang1\nKUANG2 k uang2\nKUANG3 k uang3\nKUANG4 k uang4\nKUI0 k ui0\nKUI1 k ui1\nKUI2 k ui2\nKUI3 k ui3\nKUI4 k ui4\nKUN0 k un0\nKUN1 k un1\nKUN2 k un2\nKUN3 k un3\nKUN4 k un4\nKUO0 k uo0\nKUO1 k uo1\nKUO2 k uo2\nKUO3 k uo3\nKUO4 k uo4\nLA0 l a0\nLA1 l a1\nLA2 l a2\nLA3 l a3\nLA4 l a4\nLAI0 l ai0\nLAI1 l ai1\nLAI2 l ai2\nLAI3 l ai3\nLAI4 l ai4\nLAN0 l an0\nLAN1 l an1\nLAN2 l an2\nLAN3 l an3\nLAN4 l an4\nLANG0 l ang0\nLANG1 l ang1\nLANG2 l ang2\nLANG3 l ang3\nLANG4 l ang4\nLAO0 l ao0\nLAO1 l ao1\nLAO2 l ao2\nLAO3 l ao3\nLAO4 l ao4\nLE0 l e0\nLE1 l e1\nLE2 l e2\nLE3 l e3\nLE4 l e4\nLEI0 l ei0\nLEI1 l ei1\nLEI2 l ei2\nLEI3 l ei3\nLEI4 l ei4\nLENG0 l eng0\nLENG1 l eng1\nLENG2 l eng2\nLENG3 l eng3\nLENG4 l eng4\nLI0 l i0\nLI1 l i1\nLI2 l i2\nLI3 l i3\nLI4 l i4\nLIA0 l ia0\nLIA1 l ia1\nLIA2 l ia2\nLIA3 l ia3\nLIA4 l ia4\nLIAN0 l ian0\nLIAN1 l ian1\nLIAN2 l ian2\nLIAN3 l ian3\nLIAN4 l ian4\nLIANG0 l iang0\nLIANG1 l iang1\nLIANG2 l iang2\nLIANG3 l iang3\nLIANG4 l iang4\nLIAO0 l iao0\nLIAO1 l iao1\nLIAO2 l iao2\nLIAO3 l iao3\nLIAO4 l iao4\nLIE0 l ie0\nLIE1 l ie1\nLIE2 l ie2\nLIE3 l ie3\nLIE4 l ie4\nLIN0 l in0\nLIN1 l in1\nLIN2 l in2\nLIN3 l in3\nLIN4 l in4\nLING0 l ing0\nLING1 l ing1\nLING2 l ing2\nLING3 l ing3\nLING4 l ing4\nLIU0 l iu0\nLIU1 l iu1\nLIU2 l iu2\nLIU3 l iu3\nLIU4 l iu4\nLONG0 l ong0\nLONG1 l ong1\nLONG2 l ong2\nLONG3 l ong3\nLONG4 l ong4\nLOU0 l ou0\nLOU1 l ou1\nLOU2 l ou2\nLOU3 l ou3\nLOU4 l ou4\nLU0 l u0\nLU1 l u1\nLU2 l u2\nLU3 l u3\nLU4 l u4\nLUAN0 l uan0\nLUAN1 l uan1\nLUAN2 l uan2\nLUAN3 l uan3\nLUAN4 l uan4\nLUE0 l ve0\nLUE1 l ve1\nLUE2 l ve2\nLUE3 l ve3\nLUE4 l ve4\nLVE0 l ve0\nLVE1 l ve1\nLVE2 l ve2\nLVE3 l ve3\nLVE4 l ve4\nLUN0 l un0\nLUN1 l un1\nLUN2 l un2\nLUN3 l un3\nLUN4 l un4\nLUO0 l uo0\nLUO1 l uo1\nLUO2 l uo2\nLUO3 l uo3\nLUO4 l uo4\nLV0 l v0\nLV1 l v1\nLV2 l v2\nLV3 l v3\nLV4 l v4\nMA0 m a0\nMA1 m a1\nMA2 m a2\nMA3 m a3\nMA4 m a4\nMAI0 m ai0\nMAI1 m ai1\nMAI2 m ai2\nMAI3 m ai3\nMAI4 m ai4\nMAN0 m an0\nMAN1 m an1\nMAN2 m an2\nMAN3 m an3\nMAN4 m an4\nMANG0 m ang0\nMANG1 m ang1\nMANG2 m ang2\nMANG3 m ang3\nMANG4 m ang4\nMAO0 m ao0\nMAO1 m ao1\nMAO2 m ao2\nMAO3 m ao3\nMAO4 m ao4\nME0 m e0\nME1 m e1\nME2 m e2\nME3 m e3\nME4 m e4\nMEI0 m ei0\nMEI1 m ei1\nMEI2 m ei2\nMEI3 m ei3\nMEI4 m ei4\nMEN0 m en0\nMEN1 m en1\nMEN2 m en2\nMEN3 m en3\nMEN4 m en4\nMENG0 m eng0\nMENG1 m eng1\nMENG2 m eng2\nMENG3 m eng3\nMENG4 m eng4\nMI0 m i0\nMI1 m i1\nMI2 m i2\nMI3 m i3\nMI4 m i4\nMIAN0 m ian0\nMIAN1 m ian1\nMIAN2 m ian2\nMIAN3 m ian3\nMIAN4 m ian4\nMIAO0 m iao0\nMIAO1 m iao1\nMIAO2 m iao2\nMIAO3 m iao3\nMIAO4 m iao4\nMIE0 m ie0\nMIE1 m ie1\nMIE2 m ie2\nMIE3 m ie3\nMIE4 m ie4\nMIN0 m in0\nMIN1 m in1\nMIN2 m in2\nMIN3 m in3\nMIN4 m in4\nMING0 m ing0\nMING1 m ing1\nMING2 m ing2\nMING3 m ing3\nMING4 m ing4\nMIU0 m iu0\nMIU1 m iu1\nMIU2 m iu2\nMIU3 m iu3\nMIU4 m iu4\nMO0 m o0\nMO1 m o1\nMO2 m o2\nMO3 m o3\nMO4 m o4\nMOU0 m ou0\nMOU1 m ou1\nMOU2 m ou2\nMOU3 m ou3\nMOU4 m ou4\nMU0 m u0\nMU1 m u1\nMU2 m u2\nMU3 m u3\nMU4 m u4\nNA0 n a0\nNA1 n a1\nNA2 n a2\nNA3 n a3\nNA4 n a4\nNAI0 n ai0\nNAI1 n ai1\nNAI2 n ai2\nNAI3 n ai3\nNAI4 n ai4\nNAN0 n an0\nNAN1 n an1\nNAN2 n an2\nNAN3 n an3\nNAN4 n an4\nNANG0 n ang0\nNANG1 n ang1\nNANG2 n ang2\nNANG3 n ang3\nNANG4 n ang4\nNAO0 n ao0\nNAO1 n ao1\nNAO2 n ao2\nNAO3 n ao3\nNAO4 n ao4\nNE0 n e0\nNE1 n e1\nNE2 n e2\nNE3 n e3\nNE4 n e4\nNEI0 n ei0\nNEI1 n ei1\nNEI2 n ei2\nNEI3 n ei3\nNEI4 n ei4\nNEN0 n en0\nNEN1 n en1\nNEN2 n en2\nNEN3 n en3\nNEN4 n en4\nNENG0 n eng0\nNENG1 n eng1\nNENG2 n eng2\nNENG3 n eng3\nNENG4 n eng4\nNI0 n i0\nNI1 n i1\nNI2 n i2\nNI3 n i3\nNI4 n i4\nNIAN0 n ian0\nNIAN1 n ian1\nNIAN2 n ian2\nNIAN3 n ian3\nNIAN4 n ian4\nNIANG0 n iang0\nNIANG1 n iang1\nNIANG2 n iang2\nNIANG3 n iang3\nNIANG4 n iang4\nNIAO0 n iao0\nNIAO1 n iao1\nNIAO2 n iao2\nNIAO3 n iao3\nNIAO4 n iao4\nNIE0 n ie0\nNIE1 n ie1\nNIE2 n ie2\nNIE3 n ie3\nNIE4 n ie4\nNIN0 n in0\nNIN1 n in1\nNIN2 n in2\nNIN3 n in3\nNIN4 n in4\nNING0 n ing0\nNING1 n ing1\nNING2 n ing2\nNING3 n ing3\nNING4 n ing4\nNIU0 n iu0\nNIU1 n iu1\nNIU2 n iu2\nNIU3 n iu3\nNIU4 n iu4\nNONG0 n ong0\nNONG1 n ong1\nNONG2 n ong2\nNONG3 n ong3\nNONG4 n ong4\nNU0 n u0\nNU1 n u1\nNU2 n u2\nNU3 n u3\nNU4 n u4\nNUAN0 n uan0\nNUAN1 n uan1\nNUAN2 n uan2\nNUAN3 n uan3\nNUAN4 n uan4\nNUE0 n ve0\nNUE1 n ve1\nNUE2 n ve2\nNUE3 n ve3\nNUE4 n ve4\nNVE0 n ve0\nNVE1 n ve1\nNVE2 n ve2\nNVE3 n ve3\nNVE4 n ve4\nNUO0 n uo0\nNUO1 n uo1\nNUO2 n uo2\nNUO3 n uo3\nNUO4 n uo4\nNV0 n v0\nNV1 n v1\nNV2 n v2\nNV3 n v3\nNV4 n v4\nO0 oo o0\nO1 oo o1\nO2 oo o2\nO3 oo o3\nO4 oo o4\nOU0 oo ou0\nOU1 oo ou1\nOU2 oo ou2\nOU3 oo ou3\nOU4 oo ou4\nPA0 p a0\nPA1 p a1\nPA2 p a2\nPA3 p a3\nPA4 p a4\nPAI0 p ai0\nPAI1 p ai1\nPAI2 p ai2\nPAI3 p ai3\nPAI4 p ai4\nPAN0 p an0\nPAN1 p an1\nPAN2 p an2\nPAN3 p an3\nPAN4 p an4\nPANG0 p ang0\nPANG1 p ang1\nPANG2 p ang2\nPANG3 p ang3\nPANG4 p ang4\nPAO0 p ao0\nPAO1 p ao1\nPAO2 p ao2\nPAO3 p ao3\nPAO4 p ao4\nPEI0 p ei0\nPEI1 p ei1\nPEI2 p ei2\nPEI3 p ei3\nPEI4 p ei4\nPEN0 p en0\nPEN1 p en1\nPEN2 p en2\nPEN3 p en3\nPEN4 p en4\nPENG0 p eng0\nPENG1 p eng1\nPENG2 p eng2\nPENG3 p eng3\nPENG4 p eng4\nPI0 p i0\nPI1 p i1\nPI2 p i2\nPI3 p i3\nPI4 p i4\nPIAN0 p ian0\nPIAN1 p ian1\nPIAN2 p ian2\nPIAN3 p ian3\nPIAN4 p ian4\nPIAO0 p iao0\nPIAO1 p iao1\nPIAO2 p iao2\nPIAO3 p iao3\nPIAO4 p iao4\nPIE0 p ie0\nPIE1 p ie1\nPIE2 p ie2\nPIE3 p ie3\nPIE4 p ie4\nPIN0 p in0\nPIN1 p in1\nPIN2 p in2\nPIN3 p in3\nPIN4 p in4\nPING0 p ing0\nPING1 p ing1\nPING2 p ing2\nPING3 p ing3\nPING4 p ing4\nPO0 p o0\nPO1 p o1\nPO2 p o2\nPO3 p o3\nPO4 p o4\nPOU0 p ou0\nPOU1 p ou1\nPOU2 p ou2\nPOU3 p ou3\nPOU4 p ou4\nPU0 p u0\nPU1 p u1\nPU2 p u2\nPU3 p u3\nPU4 p u4\nQI0 q i0\nQI1 q i1\nQI2 q i2\nQI3 q i3\nQI4 q i4\nQIA0 q ia0\nQIA1 q ia1\nQIA2 q ia2\nQIA3 q ia3\nQIA4 q ia4\nQIAN0 q ian0\nQIAN1 q ian1\nQIAN2 q ian2\nQIAN3 q ian3\nQIAN4 q ian4\nQIANG0 q iang0\nQIANG1 q iang1\nQIANG2 q iang2\nQIANG3 q iang3\nQIANG4 q iang4\nQIAO0 q iao0\nQIAO1 q iao1\nQIAO2 q iao2\nQIAO3 q iao3\nQIAO4 q iao4\nQIE0 q ie0\nQIE1 q ie1\nQIE2 q ie2\nQIE3 q ie3\nQIE4 q ie4\nQIN0 q in0\nQIN1 q in1\nQIN2 q in2\nQIN3 q in3\nQIN4 q in4\nQING0 q ing0\nQING1 q ing1\nQING2 q ing2\nQING3 q ing3\nQING4 q ing4\nQIONG0 q iong0\nQIONG1 q iong1\nQIONG2 q iong2\nQIONG3 q iong3\nQIONG4 q iong4\nQIU0 q iu0\nQIU1 q iu1\nQIU2 q iu2\nQIU3 q iu3\nQIU4 q iu4\nQU0 q v0\nQU1 q v1\nQU2 q v2\nQU3 q v3\nQU4 q v4\nQUAN0 q van0\nQUAN1 q van1\nQUAN2 q van2\nQUAN3 q van3\nQUAN4 q van4\nQUE0 q ve0\nQUE1 q ve1\nQUE2 q ve2\nQUE3 q ve3\nQUE4 q ve4\nQUN0 q vn0\nQUN1 q vn1\nQUN2 q vn2\nQUN3 q vn3\nQUN4 q vn4\nRAN0 r an0\nRAN1 r an1\nRAN2 r an2\nRAN3 r an3\nRAN4 r an4\nRANG0 r ang0\nRANG1 r ang1\nRANG2 r ang2\nRANG3 r ang3\nRANG4 r ang4\nRAO0 r ao0\nRAO1 r ao1\nRAO2 r ao2\nRAO3 r ao3\nRAO4 r ao4\nRE0 r e0\nRE1 r e1\nRE2 r e2\nRE3 r e3\nRE4 r e4\nREN0 r en0\nREN1 r en1\nREN2 r en2\nREN3 r en3\nREN4 r en4\nRENG0 r eng0\nRENG1 r eng1\nRENG2 r eng2\nRENG3 r eng3\nRENG4 r eng4\nRI0 r iz0\nRI1 r iz1\nRI2 r iz2\nRI3 r iz3\nRI4 r iz4\nRONG0 r ong0\nRONG1 r ong1\nRONG2 r ong2\nRONG3 r ong3\nRONG4 r ong4\nROU0 r ou0\nROU1 r ou1\nROU2 r ou2\nROU3 r ou3\nROU4 r ou4\nRU0 r u0\nRU1 r u1\nRU2 r u2\nRU3 r u3\nRU4 r u4\nRUAN0 r uan0\nRUAN1 r uan1\nRUAN2 r uan2\nRUAN3 r uan3\nRUAN4 r uan4\nRUI0 r ui0\nRUI1 r ui1\nRUI2 r ui2\nRUI3 r ui3\nRUI4 r ui4\nRUN0 r un0\nRUN1 r un1\nRUN2 r un2\nRUN3 r un3\nRUN4 r un4\nRUO0 r uo0\nRUO1 r uo1\nRUO2 r uo2\nRUO3 r uo3\nRUO4 r uo4\nSA0 s a0\nSA1 s a1\nSA2 s a2\nSA3 s a3\nSA4 s a4\nSAI0 s ai0\nSAI1 s ai1\nSAI2 s ai2\nSAI3 s ai3\nSAI4 s ai4\nSAN0 s an0\nSAN1 s an1\nSAN2 s an2\nSAN3 s an3\nSAN4 s an4\nSANG0 s ang0\nSANG1 s ang1\nSANG2 s ang2\nSANG3 s ang3\nSANG4 s ang4\nSAO0 s ao0\nSAO1 s ao1\nSAO2 s ao2\nSAO3 s ao3\nSAO4 s ao4\nSE0 s e0\nSE1 s e1\nSE2 s e2\nSE3 s e3\nSE4 s e4\nSEN0 s en0\nSEN1 s en1\nSEN2 s en2\nSEN3 s en3\nSEN4 s en4\nSENG0 s eng0\nSENG1 s eng1\nSENG2 s eng2\nSENG3 s eng3\nSENG4 s eng4\nSHA0 sh a0\nSHA1 sh a1\nSHA2 sh a2\nSHA3 sh a3\nSHA4 sh a4\nSHAI0 sh ai0\nSHAI1 sh ai1\nSHAI2 sh ai2\nSHAI3 sh ai3\nSHAI4 sh ai4\nSHAN0 sh an0\nSHAN1 sh an1\nSHAN2 sh an2\nSHAN3 sh an3\nSHAN4 sh an4\nSHANG0 sh ang0\nSHANG1 sh ang1\nSHANG2 sh ang2\nSHANG3 sh ang3\nSHANG4 sh ang4\nSHAO0 sh ao0\nSHAO1 sh ao1\nSHAO2 sh ao2\nSHAO3 sh ao3\nSHAO4 sh ao4\nSHE0 sh e0\nSHE1 sh e1\nSHE2 sh e2\nSHE3 sh e3\nSHE4 sh e4\nSHEI0 sh ei0\nSHEI1 sh ei1\nSHEI2 sh ei2\nSHEI3 sh ei3\nSHEI4 sh ei4\nSHEN0 sh en0\nSHEN1 sh en1\nSHEN2 sh en2\nSHEN3 sh en3\nSHEN4 sh en4\nSHENG0 sh eng0\nSHENG1 sh eng1\nSHENG2 sh eng2\nSHENG3 sh eng3\nSHENG4 sh eng4\nSHI0 sh ix0\nSHI1 sh ix1\nSHI2 sh ix2\nSHI3 sh ix3\nSHI4 sh ix4\nSHOU0 sh ou0\nSHOU1 sh ou1\nSHOU2 sh ou2\nSHOU3 sh ou3\nSHOU4 sh ou4\nSHU0 sh u0\nSHU1 sh u1\nSHU2 sh u2\nSHU3 sh u3\nSHU4 sh u4\nSHUA0 sh ua0\nSHUA1 sh ua1\nSHUA2 sh ua2\nSHUA3 sh ua3\nSHUA4 sh ua4\nSHUAI0 sh uai0\nSHUAI1 sh uai1\nSHUAI2 sh uai2\nSHUAI3 sh uai3\nSHUAI4 sh uai4\nSHUAN0 sh uan0\nSHUAN1 sh uan1\nSHUAN2 sh uan2\nSHUAN3 sh uan3\nSHUAN4 sh uan4\nSHUANG0 sh uang0\nSHUANG1 sh uang1\nSHUANG2 sh uang2\nSHUANG3 sh uang3\nSHUANG4 sh uang4\nSHUI0 sh ui0\nSHUI1 sh ui1\nSHUI2 sh ui2\nSHUI3 sh ui3\nSHUI4 sh ui4\nSHUN0 sh un0\nSHUN1 sh un1\nSHUN2 sh un2\nSHUN3 sh un3\nSHUN4 sh un4\nSHUO0 sh uo0\nSHUO1 sh uo1\nSHUO2 sh uo2\nSHUO3 sh uo3\nSHUO4 sh uo4\nSI0 s iy0\nSI1 s iy1\nSI2 s iy2\nSI3 s iy3\nSI4 s iy4\nSONG0 s ong0\nSONG1 s ong1\nSONG2 s ong2\nSONG3 s ong3\nSONG4 s ong4\nSOU0 s ou0\nSOU1 s ou1\nSOU2 s ou2\nSOU3 s ou3\nSOU4 s ou4\nSU0 s u0\nSU1 s u1\nSU2 s u2\nSU3 s u3\nSU4 s u4\nSUAN0 s uan0\nSUAN1 s uan1\nSUAN2 s uan2\nSUAN3 s uan3\nSUAN4 s uan4\nSUI0 s ui0\nSUI1 s ui1\nSUI2 s ui2\nSUI3 s ui3\nSUI4 s ui4\nSUN0 s un0\nSUN1 s un1\nSUN2 s un2\nSUN3 s un3\nSUN4 s un4\nSUO0 s uo0\nSUO1 s uo1\nSUO2 s uo2\nSUO3 s uo3\nSUO4 s uo4\nTA0 t a0\nTA1 t a1\nTA2 t a2\nTA3 t a3\nTA4 t a4\nTAI0 t ai0\nTAI1 t ai1\nTAI2 t ai2\nTAI3 t ai3\nTAI4 t ai4\nTAN0 t an0\nTAN1 t an1\nTAN2 t an2\nTAN3 t an3\nTAN4 t an4\nTANG0 t ang0\nTANG1 t ang1\nTANG2 t ang2\nTANG3 t ang3\nTANG4 t ang4\nTAO0 t ao0\nTAO1 t ao1\nTAO2 t ao2\nTAO3 t ao3\nTAO4 t ao4\nTE0 t e0\nTE1 t e1\nTE2 t e2\nTE3 t e3\nTE4 t e4\nTENG0 t eng0\nTENG1 t eng1\nTENG2 t eng2\nTENG3 t eng3\nTENG4 t eng4\nTI0 t i0\nTI1 t i1\nTI2 t i2\nTI3 t i3\nTI4 t i4\nTIAN0 t ian0\nTIAN1 t ian1\nTIAN2 t ian2\nTIAN3 t ian3\nTIAN4 t ian4\nTIAO0 t iao0\nTIAO1 t iao1\nTIAO2 t iao2\nTIAO3 t iao3\nTIAO4 t iao4\nTIE0 t ie0\nTIE1 t ie1\nTIE2 t ie2\nTIE3 t ie3\nTIE4 t ie4\nTING0 t ing0\nTING1 t ing1\nTING2 t ing2\nTING3 t ing3\nTING4 t ing4\nTONG0 t ong0\nTONG1 t ong1\nTONG2 t ong2\nTONG3 t ong3\nTONG4 t ong4\nTOU0 t ou0\nTOU1 t ou1\nTOU2 t ou2\nTOU3 t ou3\nTOU4 t ou4\nTU0 t u0\nTU1 t u1\nTU2 t u2\nTU3 t u3\nTU4 t u4\nTUAN0 t uan0\nTUAN1 t uan1\nTUAN2 t uan2\nTUAN3 t uan3\nTUAN4 t uan4\nTUI0 t ui0\nTUI1 t ui1\nTUI2 t ui2\nTUI3 t ui3\nTUI4 t ui4\nTUN0 t un0\nTUN1 t un1\nTUN2 t un2\nTUN3 t un3\nTUN4 t un4\nTUO0 t uo0\nTUO1 t uo1\nTUO2 t uo2\nTUO3 t uo3\nTUO4 t uo4\nWA0 uu ua0\nWA1 uu ua1\nWA2 uu ua2\nWA3 uu ua3\nWA4 uu ua4\nWAI0 uu uai0\nWAI1 uu uai1\nWAI2 uu uai2\nWAI3 uu uai3\nWAI4 uu uai4\nWAN0 uu uan0\nWAN1 uu uan1\nWAN2 uu uan2\nWAN3 uu uan3\nWAN4 uu uan4\nWANG0 uu uang0\nWANG1 uu uang1\nWANG2 uu uang2\nWANG3 uu uang3\nWANG4 uu uang4\nWEI0 uu ui0\nWEI1 uu ui1\nWEI2 uu ui2\nWEI3 uu ui3\nWEI4 uu ui4\nWEN0 uu un0\nWEN1 uu un1\nWEN2 uu un2\nWEN3 uu un3\nWEN4 uu un4\nWENG0 uu ueng0\nWENG1 uu ueng1\nWENG2 uu ueng2\nWENG3 uu ueng3\nWENG4 uu ueng4\nWO0 uu uo0\nWO1 uu uo1\nWO2 uu uo2\nWO3 uu uo3\nWO4 uu uo4\nWU0 uu u0\nWU1 uu u1\nWU2 uu u2\nWU3 uu u3\nWU4 uu u4\nXI0 x i0\nXI1 x i1\nXI2 x i2\nXI3 x i3\nXI4 x i4\nXIA0 x ia0\nXIA1 x ia1\nXIA2 x ia2\nXIA3 x ia3\nXIA4 x ia4\nXIAN0 x ian0\nXIAN1 x ian1\nXIAN2 x ian2\nXIAN3 x ian3\nXIAN4 x ian4\nXIANG0 x iang0\nXIANG1 x iang1\nXIANG2 x iang2\nXIANG3 x iang3\nXIANG4 x iang4\nXIAO0 x iao0\nXIAO1 x iao1\nXIAO2 x iao2\nXIAO3 x iao3\nXIAO4 x iao4\nXIE0 x ie0\nXIE1 x ie1\nXIE2 x ie2\nXIE3 x ie3\nXIE4 x ie4\nXIN0 x in0\nXIN1 x in1\nXIN2 x in2\nXIN3 x in3\nXIN4 x in4\nXING0 x ing0\nXING1 x ing1\nXING2 x ing2\nXING3 x ing3\nXING4 x ing4\nXIONG0 x iong0\nXIONG1 x iong1\nXIONG2 x iong2\nXIONG3 x iong3\nXIONG4 x iong4\nXIU0 x iu0\nXIU1 x iu1\nXIU2 x iu2\nXIU3 x iu3\nXIU4 x iu4\nXU0 x v0\nXU1 x v1\nXU2 x v2\nXU3 x v3\nXU4 x v4\nXUAN0 x van0\nXUAN1 x van1\nXUAN2 x van2\nXUAN3 x van3\nXUAN4 x van4\nXUE0 x ve0\nXUE1 x ve1\nXUE2 x ve2\nXUE3 x ve3\nXUE4 x ve4\nXUN0 x vn0\nXUN1 x vn1\nXUN2 x vn2\nXUN3 x vn3\nXUN4 x vn4\nYA0 ii ia0\nYA1 ii ia1\nYA2 ii ia2\nYA3 ii ia3\nYA4 ii ia4\nYAN0 ii ian0\nYAN1 ii ian1\nYAN2 ii ian2\nYAN3 ii ian3\nYAN4 ii ian4\nYANG0 ii iang0\nYANG1 ii iang1\nYANG2 ii iang2\nYANG3 ii iang3\nYANG4 ii iang4\nYAO0 ii iao0\nYAO1 ii iao1\nYAO2 ii iao2\nYAO3 ii iao3\nYAO4 ii iao4\nYE0 ii ie0\nYE1 ii ie1\nYE2 ii ie2\nYE3 ii ie3\nYE4 ii ie4\nYI0 ii i0\nYI1 ii i1\nYI2 ii i2\nYI3 ii i3\nYI4 ii i4\nYIN0 ii in0\nYIN1 ii in1\nYIN2 ii in2\nYIN3 ii in3\nYIN4 ii in4\nYING0 ii ing0\nYING1 ii ing1\nYING2 ii ing2\nYING3 ii ing3\nYING4 ii ing4\nYO0 ii ou0\nYO1 ii ou1\nYO2 ii ou2\nYO3 ii ou3\nYO4 ii ou4\nYONG0 ii iong0\nYONG1 ii iong1\nYONG2 ii iong2\nYONG3 ii iong3\nYONG4 ii iong4\nYOU0 ii iu0\nYOU1 ii iu1\nYOU2 ii iu2\nYOU3 ii iu3\nYOU4 ii iu4\nYU0 vv v0\nYU1 vv v1\nYU2 vv v2\nYU3 vv v3\nYU4 vv v4\nYUAN0 vv van0\nYUAN1 vv van1\nYUAN2 vv van2\nYUAN3 vv van3\nYUAN4 vv van4\nYUE0 vv ve0\nYUE1 vv ve1\nYUE2 vv ve2\nYUE3 vv ve3\nYUE4 vv ve4\nYUN0 vv vn0\nYUN1 vv vn1\nYUN2 vv vn2\nYUN3 vv vn3\nYUN4 vv vn4\nYUO0 ii ou0\nYUO1 ii ou1\nYUO2 ii ou2\nYUO3 ii ou3\nYUO4 ii ou4\nZA0 z a0\nZA1 z a1\nZA2 z a2\nZA3 z a3\nZA4 z a4\nZAI0 z ai0\nZAI1 z ai1\nZAI2 z ai2\nZAI3 z ai3\nZAI4 z ai4\nZAN0 z an0\nZAN1 z an1\nZAN2 z an2\nZAN3 z an3\nZAN4 z an4\nZANG0 z ang0\nZANG1 z ang1\nZANG2 z ang2\nZANG3 z ang3\nZANG4 z ang4\nZAO0 z ao0\nZAO1 z ao1\nZAO2 z ao2\nZAO3 z ao3\nZAO4 z ao4\nZE0 z e0\nZE1 z e1\nZE2 z e2\nZE3 z e3\nZE4 z e4\nZEI0 z ei0\nZEI1 z ei1\nZEI2 z ei2\nZEI3 z ei3\nZEI4 z ei4\nZEN0 z en0\nZEN1 z en1\nZEN2 z en2\nZEN3 z en3\nZEN4 z en4\nZENG0 z eng0\nZENG1 z eng1\nZENG2 z eng2\nZENG3 z eng3\nZENG4 z eng4\nZHA0 zh a0\nZHA1 zh a1\nZHA2 zh a2\nZHA3 zh a3\nZHA4 zh a4\nZHAI0 zh ai0\nZHAI1 zh ai1\nZHAI2 zh ai2\nZHAI3 zh ai3\nZHAI4 zh ai4\nZHAN0 zh an0\nZHAN1 zh an1\nZHAN2 zh an2\nZHAN3 zh an3\nZHAN4 zh an4\nZHANG0 zh ang0\nZHANG1 zh ang1\nZHANG2 zh ang2\nZHANG3 zh ang3\nZHANG4 zh ang4\nZHAO0 zh ao0\nZHAO1 zh ao1\nZHAO2 zh ao2\nZHAO3 zh ao3\nZHAO4 zh ao4\nZHE0 zh e0\nZHE1 zh e1\nZHE2 zh e2\nZHE3 zh e3\nZHE4 zh e4\nZHEI0 zh ei0\nZHEI1 zh ei1\nZHEI2 zh ei2\nZHEI3 zh ei3\nZHEI4 zh ei4\nZHEN0 zh en0\nZHEN1 zh en1\nZHEN2 zh en2\nZHEN3 zh en3\nZHEN4 zh en4\nZHENG0 zh eng0\nZHENG1 zh eng1\nZHENG2 zh eng2\nZHENG3 zh eng3\nZHENG4 zh eng4\nZHI0 zh ix0\nZHI1 zh ix1\nZHI2 zh ix2\nZHI3 zh ix3\nZHI4 zh ix4\nZHONG0 zh ong0\nZHONG1 zh ong1\nZHONG2 zh ong2\nZHONG3 zh ong3\nZHONG4 zh ong4\nZHOU0 zh ou0\nZHOU1 zh ou1\nZHOU2 zh ou2\nZHOU3 zh ou3\nZHOU4 zh ou4\nZHU0 zh u0\nZHU1 zh u1\nZHU2 zh u2\nZHU3 zh u3\nZHU4 zh u4\nZHUA0 zh ua0\nZHUA1 zh ua1\nZHUA2 zh ua2\nZHUA3 zh ua3\nZHUA4 zh ua4\nZHUAI0 zh uai0\nZHUAI1 zh uai1\nZHUAI2 zh uai2\nZHUAI3 zh uai3\nZHUAI4 zh uai4\nZHUAN0 zh uan0\nZHUAN1 zh uan1\nZHUAN2 zh uan2\nZHUAN3 zh uan3\nZHUAN4 zh uan4\nZHUANG0 zh uang0\nZHUANG1 zh uang1\nZHUANG2 zh uang2\nZHUANG3 zh uang3\nZHUANG4 zh uang4\nZHUI0 zh ui0\nZHUI1 zh ui1\nZHUI2 zh ui2\nZHUI3 zh ui3\nZHUI4 zh ui4\nZHUN0 zh un0\nZHUN1 zh un1\nZHUN2 zh un2\nZHUN3 zh un3\nZHUN4 zh un4\nZHUO0 zh uo0\nZHUO1 zh uo1\nZHUO2 zh uo2\nZHUO3 zh uo3\nZHUO4 zh uo4\nZI0 z iy0\nZI1 z iy1\nZI2 z iy2\nZI3 z iy3\nZI4 z iy4\nZONG0 z ong0\nZONG1 z ong1\nZONG2 z ong2\nZONG3 z ong3\nZONG4 z ong4\nZOU0 z ou0\nZOU1 z ou1\nZOU2 z ou2\nZOU3 z ou3\nZOU4 z ou4\nZU0 z u0\nZU1 z u1\nZU2 z u2\nZU3 z u3\nZU4 z u4\nZUAN0 z uan0\nZUAN1 z uan1\nZUAN2 z uan2\nZUAN3 z uan3\nZUAN4 z uan4\nZUI0 z ui0\nZUI1 z ui1\nZUI2 z ui2\nZUI3 z ui3\nZUI4 z ui4\nZUN0 z un0\nZUN1 z un1\nZUN2 z un2\nZUN3 z un3\nZUN4 z un4\nZUO0 z uo0\nZUO1 z uo1\nZUO2 z uo2\nZUO3 z uo3\nZUO4 z uo4\nEI0 ee ei0\nEI1 ee ei1\nEI2 ee ei2\nEI3 ee ei3\nEI4 ee ei4\nTEI0 t ei0\nTEI1 t ei1\nTEI2 t ei2\nTEI3 t ei3\nTEI4 t ei4\nHNG0 ee eng0\nHNG1 ee eng1\nHNG2 ee eng2\nHNG3 ee eng3\nHNG4 ee eng4\nLO0 l o0\nLO1 l o1\nLO2 l o2\nLO3 l o3\nLO4 l o4\nN0 ee en0\nN1 ee en1\nN2 ee en2\nN3 ee en3\nN4 ee en4\nNG0 ee eng0\nNG1 ee eng1\nNG2 ee eng2\nNG3 ee eng3\nNG4 ee eng4\nNOU0 n ao0\nNOU1 n ao1\nNOU2 n ao2\nNOU3 n ao3\nNOU4 n ao4\nSEI0 s ei0\nSEI1 s ei1\nSEI2 s ei2\nSEI3 s ei3\nSEI4 s ei4\nA5 aa a5\nAI5 aa ai5\nAN5 aa an5\nANG5 aa ang5\nAO5 aa ao5\nBA5 b a5\nBAI5 b ai5\nBAN5 b an5\nBANG5 b ang5\nBAO5 b ao5\nBEI5 b ei5\nBEN5 b en5\nBENG5 b eng5\nBI5 b i5\nBIAN5 b ian5\nBIAO5 b iao5\nBIE5 b ie5\nBIN5 b in5\nBING5 b ing5\nBO5 b o5\nBU5 b u5\nCA5 c a5\nCAI5 c ai5\nCAN5 c an5\nCANG5 c ang5\nCAO5 c ao5\nCE5 c e5\nCEN5 c en5\nCENG5 c eng5\nCHA5 ch a5\nCHAI5 ch ai5\nCHAN5 ch an5\nCHANG5 ch ang5\nCHAO5 ch ao5\nCHE5 ch e5\nCHEN5 ch en5\nCHENG5 ch eng5\nCHI5 ch ix5\nCHONG5 ch ong5\nCHOU5 ch ou5\nCHU5 ch u5\nCHUAI5 ch uai5\nCHUAN5 ch uan5\nCHUANG5 ch uang5\nCHUI5 ch ui5\nCHUN5 ch un5\nCHUO5 ch uo5\nCI5 c iy5\nCONG5 c ong5\nCOU5 c ou5\nCU5 c u5\nCUAN5 c uan5\nCUI5 c ui5\nCUN5 c un5\nCUO5 c uo5\nDA5 d a5\nDAI5 d ai5\nDAN5 d an5\nDANG5 d ang5\nDAO5 d ao5\nDE5 d e5\nDEI5 d ei5\nDEN5 d en5\nDENG5 d eng5\nDI5 d i5\nDIA5 d ia5\nDIAN5 d ian5\nDIAO5 d iao5\nDIE5 d ie5\nDING5 d ing5\nDIU5 d iu5\nDONG5 d ong5\nDOU5 d ou5\nDU5 d u5\nDUAN5 d uan5\nDUI5 d ui5\nDUN5 d un5\nDUO5 d uo5\nE5 ee e5\nEN5 ee en5\nER5 ee er5\nFA5 f a5\nFAN5 f an5\nFANG5 f ang5\nFEI5 f ei5\nFEN5 f en5\nFENG5 f eng5\nFO5 f o5\nFOU5 f ou5\nFU5 f u5\nGA5 g a5\nGAI5 g ai5\nGAN5 g an5\nGANG5 g ang5\nGAO5 g ao5\nGE5 g e5\nGEI5 g ei5\nGEN5 g en5\nGENG5 g eng5\nGONG5 g ong5\nGOU5 g ou5\nGU5 g u5\nGUA5 g ua5\nGUAI5 g uai5\nGUAN5 g uan5\nGUANG5 g uang5\nGUI5 g ui5\nGUN5 g un5\nGUO5 g uo5\nHA5 h a5\nHAI5 h ai5\nHAN5 h an5\nHANG5 h ang5\nHAO5 h ao5\nHE5 h e5\nHEI5 h ei5\nHEN5 h en5\nHENG5 h eng5\nHONG5 h ong5\nHOU5 h ou5\nHU5 h u5\nHUA5 h ua5\nHUAI5 h uai5\nHUAN5 h uan5\nHUANG5 h uang5\nHUI5 h ui5\nHUN5 h un5\nHUO5 h uo5\nJI5 j i5\nJIA5 j ia5\nJIAN5 j ian5\nJIANG5 j iang5\nJIAO5 j iao5\nJIE5 j ie5\nJIN5 j in5\nJING5 j ing5\nJIONG5 j iong5\nJIU5 j iu5\nJU5 j v5\nJUAN5 j van5\nJUE5 j ve5\nJUN5 j vn5\nKA5 k a5\nKAI5 k ai5\nKAN5 k an5\nKANG5 k ang5\nKAO5 k ao5\nKE5 k e5\nKEI5 k ei5\nKEN5 k en5\nKENG5 k eng5\nKONG5 k ong5\nKOU5 k ou5\nKU5 k u5\nKUA5 k ua5\nKUAI5 k uai5\nKUAN5 k uan5\nKUANG5 k uang5\nKUI5 k ui5\nKUN5 k un5\nKUO5 k uo5\nLA5 l a5\nLAI5 l ai5\nLAN5 l an5\nLANG5 l ang5\nLAO5 l ao5\nLE5 l e5\nLEI5 l ei5\nLENG5 l eng5\nLI5 l i5\nLIA5 l ia5\nLIAN5 l ian5\nLIANG5 l iang5\nLIAO5 l iao5\nLIE5 l ie5\nLIN5 l in5\nLING5 l ing5\nLIU5 l iu5\nLONG5 l ong5\nLOU5 l ou5\nLU5 l u5\nLUAN5 l uan5\nLUE5 l ve5\nLVE5 l ve5\nLUN5 l un5\nLUO5 l uo5\nLV5 l v5\nMA5 m a5\nMAI5 m ai5\nMAN5 m an5\nMANG5 m ang5\nMAO5 m ao5\nME5 m e5\nMEI5 m ei5\nMEN5 m en5\nMENG5 m eng5\nMI5 m i5\nMIAN5 m ian5\nMIAO5 m iao5\nMIE5 m ie5\nMIN5 m in5\nMING5 m ing5\nMIU5 m iu5\nMO5 m o5\nMOU5 m ou5\nMU5 m u5\nNA5 n a5\nNAI5 n ai5\nNAN5 n an5\nNANG5 n ang5\nNAO5 n ao5\nNE5 n e5\nNEI5 n ei5\nNEN5 n en5\nNENG5 n eng5\nNI5 n i5\nNIAN5 n ian5\nNIANG5 n iang5\nNIAO5 n iao5\nNIE5 n ie5\nNIN5 n in5\nNING5 n ing5\nNIU5 n iu5\nNONG5 n ong5\nNU5 n u5\nNUAN5 n uan5\nNUE5 n ve5\nNVE5 n ve5\nNUO5 n uo5\nNV5 n v5\nO5 oo o5\nOU5 oo ou5\nPA5 p a5\nPAI5 p ai5\nPAN5 p an5\nPANG5 p ang5\nPAO5 p ao5\nPEI5 p ei5\nPEN5 p en5\nPENG5 p eng5\nPI5 p i5\nPIAN5 p ian5\nPIAO5 p iao5\nPIE5 p ie5\nPIN5 p in5\nPING5 p ing5\nPO5 p o5\nPOU5 p ou5\nPU5 p u5\nQI5 q i5\nQIA5 q ia5\nQIAN5 q ian5\nQIANG5 q iang5\nQIAO5 q iao5\nQIE5 q ie5\nQIN5 q in5\nQING5 q ing5\nQIONG5 q iong5\nQIU5 q iu5\nQU5 q v5\nQUAN5 q van5\nQUE5 q ve5\nQUN5 q vn5\nRAN5 r an5\nRANG5 r ang5\nRAO5 r ao5\nRE5 r e5\nREN5 r en5\nRENG5 r eng5\nRI5 r iz5\nRONG5 r ong5\nROU5 r ou5\nRU5 r u5\nRUAN5 r uan5\nRUI5 r ui5\nRUN5 r un5\nRUO5 r uo5\nSA5 s a5\nSAI5 s ai5\nSAN5 s an5\nSANG5 s ang5\nSAO5 s ao5\nSE5 s e5\nSEN5 s en5\nSENG5 s eng5\nSHA5 sh a5\nSHAI5 sh ai5\nSHAN5 sh an5\nSHANG5 sh ang5\nSHAO5 sh ao5\nSHE5 sh e5\nSHEI5 sh ei5\nSHEN5 sh en5\nSHENG5 sh eng5\nSHI5 sh ix5\nSHOU5 sh ou5\nSHU5 sh u5\nSHUA5 sh ua5\nSHUAI5 sh uai5\nSHUAN5 sh uan5\nSHUANG5 sh uang5\nSHUI5 sh ui5\nSHUN5 sh un5\nSHUO5 sh uo5\nSI5 s iy5\nSONG5 s ong5\nSOU5 s ou5\nSU5 s u5\nSUAN5 s uan5\nSUI5 s ui5\nSUN5 s un5\nSUO5 s uo5\nTA5 t a5\nTAI5 t ai5\nTAN5 t an5\nTANG5 t ang5\nTAO5 t ao5\nTE5 t e5\nTENG5 t eng5\nTI5 t i5\nTIAN5 t ian5\nTIAO5 t iao5\nTIE5 t ie5\nTING5 t ing5\nTONG5 t ong5\nTOU5 t ou5\nTU5 t u5\nTUAN5 t uan5\nTUI5 t ui5\nTUN5 t un5\nTUO5 t uo5\nWA5 uu ua5\nWAI5 uu uai5\nWAN5 uu uan5\nWANG5 uu uang5\nWEI5 uu ui5\nWEN5 uu un5\nWENG5 uu ueng5\nWO5 uu uo5\nWU5 uu u5\nXI5 x i5\nXIA5 x ia5\nXIAN5 x ian5\nXIANG5 x iang5\nXIAO5 x iao5\nXIE5 x ie5\nXIN5 x in5\nXING5 x ing5\nXIONG5 x iong5\nXIU5 x iu5\nXU5 x v5\nXUAN5 x van5\nXUE5 x ve5\nXUN5 x vn5\nYA5 ii ia5\nYAN5 ii ian5\nYANG5 ii iang5\nYAO5 ii iao5\nYE5 ii ie5\nYI5 ii i5\nYIN5 ii in5\nYING5 ii ing5\nYO5 ii ou5\nYONG5 ii iong5\nYOU5 ii iu5\nYU5 vv v5\nYUAN5 vv van5\nYUE5 vv ve5\nYUN5 vv vn5\nYUO5 ii ou5\nZA5 z a5\nZAI5 z ai5\nZAN5 z an5\nZANG5 z ang5\nZAO5 z ao5\nZE5 z e5\nZEI5 z ei5\nZEN5 z en5\nZENG5 z eng5\nZHA5 zh a5\nZHAI5 zh ai5\nZHAN5 zh an5\nZHANG5 zh ang5\nZHAO5 zh ao5\nZHE5 zh e5\nZHEI5 zh ei5\nZHEN5 zh en5\nZHENG5 zh eng5\nZHI5 zh ix5\nZHONG5 zh ong5\nZHOU5 zh ou5\nZHU5 zh u5\nZHUA5 zh ua5\nZHUAI5 zh uai5\nZHUAN5 zh uan5\nZHUANG5 zh uang5\nZHUI5 zh ui5\nZHUN5 zh un5\nZHUO5 zh uo5\nZI5 z iy5\nZONG5 z ong5\nZOU5 z ou5\nZU5 z u5\nZUAN5 z uan5\nZUI5 z ui5\nZUN5 z un5\nZUO5 z uo5\nEI5 ee ei5\nTEI5 t ei5\nHNG5 ee eng5\nLO5 l o5\nN5 ee en5\nNG5 ee eng5\nNOU5 n ao5\nSEI5 s ei5"
  },
  {
    "path": "examples/thchs30/align0/local/data.sh",
    "content": "#! /usr/bin/env bash\n\nstage=-1\nstop_stage=100\n\nsource ${MAIN_ROOT}/utils/parse_options.sh\n\nmkdir -p data\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\nLEXICON_NAME=$1\n\n# download data, generate manifests\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    python3 ${TARGET_DIR}/thchs30/thchs30.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/thchs30\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare THCHS-30 failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # dump manifest to data/\n    python3 ${MAIN_ROOT}/utils/dump_manifest.py --manifest-path=data/manifest.train --output-dir=data\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # copy files to data/dict to gen word.lexicon\n    cp  ${TARGET_DIR}/thchs30/data_thchs30/lm_word/lexicon.txt data/dict/lm_word_lexicon_1\n    cp  ${TARGET_DIR}/thchs30/resource/dict/lexicon.txt data/dict/lm_word_lexicon_2\n    # copy phone.lexicon to data/dict\n    cp  ${TARGET_DIR}/thchs30/data_thchs30/lm_phone/lexicon.txt data/dict/phone.lexicon\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # gen word.lexicon\n    python local/gen_word2phone.py  --lexicon-files=\"data/dict/lm_word_lexicon_1 data/dict/lm_word_lexicon_2\" --output-path=data/dict/word.lexicon\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # reorganize dataset for MFA\n    if [ ! -d $EXP_DIR/thchs30_corpus ]; then\n        echo \"reorganizing thchs30 corpus...\"\n        python local/reorganize_thchs30.py --root-dir=data --output-dir=data/thchs30_corpus --script-type=$LEXICON_NAME\n        echo \"reorganization done.\"\n    fi\nfi\n\necho \"THCHS-30  data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/thchs30/align0/local/gen_word2phone.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Gen Chinese characters to THCHS30-30 phone lexicon using THCHS30-30's lexicon\nfile1: THCHS-30/data_thchs30/lm_word/lexicon.txt\nfile2: THCHS-30/resource/dict/lexicon.txt\n\"\"\"\nimport argparse\nfrom collections import defaultdict\nfrom pathlib import Path\nfrom typing import List\nfrom typing import Union\n\n# key: (cn, ('ee', 'er4'))，value: count\ncn_phones_counter = defaultdict(int)\n# key: cn, value: list of (phones, num)\ncn_counter = defaultdict(list)\n# key: cn, value: list of (phones, probabilities)\ncn_counter_p = defaultdict(list)\n\n\ndef is_Chinese(ch):\n    if '\\u4e00' <= ch <= '\\u9fff':\n        return True\n    return False\n\n\ndef proc_line(line: str):\n    line = line.strip()\n    if is_Chinese(line[0]):\n        line_list = line.split()\n        cn_list = line_list[0]\n        phone_list = line_list[1:]\n        if len(cn_list) == len(phone_list) / 2:\n            new_phone_list = [(phone_list[i], phone_list[i + 1])\n                              for i in range(0, len(phone_list), 2)]\n            assert len(cn_list) == len(new_phone_list)\n            for idx, cn in enumerate(cn_list):\n                phones = new_phone_list[idx]\n                cn_phones_counter[(cn, phones)] += 1\n\n\n\"\"\"\nexample lines of output\nthe first column is a Chinese character\nthe second is the probability of this pronunciation\nand the rest are the phones of this pronunciation\n一 0.22 ii i1↩\n一 0.45 ii i4↩\n一 0.32 ii i2↩\n一 0.01 ii i5\n\"\"\"\n\n\ndef gen_lexicon(lexicon_files: List[Union[str, Path]],\n                output_path: Union[str, Path]):\n    for file_path in lexicon_files:\n        with open(file_path, \"r\") as f1:\n            for line in f1:\n                proc_line(line)\n\n    for key in cn_phones_counter:\n        cn = key[0]\n        cn_counter[cn].append((key[1], cn_phones_counter[key]))\n\n    for key in cn_counter:\n        phone_count_list = cn_counter[key]\n        count_sum = sum([x[1] for x in phone_count_list])\n        for item in phone_count_list:\n            p = item[1] / count_sum\n            p = round(p, 2)\n            if p > 0:\n                cn_counter_p[key].append((item[0], p))\n\n    with open(output_path, \"w\") as wf:\n        for key in cn_counter_p:\n            phone_p_list = cn_counter_p[key]\n            for item in phone_p_list:\n                phones, p = item\n                wf.write(key + \" \" + str(p) + \" \" + \" \".join(phones) + \"\\n\")\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Gen Chinese characters to phone lexicon for THCHS-30 dataset\"\n    )\n    # A line of word_lexicon:\n    # 一丁点 ii i4 d ing1 d ian3\n    # the first is word, and the rest are the phones of the word, and the len of phones is twice of the word's len\n    parser.add_argument(\n        \"--lexicon-files\",\n        type=str,\n        default=\"data/dict/lm_word_lexicon_1 data/dict/lm_word_lexicon_2\",\n        help=\"lm_word_lexicon files\")\n    parser.add_argument(\n        \"--output-path\",\n        type=str,\n        default=\"data/dict/word.lexicon\",\n        help=\"path to save output word2phone lexicon\")\n    args = parser.parse_args()\n    lexicon_files = args.lexicon_files.split(\" \")\n    output_path = Path(args.output_path).expanduser()\n\n    gen_lexicon(lexicon_files, output_path)\n"
  },
  {
    "path": "examples/thchs30/align0/local/reorganize_thchs30.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Recorganize THCHS-30 for MFA\nread manifest.train from root-dir\nLink *.wav to output-dir\ndump *.lab from manifest.train, such as: text、syllable and phone\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\n\"\"\"\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Union\n\n\ndef link_wav(root_dir: Union[str, Path], output_dir: Union[str, Path]):\n    wav_scp_path = root_dir / 'wav.scp'\n    with open(wav_scp_path, 'r') as rf:\n        for line in rf:\n            utt, feat = line.strip().split()\n            wav_path = feat\n            wav_name = wav_path.split(\"/\")[-1]\n            new_wav_path = output_dir / wav_name\n            os.symlink(wav_path, new_wav_path)\n\n\ndef write_lab(root_dir: Union[str, Path],\n              output_dir: Union[str, Path],\n              script_type='phone'):\n    # script_type can in {'word', 'syllable', 'phone'}\n    json_name = 'text.' + script_type\n    json_path = root_dir / json_name\n    with open(json_path, 'r') as rf:\n        for line in rf:\n            line = line.strip().split()\n            utt_id = line[0]\n            context = ' '.join(line[1:])\n            transcript_name = utt_id + '.lab'\n            transcript_path = output_dir / transcript_name\n            with open(transcript_path, 'wt') as wf:\n                if script_type == 'word':\n                    # add space between chinese char\n                    context = ''.join([f + ' ' for f in context])[:-1]\n                wf.write(context + \"\\n\")\n\n\ndef reorganize_thchs30(root_dir: Union[str, Path],\n                       output_dir: Union[str, Path]=None,\n                       script_type='phone'):\n    output_dir.mkdir(parents=True, exist_ok=True)\n    link_wav(root_dir, output_dir)\n    write_lab(root_dir, output_dir, script_type)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Reorganize THCHS-30 dataset for MFA\")\n    parser.add_argument(\"--root-dir\", type=str, help=\"path to thchs30 dataset.\")\n    parser.add_argument(\n        \"--output-dir\",\n        type=str,\n        help=\"path to save outputs (audio and transcriptions)\")\n\n    parser.add_argument(\n        \"--script-type\",\n        type=str,\n        default=\"phone\",\n        help=\"type of lab ('word'/'syllable'/'phone')\")\n\n    args = parser.parse_args()\n    root_dir = Path(args.root_dir).expanduser()\n    output_dir = Path(args.output_dir).expanduser()\n    reorganize_thchs30(root_dir, output_dir, args.script_type)\n"
  },
  {
    "path": "examples/thchs30/align0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n# MFA is in tools\nexport PATH=${MAIN_ROOT}/tools/montreal-forced-aligner/bin:$PATH"
  },
  {
    "path": "examples/thchs30/align0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\nstage=0\nstop_stage=100\nEXP_DIR=exp\n# LEXICON_NAME in {'phone', 'syllable', 'word'}\nLEXICON_NAME='phone'\n# set MFA num_jobs as half of machine's cpu core number\nNUM_JOBS=$((`nproc`/2))\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\n# download dataset、unzip and generate manifest \n# gen lexicon relink gen dump\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    echo \"Start prepare thchs30 data for MFA ...\"\n    bash ./local/data.sh $LEXICON_NAME || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # run MFA\n    if [ ! -d \"$EXP_DIR/thchs30_alignment\" ]; then\n        echo \"Start MFA training ...\"\n        mfa_train_and_align data/thchs30_corpus data/dict/$LEXICON_NAME.lexicon $EXP_DIR/thchs30_alignment -o $EXP_DIR/thchs30_model --clean --verbose --temp_directory exp/.mfa_train_and_align --num_jobs $NUM_JOBS\n        echo \"MFA training done! \\nresults: $EXP_DIR/thchs30_alignment \\nmodel: $EXP_DIR/thchs30_model\\n\"\n    fi\nfi\n\n\n\n\n\n\n\n"
  },
  {
    "path": "examples/timit/README.md",
    "content": "# TIMIT\n\n* asr1 - transformer Streaming/Non-Streaming\n"
  },
  {
    "path": "examples/timit/asr1/.gitignore",
    "content": "data\nexp\ntest.profile\n"
  },
  {
    "path": "examples/timit/asr1/README.md",
    "content": "# Transformer ASR with Timit\nThe phoneme-based continuous speech corpus is a collaboration between Texas Instruments, MIT, and SRI International. The [Timit](https://catalog.ldc.upenn.edu/docs/LDC93S1/) dataset has a voice sampling frequency of 16 khz and contains a total of 6,300 sentences, with 630 people from 8 major U.S. dialects speaking a given 10 sentences each, all sentences are manually segmented and marked at the phone level. Seventy percent of the speakers are male; most of the speakers are white adults.\n\n## Dataset\n### Download and Extract\nDownload TIMIT from it's [official website](https://catalog.ldc.upenn.edu/LDC93S1) and extract it to `~/datasets`. Assume unzip the dataset in the directory `~/datasets/timit`.\n\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Get ctc alignment of test data using the final model         |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage `.\n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in `run.sh` in detail.\n## The Environment Variables\nThe path.sh contains the environment variables.\n```bash\nsource path.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`audio_file` denotes the file path of the single file you want to infer in stage 5\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"conformer\"\nYou can set the local variables (except `ckpt`) when you use `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1,2,3 --avg_num 10\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/timit_data_prep.sh ${TIMIT_path}\n     bash ./local/data.sh || exit -1\n fi\n```\n\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/timit_data_prep.sh ${TIMIT_path}\nbash ./local/data.sh\n```\nAfter processing the data, the ``data`` directory will look like this:\n```bash\ndata/\n|-- lang_char\n|   `-- vocab.txt\n|-- local\n|   `-- dev_sph.flist\n|   `-- dev_sph.scp\n|   `-- dev.text\n|   `-- dev.trans\n|   `-- dev.uttids\n|   `-- test_sph.flist\n|   `-- test_sph.scp\n|   `-- test.text\n|   `-- test.trans\n|   `-- test.uttids\n|   `-- train_sph.flist\n|   `-- train_sph.scp\n|   `-- train.text\n|   `-- train.trans\n|   `-- train.uttids\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line.\n```bash\nsource path.sh\nbash ./local/timit_data_prep.sh ${TIMIT_path}\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh conf/transformer.yaml transformer\n```\n## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh`is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line.\n```bash\nbash ./local/timit_data_prep.sh ${TIMIT_path}\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/conformer/checkpoints 10\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line.\n```bash\nsource path.sh\nbash ./local/timit_data_prep.sh ${TIMIT_path}\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 10\nCUDA_VISIBLE_DEVICES=0 ./local/test.sh conf/transformer.yaml exp/transformer/checkpoints/avg_10\n```\n## Stage 4: CTC Alignment \nIf you want to get the alignment between the audio and the text, you can use the ctc alignment. The code of this stage is shown below:\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # ctc alignment of test data\n     CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train the model, test it and do the alignment, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 4\n```\nor if you only need to train a model and do the alignment, you can use these scripts to escape stage 3(test stage):\n```bash\nbash run.sh --stage 0 --stop_stage 2\nbash run.sh --stage 4 --stop_stage 4\n```\nor you can also use these scripts in the command line.\n```bash\nsource path.sh\nbash ./local/timit_data_prep.sh ${TIMIT_path}\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 10\n# test stage is optional\nCUDA_VISIBLE_DEVICES=0 ./local/test.sh conf/transformer.yaml exp/transformer/checkpoints/avg_10\nCUDA_VISIBLE_DEVICES=0 ./local/align.sh conf/transformer.yaml exp/transformer/checkpoints/avg_10\n```\n"
  },
  {
    "path": "examples/timit/asr1/RESULTS.md",
    "content": "# TIMIT\n\n### Transformer\n| Model | Params | Config | Decode method | Loss |  PER |\n| --- | --- | --- | --- | --- | --- |\n| transformer | 5.17M | conf/transformer.yaml | attention              | 46.41119385 | 0.396950 |\n| transformer | 5.17M | conf/transformer.yaml | ctc_greedy_search      | 46.41119385 | 0.182259 |\n| transformer | 5.17M | conf/transformer.yaml | ctc_prefix_beam_search | 46.41119385 | 0.188080 |\n| transformer | 5.17M | conf/transformer.yaml | attention_rescore      | 46.41119385 | 0.184199 |\n"
  },
  {
    "path": "examples/timit/asr1/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.9,\n      \"max_speed_rate\": 1.1,\n      \"num_rates\": 3\n    },\n    \"prob\": 0.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"F\": 10,\n      \"T\": 50,\n      \"n_freq_masks\": 2,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"W\": 80,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": true,\n      \"warp_mode\": \"PIL\"\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/timit/asr1/conf/dev_spk.list",
    "content": "faks0\nfdac1\nfjem0\nmgwt0\nmjar0\nmmdb1\nmmdm2\nmpdf0\nfcmh0\nfkms0\nmbdg0\nmbwm0\nmcsh0\nfadg0\nfdms0\nfedw0\nmgjf0\nmglb0\nmrtk0\nmtaa0\nmtdt0\nmthc0\nmwjg0\nfnmr0\nfrew0\nfsem0\nmbns0\nmmjr0\nmdls0\nmdlf0\nmdvc0\nmers0\nfmah0\nfdrw0\nmrcs0\nmrjm4\nfcal1\nmmwh0\nfjsj0\nmajc0\nmjsw0\nmreb0\nfgjd0\nfjmg0\nmroa0\nmteb0\nmjfc0\nmrjr0\nfmml0\nmrws1"
  },
  {
    "path": "examples/timit/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n\n\n\n\n"
  },
  {
    "path": "examples/timit/asr1/conf/test_spk.list",
    "content": "mdab0\nmwbt0\nfelc0\nmtas1\nmwew0\nfpas0\nmjmp0\nmlnt0\nfpkt0\nmlll0\nmtls0\nfjlm0\nmbpm0\nmklt0\nfnlp0\nmcmj0\nmjdh0\nfmgd0\nmgrt0\nmnjm0\nfdhc0\nmjln0\nmpam0\nfmld0"
  },
  {
    "path": "examples/timit/asr1/conf/transformer.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.train\ndev_manifest: data/manifest.dev\ntest_manifest: data/manifest.test\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt\nspm_model_prefix: ''\nunit_type: \"word\"\nmean_std_filepath: \"\"\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 64\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 128    # dimension of attention\n    attention_heads: 4\n    linear_units: 1024  # the number of units of position-wise feed forward\n    num_blocks: 6      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 1024\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.5\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 50\naccum_grad: 1\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.004\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 1200\n  lr_decay: 1.0\nlog_interval: 10\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n\n"
  },
  {
    "path": "examples/timit/asr1/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 64\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/timit/asr1/local/align.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/alignment.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/timit/asr1/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\ndict_dir=data/lang_char\n\nunit_type=word\nTIMIT_path=\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/timit/timit_kaldi_standard_split.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --src=\"data/local\" \\\n\n    if [ $? -ne 0 ]; then\n        echo \"Prepare TIMIT failed. Terminated.\"\n        exit 1\n    fi\nfi\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    num_workers=$(nproc)\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.train.raw\" \\\n    --num_samples=-1 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=${num_workers} \\\n    --output_path=\"data/mean_std.json\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.train.raw\"\n\n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    for set in train dev test; do\n    {\n        python3 ${MAIN_ROOT}/utils/format_data.py \\\n        --cmvn_path \"data/mean_std.json\" \\\n        --unit_type ${unit_type} \\\n        --vocab_path=\"${dict_dir}/vocab.txt\" \\\n        --manifest_path=\"data/manifest.${set}.raw\" \\\n        --output_path=\"data/manifest.${set}\"\n\n        if [ $? -ne 0 ]; then\n            echo \"Formt mnaifest.${set} failed. Terminated.\"\n            exit 1\n        fi\n    }&\n    done\n    wait\nfi\n\necho \"TIMIT Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/timit/asr1/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/timit/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nset -e\n\nstage=0\nstop_stage=50\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    for type in attention ctc_greedy_search; do\n        echo \"decoding ${type}\"\n        if [ ${chunk_mode} == true ];then\n            # stream decoding only support batchsize=1\n            batch_size=1\n        else\n            batch_size=64\n        fi\n        python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu} \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n    \n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n    done\nfi\n\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    for type in ctc_prefix_beam_search; do\n        echo \"decoding ${type}\"\n        batch_size=1\n        python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu}  \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n    \n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n    done\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    for type in attention_rescoring; do\n        echo \"decoding ${type}\"\n        batch_size=1\n        python3 -u ${BIN_DIR}/test.py \\\n        --ngpu ${ngpu}  \\\n        --config ${config_path} \\\n        --decode_cfg ${decode_config_path} \\\n        --result_file ${ckpt_prefix}.${type}.rsl \\\n        --checkpoint_path ${ckpt_prefix} \\\n        --opts decode.decoding_method ${type} \\\n        --opts decode.decode_batch_size ${batch_size}\n    \n        if [ $? -ne 0 ]; then\n            echo \"Failed in evaluation!\"\n            exit 1\n        fi\n    done\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/timit/asr1/local/timit_data_prep.sh",
    "content": "#!/usr/bin/env bash\n\n# Copyright 2013   (Authors: Bagher BabaAli, Daniel Povey, Arnab Ghoshal)\n#           2014   Brno University of Technology (Author: Karel Vesely)\n# Apache 2.0.\n\nif [ $# -ne 1 ]; then\n   echo \"Argument should be the Timit directory, see ../run.sh for example.\"\n   exit 1;\nfi\n\ndir=`pwd`/data/local\nmkdir -p $dir\nlocal=`pwd`/local\nutils=`pwd`/utils\nconf=`pwd`/conf\n\nfunction error_exit () {\n  echo -e \"$@\" >&2; exit 1;\n}\nPROG=$(basename $0)\n\n[ -f $conf/test_spk.list ] || error_exit \"$PROG line $LINENO: Eval-set speaker list not found.\";\n[ -f $conf/dev_spk.list ] || error_exit \"$PROG line $LINENO: dev-set speaker list not found.\";\n\n# First check if the train & test directories exist (these can either be upper-\n# or lower-cased\nif [ ! -d $*/TRAIN -o ! -d $*/TEST ] && [ ! -d $*/train -o ! -d $*/test ]; then\n  echo \"timit_data_prep.sh: Spot check of command line argument failed\"\n  echo \"Command line argument must be absolute pathname to TIMIT directory\"\n  echo \"with name like /export/corpora5/LDC/LDC93S1/timit/TIMIT\"\n  exit 1;\nfi\n\n# Now check what case the directory structure is\nuppercased=false\ntrain_dir=train\ntest_dir=test\nif [ -d $*/TRAIN ]; then\n  uppercased=true\n  train_dir=TRAIN\n  test_dir=TEST\nfi\n\ntmpdir=$(mktemp -d /tmp/kaldi.XXXX);\ntrap 'rm -rf \"$tmpdir\"' EXIT\n\n# Get the list of speakers. The list of speakers in the 24-speaker core test\n# set and the 50-speaker development set must be supplied to the script. All\n# speakers in the 'train' directory are used for training.\nif $uppercased; then\n  tr '[:lower:]' '[:upper:]' < $conf/dev_spk.list > $tmpdir/dev_spk\n  tr '[:lower:]' '[:upper:]' < $conf/test_spk.list > $tmpdir/test_spk\n  ls -d \"$*\"/TRAIN/DR*/* | sed -e \"s:^.*/::\" > $tmpdir/train_spk\nelse\n  tr '[:upper:]' '[:lower:]' < $conf/dev_spk.list > $tmpdir/dev_spk\n  tr '[:upper:]' '[:lower:]' < $conf/test_spk.list > $tmpdir/test_spk\n  ls -d \"$*\"/train/dr*/* | sed -e \"s:^.*/::\" > $tmpdir/train_spk\nfi\n\ncd $dir\nfor x in train dev test; do\n  # First, find the list of audio files (use only si & sx utterances).\n  # Note: train & test sets are under different directories, but doing find on\n  # both and grepping for the speakers will work correctly.\n  find $*/{$train_dir,$test_dir} -not \\( -iname 'SA*' \\) -iname '*.WAV' \\\n    | grep -f $tmpdir/${x}_spk > ${x}_sph.flist\n\n  sed -e 's:.*/\\(.*\\)/\\(.*\\).\\(WAV\\|wav\\)$:\\1_\\2:' ${x}_sph.flist \\\n    > $tmpdir/${x}_sph.uttids\n  paste $tmpdir/${x}_sph.uttids ${x}_sph.flist \\\n    | sort -k1,1 > ${x}_sph.scp\n\n  cat ${x}_sph.scp | awk '{print $1}' > ${x}.uttids\n\n  # Now, Convert the transcripts into our format (no normalization yet)\n  # Get the transcripts: each line of the output contains an utterance\n  # ID followed by the transcript.\n  find $*/{$train_dir,$test_dir} -not \\( -iname 'SA*' \\) -iname '*.PHN' \\\n    | grep -f $tmpdir/${x}_spk > $tmpdir/${x}_phn.flist\n  sed -e 's:.*/\\(.*\\)/\\(.*\\).\\(PHN\\|phn\\)$:\\1_\\2:' $tmpdir/${x}_phn.flist \\\n    > $tmpdir/${x}_phn.uttids\n  while read line; do\n    [ -f $line ] || error_exit \"Cannot find transcription file '$line'\";\n    cut -f3 -d' ' \"$line\" | tr '\\n' ' ' | perl -ape 's: *$:\\n:;'\n  done < $tmpdir/${x}_phn.flist > $tmpdir/${x}_phn.trans\n  paste $tmpdir/${x}_phn.uttids $tmpdir/${x}_phn.trans \\\n    | sort -k1,1 > ${x}.trans\n\n  # Do normalization steps.\n  cat ${x}.trans | $local/timit_norm_trans.pl -i - -m $conf/phones.60-48-39.map -to 39 | sort > $x.text || exit 1;\n\ndone\n\necho \"Data preparation succeeded\""
  },
  {
    "path": "examples/timit/asr1/local/timit_norm_trans.pl",
    "content": "#!/usr/bin/env perl\nuse warnings; #sed replacement for -w perl parameter\n\n# Copyright 2012  Arnab Ghoshal\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#  http://www.apache.org/licenses/LICENSE-2.0\n#\n# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n# MERCHANTABLITY OR NON-INFRINGEMENT.\n# See the Apache 2 License for the specific language governing permissions and\n# limitations under the License.\n\n\n# This script normalizes the TIMIT phonetic transcripts that have been \n# extracted in a format where each line contains an utterance ID followed by \n# the transcript, e.g.:\n# fcke0_si1111 h# hh ah dx ux w iy dcl d ix f ay n ih q h#\n\nmy $usage = \"Usage: timit_norm_trans.pl -i transcript -m phone_map -from [60|48] -to [48|39] > normalized\\n\nNormalizes phonetic transcriptions for TIMIT, by mapping the phones to a \nsmaller set defined by the -m option. This script assumes that the mapping is \ndone in the \\\"standard\\\" fashion, i.e. to 48 or 39 phones.  The input is \nassumed to have 60 phones (+1 for glottal stop, which is deleted), but that can\nbe changed using the -from option. The input format is assumed to be utterance \nID followed by transcript on the same line.\\n\";\n\nuse strict;\nuse Getopt::Long;\ndie \"$usage\" unless(@ARGV >= 1);\nmy ($in_trans, $phone_map, $num_phones_out);\nmy $num_phones_in = 60;\nGetOptions (\"i=s\" => \\$in_trans,          # Input transcription\n\t    \"m=s\" => \\$phone_map,         # File containing phone mappings\n\t    \"from=i\" => \\$num_phones_in,  # Input #phones: must be 60 or 48\n\t    \"to=i\" => \\$num_phones_out ); # Output #phones: must be 48 or 39\n\ndie $usage unless(defined($in_trans) && defined($phone_map) && \n\t\t  defined($num_phones_out));\nif ($num_phones_in != 60 && $num_phones_in != 48) {\n  die \"Can only used 60 or 48 for -from (used $num_phones_in).\"\n}\nif ($num_phones_out != 48 && $num_phones_out != 39) {\n  die \"Can only used 48 or 39 for -to (used $num_phones_out).\"\n}\nunless ($num_phones_out < $num_phones_in) {\n  die \"Argument to -from ($num_phones_in) must be greater than that to -to ($num_phones_out).\"\n}\n\n\nopen(M, \"<$phone_map\") or die \"Cannot open mappings file '$phone_map': $!\";\nmy (%phonemap, %seen_phones);\nmy $num_seen_phones = 0;\nwhile (<M>) {\n  chomp;\n  next if ($_ =~ /^q\\s*.*$/); # Ignore glottal stops.\n  m:^(\\S+)\\s+(\\S+)\\s+(\\S+)$: or die \"Bad line: $_\";\n  my $mapped_from = ($num_phones_in == 60)? $1 : $2;\n  my $mapped_to = ($num_phones_out == 48)? $2 : $3;\n  if (!defined($seen_phones{$mapped_to})) {\n    $seen_phones{$mapped_to} = 1;\n    $num_seen_phones += 1;\n  }\n  $phonemap{$mapped_from} = $mapped_to;\n}\nif ($num_seen_phones != $num_phones_out) {\n  die \"Trying to map to $num_phones_out phones, but seen only $num_seen_phones\";\n}\n\nopen(T, \"<$in_trans\") or die \"Cannot open transcription file '$in_trans': $!\";\nwhile (<T>) {\n  chomp;\n  $_ =~ m:^(\\S+)\\s+(.+): or die \"Bad line: $_\";\n  my $utt_id = $1;\n  my $trans = $2;\n\n  $trans =~ s/q//g;  # Remove glottal stops.\n  $trans =~ s/^\\s*//; $trans =~ s/\\s*$//;  # Normalize spaces\n\n  print $utt_id;\n  for my $phone (split(/\\s+/, $trans)) {\n    if(exists $phonemap{$phone}) { print \" $phonemap{$phone}\"; }\n    if(not exists $phonemap{$phone}) { print \" $phone\"; }\n  }\n  print \"\\n\";\n}"
  },
  {
    "path": "examples/timit/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nif [ $# != 2 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_name=$2\n\nmkdir -p exp\n\n# seed may break model convergence\nseed=0\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\nfi\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0 ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/timit/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/timit/asr1/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh || exit 1;\n\ngpus=0,1,2,3\nstage=0\nstop_stage=50\nconf_path=conf/transformer.yaml\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=10\nTIMIT_path=~/datasets/timit/data/lisa/data/timit/raw/TIMIT\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/timit_data_prep.sh ${TIMIT_path}\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n"
  },
  {
    "path": "examples/tiny/.gitignore",
    "content": "ckpt*\ndata\n"
  },
  {
    "path": "examples/tiny/README.md",
    "content": "* asr0 - deepspeech2 Streaming/Non-Streaming\n* asr1 - transformer/conformer Streaming/Non-Streaming\n* asr2 - transformer/conformer Streaming/Non-Streaming with Kaldi feature\n"
  },
  {
    "path": "examples/tiny/asr0/.gitignore",
    "content": "data\nexp\n*log\n"
  },
  {
    "path": "examples/tiny/asr0/README.md",
    "content": "# DeepSpeech2 offline/online ASR with Tiny\nThis example contains code used to train a DeepSpeech2 offline or online model with Tiny dataset(a part of [[Librispeech dataset](http://www.openslr.org/resources/12)](http://www.openslr.org/resources/33))\n## Overview\nAll the scripts you need are in the `run.sh`. There are several stages in the `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Export the static graph model                                |\n\nYou can choose to run a range of stages by setting the `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in the `run.sh` in detail.\n\n## The environment variables\nThe path.sh contains the environment variable. \n```bash\nsource path.sh\n```\nThis script needs to be run first.  \n\nAnd another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n\n## The local variables\nSome local variables are set in the `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`,  it means you only use CPU. \n`stage` denotes the number of stages you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num` denotes the number K of top-K models you want to average to get the final model.\n`model_type`denotes the model type: offline or online\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"deepspeech2\"\n\nYou can set the local variables (except `ckpt`)  when you use the `run.sh`\n\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 1\n```\n## Stage 0: Data processing\nTo use this example, you need to process data firstly and you can use stage 0 in the `run.sh` to do this. The code is shown below:\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model training\nIf you want to train the model. you can use stage 1 in the ```run.sh```. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\n```\n## Stage 2:  Top-k Models Averaging\nAfter training the model,  we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model.  We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model,  you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}|| exit -1\n fi\n```\nIf you want to train a model and test it,  you can use the script below to execute stage 0, stage 1,  stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2\navg.sh best exp/deepspeech2/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_1\n```\n## Stage 4: Static graph model Export\nThis stage is to transform dygraph to static graph.\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # export ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type}\n fi\n```\nIf you already have a dynamic graph model, you can run this script:\n```bash\nsource path.sh\n./local/export.sh deepspeech2.yaml exp/deepspeech2/checkpoints/avg_1 exp/deepspeech2/checkpoints/avg_1.jit offline\n```\n"
  },
  {
    "path": "examples/tiny/asr0/conf/deepspeech2.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny \nmin_input_len: 0.0\nmax_input_len: 30.0\nmin_output_len: 0.0\nmax_output_len: 400.0\nmin_output_input_ratio: 0.05\nmax_output_input_ratio: 10.0\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n  \n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 3\nrnn_layer_size: 2048\nrnn_direction: bidirect # [forward, bidirect]\nnum_fc_layers: 0\nfc_layers_size_list: -1,\nuse_gru: False \nblank_id: 0\n  \n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 5\naccum_grad: 1\nlr: 1.0e-5 \nlr_decay: 0.8 \nweight_decay: 1.0e-6\nglobal_grad_clip: 5.0\ndist_sampler: False\nlog_interval: 1\ncheckpoint:\n  kbest_n: 3\n  latest_n: 2\n\n\n"
  },
  {
    "path": "examples/tiny/asr0/conf/deepspeech2_online.yaml",
    "content": "# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny \nmin_input_len: 0.0\nmax_input_len: 30.0\nmin_output_len: 0.0\nmax_output_len: 400.0\nmin_output_input_ratio: 0.05\nmax_output_input_ratio: 10.0\n\n\n###########################################\n#              Dataloader                 #\n###########################################\nvocab_filepath: data/lang_char/vocab.txt \nspm_model_prefix: ''\nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 161\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 8\nsubsampling_factor: 1\nnum_encs: 1\n \n############################################\n#           Network Architecture           #\n############################################\nnum_conv_layers: 2\nnum_rnn_layers: 4\nrnn_layer_size: 2048\nrnn_direction: forward\nnum_fc_layers: 2\nfc_layers_size_list: 512, 256\nuse_gru: True \nblank_id: 0\n  \n\n###########################################\n#                Training                 #\n###########################################\nn_epoch: 5\naccum_grad: 1\nlr: 1.0e-5 \nlr_decay: 1.0 \nweight_decay: 1.0e-6\nglobal_grad_clip: 5.0\ndist_sampler: False\nlog_interval: 1\ncheckpoint:\n  kbest_n: 3\n  latest_n: 2\n\n"
  },
  {
    "path": "examples/tiny/asr0/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 161\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n"
  },
  {
    "path": "examples/tiny/asr0/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: wer\ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/common_crawl_00.prune01111.trie.klm\nalpha: 2.5\nbeta: 0.3\nbeam_size: 500\ncutoff_prob: 1.0\ncutoff_top_n: 40\nnum_proc_bsearch: 8\n"
  },
  {
    "path": "examples/tiny/asr0/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 128\nerror_rate_type: wer\ndecoding_method: ctc_beam_search\nlang_model_path: data/lm/common_crawl_00.prune01111.trie.klm\nalpha: 2.5\nbeta: 0.3\nbeam_size: 500\ncutoff_prob: 1.0\ncutoff_top_n: 40\nnum_proc_bsearch: 8\n"
  },
  {
    "path": "examples/tiny/asr0/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\nunit_type=char\ndict_dir=data/lang_char\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"False\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n    \n    head -n 64 data/manifest.dev-clean  > data/manifest.tiny.raw\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.tiny.raw\" \\\n    --num_samples=64 \\\n    --spectrum_type=\"linear\" \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=20 \\\n    --use_dB_normalization=False \\\n    --num_workers=2 \\\n    --output_path=\"data/mean_std.json\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type ${unit_type} \\\n    --count_threshold=0 \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.tiny.raw\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    python3 ${MAIN_ROOT}/utils/format_data.py \\\n    --cmvn_path \"data/mean_std.json\" \\\n    --unit_type ${unit_type} \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_path=\"data/manifest.tiny.raw\" \\\n    --output_path=\"data/manifest.tiny\"\n    \n    \n    if [ $? -ne 0 ]; then\n        echo \"Formt mnaifest failed. Terminated.\"\n        exit 1\n    fi\nfi\n\necho \"LibriSpeech Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr0/local/download_lm_en.sh",
    "content": "#!/bin/bash\n\n. ${MAIN_ROOT}/utils/utility.sh\n\nDIR=data/lm\nmkdir -p ${DIR}\n\nURL=https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm\nMD5=\"099a601759d467cd0a8523ff939819c5\"\nTARGET=${DIR}/common_crawl_00.prune01111.trie.klm\n\necho \"Start downloading the language model. The language model is large, please wait for a moment ...\"\ndownload $URL $MD5 $TARGET > /dev/null 2>&1\nif [ $? -ne 0 ]; then\n    echo \"Fail to download the language model!\"\n    exit 1\nelse\n    echo \"Download the language model sucessfully\"\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr0/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr0/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\n# download language model\nbash local/download_lm_en.sh\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\npython3 -u ${BIN_DIR}/test.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${ckpt_prefix}.rsl \\\n--checkpoint_path ${ckpt_prefix}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in evaluation!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr0/local/train.sh",
    "content": "#!/bin/bash\n\nprofiler_options=\n\n# seed may break model convergence\nseed=0\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\n    echo \"using seed $seed & FLAGS_cudnn_deterministic=True ...\"\nfi\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--seed ${seed}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--seed ${seed}\nfi\n\nif [ ${seed} != 0  ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr0/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=deepspeech2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/tiny/asr0/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=4\nstage=0\nstop_stage=100\nconf_path=conf/deepspeech2.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=1\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}') ###ckpt = deepspeech2\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}|| exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n"
  },
  {
    "path": "examples/tiny/asr1/.gitignore",
    "content": "data\nexp\nlog\n"
  },
  {
    "path": "examples/tiny/asr1/README.md",
    "content": "# Transformer/Conformer ASR with Tiny\nThis example contains code used to train a [u2](https://arxiv.org/pdf/2012.05481.pdf) model (Transformer or [Conformer](https://arxiv.org/pdf/2005.08100.pdf) model) with Tiny dataset(a part of [[Librispeech dataset](http://www.openslr.org/resources/12)](http://www.openslr.org/resources/33))\n## Overview\nAll the scripts you need are in `run.sh`. There are several stages in `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the dataset <br>       (2) Calculate the CMVN of the train dataset <br>       (3) Get the vocabulary file <br>       (4) Get the manifest files of the train, development and test dataset<br>       (5) Get the sentencepiece model |\n| 1     | Train the model                                              |\n| 2     | Get the final model by averaging the top-k models, set k = 1 means to choose the best model |\n| 3     | Test the final model performance                             |\n| 4     | Get ctc alignment of test data using the final model         |\n\nYou can choose to run a range of stages by setting `stage` and `stop_stage`. \n\nFor example, if you want to execute the code in stage 2 and stage 3, you can run this script:\n```bash\nbash run.sh --stage 2 --stop_stage 3\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run ```stage 0```, you can use the script below:\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nThe document below will describe the scripts in ```run.sh```in detail.\n## The Environment Variables\nThe path.sh contains the environment variables. \n```bash\n. ./path.sh\n```\nThis script needs to be run first. And another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n## The Local Variables\nSome local variables are set in `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`, it means you only use CPU. \n`stage` denotes the number of stage you want the start from in the experiments.\n`stop stage` denotes the number of stage you want the stop at in the experiments. \n`conf_path` denotes the config path of the model.\n`avg_num`denotes the number K of top-K models you want to average to get the final model.\n`ckpt` denotes the checkpoint prefix of the model, e.g. \"transformerr\"\nYoutransformer local variables (except `ckpt`) when you use `run.sh`\nFor example, you can set the `gpus` and `avg_num` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 --avg_num 1\n```\n## Stage 0: Data Processing\nTo use this example, you need to process data firstly and you can use stage 0 in ```run.sh```to do this. The code is shown below:\n\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data.\n\nIf you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\n. ./path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the ``data`` directory will look like this:\n```bash\ndata/\n|-- dev.meta\n|-- lang_char\n|   `-- bpe_unigram_200.model\n|   `-- bpe_unigram_200.vocab\n|   `-- vocab.txt\n|-- manifest.dev\n|-- manifest.dev.raw\n|-- manifest.test\n|-- manifest.test.raw\n|-- manifest.train\n|-- manifest.train.raw\n|-- mean_std.json\n|-- test.meta\n`-- train.meta\n```\n## Stage 1: Model Training\nIf you want to train the model. you can use stage 1 in ```run.sh```. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\n```## Stage 2: Top-k Models Averaging\nAfter training the model, we need to get the final model for testing and inference. In every epoch, the model checkpoint is saved, so we can choose the best model from them based on the validation loss or we can sort them and average the parameters of the top-k models to get the final model. We can use stage 2 to do this, and the code is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # avg n best model\n     avg.sh best exp/${ckpt}/checkpoints ${avg_num}\n fi\n```\nThe `avg.sh` is in the `../../../utils/` which is define in the `path.sh`.\nIf you want to get the final model, you can use the script below to execute stage 0, stage 1, and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 1\n```\n## Stage 3: Model Testing\nThe test stage is to evaluate the model performance. The code of test stage is shown below:\n```bash\n if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train a model and test it, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 3\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 1\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer.yaml exp/transformer/checkpoints/avg_1\n```\n## Stage 4: CTC Alignment \nIf you want to get the alignment between the audio and the text, you can use the ctc alignment. The code of this stage is shown below:\n```bash\n if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n     # ctc alignment of test data\n     CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\n fi\n```\nIf you want to train the model, test it and do the alignment, you can use the script below to execute stage 0, stage 1, stage 2, and stage 3 :\n```bash\nbash run.sh --stage 0 --stop_stage 4\n```\nor if you only need to train a model and do the alignment, you can use these scripts to escape stage 3 (test stage):\n\n```bash\nbash run.sh --stage 0 --stop_stage 2\nbash run.sh --stage 4 --stop_stage 4\n```\nor you can also use these scripts in the command line (only use CPU).\n```bash\n. ./path.sh\nbash ./local/data.sh\nCUDA_VISIBLE_DEVICES= ./local/train.sh conf/transformer.yaml transformer\navg.sh best exp/transformer/checkpoints 1\n# test stage is optional\nCUDA_VISIBLE_DEVICES= ./local/test.sh conf/transformer.yaml exp/transformer/checkpoints/avg_1\nCUDA_VISIBLE_DEVICES= ./local/align.sh conf/transformer.yaml exp/transformer/checkpoints/avg_1\n```\n"
  },
  {
    "path": "examples/tiny/asr1/conf/augmentation.json",
    "content": "[\n  {\n    \"type\": \"speed\",\n    \"params\": {\n      \"min_speed_rate\": 0.9,\n      \"max_speed_rate\": 1.1,\n      \"num_rates\": 3\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"shift\",\n    \"params\": {\n      \"min_shift_ms\": -5,\n      \"max_shift_ms\": 5\n    },\n    \"prob\": 1.0\n  },\n  {\n    \"type\": \"specaug\",\n    \"params\": {\n      \"W\": 0,\n      \"warp_mode\": \"PIL\",\n      \"F\": 10,\n      \"n_freq_masks\": 2,\n      \"T\": 50,\n      \"n_time_masks\": 2,\n      \"p\": 1.0,\n      \"adaptive_number_ratio\": 0,\n      \"adaptive_size_ratio\": 0,\n      \"max_n_time_masks\": 20,\n      \"replace_with_zero\": true\n    },\n    \"prob\": 1.0\n  }\n]\n"
  },
  {
    "path": "examples/tiny/asr1/conf/chunk_confermer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \"data/mean_std.json\"\ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n    causal: True\n    use_dynamic_chunk: True\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny\n\n  \n###########################################\n#              Dataloader                 #\n###########################################\nmean_std_filepath: \"\"\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_200'\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\npreprocess_config: conf/preprocess.yaml \nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n  \n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 5\naccum_grad: 1\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 10\n  latest_n: 1\n"
  },
  {
    "path": "examples/tiny/asr1/conf/chunk_transformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \"data/mean_std.json\"\ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n    use_dynamic_chunk: true\n    use_dynamic_left_chunk: false\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny\n  \n###########################################\n#              Dataloader                 #\n###########################################\nmean_std_filepath: \"\"\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_200'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 5\naccum_grad: 1\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 10\n  latest_n: 1\n\n"
  },
  {
    "path": "examples/tiny/asr1/conf/conformer.yaml",
    "content": "# https://yaml.org/type/float.html\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \"data/mean_std.json\"\ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: 'swish'\n    pos_enc_layer_type: 'rel_pos'\n    selfattention_layer_type: 'rel_selfattn'\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny\n  \n\n###########################################\n#              Dataloader                 #\n###########################################\nmean_std_filepath: \"\"\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_200'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 5\naccum_grad: 4\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 10\n  latest_n: 1\n\n\n\n"
  },
  {
    "path": "examples/tiny/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 0.1\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n\n\n\n\n"
  },
  {
    "path": "examples/tiny/asr1/conf/transformer.yaml",
    "content": "# https://yaml.org/type/float.html\n############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: transformer\nencoder_conf:\n    output_size: 256    # dimension of attention\n    attention_heads: 4\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: true\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 4\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/manifest.tiny\ndev_manifest: data/manifest.tiny\ntest_manifest: data/manifest.tiny\n  \n###########################################\n#              Dataloader                 #\n###########################################\nmean_std_filepath: data/mean_std.json\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'spm'\nspm_model_prefix: 'data/lang_char/bpe_unigram_200'\npreprocess_config: conf/preprocess.yaml\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 4\nmaxlen_in: 512  # if input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 150  # if output length > maxlen-out, batchsize is automatically reduced\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 5\naccum_grad: 1\nglobal_grad_clip: 5.0\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-06\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 1\ncheckpoint:\n  kbest_n: 2\n  latest_n: 1\n\n\n\n"
  },
  {
    "path": "examples/tiny/asr1/conf/tuning/chunk_decode.yaml",
    "content": "decode_batch_size: 8 #64\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False."
  },
  {
    "path": "examples/tiny/asr1/conf/tuning/decode.yaml",
    "content": "decode_batch_size: 8 #64\nerror_rate_type: wer\ndecoding_method: attention  # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nbeam_size: 10\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\n"
  },
  {
    "path": "examples/tiny/asr1/local/align.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nbatch_size=1\noutput_dir=${ckpt_prefix}\nmkdir -p ${output_dir}\n\n# align dump in `result_file`\n# .tier, .TextGrid dump in `dir of result_file`\npython3 -u ${BIN_DIR}/alignment.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--decode_cfg ${decode_config_path} \\\n--result_file ${output_dir}/${type}.align \\\n--checkpoint_path ${ckpt_prefix} \\\n--opts decode.decode_batch_size ${batch_size}\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in ctc alignment!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr1/local/data.sh",
    "content": "#!/bin/bash\n\nstage=-1\nstop_stage=100\n\ndict_dir=data/lang_char\n\n# bpemode (unigram or bpe)\nnbpe=200\nbpemode=unigram\nbpeprefix=\"${dict_dir}/bpe_${bpemode}_${nbpe}\"\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nmkdir -p data\nmkdir -p ${dict_dir}\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data, generate manifests\n    python3 ${TARGET_DIR}/librispeech/librispeech.py \\\n    --manifest_prefix=\"data/manifest\" \\\n    --target_dir=\"${TARGET_DIR}/librispeech\" \\\n    --full_download=\"False\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Prepare LibriSpeech failed. Terminated.\"\n        exit 1\n    fi\n    \n    head -n 64 data/manifest.dev-clean  > data/manifest.tiny.raw\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # compute mean and stddev for normalizer\n    python3 ${MAIN_ROOT}/utils/compute_mean_std.py \\\n    --manifest_path=\"data/manifest.tiny.raw\" \\\n    --num_samples=64 \\\n    --spectrum_type=\"fbank\" \\\n    --feat_dim=80 \\\n    --delta_delta=false \\\n    --sample_rate=16000 \\\n    --stride_ms=10 \\\n    --window_ms=25 \\\n    --use_dB_normalization=False \\\n    --num_workers=2 \\\n    --output_path=\"data/mean_std.json\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Compute mean and stddev failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # build vocabulary\n    python3 ${MAIN_ROOT}/utils/build_vocab.py \\\n    --unit_type \"spm\" \\\n    --spm_vocab_size=${nbpe} \\\n    --spm_mode ${bpemode} \\\n    --spm_model_prefix ${bpeprefix} \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_paths=\"data/manifest.tiny.raw\"\n    \n    if [ $? -ne 0 ]; then\n        echo \"Build vocabulary failed. Terminated.\"\n        exit 1\n    fi\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # format manifest with tokenids, vocab size\n    python3 ${MAIN_ROOT}/utils/format_data.py \\\n    --cmvn_path \"data/mean_std.json\" \\\n    --unit_type \"spm\" \\\n    --spm_model_prefix ${bpeprefix} \\\n    --vocab_path=\"${dict_dir}/vocab.txt\" \\\n    --manifest_path=\"data/manifest.tiny.raw\" \\\n    --output_path=\"data/manifest.tiny\"\n    \n    \n    if [ $? -ne 0 ]; then\n        echo \"Formt mnaifest failed. Terminated.\"\n        exit 1\n    fi\nfi\n\necho \"LibriSpeech Data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr1/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_en.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in attention ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    if [ ${chunk_mode} == true ];then\n        # stream decoding only support batchsize=1\n        batch_size=1\n    else\n        batch_size=64\n    fi\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nfor type in ctc_prefix_beam_search attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${ckpt_prefix}.${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nprofiler_options=\nbenchmark_batch_size=0\nbenchmark_max_step=0\n\n# seed may break model convergence\nseed=0\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\n    echo \"using seed $seed & FLAGS_cudnn_deterministic=True ...\"\nfi\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\n\nmkdir -p exp\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nelse\npython3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nfi\n\n\nif [ ${seed} != 0  ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/tiny/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8 \nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/tiny/asr1/run.sh",
    "content": "#!/bin/bash\nset -e\nsource path.sh\n\ngpus=4\nstage=0\nstop_stage=50\nconf_path=conf/transformer.yaml\nips=            #xx.xx.xx.xx,xx.xx.xx.xx\ndecode_conf_path=conf/tuning/decode.yaml\navg_num=1\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus}  ./local/train.sh ${conf_path} ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 51 ] && [ ${stop_stage} -ge 51 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\n"
  },
  {
    "path": "examples/vctk/README.md",
    "content": "\n# VCTK\n\n* tts0 - Tacotron2\n* tts1 - TransformerTTS\n* tts2 - SpeedySpeech\n* tts3 - FastSpeech2\n* voc0 - WaveFlow\n* voc1 - Parallel WaveGAN\n* voc2 - MelGAN\n* voc3 - MultiBand MelGAN\n* ernie_sat - ERNIE-SAT\n* vc3 - StarGANv2-VC\n"
  },
  {
    "path": "examples/vctk/ernie_sat/README.md",
    "content": "# ERNIE-SAT with VCTK dataset\n[ERNIE-SAT](https://arxiv.org/abs/2211.03545) speech-text joint pretraining framework, which achieves SOTA results in cross-lingual multi-speaker speech synthesis and cross-lingual speech editing tasks, It can be applied to a series of scenarios such as Speech Editing, personalized Speech Synthesis, and Voice Cloning.\n\n## Model Framework\nIn ERNIE-SAT, we propose two innovations:\n- In the pretraining process, the phonemes corresponding to Chinese and English are used as input to achieve cross-language and personalized soft phoneme mapping\n- The joint mask learning of speech and text is used to realize the alignment of speech and text\n\n<p align=\"center\">\n    <img src=\"https://user-images.githubusercontent.com/24568452/186110814-1b9c6618-a0ab-4c0c-bb3d-3d860b0e8cc2.png\" />\n</p>\n\n## Dataset\n### Download and Extract the dataset\nDownload VCTK-0.92 from it's [Official Website](https://datashare.ed.ac.uk/handle/10283/3443) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/VCTK-Corpus-0.92`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for fastspeech2.\nYou can download from here [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\nps: we remove three speakers in VCTK-0.92 (see [reorganize_vctk.py](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/other/mfa/local/reorganize_vctk.py)):\n1. `p315`, because of no text for it.\n2. `p280` and `p362`, because no *_mic2.flac (which is better than *_mic1.flac) for  them.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/VCTK-Corpus-0.92`.\nAssume the path to the MFA result of VCTK is `./vctk_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, speaker, and id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n\n### Synthesizing\nWe use [HiFiGAN](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/voc5) as the neural vocoder.\n\nDownload pretrained HiFiGAN model from [hifigan_vctk_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip) and unzip it.\n```bash\nunzip hifigan_vctk_ckpt_0.2.0.zip\n```\nHiFiGAN checkpoint contains files listed below.\n```text\nhifigan_vctk_ckpt_0.2.0\n├── default.yaml                    # default config used to train HiFiGAN\n├── feats_stats.npy                 # statistics used to normalize spectrogram when training HiFiGAN\n└── snapshot_iter_2500000.pdz       # generator parameters of HiFiGAN\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n\n##  Speech Synthesis and Speech Editing\n\n### Prepare\n**prepare aligner**\n```bash\nmkdir -p tools/aligner\ncd tools\n# download MFA\nwget https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner/releases/download/v1.0.1/montreal-forced-aligner_linux.tar.gz\n# extract MFA\ntar xvf montreal-forced-aligner_linux.tar.gz\n# fix .so of MFA\ncd montreal-forced-aligner/lib\nln -snf libpython3.6m.so.1.0 libpython3.6m.so\ncd -\n# download align models and dicts\ncd aligner\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/aishell3_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/simple.lexicon\nwget https://paddlespeech.cdn.bcebos.com/MFA/ernie_sat/vctk_model.zip\nwget https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/cmudict-0.7b\ncd ../../\n```\n**prepare pretrained FastSpeech2 models**\n\nERNIE-SAT use FastSpeech2 as phoneme duration predictor:\n```bash\nmkdir download\ncd download\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_conformer_baker_ckpt_0.5.zip\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip\nunzip fastspeech2_conformer_baker_ckpt_0.5.zip\nunzip fastspeech2_nosil_ljspeech_ckpt_0.5.zip\ncd ../\n```\n**prepare source data**\n```bash\nmkdir source\ncd source\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540307.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/SSB03540428.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/LJ050-0278.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p243_313.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/p299_096.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/this_was_not_the_show_for_me.wav\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/source/README.md\ncd ../\n```\nYou can check the text of downloaded wavs in `source/README.md`.\n### Speech Synthesis and Speech Editing\n```bash\n./run.sh --stage 3 --stop-stage 3 --gpus 0\n```\n\nYou can modify `--wav_path`、`--old_str` and `--new_str` yourself, `--old_str` should be the text corresponding to the audio of  `--wav_path`, `--new_str` should be designed according to `--task_name`, both `--source_lang` and `--target_lang` should be `en` for model trained with VCTK dataset.\n## Pretrained Model\nPretrained ErnieSAT model:\n- [erniesat_vctk_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/ernie_sat/erniesat_vctk_ckpt_1.2.0.zip)\n\nModel | Step | eval/mlm_loss | eval/loss\n:-------------:| :------------:| :-----: | :-----:\ndefault| 8(gpu) x 199500|57.622215|57.622215\n"
  },
  {
    "path": "examples/vctk/ernie_sat/conf/default.yaml",
    "content": "# This configuration tested on 8 GPUs (A100) with 80GB GPU memory.\n# It takes around 2 days to finish the training,You can adjust\n# batch_size、num_workers here and ngpu in local/train.sh for your machine\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\nmean_phn_span: 8\nmlm_prob: 0.8\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 40\nnum_workers: 8\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    text_masking: false\n    postnet_layers: 5\n    postnet_filts: 5\n    postnet_chans: 256\n    encoder_type: conformer\n    decoder_type: conformer\n    enc_input_layer: sega_mlm\n    enc_pre_speech_layer: 0\n    enc_cnn_module_kernel: 7\n    enc_attention_dim: 384\n    enc_attention_heads: 2\n    enc_linear_units: 1536\n    enc_num_blocks: 4\n    enc_dropout_rate: 0.2\n    enc_positional_dropout_rate: 0.2\n    enc_attention_dropout_rate: 0.2\n    enc_normalize_before: true\n    enc_macaron_style: true\n    enc_use_cnn_module: true\n    enc_selfattention_layer_type: legacy_rel_selfattn\n    enc_activation_type: swish\n    enc_pos_enc_layer_type: legacy_rel_pos\n    enc_positionwise_layer_type: conv1d\n    enc_positionwise_conv_kernel_size: 3\n    dec_cnn_module_kernel: 31\n    dec_attention_dim: 384\n    dec_attention_heads: 2\n    dec_linear_units: 1536\n    dec_num_blocks: 4\n    dec_dropout_rate: 0.2\n    dec_positional_dropout_rate: 0.2\n    dec_attention_dropout_rate: 0.2\n    dec_macaron_style: true\n    dec_use_cnn_module: true\n    dec_selfattention_layer_type: legacy_rel_selfattn\n    dec_activation_type: swish\n    dec_pos_enc_layer_type: legacy_rel_pos\n    dec_positionwise_layer_type: conv1d\n    dec_positionwise_conv_kernel_size: 3\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\nscheduler_params:\n    d_model: 384\n    warmup_steps: 4000\ngrad_clip: 1.0\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 1500\nnum_snapshots: 50\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 0\n\ntoken_list:\n- <blank>\n- <unk>\n- AH0\n- T\n- N\n- sp\n- D\n- S\n- R\n- L\n- IH1\n- DH\n- AE1\n- M\n- EH1\n- K\n- Z\n- W\n- HH\n- ER0\n- AH1\n- IY1\n- P\n- V\n- F\n- B\n- AY1\n- IY0\n- EY1\n- AA1\n- AO1\n- UW1\n- IH0\n- OW1\n- NG\n- G\n- SH\n- ER1\n- Y\n- TH\n- AW1\n- CH\n- UH1\n- IH2\n- JH\n- OW0\n- EH2\n- OY1\n- AY2\n- EH0\n- EY2\n- UW0\n- AE2\n- AA2\n- OW2\n- AH2\n- ZH\n- AO2\n- IY2\n- AE0\n- UW2\n- AY0\n- AA0\n- AO0\n- AW2\n- EY0\n- UH2\n- ER2\n- OY2\n- UH0\n- AW0\n- OY0\n- <sos/eos>\n"
  },
  {
    "path": "examples/vctk/ernie_sat/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./vctk_alignment \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=vctk \\\n        --rootdir=~/datasets/VCTK-Corpus-0.92/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/vctk/ernie_sat/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# hifigan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize.py \\\n        --erniesat_config=${config_path} \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=hifigan_vctk_ckpt_0.2.0/default.yaml  \\\n        --voc_ckpt=hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt\nfi\n"
  },
  {
    "path": "examples/vctk/ernie_sat/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo 'speech synthesize !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=synthesize \\\n        --wav_path=source/p243_313.wav \\\n        --old_str='For that reason cover should not be given' \\\n        --new_str='I love you very much do you love me' \\\n        --source_lang=en \\\n        --target_lang=en \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=hifigan_vctk_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_gen.wav\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo 'speech edit !'\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/synthesize_e2e.py \\\n        --task_name=edit \\\n        --wav_path=source/p243_313.wav \\\n        --old_str='For that reason cover should not be given' \\\n        --new_str='For that reason cover is not impossible to be given' \\\n        --source_lang=en \\\n        --target_lang=en \\\n        --erniesat_config=${config_path} \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --erniesat_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --erniesat_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=hifigan_vctk_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --output_name=exp/pred_edit.wav\nfi\n"
  },
  {
    "path": "examples/vctk/ernie_sat/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1,2,3,4,5,6,7\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_199500.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is hifigan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize, run both speech synthesize and speech edit\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/README.md",
    "content": "# FastSpeech2 with the VCTK\nThis example contains code used to train a [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [VCTK](https://datashare.ed.ac.uk/handle/10283/3443).\n\n## Dataset\n### Download and Extract the dataset\nDownload VCTK-0.92 from it's [Official Website](https://datashare.ed.ac.uk/handle/10283/3443) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/VCTK-Corpus-0.92`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for fastspeech2.\nYou can download from here [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\nps: we remove three speakers in VCTK-0.92 (see [reorganize_vctk.py](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/other/mfa/local/reorganize_vctk.py)):\n1. `p315`, because of no text for it.\n2. `p280` and `p362`, because no *_mic2.flac (which is better than *_mic1.flac) for  them.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/VCTK-Corpus-0.92`.\nAssume the path to the MFA result of VCTK is `./vctk_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech、pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, the path of energy features, speaker, and id of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--phones-dict` is the path of the phone vocabulary file.\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/vctk/voc1) as the neural vocoder.\n\nDownload pretrained parallel wavegan model from [pwg_vctk_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_vctk_ckpt_0.1.1.zip) and unzip it.\n```bash\nunzip pwg_vctk_ckpt_0.1.1.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_vctk_ckpt_0.1.1\n├── default.yaml                   # default config used to train parallel wavegan\n├── snapshot_iter_1500000.pdz      # generator parameters of parallel wavegan\n└── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0\n```\nThe last number controls the vocoder model during synthesis, which can be `0` or `1`, use `pwgan` or `hifigan` model as vocoder.\n\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat`, `--phones_dict` `--speaker_dict` are arguments for acoustic model, which correspond to the 5 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_vctk_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_ckpt_1.2.0.zip)\n\nThe static model can be downloaded here:\n- [fastspeech2_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_static_1.1.0.zip)\n\nThe PIR static model can be downloaded here:\n - [fastspeech2_vctk_static_pir_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_static_pir_1.1.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [fastspeech2_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [fastspeech2_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_pdlite_1.3.0.zip)\n\nFastSpeech2 checkpoint contains files listed below.\n```text\nfastspeech2_vctk_ckpt_1.2.0\n├── default.yaml            # default config used to train fastspeech2\n├── energy_stats.npy        # statistics used to normalize energy when training fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── pitch_stats.npy         # statistics used to normalize pitch when training fastspeech2\n├── snapshot_iter_66200.pdz # model parameters and optimizer states\n├── speaker_id_map.txt      # speaker id map file when training a multi-speaker fastspeech2\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences.txt` using pretrained fastspeech2 and parallel wavegan models.\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_vctk \\\n  --am_config=fastspeech2_vctk_ckpt_1.2.0/default.yaml \\\n  --am_ckpt=fastspeech2_vctk_ckpt_1.2.0/snapshot_iter_66200.pdz \\\n  --am_stat=fastspeech2_vctk_ckpt_1.2.0/speech_stats.npy \\\n  --voc=pwgan_vctk \\\n  --voc_config=pwg_vctk_ckpt_0.1.1/default.yaml  \\\n  --voc_ckpt=pwg_vctk_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n  --voc_stat=pwg_vctk_ckpt_0.1.1/feats_stats.npy \\\n  --lang=en \\\n  --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --phones_dict=fastspeech2_vctk_ckpt_1.2.0/phone_id_map.txt \\\n  --speaker_dict=fastspeech2_vctk_ckpt_1.2.0/speaker_id_map.txt \\\n  --spk_id=0 \\\n  --inference_dir=exp/default/inference\n```\n"
  },
  {
    "path": "examples/vctk/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length.(in samples) 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam               # optimizer type\n    learning_rate: 0.001      # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/vctk/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_vctk \\\n        --voc=pwgan_vctk \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --lang=en\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_vctk \\\n        --voc=hifigan_vctk \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/local/lite_predict.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_vctk \\\n        --voc=pwgan_vctk \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --lang=en\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../lite_predict.py \\\n        --inference_dir=${train_output_path}/pdlite \\\n        --am=fastspeech2_vctk \\\n        --voc=hifigan_vctk \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/lite_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_vctk \\\n        --voc=pwgan_vctk \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --spk_id=0 \\\n        --lang=en\n\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_vctk \\\n        --voc=hifigan_vctk \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=2 \\\n        --spk_id=0 \\\n        --lang=en\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./vctk_alignment \\\n        --output durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=vctk \\\n        --rootdir=~/datasets/VCTK-Corpus-0.92/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize and covert phone/speaker to id, dev and test should use train's stats\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_vctk \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_vctk \\\n        --voc_config=pwg_vctk_ckpt_0.1.1/default.yaml  \\\n        --voc_ckpt=pwg_vctk_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=pwg_vctk_ckpt_0.1.1/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_vctk \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=hifigan_vctk_ckpt_0.2.0/default.yaml  \\\n        --voc_ckpt=hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=${4:-0}\nstop_stage=${4:-0}\n\n# pwgan\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_vctk \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_vctk \\\n        --voc_config=pwg_vctk_ckpt_0.1.1/default.yaml  \\\n        --voc_ckpt=pwg_vctk_ckpt_0.1.1/snapshot_iter_1500000.pdz \\\n        --voc_stat=pwg_vctk_ckpt_0.1.1/feats_stats.npy \\\n        --lang=en \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# hifigan\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_vctk \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_vctk \\\n        --voc_config=hifigan_vctk_ckpt_0.2.0/default.yaml  \\\n        --voc_ckpt=hifigan_vctk_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_vctk_ckpt_0.2.0/feats_stats.npy \\\n        --lang=en \\\n        --text=${BIN_DIR}/../../assets/sentences_en.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=0 \\\n        --inference_dir=${train_output_path}/inference\nfi\n"
  },
  {
    "path": "examples/vctk/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_331.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by 0, use 1 will use hifigan as vocoder\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} 0 || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_vctk\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_vctk\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_vctk\n    \nfi\n\n# inference with onnxruntime, use fastspeech2 + pwgan by default\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n\n# must run after stage 3 (which stage generated static models)\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    ./local/export2lite.sh ${train_output_path} inference pdlite fastspeech2_vctk x86\n    ./local/export2lite.sh ${train_output_path} inference pdlite pwgan_vctk x86\n    # ./local/export2lite.sh ${train_output_path} inference pdlite hifigan_vctk x86\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/lite_predict.sh ${train_output_path} || exit -1\nfi"
  },
  {
    "path": "examples/vctk/vc3/README.md",
    "content": "You can download test source audios from [test_wav.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/starganv2vc/test_wav.zip).\n\n\nTest Voice Conversion:\n\n```bash\nwget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/starganv2vc/test_wav.zip\nunzip test_wav.zip\n./run.sh --stage 2 --stop-stage 2 --gpus 0\n```\n"
  },
  {
    "path": "examples/vctk/vc3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n# 源码 load 的时候用的 24k, 提取 mel 用的 16k, 后续 load 和提取 mel 都要改成 24k\nfs: 16000\nn_fft: 2048\nn_shift: 300\nwin_length: 1200   # Window length.(in samples) 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\nfmin: 0           # Minimum frequency of Mel basis.\nfmax: 8000        # Maximum frequency of Mel basis.  sr // 2\nn_mels: 80\n# only for StarGANv2 VC\nnorm:             # None here\nhtk: True\npower: 2.0\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\ngenerator_params:\n    dim_in: 64\n    style_dim: 64\n    max_conv_dim: 512\n    w_hpf: 0\n    F0_channel: 256\nmapping_network_params:\n    num_domains: 20      # num of speakers in StarGANv2\n    latent_dim: 16\n    style_dim: 64        # same as style_dim in generator_params\n    hidden_dim: 512      # same as max_conv_dim in generator_params\nstyle_encoder_params:\n    dim_in: 64           # same as dim_in in generator_params\n    style_dim: 64        # same as style_dim in generator_params\n    num_domains: 20      # same as num_domains in generator_params\n    max_conv_dim: 512    # same as max_conv_dim in generator_params\ndiscriminator_params:\n    dim_in: 64           # same as dim_in in generator_params\n    num_domains: 20      # same as num_domains in mapping_network_params\n    max_conv_dim: 512    # same as max_conv_dim in generator_params\n    repeat_num: 4\nasr_params:\n    input_dim: 80\n    hidden_dim: 256\n    n_token: 80\n    token_embedding_dim: 256\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nloss_params:\n    g_loss:\n        lambda_sty: 1.\n        lambda_cyc: 5.\n        lambda_ds: 1.\n        lambda_norm: 1.\n        lambda_asr: 10.\n        lambda_f0: 5.\n        lambda_f0_sty: 0.1\n        lambda_adv: 2.\n        lambda_adv_cls: 0.5\n        norm_bias: 0.5\n    d_loss:\n        lambda_reg: 1.\n        lambda_adv_cls: 0.1\n        lambda_con_reg: 10.\n\n    adv_cls_epoch: 50\n    con_reg_epoch: 30\n        \n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 5               # Batch size.\nnum_workers: 2              # Number of workers in DataLoader.\nmax_mel_length: 192\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.0\n    beta2: 0.99\n    weight_decay: 1.0e-4                   \n    epsilon: 1.0e-9\ngenerator_scheduler_params:\n    max_learning_rate: 2.0e-4\n    phase_pct: 0.0\n    divide_factor: 1\n    total_steps: 200000                # train_max_steps\n    end_learning_rate: 2.0e-4\nstyle_encoder_optimizer_params:\n    beta1: 0.0\n    beta2: 0.99\n    weight_decay: 1.0e-4                 \n    epsilon: 1.0e-9\nstyle_encoder_scheduler_params:\n    max_learning_rate: 2.0e-4\n    phase_pct: 0.0\n    divide_factor: 1\n    total_steps: 200000                # train_max_steps\n    end_learning_rate: 2.0e-4\nmapping_network_optimizer_params:\n    beta1: 0.0\n    beta2: 0.99\n    weight_decay: 1.0e-4                 \n    epsilon: 1.0e-9\nmapping_network_scheduler_params:\n    max_learning_rate: 2.0e-6\n    phase_pct: 0.0\n    divide_factor: 1\n    total_steps: 200000                # train_max_steps\n    end_learning_rate: 2.0e-6\ndiscriminator_optimizer_params:\n    beta1: 0.0\n    beta2: 0.99\n    weight_decay: 1.0e-4                 \n    epsilon: 1.0e-9\ndiscriminator_scheduler_params:\n    max_learning_rate: 2.0e-4\n    phase_pct: 0.0\n    divide_factor: 1\n    total_steps: 200000                # train_max_steps\n    end_learning_rate: 2.0e-4        \n\n###########################################################\n#                    TRAINING SETTING                     #\n###########################################################\nmax_epoch: 150\nnum_snapshots: 5\nseed: 1"
  },
  {
    "path": "examples/vctk/vc3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=vctk \\\n        --rootdir=~/datasets/VCTK-Corpus-0.92/ \\\n        --dumpdir=dump \\\n        --config=${config_path} \\\n        --num-cpu=20\n\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\necho \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speaker-dict=dump/speaker_id_map.txt\n\nfi\n"
  },
  {
    "path": "examples/vctk/vc3/local/train.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\n\npython3 ${BIN_DIR}/train.py \\\n    --train-metadata=dump/train/norm/metadata.jsonl \\\n    --dev-metadata=dump/dev/norm/metadata.jsonl \\\n    --config=${config_path} \\\n    --output-dir=${train_output_path} \\\n    --ngpu=1 \\\n    --speaker-dict=dump/speaker_id_map.txt\n"
  },
  {
    "path": "examples/vctk/vc3/local/voice_conversion.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\nsource_path=$2\noutput_dir=$3\n\npython3 ${BIN_DIR}/vc.py \\\n    --config_path=${config_path} \\\n    --source_path=${source_path}\\\n    --output_dir=${output_dir} "
  },
  {
    "path": "examples/vctk/vc3/path.sh",
    "content": "#!/bin/bash\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nMODEL=starganv2_vc\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/t2s/exps/${MODEL}\n"
  },
  {
    "path": "examples/vctk/vc3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_331.pdz\nsource_path=test_wav/goat_01.wav\noutput_dir=vc_output\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\n# not ready now\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n# not ready now\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/voice_conversion.sh ${conf_path} ${source_path} ${output_dir}|| exit -1\nfi\n\n"
  },
  {
    "path": "examples/vctk/voc1/README.md",
    "content": "# Parallel WaveGAN with VCTK\nThis example contains code used to train a [parallel wavegan](http://arxiv.org/abs/1910.11480) model with [VCTK](https://datashare.ed.ac.uk/handle/10283/3443).\n\n## Dataset\n### Download and Extract\nDownload VCTK-0.92 from it's [Official Website](https://datashare.ed.ac.uk/handle/10283/3443) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/VCTK-Corpus-0.92`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\nps: we remove three speakers in VCTK-0.92 (see [reorganize_vctk.py](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/other/mfa/local/reorganize_vctk.py)):\n1. `p315`, because of no text for it.\n2. `p280` and `p362`, because no *_mic2.flac (which is better than *_mic1.flac) for  them.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/VCTK-Corpus-0.92`.\nAssume the path to the MFA result of VCTK is `./vctk_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER]\n                [--run-benchmark RUN_BENCHMARK]\n                [--profiler_options PROFILER_OPTIONS]\n\nTrain a ParallelWaveGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       ParallelWaveGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n\nbenchmark:\n  arguments related to benchmark.\n\n  --batch-size BATCH_SIZE\n                        batch size.\n  --max-iter MAX_ITER   train max steps.\n  --run-benchmark RUN_BENCHMARK\n                        runing benchmark or not, if True, use the --batch-size\n                        and --max-iter.\n  --profiler_options PROFILER_OPTIONS\n                        The option of profiler, which should be in format\n                        \"key1=value1;key2=value2;key3=value3\".\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` parallel wavegan config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory. If you use the pretrained model, use the `pwg_snapshot_iter_400000.pdz`.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nPretrained models can be downloaded here:\n- [pwg_vctk_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_vctk_ckpt_0.1.1.zip)\n\nThe static model can be downloaded here:\n- [pwgan_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_static_1.1.0.zip)\n\nThe ONNX model can be downloaded here:\n- [pwgan_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [pwgan_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_pdlite_1.3.0.zip)\n\n\nParallel WaveGAN checkpoint contains files listed below.\n\n```text\npwg_vctk_ckpt_0.1.1\n├── default.yaml                   # default config used to train parallel wavegan\n├── snapshot_iter_1500000.pdz      # generator parameters of parallel wavegan\n└── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n```\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/vctk/voc1/conf/default.yaml",
    "content": "# This is the hyperparameter configuration file for Parallel WaveGAN.\n# Please make sure this is adjusted for the VCTK corpus. If you want to\n# apply to the other dataset, you might need to carefully change some parameters.\n# This configuration requires 12 GB GPU memory and takes ~3 days on RTX TITAN.\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Kernel size of dilated convolution.\n    layers: 30            # Number of residual block layers.\n    stacks: 3             # Number of stacks i.e., dilation cycles.\n    residual_channels: 64 # Number of channels in residual conv.\n    gate_channels: 128    # Number of channels in gated conv.\n    skip_channels: 64     # Number of channels in skip conv.\n    aux_channels: 80      # Number of channels for auxiliary feature conv.\n                          # Must be the same as num_mels.\n    aux_context_window: 2 # Context window size for auxiliary feature.\n                          # If set to 2, previous 2 and future 2 frames will be considered.\n    dropout: 0.0          # Dropout rate. 0.0 means no dropout applied.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    upsample_scales: [4, 5, 3, 5]     # Upsampling scales. prod(upsample_scales) == n_shift\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    in_channels: 1        # Number of input channels.\n    out_channels: 1       # Number of output channels.\n    kernel_size: 3        # Number of output channels.\n    layers: 10            # Number of conv layers.\n    conv_channels: 64     # Number of chnn layers.\n    bias: True            # Whether to use bias parameter in conv.\n    use_weight_norm: True # Whether to use weight norm.\n                          # If set to true, it will be applied to all of the conv layers.\n    nonlinear_activation: \"leakyrelu\" # Nonlinear function after each conv.\n    nonlinear_activation_params:      # Nonlinear function parameters\n        negative_slope: 0.2           # Alpha in leakyrelu.\n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nstft_loss_params:\n    fft_sizes: [1024, 2048, 512]  # List of FFT size for STFT-based loss.\n    hop_sizes: [120, 240, 50]     # List of hop size for STFT-based loss\n    win_lengths: [600, 1200, 240] # List of window length for STFT-based loss.\n    window: \"hann\"                # Window function for STFT-based loss\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_adv: 4.0  # Loss balancing coefficient.\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 6              # Batch size.\nbatch_max_steps: 24000     # Length of each audio in batch. Make sure dividable by n_shift.\nnum_workers: 2             # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    epsilon: 1.0e-6            # Generator's epsilon.\n    weight_decay: 0.0      # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 0.0001             # Generator's learning rate.\n    step_size: 200000      # Generator's scheduler step size.\n    gamma: 0.5             # Generator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ngenerator_grad_norm: 10    # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    epsilon: 1.0e-6            # Discriminator's epsilon.\n    weight_decay: 0.0      # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 0.00005            # Discriminator's learning rate. \n    step_size: 200000      # Discriminator's scheduler step size.\n    gamma: 0.5             # Discriminator's scheduler gamma.\n                           # At each step size, lr will be multiplied by this parameter.\ndiscriminator_grad_norm: 1 # Discriminator's gradient norm.\n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ndiscriminator_train_start_steps: 100000 # Number of steps to start to train discriminator.\ntrain_max_steps: 1500000                # Number of training steps.\nsave_interval_steps: 5000               # Interval steps to save checkpoint.\neval_interval_steps: 1000               # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_save_intermediate_results: 4  # Number of results to be saved as intermediate results.\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/vctk/voc1/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # get durations from MFA's result\n    echo \"Generate durations.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=./vctk_alignment \\\n        --output=durations.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # extract features\n    echo \"Extract features ...\"\n    python3 ${BIN_DIR}/../preprocess.py \\\n        --rootdir=~/datasets/VCTK-Corpus-0.92/ \\\n        --dataset=vctk \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --cut-sil=True \\\n        --num-cpu=20\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # get features' stats(mean and std)\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"feats\"\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # normalize, dev and test should use train's stats\n    echo \"Normalize ...\"\n   \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n\n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\n    \n    python3 ${BIN_DIR}/../normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --stats=dump/train/feats_stats.npy \\\n        --skip-wav-copy\nfi\n"
  },
  {
    "path": "examples/vctk/voc1/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/vctk/voc5/README.md",
    "content": "# HiFiGAN with VCTK\nThis example contains code used to train a [HiFiGAN](https://arxiv.org/abs/2010.05646) model with [VCTK](https://datashare.ed.ac.uk/handle/10283/3443).\n\n## Dataset\n### Download and Extract\nDownload VCTK-0.92 from it's [Official Website](https://datashare.ed.ac.uk/handle/10283/3443) and extract it to `~/datasets`. Then the dataset is in the directory `~/datasets/VCTK-Corpus-0.92`.\n\n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) results to cut the silence in the edge of audio.\nYou can download from here [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz), or train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) of our repo.\nps: we remove three speakers in VCTK-0.92 (see [reorganize_vctk.py](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/examples/other/mfa/local/reorganize_vctk.py)):\n1. `p315`, because of no text for it.\n2. `p280` and `p362`, because no *_mic2.flac (which is better than *_mic1.flac) for  them.\n\n## Get Started\nAssume the path to the dataset is `~/datasets/VCTK-Corpus-0.92`.\nAssume the path to the MFA result of VCTK is `./vctk_alignment`.\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n```bash\n./run.sh\n```\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── norm\n    ├── raw\n    └── feats_stats.npy\n```\n\nThe dataset is split into 3 parts, namely `train`, `dev`, and `test`, each of which contains a `norm` and `raw` subfolder. The `raw` folder contains the log magnitude of the mel spectrogram of each utterance, while the norm folder contains the normalized spectrogram. The statistics used to normalize the spectrogram are computed from the training set, which is located in `dump/train/feats_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains id and paths to the spectrogram of each utterance.\n\n### Model Training\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\nHere's the complete help message.\n\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU]\n\nTrain a HiFiGAN model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       HiFiGAN config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n### Synthesizing\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG]\n                     [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA]\n                     [--output-dir OUTPUT_DIR] [--ngpu NGPU]\n\nSynthesize with GANVocoder.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --generator-type GENERATOR_TYPE\n                        type of GANVocoder, should in {pwgan, mb_melgan,\n                        style_melgan, } now\n  --config CONFIG       GANVocoder config file.\n  --checkpoint CHECKPOINT\n                        snapshot to load.\n  --test-metadata TEST_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n```\n\n\n1. `--config` config file. You should use the same config with which the model is trained.\n2. `--checkpoint` is the checkpoint to load. Pick one of the checkpoints from `checkpoints` inside the training output directory.\n3. `--test-metadata` is the metadata of the test dataset. Use the `metadata.jsonl` in the `dev/norm` subfolder from the processed directory.\n4. `--output-dir` is the directory to save the synthesized audio files.\n5. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n## Pretrained Model\nThe pretrained model can be downloaded here:\n- [hifigan_vctk_ckpt_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip)\n\nThe static model can be downloaded here:\n- [hifigan_vctk_static_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_static_1.1.0.zip)\n\nThe PIR static model can be downloaded here:\n- [hifigan_vctk_static_pir_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_static_pir_1.1.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [hifigan_vctk_onnx_1.1.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_onnx_1.1.0.zip)\n\nThe Paddle-Lite model can be downloaded here:\n- [hifigan_vctk_pdlite_1.3.0.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_pdlite_1.3.0.zip)\n\n\nModel | Step | eval/generator_loss | eval/mel_loss| eval/feature_matching_loss\n:-------------:| :------------:| :-----: | :-----: | :--------:\ndefault| 1(gpu) x 2500000|58.092|0.1234|24.384\n\nHiFiGAN checkpoint contains files listed below.\n\n```text\nhifigan_vctk_ckpt_0.2.0\n├── default.yaml                  # default config used to train hifigan\n├── feats_stats.npy               # statistics used to normalize spectrogram when training hifigan\n└── snapshot_iter_2500000.pdz     # generator parameters of hifigan\n```\n\n## Acknowledgement\nWe adapted some code from https://github.com/kan-bayashi/ParallelWaveGAN.\n"
  },
  {
    "path": "examples/vctk/voc5/conf/default.yaml",
    "content": "# This is the configuration file for VCTK dataset.\n# This configuration is based on HiFiGAN V1, which is\n# an official configuration. But I found that the optimizer\n# setting does not work well with my implementation.\n# So I changed optimizer settings as follows:\n# - AdamW -> Adam\n# - betas: [0.8, 0.99] -> betas: [0.5, 0.9]\n# - Scheduler: ExponentialLR -> MultiStepLR\n# To match the shift size difference, the upsample scales\n# is also modified from the original 256 shift setting.\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\nfs: 24000                # Sampling rate.\nn_fft: 2048              # FFT size (samples).\nn_shift: 300             # Hop size (samples). 12.5ms\nwin_length: 1200         # Window length (samples). 50ms\n                         # If set to null, it will be the same as fft_size.\nwindow: \"hann\"           # Window function.\nn_mels: 80               # Number of mel basis.\nfmin: 80                 # Minimum freq in mel basis calculation. (Hz)\nfmax: 7600               # Maximum frequency in mel basis calculation. (Hz)\n\n###########################################################\n#         GENERATOR NETWORK ARCHITECTURE SETTING          #\n###########################################################\ngenerator_params:\n    in_channels: 80                       # Number of input channels.\n    out_channels: 1                       # Number of output channels.\n    channels: 512                         # Number of initial channels.\n    kernel_size: 7                        # Kernel size of initial and final conv layers.\n    upsample_scales: [5, 5, 4, 3]         # Upsampling scales.\n    upsample_kernel_sizes: [10, 10, 8, 6] # Kernel size for upsampling layers.\n    resblock_kernel_sizes: [3, 7, 11]     # Kernel size for residual blocks.\n    resblock_dilations:                   # Dilations for residual blocks.\n        - [1, 3, 5]\n        - [1, 3, 5]\n        - [1, 3, 5]\n    use_additional_convs: True            # Whether to use additional conv layer in residual blocks.\n    bias: True                            # Whether to use bias parameter in conv.\n    nonlinear_activation: \"leakyrelu\"     # Nonlinear activation type.\n    nonlinear_activation_params:          # Nonlinear activation parameters.\n        negative_slope: 0.1\n    use_weight_norm: True                 # Whether to apply weight normalization.\n\n\n###########################################################\n#       DISCRIMINATOR NETWORK ARCHITECTURE SETTING        #\n###########################################################\ndiscriminator_params:\n    scales: 3                              # Number of multi-scale discriminator.\n    scale_downsample_pooling: \"AvgPool1D\"  # Pooling operation for scale discriminator.\n    scale_downsample_pooling_params:\n        kernel_size: 4                     # Pooling kernel size.\n        stride: 2                          # Pooling stride.\n        padding: 2                         # Padding size.\n    scale_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [15, 41, 5, 3]       # List of kernel sizes.\n        channels: 128                      # Initial number of channels.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        max_groups: 16                     # Maximum number of groups in downsampling conv layers.\n        bias: True\n        downsample_scales: [4, 4, 4, 4, 1] # Downsampling scales.\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:\n            negative_slope: 0.1\n    follow_official_norm: True             # Whether to follow the official norm setting.\n    periods: [2, 3, 5, 7, 11]              # List of period for multi-period discriminator.\n    period_discriminator_params:\n        in_channels: 1                     # Number of input channels.\n        out_channels: 1                    # Number of output channels.\n        kernel_sizes: [5, 3]               # List of kernel sizes.\n        channels: 32                       # Initial number of channels.\n        downsample_scales: [3, 3, 3, 3, 1] # Downsampling scales.\n        max_downsample_channels: 1024      # Maximum number of channels in downsampling conv layers.\n        bias: True                         # Whether to use bias parameter in conv layer.\"\n        nonlinear_activation: \"leakyrelu\"  # Nonlinear activation.\n        nonlinear_activation_params:       # Nonlinear activation parameters.\n            negative_slope: 0.1\n        use_weight_norm: True              # Whether to apply weight normalization.\n        use_spectral_norm: False           # Whether to apply spectral normalization.\n    \n\n###########################################################\n#                   STFT LOSS SETTING                     #\n###########################################################\nuse_stft_loss: False                 # Whether to use multi-resolution STFT loss.\nuse_mel_loss: True                   # Whether to use Mel-spectrogram loss.\nmel_loss_params:\n    fs: 24000\n    fft_size: 2048\n    hop_size: 300\n    win_length: 1200\n    window: \"hann\"\n    num_mels: 80\n    fmin: 0\n    fmax: 12000\n    log_base: null\ngenerator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\ndiscriminator_adv_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\nuse_feat_match_loss: True\nfeat_match_loss_params:\n    average_by_discriminators: False # Whether to average loss by #discriminators.\n    average_by_layers: False         # Whether to average loss by #layers in each discriminator.\n    include_final_outputs: False     # Whether to include final outputs in feat match loss calculation.\n\n###########################################################\n#               ADVERSARIAL LOSS SETTING                  #\n###########################################################\nlambda_aux: 45.0       # Loss balancing coefficient for STFT loss.\nlambda_adv: 1.0        # Loss balancing coefficient for adversarial loss.\nlambda_feat_match: 2.0 # Loss balancing coefficient for feat match loss..\n\n###########################################################\n#                  DATA LOADER SETTING                    #\n###########################################################\nbatch_size: 16              # Batch size.\nbatch_max_steps: 8400       # Length of each audio in batch. Make sure dividable by hop_size.\nnum_workers: 2              # Number of workers in DataLoader.\n\n###########################################################\n#             OPTIMIZER & SCHEDULER SETTING               #\n###########################################################\ngenerator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Generator's weight decay coefficient.\ngenerator_scheduler_params:\n    learning_rate: 2.0e-4               # Generator's learning rate.\n    gamma: 0.5                          # Generator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000\ngenerator_grad_norm: -1                 # Generator's gradient norm.\ndiscriminator_optimizer_params:\n    beta1: 0.5\n    beta2: 0.9\n    weight_decay: 0.0                   # Discriminator's weight decay coefficient.\ndiscriminator_scheduler_params:\n    learning_rate: 2.0e-4               # Discriminator's learning rate.\n    gamma: 0.5                          # Discriminator's scheduler gamma.\n    milestones:                         # At each milestone, lr will be multiplied by gamma.\n        - 200000\n        - 400000\n        - 600000\n        - 800000    \ndiscriminator_grad_norm: -1             # Discriminator's gradient norm.            \n\n###########################################################\n#                    INTERVAL SETTING                     #\n###########################################################\ngenerator_train_start_steps: 1     # Number of steps to start to train discriminator.\ndiscriminator_train_start_steps: 0 # Number of steps to start to train discriminator.\ntrain_max_steps: 2500000           # Number of training steps.\nsave_interval_steps: 5000         # Interval steps to save checkpoint.\neval_interval_steps: 1000          # Interval steps to evaluate the network.\n\n###########################################################\n#                     OTHER SETTING                       #\n###########################################################\nnum_snapshots: 10                 # max number of snapshots to keep while training\nseed: 42                          # random seed for paddle, random, and np.random\n"
  },
  {
    "path": "examples/vctk/voc5/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0\nstage=0\nstop_stage=100\n\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_5000.pdz\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n"
  },
  {
    "path": "examples/voxceleb/README.md",
    "content": "\ndataset info refer to [VoxCeleb](https://www.robots.ox.ac.uk/~vgg/data/voxceleb/index.html#about)\n\nsv0 - speaker verfication with softmax backend etc, all python code\n      more info refer to the sv0/readme.txt\n\nsv1 - dependence on kaldi, speaker verfication with plda/sc backend, \n      more info refer to the sv1/readme.txt\n\n\n## VoxCeleb2 preparation\n\nVoxCeleb2 audio files are released in m4a format. All the VoxCeleb2 m4a audio files must be converted in wav files before feeding them in PaddleSpeech. \nPlease, follow these steps to prepare the dataset correctly:\n\n1. Download Voxceleb2.\nYou can find download instructions here: http://www.robots.ox.ac.uk/~vgg/data/voxceleb/\n\n2. Convert .m4a to wav\nVoxCeleb2 stores files with the m4a audio format. To use them in PaddleSpeech,  you have to convert all the m4a audio files into wav files.\n\n``` shell\nffmpeg -y -i %s -ac 1 -vn -acodec pcm_s16le -ar 16000 %s\n```\n\nYou can do the conversion using ffmpeg  https://gist.github.com/seungwonpark/4f273739beef2691cd53b5c39629d830). This operation might take several hours and should be only once.\n\n3. Put all the wav files in a folder called `wav`. You should have something like `voxceleb2/wav/id*/*.wav` (e.g, `voxceleb2/wav/id00012/21Uxsk56VDQ/00001.wav`)\n\n\n## voxceleb dataset summary\n\n\n|dataset | vox1 - dev | vox1 - test |vox2 - dev| vox2 - test|\n|---------|-----------|------------|-----------|----------|\n|spks    |  1211       |40     |      5994        | 118|\n|utts     | 148642    | 4874   | 1092009     |36273|\n| time(h) | 340.4 | 11.2  | 2360.2  |79.9 |\n\n\n## trial summary\n\n| trial     | filename |  nums | positive | negative |\n|--------|-----------|--------|-------|------|\n| VoxCeleb1 | veri_test.txt | 37720 | 18860 | 18860 | \n| VoxCeleb1(cleaned) | veri_test2.txt | 37611 | 18802 | 18809 |\n| VoxCeleb1-H | list_test_hard.txt | 552536 | 276270 | 276266 |\n|VoxCeleb1-H(cleaned) |list_test_hard2.txt | 550894 | 275488 | 275406 |\n|VoxCeleb1-E | list_test_all.txt | 581480 | 290743 | 290737 | \n|VoxCeleb1-E(cleaned) | list_test_all2.txt |579818 |289921 |289897 |\n"
  },
  {
    "path": "examples/voxceleb/sv0/README.md",
    "content": "# ECAPA-TDNN with VoxCeleb\nThis example contains code used to train a ECAPA-TDNN model with [VoxCeleb dataset](https://www.robots.ox.ac.uk/~vgg/data/voxceleb/index.html#about)\n\n## Overview\nAll the scripts you need are in the `run.sh`. There are several stages in the `run.sh`, and each stage has its function.\n| Stage | Function                                                     |\n|:---- |:----------------------------------------------------------- |\n| 0     | Process data. It includes: <br>       (1) Download the VoxCeleb1 dataset <br>       (2) Download the VoxCeleb2 dataset  <br>       (3) Convert the VoxCeleb2 m4a to wav format <br>       (4) Get the manifest files of the train, development and test dataset <br> (5) Download the RIR Noise dataset and Get the noise manifest files for augmentation |\n| 1     | Train the model                                              |\n| 2     | Test the speaker verification with VoxCeleb trial|\n\nYou can choose to run a range of stages by setting the `stage` and `stop_stage `. \n\nFor example, if you want to execute the code in stage 1 and stage 2, you can run this script:\n```bash\nbash run.sh --stage 1 --stop_stage 2\n```\nOr you can set `stage` equal to `stop-stage` to only run one stage.\nFor example, if you only want to run `stage 0`, you can use the script below:\n```bash\nbash run.sh --stage 1 --stop_stage 1\n```\nThe document below will describe the scripts in the `run.sh` in detail.\n## The environment variables\nThe path.sh contains the environment variable. \n```bash\nsource path.sh\n```\nThis script needs to be run first.  \n\nAnd another script is also needed:\n```bash\nsource ${MAIN_ROOT}/utils/parse_options.sh\n```\nIt will support the way of using `--variable value` in the shell scripts.\n\n## The local variables\nSome local variables are set in the `run.sh`. \n`gpus` denotes the GPU number you want to use. If you set `gpus=`,  it means you only use CPU. \n`stage` denotes the number of the stage you want to start from in the experiments.\n`stop stage` denotes the number of the stage you want to end at in the experiments. \n`conf_path` denotes the config path of the model.\n`exp_dir` denotes the experiment directory, e.g. \"exp/ecapa-tdnn-vox12-big/\"\n\nYou can set the local variables when you use the `run.sh`\n\nFor example, you can set the `gpus` when you use the command line.:\n```bash\nbash run.sh --gpus 0,1 \n```\n## Stage 0: Data processing\nTo use this example, you need to process data firstly and you can use stage 0 in the `run.sh` to do this. The code is shown below:\n\n```bash\n if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n     # prepare data\n     bash ./local/data.sh || exit -1\n fi\n```\nStage 0 is for processing the data. If you only want to process the data. You can run\n```bash\nbash run.sh --stage 0 --stop_stage 0\n```\nYou can also just run these scripts in your command line.\n```bash\nsource path.sh\nbash ./local/data.sh\n```\nAfter processing the data, the `data` directory will look like this:\n```bash\ndata/\n├── rir_noise\n│   ├── csv\n│   │   ├── noise.csv\n│   │   └── rir.csv\n│   ├── manifest.pointsource_noises\n│   ├── manifest.real_rirs_isotropic_noises\n│   └── manifest.simulated_rirs\n├── vox\n│   ├── csv\n│   │   ├── dev.csv\n│   │   ├── enroll.csv\n│   │   ├── test.csv\n│   │   └── train.csv\n│   └── meta\n│       └── label2id.txt\n└── vox1\n    ├── list_test_all2.txt\n    ├── list_test_all.txt\n    ├── list_test_hard2.txt\n    ├── list_test_hard.txt\n    ├── manifest.dev\n    ├── manifest.test\n    ├── veri_test2.txt\n    ├── veri_test.txt\n    ├── voxceleb1.dev.meta\n    └── voxceleb1.test.meta\n```\n## Stage 1: Model training\nIf you want to train the model. you can use stage 1 in the `run.sh`. The code is shown below. \n```bash\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # train model, all `ckpt` under `exp` dir\n     CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt}\n fi\n```\nIf you want to train the model, you can use the script below to execute stage 0 and stage 1:\n```bash\nbash run.sh --stage 0 --stop_stage 1\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh ./data/ conf/ecapa_tdnn.yaml\nCUDA_VISIBLE_DEVICES= ./local/train.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml\n```\n## Stage 2: Model Testing\nThe test stage is to evaluate the model performance. The code of the test stage is shown below:\n```bash\n if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # test ckpt avg_n\n     CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${dir} ${exp_dir} ${conf_path} || exit -1\n fi\n```\nIf you want to train a model and test it,  you can use the script below to execute stage 0, stage 1 and stage 2:\n```bash\nbash run.sh --stage 0 --stop_stage 2\n```\nor you can run these scripts in the command line (only use CPU).\n```bash\nsource path.sh\nbash ./local/data.sh ./data/ conf/ecapa_tdnn.yaml\nCUDA_VISIBLE_DEVICES= ./local/train.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml\nCUDA_VISIBLE_DEVICES= ./local/test.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml\n```\n\n## 3: Pretrained Model\nYou can get the pretrained models from [this](../../../docs/source/released_model.md).\n\nusing the `tar` scripts to unpack the model and then you can use the script to test the model.\n\nFor example:\n```\nwget https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz\ntar -xvf sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz\nsource path.sh\n# If you have processed the data and get the manifest file， you can skip the following 2 steps\n\nCUDA_VISIBLE_DEVICES= bash ./local/test.sh ./data sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1/model/ conf/ecapa_tdnn.yaml\n```\nThe performance of the released models are shown in [this](./RESULT.md)\n"
  },
  {
    "path": "examples/voxceleb/sv0/RESULT.md",
    "content": "# VoxCeleb\n\n## ECAPA-TDNN \n\n| Model | Number of Params | Release | Config | dim | Test set |  Cosine | Cosine + S-Norm | \n| --- | --- | --- | --- | --- | --- | --- | ---- |\n| ECAPA-TDNN | 85M | 0.2.1 | conf/ecapa_tdnn.yaml | 192 | test | 0.8188 | 0.7815|\n\n> [SpeechBrain result](https://github.com/speechbrain/speechbrain/tree/develop/recipes/VoxCeleb/SpeakerRec#speaker-verification-using-ecapa-tdnn-embeddings):  \n> EER = 0.90% (voxceleb1 + voxceleb2) without s-norm  \n> EER = 0.80% (voxceleb1 + voxceleb2) with s-norm.  \n"
  },
  {
    "path": "examples/voxceleb/sv0/conf/ecapa_tdnn.yaml",
    "content": "###########################################\n#                Data                 #\n###########################################\naugment: True\nbatch_size: 32\nnum_workers: 2\nnum_speakers: 7205 # 1211 vox1, 5994 vox2, 7205 vox1+2, test speakers: 41\nshuffle: True\nskip_prep: False\nsplit_ratio: 0.9\nchunk_duration: 3.0 # seconds\nrandom_chunk: True\nverification_file: data/vox1/veri_test2.txt\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n# currently, we only support fbank\nsr: 16000           # sample rate\nn_mels: 80\nwindow_size: 400     #25ms, sample rate 16000, 25 * 16000 / 1000 = 400 \nhop_size: 160        #10ms, sample rate 16000, 10 * 16000 / 1000 = 160\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\n# currently, we only support ecapa-tdnn in the ecapa_tdnn.yaml\n# if we want use another model, please choose another configuration yaml file\nmodel:\n  input_size: 80\n  channels: [1024, 1024, 1024, 1024, 3072]\n  kernel_sizes: [5, 3, 3, 3, 1]\n  dilations: [1, 2, 3, 4, 1]\n  attention_channels: 128\n  lin_neurons: 192\n\n###########################################\n#                Training                 #\n###########################################\nseed: 1986 # according from speechbrain configuration\nepochs: 10\nsave_interval: 10\nlog_interval: 10\nlearning_rate: 1e-8\nmax_lr: 1e-3\nstep_size: 140000\n\n\n###########################################\n#                loss                     #\n###########################################\nmargin: 0.2\nscale: 30\n\n###########################################\n#                Testing                  #\n###########################################\nglobal_embedding_norm: True\nembedding_mean_norm: True\nembedding_std_norm: False\n\n###########################################\n#                score-norm               #\n###########################################\nscore_norm: s-norm\ncohort_size: 20000 # amount of imposter utterances in normalization cohort\nn_train_snts: 400000 # used for normalization stats\n\n\n"
  },
  {
    "path": "examples/voxceleb/sv0/conf/ecapa_tdnn_small.yaml",
    "content": "###########################################\n#                Data                 #\n###########################################\naugment: True\nbatch_size: 32\nnum_workers: 2\nnum_speakers: 1211 # 1211 vox1, 5994 vox2, 7205 vox1+2, test speakers: 41\nshuffle: True\nskip_prep: False\nsplit_ratio: 0.9\nchunk_duration: 3.0 # seconds\nrandom_chunk: True\nverification_file: data/vox1/veri_test2.txt\n\n###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n# currently, we only support fbank\nsr: 16000           # sample rate\nn_mels: 80\nwindow_size: 400     #25ms, sample rate 16000, 25 * 16000 / 1000 = 400 \nhop_size: 160        #10ms, sample rate 16000, 10 * 16000 / 1000 = 160\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\n# currently, we only support ecapa-tdnn in the ecapa_tdnn.yaml\n# if we want use another model, please choose another configuration yaml file\nmodel:\n  input_size: 80\n  channels: [512, 512, 512, 512, 1536]\n  kernel_sizes: [5, 3, 3, 3, 1]\n  dilations: [1, 2, 3, 4, 1]\n  attention_channels: 128\n  lin_neurons: 192\n\n###########################################\n#                Training                 #\n###########################################\nseed: 1986 # according from speechbrain configuration\nepochs: 100\nsave_interval: 10\nlog_interval: 10\nlearning_rate: 1e-8\nmax_lr: 1e-3\nstep_size: 140000\n\n###########################################\n#                loss                     #\n###########################################\nmargin: 0.2\nscale: 30\n\n###########################################\n#                Testing                  #\n###########################################\nglobal_embedding_norm: True\nembedding_mean_norm: True\nembedding_std_norm: False\n\n###########################################\n#                score-norm               #\n###########################################\nscore_norm: s-norm\ncohort_size: 20000 # amount of imposter utterances in normalization cohort\nn_train_snts: 400000 # used for normalization stats\n\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/convert.sh",
    "content": "# copy this to root directory of data and \n# chmod a+x convert.sh\n# ./convert.sh\n# https://unix.stackexchange.com/questions/103920/parallelize-a-bash-for-loop\ndir=$1\nopen_sem(){\n    mkfifo pipe-$$\n    exec 3<>pipe-$$\n    rm pipe-$$\n    local i=$1\n    for((;i>0;i--)); do\n        printf %s 000 >&3\n    done\n}\nrun_with_lock(){\n    local x\n    read -u 3 -n 3 x && ((0==x)) || exit $x\n    (\n     ( \"$@\"; )\n    printf '%.3d' $? >&3\n    )&\n}\nN=32 # number of vCPU\nopen_sem $N\nfor f in $(find ${dir} -name \"*.m4a\"); do\n    run_with_lock ffmpeg -loglevel panic -i \"$f\" -ar 16000 \"${f%.*}.wav\"\ndone\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/data.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nstage=0\nstop_stage=100\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nif [ $# -ne 2 ] ; then\n   echo \"Usage: $0 [options] <data-dir> <conf-path>\";\n   echo \"e.g.: $0 ./data/ conf/ecapa_tdnn.yaml\"\n   echo \"Options: \"\n   echo \"  --stage <stage|-1>               # Used to run a partially-completed data process from somewhere in the middle.\"\n   echo \"  --stop-stage <stop-stage|100>    # Used to run a partially-completed data process stop stage in the middle\"\n   exit 1;\nfi\n\ndir=$1\nconf_path=$2\nmkdir -p ${dir}\n\n# Generally the `MAIN_ROOT` refers to the root of PaddleSpeech,\n# which is defined in the path.sh\n# And we will download the voxceleb data and rirs noise to ${MAIN_ROOT}/dataset\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n   # download data, generate manifests\n   # we will generate the manifest.{dev,test} file from ${TARGET_DIR}/voxceleb/vox1/{dev,test} directory\n   # and generate the meta info and download the trial file\n   # manifest.dev: 148642\n   # manifest.test: 4847\n   echo \"Start to download vox1 dataset and generate the manifest files \"\n   python3 ${TARGET_DIR}/voxceleb/voxceleb1.py \\\n      --manifest_prefix=\"${dir}/vox1/manifest\" \\\n      --target_dir=\"${TARGET_DIR}/voxceleb/vox1/\"\n\n   if [ $? -ne 0 ]; then\n      echo \"Prepare voxceleb1 failed. Terminated.\"\n      exit 1\n   fi\n\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n   # download voxceleb2 data\n   # we will download the data and unzip the package\n   # and we will store the m4a file in ${TARGET_DIR}/voxceleb/vox2/{dev,test}\n   echo \"start to download vox2 dataset\"\n   python3 ${TARGET_DIR}/voxceleb/voxceleb2.py \\\n      --download \\\n      --target_dir=\"${TARGET_DIR}/voxceleb/vox2/\"\n\n   if [ $? -ne 0 ]; then\n      echo \"Download voxceleb2 dataset failed. Terminated.\"\n      exit 1\n   fi\n\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n   # convert the m4a to wav\n   # and we will not delete the original m4a file\n   echo \"start to convert the m4a to wav\"\n   bash local/convert.sh ${TARGET_DIR}/voxceleb/vox2/ || exit 1;\n   \n   if [ $? -ne 0 ]; then\n      echo \"Convert voxceleb2 dataset from m4a to wav failed. Terminated.\"\n      exit 1\n   fi\n   echo \"m4a convert to wav operation finished\"\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n   # generate the vox2 manifest file from wav file\n   # we will generate the ${dir}/vox2/manifest.vox2\n   # because we use all the vox2 dataset to train, so collect all the vox2 data in one file\n   echo \"start generate the vox2 manifest files\"\n   python3 ${TARGET_DIR}/voxceleb/voxceleb2.py \\\n      --generate \\\n      --manifest_prefix=\"${dir}/vox2/manifest\" \\\n      --target_dir=\"${TARGET_DIR}/voxceleb/vox2/\"\n\n   if [ $? -ne 0 ]; then\n      echo \"Prepare voxceleb2 dataset failed. Terminated.\"\n      exit 1\n   fi\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n   # generate the vox csv file\n   # Currently, our training system use csv file for dataset\n   echo \"convert the json format to csv format to be compatible with training process\"\n   python3 local/make_vox_csv_dataset_from_json.py\\\n      --train \"${dir}/vox1/manifest.dev\" \"${dir}/vox2/manifest.vox2\"\\\n      --test \"${dir}/vox1/manifest.test\" \\\n      --target_dir \"${dir}/vox/\" \\\n      --config ${conf_path}\n\n   if [ $? -ne 0 ]; then\n      echo \"Prepare voxceleb failed. Terminated.\"\n      exit 1\n   fi\nfi\n\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n   # generate the open rir noise manifest file\n   echo \"generate the open rir noise manifest file\"\n   python3 ${TARGET_DIR}/rir_noise/rir_noise.py\\\n      --manifest_prefix=\"${dir}/rir_noise/manifest\" \\\n      --target_dir=\"${TARGET_DIR}/rir_noise/\"\n\n   if [ $? -ne 0 ]; then\n      echo \"Prepare rir_noise failed. Terminated.\"\n      exit 1\n   fi\nfi\n\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n   # generate the open rir noise manifest file\n   echo \"generate the open rir noise csv file\"\n   python3 local/make_rirs_noise_csv_dataset_from_json.py \\\n      --noise_dir=\"${TARGET_DIR}/rir_noise/\" \\\n      --data_dir=\"${dir}/rir_noise/\" \\\n      --config ${conf_path}\n\n   if [ $? -ne 0 ]; then\n      echo \"Prepare rir_noise failed. Terminated.\"\n      exit 1\n   fi\nfi\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/data_prepare.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport paddle\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.datasets.voxceleb import VoxCeleb\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.io.augment import build_augment_pipeline\nfrom paddlespeech.vector.training.seeding import seed_everything\n\nlogger = Log(__name__).getlog()\n\n\ndef main(args, config):\n\n    # stage0: set the cpu device, all data prepare process will be done in cpu mode\n    paddle.set_device(\"cpu\")\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    # stage 1: generate the voxceleb csv file\n    # Note: this may occurs c++ exception, but the program will execute fine\n    # so we ignore the exception \n    # we explicitly pass the vox2 base path to data prepare and generate the audio info\n    logger.info(\"start to generate the voxceleb dataset info\")\n    train_dataset = VoxCeleb(\n        'train', target_dir=args.data_dir, vox2_base_path=config.vox2_base_path)\n\n    # stage 2: generate the augment noise csv file\n    if config.augment:\n        logger.info(\"start to generate the augment dataset info\")\n        augment_pipeline = build_augment_pipeline(target_dir=args.data_dir)\n\n\nif __name__ == \"__main__\":\n    # yapf: disable\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\"--data-dir\",\n                        default=\"./data/\",\n                        type=str,\n                        help=\"data directory\")\n    parser.add_argument(\"--config\",\n                        default=None,\n                        type=str,\n                        help=\"configuration file\")\n    args = parser.parse_args()\n    # yapf: enable\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n    print(config)\n\n    main(args, config)\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/emb.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n. ./path.sh\n\nstage=0\nstop_stage=100\nexp_dir=exp/ecapa-tdnn-vox12-big/            # experiment directory\nconf_path=conf/ecapa_tdnn.yaml\naudio_path=\"demo/voxceleb/00001.wav\"\nuse_gpu=true\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nif [ $# -ne 0 ] ; then\n   echo \"Usage: $0 [options]\";\n   echo \"e.g.: $0 ./data/ exp/voxceleb12/ conf/ecapa_tdnn.yaml\"\n   echo \"Options: \"\n   echo \"  --use-gpu <true,false|true>      # specify is gpu is to be used for training\"\n   echo \"  --stage <stage|-1>               # Used to run a partially-completed data process from somewhere in the middle.\"\n   echo \"  --stop-stage <stop-stage|100>    # Used to run a partially-completed data process stop stage in the middle\"\n   echo \"  --exp-dir                        # experiment directorh, where is has the model.pdparams\"\n   echo \"  --conf-path                      # configuration file for extracting the embedding\"\n   echo \"  --audio-path                     # audio-path, which will be processed to extract the embedding\"\n   exit 1;\nfi\n\n# set the test device\ndevice=\"cpu\"\nif ${use_gpu}; then\n    device=\"gpu\"\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # extract the audio embedding\n    python3 ${BIN_DIR}/extract_emb.py --device ${device} \\\n            --config ${conf_path} \\\n            --audio-path ${audio_path} --load-checkpoint ${exp_dir}\nfi"
  },
  {
    "path": "examples/voxceleb/sv0/local/make_rirs_noise_csv_dataset_from_json.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nConvert the PaddleSpeech jsonline format data to csv format data in voxceleb experiment.\nCurrently, Speaker Identificaton Training process use csv format.\n\"\"\"\nimport argparse\nimport csv\nimport os\nfrom typing import List\n\nimport tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.utils.vector_utils import get_chunks\n\nlogger = Log(__name__).getlog()\n\n\ndef get_chunks_list(wav_file: str,\n                    split_chunks: bool,\n                    base_path: str,\n                    chunk_duration: float=3.0) -> List[List[str]]:\n    \"\"\"Get the single audio file info \n\n    Args:\n        wav_file (list): the wav audio file and get this audio segment info list\n        split_chunks (bool): audio split flag\n        base_path (str): the audio base path \n        chunk_duration (float): the chunk duration. \n                                if set the split_chunks, we split the audio into multi-chunks segment.\n    \"\"\"\n    waveform, sr = load_audio(wav_file)\n    audio_id = wav_file.split(\"/rir_noise/\")[-1].split(\".\")[0]\n    audio_duration = waveform.shape[0] / sr\n\n    ret = []\n    if split_chunks and audio_duration > chunk_duration:  # Split into pieces of self.chunk_duration seconds.\n        uniq_chunks_list = get_chunks(chunk_duration, audio_id, audio_duration)\n\n        for idx, chunk in enumerate(uniq_chunks_list):\n            s, e = chunk.split(\"_\")[-2:]  # Timestamps of start and end\n            start_sample = int(float(s) * sr)\n            end_sample = int(float(e) * sr)\n\n            # currently, all vector csv data format use one representation\n            # id, duration, wav, start, stop, label\n            # in rirs noise, all the label name is 'noise'\n            # the label is string type and we will convert it to integer type in training\n            ret.append([\n                chunk, audio_duration, wav_file, start_sample, end_sample,\n                \"noise\"\n            ])\n    else:  # Keep whole audio.\n        ret.append(\n            [audio_id, audio_duration, wav_file, 0, waveform.shape[0], \"noise\"])\n    return ret\n\n\ndef generate_csv(wav_files,\n                 output_file: str,\n                 base_path: str,\n                 split_chunks: bool=True):\n    \"\"\"Prepare the csv file according the wav files\n\n    Args:\n        wav_files (list): all the audio list to prepare the csv file\n        output_file (str): the output csv file\n        config (CfgNode): yaml configuration content\n        split_chunks (bool): audio split flag\n    \"\"\"\n    logger.info(f'Generating csv: {output_file}')\n    header = [\"utt_id\", \"duration\", \"wav\", \"start\", \"stop\", \"label\"]\n    csv_lines = []\n    for item in tqdm.tqdm(wav_files):\n        csv_lines.extend(\n            get_chunks_list(\n                item, base_path=base_path, split_chunks=split_chunks))\n\n    if not os.path.exists(os.path.dirname(output_file)):\n        os.makedirs(os.path.dirname(output_file))\n\n    with open(output_file, mode=\"w\") as csv_f:\n        csv_writer = csv.writer(\n            csv_f, delimiter=\",\", quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n        csv_writer.writerow(header)\n        for line in csv_lines:\n            csv_writer.writerow(line)\n\n\ndef prepare_data(args, config):\n    \"\"\"Convert the jsonline format to csv format\n\n    Args:\n        args (argparse.Namespace): scripts args\n        config (CfgNode): yaml configuration content\n    \"\"\"\n    # if external config set the skip_prep flat, we will do nothing\n    if config.skip_prep:\n        return\n\n    base_path = args.noise_dir\n    wav_path = os.path.join(base_path, \"RIRS_NOISES\")\n    logger.info(f\"base path: {base_path}\")\n    logger.info(f\"wav path: {wav_path}\")\n    rir_list = os.path.join(wav_path, \"real_rirs_isotropic_noises\", \"rir_list\")\n    rir_files = []\n    with open(rir_list, 'r') as f:\n        for line in f.readlines():\n            rir_file = line.strip().split(' ')[-1]\n            rir_files.append(os.path.join(base_path, rir_file))\n\n    noise_list = os.path.join(wav_path, \"pointsource_noises\", \"noise_list\")\n    noise_files = []\n    with open(noise_list, 'r') as f:\n        for line in f.readlines():\n            noise_file = line.strip().split(' ')[-1]\n            noise_files.append(os.path.join(base_path, noise_file))\n\n    csv_path = os.path.join(args.data_dir, 'csv')\n    logger.info(f\"csv path: {csv_path}\")\n    generate_csv(\n        rir_files, os.path.join(csv_path, 'rir.csv'), base_path=base_path)\n    generate_csv(\n        noise_files, os.path.join(csv_path, 'noise.csv'), base_path=base_path)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        \"--noise_dir\",\n        default=None,\n        required=True,\n        help=\"The noise dataset dataset directory.\")\n    parser.add_argument(\n        \"--data_dir\",\n        default=None,\n        required=True,\n        help=\"The target directory stores the csv files\")\n    parser.add_argument(\n        \"--config\",\n        default=None,\n        required=True,\n        type=str,\n        help=\"configuration file\")\n    args = parser.parse_args()\n\n    # parse the yaml config file\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    # prepare the csv file from jsonlines files\n    prepare_data(args, config)\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/make_vox_csv_dataset_from_json.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nConvert the PaddleSpeech jsonline format data to csv format data in voxceleb experiment.\nCurrently, Speaker Identificaton Training process use csv format.\n\"\"\"\nimport argparse\nimport csv\nimport json\nimport os\nimport random\n\nimport tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.utils.vector_utils import get_chunks\n\nlogger = Log(__name__).getlog()\n\n\ndef prepare_csv(wav_files, output_file, config, split_chunks=True):\n    \"\"\"Prepare the csv file according the wav files\n\n    Args:\n        wav_files (list): all the audio list to prepare the csv file\n        output_file (str): the output csv file\n        config (CfgNode): yaml configuration content\n        split_chunks (bool, optional): audio split flag. Defaults to True.\n    \"\"\"\n    if not os.path.exists(os.path.dirname(output_file)):\n        os.makedirs(os.path.dirname(output_file))\n    csv_lines = []\n    header = [\"utt_id\", \"duration\", \"wav\", \"start\", \"stop\", \"label\"]\n    # voxceleb meta info for each training utterance segment\n    # we extract a segment from a utterance to train \n    # and the segment' period is between start and stop time point in the original wav file\n    # each field in the meta info means as follows:\n    # utt_id: the utterance segment name, which is uniq in training dataset\n    # duration: the total utterance time\n    # wav: utterance file path, which should be absoulute path\n    # start: start point in the original wav file sample point range\n    # stop: stop point in the original wav file sample point range\n    # label: the utterance segment's label name, \n    #        which is speaker name in speaker verification domain\n    for item in tqdm.tqdm(wav_files, total=len(wav_files)):\n        item = json.loads(item.strip())\n        audio_id = item['utt'].replace(\".wav\",\n                                       \"\")  # we remove the wav suffix name\n        audio_duration = item['feat_shape'][0]\n        wav_file = item['feat']\n        label = audio_id.split('-')[\n            0]  # speaker name in speaker verification domain\n        waveform, sr = load_audio(wav_file)\n        if split_chunks:\n            uniq_chunks_list = get_chunks(config.chunk_duration, audio_id,\n                                          audio_duration)\n            for chunk in uniq_chunks_list:\n                s, e = chunk.split(\"_\")[-2:]  # Timestamps of start and end\n                start_sample = int(float(s) * sr)\n                end_sample = int(float(e) * sr)\n                # id, duration, wav, start, stop, label\n                # in vector, the label in speaker id\n                csv_lines.append([\n                    chunk, audio_duration, wav_file, start_sample, end_sample,\n                    label\n                ])\n        else:\n            csv_lines.append([\n                audio_id, audio_duration, wav_file, 0, waveform.shape[0], label\n            ])\n\n    with open(output_file, mode=\"w\") as csv_f:\n        csv_writer = csv.writer(\n            csv_f, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n        csv_writer.writerow(header)\n        for line in csv_lines:\n            csv_writer.writerow(line)\n\n\ndef get_enroll_test_list(dataset_list, verification_file):\n    \"\"\"Get the enroll and test utterance list from all the voxceleb1 test utterance dataset.\n       Generally, we get the enroll and test utterances from the verfification file.\n       The verification file format as follows:\n       target/nontarget enroll-utt test-utt,\n       we set 0 as nontarget and 1 as target, eg:\n       0 a.wav b.wav\n       1 a.wav a.wav\n\n    Args:\n        dataset_list (list): all the dataset to get the test utterances\n        verification_file (str): voxceleb1 trial file\n    \"\"\"\n    logger.info(f\"verification file: {verification_file}\")\n    enroll_audios = set()\n    test_audios = set()\n    with open(verification_file, 'r') as f:\n        for line in f:\n            _, enroll_file, test_file = line.strip().split(' ')\n            enroll_audios.add('-'.join(enroll_file.split('/')))\n            test_audios.add('-'.join(test_file.split('/')))\n\n    enroll_files = []\n    test_files = []\n    for dataset in dataset_list:\n        with open(dataset, 'r') as f:\n            for line in f:\n                # audio_id may be in enroll and test at the same time\n                # eg: 1 a.wav a.wav\n                # the audio a.wav is enroll and test file at the same time\n                audio_id = json.loads(line.strip())['utt']\n                if audio_id in enroll_audios:\n                    enroll_files.append(line)\n                if audio_id in test_audios:\n                    test_files.append(line)\n\n    enroll_files = sorted(enroll_files)\n    test_files = sorted(test_files)\n\n    return enroll_files, test_files\n\n\ndef get_train_dev_list(dataset_list, target_dir, split_ratio):\n    \"\"\"Get the train and dev utterance list from all the training utterance dataset.\n       Generally, we use the split_ratio as the train dataset ratio,\n       and the remaining utterance (ratio is 1 - split_ratio) is the dev dataset\n\n    Args:\n        dataset_list (list): all the dataset to get the all utterances\n        target_dir (str): the target train and dev directory, \n                          we will create the csv directory to store the {train,dev}.csv file\n        split_ratio (float): train dataset ratio in all utterance list\n    \"\"\"\n    logger.info(\"start to get train and dev utt list\")\n    if not os.path.exists(os.path.join(target_dir, \"meta\")):\n        os.makedirs(os.path.join(target_dir, \"meta\"))\n\n    audio_files = []\n    speakers = set()\n    for dataset in dataset_list:\n        with open(dataset, 'r') as f:\n            for line in f:\n                # the label is speaker name\n                label_name = json.loads(line.strip())['utt2spk']\n                speakers.add(label_name)\n                audio_files.append(line.strip())\n    speakers = sorted(speakers)\n    logger.info(f\"we get {len(speakers)} speakers from all the train dataset\")\n\n    with open(os.path.join(target_dir, \"meta\", \"label2id.txt\"), 'w') as f:\n        for label_id, label_name in enumerate(speakers):\n            f.write(f'{label_name} {label_id}\\n')\n    logger.info(\n        f'we store the speakers to {os.path.join(target_dir, \"meta\", \"label2id.txt\")}'\n    )\n\n    # the split_ratio is for train dataset \n    # the remaining is for dev dataset\n    split_idx = int(split_ratio * len(audio_files))\n    audio_files = sorted(audio_files)\n    random.shuffle(audio_files)\n    train_files, dev_files = audio_files[:split_idx], audio_files[split_idx:]\n    logger.info(\n        f\"we get train utterances: {len(train_files)}, dev utterance: {len(dev_files)}\"\n    )\n    return train_files, dev_files\n\n\ndef prepare_data(args, config):\n    \"\"\"Convert the jsonline format to csv format\n\n    Args:\n        args (argparse.Namespace): scripts args\n        config (CfgNode): yaml configuration content\n    \"\"\"\n    # stage0: set the random seed\n    random.seed(config.seed)\n\n    # if external config set the skip_prep flat, we will do nothing\n    if config.skip_prep:\n        return\n\n    # stage 1: prepare the enroll and test csv file\n    #          And we generate the speaker to label file label2id.txt\n    logger.info(\"start to prepare the data csv file\")\n    enroll_files, test_files = get_enroll_test_list(\n        [args.test], verification_file=config.verification_file)\n    prepare_csv(\n        enroll_files,\n        os.path.join(args.target_dir, \"csv\", \"enroll.csv\"),\n        config,\n        split_chunks=False)\n    prepare_csv(\n        test_files,\n        os.path.join(args.target_dir, \"csv\", \"test.csv\"),\n        config,\n        split_chunks=False)\n\n    # stage 2: prepare the train and dev csv file\n    #          we get the train dataset ratio as config.split_ratio\n    #          and the remaining is dev dataset\n    logger.info(\"start to prepare the data csv file\")\n    train_files, dev_files = get_train_dev_list(\n        args.train, target_dir=args.target_dir, split_ratio=config.split_ratio)\n    prepare_csv(train_files,\n                os.path.join(args.target_dir, \"csv\", \"train.csv\"), config)\n    prepare_csv(dev_files,\n                os.path.join(args.target_dir, \"csv\", \"dev.csv\"), config)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        \"--train\",\n        required=True,\n        nargs='+',\n        help=\"The jsonline files list for train.\")\n    parser.add_argument(\n        \"--test\", required=True, help=\"The jsonline file for test\")\n    parser.add_argument(\n        \"--target_dir\",\n        default=None,\n        required=True,\n        help=\"The target directory stores the csv files and meta file.\")\n    parser.add_argument(\n        \"--config\",\n        default=None,\n        required=True,\n        type=str,\n        help=\"configuration file\")\n    args = parser.parse_args()\n\n    # parse the yaml config file\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    # prepare the csv file from jsonlines files\n    prepare_data(args, config)\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/make_voxceleb_kaldi_trial.py",
    "content": "#!/usr/bin/python3\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nMake VoxCeleb1 trial of kaldi format\nthis script creat the test trial from kaldi trial voxceleb1_test_v2.txt or official trial veri_test2.txt \nto kaldi trial format\n\"\"\"\nimport argparse\nimport codecs\nimport os\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--voxceleb_trial\",\n    default=\"voxceleb1_test_v2\",\n    type=str,\n    help=\"VoxCeleb trial file. Default we use the kaldi trial voxceleb1_test_v2.txt\"\n)\nparser.add_argument(\n    \"--trial\",\n    default=\"data/test/trial\",\n    type=str,\n    help=\"Kaldi format trial file\")\nargs = parser.parse_args()\n\n\ndef main(voxceleb_trial, trial):\n    \"\"\"\n        VoxCeleb provide several trial file, which format is different with kaldi format.\n\n        VoxCeleb format's meaning is as following:\n        --------------------------------\n        target_or_nontarget path1 path2\n        --------------------------------\n        target_or_nontarget is an integer: 1 target                 path1 is equal to path2\n                                           0 nontarget              path1 is unequal to path2    \n        path1: spkr_id/rec_id/name\n        path2: spkr_id/rec_id/name\n\n        Kaldi format's meaning is as following:\n        ---------------------------------------\n        utt_id1 utt_id2 target_or_nontarget\n        ---------------------------------------\n        utt_id1: utterance identification or speaker identification\n        utt_id2: utterance identification or speaker identification\n        target_or_nontarget is an string: 'target' utt_id1 is equal to  utt_id2\n                                        'nontarget' utt_id2 is unequal to utt_id2\n    \"\"\"\n    print(\"Start convert the voxceleb trial to kaldi format\")\n    if not os.path.exists(voxceleb_trial):\n        raise RuntimeError(\n            \"{} does not exist. Pleas input the correct file path\".format(\n                voxceleb_trial))\n\n    trial_dirname = os.path.dirname(trial)\n    if not os.path.exists(trial_dirname):\n        os.mkdir(trial_dirname)\n\n    with codecs.open(voxceleb_trial, 'r', encoding='utf-8') as f, \\\n         codecs.open(trial, 'w', encoding='utf-8') as w:\n        for line in f:\n            target_or_nontarget, path1, path2 = line.strip().split()\n\n            utt_id1 = \"-\".join(path1.split(\"/\"))\n            utt_id2 = \"-\".join(path2.split(\"/\"))\n            target = \"nontarget\"\n            if int(target_or_nontarget):\n                target = \"target\"\n            w.write(\"{} {} {}\\n\".format(utt_id1, utt_id2, target))\n    print(\"Convert the voxceleb trial to kaldi format successfully\")\n\n\nif __name__ == \"__main__\":\n    main(args.voxceleb_trial, args.trial)\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/test.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstage=1\nstop_stage=100\nuse_gpu=true    # if true, we run on GPU.\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nif [ $# -ne 3 ] ; then\n   echo \"Usage: $0 [options] <data-dir> <exp-dir> <conf-path>\";\n   echo \"e.g.: $0 ./data/ exp/voxceleb12/ conf/ecapa_tdnn.yaml\"\n   echo \"Options: \"\n   echo \"  --use-gpu <true,false|true>      # specify is gpu is to be used for training\"\n   echo \"  --stage <stage|-1>               # Used to run a partially-completed data process from somewhere in the middle.\"\n   echo \"  --stop-stage <stop-stage|100>    # Used to run a partially-completed data process stop stage in the middle\"\n   exit 1;\nfi\n\ndir=$1\nexp_dir=$2\nconf_path=$3\n\n# get the gpu nums for training\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\n# setting training device\ndevice=\"cpu\"\nif ${use_gpu}; then\n    device=\"gpu\"\nfi\nif [ $ngpu -le 0 ]; then \n    echo \"no gpu, training in cpu mode\"\n    device='cpu'\n    use_gpu=false\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n   # test the model and compute the eer metrics\n   python3 ${BIN_DIR}/test.py \\\n         --data-dir ${dir} \\\n         --load-checkpoint ${exp_dir} \\\n         --config ${conf_path} \\\n         --device ${device}\nfi\n"
  },
  {
    "path": "examples/voxceleb/sv0/local/train.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstage=0\nstop_stage=100\nuse_gpu=true    # if true, we run on GPU.\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit -1;\n\nif [ $# -ne 3 ] ; then\n   echo \"Usage: $0 [options] <data-dir> <exp-dir> <conf-path>\";\n   echo \"e.g.: $0 ./data/ exp/voxceleb12/ conf/ecapa_tdnn.yaml\"\n   echo \"Options: \"\n   echo \"  --use-gpu <true,false|true>      # specify is gpu is to be used for training\"\n   echo \"  --stage <stage|-1>               # Used to run a partially-completed data process from somewhere in the middle.\"\n   echo \"  --stop-stage <stop-stage|100>    # Used to run a partially-completed data process stop stage in the middle\"\n   exit 1;\nfi\n\ndir=$1\nexp_dir=$2\nconf_path=$3\n\n# get the gpu nums for training\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\n# setting training device\ndevice=\"cpu\"\nif ${use_gpu}; then\n    device=\"gpu\"\nfi\nif [ $ngpu -le 0 ]; then \n    echo \"no gpu, training in cpu mode\"\n    device='cpu'\n    use_gpu=false\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train the speaker identification task with voxceleb data\n    # and we will create the trained model parameters in ${exp_dir}/model.pdparams as the soft link\n    # Note: we will store the log file in exp/log directory\n    if $use_gpu; then\n        python3 -m paddle.distributed.launch --gpus=$CUDA_VISIBLE_DEVICES \\\n            ${BIN_DIR}/train.py --device ${device} --checkpoint-dir ${exp_dir} \\\n            --data-dir ${dir} --config ${conf_path}\n    else\n        python3 \\\n            ${BIN_DIR}/train.py --device ${device} --checkpoint-dir ${exp_dir} \\\n            --data-dir ${dir} --config ${conf_path}\n    fi\nfi \n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0"
  },
  {
    "path": "examples/voxceleb/sv0/path.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nexport MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\nMODEL=ecapa_tdnn\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/vector/exps/${MODEL}"
  },
  {
    "path": "examples/voxceleb/sv0/run.sh",
    "content": "#!/bin/bash\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n. ./path.sh\nset -e\n\n#######################################################################\n# stage 0: data prepare, including voxceleb1 download and generate {train,dev,enroll,test}.csv\n#          voxceleb2 data is m4a format, so we need convert the m4a to wav yourselves with the script local/convert.sh\n# stage 1: train the speaker identification model\n# stage 2: test speaker identification \n# stage 3: (todo)extract the training embeding to train the LDA and PLDA\n######################################################################\n\n# the vox2 dataset is stored in m4a format, we need to convert the audio from m4a to wav yourself\n# and put all of them to ${MAIN_ROOT}/datasets/vox2\n# we will find the wav from ${MAIN_ROOT}/datasets/vox1/{dev,test}/wav and ${MAIN_ROOT}/datasets/vox2/wav\n\nstage=0\nstop_stage=50\n\n# data directory\n# if we set the variable ${dir}, we will store the wav info to this directory\n# otherwise, we will store the wav info to data/vox1 and data/vox2 directory respectively\n# vox2 wav path, we must convert the m4a format to wav format    \ndir=data/                                 # data info directory   \n\nexp_dir=exp/ecapa-tdnn-vox12-big/            # experiment directory\nconf_path=conf/ecapa_tdnn.yaml          \ngpus=0,1,2,3\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nmkdir -p ${exp_dir}\n\nif [ $stage -le 0 ] && [ ${stop_stage} -ge 0 ]; then \n     # stage 0: data prepare for vox1 and vox2, vox2 must be converted from m4a to wav\n     bash ./local/data.sh ${dir} ${conf_path}|| exit -1;\nfi\n\nif [ $stage -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n     # stage 1: train the speaker identification model\n     CUDA_VISIBLE_DEVICES=${gpus} bash ./local/train.sh ${dir} ${exp_dir} ${conf_path} \nfi\n\nif [ $stage -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n     # stage 2: get the speaker verification scores with cosine function\n     #          now we only support use cosine to get the scores\n     CUDA_VISIBLE_DEVICES=0 bash ./local/test.sh ${dir} ${exp_dir} ${conf_path}\nfi\n\n# if [ $stage -le 3 ]; then\n#      # stage 3: extract the training embeding to train the LDA and PLDA\n#      # todo: extract the training embedding\n# fi \n"
  },
  {
    "path": "examples/wenetspeech/README.md",
    "content": "* asr0 - deepspeech2 Streaming/Non-Streaming\n* asr1 - transformer/conformer Streaming/Non-Streaming\n* asr2 - transformer/conformer Streaming/Non-Streaming with Kaldi feature\n\n# [WenetSpeech](https://github.com/wenet-e2e/WenetSpeech)\n\nA 10000+ Hours Multi-domain Chinese Corpus for Speech Recognition\n\n## Description\n\n### Creation\n\nAll the data are collected from YouTube and Podcast. Optical character recognition (OCR) and automatic speech recognition (ASR) techniques are adopted to label each YouTube and Podcast recording, respectively. To improve the quality of the corpus, we use a novel end-to-end label error detection method to further validate and filter the data.\n\n### Categories\n\nIn summary, WenetSpeech groups all data into 3 categories, as the following table shows:\n\n| Set        | Hours | Confidence  | Usage                                 |\n|------------|-------|-------------|---------------------------------------|\n| High Label | 10005 | >=0.95      | Supervised Training                   |\n| Weak Label | 2478  | [0.6, 0.95] | Semi-supervised or noise training     |\n| Unlabel    | 9952  | /           | Unsupervised training or Pre-training |\n| In Total   | 22435 | /           | All above                             |\n\n### High Label Data\n\nWe classify the high label into 10 groups according to its domain, speaking style, and scenarios.\n\n| Domain      | Youtube | Podcast | Total  |\n|-------------|---------|---------|--------|\n| audiobook   | 0       | 250.9   | 250.9  |\n| commentary  | 112.6   | 135.7   | 248.3  |\n| documentary | 386.7   | 90.5    | 477.2  |\n| drama       | 4338.2  | 0       | 4338.2 |\n| interview   | 324.2   | 614     | 938.2  |\n| news        | 0       | 868     | 868    |\n| reading     | 0       | 1110.2  | 1110.2 |\n| talk        | 204     | 90.7    | 294.7  |\n| variety     | 603.3   | 224.5   | 827.8  |\n| others      | 144     | 507.5   | 651.5  |\n| Total       | 6113    | 3892    | 10005  |\n\nAs shown in the following table, we provide 3 training subsets, namely `S`, `M`, and `L` for building ASR systems on different data scales.\n\n| Training Subsets | Confidence  | Hours |\n|------------------|-------------|-------|\n| L                | [0.95, 1.0] | 10005 |\n| M                | 1.0         | 1000  |\n| S                | 1.0         | 100   |\n\n### Evaluation Sets\n\n| Evaluation Sets | Hours | Source       | Description                                                                             |\n|-----------------|-------|--------------|-----------------------------------------------------------------------------------------|\n| DEV             | 20    | Internet     | Specially designed for some speech tools which require cross-validation set in training |\n| TEST\\_NET       | 23    | Internet     | Match test                                                                              |\n| TEST\\_MEETING   | 15    | Real meeting | Mismatch test which is a far-field, conversational, spontaneous, and meeting dataset   |\n"
  },
  {
    "path": "examples/wenetspeech/asr0/RESULTS.md",
    "content": "# Wenetspeech\n\n## Deepspeech2 Streaming\n\n| Model | Number of Params | Release | Config | Test set | Valid Loss | CER | \n| --- | --- | --- | --- | --- | --- | --- | \n| DeepSpeech2 | 1.2G | r1.0.0a | conf/deepspeech2\\_online.yaml + spec aug + fbank161, w/o LM | test\\_net | 13.307 | 15.02 |\n| DeepSpeech2 | 1.2G | r1.0.0a | conf/deepspeech2\\_online.yaml + spec aug + fbank161, w/o LM | test\\_meeting | 13.307 | 24.17 |\n"
  },
  {
    "path": "examples/wenetspeech/asr1/.gitignore",
    "content": "data\nexp\n*.profile\n"
  },
  {
    "path": "examples/wenetspeech/asr1/README.md",
    "content": "## Pack Model\n\npack model to tar.gz, e.g.\n\n```bash\n./utils/pack_model.sh  --preprocess_conf conf/preprocess.yaml --dict data/vocab.txt conf/conformer.yaml '' data/mean_std.json exp/conformer/checkpoints/wenetspeec\nh.pdparams \n\n```\n\nshow model.tar.gz\n```\ntar tf model.tar.gz \n```\n\nother way is:\n\n```bash\ntar cvzf asr1_chunk_conformer_u2_wenetspeech_ckpt_1.1.0.model.tar.gz model.yaml conf/tuning/ conf/chunk_conformer.yaml conf/preprocess.yaml data/mean_std.json exp/chunk_conformer/checkpoints/\n```\n\n## Export Static Model\n\n>> Need Paddle >= 2.4\n\n>> `data/test_meeting/data.list`\n>> {\"input\": [{\"name\": \"input1\", \"shape\": [3.2230625, 80], \"feat\": \"/home/PaddleSpeech/dataset/aishell/data_aishell/wav/test/S0764/BAC009S0764W0163.wav\", \"filetype\": \"sound\"}], \"output\": [{\"name\": \"target1\", \"shape\": [9, 5538], \"text\": \"\\u697c\\u5e02\\u8c03\\u63a7\\u5c06\\u53bb\\u5411\\u4f55\\u65b9\", \"token\": \"\\u697c \\u5e02 \\u8c03 \\u63a7 \\u5c06 \\u53bb \\u5411 \\u4f55 \\u65b9\", \"tokenid\": \"1891 1121 3502 1543 1018 477 528 163 1657\"}], \"utt\": \"BAC009S0764W0163\", \"utt2spk\": \"S0764\"}\n\n>> Test Wav: \n>> wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n### U2 chunk conformer\n>> UiDecoder\n>> Make sure `reverse_weight` in config is `0.0`\n>> https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2_wenetspeech_ckpt_1.1.0.model.tar.gz\n```\ntar zxvf asr1_chunk_conformer_u2_wenetspeech_ckpt_1.1.0.model.tar.gz\n./local/export.sh conf/chunk_conformer.yaml exp/chunk_conformer/checkpoints/avg_10 ./export.ji\n```\n\n### U2++ chunk conformer\n>> BiDecoder\n>> https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2pp_wenetspeech_ckpt_1.1.0.model.tar.gz\n>> Make sure `reverse_weight` in config is not `0.0`\n\n```\n./local/export.sh conf/chunk_conformer_u2pp.yaml exp/chunk_conformer/checkpoints/avg_10 ./export.ji\n```\n"
  },
  {
    "path": "examples/wenetspeech/asr1/RESULTS.md",
    "content": "# WenetSpeech\n\n## Conformer Streaming\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Valid Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test net | attention | 9.329 | 0.1102 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test net | ctc_greedy_search | 9.329 | 0.1207 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test net | ctc_prefix_beam_search | 9.329 | 0.1203 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test net | attention_rescoring | 9.329  | 0.1100 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test meeting | attention | 9.329 | 0.1992 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test meeting | ctc_greedy_search | 9.329 | 0.1960 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test meeting | ctc_prefix_beam_search | 9.329 | 0.1946 |  \n| conformer_online | 123.47 M | conf/chunk_conformer.yaml | spec_aug  | test meeting | attention_rescoring | 9.329  | 0.1879|  \n\n## Conformer\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | dev | attention |  |  |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | test net | ctc_greedy_search |  |  |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | test meeting | ctc_prefix_beam_search |  |  |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | test net | attention_rescoring |  |  |  \n\n\n\n## Conformer Pretrain Model\n\nPretrain model from http://mobvoi-speech-public.ufile.ucloud.cn/public/wenet/wenetspeech/20211025_conformer_exp.tar.gz\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Loss | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | aishell1 | attention | - | 0.048456 |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | aishell1 | ctc_greedy_search | - | 0.052534 |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | aishell1 | ctc_prefix_beam_search | - | 0.052915 |  \n| conformer | 32.52 M | conf/conformer.yaml | spec_aug  | aishell1 | attention_rescoring | - | 0.047904 |  \n\n\n## Conformer Steaming Pretrained Model\n\nPretrain model from https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention | 16 | 0.056273 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_greedy_search | 16 | 0.078918 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_prefix_beam_search | 16 | 0.079080 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention_rescoring | 16 | 0.054401 |\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention | -1 | 0.050767 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_greedy_search | -1 | 0.061884 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_prefix_beam_search | -1 | 0.062056 |  \n| conformer | 32.52 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention_rescoring | -1 |  0.052110 |\n\n\n## U2PP Steaming Pretrained Model\n\nPretrain model from https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2pp_wenetspeech_ckpt_1.3.0.model.tar.gz\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention | 16 | 0.057031 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_greedy_search | 16 | 0.068826 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_prefix_beam_search | 16 | 0.069111 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention_rescoring | 16 | 0.059213 |\n\n| Model | Params | Config | Augmentation| Test set | Decode method | Chunk Size | CER |  \n| --- | --- | --- | --- | --- | --- | --- | --- |\n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention | -1 | 0.049256 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_greedy_search | -1 | 0.052086 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | ctc_prefix_beam_search | -1 | 0.052267 |  \n| conformer | 122.88 M | conf/chunk_conformer.yaml | spec_aug  | aishell1 | attention_rescoring | -1 |  0.047198 |\n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/chunk_conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 512    # dimension of attention\n    attention_heads: 8\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: swish\n    pos_enc_layer_type: rel_pos\n    selfattention_layer_type: rel_selfattn\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 8\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    reverse_weight: 0.0 # unidecoder\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' \n\n# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/train_l/data.list\ndev_manifest: data/dev/data.list\ntest_manifest: data/test_meeting/data.list\n\n###########################################\n#              Dataloader                 #\n###########################################\nuse_streaming_data: True\nunit_type: 'char'\nvocab_filepath: data/lang_char/vocab.txt \npreprocess_config: conf/preprocess.yaml\nspm_model_prefix: ''\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\ndo_filter: True\nmaxlen_in: 1200  # if do_filter == False && input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 100  # if do_filter == False && output length > maxlen-out, batchsize is automatically reduced\nminlen_in: 10\nminlen_out: 0\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 26\naccum_grad: 32\nglobal_grad_clip: 5.0\ndist_sampler: True\nlog_interval: 1\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 5000\n  lr_decay: 1.0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/chunk_conformer_u2pp.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file: \ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 512    # dimension of attention\n    attention_heads: 8\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.1\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    activation_type: swish\n    pos_enc_layer_type: rel_pos\n    selfattention_layer_type: rel_selfattn\n    causal: true\n    use_dynamic_chunk: true\n    cnn_module_norm: 'layer_norm' # using nn.LayerNorm makes model converge faster\n    use_dynamic_left_chunk: false\n# decoder related\ndecoder: bitransformer\ndecoder_conf:\n    attention_heads: 8\n    linear_units: 2048\n    num_blocks: 3     # the number of encoder blocks\n    r_num_blocks: 3   #only for bitransformer\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.1\n    src_attention_dropout_rate: 0.1\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    reverse_weight: 0.3    # only for bitransformer decoder\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/train_l/data.list\ndev_manifest: data/dev/data.list\ntest_manifest: data/test_meeting/data.list\n\n###########################################\n#              Dataloader                 #\n###########################################\nuse_stream_data: True\nvocab_filepath: data/lang_char/vocab.txt \nunit_type: 'char'\npreprocess_config: conf/preprocess.yaml\nspm_model_prefix: ''\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\ndo_filter: True\nmaxlen_in: 1200  # if do_filter == False && input length  > maxlen-in, batchsize is automatically reduced\nmaxlen_out: 100  # if do_filter == False && output length > maxlen-out, batchsize is automatically reduced\nminlen_in: 10\nminlen_out: 0\nminibatches: 0 # for debug\nbatch_count: auto\nbatch_bins: 0 \nbatch_frames_in: 0\nbatch_frames_out: 0\nbatch_frames_inout: 0\nnum_workers: 0\nsubsampling_factor: 1\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 150 \naccum_grad: 8\nglobal_grad_clip: 5.0\ndist_sampler: False\noptim: adam\noptim_conf:\n  lr: 0.002\n  weight_decay: 1.0e-6\nscheduler: warmuplr\nscheduler_conf:\n  warmup_steps: 25000\n  lr_decay: 1.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/conformer.yaml",
    "content": "############################################\n#           Network Architecture           #\n############################################\ncmvn_file_type: \"json\"\n# encoder related\nencoder: conformer\nencoder_conf:\n    output_size: 512    # dimension of attention\n    attention_heads: 8\n    linear_units: 2048  # the number of units of position-wise feed forward\n    num_blocks: 12      # the number of encoder blocks\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    attention_dropout_rate: 0.0\n    input_layer: conv2d # encoder input type, you can chose conv2d, conv2d6 and conv2d8\n    normalize_before: True\n    use_cnn_module: True\n    cnn_module_kernel: 15\n    cnn_module_norm: layer_norm\n    activation_type: swish\n    pos_enc_layer_type: rel_pos\n    selfattention_layer_type: rel_selfattn\n\n# decoder related\ndecoder: transformer\ndecoder_conf:\n    attention_heads: 8\n    linear_units: 2048\n    num_blocks: 6\n    dropout_rate: 0.1\n    positional_dropout_rate: 0.1\n    self_attention_dropout_rate: 0.0\n    src_attention_dropout_rate: 0.0\n\n# hybrid CTC/attention\nmodel_conf:\n    ctc_weight: 0.3\n    lsm_weight: 0.1     # label smoothing option\n    length_normalized_loss: false\n    init_type: 'kaiming_uniform' # !Warning: need to convergence\n\n# https://yaml.org/type/float.html\n###########################################\n#                   Data                  #\n###########################################\ntrain_manifest: data/train_l/data.list\ndev_manifest: data/dev/data.list\ntest_manifest: data/test_meeting/data.list\n\n###########################################\n#              Dataloader                 #\n###########################################\nuse_stream_data: True\nunit_type: 'char'\nvocab_filepath: data/lang_char/vocab.txt \npreprocess_config: conf/preprocess.yaml\ncmvn_file: data/mean_std.json\nspm_model_prefix: ''\nfeat_dim: 80\nstride_ms: 10.0\nwindow_ms: 25.0\ndither: 0.1\nsortagrad: 0 # Feed samples from shortest to longest ; -1: enabled for all epochs, 0: disabled, other: enabled for 'other' epochs \nbatch_size: 32\nminlen_in: 10\nmaxlen_in: 1200  # if input length(number of frames) > maxlen-in, data is automatically removed\nminlen_out: 0\nmaxlen_out: 150  # if output length(number of tokens) > maxlen-out, data is automatically removed\nresample_rate: 16000\nshuffle_size: 1500 # read number of 'shuffle_size' data as a chunk, shuffle the data in the chunk\nsort_size: 1000  # read number of 'sort_size' data as a chunk, sort the data in the chunk \nnum_workers: 8\nprefetch_factor: 10\ndist_sampler: True\nnum_encs: 1\n\n###########################################\n#                 Training                #\n###########################################\nn_epoch: 32 \naccum_grad: 32\nglobal_grad_clip: 5.0\nlog_interval: 100\ncheckpoint:\n  kbest_n: 50\n  latest_n: 5\noptim: adam\noptim_conf:\n  lr: 0.001\n  weight_decay: 1.0e-6\nscheduler: warmuplr     \nscheduler_conf:\n  warmup_steps: 5000\n  lr_decay: 1.0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/preprocess.yaml",
    "content": "process:\n  # extract kaldi fbank from PCM\n  - type: fbank_kaldi\n    fs: 16000\n    n_mels: 80\n    n_shift: 160\n    win_length: 400\n    dither: 1.0\n  - type: cmvn_json\n    cmvn_path: data/mean_std.json\n  # these three processes are a.k.a. SpecAugument\n  - type: time_warp\n    max_time_warp: 5\n    inplace: true\n    mode: PIL\n  - type: freq_mask\n    F: 30\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n  - type: time_mask\n    T: 40\n    n_mask: 2\n    inplace: true\n    replace_with_zero: false\n\n\n\n\n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/tuning/chunk_decode.yaml",
    "content": "beam_size: 10\ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\nreverse_weight: 0.3 # reverse weight for attention rescoring decode mode.\ndecoding_chunk_size: 16 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: True  # simulate streaming inference. Defaults to False.\ndecode_batch_size: 128\nerror_rate_type: cer \n"
  },
  {
    "path": "examples/wenetspeech/asr1/conf/tuning/decode.yaml",
    "content": "beam_size: 10\ndecoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring'\nctc_weight: 0.5 # ctc weight for attention rescoring decode mode.\nreverse_weight: 0.3 # reverse weight for attention rescoring decode mode.\ndecoding_chunk_size: -1 # decoding chunk size. Defaults to -1.\n    # <0: for decoding, use full chunk.\n    # >0: for decoding, use fixed chunk size as set.\n    # 0: used for training, it's prohibited here. \nnum_decoding_left_chunks: -1  # number of left chunks for decoding. Defaults to -1.\nsimulate_streaming: False  # simulate streaming inference. Defaults to False.\ndecode_batch_size: 128\nerror_rate_type: cer \n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/data.sh",
    "content": "#!/bin/bash\n\n# Copyright 2021  Mobvoi Inc(Author: Di Wu, Binbin Zhang)\n#                 NPU, ASLP Group (Author: Qijie Shao)\n#\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\nstage=-1\nstop_stage=100\n\n# Use your own data path. You need to download the WenetSpeech dataset by yourself.\nwenetspeech_data_dir=./wenetspeech\n# Make sure you have 1.2T for ${shards_dir}\nshards_dir=./wenetspeech_shards\n\n#wenetspeech training set\nset=L\ntrain_set=train_`echo $set | tr 'A-Z' 'a-z'`\ndev_set=dev\ntest_sets=\"test_net test_meeting\"\n\ncmvn=true\ncmvn_sampling_divisor=20 # 20 means 5% of the training data to estimate cmvn\n\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\nset -u\nset -o pipefail\n\n\nmkdir -p data\nTARGET_DIR=${MAIN_ROOT}/dataset\nmkdir -p ${TARGET_DIR}\n\nif [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then\n    # download data\n    echo \"Please follow https://github.com/wenet-e2e/WenetSpeech to download the data.\"\n    exit 0;\nfi\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"Data preparation\"\n    local/wenetspeech_data_prep.sh \\\n        --train-subset $set \\\n        $wenetspeech_data_dir \\\n        data || exit 1;\nfi\n\ndict=data/lang_char/vocab.txt\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"Make a dictionary\"\n    echo \"dictionary: ${dict}\"\n    mkdir -p $(dirname $dict)\n    echo \"<blank>\" > ${dict} # 0 will be used for \"blank\" in CTC\n    echo \"<unk>\" >> ${dict} # <unk> must be 1\n    echo \"▁\" >> ${dict} # ▁ is for space\n    utils/text2token.py -s 1 -n 1 --space \"▁\" data/${train_set}/text \\\n        | cut -f 2- -d\" \" | tr \" \" \"\\n\" \\\n        | sort | uniq | grep -a -v -e '^\\s*$' \\\n        | grep -v \"▁\" \\\n        | awk '{print $0}' >> ${dict} \\\n        || exit 1;\n    echo \"<eos>\" >> $dict\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n  echo \"Compute cmvn\"\n  # Here we use all the training data, you can sample some some data to save time\n  # BUG!!! We should use the segmented data for CMVN\n  if $cmvn; then\n    full_size=`cat data/${train_set}/wav.scp | wc -l`\n    sampling_size=$((full_size / cmvn_sampling_divisor))\n    shuf -n $sampling_size data/$train_set/wav.scp \\\n      > data/$train_set/wav.scp.sampled\n    python3 utils/compute_cmvn_stats.py \\\n    --num_workers 16 \\\n    --train_config $train_config \\\n    --in_scp data/$train_set/wav.scp.sampled \\\n    --out_cmvn data/$train_set/mean_std.json \\\n    || exit 1;\n  fi\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n  echo \"Making shards, please wait...\"\n  RED='\\033[0;31m'\n  NOCOLOR='\\033[0m'\n  echo -e \"It requires ${RED}1.2T ${NOCOLOR}space for $shards_dir, please make sure you have enough space\"\n  echo -e \"It takes about ${RED}12 ${NOCOLOR}hours with 32 threads\"\n  for x in $dev_set $test_sets ${train_set}; do\n    dst=$shards_dir/$x\n    mkdir -p $dst\n    utils/make_filted_shard_list.py --num_node 1 --num_gpus_per_node 8 --num_utts_per_shard 1000 \\\n      --do_filter --resample 16000  \\\n      --num_threads 32 --segments data/$x/segments \\\n      data/$x/wav.scp data/$x/text \\\n      $(realpath $dst) data/$x/data.list\n  done\nfi\n\necho \"Wenetspeech data preparation done.\"\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/export.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: $0 config_path ckpt_prefix jit_model_path\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\nckpt_path_prefix=$2\njit_model_export_path=$3\n\n\n# export can not using StreamdataDataloader, set use_stream_dta False\n# u2: reverse_weight should be 0.0\n# u2pp: reverse_weight should be same with config file. e.g. 0.3\npython3 -u ${BIN_DIR}/export.py \\\n--ngpu ${ngpu} \\\n--config ${config_path} \\\n--opts use_stream_data False \\\n--checkpoint_path ${ckpt_path_prefix} \\\n--export_path ${jit_model_export_path}\n\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in export!\"\n    exit 1\nfi\n\n\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/extract_meta.py",
    "content": "# Copyright 2021  Xiaomi Corporation (Author: Yongqing Wang)\n#                 Mobvoi Inc(Author: Di Wu, Binbin Zhang)\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport json\nimport os\nimport sys\n\n\ndef get_args():\n    parser = argparse.ArgumentParser(description=\"\"\"\n      This script is used to process raw json dataset of WenetSpeech,\n      where the long wav is splitinto segments and\n      data of wenet format is generated.\n      \"\"\")\n    parser.add_argument('input_json', help=\"\"\"Input json file of WenetSpeech\"\"\")\n    parser.add_argument('output_dir', help=\"\"\"Output dir for prepared data\"\"\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef meta_analysis(input_json, output_dir):\n    input_dir = os.path.dirname(input_json)\n\n    if not os.path.exists(output_dir):\n        os.makedirs(output_dir)\n\n    try:\n        with open(input_json, 'r') as injson:\n            json_data = json.load(injson)\n    except Exception:\n        sys.exit(f'Failed to load input json file: {input_json}')\n    else:\n        if json_data['audios'] is not None:\n            with open(f'{output_dir}/text', 'w') as utt2text, \\\n                 open(f'{output_dir}/segments', 'w') as segments, \\\n                 open(f'{output_dir}/utt2dur', 'w') as utt2dur, \\\n                 open(f'{output_dir}/wav.scp', 'w') as wavscp, \\\n                 open(f'{output_dir}/utt2subsets', 'w') as utt2subsets, \\\n                 open(f'{output_dir}/reco2dur', 'w') as reco2dur:\n                for long_audio in json_data['audios']:\n                    try:\n                        long_audio_path = os.path.realpath(\n                            os.path.join(input_dir, long_audio['path']))\n                        aid = long_audio['aid']\n                        segments_lists = long_audio['segments']\n                        duration = long_audio['duration']\n                        assert (os.path.exists(long_audio_path))\n                    except AssertionError:\n                        print(f'''Warning: {aid} something is wrong,\n                                  maybe AssertionError, skipped''')\n                        continue\n                    except Exception:\n                        print(f'''Warning: {aid} something is wrong, maybe the\n                                  error path: {long_audio_path}, skipped''')\n                        continue\n                    else:\n                        wavscp.write(f'{aid}\\t{long_audio_path}\\n')\n                        reco2dur.write(f'{aid}\\t{duration}\\n')\n                        for segment_file in segments_lists:\n                            try:\n                                sid = segment_file['sid']\n                                start_time = segment_file['begin_time']\n                                end_time = segment_file['end_time']\n                                dur = end_time - start_time\n                                text = segment_file['text']\n                                segment_subsets = segment_file[\"subsets\"]\n                            except Exception:\n                                print(f'''Warning: {segment_file} something\n                                          is wrong, skipped''')\n                                continue\n                            else:\n                                utt2text.write(f'{sid}\\t{text}\\n')\n                                segments.write(\n                                    f'{sid}\\t{aid}\\t{start_time}\\t{end_time}\\n')\n                                utt2dur.write(f'{sid}\\t{dur}\\n')\n                                segment_sub_names = \" \".join(segment_subsets)\n                                utt2subsets.write(\n                                    f'{sid}\\t{segment_sub_names}\\n')\n\n\ndef main():\n    args = get_args()\n\n    meta_analysis(args.input_json, args.output_dir)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/process_opus.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Copyright 2021  NPU, ASLP Group (Author: Qijie Shao)\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# process_opus.py: segmentation and downsampling of opus audio\n# usage: python3 process_opus.py wav.scp segments output_wav.scp\nimport os\nimport sys\n\nfrom pydub import AudioSegment\n\n\ndef read_file(wav_scp, segments):\n    wav_scp_dict = {}\n    with open(wav_scp, 'r', encoding='UTF-8') as fin:\n        for line_str in fin:\n            wav_id, path = line_str.strip().split()\n            wav_scp_dict[wav_id] = path\n\n    utt_list = []\n    seg_path_list = []\n    start_time_list = []\n    end_time_list = []\n    with open(segments, 'r', encoding='UTF-8') as fin:\n        for line_str in fin:\n            arr = line_str.strip().split()\n            assert len(arr) == 4\n            utt_list.append(arr[0])\n            seg_path_list.append(wav_scp_dict[arr[1]])\n            start_time_list.append(float(arr[2]))\n            end_time_list.append(float(arr[3]))\n    return utt_list, seg_path_list, start_time_list, end_time_list\n\n\n# TODO(Qijie): Fix the process logic\ndef output(output_wav_scp, utt_list, seg_path_list, start_time_list,\n           end_time_list):\n    num_utts = len(utt_list)\n    step = int(num_utts * 0.01)\n    with open(output_wav_scp, 'w', encoding='UTF-8') as fout:\n        previous_wav_path = \"\"\n        for i in range(num_utts):\n            utt_id = utt_list[i]\n            current_wav_path = seg_path_list[i]\n            output_dir = (os.path.dirname(current_wav_path)) \\\n                .replace(\"audio\", 'audio_seg')\n            seg_wav_path = os.path.join(output_dir, utt_id + '.wav')\n\n            # if not os.path.exists(output_dir):\n            #     os.makedirs(output_dir)\n\n            if current_wav_path != previous_wav_path:\n                source_wav = AudioSegment.from_file(current_wav_path)\n            previous_wav_path = current_wav_path\n\n            start = int(start_time_list[i] * 1000)\n            end = int(end_time_list[i] * 1000)\n            target_audio = source_wav[start:end].set_frame_rate(16000)\n            target_audio.export(seg_wav_path, format=\"wav\")\n\n            fout.write(\"{} {}\\n\".format(utt_id, seg_wav_path))\n            if i % step == 0:\n                print(\"seg wav finished: {}%\".format(int(i / step)))\n\n\ndef main():\n    wav_scp = sys.argv[1]\n    segments = sys.argv[2]\n    output_wav_scp = sys.argv[3]\n\n    utt_list, seg_path_list, start_time_list, end_time_list \\\n        = read_file(wav_scp, segments)\n    output(output_wav_scp, utt_list, seg_path_list, start_time_list,\n           end_time_list)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/quant.sh",
    "content": "#!/bin/bash\n\n# ./local/quant.sh conf/chunk_conformer_u2pp.yaml conf/tuning/chunk_decode.yaml exp/chunk_conformer_u2pp/checkpoints/avg_10 data/wav.aishell.test.scp \nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_scp\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_scp=$4\n\nmkdir -p data\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_scp} ]; then\n    echo \"Plase input the right audio_scp path\"\n    exit 1\nfi\n\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in  attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/quant.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --num_utts 200 \\\n    --audio_scp ${audio_scp}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/test.sh",
    "content": "#!/bin/bash\n\nif [ $# != 3 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\n\nfor type in attention ctc_greedy_search; do\n    echo \"decoding ${type}\"\n    if [ ${chunk_mode} == true ];then\n        # stream decoding only support batchsize=1\n        batch_size=1\n    else\n        batch_size=64\n    fi\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nfor type in ctc_prefix_beam_search attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test.py \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\n\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/test_wav.sh",
    "content": "#!/bin/bash\n\nif [ $# != 4 ];then\n    echo \"usage: ${0} config_path decode_config_path ckpt_path_prefix audio_file\"\n    exit -1\nfi\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nconfig_path=$1\ndecode_config_path=$2\nckpt_prefix=$3\naudio_file=$4\n\nmkdir -p data\nwget -nc https://paddlespeech.cdn.bcebos.com/datasets/single_wav/zh/demo_01_03.wav -P data/\nif [ $? -ne 0 ]; then\n   exit 1\nfi\n\nif [ ! -f ${audio_file} ]; then\n    echo \"Plase input the right audio_file path\"\n    exit 1\nfi\n\n\nchunk_mode=false\nif [[ ${config_path} =~ ^.*chunk_.*yaml$ ]];then\n    chunk_mode=true\nfi\n\n# download language model\n#bash local/download_lm_ch.sh\n#if [ $? -ne 0 ]; then\n#    exit 1\n#fi\n\nfor type in  attention_rescoring; do\n    echo \"decoding ${type}\"\n    batch_size=1\n    output_dir=${ckpt_prefix}\n    mkdir -p ${output_dir}\n    python3 -u ${BIN_DIR}/test_wav.py \\\n    --debug True \\\n    --ngpu ${ngpu} \\\n    --config ${config_path} \\\n    --decode_cfg ${decode_config_path} \\\n    --result_file ${output_dir}/${type}.rsl \\\n    --checkpoint_path ${ckpt_prefix} \\\n    --opts decode.decoding_method ${type} \\\n    --opts decode.decode_batch_size ${batch_size} \\\n    --audio_file ${audio_file}\n\n    if [ $? -ne 0 ]; then\n        echo \"Failed in evaluation!\"\n        exit 1\n    fi\ndone\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/train.sh",
    "content": "#!/bin/bash\n\nprofiler_options=\nbenchmark_batch_size=0\nbenchmark_max_step=0\n\n# seed may break model convergence\nseed=0\n\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\nngpu=$(echo $CUDA_VISIBLE_DEVICES | awk -F \",\" '{print NF}')\necho \"using $ngpu gpus...\"\n\nif [ ${seed} != 0  ]; then\n    export FLAGS_cudnn_deterministic=True\n    echo \"using seed $seed & FLAGS_cudnn_deterministic=True ...\"\nfi\n\nif [ $# -lt 2 ] && [ $# -gt 3 ];then\n    echo \"usage: CUDA_VISIBLE_DEVICES=0 ${0} config_path ckpt_name ips(optional)\"\n    exit -1\nfi\n\nconfig_path=$1\nckpt_name=$2\nips=$3\n\nif [ ! $ips ];then\n  ips_config=\nelse\n  ips_config=\"--ips=\"${ips}\nfi\necho ${ips_config}\n\nmkdir -p exp\n\n# default memory allocator strategy may case gpu training hang\n# for no OOM raised when memory exhausted\nexport FLAGS_allocator_strategy=naive_best_fit\n\nif [ ${ngpu} == 0 ]; then\npython3 -u ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nelse\nNCCL_SOCKET_IFNAME=eth0 python3 -m paddle.distributed.launch --gpus=${CUDA_VISIBLE_DEVICES} ${ips_config} ${BIN_DIR}/train.py \\\n--ngpu ${ngpu} \\\n--seed ${seed} \\\n--config ${config_path} \\\n--output exp/${ckpt_name} \\\n--profiler-options \"${profiler_options}\" \\\n--benchmark-batch-size ${benchmark_batch_size} \\\n--benchmark-max-step ${benchmark_max_step}\nfi\n\n\nif [ ${seed} != 0  ]; then\n    unset FLAGS_cudnn_deterministic\nfi\n\nif [ $? -ne 0 ]; then\n    echo \"Failed in training!\"\n    exit 1\nfi\n\nexit 0\n"
  },
  {
    "path": "examples/wenetspeech/asr1/local/wenetspeech_data_prep.sh",
    "content": "#!/usr/bin/env bash\n\n# Copyright 2021  Xiaomi Corporation (Author: Yongqing Wang)\n#                 Seasalt AI, Inc (Author: Guoguo Chen)\n#                 Mobvoi Inc(Author: Di Wu, Binbin Zhang)\n#                 NPU, ASLP Group (Author: Qijie Shao)\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -e\nset -o pipefail\n\nstage=1\nprefix=\ntrain_subset=L\n\n. ./utils/parse_options.sh || exit 1;\n\nfilter_by_id () {\n  idlist=$1\n  input=$2\n  output=$3\n  field=1\n  if [ $# -eq 4 ]; then\n    field=$4\n  fi\n  cat $input | perl -se '\n    open(F, \"<$idlist\") || die \"Could not open id-list file $idlist\";\n    while(<F>) {\n      @A = split;\n      @A>=1 || die \"Invalid id-list file line $_\";\n      $seen{$A[0]} = 1;\n    }\n    while(<>) {\n      @A = split;\n      @A > 0 || die \"Invalid file line $_\";\n      @A >= $field || die \"Invalid file line $_\";\n      if ($seen{$A[$field-1]}) {\n        print $_;\n      }\n    }' -- -idlist=\"$idlist\" -field=\"$field\" > $output ||\\\n  (echo \"$0: filter_by_id() error: $input\" && exit 1) || exit 1;\n}\n\nsubset_data_dir () {\n  utt_list=$1\n  src_dir=$2\n  dest_dir=$3\n  mkdir -p $dest_dir || exit 1;\n  # wav.scp text segments utt2dur\n  filter_by_id $utt_list $src_dir/utt2dur $dest_dir/utt2dur ||\\\n    (echo \"$0: subset_data_dir() error: $src_dir/utt2dur\" && exit 1) || exit 1;\n  filter_by_id $utt_list $src_dir/text $dest_dir/text ||\\\n    (echo \"$0: subset_data_dir() error: $src_dir/text\" && exit 1) || exit 1;\n  filter_by_id $utt_list $src_dir/segments $dest_dir/segments ||\\\n    (echo \"$0: subset_data_dir() error: $src_dir/segments\" && exit 1) || exit 1;\n  awk '{print $2}' $dest_dir/segments | sort | uniq > $dest_dir/reco\n  filter_by_id $dest_dir/reco $src_dir/wav.scp $dest_dir/wav.scp ||\\\n    (echo \"$0: subset_data_dir() error: $src_dir/wav.scp\" && exit 1) || exit 1;\n  rm -f $dest_dir/reco\n}\n\nif [ $# -ne 2 ]; then\n  echo \"Usage: $0 [options] <wenetspeech-dataset-dir> <data-dir>\"\n  echo \" e.g.: $0 --train-subset L /disk1/audio_data/wenetspeech/ data/\"\n  echo \"\"\n  echo \"This script takes the WenetSpeech source directory, and prepares the\"\n  echo \"WeNet format data directory.\"\n  echo \"  --prefix <prefix>                # Prefix for output data directory.\"\n  echo \"  --stage <stage>                  # Processing stage.\"\n  echo \"  --train-subset <L|M|S|W>     # Train subset to be created.\"\n  exit 1\nfi\n\nwenetspeech_dir=$1\ndata_dir=$2\n\ndeclare -A subsets\nsubsets=(\n  [L]=\"train_l\"\n  [M]=\"train_m\"\n  [S]=\"train_s\"\n  [W]=\"train_w\"\n  [DEV]=\"dev\"\n  [TEST_NET]=\"test_net\"\n  [TEST_MEETING]=\"test_meeting\")\n\nprefix=${prefix:+${prefix}_}\n\ncorpus_dir=$data_dir/${prefix}corpus/\nif [ $stage -le 1 ]; then\n  echo \"$0: Extract meta into $corpus_dir\"\n  # Sanity check.\n  [ ! -f $wenetspeech_dir/WenetSpeech.json ] &&\\\n    echo \"$0: Please download $wenetspeech_dir/WenetSpeech.json!\" && exit 1;\n  [ ! -d $wenetspeech_dir/audio ] &&\\\n    echo \"$0: Please download $wenetspeech_dir/audio!\" && exit 1;\n\n  [ ! -d $corpus_dir ] && mkdir -p $corpus_dir\n\n  # Files to be created:\n  # wav.scp text segments utt2dur\n  python3 local/extract_meta.py \\\n    $wenetspeech_dir/WenetSpeech.json $corpus_dir || exit 1;\nfi\n\nif [ $stage -le 2 ]; then\n  echo \"$0: Split data to train, dev, test_net, and test_meeting\"\n  [ ! -f $corpus_dir/utt2subsets ] &&\\\n    echo \"$0: No such file $corpus_dir/utt2subsets!\" && exit 1;\n  for label in $train_subset DEV TEST_NET TEST_MEETING; do\n    if [ ! ${subsets[$label]+set} ]; then\n      echo \"$0: Subset $label is not defined in WenetSpeech.json.\" && exit 1;\n    fi\n    subset=${subsets[$label]}\n    [ ! -d $data_dir/${prefix}$subset ] && mkdir -p $data_dir/${prefix}$subset\n    cat $corpus_dir/utt2subsets | \\\n       awk -v s=$label '{for (i=2;i<=NF;i++) if($i==s) print $0;}' \\\n       > $corpus_dir/${prefix}${subset}_utt_list|| exit 1;\n    subset_data_dir $corpus_dir/${prefix}${subset}_utt_list \\\n      $corpus_dir $data_dir/${prefix}$subset || exit 1;\n  done\nfi\n\necho \"$0: Done\"\n"
  },
  {
    "path": "examples/wenetspeech/asr1/path.sh",
    "content": "export MAIN_ROOT=`realpath ${PWD}/../../../`\n\nexport PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH}\nexport LC_ALL=C\n\nexport PYTHONDONTWRITEBYTECODE=1\n# Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C\nexport PYTHONIOENCODING=UTF-8\nexport PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH}\n\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/\n\n# model exp\nMODEL=u2\nexport BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/bin\n"
  },
  {
    "path": "examples/wenetspeech/asr1/run.sh",
    "content": "#!/bin/bash\n\n. path.sh || exit 1;\nset -e\n\ngpus=0,1,2,3,4,5,6,7\nstage=0\nstop_stage=100\nconf_path=conf/conformer.yaml\nips=  #xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx\ndecode_conf_path=conf/tuning/decode.yaml\naverage_checkpoint=true\navg_num=10\n\n. ${MAIN_ROOT}/utils/parse_options.sh || exit 1;\n\navg_ckpt=avg_${avg_num}\nckpt=$(basename ${conf_path} | awk -F'.' '{print $1}')\necho \"checkpoint name ${ckpt}\"\n\naudio_file=\"data/demo_01_03.wav\"\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    bash ./local/data.sh || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `exp` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path}  ${ckpt} ${ips}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # avg n best model\n    avg.sh best exp/${ckpt}/checkpoints ${avg_num}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # test ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # ctc alignment of test data\n    CUDA_VISIBLE_DEVICES=0 ./local/align.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} || exit -1\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # export ckpt avg_n\n    CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit\nfi\n\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    # test a single .wav file\n    CUDA_VISIBLE_DEVICES=0 ./local/test_wav.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} ${audio_file} || exit -1\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    # export quant model, plesae see local/quant.sh\nfi\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/README.md",
    "content": "\n# Mixed Chinese and English TTS with CSMSC, LJSpeech-1.1, AISHELL-3 and VCTK datasets\n\nThis example contains code used to train a [Fastspeech2](https://arxiv.org/abs/2006.04558) model with [CSMSC](https://www.data-baker.com/open_source.html), [LJSpeech-1.1](https://keithito.com/LJ-Speech-Dataset/), [AISHELL3](http://www.aishelltech.com/aishell_3) and [VCTK](https://datashare.ed.ac.uk/handle/10283/3443) datasets.\n\n\n## Dataset\n### Download and Extract\nDownload all datasets and extract it to `./data`:\n- The CSMSC dataset is in the directory `./data/BZNSYP`\n- The Ljspeech dataset is in the directory `./data/LJSpeech-1.1`\n- The aishell3 dataset is in the directory `./data/data_aishell3`\n- The vctk dataset is in the directory `./data/VCTK-Corpus-0.92`\n \n### Get MFA Result and Extract\nWe use [MFA](https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner) to get durations for the fastspeech2 training.\nYou can download from here:\n- [baker_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz)\n- [ljspeech_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz)\n- [aishell3_alignment_tone.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz) \n- [vctk_alignment.tar.gz](https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz)\n\nOr train your MFA model reference to [mfa example](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/other/mfa) (use MFA1.x now) of our repo.\n\n## Get Started\nAssume the paths to the datasets are:\n- `./data/BZNSYP`\n- `./data/LJSpeech-1.1`\n- `./data/data_aishell3` \n- `./data/VCTK-Corpus-0.92`\n\nAssume the path to the MFA results of the datasets are:\n- `./data/mfa/baker_alignment_tone`\n- `./data/mfa/ljspeech_alignment`\n- `./data/mfa/aishell3_alignment_tone`\n- `./data/mfa/vctk_alignment`\n\nRun the command below to\n1. **source path**.\n2. preprocess the dataset.\n3. train the model.\n4. synthesize wavs.\n    - synthesize waveform from `metadata.jsonl`.\n    - synthesize waveform from text file.\n```bash\n./run.sh\n```\n\nYou can choose a range of stages you want to run, or set `stage` equal to `stop-stage` to use only one stage, for example, running the following command will only preprocess the dataset.\n```bash\n./run.sh --stage 0 --stop-stage 0\n```\n\n### Data Preprocessing\n```bash\n./local/preprocess.sh ${conf_path} ${datasets_root_dir} ${mfa_root_dir}\n```\nWhen it is done. A `dump` folder is created in the current directory. The structure of the dump folder is listed below.\n```text\ndump\n├── dev\n│   ├── norm\n│   └── raw\n├── phone_id_map.txt\n├── speaker_id_map.txt\n├── test\n│   ├── norm\n│   └── raw\n└── train\n    ├── energy_stats.npy\n    ├── norm\n    ├── pitch_stats.npy\n    ├── raw\n    └── speech_stats.npy\n```\nThe dataset is split into 3 parts, namely `train`, `dev`, and` test`, each of which contains a `norm` and `raw` subfolder. The raw folder contains speech, pitch and energy features of each utterance, while the norm folder contains normalized ones. The statistics used to normalize features are computed from the training set, which is located in `dump/train/*_stats.npy`.\n\nAlso, there is a `metadata.jsonl` in each subfolder. It is a table-like file that contains phones, text_lengths, speech_lengths, durations, the path of speech features, the path of pitch features, a path of energy features, speaker, and id of each utterance.\n\n\n### Model Training\n`./local/train.sh` calls `${BIN_DIR}/train.py`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}\n```\nHere's the complete help message.\n```text\nusage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA]\n                [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR]\n                [--ngpu NGPU] [--phones-dict PHONES_DICT]\n                [--speaker-dict SPEAKER_DICT] [--voice-cloning VOICE_CLONING]\n\nTrain a FastSpeech2 model.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --config CONFIG       fastspeech2 config file.\n  --train-metadata TRAIN_METADATA\n                        training data.\n  --dev-metadata DEV_METADATA\n                        dev data.\n  --output-dir OUTPUT_DIR\n                        output dir.\n  --ngpu NGPU           if ngpu=0, use cpu.\n  --phones-dict PHONES_DICT\n                        phone vocabulary file.\n  --speaker-dict SPEAKER_DICT\n                        speaker id map file for multiple speaker model.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n```\n1. `--config` is a config file in yaml format to overwrite the default config, which can be found at `conf/default.yaml`.\n2. `--train-metadata` and `--dev-metadata` should be the metadata file in the normalized subfolder of `train` and `dev` in the `dump` folder.\n3. `--output-dir` is the directory to save the results of the experiment. Checkpoints are saved in `checkpoints/` inside this directory.\n4. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n5. `--phones-dict` is the path of the phone vocabulary file.\n6. `--speaker-dict` is the path of the speaker id map file when training a multi-speaker FastSpeech2.\n\nWe have **added module speaker classifier** with reference to [Learning to Speak Fluently in a Foreign Language: Multilingual Speech Synthesis and Cross-Language Voice Cloning](https://arxiv.org/pdf/1907.04448.pdf). The main parameter configuration: `config[\"model\"][\"enable_speaker_classifier\"]`, `config[\"model\"][\"hidden_sc_dim\"]` and `config[\"updater\"][\"spk_loss_scale\"]` in `conf/default.yaml`. The current experimental results show that this module can decouple text information and speaker information, and more experiments are still being sorted out. This module is currently not enabled by default, if you are interested, you can try it yourself.\n\n\n### Synthesizing\nWe use [parallel wavegan](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/examples/aishell3/voc1) as the default neural vocoder.\nDownload the pretrained parallel wavegan model from [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip) and unzip it.\n\nWhen speaker is `174` (csmsc), use csmsc's vocoder is better than aishell3's, we recommend that you use [hifigan_csmsc_ckpt_0.1.1.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_ckpt_0.1.1.zip), please check `stage 2`  of `synthesize_e2e.sh`.\n\nBut if speaker is `175` (ljspeech), we **don't** recommend you to use ljspeech's vocoder, because ljspeech's vocoders are trained on sample rate 22.05kHz, but this acoustic model is trained on sample rate 24kHz, you can use csmsc's vocoder also, because ljspeech and csmsc are both female speakers.\n\nFor speakers in aishell3 and vctk, we recommend you use aishell3 or vctk's vocoders, because ljspeech and csmsc are both female speakers, there vocoders may not perform well for male speakers in aishell3 and vctk, you can check speaker name and spk_id in `dump/speaker_id_map.txt` and check speakers' information ( Age / Gender / Accents / region, etc ) in [this issue](https://github.com/PaddlePaddle/PaddleSpeech/issues/1620) and choose the `spk_id` you want.\n\n\n```bash\nunzip pwg_aishell3_ckpt_0.5.zip\n```\nParallel WaveGAN checkpoint contains files listed below.\n```text\npwg_aishell3_ckpt_0.5\n├── default.yaml                   # default config used to train parallel wavegan\n├── feats_stats.npy                # statistics used to normalize spectrogram when training parallel wavegan\n└── snapshot_iter_1000000.pdz      # generator parameters of parallel wavegan\n```\n`./local/synthesize.sh` calls `${BIN_DIR}/../synthesize.py`, which can synthesize waveform from `metadata.jsonl`.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize.py [-h]\n                     [--am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3, fastspeech2_mix}]\n                     [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                     [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                     [--tones_dict TONES_DICT] [--speaker_dict SPEAKER_DICT]\n                     [--voice-cloning VOICE_CLONING]\n                     [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}]\n                     [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                     [--voc_stat VOC_STAT] [--ngpu NGPU]\n                     [--test_metadata TEST_METADATA] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech,tacotron2_aishell3, fastspeech2_mix}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --voice-cloning VOICE_CLONING\n                        whether training voice cloning model.\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,wavernn_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,style_melgan_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --test_metadata TEST_METADATA\n                        test metadata.\n  --output_dir OUTPUT_DIR\n                        output dir.\n\n\n```\n`./local/synthesize_e2e.sh` calls `${BIN_DIR}/../synthesize_e2e.py`, which can synthesize waveform from text file.\n```bash\nCUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name}\n```\n```text\nusage: synthesize_e2e.py [-h]\n                         [--am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech, fastspeech2_mix}]\n                         [--am_config AM_CONFIG] [--am_ckpt AM_CKPT]\n                         [--am_stat AM_STAT] [--phones_dict PHONES_DICT]\n                         [--tones_dict TONES_DICT]\n                         [--speaker_dict SPEAKER_DICT] [--spk_id SPK_ID]\n                         [--voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}]\n                         [--voc_config VOC_CONFIG] [--voc_ckpt VOC_CKPT]\n                         [--voc_stat VOC_STAT] [--lang LANG]\n                         [--inference_dir INFERENCE_DIR] [--ngpu NGPU]\n                         [--text TEXT] [--output_dir OUTPUT_DIR]\n\nSynthesize with acoustic model & vocoder\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --am {speedyspeech_csmsc,speedyspeech_aishell3,fastspeech2_csmsc,fastspeech2_ljspeech,fastspeech2_aishell3,fastspeech2_vctk,tacotron2_csmsc,tacotron2_ljspeech, fastspeech2_mix}\n                        Choose acoustic model type of tts task.\n  --am_config AM_CONFIG\n                        Config of acoustic model.\n  --am_ckpt AM_CKPT     Checkpoint file of acoustic model.\n  --am_stat AM_STAT     mean and standard deviation used to normalize\n                        spectrogram when training acoustic model.\n  --phones_dict PHONES_DICT\n                        phone vocabulary file.\n  --tones_dict TONES_DICT\n                        tone vocabulary file.\n  --speaker_dict SPEAKER_DICT\n                        speaker id map file.\n  --spk_id SPK_ID       spk id for multi speaker acoustic model\n  --voc {pwgan_csmsc,pwgan_ljspeech,pwgan_aishell3,pwgan_vctk,mb_melgan_csmsc,style_melgan_csmsc,hifigan_csmsc,hifigan_ljspeech,hifigan_aishell3,hifigan_vctk,wavernn_csmsc}\n                        Choose vocoder type of tts task.\n  --voc_config VOC_CONFIG\n                        Config of voc.\n  --voc_ckpt VOC_CKPT   Checkpoint file of voc.\n  --voc_stat VOC_STAT   mean and standard deviation used to normalize\n                        spectrogram when training voc.\n  --lang LANG           Choose model language. zh or en or mix\n  --inference_dir INFERENCE_DIR\n                        dir to save inference models\n  --ngpu NGPU           if ngpu == 0, use cpu.\n  --text TEXT           text to synthesize, a 'utt_id sentence' pair per line.\n  --output_dir OUTPUT_DIR\n                        output dir.\n```\n1. `--am` is acoustic model type with the format {model_name}_{dataset}\n2. `--am_config`, `--am_ckpt`, `--am_stat`, `--phones_dict` `--speaker_dict` are arguments for acoustic model, which correspond to the 5 files in the fastspeech2 pretrained model.\n3. `--voc` is vocoder type with the format {model_name}_{dataset}\n4. `--voc_config`, `--voc_ckpt`, `--voc_stat` are arguments for vocoder, which correspond to the 3 files in the parallel wavegan pretrained model.\n5. `--lang` is the model language, which can be `zh` or `en` or `mix`.\n6. `--test_metadata` should be the metadata file in the normalized subfolder of `test`  in the `dump` folder.\n7. `--text` is the text file, which contains sentences to synthesize.\n8. `--output_dir` is the directory to save synthesized audio files.\n9. `--ngpu` is the number of gpus to use, if ngpu == 0, use cpu.\n\n\n## Pretrained Model\n\nPretrained FastSpeech2 model with no silence in the edge of audios:\n- [fastspeech2_mix_ckpt_1.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_1.2.0.zip)\n- [pwg_aishell3_ckpt_0.5.zip](https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip)\n\nThe static model can be downloaded here:\n- [fastspeech2_mix_static_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_static_0.2.0.zip)\n\nThe PIR static model can be downloaded here:\n- [fastspeech2_mix_static_pir_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_static_pir_0.2.0.zip) (Run PIR model need to set FLAGS_enable_pir_api=1, and PIR model only worked with paddlepaddle>=3.0.0b2)\n\nThe ONNX model can be downloaded here:\n- [fastspeech2_mix_onnx_0.2.0.zip](https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_onnx_0.2.0.zip)\n\nFastSpeech2 checkpoint contains files listed below.\n\n```text\nfastspeech2_mix_ckpt_1.2.0\n├── default.yaml            # default config used to train fastspeech2\n├── energy_stats.npy        # statistics used to energy spectrogram when training fastspeech2\n├── phone_id_map.txt        # phone vocabulary file when training fastspeech2\n├── pitch_stats.npy         # statistics used to normalize pitch when training fastspeech2\n├── snapshot_iter_99200.pdz # model parameters and optimizer states\n├── speaker_id_map.txt      # speaker id map file when training a multi-speaker fastspeech2\n└── speech_stats.npy        # statistics used to normalize spectrogram when training fastspeech2\n```\n\n\nYou can use the following scripts to synthesize for `${BIN_DIR}/../sentences_mix.txt` using pretrained fastspeech2 and parallel wavegan models.\n`174` means baker speaker, `175` means ljspeech speaker. For other speaker information, please see `speaker_id_map.txt`.\n\n```bash\nsource path.sh\n\nFLAGS_allocator_strategy=naive_best_fit \\\nFLAGS_fraction_of_gpu_memory_to_use=0.01 \\\npython3 ${BIN_DIR}/../synthesize_e2e.py \\\n  --am=fastspeech2_mix \\\n  --am_config=exp/pretrain/fastspeech2_mix_ckpt_1.2.0/default.yaml \\\n  --am_ckpt=exp/pretrain/fastspeech2_mix_ckpt_1.2.0/snapshot_iter_99200.pdz \\\n  --am_stat=exp/pretrain/fastspeech2_mix_ckpt_1.2.0/speech_stats.npy \\\n  --phones_dict=exp/pretrain/fastspeech2_mix_ckpt_1.2.0/phone_id_map.txt \\\n  --speaker_dict=exp/pretrain/fastspeech2_mix_ckpt_1.2.0/speaker_id_map.txt \\\n  --spk_id=174 \\\n  --voc=pwgan_aishell3 \\\n  --voc_config=exp/pretrain/pwg_aishell3_ckpt_0.5/default.yaml \\\n  --voc_ckpt=exp/pretrain/pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n  --voc_stat=exp/pretrain/pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n  --lang=mix \\\n  --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n  --output_dir=exp/default/test_e2e \\\n  --inference_dir=exp/default/inference\n```\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/conf/default.yaml",
    "content": "###########################################################\n#                FEATURE EXTRACTION SETTING               #\n###########################################################\n\nfs: 24000          # sr\nn_fft: 2048        # FFT size (samples).\nn_shift: 300       # Hop size (samples). 12.5ms\nwin_length: 1200   # Window length (samples). 50ms\n                   # If set to null, it will be the same as fft_size.\nwindow: \"hann\"     # Window function.\n\n# Only used for feats_type != raw\n\nfmin: 80           # Minimum frequency of Mel basis.\nfmax: 7600         # Maximum frequency of Mel basis.\nn_mels: 80         # The number of mel basis.\n\n# Only used for the model using pitch features (e.g. FastSpeech2)\nf0min: 80          # Minimum f0 for pitch extraction.\nf0max: 400         # Maximum f0 for pitch extraction.\n\n\n###########################################################\n#                       DATA SETTING                      #\n###########################################################\nbatch_size: 64\nnum_workers: 2\n\n\n###########################################################\n#                       MODEL SETTING                     #\n###########################################################\nmodel:\n    adim: 384         # attention dimension\n    aheads: 2         # number of attention heads\n    elayers: 4        # number of encoder layers\n    eunits: 1536      # number of encoder ff units\n    dlayers: 4        # number of decoder layers\n    dunits: 1536      # number of decoder ff units\n    positionwise_layer_type: conv1d   # type of position-wise layer\n    positionwise_conv_kernel_size: 3  # kernel size of position wise conv layer\n    duration_predictor_layers: 2      # number of layers of duration predictor\n    duration_predictor_chans: 256     # number of channels of duration predictor\n    duration_predictor_kernel_size: 3 # filter size of duration predictor\n    postnet_layers: 5                 # number of layers of postnet\n    postnet_filts: 5                  # filter size of conv layers in postnet\n    postnet_chans: 256                # number of channels of conv layers in postnet\n    use_scaled_pos_enc: True          # whether to use scaled positional encoding\n    encoder_normalize_before: True    # whether to perform layer normalization before the input\n    decoder_normalize_before: True    # whether to perform layer normalization before the input\n    reduction_factor: 1               # reduction factor\n    init_type: xavier_uniform         # initialization type\n    init_enc_alpha: 1.0               # initial value of alpha of encoder scaled position encoding\n    init_dec_alpha: 1.0               # initial value of alpha of decoder scaled position encoding\n    transformer_enc_dropout_rate: 0.2            # dropout rate for transformer encoder layer\n    transformer_enc_positional_dropout_rate: 0.2 # dropout rate for transformer encoder positional encoding\n    transformer_enc_attn_dropout_rate: 0.2       # dropout rate for transformer encoder attention layer\n    transformer_dec_dropout_rate: 0.2            # dropout rate for transformer decoder layer\n    transformer_dec_positional_dropout_rate: 0.2 # dropout rate for transformer decoder positional encoding\n    transformer_dec_attn_dropout_rate: 0.2       # dropout rate for transformer decoder attention layer\n    pitch_predictor_layers: 5                  # number of conv layers in pitch predictor\n    pitch_predictor_chans: 256                 # number of channels of conv layers in pitch predictor\n    pitch_predictor_kernel_size: 5             # kernel size of conv layers in pitch predictor\n    pitch_predictor_dropout: 0.5               # dropout rate in pitch predictor\n    pitch_embed_kernel_size: 1                 # kernel size of conv embedding layer for pitch\n    pitch_embed_dropout: 0.0                   # dropout rate after conv embedding layer for pitch\n    stop_gradient_from_pitch_predictor: True   # whether to stop the gradient from pitch predictor to encoder\n    energy_predictor_layers: 2                 # number of conv layers in energy predictor\n    energy_predictor_chans: 256                # number of channels of conv layers in energy predictor\n    energy_predictor_kernel_size: 3            # kernel size of conv layers in energy predictor\n    energy_predictor_dropout: 0.5              # dropout rate in energy predictor\n    energy_embed_kernel_size: 1                # kernel size of conv embedding layer for energy\n    energy_embed_dropout: 0.0                  # dropout rate after conv embedding layer for energy\n    stop_gradient_from_energy_predictor: False # whether to stop the gradient from energy predictor to encoder\n    spk_embed_dim: 256                         # speaker embedding dimension\n    spk_embed_integration_type: concat         # speaker embedding integration type\n    enable_speaker_classifier: False           # Whether to use speaker classifier module\n    hidden_sc_dim: 256                         # The hidden layer dim of speaker classifier\n    \n\n\n\n###########################################################\n#                       UPDATER SETTING                   #\n###########################################################\nupdater:\n    use_masking: True                 # whether to apply masking for padded part in loss calculation\n    spk_loss_scale: 0.02              # The scales of speaker classifier loss\n\n\n###########################################################\n#                     OPTIMIZER SETTING                   #\n###########################################################\noptimizer:\n    optim: adam               # optimizer type\n    learning_rate: 0.001      # learning rate\n\n###########################################################\n#                     TRAINING SETTING                    #\n###########################################################\nmax_epoch: 200\nnum_snapshots: 5\n\n\n###########################################################\n#                       OTHER SETTING                     #\n###########################################################\nseed: 10086\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/inference.sh",
    "content": "#!/bin/bash\n\ntrain_output_path=$1\n\nstage=0\nstop_stage=0\n\n# voc: pwgan_aishell3\n# the spk_id=174 means baker speaker, default\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_mix \\\n        --voc=pwgan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=mix \\\n        --spk_id=174 \nfi\n\n\n# voc: hifigan_aishell3\n# the spk_id=174 means baker speaker, default\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_mix \\\n        --voc=hifigan_aishell3 \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=mix \\\n        --spk_id=174\nfi\n\n# voc: hifigan_csmsc\n# when speaker is 174 (csmsc), use csmsc's vocoder is better than aishell3's\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../inference.py \\\n        --inference_dir=${train_output_path}/inference \\\n        --am=fastspeech2_mix \\\n        --voc=hifigan_csmsc \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/pd_infer_out \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --lang=mix \\\n        --spk_id=174\nfi\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/mfa_download.sh",
    "content": "#!/bin/bash\n\nexp=exp\nmfa=$exp/mfa\n\nmkdir -p $mfa\n\npushd $mfa\n\nwget -c https://paddlespeech.cdn.bcebos.com/MFA/BZNSYP/with_tone/baker_alignment_tone.tar.gz &\nwget -c https://paddlespeech.cdn.bcebos.com/MFA/LJSpeech-1.1/ljspeech_alignment.tar.gz &\nwget -c https://paddlespeech.cdn.bcebos.com/MFA/AISHELL-3/with_tone/aishell3_alignment_tone.tar.gz &\nwget -c https://paddlespeech.cdn.bcebos.com/MFA/VCTK-Corpus-0.92/vctk_alignment.tar.gz &\nwait\n\npopd\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/model_download.sh",
    "content": "#!/bin/bash\n\nexp=exp\npretrain=$exp/pretrain\n\nmkdir -p $pretrain\n\npushd $pretrain\n\nwget -c https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_1.2.0.zip &\nwget -c https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip &\nwait\n\npopd\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/ort_predict.sh",
    "content": "train_output_path=$1\n\nstage=0\nstop_stage=0\n\n# e2e, synthesize from text\n# voc: pwgan_aishell3\n# the spk_id=174 means baker speaker, default\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_mix \\\n        --voc=pwgan_aishell3 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=4 \\\n        --lang=mix \\\n        --spk_id=174\nfi\n\n\n# voc: hifigan_aishell3\n# the spk_id=174 means baker speaker, default\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_mix \\\n        --voc=hifigan_aishell3 \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=4 \\\n        --lang=mix \\\n        --spk_id=174\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    python3 ${BIN_DIR}/../ort_predict_e2e.py \\\n        --inference_dir=${train_output_path}/inference_onnx \\\n        --am=fastspeech2_mix \\\n        --voc=hifigan_csmsc \\\n        --output_dir=${train_output_path}/onnx_infer_out_e2e \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --device=cpu \\\n        --cpu_threads=4 \\\n        --lang=mix \\\n        --spk_id=174\nfi\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/preprocess.sh",
    "content": "#!/bin/bash\n\nstage=0\nstop_stage=100\n\nconfig_path=$1\ndatasets_root_dir=$2\nmfa_root_dir=$3\n\n# 1. get durations from MFA's result\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    echo \"Generate durations_baker.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=${mfa_root_dir}/baker_alignment_tone \\\n        --output durations_baker.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"Generate durations_ljspeech.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=${mfa_root_dir}/ljspeech_alignment \\\n        --output durations_ljspeech.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"Generate durations_aishell3.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=${mfa_root_dir}/aishell3_alignment_tone \\\n        --output durations_aishell3.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    echo \"Generate durations_vctk.txt from MFA results ...\"\n    python3 ${MAIN_ROOT}/utils/gen_duration_from_textgrid.py \\\n        --inputdir=${mfa_root_dir}/vctk_alignment \\\n        --output durations_vctk.txt \\\n        --config=${config_path}\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # concat duration file\n    echo \"concat durations_baker.txt, durations_ljspeech.txt, durations_aishell3.txt and durations_vctk.txt to durations.txt\"\n    cat durations_baker.txt durations_ljspeech.txt durations_aishell3.txt durations_vctk.txt > durations.txt\nfi\n\n# 2. extract features\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    echo \"Extract baker features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=baker \\\n        --rootdir=${datasets_root_dir}/BZNSYP/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --write_metadata_method=a\nfi\n\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    echo \"Extract ljspeech features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=ljspeech \\\n        --rootdir=${datasets_root_dir}/LJSpeech-1.1/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --write_metadata_method=a\nfi\n\nif [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then\n    echo \"Extract aishell3 features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=aishell3 \\\n        --rootdir=${datasets_root_dir}/data_aishell3/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --write_metadata_method=a\nfi\n\nif [ ${stage} -le 8 ] && [ ${stop_stage} -ge 8 ]; then\n    echo \"Extract vctk features ...\"\n    python3 ${BIN_DIR}/preprocess.py \\\n        --dataset=vctk \\\n        --rootdir=${datasets_root_dir}/VCTK-Corpus-0.92/ \\\n        --dumpdir=dump \\\n        --dur-file=durations.txt \\\n        --config=${config_path} \\\n        --num-cpu=20 \\\n        --cut-sil=True \\\n        --write_metadata_method=a\nfi\n\n\n# 3. get features' stats(mean and std)\nif [ ${stage} -le 9 ] && [ ${stop_stage} -ge 9 ]; then\n    echo \"Get features' stats ...\"\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"speech\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"pitch\"\n\n    python3 ${MAIN_ROOT}/utils/compute_statistics.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --field-name=\"energy\"\nfi\n\n\n# 4. normalize and covert phone/speaker to id, dev and test should use train's stats\nif [ ${stage} -le 10 ] && [ ${stop_stage} -ge 10 ]; then\n    echo \"Normalize ...\"\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/train/raw/metadata.jsonl \\\n        --dumpdir=dump/train/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/dev/raw/metadata.jsonl \\\n        --dumpdir=dump/dev/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\n\n    python3 ${BIN_DIR}/normalize.py \\\n        --metadata=dump/test/raw/metadata.jsonl \\\n        --dumpdir=dump/test/norm \\\n        --speech-stats=dump/train/speech_stats.npy \\\n        --pitch-stats=dump/train/pitch_stats.npy \\\n        --energy-stats=dump/train/energy_stats.npy \\\n        --phones-dict=dump/phone_id_map.txt \\\n        --speaker-dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/synthesize.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# voc: pwgan_aishell3\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_mix \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_aishell3 \\\n        --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n        --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n        --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n\n\n# voc: hifigan_aishell3\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize.py \\\n        --am=fastspeech2_mix \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --test_metadata=dump/test/norm/metadata.jsonl \\\n        --output_dir=${train_output_path}/test \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt\nfi\n"
  },
  {
    "path": "examples/zh_en_tts/tts3/local/synthesize_e2e.sh",
    "content": "#!/bin/bash\n\nconfig_path=$1\ntrain_output_path=$2\nckpt_name=$3\n\nstage=0\nstop_stage=0\n\n# voc: pwgan_aishell3\n# the spk_id=174 means baker speaker, default.\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_mix \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=pwgan_aishell3 \\\n        --voc_config=pwg_aishell3_ckpt_0.5/default.yaml \\\n        --voc_ckpt=pwg_aishell3_ckpt_0.5/snapshot_iter_1000000.pdz \\\n        --voc_stat=pwg_aishell3_ckpt_0.5/feats_stats.npy \\\n        --lang=mix \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=174 \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n# voc: hifigan_aishell3\n# the spk_id=174 means baker speaker, default\n# the spk_id=175 means ljspeech speaker\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    echo \"in hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_mix \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_aishell3 \\\n        --voc_config=hifigan_aishell3_ckpt_0.2.0/default.yaml \\\n        --voc_ckpt=hifigan_aishell3_ckpt_0.2.0/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_aishell3_ckpt_0.2.0/feats_stats.npy \\\n        --lang=mix \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=174 \\\n        --inference_dir=${train_output_path}/inference\nfi\n\n\n# voc: hifigan_csmsc\n# when speaker is 174 (csmsc), use csmsc's vocoder is better than aishell3's\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    echo \"in csmsc's hifigan syn_e2e\"\n    FLAGS_allocator_strategy=naive_best_fit \\\n    FLAGS_fraction_of_gpu_memory_to_use=0.01 \\\n    python3 ${BIN_DIR}/../synthesize_e2e.py \\\n        --am=fastspeech2_mix \\\n        --am_config=${config_path} \\\n        --am_ckpt=${train_output_path}/checkpoints/${ckpt_name} \\\n        --am_stat=dump/train/speech_stats.npy \\\n        --voc=hifigan_csmsc \\\n        --voc_config=hifigan_csmsc_ckpt_0.1.1/default.yaml \\\n        --voc_ckpt=hifigan_csmsc_ckpt_0.1.1/snapshot_iter_2500000.pdz \\\n        --voc_stat=hifigan_csmsc_ckpt_0.1.1/feats_stats.npy \\\n        --lang=mix \\\n        --text=${BIN_DIR}/../../assets/sentences_mix.txt \\\n        --output_dir=${train_output_path}/test_e2e \\\n        --phones_dict=dump/phone_id_map.txt \\\n        --speaker_dict=dump/speaker_id_map.txt \\\n        --spk_id=174 \\\n        --inference_dir=${train_output_path}/inference\nfi"
  },
  {
    "path": "examples/zh_en_tts/tts3/run.sh",
    "content": "#!/bin/bash\n\nset -e\nsource path.sh\n\ngpus=0,1\nstage=0\nstop_stage=100\n\ndatasets_root_dir=./data\nmfa_root_dir=./data/mfa\nconf_path=conf/default.yaml\ntrain_output_path=exp/default\nckpt_name=snapshot_iter_99200.pdz\n\n\n# with the following command, you can choose the stage range you want to run\n# such as `./run.sh --stage 0 --stop-stage 0`\n# this can not be mixed use with `$1`, `$2` ...\nsource ${MAIN_ROOT}/utils/parse_options.sh || exit 1\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # prepare data\n    ./local/preprocess.sh ${conf_path} ${datasets_root_dir} ${mfa_root_dir} || exit -1\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # train model, all `ckpt` under `train_output_path/checkpoints/` dir\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # synthesize, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # synthesize_e2e, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize_e2e.sh ${conf_path} ${train_output_path} ${ckpt_name} || exit -1\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n    # inference with static model, vocoder is pwgan by default\n    CUDA_VISIBLE_DEVICES=${gpus} ./local/inference.sh ${train_output_path} || exit -1\nfi\n\nif [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then\n    # install paddle2onnx\n    pip install paddle2onnx --upgrade\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx fastspeech2_mix\n    # considering the balance between speed and quality, we recommend that you use hifigan as vocoder\n    ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx pwgan_aishell3\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_aishell3\n    # ./local/paddle2onnx.sh ${train_output_path} inference inference_onnx hifigan_csmsc\nfi\n\n# inference with onnxruntime, use fastspeech2 + pwgan by default\nif [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then\n    ./local/ort_predict.sh ${train_output_path}\nfi\n"
  },
  {
    "path": "paddlespeech/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport _locale\n_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])\n"
  },
  {
    "path": "paddlespeech/audio/.gitignore",
    "content": "fc_patch/\n"
  },
  {
    "path": "paddlespeech/audio/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import backends\nfrom . import compliance\nfrom . import datasets\nfrom . import functional\nfrom . import streamdata\nfrom . import text\nfrom . import transform\n"
  },
  {
    "path": "paddlespeech/audio/backends/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .soundfile_backend import depth_convert\nfrom .soundfile_backend import load\nfrom .soundfile_backend import normalize\nfrom .soundfile_backend import resample\nfrom .soundfile_backend import soundfile_load\nfrom .soundfile_backend import soundfile_save\nfrom .soundfile_backend import to_mono\n"
  },
  {
    "path": "paddlespeech/audio/backends/common.py",
    "content": "# Token from https://github.com/pytorch/audio/blob/main/torchaudio/backend/common.py with modification.\n\n\nclass AudioInfo:\n    \"\"\"return of info function.\n\n    This class is used by :ref:`\"sox_io\" backend<sox_io_backend>` and\n    :ref:`\"soundfile\" backend with the new interface<soundfile_backend>`.\n\n    :ivar int sample_rate: Sample rate\n    :ivar int num_frames: The number of frames\n    :ivar int num_channels: The number of channels\n    :ivar int bits_per_sample: The number of bits per sample. This is 0 for lossy formats,\n        or when it cannot be accurately inferred.\n    :ivar str encoding: Audio encoding\n        The values encoding can take are one of the following:\n\n            * ``PCM_S``: Signed integer linear PCM\n            * ``PCM_U``: Unsigned integer linear PCM\n            * ``PCM_F``: Floating point linear PCM\n            * ``FLAC``: Flac, Free Lossless Audio Codec\n            * ``ULAW``: Mu-law\n            * ``ALAW``: A-law\n            * ``MP3`` : MP3, MPEG-1 Audio Layer III\n            * ``VORBIS``: OGG Vorbis\n            * ``AMR_WB``: Adaptive Multi-Rate\n            * ``AMR_NB``: Adaptive Multi-Rate Wideband\n            * ``OPUS``: Opus\n            * ``HTK``: Single channel 16-bit PCM\n            * ``UNKNOWN`` : None of above\n    \"\"\"\n\n    def __init__(\n            self,\n            sample_rate: int,\n            num_frames: int,\n            num_channels: int,\n            bits_per_sample: int,\n            encoding: str, ):\n        self.sample_rate = sample_rate\n        self.num_frames = num_frames\n        self.num_channels = num_channels\n        self.bits_per_sample = bits_per_sample\n        self.encoding = encoding\n\n    def __str__(self):\n        return (f\"AudioMetaData(\"\n                f\"sample_rate={self.sample_rate}, \"\n                f\"num_frames={self.num_frames}, \"\n                f\"num_channels={self.num_channels}, \"\n                f\"bits_per_sample={self.bits_per_sample}, \"\n                f\"encoding={self.encoding}\"\n                f\")\")\n"
  },
  {
    "path": "paddlespeech/audio/backends/soundfile_backend.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport warnings\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport resampy\nimport soundfile\nfrom scipy.io import wavfile\n\nfrom ..utils import depth_convert\nfrom ..utils import ParameterError\nfrom .common import AudioInfo\n\n__all__ = [\n    'resample',\n    'to_mono',\n    'normalize',\n    'save',\n    'soundfile_save',\n    'load',\n    'soundfile_load',\n    'info',\n]\nNORMALMIZE_TYPES = ['linear', 'gaussian']\nMERGE_TYPES = ['ch0', 'ch1', 'random', 'average']\nRESAMPLE_MODES = ['kaiser_best', 'kaiser_fast']\nEPS = 1e-8\n\n\ndef resample(y: np.ndarray,\n             src_sr: int,\n             target_sr: int,\n             mode: str='kaiser_fast') -> np.ndarray:\n    \"\"\"Audio resampling.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        src_sr (int): Source sample rate.\n        target_sr (int): Target sample rate.\n        mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        np.ndarray: `y` resampled to `target_sr`\n    \"\"\"\n\n    if mode == 'kaiser_best':\n        warnings.warn(\n            f'Using resampy in kaiser_best to {src_sr}=>{target_sr}. This function is pretty slow, \\\n        we recommend the mode kaiser_fast in large scale audio training')\n\n    if not isinstance(y, np.ndarray):\n        raise ParameterError(\n            'Only support numpy np.ndarray, but received y in {type(y)}')\n\n    if mode not in RESAMPLE_MODES:\n        raise ParameterError(f'resample mode must in {RESAMPLE_MODES}')\n\n    return resampy.resample(y, src_sr, target_sr, filter=mode)\n\n\ndef to_mono(y: np.ndarray, merge_type: str='average') -> np.ndarray:\n    \"\"\"Convert sterior audio to mono.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        merge_type (str, optional): Merge type to generate mono waveform. Defaults to 'average'.\n\n    Returns:\n        np.ndarray: `y` with mono channel.\n    \"\"\"\n\n    if merge_type not in MERGE_TYPES:\n        raise ParameterError(\n            f'Unsupported merge type {merge_type}, available types are {MERGE_TYPES}'\n        )\n    if y.ndim > 2:\n        raise ParameterError(\n            f'Unsupported audio array,  y.ndim > 2, the shape is {y.shape}')\n    if y.ndim == 1:  # nothing to merge\n        return y\n\n    if merge_type == 'ch0':\n        return y[0]\n    if merge_type == 'ch1':\n        return y[1]\n    if merge_type == 'random':\n        return y[np.random.randint(0, 2)]\n\n    # need to do averaging according to dtype\n\n    if y.dtype == 'float32':\n        y_out = (y[0] + y[1]) * 0.5\n    elif y.dtype == 'int16':\n        y_out = y.astype('int32')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n\n    elif y.dtype == 'int8':\n        y_out = y.astype('int16')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n    else:\n        raise ParameterError(f'Unsupported dtype: {y.dtype}')\n    return y_out\n\n\ndef soundfile_load_(file: os.PathLike,\n                    offset: Optional[float]=None,\n                    dtype: str='int16',\n                    duration: Optional[int]=None) -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio using soundfile library. This function load audio file using libsndfile.\n\n    Args:\n        file (os.PathLike): File of waveform.\n        offset (Optional[float], optional): Offset to the start of waveform. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'int16'.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n    with soundfile.SoundFile(file) as sf_desc:\n        sr_native = sf_desc.samplerate\n        if offset:\n            sf_desc.seek(int(offset * sr_native))\n        if duration is not None:\n            frame_duration = int(duration * sr_native)\n        else:\n            frame_duration = -1\n        y = sf_desc.read(frames=frame_duration, dtype=dtype, always_2d=False).T\n\n    return y, sf_desc.samplerate\n\n\ndef normalize(y: np.ndarray, norm_type: str='linear',\n              mul_factor: float=1.0) -> np.ndarray:\n    \"\"\"Normalize an input audio with additional multiplier.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n\n    Returns:\n        np.ndarray: `y` after normalization.\n    \"\"\"\n\n    if norm_type == 'linear':\n        amax = np.max(np.abs(y))\n        factor = 1.0 / (amax + EPS)\n        y = y * factor * mul_factor\n    elif norm_type == 'gaussian':\n        amean = np.mean(y)\n        astd = np.std(y)\n        astd = max(astd, EPS)\n        y = mul_factor * (y - amean) / astd\n    else:\n        raise NotImplementedError(f'norm_type should be in {NORMALMIZE_TYPES}')\n\n    return y\n\n\ndef soundfile_save(y: np.ndarray, sr: int, file: os.PathLike) -> None:\n    \"\"\"Save audio file to disk. This function saves audio to disk using scipy.io.wavfile, with additional step to convert input waveform to int16.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        sr (int): Sample rate.\n        file (os.PathLike): Path of audio file to save.\n    \"\"\"\n    if not file.endswith('.wav'):\n        raise ParameterError(\n            f'only .wav file supported, but dst file name is: {file}')\n\n    if sr <= 0:\n        raise ParameterError(\n            f'Sample rate should be larger than 0, received sr = {sr}')\n\n    if y.dtype not in ['int16', 'int8']:\n        warnings.warn(\n            f'input data type is {y.dtype}, will convert data to int16 format before saving'\n        )\n        y_out = depth_convert(y, 'int16')\n    else:\n        y_out = y\n\n    wavfile.write(file, sr, y_out)\n\n\ndef soundfile_load(\n        file: os.PathLike,\n        sr: Optional[int]=None,\n        mono: bool=True,\n        merge_type: str='average',  # ch0,ch1,random,average\n        normal: bool=True,\n        norm_type: str='linear',\n        norm_mul_factor: float=1.0,\n        offset: float=0.0,\n        duration: Optional[int]=None,\n        dtype: str='float32',\n        resample_mode: str='kaiser_fast') -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio file from disk. This function loads audio from disk using using audio backend.\n\n    Args:\n        file (os.PathLike): Path of audio file to load.\n        sr (Optional[int], optional): Sample rate of loaded waveform. Defaults to None.\n        mono (bool, optional): Return waveform with mono channel. Defaults to True.\n        merge_type (str, optional): Merge type of multi-channels waveform. Defaults to 'average'.\n        normal (bool, optional): Waveform normalization. Defaults to True.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        norm_mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n        offset (float, optional): Offset to the start of waveform. Defaults to 0.0.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'float32'.\n        resample_mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n\n    y, r = soundfile_load_(file, offset=offset, dtype=dtype, duration=duration)\n\n    if not ((y.ndim == 1 and len(y) > 0) or (y.ndim == 2 and len(y[0]) > 0)):\n        raise ParameterError(f'audio file {file} looks empty')\n\n    if mono:\n        y = to_mono(y, merge_type)\n\n    if sr is not None and sr != r:\n        y = resample(y, r, sr, mode=resample_mode)\n        r = sr\n\n    if normal:\n        y = normalize(y, norm_type, norm_mul_factor)\n    elif dtype in ['int8', 'int16']:\n        # still need to do normalization, before depth conversion\n        y = normalize(y, 'linear', 1.0)\n\n    y = depth_convert(y, dtype)\n    return y, r\n\n\n#The code below is taken from: https://github.com/pytorch/audio/blob/main/torchaudio/backend/soundfile_backend.py, with some modifications.\n\n\ndef _get_subtype_for_wav(dtype: paddle.dtype,\n                         encoding: str,\n                         bits_per_sample: int):\n    if not encoding:\n        if not bits_per_sample:\n            subtype = {\n                paddle.uint8: \"PCM_U8\",\n                paddle.int16: \"PCM_16\",\n                paddle.int32: \"PCM_32\",\n                paddle.float32: \"FLOAT\",\n                paddle.float64: \"DOUBLE\",\n            }.get(dtype)\n            if not subtype:\n                raise ValueError(f\"Unsupported dtype for wav: {dtype}\")\n            return subtype\n        if bits_per_sample == 8:\n            return \"PCM_U8\"\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_S\":\n        if not bits_per_sample:\n            return \"PCM_32\"\n        if bits_per_sample == 8:\n            raise ValueError(\"wav does not support 8-bit signed PCM encoding.\")\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_U\":\n        if bits_per_sample in (None, 8):\n            return \"PCM_U8\"\n        raise ValueError(\"wav only supports 8-bit unsigned PCM encoding.\")\n    if encoding == \"PCM_F\":\n        if bits_per_sample in (None, 32):\n            return \"FLOAT\"\n        if bits_per_sample == 64:\n            return \"DOUBLE\"\n        raise ValueError(\"wav only supports 32/64-bit float PCM encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"wav only supports 8-bit mu-law encoding.\")\n    if encoding == \"ALAW\":\n        if bits_per_sample in (None, 8):\n            return \"ALAW\"\n        raise ValueError(\"wav only supports 8-bit a-law encoding.\")\n    raise ValueError(f\"wav does not support {encoding}.\")\n\n\ndef _get_subtype_for_sphere(encoding: str, bits_per_sample: int):\n    if encoding in (None, \"PCM_S\"):\n        return f\"PCM_{bits_per_sample}\" if bits_per_sample else \"PCM_32\"\n    if encoding in (\"PCM_U\", \"PCM_F\"):\n        raise ValueError(f\"sph does not support {encoding} encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"sph only supports 8-bit for mu-law encoding.\")\n    if encoding == \"ALAW\":\n        return \"ALAW\"\n    raise ValueError(f\"sph does not support {encoding}.\")\n\n\ndef _get_subtype(dtype: paddle.dtype,\n                 format: str,\n                 encoding: str,\n                 bits_per_sample: int):\n    if format == \"wav\":\n        return _get_subtype_for_wav(dtype, encoding, bits_per_sample)\n    if format == \"flac\":\n        if encoding:\n            raise ValueError(\"flac does not support encoding.\")\n        if not bits_per_sample:\n            return \"PCM_16\"\n        if bits_per_sample > 24:\n            raise ValueError(\"flac does not support bits_per_sample > 24.\")\n        return \"PCM_S8\" if bits_per_sample == 8 else f\"PCM_{bits_per_sample}\"\n    if format in (\"ogg\", \"vorbis\"):\n        if encoding or bits_per_sample:\n            raise ValueError(\n                \"ogg/vorbis does not support encoding/bits_per_sample.\")\n        return \"VORBIS\"\n    if format == \"sph\":\n        return _get_subtype_for_sphere(encoding, bits_per_sample)\n    if format in (\"nis\", \"nist\"):\n        return \"PCM_16\"\n    raise ValueError(f\"Unsupported format: {format}\")\n\n\ndef save(\n        filepath: str,\n        src: paddle.Tensor,\n        sample_rate: int,\n        channels_first: bool=True,\n        compression: Optional[float]=None,\n        format: Optional[str]=None,\n        encoding: Optional[str]=None,\n        bits_per_sample: Optional[int]=None, ):\n    \"\"\"Save audio data to file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (str or pathlib.Path): Path to audio file.\n        src (paddle.Tensor): Audio data to save. must be 2D tensor.\n        sample_rate (int): sampling rate\n        channels_first (bool, optional): If ``True``, the given tensor is interpreted as `[channel, time]`,\n            otherwise `[time, channel]`.\n        compression (float of None, optional): Not used.\n            It is here only for interface compatibility reason with \"sox_io\" backend.\n        format (str or None, optional): Override the audio format.\n            When ``filepath`` argument is path-like object, audio format is\n            inferred from file extension. If the file extension is missing or\n            different, you can specify the correct format with this argument.\n\n            When ``filepath`` argument is file-like object,\n            this argument is required.\n\n            Valid values are ``\"wav\"``, ``\"ogg\"``, ``\"vorbis\"``,\n            ``\"flac\"`` and ``\"sph\"``.\n        encoding (str or None, optional): Changes the encoding for supported formats.\n            This argument is effective only for supported formats, such as\n            ``\"wav\"``, ``\"\"flac\"`` and ``\"sph\"``. Valid values are:\n\n                - ``\"PCM_S\"`` (signed integer Linear PCM)\n                - ``\"PCM_U\"`` (unsigned integer Linear PCM)\n                - ``\"PCM_F\"`` (floating point PCM)\n                - ``\"ULAW\"`` (mu-law)\n                - ``\"ALAW\"`` (a-law)\n\n        bits_per_sample (int or None, optional): Changes the bit depth for the\n            supported formats.\n            When ``format`` is one of ``\"wav\"``, ``\"flac\"`` or ``\"sph\"``,\n            you can change the bit depth.\n            Valid values are ``8``, ``16``, ``24``, ``32`` and ``64``.\n\n    Supported formats/encodings/bit depth/compression are:\n\n    ``\"wav\"``\n        - 32-bit floating-point PCM\n        - 32-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 8-bit unsigned integer PCM\n        - 8-bit mu-law\n        - 8-bit a-law\n\n        Note:\n            Default encoding/bit depth is determined by the dtype of\n            the input Tensor.\n\n    ``\"flac\"``\n        - 8-bit\n        - 16-bit (default)\n        - 24-bit\n\n    ``\"ogg\"``, ``\"vorbis\"``\n        - Doesn't accept changing configuration.\n\n    ``\"sph\"``\n        - 8-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 32-bit signed integer PCM (default)\n        - 8-bit mu-law\n        - 8-bit a-law\n        - 16-bit a-law\n        - 24-bit a-law\n        - 32-bit a-law\n\n    \"\"\"\n    if src.ndim != 2:\n        raise ValueError(f\"Expected 2D Tensor, got {src.ndim}D.\")\n    if compression is not None:\n        warnings.warn(\n            '`save` function of \"soundfile\" backend does not support \"compression\" parameter. '\n            \"The argument is silently ignored.\")\n    if hasattr(filepath, \"write\"):\n        if format is None:\n            raise RuntimeError(\n                \"`format` is required when saving to file object.\")\n        ext = format.lower()\n    else:\n        ext = str(filepath).split(\".\")[-1].lower()\n\n    if bits_per_sample not in (None, 8, 16, 24, 32, 64):\n        raise ValueError(\"Invalid bits_per_sample.\")\n    if bits_per_sample == 24:\n        warnings.warn(\n            \"Saving audio with 24 bits per sample might warp samples near -1. \"\n            \"Using 16 bits per sample might be able to avoid this.\")\n    subtype = _get_subtype(src.dtype, ext, encoding, bits_per_sample)\n\n    # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format,\n    # so we extend the extensions manually here\n    if ext in [\"nis\", \"nist\", \"sph\"] and format is None:\n        format = \"NIST\"\n\n    if channels_first:\n        src = src.t()\n\n    soundfile.write(\n        file=filepath,\n        data=src,\n        samplerate=sample_rate,\n        subtype=subtype,\n        format=format)\n\n\n_SUBTYPE2DTYPE = {\n    \"PCM_S8\": \"int8\",\n    \"PCM_U8\": \"uint8\",\n    \"PCM_16\": \"int16\",\n    \"PCM_32\": \"int32\",\n    \"FLOAT\": \"float32\",\n    \"DOUBLE\": \"float64\",\n}\n\n\ndef load(\n        filepath: str,\n        frame_offset: int=0,\n        num_frames: int=-1,\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[paddle.Tensor, int]:\n    \"\"\"Load audio data from file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with\n    ``float32`` dtype and the shape of `[channel, time]`.\n    The samples are normalized to fit in the range of ``[-1.0, 1.0]``.\n\n    When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit\n    signed integer and 8-bit unsigned integer (24-bit signed integer is not supported),\n    by providing ``normalize=False``, this function can return integer Tensor, where the samples\n    are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor\n    for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM.\n\n    ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as\n    ``flac`` and ``mp3``.\n    For these formats, this function always returns ``float32`` Tensor with values normalized to\n    ``[-1.0, 1.0]``.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend.\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        frame_offset (int, optional):\n            Number of frames to skip before start reading data.\n        num_frames (int, optional):\n            Maximum number of frames to read. ``-1`` reads all the remaining samples,\n            starting from ``frame_offset``.\n            This function may return the less number of frames if there is not enough\n            frames in the given file.\n        normalize (bool, optional):\n            When ``True``, this function always return ``float32``, and sample values are\n            normalized to ``[-1.0, 1.0]``.\n            If input file is integer WAV, giving ``False`` will change the resulting Tensor type to\n            integer type.\n            This argument has no effect for formats other than integer WAV type.\n        channels_first (bool, optional):\n            When True, the returned Tensor has dimension `[channel, time]`.\n            Otherwise, the returned Tensor's dimension is `[time, channel]`.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        (paddle.Tensor, int): Resulting Tensor and sample rate.\n            If the input file has integer wav format and normalization is off, then it has\n            integer type, else ``float32`` type. If ``channels_first=True``, it has\n            `[channel, time]` else `[time, channel]`.\n    \"\"\"\n    with soundfile.SoundFile(filepath, \"r\") as file_:\n        if file_.format != \"WAV\" or normalize:\n            dtype = \"float32\"\n        elif file_.subtype not in _SUBTYPE2DTYPE:\n            raise ValueError(f\"Unsupported subtype: {file_.subtype}\")\n        else:\n            dtype = _SUBTYPE2DTYPE[file_.subtype]\n\n        frames = file_._prepare_read(frame_offset, None, num_frames)\n        waveform = file_.read(frames, dtype, always_2d=True)\n        sample_rate = file_.samplerate\n\n    waveform = paddle.to_tensor(waveform)\n    if channels_first:\n        waveform = paddle.transpose(waveform, perm=[1, 0])\n    return waveform, sample_rate\n\n\n# Mapping from soundfile subtype to number of bits per sample.\n# This is mostly heuristical and the value is set to 0 when it is irrelevant\n# (lossy formats) or when it can't be inferred.\n# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard:\n# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony,\n# the default seems to be 8 bits but it can be compressed further to 4 bits.\n# The dict is inspired from\n# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94\n_SUBTYPE_TO_BITS_PER_SAMPLE = {\n    \"PCM_S8\": 8,  # Signed 8 bit data\n    \"PCM_16\": 16,  # Signed 16 bit data\n    \"PCM_24\": 24,  # Signed 24 bit data\n    \"PCM_32\": 32,  # Signed 32 bit data\n    \"PCM_U8\": 8,  # Unsigned 8 bit data (WAV and RAW only)\n    \"FLOAT\": 32,  # 32 bit float data\n    \"DOUBLE\": 64,  # 64 bit float data\n    \"ULAW\": 8,  # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"ALAW\": 8,  # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"IMA_ADPCM\": 0,  # IMA ADPCM.\n    \"MS_ADPCM\": 0,  # Microsoft ADPCM.\n    \"GSM610\":\n    0,  # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate)\n    \"VOX_ADPCM\": 0,  # OKI / Dialogix ADPCM\n    \"G721_32\": 0,  # 32kbs G721 ADPCM encoding.\n    \"G723_24\": 0,  # 24kbs G723 ADPCM encoding.\n    \"G723_40\": 0,  # 40kbs G723 ADPCM encoding.\n    \"DWVW_12\": 12,  # 12 bit Delta Width Variable Word encoding.\n    \"DWVW_16\": 16,  # 16 bit Delta Width Variable Word encoding.\n    \"DWVW_24\": 24,  # 24 bit Delta Width Variable Word encoding.\n    \"DWVW_N\": 0,  # N bit Delta Width Variable Word encoding.\n    \"DPCM_8\": 8,  # 8 bit differential PCM (XI only)\n    \"DPCM_16\": 16,  # 16 bit differential PCM (XI only)\n    \"VORBIS\": 0,  # Xiph Vorbis encoding. (lossy)\n    \"ALAC_16\": 16,  # Apple Lossless Audio Codec (16 bit).\n    \"ALAC_20\": 20,  # Apple Lossless Audio Codec (20 bit).\n    \"ALAC_24\": 24,  # Apple Lossless Audio Codec (24 bit).\n    \"ALAC_32\": 32,  # Apple Lossless Audio Codec (32 bit).\n}\n\n\ndef _get_bit_depth(subtype):\n    if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE:\n        warnings.warn(\n            f\"The {subtype} subtype is unknown to PaddleAudio. As a result, the bits_per_sample \"\n            \"attribute will be set to 0. If you are seeing this warning, please \"\n            \"report by opening an issue on github (after checking for existing/closed ones). \"\n            \"You may otherwise ignore this warning.\")\n    return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0)\n\n\n_SUBTYPE_TO_ENCODING = {\n    \"PCM_S8\": \"PCM_S\",\n    \"PCM_16\": \"PCM_S\",\n    \"PCM_24\": \"PCM_S\",\n    \"PCM_32\": \"PCM_S\",\n    \"PCM_U8\": \"PCM_U\",\n    \"FLOAT\": \"PCM_F\",\n    \"DOUBLE\": \"PCM_F\",\n    \"ULAW\": \"ULAW\",\n    \"ALAW\": \"ALAW\",\n    \"VORBIS\": \"VORBIS\",\n}\n\n\ndef _get_encoding(format: str, subtype: str):\n    if format == \"FLAC\":\n        return \"FLAC\"\n    return _SUBTYPE_TO_ENCODING.get(subtype, \"UNKNOWN\")\n\n\ndef info(filepath: str, format: Optional[str]=None) -> AudioInfo:\n    \"\"\"Get signal information of an audio file.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        AudioInfo: meta data of the given audio.\n\n    \"\"\"\n    sinfo = soundfile.info(filepath)\n    return AudioInfo(\n        sinfo.samplerate,\n        sinfo.frames,\n        sinfo.channels,\n        bits_per_sample=_get_bit_depth(sinfo.subtype),\n        encoding=_get_encoding(sinfo.format, sinfo.subtype), )\n"
  },
  {
    "path": "paddlespeech/audio/compliance/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import kaldi\nfrom . import librosa\n"
  },
  {
    "path": "paddlespeech/audio/compliance/kaldi.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from torchaudio(https://github.com/pytorch/audio)\nimport math\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import Tensor\n\nfrom ..functional import create_dct\nfrom ..functional.window import get_window\n\n__all__ = [\n    'spectrogram',\n    'fbank',\n    'mfcc',\n]\n\n# window types\nHANNING = 'hann'\nHAMMING = 'hamming'\nPOVEY = 'povey'\nRECTANGULAR = 'rect'\nBLACKMAN = 'blackman'\n\n\ndef _get_epsilon(dtype):\n    return paddle.to_tensor(1e-07, dtype=dtype)\n\n\ndef _next_power_of_2(x: int) -> int:\n    return 1 if x == 0 else 2**(x - 1).bit_length()\n\n\ndef _get_strided(waveform: Tensor,\n                 window_size: int,\n                 window_shift: int,\n                 snip_edges: bool) -> Tensor:\n    assert waveform.dim() == 1\n    num_samples = waveform.shape[0]\n\n    if snip_edges:\n        if num_samples < window_size:\n            return paddle.empty((0, 0), dtype=waveform.dtype)\n        else:\n            m = 1 + (num_samples - window_size) // window_shift\n    else:\n        reversed_waveform = paddle.flip(waveform, [0])\n        m = (num_samples + (window_shift // 2)) // window_shift\n        pad = window_size // 2 - window_shift // 2\n        pad_right = reversed_waveform\n        if pad > 0:\n            pad_left = reversed_waveform[-pad:]\n            waveform = paddle.concat((pad_left, waveform, pad_right), axis=0)\n        else:\n            waveform = paddle.concat((waveform[-pad:], pad_right), axis=0)\n\n    return paddle.signal.frame(waveform, window_size, window_shift)[:, :m].T\n\n\ndef _feature_window_function(\n        window_type: str,\n        window_size: int,\n        blackman_coeff: float,\n        dtype: int, ) -> Tensor:\n    if window_type == \"hann\":\n        return get_window('hann', window_size, fftbins=False, dtype=dtype)\n    elif window_type == \"hamming\":\n        return get_window('hamming', window_size, fftbins=False, dtype=dtype)\n    elif window_type == \"povey\":\n        return get_window(\n            'hann', window_size, fftbins=False, dtype=dtype).pow(0.85)\n    elif window_type == \"rect\":\n        return paddle.ones([window_size], dtype=dtype)\n    elif window_type == \"blackman\":\n        a = 2 * math.pi / (window_size - 1)\n        window_function = paddle.arange(window_size, dtype=dtype)\n        return (blackman_coeff - 0.5 * paddle.cos(a * window_function) +\n                (0.5 - blackman_coeff) * paddle.cos(2 * a * window_function)\n                ).astype(dtype)\n    else:\n        raise Exception('Invalid window type ' + window_type)\n\n\ndef _get_log_energy(strided_input: Tensor, epsilon: Tensor,\n                    energy_floor: float) -> Tensor:\n    log_energy = paddle.maximum(strided_input.pow(2).sum(1), epsilon).log()\n    if energy_floor == 0.0:\n        return log_energy\n    return paddle.maximum(\n        log_energy,\n        paddle.to_tensor(math.log(energy_floor), dtype=strided_input.dtype))\n\n\ndef _get_waveform_and_window_properties(\n        waveform: Tensor,\n        channel: int,\n        sr: int,\n        frame_shift: float,\n        frame_length: float,\n        round_to_power_of_two: bool,\n        preemphasis_coefficient: float) -> Tuple[Tensor, int, int, int]:\n    channel = max(channel, 0)\n    assert channel < waveform.shape[0], (\n        'Invalid channel {} for size {}'.format(channel, waveform.shape[0]))\n    waveform = waveform[channel, :]  # size (n)\n    window_shift = int(\n        sr * frame_shift *\n        0.001)  # pass frame_shift and frame_length in milliseconds\n    window_size = int(sr * frame_length * 0.001)\n    padded_window_size = _next_power_of_2(\n        window_size) if round_to_power_of_two else window_size\n\n    assert 2 <= window_size <= len(waveform), (\n        'choose a window size {} that is [2, {}]'.format(window_size,\n                                                         len(waveform)))\n    assert 0 < window_shift, '`window_shift` must be greater than 0'\n    assert padded_window_size % 2 == 0, 'the padded `window_size` must be divisible by two.' \\\n                                        ' use `round_to_power_of_two` or change `frame_length`'\n    assert 0. <= preemphasis_coefficient <= 1.0, '`preemphasis_coefficient` must be between [0,1]'\n    assert sr > 0, '`sr` must be greater than zero'\n    return waveform, window_shift, window_size, padded_window_size\n\n\ndef _get_window(waveform: Tensor,\n                padded_window_size: int,\n                window_size: int,\n                window_shift: int,\n                window_type: str,\n                blackman_coeff: float,\n                snip_edges: bool,\n                raw_energy: bool,\n                energy_floor: float,\n                dither: float,\n                remove_dc_offset: bool,\n                preemphasis_coefficient: float) -> Tuple[Tensor, Tensor]:\n    dtype = waveform.dtype\n    epsilon = _get_epsilon(dtype)\n\n    # (m, window_size)\n    strided_input = _get_strided(waveform, window_size, window_shift,\n                                 snip_edges)\n\n    if dither != 0.0:\n        x = paddle.maximum(epsilon,\n                           paddle.rand(strided_input.shape, dtype=dtype))\n        rand_gauss = paddle.sqrt(-2 * x.log()) * paddle.cos(2 * math.pi * x)\n        strided_input = strided_input + rand_gauss * dither\n\n    if remove_dc_offset:\n        row_means = paddle.mean(strided_input, axis=1).unsqueeze(1)  # (m, 1)\n        strided_input = strided_input - row_means\n\n    if raw_energy:\n        signal_log_energy = _get_log_energy(strided_input, epsilon,\n                                            energy_floor)  # (m)\n\n    if preemphasis_coefficient != 0.0:\n        # npu only support mode=constant right now\n        if paddle.get_device().startswith('npu'):\n            mode = 'constant'\n        else:\n            mode = 'replicate'\n\n        offset_strided_input = paddle.nn.functional.pad(\n            strided_input.unsqueeze(0), (1, 0), data_format='NCL',\n            mode=mode).squeeze(0)  # (m, window_size + 1)\n        strided_input = strided_input - preemphasis_coefficient * offset_strided_input[:, :\n                                                                                       -1]\n\n    window_function = _feature_window_function(\n        window_type, window_size, blackman_coeff,\n        dtype).unsqueeze(0)  # (1, window_size)\n    strided_input = strided_input * window_function  # (m, window_size)\n\n    # (m, padded_window_size)\n    if padded_window_size != window_size:\n        padding_right = padded_window_size - window_size\n        strided_input = paddle.nn.functional.pad(\n            strided_input.unsqueeze(0), (0, padding_right),\n            data_format='NCL',\n            mode='constant',\n            value=0).squeeze(0)\n\n    if not raw_energy:\n        signal_log_energy = _get_log_energy(strided_input, epsilon,\n                                            energy_floor)  # size (m)\n\n    return strided_input, signal_log_energy\n\n\ndef _subtract_column_mean(tensor: Tensor, subtract_mean: bool) -> Tensor:\n    if subtract_mean:\n        col_means = paddle.mean(tensor, axis=0).unsqueeze(0)\n        tensor = tensor - col_means\n    return tensor\n\n\ndef spectrogram(waveform: Tensor,\n                blackman_coeff: float=0.42,\n                channel: int=-1,\n                dither: float=0.0,\n                energy_floor: float=1.0,\n                frame_length: float=25.0,\n                frame_shift: float=10.0,\n                preemphasis_coefficient: float=0.97,\n                raw_energy: bool=True,\n                remove_dc_offset: bool=True,\n                round_to_power_of_two: bool=True,\n                sr: int=16000,\n                snip_edges: bool=True,\n                subtract_mean: bool=False,\n                window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return a spectrogram from a waveform. The output is identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`.\n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that cann't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to \"povey\".\n\n    Returns:\n        Tensor: A spectrogram tensor with shape `(m, padded_window_size // 2 + 1)` where m is the number of frames\n            depends on frame_length and frame_shift.\n    \"\"\"\n    dtype = waveform.dtype\n    epsilon = _get_epsilon(dtype)\n\n    waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties(\n        waveform, channel, sr, frame_shift, frame_length, round_to_power_of_two,\n        preemphasis_coefficient)\n\n    strided_input, signal_log_energy = _get_window(\n        waveform, padded_window_size, window_size, window_shift, window_type,\n        blackman_coeff, snip_edges, raw_energy, energy_floor, dither,\n        remove_dc_offset, preemphasis_coefficient)\n\n    # (m, padded_window_size // 2 + 1, 2)\n    fft = paddle.fft.rfft(strided_input)\n\n    power_spectrum = paddle.maximum(\n        fft.abs().pow(2.), epsilon).log()  # (m, padded_window_size // 2 + 1)\n    power_spectrum[:, 0] = signal_log_energy\n\n    power_spectrum = _subtract_column_mean(power_spectrum, subtract_mean)\n    return power_spectrum\n\n\ndef _inverse_mel_scale_scalar(mel_freq: float) -> float:\n    return 700.0 * (math.exp(mel_freq / 1127.0) - 1.0)\n\n\ndef _inverse_mel_scale(mel_freq: Tensor) -> Tensor:\n    return 700.0 * ((mel_freq / 1127.0).exp() - 1.0)\n\n\ndef _mel_scale_scalar(freq: float) -> float:\n    return 1127.0 * math.log(1.0 + freq / 700.0)\n\n\ndef _mel_scale(freq: Tensor) -> Tensor:\n    return 1127.0 * (1.0 + freq / 700.0).log()\n\n\ndef _vtln_warp_freq(vtln_low_cutoff: float,\n                    vtln_high_cutoff: float,\n                    low_freq: float,\n                    high_freq: float,\n                    vtln_warp_factor: float,\n                    freq: Tensor) -> Tensor:\n    assert vtln_low_cutoff > low_freq, 'be sure to set the vtln_low option higher than low_freq'\n    assert vtln_high_cutoff < high_freq, 'be sure to set the vtln_high option lower than high_freq [or negative]'\n    l = vtln_low_cutoff * max(1.0, vtln_warp_factor)\n    h = vtln_high_cutoff * min(1.0, vtln_warp_factor)\n    scale = 1.0 / vtln_warp_factor\n    Fl = scale * l\n    Fh = scale * h\n    assert l > low_freq and h < high_freq\n    scale_left = (Fl - low_freq) / (l - low_freq)\n    scale_right = (high_freq - Fh) / (high_freq - h)\n    res = paddle.empty_like(freq)\n\n    outside_low_high_freq = paddle.less_than(freq, paddle.to_tensor(low_freq)) \\\n        | paddle.greater_than(freq, paddle.to_tensor(high_freq))\n    before_l = paddle.less_than(freq, paddle.to_tensor(l))\n    before_h = paddle.less_than(freq, paddle.to_tensor(h))\n    after_h = paddle.greater_equal(freq, paddle.to_tensor(h))\n\n    res[after_h] = high_freq + scale_right * (freq[after_h] - high_freq)\n    res[before_h] = scale * freq[before_h]\n    res[before_l] = low_freq + scale_left * (freq[before_l] - low_freq)\n    res[outside_low_high_freq] = freq[outside_low_high_freq]\n\n    return res\n\n\ndef _vtln_warp_mel_freq(vtln_low_cutoff: float,\n                        vtln_high_cutoff: float,\n                        low_freq,\n                        high_freq: float,\n                        vtln_warp_factor: float,\n                        mel_freq: Tensor) -> Tensor:\n    return _mel_scale(\n        _vtln_warp_freq(vtln_low_cutoff, vtln_high_cutoff, low_freq, high_freq,\n                        vtln_warp_factor, _inverse_mel_scale(mel_freq)))\n\n\ndef _get_mel_banks(num_bins: int,\n                   window_length_padded: int,\n                   sample_freq: float,\n                   low_freq: float,\n                   high_freq: float,\n                   vtln_low: float,\n                   vtln_high: float,\n                   vtln_warp_factor: float) -> Tuple[Tensor, Tensor]:\n    assert num_bins > 3, 'Must have at least 3 mel bins'\n    assert window_length_padded % 2 == 0\n    num_fft_bins = window_length_padded / 2\n    nyquist = 0.5 * sample_freq\n\n    if high_freq <= 0.0:\n        high_freq += nyquist\n\n    assert (0.0 <= low_freq < nyquist) and (0.0 < high_freq <= nyquist) and (low_freq < high_freq), \\\n        ('Bad values in options: low-freq {} and high-freq {} vs. nyquist {}'.format(low_freq, high_freq, nyquist))\n\n    fft_bin_width = sample_freq / window_length_padded\n    mel_low_freq = _mel_scale_scalar(low_freq)\n    mel_high_freq = _mel_scale_scalar(high_freq)\n\n    mel_freq_delta = (mel_high_freq - mel_low_freq) / (num_bins + 1)\n\n    if vtln_high < 0.0:\n        vtln_high += nyquist\n\n    assert vtln_warp_factor == 1.0 or ((low_freq < vtln_low < high_freq) and\n                                       (0.0 < vtln_high < high_freq) and (vtln_low < vtln_high)), \\\n        ('Bad values in options: vtln-low {} and vtln-high {}, versus '\n         'low-freq {} and high-freq {}'.format(vtln_low, vtln_high, low_freq, high_freq))\n\n    bin = paddle.arange(num_bins, dtype=paddle.float32).unsqueeze(1)\n    # left_mel = mel_low_freq + bin * mel_freq_delta  # (num_bins, 1)\n    # center_mel = mel_low_freq + (bin + 1.0) * mel_freq_delta  # (num_bins, 1)\n    # right_mel = mel_low_freq + (bin + 2.0) * mel_freq_delta  # (num_bins, 1)\n    left_mel = mel_low_freq + bin * mel_freq_delta  # (num_bins, 1)\n    center_mel = left_mel + mel_freq_delta\n    right_mel = center_mel + mel_freq_delta\n\n    if vtln_warp_factor != 1.0:\n        left_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq, high_freq,\n                                       vtln_warp_factor, left_mel)\n        center_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq,\n                                         high_freq, vtln_warp_factor,\n                                         center_mel)\n        right_mel = _vtln_warp_mel_freq(vtln_low, vtln_high, low_freq,\n                                        high_freq, vtln_warp_factor, right_mel)\n\n    center_freqs = _inverse_mel_scale(center_mel)  # (num_bins)\n    # (1, num_fft_bins)\n    mel = _mel_scale(fft_bin_width * paddle.arange(\n        num_fft_bins, dtype=paddle.float32)).unsqueeze(0)\n\n    # (num_bins, num_fft_bins)\n    up_slope = (mel - left_mel) / (center_mel - left_mel)\n    down_slope = (right_mel - mel) / (right_mel - center_mel)\n\n    if vtln_warp_factor == 1.0:\n        bins = paddle.maximum(\n            paddle.zeros([1]), paddle.minimum(up_slope, down_slope))\n    else:\n        bins = paddle.zeros_like(up_slope)\n        up_idx = paddle.greater_than(mel, left_mel) & paddle.less_than(\n            mel, center_mel)\n        down_idx = paddle.greater_than(mel, center_mel) & paddle.less_than(\n            mel, right_mel)\n        bins[up_idx] = up_slope[up_idx]\n        bins[down_idx] = down_slope[down_idx]\n\n    return bins, center_freqs\n\n\ndef fbank(waveform: Tensor,\n          blackman_coeff: float=0.42,\n          channel: int=-1,\n          dither: float=0.0,\n          energy_floor: float=1.0,\n          frame_length: float=25.0,\n          frame_shift: float=10.0,\n          high_freq: float=0.0,\n          htk_compat: bool=False,\n          low_freq: float=20.0,\n          n_mels: int=23,\n          preemphasis_coefficient: float=0.97,\n          raw_energy: bool=True,\n          remove_dc_offset: bool=True,\n          round_to_power_of_two: bool=True,\n          sr: int=16000,\n          snip_edges: bool=True,\n          subtract_mean: bool=False,\n          use_energy: bool=False,\n          use_log_fbank: bool=True,\n          use_power: bool=True,\n          vtln_high: float=-500.0,\n          vtln_low: float=100.0,\n          vtln_warp: float=1.0,\n          window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return filter banks from a waveform. The output is identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`. `C` is in the range [0,1]. \n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        high_freq (float, optional): The upper cut-off frequency. Defaults to 0.0.\n        htk_compat (bool, optional): Put energy to the last when it is set True. Defaults to False.\n        low_freq (float, optional): The lower cut-off frequency. Defaults to 20.0.\n        n_mels (int, optional): Number of output mel bins. Defaults to 23.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that cann't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        use_energy (bool, optional): Add an dimension with energy of spectrogram to the output. Defaults to False.\n        use_log_fbank (bool, optional): Return log fbank when it is set True. Defaults to True.\n        use_power (bool, optional): Whether to use power instead of magnitude. Defaults to True.\n        vtln_high (float, optional): High inflection point in piecewise linear VTLN warping function. Defaults to -500.0.\n        vtln_low (float, optional): Low inflection point in piecewise linear VTLN warping function. Defaults to 100.0.\n        vtln_warp (float, optional): Vtln warp factor. Defaults to 1.0.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to \"povey\".\n\n    Returns:\n        Tensor: A filter banks tensor with shape `(m, n_mels)`.\n    \"\"\"\n    dtype = waveform.dtype\n\n    waveform, window_shift, window_size, padded_window_size = _get_waveform_and_window_properties(\n        waveform, channel, sr, frame_shift, frame_length, round_to_power_of_two,\n        preemphasis_coefficient)\n\n    strided_input, signal_log_energy = _get_window(\n        waveform, padded_window_size, window_size, window_shift, window_type,\n        blackman_coeff, snip_edges, raw_energy, energy_floor, dither,\n        remove_dc_offset, preemphasis_coefficient)\n\n    # (m, padded_window_size // 2 + 1)\n    spectrum = paddle.fft.rfft(strided_input).abs()\n    if use_power:\n        spectrum = spectrum.pow(2.)\n\n    # (n_mels, padded_window_size // 2)\n    mel_energies, _ = _get_mel_banks(n_mels, padded_window_size, sr, low_freq,\n                                     high_freq, vtln_low, vtln_high, vtln_warp)\n    # mel_energies = mel_energies.astype(dtype)\n    assert mel_energies.dtype == dtype\n\n    # (n_mels, padded_window_size // 2 + 1)\n    mel_energies = paddle.nn.functional.pad(\n        mel_energies.unsqueeze(0), (0, 1),\n        data_format='NCL',\n        mode='constant',\n        value=0).squeeze(0)\n\n    # (m, n_mels)\n    mel_energies = paddle.mm(spectrum, mel_energies.T)\n    if use_log_fbank:\n        mel_energies = paddle.maximum(mel_energies, _get_epsilon(dtype)).log()\n\n    if use_energy:\n        signal_log_energy = signal_log_energy.unsqueeze(1)\n        if htk_compat:\n            mel_energies = paddle.concat(\n                (mel_energies, signal_log_energy), axis=1)\n        else:\n            mel_energies = paddle.concat(\n                (signal_log_energy, mel_energies), axis=1)\n\n    # (m, n_mels + 1)\n    mel_energies = _subtract_column_mean(mel_energies, subtract_mean)\n    return mel_energies\n\n\ndef _get_dct_matrix(n_mfcc: int, n_mels: int) -> Tensor:\n    dct_matrix = create_dct(n_mels, n_mels, 'ortho')\n    dct_matrix[:, 0] = math.sqrt(1 / float(n_mels))\n    dct_matrix = dct_matrix[:, :n_mfcc]  # (n_mels, n_mfcc)\n    return dct_matrix\n\n\ndef _get_lifter_coeffs(n_mfcc: int, cepstral_lifter: float) -> Tensor:\n    i = paddle.arange(n_mfcc)\n    return 1.0 + 0.5 * cepstral_lifter * paddle.sin(math.pi * i /\n                                                    cepstral_lifter)\n\n\ndef mfcc(waveform: Tensor,\n         blackman_coeff: float=0.42,\n         cepstral_lifter: float=22.0,\n         channel: int=-1,\n         dither: float=0.0,\n         energy_floor: float=1.0,\n         frame_length: float=25.0,\n         frame_shift: float=10.0,\n         high_freq: float=0.0,\n         htk_compat: bool=False,\n         low_freq: float=20.0,\n         n_mfcc: int=13,\n         n_mels: int=23,\n         preemphasis_coefficient: float=0.97,\n         raw_energy: bool=True,\n         remove_dc_offset: bool=True,\n         round_to_power_of_two: bool=True,\n         sr: int=16000,\n         snip_edges: bool=True,\n         subtract_mean: bool=False,\n         use_energy: bool=False,\n         vtln_high: float=-500.0,\n         vtln_low: float=100.0,\n         vtln_warp: float=1.0,\n         window_type: str=\"povey\") -> Tensor:\n    \"\"\"Compute and return mel frequency cepstral coefficients from a waveform. The output is\n            identical to Kaldi's.\n\n    Args:\n        waveform (Tensor): A waveform tensor with shape `(C, T)`.\n        blackman_coeff (float, optional): Coefficient for Blackman window.. Defaults to 0.42.\n        cepstral_lifter (float, optional): Scaling of output mfccs. Defaults to 22.0.\n        channel (int, optional): Select the channel of waveform. Defaults to -1.\n        dither (float, optional): Dithering constant . Defaults to 0.0.\n        energy_floor (float, optional): Floor on energy of the output Spectrogram. Defaults to 1.0.\n        frame_length (float, optional): Frame length in milliseconds. Defaults to 25.0.\n        frame_shift (float, optional): Shift between adjacent frames in milliseconds. Defaults to 10.0.\n        high_freq (float, optional): The upper cut-off frequency. Defaults to 0.0.\n        htk_compat (bool, optional): Put energy to the last when it is set True. Defaults to False.\n        low_freq (float, optional): The lower cut-off frequency. Defaults to 20.0.\n        n_mfcc (int, optional): Number of cepstra in MFCC. Defaults to 13.\n        n_mels (int, optional): Number of output mel bins. Defaults to 23.\n        preemphasis_coefficient (float, optional): Preemphasis coefficient for input waveform. Defaults to 0.97.\n        raw_energy (bool, optional): Whether to compute before preemphasis and windowing. Defaults to True.\n        remove_dc_offset (bool, optional): Whether to subtract mean from waveform on frames. Defaults to True.\n        round_to_power_of_two (bool, optional): If True, round window size to power of two by zero-padding input\n            to FFT. Defaults to True.\n        sr (int, optional): Sample rate of input waveform. Defaults to 16000.\n        snip_edges (bool, optional): Drop samples in the end of waveform that cann't fit a signal frame when it\n            is set True. Otherwise performs reflect padding to the end of waveform. Defaults to True.\n        subtract_mean (bool, optional): Whether to subtract mean of feature files. Defaults to False.\n        use_energy (bool, optional): Add an dimension with energy of spectrogram to the output. Defaults to False.\n        vtln_high (float, optional): High inflection point in piecewise linear VTLN warping function. Defaults to -500.0.\n        vtln_low (float, optional): Low inflection point in piecewise linear VTLN warping function. Defaults to 100.0.\n        vtln_warp (float, optional): Vtln warp factor. Defaults to 1.0.\n        window_type (str, optional): Choose type of window for FFT computation. Defaults to POVEY.\n\n    Returns:\n        Tensor: A mel frequency cepstral coefficients tensor with shape `(m, n_mfcc)`.\n    \"\"\"\n    assert n_mfcc <= n_mels, 'n_mfcc cannot be larger than n_mels: %d vs %d' % (\n        n_mfcc, n_mels)\n\n    dtype = waveform.dtype\n\n    # (m, n_mels + use_energy)\n    feature = fbank(\n        waveform=waveform,\n        blackman_coeff=blackman_coeff,\n        channel=channel,\n        dither=dither,\n        energy_floor=energy_floor,\n        frame_length=frame_length,\n        frame_shift=frame_shift,\n        high_freq=high_freq,\n        htk_compat=htk_compat,\n        low_freq=low_freq,\n        n_mels=n_mels,\n        preemphasis_coefficient=preemphasis_coefficient,\n        raw_energy=raw_energy,\n        remove_dc_offset=remove_dc_offset,\n        round_to_power_of_two=round_to_power_of_two,\n        sr=sr,\n        snip_edges=snip_edges,\n        subtract_mean=False,\n        use_energy=use_energy,\n        use_log_fbank=True,\n        use_power=True,\n        vtln_high=vtln_high,\n        vtln_low=vtln_low,\n        vtln_warp=vtln_warp,\n        window_type=window_type)\n\n    if use_energy:\n        # (m)\n        signal_log_energy = feature[:, n_mels if htk_compat else 0]\n        mel_offset = int(not htk_compat)\n        feature = feature[:, mel_offset:(n_mels + mel_offset)]\n\n    # (n_mels, n_mfcc)\n    dct_matrix = _get_dct_matrix(n_mfcc, n_mels).astype(dtype=dtype)\n\n    # (m, n_mfcc)\n    feature = feature.matmul(dct_matrix)\n\n    if cepstral_lifter != 0.0:\n        # (1, n_mfcc)\n        lifter_coeffs = _get_lifter_coeffs(n_mfcc, cepstral_lifter).unsqueeze(0)\n        feature *= lifter_coeffs.astype(dtype=dtype)\n\n    if use_energy:\n        feature[:, 0] = signal_log_energy\n\n    if htk_compat:\n        energy = feature[:, 0].unsqueeze(1)  # (m, 1)\n        feature = feature[:, 1:]  # (m, n_mfcc - 1)\n        if not use_energy:\n            energy *= math.sqrt(2)\n\n        feature = paddle.concat((feature, energy), axis=1)\n\n    feature = _subtract_column_mean(feature, subtract_mean)\n    return feature\n"
  },
  {
    "path": "paddlespeech/audio/compliance/librosa.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from librosa(https://github.com/librosa/librosa)\nimport warnings\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport numpy as np\nimport scipy\nfrom numpy.lib.stride_tricks import as_strided\nfrom scipy import signal\n\nfrom ..utils import depth_convert\nfrom ..utils import ParameterError\n\n__all__ = [\n    # dsp\n    'stft',\n    'mfcc',\n    'hz_to_mel',\n    'mel_to_hz',\n    'mel_frequencies',\n    'power_to_db',\n    'compute_fbank_matrix',\n    'melspectrogram',\n    'spectrogram',\n    'mu_encode',\n    'mu_decode',\n    # augmentation\n    'depth_augment',\n    'spect_augment',\n    'random_crop1d',\n    'random_crop2d',\n    'adaptive_spect_augment',\n]\n\n\ndef _pad_center(data: np.ndarray, size: int, axis: int=-1,\n                **kwargs) -> np.ndarray:\n    \"\"\"Pad an array to a target length along a target axis.\n\n    This differs from `np.pad` by centering the data prior to padding,\n    analogous to `str.center`\n    \"\"\"\n\n    kwargs.setdefault(\"mode\", \"constant\")\n    n = data.shape[axis]\n    lpad = int((size - n) // 2)\n    lengths = [(0, 0)] * data.ndim\n    lengths[axis] = (lpad, int(size - n - lpad))\n\n    if lpad < 0:\n        raise ParameterError((\"Target size ({size:d}) must be \"\n                              \"at least input size ({n:d})\"))\n\n    return np.pad(data, lengths, **kwargs)\n\n\ndef _split_frames(x: np.ndarray,\n                  frame_length: int,\n                  hop_length: int,\n                  axis: int=-1) -> np.ndarray:\n    \"\"\"Slice a data array into (overlapping) frames.\n\n    This function is aligned with librosa.frame\n    \"\"\"\n\n    if not isinstance(x, np.ndarray):\n        raise ParameterError(\n            f\"Input must be of type numpy.ndarray, given type(x)={type(x)}\")\n\n    if x.shape[axis] < frame_length:\n        raise ParameterError(f\"Input is too short (n={x.shape[axis]:d})\"\n                             f\" for frame_length={frame_length:d}\")\n\n    if hop_length < 1:\n        raise ParameterError(f\"Invalid hop_length: {hop_length:d}\")\n\n    if axis == -1 and not x.flags[\"F_CONTIGUOUS\"]:\n        warnings.warn(f\"librosa.util.frame called with axis={axis} \"\n                      \"on a non-contiguous input. This will result in a copy.\")\n        x = np.asfortranarray(x)\n    elif axis == 0 and not x.flags[\"C_CONTIGUOUS\"]:\n        warnings.warn(f\"librosa.util.frame called with axis={axis} \"\n                      \"on a non-contiguous input. This will result in a copy.\")\n        x = np.ascontiguousarray(x)\n\n    n_frames = 1 + (x.shape[axis] - frame_length) // hop_length\n    strides = np.asarray(x.strides)\n\n    new_stride = np.prod(strides[strides > 0] // x.itemsize) * x.itemsize\n\n    if axis == -1:\n        shape = list(x.shape)[:-1] + [frame_length, n_frames]\n        strides = list(strides) + [hop_length * new_stride]\n\n    elif axis == 0:\n        shape = [n_frames, frame_length] + list(x.shape)[1:]\n        strides = [hop_length * new_stride] + list(strides)\n\n    else:\n        raise ParameterError(f\"Frame axis={axis} must be either 0 or -1\")\n\n    return as_strided(x, shape=shape, strides=strides)\n\n\ndef _check_audio(y, mono=True) -> bool:\n    \"\"\"Determine whether a variable contains valid audio data.\n\n    The audio y must be a np.ndarray, ether 1-channel or two channel\n    \"\"\"\n    if not isinstance(y, np.ndarray):\n        raise ParameterError(\"Audio data must be of type numpy.ndarray\")\n    if y.ndim > 2:\n        raise ParameterError(\n            f\"Invalid shape for audio ndim={y.ndim:d}, shape={y.shape}\")\n\n    if mono and y.ndim == 2:\n        raise ParameterError(\n            f\"Invalid shape for mono audio ndim={y.ndim:d}, shape={y.shape}\")\n\n    if (mono and len(y) == 0) or (not mono and y.shape[1] < 0):\n        raise ParameterError(f\"Audio is empty ndim={y.ndim:d}, shape={y.shape}\")\n\n    if not np.issubdtype(y.dtype, np.floating):\n        raise ParameterError(\"Audio data must be floating-point\")\n\n    if not np.isfinite(y).all():\n        raise ParameterError(\"Audio buffer is not finite everywhere\")\n\n    return True\n\n\ndef hz_to_mel(frequencies: Union[float, List[float], np.ndarray],\n              htk: bool=False) -> np.ndarray:\n    \"\"\"Convert Hz to Mels.\n\n    Args:\n        frequencies (Union[float, List[float], np.ndarray]): Frequencies in Hz.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Frequency in mels.\n    \"\"\"\n    freq = np.asanyarray(frequencies)\n\n    if htk:\n        return 2595.0 * np.log10(1.0 + freq / 700.0)\n\n    # Fill in the linear part\n    f_min = 0.0\n    f_sp = 200.0 / 3\n\n    mels = (freq - f_min) / f_sp\n\n    # Fill in the log-scale part\n\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = np.log(6.4) / 27.0  # step size for log region\n\n    if freq.ndim:\n        # If we have array data, vectorize\n        log_t = freq >= min_log_hz\n        mels[log_t] = min_log_mel + \\\n            np.log(freq[log_t] / min_log_hz) / logstep\n    elif freq >= min_log_hz:\n        # If we have scalar data, heck directly\n        mels = min_log_mel + np.log(freq / min_log_hz) / logstep\n\n    return mels\n\n\ndef mel_to_hz(mels: Union[float, List[float], np.ndarray],\n              htk: int=False) -> np.ndarray:\n    \"\"\"Convert mel bin numbers to frequencies.\n\n    Args:\n        mels (Union[float, List[float], np.ndarray]): Frequency in mels.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Frequencies in Hz.\n    \"\"\"\n    mel_array = np.asanyarray(mels)\n\n    if htk:\n        return 700.0 * (10.0**(mel_array / 2595.0) - 1.0)\n\n    # Fill in the linear scale\n    f_min = 0.0\n    f_sp = 200.0 / 3\n    freqs = f_min + f_sp * mel_array\n\n    # And now the nonlinear scale\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = np.log(6.4) / 27.0  # step size for log region\n\n    if mel_array.ndim:\n        # If we have vector data, vectorize\n        log_t = mel_array >= min_log_mel\n        freqs[log_t] = min_log_hz * \\\n            np.exp(logstep * (mel_array[log_t] - min_log_mel))\n    elif mel_array >= min_log_mel:\n        # If we have scalar data, check directly\n        freqs = min_log_hz * np.exp(logstep * (mel_array - min_log_mel))\n\n    return freqs\n\n\ndef mel_frequencies(n_mels: int=128,\n                    fmin: float=0.0,\n                    fmax: float=11025.0,\n                    htk: bool=False) -> np.ndarray:\n    \"\"\"Compute mel frequencies.\n\n    Args:\n        n_mels (int, optional): Number of mel bins. Defaults to 128.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (float, optional): Maximum frequency in Hz. Defaults to 11025.0.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        np.ndarray: Vector of n_mels frequencies in Hz with shape `(n_mels,)`.\n    \"\"\"\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    min_mel = hz_to_mel(fmin, htk=htk)\n    max_mel = hz_to_mel(fmax, htk=htk)\n\n    mels = np.linspace(min_mel, max_mel, n_mels)\n\n    return mel_to_hz(mels, htk=htk)\n\n\ndef fft_frequencies(sr: int, n_fft: int) -> np.ndarray:\n    \"\"\"Compute fourier frequencies.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): FFT size.\n\n    Returns:\n        np.ndarray: FFT frequencies in Hz with shape `(n_fft//2 + 1,)`.\n    \"\"\"\n    return np.linspace(0, float(sr) / 2, int(1 + n_fft // 2), endpoint=True)\n\n\ndef compute_fbank_matrix(sr: int,\n                         n_fft: int,\n                         n_mels: int=128,\n                         fmin: float=0.0,\n                         fmax: Optional[float]=None,\n                         htk: bool=False,\n                         norm: str=\"slaney\",\n                         dtype: type=np.float32) -> np.ndarray:\n    \"\"\"Compute fbank matrix.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): FFT size.\n        n_mels (int, optional): Number of mel bins. Defaults to 128.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        norm (str, optional): Type of normalization. Defaults to \"slaney\".\n        dtype (type, optional): Data type. Defaults to np.float32.\n\n\n    Returns:\n        np.ndarray: Mel transform matrix with shape `(n_mels, n_fft//2 + 1)`.\n    \"\"\"\n    if norm != \"slaney\":\n        raise ParameterError('norm must set to slaney')\n\n    if fmax is None:\n        fmax = float(sr) / 2\n\n    # Initialize the weights\n    n_mels = int(n_mels)\n    weights = np.zeros((n_mels, int(1 + n_fft // 2)), dtype=dtype)\n\n    # Center freqs of each FFT bin\n    fftfreqs = fft_frequencies(sr=sr, n_fft=n_fft)\n\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    mel_f = mel_frequencies(n_mels + 2, fmin=fmin, fmax=fmax, htk=htk)\n\n    fdiff = np.diff(mel_f)\n    ramps = np.subtract.outer(mel_f, fftfreqs)\n\n    for i in range(n_mels):\n        # lower and upper slopes for all bins\n        lower = -ramps[i] / fdiff[i]\n        upper = ramps[i + 2] / fdiff[i + 1]\n\n        # .. then intersect them with each other and zero\n        weights[i] = np.maximum(0, np.minimum(lower, upper))\n\n    if norm == \"slaney\":\n        # Slaney-style mel is scaled to be approx constant energy per channel\n        enorm = 2.0 / (mel_f[2:n_mels + 2] - mel_f[:n_mels])\n        weights *= enorm[:, np.newaxis]\n\n    # Only check weights if f_mel[0] is positive\n    if not np.all((mel_f[:-2] == 0) | (weights.max(axis=1) > 0)):\n        # This means we have an empty channel somewhere\n        warnings.warn(\"Empty filters detected in mel frequency basis. \"\n                      \"Some channels will produce empty responses. \"\n                      \"Try increasing your sampling rate (and fmax) or \"\n                      \"reducing n_mels.\")\n\n    return weights\n\n\ndef stft(x: np.ndarray,\n         n_fft: int=2048,\n         hop_length: Optional[int]=None,\n         win_length: Optional[int]=None,\n         window: str=\"hann\",\n         center: bool=True,\n         dtype: type=np.complex64,\n         pad_mode: str=\"reflect\") -> np.ndarray:\n    \"\"\"Short-time Fourier transform (STFT).\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        n_fft (int, optional): FFT size. Defaults to 2048.\n        hop_length (Optional[int], optional): Number of steps to advance between adjacent windows. Defaults to None.\n        win_length (Optional[int], optional): The size of window. Defaults to None.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        dtype (type, optional): Data type of STFT results. Defaults to np.complex64.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n\n    Returns:\n        np.ndarray: The complex STFT output with shape `(n_fft//2 + 1, num_frames)`.\n    \"\"\"\n    _check_audio(x)\n\n    # By default, use the entire frame\n    if win_length is None:\n        win_length = n_fft\n\n    # Set the default hop, if it's not already specified\n    if hop_length is None:\n        hop_length = int(win_length // 4)\n\n    fft_window = signal.get_window(window, win_length, fftbins=True)\n\n    # Pad the window out to n_fft size\n    fft_window = _pad_center(fft_window, n_fft)\n\n    # Reshape so that the window can be broadcast\n    fft_window = fft_window.reshape((-1, 1))\n\n    # Pad the time series so that frames are centered\n    if center:\n        if n_fft > x.shape[-1]:\n            warnings.warn(\n                f\"n_fft={n_fft} is too small for input signal of length={x.shape[-1]}\"\n            )\n        x = np.pad(x, int(n_fft // 2), mode=pad_mode)\n\n    elif n_fft > x.shape[-1]:\n        raise ParameterError(\n            f\"n_fft={n_fft} is too small for input signal of length={x.shape[-1]}\"\n        )\n\n    # Window the time series.\n    x_frames = _split_frames(x, frame_length=n_fft, hop_length=hop_length)\n    # Pre-allocate the STFT matrix\n    stft_matrix = np.empty(\n        (int(1 + n_fft // 2), x_frames.shape[1]), dtype=dtype, order=\"F\")\n    fft = np.fft  # use numpy fft as default\n    # Constrain STFT block sizes to 256 KB\n    MAX_MEM_BLOCK = 2**8 * 2**10\n    # how many columns can we fit within MAX_MEM_BLOCK?\n    n_columns = MAX_MEM_BLOCK // (stft_matrix.shape[0] * stft_matrix.itemsize)\n    n_columns = max(n_columns, 1)\n\n    for bl_s in range(0, stft_matrix.shape[1], n_columns):\n        bl_t = min(bl_s + n_columns, stft_matrix.shape[1])\n        stft_matrix[:, bl_s:bl_t] = fft.rfft(\n            fft_window * x_frames[:, bl_s:bl_t], axis=0)\n\n    return stft_matrix\n\n\ndef power_to_db(spect: np.ndarray,\n                ref: float=1.0,\n                amin: float=1e-10,\n                top_db: Optional[float]=80.0) -> np.ndarray:\n    \"\"\"Convert a power spectrogram (amplitude squared) to decibel (dB) units. The function computes the scaling `10 * log10(x / ref)` in a numerically stable way.\n\n    Args:\n        spect (np.ndarray): STFT power spectrogram of an input waveform.\n        ref (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to 80.0.\n\n    Returns:\n        np.ndarray: Power spectrogram in db scale.\n    \"\"\"\n    spect = np.asarray(spect)\n\n    if amin <= 0:\n        raise ParameterError(\"amin must be strictly positive\")\n\n    if np.issubdtype(spect.dtype, np.complexfloating):\n        warnings.warn(\n            \"power_to_db was called on complex input so phase \"\n            \"information will be discarded. To suppress this warning, \"\n            \"call power_to_db(np.abs(D)**2) instead.\")\n        magnitude = np.abs(spect)\n    else:\n        magnitude = spect\n\n    if callable(ref):\n        # User supplied a function to calculate reference power\n        ref_value = ref(magnitude)\n    else:\n        ref_value = np.abs(ref)\n\n    log_spec = 10.0 * np.log10(np.maximum(amin, magnitude))\n    log_spec -= 10.0 * np.log10(np.maximum(amin, ref_value))\n\n    if top_db is not None:\n        if top_db < 0:\n            raise ParameterError(\"top_db must be non-negative\")\n        log_spec = np.maximum(log_spec, log_spec.max() - top_db)\n\n    return log_spec\n\n\ndef mfcc(x: np.ndarray,\n         sr: int=16000,\n         spect: Optional[np.ndarray]=None,\n         n_mfcc: int=20,\n         dct_type: int=2,\n         norm: str=\"ortho\",\n         lifter: int=0,\n         **kwargs) -> np.ndarray:\n    \"\"\"Mel-frequency cepstral coefficients (MFCCs)\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        spect (Optional[np.ndarray], optional): Input log-power Mel spectrogram. Defaults to None.\n        n_mfcc (int, optional): Number of cepstra in MFCC. Defaults to 20.\n        dct_type (int, optional): Discrete cosine transform (DCT) type. Defaults to 2.\n        norm (str, optional): Type of normalization. Defaults to \"ortho\".\n        lifter (int, optional): Cepstral filtering. Defaults to 0.\n\n    Returns:\n        np.ndarray: Mel frequency cepstral coefficients array with shape `(n_mfcc, num_frames)`.\n    \"\"\"\n    if spect is None:\n        spect = melspectrogram(x, sr=sr, **kwargs)\n\n    M = scipy.fftpack.dct(spect, axis=0, type=dct_type, norm=norm)[:n_mfcc]\n\n    if lifter > 0:\n        factor = np.sin(np.pi * np.arange(1, 1 + n_mfcc, dtype=M.dtype) /\n                        lifter)\n        return M * factor[:, np.newaxis]\n    elif lifter == 0:\n        return M\n    else:\n        raise ParameterError(\n            f\"MFCC lifter={lifter} must be a non-negative number\")\n\n\ndef melspectrogram(x: np.ndarray,\n                   sr: int=16000,\n                   window_size: int=512,\n                   hop_length: int=320,\n                   n_mels: int=64,\n                   fmin: float=50.0,\n                   fmax: Optional[float]=None,\n                   window: str='hann',\n                   center: bool=True,\n                   pad_mode: str='reflect',\n                   power: float=2.0,\n                   to_db: bool=True,\n                   ref: float=1.0,\n                   amin: float=1e-10,\n                   top_db: Optional[float]=None) -> np.ndarray:\n    \"\"\"Compute mel-spectrogram.\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        window_size (int, optional): Size of FFT and window length. Defaults to 512.\n        hop_length (int, optional): Number of steps to advance between adjacent windows. Defaults to 320.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        fmin (float, optional): Minimum frequency in Hz. Defaults to 50.0.\n        fmax (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n        power (float, optional): Exponent for the magnitude melspectrogram. Defaults to 2.0.\n        to_db (bool, optional): Enable db scale. Defaults to True.\n        ref (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to None.\n\n    Returns:\n        np.ndarray: The mel-spectrogram in power scale or db scale with shape `(n_mels, num_frames)`.\n    \"\"\"\n    _check_audio(x, mono=True)\n    if len(x) <= 0:\n        raise ParameterError('The input waveform is empty')\n\n    if fmax is None:\n        fmax = sr // 2\n    if fmin < 0 or fmin >= fmax:\n        raise ParameterError('fmin and fmax must statisfy 0<fmin<fmax')\n\n    s = stft(\n        x,\n        n_fft=window_size,\n        hop_length=hop_length,\n        win_length=window_size,\n        window=window,\n        center=center,\n        pad_mode=pad_mode)\n\n    spect_power = np.abs(s)**power\n    fb_matrix = compute_fbank_matrix(\n        sr=sr, n_fft=window_size, n_mels=n_mels, fmin=fmin, fmax=fmax)\n    mel_spect = np.matmul(fb_matrix, spect_power)\n    if to_db:\n        return power_to_db(mel_spect, ref=ref, amin=amin, top_db=top_db)\n    else:\n        return mel_spect\n\n\ndef spectrogram(x: np.ndarray,\n                sr: int=16000,\n                window_size: int=512,\n                hop_length: int=320,\n                window: str='hann',\n                center: bool=True,\n                pad_mode: str='reflect',\n                power: float=2.0) -> np.ndarray:\n    \"\"\"Compute spectrogram.\n\n    Args:\n        x (np.ndarray): Input waveform in one dimension.\n        sr (int, optional): Sample rate. Defaults to 16000.\n        window_size (int, optional): Size of FFT and window length. Defaults to 512.\n        hop_length (int, optional): Number of steps to advance between adjacent windows. Defaults to 320.\n        window (str, optional): A string of window specification. Defaults to \"hann\".\n        center (bool, optional): Whether to pad `x` to make that the :math:`t \\times hop\\\\_length` at the center of `t`-th frame. Defaults to True.\n        pad_mode (str, optional): Choose padding pattern when `center` is `True`. Defaults to \"reflect\".\n        power (float, optional): Exponent for the magnitude melspectrogram. Defaults to 2.0.\n\n    Returns:\n        np.ndarray: The STFT spectrogram in power scale `(n_fft//2 + 1, num_frames)`.\n    \"\"\"\n\n    s = stft(\n        x,\n        n_fft=window_size,\n        hop_length=hop_length,\n        win_length=window_size,\n        window=window,\n        center=center,\n        pad_mode=pad_mode)\n\n    return np.abs(s)**power\n\n\ndef mu_encode(x: np.ndarray, mu: int=255, quantized: bool=True) -> np.ndarray:\n    \"\"\"Mu-law encoding. Encode waveform based on mu-law companding. When quantized is True, the result will be converted to integer in range `[0,mu-1]`. Otherwise, the resulting waveform is in range `[-1,1]`.\n\n    Args:\n        x (np.ndarray): The input waveform to encode.\n        mu (int, optional): The endoceding parameter. Defaults to 255.\n        quantized (bool, optional): If `True`, quantize the encoded values into `1 + mu` distinct integer values. Defaults to True.\n\n    Returns:\n        np.ndarray: The mu-law encoded waveform.\n    \"\"\"\n    mu = 255\n    y = np.sign(x) * np.log1p(mu * np.abs(x)) / np.log1p(mu)\n    if quantized:\n        y = np.floor((y + 1) / 2 * mu + 0.5)  # convert to [0 , mu-1]\n    return y\n\n\ndef mu_decode(y: np.ndarray, mu: int=255, quantized: bool=True) -> np.ndarray:\n    \"\"\"Mu-law decoding. Compute the mu-law decoding given an input code. It assumes that the input `y` is in range `[0,mu-1]` when quantize is True and `[-1,1]` otherwise.\n\n    Args:\n        y (np.ndarray): The encoded waveform.\n        mu (int, optional): The endoceding parameter. Defaults to 255.\n        quantized (bool, optional): If `True`, the input is assumed to be quantized to `1 + mu` distinct integer values. Defaults to True.\n\n    Returns:\n        np.ndarray: The mu-law decoded waveform.\n    \"\"\"\n    if mu < 1:\n        raise ParameterError('mu is typically set as 2**k-1, k=1, 2, 3,...')\n\n    mu = mu - 1\n    if quantized:  # undo the quantization\n        y = y * 2 / mu - 1\n    x = np.sign(y) / mu * ((1 + mu)**np.abs(y) - 1)\n    return x\n\n\ndef _randint(high: int) -> int:\n    \"\"\"Generate one random integer in range [0 high)\n\n     This is a helper function for random data augmentation\n    \"\"\"\n    return int(np.random.randint(0, high=high))\n\n\ndef depth_augment(y: np.ndarray,\n                  choices: List=['int8', 'int16'],\n                  probs: List[float]=[0.5, 0.5]) -> np.ndarray:\n    \"\"\" Audio depth augmentation. Do audio depth augmentation to simulate the distortion brought by quantization.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        choices (List, optional): A list of data type to depth conversion. Defaults to ['int8', 'int16'].\n        probs (List[float], optional): Probabilities to depth conversion. Defaults to [0.5, 0.5].\n\n    Returns:\n        np.ndarray: The augmented waveform.\n    \"\"\"\n    assert len(probs) == len(\n        choices\n    ), 'number of choices {} must be equal to size of probs {}'.format(\n        len(choices), len(probs))\n    depth = np.random.choice(choices, p=probs)\n    src_depth = y.dtype\n    y1 = depth_convert(y, depth)\n    y2 = depth_convert(y1, src_depth)\n\n    return y2\n\n\ndef adaptive_spect_augment(spect: np.ndarray,\n                           tempo_axis: int=0,\n                           level: float=0.1) -> np.ndarray:\n    \"\"\"Do adaptive spectrogram augmentation. The level of the augmentation is govern by the parameter level, ranging from 0 to 1, with 0 represents no augmentation.\n\n    Args:\n        spect (np.ndarray): Input spectrogram.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n        level (float, optional): The level factor of masking. Defaults to 0.1.\n\n    Returns:\n        np.ndarray: The augmented spectrogram.\n    \"\"\"\n    assert spect.ndim == 2., 'only supports 2d tensor or numpy array'\n    if tempo_axis == 0:\n        nt, nf = spect.shape\n    else:\n        nf, nt = spect.shape\n\n    time_mask_width = int(nt * level * 0.5)\n    freq_mask_width = int(nf * level * 0.5)\n\n    num_time_mask = int(10 * level)\n    num_freq_mask = int(10 * level)\n\n    if tempo_axis == 0:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[start:start + time_mask_width, :] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[:, start:start + freq_mask_width] = 0\n    else:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[:, start:start + time_mask_width] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[start:start + freq_mask_width, :] = 0\n\n    return spect\n\n\ndef spect_augment(spect: np.ndarray,\n                  tempo_axis: int=0,\n                  max_time_mask: int=3,\n                  max_freq_mask: int=3,\n                  max_time_mask_width: int=30,\n                  max_freq_mask_width: int=20) -> np.ndarray:\n    \"\"\"Do spectrogram augmentation in both time and freq axis.\n\n    Args:\n        spect (np.ndarray): Input spectrogram.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n        max_time_mask (int, optional): Maximum number of time masking. Defaults to 3.\n        max_freq_mask (int, optional): Maximum number of frequency masking. Defaults to 3.\n        max_time_mask_width (int, optional): Maximum width of time masking. Defaults to 30.\n        max_freq_mask_width (int, optional): Maximum width of frequency masking. Defaults to 20.\n\n    Returns:\n        np.ndarray: The augmented spectrogram.\n    \"\"\"\n    assert spect.ndim == 2., 'only supports 2d tensor or numpy array'\n    if tempo_axis == 0:\n        nt, nf = spect.shape\n    else:\n        nf, nt = spect.shape\n\n    num_time_mask = _randint(max_time_mask)\n    num_freq_mask = _randint(max_freq_mask)\n\n    time_mask_width = _randint(max_time_mask_width)\n    freq_mask_width = _randint(max_freq_mask_width)\n\n    if tempo_axis == 0:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[start:start + time_mask_width, :] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[:, start:start + freq_mask_width] = 0\n    else:\n        for _ in range(num_time_mask):\n            start = _randint(nt - time_mask_width)\n            spect[:, start:start + time_mask_width] = 0\n        for _ in range(num_freq_mask):\n            start = _randint(nf - freq_mask_width)\n            spect[start:start + freq_mask_width, :] = 0\n\n    return spect\n\n\ndef random_crop1d(y: np.ndarray, crop_len: int) -> np.ndarray:\n    \"\"\" Random cropping on a input waveform.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D.\n        crop_len (int): Length of waveform to crop.\n\n    Returns:\n        np.ndarray: The cropped waveform.\n    \"\"\"\n    if y.ndim != 1:\n        'only accept 1d tensor or numpy array'\n    n = len(y)\n    idx = _randint(n - crop_len)\n    return y[idx:idx + crop_len]\n\n\ndef random_crop2d(s: np.ndarray, crop_len: int,\n                  tempo_axis: int=0) -> np.ndarray:\n    \"\"\" Random cropping on a spectrogram.\n\n    Args:\n        s (np.ndarray): Input spectrogram in 2D.\n        crop_len (int): Length of spectrogram to crop.\n        tempo_axis (int, optional): Indicate the tempo axis. Defaults to 0.\n\n    Returns:\n        np.ndarray: The cropped spectrogram.\n    \"\"\"\n    if tempo_axis >= s.ndim:\n        raise ParameterError('axis out of range')\n\n    n = s.shape[tempo_axis]\n    idx = _randint(high=n - crop_len)\n    sli = [slice(None) for i in range(s.ndim)]\n    sli[tempo_axis] = slice(idx, idx + crop_len)\n    out = s[tuple(sli)]\n    return out\n"
  },
  {
    "path": "paddlespeech/audio/datasets/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .esc50 import ESC50\nfrom .voxceleb import VoxCeleb\n"
  },
  {
    "path": "paddlespeech/audio/datasets/dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nimport numpy as np\nimport paddle\n\nfrom ..backends.soundfile_backend import soundfile_load as load_audio\nfrom ..compliance.kaldi import fbank as kaldi_fbank\nfrom ..compliance.kaldi import mfcc as kaldi_mfcc\nfrom ..compliance.librosa import melspectrogram\nfrom ..compliance.librosa import mfcc\n\nfeat_funcs = {\n    'raw': None,\n    'melspectrogram': melspectrogram,\n    'mfcc': mfcc,\n    'kaldi_fbank': kaldi_fbank,\n    'kaldi_mfcc': kaldi_mfcc,\n}\n\n\nclass AudioClassificationDataset(paddle.io.Dataset):\n    \"\"\"\n    Base class of audio classification dataset.\n    \"\"\"\n\n    def __init__(self,\n                 files: List[str],\n                 labels: List[int],\n                 feat_type: str='raw',\n                 sample_rate: int=None,\n                 **kwargs):\n        \"\"\"\n        Ags:\n            files (:obj:`List[str]`): A list of absolute path of audio files.\n            labels (:obj:`List[int]`): Labels of audio files.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        super(AudioClassificationDataset, self).__init__()\n\n        if feat_type not in feat_funcs.keys():\n            raise RuntimeError(\n                f\"Unknown feat_type: {feat_type}, it must be one in {list(feat_funcs.keys())}\"\n            )\n\n        self.files = files\n        self.labels = labels\n\n        self.feat_type = feat_type\n        self.sample_rate = sample_rate\n        self.feat_config = kwargs  # Pass keyword arguments to customize feature config\n\n    def _get_data(self, input_file: str):\n        raise NotImplementedError\n\n    def _convert_to_record(self, idx):\n        file, label = self.files[idx], self.labels[idx]\n\n        if self.sample_rate is None:\n            waveform, sample_rate = load_audio(file)\n        else:\n            waveform, sample_rate = load_audio(file, sr=self.sample_rate)\n\n        feat_func = feat_funcs[self.feat_type]\n\n        record = {}\n        if self.feat_type in ['kaldi_fbank', 'kaldi_mfcc']:\n            waveform = paddle.to_tensor(waveform).unsqueeze(0)  # (C, T)\n            record['feat'] = feat_func(\n                waveform=waveform, sr=self.sample_rate, **self.feat_config)\n        else:\n            record['feat'] = feat_func(\n                waveform, sample_rate,\n                **self.feat_config) if feat_func else waveform\n        record['label'] = label\n        return record\n\n    def __getitem__(self, idx):\n        record = self._convert_to_record(idx)\n        if self.feat_type in ['kaldi_fbank', 'kaldi_mfcc']:\n            return self.keys[idx], record['feat'], record['label']\n        else:\n            return np.array(record['feat']).transpose(), np.array(\n                record['label'], dtype=np.int64)\n\n    def __len__(self):\n        return len(self.files)\n"
  },
  {
    "path": "paddlespeech/audio/datasets/esc50.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport os\nfrom typing import List\nfrom typing import Tuple\n\nfrom ...utils.env import DATA_HOME\nfrom ..utils.download import download_and_decompress\nfrom .dataset import AudioClassificationDataset\n\n__all__ = ['ESC50']\n\n\nclass ESC50(AudioClassificationDataset):\n    \"\"\"\n    The ESC-50 dataset is a labeled collection of 2000 environmental audio recordings\n    suitable for benchmarking methods of environmental sound classification. The dataset\n    consists of 5-second-long recordings organized into 50 semantical classes (with\n    40 examples per class)\n\n    Reference:\n        ESC: Dataset for Environmental Sound Classification\n        http://dx.doi.org/10.1145/2733373.2806390\n    \"\"\"\n\n    archieves = [\n        {\n            'url':\n            'https://paddleaudio.bj.bcebos.com/datasets/ESC-50-master.zip',\n            'md5': '7771e4b9d86d0945acce719c7a59305a',\n        },\n    ]\n    label_list = [\n        # Animals\n        'Dog',\n        'Rooster',\n        'Pig',\n        'Cow',\n        'Frog',\n        'Cat',\n        'Hen',\n        'Insects (flying)',\n        'Sheep',\n        'Crow',\n        # Natural soundscapes & water sounds\n        'Rain',\n        'Sea waves',\n        'Crackling fire',\n        'Crickets',\n        'Chirping birds',\n        'Water drops',\n        'Wind',\n        'Pouring water',\n        'Toilet flush',\n        'Thunderstorm',\n        # Human, non-speech sounds\n        'Crying baby',\n        'Sneezing',\n        'Clapping',\n        'Breathing',\n        'Coughing',\n        'Footsteps',\n        'Laughing',\n        'Brushing teeth',\n        'Snoring',\n        'Drinking, sipping',\n        # Interior/domestic sounds\n        'Door knock',\n        'Mouse click',\n        'Keyboard typing',\n        'Door, wood creaks',\n        'Can opening',\n        'Washing machine',\n        'Vacuum cleaner',\n        'Clock alarm',\n        'Clock tick',\n        'Glass breaking',\n        # Exterior/urban noises\n        'Helicopter',\n        'Chainsaw',\n        'Siren',\n        'Car horn',\n        'Engine',\n        'Train',\n        'Church bells',\n        'Airplane',\n        'Fireworks',\n        'Hand saw',\n    ]\n    meta = os.path.join('ESC-50-master', 'meta', 'esc50.csv')\n    meta_info = collections.namedtuple(\n        'META_INFO',\n        ('filename', 'fold', 'target', 'category', 'esc10', 'src_file', 'take'))\n    audio_path = os.path.join('ESC-50-master', 'audio')\n\n    def __init__(self,\n                 mode: str='train',\n                 split: int=1,\n                 feat_type: str='raw',\n                 **kwargs):\n        \"\"\"\n        Ags:\n            mode (:obj:`str`, `optional`, defaults to `train`):\n                It identifies the dataset mode (train or dev).\n            split (:obj:`int`, `optional`, defaults to 1):\n                It specify the fold of dev dataset.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extract of an audio file.\n        \"\"\"\n        files, labels = self._get_data(mode, split)\n        super(ESC50, self).__init__(\n            files=files, labels=labels, feat_type=feat_type, **kwargs)\n\n    def _get_meta_info(self) -> List[collections.namedtuple]:\n        ret = []\n        with open(os.path.join(DATA_HOME, self.meta), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                ret.append(self.meta_info(*line.strip().split(',')))\n        return ret\n\n    def _get_data(self, mode: str, split: int) -> Tuple[List[str], List[int]]:\n        if not os.path.isdir(os.path.join(DATA_HOME, self.audio_path)) or \\\n            not os.path.isfile(os.path.join(DATA_HOME, self.meta)):\n            download_and_decompress(self.archieves, DATA_HOME)\n\n        meta_info = self._get_meta_info()\n\n        files = []\n        labels = []\n        for sample in meta_info:\n            filename, fold, target, _, _, _, _ = sample\n            if mode == 'train' and int(fold) != split:\n                files.append(os.path.join(DATA_HOME, self.audio_path, filename))\n                labels.append(int(target))\n\n            if mode != 'train' and int(fold) == split:\n                files.append(os.path.join(DATA_HOME, self.audio_path, filename))\n                labels.append(int(target))\n\n        return files, labels\n"
  },
  {
    "path": "paddlespeech/audio/datasets/voxceleb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\nimport csv\nimport glob\nimport os\nimport random\nfrom multiprocessing import cpu_count\nfrom typing import List\n\nfrom paddle.io import Dataset\nfrom pathos.multiprocessing import Pool\nfrom tqdm import tqdm\n\nfrom ...utils.env import DATA_HOME\nfrom ..backends.soundfile_backend import soundfile_load as load_audio\nfrom ..utils.download import decompress\nfrom ..utils.download import download_and_decompress\nfrom .dataset import feat_funcs\n\n__all__ = ['VoxCeleb']\n\n\nclass VoxCeleb(Dataset):\n    source_url = 'https://thor.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a/'\n    archieves_audio_dev = [\n        {\n            'url': source_url + 'vox1_dev_wav_partaa',\n            'md5': 'e395d020928bc15670b570a21695ed96',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partab',\n            'md5': 'bbfaaccefab65d82b21903e81a8a8020',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partac',\n            'md5': '017d579a2a96a077f40042ec33e51512',\n        },\n        {\n            'url': source_url + 'vox1_dev_wav_partad',\n            'md5': '7bb1e9f70fddc7a678fa998ea8b3ba19',\n        },\n    ]\n    archieves_audio_test = [\n        {\n            'url': source_url + 'vox1_test_wav.zip',\n            'md5': '185fdc63c3c739954633d50379a3d102',\n        },\n    ]\n    archieves_meta = [\n        {\n            'url':\n            'https://www.robots.ox.ac.uk/~vgg/data/voxceleb/meta/veri_test2.txt',\n            'md5':\n            'b73110731c9223c1461fe49cb48dddfc',\n        },\n    ]\n\n    num_speakers = 1211  # 1211 vox1, 5994 vox2, 7205 vox1+2, test speakers: 41\n    sample_rate = 16000\n    meta_info = collections.namedtuple(\n        'META_INFO', ('id', 'duration', 'wav', 'start', 'stop', 'spk_id'))\n    base_path = os.path.join(DATA_HOME, 'vox1')\n    wav_path = os.path.join(base_path, 'wav')\n    meta_path = os.path.join(base_path, 'meta')\n    veri_test_file = os.path.join(meta_path, 'veri_test2.txt')\n    csv_path = os.path.join(base_path, 'csv')\n    subsets = ['train', 'dev', 'enroll', 'test']\n\n    def __init__(\n            self,\n            subset: str='train',\n            feat_type: str='raw',\n            random_chunk: bool=True,\n            chunk_duration: float=3.0,  # seconds\n            split_ratio: float=0.9,  # train split ratio\n            seed: int=0,\n            target_dir: str=None,\n            vox2_base_path=None,\n            **kwargs):\n        \"\"\"VoxCeleb data prepare and get the specific dataset audio info\n\n        Args:\n            subset (str, optional): dataset name, such as train, dev, enroll or test. Defaults to 'train'.\n            feat_type (str, optional): feat type, such raw, melspectrogram(fbank) or mfcc . Defaults to 'raw'.\n            random_chunk (bool, optional): random select a duration from audio. Defaults to True.\n            chunk_duration (float, optional): chunk duration if random_chunk flag is set. Defaults to 3.0.\n            target_dir (str, optional): data dir, audio info will be stored in this directory. Defaults to None.\n            vox2_base_path (_type_, optional): vox2 directory. vox2 data must be converted from m4a to wav. Defaults to None.\n        \"\"\"\n        assert subset in self.subsets, \\\n            'Dataset subset must be one in {}, but got {}'.format(self.subsets, subset)\n\n        self.subset = subset\n        self.spk_id2label = {}\n        self.feat_type = feat_type\n        self.feat_config = kwargs\n        self.random_chunk = random_chunk\n        self.chunk_duration = chunk_duration\n        self.split_ratio = split_ratio\n        self.target_dir = target_dir if target_dir else VoxCeleb.base_path\n        self.vox2_base_path = vox2_base_path\n\n        # if we set the target dir, we will change the vox data info data from base path to target dir\n        VoxCeleb.csv_path = os.path.join(\n            target_dir, \"voxceleb\", 'csv') if target_dir else VoxCeleb.csv_path\n        VoxCeleb.meta_path = os.path.join(\n            target_dir, \"voxceleb\",\n            'meta') if target_dir else VoxCeleb.meta_path\n        VoxCeleb.veri_test_file = os.path.join(VoxCeleb.meta_path,\n                                               'veri_test2.txt')\n        # self._data = self._get_data()[:1000]  # KP: Small dataset test.\n        self._data = self._get_data()\n        super(VoxCeleb, self).__init__()\n\n        # Set up a seed to reproduce training or predicting result.\n        # random.seed(seed)\n\n    def _get_data(self):\n        # Download audio files.\n        # We need the users to decompress all vox1/dev/wav and vox1/test/wav/ to vox1/wav/ dir\n        # so, we check the vox1/wav dir status\n        print(f\"wav base path: {self.wav_path}\")\n        if not os.path.isdir(self.wav_path):\n            print(\"start to download the voxceleb1 dataset\")\n            download_and_decompress(  # multi-zip parts concatenate to vox1_dev_wav.zip\n                self.archieves_audio_dev,\n                self.base_path,\n                decompress=False)\n            download_and_decompress(  # download the vox1_test_wav.zip and unzip\n                self.archieves_audio_test,\n                self.base_path,\n                decompress=True)\n\n            # Download all parts and concatenate the files into one zip file.\n            dev_zipfile = os.path.join(self.base_path, 'vox1_dev_wav.zip')\n            print(f'Concatenating all parts to: {dev_zipfile}')\n            os.system(\n                f'cat {os.path.join(self.base_path, \"vox1_dev_wav_parta*\")} > {dev_zipfile}'\n            )\n\n            # Extract all audio files of dev and test set.\n            decompress(dev_zipfile, self.base_path)\n\n        # Download meta files.\n        if not os.path.isdir(self.meta_path):\n            print(\"prepare the meta data\")\n            download_and_decompress(\n                self.archieves_meta, self.meta_path, decompress=False)\n\n        # Data preparation.\n        if not os.path.isdir(self.csv_path):\n            os.makedirs(self.csv_path)\n            self.prepare_data()\n\n        data = []\n        print(\n            f\"read the {self.subset} from {os.path.join(self.csv_path, f'{self.subset}.csv')}\"\n        )\n        with open(os.path.join(self.csv_path, f'{self.subset}.csv'), 'r') as rf:\n            for line in rf.readlines()[1:]:\n                audio_id, duration, wav, start, stop, spk_id = line.strip(\n                ).split(',')\n                data.append(\n                    self.meta_info(audio_id,\n                                   float(duration), wav,\n                                   int(start), int(stop), spk_id))\n\n        with open(os.path.join(self.meta_path, 'spk_id2label.txt'), 'r') as f:\n            for line in f.readlines():\n                spk_id, label = line.strip().split(' ')\n                self.spk_id2label[spk_id] = int(label)\n\n        return data\n\n    def _convert_to_record(self, idx: int):\n        sample = self._data[idx]\n\n        record = {}\n        # To show all fields in a namedtuple: `type(sample)._fields`\n        for field in type(sample)._fields:\n            record[field] = getattr(sample, field)\n\n        waveform, sr = load_audio(record['wav'])\n\n        # random select a chunk audio samples from the audio\n        if self.random_chunk:\n            num_wav_samples = waveform.shape[0]\n            num_chunk_samples = int(self.chunk_duration * sr)\n            start = random.randint(0, num_wav_samples - num_chunk_samples - 1)\n            stop = start + num_chunk_samples\n        else:\n            start = record['start']\n            stop = record['stop']\n\n        waveform = waveform[start:stop]\n\n        assert self.feat_type in feat_funcs.keys(), \\\n            f\"Unknown feat_type: {self.feat_type}, it must be one in {list(feat_funcs.keys())}\"\n        feat_func = feat_funcs[self.feat_type]\n        feat = feat_func(\n            waveform, sr=sr, **self.feat_config) if feat_func else waveform\n\n        record.update({'feat': feat})\n        if self.subset in ['train',\n                           'dev']:  # Labels are available in train and dev.\n            record.update({'label': self.spk_id2label[record['spk_id']]})\n\n        return record\n\n    @staticmethod\n    def _get_chunks(seg_dur, audio_id, audio_duration):\n        num_chunks = int(audio_duration / seg_dur)  # all in milliseconds\n\n        chunk_lst = [\n            audio_id + \"_\" + str(i * seg_dur) + \"_\" + str(i * seg_dur + seg_dur)\n            for i in range(num_chunks)\n        ]\n        return chunk_lst\n\n    def _get_audio_info(self, wav_file: str,\n                        split_chunks: bool) -> List[List[str]]:\n        waveform, sr = load_audio(wav_file)\n        spk_id, sess_id, utt_id = wav_file.split(\"/\")[-3:]\n        audio_id = '-'.join([spk_id, sess_id, utt_id.split(\".\")[0]])\n        audio_duration = waveform.shape[0] / sr\n\n        ret = []\n        if split_chunks:  # Split into pieces of self.chunk_duration seconds.\n            uniq_chunks_list = self._get_chunks(self.chunk_duration, audio_id,\n                                                audio_duration)\n\n            for chunk in uniq_chunks_list:\n                s, e = chunk.split(\"_\")[-2:]  # Timestamps of start and end\n                start_sample = int(float(s) * sr)\n                end_sample = int(float(e) * sr)\n                # id, duration, wav, start, stop, spk_id\n                ret.append([\n                    chunk, audio_duration, wav_file, start_sample, end_sample,\n                    spk_id\n                ])\n        else:  # Keep whole audio.\n            ret.append([\n                audio_id, audio_duration, wav_file, 0, waveform.shape[0], spk_id\n            ])\n        return ret\n\n    def generate_csv(self,\n                     wav_files: List[str],\n                     output_file: str,\n                     split_chunks: bool=True):\n        print(f'Generating csv: {output_file}')\n        header = [\"id\", \"duration\", \"wav\", \"start\", \"stop\", \"spk_id\"]\n        # Note: this may occurs c++ exception, but the program will execute fine\n        # so we can ignore the exception \n        with Pool(cpu_count()) as p:\n            infos = list(\n                tqdm(\n                    p.imap(lambda x: self._get_audio_info(x, split_chunks),\n                           wav_files),\n                    total=len(wav_files)))\n\n        csv_lines = []\n        for info in infos:\n            csv_lines.extend(info)\n\n        with open(output_file, mode=\"w\") as csv_f:\n            csv_writer = csv.writer(\n                csv_f, delimiter=\",\", quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            csv_writer.writerow(header)\n            for line in csv_lines:\n                csv_writer.writerow(line)\n\n    def prepare_data(self):\n        # Audio of speakers in veri_test_file should not be included in training set.\n        print(\"start to prepare the data csv file\")\n        enroll_files = set()\n        test_files = set()\n        # get the enroll and test audio file path\n        with open(self.veri_test_file, 'r') as f:\n            for line in f.readlines():\n                _, enrol_file, test_file = line.strip().split(' ')\n                enroll_files.add(os.path.join(self.wav_path, enrol_file))\n                test_files.add(os.path.join(self.wav_path, test_file))\n            enroll_files = sorted(enroll_files)\n            test_files = sorted(test_files)\n\n        # get the enroll and test speakers\n        test_spks = set()\n        for file in (enroll_files + test_files):\n            spk = file.split('/wav/')[1].split('/')[0]\n            test_spks.add(spk)\n\n        # get all the train and dev audios file path\n        audio_files = []\n        speakers = set()\n        print(\"Getting file list...\")\n        for path in [self.wav_path, self.vox2_base_path]:\n            # if vox2 directory is not set and vox2 is not a directory \n            # we will not process this directory\n            if not path or not os.path.exists(path):\n                print(f\"{path} is an invalid path, please check again, \"\n                      \"and we will ignore the vox2 base path\")\n                continue\n            for file in glob.glob(\n                    os.path.join(path, \"**\", \"*.wav\"), recursive=True):\n                spk = file.split('/wav/')[1].split('/')[0]\n                if spk in test_spks:\n                    continue\n                speakers.add(spk)\n                audio_files.append(file)\n\n        print(\n            f\"start to generate the {os.path.join(self.meta_path, 'spk_id2label.txt')}\"\n        )\n        # encode the train and dev speakers label to spk_id2label.txt\n        with open(os.path.join(self.meta_path, 'spk_id2label.txt'), 'w') as f:\n            for label, spk_id in enumerate(\n                    sorted(speakers)):  # 1211 vox1, 5994 vox2, 7205 vox1+2\n                f.write(f'{spk_id} {label}\\n')\n\n        audio_files = sorted(audio_files)\n        random.shuffle(audio_files)\n        split_idx = int(self.split_ratio * len(audio_files))\n        # split_ratio to train\n        train_files, dev_files = audio_files[:split_idx], audio_files[\n            split_idx:]\n\n        self.generate_csv(train_files, os.path.join(self.csv_path, 'train.csv'))\n        self.generate_csv(dev_files, os.path.join(self.csv_path, 'dev.csv'))\n\n        self.generate_csv(\n            enroll_files,\n            os.path.join(self.csv_path, 'enroll.csv'),\n            split_chunks=False)\n        self.generate_csv(\n            test_files,\n            os.path.join(self.csv_path, 'test.csv'),\n            split_chunks=False)\n\n    def __getitem__(self, idx):\n        return self._convert_to_record(idx)\n\n    def __len__(self):\n        return len(self._data)\n"
  },
  {
    "path": "paddlespeech/audio/functional/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .functional import compute_fbank_matrix\nfrom .functional import create_dct\nfrom .functional import fft_frequencies\nfrom .functional import hz_to_mel\nfrom .functional import mel_frequencies\nfrom .functional import mel_to_hz\nfrom .functional import power_to_db\n"
  },
  {
    "path": "paddlespeech/audio/functional/functional.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from librosa(https://github.com/librosa/librosa)\nimport math\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nfrom paddle import Tensor\n\n__all__ = [\n    'hz_to_mel',\n    'mel_to_hz',\n    'mel_frequencies',\n    'fft_frequencies',\n    'compute_fbank_matrix',\n    'power_to_db',\n    'create_dct',\n]\n\n\ndef hz_to_mel(freq: Union[Tensor, float],\n              htk: bool=False) -> Union[Tensor, float]:\n    \"\"\"Convert Hz to Mels.\n\n    Args:\n        freq (Union[Tensor, float]): The input tensor with arbitrary shape.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        Union[Tensor, float]: Frequency in mels.\n    \"\"\"\n\n    if htk:\n        if isinstance(freq, Tensor):\n            return 2595.0 * paddle.log10(1.0 + freq / 700.0)\n        else:\n            return 2595.0 * math.log10(1.0 + freq / 700.0)\n\n    # Fill in the linear part\n    f_min = 0.0\n    f_sp = 200.0 / 3\n\n    mels = (freq - f_min) / f_sp\n\n    # Fill in the log-scale part\n\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = math.log(6.4) / 27.0  # step size for log region\n\n    if isinstance(freq, Tensor):\n        target = min_log_mel + paddle.log(\n            freq / min_log_hz + 1e-10) / logstep  # prevent nan with 1e-10\n        mask = (freq > min_log_hz).astype(freq.dtype)\n        mels = target * mask + mels * (\n            1 - mask)  # will replace by masked_fill OP in future\n    else:\n        if freq >= min_log_hz:\n            mels = min_log_mel + math.log(freq / min_log_hz + 1e-10) / logstep\n\n    return mels\n\n\ndef mel_to_hz(mel: Union[float, Tensor],\n              htk: bool=False) -> Union[float, Tensor]:\n    \"\"\"Convert mel bin numbers to frequencies.\n\n    Args:\n        mel (Union[float, Tensor]): The mel frequency represented as a tensor with arbitrary shape.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n\n    Returns:\n        Union[float, Tensor]: Frequencies in Hz.\n    \"\"\"\n    if htk:\n        return 700.0 * (10.0**(mel / 2595.0) - 1.0)\n\n    f_min = 0.0\n    f_sp = 200.0 / 3\n    freqs = f_min + f_sp * mel\n    # And now the nonlinear scale\n    min_log_hz = 1000.0  # beginning of log region (Hz)\n    min_log_mel = (min_log_hz - f_min) / f_sp  # same (Mels)\n    logstep = math.log(6.4) / 27.0  # step size for log region\n    if isinstance(mel, Tensor):\n        target = min_log_hz * paddle.exp(logstep * (mel - min_log_mel))\n        mask = (mel > min_log_mel).astype(mel.dtype)\n        freqs = target * mask + freqs * (\n            1 - mask)  # will replace by masked_fill OP in future\n    else:\n        if mel >= min_log_mel:\n            freqs = min_log_hz * math.exp(logstep * (mel - min_log_mel))\n\n    return freqs\n\n\ndef mel_frequencies(n_mels: int=64,\n                    f_min: float=0.0,\n                    f_max: float=11025.0,\n                    htk: bool=False,\n                    dtype: str='float32') -> Tensor:\n    \"\"\"Compute mel frequencies.\n\n    Args:\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        fmax (float, optional): Maximum frequency in Hz. Defaults to 11025.0.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        dtype (str, optional): The data type of the return frequencies. Defaults to 'float32'.\n\n    Returns:\n        Tensor: Tensor of n_mels frequencies in Hz with shape `(n_mels,)`.\n    \"\"\"\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    min_mel = hz_to_mel(f_min, htk=htk)\n    max_mel = hz_to_mel(f_max, htk=htk)\n    mels = paddle.linspace(min_mel, max_mel, n_mels, dtype=dtype)\n    freqs = mel_to_hz(mels, htk=htk)\n    return freqs\n\n\ndef fft_frequencies(sr: int, n_fft: int, dtype: str='float32') -> Tensor:\n    \"\"\"Compute fourier frequencies.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): Number of fft bins.\n        dtype (str, optional): The data type of the return frequencies. Defaults to 'float32'.\n\n    Returns:\n        Tensor: FFT frequencies in Hz with shape `(n_fft//2 + 1,)`.\n    \"\"\"\n    return paddle.linspace(0, float(sr) / 2, int(1 + n_fft // 2), dtype=dtype)\n\n\ndef compute_fbank_matrix(sr: int,\n                         n_fft: int,\n                         n_mels: int=64,\n                         f_min: float=0.0,\n                         f_max: Optional[float]=None,\n                         htk: bool=False,\n                         norm: Union[str, float]='slaney',\n                         dtype: str='float32') -> Tensor:\n    \"\"\"Compute fbank matrix.\n\n    Args:\n        sr (int): Sample rate.\n        n_fft (int): Number of fft bins.\n        n_mels (int, optional): Number of mel bins. Defaults to 64.\n        f_min (float, optional): Minimum frequency in Hz. Defaults to 0.0.\n        f_max (Optional[float], optional): Maximum frequency in Hz. Defaults to None.\n        htk (bool, optional): Use htk scaling. Defaults to False.\n        norm (Union[str, float], optional): Type of normalization. Defaults to 'slaney'.\n        dtype (str, optional): The data type of the return matrix. Defaults to 'float32'.\n\n    Returns:\n        Tensor: Mel transform matrix with shape `(n_mels, n_fft//2 + 1)`.\n    \"\"\"\n\n    if f_max is None:\n        f_max = float(sr) / 2\n\n    # Initialize the weights\n    weights = paddle.zeros((n_mels, int(1 + n_fft // 2)), dtype=dtype)\n\n    # Center freqs of each FFT bin\n    fftfreqs = fft_frequencies(sr=sr, n_fft=n_fft, dtype=dtype)\n\n    # 'Center freqs' of mel bands - uniformly spaced between limits\n    mel_f = mel_frequencies(\n        n_mels + 2, f_min=f_min, f_max=f_max, htk=htk, dtype=dtype)\n\n    fdiff = mel_f[1:] - mel_f[:-1]  #np.diff(mel_f)\n    ramps = mel_f.unsqueeze(1) - fftfreqs.unsqueeze(0)\n    #ramps = np.subtract.outer(mel_f, fftfreqs)\n\n    for i in range(n_mels):\n        # lower and upper slopes for all bins\n        lower = -ramps[i] / fdiff[i]\n        upper = ramps[i + 2] / fdiff[i + 1]\n\n        # .. then intersect them with each other and zero\n        weights[i] = paddle.maximum(\n            paddle.zeros_like(lower), paddle.minimum(lower, upper))\n\n    # Slaney-style mel is scaled to be approx constant energy per channel\n    if norm == 'slaney':\n        enorm = 2.0 / (mel_f[2:n_mels + 2] - mel_f[:n_mels])\n        weights *= enorm.unsqueeze(1)\n    elif isinstance(norm, int) or isinstance(norm, float):\n        weights = paddle.nn.functional.normalize(weights, p=norm, axis=-1)\n\n    return weights\n\n\ndef power_to_db(spect: Tensor,\n                ref_value: float=1.0,\n                amin: float=1e-10,\n                top_db: Optional[float]=None) -> Tensor:\n    \"\"\"Convert a power spectrogram (amplitude squared) to decibel (dB) units. The function computes the scaling `10 * log10(x / ref)` in a numerically stable way.\n\n    Args:\n        spect (Tensor): STFT power spectrogram.\n        ref_value (float, optional): The reference value. If smaller than 1.0, the db level of the signal will be pulled up accordingly. Otherwise, the db level is pushed down. Defaults to 1.0.\n        amin (float, optional): Minimum threshold. Defaults to 1e-10.\n        top_db (Optional[float], optional): Threshold the output at `top_db` below the peak. Defaults to None.\n\n    Returns:\n        Tensor: Power spectrogram in db scale.\n    \"\"\"\n    if amin <= 0:\n        raise Exception(\"amin must be strictly positive\")\n\n    if ref_value <= 0:\n        raise Exception(\"ref_value must be strictly positive\")\n\n    ones = paddle.ones_like(spect)\n    log_spec = 10.0 * paddle.log10(paddle.maximum(ones * amin, spect))\n    log_spec -= 10.0 * math.log10(max(ref_value, amin))\n\n    if top_db is not None:\n        if top_db < 0:\n            raise Exception(\"top_db must be non-negative\")\n        log_spec = paddle.maximum(log_spec, ones * (log_spec.max() - top_db))\n\n    return log_spec\n\n\ndef create_dct(n_mfcc: int,\n               n_mels: int,\n               norm: Optional[str]='ortho',\n               dtype: str='float32') -> Tensor:\n    \"\"\"Create a discrete cosine transform(DCT) matrix.\n\n    Args:\n        n_mfcc (int): Number of mel frequency cepstral coefficients. \n        n_mels (int): Number of mel filterbanks.\n        norm (Optional[str], optional): Normalization type. Defaults to 'ortho'.\n        dtype (str, optional): The data type of the return matrix. Defaults to 'float32'.\n\n    Returns:\n        Tensor: The DCT matrix with shape `(n_mels, n_mfcc)`.\n    \"\"\"\n    n = paddle.arange(n_mels, dtype=dtype)\n    k = paddle.arange(n_mfcc, dtype=dtype).unsqueeze(1)\n    dct = paddle.cos(math.pi / float(n_mels) * (n + 0.5) *\n                     k)  # size (n_mfcc, n_mels)\n    if norm is None:\n        dct *= 2.0\n    else:\n        assert norm == \"ortho\"\n        dct[0] *= 1.0 / math.sqrt(2.0)\n        dct *= math.sqrt(2.0 / float(n_mels))\n    return dct.T\n"
  },
  {
    "path": "paddlespeech/audio/functional/window.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\nimport math\nfrom typing import List\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import Tensor\n\n\nclass WindowFunctionRegister(object):\n    def __init__(self):\n        self._functions_dict = dict()\n\n    def register(self):\n        def add_subfunction(func):\n            name = func.__name__\n            self._functions_dict[name] = func\n            return func\n\n        return add_subfunction\n\n    def get(self, name):\n        return self._functions_dict[name]\n\n\nwindow_function_register = WindowFunctionRegister()\n\n\n@window_function_register.register()\ndef _cat(x: List[Tensor], data_type: str) -> Tensor:\n    l = [paddle.to_tensor(_, data_type) for _ in x]\n    return paddle.concat(l)\n\n\n@window_function_register.register()\ndef _acosh(x: Union[Tensor, float]) -> Tensor:\n    if isinstance(x, float):\n        return math.log(x + math.sqrt(x**2 - 1))\n    return paddle.log(x + paddle.sqrt(paddle.square(x) - 1))\n\n\n@window_function_register.register()\ndef _extend(M: int, sym: bool) -> bool:\n    \"\"\"Extend window by 1 sample if needed for DFT-even symmetry.\"\"\"\n    if not sym:\n        return M + 1, True\n    else:\n        return M, False\n\n\n@window_function_register.register()\ndef _len_guards(M: int) -> bool:\n    \"\"\"Handle small or incorrect window lengths.\"\"\"\n    if int(M) != M or M < 0:\n        raise ValueError('Window length M must be a non-negative integer')\n\n    return M <= 1\n\n\n@window_function_register.register()\ndef _truncate(w: Tensor, needed: bool) -> Tensor:\n    \"\"\"Truncate window by 1 sample if needed for DFT-even symmetry.\"\"\"\n    if needed:\n        return w[:-1]\n    else:\n        return w\n\n\n@window_function_register.register()\ndef _general_gaussian(M: int, p, sig, sym: bool=True,\n                      dtype: str='float64') -> Tensor:\n    \"\"\"Compute a window with a generalized Gaussian shape.\n    This function is consistent with scipy.signal.windows.general_gaussian().\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype) - (M - 1.0) / 2.0\n    w = paddle.exp(-0.5 * paddle.abs(n / sig)**(2 * p))\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _general_cosine(M: int, a: float, sym: bool=True,\n                    dtype: str='float64') -> Tensor:\n    \"\"\"Compute a generic weighted sum of cosine terms window.\n    This function is consistent with scipy.signal.windows.general_cosine().\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    fac = paddle.linspace(-math.pi, math.pi, M, dtype=dtype)\n    w = paddle.zeros((M, ), dtype=dtype)\n    for k in range(len(a)):\n        w += a[k] * paddle.cos(k * fac)\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _general_hamming(M: int, alpha: float, sym: bool=True,\n                     dtype: str='float64') -> Tensor:\n    \"\"\"Compute a generalized Hamming window.\n    This function is consistent with scipy.signal.windows.general_hamming()\n    \"\"\"\n    return _general_cosine(M, [alpha, 1.0 - alpha], sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _taylor(M: int,\n            nbar=4,\n            sll=30,\n            norm=True,\n            sym: bool=True,\n            dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Taylor window.\n    The Taylor window taper function approximates the Dolph-Chebyshev window's\n    constant sidelobe level for a parameterized number of near-in sidelobes.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    # Original text uses a negative sidelobe level parameter and then negates\n    # it in the calculation of B. To keep consistent with other methods we\n    # assume the sidelobe level parameter to be positive.\n    B = 10**(sll / 20)\n    A = _acosh(B) / math.pi\n    s2 = nbar**2 / (A**2 + (nbar - 0.5)**2)\n    ma = paddle.arange(1, nbar, dtype=dtype)\n\n    Fm = paddle.empty((nbar - 1, ), dtype=dtype)\n    signs = paddle.empty_like(ma)\n    signs[::2] = 1\n    signs[1::2] = -1\n    m2 = ma * ma\n    for mi in range(len(ma)):\n        numer = signs[mi] * paddle.prod(1 - m2[mi] / s2 / (A**2 + (ma - 0.5)**2\n                                                           ))\n        if mi == 0:\n            denom = 2 * paddle.prod(1 - m2[mi] / m2[mi + 1:])\n        elif mi == len(ma) - 1:\n            denom = 2 * paddle.prod(1 - m2[mi] / m2[:mi])\n        else:\n            denom = (2 * paddle.prod(1 - m2[mi] / m2[:mi]) *\n                     paddle.prod(1 - m2[mi] / m2[mi + 1:]))\n\n        Fm[mi] = numer / denom\n\n    def W(n):\n        return 1 + 2 * paddle.matmul(\n            Fm.unsqueeze(0),\n            paddle.cos(2 * math.pi * ma.unsqueeze(1) *\n                       (n - M / 2.0 + 0.5) / M), )\n\n    w = W(paddle.arange(0, M, dtype=dtype))\n\n    # normalize (Note that this is not described in the original text [1])\n    if norm:\n        scale = 1.0 / W((M - 1) / 2)\n        w *= scale\n    w = w.squeeze()\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _hamming(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Hamming window.\n    The Hamming window is a taper formed by using a raised cosine with\n    non-zero endpoints, optimized to minimize the nearest side lobe.\n    \"\"\"\n    return _general_hamming(M, 0.54, sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _hann(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Hann window.\n    The Hann window is a taper formed by using a raised cosine or sine-squared\n    with ends that touch zero.\n    \"\"\"\n    return _general_hamming(M, 0.5, sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _tukey(M: int, alpha=0.5, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Tukey window.\n    The Tukey window is also known as a tapered cosine window.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n\n    if alpha <= 0:\n        return paddle.ones((M, ), dtype=dtype)\n    elif alpha >= 1.0:\n        return hann(M, sym=sym)\n\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype)\n    width = int(alpha * (M - 1) / 2.0)\n    n1 = n[0:width + 1]\n    n2 = n[width + 1:M - width - 1]\n    n3 = n[M - width - 1:]\n\n    w1 = 0.5 * (1 + paddle.cos(math.pi * (-1 + 2.0 * n1 / alpha / (M - 1))))\n    w2 = paddle.ones(n2.shape, dtype=dtype)\n    w3 = 0.5 * (1 + paddle.cos(math.pi * (-2.0 / alpha + 1 + 2.0 * n3 / alpha /\n                                          (M - 1))))\n    w = paddle.concat([w1, w2, w3])\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _gaussian(M: int, std: float, sym: bool=True,\n              dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Gaussian window.\n    The Gaussian widows has a Gaussian shape defined by the standard deviation(std).\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(0, M, dtype=dtype) - (M - 1.0) / 2.0\n    sig2 = 2 * std * std\n    w = paddle.exp(-(n**2) / sig2)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _exponential(M: int,\n                 center=None,\n                 tau=1.0,\n                 sym: bool=True,\n                 dtype: str='float64') -> Tensor:\n    \"\"\"Compute an exponential (or Poisson) window.\"\"\"\n    if sym and center is not None:\n        raise ValueError(\"If sym==True, center must be None.\")\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    if center is None:\n        center = (M - 1) / 2\n\n    n = paddle.arange(0, M, dtype=dtype)\n    w = paddle.exp(-paddle.abs(n - center) / tau)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _triang(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a triangular window.\"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    n = paddle.arange(1, (M + 1) // 2 + 1, dtype=dtype)\n    if M % 2 == 0:\n        w = (2 * n - 1.0) / M\n        w = paddle.concat([w, w[::-1]])\n    else:\n        w = 2 * n / (M + 1.0)\n        w = paddle.concat([w, w[-2::-1]])\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _bohman(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Bohman window.\n    The Bohman window is the autocorrelation of a cosine window.\n    \"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n\n    fac = paddle.abs(paddle.linspace(-1, 1, M, dtype=dtype)[1:-1])\n    w = (1 - fac) * paddle.cos(math.pi * fac) + 1.0 / math.pi * paddle.sin(\n        math.pi * fac)\n    w = _cat([0, w, 0], dtype)\n\n    return _truncate(w, needs_trunc)\n\n\n@window_function_register.register()\ndef _blackman(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a Blackman window.\n    The Blackman window is a taper formed by using the first three terms of\n    a summation of cosines. It was designed to have close to the minimal\n    leakage possible.  It is close to optimal, only slightly worse than a\n    Kaiser window.\n    \"\"\"\n    return _general_cosine(M, [0.42, 0.50, 0.08], sym, dtype=dtype)\n\n\n@window_function_register.register()\ndef _cosine(M: int, sym: bool=True, dtype: str='float64') -> Tensor:\n    \"\"\"Compute a window with a simple cosine shape.\"\"\"\n    if _len_guards(M):\n        return paddle.ones((M, ), dtype=dtype)\n    M, needs_trunc = _extend(M, sym)\n    w = paddle.sin(math.pi / M * (paddle.arange(0, M, dtype=dtype) + 0.5))\n\n    return _truncate(w, needs_trunc)\n\n\ndef get_window(\n        window: Union[str, Tuple[str, float]],\n        win_length: int,\n        fftbins: bool=True,\n        dtype: str='float64', ) -> Tensor:\n    \"\"\"Return a window of a given length and type.\n\n    Args:\n        window (Union[str, Tuple[str, float]]): The window function applied to the signal before the Fourier transform. Supported window functions: 'hamming', 'hann', 'gaussian', 'general_gaussian', 'exponential', 'triang', 'bohman', 'blackman', 'cosine', 'tukey', 'taylor'.\n        win_length (int): Number of samples.\n        fftbins (bool, optional): If True, create a \"periodic\" window. Otherwise, create a \"symmetric\" window, for use in filter design. Defaults to True.\n        dtype (str, optional): The data type of the return window. Defaults to 'float64'.\n\n    Returns:\n        Tensor: The window represented as a tensor.\n\n    Examples:\n        .. code-block:: python\n\n            import paddle\n\n            n_fft = 512\n            cosine_window = paddle.audio.functional.get_window('cosine', n_fft)\n\n            std = 7\n            gaussian_window = paddle.audio.functional.get_window(('gaussian',std), n_fft)\n    \"\"\"\n    sym = not fftbins\n\n    args = ()\n    if isinstance(window, tuple):\n        winstr = window[0]\n        if len(window) > 1:\n            args = window[1:]\n    elif isinstance(window, str):\n        if window in ['gaussian', 'exponential']:\n            raise ValueError(\"The '\" + window + \"' window needs one or \"\n                             \"more parameters -- pass a tuple.\")\n        else:\n            winstr = window\n    else:\n        raise ValueError(\"%s as window type is not supported.\" %\n                         str(type(window)))\n\n    try:\n        winfunc = window_function_register.get('_' + winstr)\n    except KeyError as e:\n        raise ValueError(\"Unknown window type.\") from e\n\n    params = (win_length, ) + args\n    kwargs = {'sym': sym}\n    return winfunc(*params, dtype=dtype, **kwargs)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/__init__.py",
    "content": "# Copyright (c) 2017-2019 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n# flake8: noqa\nfrom .cache import cached_tarfile_samples\nfrom .cache import cached_tarfile_to_samples\nfrom .cache import lru_cleanup\nfrom .cache import pipe_cleaner\nfrom .compat import FluidWrapper\nfrom .compat import WebDataset\nfrom .compat import WebLoader\nfrom .extradatasets import MockDataset\nfrom .extradatasets import with_epoch\nfrom .extradatasets import with_length\nfrom .filters import associate\nfrom .filters import audio_cmvn\nfrom .filters import audio_compute_fbank\nfrom .filters import audio_data_filter\nfrom .filters import audio_padding\nfrom .filters import audio_resample\nfrom .filters import audio_spec_aug\nfrom .filters import audio_tokenize\nfrom .filters import batched\nfrom .filters import decode\nfrom .filters import detshuffle\nfrom .filters import extract_keys\nfrom .filters import getfirst\nfrom .filters import info\nfrom .filters import map\nfrom .filters import map_dict\nfrom .filters import map_tuple\nfrom .filters import pipelinefilter\nfrom .filters import placeholder\nfrom .filters import rename\nfrom .filters import rename_keys\nfrom .filters import select\nfrom .filters import shuffle\nfrom .filters import slice\nfrom .filters import sort\nfrom .filters import to_tuple\nfrom .filters import transform_with\nfrom .filters import unbatched\nfrom .filters import xdecode\nfrom .handlers import ignore_and_continue\nfrom .handlers import ignore_and_stop\nfrom .handlers import reraise_exception\nfrom .handlers import warn_and_continue\nfrom .handlers import warn_and_stop\nfrom .mix import RandomMix\nfrom .mix import RoundRobin\nfrom .pipeline import DataPipeline\nfrom .shardlists import MultiShardSample\nfrom .shardlists import non_empty\nfrom .shardlists import resampled\nfrom .shardlists import ResampledShards\nfrom .shardlists import shardspec\nfrom .shardlists import SimpleShardList\nfrom .shardlists import single_node_only\nfrom .shardlists import split_by_node\nfrom .shardlists import split_by_worker\nfrom .tariterators import tarfile_samples\nfrom .tariterators import tarfile_to_samples\nfrom .utils import PipelineStage\nfrom .utils import repeatedly\nfrom .writer import numpy_dumps\nfrom .writer import ShardWriter\nfrom .writer import TarWriter\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/autodecode.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n\"\"\"Automatically decode webdataset samples.\"\"\"\nimport io\nimport json\nimport os\nimport pickle\nimport re\nimport tempfile\nfrom functools import partial\n\nimport numpy as np\n\"\"\"Extensions passed on to the image decoder.\"\"\"\nimage_extensions = \"jpg jpeg png ppm pgm pbm pnm\".split()\n\n################################################################\n# handle basic datatypes\n################################################################\n\n\ndef paddle_loads(data):\n    \"\"\"Load data using paddle.loads, importing paddle only if needed.\n\n    :param data: data to be decoded\n    \"\"\"\n    import io\n\n    import paddle\n\n    stream = io.BytesIO(data)\n    return paddle.load(stream)\n\n\ndef tenbin_loads(data):\n    from . import tenbin\n\n    return tenbin.decode_buffer(data)\n\n\ndef msgpack_loads(data):\n    import msgpack\n\n    return msgpack.unpackb(data)\n\n\ndef npy_loads(data):\n    import numpy.lib.format\n\n    stream = io.BytesIO(data)\n    return numpy.lib.format.read_array(stream)\n\n\ndef cbor_loads(data):\n    import cbor\n\n    return cbor.loads(data)\n\n\ndecoders = {\n    \"txt\": lambda data: data.decode(\"utf-8\"),\n    \"text\": lambda data: data.decode(\"utf-8\"),\n    \"transcript\": lambda data: data.decode(\"utf-8\"),\n    \"cls\": lambda data: int(data),\n    \"cls2\": lambda data: int(data),\n    \"index\": lambda data: int(data),\n    \"inx\": lambda data: int(data),\n    \"id\": lambda data: int(data),\n    \"json\": lambda data: json.loads(data),\n    \"jsn\": lambda data: json.loads(data),\n    \"pyd\": lambda data: pickle.loads(data),\n    \"pickle\": lambda data: pickle.loads(data),\n    \"pdparams\": lambda data: paddle_loads(data),\n    \"ten\": tenbin_loads,\n    \"tb\": tenbin_loads,\n    \"mp\": msgpack_loads,\n    \"msg\": msgpack_loads,\n    \"npy\": npy_loads,\n    \"npz\": lambda data: np.load(io.BytesIO(data)),\n    \"cbor\": cbor_loads,\n}\n\n\ndef basichandlers(key, data):\n    \"\"\"Handle basic file decoding.\n\n    This function is usually part of the post= decoders.\n    This handles the following forms of decoding:\n\n    - txt -> unicode string\n    - cls cls2 class count index inx id -> int\n    - json jsn -> JSON decoding\n    - pyd pickle -> pickle decoding\n    - pdparams -> paddle.loads\n    - ten tenbin -> fast tensor loading\n    - mp messagepack msg -> messagepack decoding\n    - npy -> Python NPY decoding\n\n    :param key: file name extension\n    :param data: binary data to be decoded\n    \"\"\"\n    extension = re.sub(r\".*[.]\", \"\", key)\n\n    if extension in decoders:\n        return decoders[extension](data)\n\n    return None\n\n\n################################################################\n# Generic extension handler.\n################################################################\n\n\ndef call_extension_handler(key, data, f, extensions):\n    \"\"\"Call the function f with the given data if the key matches the extensions.\n\n    :param key: actual key found in the sample\n    :param data: binary data\n    :param f: decoder function\n    :param extensions: list of matching extensions\n    \"\"\"\n    extension = key.lower().split(\".\")\n    for target in extensions:\n        target = target.split(\".\")\n        if len(target) > len(extension):\n            continue\n        if extension[-len(target):] == target:\n            return f(data)\n    return None\n\n\ndef handle_extension(extensions, f):\n    \"\"\"Return a decoder function for the list of extensions.\n\n    Extensions can be a space separated list of extensions.\n    Extensions can contain dots, in which case the corresponding number\n    of extension components must be present in the key given to f.\n    Comparisons are case insensitive.\n\n    Examples:\n    handle_extension(\"jpg jpeg\", my_decode_jpg)  # invoked for any file.jpg\n    handle_extension(\"seg.jpg\", special_case_jpg)  # invoked only for file.seg.jpg\n    \"\"\"\n    extensions = extensions.lower().split()\n    return partial(call_extension_handler, f=f, extensions=extensions)\n\n\n################################################################\n# handle images\n################################################################\n\nimagespecs = {\n    \"l8\": (\"numpy\", \"uint8\", \"l\"),\n    \"rgb8\": (\"numpy\", \"uint8\", \"rgb\"),\n    \"rgba8\": (\"numpy\", \"uint8\", \"rgba\"),\n    \"l\": (\"numpy\", \"float\", \"l\"),\n    \"rgb\": (\"numpy\", \"float\", \"rgb\"),\n    \"rgba\": (\"numpy\", \"float\", \"rgba\"),\n    \"paddlel8\": (\"paddle\", \"uint8\", \"l\"),\n    \"paddlergb8\": (\"paddle\", \"uint8\", \"rgb\"),\n    \"paddlergba8\": (\"paddle\", \"uint8\", \"rgba\"),\n    \"paddlel\": (\"paddle\", \"float\", \"l\"),\n    \"paddlergb\": (\"paddle\", \"float\", \"rgb\"),\n    \"paddle\": (\"paddle\", \"float\", \"rgb\"),\n    \"paddlergba\": (\"paddle\", \"float\", \"rgba\"),\n    \"pill\": (\"pil\", None, \"l\"),\n    \"pil\": (\"pil\", None, \"rgb\"),\n    \"pilrgb\": (\"pil\", None, \"rgb\"),\n    \"pilrgba\": (\"pil\", None, \"rgba\"),\n}\n\n\nclass ImageHandler:\n    \"\"\"Decode image data using the given `imagespec`.\n\n    The `imagespec` specifies whether the image is decoded\n    to numpy/paddle/pi, decoded to uint8/float, and decoded\n    to l/rgb/rgba:\n\n    - l8: numpy uint8 l\n    - rgb8: numpy uint8 rgb\n    - rgba8: numpy uint8 rgba\n    - l: numpy float l\n    - rgb: numpy float rgb\n    - rgba: numpy float rgba\n    - paddlel8: paddle uint8 l\n    - paddlergb8: paddle uint8 rgb\n    - paddlergba8: paddle uint8 rgba\n    - paddlel: paddle float l\n    - paddlergb: paddle float rgb\n    - paddle: paddle float rgb\n    - paddlergba: paddle float rgba\n    - pill: pil None l\n    - pil: pil None rgb\n    - pilrgb: pil None rgb\n    - pilrgba: pil None rgba\n\n    \"\"\"\n\n    def __init__(self, imagespec, extensions=image_extensions):\n        \"\"\"Create an image handler.\n\n        :param imagespec: short string indicating the type of decoding\n        :param extensions: list of extensions the image handler is invoked for\n        \"\"\"\n        if imagespec not in list(imagespecs.keys()):\n            raise ValueError(\"Unknown imagespec: %s\" % imagespec)\n        self.imagespec = imagespec.lower()\n        self.extensions = extensions\n\n    def __call__(self, key, data):\n        \"\"\"Perform image decoding.\n\n        :param key: file name extension\n        :param data: binary data\n        \"\"\"\n        import PIL.Image\n\n        extension = re.sub(r\".*[.]\", \"\", key)\n        if extension.lower() not in self.extensions:\n            return None\n        imagespec = self.imagespec\n        atype, etype, mode = imagespecs[imagespec]\n        with io.BytesIO(data) as stream:\n            img = PIL.Image.open(stream)\n            img.load()\n            img = img.convert(mode.upper())\n        if atype == \"pil\":\n            return img\n        elif atype == \"numpy\":\n            result = np.asarray(img)\n            if result.dtype != np.uint8:\n                raise ValueError(\"ImageHandler: numpy image must be uint8\")\n            if etype == \"uint8\":\n                return result\n            else:\n                return result.astype(\"f\") / 255.0\n        elif atype == \"paddle\":\n            import paddle\n\n            result = np.asarray(img)\n            if result.dtype != np.uint8:\n                raise ValueError(\"ImageHandler: paddle image must be uint8\")\n            if etype == \"uint8\":\n                result = np.array(result.transpose(2, 0, 1))\n                return paddle.tensor(result)\n            else:\n                result = np.array(result.transpose(2, 0, 1))\n                return paddle.tensor(result) / 255.0\n        return None\n\n\ndef imagehandler(imagespec, extensions=image_extensions):\n    \"\"\"Create an image handler.\n\n    This is just a lower case alias for ImageHander.\n\n    :param imagespec: textual image spec\n    :param extensions: list of extensions the handler should be applied for\n    \"\"\"\n    return ImageHandler(imagespec, extensions)\n\n\n################################################################\n# torch video\n################################################################\n'''\ndef torch_video(key, data):\n    \"\"\"Decode video using the torchvideo library.\n\n    :param key: file name extension\n    :param data: data to be decoded\n    \"\"\"\n    extension = re.sub(r\".*[.]\", \"\", key)\n    if extension not in \"mp4 ogv mjpeg avi mov h264 mpg webm wmv\".split():\n        return None\n\n    import torchvision.io\n\n    with tempfile.TemporaryDirectory() as dirname:\n        fname = os.path.join(dirname, f\"file.{extension}\")\n        with open(fname, \"wb\") as stream:\n            stream.write(data)\n        return torchvision.io.read_video(fname, pts_unit=\"sec\")\n'''\n\n################################################################\n# paddlespeech.audio\n################################################################\n\n\ndef paddle_audio(key, data):\n    \"\"\"Decode audio using the paddleaudio library.\n\n    :param key: file name extension\n    :param data: data to be decoded\n    \"\"\"\n    extension = re.sub(r\".*[.]\", \"\", key)\n    if extension not in [\"flac\", \"mp3\", \"sox\", \"wav\", \"m4a\", \"ogg\", \"wma\"]:\n        return None\n\n    with tempfile.TemporaryDirectory() as dirname:\n        fname = os.path.join(dirname, f\"file.{extension}\")\n        with open(fname, \"wb\") as stream:\n            stream.write(data)\n        return paddlespeech.audio.backends.soundfile_load(fname)\n\n\n################################################################\n# special class for continuing decoding\n################################################################\n\n\nclass Continue:\n    \"\"\"Special class for continuing decoding.\n\n    This is mostly used for decompression, as in:\n\n        def decompressor(key, data):\n            if key.endswith(\".gz\"):\n                return Continue(key[:-3], decompress(data))\n            return None\n    \"\"\"\n\n    def __init__(self, key, data):\n        \"\"\"__init__.\n\n        :param key:\n        :param data:\n        \"\"\"\n        self.key, self.data = key, data\n\n\ndef gzfilter(key, data):\n    \"\"\"Decode .gz files.\n\n    This decodes compressed files and the continues decoding.\n\n    :param key: file name extension\n    :param data: binary data\n    \"\"\"\n    import gzip\n\n    if not key.endswith(\".gz\"):\n        return None\n    decompressed = gzip.open(io.BytesIO(data)).read()\n    return Continue(key[:-3], decompressed)\n\n\n################################################################\n# decode entire training amples\n################################################################\n\ndefault_pre_handlers = [gzfilter]\ndefault_post_handlers = [basichandlers]\n\n\nclass Decoder:\n    \"\"\"Decode samples using a list of handlers.\n\n    For each key/data item, this iterates through the list of\n    handlers until some handler returns something other than None.\n    \"\"\"\n\n    def __init__(self, handlers, pre=None, post=None, only=None, partial=False):\n        \"\"\"Create a Decoder.\n\n        :param handlers: main list of handlers\n        :param pre: handlers called before the main list (.gz handler by default)\n        :param post: handlers called after the main list (default handlers by default)\n        :param only: a list of extensions; when give, only ignores files with those extensions\n        :param partial: allow partial decoding (i.e., don't decode fields that aren't of type bytes)\n        \"\"\"\n        if isinstance(only, str):\n            only = only.split()\n        self.only = only if only is None else set(only)\n        if pre is None:\n            pre = default_pre_handlers\n        if post is None:\n            post = default_post_handlers\n        assert all(callable(h)\n                   for h in handlers), f\"one of {handlers} not callable\"\n        assert all(callable(h) for h in pre), f\"one of {pre} not callable\"\n        assert all(callable(h) for h in post), f\"one of {post} not callable\"\n        self.handlers = pre + handlers + post\n        self.partial = partial\n\n    def decode1(self, key, data):\n        \"\"\"Decode a single field of a sample.\n\n        :param key: file name extension\n        :param data: binary data\n        \"\"\"\n        key = \".\" + key\n        for f in self.handlers:\n            result = f(key, data)\n            if isinstance(result, Continue):\n                key, data = result.key, result.data\n                continue\n            if result is not None:\n                return result\n        return data\n\n    def decode(self, sample):\n        \"\"\"Decode an entire sample.\n\n        :param sample: the sample, a dictionary of key value pairs\n        \"\"\"\n        result = {}\n        assert isinstance(sample, dict), sample\n        for k, v in list(sample.items()):\n            if k[0] == \"_\":\n                if isinstance(v, bytes):\n                    v = v.decode(\"utf-8\")\n                result[k] = v\n                continue\n            if self.only is not None and k not in self.only:\n                result[k] = v\n                continue\n            assert v is not None\n            if self.partial:\n                if isinstance(v, bytes):\n                    result[k] = self.decode1(k, v)\n                else:\n                    result[k] = v\n            else:\n                assert isinstance(v, bytes)\n                result[k] = self.decode1(k, v)\n        return result\n\n    def __call__(self, sample):\n        \"\"\"Decode an entire sample.\n\n        :param sample: the sample\n        \"\"\"\n        assert isinstance(sample, dict), (len(sample), sample)\n        return self.decode(sample)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/cache.py",
    "content": "# Copyright (c) 2017-2019 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\nimport os\nimport random\nimport re\nimport sys\nfrom urllib.parse import urlparse\n\nfrom . import filters\nfrom . import gopen\nfrom .handlers import reraise_exception\nfrom .tariterators import tar_file_and_group_expander\n\ndefault_cache_dir = os.environ.get(\"WDS_CACHE\", \"./_cache\")\ndefault_cache_size = float(os.environ.get(\"WDS_CACHE_SIZE\", \"1e18\"))\n\n\ndef lru_cleanup(cache_dir, cache_size, keyfn=os.path.getctime, verbose=False):\n    \"\"\"Performs cleanup of the file cache in cache_dir using an LRU strategy,\n    keeping the total size of all remaining files below cache_size.\"\"\"\n    if not os.path.exists(cache_dir):\n        return\n    total_size = 0\n    for dirpath, dirnames, filenames in os.walk(cache_dir):\n        for filename in filenames:\n            total_size += os.path.getsize(os.path.join(dirpath, filename))\n    if total_size <= cache_size:\n        return\n    # sort files by last access time\n    files = []\n    for dirpath, dirnames, filenames in os.walk(cache_dir):\n        for filename in filenames:\n            files.append(os.path.join(dirpath, filename))\n    files.sort(key=keyfn, reverse=True)\n    # delete files until we're under the cache size\n    while len(files) > 0 and total_size > cache_size:\n        fname = files.pop()\n        total_size -= os.path.getsize(fname)\n        if verbose:\n            print(\"# deleting %s\" % fname, file=sys.stderr)\n        os.remove(fname)\n\n\ndef download(url, dest, chunk_size=1024**2, verbose=False):\n    \"\"\"Download a file from `url` to `dest`.\"\"\"\n    temp = dest + f\".temp{os.getpid()}\"\n    with gopen.gopen(url) as stream:\n        with open(temp, \"wb\") as f:\n            while True:\n                data = stream.read(chunk_size)\n                if not data:\n                    break\n                f.write(data)\n    os.rename(temp, dest)\n\n\ndef pipe_cleaner(spec):\n    \"\"\"Guess the actual URL from a \"pipe:\" specification.\"\"\"\n    if spec.startswith(\"pipe:\"):\n        spec = spec[5:]\n        words = spec.split(\" \")\n        for word in words:\n            if re.match(r\"^(https?|gs|ais|s3)\", word):\n                return word\n    return spec\n\n\ndef get_file_cached(\n        spec,\n        cache_size=-1,\n        cache_dir=None,\n        url_to_name=pipe_cleaner,\n        verbose=False, ):\n    if cache_size == -1:\n        cache_size = default_cache_size\n    if cache_dir is None:\n        cache_dir = default_cache_dir\n    url = url_to_name(spec)\n    parsed = urlparse(url)\n    dirname, filename = os.path.split(parsed.path)\n    dirname = dirname.lstrip(\"/\")\n    dirname = re.sub(r\"[:/|;]\", \"_\", dirname)\n    destdir = os.path.join(cache_dir, dirname)\n    os.makedirs(destdir, exist_ok=True)\n    dest = os.path.join(cache_dir, dirname, filename)\n    if not os.path.exists(dest):\n        if verbose:\n            print(\"# downloading %s to %s\" % (url, dest), file=sys.stderr)\n        lru_cleanup(cache_dir, cache_size, verbose=verbose)\n        download(spec, dest, verbose=verbose)\n    return dest\n\n\ndef get_filetype(fname):\n    with os.popen(\"file '%s'\" % fname) as f:\n        ftype = f.read()\n    return ftype\n\n\ndef check_tar_format(fname):\n    \"\"\"Check whether a file is a tar archive.\"\"\"\n    ftype = get_filetype(fname)\n    return \"tar archive\" in ftype or \"gzip compressed\" in ftype\n\n\nverbose_cache = int(os.environ.get(\"WDS_VERBOSE_CACHE\", \"0\"))\n\n\ndef cached_url_opener(\n        data,\n        handler=reraise_exception,\n        cache_size=-1,\n        cache_dir=None,\n        url_to_name=pipe_cleaner,\n        validator=check_tar_format,\n        verbose=False,\n        always=False, ):\n    \"\"\"Given a stream of url names (packaged in `dict(url=url)`), yield opened streams.\"\"\"\n    verbose = verbose or verbose_cache\n    for sample in data:\n        assert isinstance(sample, dict), sample\n        assert \"url\" in sample\n        url = sample[\"url\"]\n        attempts = 5\n        try:\n            if not always and os.path.exists(url):\n                dest = url\n            else:\n                dest = get_file_cached(\n                    url,\n                    cache_size=cache_size,\n                    cache_dir=cache_dir,\n                    url_to_name=url_to_name,\n                    verbose=verbose, )\n            if verbose:\n                print(\"# opening %s\" % dest, file=sys.stderr)\n            assert os.path.exists(dest)\n            if not validator(dest):\n                ftype = get_filetype(dest)\n                with open(dest, \"rb\") as f:\n                    data = f.read(200)\n                os.remove(dest)\n                raise ValueError(\n                    \"%s (%s) is not a tar archive, but a %s, contains %s\" %\n                    (dest, url, ftype, repr(data)))\n            try:\n                stream = open(dest, \"rb\")\n                sample.update(stream=stream)\n                yield sample\n            except FileNotFoundError as exn:\n                # dealing with race conditions in lru_cleanup\n                attempts -= 1\n                if attempts > 0:\n                    time.sleep(random.random() * 10)\n                    continue\n                raise exn\n        except Exception as exn:\n            exn.args = exn.args + (url, )\n            if handler(exn):\n                continue\n            else:\n                break\n\n\ndef cached_tarfile_samples(\n        src,\n        handler=reraise_exception,\n        cache_size=-1,\n        cache_dir=None,\n        verbose=False,\n        url_to_name=pipe_cleaner,\n        always=False, ):\n    streams = cached_url_opener(\n        src,\n        handler=handler,\n        cache_size=cache_size,\n        cache_dir=cache_dir,\n        verbose=verbose,\n        url_to_name=url_to_name,\n        always=always, )\n    samples = tar_file_and_group_expander(streams, handler=handler)\n    return samples\n\n\ncached_tarfile_to_samples = filters.pipelinefilter(cached_tarfile_samples)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/compat.py",
    "content": "# Copyright (c) 2017-2019 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\nimport yaml\n\nfrom . import autodecode\nfrom . import cache\nfrom . import filters\nfrom . import shardlists\nfrom . import tariterators\nfrom .filters import reraise_exception\nfrom .paddle_utils import DataLoader\nfrom .paddle_utils import IterableDataset\nfrom .pipeline import DataPipeline\n\n\nclass FluidInterface:\n    def batched(self, batchsize):\n        return self.compose(filters.batched(batchsize))\n\n    def dynamic_batched(self, max_frames_in_batch):\n        return self.compose(filter.dynamic_batched(max_frames_in_batch))\n\n    def unbatched(self):\n        return self.compose(filters.unbatched())\n\n    def listed(self, batchsize, partial=True):\n        return self.compose(\n            filters.batched(), batchsize=batchsize, collation_fn=None)\n\n    def unlisted(self):\n        return self.compose(filters.unlisted())\n\n    def log_keys(self, logfile=None):\n        return self.compose(filters.log_keys(logfile))\n\n    def shuffle(self, size, **kw):\n        if size < 1:\n            return self\n        else:\n            return self.compose(filters.shuffle(size, **kw))\n\n    def map(self, f, handler=reraise_exception):\n        return self.compose(filters.map(f, handler=handler))\n\n    def decode(self,\n               *args,\n               pre=None,\n               post=None,\n               only=None,\n               partial=False,\n               handler=reraise_exception):\n        handlers = [\n            autodecode.ImageHandler(x) if isinstance(x, str) else x\n            for x in args\n        ]\n        decoder = autodecode.Decoder(\n            handlers, pre=pre, post=post, only=only, partial=partial)\n        return self.map(decoder, handler=handler)\n\n    def map_dict(self, handler=reraise_exception, **kw):\n        return self.compose(filters.map_dict(handler=handler, **kw))\n\n    def select(self, predicate, **kw):\n        return self.compose(filters.select(predicate, **kw))\n\n    def to_tuple(self, *args, handler=reraise_exception):\n        return self.compose(filters.to_tuple(*args, handler=handler))\n\n    def map_tuple(self, *args, handler=reraise_exception):\n        return self.compose(filters.map_tuple(*args, handler=handler))\n\n    def slice(self, *args):\n        return self.compose(filters.slice(*args))\n\n    def rename(self, **kw):\n        return self.compose(filters.rename(**kw))\n\n    def rsample(self, p=0.5):\n        return self.compose(filters.rsample(p))\n\n    def rename_keys(self, *args, **kw):\n        return self.compose(filters.rename_keys(*args, **kw))\n\n    def extract_keys(self, *args, **kw):\n        return self.compose(filters.extract_keys(*args, **kw))\n\n    def xdecode(self, *args, **kw):\n        return self.compose(filters.xdecode(*args, **kw))\n\n    def audio_data_filter(self, *args, **kw):\n        return self.compose(filters.audio_data_filter(*args, **kw))\n\n    def audio_tokenize(self, *args, **kw):\n        return self.compose(filters.audio_tokenize(*args, **kw))\n\n    def resample(self, *args, **kw):\n        return self.compose(filters.resample(*args, **kw))\n\n    def audio_compute_fbank(self, *args, **kw):\n        return self.compose(filters.audio_compute_fbank(*args, **kw))\n\n    def audio_spec_aug(self, *args, **kw):\n        return self.compose(filters.audio_spec_aug(*args, **kw))\n\n    def sort(self, size=500):\n        return self.compose(filters.sort(size))\n\n    def audio_padding(self):\n        return self.compose(filters.audio_padding())\n\n    def audio_cmvn(self, cmvn_file):\n        return self.compose(filters.audio_cmvn(cmvn_file))\n\n\nclass WebDataset(DataPipeline, FluidInterface):\n    \"\"\"Small fluid-interface wrapper for DataPipeline.\"\"\"\n\n    def __init__(\n            self,\n            urls,\n            handler=reraise_exception,\n            resampled=False,\n            repeat=False,\n            shardshuffle=None,\n            cache_size=0,\n            cache_dir=None,\n            detshuffle=False,\n            nodesplitter=shardlists.single_node_only,\n            verbose=False, ):\n        super().__init__()\n        if isinstance(urls, IterableDataset):\n            assert not resampled\n            self.append(urls)\n        elif isinstance(urls, str) and (urls.endswith(\".yaml\") or\n                                        urls.endswith(\".yml\")):\n            with (open(urls)) as stream:\n                spec = yaml.safe_load(stream)\n            assert \"datasets\" in spec\n            self.append(shardlists.MultiShardSample(spec))\n        elif isinstance(urls, dict):\n            assert \"datasets\" in urls\n            self.append(shardlists.MultiShardSample(urls))\n        elif resampled:\n            self.append(shardlists.ResampledShards(urls))\n        else:\n            self.append(shardlists.SimpleShardList(urls))\n            self.append(nodesplitter)\n            self.append(shardlists.split_by_worker)\n            if shardshuffle is True:\n                shardshuffle = 100\n            if shardshuffle is not None:\n                if detshuffle:\n                    self.append(filters.detshuffle(shardshuffle))\n                else:\n                    self.append(filters.shuffle(shardshuffle))\n        if cache_size == 0:\n            self.append(tariterators.tarfile_to_samples(handler=handler))\n        else:\n            assert cache_size == -1 or cache_size > 0\n            self.append(\n                cache.cached_tarfile_to_samples(\n                    handler=handler,\n                    verbose=verbose,\n                    cache_size=cache_size,\n                    cache_dir=cache_dir, ))\n\n\nclass FluidWrapper(DataPipeline, FluidInterface):\n    \"\"\"Small fluid-interface wrapper for DataPipeline.\"\"\"\n\n    def __init__(self, initial):\n        super().__init__()\n        self.append(initial)\n\n\nclass WebLoader(DataPipeline, FluidInterface):\n    def __init__(self, *args, **kw):\n        super().__init__(DataLoader(*args, **kw))\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/extradatasets.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n\"\"\"Train PyTorch models directly from POSIX tar archive.\n\nCode works locally or over HTTP connections.\n\"\"\"\nfrom . import utils\nfrom .paddle_utils import IterableDataset\nfrom .utils import PipelineStage\n\n\nclass MockDataset(IterableDataset):\n    \"\"\"MockDataset.\n\n    A mock dataset for performance testing and unit testing.\n    \"\"\"\n\n    def __init__(self, sample, length):\n        \"\"\"Create a mock dataset instance.\n\n        :param sample: the sample to be returned repeatedly\n        :param length: the length of the mock dataset\n        \"\"\"\n        self.sample = sample\n        self.length = length\n\n    def __iter__(self):\n        \"\"\"Return an iterator over this mock dataset.\"\"\"\n        for i in range(self.length):\n            yield self.sample\n\n\nclass repeatedly(IterableDataset, PipelineStage):\n    \"\"\"Repeatedly yield samples from a dataset.\"\"\"\n\n    def __init__(self, source, nepochs=None, nbatches=None, length=None):\n        \"\"\"Create an instance of Repeatedly.\n\n        :param nepochs: repeat for a maximum of nepochs\n        :param nbatches: repeat for a maximum of nbatches\n        \"\"\"\n        self.source = source\n        self.length = length\n        self.nbatches = nbatches\n\n    def invoke(self, source):\n        \"\"\"Return an iterator that iterates repeatedly over a source.\"\"\"\n        return utils.repeatedly(\n            source,\n            nepochs=self.nepochs,\n            nbatches=self.nbatches, )\n\n\nclass with_epoch(IterableDataset):\n    \"\"\"Change the actual and nominal length of an IterableDataset.\n\n    This will continuously iterate through the original dataset, but\n    impose new epoch boundaries at the given length/nominal.\n    This exists mainly as a workaround for the odd logic in DataLoader.\n    It is also useful for choosing smaller nominal epoch sizes with\n    very large datasets.\n\n    \"\"\"\n\n    def __init__(self, dataset, length):\n        \"\"\"Chop the dataset to the given length.\n\n        :param dataset: IterableDataset\n        :param length: declared length of the dataset\n        :param nominal: nominal length of dataset (if different from declared)\n        \"\"\"\n        super().__init__()\n        self.length = length\n        self.source = None\n\n    def __getstate__(self):\n        \"\"\"Return the pickled state of the dataset.\n\n        This resets the dataset iterator, since that can't be pickled.\n        \"\"\"\n        result = dict(self.__dict__)\n        result[\"source\"] = None\n        return result\n\n    def invoke(self, dataset):\n        \"\"\"Return an iterator over the dataset.\n\n        This iterator returns as many samples as given by the `length`\n        parameter.\n        \"\"\"\n        if self.source is None:\n            self.source = iter(dataset)\n        for i in range(self.length):\n            try:\n                sample = next(self.source)\n            except StopIteration:\n                self.source = iter(dataset)\n                try:\n                    sample = next(self.source)\n                except StopIteration:\n                    return\n            yield sample\n        self.source = None\n\n\nclass with_length(IterableDataset, PipelineStage):\n    \"\"\"Repeatedly yield samples from a dataset.\"\"\"\n\n    def __init__(self, dataset, length):\n        \"\"\"Create an instance of Repeatedly.\n\n        :param dataset: source dataset\n        :param length: stated length\n        \"\"\"\n        super().__init__()\n        self.dataset = dataset\n        self.length = length\n\n    def invoke(self, dataset):\n        \"\"\"Return an iterator that iterates repeatedly over a source.\"\"\"\n        return iter(dataset)\n\n    def __len__(self):\n        \"\"\"Return the user specified length.\"\"\"\n        return self.length\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/filters.py",
    "content": "# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n#\n# Modified from https://github.com/webdataset/webdataset\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"A collection of iterators for data transformations.\n\nThese functions are plain iterator functions. You can find curried versions\nin webdataset.filters, and you can find IterableDataset wrappers in\nwebdataset.processing.\n\"\"\"\nimport io\nimport itertools\nimport os\nimport random\nimport re\nimport sys\nimport time\nfrom fnmatch import fnmatch\nfrom functools import reduce\n\nimport paddle\n\nfrom . import autodecode\nfrom . import utils\nfrom ..transform.cmvn import GlobalCMVN\nfrom ..transform.spec_augment import freq_mask\nfrom ..transform.spec_augment import time_mask\nfrom ..transform.spec_augment import time_warp\nfrom ..utils.tensor_utils import pad_sequence\nfrom .utils import PipelineStage\nfrom paddlespeech.audio import backends\nfrom paddlespeech.audio.compliance import kaldi\n\n\nclass FilterFunction(object):\n    \"\"\"Helper class for currying pipeline stages.\n\n    We use this roundabout construct becauce it can be pickled.\n    \"\"\"\n\n    def __init__(self, f, *args, **kw):\n        \"\"\"Create a curried function.\"\"\"\n        self.f = f\n        self.args = args\n        self.kw = kw\n\n    def __call__(self, data):\n        \"\"\"Call the curried function with the given argument.\"\"\"\n        return self.f(data, *self.args, **self.kw)\n\n    def __str__(self):\n        \"\"\"Compute a string representation.\"\"\"\n        return f\"<{self.f.__name__} {self.args} {self.kw}>\"\n\n    def __repr__(self):\n        \"\"\"Compute a string representation.\"\"\"\n        return f\"<{self.f.__name__} {self.args} {self.kw}>\"\n\n\nclass RestCurried(object):\n    \"\"\"Helper class for currying pipeline stages.\n\n    We use this roundabout construct because it can be pickled.\n    \"\"\"\n\n    def __init__(self, f):\n        \"\"\"Store the function for future currying.\"\"\"\n        self.f = f\n\n    def __call__(self, *args, **kw):\n        \"\"\"Curry with the given arguments.\"\"\"\n        return FilterFunction(self.f, *args, **kw)\n\n\ndef pipelinefilter(f):\n    \"\"\"Turn the decorated function into one that is partially applied for\n    all arguments other than the first.\"\"\"\n    result = RestCurried(f)\n    return result\n\n\ndef reraise_exception(exn):\n    \"\"\"Reraises the given exception; used as a handler.\n\n    :param exn: exception\n    \"\"\"\n    raise exn\n\n\ndef identity(x):\n    \"\"\"Return the argument.\"\"\"\n    return x\n\n\ndef compose2(f, g):\n    \"\"\"Compose two functions, g(f(x)).\"\"\"\n    return lambda x: g(f(x))\n\n\ndef compose(*args):\n    \"\"\"Compose a sequence of functions (left-to-right).\"\"\"\n    return reduce(compose2, args)\n\n\ndef pipeline(source, *args):\n    \"\"\"Write an input pipeline; first argument is source, rest are filters.\"\"\"\n    if len(args) == 0:\n        return source\n    return compose(*args)(source)\n\n\ndef getfirst(a, keys, default=None, missing_is_error=True):\n    \"\"\"Get the first matching key from a dictionary.\n\n    Keys can be specified as a list, or as a string of keys separated by ';'.\n    \"\"\"\n    if isinstance(keys, str):\n        assert \" \" not in keys\n        keys = keys.split(\";\")\n    for k in keys:\n        if k in a:\n            return a[k]\n    if missing_is_error:\n        raise ValueError(f\"didn't find {keys} in {list(a.keys())}\")\n    return default\n\n\ndef parse_field_spec(fields):\n    \"\"\"Parse a specification for a list of fields to be extracted.\n\n    Keys are separated by spaces in the spec. Each key can itself\n    be composed of key alternatives separated by ';'.\n    \"\"\"\n    if isinstance(fields, str):\n        fields = fields.split()\n    return [field.split(\";\") for field in fields]\n\n\ndef transform_with(sample, transformers):\n    \"\"\"Transform a list of values using a list of functions.\n\n    sample: list of values\n    transformers: list of functions\n\n    If there are fewer transformers than inputs, or if a transformer\n    function is None, then the identity function is used for the\n    corresponding sample fields.\n    \"\"\"\n    if transformers is None or len(transformers) == 0:\n        return sample\n    result = list(sample)\n    assert len(transformers) <= len(sample)\n    for i in range(len(transformers)):  # skipcq: PYL-C0200\n        f = transformers[i]\n        if f is not None:\n            result[i] = f(sample[i])\n    return result\n\n\n###\n# Iterators\n###\n\n\ndef _info(data, fmt=None, n=3, every=-1, width=50, stream=sys.stderr, name=\"\"):\n    \"\"\"Print information about the samples that are passing through.\n\n    :param data: source iterator\n    :param fmt: format statement (using sample dict as keyword)\n    :param n: when to stop\n    :param every: how often to print\n    :param width: maximum width\n    :param stream: output stream\n    :param name: identifier printed before any output\n    \"\"\"\n    for i, sample in enumerate(data):\n        if i < n or (every > 0 and (i + 1) % every == 0):\n            if fmt is None:\n                print(\"---\", name, file=stream)\n                for k, v in sample.items():\n                    print(k, repr(v)[:width], file=stream)\n            else:\n                print(fmt.format(**sample), file=stream)\n        yield sample\n\n\ninfo = pipelinefilter(_info)\n\n\ndef pick(buf, rng):\n    k = rng.randint(0, len(buf) - 1)\n    sample = buf[k]\n    buf[k] = buf[-1]\n    buf.pop()\n    return sample\n\n\ndef _shuffle(data, bufsize=1000, initial=100, rng=None, handler=None):\n    \"\"\"Shuffle the data in the stream.\n\n    This uses a buffer of size `bufsize`. Shuffling at\n    startup is less random; this is traded off against\n    yielding samples quickly.\n\n    data: iterator\n    bufsize: buffer size for shuffling\n    returns: iterator\n    rng: either random module or random.Random instance\n\n    \"\"\"\n    if rng is None:\n        rng = random.Random(int((os.getpid() + time.time()) * 1e9))\n    initial = min(initial, bufsize)\n    buf = []\n    for sample in data:\n        buf.append(sample)\n        if len(buf) < bufsize:\n            try:\n                buf.append(next(data))  # skipcq: PYL-R1708\n            except StopIteration:\n                pass\n        if len(buf) >= initial:\n            yield pick(buf, rng)\n    while len(buf) > 0:\n        yield pick(buf, rng)\n\n\nshuffle = pipelinefilter(_shuffle)\n\n\nclass detshuffle(PipelineStage):\n    def __init__(self, bufsize=1000, initial=100, seed=0, epoch=-1):\n        self.bufsize = bufsize\n        self.initial = initial\n        self.seed = seed\n        self.epoch = epoch\n\n    def run(self, src):\n        self.epoch += 1\n        rng = random.Random()\n        rng.seed((self.seed, self.epoch))\n        return _shuffle(src, self.bufsize, self.initial, rng)\n\n\ndef _select(data, predicate):\n    \"\"\"Select samples based on a predicate.\n\n    :param data: source iterator\n    :param predicate: predicate (function)\n    \"\"\"\n    for sample in data:\n        if predicate(sample):\n            yield sample\n\n\nselect = pipelinefilter(_select)\n\n\ndef _log_keys(data, logfile=None):\n    import fcntl\n\n    if logfile is None or logfile == \"\":\n        for sample in data:\n            yield sample\n    else:\n        with open(logfile, \"a\") as stream:\n            for i, sample in enumerate(data):\n                buf = f\"{i}\\t{sample.get('__worker__')}\\t{sample.get('__rank__')}\\t{sample.get('__key__')}\\n\"\n                try:\n                    fcntl.flock(stream.fileno(), fcntl.LOCK_EX)\n                    stream.write(buf)\n                finally:\n                    fcntl.flock(stream.fileno(), fcntl.LOCK_UN)\n                yield sample\n\n\nlog_keys = pipelinefilter(_log_keys)\n\n\ndef _minedecode(x):\n    if isinstance(x, str):\n        return autodecode.imagehandler(x)\n    else:\n        return x\n\n\ndef _decode(data, *args, handler=reraise_exception, **kw):\n    \"\"\"Decode data based on the decoding functions given as arguments.\"\"\"\n    decoder = _minedecode\n    handlers = [decoder(x) for x in args]\n    f = autodecode.Decoder(handlers, **kw)\n\n    for sample in data:\n        assert isinstance(sample, dict), sample\n        try:\n            decoded = f(sample)\n        except Exception as exn:  # skipcq: PYL-W0703\n            if handler(exn):\n                continue\n            else:\n                break\n        yield decoded\n\n\ndecode = pipelinefilter(_decode)\n\n\ndef _map(data, f, handler=reraise_exception):\n    \"\"\"Map samples.\"\"\"\n    for sample in data:\n        try:\n            result = f(sample)\n        except Exception as exn:\n            if handler(exn):\n                continue\n            else:\n                break\n        if result is None:\n            continue\n        if isinstance(sample, dict) and isinstance(result, dict):\n            result[\"__key__\"] = sample.get(\"__key__\")\n        yield result\n\n\nmap = pipelinefilter(_map)\n\n\ndef _rename(data, handler=reraise_exception, keep=True, **kw):\n    \"\"\"Rename samples based on keyword arguments.\"\"\"\n    for sample in data:\n        try:\n            if not keep:\n                yield {\n                    k: getfirst(sample, v, missing_is_error=True)\n                    for k, v in kw.items()\n                }\n            else:\n\n                def listify(v):\n                    return v.split(\";\") if isinstance(v, str) else v\n\n                to_be_replaced = {x for v in kw.values() for x in listify(v)}\n                result = {\n                    k: v\n                    for k, v in sample.items() if k not in to_be_replaced\n                }\n                result.update({\n                    k: getfirst(sample, v, missing_is_error=True)\n                    for k, v in kw.items()\n                })\n                yield result\n        except Exception as exn:\n            if handler(exn):\n                continue\n            else:\n                break\n\n\nrename = pipelinefilter(_rename)\n\n\ndef _associate(data, associator, **kw):\n    \"\"\"Associate additional data with samples.\"\"\"\n    for sample in data:\n        if callable(associator):\n            extra = associator(sample[\"__key__\"])\n        else:\n            extra = associator.get(sample[\"__key__\"], {})\n        sample.update(extra)  # destructive\n        yield sample\n\n\nassociate = pipelinefilter(_associate)\n\n\ndef _map_dict(data, handler=reraise_exception, **kw):\n    \"\"\"Map the entries in a dict sample with individual functions.\"\"\"\n    assert len(list(kw.keys())) > 0\n    for key, f in kw.items():\n        assert callable(f), (key, f)\n\n    for sample in data:\n        assert isinstance(sample, dict)\n        try:\n            for k, f in kw.items():\n                sample[k] = f(sample[k])\n        except Exception as exn:\n            if handler(exn):\n                continue\n            else:\n                break\n        yield sample\n\n\nmap_dict = pipelinefilter(_map_dict)\n\n\ndef _to_tuple(data,\n              *args,\n              handler=reraise_exception,\n              missing_is_error=True,\n              none_is_error=None):\n    \"\"\"Convert dict samples to tuples.\"\"\"\n    if none_is_error is None:\n        none_is_error = missing_is_error\n    if len(args) == 1 and isinstance(args[0], str) and \" \" in args[0]:\n        args = args[0].split()\n\n    for sample in data:\n        try:\n            result = tuple([\n                getfirst(sample, f, missing_is_error=missing_is_error)\n                for f in args\n            ])\n            if none_is_error and any(x is None for x in result):\n                raise ValueError(f\"to_tuple {args} got {sample.keys()}\")\n            yield result\n        except Exception as exn:\n            if handler(exn):\n                continue\n            else:\n                break\n\n\nto_tuple = pipelinefilter(_to_tuple)\n\n\ndef _map_tuple(data, *args, handler=reraise_exception):\n    \"\"\"Map the entries of a tuple with individual functions.\"\"\"\n    args = [f if f is not None else utils.identity for f in args]\n    for f in args:\n        assert callable(f), f\n    for sample in data:\n        assert isinstance(sample, (list, tuple))\n        sample = list(sample)\n        n = min(len(args), len(sample))\n        try:\n            for i in range(n):\n                sample[i] = args[i](sample[i])\n        except Exception as exn:\n            if handler(exn):\n                continue\n            else:\n                break\n        yield tuple(sample)\n\n\nmap_tuple = pipelinefilter(_map_tuple)\n\n\ndef _unlisted(data):\n    \"\"\"Turn batched data back into unbatched data.\"\"\"\n    for batch in data:\n        assert isinstance(batch, list), sample\n        for sample in batch:\n            yield sample\n\n\nunlisted = pipelinefilter(_unlisted)\n\n\ndef _unbatched(data):\n    \"\"\"Turn batched data back into unbatched data.\"\"\"\n    for sample in data:\n        assert isinstance(sample, (tuple, list)), sample\n        assert len(sample) > 0\n        for i in range(len(sample[0])):\n            yield tuple(x[i] for x in sample)\n\n\nunbatched = pipelinefilter(_unbatched)\n\n\ndef _rsample(data, p=0.5):\n    \"\"\"Randomly subsample a stream of data.\"\"\"\n    assert p >= 0.0 and p <= 1.0\n    for sample in data:\n        if random.uniform(0.0, 1.0) < p:\n            yield sample\n\n\nrsample = pipelinefilter(_rsample)\n\nslice = pipelinefilter(itertools.islice)\n\n\ndef _extract_keys(source,\n                  *patterns,\n                  duplicate_is_error=True,\n                  ignore_missing=False):\n    for sample in source:\n        result = []\n        for pattern in patterns:\n            pattern = pattern.split(\";\") if isinstance(pattern,\n                                                       str) else pattern\n            matches = [\n                x for x in sample.keys()\n                if any(fnmatch(\".\" + x, p) for p in pattern)\n            ]\n            if len(matches) == 0:\n                if ignore_missing:\n                    continue\n                else:\n                    raise ValueError(\n                        f\"Cannot find {pattern} in sample keys {sample.keys()}.\")\n            if len(matches) > 1 and duplicate_is_error:\n                raise ValueError(\n                    f\"Multiple sample keys {sample.keys()} match {pattern}.\")\n            value = sample[matches[0]]\n            result.append(value)\n        yield tuple(result)\n\n\nextract_keys = pipelinefilter(_extract_keys)\n\n\ndef _rename_keys(source,\n                 *args,\n                 keep_unselected=False,\n                 must_match=True,\n                 duplicate_is_error=True,\n                 **kw):\n    renamings = [(pattern, output) for output, pattern in args]\n    renamings += [(pattern, output) for output, pattern in kw.items()]\n    for sample in source:\n        new_sample = {}\n        matched = {k: False for k, _ in renamings}\n        for path, value in sample.items():\n            fname = re.sub(r\".*/\", \"\", path)\n            new_name = None\n            for pattern, name in renamings[::-1]:\n                if fnmatch(fname.lower(), pattern):\n                    matched[pattern] = True\n                    new_name = name\n                    break\n            if new_name is None:\n                if keep_unselected:\n                    new_sample[path] = value\n                continue\n            if new_name in new_sample:\n                if duplicate_is_error:\n                    raise ValueError(\n                        f\"Duplicate value in sample {sample.keys()} after rename.\"\n                    )\n                continue\n            new_sample[new_name] = value\n        if must_match and not all(matched.values()):\n            raise ValueError(\n                f\"Not all patterns ({matched}) matched sample keys ({sample.keys()}).\"\n            )\n\n        yield new_sample\n\n\nrename_keys = pipelinefilter(_rename_keys)\n\n\ndef decode_bin(stream):\n    return stream.read()\n\n\ndef decode_text(stream):\n    binary = stream.read()\n    return binary.decode(\"utf-8\")\n\n\ndef decode_pickle(stream):\n    return pickle.load(stream)\n\n\ndefault_decoders = [\n    (\"*.bin\", decode_bin),\n    (\"*.txt\", decode_text),\n    (\"*.pyd\", decode_pickle),\n]\n\n\ndef find_decoder(decoders, path):\n    fname = re.sub(r\".*/\", \"\", path)\n    if fname.startswith(\"__\"):\n        return lambda x: x\n    for pattern, fun in decoders[::-1]:\n        if fnmatch(fname.lower(), pattern) or fnmatch(\".\" + fname.lower(),\n                                                      pattern):\n            return fun\n    return None\n\n\ndef _xdecode(\n        source,\n        *args,\n        must_decode=True,\n        defaults=default_decoders,\n        **kw, ):\n    decoders = list(defaults) + list(args)\n    decoders += [(\"*.\" + k, v) for k, v in kw.items()]\n    for sample in source:\n        new_sample = {}\n        for path, data in sample.items():\n            if path.startswith(\"__\"):\n                new_sample[path] = data\n                continue\n            decoder = find_decoder(decoders, path)\n            if decoder is False:\n                value = data\n            elif decoder is None:\n                if must_decode:\n                    raise ValueError(f\"No decoder found for {path}.\")\n                value = data\n            else:\n                if isinstance(data, bytes):\n                    data = io.BytesIO(data)\n                value = decoder(data)\n            new_sample[path] = value\n        yield new_sample\n\n\nxdecode = pipelinefilter(_xdecode)\n\n\ndef _audio_data_filter(source,\n                       frame_shift=10,\n                       max_length=10240,\n                       min_length=10,\n                       token_max_length=200,\n                       token_min_length=1,\n                       min_output_input_ratio=0.0005,\n                       max_output_input_ratio=1):\n    \"\"\" Filter sample according to feature and label length\n        Inplace operation.\n\n        Args::\n            source: Iterable[{fname, wav, label, sample_rate}]\n            frame_shift: length of frame shift (ms)\n            max_length: drop utterance which is greater than max_length(10ms)\n            min_length: drop utterance which is less than min_length(10ms)\n            token_max_length: drop utterance which is greater than\n                token_max_length, especially when use char unit for\n                english modeling\n            token_min_length: drop utterance which is\n                less than token_max_length\n            min_output_input_ratio: minimal ration of\n                token_length / feats_length(10ms)\n            max_output_input_ratio: maximum ration of\n                token_length / feats_length(10ms)\n\n        Returns:\n            Iterable[{fname, wav, label, sample_rate}]\n    \"\"\"\n    for sample in source:\n        assert 'sample_rate' in sample\n        assert 'wav' in sample\n        assert 'label' in sample\n        # sample['wav'] is paddle.Tensor, we have 100 frames every second (default)\n        num_frames = sample['wav'].shape[1] / sample['sample_rate'] * (\n            1000 / frame_shift)\n        if num_frames < min_length:\n            continue\n        if num_frames > max_length:\n            continue\n        if len(sample['label']) < token_min_length:\n            continue\n        if len(sample['label']) > token_max_length:\n            continue\n        if num_frames != 0:\n            if len(sample['label']) / num_frames < min_output_input_ratio:\n                continue\n            if len(sample['label']) / num_frames > max_output_input_ratio:\n                continue\n        yield sample\n\n\naudio_data_filter = pipelinefilter(_audio_data_filter)\n\n\ndef _audio_tokenize(source,\n                    symbol_table,\n                    bpe_model=None,\n                    non_lang_syms=None,\n                    split_with_space=False):\n    \"\"\" Decode text to chars or BPE\n        Inplace operation\n\n        Args:\n            source: Iterable[{fname, wav, txt, sample_rate}]\n\n        Returns:\n            Iterable[{fname, wav, txt, tokens, label, sample_rate}]\n    \"\"\"\n    if non_lang_syms is not None:\n        non_lang_syms_pattern = re.compile(r\"(\\[[^\\[\\]]+\\]|<[^<>]+>|{[^{}]+})\")\n    else:\n        non_lang_syms = {}\n        non_lang_syms_pattern = None\n\n    if bpe_model is not None:\n        import sentencepiece as spm\n        sp = spm.SentencePieceProcessor()\n        sp.load(bpe_model)\n    else:\n        sp = None\n\n    for sample in source:\n        assert 'txt' in sample\n        txt = sample['txt'].strip()\n        if non_lang_syms_pattern is not None:\n            parts = non_lang_syms_pattern.split(txt.upper())\n            parts = [w for w in parts if len(w.strip()) > 0]\n        else:\n            parts = [txt]\n\n        label = []\n        tokens = []\n        for part in parts:\n            if part in non_lang_syms:\n                tokens.append(part)\n            else:\n                if bpe_model is not None:\n                    tokens.extend(__tokenize_by_bpe_model(sp, part))\n                else:\n                    if split_with_space:\n                        part = part.split(\" \")\n                    for ch in part:\n                        if ch == ' ':\n                            ch = \"<space>\"\n                        tokens.append(ch)\n\n        for ch in tokens:\n            if ch in symbol_table:\n                label.append(symbol_table[ch])\n            elif '<unk>' in symbol_table:\n                label.append(symbol_table['<unk>'])\n\n        sample['tokens'] = tokens\n        sample['label'] = label\n        yield sample\n\n\naudio_tokenize = pipelinefilter(_audio_tokenize)\n\n\ndef _audio_resample(source, resample_rate=16000):\n    \"\"\" Resample data.\n        Inplace operation.\n\n        Args:\n            data: Iterable[{fname, wav, label, sample_rate}]\n            resample_rate: target resample rate\n\n        Returns:\n            Iterable[{fname, wav, label, sample_rate}]\n    \"\"\"\n    for sample in source:\n        assert 'sample_rate' in sample\n        assert 'wav' in sample\n        sample_rate = sample['sample_rate']\n        waveform = sample['wav']\n        if sample_rate != resample_rate:\n            sample['sample_rate'] = resample_rate\n            sample['wav'] = paddle.to_tensor(\n                backends.soundfile_backend.resample(\n                    waveform.numpy(),\n                    src_sr=sample_rate,\n                    target_sr=resample_rate))\n        yield sample\n\n\naudio_resample = pipelinefilter(_audio_resample)\n\n\ndef _audio_compute_fbank(source,\n                         num_mel_bins=80,\n                         frame_length=25,\n                         frame_shift=10,\n                         dither=0.0):\n    \"\"\" Extract fbank\n\n        Args:\n            source: Iterable[{fname, wav, label, sample_rate}]\n            num_mel_bins: number of mel filter bank\n            frame_length: length of one frame (ms)\n            frame_shift: length of frame shift (ms)\n            dither: value of dither\n\n        Returns:\n            Iterable[{fname, feat, label}]\n    \"\"\"\n    for sample in source:\n        assert 'sample_rate' in sample\n        assert 'wav' in sample\n        assert 'fname' in sample\n        assert 'label' in sample\n        sample_rate = sample['sample_rate']\n        waveform = sample['wav']\n        waveform = waveform * (1 << 15)\n        # Only keep fname, feat, label\n        mat = kaldi.fbank(\n            waveform,\n            n_mels=num_mel_bins,\n            frame_length=frame_length,\n            frame_shift=frame_shift,\n            dither=dither,\n            energy_floor=0.0,\n            sr=sample_rate)\n        yield dict(fname=sample['fname'], label=sample['label'], feat=mat)\n\n\naudio_compute_fbank = pipelinefilter(_audio_compute_fbank)\n\n\ndef _audio_spec_aug(\n        source,\n        max_w=5,\n        w_inplace=True,\n        w_mode=\"PIL\",\n        max_f=30,\n        num_f_mask=2,\n        f_inplace=True,\n        f_replace_with_zero=False,\n        max_t=40,\n        num_t_mask=2,\n        t_inplace=True,\n        t_replace_with_zero=False, ):\n    \"\"\" Do spec augmentation\n        Inplace operation\n\n        Args:\n            source: Iterable[{fname, feat, label}]\n            max_w: max width of time warp\n            w_inplace: whether to inplace the original data while time warping\n            w_mode: time warp mode\n            max_f: max width of freq mask\n            num_f_mask: number of freq mask to apply\n            f_inplace: whether to inplace the original data while frequency masking\n            f_replace_with_zero: use zero to mask\n            max_t: max width of time mask\n            num_t_mask: number of time mask to apply\n            t_inplace: whether to inplace the original data while time masking\n            t_replace_with_zero: use zero to mask\n            \n        Returns\n            Iterable[{fname, feat, label}]\n     \"\"\"\n    for sample in source:\n        x = sample['feat']\n        x = x.numpy()\n        x = time_warp(x, max_time_warp=max_w, inplace=w_inplace, mode=w_mode)\n        x = freq_mask(\n            x,\n            F=max_f,\n            n_mask=num_f_mask,\n            inplace=f_inplace,\n            replace_with_zero=f_replace_with_zero)\n        x = time_mask(\n            x,\n            T=max_t,\n            n_mask=num_t_mask,\n            inplace=t_inplace,\n            replace_with_zero=t_replace_with_zero)\n        sample['feat'] = paddle.to_tensor(x, dtype=paddle.float32)\n        yield sample\n\n\naudio_spec_aug = pipelinefilter(_audio_spec_aug)\n\n\ndef _sort(source, sort_size=500):\n    \"\"\" Sort the data by feature length.\n        Sort is used after shuffle and before batch, so we can group\n        utts with similar lengths into a batch, and `sort_size` should\n        be less than `shuffle_size`\n\n        Args:\n            source: Iterable[{fname, feat, label}]\n            sort_size: buffer size for sort\n\n        Returns:\n            Iterable[{fname, feat, label}]\n    \"\"\"\n\n    buf = []\n    for sample in source:\n        buf.append(sample)\n        if len(buf) >= sort_size:\n            buf.sort(key=lambda x: x['feat'].shape[0])\n            for x in buf:\n                yield x\n            buf = []\n    # The sample left over\n    buf.sort(key=lambda x: x['feat'].shape[0])\n    for x in buf:\n        yield x\n\n\nsort = pipelinefilter(_sort)\n\n\ndef _batched(source, batch_size=16):\n    \"\"\" Static batch the data by `batch_size`\n\n        Args:\n            data: Iterable[{fname, feat, label}]\n            batch_size: batch size\n\n        Returns:\n            Iterable[List[{fname, feat, label}]]\n    \"\"\"\n    buf = []\n    for sample in source:\n        buf.append(sample)\n        if len(buf) >= batch_size:\n            yield buf\n            buf = []\n    if len(buf) > 0:\n        yield buf\n\n\nbatched = pipelinefilter(_batched)\n\n\ndef dynamic_batched(source, max_frames_in_batch=12000):\n    \"\"\" Dynamic batch the data until the total frames in batch\n        reach `max_frames_in_batch`\n\n        Args:\n            source: Iterable[{fname, feat, label}]\n            max_frames_in_batch: max_frames in one batch\n\n        Returns:\n            Iterable[List[{fname, feat, label}]]\n    \"\"\"\n    buf = []\n    longest_frames = 0\n    for sample in source:\n        assert 'feat' in sample\n        assert isinstance(sample['feat'], paddle.Tensor)\n        new_sample_frames = sample['feat'].size(0)\n        longest_frames = max(longest_frames, new_sample_frames)\n        frames_after_padding = longest_frames * (len(buf) + 1)\n        if frames_after_padding > max_frames_in_batch:\n            yield buf\n            buf = [sample]\n            longest_frames = new_sample_frames\n        else:\n            buf.append(sample)\n    if len(buf) > 0:\n        yield buf\n\n\ndef _audio_padding(source):\n    \"\"\" Padding the data into training data\n\n        Args:\n            source: Iterable[List[{fname, feat, label}]]\n\n        Returns:\n            Iterable[Tuple(fname, feats, labels, feats lengths, label lengths)]\n    \"\"\"\n    for sample in source:\n        assert isinstance(sample, list)\n        feats_length = paddle.to_tensor(\n            [x['feat'].shape[0] for x in sample], dtype=\"int64\")\n        order = paddle.argsort(feats_length, descending=True)\n        feats_lengths = paddle.to_tensor(\n            [sample[i]['feat'].shape[0] for i in order], dtype=\"int64\")\n        sorted_feats = [sample[i]['feat'] for i in order]\n        sorted_keys = [sample[i]['fname'] for i in order]\n        sorted_labels = [\n            paddle.to_tensor(sample[i]['label'], dtype=\"int32\") for i in order\n        ]\n        label_lengths = paddle.to_tensor(\n            [x.shape[0] for x in sorted_labels], dtype=\"int64\")\n        padded_feats = pad_sequence(\n            sorted_feats, batch_first=True, padding_value=0)\n        padding_labels = pad_sequence(\n            sorted_labels, batch_first=True, padding_value=-1)\n\n        yield (sorted_keys, padded_feats, feats_lengths, padding_labels,\n               label_lengths)\n\n\naudio_padding = pipelinefilter(_audio_padding)\n\n\ndef _audio_cmvn(source, cmvn_file):\n    global_cmvn = GlobalCMVN(cmvn_file)\n    for batch in source:\n        sorted_keys, padded_feats, feats_lengths, padding_labels, label_lengths = batch\n        padded_feats = padded_feats.numpy()\n        padded_feats = global_cmvn(padded_feats)\n        padded_feats = paddle.to_tensor(padded_feats, dtype=paddle.float32)\n        yield (sorted_keys, padded_feats, feats_lengths, padding_labels,\n               label_lengths)\n\n\naudio_cmvn = pipelinefilter(_audio_cmvn)\n\n\ndef _placeholder(source):\n    for data in source:\n        yield data\n\n\nplaceholder = pipelinefilter(_placeholder)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/gopen.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n#\n\"\"\"Open URLs by calling subcommands.\"\"\"\nimport os\nimport re\nimport sys\nfrom subprocess import PIPE\nfrom subprocess import Popen\nfrom urllib.parse import urlparse\n\n# global used for printing additional node information during verbose output\ninfo = {}\n\n\nclass Pipe:\n    \"\"\"Wrapper class for subprocess.Pipe.\n\n    This class looks like a stream from the outside, but it checks\n    subprocess status and handles timeouts with exceptions.\n    This way, clients of the class do not need to know that they are\n    dealing with subprocesses.\n\n    :param *args: passed to `subprocess.Pipe`\n    :param **kw: passed to `subprocess.Pipe`\n    :param timeout: timeout for closing/waiting\n    :param ignore_errors: don't raise exceptions on subprocess errors\n    :param ignore_status: list of status codes to ignore\n    \"\"\"\n\n    def __init__(\n            self,\n            *args,\n            mode=None,\n            timeout=7200.0,\n            ignore_errors=False,\n            ignore_status=[],\n            **kw, ):\n        \"\"\"Create an IO Pipe.\"\"\"\n        self.ignore_errors = ignore_errors\n        self.ignore_status = [0] + ignore_status\n        self.timeout = timeout\n        self.args = (args, kw)\n        if mode[0] == \"r\":\n            self.proc = Popen(*args, stdout=PIPE, **kw)\n            self.stream = self.proc.stdout\n            if self.stream is None:\n                raise ValueError(f\"{args}: couldn't open\")\n        elif mode[0] == \"w\":\n            self.proc = Popen(*args, stdin=PIPE, **kw)\n            self.stream = self.proc.stdin\n            if self.stream is None:\n                raise ValueError(f\"{args}: couldn't open\")\n        self.status = None\n\n    def __str__(self):\n        return f\"<Pipe {self.args}>\"\n\n    def check_status(self):\n        \"\"\"Poll the process and handle any errors.\"\"\"\n        status = self.proc.poll()\n        if status is not None:\n            self.wait_for_child()\n\n    def wait_for_child(self):\n        \"\"\"Check the status variable and raise an exception if necessary.\"\"\"\n        verbose = int(os.environ.get(\"GOPEN_VERBOSE\", 0))\n        if self.status is not None and verbose:\n            # print(f\"(waiting again [{self.status} {os.getpid()}:{self.proc.pid}])\", file=sys.stderr)\n            return\n        self.status = self.proc.wait()\n        if verbose:\n            print(\n                f\"pipe exit [{self.status} {os.getpid()}:{self.proc.pid}] {self.args} {info}\",\n                file=sys.stderr, )\n        if self.status not in self.ignore_status and not self.ignore_errors:\n            raise Exception(f\"{self.args}: exit {self.status} (read) {info}\")\n\n    def read(self, *args, **kw):\n        \"\"\"Wrap stream.read and checks status.\"\"\"\n        result = self.stream.read(*args, **kw)\n        self.check_status()\n        return result\n\n    def write(self, *args, **kw):\n        \"\"\"Wrap stream.write and checks status.\"\"\"\n        result = self.stream.write(*args, **kw)\n        self.check_status()\n        return result\n\n    def readLine(self, *args, **kw):\n        \"\"\"Wrap stream.readLine and checks status.\"\"\"\n        result = self.stream.readLine(*args, **kw)\n        self.status = self.proc.poll()\n        self.check_status()\n        return result\n\n    def close(self):\n        \"\"\"Wrap stream.close, wait for the subprocess, and handle errors.\"\"\"\n        self.stream.close()\n        self.status = self.proc.wait(self.timeout)\n        self.wait_for_child()\n\n    def __enter__(self):\n        \"\"\"Context handler.\"\"\"\n        return self\n\n    def __exit__(self, etype, value, traceback):\n        \"\"\"Context handler.\"\"\"\n        self.close()\n\n\ndef set_options(obj,\n                timeout=None,\n                ignore_errors=None,\n                ignore_status=None,\n                handler=None):\n    \"\"\"Set options for Pipes.\n\n    This function can be called on any stream. It will set pipe options only\n    when its argument is a pipe.\n\n    :param obj: any kind of stream\n    :param timeout: desired timeout\n    :param ignore_errors: desired ignore_errors setting\n    :param ignore_status: desired ignore_status setting\n    :param handler: desired error handler\n    \"\"\"\n    if not isinstance(obj, Pipe):\n        return False\n    if timeout is not None:\n        obj.timeout = timeout\n    if ignore_errors is not None:\n        obj.ignore_errors = ignore_errors\n    if ignore_status is not None:\n        obj.ignore_status = ignore_status\n    if handler is not None:\n        obj.handler = handler\n    return True\n\n\ndef gopen_file(url, mode=\"rb\", bufsize=8192):\n    \"\"\"Open a file.\n\n    This works for local files, files over HTTP, and pipe: files.\n\n    :param url: URL to be opened\n    :param mode: mode to open it with\n    :param bufsize: requested buffer size\n    \"\"\"\n    return open(url, mode)\n\n\ndef gopen_pipe(url, mode=\"rb\", bufsize=8192):\n    \"\"\"Use gopen to open a pipe.\n\n    :param url: a pipe: URL\n    :param mode: desired mode\n    :param bufsize: desired buffer size\n    \"\"\"\n    assert url.startswith(\"pipe:\")\n    cmd = url[5:]\n    if mode[0] == \"r\":\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141], )  # skipcq: BAN-B604\n    elif mode[0] == \"w\":\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141], )  # skipcq: BAN-B604\n    else:\n        raise ValueError(f\"{mode}: unknown mode\")\n\n\ndef gopen_curl(url, mode=\"rb\", bufsize=8192):\n    \"\"\"Open a URL with `curl`.\n\n    :param url: url (usually, http:// etc.)\n    :param mode: file mode\n    :param bufsize: buffer size\n    \"\"\"\n    if mode[0] == \"r\":\n        cmd = f\"curl -s -L '{url}'\"\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141, 23], )  # skipcq: BAN-B604\n    elif mode[0] == \"w\":\n        cmd = f\"curl -s -L -T - '{url}'\"\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141, 26], )  # skipcq: BAN-B604\n    else:\n        raise ValueError(f\"{mode}: unknown mode\")\n\n\ndef gopen_htgs(url, mode=\"rb\", bufsize=8192):\n    \"\"\"Open a URL with `curl`.\n\n    :param url: url (usually, http:// etc.)\n    :param mode: file mode\n    :param bufsize: buffer size\n    \"\"\"\n    if mode[0] == \"r\":\n        url = re.sub(r\"(?i)^htgs://\", \"gs://\", url)\n        cmd = f\"curl -s -L '{url}'\"\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141, 23], )  # skipcq: BAN-B604\n    elif mode[0] == \"w\":\n        raise ValueError(f\"{mode}: cannot write\")\n    else:\n        raise ValueError(f\"{mode}: unknown mode\")\n\n\ndef gopen_gsutil(url, mode=\"rb\", bufsize=8192):\n    \"\"\"Open a URL with `curl`.\n\n    :param url: url (usually, http:// etc.)\n    :param mode: file mode\n    :param bufsize: buffer size\n    \"\"\"\n    if mode[0] == \"r\":\n        cmd = f\"gsutil cat '{url}'\"\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141, 23], )  # skipcq: BAN-B604\n    elif mode[0] == \"w\":\n        cmd = f\"gsutil cp - '{url}'\"\n        return Pipe(\n            cmd,\n            mode=mode,\n            shell=True,\n            bufsize=bufsize,\n            ignore_status=[141, 26], )  # skipcq: BAN-B604\n    else:\n        raise ValueError(f\"{mode}: unknown mode\")\n\n\ndef gopen_error(url, *args, **kw):\n    \"\"\"Raise a value error.\n\n    :param url: url\n    :param args: other arguments\n    :param kw: other keywords\n    \"\"\"\n    raise ValueError(f\"{url}: no gopen handler defined\")\n\n\n\"\"\"A dispatch table mapping URL schemes to handlers.\"\"\"\ngopen_schemes = dict(\n    __default__=gopen_error,\n    pipe=gopen_pipe,\n    http=gopen_curl,\n    https=gopen_curl,\n    sftp=gopen_curl,\n    ftps=gopen_curl,\n    scp=gopen_curl,\n    gs=gopen_gsutil,\n    htgs=gopen_htgs, )\n\n\ndef gopen(url, mode=\"rb\", bufsize=8192, **kw):\n    \"\"\"Open the URL.\n\n    This uses the `gopen_schemes` dispatch table to dispatch based\n    on scheme.\n\n    Support for the following schemes is built-in: pipe, file,\n    http, https, sftp, ftps, scp.\n\n    When no scheme is given the url is treated as a file.\n\n    You can use the OPEN_VERBOSE argument to get info about\n    files being opened.\n\n    :param url: the source URL\n    :param mode: the mode (\"rb\", \"r\")\n    :param bufsize: the buffer size\n    \"\"\"\n    global fallback_gopen\n    verbose = int(os.environ.get(\"GOPEN_VERBOSE\", 0))\n    if verbose:\n        print(\"GOPEN\", url, info, file=sys.stderr)\n    assert mode in [\"rb\", \"wb\"], mode\n    if url == \"-\":\n        if mode == \"rb\":\n            return sys.stdin.buffer\n        elif mode == \"wb\":\n            return sys.stdout.buffer\n        else:\n            raise ValueError(f\"unknown mode {mode}\")\n    pr = urlparse(url)\n    if pr.scheme == \"\":\n        bufsize = int(os.environ.get(\"GOPEN_BUFFER\", -1))\n        return open(url, mode, buffering=bufsize)\n    if pr.scheme == \"file\":\n        bufsize = int(os.environ.get(\"GOPEN_BUFFER\", -1))\n        return open(pr.path, mode, buffering=bufsize)\n    handler = gopen_schemes[\"__default__\"]\n    handler = gopen_schemes.get(pr.scheme, handler)\n    return handler(url, mode, bufsize, **kw)\n\n\ndef reader(url, **kw):\n    \"\"\"Open url with gopen and mode \"rb\".\n\n    :param url: source URL\n    :param kw: other keywords forwarded to gopen\n    \"\"\"\n    return gopen(url, \"rb\", **kw)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/handlers.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n#\n\"\"\"Pluggable exception handlers.\n\nThese are functions that take an exception as an argument and then return...\n\n- the exception (in order to re-raise it)\n- True (in order to continue and ignore the exception)\n- False (in order to ignore the exception and stop processing)\n\nThey are used as handler= arguments in much of the library.\n\"\"\"\nimport time\nimport warnings\n\n\ndef reraise_exception(exn):\n    \"\"\"Call in an exception handler to re-raise the exception.\"\"\"\n    raise exn\n\n\ndef ignore_and_continue(exn):\n    \"\"\"Call in an exception handler to ignore any exception and continue.\"\"\"\n    return True\n\n\ndef warn_and_continue(exn):\n    \"\"\"Call in an exception handler to ignore any exception, isssue a warning, and continue.\"\"\"\n    warnings.warn(repr(exn))\n    time.sleep(0.5)\n    return True\n\n\ndef ignore_and_stop(exn):\n    \"\"\"Call in an exception handler to ignore any exception and stop further processing.\"\"\"\n    return False\n\n\ndef warn_and_stop(exn):\n    \"\"\"Call in an exception handler to ignore any exception and stop further processing.\"\"\"\n    warnings.warn(repr(exn))\n    time.sleep(0.5)\n    return False\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/mix.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n\"\"\"Classes for mixing samples from multiple sources.\"\"\"\nimport random\n\nimport numpy as np\n\nfrom .paddle_utils import IterableDataset\n\n\ndef round_robin_shortest(*sources):\n    i = 0\n    while True:\n        try:\n            sample = next(sources[i % len(sources)])\n            yield sample\n        except StopIteration:\n            break\n        i += 1\n\n\ndef round_robin_longest(*sources):\n    i = 0\n    while len(sources) > 0:\n        try:\n            sample = next(sources[i])\n            i += 1\n            yield sample\n        except StopIteration:\n            del sources[i]\n\n\nclass RoundRobin(IterableDataset):\n    def __init__(self, datasets, longest=False):\n        self.datasets = datasets\n        self.longest = longest\n\n    def __iter__(self):\n        \"\"\"Return an iterator over the sources.\"\"\"\n        sources = [iter(d) for d in self.datasets]\n        if self.longest:\n            return round_robin_longest(*sources)\n        else:\n            return round_robin_shortest(*sources)\n\n\ndef random_samples(sources, probs=None, longest=False):\n    if probs is None:\n        probs = [1] * len(sources)\n    else:\n        probs = list(probs)\n    while len(sources) > 0:\n        cum = (np.array(probs) / np.sum(probs)).cumsum()\n        r = random.random()\n        i = np.searchsorted(cum, r)\n        try:\n            yield next(sources[i])\n        except StopIteration:\n            if longest:\n                del sources[i]\n                del probs[i]\n            else:\n                break\n\n\nclass RandomMix(IterableDataset):\n    def __init__(self, datasets, probs=None, longest=False):\n        self.datasets = datasets\n        self.probs = probs\n        self.longest = longest\n\n    def __iter__(self):\n        \"\"\"Return an iterator over the sources.\"\"\"\n        sources = [iter(d) for d in self.datasets]\n        return random_samples(sources, self.probs, longest=self.longest)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/paddle_utils.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n\"\"\"Mock implementations of paddle interfaces when paddle is not available.\"\"\"\n\ntry:\n    from paddle.io import DataLoader\n    from paddle.io import IterableDataset\nexcept ModuleNotFoundError:\n\n    class IterableDataset:\n        \"\"\"Empty implementation of IterableDataset when paddle is not available.\"\"\"\n\n        pass\n\n    class DataLoader:\n        \"\"\"Empty implementation of DataLoader when paddle is not available.\"\"\"\n\n        pass\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/pipeline.py",
    "content": "# Copyright (c) 2017-2019 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#%%\nimport copy\nimport sys\nfrom itertools import islice\n\nfrom .paddle_utils import DataLoader\nfrom .paddle_utils import IterableDataset\nfrom .utils import PipelineStage\n\n\ndef add_length_method(obj):\n    def length(self):\n        return self.size\n\n    Combined = type(\n        obj.__class__.__name__ + \"_Length\",\n        (obj.__class__, IterableDataset),\n        {\"__len__\": length}, )\n    obj.__class__ = Combined\n    return obj\n\n\nclass DataPipeline(IterableDataset, PipelineStage):\n    \"\"\"A pipeline starting with an IterableDataset and a series of filters.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__()\n        self.pipeline = []\n        self.length = -1\n        self.repetitions = 1\n        self.nsamples = -1\n        for arg in args:\n            if arg is None:\n                continue\n            if isinstance(arg, list):\n                self.pipeline.extend(arg)\n            else:\n                self.pipeline.append(arg)\n\n    def invoke(self, f, *args, **kwargs):\n        \"\"\"Apply a pipeline stage, possibly to the output of a previous stage.\"\"\"\n        if isinstance(f, PipelineStage):\n            return f.run(*args, **kwargs)\n        if isinstance(f, (IterableDataset, DataLoader)) and len(args) == 0:\n            return iter(f)\n        if isinstance(f, list):\n            return iter(f)\n        if callable(f):\n            result = f(*args, **kwargs)\n            return result\n        raise ValueError(f\"{f}: not a valid pipeline stage\")\n\n    def iterator1(self):\n        \"\"\"Create an iterator through one epoch in the pipeline.\"\"\"\n        source = self.invoke(self.pipeline[0])\n        for step in self.pipeline[1:]:\n            source = self.invoke(step, source)\n        return source\n\n    def iterator(self):\n        \"\"\"Create an iterator through the entire dataset, using the given number of repetitions.\"\"\"\n        for i in range(self.repetitions):\n            for sample in self.iterator1():\n                yield sample\n\n    def __iter__(self):\n        \"\"\"Create an iterator through the pipeline, repeating and slicing as requested.\"\"\"\n        if self.repetitions != 1:\n            if self.nsamples > 0:\n                return islice(self.iterator(), self.nsamples)\n            else:\n                return self.iterator()\n        else:\n            return self.iterator()\n\n    def stage(self, i):\n        \"\"\"Return pipeline stage i.\"\"\"\n        return self.pipeline[i]\n\n    def append(self, f):\n        \"\"\"Append a pipeline stage (modifies the object).\"\"\"\n        self.pipeline.append(f)\n        return self\n\n    def append_list(self, *args):\n        for arg in args:\n            self.pipeline.append(arg)\n        return self\n\n    def compose(self, *args):\n        \"\"\"Append a pipeline stage to a copy of the pipeline and returns the copy.\"\"\"\n        result = copy.copy(self)\n        for arg in args:\n            result.append(arg)\n        return result\n\n    def with_length(self, n):\n        \"\"\"Add a __len__ method returning the desired value.\n\n        This does not change the actual number of samples in an epoch.\n        PyTorch IterableDataset should not have a __len__ method.\n        This is provided only as a workaround for some broken training environments\n        that require a __len__ method.\n        \"\"\"\n        self.size = n\n        return add_length_method(self)\n\n    def with_epoch(self, nsamples=-1, nbatches=-1):\n        \"\"\"Change the epoch to return the given number of samples/batches.\n\n        The two arguments mean the same thing.\"\"\"\n        self.repetitions = sys.maxsize\n        self.nsamples = max(nsamples, nbatches)\n        return self\n\n    def repeat(self, nepochs=-1, nbatches=-1):\n        \"\"\"Repeat iterating through the dataset for the given #epochs up to the given #samples.\"\"\"\n        if nepochs > 0:\n            self.repetitions = nepochs\n            self.nsamples = nbatches\n        else:\n            self.repetitions = sys.maxsize\n            self.nsamples = nbatches\n        return self\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/shardlists.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n#\n# Modified from https://github.com/webdataset/webdataset\n\"\"\"Train PyTorch models directly from POSIX tar archive.\n\nCode works locally or over HTTP connections.\n\"\"\"\nimport os\nimport random\nimport sys\nimport time\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom itertools import islice\nfrom typing import List\n\nimport braceexpand\nimport yaml\n\nfrom . import utils\nfrom ..utils.log import Logger\nfrom .filters import pipelinefilter\nfrom .paddle_utils import IterableDataset\nlogger = Logger(__name__)\n\n\ndef expand_urls(urls):\n    if isinstance(urls, str):\n        urllist = urls.split(\"::\")\n        result = []\n        for url in urllist:\n            result.extend(braceexpand.braceexpand(url))\n        return result\n    else:\n        return list(urls)\n\n\nclass SimpleShardList(IterableDataset):\n    \"\"\"An iterable dataset yielding a list of urls.\"\"\"\n\n    def __init__(self, urls, seed=None):\n        \"\"\"Iterate through the list of shards.\n\n        :param urls: a list of URLs as a Python list or brace notation string\n        \"\"\"\n        super().__init__()\n        urls = expand_urls(urls)\n        self.urls = urls\n        assert isinstance(self.urls[0], str)\n        self.seed = seed\n\n    def __len__(self):\n        return len(self.urls)\n\n    def __iter__(self):\n        \"\"\"Return an iterator over the shards.\"\"\"\n        urls = self.urls.copy()\n        if self.seed is not None:\n            random.Random(self.seed).shuffle(urls)\n        for url in urls:\n            yield dict(url=url)\n\n\ndef split_by_node(src, group=None):\n    rank, world_size, worker, num_workers = utils.paddle_worker_info(\n        group=group)\n    logger.info(f\"world_size:{world_size}, rank:{rank}\")\n    if world_size > 1:\n        for s in islice(src, rank, None, world_size):\n            yield s\n    else:\n        for s in src:\n            yield s\n\n\ndef single_node_only(src, group=None):\n    rank, world_size, worker, num_workers = utils.paddle_worker_info(\n        group=group)\n    if world_size > 1:\n        raise ValueError(\n            \"input pipeline needs to be reconfigured for multinode training\")\n    for s in src:\n        yield s\n\n\ndef split_by_worker(src):\n    rank, world_size, worker, num_workers = utils.paddle_worker_info()\n    logger.info(f\"num_workers:{num_workers}, worker:{worker}\")\n    if num_workers > 1:\n        for s in islice(src, worker, None, num_workers):\n            yield s\n    else:\n        for s in src:\n            yield s\n\n\ndef resampled_(src, n=sys.maxsize):\n    import random\n\n    seed = time.time()\n    try:\n        seed = open(\"/dev/random\", \"rb\").read(20)\n    except Exception as exn:\n        print(repr(exn)[:50], file=sys.stderr)\n    rng = random.Random(seed)\n    print(\"# resampled loading\", file=sys.stderr)\n    items = list(src)\n    print(\n        f\"# resampled got {len(items)} samples, yielding {n}\", file=sys.stderr)\n    for i in range(n):\n        yield rng.choice(items)\n\n\nresampled = pipelinefilter(resampled_)\n\n\ndef non_empty(src):\n    count = 0\n    for s in src:\n        yield s\n        count += 1\n    if count == 0:\n        raise ValueError(\n            \"pipeline stage received no data at all and this was declared as an error\"\n        )\n\n\n@dataclass\nclass MSSource:\n    \"\"\"Class representing a data source.\"\"\"\n\n    name: str = \"\"\n    perepoch: int = -1\n    resample: bool = False\n    urls: List[str] = field(default_factory=list)\n\n\ndefault_rng = random.Random()\n\n\ndef expand(s):\n    return os.path.expanduser(os.path.expandvars(s))\n\n\nclass MultiShardSample(IterableDataset):\n    def __init__(self, fname):\n        \"\"\"Construct a shardlist from multiple sources using a YAML spec.\"\"\"\n        self.epoch = -1\n        self.parse_spec(fname)\n\n    def parse_spec(self, fname):\n        self.rng = default_rng  # capture default_rng if we fork\n        if isinstance(fname, dict):\n            spec = fname\n            fname = \"{dict}\"\n        else:\n            with open(fname) as stream:\n                spec = yaml.safe_load(stream)\n        assert set(spec.keys()).issubset(\n            set(\"prefix datasets buckets\".split())), list(spec.keys())\n        prefix = expand(spec.get(\"prefix\", \"\"))\n        self.sources = []\n        for ds in spec[\"datasets\"]:\n            assert set(ds.keys()).issubset(\n                set(\"buckets name shards resample choose\".split())), list(\n                    ds.keys())\n            buckets = ds.get(\"buckets\", spec.get(\"buckets\", []))\n            if isinstance(buckets, str):\n                buckets = [buckets]\n            buckets = [expand(s) for s in buckets]\n            if buckets == []:\n                buckets = [\"\"]\n            assert len(\n                buckets\n            ) == 1, f\"{buckets}: FIXME support for multiple buckets unimplemented\"\n            bucket = buckets[0]\n            name = ds.get(\"name\", \"@\" + bucket)\n            urls = ds[\"shards\"]\n            if isinstance(urls, str):\n                urls = [urls]\n            # urls = [u for url in urls for u in braceexpand.braceexpand(url)]\n            urls = [\n                prefix + os.path.join(bucket, u)\n                for url in urls for u in braceexpand.braceexpand(expand(url))\n            ]\n            resample = ds.get(\"resample\", -1)\n            nsample = ds.get(\"choose\", -1)\n            if nsample > len(urls):\n                raise ValueError(\n                    f\"perepoch {nsample} must be no greater than the number of shards\"\n                )\n            if (nsample > 0) and (resample > 0):\n                raise ValueError(\"specify only one of perepoch or choose\")\n            entry = MSSource(\n                name=name, urls=urls, perepoch=nsample, resample=resample)\n            self.sources.append(entry)\n            print(f\"# {name} {len(urls)} {nsample}\", file=sys.stderr)\n\n    def set_epoch(self, seed):\n        \"\"\"Set the current epoch (for consistent shard selection among nodes).\"\"\"\n        self.rng = random.Random(seed)\n\n    def get_shards_for_epoch(self):\n        result = []\n        for source in self.sources:\n            if source.resample > 0:\n                # sample with replacement\n                l = self.rng.choices(source.urls, k=source.resample)\n            elif source.perepoch > 0:\n                # sample without replacement\n                l = list(source.urls)\n                self.rng.shuffle(l)\n                l = l[:source.perepoch]\n            else:\n                l = list(source.urls)\n            result += l\n        self.rng.shuffle(result)\n        return result\n\n    def __iter__(self):\n        shards = self.get_shards_for_epoch()\n        for shard in shards:\n            yield dict(url=shard)\n\n\ndef shardspec(spec):\n    if spec.endswith(\".yaml\"):\n        return MultiShardSample(spec)\n    else:\n        return SimpleShardList(spec)\n\n\nclass ResampledShards(IterableDataset):\n    \"\"\"An iterable dataset yielding a list of urls.\"\"\"\n\n    def __init__(\n            self,\n            urls,\n            nshards=sys.maxsize,\n            worker_seed=None,\n            deterministic=False, ):\n        \"\"\"Sample shards from the shard list with replacement.\n\n        :param urls: a list of URLs as a Python list or brace notation string\n        \"\"\"\n        super().__init__()\n        urls = expand_urls(urls)\n        self.urls = urls\n        assert isinstance(self.urls[0], str)\n        self.nshards = nshards\n        self.worker_seed = utils.paddle_worker_seed if worker_seed is None else worker_seed\n        self.deterministic = deterministic\n        self.epoch = -1\n\n    def __iter__(self):\n        \"\"\"Return an iterator over the shards.\"\"\"\n        self.epoch += 1\n        if self.deterministic:\n            seed = utils.make_seed(self.worker_seed(), self.epoch)\n        else:\n            seed = utils.make_seed(self.worker_seed(), self.epoch,\n                                   os.getpid(), time.time_ns(), os.urandom(4))\n        if os.environ.get(\"WDS_SHOW_SEED\", \"0\") == \"1\":\n            print(f\"# ResampledShards seed {seed}\")\n        self.rng = random.Random(seed)\n        for _ in range(self.nshards):\n            index = self.rng.randint(0, len(self.urls) - 1)\n            yield dict(url=self.urls[index])\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/soundfile.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport warnings\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport resampy\nimport soundfile\nfrom scipy.io import wavfile\n\nfrom ..utils import depth_convert\nfrom ..utils import ParameterError\nfrom .common import AudioInfo\n\n__all__ = [\n    'resample',\n    'to_mono',\n    'normalize',\n    'save',\n    'soundfile_save',\n    'load',\n    'soundfile_load',\n    'info',\n]\nNORMALMIZE_TYPES = ['linear', 'gaussian']\nMERGE_TYPES = ['ch0', 'ch1', 'random', 'average']\nRESAMPLE_MODES = ['kaiser_best', 'kaiser_fast']\nEPS = 1e-8\n\n\ndef resample(y: np.ndarray,\n             src_sr: int,\n             target_sr: int,\n             mode: str='kaiser_fast') -> np.ndarray:\n    \"\"\"Audio resampling.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        src_sr (int): Source sample rate.\n        target_sr (int): Target sample rate.\n        mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        np.ndarray: `y` resampled to `target_sr`\n    \"\"\"\n\n    if mode == 'kaiser_best':\n        warnings.warn(\n            f'Using resampy in kaiser_best to {src_sr}=>{target_sr}. This function is pretty slow, \\\n        we recommend the mode kaiser_fast in large scale audio training')\n\n    if not isinstance(y, np.ndarray):\n        raise ParameterError(\n            'Only support numpy np.ndarray, but received y in {type(y)}')\n\n    if mode not in RESAMPLE_MODES:\n        raise ParameterError(f'resample mode must in {RESAMPLE_MODES}')\n\n    return resampy.resample(y, src_sr, target_sr, filter=mode)\n\n\ndef to_mono(y: np.ndarray, merge_type: str='average') -> np.ndarray:\n    \"\"\"Convert sterior audio to mono.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        merge_type (str, optional): Merge type to generate mono waveform. Defaults to 'average'.\n\n    Returns:\n        np.ndarray: `y` with mono channel.\n    \"\"\"\n\n    if merge_type not in MERGE_TYPES:\n        raise ParameterError(\n            f'Unsupported merge type {merge_type}, available types are {MERGE_TYPES}'\n        )\n    if y.ndim > 2:\n        raise ParameterError(\n            f'Unsupported audio array,  y.ndim > 2, the shape is {y.shape}')\n    if y.ndim == 1:  # nothing to merge\n        return y\n\n    if merge_type == 'ch0':\n        return y[0]\n    if merge_type == 'ch1':\n        return y[1]\n    if merge_type == 'random':\n        return y[np.random.randint(0, 2)]\n\n    # need to do averaging according to dtype\n\n    if y.dtype == 'float32':\n        y_out = (y[0] + y[1]) * 0.5\n    elif y.dtype == 'int16':\n        y_out = y.astype('int32')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n\n    elif y.dtype == 'int8':\n        y_out = y.astype('int16')\n        y_out = (y_out[0] + y_out[1]) // 2\n        y_out = np.clip(y_out, np.iinfo(y.dtype).min,\n                        np.iinfo(y.dtype).max).astype(y.dtype)\n    else:\n        raise ParameterError(f'Unsupported dtype: {y.dtype}')\n    return y_out\n\n\ndef soundfile_load_(file: os.PathLike,\n                    offset: Optional[float]=None,\n                    dtype: str='int16',\n                    duration: Optional[int]=None) -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio using soundfile library. This function load audio file using libsndfile.\n\n    Args:\n        file (os.PathLike): File of waveform.\n        offset (Optional[float], optional): Offset to the start of waveform. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'int16'.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n    with soundfile.SoundFile(file) as sf_desc:\n        sr_native = sf_desc.samplerate\n        if offset:\n            sf_desc.seek(int(offset * sr_native))\n        if duration is not None:\n            frame_duration = int(duration * sr_native)\n        else:\n            frame_duration = -1\n        y = sf_desc.read(frames=frame_duration, dtype=dtype, always_2d=False).T\n\n    return y, sf_desc.samplerate\n\n\ndef normalize(y: np.ndarray, norm_type: str='linear',\n              mul_factor: float=1.0) -> np.ndarray:\n    \"\"\"Normalize an input audio with additional multiplier.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n\n    Returns:\n        np.ndarray: `y` after normalization.\n    \"\"\"\n\n    if norm_type == 'linear':\n        amax = np.max(np.abs(y))\n        factor = 1.0 / (amax + EPS)\n        y = y * factor * mul_factor\n    elif norm_type == 'gaussian':\n        amean = np.mean(y)\n        astd = np.std(y)\n        astd = max(astd, EPS)\n        y = mul_factor * (y - amean) / astd\n    else:\n        raise NotImplementedError(f'norm_type should be in {NORMALMIZE_TYPES}')\n\n    return y\n\n\ndef soundfile_save(y: np.ndarray, sr: int, file: os.PathLike) -> None:\n    \"\"\"Save audio file to disk. This function saves audio to disk using scipy.io.wavfile, with additional step to convert input waveform to int16.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        sr (int): Sample rate.\n        file (os.PathLike): Path of audio file to save.\n    \"\"\"\n    if not file.endswith('.wav'):\n        raise ParameterError(\n            f'only .wav file supported, but dst file name is: {file}')\n\n    if sr <= 0:\n        raise ParameterError(\n            f'Sample rate should be larger than 0, received sr = {sr}')\n\n    if y.dtype not in ['int16', 'int8']:\n        warnings.warn(\n            f'input data type is {y.dtype}, will convert data to int16 format before saving'\n        )\n        y_out = depth_convert(y, 'int16')\n    else:\n        y_out = y\n\n    wavfile.write(file, sr, y_out)\n\n\ndef soundfile_load(\n        file: os.PathLike,\n        sr: Optional[int]=None,\n        mono: bool=True,\n        merge_type: str='average',  # ch0,ch1,random,average\n        normal: bool=True,\n        norm_type: str='linear',\n        norm_mul_factor: float=1.0,\n        offset: float=0.0,\n        duration: Optional[int]=None,\n        dtype: str='float32',\n        resample_mode: str='kaiser_fast') -> Tuple[np.ndarray, int]:\n    \"\"\"Load audio file from disk. This function loads audio from disk using using audio backend.\n\n    Args:\n        file (os.PathLike): Path of audio file to load.\n        sr (Optional[int], optional): Sample rate of loaded waveform. Defaults to None.\n        mono (bool, optional): Return waveform with mono channel. Defaults to True.\n        merge_type (str, optional): Merge type of multi-channels waveform. Defaults to 'average'.\n        normal (bool, optional): Waveform normalization. Defaults to True.\n        norm_type (str, optional): Type of normalization. Defaults to 'linear'.\n        norm_mul_factor (float, optional): Scaling factor. Defaults to 1.0.\n        offset (float, optional): Offset to the start of waveform. Defaults to 0.0.\n        duration (Optional[int], optional): Duration of waveform to read. Defaults to None.\n        dtype (str, optional): Data type of waveform. Defaults to 'float32'.\n        resample_mode (str, optional): The resampling filter to use. Defaults to 'kaiser_fast'.\n\n    Returns:\n        Tuple[np.ndarray, int]: Waveform in ndarray and its samplerate.\n    \"\"\"\n\n    y, r = soundfile_load_(file, offset=offset, dtype=dtype, duration=duration)\n\n    if not ((y.ndim == 1 and len(y) > 0) or (y.ndim == 2 and len(y[0]) > 0)):\n        raise ParameterError(f'audio file {file} looks empty')\n\n    if mono:\n        y = to_mono(y, merge_type)\n\n    if sr is not None and sr != r:\n        y = resample(y, r, sr, mode=resample_mode)\n        r = sr\n\n    if normal:\n        y = normalize(y, norm_type, norm_mul_factor)\n    elif dtype in ['int8', 'int16']:\n        # still need to do normalization, before depth conversion\n        y = normalize(y, 'linear', 1.0)\n\n    y = depth_convert(y, dtype)\n    return y, r\n\n\n#The code below is taken from: https://github.com/pytorch/audio/blob/main/torchaudio/backend/soundfile_backend.py, with some modifications.\n\n\ndef _get_subtype_for_wav(dtype: paddle.dtype,\n                         encoding: str,\n                         bits_per_sample: int):\n    if not encoding:\n        if not bits_per_sample:\n            subtype = {\n                paddle.uint8: \"PCM_U8\",\n                paddle.int16: \"PCM_16\",\n                paddle.int32: \"PCM_32\",\n                paddle.float32: \"FLOAT\",\n                paddle.float64: \"DOUBLE\",\n            }.get(dtype)\n            if not subtype:\n                raise ValueError(f\"Unsupported dtype for wav: {dtype}\")\n            return subtype\n        if bits_per_sample == 8:\n            return \"PCM_U8\"\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_S\":\n        if not bits_per_sample:\n            return \"PCM_32\"\n        if bits_per_sample == 8:\n            raise ValueError(\"wav does not support 8-bit signed PCM encoding.\")\n        return f\"PCM_{bits_per_sample}\"\n    if encoding == \"PCM_U\":\n        if bits_per_sample in (None, 8):\n            return \"PCM_U8\"\n        raise ValueError(\"wav only supports 8-bit unsigned PCM encoding.\")\n    if encoding == \"PCM_F\":\n        if bits_per_sample in (None, 32):\n            return \"FLOAT\"\n        if bits_per_sample == 64:\n            return \"DOUBLE\"\n        raise ValueError(\"wav only supports 32/64-bit float PCM encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"wav only supports 8-bit mu-law encoding.\")\n    if encoding == \"ALAW\":\n        if bits_per_sample in (None, 8):\n            return \"ALAW\"\n        raise ValueError(\"wav only supports 8-bit a-law encoding.\")\n    raise ValueError(f\"wav does not support {encoding}.\")\n\n\ndef _get_subtype_for_sphere(encoding: str, bits_per_sample: int):\n    if encoding in (None, \"PCM_S\"):\n        return f\"PCM_{bits_per_sample}\" if bits_per_sample else \"PCM_32\"\n    if encoding in (\"PCM_U\", \"PCM_F\"):\n        raise ValueError(f\"sph does not support {encoding} encoding.\")\n    if encoding == \"ULAW\":\n        if bits_per_sample in (None, 8):\n            return \"ULAW\"\n        raise ValueError(\"sph only supports 8-bit for mu-law encoding.\")\n    if encoding == \"ALAW\":\n        return \"ALAW\"\n    raise ValueError(f\"sph does not support {encoding}.\")\n\n\ndef _get_subtype(dtype: paddle.dtype,\n                 format: str,\n                 encoding: str,\n                 bits_per_sample: int):\n    if format == \"wav\":\n        return _get_subtype_for_wav(dtype, encoding, bits_per_sample)\n    if format == \"flac\":\n        if encoding:\n            raise ValueError(\"flac does not support encoding.\")\n        if not bits_per_sample:\n            return \"PCM_16\"\n        if bits_per_sample > 24:\n            raise ValueError(\"flac does not support bits_per_sample > 24.\")\n        return \"PCM_S8\" if bits_per_sample == 8 else f\"PCM_{bits_per_sample}\"\n    if format in (\"ogg\", \"vorbis\"):\n        if encoding or bits_per_sample:\n            raise ValueError(\n                \"ogg/vorbis does not support encoding/bits_per_sample.\")\n        return \"VORBIS\"\n    if format == \"sph\":\n        return _get_subtype_for_sphere(encoding, bits_per_sample)\n    if format in (\"nis\", \"nist\"):\n        return \"PCM_16\"\n    raise ValueError(f\"Unsupported format: {format}\")\n\n\ndef save(\n        filepath: str,\n        src: paddle.Tensor,\n        sample_rate: int,\n        channels_first: bool=True,\n        compression: Optional[float]=None,\n        format: Optional[str]=None,\n        encoding: Optional[str]=None,\n        bits_per_sample: Optional[int]=None, ):\n    \"\"\"Save audio data to file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (str or pathlib.Path): Path to audio file.\n        src (paddle.Tensor): Audio data to save. must be 2D tensor.\n        sample_rate (int): sampling rate\n        channels_first (bool, optional): If ``True``, the given tensor is interpreted as `[channel, time]`,\n            otherwise `[time, channel]`.\n        compression (float of None, optional): Not used.\n            It is here only for interface compatibility reason with \"sox_io\" backend.\n        format (str or None, optional): Override the audio format.\n            When ``filepath`` argument is path-like object, audio format is\n            inferred from file extension. If the file extension is missing or\n            different, you can specify the correct format with this argument.\n\n            When ``filepath`` argument is file-like object,\n            this argument is required.\n\n            Valid values are ``\"wav\"``, ``\"ogg\"``, ``\"vorbis\"``,\n            ``\"flac\"`` and ``\"sph\"``.\n        encoding (str or None, optional): Changes the encoding for supported formats.\n            This argument is effective only for supported formats, such as\n            ``\"wav\"``, ``\"\"flac\"`` and ``\"sph\"``. Valid values are:\n\n                - ``\"PCM_S\"`` (signed integer Linear PCM)\n                - ``\"PCM_U\"`` (unsigned integer Linear PCM)\n                - ``\"PCM_F\"`` (floating point PCM)\n                - ``\"ULAW\"`` (mu-law)\n                - ``\"ALAW\"`` (a-law)\n\n        bits_per_sample (int or None, optional): Changes the bit depth for the\n            supported formats.\n            When ``format`` is one of ``\"wav\"``, ``\"flac\"`` or ``\"sph\"``,\n            you can change the bit depth.\n            Valid values are ``8``, ``16``, ``24``, ``32`` and ``64``.\n\n    Supported formats/encodings/bit depth/compression are:\n\n    ``\"wav\"``\n        - 32-bit floating-point PCM\n        - 32-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 8-bit unsigned integer PCM\n        - 8-bit mu-law\n        - 8-bit a-law\n\n        Note:\n            Default encoding/bit depth is determined by the dtype of\n            the input Tensor.\n\n    ``\"flac\"``\n        - 8-bit\n        - 16-bit (default)\n        - 24-bit\n\n    ``\"ogg\"``, ``\"vorbis\"``\n        - Doesn't accept changing configuration.\n\n    ``\"sph\"``\n        - 8-bit signed integer PCM\n        - 16-bit signed integer PCM\n        - 24-bit signed integer PCM\n        - 32-bit signed integer PCM (default)\n        - 8-bit mu-law\n        - 8-bit a-law\n        - 16-bit a-law\n        - 24-bit a-law\n        - 32-bit a-law\n\n    \"\"\"\n    if src.ndim != 2:\n        raise ValueError(f\"Expected 2D Tensor, got {src.ndim}D.\")\n    if compression is not None:\n        warnings.warn(\n            '`save` function of \"soundfile\" backend does not support \"compression\" parameter. '\n            \"The argument is silently ignored.\")\n    if hasattr(filepath, \"write\"):\n        if format is None:\n            raise RuntimeError(\n                \"`format` is required when saving to file object.\")\n        ext = format.lower()\n    else:\n        ext = str(filepath).split(\".\")[-1].lower()\n\n    if bits_per_sample not in (None, 8, 16, 24, 32, 64):\n        raise ValueError(\"Invalid bits_per_sample.\")\n    if bits_per_sample == 24:\n        warnings.warn(\n            \"Saving audio with 24 bits per sample might warp samples near -1. \"\n            \"Using 16 bits per sample might be able to avoid this.\")\n    subtype = _get_subtype(src.dtype, ext, encoding, bits_per_sample)\n\n    # sph is a extension used in TED-LIUM but soundfile does not recognize it as NIST format,\n    # so we extend the extensions manually here\n    if ext in [\"nis\", \"nist\", \"sph\"] and format is None:\n        format = \"NIST\"\n\n    if channels_first:\n        src = src.t()\n\n    soundfile.write(\n        file=filepath,\n        data=src,\n        samplerate=sample_rate,\n        subtype=subtype,\n        format=format)\n\n\n_SUBTYPE2DTYPE = {\n    \"PCM_S8\": \"int8\",\n    \"PCM_U8\": \"uint8\",\n    \"PCM_16\": \"int16\",\n    \"PCM_32\": \"int32\",\n    \"FLOAT\": \"float32\",\n    \"DOUBLE\": \"float64\",\n}\n\n\ndef load(\n        filepath: str,\n        frame_offset: int=0,\n        num_frames: int=-1,\n        normalize: bool=True,\n        channels_first: bool=True,\n        format: Optional[str]=None, ) -> Tuple[paddle.Tensor, int]:\n    \"\"\"Load audio data from file.\n\n    Note:\n        The formats this function can handle depend on the soundfile installation.\n        This function is tested on the following formats;\n\n        * WAV\n\n            * 32-bit floating-point\n            * 32-bit signed integer\n            * 16-bit signed integer\n            * 8-bit unsigned integer\n\n        * FLAC\n        * OGG/VORBIS\n        * SPHERE\n\n    By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with\n    ``float32`` dtype and the shape of `[channel, time]`.\n    The samples are normalized to fit in the range of ``[-1.0, 1.0]``.\n\n    When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit\n    signed integer and 8-bit unsigned integer (24-bit signed integer is not supported),\n    by providing ``normalize=False``, this function can return integer Tensor, where the samples\n    are expressed within the whole range of the corresponding dtype, that is, ``int32`` tensor\n    for 32-bit signed PCM, ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM.\n\n    ``normalize`` parameter has no effect on 32-bit floating-point WAV and other formats, such as\n    ``flac`` and ``mp3``.\n    For these formats, this function always returns ``float32`` Tensor with values normalized to\n    ``[-1.0, 1.0]``.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend.\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        frame_offset (int, optional):\n            Number of frames to skip before start reading data.\n        num_frames (int, optional):\n            Maximum number of frames to read. ``-1`` reads all the remaining samples,\n            starting from ``frame_offset``.\n            This function may return the less number of frames if there is not enough\n            frames in the given file.\n        normalize (bool, optional):\n            When ``True``, this function always return ``float32``, and sample values are\n            normalized to ``[-1.0, 1.0]``.\n            If input file is integer WAV, giving ``False`` will change the resulting Tensor type to\n            integer type.\n            This argument has no effect for formats other than integer WAV type.\n        channels_first (bool, optional):\n            When True, the returned Tensor has dimension `[channel, time]`.\n            Otherwise, the returned Tensor's dimension is `[time, channel]`.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        (paddle.Tensor, int): Resulting Tensor and sample rate.\n            If the input file has integer wav format and normalization is off, then it has\n            integer type, else ``float32`` type. If ``channels_first=True``, it has\n            `[channel, time]` else `[time, channel]`.\n    \"\"\"\n    with soundfile.SoundFile(filepath, \"r\") as file_:\n        if file_.format != \"WAV\" or normalize:\n            dtype = \"float32\"\n        elif file_.subtype not in _SUBTYPE2DTYPE:\n            raise ValueError(f\"Unsupported subtype: {file_.subtype}\")\n        else:\n            dtype = _SUBTYPE2DTYPE[file_.subtype]\n\n        frames = file_._prepare_read(frame_offset, None, num_frames)\n        waveform = file_.read(frames, dtype, always_2d=True)\n        sample_rate = file_.samplerate\n\n    waveform = paddle.to_tensor(waveform)\n    if channels_first:\n        waveform = paddle.transpose(waveform, perm=[1, 0])\n    return waveform, sample_rate\n\n\n# Mapping from soundfile subtype to number of bits per sample.\n# This is mostly heuristical and the value is set to 0 when it is irrelevant\n# (lossy formats) or when it can't be inferred.\n# For ADPCM (and G72X) subtypes, it's hard to infer the bit depth because it's not part of the standard:\n# According to https://en.wikipedia.org/wiki/Adaptive_differential_pulse-code_modulation#In_telephony,\n# the default seems to be 8 bits but it can be compressed further to 4 bits.\n# The dict is inspired from\n# https://github.com/bastibe/python-soundfile/blob/744efb4b01abc72498a96b09115b42a4cabd85e4/soundfile.py#L66-L94\n_SUBTYPE_TO_BITS_PER_SAMPLE = {\n    \"PCM_S8\": 8,  # Signed 8 bit data\n    \"PCM_16\": 16,  # Signed 16 bit data\n    \"PCM_24\": 24,  # Signed 24 bit data\n    \"PCM_32\": 32,  # Signed 32 bit data\n    \"PCM_U8\": 8,  # Unsigned 8 bit data (WAV and RAW only)\n    \"FLOAT\": 32,  # 32 bit float data\n    \"DOUBLE\": 64,  # 64 bit float data\n    \"ULAW\": 8,  # U-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"ALAW\": 8,  # A-Law encoded. See https://en.wikipedia.org/wiki/G.711#Types\n    \"IMA_ADPCM\": 0,  # IMA ADPCM.\n    \"MS_ADPCM\": 0,  # Microsoft ADPCM.\n    \"GSM610\":\n    0,  # GSM 6.10 encoding. (Wikipedia says 1.625 bit depth?? https://en.wikipedia.org/wiki/Full_Rate)\n    \"VOX_ADPCM\": 0,  # OKI / Dialogix ADPCM\n    \"G721_32\": 0,  # 32kbs G721 ADPCM encoding.\n    \"G723_24\": 0,  # 24kbs G723 ADPCM encoding.\n    \"G723_40\": 0,  # 40kbs G723 ADPCM encoding.\n    \"DWVW_12\": 12,  # 12 bit Delta Width Variable Word encoding.\n    \"DWVW_16\": 16,  # 16 bit Delta Width Variable Word encoding.\n    \"DWVW_24\": 24,  # 24 bit Delta Width Variable Word encoding.\n    \"DWVW_N\": 0,  # N bit Delta Width Variable Word encoding.\n    \"DPCM_8\": 8,  # 8 bit differential PCM (XI only)\n    \"DPCM_16\": 16,  # 16 bit differential PCM (XI only)\n    \"VORBIS\": 0,  # Xiph Vorbis encoding. (lossy)\n    \"ALAC_16\": 16,  # Apple Lossless Audio Codec (16 bit).\n    \"ALAC_20\": 20,  # Apple Lossless Audio Codec (20 bit).\n    \"ALAC_24\": 24,  # Apple Lossless Audio Codec (24 bit).\n    \"ALAC_32\": 32,  # Apple Lossless Audio Codec (32 bit).\n}\n\n\ndef _get_bit_depth(subtype):\n    if subtype not in _SUBTYPE_TO_BITS_PER_SAMPLE:\n        warnings.warn(\n            f\"The {subtype} subtype is unknown to PaddleAudio. As a result, the bits_per_sample \"\n            \"attribute will be set to 0. If you are seeing this warning, please \"\n            \"report by opening an issue on github (after checking for existing/closed ones). \"\n            \"You may otherwise ignore this warning.\")\n    return _SUBTYPE_TO_BITS_PER_SAMPLE.get(subtype, 0)\n\n\n_SUBTYPE_TO_ENCODING = {\n    \"PCM_S8\": \"PCM_S\",\n    \"PCM_16\": \"PCM_S\",\n    \"PCM_24\": \"PCM_S\",\n    \"PCM_32\": \"PCM_S\",\n    \"PCM_U8\": \"PCM_U\",\n    \"FLOAT\": \"PCM_F\",\n    \"DOUBLE\": \"PCM_F\",\n    \"ULAW\": \"ULAW\",\n    \"ALAW\": \"ALAW\",\n    \"VORBIS\": \"VORBIS\",\n}\n\n\ndef _get_encoding(format: str, subtype: str):\n    if format == \"FLAC\":\n        return \"FLAC\"\n    return _SUBTYPE_TO_ENCODING.get(subtype, \"UNKNOWN\")\n\n\ndef info(filepath: str, format: Optional[str]=None) -> AudioInfo:\n    \"\"\"Get signal information of an audio file.\n\n    Note:\n        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts\n        ``pathlib.Path`` object as well. This is for the consistency with ``\"sox_io\"`` backend,\n\n    Args:\n        filepath (path-like object or file-like object):\n            Source of audio data.\n        format (str or None, optional):\n            Not used. PySoundFile does not accept format hint.\n\n    Returns:\n        AudioInfo: meta data of the given audio.\n\n    \"\"\"\n    sinfo = soundfile.info(filepath)\n    return AudioInfo(\n        sinfo.samplerate,\n        sinfo.frames,\n        sinfo.channels,\n        bits_per_sample=_get_bit_depth(sinfo.subtype),\n        encoding=_get_encoding(sinfo.format, sinfo.subtype), )\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/tariterators.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Low level iteration functions for tar archives.\"\"\"\nimport random\nimport re\nimport tarfile\n\nimport braceexpand\n\nfrom . import filters\nfrom . import gopen\nfrom .handlers import reraise_exception\n\ntrace = False\nmeta_prefix = \"__\"\nmeta_suffix = \"__\"\n\nimport paddle\nimport numpy as np\nfrom paddlespeech.audio.backends import soundfile_load\n\nAUDIO_FORMAT_SETS = set(['flac', 'mp3', 'm4a', 'ogg', 'opus', 'wav', 'wma'])\n\n\ndef base_plus_ext(path):\n    \"\"\"Split off all file extensions.\n\n    Returns base, allext.\n\n    :param path: path with extensions\n    :param returns: path with all extensions removed\n\n    \"\"\"\n    match = re.match(r\"^((?:.*/|)[^.]+)[.]([^/]*)$\", path)\n    if not match:\n        return None, None\n    return match.group(1), match.group(2)\n\n\ndef valid_sample(sample):\n    \"\"\"Check whether a sample is valid.\n\n    :param sample: sample to be checked\n    \"\"\"\n    return (sample is not None and isinstance(sample, dict) and\n            len(list(sample.keys())) > 0 and not sample.get(\"__bad__\", False))\n\n\n# FIXME: UNUSED\ndef shardlist(urls, *, shuffle=False):\n    \"\"\"Given a list of URLs, yields that list, possibly shuffled.\"\"\"\n    if isinstance(urls, str):\n        urls = braceexpand.braceexpand(urls)\n    else:\n        urls = list(urls)\n    if shuffle:\n        random.shuffle(urls)\n    for url in urls:\n        yield dict(url=url)\n\n\ndef url_opener(data, handler=reraise_exception, **kw):\n    \"\"\"Given a stream of url names (packaged in `dict(url=url)`), yield opened streams.\"\"\"\n    for sample in data:\n        assert isinstance(sample, dict), sample\n        assert \"url\" in sample\n        url = sample[\"url\"]\n        try:\n            stream = gopen.gopen(url, **kw)\n            sample.update(stream=stream)\n            yield sample\n        except Exception as exn:\n            exn.args = exn.args + (url, )\n            if handler(exn):\n                continue\n            else:\n                break\n\n\ndef tar_file_iterator(fileobj,\n                      skip_meta=r\"__[^/]*__($|/)\",\n                      handler=reraise_exception):\n    \"\"\"Iterate over tar file, yielding filename, content pairs for the given tar stream.\n\n    :param fileobj: byte stream suitable for tarfile\n    :param skip_meta: regexp for keys that are skipped entirely (Default value = r\"__[^/]*__($|/)\")\n\n    \"\"\"\n    stream = tarfile.open(fileobj=fileobj, mode=\"r:*\")\n    for tarinfo in stream:\n        fname = tarinfo.name\n        try:\n            if not tarinfo.isreg():\n                continue\n            if fname is None:\n                continue\n            if (\"/\" not in fname and fname.startswith(meta_prefix) and\n                    fname.endswith(meta_suffix)):\n                # skipping metadata for now\n                continue\n            if skip_meta is not None and re.match(skip_meta, fname):\n                continue\n\n            name = tarinfo.name\n            pos = name.rfind('.')\n            assert pos > 0\n            prefix, postfix = name[:pos], name[pos + 1:]\n            if postfix == 'wav':\n                waveform, sample_rate = soundfile_load(\n                    stream.extractfile(tarinfo), normal=False)\n                result = dict(\n                    fname=prefix, wav=waveform, sample_rate=sample_rate)\n            else:\n                txt = stream.extractfile(tarinfo).read().decode('utf8').strip()\n                result = dict(fname=prefix, txt=txt)\n            #result = dict(fname=fname, data=data)\n            yield result\n            stream.members = []\n        except Exception as exn:\n            if hasattr(exn, \"args\") and len(exn.args) > 0:\n                exn.args = (exn.args[0] + \" @ \" + str(fileobj), ) + exn.args[1:]\n            if handler(exn):\n                continue\n            else:\n                break\n    del stream\n\n\ndef tar_file_and_group_iterator(fileobj,\n                                skip_meta=r\"__[^/]*__($|/)\",\n                                handler=reraise_exception):\n    \"\"\" Expand a stream of open tar files into a stream of tar file contents.\n        And groups the file with same prefix\n\n        Args:\n            data: Iterable[{src, stream}]\n\n        Returns:\n            Iterable[{key, wav, txt, sample_rate}]\n    \"\"\"\n    stream = tarfile.open(fileobj=fileobj, mode=\"r:*\")\n    prev_prefix = None\n    example = {}\n    valid = True\n    for tarinfo in stream:\n        name = tarinfo.name\n        pos = name.rfind('.')\n        assert pos > 0\n        prefix, postfix = name[:pos], name[pos + 1:]\n        if prev_prefix is not None and prefix != prev_prefix:\n            example['fname'] = prev_prefix\n            if valid:\n                yield example\n            example = {}\n            valid = True\n        with stream.extractfile(tarinfo) as file_obj:\n            try:\n                if postfix == 'txt':\n                    example['txt'] = file_obj.read().decode('utf8').strip()\n                elif postfix in AUDIO_FORMAT_SETS:\n                    waveform, sample_rate = soundfile_load(\n                        file_obj, normal=False)\n                    waveform = paddle.to_tensor(\n                        np.expand_dims(np.array(waveform), 0),\n                        dtype=paddle.float32)\n\n                    example['wav'] = waveform\n                    example['sample_rate'] = sample_rate\n                else:\n                    example[postfix] = file_obj.read()\n            except Exception as exn:\n                if hasattr(exn, \"args\") and len(exn.args) > 0:\n                    exn.args = (exn.args[0] + \" @ \" + str(fileobj),\n                                ) + exn.args[1:]\n                if handler(exn):\n                    continue\n                else:\n                    break\n                valid = False\n            #  logging.warning('error to parse {}'.format(name))\n        prev_prefix = prefix\n    if prev_prefix is not None:\n        example['fname'] = prev_prefix\n        yield example\n    stream.close()\n\n\ndef tar_file_expander(data, handler=reraise_exception):\n    \"\"\"Expand a stream of open tar files into a stream of tar file contents.\n\n    This returns an iterator over (filename, file_contents).\n    \"\"\"\n    for source in data:\n        url = source[\"url\"]\n        try:\n            assert isinstance(source, dict)\n            assert \"stream\" in source\n            for sample in tar_file_iterator(source[\"stream\"]):\n                assert (isinstance(sample, dict) and \"data\" in sample and\n                        \"fname\" in sample)\n                sample[\"__url__\"] = url\n                yield sample\n        except Exception as exn:\n            exn.args = exn.args + (source.get(\"stream\"), source.get(\"url\"))\n            if handler(exn):\n                continue\n            else:\n                break\n\n\ndef tar_file_and_group_expander(data, handler=reraise_exception):\n    \"\"\"Expand a stream of open tar files into a stream of tar file contents.\n\n    This returns an iterator over (filename, file_contents).\n    \"\"\"\n    for source in data:\n        url = source[\"url\"]\n        try:\n            assert isinstance(source, dict)\n            assert \"stream\" in source\n            for sample in tar_file_and_group_iterator(source[\"stream\"]):\n                assert (isinstance(sample, dict) and \"wav\" in sample and\n                        \"txt\" in sample and \"fname\" in sample)\n                sample[\"__url__\"] = url\n                yield sample\n        except Exception as exn:\n            exn.args = exn.args + (source.get(\"stream\"), source.get(\"url\"))\n            if handler(exn):\n                continue\n            else:\n                break\n\n\ndef group_by_keys(data,\n                  keys=base_plus_ext,\n                  lcase=True,\n                  suffixes=None,\n                  handler=None):\n    \"\"\"Return function over iterator that groups key, value pairs into samples.\n\n    :param keys: function that splits the key into key and extension (base_plus_ext)\n    :param lcase: convert suffixes to lower case (Default value = True)\n    \"\"\"\n    current_sample = None\n    for filesample in data:\n        assert isinstance(filesample, dict)\n        fname, value = filesample[\"fname\"], filesample[\"data\"]\n        prefix, suffix = keys(fname)\n        if trace:\n            print(\n                prefix,\n                suffix,\n                current_sample.keys()\n                if isinstance(current_sample, dict) else None, )\n        if prefix is None:\n            continue\n        if lcase:\n            suffix = suffix.lower()\n        if current_sample is None or prefix != current_sample[\"__key__\"]:\n            if valid_sample(current_sample):\n                yield current_sample\n            current_sample = dict(__key__=prefix, __url__=filesample[\"__url__\"])\n        if suffix in current_sample:\n            raise ValueError(\n                f\"{fname}: duplicate file name in tar file {suffix} {current_sample.keys()}\"\n            )\n        if suffixes is None or suffix in suffixes:\n            current_sample[suffix] = value\n    if valid_sample(current_sample):\n        yield current_sample\n\n\ndef tarfile_samples(src, handler=reraise_exception):\n    streams = url_opener(src, handler=handler)\n    samples = tar_file_and_group_expander(streams, handler=handler)\n    return samples\n\n\ntarfile_to_samples = filters.pipelinefilter(tarfile_samples)\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/utils.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n#\n# Modified from https://github.com/webdataset/webdataset\n\"\"\"Miscellaneous utility functions.\"\"\"\nimport importlib\nimport itertools as itt\nimport os\nimport re\nimport sys\nfrom typing import Any\nfrom typing import Callable\nfrom typing import Iterator\nfrom typing import Union\n\nfrom ..utils.log import Logger\n\nlogger = Logger(__name__)\n\n\ndef make_seed(*args):\n    seed = 0\n    for arg in args:\n        seed = (seed * 31 + hash(arg)) & 0x7FFFFFFF\n    return seed\n\n\nclass PipelineStage:\n    def invoke(self, *args, **kw):\n        raise NotImplementedError\n\n\ndef identity(x: Any) -> Any:\n    \"\"\"Return the argument as is.\"\"\"\n    return x\n\n\ndef safe_eval(s: str, expr: str=\"{}\"):\n    \"\"\"Evaluate the given expression more safely.\"\"\"\n    if re.sub(\"[^A-Za-z0-9_]\", \"\", s) != s:\n        raise ValueError(f\"safe_eval: illegal characters in: '{s}'\")\n    return eval(expr.format(s))\n\n\ndef lookup_sym(sym: str, modules: list):\n    \"\"\"Look up a symbol in a list of modules.\"\"\"\n    for mname in modules:\n        module = importlib.import_module(mname, package=\"webdataset\")\n        result = getattr(module, sym, None)\n        if result is not None:\n            return result\n    return None\n\n\ndef repeatedly0(loader: Iterator,\n                nepochs: int=sys.maxsize,\n                nbatches: int=sys.maxsize):\n    \"\"\"Repeatedly returns batches from a DataLoader.\"\"\"\n    for epoch in range(nepochs):\n        for sample in itt.islice(loader, nbatches):\n            yield sample\n\n\ndef guess_batchsize(batch: Union[tuple, list]):\n    \"\"\"Guess the batch size by looking at the length of the first element in a tuple.\"\"\"\n    return len(batch[0])\n\n\ndef repeatedly(\n        source: Iterator,\n        nepochs: int=None,\n        nbatches: int=None,\n        nsamples: int=None,\n        batchsize: Callable[..., int]=guess_batchsize, ):\n    \"\"\"Repeatedly yield samples from an iterator.\"\"\"\n    epoch = 0\n    batch = 0\n    total = 0\n    while True:\n        for sample in source:\n            yield sample\n            batch += 1\n            if nbatches is not None and batch >= nbatches:\n                return\n            if nsamples is not None:\n                total += guess_batchsize(sample)\n                if total >= nsamples:\n                    return\n        epoch += 1\n        if nepochs is not None and epoch >= nepochs:\n            return\n\n\ndef paddle_worker_info(group=None):\n    \"\"\"Return node and worker info for PyTorch and some distributed environments.\"\"\"\n    rank = 0\n    world_size = 1\n    worker = 0\n    num_workers = 1\n    if \"RANK\" in os.environ and \"WORLD_SIZE\" in os.environ:\n        rank = int(os.environ[\"RANK\"])\n        world_size = int(os.environ[\"WORLD_SIZE\"])\n    else:\n        try:\n            import paddle.distributed\n            group = group or paddle.distributed.get_group()\n            rank = paddle.distributed.get_rank()\n            world_size = paddle.distributed.get_world_size()\n        except ModuleNotFoundError:\n            pass\n    if \"WORKER\" in os.environ and \"NUM_WORKERS\" in os.environ:\n        worker = int(os.environ[\"WORKER\"])\n        num_workers = int(os.environ[\"NUM_WORKERS\"])\n    else:\n        try:\n            from paddle.io import get_worker_info\n            worker_info = get_worker_info()\n            if worker_info is not None:\n                worker = worker_info.id\n                num_workers = worker_info.num_workers\n        except ModuleNotFoundError as E:\n            logger.info(f\"not found {E}\")\n            exit(-1)\n\n    return rank, world_size, worker, num_workers\n\n\ndef paddle_worker_seed(group=None):\n    \"\"\"Compute a distinct, deterministic RNG seed for each worker and node.\"\"\"\n    rank, world_size, worker, num_workers = paddle_worker_info(group=group)\n    return rank * 1000 + worker\n"
  },
  {
    "path": "paddlespeech/audio/streamdata/writer.py",
    "content": "#\n# Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# This file is part of the WebDataset library.\n# See the LICENSE file for licensing terms (BSD-style).\n# Modified from https://github.com/webdataset/webdataset\n#\n\"\"\"Classes and functions for writing tar files and WebDataset files.\"\"\"\nimport io\nimport json\nimport pickle\nimport re\nimport tarfile\nimport time\nfrom typing import Any\nfrom typing import Callable\nfrom typing import Optional\nfrom typing import Union\n\nimport numpy as np\n\nfrom . import gopen\n\n\ndef imageencoder(image: Any, format: str=\"PNG\"):  # skipcq: PYL-W0622\n    \"\"\"Compress an image using PIL and return it as a string.\n\n    Can handle float or uint8 images.\n\n    :param image: ndarray representing an image\n    :param format: compression format (PNG, JPEG, PPM)\n\n    \"\"\"\n    import PIL\n\n    assert isinstance(image, (PIL.Image.Image, np.ndarray)), type(image)\n\n    if isinstance(image, np.ndarray):\n        if image.dtype in [np.dtype(\"f\"), np.dtype(\"d\")]:\n            if not (np.amin(image) > -0.001 and np.amax(image) < 1.001):\n                raise ValueError(\n                    f\"image values out of range {np.amin(image)} {np.amax(image)}\"\n                )\n            image = np.clip(image, 0.0, 1.0)\n            image = np.array(image * 255.0, \"uint8\")\n        assert image.ndim in [2, 3]\n        if image.ndim == 3:\n            assert image.shape[2] in [1, 3]\n        image = PIL.Image.fromarray(image)\n    if format.upper() == \"JPG\":\n        format = \"JPEG\"\n    elif format.upper() in [\"IMG\", \"IMAGE\"]:\n        format = \"PPM\"\n    if format == \"JPEG\":\n        opts = dict(quality=100)\n    else:\n        opts = {}\n    with io.BytesIO() as result:\n        image.save(result, format=format, **opts)\n        return result.getvalue()\n\n\ndef bytestr(data: Any):\n    \"\"\"Convert data into a bytestring.\n\n    Uses str and ASCII encoding for data that isn't already in string format.\n\n    :param data: data\n    \"\"\"\n    if isinstance(data, bytes):\n        return data\n    if isinstance(data, str):\n        return data.encode(\"ascii\")\n    return str(data).encode(\"ascii\")\n\n\ndef paddle_dumps(data: Any):\n    \"\"\"Dump data into a bytestring using paddle.dumps.\n\n    This delays importing paddle until needed.\n\n    :param data: data to be dumped\n    \"\"\"\n    import io\n\n    import paddle\n\n    stream = io.BytesIO()\n    paddle.save(data, stream)\n    return stream.getvalue()\n\n\ndef numpy_dumps(data: np.ndarray):\n    \"\"\"Dump data into a bytestring using numpy npy format.\n\n    :param data: data to be dumped\n    \"\"\"\n    import io\n\n    import numpy.lib.format\n\n    stream = io.BytesIO()\n    numpy.lib.format.write_array(stream, data)\n    return stream.getvalue()\n\n\ndef numpy_npz_dumps(data: np.ndarray):\n    \"\"\"Dump data into a bytestring using numpy npz format.\n\n    :param data: data to be dumped\n    \"\"\"\n    import io\n\n    stream = io.BytesIO()\n    np.savez_compressed(stream, **data)\n    return stream.getvalue()\n\n\ndef tenbin_dumps(x):\n    from . import tenbin\n\n    if isinstance(x, list):\n        return memoryview(tenbin.encode_buffer(x))\n    else:\n        return memoryview(tenbin.encode_buffer([x]))\n\n\ndef cbor_dumps(x):\n    import cbor\n\n    return cbor.dumps(x)\n\n\ndef mp_dumps(x):\n    import msgpack\n\n    return msgpack.packb(x)\n\n\ndef add_handlers(d, keys, value):\n    if isinstance(keys, str):\n        keys = keys.split()\n    for k in keys:\n        d[k] = value\n\n\ndef make_handlers():\n    \"\"\"Create a list of handlers for encoding data.\"\"\"\n    handlers = {}\n    add_handlers(handlers, \"cls cls2 class count index inx id\",\n                 lambda x: str(x).encode(\"ascii\"))\n    add_handlers(handlers, \"txt text transcript\", lambda x: x.encode(\"utf-8\"))\n    add_handlers(handlers, \"html htm\", lambda x: x.encode(\"utf-8\"))\n    add_handlers(handlers, \"pyd pickle\", pickle.dumps)\n    add_handlers(handlers, \"pdparams\", paddle_dumps)\n    add_handlers(handlers, \"npy\", numpy_dumps)\n    add_handlers(handlers, \"npz\", numpy_npz_dumps)\n    add_handlers(handlers, \"ten tenbin tb\", tenbin_dumps)\n    add_handlers(handlers, \"json jsn\", lambda x: json.dumps(x).encode(\"utf-8\"))\n    add_handlers(handlers, \"mp msgpack msg\", mp_dumps)\n    add_handlers(handlers, \"cbor\", cbor_dumps)\n    add_handlers(handlers, \"jpg jpeg img image\",\n                 lambda data: imageencoder(data, \"jpg\"))\n    add_handlers(handlers, \"png\", lambda data: imageencoder(data, \"png\"))\n    add_handlers(handlers, \"pbm\", lambda data: imageencoder(data, \"pbm\"))\n    add_handlers(handlers, \"pgm\", lambda data: imageencoder(data, \"pgm\"))\n    add_handlers(handlers, \"ppm\", lambda data: imageencoder(data, \"ppm\"))\n    return handlers\n\n\ndefault_handlers = make_handlers()\n\n\ndef encode_based_on_extension1(data: Any, tname: str, handlers: dict):\n    \"\"\"Encode data based on its extension and a dict of handlers.\n\n    :param data: data\n    :param tname: file extension\n    :param handlers: handlers\n    \"\"\"\n    if tname[0] == \"_\":\n        if not isinstance(data, str):\n            raise ValueError(\"the values of metadata must be of string type\")\n        return data\n    extension = re.sub(r\".*\\.\", \"\", tname).lower()\n    if isinstance(data, bytes):\n        return data\n    if isinstance(data, str):\n        return data.encode(\"utf-8\")\n    handler = handlers.get(extension)\n    if handler is None:\n        raise ValueError(f\"no handler found for {extension}\")\n    return handler(data)\n\n\ndef encode_based_on_extension(sample: dict, handlers: dict):\n    \"\"\"Encode an entire sample with a collection of handlers.\n\n    :param sample: data sample (a dict)\n    :param handlers: handlers for encoding\n    \"\"\"\n    return {\n        k: encode_based_on_extension1(v, k, handlers)\n        for k, v in list(sample.items())\n    }\n\n\ndef make_encoder(spec: Union[bool, str, dict, Callable]):\n    \"\"\"Make an encoder function from a specification.\n\n    :param spec: specification\n    \"\"\"\n    if spec is False or spec is None:\n\n        def encoder(x):\n            \"\"\"Do not encode at all.\"\"\"\n            return x\n\n    elif callable(spec):\n        encoder = spec\n    elif isinstance(spec, dict):\n\n        def f(sample):\n            \"\"\"Encode based on extension.\"\"\"\n            return encode_based_on_extension(sample, spec)\n\n        encoder = f\n\n    elif spec is True:\n        handlers = default_handlers\n\n        def g(sample):\n            \"\"\"Encode based on extension.\"\"\"\n            return encode_based_on_extension(sample, handlers)\n\n        encoder = g\n\n    else:\n        raise ValueError(f\"{spec}: unknown decoder spec\")\n    if not callable(encoder):\n        raise ValueError(f\"{spec} did not yield a callable encoder\")\n    return encoder\n\n\nclass TarWriter:\n    \"\"\"A class for writing dictionaries to tar files.\n\n    :param fileobj: fileobj: file name for tar file (.tgz/.tar) or open file descriptor\n    :param encoder: sample encoding (Default value = True)\n    :param compress:  (Default value = None)\n\n    `True` will use an encoder that behaves similar to the automatic\n    decoder for `Dataset`. `False` disables encoding and expects byte strings\n    (except for metadata, which must be strings). The `encoder` argument can\n    also be a `callable`, or a dictionary mapping extensions to encoders.\n\n    The following code will add two file to the tar archive: `a/b.png` and\n    `a/b.output.png`.\n\n    ```Python\n        tarwriter = TarWriter(stream)\n        image = imread(\"b.jpg\")\n        image2 = imread(\"b.out.jpg\")\n        sample = {\"__key__\": \"a/b\", \"png\": image, \"output.png\": image2}\n        tarwriter.write(sample)\n    ```\n    \"\"\"\n\n    def __init__(\n            self,\n            fileobj,\n            user: str=\"bigdata\",\n            group: str=\"bigdata\",\n            mode: int=0o0444,\n            compress: Optional[bool]=None,\n            encoder: Union[None, bool, Callable]=True,\n            keep_meta: bool=False, ):\n        \"\"\"Create a tar writer.\n\n        :param fileobj: stream to write data to\n        :param user: user for tar files\n        :param group: group for tar files\n        :param mode: mode for tar files\n        :param compress: desired compression\n        :param encoder: encoder function\n        :param keep_meta: keep metadata (entries starting with \"_\")\n        \"\"\"\n        if isinstance(fileobj, str):\n            if compress is False:\n                tarmode = \"w|\"\n            elif compress is True:\n                tarmode = \"w|gz\"\n            else:\n                tarmode = \"w|gz\" if fileobj.endswith(\"gz\") else \"w|\"\n            fileobj = gopen.gopen(fileobj, \"wb\")\n            self.own_fileobj = fileobj\n        else:\n            tarmode = \"w|gz\" if compress is True else \"w|\"\n            self.own_fileobj = None\n        self.encoder = make_encoder(encoder)\n        self.keep_meta = keep_meta\n        self.stream = fileobj\n        self.tarstream = tarfile.open(fileobj=fileobj, mode=tarmode)\n\n        self.user = user\n        self.group = group\n        self.mode = mode\n        self.compress = compress\n\n    def __enter__(self):\n        \"\"\"Enter context.\"\"\"\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        \"\"\"Exit context.\"\"\"\n        self.close()\n\n    def close(self):\n        \"\"\"Close the tar file.\"\"\"\n        self.tarstream.close()\n        if self.own_fileobj is not None:\n            self.own_fileobj.close()\n            self.own_fileobj = None\n\n    def write(self, obj):\n        \"\"\"Write a dictionary to the tar file.\n\n        :param obj: dictionary of objects to be stored\n        :returns: size of the entry\n\n        \"\"\"\n        total = 0\n        obj = self.encoder(obj)\n        if \"__key__\" not in obj:\n            raise ValueError(\"object must contain a __key__\")\n        for k, v in list(obj.items()):\n            if k[0] == \"_\":\n                continue\n            if not isinstance(v, (bytes, bytearray, memoryview)):\n                raise ValueError(\n                    f\"{k} doesn't map to a bytes after encoding ({type(v)})\")\n        key = obj[\"__key__\"]\n        for k in sorted(obj.keys()):\n            if k == \"__key__\":\n                continue\n            if not self.keep_meta and k[0] == \"_\":\n                continue\n            v = obj[k]\n            if isinstance(v, str):\n                v = v.encode(\"utf-8\")\n            now = time.time()\n            ti = tarfile.TarInfo(key + \".\" + k)\n            ti.size = len(v)\n            ti.mtime = now\n            ti.mode = self.mode\n            ti.uname = self.user\n            ti.gname = self.group\n            if not isinstance(v, (bytes, bytearray, memoryview)):\n                raise ValueError(\n                    f\"converter didn't yield bytes: {k}, {type(v)}\")\n            stream = io.BytesIO(v)\n            self.tarstream.addfile(ti, stream)\n            total += ti.size\n        return total\n\n\nclass ShardWriter:\n    \"\"\"Like TarWriter but splits into multiple shards.\"\"\"\n\n    def __init__(\n            self,\n            pattern: str,\n            maxcount: int=100000,\n            maxsize: float=3e9,\n            post: Optional[Callable]=None,\n            start_shard: int=0,\n            **kw, ):\n        \"\"\"Create a ShardWriter.\n\n        :param pattern: output file pattern\n        :param maxcount: maximum number of records per shard (Default value = 100000)\n        :param maxsize: maximum size of each shard (Default value = 3e9)\n        :param kw: other options passed to TarWriter\n        \"\"\"\n        self.verbose = 1\n        self.kw = kw\n        self.maxcount = maxcount\n        self.maxsize = maxsize\n        self.post = post\n\n        self.tarstream = None\n        self.shard = start_shard\n        self.pattern = pattern\n        self.total = 0\n        self.count = 0\n        self.size = 0\n        self.fname = None\n        self.next_stream()\n\n    def next_stream(self):\n        \"\"\"Close the current stream and move to the next.\"\"\"\n        self.finish()\n        self.fname = self.pattern % self.shard\n        if self.verbose:\n            print(\n                \"# writing\",\n                self.fname,\n                self.count,\n                \"%.1f GB\" % (self.size / 1e9),\n                self.total, )\n        self.shard += 1\n        stream = open(self.fname, \"wb\")\n        self.tarstream = TarWriter(stream, **self.kw)\n        self.count = 0\n        self.size = 0\n\n    def write(self, obj):\n        \"\"\"Write a sample.\n\n        :param obj: sample to be written\n        \"\"\"\n        if (self.tarstream is None or self.count >= self.maxcount or\n                self.size >= self.maxsize):\n            self.next_stream()\n        size = self.tarstream.write(obj)\n        self.count += 1\n        self.total += 1\n        self.size += size\n\n    def finish(self):\n        \"\"\"Finish all writing (use close instead).\"\"\"\n        if self.tarstream is not None:\n            self.tarstream.close()\n            assert self.fname is not None\n            if callable(self.post):\n                self.post(self.fname)\n            self.tarstream = None\n\n    def close(self):\n        \"\"\"Close the stream.\"\"\"\n        self.finish()\n        del self.tarstream\n        del self.shard\n        del self.count\n        del self.size\n\n    def __enter__(self):\n        \"\"\"Enter context.\"\"\"\n        return self\n\n    def __exit__(self, *args, **kw):\n        \"\"\"Exit context.\"\"\"\n        self.close()\n"
  },
  {
    "path": "paddlespeech/audio/text/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/audio/text/text_featurizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the text featurizer class.\"\"\"\nfrom pprint import pformat\nfrom typing import Union\n\nimport sentencepiece as spm\n\nfrom ..utils.log import Logger\nfrom .utility import BLANK\nfrom .utility import EOS\nfrom .utility import load_dict\nfrom .utility import MASKCTC\nfrom .utility import SOS\nfrom .utility import SPACE\nfrom .utility import UNK\n\nlogger = Logger(__name__)\n\n__all__ = [\"TextFeaturizer\"]\n\n\nclass TextFeaturizer():\n    def __init__(self, unit_type, vocab, spm_model_prefix=None, maskctc=False):\n        \"\"\"Text featurizer, for processing or extracting features from text.\n\n        Currently, it supports char/word/sentence-piece level tokenizing and conversion into\n        a list of token indices. Note that the token indexing order follows the\n        given vocabulary file.\n\n        Args:\n            unit_type (str): unit type, e.g. char, word, spm\n            vocab Option[str, list]: Filepath to load vocabulary for token indices conversion, or vocab list.\n            spm_model_prefix (str, optional): spm model prefix. Defaults to None.\n        \"\"\"\n        assert unit_type in ('char', 'spm', 'word')\n        self.unit_type = unit_type\n        self.unk = UNK\n        self.maskctc = maskctc\n\n        if vocab:\n            self.vocab_dict, self._id2token, self.vocab_list, self.unk_id, self.eos_id, self.blank_id = self._load_vocabulary_from_file(\n                vocab, maskctc)\n            self.vocab_size = len(self.vocab_list)\n        else:\n            logger.warning(\"TextFeaturizer: not have vocab file or vocab list.\")\n\n        if unit_type == 'spm':\n            spm_model = spm_model_prefix + '.model'\n            self.sp = spm.SentencePieceProcessor()\n            self.sp.Load(spm_model)\n\n    def tokenize(self, text, replace_space=True):\n        if self.unit_type == 'char':\n            tokens = self.char_tokenize(text, replace_space)\n        elif self.unit_type == 'word':\n            tokens = self.word_tokenize(text)\n        else:  # spm\n            tokens = self.spm_tokenize(text)\n        return tokens\n\n    def detokenize(self, tokens):\n        if self.unit_type == 'char':\n            text = self.char_detokenize(tokens)\n        elif self.unit_type == 'word':\n            text = self.word_detokenize(tokens)\n        else:  # spm\n            text = self.spm_detokenize(tokens)\n        return text\n\n    def featurize(self, text):\n        \"\"\"Convert text string to a list of token indices.\n\n        Args:\n            text (str): Text to process.\n\n        Returns:\n            List[int]: List of token indices.\n        \"\"\"\n        tokens = self.tokenize(text)\n        ids = []\n        for token in tokens:\n            if token not in self.vocab_dict:\n                logger.debug(f\"Text Token: {token} -> {self.unk}\")\n                token = self.unk\n            ids.append(self.vocab_dict[token])\n        return ids\n\n    def defeaturize(self, idxs):\n        \"\"\"Convert a list of token indices to text string,\n        ignore index after eos_id.\n\n        Args:\n            idxs (List[int]): List of token indices.\n\n        Returns:\n            str: Text.\n        \"\"\"\n        tokens = []\n        for idx in idxs:\n            if idx == self.eos_id:\n                break\n            tokens.append(self._id2token[idx])\n        text = self.detokenize(tokens)\n        return text\n\n    def char_tokenize(self, text, replace_space=True):\n        \"\"\"Character tokenizer.\n\n        Args:\n            text (str): text string.\n            replace_space (bool): False only used by build_vocab.py.\n\n        Returns:\n            List[str]: tokens.\n        \"\"\"\n        text = text.strip()\n        if replace_space:\n            text_list = [SPACE if item == \" \" else item for item in list(text)]\n        else:\n            text_list = list(text)\n        return text_list\n\n    def char_detokenize(self, tokens):\n        \"\"\"Character detokenizer.\n\n        Args:\n            tokens (List[str]): tokens.\n\n        Returns:\n           str: text string.\n        \"\"\"\n        tokens = [t.replace(SPACE, \" \") for t in tokens]\n        return \"\".join(tokens)\n\n    def word_tokenize(self, text):\n        \"\"\"Word tokenizer, separate by <space>.\"\"\"\n        return text.strip().split()\n\n    def word_detokenize(self, tokens):\n        \"\"\"Word detokenizer, separate by <space>.\"\"\"\n        return \" \".join(tokens)\n\n    def spm_tokenize(self, text):\n        \"\"\"spm tokenize.\n\n        Args:\n            text (str): text string.\n\n        Returns:\n            List[str]: sentence pieces str code\n        \"\"\"\n        stats = {\"num_empty\": 0, \"num_filtered\": 0}\n\n        def valid(line):\n            return True\n\n        def encode(l):\n            return self.sp.EncodeAsPieces(l)\n\n        def encode_line(line):\n            line = line.strip()\n            if len(line) > 0:\n                line = encode(line)\n                if valid(line):\n                    return line\n                else:\n                    stats[\"num_filtered\"] += 1\n            else:\n                stats[\"num_empty\"] += 1\n            return None\n\n        enc_line = encode_line(text)\n        return enc_line\n\n    def spm_detokenize(self, tokens, input_format='piece'):\n        \"\"\"spm detokenize.\n\n        Args:\n            ids (List[str]): tokens.\n\n        Returns:\n            str: text\n        \"\"\"\n        if input_format == \"piece\":\n\n            def decode(l):\n                return \"\".join(self.sp.DecodePieces(l))\n        elif input_format == \"id\":\n\n            def decode(l):\n                return \"\".join(self.sp.DecodeIds(l))\n\n        return decode(tokens)\n\n    def _load_vocabulary_from_file(self, vocab: Union[str, list],\n                                   maskctc: bool):\n        \"\"\"Load vocabulary from file.\"\"\"\n        if isinstance(vocab, list):\n            vocab_list = vocab\n        else:\n            vocab_list = load_dict(vocab, maskctc)\n        assert vocab_list is not None\n        logger.debug(f\"Vocab: {pformat(vocab_list)}\")\n\n        id2token = dict(\n            [(idx, token) for (idx, token) in enumerate(vocab_list)])\n        token2id = dict(\n            [(token, idx) for (idx, token) in enumerate(vocab_list)])\n\n        blank_id = vocab_list.index(BLANK) if BLANK in vocab_list else -1\n        maskctc_id = vocab_list.index(MASKCTC) if MASKCTC in vocab_list else -1\n        unk_id = vocab_list.index(UNK) if UNK in vocab_list else -1\n        eos_id = vocab_list.index(EOS) if EOS in vocab_list else -1\n        sos_id = vocab_list.index(SOS) if SOS in vocab_list else -1\n        space_id = vocab_list.index(SPACE) if SPACE in vocab_list else -1\n\n        logger.info(f\"BLANK id: {blank_id}\")\n        logger.info(f\"UNK id: {unk_id}\")\n        logger.info(f\"EOS id: {eos_id}\")\n        logger.info(f\"SOS id: {sos_id}\")\n        logger.info(f\"SPACE id: {space_id}\")\n        logger.info(f\"MASKCTC id: {maskctc_id}\")\n        return token2id, id2token, vocab_list, unk_id, eos_id, blank_id\n"
  },
  {
    "path": "paddlespeech/audio/text/utility.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains data helper functions.\"\"\"\nimport json\nimport math\nimport tarfile\nfrom collections import namedtuple\nfrom typing import List\nfrom typing import Optional\nfrom typing import Text\n\nimport jsonlines\nimport numpy as np\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"load_dict\", \"load_cmvn\", \"read_manifest\", \"rms_to_db\", \"rms_to_dbfs\",\n    \"max_dbfs\", \"mean_dbfs\", \"gain_db_to_ratio\", \"normalize_audio\", \"SOS\",\n    \"EOS\", \"UNK\", \"BLANK\", \"MASKCTC\", \"SPACE\", \"convert_samples_to_float32\",\n    \"convert_samples_from_float32\"\n]\n\nIGNORE_ID = -1\n# `sos` and `eos` using same token\nSOS = \"<eos>\"\nEOS = SOS\nUNK = \"<unk>\"\nBLANK = \"<blank>\"\nMASKCTC = \"<mask>\"\nSPACE = \"<space>\"\n\n\ndef load_dict(dict_path: Optional[Text], maskctc=False) -> Optional[List[Text]]:\n    if dict_path is None:\n        return None\n\n    with open(dict_path, \"r\") as f:\n        dictionary = f.readlines()\n    # first token is `<blank>`\n    # multi line: `<blank> 0\\n`\n    # one line: `<blank>`\n    # space is relpace with <space>\n    char_list = [entry[:-1].split(\" \")[0] for entry in dictionary]\n    if BLANK not in char_list:\n        char_list.insert(0, BLANK)\n    if EOS not in char_list:\n        char_list.append(EOS)\n    # for non-autoregressive maskctc model\n    if maskctc and MASKCTC not in char_list:\n        char_list.append(MASKCTC)\n    return char_list\n\n\ndef read_manifest(\n        manifest_path,\n        max_input_len=float('inf'),\n        min_input_len=0.0,\n        max_output_len=float('inf'),\n        min_output_len=0.0,\n        max_output_input_ratio=float('inf'),\n        min_output_input_ratio=0.0, ):\n    \"\"\"Load and parse manifest file.\n\n    Args:\n        manifest_path ([type]): Manifest file to load and parse.\n        max_input_len ([type], optional): maximum output seq length,\n            in seconds for raw wav, in frame numbers for feature data.\n            Defaults to float('inf').\n        min_input_len (float, optional): minimum input seq length,\n            in seconds for raw wav, in frame numbers for feature data.\n            Defaults to 0.0.\n        max_output_len (float, optional): maximum input seq length,\n            in modeling units. Defaults to 500.0.\n        min_output_len (float, optional): minimum input seq length,\n            in modeling units. Defaults to 0.0.\n        max_output_input_ratio (float, optional):\n            maximum output seq length/output seq length ratio. Defaults to 10.0.\n        min_output_input_ratio (float, optional):\n            minimum output seq length/output seq length ratio. Defaults to 0.05.\n\n    Raises:\n        IOError: If failed to parse the manifest.\n\n    Returns:\n        List[dict]: Manifest parsing results.\n    \"\"\"\n    manifest = []\n    with jsonlines.open(manifest_path, 'r') as reader:\n        for json_data in reader:\n            feat_len = json_data[\"input\"][0][\"shape\"][\n                0] if \"input\" in json_data and \"shape\" in json_data[\"input\"][\n                    0] else 1.0\n            token_len = json_data[\"output\"][0][\"shape\"][\n                0] if \"output\" in json_data and \"shape\" in json_data[\"output\"][\n                    0] else 1.0\n            conditions = [\n                feat_len >= min_input_len,\n                feat_len <= max_input_len,\n                token_len >= min_output_len,\n                token_len <= max_output_len,\n                token_len / feat_len >= min_output_input_ratio,\n                token_len / feat_len <= max_output_input_ratio,\n            ]\n            if all(conditions):\n                manifest.append(json_data)\n    return manifest\n\n\n# Tar File read\nTarLocalData = namedtuple('TarLocalData', ['tar2info', 'tar2object'])\n\n\ndef parse_tar(file):\n    \"\"\"Parse a tar file to get a tarfile object\n    and a map containing tarinfoes\n    \"\"\"\n    result = {}\n    f = tarfile.open(file)\n    for tarinfo in f.getmembers():\n        result[tarinfo.name] = tarinfo\n    return f, result\n\n\ndef subfile_from_tar(file, local_data=None):\n    \"\"\"Get subfile object from tar.\n\n    tar:tarpath#filename\n\n    It will return a subfile object from tar file\n    and cached tar file info for next reading request.\n    \"\"\"\n    tarpath, filename = file.split(':', 1)[1].split('#', 1)\n\n    if local_data is None:\n        local_data = TarLocalData(tar2info={}, tar2object={})\n\n    assert isinstance(local_data, TarLocalData)\n\n    if 'tar2info' not in local_data.__dict__:\n        local_data.tar2info = {}\n    if 'tar2object' not in local_data.__dict__:\n        local_data.tar2object = {}\n\n    if tarpath not in local_data.tar2info:\n        fobj, infos = parse_tar(tarpath)\n        local_data.tar2info[tarpath] = infos\n        local_data.tar2object[tarpath] = fobj\n    else:\n        fobj = local_data.tar2object[tarpath]\n        infos = local_data.tar2info[tarpath]\n    return fobj.extractfile(infos[filename])\n\n\ndef rms_to_db(rms: float):\n    \"\"\"Root Mean Square to dB.\n\n    Args:\n        rms ([float]): root mean square\n\n    Returns:\n        float: dB\n    \"\"\"\n    return 20.0 * math.log10(max(1e-16, rms))\n\n\ndef rms_to_dbfs(rms: float):\n    \"\"\"Root Mean Square to dBFS.\n    https://fireattack.wordpress.com/2017/02/06/replaygain-loudness-normalization-and-applications/\n    Audio is mix of sine wave, so 1 amp sine wave's Full scale is 0.7071, equal to -3.0103dB.\n\n    dB = dBFS + 3.0103\n    dBFS = db - 3.0103\n    e.g. 0 dB = -3.0103 dBFS\n\n    Args:\n        rms ([float]): root mean square\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    return rms_to_db(rms) - 3.0103\n\n\ndef max_dbfs(sample_data: np.ndarray):\n    \"\"\"Peak dBFS based on the maximum energy sample.\n\n    Args:\n        sample_data ([np.ndarray]): float array, [-1, 1].\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    # Peak dBFS based on the maximum energy sample. Will prevent overdrive if used for normalization.\n    return rms_to_dbfs(max(abs(np.min(sample_data)), abs(np.max(sample_data))))\n\n\ndef mean_dbfs(sample_data):\n    \"\"\"Peak dBFS based on the RMS energy.\n\n    Args:\n        sample_data ([np.ndarray]): float array, [-1, 1].\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    return rms_to_dbfs(\n        math.sqrt(np.mean(np.square(sample_data, dtype=np.float64))))\n\n\ndef gain_db_to_ratio(gain_db: float):\n    \"\"\"dB to ratio\n\n    Args:\n        gain_db (float): gain in dB\n\n    Returns:\n        float: scale in amp\n    \"\"\"\n    return math.pow(10.0, gain_db / 20.0)\n\n\ndef normalize_audio(sample_data: np.ndarray, dbfs: float=-3.0103):\n    \"\"\"Nomalize audio to dBFS.\n\n    Args:\n        sample_data (np.ndarray): input wave samples, [-1, 1].\n        dbfs (float, optional): target dBFS. Defaults to -3.0103.\n\n    Returns:\n        np.ndarray: normalized wave\n    \"\"\"\n    return np.maximum(\n        np.minimum(sample_data * gain_db_to_ratio(dbfs - max_dbfs(sample_data)),\n                   1.0), -1.0)\n\n\ndef _load_json_cmvn(json_cmvn_file):\n    \"\"\" Load the json format cmvn stats file and calculate cmvn\n\n    Args:\n        json_cmvn_file: cmvn stats file in json format\n\n    Returns:\n        a numpy array of [means, vars]\n    \"\"\"\n    with open(json_cmvn_file) as f:\n        cmvn_stats = json.load(f)\n\n    means = cmvn_stats['mean_stat']\n    variance = cmvn_stats['var_stat']\n    count = cmvn_stats['frame_num']\n    for i in range(len(means)):\n        means[i] /= count\n        variance[i] = variance[i] / count - means[i] * means[i]\n        if variance[i] < 1.0e-20:\n            variance[i] = 1.0e-20\n        variance[i] = 1.0 / math.sqrt(variance[i])\n    cmvn = np.array([means, variance])\n    return cmvn\n\n\ndef _load_kaldi_cmvn(kaldi_cmvn_file):\n    \"\"\" Load the kaldi format cmvn stats file and calculate cmvn\n\n    Args:\n        kaldi_cmvn_file:  kaldi text style global cmvn file, which\n           is generated by:\n           compute-cmvn-stats --binary=false scp:feats.scp global_cmvn\n\n    Returns:\n        a numpy array of [means, vars]\n    \"\"\"\n    means = []\n    variance = []\n    with open(kaldi_cmvn_file, 'r') as fid:\n        # kaldi binary file start with '\\0B'\n        if fid.read(2) == '\\0B':\n            logger.error('kaldi cmvn binary file is not supported, please '\n                         'recompute it by: compute-cmvn-stats --binary=false '\n                         ' scp:feats.scp global_cmvn')\n            sys.exit(1)\n        fid.seek(0)\n        arr = fid.read().split()\n        assert (arr[0] == '[')\n        assert (arr[-2] == '0')\n        assert (arr[-1] == ']')\n        feat_dim = int((len(arr) - 2 - 2) / 2)\n        for i in range(1, feat_dim + 1):\n            means.append(float(arr[i]))\n        count = float(arr[feat_dim + 1])\n        for i in range(feat_dim + 2, 2 * feat_dim + 2):\n            variance.append(float(arr[i]))\n\n    for i in range(len(means)):\n        means[i] /= count\n        variance[i] = variance[i] / count - means[i] * means[i]\n        if variance[i] < 1.0e-20:\n            variance[i] = 1.0e-20\n        variance[i] = 1.0 / math.sqrt(variance[i])\n    cmvn = np.array([means, variance])\n    return cmvn\n\n\ndef load_cmvn(cmvn_file: str, filetype: str):\n    \"\"\"load cmvn from file.\n\n    Args:\n        cmvn_file (str): cmvn path.\n        filetype (str): file type, optional[npz, json, kaldi].\n\n    Raises:\n        ValueError: file type not support.\n\n    Returns:\n        Tuple[np.ndarray, np.ndarray]: mean, istd\n    \"\"\"\n    assert filetype in ['npz', 'json', 'kaldi'], filetype\n    filetype = filetype.lower()\n    if filetype == \"json\":\n        cmvn = _load_json_cmvn(cmvn_file)\n    elif filetype == \"kaldi\":\n        cmvn = _load_kaldi_cmvn(cmvn_file)\n    elif filetype == \"npz\":\n        eps = 1e-14\n        npzfile = np.load(cmvn_file)\n        mean = np.squeeze(npzfile[\"mean\"])\n        std = np.squeeze(npzfile[\"std\"])\n        istd = 1 / (std + eps)\n        cmvn = [mean, istd]\n    else:\n        raise ValueError(f\"cmvn file type no support: {filetype}\")\n    return cmvn[0], cmvn[1]\n\n\ndef convert_samples_to_float32(samples):\n    \"\"\"Convert sample type to float32.\n\n    Audio sample type is usually integer or float-point.\n    Integers will be scaled to [-1, 1] in float32.\n\n    PCM16 -> PCM32\n    \"\"\"\n    float32_samples = samples.astype('float32')\n    if samples.dtype in np.sctypes['int']:\n        bits = np.iinfo(samples.dtype).bits\n        float32_samples *= (1. / 2**(bits - 1))\n    elif samples.dtype in np.sctypes['float']:\n        pass\n    else:\n        raise TypeError(\"Unsupported sample type: %s.\" % samples.dtype)\n    return float32_samples\n\n\ndef convert_samples_from_float32(samples, dtype):\n    \"\"\"Convert sample type from float32 to dtype.\n\n    Audio sample type is usually integer or float-point. For integer\n    type, float32 will be rescaled from [-1, 1] to the maximum range\n    supported by the integer type.\n\n    PCM32 -> PCM16\n    \"\"\"\n    dtype = np.dtype(dtype)\n    output_samples = samples.copy()\n    if dtype in np.sctypes['int']:\n        bits = np.iinfo(dtype).bits\n        output_samples *= (2**(bits - 1) / 1.)\n        min_val = np.iinfo(dtype).min\n        max_val = np.iinfo(dtype).max\n        output_samples[output_samples > max_val] = max_val\n        output_samples[output_samples < min_val] = min_val\n    elif samples.dtype in np.sctypes['float']:\n        min_val = np.finfo(dtype).min\n        max_val = np.finfo(dtype).max\n        output_samples[output_samples > max_val] = max_val\n        output_samples[output_samples < min_val] = min_val\n    else:\n        raise TypeError(\"Unsupported sample type: %s.\" % samples.dtype)\n    return output_samples.astype(dtype)\n"
  },
  {
    "path": "paddlespeech/audio/transform/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/audio/transform/add_deltas.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport numpy as np\n\n\ndef delta(feat, window):\n    assert window > 0\n    delta_feat = np.zeros_like(feat)\n    for i in range(1, window + 1):\n        delta_feat[:-i] += i * feat[i:]\n        delta_feat[i:] += -i * feat[:-i]\n        delta_feat[-i:] += i * feat[-1]\n        delta_feat[:i] += -i * feat[0]\n    delta_feat /= 2 * sum(i**2 for i in range(1, window + 1))\n    return delta_feat\n\n\ndef add_deltas(x, window=2, order=2):\n    \"\"\"\n    Args:\n        x (np.ndarray): speech feat, (T, D).\n\n    Return:\n        np.ndarray: (T, (1+order)*D)\n    \"\"\"\n    feats = [x]\n    for _ in range(order):\n        feats.append(delta(feats[-1], window))\n    return np.concatenate(feats, axis=1)\n\n\nclass AddDeltas():\n    def __init__(self, window=2, order=2):\n        self.window = window\n        self.order = order\n\n    def __repr__(self):\n        return \"{name}(window={window}, order={order}\".format(\n            name=self.__class__.__name__, window=self.window, order=self.order)\n\n    def __call__(self, x):\n        return add_deltas(x, window=self.window, order=self.order)\n"
  },
  {
    "path": "paddlespeech/audio/transform/channel_selector.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport numpy\n\n\nclass ChannelSelector():\n    \"\"\"Select 1ch from multi-channel signal\"\"\"\n\n    def __init__(self, train_channel=\"random\", eval_channel=0, axis=1):\n        self.train_channel = train_channel\n        self.eval_channel = eval_channel\n        self.axis = axis\n\n    def __repr__(self):\n        return (\"{name}(train_channel={train_channel}, \"\n                \"eval_channel={eval_channel}, axis={axis})\".format(\n                    name=self.__class__.__name__,\n                    train_channel=self.train_channel,\n                    eval_channel=self.eval_channel,\n                    axis=self.axis, ))\n\n    def __call__(self, x, train=True):\n        # Assuming x: [Time, Channel] by default\n\n        if x.ndim <= self.axis:\n            # If the dimension is insufficient, then unsqueeze\n            # (e.g [Time] -> [Time, 1])\n            ind = tuple(\n                slice(None) if i < x.ndim else None\n                for i in range(self.axis + 1))\n            x = x[ind]\n\n        if train:\n            channel = self.train_channel\n        else:\n            channel = self.eval_channel\n\n        if channel == \"random\":\n            ch = numpy.random.randint(0, x.shape[self.axis])\n        else:\n            ch = channel\n\n        ind = tuple(\n            slice(None) if i != self.axis else ch for i in range(x.ndim))\n        return x[ind]\n"
  },
  {
    "path": "paddlespeech/audio/transform/cmvn.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport io\nimport json\n\nimport h5py\nimport kaldiio\nimport numpy as np\n\n\nclass CMVN():\n    \"Apply Global/Spk CMVN/iverserCMVN.\"\n\n    def __init__(\n            self,\n            stats,\n            norm_means=True,\n            norm_vars=False,\n            filetype=\"mat\",\n            utt2spk=None,\n            spk2utt=None,\n            reverse=False,\n            std_floor=1.0e-20, ):\n        self.stats_file = stats\n        self.norm_means = norm_means\n        self.norm_vars = norm_vars\n        self.reverse = reverse\n\n        if isinstance(stats, dict):\n            stats_dict = dict(stats)\n        else:\n            # Use for global CMVN\n            if filetype == \"mat\":\n                stats_dict = {None: kaldiio.load_mat(stats)}\n            # Use for global CMVN\n            elif filetype == \"npy\":\n                stats_dict = {None: np.load(stats)}\n            # Use for speaker CMVN\n            elif filetype == \"ark\":\n                self.accept_uttid = True\n                stats_dict = dict(kaldiio.load_ark(stats))\n            # Use for speaker CMVN\n            elif filetype == \"hdf5\":\n                self.accept_uttid = True\n                stats_dict = h5py.File(stats)\n            else:\n                raise ValueError(\"Not supporting filetype={}\".format(filetype))\n\n        if utt2spk is not None:\n            self.utt2spk = {}\n            with io.open(utt2spk, \"r\", encoding=\"utf-8\") as f:\n                for line in f:\n                    utt, spk = line.rstrip().split(None, 1)\n                    self.utt2spk[utt] = spk\n        elif spk2utt is not None:\n            self.utt2spk = {}\n            with io.open(spk2utt, \"r\", encoding=\"utf-8\") as f:\n                for line in f:\n                    spk, utts = line.rstrip().split(None, 1)\n                    for utt in utts.split():\n                        self.utt2spk[utt] = spk\n        else:\n            self.utt2spk = None\n\n        # Kaldi makes a matrix for CMVN which has a shape of (2, feat_dim + 1),\n        # and the first vector contains the sum of feats and the second is\n        # the sum of squares. The last value of the first, i.e. stats[0,-1],\n        # is the number of samples for this statistics.\n        self.bias = {}\n        self.scale = {}\n        for spk, stats in stats_dict.items():\n            assert len(stats) == 2, stats.shape\n\n            count = stats[0, -1]\n\n            # If the feature has two or more dimensions\n            if not (np.isscalar(count) or isinstance(count, (int, float))):\n                # The first is only used\n                count = count.flatten()[0]\n\n            mean = stats[0, :-1] / count\n            # V(x) = E(x^2) - (E(x))^2\n            var = stats[1, :-1] / count - mean * mean\n            std = np.maximum(np.sqrt(var), std_floor)\n            self.bias[spk] = -mean\n            self.scale[spk] = 1 / std\n\n    def __repr__(self):\n        return (\"{name}(stats_file={stats_file}, \"\n                \"norm_means={norm_means}, norm_vars={norm_vars}, \"\n                \"reverse={reverse})\".format(\n                    name=self.__class__.__name__,\n                    stats_file=self.stats_file,\n                    norm_means=self.norm_means,\n                    norm_vars=self.norm_vars,\n                    reverse=self.reverse, ))\n\n    def __call__(self, x, uttid=None):\n        if self.utt2spk is not None:\n            spk = self.utt2spk[uttid]\n        else:\n            spk = uttid\n\n        if not self.reverse:\n            # apply cmvn\n            if self.norm_means:\n                x = np.add(x, self.bias[spk])\n            if self.norm_vars:\n                x = np.multiply(x, self.scale[spk])\n\n        else:\n            # apply reverse cmvn\n            if self.norm_vars:\n                x = np.divide(x, self.scale[spk])\n            if self.norm_means:\n                x = np.subtract(x, self.bias[spk])\n\n        return x\n\n\nclass UtteranceCMVN():\n    \"Apply Utterance CMVN\"\n\n    def __init__(self, norm_means=True, norm_vars=False, std_floor=1.0e-20):\n        self.norm_means = norm_means\n        self.norm_vars = norm_vars\n        self.std_floor = std_floor\n\n    def __repr__(self):\n        return \"{name}(norm_means={norm_means}, norm_vars={norm_vars})\".format(\n            name=self.__class__.__name__,\n            norm_means=self.norm_means,\n            norm_vars=self.norm_vars, )\n\n    def __call__(self, x, uttid=None):\n        # x: [Time, Dim]\n        square_sums = (x**2).sum(axis=0)\n        mean = x.mean(axis=0)\n\n        if self.norm_means:\n            x = np.subtract(x, mean)\n\n        if self.norm_vars:\n            var = square_sums / x.shape[0] - mean**2\n            std = np.maximum(np.sqrt(var), self.std_floor)\n            x = np.divide(x, std)\n\n        return x\n\n\nclass GlobalCMVN():\n    \"Apply Global CMVN\"\n\n    def __init__(self,\n                 cmvn_path,\n                 norm_means=True,\n                 norm_vars=True,\n                 std_floor=1.0e-20):\n        # cmvn_path: Option[str, dict]\n        cmvn = cmvn_path\n        self.cmvn = cmvn\n        self.norm_means = norm_means\n        self.norm_vars = norm_vars\n        self.std_floor = std_floor\n        if isinstance(cmvn, dict):\n            cmvn_stats = cmvn\n        else:\n            with open(cmvn) as f:\n                cmvn_stats = json.load(f)\n        self.count = cmvn_stats['frame_num']\n        self.mean = np.array(cmvn_stats['mean_stat']) / self.count\n        self.square_sums = np.array(cmvn_stats['var_stat'])\n        self.var = self.square_sums / self.count - self.mean**2\n        self.std = np.maximum(np.sqrt(self.var), self.std_floor)\n\n    def __repr__(self):\n        return f\"\"\"{self.__class__.__name__}(\n            cmvn_path={self.cmvn},\n            norm_means={self.norm_means},\n            norm_vars={self.norm_vars},)\"\"\"\n\n    def __call__(self, x, uttid=None):\n        # x: [Time, Dim]\n        if self.norm_means:\n            x = np.subtract(x, self.mean)\n\n        if self.norm_vars:\n            x = np.divide(x, self.std)\n        return x\n"
  },
  {
    "path": "paddlespeech/audio/transform/functional.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport inspect\n\nfrom paddlespeech.audio.transform.transform_interface import TransformInterface\nfrom paddlespeech.audio.utils.check_kwargs import check_kwargs\n\n\nclass FuncTrans(TransformInterface):\n    \"\"\"Functional Transformation\n\n    WARNING:\n        Builtin or C/C++ functions may not work properly\n        because this class heavily depends on the `inspect` module.\n\n    Usage:\n\n    >>> def foo_bar(x, a=1, b=2):\n    ...     '''Foo bar\n    ...     :param x: input\n    ...     :param int a: default 1\n    ...     :param int b: default 2\n    ...     '''\n    ...     return x + a - b\n\n\n    >>> class FooBar(FuncTrans):\n    ...     _func = foo_bar\n    ...     __doc__ = foo_bar.__doc__\n    \"\"\"\n\n    _func = None\n\n    def __init__(self, **kwargs):\n        self.kwargs = kwargs\n        check_kwargs(self.func, kwargs)\n\n    def __call__(self, x):\n        return self.func(x, **self.kwargs)\n\n    @classmethod\n    def add_arguments(cls, parser):\n        fname = cls._func.__name__.replace(\"_\", \"-\")\n        group = parser.add_argument_group(fname + \" transformation setting\")\n        for k, v in cls.default_params().items():\n            # TODO(karita): get help and choices from docstring?\n            attr = k.replace(\"_\", \"-\")\n            group.add_argument(f\"--{fname}-{attr}\", default=v, type=type(v))\n        return parser\n\n    @property\n    def func(self):\n        return type(self)._func\n\n    @classmethod\n    def default_params(cls):\n        try:\n            d = dict(inspect.signature(cls._func).parameters)\n        except ValueError:\n            d = dict()\n        return {\n            k: v.default\n            for k, v in d.items() if v.default != inspect.Parameter.empty\n        }\n\n    def __repr__(self):\n        params = self.default_params()\n        params.update(**self.kwargs)\n        ret = self.__class__.__name__ + \"(\"\n        if len(params) == 0:\n            return ret + \")\"\n        for k, v in params.items():\n            ret += \"{}={}, \".format(k, v)\n        return ret[:-2] + \")\"\n"
  },
  {
    "path": "paddlespeech/audio/transform/perturb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport io\nimport os\nimport sys\n\nimport h5py\nimport librosa\nimport numpy\nimport numpy as np\nimport scipy\nimport soundfile\n\n\nclass SoundHDF5File():\n    \"\"\"Collecting sound files to a HDF5 file\n\n    >>> f = SoundHDF5File('a.flac.h5', mode='a')\n    >>> array = np.random.randint(0, 100, 100, dtype=np.int16)\n    >>> f['id'] = (array, 16000)\n    >>> array, rate = f['id']\n\n\n    :param: str filepath:\n    :param: str mode:\n    :param: str format: The type used when saving wav. flac, nist, htk, etc.\n    :param: str dtype:\n\n    \"\"\"\n\n    def __init__(self,\n                 filepath,\n                 mode=\"r+\",\n                 format=None,\n                 dtype=\"int16\",\n                 **kwargs):\n        self.filepath = filepath\n        self.mode = mode\n        self.dtype = dtype\n\n        self.file = h5py.File(filepath, mode, **kwargs)\n        if format is None:\n            # filepath = a.flac.h5 -> format = flac\n            second_ext = os.path.splitext(os.path.splitext(filepath)[0])[1]\n            format = second_ext[1:]\n            if format.upper() not in soundfile.available_formats():\n                # If not found, flac is selected\n                format = \"flac\"\n\n        # This format affects only saving\n        self.format = format\n\n    def __repr__(self):\n        return '<SoundHDF5 file \"{}\" (mode {}, format {}, type {})>'.format(\n            self.filepath, self.mode, self.format, self.dtype)\n\n    def create_dataset(self, name, shape=None, data=None, **kwds):\n        f = io.BytesIO()\n        array, rate = data\n        soundfile.write(f, array, rate, format=self.format)\n        self.file.create_dataset(\n            name, shape=shape, data=np.void(f.getvalue()), **kwds)\n\n    def __setitem__(self, name, data):\n        self.create_dataset(name, data=data)\n\n    def __getitem__(self, key):\n        data = self.file[key][()]\n        f = io.BytesIO(data.tobytes())\n        array, rate = soundfile.read(f, dtype=self.dtype)\n        return array, rate\n\n    def keys(self):\n        return self.file.keys()\n\n    def values(self):\n        for k in self.file:\n            yield self[k]\n\n    def items(self):\n        for k in self.file:\n            yield k, self[k]\n\n    def __iter__(self):\n        return iter(self.file)\n\n    def __contains__(self, item):\n        return item in self.file\n\n    def __len__(self):\n        return len(self.file)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.file.close()\n\n    def close(self):\n        self.file.close()\n\n\nclass SpeedPerturbation():\n    \"\"\"SpeedPerturbation\n\n    The speed perturbation in kaldi uses sox-speed instead of sox-tempo,\n    and sox-speed just to resample the input,\n    i.e pitch and tempo are changed both.\n\n    \"Why use speed option instead of tempo -s in SoX for speed perturbation\"\n    https://groups.google.com/forum/#!topic/kaldi-help/8OOG7eE4sZ8\n\n    Warning:\n        This function is very slow because of resampling.\n        I recommmend to apply speed-perturb outside the training using sox.\n\n    \"\"\"\n\n    def __init__(\n            self,\n            lower=0.9,\n            upper=1.1,\n            utt2ratio=None,\n            keep_length=True,\n            res_type=\"kaiser_best\",\n            seed=None, ):\n        self.res_type = res_type\n        self.keep_length = keep_length\n        self.state = numpy.random.RandomState(seed)\n\n        if utt2ratio is not None:\n            self.utt2ratio = {}\n            # Use the scheduled ratio for each utterances\n            self.utt2ratio_file = utt2ratio\n            self.lower = None\n            self.upper = None\n            self.accept_uttid = True\n\n            with open(utt2ratio, \"r\") as f:\n                for line in f:\n                    utt, ratio = line.rstrip().split(None, 1)\n                    ratio = float(ratio)\n                    self.utt2ratio[utt] = ratio\n        else:\n            self.utt2ratio = None\n            # The ratio is given on runtime randomly\n            self.lower = lower\n            self.upper = upper\n\n    def __repr__(self):\n        if self.utt2ratio is None:\n            return \"{}(lower={}, upper={}, \" \"keep_length={}, res_type={})\".format(\n                self.__class__.__name__,\n                self.lower,\n                self.upper,\n                self.keep_length,\n                self.res_type, )\n        else:\n            return \"{}({}, res_type={})\".format(\n                self.__class__.__name__, self.utt2ratio_file, self.res_type)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        x = x.astype(numpy.float32)\n        if self.accept_uttid:\n            ratio = self.utt2ratio[uttid]\n        else:\n            ratio = self.state.uniform(self.lower, self.upper)\n\n        # Note1: resample requires the sampling-rate of input and output,\n        #        but actually only the ratio is used.\n        y = librosa.resample(\n            x, orig_sr=ratio, target_sr=1, res_type=self.res_type)\n\n        if self.keep_length:\n            diff = abs(len(x) - len(y))\n            if len(y) > len(x):\n                # Truncate noise\n                y = y[diff // 2:-((diff + 1) // 2)]\n            elif len(y) < len(x):\n                # Assume the time-axis is the first: (Time, Channel)\n                pad_width = [(diff // 2, (diff + 1) // 2)] + [\n                    (0, 0) for _ in range(y.ndim - 1)\n                ]\n                y = numpy.pad(\n                    y, pad_width=pad_width, constant_values=0, mode=\"constant\")\n        return y\n\n\nclass SpeedPerturbationSox():\n    \"\"\"SpeedPerturbationSox\n\n    The speed perturbation in kaldi uses sox-speed instead of sox-tempo,\n    and sox-speed just to resample the input,\n    i.e pitch and tempo are changed both.\n\n    To speed up or slow down the sound of a file,\n    use speed to modify the pitch and the duration of the file.\n    This raises the speed and reduces the time.\n    The default factor is 1.0 which makes no change to the audio.\n    2.0 doubles speed, thus time length is cut by a half and pitch is one interval higher.\n\n    \"Why use speed option instead of tempo -s in SoX for speed perturbation\"\n    https://groups.google.com/forum/#!topic/kaldi-help/8OOG7eE4sZ8\n\n    tempo option:\n    sox -t wav input.wav -t wav output.tempo0.9.wav tempo -s 0.9\n\n    speed option:\n    sox -t wav input.wav -t wav output.speed0.9.wav speed 0.9\n\n    If we use speed option like above, the pitch of audio also will be changed,\n    but the tempo option does not change the pitch.\n    \"\"\"\n\n    def __init__(\n            self,\n            lower=0.9,\n            upper=1.1,\n            utt2ratio=None,\n            keep_length=True,\n            sr=16000,\n            seed=None, ):\n        self.sr = sr\n        self.keep_length = keep_length\n        self.state = numpy.random.RandomState(seed)\n\n        try:\n            import soxbindings as sox\n        except ImportError:\n            try:\n                from paddlespeech.s2t.utils import dynamic_pip_install\n                package = \"sox\"\n                dynamic_pip_install.install(package)\n                package = \"soxbindings\"\n                if sys.platform != \"win32\":\n                    dynamic_pip_install.install(package)\n                import soxbindings as sox\n            except Exception:\n                raise RuntimeError(\n                    \"Can not install soxbindings on your system.\")\n        self.sox = sox\n\n        if utt2ratio is not None:\n            self.utt2ratio = {}\n            # Use the scheduled ratio for each utterances\n            self.utt2ratio_file = utt2ratio\n            self.lower = None\n            self.upper = None\n            self.accept_uttid = True\n\n            with open(utt2ratio, \"r\") as f:\n                for line in f:\n                    utt, ratio = line.rstrip().split(None, 1)\n                    ratio = float(ratio)\n                    self.utt2ratio[utt] = ratio\n        else:\n            self.utt2ratio = None\n            # The ratio is given on runtime randomly\n            self.lower = lower\n            self.upper = upper\n\n    def __repr__(self):\n        if self.utt2ratio is None:\n            return f\"\"\"{self.__class__.__name__}(\n                lower={self.lower},\n                upper={self.upper},\n                keep_length={self.keep_length},\n                sample_rate={self.sr})\"\"\"\n\n        else:\n            return f\"\"\"{self.__class__.__name__}(\n                utt2ratio={self.utt2ratio_file},\n                sample_rate={self.sr})\"\"\"\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n\n        x = x.astype(numpy.float32)\n        if self.accept_uttid:\n            ratio = self.utt2ratio[uttid]\n        else:\n            ratio = self.state.uniform(self.lower, self.upper)\n\n        tfm = self.sox.Transformer()\n        tfm.set_globals(multithread=False)\n        tfm.speed(ratio)\n        y = tfm.build_array(input_array=x, sample_rate_in=self.sr)\n\n        if self.keep_length:\n            diff = abs(len(x) - len(y))\n            if len(y) > len(x):\n                # Truncate noise\n                y = y[diff // 2:-((diff + 1) // 2)]\n            elif len(y) < len(x):\n                # Assume the time-axis is the first: (Time, Channel)\n                pad_width = [(diff // 2, (diff + 1) // 2)] + [\n                    (0, 0) for _ in range(y.ndim - 1)\n                ]\n                y = numpy.pad(\n                    y, pad_width=pad_width, constant_values=0, mode=\"constant\")\n\n        if y.ndim == 2 and x.ndim == 1:\n            # (T, C) -> (T)\n            y = y.sequence(1)\n        return y\n\n\nclass BandpassPerturbation():\n    \"\"\"BandpassPerturbation\n\n    Randomly dropout along the frequency axis.\n\n    The original idea comes from the following:\n        \"randomly-selected frequency band was cut off under the constraint of\n         leaving at least 1,000 Hz band within the range of less than 4,000Hz.\"\n        (The Hitachi/JHU CHiME-5 system: Advances in speech recognition for\n         everyday home environments using multiple microphone arrays;\n         http://spandh.dcs.shef.ac.uk/chime_workshop/papers/CHiME_2018_paper_kanda.pdf)\n\n    \"\"\"\n\n    def __init__(self, lower=0.0, upper=0.75, seed=None, axes=(-1, )):\n        self.lower = lower\n        self.upper = upper\n        self.state = numpy.random.RandomState(seed)\n        # x_stft: (Time, Channel, Freq)\n        self.axes = axes\n\n    def __repr__(self):\n        return \"{}(lower={}, upper={})\".format(self.__class__.__name__,\n                                               self.lower, self.upper)\n\n    def __call__(self, x_stft, uttid=None, train=True):\n        if not train:\n            return x_stft\n\n        if x_stft.ndim == 1:\n            raise RuntimeError(\"Input in time-freq domain: \"\n                               \"(Time, Channel, Freq) or (Time, Freq)\")\n\n        ratio = self.state.uniform(self.lower, self.upper)\n        axes = [i if i >= 0 else x_stft.ndim - i for i in self.axes]\n        shape = [s if i in axes else 1 for i, s in enumerate(x_stft.shape)]\n\n        mask = self.state.randn(*shape) > ratio\n        x_stft *= mask\n        return x_stft\n\n\nclass VolumePerturbation():\n    def __init__(self,\n                 lower=-1.6,\n                 upper=1.6,\n                 utt2ratio=None,\n                 dbunit=True,\n                 seed=None):\n        self.dbunit = dbunit\n        self.utt2ratio_file = utt2ratio\n        self.lower = lower\n        self.upper = upper\n        self.state = numpy.random.RandomState(seed)\n\n        if utt2ratio is not None:\n            # Use the scheduled ratio for each utterances\n            self.utt2ratio = {}\n            self.lower = None\n            self.upper = None\n            self.accept_uttid = True\n\n            with open(utt2ratio, \"r\") as f:\n                for line in f:\n                    utt, ratio = line.rstrip().split(None, 1)\n                    ratio = float(ratio)\n                    self.utt2ratio[utt] = ratio\n        else:\n            # The ratio is given on runtime randomly\n            self.utt2ratio = None\n\n    def __repr__(self):\n        if self.utt2ratio is None:\n            return \"{}(lower={}, upper={}, dbunit={})\".format(\n                self.__class__.__name__, self.lower, self.upper, self.dbunit)\n        else:\n            return '{}(\"{}\", dbunit={})'.format(\n                self.__class__.__name__, self.utt2ratio_file, self.dbunit)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n\n        x = x.astype(numpy.float32)\n\n        if self.accept_uttid:\n            ratio = self.utt2ratio[uttid]\n        else:\n            ratio = self.state.uniform(self.lower, self.upper)\n        if self.dbunit:\n            ratio = 10**(ratio / 20)\n        return x * ratio\n\n\nclass NoiseInjection():\n    \"\"\"Add isotropic noise\"\"\"\n\n    def __init__(\n            self,\n            utt2noise=None,\n            lower=-20,\n            upper=-5,\n            utt2ratio=None,\n            filetype=\"list\",\n            dbunit=True,\n            seed=None, ):\n        self.utt2noise_file = utt2noise\n        self.utt2ratio_file = utt2ratio\n        self.filetype = filetype\n        self.dbunit = dbunit\n        self.lower = lower\n        self.upper = upper\n        self.state = numpy.random.RandomState(seed)\n\n        if utt2ratio is not None:\n            # Use the scheduled ratio for each utterances\n            self.utt2ratio = {}\n            with open(utt2noise, \"r\") as f:\n                for line in f:\n                    utt, snr = line.rstrip().split(None, 1)\n                    snr = float(snr)\n                    self.utt2ratio[utt] = snr\n        else:\n            # The ratio is given on runtime randomly\n            self.utt2ratio = None\n\n        if utt2noise is not None:\n            self.utt2noise = {}\n            if filetype == \"list\":\n                with open(utt2noise, \"r\") as f:\n                    for line in f:\n                        utt, filename = line.rstrip().split(None, 1)\n                        signal, rate = soundfile.read(filename, dtype=\"int16\")\n                        # Load all files in memory\n                        self.utt2noise[utt] = (signal, rate)\n\n            elif filetype == \"sound.hdf5\":\n                self.utt2noise = SoundHDF5File(utt2noise, \"r\")\n            else:\n                raise ValueError(filetype)\n        else:\n            self.utt2noise = None\n\n        if utt2noise is not None and utt2ratio is not None:\n            if set(self.utt2ratio) != set(self.utt2noise):\n                raise RuntimeError(\"The uttids mismatch between {} and {}\".\n                                   format(utt2ratio, utt2noise))\n\n    def __repr__(self):\n        if self.utt2ratio is None:\n            return \"{}(lower={}, upper={}, dbunit={})\".format(\n                self.__class__.__name__, self.lower, self.upper, self.dbunit)\n        else:\n            return '{}(\"{}\", dbunit={})'.format(\n                self.__class__.__name__, self.utt2ratio_file, self.dbunit)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        x = x.astype(numpy.float32)\n\n        # 1. Get ratio of noise to signal in sound pressure level\n        if uttid is not None and self.utt2ratio is not None:\n            ratio = self.utt2ratio[uttid]\n        else:\n            ratio = self.state.uniform(self.lower, self.upper)\n\n        if self.dbunit:\n            ratio = 10**(ratio / 20)\n        scale = ratio * numpy.sqrt((x**2).mean())\n\n        # 2. Get noise\n        if self.utt2noise is not None:\n            # Get noise from the external source\n            if uttid is not None:\n                noise, rate = self.utt2noise[uttid]\n            else:\n                # Randomly select the noise source\n                noise = self.state.choice(list(self.utt2noise.values()))\n            # Normalize the level\n            noise /= numpy.sqrt((noise**2).mean())\n\n            # Adjust the noise length\n            diff = abs(len(x) - len(noise))\n            offset = self.state.randint(0, diff)\n            if len(noise) > len(x):\n                # Truncate noise\n                noise = noise[offset:-(diff - offset)]\n            else:\n                noise = numpy.pad(\n                    noise, pad_width=[offset, diff - offset], mode=\"wrap\")\n\n        else:\n            # Generate white noise\n            noise = self.state.normal(0, 1, x.shape)\n\n        # 3. Add noise to signal\n        return x + noise * scale\n\n\nclass RIRConvolve():\n    def __init__(self, utt2rir, filetype=\"list\"):\n        self.utt2rir_file = utt2rir\n        self.filetype = filetype\n\n        self.utt2rir = {}\n        if filetype == \"list\":\n            with open(utt2rir, \"r\") as f:\n                for line in f:\n                    utt, filename = line.rstrip().split(None, 1)\n                    signal, rate = soundfile.read(filename, dtype=\"int16\")\n                    self.utt2rir[utt] = (signal, rate)\n\n        elif filetype == \"sound.hdf5\":\n            self.utt2rir = SoundHDF5File(utt2rir, \"r\")\n        else:\n            raise NotImplementedError(filetype)\n\n    def __repr__(self):\n        return '{}(\"{}\")'.format(self.__class__.__name__, self.utt2rir_file)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n\n        x = x.astype(numpy.float32)\n\n        if x.ndim != 1:\n            # Must be single channel\n            raise RuntimeError(\n                \"Input x must be one dimensional array, but got {}\".format(\n                    x.shape))\n\n        rir, rate = self.utt2rir[uttid]\n        if rir.ndim == 2:\n            # FIXME(kamo): Use chainer.convolution_1d?\n            # return [Time, Channel]\n            return numpy.stack(\n                [scipy.convolve(x, r, mode=\"same\") for r in rir], axis=-1)\n        else:\n            return scipy.convolve(x, rir, mode=\"same\")\n"
  },
  {
    "path": "paddlespeech/audio/transform/spec_augment.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Spec Augment module for preprocessing i.e., data augmentation\"\"\"\nimport random\n\nimport numpy\nfrom PIL import Image\n\nfrom .functional import FuncTrans\n\n\ndef time_warp(x, max_time_warp=80, inplace=False, mode=\"PIL\"):\n    \"\"\"time warp for spec augment\n\n    move random center frame by the random width ~ uniform(-window, window)\n    :param numpy.ndarray x: spectrogram (time, freq)\n    :param int max_time_warp: maximum time frames to warp\n    :param bool inplace: overwrite x with the result\n    :param str mode: \"PIL\" (default, fast, not differentiable) or \"sparse_image_warp\"\n        (slow, differentiable)\n    :returns numpy.ndarray: time warped spectrogram (time, freq)\n    \"\"\"\n    window = max_time_warp\n    if window == 0:\n        return x\n\n    if mode == \"PIL\":\n        t = x.shape[0]\n        if t - window <= window:\n            return x\n        # NOTE: randrange(a, b) emits a, a + 1, ..., b - 1\n        center = random.randrange(window, t - window)\n        warped = random.randrange(center - window, center +\n                                  window) + 1  # 1 ... t - 1\n\n        left = Image.fromarray(x[:center]).resize((x.shape[1], warped),\n                                                  Image.BICUBIC)\n        right = Image.fromarray(x[center:]).resize((x.shape[1], t - warped),\n                                                   Image.BICUBIC)\n        if inplace:\n            x[:warped] = left\n            x[warped:] = right\n            return x\n        return numpy.concatenate((left, right), 0)\n    elif mode == \"sparse_image_warp\":\n        import paddle\n\n        from espnet.utils import spec_augment\n\n        # TODO(karita): make this differentiable again\n        return spec_augment.time_warp(paddle.to_tensor(x), window).numpy()\n    else:\n        raise NotImplementedError(\"unknown resize mode: \" + mode +\n                                  \", choose one from (PIL, sparse_image_warp).\")\n\n\nclass TimeWarp(FuncTrans):\n    _func = time_warp\n    __doc__ = time_warp.__doc__\n\n    def __call__(self, x, train):\n        if not train:\n            return x\n        return super().__call__(x)\n\n\ndef freq_mask(x, F=30, n_mask=2, replace_with_zero=True, inplace=False):\n    \"\"\"freq mask for spec agument\n\n    :param numpy.ndarray x: (time, freq)\n    :param int n_mask: the number of masks\n    :param bool inplace: overwrite\n    :param bool replace_with_zero: pad zero on mask if true else use mean\n    \"\"\"\n    if inplace:\n        cloned = x\n    else:\n        cloned = x.copy()\n\n    num_mel_channels = cloned.shape[1]\n    fs = numpy.random.randint(0, F, size=(n_mask, 2))\n\n    for f, mask_end in fs:\n        f_zero = random.randrange(0, num_mel_channels - f)\n        mask_end += f_zero\n\n        # avoids randrange error if values are equal and range is empty\n        if f_zero == f_zero + f:\n            continue\n\n        if replace_with_zero:\n            cloned[:, f_zero:mask_end] = 0\n        else:\n            cloned[:, f_zero:mask_end] = cloned.mean()\n    return cloned\n\n\nclass FreqMask(FuncTrans):\n    _func = freq_mask\n    __doc__ = freq_mask.__doc__\n\n    def __call__(self, x, train):\n        if not train:\n            return x\n        return super().__call__(x)\n\n\ndef time_mask(spec, T=40, n_mask=2, replace_with_zero=True, inplace=False):\n    \"\"\"freq mask for spec agument\n\n    :param numpy.ndarray spec: (time, freq)\n    :param int n_mask: the number of masks\n    :param bool inplace: overwrite\n    :param bool replace_with_zero: pad zero on mask if true else use mean\n    \"\"\"\n    if inplace:\n        cloned = spec\n    else:\n        cloned = spec.copy()\n    len_spectro = cloned.shape[0]\n    ts = numpy.random.randint(0, T, size=(n_mask, 2))\n    for t, mask_end in ts:\n        # avoid randint range error\n        if len_spectro - t <= 0:\n            continue\n        t_zero = random.randrange(0, len_spectro - t)\n\n        # avoids randrange error if values are equal and range is empty\n        if t_zero == t_zero + t:\n            continue\n\n        mask_end += t_zero\n        if replace_with_zero:\n            cloned[t_zero:mask_end] = 0\n        else:\n            cloned[t_zero:mask_end] = cloned.mean()\n    return cloned\n\n\nclass TimeMask(FuncTrans):\n    _func = time_mask\n    __doc__ = time_mask.__doc__\n\n    def __call__(self, x, train):\n        if not train:\n            return x\n        return super().__call__(x)\n\n\ndef spec_augment(\n        x,\n        resize_mode=\"PIL\",\n        max_time_warp=80,\n        max_freq_width=27,\n        n_freq_mask=2,\n        max_time_width=100,\n        n_time_mask=2,\n        inplace=True,\n        replace_with_zero=True, ):\n    \"\"\"spec agument\n\n    apply random time warping and time/freq masking\n    default setting is based on LD (Librispeech double) in Table 2\n        https://arxiv.org/pdf/1904.08779.pdf\n\n    :param numpy.ndarray x: (time, freq)\n    :param str resize_mode: \"PIL\" (fast, nondifferentiable) or \"sparse_image_warp\"\n        (slow, differentiable)\n    :param int max_time_warp: maximum frames to warp the center frame in spectrogram (W)\n    :param int freq_mask_width: maximum width of the random freq mask (F)\n    :param int n_freq_mask: the number of the random freq mask (m_F)\n    :param int time_mask_width: maximum width of the random time mask (T)\n    :param int n_time_mask: the number of the random time mask (m_T)\n    :param bool inplace: overwrite intermediate array\n    :param bool replace_with_zero: pad zero on mask if true else use mean\n    \"\"\"\n    assert isinstance(x, numpy.ndarray)\n    assert x.ndim == 2\n    x = time_warp(x, max_time_warp, inplace=inplace, mode=resize_mode)\n    x = freq_mask(\n        x,\n        max_freq_width,\n        n_freq_mask,\n        inplace=inplace,\n        replace_with_zero=replace_with_zero, )\n    x = time_mask(\n        x,\n        max_time_width,\n        n_time_mask,\n        inplace=inplace,\n        replace_with_zero=replace_with_zero, )\n    return x\n\n\nclass SpecAugment(FuncTrans):\n    _func = spec_augment\n    __doc__ = spec_augment.__doc__\n\n    def __call__(self, x, train):\n        if not train:\n            return x\n        return super().__call__(x)\n"
  },
  {
    "path": "paddlespeech/audio/transform/spectrogram.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport librosa\nimport numpy as np\nimport paddle\nfrom python_speech_features import logfbank\n\nfrom paddlespeech.audio.compliance import kaldi\n\n\ndef stft(x,\n         n_fft,\n         n_shift,\n         win_length=None,\n         window=\"hann\",\n         center=True,\n         pad_mode=\"reflect\"):\n    # x: [Time, Channel]\n    if x.ndim == 1:\n        single_channel = True\n        # x: [Time] -> [Time, Channel]\n        x = x[:, None]\n    else:\n        single_channel = False\n    x = x.astype(np.float32)\n\n    # FIXME(kamo): librosa.stft can't use multi-channel?\n    # x: [Time, Channel, Freq]\n    x = np.stack(\n        [\n            librosa.stft(\n                y=x[:, ch],\n                n_fft=n_fft,\n                hop_length=n_shift,\n                win_length=win_length,\n                window=window,\n                center=center,\n                pad_mode=pad_mode, ).T for ch in range(x.shape[1])\n        ],\n        axis=1, )\n\n    if single_channel:\n        # x: [Time, Channel, Freq] -> [Time, Freq]\n        x = x[:, 0]\n    return x\n\n\ndef istft(x, n_shift, win_length=None, window=\"hann\", center=True):\n    # x: [Time, Channel, Freq]\n    if x.ndim == 2:\n        single_channel = True\n        # x: [Time, Freq] -> [Time, Channel, Freq]\n        x = x[:, None, :]\n    else:\n        single_channel = False\n\n    # x: [Time, Channel]\n    x = np.stack(\n        [\n            librosa.istft(\n                stft_matrix=x[:, ch].T,  # [Time, Freq] -> [Freq, Time]\n                hop_length=n_shift,\n                win_length=win_length,\n                window=window,\n                center=center, ) for ch in range(x.shape[1])\n        ],\n        axis=1, )\n\n    if single_channel:\n        # x: [Time, Channel] -> [Time]\n        x = x[:, 0]\n    return x\n\n\ndef stft2logmelspectrogram(x_stft,\n                           fs,\n                           n_mels,\n                           n_fft,\n                           fmin=None,\n                           fmax=None,\n                           eps=1e-10):\n    # x_stft: (Time, Channel, Freq) or (Time, Freq)\n    fmin = 0 if fmin is None else fmin\n    fmax = fs / 2 if fmax is None else fmax\n\n    # spc: (Time, Channel, Freq) or (Time, Freq)\n    spc = np.abs(x_stft)\n    # mel_basis: (Mel_freq, Freq)\n    mel_basis = librosa.filters.mel(\n        sr=fs, n_fft=n_fft, n_mels=n_mels, fmin=fmin, fmax=fmax)\n    # lmspc: (Time, Channel, Mel_freq) or (Time, Mel_freq)\n    lmspc = np.log10(np.maximum(eps, np.dot(spc, mel_basis.T)))\n\n    return lmspc\n\n\ndef spectrogram(x, n_fft, n_shift, win_length=None, window=\"hann\"):\n    # x: (Time, Channel) -> spc: (Time, Channel, Freq)\n    spc = np.abs(stft(x, n_fft, n_shift, win_length, window=window))\n    return spc\n\n\ndef logmelspectrogram(\n        x,\n        fs,\n        n_mels,\n        n_fft,\n        n_shift,\n        win_length=None,\n        window=\"hann\",\n        fmin=None,\n        fmax=None,\n        eps=1e-10,\n        pad_mode=\"reflect\", ):\n    # stft: (Time, Channel, Freq) or (Time, Freq)\n    x_stft = stft(\n        x,\n        n_fft=n_fft,\n        n_shift=n_shift,\n        win_length=win_length,\n        window=window,\n        pad_mode=pad_mode, )\n\n    return stft2logmelspectrogram(\n        x_stft,\n        fs=fs,\n        n_mels=n_mels,\n        n_fft=n_fft,\n        fmin=fmin,\n        fmax=fmax,\n        eps=eps)\n\n\nclass Spectrogram():\n    def __init__(self, n_fft, n_shift, win_length=None, window=\"hann\"):\n        self.n_fft = n_fft\n        self.n_shift = n_shift\n        self.win_length = win_length\n        self.window = window\n\n    def __repr__(self):\n        return (\"{name}(n_fft={n_fft}, n_shift={n_shift}, \"\n                \"win_length={win_length}, window={window})\".format(\n                    name=self.__class__.__name__,\n                    n_fft=self.n_fft,\n                    n_shift=self.n_shift,\n                    win_length=self.win_length,\n                    window=self.window, ))\n\n    def __call__(self, x):\n        return spectrogram(\n            x,\n            n_fft=self.n_fft,\n            n_shift=self.n_shift,\n            win_length=self.win_length,\n            window=self.window, )\n\n\nclass LogMelSpectrogram():\n    def __init__(\n            self,\n            fs,\n            n_mels,\n            n_fft,\n            n_shift,\n            win_length=None,\n            window=\"hann\",\n            fmin=None,\n            fmax=None,\n            eps=1e-10, ):\n        self.fs = fs\n        self.n_mels = n_mels\n        self.n_fft = n_fft\n        self.n_shift = n_shift\n        self.win_length = win_length\n        self.window = window\n        self.fmin = fmin\n        self.fmax = fmax\n        self.eps = eps\n\n    def __repr__(self):\n        return (\"{name}(fs={fs}, n_mels={n_mels}, n_fft={n_fft}, \"\n                \"n_shift={n_shift}, win_length={win_length}, window={window}, \"\n                \"fmin={fmin}, fmax={fmax}, eps={eps}))\".format(\n                    name=self.__class__.__name__,\n                    fs=self.fs,\n                    n_mels=self.n_mels,\n                    n_fft=self.n_fft,\n                    n_shift=self.n_shift,\n                    win_length=self.win_length,\n                    window=self.window,\n                    fmin=self.fmin,\n                    fmax=self.fmax,\n                    eps=self.eps, ))\n\n    def __call__(self, x):\n        return logmelspectrogram(\n            x,\n            fs=self.fs,\n            n_mels=self.n_mels,\n            n_fft=self.n_fft,\n            n_shift=self.n_shift,\n            win_length=self.win_length,\n            window=self.window, )\n\n\nclass Stft2LogMelSpectrogram():\n    def __init__(self, fs, n_mels, n_fft, fmin=None, fmax=None, eps=1e-10):\n        self.fs = fs\n        self.n_mels = n_mels\n        self.n_fft = n_fft\n        self.fmin = fmin\n        self.fmax = fmax\n        self.eps = eps\n\n    def __repr__(self):\n        return (\"{name}(fs={fs}, n_mels={n_mels}, n_fft={n_fft}, \"\n                \"fmin={fmin}, fmax={fmax}, eps={eps}))\".format(\n                    name=self.__class__.__name__,\n                    fs=self.fs,\n                    n_mels=self.n_mels,\n                    n_fft=self.n_fft,\n                    fmin=self.fmin,\n                    fmax=self.fmax,\n                    eps=self.eps, ))\n\n    def __call__(self, x):\n        return stft2logmelspectrogram(\n            x,\n            fs=self.fs,\n            n_mels=self.n_mels,\n            n_fft=self.n_fft,\n            fmin=self.fmin,\n            fmax=self.fmax, )\n\n\nclass Stft():\n    def __init__(\n            self,\n            n_fft,\n            n_shift,\n            win_length=None,\n            window=\"hann\",\n            center=True,\n            pad_mode=\"reflect\", ):\n        self.n_fft = n_fft\n        self.n_shift = n_shift\n        self.win_length = win_length\n        self.window = window\n        self.center = center\n        self.pad_mode = pad_mode\n\n    def __repr__(self):\n        return (\"{name}(n_fft={n_fft}, n_shift={n_shift}, \"\n                \"win_length={win_length}, window={window},\"\n                \"center={center}, pad_mode={pad_mode})\".format(\n                    name=self.__class__.__name__,\n                    n_fft=self.n_fft,\n                    n_shift=self.n_shift,\n                    win_length=self.win_length,\n                    window=self.window,\n                    center=self.center,\n                    pad_mode=self.pad_mode, ))\n\n    def __call__(self, x):\n        return stft(\n            x,\n            self.n_fft,\n            self.n_shift,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center,\n            pad_mode=self.pad_mode, )\n\n\nclass IStft():\n    def __init__(self, n_shift, win_length=None, window=\"hann\", center=True):\n        self.n_shift = n_shift\n        self.win_length = win_length\n        self.window = window\n        self.center = center\n\n    def __repr__(self):\n        return (\"{name}(n_shift={n_shift}, \"\n                \"win_length={win_length}, window={window},\"\n                \"center={center})\".format(\n                    name=self.__class__.__name__,\n                    n_shift=self.n_shift,\n                    win_length=self.win_length,\n                    window=self.window,\n                    center=self.center, ))\n\n    def __call__(self, x):\n        return istft(\n            x,\n            self.n_shift,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center, )\n\n\nclass LogMelSpectrogramKaldi():\n    def __init__(\n            self,\n            fs=16000,\n            n_mels=80,\n            n_shift=160,  # unit:sample, 10ms\n            win_length=400,  # unit:sample, 25ms\n            energy_floor=0.0,\n            dither=0.1):\n        \"\"\"\n        The Kaldi implementation of LogMelSpectrogram \n        Args:\n            fs (int): sample rate of the audio\n            n_mels (int): number of mel filter banks\n            n_shift (int): number of points in a frame shift\n            win_length (int): number of points in a frame windows\n            energy_floor (float): Floor on energy in Spectrogram computation (absolute)\n            dither (float): Dithering constant\n\n        Returns:\n            LogMelSpectrogramKaldi\n        \"\"\"\n\n        self.fs = fs\n        self.n_mels = n_mels\n        num_point_ms = fs / 1000\n        self.n_frame_length = win_length / num_point_ms\n        self.n_frame_shift = n_shift / num_point_ms\n        self.energy_floor = energy_floor\n        self.dither = dither\n\n    def __repr__(self):\n        return (\n            \"{name}(fs={fs}, n_mels={n_mels}, \"\n            \"n_frame_shift={n_frame_shift}, n_frame_length={n_frame_length}, \"\n            \"dither={dither}))\".format(\n                name=self.__class__.__name__,\n                fs=self.fs,\n                n_mels=self.n_mels,\n                n_frame_shift=self.n_frame_shift,\n                n_frame_length=self.n_frame_length,\n                dither=self.dither, ))\n\n    def __call__(self, x, train):\n        \"\"\"\n        Args:\n            x (np.ndarray): shape (Ti,)\n            train (bool): True, train mode.\n\n        Raises:\n            ValueError: not support (Ti, C)\n\n        Returns:\n            np.ndarray: (T, D)\n        \"\"\"\n        dither = self.dither if train else 0.0\n        if x.ndim != 1:\n            raise ValueError(\"Not support x: [Time, Channel]\")\n        waveform = paddle.to_tensor(np.expand_dims(x, 0), dtype=paddle.float32)\n        mat = kaldi.fbank(\n            waveform,\n            n_mels=self.n_mels,\n            frame_length=self.n_frame_length,\n            frame_shift=self.n_frame_shift,\n            dither=dither,\n            energy_floor=self.energy_floor,\n            sr=self.fs)\n        mat = np.squeeze(mat.numpy())\n        return mat\n\n\nclass WavProcess():\n    def __init__(self):\n        \"\"\"\n        Args:\n            dither (float): Dithering constant\n\n        Returns:\n        \"\"\"\n\n    def __call__(self, x):\n        \"\"\"\n        Args:\n            x (np.ndarray): shape (Ti,)\n            train (bool): True, train mode.\n\n        Raises:\n            ValueError: not support (Ti, C)\n\n        Returns:\n            np.ndarray: (T, D)\n        \"\"\"\n        if x.ndim != 1:\n            raise ValueError(\"Not support x: [Time, Channel]\")\n        waveform = x.astype(\"float32\") / 32768.0\n        waveform = np.expand_dims(waveform, -1)\n        return waveform\n\n\nclass LogMelSpectrogramKaldi_decay():\n    def __init__(\n            self,\n            fs=16000,\n            n_mels=80,\n            n_fft=512,  # fft point\n            n_shift=160,  # unit:sample, 10ms\n            win_length=400,  # unit:sample, 25ms\n            window=\"povey\",\n            fmin=20,\n            fmax=None,\n            eps=1e-10,\n            dither=1.0):\n        self.fs = fs\n        self.n_mels = n_mels\n        self.n_fft = n_fft\n        if n_shift > win_length:\n            raise ValueError(\"Stride size must not be greater than \"\n                             \"window size.\")\n        self.n_shift = n_shift / fs  # unit: ms\n        self.win_length = win_length / fs  # unit: ms\n\n        self.window = window\n        self.fmin = fmin\n        if fmax is None:\n            fmax_ = fmax if fmax else self.fs / 2\n        elif fmax > int(self.fs / 2):\n            raise ValueError(\"fmax must not be greater than half of \"\n                             \"sample rate.\")\n        self.fmax = fmax_\n\n        self.eps = eps\n        self.remove_dc_offset = True\n        self.preemph = 0.97\n        self.dither = dither  # only work in train mode\n\n    def __repr__(self):\n        return (\n            \"{name}(fs={fs}, n_mels={n_mels}, n_fft={n_fft}, \"\n            \"n_shift={n_shift}, win_length={win_length}, preemph={preemph}, window={window}, \"\n            \"fmin={fmin}, fmax={fmax}, eps={eps}, dither={dither}))\".format(\n                name=self.__class__.__name__,\n                fs=self.fs,\n                n_mels=self.n_mels,\n                n_fft=self.n_fft,\n                n_shift=self.n_shift,\n                preemph=self.preemph,\n                win_length=self.win_length,\n                window=self.window,\n                fmin=self.fmin,\n                fmax=self.fmax,\n                eps=self.eps,\n                dither=self.dither, ))\n\n    def __call__(self, x, train):\n        \"\"\"\n\n        Args:\n            x (np.ndarray): shape (Ti,)\n            train (bool): True, train mode.\n\n        Raises:\n            ValueError: not support (Ti, C)\n\n        Returns:\n            np.ndarray: (T, D)\n        \"\"\"\n        dither = self.dither if train else 0.0\n        if x.ndim != 1:\n            raise ValueError(\"Not support x: [Time, Channel]\")\n\n        if x.dtype in np.sctypes['float']:\n            # PCM32 -> PCM16\n            bits = np.iinfo(np.int16).bits\n            x = x * 2**(bits - 1)\n\n        # logfbank need PCM16 input\n        y = logfbank(\n            signal=x,\n            samplerate=self.fs,\n            winlen=self.win_length,  # unit ms\n            winstep=self.n_shift,  # unit ms\n            nfilt=self.n_mels,\n            nfft=self.n_fft,\n            lowfreq=self.fmin,\n            highfreq=self.fmax,\n            dither=dither,\n            remove_dc_offset=self.remove_dc_offset,\n            preemph=self.preemph,\n            wintype=self.window)\n        return y\n"
  },
  {
    "path": "paddlespeech/audio/transform/transform_interface.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\n\nclass TransformInterface:\n    \"\"\"Transform Interface\"\"\"\n\n    def __call__(self, x):\n        raise NotImplementedError(\"__call__ method is not implemented\")\n\n    @classmethod\n    def add_arguments(cls, parser):\n        return parser\n\n    def __repr__(self):\n        return self.__class__.__name__ + \"()\"\n\n\nclass Identity(TransformInterface):\n    \"\"\"Identity Function\"\"\"\n\n    def __call__(self, x):\n        return x\n"
  },
  {
    "path": "paddlespeech/audio/transform/transformation.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Transformation module.\"\"\"\nimport copy\nimport io\nimport logging\nfrom collections import OrderedDict\nfrom collections.abc import Sequence\nfrom inspect import signature\n\nimport yaml\n\nfrom ..utils.dynamic_import import dynamic_import\n\nimport_alias = dict(\n    identity=\"paddlespeech.audio.transform.transform_interface:Identity\",\n    time_warp=\"paddlespeech.audio.transform.spec_augment:TimeWarp\",\n    time_mask=\"paddlespeech.audio.transform.spec_augment:TimeMask\",\n    freq_mask=\"paddlespeech.audio.transform.spec_augment:FreqMask\",\n    spec_augment=\"paddlespeech.audio.transform.spec_augment:SpecAugment\",\n    speed_perturbation=\"paddlespeech.audio.transform.perturb:SpeedPerturbation\",\n    speed_perturbation_sox=\"paddlespeech.audio.transform.perturb:SpeedPerturbationSox\",\n    volume_perturbation=\"paddlespeech.audio.transform.perturb:VolumePerturbation\",\n    noise_injection=\"paddlespeech.audio.transform.perturb:NoiseInjection\",\n    bandpass_perturbation=\"paddlespeech.audio.transform.perturb:BandpassPerturbation\",\n    rir_convolve=\"paddlespeech.audio.transform.perturb:RIRConvolve\",\n    delta=\"paddlespeech.audio.transform.add_deltas:AddDeltas\",\n    cmvn=\"paddlespeech.audio.transform.cmvn:CMVN\",\n    utterance_cmvn=\"paddlespeech.audio.transform.cmvn:UtteranceCMVN\",\n    fbank=\"paddlespeech.audio.transform.spectrogram:LogMelSpectrogram\",\n    spectrogram=\"paddlespeech.audio.transform.spectrogram:Spectrogram\",\n    wav_process=\"paddlespeech.audio.transform.spectrogram:WavProcess\",\n    stft=\"paddlespeech.audio.transform.spectrogram:Stft\",\n    istft=\"paddlespeech.audio.transform.spectrogram:IStft\",\n    stft2fbank=\"paddlespeech.audio.transform.spectrogram:Stft2LogMelSpectrogram\",\n    wpe=\"paddlespeech.audio.transform.wpe:WPE\",\n    channel_selector=\"paddlespeech.audio.transform.channel_selector:ChannelSelector\",\n    fbank_kaldi=\"paddlespeech.audio.transform.spectrogram:LogMelSpectrogramKaldi\",\n    cmvn_json=\"paddlespeech.audio.transform.cmvn:GlobalCMVN\")\n\n\nclass Transformation():\n    \"\"\"Apply some functions to the mini-batch\n\n    Examples:\n        >>> kwargs = {\"process\": [{\"type\": \"fbank\",\n        ...                        \"n_mels\": 80,\n        ...                        \"fs\": 16000},\n        ...                       {\"type\": \"cmvn\",\n        ...                        \"stats\": \"data/train/cmvn.ark\",\n        ...                        \"norm_vars\": True},\n        ...                       {\"type\": \"delta\", \"window\": 2, \"order\": 2}]}\n        >>> transform = Transformation(kwargs)\n        >>> bs = 10\n        >>> xs = [np.random.randn(100, 80).astype(np.float32)\n        ...       for _ in range(bs)]\n        >>> xs = transform(xs)\n    \"\"\"\n\n    def __init__(self, conffile=None):\n        if conffile is not None:\n            if isinstance(conffile, dict):\n                self.conf = copy.deepcopy(conffile)\n            else:\n                with io.open(conffile, encoding=\"utf-8\") as f:\n                    self.conf = yaml.safe_load(f)\n                    assert isinstance(self.conf, dict), type(self.conf)\n        else:\n            self.conf = {\"mode\": \"sequential\", \"process\": []}\n\n        self.functions = OrderedDict()\n        if self.conf.get(\"mode\", \"sequential\") == \"sequential\":\n            for idx, process in enumerate(self.conf[\"process\"]):\n                assert isinstance(process, dict), type(process)\n                opts = dict(process)\n                process_type = opts.pop(\"type\")\n                class_obj = dynamic_import(process_type, import_alias)\n                # TODO(karita): assert issubclass(class_obj, TransformInterface)\n                try:\n                    self.functions[idx] = class_obj(**opts)\n                except TypeError:\n                    try:\n                        signa = signature(class_obj)\n                    except ValueError:\n                        # Some function, e.g. built-in function, are failed\n                        pass\n                    else:\n                        logging.error(\"Expected signature: {}({})\".format(\n                            class_obj.__name__, signa))\n                    raise\n        else:\n            raise NotImplementedError(\n                \"Not supporting mode={}\".format(self.conf[\"mode\"]))\n\n    def __repr__(self):\n        rep = \"\\n\" + \"\\n\".join(\"    {}: {}\".format(k, v)\n                               for k, v in self.functions.items())\n        return \"{}({})\".format(self.__class__.__name__, rep)\n\n    def __call__(self, xs, uttid_list=None, **kwargs):\n        \"\"\"Return new mini-batch\n\n        :param Union[Sequence[np.ndarray], np.ndarray] xs:\n        :param Union[Sequence[str], str] uttid_list:\n        :return: batch:\n        :rtype: List[np.ndarray]\n        \"\"\"\n        if not isinstance(xs, Sequence):\n            is_batch = False\n            xs = [xs]\n        else:\n            is_batch = True\n\n        if isinstance(uttid_list, str):\n            uttid_list = [uttid_list for _ in range(len(xs))]\n\n        if self.conf.get(\"mode\", \"sequential\") == \"sequential\":\n            for idx in range(len(self.conf[\"process\"])):\n                func = self.functions[idx]\n                # TODO(karita): use TrainingTrans and UttTrans to check __call__ args\n                # Derive only the args which the func has\n                try:\n                    param = signature(func).parameters\n                except ValueError:\n                    # Some function, e.g. built-in function, are failed\n                    param = {}\n                _kwargs = {k: v for k, v in kwargs.items() if k in param}\n                try:\n                    if uttid_list is not None and \"uttid\" in param:\n                        xs = [\n                            func(x, u, **_kwargs)\n                            for x, u in zip(xs, uttid_list)\n                        ]\n                    else:\n                        xs = [func(x, **_kwargs) for x in xs]\n                except Exception:\n                    logging.fatal(\"Catch a exception from {}th func: {}\".format(\n                        idx, func))\n                    raise\n        else:\n            raise NotImplementedError(\n                \"Not supporting mode={}\".format(self.conf[\"mode\"]))\n\n        if is_batch:\n            return xs\n        else:\n            return xs[0]\n"
  },
  {
    "path": "paddlespeech/audio/transform/wpe.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom nara_wpe.wpe import wpe\n\n\nclass WPE(object):\n    def __init__(self,\n                 taps=10,\n                 delay=3,\n                 iterations=3,\n                 psd_context=0,\n                 statistics_mode=\"full\"):\n        self.taps = taps\n        self.delay = delay\n        self.iterations = iterations\n        self.psd_context = psd_context\n        self.statistics_mode = statistics_mode\n\n    def __repr__(self):\n        return (\"{name}(taps={taps}, delay={delay}\"\n                \"iterations={iterations}, psd_context={psd_context}, \"\n                \"statistics_mode={statistics_mode})\".format(\n                    name=self.__class__.__name__,\n                    taps=self.taps,\n                    delay=self.delay,\n                    iterations=self.iterations,\n                    psd_context=self.psd_context,\n                    statistics_mode=self.statistics_mode, ))\n\n    def __call__(self, xs):\n        \"\"\"Return enhanced\n\n        :param np.ndarray xs: (Time, Channel, Frequency)\n        :return: enhanced_xs\n        :rtype: np.ndarray\n\n        \"\"\"\n        # nara_wpe.wpe: (F, C, T)\n        xs = wpe(\n            xs.transpose((2, 1, 0)),\n            taps=self.taps,\n            delay=self.delay,\n            iterations=self.iterations,\n            psd_context=self.psd_context,\n            statistics_mode=self.statistics_mode, )\n        return xs.transpose(2, 1, 0)\n"
  },
  {
    "path": "paddlespeech/audio/utils/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom ...utils.env import DATA_HOME\nfrom ...utils.env import MODEL_HOME\nfrom .download import decompress\nfrom .download import download_and_decompress\nfrom .download import load_state_dict_from_url\nfrom .error import ParameterError\nfrom .log import Logger\nfrom .log import logger\nfrom .numeric import depth_convert\nfrom .numeric import pcm16to32\nfrom .time import seconds_to_hms\nfrom .time import Timer\n"
  },
  {
    "path": "paddlespeech/audio/utils/check_kwargs.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport inspect\n\n\ndef check_kwargs(func, kwargs, name=None):\n    \"\"\"check kwargs are valid for func\n\n    If kwargs are invalid, raise TypeError as same as python default\n    :param function func: function to be validated\n    :param dict kwargs: keyword arguments for func\n    :param str name: name used in TypeError (default is func name)\n    \"\"\"\n    try:\n        params = inspect.signature(func).parameters\n    except ValueError:\n        return\n    if name is None:\n        name = func.__name__\n    for k in kwargs.keys():\n        if k not in params:\n            raise TypeError(\n                f\"{name}() got an unexpected keyword argument '{k}'\")\n"
  },
  {
    "path": "paddlespeech/audio/utils/download.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import Dict\nfrom typing import List\n\nfrom paddle.framework import load as load_state_dict\nfrom paddle.utils import download\n\nfrom .log import logger\n\ndownload.logger = logger\n\n__all__ = [\n    'decompress',\n    'download_and_decompress',\n    'load_state_dict_from_url',\n]\n\n\ndef decompress(file: str):\n    \"\"\"\n    Extracts all files from a compressed file.\n    \"\"\"\n    assert os.path.isfile(file), \"File: {} not exists.\".format(file)\n    download._decompress(file)\n\n\ndef download_and_decompress(archives: List[Dict[str, str]],\n                            path: str,\n                            decompress: bool=True):\n    \"\"\"\n    Download archieves and decompress to specific path.\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    for archive in archives:\n        assert 'url' in archive and 'md5' in archive, \\\n            'Dictionary keys of \"url\" and \"md5\" are required in the archive, but got: {list(archieve.keys())}'\n        download.get_path_from_url(\n            archive['url'], path, archive['md5'], decompress=decompress)\n\n\ndef load_state_dict_from_url(url: str, path: str, md5: str=None):\n    \"\"\"\n    Download and load a state dict from url\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    download.get_path_from_url(url, path, md5)\n    return load_state_dict(os.path.join(path, os.path.basename(url)))\n"
  },
  {
    "path": "paddlespeech/audio/utils/dynamic_import.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport importlib\n\n__all__ = [\"dynamic_import\"]\n\n\ndef dynamic_import(import_path, alias=dict()):\n    \"\"\"dynamic import module and class\n\n    :param str import_path: syntax 'module_name:class_name'\n        e.g., 'paddlespeech.s2t.models.u2:U2Model'\n    :param dict alias: shortcut for registered class\n    :return: imported class\n    \"\"\"\n    if import_path not in alias and \":\" not in import_path:\n        raise ValueError(\n            \"import_path should be one of {} or \"\n            'include \":\", e.g. \"paddlespeech.s2t.models.u2:U2Model\" : '\n            \"{}\".format(set(alias), import_path))\n    if \":\" not in import_path:\n        import_path = alias[import_path]\n\n    module_name, objname = import_path.split(\":\")\n    m = importlib.import_module(module_name)\n    return getattr(m, objname)\n"
  },
  {
    "path": "paddlespeech/audio/utils/error.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = ['ParameterError']\n\n\nclass ParameterError(Exception):\n    \"\"\"Exception class for Parameter checking\"\"\"\n    pass\n"
  },
  {
    "path": "paddlespeech/audio/utils/log.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport contextlib\nimport functools\nimport logging\nimport threading\nimport time\n\nimport colorlog\n\n__all__ = [\n    'Logger',\n    'logger',\n]\n\nlog_config = {\n    'DEBUG': {\n        'level': 10,\n        'color': 'purple'\n    },\n    'INFO': {\n        'level': 20,\n        'color': 'green'\n    },\n    'TRAIN': {\n        'level': 21,\n        'color': 'cyan'\n    },\n    'EVAL': {\n        'level': 22,\n        'color': 'blue'\n    },\n    'WARNING': {\n        'level': 30,\n        'color': 'yellow'\n    },\n    'ERROR': {\n        'level': 40,\n        'color': 'red'\n    },\n    'CRITICAL': {\n        'level': 50,\n        'color': 'bold_red'\n    }\n}\n\n\nclass Logger(object):\n    '''\n    Deafult logger in PaddleAudio\n    Args:\n        name(str) : Logger name, default is 'PaddleAudio'\n    '''\n\n    def __init__(self, name: str=None):\n        name = 'PaddleAudio' if not name else name\n        self.name = name\n        self.logger = logging.getLogger(name)\n\n        for key, conf in log_config.items():\n            logging.addLevelName(conf['level'], key)\n            self.__dict__[key] = functools.partial(self.__call__, conf['level'])\n            self.__dict__[key.lower()] = functools.partial(self.__call__,\n                                                           conf['level'])\n\n        self.format = colorlog.ColoredFormatter(\n            '%(log_color)s[%(asctime)-15s] [%(levelname)8s]%(reset)s - %(message)s',\n            log_colors={key: conf['color']\n                        for key, conf in log_config.items()})\n\n        self.handler = logging.StreamHandler()\n        self.handler.setFormatter(self.format)\n\n        self.logger.addHandler(self.handler)\n        self.logLevel = 'DEBUG'\n        self.logger.setLevel(logging.DEBUG)\n        self.logger.propagate = False\n        self._is_enable = True\n\n    def disable(self):\n        self._is_enable = False\n\n    def enable(self):\n        self._is_enable = True\n\n    @property\n    def is_enable(self) -> bool:\n        return self._is_enable\n\n    def __call__(self, log_level: str, msg: str):\n        if not self.is_enable:\n            return\n\n        self.logger.log(log_level, self.name + \" | \" + msg)\n\n    @contextlib.contextmanager\n    def use_terminator(self, terminator: str):\n        old_terminator = self.handler.terminator\n        self.handler.terminator = terminator\n        yield\n        self.handler.terminator = old_terminator\n\n    @contextlib.contextmanager\n    def processing(self, msg: str, interval: float=0.1):\n        '''\n        Continuously print a progress bar with rotating special effects.\n        Args:\n            msg(str): Message to be printed.\n            interval(float): Rotation interval. Default to 0.1.\n        '''\n        end = False\n\n        def _printer():\n            index = 0\n            flags = ['\\\\', '|', '/', '-']\n            while not end:\n                flag = flags[index % len(flags)]\n                with self.use_terminator('\\r'):\n                    self.info('{}: {}'.format(msg, flag))\n                time.sleep(interval)\n                index += 1\n\n        t = threading.Thread(target=_printer)\n        t.start()\n        yield\n        end = True\n\n\nlogger = Logger()\n"
  },
  {
    "path": "paddlespeech/audio/utils/numeric.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Union\n\nimport numpy as np\n\n__all__ = [\"pcm16to32\", \"depth_convert\"]\n\n\ndef pcm16to32(audio: np.ndarray) -> np.ndarray:\n    \"\"\"pcm int16 to float32\n\n    Args:\n        audio (np.ndarray): Waveform with dtype of int16.\n\n    Returns:\n        np.ndarray: Waveform with dtype of float32.\n    \"\"\"\n    if audio.dtype == np.int16:\n        audio = audio.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        audio = audio / (2**(bits - 1))\n    return audio\n\n\ndef _safe_cast(y: np.ndarray, dtype: Union[type, str]) -> np.ndarray:\n    \"\"\"Data type casting in a safe way, i.e., prevent overflow or underflow.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        dtype (Union[type, str]): Data type of waveform.\n\n    Returns:\n        np.ndarray: `y` after safe casting.\n    \"\"\"\n    if 'float' in str(y.dtype):\n        return np.clip(y, np.finfo(dtype).min,\n                       np.finfo(dtype).max).astype(dtype)\n    else:\n        return np.clip(y, np.iinfo(dtype).min,\n                       np.iinfo(dtype).max).astype(dtype)\n\n\ndef depth_convert(y: np.ndarray, dtype: Union[type, str]) -> np.ndarray:\n    \"\"\"Convert audio array to target dtype safely. \n    This function convert audio waveform to a target dtype, with addition steps of\n    preventing overflow/underflow and preserving audio range.\n\n    Args:\n        y (np.ndarray): Input waveform array in 1D or 2D.\n        dtype (Union[type, str]): Data type of waveform.\n\n    Returns:\n        np.ndarray: `y` after safe casting.\n    \"\"\"\n\n    SUPPORT_DTYPE = ['int16', 'int8', 'float32', 'float64']\n    if y.dtype not in SUPPORT_DTYPE:\n        raise ParameterError(\n            'Unsupported audio dtype, '\n            f'y.dtype is {y.dtype}, supported dtypes are {SUPPORT_DTYPE}')\n\n    if dtype not in SUPPORT_DTYPE:\n        raise ParameterError(\n            'Unsupported audio dtype, '\n            f'target dtype  is {dtype}, supported dtypes are {SUPPORT_DTYPE}')\n\n    if dtype == y.dtype:\n        return y\n\n    if dtype == 'float64' and y.dtype == 'float32':\n        return _safe_cast(y, dtype)\n    if dtype == 'float32' and y.dtype == 'float64':\n        return _safe_cast(y, dtype)\n\n    if dtype == 'int16' or dtype == 'int8':\n        if y.dtype in ['float64', 'float32']:\n            factor = np.iinfo(dtype).max\n            y = np.clip(y * factor, np.iinfo(dtype).min,\n                        np.iinfo(dtype).max).astype(dtype)\n            y = y.astype(dtype)\n        else:\n            if dtype == 'int16' and y.dtype == 'int8':\n                factor = np.iinfo('int16').max / np.iinfo('int8').max - EPS\n                y = y.astype('float32') * factor\n                y = y.astype('int16')\n\n            else:  # dtype == 'int8' and y.dtype=='int16':\n                y = y.astype('int32') * np.iinfo('int8').max / \\\n                    np.iinfo('int16').max\n                y = y.astype('int8')\n\n    if dtype in ['float32', 'float64']:\n        org_dtype = y.dtype\n        y = y.astype(dtype) / np.iinfo(org_dtype).max\n    return y\n"
  },
  {
    "path": "paddlespeech/audio/utils/tensor_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Unility functions for Transformer.\"\"\"\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\n\nfrom .log import Logger\n\n__all__ = [\"pad_sequence\", \"add_sos_eos\", \"th_accuracy\", \"has_tensor\"]\n\nlogger = Logger(__name__)\n\n\ndef has_tensor(val):\n    if isinstance(val, (list, tuple)):\n        for item in val:\n            if has_tensor(item):\n                return True\n    elif isinstance(val, dict):\n        for k, v in val.items():\n            if has_tensor(v):\n                return True\n    else:\n        return paddle.is_tensor(val)\n\n\ndef pad_sequence(sequences: List[paddle.Tensor],\n                 batch_first: bool=False,\n                 padding_value: float=0.0) -> paddle.Tensor:\n    r\"\"\"Pad a list of variable length Tensors with ``padding_value``\n\n    ``pad_sequence`` stacks a list of Tensors along a new dimension,\n    and pads them to equal length. For example, if the input is list of\n    sequences with size ``L x *`` and if batch_first is False, and ``T x B x *``\n    otherwise.\n\n    `B` is batch size. It is equal to the number of elements in ``sequences``.\n    `T` is length of the longest sequence.\n    `L` is length of the sequence.\n    `*` is any number of trailing dimensions, including none.\n\n    Example:\n        >>> from paddle.nn.utils.rnn import pad_sequence\n        >>> a = paddle.ones(25, 300)\n        >>> b = paddle.ones(22, 300)\n        >>> c = paddle.ones(15, 300)\n        >>> pad_sequence([a, b, c]).shape\n        paddle.Tensor([25, 3, 300])\n\n    Note:\n        This function returns a Tensor of size ``T x B x *`` or ``B x T x *``\n        where `T` is the length of the longest sequence. This function assumes\n        trailing dimensions and type of all the Tensors in sequences are same.\n\n    Args:\n        sequences (list[Tensor]): list of variable length sequences.\n        batch_first (bool, optional): output will be in ``B x T x *`` if True, or in\n            ``T x B x *`` otherwise\n        padding_value (float, optional): value for padded elements. Default: 0.\n\n    Returns:\n        Tensor of size ``T x B x *`` if :attr:`batch_first` is ``False``.\n        Tensor of size ``B x T x *`` otherwise\n    \"\"\"\n\n    # assuming trailing dimensions and type of all the Tensors\n    # in sequences are same and fetching those from sequences[0]\n    max_size = paddle.shape(sequences[0])\n    # (TODO Hui Zhang): slice not support `end==start`\n    # trailing_dims = max_size[1:]\n    trailing_dims = tuple(\n        max_size[1:].numpy().tolist()) if sequences[0].ndim >= 2 else ()\n    max_len = max([s.shape[0] for s in sequences])\n    if batch_first:\n        out_dims = (len(sequences), max_len) + trailing_dims\n    else:\n        out_dims = (max_len, len(sequences)) + trailing_dims\n    out_tensor = paddle.full(out_dims, padding_value, sequences[0].dtype)\n    for i, tensor in enumerate(sequences):\n        length = tensor.shape[0]\n        # use index notation to prevent duplicate references to the tensor\n        if batch_first:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # TODO (Hui Zhang): set_value op not support int16\n            # TODO (Hui Zhang): set_varbase 2 rank not support [0,0,...]\n            # out_tensor[i, :length, ...] = tensor\n            if length != 0:\n                out_tensor[i, :length] = tensor\n            else:\n                out_tensor[i, length] = tensor\n        else:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # out_tensor[:length, i, ...] = tensor\n            if length != 0:\n                out_tensor[:length, i] = tensor\n            else:\n                out_tensor[length, i] = tensor\n\n    return out_tensor\n\n\ndef add_sos_eos(ys_pad: paddle.Tensor, sos: int, eos: int,\n                ignore_id: int) -> Tuple[paddle.Tensor, paddle.Tensor]:\n    \"\"\"Add <sos> and <eos> labels.\n    Args:\n        ys_pad (paddle.Tensor): batch of padded target sequences (B, Lmax)\n        sos (int): index of <sos>\n        eos (int): index of <eeos>\n        ignore_id (int): index of padding\n    Returns:\n        ys_in (paddle.Tensor) : (B, Lmax + 1)\n        ys_out (paddle.Tensor) : (B, Lmax + 1)\n    Examples:\n        >>> sos_id = 10\n        >>> eos_id = 11\n        >>> ignore_id = -1\n        >>> ys_pad\n        tensor([[ 1,  2,  3,  4,  5],\n                [ 4,  5,  6, -1, -1],\n                [ 7,  8,  9, -1, -1]], dtype=paddle.int32)\n        >>> ys_in,ys_out=add_sos_eos(ys_pad, sos_id , eos_id, ignore_id)\n        >>> ys_in\n        tensor([[10,  1,  2,  3,  4,  5],\n                [10,  4,  5,  6, 11, 11],\n                [10,  7,  8,  9, 11, 11]])\n        >>> ys_out\n        tensor([[ 1,  2,  3,  4,  5, 11],\n                [ 4,  5,  6, 11, -1, -1],\n                [ 7,  8,  9, 11, -1, -1]])\n    \"\"\"\n    # TODO(Hui Zhang): using comment code,\n    # _sos = paddle.to_tensor(\n    #    [sos], dtype=ys_pad.dtype, stop_gradient=True, place=ys_pad.place)\n    # _eos = paddle.to_tensor(\n    #    [eos], dtype=ys_pad.dtype, stop_gradient=True, place=ys_pad.place)\n    # ys = [y[y != ignore_id] for y in ys_pad]  # parse padded ys\n    # ys_in = [paddle.concat([_sos, y], axis=0) for y in ys]\n    # ys_out = [paddle.concat([y, _eos], axis=0) for y in ys]\n    # return pad_sequence(ys_in, padding_value=eos).transpose([1,0]), pad_sequence(ys_out, padding_value=ignore_id).transpose([1,0])\n\n    B = ys_pad.shape[0]\n    _sos = paddle.full([B, 1], sos, dtype=ys_pad.dtype)\n    _eos = paddle.full([B, 1], eos, dtype=ys_pad.dtype)\n    ys_in = paddle.cat([_sos, ys_pad], dim=1)\n    mask_pad = (ys_in == ignore_id)\n    ys_in = ys_in.masked_fill(mask_pad, eos)\n\n    ys_out = paddle.cat([ys_pad, _eos], dim=1)\n    ys_out = ys_out.masked_fill(mask_pad, eos)\n    mask_eos = (ys_out == ignore_id)\n    ys_out = ys_out.masked_fill(mask_eos, eos)\n    ys_out = ys_out.masked_fill(mask_pad, ignore_id)\n    return ys_in, ys_out\n\n\ndef th_accuracy(pad_outputs: paddle.Tensor,\n                pad_targets: paddle.Tensor,\n                ignore_label: int) -> float:\n    \"\"\"Calculate accuracy.\n    Args:\n        pad_outputs (Tensor): Prediction tensors (B * Lmax, D).\n        pad_targets (LongTensor): Target label tensors (B, Lmax, D).\n        ignore_label (int): Ignore label id.\n    Returns:\n        float: Accuracy value (0.0 - 1.0).\n    \"\"\"\n    pad_pred = pad_outputs.reshape(\n        [pad_targets.shape[0], pad_targets.shape[1],\n         pad_outputs.shape[1]]).argmax(2)\n    mask = pad_targets != ignore_label\n    #TODO(Hui Zhang): sum not support bool type\n    # numerator = paddle.sum(\n    #     pad_pred.masked_select(mask) == pad_targets.masked_select(mask))\n    numerator = (\n        pad_pred.masked_select(mask) == pad_targets.masked_select(mask))\n    numerator = paddle.sum(numerator.type_as(pad_targets))\n    #TODO(Hui Zhang): sum not support bool type\n    # denominator = paddle.sum(mask)\n    denominator = paddle.sum(mask.type_as(pad_targets))\n    return float(numerator) / float(denominator)\n\n\ndef reverse_pad_list(ys_pad: paddle.Tensor,\n                     ys_lens: paddle.Tensor,\n                     pad_value: float=-1.0) -> paddle.Tensor:\n    \"\"\"Reverse padding for the list of tensors.\n    Args:\n        ys_pad (tensor): The padded tensor (B, Tokenmax).\n        ys_lens (tensor): The lens of token seqs (B)\n        pad_value (int): Value for padding.\n    Returns:\n        Tensor: Padded tensor (B, Tokenmax).\n    Examples:\n        >>> x\n        tensor([[1, 2, 3, 4], [5, 6, 7, 0], [8, 9, 0, 0]])\n        >>> pad_list(x, 0)\n        tensor([[4, 3, 2, 1],\n                [7, 6, 5, 0],\n                [9, 8, 0, 0]])\n    \"\"\"\n    r_ys_pad = pad_sequence([(paddle.flip(y.int()[:i], [0]))\n                             for y, i in zip(ys_pad, ys_lens)], True, pad_value)\n    return r_ys_pad\n\n\ndef st_reverse_pad_list(ys_pad: paddle.Tensor,\n                        ys_lens: paddle.Tensor,\n                        sos: float,\n                        eos: float) -> paddle.Tensor:\n    \"\"\"Reverse padding for the list of tensors.\n    Args:\n        ys_pad (tensor): The padded tensor (B, Tokenmax).\n        ys_lens (tensor): The lens of token seqs (B)\n    Returns:\n        Tensor: Padded tensor (B, Tokenmax).\n    Examples:\n        >>> x\n        tensor([[1, 2, 3, 4], [5, 6, 7, 0], [8, 9, 0, 0]])\n        >>> pad_list(x, 0)\n        tensor([[4, 3, 2, 1],\n                [7, 6, 5, 0],\n                [9, 8, 0, 0]])\n    \"\"\"\n    # Equal to:\n    #   >>> r_hyps = reverse_pad_list(r_hyps, r_hyps_lens, float(self.ignore_id))\n    #   >>> r_hyps, _ = add_sos_eos(r_hyps, self.sos, self.eos, self.ignore_id)\n    B = ys_pad.shape[0]\n    _sos = paddle.full([B, 1], sos, dtype=ys_pad.dtype)\n    max_len = paddle.max(ys_lens)\n    index_range = paddle.arange(0, max_len, 1)\n    seq_len_expand = ys_lens.unsqueeze(1)\n    seq_mask = seq_len_expand > index_range  # (beam, max_len)\n\n    index = (seq_len_expand - 1) - index_range  # (beam, max_len)\n    #   >>> index\n    #   >>> tensor([[ 2,  1,  0],\n    #   >>>         [ 2,  1,  0],\n    #   >>>         [ 0, -1, -2]])\n    index = index * seq_mask.astype(index.dtype)\n\n    #   >>> index\n    #   >>> tensor([[2, 1, 0],\n    #   >>>         [2, 1, 0],\n    #   >>>         [0, 0, 0]])\n    def paddle_gather(x, dim, index):\n        index_shape = index.shape\n        index_flatten = index.flatten()\n        if dim < 0:\n            dim = len(x.shape) + dim\n        nd_index = []\n        for k in range(len(x.shape)):\n            if k == dim:\n                nd_index.append(index_flatten)\n            else:\n                reshape_shape = [1] * len(x.shape)\n                reshape_shape[k] = x.shape[k]\n                x_arange = paddle.arange(x.shape[k], dtype=index.dtype)\n                x_arange = x_arange.reshape(reshape_shape)\n                dim_index = paddle.expand(x_arange, index_shape).flatten()\n                nd_index.append(dim_index)\n        ind2 = paddle.transpose(paddle.stack(nd_index), [1, 0]).astype(\"int64\")\n        paddle_out = paddle.gather_nd(x, ind2).reshape(index_shape)\n        return paddle_out\n\n    r_hyps = paddle_gather(ys_pad, 1, index)\n    #   >>> r_hyps\n    #   >>> tensor([[3, 2, 1],\n    #   >>>         [4, 8, 9],\n    #   >>>         [2, 2, 2]])\n    _eos = paddle.full([1], eos, dtype=r_hyps.dtype)\n    r_hyps = paddle.where(seq_mask, r_hyps, _eos)\n    #   >>> r_hyps\n    #   >>> tensor([[3, 2, 1],\n    #   >>>         [4, 8, 9],\n    #   >>>         [2, eos, eos]])\n\n    r_hyps = paddle.cat([_sos, r_hyps], dim=1)\n    # r_hyps = paddle.concat([hyps[:, 0:1], r_hyps], axis=1)\n    #   >>> r_hyps\n    #   >>> tensor([[sos, 3, 2, 1],\n    #   >>>         [sos, 4, 8, 9],\n    #   >>>         [sos, 2, eos, eos]])\n    return r_hyps\n"
  },
  {
    "path": "paddlespeech/audio/utils/time.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport time\n\n__all__ = [\n    'Timer',\n    'seconds_to_hms',\n]\n\n\nclass Timer(object):\n    '''Calculate runing speed and estimated time of arrival(ETA)'''\n\n    def __init__(self, total_step: int):\n        self.total_step = total_step\n        self.last_start_step = 0\n        self.current_step = 0\n        self._is_running = True\n\n    def start(self):\n        self.last_time = time.time()\n        self.start_time = time.time()\n\n    def stop(self):\n        self._is_running = False\n        self.end_time = time.time()\n\n    def count(self) -> int:\n        if not self.current_step >= self.total_step:\n            self.current_step += 1\n        return self.current_step\n\n    @property\n    def timing(self) -> float:\n        run_steps = self.current_step - self.last_start_step\n        self.last_start_step = self.current_step\n        time_used = time.time() - self.last_time\n        self.last_time = time.time()\n        return run_steps / time_used\n\n    @property\n    def is_running(self) -> bool:\n        return self._is_running\n\n    @property\n    def eta(self) -> str:\n        if not self.is_running:\n            return '00:00:00'\n        scale = self.total_step / self.current_step\n        remaining_time = (time.time() - self.start_time) * scale\n        return seconds_to_hms(remaining_time)\n\n\ndef seconds_to_hms(seconds: int) -> str:\n    '''Convert the number of seconds to hh:mm:ss'''\n    h = math.floor(seconds / 3600)\n    m = math.floor((seconds - h * 3600) / 60)\n    s = int(seconds - h * 3600 - m * 60)\n    hms_str = '{:0>2}:{:0>2}:{:0>2}'.format(h, m, s)\n    return hms_str\n"
  },
  {
    "path": "paddlespeech/audiotools/README.md",
    "content": "Audiotools is a comprehensive toolkit designed for audio processing and analysis, providing robust solutions for audio signal processing, data management, model training, and evaluation.\n\n### Directory Structure\n\n```\n.\n├── audiotools\n│   ├── README.md\n│   ├── __init__.py\n│   ├── core\n│   │   ├── __init__.py\n│   │   ├── _julius.py\n│   │   ├── audio_signal.py\n│   │   ├── display.py\n│   │   ├── dsp.py\n│   │   ├── effects.py\n│   │   ├── ffmpeg.py\n│   │   ├── loudness.py\n│   │   └── util.py\n│   ├── data\n│   │   ├── __init__.py\n│   │   ├── datasets.py\n│   │   ├── preprocess.py\n│   │   └── transforms.py\n│   ├── metrics\n│   │   ├── __init__.py\n│   │   └── quality.py\n│   ├── ml\n│   │   ├── __init__.py\n│   │   ├── accelerator.py\n│   │   ├── basemodel.py\n│   │   └── decorators.py\n│   ├── requirements.txt\n│   └── post.py\n├── tests\n│   └── audiotools\n│       ├── core\n│       │   ├── test_audio_signal.py\n│       │   ├── test_bands.py\n│       │   ├── test_display.py\n│       │   ├── test_dsp.py\n│       │   ├── test_effects.py\n│       │   ├── test_fftconv.py\n│       │   ├── test_grad.py\n│       │   ├── test_highpass.py\n│       │   ├── test_loudness.py\n│       │   ├── test_lowpass.py\n│       │   └── test_util.py\n│       ├── data\n│       │   ├── test_datasets.py\n│       │   ├── test_preprocess.py\n│       │   └── test_transforms.py\n│       ├── ml\n│       │   ├── test_decorators.py\n│       │   └── test_model.py\n│       └── test_post.py\n\n```\n\n- **core**: Contains the core class AudioSignal, which is responsible for the fundamental representation and manipulation of audio signals.\n\n- **data**: Primarily dedicated to storing and processing datasets, including classes and functions for data preprocessing, ensuring efficient loading and transformation of audio data.\n\n- **metrics**: Implements functions for various audio evaluation metrics, enabling precise assessment of the performance of audio models and processing algorithms.\n\n- **ml**: Comprises classes and methods related to model training, supporting the construction, training, and optimization of machine learning models in the context of audio.\n\nThis project aims to provide developers and researchers with an efficient and flexible framework to foster innovation and exploration across various domains of audio technology.\n"
  },
  {
    "path": "paddlespeech/audiotools/__init__.py",
    "content": "# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import metrics\nfrom . import ml\nfrom . import post\nfrom .core import AudioSignal\nfrom .core import highpass_filter\nfrom .core import highpass_filters\nfrom .core import Meter\nfrom .core import STFTParams\nfrom .core import util\nfrom .data import datasets\nfrom .data import preprocess\nfrom .data import transforms\n"
  },
  {
    "path": "paddlespeech/audiotools/core/__init__.py",
    "content": "# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import util\nfrom ...t2s.modules import fft_conv1d\nfrom ...t2s.modules import FFTConv1D\nfrom ._julius import highpass_filter\nfrom ._julius import highpass_filters\nfrom ._julius import lowpass_filter\nfrom ._julius import LowPassFilter\nfrom ._julius import LowPassFilters\nfrom ._julius import pure_tone\nfrom ._julius import resample_frac\nfrom ._julius import split_bands\nfrom ._julius import SplitBands\nfrom .audio_signal import AudioSignal\nfrom .audio_signal import STFTParams\nfrom .loudness import Meter\n"
  },
  {
    "path": "paddlespeech/audiotools/core/_julius.py",
    "content": "# MIT License, Copyright (c) 2020 Alexandre Défossez.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n# \n# Modified from julius(https://github.com/adefossez/julius/tree/main/julius)\n\"\"\"\nImplementation of a FFT based 1D convolution in PaddlePaddle.\nWhile FFT is used in some cases for small kernel sizes, it is not the default for long ones, e.g. 512.\nThis module implements efficient FFT based convolutions for such cases. A typical\napplication is for evaluating FIR filters with a long receptive field, typically\nevaluated with a stride of 1.\n\"\"\"\nimport inspect\nimport math\nimport sys\nimport typing\nfrom typing import Optional\nfrom typing import Sequence\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.utils import satisfy_paddle_version\n\n__all__ = [\n    'highpass_filter', 'highpass_filters', 'lowpass_filter', 'LowPassFilter',\n    'LowPassFilters', 'pure_tone', 'resample_frac', 'split_bands', 'SplitBands'\n]\n\n\ndef simple_repr(obj, attrs: Optional[Sequence[str]]=None, overrides: dict={}):\n    \"\"\"\n    Return a simple representation string for `obj`.\n    If `attrs` is not None, it should be a list of attributes to include.\n    \"\"\"\n    params = inspect.signature(obj.__class__).parameters\n    attrs_repr = []\n    if attrs is None:\n        attrs = list(params.keys())\n    for attr in attrs:\n        display = False\n        if attr in overrides:\n            value = overrides[attr]\n        elif hasattr(obj, attr):\n            value = getattr(obj, attr)\n        else:\n            continue\n        if attr in params:\n            param = params[attr]\n            if param.default is inspect._empty or value != param.default:  # type: ignore\n                display = True\n        else:\n            display = True\n\n        if display:\n            attrs_repr.append(f\"{attr}={value}\")\n    return f\"{obj.__class__.__name__}({','.join(attrs_repr)})\"\n\n\ndef sinc(x: paddle.Tensor):\n    \"\"\"\n    Implementation of sinc, i.e. sin(x) / x\n\n    __Warning__: the input is not multiplied by `pi`!\n    \"\"\"\n    return paddle.where(\n        x == 0,\n        paddle.to_tensor(1.0, dtype=x.dtype, place=x.place),\n        paddle.sin(x) / x, )\n\n\nclass ResampleFrac(paddle.nn.Layer):\n    \"\"\"\n    Resampling from the sample rate `old_sr` to `new_sr`.\n    \"\"\"\n\n    def __init__(self,\n                 old_sr: int,\n                 new_sr: int,\n                 zeros: int=24,\n                 rolloff: float=0.945):\n        \"\"\"\n        Args:\n            old_sr (int): sample rate of the input signal x.\n            new_sr (int): sample rate of the output.\n            zeros (int): number of zero crossing to keep in the sinc filter.\n            rolloff (float): use a lowpass filter that is `rolloff * new_sr / 2`,\n                to ensure sufficient margin due to the imperfection of the FIR filter used.\n                Lowering this value will reduce anti-aliasing, but will reduce some of the\n                highest frequencies.\n\n        Shape:\n\n            - Input: `[*, T]`\n            - Output: `[*, T']` with `T' = int(new_sr * T / old_sr)`\n\n\n        .. caution::\n            After dividing `old_sr` and `new_sr` by their GCD, both should be small\n            for this implementation to be fast.\n\n        >>> import paddle\n        >>> resample = ResampleFrac(4, 5)\n        >>> x = paddle.randn([1000])\n        >>> print(len(resample(x)))\n        1250\n        \"\"\"\n        super().__init__()\n        if not isinstance(old_sr, int) or not isinstance(new_sr, int):\n            raise ValueError(\"old_sr and new_sr should be integers\")\n        gcd = math.gcd(old_sr, new_sr)\n        self.old_sr = old_sr // gcd\n        self.new_sr = new_sr // gcd\n        self.zeros = zeros\n        self.rolloff = rolloff\n\n        self._init_kernels()\n\n    def _init_kernels(self):\n        if self.old_sr == self.new_sr:\n            return\n\n        kernels = []\n        sr = min(self.new_sr, self.old_sr)\n        sr *= self.rolloff\n\n        self._width = math.ceil(self.zeros * self.old_sr / sr)\n        idx = paddle.arange(\n            -self._width, self._width + self.old_sr, dtype=\"float32\")\n        for i in range(self.new_sr):\n            t = (-i / self.new_sr + idx / paddle.full(idx.shape, self.old_sr)\n                 ) * sr\n            t = paddle.clip(t, -self.zeros, self.zeros)\n            t *= math.pi\n            window = paddle.cos(t / self.zeros / 2)**2\n            kernel = sinc(t) * window\n            # Renormalize kernel to ensure a constant signal is preserved.\n            kernel = kernel / kernel.sum()\n            kernels.append(kernel)\n\n        _kernel = paddle.stack(kernels).reshape([self.new_sr, 1, -1])\n        self.kernel = self.create_parameter(\n            shape=_kernel.shape,\n            dtype=_kernel.dtype, )\n        self.kernel.set_value(_kernel)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            output_length: Optional[int]=None,\n            full: bool=False, ):\n        \"\"\"\n        Resample x.\n        Args:\n            x (Tensor): signal to resample, time should be the last dimension\n            output_length (None or int): This can be set to the desired output length\n                (last dimension). Allowed values are between 0 and\n                ceil(length * new_sr / old_sr). When None (default) is specified, the\n                floored output length will be used. In order to select the largest possible\n                size, use the `full` argument.\n            full (bool): return the longest possible output from the input. This can be useful\n                if you chain resampling operations, and want to give the `output_length` only\n                for the last one, while passing `full=True` to all the other ones.\n        \"\"\"\n        if self.old_sr == self.new_sr:\n            return x\n        shape = x.shape\n        _dtype = x.dtype\n        length = x.shape[-1]\n        x = x.reshape([-1, length])\n        x = F.pad(\n            x.unsqueeze(1),\n            [self._width, self._width + self.old_sr],\n            mode=\"replicate\",\n            data_format=\"NCL\", ).astype(self.kernel.dtype)\n        ys = F.conv1d(x, self.kernel, stride=self.old_sr, data_format=\"NCL\")\n        y = ys.transpose(\n            [0, 2, 1]).reshape(list(shape[:-1]) + [-1]).astype(_dtype)\n\n        float_output_length = paddle.to_tensor(\n            self.new_sr * length / self.old_sr, dtype=\"float32\")\n        max_output_length = paddle.ceil(float_output_length).astype(\"int64\")\n        default_output_length = paddle.floor(float_output_length).astype(\n            \"int64\")\n\n        if output_length is None:\n            applied_output_length = (max_output_length\n                                     if full else default_output_length)\n        elif output_length < 0 or output_length > max_output_length:\n            raise ValueError(\n                f\"output_length must be between 0 and {max_output_length.numpy()}\"\n            )\n        else:\n            applied_output_length = paddle.to_tensor(\n                output_length, dtype=\"int64\")\n            if full:\n                raise ValueError(\n                    \"You cannot pass both full=True and output_length\")\n        return y[..., :applied_output_length]\n\n    def __repr__(self):\n        return simple_repr(self)\n\n\ndef resample_frac(\n        x: paddle.Tensor,\n        old_sr: int,\n        new_sr: int,\n        zeros: int=24,\n        rolloff: float=0.945,\n        output_length: Optional[int]=None,\n        full: bool=False, ):\n    \"\"\"\n    Functional version of `ResampleFrac`, refer to its documentation for more information.\n\n    ..warning::\n        If you call repeatidly this functions with the same sample rates, then the\n        resampling kernel will be recomputed everytime. For best performance, you should use\n        and cache an instance of `ResampleFrac`.\n    \"\"\"\n    return ResampleFrac(old_sr, new_sr, zeros, rolloff)(x, output_length, full)\n\n\ndef pad_to(tensor: paddle.Tensor,\n           target_length: int,\n           mode: str=\"constant\",\n           value: float=0.0):\n    \"\"\"\n    Pad the given tensor to the given length, with 0s on the right.\n    \"\"\"\n    return F.pad(\n        tensor, (0, target_length - tensor.shape[-1]),\n        mode=mode,\n        value=value,\n        data_format=\"NCL\")\n\n\ndef pure_tone(freq: float, sr: float=128, dur: float=4, device=None):\n    \"\"\"\n    Return a pure tone, i.e. cosine.\n\n    Args:\n        freq (float): frequency (in Hz)\n        sr (float): sample rate (in Hz)\n        dur (float): duration (in seconds)\n    \"\"\"\n    time = paddle.arange(int(sr * dur), dtype=\"float32\") / sr\n    return paddle.cos(2 * math.pi * freq * time)\n\n\nclass LowPassFilters(nn.Layer):\n    \"\"\"\n    Bank of low pass filters.\n    \"\"\"\n\n    def __init__(self,\n                 cutoffs: Sequence[float],\n                 stride: int=1,\n                 pad: bool=True,\n                 zeros: float=8,\n                 fft: Optional[bool]=None,\n                 dtype=\"float32\"):\n        super().__init__()\n        self.cutoffs = list(cutoffs)\n        if min(self.cutoffs) < 0:\n            raise ValueError(\"Minimum cutoff must be larger than zero.\")\n        if max(self.cutoffs) > 0.5:\n            raise ValueError(\"A cutoff above 0.5 does not make sense.\")\n        self.stride = stride\n        self.pad = pad\n        self.zeros = zeros\n        self.half_size = int(zeros / min([c for c in self.cutoffs if c > 0]) /\n                             2)\n        if fft is None:\n            fft = self.half_size > 32\n        self.fft = fft\n\n        # Create filters\n        window = paddle.audio.functional.get_window(\n            \"hann\", 2 * self.half_size + 1, fftbins=False, dtype=dtype)\n        time = paddle.arange(\n            -self.half_size, self.half_size + 1, dtype=\"float32\")\n        filters = []\n        for cutoff in cutoffs:\n            if cutoff == 0:\n                filter_ = paddle.zeros_like(time)\n            else:\n                filter_ = 2 * cutoff * window * sinc(2 * cutoff * math.pi *\n                                                     time)\n                # Normalize filter\n                filter_ /= paddle.sum(filter_)\n            filters.append(filter_)\n        filters = paddle.stack(filters)[:, None]\n        self.filters = self.create_parameter(\n            shape=filters.shape,\n            default_initializer=nn.initializer.Constant(value=0.0),\n            dtype=\"float32\",\n            is_bias=False,\n            attr=paddle.ParamAttr(trainable=False), )\n        self.filters.set_value(filters)\n\n    def forward(self, _input):\n        shape = list(_input.shape)\n        _input = _input.reshape([-1, 1, shape[-1]])\n        if self.pad:\n            _input = F.pad(\n                _input, (self.half_size, self.half_size),\n                mode=\"replicate\",\n                data_format=\"NCL\")\n        if self.fft:\n            from paddlespeech.t2s.modules import fft_conv1d\n            out = fft_conv1d(_input, self.filters, stride=self.stride)\n        else:\n            out = F.conv1d(_input, self.filters, stride=self.stride)\n\n        shape.insert(0, len(self.cutoffs))\n        shape[-1] = out.shape[-1]\n        return out.transpose([1, 0, 2]).reshape(shape)\n\n\nclass LowPassFilter(nn.Layer):\n    \"\"\"\n    Same as `LowPassFilters` but applies a single low pass filter.\n    \"\"\"\n\n    def __init__(self,\n                 cutoff: float,\n                 stride: int=1,\n                 pad: bool=True,\n                 zeros: float=8,\n                 fft: Optional[bool]=None):\n        super().__init__()\n        self._lowpasses = LowPassFilters([cutoff], stride, pad, zeros, fft)\n\n    @property\n    def cutoff(self):\n        return self._lowpasses.cutoffs[0]\n\n    @property\n    def stride(self):\n        return self._lowpasses.stride\n\n    @property\n    def pad(self):\n        return self._lowpasses.pad\n\n    @property\n    def zeros(self):\n        return self._lowpasses.zeros\n\n    @property\n    def fft(self):\n        return self._lowpasses.fft\n\n    def forward(self, _input):\n        return self._lowpasses(_input)[0]\n\n\ndef lowpass_filters(\n        _input: paddle.Tensor,\n        cutoffs: Sequence[float],\n        stride: int=1,\n        pad: bool=True,\n        zeros: float=8,\n        fft: Optional[bool]=None, ):\n    \"\"\"\n    Functional version of `LowPassFilters`, refer to this class for more information.\n    \"\"\"\n    return LowPassFilters(cutoffs, stride, pad, zeros, fft)(_input)\n\n\ndef lowpass_filter(_input: paddle.Tensor,\n                   cutoff: float,\n                   stride: int=1,\n                   pad: bool=True,\n                   zeros: float=8,\n                   fft: Optional[bool]=None):\n    \"\"\"\n    Same as `lowpass_filters` but with a single cutoff frequency.\n    Output will not have a dimension inserted in the front.\n    \"\"\"\n    return lowpass_filters(_input, [cutoff], stride, pad, zeros, fft)[0]\n\n\nclass HighPassFilters(paddle.nn.Layer):\n    \"\"\"\n    Bank of high pass filters. See `julius.lowpass.LowPassFilters` for more\n    details on the implementation.\n\n    Args:\n        cutoffs (list[float]): list of cutoff frequencies, in [0, 0.5] expressed as `f/f_s` where\n            f_s is the samplerate and `f` is the cutoff frequency.\n            The upper limit is 0.5, because a signal sampled at `f_s` contains only\n            frequencies under `f_s / 2`.\n        stride (int): how much to decimate the output. Probably not a good idea\n            to do so with a high pass filters though...\n        pad (bool): if True, appropriately pad the _input with zero over the edge. If `stride=1`,\n            the output will have the same length as the _input.\n        zeros (float): Number of zero crossings to keep.\n            Controls the receptive field of the Finite Impulse Response filter.\n            For filters with low cutoff frequency, e.g. 40Hz at 44.1kHz,\n            it is a bad idea to set this to a high value.\n            This is likely appropriate for most use. Lower values\n            will result in a faster filter, but with a slower attenuation around the\n            cutoff frequency.\n        fft (bool or None): if True, uses `julius.fftconv` rather than PyTorch convolutions.\n            If False, uses PyTorch convolutions. If None, either one will be chosen automatically\n            depending on the effective filter size.\n\n\n    ..warning::\n        All the filters will use the same filter size, aligned on the lowest\n        frequency provided. If you combine a lot of filters with very diverse frequencies, it might\n        be more efficient to split them over multiple modules with similar frequencies.\n\n    Shape:\n\n        - Input: `[*, T]`\n        - Output: `[F, *, T']`, with `T'=T` if `pad` is True and `stride` is 1, and\n            `F` is the numer of cutoff frequencies.\n\n    >>> highpass = HighPassFilters([1/4])\n    >>> x = paddle.randn([4, 12, 21, 1024])\n    >>> list(highpass(x).shape)\n    [1, 4, 12, 21, 1024]\n    \"\"\"\n\n    def __init__(self,\n                 cutoffs: Sequence[float],\n                 stride: int=1,\n                 pad: bool=True,\n                 zeros: float=8,\n                 fft: Optional[bool]=None):\n        super().__init__()\n        self._lowpasses = LowPassFilters(cutoffs, stride, pad, zeros, fft)\n\n    @property\n    def cutoffs(self):\n        return self._lowpasses.cutoffs\n\n    @property\n    def stride(self):\n        return self._lowpasses.stride\n\n    @property\n    def pad(self):\n        return self._lowpasses.pad\n\n    @property\n    def zeros(self):\n        return self._lowpasses.zeros\n\n    @property\n    def fft(self):\n        return self._lowpasses.fft\n\n    def forward(self, _input):\n        lows = self._lowpasses(_input)\n\n        # We need to extract the right portion of the _input in case\n        # pad is False or stride > 1\n        if self.pad:\n            start, end = 0, _input.shape[-1]\n        else:\n            start = self._lowpasses.half_size\n            end = -start\n        _input = _input[..., start:end:self.stride]\n        highs = _input - lows\n        return highs\n\n\nclass HighPassFilter(paddle.nn.Layer):\n    \"\"\"\n    Same as `HighPassFilters` but applies a single high pass filter.\n\n    Shape:\n\n        - Input: `[*, T]`\n        - Output: `[*, T']`, with `T'=T` if `pad` is True and `stride` is 1.\n\n    >>> highpass = HighPassFilter(1/4, stride=1)\n    >>> x = paddle.randn([4, 124])\n    >>> list(highpass(x).shape)\n    [4, 124]\n    \"\"\"\n\n    def __init__(self,\n                 cutoff: float,\n                 stride: int=1,\n                 pad: bool=True,\n                 zeros: float=8,\n                 fft: Optional[bool]=None):\n        super().__init__()\n        self._highpasses = HighPassFilters([cutoff], stride, pad, zeros, fft)\n\n    @property\n    def cutoff(self):\n        return self._highpasses.cutoffs[0]\n\n    @property\n    def stride(self):\n        return self._highpasses.stride\n\n    @property\n    def pad(self):\n        return self._highpasses.pad\n\n    @property\n    def zeros(self):\n        return self._highpasses.zeros\n\n    @property\n    def fft(self):\n        return self._highpasses.fft\n\n    def forward(self, _input):\n        return self._highpasses(_input)[0]\n\n\ndef highpass_filters(\n        _input: paddle.Tensor,\n        cutoffs: Sequence[float],\n        stride: int=1,\n        pad: bool=True,\n        zeros: float=8,\n        fft: Optional[bool]=None, ):\n    \"\"\"\n    Functional version of `HighPassFilters`, refer to this class for more information.\n    \"\"\"\n    return HighPassFilters(cutoffs, stride, pad, zeros, fft)(_input)\n\n\ndef highpass_filter(_input: paddle.Tensor,\n                    cutoff: float,\n                    stride: int=1,\n                    pad: bool=True,\n                    zeros: float=8,\n                    fft: Optional[bool]=None):\n    \"\"\"\n    Functional version of `HighPassFilter`, refer to this class for more information.\n    Output will not have a dimension inserted in the front.\n    \"\"\"\n    return highpass_filters(_input, [cutoff], stride, pad, zeros, fft)[0]\n\n\nclass SplitBands(paddle.nn.Layer):\n    \"\"\"\n    Decomposes a signal over the given frequency bands in the waveform domain using\n    a cascade of low pass filters as implemented by `julius.lowpass.LowPassFilters`.\n    You can either specify explicitly the frequency cutoffs, or just the number of bands,\n    in which case the frequency cutoffs will be spread out evenly in mel scale.\n\n    Args:\n        sample_rate (float): Sample rate of the input signal in Hz.\n        n_bands (int or None): number of bands, when not giving them explicitly with `cutoffs`.\n            In that case, the cutoff frequencies will be evenly spaced in mel-space.\n        cutoffs (list[float] or None): list of frequency cutoffs in Hz.\n        pad (bool): if True, appropriately pad the input with zero over the edge. If `stride=1`,\n            the output will have the same length as the input.\n        zeros (float): Number of zero crossings to keep. See `LowPassFilters` for more informations.\n        fft (bool or None): See `LowPassFilters` for more info.\n\n    ..note::\n        The sum of all the bands will always be the input signal.\n\n    ..warning::\n        Unlike `julius.lowpass.LowPassFilters`, the cutoffs frequencies must be provided in Hz along\n        with the sample rate.\n\n    Shape:\n\n        - Input: `[*, T]`\n        - Output: `[B, *, T']`, with `T'=T` if `pad` is True.\n            If `n_bands` was provided, `B = n_bands` otherwise `B = len(cutoffs) + 1`\n\n    >>> bands = SplitBands(sample_rate=128, n_bands=10)\n    >>> x = paddle.randn(shape=[6, 4, 1024])\n    >>> list(bands(x).shape)\n    [10, 6, 4, 1024]\n    \"\"\"\n\n    def __init__(\n            self,\n            sample_rate: float,\n            n_bands: Optional[int]=None,\n            cutoffs: Optional[Sequence[float]]=None,\n            pad: bool=True,\n            zeros: float=8,\n            fft: Optional[bool]=None, ):\n        super().__init__()\n        if (cutoffs is None) + (n_bands is None) != 1:\n            raise ValueError(\n                \"You must provide either n_bands, or cutoffs, but not both.\")\n\n        self.sample_rate = sample_rate\n        self.n_bands = n_bands\n        self._cutoffs = list(cutoffs) if cutoffs is not None else None\n        self.pad = pad\n        self.zeros = zeros\n        self.fft = fft\n\n        if cutoffs is None:\n            if n_bands is None:\n                raise ValueError(\"You must provide one of n_bands or cutoffs.\")\n            if not n_bands >= 1:\n                raise ValueError(\n                    f\"n_bands must be greater than one (got {n_bands})\")\n            cutoffs = paddle.audio.functional.mel_frequencies(\n                n_bands + 1, 0, sample_rate / 2)[1:-1]\n        else:\n            if max(cutoffs) > 0.5 * sample_rate:\n                raise ValueError(\n                    \"A cutoff above sample_rate/2 does not make sense.\")\n        if len(cutoffs) > 0:\n            self.lowpass = LowPassFilters(\n                [c / sample_rate for c in cutoffs],\n                pad=pad,\n                zeros=zeros,\n                fft=fft)\n        else:\n            self.lowpass = None  # type: ignore\n\n    def forward(self, input):\n        if self.lowpass is None:\n            return input[None]\n        lows = self.lowpass(input)\n        low = lows[0]\n        bands = [low]\n        for low_and_band in lows[1:]:\n            # Get a bandpass filter by subtracting lowpasses\n            band = low_and_band - low\n            bands.append(band)\n            low = low_and_band\n        # Last band is whatever is left in the signal\n        bands.append(input - low)\n        return paddle.stack(bands)\n\n    @property\n    def cutoffs(self):\n        if self._cutoffs is not None:\n            return self._cutoffs\n        elif self.lowpass is not None:\n            return [c * self.sample_rate for c in self.lowpass.cutoffs]\n        else:\n            return []\n\n\ndef split_bands(\n        signal: paddle.Tensor,\n        sample_rate: float,\n        n_bands: Optional[int]=None,\n        cutoffs: Optional[Sequence[float]]=None,\n        pad: bool=True,\n        zeros: float=8,\n        fft: Optional[bool]=None, ):\n    \"\"\"\n    Functional version of `SplitBands`, refer to this class for more information.\n\n    >>> x = paddle.randn(shape=[6, 4, 1024])\n    >>> list(split_bands(x, sample_rate=64, cutoffs=[12, 24]).shape)\n    [3, 6, 4, 1024]\n    \"\"\"\n    return SplitBands(sample_rate, n_bands, cutoffs, pad, zeros, fft)(signal)\n"
  },
  {
    "path": "paddlespeech/audiotools/core/audio_signal.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n# \n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/audio_signal.py)\nimport copy\nimport functools\nimport hashlib\nimport math\nimport pathlib\nimport tempfile\nimport typing\nimport warnings\nfrom collections import namedtuple\nfrom pathlib import Path\nfrom typing import Optional\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile\n\nfrom . import util\nfrom ._julius import resample_frac\nfrom .display import DisplayMixin\nfrom .dsp import DSPMixin\nfrom .effects import EffectMixin\nfrom .effects import ImpulseResponseMixin\nfrom .ffmpeg import FFMPEGMixin\nfrom .loudness import LoudnessMixin\n\n__all__ = ['STFTParams', 'AudioSignal']\n\n\ndef create_dct(n_mfcc: int, n_mels: int, norm: Optional[str]) -> paddle.Tensor:\n    r\"\"\"Create a DCT transformation matrix with shape (``n_mels``, ``n_mfcc``),\n    normalized depending on norm.\n\n    Args:\n        n_mfcc (int): Number of mfc coefficients to retain\n        n_mels (int): Number of mel filterbanks\n        norm (str or None): Norm to use (either \"ortho\" or None)\n\n    Returns:\n        paddle.Tensor: The transformation matrix, to be right-multiplied to\n        row-wise data of size (``n_mels``, ``n_mfcc``).\n    \"\"\"\n\n    if norm is not None and norm != \"ortho\":\n        raise ValueError('norm must be either \"ortho\" or None')\n\n    # http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-II\n    n = paddle.arange(float(n_mels))\n    k = paddle.arange(float(n_mfcc)).unsqueeze([1])\n    dct = paddle.cos(math.pi / float(n_mels) * (n + 0.5) *\n                     k)  # size (n_mfcc, n_mels)\n\n    if norm is None:\n        dct *= 2.0\n    else:\n        dct[0] *= 1.0 / math.sqrt(2.0)\n        dct *= math.sqrt(2.0 / float(n_mels))\n    return dct.transpose([1, 0])\n\n\nSTFTParams = namedtuple(\n    \"STFTParams\",\n    [\n        \"window_length\",\n        \"hop_length\",\n        \"window_type\",\n        \"match_stride\",\n        \"padding_type\",\n    ], )\n\"\"\"\nSTFTParams object is a container that holds STFT parameters - window_length,\nhop_length, and window_type. Not all parameters need to be specified. Ones that\nare not specified will be inferred by the AudioSignal parameters.\n\nParameters\n----------\nwindow_length : int, optional\n    Window length of STFT, by default ``0.032 * self.sample_rate``.\nhop_length : int, optional\n    Hop length of STFT, by default ``window_length // 4``.\nwindow_type : str, optional\n    Type of window to use, by default ``sqrt\\_hann``.\nmatch_stride : bool, optional\n    Whether to match the stride of convolutional layers, by default False\npadding_type : str, optional\n    Type of padding to use, by default 'reflect'\n\"\"\"\nSTFTParams.__new__.__defaults__ = (None, None, None, None, None)\n\n\nclass AudioSignal(\n        EffectMixin,\n        LoudnessMixin,\n        ImpulseResponseMixin,\n        DSPMixin,\n        DisplayMixin,\n        FFMPEGMixin, ):\n    \"\"\"This is the core object of this library. Audio is always\n    loaded into an AudioSignal, which then enables all the features\n    of this library, including audio augmentations, I/O, playback,\n    and more.\n\n    The structure of this object is that the base functionality\n    is defined in ``core/audio_signal.py``, while extensions to\n    that functionality are defined in the other ``core/*.py``\n    files. For example, all the display-based functionality\n    (e.g. plot spectrograms, waveforms, write to tensorboard)\n    are in ``core/display.py``.\n\n    Parameters\n    ----------\n    audio_path_or_array : typing.Union[paddle.Tensor, str, Path, np.ndarray]\n        Object to create AudioSignal from. Can be a tensor, numpy array,\n        or a path to a file. The file is always reshaped to\n    sample_rate : int, optional\n        Sample rate of the audio. If different from underlying file, resampling is\n        performed. If passing in an array or tensor, this must be defined,\n        by default None\n    stft_params : STFTParams, optional\n        Parameters of STFT to use. , by default None\n    offset : float, optional\n        Offset in seconds to read from file, by default 0\n    duration : float, optional\n        Duration in seconds to read from file, by default None\n    device : str, optional\n        Device to load audio onto, by default None\n\n    Examples\n    --------\n    Loading an AudioSignal from an array, at a sample rate of\n    44100.\n\n    >>> signal = AudioSignal(paddle.randn([5*44100]), 44100)\n\n    Note, the signal is reshaped to have a batch size, and one\n    audio channel:\n\n    >>> print(signal.shape)\n    (1, 1, 44100)\n\n    You can treat AudioSignals like tensors, and many of the same\n    functions you might use on tensors are defined for AudioSignals\n    as well:\n\n    >>> signal.to(\"cuda\")\n    >>> signal.cuda()\n    >>> signal.clone()\n    >>> signal.detach()\n\n    Indexing AudioSignals returns an AudioSignal:\n\n    >>> signal[..., 3*44100:4*44100]\n\n    The above signal is 1 second long, and is also an AudioSignal.\n    \"\"\"\n\n    def __init__(\n            self,\n            audio_path_or_array: typing.Union[paddle.Tensor, str, Path,\n                                              np.ndarray],\n            sample_rate: int=None,\n            stft_params: STFTParams=None,\n            offset: float=0,\n            duration: float=None,\n            device: str=None, ):\n        # \n        audio_path = None\n        audio_array = None\n\n        if isinstance(audio_path_or_array, str):\n            audio_path = audio_path_or_array\n        elif isinstance(audio_path_or_array, pathlib.Path):\n            audio_path = audio_path_or_array\n        elif isinstance(audio_path_or_array, np.ndarray):\n            audio_array = audio_path_or_array\n        elif paddle.is_tensor(audio_path_or_array):\n            audio_array = audio_path_or_array\n        else:\n            raise ValueError(\"audio_path_or_array must be either a Path, \"\n                             \"string, numpy array, or paddle Tensor!\")\n\n        self.path_to_file = None\n\n        self.audio_data = None\n        self.sources = None  # List of AudioSignal objects.\n        self.stft_data = None\n        if audio_path is not None:\n            self.load_from_file(\n                audio_path, offset=offset, duration=duration, device=device)\n        elif audio_array is not None:\n            assert sample_rate is not None, \"Must set sample rate!\"\n            self.load_from_array(audio_array, sample_rate, device=device)\n\n        self.window = None\n        self.stft_params = stft_params\n\n        self.metadata = {\n            \"offset\": offset,\n            \"duration\": duration,\n        }\n\n    @property\n    def path_to_input_file(\n            self, ):\n        \"\"\"\n        Path to input file, if it exists.\n        Alias to ``path_to_file`` for backwards compatibility\n        \"\"\"\n        return self.path_to_file\n\n    @classmethod\n    def excerpt(\n            cls,\n            audio_path: typing.Union[str, Path],\n            offset: float=None,\n            duration: float=None,\n            state: typing.Union[np.random.RandomState, int]=None,\n            **kwargs, ):\n        \"\"\"Randomly draw an excerpt of ``duration`` seconds from an\n        audio file specified at ``audio_path``, between ``offset`` seconds\n        and end of file. ``state`` can be used to seed the random draw.\n\n        Parameters\n        ----------\n        audio_path : typing.Union[str, Path]\n            Path to audio file to grab excerpt from.\n        offset : float, optional\n            Lower bound for the start time, in seconds drawn from\n            the file, by default None.\n        duration : float, optional\n            Duration of excerpt, in seconds, by default None\n        state : typing.Union[np.random.RandomState, int], optional\n            RandomState or seed of random state, by default None\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal containing excerpt.\n\n        Examples\n        --------\n        >>> signal = AudioSignal.excerpt(\"path/to/audio\", duration=5)\n        \"\"\"\n        info = util.info(audio_path)\n        total_duration = info.duration\n\n        state = util.random_state(state)\n        lower_bound = 0 if offset is None else offset\n        upper_bound = max(total_duration - duration, 0)\n        offset = state.uniform(lower_bound, upper_bound)\n\n        signal = cls(audio_path, offset=offset, duration=duration, **kwargs)\n        signal.metadata[\"offset\"] = offset\n        signal.metadata[\"duration\"] = duration\n\n        return signal\n\n    @classmethod\n    def salient_excerpt(\n            cls,\n            audio_path: typing.Union[str, Path],\n            loudness_cutoff: float=None,\n            num_tries: int=8,\n            state: typing.Union[np.random.RandomState, int]=None,\n            **kwargs, ):\n        \"\"\"Similar to AudioSignal.excerpt, except it extracts excerpts only\n        if they are above a specified loudness threshold, which is computed via\n        a fast LUFS routine.\n\n        Parameters\n        ----------\n        audio_path : typing.Union[str, Path]\n            Path to audio file to grab excerpt from.\n        loudness_cutoff : float, optional\n            Loudness threshold in dB. Typical values are ``-40, -60``,\n            etc, by default None\n        num_tries : int, optional\n            Number of tries to grab an excerpt above the threshold\n            before giving up, by default 8.\n        state : typing.Union[np.random.RandomState, int], optional\n            RandomState or seed of random state, by default None\n        kwargs : dict\n            Keyword arguments to AudioSignal.excerpt\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal containing excerpt.\n\n\n        .. warning::\n            if ``num_tries`` is set to None, ``salient_excerpt`` may try forever, which can\n            result in an infinite loop if ``audio_path`` does not have\n            any loud enough excerpts.\n\n        Examples\n        --------\n        >>> signal = AudioSignal.salient_excerpt(\n                \"path/to/audio\",\n                loudness_cutoff=-40,\n                duration=5\n            )\n        \"\"\"\n        state = util.random_state(state)\n        if loudness_cutoff is None:\n            excerpt = cls.excerpt(audio_path, state=state, **kwargs)\n        else:\n            loudness = -np.inf\n            num_try = 0\n            while loudness <= loudness_cutoff:\n                excerpt = cls.excerpt(audio_path, state=state, **kwargs)\n                loudness = excerpt.loudness()\n                num_try += 1\n                if num_tries is not None and num_try >= num_tries:\n                    break\n        return excerpt\n\n    @classmethod\n    def zeros(\n            cls,\n            duration: float,\n            sample_rate: int,\n            num_channels: int=1,\n            batch_size: int=1,\n            **kwargs, ):\n        \"\"\"Helper function create an AudioSignal of all zeros.\n\n        Parameters\n        ----------\n        duration : float\n            Duration of AudioSignal\n        sample_rate : int\n            Sample rate of AudioSignal\n        num_channels : int, optional\n            Number of channels, by default 1\n        batch_size : int, optional\n            Batch size, by default 1\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal containing all zeros.\n\n        Examples\n        --------\n        Generate 5 seconds of all zeros at a sample rate of 44100.\n\n        >>> signal = AudioSignal.zeros(5.0, 44100)\n        \"\"\"\n        n_samples = int(duration * sample_rate)\n        return cls(\n            paddle.zeros([batch_size, num_channels, n_samples]),\n            sample_rate,\n            **kwargs, )\n\n    @classmethod\n    def wave(\n            cls,\n            frequency: float,\n            duration: float,\n            sample_rate: int,\n            num_channels: int=1,\n            shape: str=\"sine\",\n            **kwargs, ):\n        \"\"\"\n        Generate a waveform of a given frequency and shape.\n\n        Parameters\n        ----------\n        frequency : float\n            Frequency of the waveform\n        duration : float\n            Duration of the waveform\n        sample_rate : int\n            Sample rate of the waveform\n        num_channels : int, optional\n            Number of channels, by default 1\n        shape : str, optional\n            Shape of the waveform, by default \"saw\"\n            One of \"sawtooth\", \"square\", \"sine\", \"triangle\"\n        kwargs : dict\n            Keyword arguments to AudioSignal\n        \"\"\"\n        n_samples = int(duration * sample_rate)\n        t = np.linspace(0, duration, n_samples)\n        if shape == \"sawtooth\":\n            from scipy.signal import sawtooth\n\n            wave_data = sawtooth(2 * np.pi * frequency * t, 0.5)\n        elif shape == \"square\":\n            from scipy.signal import square\n\n            wave_data = square(2 * np.pi * frequency * t)\n        elif shape == \"sine\":\n            wave_data = np.sin(2 * np.pi * frequency * t)\n        elif shape == \"triangle\":\n            from scipy.signal import sawtooth\n\n            # frequency is doubled by the abs call, so omit the 2 in 2pi\n            wave_data = sawtooth(np.pi * frequency * t, 0.5)\n            wave_data = -np.abs(wave_data) * 2 + 1\n        else:\n            raise ValueError(f\"Invalid shape {shape}\")\n\n        wave_data = paddle.to_tensor(wave_data, dtype=paddle.float32)\n        wave_data = wave_data[None, None].expand([1, num_channels, -1])\n        return cls(wave_data, sample_rate, **kwargs)\n\n    @classmethod\n    def batch(\n            cls,\n            audio_signals: list,\n            pad_signals: bool=False,\n            truncate_signals: bool=False,\n            resample: bool=False,\n            dim: int=0, ):\n        \"\"\"Creates a batched AudioSignal from a list of AudioSignals.\n\n        Parameters\n        ----------\n        audio_signals : list[AudioSignal]\n            List of AudioSignal objects\n        pad_signals : bool, optional\n            Whether to pad signals to length of the maximum length\n            AudioSignal in the list, by default False\n        truncate_signals : bool, optional\n            Whether to truncate signals to length of shortest length\n            AudioSignal in the list, by default False\n        resample : bool, optional\n            Whether to resample AudioSignal to the sample rate of\n            the first AudioSignal in the list, by default False\n        dim : int, optional\n            Dimension along which to batch the signals.\n\n        Returns\n        -------\n        AudioSignal\n            Batched AudioSignal.\n\n        Raises\n        ------\n        RuntimeError\n            If not all AudioSignals are the same sample rate, and\n            ``resample=False``, an error is raised.\n        RuntimeError\n            If not all AudioSignals are the same the length, and\n            both ``pad_signals=False`` and ``truncate_signals=False``,\n            an error is raised.\n\n        Examples\n        --------\n        Batching a bunch of random signals:\n\n        >>> signal_list = [AudioSignal(paddle.randn([44100]), 44100) for _ in range(10)]\n        >>> signal = AudioSignal.batch(signal_list)\n        >>> print(signal.shape)\n        (10, 1, 44100)\n\n        \"\"\"\n        signal_lengths = [x.signal_length for x in audio_signals]\n        sample_rates = [x.sample_rate for x in audio_signals]\n\n        if len(set(sample_rates)) != 1:\n            if resample:\n                for x in audio_signals:\n                    x.resample(sample_rates[0])\n            else:\n                raise RuntimeError(\n                    f\"Not all signals had the same sample rate! Got {sample_rates}. \"\n                    f\"All signals must have the same sample rate, or resample must be True. \"\n                )\n\n        if len(set(signal_lengths)) != 1:\n            if pad_signals:\n                max_length = max(signal_lengths)\n                for x in audio_signals:\n                    pad_len = max_length - x.signal_length\n                    x.zero_pad(0, pad_len)\n            elif truncate_signals:\n                min_length = min(signal_lengths)\n                for x in audio_signals:\n                    x.truncate_samples(min_length)\n            else:\n                raise RuntimeError(\n                    f\"Not all signals had the same length! Got {signal_lengths}. \"\n                    f\"All signals must be the same length, or pad_signals/truncate_signals \"\n                    f\"must be True. \")\n        # Concatenate along the specified dimension (default 0)\n        audio_data = paddle.concat(\n            [x.audio_data for x in audio_signals], axis=dim)\n        audio_paths = [x.path_to_file for x in audio_signals]\n\n        batched_signal = cls(\n            audio_data,\n            sample_rate=audio_signals[0].sample_rate, )\n        batched_signal.path_to_file = audio_paths\n        return batched_signal\n\n    # I/O\n    def load_from_file(\n            self,\n            audio_path: typing.Union[str, Path],\n            offset: float,\n            duration: float,\n            device: str=\"cpu\", ):\n        \"\"\"Loads data from file. Used internally when AudioSignal\n        is instantiated with a path to a file.\n\n        Parameters\n        ----------\n        audio_path : typing.Union[str, Path]\n            Path to file\n        offset : float\n            Offset in seconds\n        duration : float\n            Duration in seconds\n        device : str, optional\n            Device to put AudioSignal on, by default \"cpu\"\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal loaded from file\n        \"\"\"\n        # need `ffmpeg`\n        data, sample_rate = librosa.load(\n            audio_path,\n            offset=offset,\n            duration=duration,\n            sr=None,\n            mono=False, )\n        data = util.ensure_tensor(data)\n        if data.shape[-1] == 0:\n            raise RuntimeError(\n                f\"Audio file {audio_path} with offset {offset} and duration {duration} is empty!\"\n            )\n\n        if data.ndim < 2:\n            data = data.unsqueeze(0)\n        if data.ndim < 3:\n            data = data.unsqueeze(0)\n        self.audio_data = data\n\n        self.original_signal_length = self.signal_length\n\n        self.sample_rate = sample_rate\n        self.path_to_file = audio_path\n        return self.to(device)\n\n    def load_from_array(\n            self,\n            audio_array: typing.Union[paddle.Tensor, np.ndarray],\n            sample_rate: int,\n            device: str=\"cpu\", ):\n        \"\"\"Loads data from array, reshaping it to be exactly 3\n        dimensions. Used internally when AudioSignal is called\n        with a tensor or an array.\n\n        Parameters\n        ----------\n        audio_array : typing.Union[paddle.Tensor, np.ndarray]\n            Array/tensor of audio of samples.\n        sample_rate : int\n            Sample rate of audio\n        device : str, optional\n            Device to move audio onto, by default \"cpu\"\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal loaded from array\n        \"\"\"\n        audio_data = util.ensure_tensor(audio_array)\n\n        if str(audio_data.dtype) == paddle.float64:\n            audio_data = audio_data.astype(\"float32\")\n\n        if audio_data.ndim < 2:\n            audio_data = audio_data.unsqueeze(0)\n        if audio_data.ndim < 3:\n            audio_data = audio_data.unsqueeze(0)\n        self.audio_data = audio_data\n\n        self.original_signal_length = self.signal_length\n\n        self.sample_rate = sample_rate\n\n        return self\n\n    def write(self, audio_path: typing.Union[str, Path]):\n        \"\"\"Writes audio to a file. Only writes the audio\n        that is in the very first item of the batch. To write other items\n        in the batch, index the signal along the batch dimension\n        before writing. After writing, the signal's ``path_to_file``\n        attribute is updated to the new path.\n\n        Parameters\n        ----------\n        audio_path : typing.Union[str, Path]\n            Path to write audio to.\n\n        Returns\n        -------\n        AudioSignal\n            Returns original AudioSignal, so you can use this in a fluent\n            interface.\n\n        Examples\n        --------\n        Creating and writing a signal to disk:\n\n        >>> signal = AudioSignal(paddle.randn([10, 1, 44100]), 44100)\n        >>> signal.write(\"/tmp/out.wav\")\n\n        Writing a different element of the batch:\n\n        >>> signal[5].write(\"/tmp/out.wav\")\n\n        Using this in a fluent interface:\n\n        >>> signal.write(\"/tmp/original.wav\").low_pass(4000).write(\"/tmp/lowpass.wav\")\n\n        \"\"\"\n        if self.audio_data[0].abs().max() > 1:\n            warnings.warn(\"Audio amplitude > 1 clipped when saving\")\n        soundfile.write(\n            str(audio_path), self.audio_data[0].numpy().T, self.sample_rate)\n\n        self.path_to_file = audio_path\n        return self\n\n    def deepcopy(self):\n        \"\"\"Copies the signal and all of its attributes.\n\n        Returns\n        -------\n        AudioSignal\n            Deep copy of the audio signal.\n        \"\"\"\n        return copy.deepcopy(self)\n\n    def copy(self):\n        \"\"\"Shallow copy of signal.\n\n        Returns\n        -------\n        AudioSignal\n            Shallow copy of the audio signal.\n        \"\"\"\n        return copy.copy(self)\n\n    def clone(self):\n        \"\"\"Clones all tensors contained in the AudioSignal,\n        and returns a copy of the signal with everything\n        cloned. Useful when using AudioSignal within autograd\n        computation graphs.\n\n        Relevant attributes are the stft data, the audio data,\n        and the loudness of the file.\n\n        Returns\n        -------\n        AudioSignal\n            Clone of AudioSignal.\n        \"\"\"\n        clone = type(self)(\n            self.audio_data.clone(),\n            self.sample_rate,\n            stft_params=self.stft_params, )\n        if self.stft_data is not None:\n            clone.stft_data = self.stft_data.clone()\n        if self._loudness is not None:\n            clone._loudness = self._loudness.clone()\n        clone.path_to_file = copy.deepcopy(self.path_to_file)\n        clone.metadata = copy.deepcopy(self.metadata)\n        return clone\n\n    def detach(self):\n        \"\"\"Detaches tensors contained in AudioSignal.\n\n        Relevant attributes are the stft data, the audio data,\n        and the loudness of the file.\n\n        Returns\n        -------\n        AudioSignal\n            Same signal, but with all tensors detached.\n        \"\"\"\n        if self._loudness is not None:\n            self._loudness = self._loudness.detach()\n        if self.stft_data is not None:\n            self.stft_data = self.stft_data.detach()\n\n        self.audio_data = self.audio_data.detach()\n        return self\n\n    def hash(self):\n        \"\"\"Writes the audio data to a temporary file, and then\n        hashes it using hashlib. Useful for creating a file\n        name based on the audio content.\n\n        Returns\n        -------\n        str\n            Hash of audio data.\n\n        Examples\n        --------\n        Creating a signal, and writing it to a unique file name:\n\n        >>> signal = AudioSignal(paddle.randn([44100]), 44100)\n        >>> hash = signal.hash()\n        >>> signal.write(f\"{hash}.wav\")\n\n        \"\"\"\n        with tempfile.NamedTemporaryFile(suffix=\".wav\") as f:\n            self.write(f.name)\n            h = hashlib.sha256()\n            b = bytearray(128 * 1024)\n            mv = memoryview(b)\n            with open(f.name, \"rb\", buffering=0) as f:\n                for n in iter(lambda: f.readinto(mv), 0):\n                    h.update(mv[:n])\n            file_hash = h.hexdigest()\n        return file_hash\n\n    # Signal operations\n    def to_mono(self):\n        \"\"\"Converts audio data to mono audio, by taking the mean\n        along the channels dimension.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with mean of channels.\n        \"\"\"\n        self.audio_data = self.audio_data.mean(1, keepdim=True)\n        return self\n\n    def resample(self, sample_rate: int):\n        \"\"\"Resamples the audio, using sinc interpolation. This works on both\n        cpu and gpu, and is much faster on gpu.\n\n        Parameters\n        ----------\n        sample_rate : int\n            Sample rate to resample to.\n\n        Returns\n        -------\n        AudioSignal\n            Resampled AudioSignal\n        \"\"\"\n        if sample_rate == self.sample_rate:\n            return self\n        self.audio_data = resample_frac(self.audio_data, self.sample_rate,\n                                        sample_rate)\n        self.sample_rate = sample_rate\n        return self\n\n    # Tensor operations\n    def to(self, device: str):\n        \"\"\"Moves all tensors contained in signal to the specified device.\n\n        Parameters\n        ----------\n        device : str\n            Device to move AudioSignal onto. Typical values are\n            \"gpu\", \"cpu\", or \"gpu:x\" to specify the nth gpu.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with all tensors moved to specified device.\n        \"\"\"\n        if self._loudness is not None:\n            self._loudness = util.move_to_device(self._loudness, device)\n        if self.stft_data is not None:\n            self.stft_data = util.move_to_device(self.stft_data, device)\n        if self.audio_data is not None:\n            self.audio_data = util.move_to_device(self.audio_data, device)\n        return self\n\n    def float(self):\n        \"\"\"Calls ``.float()`` on ``self.audio_data``.\n\n        Returns\n        -------\n        AudioSignal\n        \"\"\"\n        self.audio_data = self.audio_data.astype(\"float32\")\n        return self\n\n    def cpu(self):\n        \"\"\"Moves AudioSignal to cpu.\n\n        Returns\n        -------\n        AudioSignal\n        \"\"\"\n        return self.to(\"cpu\")\n\n    def cuda(self):\n        \"\"\"Moves AudioSignal to cuda.\n\n        Returns\n        -------\n        AudioSignal\n        \"\"\"\n        return self.to(\"gpu\")\n\n    def numpy(self):\n        \"\"\"Detaches ``self.audio_data``, moves to cpu, and converts to numpy.\n\n        Returns\n        -------\n        np.ndarray\n            Audio data as a numpy array.\n        \"\"\"\n        return self.audio_data.detach().cpu().numpy()\n\n    def zero_pad(self, before: int, after: int):\n        \"\"\"Zero pads the audio_data tensor before and after.\n\n        Parameters\n        ----------\n        before : int\n            How many zeros to prepend to audio.\n        after : int\n            How many zeros to append to audio.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with padding applied.\n        \"\"\"\n        self.audio_data = paddle.nn.functional.pad(\n            self.audio_data, (before, after), data_format=\"NCL\")\n        return self\n\n    def zero_pad_to(self, length: int, mode: str=\"after\"):\n        \"\"\"Pad with zeros to a specified length, either before or after\n        the audio data.\n\n        Parameters\n        ----------\n        length : int\n            Length to pad to\n        mode : str, optional\n            Whether to prepend or append zeros to signal, by default \"after\"\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with padding applied.\n        \"\"\"\n        if mode == \"before\":\n            self.zero_pad(max(length - self.signal_length, 0), 0)\n        elif mode == \"after\":\n            self.zero_pad(0, max(length - self.signal_length, 0))\n        return self\n\n    def trim(self, before: int, after: int):\n        \"\"\"Trims the audio_data tensor before and after.\n\n        Parameters\n        ----------\n        before : int\n            How many samples to trim from beginning.\n        after : int\n            How many samples to trim from end.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with trimming applied.\n        \"\"\"\n        if after == 0:\n            self.audio_data = self.audio_data[..., before:]\n        else:\n            self.audio_data = self.audio_data[..., before:-after]\n        return self\n\n    def truncate_samples(self, length_in_samples: int):\n        \"\"\"Truncate signal to specified length.\n\n        Parameters\n        ----------\n        length_in_samples : int\n            Truncate to this many samples.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with truncation applied.\n        \"\"\"\n        self.audio_data = self.audio_data[..., :length_in_samples]\n        return self\n\n    @property\n    def device(self):\n        \"\"\"Get device that AudioSignal is on.\n\n        Returns\n        -------\n        paddle.device\n            Device that AudioSignal is on.\n        \"\"\"\n        if self.audio_data is not None:\n            device = self.audio_data.place\n        elif self.stft_data is not None:\n            device = self.stft_data.place\n        return device\n\n    # Properties\n    @property\n    def audio_data(self):\n        \"\"\"Returns the audio data tensor in the object.\n\n        Audio data is always of the shape\n        (batch_size, num_channels, num_samples). If value has less\n        than 3 dims (e.g. is (num_channels, num_samples)), then it will\n        be reshaped to (1, num_channels, num_samples) - a batch size of 1.\n\n        Parameters\n        ----------\n        data : typing.Union[paddle.Tensor, np.ndarray]\n            Audio data to set.\n\n        Returns\n        -------\n        paddle.Tensor\n            Audio samples.\n        \"\"\"\n        return self._audio_data\n\n    @audio_data.setter\n    def audio_data(self, data: typing.Union[paddle.Tensor, np.ndarray]):\n        if data is not None:\n            assert paddle.is_tensor(data), \"audio_data should be paddle.Tensor\"\n            assert data.ndim == 3, \"audio_data should be 3-dim (B, C, T)\"\n        self._audio_data = data\n        # Old loudness value not guaranteed to be right, reset it.\n        self._loudness = None\n        return\n\n    # alias for audio_data\n    samples = audio_data\n\n    @property\n    def stft_data(self):\n        \"\"\"Returns the STFT data inside the signal. Shape is\n        (batch, channels, frequencies, time).\n\n        Returns\n        -------\n        paddle.Tensor\n            Complex spectrogram data.\n        \"\"\"\n        return self._stft_data\n\n    @stft_data.setter\n    def stft_data(self, data: typing.Union[paddle.Tensor, np.ndarray]):\n        if data is not None:\n            assert paddle.is_tensor(data) and paddle.is_complex(data)\n            if self.stft_data is not None and self.stft_data.shape != data.shape:\n                warnings.warn(\"stft_data changed shape\")\n        self._stft_data = data\n        return\n\n    @property\n    def batch_size(self):\n        \"\"\"Batch size of audio signal.\n\n        Returns\n        -------\n        int\n            Batch size of signal.\n        \"\"\"\n        return self.audio_data.shape[0]\n\n    @property\n    def signal_length(self):\n        \"\"\"Length of audio signal.\n\n        Returns\n        -------\n        int\n            Length of signal in samples.\n        \"\"\"\n        return self.audio_data.shape[-1]\n\n    # alias for signal_length\n    length = signal_length\n\n    @property\n    def shape(self):\n        \"\"\"Shape of audio data.\n\n        Returns\n        -------\n        tuple\n            Shape of audio data.\n        \"\"\"\n        return self.audio_data.shape\n\n    @property\n    def signal_duration(self):\n        \"\"\"Length of audio signal in seconds.\n\n        Returns\n        -------\n        float\n            Length of signal in seconds.\n        \"\"\"\n        return self.signal_length / self.sample_rate\n\n    # alias for signal_duration\n    duration = signal_duration\n\n    @property\n    def num_channels(self):\n        \"\"\"Number of audio channels.\n\n        Returns\n        -------\n        int\n            Number of audio channels.\n        \"\"\"\n        return self.audio_data.shape[1]\n\n    # STFT\n    @staticmethod\n    @functools.lru_cache(None)\n    def get_window(window_type: str, window_length: int, device: str=None):\n        \"\"\"Wrapper around scipy.signal.get_window so one can also get the\n        popular sqrt-hann window. This function caches for efficiency\n        using functools.lru\\_cache.\n\n        Parameters\n        ----------\n        window_type : str\n            Type of window to get\n        window_length : int\n            Length of the window\n        device : str\n            Device to put window onto.\n\n        Returns\n        -------\n        paddle.Tensor\n            Window returned by scipy.signal.get_window, as a tensor.\n        \"\"\"\n        from scipy import signal\n\n        if window_type == \"average\":\n            window = np.ones(window_length) / window_length\n        elif window_type == \"sqrt_hann\":\n            window = np.sqrt(signal.get_window(\"hann\", window_length))\n        else:\n            window = signal.get_window(window_type, window_length)\n        window = paddle.to_tensor(window).astype(\"float32\")\n        return window\n\n    @property\n    def stft_params(self):\n        \"\"\"Returns STFTParams object, which can be re-used to other\n        AudioSignals.\n\n        This property can be set as well. If values are not defined in STFTParams,\n        they are inferred automatically from the signal properties. The default is to use\n        32ms windows, with 8ms hop length, and the square root of the hann window.\n\n        Returns\n        -------\n        STFTParams\n            STFT parameters for the AudioSignal.\n\n        Examples\n        --------\n        >>> stft_params = STFTParams(128, 32)\n        >>> signal1 = AudioSignal(paddle.randn([44100]), 44100, stft_params=stft_params)\n        >>> signal2 = AudioSignal(paddle.randn([44100]), 44100, stft_params=signal1.stft_params)\n        >>> signal1.stft_params = STFTParams() # Defaults\n        \"\"\"\n        return self._stft_params\n\n    @stft_params.setter\n    def stft_params(self, value: STFTParams):\n        # \n        default_win_len = int(2**(np.ceil(np.log2(0.032 * self.sample_rate))))\n        default_hop_len = default_win_len // 4\n        default_win_type = \"hann\"\n        default_match_stride = False\n        default_padding_type = \"reflect\"\n\n        default_stft_params = STFTParams(\n            window_length=default_win_len,\n            hop_length=default_hop_len,\n            window_type=default_win_type,\n            match_stride=default_match_stride,\n            padding_type=default_padding_type, )._asdict()\n\n        value = value._asdict() if value else default_stft_params\n\n        for key in default_stft_params:\n            if value[key] is None:\n                value[key] = default_stft_params[key]\n\n        self._stft_params = STFTParams(**value)\n        self.stft_data = None\n\n    def compute_stft_padding(self,\n                             window_length: int,\n                             hop_length: int,\n                             match_stride: bool):\n        \"\"\"Compute how the STFT should be padded, based on match\\_stride.\n\n        Parameters\n        ----------\n        window_length : int\n            Window length of STFT.\n        hop_length : int\n            Hop length of STFT.\n        match_stride : bool\n            Whether or not to match stride, making the STFT have the same alignment as\n            convolutional layers.\n\n        Returns\n        -------\n        tuple\n            Amount to pad on either side of audio.\n        \"\"\"\n        length = self.signal_length\n\n        if match_stride:\n            assert hop_length == window_length // 4, \"For match_stride, hop must equal n_fft // 4\"\n            right_pad = math.ceil(length / hop_length) * hop_length - length\n            pad = (window_length - hop_length) // 2\n        else:\n            right_pad = 0\n            pad = 0\n\n        return right_pad, pad\n\n    def stft(\n            self,\n            window_length: int=None,\n            hop_length: int=None,\n            window_type: str=None,\n            match_stride: bool=None,\n            padding_type: str=None, ):\n        \"\"\"Computes the short-time Fourier transform of the audio data,\n        with specified STFT parameters.\n\n        Parameters\n        ----------\n        window_length : int, optional\n            Window length of STFT, by default ``0.032 * self.sample_rate``.\n        hop_length : int, optional\n            Hop length of STFT, by default ``window_length // 4``.\n        window_type : str, optional\n            Type of window to use, by default ``sqrt\\_hann``.\n        match_stride : bool, optional\n            Whether to match the stride of convolutional layers, by default False\n        padding_type : str, optional\n            Type of padding to use, by default 'reflect'\n\n        Returns\n        -------\n        paddle.Tensor\n            STFT of audio data.\n\n        Examples\n        --------\n        Compute the STFT of an AudioSignal:\n\n        >>> signal = AudioSignal(paddle.randn([44100]), 44100)\n        >>> signal.stft()\n\n        Vary the window and hop length:\n\n        >>> stft_params_list = [STFTParams(128, 32), STFTParams(512, 128)]\n        >>> for stft_params in stft_params_list:\n        >>>     signal.stft_params = stft_params\n        >>>     signal.stft()\n\n        \"\"\"\n        window_length = self.stft_params.window_length if window_length is None else int(\n            window_length)\n        hop_length = self.stft_params.hop_length if hop_length is None else int(\n            hop_length)\n        window_type = self.stft_params.window_type if window_type is None else window_type\n        match_stride = self.stft_params.match_stride if match_stride is None else match_stride\n        padding_type = self.stft_params.padding_type if padding_type is None else padding_type\n\n        window = self.get_window(window_type, window_length)\n\n        audio_data = self.audio_data\n        right_pad, pad = self.compute_stft_padding(window_length, hop_length,\n                                                   match_stride)\n        audio_data = paddle.nn.functional.pad(\n            x=audio_data,\n            pad=[pad, pad + right_pad],\n            mode=\"reflect\",\n            data_format=\"NCL\", )\n        stft_data = paddle.signal.stft(\n            audio_data.reshape([-1, audio_data.shape[-1]]).astype(\"float32\"),\n            n_fft=window_length,\n            hop_length=hop_length,\n            window=window,\n            # return_complex=True,\n            center=True, )\n        _, nf, nt = stft_data.shape\n        stft_data = stft_data.reshape(\n            [self.batch_size, self.num_channels, nf, nt])\n\n        if match_stride:\n            # Drop first two and last two frames, which are added\n            # because of padding. Now num_frames * hop_length = num_samples.\n            stft_data = stft_data[..., 2:-2]\n        self.stft_data = stft_data\n\n        return stft_data\n\n    def istft(\n            self,\n            window_length: int=None,\n            hop_length: int=None,\n            window_type: str=None,\n            match_stride: bool=None,\n            length: int=None, ):\n        \"\"\"Computes inverse STFT and sets it to audio\\_data.\n\n        Parameters\n        ----------\n        window_length : int, optional\n            Window length of STFT, by default ``0.032 * self.sample_rate``.\n        hop_length : int, optional\n            Hop length of STFT, by default ``window_length // 4``.\n        window_type : str, optional\n            Type of window to use, by default ``sqrt\\_hann``.\n        match_stride : bool, optional\n            Whether to match the stride of convolutional layers, by default False\n        length : int, optional\n            Original length of signal, by default None\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with istft applied.\n\n        Raises\n        ------\n        RuntimeError\n            Raises an error if stft was not called prior to istft on the signal,\n            or if stft_data is not set.\n        \"\"\"\n        if self.stft_data is None:\n            raise RuntimeError(\"Cannot do inverse STFT without self.stft_data!\")\n\n        window_length = self.stft_params.window_length if window_length is None else int(\n            window_length)\n        hop_length = self.stft_params.hop_length if hop_length is None else int(\n            hop_length)\n        window_type = self.stft_params.window_type if window_type is None else window_type\n        match_stride = self.stft_params.match_stride if match_stride is None else match_stride\n\n        window = self.get_window(window_type, window_length,\n                                 self.stft_data.place)\n\n        nb, nch, nf, nt = self.stft_data.shape\n        stft_data = self.stft_data.reshape([nb * nch, nf, nt])\n        right_pad, pad = self.compute_stft_padding(window_length, hop_length,\n                                                   match_stride)\n\n        if length is None:\n            length = self.original_signal_length\n            length = length + 2 * pad + right_pad\n\n        if match_stride:\n            # Zero-pad the STFT on either side, putting back the frames that were\n            # dropped in stft().\n            stft_data = paddle.nn.functional.pad(\n                stft_data, pad=(2, 2), data_format=\"NCL\")\n\n        audio_data = paddle.signal.istft(\n            stft_data,\n            n_fft=window_length,\n            hop_length=hop_length,\n            window=window,\n            length=length,\n            center=True, )\n        audio_data = audio_data.reshape([nb, nch, -1])\n        if match_stride:\n            audio_data = audio_data[..., pad:-(pad + right_pad)]\n        self.audio_data = audio_data\n\n        return self\n\n    @staticmethod\n    @functools.lru_cache(None)\n    def get_mel_filters(sr: int,\n                        n_fft: int,\n                        n_mels: int,\n                        fmin: float=0.0,\n                        fmax: float=None):\n        \"\"\"Create a Filterbank matrix to combine FFT bins into Mel-frequency bins.\n\n        Parameters\n        ----------\n        sr : int\n            Sample rate of audio\n        n_fft : int\n            Number of FFT bins\n        n_mels : int\n            Number of mels\n        fmin : float, optional\n            Lowest frequency, in Hz, by default 0.0\n        fmax : float, optional\n            Highest frequency, by default None\n\n        Returns\n        -------\n        np.ndarray [shape=(n_mels, 1 + n_fft/2)]\n            Mel transform matrix\n        \"\"\"\n        from librosa.filters import mel as librosa_mel_fn\n\n        return librosa_mel_fn(\n            sr=sr,\n            n_fft=n_fft,\n            n_mels=n_mels,\n            fmin=fmin,\n            fmax=fmax, )\n\n    def mel_spectrogram(\n            self,\n            n_mels: int=80,\n            mel_fmin: float=0.0,\n            mel_fmax: float=None,\n            **kwargs, ):\n        \"\"\"Computes a Mel spectrogram.\n\n        Parameters\n        ----------\n        n_mels : int, optional\n            Number of mels, by default 80\n        mel_fmin : float, optional\n            Lowest frequency, in Hz, by default 0.0\n        mel_fmax : float, optional\n            Highest frequency, by default None\n        kwargs : dict, optional\n            Keyword arguments to self.stft().\n\n        Returns\n        -------\n        paddle.Tensor [shape=(batch, channels, mels, time)]\n            Mel spectrogram.\n        \"\"\"\n        # from paddle.audio.compliance.librosa import melspectrogram\n        # # from ..compliance.librosa import melspectrogram\n        # return melspectrogram(\n        #     x=self.audio_data,\n        #     sr=self.sample_rate,\n        #     window_size: int=512,\n        #     hop_length: int=320,\n        #     n_mels: int=64,\n        #     fmin: float=50.0,\n        #     fmax: Optional[float]=None,\n        #     window: str='hann',\n        #     center: bool=True,\n        #     pad_mode: str='reflect',\n        #     power: float=2.0,\n        #     to_db: bool=True,\n        #     ref: float=1.0,\n        #     amin: float=1e-10,\n        #     top_db: Optional[float]=None\n        # )\n\n        stft = self.stft(**kwargs)\n        magnitude = paddle.abs(stft)\n\n        nf = magnitude.shape[2]\n        mel_basis = self.get_mel_filters(\n            sr=self.sample_rate,\n            n_fft=2 * (nf - 1),\n            n_mels=n_mels,\n            fmin=mel_fmin,\n            fmax=mel_fmax, )\n        mel_basis = paddle.to_tensor(mel_basis)\n\n        mel_spectrogram = magnitude.transpose([0, 1, 3, 2]) @ mel_basis.T\n        mel_spectrogram = mel_spectrogram.transpose([0, 1, 3, 2])\n        return mel_spectrogram\n\n    @staticmethod\n    @functools.lru_cache(None)\n    def get_dct(n_mfcc: int, n_mels: int, norm: str=\"ortho\", device: str=None):\n        \"\"\"Create a discrete cosine transform (DCT) transformation matrix with shape (``n_mels``, ``n_mfcc``),\n        it can be normalized depending on norm. For more information about dct:\n        http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-II\n\n        Parameters\n        ----------\n        n_mfcc : int\n            Number of mfccs\n        n_mels : int\n            Number of mels\n        norm   : str\n            Use \"ortho\" to get a orthogonal matrix or None, by default \"ortho\"\n        device : str, optional\n            Device to load the transformation matrix on, by default None\n\n        Returns\n        -------\n        paddle.Tensor [shape=(n_mels, n_mfcc)] T\n            The dct transformation matrix.\n        \"\"\"\n\n        return create_dct(n_mfcc, n_mels, norm)\n\n    def mfcc(\n            self,\n            n_mfcc: int=40,\n            n_mels: int=80,\n            log_offset: float=1e-6,\n            **kwargs, ):\n        \"\"\"Computes mel-frequency cepstral coefficients (MFCCs).\n\n        Parameters\n        ----------\n        n_mfcc : int, optional\n            Number of mels, by default 40\n        n_mels : int, optional\n            Number of mels, by default 80\n        log_offset: float, optional\n            Small value to prevent numerical issues when trying to compute log(0), by default 1e-6\n        kwargs : dict, optional\n            Keyword arguments to self.mel_spectrogram(), note that some of them will be used for self.stft()\n\n        Returns\n        -------\n        paddle.Tensor [shape=(batch, channels, mfccs, time)]\n            MFCCs.\n        \"\"\"\n\n        # from paddle.audio.compliance.librosa import mfcc\n        # return mfcc(self.audio_data, self.sample_rate, n_mfcc=n_mfcc, n_mels=n_mels)\n\n        mel_spectrogram = self.mel_spectrogram(n_mels, **kwargs)\n        mel_spectrogram = paddle.log(mel_spectrogram + log_offset)\n        dct_mat = self.get_dct(n_mfcc, n_mels, \"ortho\", self.device)\n\n        mfcc = mel_spectrogram.transpose([0, 1, 3, 2]) @ dct_mat\n        mfcc = mfcc.transpose([0, 1, 3, 2])\n        return mfcc\n\n    @property\n    def magnitude(self):\n        \"\"\"Computes and returns the absolute value of the STFT, which\n        is the magnitude. This value can also be set to some tensor.\n        When set, ``self.stft_data`` is manipulated so that its magnitude\n        matches what this is set to, and modulated by the phase.\n\n        Returns\n        -------\n        paddle.Tensor\n            Magnitude of STFT.\n\n        Examples\n        --------\n        >>> signal = AudioSignal(paddle.randn([44100]), 44100)\n        >>> magnitude = signal.magnitude # Computes stft if not computed\n        >>> magnitude[magnitude < magnitude.mean()] = 0\n        >>> signal.magnitude = magnitude\n        >>> signal.istft()\n        \"\"\"\n        if self.stft_data is None:\n            self.stft()\n        return paddle.abs(self.stft_data)\n\n    @magnitude.setter\n    def magnitude(self, value):\n        self.stft_data = value * util.exp_compat(1j * self.phase)\n        return\n\n    def log_magnitude(self,\n                      ref_value: float=1.0,\n                      amin: float=1e-5,\n                      top_db: float=80.0):\n        \"\"\"Computes the log-magnitude of the spectrogram.\n\n        Parameters\n        ----------\n        ref_value : float, optional\n            The magnitude is scaled relative to ``ref``: ``20 * log10(S / ref)``.\n            Zeros in the output correspond to positions where ``S == ref``,\n            by default 1.0\n        amin : float, optional\n            Minimum threshold for ``S`` and ``ref``, by default 1e-5\n        top_db : float, optional\n            Threshold the output at ``top_db`` below the peak:\n            ``max(10 * log10(S/ref)) - top_db``, by default -80.0\n\n        Returns\n        -------\n        paddle.Tensor\n            Log-magnitude spectrogram\n        \"\"\"\n        magnitude = self.magnitude\n\n        amin = amin**2\n        log_spec = 10.0 * paddle.log10(magnitude.pow(2).clip(min=amin))\n        if paddle.is_tensor(ref_value):\n            ref_value = ref_value.item()\n        log_spec -= 10.0 * np.log10(np.maximum(amin, ref_value))\n\n        if top_db is not None:\n            log_spec = paddle.maximum(log_spec, log_spec.max() - top_db)\n        return log_spec\n\n    @property\n    def phase(self):\n        \"\"\"Computes and returns the phase of the STFT.\n        This value can also be set to some tensor.\n        When set, ``self.stft_data`` is manipulated so that its phase\n        matches what this is set to, we original magnitudeith th.\n\n        Returns\n        -------\n        paddle.Tensor\n            Phase of STFT.\n\n        Examples\n        --------\n        >>> signal = AudioSignal(paddle.randn([44100]), 44100)\n        >>> phase = signal.phase # Computes stft if not computed\n        >>> phase[phase < phase.mean()] = 0\n        >>> signal.phase = phase\n        >>> signal.istft()\n        \"\"\"\n        if self.stft_data is None:\n            self.stft()\n        return paddle.angle(self.stft_data)\n\n    @phase.setter\n    def phase(self, value):\n        # \n        self.stft_data = self.magnitude * util.exp_compat(1j * value)\n        return\n\n    # Operator overloading\n    def __add__(self, other):\n        new_signal = self.clone()\n        new_signal.audio_data += util._get_value(other)\n        return new_signal\n\n    def __iadd__(self, other):\n        self.audio_data += util._get_value(other)\n        return self\n\n    def __radd__(self, other):\n        return self + other\n\n    def __sub__(self, other):\n        new_signal = self.clone()\n        new_signal.audio_data -= util._get_value(other)\n        return new_signal\n\n    def __isub__(self, other):\n        self.audio_data -= util._get_value(other)\n        return self\n\n    def __mul__(self, other):\n        new_signal = self.clone()\n        new_signal.audio_data *= util._get_value(other)\n        return new_signal\n\n    def __imul__(self, other):\n        self.audio_data *= util._get_value(other)\n        return self\n\n    def __rmul__(self, other):\n        return self * other\n\n    # Representation\n    def _info(self):\n        # \n        dur = f\"{self.signal_duration:0.3f}\" if self.signal_duration else \"[unknown]\"\n        info = {\n            \"duration\":\n            f\"{dur} seconds\",\n            \"batch_size\":\n            self.batch_size,\n            \"path\":\n            self.path_to_file if self.path_to_file else \"path unknown\",\n            \"sample_rate\":\n            self.sample_rate,\n            \"num_channels\": (self.num_channels\n                             if self.num_channels else \"[unknown]\"),\n            \"audio_data.shape\":\n            self.audio_data.shape,\n            \"stft_params\":\n            self.stft_params,\n            \"device\":\n            self.device,\n        }\n\n        return info\n\n    def markdown(self):\n        \"\"\"Produces a markdown representation of AudioSignal, in a markdown table.\n\n        Returns\n        -------\n        str\n            Markdown representation of AudioSignal.\n\n        Examples\n        --------\n        >>> signal = AudioSignal(paddle.randn([44100]), 44100)\n        >>> print(signal.markdown())\n        | Key | Value\n        |---|---\n        | duration | 1.000 seconds |\n        | batch_size | 1 |\n        | path | path unknown |\n        | sample_rate | 44100 |\n        | num_channels | 1 |\n        | audio_data.shape | paddle.Size([1, 1, 44100]) |\n        | stft_params | STFTParams(window_length=2048, hop_length=512, window_type='sqrt_hann', match_stride=False) |\n        | device | cpu |\n        \"\"\"\n        info = self._info()\n\n        FORMAT = \"| Key | Value \\n\" \"|---|--- \\n\"\n        for k, v in info.items():\n            row = f\"| {k} | {v} |\\n\"\n            FORMAT += row\n        return FORMAT\n\n    def __str__(self):\n        info = self._info()\n\n        desc = \"\"\n        for k, v in info.items():\n            desc += f\"{k}: {v}\\n\"\n        return desc\n\n    def __rich__(self):\n        from rich.table import Table\n\n        info = self._info()\n\n        table = Table(title=f\"{self.__class__.__name__}\")\n        table.add_column(\"Key\", style=\"green\")\n        table.add_column(\"Value\", style=\"cyan\")\n\n        for k, v in info.items():\n            table.add_row(k, str(v))\n        return table\n\n    # Comparison\n    def __eq__(self, other):\n        for k, v in list(self.__dict__.items()):\n            if paddle.is_tensor(v):\n\n                if paddle.is_complex(v):\n                    if not np.allclose(\n                            v.cpu().numpy(),\n                            other.__dict__[k].cpu().numpy(),\n                            atol=1e-6):\n                        max_error = (v - other.__dict__[k]).abs().max()\n                        print(f\"Max abs error for {k}: {max_error}\")\n                        return False\n                else:\n                    if not paddle.allclose(v, other.__dict__[k], atol=1e-6):\n                        max_error = (v - other.__dict__[k]).abs().max()\n                        print(f\"Max abs error for {k}: {max_error}\")\n                        return False\n        return True\n\n    # Indexing\n    def __getitem__(self, key):\n        if paddle.is_tensor(key) and key.ndim == 0 and key.item() is True:\n            assert self.batch_size == 1\n            audio_data = self.audio_data\n            _loudness = self._loudness\n            stft_data = self.stft_data\n\n        elif isinstance(key, (bool, int, list, slice, tuple)) or (\n                paddle.is_tensor(key) and key.ndim <= 1):\n            # Indexing only on the batch dimension.\n            # Then let's copy over relevant stuff.\n            # Future work: make this work for time-indexing\n            # as well, using the hop length.\n            audio_data = self.audio_data[key]\n            _loudness = self._loudness[\n                key] if self._loudness is not None else None\n            # stft_data = self.stft_data[\n            #     key] if self.stft_data is not None else None\n            stft_data = util.bool_index_compat(\n                self.stft_data, key) if self.stft_data is not None else None\n\n        sources = None\n\n        copy = type(self)(\n            audio_data, self.sample_rate, stft_params=self.stft_params)\n        copy._loudness = _loudness\n        copy._stft_data = stft_data\n        copy.sources = sources\n\n        return copy\n\n    def __setitem__(self, key, value):\n        if not isinstance(value, type(self)):\n            self.audio_data[key] = value\n            return\n\n        if paddle.is_tensor(key) and key.ndim == 0 and key.item() is True:\n            assert self.batch_size == 1\n            self.audio_data = value.audio_data\n            self._loudness = value._loudness\n            self.stft_data = value.stft_data\n            return\n\n        elif isinstance(key, (bool, int, list, slice, tuple)) or (\n                paddle.is_tensor(key) and key.ndim <= 1):\n            if self.audio_data is not None and value.audio_data is not None:\n                self.audio_data[key] = value.audio_data\n            if self._loudness is not None and value._loudness is not None:\n                if paddle.is_tensor(key) and key.dtype == paddle.bool:\n                    # FOR Paddle BOOL Index\n                    _key_no_bool = paddle.nonzero(key).flatten()\n                    self._loudness[_key_no_bool] = value._loudness\n                else:\n                    self._loudness[key] = value._loudness\n            if self.stft_data is not None and value.stft_data is not None:\n                # self.stft_data[key] = value.stft_data\n                self.stft_data = util.bool_setitem_compat(self.stft_data, key,\n                                                          value.stft_data)\n            return\n\n    def __ne__(self, other):\n        return not self == other\n"
  },
  {
    "path": "paddlespeech/audiotools/core/display.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/display.py)\nimport inspect\nimport typing\nfrom functools import wraps\n\nfrom . import util\n\n\ndef format_figure(func):\n    \"\"\"Decorator for formatting figures produced by the code below.\n    See :py:func:`audiotools.core.util.format_figure` for more.\n\n    Parameters\n    ----------\n    func : Callable\n        Plotting function that is decorated by this function.\n\n    \"\"\"\n\n    @wraps(func)\n    def wrapper(*args, **kwargs):\n        f_keys = inspect.signature(util.format_figure).parameters.keys()\n        f_kwargs = {}\n        for k, v in list(kwargs.items()):\n            if k in f_keys:\n                kwargs.pop(k)\n                f_kwargs[k] = v\n        func(*args, **kwargs)\n        util.format_figure(**f_kwargs)\n\n    return wrapper\n\n\nclass DisplayMixin:\n    @format_figure\n    def specshow(\n            self,\n            preemphasis: bool=False,\n            x_axis: str=\"time\",\n            y_axis: str=\"linear\",\n            n_mels: int=128,\n            **kwargs, ):\n        \"\"\"Displays a spectrogram, using ``librosa.display.specshow``.\n\n        Parameters\n        ----------\n        preemphasis : bool, optional\n            Whether or not to apply preemphasis, which makes high\n            frequency detail easier to see, by default False\n        x_axis : str, optional\n            How to label the x axis, by default \"time\"\n        y_axis : str, optional\n            How to label the y axis, by default \"linear\"\n        n_mels : int, optional\n            If displaying a mel spectrogram with ``y_axis = \"mel\"``,\n            this controls the number of mels, by default 128.\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.util.format_figure`.\n        \"\"\"\n        import librosa\n        import librosa.display\n\n        # Always re-compute the STFT data before showing it, in case\n        # it changed.\n        signal = self.clone()\n        signal.stft_data = None\n\n        if preemphasis:\n            signal.preemphasis()\n\n        ref = signal.magnitude.max()\n        log_mag = signal.log_magnitude(ref_value=ref)\n\n        if y_axis == \"mel\":\n            log_mag = 20 * signal.mel_spectrogram(n_mels).clip(1e-5).log10()\n            log_mag -= log_mag.max()\n\n        librosa.display.specshow(\n            log_mag.numpy()[0].mean(axis=0),\n            x_axis=x_axis,\n            y_axis=y_axis,\n            sr=signal.sample_rate,\n            **kwargs, )\n\n    @format_figure\n    def waveplot(self, x_axis: str=\"time\", **kwargs):\n        \"\"\"Displays a waveform plot, using ``librosa.display.waveshow``.\n\n        Parameters\n        ----------\n        x_axis : str, optional\n            How to label the x axis, by default \"time\"\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.util.format_figure`.\n        \"\"\"\n        import librosa\n        import librosa.display\n\n        audio_data = self.audio_data[0].mean(axis=0)\n        audio_data = audio_data.cpu().numpy()\n\n        plot_fn = \"waveshow\" if hasattr(librosa.display,\n                                        \"waveshow\") else \"waveplot\"\n        wave_plot_fn = getattr(librosa.display, plot_fn)\n        wave_plot_fn(audio_data, x_axis=x_axis, sr=self.sample_rate, **kwargs)\n\n    @format_figure\n    def wavespec(self, x_axis: str=\"time\", **kwargs):\n        \"\"\"Displays a waveform plot, using ``librosa.display.waveshow``.\n\n        Parameters\n        ----------\n        x_axis : str, optional\n            How to label the x axis, by default \"time\"\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.display.DisplayMixin.specshow`.\n        \"\"\"\n        import matplotlib.pyplot as plt\n        from matplotlib.gridspec import GridSpec\n\n        gs = GridSpec(6, 1)\n        plt.subplot(gs[0, :])\n        self.waveplot(x_axis=x_axis)\n        plt.subplot(gs[1:, :])\n        self.specshow(x_axis=x_axis, **kwargs)\n\n    def write_audio_to_tb(\n            self,\n            tag: str,\n            writer,\n            step: int=None,\n            plot_fn: typing.Union[typing.Callable, str]=\"specshow\",\n            **kwargs, ):\n        \"\"\"Writes a signal and its spectrogram to Tensorboard. Will show up\n        under the Audio and Images tab in Tensorboard.\n\n        Parameters\n        ----------\n        tag : str\n            Tag to write signal to (e.g. ``clean/sample_0.wav``). The image will be\n            written to the corresponding ``.png`` file (e.g. ``clean/sample_0.png``).\n        writer : SummaryWriter\n            A SummaryWriter object from PyTorch library.\n        step : int, optional\n            The step to write the signal to, by default None\n        plot_fn : typing.Union[typing.Callable, str], optional\n            How to create the image. Set to ``None`` to avoid plotting, by default \"specshow\"\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.display.DisplayMixin.specshow` or\n            whatever ``plot_fn`` is set to.\n        \"\"\"\n        import matplotlib.pyplot as plt\n\n        audio_data = self.audio_data[0, 0].detach().cpu().numpy()\n        sample_rate = self.sample_rate\n        writer.add_audio(tag, audio_data, step, sample_rate)\n\n        if plot_fn is not None:\n            if isinstance(plot_fn, str):\n                plot_fn = getattr(self, plot_fn)\n            fig = plt.figure()\n            plt.clf()\n            plot_fn(**kwargs)\n            writer.add_figure(tag.replace(\"wav\", \"png\"), fig, step)\n\n    def save_image(\n            self,\n            image_path: str,\n            plot_fn: typing.Union[typing.Callable, str]=\"specshow\",\n            **kwargs, ):\n        \"\"\"Save AudioSignal spectrogram (or whatever ``plot_fn`` is set to) to\n        a specified file.\n\n        Parameters\n        ----------\n        image_path : str\n            Where to save the file to.\n        plot_fn : typing.Union[typing.Callable, str], optional\n            How to create the image. Set to ``None`` to avoid plotting, by default \"specshow\"\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.display.DisplayMixin.specshow` or\n            whatever ``plot_fn`` is set to.\n        \"\"\"\n        import matplotlib.pyplot as plt\n\n        if isinstance(plot_fn, str):\n            plot_fn = getattr(self, plot_fn)\n\n        plt.clf()\n        plot_fn(**kwargs)\n        plt.savefig(image_path, bbox_inches=\"tight\", pad_inches=0)\n        plt.close()\n"
  },
  {
    "path": "paddlespeech/audiotools/core/dsp.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/dsp.py)\nimport typing\n\nimport numpy as np\nimport paddle\n\nfrom . import _julius\nfrom . import util\n\n\ndef _unfold(x, kernel_sizes, strides):\n    # https://github.com/PaddlePaddle/Paddle/pull/70102\n\n    if 1 == kernel_sizes[0]:\n        x_zeros = paddle.zeros_like(x)\n        x = paddle.concat([x, x_zeros], axis=2)\n\n        kernel_sizes = [2, kernel_sizes[1]]\n        strides = list(strides)\n\n    unfolded = paddle.nn.functional.unfold(\n        x,\n        kernel_sizes=kernel_sizes,\n        strides=strides, )\n    if 2 == kernel_sizes[0]:\n        unfolded = unfolded[:, :kernel_sizes[1]]\n    return unfolded\n\n\ndef _fold(x, output_sizes, kernel_sizes, strides):\n    # https://github.com/PaddlePaddle/Paddle/pull/70102\n\n    if 1 == output_sizes[0] and 1 == kernel_sizes[0]:\n        x_zeros = paddle.zeros_like(x)\n        x = paddle.concat([x, x_zeros], axis=1)\n\n        output_sizes = (2, output_sizes[1])\n        kernel_sizes = (2, kernel_sizes[1])\n\n    fold = paddle.nn.functional.fold(\n        x,\n        output_sizes=output_sizes,\n        kernel_sizes=kernel_sizes,\n        strides=strides, )\n    if 2 == kernel_sizes[0]:\n        fold = fold[:, :, :1]\n    return fold\n\n\nclass DSPMixin:\n    _original_batch_size = None\n    _original_num_channels = None\n    _padded_signal_length = None\n\n    def _preprocess_signal_for_windowing(self, window_duration, hop_duration):\n        self._original_batch_size = self.batch_size\n        self._original_num_channels = self.num_channels\n\n        window_length = int(window_duration * self.sample_rate)\n        hop_length = int(hop_duration * self.sample_rate)\n\n        if window_length % hop_length != 0:\n            factor = window_length // hop_length\n            window_length = factor * hop_length\n\n        self.zero_pad(hop_length, hop_length)\n        self._padded_signal_length = self.signal_length\n\n        return window_length, hop_length\n\n    def windows(self,\n                window_duration: float,\n                hop_duration: float,\n                preprocess: bool=True):\n        \"\"\"Generator which yields windows of specified duration from signal with a specified\n        hop length.\n\n        Parameters\n        ----------\n        window_duration : float\n            Duration of every window in seconds.\n        hop_duration : float\n            Hop between windows in seconds.\n        preprocess : bool, optional\n            Whether to preprocess the signal, so that the first sample is in\n            the middle of the first window, by default True\n\n        Yields\n        ------\n        AudioSignal\n            Each window is returned as an AudioSignal.\n        \"\"\"\n        if preprocess:\n            window_length, hop_length = self._preprocess_signal_for_windowing(\n                window_duration, hop_duration)\n\n        self.audio_data = self.audio_data.reshape([-1, 1, self.signal_length])\n\n        for b in range(self.batch_size):\n            i = 0\n            start_idx = i * hop_length\n            while True:\n                start_idx = i * hop_length\n                i += 1\n                end_idx = start_idx + window_length\n                if end_idx > self.signal_length:\n                    break\n                yield self[b, ..., start_idx:end_idx]\n\n    def collect_windows(self,\n                        window_duration: float,\n                        hop_duration: float,\n                        preprocess: bool=True):\n        \"\"\"Reshapes signal into windows of specified duration from signal with a specified\n        hop length. Window are placed along the batch dimension. Use with\n        :py:func:`audiotools.core.dsp.DSPMixin.overlap_and_add` to reconstruct the\n        original signal.\n\n        Parameters\n        ----------\n        window_duration : float\n            Duration of every window in seconds.\n        hop_duration : float\n            Hop between windows in seconds.\n        preprocess : bool, optional\n            Whether to preprocess the signal, so that the first sample is in\n            the middle of the first window, by default True\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal unfolded with shape ``(nb * nch * num_windows, 1, window_length)``\n        \"\"\"\n        if preprocess:\n            window_length, hop_length = self._preprocess_signal_for_windowing(\n                window_duration, hop_duration)\n\n        # self.audio_data: (nb, nch, nt).\n        # unfolded = paddle.nn.functional.unfold(\n        #     self.audio_data.reshape([-1, 1, 1, self.signal_length]),\n        #     kernel_sizes=(1, window_length),\n        #     strides=(1, hop_length),\n        # )\n        unfolded = _unfold(\n            self.audio_data.reshape([-1, 1, 1, self.signal_length]),\n            kernel_sizes=(1, window_length),\n            strides=(1, hop_length), )\n        # unfolded: (nb * nch, window_length, num_windows).\n        # -> (nb * nch * num_windows, 1, window_length)\n        unfolded = unfolded.transpose([0, 2, 1]).reshape([-1, 1, window_length])\n        self.audio_data = unfolded\n        return self\n\n    def overlap_and_add(self, hop_duration: float):\n        \"\"\"Function which takes a list of windows and overlap adds them into a\n        signal the same length as ``audio_signal``.\n\n        Parameters\n        ----------\n        hop_duration : float\n            How much to shift for each window\n            (overlap is window_duration - hop_duration) in seconds.\n\n        Returns\n        -------\n        AudioSignal\n            overlap-and-added signal.\n        \"\"\"\n        hop_length = int(hop_duration * self.sample_rate)\n        window_length = self.signal_length\n\n        nb, nch = self._original_batch_size, self._original_num_channels\n\n        unfolded = self.audio_data.reshape(\n            [nb * nch, -1, window_length]).transpose([0, 2, 1])\n        # folded = paddle.nn.functional.fold(\n        #     unfolded,\n        #     output_sizes=(1, self._padded_signal_length),\n        #     kernel_sizes=(1, window_length),\n        #     strides=(1, hop_length),\n        # )\n        folded = _fold(\n            unfolded,\n            output_sizes=(1, self._padded_signal_length),\n            kernel_sizes=(1, window_length),\n            strides=(1, hop_length), )\n\n        norm = paddle.ones_like(unfolded)\n        # norm = paddle.nn.functional.fold(\n        #     norm,\n        #     output_sizes=(1, self._padded_signal_length),\n        #     kernel_sizes=(1, window_length),\n        #     strides=(1, hop_length),\n        # )\n        norm = _fold(\n            norm,\n            output_sizes=(1, self._padded_signal_length),\n            kernel_sizes=(1, window_length),\n            strides=(1, hop_length), )\n\n        folded = folded / norm\n\n        folded = folded.reshape([nb, nch, -1])\n        self.audio_data = folded\n        self.trim(hop_length, hop_length)\n        return self\n\n    def low_pass(self,\n                 cutoffs: typing.Union[paddle.Tensor, np.ndarray, float],\n                 zeros: int=51):\n        \"\"\"Low-passes the signal in-place. Each item in the batch\n        can have a different low-pass cutoff, if the input\n        to this signal is an array or tensor. If a float, all\n        items are given the same low-pass filter.\n\n        Parameters\n        ----------\n        cutoffs : typing.Union[paddle.Tensor, np.ndarray, float]\n            Cutoff in Hz of low-pass filter.\n        zeros : int, optional\n            Number of taps to use in low-pass filter, by default 51\n\n        Returns\n        -------\n        AudioSignal\n            Low-passed AudioSignal.\n        \"\"\"\n        cutoffs = util.ensure_tensor(cutoffs, 2, self.batch_size)\n        cutoffs = cutoffs / self.sample_rate\n        filtered = paddle.empty_like(self.audio_data)\n\n        for i, cutoff in enumerate(cutoffs):\n            lp_filter = _julius.LowPassFilter(cutoff.cpu(), zeros=zeros)\n            filtered[i] = lp_filter(self.audio_data[i])\n\n        self.audio_data = filtered\n        self.stft_data = None\n        return self\n\n    def high_pass(self,\n                  cutoffs: typing.Union[paddle.Tensor, np.ndarray, float],\n                  zeros: int=51):\n        \"\"\"High-passes the signal in-place. Each item in the batch\n        can have a different high-pass cutoff, if the input\n        to this signal is an array or tensor. If a float, all\n        items are given the same high-pass filter.\n\n        Parameters\n        ----------\n        cutoffs : typing.Union[paddle.Tensor, np.ndarray, float]\n            Cutoff in Hz of high-pass filter.\n        zeros : int, optional\n            Number of taps to use in high-pass filter, by default 51\n\n        Returns\n        -------\n        AudioSignal\n            High-passed AudioSignal.\n        \"\"\"\n        cutoffs = util.ensure_tensor(cutoffs, 2, self.batch_size)\n        cutoffs = cutoffs / self.sample_rate\n        filtered = paddle.empty_like(self.audio_data)\n\n        for i, cutoff in enumerate(cutoffs):\n            hp_filter = _julius.HighPassFilter(cutoff.cpu(), zeros=zeros)\n            filtered[i] = hp_filter(self.audio_data[i])\n\n        self.audio_data = filtered\n        self.stft_data = None\n        return self\n\n    def mask_frequencies(\n            self,\n            fmin_hz: typing.Union[paddle.Tensor, np.ndarray, float],\n            fmax_hz: typing.Union[paddle.Tensor, np.ndarray, float],\n            val: float=0.0, ):\n        \"\"\"Masks frequencies between ``fmin_hz`` and ``fmax_hz``, and fills them\n        with the value specified by ``val``. Useful for implementing SpecAug.\n        The min and max can be different for every item in the batch.\n\n        Parameters\n        ----------\n        fmin_hz : typing.Union[paddle.Tensor, np.ndarray, float]\n            Lower end of band to mask out.\n        fmax_hz : typing.Union[paddle.Tensor, np.ndarray, float]\n            Upper end of band to mask out.\n        val : float, optional\n            Value to fill in, by default 0.0\n\n        Returns\n        -------\n        AudioSignal\n            Signal with ``stft_data`` manipulated. Apply ``.istft()`` to get the\n            masked audio data.\n        \"\"\"\n        # SpecAug\n        mag, phase = self.magnitude, self.phase\n        fmin_hz = util.ensure_tensor(\n            fmin_hz,\n            ndim=mag.ndim, )\n        fmax_hz = util.ensure_tensor(\n            fmax_hz,\n            ndim=mag.ndim, )\n        assert paddle.all(fmin_hz < fmax_hz)\n\n        # build mask\n        nbins = mag.shape[-2]\n        bins_hz = paddle.linspace(\n            0,\n            self.sample_rate / 2,\n            nbins, )\n        bins_hz = bins_hz[None, None, :, None].tile(\n            [self.batch_size, 1, 1, mag.shape[-1]])\n\n        fmin_hz, fmax_hz = fmin_hz.astype(bins_hz.dtype), fmax_hz.astype(\n            bins_hz.dtype)\n        mask = (fmin_hz <= bins_hz) & (bins_hz < fmax_hz)\n\n        mag = paddle.where(mask, paddle.full_like(mag, val), mag)\n        phase = paddle.where(mask, paddle.full_like(phase, val), phase)\n        self.stft_data = mag * util.exp_compat(1j * phase)\n        return self\n\n    def mask_timesteps(\n            self,\n            tmin_s: typing.Union[paddle.Tensor, np.ndarray, float],\n            tmax_s: typing.Union[paddle.Tensor, np.ndarray, float],\n            val: float=0.0, ):\n        \"\"\"Masks timesteps between ``tmin_s`` and ``tmax_s``, and fills them\n        with the value specified by ``val``. Useful for implementing SpecAug.\n        The min and max can be different for every item in the batch.\n\n        Parameters\n        ----------\n        tmin_s : typing.Union[paddle.Tensor, np.ndarray, float]\n            Lower end of timesteps to mask out.\n        tmax_s : typing.Union[paddle.Tensor, np.ndarray, float]\n            Upper end of timesteps to mask out.\n        val : float, optional\n            Value to fill in, by default 0.0\n\n        Returns\n        -------\n        AudioSignal\n            Signal with ``stft_data`` manipulated. Apply ``.istft()`` to get the\n            masked audio data.\n        \"\"\"\n        # SpecAug\n        mag, phase = self.magnitude, self.phase\n        tmin_s = util.ensure_tensor(tmin_s, ndim=mag.ndim)\n        tmax_s = util.ensure_tensor(tmax_s, ndim=mag.ndim)\n\n        assert paddle.all(tmin_s < tmax_s)\n\n        # build mask\n        nt = mag.shape[-1]\n        bins_t = paddle.linspace(\n            0,\n            self.signal_duration,\n            nt, )\n        bins_t = bins_t[None, None, None, :].tile(\n            [self.batch_size, 1, mag.shape[-2], 1])\n        mask = (tmin_s <= bins_t) & (bins_t < tmax_s)\n\n        # mag = mag.masked_fill(mask, val)\n        # phase = phase.masked_fill(mask, val)\n        mag = paddle.where(mask, paddle.full_like(mag, val), mag)\n        phase = paddle.where(mask, paddle.full_like(phase, val), phase)\n\n        self.stft_data = mag * util.exp_compat(1j * phase)\n        return self\n\n    def mask_low_magnitudes(\n            self,\n            db_cutoff: typing.Union[paddle.Tensor, np.ndarray, float],\n            val: float=0.0):\n        \"\"\"Mask away magnitudes below a specified threshold, which\n        can be different for every item in the batch.\n\n        Parameters\n        ----------\n        db_cutoff : typing.Union[paddle.Tensor, np.ndarray, float]\n            Decibel value for which things below it will be masked away.\n        val : float, optional\n            Value to fill in for masked portions, by default 0.0\n\n        Returns\n        -------\n        AudioSignal\n            Signal with ``stft_data`` manipulated. Apply ``.istft()`` to get the\n            masked audio data.\n        \"\"\"\n        mag = self.magnitude\n        log_mag = self.log_magnitude()\n\n        db_cutoff = util.ensure_tensor(db_cutoff, ndim=mag.ndim)\n        db_cutoff = db_cutoff.astype(log_mag.dtype)\n        mask = log_mag < db_cutoff\n        # mag = mag.masked_fill(mask, val)\n        mag = paddle.where(mask, mag, val * paddle.ones_like(mag))\n\n        self.magnitude = mag\n        return self\n\n    def shift_phase(self,\n                    shift: typing.Union[paddle.Tensor, np.ndarray, float]):\n        \"\"\"Shifts the phase by a constant value.\n\n        Parameters\n        ----------\n        shift : typing.Union[paddle.Tensor, np.ndarray, float]\n            What to shift the phase by.\n\n        Returns\n        -------\n        AudioSignal\n            Signal with ``stft_data`` manipulated. Apply ``.istft()`` to get the\n            masked audio data.\n        \"\"\"\n        shift = util.ensure_tensor(shift, ndim=self.phase.ndim)\n        shift = shift.astype(self.phase.dtype)\n        self.phase = self.phase + shift\n        return self\n\n    def corrupt_phase(self,\n                      scale: typing.Union[paddle.Tensor, np.ndarray, float]):\n        \"\"\"Corrupts the phase randomly by some scaled value.\n\n        Parameters\n        ----------\n        scale : typing.Union[paddle.Tensor, np.ndarray, float]\n            Standard deviation of noise to add to the phase.\n\n        Returns\n        -------\n        AudioSignal\n            Signal with ``stft_data`` manipulated. Apply ``.istft()`` to get the\n            masked audio data.\n        \"\"\"\n        scale = util.ensure_tensor(scale, ndim=self.phase.ndim)\n        self.phase = self.phase + scale * paddle.randn(\n            shape=self.phase.shape, dtype=self.phase.dtype)\n        return self\n\n    def preemphasis(self, coef: float=0.85):\n        \"\"\"Applies pre-emphasis to audio signal.\n\n        Parameters\n        ----------\n        coef : float, optional\n            How much pre-emphasis to apply, lower values do less. 0 does nothing.\n            by default 0.85\n\n        Returns\n        -------\n        AudioSignal\n            Pre-emphasized signal.\n        \"\"\"\n        kernel = paddle.to_tensor([1, -coef, 0]).reshape([1, 1, -1])\n        x = self.audio_data.reshape([-1, 1, self.signal_length])\n        x = paddle.nn.functional.conv1d(\n            x.astype(kernel.dtype), kernel, padding=1)\n        self.audio_data = x.reshape(self.audio_data.shape)\n        return self\n"
  },
  {
    "path": "paddlespeech/audiotools/core/effects.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/effects.py)\nimport typing\n\nimport numpy as np\nimport paddle\n\nfrom . import util\nfrom ._julius import SplitBands\n\n\nclass EffectMixin:\n    GAIN_FACTOR = np.log(10) / 20\n    \"\"\"Gain factor for converting between amplitude and decibels.\"\"\"\n    CODEC_PRESETS = {\n        \"8-bit\": {\n            \"format\": \"wav\",\n            \"encoding\": \"ULAW\",\n            \"bits_per_sample\": 8\n        },\n        \"GSM-FR\": {\n            \"format\": \"gsm\"\n        },\n        \"MP3\": {\n            \"format\": \"mp3\",\n            \"compression\": -9\n        },\n        \"Vorbis\": {\n            \"format\": \"vorbis\",\n            \"compression\": -1\n        },\n        \"Ogg\": {\n            \"format\": \"ogg\",\n            \"compression\": -1,\n        },\n        \"Amr-nb\": {\n            \"format\": \"amr-nb\"\n        },\n    }\n    \"\"\"Presets for applying codecs via torchaudio.\"\"\"\n\n    def mix(\n            self,\n            other,\n            snr: typing.Union[paddle.Tensor, np.ndarray, float]=10,\n            other_eq: typing.Union[paddle.Tensor, np.ndarray]=None, ):\n        \"\"\"Mixes noise with signal at specified\n        signal-to-noise ratio. Optionally, the\n        other signal can be equalized in-place.\n\n\n        Parameters\n        ----------\n        other : AudioSignal\n            AudioSignal object to mix with.\n        snr : typing.Union[paddle.Tensor, np.ndarray, float], optional\n            Signal to noise ratio, by default 10\n        other_eq : typing.Union[paddle.Tensor, np.ndarray], optional\n            EQ curve to apply to other signal, if any, by default None\n\n        Returns\n        -------\n        AudioSignal\n            In-place modification of AudioSignal.\n        \"\"\"\n        snr = util.ensure_tensor(snr)\n\n        pad_len = max(0, self.signal_length - other.signal_length)\n        other.zero_pad(0, pad_len)\n        other.truncate_samples(self.signal_length)\n        if other_eq is not None:\n            other = other.equalizer(other_eq)\n\n        tgt_loudness = self.loudness() - snr\n        other = other.normalize(tgt_loudness)\n\n        self.audio_data = self.audio_data + other.audio_data\n        return self\n\n    def convolve(self, other, start_at_max: bool=True):\n        \"\"\"Convolves self with other.\n        This function uses FFTs to do the convolution.\n\n        Parameters\n        ----------\n        other : AudioSignal\n            Signal to convolve with.\n        start_at_max : bool, optional\n            Whether to start at the max value of other signal, to\n            avoid inducing delays, by default True\n\n        Returns\n        -------\n        AudioSignal\n            Convolved signal, in-place.\n        \"\"\"\n        from . import AudioSignal\n\n        pad_len = self.signal_length - other.signal_length\n\n        if pad_len > 0:\n            other.zero_pad(0, pad_len)\n        else:\n            other.truncate_samples(self.signal_length)\n\n        if start_at_max:\n            # Use roll to rotate over the max for every item\n            # so that the impulse responses don't induce any\n            # delay.\n            idx = paddle.argmax(paddle.abs(other.audio_data), axis=-1)\n            irs = paddle.zeros_like(other.audio_data)\n            for i in range(other.batch_size):\n                irs[i] = paddle.roll(\n                    other.audio_data[i], shifts=-idx[i].item(), axis=-1)\n            other = AudioSignal(irs, other.sample_rate)\n\n        delta = paddle.zeros_like(other.audio_data)\n        delta[..., 0] = 1\n\n        length = self.signal_length\n        delta_fft = paddle.fft.rfft(delta, n=length)\n        other_fft = paddle.fft.rfft(other.audio_data, n=length)\n        self_fft = paddle.fft.rfft(self.audio_data, n=length)\n\n        convolved_fft = other_fft * self_fft\n        convolved_audio = paddle.fft.irfft(convolved_fft, n=length)\n\n        delta_convolved_fft = other_fft * delta_fft\n        delta_audio = paddle.fft.irfft(delta_convolved_fft, n=length)\n\n        # Use the delta to rescale the audio exactly as needed.\n        delta_max = paddle.max(paddle.abs(delta_audio), axis=-1, keepdim=True)\n        scale = 1 / paddle.clip(delta_max, min=1e-5)\n        convolved_audio = convolved_audio * scale\n\n        self.audio_data = convolved_audio\n\n        return self\n\n    def apply_ir(\n            self,\n            ir,\n            drr: typing.Union[paddle.Tensor, np.ndarray, float]=None,\n            ir_eq: typing.Union[paddle.Tensor, np.ndarray]=None,\n            use_original_phase: bool=False, ):\n        \"\"\"Applies an impulse response to the signal. If ` is`ir_eq``\n        is specified, the impulse response is equalized before\n        it is applied, using the given curve.\n\n        Parameters\n        ----------\n        ir : AudioSignal\n            Impulse response to convolve with.\n        drr : typing.Union[paddle.Tensor, np.ndarray, float], optional\n            Direct-to-reverberant ratio that impulse response will be\n            altered to, if specified, by default None\n        ir_eq : typing.Union[paddle.Tensor, np.ndarray], optional\n            Equalization that will be applied to impulse response\n            if specified, by default None\n        use_original_phase : bool, optional\n            Whether to use the original phase, instead of the convolved\n            phase, by default False\n\n        Returns\n        -------\n        AudioSignal\n            Signal with impulse response applied to it\n        \"\"\"\n        if ir_eq is not None:\n            ir = ir.equalizer(ir_eq)\n        if drr is not None:\n            ir = ir.alter_drr(drr)\n\n        # Save the peak before\n        max_spk = self.audio_data.abs().max(axis=-1, keepdim=True)\n\n        # Augment the impulse response to simulate microphone effects\n        # and with varying direct-to-reverberant ratio.\n        phase = self.phase\n        self.convolve(ir)\n\n        # Use the input phase\n        if use_original_phase:\n            self.stft()\n            self.stft_data = self.magnitude * util.exp_compat(1j * phase)\n            self.istft()\n\n        # Rescale to the input's amplitude\n        max_transformed = self.audio_data.abs().max(axis=-1, keepdim=True)\n        scale_factor = max_spk.clip(1e-8) / max_transformed.clip(1e-8)\n        self = self * scale_factor\n\n        return self\n\n    def ensure_max_of_audio(self, _max: float=1.0):\n        \"\"\"Ensures that ``abs(audio_data) <= max``.\n\n        Parameters\n        ----------\n        max : float, optional\n            Max absolute value of signal, by default 1.0\n\n        Returns\n        -------\n        AudioSignal\n            Signal with values scaled between -max and max.\n        \"\"\"\n        peak = self.audio_data.abs().max(axis=-1, keepdim=True)\n        peak_gain = paddle.ones_like(peak)\n        # peak_gain[peak > _max] = _max / peak[peak > _max]\n        peak_gain = paddle.where(peak > _max, _max / peak, peak_gain)\n        self.audio_data = self.audio_data * peak_gain\n        return self\n\n    def normalize(self,\n                  db: typing.Union[paddle.Tensor, np.ndarray, float]=-24.0):\n        \"\"\"Normalizes the signal's volume to the specified db, in LUFS.\n        This is GPU-compatible, making for very fast loudness normalization.\n\n        Parameters\n        ----------\n        db : typing.Union[paddle.Tensor, np.ndarray, float], optional\n            Loudness to normalize to, by default -24.0\n\n        Returns\n        -------\n        AudioSignal\n            Normalized audio signal.\n        \"\"\"\n        db = util.ensure_tensor(db)\n        ref_db = self.loudness()\n        gain = db.astype(ref_db.dtype) - ref_db\n        gain = util.exp_compat(gain * self.GAIN_FACTOR)\n\n        self.audio_data = self.audio_data * gain[:, None, None]\n        return self\n\n    def volume_change(self, db: typing.Union[paddle.Tensor, np.ndarray, float]):\n        \"\"\"Change volume of signal by some amount, in dB.\n\n        Parameters\n        ----------\n        db : typing.Union[paddle.Tensor, np.ndarray, float]\n            Amount to change volume by.\n\n        Returns\n        -------\n        AudioSignal\n            Signal at new volume.\n        \"\"\"\n        db = util.ensure_tensor(db, ndim=1)\n        gain = util.exp_compat(db * self.GAIN_FACTOR)\n        self.audio_data = self.audio_data * gain[:, None, None]\n        return self\n\n    def mel_filterbank(self, n_bands: int):\n        \"\"\"Breaks signal into mel bands.\n\n        Parameters\n        ----------\n        n_bands : int\n            Number of mel bands to use.\n\n        Returns\n        -------\n        paddle.Tensor\n            Mel-filtered bands, with last axis being the band index.\n        \"\"\"\n        filterbank = SplitBands(self.sample_rate, n_bands)\n        filtered = filterbank(self.audio_data)\n        return filtered.transpose([1, 2, 3, 0])\n\n    def equalizer(self, db: typing.Union[paddle.Tensor, np.ndarray]):\n        \"\"\"Applies a mel-spaced equalizer to the audio signal.\n\n        Parameters\n        ----------\n        db : typing.Union[paddle.Tensor, np.ndarray]\n            EQ curve to apply.\n\n        Returns\n        -------\n        AudioSignal\n            AudioSignal with equalization applied.\n        \"\"\"\n        db = util.ensure_tensor(db)\n        n_bands = db.shape[-1]\n        fbank = self.mel_filterbank(n_bands)\n\n        # If there's a batch dimension, make sure it's the same.\n        if db.ndim == 2:\n            if db.shape[0] != 1:\n                assert db.shape[0] == fbank.shape[0]\n        else:\n            db = db.unsqueeze(0)\n\n        weights = (10**db).astype(\"float32\")\n        fbank = fbank * weights[:, None, None, :]\n        eq_audio_data = fbank.sum(-1)\n        self.audio_data = eq_audio_data\n        return self\n\n    def clip_distortion(\n            self,\n            clip_percentile: typing.Union[paddle.Tensor, np.ndarray, float]):\n        \"\"\"Clips the signal at a given percentile. The higher it is,\n        the lower the threshold for clipping.\n\n        Parameters\n        ----------\n        clip_percentile : typing.Union[paddle.Tensor, np.ndarray, float]\n            Values are between 0.0 to 1.0. Typical values are 0.1 or below.\n\n        Returns\n        -------\n        AudioSignal\n            Audio signal with clipped audio data.\n        \"\"\"\n        clip_percentile = util.ensure_tensor(clip_percentile, ndim=1)\n        clip_percentile = clip_percentile.cpu().numpy()\n        min_thresh = paddle.quantile(\n            self.audio_data, (clip_percentile / 2).tolist(), axis=-1)[None]\n        max_thresh = paddle.quantile(\n            self.audio_data, (1 - clip_percentile / 2).tolist(), axis=-1)[None]\n\n        nc = self.audio_data.shape[1]\n        min_thresh = min_thresh[:, :nc, :]\n        max_thresh = max_thresh[:, :nc, :]\n\n        self.audio_data = self.audio_data.clip(min_thresh, max_thresh)\n\n        return self\n\n    def quantization(self,\n                     quantization_channels: typing.Union[paddle.Tensor,\n                                                         np.ndarray, int]):\n        \"\"\"Applies quantization to the input waveform.\n\n        Parameters\n        ----------\n        quantization_channels : typing.Union[paddle.Tensor, np.ndarray, int]\n            Number of evenly spaced quantization channels to quantize\n            to.\n\n        Returns\n        -------\n        AudioSignal\n            Quantized AudioSignal.\n        \"\"\"\n        quantization_channels = util.ensure_tensor(\n            quantization_channels, ndim=3)\n\n        x = self.audio_data\n        quantization_channels = quantization_channels.astype(x.dtype)\n        x = (x + 1) / 2\n        x = x * quantization_channels\n        x = x.floor()\n        x = x / quantization_channels\n        x = 2 * x - 1\n\n        residual = (self.audio_data - x).detach()\n        self.audio_data = self.audio_data - residual\n        return self\n\n    def mulaw_quantization(self,\n                           quantization_channels: typing.Union[\n                               paddle.Tensor, np.ndarray, int]):\n        \"\"\"Applies mu-law quantization to the input waveform.\n\n        Parameters\n        ----------\n        quantization_channels : typing.Union[paddle.Tensor, np.ndarray, int]\n            Number of mu-law spaced quantization channels to quantize\n            to.\n\n        Returns\n        -------\n        AudioSignal\n            Quantized AudioSignal.\n        \"\"\"\n        mu = quantization_channels - 1.0\n        mu = util.ensure_tensor(mu, ndim=3)\n\n        x = self.audio_data\n\n        # quantize\n        x = paddle.sign(x) * paddle.log1p(mu * paddle.abs(x)) / paddle.log1p(mu)\n        x = ((x + 1) / 2 * mu + 0.5).astype(\"int64\")\n\n        # unquantize\n        x = (x.astype(mu.dtype) / mu) * 2 - 1.0\n        x = paddle.sign(x) * (\n            util.exp_compat(paddle.abs(x) * paddle.log1p(mu)) - 1.0) / mu\n\n        residual = (self.audio_data - x).detach()\n        self.audio_data = self.audio_data - residual\n        return self\n\n    def __matmul__(self, other):\n        return self.convolve(other)\n\n\nclass ImpulseResponseMixin:\n    \"\"\"These functions are generally only used with AudioSignals that are derived\n    from impulse responses, not other sources like music or speech. These methods\n    are used to replicate the data augmentation described in [1].\n\n    1.  Bryan, Nicholas J. \"Impulse response data augmentation and deep\n        neural networks for blind room acoustic parameter estimation.\"\n        ICASSP 2020-2020 IEEE International Conference on Acoustics,\n        Speech and Signal Processing (ICASSP). IEEE, 2020.\n    \"\"\"\n\n    def decompose_ir(self):\n        \"\"\"Decomposes an impulse response into early and late\n        field responses.\n        \"\"\"\n        # Equations 1 and 2\n        # -----------------\n        # Breaking up into early\n        # response + late field response.\n\n        td = paddle.argmax(self.audio_data, axis=-1, keepdim=True)\n        t0 = int(self.sample_rate * 0.0025)\n\n        idx = paddle.arange(self.audio_data.shape[-1])[None, None, :]\n        idx = idx.expand([self.batch_size, -1, -1])\n        early_idx = (idx >= td - t0) * (idx <= td + t0)\n\n        early_response = paddle.zeros_like(self.audio_data)\n\n        # early_response[early_idx] = self.audio_data[early_idx]\n        early_response = paddle.where(early_idx, self.audio_data,\n                                      early_response)\n\n        late_idx = ~early_idx\n        late_field = paddle.zeros_like(self.audio_data)\n        # late_field[late_idx] = self.audio_data[late_idx]\n        late_field = paddle.where(late_idx, self.audio_data, late_field)\n\n        # Equation 4\n        # ----------\n        # Decompose early response into windowed\n        # direct path and windowed residual.\n\n        window = paddle.zeros_like(self.audio_data)\n        window_idx = paddle.nonzero(early_idx)\n        for idx in range(self.batch_size):\n            # window_idx = early_idx[idx, 0]\n\n            # ----- Just for this -----\n            # window[idx, ..., window_idx] = self.get_window(\"hann\", window_idx.sum().item())\n            # indices = paddle.nonzero(window_idx).reshape(\n            #     [-1])  # shape: [num_true], dtype: int64  \n            indices = window_idx[window_idx[:, 0] == idx][:, -1]\n\n            temp_window = self.get_window(\"hann\", indices.shape[0])\n\n            window_slice = window[idx, 0]\n            updated_window_slice = paddle.scatter(\n                window_slice, index=indices, updates=temp_window)\n\n            window[idx, 0] = updated_window_slice\n            # ----- Just for that -----\n\n        return early_response, late_field, window\n\n    def measure_drr(self):\n        \"\"\"Measures the direct-to-reverberant ratio of the impulse\n        response.\n\n        Returns\n        -------\n        float\n            Direct-to-reverberant ratio\n        \"\"\"\n        early_response, late_field, _ = self.decompose_ir()\n        num = (early_response**2).sum(axis=-1)\n        den = (late_field**2).sum(axis=-1)\n        drr = 10 * paddle.log10(num / den)\n        return drr\n\n    @staticmethod\n    def solve_alpha(early_response, late_field, wd, target_drr):\n        \"\"\"Used to solve for the alpha value, which is used\n        to alter the drr.\n        \"\"\"\n        # Equation 5\n        # ----------\n        # Apply the good ol' quadratic formula.\n\n        wd_sq = wd**2\n        wd_sq_1 = (1 - wd)**2\n        e_sq = early_response**2\n        l_sq = late_field**2\n        a = (wd_sq * e_sq).sum(axis=-1)\n        b = (2 * (1 - wd) * wd * e_sq).sum(axis=-1)\n        c = (wd_sq_1 * e_sq).sum(axis=-1) - paddle.pow(10 * paddle.ones_like(\n            target_drr, dtype=\"float32\"), target_drr.cast(\"float32\") /\n                                                       10) * l_sq.sum(axis=-1)\n\n        expr = ((b**2) - 4 * a * c).sqrt()\n        alpha = paddle.maximum(\n            (-b - expr) / (2 * a),\n            (-b + expr) / (2 * a), )\n        return alpha\n\n    def alter_drr(self, drr: typing.Union[paddle.Tensor, np.ndarray, float]):\n        \"\"\"Alters the direct-to-reverberant ratio of the impulse response.\n\n        Parameters\n        ----------\n        drr : typing.Union[paddle.Tensor, np.ndarray, float]\n            Direct-to-reverberant ratio that impulse response will be\n            altered to, if specified, by default None\n\n        Returns\n        -------\n        AudioSignal\n            Altered impulse response.\n        \"\"\"\n        drr = util.ensure_tensor(\n            drr, 2, self.batch_size\n        )  # Assuming util.ensure_tensor is adapted or equivalent exists\n\n        early_response, late_field, window = self.decompose_ir()\n        alpha = self.solve_alpha(early_response, late_field, window, drr)\n        min_alpha = late_field.abs().max(axis=-1)[0] / early_response.abs().max(\n            axis=-1)[0]\n        alpha = paddle.maximum(alpha, min_alpha)[..., None]\n\n        aug_ir_data = alpha * window * early_response + (\n            (1 - window) * early_response) + late_field\n        self.audio_data = aug_ir_data\n        self.ensure_max_of_audio(\n        )  # Assuming ensure_max_of_audio is a method defined elsewhere\n        return self\n"
  },
  {
    "path": "paddlespeech/audiotools/core/ffmpeg.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/ffmpeg.py)\nimport json\nimport shlex\nimport subprocess\nimport tempfile\nfrom pathlib import Path\nfrom typing import Tuple\n\nimport ffmpy\nimport numpy as np\nimport paddle\n\n\ndef r128stats(filepath: str, quiet: bool):\n    \"\"\"Takes a path to an audio file, returns a dict with the loudness\n    stats computed by the ffmpeg ebur128 filter.\n\n    Parameters\n    ----------\n    filepath : str\n        Path to compute loudness stats on.\n    quiet : bool\n        Whether to show FFMPEG output during computation.\n\n    Returns\n    -------\n    dict\n        Dictionary containing loudness stats.\n    \"\"\"\n    ffargs = [\n        \"ffmpeg\",\n        \"-nostats\",\n        \"-i\",\n        filepath,\n        \"-filter_complex\",\n        \"ebur128\",\n        \"-f\",\n        \"null\",\n        \"-\",\n    ]\n    if quiet:\n        ffargs += [\"-hide_banner\"]\n    proc = subprocess.Popen(\n        ffargs, stderr=subprocess.PIPE, universal_newlines=True)\n    stats = proc.communicate()[1]\n    summary_index = stats.rfind(\"Summary:\")\n\n    summary_list = stats[summary_index:].split()\n    i_lufs = float(summary_list[summary_list.index(\"I:\") + 1])\n    i_thresh = float(summary_list[summary_list.index(\"I:\") + 4])\n    lra = float(summary_list[summary_list.index(\"LRA:\") + 1])\n    lra_thresh = float(summary_list[summary_list.index(\"LRA:\") + 4])\n    lra_low = float(summary_list[summary_list.index(\"low:\") + 1])\n    lra_high = float(summary_list[summary_list.index(\"high:\") + 1])\n    stats_dict = {\n        \"I\": i_lufs,\n        \"I Threshold\": i_thresh,\n        \"LRA\": lra,\n        \"LRA Threshold\": lra_thresh,\n        \"LRA Low\": lra_low,\n        \"LRA High\": lra_high,\n    }\n\n    return stats_dict\n\n\ndef ffprobe_offset_and_codec(path: str) -> Tuple[float, str]:\n    \"\"\"Given a path to a file, returns the start time offset and codec of\n    the first audio stream.\n    \"\"\"\n    ff = ffmpy.FFprobe(\n        inputs={path: None},\n        global_options=\"-show_entries format=start_time:stream=duration,start_time,codec_type,codec_name,start_pts,time_base -of json -v quiet\",\n    )\n    streams = json.loads(ff.run(stdout=subprocess.PIPE)[0])[\"streams\"]\n    seconds_offset = 0.0\n    codec = None\n\n    # Get the offset and codec of the first audio stream we find\n    # and return its start time, if it has one.\n    for stream in streams:\n        if stream[\"codec_type\"] == \"audio\":\n            seconds_offset = stream.get(\"start_time\", 0.0)\n            codec = stream.get(\"codec_name\")\n            break\n    return float(seconds_offset), codec\n\n\nclass FFMPEGMixin:\n    _loudness = None\n\n    def ffmpeg_loudness(self, quiet: bool=True):\n        \"\"\"Computes loudness of audio file using FFMPEG.\n\n        Parameters\n        ----------\n        quiet : bool, optional\n            Whether to show FFMPEG output during computation,\n            by default True\n\n        Returns\n        -------\n        paddle.Tensor\n            Loudness of every item in the batch, computed via\n            FFMPEG.\n        \"\"\"\n        loudness = []\n\n        with tempfile.NamedTemporaryFile(suffix=\".wav\") as f:\n            for i in range(self.batch_size):\n                self[i].write(f.name)\n                loudness_stats = r128stats(f.name, quiet=quiet)\n                loudness.append(loudness_stats[\"I\"])\n\n        self._loudness = paddle.to_tensor(np.array(loudness)).astype(\"float32\")\n        return self.loudness()\n"
  },
  {
    "path": "paddlespeech/audiotools/core/loudness.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/loudness.py)\nimport copy\nimport math\nimport typing\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nimport scipy\n\nfrom . import _julius\n\n\ndef _unfold1d(x, kernel_size, stride):\n    # https://github.com/PaddlePaddle/Paddle/pull/70102\n    \"\"\"1D only unfolding similar to the one from Paddlepaddle.\n\n    Given an _input tensor of size `[*, T]` this will return\n    a tensor `[*, F, K]` with `K` the kernel size, and `F` the number\n    of frames. The i-th frame is a view onto `i * stride: i * stride + kernel_size`.\n    This will automatically pad the _input to cover at least once all entries in `_input`.\n\n    Args:\n        _input (Tensor): tensor for which to return the frames.\n        kernel_size (int): size of each frame.\n        stride (int): stride between each frame.\n\n    Shape:\n\n        - Inputs: `_input` is `[*, T]`\n        - Output: `[*, F, kernel_size]` with `F = 1 + ceil((T - kernel_size) / stride)`\n    \"\"\"\n\n    if 3 != x.dim():\n        raise NotImplementedError\n\n    N, C, length = x.shape\n    x = x.reshape([N * C, 1, length])\n\n    n_frames = math.ceil((max(length, kernel_size) - kernel_size) / stride) + 1\n    tgt_length = (n_frames - 1) * stride + kernel_size\n    x = F.pad(x, (0, tgt_length - length), data_format=\"NCL\")\n\n    x = x.unsqueeze(-1)\n\n    unfolded = paddle.nn.functional.unfold(\n        x,\n        kernel_sizes=[kernel_size, 1],\n        strides=[stride, 1], )\n\n    unfolded = unfolded.transpose([0, 2, 1])\n    unfolded = unfolded.reshape([N, C, *unfolded.shape[1:]])\n    return unfolded\n\n\nclass Meter(paddle.nn.Layer):\n    \"\"\"Tensorized version of pyloudnorm.Meter. Works with batched audio tensors.\n\n    Parameters\n    ----------\n    rate : int\n        Sample rate of audio.\n    filter_class : str, optional\n        Class of weighting filter used.\n        K-weighting' (default), 'Fenton/Lee 1'\n        'Fenton/Lee 2', 'Dash et al.'\n        by default \"K-weighting\"\n    block_size : float, optional\n        Gating block size in seconds, by default 0.400\n    zeros : int, optional\n         Number of zeros to use in FIR approximation of\n         IIR filters, by default 512\n    use_fir : bool, optional\n        Whether to use FIR approximation or exact IIR formulation.\n        If computing on GPU, ``use_fir=True`` will be used, as its\n        much faster, by default False\n    \"\"\"\n\n    def __init__(\n            self,\n            rate: int,\n            filter_class: str=\"K-weighting\",\n            block_size: float=0.400,\n            zeros: int=512,\n            use_fir: bool=False, ):\n        super().__init__()\n\n        self.rate = rate\n        self.filter_class = filter_class\n        self.block_size = block_size\n        self.use_fir = use_fir\n\n        G = paddle.to_tensor(\n            np.array([1.0, 1.0, 1.0, 1.41, 1.41]), stop_gradient=True)\n        self.register_buffer(\"G\", G)\n\n        # Compute impulse responses so that filtering is fast via\n        # a convolution at runtime, on GPU, unlike lfilter.\n        impulse = np.zeros((zeros, ))\n        impulse[..., 0] = 1.0\n\n        firs = np.zeros((len(self._filters), 1, zeros))\n        # passband_gain = torch.zeros(len(self._filters))\n        passband_gain = paddle.zeros([len(self._filters)], dtype=\"float32\")\n\n        for i, (_, filter_stage) in enumerate(self._filters.items()):\n            firs[i] = scipy.signal.lfilter(filter_stage.b, filter_stage.a,\n                                           impulse)\n            passband_gain[i] = filter_stage.passband_gain\n\n        firs = paddle.to_tensor(\n            firs[..., ::-1].copy(), dtype=\"float32\", stop_gradient=True)\n\n        self.register_buffer(\"firs\", firs)\n        self.register_buffer(\"passband_gain\", passband_gain)\n\n    def apply_filter_gpu(self, data: paddle.Tensor):\n        \"\"\"Performs FIR approximation of loudness computation.\n\n        Parameters\n        ----------\n        data : paddle.Tensor\n            Audio data of shape (nb, nch, nt).\n\n        Returns\n        -------\n        paddle.Tensor\n            Filtered audio data.\n        \"\"\"\n        # Data is of shape (nb, nch, nt)\n        # Reshape to (nb*nch, 1, nt)\n        nb, nt, nch = data.shape\n        data = data.transpose([0, 2, 1])\n        data = data.reshape([nb * nch, 1, nt])\n\n        # Apply padding\n        pad_length = self.firs.shape[-1]\n\n        # Apply filtering in sequence\n        for i in range(self.firs.shape[0]):\n            data = F.pad(data, (pad_length, pad_length), data_format=\"NCL\")\n            data = _julius.fft_conv1d(data, self.firs[i, None, ...])\n            data = self.passband_gain[i] * data\n            data = data[..., 1:nt + 1]\n\n        data = data.transpose([0, 2, 1])\n        data = data[:, :nt, :]\n        return data\n\n    @staticmethod\n    def scipy_lfilter(waveform, a_coeffs, b_coeffs, clamp: bool=True):\n        # 使用 scipy.signal.lfilter 进行滤波（处理三维数据）\n        output = np.zeros_like(waveform)\n        for batch_idx in range(waveform.shape[0]):\n            for channel_idx in range(waveform.shape[2]):\n                output[batch_idx, :, channel_idx] = scipy.signal.lfilter(\n                    b_coeffs, a_coeffs, waveform[batch_idx, :, channel_idx])\n        return output\n\n    def apply_filter_cpu(self, data: paddle.Tensor):\n        \"\"\"Performs IIR formulation of loudness computation.\n\n        Parameters\n        ----------\n        data : paddle.Tensor\n            Audio data of shape (nb, nch, nt).\n\n        Returns\n        -------\n        paddle.Tensor\n            Filtered audio data.\n        \"\"\"\n        _data = data.cpu().numpy().copy()\n        for _, filter_stage in self._filters.items():\n            passband_gain = filter_stage.passband_gain\n\n            a_coeffs = filter_stage.a\n            b_coeffs = filter_stage.b\n\n            filtered = self.scipy_lfilter(_data, a_coeffs, b_coeffs)\n            _data[:] = passband_gain * filtered\n        data = paddle.to_tensor(_data)\n        return data\n\n    def apply_filter(self, data: paddle.Tensor):\n        \"\"\"Applies filter on either CPU or GPU, depending\n        on if the audio is on GPU or is on CPU, or if\n        ``self.use_fir`` is True.\n\n        Parameters\n        ----------\n        data : paddle.Tensor\n            Audio data of shape (nb, nch, nt).\n\n        Returns\n        -------\n        paddle.Tensor\n            Filtered audio data.\n        \"\"\"\n        # if data.place.is_gpu_place() or self.use_fir:\n        #     data = self.apply_filter_gpu(data)\n        # else:\n        #     data = self.apply_filter_cpu(data)\n        data = self.apply_filter_cpu(data)\n        return data\n\n    def forward(self, data: paddle.Tensor):\n        \"\"\"Computes integrated loudness of data.\n\n        Parameters\n        ----------\n        data : paddle.Tensor\n            Audio data of shape (nb, nch, nt).\n\n        Returns\n        -------\n        paddle.Tensor\n            Filtered audio data.\n        \"\"\"\n        return self.integrated_loudness(data)\n\n    def _unfold(self, input_data):\n        T_g = self.block_size\n        overlap = 0.75  # overlap of 75% of the block duration\n        step = 1.0 - overlap  # step size by percentage\n\n        kernel_size = int(T_g * self.rate)\n        stride = int(T_g * self.rate * step)\n        unfolded = _unfold1d(\n            input_data.transpose([0, 2, 1]), kernel_size, stride)\n        unfolded = unfolded.transpose([0, 1, 3, 2])\n\n        return unfolded\n\n    def integrated_loudness(self, data: paddle.Tensor):\n        \"\"\"Computes integrated loudness of data.\n\n        Parameters\n        ----------\n        data : paddle.Tensor\n            Audio data of shape (nb, nch, nt).\n\n        Returns\n        -------\n        paddle.Tensor\n            Filtered audio data.\n        \"\"\"\n        if not paddle.is_tensor(data):\n            data = paddle.to_tensor(data, dtype=\"float32\")\n        else:\n            data = data.astype(\"float32\")\n\n        input_data = data.clone()\n        # Data always has a batch and channel dimension.\n        # Is of shape (nb, nt, nch)\n        if input_data.ndim < 2:\n            input_data = input_data.unsqueeze(-1)\n        if input_data.ndim < 3:\n            input_data = input_data.unsqueeze(0)\n\n        nb, nt, nch = input_data.shape\n\n        # Apply frequency weighting filters - account\n        # for the acoustic respose of the head and auditory system\n        input_data = self.apply_filter(input_data)\n\n        G = self.G  # channel gains\n        T_g = self.block_size  # 400 ms gating block standard\n        Gamma_a = -70.0  # -70 LKFS = absolute loudness threshold\n\n        unfolded = self._unfold(input_data)\n\n        z = (1.0 / (T_g * self.rate)) * unfolded.square().sum(2)\n        l = -0.691 + 10.0 * paddle.log10(\n            (G[None, :nch, None] * z).sum(1, keepdim=True))\n        l = l.expand_as(z)\n\n        # find gating block indices above absolute threshold\n        z_avg_gated = z\n        z_avg_gated[l <= Gamma_a] = 0\n        masked = l > Gamma_a\n        z_avg_gated = z_avg_gated.sum(2) / masked.sum(2).astype(\"float32\")\n\n        # calculate the relative threshold value (see eq. 6)\n        Gamma_r = -0.691 + 10.0 * paddle.log10(\n            (z_avg_gated * G[None, :nch]).sum(-1)) - 10.0\n        Gamma_r = Gamma_r[:, None, None]\n        Gamma_r = Gamma_r.expand([nb, nch, l.shape[-1]])\n\n        # find gating block indices above relative and absolute thresholds  (end of eq. 7)\n        z_avg_gated = z\n        z_avg_gated[l <= Gamma_a] = 0\n        z_avg_gated[l <= Gamma_r] = 0\n        masked = (l > Gamma_a) * (l > Gamma_r)\n        z_avg_gated = z_avg_gated.sum(2) / (masked.sum(2) + 10e-6)\n\n        # TODO Currently, paddle has a segmentation fault bug in this section of the code\n        # z_avg_gated = paddle.nan_to_num(z_avg_gated)\n        # z_avg_gated = paddle.where(\n        #     paddle.isnan(z_avg_gated),\n        #     paddle.zeros_like(z_avg_gated), z_avg_gated)\n        z_avg_gated[z_avg_gated == float(\"inf\")] = float(\n            np.finfo(np.float32).max)\n        z_avg_gated[z_avg_gated == -float(\"inf\")] = float(\n            np.finfo(np.float32).min)\n\n        LUFS = -0.691 + 10.0 * paddle.log10(\n            (G[None, :nch] * z_avg_gated).sum(1))\n        return LUFS.astype(\"float32\")\n\n    @property\n    def filter_class(self):\n        return self._filter_class\n\n    @filter_class.setter\n    def filter_class(self, value):\n        from pyloudnorm import Meter\n\n        meter = Meter(self.rate)\n        meter.filter_class = value\n        self._filter_class = value\n        self._filters = meter._filters\n\n\nclass LoudnessMixin:\n    _loudness = None\n    MIN_LOUDNESS = -70\n    \"\"\"Minimum loudness possible.\"\"\"\n\n    def loudness(self,\n                 filter_class: str=\"K-weighting\",\n                 block_size: float=0.400,\n                 **kwargs):\n        \"\"\"Calculates loudness using an implementation of ITU-R BS.1770-4.\n        Allows control over gating block size and frequency weighting filters for\n        additional control. Measure the integrated gated loudness of a signal.\n\n        API is derived from PyLoudnorm, but this implementation is ported to PyTorch\n        and is tensorized across batches. When on GPU, an FIR approximation of the IIR\n        filters is used to compute loudness for speed.\n\n        Uses the weighting filters and block size defined by the meter\n        the integrated loudness is measured based upon the gating algorithm\n        defined in the ITU-R BS.1770-4 specification.\n\n        Parameters\n        ----------\n        filter_class : str, optional\n            Class of weighting filter used.\n            K-weighting' (default), 'Fenton/Lee 1'\n            'Fenton/Lee 2', 'Dash et al.'\n            by default \"K-weighting\"\n        block_size : float, optional\n            Gating block size in seconds, by default 0.400\n        kwargs : dict, optional\n            Keyword arguments to :py:func:`audiotools.core.loudness.Meter`.\n\n        Returns\n        -------\n        paddle.Tensor\n            Loudness of audio data.\n        \"\"\"\n        if self._loudness is not None:\n            return self._loudness  # .to(self.device)\n        original_length = self.signal_length\n        if self.signal_duration < 0.5:\n            pad_len = int((0.5 - self.signal_duration) * self.sample_rate)\n            self.zero_pad(0, pad_len)\n\n        # create BS.1770 meter\n        meter = Meter(\n            self.sample_rate,\n            filter_class=filter_class,\n            block_size=block_size,\n            **kwargs)\n        # meter = meter.to(self.device)\n        # measure loudness\n        loudness = meter.integrated_loudness(\n            self.audio_data.transpose([0, 2, 1]))\n        self.truncate_samples(original_length)\n        min_loudness = paddle.ones_like(loudness) * self.MIN_LOUDNESS\n        self._loudness = paddle.maximum(loudness, min_loudness)\n\n        return self._loudness  # .to(self.device)\n"
  },
  {
    "path": "paddlespeech/audiotools/core/util.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/core/util.py)\nimport collections\nimport csv\nimport glob\nimport math\nimport numbers\nimport os\nimport random\nimport typing\nfrom contextlib import contextmanager\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import NamedTuple\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Type\nfrom typing import Union\n\nimport ffmpeg\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile\nfrom flatten_dict import flatten\nfrom flatten_dict import unflatten\n\nfrom paddlespeech.utils import satisfy_paddle_version\nfrom paddlespeech.vector.training.seeding import seed_everything\n\n__all__ = [\n    \"exp_compat\",\n    \"bool_index_compat\",\n    \"bool_setitem_compat\",\n    \"Info\",\n    \"info\",\n    \"ensure_tensor\",\n    \"random_state\",\n    \"find_audio\",\n    \"read_sources\",\n    \"choose_from_list_of_lists\",\n    \"chdir\",\n    \"move_to_device\",\n    \"prepare_batch\",\n    \"sample_from_dist\",\n    \"format_figure\",\n    \"default_collate\",\n    \"collate\",\n    \"hz_to_bin\",\n    \"generate_chord_dataset\",\n]\n\n\ndef exp_compat(x):\n    \"\"\"\n    Compute the exponential of the input tensor `x`.\n\n    This function is designed to handle compatibility issues with PaddlePaddle versions below 2.6,\n    which do not support the `exp` operation for complex tensors. In such cases, the computation\n    is offloaded to NumPy.\n\n    Args:\n        x (paddle.Tensor): The input tensor for which to compute the exponential.\n\n    Returns:\n        paddle.Tensor: The result of the exponential operation, as a PaddlePaddle tensor.\n\n    Notes:\n        - If the PaddlePaddle version is 2.6 or above, the function uses `paddle.exp` directly.\n        - For versions below 2.6, the tensor is first converted to a NumPy array, the exponential\n          is computed using `np.exp`, and the result is then converted back to a PaddlePaddle tensor.\n    \"\"\"\n    if satisfy_paddle_version(\"2.6\"):\n        return paddle.exp(x)\n    else:\n        x_np = x.cpu().numpy()\n        return paddle.to_tensor(np.exp(x_np))\n\n\ndef bool_index_compat(x, mask):\n    \"\"\"\n    Perform boolean indexing on the input tensor `x` using the provided `mask`.\n\n    This function ensures compatibility with PaddlePaddle versions below 2.6, where boolean indexing\n    may not be fully supported. For older versions, the operation is performed using NumPy.\n\n    Args:\n        x (paddle.Tensor): The input tensor to be indexed.\n        mask (paddle.Tensor or int): The boolean mask or integer index used for indexing.\n\n    Returns:\n        paddle.Tensor: The result of the boolean indexing operation, as a PaddlePaddle tensor.\n\n    Notes:\n        - If the PaddlePaddle version is 2.6 or above, or if `mask` is an integer, the function uses\n          Paddle's native indexing directly.\n        - For versions below 2.6, the tensor and mask are converted to NumPy arrays, the indexing\n          operation is performed using NumPy, and the result is converted back to a PaddlePaddle tensor.\n    \"\"\"\n    if satisfy_paddle_version(\"2.6\") or isinstance(mask, (int, list, slice)):\n        return x[mask]\n    else:\n        x_np = x.cpu().numpy()[mask.cpu().numpy()]\n        return paddle.to_tensor(x_np)\n\n\ndef bool_setitem_compat(x, mask, y):\n    \"\"\"\n    Perform boolean assignment on the input tensor `x` using the provided `mask` and values `y`.\n\n    This function ensures compatibility with PaddlePaddle versions below 2.6, where boolean assignment\n    may not be fully supported. For older versions, the operation is performed using NumPy.\n\n    Args:\n        x (paddle.Tensor): The input tensor to be modified.\n        mask (paddle.Tensor): The boolean mask used for assignment.\n        y (paddle.Tensor): The values to assign to the selected elements of `x`.\n\n    Returns:\n        paddle.Tensor: The modified tensor after the assignment operation.\n\n    Notes:\n        - If the PaddlePaddle version is 2.6 or above, the function uses Paddle's native assignment directly.\n        - For versions below 2.6, the tensor, mask, and values are converted to NumPy arrays, the assignment\n          operation is performed using NumPy, and the result is converted back to a PaddlePaddle tensor.\n    \"\"\"\n    if satisfy_paddle_version(\"2.6\"):\n\n        x[mask] = y\n        return x\n    else:\n        x_np = x.cpu().numpy()\n        x_np[mask.cpu().numpy()] = y.cpu().numpy()\n\n        return paddle.to_tensor(x_np)\n\n\n@dataclass\nclass Info:\n\n    sample_rate: float\n    num_frames: int\n\n    @property\n    def duration(self) -> float:\n        return self.num_frames / self.sample_rate\n\n\ndef info_ffmpeg(audio_path: str):\n    \"\"\"\n    Parameters\n    ----------\n    audio_path : str\n        Path to audio file.\n    \"\"\"\n    probe = ffmpeg.probe(audio_path)\n    audio_streams = [\n        stream for stream in probe['streams'] if stream['codec_type'] == 'audio'\n    ]\n    if not audio_streams:\n        raise ValueError(\"No audio stream found in the file.\")\n    audio_stream = audio_streams[0]\n\n    sample_rate = int(audio_stream['sample_rate'])\n    duration = float(audio_stream['duration'])\n\n    num_frames = int(duration * sample_rate)\n\n    info = Info(sample_rate=sample_rate, num_frames=num_frames)\n    return info\n\n\ndef info(audio_path: str):\n    \"\"\"\n\n    Parameters\n    ----------\n    audio_path : str\n        Path to audio file.\n    \"\"\"\n    try:\n        info = soundfile.info(str(audio_path))\n        info = Info(sample_rate=info.samplerate, num_frames=info.frames)\n    except:\n        info = info_ffmpeg(str(audio_path))\n\n    return info\n\n\ndef ensure_tensor(\n        x: typing.Union[np.ndarray, paddle.Tensor, float, int],\n        ndim: int=None,\n        batch_size: int=None, ):\n    \"\"\"Ensures that the input ``x`` is a tensor of specified\n    dimensions and batch size.\n\n    Parameters\n    ----------\n    x : typing.Union[np.ndarray, paddle.Tensor, float, int]\n        Data that will become a tensor on its way out.\n    ndim : int, optional\n        How many dimensions should be in the output, by default None\n    batch_size : int, optional\n        The batch size of the output, by default None\n\n    Returns\n    -------\n    paddle.Tensor\n        Modified version of ``x`` as a tensor.\n    \"\"\"\n    if not paddle.is_tensor(x):\n        x = paddle.to_tensor(x)\n    if ndim is not None:\n        assert x.ndim <= ndim\n        while x.ndim < ndim:\n            x = x.unsqueeze(-1)\n    if batch_size is not None:\n        if x.shape[0] != batch_size:\n            shape = list(x.shape)\n            shape[0] = batch_size\n            x = paddle.expand(x, shape)\n    return x\n\n\ndef _get_value(other):\n    # \n    from .audio_signal import AudioSignal\n    if isinstance(other, AudioSignal):\n        return other.audio_data\n    return other\n\n\ndef random_state(seed: typing.Union[int, np.random.RandomState]):\n    \"\"\"\n    Turn seed into a np.random.RandomState instance.\n\n    Parameters\n    ----------\n    seed : typing.Union[int, np.random.RandomState] or None\n        If seed is None, return the RandomState singleton used by np.random.\n        If seed is an int, return a new RandomState instance seeded with seed.\n        If seed is already a RandomState instance, return it.\n        Otherwise raise ValueError.\n\n    Returns\n    -------\n    np.random.RandomState\n        Random state object.\n\n    Raises\n    ------\n    ValueError\n        If seed is not valid, an error is thrown.\n    \"\"\"\n    if seed is None or seed is np.random:\n        return np.random.mtrand._rand\n    elif isinstance(seed, (numbers.Integral, np.integer, int)):\n        return np.random.RandomState(seed)\n    elif isinstance(seed, np.random.RandomState):\n        return seed\n    else:\n        raise ValueError(\"%r cannot be used to seed a numpy.random.RandomState\"\n                         \" instance\" % seed)\n\n\n@contextmanager\ndef _close_temp_files(tmpfiles: list):\n    \"\"\"Utility function for creating a context and closing all temporary files\n    once the context is exited. For correct functionality, all temporary file\n    handles created inside the context must be appended to the ```tmpfiles```\n    list.\n\n    This function is taken wholesale from Scaper.\n\n    Parameters\n    ----------\n    tmpfiles : list\n        List of temporary file handles\n    \"\"\"\n\n    def _close():\n        for t in tmpfiles:\n            try:\n                t.close()\n                os.unlink(t.name)\n            except:\n                pass\n\n    try:\n        yield\n    except:\n        _close()\n        raise\n    _close()\n\n\nAUDIO_EXTENSIONS = [\".wav\", \".flac\", \".mp3\"]\n\n\ndef find_audio(folder: str, ext: List[str]=AUDIO_EXTENSIONS):\n    \"\"\"Finds all audio files in a directory recursively.\n    Returns a list.\n\n    Parameters\n    ----------\n    folder : str\n        Folder to look for audio files in, recursively.\n    ext : List[str], optional\n        Extensions to look for without the ., by default\n        ``['.wav', '.flac', '.mp3', '.mp4']``.\n    \"\"\"\n    folder = Path(folder)\n    # Take care of case where user has passed in an audio file directly\n    # into one of the calling functions.\n    if str(folder).endswith(tuple(ext)):\n        # if, however, there's a glob in the path, we need to\n        # return the glob, not the file.\n        if \"*\" in str(folder):\n            return glob.glob(str(folder), recursive=(\"**\" in str(folder)))\n        else:\n            return [folder]\n\n    files = []\n    for x in ext:\n        files += folder.glob(f\"**/*{x}\")\n    return files\n\n\ndef read_sources(\n        sources: List[str],\n        remove_empty: bool=True,\n        relative_path: str=\"\",\n        ext: List[str]=AUDIO_EXTENSIONS, ):\n    \"\"\"Reads audio sources that can either be folders\n    full of audio files, or CSV files that contain paths\n    to audio files. CSV files that adhere to the expected\n    format can be generated by\n    :py:func:`audiotools.data.preprocess.create_csv`.\n\n    Parameters\n    ----------\n    sources : List[str]\n        List of audio sources to be converted into a\n        list of lists of audio files.\n    remove_empty : bool, optional\n        Whether or not to remove rows with an empty \"path\"\n        from each CSV file, by default True.\n\n    Returns\n    -------\n    list\n        List of lists of rows of CSV files.\n    \"\"\"\n    files = []\n    relative_path = Path(relative_path)\n    for source in sources:\n        source = str(source)\n        _files = []\n        if source.endswith(\".csv\"):\n            with open(source, \"r\") as f:\n                reader = csv.DictReader(f)\n                for x in reader:\n                    if remove_empty and x[\"path\"] == \"\":\n                        continue\n                    if x[\"path\"] != \"\":\n                        x[\"path\"] = str(relative_path / x[\"path\"])\n                    _files.append(x)\n        else:\n            for x in find_audio(source, ext=ext):\n                x = str(relative_path / x)\n                _files.append({\"path\": x})\n        files.append(sorted(_files, key=lambda x: x[\"path\"]))\n    return files\n\n\ndef choose_from_list_of_lists(state: np.random.RandomState,\n                              list_of_lists: list,\n                              p: float=None):\n    \"\"\"Choose a single item from a list of lists.\n\n    Parameters\n    ----------\n    state : np.random.RandomState\n        Random state to use when choosing an item.\n    list_of_lists : list\n        A list of lists from which items will be drawn.\n    p : float, optional\n        Probabilities of each list, by default None\n\n    Returns\n    -------\n    typing.Any\n        An item from the list of lists.\n    \"\"\"\n    source_idx = state.choice(list(range(len(list_of_lists))), p=p)\n    item_idx = state.randint(len(list_of_lists[source_idx]))\n    return list_of_lists[source_idx][item_idx], source_idx, item_idx\n\n\n@contextmanager\ndef chdir(newdir: typing.Union[Path, str]):\n    \"\"\"\n    Context manager for switching directories to run a\n    function. Useful for when you want to use relative\n    paths to different runs.\n\n    Parameters\n    ----------\n    newdir : typing.Union[Path, str]\n        Directory to switch to.\n    \"\"\"\n    curdir = os.getcwd()\n    try:\n        os.chdir(newdir)\n        yield\n    finally:\n        os.chdir(curdir)\n\n\ndef move_to_device(data, device):\n    if device is None or device == \"\":\n        return data\n    elif device == 'cpu':\n        return paddle.to_tensor(data, place=paddle.CPUPlace())\n    elif device in ('gpu', 'cuda'):\n        return paddle.to_tensor(data, place=paddle.CUDAPlace())\n    else:\n        device = device.replace(\"cuda\", \"gpu\") if \"cuda\" in device else device\n        return data.to(device)\n\n\ndef prepare_batch(batch: typing.Union[dict, list, paddle.Tensor],\n                  device: str=\"cpu\"):\n    \"\"\"Moves items in a batch (typically generated by a DataLoader as a list\n    or a dict) to the specified device. This works even if dictionaries\n    are nested.\n\n    Parameters\n    ----------\n    batch : typing.Union[dict, list, paddle.Tensor]\n        Batch, typically generated by a dataloader, that will be moved to\n        the device.\n    device : str, optional\n        Device to move batch to, by default \"cpu\"\n\n    Returns\n    -------\n    typing.Union[dict, list, paddle.Tensor]\n        Batch with all values moved to the specified device.\n    \"\"\"\n    device = device.replace(\"cuda\", \"gpu\")\n    if isinstance(batch, dict):\n        batch = flatten(batch)\n        for key, val in batch.items():\n            try:\n                # batch[key] = val.to(device)\n                batch[key] = move_to_device(val, device)\n            except:\n                pass\n        batch = unflatten(batch)\n    elif paddle.is_tensor(batch):\n        # batch = batch.to(device)\n        batch = move_to_device(batch, device)\n    elif isinstance(batch, list):\n        for i in range(len(batch)):\n            try:\n                batch[i] = batch[i].to(device)\n            except:\n                pass\n    return batch\n\n\ndef sample_from_dist(dist_tuple: tuple, state: np.random.RandomState=None):\n    \"\"\"Samples from a distribution defined by a tuple. The first\n    item in the tuple is the distribution type, and the rest of the\n    items are arguments to that distribution. The distribution function\n    is gotten from the ``np.random.RandomState`` object.\n\n    Parameters\n    ----------\n    dist_tuple : tuple\n        Distribution tuple\n    state : np.random.RandomState, optional\n        Random state, or seed to use, by default None\n\n    Returns\n    -------\n    typing.Union[float, int, str]\n        Draw from the distribution.\n\n    Examples\n    --------\n    Sample from a uniform distribution:\n\n    >>> dist_tuple = (\"uniform\", 0, 1)\n    >>> sample_from_dist(dist_tuple)\n\n    Sample from a constant distribution:\n\n    >>> dist_tuple = (\"const\", 0)\n    >>> sample_from_dist(dist_tuple)\n\n    Sample from a normal distribution:\n\n    >>> dist_tuple = (\"normal\", 0, 0.5)\n    >>> sample_from_dist(dist_tuple)\n\n    \"\"\"\n    if dist_tuple[0] == \"const\":\n        return dist_tuple[1]\n    state = random_state(state)\n    dist_fn = getattr(state, dist_tuple[0])\n    return dist_fn(*dist_tuple[1:])\n\n\nBASE_SIZE = 864\nDEFAULT_FIG_SIZE = (9, 3)\n\n\ndef format_figure(\n        fig_size: tuple=None,\n        title: str=None,\n        fig=None,\n        format_axes: bool=True,\n        format: bool=True,\n        font_color: str=\"white\", ):\n    \"\"\"Prettifies the spectrogram and waveform plots. A title\n    can be inset into the top right corner, and the axes can be\n    inset into the figure, allowing the data to take up the entire\n    image. Used in\n\n    - :py:func:`audiotools.core.display.DisplayMixin.specshow`\n    - :py:func:`audiotools.core.display.DisplayMixin.waveplot`\n    - :py:func:`audiotools.core.display.DisplayMixin.wavespec`\n\n    Parameters\n    ----------\n    fig_size : tuple, optional\n        Size of figure, by default (9, 3)\n    title : str, optional\n        Title to inset in top right, by default None\n    fig : matplotlib.figure.Figure, optional\n        Figure object, if None ``plt.gcf()`` will be used, by default None\n    format_axes : bool, optional\n        Format the axes to be inside the figure, by default True\n    format : bool, optional\n        This formatting can be skipped entirely by passing ``format=False``\n        to any of the plotting functions that use this formater, by default True\n    font_color : str, optional\n        Color of font of axes, by default \"white\"\n    \"\"\"\n    import matplotlib\n    import matplotlib.pyplot as plt\n\n    if fig_size is None:\n        fig_size = DEFAULT_FIG_SIZE\n    if not format:\n        return\n    if fig is None:\n        fig = plt.gcf()\n    fig.set_size_inches(*fig_size)\n    axs = fig.axes\n\n    pixels = (fig.get_size_inches() * fig.dpi)[0]\n    font_scale = pixels / BASE_SIZE\n\n    if format_axes:\n        axs = fig.axes\n\n        for ax in axs:\n            ymin, _ = ax.get_ylim()\n            xmin, _ = ax.get_xlim()\n\n            ticks = ax.get_yticks()\n            for t in ticks[2:-1]:\n                t = axs[0].annotate(\n                    f\"{(t / 1000):2.1f}k\",\n                    xy=(xmin, t),\n                    xycoords=\"data\",\n                    xytext=(5, -5),\n                    textcoords=\"offset points\",\n                    ha=\"left\",\n                    va=\"top\",\n                    color=font_color,\n                    fontsize=12 * font_scale,\n                    alpha=0.75, )\n\n            ticks = ax.get_xticks()[2:]\n            for t in ticks[:-1]:\n                t = axs[0].annotate(\n                    f\"{t:2.1f}s\",\n                    xy=(t, ymin),\n                    xycoords=\"data\",\n                    xytext=(5, 5),\n                    textcoords=\"offset points\",\n                    ha=\"center\",\n                    va=\"bottom\",\n                    color=font_color,\n                    fontsize=12 * font_scale,\n                    alpha=0.75, )\n\n            ax.margins(0, 0)\n            ax.set_axis_off()\n            ax.xaxis.set_major_locator(plt.NullLocator())\n            ax.yaxis.set_major_locator(plt.NullLocator())\n\n        plt.subplots_adjust(\n            top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)\n\n    if title is not None:\n        t = axs[0].annotate(\n            title,\n            xy=(1, 1),\n            xycoords=\"axes fraction\",\n            fontsize=20 * font_scale,\n            xytext=(-5, -5),\n            textcoords=\"offset points\",\n            ha=\"right\",\n            va=\"top\",\n            color=\"white\", )\n        t.set_bbox(dict(facecolor=\"black\", alpha=0.5, edgecolor=\"black\"))\n\n\n_default_collate_err_msg_format = (\n    \"default_collate: batch must contain tensors, numpy arrays, numbers, \"\n    \"dicts or lists; found {}\")\n\n\ndef collate_tensor_fn(\n        batch,\n        *,\n        collate_fn_map: Optional[Dict[Union[type, Tuple[type, ...]],\n                                      Callable]]=None, ):\n    out = paddle.stack(batch, axis=0)\n    return out\n\n\ndef collate_float_fn(\n        batch,\n        *,\n        collate_fn_map: Optional[Dict[Union[Type, Tuple[Type, ...]],\n                                      Callable]]=None, ):\n    return paddle.to_tensor(batch, dtype=paddle.float64)\n\n\ndef collate_int_fn(\n        batch,\n        *,\n        collate_fn_map: Optional[Dict[Union[Type, Tuple[Type, ...]],\n                                      Callable]]=None, ):\n    return paddle.to_tensor(batch)\n\n\ndef collate_str_fn(\n        batch,\n        *,\n        collate_fn_map: Optional[Dict[Union[Type, Tuple[Type, ...]],\n                                      Callable]]=None, ):\n    return batch\n\n\ndefault_collate_fn_map: Dict[Union[Type, Tuple[Type, ...]], Callable] = {\n    paddle.Tensor: collate_tensor_fn\n}\ndefault_collate_fn_map[float] = collate_float_fn\ndefault_collate_fn_map[int] = collate_int_fn\ndefault_collate_fn_map[str] = collate_str_fn\ndefault_collate_fn_map[bytes] = collate_str_fn\n\n\ndef default_collate(batch,\n                    *,\n                    collate_fn_map: Optional[Dict[Union[Type, Tuple[Type, ...]],\n                                                  Callable]]=None):\n    r\"\"\"\n    General collate function that handles collection type of element within each batch.\n\n    The function also opens function registry to deal with specific element types. `default_collate_fn_map`\n    provides default collate functions for tensors, numpy arrays, numbers and strings.\n\n    Args:\n        batch: a single batch to be collated\n        collate_fn_map: Optional dictionary mapping from element type to the corresponding collate function.\n            If the element type isn't present in this dictionary,\n            this function will go through each key of the dictionary in the insertion order to\n            invoke the corresponding collate function if the element type is a subclass of the key.\n    Note:\n        Each collate function requires a positional argument for batch and a keyword argument\n        for the dictionary of collate functions as `collate_fn_map`.\n    \"\"\"\n    elem = batch[0]\n    elem_type = type(elem)\n\n    if collate_fn_map is not None:\n        if elem_type in collate_fn_map:\n            return collate_fn_map[elem_type](\n                batch, collate_fn_map=collate_fn_map)\n\n        for collate_type in collate_fn_map:\n            if isinstance(elem, collate_type):\n                return collate_fn_map[collate_type](\n                    batch, collate_fn_map=collate_fn_map)\n\n    if isinstance(elem, collections.abc.Mapping):\n        try:\n            return elem_type({\n                key: default_collate(\n                    [d[key] for d in batch], collate_fn_map=collate_fn_map)\n                for key in elem\n            })\n        except TypeError:\n            # The mapping type may not support `__init__(iterable)`.\n            return {\n                key: default_collate(\n                    [d[key] for d in batch], collate_fn_map=collate_fn_map)\n                for key in elem\n            }\n    elif isinstance(elem, tuple) and hasattr(elem, \"_fields\"):  # namedtuple\n        return elem_type(*(default_collate(\n            samples, collate_fn_map=collate_fn_map) for samples in zip(*batch)))\n    elif isinstance(elem, collections.abc.Sequence):\n        # check to make sure that the elements in batch have consistent size\n        it = iter(batch)\n        elem_size = len(next(it))\n        if not all(len(elem) == elem_size for elem in it):\n            raise RuntimeError(\n                \"each element in list of batch should be of equal size\")\n        transposed = list(\n            zip(*batch))  # It may be accessed twice, so we use a list.\n\n        if isinstance(elem, tuple):\n            return [\n                default_collate(samples, collate_fn_map=collate_fn_map)\n                for samples in transposed\n            ]  # Backwards compatibility.\n        else:\n            try:\n                return elem_type([\n                    default_collate(samples, collate_fn_map=collate_fn_map)\n                    for samples in transposed\n                ])\n            except TypeError:\n                # The sequence type may not support `__init__(iterable)` (e.g., `range`).\n                return [\n                    default_collate(samples, collate_fn_map=collate_fn_map)\n                    for samples in transposed\n                ]\n\n    raise TypeError(_default_collate_err_msg_format.format(elem_type))\n\n\ndef collate(list_of_dicts: list, n_splits: int=None):\n    \"\"\"Collates a list of dictionaries (e.g. as returned by a\n    dataloader) into a dictionary with batched values. This routine\n    uses the default torch collate function for everything\n    except AudioSignal objects, which are handled by the\n    :py:func:`audiotools.core.audio_signal.AudioSignal.batch`\n    function.\n\n    This function takes n_splits to enable splitting a batch\n    into multiple sub-batches for the purposes of gradient accumulation,\n    etc.\n\n    Parameters\n    ----------\n    list_of_dicts : list\n        List of dictionaries to be collated.\n    n_splits : int\n        Number of splits to make when creating the batches (split into\n        sub-batches). Useful for things like gradient accumulation.\n\n    Returns\n    -------\n    dict\n        Dictionary containing batched data.\n    \"\"\"\n\n    from .audio_signal import AudioSignal\n\n    batches = []\n    list_len = len(list_of_dicts)\n\n    return_list = False if n_splits is None else True\n    n_splits = 1 if n_splits is None else n_splits\n    n_items = int(math.ceil(list_len / n_splits))\n\n    for i in range(0, list_len, n_items):\n        # Flatten the dictionaries to avoid recursion.\n        list_of_dicts_ = [flatten(d) for d in list_of_dicts[i:i + n_items]]\n        dict_of_lists = {\n            k: [dic[k] for dic in list_of_dicts_]\n            for k in list_of_dicts_[0]\n        }\n\n        batch = {}\n        for k, v in dict_of_lists.items():\n            if isinstance(v, list):\n                if all(isinstance(s, AudioSignal) for s in v):\n                    batch[k] = AudioSignal.batch(v, pad_signals=True)\n                else:\n                    batch[k] = default_collate(\n                        v, collate_fn_map=default_collate_fn_map)\n        batches.append(unflatten(batch))\n\n    batches = batches[0] if not return_list else batches\n    return batches\n\n\ndef hz_to_bin(hz: paddle.Tensor, n_fft: int, sample_rate: int):\n    \"\"\"Closest frequency bin given a frequency, number\n    of bins, and a sampling rate.\n\n    Parameters\n    ----------\n    hz : paddle.Tensor\n       Tensor of frequencies in Hz.\n    n_fft : int\n        Number of FFT bins.\n    sample_rate : int\n        Sample rate of audio.\n\n    Returns\n    -------\n    paddle.Tensor\n        Closest bins to the data.\n    \"\"\"\n    shape = hz.shape\n    hz = hz.reshape([-1])\n    freqs = paddle.linspace(0, sample_rate / 2, 2 + n_fft // 2)\n    hz = paddle.clip(hz, max=sample_rate / 2).astype(freqs.dtype)\n\n    closest = (hz[None, :] - freqs[:, None]).abs()\n    closest_bins = closest.argmin(axis=0)\n\n    return closest_bins.reshape(shape)\n\n\ndef generate_chord_dataset(\n        max_voices: int=8,\n        sample_rate: int=44100,\n        num_items: int=5,\n        duration: float=1.0,\n        min_note: str=\"C2\",\n        max_note: str=\"C6\",\n        output_dir: Path=\"chords\", ):\n    \"\"\"\n    Generates a toy multitrack dataset of chords, synthesized from sine waves.\n\n\n    Parameters\n    ----------\n    max_voices : int, optional\n        Maximum number of voices in a chord, by default 8\n    sample_rate : int, optional\n        Sample rate of audio, by default 44100\n    num_items : int, optional\n        Number of items to generate, by default 5\n    duration : float, optional\n        Duration of each item, by default 1.0\n    min_note : str, optional\n        Minimum note in the dataset, by default \"C2\"\n    max_note : str, optional\n        Maximum note in the dataset, by default \"C6\"\n    output_dir : Path, optional\n        Directory to save the dataset, by default \"chords\"\n\n    \"\"\"\n    import librosa\n    from .audio_signal import AudioSignal\n    from ..data.preprocess import create_csv\n\n    min_midi = librosa.note_to_midi(min_note)\n    max_midi = librosa.note_to_midi(max_note)\n\n    tracks = []\n    for idx in range(num_items):\n        track = {}\n        # figure out how many voices to put in this track\n        num_voices = random.randint(1, max_voices)\n        for voice_idx in range(num_voices):\n            # choose some random params\n            midinote = random.randint(min_midi, max_midi)\n            dur = random.uniform(0.85 * duration, duration)\n\n            sig = AudioSignal.wave(\n                frequency=librosa.midi_to_hz(midinote),\n                duration=dur,\n                sample_rate=sample_rate,\n                shape=\"sine\", )\n            track[f\"voice_{voice_idx}\"] = sig\n        tracks.append(track)\n\n    # save the tracks to disk\n    output_dir = Path(output_dir)\n    output_dir.mkdir(exist_ok=True)\n    for idx, track in enumerate(tracks):\n        track_dir = output_dir / f\"track_{idx}\"\n        track_dir.mkdir(exist_ok=True)\n        for voice_name, sig in track.items():\n            sig.write(track_dir / f\"{voice_name}.wav\")\n\n    all_voices = list(set([k for track in tracks for k in track.keys()]))\n    voice_lists = {voice: [] for voice in all_voices}\n    for track in tracks:\n        for voice_name in all_voices:\n            if voice_name in track:\n                voice_lists[voice_name].append(track[voice_name].path_to_file)\n            else:\n                voice_lists[voice_name].append(\"\")\n\n    for voice_name, paths in voice_lists.items():\n        create_csv(paths, output_dir / f\"{voice_name}.csv\", loudness=True)\n\n    return output_dir\n"
  },
  {
    "path": "paddlespeech/audiotools/data/__init__.py",
    "content": "# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import datasets\nfrom . import preprocess\nfrom . import transforms\n"
  },
  {
    "path": "paddlespeech/audiotools/data/datasets.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/data/datasets.py)\nfrom pathlib import Path\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import List\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.io import SequenceSampler\n\nfrom ..core import AudioSignal\nfrom ..core import util\n\n__all__ = [\n    \"AudioLoader\", \"AudioDataset\", \"ConcatDataset\",\n    \"ResumableDistributedSampler\", \"ResumableSequentialSampler\"\n]\n\n\nclass AudioLoader:\n    \"\"\"Loads audio endlessly from a list of audio sources\n    containing paths to audio files. Audio sources can be\n    folders full of audio files (which are found via file\n    extension) or by providing a CSV file which contains paths\n    to audio files.\n\n    Parameters\n    ----------\n    sources : List[str], optional\n        Sources containing folders, or CSVs with\n        paths to audio files, by default None\n    weights : List[float], optional\n        Weights to sample audio files from each source, by default None\n    relative_path : str, optional\n        Path audio should be loaded relative to, by default \"\"\n    transform : Callable, optional\n        Transform to instantiate alongside audio sample,\n        by default None\n    ext : List[str]\n        List of extensions to find audio within each source by. Can\n        also be a file name (e.g. \"vocals.wav\"). by default\n        ``['.wav', '.flac', '.mp3', '.mp4']``.\n    shuffle: bool\n        Whether to shuffle the files within the dataloader. Defaults to True.\n    shuffle_state: int\n        State to use to seed the shuffle of the files.\n    \"\"\"\n\n    def __init__(\n            self,\n            sources: List[str]=None,\n            weights: List[float]=None,\n            transform: Callable=None,\n            relative_path: str=\"\",\n            ext: List[str]=util.AUDIO_EXTENSIONS,\n            shuffle: bool=True,\n            shuffle_state: int=0, ):\n        self.audio_lists = util.read_sources(\n            sources, relative_path=relative_path, ext=ext)\n\n        self.audio_indices = [(src_idx, item_idx)\n                              for src_idx, src in enumerate(self.audio_lists)\n                              for item_idx in range(len(src))]\n        if shuffle:\n            state = util.random_state(shuffle_state)\n            state.shuffle(self.audio_indices)\n\n        self.sources = sources\n        self.weights = weights\n        self.transform = transform\n\n    def __call__(\n            self,\n            state,\n            sample_rate: int,\n            duration: float,\n            loudness_cutoff: float=-40,\n            num_channels: int=1,\n            offset: float=None,\n            source_idx: int=None,\n            item_idx: int=None,\n            global_idx: int=None, ):\n        if source_idx is not None and item_idx is not None:\n            try:\n                audio_info = self.audio_lists[source_idx][item_idx]\n            except:\n                audio_info = {\"path\": \"none\"}\n        elif global_idx is not None:\n            source_idx, item_idx = self.audio_indices[global_idx %\n                                                      len(self.audio_indices)]\n            audio_info = self.audio_lists[source_idx][item_idx]\n        else:\n            audio_info, source_idx, item_idx = util.choose_from_list_of_lists(\n                state, self.audio_lists, p=self.weights)\n\n        path = audio_info[\"path\"]\n        signal = AudioSignal.zeros(duration, sample_rate, num_channels)\n\n        if path != \"none\":\n            if offset is None:\n                signal = AudioSignal.salient_excerpt(\n                    path,\n                    duration=duration,\n                    state=state,\n                    loudness_cutoff=loudness_cutoff, )\n            else:\n                signal = AudioSignal(\n                    path,\n                    offset=offset,\n                    duration=duration, )\n\n        if num_channels == 1:\n            signal = signal.to_mono()\n        signal = signal.resample(sample_rate)\n\n        if signal.duration < duration:\n            signal = signal.zero_pad_to(int(duration * sample_rate))\n\n        for k, v in audio_info.items():\n            signal.metadata[k] = v\n\n        item = {\n            \"signal\": signal,\n            \"source_idx\": source_idx,\n            \"item_idx\": item_idx,\n            \"source\": str(self.sources[source_idx]),\n            \"path\": str(path),\n        }\n        if self.transform is not None:\n            item[\"transform_args\"] = self.transform.instantiate(\n                state, signal=signal)\n        return item\n\n\ndef default_matcher(x, y):\n    return Path(x).parent == Path(y).parent\n\n\ndef align_lists(lists, matcher: Callable=default_matcher):\n    longest_list = lists[np.argmax([len(l) for l in lists])]\n    for i, x in enumerate(longest_list):\n        for l in lists:\n            if i >= len(l):\n                l.append({\"path\": \"none\"})\n            elif not matcher(l[i][\"path\"], x[\"path\"]):\n                l.insert(i, {\"path\": \"none\"})\n    return lists\n\n\nclass AudioDataset:\n    \"\"\"Loads audio from multiple loaders (with associated transforms)\n    for a specified number of samples. Excerpts are drawn randomly\n    of the specified duration, above a specified loudness threshold\n    and are resampled on the fly to the desired sample rate\n    (if it is different from the audio source sample rate).\n\n    This takes either a single AudioLoader object,\n    a dictionary of AudioLoader objects, or a dictionary of AudioLoader\n    objects. Each AudioLoader is called by the dataset, and the\n    result is placed in the output dictionary. A transform can also be\n    specified for the entire dataset, rather than for each specific\n    loader. This transform can be applied to the output of all the\n    loaders if desired.\n\n    AudioLoader objects can be specified as aligned, which means the\n    loaders correspond to multitrack audio (e.g. a vocals, bass,\n    drums, and other loader for multitrack music mixtures).\n\n\n    Parameters\n    ----------\n    loaders : Union[AudioLoader, List[AudioLoader], Dict[str, AudioLoader]]\n        AudioLoaders to sample audio from.\n    sample_rate : int\n        Desired sample rate.\n    n_examples : int, optional\n        Number of examples (length of dataset), by default 1000\n    duration : float, optional\n        Duration of audio samples, by default 0.5\n    loudness_cutoff : float, optional\n        Loudness cutoff threshold for audio samples, by default -40\n    num_channels : int, optional\n        Number of channels in output audio, by default 1\n    transform : Callable, optional\n        Transform to instantiate alongside each dataset item, by default None\n    aligned : bool, optional\n        Whether the loaders should be sampled in an aligned manner (e.g. same\n        offset, duration, and matched file name), by default False\n    shuffle_loaders : bool, optional\n        Whether to shuffle the loaders before sampling from them, by default False\n    matcher : Callable\n        How to match files from adjacent audio lists (e.g. for a multitrack audio loader),\n        by default uses the parent directory of each file.\n    without_replacement : bool\n        Whether to choose files with or without replacement, by default True.\n\n\n    Examples\n    --------\n    >>> from paddlespeech.audiotools.data.datasets import AudioLoader\n    >>> from paddlespeech.audiotools.data.datasets import AudioDataset\n    >>> from paddlespeech.audiotools import transforms as tfm\n    >>> import numpy as np\n    >>>\n    >>> loaders = [\n    >>>     AudioLoader(\n    >>>         sources=[f\"tests/audiotools/audio/spk\"],\n    >>>         transform=tfm.Equalizer(),\n    >>>         ext=[\"wav\"],\n    >>>     )\n    >>>     for i in range(5)\n    >>> ]\n    >>>\n    >>> dataset = AudioDataset(\n    >>>     loaders = loaders,\n    >>>     sample_rate = 44100,\n    >>>     duration = 1.0,\n    >>>     transform = tfm.RescaleAudio(),\n    >>> )\n    >>>\n    >>> item = dataset[np.random.randint(len(dataset))]\n    >>>\n    >>> for i in range(len(loaders)):\n    >>>     item[i][\"signal\"] = loaders[i].transform(\n    >>>         item[i][\"signal\"], **item[i][\"transform_args\"]\n    >>>     )\n    >>>     item[i][\"signal\"].widget(i)\n    >>>\n    >>> mix = sum([item[i][\"signal\"] for i in range(len(loaders))])\n    >>> mix = dataset.transform(mix, **item[\"transform_args\"])\n    >>> mix.widget(\"mix\")\n\n    Below is an example of how one could load MUSDB multitrack data:\n\n    >>> from paddlespeech import audiotools as at\n    >>> from pathlib import Path\n    >>> from paddlespeech.audiotools import transforms as tfm\n    >>> import numpy as np\n    >>> import torch\n    >>>\n    >>> def build_dataset(\n    >>>     sample_rate: int = 44100,\n    >>>     duration: float = 5.0,\n    >>>     musdb_path: str = \"~/.data/musdb/\",\n    >>> ):\n    >>>     musdb_path = Path(musdb_path).expanduser()\n    >>>     loaders = {\n    >>>         src: at.datasets.AudioLoader(\n    >>>             sources=[musdb_path],\n    >>>             transform=tfm.Compose(\n    >>>                 tfm.VolumeNorm((\"uniform\", -20, -10)),\n    >>>                 tfm.Silence(prob=0.1),\n    >>>             ),\n    >>>             ext=[f\"{src}.wav\"],\n    >>>         )\n    >>>         for src in [\"vocals\", \"bass\", \"drums\", \"other\"]\n    >>>     }\n    >>>\n    >>>     dataset = at.datasets.AudioDataset(\n    >>>         loaders=loaders,\n    >>>         sample_rate=sample_rate,\n    >>>         duration=duration,\n    >>>         num_channels=1,\n    >>>         aligned=True,\n    >>>         transform=tfm.RescaleAudio(),\n    >>>         shuffle_loaders=True,\n    >>>     )\n    >>>     return dataset, list(loaders.keys())\n    >>>\n    >>> train_data, sources = build_dataset()\n    >>> dataloader = torch.utils.data.DataLoader(\n    >>>     train_data,\n    >>>     batch_size=16,\n    >>>     num_workers=0,\n    >>>     collate_fn=train_data.collate,\n    >>> )\n    >>> batch = next(iter(dataloader))\n    >>>\n    >>> for k in sources:\n    >>>     src = batch[k]\n    >>>     src[\"transformed\"] = train_data.loaders[k].transform(\n    >>>         src[\"signal\"].clone(), **src[\"transform_args\"]\n    >>>     )\n    >>>\n    >>> mixture = sum(batch[k][\"transformed\"] for k in sources)\n    >>> mixture = train_data.transform(mixture, **batch[\"transform_args\"])\n    >>>\n    >>> # Say a model takes the mix and gives back (n_batch, n_src, n_time).\n    >>> # Construct the targets:\n    >>> targets = at.AudioSignal.batch([batch[k][\"transformed\"] for k in sources], dim=1)\n\n    Similarly, here's example code for loading Slakh data:\n\n    >>> from paddlespeech import audiotools as at\n    >>> from pathlib import Path\n    >>> from paddlespeech.audiotools import transforms as tfm\n    >>> import numpy as np\n    >>> import torch\n    >>> import glob\n    >>>\n    >>> def build_dataset(\n    >>>     sample_rate: int = 16000,\n    >>>     duration: float = 10.0,\n    >>>     slakh_path: str = \"~/.data/slakh/\",\n    >>> ):\n    >>>     slakh_path = Path(slakh_path).expanduser()\n    >>>\n    >>>     # Find the max number of sources in Slakh\n    >>>     src_names = [x.name for x in list(slakh_path.glob(\"**/*.wav\"))  if \"S\" in str(x.name)]\n    >>>     n_sources = len(list(set(src_names)))\n    >>>\n    >>>     loaders = {\n    >>>         f\"S{i:02d}\": at.datasets.AudioLoader(\n    >>>             sources=[slakh_path],\n    >>>             transform=tfm.Compose(\n    >>>                 tfm.VolumeNorm((\"uniform\", -20, -10)),\n    >>>                 tfm.Silence(prob=0.1),\n    >>>             ),\n    >>>             ext=[f\"S{i:02d}.wav\"],\n    >>>         )\n    >>>         for i in range(n_sources)\n    >>>     }\n    >>>     dataset = at.datasets.AudioDataset(\n    >>>         loaders=loaders,\n    >>>         sample_rate=sample_rate,\n    >>>         duration=duration,\n    >>>         num_channels=1,\n    >>>         aligned=True,\n    >>>         transform=tfm.RescaleAudio(),\n    >>>         shuffle_loaders=False,\n    >>>     )\n    >>>\n    >>>     return dataset, list(loaders.keys())\n    >>>\n    >>> train_data, sources = build_dataset()\n    >>> dataloader = torch.utils.data.DataLoader(\n    >>>     train_data,\n    >>>     batch_size=16,\n    >>>     num_workers=0,\n    >>>     collate_fn=train_data.collate,\n    >>> )\n    >>> batch = next(iter(dataloader))\n    >>>\n    >>> for k in sources:\n    >>>     src = batch[k]\n    >>>     src[\"transformed\"] = train_data.loaders[k].transform(\n    >>>         src[\"signal\"].clone(), **src[\"transform_args\"]\n    >>>     )\n    >>>\n    >>> mixture = sum(batch[k][\"transformed\"] for k in sources)\n    >>> mixture = train_data.transform(mixture, **batch[\"transform_args\"])\n\n    \"\"\"\n\n    def __init__(\n            self,\n            loaders: Union[AudioLoader, List[AudioLoader], Dict[str,\n                                                                AudioLoader]],\n            sample_rate: int,\n            n_examples: int=1000,\n            duration: float=0.5,\n            offset: float=None,\n            loudness_cutoff: float=-40,\n            num_channels: int=1,\n            transform: Callable=None,\n            aligned: bool=False,\n            shuffle_loaders: bool=False,\n            matcher: Callable=default_matcher,\n            without_replacement: bool=True, ):\n        # Internally we convert loaders to a dictionary\n        if isinstance(loaders, list):\n            loaders = {i: l for i, l in enumerate(loaders)}\n        elif isinstance(loaders, AudioLoader):\n            loaders = {0: loaders}\n\n        self.loaders = loaders\n        self.loudness_cutoff = loudness_cutoff\n        self.num_channels = num_channels\n\n        self.length = n_examples\n        self.transform = transform\n        self.sample_rate = sample_rate\n        self.duration = duration\n        self.offset = offset\n        self.aligned = aligned\n        self.shuffle_loaders = shuffle_loaders\n        self.without_replacement = without_replacement\n\n        if aligned:\n            loaders_list = list(loaders.values())\n            for i in range(len(loaders_list[0].audio_lists)):\n                input_lists = [l.audio_lists[i] for l in loaders_list]\n                # Alignment happens in-place\n                align_lists(input_lists, matcher)\n\n    def __getitem__(self, idx):\n        state = util.random_state(idx)\n        offset = None if self.offset is None else self.offset\n        item = {}\n\n        keys = list(self.loaders.keys())\n        if self.shuffle_loaders:\n            state.shuffle(keys)\n\n        loader_kwargs = {\n            \"state\": state,\n            \"sample_rate\": self.sample_rate,\n            \"duration\": self.duration,\n            \"loudness_cutoff\": self.loudness_cutoff,\n            \"num_channels\": self.num_channels,\n            \"global_idx\": idx if self.without_replacement else None,\n        }\n\n        # Draw item from first loader\n        loader = self.loaders[keys[0]]\n        item[keys[0]] = loader(**loader_kwargs)\n\n        for key in keys[1:]:\n            loader = self.loaders[key]\n            if self.aligned:\n                # Path mapper takes the current loader + everything\n                # returned by the first loader.\n                offset = item[keys[0]][\"signal\"].metadata[\"offset\"]\n                loader_kwargs.update({\n                    \"offset\": offset,\n                    \"source_idx\": item[keys[0]][\"source_idx\"],\n                    \"item_idx\": item[keys[0]][\"item_idx\"],\n                })\n            item[key] = loader(**loader_kwargs)\n\n        # Sort dictionary back into original order\n        keys = list(self.loaders.keys())\n        item = {k: item[k] for k in keys}\n\n        item[\"idx\"] = idx\n        if self.transform is not None:\n            item[\"transform_args\"] = self.transform.instantiate(\n                state=state, signal=item[keys[0]][\"signal\"])\n\n        # If there's only one loader, pop it up\n        # to the main dictionary, instead of keeping it\n        # nested.\n        if len(keys) == 1:\n            item.update(item.pop(keys[0]))\n\n        return item\n\n    def __len__(self):\n        return self.length\n\n    @staticmethod\n    def collate(list_of_dicts: Union[list, dict], n_splits: int=None):\n        \"\"\"Collates items drawn from this dataset. Uses\n        :py:func:`audiotools.core.util.collate`.\n\n        Parameters\n        ----------\n        list_of_dicts : typing.Union[list, dict]\n            Data drawn from each item.\n        n_splits : int\n            Number of splits to make when creating the batches (split into\n            sub-batches). Useful for things like gradient accumulation.\n\n        Returns\n        -------\n        dict\n            Dictionary of batched data.\n        \"\"\"\n        return util.collate(list_of_dicts, n_splits=n_splits)\n\n\nclass ConcatDataset(AudioDataset):\n    # \n    def __init__(self, datasets: list):\n        self.datasets = datasets\n\n    def __len__(self):\n        return sum([len(d) for d in self.datasets])\n\n    def __getitem__(self, idx):\n        dataset = self.datasets[idx % len(self.datasets)]\n        return dataset[idx // len(self.datasets)]\n\n\nclass ResumableDistributedSampler(DistributedBatchSampler):\n    \"\"\"Distributed sampler that can be resumed from a given start index.\"\"\"\n\n    def __init__(self,\n                 dataset,\n                 batch_size,\n                 start_idx: int=None,\n                 num_replicas=None,\n                 rank=None,\n                 shuffle=False,\n                 drop_last=False):\n        super().__init__(\n            dataset=dataset,\n            batch_size=batch_size,\n            num_replicas=num_replicas,\n            rank=rank,\n            shuffle=shuffle,\n            drop_last=drop_last, )\n        # Start index, allows to resume an experiment at the index it was\n        if start_idx is not None:\n            self.start_idx = start_idx // self.num_replicas\n        else:\n            self.start_idx = 0\n        # 重新计算样本总数，因为 DistributedBatchSampler 的 __len__ 方法是基于 shuffle 后的样本总数计算的\n        self.total_size = len(self.dataset) if not shuffle else len(\n            self.indices)\n\n    def __iter__(self):\n        # 由于 Paddle 的 DistributedBatchSampler 直接返回 batch，我们需要将其展开为单个索引\n        indices_iter = iter(super().__iter__())\n        # 跳过前面的 start_idx 个 batch\n        for _ in range(self.start_idx):\n            next(indices_iter)\n\n        current_idx = 0\n        while True:\n            batch_indices = next(indices_iter, None)\n            if batch_indices is None:\n                break\n            for idx in batch_indices:\n                if current_idx >= self.start_idx * self.batch_size:  # 调整判断条件，确保从 start_idx 开始\n                    yield idx\n                current_idx += 1\n        self.start_idx = 0  # set the index back to 0 so for the next epoch\n\n\nclass ResumableSequentialSampler(SequenceSampler):\n    \"\"\"Sequential sampler that can be resumed from a given start index.\"\"\"\n\n    def __init__(self, dataset, start_idx: int=None, **kwargs):\n        super().__init__(dataset, **kwargs)\n        # Start index, allows to resume an experiment at the index it was\n        self.start_idx = start_idx if start_idx is not None else 0\n\n    def __iter__(self):\n        for i, idx in enumerate(super().__iter__()):\n            if i >= self.start_idx:\n                yield idx\n        self.start_idx = 0  # set the index back to 0 so for the next epoch\n"
  },
  {
    "path": "paddlespeech/audiotools/data/preprocess.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/data/preprocess.py)\nimport csv\nimport os\nfrom pathlib import Path\n\nfrom tqdm import tqdm\n\nfrom ..core import AudioSignal\n\n\ndef create_csv(audio_files: list,\n               output_csv: Path,\n               loudness: bool=False,\n               data_path: str=None):\n    \"\"\"Converts a folder of audio files to a CSV file. If ``loudness = True``,\n    the output of this function will create a CSV file that looks something\n    like:\n\n    ..  csv-table::\n        :header: path,loudness\n\n        daps/produced/f1_script1_produced.wav,-16.299999237060547\n        daps/produced/f1_script2_produced.wav,-16.600000381469727\n        daps/produced/f1_script3_produced.wav,-17.299999237060547\n        daps/produced/f1_script4_produced.wav,-16.100000381469727\n        daps/produced/f1_script5_produced.wav,-16.700000762939453\n        daps/produced/f3_script1_produced.wav,-16.5\n\n    ..  note::\n        The paths above are written relative to the ``data_path`` argument\n        which defaults to the environment variable ``PATH_TO_DATA`` if\n        it isn't passed to this function, and defaults to the empty string\n        if that environment variable is not set.\n\n    You can produce a CSV file from a directory of audio files via:\n\n    >>> from paddlespeech import audiotools\n    >>> directory = ...\n    >>> audio_files = audiotools.util.find_audio(directory)\n    >>> output_path = \"train.csv\"\n    >>> audiotools.data.preprocess.create_csv(\n    >>>     audio_files, output_csv, loudness=True\n    >>> )\n\n    Note that you can create empty rows in the CSV file by passing an empty\n    string or None in the ``audio_files`` list. This is useful if you want to\n    sync multiple CSV files in a multitrack setting. The loudness of these\n    empty rows will be set to -inf.\n\n    Parameters\n    ----------\n    audio_files : list\n        List of audio files.\n    output_csv : Path\n        Output CSV, with each row containing the relative path of every file\n        to ``data_path``, if specified (defaults to None).\n    loudness : bool\n        Compute loudness of entire file and store alongside path.\n    \"\"\"\n\n    info = []\n    pbar = tqdm(audio_files)\n    for af in pbar:\n        af = Path(af)\n        pbar.set_description(f\"Processing {af.name}\")\n        _info = {}\n        if af.name == \"\":\n            _info[\"path\"] = \"\"\n            if loudness:\n                _info[\"loudness\"] = -float(\"inf\")\n        else:\n            _info[\"path\"] = af.relative_to(\n                data_path) if data_path is not None else af\n            if loudness:\n                _info[\"loudness\"] = AudioSignal(af).ffmpeg_loudness().item()\n\n        info.append(_info)\n\n    with open(output_csv, \"w\") as f:\n        writer = csv.DictWriter(f, fieldnames=list(info[0].keys()))\n        writer.writeheader()\n\n        for item in info:\n            writer.writerow(item)\n"
  },
  {
    "path": "paddlespeech/audiotools/data/transforms.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/data/transforms.py)\nimport copy\nfrom contextlib import contextmanager\nfrom inspect import signature\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom flatten_dict import flatten\nfrom flatten_dict import unflatten\nfrom numpy.random import RandomState\n\nfrom .. import ml\nfrom ..core import AudioSignal\nfrom ..core import util\nfrom .datasets import AudioLoader\nfrom paddlespeech.utils import satisfy_paddle_version\n\n__all__ = [\n    \"Identity\",\n    \"SpectralTransform\",\n    \"Compose\",\n    \"Choose\",\n    \"Repeat\",\n    \"RepeatUpTo\",\n    \"ClippingDistortion\",\n    \"Equalizer\",\n    \"BackgroundNoise\",\n    \"RoomImpulseResponse\",\n    \"VolumeNorm\",\n    \"GlobalVolumeNorm\",\n    \"Silence\",\n    \"LowPass\",\n    \"HighPass\",\n    \"FrequencyMask\",\n    \"TimeMask\",\n    \"Smoothing\",\n    \"FrequencyNoise\",\n]\n\n\nclass BaseTransform:\n    \"\"\"This is the base class for all transforms that are implemented\n    in this library. Transforms have two main operations: ``transform``\n    and ``instantiate``.\n\n    ``instantiate`` sets the parameters randomly\n    from distribution tuples for each parameter. For example, for the\n    ``BackgroundNoise`` transform, the signal-to-noise ratio (``snr``)\n    is chosen randomly by instantiate. By default, it chosen uniformly\n    between 10.0 and 30.0 (the tuple is set to ``(\"uniform\", 10.0, 30.0)``).\n\n    ``transform`` applies the transform using the instantiated parameters.\n    A simple example is as follows:\n\n    >>> seed = 0\n    >>> signal = ...\n    >>> transform = transforms.NoiseFloor(db = (\"uniform\", -50.0, -30.0))\n    >>> kwargs = transform.instantiate()\n    >>> output = transform(signal.clone(), **kwargs)\n\n    By breaking apart the instantiation of parameters from the actual audio\n    processing of the transform, we can make things more reproducible, while\n    also applying the transform on batches of data efficiently on GPU,\n    rather than on individual audio samples.\n\n    ..  note::\n        We call ``signal.clone()`` for the input to the ``transform`` function\n        because signals are modified in-place! If you don't clone the signal,\n        you will lose the original data.\n\n    Parameters\n    ----------\n    keys : list, optional\n        Keys that the transform looks for when\n        calling ``self.transform``, by default []. In general this is\n        set automatically, and you won't need to manipulate this argument.\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n\n    Examples\n    --------\n\n    >>> seed = 0\n    >>>\n    >>> audio_path = \"tests/audio/spk/f10_script4_produced.wav\"\n    >>> signal = AudioSignal(audio_path, offset=10, duration=2)\n    >>> transform = tfm.Compose(\n    >>>     [\n    >>>         tfm.RoomImpulseResponse(sources=[\"tests/audio/irs.csv\"]),\n    >>>         tfm.BackgroundNoise(sources=[\"tests/audio/noises.csv\"]),\n    >>>     ],\n    >>> )\n    >>>\n    >>> kwargs = transform.instantiate(seed, signal)\n    >>> output = transform(signal, **kwargs)\n\n    \"\"\"\n\n    def __init__(self, keys: list=[], name: str=None, prob: float=1.0):\n        # Get keys from the _transform signature.\n        tfm_keys = list(signature(self._transform).parameters.keys())\n\n        # Filter out signal and kwargs keys.\n        ignore_keys = [\"signal\", \"kwargs\"]\n        tfm_keys = [k for k in tfm_keys if k not in ignore_keys]\n\n        # Combine keys specified by the child class, the keys found in\n        # _transform signature, and the mask key.\n        self.keys = keys + tfm_keys + [\"mask\"]\n\n        self.prob = prob\n\n        if name is None:\n            name = self.__class__.__name__\n        self.name = name\n\n    def _prepare(self, batch: dict):\n        sub_batch = batch[self.name]\n\n        for k in self.keys:\n            assert k in sub_batch.keys(), f\"{k} not in batch\"\n\n        return sub_batch\n\n    def _transform(self, signal):\n        return signal\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal=None):\n        return {}\n\n    @staticmethod\n    def apply_mask(batch: dict, mask: paddle.Tensor):\n        \"\"\"Applies a mask to the batch.\n\n        Parameters\n        ----------\n        batch : dict\n            Batch whose values will be masked in the ``transform`` pass.\n        mask : paddle.Tensor\n            Mask to apply to batch.\n\n        Returns\n        -------\n        dict\n            A dictionary that contains values only where ``mask = True``.\n        \"\"\"\n        # masked_batch = {k: v[mask] for k, v in flatten(batch).items()}\n        masked_batch = {}\n        for k, v in flatten(batch).items():\n            # `v` may be `Tensor` or `AudioSignal`\n            if 0 == len(v.shape) and 0 == mask.dim():\n                if mask:  # 0d 的 True\n                    masked_batch[k] = v.unsqueeze(0)\n                else:\n                    masked_batch[k] = paddle.to_tensor([], dtype=v.dtype)\n            else:\n                if not satisfy_paddle_version('2.6'):\n                    if 0 == mask.dim() and bool(mask) and paddle.is_tensor(v):\n                        masked_batch[k] = v.unsqueeze(0)\n                    else:\n                        masked_batch[k] = v[mask]\n                else:\n                    masked_batch[k] = v[mask]\n        return unflatten(masked_batch)\n\n    def transform(self, signal: AudioSignal, **kwargs):\n        \"\"\"Apply the transform to the audio signal,\n        with given keyword arguments.\n\n        Parameters\n        ----------\n        signal : AudioSignal\n            Signal that will be modified by the transforms in-place.\n        kwargs: dict\n            Keyword arguments to the specific transforms ``self._transform``\n            function.\n\n        Returns\n        -------\n        AudioSignal\n            Transformed AudioSignal.\n\n        Examples\n        --------\n\n        >>> for seed in range(10):\n        >>>     kwargs = transform.instantiate(seed, signal)\n        >>>     output = transform(signal.clone(), **kwargs)\n\n        \"\"\"\n        tfm_kwargs = self._prepare(kwargs)\n        mask = tfm_kwargs[\"mask\"]\n\n        if paddle.any(mask):\n            tfm_kwargs = self.apply_mask(tfm_kwargs, mask)\n            tfm_kwargs = {k: v for k, v in tfm_kwargs.items() if k != \"mask\"}\n            signal[mask] = self._transform(signal[mask], **tfm_kwargs)\n\n        return signal\n\n    def __call__(self, *args, **kwargs):\n        return self.transform(*args, **kwargs)\n\n    def instantiate(\n            self,\n            state: RandomState=None,\n            signal: AudioSignal=None, ):\n        \"\"\"Instantiates parameters for the transform.\n\n        Parameters\n        ----------\n        state : RandomState, optional\n            _description_, by default None\n        signal : AudioSignal, optional\n            _description_, by default None\n\n        Returns\n        -------\n        dict\n            Dictionary containing instantiated arguments for every keyword\n            argument to ``self._transform``.\n\n        Examples\n        --------\n\n        >>> for seed in range(10):\n        >>>     kwargs = transform.instantiate(seed, signal)\n        >>>     output = transform(signal.clone(), **kwargs)\n\n        \"\"\"\n        state = util.random_state(state)\n\n        # Not all instantiates need the signal. Check if signal\n        # is needed before passing it in, so that the end-user\n        # doesn't need to have variables they're not using flowing\n        # into their function.\n        needs_signal = \"signal\" in set(\n            signature(self._instantiate).parameters.keys())\n        kwargs = {}\n        if needs_signal:\n            kwargs = {\"signal\": signal}\n\n        # Instantiate the parameters for the transform.\n        params = self._instantiate(state, **kwargs)\n        for k in list(params.keys()):\n            v = params[k]\n            if isinstance(v, (AudioSignal, paddle.Tensor, dict)):\n                params[k] = v\n            else:\n                params[k] = paddle.to_tensor(v)\n        mask = state.rand() <= self.prob\n        params[f\"mask\"] = paddle.to_tensor(mask)\n\n        # Put the params into a nested dictionary that will be\n        # used later when calling the transform. This is to avoid\n        # collisions in the dictionary.\n        params = {self.name: params}\n\n        return params\n\n    def batch_instantiate(\n            self,\n            states: list=None,\n            signal: AudioSignal=None, ):\n        \"\"\"Instantiates arguments for every item in a batch,\n        given a list of states. Each state in the list\n        corresponds to one item in the batch.\n\n        Parameters\n        ----------\n        states : list, optional\n            List of states, by default None\n        signal : AudioSignal, optional\n            AudioSignal to pass to the ``self.instantiate`` section\n            if it is needed for this transform, by default None\n\n        Returns\n        -------\n        dict\n            Collated dictionary of arguments.\n\n        Examples\n        --------\n\n        >>> batch_size = 4\n        >>> signal = AudioSignal(audio_path, offset=10, duration=2)\n        >>> signal_batch = AudioSignal.batch([signal.clone() for _ in range(batch_size)])\n        >>>\n        >>> states = [seed + idx for idx in list(range(batch_size))]\n        >>> kwargs = transform.batch_instantiate(states, signal_batch)\n        >>> batch_output = transform(signal_batch, **kwargs)\n        \"\"\"\n        kwargs = []\n        for state in states:\n            kwargs.append(self.instantiate(state, signal))\n        kwargs = util.collate(kwargs)\n        return kwargs\n\n\nclass Identity(BaseTransform):\n    \"\"\"This transform just returns the original signal.\"\"\"\n\n    pass\n\n\nclass SpectralTransform(BaseTransform):\n    \"\"\"Spectral transforms require STFT data to exist, since manipulations\n    of the STFT require the spectrogram. This just calls ``stft`` before\n    the transform is called, and calls ``istft`` after the transform is\n    called so that the audio data is written to after the spectral\n    manipulation.\n    \"\"\"\n\n    def transform(self, signal, **kwargs):\n        signal.stft()\n        super().transform(signal, **kwargs)\n        signal.istft()\n        return signal\n\n\nclass Compose(BaseTransform):\n    \"\"\"Compose applies transforms in sequence, one after the other. The\n    transforms are passed in as positional arguments or as a list like so:\n\n    >>> transform = tfm.Compose(\n    >>>     [\n    >>>         tfm.RoomImpulseResponse(sources=[\"tests/audio/irs.csv\"]),\n    >>>         tfm.BackgroundNoise(sources=[\"tests/audio/noises.csv\"]),\n    >>>     ],\n    >>> )\n\n    This will convolve the signal with a room impulse response, and then\n    add background noise to the signal. Instantiate instantiates\n    all the parameters for every transform in the transform list so the\n    interface for using the Compose transform is the same as everything\n    else:\n\n    >>> kwargs = transform.instantiate()\n    >>> output = transform(signal.clone(), **kwargs)\n\n    Under the hood, the transform maps each transform to a unique name\n    under the hood of the form ``{position}.{name}``, where ``position``\n    is the index of the transform in the list. ``Compose`` can nest\n    within other ``Compose`` transforms, like so:\n\n    >>> preprocess = transforms.Compose(\n    >>>     tfm.GlobalVolumeNorm(),\n    >>>     tfm.CrossTalk(),\n    >>>     name=\"preprocess\",\n    >>> )\n    >>> augment = transforms.Compose(\n    >>>     tfm.RoomImpulseResponse(),\n    >>>     tfm.BackgroundNoise(),\n    >>>     name=\"augment\",\n    >>> )\n    >>> postprocess = transforms.Compose(\n    >>>     tfm.VolumeChange(),\n    >>>     tfm.RescaleAudio(),\n    >>>     tfm.ShiftPhase(),\n    >>>     name=\"postprocess\",\n    >>> )\n    >>> transform = transforms.Compose(preprocess, augment, postprocess),\n\n    This defines 3 composed transforms, and then composes them in sequence\n    with one another.\n\n    Parameters\n    ----------\n    *transforms : list\n        List of transforms to apply\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(self, *transforms: list, name: str=None, prob: float=1.0):\n        if isinstance(transforms[0], list):\n            transforms = transforms[0]\n\n        for i, tfm in enumerate(transforms):\n            tfm.name = f\"{i}.{tfm.name}\"\n\n        keys = [tfm.name for tfm in transforms]\n        super().__init__(keys=keys, name=name, prob=prob)\n\n        self.transforms = transforms\n        self.transforms_to_apply = keys\n\n    @contextmanager\n    def filter(self, *names: list):\n        \"\"\"This can be used to skip transforms entirely when applying\n        the sequence of transforms to a signal. For example, take\n        the following transforms with the names ``preprocess, augment, postprocess``.\n\n        >>> preprocess = transforms.Compose(\n        >>>     tfm.GlobalVolumeNorm(),\n        >>>     tfm.CrossTalk(),\n        >>>     name=\"preprocess\",\n        >>> )\n        >>> augment = transforms.Compose(\n        >>>     tfm.RoomImpulseResponse(),\n        >>>     tfm.BackgroundNoise(),\n        >>>     name=\"augment\",\n        >>> )\n        >>> postprocess = transforms.Compose(\n        >>>     tfm.VolumeChange(),\n        >>>     tfm.RescaleAudio(),\n        >>>     tfm.ShiftPhase(),\n        >>>     name=\"postprocess\",\n        >>> )\n        >>> transform = transforms.Compose(preprocess, augment, postprocess)\n\n        If we wanted to apply all 3 to a signal, we do:\n\n        >>> kwargs = transform.instantiate()\n        >>> output = transform(signal.clone(), **kwargs)\n\n        But if we only wanted to apply the ``preprocess`` and ``postprocess``\n        transforms to the signal, we do:\n\n        >>> with transform_fn.filter(\"preprocess\", \"postprocess\"):\n        >>>     output = transform(signal.clone(), **kwargs)\n\n        Parameters\n        ----------\n        *names : list\n            List of transforms, identified by name, to apply to signal.\n        \"\"\"\n        old_transforms = self.transforms_to_apply\n        self.transforms_to_apply = names\n        yield\n        self.transforms_to_apply = old_transforms\n\n    def _transform(self, signal, **kwargs):\n        for transform in self.transforms:\n            if any([x in transform.name for x in self.transforms_to_apply]):\n                signal = transform(signal, **kwargs)\n        return signal\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal=None):\n        parameters = {}\n        for transform in self.transforms:\n            parameters.update(transform.instantiate(state, signal=signal))\n        return parameters\n\n    def __getitem__(self, idx):\n        return self.transforms[idx]\n\n    def __len__(self):\n        return len(self.transforms)\n\n    def __iter__(self):\n        for transform in self.transforms:\n            yield transform\n\n\nclass Choose(Compose):\n    \"\"\"Choose logic is the same as :py:func:`audiotools.data.transforms.Compose`,\n    but instead of applying all the transforms in sequence, it applies just a single transform,\n    which is chosen for each item in the batch.\n\n    Parameters\n    ----------\n    *transforms : list\n        List of transforms to apply\n    weights : list\n        Probability of choosing any specific transform.\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n\n    Examples\n    --------\n\n    >>> transforms.Choose(tfm.LowPass(), tfm.HighPass())\n    \"\"\"\n\n    def __init__(\n            self,\n            *transforms: list,\n            weights: list=None,\n            name: str=None,\n            prob: float=1.0, ):\n        super().__init__(*transforms, name=name, prob=prob)\n\n        if weights is None:\n            _len = len(self.transforms)\n            weights = [1 / _len for _ in range(_len)]\n        self.weights = np.array(weights)\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal=None):\n        kwargs = super()._instantiate(state, signal)\n        tfm_idx = list(range(len(self.transforms)))\n        tfm_idx = state.choice(tfm_idx, p=self.weights)\n        one_hot = []\n        for i, t in enumerate(self.transforms):\n            mask = kwargs[t.name][\"mask\"]\n            if mask.item():\n                kwargs[t.name][\"mask\"] = paddle.to_tensor(i == tfm_idx)\n            one_hot.append(kwargs[t.name][\"mask\"])\n        kwargs[\"one_hot\"] = one_hot\n        return kwargs\n\n\nclass Repeat(Compose):\n    \"\"\"Repeatedly applies a given transform ``n_repeat`` times.\"\n\n    Parameters\n    ----------\n    transform : BaseTransform\n        Transform to repeat.\n    n_repeat : int, optional\n        Number of times to repeat transform, by default 1\n    \"\"\"\n\n    def __init__(\n            self,\n            transform,\n            n_repeat: int=1,\n            name: str=None,\n            prob: float=1.0, ):\n        transforms = [copy.copy(transform) for _ in range(n_repeat)]\n        super().__init__(transforms, name=name, prob=prob)\n\n        self.n_repeat = n_repeat\n\n\nclass RepeatUpTo(Choose):\n    \"\"\"Repeatedly applies a given transform up to ``max_repeat`` times.\"\n\n    Parameters\n    ----------\n    transform : BaseTransform\n        Transform to repeat.\n    max_repeat : int, optional\n        Max number of times to repeat transform, by default 1\n    weights : list\n        Probability of choosing any specific number up to ``max_repeat``.\n    \"\"\"\n\n    def __init__(\n            self,\n            transform,\n            max_repeat: int=5,\n            weights: list=None,\n            name: str=None,\n            prob: float=1.0, ):\n        transforms = []\n        for n in range(1, max_repeat):\n            transforms.append(Repeat(transform, n_repeat=n))\n        super().__init__(transforms, name=name, prob=prob, weights=weights)\n\n        self.max_repeat = max_repeat\n\n\nclass ClippingDistortion(BaseTransform):\n    \"\"\"Adds clipping distortion to signal. Corresponds\n    to :py:func:`audiotools.core.effects.EffectMixin.clip_distortion`.\n\n    Parameters\n    ----------\n    perc : tuple, optional\n        Clipping percentile. Values are between 0.0 to 1.0.\n        Typical values are 0.1 or below, by default (\"uniform\", 0.0, 0.1)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            perc: tuple=(\"uniform\", 0.0, 0.1),\n            name: str=None,\n            prob: float=1.0, ):\n        super().__init__(name=name, prob=prob)\n\n        self.perc = perc\n\n    def _instantiate(self, state: RandomState):\n        return {\"perc\": util.sample_from_dist(self.perc, state)}\n\n    def _transform(self, signal, perc):\n        return signal.clip_distortion(perc)\n\n\nclass Equalizer(BaseTransform):\n    \"\"\"Applies an equalization curve to the audio signal. Corresponds\n    to :py:func:`audiotools.core.effects.EffectMixin.equalizer`.\n\n    Parameters\n    ----------\n    eq_amount : tuple, optional\n        The maximum dB cut to apply to the audio in any band,\n        by default (\"const\", 1.0 dB)\n    n_bands : int, optional\n        Number of bands in EQ, by default 6\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            eq_amount: tuple=(\"const\", 1.0),\n            n_bands: int=6,\n            name: str=None,\n            prob: float=1.0, ):\n        super().__init__(name=name, prob=prob)\n\n        self.eq_amount = eq_amount\n        self.n_bands = n_bands\n\n    def _instantiate(self, state: RandomState):\n        eq_amount = util.sample_from_dist(self.eq_amount, state)\n        eq = -eq_amount * state.rand(self.n_bands)\n        return {\"eq\": eq}\n\n    def _transform(self, signal, eq):\n        return signal.equalizer(eq)\n\n\nclass BackgroundNoise(BaseTransform):\n    \"\"\"Adds background noise from audio specified by a set of CSV files.\n    A valid CSV file looks like, and is typically generated by\n    :py:func:`audiotools.data.preprocess.create_csv`:\n\n    ..  csv-table::\n        :header: path\n\n        room_tone/m6_script2_clean.wav\n        room_tone/m6_script2_cleanraw.wav\n        room_tone/m6_script2_ipad_balcony1.wav\n        room_tone/m6_script2_ipad_bedroom1.wav\n        room_tone/m6_script2_ipad_confroom1.wav\n        room_tone/m6_script2_ipad_confroom2.wav\n        room_tone/m6_script2_ipad_livingroom1.wav\n        room_tone/m6_script2_ipad_office1.wav\n\n    ..  note::\n        All paths are relative to an environment variable called ``PATH_TO_DATA``,\n        so that CSV files are portable across machines where data may be\n        located in different places.\n\n    This transform calls :py:func:`audiotools.core.effects.EffectMixin.mix`\n    and :py:func:`audiotools.core.effects.EffectMixin.equalizer` under the\n    hood.\n\n    Parameters\n    ----------\n    snr : tuple, optional\n        Signal-to-noise ratio, by default (\"uniform\", 10.0, 30.0)\n    sources : List[str], optional\n        Sources containing folders, or CSVs with paths to audio files,\n        by default None\n    weights : List[float], optional\n        Weights to sample audio files from each source, by default None\n    eq_amount : tuple, optional\n        Amount of equalization to apply, by default (\"const\", 1.0)\n    n_bands : int, optional\n        Number of bands in equalizer, by default 3\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    loudness_cutoff : float, optional\n        Loudness cutoff when loading from audio files, by default None\n    \"\"\"\n\n    def __init__(\n            self,\n            snr: tuple=(\"uniform\", 10.0, 30.0),\n            sources: List[str]=None,\n            weights: List[float]=None,\n            eq_amount: tuple=(\"const\", 1.0),\n            n_bands: int=3,\n            name: str=None,\n            prob: float=1.0,\n            loudness_cutoff: float=None, ):\n        super().__init__(name=name, prob=prob)\n\n        self.snr = snr\n        self.eq_amount = eq_amount\n        self.n_bands = n_bands\n        self.loader = AudioLoader(sources, weights)\n        self.loudness_cutoff = loudness_cutoff\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal):\n        eq_amount = util.sample_from_dist(self.eq_amount, state)\n        eq = -eq_amount * state.rand(self.n_bands)\n        snr = util.sample_from_dist(self.snr, state)\n\n        bg_signal = self.loader(\n            state,\n            signal.sample_rate,\n            duration=signal.signal_duration,\n            loudness_cutoff=self.loudness_cutoff,\n            num_channels=signal.num_channels, )[\"signal\"]\n\n        return {\"eq\": eq, \"bg_signal\": bg_signal, \"snr\": snr}\n\n    def _transform(self, signal, bg_signal, snr, eq):\n        # Clone bg_signal so that transform can be repeatedly applied\n        # to different signals with the same effect.\n        return signal.mix(bg_signal.clone(), snr, eq)\n\n\nclass RoomImpulseResponse(BaseTransform):\n    \"\"\"Convolves signal with a room impulse response, at a specified\n    direct-to-reverberant ratio, with equalization applied. Room impulse\n    response data is drawn from a CSV file that was produced via\n    :py:func:`audiotools.data.preprocess.create_csv`.\n\n    This transform calls :py:func:`audiotools.core.effects.EffectMixin.apply_ir`\n    under the hood.\n\n    Parameters\n    ----------\n    drr : tuple, optional\n        _description_, by default (\"uniform\", 0.0, 30.0)\n    sources : List[str], optional\n        Sources containing folders, or CSVs with paths to audio files,\n        by default None\n    weights : List[float], optional\n        Weights to sample audio files from each source, by default None\n    eq_amount : tuple, optional\n        Amount of equalization to apply, by default (\"const\", 1.0)\n    n_bands : int, optional\n        Number of bands in equalizer, by default 6\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    use_original_phase : bool, optional\n        Whether or not to use the original phase, by default False\n    offset : float, optional\n        Offset from each impulse response file to use, by default 0.0\n    duration : float, optional\n        Duration of each impulse response, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            drr: tuple=(\"uniform\", 0.0, 30.0),\n            sources: List[str]=None,\n            weights: List[float]=None,\n            eq_amount: tuple=(\"const\", 1.0),\n            n_bands: int=6,\n            name: str=None,\n            prob: float=1.0,\n            use_original_phase: bool=False,\n            offset: float=0.0,\n            duration: float=1.0, ):\n        super().__init__(name=name, prob=prob)\n\n        self.drr = drr\n        self.eq_amount = eq_amount\n        self.n_bands = n_bands\n        self.use_original_phase = use_original_phase\n\n        self.loader = AudioLoader(sources, weights)\n        self.offset = offset\n        self.duration = duration\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal=None):\n        eq_amount = util.sample_from_dist(self.eq_amount, state)\n        eq = -eq_amount * state.rand(self.n_bands)\n        drr = util.sample_from_dist(self.drr, state)\n\n        ir_signal = self.loader(\n            state,\n            signal.sample_rate,\n            offset=self.offset,\n            duration=self.duration,\n            loudness_cutoff=None,\n            num_channels=signal.num_channels, )[\"signal\"]\n        ir_signal.zero_pad_to(signal.sample_rate)\n\n        return {\"eq\": eq, \"ir_signal\": ir_signal, \"drr\": drr}\n\n    def _transform(self, signal, ir_signal, drr, eq):\n        # Clone ir_signal so that transform can be repeatedly applied\n        # to different signals with the same effect.\n        return signal.apply_ir(\n            ir_signal.clone(),\n            drr,\n            eq,\n            use_original_phase=self.use_original_phase)\n\n\nclass VolumeNorm(BaseTransform):\n    \"\"\"Normalizes the volume of the excerpt to a specified decibel.\n\n    Uses :py:func:`audiotools.core.effects.EffectMixin.normalize`.\n\n    Parameters\n    ----------\n    db : tuple, optional\n        dB to normalize signal to, by default (\"const\", -24)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            db: tuple=(\"const\", -24),\n            name: str=None,\n            prob: float=1.0, ):\n        super().__init__(name=name, prob=prob)\n\n        self.db = db\n\n    def _instantiate(self, state: RandomState):\n        return {\"db\": util.sample_from_dist(self.db, state)}\n\n    def _transform(self, signal, db):\n        return signal.normalize(db)\n\n\nclass GlobalVolumeNorm(BaseTransform):\n    \"\"\"Similar to :py:func:`audiotools.data.transforms.VolumeNorm`, this\n    transform also normalizes the volume of a signal, but it uses\n    the volume of the entire audio file the loaded excerpt comes from,\n    rather than the volume of just the excerpt. The volume of the\n    entire audio file is expected in ``signal.metadata[\"loudness\"]``.\n    If loading audio from a CSV generated by :py:func:`audiotools.data.preprocess.create_csv`\n    with ``loudness = True``, like the following:\n\n    ..  csv-table::\n        :header: path,loudness\n\n        daps/produced/f1_script1_produced.wav,-16.299999237060547\n        daps/produced/f1_script2_produced.wav,-16.600000381469727\n        daps/produced/f1_script3_produced.wav,-17.299999237060547\n        daps/produced/f1_script4_produced.wav,-16.100000381469727\n        daps/produced/f1_script5_produced.wav,-16.700000762939453\n        daps/produced/f3_script1_produced.wav,-16.5\n\n    The ``AudioLoader`` will automatically load the loudness column into\n    the metadata of the signal.\n\n    Uses :py:func:`audiotools.core.effects.EffectMixin.volume_change`.\n\n    Parameters\n    ----------\n    db : tuple, optional\n        dB to normalize signal to, by default (\"const\", -24)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            db: tuple=(\"const\", -24),\n            name: str=None,\n            prob: float=1.0, ):\n        super().__init__(name=name, prob=prob)\n\n        self.db = db\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal):\n        if \"loudness\" not in signal.metadata:\n            db_change = 0.0\n        elif float(signal.metadata[\"loudness\"]) == float(\"-inf\"):\n            db_change = 0.0\n        else:\n            db = util.sample_from_dist(self.db, state)\n            db_change = db - float(signal.metadata[\"loudness\"])\n\n        return {\"db\": db_change}\n\n    def _transform(self, signal, db):\n        return signal.volume_change(db)\n\n\nclass Silence(BaseTransform):\n    \"\"\"Zeros out the signal with some probability.\n\n    Parameters\n    ----------\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 0.1\n    \"\"\"\n\n    def __init__(self, name: str=None, prob: float=0.1):\n        super().__init__(name=name, prob=prob)\n\n    def _transform(self, signal):\n        _loudness = signal._loudness\n        signal = AudioSignal(\n            paddle.zeros_like(signal.audio_data),\n            sample_rate=signal.sample_rate,\n            stft_params=signal.stft_params, )\n        # So that the amound of noise added is as if it wasn't silenced.\n        # TODO: improve this hack\n        signal._loudness = _loudness\n\n        return signal\n\n\nclass LowPass(BaseTransform):\n    \"\"\"Applies a LowPass filter.\n\n    Uses :py:func:`audiotools.core.dsp.DSPMixin.low_pass`.\n\n    Parameters\n    ----------\n    cutoff : tuple, optional\n        Cutoff frequency distribution,\n        by default ``(\"choice\", [4000, 8000, 16000])``\n    zeros : int, optional\n        Number of zero-crossings in filter, argument to\n        ``julius.LowPassFilters``, by default 51\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            cutoff: tuple=(\"choice\", [4000, 8000, 16000]),\n            zeros: int=51,\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(name=name, prob=prob)\n\n        self.cutoff = cutoff\n        self.zeros = zeros\n\n    def _instantiate(self, state: RandomState):\n        return {\"cutoff\": util.sample_from_dist(self.cutoff, state)}\n\n    def _transform(self, signal, cutoff):\n        return signal.low_pass(cutoff, zeros=self.zeros)\n\n\nclass HighPass(BaseTransform):\n    \"\"\"Applies a HighPass filter.\n\n    Uses :py:func:`audiotools.core.dsp.DSPMixin.high_pass`.\n\n    Parameters\n    ----------\n    cutoff : tuple, optional\n        Cutoff frequency distribution,\n        by default ``(\"choice\", [50, 100, 250, 500, 1000])``\n    zeros : int, optional\n        Number of zero-crossings in filter, argument to\n        ``julius.LowPassFilters``, by default 51\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            cutoff: tuple=(\"choice\", [50, 100, 250, 500, 1000]),\n            zeros: int=51,\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(name=name, prob=prob)\n\n        self.cutoff = cutoff\n        self.zeros = zeros\n\n    def _instantiate(self, state: RandomState):\n        return {\"cutoff\": util.sample_from_dist(self.cutoff, state)}\n\n    def _transform(self, signal, cutoff):\n        return signal.high_pass(cutoff, zeros=self.zeros)\n\n\nclass FrequencyMask(SpectralTransform):\n    \"\"\"Masks a band of frequencies at a center frequency\n    from the audio.\n\n    Uses :py:func:`audiotools.core.dsp.DSPMixin.mask_frequencies`.\n\n    Parameters\n    ----------\n    f_center : tuple, optional\n        Center frequency between 0.0 and 1.0 (Nyquist), by default (\"uniform\", 0.0, 1.0)\n    f_width : tuple, optional\n        Width of zero'd out band, by default (\"const\", 0.1)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            f_center: tuple=(\"uniform\", 0.0, 1.0),\n            f_width: tuple=(\"const\", 0.1),\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(name=name, prob=prob)\n        self.f_center = f_center\n        self.f_width = f_width\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal):\n        f_center = util.sample_from_dist(self.f_center, state)\n        f_width = util.sample_from_dist(self.f_width, state)\n\n        fmin = max(f_center - (f_width / 2), 0.0)\n        fmax = min(f_center + (f_width / 2), 1.0)\n\n        fmin_hz = (signal.sample_rate / 2) * fmin\n        fmax_hz = (signal.sample_rate / 2) * fmax\n\n        return {\"fmin_hz\": fmin_hz, \"fmax_hz\": fmax_hz}\n\n    def _transform(self, signal, fmin_hz: float, fmax_hz: float):\n        return signal.mask_frequencies(fmin_hz=fmin_hz, fmax_hz=fmax_hz)\n\n\nclass TimeMask(SpectralTransform):\n    \"\"\"Masks out contiguous time-steps from signal.\n\n    Uses :py:func:`audiotools.core.dsp.DSPMixin.mask_timesteps`.\n\n    Parameters\n    ----------\n    t_center : tuple, optional\n        Center time in terms of 0.0 and 1.0 (duration of signal),\n        by default (\"uniform\", 0.0, 1.0)\n    t_width : tuple, optional\n        Width of dropped out portion, by default (\"const\", 0.025)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            t_center: tuple=(\"uniform\", 0.0, 1.0),\n            t_width: tuple=(\"const\", 0.025),\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(name=name, prob=prob)\n        self.t_center = t_center\n        self.t_width = t_width\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal):\n        t_center = util.sample_from_dist(self.t_center, state)\n        t_width = util.sample_from_dist(self.t_width, state)\n\n        tmin = max(t_center - (t_width / 2), 0.0)\n        tmax = min(t_center + (t_width / 2), 1.0)\n\n        tmin_s = signal.signal_duration * tmin\n        tmax_s = signal.signal_duration * tmax\n        return {\"tmin_s\": tmin_s, \"tmax_s\": tmax_s}\n\n    def _transform(self, signal, tmin_s: float, tmax_s: float):\n        return signal.mask_timesteps(tmin_s=tmin_s, tmax_s=tmax_s)\n\n\nclass Smoothing(BaseTransform):\n    \"\"\"Convolves the signal with a smoothing window.\n\n    Uses :py:func:`audiotools.core.effects.EffectMixin.convolve`.\n\n    Parameters\n    ----------\n    window_type : tuple, optional\n        Type of window to use, by default (\"const\", \"average\")\n    window_length : tuple, optional\n        Length of smoothing window, by\n        default (\"choice\", [8, 16, 32, 64, 128, 256, 512])\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            window_type: tuple=(\"const\", \"average\"),\n            window_length: tuple=(\"choice\", [8, 16, 32, 64, 128, 256, 512]),\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(name=name, prob=prob)\n        self.window_type = window_type\n        self.window_length = window_length\n\n    def _instantiate(self, state: RandomState, signal: AudioSignal=None):\n        window_type = util.sample_from_dist(self.window_type, state)\n        window_length = util.sample_from_dist(self.window_length, state)\n        window = signal.get_window(\n            window_type=window_type, window_length=window_length, device=\"cpu\")\n        return {\"window\": AudioSignal(window, signal.sample_rate)}\n\n    def _transform(self, signal, window):\n        sscale = signal.audio_data.abs().max(axis=-1, keepdim=True)\n        sscale[sscale == 0.0] = 1.0\n\n        out = signal.convolve(window)\n\n        oscale = out.audio_data.abs().max(axis=-1, keepdim=True)\n        oscale[oscale == 0.0] = 1.0\n\n        out = out * (sscale / oscale)\n        return out\n\n\nclass FrequencyNoise(FrequencyMask):\n    \"\"\"Similar to :py:func:`audiotools.data.transforms.FrequencyMask`, but\n    replaces with noise instead of zeros.\n\n    Parameters\n    ----------\n    f_center : tuple, optional\n        Center frequency between 0.0 and 1.0 (Nyquist), by default (\"uniform\", 0.0, 1.0)\n    f_width : tuple, optional\n        Width of zero'd out band, by default (\"const\", 0.1)\n    name : str, optional\n        Name of this transform, used to identify it in the dictionary\n        produced by ``self.instantiate``, by default None\n    prob : float, optional\n        Probability of applying this transform, by default 1.0\n    \"\"\"\n\n    def __init__(\n            self,\n            f_center: tuple=(\"uniform\", 0.0, 1.0),\n            f_width: tuple=(\"const\", 0.1),\n            name: str=None,\n            prob: float=1, ):\n        super().__init__(\n            f_center=f_center, f_width=f_width, name=name, prob=prob)\n\n    def _transform(self, signal, fmin_hz: float, fmax_hz: float):\n        signal = signal.mask_frequencies(fmin_hz=fmin_hz, fmax_hz=fmax_hz)\n        mag, phase = signal.magnitude, signal.phase\n\n        mag_r, phase_r = paddle.randn(\n            shape=mag.shape, dtype=mag.dtype), paddle.randn(\n                shape=phase.shape, dtype=phase.dtype)\n        mask = (mag == 0.0) * (phase == 0.0)\n\n        # mag[mask] = mag_r[mask]\n        # phase[mask] = phase_r[mask]\n        mag = paddle.where(mask, mag_r, mag)\n        phase = paddle.where(mask, phase_r, phase)\n\n        signal.magnitude = mag\n        signal.phase = phase\n        return signal\n"
  },
  {
    "path": "paddlespeech/audiotools/metrics/__init__.py",
    "content": "# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nFunctions for comparing AudioSignal objects to one another.\n\"\"\"\nfrom . import quality\n"
  },
  {
    "path": "paddlespeech/audiotools/metrics/quality.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/metrics/quality.py)\nimport os\n\nimport numpy as np\nimport paddle\n\nfrom ..core import AudioSignal\n\n\ndef visqol(\n        estimates: AudioSignal,\n        references: AudioSignal,\n        mode: str=\"audio\", ):\n    \"\"\"ViSQOL score.\n\n    Parameters\n    ----------\n    estimates : AudioSignal\n        Degraded AudioSignal\n    references : AudioSignal\n        Reference AudioSignal\n    mode : str, optional\n        'audio' or 'speech', by default 'audio'\n\n    Returns\n    -------\n    Tensor[float]\n        ViSQOL score (MOS-LQO)\n    \"\"\"\n    try:\n        from pyvisqol import visqol_lib_py\n        from pyvisqol.pb2 import visqol_config_pb2\n        from pyvisqol.pb2 import similarity_result_pb2\n    except ImportError:\n        from visqol import visqol_lib_py\n        from visqol.pb2 import visqol_config_pb2\n        from visqol.pb2 import similarity_result_pb2\n\n    config = visqol_config_pb2.VisqolConfig()\n    if mode == \"audio\":\n        target_sr = 48000\n        config.options.use_speech_scoring = False\n        svr_model_path = \"libsvm_nu_svr_model.txt\"\n    elif mode == \"speech\":\n        target_sr = 16000\n        config.options.use_speech_scoring = True\n        svr_model_path = \"lattice_tcditugenmeetpackhref_ls2_nl60_lr12_bs2048_learn.005_ep2400_train1_7_raw.tflite\"\n    else:\n        raise ValueError(f\"Unrecognized mode: {mode}\")\n    config.audio.sample_rate = target_sr\n    config.options.svr_model_path = os.path.join(\n        os.path.dirname(visqol_lib_py.__file__), \"model\", svr_model_path)\n\n    api = visqol_lib_py.VisqolApi()\n    api.Create(config)\n\n    estimates = estimates.clone().to_mono().resample(target_sr)\n    references = references.clone().to_mono().resample(target_sr)\n\n    visqols = []\n    for i in range(estimates.batch_size):\n        _visqol = api.Measure(\n            references.audio_data[i, 0].detach().cpu().numpy().astype(float),\n            estimates.audio_data[i, 0].detach().cpu().numpy().astype(float), )\n        visqols.append(_visqol.moslqo)\n    return paddle.to_tensor(np.array(visqols))\n\n\nif __name__ == \"__main__\":\n    signal = AudioSignal(paddle.randn([44100]), 44100)\n    print(visqol(signal, signal))\n"
  },
  {
    "path": "paddlespeech/audiotools/ml/__init__.py",
    "content": "# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import decorators\nfrom .accelerator import Accelerator\nfrom .basemodel import BaseModel\n"
  },
  {
    "path": "paddlespeech/audiotools/ml/accelerator.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/ml/accelerator.py)\nimport os\nimport typing\n\nimport paddle\nimport paddle.distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.io import SequenceSampler\n\n\nclass ResumableDistributedSampler(DistributedBatchSampler):\n    \"\"\"Distributed sampler that can be resumed from a given start index.\"\"\"\n\n    def __init__(self, dataset, start_idx: int=None, **kwargs):\n        super().__init__(dataset, **kwargs)\n        # Start index, allows to resume an experiment at the index it was\n        self.start_idx = start_idx // self.num_replicas if start_idx is not None else 0\n\n    def __iter__(self):\n        for i, idx in enumerate(super().__iter__()):\n            if i >= self.start_idx:\n                yield idx\n        self.start_idx = 0  # set the index back to 0 so for the next epoch\n\n\nclass ResumableSequentialSampler(SequenceSampler):\n    \"\"\"Sequential sampler that can be resumed from a given start index.\"\"\"\n\n    def __init__(self, dataset, start_idx: int=None, **kwargs):\n        super().__init__(dataset, **kwargs)\n        # Start index, allows to resume an experiment at the index it was\n        self.start_idx = start_idx if start_idx is not None else 0\n\n    def __iter__(self):\n        for i, idx in enumerate(super().__iter__()):\n            if i >= self.start_idx:\n                yield idx\n        self.start_idx = 0  # set the index back to 0 so for the next epoch\n\n\nclass Accelerator:\n    \"\"\"This class is used to prepare models and dataloaders for\n    usage with DDP or DP. Use the functions prepare_model, prepare_dataloader to\n    prepare the respective objects. In the case of models, they are moved to\n    the appropriate GPU. In the case of\n    dataloaders, a sampler is created and the dataloader is initialized with\n    that sampler.\n\n    If the world size is 1, prepare_model and prepare_dataloader are\n    no-ops. If the environment variable ``PADDLE_TRAINER_ID`` is not set, then the\n    script was launched without ``paddle.distributed.launch``, and ``DataParallel``\n    will be used instead of ``DistributedDataParallel`` (not recommended), if\n    the world size (number of GPUs) is greater than 1.\n\n    Parameters\n    ----------\n    amp : bool, optional\n        Whether or not to enable automatic mixed precision, by default False\n        (Note: This is a placeholder as PaddlePaddle doesn't have native support for AMP as of now)\n    \"\"\"\n\n    def __init__(self, amp: bool=False):\n        trainer_id = os.getenv(\"PADDLE_TRAINER_ID\", None)\n        self.world_size = paddle.distributed.get_world_size()\n\n        self.use_ddp = self.world_size > 1 and trainer_id is not None\n        self.use_dp = self.world_size > 1 and trainer_id is None\n        self.device = \"cpu\" if self.world_size == 0 else \"cuda\"\n\n        if self.use_ddp:\n            trainer_id = int(trainer_id)\n            dist.init_parallel_env()\n\n        self.local_rank = 0 if trainer_id is None else int(trainer_id)\n        self.amp = amp\n\n        class DummyScaler:\n            def __init__(self):\n                pass\n\n            def step(self, optimizer):\n                optimizer.step()\n\n            def scale(self, loss):\n                return loss\n\n            def unscale_(self, optimizer):\n                return optimizer\n\n            def update(self):\n                pass\n\n        self.scaler = paddle.amp.GradScaler() if self.amp else DummyScaler()\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        pass\n\n    def prepare_model(self, model: paddle.nn.Layer, **kwargs):\n        \"\"\"Prepares model for DDP or DP. The model is moved to\n        the device of the correct rank.\n\n        Parameters\n        ----------\n        model : paddle.nn.Layer\n            Model that is converted for DDP or DP.\n\n        Returns\n        -------\n        paddle.nn.Layer\n            Wrapped model, or original model if DDP and DP are turned off.\n        \"\"\"\n        if self.use_ddp:\n            model = paddle.nn.SyncBatchNorm.convert_sync_batchnorm(model)\n            model = paddle.DataParallel(model, **kwargs)\n        elif self.use_dp:\n            model = paddle.DataParallel(model, **kwargs)\n        return model\n\n    def autocast(self, *args, **kwargs):\n        return paddle.amp.auto_cast(self.amp, *args, **kwargs)\n\n    def backward(self, loss: paddle.Tensor):\n        \"\"\"Backwards pass.\n\n        Parameters\n        ----------\n        loss : paddle.Tensor\n            Loss value.\n        \"\"\"\n        scaled = self.scaler.scale(loss)  # scale the loss\n        scaled.backward()\n\n    def step(self, optimizer: paddle.optimizer.Optimizer):\n        \"\"\"Steps the optimizer.\n\n        Parameters\n        ----------\n        optimizer : paddle.optimizer.Optimizer\n            Optimizer to step forward.\n        \"\"\"\n        self.scaler.step(optimizer)\n\n    def update(self):\n        # https://www.paddlepaddle.org.cn/documentation/docs/zh/2.6/api/paddle/amp/GradScaler_cn.html#step-optimizer\n        self.scaler.update()\n\n    def prepare_dataloader(self,\n                           dataset: typing.Iterable,\n                           start_idx: int=None,\n                           **kwargs):\n        \"\"\"Wraps a dataset with a DataLoader, using the correct sampler if DDP is\n        enabled.\n\n        Parameters\n        ----------\n        dataset : typing.Iterable\n            Dataset to build Dataloader around.\n        start_idx : int, optional\n            Start index of sampler, useful if resuming from some epoch,\n            by default None\n\n        Returns\n        -------\n        DataLoader\n            Wrapped DataLoader.\n        \"\"\"\n\n        if self.use_ddp:\n            sampler = ResumableDistributedSampler(\n                dataset,\n                start_idx,\n                batch_size=kwargs.get(\"batch_size\", 1),\n                shuffle=kwargs.get(\"shuffle\", True),\n                drop_last=kwargs.get(\"drop_last\", False),\n                num_replicas=self.world_size,\n                rank=self.local_rank, )\n            if \"num_workers\" in kwargs:\n                kwargs[\"num_workers\"] = max(kwargs[\"num_workers\"] //\n                                            self.world_size, 1)\n        else:\n            sampler = ResumableSequentialSampler(dataset, start_idx)\n\n        dataloader = DataLoader(\n            dataset,\n            batch_sampler=sampler if self.use_ddp else None,\n            sampler=sampler if not self.use_ddp else None,\n            **kwargs, )\n        return dataloader\n\n    @staticmethod\n    def unwrap(model):\n        return model\n"
  },
  {
    "path": "paddlespeech/audiotools/ml/basemodel.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/ml/layers/base.py)\nimport inspect\nimport shutil\nimport tempfile\nimport typing\nfrom pathlib import Path\n\nimport paddle\nfrom paddle import nn\n\n\nclass BaseModel(nn.Layer):\n    \"\"\"This is a class that adds useful save/load functionality to a\n    ``paddle.nn.Layer`` object. ``BaseModel`` objects can be saved\n    as ``package`` easily, making them super easy to port between\n    machines without requiring a ton of dependencies. Files can also be\n    saved as just weights, in the standard way.\n\n    >>> class Model(ml.BaseModel):\n    >>>     def __init__(self, arg1: float = 1.0):\n    >>>         super().__init__()\n    >>>         self.arg1 = arg1\n    >>>         self.linear = nn.Linear(1, 1)\n    >>>\n    >>>     def forward(self, x):\n    >>>         return self.linear(x)\n    >>>\n    >>> model1 = Model()\n    >>>\n    >>> with tempfile.NamedTemporaryFile(suffix=\".pth\") as f:\n    >>>     model1.save(\n    >>>         f.name,\n    >>>     )\n    >>>     model2 = Model.load(f.name)\n    >>>     out2 = seed_and_run(model2, x)\n    >>>     assert paddle.allclose(out1, out2)\n    >>>\n    >>>     model1.save(f.name, package=True)\n    >>>     model2 = Model.load(f.name)\n    >>>     model2.save(f.name, package=False)\n    >>>     model3 = Model.load(f.name)\n    >>>     out3 = seed_and_run(model3, x)\n    >>>\n    >>> with tempfile.TemporaryDirectory() as d:\n    >>>     model1.save_to_folder(d, {\"data\": 1.0})\n    >>>     Model.load_from_folder(d)\n\n    \"\"\"\n\n    def save(\n            self,\n            path: str,\n            metadata: dict=None,\n            package: bool=False,\n            intern: list=[],\n            extern: list=[],\n            mock: list=[], ):\n        \"\"\"Saves the model, either as a package, or just as\n        weights, alongside some specified metadata.\n\n        Parameters\n        ----------\n        path : str\n            Path to save model to.\n        metadata : dict, optional\n            Any metadata to save alongside the model,\n            by default None\n        package : bool, optional\n            Whether to use ``package`` to save the model in\n            a format that is portable, by default True\n        intern : list, optional\n            List of additional libraries that are internal\n            to the model, used with package, by default []\n        extern : list, optional\n            List of additional libraries that are external to\n            the model, used with package, by default []\n        mock : list, optional\n            List of libraries to mock, used with package,\n            by default []\n\n        Returns\n        -------\n        str\n            Path to saved model.\n        \"\"\"\n        sig = inspect.signature(self.__class__)\n        args = {}\n\n        for key, val in sig.parameters.items():\n            arg_val = val.default\n            if arg_val is not inspect.Parameter.empty:\n                args[key] = arg_val\n\n        # Look up attibutes in self, and if any of them are in args,\n        # overwrite them in args.\n        for attribute in dir(self):\n            if attribute in args:\n                args[attribute] = getattr(self, attribute)\n\n        metadata = {} if metadata is None else metadata\n        metadata[\"kwargs\"] = args\n        if not hasattr(self, \"metadata\"):\n            self.metadata = {}\n        self.metadata.update(metadata)\n\n        if not package:\n            state_dict = {\"state_dict\": self.state_dict(), \"metadata\": metadata}\n            paddle.save(state_dict, str(path))\n        else:\n            raise NotImplementedError(\n                \"Currently Paddle does not support packaging\")\n\n        return path\n\n    @property\n    def device(self):\n        \"\"\"Gets the device the model is on by looking at the device of\n        the first parameter. May not be valid if model is split across\n        multiple devices.\n        \"\"\"\n        return list(self.parameters())[0].place\n\n    @classmethod\n    def load(\n            cls,\n            location: str,\n            *args,\n            package_name: str=None,\n            strict: bool=False,\n            **kwargs, ):\n        \"\"\"Load model from a path. Tries first to load as a package, and if\n        that fails, tries to load as weights. The arguments to the class are\n        specified inside the model weights file.\n\n        Parameters\n        ----------\n        location : str\n            Path to file.\n        package_name : str, optional\n            Name of package, by default ``cls.__name__``.\n        strict : bool, optional\n            Ignore unmatched keys, by default False\n        kwargs : dict\n            Additional keyword arguments to the model instantiation, if\n            not loading from package.\n\n        Returns\n        -------\n        BaseModel\n            A model that inherits from BaseModel.\n        \"\"\"\n        model_dict = paddle.load(location)\n        metadata = model_dict[\"metadata\"]\n        metadata[\"kwargs\"].update(kwargs)\n\n        sig = inspect.signature(cls)\n        class_keys = list(sig.parameters.keys())\n        for k in list(metadata[\"kwargs\"].keys()):\n            if k not in class_keys:\n                metadata[\"kwargs\"].pop(k)\n\n        model = cls(*args, **metadata[\"kwargs\"])\n        model.set_state_dict(model_dict[\"state_dict\"])\n        model.metadata = metadata\n\n        return model\n\n    def save_to_folder(\n            self,\n            folder: typing.Union[str, Path],\n            extra_data: dict=None,\n            package: bool=False, ):\n        \"\"\"Dumps a model into a folder, as both a package\n        and as weights, as well as anything specified in\n        ``extra_data``. ``extra_data`` is a dictionary of other\n        pickleable files, with the keys being the paths\n        to save them in. The model is saved under a subfolder\n        specified by the name of the class (e.g. ``folder/generator/[package, weights].pth``\n        if the model name was ``Generator``).\n\n        >>> with tempfile.TemporaryDirectory() as d:\n        >>>     extra_data = {\n        >>>         \"optimizer.pth\": optimizer.state_dict()\n        >>>     }\n        >>>     model.save_to_folder(d, extra_data)\n        >>>     Model.load_from_folder(d)\n\n        Parameters\n        ----------\n        folder : typing.Union[str, Path]\n            _description_\n        extra_data : dict, optional\n            _description_, by default None\n\n        Returns\n        -------\n        str\n            Path to folder\n        \"\"\"\n        extra_data = {} if extra_data is None else extra_data\n        model_name = type(self).__name__.lower()\n        target_base = Path(f\"{folder}/{model_name}/\")\n        target_base.mkdir(exist_ok=True, parents=True)\n\n        if package:\n            package_path = target_base / f\"package.pth\"\n            self.save(package_path)\n\n        weights_path = target_base / f\"weights.pth\"\n        self.save(weights_path, package=False)\n\n        for path, obj in extra_data.items():\n            paddle.save(obj, str(target_base / path))\n\n        return target_base\n\n    @classmethod\n    def load_from_folder(\n            cls,\n            folder: typing.Union[str, Path],\n            package: bool=False,\n            strict: bool=False,\n            **kwargs, ):\n        \"\"\"Loads the model from a folder generated by\n        :py:func:`audiotools.ml.layers.base.BaseModel.save_to_folder`.\n        Like that function, this one looks for a subfolder that has\n        the name of the class (e.g. ``folder/generator/[package, weights].pth`` if the\n        model name was ``Generator``).\n\n        Parameters\n        ----------\n        folder : typing.Union[str, Path]\n            _description_\n        package : bool, optional\n            Whether to use ``package`` to load the model,\n            loading the model from ``package.pth``.\n        strict : bool, optional\n            Ignore unmatched keys, by default False\n\n        Returns\n        -------\n        tuple\n            tuple of model and extra data as saved by\n            :py:func:`audiotools.ml.layers.base.BaseModel.save_to_folder`.\n        \"\"\"\n        folder = Path(folder) / cls.__name__.lower()\n        model_pth = \"package.pth\" if package else \"weights.pth\"\n        model_pth = folder / model_pth\n\n        model = cls.load(str(model_pth))\n        extra_data = {}\n        excluded = [\"package.pth\", \"weights.pth\"]\n        files = [\n            x for x in folder.glob(\"*\")\n            if x.is_file() and x.name not in excluded\n        ]\n        for f in files:\n            extra_data[f.name] = paddle.load(str(f), **kwargs)\n\n        return model, extra_data\n"
  },
  {
    "path": "paddlespeech/audiotools/ml/decorators.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/ml/decorators.py)\nimport math\nimport os\nimport time\nfrom collections import defaultdict\nfrom functools import wraps\n\nimport paddle\nimport paddle.distributed as dist\nfrom rich import box\nfrom rich.console import Console\nfrom rich.console import Group\nfrom rich.live import Live\nfrom rich.markdown import Markdown\nfrom rich.padding import Padding\nfrom rich.panel import Panel\nfrom rich.progress import BarColumn\nfrom rich.progress import Progress\nfrom rich.progress import SpinnerColumn\nfrom rich.progress import TimeElapsedColumn\nfrom rich.progress import TimeRemainingColumn\nfrom rich.rule import Rule\nfrom rich.table import Table\nfrom visualdl import LogWriter\n\n\n# This is here so that the history can be pickled.\ndef default_list():\n    return []\n\n\nclass Mean:\n    \"\"\"Keeps track of the running mean, along with the latest\n    value.\n    \"\"\"\n\n    def __init__(self):\n        self.reset()\n\n    def __call__(self):\n        mean = self.total / max(self.count, 1)\n        return mean\n\n    def reset(self):\n        self.count = 0\n        self.total = 0\n\n    def update(self, val):\n        if math.isfinite(val):\n            self.count += 1\n            self.total += val\n\n\ndef when(condition):\n    \"\"\"Runs a function only when the condition is met. The condition is\n    a function that is run.\n\n    Parameters\n    ----------\n    condition : Callable\n        Function to run to check whether or not to run the decorated\n        function.\n\n    Example\n    -------\n    Checkpoint only runs every 100 iterations, and only if the\n    local rank is 0.\n\n    >>> i = 0\n    >>> rank = 0\n    >>>\n    >>> @when(lambda: i % 100 == 0 and rank == 0)\n    >>> def checkpoint():\n    >>>     print(\"Saving to /runs/exp1\")\n    >>>\n    >>> for i in range(1000):\n    >>>     checkpoint()\n\n    \"\"\"\n\n    def decorator(fn):\n        @wraps(fn)\n        def decorated(*args, **kwargs):\n            if condition():\n                return fn(*args, **kwargs)\n\n        return decorated\n\n    return decorator\n\n\ndef timer(prefix: str=\"time\"):\n    \"\"\"Adds execution time to the output dictionary of the decorated\n    function. The function decorated by this must output a dictionary.\n    The key added will follow the form \"[prefix]/[name_of_function]\"\n\n    Parameters\n    ----------\n    prefix : str, optional\n        The key added will follow the form \"[prefix]/[name_of_function]\",\n        by default \"time\".\n    \"\"\"\n\n    def decorator(fn):\n        @wraps(fn)\n        def decorated(*args, **kwargs):\n            s = time.perf_counter()\n            output = fn(*args, **kwargs)\n            assert isinstance(output, dict)\n            e = time.perf_counter()\n            output[f\"{prefix}/{fn.__name__}\"] = e - s\n            return output\n\n        return decorated\n\n    return decorator\n\n\nclass Tracker:\n    \"\"\"\n    A tracker class that helps to monitor the progress of training and logging the metrics.\n\n    Attributes\n    ----------\n    metrics : dict\n        A dictionary containing the metrics for each label.\n    history : dict\n        A dictionary containing the history of metrics for each label.\n    writer : LogWriter\n        A LogWriter object for logging the metrics.\n    rank : int\n        The rank of the current process.\n    step : int\n        The current step of the training.\n    tasks : dict\n        A dictionary containing the progress bars and tables for each label.\n    pbar : Progress\n        A progress bar object for displaying the progress.\n    consoles : list\n        A list of console objects for logging.\n    live : Live\n        A Live object for updating the display live.\n\n    Methods\n    -------\n    print(msg: str)\n        Prints the given message to all consoles.\n    update(label: str, fn_name: str)\n        Updates the progress bar and table for the given label.\n    done(label: str, title: str)\n        Resets the progress bar and table for the given label and prints the final result.\n    track(label: str, length: int, completed: int = 0, op: dist.ReduceOp = dist.ReduceOp.AVG, ddp_active: bool = \"LOCAL_RANK\" in os.environ)\n        A decorator for tracking the progress and metrics of a function.\n    log(label: str, value_type: str = \"value\", history: bool = True)\n        A decorator for logging the metrics of a function.\n    is_best(label: str, key: str) -> bool\n        Checks if the latest value of the given key in the label is the best so far.\n    state_dict() -> dict\n        Returns a dictionary containing the state of the tracker.\n    load_state_dict(state_dict: dict) -> Tracker\n        Loads the state of the tracker from the given state dictionary.\n    \"\"\"\n\n    def __init__(\n            self,\n            writer: LogWriter=None,\n            log_file: str=None,\n            rank: int=0,\n            console_width: int=100,\n            step: int=0, ):\n        \"\"\"\n        Initializes the Tracker object.\n\n        Parameters\n        ----------\n        writer : LogWriter, optional\n            A LogWriter object for logging the metrics, by default None.\n        log_file : str, optional\n            The path to the log file, by default None.\n        rank : int, optional\n            The rank of the current process, by default 0.\n        console_width : int, optional\n            The width of the console, by default 100.\n        step : int, optional\n            The current step of the training, by default 0.\n        \"\"\"\n        self.metrics = {}\n        self.history = {}\n        self.writer = writer\n        self.rank = rank\n        self.step = step\n\n        # Create progress bars etc.\n        self.tasks = {}\n        self.pbar = Progress(\n            SpinnerColumn(),\n            \"[progress.description]{task.description}\",\n            \"{task.completed}/{task.total}\",\n            BarColumn(),\n            TimeElapsedColumn(),\n            \"/\",\n            TimeRemainingColumn(), )\n        self.consoles = [Console(width=console_width)]\n        self.live = Live(console=self.consoles[0], refresh_per_second=10)\n        if log_file is not None:\n            self.consoles.append(\n                Console(width=console_width, file=open(log_file, \"a\")))\n\n    def print(self, msg):\n        \"\"\"\n        Prints the given message to all consoles.\n\n        Parameters\n        ----------\n        msg : str\n            The message to be printed.\n        \"\"\"\n        if self.rank == 0:\n            for c in self.consoles:\n                c.log(msg)\n\n    def update(self, label, fn_name):\n        \"\"\"\n        Updates the progress bar and table for the given label.\n\n        Parameters\n        ----------\n        label : str\n            The label of the progress bar and table to be updated.\n        fn_name : str\n            The name of the function associated with the label.\n        \"\"\"\n        if self.rank == 0:\n            self.pbar.advance(self.tasks[label][\"pbar\"])\n\n            # Create table\n            table = Table(title=label, expand=True, box=box.MINIMAL)\n            table.add_column(\"key\", style=\"cyan\")\n            table.add_column(\"value\", style=\"bright_blue\")\n            table.add_column(\"mean\", style=\"bright_green\")\n\n            keys = self.metrics[label][\"value\"].keys()\n            for k in keys:\n                value = self.metrics[label][\"value\"][k]\n                mean = self.metrics[label][\"mean\"][k]()\n                table.add_row(k, f\"{value:10.6f}\", f\"{mean:10.6f}\")\n\n            self.tasks[label][\"table\"] = table\n            tables = [t[\"table\"] for t in self.tasks.values()]\n            group = Group(*tables, self.pbar)\n            self.live.update(\n                Group(\n                    Padding(\"\", (0, 0)),\n                    Rule(f\"[italic]{fn_name}()\", style=\"white\"),\n                    Padding(\"\", (0, 0)),\n                    Panel.fit(\n                        group,\n                        padding=(0, 5),\n                        title=\"[b]Progress\",\n                        border_style=\"blue\", ), ))\n\n    def done(self, label: str, title: str):\n        \"\"\"\n        Resets the progress bar and table for the given label and prints the final result.\n\n        Parameters\n        ----------\n        label : str\n            The label of the progress bar and table to be reset.\n        title : str\n            The title to be displayed when printing the final result.\n        \"\"\"\n        for label in self.metrics:\n            for v in self.metrics[label][\"mean\"].values():\n                v.reset()\n\n        if self.rank == 0:\n            self.pbar.reset(self.tasks[label][\"pbar\"])\n            tables = [t[\"table\"] for t in self.tasks.values()]\n            group = Group(Markdown(f\"# {title}\"), *tables, self.pbar)\n            self.print(group)\n\n    def track(\n            self,\n            label: str,\n            length: int,\n            completed: int=0,\n            op: dist.ReduceOp=dist.ReduceOp.AVG,\n            ddp_active: bool=\"LOCAL_RANK\" in os.environ, ):\n        \"\"\"\n        A decorator for tracking the progress and metrics of a function.\n\n        Parameters\n        ----------\n        label : str\n            The label to be associated with the progress and metrics.\n        length : int\n            The total number of iterations to be completed.\n        completed : int, optional\n            The number of iterations already completed, by default 0.\n        op : dist.ReduceOp, optional\n            The reduce operation to be used, by default dist.ReduceOp.AVG.\n        ddp_active : bool, optional\n            Whether the DistributedDataParallel is active, by default \"LOCAL_RANK\" in os.environ.\n        \"\"\"\n        self.tasks[label] = {\n            \"pbar\":\n            self.pbar.add_task(\n                f\"[white]Iteration ({label})\",\n                total=length,\n                completed=completed),\n            \"table\":\n            Table(),\n        }\n        self.metrics[label] = {\n            \"value\": defaultdict(),\n            \"mean\": defaultdict(lambda: Mean()),\n        }\n\n        def decorator(fn):\n            @wraps(fn)\n            def decorated(*args, **kwargs):\n                output = fn(*args, **kwargs)\n                if not isinstance(output, dict):\n                    self.update(label, fn.__name__)\n                    return output\n                # Collect across all DDP processes\n                scalar_keys = []\n                for k, v in output.items():\n                    if isinstance(v, (int, float)):\n                        v = paddle.to_tensor([v])\n                    if not paddle.is_tensor(v):\n                        continue\n                    if ddp_active and v.is_cuda:\n                        dist.all_reduce(v, op=op)\n                    output[k] = v.detach()\n                    if paddle.numel(v) == 1:\n                        scalar_keys.append(k)\n                        output[k] = v.item()\n\n                # Save the outputs to tracker\n                for k, v in output.items():\n                    if k not in scalar_keys:\n                        continue\n                    self.metrics[label][\"value\"][k] = v\n                    # Update the running mean\n                    self.metrics[label][\"mean\"][k].update(v)\n\n                self.update(label, fn.__name__)\n                return output\n\n            return decorated\n\n        return decorator\n\n    def log(self, label: str, value_type: str=\"value\", history: bool=True):\n        \"\"\"\n        A decorator for logging the metrics of a function.\n\n        Parameters\n        ----------\n        label : str\n            The label to be associated with the logging.\n        value_type : str, optional\n            The type of value to be logged, by default \"value\".\n        history : bool, optional\n            Whether to save the history of the metrics, by default True.\n        \"\"\"\n        assert value_type in [\"mean\", \"value\"]\n        if history:\n            if label not in self.history:\n                self.history[label] = defaultdict(default_list)\n\n        def decorator(fn):\n            @wraps(fn)\n            def decorated(*args, **kwargs):\n                output = fn(*args, **kwargs)\n                if self.rank == 0:\n                    nonlocal value_type, label\n                    metrics = self.metrics[label][value_type]\n                    for k, v in metrics.items():\n                        v = v() if isinstance(v, Mean) else v\n                        if self.writer is not None:\n                            self.writer.add_scalar(\n                                tag=f\"{k}/{label}\", value=v, step=self.step)\n                        if label in self.history:\n                            self.history[label][k].append(v)\n\n                    if label in self.history:\n                        self.history[label][\"step\"].append(self.step)\n\n                return output\n\n            return decorated\n\n        return decorator\n\n    def is_best(self, label, key):\n        \"\"\"\n        Checks if the latest value of the given key in the label is the best so far.\n\n        Parameters\n        ----------\n        label : str\n            The label of the metrics to be checked.\n        key : str\n            The key of the metric to be checked.\n\n        Returns\n        -------\n        bool\n            True if the latest value is the best so far, otherwise False.\n        \"\"\"\n        return self.history[label][key][-1] == min(self.history[label][key])\n\n    def state_dict(self):\n        \"\"\"\n        Returns a dictionary containing the state of the tracker.\n\n        Returns\n        -------\n        dict\n            A dictionary containing the history and step of the tracker.\n        \"\"\"\n        return {\"history\": self.history, \"step\": self.step}\n\n    def load_state_dict(self, state_dict):\n        \"\"\"\n        Loads the state of the tracker from the given state dictionary.\n\n        Parameters\n        ----------\n        state_dict : dict\n            A dictionary containing the history and step of the tracker.\n\n        Returns\n        -------\n        Tracker\n            The tracker object with the loaded state.\n        \"\"\"\n        self.history = state_dict[\"history\"]\n        self.step = state_dict[\"step\"]\n        return self\n"
  },
  {
    "path": "paddlespeech/audiotools/post.py",
    "content": "# MIT License, Copyright (c) 2023-Present, Descript.\n# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from audiotools(https://github.com/descriptinc/audiotools/blob/master/audiotools/post.py)\nimport typing\n\nimport paddle\n\nfrom paddlespeech.audiotools.core import AudioSignal\n\n\ndef audio_table(\n        audio_dict: dict,\n        first_column: str=None,\n        format_fn: typing.Callable=None,\n        **kwargs, ):\n    \"\"\"Embeds an audio table into HTML, or as the output cell\n    in a notebook.\n\n    Parameters\n    ----------\n    audio_dict : dict\n        Dictionary of data to embed.\n    first_column : str, optional\n        The label for the first column of the table, by default None\n    format_fn : typing.Callable, optional\n        How to format the data, by default None\n\n    Returns\n    -------\n    str\n        Table as a string\n\n    Examples\n    --------\n\n    >>> audio_dict = {}\n    >>> for i in range(signal_batch.batch_size):\n    >>>     audio_dict[i] = {\n    >>>         \"input\": signal_batch[i],\n    >>>         \"output\": output_batch[i]\n    >>>     }\n    >>> audiotools.post.audio_zip(audio_dict)\n\n    \"\"\"\n\n    output = []\n    columns = None\n\n    def _default_format_fn(label, x, **kwargs):\n        if paddle.is_tensor(x):\n            x = x.tolist()\n\n        if x is None:\n            return \".\"\n        elif isinstance(x, AudioSignal):\n            return x.embed(display=False, return_html=True, **kwargs)\n        else:\n            return str(x)\n\n    if format_fn is None:\n        format_fn = _default_format_fn\n\n    if first_column is None:\n        first_column = \".\"\n\n    for k, v in audio_dict.items():\n        if not isinstance(v, dict):\n            v = {\"Audio\": v}\n\n        v_keys = list(v.keys())\n        if columns is None:\n            columns = [first_column] + v_keys\n            output.append(\" | \".join(columns))\n\n            layout = \"|---\" + len(v_keys) * \"|:-:\"\n            output.append(layout)\n\n        formatted_audio = []\n        for col in columns[1:]:\n            formatted_audio.append(format_fn(col, v[col], **kwargs))\n\n        row = f\"| {k} | \"\n        row += \" | \".join(formatted_audio)\n        output.append(row)\n\n    output = \"\\n\" + \"\\n\".join(output)\n    return output\n"
  },
  {
    "path": "paddlespeech/cli/README.md",
    "content": "# PaddleSpeech Command Line\n\n([简体中文](./README_cn.md)|English)\n\n The simplest approach to use PaddleSpeech models.\n\n ## Help\n ```bash\n paddlespeech help\n ```\n ## Audio Classification\n ```bash\n paddlespeech cls --input input.wav\n ```\n\n ## Speaker Verification\n\n ```bash\n paddlespeech vector --task spk --input input_16k.wav\n ```\n\n ## Automatic Speech Recognition\n ```\n paddlespeech asr --lang zh --input input_16k.wav\n ```\n \n ## Speech Translation (English to Chinese)\n \n (not support for Windows now)\n ```bash\n paddlespeech st --input input_16k.wav\n ```\n \n ## Text-to-Speech\n ```bash\n paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n ```\n \n ## Text Post-precessing\n\n- Punctuation Restoration\n  ```bash\n  paddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n  ```\n- Faster Punctuation Restoration\n  ```bash\n  paddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭 --model ernie_linear_p3_wudao_fast\n  ```\n"
  },
  {
    "path": "paddlespeech/cli/README_cn.md",
    "content": "# PaddleSpeech 命令行工具\n\n(简体中文|[English](./README.md))\n\n`paddlespeech.cli` 模块是 PaddleSpeech 的命令行工具，它提供了最简便的方式调用 PaddleSpeech 提供的不同语音应用场景的预训练模型，用一行命令就可以进行模型预测：\n\n ## 命令行使用帮助\n ```bash\n paddlespeech help\n ```\n\n ## 声音分类\n ```bash\n paddlespeech cls --input input.wav\n ```\n\n  ## 声纹识别\n\n ```bash\n paddlespeech vector --task spk --input input_16k.wav\n ```\n\n ## 语音识别\n ```\n paddlespeech asr --lang zh --input input_16k.wav\n ```\n \n ## 语音翻译（英-中）\n \n (暂不支持Windows系统)\n ```bash\n paddlespeech st --input input_16k.wav\n ```\n \n ## 语音合成\n ```bash\n paddlespeech tts --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n ```\n \n ## 文本后处理\n\n- 标点恢复\n  ```bash\n  paddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭\n  ```\n- 快速标点恢复\n  ```bash\n  paddlespeech text --task punc --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭 --model ernie_linear_p3_wudao_fast\n  ```\n"
  },
  {
    "path": "paddlespeech/cli/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport _locale\n\nfrom .base_commands import BaseCommand\nfrom .base_commands import HelpCommand\n\n_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])\n"
  },
  {
    "path": "paddlespeech/cli/asr/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import ASRExecutor\n"
  },
  {
    "path": "paddlespeech/cli/asr/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport io\nimport os\nimport sys\nimport time\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom ...utils.env import MODEL_HOME\nfrom ..download import get_path_from_url\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import CLI_TIMER\nfrom ..utils import stats_wrapper\nfrom ..utils import timer_register\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = ['ASRExecutor']\n\n\n@timer_register\nclass ASRExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__(task='asr', inference_type='offline')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.asr', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Audio file to recognize.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='conformer_u2pp_online_wenetspeech',\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help='Choose model type of asr task.')\n        self.parser.add_argument(\n            '--lang',\n            type=str,\n            default='zh',\n            help='Choose model language. [zh, en, zh_en], zh:[conformer_wenetspeech-zh-16k], en:[transformer_librispeech-en-16k], zh_en:[conformer_talcs-codeswitch_zh_en-16k]'\n        )\n        self.parser.add_argument(\n            '--codeswitch',\n            type=bool,\n            default=False,\n            help='Choose whether use code-switch. True or False.')\n        self.parser.add_argument(\n            \"--sample_rate\",\n            type=int,\n            default=16000,\n            choices=[8000, 16000],\n            help='Choose the audio sample rate of the model. 8000 or 16000')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of asr task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--decode_method',\n            type=str,\n            default='attention_rescoring',\n            choices=[\n                'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention',\n                'attention_rescoring'\n            ],\n            help='only support transformer and conformer model')\n        self.parser.add_argument(\n            '--num_decoding_left_chunks',\n            '-num_left',\n            type=str,\n            default=-1,\n            help='only support transformer and conformer online model')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--yes',\n            '-y',\n            action=\"store_true\",\n            default=False,\n            help='No additional parameters required. \\\n            Once set this parameter, it means accepting the request of the program by default, \\\n            which includes transforming the audio sample rate')\n        self.parser.add_argument(\n            '--rtf',\n            action=\"store_true\",\n            default=False,\n            help='Show Real-time Factor(RTF).')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _init_from_path(self,\n                        model_type: str='wenetspeech',\n                        lang: str='zh',\n                        codeswitch: bool=False,\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='attention_rescoring',\n                        num_decoding_left_chunks: int=-1,\n                        ckpt_path: Optional[os.PathLike]=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        logger.debug(\"start to init the model\")\n        # default max_len: unit:second\n        self.max_len = 50\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        if cfg_path is None or ckpt_path is None:\n            sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n            if lang == \"zh_en\" and codeswitch is True:\n                tag = model_type + '-' + 'codeswitch_' + lang + '-' + sample_rate_str\n            elif lang == \"zh_en\" or codeswitch is True:\n                raise Exception(\"codeswitch is true only in zh_en model\")\n            else:\n                tag = model_type + '-' + lang + '-' + sample_rate_str\n            self.task_resource.set_task_model(tag, version=None)\n            self.res_path = self.task_resource.res_dir\n\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.res_path,\n                self.task_resource.res_dict['ckpt_path'] + \".pdparams\")\n            logger.debug(self.res_path)\n\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path + \".pdparams\")\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n        logger.debug(self.cfg_path)\n        logger.debug(self.ckpt_path)\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        with UpdateConfig(self.config):\n            if self.config.spm_model_prefix:\n                self.config.spm_model_prefix = os.path.join(\n                    self.res_path, self.config.spm_model_prefix)\n            self.text_feature = TextFeaturizer(\n                unit_type=self.config.unit_type,\n                vocab=self.config.vocab_filepath,\n                spm_model_prefix=self.config.spm_model_prefix)\n            if \"deepspeech2\" in model_type:\n                self.config.decode.lang_model_path = os.path.join(\n                    MODEL_HOME, 'language_model',\n                    self.config.decode.lang_model_path)\n\n                lm_url = self.task_resource.res_dict['lm_url']\n                lm_md5 = self.task_resource.res_dict['lm_md5']\n                self.download_lm(\n                    lm_url,\n                    os.path.dirname(self.config.decode.lang_model_path), lm_md5)\n\n            elif \"conformer\" in model_type or \"transformer\" in model_type:\n                self.config.decode.decoding_method = decode_method\n                if num_decoding_left_chunks:\n                    assert num_decoding_left_chunks == -1 or num_decoding_left_chunks >= 0, \"num_decoding_left_chunks should be -1 or >=0\"\n                    self.config.num_decoding_left_chunks = num_decoding_left_chunks\n\n            else:\n                raise Exception(\"wrong type\")\n        model_name = model_type[:model_type.rindex(\n            '_')]  # model_type: {model_name}_{dataset}\n        model_class = self.task_resource.get_model_class(model_name)\n        model_conf = self.config\n        model = model_class.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        model_dict = paddle.load(self.ckpt_path)\n        self.model.set_state_dict(model_dict)\n\n        # compute the max len limit\n        if \"conformer\" in model_type or \"transformer\" in model_type:\n            # in transformer like model, we may use the subsample rate cnn network\n            subsample_rate = self.model.subsampling_rate()\n            frame_shift_ms = self.config.preprocess_config.process[0][\n                'n_shift'] / self.config.preprocess_config.process[0]['fs']\n            max_len = self.model.encoder.embed.pos_enc.max_len\n\n            if self.config.encoder_conf.get(\"max_len\", None):\n                max_len = self.config.encoder_conf.max_len\n\n            self.max_len = frame_shift_ms * max_len * subsample_rate\n            logger.debug(\n                f\"The asr server limit max duration len: {self.max_len}\")\n\n    def preprocess(self, model_type: str, input: Union[str, os.PathLike]):\n        \"\"\"\n        Input preprocess and return paddle.Tensor stored in self.input.\n        Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n\n        audio_file = input\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(\"Preprocess audio_file:\" + audio_file)\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        # Get the object for feature extraction\n        if \"deepspeech2\" in model_type or \"conformer\" in model_type or \"transformer\" in model_type:\n            logger.debug(\"get the preprocess conf\")\n            preprocess_conf = self.config.preprocess_config\n            preprocess_args = {\"train\": False}\n            preprocessing = Transformation(preprocess_conf)\n            logger.debug(\"read the audio file\")\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            if self.change_format:\n                if audio.shape[1] >= 2:\n                    audio = audio.mean(axis=1, dtype=np.int16)\n                else:\n                    audio = audio[:, 0]\n                # pcm16 -> pcm 32\n                audio = self._pcm16to32(audio)\n                audio = librosa.resample(\n                    audio,\n                    orig_sr=audio_sample_rate,\n                    target_sr=self.sample_rate)\n                audio_sample_rate = self.sample_rate\n                # pcm32 -> pcm 16\n                audio = self._pcm32to16(audio)\n            else:\n                audio = audio[:, 0]\n\n            logger.debug(f\"audio shape: {audio.shape}\")\n            # fbank\n            audio = preprocessing(audio, **preprocess_args)\n\n            audio_len = paddle.to_tensor(audio.shape[0]).unsqueeze(axis=0)\n            audio = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)\n\n            self._inputs[\"audio\"] = audio\n            self._inputs[\"audio_len\"] = audio_len\n            logger.debug(f\"audio feat shape: {audio.shape}\")\n\n        else:\n            raise Exception(\"wrong type\")\n\n        logger.debug(\"audio feat process success\")\n\n    @paddle.no_grad()\n    def infer(self, model_type: str):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        logger.debug(\"start to infer the model to get the output\")\n        cfg = self.config.decode\n        audio = self._inputs[\"audio\"]\n        audio_len = self._inputs[\"audio_len\"]\n        if \"deepspeech2\" in model_type:\n            decode_batch_size = audio.shape[0]\n            self.model.decoder.init_decoder(\n                decode_batch_size, self.text_feature.vocab_list,\n                cfg.decoding_method, cfg.lang_model_path, cfg.alpha, cfg.beta,\n                cfg.beam_size, cfg.cutoff_prob, cfg.cutoff_top_n,\n                cfg.num_proc_bsearch)\n\n            result_transcripts = self.model.decode(audio, audio_len)\n            self.model.decoder.del_decoder()\n            self._outputs[\"result\"] = result_transcripts[0]\n\n        elif \"conformer\" in model_type or \"transformer\" in model_type:\n            logger.debug(\n                f\"we will use the transformer like model : {model_type}\")\n            try:\n                result_transcripts = self.model.decode(\n                    audio,\n                    audio_len,\n                    text_feature=self.text_feature,\n                    decoding_method=cfg.decoding_method,\n                    beam_size=cfg.beam_size,\n                    ctc_weight=cfg.ctc_weight,\n                    decoding_chunk_size=cfg.decoding_chunk_size,\n                    num_decoding_left_chunks=cfg.num_decoding_left_chunks,\n                    simulate_streaming=cfg.simulate_streaming)\n                self._outputs[\"result\"] = result_transcripts[0][0]\n            except Exception as e:\n                logger.exception(e)\n\n        else:\n            raise Exception(\"invalid model name\")\n\n    def postprocess(self) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        return self._outputs[\"result\"]\n\n    def download_lm(self, url, lm_dir, md5sum):\n        download_path = get_path_from_url(\n            url=url,\n            root_dir=lm_dir,\n            md5sum=md5sum,\n            decompress=False, )\n\n    def _pcm16to32(self, audio):\n        assert (audio.dtype == np.int16)\n        audio = audio.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        audio = audio / (2**(bits - 1))\n        return audio\n\n    def _pcm32to16(self, audio):\n        assert (audio.dtype == np.float32)\n        bits = np.iinfo(np.int16).bits\n        audio = audio * (2**(bits - 1))\n        audio = np.round(audio).astype(\"int16\")\n        return audio\n\n    def _check(self, audio_file: str, sample_rate: int, force_yes: bool=False):\n        self.sample_rate = sample_rate\n        if self.sample_rate != 16000 and self.sample_rate != 8000:\n            logger.error(\n                \"invalid sample rate, please input --sr 8000 or --sr 16000\")\n            return False\n\n        if isinstance(audio_file, (str, os.PathLike)):\n            if not os.path.isfile(audio_file):\n                logger.error(\"Please input the right audio file path\")\n                return False\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        logger.debug(\"checking the audio file format......\")\n        try:\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            audio_duration = audio.shape[0] / audio_sample_rate\n            if audio_duration > self.max_len:\n                logger.error(\n                    f\"Please input audio file less then {self.max_len} seconds.\\n\"\n                )\n                return False\n        except Exception as e:\n            logger.exception(e)\n            logger.error(\n                f\"can not open the audio file, please check the audio file({audio_file}) format is 'wav'. \\n \\\n                 you can try to use sox to change the file format.\\n \\\n                 For example: \\n \\\n                 sample rate: 16k \\n \\\n                 sox input_audio.xx --rate 16k --bits 16 --channels 1 output_audio.wav \\n \\\n                 sample rate: 8k \\n \\\n                 sox input_audio.xx --rate 8k --bits 16 --channels 1 output_audio.wav \\n \\\n                 \")\n            return False\n        logger.debug(\"The sample rate is %d\" % audio_sample_rate)\n        if audio_sample_rate != self.sample_rate:\n            logger.warning(\"The sample rate of the input file is not {}.\\n \\\n                            The program will resample the wav file to {}.\\n \\\n                            If the result does not meet your expectations，\\n \\\n                            Please input the 16k 16 bit 1 channel wav file. \\\n                        \".format(self.sample_rate, self.sample_rate))\n            if force_yes is False:\n                while (True):\n                    logger.debug(\n                        \"Whether to change the sample rate and the channel. Y: change the sample. N: exit the prgream.\"\n                    )\n                    content = input(\"Input(Y/N):\")\n                    if content.strip() == \"Y\" or content.strip(\n                    ) == \"y\" or content.strip() == \"yes\" or content.strip(\n                    ) == \"Yes\":\n                        logger.debug(\n                            \"change the sampele rate, channel to 16k and 1 channel\"\n                        )\n                        break\n                    elif content.strip() == \"N\" or content.strip(\n                    ) == \"n\" or content.strip() == \"no\" or content.strip(\n                    ) == \"No\":\n                        logger.debug(\"Exit the program\")\n                        return False\n                    else:\n                        logger.warning(\"Not regular input, please input again\")\n\n            self.change_format = True\n        else:\n            logger.debug(\"The audio file format is right\")\n            self.change_format = False\n\n        return True\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model = parser_args.model\n        lang = parser_args.lang\n        codeswitch = parser_args.codeswitch\n        sample_rate = parser_args.sample_rate\n        config = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        decode_method = parser_args.decode_method\n        force_yes = parser_args.yes\n        rtf = parser_args.rtf\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(\n                    audio_file=input_,\n                    model=model,\n                    lang=lang,\n                    codeswitch=codeswitch,\n                    sample_rate=sample_rate,\n                    config=config,\n                    ckpt_path=ckpt_path,\n                    decode_method=decode_method,\n                    force_yes=force_yes,\n                    rtf=rtf,\n                    device=device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        if rtf:\n            self.show_rtf(CLI_TIMER[self.__class__.__name__])\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str='conformer_u2pp_online_wenetspeech',\n                 lang: str='zh',\n                 codeswitch: bool=False,\n                 sample_rate: int=16000,\n                 config: os.PathLike=None,\n                 ckpt_path: os.PathLike=None,\n                 decode_method: str='attention_rescoring',\n                 num_decoding_left_chunks: int=-1,\n                 force_yes: bool=False,\n                 rtf: bool=False,\n                 device=paddle.get_device()):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        audio_file = os.path.abspath(audio_file)\n        paddle.set_device(device)\n        self._init_from_path(model, lang, codeswitch, sample_rate, config,\n                             decode_method, num_decoding_left_chunks, ckpt_path)\n        if not self._check(audio_file, sample_rate, force_yes):\n            sys.exit(-1)\n        if rtf:\n            k = self.__class__.__name__\n            CLI_TIMER[k]['start'].append(time.time())\n\n        self.preprocess(model, audio_file)\n        self.infer(model)\n        res = self.postprocess()  # Retrieve result of asr.\n\n        if rtf:\n            CLI_TIMER[k]['end'].append(time.time())\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            CLI_TIMER[k]['extra'].append(audio.shape[0] / audio_sample_rate)\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/base_commands.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom typing import List\n\nimport numpy\nfrom prettytable import PrettyTable\n\nfrom ..resource import CommonTaskResource\nfrom .entry import commands\nfrom .utils import cli_register\nfrom .utils import explicit_command_register\nfrom .utils import get_command\n\n__all__ = ['BaseCommand', 'HelpCommand', 'StatsCommand']\n\n\n@cli_register(name='paddlespeech')\nclass BaseCommand:\n    def execute(self, argv: List[str]) -> bool:\n        help = get_command('paddlespeech.help')\n        return help().execute(argv)\n\n\n@cli_register(name='paddlespeech.help', description='Show help for commands.')\nclass HelpCommand:\n    def execute(self, argv: List[str]) -> bool:\n        msg = 'Usage:\\n'\n        msg += '    paddlespeech <command> <options>\\n\\n'\n        msg += 'Commands:\\n'\n        for command, detail in commands['paddlespeech'].items():\n            if command.startswith('_'):\n                continue\n\n            if '_description' not in detail:\n                continue\n            msg += '    {:<15}        {}\\n'.format(command,\n                                                   detail['_description'])\n\n        print(msg)\n        return True\n\n\n@cli_register(\n    name='paddlespeech.version',\n    description='Show version and commit id of current package.')\nclass VersionCommand:\n    def execute(self, argv: List[str]) -> bool:\n        try:\n            from .. import __version__\n            version = __version__\n        except ImportError:\n            version = 'Not an official release'\n\n        try:\n            from .. import __commit__\n            commit_id = __commit__\n        except ImportError:\n            commit_id = 'Not found'\n\n        msg = 'Package Version:\\n'\n        msg += '    {}\\n\\n'.format(version)\n        msg += 'Commit ID:\\n'\n        msg += '    {}\\n\\n'.format(commit_id)\n\n        print(msg)\n        return True\n\n\nmodel_name_format = {\n    'asr': 'Model-Size-Code Switch-Multilingual-Language-Sample Rate',\n    'cls': 'Model-Sample Rate',\n    'st': 'Model-Source language-Target language',\n    'text': 'Model-Task-Language',\n    'tts': 'Model-Language',\n    'vector': 'Model-Sample Rate',\n    'ssl': 'Model-Language-Sample Rate',\n    'whisper': 'Model-Language-Sample Rate'\n}\n\n\n@cli_register(\n    name='paddlespeech.stats',\n    description='Get speech tasks support models list.')\nclass StatsCommand:\n    def __init__(self):\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.stats', add_help=True)\n        self.task_choices = [\n            'asr', 'cls', 'st', 'text', 'tts', 'vector', 'kws', 'ssl', 'whisper'\n        ]\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default='asr',\n            choices=self.task_choices,\n            help='Choose speech task.',\n            required=True)\n\n    def show_support_models(self, pretrained_models: dict):\n        fields = model_name_format[self.task].split(\"-\")\n        table = PrettyTable(fields)\n        for key in pretrained_models:\n            line = key.split(\"-\")\n            if self.task == \"asr\" and len(line) < len(fields):\n                for i in range(len(line), len(fields)):\n                    line.append(\"-\")\n                if \"codeswitch\" in key:\n                    line[3], line[1] = line[1].split(\"_\")[0], line[1].split(\n                        \"_\")[1:]\n                elif \"multilingual\" in key:\n                    line[4], line[1] = line[1].split(\"_\")[0], line[1].split(\n                        \"_\")[1:]\n                # Avoid having arrays within the elements of the input parameters when passing them to numpy.array\n                if type(line[1]) is list:\n                    line[1] = \"/\".join(line[1])\n                tmp = numpy.array(line)\n                idx = [0, 5, 3, 4, 1, 2]\n                line = tmp[idx]\n            table.add_row(line)\n\n        print(table)\n\n    def execute(self, argv: List[str]) -> bool:\n        parser_args = self.parser.parse_args(argv)\n        self.task = parser_args.task\n        if self.task not in self.task_choices:\n            print(\"Please input correct speech task, choices = \" + str(\n                self.task_choices))\n            return\n\n        pretrained_models = CommonTaskResource(task=self.task).pretrained_models\n\n        try:\n            print(\n                \"Here is the list of {} pretrained models released by PaddleSpeech that can be used by command line and python API\"\n                .format(self.task.upper()))\n            self.show_support_models(pretrained_models)\n            return True\n        except BaseException:\n            print(\"Failed to get the list of {} pretrained models.\".format(\n                self.task.upper()))\n            return False\n\n\n# Dynamic import when running specific command\n_commands = {\n    'asr': ['Speech to text infer command.', 'ASRExecutor'],\n    'cls': ['Audio classification infer command.', 'CLSExecutor'],\n    'st': ['Speech translation infer command.', 'STExecutor'],\n    'text': ['Text command.', 'TextExecutor'],\n    'tts': ['Text to Speech infer command.', 'TTSExecutor'],\n    'vector': ['Speech to vector embedding infer command.', 'VectorExecutor'],\n    'kws': ['Keyword Spotting infer command.', 'KWSExecutor'],\n    'ssl':\n    ['Self-Supervised Learning Pretrained model infer command.', 'SSLExecutor'],\n    'whisper': [\n        'Whisper model for speech to text or translate speech to English.',\n        'WhisperExecutor'\n    ]\n}\n\nfor com, info in _commands.items():\n    explicit_command_register(\n        name='paddlespeech.{}'.format(com),\n        description=info[0],\n        cls='paddlespeech.cli.{}.{}'.format(com, info[1]))\n"
  },
  {
    "path": "paddlespeech/cli/cls/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import CLSExecutor\n"
  },
  {
    "path": "paddlespeech/cli/cls/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle.audio.features import LogMelSpectrogram\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import stats_wrapper\nfrom paddlespeech.audio.backends import soundfile_load as load\n\n__all__ = ['CLSExecutor']\n\n\nclass CLSExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__(task='cls')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.cls', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Audio file to classify.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='panns_cnn14',\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help='Choose model type of cls task.')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of cls task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--label_file',\n            type=str,\n            default=None,\n            help='Label file of cls task.')\n        self.parser.add_argument(\n            '--topk',\n            type=int,\n            default=1,\n            help='Return topk scores of classification result.')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _init_from_path(self,\n                        model_type: str='panns_cnn14',\n                        cfg_path: Optional[os.PathLike]=None,\n                        ckpt_path: Optional[os.PathLike]=None,\n                        label_file: Optional[os.PathLike]=None):\n        \"\"\"\n            Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        if label_file is None or ckpt_path is None:\n            tag = model_type + '-' + '32k'  # panns_cnn14-32k\n            self.task_resource.set_task_model(tag, version=None)\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.label_file = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['label_file'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.label_file = os.path.abspath(label_file)\n            self.ckpt_path = os.path.abspath(ckpt_path)\n\n        # config\n        with open(self.cfg_path, 'r') as f:\n            self._conf = yaml.safe_load(f)\n\n        # labels\n        self._label_list = []\n        with open(self.label_file, 'r') as f:\n            for line in f:\n                self._label_list.append(line.strip())\n\n        # model\n        model_class = self.task_resource.get_model_class(model_type)\n        model_dict = paddle.load(self.ckpt_path)\n        self.model = model_class(extract_embedding=False)\n        self.model.set_state_dict(model_dict)\n        self.model.eval()\n\n    def preprocess(self, audio_file: Union[str, os.PathLike]):\n        \"\"\"\n            Input preprocess and return paddle.Tensor stored in self.input.\n            Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n        feat_conf = self._conf['feature']\n        logger.debug(feat_conf)\n        waveform, _ = load(\n            file=audio_file,\n            sr=feat_conf['sample_rate'],\n            mono=True,\n            dtype='float32')\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(\"Preprocessing audio_file:\" + audio_file)\n\n        # set 'pad_mode' be 'constant' when device is npu, otherwise be the default 'pad_mode' value\n        if paddle.get_device().startswith('npu'):\n            pad_mode_kwarg = {\"pad_mode\": \"constant\"}\n        else:\n            pad_mode_kwarg = {}\n\n        # Feature extraction\n        feature_extractor = LogMelSpectrogram(\n            sr=feat_conf['sample_rate'],\n            n_fft=feat_conf['n_fft'],\n            hop_length=feat_conf['hop_length'],\n            window=feat_conf['window'],\n            win_length=feat_conf['window_length'],\n            f_min=feat_conf['f_min'],\n            f_max=feat_conf['f_max'],\n            n_mels=feat_conf['n_mels'],\n            **pad_mode_kwarg, )\n        feats = feature_extractor(\n            paddle.to_tensor(paddle.to_tensor(waveform).unsqueeze(0)))\n        self._inputs['feats'] = paddle.transpose(feats, [0, 2, 1]).unsqueeze(\n            1)  # [B, N, T] -> [B, 1, T, N]\n\n    @paddle.no_grad()\n    def infer(self):\n        \"\"\"\n            Model inference and result stored in self.output.\n        \"\"\"\n        self._outputs['logits'] = self.model(self._inputs['feats'])\n\n    def _generate_topk_label(self, result: np.ndarray, topk: int) -> str:\n        assert topk <= len(\n            self._label_list), 'Value of topk is larger than number of labels.'\n\n        topk_idx = (-result).argsort()[:topk]\n        ret = ''\n        for idx in topk_idx:\n            label, score = self._label_list[idx], result[idx]\n            ret += f'{label} {score} '\n        return ret\n\n    def postprocess(self, topk: int) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        return self._generate_topk_label(\n            result=self._outputs['logits'].squeeze(0).numpy(), topk=topk)\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model_type = parser_args.model\n        label_file = parser_args.label_file\n        cfg_path = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        topk = parser_args.topk\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(input_, model_type, cfg_path, ckpt_path, label_file,\n                           topk, device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str='panns_cnn14',\n                 config: Optional[os.PathLike]=None,\n                 ckpt_path: Optional[os.PathLike]=None,\n                 label_file: Optional[os.PathLike]=None,\n                 topk: int=1,\n                 device: str=paddle.get_device()):\n        \"\"\"\n            Python API to call an executor.\n        \"\"\"\n        audio_file = os.path.abspath(os.path.expanduser(audio_file))\n        paddle.set_device(device)\n        self._init_from_path(model, config, ckpt_path, label_file)\n        self.preprocess(audio_file)\n        self.infer()\n        res = self.postprocess(topk)  # Retrieve result of cls.\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/download.py",
    "content": "#   Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport hashlib\nimport os\nimport os.path as osp\nimport shutil\nimport subprocess\nimport tarfile\nimport time\nimport zipfile\n\nimport requests\nfrom tqdm import tqdm\n\nfrom .log import logger\n\n__all__ = ['get_path_from_url']\n\nDOWNLOAD_RETRY_LIMIT = 3\n\n\ndef _is_url(path):\n    \"\"\"\n    Whether path is URL.\n    Args:\n        path (string): URL string or not.\n    \"\"\"\n    return path.startswith('http://') or path.startswith('https://')\n\n\ndef _map_path(url, root_dir):\n    # parse path after download under root_dir\n    fname = osp.split(url)[-1]\n    fpath = fname\n    return osp.join(root_dir, fpath)\n\n\ndef _get_unique_endpoints(trainer_endpoints):\n    # Sorting is to avoid different environmental variables for each card\n    trainer_endpoints.sort()\n    ips = set()\n    unique_endpoints = set()\n    for endpoint in trainer_endpoints:\n        ip = endpoint.split(\":\")[0]\n        if ip in ips:\n            continue\n        ips.add(ip)\n        unique_endpoints.add(endpoint)\n    logger.debug(\"unique_endpoints {}\".format(unique_endpoints))\n    return unique_endpoints\n\n\ndef get_path_from_url(url,\n                      root_dir,\n                      md5sum=None,\n                      check_exist=True,\n                      decompress=True,\n                      method='get'):\n    \"\"\" Download from given url to root_dir.\n    if file or directory specified by url is exists under\n    root_dir, return the path directly, otherwise download\n    from url and decompress it, return the path.\n    Args:\n        url (str): download url\n        root_dir (str): root dir for downloading, it should be\n                        WEIGHTS_HOME or DATASET_HOME\n        md5sum (str): md5 sum of download package\n        decompress (bool): decompress zip or tar file. Default is `True`\n        method (str): which download method to use. Support `wget` and `get`. Default is `get`.\n    Returns:\n        str: a local path to save downloaded models & weights & datasets.\n    \"\"\"\n\n    from paddle.distributed import ParallelEnv\n\n    assert _is_url(url), \"downloading from {} not a url\".format(url)\n    # parse path after download to decompress under root_dir\n    fullpath = _map_path(url, root_dir)\n    # Mainly used to solve the problem of downloading data from different \n    # machines in the case of multiple machines. Different ips will download \n    # data, and the same ip will only download data once.\n    unique_endpoints = _get_unique_endpoints(ParallelEnv().trainer_endpoints[:])\n    if osp.exists(fullpath) and check_exist and _md5check(fullpath, md5sum):\n        logger.debug(\"Found {}\".format(fullpath))\n    else:\n        if ParallelEnv().current_endpoint in unique_endpoints:\n            fullpath = _download(url, root_dir, md5sum, method=method)\n        else:\n            while not os.path.exists(fullpath):\n                time.sleep(1)\n\n    if ParallelEnv().current_endpoint in unique_endpoints:\n        if decompress and (tarfile.is_tarfile(fullpath) or\n                           zipfile.is_zipfile(fullpath)):\n            fullpath = _decompress(fullpath)\n\n    return fullpath\n\n\ndef _get_download(url, fullname):\n    # using requests.get method\n    fname = osp.basename(fullname)\n    try:\n        req = requests.get(url, stream=True)\n    except Exception as e:  # requests.exceptions.ConnectionError\n        logger.debug(\"Downloading {} from {} failed with exception {}\".format(\n            fname, url, str(e)))\n        return False\n\n    if req.status_code != 200:\n        raise RuntimeError(\"Downloading from {} failed with code \"\n                           \"{}!\".format(url, req.status_code))\n\n    # For protecting download interupted, download to\n    # tmp_fullname firstly, move tmp_fullname to fullname\n    # after download finished\n    tmp_fullname = fullname + \"_tmp\"\n    total_size = req.headers.get('content-length')\n    with open(tmp_fullname, 'wb') as f:\n        if total_size:\n            with tqdm(total=(int(total_size)), unit='B', unit_scale=True) as pbar:\n                for chunk in req.iter_content(chunk_size=1024):\n                    f.write(chunk)\n                    pbar.update(len(chunk))\n        else:\n            for chunk in req.iter_content(chunk_size=1024):\n                if chunk:\n                    f.write(chunk)\n    shutil.move(tmp_fullname, fullname)\n\n    return fullname\n\n\ndef _wget_download(url, fullname):\n    # using wget to download url\n    tmp_fullname = fullname + \"_tmp\"\n    # –user-agent\n    command = 'wget -O {} -t {} {}'.format(tmp_fullname, DOWNLOAD_RETRY_LIMIT,\n                                           url)\n    subprc = subprocess.Popen(\n        command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n    _ = subprc.communicate()\n\n    if subprc.returncode != 0:\n        raise RuntimeError(\n            '{} failed. Please make sure `wget` is installed or {} exists'.\n            format(command, url))\n\n    shutil.move(tmp_fullname, fullname)\n\n    return fullname\n\n\n_download_methods = {\n    'get': _get_download,\n    'wget': _wget_download,\n}\n\n\ndef _download(url, path, md5sum=None, method='get'):\n    \"\"\"\n    Download from url, save to path.\n    url (str): download url\n    path (str): download to given path\n    md5sum (str): md5 sum of download package\n    method (str): which download method to use. Support `wget` and `get`. Default is `get`.\n    \"\"\"\n    assert method in _download_methods, 'make sure `{}` implemented'.format(\n        method)\n\n    if not osp.exists(path):\n        os.makedirs(path)\n\n    fname = osp.split(url)[-1]\n    fullname = osp.join(path, fname)\n    retry_cnt = 0\n\n    logger.debug(\"Downloading {} from {}\".format(fname, url))\n    while not (osp.exists(fullname) and _md5check(fullname, md5sum)):\n        if retry_cnt < DOWNLOAD_RETRY_LIMIT:\n            retry_cnt += 1\n        else:\n            raise RuntimeError(\"Download from {} failed. \"\n                               \"Retry limit reached\".format(url))\n\n        if not _download_methods[method](url, fullname):\n            time.sleep(1)\n            continue\n\n    return fullname\n\n\ndef _md5check(fullname, md5sum=None):\n    if md5sum is None:\n        return True\n\n    logger.debug(\"File {} md5 checking...\".format(fullname))\n    md5 = hashlib.md5()\n    with open(fullname, 'rb') as f:\n        for chunk in iter(lambda: f.read(4096), b\"\"):\n            md5.update(chunk)\n    calc_md5sum = md5.hexdigest()\n\n    if calc_md5sum != md5sum:\n        logger.debug(\"File {} md5 check failed, {}(calc) != \"\n                     \"{}(base)\".format(fullname, calc_md5sum, md5sum))\n        return False\n    return True\n\n\ndef _decompress(fname):\n    \"\"\"\n    Decompress for zip and tar file\n    \"\"\"\n    logger.debug(\"Decompressing {}...\".format(fname))\n\n    # For protecting decompressing interupted,\n    # decompress to fpath_tmp directory firstly, if decompress\n    # successed, move decompress files to fpath and delete\n    # fpath_tmp and remove download compress file.\n\n    if tarfile.is_tarfile(fname):\n        uncompressed_path = _uncompress_file_tar(fname)\n    elif zipfile.is_zipfile(fname):\n        uncompressed_path = _uncompress_file_zip(fname)\n    else:\n        raise TypeError(\"Unsupport compress file type {}\".format(fname))\n\n    return uncompressed_path\n\n\ndef _uncompress_file_zip(filepath):\n    files = zipfile.ZipFile(filepath, 'r')\n    file_list = files.namelist()\n\n    file_dir = os.path.dirname(filepath)\n\n    if _is_a_single_file(file_list):\n        rootpath = file_list[0]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n\n        for item in file_list:\n            files.extract(item, file_dir)\n\n    elif _is_a_single_dir(file_list):\n        rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[0]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n\n        for item in file_list:\n            files.extract(item, file_dir)\n\n    else:\n        rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n        if not os.path.exists(uncompressed_path):\n            os.makedirs(uncompressed_path)\n        for item in file_list:\n            files.extract(item, os.path.join(file_dir, rootpath))\n\n    files.close()\n\n    return uncompressed_path\n\n\ndef _uncompress_file_tar(filepath, mode=\"r:*\"):\n    files = tarfile.open(filepath, mode)\n    file_list = files.getnames()\n\n    file_dir = os.path.dirname(filepath)\n\n    if _is_a_single_file(file_list):\n        rootpath = file_list[0]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n        for item in file_list:\n            files.extract(item, file_dir)\n    elif _is_a_single_dir(file_list):\n        rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n        for item in file_list:\n            files.extract(item, file_dir)\n    else:\n        rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n        if not os.path.exists(uncompressed_path):\n            os.makedirs(uncompressed_path)\n\n        for item in file_list:\n            files.extract(item, os.path.join(file_dir, rootpath))\n\n    files.close()\n\n    return uncompressed_path\n\n\ndef _is_a_single_file(file_list):\n    if len(file_list) == 1 and file_list[0].find(os.sep) < -1:\n        return True\n    return False\n\n\ndef _is_a_single_dir(file_list):\n    new_file_list = []\n    for file_path in file_list:\n        if '/' in file_path:\n            file_path = file_path.replace('/', os.sep)\n        elif '\\\\' in file_path:\n            file_path = file_path.replace('\\\\', os.sep)\n        new_file_list.append(file_path)\n\n    file_name = new_file_list[0].split(os.sep)[0]\n    for i in range(1, len(new_file_list)):\n        if file_name != new_file_list[i].split(os.sep)[0]:\n            return False\n    return True\n"
  },
  {
    "path": "paddlespeech/cli/entry.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nfrom collections import defaultdict\n\n__all__ = ['commands']\n\n\ndef _CommandDict():\n    return defaultdict(_CommandDict)\n\n\ndef _execute():\n    com = commands\n\n    idx = 0\n    for _argv in (['paddlespeech'] + sys.argv[1:]):\n        if _argv not in com:\n            break\n        idx += 1\n        com = com[_argv]\n\n    # The method 'execute' of a command instance returns 'True' for a success\n    # while 'False' for a failure. Here converts this result into a exit status\n    # in bash: 0 for a success and 1 for a failure.\n    if not callable(com['_entry']):\n        i = com['_entry'].rindex('.')\n        module, cls = com['_entry'][:i], com['_entry'][i + 1:]\n        exec(\"from {} import {}\".format(module, cls))\n        com['_entry'] = locals()[cls]\n    status = 0 if com['_entry']().execute(sys.argv[idx:]) else 1\n    return status\n\n\ncommands = _CommandDict()\n"
  },
  {
    "path": "paddlespeech/cli/executor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nimport os\nimport sys\nfrom abc import ABC\nfrom abc import abstractmethod\nfrom collections import OrderedDict\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Union\n\nimport paddle\n\nfrom ..resource import CommonTaskResource\nfrom .log import logger\n\n\nclass BaseExecutor(ABC):\n    \"\"\"\n        An abstract executor of paddlespeech tasks.\n    \"\"\"\n\n    def __init__(self, task: str, **kwargs):\n        self._inputs = OrderedDict()\n        self._outputs = OrderedDict()\n        self.task_resource = CommonTaskResource(task=task, **kwargs)\n\n    @abstractmethod\n    def _init_from_path(self, *args, **kwargs):\n        \"\"\"\n        Init model and other resources from arguments. This method should be called by `__call__()`.\n        \"\"\"\n        pass\n\n    @abstractmethod\n    def preprocess(self, input: Any, *args, **kwargs):\n        \"\"\"\n        Input preprocess and return paddle.Tensor stored in self._inputs.\n        Input content can be a text(tts), a file(asr, cls), a stream(not supported yet) or anything needed.\n\n        Args:\n            input (Any): Input text/file/stream or other content.\n        \"\"\"\n        pass\n\n    @paddle.no_grad()\n    @abstractmethod\n    def infer(self, *args, **kwargs):\n        \"\"\"\n        Model inference and put results into self._outputs.\n        This method get input tensors from self._inputs, and write output tensors into self._outputs.\n        \"\"\"\n        pass\n\n    @abstractmethod\n    def postprocess(self, *args, **kwargs) -> Union[str, os.PathLike]:\n        \"\"\"\n        Output postprocess and return results.\n        This method get model output from self._outputs and convert it into human-readable results.\n\n        Returns:\n            Union[str, os.PathLike]: Human-readable results such as texts and audio files.\n        \"\"\"\n        pass\n\n    @abstractmethod\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n        Command line entry. This method can only be accessed by a command line such as `paddlespeech asr`.\n\n        Args:\n            argv (List[str]): Arguments from command line.\n\n        Returns:\n            int: Result of the command execution. `True` for a success and `False` for a failure.\n        \"\"\"\n        pass\n\n    @abstractmethod\n    def __call__(self, *arg, **kwargs):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        pass\n\n    def get_input_source(self, input_: Union[str, os.PathLike, None]\n                         ) -> Dict[str, Union[str, os.PathLike]]:\n        \"\"\"\n        Get task input source from command line input.\n\n        Args:\n            input_ (Union[str, os.PathLike, None]): Input from command line.\n\n        Returns:\n            Dict[str, Union[str, os.PathLike]]: A dict with ids and inputs.\n        \"\"\"\n        if self._is_job_input(input_):\n            # .job/.scp/.txt file\n            ret = self._get_job_contents(input_)\n        else:\n            # job from stdin\n            ret = OrderedDict()\n            if input_ is None:  # Take input from stdin\n                if not sys.stdin.isatty(\n                ):  # Avoid getting stuck when stdin is empty.\n                    for i, line in enumerate(sys.stdin):\n                        line = line.strip()\n                        if len(line.split()) == 1:\n                            ret[str(i + 1)] = line\n                        elif len(line.split()) == 2:\n                            id_, info = line.split()\n                            ret[id_] = info\n                        else:  # No valid input info from one line.\n                            continue\n            else:\n                ret[1] = input_\n        return ret\n\n    def process_task_results(self,\n                             input_: Union[str, os.PathLike, None],\n                             results: Dict[str, os.PathLike],\n                             job_dump_result: bool=False):\n        \"\"\"\n        Handling task results and redirect stdout if needed.\n\n        Args:\n            input_ (Union[str, os.PathLike, None]): Input from command line.\n            results (Dict[str, os.PathLike]): Task outputs.\n            job_dump_result (bool, optional): if True, dumps job results into file. Defaults to False.\n        \"\"\"\n\n        if not self._is_job_input(input_) and len(\n                results) == 1:  # Only one input sample\n            raw_text = list(results.values())[0]\n        else:\n            raw_text = self._format_task_results(results)\n\n        print(raw_text, end='')  # Stdout\n\n        if self._is_job_input(\n                input_) and job_dump_result:  # Dump to *.job.done \n            try:\n                job_output_file = os.path.abspath(input_) + '.done'\n                sys.stdout = open(job_output_file, 'w')\n                print(raw_text, end='')\n                logger.info(f'Results had been saved to: {job_output_file}')\n            finally:\n                sys.stdout.close()\n\n    def _is_job_input(self, input_: Union[str, os.PathLike]) -> bool:\n        \"\"\"\n        Check if current input file is a job input or not.\n\n        Args:\n            input_ (Union[str, os.PathLike]): Input file of current task.\n\n        Returns:\n            bool: return `True` for job input, `False` otherwise.\n        \"\"\"\n        return input_ and os.path.isfile(input_) and (input_.endswith('.job') or\n                                                      input_.endswith('.txt') or\n                                                      input_.endswith('.scp'))\n\n    def _get_job_contents(\n            self, job_input: os.PathLike) -> Dict[str, Union[str, os.PathLike]]:\n        \"\"\"\n        Read a job input file and return its contents in a dictionary.\n\n        Args:\n            job_input (os.PathLike): The job input file.\n\n        Returns:\n            Dict[str, str]: Contents of job input.\n        \"\"\"\n        job_contents = OrderedDict()\n        with open(job_input) as f:\n            for line in f:\n                line = line.strip()\n                if not line:\n                    continue\n                k, v = line.split()  # space or \\t\n                job_contents[k] = v\n        return job_contents\n\n    def _format_task_results(\n            self, results: Dict[str, Union[str, os.PathLike]]) -> str:\n        \"\"\"\n        Convert task results to raw text.\n\n        Args:\n            results (Dict[str, str]): A dictionary of task results.\n\n        Returns:\n            str: A string object contains task results.\n        \"\"\"\n        ret = ''\n        for k, v in results.items():\n            ret += f'{k} {v}\\n'\n        return ret\n\n    def disable_task_loggers(self):\n        \"\"\"\n        Disable all loggers in current task.\n        \"\"\"\n        loggers = [\n            logging.getLogger(name) for name in logging.root.manager.loggerDict\n        ]\n        for l in loggers:\n            l.setLevel(logging.ERROR)\n\n    def show_rtf(self, info: Dict[str, List[float]]):\n        \"\"\"\n        Calculate rft of current task and show results.\n        \"\"\"\n        num_samples = 0\n        task_duration = 0.0\n        wav_duration = 0.0\n\n        for start, end, dur in zip(info['start'], info['end'], info['extra']):\n            num_samples += 1\n            task_duration += end - start\n            wav_duration += dur\n\n        logger.info('Sample Count: {}'.format(num_samples))\n        logger.info('Avg RTF: {}'.format(task_duration / wav_duration))\n"
  },
  {
    "path": "paddlespeech/cli/kws/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import KWSExecutor\n"
  },
  {
    "path": "paddlespeech/cli/kws/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nimport yaml\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import stats_wrapper\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.kaldi import fbank as kaldi_fbank\n\n__all__ = ['KWSExecutor']\n\n\nclass KWSExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__(task='kws')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.kws', add_help=True)\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Audio file to keyword spotting.')\n        self.parser.add_argument(\n            '--threshold',\n            type=float,\n            default=0.8,\n            help='Score threshold for keyword spotting.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='mdtc_heysnips',\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help='Choose model type of kws task.')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of kws task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _init_from_path(self,\n                        model_type: str='mdtc_heysnips',\n                        cfg_path: Optional[os.PathLike]=None,\n                        ckpt_path: Optional[os.PathLike]=None):\n        \"\"\"\n            Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        if ckpt_path is None:\n            tag = model_type + '-' + '16k'\n            self.task_resource.set_task_model(tag)\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'] + '.pdparams')\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path)\n\n        # config\n        with open(self.cfg_path, 'r') as f:\n            config = yaml.safe_load(f)\n\n        # model\n        backbone_class = self.task_resource.get_model_class(\n            model_type.split('_')[0])\n        model_class = self.task_resource.get_model_class(\n            model_type.split('_')[0] + '_for_kws')\n        backbone = backbone_class(\n            stack_num=config['stack_num'],\n            stack_size=config['stack_size'],\n            in_channels=config['in_channels'],\n            res_channels=config['res_channels'],\n            kernel_size=config['kernel_size'],\n            causal=True, )\n        self.model = model_class(\n            backbone=backbone, num_keywords=config['num_keywords'])\n        model_dict = paddle.load(self.ckpt_path)\n        self.model.set_state_dict(model_dict)\n        self.model.eval()\n\n        self.feature_extractor = lambda x: kaldi_fbank(\n            x, sr=config['sample_rate'],\n            frame_shift=config['frame_shift'],\n            frame_length=config['frame_length'],\n            n_mels=config['n_mels']\n        )\n\n    def preprocess(self, audio_file: Union[str, os.PathLike]):\n        \"\"\"\n            Input preprocess and return paddle.Tensor stored in self.input.\n            Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n        assert os.path.isfile(audio_file)\n        waveform, _ = load_audio(audio_file)\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(\"Preprocessing audio_file:\" + audio_file)\n\n        # Feature extraction\n        waveform = paddle.to_tensor(waveform).unsqueeze(0)\n        self._inputs['feats'] = self.feature_extractor(waveform).unsqueeze(0)\n\n    @paddle.no_grad()\n    def infer(self):\n        \"\"\"\n            Model inference and result stored in self.output.\n        \"\"\"\n        self._outputs['logits'] = self.model(self._inputs['feats'])\n\n    def postprocess(self, threshold: float) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        kws_score = max(self._outputs['logits'][0, :, 0]).item()\n        return 'Score: {:.3f}, Threshold: {}, Is keyword: {}'.format(\n            kws_score, threshold, kws_score > threshold)\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model_type = parser_args.model\n        cfg_path = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        device = parser_args.device\n        threshold = parser_args.threshold\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(input_, threshold, model_type, cfg_path, ckpt_path,\n                           device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 threshold: float=0.8,\n                 model: str='mdtc_heysnips',\n                 config: Optional[os.PathLike]=None,\n                 ckpt_path: Optional[os.PathLike]=None,\n                 device: str=paddle.get_device()):\n        \"\"\"\n            Python API to call an executor.\n        \"\"\"\n        audio_file = os.path.abspath(os.path.expanduser(audio_file))\n        paddle.set_device(device)\n        self._init_from_path(model, config, ckpt_path)\n        self.preprocess(audio_file)\n        self.infer()\n        res = self.postprocess(threshold)\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/log.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport functools\nimport logging\n\n__all__ = [\n    'logger',\n]\n\n\nclass Logger(object):\n    def __init__(self, name: str=None):\n        name = 'PaddleSpeech' if not name else name\n        self.logger = logging.getLogger(name)\n\n        log_config = {\n            'DEBUG': 10,\n            'INFO': 20,\n            'TRAIN': 21,\n            'EVAL': 22,\n            'WARNING': 30,\n            'ERROR': 40,\n            'CRITICAL': 50,\n            'EXCEPTION': 100,\n        }\n        for key, level in log_config.items():\n            logging.addLevelName(level, key)\n            if key == 'EXCEPTION':\n                self.__dict__[key.lower()] = self.logger.exception\n            else:\n                self.__dict__[key.lower()] = functools.partial(self.__call__,\n                                                               level)\n\n        self.format = logging.Formatter(\n            fmt='[%(asctime)-15s] [%(levelname)8s] - %(message)s')\n\n        self.handler = logging.StreamHandler()\n        self.handler.setFormatter(self.format)\n\n        self.logger.addHandler(self.handler)\n        self.logger.setLevel(logging.INFO)\n        self.logger.propagate = False\n\n    def __call__(self, log_level: str, msg: str):\n        self.logger.log(log_level, msg)\n\n\nlogger = Logger()\n"
  },
  {
    "path": "paddlespeech/cli/ssl/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import SSLExecutor\n"
  },
  {
    "path": "paddlespeech/cli/ssl/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport io\nimport os\nimport sys\nimport time\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile\nfrom paddlenlp.transformers import AutoTokenizer\nfrom yacs.config import CfgNode\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import CLI_TIMER\nfrom ..utils import stats_wrapper\nfrom ..utils import timer_register\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = ['SSLExecutor']\n\n\n@timer_register\nclass SSLExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__('ssl')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.ssl', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Audio file to recognize.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='wav2vec2',\n            choices=['wav2vec2', 'hubert', \"wavlm\"],\n            help='Choose model type of asr task.')\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default='asr',\n            choices=['asr', 'vector'],\n            help='Choose output type for ssl task')\n        self.parser.add_argument(\n            '--lang',\n            type=str,\n            default='en',\n            help='Choose model language. zh or en, zh:[wav2vec2ASR_aishell1-zh-16k], en:[wav2vec2ASR_librispeech-en-16k, hubertASR_librispeech_100-en-16k]'\n        )\n        self.parser.add_argument(\n            \"--sample_rate\",\n            type=int,\n            default=16000,\n            choices=[8000, 16000],\n            help='Choose the audio sample rate of the model. 8000 or 16000')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of asr task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--decode_method',\n            type=str,\n            default='ctc_greedy_search',\n            choices=[\n                'ctc_greedy_search',\n                'ctc_prefix_beam_search',\n            ],\n            help='only support asr task')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--yes',\n            '-y',\n            action=\"store_true\",\n            default=False,\n            help='No additional parameters required. \\\n            Once set this parameter, it means accepting the request of the program by default, \\\n            which includes transforming the audio sample rate')\n        self.parser.add_argument(\n            '--rtf',\n            action=\"store_true\",\n            default=False,\n            help='Show Real-time Factor(RTF).')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n        self.last_call_params = None\n\n    def _init_from_path(self,\n                        model_type: str=None,\n                        task: str='asr',\n                        lang: str='en',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='ctc_greedy_search',\n                        ckpt_path: Optional[os.PathLike]=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        logger.debug(\"start to init the model\")\n\n        if model_type is None:\n            logger.debug(\n                \"Model type had not been specified, default {} was used.\".\n                format(model_type))\n        # default max_len: unit:second\n        self.max_len = 50\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n        if cfg_path is None or ckpt_path is None:\n            sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n            if task == 'asr':\n                if model_type == 'wav2vec2':\n                    if lang == 'en':\n                        model_prefix = 'wav2vec2ASR_librispeech'\n                    elif lang == 'zh':\n                        model_prefix = 'wav2vec2ASR_aishell1'\n                    tag = model_prefix + '-' + lang + '-' + sample_rate_str\n                elif model_type == 'hubert':\n                    if lang == 'en':\n                        model_prefix = 'hubertASR_librispeech-100h'\n                    elif lang == 'zh':\n                        logger.error(\"zh hubertASR is not supported yet\")\n                    tag = model_prefix + '-' + lang + '-' + sample_rate_str\n                elif model_type == 'wavlm':\n                    if lang == \"en\":\n                        model_prefix = \"wavlmASR_librispeech\"\n                    elif lang == \"zh\":\n                        logger.error(\"zh wavlmASR is not supported yet\")\n                    tag = model_prefix + '-' + lang + '-' + sample_rate_str\n            else:\n                tag = model_type + '-' + lang + '-' + sample_rate_str\n            self.task_resource.set_task_model(tag, version=None)\n            self.res_path = self.task_resource.res_dir\n\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.res_path,\n                self.task_resource.res_dict['ckpt_path'] + \".pdparams\")\n            logger.debug(self.res_path)\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path + \".pdparams\")\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n        logger.debug(self.cfg_path)\n        logger.debug(self.ckpt_path)\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n        if task == 'asr':\n            with UpdateConfig(self.config):\n                if lang == 'en':\n                    self.text_feature = TextFeaturizer(\n                        unit_type=self.config.unit_type,\n                        vocab=self.config.vocab_filepath)\n                    self.config.output_dim = len(self.config.vocab_filepath)\n                elif lang == 'zh':\n                    self.text_feature = AutoTokenizer.from_pretrained(\n                        self.config.tokenizer)\n                    self.config.output_dim = self.text_feature.vocab_size\n                self.config.decode.decoding_method = decode_method\n            model_name = model_prefix[:model_prefix.rindex(\n                '_')]  # model_type: {model_name}_{dataset}\n        else:\n            model_name = model_type\n        model_class = self.task_resource.get_model_class(model_name)\n        model_conf = self.config\n        model = model_class.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        model_dict = paddle.load(self.ckpt_path)\n        if task == 'asr':\n            self.model.set_state_dict(model_dict)\n        else:\n            getattr(self.model, model_type).set_state_dict(model_dict)\n\n    def preprocess(self, input: Union[str, os.PathLike]):\n        \"\"\"\n        Input preprocess and return paddle.Tensor stored in self.input.\n        Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n\n        audio_file = input\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(\"Preprocess audio_file:\" + audio_file)\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        # Get the object for feature extraction\n        logger.debug(\"get the preprocess conf\")\n        preprocess_conf = self.config.preprocess_config\n        preprocess_args = {\"train\": False}\n        preprocessing = Transformation(preprocess_conf)\n        logger.debug(\"read the audio file\")\n        audio, audio_sample_rate = soundfile.read(\n            audio_file, dtype=\"int16\", always_2d=True)\n        if self.change_format:\n            if audio.shape[1] >= 2:\n                audio = audio.mean(axis=1, dtype=np.int16)\n            else:\n                audio = audio[:, 0]\n            # pcm16 -> pcm 32\n            audio = self._pcm16to32(audio)\n            audio = librosa.resample(\n                audio, orig_sr=audio_sample_rate, target_sr=self.sample_rate)\n            audio_sample_rate = self.sample_rate\n            # pcm32 -> pcm 16\n            audio = self._pcm32to16(audio)\n        else:\n            audio = audio[:, 0]\n\n        logger.debug(f\"audio shape: {audio.shape}\")\n        # fbank\n        audio = preprocessing(audio, **preprocess_args)\n\n        audio_len = paddle.to_tensor(audio.shape[0]).unsqueeze(axis=0)\n        audio = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)\n\n        self._inputs[\"audio\"] = audio\n        self._inputs[\"audio_len\"] = audio_len\n        logger.debug(f\"audio feat shape: {audio.shape}\")\n\n        logger.debug(\"audio feat process success\")\n\n    @paddle.no_grad()\n    def infer(self, model_type: str, task: str):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        logger.debug(\"start to infer the model to get the output\")\n        audio = self._inputs[\"audio\"]\n        if task == 'asr':\n            cfg = self.config.decode\n            logger.debug(f\"we will use the {model_type}ASR like model.\")\n            try:\n                result_transcripts = self.model.decode(\n                    audio,\n                    text_feature=self.text_feature,\n                    decoding_method=cfg.decoding_method,\n                    beam_size=cfg.beam_size,\n                    tokenizer=getattr(self.config, 'tokenizer', None))\n                self._outputs[\"result\"] = result_transcripts[0][0]\n            except Exception as e:\n                logger.exception(e)\n        else:\n            logger.debug(\n                f\"we will use the {model_type} like model to extract audio feature.\"\n            )\n            try:\n                out_feature = self.model(audio[:, :, 0])\n                self._outputs[\"result\"] = out_feature[0]\n            except Exception as e:\n                logger.exception(e)\n\n    def postprocess(self) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        return self._outputs[\"result\"]\n\n    def _pcm16to32(self, audio):\n        assert (audio.dtype == np.int16)\n        audio = audio.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        audio = audio / (2**(bits - 1))\n        return audio\n\n    def _pcm32to16(self, audio):\n        assert (audio.dtype == np.float32)\n        bits = np.iinfo(np.int16).bits\n        audio = audio * (2**(bits - 1))\n        audio = np.round(audio).astype(\"int16\")\n        return audio\n\n    def _check(self, audio_file: str, sample_rate: int, force_yes: bool=False):\n        self.sample_rate = sample_rate\n        if self.sample_rate != 16000 and self.sample_rate != 8000:\n            logger.error(\n                \"invalid sample rate, please input --sr 8000 or --sr 16000\")\n            return False\n\n        if isinstance(audio_file, (str, os.PathLike)):\n            if not os.path.isfile(audio_file):\n                logger.error(\"Please input the right audio file path\")\n                return False\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        logger.debug(\"checking the audio file format......\")\n        try:\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            audio_duration = audio.shape[0] / audio_sample_rate\n            if audio_duration > self.max_len:\n                logger.error(\n                    f\"Please input audio file less then {self.max_len} seconds.\\n\"\n                )\n                return False\n        except Exception as e:\n            logger.exception(e)\n            logger.error(\n                f\"can not open the audio file, please check the audio file({audio_file}) format is 'wav'. \\n \\\n                 you can try to use sox to change the file format.\\n \\\n                 For example: \\n \\\n                 sample rate: 16k \\n \\\n                 sox input_audio.xx --rate 16k --bits 16 --channels 1 output_audio.wav \\n \\\n                 sample rate: 8k \\n \\\n                 sox input_audio.xx --rate 8k --bits 16 --channels 1 output_audio.wav \\n \\\n                 \")\n            return False\n        logger.debug(\"The sample rate is %d\" % audio_sample_rate)\n        if audio_sample_rate != self.sample_rate:\n            logger.warning(\"The sample rate of the input file is not {}.\\n \\\n                            The program will resample the wav file to {}.\\n \\\n                            If the result does not meet your expectations，\\n \\\n                            Please input the 16k 16 bit 1 channel wav file. \\\n                        \".format(self.sample_rate, self.sample_rate))\n            if force_yes is False:\n                while (True):\n                    logger.debug(\n                        \"Whether to change the sample rate and the channel. Y: change the sample. N: exit the prgream.\"\n                    )\n                    content = input(\"Input(Y/N):\")\n                    if content.strip() == \"Y\" or content.strip(\n                    ) == \"y\" or content.strip() == \"yes\" or content.strip(\n                    ) == \"Yes\":\n                        logger.debug(\n                            \"change the sampele rate, channel to 16k and 1 channel\"\n                        )\n                        break\n                    elif content.strip() == \"N\" or content.strip(\n                    ) == \"n\" or content.strip() == \"no\" or content.strip(\n                    ) == \"No\":\n                        logger.debug(\"Exit the program\")\n                        return False\n                    else:\n                        logger.warning(\"Not regular input, please input again\")\n\n            self.change_format = True\n        else:\n            logger.debug(\"The audio file format is right\")\n            self.change_format = False\n\n        return True\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model = parser_args.model\n        task = parser_args.task\n        lang = parser_args.lang\n        sample_rate = parser_args.sample_rate\n        config = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        decode_method = parser_args.decode_method\n        force_yes = parser_args.yes\n        rtf = parser_args.rtf\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(\n                    audio_file=input_,\n                    model=model,\n                    task=task,\n                    lang=lang,\n                    sample_rate=sample_rate,\n                    config=config,\n                    ckpt_path=ckpt_path,\n                    decode_method=decode_method,\n                    force_yes=force_yes,\n                    rtf=rtf,\n                    device=device)\n                task_results[id_] = res\n\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        if rtf:\n            self.show_rtf(CLI_TIMER[self.__class__.__name__])\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str=None,\n                 task: str='asr',\n                 lang: str='en',\n                 sample_rate: int=16000,\n                 config: os.PathLike=None,\n                 ckpt_path: os.PathLike=None,\n                 decode_method: str='ctc_greedy_search',\n                 force_yes: bool=False,\n                 rtf: bool=False,\n                 device=paddle.get_device()):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n\n        current_call_params = {\n            \"model\": model,\n            \"task\": task,\n            \"lang\": lang,\n            \"sample_rate\": sample_rate,\n            \"config\": config,\n            \"ckpt_path\": ckpt_path,\n            \"decode_method\": decode_method,\n            \"force_yes\": force_yes,\n            \"rtf\": rtf,\n            \"device\": device\n        }\n        if self.last_call_params is not None and self.last_call_params != current_call_params and hasattr(\n                self, 'model'):\n            del self.model\n        self.last_call_params = current_call_params\n\n        audio_file = os.path.abspath(audio_file)\n        paddle.set_device(device)\n        self._init_from_path(model, task, lang, sample_rate, config,\n                             decode_method, ckpt_path)\n        if not self._check(audio_file, sample_rate, force_yes):\n            sys.exit(-1)\n        if rtf:\n            k = self.__class__.__name__\n            CLI_TIMER[k]['start'].append(time.time())\n        self.preprocess(audio_file)\n        self.infer(model, task)\n        res = self.postprocess()  # Retrieve result of asr.\n\n        if rtf:\n            CLI_TIMER[k]['end'].append(time.time())\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            CLI_TIMER[k]['extra'].append(audio.shape[0] / audio_sample_rate)\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/st/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import STExecutor\n"
  },
  {
    "path": "paddlespeech/cli/st/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport subprocess\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport kaldiio\nimport numpy as np\nimport paddle\nimport soundfile\nfrom kaldiio import WriteHelper\nfrom yacs.config import CfgNode\n\nfrom ...utils.env import MODEL_HOME\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import download_and_decompress\nfrom ..utils import stats_wrapper\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = [\"STExecutor\"]\n\nkaldi_bins = {\n    \"url\":\n    \"https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/kaldi_bins.tar.gz\",\n    \"md5\":\n    \"c0682303b3f3393dbf6ed4c4e35a53eb\",\n}\n\n\nclass STExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__(task='st')\n        self.kaldi_bins = kaldi_bins\n\n        self.parser = argparse.ArgumentParser(\n            prog=\"paddlespeech.st\", add_help=True)\n        self.parser.add_argument(\n            \"--input\", type=str, default=None, help=\"Audio file to translate.\")\n        self.parser.add_argument(\n            \"--model\",\n            type=str,\n            default=\"fat_st_ted\",\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help=\"Choose model type of st task.\")\n        self.parser.add_argument(\n            \"--src_lang\",\n            type=str,\n            default=\"en\",\n            help=\"Choose model source language.\")\n        self.parser.add_argument(\n            \"--tgt_lang\",\n            type=str,\n            default=\"zh\",\n            help=\"Choose model target language.\")\n        self.parser.add_argument(\n            \"--sample_rate\",\n            type=int,\n            default=16000,\n            choices=[16000],\n            help='Choose the audio sample rate of the model. 8000 or 16000')\n        self.parser.add_argument(\n            \"--config\",\n            type=str,\n            default=None,\n            help=\"Config of st task. Use default config when it is None.\")\n        self.parser.add_argument(\n            \"--ckpt_path\",\n            type=str,\n            default=None,\n            help=\"Checkpoint file of model.\")\n        self.parser.add_argument(\n            \"--device\",\n            type=str,\n            default=paddle.get_device(),\n            help=\"Choose device to execute model inference.\")\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _set_kaldi_bins(self) -> os.PathLike:\n        \"\"\"\n            Download and returns kaldi_bins resources path of current task.\n        \"\"\"\n        decompressed_path = download_and_decompress(self.kaldi_bins, MODEL_HOME)\n        decompressed_path = os.path.abspath(decompressed_path)\n        logger.debug(\"Kaldi_bins stored in: {}\".format(decompressed_path))\n        if \"LD_LIBRARY_PATH\" in os.environ:\n            os.environ[\"LD_LIBRARY_PATH\"] += f\":{decompressed_path}\"\n        else:\n            os.environ[\"LD_LIBRARY_PATH\"] = f\"{decompressed_path}\"\n        os.environ[\"PATH\"] += f\":{decompressed_path}\"\n        return decompressed_path\n\n    def _init_from_path(self,\n                        model_type: str=\"fat_st_ted\",\n                        src_lang: str=\"en\",\n                        tgt_lang: str=\"zh\",\n                        cfg_path: Optional[os.PathLike]=None,\n                        ckpt_path: Optional[os.PathLike]=None):\n        \"\"\"\n            Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        if cfg_path is None or ckpt_path is None:\n            tag = model_type + \"-\" + src_lang + \"-\" + tgt_lang\n            self.task_resource.set_task_model(tag, version=None)\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'])\n            logger.debug(self.cfg_path)\n            logger.debug(self.ckpt_path)\n            res_path = self.task_resource.res_dir\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path)\n            res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n        self.config.decode.decoding_method = \"fullsentence\"\n\n        with UpdateConfig(self.config):\n            self.config.cmvn_path = os.path.join(res_path,\n                                                 self.config.cmvn_path)\n            self.config.spm_model_prefix = os.path.join(\n                res_path, self.config.spm_model_prefix)\n            self.text_feature = TextFeaturizer(\n                unit_type=self.config.unit_type,\n                vocab=self.config.vocab_filepath,\n                spm_model_prefix=self.config.spm_model_prefix)\n\n        model_conf = self.config\n        model_name = model_type[:model_type.rindex(\n            '_')]  # model_type: {model_name}_{dataset}\n        model_class = self.task_resource.get_model_class(model_name)\n        self.model = model_class.from_config(model_conf)\n        self.model.eval()\n\n        # load model\n        params_path = self.ckpt_path\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n        # set kaldi bins\n        self._set_kaldi_bins()\n\n    def _check(self, audio_file: str, sample_rate: int):\n        _, audio_sample_rate = soundfile.read(\n            audio_file, dtype=\"int16\", always_2d=True)\n        if audio_sample_rate != sample_rate:\n            raise Exception(\"invalid sample rate\")\n            sys.exit(-1)\n\n    def preprocess(self, wav_file: Union[str, os.PathLike], model_type: str):\n        \"\"\"\n            Input preprocess and return paddle.Tensor stored in self.input.\n            Input content can be a file(wav).\n        \"\"\"\n        audio_file = os.path.abspath(wav_file)\n        logger.debug(\"Preprocess audio_file:\" + audio_file)\n\n        if \"fat_st\" in model_type:\n            cmvn = self.config.cmvn_path\n            utt_name = \"_tmp\"\n\n            # Get the object for feature extraction\n            fbank_extract_command = [\n                \"compute-fbank-feats\", \"--num-mel-bins=80\", \"--verbose=2\",\n                \"--sample-frequency=16000\", \"scp:-\", \"ark:-\"\n            ]\n            fbank_extract_process = subprocess.Popen(\n                fbank_extract_command,\n                stdin=subprocess.PIPE,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE)\n            fbank_extract_process.stdin.write(\n                f\"{utt_name} {wav_file}\".encode(\"utf8\"))\n            fbank_extract_process.stdin.close()\n            fbank_feat = dict(\n                kaldiio.load_ark(fbank_extract_process.stdout))[utt_name]\n\n            extract_command = [\"compute-kaldi-pitch-feats\", \"scp:-\", \"ark:-\"]\n            pitch_extract_process = subprocess.Popen(\n                extract_command,\n                stdin=subprocess.PIPE,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE)\n            pitch_extract_process.stdin.write(\n                f\"{utt_name} {wav_file}\".encode(\"utf8\"))\n            process_command = [\"process-kaldi-pitch-feats\", \"ark:\", \"ark:-\"]\n            pitch_process = subprocess.Popen(\n                process_command,\n                stdin=pitch_extract_process.stdout,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE)\n            pitch_extract_process.stdin.close()\n            pitch_feat = dict(kaldiio.load_ark(pitch_process.stdout))[utt_name]\n            concated_feat = np.concatenate((fbank_feat, pitch_feat), axis=1)\n            raw_feat = f\"{utt_name}.raw\"\n            with WriteHelper(\n                    f\"ark,scp:{raw_feat}.ark,{raw_feat}.scp\") as writer:\n                writer(utt_name, concated_feat)\n            cmvn_command = [\n                \"apply-cmvn\", \"--norm-vars=true\", cmvn, f\"scp:{raw_feat}.scp\",\n                \"ark:-\"\n            ]\n            cmvn_process = subprocess.Popen(\n                cmvn_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n            process_command = [\n                \"copy-feats\", \"--compress=true\", \"ark:-\", \"ark:-\"\n            ]\n            process = subprocess.Popen(\n                process_command,\n                stdin=cmvn_process.stdout,\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE)\n            norm_feat = dict(kaldiio.load_ark(process.stdout))[utt_name]\n            self._inputs[\"audio\"] = paddle.to_tensor(norm_feat).unsqueeze(0)\n            self._inputs[\"audio_len\"] = paddle.to_tensor(\n                self._inputs[\"audio\"].shape[1:2], dtype=\"int64\")\n        else:\n            raise ValueError(\"Wrong model type.\")\n\n    @paddle.no_grad()\n    def infer(self, model_type: str):\n        \"\"\"\n            Model inference and result stored in self.output.\n        \"\"\"\n        cfg = self.config.decode\n        audio = self._inputs[\"audio\"]\n        audio_len = self._inputs[\"audio_len\"]\n        if model_type == \"fat_st_ted\":\n            hyps = self.model.decode(\n                audio,\n                audio_len,\n                text_feature=self.text_feature,\n                decoding_method=cfg.decoding_method,\n                beam_size=cfg.beam_size,\n                word_reward=cfg.word_reward,\n                decoding_chunk_size=cfg.decoding_chunk_size,\n                num_decoding_left_chunks=cfg.num_decoding_left_chunks,\n                simulate_streaming=cfg.simulate_streaming)\n            self._outputs[\"result\"] = hyps\n        else:\n            raise ValueError(\"Wrong model type.\")\n\n    def postprocess(self, model_type: str) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        if model_type == \"fat_st_ted\":\n            return self._outputs[\"result\"]\n        else:\n            raise ValueError(\"Wrong model type.\")\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model = parser_args.model\n        src_lang = parser_args.src_lang\n        tgt_lang = parser_args.tgt_lang\n        sample_rate = parser_args.sample_rate\n        config = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(input_, model, src_lang, tgt_lang, sample_rate,\n                           config, ckpt_path, device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str='fat_st_ted',\n                 src_lang: str='en',\n                 tgt_lang: str='zh',\n                 sample_rate: int=16000,\n                 config: Optional[os.PathLike]=None,\n                 ckpt_path: Optional[os.PathLike]=None,\n                 device: str=paddle.get_device()):\n        \"\"\"\n            Python API to call an executor.\n        \"\"\"\n        audio_file = os.path.abspath(audio_file)\n        self._check(audio_file, sample_rate)\n        paddle.set_device(device)\n        self._init_from_path(model, src_lang, tgt_lang, config, ckpt_path)\n        self.preprocess(audio_file, model)\n        self.infer(model)\n        res = self.postprocess(model)\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/text/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import TextExecutor\n"
  },
  {
    "path": "paddlespeech/cli/text/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport re\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import stats_wrapper\nfrom paddlespeech.text.models.ernie_linear import ErnieLinear\n\n__all__ = ['TextExecutor']\n\n\nclass TextExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__(task='text')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.text', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Input text.')\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default='punc',\n            choices=['punc'],\n            help='Choose text task.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='ernie_linear_p7_wudao',\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help='Choose model type of text task.')\n        self.parser.add_argument(\n            '--lang',\n            type=str,\n            default='zh',\n            choices=['zh', 'en'],\n            help='Choose model language.')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of cls task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--punc_vocab',\n            type=str,\n            default=None,\n            help='Vocabulary file of punctuation restoration task.')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _init_from_path(self,\n                        task: str='punc',\n                        model_type: str='ernie_linear_p7_wudao',\n                        lang: str='zh',\n                        cfg_path: Optional[os.PathLike]=None,\n                        ckpt_path: Optional[os.PathLike]=None,\n                        vocab_file: Optional[os.PathLike]=None):\n        \"\"\"\n            Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        self.task = task\n\n        if cfg_path is None or ckpt_path is None or vocab_file is None:\n            tag = '-'.join([model_type, task, lang])\n            self.task_resource.set_task_model(tag, version=None)\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'])\n            self.vocab_file = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['vocab_file'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path)\n            self.vocab_file = os.path.abspath(vocab_file)\n\n        model_name = model_type[:model_type.rindex('_')]\n        if self.task == 'punc':\n            # punc list\n            self._punc_list = []\n            with open(self.vocab_file, 'r', encoding='utf-8') as f:\n                for line in f:\n                    self._punc_list.append(line.strip())\n\n            # model\n            model_class, tokenizer_class = self.task_resource.get_model_class(\n                model_name)\n            self.model = model_class(\n                cfg_path=self.cfg_path, ckpt_path=self.ckpt_path)\n            self.tokenizer = tokenizer_class.from_pretrained('ernie-1.0')\n        else:\n            raise NotImplementedError\n\n        self.model.eval()\n\n    #init new models\n    def _init_from_path_new(self,\n                            task: str='punc',\n                            model_type: str='ernie_linear_p7_wudao',\n                            lang: str='zh',\n                            cfg_path: Optional[os.PathLike]=None,\n                            ckpt_path: Optional[os.PathLike]=None,\n                            vocab_file: Optional[os.PathLike]=None):\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        self.task = task\n\n        if cfg_path is None or ckpt_path is None or vocab_file is None:\n            tag = '-'.join([model_type, task, lang])\n            self.task_resource.set_task_model(tag, version=None)\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'])\n            self.vocab_file = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['vocab_file'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path)\n            self.vocab_file = os.path.abspath(vocab_file)\n\n        model_name = model_type[:model_type.rindex('_')]\n\n        if self.task == 'punc':\n            # punc list\n            self._punc_list = []\n            with open(self.vocab_file, 'r', encoding='utf-8') as f:\n                for line in f:\n                    self._punc_list.append(line.strip())\n\n            # model\n            with open(self.cfg_path, 'r', encoding='utf-8') as f:\n                config = CfgNode(yaml.safe_load(f))\n            self.model = ErnieLinear(**config[\"model\"])\n\n            _, tokenizer_class = self.task_resource.get_model_class(model_name)\n            state_dict = paddle.load(self.ckpt_path)\n            self.model.set_state_dict(state_dict[\"main_params\"])\n            self.model.eval()\n\n            #tokenizer: fast version: ernie-3.0-mini-zh   slow version:ernie-1.0\n            if 'fast' not in model_type:\n                self.tokenizer = tokenizer_class.from_pretrained('ernie-1.0')\n            else:\n                self.tokenizer = tokenizer_class.from_pretrained(\n                    'ernie-3.0-mini-zh')\n\n        else:\n            raise NotImplementedError\n\n    def _clean_text(self, text):\n        text = text.lower()\n        text = re.sub('[^A-Za-z0-9\\u4e00-\\u9fa5]', '', text)\n        text = re.sub(f'[{\"\".join([p for p in self._punc_list][1:])}]', '',\n                      text)\n        return text\n\n    def preprocess(self, text: Union[str, os.PathLike]):\n        \"\"\"\n            Input preprocess and return paddle.Tensor stored in self.input.\n            Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n        if self.task == 'punc':\n            clean_text = self._clean_text(text)\n            assert len(clean_text) > 0, f'Invalid input string: {text}'\n\n            tokenized_input = self.tokenizer(\n                list(clean_text), return_length=True, is_split_into_words=True)\n\n            self._inputs['input_ids'] = tokenized_input['input_ids']\n            self._inputs['seg_ids'] = tokenized_input['token_type_ids']\n            self._inputs['seq_len'] = tokenized_input['seq_len']\n        else:\n            raise NotImplementedError\n\n    @paddle.no_grad()\n    def infer(self):\n        \"\"\"\n            Model inference and result stored in self.output.\n        \"\"\"\n        if self.task == 'punc':\n            input_ids = paddle.to_tensor(self._inputs['input_ids']).unsqueeze(0)\n            seg_ids = paddle.to_tensor(self._inputs['seg_ids']).unsqueeze(0)\n            logits, _ = self.model(input_ids, seg_ids)\n            preds = paddle.argmax(logits, axis=-1).squeeze(0)\n\n            self._outputs['preds'] = preds\n        else:\n            raise NotImplementedError\n\n    def postprocess(self, isNewTrainer: bool=False) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        if self.task == 'punc':\n            input_ids = self._inputs['input_ids']\n            seq_len = self._inputs['seq_len']\n            preds = self._outputs['preds']\n\n            tokens = self.tokenizer.convert_ids_to_tokens(\n                input_ids[1:seq_len - 1])\n            labels = preds[1:seq_len - 1].tolist()\n            assert len(tokens) == len(labels)\n            if isNewTrainer:\n                self._punc_list = [0] + self._punc_list\n            text = ''\n            for t, l in zip(tokens, labels):\n                text += t\n                if l != 0:  # Non punc.\n                    text += self._punc_list[l]\n            return text\n        else:\n            raise NotImplementedError\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        task = parser_args.task\n        model_type = parser_args.model\n        lang = parser_args.lang\n        cfg_path = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        punc_vocab = parser_args.punc_vocab\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(input_, task, model_type, lang, cfg_path, ckpt_path,\n                           punc_vocab, device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(\n            self,\n            text: str,\n            task: str='punc',\n            model: str='ernie_linear_p7_wudao',\n            lang: str='zh',\n            config: Optional[os.PathLike]=None,\n            ckpt_path: Optional[os.PathLike]=None,\n            punc_vocab: Optional[os.PathLike]=None,\n            device: str=paddle.get_device(), ):\n        \"\"\"\n            Python API to call an executor.\n        \"\"\"\n        #Here is old version models \n        if model in ['ernie_linear_p7_wudao', 'ernie_linear_p3_wudao']:\n            paddle.set_device(device)\n            self._init_from_path(task, model, lang, config, ckpt_path,\n                                 punc_vocab)\n            self.preprocess(text)\n            self.infer()\n            res = self.postprocess()  # Retrieve result of text task.\n        #Add new way to infer\n        else:\n            paddle.set_device(device)\n            self._init_from_path_new(task, model, lang, config, ckpt_path,\n                                     punc_vocab)\n            self.preprocess(text)\n            self.infer()\n            res = self.postprocess(isNewTrainer=True)\n        return res\n"
  },
  {
    "path": "paddlespeech/cli/tts/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import TTSExecutor\n"
  },
  {
    "path": "paddlespeech/cli/tts/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport time\nfrom collections import OrderedDict\nfrom typing import Any\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import stats_wrapper\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sess\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.utils import str2bool\n\n__all__ = ['TTSExecutor']\nONNX_SUPPORT_SET = {\n    'speedyspeech_csmsc',\n    'fastspeech2_csmsc',\n    'fastspeech2_ljspeech',\n    'fastspeech2_aishell3',\n    'fastspeech2_vctk',\n    'fastspeech2_male',\n    'fastspeech2_mix',\n    'fastspeech2_canton',\n    'pwgan_csmsc',\n    'pwgan_ljspeech',\n    'pwgan_aishell3',\n    'pwgan_vctk',\n    'pwgan_male',\n    'mb_melgan_csmsc',\n    'hifigan_csmsc',\n    'hifigan_ljspeech',\n    'hifigan_aishell3',\n    'hifigan_vctk',\n    'hifigan_male',\n}\n\n\nclass TTSExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__('tts')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.tts', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Input text to generate.')\n        # acoustic model\n        self.parser.add_argument(\n            '--am',\n            type=str,\n            default='fastspeech2_csmsc',\n            choices=[\n                'speedyspeech_csmsc',\n                'fastspeech2_csmsc',\n                'fastspeech2_ljspeech',\n                'fastspeech2_aishell3',\n                'fastspeech2_vctk',\n                'fastspeech2_mix',\n                'tacotron2_csmsc',\n                'tacotron2_ljspeech',\n                'fastspeech2_male',\n                'fastspeech2_canton',\n            ],\n            help='Choose acoustic model type of tts task.')\n        self.parser.add_argument(\n            '--am_config',\n            type=str,\n            default=None,\n            help='Config of acoustic model. Use default config when it is None.')\n        self.parser.add_argument(\n            '--am_ckpt',\n            type=str,\n            default=None,\n            help='Checkpoint file of acoustic model.')\n        self.parser.add_argument(\n            \"--am_stat\",\n            type=str,\n            default=None,\n            help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n        )\n        self.parser.add_argument(\n            \"--phones_dict\",\n            type=str,\n            default=None,\n            help=\"phone vocabulary file.\")\n        self.parser.add_argument(\n            \"--tones_dict\",\n            type=str,\n            default=None,\n            help=\"tone vocabulary file.\")\n        self.parser.add_argument(\n            \"--speaker_dict\",\n            type=str,\n            default=None,\n            help=\"speaker id map file.\")\n        self.parser.add_argument(\n            '--spk_id',\n            type=int,\n            default=0,\n            help='spk id for multi speaker acoustic model')\n        # vocoder\n        self.parser.add_argument(\n            '--voc',\n            type=str,\n            default='hifigan_csmsc',\n            choices=[\n                'pwgan_csmsc',\n                'pwgan_ljspeech',\n                'pwgan_aishell3',\n                'pwgan_vctk',\n                'mb_melgan_csmsc',\n                'style_melgan_csmsc',\n                'hifigan_csmsc',\n                'hifigan_ljspeech',\n                'hifigan_aishell3',\n                'hifigan_vctk',\n                'wavernn_csmsc',\n                'pwgan_male',\n                'hifigan_male',\n            ],\n            help='Choose vocoder type of tts task.')\n\n        self.parser.add_argument(\n            '--voc_config',\n            type=str,\n            default=None,\n            help='Config of voc. Use default config when it is None.')\n        self.parser.add_argument(\n            '--voc_ckpt',\n            type=str,\n            default=None,\n            help='Checkpoint file of voc.')\n        self.parser.add_argument(\n            \"--voc_stat\",\n            type=str,\n            default=None,\n            help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n        )\n        # other\n        self.parser.add_argument(\n            '--lang',\n            type=str,\n            default='zh',\n            help='Choose model language. zh or en or mix')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n\n        self.parser.add_argument('--cpu_threads', type=int, default=2)\n\n        self.parser.add_argument(\n            '--output', type=str, default='output.wav', help='output file name')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n        self.parser.add_argument(\n            \"--use_onnx\",\n            type=str2bool,\n            default=False,\n            help=\"whether to usen onnxruntime inference.\")\n        self.parser.add_argument(\n            '--fs',\n            type=int,\n            default=24000,\n            help='sample rate for onnx models when use specified model files.')\n\n    def _init_from_path(\n            self,\n            am: str='fastspeech2_csmsc',\n            am_config: Optional[os.PathLike]=None,\n            am_ckpt: Optional[os.PathLike]=None,\n            am_stat: Optional[os.PathLike]=None,\n            phones_dict: Optional[os.PathLike]=None,\n            tones_dict: Optional[os.PathLike]=None,\n            speaker_dict: Optional[os.PathLike]=None,\n            voc: str='hifigan_csmsc',\n            voc_config: Optional[os.PathLike]=None,\n            voc_ckpt: Optional[os.PathLike]=None,\n            voc_stat: Optional[os.PathLike]=None,\n            lang: str='zh', ):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'am_inference') and hasattr(self, 'voc_inference'):\n            logger.debug('Models had been initialized.')\n            return\n\n        # am\n        if am_ckpt is None or am_config is None or am_stat is None or phones_dict is None:\n            use_pretrained_am = True\n        else:\n            use_pretrained_am = False\n\n        am_tag = am + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=am_tag,\n            model_type=0,  # am\n            skip_download=not use_pretrained_am,\n            version=None,  # default version\n        )\n        if use_pretrained_am:\n            self.am_res_path = self.task_resource.res_dir\n            self.am_config = os.path.join(self.am_res_path,\n                                          self.task_resource.res_dict['config'])\n            self.am_ckpt = os.path.join(self.am_res_path,\n                                        self.task_resource.res_dict['ckpt'])\n            self.am_stat = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['speech_stats'])\n            # must have phones_dict in acoustic\n            self.phones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['phones_dict'])\n            logger.debug(self.am_res_path)\n            logger.debug(self.am_config)\n            logger.debug(self.am_ckpt)\n        else:\n            self.am_config = os.path.abspath(am_config)\n            self.am_ckpt = os.path.abspath(am_ckpt)\n            self.am_stat = os.path.abspath(am_stat)\n            self.phones_dict = os.path.abspath(phones_dict)\n            self.am_res_path = os.path.dirname(self.am_config)\n\n        # for speedyspeech\n        self.tones_dict = None\n        if 'tones_dict' in self.task_resource.res_dict:\n            self.tones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['tones_dict'])\n            if tones_dict:\n                self.tones_dict = tones_dict\n\n        # for multi speaker fastspeech2\n        self.speaker_dict = None\n        if 'speaker_dict' in self.task_resource.res_dict:\n            self.speaker_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['speaker_dict'])\n            if speaker_dict:\n                self.speaker_dict = speaker_dict\n\n        # voc\n        if voc_ckpt is None or voc_config is None or voc_stat is None:\n            use_pretrained_voc = True\n        else:\n            use_pretrained_voc = False\n        voc_lang = lang\n        # When speaker is 174 (csmsc), use csmsc's vocoder is better than aishell3's\n        if lang == 'mix' or lang == 'canton':\n            voc_dataset = voc[voc.rindex('_') + 1:]\n            if voc_dataset in {\"ljspeech\", \"vctk\"}:\n                voc_lang = 'en'\n            else:\n                voc_lang = 'zh'\n        voc_tag = voc + '-' + voc_lang\n        self.task_resource.set_task_model(\n            model_tag=voc_tag,\n            model_type=1,  # vocoder\n            skip_download=not use_pretrained_voc,\n            version=None,  # default version\n        )\n        if use_pretrained_voc:\n            self.voc_res_path = self.task_resource.voc_res_dir\n            self.voc_config = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['config'])\n            self.voc_ckpt = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['ckpt'])\n            self.voc_stat = os.path.join(\n                self.voc_res_path,\n                self.task_resource.voc_res_dict['speech_stats'])\n            logger.debug(self.voc_res_path)\n            logger.debug(self.voc_config)\n            logger.debug(self.voc_ckpt)\n        else:\n            self.voc_config = os.path.abspath(voc_config)\n            self.voc_ckpt = os.path.abspath(voc_ckpt)\n            self.voc_stat = os.path.abspath(voc_stat)\n            self.voc_res_path = os.path.dirname(\n                os.path.abspath(self.voc_config))\n\n        # Init body.\n        with open(self.am_config) as f:\n            self.am_config = CfgNode(yaml.safe_load(f))\n        with open(self.voc_config) as f:\n            self.voc_config = CfgNode(yaml.safe_load(f))\n\n        with open(self.phones_dict, 'rt', encoding='utf-8') as f:\n            phn_id = [line.strip().split() for line in f.readlines()]\n        vocab_size = len(phn_id)\n\n        tone_size = None\n        if self.tones_dict:\n            with open(self.tones_dict, 'rt', encoding='utf-8') as f:\n                tone_id = [line.strip().split() for line in f.readlines()]\n            tone_size = len(tone_id)\n\n        spk_num = None\n        if self.speaker_dict:\n            with open(self.speaker_dict, 'rt', encoding='utf-8') as f:\n                spk_id = [line.strip().split() for line in f.readlines()]\n            spk_num = len(spk_id)\n\n        # frontend\n        self.frontend = get_frontend(\n            lang=lang, phones_dict=self.phones_dict, tones_dict=self.tones_dict)\n\n        # acoustic model\n        self.am_inference = get_am_inference(\n            am=am,\n            am_config=self.am_config,\n            am_ckpt=self.am_ckpt,\n            am_stat=self.am_stat,\n            phones_dict=self.phones_dict,\n            tones_dict=self.tones_dict,\n            speaker_dict=self.speaker_dict)\n\n        # vocoder\n        self.voc_inference = get_voc_inference(\n            voc=voc,\n            voc_config=self.voc_config,\n            voc_ckpt=self.voc_ckpt,\n            voc_stat=self.voc_stat)\n\n    def _init_from_path_onnx(self,\n                             am: str='fastspeech2_csmsc',\n                             am_ckpt: Optional[os.PathLike]=None,\n                             phones_dict: Optional[os.PathLike]=None,\n                             tones_dict: Optional[os.PathLike]=None,\n                             speaker_dict: Optional[os.PathLike]=None,\n                             voc: str='hifigan_csmsc',\n                             voc_ckpt: Optional[os.PathLike]=None,\n                             lang: str='zh',\n                             device: str='cpu',\n                             cpu_threads: int=2,\n                             fs: int=24000):\n        if hasattr(self, 'am_sess') and hasattr(self, 'voc_sess'):\n            logger.debug('Models had been initialized.')\n            return\n\n        # am\n        if am_ckpt is None or phones_dict is None:\n            use_pretrained_am = True\n        else:\n            use_pretrained_am = False\n\n        am_tag = am + '_onnx' + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=am_tag,\n            model_type=0,  # am\n            skip_download=not use_pretrained_am,\n            version=None,  # default version\n        )\n        if use_pretrained_am:\n            self.am_res_path = self.task_resource.res_dir\n            self.am_ckpt = os.path.join(self.am_res_path,\n                                        self.task_resource.res_dict['ckpt'])\n            # must have phones_dict in acoustic\n            self.phones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['phones_dict'])\n            self.am_fs = self.task_resource.res_dict['sample_rate']\n            logger.debug(self.am_res_path)\n            logger.debug(self.am_ckpt)\n        else:\n            self.am_ckpt = os.path.abspath(am_ckpt)\n            self.phones_dict = os.path.abspath(phones_dict)\n            self.am_res_path = os.path.dirname(self.am_ckpt)\n            self.am_fs = fs\n\n        # for speedyspeech\n        self.tones_dict = None\n        if 'tones_dict' in self.task_resource.res_dict:\n            self.tones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['tones_dict'])\n            if tones_dict:\n                self.tones_dict = tones_dict\n\n        # voc\n        if voc_ckpt is None:\n            use_pretrained_voc = True\n        else:\n            use_pretrained_voc = False\n        voc_lang = lang\n        if lang == 'mix' or lang == 'canton':\n            voc_dataset = voc[voc.rindex('_') + 1:]\n            if voc_dataset in {\"ljspeech\", \"vctk\"}:\n                voc_lang = 'en'\n            else:\n                voc_lang = 'zh'\n        voc_tag = voc + '_onnx' + '-' + voc_lang\n        self.task_resource.set_task_model(\n            model_tag=voc_tag,\n            model_type=1,  # vocoder\n            skip_download=not use_pretrained_voc,\n            version=None,  # default version\n        )\n        if use_pretrained_voc:\n            self.voc_res_path = self.task_resource.voc_res_dir\n            self.voc_ckpt = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['ckpt'])\n            logger.debug(self.voc_res_path)\n            logger.debug(self.voc_ckpt)\n        else:\n            self.voc_ckpt = os.path.abspath(voc_ckpt)\n            self.voc_res_path = os.path.dirname(os.path.abspath(self.voc_ckpt))\n\n        # frontend\n        self.frontend = get_frontend(\n            lang=lang, phones_dict=self.phones_dict, tones_dict=self.tones_dict)\n        self.am_sess = get_sess(\n            model_path=self.am_ckpt, device=device, cpu_threads=cpu_threads)\n\n        # vocoder\n        self.voc_sess = get_sess(\n            model_path=self.voc_ckpt, device=device, cpu_threads=cpu_threads)\n\n    def preprocess(self, input: Any, *args, **kwargs):\n        \"\"\"\n        Input preprocess and return paddle.Tensor stored in self._inputs.\n        Input content can be a text(tts), a file(asr, cls), a stream(not supported yet) or anything needed.\n\n        Args:\n            input (Any): Input text/file/stream or other content.\n        \"\"\"\n        pass\n\n    @paddle.no_grad()\n    def infer(self,\n              text: str,\n              lang: str='zh',\n              am: str='fastspeech2_csmsc',\n              spk_id: int=0):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        am_name = am[:am.rindex('_')]\n        am_dataset = am[am.rindex('_') + 1:]\n        merge_sentences = False\n        get_tone_ids = False\n        if am_name == 'speedyspeech':\n            get_tone_ids = True\n        frontend_st = time.time()\n        frontend_dict = run_frontend(\n            frontend=self.frontend,\n            text=text,\n            merge_sentences=merge_sentences,\n            get_tone_ids=get_tone_ids,\n            lang=lang)\n        self.frontend_time = time.time() - frontend_st\n        self.am_time = 0\n        self.voc_time = 0\n        flags = 0\n        phone_ids = frontend_dict['phone_ids']\n        for i in range(len(phone_ids)):\n            am_st = time.time()\n            part_phone_ids = phone_ids[i]\n            # am\n            if am_name == 'speedyspeech':\n                part_tone_ids = frontend_dict['tone_ids'][i]\n                mel = self.am_inference(part_phone_ids, part_tone_ids)\n            # fastspeech2\n            else:\n                # multi speaker\n                if am_dataset in {'aishell3', 'vctk', 'mix', 'canton'}:\n                    mel = self.am_inference(\n                        part_phone_ids, spk_id=paddle.to_tensor([spk_id]))\n                else:\n                    mel = self.am_inference(part_phone_ids)\n            self.am_time += (time.time() - am_st)\n            # voc\n            voc_st = time.time()\n            wav = self.voc_inference(mel)\n            if flags == 0:\n                wav_all = wav\n                flags = 1\n            else:\n                wav_all = paddle.concat([wav_all, wav])\n            self.voc_time += (time.time() - voc_st)\n        self._outputs['wav'] = wav_all\n\n    def infer_onnx(self,\n                   text: str,\n                   lang: str='zh',\n                   am: str='fastspeech2_csmsc',\n                   spk_id: int=0):\n        am_name = am[:am.rindex('_')]\n        am_dataset = am[am.rindex('_') + 1:]\n        merge_sentences = False\n        get_tone_ids = False\n        if am_name == 'speedyspeech':\n            get_tone_ids = True\n        am_input_feed = {}\n        frontend_st = time.time()\n        frontend_dict = run_frontend(\n            frontend=self.frontend,\n            text=text,\n            merge_sentences=merge_sentences,\n            get_tone_ids=get_tone_ids,\n            lang=lang,\n            to_tensor=False, )\n        self.frontend_time = time.time() - frontend_st\n        phone_ids = frontend_dict['phone_ids']\n        self.am_time = 0\n        self.voc_time = 0\n        flags = 0\n        for i in range(len(phone_ids)):\n            am_st = time.time()\n            part_phone_ids = phone_ids[i]\n            if am_name == 'fastspeech2':\n                am_input_feed.update({'text': part_phone_ids})\n                if am_dataset in {\"aishell3\", \"vctk\", \"mix\", \"canton\"}:\n                    # NOTE: 'spk_id' should be List[int] rather than int here!!\n                    am_input_feed.update({'spk_id': [spk_id]})\n            elif am_name == 'speedyspeech':\n                part_tone_ids = frontend_dict['tone_ids'][i]\n                am_input_feed.update({\n                    'phones': part_phone_ids,\n                    'tones': part_tone_ids\n                })\n            mel = self.am_sess.run(output_names=None, input_feed=am_input_feed)\n            mel = mel[0]\n            self.am_time += (time.time() - am_st)\n            # voc\n            voc_st = time.time()\n            wav = self.voc_sess.run(\n                output_names=None, input_feed={'logmel': mel})\n            wav = wav[0]\n            if flags == 0:\n                wav_all = wav\n                flags = 1\n            else:\n                wav_all = np.concatenate([wav_all, wav])\n            self.voc_time += (time.time() - voc_st)\n\n        self._outputs['wav'] = wav_all\n\n    def postprocess(self, output: str='output.wav') -> Union[str, os.PathLike]:\n        \"\"\"\n        Output postprocess and return results.\n        This method get model output from self._outputs and convert it into human-readable results.\n\n        Returns:\n            Union[str, os.PathLike]: Human-readable results such as texts and audio files.\n        \"\"\"\n        output = os.path.abspath(os.path.expanduser(output))\n        sf.write(\n            output, self._outputs['wav'].numpy(), samplerate=self.am_config.fs)\n        return output\n\n    def postprocess_onnx(self,\n                         output: str='output.wav') -> Union[str, os.PathLike]:\n        \"\"\"\n        Output postprocess and return results.\n        This method get model output from self._outputs and convert it into human-readable results.\n\n        Returns:\n            Union[str, os.PathLike]: Human-readable results such as texts and audio files.\n        \"\"\"\n        output = os.path.abspath(os.path.expanduser(output))\n        sf.write(output, self._outputs['wav'], samplerate=self.am_fs)\n        return output\n\n    # 命令行的入口是这里\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n        Command line entry.\n        \"\"\"\n\n        args = self.parser.parse_args(argv)\n\n        am = args.am\n        am_config = args.am_config\n        am_ckpt = args.am_ckpt\n        am_stat = args.am_stat\n        phones_dict = args.phones_dict\n        tones_dict = args.tones_dict\n        speaker_dict = args.speaker_dict\n        voc = args.voc\n        voc_config = args.voc_config\n        voc_ckpt = args.voc_ckpt\n        voc_stat = args.voc_stat\n        lang = args.lang\n        device = args.device\n        spk_id = args.spk_id\n        use_onnx = args.use_onnx\n        cpu_threads = args.cpu_threads\n        fs = args.fs\n\n        if not args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            if len(task_source) > 1:\n                assert isinstance(args.output,\n                                  str) and args.output.endswith('.wav')\n                output = args.output.replace('.wav', f'_{id_}.wav')\n            else:\n                output = args.output\n\n            try:\n                res = self(\n                    text=input_,\n                    # acoustic model related\n                    am=am,\n                    am_config=am_config,\n                    am_ckpt=am_ckpt,\n                    am_stat=am_stat,\n                    phones_dict=phones_dict,\n                    tones_dict=tones_dict,\n                    speaker_dict=speaker_dict,\n                    spk_id=spk_id,\n                    # vocoder related\n                    voc=voc,\n                    voc_config=voc_config,\n                    voc_ckpt=voc_ckpt,\n                    voc_stat=voc_stat,\n                    # other\n                    lang=lang,\n                    device=device,\n                    output=output,\n                    use_onnx=use_onnx,\n                    cpu_threads=cpu_threads,\n                    fs=fs)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        self.process_task_results(args.input, task_results,\n                                  args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    # pyton api 的入口是这里\n    @stats_wrapper\n    def __call__(self,\n                 text: str,\n                 am: str='fastspeech2_csmsc',\n                 am_config: Optional[os.PathLike]=None,\n                 am_ckpt: Optional[os.PathLike]=None,\n                 am_stat: Optional[os.PathLike]=None,\n                 spk_id: int=0,\n                 phones_dict: Optional[os.PathLike]=None,\n                 tones_dict: Optional[os.PathLike]=None,\n                 speaker_dict: Optional[os.PathLike]=None,\n                 voc: str='hifigan_csmsc',\n                 voc_config: Optional[os.PathLike]=None,\n                 voc_ckpt: Optional[os.PathLike]=None,\n                 voc_stat: Optional[os.PathLike]=None,\n                 lang: str='zh',\n                 device: str=paddle.get_device(),\n                 output: str='output.wav',\n                 use_onnx: bool=False,\n                 cpu_threads: int=2,\n                 fs: int=24000):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        if not use_onnx:\n            paddle.set_device(device)\n            self._init_from_path(\n                am=am,\n                am_config=am_config,\n                am_ckpt=am_ckpt,\n                am_stat=am_stat,\n                phones_dict=phones_dict,\n                tones_dict=tones_dict,\n                speaker_dict=speaker_dict,\n                voc=voc,\n                voc_config=voc_config,\n                voc_ckpt=voc_ckpt,\n                voc_stat=voc_stat,\n                lang=lang)\n\n            self.infer(text=text, lang=lang, am=am, spk_id=spk_id)\n            res = self.postprocess(output=output)\n            return res\n        else:\n            # use onnx\n            # we use `cpu` for onnxruntime by default\n            # please see description in https://github.com/PaddlePaddle/PaddleSpeech/pull/2220\n            self.task_resource = CommonTaskResource(\n                task='tts', model_format='onnx')\n            assert (\n                am in ONNX_SUPPORT_SET and voc in ONNX_SUPPORT_SET\n            ), f'the am and voc you choose, they should be in {ONNX_SUPPORT_SET}'\n            self._init_from_path_onnx(\n                am=am,\n                am_ckpt=am_ckpt,\n                phones_dict=phones_dict,\n                tones_dict=tones_dict,\n                speaker_dict=speaker_dict,\n                voc=voc,\n                voc_ckpt=voc_ckpt,\n                lang=lang,\n                device=device,\n                cpu_threads=cpu_threads,\n                fs=fs)\n            self.infer_onnx(text=text, lang=lang, am=am, spk_id=spk_id)\n            res = self.postprocess_onnx(output=output)\n            return res\n"
  },
  {
    "path": "paddlespeech/cli/utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport hashlib\nimport inspect\nimport json\nimport os\nimport tarfile\nimport threading\nimport time\nimport uuid\nimport zipfile\nfrom typing import Any\nfrom typing import Dict\n\nimport paddle\nimport requests\nimport soundfile as sf\nimport yaml\nfrom paddle.framework import load\n\nfrom . import download\nfrom ..utils.env import CONF_HOME\nfrom .entry import commands\ntry:\n    from .. import __version__\nexcept ImportError:\n    __version__ = \"0.0.0\"  # for develop branch\n\nrequests.adapters.DEFAULT_RETRIES = 3\n\n__all__ = [\n    'timer_register',\n    'cli_register',\n    'explicit_command_register',\n    'get_command',\n    'download_and_decompress',\n    'load_state_dict_from_url',\n    'stats_wrapper',\n]\n\nCLI_TIMER = {}\n\n\ndef timer_register(command):\n    CLI_TIMER[command.__name__] = {'start': [], 'end': [], 'extra': []}\n    return command\n\n\ndef cli_register(name: str, description: str='') -> Any:\n    def _warpper(command):\n        items = name.split('.')\n\n        com = commands\n        for item in items:\n            com = com[item]\n        com['_entry'] = command\n        if description:\n            com['_description'] = description\n        return command\n\n    return _warpper\n\n\ndef explicit_command_register(name: str, description: str='', cls: str=''):\n    items = name.split('.')\n    com = commands\n    for item in items:\n        com = com[item]\n    com['_entry'] = cls\n    if description:\n        com['_description'] = description\n\n\ndef get_command(name: str) -> Any:\n    items = name.split('.')\n    com = commands\n    for item in items:\n        com = com[item]\n\n    return com['_entry']\n\n\ndef _get_uncompress_path(filepath: os.PathLike) -> os.PathLike:\n    file_dir = os.path.dirname(filepath)\n    is_zip_file = False\n    if tarfile.is_tarfile(filepath):\n        files = tarfile.open(filepath, \"r:*\")\n        file_list = files.getnames()\n    elif zipfile.is_zipfile(filepath):\n        files = zipfile.ZipFile(filepath, 'r')\n        file_list = files.namelist()\n        is_zip_file = True\n    else:\n        return file_dir\n\n    if download._is_a_single_file(file_list):\n        rootpath = file_list[0]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n    elif download._is_a_single_dir(file_list):\n        if is_zip_file:\n            rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[0]\n        else:\n            rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n    else:\n        rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n\n    files.close()\n    return uncompressed_path\n\n\ndef download_and_decompress(archive: Dict[str, str], path: str) -> os.PathLike:\n    \"\"\"\n    Download archieves and decompress to specific path.\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    assert 'url' in archive and 'md5' in archive, \\\n        'Dictionary keys of \"url\" and \"md5\" are required in the archive, but got: {}'.format(list(archive.keys()))\n\n    filepath = os.path.join(path, os.path.basename(archive['url']))\n    if os.path.isfile(filepath) and download._md5check(filepath,\n                                                       archive['md5']):\n        uncompress_path = _get_uncompress_path(filepath)\n        if not os.path.isdir(uncompress_path):\n            download._decompress(filepath)\n    else:\n        StatsWorker(\n            task='download',\n            version=__version__,\n            extra_info={\n                'download_url': archive['url'],\n                'paddle_version': paddle.__version__\n            }).start()\n        uncompress_path = download.get_path_from_url(archive['url'], path,\n                                                     archive['md5'])\n\n    return uncompress_path\n\n\ndef load_state_dict_from_url(url: str, path: str, md5: str=None) -> os.PathLike:\n    \"\"\"\n    Download and load a state dict from url\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    download.get_path_from_url(url, path, md5)\n    return load(os.path.join(path, os.path.basename(url)))\n\n\ndef _md5(text: str):\n    '''Calculate the md5 value of the input text.'''\n    md5code = hashlib.md5(text.encode())\n    return md5code.hexdigest()\n\n\nclass ConfigCache:\n    def __init__(self):\n        self._data = {}\n        self._initialize()\n        self.file = os.path.join(CONF_HOME, 'cache.yaml')\n        if not os.path.exists(self.file):\n            self.flush()\n            return\n\n        with open(self.file, 'r') as file:\n            try:\n                cfg = yaml.load(file, Loader=yaml.FullLoader)\n                self._data.update(cfg)\n            except Exception as e:\n                self.flush()\n\n    @property\n    def cache_info(self):\n        return self._data['cache_info']\n\n    def _initialize(self):\n        # Set default configuration values.\n        cache_info = _md5(str(uuid.uuid1())[-12:]) + \"-\" + str(int(time.time()))\n        self._data['cache_info'] = cache_info\n\n    def flush(self):\n        '''Flush the current configuration into the configuration file.'''\n        with open(self.file, 'w') as file:\n            cfg = json.loads(json.dumps(self._data))\n            yaml.dump(cfg, file)\n\n\nstats_api = \"http://paddlepaddle.org.cn/paddlehub/stat\"\ncache_info = ConfigCache().cache_info\n\n\nclass StatsWorker(threading.Thread):\n    def __init__(self,\n                 task=\"asr\",\n                 model=None,\n                 version=__version__,\n                 extra_info={}):\n        threading.Thread.__init__(self)\n        self._task = task\n        self._model = model\n        self._version = version\n        self._extra_info = extra_info\n\n    def run(self):\n        params = {\n            'task': self._task,\n            'version': self._version,\n            'from': 'ppspeech'\n        }\n        if self._model:\n            params['model'] = self._model\n\n        self._extra_info.update({\n            'cache_info': cache_info,\n        })\n        params.update({\"extra\": json.dumps(self._extra_info)})\n\n        try:\n            requests.get(stats_api, params)\n        except Exception:\n            pass\n\n        return\n\n\ndef _note_one_stat(cls_name, params={}):\n    task = cls_name.replace('Executor', '').lower()  # XXExecutor\n    extra_info = {\n        'paddle_version': paddle.__version__,\n    }\n\n    if 'model' in params:\n        model = params['model']\n    else:\n        model = None\n\n    if 'audio_file' in params:\n        try:\n            # recursive import cased by: utils.DATA_HOME\n            _, sr = sf.read(params['audio_file'])\n        except Exception:\n            sr = -1\n\n    if task == 'asr':\n        extra_info.update({\n            'lang': params['lang'],\n            'inp_sr': sr,\n            'model_sr': params['sample_rate'],\n        })\n    elif task == 'st':\n        extra_info.update({\n            'lang':\n            params['src_lang'] + '-' + params['tgt_lang'],\n            'inp_sr':\n            sr,\n            'model_sr':\n            params['sample_rate'],\n        })\n    elif task == 'tts':\n        model = params['am']\n        extra_info.update({\n            'lang': params['lang'],\n            'vocoder': params['voc'],\n        })\n    elif task == 'cls':\n        extra_info.update({\n            'inp_sr': sr,\n        })\n    elif task == 'text':\n        extra_info.update({\n            'sub_task': params['task'],\n            'lang': params['lang'],\n        })\n    else:\n        return\n\n    StatsWorker(\n        task=task,\n        model=model,\n        version=__version__,\n        extra_info=extra_info, ).start()\n\n\ndef _parse_args(func, *args, **kwargs):\n    # FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)\n    argspec = inspect.getfullargspec(func)\n\n    keys = argspec[0]\n    if keys[0] == 'self':  # Remove self pointer.\n        keys = keys[1:]\n\n    default_values = argspec[3]\n    values = [None] * (len(keys) - len(default_values))\n    values.extend(list(default_values))\n    params = dict(zip(keys, values))\n\n    for idx, v in enumerate(args):\n        params[keys[idx]] = v\n    for k, v in kwargs.items():\n        params[k] = v\n\n    return params\n\n\ndef stats_wrapper(executor_func):\n    def _warpper(self, *args, **kwargs):\n        try:\n            _note_one_stat(\n                type(self).__name__, _parse_args(executor_func, *args,\n                                                 **kwargs))\n        except Exception:\n            pass\n        return executor_func(self, *args, **kwargs)\n\n    return _warpper\n"
  },
  {
    "path": "paddlespeech/cli/vector/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import VectorExecutor\n"
  },
  {
    "path": "paddlespeech/cli/vector/infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport sys\nfrom collections import OrderedDict\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import stats_wrapper\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.vector.io.batch import feature_normalize\nfrom paddlespeech.vector.modules.sid_model import SpeakerIdetification\n\n\nclass VectorExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__('vector')\n        self.parser = argparse.ArgumentParser(\n            prog=\"paddlespeech.vector\", add_help=True)\n\n        self.parser.add_argument(\n            \"--model\",\n            type=str,\n            default=\"ecapatdnn_voxceleb12\",\n            choices=[\n                tag[:tag.index('-')]\n                for tag in self.task_resource.pretrained_models.keys()\n            ],\n            help=\"Choose model type of vector task.\")\n        self.parser.add_argument(\n            \"--task\",\n            type=str,\n            default=\"spk\",\n            choices=[\"spk\", \"score\"],\n            help=\"task type in vector domain\")\n        self.parser.add_argument(\n            \"--input\",\n            type=str,\n            default=None,\n            help=\"Audio file to extract embedding.\")\n        self.parser.add_argument(\n            \"--sample_rate\",\n            type=int,\n            default=16000,\n            choices=[16000],\n            help=\"Choose the audio sample rate of the model. 8000 or 16000\")\n        self.parser.add_argument(\n            \"--ckpt_path\",\n            type=str,\n            default=None,\n            help=\"Checkpoint file of model.\")\n        self.parser.add_argument(\n            '--yes',\n            '-y',\n            action=\"store_true\",\n            default=False,\n            help='No additional parameters required. \\\n            Once set this parameter, it means accepting the request of the program by default, \\\n            which includes transforming the audio sample rate')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of asr task. Use default config when it is None.')\n        self.parser.add_argument(\n            \"--device\",\n            type=str,\n            default=paddle.get_device(),\n            help=\"Choose device to execute model inference.\")\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"Command line entry for vector model\n\n        Args:\n            argv (List[str]): command line args list\n\n        Returns:\n            bool: \n                False: some audio occurs error\n                True: all audio process success\n        \"\"\"\n        # stage 0: parse the args and get the required args\n        parser_args = self.parser.parse_args(argv)\n        model = parser_args.model\n        sample_rate = parser_args.sample_rate\n        config = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        force_yes = parser_args.yes\n        device = parser_args.device\n\n        # stage 1: configurate the verbose flag\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        # stage 2: read the input data and store them as a list\n        task_source = self.get_input_source(parser_args.input)\n        logger.debug(f\"task source: {task_source}\")\n\n        # stage 3: process the audio one by one\n        # we do action according the task type\n        task_result = OrderedDict()\n        has_exceptions = False\n        for id_, input_ in task_source.items():\n            try:\n                # extract the speaker audio embedding\n                if parser_args.task == \"spk\":\n                    logger.debug(\"do vector spk task\")\n                    res = self(\n                        audio_file=input_,\n                        model=model,\n                        sample_rate=sample_rate,\n                        config=config,\n                        ckpt_path=ckpt_path,\n                        force_yes=force_yes,\n                        device=device)\n                    task_result[id_] = res\n                elif parser_args.task == \"score\":\n                    logger.debug(\"do vector score task\")\n                    logger.debug(f\"input content {input_}\")\n                    if len(input_.split()) != 2:\n                        logger.error(\n                            f\"vector score task input {input_} wav num is not two,\"\n                            \"that is {len(input_.split())}\")\n                        sys.exit(-1)\n\n                    # get the enroll and test embedding\n                    enroll_audio, test_audio = input_.split()\n                    logger.debug(\n                        f\"score task, enroll audio: {enroll_audio}, test audio: {test_audio}\"\n                    )\n                    enroll_embedding = self(\n                        audio_file=enroll_audio,\n                        model=model,\n                        sample_rate=sample_rate,\n                        config=config,\n                        ckpt_path=ckpt_path,\n                        force_yes=force_yes,\n                        device=device)\n                    test_embedding = self(\n                        audio_file=test_audio,\n                        model=model,\n                        sample_rate=sample_rate,\n                        config=config,\n                        ckpt_path=ckpt_path,\n                        force_yes=force_yes,\n                        device=device)\n\n                    # get the score\n                    res = self.get_embeddings_score(enroll_embedding,\n                                                    test_embedding)\n                    task_result[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_result[id_] = f'{e.__class__.__name__}: {e}'\n\n        logger.debug(\"task result as follows: \")\n        logger.debug(f\"{task_result}\")\n\n        # stage 4: process the all the task results\n        self.process_task_results(parser_args.input, task_result,\n                                  parser_args.job_dump_result)\n\n        # stage 5: return the exception flag\n        #          if return False, somen audio process occurs error\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    def _get_job_contents(\n            self, job_input: os.PathLike) -> Dict[str, Union[str, os.PathLike]]:\n        \"\"\"\n        Read a job input file and return its contents in a dictionary.\n        Refactor from the Executor._get_job_contents\n\n        Args:\n            job_input (os.PathLike): The job input file.\n\n        Returns:\n            Dict[str, str]: Contents of job input.\n        \"\"\"\n        job_contents = OrderedDict()\n        with open(job_input) as f:\n            for line in f:\n                line = line.strip()\n                if not line:\n                    continue\n                k = line.split(' ')[0]\n                v = ' '.join(line.split(' ')[1:])\n                job_contents[k] = v\n        return job_contents\n\n    def get_embeddings_score(self, enroll_embedding, test_embedding):\n        \"\"\"get the enroll embedding and test embedding score\n\n        Args:\n            enroll_embedding (numpy.array): shape: (emb_size), enroll audio embedding\n            test_embedding (numpy.array): shape: (emb_size), test audio embedding\n\n        Returns:\n            score: the score between enroll embedding and test embedding\n        \"\"\"\n        if not hasattr(self, \"score_func\"):\n            self.score_func = paddle.nn.CosineSimilarity(axis=0)\n            logger.debug(\"create the cosine score function \")\n\n        score = self.score_func(\n            paddle.to_tensor(enroll_embedding),\n            paddle.to_tensor(test_embedding))\n\n        return score.item()\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str='ecapatdnn_voxceleb12',\n                 sample_rate: int=16000,\n                 config: os.PathLike=None,\n                 ckpt_path: os.PathLike=None,\n                 force_yes: bool=False,\n                 device=paddle.get_device()):\n        \"\"\"Extract the audio embedding\n\n        Args:\n            audio_file (os.PathLike): audio path, \n                                      whose format must be wav and sample rate must be matched the model\n            model (str, optional): mode type, which is been loaded from the pretrained model list. \n                                   Defaults to 'ecapatdnn-voxceleb12'.\n            sample_rate (int, optional): model sample rate. Defaults to 16000.\n            config (os.PathLike, optional): yaml config. Defaults to None.\n            ckpt_path (os.PathLike, optional): pretrained model path. Defaults to None.\n            device (optional): paddle running host device. Defaults to paddle.get_device().\n\n        Returns:\n            dict: return the audio embedding and the embedding shape\n        \"\"\"\n        # stage 0: check the audio format\n        audio_file = os.path.abspath(audio_file)\n        if not self._check(audio_file, sample_rate, force_yes):\n            sys.exit(-1)\n\n        # stage 1: set the paddle runtime host device\n        logger.debug(f\"device type: {device}\")\n        paddle.device.set_device(device)\n\n        # stage 2: read the specific pretrained model\n        self._init_from_path(model, sample_rate, config, ckpt_path)\n\n        # stage 3: preprocess the audio and get the audio feat\n        self.preprocess(model, audio_file)\n\n        # stage 4: infer the model and get the audio embedding\n        self.infer(model)\n\n        # stage 5: process the result and set them to output dict\n        res = self.postprocess()\n\n        return res\n\n    def _init_from_path(self,\n                        model_type: str='ecapatdnn_voxceleb12',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        ckpt_path: Optional[os.PathLike]=None,\n                        task=None):\n        \"\"\"Init the neural network from the model path\n\n        Args:\n            model_type (str, optional): model tag in the pretrained model list. \n                                        Defaults to 'ecapatdnn_voxceleb12'.\n            sample_rate (int, optional): model sample rate. \n                                         Defaults to 16000.\n            cfg_path (Optional[os.PathLike], optional): yaml config file path. \n                                                        Defaults to None.\n            ckpt_path (Optional[os.PathLike], optional): the pretrained model path, which is stored in the disk. \n                                                         Defaults to None.\n            task (str, optional): the model task type\n        \"\"\"\n        # stage 0: avoid to init the mode again\n        self.task = task\n        if hasattr(self, \"model\"):\n            logger.debug(\"Model has been initialized\")\n            return\n\n        # stage 1: get the model and config path\n        #          if we want init the network from the model stored in the disk,\n        #          we must pass the config path and the ckpt model path\n        if cfg_path is None or ckpt_path is None:\n            # get the mode from pretrained list\n            sample_rate_str = \"16k\" if sample_rate == 16000 else \"8k\"\n            tag = model_type + \"-\" + sample_rate_str\n            self.task_resource.set_task_model(tag, version=None)\n            logger.debug(f\"load the pretrained model: {tag}\")\n            # get the model from the pretrained list\n            # we download the pretrained model and store it in the res_path\n            self.res_path = self.task_resource.res_dir\n\n            self.cfg_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.task_resource.res_dir,\n                self.task_resource.res_dict['ckpt_path'] + '.pdparams')\n        else:\n            # get the model from disk\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path + \".pdparams\")\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        logger.debug(f\"start to read the ckpt from {self.ckpt_path}\")\n        logger.debug(f\"read the config from {self.cfg_path}\")\n        logger.debug(f\"get the res path {self.res_path}\")\n\n        # stage 2: read and config and init the model body\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        # stage 3: get the model name to instance the model network with dynamic_import\n        logger.debug(\"start to dynamic import the model class\")\n        model_name = model_type[:model_type.rindex('_')]\n        model_class = self.task_resource.get_model_class(model_name)\n        logger.debug(f\"model name {model_name}\")\n        model_conf = self.config.model\n        backbone = model_class(**model_conf)\n        model = SpeakerIdetification(\n            backbone=backbone, num_class=self.config.num_speakers)\n        self.model = model\n        self.model.eval()\n\n        # stage 4: load the model parameters\n        logger.debug(\"start to set the model parameters to model\")\n        model_dict = paddle.load(self.ckpt_path)\n        self.model.set_state_dict(model_dict)\n\n        logger.debug(\"create the model instance success\")\n\n    @paddle.no_grad()\n    def infer(self, model_type: str):\n        \"\"\"Infer the model to get the embedding\n\n        Args:\n            model_type (str): speaker verification model type\n        \"\"\"\n        # stage 0: get the feat and length from _inputs\n        feats = self._inputs[\"feats\"]\n        lengths = self._inputs[\"lengths\"]\n        logger.debug(\"start to do backbone network model forward\")\n        logger.debug(\n            f\"feats shape:{feats.shape}, lengths shape: {lengths.shape}\")\n\n        # stage 1: get the audio embedding\n        # embedding from (1, emb_size, 1) -> (emb_size)\n        embedding = self.model.backbone(feats, lengths).squeeze().numpy()\n        logger.debug(f\"embedding size: {embedding.shape}\")\n\n        # stage 2: put the embedding and dim info to _outputs property\n        #          the embedding type is numpy.array\n        self._outputs[\"embedding\"] = embedding\n\n    def postprocess(self) -> Union[str, os.PathLike]:\n        \"\"\"Return the audio embedding info\n\n        Returns:\n            Union[str, os.PathLike]: audio embedding info\n        \"\"\"\n        embedding = self._outputs[\"embedding\"]\n        return embedding\n\n    def preprocess(self, model_type: str, input_file: Union[str, os.PathLike]):\n        \"\"\"Extract the audio feat\n\n        Args:\n            model_type (str): speaker verification model type\n            input_file (Union[str, os.PathLike]): audio file path\n        \"\"\"\n        audio_file = input_file\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(f\"Preprocess audio file: {audio_file}\")\n\n        # stage 1: load the audio sample points\n        #    Note: this process must match the training process\n        waveform, sr = load_audio(audio_file)\n        logger.debug(\n            f\"load the audio sample points, shape is: {waveform.shape}\")\n\n        # stage 2: get the audio feat\n        # Note: Now we only support fbank feature\n        try:\n            feat = melspectrogram(\n                x=waveform,\n                sr=self.config.sr,\n                n_mels=self.config.n_mels,\n                window_size=self.config.window_size,\n                hop_length=self.config.hop_size)\n            logger.debug(f\"extract the audio feat, shape is: {feat.shape}\")\n        except Exception as e:\n            logger.debug(f\"feat occurs exception {e}\")\n            sys.exit(-1)\n\n        feat = paddle.to_tensor(feat).unsqueeze(0)\n        # in inference period, the lengths is all one without padding\n        lengths = paddle.ones([1])\n\n        # stage 3: we do feature normalize,\n        #          Now we assume that the feat must do normalize\n        feat = feature_normalize(feat, mean_norm=True, std_norm=False)\n\n        # stage 4: store the feat and length in the _inputs,\n        #          which will be used in other function\n        logger.debug(f\"feats shape: {feat.shape}\")\n        self._inputs[\"feats\"] = feat\n        self._inputs[\"lengths\"] = lengths\n\n        logger.debug(\"audio extract the feat success\")\n\n    def _check(self, audio_file: str, sample_rate: int, force_yes: bool=False):\n        \"\"\"Check if the model sample match the audio sample rate \n\n        Args:\n            audio_file (str): audio file path, which will be extracted the embedding\n            sample_rate (int): the desired model sample rate \n\n        Returns:\n            bool: return if the audio sample rate matches the model sample rate\n        \"\"\"\n        self.sample_rate = sample_rate\n        if self.sample_rate != 16000 and self.sample_rate != 8000:\n            logger.error(\n                \"invalid sample rate, please input --sr 8000 or --sr 16000\")\n            logger.error(\n                f\"The model sample rate: {self.sample_rate}, the external sample rate is: {sample_rate}\"\n            )\n            return False\n\n        if isinstance(audio_file, (str, os.PathLike)):\n            if not os.path.isfile(audio_file):\n                logger.error(\"Please input the right audio file path\")\n                return False\n\n        logger.debug(\"checking the aduio file format......\")\n        try:\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"float32\", always_2d=True)\n        except Exception as e:\n            logger.exception(e)\n            logger.error(\n                \"can not open the audio file, please check the audio file format is 'wav'. \\n \\\n                 you can try to use sox to change the file format.\\n \\\n                 For example: \\n \\\n                 sample rate: 16k \\n \\\n                 sox input_audio.xx --rate 16k --bits 16 --channels 1 output_audio.wav \\n \\\n                 sample rate: 8k \\n \\\n                 sox input_audio.xx --rate 8k --bits 16 --channels 1 output_audio.wav \\n \\\n                 \")\n            return False\n\n        logger.debug(f\"The sample rate is {audio_sample_rate}\")\n\n        if audio_sample_rate != self.sample_rate:\n            logger.debug(\"The sample rate of the input file is not {}.\\n \\\n                            The program will resample the wav file to {}.\\n \\\n                            If the result does not meet your expectations，\\n \\\n                            Please input the 16k 16 bit 1 channel wav file. \\\n                        \".format(self.sample_rate, self.sample_rate))\n            if force_yes is False:\n                while (True):\n                    logger.debug(\n                        \"Whether to change the sample rate and the channel. Y: change the sample. N: exit the prgream.\"\n                    )\n                    content = input(\"Input(Y/N):\")\n                    if content.strip() == \"Y\" or content.strip(\n                    ) == \"y\" or content.strip() == \"yes\" or content.strip(\n                    ) == \"Yes\":\n                        logger.debug(\n                            \"change the sampele rate, channel to 16k and 1 channel\"\n                        )\n                        break\n                    elif content.strip() == \"N\" or content.strip(\n                    ) == \"n\" or content.strip() == \"no\" or content.strip(\n                    ) == \"No\":\n                        logger.debug(\"Exit the program\")\n                        return False\n                    else:\n                        logger.warning(\"Not regular input, please input again\")\n            self.change_format = True\n        else:\n            logger.debug(\"The audio file format is right\")\n            self.change_format = False\n\n        return True\n"
  },
  {
    "path": "paddlespeech/cli/whisper/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .infer import WhisperExecutor\n"
  },
  {
    "path": "paddlespeech/cli/whisper/infer.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport io\nimport os\nimport sys\nimport time\nfrom collections import OrderedDict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom ...utils.env import DATA_HOME\nfrom ..download import get_path_from_url\nfrom ..executor import BaseExecutor\nfrom ..log import logger\nfrom ..utils import CLI_TIMER\nfrom ..utils import stats_wrapper\nfrom ..utils import timer_register\nfrom paddlespeech.s2t.models.whisper import log_mel_spectrogram\nfrom paddlespeech.s2t.models.whisper import ModelDimensions\nfrom paddlespeech.s2t.models.whisper import Whisper\nfrom paddlespeech.s2t.models.whisper.tokenizer import LANGUAGES\nfrom paddlespeech.s2t.models.whisper.tokenizer import TO_LANGUAGE_CODE\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = ['WhisperExecutor']\n\n\n@timer_register\nclass WhisperExecutor(BaseExecutor):\n    def __init__(self):\n        super().__init__('whisper')\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech.whisper', add_help=True)\n        self.parser.add_argument(\n            '--input', type=str, default=None, help='Audio file to recognize.')\n        self.parser.add_argument(\n            '--model',\n            type=str,\n            default='whisper',\n            choices=['whisper'],\n            help='Choose model type of asr task.')\n        self.parser.add_argument(\n            '--lang',\n            type=str,\n            default='',\n            choices=['', 'en'],\n            help='Choose model language. Default is \"\", English-only model set [en].'\n        )\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default='transcribe',\n            choices=[\"transcribe\", \"translate\"],\n            help='Choose task tpye for transcribe or translate.')\n        self.parser.add_argument(\n            '--size',\n            type=str,\n            default='turbo',\n            choices=['large', 'medium', 'base', 'small', 'tiny', 'turbo'],\n            help='Choose model size.')\n        self.parser.add_argument(\n            '--language',\n            type=str,\n            default='None',\n            choices=sorted(LANGUAGES.keys()) + sorted(\n                [k.title() for k in TO_LANGUAGE_CODE.keys()]),\n            help='Choose model decode language. Default is None, recognized by model.'\n        )\n        self.parser.add_argument(\n            \"--sample_rate\",\n            type=int,\n            default=16000,\n            choices=[16000],\n            help='Choose the audio sample rate of the model. only support 16000')\n        self.parser.add_argument(\n            '--config',\n            type=str,\n            default=None,\n            help='Config of asr task. Use default config when it is None.')\n        self.parser.add_argument(\n            '--decode_method',\n            type=str,\n            default='ctc_prefix_beam_search',\n            choices=['ctc_greedy_search', 'ctc_prefix_beam_search'],\n            help='only support transformer and conformer model')\n        self.parser.add_argument(\n            '--ckpt_path',\n            type=str,\n            default=None,\n            help='Checkpoint file of model.')\n        self.parser.add_argument(\n            '--yes',\n            '-y',\n            action=\"store_true\",\n            default=False,\n            help='No additional parameters required. \\\n            Once set this parameter, it means accepting the request of the program by default, \\\n            which includes transforming the audio sample rate')\n        self.parser.add_argument(\n            '--rtf',\n            action=\"store_true\",\n            default=False,\n            help='Show Real-time Factor(RTF).')\n        self.parser.add_argument(\n            '--device',\n            type=str,\n            default=paddle.get_device(),\n            help='Choose device to execute model inference.')\n        self.parser.add_argument(\n            '-d',\n            '--job_dump_result',\n            action='store_true',\n            help='Save job result into file.')\n        self.parser.add_argument(\n            '-v',\n            '--verbose',\n            action='store_true',\n            help='Increase logger verbosity of current task.')\n\n    def _init_from_path(self,\n                        model_type: str='whisper',\n                        lang: str='',\n                        task: str='transcribe',\n                        size: str='turbo',\n                        language: str='None',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='ctc_prefix_beam_search',\n                        num_decoding_left_chunks: int=-1,\n                        ckpt_path: Optional[os.PathLike]=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        logger.debug(\"start to init the model\")\n\n        if hasattr(self, 'model'):\n            logger.debug('Model had been initialized.')\n            return\n\n        if cfg_path is None or ckpt_path is None:\n            sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n            if lang == \"\":\n                tag = model_type + '-' + size + '-' + sample_rate_str\n            else:\n                tag = model_type + '-' + size + '-' + lang + '-' + sample_rate_str\n            self.task_resource.set_task_model(tag, version=None)\n            self.res_path = self.task_resource.res_dir\n\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n            self.ckpt_path = os.path.join(\n                self.res_path,\n                self.task_resource.res_dict['ckpt_path'] + \".pdparams\")\n            logger.debug(self.res_path)\n\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.ckpt_path = os.path.abspath(ckpt_path + \".pdparams\")\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n        logger.debug(self.cfg_path)\n        logger.debug(self.ckpt_path)\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        with UpdateConfig(self.config):\n            if \"whisper\" in model_type:\n                resource_url = self.task_resource.res_dict['resource_data']\n                resource_md5 = self.task_resource.res_dict['resource_data_md5']\n\n                self.resource_path = os.path.join(\n                    DATA_HOME, self.task_resource.version, 'whisper')\n                self.download_resource(resource_url, self.resource_path,\n                                       resource_md5)\n            else:\n                raise Exception(\"wrong type\")\n\n        # load model\n        model_dict = paddle.load(self.ckpt_path)\n        dims = ModelDimensions(**model_dict[\"dims\"])\n        self.dims = dims\n        self.model = Whisper(dims)\n        self.model.load_dict(model_dict)\n        self.model.eval()\n\n        #set task\n        if task is not None:\n            self.task = task\n\n        #set language\n        if language is not None:\n            if lang == 'en' and language != 'en':\n                logger.info(\n                    \"{tag} is an English-only model, set language=English .\")\n                self.language = 'en'\n            else:\n                self.language = language\n\n    def preprocess(self, model_type: str, input: Union[str, os.PathLike]):\n        \"\"\"\n        Input preprocess and return paddle.Tensor stored in self.input.\n        Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n        \"\"\"\n\n        audio_file = input\n        if isinstance(audio_file, (str, os.PathLike)):\n            logger.debug(\"Preprocess audio_file:\" + audio_file)\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        # Get the object for feature extraction\n        # whisper hard-coded audio hyperparameters, params in paddlespeech/s2t/models/whisper/whisper.py\n        logger.debug(\"read the audio file\")\n        audio, audio_sample_rate = soundfile.read(\n            audio_file, dtype=\"float32\", always_2d=True)\n        if self.change_format:\n            if audio.shape[1] >= 2:\n                audio = audio.mean(axis=1, dtype=np.int16)\n            else:\n                audio = audio[:, 0]\n            # pcm16 -> pcm 32\n            audio = self._pcm16to32(audio)\n            audio = librosa.resample(\n                audio, orig_sr=audio_sample_rate, target_sr=self.sample_rate)\n            audio_sample_rate = self.sample_rate\n            # pcm32 -> pcm 16\n            audio = self._pcm32to16(audio)\n        else:\n            audio = audio[:, 0]\n\n        logger.debug(f\"audio shape: {audio.shape}\")\n        # fbank\n        audio = log_mel_spectrogram(\n            audio,\n            resource_path=self.resource_path,\n            n_mels=self.dims.n_mels,\n            padding=480000)\n        audio_len = paddle.to_tensor(audio.shape[0]).unsqueeze(axis=0)\n\n        self._inputs[\"audio\"] = audio\n        self._inputs[\"audio_len\"] = audio_len\n        logger.debug(f\"audio feat shape: {audio.shape}\")\n\n        logger.debug(\"audio feat process success\")\n\n    @paddle.no_grad()\n    def infer(self, model_type: str):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        logger.debug(\"start to infer the model to get the output\")\n        cfg = self.config\n        audio = self._inputs[\"audio\"]\n        if cfg.temperature_increment_on_fallback is not None:\n            temperature = tuple(\n                np.arange(cfg.temperature, 1.0 + 1e-6,\n                          cfg.temperature_increment_on_fallback))\n        else:\n            temperature = [cfg.temperature]\n        self._outputs[\"result\"] = self.model.transcribe(\n            audio,\n            verbose=cfg.verbose,\n            task=self.task,\n            language=self.language,\n            resource_path=self.resource_path,\n            temperature=temperature,\n            compression_ratio_threshold=cfg.compression_ratio_threshold,\n            logprob_threshold=cfg.logprob_threshold,\n            best_of=cfg.best_of,\n            beam_size=cfg.beam_size,\n            patience=cfg.patience,\n            length_penalty=cfg.length_penalty,\n            initial_prompt=cfg.initial_prompt,\n            condition_on_previous_text=cfg.condition_on_previous_text,\n            no_speech_threshold=cfg.no_speech_threshold)\n\n    def postprocess(self) -> Union[str, os.PathLike]:\n        \"\"\"\n            Output postprocess and return human-readable results such as texts and audio files.\n        \"\"\"\n        return self._outputs[\"result\"]\n\n    def download_resource(self, url, lm_dir, md5sum):\n        download_path = get_path_from_url(\n            url=url,\n            root_dir=lm_dir,\n            md5sum=md5sum,\n            decompress=True, )\n\n    def _pcm16to32(self, audio):\n        assert (audio.dtype == np.int16)\n        audio = audio.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        audio = audio / (2**(bits - 1))\n        return audio\n\n    def _pcm32to16(self, audio):\n        assert (audio.dtype == np.float32)\n        bits = np.iinfo(np.int16).bits\n        audio = audio * (2**(bits - 1))\n        audio = np.round(audio).astype(\"int16\")\n        return audio\n\n    def _check(self, audio_file: str, sample_rate: int, force_yes: bool=False):\n        self.sample_rate = sample_rate\n        if self.sample_rate != 16000 and self.sample_rate != 8000:\n            logger.error(\n                \"invalid sample rate, please input --sr 8000 or --sr 16000\")\n            return False\n\n        if isinstance(audio_file, (str, os.PathLike)):\n            if not os.path.isfile(audio_file):\n                logger.error(\"Please input the right audio file path\")\n                return False\n        elif isinstance(audio_file, io.BytesIO):\n            audio_file.seek(0)\n\n        logger.debug(\"checking the audio file format......\")\n        try:\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n        except Exception as e:\n            logger.exception(e)\n            logger.error(\n                f\"can not open the audio file, please check the audio file({audio_file}) format is 'wav'. \\n \\\n                 you can try to use sox to change the file format.\\n \\\n                 For example: \\n \\\n                 sample rate: 16k \\n \\\n                 sox input_audio.xx --rate 16k --bits 16 --channels 1 output_audio.wav \\n \\\n                 sample rate: 8k \\n \\\n                 sox input_audio.xx --rate 8k --bits 16 --channels 1 output_audio.wav \\n \\\n                 \")\n            return False\n        logger.debug(\"The sample rate is %d\" % audio_sample_rate)\n        if audio_sample_rate != self.sample_rate:\n            logger.warning(\"The sample rate of the input file is not {}.\\n \\\n                            The program will resample the wav file to {}.\\n \\\n                            If the result does not meet your expectations，\\n \\\n                            Please input the 16k 16 bit 1 channel wav file. \\\n                        \".format(self.sample_rate, self.sample_rate))\n            if force_yes is False:\n                while (True):\n                    logger.debug(\n                        \"Whether to change the sample rate and the channel. Y: change the sample. N: exit the prgream.\"\n                    )\n                    content = input(\"Input(Y/N):\")\n                    if content.strip() == \"Y\" or content.strip(\n                    ) == \"y\" or content.strip() == \"yes\" or content.strip(\n                    ) == \"Yes\":\n                        logger.debug(\n                            \"change the sampele rate, channel to 16k and 1 channel\"\n                        )\n                        break\n                    elif content.strip() == \"N\" or content.strip(\n                    ) == \"n\" or content.strip() == \"no\" or content.strip(\n                    ) == \"No\":\n                        logger.debug(\"Exit the program\")\n                        return False\n                    else:\n                        logger.warning(\"Not regular input, please input again\")\n\n            self.change_format = True\n        else:\n            logger.debug(\"The audio file format is right\")\n            self.change_format = False\n\n        return True\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n\n        model = parser_args.model\n        lang = parser_args.lang\n        task = parser_args.task\n        size = parser_args.size\n        language = parser_args.language\n        sample_rate = parser_args.sample_rate\n        config = parser_args.config\n        ckpt_path = parser_args.ckpt_path\n        decode_method = parser_args.decode_method\n        force_yes = parser_args.yes\n        rtf = parser_args.rtf\n        device = parser_args.device\n\n        if not parser_args.verbose:\n            self.disable_task_loggers()\n\n        task_source = self.get_input_source(parser_args.input)\n        task_results = OrderedDict()\n        has_exceptions = False\n\n        for id_, input_ in task_source.items():\n            try:\n                res = self(\n                    audio_file=input_,\n                    model=model,\n                    lang=lang,\n                    task=task,\n                    size=size,\n                    language=language,\n                    sample_rate=sample_rate,\n                    config=config,\n                    ckpt_path=ckpt_path,\n                    decode_method=decode_method,\n                    force_yes=force_yes,\n                    rtf=rtf,\n                    device=device)\n                task_results[id_] = res\n            except Exception as e:\n                has_exceptions = True\n                task_results[id_] = f'{e.__class__.__name__}: {e}'\n\n        if rtf:\n            self.show_rtf(CLI_TIMER[self.__class__.__name__])\n\n        self.process_task_results(parser_args.input, task_results,\n                                  parser_args.job_dump_result)\n\n        if has_exceptions:\n            return False\n        else:\n            return True\n\n    @stats_wrapper\n    def __call__(self,\n                 audio_file: os.PathLike,\n                 model: str='whisper',\n                 lang: str='',\n                 task: str='transcribe',\n                 size: str='large',\n                 language: str='None',\n                 sample_rate: int=16000,\n                 config: os.PathLike=None,\n                 ckpt_path: os.PathLike=None,\n                 decode_method: str='attention_rescoring',\n                 num_decoding_left_chunks: int=-1,\n                 force_yes: bool=False,\n                 rtf: bool=False,\n                 device=paddle.get_device()):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        audio_file = os.path.abspath(audio_file)\n        paddle.set_device(device)\n        self._init_from_path(model, lang, task, size, language, sample_rate,\n                             config, decode_method, num_decoding_left_chunks,\n                             ckpt_path)\n        if not self._check(audio_file, sample_rate, force_yes):\n            sys.exit(-1)\n        if rtf:\n            k = self.__class__.__name__\n            CLI_TIMER[k]['start'].append(time.time())\n\n        self.preprocess(model, audio_file)\n        self.infer(model)\n        res = self.postprocess()  # Retrieve result of asr.\n\n        if rtf:\n            CLI_TIMER[k]['end'].append(time.time())\n            audio, audio_sample_rate = soundfile.read(\n                audio_file, dtype=\"int16\", always_2d=True)\n            CLI_TIMER[k]['extra'].append(audio.shape[0] / audio_sample_rate)\n\n        return res\n"
  },
  {
    "path": "paddlespeech/cls/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/cls/exps/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/deploy/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/deploy/predict.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport numpy as np\nimport paddle\nfrom paddle import inference\nfrom paddle.audio.datasets import ESC50\nfrom paddle.audio.features import LogMelSpectrogram\nfrom scipy.special import softmax\n\nimport paddlespeech.utils\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\n\n# yapf: disable\nparser = argparse.ArgumentParser()\nparser.add_argument(\"--model_dir\", type=str, required=True, default=\"./export\", help=\"The directory to static model.\")\nparser.add_argument('--device', choices=['cpu', 'gpu', 'xpu', 'gcu'], default=\"gpu\", help=\"Select which device to train model, defaults to gpu.\")\nparser.add_argument(\"--wav\", type=str, required=True, help=\"Audio file to infer.\")\nparser.add_argument(\"--batch_size\", type=int, default=1, help=\"Batch size per GPU/CPU for training.\")\nparser.add_argument('--use_tensorrt', type=eval, default=False, choices=[True, False], help='Enable to use tensorrt to speed up.')\nparser.add_argument(\"--precision\", type=str, default=\"fp32\", choices=[\"fp32\", \"fp16\"], help='The tensorrt precision.')\nparser.add_argument('--cpu_threads', type=int, default=10, help='Number of threads to predict when using cpu.')\nparser.add_argument('--enable_mkldnn', type=eval, default=False, choices=[True, False], help='Enable to use mkldnn to speed up when using cpu.')\nparser.add_argument(\"--log_dir\", type=str, default=\"./log\", help=\"The path to save log.\")\nargs = parser.parse_args()\n# yapf: enable\n\n\ndef extract_features(files: str, **kwargs):\n    waveforms = []\n    srs = []\n    max_length = float('-inf')\n    for file in files:\n        waveform, sr = load_audio(file)\n        max_length = max(max_length, len(waveform))\n        waveforms.append(waveform)\n        srs.append(sr)\n\n    feats = []\n    for i in range(len(waveforms)):\n        # padding\n        if len(waveforms[i]) < max_length:\n            pad_width = max_length - len(waveforms[i])\n            waveforms[i] = np.pad(waveforms[i], pad_width=(0, pad_width))\n\n        feature_extractor = LogMelSpectrogram(sr, **kwargs)\n        feat = feature_extractor(paddle.to_tensor(waveforms[i]))\n        feat = paddle.transpose(feat, perm=[1, 0]).unsqueeze(0)\n        feats.append(feat)\n\n    return np.stack(feats, axis=0)\n\n\nclass Predictor(object):\n    def __init__(self,\n                 model_dir,\n                 device=\"gpu\",\n                 batch_size=1,\n                 use_tensorrt=False,\n                 precision=\"fp32\",\n                 cpu_threads=10,\n                 enable_mkldnn=False):\n        self.batch_size = batch_size\n\n        if paddlespeech.utils.satisfy_paddle_version('3.0.0-beta'):\n            config = inference.Config(model_dir, 'inference')\n            config.disable_mkldnn()\n        else:\n            model_file = os.path.join(model_dir, 'inference.pdmodel')\n            params_file = os.path.join(model_dir, \"inference.pdiparams\")\n\n            assert os.path.isfile(model_file) and os.path.isfile(\n                params_file), 'Please check model and parameter files.'\n\n            config = inference.Config(model_file, params_file)\n\n        if device == \"gpu\":\n            # set GPU configs accordingly\n            # such as intialize the gpu memory, enable tensorrt\n            config.enable_use_gpu(100, 0)\n            precision_map = {\n                \"fp16\": inference.PrecisionType.Half,\n                \"fp32\": inference.PrecisionType.Float32,\n            }\n            precision_mode = precision_map[precision]\n\n            if use_tensorrt:\n                config.enable_tensorrt_engine(\n                    max_batch_size=batch_size,\n                    min_subgraph_size=30,\n                    precision_mode=precision_mode)\n        elif device == \"cpu\":\n            # set CPU configs accordingly,\n            # such as enable_mkldnn, set_cpu_math_library_num_threads\n            config.disable_gpu()\n            if enable_mkldnn:\n                # cache 10 different shapes for mkldnn to avoid memory leak\n                config.set_mkldnn_cache_capacity(10)\n                config.enable_mkldnn()\n            config.set_cpu_math_library_num_threads(cpu_threads)\n        elif device == \"xpu\":\n            # set XPU configs accordingly\n            config.enable_xpu(100)\n\n        config.switch_use_feed_fetch_ops(False)\n        self.predictor = inference.create_predictor(config)\n        self.input_handles = [\n            self.predictor.get_input_handle(name)\n            for name in self.predictor.get_input_names()\n        ]\n        self.output_handle = self.predictor.get_output_handle(\n            self.predictor.get_output_names()[0])\n\n    def predict(self, wavs):\n        feats = extract_features(wavs)\n\n        self.input_handles[0].copy_from_cpu(feats)\n        self.predictor.run()\n        logits = self.output_handle.copy_to_cpu()\n        probs = softmax(logits, axis=1)\n        indices = np.argmax(probs, axis=1)\n\n        return indices\n\n\nif __name__ == \"__main__\":\n    # Define predictor to do prediction.\n    predictor = Predictor(args.model_dir, args.device, args.batch_size,\n                          args.use_tensorrt, args.precision, args.cpu_threads,\n                          args.enable_mkldnn)\n\n    wavs = [args.wav]\n\n    for i in range(len(wavs)):\n        wavs[i] = os.path.abspath(os.path.expanduser(wavs[i]))\n        assert os.path.isfile(\n            wavs[i]), f'Please check input wave file: {wavs[i]}'\n\n    results = predictor.predict(wavs)\n    for idx, wav in enumerate(wavs):\n        print(f'Wav: {wav} \\t Label: {ESC50.label_list[results[idx]]}')\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/export_model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport paddle\n\nfrom paddlespeech.audio.datasets import ESC50\nfrom paddlespeech.cls.models import cnn14\nfrom paddlespeech.cls.models import SoundClassifier\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument(\"--checkpoint\", type=str, required=True, help=\"Checkpoint of model.\")\nparser.add_argument(\"--output_dir\", type=str, default='./export', help=\"Path to save static model and its parameters.\")\nargs = parser.parse_args()\n# yapf: enable\n\nif __name__ == '__main__':\n    model = SoundClassifier(\n        backbone=cnn14(pretrained=False, extract_embedding=True),\n        num_class=len(ESC50.label_list))\n    model.set_state_dict(paddle.load(args.checkpoint))\n    model.eval()\n\n    model = paddle.jit.to_static(\n        model,\n        input_spec=[\n            paddle.static.InputSpec(\n                shape=[None, None, 64], dtype=paddle.float32)\n        ],\n        full_graph=True)\n\n    # Save in static graph model.\n    paddle.jit.save(model, os.path.join(args.output_dir, \"inference\"))\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/predict.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport paddle\nimport paddle.nn.functional as F\nimport yaml\nfrom paddle.audio.features import LogMelSpectrogram\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.utils import logger\nfrom paddlespeech.cls.models import SoundClassifier\nfrom paddlespeech.utils.dynamic_import import dynamic_import\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument(\"--cfg_path\", type=str, required=True)\nargs = parser.parse_args()\n# yapf: enable\n\n\ndef extract_features(file: str, **feat_conf) -> paddle.Tensor:\n    file = os.path.abspath(os.path.expanduser(file))\n    waveform, _ = load_audio(file, sr=feat_conf['sr'])\n    feature_extractor = LogMelSpectrogram(**feat_conf)\n    feat = feature_extractor(paddle.to_tensor(waveform).unsqueeze(0))\n    feat = paddle.transpose(feat, [0, 2, 1])\n    return feat\n\n\nif __name__ == '__main__':\n\n    args.cfg_path = os.path.abspath(os.path.expanduser(args.cfg_path))\n    with open(args.cfg_path, 'r') as f:\n        config = yaml.safe_load(f)\n\n    model_conf = config['model']\n    data_conf = config['data']\n    feat_conf = config['feature']\n    predicting_conf = config['predicting']\n\n    ds_class = dynamic_import(data_conf['dataset'])\n    backbone_class = dynamic_import(model_conf['backbone'])\n\n    model = SoundClassifier(\n        backbone=backbone_class(pretrained=False, extract_embedding=True),\n        num_class=len(ds_class.label_list))\n    model.set_state_dict(paddle.load(predicting_conf['checkpoint']))\n    model.eval()\n\n    feat = extract_features(predicting_conf['audio_file'], **feat_conf)\n    logits = model(feat)\n    probs = F.softmax(logits, axis=1).numpy()\n\n    sorted_indices = (-probs[0]).argsort()\n\n    msg = f\"[{predicting_conf['audio_file']}]\\n\"\n    for idx in sorted_indices[:predicting_conf['top_k']]:\n        msg += f'{ds_class.label_list[idx]}: {probs[0][idx]}\\n'\n    logger.info(msg)\n"
  },
  {
    "path": "paddlespeech/cls/exps/panns/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport paddle\nimport yaml\nfrom paddle.audio.features import LogMelSpectrogram\n\nfrom paddlespeech.audio.utils import logger\nfrom paddlespeech.audio.utils import Timer\nfrom paddlespeech.cls.models import SoundClassifier\nfrom paddlespeech.utils.dynamic_import import dynamic_import\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument(\"--cfg_path\", type=str, required=True)\nargs = parser.parse_args()\n# yapf: enable\n\nif __name__ == \"__main__\":\n    nranks = paddle.distributed.get_world_size()\n    if paddle.distributed.get_world_size() > 1:\n        paddle.distributed.init_parallel_env()\n    local_rank = paddle.distributed.get_rank()\n\n    args.cfg_path = os.path.abspath(os.path.expanduser(args.cfg_path))\n    with open(args.cfg_path, 'r') as f:\n        config = yaml.safe_load(f)\n\n    model_conf = config['model']\n    data_conf = config['data']\n    feat_conf = config['feature']\n    training_conf = config['training']\n\n    # Dataset\n    ds_class = dynamic_import(data_conf['dataset'])\n    train_ds = ds_class(**data_conf['train'])\n    dev_ds = ds_class(**data_conf['dev'])\n    train_sampler = paddle.io.DistributedBatchSampler(\n        train_ds,\n        batch_size=training_conf['batch_size'],\n        shuffle=True,\n        drop_last=False)\n    train_loader = paddle.io.DataLoader(\n        train_ds,\n        batch_sampler=train_sampler,\n        num_workers=training_conf['num_workers'],\n        return_list=True,\n        use_buffer_reader=True, )\n\n    # Feature\n    feature_extractor = LogMelSpectrogram(**feat_conf)\n\n    # Model\n    backbone_class = dynamic_import(model_conf['backbone'])\n    backbone = backbone_class(pretrained=True, extract_embedding=True)\n    model = SoundClassifier(backbone, num_class=data_conf['num_classes'])\n    model = paddle.DataParallel(model)\n    optimizer = paddle.optimizer.Adam(\n        learning_rate=training_conf['learning_rate'],\n        parameters=model.parameters())\n    criterion = paddle.nn.loss.CrossEntropyLoss()\n\n    steps_per_epoch = len(train_sampler)\n    timer = Timer(steps_per_epoch * training_conf['epochs'])\n    timer.start()\n\n    for epoch in range(1, training_conf['epochs'] + 1):\n        model.train()\n\n        avg_loss = 0\n        num_corrects = 0\n        num_samples = 0\n        for batch_idx, batch in enumerate(train_loader):\n            waveforms, labels = batch\n            feats = feature_extractor(\n                waveforms\n            )  # Need a padding when lengths of waveforms differ in a batch.\n            feats = paddle.transpose(feats, [0, 2, 1])  # To [N, length, n_mels]\n\n            logits = model(feats)\n\n            loss = criterion(logits, labels)\n            loss.backward()\n            optimizer.step()\n            if isinstance(optimizer._learning_rate,\n                          paddle.optimizer.lr.LRScheduler):\n                optimizer._learning_rate.step()\n            optimizer.clear_grad()\n\n            # Calculate loss\n            avg_loss += float(loss)\n\n            # Calculate metrics\n            preds = paddle.argmax(logits, axis=1)\n            num_corrects += (preds == labels).numpy().sum()\n            num_samples += feats.shape[0]\n\n            timer.count()\n\n            if (batch_idx + 1\n                ) % training_conf['log_freq'] == 0 and local_rank == 0:\n                lr = optimizer.get_lr()\n                avg_loss /= training_conf['log_freq']\n                avg_acc = num_corrects / num_samples\n\n                print_msg = 'Epoch={}/{}, Step={}/{}'.format(\n                    epoch, training_conf['epochs'], batch_idx + 1,\n                    steps_per_epoch)\n                print_msg += ' loss={:.4f}'.format(avg_loss)\n                print_msg += ' acc={:.4f}'.format(avg_acc)\n                print_msg += ' lr={:.6f} step/sec={:.2f} | ETA {}'.format(\n                    lr, timer.timing, timer.eta)\n                logger.train(print_msg)\n\n                avg_loss = 0\n                num_corrects = 0\n                num_samples = 0\n\n        if epoch % training_conf[\n                'save_freq'] == 0 and batch_idx + 1 == steps_per_epoch and local_rank == 0:\n            dev_sampler = paddle.io.BatchSampler(\n                dev_ds,\n                batch_size=training_conf['batch_size'],\n                shuffle=False,\n                drop_last=False)\n            dev_loader = paddle.io.DataLoader(\n                dev_ds,\n                batch_sampler=dev_sampler,\n                num_workers=training_conf['num_workers'],\n                return_list=True, )\n\n            model.eval()\n            num_corrects = 0\n            num_samples = 0\n            with logger.processing('Evaluation on validation dataset'):\n                for batch_idx, batch in enumerate(dev_loader):\n                    waveforms, labels = batch\n                    feats = feature_extractor(waveforms)\n                    feats = paddle.transpose(feats, [0, 2, 1])\n\n                    logits = model(feats)\n\n                    preds = paddle.argmax(logits, axis=1)\n                    num_corrects += (preds == labels).numpy().sum()\n                    num_samples += feats.shape[0]\n\n            print_msg = '[Evaluation result]'\n            print_msg += ' dev_acc={:.4f}'.format(num_corrects / num_samples)\n\n            logger.eval(print_msg)\n\n            # Save model\n            save_dir = os.path.join(training_conf['checkpoint_dir'],\n                                    'epoch_{}'.format(epoch))\n            logger.info('Saving model checkpoint to {}'.format(save_dir))\n            paddle.save(model.state_dict(),\n                        os.path.join(save_dir, 'model.pdparams'))\n            paddle.save(optimizer.state_dict(),\n                        os.path.join(save_dir, 'model.pdopt'))\n"
  },
  {
    "path": "paddlespeech/cls/models/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .panns import *\n"
  },
  {
    "path": "paddlespeech/cls/models/panns/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .classifier import *\nfrom .panns import *\n"
  },
  {
    "path": "paddlespeech/cls/models/panns/classifier.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle.nn as nn\n\n\nclass SoundClassifier(nn.Layer):\n    \"\"\"\n    Model for sound classification which uses panns pretrained models to extract\n    embeddings from audio files.\n    \"\"\"\n\n    def __init__(self, backbone, num_class, dropout=0.1):\n        super(SoundClassifier, self).__init__()\n        self.backbone = backbone\n        self.dropout = nn.Dropout(dropout)\n        self.fc = nn.Linear(self.backbone.emb_size, num_class)\n\n    def forward(self, x):\n        # x: (batch_size, num_frames, num_melbins) -> (batch_size, 1, num_frames, num_melbins)\n        x = x.unsqueeze(1)\n        x = self.backbone(x)\n        x = self.dropout(x)\n        logits = self.fc(x)\n\n        return logits\n"
  },
  {
    "path": "paddlespeech/cls/models/panns/panns.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.audio.utils.download import load_state_dict_from_url\nfrom paddlespeech.utils.env import MODEL_HOME\n\n__all__ = ['CNN14', 'CNN10', 'CNN6', 'cnn14', 'cnn10', 'cnn6']\n\npretrained_model_urls = {\n    'cnn14': 'https://bj.bcebos.com/paddleaudio/models/panns_cnn14.pdparams',\n    'cnn10': 'https://bj.bcebos.com/paddleaudio/models/panns_cnn10.pdparams',\n    'cnn6': 'https://bj.bcebos.com/paddleaudio/models/panns_cnn6.pdparams',\n}\n\n\nclass ConvBlock(nn.Layer):\n    def __init__(self, in_channels, out_channels):\n        super(ConvBlock, self).__init__()\n\n        self.conv1 = nn.Conv2D(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=(3, 3),\n            stride=(1, 1),\n            padding=(1, 1),\n            bias_attr=False)\n        self.conv2 = nn.Conv2D(\n            in_channels=out_channels,\n            out_channels=out_channels,\n            kernel_size=(3, 3),\n            stride=(1, 1),\n            padding=(1, 1),\n            bias_attr=False)\n        self.bn1 = nn.BatchNorm2D(out_channels)\n        self.bn2 = nn.BatchNorm2D(out_channels)\n\n    def forward(self, x, pool_size=(2, 2), pool_type='avg'):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = F.relu(x)\n\n        x = self.conv2(x)\n        x = self.bn2(x)\n        x = F.relu(x)\n\n        if pool_type == 'max':\n            x = F.max_pool2d(x, kernel_size=pool_size)\n        elif pool_type == 'avg':\n            x = F.avg_pool2d(x, kernel_size=pool_size)\n        elif pool_type == 'avg+max':\n            x = F.avg_pool2d(\n                x, kernel_size=pool_size) + F.max_pool2d(\n                    x, kernel_size=pool_size)\n        else:\n            raise Exception(\n                f'Pooling type of {pool_type} is not supported. It must be one of \"max\", \"avg\" and \"avg+max\".'\n            )\n        return x\n\n\nclass ConvBlock5x5(nn.Layer):\n    def __init__(self, in_channels, out_channels):\n        super(ConvBlock5x5, self).__init__()\n\n        self.conv1 = nn.Conv2D(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=(5, 5),\n            stride=(1, 1),\n            padding=(2, 2),\n            bias_attr=False)\n        self.bn1 = nn.BatchNorm2D(out_channels)\n\n    def forward(self, x, pool_size=(2, 2), pool_type='avg'):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = F.relu(x)\n\n        if pool_type == 'max':\n            x = F.max_pool2d(x, kernel_size=pool_size)\n        elif pool_type == 'avg':\n            x = F.avg_pool2d(x, kernel_size=pool_size)\n        elif pool_type == 'avg+max':\n            x = F.avg_pool2d(\n                x, kernel_size=pool_size) + F.max_pool2d(\n                    x, kernel_size=pool_size)\n        else:\n            raise Exception(\n                f'Pooling type of {pool_type} is not supported. It must be one of \"max\", \"avg\" and \"avg+max\".'\n            )\n        return x\n\n\nclass CNN14(nn.Layer):\n    \"\"\"\n    The CNN14(14-layer CNNs) mainly consist of 6 convolutional blocks while each convolutional\n    block consists of 2 convolutional layers with a kernel size of 3 × 3.\n\n    Reference:\n        PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition\n        https://arxiv.org/pdf/1912.10211.pdf\n    \"\"\"\n    emb_size = 2048\n\n    def __init__(self, extract_embedding: bool=True):\n\n        super(CNN14, self).__init__()\n        self.bn0 = nn.BatchNorm2D(64)\n        self.conv_block1 = ConvBlock(in_channels=1, out_channels=64)\n        self.conv_block2 = ConvBlock(in_channels=64, out_channels=128)\n        self.conv_block3 = ConvBlock(in_channels=128, out_channels=256)\n        self.conv_block4 = ConvBlock(in_channels=256, out_channels=512)\n        self.conv_block5 = ConvBlock(in_channels=512, out_channels=1024)\n        self.conv_block6 = ConvBlock(in_channels=1024, out_channels=2048)\n\n        self.fc1 = nn.Linear(2048, self.emb_size)\n        self.fc_audioset = nn.Linear(self.emb_size, 527)\n        self.extract_embedding = extract_embedding\n\n    def forward(self, x):\n        x.stop_gradient = False\n        x = x.transpose([0, 3, 2, 1])\n        x = self.bn0(x)\n        x = x.transpose([0, 3, 2, 1])\n\n        x = self.conv_block1(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block2(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block3(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block4(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block5(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block6(x, pool_size=(1, 1), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = x.mean(axis=3)\n        x = x.max(axis=2) + x.mean(axis=2)\n\n        x = F.dropout(x, p=0.5, training=self.training)\n        x = F.relu(self.fc1(x))\n\n        if self.extract_embedding:\n            output = F.dropout(x, p=0.5, training=self.training)\n        else:\n            output = F.sigmoid(self.fc_audioset(x))\n        return output\n\n\nclass CNN10(nn.Layer):\n    \"\"\"\n    The CNN10(14-layer CNNs) mainly consist of 4 convolutional blocks while each convolutional\n    block consists of 2 convolutional layers with a kernel size of 3 × 3.\n\n    Reference:\n        PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition\n        https://arxiv.org/pdf/1912.10211.pdf\n    \"\"\"\n    emb_size = 512\n\n    def __init__(self, extract_embedding: bool=True):\n\n        super(CNN10, self).__init__()\n        self.bn0 = nn.BatchNorm2D(64)\n        self.conv_block1 = ConvBlock(in_channels=1, out_channels=64)\n        self.conv_block2 = ConvBlock(in_channels=64, out_channels=128)\n        self.conv_block3 = ConvBlock(in_channels=128, out_channels=256)\n        self.conv_block4 = ConvBlock(in_channels=256, out_channels=512)\n\n        self.fc1 = nn.Linear(512, self.emb_size)\n        self.fc_audioset = nn.Linear(self.emb_size, 527)\n        self.extract_embedding = extract_embedding\n\n    def forward(self, x):\n        x.stop_gradient = False\n        x = x.transpose([0, 3, 2, 1])\n        x = self.bn0(x)\n        x = x.transpose([0, 3, 2, 1])\n\n        x = self.conv_block1(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block2(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block3(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block4(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = x.mean(axis=3)\n        x = x.max(axis=2) + x.mean(axis=2)\n\n        x = F.dropout(x, p=0.5, training=self.training)\n        x = F.relu(self.fc1(x))\n\n        if self.extract_embedding:\n            output = F.dropout(x, p=0.5, training=self.training)\n        else:\n            output = F.sigmoid(self.fc_audioset(x))\n        return output\n\n\nclass CNN6(nn.Layer):\n    \"\"\"\n    The CNN14(14-layer CNNs) mainly consist of 4 convolutional blocks while each convolutional\n    block consists of 1 convolutional layers with a kernel size of 5 × 5.\n\n    Reference:\n        PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition\n        https://arxiv.org/pdf/1912.10211.pdf\n    \"\"\"\n    emb_size = 512\n\n    def __init__(self, extract_embedding: bool=True):\n\n        super(CNN6, self).__init__()\n        self.bn0 = nn.BatchNorm2D(64)\n        self.conv_block1 = ConvBlock5x5(in_channels=1, out_channels=64)\n        self.conv_block2 = ConvBlock5x5(in_channels=64, out_channels=128)\n        self.conv_block3 = ConvBlock5x5(in_channels=128, out_channels=256)\n        self.conv_block4 = ConvBlock5x5(in_channels=256, out_channels=512)\n\n        self.fc1 = nn.Linear(512, self.emb_size)\n        self.fc_audioset = nn.Linear(self.emb_size, 527)\n        self.extract_embedding = extract_embedding\n\n    def forward(self, x):\n        x.stop_gradient = False\n        x = x.transpose([0, 3, 2, 1])\n        x = self.bn0(x)\n        x = x.transpose([0, 3, 2, 1])\n\n        x = self.conv_block1(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block2(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block3(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = self.conv_block4(x, pool_size=(2, 2), pool_type='avg')\n        x = F.dropout(x, p=0.2, training=self.training)\n\n        x = x.mean(axis=3)\n        x = x.max(axis=2) + x.mean(axis=2)\n\n        x = F.dropout(x, p=0.5, training=self.training)\n        x = F.relu(self.fc1(x))\n\n        if self.extract_embedding:\n            output = F.dropout(x, p=0.5, training=self.training)\n        else:\n            output = F.sigmoid(self.fc_audioset(x))\n        return output\n\n\ndef cnn14(pretrained: bool=False, extract_embedding: bool=True) -> CNN14:\n    model = CNN14(extract_embedding=extract_embedding)\n    if pretrained:\n        state_dict = load_state_dict_from_url(\n            url=pretrained_model_urls['cnn14'],\n            path=os.path.join(MODEL_HOME, 'panns'))\n        model.set_state_dict(state_dict)\n    return model\n\n\ndef cnn10(pretrained: bool=False, extract_embedding: bool=True) -> CNN10:\n    model = CNN10(extract_embedding=extract_embedding)\n    if pretrained:\n        state_dict = load_state_dict_from_url(\n            url=pretrained_model_urls['cnn10'],\n            path=os.path.join(MODEL_HOME, 'panns'))\n        model.set_state_dict(state_dict)\n    return model\n\n\ndef cnn6(pretrained: bool=False, extract_embedding: bool=True) -> CNN6:\n    model = CNN6(extract_embedding=extract_embedding)\n    if pretrained:\n        state_dict = load_state_dict_from_url(\n            url=pretrained_model_urls['cnn6'],\n            path=os.path.join(MODEL_HOME, 'panns'))\n        model.set_state_dict(state_dict)\n    return model\n"
  },
  {
    "path": "paddlespeech/dataset/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/dataset/aidatatang_200zh/README.md",
    "content": "# [Aidatatang_200zh](http://openslr.elda.org/62/)\n\nAidatatang_200zh is a free Chinese Mandarin speech corpus provided by Beijing DataTang Technology Co., Ltd under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.\nThe contents and the corresponding descriptions of the corpus include:\n\n* The corpus contains 200 hours of acoustic data, which is mostly mobile recorded data.\n* 600 speakers from different accent areas in China are invited to participate in the recording.\n* The transcription accuracy for each sentence is larger than 98%.\n* Recordings are conducted in a quiet indoor environment.\n* The database is divided into training set, validation set, and testing set in a ratio of 7: 1: 2.\n* Detail information such as speech data coding and speaker information is preserved in the metadata file.\n* Segmented transcripts are also provided.\n\nThe corpus aims to support researchers in speech recognition, machine translation, voiceprint recognition, and other speech-related fields. Therefore, the corpus is totally free for academic use.\n"
  },
  {
    "path": "paddlespeech/dataset/aidatatang_200zh/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .aidatatang_200zh import main as aidatatang_200zh_main\n"
  },
  {
    "path": "paddlespeech/dataset/aidatatang_200zh/aidatatang_200zh.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare aidatatang_200zh mandarin dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\nfrom paddlespeech.utils.argparse import print_arguments\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nURL_ROOT = 'http://www.openslr.org/resources/62'\n# URL_ROOT = 'https://openslr.magicdatatech.com/resources/62'\nDATA_URL = URL_ROOT + '/aidatatang_200zh.tgz'\nMD5_DATA = '6e0f4f39cd5f667a7ee53c397c8d0949'\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/aidatatang_200zh\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % manifest_path_prefix)\n    json_lines = []\n    transcript_path = os.path.join(data_dir, 'transcript',\n                                   'aidatatang_200_zh_transcript.txt')\n    transcript_dict = {}\n    for line in codecs.open(transcript_path, 'r', 'utf-8'):\n        line = line.strip()\n        if line == '':\n            continue\n        audio_id, text = line.split(' ', 1)\n        # remove withespace, character text\n        text = ''.join(text.split())\n        transcript_dict[audio_id] = text\n\n    data_types = ['train', 'dev', 'test']\n    for dtype in data_types:\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        audio_dir = os.path.join(data_dir, 'corpus/', dtype)\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for fname in filelist:\n                if not fname.endswith('.wav'):\n                    continue\n\n                audio_path = os.path.abspath(os.path.join(subfolder, fname))\n                audio_id = os.path.basename(fname)[:-4]\n                utt2spk = Path(audio_path).parent.name\n\n                audio_data, samplerate = soundfile.read(audio_path)\n                duration = float(len(audio_data) / samplerate)\n                text = transcript_dict[audio_id]\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt': audio_id,\n                            'utt2spk': str(utt2spk),\n                            'feat': audio_path,\n                            'feat_shape': (duration, ),  # second\n                            'text': text,\n                        },\n                        ensure_ascii=False))\n\n                total_sec += duration\n                total_text += len(text)\n                total_num += 1\n\n        manifest_path = manifest_path_prefix + '.' + dtype\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n        manifest_dir = os.path.dirname(manifest_path_prefix)\n        meta_path = os.path.join(manifest_dir, dtype) + '.meta'\n        with open(meta_path, 'w') as f:\n            print(f\"{dtype}:\", file=f)\n            print(f\"{total_num} utts\", file=f)\n            print(f\"{total_sec / (60*60)} h\", file=f)\n            print(f\"{total_text} text\", file=f)\n            print(f\"{total_text / total_sec} text/sec\", file=f)\n            print(f\"{total_sec / total_num} sec/utt\", file=f)\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path, subset):\n    \"\"\"Download, unpack and create manifest file.\"\"\"\n    data_dir = os.path.join(target_dir, subset)\n    if not os.path.exists(data_dir):\n        filepath = download(url, md5sum, target_dir)\n        unpack(filepath, target_dir)\n        # unpack all audio tar files\n        audio_dir = os.path.join(data_dir, 'corpus')\n        for subfolder, dirlist, filelist in sorted(os.walk(audio_dir)):\n            for sub in dirlist:\n                print(f\"unpack dir {sub}...\")\n                for folder, _, filelist in sorted(\n                        os.walk(os.path.join(subfolder, sub))):\n                    for ftar in filelist:\n                        unpack(os.path.join(folder, ftar), folder, True)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              target_dir)\n\n    create_manifest(data_dir, manifest_path)\n\n\ndef main():\n    print_arguments(args, globals())\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    prepare_dataset(\n        url=DATA_URL,\n        md5sum=MD5_DATA,\n        target_dir=args.target_dir,\n        manifest_path=args.manifest_prefix,\n        subset='aidatatang_200zh')\n\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/aishell/README.md",
    "content": "# [Aishell1](http://openslr.elda.org/33/)\n\nThis Open Source Mandarin Speech Corpus, AISHELL-ASR0009-OS1, is 178 hours long. It is a part of AISHELL-ASR0009, of which utterance contains 11 domains, including smart home, autonomous driving, and industrial production. The whole recording was put in quiet indoor environment, using 3 different devices at the same time: high fidelity microphone (44.1kHz, 16-bit,); Android-system mobile phone (16kHz, 16-bit), iOS-system mobile phone (16kHz, 16-bit). Audios in high fidelity were re-sampled to 16kHz to build AISHELL- ASR0009-OS1. 400 speakers from different accent areas in China were invited to participate in the recording. The manual transcription accuracy rate is above 95%, through professional speech annotation and strict quality inspection. The corpus is divided into training, development and testing sets. ( This database is free for academic research, not in the commerce, if without permission. )\n\n\n## Dataset Architecture\n\n```bash\ndata_aishell\n├── transcript      # text 目录\n└── wav             # wav 目录\n    ├── dev         # dev 目录\n    │   ├── S0724   # spk 目录\n    │   ├── S0725\n    │   ├── S0726\n    ├── train\n    │   ├── S0724\n    │   ├── S0725\n    │   ├── S0726\n    ├── test\n    │   ├── S0724\n    │   ├── S0725\n    │   ├── S0726\n \n\ndata_aishell\n├── transcript\n│   └── aishell_transcript_v0.8.txt   # 文本标注文件\n└── wav\n    ├── dev\n    │   ├── S0724\n    │   │   ├── BAC009S0724W0121.wav  # S0724 的音频\n    │   │   ├── BAC009S0724W0122.wav\n    │   │   ├── BAC009S0724W0123.wav\n    ├── test\n    │   ├── S0724\n    │   │   ├── BAC009S0724W0121.wav\n    │   │   ├── BAC009S0724W0122.wav\n    │   │   ├── BAC009S0724W0123.wav\n    ├── train\n    │   ├── S0724\n    │   │   ├── BAC009S0724W0121.wav\n    │   │   ├── BAC009S0724W0122.wav\n    │   │   ├── BAC009S0724W0123.wav\n    \n标注文件格式： <utt> <tokens>\n> head data_aishell/transcript/aishell_transcript_v0.8.txt \nBAC009S0002W0122 而 对 楼市 成交 抑制 作用 最 大 的 限 购\nBAC009S0002W0123 也 成为 地方 政府 的 眼中 钉\nBAC009S0002W0124 自 六月 底 呼和浩特 市 率先 宣布 取消 限 购 后\nBAC009S0002W0125 各地 政府 便 纷纷 跟进\nBAC009S0002W0126 仅 一 个 多 月 的 时间 里\nBAC009S0002W0127 除了 北京 上海 广州 深圳 四 个 一 线 城市 和 三亚 之外\nBAC009S0002W0128 四十六 个 限 购 城市 当中\nBAC009S0002W0129 四十一 个 已 正式 取消 或 变相 放松 了 限 购\nBAC009S0002W0130 财政 金融 政策 紧随 其后 而来\nBAC009S0002W0131 显示 出 了 极 强 的 威力\n```\n"
  },
  {
    "path": "paddlespeech/dataset/aishell/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .aishell import check_dataset\nfrom .aishell import create_manifest\nfrom .aishell import download_dataset\nfrom .aishell import main as aishell_main\nfrom .aishell import prepare_dataset\n"
  },
  {
    "path": "paddlespeech/dataset/aishell/aishell.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Prepare Aishell mandarin dataset\n\nDownload, unpack and create manifest files.\nManifest file is a json-format file with each line containing the\nmeta data (i.e. audio filepath, transcript and audio duration)\nof each audio file in the data set.\n\"\"\"\nimport argparse\nimport codecs\nimport json\nimport os\nfrom pathlib import Path\n\nimport soundfile\n\nfrom paddlespeech.dataset.download import download\nfrom paddlespeech.dataset.download import unpack\nfrom paddlespeech.utils.argparse import print_arguments\n\nDATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech')\n\nURL_ROOT = 'http://openslr.elda.org/resources/33'\n# URL_ROOT = 'https://openslr.magicdatatech.com/resources/33'\nDATA_URL = URL_ROOT + '/data_aishell.tgz'\nMD5_DATA = '2f494334227864a8a8fec932999db9d8'\nRESOURCE_URL = URL_ROOT + '/resource_aishell.tgz'\nMD5_RESOURCE = '957d480a0fcac85fc18e550756f624e5'\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--target_dir\",\n    default=DATA_HOME + \"/Aishell\",\n    type=str,\n    help=\"Directory to save the dataset. (default: %(default)s)\")\nparser.add_argument(\n    \"--manifest_prefix\",\n    default=\"manifest\",\n    type=str,\n    help=\"Filepath prefix for output manifests. (default: %(default)s)\")\nargs = parser.parse_args()\n\n\ndef create_manifest(data_dir, manifest_path_prefix):\n    print(\"Creating manifest %s ...\" % os.path.join(data_dir,\n                                                    manifest_path_prefix))\n    json_lines = []\n    transcript_path = os.path.join(data_dir, 'transcript',\n                                   'aishell_transcript_v0.8.txt')\n    transcript_dict = {}\n    for line in codecs.open(transcript_path, 'r', 'utf-8'):\n        line = line.strip()\n        if line == '':\n            continue\n        audio_id, text = line.split(' ', 1)\n        # remove withespace, character text\n        text = ''.join(text.split())\n        transcript_dict[audio_id] = text\n\n    data_metas = dict()\n    data_types = ['train', 'dev', 'test']\n    for dtype in data_types:\n        del json_lines[:]\n        total_sec = 0.0\n        total_text = 0.0\n        total_num = 0\n\n        audio_dir = os.path.join(data_dir, 'wav', dtype)\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for fname in filelist:\n                audio_path = os.path.abspath(os.path.join(subfolder, fname))\n                audio_id = os.path.basename(fname)[:-4]\n                # if no transcription for audio then skipped\n                if audio_id not in transcript_dict:\n                    continue\n\n                utt2spk = Path(audio_path).parent.name\n                audio_data, samplerate = soundfile.read(audio_path)\n                duration = float(len(audio_data) / samplerate)\n                text = transcript_dict[audio_id]\n                json_lines.append(\n                    json.dumps(\n                        {\n                            'utt': audio_id,\n                            'utt2spk': str(utt2spk),\n                            'feat': audio_path,\n                            'feat_shape': (duration, ),  # second\n                            'text': text\n                        },\n                        ensure_ascii=False))\n\n                total_sec += duration\n                total_text += len(text)\n                total_num += 1\n\n        manifest_path = manifest_path_prefix + '.' + dtype\n        with codecs.open(manifest_path, 'w', 'utf-8') as fout:\n            for line in json_lines:\n                fout.write(line + '\\n')\n\n        meta = dict()\n        meta[\"dtype\"] = dtype  # train, dev, test\n        meta[\"utts\"] = total_num\n        meta[\"hours\"] = total_sec / (60 * 60)\n        meta[\"text\"] = total_text\n        meta[\"text/sec\"] = total_text / total_sec\n        meta[\"sec/utt\"] = total_sec / total_num\n        data_metas[dtype] = meta\n\n        manifest_dir = os.path.dirname(manifest_path_prefix)\n        meta_path = os.path.join(manifest_dir, dtype) + '.meta'\n        with open(meta_path, 'w') as f:\n            for key, val in meta.items():\n                print(f\"{key}: {val}\", file=f)\n\n    return data_metas\n\n\ndef download_dataset(url, md5sum, target_dir):\n    \"\"\"Download, unpack and create manifest file.\"\"\"\n    data_dir = os.path.join(target_dir, 'data_aishell')\n    if not os.path.exists(data_dir):\n        filepath = download(url, md5sum, target_dir)\n        unpack(filepath, target_dir)\n        # unpack all audio tar files\n        audio_dir = os.path.join(data_dir, 'wav')\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for ftar in filelist:\n                unpack(os.path.join(subfolder, ftar), subfolder, True)\n    else:\n        print(\"Skip downloading and unpacking. Data already exists in %s.\" %\n              os.path.abspath(target_dir))\n    return os.path.abspath(data_dir)\n\n\ndef check_dataset(data_dir):\n    print(f\"check dataset {os.path.abspath(data_dir)} ...\")\n\n    transcript_path = os.path.join(data_dir, 'transcript',\n                                   'aishell_transcript_v0.8.txt')\n    if not os.path.exists(transcript_path):\n        raise FileNotFoundError(f\"no transcript file found in {data_dir}.\")\n\n    transcript_dict = {}\n    for line in codecs.open(transcript_path, 'r', 'utf-8'):\n        line = line.strip()\n        if line == '':\n            continue\n        audio_id, text = line.split(' ', 1)\n        # remove withespace, character text\n        text = ''.join(text.split())\n        transcript_dict[audio_id] = text\n\n    no_label = 0\n    data_types = ['train', 'dev', 'test']\n    for dtype in data_types:\n        audio_dir = os.path.join(data_dir, 'wav', dtype)\n        if not os.path.exists(audio_dir):\n            raise IOError(f\"{audio_dir} does not exist.\")\n\n        for subfolder, _, filelist in sorted(os.walk(audio_dir)):\n            for fname in filelist:\n                audio_path = os.path.abspath(os.path.join(subfolder, fname))\n                audio_id = os.path.basename(fname)[:-4]\n                # if no transcription for audio then skipped\n                if audio_id not in transcript_dict:\n                    print(f\"Warning: {audio_id} not has transcript.\")\n                    no_label += 1\n                    continue\n\n                utt2spk = Path(audio_path).parent.name\n                audio_data, samplerate = soundfile.read(audio_path)\n                assert samplerate == 16000, f\"{audio_path} sample rate is {samplerate} not 16k, please check.\"\n\n        print(f\"Warning: {dtype} has {no_label} audio does not has transcript.\")\n\n\ndef prepare_dataset(url, md5sum, target_dir, manifest_path=None, check=False):\n    \"\"\"Download, unpack and create manifest file.\"\"\"\n    data_dir = download_dataset(url, md5sum, target_dir)\n\n    if check:\n        try:\n            check_dataset(data_dir)\n        except Exception as e:\n            raise ValueError(\n                f\"{data_dir} dataset format not right, please check it.\")\n\n    meta = None\n    if manifest_path:\n        meta = create_manifest(data_dir, manifest_path)\n\n    return data_dir, meta\n\n\ndef main():\n    print_arguments(args, globals())\n    if args.target_dir.startswith('~'):\n        args.target_dir = os.path.expanduser(args.target_dir)\n\n    data_dir, meta = prepare_dataset(\n        url=DATA_URL,\n        md5sum=MD5_DATA,\n        target_dir=args.target_dir,\n        manifest_path=args.manifest_prefix,\n        check=True)\n\n    resource_dir, _ = prepare_dataset(\n        url=RESOURCE_URL,\n        md5sum=MD5_RESOURCE,\n        target_dir=args.target_dir,\n        manifest_path=None)\n\n    print(\"Data download and manifest prepare done!\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/download.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport hashlib\nimport os\nimport sys\nimport tarfile\nimport zipfile\nfrom typing import Text\n\n__all__ = [\n    \"check_md5sum\",\n    \"getfile_insensitive\",\n    \"download_multi\",\n    \"download\",\n    \"unpack\",\n    \"unzip\",\n    \"md5file\",\n]\n\n\ndef md5file(fname):\n    hash_md5 = hashlib.md5()\n    f = open(fname, \"rb\")\n    for chunk in iter(lambda: f.read(4096), b\"\"):\n        hash_md5.update(chunk)\n    f.close()\n    return hash_md5.hexdigest()\n\n\ndef getfile_insensitive(path):\n    \"\"\"Get the actual file path when given insensitive filename.\"\"\"\n    directory, filename = os.path.split(path)\n    directory, filename = (directory or '.'), filename.lower()\n    for f in os.listdir(directory):\n        newpath = os.path.join(directory, f)\n        if os.path.isfile(newpath) and f.lower() == filename:\n            return newpath\n\n\ndef download_multi(url, target_dir, extra_args):\n    \"\"\"Download multiple files from url to target_dir.\"\"\"\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n    print(\"Downloading %s ...\" % url)\n    ret_code = os.system(\"wget -c \" + url + ' ' + extra_args + \" -P \" +\n                         target_dir)\n    return ret_code\n\n\ndef download(url, md5sum, target_dir):\n    \"\"\"Download file from url to target_dir, and check md5sum.\"\"\"\n    if not os.path.exists(target_dir):\n        os.makedirs(target_dir)\n    filepath = os.path.join(target_dir, url.split(\"/\")[-1])\n    if not (os.path.exists(filepath) and md5file(filepath) == md5sum):\n        print(\"Downloading %s ...\" % url)\n        os.system(\"wget -c \" + url + \" -P \" + target_dir)\n        print(\"\\nMD5 Chesksum %s ...\" % filepath)\n        if not md5file(filepath) == md5sum:\n            raise RuntimeError(\"MD5 checksum failed.\")\n    else:\n        print(\"File exists, skip downloading. (%s)\" % filepath)\n    return filepath\n\n\ndef check_md5sum(filepath: Text, md5sum: Text) -> bool:\n    \"\"\"check md5sum of file.\n\n    Args:\n        filepath (Text): [description]\n        md5sum (Text): [description]\n\n    Returns:\n        bool: same or not.\n    \"\"\"\n    return md5file(filepath) == md5sum\n\n\ndef unpack(filepath, target_dir, rm_tar=False):\n    \"\"\"Unpack the file to the target_dir.\"\"\"\n    print(\"Unpacking %s ...\" % filepath)\n    tar = tarfile.open(filepath)\n    tar.extractall(target_dir)\n    tar.close()\n    if rm_tar:\n        os.remove(filepath)\n\n\ndef unzip(filepath, target_dir, rm_tar=False):\n    \"\"\"Unzip the file to the target_dir.\"\"\"\n    print(\"Unpacking %s ...\" % filepath)\n    tar = zipfile.ZipFile(filepath, 'r')\n    tar.extractall(target_dir)\n    tar.close()\n    if rm_tar:\n        os.remove(filepath)\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# s2t utils binaries.\nfrom .avg_model import main as avg_ckpts_main\nfrom .build_vocab import main as build_vocab_main\nfrom .compute_mean_std import main as compute_mean_std_main\nfrom .compute_wer import main as compute_wer_main\nfrom .format_data import main as format_data_main\nfrom .format_rsl import main as format_rsl_main\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/avg_model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport glob\nimport json\nimport os\n\nimport numpy as np\nimport paddle\n\n\ndef average_checkpoints(dst_model=\"\",\n                        ckpt_dir=\"\",\n                        val_best=True,\n                        num=5,\n                        min_epoch=0,\n                        max_epoch=65536):\n    paddle.set_device('cpu')\n\n    val_scores = []\n    jsons = glob.glob(f'{ckpt_dir}/[!train]*.json')\n    jsons = sorted(jsons, key=os.path.getmtime, reverse=True)\n    for y in jsons:\n        with open(y, 'r') as f:\n            dic_json = json.load(f)\n        loss = dic_json['val_loss']\n        epoch = dic_json['epoch']\n        if epoch >= min_epoch and epoch <= max_epoch:\n            val_scores.append((epoch, loss))\n    assert val_scores, f\"Not find any valid checkpoints: {val_scores}\"\n    val_scores = np.array(val_scores)\n\n    if val_best:\n        sort_idx = np.argsort(val_scores[:, 1])\n        sorted_val_scores = val_scores[sort_idx]\n    else:\n        sorted_val_scores = val_scores\n\n    beat_val_scores = sorted_val_scores[:num, 1]\n    selected_epochs = sorted_val_scores[:num, 0].astype(np.int64)\n    avg_val_score = np.mean(beat_val_scores)\n    print(\"selected val scores = \" + str(beat_val_scores))\n    print(\"selected epochs = \" + str(selected_epochs))\n    print(\"averaged val score = \" + str(avg_val_score))\n\n    path_list = [\n        ckpt_dir + '/{}.pdparams'.format(int(epoch))\n        for epoch in sorted_val_scores[:num, 0]\n    ]\n    print(path_list)\n\n    avg = None\n    num = num\n    assert num == len(path_list)\n    for path in path_list:\n        print(f'Processing {path}')\n        states = paddle.load(path)\n        if avg is None:\n            avg = states\n        else:\n            for k in avg.keys():\n                avg[k] += states[k]\n    # average\n    for k in avg.keys():\n        if avg[k] is not None:\n            avg[k] /= num\n\n    paddle.save(avg, dst_model)\n    print(f'Saving to {dst_model}')\n\n    meta_path = os.path.splitext(dst_model)[0] + '.avg.json'\n    with open(meta_path, 'w') as f:\n        data = json.dumps({\n            \"mode\": 'val_best' if val_best else 'latest',\n            \"avg_ckpt\": dst_model,\n            \"val_loss_mean\": avg_val_score,\n            \"ckpts\": path_list,\n            \"epochs\": selected_epochs.tolist(),\n            \"val_losses\": beat_val_scores.tolist(),\n        })\n        f.write(data + \"\\n\")\n\n\ndef define_argparse():\n    parser = argparse.ArgumentParser(description='average model')\n    parser.add_argument('--dst_model', required=True, help='averaged model')\n    parser.add_argument(\n        '--ckpt_dir', required=True, help='ckpt model dir for average')\n    parser.add_argument(\n        '--val_best', action=\"store_true\", help='averaged model')\n    parser.add_argument(\n        '--num', default=5, type=int, help='nums for averaged model')\n    parser.add_argument(\n        '--min_epoch',\n        default=0,\n        type=int,\n        help='min epoch used for averaging model')\n    parser.add_argument(\n        '--max_epoch',\n        default=65536,  # Big enough\n        type=int,\n        help='max epoch used for averaging model')\n\n    args = parser.parse_args()\n    print(args)\n    return args\n\n\ndef main():\n    args = define_argparse()\n    average_checkpoints(\n        dst_model=args.dst_model,\n        ckpt_dir=args.ckpt_dir,\n        val_best=args.val_best,\n        num=args.num,\n        min_epoch=args.min_epoch,\n        max_epoch=args.max_epoch)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/build_vocab.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Build vocabulary from manifest files.\nEach item in vocabulary file is a character.\n\"\"\"\nimport argparse\nimport functools\nimport os\nimport tempfile\nfrom collections import Counter\n\nimport jsonlines\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.frontend.utility import BLANK\nfrom paddlespeech.s2t.frontend.utility import SOS\nfrom paddlespeech.s2t.frontend.utility import SPACE\nfrom paddlespeech.s2t.frontend.utility import UNK\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef count_manifest(counter, text_feature, manifest_path):\n    manifest_jsons = []\n    with jsonlines.open(manifest_path, 'r') as reader:\n        for json_data in reader:\n            manifest_jsons.append(json_data)\n\n    for line_json in manifest_jsons:\n        if isinstance(line_json['text'], str):\n            tokens = text_feature.tokenize(\n                line_json['text'], replace_space=False)\n\n            counter.update(tokens)\n        else:\n            assert isinstance(line_json['text'], list)\n            for text in line_json['text']:\n                tokens = text_feature.tokenize(text, replace_space=False)\n                counter.update(tokens)\n\n\ndef dump_text_manifest(fileobj, manifest_path, key='text'):\n    manifest_jsons = []\n    with jsonlines.open(manifest_path, 'r') as reader:\n        for json_data in reader:\n            manifest_jsons.append(json_data)\n\n    for line_json in manifest_jsons:\n        if isinstance(line_json[key], str):\n            fileobj.write(line_json[key] + \"\\n\")\n        else:\n            assert isinstance(line_json[key], list)\n            for line in line_json[key]:\n                fileobj.write(line + \"\\n\")\n\n\ndef build_vocab(manifest_paths=\"\",\n                vocab_path=\"examples/librispeech/data/vocab.txt\",\n                unit_type=\"char\",\n                count_threshold=0,\n                text_keys='text',\n                spm_mode=\"unigram\",\n                spm_vocab_size=0,\n                spm_model_prefix=\"\",\n                spm_character_coverage=0.9995):\n    manifest_paths = [manifest_paths] if isinstance(manifest_paths,\n                                                    str) else manifest_paths\n\n    fout = open(vocab_path, 'w', encoding='utf-8')\n    fout.write(BLANK + \"\\n\")  # 0 will be used for \"blank\" in CTC\n    fout.write(UNK + '\\n')  # <unk> must be 1\n\n    if unit_type == 'spm':\n        # tools/spm_train --input=$wave_data/lang_char/input.txt\n        # --vocab_size=${nbpe} --model_type=${bpemode}\n        # --model_prefix=${bpemodel} --input_sentence_size=100000000\n        import sentencepiece as spm\n\n        fp = tempfile.NamedTemporaryFile(mode='w', delete=False)\n        for manifest_path in manifest_paths:\n            _text_keys = [text_keys] if type(\n                text_keys) is not list else text_keys\n            for text_key in _text_keys:\n                dump_text_manifest(fp, manifest_path, key=text_key)\n        fp.close()\n        # train\n        spm.SentencePieceTrainer.Train(\n            input=fp.name,\n            vocab_size=spm_vocab_size,\n            model_type=spm_mode,\n            model_prefix=spm_model_prefix,\n            input_sentence_size=100000000,\n            character_coverage=spm_character_coverage)\n        os.unlink(fp.name)\n\n    # encode\n    text_feature = TextFeaturizer(unit_type, \"\", spm_model_prefix)\n    counter = Counter()\n\n    for manifest_path in manifest_paths:\n        count_manifest(counter, text_feature, manifest_path)\n\n    count_sorted = sorted(counter.items(), key=lambda x: x[1], reverse=True)\n    tokens = []\n    for token, count in count_sorted:\n        if count < count_threshold:\n            break\n        # replace space by `<space>`\n        token = SPACE if token == ' ' else token\n        tokens.append(token)\n\n    tokens = sorted(tokens)\n    for token in tokens:\n        fout.write(token + '\\n')\n\n    fout.write(SOS + \"\\n\")  # <sos/eos>\n    fout.close()\n\n\ndef define_argparse():\n    parser = argparse.ArgumentParser(description=__doc__)\n    add_arg = functools.partial(add_arguments, argparser=parser)\n\n    # yapf: disable\n    add_arg('unit_type', str, \"char\", \"Unit type, e.g. char, word, spm\")\n    add_arg('count_threshold', int, 0,\n            \"Truncation threshold for char/word counts.Default 0, no truncate.\")\n    add_arg('vocab_path', str,\n            'examples/librispeech/data/vocab.txt',\n            \"Filepath to write the vocabulary.\")\n    add_arg('manifest_paths', str,\n            None,\n            \"Filepaths of manifests for building vocabulary. \"\n            \"You can provide multiple manifest files.\",\n            nargs='+',\n            required=True)\n    add_arg('text_keys', str,\n            'text',\n            \"keys of the text in manifest for building vocabulary. \"\n            \"You can provide multiple k.\",\n            nargs='+')\n    # bpe\n    add_arg('spm_vocab_size', int, 0, \"Vocab size for spm.\")\n    add_arg('spm_mode', str, 'unigram', \"spm model type, e.g. unigram, spm, char, word. only need when `unit_type` is spm\")\n    add_arg('spm_model_prefix', str, \"\", \"spm_model_%(spm_mode)_%(count_threshold), spm model prefix, only need when `unit_type` is spm\")\n    add_arg('spm_character_coverage', float, 0.9995, \"character coverage to determine the minimum symbols\")\n    # yapf: disable\n\n    args = parser.parse_args()\n    return args\n\ndef main():\n    args = define_argparse()\n    print_arguments(args, globals())\n    build_vocab(**vars(args))\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/compute_mean_std.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Compute mean and std for feature normalizer, and save to file.\"\"\"\nimport argparse\nimport functools\n\nfrom paddlespeech.s2t.frontend.augmentor.augmentation import AugmentationPipeline\nfrom paddlespeech.s2t.frontend.featurizer.audio_featurizer import AudioFeaturizer\nfrom paddlespeech.s2t.frontend.normalizer import FeatureNormalizer\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef compute_cmvn(manifest_path=\"data/librispeech/manifest.train\",\n                 output_path=\"data/librispeech/mean_std.npz\",\n                 num_samples=2000,\n                 num_workers=0,\n                 spectrum_type=\"linear\",\n                 feat_dim=13,\n                 delta_delta=False,\n                 stride_ms=10,\n                 window_ms=20,\n                 sample_rate=16000,\n                 use_dB_normalization=True,\n                 target_dB=-20):\n\n    augmentation_pipeline = AugmentationPipeline('{}')\n    audio_featurizer = AudioFeaturizer(\n        spectrum_type=spectrum_type,\n        feat_dim=feat_dim,\n        delta_delta=delta_delta,\n        stride_ms=float(stride_ms),\n        window_ms=float(window_ms),\n        n_fft=None,\n        max_freq=None,\n        target_sample_rate=sample_rate,\n        use_dB_normalization=use_dB_normalization,\n        target_dB=target_dB,\n        dither=0.0)\n\n    def augment_and_featurize(audio_segment):\n        augmentation_pipeline.transform_audio(audio_segment)\n        return audio_featurizer.featurize(audio_segment)\n\n    normalizer = FeatureNormalizer(\n        mean_std_filepath=None,\n        manifest_path=manifest_path,\n        featurize_func=augment_and_featurize,\n        num_samples=num_samples,\n        num_workers=num_workers)\n    normalizer.write_to_file(output_path)\n\n\ndef define_argparse():\n    parser = argparse.ArgumentParser(description=__doc__)\n    add_arg = functools.partial(add_arguments, argparser=parser)\n\n    # yapf: disable\n    add_arg('manifest_path', str,\n            'data/librispeech/manifest.train',\n            \"Filepath of manifest to compute normalizer's mean and stddev.\")\n\n    add_arg('output_path', str,\n            'data/librispeech/mean_std.npz',\n            \"Filepath of write mean and stddev to (.npz).\")\n    add_arg('num_samples',  int,    2000,    \"# of samples to for statistics.\")\n    add_arg('num_workers',\n                            default=0,\n                            type=int,\n                            help='num of subprocess workers for processing')\n\n\n    add_arg('spectrum_type', str,\n            'linear',\n            \"Audio feature type. Options: linear, mfcc, fbank.\",\n            choices=['linear', 'mfcc', 'fbank'])\n    add_arg('feat_dim', int, 13, \"Audio feature dim.\")\n    add_arg('delta_delta', bool,  False, \"Audio feature with delta delta.\")\n    add_arg('stride_ms', int, 10,  \"stride length in ms.\")\n    add_arg('window_ms', int, 20,  \"stride length in ms.\")\n    add_arg('sample_rate',  int, 16000,  \"target sample rate.\")\n    add_arg('use_dB_normalization', bool, True, \"do dB normalization.\")\n    add_arg('target_dB',   int, -20,  \"target dB.\")\n    # yapf: disable\n\n    args = parser.parse_args()\n    return args\n\ndef main():\n    args = define_argparse()\n    print_arguments(args, globals())\n    compute_cmvn(**vars(args))\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/compute_wer.py",
    "content": "# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n# flake8: noqa\nimport codecs\nimport re\nimport sys\nimport unicodedata\n\nremove_tag = True\nspacelist = [' ', '\\t', '\\r', '\\n']\npuncts = [\n    '!', ',', '?', '、', '。', '！', '，', '；', '？', '：', '「', '」', '︰', '『', '』',\n    '《', '》'\n]\n\n\ndef characterize(string):\n    res = []\n    i = 0\n    while i < len(string):\n        char = string[i]\n        if char in puncts:\n            i += 1\n            continue\n        cat1 = unicodedata.category(char)\n        #https://unicodebook.readthedocs.io/unicode.html#unicode-categories\n        if cat1 == 'Zs' or cat1 == 'Cn' or char in spacelist:  # space or not assigned\n            i += 1\n            continue\n        if cat1 == 'Lo':  # letter-other\n            res.append(char)\n            i += 1\n        else:\n            # some input looks like: <unk><noise>, we want to separate it to two words.\n            sep = ' '\n            if char == '<': sep = '>'\n            j = i + 1\n            while j < len(string):\n                c = string[j]\n                if ord(c) >= 128 or (c in spacelist) or (c == sep):\n                    break\n                j += 1\n            if j < len(string) and string[j] == '>':\n                j += 1\n            res.append(string[i:j])\n            i = j\n    return res\n\n\ndef stripoff_tags(x):\n    if not x: return ''\n    chars = []\n    i = 0\n    T = len(x)\n    while i < T:\n        if x[i] == '<':\n            while i < T and x[i] != '>':\n                i += 1\n            i += 1\n        else:\n            chars.append(x[i])\n            i += 1\n    return ''.join(chars)\n\n\ndef normalize(sentence, ignore_words, cs, split=None):\n    \"\"\" sentence, ignore_words are both in unicode\n    \"\"\"\n    new_sentence = []\n    for token in sentence:\n        x = token\n        if not cs:\n            x = x.upper()\n        if x in ignore_words:\n            continue\n        if remove_tag:\n            x = stripoff_tags(x)\n        if not x:\n            continue\n        if split and x in split:\n            new_sentence += split[x]\n        else:\n            new_sentence.append(x)\n    return new_sentence\n\n\nclass Calculator:\n    def __init__(self):\n        self.data = {}\n        self.space = []\n        self.cost = {}\n        self.cost['cor'] = 0\n        self.cost['sub'] = 1\n        self.cost['del'] = 1\n        self.cost['ins'] = 1\n\n    def calculate(self, lab, rec):\n        # Initialization\n        lab.insert(0, '')\n        rec.insert(0, '')\n        while len(self.space) < len(lab):\n            self.space.append([])\n        for row in self.space:\n            for element in row:\n                element['dist'] = 0\n                element['error'] = 'non'\n            while len(row) < len(rec):\n                row.append({'dist': 0, 'error': 'non'})\n        for i in range(len(lab)):\n            self.space[i][0]['dist'] = i\n            self.space[i][0]['error'] = 'del'\n        for j in range(len(rec)):\n            self.space[0][j]['dist'] = j\n            self.space[0][j]['error'] = 'ins'\n        self.space[0][0]['error'] = 'non'\n        for token in lab:\n            if token not in self.data and len(token) > 0:\n                self.data[token] = {\n                    'all': 0,\n                    'cor': 0,\n                    'sub': 0,\n                    'ins': 0,\n                    'del': 0\n                }\n        for token in rec:\n            if token not in self.data and len(token) > 0:\n                self.data[token] = {\n                    'all': 0,\n                    'cor': 0,\n                    'sub': 0,\n                    'ins': 0,\n                    'del': 0\n                }\n        # Computing edit distance\n        for i, lab_token in enumerate(lab):\n            for j, rec_token in enumerate(rec):\n                if i == 0 or j == 0:\n                    continue\n                min_dist = sys.maxsize\n                min_error = 'none'\n                dist = self.space[i - 1][j]['dist'] + self.cost['del']\n                error = 'del'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                dist = self.space[i][j - 1]['dist'] + self.cost['ins']\n                error = 'ins'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                if lab_token == rec_token:\n                    dist = self.space[i - 1][j - 1]['dist'] + self.cost['cor']\n                    error = 'cor'\n                else:\n                    dist = self.space[i - 1][j - 1]['dist'] + self.cost['sub']\n                    error = 'sub'\n                if dist < min_dist:\n                    min_dist = dist\n                    min_error = error\n                self.space[i][j]['dist'] = min_dist\n                self.space[i][j]['error'] = min_error\n        # Tracing back\n        result = {\n            'lab': [],\n            'rec': [],\n            'all': 0,\n            'cor': 0,\n            'sub': 0,\n            'ins': 0,\n            'del': 0\n        }\n        i = len(lab) - 1\n        j = len(rec) - 1\n        while True:\n            if self.space[i][j]['error'] == 'cor':  # correct\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['cor'] = self.data[lab[i]]['cor'] + 1\n                    result['all'] = result['all'] + 1\n                    result['cor'] = result['cor'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, rec[j])\n                i = i - 1\n                j = j - 1\n            elif self.space[i][j]['error'] == 'sub':  # substitution\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['sub'] = self.data[lab[i]]['sub'] + 1\n                    result['all'] = result['all'] + 1\n                    result['sub'] = result['sub'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, rec[j])\n                i = i - 1\n                j = j - 1\n            elif self.space[i][j]['error'] == 'del':  # deletion\n                if len(lab[i]) > 0:\n                    self.data[lab[i]]['all'] = self.data[lab[i]]['all'] + 1\n                    self.data[lab[i]]['del'] = self.data[lab[i]]['del'] + 1\n                    result['all'] = result['all'] + 1\n                    result['del'] = result['del'] + 1\n                result['lab'].insert(0, lab[i])\n                result['rec'].insert(0, \"\")\n                i = i - 1\n            elif self.space[i][j]['error'] == 'ins':  # insertion\n                if len(rec[j]) > 0:\n                    self.data[rec[j]]['ins'] = self.data[rec[j]]['ins'] + 1\n                    result['ins'] = result['ins'] + 1\n                result['lab'].insert(0, \"\")\n                result['rec'].insert(0, rec[j])\n                j = j - 1\n            elif self.space[i][j]['error'] == 'non':  # starting point\n                break\n            else:  # shouldn't reach here\n                print(\n                    'this should not happen , i = {i} , j = {j} , error = {error}'.\n                    format(i=i, j=j, error=self.space[i][j]['error']))\n        return result\n\n    def overall(self):\n        result = {'all': 0, 'cor': 0, 'sub': 0, 'ins': 0, 'del': 0}\n        for token in self.data:\n            result['all'] = result['all'] + self.data[token]['all']\n            result['cor'] = result['cor'] + self.data[token]['cor']\n            result['sub'] = result['sub'] + self.data[token]['sub']\n            result['ins'] = result['ins'] + self.data[token]['ins']\n            result['del'] = result['del'] + self.data[token]['del']\n        return result\n\n    def cluster(self, data):\n        result = {'all': 0, 'cor': 0, 'sub': 0, 'ins': 0, 'del': 0}\n        for token in data:\n            if token in self.data:\n                result['all'] = result['all'] + self.data[token]['all']\n                result['cor'] = result['cor'] + self.data[token]['cor']\n                result['sub'] = result['sub'] + self.data[token]['sub']\n                result['ins'] = result['ins'] + self.data[token]['ins']\n                result['del'] = result['del'] + self.data[token]['del']\n        return result\n\n    def keys(self):\n        return list(self.data.keys())\n\n\ndef width(string):\n    return sum(1 + (unicodedata.east_asian_width(c) in \"AFW\") for c in string)\n\n\ndef default_cluster(word):\n    unicode_names = [unicodedata.name(char) for char in word]\n    for i in reversed(range(len(unicode_names))):\n        if unicode_names[i].startswith('DIGIT'):  # 1\n            unicode_names[i] = 'Number'  # 'DIGIT'\n        elif (unicode_names[i].startswith('CJK UNIFIED IDEOGRAPH') or\n              unicode_names[i].startswith('CJK COMPATIBILITY IDEOGRAPH')):\n            # 明 / 郎\n            unicode_names[i] = 'Mandarin'  # 'CJK IDEOGRAPH'\n        elif (unicode_names[i].startswith('LATIN CAPITAL LETTER') or\n              unicode_names[i].startswith('LATIN SMALL LETTER')):\n            # A / a\n            unicode_names[i] = 'English'  # 'LATIN LETTER'\n        elif unicode_names[i].startswith('HIRAGANA LETTER'):  # は こ め\n            unicode_names[i] = 'Japanese'  # 'GANA LETTER'\n        elif (unicode_names[i].startswith('AMPERSAND') or\n              unicode_names[i].startswith('APOSTROPHE') or\n              unicode_names[i].startswith('COMMERCIAL AT') or\n              unicode_names[i].startswith('DEGREE CELSIUS') or\n              unicode_names[i].startswith('EQUALS SIGN') or\n              unicode_names[i].startswith('FULL STOP') or\n              unicode_names[i].startswith('HYPHEN-MINUS') or\n              unicode_names[i].startswith('LOW LINE') or\n              unicode_names[i].startswith('NUMBER SIGN') or\n              unicode_names[i].startswith('PLUS SIGN') or\n              unicode_names[i].startswith('SEMICOLON')):\n            # & / ' / @ / ℃ / = / . / - / _ / # / + / ;\n            del unicode_names[i]\n        else:\n            return 'Other'\n    if len(unicode_names) == 0:\n        return 'Other'\n    if len(unicode_names) == 1:\n        return unicode_names[0]\n    for i in range(len(unicode_names) - 1):\n        if unicode_names[i] != unicode_names[i + 1]:\n            return 'Other'\n    return unicode_names[0]\n\n\ndef usage():\n    print(\n        \"compute-wer.py : compute word error rate (WER) and align recognition results and references.\"\n    )\n    print(\n        \"         usage : python compute-wer.py [--cs={0,1}] [--cluster=foo] [--ig=ignore_file] [--char={0,1}] [--v={0,1}] [--padding-symbol={space,underline}] test.ref test.hyp > test.wer\"\n    )\n\n\ndef main():\n    # python utils/compute-wer.py --char=1 --v=1 ref hyp > rsl.error\n    if len(sys.argv) == 1:\n        usage()\n        sys.exit(0)\n    calculator = Calculator()\n    cluster_file = ''\n    ignore_words = set()\n    tochar = False\n    verbose = 1\n    padding_symbol = ' '\n    case_sensitive = False\n    max_words_per_line = sys.maxsize\n    split = None\n    while len(sys.argv) > 3:\n        a = '--maxw='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):]\n            del sys.argv[1]\n            max_words_per_line = int(b)\n            continue\n        a = '--rt='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            remove_tag = (b == 'true') or (b != '0')\n            continue\n        a = '--cs='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            case_sensitive = (b == 'true') or (b != '0')\n            continue\n        a = '--cluster='\n        if sys.argv[1].startswith(a):\n            cluster_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            continue\n        a = '--splitfile='\n        if sys.argv[1].startswith(a):\n            split_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            split = dict()\n            with codecs.open(split_file, 'r', 'utf-8') as fh:\n                for line in fh:  # line in unicode\n                    words = line.strip().split()\n                    if len(words) >= 2:\n                        split[words[0]] = words[1:]\n            continue\n        a = '--ig='\n        if sys.argv[1].startswith(a):\n            ignore_file = sys.argv[1][len(a):]\n            del sys.argv[1]\n            with codecs.open(ignore_file, 'r', 'utf-8') as fh:\n                for line in fh:  # line in unicode\n                    line = line.strip()\n                    if len(line) > 0:\n                        ignore_words.add(line)\n            continue\n        a = '--char='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            tochar = (b == 'true') or (b != '0')\n            continue\n        a = '--v='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            verbose = 0\n            try:\n                verbose = int(b)\n            except:\n                if b == 'true' or b != '0':\n                    verbose = 1\n            continue\n        a = '--padding-symbol='\n        if sys.argv[1].startswith(a):\n            b = sys.argv[1][len(a):].lower()\n            del sys.argv[1]\n            if b == 'space':\n                padding_symbol = ' '\n            elif b == 'underline':\n                padding_symbol = '_'\n            continue\n        if True or sys.argv[1].startswith('-'):\n            #ignore invalid switch\n            del sys.argv[1]\n            continue\n\n    if not case_sensitive:\n        ig = set([w.upper() for w in ignore_words])\n        ignore_words = ig\n\n    default_clusters = {}\n    default_words = {}\n\n    ref_file = sys.argv[1]\n    hyp_file = sys.argv[2]\n    rec_set = {}\n    if split and not case_sensitive:\n        newsplit = dict()\n        for w in split:\n            words = split[w]\n            for i in range(len(words)):\n                words[i] = words[i].upper()\n            newsplit[w.upper()] = words\n        split = newsplit\n\n    with codecs.open(hyp_file, 'r', 'utf-8') as fh:\n        for line in fh:\n            if tochar:\n                array = characterize(line)\n            else:\n                array = line.strip().split()\n            if len(array) == 0: continue\n            fid = array[0]\n            rec_set[fid] = normalize(array[1:], ignore_words, case_sensitive,\n                                     split)\n\n    # compute error rate on the interaction of reference file and hyp file\n    for line in open(ref_file, 'r', encoding='utf-8'):\n        if tochar:\n            array = characterize(line)\n        else:\n            array = line.rstrip('\\n').split()\n        if len(array) == 0: continue\n        fid = array[0]\n        if fid not in rec_set:\n            continue\n        lab = normalize(array[1:], ignore_words, case_sensitive, split)\n        rec = rec_set[fid]\n        if verbose:\n            print('\\nutt: %s' % fid)\n\n        for word in rec + lab:\n            if word not in default_words:\n                default_cluster_name = default_cluster(word)\n                if default_cluster_name not in default_clusters:\n                    default_clusters[default_cluster_name] = {}\n                if word not in default_clusters[default_cluster_name]:\n                    default_clusters[default_cluster_name][word] = 1\n                default_words[word] = default_cluster_name\n\n        result = calculator.calculate(lab, rec)\n        if verbose:\n            if result['all'] != 0:\n                wer = float(result['ins'] + result['sub'] + result[\n                    'del']) * 100.0 / result['all']\n            else:\n                wer = 0.0\n            print('WER: %4.2f %%' % wer, end=' ')\n            print('N=%d C=%d S=%d D=%d I=%d' %\n                  (result['all'], result['cor'], result['sub'], result['del'],\n                   result['ins']))\n            space = {}\n            space['lab'] = []\n            space['rec'] = []\n            for idx in range(len(result['lab'])):\n                len_lab = width(result['lab'][idx])\n                len_rec = width(result['rec'][idx])\n                length = max(len_lab, len_rec)\n                space['lab'].append(length - len_lab)\n                space['rec'].append(length - len_rec)\n            upper_lab = len(result['lab'])\n            upper_rec = len(result['rec'])\n            lab1, rec1 = 0, 0\n            while lab1 < upper_lab or rec1 < upper_rec:\n                if verbose > 1:\n                    print('lab(%s):' % fid.encode('utf-8'), end=' ')\n                else:\n                    print('lab:', end=' ')\n                lab2 = min(upper_lab, lab1 + max_words_per_line)\n                for idx in range(lab1, lab2):\n                    token = result['lab'][idx]\n                    print('{token}'.format(token=token), end='')\n                    for n in range(space['lab'][idx]):\n                        print(padding_symbol, end='')\n                    print(' ', end='')\n                print()\n                if verbose > 1:\n                    print('rec(%s):' % fid.encode('utf-8'), end=' ')\n                else:\n                    print('rec:', end=' ')\n                rec2 = min(upper_rec, rec1 + max_words_per_line)\n                for idx in range(rec1, rec2):\n                    token = result['rec'][idx]\n                    print('{token}'.format(token=token), end='')\n                    for n in range(space['rec'][idx]):\n                        print(padding_symbol, end='')\n                    print(' ', end='')\n                print('\\n', end='\\n')\n                lab1 = lab2\n                rec1 = rec2\n\n    if verbose:\n        print(\n            '==========================================================================='\n        )\n        print()\n\n    result = calculator.overall()\n    if result['all'] != 0:\n        wer = float(result['ins'] + result['sub'] + result[\n            'del']) * 100.0 / result['all']\n    else:\n        wer = 0.0\n    print('Overall -> %4.2f %%' % wer, end=' ')\n    print('N=%d C=%d S=%d D=%d I=%d' %\n          (result['all'], result['cor'], result['sub'], result['del'],\n           result['ins']))\n    if not verbose:\n        print()\n\n    if verbose:\n        for cluster_id in default_clusters:\n            result = calculator.cluster(\n                [k for k in default_clusters[cluster_id]])\n            if result['all'] != 0:\n                wer = float(result['ins'] + result['sub'] + result[\n                    'del']) * 100.0 / result['all']\n            else:\n                wer = 0.0\n            print('%s -> %4.2f %%' % (cluster_id, wer), end=' ')\n            print('N=%d C=%d S=%d D=%d I=%d' %\n                  (result['all'], result['cor'], result['sub'], result['del'],\n                   result['ins']))\n        if len(cluster_file) > 0:  # compute separated WERs for word clusters\n            cluster_id = ''\n            cluster = []\n            for line in open(cluster_file, 'r', encoding='utf-8'):\n                for token in line.decode('utf-8').rstrip('\\n').split():\n                    # end of cluster reached, like </Keyword>\n                    if token[0:2] == '</' and token[len(token)-1] == '>' and \\\n                       token.lstrip('</').rstrip('>') == cluster_id :\n                        result = calculator.cluster(cluster)\n                        if result['all'] != 0:\n                            wer = float(result['ins'] + result['sub'] + result[\n                                'del']) * 100.0 / result['all']\n                        else:\n                            wer = 0.0\n                        print('%s -> %4.2f %%' % (cluster_id, wer), end=' ')\n                        print('N=%d C=%d S=%d D=%d I=%d' %\n                              (result['all'], result['cor'], result['sub'],\n                               result['del'], result['ins']))\n                        cluster_id = ''\n                        cluster = []\n                    # begin of cluster reached, like <Keyword>\n                    elif token[0] == '<' and token[len(token)-1] == '>' and \\\n                         cluster_id == '' :\n                        cluster_id = token.lstrip('<').rstrip('>')\n                        cluster = []\n                    # general terms, like WEATHER / CAR / ...\n                    else:\n                        cluster.append(token)\n        print()\n        print(\n            '==========================================================================='\n        )\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/format_data.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"format manifest with more metadata.\"\"\"\nimport argparse\nimport functools\nimport json\n\nimport jsonlines\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.frontend.utility import load_cmvn\nfrom paddlespeech.s2t.io.utility import feat_type\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef define_argparse():\n    parser = argparse.ArgumentParser(description=__doc__)\n    add_arg = functools.partial(add_arguments, argparser=parser)\n    # yapf: disable\n    add_arg('manifest_paths',   str,\n            None,\n            \"Filepaths of manifests for building vocabulary. \"\n            \"You can provide multiple manifest files.\",\n            nargs='+',\n            required=True)\n    add_arg('output_path',  str, None, \"filepath of formated manifest.\", required=True)\n    add_arg('cmvn_path',       str,\n            'examples/librispeech/data/mean_std.json',\n            \"Filepath of cmvn.\")\n    add_arg('unit_type', str, \"char\", \"Unit type, e.g. char, word, spm\")\n    add_arg('vocab_path',       str,\n            'examples/librispeech/data/vocab.txt',\n            \"Filepath of the vocabulary.\")\n    # bpe\n    add_arg('spm_model_prefix', str, None,\n        \"spm model prefix, spm_model_%(bpe_mode)_%(count_threshold), only need when `unit_type` is spm\")\n\n    # yapf: disable\n    args = parser.parse_args()\n    return args\n\ndef format_data(\n    manifest_paths=\"\",\n    output_path=\"\",\n    cmvn_path=\"examples/librispeech/data/mean_std.json\",\n    unit_type=\"char\",\n    vocab_path=\"examples/librispeech/data/vocab.txt\",\n    spm_model_prefix=\"\"):\n    manifest_paths = [manifest_paths] if isinstance(manifest_paths, str) else manifest_paths\n\n    fout = open(output_path, 'w', encoding='utf-8')\n\n    # get feat dim\n    filetype = cmvn_path.split(\".\")[-1]\n    mean, istd = load_cmvn(cmvn_path, filetype=filetype)\n    feat_dim = mean.shape[0] #(D)\n    print(f\"Feature dim: {feat_dim}\")\n\n    text_feature = TextFeaturizer(unit_type, vocab_path, spm_model_prefix)\n    vocab_size = text_feature.vocab_size\n    print(f\"Vocab size: {vocab_size}\")\n\n    # josnline like this\n    # {\n    #   \"input\": [{\"name\": \"input1\", \"shape\": (100, 83), \"feat\": \"xxx.ark:123\"}],\n    #   \"output\": [{\"name\":\"target1\", \"shape\": (40, 5002), \"text\": \"a b c de\"}],\n    #   \"utt2spk\": \"111-2222\",\n    #   \"utt\": \"111-2222-333\"\n    # }\n    count = 0\n    for manifest_path in manifest_paths:\n        with jsonlines.open(str(manifest_path), 'r') as reader:\n            manifest_jsons = list(reader)\n\n        for line_json in manifest_jsons:\n            output_json = {\n                \"input\": [],\n                \"output\": [],\n                'utt': line_json['utt'],\n                'utt2spk': line_json.get('utt2spk', 'global'),\n            }\n\n            # output\n            line = line_json['text']\n            if isinstance(line, str):\n                # only one target\n                tokens = text_feature.tokenize(line)\n                tokenids = text_feature.featurize(line)\n                output_json['output'].append({\n                    'name': 'target1',\n                    'shape': (len(tokenids), vocab_size),\n                    'text': line,\n                    'token': ' '.join(tokens),\n                    'tokenid': ' '.join(map(str, tokenids)),\n                })\n            else:\n                # isinstance(line, list), multi target in one vocab\n                for i, item in enumerate(line, 1):\n                    tokens = text_feature.tokenize(item)\n                    tokenids = text_feature.featurize(item)\n                    output_json['output'].append({\n                        'name': f'target{i}',\n                        'shape': (len(tokenids), vocab_size),\n                        'text': item,\n                        'token': ' '.join(tokens),\n                        'tokenid': ' '.join(map(str, tokenids)),\n                    })\n\n            # input\n            line = line_json['feat']\n            if isinstance(line, str):\n                # only one input\n                feat_shape = line_json['feat_shape']\n                assert isinstance(feat_shape, (list, tuple)), type(feat_shape)\n                filetype = feat_type(line)\n                if filetype == 'sound':\n                    feat_shape.append(feat_dim)\n                else: # kaldi\n                    raise NotImplementedError('no support kaldi feat now!')\n\n                output_json['input'].append({\n                    \"name\": \"input1\",\n                    \"shape\": feat_shape,\n                    \"feat\": line,\n                    \"filetype\": filetype,\n                })\n            else:\n                # isinstance(line, list), multi input \n                raise NotImplementedError(\"not support multi input now!\")\n\n            fout.write(json.dumps(output_json) + '\\n')\n            count += 1\n\n    print(f\"{manifest_paths} Examples number: {count}\")\n    fout.close()\n\ndef main():\n    args = define_argparse()\n    print_arguments(args, globals())\n    format_data(**vars(args))\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/dataset/s2t/format_rsl.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nformat ref/hyp file for `utt text` format to compute CER/WER/MER.\n\nnorm:\nBAC009S0764W0196 明确了发展目标和重点任务\nBAC009S0764W0186 实现我国房地产市场的平稳运行\n\n\nsclite:\n加大对结构机械化环境和收集谈控机制力度(BAC009S0906W0240.wav)\n河南省新乡市丰秋县刘光镇政府东五零左右(BAC009S0770W0441.wav)\n\"\"\"\nimport argparse\n\nimport jsonlines\n\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef transform_hyp(origin, trans, trans_sclite):\n    \"\"\"\n    Args:\n        origin: The input json file which contains the model output\n        trans: The output file for caculate CER/WER\n        trans_sclite: The output file for caculate CER/WER using sclite\n    \"\"\"\n    input_dict = {}\n\n    with open(origin, \"r+\", encoding=\"utf8\") as f:\n        for item in jsonlines.Reader(f):\n            input_dict[item[\"utt\"]] = item[\"hyps\"][0]\n\n    if trans:\n        with open(trans, \"w+\", encoding=\"utf8\") as f:\n            for key in input_dict.keys():\n                f.write(key + \" \" + input_dict[key] + \"\\n\")\n        print(f\"transform_hyp output: {trans}\")\n\n    if trans_sclite:\n        with open(trans_sclite, \"w+\") as f:\n            for key in input_dict.keys():\n                line = input_dict[key] + \"(\" + key + \".wav\" + \")\" + \"\\n\"\n                f.write(line)\n        print(f\"transform_hyp output: {trans_sclite}\")\n\n\ndef transform_ref(origin, trans, trans_sclite):\n    \"\"\"\n    Args:\n        origin: The input json file which contains the model output\n        trans: The output file for caculate CER/WER\n        trans_sclite: The output file for caculate CER/WER using sclite\n    \"\"\"\n    input_dict = {}\n\n    with open(origin, \"r\", encoding=\"utf8\") as f:\n        for item in jsonlines.Reader(f):\n            input_dict[item[\"utt\"]] = item[\"text\"]\n\n    if trans:\n        with open(trans, \"w\", encoding=\"utf8\") as f:\n            for key in input_dict.keys():\n                f.write(key + \" \" + input_dict[key] + \"\\n\")\n        print(f\"transform_hyp output: {trans}\")\n\n    if trans_sclite:\n        with open(trans_sclite, \"w\") as f:\n            for key in input_dict.keys():\n                line = input_dict[key] + \"(\" + key + \".wav\" + \")\" + \"\\n\"\n                f.write(line)\n        print(f\"transform_hyp output: {trans_sclite}\")\n\n\ndef define_argparse():\n    parser = argparse.ArgumentParser(\n        prog='format ref/hyp file for compute CER/WER', add_help=True)\n    parser.add_argument(\n        '--origin_hyp', type=str, default=\"\", help='origin hyp file')\n    parser.add_argument(\n        '--trans_hyp',\n        type=str,\n        default=\"\",\n        help='hyp file for caculating CER/WER')\n    parser.add_argument(\n        '--trans_hyp_sclite',\n        type=str,\n        default=\"\",\n        help='hyp file for caculating CER/WER by sclite')\n\n    parser.add_argument(\n        '--origin_ref', type=str, default=\"\", help='origin ref file')\n    parser.add_argument(\n        '--trans_ref',\n        type=str,\n        default=\"\",\n        help='ref file for caculating CER/WER')\n    parser.add_argument(\n        '--trans_ref_sclite',\n        type=str,\n        default=\"\",\n        help='ref file for caculating CER/WER by sclite')\n    parser_args = parser.parse_args()\n    return parser_args\n\n\ndef format_result(origin_hyp=\"\",\n                  trans_hyp=\"\",\n                  trans_hyp_sclite=\"\",\n                  origin_ref=\"\",\n                  trans_ref=\"\",\n                  trans_ref_sclite=\"\"):\n\n    if origin_hyp:\n        transform_hyp(\n            origin=origin_hyp, trans=trans_hyp, trans_sclite=trans_hyp_sclite)\n\n    if origin_ref:\n        transform_ref(\n            origin=origin_ref, trans=trans_ref, trans_sclite=trans_ref_sclite)\n\n\ndef main():\n    args = define_argparse()\n    print_arguments(args, globals())\n\n    format_result(**vars(args))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/kws/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .models.mdtc import MDTC\n"
  },
  {
    "path": "paddlespeech/kws/exps/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/collate.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\n\nimport paddle\n\n\ndef collate_features(batch):\n    # (key, feat, label)\n    collate_start = time.time()\n    keys = []\n    feats = []\n    labels = []\n    lengths = []\n    for sample in batch:\n        keys.append(sample[0])\n        feats.append(sample[1])\n        labels.append(sample[2])\n        lengths.append(sample[1].shape[0])\n\n    max_length = max(lengths)\n    for i in range(len(feats)):\n        feats[i] = paddle.nn.functional.pad(\n            feats[i], [0, max_length - feats[i].shape[0], 0, 0],\n            data_format='NLC')\n\n    return keys, paddle.stack(feats), paddle.to_tensor(\n        labels), paddle.to_tensor(lengths)\n"
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/compute_det.py",
    "content": "# Copyright (c) 2021 Binbin Zhang(binbzha@qq.com)\n#               2022 Shaoqing Yu(954793264@qq.com)\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wekws(https://github.com/wenet-e2e/wekws)\nimport os\n\nimport paddle\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\n\ndef load_label_and_score(keyword_index: int,\n                         ds: paddle.io.Dataset,\n                         score_file: os.PathLike):\n    score_table = {}  # {utt_id: scores_over_frames}\n    with open(score_file, 'r', encoding='utf8') as fin:\n        for line in fin:\n            arr = line.strip().split()\n            key = arr[0]\n            current_keyword = arr[1]\n            str_list = arr[2:]\n            if int(current_keyword) == keyword_index:\n                scores = list(map(float, str_list))\n                if key not in score_table:\n                    score_table.update({key: scores})\n    keyword_table = {}  # scores of keyword utt_id\n    filler_table = {}  # scores of non-keyword utt_id\n    filler_duration = 0.0\n\n    for key, index, duration in zip(ds.keys, ds.labels, ds.durations):\n        assert key in score_table\n        if index == keyword_index:\n            keyword_table[key] = score_table[key]\n        else:\n            filler_table[key] = score_table[key]\n            filler_duration += duration\n\n    return keyword_table, filler_table, filler_duration\n\n\nif __name__ == '__main__':\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--keyword_index', type=int, default=0, help='keyword index')\n    parser.add_argument(\n        '--step',\n        type=float,\n        default=0.01,\n        help='threshold step of trigger score')\n    parser.add_argument(\n        '--window_shift',\n        type=int,\n        default=50,\n        help='window_shift is used to skip the frames after triggered')\n    parser.add_argument(\n        \"--score_file\",\n        type=str,\n        required=True,\n        help='output file of trigger scores')\n    parser.add_argument(\n        '--stats_file',\n        type=str,\n        default='./stats.0.txt',\n        help='output file of detection error tradeoff')\n    args = parser.parse_args()\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    # Dataset\n    ds_class = dynamic_import(config['dataset'])\n    test_ds = ds_class(\n        data_dir=config['data_dir'],\n        mode='test',\n        feat_type=config['feat_type'],\n        sample_rate=config['sample_rate'],\n        frame_shift=config['frame_shift'],\n        frame_length=config['frame_length'],\n        n_mels=config['n_mels'], )\n\n    keyword_table, filler_table, filler_duration = load_label_and_score(\n        args.keyword_index, test_ds, args.score_file)\n    print('Filler total duration Hours: {}'.format(filler_duration / 3600.0))\n    pbar = tqdm(total=int(1.0 / args.step))\n    with open(args.stats_file, 'w', encoding='utf8') as fout:\n        keyword_index = args.keyword_index\n        threshold = 0.0\n        while threshold <= 1.0:\n            num_false_reject = 0\n            # transverse the all keyword_table\n            for key, score_list in keyword_table.items():\n                # computer positive test sample, use the max score of list.\n                score = max(score_list)\n                if float(score) < threshold:\n                    num_false_reject += 1\n            num_false_alarm = 0\n            # transverse the all filler_table\n            for key, score_list in filler_table.items():\n                i = 0\n                while i < len(score_list):\n                    if score_list[i] >= threshold:\n                        num_false_alarm += 1\n                        i += args.window_shift\n                    else:\n                        i += 1\n            if len(keyword_table) != 0:\n                false_reject_rate = num_false_reject / len(keyword_table)\n            num_false_alarm = max(num_false_alarm, 1e-6)\n            if filler_duration != 0:\n                false_alarm_per_hour = num_false_alarm / \\\n                    (filler_duration / 3600.0)\n            fout.write('{:.6f} {:.6f} {:.6f}\\n'.format(\n                threshold, false_alarm_per_hour, false_reject_rate))\n            threshold += args.step\n            pbar.update(1)\n\n    pbar.close()\n    print('DET saved to: {}'.format(args.stats_file))\n"
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/plot_det_curve.py",
    "content": "# Copyright (c) 2021 Binbin Zhang(binbzha@qq.com)\n#                    Menglong Xu\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wekws(https://github.com/wenet-e2e/wekws)\nimport argparse\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# yapf: disable\nparser = argparse.ArgumentParser(__doc__)\nparser.add_argument('--keyword_label', type=str, required=True, help='keyword string shown on image')\nparser.add_argument('--stats_file', type=str, required=True, help='output file of detection error tradeoff')\nparser.add_argument('--img_file', type=str, default='./det.png', help='output det image')\nargs = parser.parse_args()\n# yapf: enable\n\n\ndef load_stats_file(stats_file):\n    values = []\n    with open(stats_file, 'r', encoding='utf8') as fin:\n        for line in fin:\n            arr = line.strip().split()\n            threshold, fa_per_hour, frr = arr\n            values.append([float(fa_per_hour), float(frr) * 100])\n    values.reverse()\n    return np.array(values)\n\n\ndef plot_det_curve(keywords, stats_file, figure_file, xlim, x_step, ylim,\n                   y_step):\n    plt.figure(dpi=200)\n    plt.rcParams['xtick.direction'] = 'in'\n    plt.rcParams['ytick.direction'] = 'in'\n    plt.rcParams['font.size'] = 12\n\n    for index, keyword in enumerate(keywords):\n        values = load_stats_file(stats_file)\n        plt.plot(values[:, 0], values[:, 1], label=keyword)\n\n    plt.xlim([0, xlim])\n    plt.ylim([0, ylim])\n    plt.xticks(range(0, xlim + x_step, x_step))\n    plt.yticks(range(0, ylim + y_step, y_step))\n    plt.xlabel('False Alarm Per Hour')\n    plt.ylabel('False Rejection Rate (\\\\%)')\n    plt.grid(linestyle='--')\n    plt.legend(loc='best', fontsize=16)\n    plt.savefig(figure_file)\n\n\nif __name__ == '__main__':\n    img_file = os.path.abspath(args.img_file)\n    stats_file = os.path.abspath(args.stats_file)\n    plot_det_curve([args.keyword_label], stats_file, img_file, 10, 2, 10, 2)\n\n    print('DET curve image saved to: {}'.format(img_file))\n"
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/score.py",
    "content": "# Copyright (c) 2021 Binbin Zhang(binbzha@qq.com)\n#               2022 Shaoqing Yu(954793264@qq.com)\n#               2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wekws(https://github.com/wenet-e2e/wekws)\nimport paddle\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.kws.exps.mdtc.collate import collate_features\nfrom paddlespeech.kws.models.mdtc import KWSModel\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\nif __name__ == '__main__':\n    parser = default_argument_parser()\n    parser.add_argument(\n        \"--ckpt\",\n        type=str,\n        required=True,\n        help='model checkpoint for evaluation.')\n    parser.add_argument(\n        \"--score_file\",\n        type=str,\n        default='./scores.txt',\n        help='output file of trigger scores')\n    args = parser.parse_args()\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    # Dataset\n    ds_class = dynamic_import(config['dataset'])\n    test_ds = ds_class(\n        data_dir=config['data_dir'],\n        mode='test',\n        feat_type=config['feat_type'],\n        sample_rate=config['sample_rate'],\n        frame_shift=config['frame_shift'],\n        frame_length=config['frame_length'],\n        n_mels=config['n_mels'], )\n    test_sampler = paddle.io.BatchSampler(\n        test_ds, batch_size=config['batch_size'], drop_last=False)\n    test_loader = paddle.io.DataLoader(\n        test_ds,\n        batch_sampler=test_sampler,\n        num_workers=config['num_workers'],\n        return_list=True,\n        use_buffer_reader=True,\n        collate_fn=collate_features, )\n\n    # Model\n    backbone_class = dynamic_import(config['backbone'])\n    backbone = backbone_class(\n        stack_num=config['stack_num'],\n        stack_size=config['stack_size'],\n        in_channels=config['in_channels'],\n        res_channels=config['res_channels'],\n        kernel_size=config['kernel_size'], )\n    model = KWSModel(backbone=backbone, num_keywords=config['num_keywords'])\n    model.set_state_dict(paddle.load(args.ckpt))\n    model.eval()\n\n    with paddle.no_grad(), open(args.score_file, 'w', encoding='utf8') as f:\n        for batch_idx, batch in enumerate(\n                tqdm(test_loader, total=len(test_loader))):\n            keys, feats, labels, lengths = batch\n            logits = model(feats)\n            num_keywords = logits.shape[2]\n            for i in range(len(keys)):\n                key = keys[i]\n                score = logits[i][:lengths[i]]\n                for keyword_i in range(num_keywords):\n                    keyword_scores = score[:, keyword_i]\n                    score_frames = ' '.join(\n                        ['{:.6f}'.format(x) for x in keyword_scores.tolist()])\n                    f.write('{} {} {}\\n'.format(key, keyword_i, score_frames))\n\n    print('Result saved to: {}'.format(args.score_file))\n"
  },
  {
    "path": "paddlespeech/kws/exps/mdtc/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport paddle\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.utils import logger\nfrom paddlespeech.audio.utils import Timer\nfrom paddlespeech.kws.exps.mdtc.collate import collate_features\nfrom paddlespeech.kws.models.loss import max_pooling_loss\nfrom paddlespeech.kws.models.mdtc import KWSModel\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\nif __name__ == '__main__':\n    parser = default_argument_parser()\n    args = parser.parse_args()\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    nranks = paddle.distributed.get_world_size()\n    if paddle.distributed.get_world_size() > 1:\n        paddle.distributed.init_parallel_env()\n    local_rank = paddle.distributed.get_rank()\n\n    # Dataset\n    ds_class = dynamic_import(config['dataset'])\n    train_ds = ds_class(\n        data_dir=config['data_dir'],\n        mode='train',\n        feat_type=config['feat_type'],\n        sample_rate=config['sample_rate'],\n        frame_shift=config['frame_shift'],\n        frame_length=config['frame_length'],\n        n_mels=config['n_mels'], )\n    dev_ds = ds_class(\n        data_dir=config['data_dir'],\n        mode='dev',\n        feat_type=config['feat_type'],\n        sample_rate=config['sample_rate'],\n        frame_shift=config['frame_shift'],\n        frame_length=config['frame_length'],\n        n_mels=config['n_mels'], )\n\n    train_sampler = paddle.io.DistributedBatchSampler(\n        train_ds,\n        batch_size=config['batch_size'],\n        shuffle=True,\n        drop_last=False)\n    train_loader = paddle.io.DataLoader(\n        train_ds,\n        batch_sampler=train_sampler,\n        num_workers=config['num_workers'],\n        return_list=True,\n        use_buffer_reader=True,\n        collate_fn=collate_features, )\n\n    # Model\n    backbone_class = dynamic_import(config['backbone'])\n    backbone = backbone_class(\n        stack_num=config['stack_num'],\n        stack_size=config['stack_size'],\n        in_channels=config['in_channels'],\n        res_channels=config['res_channels'],\n        kernel_size=config['kernel_size'], )\n    model = KWSModel(backbone=backbone, num_keywords=config['num_keywords'])\n    model = paddle.DataParallel(model)\n    clip = paddle.nn.ClipGradByGlobalNorm(config['grad_clip'])\n    optimizer = paddle.optimizer.Adam(\n        learning_rate=config['learning_rate'],\n        weight_decay=config['weight_decay'],\n        parameters=model.parameters(),\n        grad_clip=clip)\n    criterion = max_pooling_loss\n\n    steps_per_epoch = len(train_sampler)\n    timer = Timer(steps_per_epoch * config['epochs'])\n    timer.start()\n\n    for epoch in range(1, config['epochs'] + 1):\n        model.train()\n\n        avg_loss = 0\n        num_corrects = 0\n        num_samples = 0\n        for batch_idx, batch in enumerate(train_loader):\n            keys, feats, labels, lengths = batch\n            logits = model(feats)\n            loss, corrects, acc = criterion(logits, labels, lengths)\n            loss.backward()\n            optimizer.step()\n            if isinstance(optimizer._learning_rate,\n                          paddle.optimizer.lr.LRScheduler):\n                optimizer._learning_rate.step()\n            optimizer.clear_grad()\n\n            # Calculate loss\n            avg_loss += float(loss)\n\n            # Calculate metrics\n            num_corrects += corrects\n            num_samples += feats.shape[0]\n\n            timer.count()\n\n            if (batch_idx + 1) % config['log_freq'] == 0 and local_rank == 0:\n                lr = optimizer.get_lr()\n                avg_loss /= config['log_freq']\n                avg_acc = num_corrects / num_samples\n\n                print_msg = 'Epoch={}/{}, Step={}/{}'.format(\n                    epoch, config['epochs'], batch_idx + 1, steps_per_epoch)\n                print_msg += ' loss={:.4f}'.format(avg_loss)\n                print_msg += ' acc={:.4f}'.format(avg_acc)\n                print_msg += ' lr={:.6f} step/sec={:.2f} | ETA {}'.format(\n                    lr, timer.timing, timer.eta)\n                logger.train(print_msg)\n\n                avg_loss = 0\n                num_corrects = 0\n                num_samples = 0\n\n        if epoch % config[\n                'save_freq'] == 0 and batch_idx + 1 == steps_per_epoch and local_rank == 0:\n            dev_sampler = paddle.io.BatchSampler(\n                dev_ds,\n                batch_size=config['batch_size'],\n                shuffle=False,\n                drop_last=False)\n            dev_loader = paddle.io.DataLoader(\n                dev_ds,\n                batch_sampler=dev_sampler,\n                num_workers=config['num_workers'],\n                return_list=True,\n                use_buffer_reader=True,\n                collate_fn=collate_features, )\n\n            model.eval()\n            num_corrects = 0\n            num_samples = 0\n            with logger.processing('Evaluation on validation dataset'):\n                for batch_idx, batch in enumerate(dev_loader):\n                    keys, feats, labels, lengths = batch\n                    logits = model(feats)\n                    loss, corrects, acc = criterion(logits, labels, lengths)\n                    num_corrects += corrects\n                    num_samples += feats.shape[0]\n\n            eval_acc = num_corrects / num_samples\n            print_msg = '[Evaluation result]'\n            print_msg += ' dev_acc={:.4f}'.format(eval_acc)\n\n            logger.eval(print_msg)\n\n            # Save model\n            save_dir = os.path.join(config['checkpoint_dir'],\n                                    'epoch_{}'.format(epoch))\n            logger.info('Saving model checkpoint to {}'.format(save_dir))\n            paddle.save(model.state_dict(),\n                        os.path.join(save_dir, 'model.pdparams'))\n            paddle.save(optimizer.state_dict(),\n                        os.path.join(save_dir, 'model.pdopt'))\n"
  },
  {
    "path": "paddlespeech/kws/models/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .mdtc import KWSModel\nfrom .mdtc import MDTC\n"
  },
  {
    "path": "paddlespeech/kws/models/loss.py",
    "content": "# Copyright (c) 2021 Binbin Zhang\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wekws(https://github.com/wenet-e2e/wekws)\nimport paddle\n\n\ndef padding_mask(lengths: paddle.Tensor) -> paddle.Tensor:\n    batch_size = lengths.shape[0]\n    max_len = int(lengths.max().item())\n    seq = paddle.arange(max_len, dtype=paddle.int64)\n    seq = seq.expand((batch_size, max_len))\n    return seq >= lengths.unsqueeze(1)\n\n\ndef fill_mask_elements(condition: paddle.Tensor, value: float,\n                       x: paddle.Tensor) -> paddle.Tensor:\n    assert condition.shape == x.shape\n    values = paddle.ones_like(x, dtype=x.dtype) * value\n    return paddle.where(condition, values, x)\n\n\ndef max_pooling_loss(logits: paddle.Tensor,\n                     target: paddle.Tensor,\n                     lengths: paddle.Tensor,\n                     min_duration: int=0):\n\n    mask = padding_mask(lengths)\n    num_utts = logits.shape[0]\n    num_keywords = logits.shape[2]\n\n    loss = 0.0\n    for i in range(num_utts):\n        for j in range(num_keywords):\n            # Add entropy loss CE = -(t * log(p) + (1 - t) * log(1 - p))\n            if target[i] == j:\n                # For the keyword, do max-polling\n                prob = logits[i, :, j]\n                m = mask[i]\n                if min_duration > 0:\n                    m[:min_duration] = True\n                prob = fill_mask_elements(m, 0.0, prob)\n                prob = paddle.clip(prob, 1e-8, 1.0)\n                max_prob = prob.max()\n                loss += -paddle.log(max_prob)\n            else:\n                # For other keywords or filler, do min-polling\n                prob = 1 - logits[i, :, j]\n                prob = fill_mask_elements(mask[i], 1.0, prob)\n                prob = paddle.clip(prob, 1e-8, 1.0)\n                min_prob = prob.min()\n                loss += -paddle.log(min_prob)\n    loss = loss / num_utts\n\n    # Compute accuracy of current batch\n    mask = mask.unsqueeze(-1)\n    logits = fill_mask_elements(mask, 0.0, logits)\n    max_logits = logits.max(1)\n    num_correct = 0\n    for i in range(num_utts):\n        max_p = max_logits[i].max(0).item()\n        idx = max_logits[i].argmax(0).item()\n        # Predict correct as the i'th keyword\n        if max_p > 0.5 and idx == target[i].item():\n            num_correct += 1\n        # Predict correct as the filler, filler id < 0\n        if max_p < 0.5 and target[i].item() < 0:\n            num_correct += 1\n    acc = num_correct / num_utts\n    # acc = 0.0\n    return loss, num_correct, acc\n"
  },
  {
    "path": "paddlespeech/kws/models/mdtc.py",
    "content": "# Copyright (c) 2021 Jingyong Hou (houjingyong@gmail.com)\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wekws(https://github.com/wenet-e2e/wekws)\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\n\nclass DSDilatedConv1d(nn.Layer):\n    def __init__(\n            self,\n            in_channels: int,\n            out_channels: int,\n            kernel_size: int,\n            dilation: int=1,\n            stride: int=1,\n            bias: bool=True, ):\n        super(DSDilatedConv1d, self).__init__()\n        self.receptive_fields = dilation * (kernel_size - 1)\n        self.conv = nn.Conv1D(\n            in_channels,\n            in_channels,\n            kernel_size,\n            padding=0,\n            dilation=dilation,\n            stride=stride,\n            groups=in_channels,\n            bias_attr=bias, )\n        self.bn = nn.BatchNorm1D(in_channels)\n        self.pointwise = nn.Conv1D(\n            in_channels,\n            out_channels,\n            kernel_size=1,\n            padding=0,\n            dilation=1,\n            bias_attr=bias)\n\n    def forward(self, inputs: paddle.Tensor):\n        outputs = self.conv(inputs)\n        outputs = self.bn(outputs)\n        outputs = self.pointwise(outputs)\n        return outputs\n\n\nclass TCNBlock(nn.Layer):\n    def __init__(\n            self,\n            in_channels: int,\n            res_channels: int,\n            kernel_size: int,\n            dilation: int,\n            causal: bool, ):\n        super(TCNBlock, self).__init__()\n        self.in_channels = in_channels\n        self.res_channels = res_channels\n        self.kernel_size = kernel_size\n        self.dilation = dilation\n        self.causal = causal\n        self.receptive_fields = dilation * (kernel_size - 1)\n        self.half_receptive_fields = self.receptive_fields // 2\n        self.conv1 = DSDilatedConv1d(\n            in_channels=in_channels,\n            out_channels=res_channels,\n            kernel_size=kernel_size,\n            dilation=dilation, )\n        self.bn1 = nn.BatchNorm1D(res_channels)\n        self.relu1 = nn.ReLU()\n\n        self.conv2 = nn.Conv1D(\n            in_channels=res_channels, out_channels=res_channels, kernel_size=1)\n        self.bn2 = nn.BatchNorm1D(res_channels)\n        self.relu2 = nn.ReLU()\n\n    def forward(self, inputs: paddle.Tensor):\n        outputs = self.relu1(self.bn1(self.conv1(inputs)))\n        outputs = self.bn2(self.conv2(outputs))\n        if self.causal:\n            inputs = inputs[:, :, self.receptive_fields:]\n        else:\n            inputs = inputs[:, :, self.half_receptive_fields:\n                            -self.half_receptive_fields]\n        if self.in_channels == self.res_channels:\n            res_out = self.relu2(outputs + inputs)\n        else:\n            res_out = self.relu2(outputs)\n        return res_out\n\n\nclass TCNStack(nn.Layer):\n    def __init__(\n            self,\n            in_channels: int,\n            stack_num: int,\n            stack_size: int,\n            res_channels: int,\n            kernel_size: int,\n            causal: bool, ):\n        super(TCNStack, self).__init__()\n        self.in_channels = in_channels\n        self.stack_num = stack_num\n        self.stack_size = stack_size\n        self.res_channels = res_channels\n        self.kernel_size = kernel_size\n        self.causal = causal\n        self.res_blocks = self.stack_tcn_blocks()\n        self.receptive_fields = self.calculate_receptive_fields()\n        self.res_blocks = nn.Sequential(*self.res_blocks)\n\n    def calculate_receptive_fields(self):\n        receptive_fields = 0\n        for block in self.res_blocks:\n            receptive_fields += block.receptive_fields\n        return receptive_fields\n\n    def build_dilations(self):\n        dilations = []\n        for s in range(0, self.stack_size):\n            for l in range(0, self.stack_num):\n                dilations.append(2**l)\n        return dilations\n\n    def stack_tcn_blocks(self):\n        dilations = self.build_dilations()\n        res_blocks = nn.LayerList()\n\n        res_blocks.append(\n            TCNBlock(\n                self.in_channels,\n                self.res_channels,\n                self.kernel_size,\n                dilations[0],\n                self.causal, ))\n        for dilation in dilations[1:]:\n            res_blocks.append(\n                TCNBlock(\n                    self.res_channels,\n                    self.res_channels,\n                    self.kernel_size,\n                    dilation,\n                    self.causal, ))\n        return res_blocks\n\n    def forward(self, inputs: paddle.Tensor):\n        outputs = self.res_blocks(inputs)\n        return outputs\n\n\nclass MDTC(nn.Layer):\n    def __init__(\n            self,\n            stack_num: int,\n            stack_size: int,\n            in_channels: int,\n            res_channels: int,\n            kernel_size: int,\n            causal: bool=True, ):\n        super(MDTC, self).__init__()\n        assert kernel_size % 2 == 1\n        self.kernel_size = kernel_size\n        self.causal = causal\n        self.preprocessor = TCNBlock(\n            in_channels, res_channels, kernel_size, dilation=1, causal=causal)\n        self.relu = nn.ReLU()\n        self.blocks = nn.LayerList()\n        self.receptive_fields = self.preprocessor.receptive_fields\n        for i in range(stack_num):\n            self.blocks.append(\n                TCNStack(res_channels, stack_size, 1, res_channels, kernel_size,\n                         causal))\n            self.receptive_fields += self.blocks[-1].receptive_fields\n        self.half_receptive_fields = self.receptive_fields // 2\n        self.hidden_dim = res_channels\n\n    def forward(self, x: paddle.Tensor):\n        if self.causal:\n            outputs = F.pad(x, (0, 0, self.receptive_fields, 0, 0, 0),\n                            'constant')\n        else:\n            outputs = F.pad(\n                x,\n                (0, 0, self.half_receptive_fields, self.half_receptive_fields,\n                 0, 0),\n                'constant', )\n        outputs = outputs.transpose([0, 2, 1])\n        outputs_list = []\n        outputs = self.relu(self.preprocessor(outputs))\n        for block in self.blocks:\n            outputs = block(outputs)\n            outputs_list.append(outputs)\n\n        normalized_outputs = []\n        output_size = outputs_list[-1].shape[-1]\n        for x in outputs_list:\n            remove_length = x.shape[-1] - output_size\n            if self.causal and remove_length > 0:\n                normalized_outputs.append(x[:, :, remove_length:])\n            elif not self.causal and remove_length > 1:\n                half_remove_length = remove_length // 2\n                normalized_outputs.append(\n                    x[:, :, half_remove_length:-half_remove_length])\n            else:\n                normalized_outputs.append(x)\n\n        outputs = paddle.zeros_like(\n            outputs_list[-1], dtype=outputs_list[-1].dtype)\n        for x in normalized_outputs:\n            outputs += x\n        outputs = outputs.transpose([0, 2, 1])\n        return outputs, None\n\n\nclass KWSModel(nn.Layer):\n    def __init__(self, backbone, num_keywords):\n        super(KWSModel, self).__init__()\n        self.backbone = backbone\n        self.linear = nn.Linear(self.backbone.hidden_dim, num_keywords)\n        self.activation = nn.Sigmoid()\n\n    def forward(self, x):\n        outputs = self.backbone(x)\n        outputs = self.linear(outputs)\n        return self.activation(outputs)\n"
  },
  {
    "path": "paddlespeech/resource/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .resource import CommonTaskResource\n"
  },
  {
    "path": "paddlespeech/resource/model_alias.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = [\n    'model_alias',\n]\n\n# Records of model name to import class\nmodel_alias = {\n    # ---------------------------------\n    # -------------- SSL --------------\n    # ---------------------------------\n    \"wav2vec2ASR\": [\"paddlespeech.s2t.models.wav2vec2:Wav2vec2ASR\"],\n    \"wav2vec2\": [\"paddlespeech.s2t.models.wav2vec2:Wav2vec2Base\"],\n    \"hubertASR\": [\"paddlespeech.s2t.models.hubert:HubertASR\"],\n    \"hubert\": [\"paddlespeech.s2t.models.hubert:HubertBase\"],\n    \"wavlmASR\": [\"paddlespeech.s2t.models.wavlm:WavLMASR\"],\n\n    # ---------------------------------\n    # -------------- ASR --------------\n    # ---------------------------------\n    \"deepspeech2offline\": [\"paddlespeech.s2t.models.ds2:DeepSpeech2Model\"],\n    \"deepspeech2online\": [\"paddlespeech.s2t.models.ds2:DeepSpeech2Model\"],\n    \"conformer\": [\"paddlespeech.s2t.models.u2:U2Model\"],\n    \"conformer_online\": [\"paddlespeech.s2t.models.u2:U2Model\"],\n    \"conformer_u2pp_online\": [\"paddlespeech.s2t.models.u2:U2Model\"],\n    \"transformer\": [\"paddlespeech.s2t.models.u2:U2Model\"],\n    \"wenetspeech\": [\"paddlespeech.s2t.models.u2:U2Model\"],\n\n    # ---------------------------------\n    # ------------ Whisper ------------\n    # ---------------------------------\n    \"whisper\": [\"paddlespeech.s2t.models.whisper:Whisper\"],\n\n    # ---------------------------------\n    # -------------- CLS --------------\n    # ---------------------------------\n    \"panns_cnn6\": [\"paddlespeech.cls.models.panns:CNN6\"],\n    \"panns_cnn10\": [\"paddlespeech.cls.models.panns:CNN10\"],\n    \"panns_cnn14\": [\"paddlespeech.cls.models.panns:CNN14\"],\n\n    # ---------------------------------\n    # -------------- ST ---------------\n    # ---------------------------------\n    \"fat_st\": [\"paddlespeech.s2t.models.u2_st:U2STModel\"],\n\n    # ---------------------------------\n    # -------------- TEXT -------------\n    # ---------------------------------\n    \"ernie_linear_p7\": [\n        \"paddlespeech.text.models:ErnieLinear\",\n        \"paddlenlp.transformers:ErnieTokenizer\"\n    ],\n    \"ernie_linear_p3\": [\n        \"paddlespeech.text.models:ErnieLinear\",\n        \"paddlenlp.transformers:ErnieTokenizer\"\n    ],\n    \"ernie_linear_p3_wudao\": [\n        \"paddlespeech.text.models:ErnieLinear\",\n        \"paddlenlp.transformers:ErnieTokenizer\"\n    ],\n\n    # ---------------------------------\n    # -------------- TTS --------------\n    # ---------------------------------\n    # acoustic model\n    \"speedyspeech\": [\"paddlespeech.t2s.models.speedyspeech:SpeedySpeech\"],\n    \"speedyspeech_inference\":\n    [\"paddlespeech.t2s.models.speedyspeech:SpeedySpeechInference\"],\n    \"fastspeech2\": [\"paddlespeech.t2s.models.fastspeech2:FastSpeech2\"],\n    \"fastspeech2_inference\":\n    [\"paddlespeech.t2s.models.fastspeech2:FastSpeech2Inference\"],\n    \"tacotron2\": [\"paddlespeech.t2s.models.tacotron2:Tacotron2\"],\n    \"tacotron2_inference\":\n    [\"paddlespeech.t2s.models.tacotron2:Tacotron2Inference\"],\n    # voc\n    \"pwgan\": [\"paddlespeech.t2s.models.parallel_wavegan:PWGGenerator\"],\n    \"pwgan_inference\":\n    [\"paddlespeech.t2s.models.parallel_wavegan:PWGInference\"],\n    \"mb_melgan\": [\"paddlespeech.t2s.models.melgan:MelGANGenerator\"],\n    \"mb_melgan_inference\": [\"paddlespeech.t2s.models.melgan:MelGANInference\"],\n    \"style_melgan\": [\"paddlespeech.t2s.models.melgan:StyleMelGANGenerator\"],\n    \"style_melgan_inference\":\n    [\"paddlespeech.t2s.models.melgan:StyleMelGANInference\"],\n    \"hifigan\": [\"paddlespeech.t2s.models.hifigan:HiFiGANGenerator\"],\n    \"hifigan_inference\": [\"paddlespeech.t2s.models.hifigan:HiFiGANInference\"],\n    \"wavernn\": [\"paddlespeech.t2s.models.wavernn:WaveRNN\"],\n    \"wavernn_inference\": [\"paddlespeech.t2s.models.wavernn:WaveRNNInference\"],\n\n    # ---------------------------------\n    # ------------ Vector -------------\n    # ---------------------------------\n    \"ecapatdnn\": [\"paddlespeech.vector.models.ecapa_tdnn:EcapaTdnn\"],\n\n    # ---------------------------------\n    # -------------- kws --------------\n    # ---------------------------------\n    \"mdtc\": [\"paddlespeech.kws.models.mdtc:MDTC\"],\n    \"mdtc_for_kws\": [\"paddlespeech.kws.models.mdtc:KWSModel\"],\n}\n"
  },
  {
    "path": "paddlespeech/resource/pretrained_models.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = [\n    'asr_dynamic_pretrained_models',\n    'asr_static_pretrained_models',\n    'asr_onnx_pretrained_models',\n    'cls_dynamic_pretrained_models',\n    'cls_static_pretrained_models',\n    'st_dynamic_pretrained_models',\n    'st_kaldi_bins',\n    'text_dynamic_pretrained_models',\n    'tts_dynamic_pretrained_models',\n    'tts_static_pretrained_models',\n    'tts_onnx_pretrained_models',\n    'vector_dynamic_pretrained_models',\n    'ssl_dynamic_pretrained_models',\n    'whisper_dynamic_pretrained_models',\n]\n\n# The tags for pretrained_models should be \"{model_name}[_{dataset}][-{lang}][-...]\".\n# Add code-switch and multilingual tag, \"{model_name}[_{dataset}]-[codeswitch/multilingual][_{lang}][-...]\".\n# e.g. \"conformer_wenetspeech-zh-16k\" and \"panns_cnn6-32k\".\n# Command line and python api use \"{model_name}[_{dataset}]\" as --model, usage:\n# \"paddlespeech asr --model conformer_wenetspeech --lang zh --sr 16000 --input ./input.wav\"\n\n# ---------------------------------\n# -------------- SSL --------------\n# ---------------------------------\nssl_dynamic_pretrained_models = {\n    \"wav2vec2-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr3/wav2vec2-large-960h-lv60-self_ckpt_1.3.0.model.tar.gz',\n            'md5':\n            'acc46900680e341e500437aa59193518',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'wav2vec2-large-960h-lv60-self',\n            'model':\n            'wav2vec2-large-960h-lv60-self.pdparams',\n            'params':\n            'wav2vec2-large-960h-lv60-self.pdparams',\n        },\n    },\n    \"wav2vec2ASR_librispeech-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr3/wav2vec2ASR-large-960h-librispeech_ckpt_1.3.1.model.tar.gz',\n            'md5':\n            'cbe28d6c78f3dd2e189968402381f454',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/wav2vec2ASR/checkpoints/avg_1',\n            'model':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n            'params':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n        },\n    },\n    \"wav2vec2-zh-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2-large-wenetspeech-self_ckpt_1.3.0.model.tar.gz',\n            'md5':\n            '00ea4975c05d1bb58181205674052fe1',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'chinese-wav2vec2-large',\n            'model':\n            'chinese-wav2vec2-large.pdparams',\n            'params':\n            'chinese-wav2vec2-large.pdparams',\n        },\n    },\n    \"wav2vec2ASR_aishell1-zh-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2ASR-large-aishell1_ckpt_1.3.0.model.tar.gz',\n            'md5':\n            'ac8fa0a6345e6a7535f6fabb5e59e218',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/wav2vec2ASR/checkpoints/avg_1',\n            'model':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n            'params':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n        },\n        '1.4': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr3/wav2vec2ASR-large-aishell1_ckpt_1.4.0.model.tar.gz',\n            'md5':\n            '150e51b8ea5d255ccce6b395de8d916a',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/wav2vec2ASR/checkpoints/avg_1',\n            'model':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n            'params':\n            'exp/wav2vec2ASR/checkpoints/avg_1.pdparams',\n        },\n    },\n    \"hubert-en-16k\": {\n        '1.4': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/hubert/hubert-large-lv60_ckpt_1.4.0.model.tar.gz',\n            'md5':\n            'efecfb87a8718aa9253b7459c1fe9b54',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'hubert-large-lv60',\n            'model':\n            'hubert-large-lv60.pdparams',\n            'params':\n            'hubert-large-lv60.pdparams',\n        },\n    },\n    \"hubertASR_librispeech-100h-en-16k\": {\n        '1.4': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/hubert/hubertASR-large-100h-librispeech_ckpt_1.4.0.model.tar.gz',\n            'md5':\n            '574cefd11aaef5737969ce22a7f33ea2',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/hubertASR/checkpoints/avg_1',\n            'model':\n            'exp/hubertASR/checkpoints/avg_1.pdparams',\n            'params':\n            'exp/hubertASR/checkpoints/avg_1.pdparams',\n        },\n    },\n    \"wavlmASR_librispeech-en-16k\": {\n        \"1.0\": {\n            \"url\":\n            \"https://paddlespeech.cdn.bcebos.com/wavlm/wavlm_baseplus_libriclean_100h.tar.gz\",\n            \"md5\":\n            \"f2238e982bb8bcf046e536201f5ea629\",\n            \"cfg_path\":\n            \"model.yaml\",\n            \"ckpt_path\":\n            \"exp/wavlmASR/checkpoints/46\",\n            \"model\":\n            \"exp/wavlmASR/checkpoints/46.pdparams\",\n            \"params\":\n            \"exp/wavlmASR/checkpoints/46.pdparams\",\n        }\n    }\n}\n\n# ---------------------------------\n# -------------- ASR --------------\n# ---------------------------------\nasr_dynamic_pretrained_models = {\n    \"conformer_wenetspeech-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1_conformer_wenetspeech_ckpt_0.1.1.model.tar.gz',\n            'md5':\n            '76cb19ed857e6623856b7cd7ebbfeda4',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/conformer/checkpoints/wenetspeech',\n        },\n    },\n    \"conformer_online_wenetspeech-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_wenetspeech_ckpt_1.0.0a.model.tar.gz',\n            'md5':\n            'b8c02632b04da34aca88459835be54a6',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/avg_10',\n            'model':\n            'exp/chunk_conformer/checkpoints/avg_10.pdparams',\n            'params':\n            'exp/chunk_conformer/checkpoints/avg_10.pdparams',\n            'lm_url':\n            '',\n            'lm_md5':\n            '',\n        },\n    },\n    \"conformer_u2pp_online_wenetspeech-zh-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/asr1_chunk_conformer_u2pp_wenetspeech_ckpt_1.3.0.model.tar.gz',\n            'md5':\n            '62d230c1bf27731192aa9d3b8deca300',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer_u2pp/checkpoints/avg_10',\n            'model':\n            'exp/chunk_conformer_u2pp/checkpoints/avg_10.pdparams',\n            'params':\n            'exp/chunk_conformer_u2pp/checkpoints/avg_10.pdparams',\n            'lm_url':\n            '',\n            'lm_md5':\n            '',\n        },\n    },\n    \"conformer_online_multicn-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/multi_cn/asr1/asr1_chunk_conformer_multi_cn_ckpt_0.2.0.model.tar.gz',\n            'md5':\n            '7989b3248c898070904cf042fd656003',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/multi_cn',\n        },\n        '2.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/multi_cn/asr1/asr1_chunk_conformer_multi_cn_ckpt_0.2.3.model.tar.gz',\n            'md5':\n            '0ac93d390552336f2a906aec9e33c5fa',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/multi_cn',\n            'model':\n            'exp/chunk_conformer/checkpoints/multi_cn.pdparams',\n            'params':\n            'exp/chunk_conformer/checkpoints/multi_cn.pdparams',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3',\n        },\n    },\n    \"conformer_aishell-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_conformer_aishell_ckpt_0.1.2.model.tar.gz',\n            'md5':\n            '3f073eccfa7bb14e0c6867d65fc0dc3a',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/conformer/checkpoints/avg_30',\n        },\n    },\n    \"conformer_online_aishell-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_chunk_conformer_aishell_ckpt_0.2.0.model.tar.gz',\n            'md5':\n            'b374cfb93537761270b6224fb0bfc26a',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/avg_30',\n        },\n        '1.4': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr1/asr1_conformer_aishell_ckpt_1.5.0.model.tar.gz',\n            'md5':\n            '38924b8adc28ef458847c3571e87e3cb',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/avg_30',\n        },\n    },\n    \"transformer_librispeech-en-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr1/asr1_transformer_librispeech_ckpt_0.1.1.model.tar.gz',\n            'md5':\n            '2c667da24922aad391eacafe37bc1660',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/transformer/checkpoints/avg_10',\n        },\n    },\n    \"deepspeech2online_wenetspeech-zh-16k\": {\n        '1.0.3': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.3.model.tar.gz',\n            'md5':\n            'cfe273793e68f790f742b411c98bc75e',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n        '1.0.4': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.4.model.tar.gz',\n            'md5':\n            'c595cb76902b5a5d01409171375989f4',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n    \"deepspeech2offline_aishell-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz',\n            'md5':\n            '4d26066c6f19f52087425dc722ae5b13',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2/checkpoints/avg_10',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n    \"deepspeech2online_aishell-zh-16k\": {\n        '1.0.2': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_fbank161_ckpt_1.0.2.model.tar.gz',\n            'md5':\n            '4dd42cfce9aaa54db0ec698da6c48ec5',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_1',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n    \"deepspeech2offline_librispeech-en-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/librispeech/asr0/asr0_deepspeech2_offline_librispeech_ckpt_1.0.1.model.tar.gz',\n            'md5':\n            'ed9e2b008a65268b3484020281ab048c',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2/checkpoints/avg_5',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/en_lm/common_crawl_00.prune01111.trie.klm',\n            'lm_md5':\n            '099a601759d467cd0a8523ff939819c5'\n        },\n    },\n    \"conformer_talcs-codeswitch_zh_en-16k\": {\n        '1.4': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/tal_cs/asr1/asr1_conformer_talcs_ckpt_1.4.0.model.tar.gz',\n            'md5':\n            '01962c5d0a70878fe41cacd4f61e14d1',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/conformer/checkpoints/avg_10'\n        },\n    },\n    \"conformer_online_talcs-codeswitch_zh_en-16k\": {\n        '1.6': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/s2t/tal_cs/asr1/asr1_chunk_conformer_talcs_ckpt_1.6.0.model.tar.gz',\n            'md5':\n            '3132daf1004fd76c185e14b7f0af01f9',\n            'cfg_path':\n            'model.yaml',\n            'model':\n            'exp/chunk_conformer/checkpoints/avg_10.pdparams',\n            'params':\n            'exp/chunk_conformer/checkpoints/avg_10.pdparams',\n            'ckpt_path':\n            'exp/chunk_conformer/checkpoints/avg_10',\n        },\n    },\n}\n\nasr_static_pretrained_models = {\n    \"deepspeech2offline_aishell-zh-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_offline_aishell_ckpt_1.0.1.model.tar.gz',\n            'md5':\n            '4d26066c6f19f52087425dc722ae5b13',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2/checkpoints/avg_10.jit.pdiparams',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        }\n    },\n    \"deepspeech2online_aishell-zh-16k\": {\n        '1.0.1': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_fbank161_ckpt_1.0.1.model.tar.gz',\n            'md5':\n            'df5ddeac8b679a470176649ac4b78726',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_1',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdiparams',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n        '1.0.2': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_fbank161_ckpt_1.0.2.model.tar.gz',\n            'md5':\n            '4dd42cfce9aaa54db0ec698da6c48ec5',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_1',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n    \"deepspeech2online_wenetspeech-zh-16k\": {\n        '1.0.3': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.3.model.tar.gz',\n            'md5':\n            'cfe273793e68f790f742b411c98bc75e',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n        '1.0.4': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.4.model.tar.gz',\n            'md5':\n            'c595cb76902b5a5d01409171375989f4',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n}\n\nasr_onnx_pretrained_models = {\n    \"deepspeech2online_aishell-zh-16k\": {\n        '1.0.2': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_fbank161_ckpt_1.0.2.model.tar.gz',\n            'md5':\n            '4dd42cfce9aaa54db0ec698da6c48ec5',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_1',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_1.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n    \"deepspeech2online_wenetspeech-zh-16k\": {\n        '1.0.3': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.3.model.tar.gz',\n            'md5':\n            'cfe273793e68f790f742b411c98bc75e',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n        '1.0.4': {\n            'url':\n            'http://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr0/asr0_deepspeech2_online_wenetspeech_ckpt_1.0.4.model.tar.gz',\n            'md5':\n            'c595cb76902b5a5d01409171375989f4',\n            'cfg_path':\n            'model.yaml',\n            'ckpt_path':\n            'exp/deepspeech2_online/checkpoints/avg_10',\n            'model':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdmodel',\n            'params':\n            'exp/deepspeech2_online/checkpoints/avg_10.jit.pdiparams',\n            'onnx_model':\n            'onnx/model.onnx',\n            'lm_url':\n            'https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm',\n            'lm_md5':\n            '29e02312deb2e59b3c8686c7966d4fe3'\n        },\n    },\n}\n\nwhisper_dynamic_pretrained_models = {\n    \"whisper-large-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-large-model.tar.gz',\n            'md5':\n            'cf1557af9d8ffa493fefad9cb08ae189',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-large-model',\n            'model':\n            'whisper-large-model.pdparams',\n            'params':\n            'whisper-large-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-large-model.tar.gz',\n            'md5':\n            '9ebbd228fa07ca4557e5da863dac2982',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-large-model',\n            'model':\n            'whisper-large-model.pdparams',\n            'params':\n            'whisper-large-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-base-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-base-en-model.tar.gz',\n            'md5':\n            'b156529aefde6beb7726d2ea98fd067a',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-base-en-model',\n            'model':\n            'whisper-base-en-model.pdparams',\n            'params':\n            'whisper-base-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-base-en-model.tar.gz',\n            'md5':\n            '376617a9c5f36404f50dde3708bac0c6',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-base-en-model',\n            'model':\n            'whisper-base-en-model.pdparams',\n            'params':\n            'whisper-base-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-base-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-base-model.tar.gz',\n            'md5':\n            '6b012a5abd583db14398c3492e47120b',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-base-model',\n            'model':\n            'whisper-base-model.pdparams',\n            'params':\n            'whisper-base-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-base-model.tar.gz',\n            'md5':\n            '61836cb29c93048621f83364d83b532b',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-base-model',\n            'model':\n            'whisper-base-model.pdparams',\n            'params':\n            'whisper-base-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-medium-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-medium-en-model.tar.gz',\n            'md5':\n            'c7f57d270bd20c7b170ba9dcf6c16f74',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-medium-en-model',\n            'model':\n            'whisper-medium-en-model.pdparams',\n            'params':\n            'whisper-medium-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-medium-en-model.tar.gz',\n            'md5':\n            'ac01145c5de962f1416f3d98171be559',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-medium-en-model',\n            'model':\n            'whisper-medium-en-model.pdparams',\n            'params':\n            'whisper-medium-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-medium-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-medium-model.tar.gz',\n            'md5':\n            '4c7dcd0df25f408199db4a4548336786',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-medium-model',\n            'model':\n            'whisper-medium-model.pdparams',\n            'params':\n            'whisper-medium-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-medium-model.tar.gz',\n            'md5':\n            '07770819961d1fe795facd3666f8db17',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-medium-model',\n            'model':\n            'whisper-medium-model.pdparams',\n            'params':\n            'whisper-medium-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-small-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-small-en-model.tar.gz',\n            'md5':\n            '2b24efcb2e93f3275af7c0c7f598ff1c',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-small-en-model',\n            'model':\n            'whisper-small-en-model.pdparams',\n            'params':\n            'whisper-small-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-small-en-model.tar.gz',\n            'md5':\n            '67af14156b93f49ae738a17204189e46',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-small-en-model',\n            'model':\n            'whisper-small-en-model.pdparams',\n            'params':\n            'whisper-small-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-small-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-small-model.tar.gz',\n            'md5':\n            '5a57911dd41651dd6ed78c5763912825',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-small-model',\n            'model':\n            'whisper-small-model.pdparams',\n            'params':\n            'whisper-small-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-small-model.tar.gz',\n            'md5':\n            'db53c4bf39a9ad46ef77e6f9a37200b6',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-small-model',\n            'model':\n            'whisper-small-model.pdparams',\n            'params':\n            'whisper-small-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-tiny-en-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-tiny-en-model.tar.gz',\n            'md5':\n            '14969164a3f713fd58e56978c34188f6',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-tiny-en-model',\n            'model':\n            'whisper-tiny-en-model.pdparams',\n            'params':\n            'whisper-tiny-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-tiny-en-model.tar.gz',\n            'md5':\n            'f91f8447d8b37ed13f4327ef6565b094',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-tiny-en-model',\n            'model':\n            'whisper-tiny-en-model.pdparams',\n            'params':\n            'whisper-tiny-en-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-tiny-16k\": {\n        '1.3': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221122/whisper-tiny-model.tar.gz',\n            'md5':\n            'a5b82a1f2067a2ca400f17fabd62b81b',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-tiny-model',\n            'model':\n            'whisper-tiny-model.pdparams',\n            'params':\n            'whisper-tiny-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.cdn.bcebos.com/whisper/whisper_model_20221108/assets.tar',\n            'resource_data_md5':\n            '37a0a8abdb3641a51194f79567a93b61',\n        },\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-tiny-model.tar.gz',\n            'md5':\n            '6f2209ac656ff12de085c824363316e2',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-tiny-model',\n            'model':\n            'whisper-tiny-model.pdparams',\n            'params':\n            'whisper-tiny-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n    \"whisper-turbo-16k\": {\n        '1.5': {\n            'url':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/whisper-turbo-model.tar.gz',\n            'md5':\n            'fe2dd1a1d6eb8e6d017aafc7d5f62336',\n            'cfg_path':\n            'whisper.yaml',\n            'ckpt_path':\n            'whisper-turbo-model',\n            'model':\n            'whisper-turbo-model.pdparams',\n            'params':\n            'whisper-turbo-model.pdparams',\n            'resource_data':\n            'https://paddlespeech.bj.bcebos.com/whisper/whisper_model_20250825/assets.tar',\n            'resource_data_md5':\n            'dd61d092d362f1fdbae6ede08282e177',\n        },\n    },\n}\n\n# ---------------------------------\n# -------------- CLS --------------\n# ---------------------------------\ncls_dynamic_pretrained_models = {\n    \"panns_cnn6-32k\": {\n        '1.0': {\n            'url': 'https://paddlespeech.cdn.bcebos.com/cls/panns_cnn6.tar.gz',\n            'md5': '4cf09194a95df024fd12f84712cf0f9c',\n            'cfg_path': 'panns.yaml',\n            'ckpt_path': 'cnn6.pdparams',\n            'label_file': 'audioset_labels.txt',\n        },\n    },\n    \"panns_cnn10-32k\": {\n        '1.0': {\n            'url': 'https://paddlespeech.cdn.bcebos.com/cls/panns_cnn10.tar.gz',\n            'md5': 'cb8427b22176cc2116367d14847f5413',\n            'cfg_path': 'panns.yaml',\n            'ckpt_path': 'cnn10.pdparams',\n            'label_file': 'audioset_labels.txt',\n        },\n    },\n    \"panns_cnn14-32k\": {\n        '1.0': {\n            'url': 'https://paddlespeech.cdn.bcebos.com/cls/panns_cnn14.tar.gz',\n            'md5': 'e3b9b5614a1595001161d0ab95edee97',\n            'cfg_path': 'panns.yaml',\n            'ckpt_path': 'cnn14.pdparams',\n            'label_file': 'audioset_labels.txt',\n        },\n    },\n}\n\ncls_static_pretrained_models = {\n    \"panns_cnn6-32k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn6_static.tar.gz',\n            'md5':\n            'da087c31046d23281d8ec5188c1967da',\n            'cfg_path':\n            'panns.yaml',\n            'model_path':\n            'inference.pdmodel',\n            'params_path':\n            'inference.pdiparams',\n            'label_file':\n            'audioset_labels.txt',\n        },\n    },\n    \"panns_cnn10-32k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn10_static.tar.gz',\n            'md5':\n            '5460cc6eafbfaf0f261cc75b90284ae1',\n            'cfg_path':\n            'panns.yaml',\n            'model_path':\n            'inference.pdmodel',\n            'params_path':\n            'inference.pdiparams',\n            'label_file':\n            'audioset_labels.txt',\n        },\n    },\n    \"panns_cnn14-32k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/cls/inference_model/panns_cnn14_static.tar.gz',\n            'md5':\n            'ccc80b194821274da79466862b2ab00f',\n            'cfg_path':\n            'panns.yaml',\n            'model_path':\n            'inference.pdmodel',\n            'params_path':\n            'inference.pdiparams',\n            'label_file':\n            'audioset_labels.txt',\n        },\n    },\n}\n\n# ---------------------------------\n# -------------- ST ---------------\n# ---------------------------------\nst_dynamic_pretrained_models = {\n    \"fat_st_ted-en-zh\": {\n        '1.0': {\n            \"url\":\n            \"https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/st1_transformer_mtl_noam_ted-en-zh_ckpt_0.1.1.model.tar.gz\",\n            \"md5\":\n            \"d62063f35a16d91210a71081bd2dd557\",\n            \"cfg_path\":\n            \"model.yaml\",\n            \"ckpt_path\":\n            \"exp/transformer_mtl_noam/checkpoints/fat_st_ted-en-zh.pdparams\",\n        },\n    },\n}\n\nst_kaldi_bins = {\n    \"url\":\n    \"https://paddlespeech.cdn.bcebos.com/s2t/ted_en_zh/st1/kaldi_bins.tar.gz\",\n    \"md5\":\n    \"c0682303b3f3393dbf6ed4c4e35a53eb\",\n}\n\n# ---------------------------------\n# -------------- TEXT -------------\n# ---------------------------------\ntext_dynamic_pretrained_models = {\n    \"ernie_linear_p7_wudao-punc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/text/ernie_linear_p7_wudao-punc-zh.tar.gz',\n            'md5':\n            '12283e2ddde1797c5d1e57036b512746',\n            'cfg_path':\n            'ckpt/model_config.json',\n            'ckpt_path':\n            'ckpt/model_state.pdparams',\n            'vocab_file':\n            'punc_vocab.txt',\n        }\n    },\n    \"ernie_linear_p3_wudao-punc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/text/ernie_linear_p3_wudao-punc-zh.tar.gz',\n            'md5':\n            '448eb2fdf85b6a997e7e652e80c51dd2',\n            'cfg_path':\n            'ckpt/model_config.json',\n            'ckpt_path':\n            'ckpt/model_state.pdparams',\n            'vocab_file':\n            'punc_vocab.txt',\n        }\n    },\n    \"ernie_linear_p3_wudao_fast-punc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/text/ernie_linear_p3_wudao_fast-punc-zh.tar.gz',\n            'md5':\n            'c93f9594119541a5dbd763381a751d08',\n            'cfg_path':\n            'ckpt/model_config.json',\n            'ckpt_path':\n            'ckpt/model_state.pdparams',\n            'vocab_file':\n            'punc_vocab.txt',\n        }\n    }\n}\n\n# ---------------------------------\n# -------------- TTS --------------\n# ---------------------------------\ntts_dynamic_pretrained_models = {\n    # speedyspeech\n    \"speedyspeech_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_ckpt_0.2.0.zip',\n            'md5':\n            '6f6fa967b408454b6662c8c00c0027cb',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_30600.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'tones_dict':\n            'tone_id_map.txt',\n        },\n    },\n    # fastspeech2\n    \"fastspeech2_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_ckpt_0.4.zip',\n            'md5':\n            '637d28a5e53aa60275612ba4393d5f22',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_76000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"fastspeech2_canton-canton\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_ckpt_1.4.0.zip',\n            'md5':\n            '504560c082deba82120927627c900374',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_140000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n        },\n    },\n    \"fastspeech2_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_ljspeech_ckpt_0.5.zip',\n            'md5':\n            'ffed800c93deaf16ca9b3af89bfcd747',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_100000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"fastspeech2_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_aishell3_ckpt_0.4.zip',\n            'md5':\n            'f4dd4a5f49a4552b77981f544ab3392e',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_96400.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n        },\n    },\n    \"fastspeech2_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_vctk_ckpt_0.5.zip',\n            'md5':\n            '743e5024ca1e17a88c5c271db9779ba4',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_66200.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n        },\n    },\n    \"fastspeech2_cnndecoder_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_ckpt_1.0.0.zip',\n            'md5':\n            '6eb28e22ace73e0ebe7845f86478f89f',\n            'config':\n            'cnndecoder.yaml',\n            'ckpt':\n            'snapshot_iter_153000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"fastspeech2_mix-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_csmscljspeech_add-zhen.zip',\n            'md5':\n            '77d9d4b5a79ed6203339ead7ef6c74f9',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_94000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n        },\n        '2.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_ckpt_0.2.0.zip',\n            'md5':\n            '1d938e104e972386c8bfcbcc98a91587',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_99200.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n        },\n    },\n    \"fastspeech2_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_ckpt_1.4.0.zip',\n            'md5':\n            '43a9f4bc48a91f5a6f53017474e6c788',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_76000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"fastspeech2_male-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_ckpt_1.4.0.zip',\n            'md5':\n            'cc9f44f1f20a8173f63e2d1d41ef1a9c',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_100000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"fastspeech2_male-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_ckpt_1.4.0.zip',\n            'md5':\n            '6d48ad60ef0ab2cee89a5d8cfd93dd86',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_177000.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    # tacotron2\n    \"tacotron2_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_csmsc_ckpt_0.2.0.zip',\n            'md5':\n            '0df4b6f0bcbe0d73c5ed6df8867ab91a',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_30600.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    \"tacotron2_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/tacotron2/tacotron2_ljspeech_ckpt_0.2.0.zip',\n            'md5':\n            '6a5eddd81ae0e81d16959b97481135f3',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_60300.pdz',\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n        },\n    },\n    # pwgan\n    \"pwgan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_ckpt_0.4.zip',\n            'md5':\n            '2e481633325b5bdf0a3823c714d2c117',\n            'config':\n            'pwg_default.yaml',\n            'ckpt':\n            'pwg_snapshot_iter_400000.pdz',\n            'speech_stats':\n            'pwg_stats.npy',\n        },\n    },\n    \"pwgan_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_ljspeech_ckpt_0.5.zip',\n            'md5':\n            '53610ba9708fd3008ccaf8e99dacbaf0',\n            'config':\n            'pwg_default.yaml',\n            'ckpt':\n            'pwg_snapshot_iter_400000.pdz',\n            'speech_stats':\n            'pwg_stats.npy',\n        },\n    },\n    \"pwgan_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_aishell3_ckpt_0.5.zip',\n            'md5':\n            'd7598fa41ad362d62f85ffc0f07e3d84',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_1000000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"pwgan_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_vctk_ckpt_0.1.1.zip',\n            'md5':\n            'b3da1defcde3e578be71eb284cb89f2c',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_1500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"pwgan_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_male_ckpt_1.4.0.zip',\n            'md5':\n            'a443d6253bf9be377f27ae5972a03c65',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_200000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    # mb_melgan\n    \"mb_melgan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_ckpt_0.1.1.zip',\n            'md5':\n            'ee5f0604e20091f0d495b6ec4618b90d',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_1000000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    # style_melgan\n    \"style_melgan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/style_melgan/style_melgan_csmsc_ckpt_0.1.1.zip',\n            'md5':\n            '5de2d5348f396de0c966926b8c462755',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_1500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    # hifigan\n    \"hifigan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_ckpt_0.1.1.zip',\n            'md5':\n            'dd40a3d88dfcf64513fba2f0f961ada6',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_2500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"hifigan_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_ckpt_0.2.0.zip',\n            'md5':\n            '70e9131695decbca06a65fe51ed38a72',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_2500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"hifigan_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_ckpt_0.2.0.zip',\n            'md5':\n            '3bb49bc75032ed12f79c00c8cc79a09a',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_2500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"hifigan_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_ckpt_0.2.0.zip',\n            'md5':\n            '7da8f88359bca2457e705d924cf27bd4',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_2500000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    \"hifigan_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_ckpt_1.4.0.zip',\n            'md5':\n            'a709830596e102c2b83f8adc26d41d85',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_630000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n    # wavernn\n    \"wavernn_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/wavernn/wavernn_csmsc_ckpt_0.2.0.zip',\n            'md5':\n            'ee37b752f09bcba8f2af3b777ca38e13',\n            'config':\n            'default.yaml',\n            'ckpt':\n            'snapshot_iter_400000.pdz',\n            'speech_stats':\n            'feats_stats.npy',\n        },\n    },\n}\ntts_dynamic_pretrained_models[\n    \"fastspeech2_mix-zh\"] = tts_dynamic_pretrained_models[\n        \"fastspeech2_mix-en\"] = tts_dynamic_pretrained_models[\n            \"fastspeech2_mix-mix\"]\ntts_dynamic_pretrained_models[\"pwgan_male-en\"] = tts_dynamic_pretrained_models[\n    \"pwgan_male-mix\"] = tts_dynamic_pretrained_models[\"pwgan_male-zh\"]\ntts_dynamic_pretrained_models[\n    \"hifigan_male-en\"] = tts_dynamic_pretrained_models[\n        \"hifigan_male-mix\"] = tts_dynamic_pretrained_models[\"hifigan_male-zh\"]\n\ntts_static_pretrained_models = {\n    # speedyspeech\n    \"speedyspeech_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_nosil_baker_static_0.5.zip',\n            'md5':\n            'f10cbdedf47dc7a9668d2264494e1823',\n            'model':\n            'speedyspeech_csmsc.pdmodel',\n            'params':\n            'speedyspeech_csmsc.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'tones_dict':\n            'tone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    # fastspeech2\n    \"fastspeech2_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_nosil_baker_static_0.4.zip',\n            'md5':\n            '9788cd9745e14c7a5d12d32670b2a5a7',\n            'model':\n            'fastspeech2_csmsc.pdmodel',\n            'params':\n            'fastspeech2_csmsc.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_static_1.1.0.zip',\n            'md5':\n            'c49f70b52973423ec45aaa6184fb5bc6',\n            'model':\n            'fastspeech2_ljspeech.pdmodel',\n            'params':\n            'fastspeech2_ljspeech.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"fastspeech2_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_static_1.1.0.zip',\n            'md5':\n            '695af44679f48eb4abc159977ddaee16',\n            'model':\n            'fastspeech2_aishell3.pdmodel',\n            'params':\n            'fastspeech2_aishell3.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_static_1.1.0.zip',\n            'md5':\n            '92d8c082f180bda2fd05a534fb4a1b62',\n            'model':\n            'fastspeech2_vctk.pdmodel',\n            'params':\n            'fastspeech2_vctk.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_mix-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_csmscljspeech_add-zhen_static.zip',\n            'md5':\n            'b5001f66cccafdde07707e1b6269fa58',\n            'model':\n            'fastspeech2_mix.pdmodel',\n            'params':\n            'fastspeech2_mix.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n        '2.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_static_0.2.0.zip',\n            'md5':\n            'c6dd138fab3ba261299c0b2efee51d5a',\n            'model':\n            'fastspeech2_mix.pdmodel',\n            'params':\n            'fastspeech2_mix.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_static_1.4.0.zip',\n            'md5':\n            '9b7218829e7fa01aa33dbb2c5f6ef20f',\n            'model':\n            'fastspeech2_male-zh.pdmodel',\n            'params':\n            'fastspeech2_male-zh.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_static_1.4.0.zip',\n            'md5':\n            '33cea19b6821b371d242969ffd8b6cbf',\n            'model':\n            'fastspeech2_male-en.pdmodel',\n            'params':\n            'fastspeech2_male-en.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_static_1.4.0.zip',\n            'md5':\n            '66585b04c0ced72f3cb82ee85b814d80',\n            'model':\n            'fastspeech2_male-mix.pdmodel',\n            'params':\n            'fastspeech2_male-mix.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_canton-canton\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_static_1.4.0.zip',\n            'md5':\n            '5da80931666503b9b6aed25e894d2ade',\n            'model':\n            'fastspeech2_canton.pdmodel',\n            'params':\n            'fastspeech2_canton.pdiparams',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    # pwgan\n    \"pwgan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwg_baker_static_0.4.zip',\n            'md5':\n            'e3504aed9c5a290be12d1347836d2742',\n            'model':\n            'pwgan_csmsc.pdmodel',\n            'params':\n            'pwgan_csmsc.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_static_1.1.0.zip',\n            'md5':\n            '6f457a069da99c6814ac1fb4677281e4',\n            'model':\n            'pwgan_ljspeech.pdmodel',\n            'params':\n            'pwgan_ljspeech.pdiparams',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"pwgan_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_static_1.1.0.zip',\n            'md5':\n            '199f64010238275fbdacb326a5cf82d1',\n            'model':\n            'pwgan_aishell3.pdmodel',\n            'params':\n            'pwgan_aishell3.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_static_1.1.0.zip',\n            'md5':\n            'ee0fc571ad5a7fbe4ca20e49df22b819',\n            'model':\n            'pwgan_vctk.pdmodel',\n            'params':\n            'pwgan_vctk.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_male_static_1.4.0.zip',\n            'md5':\n            '52a480ad35694b96603e0a92e9fb3f95',\n            'model':\n            'pwgan_male.pdmodel',\n            'params':\n            'pwgan_male.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    # mb_melgan\n    \"mb_melgan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_static_0.1.1.zip',\n            'md5':\n            'ac6eee94ba483421d750433f4c3b8d36',\n            'model':\n            'mb_melgan_csmsc.pdmodel',\n            'params':\n            'mb_melgan_csmsc.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    # hifigan\n    \"hifigan_csmsc-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_static_0.1.1.zip',\n            'md5':\n            '7edd8c436b3a5546b3a7cb8cff9d5a0c',\n            'model':\n            'hifigan_csmsc.pdmodel',\n            'params':\n            'hifigan_csmsc.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_ljspeech-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_static_1.1.0.zip',\n            'md5':\n            '8c674e79be7c45f6eda74825316438a0',\n            'model':\n            'hifigan_ljspeech.pdmodel',\n            'params':\n            'hifigan_ljspeech.pdiparams',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"hifigan_aishell3-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_static_1.1.0.zip',\n            'md5':\n            '7a10ec5d8d851e2000128f040d30cc01',\n            'model':\n            'hifigan_aishell3.pdmodel',\n            'params':\n            'hifigan_aishell3.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_vctk-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_static_1.1.0.zip',\n            'md5':\n            '130f791dfac84ccdd44ccbdfb67bf08e',\n            'model':\n            'hifigan_vctk.pdmodel',\n            'params':\n            'hifigan_vctk.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_male-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_static_1.4.0.zip',\n            'md5':\n            '9011fa2738b501e909d1a61054bed29b',\n            'model':\n            'hifigan_male.pdmodel',\n            'params':\n            'hifigan_male.pdiparams',\n            'sample_rate':\n            24000,\n        },\n    },\n}\n\ntts_static_pretrained_models[\n    \"fastspeech2_mix-zh\"] = tts_static_pretrained_models[\n        \"fastspeech2_mix-en\"] = tts_static_pretrained_models[\n            \"fastspeech2_mix-mix\"]\ntts_static_pretrained_models[\"pwgan_male-en\"] = tts_static_pretrained_models[\n    \"pwgan_male-mix\"] = tts_static_pretrained_models[\"pwgan_male-zh\"]\ntts_static_pretrained_models[\"hifigan_male-en\"] = tts_static_pretrained_models[\n    \"hifigan_male-mix\"] = tts_static_pretrained_models[\"hifigan_male-zh\"]\ntts_static_pretrained_models[\n    \"pwgan_aishell3-canton\"] = tts_static_pretrained_models[\"pwgan_aishell3-zh\"]\n\ntts_onnx_pretrained_models = {\n    # speedyspeech\n    \"speedyspeech_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/speedyspeech/speedyspeech_csmsc_onnx_0.2.0.zip',\n            'md5':\n            '3e9c45af9ef70675fc1968ed5074fc88',\n            'ckpt':\n            'speedyspeech_csmsc.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'tones_dict':\n            'tone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    # fastspeech2\n    \"fastspeech2_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_csmsc_onnx_0.2.0.zip',\n            'md5':\n            'fd3ad38d83273ad51f0ea4f4abf3ab4e',\n            'ckpt':\n            'fastspeech2_csmsc.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_ljspeech_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_ljspeech_onnx_1.1.0.zip',\n            'md5':\n            '00754307636a48c972a5f3e65cda3d18',\n            'ckpt':\n            'fastspeech2_ljspeech.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"fastspeech2_aishell3_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_aishell3_onnx_1.1.0.zip',\n            'md5':\n            'a1d6ee21de897ce394f5469e2bb4df0d',\n            'ckpt':\n            'fastspeech2_aishell3.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_vctk_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_vctk_onnx_1.1.0.zip',\n            'md5':\n            'd9c3a9b02204a2070504dd99f5f959bf',\n            'ckpt':\n            'fastspeech2_vctk.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_cnndecoder_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip',\n            'md5':\n            '5f70e1a6bcd29d72d54e7931aa86f266',\n            'ckpt': [\n                'fastspeech2_csmsc_am_encoder_infer.onnx',\n                'fastspeech2_csmsc_am_decoder.onnx',\n                'fastspeech2_csmsc_am_postnet.onnx',\n            ],\n            'speech_stats':\n            'speech_stats.npy',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_mix_onnx-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_csmscljspeech_add-zhen_onnx.zip',\n            'md5':\n            '73052520202957920cf54700980933d0',\n            'ckpt':\n            'fastspeech2_mix.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n        '2.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/t2s/chinse_english_mixed/models/fastspeech2_mix_onnx_0.2.0.zip',\n            'md5':\n            '43b8ca5f85709c503777f808eb02a39e',\n            'ckpt':\n            'fastspeech2_mix.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_zh_onnx_1.4.0.zip',\n            'md5':\n            '46c66f5ab86f4fcb493d899d9901c863',\n            'ckpt':\n            'fastspeech2_male-zh.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_en_onnx_1.4.0.zip',\n            'md5':\n            '401fb5cc31fdb25e22e901c9acba79c8',\n            'ckpt':\n            'fastspeech2_male-en.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_male_onnx-mix\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_male_mix_onnx_1.4.0.zip',\n            'md5':\n            '07e51c5991c529b78603034547e9d0fa',\n            'ckpt':\n            'fastspeech2_male-mix.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"fastspeech2_canton_onnx-canton\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_canton_onnx_1.4.0.zip',\n            'md5':\n            '1c8d51ceb2f9bdd168e23be575c2ccf8',\n            'ckpt':\n            'fastspeech2_canton.onnx',\n            'phones_dict':\n            'phone_id_map.txt',\n            'speaker_dict':\n            'speaker_id_map.txt',\n            'sample_rate':\n            24000,\n        },\n    },\n    # pwgan\n    \"pwgan_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_csmsc_onnx_0.2.0.zip',\n            'md5':\n            '711d0ade33e73f3b721efc9f20669f9c',\n            'ckpt':\n            'pwgan_csmsc.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_ljspeech_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_ljspeech_onnx_1.1.0.zip',\n            'md5':\n            '73cdeeccb77f2ea6ed4d07e71d8ac8b8',\n            'ckpt':\n            'pwgan_ljspeech.onnx',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"pwgan_aishell3_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_aishell3_onnx_1.1.0.zip',\n            'md5':\n            '096ab64e152a4fa476aff79ebdadb01b',\n            'ckpt':\n            'pwgan_aishell3.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_vctk_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_vctk_onnx_1.1.0.zip',\n            'md5':\n            '4e754d42cf85f6428f0af887c923d86c',\n            'ckpt':\n            'pwgan_vctk.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"pwgan_male_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/pwgan/pwgan_male_onnx_1.4.0.zip',\n            'md5':\n            '13163fd1326f555650dc7141d31767c3',\n            'ckpt':\n            'pwgan_male.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    # mb_melgan\n    \"mb_melgan_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip',\n            'md5':\n            '5b83ec746e8414bc29032d954ffd07ec',\n            'ckpt':\n            'mb_melgan_csmsc.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    # hifigan\n    \"hifigan_csmsc_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_csmsc_onnx_0.2.0.zip',\n            'md5':\n            '1a7dc0385875889e46952e50c0994a6b',\n            'ckpt':\n            'hifigan_csmsc.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_ljspeech_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_ljspeech_onnx_1.1.0.zip',\n            'md5':\n            '062f54b79c1135a50adb5fc8406260b2',\n            'ckpt':\n            'hifigan_ljspeech.onnx',\n            'sample_rate':\n            22050,\n        },\n    },\n    \"hifigan_aishell3_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_aishell3_onnx_1.1.0.zip',\n            'md5':\n            'd6c0d684ad148583ca57837d5e870167',\n            'ckpt':\n            'hifigan_aishell3.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_vctk_onnx-en\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_vctk_onnx_1.1.0.zip',\n            'md5':\n            'fd714df3be283c0efbefc8510160ff6d',\n            'ckpt':\n            'hifigan_vctk.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n    \"hifigan_male_onnx-zh\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/hifigan/hifigan_male_onnx_1.4.0.zip',\n            'md5':\n            'ec6b35417b1fe811d3b1641d4b527769',\n            'ckpt':\n            'hifigan_male.onnx',\n            'sample_rate':\n            24000,\n        },\n    },\n}\n\ntts_onnx_pretrained_models[\n    \"fastspeech2_mix_onnx-zh\"] = tts_onnx_pretrained_models[\n        \"fastspeech2_mix_onnx-en\"] = tts_onnx_pretrained_models[\n            \"fastspeech2_mix_onnx-mix\"]\ntts_onnx_pretrained_models[\"pwgan_male_onnx-en\"] = tts_onnx_pretrained_models[\n    \"pwgan_male_onnx-mix\"] = tts_onnx_pretrained_models[\"pwgan_male_onnx-zh\"]\ntts_onnx_pretrained_models[\"hifigan_male_onnx-en\"] = tts_onnx_pretrained_models[\n    \"hifigan_male_onnx-mix\"] = tts_onnx_pretrained_models[\n        \"hifigan_male_onnx-zh\"]\ntts_onnx_pretrained_models[\n    \"pwgan_aishell3_onnx-canton\"] = tts_onnx_pretrained_models[\n        \"pwgan_aishell3_onnx-zh\"]\n\n# ---------------------------------\n# ------------ Vector -------------\n# ---------------------------------\nvector_dynamic_pretrained_models = {\n    \"ecapatdnn_voxceleb12-16k\": {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/vector/voxceleb/sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_0.tar.gz',\n            'md5':\n            'cc33023c54ab346cd318408f43fcaf95',\n            'cfg_path':\n            'conf/model.yaml',  # the yaml config path\n            'ckpt_path':\n            'model/model',  # the format is ${dir}/{model_name},\n            # so the first 'model' is dir, the second 'model' is the name\n            # this means we have a model stored as model/model.pdparams\n        },\n    },\n}\n\n# ---------------------------------\n# ------------- KWS ---------------\n# ---------------------------------\nkws_dynamic_pretrained_models = {\n    'mdtc_heysnips-16k': {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/kws/heysnips/kws0_mdtc_heysnips_ckpt.tar.gz',\n            'md5':\n            'c0de0a9520d66c3c8d6679460893578f',\n            'cfg_path':\n            'conf/mdtc.yaml',\n            'ckpt_path':\n            'ckpt/model',\n        },\n    },\n}\n\n# ---------------------------------\n# ------------- G2PW ---------------\n# ---------------------------------\ng2pw_onnx_models = {\n    'G2PWModel': {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/g2p/G2PWModel_1.0.zip',\n            'md5':\n            '7e049a55547da840502cf99e8a64f20e',\n        },\n        '1.1': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/g2p/new/G2PWModel_1.1.zip',\n            'md5':\n            'f8b60501770bff92ed6ce90860a610e6',\n        },\n    },\n}\n\n# ---------------------------------\n# ---------- Rhy_frontend ---------\n# ---------------------------------\nrhy_frontend_models = {\n    'rhy_e2e': {\n        '1.0': {\n            'url':\n            'https://paddlespeech.cdn.bcebos.com/Rhy_e2e/rhy_frontend.zip',\n            'md5': '6624a77393de5925d5a84400b363d8ef',\n        },\n    },\n}\n\n# ---------------------------------\n# ---------- StarGANv2VC ----------\n# ---------------------------------\n\nStarGANv2VC_source = {\n    '1.0': {\n        'url':\n        'https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/starganv2vc/StarGANv2VC_source.zip',\n        'md5':\n        '195e169419163f5648030ba84c71f866',\n    }\n}\n"
  },
  {
    "path": "paddlespeech/resource/resource.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom collections import OrderedDict\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nfrom ..cli.utils import download_and_decompress\nfrom ..utils.dynamic_import import dynamic_import\nfrom ..utils.env import MODEL_HOME\nfrom .model_alias import model_alias\n\ntask_supported = [\n    'asr', 'cls', 'st', 'text', 'tts', 'vector', 'kws', 'ssl', 'whisper'\n]\nmodel_format_supported = ['dynamic', 'static', 'onnx']\ninference_mode_supported = ['online', 'offline']\n\n\nclass CommonTaskResource:\n    def __init__(self, task: str, model_format: str='dynamic', **kwargs):\n        assert task in task_supported, 'Arg \"task\" must be one of {}.'.format(\n            task_supported)\n        assert model_format in model_format_supported, 'Arg \"model_format\" must be one of {}.'.format(\n            model_format_supported)\n\n        self.task = task\n        self.model_format = model_format\n        self.pretrained_models = self._get_pretrained_models()\n\n        if 'inference_mode' in kwargs:\n            assert kwargs[\n                'inference_mode'] in inference_mode_supported, 'Arg \"inference_mode\" must be one of {}.'.format(\n                    inference_mode_supported)\n            self._inference_mode_filter(kwargs['inference_mode'])\n\n        # Initialize after model and version had been set.\n        self.model_tag = None\n        self.version = None\n        self.res_dict = None\n        self.res_dir = None\n\n        if self.task == 'tts':\n            # For vocoder\n            self.voc_model_tag = None\n            self.voc_version = None\n            self.voc_res_dict = None\n            self.voc_res_dir = None\n\n    def set_task_model(self,\n                       model_tag: str,\n                       model_type: int=0,\n                       skip_download: bool=False,\n                       version: Optional[str]=None):\n        \"\"\"Set model tag and version of current task.\n\n        Args:\n            model_tag (str): Model tag.\n            model_type (int): 0 for acoustic model otherwise vocoder in tts task.\n            version (Optional[str], optional): Version of pretrained model. Defaults to None.\n        \"\"\"\n        assert model_tag in self.pretrained_models, \\\n            \"Can't find \\\"{}\\\" in resource. Model name must be one of {}\".format(model_tag, list(self.pretrained_models.keys()))\n\n        if version is None:\n            version = self._get_default_version(model_tag)\n\n        assert version in self.pretrained_models[model_tag], \\\n            \"Can't find version \\\"{}\\\" in \\\"{}\\\". Model name must be one of {}\".format(\n                version, model_tag, list(self.pretrained_models[model_tag].keys()))\n\n        if model_type == 0:\n            self.model_tag = model_tag\n            self.version = version\n            self.res_dict = self.pretrained_models[model_tag][version]\n            self._format_path(self.res_dict)\n            if not skip_download:\n                self.res_dir = self._fetch(self.res_dict,\n                                           self._get_model_dir(model_type))\n        else:\n            assert self.task == 'tts', 'Vocoder will only be used in tts task.'\n            self.voc_model_tag = model_tag\n            self.voc_version = version\n            self.voc_res_dict = self.pretrained_models[model_tag][version]\n            self._format_path(self.voc_res_dict)\n            if not skip_download:\n                self.voc_res_dir = self._fetch(self.voc_res_dict,\n                                               self._get_model_dir(model_type))\n\n    @staticmethod\n    def get_model_class(model_name) -> List[object]:\n        \"\"\"Dynamic import model class.\n        Args:\n            model_name (str): Model name.\n\n        Returns:\n            List[object]: Return a list of model class.\n        \"\"\"\n        assert model_name in model_alias, 'No model classes found for \"{}\"'.format(\n            model_name)\n        ret = []\n        for import_path in model_alias[model_name]:\n            ret.append(dynamic_import(import_path))\n\n        if len(ret) == 1:\n            return ret[0]\n        else:\n            return ret\n\n    def get_versions(self, model_tag: str) -> List[str]:\n        \"\"\"List all available versions.\n\n        Args:\n            model_tag (str): Model tag.\n\n        Returns:\n            List[str]: Version list of model.\n        \"\"\"\n        return list(self.pretrained_models[model_tag].keys())\n\n    def _get_default_version(self, model_tag: str) -> str:\n        \"\"\"Get default version of model.\n\n        Args:\n            model_tag (str): Model tag.\n\n        Returns:\n            str: Default version.\n        \"\"\"\n        return self.get_versions(model_tag)[-1]  # get latest version\n\n    def _get_model_dir(self, model_type: int=0) -> os.PathLike:\n        \"\"\"Get resource directory.\n\n        Args:\n            model_type (int): 0 for acoustic model otherwise vocoder in tts task.\n\n        Returns:\n            os.PathLike: Directory of model resource.\n        \"\"\"\n        if model_type == 0:\n            model_tag = self.model_tag\n            version = self.version\n        else:\n            model_tag = self.voc_model_tag\n            version = self.voc_version\n\n        return os.path.join(MODEL_HOME, model_tag, version)\n\n    def _get_pretrained_models(self) -> Dict[str, str]:\n        \"\"\"Get all available models for current task.\n\n        Returns:\n            Dict[str, str]: A dictionary with model tag and resources info.\n        \"\"\"\n        try:\n            import_models = '{}_{}_pretrained_models'.format(self.task,\n                                                             self.model_format)\n            exec('from .pretrained_models import {}'.format(import_models))\n            models = OrderedDict(locals()[import_models])\n        except Exception as e:\n            models = OrderedDict({})  # no models.\n        finally:\n            return models\n\n    def _inference_mode_filter(self, inference_mode: Optional[str]):\n        \"\"\"Filter models dict based on inference_mode.\n\n        Args:\n            inference_mode (Optional[str]): 'online', 'offline' or None.\n        \"\"\"\n        if inference_mode is None:\n            return\n\n        if self.task == 'asr':\n            online_flags = [\n                'online' in model_tag\n                for model_tag in self.pretrained_models.keys()\n            ]\n            for online_flag, model_tag in zip(\n                    online_flags, list(self.pretrained_models.keys())):\n                if inference_mode == 'online' and online_flag:\n                    continue\n                elif inference_mode == 'offline' and not online_flag:\n                    continue\n                else:\n                    del self.pretrained_models[model_tag]\n        elif self.task == 'tts':\n            # Hardcode for tts online models.\n            tts_online_models = [\n                'fastspeech2_csmsc-zh', 'fastspeech2_cnndecoder_csmsc-zh',\n                'mb_melgan_csmsc-zh', 'hifigan_csmsc-zh'\n            ]\n            for model_tag in list(self.pretrained_models.keys()):\n                if inference_mode == 'online' and model_tag in tts_online_models:\n                    continue\n                elif inference_mode == 'offline':\n                    continue\n                else:\n                    del self.pretrained_models[model_tag]\n        else:\n            raise NotImplementedError('Only supports asr and tts task.')\n\n    @staticmethod\n    def _fetch(res_dict: Dict[str, str],\n               target_dir: os.PathLike) -> os.PathLike:\n        \"\"\"Fetch archive from url.\n\n        Args:\n            res_dict (Dict[str, str]): Info dict of a resource.\n            target_dir (os.PathLike): Directory to save archives.\n\n        Returns:\n            os.PathLike: Directory of model resource.\n        \"\"\"\n        return download_and_decompress(res_dict, target_dir)\n\n    @staticmethod\n    def _format_path(res_dict: Dict[str, str]):\n        for k, v in res_dict.items():\n            if isinstance(v, str) and '/' in v:\n                if v.startswith('https://') or v.startswith('http://'):\n                    continue\n                else:\n                    res_dict[k] = os.path.join(*(v.split('/')))\n"
  },
  {
    "path": "paddlespeech/s2t/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Any\nfrom typing import List\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n########### hack logging #############\nlogger.warn = logger.warning\n\n########### hack paddle #############\npaddle.half = 'float16'\npaddle.float = 'float32'\npaddle.double = 'float64'\npaddle.short = 'int16'\npaddle.int = 'int32'\npaddle.long = 'int64'\npaddle.uint16 = 'uint16'\npaddle.cdouble = 'complex128'\n\nif not hasattr(paddle, 'sigmoid'):\n    logger.debug(\"register user sigmoid to paddle, remove this when fixed!\")\n    setattr(paddle, 'sigmoid', paddle.nn.functional.sigmoid)\n\nif not hasattr(paddle, 'log_sigmoid'):\n    logger.debug(\"register user log_sigmoid to paddle, remove this when fixed!\")\n    setattr(paddle, 'log_sigmoid', paddle.nn.functional.log_sigmoid)\n\nif not hasattr(paddle, 'relu'):\n    logger.debug(\"register user relu to paddle, remove this when fixed!\")\n    setattr(paddle, 'relu', paddle.nn.functional.relu)\n\n\ndef cat(xs, dim=0):\n    return paddle.concat(xs, axis=dim)\n\n\nif not hasattr(paddle, 'cat'):\n    logger.debug(\n        \"override cat of paddle if exists or register, remove this when fixed!\")\n    paddle.cat = cat\n\n\n########### hack paddle.Tensor #############\ndef item(x: paddle.Tensor):\n    return x.numpy().item()\n\n\nif not hasattr(paddle.Tensor, 'item'):\n    logger.debug(\n        \"override item of paddle.Tensor if exists or register, remove this when fixed!\"\n    )\n    paddle.Tensor.item = item\n\n\ndef func_long(x: paddle.Tensor):\n    return paddle.cast(x, paddle.long)\n\n\nif not hasattr(paddle.Tensor, 'long'):\n    logger.debug(\n        \"override long of paddle.Tensor if exists or register, remove this when fixed!\"\n    )\n    paddle.Tensor.long = func_long\n    paddle.static.Variable.long = func_long\n\nif not hasattr(paddle.Tensor, 'numel'):\n    logger.debug(\n        \"override numel of paddle.Tensor if exists or register, remove this when fixed!\"\n    )\n    paddle.Tensor.numel = paddle.numel\n    paddle.static.Variable.numel = paddle.numel\n\n\ndef new_full(x: paddle.Tensor,\n             size: Union[List[int], Tuple[int], paddle.Tensor],\n             fill_value: Union[float, int, bool, paddle.Tensor],\n             dtype=None):\n    return paddle.full(size, fill_value, dtype=x.dtype)\n\n\nif not hasattr(paddle.Tensor, 'new_full'):\n    logger.debug(\n        \"override new_full of paddle.Tensor if exists or register, remove this when fixed!\"\n    )\n    paddle.Tensor.new_full = new_full\n    paddle.static.Variable.new_full = new_full\n\n\ndef contiguous(xs: paddle.Tensor) -> paddle.Tensor:\n    return xs\n\n\nif not hasattr(paddle.Tensor, 'contiguous'):\n    logger.debug(\n        \"override contiguous of paddle.Tensor if exists or register, remove this when fixed!\"\n    )\n    paddle.Tensor.contiguous = contiguous\n    paddle.static.Variable.contiguous = contiguous\n\n\ndef view(xs: paddle.Tensor, *args: int) -> paddle.Tensor:\n    return xs.reshape(args)\n\n\nif not hasattr(paddle.Tensor, 'view'):\n    logger.debug(\"register user view to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.view = view\n    paddle.static.Variable.view = view\n\n\ndef view_as(xs: paddle.Tensor, ys: paddle.Tensor) -> paddle.Tensor:\n    return xs.reshape(paddle.shape(ys))\n\n\nif not hasattr(paddle.Tensor, 'view_as'):\n    logger.debug(\n        \"register user view_as to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.view_as = view_as\n    paddle.static.Variable.view_as = view_as\n\n\ndef is_broadcastable(shp1, shp2):\n    for a, b in zip(shp1[::-1], shp2[::-1]):\n        if a == 1 or b == 1 or a == b:\n            pass\n        else:\n            return False\n    return True\n\n\ndef broadcast_shape(shp1, shp2):\n    result = []\n    for a, b in zip(shp1[::-1], shp2[::-1]):\n        result.append(max(a, b))\n    return result[::-1]\n\n\ndef masked_fill(xs: paddle.Tensor,\n                mask: paddle.Tensor,\n                value: Union[float, int]):\n    # will be nan when value is `inf`.\n    # mask = mask.astype(xs.dtype)\n    # return xs * (1.0 - mask) + mask * value\n\n    bshape = broadcast_shape(xs.shape, mask.shape)\n    mask.stop_gradient = True\n    # tmp = paddle.ones(shape=[len(bshape)], dtype='int32')\n    # for index in range(len(bshape)):\n    #     tmp[index] = bshape[index]\n    mask = mask.broadcast_to(bshape)\n    trues = paddle.full_like(xs, fill_value=value)\n    xs = paddle.where(mask, trues, xs)\n    return xs\n\n\nif not hasattr(paddle.Tensor, 'masked_fill'):\n    logger.debug(\n        \"register user masked_fill to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.masked_fill = masked_fill\n    paddle.static.Variable.masked_fill = masked_fill\n\n\ndef masked_fill_(xs: paddle.Tensor,\n                 mask: paddle.Tensor,\n                 value: Union[float, int]) -> paddle.Tensor:\n    assert is_broadcastable(xs.shape, mask.shape) is True\n    bshape = paddle.broadcast_shape(xs.shape, mask.shape)\n    mask = mask.broadcast_to(bshape)\n    trues = paddle.ones_like(xs) * value\n    ret = paddle.where(mask, trues, xs)\n    paddle.assign(ret.detach(), output=xs)\n    return xs\n\n\nif not hasattr(paddle.Tensor, 'masked_fill_'):\n    logger.debug(\n        \"register user masked_fill_ to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.masked_fill_ = masked_fill_\n    paddle.static.Variable.maksed_fill_ = masked_fill_\n\n\ndef fill_(xs: paddle.Tensor, value: Union[float, int]) -> paddle.Tensor:\n    val = paddle.full_like(xs, value)\n    paddle.assign(val.detach(), output=xs)\n    return xs\n\n\nif not hasattr(paddle.Tensor, 'fill_'):\n    logger.debug(\n        \"register user fill_ to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.fill_ = fill_\n    paddle.static.Variable.fill_ = fill_\n\n\ndef repeat(xs: paddle.Tensor, *size: Any) -> paddle.Tensor:\n    return paddle.tile(xs, size)\n\n\nif not hasattr(paddle.Tensor, 'repeat'):\n    logger.debug(\n        \"register user repeat to paddle.Tensor, remove this when fixed!\")\n    paddle.Tensor.repeat = repeat\n    paddle.static.Variable.repeat = repeat\n\nif not hasattr(paddle.Tensor, 'softmax'):\n    logger.debug(\n        \"register user softmax to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'softmax', paddle.nn.functional.softmax)\n\nif not hasattr(paddle.Tensor, 'sigmoid'):\n    logger.debug(\n        \"register user sigmoid to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'sigmoid', paddle.nn.functional.sigmoid)\n\nif not hasattr(paddle.Tensor, 'relu'):\n    logger.debug(\"register user relu to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'relu', paddle.nn.functional.relu)\n\n\ndef type_as(x: paddle.Tensor, other: paddle.Tensor) -> paddle.Tensor:\n    return x.astype(other.dtype)\n\n\nif not hasattr(paddle.Tensor, 'type_as'):\n    logger.debug(\n        \"register user type_as to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'type_as', type_as)\n    setattr(paddle.static.Variable, 'type_as', type_as)\n\n\ndef to(x: paddle.Tensor, *args, **kwargs) -> paddle.Tensor:\n    assert len(args) == 1\n    if isinstance(args[0], str):  # dtype\n        return x.astype(args[0])\n    elif isinstance(args[0], paddle.Tensor):  # Tensor\n        return x.astype(args[0].dtype)\n    else:  # Device\n        return x\n\n\nif not hasattr(paddle.Tensor, 'to'):\n    logger.debug(\"register user to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'to', to)\n    setattr(paddle.static.Variable, 'to', to)\n\n\ndef func_float(x: paddle.Tensor) -> paddle.Tensor:\n    return x.astype(paddle.float)\n\n\nif not hasattr(paddle.Tensor, 'float'):\n    logger.debug(\n        \"register user float to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'float', func_float)\n    setattr(paddle.static.Variable, 'float', func_float)\n\n\ndef func_int(x: paddle.Tensor) -> paddle.Tensor:\n    return x.astype(paddle.int)\n\n\nif not hasattr(paddle.Tensor, 'int'):\n    logger.debug(\"register user int to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'int', func_int)\n    setattr(paddle.static.Variable, 'int', func_int)\n\n\ndef tolist(x: paddle.Tensor) -> List[Any]:\n    return x.numpy().tolist()\n\n\nif not hasattr(paddle.Tensor, 'tolist'):\n    logger.debug(\n        \"register user tolist to paddle.Tensor, remove this when fixed!\")\n    setattr(paddle.Tensor, 'tolist', tolist)\n    setattr(paddle.static.Variable, 'tolist', tolist)\n\n########### hack paddle.nn #############\nfrom paddle.nn import Layer\nfrom typing import Optional\nfrom typing import Mapping\nfrom typing import Iterable\nfrom typing import Tuple\nfrom typing import Iterator\nfrom collections import OrderedDict, abc as container_abcs\n\n\nclass LayerDict(paddle.nn.Layer):\n    r\"\"\"Holds submodules in a dictionary.\n\n    :class:`~paddle.nn.LayerDict` can be indexed like a regular Python dictionary,\n    but modules it contains are properly registered, and will be visible by all\n    :class:`~paddle.nn.Layer` methods.\n\n    :class:`~paddle.nn.LayerDict` is an **ordered** dictionary that respects\n\n    * the order of insertion, and\n\n    * in :meth:`~paddle.nn.LayerDict.update`, the order of the merged\n      ``OrderedDict``, ``dict`` (started from Python 3.6) or another\n      :class:`~paddle.nn.LayerDict` (the argument to\n      :meth:`~paddle.nn.LayerDict.update`).\n\n    Note that :meth:`~paddle.nn.LayerDict.update` with other unordered mapping\n    types (e.g., Python's plain ``dict`` before Python version 3.6) does not\n    preserve the order of the merged mapping.\n\n    Args:\n        modules (iterable, optional): a mapping (dictionary) of (string: module)\n            or an iterable of key-value pairs of type (string, module)\n\n    Example::\n\n        class MyModule(nn.Layer):\n            def __init__(self):\n                super(MyModule, self).__init__()\n                self.choices = nn.LayerDict({\n                        'conv': nn.Conv2d(10, 10, 3),\n                        'pool': nn.MaxPool2d(3)\n                })\n                self.activations = nn.LayerDict([\n                        ['lrelu', nn.LeakyReLU()],\n                        ['prelu', nn.PReLU()]\n                ])\n\n            def forward(self, x, choice, act):\n                x = self.choices[choice](x)\n                x = self.activations[act](x)\n                return x\n    \"\"\"\n\n    def __init__(self, modules: Optional[Mapping[str, Layer]]=None) -> None:\n        super(LayerDict, self).__init__()\n        if modules is not None:\n            self.update(modules)\n\n    def __getitem__(self, key: str) -> Layer:\n        return self._modules[key]\n\n    def __setitem__(self, key: str, module: Layer) -> None:\n        self.add_module(key, module)\n\n    def __delitem__(self, key: str) -> None:\n        del self._modules[key]\n\n    def __len__(self) -> int:\n        return len(self._modules)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._modules)\n\n    def __contains__(self, key: str) -> bool:\n        return key in self._modules\n\n    def clear(self) -> None:\n        \"\"\"Remove all items from the LayerDict.\n        \"\"\"\n        self._modules.clear()\n\n    def pop(self, key: str) -> Layer:\n        r\"\"\"Remove key from the LayerDict and return its module.\n\n        Args:\n            key (string): key to pop from the LayerDict\n        \"\"\"\n        v = self[key]\n        del self[key]\n        return v\n\n    def keys(self) -> Iterable[str]:\n        r\"\"\"Return an iterable of the LayerDict keys.\n        \"\"\"\n        return self._modules.keys()\n\n    def items(self) -> Iterable[Tuple[str, Layer]]:\n        r\"\"\"Return an iterable of the LayerDict key/value pairs.\n        \"\"\"\n        return self._modules.items()\n\n    def values(self) -> Iterable[Layer]:\n        r\"\"\"Return an iterable of the LayerDict values.\n        \"\"\"\n        return self._modules.values()\n\n    def update(self, modules: Mapping[str, Layer]) -> None:\n        r\"\"\"Update the :class:`~paddle.nn.LayerDict` with the key-value pairs from a\n        mapping or an iterable, overwriting existing keys.\n\n        .. note::\n            If :attr:`modules` is an ``OrderedDict``, a :class:`~paddle.nn.LayerDict`, or\n            an iterable of key-value pairs, the order of new elements in it is preserved.\n\n        Args:\n            modules (iterable): a mapping (dictionary) from string to :class:`~paddle.nn.Layer`,\n                or an iterable of key-value pairs of type (string, :class:`~paddle.nn.Layer`)\n        \"\"\"\n        if not isinstance(modules, container_abcs.Iterable):\n            raise TypeError(\"LayerDict.update should be called with an \"\n                            \"iterable of key/value pairs, but got \" + type(\n                                modules).__name__)\n\n        if isinstance(modules,\n                      (OrderedDict, LayerDict, container_abcs.Mapping)):\n            for key, module in modules.items():\n                self[key] = module\n        else:\n            # modules here can be a list with two items\n            for j, m in enumerate(modules):\n                if not isinstance(m, container_abcs.Iterable):\n                    raise TypeError(\"LayerDict update sequence element \"\n                                    \"#\" + str(j) + \" should be Iterable; is\" +\n                                    type(m).__name__)\n                if not len(m) == 2:\n                    raise ValueError(\"LayerDict update sequence element \"\n                                     \"#\" + str(j) + \" has length \" + str(\n                                         len(m)) + \"; 2 is required\")\n                # modules can be Mapping (what it's typed at), or a list: [(name1, module1), (name2, module2)]\n                # that's too cumbersome to type correctly with overloads, so we add an ignore here\n                self[m[0]] = m[1]  # type: ignore[assignment]\n\n    # remove forward alltogether to fallback on Module's _forward_unimplemented\n\n\nif not hasattr(paddle.nn, 'LayerDict'):\n    logger.debug(\n        \"register user LayerDict to paddle.nn, remove this when fixed!\")\n    setattr(paddle.nn, 'LayerDict', LayerDict)\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/README.md",
    "content": "# Decoders\nwe borrow a lot of code from Espnet Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\n\n## Reference\n### CTC Prefix Beam Search\n* [Sequence Modeling With CTC](https://distill.pub/2017/ctc/)\n* [First-Pass Large Vocabulary Continuous Speech Recognition using Bi-Directional Recurrent DNNs](https://arxiv.org/pdf/1408.2873.pdf)\n\n### CTC Prefix Score & Join CTC/ATT One-passing Decoding\n* [Hybrid CTC/Attention Architecture for End-to-End Speech Recognition](http://www.ifp.illinois.edu/speech/speech_web_lg/slides/2019/watanabe_hybridCTCAttention_2017.pdf)\n* [Vectorized Beam Search for CTC-Attention-based Speech Recognition](https://www.isca-speech.org/archive/pdfs/interspeech_2019/seki19b_interspeech.pdf)\n\n### Streaming Join CTC/ATT Beam Search\n* [STREAMING TRANSFORMER ASR WITH BLOCKWISE SYNCHRONOUS BEAM SEARCH](https://arxiv.org/abs/2006.14941)\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/beam_search/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .batch_beam_search import BatchBeamSearch\nfrom .beam_search import beam_search\nfrom .beam_search import BeamSearch\nfrom .beam_search import Hypothesis\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/beam_search/batch_beam_search.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference espnet Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n\n\nclass BatchBeamSearch():\n    pass\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/beam_search/beam_search.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Beam search module.\"\"\"\nfrom itertools import chain\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import NamedTuple\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\n\nfrom ..scorers.scorer_interface import PartialScorerInterface\nfrom ..scorers.scorer_interface import ScorerInterface\nfrom ..utils import end_detect\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\nclass Hypothesis(NamedTuple):\n    \"\"\"Hypothesis data type.\"\"\"\n\n    yseq: paddle.Tensor  # (T,)\n    score: Union[float, paddle.Tensor] = 0\n    scores: Dict[str, Union[float, paddle.Tensor]] = dict()\n    states: Dict[str, Any] = dict()\n\n    def asdict(self) -> dict:\n        \"\"\"Convert data to JSON-friendly dict.\"\"\"\n        return self._replace(\n            yseq=self.yseq.tolist(),\n            score=float(self.score),\n            scores={k: float(v)\n                    for k, v in self.scores.items()}, )._asdict()\n\n\nclass BeamSearch(paddle.nn.Layer):\n    \"\"\"Beam search implementation.\"\"\"\n\n    def __init__(\n            self,\n            scorers: Dict[str, ScorerInterface],\n            weights: Dict[str, float],\n            beam_size: int,\n            vocab_size: int,\n            sos: int,\n            eos: int,\n            token_list: List[str]=None,\n            pre_beam_ratio: float=1.5,\n            pre_beam_score_key: str=None, ):\n        \"\"\"Initialize beam search.\n\n        Args:\n            scorers (dict[str, ScorerInterface]): Dict of decoder modules\n                e.g., Decoder, CTCPrefixScorer, LM\n                The scorer will be ignored if it is `None`\n            weights (dict[str, float]): Dict of weights for each scorers\n                The scorer will be ignored if its weight is 0\n            beam_size (int): The number of hypotheses kept during search\n            vocab_size (int): The number of vocabulary\n            sos (int): Start of sequence id\n            eos (int): End of sequence id\n            token_list (list[str]): List of tokens for debug log\n            pre_beam_score_key (str): key of scores to perform pre-beam search\n            pre_beam_ratio (float): beam size in the pre-beam search\n                will be `int(pre_beam_ratio * beam_size)`\n\n        \"\"\"\n        super().__init__()\n        # set scorers\n        self.weights = weights\n        self.scorers = dict()  # all = full + partial\n        self.full_scorers = dict()  # full tokens\n        self.part_scorers = dict()  # partial tokens\n        # this module dict is required for recursive cast\n        # `self.to(device, dtype)` in `recog.py`\n        self.nn_dict = paddle.nn.LayerDict()  # nn.Layer\n        for k, v in scorers.items():\n            w = weights.get(k, 0)\n            if w == 0 or v is None:\n                continue\n            assert isinstance(\n                v, ScorerInterface\n            ), f\"{k} ({type(v)}) does not implement ScorerInterface\"\n            self.scorers[k] = v\n            if isinstance(v, PartialScorerInterface):\n                self.part_scorers[k] = v\n            else:\n                self.full_scorers[k] = v\n            if isinstance(v, paddle.nn.Layer):\n                self.nn_dict[k] = v\n\n        # set configurations\n        self.sos = sos\n        self.eos = eos\n        self.token_list = token_list\n        # pre_beam_size > beam_size\n        self.pre_beam_size = int(pre_beam_ratio * beam_size)\n        self.beam_size = beam_size\n        self.n_vocab = vocab_size\n        if (pre_beam_score_key is not None and pre_beam_score_key != \"full\" and\n                pre_beam_score_key not in self.full_scorers):\n            raise KeyError(\n                f\"{pre_beam_score_key} is not found in {self.full_scorers}\")\n        # selected `key` scorer to do pre beam search\n        self.pre_beam_score_key = pre_beam_score_key\n        # do_pre_beam when need, valid and has part_scorers\n        self.do_pre_beam = (self.pre_beam_score_key is not None and\n                            self.pre_beam_size < self.n_vocab and\n                            len(self.part_scorers) > 0)\n\n    def init_hyp(self, x: paddle.Tensor) -> List[Hypothesis]:\n        \"\"\"Get an initial hypothesis data.\n\n        Args:\n            x (paddle.Tensor): The encoder output feature, (T, D)\n\n        Returns:\n            Hypothesis: The initial hypothesis.\n\n        \"\"\"\n        init_states = dict()\n        init_scores = dict()\n        for k, d in self.scorers.items():\n            init_states[k] = d.init_state(x)\n            init_scores[k] = 0.0\n        return [\n            Hypothesis(\n                yseq=paddle.to_tensor([self.sos], place=x.place),\n                score=0.0,\n                scores=init_scores,\n                states=init_states, )\n        ]\n\n    @staticmethod\n    def append_token(xs: paddle.Tensor,\n                     x: Union[int, paddle.Tensor]) -> paddle.Tensor:\n        \"\"\"Append new token to prefix tokens.\n\n        Args:\n            xs (paddle.Tensor): The prefix token, (T,)\n            x (int): The new token to append\n\n        Returns:\n            paddle.Tensor: (T+1,), New tensor contains: xs + [x] with xs.dtype and xs.device\n\n        \"\"\"\n        x = paddle.to_tensor([x], dtype=xs.dtype) if isinstance(x, int) else x\n        return paddle.concat((xs, x))\n\n    def score_full(self, hyp: Hypothesis, x: paddle.Tensor\n                   ) -> Tuple[Dict[str, paddle.Tensor], Dict[str, Any]]:\n        \"\"\"Score new hypothesis by `self.full_scorers`.\n\n        Args:\n            hyp (Hypothesis): Hypothesis with prefix tokens to score\n            x (paddle.Tensor): Corresponding input feature, (T, D)\n\n        Returns:\n            Tuple[Dict[str, paddle.Tensor], Dict[str, Any]]: Tuple of\n                score dict of `hyp` that has string keys of `self.full_scorers`\n                and tensor score values of shape: `(self.n_vocab,)`,\n                and state dict that has string keys\n                and state values of `self.full_scorers`\n\n        \"\"\"\n        scores = dict()\n        states = dict()\n        for k, d in self.full_scorers.items():\n            # scores[k] shape (self.n_vocab,)\n            scores[k], states[k] = d.score(hyp.yseq, hyp.states[k], x)\n        return scores, states\n\n    def score_partial(self,\n                      hyp: Hypothesis,\n                      ids: paddle.Tensor,\n                      x: paddle.Tensor\n                      ) -> Tuple[Dict[str, paddle.Tensor], Dict[str, Any]]:\n        \"\"\"Score new hypothesis by `self.part_scorers`.\n\n        Args:\n            hyp (Hypothesis): Hypothesis with prefix tokens to score\n            ids (paddle.Tensor): 1D tensor of new partial tokens to score,\n                len(ids) < n_vocab\n            x (paddle.Tensor): Corresponding input feature, (T, D)\n\n        Returns:\n            Tuple[Dict[str, paddle.Tensor], Dict[str, Any]]: Tuple of\n                score dict of `hyp` that has string keys of `self.part_scorers`\n                and tensor score values of shape: `(len(ids),)`,\n                and state dict that has string keys\n                and state values of `self.part_scorers`\n\n        \"\"\"\n        scores = dict()\n        states = dict()\n        for k, d in self.part_scorers.items():\n            # scores[k] shape (len(ids),)\n            scores[k], states[k] = d.score_partial(hyp.yseq, ids, hyp.states[k],\n                                                   x)\n        return scores, states\n\n    def beam(self, weighted_scores: paddle.Tensor,\n             ids: paddle.Tensor) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute topk full token ids and partial token ids.\n\n        Args:\n            weighted_scores (paddle.Tensor): The weighted sum scores for each tokens.\n                Its shape is `(self.n_vocab,)`.\n            ids (paddle.Tensor): The partial token ids(Global) to compute topk.\n\n        Returns:\n            Tuple[paddle.Tensor, paddle.Tensor]:\n                The topk full token ids and partial token ids.\n                Their shapes are `(self.beam_size,)`.\n                i.e. (global ids, global relative local ids).\n\n        \"\"\"\n        # no pre beam performed, `ids` equal to `weighted_scores`\n        if paddle.shape(weighted_scores)[0] == paddle.shape(ids)[0]:\n            top_ids = weighted_scores.topk(\n                self.beam_size)[1]  # index in n_vocab\n            return top_ids, top_ids\n\n        # mask pruned in pre-beam not to select in topk\n        tmp = weighted_scores[ids]\n        weighted_scores[:] = -float(\"inf\")\n        weighted_scores[ids] = tmp\n        # top_ids no equal to local_ids, since ids shape not same\n        top_ids = weighted_scores.topk(self.beam_size)[1]  # index in n_vocab\n        local_ids = weighted_scores[ids].topk(\n            self.beam_size)[1]  # index in len(ids)\n        return top_ids, local_ids\n\n    @staticmethod\n    def merge_scores(\n            prev_scores: Dict[str, float],\n            next_full_scores: Dict[str, paddle.Tensor],\n            full_idx: int,\n            next_part_scores: Dict[str, paddle.Tensor],\n            part_idx: int, ) -> Dict[str, paddle.Tensor]:\n        \"\"\"Merge scores for new hypothesis.\n\n        Args:\n            prev_scores (Dict[str, float]):\n                The previous hypothesis scores by `self.scorers`\n            next_full_scores (Dict[str, paddle.Tensor]): scores by `self.full_scorers`\n            full_idx (int): The next token id for `next_full_scores`\n            next_part_scores (Dict[str, paddle.Tensor]):\n                scores of partial tokens by `self.part_scorers`\n            part_idx (int): The new token id for `next_part_scores`\n\n        Returns:\n            Dict[str, paddle.Tensor]: The new score dict.\n                Its keys are names of `self.full_scorers` and `self.part_scorers`.\n                Its values are scalar tensors by the scorers.\n\n        \"\"\"\n        new_scores = dict()\n        for k, v in next_full_scores.items():\n            new_scores[k] = prev_scores[k] + v[full_idx]\n        for k, v in next_part_scores.items():\n            new_scores[k] = prev_scores[k] + v[part_idx]\n        return new_scores\n\n    def merge_states(self, states: Any, part_states: Any, part_idx: int) -> Any:\n        \"\"\"Merge states for new hypothesis.\n\n        Args:\n            states: states of `self.full_scorers`\n            part_states: states of `self.part_scorers`\n            part_idx (int): The new token id for `part_scores`\n\n        Returns:\n            Dict[str, paddle.Tensor]: The new score dict.\n                Its keys are names of `self.full_scorers` and `self.part_scorers`.\n                Its values are states of the scorers.\n\n        \"\"\"\n        new_states = dict()\n        for k, v in states.items():\n            new_states[k] = v\n        for k, d in self.part_scorers.items():\n            new_states[k] = d.select_state(part_states[k], part_idx)\n        return new_states\n\n    def search(self, running_hyps: List[Hypothesis],\n               x: paddle.Tensor) -> List[Hypothesis]:\n        \"\"\"Search new tokens for running hypotheses and encoded speech x.\n\n        Args:\n            running_hyps (List[Hypothesis]): Running hypotheses on beam\n            x (paddle.Tensor): Encoded speech feature (T, D)\n\n        Returns:\n            List[Hypotheses]: Best sorted hypotheses\n\n        \"\"\"\n        best_hyps = []\n        part_ids = paddle.arange(self.n_vocab)  # no pre-beam\n        for hyp in running_hyps:\n            # scoring\n            weighted_scores = paddle.zeros([self.n_vocab], dtype=x.dtype)\n            scores, states = self.score_full(hyp, x)\n            for k in self.full_scorers:\n                weighted_scores += self.weights[k] * scores[k]\n            # partial scoring\n            if self.do_pre_beam:\n                pre_beam_scores = (weighted_scores\n                                   if self.pre_beam_score_key == \"full\" else\n                                   scores[self.pre_beam_score_key])\n                part_ids = paddle.topk(pre_beam_scores, self.pre_beam_size)[1]\n            part_scores, part_states = self.score_partial(hyp, part_ids, x)\n            for k in self.part_scorers:\n                weighted_scores[part_ids] += self.weights[k] * part_scores[k]\n            # add previous hyp score\n            weighted_scores += hyp.score\n\n            # update hyps\n            for j, part_j in zip(*self.beam(weighted_scores, part_ids)):\n                # `part_j` is `j` relative id in `part_scores`\n                # will be (2 x beam at most)\n                best_hyps.append(\n                    Hypothesis(\n                        score=weighted_scores[j],\n                        yseq=self.append_token(hyp.yseq, j),\n                        scores=self.merge_scores(hyp.scores, scores, j,\n                                                 part_scores, part_j),\n                        states=self.merge_states(states, part_states, part_j),\n                    ))\n\n            # sort and prune 2 x beam -> beam\n            best_hyps = sorted(\n                best_hyps, key=lambda x: x.score,\n                reverse=True)[:min(len(best_hyps), self.beam_size)]\n        return best_hyps\n\n    def forward(self,\n                x: paddle.Tensor,\n                maxlenratio: float=0.0,\n                minlenratio: float=0.0) -> List[Hypothesis]:\n        \"\"\"Perform beam search.\n\n        Args:\n            x (paddle.Tensor): Encoded speech feature (T, D)\n            maxlenratio (float): Input length ratio to obtain max output length.\n                If maxlenratio=0.0 (default), it uses a end-detect function\n                    to automatically find maximum hypothesis lengths\n                If maxlenratio<0.0, its absolute value is interpreted\n                    as a constant max output length.\n            minlenratio (float): Input length ratio to obtain min output length.\n\n        Returns:\n            list[Hypothesis]: N-best decoding results\n\n        \"\"\"\n        # set length bounds\n        if maxlenratio == 0:\n            maxlen = paddle.shape(x)[0]\n        elif maxlenratio < 0:\n            maxlen = -1 * int(maxlenratio)\n        else:\n            maxlen = max(1, int(maxlenratio * paddle.shape(x)[0]))\n        minlen = int(minlenratio * paddle.shape(x)[0])\n        logger.info(\"decoder input length: \" + str(paddle.shape(x)[0]))\n        logger.info(\"max output length: \" + str(maxlen))\n        logger.info(\"min output length: \" + str(minlen))\n\n        # main loop of prefix search\n        running_hyps = self.init_hyp(x)\n        ended_hyps = []\n        for i in range(maxlen):\n            logger.debug(\"position \" + str(i))\n            best = self.search(running_hyps, x)\n            # post process of one iteration\n            running_hyps = self.post_process(i, maxlen, maxlenratio, best,\n                                             ended_hyps)\n            # end detection\n            if maxlenratio == 0.0 and end_detect(\n                [h.asdict() for h in ended_hyps], i):\n                logger.info(f\"end detected at {i}\")\n                break\n            if len(running_hyps) == 0:\n                logger.info(\"no hypothesis. Finish decoding.\")\n                break\n            else:\n                logger.debug(f\"remained hypotheses: {len(running_hyps)}\")\n\n        nbest_hyps = sorted(ended_hyps, key=lambda x: x.score, reverse=True)\n        # check the number of hypotheses reaching to eos\n        if len(nbest_hyps) == 0:\n            logger.warning(\"there is no N-best results, perform recognition \"\n                           \"again with smaller minlenratio.\")\n            return ([] if minlenratio < 0.1 else\n                    self.forward(x, maxlenratio, max(0.0, minlenratio - 0.1)))\n\n        # report the best result\n        best = nbest_hyps[0]\n        for k, v in best.scores.items():\n            logger.info(\n                f\"{float(v):6.2f} * {self.weights[k]:3} = {float(v) * self.weights[k]:6.2f} for {k}\"\n            )\n        logger.info(f\"total log probability: {float(best.score):.2f}\")\n        logger.info(\n            f\"normalized log probability: {float(best.score) / len(best.yseq):.2f}\"\n        )\n        logger.info(f\"total number of ended hypotheses: {len(nbest_hyps)}\")\n        if self.token_list is not None:\n            # logger.info(\n            #     \"best hypo: \"\n            #     + \"\".join([self.token_list[x] for x in best.yseq[1:-1]])\n            #     + \"\\n\"\n            # )\n            logger.info(\"best hypo: \" + \"\".join(\n                [self.token_list[x] for x in best.yseq[1:]]) + \"\\n\")\n        return nbest_hyps\n\n    def post_process(\n            self,\n            i: int,\n            maxlen: int,\n            maxlenratio: float,\n            running_hyps: List[Hypothesis],\n            ended_hyps: List[Hypothesis], ) -> List[Hypothesis]:\n        \"\"\"Perform post-processing of beam search iterations.\n\n        Args:\n            i (int): The length of hypothesis tokens.\n            maxlen (int): The maximum length of tokens in beam search.\n            maxlenratio (int): The maximum length ratio in beam search.\n            running_hyps (List[Hypothesis]): The running hypotheses in beam search.\n            ended_hyps (List[Hypothesis]): The ended hypotheses in beam search.\n\n        Returns:\n            List[Hypothesis]: The new running hypotheses.\n\n        \"\"\"\n        logger.debug(f\"the number of running hypotheses: {len(running_hyps)}\")\n        if self.token_list is not None:\n            logger.debug(\"best hypo: \" + \"\".join(\n                [self.token_list[x] for x in running_hyps[0].yseq[1:]]))\n        # add eos in the final loop to avoid that there are no ended hyps\n        if i == maxlen - 1:\n            logger.info(\"adding <eos> in the last position in the loop\")\n            running_hyps = [\n                h._replace(yseq=self.append_token(h.yseq, self.eos))\n                for h in running_hyps\n            ]\n\n        # add ended hypotheses to a final list, and removed them from current hypotheses\n        # (this will be a problem, number of hyps < beam)\n        remained_hyps = []\n        for hyp in running_hyps:\n            if hyp.yseq[-1] == self.eos:\n                # e.g., Word LM needs to add final <eos> score\n                for k, d in chain(self.full_scorers.items(),\n                                  self.part_scorers.items()):\n                    s = d.final_score(hyp.states[k])\n                    hyp.scores[k] += s\n                    hyp = hyp._replace(score=hyp.score + self.weights[k] * s)\n                ended_hyps.append(hyp)\n            else:\n                remained_hyps.append(hyp)\n        return remained_hyps\n\n\ndef beam_search(\n        x: paddle.Tensor,\n        sos: int,\n        eos: int,\n        beam_size: int,\n        vocab_size: int,\n        scorers: Dict[str, ScorerInterface],\n        weights: Dict[str, float],\n        token_list: List[str]=None,\n        maxlenratio: float=0.0,\n        minlenratio: float=0.0,\n        pre_beam_ratio: float=1.5,\n        pre_beam_score_key: str=\"full\", ) -> list:\n    \"\"\"Perform beam search with scorers.\n\n    Args:\n        x (paddle.Tensor): Encoded speech feature (T, D)\n        sos (int): Start of sequence id\n        eos (int): End of sequence id\n        beam_size (int): The number of hypotheses kept during search\n        vocab_size (int): The number of vocabulary\n        scorers (dict[str, ScorerInterface]): Dict of decoder modules\n            e.g., Decoder, CTCPrefixScorer, LM\n            The scorer will be ignored if it is `None`\n        weights (dict[str, float]): Dict of weights for each scorers\n            The scorer will be ignored if its weight is 0\n        token_list (list[str]): List of tokens for debug log\n        maxlenratio (float): Input length ratio to obtain max output length.\n            If maxlenratio=0.0 (default), it uses a end-detect function\n            to automatically find maximum hypothesis lengths\n        minlenratio (float): Input length ratio to obtain min output length.\n        pre_beam_score_key (str): key of scores to perform pre-beam search\n        pre_beam_ratio (float): beam size in the pre-beam search\n            will be `int(pre_beam_ratio * beam_size)`\n\n    Returns:\n        List[Dict]: N-best decoding results\n\n    \"\"\"\n    ret = BeamSearch(\n        scorers,\n        weights,\n        beam_size=beam_size,\n        vocab_size=vocab_size,\n        pre_beam_ratio=pre_beam_ratio,\n        pre_beam_score_key=pre_beam_score_key,\n        sos=sos,\n        eos=eos,\n        token_list=token_list, ).forward(\n            x=x, maxlenratio=maxlenratio, minlenratio=minlenratio)\n    return [h.asdict() for h in ret]\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/ctcdecoder/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .swig_wrapper import ctc_beam_search_decoding\nfrom .swig_wrapper import ctc_beam_search_decoding_batch\nfrom .swig_wrapper import ctc_greedy_decoding\nfrom .swig_wrapper import CTCBeamSearchDecoder\nfrom .swig_wrapper import Scorer\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/ctcdecoder/decoders_deprecated.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains various CTC decoders.\"\"\"\nimport multiprocessing\nfrom itertools import groupby\nfrom math import log\n\nimport numpy as np\n\n\ndef ctc_greedy_decoder(probs_seq, vocabulary):\n    \"\"\"CTC greedy (best path) decoder.\n\n    Path consisting of the most probable tokens are further post-processed to\n    remove consecutive repetitions and all blanks.\n\n    :param probs_seq: 2-D list of probabilities over the vocabulary for each\n                      character. Each element is a list of float probabilities\n                      for one character.\n    :type probs_seq: list\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :return: Decoding result string.\n    :rtype: baseline\n    \"\"\"\n    # dimension verification\n    for probs in probs_seq:\n        if not len(probs) == len(vocabulary) + 1:\n            raise ValueError(\"probs_seq dimension mismatchedd with vocabulary\")\n    # argmax to get the best index for each time step\n    max_index_list = list(np.array(probs_seq).argmax(axis=1))\n    # remove consecutive duplicate indexes\n    index_list = [index_group[0] for index_group in groupby(max_index_list)]\n    # remove blank indexes\n    blank_index = len(vocabulary)\n    index_list = [index for index in index_list if index != blank_index]\n    # convert index list to string\n    return ''.join([vocabulary[index] for index in index_list])\n\n\ndef ctc_beam_search_decoder(probs_seq,\n                            beam_size,\n                            vocabulary,\n                            cutoff_prob=1.0,\n                            cutoff_top_n=40,\n                            ext_scoring_func=None,\n                            nproc=False):\n    \"\"\"CTC Beam search decoder.\n\n    It utilizes beam search to approximately select top best decoding\n    labels and returning results in the descending order.\n    The implementation is based on Prefix Beam Search\n    (https://arxiv.org/abs/1408.2873), and the unclear part is\n    redesigned. Two important modifications: 1) in the iterative computation\n    of probabilities, the assignment operation is changed to accumulation for\n    one prefix may comes from different paths; 2) the if condition \"if l^+ not\n    in A_prev then\" after probabilities' computation is deprecated for it is\n    hard to understand and seems unnecessary.\n\n    :param probs_seq: 2-D list of probability distributions over each time\n                      step, with each element being a list of normalized\n                      probabilities over vocabulary and blank.\n    :type probs_seq: 2-D list\n    :param beam_size: Width for beam search.\n    :type beam_size: int\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :param cutoff_prob: Cutoff probability in pruning,\n                        default 1.0, no pruning.\n    :type cutoff_prob: float\n    :param ext_scoring_func: External scoring function for\n                            partially decoded sentence, e.g. word count\n                            or language model.\n    :type external_scoring_func: callable\n    :param nproc: Whether the decoder used in multiprocesses.\n    :type nproc: bool\n    :return: List of tuples of log probability and sentence as decoding\n             results, in descending order of the probability.\n    :rtype: list\n    \"\"\"\n    # dimension check\n    for prob_list in probs_seq:\n        if not len(prob_list) == len(vocabulary) + 1:\n            raise ValueError(\"The shape of prob_seq does not match with the \"\n                             \"shape of the vocabulary.\")\n\n    # blank_id assign\n    blank_id = len(vocabulary)\n\n    # If the decoder called in the multiprocesses, then use the global scorer\n    # instantiated in ctc_beam_search_decoder_batch().\n    if nproc is True:\n        global ext_nproc_scorer\n        ext_scoring_func = ext_nproc_scorer\n\n    # initialize\n    # prefix_set_prev: the set containing selected prefixes\n    # probs_b_prev: prefixes' probability ending with blank in previous step\n    # probs_nb_prev: prefixes' probability ending with non-blank in previous step\n    prefix_set_prev = {'\\t': 1.0}\n    probs_b_prev, probs_nb_prev = {'\\t': 1.0}, {'\\t': 0.0}\n\n    # extend prefix in loop\n    for time_step in range(len(probs_seq)):\n        # prefix_set_next: the set containing candidate prefixes\n        # probs_b_cur: prefixes' probability ending with blank in current step\n        # probs_nb_cur: prefixes' probability ending with non-blank in current step\n        prefix_set_next, probs_b_cur, probs_nb_cur = {}, {}, {}\n\n        prob_idx = list(enumerate(probs_seq[time_step]))\n        cutoff_len = len(prob_idx)\n        # If pruning is enabled\n        if cutoff_prob < 1.0 or cutoff_top_n < cutoff_len:\n            prob_idx = sorted(prob_idx, key=lambda asd: asd[1], reverse=True)\n            cutoff_len, cum_prob = 0, 0.0\n            for i in range(len(prob_idx)):\n                cum_prob += prob_idx[i][1]\n                cutoff_len += 1\n                if cum_prob >= cutoff_prob:\n                    break\n            cutoff_len = min(cutoff_len, cutoff_top_n)\n            prob_idx = prob_idx[0:cutoff_len]\n\n        for l in prefix_set_prev:\n            if l not in prefix_set_next:\n                probs_b_cur[l], probs_nb_cur[l] = 0.0, 0.0\n\n            # extend prefix by travering prob_idx\n            for index in range(cutoff_len):\n                c, prob_c = prob_idx[index][0], prob_idx[index][1]\n\n                if c == blank_id:\n                    probs_b_cur[l] += prob_c * (\n                        probs_b_prev[l] + probs_nb_prev[l])\n                else:\n                    last_char = l[-1]\n                    new_char = vocabulary[c]\n                    l_plus = l + new_char\n                    if l_plus not in prefix_set_next:\n                        probs_b_cur[l_plus], probs_nb_cur[l_plus] = 0.0, 0.0\n\n                    if new_char == last_char:\n                        probs_nb_cur[l_plus] += prob_c * probs_b_prev[l]\n                        probs_nb_cur[l] += prob_c * probs_nb_prev[l]\n                    elif new_char == ' ':\n                        if (ext_scoring_func is None) or (len(l) == 1):\n                            score = 1.0\n                        else:\n                            prefix = l[1:]\n                            score = ext_scoring_func(prefix)\n                        probs_nb_cur[l_plus] += score * prob_c * (\n                            probs_b_prev[l] + probs_nb_prev[l])\n                    else:\n                        probs_nb_cur[l_plus] += prob_c * (\n                            probs_b_prev[l] + probs_nb_prev[l])\n                    # add l_plus into prefix_set_next\n                    prefix_set_next[l_plus] = probs_nb_cur[\n                        l_plus] + probs_b_cur[l_plus]\n            # add l into prefix_set_next\n            prefix_set_next[l] = probs_b_cur[l] + probs_nb_cur[l]\n        # update probs\n        probs_b_prev, probs_nb_prev = probs_b_cur, probs_nb_cur\n\n        # store top beam_size prefixes\n        prefix_set_prev = sorted(\n            prefix_set_next.items(), key=lambda asd: asd[1], reverse=True)\n        if beam_size < len(prefix_set_prev):\n            prefix_set_prev = prefix_set_prev[:beam_size]\n        prefix_set_prev = dict(prefix_set_prev)\n\n    beam_result = []\n    for seq, prob in prefix_set_prev.items():\n        if prob > 0.0 and len(seq) > 1:\n            result = seq[1:]\n            # score last word by external scorer\n            if (ext_scoring_func is not None) and (result[-1] != ' '):\n                prob = prob * ext_scoring_func(result)\n            log_prob = log(prob)\n            beam_result.append((log_prob, result))\n        else:\n            beam_result.append((float('-inf'), ''))\n\n    # output top beam_size decoding results\n    beam_result = sorted(beam_result, key=lambda asd: asd[0], reverse=True)\n    return beam_result\n\n\ndef ctc_beam_search_decoder_batch(probs_split,\n                                  beam_size,\n                                  vocabulary,\n                                  num_processes,\n                                  cutoff_prob=1.0,\n                                  cutoff_top_n=40,\n                                  ext_scoring_func=None):\n    \"\"\"CTC beam search decoder using multiple processes.\n\n    :param probs_seq: 3-D list with each element as an instance of 2-D list\n                      of probabilities used by ctc_beam_search_decoder().\n    :type probs_seq: 3-D list\n    :param beam_size: Width for beam search.\n    :type beam_size: int\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :param num_processes: Number of parallel processes.\n    :type num_processes: int\n    :param cutoff_prob: Cutoff probability in pruning,\n                        default 1.0, no pruning.\n    :type cutoff_prob: float\n    :param num_processes: Number of parallel processes.\n    :type num_processes: int\n    :param ext_scoring_func: External scoring function for\n                            partially decoded sentence, e.g. word count\n                            or language model.\n    :type external_scoring_function: callable\n    :return: List of tuples of log probability and sentence as decoding\n             results, in descending order of the probability.\n    :rtype: list\n    \"\"\"\n    if not num_processes > 0:\n        raise ValueError(\"Number of processes must be positive!\")\n\n    # use global variable to pass the externnal scorer to beam search decoder\n    global ext_nproc_scorer\n    ext_nproc_scorer = ext_scoring_func\n    nproc = True\n\n    pool = multiprocessing.Pool(processes=num_processes)\n    results = []\n    for i, probs_list in enumerate(probs_split):\n        args = (probs_list, beam_size, vocabulary, cutoff_prob, cutoff_top_n,\n                None, nproc)\n        results.append(pool.apply_async(ctc_beam_search_decoder, args))\n\n    pool.close()\n    pool.join()\n    beam_search_results = [result.get() for result in results]\n    return beam_search_results\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/ctcdecoder/scorer_deprecated.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"External Scorer for Beam Search Decoder.\"\"\"\nimport os\n\nimport kenlm\nimport numpy as np\n\n\nclass Scorer(object):\n    \"\"\"External scorer to evaluate a prefix or whole sentence in\n       beam search decoding, including the score from n-gram language\n       model and word count.\n\n    :param alpha: Parameter associated with language model. Don't use\n                  language model when alpha = 0.\n    :type alpha: float\n    :param beta: Parameter associated with word count. Don't use word\n                count when beta = 0.\n    :type beta: float\n    :model_path: Path to load language model.\n    :type model_path: str\n    \"\"\"\n\n    def __init__(self, alpha, beta, model_path):\n        self._alpha = alpha\n        self._beta = beta\n        if not os.path.isfile(model_path):\n            raise IOError(\"Invaid language model path: %s\" % model_path)\n        self._language_model = kenlm.LanguageModel(model_path)\n\n    # n-gram language model scoring\n    def _language_model_score(self, sentence):\n        #log10 prob of last word\n        log_cond_prob = list(\n            self._language_model.full_scores(sentence, eos=False))[-1][0]\n        return np.power(10, log_cond_prob)\n\n    # word insertion term\n    def _word_count(self, sentence):\n        words = sentence.strip().split(' ')\n        return len(words)\n\n    # reset alpha and beta\n    def reset_params(self, alpha, beta):\n        self._alpha = alpha\n        self._beta = beta\n\n    # execute evaluation\n    def __call__(self, sentence, log=False):\n        \"\"\"Evaluation function, gathering all the different scores\n        and return the final one.\n\n        :param sentence: The input sentence for evaluation\n        :type sentence: str\n        :param log: Whether return the score in log representation.\n        :type log: bool\n        :return: Evaluation score, in the decimal or log.\n        :rtype: float\n        \"\"\"\n        lm = self._language_model_score(sentence)\n        word_cnt = self._word_count(sentence)\n        if log is False:\n            score = np.power(lm, self._alpha) * np.power(word_cnt, self._beta)\n        else:\n            score = self._alpha * np.log(lm) + self._beta * np.log(word_cnt)\n        return score\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/ctcdecoder/swig_wrapper.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Wrapper for various CTC decoders in SWIG.\"\"\"\nimport paddlespeech_ctcdecoders\n\n\nclass Scorer(paddlespeech_ctcdecoders.Scorer):\n    \"\"\"Wrapper for Scorer.\n\n    :param alpha: Parameter associated with language model. Don't use\n                  language model when alpha = 0.\n    :type alpha: float\n    :param beta: Parameter associated with word count. Don't use word\n                 count when beta = 0.\n    :type beta: float\n    :model_path: Path to load language model.\n    :type model_path: str\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    \"\"\"\n\n    def __init__(self, alpha, beta, model_path, vocabulary):\n        paddlespeech_ctcdecoders.Scorer.__init__(self, alpha, beta, model_path,\n                                                 vocabulary)\n\n\ndef ctc_greedy_decoding(probs_seq, vocabulary, blank_id):\n    \"\"\"Wrapper for ctc best path decodeing function in swig.\n\n    :param probs_seq: 2-D list of probability distributions over each time\n                      step, with each element being a list of normalized\n                      probabilities over vocabulary and blank.\n    :type probs_seq: 2-D list\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :return: Decoding result string.\n    :rtype: str\n    \"\"\"\n    result = paddlespeech_ctcdecoders.ctc_greedy_decoding(probs_seq.tolist(),\n                                                          vocabulary, blank_id)\n    return result\n\n\ndef ctc_beam_search_decoding(probs_seq,\n                             vocabulary,\n                             beam_size,\n                             cutoff_prob=1.0,\n                             cutoff_top_n=40,\n                             ext_scoring_func=None,\n                             blank_id=0):\n    \"\"\"Wrapper for the CTC Beam Search Decoding function.\n\n    :param probs_seq: 2-D list of probability distributions over each time\n                      step, with each element being a list of normalized\n                      probabilities over vocabulary and blank.\n    :type probs_seq: 2-D list\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :param beam_size: Width for beam search.\n    :type beam_size: int\n    :param cutoff_prob: Cutoff probability in pruning,\n                        default 1.0, no pruning.\n    :type cutoff_prob: float\n    :param cutoff_top_n: Cutoff number in pruning, only top cutoff_top_n\n                         characters with highest probs in vocabulary will be\n                         used in beam search, default 40.\n    :type cutoff_top_n: int\n    :param ext_scoring_func: External scoring function for\n                             partially decoded sentence, e.g. word count\n                             or language model.\n    :type external_scoring_func: callable\n    :return: List of tuples of log probability and sentence as decoding\n             results, in descending order of the probability.\n    :rtype: list\n    \"\"\"\n    beam_results = paddlespeech_ctcdecoders.ctc_beam_search_decoding(\n        probs_seq.tolist(), vocabulary, beam_size, cutoff_prob, cutoff_top_n,\n        ext_scoring_func, blank_id)\n    beam_results = [(res[0], res[1].decode('utf-8')) for res in beam_results]\n    return beam_results\n\n\ndef ctc_beam_search_decoding_batch(probs_split,\n                                   vocabulary,\n                                   beam_size,\n                                   num_processes,\n                                   cutoff_prob=1.0,\n                                   cutoff_top_n=40,\n                                   ext_scoring_func=None,\n                                   blank_id=0):\n    \"\"\"Wrapper for the batched CTC beam search decodeing batch function.\n\n    :param probs_seq: 3-D list with each element as an instance of 2-D list\n                      of probabilities used by ctc_beam_search_decoder().\n    :type probs_seq: 3-D list\n    :param vocabulary: Vocabulary list.\n    :type vocabulary: list\n    :param beam_size: Width for beam search.\n    :type beam_size: int\n    :param num_processes: Number of parallel processes.\n    :type num_processes: int\n    :param cutoff_prob: Cutoff probability in vocabulary pruning,\n                        default 1.0, no pruning.\n    :type cutoff_prob: float\n    :param cutoff_top_n: Cutoff number in pruning, only top cutoff_top_n\n                         characters with highest probs in vocabulary will be\n                         used in beam search, default 40.\n    :type cutoff_top_n: int\n    :param num_processes: Number of parallel processes.\n    :type num_processes: int\n    :param ext_scoring_func: External scoring function for\n                             partially decoded sentence, e.g. word count\n                             or language model.\n    :type external_scoring_function: callable\n    :return: List of tuples of log probability and sentence as decoding\n             results, in descending order of the probability.\n    :rtype: list\n    \"\"\"\n    probs_split = [probs_seq.tolist() for probs_seq in probs_split]\n\n    batch_beam_results = paddlespeech_ctcdecoders.ctc_beam_search_decoding_batch(\n        probs_split, vocabulary, beam_size, num_processes, cutoff_prob,\n        cutoff_top_n, ext_scoring_func, blank_id)\n    batch_beam_results = [[(res[0], res[1]) for res in beam_results]\n                          for beam_results in batch_beam_results]\n    return batch_beam_results\n\n\nclass CTCBeamSearchDecoder(paddlespeech_ctcdecoders.CtcBeamSearchDecoderBatch):\n    \"\"\"Wrapper for CtcBeamSearchDecoderBatch.\n    Args:\n        vocab_list (list): Vocabulary list.\n        beam_size (int): Width for beam search.\n        num_processes (int): Number of parallel processes.\n        param cutoff_prob (float): Cutoff probability in vocabulary pruning,\n                            default 1.0, no pruning.\n        cutoff_top_n (int): Cutoff number in pruning, only top cutoff_top_n\n                            characters with highest probs in vocabulary will be\n                            used in beam search, default 40.\n        param ext_scorer (Scorer): External scorer for partially decoded sentence, e.g. word count\n                                or language model.\n    \"\"\"\n\n    def __init__(self, vocab_list, batch_size, beam_size, num_processes,\n                 cutoff_prob, cutoff_top_n, _ext_scorer, blank_id):\n        paddlespeech_ctcdecoders.CtcBeamSearchDecoderBatch.__init__(\n            self, vocab_list, batch_size, beam_size, num_processes, cutoff_prob,\n            cutoff_top_n, _ext_scorer, blank_id)\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/ctcdecoder/tests/test_decoders.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Test decoders.\"\"\"\nimport unittest\n\nfrom paddlespeech.s2t.decoders import decoders_deprecated as decoder\n\n\nclass TestDecoders(unittest.TestCase):\n    def setUp(self):\n        self.vocab_list = [\"\\'\", ' ', 'a', 'b', 'c', 'd']\n        self.beam_size = 20\n        self.probs_seq1 = [[\n            0.06390443, 0.21124858, 0.27323887, 0.06870235, 0.0361254,\n            0.18184413, 0.16493624\n        ], [\n            0.03309247, 0.22866108, 0.24390638, 0.09699597, 0.31895462,\n            0.0094893, 0.06890021\n        ], [\n            0.218104, 0.19992557, 0.18245131, 0.08503348, 0.14903535,\n            0.08424043, 0.08120984\n        ], [\n            0.12094152, 0.19162472, 0.01473646, 0.28045061, 0.24246305,\n            0.05206269, 0.09772094\n        ], [\n            0.1333387, 0.00550838, 0.00301669, 0.21745861, 0.20803985,\n            0.41317442, 0.01946335\n        ], [\n            0.16468227, 0.1980699, 0.1906545, 0.18963251, 0.19860937,\n            0.04377724, 0.01457421\n        ]]\n        self.probs_seq2 = [[\n            0.08034842, 0.22671944, 0.05799633, 0.36814645, 0.11307441,\n            0.04468023, 0.10903471\n        ], [\n            0.09742457, 0.12959763, 0.09435383, 0.21889204, 0.15113123,\n            0.10219457, 0.20640612\n        ], [\n            0.45033529, 0.09091417, 0.15333208, 0.07939558, 0.08649316,\n            0.12298585, 0.01654384\n        ], [\n            0.02512238, 0.22079203, 0.19664364, 0.11906379, 0.07816055,\n            0.22538587, 0.13483174\n        ], [\n            0.17928453, 0.06065261, 0.41153005, 0.1172041, 0.11880313,\n            0.07113197, 0.04139363\n        ], [\n            0.15882358, 0.1235788, 0.23376776, 0.20510435, 0.00279306,\n            0.05294827, 0.22298418\n        ]]\n        self.greedy_result = [\"ac'bdc\", \"b'da\"]\n        self.beam_search_result = ['acdc', \"b'a\"]\n\n    def test_greedy_decoder_1(self):\n        bst_result = decoder.ctc_greedy_decoder(self.probs_seq1,\n                                                self.vocab_list)\n        self.assertEqual(bst_result, self.greedy_result[0])\n\n    def test_greedy_decoder_2(self):\n        bst_result = decoder.ctc_greedy_decoder(self.probs_seq2,\n                                                self.vocab_list)\n        self.assertEqual(bst_result, self.greedy_result[1])\n\n    def test_beam_search_decoder_1(self):\n        beam_result = decoder.ctc_beam_search_decoder(\n            probs_seq=self.probs_seq1,\n            beam_size=self.beam_size,\n            vocabulary=self.vocab_list)\n        self.assertEqual(beam_result[0][1], self.beam_search_result[0])\n\n    def test_beam_search_decoder_2(self):\n        beam_result = decoder.ctc_beam_search_decoder(\n            probs_seq=self.probs_seq2,\n            beam_size=self.beam_size,\n            vocabulary=self.vocab_list)\n        self.assertEqual(beam_result[0][1], self.beam_search_result[1])\n\n    def test_beam_search_decoder_batch(self):\n        beam_results = decoder.ctc_beam_search_decoder_batch(\n            probs_split=[self.probs_seq1, self.probs_seq2],\n            beam_size=self.beam_size,\n            vocabulary=self.vocab_list,\n            num_processes=24)\n        self.assertEqual(beam_results[0][0][1], self.beam_search_result[0])\n        self.assertEqual(beam_results[1][0][1], self.beam_search_result[1])\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/recog.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference espnet Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"V2 backend for `asr_recog.py` using py:class:`decoders.beam_search.BeamSearch`.\"\"\"\nimport jsonlines\nimport paddle\nfrom yacs.config import CfgNode\n\nfrom .beam_search import BatchBeamSearch\nfrom .beam_search import BeamSearch\nfrom .scorers.length_bonus import LengthBonus\nfrom .scorers.scorer_interface import BatchScorerInterface\nfrom .utils import add_results_to_json\nfrom paddlespeech.s2t.exps import dynamic_import_tester\nfrom paddlespeech.s2t.io.reader import LoadInputsAndTargets\nfrom paddlespeech.s2t.models.asr_interface import ASRInterface\nfrom paddlespeech.s2t.models.lm_interface import dynamic_import_lm\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n# NOTE: you need this func to generate our sphinx doc\n\n\ndef get_config(config_path):\n    confs = CfgNode(new_allowed=True)\n    confs.merge_from_file(config_path)\n    return confs\n\n\ndef load_trained_model(args):\n    confs = get_config(args.model_conf)\n    class_obj = dynamic_import_tester(args.model_name)\n    exp = class_obj(confs, args)\n    with exp.eval():\n        exp.setup()\n        exp.restore()\n    char_list = exp.args.char_list\n    model = exp.model\n    return model, char_list, exp, confs\n\n\ndef load_trained_lm(args):\n    lm_args = get_config(args.rnnlm_conf)\n    lm_model_module = lm_args.model_module\n    lm_class = dynamic_import_lm(lm_model_module)\n    lm = lm_class(**lm_args.model)\n    model_dict = paddle.load(args.rnnlm)\n    lm.set_state_dict(model_dict)\n    return lm\n\n\ndef recog_v2(args):\n    \"\"\"Decode with custom models that implements ScorerInterface.\n\n    Args:\n        args (namespace): The program arguments.\n        See py:func:`bin.asr_recog.get_parser` for details\n\n    \"\"\"\n    logger.warning(\"experimental API for custom LMs is selected by --api v2\")\n    if args.batchsize > 1:\n        raise NotImplementedError(\"multi-utt batch decoding is not implemented\")\n    if args.streaming_mode is not None:\n        raise NotImplementedError(\"streaming mode is not implemented\")\n    if args.word_rnnlm:\n        raise NotImplementedError(\"word LM is not implemented\")\n\n    # set_deterministic(args)\n    model, char_list, exp, confs = load_trained_model(args)\n    assert isinstance(model, ASRInterface)\n\n    load_inputs_and_targets = LoadInputsAndTargets(\n        mode=\"asr\",\n        load_output=False,\n        sort_in_input_length=False,\n        preprocess_conf=confs.preprocess_config\n        if args.preprocess_conf is None else args.preprocess_conf,\n        preprocess_args={\"train\": False}, )\n\n    if args.rnnlm:\n        lm = load_trained_lm(args)\n        lm.eval()\n    else:\n        lm = None\n\n    if args.ngram_model:\n        from .scorers.ngram import NgramFullScorer\n        from .scorers.ngram import NgramPartScorer\n\n        if args.ngram_scorer == \"full\":\n            ngram = NgramFullScorer(args.ngram_model, char_list)\n        else:\n            ngram = NgramPartScorer(args.ngram_model, char_list)\n    else:\n        ngram = None\n\n    scorers = model.scorers()  # decoder\n    scorers[\"lm\"] = lm\n    scorers[\"ngram\"] = ngram\n    scorers[\"length_bonus\"] = LengthBonus(len(char_list))\n    weights = dict(\n        decoder=1.0 - args.ctc_weight,\n        ctc=args.ctc_weight,\n        lm=args.lm_weight,\n        ngram=args.ngram_weight,\n        length_bonus=args.penalty, )\n    beam_search = BeamSearch(\n        beam_size=args.beam_size,\n        vocab_size=len(char_list),\n        weights=weights,\n        scorers=scorers,\n        sos=model.sos,\n        eos=model.eos,\n        token_list=char_list,\n        pre_beam_score_key=None if args.ctc_weight == 1.0 else \"full\", )\n\n    # TODO(karita): make all scorers batchfied\n    if args.batchsize == 1:\n        non_batch = [\n            k for k, v in beam_search.full_scorers.items()\n            if not isinstance(v, BatchScorerInterface)\n        ]\n        if len(non_batch) == 0:\n            beam_search.__class__ = BatchBeamSearch\n            logger.info(\"BatchBeamSearch implementation is selected.\")\n        else:\n            logger.warning(f\"As non-batch scorers {non_batch} are found, \"\n                           f\"fall back to non-batch implementation.\")\n\n    if args.ngpu > 1:\n        raise NotImplementedError(\"only single GPU decoding is supported\")\n    if args.ngpu == 1:\n        device = \"gpu:0\"\n    else:\n        device = \"cpu\"\n    paddle.set_device(device)\n    dtype = getattr(paddle, args.dtype)\n    logger.info(f\"Decoding device={device}, dtype={dtype}\")\n    model.to(device=device, dtype=dtype)\n    model.eval()\n    beam_search.to(device=device, dtype=dtype)\n    beam_search.eval()\n\n    # read json data\n    js = []\n    with jsonlines.open(args.recog_json, \"r\") as reader:\n        for item in reader:\n            js.append(item)\n    # jsonlines to dict, key by 'utt', value by jsonline\n    js = {item['utt']: item for item in js}\n\n    new_js = {}\n    with paddle.no_grad():\n        with jsonlines.open(args.result_label, \"w\") as f:\n            for idx, name in enumerate(js.keys(), 1):\n                logger.info(f\"({idx}/{len(js.keys())}) decoding \" + name)\n                batch = [(name, js[name])]\n                feat = load_inputs_and_targets(batch)[0][0]\n                logger.info(f'feat: {feat.shape}')\n                enc = model.encode(paddle.to_tensor(feat).to(dtype))\n                logger.info(f'eout: {enc.shape}')\n                nbest_hyps = beam_search(\n                    x=enc,\n                    maxlenratio=args.maxlenratio,\n                    minlenratio=args.minlenratio)\n                nbest_hyps = [\n                    h.asdict()\n                    for h in nbest_hyps[:min(len(nbest_hyps), args.nbest)]\n                ]\n                new_js[name] = add_results_to_json(js[name], nbest_hyps,\n                                                   char_list)\n\n                item = new_js[name]['output'][0]  # 1-best\n                ref = item['text']\n                rec_text = item['rec_text'].replace('▁', ' ').replace(\n                    '<eos>', '').strip()\n                rec_tokenid = list(map(int, item['rec_tokenid'].split()))\n                f.write({\n                    \"utt\": name,\n                    \"refs\": [ref],\n                    \"hyps\": [rec_text],\n                    \"hyps_tokenid\": [rec_tokenid],\n                })\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/recog_bin.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference espnet Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"End-to-end speech recognition model decoding script.\"\"\"\nimport logging\nimport os\nimport random\nimport sys\n\nimport configargparse\nimport numpy as np\n\nfrom paddlespeech.utils.argparse import strtobool\n\n\ndef get_parser():\n    \"\"\"Get default arguments.\"\"\"\n    parser = configargparse.ArgumentParser(\n        description=\"Transcribe text from speech using \"\n        \"a speech recognition model on one CPU or GPU\",\n        config_file_parser_class=configargparse.YAMLConfigFileParser,\n        formatter_class=configargparse.ArgumentDefaultsHelpFormatter, )\n    parser.add(\n        '--model-name',\n        type=str,\n        default='u2_kaldi',\n        help='model name, e.g: deepspeech2, u2, u2_kaldi, u2_st')\n    # general configuration\n    parser.add(\"--config\", is_config_file=True, help=\"Config file path\")\n    parser.add(\n        \"--config2\",\n        is_config_file=True,\n        help=\"Second config file path that overwrites the settings in `--config`\",\n    )\n    parser.add(\n        \"--config3\",\n        is_config_file=True,\n        help=\"Third config file path that overwrites the settings \"\n        \"in `--config` and `--config2`\", )\n\n    parser.add_argument(\"--ngpu\", type=int, default=0, help=\"Number of GPUs\")\n    parser.add_argument(\n        \"--dtype\",\n        choices=(\"float16\", \"float32\", \"float64\"),\n        default=\"float32\",\n        help=\"Float precision (only available in --api v2)\", )\n    parser.add_argument(\"--debugmode\", type=int, default=1, help=\"Debugmode\")\n    parser.add_argument(\"--seed\", type=int, default=1, help=\"Random seed\")\n    parser.add_argument(\n        \"--verbose\", \"-V\", type=int, default=2, help=\"Verbose option\")\n    parser.add_argument(\n        \"--batchsize\",\n        type=int,\n        default=1,\n        help=\"Batch size for beam search (0: means no batch processing)\", )\n    parser.add_argument(\n        \"--preprocess-conf\",\n        type=str,\n        default=None,\n        help=\"The configuration file for the pre-processing\", )\n    parser.add_argument(\n        \"--api\",\n        default=\"v2\",\n        choices=[\"v2\"],\n        help=\"Beam search APIs \"\n        \"v2: Experimental API. It supports any models that implements ScorerInterface.\",\n    )\n    # task related\n    parser.add_argument(\n        \"--recog-json\", type=str, help=\"Filename of recognition data (json)\")\n    parser.add_argument(\n        \"--result-label\",\n        type=str,\n        required=True,\n        help=\"Filename of result label data (json)\", )\n    # model (parameter) related\n    parser.add_argument(\n        \"--model\",\n        type=str,\n        required=True,\n        help=\"Model file parameters to read\")\n    parser.add_argument(\n        \"--model-conf\", type=str, default=None, help=\"Model config file\")\n    parser.add_argument(\n        \"--num-spkrs\",\n        type=int,\n        default=1,\n        choices=[1, 2],\n        help=\"Number of speakers in the speech\", )\n    parser.add_argument(\n        \"--num-encs\",\n        default=1,\n        type=int,\n        help=\"Number of encoders in the model.\")\n    # search related\n    parser.add_argument(\n        \"--nbest\", type=int, default=1, help=\"Output N-best hypotheses\")\n    parser.add_argument(\"--beam-size\", type=int, default=1, help=\"Beam size\")\n    parser.add_argument(\n        \"--penalty\", type=float, default=0.0, help=\"Incertion penalty\")\n    parser.add_argument(\n        \"--maxlenratio\",\n        type=float,\n        default=0.0,\n        help=\"\"\"Input length ratio to obtain max output length.\n                        If maxlenratio=0.0 (default), it uses a end-detect function\n                        to automatically find maximum hypothesis lengths.\n                        If maxlenratio<0.0, its absolute value is interpreted\n                        as a constant max output length\"\"\", )\n    parser.add_argument(\n        \"--minlenratio\",\n        type=float,\n        default=0.0,\n        help=\"Input length ratio to obtain min output length\", )\n    parser.add_argument(\n        \"--ctc-weight\",\n        type=float,\n        default=0.0,\n        help=\"CTC weight in joint decoding\")\n    parser.add_argument(\n        \"--weights-ctc-dec\",\n        type=float,\n        action=\"append\",\n        help=\"ctc weight assigned to each encoder during decoding.\"\n        \"[in multi-encoder mode only]\", )\n    parser.add_argument(\n        \"--ctc-window-margin\",\n        type=int,\n        default=0,\n        help=\"\"\"Use CTC window with margin parameter to accelerate\n                        CTC/attention decoding especially on GPU. Smaller magin\n                        makes decoding faster, but may increase search errors.\n                        If margin=0 (default), this function is disabled\"\"\", )\n    # transducer related\n    parser.add_argument(\n        \"--search-type\",\n        type=str,\n        default=\"default\",\n        choices=[\"default\", \"nsc\", \"tsd\", \"alsd\", \"maes\"],\n        help=\"\"\"Type of beam search implementation to use during inference.\n        Can be either: default beam search (\"default\"),\n        N-Step Constrained beam search (\"nsc\"), Time-Synchronous Decoding (\"tsd\"),\n        Alignment-Length Synchronous Decoding (\"alsd\") or\n        modified Adaptive Expansion Search (\"maes\").\"\"\", )\n    parser.add_argument(\n        \"--nstep\",\n        type=int,\n        default=1,\n        help=\"\"\"Number of expansion steps allowed in NSC beam search or mAES\n        (nstep > 0 for NSC and nstep > 1 for mAES).\"\"\", )\n    parser.add_argument(\n        \"--prefix-alpha\",\n        type=int,\n        default=2,\n        help=\"Length prefix difference allowed in NSC beam search or mAES.\", )\n    parser.add_argument(\n        \"--max-sym-exp\",\n        type=int,\n        default=2,\n        help=\"Number of symbol expansions allowed in TSD.\", )\n    parser.add_argument(\n        \"--u-max\",\n        type=int,\n        default=400,\n        help=\"Length prefix difference allowed in ALSD.\", )\n    parser.add_argument(\n        \"--expansion-gamma\",\n        type=float,\n        default=2.3,\n        help=\"Allowed logp difference for prune-by-value method in mAES.\", )\n    parser.add_argument(\n        \"--expansion-beta\",\n        type=int,\n        default=2,\n        help=\"\"\"Number of additional candidates for expanded hypotheses\n                selection in mAES.\"\"\", )\n    parser.add_argument(\n        \"--score-norm\",\n        type=strtobool,\n        nargs=\"?\",\n        default=True,\n        help=\"Normalize final hypotheses' score by length\", )\n    parser.add_argument(\n        \"--softmax-temperature\",\n        type=float,\n        default=1.0,\n        help=\"Penalization term for softmax function.\", )\n    # rnnlm related\n    parser.add_argument(\n        \"--rnnlm\", type=str, default=None, help=\"RNNLM model file to read\")\n    parser.add_argument(\n        \"--rnnlm-conf\",\n        type=str,\n        default=None,\n        help=\"RNNLM model config file to read\")\n    parser.add_argument(\n        \"--word-rnnlm\",\n        type=str,\n        default=None,\n        help=\"Word RNNLM model file to read\")\n    parser.add_argument(\n        \"--word-rnnlm-conf\",\n        type=str,\n        default=None,\n        help=\"Word RNNLM model config file to read\", )\n    parser.add_argument(\n        \"--word-dict\", type=str, default=None, help=\"Word list to read\")\n    parser.add_argument(\n        \"--lm-weight\", type=float, default=0.1, help=\"RNNLM weight\")\n    # ngram related\n    parser.add_argument(\n        \"--ngram-model\",\n        type=str,\n        default=None,\n        help=\"ngram model file to read\")\n    parser.add_argument(\n        \"--ngram-weight\", type=float, default=0.1, help=\"ngram weight\")\n    parser.add_argument(\n        \"--ngram-scorer\",\n        type=str,\n        default=\"part\",\n        choices=(\"full\", \"part\"),\n        help=\"\"\"if the ngram is set as a part scorer, similar with CTC scorer,\n                ngram scorer only scores topK hypethesis.\n                if the ngram is set as full scorer, ngram scorer scores all hypthesis\n                the decoding speed of part scorer is musch faster than full one\"\"\",\n    )\n    # streaming related\n    parser.add_argument(\n        \"--streaming-mode\",\n        type=str,\n        default=None,\n        choices=[\"window\", \"segment\"],\n        help=\"\"\"Use streaming recognizer for inference.\n                        `--batchsize` must be set to 0 to enable this mode\"\"\", )\n    parser.add_argument(\n        \"--streaming-window\", type=int, default=10, help=\"Window size\")\n    parser.add_argument(\n        \"--streaming-min-blank-dur\",\n        type=int,\n        default=10,\n        help=\"Minimum blank duration threshold\", )\n    parser.add_argument(\n        \"--streaming-onset-margin\", type=int, default=1, help=\"Onset margin\")\n    parser.add_argument(\n        \"--streaming-offset-margin\", type=int, default=1, help=\"Offset margin\")\n    # non-autoregressive related\n    # Mask CTC related. See https://arxiv.org/abs/2005.08700 for the detail.\n    parser.add_argument(\n        \"--maskctc-n-iterations\",\n        type=int,\n        default=10,\n        help=\"Number of decoding iterations.\"\n        \"For Mask CTC, set 0 to predict 1 mask/iter.\", )\n    parser.add_argument(\n        \"--maskctc-probability-threshold\",\n        type=float,\n        default=0.999,\n        help=\"Threshold probability for CTC output\", )\n    # quantize model related\n    parser.add_argument(\n        \"--quantize-config\",\n        nargs=\"*\",\n        help=\"Quantize config list. E.g.: --quantize-config=[Linear,LSTM,GRU]\",\n    )\n    parser.add_argument(\n        \"--quantize-dtype\",\n        type=str,\n        default=\"qint8\",\n        help=\"Dtype dynamic quantize\")\n    parser.add_argument(\n        \"--quantize-asr-model\",\n        type=bool,\n        default=False,\n        help=\"Quantize asr model\", )\n    parser.add_argument(\n        \"--quantize-lm-model\",\n        type=bool,\n        default=False,\n        help=\"Quantize lm model\", )\n    return parser\n\n\ndef main(args):\n    \"\"\"Run the main decoding function.\"\"\"\n    parser = get_parser()\n    parser.add_argument(\n        \"--output\", metavar=\"CKPT_DIR\", help=\"path to save checkpoint.\")\n    parser.add_argument(\n        \"--checkpoint_path\", type=str, help=\"path to load checkpoint\")\n    parser.add_argument(\"--dict-path\", type=str, help=\"path to load checkpoint\")\n    args = parser.parse_args(args)\n\n    if args.ngpu == 0 and args.dtype == \"float16\":\n        raise ValueError(\n            f\"--dtype {args.dtype} does not support the CPU backend.\")\n\n    # logging info\n    if args.verbose == 1:\n        logging.basicConfig(\n            level=logging.INFO,\n            format=\"%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s\",\n        )\n    elif args.verbose == 2:\n        logging.basicConfig(\n            level=logging.DEBUG,\n            format=\"%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s\",\n        )\n    else:\n        logging.basicConfig(\n            level=logging.WARN,\n            format=\"%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s\",\n        )\n        logging.warning(\"Skip DEBUG/INFO messages\")\n    logging.info(args)\n\n    # check CUDA_VISIBLE_DEVICES\n    if args.ngpu > 0:\n        cvd = os.environ.get(\"CUDA_VISIBLE_DEVICES\")\n        if cvd is None:\n            logging.warning(\"CUDA_VISIBLE_DEVICES is not set.\")\n        elif args.ngpu != len(cvd.split(\",\")):\n            logging.error(\"#gpus is not matched with CUDA_VISIBLE_DEVICES.\")\n            sys.exit(1)\n\n        # TODO(mn5k): support of multiple GPUs\n        if args.ngpu > 1:\n            logging.error(\"The program only supports ngpu=1.\")\n            sys.exit(1)\n\n    # display PYTHONPATH\n    logging.info(\"python path = \" + os.environ.get(\"PYTHONPATH\", \"(None)\"))\n\n    # seed setting\n    random.seed(args.seed)\n    np.random.seed(args.seed)\n    logging.info(\"set random seed = %d\" % args.seed)\n\n    # validate rnn options\n    if args.rnnlm is not None and args.word_rnnlm is not None:\n        logging.error(\n            \"It seems that both --rnnlm and --word-rnnlm are specified. \"\n            \"Please use either option.\")\n        sys.exit(1)\n\n    # recog\n    if args.num_spkrs == 1:\n        if args.num_encs == 1:\n            # Experimental API that supports custom LMs\n            if args.api == \"v2\":\n                from paddlespeech.s2t.decoders.recog import recog_v2\n                recog_v2(args)\n            else:\n                raise ValueError(\"Only support --api v2\")\n        else:\n            if args.api == \"v2\":\n                raise NotImplementedError(\n                    f\"--num-encs {args.num_encs} > 1 is not supported in --api v2\"\n                )\n    elif args.num_spkrs == 2:\n        raise ValueError(\"asr_mix not supported.\")\n\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/ctc.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"ScorerInterface implementation for CTC.\"\"\"\nimport numpy as np\nimport paddle\n\nfrom .ctc_prefix_score import CTCPrefixScore\nfrom .ctc_prefix_score import CTCPrefixScorePD\nfrom .scorer_interface import BatchPartialScorerInterface\n\n\nclass CTCPrefixScorer(BatchPartialScorerInterface):\n    \"\"\"Decoder interface wrapper for CTCPrefixScore.\"\"\"\n\n    def __init__(self, ctc: paddle.nn.Layer, eos: int):\n        \"\"\"Initialize class.\n\n        Args:\n            ctc (paddle.nn.Layer): The CTC implementation.\n                For example, :class:`paddlespeech.s2t.modules.ctc.CTC`\n            eos (int): The end-of-sequence id.\n\n        \"\"\"\n        self.ctc = ctc\n        self.eos = eos\n        self.impl = None\n\n    def init_state(self, x: paddle.Tensor):\n        \"\"\"Get an initial state for decoding.\n\n        Args:\n            x (paddle.Tensor): The encoded feature tensor\n\n        Returns: initial state\n\n        \"\"\"\n        logp = self.ctc.log_softmax(x.unsqueeze(0)).squeeze(0).numpy()\n        # TODO(karita): use CTCPrefixScorePD\n        self.impl = CTCPrefixScore(logp, 0, self.eos, np)\n        return 0, self.impl.initial_state()\n\n    def select_state(self, state, i, new_id=None):\n        \"\"\"Select state with relative ids in the main beam search.\n\n        Args:\n            state: Decoder state for prefix tokens\n            i (int): Index to select a state in the main beam search\n            new_id (int): New label id to select a state if necessary\n\n        Returns:\n            state: pruned state\n\n        \"\"\"\n        if type(state) == tuple:\n            if len(state) == 2:  # for CTCPrefixScore\n                sc, st = state\n                return sc[i], st[i]\n            else:  # for CTCPrefixScorePD (need new_id > 0)\n                r, log_psi, f_min, f_max, scoring_idmap = state\n                s = log_psi[i, new_id].expand(paddle.shape(log_psi)[1])\n                if scoring_idmap is not None:\n                    return r[:, :, i, scoring_idmap[i, new_id]], s, f_min, f_max\n                else:\n                    return r[:, :, i, new_id], s, f_min, f_max\n        return None if state is None else state[i]\n\n    def score_partial(self, y, ids, state, x):\n        \"\"\"Score new token.\n\n        Args:\n            y (paddle.Tensor): 1D prefix token\n            next_tokens (paddle.Tensor): paddle.int64 next token to score\n            state: decoder state for prefix tokens\n            x (paddle.Tensor): 2D encoder feature that generates ys\n\n        Returns:\n            tuple[paddle.Tensor, Any]:\n                Tuple of a score tensor for y that has a shape `(len(next_tokens),)`\n                and next state for ys\n\n        \"\"\"\n        prev_score, state = state\n        presub_score, new_st = self.impl(y.cpu(), ids.cpu(), state)\n        tscore = paddle.to_tensor(\n            presub_score - prev_score, place=x.place, dtype=x.dtype)\n        return tscore, (presub_score, new_st)\n\n    def batch_init_state(self, x: paddle.Tensor):\n        \"\"\"Get an initial state for decoding.\n\n        Args:\n            x (paddle.Tensor): The encoded feature tensor\n\n        Returns: initial state\n\n        \"\"\"\n        logp = self.ctc.log_softmax(x.unsqueeze(0))  # assuming batch_size = 1\n        xlen = paddle.to_tensor([paddle.shape(logp)[1]])\n        self.impl = CTCPrefixScorePD(logp, xlen, 0, self.eos)\n        return None\n\n    def batch_score_partial(self, y, ids, state, x):\n        \"\"\"Score new token.\n\n        Args:\n            y (paddle.Tensor): 1D prefix token\n            ids (paddle.Tensor): paddle.int64 next token to score\n            state: decoder state for prefix tokens\n            x (paddle.Tensor): 2D encoder feature that generates ys\n\n        Returns:\n            tuple[paddle.Tensor, Any]:\n                Tuple of a score tensor for y that has a shape `(len(next_tokens),)`\n                and next state for ys\n\n        \"\"\"\n        batch_state = (\n            (paddle.stack([s[0] for s in state], axis=2),\n             paddle.stack([s[1] for s in state]), state[0][2], state[0][3], )\n            if state[0] is not None else None)\n        return self.impl(y, batch_state, ids)\n\n    def extend_prob(self, x: paddle.Tensor):\n        \"\"\"Extend probs for decoding.\n\n        This extension is for streaming decoding\n        as in Eq (14) in https://arxiv.org/abs/2006.14941\n\n        Args:\n            x (paddle.Tensor): The encoded feature tensor\n\n        \"\"\"\n        logp = self.ctc.log_softmax(x.unsqueeze(0))\n        self.impl.extend_prob(logp)\n\n    def extend_state(self, state):\n        \"\"\"Extend state for decoding.\n\n        This extension is for streaming decoding\n        as in Eq (14) in https://arxiv.org/abs/2006.14941\n\n        Args:\n            state: The states of hyps\n\n        Returns: extended state\n\n        \"\"\"\n        new_state = []\n        for s in state:\n            new_state.append(self.impl.extend_state(s))\n\n        return new_state\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/ctc_prefix_score.py",
    "content": "#!/usr/bin/env python3\n# Copyright 2018 Mitsubishi Electric Research Labs (Takaaki Hori)\n#  Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)\nimport numpy as np\nimport paddle\nimport six\n\n\nclass CTCPrefixScorePD():\n    \"\"\"Batch processing of CTCPrefixScore\n\n    which is based on Algorithm 2 in WATANABE et al.\n    \"HYBRID CTC/ATTENTION ARCHITECTURE FOR END-TO-END SPEECH RECOGNITION,\"\n    but extended to efficiently compute the label probabilities for multiple\n    hypotheses simultaneously\n    See also Seki et al. \"Vectorized Beam Search for CTC-Attention-Based\n    Speech Recognition,\" In INTERSPEECH (pp. 3825-3829), 2019.\n    \"\"\"\n\n    def __init__(self, x, xlens, blank, eos, margin=0):\n        \"\"\"Construct CTC prefix scorer\n\n        `margin` is M in eq.(22,23)\n\n        :param paddle.Tensor x: input label posterior sequences (B, T, O)\n        :param paddle.Tensor xlens: input lengths (B,)\n        :param int blank: blank label id\n        :param int eos: end-of-sequence id\n        :param int margin: margin parameter for windowing (0 means no windowing)\n        \"\"\"\n        # In the comment lines,\n        # we assume T: input_length, B: batch size, W: beam width, O: output dim.\n        self.logzero = -10000000000.0\n        self.blank = blank\n        self.eos = eos\n        self.batch = paddle.shape(x)[0]\n        self.input_length = paddle.shape(x)[1]\n        self.odim = paddle.shape(x)[2]\n        self.dtype = x.dtype\n\n        # Pad the rest of posteriors in the batch\n        # TODO(takaaki-hori): need a better way without for-loops\n        for i, l in enumerate(xlens):\n            if l < self.input_length:\n                x[i, l:, :] = self.logzero\n                x[i, l:, blank] = 0\n        # Reshape input x\n        xn = x.transpose([1, 0, 2])  # (B, T, O) -> (T, B, O)\n        xb = xn[:, :, self.blank].unsqueeze(2).expand(-1, -1,\n                                                      self.odim)  # (T,B,O)\n        self.x = paddle.stack([xn, xb])  # (2, T, B, O)\n        self.end_frames = paddle.to_tensor(xlens) - 1  # (B,)\n\n        # Setup CTC windowing\n        self.margin = margin\n        if margin > 0:\n            self.frame_ids = paddle.arange(self.input_length, dtype=self.dtype)\n        # Base indices for index conversion\n        # B idx, hyp idx. shape (B*W, 1)\n        self.idx_bh = None\n        # B idx. shape (B,)\n        self.idx_b = paddle.arange(self.batch)\n        # B idx, O idx. shape (B, 1)\n        self.idx_bo = (self.idx_b * self.odim).unsqueeze(1)\n\n    def __call__(self, y, state, scoring_ids=None, att_w=None):\n        \"\"\"Compute CTC prefix scores for next labels\n\n        :param list y: prefix label sequences\n        :param tuple state: previous CTC state\n        :param paddle.Tensor scoring_ids: selected next ids to score (BW, O'), O' <= O\n        :param paddle.Tensor att_w: attention weights to decide CTC window\n        :return new_state, ctc_local_scores (BW, O)\n        \"\"\"\n        output_length = len(y[0]) - 1  # ignore sos\n        last_ids = [yi[-1] for yi in y]  # last output label ids\n        n_bh = len(last_ids)  # batch * hyps\n        n_hyps = n_bh // self.batch  # assuming each utterance has the same # of hyps\n        self.scoring_num = paddle.shape(scoring_ids)[\n            -1] if scoring_ids is not None else 0\n        # prepare state info\n        if state is None:\n            r_prev = paddle.full(\n                (self.input_length, 2, self.batch, n_hyps),\n                self.logzero,\n                dtype=self.dtype, )  # (T, 2, B, W)\n            r_prev[:, 1] = paddle.cumsum(self.x[0, :, :, self.blank],\n                                         0).unsqueeze(2)\n            r_prev = r_prev.reshape([-1, 2, n_bh])  # (T, 2, BW)\n            s_prev = 0.0  # score\n            f_min_prev = 0  # eq. 22-23\n            f_max_prev = 1  # eq. 22-23\n        else:\n            r_prev, s_prev, f_min_prev, f_max_prev = state\n\n        # select input dimensions for scoring\n        if self.scoring_num > 0:\n            # (BW, O)\n            scoring_idmap = paddle.full(\n                (n_bh, self.odim), -1, dtype=paddle.long)\n            snum = self.scoring_num\n            if self.idx_bh is None or n_bh > len(self.idx_bh):\n                self.idx_bh = paddle.arange(n_bh).reshape([-1, 1])  # (BW, 1)\n            scoring_idmap[self.idx_bh[:n_bh], scoring_ids] = paddle.arange(snum)\n            scoring_idx = (\n                scoring_ids + self.idx_bo.repeat(1, n_hyps).reshape(\n                    [-1, 1])  # (BW,1)\n            ).reshape([-1])  # (BWO)\n            # x_ shape (2, T, B*W, O)\n            x_ = paddle.index_select(\n                self.x.reshape([2, -1, self.batch * self.odim]), scoring_idx,\n                2).reshape([2, -1, n_bh, snum])\n        else:\n            scoring_ids = None\n            scoring_idmap = None\n            snum = self.odim\n            # x_ shape (2, T, B*W, O)\n            x_ = self.x.unsqueeze(3).repeat(1, 1, 1, n_hyps, 1).reshape(\n                [2, -1, n_bh, snum])\n\n        # new CTC forward probs are prepared as a (T x 2 x BW x S) tensor\n        # that corresponds to r_t^n(h) and r_t^b(h) in a batch.\n        r = paddle.full(\n            (self.input_length, 2, n_bh, snum),\n            self.logzero,\n            dtype=self.dtype, )\n        if output_length == 0:\n            r[0, 0] = x_[0, 0]\n\n        r_sum = paddle.logsumexp(r_prev, 1)  #(T,BW)\n        log_phi = r_sum.unsqueeze(2).repeat(1, 1, snum)  # (T, BW, O)\n        if scoring_ids is not None:\n            for idx in range(n_bh):\n                pos = scoring_idmap[idx, last_ids[idx]]\n                if pos >= 0:\n                    log_phi[:, idx, pos] = r_prev[:, 1, idx]\n        else:\n            for idx in range(n_bh):\n                log_phi[:, idx, last_ids[idx]] = r_prev[:, 1, idx]\n\n        # decide start and end frames based on attention weights\n        if att_w is not None and self.margin > 0:\n            f_arg = paddle.matmul(att_w, self.frame_ids)\n            f_min = max(int(f_arg.min().cpu()), f_min_prev)\n            f_max = max(int(f_arg.max().cpu()), f_max_prev)\n            start = min(f_max_prev, max(f_min - self.margin, output_length, 1))\n            end = min(f_max + self.margin, self.input_length)\n        else:\n            f_min = f_max = 0\n            # if one frame one out, the output_length is the eating frame num now.\n            start = max(output_length, 1)\n            end = self.input_length\n\n        # compute forward probabilities log(r_t^n(h)) and log(r_t^b(h))\n        for t in range(start, end):\n            rp = r[t - 1]  # (2 x BW x O')\n            rr = paddle.stack([rp[0], log_phi[t - 1], rp[0], rp[1]]).reshape(\n                [2, 2, n_bh, snum])  # (2,2,BW,O')\n            r[t] = paddle.logsumexp(rr, 1) + x_[:, t]\n\n        # compute log prefix probabilities log(psi)\n        log_phi_x = paddle.concat(\n            (log_phi[0].unsqueeze(0), log_phi[:-1]), axis=0) + x_[0]\n        if scoring_ids is not None:\n            log_psi = paddle.full(\n                (n_bh, self.odim), self.logzero, dtype=self.dtype)\n            log_psi_ = paddle.logsumexp(\n                paddle.concat(\n                    (log_phi_x[start:end], r[start - 1, 0].unsqueeze(0)),\n                    axis=0),\n                axis=0, )\n            for si in range(n_bh):\n                log_psi[si, scoring_ids[si]] = log_psi_[si]\n        else:\n            log_psi = paddle.logsumexp(\n                paddle.concat(\n                    (log_phi_x[start:end], r[start - 1, 0].unsqueeze(0)),\n                    axis=0),\n                axis=0, )\n\n        for si in range(n_bh):\n            log_psi[si, self.eos] = r_sum[self.end_frames[si // n_hyps], si]\n\n        # exclude blank probs\n        log_psi[:, self.blank] = self.logzero\n\n        return (log_psi - s_prev), (r, log_psi, f_min, f_max, scoring_idmap)\n\n    def index_select_state(self, state, best_ids):\n        \"\"\"Select CTC states according to best ids\n\n        :param state    : CTC state\n        :param best_ids : index numbers selected by beam pruning (B, W)\n        :return selected_state\n        \"\"\"\n        r, s, f_min, f_max, scoring_idmap = state\n        # convert ids to BHO space\n        n_bh = len(s)\n        n_hyps = n_bh // self.batch\n        vidx = (best_ids +\n                (self.idx_b *\n                 (n_hyps * self.odim)).reshape([-1, 1])).reshape([-1])\n        # select hypothesis scores\n        s_new = paddle.index_select(s.reshape([-1]), vidx, 0)\n        s_new = s_new.reshape([-1, 1]).repeat(1, self.odim).reshape(\n            [n_bh, self.odim])\n        # convert ids to BHS space (S: scoring_num)\n        if scoring_idmap is not None:\n            snum = self.scoring_num\n            hyp_idx = (best_ids // self.odim +\n                       (self.idx_b * n_hyps).reshape([-1, 1])).reshape([-1])\n            label_ids = paddle.fmod(best_ids, self.odim).reshape([-1])\n            score_idx = scoring_idmap[hyp_idx, label_ids]\n            score_idx[score_idx == -1] = 0\n            vidx = score_idx + hyp_idx * snum\n        else:\n            snum = self.odim\n        # select forward probabilities\n        r_new = paddle.index_select(r.reshape([-1, 2, n_bh * snum]), vidx,\n                                    2).reshape([-1, 2, n_bh])\n        return r_new, s_new, f_min, f_max\n\n    def extend_prob(self, x):\n        \"\"\"Extend CTC prob.\n\n        :param paddle.Tensor x: input label posterior sequences (B, T, O)\n        \"\"\"\n\n        if self.x.shape[1] < x.shape[1]:  # self.x (2,T,B,O); x (B,T,O)\n            # Pad the rest of posteriors in the batch\n            # TODO(takaaki-hori): need a better way without for-loops\n            xlens = [paddle.shape(x)[1]]\n            for i, l in enumerate(xlens):\n                if l < self.input_length:\n                    x[i, l:, :] = self.logzero\n                    x[i, l:, self.blank] = 0\n            tmp_x = self.x\n            xn = x.transpose([1, 0, 2])  # (B, T, O) -> (T, B, O)\n            xb = xn[:, :, self.blank].unsqueeze(2).expand(-1, -1, self.odim)\n            self.x = paddle.stack([xn, xb])  # (2, T, B, O)\n            self.x[:, :tmp_x.shape[1], :, :] = tmp_x\n            self.input_length = paddle.shape(x)[1]\n            self.end_frames = paddle.to_tensor(xlens) - 1\n\n    def extend_state(self, state):\n        \"\"\"Compute CTC prefix state.\n\n\n        :param state    : CTC state\n        :return ctc_state\n        \"\"\"\n\n        if state is None:\n            # nothing to do\n            return state\n        else:\n            r_prev, s_prev, f_min_prev, f_max_prev = state\n\n            r_prev_new = paddle.full(\n                (self.input_length, 2),\n                self.logzero,\n                dtype=self.dtype, )\n            start = max(r_prev.shape[0], 1)\n            r_prev_new[0:start] = r_prev\n            for t in range(start, self.input_length):\n                r_prev_new[t, 1] = r_prev_new[t - 1, 1] + self.x[0, t, :,\n                                                                 self.blank]\n\n            return (r_prev_new, s_prev, f_min_prev, f_max_prev)\n\n\nclass CTCPrefixScore():\n    \"\"\"Compute CTC label sequence scores\n\n    which is based on Algorithm 2 in WATANABE et al.\n    \"HYBRID CTC/ATTENTION ARCHITECTURE FOR END-TO-END SPEECH RECOGNITION,\"\n    but extended to efficiently compute the probabilities of multiple labels\n    simultaneously\n    \"\"\"\n\n    def __init__(self, x, blank, eos, xp):\n        self.xp = xp\n        self.logzero = -10000000000.0\n        self.blank = blank\n        self.eos = eos\n        self.input_length = len(x)\n        self.x = x  # (T, O)\n\n    def initial_state(self):\n        \"\"\"Obtain an initial CTC state\n\n        :return: CTC state\n        \"\"\"\n        # initial CTC state is made of a frame x 2 tensor that corresponds to\n        # r_t^n(<sos>) and r_t^b(<sos>), where 0 and 1 of axis=1 represent\n        # superscripts n and b (non-blank and blank), respectively.\n        # r shape (T, 2)\n        r = self.xp.full((self.input_length, 2), self.logzero, dtype=np.float32)\n        r[0, 1] = self.x[0, self.blank]\n        for i in six.moves.range(1, self.input_length):\n            r[i, 1] = r[i - 1, 1] + self.x[i, self.blank]\n        return r\n\n    def __call__(self, y, cs, r_prev):\n        \"\"\"Compute CTC prefix scores for next labels\n\n        :param y     : prefix label sequence\n        :param cs    : array of next labels\n        :param r_prev: previous CTC state\n        :return ctc_scores, ctc_states\n        \"\"\"\n        # initialize CTC states\n        output_length = len(y) - 1  # ignore sos\n        # new CTC states are prepared as a frame x (n or b) x n_labels tensor\n        # that corresponds to r_t^n(h) and r_t^b(h).\n        # r shape (T, 2, n_labels)\n        r = self.xp.ndarray((self.input_length, 2, len(cs)), dtype=np.float32)\n        xs = self.x[:, cs]\n        if output_length == 0:\n            r[0, 0] = xs[0]\n            r[0, 1] = self.logzero\n        else:\n            # Although the code does not exactly follow Algorithm 2,\n            # we don't have to change it because we can assume\n            # r_t(h)=0 for t < |h| in CTC forward computation\n            # (Note: we assume here that index t starts with 0).\n            # The purpose of this difference is to reduce the number of for-loops.\n            # https://github.com/espnet/espnet/pull/3655\n            # where we start to accumulate r_t(h) from t=|h|\n            # and iterate r_t(h) = (r_{t-1}(h) + ...) to T-1,\n            # avoiding accumulating zeros for t=1~|h|-1.\n            # Thus, we need to set r_{|h|-1}(h) = 0,\n            # i.e., r[output_length-1] = logzero, for initialization.\n            # This is just for reducing the computation.\n            r[output_length - 1] = self.logzero\n\n        # prepare forward probabilities for the last label\n        r_sum = self.xp.logaddexp(r_prev[:, 0],\n                                  r_prev[:, 1])  # log(r_t^n(g) + r_t^b(g))\n        last = y[-1]\n        if output_length > 0 and last in cs:\n            log_phi = self.xp.ndarray(\n                (self.input_length, len(cs)), dtype=np.float32)\n            for i in six.moves.range(len(cs)):\n                log_phi[:, i] = r_sum if cs[i] != last else r_prev[:, 1]\n        else:\n            log_phi = r_sum\n\n        # compute forward probabilities log(r_t^n(h)), log(r_t^b(h)),\n        # and log prefix probabilities log(psi)\n        start = max(output_length, 1)\n        log_psi = r[start - 1, 0]\n        for t in six.moves.range(start, self.input_length):\n            r[t, 0] = self.xp.logaddexp(r[t - 1, 0], log_phi[t - 1]) + xs[t]\n            r[t, 1] = (self.xp.logaddexp(r[t - 1, 0], r[t - 1, 1]) +\n                       self.x[t, self.blank])\n            log_psi = self.xp.logaddexp(log_psi, log_phi[t - 1] + xs[t])\n\n        # get P(...eos|X) that ends with the prefix itself\n        eos_pos = self.xp.where(cs == self.eos)[0]\n        if len(eos_pos) > 0:\n            log_psi[eos_pos] = r_sum[-1]  # log(r_T^n(g) + r_T^b(g))\n\n        # exclude blank probs\n        blank_pos = self.xp.where(cs == self.blank)[0]\n        if len(blank_pos) > 0:\n            log_psi[blank_pos] = self.logzero\n\n        # return the log prefix probability and CTC states, where the label axis\n        # of the CTC states is moved to the first axis to slice it easily\n        # log_psi shape (n_labels,), state shape (n_labels, T, 2)\n        return log_psi, self.xp.rollaxis(r, 2)\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/length_bonus.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Length bonus module.\"\"\"\nfrom typing import Any\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\n\nfrom .scorer_interface import BatchScorerInterface\n\n\nclass LengthBonus(BatchScorerInterface):\n    \"\"\"Length bonus in beam search.\"\"\"\n\n    def __init__(self, n_vocab: int):\n        \"\"\"Initialize class.\n\n        Args:\n            n_vocab (int): The number of tokens in vocabulary for beam search\n\n        \"\"\"\n        self.n = n_vocab\n\n    def score(self, y, state, x):\n        \"\"\"Score new token.\n\n        Args:\n            y (paddle.Tensor): 1D paddle.int64 prefix tokens.\n            state: Scorer state for prefix tokens\n            x (paddle.Tensor): 2D encoder feature that generates ys.\n\n        Returns:\n            tuple[paddle.Tensor, Any]: Tuple of\n                paddle.float32 scores for next token (n_vocab)\n                and None\n\n        \"\"\"\n        return paddle.to_tensor(\n            [1.0], place=x.place, dtype=x.dtype).expand(self.n), None\n\n    def batch_score(self,\n                    ys: paddle.Tensor,\n                    states: List[Any],\n                    xs: paddle.Tensor) -> Tuple[paddle.Tensor, List[Any]]:\n        \"\"\"Score new token batch.\n\n        Args:\n            ys (paddle.Tensor): paddle.int64 prefix tokens (n_batch, ylen).\n            states (List[Any]): Scorer states for prefix tokens.\n            xs (paddle.Tensor):\n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        return (paddle.to_tensor([1.0], place=xs.place, dtype=xs.dtype).expand(\n            ys.shape[0], self.n), None, )\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/ngram.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Ngram lm implement.\"\"\"\nfrom abc import ABC\n\nimport kenlm\nimport paddle\n\nfrom .scorer_interface import BatchScorerInterface\nfrom .scorer_interface import PartialScorerInterface\n\n\nclass Ngrambase(ABC):\n    \"\"\"Ngram base implemented through ScorerInterface.\"\"\"\n\n    def __init__(self, ngram_model, token_list):\n        \"\"\"Initialize Ngrambase.\n\n        Args:\n            ngram_model: ngram model path\n            token_list: token list from dict or model.json\n\n        \"\"\"\n        self.chardict = [x if x != \"<eos>\" else \"</s>\" for x in token_list]\n        self.charlen = len(self.chardict)\n        self.lm = kenlm.LanguageModel(ngram_model)\n        self.tmpkenlmstate = kenlm.State()\n\n    def init_state(self, x):\n        \"\"\"Initialize tmp state.\"\"\"\n        state = kenlm.State()\n        self.lm.NullContextWrite(state)\n        return state\n\n    def score_partial_(self, y, next_token, state, x):\n        \"\"\"Score interface for both full and partial scorer.\n\n        Args:\n            y: previous char\n            next_token: next token need to be score\n            state: previous state\n            x: encoded feature\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        out_state = kenlm.State()\n        ys = self.chardict[y[-1]] if y.shape[0] > 1 else \"<s>\"\n        self.lm.BaseScore(state, ys, out_state)\n        scores = paddle.empty_like(next_token, dtype=x.dtype)\n        for i, j in enumerate(next_token):\n            scores[i] = self.lm.BaseScore(out_state, self.chardict[j],\n                                          self.tmpkenlmstate)\n        return scores, out_state\n\n\nclass NgramFullScorer(Ngrambase, BatchScorerInterface):\n    \"\"\"Fullscorer for ngram.\"\"\"\n\n    def score(self, y, state, x):\n        \"\"\"Score interface for both full and partial scorer.\n\n        Args:\n            y: previous char\n            state: previous state\n            x: encoded feature\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        return self.score_partial_(y,\n                                   paddle.to_tensor(range(self.charlen)), state,\n                                   x)\n\n\nclass NgramPartScorer(Ngrambase, PartialScorerInterface):\n    \"\"\"Partialscorer for ngram.\"\"\"\n\n    def score_partial(self, y, next_token, state, x):\n        \"\"\"Score interface for both full and partial scorer.\n\n        Args:\n            y: previous char\n            next_token: next token need to be score\n            state: previous state\n            x: encoded feature\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        return self.score_partial_(y, next_token, state, x)\n\n    def select_state(self, state, i):\n        \"\"\"Empty select state for scorer interface.\"\"\"\n        return state\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/scorers/scorer_interface.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Scorer interface module.\"\"\"\nimport warnings\nfrom typing import Any\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\n\n\nclass ScorerInterface:\n    \"\"\"Scorer interface for beam search.\n\n    The scorer performs scoring of the all tokens in vocabulary.\n\n    Examples:\n        * Search heuristics\n            * :class:`scorers.length_bonus.LengthBonus`\n        * Decoder networks of the sequence-to-sequence models\n            * :class:`transformer.decoder.Decoder`\n            * :class:`rnn.decoders.Decoder`\n        * Neural language models\n            * :class:`lm.transformer.TransformerLM`\n            * :class:`lm.default.DefaultRNNLM`\n            * :class:`lm.seq_rnn.SequentialRNNLM`\n\n    \"\"\"\n\n    def init_state(self, x: paddle.Tensor) -> Any:\n        \"\"\"Get an initial state for decoding (optional).\n\n        Args:\n            x (paddle.Tensor): The encoded feature tensor\n\n        Returns: initial state\n\n        \"\"\"\n        return None\n\n    def select_state(self, state: Any, i: int, new_id: int=None) -> Any:\n        \"\"\"Select state with relative ids in the main beam search.\n\n        Args:\n            state: Decoder state for prefix tokens\n            i (int): Index to select a state in the main beam search\n            new_id (int): New label index to select a state if necessary\n\n        Returns:\n            state: pruned state\n\n        \"\"\"\n        return None if state is None else state[i]\n\n    def score(self, y: paddle.Tensor, state: Any,\n              x: paddle.Tensor) -> Tuple[paddle.Tensor, Any]:\n        \"\"\"Score new token (required).\n\n        Args:\n            y (paddle.Tensor): 1D paddle.int64 prefix tokens.\n            state: Scorer state for prefix tokens\n            x (paddle.Tensor): The encoder feature that generates ys.\n\n        Returns:\n            tuple[paddle.Tensor, Any]: Tuple of\n                scores for next token that has a shape of `(n_vocab)`\n                and next state for ys\n\n        \"\"\"\n        raise NotImplementedError\n\n    def final_score(self, state: Any) -> float:\n        \"\"\"Score eos (optional).\n\n        Args:\n            state: Scorer state for prefix tokens\n\n        Returns:\n            float: final score\n\n        \"\"\"\n        return 0.0\n\n\nclass BatchScorerInterface(ScorerInterface):\n    \"\"\"Batch scorer interface.\"\"\"\n\n    def batch_init_state(self, x: paddle.Tensor) -> Any:\n        \"\"\"Get an initial state for decoding (optional).\n\n        Args:\n            x (paddle.Tensor): The encoded feature tensor\n\n        Returns: initial state\n\n        \"\"\"\n        return self.init_state(x)\n\n    def batch_score(self,\n                    ys: paddle.Tensor,\n                    states: List[Any],\n                    xs: paddle.Tensor) -> Tuple[paddle.Tensor, List[Any]]:\n        \"\"\"Score new token batch (required).\n\n        Args:\n            ys (paddle.Tensor): paddle.int64 prefix tokens (n_batch, ylen).\n            states (List[Any]): Scorer states for prefix tokens.\n            xs (paddle.Tensor):\n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        warnings.warn(\n            \"{} batch score is implemented through for loop not parallelized\".\n            format(self.__class__.__name__))\n        scores = list()\n        outstates = list()\n        for i, (y, state, x) in enumerate(zip(ys, states, xs)):\n            score, outstate = self.score(y, state, x)\n            outstates.append(outstate)\n            scores.append(score)\n        scores = paddle.cat(scores, 0).reshape([ys.shape[0], -1])\n        return scores, outstates\n\n\nclass PartialScorerInterface(ScorerInterface):\n    \"\"\"Partial scorer interface for beam search.\n\n    The partial scorer performs scoring when non-partial scorer finished scoring,\n    and receives pre-pruned next tokens to score because it is too heavy to score\n    all the tokens.\n\n    Score sub-set of tokens, not all.\n\n    Examples:\n         * Prefix search for connectionist-temporal-classification models\n             * :class:`decoders.scorers.ctc.CTCPrefixScorer`\n\n    \"\"\"\n\n    def score_partial(self,\n                      y: paddle.Tensor,\n                      next_tokens: paddle.Tensor,\n                      state: Any,\n                      x: paddle.Tensor) -> Tuple[paddle.Tensor, Any]:\n        \"\"\"Score new token (required).\n\n        Args:\n            y (paddle.Tensor): 1D prefix token\n            next_tokens (paddle.Tensor): paddle.int64 next token to score\n            state: decoder state for prefix tokens\n            x (paddle.Tensor): The encoder feature that generates ys\n\n        Returns:\n            tuple[paddle.Tensor, Any]:\n                Tuple of a score tensor for y that has a shape `(len(next_tokens),)`\n                and next state for ys\n\n        \"\"\"\n        raise NotImplementedError\n\n\nclass BatchPartialScorerInterface(BatchScorerInterface, PartialScorerInterface):\n    \"\"\"Batch partial scorer interface for beam search.\"\"\"\n\n    def batch_score_partial(\n            self,\n            ys: paddle.Tensor,\n            next_tokens: paddle.Tensor,\n            states: List[Any],\n            xs: paddle.Tensor, ) -> Tuple[paddle.Tensor, Any]:\n        \"\"\"Score new token (required).\n\n        Args:\n            ys (paddle.Tensor): paddle.int64 prefix tokens (n_batch, ylen).\n            next_tokens (paddle.Tensor): paddle.int64 tokens to score (n_batch, n_token).\n            states (List[Any]): Scorer states for prefix tokens.\n            xs (paddle.Tensor):\n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[paddle.Tensor, Any]:\n                Tuple of a score tensor for ys that has a shape `(n_batch, n_vocab)`\n                and next states for ys\n        \"\"\"\n        raise NotImplementedError\n"
  },
  {
    "path": "paddlespeech/s2t/decoders/utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport numpy as np\n\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n__all__ = [\"end_detect\", \"parse_hypothesis\", \"add_results_to_json\"]\n\n\ndef end_detect(ended_hyps, i, M=3, D_end=np.log(1 * np.exp(-10))):\n    \"\"\"End detection.\n\n    described in Eq. (50) of S. Watanabe et al\n    \"Hybrid CTC/Attention Architecture for End-to-End Speech Recognition\"\n\n    :param ended_hyps: dict\n    :param i: int\n    :param M: int\n    :param D_end: float\n    :return: bool\n    \"\"\"\n    if len(ended_hyps) == 0:\n        return False\n    count = 0\n    best_hyp = sorted(ended_hyps, key=lambda x: x[\"score\"], reverse=True)[0]\n    for m in range(M):\n        # get ended_hyps with their length is i - m\n        hyp_length = i - m\n        hyps_same_length = [\n            x for x in ended_hyps if len(x[\"yseq\"]) == hyp_length\n        ]\n        if len(hyps_same_length) > 0:\n            best_hyp_same_length = sorted(\n                hyps_same_length, key=lambda x: x[\"score\"], reverse=True)[0]\n            if best_hyp_same_length[\"score\"] - best_hyp[\"score\"] < D_end:\n                count += 1\n\n    if count == M:\n        return True\n    else:\n        return False\n\n\n# * ------------------ recognition related ------------------ *\ndef parse_hypothesis(hyp, char_list):\n    \"\"\"Parse hypothesis.\n\n    Args:\n        hyp (list[dict[str, Any]]): Recognition hypothesis.\n        char_list (list[str]): List of characters.\n\n    Returns:\n        tuple(str, str, str, float)\n\n    \"\"\"\n    # remove sos and get results\n    tokenid_as_list = list(map(int, hyp[\"yseq\"][1:]))\n    token_as_list = [char_list[idx] for idx in tokenid_as_list]\n    score = float(hyp[\"score\"])\n\n    # convert to string\n    tokenid = \" \".join([str(idx) for idx in tokenid_as_list])\n    token = \" \".join(token_as_list)\n    text = \"\".join(token_as_list).replace(\"<space>\", \" \")\n\n    return text, token, tokenid, score\n\n\ndef add_results_to_json(js, nbest_hyps, char_list):\n    \"\"\"Add N-best results to json.\n\n    Args:\n        js (dict[str, Any]): Groundtruth utterance dict.\n        nbest_hyps_sd (list[dict[str, Any]]):\n            List of hypothesis for multi_speakers: nutts x nspkrs.\n        char_list (list[str]): List of characters.\n\n    Returns:\n        dict[str, Any]: N-best results added utterance dict.\n\n    \"\"\"\n    # copy old json info\n    new_js = dict()\n    new_js[\"utt2spk\"] = js[\"utt2spk\"]\n    new_js[\"output\"] = []\n\n    for n, hyp in enumerate(nbest_hyps, 1):\n        # parse hypothesis\n        rec_text, rec_token, rec_tokenid, score = parse_hypothesis(hyp,\n                                                                   char_list)\n\n        # copy ground-truth\n        if len(js[\"output\"]) > 0:\n            out_dic = dict(js[\"output\"][0].items())\n        else:\n            # for no reference case (e.g., speech translation)\n            out_dic = {\"name\": \"\"}\n\n        # update name\n        out_dic[\"name\"] += \"[%d]\" % n\n\n        # add recognition results\n        out_dic[\"rec_text\"] = rec_text\n        out_dic[\"rec_token\"] = rec_token\n        out_dic[\"rec_tokenid\"] = rec_tokenid\n        out_dic[\"score\"] = score\n\n        # add to list of N-best result dicts\n        new_js[\"output\"].append(out_dic)\n\n        # show 1-best result\n        if n == 1:\n            if \"text\" in out_dic.keys():\n                logger.info(\"groundtruth: %s\" % out_dic[\"text\"])\n            logger.info(\"prediction : %s\" % out_dic[\"rec_text\"])\n\n    return new_js\n"
  },
  {
    "path": "paddlespeech/s2t/exps/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\nmodel_trainer_alias = {\n    \"ds2\": \"paddlespeech.s2t.exp.deepspeech2.model:DeepSpeech2Trainer\",\n    \"u2\": \"paddlespeech.s2t.exps.u2.model:U2Trainer\",\n    \"u2_kaldi\": \"paddlespeech.s2t.exps.u2_kaldi.model:U2Trainer\",\n    \"u2_st\": \"paddlespeech.s2t.exps.u2_st.model:U2STTrainer\",\n}\n\n\ndef dynamic_import_trainer(module):\n    \"\"\"Import Trainer dynamically.\n\n    Args:\n        module (str): trainer name. e.g., ds2, u2, u2_kaldi\n\n    Returns:\n        type: Trainer class\n\n    \"\"\"\n    model_class = dynamic_import(module, model_trainer_alias)\n    assert issubclass(model_class,\n                      Trainer), f\"{module} does not implement Trainer\"\n    return model_class\n\n\nmodel_tester_alias = {\n    \"ds2\": \"paddlespeech.s2t.exp.deepspeech2.model:DeepSpeech2Tester\",\n    \"u2\": \"paddlespeech.s2t.exps.u2.model:U2Tester\",\n    \"u2_kaldi\": \"paddlespeech.s2t.exps.u2_kaldi.model:U2Tester\",\n    \"u2_st\": \"paddlespeech.s2t.exps.u2_st.model:U2STTester\",\n}\n\n\ndef dynamic_import_tester(module):\n    \"\"\"Import Tester dynamically.\n\n    Args:\n        module (str): tester name. e.g., ds2, u2, u2_kaldi\n\n    Returns:\n        type: Tester class\n\n    \"\"\"\n    model_class = dynamic_import(module, model_tester_alias)\n    assert issubclass(model_class,\n                      Trainer), f\"{module} does not implement Tester\"\n    return model_class\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/client.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Client-end for the ASR demo.\"\"\"\nimport argparse\nimport sys\n\nimport keyboard\nimport pyaudio\n\nfrom paddlespeech.s2t.utils.socket_server import socket_send\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--host_ip\",\n    default=\"localhost\",\n    type=str,\n    help=\"Server IP address. (default: %(default)s)\")\nparser.add_argument(\n    \"--host_port\",\n    default=8086,\n    type=int,\n    help=\"Server Port. (default: %(default)s)\")\nargs = parser.parse_args()\n\nis_recording = False\nenable_trigger_record = True\n\n\ndef on_press_release(x):\n    \"\"\"Keyboard callback function.\"\"\"\n    global is_recording, enable_trigger_record\n    press = keyboard.KeyboardEvent('down', 28, 'space')\n    release = keyboard.KeyboardEvent('up', 28, 'space')\n    if x.event_type == 'down' and x.name == press.name:\n        if (not is_recording) and enable_trigger_record:\n            sys.stdout.write(\"Start Recording ... \")\n            sys.stdout.flush()\n            is_recording = True\n    if x.event_type == 'up' and x.name == release.name:\n        if is_recording:\n            is_recording = False\n\n\ndata_list = []\n\n\ndef callback(in_data, frame_count, time_info, status):\n    \"\"\"Audio recorder's stream callback function.\"\"\"\n    global data_list, is_recording, enable_trigger_record\n    if is_recording:\n        data_list.append(in_data)\n        enable_trigger_record = False\n    elif len(data_list) > 0:\n        socket_send(args.host_ip, args.host_port, ''.join(data_list))\n        data_list = []\n    enable_trigger_record = True\n    return (in_data, pyaudio.paContinue)\n\n\ndef main():\n    # prepare audio recorder\n    p = pyaudio.PyAudio()\n    stream = p.open(\n        format=pyaudio.paInt16,\n        channels=1,\n        rate=16000,\n        input=True,\n        stream_callback=callback)\n    stream.start_stream()\n\n    # prepare keyboard listener\n    while (1):\n        keyboard.hook(on_press_release)\n        if keyboard.record('esc'):\n            break\n\n    # close up\n    stream.stop_stream()\n    stream.close()\n    p.terminate()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/record.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Record wav from Microphone\"\"\"\n# http://people.csail.mit.edu/hubert/pyaudio/\nimport wave\n\nimport pyaudio\n\nCHUNK = 1024\nFORMAT = pyaudio.paInt16\nCHANNELS = 1\nRATE = 16000\nRECORD_SECONDS = 5\nWAVE_OUTPUT_FILENAME = \"output.wav\"\n\np = pyaudio.PyAudio()\n\nstream = p.open(\n    format=FORMAT,\n    channels=CHANNELS,\n    rate=RATE,\n    input=True,\n    frames_per_buffer=CHUNK)\n\nprint(\"* recording\")\n\nframes = []\n\nfor i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):\n    data = stream.read(CHUNK)\n    frames.append(data)\n\nprint(\"* done recording\")\n\nstream.stop_stream()\nstream.close()\np.terminate()\n\nwf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')\nwf.setnchannels(CHANNELS)\nwf.setsampwidth(p.get_sample_size(FORMAT))\nwf.setframerate(RATE)\nwf.writeframes(b''.join(frames))\nwf.close()\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/runtime.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Server-end for the ASR demo.\"\"\"\nimport functools\n\nimport numpy as np\nimport paddle\nfrom paddle.inference import Config\nfrom paddle.inference import create_predictor\nfrom paddle.io import DataLoader\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.io.collator import SpeechCollator\nfrom paddlespeech.s2t.io.dataset import ManifestDataset\nfrom paddlespeech.s2t.models.ds2 import DeepSpeech2Model\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.socket_server import AsrRequestHandler\nfrom paddlespeech.s2t.utils.socket_server import AsrTCPServer\nfrom paddlespeech.s2t.utils.socket_server import warm_up_test\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef init_predictor(args):\n    if args.model_dir is not None:\n        config = Config(args.model_dir)\n    else:\n        config = Config(args.model_file, args.params_file)\n\n    config.enable_memory_optim()\n    if args.use_gpu:\n        config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)\n    else:\n        # If not specific mkldnn, you can set the blas thread.\n        # The thread num should not be greater than the number of cores in the CPU.\n        config.set_cpu_math_library_num_threads(4)\n        config.enable_mkldnn()\n\n    predictor = create_predictor(config)\n    return predictor\n\n\ndef run(predictor, img):\n    # copy img data to input tensor\n    input_names = predictor.get_input_names()\n    for i, name in enumerate(input_names):\n        input_tensor = predictor.get_input_handle(name)\n        #input_tensor.reshape(img[i].shape)\n        #input_tensor.copy_from_cpu(img[i].copy())\n\n    # do the inference\n    predictor.run()\n\n    results = []\n    # get out data from output tensor\n    output_names = predictor.get_output_names()\n    for i, name in enumerate(output_names):\n        output_tensor = predictor.get_output_handle(name)\n        output_data = output_tensor.copy_to_cpu()\n        results.append(output_data)\n\n    return results\n\n\ndef inference(config, args):\n    predictor = init_predictor(args)\n\n\ndef start_server(config, args):\n    \"\"\"Start the ASR server\"\"\"\n    config.defrost()\n    config.manifest = config.test_manifest\n    dataset = ManifestDataset.from_config(config)\n\n    config.augmentation_config = \"\"\n    config.keep_transcription_text = True\n    config.batch_size = 1\n    config.num_workers = 0\n    collate_fn = SpeechCollator.from_config(config)\n    test_loader = DataLoader(dataset, collate_fn=collate_fn, num_workers=0)\n\n    model = DeepSpeech2Model.from_pretrained(test_loader, config,\n                                             args.checkpoint_path)\n    model.eval()\n\n    # prepare ASR inference handler\n    def file_to_transcript(filename):\n        feature = test_loader.collate_fn.process_utterance(filename, \"\")\n        audio = np.array([feature[0]]).astype('float32')  #[1, T, D]\n        audio_len = feature[0].shape[0]\n        audio_len = np.array([audio_len]).astype('int64')  # [1]\n\n        result_transcript = model.decode(\n            paddle.to_tensor(audio),\n            paddle.to_tensor(audio_len),\n            vocab_list=test_loader.collate_fn.vocab_list,\n            decoding_method=config.decode.decoding_method,\n            lang_model_path=config.decode.lang_model_path,\n            beam_alpha=config.decode.alpha,\n            beam_beta=config.decode.beta,\n            beam_size=config.decode.beam_size,\n            cutoff_prob=config.decode.cutoff_prob,\n            cutoff_top_n=config.decode.cutoff_top_n,\n            num_processes=config.decode.num_proc_bsearch)\n        return result_transcript[0]\n\n    # warming up with utterrances sampled from Librispeech\n    print('-----------------------------------------------------------')\n    print('Warming up ...')\n    warm_up_test(\n        audio_process_handler=file_to_transcript,\n        manifest_path=args.warmup_manifest,\n        num_test_cases=3)\n    print('-----------------------------------------------------------')\n\n    # start the server\n    server = AsrTCPServer(\n        server_address=(args.host_ip, args.host_port),\n        RequestHandlerClass=AsrRequestHandler,\n        speech_save_dir=args.speech_save_dir,\n        audio_process_handler=file_to_transcript)\n    print(\"ASR Server Started.\")\n    server.serve_forever()\n\n\ndef main(config, args):\n    start_server(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    add_arg = functools.partial(add_arguments, argparser=parser)\n    # yapf: disable\n    add_arg('host_ip',          str,\n            'localhost',\n            \"Server's IP address.\")\n    add_arg('host_port',        int,    8089,    \"Server's IP port.\")\n    add_arg('speech_save_dir',  str,\n            'demo_cache',\n            \"Directory to save demo audios.\")\n    add_arg('warmup_manifest',  str, None, \"Filepath of manifest to warm up.\")\n    add_arg(\n        \"--model_file\",\n        type=str,\n        default=\"\",\n        help=\"Model filename, Specify this when your model is a combined model.\"\n    )\n    add_arg(\n        \"--params_file\",\n        type=str,\n        default=\"\",\n        help=\"Parameter filename, Specify this when your model is a combined model.\"\n    )\n    add_arg(\n        \"--model_dir\",\n        type=str,\n        default=None,\n        help=\"Model dir, If you load a non-combined model, specify the directory of the model.\"\n    )\n    add_arg(\"--use_gpu\",\n                        type=bool,\n                        default=False,\n                        help=\"Whether use gpu.\")\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n\n    args.warmup_manifest = config.test_manifest\n    print_arguments(args, globals())\n\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/send.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Socket client to send wav to ASR server.\"\"\"\nimport argparse\nimport wave\n\nfrom paddlespeech.s2t.utils.socket_server import socket_send\n\nparser = argparse.ArgumentParser(description=__doc__)\nparser.add_argument(\n    \"--host_ip\",\n    default=\"localhost\",\n    type=str,\n    help=\"Server IP address. (default: %(default)s)\")\nparser.add_argument(\n    \"--host_port\",\n    default=8086,\n    type=int,\n    help=\"Server Port. (default: %(default)s)\")\nargs = parser.parse_args()\n\nWAVE_OUTPUT_FILENAME = \"output.wav\"\n\n\ndef main():\n    wf = wave.open(WAVE_OUTPUT_FILENAME, 'rb')\n    nframe = wf.getnframes()\n    data = wf.readframes(nframe)\n    print(f\"Wave: {WAVE_OUTPUT_FILENAME}\")\n    print(f\"Wave samples: {nframe}\")\n    print(f\"Wave channels: {wf.getnchannels()}\")\n    print(f\"Wave sample rate: {wf.getframerate()}\")\n    print(f\"Wave sample width: {wf.getsampwidth()}\")\n    assert isinstance(data, bytes)\n    socket_send(args.host_ip, args.host_port, data)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/deploy/server.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Server-end for the ASR demo.\"\"\"\nimport functools\n\nimport numpy as np\nimport paddle\nfrom paddle.io import DataLoader\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.io.collator import SpeechCollator\nfrom paddlespeech.s2t.io.dataset import ManifestDataset\nfrom paddlespeech.s2t.models.ds2 import DeepSpeech2Model\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.socket_server import AsrRequestHandler\nfrom paddlespeech.s2t.utils.socket_server import AsrTCPServer\nfrom paddlespeech.s2t.utils.socket_server import warm_up_test\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef start_server(config, args):\n    \"\"\"Start the ASR server\"\"\"\n    config.defrost()\n    config.manifest = config.test_manifest\n    dataset = ManifestDataset.from_config(config)\n\n    config.augmentation_config = \"\"\n    config.keep_transcription_text = True\n    config.batch_size = 1\n    config.num_workers = 0\n    collate_fn = SpeechCollator.from_config(config)\n    test_loader = DataLoader(dataset, collate_fn=collate_fn, num_workers=0)\n\n    model = DeepSpeech2Model.from_pretrained(test_loader, config,\n                                             args.checkpoint_path)\n    model.eval()\n\n    # prepare ASR inference handler\n    def file_to_transcript(filename):\n        feature = test_loader.collate_fn.process_utterance(filename, \"\")\n        audio = np.array([feature[0]]).astype('float32')  #[1, T, D]\n        # audio = audio.swapaxes(1,2)\n        print('---file_to_transcript feature----')\n        print(audio.shape)\n        audio_len = feature[0].shape[0]\n        print(audio_len)\n        audio_len = np.array([audio_len]).astype('int64')  # [1]\n\n        result_transcript = model.decode(\n            paddle.to_tensor(audio),\n            paddle.to_tensor(audio_len),\n            vocab_list=test_loader.collate_fn.vocab_list,\n            decoding_method=config.decode.decoding_method,\n            lang_model_path=config.decode.lang_model_path,\n            beam_alpha=config.decode.alpha,\n            beam_beta=config.decode.beta,\n            beam_size=config.decode.beam_size,\n            cutoff_prob=config.decode.cutoff_prob,\n            cutoff_top_n=config.decode.cutoff_top_n,\n            num_processes=config.decode.num_proc_bsearch)\n        return result_transcript[0]\n\n    # warming up with utterrances sampled from Librispeech\n    print('-----------------------------------------------------------')\n    print('Warming up ...')\n    warm_up_test(\n        audio_process_handler=file_to_transcript,\n        manifest_path=args.warmup_manifest,\n        num_test_cases=3)\n    print('-----------------------------------------------------------')\n\n    # start the server\n    server = AsrTCPServer(\n        server_address=(args.host_ip, args.host_port),\n        RequestHandlerClass=AsrRequestHandler,\n        speech_save_dir=args.speech_save_dir,\n        audio_process_handler=file_to_transcript)\n    print(\"ASR Server Started.\")\n    server.serve_forever()\n\n\ndef main(config, args):\n    start_server(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    add_arg = functools.partial(add_arguments, argparser=parser)\n    # yapf: disable\n    add_arg('host_ip',          str,\n            'localhost',\n            \"Server's IP address.\")\n    add_arg('host_port',        int,    8088,    \"Server's IP port.\")\n    add_arg('speech_save_dir',  str,\n            'demo_cache',\n            \"Directory to save demo audios.\")\n    add_arg('warmup_manifest', str, None, \"Filepath of manifest to warm up.\")\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n\n    args.warmup_manifest = config.test_manifest\n    print_arguments(args, globals())\n\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/export.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Export for DeepSpeech2 model.\"\"\"\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.deepspeech2.model import DeepSpeech2Tester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_export()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args)\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for DeepSpeech2 model.\"\"\"\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.deepspeech2.model import DeepSpeech2Tester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/test_export.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for DeepSpeech2 model.\"\"\"\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.deepspeech2.model import DeepSpeech2ExportTester as ExportTester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = ExportTester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        \"--enable-auto-log\", action=\"store_true\", help=\"use auto log\")\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/test_wav.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for DeepSpeech2 model.\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\n\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.ds2 import DeepSpeech2Model\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.checkpoint import Checkpoint\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nfrom paddlespeech.utils.argparse import print_arguments\n\nlogger = Log(__name__).getlog()\n\n\nclass DeepSpeech2Tester_hub():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n\n        self.preprocess_conf = config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n\n        self.text_feature = TextFeaturizer(\n            unit_type=config.unit_type,\n            vocab=config.vocab_filepath,\n            spm_model_prefix=config.spm_model_prefix)\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n    def compute_result_transcripts(self, audio, audio_len, vocab_list, cfg):\n        decode_batch_size = cfg.decode_batch_size\n        self.model.decoder.init_decoder(\n            decode_batch_size, vocab_list, cfg.decoding_method,\n            cfg.lang_model_path, cfg.alpha, cfg.beta, cfg.beam_size,\n            cfg.cutoff_prob, cfg.cutoff_top_n, cfg.num_proc_bsearch)\n        result_transcripts = self.model.decode(audio, audio_len)\n        return result_transcripts\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        self.model.eval()\n        cfg = self.config\n        audio_file = self.audio_file\n\n        audio, sample_rate = soundfile.read(\n            self.audio_file, dtype=\"int16\", always_2d=True)\n\n        audio = audio[:, 0]\n        logger.info(f\"audio shape: {audio.shape}\")\n\n        # fbank\n        feat = self.preprocessing(audio, **self.preprocess_args)\n        logger.info(f\"feat shape: {feat.shape}\")\n\n        audio_len = paddle.to_tensor(feat.shape[0]).unsqueeze(0)\n        audio = paddle.to_tensor(feat, dtype='float32').unsqueeze(axis=0)\n\n        result_transcripts = self.compute_result_transcripts(\n            audio, audio_len, self.text_feature.vocab_list, cfg.decode)\n\n        logger.info(\"result_transcripts: \" + result_transcripts[0])\n\n    def run_test(self):\n        self.resume()\n        try:\n            self.test()\n        except KeyboardInterrupt:\n            exit(-1)\n\n    def setup(self):\n        \"\"\"Setup the experiment.\n        \"\"\"\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        self.setup_output_dir()\n        self.setup_checkpointer()\n\n        self.setup_model()\n\n    def setup_output_dir(self):\n        \"\"\"Create a directory used for output.\n        \"\"\"\n        # output dir\n        if self.args.output:\n            output_dir = Path(self.args.output).expanduser()\n            output_dir.mkdir(parents=True, exist_ok=True)\n        else:\n            output_dir = Path(\n                self.args.checkpoint_path).expanduser().parent.parent\n            output_dir.mkdir(parents=True, exist_ok=True)\n        self.output_dir = output_dir\n\n    def setup_model(self):\n        config = self.config.clone()\n        with UpdateConfig(config):\n            config.input_dim = config.feat_dim\n            config.output_dim = self.text_feature.vocab_size\n        model = DeepSpeech2Model.from_config(config)\n        self.model = model\n\n    def setup_checkpointer(self):\n        \"\"\"Create a directory used to save checkpoints into.\n\n        It is \"checkpoints\" inside the output directory.\n        \"\"\"\n        # checkpoint dir\n        checkpoint_dir = self.output_dir / \"checkpoints\"\n        checkpoint_dir.mkdir(exist_ok=True)\n\n        self.checkpoint_dir = checkpoint_dir\n\n        self.checkpoint = Checkpoint(\n            kbest_n=self.config.checkpoint.kbest_n,\n            latest_n=self.config.checkpoint.latest_n)\n\n    def resume(self):\n        \"\"\"Resume from the checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n        \"\"\"\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n\ndef check(audio_file):\n    logger.info(\"checking the audio file format......\")\n    try:\n        sig, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main_sp(config, args):\n    exp = DeepSpeech2Tester_hub(config, args)\n    exp.setup()\n    exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n    if not os.path.isfile(args.audio_file):\n        print(\"Please input the audio file path\")\n        sys.exit(-1)\n    check(args.audio_file)\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/bin/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for DeepSpeech2 model.\"\"\"\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.deepspeech2.model import DeepSpeech2Trainer as Trainer\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/deepspeech2/model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains DeepSpeech2 and DeepSpeech2Online model.\"\"\"\nimport os\nimport time\nfrom collections import defaultdict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle import inference\n\nimport paddlespeech.utils\nfrom paddlespeech.audio.text.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import BatchDataLoader\nfrom paddlespeech.s2t.models.ds2 import DeepSpeech2InferModel\nfrom paddlespeech.s2t.models.ds2 import DeepSpeech2Model\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass DeepSpeech2Trainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n\n    def train_batch(self, batch_index, batch_data, msg):\n        batch_size = self.config.batch_size\n        accum_grad = self.config.accum_grad\n\n        start = time.time()\n\n        # forward\n        utt, audio, audio_len, text, text_len = batch_data\n        loss = self.model(audio, audio_len, text, text_len)\n        losses_np = {\n            'train_loss': float(loss),\n        }\n\n        # loss backward\n        if (batch_index + 1) % accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n\n        with context():\n            loss.backward()\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step\n        if (batch_index + 1) % accum_grad == 0:\n            self.optimizer.step()\n            self.optimizer.clear_grad()\n            self.iteration += 1\n\n        iteration_time = time.time() - start\n\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"batch_size\", batch_size)\n        report(\"accum\", accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if dist.get_rank() == 0 and self.visualizer:\n            for k, v in losses_np.items():\n                # `step -1` since we update `step` after optimizer.step().\n                self.visualizer.add_scalar(\"train/{}\".format(k), v,\n                                           self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        logger.info(f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        self.model.eval()\n        valid_losses = defaultdict(list)\n        num_seen_utts = 1\n        total_loss = 0.0\n        for i, batch in enumerate(self.valid_loader):\n            utt, audio, audio_len, text, text_len = batch\n            loss = self.model(audio, audio_len, text, text_len)\n            if paddle.isfinite(loss):\n                num_utts = batch[1].shape[0]\n                num_seen_utts += num_utts\n                total_loss += float(loss) * num_utts\n                valid_losses['val_loss'].append(float(loss))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_dump = {k: np.mean(v) for k, v in valid_losses.items()}\n                valid_dump['val_history_loss'] = total_loss / num_seen_utts\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                msg += \"batch : {}/{}, \".format(i + 1, len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_dump.items())\n                logger.info(msg)\n\n        logger.info('Rank {} Val info val_loss {}'.format(\n            dist.get_rank(), total_loss / num_seen_utts))\n        return total_loss, num_seen_utts\n\n    def setup_model(self):\n        config = self.config.clone()\n        with UpdateConfig(config):\n            if self.train:\n                config.input_dim = self.train_loader.feat_dim\n                config.output_dim = self.train_loader.vocab_size\n            else:\n                config.input_dim = self.test_loader.feat_dim\n                config.output_dim = self.test_loader.vocab_size\n\n        model = DeepSpeech2Model.from_config(config)\n        if self.parallel:\n            model = paddle.DataParallel(model)\n\n        logger.info(f\"{model}\")\n        layer_tools.print_params(model, logger.info)\n        self.model = model\n        logger.info(\"Setup model!\")\n\n        if not self.train:\n            return\n\n        grad_clip = paddle.nn.ClipGradByGlobalNorm(config.global_grad_clip)\n        lr_scheduler = paddle.optimizer.lr.ExponentialDecay(\n            learning_rate=config.lr, gamma=config.lr_decay, verbose=True)\n        optimizer = paddle.optimizer.Adam(\n            learning_rate=lr_scheduler,\n            parameters=model.parameters(),\n            weight_decay=paddle.regularizer.L2Decay(config.weight_decay),\n            grad_clip=grad_clip)\n        self.optimizer = optimizer\n        self.lr_scheduler = lr_scheduler\n        logger.info(\"Setup optimizer/lr_scheduler!\")\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        config.defrost()\n        if self.train:\n            # train/valid dataset, return token ids\n            self.train_loader = BatchDataLoader(\n                json_file=config.train_manifest,\n                train_mode=True,\n                sortagrad=config.sortagrad,\n                batch_size=config.batch_size,\n                maxlen_in=config.maxlen_in,\n                maxlen_out=config.maxlen_out,\n                minibatches=config.minibatches,\n                mini_batch_size=self.args.ngpu,\n                batch_count=config.batch_count,\n                batch_bins=config.batch_bins,\n                batch_frames_in=config.batch_frames_in,\n                batch_frames_out=config.batch_frames_out,\n                batch_frames_inout=config.batch_frames_inout,\n                preprocess_conf=config.preprocess_config,\n                n_iter_processes=config.num_workers,\n                subsampling_factor=1,\n                num_encs=1,\n                dist_sampler=config.get('dist_sampler', False),\n                shortest_first=False)\n\n            self.valid_loader = BatchDataLoader(\n                json_file=config.dev_manifest,\n                train_mode=False,\n                sortagrad=False,\n                batch_size=config.batch_size,\n                maxlen_in=float('inf'),\n                maxlen_out=float('inf'),\n                minibatches=0,\n                mini_batch_size=self.args.ngpu,\n                batch_count='auto',\n                batch_bins=0,\n                batch_frames_in=0,\n                batch_frames_out=0,\n                batch_frames_inout=0,\n                preprocess_conf=config.preprocess_config,\n                n_iter_processes=config.num_workers,\n                subsampling_factor=1,\n                num_encs=1,\n                dist_sampler=config.get('dist_sampler', False),\n                shortest_first=False)\n            logger.info(\"Setup train/valid Dataloader!\")\n        else:\n            decode_batch_size = config.get('decode', dict()).get(\n                'decode_batch_size', 1)\n            # test dataset, return raw text\n            self.test_loader = BatchDataLoader(\n                json_file=config.test_manifest,\n                train_mode=False,\n                sortagrad=False,\n                batch_size=decode_batch_size,\n                maxlen_in=float('inf'),\n                maxlen_out=float('inf'),\n                minibatches=0,\n                mini_batch_size=1,\n                batch_count='auto',\n                batch_bins=0,\n                batch_frames_in=0,\n                batch_frames_out=0,\n                batch_frames_inout=0,\n                preprocess_conf=config.preprocess_config,\n                n_iter_processes=1,\n                subsampling_factor=1,\n                num_encs=1)\n            logger.info(\"Setup test/align Dataloader!\")\n\n\nclass DeepSpeech2Tester(DeepSpeech2Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self._text_featurizer = TextFeaturizer(\n            unit_type=config.unit_type, vocab=config.vocab_filepath)\n        self.vocab_list = self._text_featurizer.vocab_list\n\n    def ordid2token(self, texts, texts_len):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(\n                self._text_featurizer.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self,\n                        utts,\n                        audio,\n                        audio_len,\n                        texts,\n                        texts_len,\n                        fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n\n        target_transcripts = self.ordid2token(texts, texts_len)\n\n        result_transcripts = self.compute_result_transcripts(audio, audio_len)\n\n        for utt, target, result in zip(utts, target_transcripts,\n                                       result_transcripts):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\"utt\": utt, \"refs\": [target], \"hyps\": [result]})\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\n                \"Current error rate [%s] = %f\" %\n                (decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type)\n\n    def compute_result_transcripts(self, audio, audio_len):\n        result_transcripts = self.model.decode(audio, audio_len)\n        return result_transcripts\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n        self.model.eval()\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n\n        # Initialized the decoder in model\n        decode_cfg = self.config.decode\n        vocab_list = self.vocab_list\n        decode_batch_size = decode_cfg.decode_batch_size\n        self.model.decoder.init_decoder(\n            decode_batch_size, vocab_list, decode_cfg.decoding_method,\n            decode_cfg.lang_model_path, decode_cfg.alpha, decode_cfg.beta,\n            decode_cfg.beam_size, decode_cfg.cutoff_prob,\n            decode_cfg.cutoff_top_n, decode_cfg.num_proc_bsearch)\n\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                utts, audio, audio_len, texts, texts_len = batch\n                metrics = self.compute_metrics(utts, audio, audio_len, texts,\n                                               texts_len, fout)\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                logger.info(\"Error rate [%s] (%d/?) = %f\" %\n                            (error_rate_type, num_ins, errors_sum / len_refs))\n\n        # logging\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n        self.model.decoder.del_decoder()\n\n    @paddle.no_grad()\n    def export(self):\n        infer_model = DeepSpeech2InferModel.from_pretrained(\n            self.test_loader, self.config, self.args.checkpoint_path)\n        infer_model.eval()\n        static_model = infer_model.export()\n        try:\n            logger.info(f\"Export code: {static_model.forward.code}\")\n        except:\n            logger.info(\n                f\"Fail to print Export code, static_model.forward.code can not be run.\"\n            )\n        paddle.jit.save(static_model, self.args.export_path)\n\n\nclass DeepSpeech2ExportTester(DeepSpeech2Tester):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.apply_static = True\n        self.args = args\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n        if self.args.enable_auto_log is True:\n            from paddlespeech.s2t.utils.log import Autolog\n            self.autolog = Autolog(\n                batch_size=self.config.decode.decode_batch_size,\n                model_name=\"deepspeech2\",\n                model_precision=\"fp32\").getlog()\n        self.model.eval()\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n\n        # Initialized the decoder in model\n        decode_cfg = self.config.decode\n        vocab_list = self.vocab_list\n        if self.config.rnn_direction == \"forward\":\n            decode_batch_size = 1\n        elif self.config.rnn_direction == \"bidirect\":\n            decode_batch_size = self.test_loader.batch_size\n        else:\n            raise Exception(\"wrong model type\")\n        self.model.decoder.init_decoder(\n            decode_batch_size, vocab_list, decode_cfg.decoding_method,\n            decode_cfg.lang_model_path, decode_cfg.alpha, decode_cfg.beta,\n            decode_cfg.beam_size, decode_cfg.cutoff_prob,\n            decode_cfg.cutoff_top_n, decode_cfg.num_proc_bsearch)\n\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                utts, audio, audio_len, texts, texts_len = batch\n                metrics = self.compute_metrics(utts, audio, audio_len, texts,\n                                               texts_len, fout)\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                logger.info(\"Error rate [%s] (%d/?) = %f\" %\n                            (error_rate_type, num_ins, errors_sum / len_refs))\n        # logging\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n        if self.args.enable_auto_log is True:\n            self.autolog.report()\n        self.model.decoder.del_decoder()\n\n    def compute_result_transcripts(self, audio, audio_len):\n        if self.config.rnn_direction == \"forward\":\n            output_probs, output_lens, trans_batch = self.static_forward_online(\n                audio, audio_len, decoder_chunk_size=1)\n            result_transcripts = [trans[-1] for trans in trans_batch]\n        elif self.config.rnn_direction == \"bidirect\":\n            output_probs, output_lens = self.static_forward_offline(audio,\n                                                                    audio_len)\n            batch_size = output_probs.shape[0]\n            self.model.decoder.reset_decoder(batch_size=batch_size)\n\n            self.model.decoder.next(output_probs, output_lens)\n\n            trans_best, trans_beam = self.model.decoder.decode()\n\n            result_transcripts = trans_best\n\n        else:\n            raise Exception(\"wrong model type\")\n\n        self.predictor.try_shrink_memory()\n\n        #replace the <space> with ' '\n        result_transcripts = [\n            self._text_featurizer.detokenize(sentence)\n            for sentence in result_transcripts\n        ]\n\n        return result_transcripts\n\n    def run_test(self):\n        \"\"\"Do Test/Decode\"\"\"\n        try:\n            with Timer(\"Test/Decode Done: {}\"):\n                with self.eval():\n                    self.test()\n        except KeyboardInterrupt:\n            exit(-1)\n\n    def static_forward_online(self, audio, audio_len,\n                              decoder_chunk_size: int=1):\n        \"\"\"\n        Parameters\n        ----------\n            audio (Tensor): shape[B, T, D]\n            audio_len (Tensor): shape[B]\n            decoder_chunk_size(int)\n        Returns\n        -------\n            output_probs(numpy.array): shape[B, T, vocab_size]\n            output_lens(numpy.array): shape[B]\n            trans(list(list(str))): shape[B, T]\n        \"\"\"\n        output_probs_list = []\n        output_lens_list = []\n        subsampling_rate = self.model.encoder.conv.subsampling_rate\n        receptive_field_length = self.model.encoder.conv.receptive_field_length\n        chunk_stride = subsampling_rate * decoder_chunk_size\n        chunk_size = (decoder_chunk_size - 1\n                      ) * subsampling_rate + receptive_field_length\n\n        x_batch = audio.numpy()\n        batch_size, Tmax, x_dim = x_batch.shape\n        x_len_batch = audio_len.numpy().astype(np.int64)\n        if (Tmax - chunk_size) % chunk_stride != 0:\n            # The length of padding for the batch\n            padding_len_batch = chunk_stride - (Tmax - chunk_size\n                                                ) % chunk_stride\n        else:\n            padding_len_batch = 0\n        x_list = np.split(x_batch, batch_size, axis=0)\n        x_len_list = np.split(x_len_batch, batch_size, axis=0)\n\n        trans_batch = []\n        for x, x_len in zip(x_list, x_len_list):\n            if self.args.enable_auto_log is True:\n                self.autolog.times.start()\n            x_len = x_len[0]\n            assert (chunk_size <= x_len)\n\n            if (x_len - chunk_size) % chunk_stride != 0:\n                padding_len_x = chunk_stride - (x_len - chunk_size\n                                                ) % chunk_stride\n            else:\n                padding_len_x = 0\n\n            padding = np.zeros(\n                (x.shape[0], padding_len_x, x.shape[2]), dtype=x.dtype)\n            padded_x = np.concatenate([x, padding], axis=1)\n\n            num_chunk = (x_len + padding_len_x - chunk_size) / chunk_stride + 1\n            num_chunk = int(num_chunk)\n\n            chunk_state_h_box = np.zeros(\n                (self.config.num_rnn_layers, 1, self.config.rnn_layer_size),\n                dtype=x.dtype)\n            chunk_state_c_box = np.zeros(\n                (self.config.num_rnn_layers, 1, self.config.rnn_layer_size),\n                dtype=x.dtype)\n\n            input_names = self.predictor.get_input_names()\n            audio_handle = self.predictor.get_input_handle(input_names[0])\n            audio_len_handle = self.predictor.get_input_handle(input_names[1])\n            h_box_handle = self.predictor.get_input_handle(input_names[2])\n            c_box_handle = self.predictor.get_input_handle(input_names[3])\n\n            trans = []\n            probs_chunk_list = []\n            probs_chunk_lens_list = []\n            if self.args.enable_auto_log is True:\n                # record the model preprocessing time\n                self.autolog.times.stamp()\n\n            self.model.decoder.reset_decoder(batch_size=1)\n            for i in range(0, num_chunk):\n                start = i * chunk_stride\n                end = start + chunk_size\n                x_chunk = padded_x[:, start:end, :]\n                if x_len < i * chunk_stride:\n                    x_chunk_lens = 0\n                else:\n                    x_chunk_lens = min(x_len - i * chunk_stride, chunk_size)\n                #means the number of input frames in the chunk is not enough for predicting one prob\n                if (x_chunk_lens < receptive_field_length):\n                    break\n                x_chunk_lens = np.array([x_chunk_lens])\n                audio_handle.reshape(x_chunk.shape)\n                audio_handle.copy_from_cpu(x_chunk)\n\n                audio_len_handle.reshape(x_chunk_lens.shape)\n                audio_len_handle.copy_from_cpu(x_chunk_lens)\n\n                h_box_handle.reshape(chunk_state_h_box.shape)\n                h_box_handle.copy_from_cpu(chunk_state_h_box)\n\n                c_box_handle.reshape(chunk_state_c_box.shape)\n                c_box_handle.copy_from_cpu(chunk_state_c_box)\n\n                output_names = self.predictor.get_output_names()\n                output_handle = self.predictor.get_output_handle(\n                    output_names[0])\n                output_lens_handle = self.predictor.get_output_handle(\n                    output_names[1])\n                output_state_h_handle = self.predictor.get_output_handle(\n                    output_names[2])\n                output_state_c_handle = self.predictor.get_output_handle(\n                    output_names[3])\n                self.predictor.run()\n                output_chunk_probs = output_handle.copy_to_cpu()\n                output_chunk_lens = output_lens_handle.copy_to_cpu()\n                chunk_state_h_box = output_state_h_handle.copy_to_cpu()\n                chunk_state_c_box = output_state_c_handle.copy_to_cpu()\n                self.model.decoder.next(output_chunk_probs, output_chunk_lens)\n                probs_chunk_list.append(output_chunk_probs)\n                probs_chunk_lens_list.append(output_chunk_lens)\n                trans_best, trans_beam = self.model.decoder.decode()\n                trans.append(trans_best[0])\n            trans_batch.append(trans)\n            output_probs = np.concatenate(probs_chunk_list, axis=1)\n            output_lens = np.sum(probs_chunk_lens_list, axis=0)\n            vocab_size = output_probs.shape[2]\n            output_probs_padding_len = Tmax + padding_len_batch - output_probs.shape[\n                1]\n            output_probs_padding = np.zeros(\n                (1, output_probs_padding_len, vocab_size),\n                dtype=output_probs.\n                dtype)  # The prob padding for a piece of utterance\n            output_probs = np.concatenate(\n                [output_probs, output_probs_padding], axis=1)\n            output_probs_list.append(output_probs)\n            output_lens_list.append(output_lens)\n            if self.args.enable_auto_log is True:\n                # record the model inference time\n                self.autolog.times.stamp()\n                # record the post processing time\n                self.autolog.times.stamp()\n                self.autolog.times.end()\n        output_probs = np.concatenate(output_probs_list, axis=0)\n        output_lens = np.concatenate(output_lens_list, axis=0)\n        return output_probs, output_lens, trans_batch\n\n    def static_forward_offline(self, audio, audio_len):\n        \"\"\"\n        Parameters\n        ----------\n            audio (Tensor): shape[B, T, D]\n            audio_len (Tensor): shape[B]\n\n        Returns\n        -------\n            output_probs(numpy.array): shape[B, T, vocab_size]\n            output_lens(numpy.array): shape[B]\n        \"\"\"\n        x = audio.numpy()\n        x_len = audio_len.numpy().astype(np.int64)\n\n        input_names = self.predictor.get_input_names()\n        audio_handle = self.predictor.get_input_handle(input_names[0])\n        audio_len_handle = self.predictor.get_input_handle(input_names[1])\n\n        audio_handle.reshape(x.shape)\n        audio_handle.copy_from_cpu(x)\n\n        audio_len_handle.reshape(x_len.shape)\n        audio_len_handle.copy_from_cpu(x_len)\n\n        if self.args.enable_auto_log is True:\n            self.autolog.times.start()\n            # record the prefix processing time\n            self.autolog.times.stamp()\n        self.predictor.run()\n        if self.args.enable_auto_log is True:\n            # record the model inference time\n            self.autolog.times.stamp()\n            # record the post processing time\n            self.autolog.times.stamp()\n            self.autolog.times.end()\n\n        output_names = self.predictor.get_output_names()\n        output_handle = self.predictor.get_output_handle(output_names[0])\n        output_lens_handle = self.predictor.get_output_handle(output_names[1])\n        output_probs = output_handle.copy_to_cpu()\n        output_lens = output_lens_handle.copy_to_cpu()\n        return output_probs, output_lens\n\n    def setup_model(self):\n        super().setup_model()\n\n        # after paddle 3.0, support new inference interface\n        if paddlespeech.utils.satisfy_paddle_version('3.0.0-beta'):\n            model_dir = os.path.dirname(self.args.export_path)\n            model_prefix = os.path.basename(self.args.export_path)\n            deepspeech_config = inference.Config(model_dir, model_prefix)\n        else:\n            deepspeech_config = inference.Config(\n                self.args.export_path + \".pdmodel\",\n                self.args.export_path + \".pdiparams\")\n\n        deepspeech_config.disable_mkldnn()\n\n        if (os.environ['CUDA_VISIBLE_DEVICES'].strip() != ''):\n            deepspeech_config.enable_use_gpu(100, 0)\n            deepspeech_config.enable_memory_optim()\n        deepspeech_predictor = inference.create_predictor(deepspeech_config)\n        self.predictor = deepspeech_predictor\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/bin/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/bin/test.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for hubert model.\"\"\"\nimport cProfile\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.hubert.model import HubertASRTester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save asr result to\n    parser.add_argument(\n        '--dict-path', type=str, default=None, help='dict path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/bin/test_wav.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for hubert model.\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\n\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.hubert.hubert_ASR import HubertASR\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nlogger = Log(__name__).getlog()\n\n\nclass HubertInfer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n\n        self.text_feature = TextFeaturizer(\n            unit_type=config.unit_type, vocab=config.vocab_filepath)\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.output_dim = self.text_feature.vocab_size\n        model = HubertASR.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n    def run(self):\n        check(args.audio_file)\n\n        with paddle.no_grad():\n            # read\n            audio, _ = soundfile.read(\n                self.audio_file, dtype=\"int16\", always_2d=True)\n            logger.info(f\"audio shape: {audio.shape}\")\n\n            xs = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)\n            decode_config = self.config.decode\n            result_transcripts, result_tokenids = self.model.decode(\n                xs,\n                text_feature=self.text_feature,\n                decoding_method=decode_config.decoding_method,\n                beam_size=decode_config.beam_size)\n            rsl = result_transcripts[0]\n            utt = Path(self.audio_file).name\n            logger.info(f\"hyp: {utt} {rsl}\")\n            return rsl\n\n\ndef check(audio_file):\n    if not os.path.isfile(audio_file):\n        print(\"Please input the right audio file path\")\n        sys.exit(-1)\n\n    logger.info(\"checking the audio file format......\")\n    try:\n        sig, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main(config, args):\n    HubertInfer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n\n    config = CfgNode(new_allowed=True)\n\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/bin/train.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for hubert model.\"\"\"\nimport cProfile\nimport os\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.hubert.model import HubertASRTrainer as Trainer\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--resume', type=str, default=\"\", nargs=\"?\", help='resume ckpt path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/hubert/model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains hubert model.\"\"\"\nimport json\nimport math\nimport os\nimport re\nimport time\nfrom collections import OrderedDict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom hyperpyyaml import load_hyperpyyaml\nfrom paddle import distributed as dist\nfrom paddlenlp.transformers import AutoTokenizer\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.io.speechbrain import data_pipeline\nfrom paddlespeech.s2t.io.speechbrain import dataio\nfrom paddlespeech.s2t.io.speechbrain import dataset\nfrom paddlespeech.s2t.io.speechbrain.dataloader import make_dataloader\nfrom paddlespeech.s2t.models.hubert.hubert_ASR import HubertASR\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import TimeDomainSpecAugment\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\n# Todo: change this when paddle supports this api\ndef clip_grad_norm_(\n        parameters,\n        max_norm,\n        norm_type=2.0,\n        error_if_nonfinite=False, ):\n    r\"\"\"Clips gradient norm of the iteratable parameters.\n\n    Norms are calculated together on all gradients, just as they are\n    connected into one vector. The gradient will be modified in place.\n\n    This API can only run in dynamic graph mode, not static graph mode.\n\n    Args:\n        parameters (Iterable[paddle.Tensor] or paddle.Tensor): Tensors or a single Tensor\n            that will be normalized gradients\n        max_norm (float or int): max norm of the gradients\n        norm_type (float or int): type of the used p-norm. Can be `inf` for\n            infinity norm.\n        error_if_nonfinite (bool): if True, throw an error if the total\n            norm of the gradients from :attr:`parameters` is `nan`,\n            `inf`, or `-inf`.\n\n    Returns:\n        Total norm of the parameter gradients (treated as a single vector).\n    Example:\n        .. code-block:: python\n            import paddle\n\n            x = paddle.uniform([10, 10], min=-1.0, max=1.0, dtype='float32')\n            max_norm = float(5.0)\n            linear = paddle.nn.Linear(in_features=10, out_features=10)\n            out = linear(x)\n            loss = paddle.mean(out)\n            loss.backward()\n\n            paddle.nn.utils.clip_grad_norm_(linear.parameters(), max_norm)\n\n            sdg = paddle.optimizer.SGD(learning_rate=0.1, parameters=linear.parameters())\n            sdg.step()\n    \"\"\"\n    if not paddle.in_dynamic_mode():\n        raise RuntimeError('this API can only run in dynamic mode.')\n\n    if isinstance(parameters, paddle.Tensor):\n        parameters = [parameters]\n\n    support_norm_type = [float(\"inf\"), 0, 1, 2]\n    if norm_type not in support_norm_type:\n        raise ValueError(f'norm_type only support {support_norm_type}')\n\n    grads = [p.grad for p in parameters if p.grad is not None]\n    max_norm = float(max_norm)\n    norm_type = float(norm_type)\n    if len(grads) == 0:\n        return paddle.to_tensor(0.0)\n    if norm_type == float(\"inf\"):\n        norms = [g.detach().abs().max() for g in grads]\n        total_norm = (norms[0]\n                      if len(norms) == 1 else paddle.max(paddle.stack(norms)))\n    else:\n        total_norm = paddle.linalg.norm(\n            paddle.stack(\n                [paddle.linalg.norm(g.detach(), norm_type) for g in grads]),\n            norm_type, )\n\n    if error_if_nonfinite and paddle.logical_or(total_norm.isnan(),\n                                                total_norm.isinf()):\n        raise RuntimeError(\n            f'The total norm of {norm_type} order of the gradients from '\n            '`parameters` is non-finite, so it cannot be clipped. In any case, '\n            'disable this error and scale the gradient by non-finite norm, '\n            'set `error_if_nonfinite=False`')\n    clip_coef = max_norm / (total_norm + 1e-6)\n    # Note: when the coef is clamped to 1, it is redundant to multiply the clamped coef, but this\n    # avoids the `if clip_coef < 1:` condition.\n    clip_coef_clamped = paddle.clip(clip_coef, max=1.0)\n    with paddle.no_grad():\n        for _, p in enumerate(parameters):\n            g = p.grad\n            if g is not None:\n                p.grad = paddle.multiply(x=g, y=clip_coef_clamped)\n    return total_norm\n\n\nclass HubertASRTrainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.avg_train_loss = 0.0\n        self.loss_isfinite = True  # while flag is 'False', loss in Nan or inf, and can not be avg\n        self.use_sb = True  # whether use speech brain dataloader\n\n    def update_average(self, batch_index, loss):\n        \"\"\"Update running average of the loss.\n        Arguments\n        ---------\n        batch_index : int\n            current batch index\n        loss : paddle.tensor\n            detached loss, a single float value.\n        \"\"\"\n        if math.isfinite(loss):\n            self.avg_train_loss -= self.avg_train_loss / (batch_index + 1)\n            self.avg_train_loss += loss / (batch_index + 1)\n        else:\n            self.loss_isfinite = False\n            logger.info('loss:{} in Nan or inf, error'.format(loss))\n\n    def before_train(self):\n        from_scratch = self.resume_or_scratch()\n        if from_scratch:\n            # scratch: save init model, i.e. 0 epoch\n            self.save(tag='init', infos=None)\n        else:\n            # resume: train next_epoch and next_iteration\n            self.epoch += 1\n            logger.info(\n                f\"Resume train: epoch {self.epoch }, step {self.iteration}!\")\n\n        self.maybe_batch_sampler_step()\n\n    def train_batch(self, batch_index, batch, msg):\n        train_conf = self.config\n        start = time.time()\n\n        # forward\n        ## sb data pipeline\n        if self.use_sb:\n            wav, wavs_lens_rate = batch['sig']\n            target, target_lens_rate = batch['tokens']\n            target_lens = (target_lens_rate *\n                           target.shape[1]).round().astype(paddle.int64)\n        else:\n            utt, wav, wavs_lens, target, target_lens = batch\n            wavs_lens_rate = wavs_lens / wav.shape[1]\n            wav = wav[:, :, 0]\n        logger.info('training utt ids: {}'.format(utt))\n        if hasattr(train_conf, 'audio_augment'):\n            wav = self.speech_augmentation(wav, wavs_lens_rate)\n\n        loss = self.model(wav, wavs_lens_rate, target, target_lens)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        # update self.avg_train_loss\n        self.update_average(batch_index, float(loss))\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            # When using cpu w/o DDP, model does not have `no_sync`\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            loss.backward()\n\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step old\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            #do global grad clip\n            if train_conf.global_grad_clip != 0:\n                clip_grad_norm_(self.model.parameters(),\n                                train_conf.global_grad_clip)\n            self.model_optimizer.step()\n            self.model_optimizer.clear_grad()\n            if not train_conf.freeze_hubert:\n                self.hubert_optimizer.step()\n                self.hubert_optimizer.clear_grad()\n            if self.config.model_scheduler != 'newbobscheduler':\n                self.model_lr_scheduler.step()\n            if self.config.hubert_scheduler != 'newbobscheduler':\n                if not train_conf.freeze_hubert:\n                    self.hubert_lr_scheduler.step()\n            self.iteration += 1\n\n        losses_np = {'loss': self.avg_train_loss * train_conf.accum_grad}\n        iteration_time = time.time() - start\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"loss_whitoutavg\", float(loss))\n        report(\"batch_size\", self.config.batch_size)\n        report(\"accum\", train_conf.accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\n                    \"model_lr\": self.model_lr_scheduler(),\n                    \"hubert_lr\": self.hubert_lr_scheduler()\n                })\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag='train/' + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = {}\n        step = 0\n        total_loss = 0.0\n        num_seen_utts = 1  # use update_average and no need for num_seen_utts here\n        for i, batch in enumerate(self.valid_loader):\n            if self.use_sb:\n                wav, wavs_lens_rate = batch['sig']\n                target, target_lens_rate = batch['tokens']\n                target_lens = (target_lens_rate *\n                               target.shape[1]).round().astype(paddle.int64)\n            else:\n                utt, wav, wavs_lens, target, target_lens = batch\n                wavs_lens_rate = wavs_lens / wav.shape[1]\n                wav = wav[:, :, 0]\n\n            loss = self.model(wav, wavs_lens_rate, target, target_lens)\n            # use update_average\n            total_loss -= total_loss / (step + 1)\n            total_loss += loss / (step + 1)\n\n            if math.isfinite(float(loss)):\n                step += 1\n                valid_losses['val_loss'] = float(loss)\n            else:\n                logger.info('loss:{} in Nan or inf, error'.format(float(loss)))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_losses['val_history_loss'] = float(total_loss)\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_losses.items())\n                logger.info(msg)\n\n        logger.info(\n            'Rank {} Val info val_loss {}'.format(dist.get_rank(), total_loss))\n        return total_loss, num_seen_utts\n\n    @mp_tools.rank_zero_only\n    def save(self, tag=None, infos: dict=None):\n        \"\"\"Save checkpoint (model parameters and optimizer states).\n\n        Args:\n            tag (int or str, optional): None for step, else using tag, e.g epoch. Defaults to None.\n            infos (dict, optional): meta data to save. Defaults to None.\n        \"\"\"\n\n        infos = infos if infos else dict()\n        infos.update({\n            \"epoch\": self.epoch,\n            \"model_lr\": self.model_optimizer.get_lr(),\n            \"hubert_lr\": self.hubert_optimizer.get_lr()\n        })\n\n        checkpoint_path = os.path.join(\n            self.checkpoint_dir,\n            \"{}\".format(self.iteration if tag is None else tag))\n\n        model_dict = self.model.state_dict()\n        params_path = checkpoint_path + \".pdparams\"\n        paddle.save(model_dict, params_path)\n        logger.info(\"Saved model to {}\".format(params_path))\n\n        model_opt_dict = self.model_optimizer.state_dict()\n        hubert_opt_dict = self.hubert_optimizer.state_dict()\n\n        opt_dict = {'model': model_opt_dict, 'hubert': hubert_opt_dict}\n\n        optimizer_path = checkpoint_path + \".pdopt\"\n        paddle.save(opt_dict, optimizer_path)\n        logger.info(\"Saved optimzier state to {}\".format(optimizer_path))\n\n        scheduler_dict = {}\n\n        if self.config.model_scheduler == 'newbobscheduler':\n            scheduler_dict['model'] = self.model_lr_scheduler.save()\n        if self.config.hubert_scheduler == 'newbobscheduler':\n            scheduler_dict['hubert'] = self.hubert_lr_scheduler.save()\n        if scheduler_dict:\n            scheduler_path = checkpoint_path + \".pdlrs\"\n            paddle.save(scheduler_dict, scheduler_path)\n            logger.info(\"Saved scheduler state to {}\".format(scheduler_path))\n        info_path = re.sub('.pdparams$', '.json', params_path)\n        infos = {} if infos is None else infos\n        with open(info_path, 'w', encoding='utf8') as fout:\n            data = json.dumps(infos)\n            fout.write(data)\n\n    def resume_or_scratch(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        scratch = None\n        if self.args.resume:\n            # just restore ckpt\n            # lr will restore from optimizer ckpt\n            resume_json_path = os.path.join(self.checkpoint_dir,\n                                            self.args.resume + '.json')\n            with open(resume_json_path, 'r', encoding='utf8') as f:\n                resume_json = json.load(f)\n            self.iteration = 0\n            self.epoch = resume_json[\"epoch\"]\n\n            # restore model from *.pdparams\n            params_path = os.path.join(self.checkpoint_dir,\n                                       \"{}\".format(self.epoch)) + '.pdparams'\n            model_dict = paddle.load(params_path)\n            self.model.set_state_dict(model_dict)\n\n            # restore optimizer from *.pdopt\n            optimizer_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdopt'\n            optimizer_dict = paddle.load(optimizer_path)\n            self.model_optimizer.set_state_dict(optimizer_dict['model'])\n            self.hubert_optimizer.set_state_dict(optimizer_dict['hubert'])\n\n            # restore lr_scheduler from *.pdlrs\n            scheduler_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdlrs'\n            if os.path.isfile(os.path.join(scheduler_path)):\n                scheduler_dict = paddle.load(scheduler_path)\n                if self.config.model_scheduler == 'newbobscheduler':\n                    self.model_lr_scheduler.load(scheduler_dict['model'])\n                if self.config.hubert_scheduler == 'newbobscheduler':\n                    self.hubert_lr_scheduler.load(scheduler_dict['hubert'])\n            logger.info(\n                f\"Restore ckpt: epoch {self.epoch }, step {self.iteration}!\")\n            scratch = False\n        else:\n            self.iteration = 0\n            self.epoch = 0\n            scratch = True\n            logger.info(\"Init from scratch!\")\n        return scratch\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"model_lr\", self.model_optimizer.get_lr())\n                            report(\"hubert_lr\", self.hubert_optimizer.get_lr())\n                            self.train_batch(batch_index, batch, msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            if not self.use_streamdata:\n                                report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips,samples/s'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k.split(',')[0]}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += f\" {k.split(',')[1]}\" if len(\n                                k.split(',')) == 2 else \"\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = float(total_loss)\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/model_lr',\n                    value=self.model_lr_scheduler(),\n                    step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/hubert_lr',\n                    value=self.hubert_lr_scheduler(),\n                    step=self.epoch)\n\n            if self.config.model_scheduler == 'newbobscheduler':\n                self.model_lr_scheduler.step(cv_loss)\n            if self.config.hubert_scheduler == 'newbobscheduler':\n                if not self.config.freeze_hubert:\n                    self.hubert_lr_scheduler.step(cv_loss)\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.avg_train_loss = 0.0\n            self.new_epoch()\n\n    def dataio_prepare(self, hparams):\n        \"\"\"This function prepares the datasets to be used in the brain class.\n        It also defines the data processing pipeline through user-defined functions.\"\"\"\n        data_folder = hparams[\"data_folder\"]\n\n        train_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"train_data\"],\n            replacements={\"data_root\": data_folder}, )\n\n        if hparams[\"sorting\"] == \"ascending\":\n            # we sort training data to speed up training and get better results.\n            train_data = train_data.filtered_sorted(sort_key=\"duration\")\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"descending\":\n            train_data = train_data.filtered_sorted(\n                sort_key=\"duration\", reverse=True)\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"random\":\n            pass\n\n        else:\n            raise NotImplementedError(\n                \"sorting must be random, ascending or descending\")\n\n        valid_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"valid_data\"],\n            replacements={\"data_root\": data_folder}, )\n        valid_data = valid_data.filtered_sorted(sort_key=\"duration\")\n\n        test_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"test_data\"],\n            replacements={\"data_root\": data_folder}, )\n        test_data = test_data.filtered_sorted(sort_key=\"duration\")\n\n        datasets = [train_data, valid_data, test_data]\n\n        # Defining tokenizer and loading it\n        tokenizer = AutoTokenizer.from_pretrained('bert-base-chinese')\n        self.tokenizer = tokenizer\n\n        # 2. Define audio pipeline:\n        @data_pipeline.takes(\"wav\")\n        @data_pipeline.provides(\"sig\")\n        def audio_pipeline(wav):\n            sig = dataio.read_audio(wav)\n            return sig\n\n        dataset.add_dynamic_item(datasets, audio_pipeline)\n\n        # 3. Define text pipeline:\n        @data_pipeline.takes(\"transcript\")\n        @data_pipeline.provides(\"wrd\", \"tokens_list\", \"tokens\")\n        def text_pipeline(wrd):\n            wrd = \"\".join(wrd.split(\" \"))\n            yield wrd\n            tokens_list = tokenizer(wrd)[\"input_ids\"]\n            yield tokens_list\n            tokens = np.array(tokens_list, dtype=\"int64\")\n            # tokens = paddle.to_tensor(tokens_list, dtype=\"int64\")\n            yield tokens\n\n        dataset.add_dynamic_item(datasets, text_pipeline)\n\n        # 4. Set output:\n        dataset.set_output_keys(\n            datasets,\n            [\"id\", \"sig\", \"wrd\", \"tokens\"], )\n\n        # 5. If Dynamic Batching is used, we instantiate the needed samplers.\n        train_batch_sampler = None\n        valid_batch_sampler = None\n        if hparams[\"dynamic_batching\"]:\n            from sampler import DynamicBatchSampler  # noqa\n\n            dynamic_hparams = hparams[\"dynamic_batch_sampler\"]\n            num_buckets = dynamic_hparams[\"num_buckets\"]\n\n            train_batch_sampler = DynamicBatchSampler(\n                train_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n            valid_batch_sampler = DynamicBatchSampler(\n                valid_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n        return (train_data, valid_data, test_data, tokenizer,\n                train_batch_sampler, valid_batch_sampler, )\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        self.use_sb = config.get(\"use_sb_pipeline\", False)\n        if self.use_sb:\n            hparams_file = config.sb_pipeline_conf\n            with open(hparams_file, 'r', encoding='utf8') as fin:\n                hparams = load_hyperpyyaml(fin, None)\n\n            (train_data, valid_data, test_data, tokenizer, train_bsampler,\n             valid_bsampler, ) = self.dataio_prepare(hparams)\n\n            train_dataloader_opts = hparams[\"train_dataloader_opts\"]\n            valid_dataloader_opts = hparams[\"valid_dataloader_opts\"]\n\n            if train_bsampler is not None:\n                train_dataloader_opts = {\n                    \"batch_sampler\": train_bsampler,\n                    \"num_workers\": hparams[\"num_workers\"],\n                }\n\n            if valid_bsampler is not None:\n                valid_dataloader_opts = {\"batch_sampler\": valid_bsampler}\n\n            if self.train:\n                self.train_loader = make_dataloader(\n                    train_data, stage='train', **train_dataloader_opts)\n                self.valid_loader = make_dataloader(\n                    valid_data,\n                    stage='val',\n                    **valid_dataloader_opts, )\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                self.test_loader = make_dataloader(\n                    test_data, stage='test', **hparams[\"test_dataloader_opts\"])\n        else:\n            if self.train:\n                self.train_loader = DataLoaderFactory.get_dataloader(\n                    'train', config, self.args)\n                self.valid_loader = DataLoaderFactory.get_dataloader(\n                    'valid', config, self.args)\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                decode_batch_size = config.get('decode', dict()).get(\n                    'decode_batch_size', 1)\n                self.test_loader = DataLoaderFactory.get_dataloader(\n                    'test', config, self.args)\n                self.align_loader = DataLoaderFactory.get_dataloader(\n                    'align', config, self.args)\n                logger.info(\"Setup test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n\n        with UpdateConfig(model_conf):\n            if self.use_sb:\n                model_conf.output_dim = self.tokenizer.vocab_size\n            else:\n                if self.train:\n                    model_conf.input_dim = self.train_loader.feat_dim\n                    model_conf.output_dim = self.train_loader.vocab_size\n                else:\n                    model_conf.input_dim = self.test_loader.feat_dim\n                    model_conf.output_dim = self.test_loader.vocab_size\n\n        model = HubertASR.from_config(model_conf)\n\n        model_dict = paddle.load(config.hubert_params_path)\n        model.set_state_dict(model_dict)\n\n        if self.parallel:\n            model = paddle.DataParallel(model, find_unused_parameters=True)\n\n        layer_tools.print_params(model, logger.info)\n        self.model = model\n        logger.info(\"Setup model!\")\n\n        # setup speech augmentation for hubert\n        if hasattr(config, 'audio_augment') and self.train:\n            self.speech_augmentation = TimeDomainSpecAugment(\n                **config.audio_augment)\n\n        if not self.train:\n            return\n\n        train_config = config\n        model_optim_type = train_config.model_optim\n        model_optim_conf = train_config.model_optim_conf\n        logger.info(\"optim_model:{},{}\", model_optim_type, model_optim_conf)\n        hubert_optim_type = train_config.hubert_optim\n        hubert_optim_conf = train_config.hubert_optim_conf\n        logger.info(\"optim_model:{},{}\", hubert_optim_type, hubert_optim_conf)\n\n        model_scheduler_type = train_config.model_scheduler\n        model_scheduler_conf = train_config.model_scheduler_conf\n        hubert_scheduler_type = train_config.hubert_scheduler\n        hubert_scheduler_conf = train_config.hubert_scheduler_conf\n\n        model_scheduler_args = dict(\n            **{\"learning_rate\": model_optim_conf.lr,\n               \"verbose\": False}, **(dict(model_scheduler_conf)))\n\n        hubert_scheduler_args = dict(\n            **{\"learning_rate\": hubert_optim_conf.lr,\n               \"verbose\": False}, **(dict(hubert_scheduler_conf)))\n\n        model_lr_scheduler = LRSchedulerFactory.from_args(model_scheduler_type,\n                                                          model_scheduler_args)\n        hubert_lr_scheduler = LRSchedulerFactory.from_args(\n            hubert_scheduler_type, hubert_scheduler_args)\n\n        def optimizer_args(\n                config,\n                optim_type,\n                optim_conf,\n                parameters,\n                lr_scheduler=None, ):\n            optim_arg = dict(optim_conf)\n            optim_arg.update({\n                \"learning_rate\":\n                lr_scheduler if lr_scheduler else optim_conf.lr,\n                \"parameters\":\n                parameters\n            })\n            return optim_arg\n\n        model_optimizer_args = optimizer_args(config, model_optim_type,\n                                              model_optim_conf, [{\n                                                  'params':\n                                                  model._layers.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model._layers.ctc.parameters()\n                                              }] if self.parallel else [{\n                                                  'params':\n                                                  model.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model.ctc.parameters()\n                                              }], model_lr_scheduler)\n\n        hubert_optimizer_args = optimizer_args(\n            config, hubert_optim_type, hubert_optim_conf,\n            model._layers.hubert.parameters() if self.parallel else\n            model.hubert.parameters(), hubert_lr_scheduler)\n\n        model_optimizer = OptimizerFactory.from_args(model_optim_type,\n                                                     model_optimizer_args)\n        hubert_optimizer = OptimizerFactory.from_args(hubert_optim_type,\n                                                      hubert_optimizer_args)\n\n        self.model_optimizer = model_optimizer\n        self.hubert_optimizer = hubert_optimizer\n        self.model_lr_scheduler = model_lr_scheduler\n        self.hubert_lr_scheduler = hubert_lr_scheduler\n        logger.info(\"Setup optimizer/lr_scheduler!\")\n\n\nclass HubertASRTester(HubertASRTrainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_featurizer = TextFeaturizer(\n            unit_type=config.unit_type, vocab=config.vocab_filepath)\n        self.vocab_list = self.text_featurizer.vocab_list\n\n    def id2token(self, texts, texts_len):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(self.text_featurizer.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self, id, audio, audio_len, texts, texts_len,\n                        fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n\n        start_time = time.time()\n        target_transcripts = self.id2token(texts, texts_len)\n        result_transcripts, result_tokenids = self.model.decode(\n            audio,\n            text_feature=self.text_featurizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    def sb_compute_metrics(self, id, sig, wrd, tokens, fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n        start_time = time.time()\n        target_transcripts = wrd\n        result_transcripts, result_tokenids = self.model.decode(\n            sig[0],\n            text_feature=self.tokenizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            sb_pipeline=True)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=sig[1].sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n        self.model.eval()\n\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        # Initialized the decoder in model\n        decode_cfg = self.config.decode\n        vocab_list = self.vocab_list\n        decode_batch_size = decode_cfg.decode_batch_size\n\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                if self.use_sb:\n                    metrics = self.sb_compute_metrics(**batch, fout=fout)\n                else:\n                    metrics = self.compute_metrics(*batch, fout=fout)\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                rtf = num_time / (num_frames)\n                logger.info(\n                    \"RTF: %f, Error rate [%s] (%d/?) = %f\" %\n                    (rtf, error_rate_type, num_ins, errors_sum / len_refs))\n\n        # logging\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n\n        err_meta_path = os.path.splitext(self.args.result_file)[0] + '.err'\n        err_type_str = \"{}\".format(error_rate_type)\n        with open(err_meta_path, 'w', encoding='utf8') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                error_rate_type:\n                errors_sum / len_refs,\n                \"dataset_hour\": (num_frames) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"err_sum\":\n                errors_sum,\n                \"ref_len\":\n                len_refs,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/lm/transformer/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/lm/transformer/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/lm/transformer/bin/cacu_perplexity.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nimport configargparse\n\n\ndef get_parser():\n    \"\"\"Get default arguments.\"\"\"\n    parser = configargparse.ArgumentParser(\n        description=\"The parser for caculating the perplexity of transformer language model \",\n        config_file_parser_class=configargparse.YAMLConfigFileParser,\n        formatter_class=configargparse.ArgumentDefaultsHelpFormatter, )\n\n    parser.add_argument(\n        \"--rnnlm\", type=str, default=None, help=\"RNNLM model file to read\")\n\n    parser.add_argument(\n        \"--rnnlm-conf\",\n        type=str,\n        default=None,\n        help=\"RNNLM model config file to read\")\n\n    parser.add_argument(\n        \"--vocab_path\",\n        type=str,\n        default=None,\n        help=\"vocab path to for token2id\")\n\n    parser.add_argument(\n        \"--bpeprefix\",\n        type=str,\n        default=None,\n        help=\"The path of bpeprefix for loading\")\n\n    parser.add_argument(\n        \"--text_path\",\n        type=str,\n        default=None,\n        help=\"The path of text file for testing \")\n\n    parser.add_argument(\n        \"--ngpu\",\n        type=int,\n        default=0,\n        help=\"The number of gpu to use, 0 for using cpu instead\")\n\n    parser.add_argument(\n        \"--dtype\",\n        choices=(\"float16\", \"float32\", \"float64\"),\n        default=\"float32\",\n        help=\"Float precision (only available in --api v2)\", )\n\n    parser.add_argument(\n        \"--output_dir\",\n        type=str,\n        default=\".\",\n        help=\"The output directory to store the sentence PPL\")\n\n    return parser\n\n\ndef main(args):\n    parser = get_parser()\n    args = parser.parse_args(args)\n    from paddlespeech.s2t.exps.lm.transformer.lm_cacu_perplexity import run_get_perplexity\n    run_get_perplexity(args)\n\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "paddlespeech/s2t/exps/lm/transformer/lm_cacu_perplexity.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Caculating the PPL of LM model\nimport os\n\nimport numpy as np\nimport paddle\nfrom paddle.io import DataLoader\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.models.lm.dataset import TextCollatorSpm\nfrom paddlespeech.s2t.models.lm.dataset import TextDataset\nfrom paddlespeech.s2t.models.lm_interface import dynamic_import_lm\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\ndef get_config(config_path):\n    confs = CfgNode(new_allowed=True)\n    confs.merge_from_file(config_path)\n    return confs\n\n\ndef load_trained_lm(args):\n    lm_config = get_config(args.rnnlm_conf)\n    lm_model_module = lm_config.model_module\n    lm_class = dynamic_import_lm(lm_model_module)\n    lm = lm_class(**lm_config.model)\n    model_dict = paddle.load(args.rnnlm)\n    lm.set_state_dict(model_dict)\n    return lm, lm_config\n\n\ndef write_dict_into_file(ppl_dict, name):\n    with open(name, \"w\") as f:\n        for key in ppl_dict.keys():\n            f.write(key + \" \" + ppl_dict[key] + \"\\n\")\n    return\n\n\ndef cacu_perplexity(\n        lm_model,\n        lm_config,\n        args,\n        log_base=None, ):\n    unit_type = lm_config.data.unit_type\n    batch_size = lm_config.decoding.batch_size\n    num_workers = lm_config.decoding.num_workers\n    text_file_path = args.text_path\n\n    total_nll = 0.0\n    total_ntokens = 0\n    ppl_dict = {}\n    len_dict = {}\n    text_dataset = TextDataset.from_file(text_file_path)\n    collate_fn_text = TextCollatorSpm(\n        unit_type=unit_type,\n        vocab_filepath=args.vocab_path,\n        spm_model_prefix=args.bpeprefix)\n    train_loader = DataLoader(\n        text_dataset,\n        batch_size=batch_size,\n        collate_fn=collate_fn_text,\n        num_workers=num_workers)\n\n    logger.info(\"start caculating PPL......\")\n    for i, (keys, ys_input_pad, ys_output_pad,\n            y_lens) in enumerate(train_loader()):\n\n        ys_input_pad = paddle.to_tensor(ys_input_pad)\n        ys_output_pad = paddle.to_tensor(ys_output_pad)\n        _, unused_logp, unused_count, nll, nll_count = lm_model.forward(\n            ys_input_pad, ys_output_pad)\n        nll = nll.numpy()\n        nll_count = nll_count.numpy()\n        for key, _nll, ntoken in zip(keys, nll, nll_count):\n            if log_base is None:\n                utt_ppl = np.exp(_nll / ntoken)\n            else:\n                utt_ppl = log_base**(_nll / ntoken / np.log(log_base))\n\n            # Write PPL of each utts for debugging or analysis\n            ppl_dict[key] = str(utt_ppl)\n            len_dict[key] = str(ntoken)\n\n        total_nll += nll.sum()\n        total_ntokens += nll_count.sum()\n        logger.info(\"Current total nll: \" + str(total_nll))\n        logger.info(\"Current total tokens: \" + str(total_ntokens))\n    write_dict_into_file(ppl_dict, os.path.join(args.output_dir, \"uttPPL\"))\n    write_dict_into_file(len_dict, os.path.join(args.output_dir, \"uttLEN\"))\n    if log_base is None:\n        ppl = np.exp(total_nll / total_ntokens)\n    else:\n        ppl = log_base**(total_nll / total_ntokens / np.log(log_base))\n\n    if log_base is None:\n        log_base = np.e\n    else:\n        log_base = log_base\n\n    return ppl, log_base\n\n\ndef run_get_perplexity(args):\n    if args.ngpu > 1:\n        raise NotImplementedError(\"only single GPU decoding is supported\")\n    if args.ngpu == 1:\n        device = \"gpu:0\"\n    else:\n        device = \"cpu\"\n    paddle.set_device(device)\n    dtype = getattr(paddle, args.dtype)\n    logger.info(f\"Decoding device={device}, dtype={dtype}\")\n    lm_model, lm_config = load_trained_lm(args)\n    lm_model.to(device=device, dtype=dtype)\n    lm_model.eval()\n    PPL, log_base = cacu_perplexity(lm_model, lm_config, args, None)\n    logger.info(\"Final PPL: \" + str(PPL))\n    logger.info(\"The log base is:\" + str(\"%.2f\" % log_base))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/alignment.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Alignment for U2 model.\"\"\"\nfrom paddlespeech.s2t.exps.u2.model import U2Tester as Tester\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.training.cli import maybe_dump_config\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_align()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = config_from_args(args)\n    print(config)\n    maybe_dump_config(args.dump_config, config)\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/export.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Export for U2 model.\"\"\"\nfrom paddlespeech.s2t.exps.u2.model import U2Tester as Tester\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.training.cli import maybe_dump_config\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_export()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = config_from_args(args)\n    print(config)\n    maybe_dump_config(args.dump_config, config)\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/quant.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Quantzation U2 model.\"\"\"\nimport paddle\nfrom kaldiio import ReadHelper\nfrom paddleslim import PTQ\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.u2 import U2Model\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass U2Infer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_scp = args.audio_scp\n\n        self.preprocess_conf = config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n        self.text_feature = TextFeaturizer(\n            unit_type=config.unit_type,\n            vocab=config.vocab_filepath,\n            spm_model_prefix=config.spm_model_prefix)\n\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.input_dim = config.feat_dim\n            model_conf.output_dim = self.text_feature.vocab_size\n        model = U2Model.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n        self.ptq = PTQ()\n        self.model = self.ptq.quantize(model)\n\n        # load model\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n    def run(self):\n        cnt = 0\n        with ReadHelper(f\"scp:{self.audio_scp}\") as reader:\n            for key, (rate, audio) in reader:\n                assert rate == 16000\n                cnt += 1\n                if cnt > args.num_utts:\n                    break\n\n                with paddle.no_grad():\n                    logger.info(f\"audio shape: {audio.shape}\")\n\n                    # fbank\n                    feat = self.preprocessing(audio, **self.preprocess_args)\n                    logger.info(f\"feat shape: {feat.shape}\")\n\n                    ilen = paddle.to_tensor(feat.shape[0]).unsqueeze(0)\n                    xs = paddle.to_tensor(feat, dtype='float32').unsqueeze(0)\n                    decode_config = self.config.decode\n                    logger.info(f\"decode cfg: {decode_config}\")\n                    result_transcripts = self.model.decode(\n                        xs,\n                        ilen,\n                        text_feature=self.text_feature,\n                        decoding_method=decode_config.decoding_method,\n                        beam_size=decode_config.beam_size,\n                        ctc_weight=decode_config.ctc_weight,\n                        decoding_chunk_size=decode_config.decoding_chunk_size,\n                        num_decoding_left_chunks=decode_config.\n                        num_decoding_left_chunks,\n                        simulate_streaming=decode_config.simulate_streaming,\n                        reverse_weight=decode_config.reverse_weight)\n                    rsl = result_transcripts[0][0]\n                    utt = key\n                    logger.info(f\"hyp: {utt} {rsl}\")\n                    # print(self.model)\n                    # print(self.model.forward_encoder_chunk)\n\n        logger.info(\"-------------start quant ----------------------\")\n        batch_size = 1\n        feat_dim = 80\n        model_size = 512\n        num_left_chunks = -1\n        reverse_weight = 0.3\n        logger.info(\n            f\"U2 Export Model Params: batch_size {batch_size}, feat_dim {feat_dim}, model_size {model_size}, num_left_chunks {num_left_chunks}, reverse_weight {reverse_weight}\"\n        )\n\n        # ######################## self.model.forward_encoder_chunk ############\n        # input_spec = [\n        #     # (T,), int16\n        #     paddle.static.InputSpec(shape=[None], dtype='int16'),\n        # ]\n        # self.model.forward_feature = paddle.jit.to_static(\n        #     self.model.forward_feature, input_spec=input_spec)\n\n        ######################### self.model.forward_encoder_chunk ############\n        input_spec = [\n            # xs, (B, T, D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, feat_dim], dtype='float32'),\n            # offset, int, but need be tensor\n            paddle.static.InputSpec(shape=[1], dtype='int32'),\n            # required_cache_size, int\n            num_left_chunks,\n            # att_cache\n            paddle.static.InputSpec(\n                shape=[None, None, None, None], dtype='float32'),\n            # cnn_cache\n            paddle.static.InputSpec(\n                shape=[None, None, None, None], dtype='float32')\n        ]\n        self.model.forward_encoder_chunk = paddle.jit.to_static(\n            self.model.forward_encoder_chunk, input_spec=input_spec)\n\n        ######################### self.model.ctc_activation ########################\n        input_spec = [\n            # encoder_out, (B,T,D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, model_size], dtype='float32')\n        ]\n        self.model.ctc_activation = paddle.jit.to_static(\n            self.model.ctc_activation, input_spec=input_spec)\n\n        ######################### self.model.forward_attention_decoder ########################\n        input_spec = [\n            # hyps, (B, U)\n            paddle.static.InputSpec(shape=[None, None], dtype='int64'),\n            # hyps_lens, (B,)\n            paddle.static.InputSpec(shape=[None], dtype='int64'),\n            # encoder_out, (B,T,D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, model_size], dtype='float32'),\n            reverse_weight\n        ]\n        self.model.forward_attention_decoder = paddle.jit.to_static(\n            self.model.forward_attention_decoder, input_spec=input_spec)\n        ################################################################################\n\n        # jit save\n        logger.info(f\"export save: {self.args.export_path}\")\n        self.ptq.ptq._convert(self.model)\n        paddle.jit.save(\n            self.model,\n            self.args.export_path,\n            combine_params=True,\n            skip_forward=True)\n\n\ndef main(config, args):\n    U2Infer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n\n    config = config_from_args(args)\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for U2 model.\"\"\"\nimport cProfile\n\nfrom paddlespeech.s2t.exps.u2.model import U2Tester as Tester\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.training.cli import maybe_dump_config\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = config_from_args(args)\n    print(config)\n    maybe_dump_config(args.dump_config, config)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/test_wav.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for U2 model.\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.u2 import U2Model\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nlogger = Log(__name__).getlog()\n\n# TODO(hui zhang): dynamic load\n\n\nclass U2Infer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n\n        self.preprocess_conf = config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n        self.text_feature = TextFeaturizer(\n            unit_type=config.unit_type,\n            vocab=config.vocab_filepath,\n            spm_model_prefix=config.spm_model_prefix)\n\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.input_dim = config.feat_dim\n            model_conf.output_dim = self.text_feature.vocab_size\n        model = U2Model.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n    def run(self):\n        check(args.audio_file)\n\n        with paddle.no_grad():\n            # read\n            audio, sample_rate = soundfile.read(\n                self.audio_file, dtype=\"int16\", always_2d=True)\n            audio = audio[:, 0]\n            logger.info(f\"audio shape: {audio.shape}\")\n\n            # fbank\n            feat = self.preprocessing(audio, **self.preprocess_args)\n            logger.info(f\"feat shape: {feat.shape}\")\n            if self.args.debug:\n                np.savetxt(\"feat.transform.txt\", feat)\n\n            ilen = paddle.to_tensor(feat.shape[0]).unsqueeze(0)\n            xs = paddle.to_tensor(feat, dtype='float32').unsqueeze(0)\n            decode_config = self.config.decode\n            logger.info(f\"decode cfg: {decode_config}\")\n            reverse_weight = getattr(decode_config, 'reverse_weight', 0.0)\n            result_transcripts = self.model.decode(\n                xs,\n                ilen,\n                text_feature=self.text_feature,\n                decoding_method=decode_config.decoding_method,\n                beam_size=decode_config.beam_size,\n                ctc_weight=decode_config.ctc_weight,\n                decoding_chunk_size=decode_config.decoding_chunk_size,\n                num_decoding_left_chunks=decode_config.num_decoding_left_chunks,\n                simulate_streaming=decode_config.simulate_streaming,\n                reverse_weight=reverse_weight)\n            rsl = result_transcripts[0][0]\n            utt = Path(self.audio_file).name\n            logger.info(f\"hyp: {utt} {result_transcripts[0][0]}\")\n            return rsl\n\n\ndef check(audio_file):\n    if not os.path.isfile(audio_file):\n        print(\"Please input the right audio file path\")\n        sys.exit(-1)\n\n    logger.info(\"checking the audio file format......\")\n    try:\n        sig, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main(config, args):\n    U2Infer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n\n    config = config_from_args(args)\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/bin/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for U2 model.\"\"\"\nimport cProfile\nimport os\n\nfrom paddlespeech.s2t.exps.u2.model import U2Trainer as Trainer\nfrom paddlespeech.s2t.training.cli import config_from_args\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.training.cli import maybe_dump_config\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = config_from_args(args)\n    print(config)\n    maybe_dump_config(args.dump_path, config)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains U2 model.\"\"\"\nimport json\nimport os\nimport time\nfrom collections import defaultdict\nfrom collections import OrderedDict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.nn.utils import clip_grad_norm_\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.models.u2 import U2Model\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import ctc_utils\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass U2Trainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n\n    def train_batch(self, batch_index, batch_data, scaler, msg):\n        train_conf = self.config\n        start = time.time()\n\n        # forward\n        utt, audio, audio_len, text, text_len = batch_data\n        with paddle.amp.auto_cast(\n                level=self.amp_level, enable=True if scaler else False):\n            loss, attention_loss, ctc_loss = self.model(audio, audio_len, text,\n                                                        text_len)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        losses_np = {'loss': float(loss) * train_conf.accum_grad}\n        if attention_loss:\n            losses_np['att_loss'] = float(attention_loss)\n        if ctc_loss:\n            losses_np['ctc_loss'] = float(ctc_loss)\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            # When using cpu w/o DDP, model does not have `no_sync`\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            if scaler:\n                scaler.scale(loss).backward()\n            else:\n                loss.backward()\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            # do global grad clip\n            if train_conf.global_grad_clip != 0:\n                if scaler:\n                    scaler.unscale_(self.optimizer)\n                # need paddlepaddle==develop or paddlepaddle>=2.5\n                clip_grad_norm_(self.model.parameters(),\n                                train_conf.global_grad_clip)\n            if scaler:\n                scaler.step(self.optimizer)\n                scaler.update()\n            else:\n                self.optimizer.step()\n            self.optimizer.clear_grad()\n            self.lr_scheduler.step()\n            self.iteration += 1\n\n        iteration_time = time.time() - start\n\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"batch_size\", self.config.batch_size)\n        report(\"accum\", train_conf.accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\"lr\": self.lr_scheduler()})\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag='train/' + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = defaultdict(list)\n        num_seen_utts = 1\n        total_loss = 0.0\n        for i, batch in enumerate(self.valid_loader):\n            utt, audio, audio_len, text, text_len = batch\n            loss, attention_loss, ctc_loss = self.model(audio, audio_len, text,\n                                                        text_len)\n            if paddle.isfinite(loss):\n                num_utts = batch[1].shape[0]\n                num_seen_utts += num_utts\n                total_loss += float(loss) * num_utts\n                valid_losses['val_loss'].append(float(loss))\n                if attention_loss:\n                    valid_losses['val_att_loss'].append(float(attention_loss))\n                if ctc_loss:\n                    valid_losses['val_ctc_loss'].append(float(ctc_loss))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_dump = {k: np.mean(v) for k, v in valid_losses.items()}\n                valid_dump['val_history_loss'] = total_loss / num_seen_utts\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_dump.items())\n                logger.info(msg)\n\n        logger.info('Rank {} Val info val_loss {}'.format(\n            dist.get_rank(), total_loss / num_seen_utts))\n        return total_loss, num_seen_utts\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"lr\", self.lr_scheduler())\n                            self.train_batch(batch_index, batch, self.scaler,\n                                             msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            if not self.use_streamdata:\n                                report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips,samples/s'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k.split(',')[0]}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += f\" {k.split(',')[1]}\" if len(\n                                k.split(',')) == 2 else \"\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    # the default operator in all_reduce function is sum.\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = total_loss / num_seen_utts\n\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/lr', value=self.lr_scheduler(), step=self.epoch)\n\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.new_epoch()\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        if self.train:\n            self.train_loader = DataLoaderFactory.get_dataloader(\n                'train', config, self.args)\n            self.valid_loader = DataLoaderFactory.get_dataloader(\n                'valid', config, self.args)\n            logger.info(\"Setup train/valid Dataloader!\")\n        else:\n            decode_batch_size = config.get('decode', dict()).get(\n                'decode_batch_size', 1)\n            self.test_loader = DataLoaderFactory.get_dataloader('test', config,\n                                                                self.args)\n            self.align_loader = DataLoaderFactory.get_dataloader(\n                'align', config, self.args)\n            logger.info(\"Setup test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n\n        with UpdateConfig(model_conf):\n            if self.train:\n                model_conf.input_dim = self.train_loader.feat_dim\n                model_conf.output_dim = self.train_loader.vocab_size\n            else:\n                model_conf.input_dim = self.test_loader.feat_dim\n                model_conf.output_dim = self.test_loader.vocab_size\n\n        model = U2Model.from_config(model_conf)\n\n        # For Mixed Precision Training\n        self.use_amp = self.config.get(\"use_amp\", True)\n        self.amp_level = self.config.get(\"amp_level\", \"O1\")\n        if self.train and self.use_amp:\n            self.scaler = paddle.amp.GradScaler(\n                init_loss_scaling=self.config.get(\n                    \"scale_loss\", 32768.0))  #amp default num 32768.0\n            #Set amp_level\n            if self.amp_level == 'O2':\n                model = paddle.amp.decorate(models=model, level=self.amp_level)\n        else:\n            self.scaler = None\n        if self.parallel:\n            model = paddle.DataParallel(model)\n\n        logger.info(f\"{model}\")\n        layer_tools.print_params(model, logger.info)\n        self.model = model\n        logger.info(\"Setup model!\")\n\n        if not self.train:\n            return\n\n        train_config = config\n        optim_type = train_config.optim\n        optim_conf = train_config.optim_conf\n        scheduler_type = train_config.scheduler\n        scheduler_conf = train_config.scheduler_conf\n\n        scheduler_args = {\n            \"learning_rate\": optim_conf.lr,\n            \"verbose\": False,\n            \"warmup_steps\": scheduler_conf.warmup_steps,\n            \"gamma\": scheduler_conf.lr_decay,\n            \"d_model\": model_conf.encoder_conf.output_size,\n        }\n        lr_scheduler = LRSchedulerFactory.from_args(scheduler_type,\n                                                    scheduler_args)\n\n        def optimizer_args(\n                config,\n                parameters,\n                lr_scheduler=None, ):\n            train_config = config\n            optim_type = train_config.optim\n            optim_conf = train_config.optim_conf\n            scheduler_type = train_config.scheduler\n            scheduler_conf = train_config.scheduler_conf\n            return {\n                \"weight_decay\": optim_conf.weight_decay,\n                \"learning_rate\": lr_scheduler\n                if lr_scheduler else optim_conf.lr,\n                \"parameters\": parameters,\n                \"epsilon\": 1e-9 if optim_type == 'noam' else None,\n                \"beta1\": 0.9 if optim_type == 'noam' else None,\n                \"beat2\": 0.98 if optim_type == 'noam' else None,\n            }\n\n        optimzer_args = optimizer_args(config, model.parameters(), lr_scheduler)\n        optimizer = OptimizerFactory.from_args(optim_type, optimzer_args)\n\n        self.optimizer = optimizer\n        self.lr_scheduler = lr_scheduler\n        logger.info(\"Setup optimizer/lr_scheduler!\")\n\n\nclass U2Tester(U2Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n        self.vocab_list = self.text_feature.vocab_list\n\n    def id2token(self, texts, texts_len, text_feature):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(text_feature.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self,\n                        utts,\n                        audio,\n                        audio_len,\n                        texts,\n                        texts_len,\n                        fout=None):\n        decode_config = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_config.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_config.error_rate_type == 'cer' else error_rate.wer\n        reverse_weight = getattr(decode_config, 'reverse_weight', 0.0)\n\n        start_time = time.time()\n        target_transcripts = self.id2token(texts, texts_len, self.text_feature)\n\n        result_transcripts, result_tokenids = self.model.decode(\n            audio,\n            audio_len,\n            text_feature=self.text_feature,\n            decoding_method=decode_config.decoding_method,\n            beam_size=decode_config.beam_size,\n            ctc_weight=decode_config.ctc_weight,\n            decoding_chunk_size=decode_config.decoding_chunk_size,\n            num_decoding_left_chunks=decode_config.num_decoding_left_chunks,\n            simulate_streaming=decode_config.simulate_streaming,\n            reverse_weight=reverse_weight)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                utts, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_config.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_config.error_rate_type,\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        assert self.args.result_file\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n\n        stride_ms = self.config.stride_ms\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                metrics = self.compute_metrics(*batch, fout=fout)\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                rtf = num_time / (num_frames * stride_ms)\n                logger.info(\n                    \"RTF: %f, Error rate [%s] (%d/?) = %f\" %\n                    (rtf, error_rate_type, num_ins, errors_sum / len_refs))\n\n        rtf = num_time / (num_frames * stride_ms)\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"RTF: {}, \".format(rtf)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n\n        # test meta results\n        err_meta_path = os.path.splitext(self.args.result_file)[0] + '.err'\n        err_type_str = \"{}\".format(error_rate_type)\n        with open(err_meta_path, 'w') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                error_rate_type:\n                errors_sum / len_refs,\n                \"dataset_hour\": (num_frames * stride_ms) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"err_sum\":\n                errors_sum,\n                \"ref_len\":\n                len_refs,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n\n    @paddle.no_grad()\n    def align(self):\n        ctc_utils.ctc_align(self.config, self.model, self.align_loader,\n                            self.config.decode.decode_batch_size,\n                            self.config.stride_ms, self.vocab_list,\n                            self.args.result_file)\n\n    def load_inferspec(self):\n        \"\"\"infer model and input spec.\n\n        Returns:\n            nn.Layer: inference model\n            List[paddle.static.InputSpec]: input spec.\n        \"\"\"\n        from paddlespeech.s2t.models.u2 import U2InferModel\n        infer_model = U2InferModel.from_pretrained(self.test_loader,\n                                                   self.config.clone(),\n                                                   self.args.checkpoint_path)\n        batch_size = 1\n        feat_dim = self.test_loader.feat_dim\n        model_size = self.config.encoder_conf.output_size\n        num_left_chunks = -1\n        logger.info(\n            f\"U2 Export Model Params: batch_size {batch_size}, feat_dim {feat_dim}, model_size {model_size}, num_left_chunks {num_left_chunks}\"\n        )\n\n        return infer_model, (batch_size, feat_dim, model_size, num_left_chunks)\n\n    @paddle.no_grad()\n    def export(self):\n        infer_model, input_spec = self.load_inferspec()\n        infer_model.eval()\n        paddle.set_device('cpu')\n\n        assert isinstance(input_spec, (list, tuple)), type(input_spec)\n        batch_size, feat_dim, model_size, num_left_chunks = input_spec\n\n        ######################## infer_model.forward_encoder_chunk ############\n        input_spec = [\n            # (T,), int16\n            paddle.static.InputSpec(shape=[None], dtype='int16'),\n        ]\n        infer_model.forward_feature = paddle.jit.to_static(\n            infer_model.forward_feature, input_spec=input_spec)\n\n        ######################### infer_model.forward_encoder_chunk ############\n        input_spec = [\n            # xs, (B, T, D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, feat_dim], dtype='float32'),\n            # offset, int, but need be tensor\n            paddle.static.InputSpec(shape=[1], dtype='int32'),\n            # required_cache_size, int\n            num_left_chunks,\n            # att_cache\n            paddle.static.InputSpec(\n                shape=[None, None, None, None], dtype='float32'),\n            # cnn_cache\n            paddle.static.InputSpec(\n                shape=[None, None, None, None], dtype='float32')\n        ]\n        infer_model.forward_encoder_chunk = paddle.jit.to_static(\n            infer_model.forward_encoder_chunk, input_spec=input_spec)\n\n        ######################### infer_model.ctc_activation ########################\n        input_spec = [\n            # encoder_out, (B,T,D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, model_size], dtype='float32')\n        ]\n        infer_model.ctc_activation = paddle.jit.to_static(\n            infer_model.ctc_activation, input_spec=input_spec)\n\n        ######################### infer_model.forward_attention_decoder ########################\n        reverse_weight = 0.3\n        input_spec = [\n            # hyps, (B, U)\n            paddle.static.InputSpec(shape=[None, None], dtype='int64'),\n            # hyps_lens, (B,)\n            paddle.static.InputSpec(shape=[None], dtype='int64'),\n            # encoder_out, (B,T,D)\n            paddle.static.InputSpec(\n                shape=[batch_size, None, model_size], dtype='float32'),\n            reverse_weight\n        ]\n        infer_model.forward_attention_decoder = paddle.jit.to_static(\n            infer_model.forward_attention_decoder, input_spec=input_spec)\n\n        # jit save\n        logger.info(f\"export save: {self.args.export_path}\")\n        paddle.jit.save(\n            infer_model,\n            self.args.export_path,\n            combine_params=True,\n            skip_forward=True)\n\n        # test dy2static\n        def flatten(out):\n            if isinstance(out, paddle.Tensor):\n                return [out]\n\n            flatten_out = []\n            for var in out:\n                if isinstance(var, (list, tuple)):\n                    flatten_out.extend(flatten(var))\n                else:\n                    flatten_out.append(var)\n            return flatten_out\n\n        # forward_encoder_chunk dygraph\n        xs1 = paddle.full([1, 67, 80], 0.1, dtype='float32')\n        offset = paddle.to_tensor([0], dtype='int32')\n        required_cache_size = num_left_chunks\n        att_cache = paddle.zeros([0, 0, 0, 0])\n        cnn_cache = paddle.zeros([0, 0, 0, 0])\n        xs_d, att_cache_d, cnn_cache_d = infer_model.forward_encoder_chunk(\n            xs1, offset, required_cache_size, att_cache, cnn_cache)\n\n        # load static model\n        from paddle.jit.layer import Layer\n        layer = Layer()\n        logger.info(f\"load export model: {self.args.export_path}\")\n        layer.load(self.args.export_path, paddle.CPUPlace())\n\n        # forward_encoder_chunk static\n        xs1 = paddle.full([1, 67, 80], 0.1, dtype='float32')\n        offset = paddle.to_tensor([0], dtype='int32')\n        att_cache = paddle.zeros([0, 0, 0, 0])\n        cnn_cache = paddle.zeros([0, 0, 0, 0])\n        func = getattr(layer, 'forward_encoder_chunk')\n        xs_s, att_cache_s, cnn_cache_s = func(xs1, offset, att_cache, cnn_cache)\n        np.testing.assert_allclose(xs_d, xs_s, atol=1e-5)\n        np.testing.assert_allclose(att_cache_d, att_cache_s, atol=1e-4)\n        np.testing.assert_allclose(cnn_cache_d, cnn_cache_s, atol=1e-4)\n        # logger.info(f\"forward_encoder_chunk output: {xs_s}\")\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2/trainer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains U2 model.\"\"\"\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\n\nfrom paddlespeech.s2t.io.collator import SpeechCollator\nfrom paddlespeech.s2t.io.dataset import ManifestDataset\nfrom paddlespeech.s2t.io.sampler import SortagradBatchSampler\nfrom paddlespeech.s2t.io.sampler import SortagradDistributedBatchSampler\nfrom paddlespeech.s2t.models.u2 import U2Evaluator\nfrom paddlespeech.s2t.models.u2 import U2Model\nfrom paddlespeech.s2t.models.u2 import U2Updater\nfrom paddlespeech.s2t.training.extensions.snapshot import Snapshot\nfrom paddlespeech.s2t.training.extensions.visualizer import VisualDL\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.training.updaters.trainer import Trainer as NewTrainer\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass U2Trainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        config.defrost()\n        config.keep_transcription_text = False\n\n        # train/valid dataset, return token ids\n        config.manifest = config.train_manifest\n        train_dataset = ManifestDataset.from_config(config)\n\n        config.manifest = config.dev_manifest\n        dev_dataset = ManifestDataset.from_config(config)\n\n        collate_fn_train = SpeechCollator.from_config(config)\n\n        collate_fn_dev = SpeechCollator.from_config(config)\n\n        if self.parallel:\n            batch_sampler = SortagradDistributedBatchSampler(\n                train_dataset,\n                batch_size=config.batch_size,\n                num_replicas=None,\n                rank=None,\n                shuffle=True,\n                drop_last=True,\n                sortagrad=config.sortagrad,\n                shuffle_method=config.shuffle_method)\n        else:\n            batch_sampler = SortagradBatchSampler(\n                train_dataset,\n                shuffle=True,\n                batch_size=config.batch_size,\n                drop_last=True,\n                sortagrad=config.sortagrad,\n                shuffle_method=config.shuffle_method)\n        self.train_loader = DataLoader(\n            train_dataset,\n            batch_sampler=batch_sampler,\n            collate_fn=collate_fn_train,\n            num_workers=config.num_workers, )\n        self.valid_loader = DataLoader(\n            dev_dataset,\n            batch_size=config.batch_size,\n            shuffle=False,\n            drop_last=False,\n            collate_fn=collate_fn_dev,\n            num_workers=config.num_workers, )\n\n        # test dataset, return raw text\n        config.manifest = config.test_manifest\n        # filter test examples, will cause less examples, but no mismatch with training\n        # and can use large batch size , save training time, so filter test egs now.\n        config.min_input_len = 0.0  # second\n        config.max_input_len = float('inf')  # second\n        config.min_output_len = 0.0  # tokens\n        config.max_output_len = float('inf')  # tokens\n        config.min_output_input_ratio = 0.00\n        config.max_output_input_ratio = float('inf')\n\n        test_dataset = ManifestDataset.from_config(config)\n        # return text ord id\n        config.keep_transcription_text = True\n        self.test_loader = DataLoader(\n            test_dataset,\n            batch_size=config.decode.batch_size,\n            shuffle=False,\n            drop_last=False,\n            collate_fn=SpeechCollator.from_config(config))\n        # return text token id\n        config.keep_transcription_text = False\n        self.align_loader = DataLoader(\n            test_dataset,\n            batch_size=config.decode.batch_size,\n            shuffle=False,\n            drop_last=False,\n            collate_fn=SpeechCollator.from_config(config))\n        logger.info(\"Setup train/valid/test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.input_dim = self.train_loader.collate_fn.feature_size\n            model_conf.output_dim = self.train_loader.collate_fn.vocab_size\n\n        model = U2Model.from_config(model_conf)\n\n        if self.parallel:\n            model = paddle.DataParallel(model)\n\n        model.train()\n        logger.info(f\"{model}\")\n        layer_tools.print_params(model, logger.info)\n\n        train_config = config\n        optim_type = train_config.optim\n        optim_conf = train_config.optim_conf\n        scheduler_type = train_config.scheduler\n        scheduler_conf = train_config.scheduler_conf\n\n        scheduler_args = {\n            \"learning_rate\": optim_conf.lr,\n            \"verbose\": False,\n            \"warmup_steps\": scheduler_conf.warmup_steps,\n            \"gamma\": scheduler_conf.lr_decay,\n            \"d_model\": model_conf.encoder_conf.output_size,\n        }\n        lr_scheduler = LRSchedulerFactory.from_args(scheduler_type,\n                                                    scheduler_args)\n\n        def optimizer_args(\n                config,\n                parameters,\n                lr_scheduler=None, ):\n            train_config = config\n            optim_type = train_config.optim\n            optim_conf = train_config.optim_conf\n            scheduler_type = train_config.scheduler\n            scheduler_conf = train_config.scheduler_conf\n            return {\n                \"grad_clip\": train_config.global_grad_clip,\n                \"weight_decay\": optim_conf.weight_decay,\n                \"learning_rate\": lr_scheduler\n                if lr_scheduler else optim_conf.lr,\n                \"parameters\": parameters,\n                \"epsilon\": 1e-9 if optim_type == 'noam' else None,\n                \"beta1\": 0.9 if optim_type == 'noam' else None,\n                \"beat2\": 0.98 if optim_type == 'noam' else None,\n            }\n\n        optimzer_args = optimizer_args(config, model.parameters(), lr_scheduler)\n        optimizer = OptimizerFactory.from_args(optim_type, optimzer_args)\n\n        self.model = model\n        self.optimizer = optimizer\n        self.lr_scheduler = lr_scheduler\n        logger.info(\"Setup model/optimizer/lr_scheduler!\")\n\n    def setup_updater(self):\n        output_dir = self.output_dir\n        config = self.config\n\n        updater = U2Updater(\n            model=self.model,\n            optimizer=self.optimizer,\n            scheduler=self.lr_scheduler,\n            dataloader=self.train_loader,\n            output_dir=output_dir,\n            accum_grad=config.accum_grad)\n\n        trainer = NewTrainer(updater, (config.n_epoch, 'epoch'), output_dir)\n\n        evaluator = U2Evaluator(self.model, self.valid_loader)\n\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n\n        if dist.get_rank() == 0:\n            trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n            num_snapshots = config.checkpoint.kbest_n\n            trainer.extend(\n                Snapshot(\n                    mode='kbest',\n                    max_size=num_snapshots,\n                    indicator='VALID/LOSS',\n                    less_better=True),\n                trigger=(1, 'epoch'))\n        # print(trainer.extensions)\n        # trainer.run()\n        self.trainer = trainer\n\n    def run(self):\n        \"\"\"The routine of the experiment after setup. This method is intended\n        to be used by the user.\n        \"\"\"\n        self.setup_updater()\n        with Timer(\"Training Done: {}\"):\n            self.trainer.run()\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/bin/recog.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nfrom paddlespeech.s2t.decoders.recog_bin import main\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/bin/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for U2 model.\"\"\"\nimport cProfile\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\nfrom paddlespeech.utils.argparse import print_arguments\n\nmodel_test_alias = {\n    \"u2\": \"paddlespeech.s2t.exps.u2.model:U2Tester\",\n    \"u2_kaldi\": \"paddlespeech.s2t.exps.u2_kaldi.model:U2Tester\",\n}\n\n\ndef main_sp(config, args):\n    class_obj = dynamic_import(args.model_name, model_test_alias)\n    exp = class_obj(config, args)\n    with exp.eval():\n        exp.setup()\n        if args.run_mode == 'test':\n            exp.run_test()\n        elif args.run_mode == 'export':\n            exp.run_export()\n        elif args.run_mode == 'align':\n            exp.run_align()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--model-name',\n        type=str,\n        default='u2_kaldi',\n        help='model name, e.g: deepspeech2, u2, u2_kaldi, u2_st')\n    parser.add_argument(\n        '--run-mode',\n        type=str,\n        default='test',\n        help='run mode, e.g. test, align, export')\n    parser.add_argument(\n        '--dict-path', type=str, default=None, help='dict path.')\n    # save asr result to \n    parser.add_argument(\n        \"--result-file\", type=str, help=\"path of save the asr result\")\n    # save jit model to \n    parser.add_argument(\n        \"--export-path\", type=str, help=\"path of the jit model to save\")\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = CfgNode()\n    config.set_new_allowed(True)\n    config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/bin/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for U2 model.\"\"\"\nimport cProfile\nimport os\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\nfrom paddlespeech.utils.argparse import print_arguments\n\nmodel_train_alias = {\n    \"u2\": \"paddlespeech.s2t.exps.u2.model:U2Trainer\",\n    \"u2_kaldi\": \"paddlespeech.s2t.exps.u2_kaldi.model:U2Trainer\",\n}\n\n\ndef main_sp(config, args):\n    class_obj = dynamic_import(args.model_name, model_train_alias)\n    exp = class_obj(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--model-name',\n        type=str,\n        default='u2_kaldi',\n        help='model name, e.g: deepspeech2, u2, u2_kaldi, u2_st')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    config = CfgNode()\n    config.set_new_allowed(True)\n    config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_kaldi/model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains U2 model.\"\"\"\nimport json\nimport os\nimport time\nfrom collections import defaultdict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle import distributed as dist\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.frontend.utility import load_dict\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.models.u2 import U2Model\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import ctc_utils\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass U2Trainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n\n    def train_batch(self, batch_index, batch_data, msg):\n        train_conf = self.config\n        start = time.time()\n\n        # forward\n        utt, audio, audio_len, text, text_len = batch_data\n        loss, attention_loss, ctc_loss = self.model(audio, audio_len, text,\n                                                    text_len)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        losses_np = {'loss': float(loss) * train_conf.accum_grad}\n        if attention_loss:\n            losses_np['att_loss'] = float(attention_loss)\n        if ctc_loss:\n            losses_np['ctc_loss'] = float(ctc_loss)\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            loss.backward()\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            self.optimizer.step()\n            self.optimizer.clear_grad()\n            self.lr_scheduler.step()\n            self.iteration += 1\n\n        iteration_time = time.time() - start\n\n        if (batch_index + 1) % train_conf.log_interval == 0:\n            msg += \"train time: {:>.3f}s, \".format(iteration_time)\n            msg += \"batch size: {}, \".format(self.config.batch_size)\n            msg += \"accum: {}, \".format(train_conf.accum_grad)\n            msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                             for k, v in losses_np.items())\n            logger.info(msg)\n\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\"lr\": self.lr_scheduler()})\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag=\"train/\" + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = defaultdict(list)\n        num_seen_utts = 1\n        total_loss = 0.0\n\n        for i, batch in enumerate(self.valid_loader):\n            utt, audio, audio_len, text, text_len = batch\n            loss, attention_loss, ctc_loss = self.model(audio, audio_len, text,\n                                                        text_len)\n            if paddle.isfinite(loss):\n                num_utts = batch[1].shape[0]\n                num_seen_utts += num_utts\n                total_loss += float(loss) * num_utts\n                valid_losses['val_loss'].append(float(loss))\n                if attention_loss:\n                    valid_losses['val_att_loss'].append(float(attention_loss))\n                if ctc_loss:\n                    valid_losses['val_ctc_loss'].append(float(ctc_loss))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_dump = {k: np.mean(v) for k, v in valid_losses.items()}\n                valid_dump['val_history_loss'] = total_loss / num_seen_utts\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_dump.items())\n                logger.info(msg)\n\n        logger.info('Rank {} Val info val_loss {}'.format(\n            dist.get_rank(), total_loss / num_seen_utts))\n        return total_loss, num_seen_utts\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train: Rank: {}, \".format(dist.get_rank())\n                        msg += \"epoch: {}, \".format(self.epoch)\n                        msg += \"step: {}, \".format(self.iteration)\n                        if not self.use_streamdata:\n                            msg += \"batch : {}/{}, \".format(\n                                batch_index + 1, len(self.train_loader))\n                        msg += \"lr: {:>.8f}, \".format(self.lr_scheduler())\n                        msg += \"data time: {:>.3f}s, \".format(dataload_time)\n                        self.train_batch(batch_index, batch, msg)\n                        self.after_train_batch()\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    # the default operator in all_reduce function is sum.\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = total_loss / num_seen_utts\n\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/lr', value=self.lr_scheduler(), step=self.epoch)\n\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.new_epoch()\n\n    def setup_dataloader(self):\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        if self.train:\n            config = self.config.clone()\n            self.train_loader = DataLoaderFactory.get_dataloader(\n                'train', config, self.args)\n            config = self.config.clone()\n            config['preprocess_config'] = None\n            self.valid_loader = DataLoaderFactory.get_dataloader(\n                'valid', config, self.args)\n            logger.info(\"Setup train/valid Dataloader!\")\n        else:\n            config = self.config.clone()\n            config['preprocess_config'] = None\n            self.test_loader = DataLoaderFactory.get_dataloader('test', config,\n                                                                self.args)\n            config = self.config.clone()\n            config['preprocess_config'] = None\n            self.align_loader = DataLoaderFactory.get_dataloader(\n                'align', config, self.args)\n            logger.info(\"Setup test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.input_dim = self.train_loader.feat_dim\n            model_conf.output_dim = self.train_loader.vocab_size\n        model = U2Model.from_config(model_conf)\n        if self.parallel:\n            model = paddle.DataParallel(model)\n        layer_tools.print_params(model, logger.info)\n\n        # lr\n        scheduler_conf = config.scheduler_conf\n        scheduler_args = {\n            \"learning_rate\": scheduler_conf.lr,\n            \"warmup_steps\": scheduler_conf.warmup_steps,\n            \"gamma\": scheduler_conf.lr_decay,\n            \"d_model\": model_conf.encoder_conf.output_size,\n            \"verbose\": False,\n        }\n        lr_scheduler = LRSchedulerFactory.from_args(config.scheduler,\n                                                    scheduler_args)\n\n        # opt\n        def optimizer_args(\n                config,\n                parameters,\n                lr_scheduler=None, ):\n            optim_conf = config.optim_conf\n            return {\n                \"grad_clip\": optim_conf.global_grad_clip,\n                \"weight_decay\": optim_conf.weight_decay,\n                \"learning_rate\": lr_scheduler,\n                \"parameters\": parameters,\n            }\n\n        optimzer_args = optimizer_args(config, model.parameters(), lr_scheduler)\n        optimizer = OptimizerFactory.from_args(config.optim, optimzer_args)\n\n        self.model = model\n        self.lr_scheduler = lr_scheduler\n        self.optimizer = optimizer\n        logger.info(\"Setup model/optimizer/lr_scheduler!\")\n\n\nclass U2Tester(U2Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n        self.vocab_list = self.text_feature.vocab_list\n\n    def id2token(self, texts, texts_len, text_feature):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(text_feature.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self,\n                        utts,\n                        audio,\n                        audio_len,\n                        texts,\n                        texts_len,\n                        fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n\n        start_time = time.time()\n        target_transcripts = self.id2token(texts, texts_len, self.text_feature)\n        result_transcripts, result_tokenids = self.model.decode(\n            audio,\n            audio_len,\n            text_feature=self.text_feature,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            ctc_weight=decode_cfg.ctc_weight,\n            decoding_chunk_size=decode_cfg.decoding_chunk_size,\n            num_decoding_left_chunks=decode_cfg.num_decoding_left_chunks,\n            simulate_streaming=decode_cfg.simulate_streaming)\n        decode_time = time.time() - start_time\n\n        for i, (utt, target, result, rec_tids) in enumerate(\n                zip(utts, target_transcripts, result_transcripts,\n                    result_tokenids)):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\n                \"One example error rate [%s] = %f\" %\n                (decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        assert self.args.result_file\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n\n        stride_ms = self.config.stride_ms\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                metrics = self.compute_metrics(*batch, fout=fout)\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                rtf = num_time / (num_frames * stride_ms)\n                logger.info(\n                    \"RTF: %f, Error rate [%s] (%d/?) = %f\" %\n                    (rtf, error_rate_type, num_ins, errors_sum / len_refs))\n\n        rtf = num_time / (num_frames * stride_ms)\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"RTF: {}, \".format(rtf)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n\n        # test meta results\n        err_meta_path = os.path.splitext(self.args.result_file)[0] + '.err'\n        err_type_str = \"{}\".format(error_rate_type)\n        with open(err_meta_path, 'w') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                error_rate_type:\n                errors_sum / len_refs,\n                \"dataset_hour\": (num_frames * stride_ms) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"err_sum\":\n                errors_sum,\n                \"ref_len\":\n                len_refs,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n\n    @paddle.no_grad()\n    def align(self):\n        ctc_utils.ctc_align(self.config, self.model, self.align_loader,\n                            self.config.decode.decode_batch_size,\n                            self.config.stride_ms, self.vocab_list,\n                            self.args.result_file)\n\n    def load_inferspec(self):\n        \"\"\"infer model and input spec.\n\n        Returns:\n            nn.Layer: inference model\n            List[paddle.static.InputSpec]: input spec.\n        \"\"\"\n        from paddlespeech.s2t.models.u2 import U2InferModel\n        infer_model = U2InferModel.from_pretrained(self.test_loader,\n                                                   self.config.clone(),\n                                                   self.args.checkpoint_path)\n        feat_dim = self.test_loader.feat_dim\n        input_spec = [\n            paddle.static.InputSpec(shape=[1, None, feat_dim],\n                                    dtype='float32'),  # audio, [B,T,D]\n            paddle.static.InputSpec(shape=[1],\n                                    dtype='int64'),  # audio_length, [B]\n        ]\n        return infer_model, input_spec\n\n    @paddle.no_grad()\n    def export(self):\n        infer_model, input_spec = self.load_inferspec()\n        assert isinstance(input_spec, list), type(input_spec)\n        infer_model.eval()\n        static_model = paddle.jit.to_static(infer_model, input_spec=input_spec)\n        logger.info(f\"Export code: {static_model.forward.code}\")\n        paddle.jit.save(static_model, self.args.export_path)\n\n    def setup_dict(self):\n        # load dictionary for debug log\n        self.args.char_list = load_dict(self.args.dict_path,\n                                        \"maskctc\" in self.args.model_name)\n\n    def setup(self):\n        super().setup()\n        self.setup_dict()\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/bin/export.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Export for U2 model.\"\"\"\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.u2_st.model import U2STTester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_export()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save jit model to\n    parser.add_argument(\n        \"--export_path\", type=str, help=\"path of the jit model to save\")\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/bin/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for U2 model.\"\"\"\nimport cProfile\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.u2_st.model import U2STTester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_conf = CfgNode(new_allowed=True)\n        decode_conf.merge_from_file(args.decode_cfg)\n        config.decode = decode_conf\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/bin/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for U2 model.\"\"\"\nimport cProfile\nimport os\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.u2_st.model import U2STTrainer as Trainer\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/u2_st/model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains U2 model.\"\"\"\nimport json\nimport os\nimport time\nfrom collections import defaultdict\nfrom collections import OrderedDict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle import distributed as dist\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.models.u2_st import U2STModel\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import bleu_score\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\nclass U2STTrainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n\n    def train_batch(self, batch_index, batch_data, msg):\n        train_conf = self.config\n        start = time.time()\n        # forward\n        utt, audio, audio_len, text, text_len = batch_data\n        if isinstance(text, list) and isinstance(text_len, list):\n            # joint training with ASR. Two decoding texts [translation, transcription]\n            text, text_transcript = text\n            text_len, text_transcript_len = text_len\n            loss, st_loss, attention_loss, ctc_loss = self.model(\n                audio, audio_len, text, text_len, text_transcript,\n                text_transcript_len)\n        else:\n            loss, st_loss, attention_loss, ctc_loss = self.model(\n                audio, audio_len, text, text_len)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        losses_np = {'loss': float(loss) * train_conf.accum_grad}\n        if st_loss:\n            losses_np['st_loss'] = float(st_loss)\n        if attention_loss:\n            losses_np['att_loss'] = float(attention_loss)\n        if ctc_loss:\n            losses_np['ctc_loss'] = float(ctc_loss)\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            loss.backward()\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            self.optimizer.step()\n            self.optimizer.clear_grad()\n            self.lr_scheduler.step()\n            self.iteration += 1\n\n        iteration_time = time.time() - start\n\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"batch_size\", self.config.batch_size)\n        report(\"accum\", train_conf.accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if (batch_index + 1) % train_conf.log_interval == 0:\n            msg += \"train time: {:>.3f}s, \".format(iteration_time)\n            msg += \"batch size: {}, \".format(self.config.batch_size)\n            msg += \"accum: {}, \".format(train_conf.accum_grad)\n            msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                             for k, v in losses_np.items())\n            logger.info(msg)\n\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\"lr\": self.lr_scheduler()})\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag=\"train/\" + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = defaultdict(list)\n        num_seen_utts = 1\n        total_loss = 0.0\n        for i, batch in enumerate(self.valid_loader):\n            utt, audio, audio_len, text, text_len = batch\n            if isinstance(text, list) and isinstance(text_len, list):\n                text, text_transcript = text\n                text_len, text_transcript_len = text_len\n                loss, st_loss, attention_loss, ctc_loss = self.model(\n                    audio, audio_len, text, text_len, text_transcript,\n                    text_transcript_len)\n            else:\n                loss, st_loss, attention_loss, ctc_loss = self.model(\n                    audio, audio_len, text, text_len)\n            if paddle.isfinite(loss):\n                num_utts = batch[1].shape[0]\n                num_seen_utts += num_utts\n                total_loss += float(st_loss) * num_utts\n                valid_losses['val_loss'].append(float(st_loss))\n                if attention_loss:\n                    valid_losses['val_att_loss'].append(float(attention_loss))\n                if ctc_loss:\n                    valid_losses['val_ctc_loss'].append(float(ctc_loss))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_dump = {k: np.mean(v) for k, v in valid_losses.items()}\n                valid_dump['val_history_st_loss'] = total_loss / num_seen_utts\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_dump.items())\n                logger.info(msg)\n\n        logger.info('Rank {} Val info st_val_loss {}'.format(\n            dist.get_rank(), total_loss / num_seen_utts))\n        return total_loss, num_seen_utts\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"lr\", self.lr_scheduler())\n                            self.train_batch(batch_index, batch, msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            if not self.use_streamdata:\n                                report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips,sent./sec'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k.split(',')[0]}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += f\" {k.split(',')[1]}\" if len(\n                                k.split(',')) == 2 else \"\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    # the default operator in all_reduce function is sum.\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = total_loss / num_seen_utts\n\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/lr', value=self.lr_scheduler(), step=self.epoch)\n\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.new_epoch()\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n\n        load_transcript = True if config.model_conf.asr_weight > 0 else False\n\n        config = self.config.clone()\n        config['load_transcript'] = load_transcript\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        if self.train:\n            self.train_loader = DataLoaderFactory.get_dataloader(\n                'train', config, self.args)\n            self.valid_loader = DataLoaderFactory.get_dataloader(\n                'valid', config, self.args)\n            logger.info(\"Setup train/valid Dataloader!\")\n        else:\n            self.test_loader = DataLoaderFactory.get_dataloader('test', config,\n                                                                self.args)\n            logger.info(\"Setup test Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n        with UpdateConfig(model_conf):\n            if self.train:\n                model_conf.input_dim = self.train_loader.feat_dim\n                model_conf.output_dim = self.train_loader.vocab_size\n            else:\n                model_conf.input_dim = self.test_loader.feat_dim\n                model_conf.output_dim = self.test_loader.vocab_size\n\n        model = U2STModel.from_config(model_conf)\n\n        if self.parallel:\n            model = paddle.DataParallel(model)\n\n        logger.info(f\"{model}\")\n        layer_tools.print_params(model, logger.info)\n\n        train_config = config\n        optim_type = train_config.optim\n        optim_conf = train_config.optim_conf\n        scheduler_type = train_config.scheduler\n        scheduler_conf = train_config.scheduler_conf\n\n        scheduler_args = {\n            \"learning_rate\": optim_conf.lr,\n            \"verbose\": False,\n            \"warmup_steps\": scheduler_conf.warmup_steps,\n            \"gamma\": scheduler_conf.lr_decay,\n            \"d_model\": model_conf.encoder_conf.output_size,\n        }\n        lr_scheduler = LRSchedulerFactory.from_args(scheduler_type,\n                                                    scheduler_args)\n\n        def optimizer_args(\n                config,\n                parameters,\n                lr_scheduler=None, ):\n            train_config = config\n            optim_type = train_config.optim\n            optim_conf = train_config.optim_conf\n            scheduler_type = train_config.scheduler\n            scheduler_conf = train_config.scheduler_conf\n            return {\n                \"grad_clip\": train_config.global_grad_clip,\n                \"weight_decay\": optim_conf.weight_decay,\n                \"learning_rate\": lr_scheduler\n                if lr_scheduler else optim_conf.lr,\n                \"parameters\": parameters,\n                \"epsilon\": 1e-9 if optim_type == 'noam' else None,\n                \"beta1\": 0.9 if optim_type == 'noam' else None,\n                \"beat2\": 0.98 if optim_type == 'noam' else None,\n            }\n\n        optimzer_args = optimizer_args(config, model.parameters(), lr_scheduler)\n        optimizer = OptimizerFactory.from_args(optim_type, optimzer_args)\n\n        self.model = model\n        self.optimizer = optimizer\n        self.lr_scheduler = lr_scheduler\n        logger.info(\"Setup model/optimizer/lr_scheduler!\")\n\n\nclass U2STTester(U2STTrainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n        self.vocab_list = self.text_feature.vocab_list\n\n    def id2token(self, texts, texts_len, text_feature):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(text_feature.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def translate(self, audio, audio_len):\n        \"\"\"\"E2E translation from extracted audio feature\"\"\"\n        decode_cfg = self.config.decode\n        self.model.eval()\n\n        hyps = self.model.decode(\n            audio,\n            audio_len,\n            text_feature=self.text_feature,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            word_reward=decode_cfg.word_reward,\n            maxlenratio=decode_cfg.maxlenratio,\n            decoding_chunk_size=decode_cfg.decoding_chunk_size,\n            num_decoding_left_chunks=decode_cfg.num_decoding_left_chunks,\n            simulate_streaming=decode_cfg.simulate_streaming)\n        return hyps\n\n    def compute_translation_metrics(self,\n                                    utts,\n                                    audio,\n                                    audio_len,\n                                    texts,\n                                    texts_len,\n                                    bleu_func,\n                                    fout=None):\n        decode_cfg = self.config.decode\n        len_refs, num_ins = 0, 0\n\n        start_time = time.time()\n\n        refs = self.id2token(texts, texts_len, self.text_feature)\n\n        hyps = self.model.decode(\n            audio,\n            audio_len,\n            text_feature=self.text_feature,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            word_reward=decode_cfg.word_reward,\n            maxlenratio=decode_cfg.maxlenratio,\n            decoding_chunk_size=decode_cfg.decoding_chunk_size,\n            num_decoding_left_chunks=decode_cfg.num_decoding_left_chunks,\n            simulate_streaming=decode_cfg.simulate_streaming)\n\n        decode_time = time.time() - start_time\n\n        for utt, target, result in zip(utts, refs, hyps):\n            len_refs += len(target.split())\n            num_ins += 1\n            if fout:\n                fout.write({\"utt\": utt, \"ref\": target, \"hyp\": result})\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example BLEU = %s\" %\n                        (bleu_func([result], [[target]]).prec_str))\n\n        return dict(\n            hyps=hyps,\n            refs=refs,\n            bleu=bleu_func(hyps, [refs]).score,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        assert self.args.result_file\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n\n        decode_cfg = self.config.decode\n        bleu_func = bleu_score.char_bleu if decode_cfg.error_rate_type == 'char-bleu' else bleu_score.bleu\n\n        stride_ms = self.config.stride_ms\n        hyps, refs = [], []\n        len_refs, num_ins = 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                metrics = self.compute_translation_metrics(\n                    *batch, bleu_func=bleu_func, fout=fout)\n                hyps += metrics['hyps']\n                refs += metrics['refs']\n                bleu = metrics['bleu']\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                rtf = num_time / (num_frames * stride_ms)\n                logger.info(\"RTF: %f, instance (%d), batch BELU   = %f\" %\n                            (rtf, num_ins, bleu))\n\n        rtf = num_time / (num_frames * stride_ms)\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"RTF: {}, \".format(rtf)\n        msg += \"Test set [%s]: %s\" % (len(hyps), str(bleu_func(hyps, [refs])))\n        logger.info(msg)\n        bleu_meta_path = os.path.splitext(self.args.result_file)[0] + '.bleu'\n        err_type_str = \"BLEU\"\n        with open(bleu_meta_path, 'w') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                err_type_str:\n                bleu_func(hyps, [refs]).score,\n                \"dataset_hour\": (num_frames * stride_ms) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n\n    def load_inferspec(self):\n        \"\"\"infer model and input spec.\n\n        Returns:\n            nn.Layer: inference model\n            List[paddle.static.InputSpec]: input spec.\n        \"\"\"\n        from paddlespeech.s2t.models.u2_st import U2STInferModel\n        infer_model = U2STInferModel.from_pretrained(self.test_loader,\n                                                     self.config.clone(),\n                                                     self.args.checkpoint_path)\n        feat_dim = self.test_loader.feat_dim\n        input_spec = [\n            paddle.static.InputSpec(shape=[1, None, feat_dim],\n                                    dtype='float32'),  # audio, [B,T,D]\n            paddle.static.InputSpec(shape=[1],\n                                    dtype='int64'),  # audio_length, [B]\n        ]\n        return infer_model, input_spec\n\n    @paddle.no_grad()\n    def export(self):\n        infer_model, input_spec = self.load_inferspec()\n        assert isinstance(input_spec, list), type(input_spec)\n        infer_model.eval()\n        static_model = paddle.jit.to_static(infer_model, input_spec=input_spec)\n        logger.info(f\"Export code: {static_model.forward.code}\")\n        paddle.jit.save(static_model, self.args.export_path)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/bin/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/bin/test.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for wav2vec2.0 model.\"\"\"\nimport cProfile\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.wav2vec2.model import Wav2Vec2ASRTester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save asr result to\n    parser.add_argument(\n        '--dict-path', type=str, default=None, help='dict path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/bin/test_wav.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for wav2vec2.0 model.\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\n\nimport paddle\nimport soundfile\nfrom paddlenlp.transformers import AutoTokenizer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.wav2vec2.wav2vec2_ASR import Wav2vec2ASR\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nlogger = Log(__name__).getlog()\n\n\nclass Wav2vec2Infer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n        self.tokenizer = config.get(\"tokenizer\", None)\n\n        if self.tokenizer:\n            self.text_feature = AutoTokenizer.from_pretrained(\n                self.config.tokenizer)\n        else:\n            self.text_feature = TextFeaturizer(\n                unit_type=config.unit_type, vocab=config.vocab_filepath)\n\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.output_dim = self.text_feature.vocab_size\n        model = Wav2vec2ASR.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n    def run(self):\n        check(args.audio_file)\n\n        with paddle.no_grad():\n            # read\n            audio, _ = soundfile.read(\n                self.audio_file, dtype=\"int16\", always_2d=True)\n            logger.info(f\"audio shape: {audio.shape}\")\n            xs = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)\n            decode_config = self.config.decode\n            result_transcripts, result_tokenids = self.model.decode(\n                xs,\n                text_feature=self.text_feature,\n                decoding_method=decode_config.decoding_method,\n                beam_size=decode_config.beam_size,\n                tokenizer=self.tokenizer, )\n            rsl = result_transcripts[0]\n            utt = Path(self.audio_file).name\n            logger.info(f\"hyp: {utt} {rsl}\")\n            return rsl\n\n\ndef check(audio_file):\n    if not os.path.isfile(audio_file):\n        print(\"Please input the right audio file path\")\n        sys.exit(-1)\n\n    logger.info(\"checking the audio file format......\")\n    try:\n        sig, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main(config, args):\n    Wav2vec2Infer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    args = parser.parse_args()\n\n    config = CfgNode(new_allowed=True)\n\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/bin/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for wav2vec2.0 model.\"\"\"\nimport cProfile\nimport os\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.wav2vec2.model import Wav2Vec2ASRTrainer as Trainer\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--resume', type=str, default=\"\", nargs=\"?\", help='resume ckpt path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wav2vec2/model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains wav2vec2 model.\"\"\"\nimport json\nimport math\nimport os\nimport re\nimport time\nfrom collections import OrderedDict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom hyperpyyaml import load_hyperpyyaml\nfrom paddle import distributed as dist\nfrom paddlenlp.transformers import AutoTokenizer\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.io.speechbrain import data_pipeline\nfrom paddlespeech.s2t.io.speechbrain import dataio\nfrom paddlespeech.s2t.io.speechbrain import dataset\nfrom paddlespeech.s2t.io.speechbrain.dataloader import make_dataloader\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import TimeDomainSpecAugment\nfrom paddlespeech.s2t.models.wav2vec2.wav2vec2_ASR import Wav2vec2ASR\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\ndef clip_grad_norm_(\n        parameters,\n        max_norm,\n        norm_type=2.0,\n        error_if_nonfinite=False, ):\n    r\"\"\"Clips gradient norm of the iteratable parameters.\n\n    Norms are calculated together on all gradients, just as they are\n    connected into one vector. The gradient will be modified in place.\n\n    This API can only run in dynamic graph mode, not static graph mode.\n\n    Args:\n        parameters (Iterable[paddle.Tensor] or paddle.Tensor): Tensors or a single Tensor\n            that will be normalized gradients\n        max_norm (float or int): max norm of the gradients\n        norm_type (float or int): type of the used p-norm. Can be `inf` for\n            infinity norm.\n        error_if_nonfinite (bool): if True, throw an error if the total\n            norm of the gradients from :attr:`parameters` is `nan`,\n            `inf`, or `-inf`.\n\n    Returns:\n        Total norm of the parameter gradients (treated as a single vector).\n    Example:\n        .. code-block:: python\n            import paddle\n\n            x = paddle.uniform([10, 10], min=-1.0, max=1.0, dtype='float32')\n            max_norm = float(5.0)\n            linear = paddle.nn.Linear(in_features=10, out_features=10)\n            out = linear(x)\n            loss = paddle.mean(out)\n            loss.backward()\n\n            paddle.nn.utils.clip_grad_norm_(linear.parameters(), max_norm)\n\n            sdg = paddle.optimizer.SGD(learning_rate=0.1, parameters=linear.parameters())\n            sdg.step()\n    \"\"\"\n    if not paddle.in_dynamic_mode():\n        raise RuntimeError('this API can only run in dynamic mode.')\n\n    if isinstance(parameters, paddle.Tensor):\n        parameters = [parameters]\n\n    support_norm_type = [float(\"inf\"), 0, 1, 2]\n    if norm_type not in support_norm_type:\n        raise ValueError(f'norm_type only support {support_norm_type}')\n\n    grads = [p.grad for p in parameters if p.grad is not None]\n    max_norm = float(max_norm)\n    norm_type = float(norm_type)\n    if len(grads) == 0:\n        return paddle.to_tensor(0.0)\n    if norm_type == float(\"inf\"):\n        norms = [g.detach().abs().max() for g in grads]\n        total_norm = (norms[0]\n                      if len(norms) == 1 else paddle.max(paddle.stack(norms)))\n    else:\n        total_norm = paddle.linalg.norm(\n            paddle.stack(\n                [paddle.linalg.norm(g.detach(), norm_type) for g in grads]),\n            norm_type, )\n\n    if error_if_nonfinite and paddle.logical_or(total_norm.isnan(),\n                                                total_norm.isinf()):\n        raise RuntimeError(\n            f'The total norm of {norm_type} order of the gradients from '\n            '`parameters` is non-finite, so it cannot be clipped. In any case, '\n            'disable this error and scale the gradient by non-finite norm, '\n            'set `error_if_nonfinite=False`')\n    clip_coef = max_norm / (total_norm + 1e-6)\n    # Note: when the coef is clamped to 1, it is redundant to multiply the clamped coef, but this\n    # avoids the `if clip_coef < 1:` condition.\n    clip_coef_clamped = paddle.clip(clip_coef, max=1.0)\n    with paddle.no_grad():\n        for _, p in enumerate(parameters):\n            g = p.grad\n            if g is not None:\n                p.grad = paddle.multiply(x=g, y=clip_coef_clamped)\n    return total_norm\n\n\nclass Wav2Vec2ASRTrainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.avg_train_loss = 0.0\n        self.loss_isfinite = True  # while flag is 'False', loss in Nan or inf, and can not be avg\n        self.use_sb = True  # whether use speech brain dataloader\n\n    def update_average(self, batch_index, loss):\n        \"\"\"Update running average of the loss.\n        Arguments\n        ---------\n        batch_index : int\n            current batch index\n        loss : paddle.tensor\n            detached loss, a single float value.\n        \"\"\"\n        if math.isfinite(loss):\n            self.avg_train_loss -= self.avg_train_loss / (batch_index + 1)\n            self.avg_train_loss += loss / (batch_index + 1)\n        else:\n            self.loss_isfinite = False\n            logger.info('loss:{} in Nan or inf, error'.format(loss))\n\n    def before_train(self):\n        from_scratch = self.resume_or_scratch()\n        if from_scratch:\n            # scratch: save init model, i.e. 0 epoch\n            self.save(tag='init', infos=None)\n        else:\n            # resume: train next_epoch and next_iteration\n            self.epoch += 1\n            logger.info(\n                f\"Resume train: epoch {self.epoch }, step {self.iteration}!\")\n\n        self.maybe_batch_sampler_step()\n\n    def train_batch(self, batch_index, batch, msg):\n        train_conf = self.config\n        start = time.time()\n\n        # forward\n        ## sb data pipeline\n        if self.use_sb:\n            wav, wavs_lens_rate = batch['sig']\n            target, target_lens_rate = batch['tokens']\n            target_lens = (target_lens_rate *\n                           target.shape[1]).round().astype(paddle.int64)\n        else:\n            utt, wav, wavs_lens, target, target_lens = batch\n            wavs_lens_rate = wavs_lens / wav.shape[1]\n            wav = wav[:, :, 0]\n\n        if hasattr(train_conf, 'audio_augment'):\n            wav = self.speech_augmentation(wav, wavs_lens_rate)\n\n        loss = self.model(wav, wavs_lens_rate, target, target_lens)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        # update self.avg_train_loss\n        self.update_average(batch_index, float(loss))\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            # When using cpu w/o DDP, model does not have `no_sync`\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            loss.backward()\n\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # optimizer step old\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            #do global grad clip\n            if train_conf.global_grad_clip != 0:\n                clip_grad_norm_(self.model.parameters(),\n                                train_conf.global_grad_clip)\n            self.model_optimizer.step()\n            self.model_optimizer.clear_grad()\n            if not train_conf.freeze_wav2vec2:\n                self.wav2vec2_optimizer.step()\n                self.wav2vec2_optimizer.clear_grad()\n            if self.config.model_scheduler != 'newbobscheduler':\n                self.model_lr_scheduler.step()\n            if self.config.wav2vec2_scheduler != 'newbobscheduler':\n                if not train_conf.freeze_wav2vec2:\n                    self.wav2vec2_lr_scheduler.step()\n            self.iteration += 1\n\n        losses_np = {'loss': self.avg_train_loss * train_conf.accum_grad}\n        iteration_time = time.time() - start\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"loss_whitoutavg\", float(loss))\n        report(\"batch_size\", self.config.batch_size)\n        report(\"accum\", train_conf.accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\n                    \"model_lr\": self.model_lr_scheduler(),\n                    \"wav2vec2_lr\": self.wav2vec2_lr_scheduler()\n                })\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag='train/' + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = {}\n        step = 0\n        total_loss = 0.0\n        num_seen_utts = 1  # use update_average and no need for num_seen_utts here\n        for i, batch in enumerate(self.valid_loader):\n            if self.use_sb:\n                wav, wavs_lens_rate = batch['sig']\n                target, target_lens_rate = batch['tokens']\n                target_lens = (target_lens_rate *\n                               target.shape[1]).round().astype(paddle.int64)\n            else:\n                utt, wav, wavs_lens, target, target_lens = batch\n                wavs_lens_rate = wavs_lens / wav.shape[1]\n                wav = wav[:, :, 0]\n\n            loss = self.model(wav, wavs_lens_rate, target, target_lens)\n            # use update_average\n            total_loss -= total_loss / (step + 1)\n            total_loss += loss / (step + 1)\n\n            if math.isfinite(float(loss)):\n                step += 1\n                valid_losses['val_loss'] = float(loss)\n            else:\n                logger.info('loss:{} in Nan or inf, error'.format(float(loss)))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_losses['val_history_loss'] = float(total_loss)\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_losses.items())\n                logger.info(msg)\n\n        logger.info(\n            'Rank {} Val info val_loss {}'.format(dist.get_rank(), total_loss))\n        return total_loss, num_seen_utts\n\n    @mp_tools.rank_zero_only\n    def save(self, tag=None, infos: dict=None):\n        \"\"\"Save checkpoint (model parameters and optimizer states).\n\n        Args:\n            tag (int or str, optional): None for step, else using tag, e.g epoch. Defaults to None.\n            infos (dict, optional): meta data to save. Defaults to None.\n        \"\"\"\n\n        infos = infos if infos else dict()\n        infos.update({\n            \"epoch\": self.epoch,\n            \"model_lr\": self.model_optimizer.get_lr(),\n            \"wav2vec2_lr\": self.wav2vec2_optimizer.get_lr()\n        })\n\n        checkpoint_path = os.path.join(\n            self.checkpoint_dir,\n            \"{}\".format(self.iteration if tag is None else tag))\n\n        model_dict = self.model.state_dict()\n        params_path = checkpoint_path + \".pdparams\"\n        paddle.save(model_dict, params_path)\n        logger.info(\"Saved model to {}\".format(params_path))\n\n        model_opt_dict = self.model_optimizer.state_dict()\n        wav2vec2_opt_dict = self.wav2vec2_optimizer.state_dict()\n\n        opt_dict = {'model': model_opt_dict, 'wav2vec2': wav2vec2_opt_dict}\n\n        optimizer_path = checkpoint_path + \".pdopt\"\n        paddle.save(opt_dict, optimizer_path)\n        logger.info(\"Saved optimzier state to {}\".format(optimizer_path))\n\n        scheduler_dict = {}\n\n        if self.config.model_scheduler == 'newbobscheduler':\n            scheduler_dict['model'] = self.model_lr_scheduler.save()\n        if self.config.wav2vec2_scheduler == 'newbobscheduler':\n            scheduler_dict['wav2vec2'] = self.wav2vec2_lr_scheduler.save()\n        if scheduler_dict:\n            scheduler_path = checkpoint_path + \".pdlrs\"\n            paddle.save(scheduler_dict, scheduler_path)\n            logger.info(\"Saved scheduler state to {}\".format(scheduler_path))\n        info_path = re.sub('.pdparams$', '.json', params_path)\n        infos = {} if infos is None else infos\n        with open(info_path, 'w', encoding='utf8') as fout:\n            data = json.dumps(infos)\n            fout.write(data)\n\n    def resume_or_scratch(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        scratch = None\n        if self.args.resume:\n            # just restore ckpt\n            # lr will restore from optimizer ckpt\n            resume_json_path = os.path.join(self.checkpoint_dir,\n                                            self.args.resume + '.json')\n            with open(resume_json_path, 'r', encoding='utf8') as f:\n                resume_json = json.load(f)\n            self.iteration = 0\n            self.epoch = resume_json[\"epoch\"]\n\n            # restore model from *.pdparams\n            params_path = os.path.join(self.checkpoint_dir,\n                                       \"{}\".format(self.epoch)) + '.pdparams'\n            model_dict = paddle.load(params_path)\n            self.model.set_state_dict(model_dict)\n\n            # restore optimizer from *.pdopt\n            optimizer_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdopt'\n            optimizer_dict = paddle.load(optimizer_path)\n            self.model_optimizer.set_state_dict(optimizer_dict['model'])\n            self.wav2vec2_optimizer.set_state_dict(optimizer_dict['wav2vec2'])\n\n            # restore lr_scheduler from *.pdlrs\n            scheduler_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdlrs'\n            if os.path.isfile(os.path.join(scheduler_path)):\n                scheduler_dict = paddle.load(scheduler_path)\n                if self.config.model_scheduler == 'newbobscheduler':\n                    self.model_lr_scheduler.load(scheduler_dict['model'])\n                if self.config.wav2vec2_scheduler == 'newbobscheduler':\n                    self.wav2vec2_lr_scheduler.load(scheduler_dict['wav2vec2'])\n            logger.info(\n                f\"Restore ckpt: epoch {self.epoch }, step {self.iteration}!\")\n            scratch = False\n        else:\n            self.iteration = 0\n            self.epoch = 0\n            scratch = True\n            logger.info(\"Init from scratch!\")\n        return scratch\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"model_lr\", self.model_optimizer.get_lr())\n                            report(\"wav2vec2_lr\",\n                                   self.wav2vec2_optimizer.get_lr())\n                            self.train_batch(batch_index, batch, msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            if not self.use_streamdata:\n                                report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips,samples/s'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k.split(',')[0]}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += f\" {k.split(',')[1]}\" if len(\n                                k.split(',')) == 2 else \"\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = float(total_loss)\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/model_lr',\n                    value=self.model_lr_scheduler(),\n                    step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/wav2vec2_lr',\n                    value=self.wav2vec2_lr_scheduler(),\n                    step=self.epoch)\n\n            if self.config.model_scheduler == 'newbobscheduler':\n                self.model_lr_scheduler.step(cv_loss)\n            if self.config.wav2vec2_scheduler == 'newbobscheduler':\n                if not self.config.freeze_wav2vec2:\n                    self.wav2vec2_lr_scheduler.step(cv_loss)\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.avg_train_loss = 0.0\n            self.new_epoch()\n\n    def dataio_prepare(self, hparams):\n        \"\"\"This function prepares the datasets to be used in the brain class.\n        It also defines the data processing pipeline through user-defined functions.\"\"\"\n        data_folder = hparams[\"data_folder\"]\n\n        train_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"train_data\"],\n            replacements={\"data_root\": data_folder}, )\n\n        if hparams[\"sorting\"] == \"ascending\":\n            # we sort training data to speed up training and get better results.\n            train_data = train_data.filtered_sorted(sort_key=\"duration\")\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"descending\":\n            train_data = train_data.filtered_sorted(\n                sort_key=\"duration\", reverse=True)\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"random\":\n            pass\n\n        else:\n            raise NotImplementedError(\n                \"sorting must be random, ascending or descending\")\n\n        valid_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"valid_data\"],\n            replacements={\"data_root\": data_folder}, )\n        valid_data = valid_data.filtered_sorted(sort_key=\"duration\")\n\n        test_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"test_data\"],\n            replacements={\"data_root\": data_folder}, )\n        test_data = test_data.filtered_sorted(sort_key=\"duration\")\n\n        datasets = [train_data, valid_data, test_data]\n\n        # Defining tokenizer and loading it\n        tokenizer = AutoTokenizer.from_pretrained('bert-base-chinese')\n        self.tokenizer = tokenizer\n        # 2. Define audio pipeline:\n        @data_pipeline.takes(\"wav\")\n        @data_pipeline.provides(\"sig\")\n        def audio_pipeline(wav):\n            sig = dataio.read_audio(wav)\n            return sig\n\n        dataset.add_dynamic_item(datasets, audio_pipeline)\n\n        # 3. Define text pipeline:\n        @data_pipeline.takes(\"transcript\")\n        @data_pipeline.provides(\"wrd\", \"tokens_list\", \"tokens\")\n        def text_pipeline(wrd):\n            wrd = \"\".join(wrd.split(\" \"))\n            yield wrd\n            tokens_list = tokenizer(wrd)[\"input_ids\"]\n            yield tokens_list\n            tokens = np.array(tokens_list, dtype=\"int64\")\n            # tokens = paddle.to_tensor(tokens_list, dtype=\"int64\")\n            yield tokens\n\n        dataset.add_dynamic_item(datasets, text_pipeline)\n\n        # 4. Set output:\n        dataset.set_output_keys(\n            datasets,\n            [\"id\", \"sig\", \"wrd\", \"tokens\"], )\n\n        # 5. If Dynamic Batching is used, we instantiate the needed samplers.\n        train_batch_sampler = None\n        valid_batch_sampler = None\n        if hparams[\"dynamic_batching\"]:\n            from sampler import DynamicBatchSampler  # noqa\n\n            dynamic_hparams = hparams[\"dynamic_batch_sampler\"]\n            num_buckets = dynamic_hparams[\"num_buckets\"]\n\n            train_batch_sampler = DynamicBatchSampler(\n                train_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n            valid_batch_sampler = DynamicBatchSampler(\n                valid_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n        return (train_data, valid_data, test_data, tokenizer,\n                train_batch_sampler, valid_batch_sampler, )\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        self.use_sb = config.get(\"use_sb_pipeline\", False)\n        if self.use_sb:\n            hparams_file = config.sb_pipeline_conf\n            with open(hparams_file, 'r', encoding='utf8') as fin:\n                hparams = load_hyperpyyaml(fin, None)\n\n            (train_data, valid_data, test_data, tokenizer, train_bsampler,\n             valid_bsampler, ) = self.dataio_prepare(hparams)\n\n            train_dataloader_opts = hparams[\"train_dataloader_opts\"]\n            valid_dataloader_opts = hparams[\"valid_dataloader_opts\"]\n\n            if train_bsampler is not None:\n                train_dataloader_opts = {\n                    \"batch_sampler\": train_bsampler,\n                    \"num_workers\": hparams[\"num_workers\"],\n                }\n\n            if valid_bsampler is not None:\n                valid_dataloader_opts = {\"batch_sampler\": valid_bsampler}\n\n            if self.train:\n                self.train_loader = make_dataloader(\n                    train_data, stage='train', **train_dataloader_opts)\n                self.valid_loader = make_dataloader(\n                    valid_data,\n                    stage='val',\n                    **valid_dataloader_opts, )\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                self.test_loader = make_dataloader(\n                    test_data, stage='test', **hparams[\"test_dataloader_opts\"])\n        else:\n            if self.train:\n                self.train_loader = DataLoaderFactory.get_dataloader(\n                    'train', config, self.args)\n                self.valid_loader = DataLoaderFactory.get_dataloader(\n                    'valid', config, self.args)\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                decode_batch_size = config.get('decode', dict()).get(\n                    'decode_batch_size', 1)\n                self.test_loader = DataLoaderFactory.get_dataloader(\n                    'test', config, self.args)\n                self.align_loader = DataLoaderFactory.get_dataloader(\n                    'align', config, self.args)\n                logger.info(\"Setup test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n\n        with UpdateConfig(model_conf):\n            if self.use_sb:\n                model_conf.output_dim = self.tokenizer.vocab_size\n            else:\n                if self.train:\n                    model_conf.input_dim = self.train_loader.feat_dim\n                    model_conf.output_dim = self.train_loader.vocab_size\n                else:\n                    model_conf.input_dim = self.test_loader.feat_dim\n                    model_conf.output_dim = self.test_loader.vocab_size\n\n        model = Wav2vec2ASR.from_config(model_conf)\n\n        model_dict = paddle.load(config.wav2vec2_params_path)\n        model.wav2vec2.set_state_dict(model_dict)\n\n        if self.parallel:\n            model = paddle.DataParallel(model, find_unused_parameters=True)\n\n        layer_tools.print_params(model, logger.info)\n        self.model = model\n        logger.info(\"Setup model!\")\n\n        # setup speech augmentation for wav2vec2\n        if hasattr(config, 'audio_augment') and self.train:\n            self.speech_augmentation = TimeDomainSpecAugment(\n                **config.audio_augment)\n\n        if not self.train:\n            return\n\n        train_config = config\n        model_optim_type = train_config.model_optim\n        model_optim_conf = train_config.model_optim_conf\n        logger.info(\"optim_model:{},{}\", model_optim_type, model_optim_conf)\n        wav2vec2_optim_type = train_config.wav2vec2_optim\n        wav2vec2_optim_conf = train_config.wav2vec2_optim_conf\n        logger.info(\"optim_model:{},{}\", wav2vec2_optim_type,\n                    wav2vec2_optim_conf)\n\n        model_scheduler_type = train_config.model_scheduler\n        model_scheduler_conf = train_config.model_scheduler_conf\n        wav2vec2_scheduler_type = train_config.wav2vec2_scheduler\n        wav2vec2_scheduler_conf = train_config.wav2vec2_scheduler_conf\n\n        model_scheduler_args = dict(\n            **{\"learning_rate\": model_optim_conf.lr,\n               \"verbose\": False}, **(dict(model_scheduler_conf)))\n\n        wav2vec2_scheduler_args = dict(\n            **{\"learning_rate\": wav2vec2_optim_conf.lr,\n               \"verbose\": False}, **(dict(wav2vec2_scheduler_conf)))\n\n        model_lr_scheduler = LRSchedulerFactory.from_args(model_scheduler_type,\n                                                          model_scheduler_args)\n        wav2vec2_lr_scheduler = LRSchedulerFactory.from_args(\n            wav2vec2_scheduler_type, wav2vec2_scheduler_args)\n\n        def optimizer_args(\n                config,\n                optim_type,\n                optim_conf,\n                parameters,\n                lr_scheduler=None, ):\n            optim_arg = dict(optim_conf)\n            optim_arg.update({\n                \"learning_rate\":\n                lr_scheduler if lr_scheduler else optim_conf.lr,\n                \"parameters\":\n                parameters\n            })\n            return optim_arg\n\n        model_optimizer_args = optimizer_args(config, model_optim_type,\n                                              model_optim_conf, [{\n                                                  'params':\n                                                  model._layers.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model._layers.ctc.parameters()\n                                              }] if self.parallel else [{\n                                                  'params':\n                                                  model.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model.ctc.parameters()\n                                              }], model_lr_scheduler)\n\n        wav2vec2_optimizer_args = optimizer_args(\n            config, wav2vec2_optim_type, wav2vec2_optim_conf,\n            model._layers.wav2vec2.parameters() if self.parallel else\n            model.wav2vec2.parameters(), wav2vec2_lr_scheduler)\n\n        model_optimizer = OptimizerFactory.from_args(model_optim_type,\n                                                     model_optimizer_args)\n        wav2vec2_optimizer = OptimizerFactory.from_args(wav2vec2_optim_type,\n                                                        wav2vec2_optimizer_args)\n\n        self.model_optimizer = model_optimizer\n        self.wav2vec2_optimizer = wav2vec2_optimizer\n        self.model_lr_scheduler = model_lr_scheduler\n        self.wav2vec2_lr_scheduler = wav2vec2_lr_scheduler\n        logger.info(\"Setup optimizer/lr_scheduler!\")\n\n\nclass Wav2Vec2ASRTester(Wav2Vec2ASRTrainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_featurizer = TextFeaturizer(\n            unit_type=config.unit_type, vocab=config.vocab_filepath)\n        self.vocab_list = self.text_featurizer.vocab_list\n\n    def id2token(self, texts, texts_len):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(self.text_featurizer.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self, id, audio, audio_len, texts, texts_len,\n                        fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n\n        start_time = time.time()\n        target_transcripts = self.id2token(texts, texts_len)\n        result_transcripts, result_tokenids = self.model.decode(\n            audio,\n            text_feature=self.text_featurizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    def sb_compute_metrics(self, id, sig, wrd, tokens, fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n        start_time = time.time()\n        target_transcripts = wrd\n        result_transcripts, result_tokenids = self.model.decode(\n            sig[0],\n            text_feature=self.tokenizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            sb_pipeline=True)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=sig[1].sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n        self.model.eval()\n\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        # Initialized the decoder in model\n        decode_cfg = self.config.decode\n        vocab_list = self.vocab_list\n        decode_batch_size = decode_cfg.decode_batch_size\n\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                if self.use_sb:\n                    metrics = self.sb_compute_metrics(**batch, fout=fout)\n                else:\n                    metrics = self.compute_metrics(*batch, fout=fout)\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                rtf = num_time / (num_frames)\n                logger.info(\n                    \"RTF: %f, Error rate [%s] (%d/?) = %f\" %\n                    (rtf, error_rate_type, num_ins, errors_sum / len_refs))\n\n        # logging\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n\n        err_meta_path = os.path.splitext(self.args.result_file)[0] + '.err'\n        err_type_str = \"{}\".format(error_rate_type)\n        with open(err_meta_path, 'w', encoding='utf8') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                error_rate_type:\n                errors_sum / len_refs,\n                \"dataset_hour\": (num_frames) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"err_sum\":\n                errors_sum,\n                \"ref_len\":\n                len_refs,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/bin/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/bin/test.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for WavLM model.\"\"\"\nimport cProfile\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.wavlm.model import WavLMASRTester as Tester\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import add_arguments\nfrom paddlespeech.utils.argparse import print_arguments\n\n\ndef main_sp(config, args):\n    exp = Tester(config, args)\n    with exp.eval():\n        exp.setup()\n        exp.run_test()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save asr result to\n    parser.add_argument(\n        '--dict-path', type=str, default=None, help='dict path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats('test.profile')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/bin/test_wav.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Evaluation for wavlm model.\"\"\"\nimport os\nimport sys\nfrom pathlib import Path\n\nimport paddle\nimport soundfile\nfrom paddlenlp.transformers import AutoTokenizer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.models.wavlm.wavlm_asr import WavLMASR\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nlogger = Log(__name__).getlog()\n\n\nclass WavLMInfer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n        self.tokenizer = config.get(\"tokenizer\", None)\n\n        if self.tokenizer:\n            self.text_feature = AutoTokenizer.from_pretrained(\n                self.config.tokenizer)\n        else:\n            self.text_feature = TextFeaturizer(\n                unit_type=config.unit_type, vocab=config.vocab_filepath)\n\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n\n        # model\n        model_conf = config\n        with UpdateConfig(model_conf):\n            model_conf.output_dim = self.text_feature.vocab_size\n        model = WavLMASR.from_config(model_conf)\n        self.model = model\n        self.model.eval()\n\n        # load model\n        params_path = self.args.checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        self.model.set_state_dict(model_dict)\n\n    def run(self):\n        check(args.audio_file)\n\n        with paddle.no_grad():\n            # read\n            audio, _ = soundfile.read(\n                self.audio_file, dtype=\"int16\", always_2d=True)\n            logger.info(f\"audio shape: {audio.shape}\")\n            xs = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)\n            decode_config = self.config.decode\n            result_transcripts, result_tokenids = self.model.decode(\n                xs,\n                text_feature=self.text_feature,\n                decoding_method=decode_config.decoding_method,\n                beam_size=decode_config.beam_size,\n                tokenizer=self.tokenizer, )\n            rsl = result_transcripts[0]\n            utt = Path(self.audio_file).name\n            logger.info(f\"hyp: {utt} {rsl}\")\n            return rsl\n\n\ndef check(audio_file):\n    if not os.path.isfile(audio_file):\n        print(\"Please input the right audio file path\")\n        sys.exit(-1)\n\n    logger.info(\"checking the audio file format......\")\n    try:\n        sig, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main(config, args):\n    WavLMInfer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save asr result to\n    args = parser.parse_args()\n\n    config = CfgNode(new_allowed=True)\n\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/bin/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Trainer for wavlm model.\"\"\"\nimport cProfile\nimport os\n\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.exps.wavlm.model import WavLMASRTrainer as Trainer\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.utils.argparse import print_arguments, add_arguments\n\n\ndef main_sp(config, args):\n    exp = Trainer(config, args)\n    exp.setup()\n    exp.run()\n\n\ndef main(config, args):\n    main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    parser.add_argument(\n        '--resume', type=str, default=\"\", nargs=\"?\", help='resume ckpt path.')\n    args = parser.parse_args()\n    print_arguments(args, globals())\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    if args.dump_config:\n        with open(args.dump_config, 'w') as f:\n            print(config, file=f)\n\n    # Setting for profiling\n    pr = cProfile.Profile()\n    pr.runcall(main, config, args)\n    pr.dump_stats(os.path.join(args.output, 'train.profile'))\n"
  },
  {
    "path": "paddlespeech/s2t/exps/wavlm/model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains wavlm model.\"\"\"\nimport json\nimport math\nimport os\nimport re\nimport time\nfrom collections import OrderedDict\nfrom contextlib import nullcontext\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom hyperpyyaml import load_hyperpyyaml\nfrom paddle import distributed as dist\nfrom paddlenlp.transformers import AutoTokenizer\n\nfrom paddlespeech.s2t.frontend.featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.dataloader import DataLoaderFactory\nfrom paddlespeech.s2t.io.speechbrain import data_pipeline\nfrom paddlespeech.s2t.io.speechbrain import dataio\nfrom paddlespeech.s2t.io.speechbrain import dataset\nfrom paddlespeech.s2t.io.speechbrain.dataloader import make_dataloader\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import TimeDomainSpecAugment\nfrom paddlespeech.s2t.models.wavlm.wavlm_asr import WavLMASR\nfrom paddlespeech.s2t.training.optimizer import OptimizerFactory\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.scheduler import LRSchedulerFactory\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.trainer import Trainer\nfrom paddlespeech.s2t.utils import error_rate\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\nlogger = Log(__name__).getlog()\n\n\ndef clip_grad_norm_(\n        parameters,\n        max_norm,\n        norm_type=2.0,\n        error_if_nonfinite=False, ):\n    r\"\"\"Clips gradient norm of the iteratable parameters.\n\n    Norms are calculated together on all gradients, just as they are\n    connected into one vector. The gradient will be modified in place.\n\n    This API can only run in dynamic graph mode, not static graph mode.\n\n    Args:\n        parameters (Iterable[paddle.Tensor] or paddle.Tensor): Tensors or a single Tensor\n            that will be normalized gradients\n        max_norm (float or int): max norm of the gradients\n        norm_type (float or int): type of the used p-norm. Can be `inf` for\n            infinity norm.\n        error_if_nonfinite (bool): if True, throw an error if the total\n            norm of the gradients from :attr:`parameters` is `nan`,\n            `inf`, or `-inf`.\n\n    Returns:\n        Total norm of the parameter gradients (treated as a single vector).\n    Example:\n        .. code-block:: python\n            import paddle\n\n            x = paddle.uniform([10, 10], min=-1.0, max=1.0, dtype='float32')\n            max_norm = float(5.0)\n            linear = paddle.nn.Linear(in_features=10, out_features=10)\n            out = linear(x)\n            loss = paddle.mean(out)\n            loss.backward()\n\n            paddle.nn.utils.clip_grad_norm_(linear.parameters(), max_norm)\n\n            sdg = paddle.optimizer.SGD(learning_rate=0.1, parameters=linear.parameters())\n            sdg.step()\n    \"\"\"\n    if not paddle.in_dynamic_mode():\n        raise RuntimeError('this API can only run in dynamic mode.')\n\n    if isinstance(parameters, paddle.Tensor):\n        parameters = [parameters]\n\n    support_norm_type = [float(\"inf\"), 0, 1, 2]\n    if norm_type not in support_norm_type:\n        raise ValueError(f'norm_type only support {support_norm_type}')\n\n    grads = [p.grad for p in parameters if p.grad is not None]\n    max_norm = float(max_norm)\n    norm_type = float(norm_type)\n    if len(grads) == 0:\n        return paddle.to_tensor(0.0)\n    if norm_type == float(\"inf\"):\n        norms = [g.detach().abs().max() for g in grads]\n        total_norm = (norms[0]\n                      if len(norms) == 1 else paddle.max(paddle.stack(norms)))\n    else:\n        total_norm = paddle.linalg.norm(\n            paddle.stack(\n                [paddle.linalg.norm(g.detach(), norm_type) for g in grads]),\n            norm_type, )\n\n    if error_if_nonfinite and paddle.logical_or(total_norm.isnan(),\n                                                total_norm.isinf()):\n        raise RuntimeError(\n            f'The total norm of {norm_type} order of the gradients from '\n            '`parameters` is non-finite, so it cannot be clipped. In any case, '\n            'disable this error and scale the gradient by non-finite norm, '\n            'set `error_if_nonfinite=False`')\n    clip_coef = max_norm / (total_norm + 1e-6)\n    # Note: when the coef is clamped to 1, it is redundant to multiply the clamped coef, but this\n    # avoids the `if clip_coef < 1:` condition.\n    clip_coef_clamped = paddle.clip(clip_coef, max=1.0)\n    with paddle.no_grad():\n        for _, p in enumerate(parameters):\n            g = p.grad\n            if g is not None:\n                p.grad = paddle.multiply(x=g, y=clip_coef_clamped)\n    return total_norm\n\n\nclass WavLMASRTrainer(Trainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.avg_train_loss = 0.0\n        self.loss_isfinite = True  # while flag is 'False', loss in Nan or inf, and can not be avg\n        self.use_sb = True  # whether use speech brain dataloader\n\n    def update_average(self, batch_index, loss):\n        \"\"\"Update running average of the loss.\n        Arguments\n        ---------\n        batch_index : int\n            current batch index\n        loss : paddle.tensor\n            detached loss, a single float value.\n        \"\"\"\n        if math.isfinite(loss):\n            self.avg_train_loss -= self.avg_train_loss / (batch_index + 1)\n            self.avg_train_loss += loss / (batch_index + 1)\n        else:\n            self.loss_isfinite = False\n            logger.info('loss:{} in Nan or inf, error'.format(loss))\n\n    def before_train(self):\n        from_scratch = self.resume_or_scratch()\n        if from_scratch:\n            # scratch: save init model, i.e. 0 epoch\n            self.save(tag='init', infos=None)\n        else:\n            # resume: train next_epoch and next_iteration\n            self.epoch += 1\n            logger.info(\n                f\"Resume train: epoch {self.epoch }, step {self.iteration}!\")\n\n        self.maybe_batch_sampler_step()\n\n    def train_batch(self, batch_index, batch, msg):\n        train_conf = self.config\n        start = time.time()\n\n        # forward\n        ## sb data pipeline\n        if self.use_sb:\n            wav, wavs_lens_rate = batch['sig']\n            target, target_lens_rate = batch['tokens']\n            target_lens = (target_lens_rate *\n                           target.shape[1]).round().astype(paddle.int64)\n        else:\n            utt, wav, wavs_lens, target, target_lens = batch\n            wavs_lens_rate = wavs_lens / wav.shape[1]\n            wav = wav[:, :, 0]\n\n        if hasattr(train_conf, 'audio_augment'):\n            wav = self.speech_augmentation(wav, wavs_lens_rate)\n        loss = self.model(wav, wavs_lens_rate, target, target_lens)\n\n        # loss div by `batch_size * accum_grad`\n        loss /= train_conf.accum_grad\n        # update self.avg_train_loss\n        self.update_average(batch_index, float(loss))\n\n        # loss backward\n        if (batch_index + 1) % train_conf.accum_grad != 0:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            # When using cpu w/o DDP, model does not have `no_sync`\n            context = self.model.no_sync if (hasattr(self.model, \"no_sync\") and\n                                             self.parallel) else nullcontext\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n        with context():\n            loss.backward()\n\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # NOTE: the code below asserted that the backward() is problematic, and as more steps are accumulated, the output from wavlm alone will be the same for all frames\n        # optimizer step old\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            #do global grad clip\n            if train_conf.global_grad_clip != 0:\n                clip_grad_norm_(self.model.parameters(),\n                                train_conf.global_grad_clip)\n            self.model_optimizer.step()\n            self.model_optimizer.clear_grad()\n            if not train_conf.freeze_wavlm:\n                self.wavlm_optimizer.step()\n                self.wavlm_optimizer.clear_grad()\n            if self.config.model_scheduler != 'newbobscheduler':\n                self.model_lr_scheduler.step()\n            if self.config.wavlm_scheduler != 'newbobscheduler':\n                if not train_conf.freeze_wavlm:\n                    self.wavlm_lr_scheduler.step()\n            self.iteration += 1\n\n        losses_np = {'loss': self.avg_train_loss * train_conf.accum_grad}\n        iteration_time = time.time() - start\n        for k, v in losses_np.items():\n            report(k, v)\n        report(\"loss_whitoutavg\", float(loss))\n        report(\"batch_size\", self.config.batch_size)\n        report(\"accum\", train_conf.accum_grad)\n        report(\"step_cost\", iteration_time)\n\n        if (batch_index + 1) % train_conf.accum_grad == 0:\n            if dist.get_rank() == 0 and self.visualizer:\n                losses_np_v = losses_np.copy()\n                losses_np_v.update({\n                    \"model_lr\": self.model_lr_scheduler(),\n                    \"wavlm_lr\": self.wavlm_lr_scheduler()\n                })\n                for key, val in losses_np_v.items():\n                    self.visualizer.add_scalar(\n                        tag='train/' + key, value=val, step=self.iteration - 1)\n\n    @paddle.no_grad()\n    def valid(self):\n        self.model.eval()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Valid Total Examples: {len(self.valid_loader.dataset)}\")\n        valid_losses = {}\n        step = 0\n        total_loss = 0.0\n        num_seen_utts = 1  # use update_average and no need for num_seen_utts here\n        for i, batch in enumerate(self.valid_loader):\n            if self.use_sb:\n                wav, wavs_lens_rate = batch['sig']\n                target, target_lens_rate = batch['tokens']\n                target_lens = (target_lens_rate *\n                               target.shape[1]).round().astype(paddle.int64)\n            else:\n                utt, wav, wavs_lens, target, target_lens = batch\n                wavs_lens_rate = wavs_lens / wav.shape[1]\n                wav = wav[:, :, 0]\n\n            loss = self.model(wav, wavs_lens_rate, target, target_lens)\n            # use update_average\n            total_loss -= total_loss / (step + 1)\n            total_loss += loss / (step + 1)\n\n            if math.isfinite(float(loss)):\n                step += 1\n                valid_losses['val_loss'] = float(loss)\n            else:\n                logger.info('loss:{} in Nan or inf, error'.format(float(loss)))\n\n            if (i + 1) % self.config.log_interval == 0:\n                valid_losses['val_history_loss'] = float(total_loss)\n\n                # logging\n                msg = f\"Valid: Rank: {dist.get_rank()}, \"\n                msg += \"epoch: {}, \".format(self.epoch)\n                msg += \"step: {}, \".format(self.iteration)\n                if not self.use_streamdata:\n                    msg += \"batch: {}/{}, \".format(i + 1,\n                                                   len(self.valid_loader))\n                msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                 for k, v in valid_losses.items())\n                logger.info(msg)\n\n        logger.info(\n            'Rank {} Val info val_loss {}'.format(dist.get_rank(), total_loss))\n        return total_loss, num_seen_utts\n\n    @mp_tools.rank_zero_only\n    def save(self, tag=None, infos: dict=None):\n        \"\"\"Save checkpoint (model parameters and optimizer states).\n\n        Args:\n            tag (int or str, optional): None for step, else using tag, e.g epoch. Defaults to None.\n            infos (dict, optional): meta data to save. Defaults to None.\n        \"\"\"\n\n        infos = infos if infos else dict()\n        infos.update({\n            \"epoch\": self.epoch,\n            \"model_lr\": self.model_optimizer.get_lr(),\n            \"wavlm_lr\": self.wavlm_optimizer.get_lr()\n        })\n\n        checkpoint_path = os.path.join(\n            self.checkpoint_dir,\n            \"{}\".format(self.iteration if tag is None else tag))\n\n        model_dict = self.model.state_dict()\n        params_path = checkpoint_path + \".pdparams\"\n        paddle.save(model_dict, params_path)\n        logger.info(\"Saved model to {}\".format(params_path))\n\n        model_opt_dict = self.model_optimizer.state_dict()\n        wavlm_opt_dict = self.wavlm_optimizer.state_dict()\n\n        opt_dict = {'model': model_opt_dict, 'wavlm': wavlm_opt_dict}\n\n        optimizer_path = checkpoint_path + \".pdopt\"\n        paddle.save(opt_dict, optimizer_path)\n        logger.info(\"Saved optimzier state to {}\".format(optimizer_path))\n\n        scheduler_dict = {}\n\n        if self.config.model_scheduler == 'newbobscheduler':\n            scheduler_dict['model'] = self.model_lr_scheduler.save()\n        if self.config.wavlm_scheduler == 'newbobscheduler':\n            scheduler_dict['wavlm'] = self.wavlm_lr_scheduler.save()\n        if scheduler_dict:\n            scheduler_path = checkpoint_path + \".pdlrs\"\n            paddle.save(scheduler_dict, scheduler_path)\n            logger.info(\"Saved scheduler state to {}\".format(scheduler_path))\n        info_path = re.sub('.pdparams$', '.json', params_path)\n        infos = {} if infos is None else infos\n        with open(info_path, 'w', encoding='utf8') as fout:\n            data = json.dumps(infos)\n            fout.write(data)\n\n    def resume_or_scratch(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        scratch = None\n        if self.args.resume:\n            # just restore ckpt\n            # lr will restore from optimizer ckpt\n            resume_json_path = os.path.join(self.checkpoint_dir,\n                                            self.args.resume + '.json')\n            with open(resume_json_path, 'r', encoding='utf8') as f:\n                resume_json = json.load(f)\n            self.iteration = 0\n            self.epoch = resume_json[\"epoch\"]\n\n            # restore model from *.pdparams\n            params_path = os.path.join(self.checkpoint_dir,\n                                       \"{}\".format(self.epoch)) + '.pdparams'\n            model_dict = paddle.load(params_path)\n            self.model.set_state_dict(model_dict)\n\n            # restore optimizer from *.pdopt\n            optimizer_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdopt'\n            optimizer_dict = paddle.load(optimizer_path)\n            self.model_optimizer.set_state_dict(optimizer_dict['model'])\n            self.wavlm_optimizer.set_state_dict(optimizer_dict['wavlm'])\n\n            # restore lr_scheduler from *.pdlrs\n            scheduler_path = os.path.join(self.checkpoint_dir,\n                                          \"{}\".format(self.epoch)) + '.pdlrs'\n            if os.path.isfile(os.path.join(scheduler_path)):\n                scheduler_dict = paddle.load(scheduler_path)\n                if self.config.model_scheduler == 'newbobscheduler':\n                    self.model_lr_scheduler.load(scheduler_dict['model'])\n                if self.config.wavlm_scheduler == 'newbobscheduler':\n                    self.wavlm_lr_scheduler.load(scheduler_dict['wavlm'])\n            logger.info(\n                f\"Restore ckpt: epoch {self.epoch }, step {self.iteration}!\")\n            scratch = False\n        else:\n            self.iteration = 0\n            self.epoch = 0\n            scratch = True\n            logger.info(\"Init from scratch!\")\n        return scratch\n\n    def do_train(self):\n        \"\"\"The training process control by step.\"\"\"\n        # !!!IMPORTANT!!!\n        # Try to export the model by script, if fails, we should refine\n        # the code to satisfy the script export requirements\n        # script_model = paddle.jit.to_static(self.model)\n        # script_model_path = str(self.checkpoint_dir / 'init')\n        # paddle.jit.save(script_model, script_model_path)\n\n        self.before_train()\n        if not self.use_streamdata:\n            logger.info(\n                f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"model_lr\", self.model_optimizer.get_lr())\n                            report(\"wavlm_lr\", self.wavlm_optimizer.get_lr())\n                            self.train_batch(batch_index, batch, msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            if not self.use_streamdata:\n                                report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips,samples/s'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k.split(',')[0]}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += f\" {k.split(',')[1]}\" if len(\n                                k.split(',')) == 2 else \"\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = float(total_loss)\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/model_lr',\n                    value=self.model_lr_scheduler(),\n                    step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/wavlm_lr',\n                    value=self.wavlm_lr_scheduler(),\n                    step=self.epoch)\n\n            if self.config.model_scheduler == 'newbobscheduler':\n                self.model_lr_scheduler.step(cv_loss)\n            if self.config.wavlm_scheduler == 'newbobscheduler':\n                if not self.config.freeze_wavlm:\n                    self.wavlm_lr_scheduler.step(cv_loss)\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.avg_train_loss = 0.0\n            self.new_epoch()\n\n    def dataio_prepare(self, hparams):\n        \"\"\"This function prepares the datasets to be used in the brain class.\n        It also defines the data processing pipeline through user-defined functions.\"\"\"\n        data_folder = hparams[\"data_folder\"]\n\n        train_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"train_data\"],\n            replacements={\"data_root\": data_folder}, )\n\n        if hparams[\"sorting\"] == \"ascending\":\n            # we sort training data to speed up training and get better results.\n            train_data = train_data.filtered_sorted(sort_key=\"duration\")\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"descending\":\n            train_data = train_data.filtered_sorted(\n                sort_key=\"duration\", reverse=True)\n            # when sorting do not shuffle in dataloader ! otherwise is pointless\n            hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n        elif hparams[\"sorting\"] == \"random\":\n            pass\n\n        else:\n            raise NotImplementedError(\n                \"sorting must be random, ascending or descending\")\n\n        valid_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"valid_data\"],\n            replacements={\"data_root\": data_folder}, )\n        valid_data = valid_data.filtered_sorted(sort_key=\"duration\")\n\n        test_data = dataset.DynamicItemDataset.from_csv(\n            csv_path=hparams[\"test_data\"],\n            replacements={\"data_root\": data_folder}, )\n        test_data = test_data.filtered_sorted(sort_key=\"duration\")\n\n        datasets = [train_data, valid_data, test_data]\n\n        # Defining tokenizer and loading it\n        tokenizer = AutoTokenizer.from_pretrained('bert-base-chinese')\n        self.tokenizer = tokenizer\n        # 2. Define audio pipeline:\n        @data_pipeline.takes(\"wav\")\n        @data_pipeline.provides(\"sig\")\n        def audio_pipeline(wav):\n            sig = dataio.read_audio(wav)\n            return sig\n\n        dataset.add_dynamic_item(datasets, audio_pipeline)\n\n        # 3. Define text pipeline:\n        @data_pipeline.takes(\"transcript\")\n        @data_pipeline.provides(\"wrd\", \"tokens_list\", \"tokens\")\n        def text_pipeline(wrd):\n            wrd = \"\".join(wrd.split(\" \"))\n            yield wrd\n            tokens_list = tokenizer(wrd)[\"input_ids\"]\n            yield tokens_list\n            tokens = np.array(tokens_list, dtype=\"int64\")\n            # tokens = paddle.to_tensor(tokens_list, dtype=\"int64\")\n            yield tokens\n\n        dataset.add_dynamic_item(datasets, text_pipeline)\n\n        # 4. Set output:\n        dataset.set_output_keys(\n            datasets,\n            [\"id\", \"sig\", \"wrd\", \"tokens\"], )\n\n        # 5. If Dynamic Batching is used, we instantiate the needed samplers.\n        train_batch_sampler = None\n        valid_batch_sampler = None\n        if hparams[\"dynamic_batching\"]:\n            from sampler import DynamicBatchSampler  # noqa\n\n            dynamic_hparams = hparams[\"dynamic_batch_sampler\"]\n            num_buckets = dynamic_hparams[\"num_buckets\"]\n\n            train_batch_sampler = DynamicBatchSampler(\n                train_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n            valid_batch_sampler = DynamicBatchSampler(\n                valid_data,\n                dynamic_hparams[\"max_batch_len\"],\n                num_buckets=num_buckets,\n                length_func=lambda x: x[\"duration\"],\n                shuffle=dynamic_hparams[\"shuffle_ex\"],\n                batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n        return (train_data, valid_data, test_data, tokenizer,\n                train_batch_sampler, valid_batch_sampler, )\n\n    def setup_dataloader(self):\n        config = self.config.clone()\n        self.use_streamdata = config.get(\"use_stream_data\", False)\n        self.use_sb = config.get(\"use_sb_pipeline\", False)\n        if self.use_sb:\n            hparams_file = config.sb_pipeline_conf\n            with open(hparams_file, 'r', encoding='utf8') as fin:\n                hparams = load_hyperpyyaml(fin, None)\n\n            (train_data, valid_data, test_data, tokenizer, train_bsampler,\n             valid_bsampler, ) = self.dataio_prepare(hparams)\n\n            train_dataloader_opts = hparams[\"train_dataloader_opts\"]\n            valid_dataloader_opts = hparams[\"valid_dataloader_opts\"]\n\n            if train_bsampler is not None:\n                train_dataloader_opts = {\n                    \"batch_sampler\": train_bsampler,\n                    \"num_workers\": hparams[\"num_workers\"],\n                }\n\n            if valid_bsampler is not None:\n                valid_dataloader_opts = {\"batch_sampler\": valid_bsampler}\n\n            if self.train:\n                self.train_loader = make_dataloader(\n                    train_data, stage='train', **train_dataloader_opts)\n                self.valid_loader = make_dataloader(\n                    valid_data,\n                    stage='val',\n                    **valid_dataloader_opts, )\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                self.test_loader = make_dataloader(\n                    test_data, stage='test', **hparams[\"test_dataloader_opts\"])\n        else:\n            if self.train:\n                self.train_loader = DataLoaderFactory.get_dataloader(\n                    'train', config, self.args)\n                self.valid_loader = DataLoaderFactory.get_dataloader(\n                    'valid', config, self.args)\n                logger.info(\"Setup train/valid Dataloader!\")\n            else:\n                decode_batch_size = config.get('decode', dict()).get(\n                    'decode_batch_size', 1)\n                self.test_loader = DataLoaderFactory.get_dataloader(\n                    'test', config, self.args)\n                self.align_loader = DataLoaderFactory.get_dataloader(\n                    'align', config, self.args)\n                logger.info(\"Setup test/align Dataloader!\")\n\n    def setup_model(self):\n        config = self.config\n        model_conf = config\n\n        with UpdateConfig(model_conf):\n            if self.use_sb:\n                model_conf.output_dim = self.tokenizer.vocab_size\n            else:\n                if self.train:\n                    model_conf.input_dim = self.train_loader.feat_dim\n                    model_conf.output_dim = self.train_loader.vocab_size\n                else:\n                    model_conf.input_dim = self.test_loader.feat_dim\n                    model_conf.output_dim = self.test_loader.vocab_size\n\n        model = WavLMASR.from_config(model_conf)\n\n        model_dict = paddle.load(config.wavlm_params_path)\n        model.wavlm.set_state_dict(model_dict)\n\n        if self.parallel:\n            model = paddle.DataParallel(model, find_unused_parameters=True)\n\n        layer_tools.print_params(model, logger.info)\n        self.model = model\n        logger.info(\"Setup model!\")\n\n        # setup speech augmentation for wavlm\n        if hasattr(config, 'audio_augment') and self.train:\n            self.speech_augmentation = TimeDomainSpecAugment(\n                **config.audio_augment)\n\n        if not self.train:\n            return\n\n        train_config = config\n        model_optim_type = train_config.model_optim\n        model_optim_conf = train_config.model_optim_conf\n        logger.info(\"optim_model:{},{}\", model_optim_type, model_optim_conf)\n        wavlm_optim_type = train_config.wavlm_optim\n        wavlm_optim_conf = train_config.wavlm_optim_conf\n        logger.info(\"optim_model:{},{}\", wavlm_optim_type, wavlm_optim_conf)\n\n        model_scheduler_type = train_config.model_scheduler\n        model_scheduler_conf = train_config.model_scheduler_conf\n        wavlm_scheduler_type = train_config.wavlm_scheduler\n        wavlm_scheduler_conf = train_config.wavlm_scheduler_conf\n\n        model_scheduler_args = dict(\n            **{\"learning_rate\": model_optim_conf.lr,\n               \"verbose\": False}, **(dict(model_scheduler_conf)))\n\n        wavlm_scheduler_args = dict(\n            **{\"learning_rate\": wavlm_optim_conf.lr,\n               \"verbose\": False}, **(dict(wavlm_scheduler_conf)))\n\n        model_lr_scheduler = LRSchedulerFactory.from_args(model_scheduler_type,\n                                                          model_scheduler_args)\n        wavlm_lr_scheduler = LRSchedulerFactory.from_args(wavlm_scheduler_type,\n                                                          wavlm_scheduler_args)\n\n        def optimizer_args(\n                config,\n                optim_type,\n                optim_conf,\n                parameters,\n                lr_scheduler=None, ):\n            optim_arg = dict(optim_conf)\n            optim_arg.update({\n                \"learning_rate\":\n                lr_scheduler if lr_scheduler else optim_conf.lr,\n                \"parameters\":\n                parameters\n            })\n            return optim_arg\n\n        model_optimizer_args = optimizer_args(config, model_optim_type,\n                                              model_optim_conf, [{\n                                                  'params':\n                                                  model._layers.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model._layers.ctc.parameters()\n                                              }] if self.parallel else [{\n                                                  'params':\n                                                  model.enc.parameters()\n                                              }, {\n                                                  'params':\n                                                  model.ctc.parameters()\n                                              }], model_lr_scheduler)\n        # [{'params': model._layers.ctc.parameters()}] if self.parallel else [{'params': model.ctc.parameters()}], model_lr_scheduler)\n\n        wavlm_optimizer_args = optimizer_args(\n            config, wavlm_optim_type, wavlm_optim_conf,\n            model._layers.wavlm.parameters()\n            if self.parallel else model.wavlm.parameters(), wavlm_lr_scheduler)\n\n        model_optimizer = OptimizerFactory.from_args(model_optim_type,\n                                                     model_optimizer_args)\n        wavlm_optimizer = OptimizerFactory.from_args(wavlm_optim_type,\n                                                     wavlm_optimizer_args)\n\n        self.model_optimizer = model_optimizer\n        self.wavlm_optimizer = wavlm_optimizer\n        self.model_lr_scheduler = model_lr_scheduler\n        self.wavlm_lr_scheduler = wavlm_lr_scheduler\n        logger.info(\"Setup optimizer/lr_scheduler!\")\n\n\nclass WavLMASRTester(WavLMASRTrainer):\n    def __init__(self, config, args):\n        super().__init__(config, args)\n        self.text_featurizer = TextFeaturizer(\n            unit_type=config.unit_type, vocab=config.vocab_filepath)\n        self.vocab_list = self.text_featurizer.vocab_list\n\n    def id2token(self, texts, texts_len):\n        \"\"\" ord() id to chr() chr \"\"\"\n        trans = []\n        for text, n in zip(texts, texts_len):\n            n = n.numpy().item()\n            ids = text[:n]\n            trans.append(self.text_featurizer.defeaturize(ids.numpy().tolist()))\n        return trans\n\n    def compute_metrics(self, id, audio, audio_len, texts, texts_len,\n                        fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n\n        start_time = time.time()\n        target_transcripts = self.id2token(texts, texts_len)\n        result_transcripts, result_tokenids = self.model.decode(\n            audio,\n            text_feature=self.text_featurizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=audio_len.sum().numpy().item(),\n            decode_time=decode_time)\n\n    def sb_compute_metrics(self, id, sig, wrd, tokens, fout=None):\n        decode_cfg = self.config.decode\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        errors_func = error_rate.char_errors if decode_cfg.error_rate_type == 'cer' else error_rate.word_errors\n        error_rate_func = error_rate.cer if decode_cfg.error_rate_type == 'cer' else error_rate.wer\n        start_time = time.time()\n        target_transcripts = wrd\n        result_transcripts, result_tokenids = self.model.decode(\n            sig[0],\n            text_feature=self.tokenizer,\n            decoding_method=decode_cfg.decoding_method,\n            beam_size=decode_cfg.beam_size,\n            sb_pipeline=True)\n        decode_time = time.time() - start_time\n\n        for utt, target, result, rec_tids in zip(\n                id, target_transcripts, result_transcripts, result_tokenids):\n            errors, len_ref = errors_func(target, result)\n            errors_sum += errors\n            len_refs += len_ref\n            num_ins += 1\n            if fout:\n                fout.write({\n                    \"utt\": utt,\n                    \"refs\": [target],\n                    \"hyps\": [result],\n                    \"hyps_tokenid\": [rec_tids],\n                })\n            logger.info(f\"Utt: {utt}\")\n            logger.info(f\"Ref: {target}\")\n            logger.info(f\"Hyp: {result}\")\n            logger.info(\"One example error rate [%s] = %f\" % (\n                decode_cfg.error_rate_type, error_rate_func(target, result)))\n\n        return dict(\n            errors_sum=errors_sum,\n            len_refs=len_refs,\n            num_ins=num_ins,  # num examples\n            error_rate=errors_sum / len_refs,\n            error_rate_type=decode_cfg.error_rate_type,\n            num_frames=sig[1].sum().numpy().item(),\n            decode_time=decode_time)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def test(self):\n        logger.info(f\"Test Total Examples: {len(self.test_loader.dataset)}\")\n        self.model.eval()\n\n        error_rate_type = None\n        errors_sum, len_refs, num_ins = 0.0, 0, 0\n        num_frames = 0.0\n        num_time = 0.0\n        # Initialized the decoder in model\n        decode_cfg = self.config.decode\n        vocab_list = self.vocab_list\n        decode_batch_size = decode_cfg.decode_batch_size\n\n        with jsonlines.open(self.args.result_file, 'w') as fout:\n            for i, batch in enumerate(self.test_loader):\n                if self.use_sb:\n                    metrics = self.sb_compute_metrics(**batch, fout=fout)\n                else:\n                    metrics = self.compute_metrics(*batch, fout=fout)\n                num_frames += metrics['num_frames']\n                num_time += metrics[\"decode_time\"]\n                errors_sum += metrics['errors_sum']\n                len_refs += metrics['len_refs']\n                num_ins += metrics['num_ins']\n                error_rate_type = metrics['error_rate_type']\n                rtf = num_time / (num_frames)\n                logger.info(\n                    \"RTF: %f, Error rate [%s] (%d/?) = %f\" %\n                    (rtf, error_rate_type, num_ins, errors_sum / len_refs))\n\n        # logging\n        msg = \"Test: \"\n        msg += \"epoch: {}, \".format(self.epoch)\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"Final error rate [%s] (%d/%d) = %f\" % (\n            error_rate_type, num_ins, num_ins, errors_sum / len_refs)\n        logger.info(msg)\n\n        err_meta_path = os.path.splitext(self.args.result_file)[0] + '.err'\n        err_type_str = \"{}\".format(error_rate_type)\n        with open(err_meta_path, 'w', encoding='utf8') as f:\n            data = json.dumps({\n                \"epoch\":\n                self.epoch,\n                \"step\":\n                self.iteration,\n                \"rtf\":\n                rtf,\n                error_rate_type:\n                errors_sum / len_refs,\n                \"dataset_hour\": (num_frames) / 1000.0 / 3600.0,\n                \"process_hour\":\n                num_time / 1000.0 / 3600.0,\n                \"num_examples\":\n                num_ins,\n                \"err_sum\":\n                errors_sum,\n                \"ref_len\":\n                len_refs,\n                \"decode_method\":\n                self.config.decode.decoding_method,\n            })\n            f.write(data + '\\n')\n"
  },
  {
    "path": "paddlespeech/s2t/exps/whisper/test_wav.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.∏\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from Whisper (https://github.com/openai/whisper/whisper/)\nimport os.path\nimport sys\n\nimport distutils\nimport numpy as np\nimport paddle\nimport soundfile\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.models.whisper import log_mel_spectrogram\nfrom paddlespeech.s2t.models.whisper import ModelDimensions\nfrom paddlespeech.s2t.models.whisper import transcribe\nfrom paddlespeech.s2t.models.whisper import Whisper\nfrom paddlespeech.s2t.training.cli import default_argument_parser\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.utils.argparse import strtobool\n\nlogger = Log(__name__).getlog()\n\n\nclass WhisperInfer():\n    def __init__(self, config, args):\n        self.args = args\n        self.config = config\n        self.audio_file = args.audio_file\n\n        paddle.set_device('gpu' if self.args.ngpu > 0 else 'cpu')\n        config.pop(\"ngpu\")\n\n        #load_model\n        model_dict = paddle.load(self.config.model_file)\n        config.pop(\"model_file\")\n        dims = ModelDimensions(**model_dict[\"dims\"])\n        self.dims = dims\n        self.model = Whisper(dims)\n        self.model.load_dict(model_dict)\n\n    def run(self):\n        check(args.audio_file)\n\n        with paddle.no_grad():\n            temperature = config.pop(\"temperature\")\n            temperature_increment_on_fallback = config.pop(\n                \"temperature_increment_on_fallback\")\n            if temperature_increment_on_fallback is not None:\n                temperature = tuple(\n                    np.arange(temperature, 1.0 + 1e-6,\n                              temperature_increment_on_fallback))\n            else:\n                temperature = [temperature]\n\n            #load audio\n            mel = log_mel_spectrogram(\n                args.audio_file,\n                resource_path=config.resource_path,\n                n_mels=self.dims.n_mels,\n                padding=480000)\n            result = transcribe(\n                self.model, mel, temperature=temperature, **config)\n            if args.result_file is not None:\n                with open(args.result_file, 'w') as f:\n                    f.write(str(result))\n            return result\n\n\ndef check(audio_file: str):\n    if not os.path.isfile(audio_file):\n        print(\"Please input the right audio file path\")\n        sys.exit(-1)\n\n    logger.info(\"checking the audio file format......\")\n    try:\n        _, sample_rate = soundfile.read(audio_file)\n    except Exception as e:\n        logger.error(str(e))\n        logger.error(\n            \"can not open the wav file, please check the audio file format\")\n        sys.exit(-1)\n    logger.info(\"The sample rate is %d\" % sample_rate)\n    assert (sample_rate == 16000)\n    logger.info(\"The audio file format is right\")\n\n\ndef main(config, args):\n    WhisperInfer(config, args).run()\n\n\nif __name__ == \"__main__\":\n    parser = default_argument_parser()\n    # save asr result to\n    parser.add_argument(\n        \"--result_file\", type=str, help=\"path of save the asr result\")\n    parser.add_argument(\n        \"--audio_file\", type=str, help=\"path of the input audio file\")\n    parser.add_argument(\n        \"--debug\", type=strtobool, default=False, help=\"for debug.\")\n    args = parser.parse_args()\n\n    config = CfgNode(new_allowed=True)\n\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/audio.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the audio segment class.\"\"\"\nimport copy\nimport io\nimport random\nimport re\nimport struct\n\nimport numpy as np\nimport resampy\nimport soundfile\nfrom scipy import signal\n\nfrom .utility import convert_samples_from_float32\nfrom .utility import convert_samples_to_float32\nfrom .utility import subfile_from_tar\n\n\nclass AudioSegment():\n    \"\"\"Monaural audio segment abstraction.\n\n    :param samples: Audio samples [num_samples x num_channels].\n    :type samples: ndarray.float32\n    :param sample_rate: Audio sample rate.\n    :type sample_rate: int\n    :raises TypeError: If the sample data type is not float or int.\n    \"\"\"\n\n    def __init__(self, samples, sample_rate):\n        \"\"\"Create audio segment from samples.\n\n        Samples are convert float32 internally, with int scaled to [-1, 1].\n        \"\"\"\n        self._samples = self._convert_samples_to_float32(samples)\n        self._sample_rate = sample_rate\n        if self._samples.ndim >= 2:\n            self._samples = np.mean(self._samples, 1)\n\n    def __eq__(self, other):\n        \"\"\"Return whether two objects are equal.\"\"\"\n        if type(other) is not type(self):\n            return False\n        if self._sample_rate != other._sample_rate:\n            return False\n        if self._samples.shape != other._samples.shape:\n            return False\n        if np.any(self.samples != other._samples):\n            return False\n        return True\n\n    def __ne__(self, other):\n        \"\"\"Return whether two objects are unequal.\"\"\"\n        return not self.__eq__(other)\n\n    def __str__(self):\n        \"\"\"Return human-readable representation of segment.\"\"\"\n        return (\"%s: num_samples=%d, sample_rate=%d, duration=%.2fsec, \"\n                \"rms=%.2fdB\" % (type(self), self.num_samples, self.sample_rate,\n                                self.duration, self.rms_db))\n\n    @classmethod\n    def from_file(cls, file, infos=None):\n        \"\"\"Create audio segment from audio file.\n\n        Args:\n            filepath (str|file): Filepath or file object to audio file.\n            infos (TarLocalData, optional): tar2obj and tar2infos. Defaults to None.\n\n        Returns:\n            AudioSegment: Audio segment instance.\n        \"\"\"\n        if isinstance(file, str) and re.findall(r\".seqbin_\\d+$\", file):\n            return cls.from_sequence_file(file)\n        elif isinstance(file, str) and file.startswith('tar:'):\n            return cls.from_file(subfile_from_tar(file, infos))\n        else:\n            samples, sample_rate = soundfile.read(file, dtype='float32')\n            return cls(samples, sample_rate)\n\n    @classmethod\n    def slice_from_file(cls, file, start=None, end=None):\n        \"\"\"Loads a small section of an audio without having to load\n        the entire file into the memory which can be incredibly wasteful.\n\n        :param file: Input audio filepath or file object.\n        :type file: str|file\n        :param start: Start time in seconds. If start is negative, it wraps\n                      around from the end. If not provided, this function\n                      reads from the very beginning.\n        :type start: float\n        :param end: End time in seconds. If end is negative, it wraps around\n                    from the end. If not provided, the default behvaior is\n                    to read to the end of the file.\n        :type end: float\n        :return: AudioSegment instance of the specified slice of the input\n                 audio file.\n        :rtype: AudioSegment\n        :raise ValueError: If start or end is incorrectly set, e.g. out of\n                           bounds in time.\n        \"\"\"\n        sndfile = soundfile.SoundFile(file)\n        sample_rate = sndfile.samplerate\n        duration = float(len(sndfile)) / sample_rate\n        start = 0. if start is None else start\n        end = duration if end is None else end\n        if start < 0.0:\n            start += duration\n        if end < 0.0:\n            end += duration\n        if start < 0.0:\n            raise ValueError(\"The slice start position (%f s) is out of \"\n                             \"bounds.\" % start)\n        if end < 0.0:\n            raise ValueError(\"The slice end position (%f s) is out of bounds.\" %\n                             end)\n        if start > end:\n            raise ValueError(\"The slice start position (%f s) is later than \"\n                             \"the slice end position (%f s).\" % (start, end))\n        if end > duration:\n            raise ValueError(\"The slice end position (%f s) is out of bounds \"\n                             \"(> %f s)\" % (end, duration))\n        start_frame = int(start * sample_rate)\n        end_frame = int(end * sample_rate)\n        sndfile.seek(start_frame)\n        data = sndfile.read(frames=end_frame - start_frame, dtype='float32')\n        return cls(data, sample_rate)\n\n    @classmethod\n    def from_sequence_file(cls, filepath):\n        \"\"\"Create audio segment from sequence file. Sequence file is a binary\n        file containing a collection of multiple audio files, with several\n        header bytes in the head indicating the offsets of each audio byte data\n        chunk.\n\n        The format is:\n\n            4 bytes (int, version),\n            4 bytes (int, num of utterance),\n            4 bytes (int, bytes per header),\n            [bytes_per_header*(num_utterance+1)] bytes (offsets for each audio),\n            audio_bytes_data_of_1st_utterance,\n            audio_bytes_data_of_2nd_utterance,\n            ......\n\n        Sequence file name must end with \".seqbin\". And the filename of the 5th\n        utterance's audio file in sequence file \"xxx.seqbin\" must be\n        \"xxx.seqbin_5\", with \"5\" indicating the utterance index within this\n        sequence file (starting from 1).\n\n        :param filepath: Filepath of sequence file.\n        :type filepath: str\n        :return: Audio segment instance.\n        :rtype: AudioSegment\n        \"\"\"\n        # parse filepath\n        matches = re.match(r\"(.+\\.seqbin)_(\\d+)\", filepath)\n        if matches is None:\n            raise IOError(\"File type of %s is not supported\" % filepath)\n        filename = matches.group(1)\n        fileno = int(matches.group(2))\n\n        # read headers\n        f = io.open(filename, mode='rb', encoding='utf8')\n        version = f.read(4)\n        num_utterances = struct.unpack(\"i\", f.read(4))[0]\n        bytes_per_header = struct.unpack(\"i\", f.read(4))[0]\n        header_bytes = f.read(bytes_per_header * (num_utterances + 1))\n        header = [\n            struct.unpack(\"i\", header_bytes[bytes_per_header * i:\n                                            bytes_per_header * (i + 1)])[0]\n            for i in range(num_utterances + 1)\n        ]\n\n        # read audio bytes\n        f.seek(header[fileno - 1])\n        audio_bytes = f.read(header[fileno] - header[fileno - 1])\n        f.close()\n\n        # create audio segment\n        try:\n            return cls.from_bytes(audio_bytes)\n        except Exception as e:\n            samples = np.frombuffer(audio_bytes, dtype='int16')\n            return cls(samples=samples, sample_rate=8000)\n\n    @classmethod\n    def from_bytes(cls, bytes):\n        \"\"\"Create audio segment from a byte string containing audio samples.\n\n        :param bytes: Byte string containing audio samples.\n        :type bytes: str\n        :return: Audio segment instance.\n        :rtype: AudioSegment\n        \"\"\"\n        samples, sample_rate = soundfile.read(\n            io.BytesIO(bytes), dtype='float32')\n        return cls(samples, sample_rate)\n\n    @classmethod\n    def from_pcm(cls, samples, sample_rate):\n        \"\"\"Create audio segment from a byte string containing audio samples.\n        :param samples: Audio samples [num_samples x num_channels].\n        :type samples: numpy.ndarray\n        :param sample_rate: Audio sample rate.\n        :type sample_rate: int\n        :return: Audio segment instance.\n        :rtype: AudioSegment\n        \"\"\"\n        return cls(samples, sample_rate)\n\n    @classmethod\n    def concatenate(cls, *segments):\n        \"\"\"Concatenate an arbitrary number of audio segments together.\n\n        :param *segments: Input audio segments to be concatenated.\n        :type *segments: tuple of AudioSegment\n        :return: Audio segment instance as concatenating results.\n        :rtype: AudioSegment\n        :raises ValueError: If the number of segments is zero, or if the\n                            sample_rate of any segments does not match.\n        :raises TypeError: If any segment is not AudioSegment instance.\n        \"\"\"\n        # Perform basic sanity-checks.\n        if len(segments) == 0:\n            raise ValueError(\"No audio segments are given to concatenate.\")\n        sample_rate = segments[0]._sample_rate\n        for seg in segments:\n            if sample_rate != seg._sample_rate:\n                raise ValueError(\"Can't concatenate segments with \"\n                                 \"different sample rates\")\n            if type(seg) is not cls:\n                raise TypeError(\"Only audio segments of the same type \"\n                                \"can be concatenated.\")\n        samples = np.concatenate([seg.samples for seg in segments])\n        return cls(samples, sample_rate)\n\n    @classmethod\n    def make_silence(cls, duration, sample_rate):\n        \"\"\"Creates a silent audio segment of the given duration and sample rate.\n\n        :param duration: Length of silence in seconds.\n        :type duration: float\n        :param sample_rate: Sample rate.\n        :type sample_rate: float\n        :return: Silent AudioSegment instance of the given duration.\n        :rtype: AudioSegment\n        \"\"\"\n        samples = np.zeros(int(duration * sample_rate))\n        return cls(samples, sample_rate)\n\n    def to_wav_file(self, filepath, dtype='float32'):\n        \"\"\"Save audio segment to disk as wav file.\n\n        :param filepath: WAV filepath or file object to save the\n                         audio segment.\n        :type filepath: str|file\n        :param dtype: Subtype for audio file. Options: 'int16', 'int32',\n                      'float32', 'float64'. Default is 'float32'.\n        :type dtype: str\n        :raises TypeError: If dtype is not supported.\n        \"\"\"\n        samples = self._convert_samples_from_float32(self._samples, dtype)\n        subtype_map = {\n            'int16': 'PCM_16',\n            'int32': 'PCM_32',\n            'float32': 'FLOAT',\n            'float64': 'DOUBLE'\n        }\n        soundfile.write(\n            filepath,\n            samples,\n            self._sample_rate,\n            format='WAV',\n            subtype=subtype_map[dtype])\n\n    def superimpose(self, other):\n        \"\"\"Add samples from another segment to those of this segment\n        (sample-wise addition, not segment concatenation).\n\n        Note that this is an in-place transformation.\n\n        :param other: Segment containing samples to be added in.\n        :type other: AudioSegments\n        :raise TypeError: If type of two segments don't match.\n        :raise ValueError: If the sample rates of the two segments are not\n                           equal, or if the lengths of segments don't match.\n        \"\"\"\n        if isinstance(other, type(self)):\n            raise TypeError(\"Cannot add segments of different types: %s \"\n                            \"and %s.\" % (type(self), type(other)))\n        if self._sample_rate != other._sample_rate:\n            raise ValueError(\"Sample rates must match to add segments.\")\n        if len(self._samples) != len(other._samples):\n            raise ValueError(\"Segment lengths must match to add segments.\")\n        self._samples += other._samples\n\n    def to_bytes(self, dtype='float32'):\n        \"\"\"Create a byte string containing the audio content.\n\n        :param dtype: Data type for export samples. Options: 'int16', 'int32',\n                      'float32', 'float64'. Default is 'float32'.\n        :type dtype: str\n        :return: Byte string containing audio content.\n        :rtype: str\n        \"\"\"\n        samples = self._convert_samples_from_float32(self._samples, dtype)\n        return samples.tostring()\n\n    def to(self, dtype='int16'):\n        \"\"\"Create a `dtype` audio content.\n\n        :param dtype: Data type for export samples. Options: 'int16', 'int32',\n                      'float32', 'float64'. Default is 'float32'.\n        :type dtype: str\n        :return: np.ndarray containing `dtype` audio content.\n        :rtype: str\n        \"\"\"\n        samples = self._convert_samples_from_float32(self._samples, dtype)\n        return samples\n\n    def gain_db(self, gain):\n        \"\"\"Apply gain in decibels to samples.\n\n        Note that this is an in-place transformation.\n\n        :param gain: Gain in decibels to apply to samples.\n        :type gain: float|1darray\n        \"\"\"\n        self._samples *= 10.**(gain / 20.)\n\n    def change_speed(self, speed_rate):\n        \"\"\"Change the audio speed by linear interpolation.\n\n        Note that this is an in-place transformation.\n\n        :param speed_rate: Rate of speed change:\n                           speed_rate > 1.0, speed up the audio;\n                           speed_rate = 1.0, unchanged;\n                           speed_rate < 1.0, slow down the audio;\n                           speed_rate <= 0.0, not allowed, raise ValueError.\n        :type speed_rate: float\n        :raises ValueError: If speed_rate <= 0.0.\n        \"\"\"\n        if speed_rate == 1.0:\n            return\n        if speed_rate <= 0:\n            raise ValueError(\"speed_rate should be greater than zero.\")\n\n        # numpy\n        # old_length = self._samples.shape[0]\n        # new_length = int(old_length / speed_rate)\n        # old_indices = np.arange(old_length)\n        # new_indices = np.linspace(start=0, stop=old_length, num=new_length)\n        # self._samples = np.interp(new_indices, old_indices, self._samples)\n\n        # sox, slow\n        try:\n            import soxbindings as sox\n        except ImportError:\n            try:\n                from paddlespeech.s2t.utils import dynamic_pip_install\n                package = \"sox\"\n                dynamic_pip_install.install(package)\n                package = \"soxbindings\"\n                dynamic_pip_install.install(package)\n                import soxbindings as sox\n            except Exception:\n                raise RuntimeError(\n                    \"Can not install soxbindings on your system.\")\n\n        tfm = sox.Transformer()\n        tfm.set_globals(multithread=False)\n        tfm.speed(speed_rate)\n        self._samples = tfm.build_array(\n            input_array=self._samples,\n            sample_rate_in=self._sample_rate).squeeze(-1).astype(\n                np.float32).copy()\n\n    def normalize(self, target_db=-20, max_gain_db=300.0):\n        \"\"\"Normalize audio to be of the desired RMS value in decibels.\n\n        Note that this is an in-place transformation.\n\n        :param target_db: Target RMS value in decibels. This value should be\n                          less than 0.0 as 0.0 is full-scale audio.\n        :type target_db: float\n        :param max_gain_db: Max amount of gain in dB that can be applied for\n                            normalization. This is to prevent nans when\n                            attempting to normalize a signal consisting of\n                            all zeros.\n        :type max_gain_db: float\n        :raises ValueError: If the required gain to normalize the segment to\n                            the target_db value exceeds max_gain_db.\n        \"\"\"\n        gain = target_db - self.rms_db\n        if gain > max_gain_db:\n            raise ValueError(\n                \"Unable to normalize segment to %f dB because the \"\n                \"the probable gain have exceeds max_gain_db (%f dB)\" %\n                (target_db, max_gain_db))\n        self.gain_db(min(max_gain_db, target_db - self.rms_db))\n\n    def normalize_online_bayesian(self,\n                                  target_db,\n                                  prior_db,\n                                  prior_samples,\n                                  startup_delay=0.0):\n        \"\"\"Normalize audio using a production-compatible online/causal\n        algorithm. This uses an exponential likelihood and gamma prior to\n        make online estimates of the RMS even when there are very few samples.\n\n        Note that this is an in-place transformation.\n\n        :param target_db: Target RMS value in decibels.\n        :type target_bd: float\n        :param prior_db: Prior RMS estimate in decibels.\n        :type prior_db: float\n        :param prior_samples: Prior strength in number of samples.\n        :type prior_samples: float\n        :param startup_delay: Default 0.0s. If provided, this function will\n                              accrue statistics for the first startup_delay\n                              seconds before applying online normalization.\n        :type startup_delay: float\n        \"\"\"\n        # Estimate total RMS online.\n        startup_sample_idx = min(self.num_samples - 1,\n                                 int(self.sample_rate * startup_delay))\n        prior_mean_squared = 10.**(prior_db / 10.)\n        prior_sum_of_squares = prior_mean_squared * prior_samples\n        cumsum_of_squares = np.cumsum(self.samples**2)\n        sample_count = np.arange(self.num_samples) + 1\n        if startup_sample_idx > 0:\n            cumsum_of_squares[:startup_sample_idx] = \\\n                cumsum_of_squares[startup_sample_idx]\n            sample_count[:startup_sample_idx] = \\\n                sample_count[startup_sample_idx]\n        mean_squared_estimate = ((cumsum_of_squares + prior_sum_of_squares) /\n                                 (sample_count + prior_samples))\n        rms_estimate_db = 10 * np.log10(mean_squared_estimate)\n        # Compute required time-varying gain.\n        gain_db = target_db - rms_estimate_db\n        self.gain_db(gain_db)\n\n    def resample(self, target_sample_rate, filter='kaiser_best'):\n        \"\"\"Resample the audio to a target sample rate.\n\n        Note that this is an in-place transformation.\n\n        :param target_sample_rate: Target sample rate.\n        :type target_sample_rate: int\n        :param filter: The resampling filter to use one of {'kaiser_best',\n                       'kaiser_fast'}.\n        :type filter: str\n        \"\"\"\n        self._samples = resampy.resample(\n            self.samples, self.sample_rate, target_sample_rate, filter=filter)\n        self._sample_rate = target_sample_rate\n\n    def pad_silence(self, duration, sides='both'):\n        \"\"\"Pad this audio sample with a period of silence.\n\n        Note that this is an in-place transformation.\n\n        :param duration: Length of silence in seconds to pad.\n        :type duration: float\n        :param sides: Position for padding:\n                     'beginning' - adds silence in the beginning;\n                     'end' - adds silence in the end;\n                     'both' - adds silence in both the beginning and the end.\n        :type sides: str\n        :raises ValueError: If sides is not supported.\n        \"\"\"\n        if duration == 0.0:\n            return self\n        cls = type(self)\n        silence = self.make_silence(duration, self._sample_rate)\n        if sides == \"beginning\":\n            padded = cls.concatenate(silence, self)\n        elif sides == \"end\":\n            padded = cls.concatenate(self, silence)\n        elif sides == \"both\":\n            padded = cls.concatenate(silence, self, silence)\n        else:\n            raise ValueError(\"Unknown value for the sides %s\" % sides)\n        self._samples = padded._samples\n\n    def shift(self, shift_ms):\n        \"\"\"Shift the audio in time. If `shift_ms` is positive, shift with time\n        advance; if negative, shift with time delay. Silence are padded to\n        keep the duration unchanged.\n\n        Note that this is an in-place transformation.\n\n        :param shift_ms: Shift time in millseconds. If positive, shift with\n                         time advance; if negative; shift with time delay.\n        :type shift_ms: float\n        :raises ValueError: If shift_ms is longer than audio duration.\n        \"\"\"\n        if abs(shift_ms) / 1000.0 > self.duration:\n            raise ValueError(\"Absolute value of shift_ms should be smaller \"\n                             \"than audio duration.\")\n        shift_samples = int(shift_ms * self._sample_rate / 1000)\n        if shift_samples > 0:\n            # time advance\n            self._samples[:-shift_samples] = self._samples[shift_samples:]\n            self._samples[-shift_samples:] = 0\n        elif shift_samples < 0:\n            # time delay\n            self._samples[-shift_samples:] = self._samples[:shift_samples]\n            self._samples[:-shift_samples] = 0\n\n    def subsegment(self, start_sec=None, end_sec=None):\n        \"\"\"Cut the AudioSegment between given boundaries.\n\n        Note that this is an in-place transformation.\n\n        :param start_sec: Beginning of subsegment in seconds.\n        :type start_sec: float\n        :param end_sec: End of subsegment in seconds.\n        :type end_sec: float\n        :raise ValueError: If start_sec or end_sec is incorrectly set, e.g. out\n                           of bounds in time.\n        \"\"\"\n        start_sec = 0.0 if start_sec is None else start_sec\n        end_sec = self.duration if end_sec is None else end_sec\n        if start_sec < 0.0:\n            start_sec = self.duration + start_sec\n        if end_sec < 0.0:\n            end_sec = self.duration + end_sec\n        if start_sec < 0.0:\n            raise ValueError(\"The slice start position (%f s) is out of \"\n                             \"bounds.\" % start_sec)\n        if end_sec < 0.0:\n            raise ValueError(\"The slice end position (%f s) is out of bounds.\" %\n                             end_sec)\n        if start_sec > end_sec:\n            raise ValueError(\"The slice start position (%f s) is later than \"\n                             \"the end position (%f s).\" % (start_sec, end_sec))\n        if end_sec > self.duration:\n            raise ValueError(\"The slice end position (%f s) is out of bounds \"\n                             \"(> %f s)\" % (end_sec, self.duration))\n        start_sample = int(round(start_sec * self._sample_rate))\n        end_sample = int(round(end_sec * self._sample_rate))\n        self._samples = self._samples[start_sample:end_sample]\n\n    def random_subsegment(self, subsegment_length, rng=None):\n        \"\"\"Cut the specified length of the audiosegment randomly.\n\n        Note that this is an in-place transformation.\n\n        :param subsegment_length: Subsegment length in seconds.\n        :type subsegment_length: float\n        :param rng: Random number generator state.\n        :type rng: random.Random\n        :raises ValueError: If the length of subsegment is greater than\n                            the origineal segemnt.\n        \"\"\"\n        rng = random.Random() if rng is None else rng\n        if subsegment_length > self.duration:\n            raise ValueError(\"Length of subsegment must not be greater \"\n                             \"than original segment.\")\n        start_time = rng.uniform(0.0, self.duration - subsegment_length)\n        self.subsegment(start_time, start_time + subsegment_length)\n\n    def convolve(self, impulse_segment, allow_resample=False):\n        \"\"\"Convolve this audio segment with the given impulse segment.\n\n        Note that this is an in-place transformation.\n\n        :param impulse_segment: Impulse response segments.\n        :type impulse_segment: AudioSegment\n        :param allow_resample: Indicates whether resampling is allowed when\n                               the impulse_segment has a different sample\n                               rate from this signal.\n        :type allow_resample: bool\n        :raises ValueError: If the sample rate is not match between two\n                            audio segments when resample is not allowed.\n        \"\"\"\n        if allow_resample and self.sample_rate != impulse_segment.sample_rate:\n            impulse_segment.resample(self.sample_rate)\n        if self.sample_rate != impulse_segment.sample_rate:\n            raise ValueError(\"Impulse segment's sample rate (%d Hz) is not \"\n                             \"equal to base signal sample rate (%d Hz).\" %\n                             (impulse_segment.sample_rate, self.sample_rate))\n        samples = signal.fftconvolve(self.samples, impulse_segment.samples,\n                                     \"full\")\n        self._samples = samples\n\n    def convolve_and_normalize(self, impulse_segment, allow_resample=False):\n        \"\"\"Convolve and normalize the resulting audio segment so that it\n        has the same average power as the input signal.\n\n        Note that this is an in-place transformation.\n\n        :param impulse_segment: Impulse response segments.\n        :type impulse_segment: AudioSegment\n        :param allow_resample: Indicates whether resampling is allowed when\n                               the impulse_segment has a different sample\n                               rate from this signal.\n        :type allow_resample: bool\n        \"\"\"\n        target_db = self.rms_db\n        self.convolve(impulse_segment, allow_resample=allow_resample)\n        self.normalize(target_db)\n\n    def add_noise(self,\n                  noise,\n                  snr_dB,\n                  allow_downsampling=False,\n                  max_gain_db=300.0,\n                  rng=None):\n        \"\"\"Add the given noise segment at a specific signal-to-noise ratio.\n        If the noise segment is longer than this segment, a random subsegment\n        of matching length is sampled from it and used instead.\n\n        Note that this is an in-place transformation.\n\n        :param noise: Noise signal to add.\n        :type noise: AudioSegment\n        :param snr_dB: Signal-to-Noise Ratio, in decibels.\n        :type snr_dB: float\n        :param allow_downsampling: Whether to allow the noise signal to be\n                                   downsampled to match the base signal sample\n                                   rate.\n        :type allow_downsampling: bool\n        :param max_gain_db: Maximum amount of gain to apply to noise signal\n                            before adding it in. This is to prevent attempting\n                            to apply infinite gain to a zero signal.\n        :type max_gain_db: float\n        :param rng: Random number generator state.\n        :type rng: None|random.Random\n        :raises ValueError: If the sample rate does not match between the two\n                            audio segments when downsampling is not allowed, or\n                            if the duration of noise segments is shorter than\n                            original audio segments.\n        \"\"\"\n        rng = random.Random() if rng is None else rng\n        if allow_downsampling and noise.sample_rate > self.sample_rate:\n            noise = noise.resample(self.sample_rate)\n        if noise.sample_rate != self.sample_rate:\n            raise ValueError(\"Noise sample rate (%d Hz) is not equal to base \"\n                             \"signal sample rate (%d Hz).\" % (noise.sample_rate,\n                                                              self.sample_rate))\n        if noise.duration < self.duration:\n            raise ValueError(\"Noise signal (%f sec) must be at least as long as\"\n                             \" base signal (%f sec).\" %\n                             (noise.duration, self.duration))\n        noise_gain_db = min(self.rms_db - noise.rms_db - snr_dB, max_gain_db)\n        noise_new = copy.deepcopy(noise)\n        noise_new.random_subsegment(self.duration, rng=rng)\n        noise_new.gain_db(noise_gain_db)\n        self.superimpose(noise_new)\n\n    @property\n    def samples(self):\n        \"\"\"Return audio samples.\n\n        :return: Audio samples.\n        :rtype: ndarray\n        \"\"\"\n        return self._samples.copy()\n\n    @property\n    def sample_rate(self):\n        \"\"\"Return audio sample rate.\n\n        :return: Audio sample rate.\n        :rtype: int\n        \"\"\"\n        return self._sample_rate\n\n    @property\n    def num_samples(self):\n        \"\"\"Return number of samples.\n\n        :return: Number of samples.\n        :rtype: int\n        \"\"\"\n        return self._samples.shape[0]\n\n    @property\n    def duration(self):\n        \"\"\"Return audio duration.\n\n        :return: Audio duration in seconds.\n        :rtype: float\n        \"\"\"\n        return self._samples.shape[0] / float(self._sample_rate)\n\n    @property\n    def rms_db(self):\n        \"\"\"Return root mean square energy of the audio in decibels.\n\n        :return: Root mean square energy in decibels.\n        :rtype: float\n        \"\"\"\n        # square root => multiply by 10 instead of 20 for dBs\n        mean_square = np.mean(self._samples**2)\n        return 10 * np.log10(mean_square)\n\n    def _convert_samples_to_float32(self, samples):\n        \"\"\"Convert sample type to float32.\n\n        Audio sample type is usually integer or float-point.\n        Integers will be scaled to [-1, 1] in float32.\n        \"\"\"\n        return convert_samples_to_float32(samples)\n\n    def _convert_samples_from_float32(self, samples, dtype):\n        \"\"\"Convert sample type from float32 to dtype.\n\n        Audio sample type is usually integer or float-point. For integer\n        type, float32 will be rescaled from [-1, 1] to the maximum range\n        supported by the integer type.\n\n        This is for writing a audio file.\n        \"\"\"\n        return convert_samples_from_float32(samples, dtype)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/augmentation.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the data augmentation pipeline.\"\"\"\nimport json\nimport os\nfrom collections.abc import Sequence\nfrom inspect import signature\nfrom pprint import pformat\n\nimport numpy as np\n\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"AugmentationPipeline\"]\n\nimport_alias = dict(\n    volume=\"paddlespeech.s2t.frontend.augmentor.impulse_response:VolumePerturbAugmentor\",\n    shift=\"paddlespeech.s2t.frontend.augmentor.shift_perturb:ShiftPerturbAugmentor\",\n    speed=\"paddlespeech.s2t.frontend.augmentor.speed_perturb:SpeedPerturbAugmentor\",\n    resample=\"paddlespeech.s2t.frontend.augmentor.resample:ResampleAugmentor\",\n    bayesian_normal=\"paddlespeech.s2t.frontend.augmentor.online_bayesian_normalization:OnlineBayesianNormalizationAugmentor\",\n    noise=\"paddlespeech.s2t.frontend.augmentor.noise_perturb:NoisePerturbAugmentor\",\n    impulse=\"paddlespeech.s2t.frontend.augmentor.impulse_response:ImpulseResponseAugmentor\",\n    specaug=\"paddlespeech.s2t.frontend.augmentor.spec_augment:SpecAugmentor\", )\n\n\nclass AugmentationPipeline():\n    \"\"\"Build a pre-processing pipeline with various augmentation models.Such a\n    data augmentation pipeline is oftern leveraged to augment the training\n    samples to make the model invariant to certain types of perturbations in the\n    real world, improving model's generalization ability.\n\n    The pipeline is built according to the augmentation configuration in json\n    string, e.g.\n    \n    .. code-block::\n\n        [ {\n                \"type\": \"noise\",\n                \"params\": {\"min_snr_dB\": 10,\n                           \"max_snr_dB\": 20,\n                           \"noise_manifest_path\": \"datasets/manifest.noise\"},\n                \"prob\": 0.0\n            },\n            {\n                \"type\": \"speed\",\n                \"params\": {\"min_speed_rate\": 0.9,\n                           \"max_speed_rate\": 1.1},\n                \"prob\": 1.0\n            },\n            {\n                \"type\": \"shift\",\n                \"params\": {\"min_shift_ms\": -5,\n                           \"max_shift_ms\": 5},\n                \"prob\": 1.0\n            },\n            {\n                \"type\": \"volume\",\n                \"params\": {\"min_gain_dBFS\": -10,\n                           \"max_gain_dBFS\": 10},\n                \"prob\": 0.0\n            },\n            {\n                \"type\": \"bayesian_normal\",\n                \"params\": {\"target_db\": -20,\n                           \"prior_db\": -20,\n                           \"prior_samples\": 100},\n                \"prob\": 0.0\n            }\n        ]\n        \n    This augmentation configuration inserts two augmentation models\n    into the pipeline, with one is VolumePerturbAugmentor and the other\n    SpeedPerturbAugmentor. \"prob\" indicates the probability of the current\n    augmentor to take effect. If \"prob\" is zero, the augmentor does not take\n    effect.\n\n    Params:\n        preprocess_conf(str): Augmentation configuration in `json file` or `json string`.\n        random_seed(int): Random seed.\n    \n    Raises:\n        ValueError: If the augmentation json config is in incorrect format\".\n    \"\"\"\n\n    SPEC_TYPES = {'specaug'}\n\n    def __init__(self, preprocess_conf: str, random_seed: int=0):\n        self._rng = np.random.RandomState(random_seed)\n        self.conf = {'mode': 'sequential', 'process': []}\n        if preprocess_conf:\n            if os.path.isfile(preprocess_conf):\n                # json file\n                with open(preprocess_conf, 'r') as fin:\n                    json_string = fin.read()\n            else:\n                # json string\n                json_string = preprocess_conf\n            process = json.loads(json_string)\n            self.conf['process'] += process\n\n        self._augmentors, self._rates = self._parse_pipeline_from('all')\n        self._audio_augmentors, self._audio_rates = self._parse_pipeline_from(\n            'audio')\n        self._spec_augmentors, self._spec_rates = self._parse_pipeline_from(\n            'feature')\n        logger.info(\n            f\"Augmentation: {pformat(list(zip(self._augmentors, self._rates)))}\")\n\n    def __call__(self, xs, uttid_list=None, **kwargs):\n        if not isinstance(xs, Sequence):\n            is_batch = False\n            xs = [xs]\n        else:\n            is_batch = True\n\n        if isinstance(uttid_list, str):\n            uttid_list = [uttid_list for _ in range(len(xs))]\n\n        if self.conf.get(\"mode\", \"sequential\") == \"sequential\":\n            for idx, (func, rate) in enumerate(\n                    zip(self._augmentors, self._rates), 0):\n                if self._rng.uniform(0., 1.) >= rate:\n                    continue\n\n                # Derive only the args which the func has\n                try:\n                    param = signature(func).parameters\n                except ValueError:\n                    # Some function, e.g. built-in function, are failed\n                    param = {}\n                _kwargs = {k: v for k, v in kwargs.items() if k in param}\n\n                try:\n                    if uttid_list is not None and \"uttid\" in param:\n                        xs = [\n                            func(x, u, **_kwargs)\n                            for x, u in zip(xs, uttid_list)\n                        ]\n                    else:\n                        xs = [func(x, **_kwargs) for x in xs]\n                except Exception:\n                    logger.fatal(\"Catch a exception from {}th func: {}\".format(\n                        idx, func))\n                    raise\n        else:\n            raise NotImplementedError(\n                \"Not supporting mode={}\".format(self.conf[\"mode\"]))\n\n        if is_batch:\n            return xs\n        else:\n            return xs[0]\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Run the pre-processing pipeline for data augmentation.\n\n        Note that this is an in-place transformation.\n        \n        :param audio_segment: Audio segment to process.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        for augmentor, rate in zip(self._audio_augmentors, self._audio_rates):\n            if self._rng.uniform(0., 1.) < rate:\n                augmentor.transform_audio(audio_segment)\n\n    def transform_feature(self, spec_segment):\n        \"\"\"spectrogram augmentation.\n         \n        Args:\n            spec_segment (np.ndarray): audio feature, (D, T).\n        \"\"\"\n        for augmentor, rate in zip(self._spec_augmentors, self._spec_rates):\n            if self._rng.uniform(0., 1.) < rate:\n                spec_segment = augmentor.transform_feature(spec_segment)\n        return spec_segment\n\n    def _parse_pipeline_from(self, aug_type='all'):\n        \"\"\"Parse the config json to build a augmentation pipelien.\"\"\"\n        assert aug_type in ('audio', 'feature', 'all'), aug_type\n        audio_confs = []\n        feature_confs = []\n        all_confs = []\n        for config in self.conf['process']:\n            all_confs.append(config)\n            if config[\"type\"] in self.SPEC_TYPES:\n                feature_confs.append(config)\n            else:\n                audio_confs.append(config)\n\n        if aug_type == 'audio':\n            aug_confs = audio_confs\n        elif aug_type == 'feature':\n            aug_confs = feature_confs\n        elif aug_type == 'all':\n            aug_confs = all_confs\n        else:\n            raise ValueError(f\"Not support: {aug_type}\")\n\n        augmentors = [\n            self._get_augmentor(config[\"type\"], config[\"params\"])\n            for config in aug_confs\n        ]\n        rates = [config[\"prob\"] for config in aug_confs]\n        return augmentors, rates\n\n    def _get_augmentor(self, augmentor_type, params):\n        \"\"\"Return an augmentation model by the type name, and pass in params.\"\"\"\n        class_obj = dynamic_import(augmentor_type, import_alias)\n        assert issubclass(class_obj, AugmentorBase)\n        try:\n            obj = class_obj(self._rng, **params)\n        except Exception:\n            raise ValueError(\"Unknown augmentor type [%s].\" % augmentor_type)\n        return obj\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/base.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the abstract base class for augmentation models.\"\"\"\nfrom abc import ABCMeta\nfrom abc import abstractmethod\n\n\nclass AugmentorBase():\n    \"\"\"Abstract base class for augmentation model (augmentor) class.\n    All augmentor classes should inherit from this class, and implement the\n    following abstract methods.\n    \"\"\"\n\n    __metaclass__ = ABCMeta\n\n    @abstractmethod\n    def __init__(self):\n        pass\n\n    @abstractmethod\n    def __call__(self, xs):\n        raise NotImplementedError(\"AugmentorBase: Not impl __call__\")\n\n    @abstractmethod\n    def transform_audio(self, audio_segment):\n        \"\"\"Adds various effects to the input audio segment. Such effects\n        will augment the training data to make the model invariant to certain\n        types of perturbations in the real world, improving model's\n        generalization ability.\n        \n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        raise NotImplementedError(\"AugmentorBase: Not impl transform_audio\")\n\n    @abstractmethod\n    def transform_feature(self, spec_segment):\n        \"\"\"Adds various effects to the input audo feature segment. Such effects\n        will augment the training data to make the model invariant to certain\n        types of time_mask or freq_mask in the real world, improving model's\n        generalization ability.\n        \n        Args:\n            spec_segment (Spectrogram): Spectrogram segment to add effects to.\n        \"\"\"\n        raise NotImplementedError(\"AugmentorBase: Not impl transform_feature\")\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/impulse_response.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the impulse response augmentation model.\"\"\"\nimport jsonlines\n\nfrom paddlespeech.s2t.frontend.audio import AudioSegment\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass ImpulseResponseAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding impulse response effect.\n\n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param impulse_manifest_path: Manifest path for impulse audio data.\n    :type impulse_manifest_path: str\n    \"\"\"\n\n    def __init__(self, rng, impulse_manifest_path):\n        self._rng = rng\n        with jsonlines.open(impulse_manifest_path, 'r') as reader:\n            self._impulse_manifest = list(reader)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Add impulse response effect.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        impulse_json = self._rng.choice(\n            self._impulse_manifest, 1, replace=False)[0]\n        impulse_segment = AudioSegment.from_file(impulse_json['audio_filepath'])\n        audio_segment.convolve(impulse_segment, allow_resample=True)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/noise_perturb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the noise perturb augmentation model.\"\"\"\nimport jsonlines\n\nfrom paddlespeech.s2t.frontend.audio import AudioSegment\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass NoisePerturbAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding background noise.\n\n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param min_snr_dB: Minimal signal noise ratio, in decibels.\n    :type min_snr_dB: float\n    :param max_snr_dB: Maximal signal noise ratio, in decibels.\n    :type max_snr_dB: float\n    :param noise_manifest_path: Manifest path for noise audio data.\n    :type noise_manifest_path: str\n    \"\"\"\n\n    def __init__(self, rng, min_snr_dB, max_snr_dB, noise_manifest_path):\n        self._min_snr_dB = min_snr_dB\n        self._max_snr_dB = max_snr_dB\n        self._rng = rng\n        with jsonlines.open(noise_manifest_path, 'r') as reader:\n            self._noise_manifest = list(reader)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Add background noise audio.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        noise_json = self._rng.choice(self._noise_manifest, 1, replace=False)[0]\n        if noise_json['duration'] < audio_segment.duration:\n            raise RuntimeError(\"The duration of sampled noise audio is smaller \"\n                               \"than the audio segment to add effects to.\")\n        diff_duration = noise_json['duration'] - audio_segment.duration\n        start = self._rng.uniform(0, diff_duration)\n        end = start + audio_segment.duration\n        noise_segment = AudioSegment.slice_from_file(\n            noise_json['audio_filepath'], start=start, end=end)\n        snr_dB = self._rng.uniform(self._min_snr_dB, self._max_snr_dB)\n        audio_segment.add_noise(\n            noise_segment, snr_dB, allow_downsampling=True, rng=self._rng)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/online_bayesian_normalization.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contain the online bayesian normalization augmentation model.\"\"\"\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass OnlineBayesianNormalizationAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding online bayesian normalization.\n\n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param target_db: Target RMS value in decibels.\n    :type target_db: float\n    :param prior_db: Prior RMS estimate in decibels.\n    :type prior_db: float\n    :param prior_samples: Prior strength in number of samples.\n    :type prior_samples: int\n    :param startup_delay: Default 0.0s. If provided, this function will\n                          accrue statistics for the first startup_delay \n                          seconds before applying online normalization.\n    :type starup_delay: float.\n    \"\"\"\n\n    def __init__(self,\n                 rng,\n                 target_db,\n                 prior_db,\n                 prior_samples,\n                 startup_delay=0.0):\n        self._target_db = target_db\n        self._prior_db = prior_db\n        self._prior_samples = prior_samples\n        self._rng = rng\n        self._startup_delay = startup_delay\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Normalizes the input audio using the online Bayesian approach.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegment|SpeechSegment\n        \"\"\"\n        audio_segment.normalize_online_bayesian(self._target_db, self._prior_db,\n                                                self._prior_samples,\n                                                self._startup_delay)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/resample.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contain the resample augmentation model.\"\"\"\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass ResampleAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for resampling.\n\n    See more info here:\n    https://ccrma.stanford.edu/~jos/resample/index.html\n    \n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param new_sample_rate: New sample rate in Hz.\n    :type new_sample_rate: int\n    \"\"\"\n\n    def __init__(self, rng, new_sample_rate):\n        self._new_sample_rate = new_sample_rate\n        self._rng = rng\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Resamples the input audio to a target sample rate.\n\n        Note that this is an in-place transformation.\n\n        :param audio: Audio segment to add effects to.\n        :type audio: AudioSegment|SpeechSegment\n        \"\"\"\n        audio_segment.resample(self._new_sample_rate)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/shift_perturb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the volume perturb augmentation model.\"\"\"\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass ShiftPerturbAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding random shift perturbation.\n    \n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param min_shift_ms: Minimal shift in milliseconds.\n    :type min_shift_ms: float\n    :param max_shift_ms: Maximal shift in milliseconds.\n    :type max_shift_ms: float\n    \"\"\"\n\n    def __init__(self, rng, min_shift_ms, max_shift_ms):\n        self._min_shift_ms = min_shift_ms\n        self._max_shift_ms = max_shift_ms\n        self._rng = rng\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Shift audio.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        shift_ms = self._rng.uniform(self._min_shift_ms, self._max_shift_ms)\n        audio_segment.shift(shift_ms)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/spec_augment.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the volume perturb augmentation model.\"\"\"\nimport random\n\nimport numpy as np\nfrom PIL import Image\n\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\nclass SpecAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for Time warping, Frequency masking, Time masking.\n\n    SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition\n        https://arxiv.org/abs/1904.08779\n\n    SpecAugment on Large Scale Datasets\n        https://arxiv.org/abs/1912.05533\n\n    \"\"\"\n\n    def __init__(self,\n                 rng,\n                 F,\n                 T,\n                 n_freq_masks,\n                 n_time_masks,\n                 p=1.0,\n                 W=40,\n                 adaptive_number_ratio=0,\n                 adaptive_size_ratio=0,\n                 max_n_time_masks=20,\n                 replace_with_zero=True,\n                 warp_mode='PIL'):\n        \"\"\"SpecAugment class.\n        Args:\n            rng (random.Random): random generator object.\n            F (int): parameter for frequency masking\n            T (int): parameter for time masking\n            n_freq_masks (int): number of frequency masks\n            n_time_masks (int): number of time masks\n            p (float): parameter for upperbound of the time mask\n            W (int): parameter for time warping\n            adaptive_number_ratio (float): adaptive multiplicity ratio for time masking\n            adaptive_size_ratio (float): adaptive size ratio for time masking\n            max_n_time_masks (int): maximum number of time masking\n            replace_with_zero (bool): pad zero on mask if true else use mean\n            warp_mode (str):  \"PIL\" (default, fast, not differentiable)\n                 or \"sparse_image_warp\" (slow, differentiable)\n        \"\"\"\n        super().__init__()\n        self._rng = rng\n        self.inplace = True\n        self.replace_with_zero = replace_with_zero\n\n        self.mode = warp_mode\n        self.W = W\n        self.F = F\n        self.T = T\n        self.n_freq_masks = n_freq_masks\n        self.n_time_masks = n_time_masks\n        self.p = p\n\n        # adaptive SpecAugment\n        self.adaptive_number_ratio = adaptive_number_ratio\n        self.adaptive_size_ratio = adaptive_size_ratio\n        self.max_n_time_masks = max_n_time_masks\n\n        if adaptive_number_ratio > 0:\n            self.n_time_masks = 0\n            logger.info('n_time_masks is set ot zero for adaptive SpecAugment.')\n        if adaptive_size_ratio > 0:\n            self.T = 0\n            logger.info('T is set to zero for adaptive SpecAugment.')\n\n        self._freq_mask = None\n        self._time_mask = None\n\n    def librispeech_basic(self):\n        self.W = 80\n        self.F = 27\n        self.T = 100\n        self.n_freq_masks = 1\n        self.n_time_masks = 1\n        self.p = 1.0\n\n    def librispeech_double(self):\n        self.W = 80\n        self.F = 27\n        self.T = 100\n        self.n_freq_masks = 2\n        self.n_time_masks = 2\n        self.p = 1.0\n\n    def switchboard_mild(self):\n        self.W = 40\n        self.F = 15\n        self.T = 70\n        self.n_freq_masks = 2\n        self.n_time_masks = 2\n        self.p = 0.2\n\n    def switchboard_strong(self):\n        self.W = 40\n        self.F = 27\n        self.T = 70\n        self.n_freq_masks = 2\n        self.n_time_masks = 2\n        self.p = 0.2\n\n    @property\n    def freq_mask(self):\n        return self._freq_mask\n\n    @property\n    def time_mask(self):\n        return self._time_mask\n\n    def __repr__(self):\n        return f\"specaug: F-{self.F}, T-{self.T}, F-n-{self.n_freq_masks}, T-n-{self.n_time_masks}\"\n\n    def time_warp(self, x, mode='PIL'):\n        \"\"\"time warp for spec augment\n        move random center frame by the random width ~ uniform(-window, window)\n\n        Args:\n            x (np.ndarray): spectrogram (time, freq)\n            mode (str): PIL or sparse_image_warp\n\n        Raises:\n            NotImplementedError: [description]\n            NotImplementedError: [description]\n\n        Returns:\n            np.ndarray: time warped spectrogram (time, freq)\n        \"\"\"\n        window = max_time_warp = self.W\n        if window == 0:\n            return x\n\n        if mode == \"PIL\":\n            t = x.shape[0]\n            if t - window <= window:\n                return x\n            # NOTE: randrange(a, b) emits a, a + 1, ..., b - 1\n            center = random.randrange(window, t - window)\n            warped = random.randrange(center - window, center +\n                                      window) + 1  # 1 ... t - 1\n\n            left = Image.fromarray(x[:center]).resize((x.shape[1], warped),\n                                                      Image.BICUBIC)\n            right = Image.fromarray(x[center:]).resize((x.shape[1], t - warped),\n                                                       Image.BICUBIC)\n            if self.inplace:\n                x[:warped] = left\n                x[warped:] = right\n                return x\n            return np.concatenate((left, right), 0)\n        elif mode == \"sparse_image_warp\":\n            raise NotImplementedError('sparse_image_warp')\n        else:\n            raise NotImplementedError(\n                \"unknown resize mode: \" + mode +\n                \", choose one from (PIL, sparse_image_warp).\")\n\n    def mask_freq(self, x, replace_with_zero=False):\n        \"\"\"freq mask\n\n        Args:\n            x (np.ndarray): spectrogram (time, freq)\n            replace_with_zero (bool, optional): Defaults to False.\n\n        Returns:\n            np.ndarray: freq mask spectrogram (time, freq)\n        \"\"\"\n        n_bins = x.shape[1]\n        for i in range(0, self.n_freq_masks):\n            f = int(self._rng.uniform(low=0, high=self.F))\n            f_0 = int(self._rng.uniform(low=0, high=n_bins - f))\n            assert f_0 <= f_0 + f\n            if replace_with_zero:\n                x[:, f_0:f_0 + f] = 0\n            else:\n                x[:, f_0:f_0 + f] = x.mean()\n            self._freq_mask = (f_0, f_0 + f)\n        return x\n\n    def mask_time(self, x, replace_with_zero=False):\n        \"\"\"time mask\n\n        Args:\n            x (np.ndarray): spectrogram (time, freq)\n            replace_with_zero (bool, optional): Defaults to False.\n\n        Returns:\n            np.ndarray: time mask spectrogram (time, freq)\n        \"\"\"\n        n_frames = x.shape[0]\n\n        if self.adaptive_number_ratio > 0:\n            n_masks = int(n_frames * self.adaptive_number_ratio)\n            n_masks = min(n_masks, self.max_n_time_masks)\n        else:\n            n_masks = self.n_time_masks\n\n        if self.adaptive_size_ratio > 0:\n            T = self.adaptive_size_ratio * n_frames\n        else:\n            T = self.T\n\n        for i in range(n_masks):\n            t = int(self._rng.uniform(low=0, high=T))\n            t = min(t, int(n_frames * self.p))\n            t_0 = int(self._rng.uniform(low=0, high=n_frames - t))\n            assert t_0 <= t_0 + t\n            if replace_with_zero:\n                x[t_0:t_0 + t, :] = 0\n            else:\n                x[t_0:t_0 + t, :] = x.mean()\n            self._time_mask = (t_0, t_0 + t)\n        return x\n\n    def __call__(self, x, train=True):\n        if not train:\n            return x\n        return self.transform_feature(x)\n\n    def transform_feature(self, x: np.ndarray):\n        \"\"\"\n        Args:\n            x (np.ndarray): `[T, F]`\n        Returns:\n            x (np.ndarray): `[T, F]`\n        \"\"\"\n        assert isinstance(x, np.ndarray)\n        assert x.ndim == 2\n        x = self.time_warp(x, self.mode)\n        x = self.mask_freq(x, self.replace_with_zero)\n        x = self.mask_time(x, self.replace_with_zero)\n        return x\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/speed_perturb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contain the speech perturbation augmentation model.\"\"\"\nimport numpy as np\n\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass SpeedPerturbAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding speed perturbation.\"\"\"\n\n    def __init__(self, rng, min_speed_rate=0.9, max_speed_rate=1.1,\n                 num_rates=3):\n        \"\"\"speed perturbation.\n        \n        The speed perturbation in kaldi uses sox-speed instead of sox-tempo,\n        and sox-speed just to resample the input,\n        i.e pitch and tempo are changed both.\n\n        \"Why use speed option instead of tempo -s in SoX for speed perturbation\"\n        https://groups.google.com/forum/#!topic/kaldi-help/8OOG7eE4sZ8\n    \n        Sox speed:\n        https://pysox.readthedocs.io/en/latest/api.html#sox.transform.Transformer\n        \n        See reference paper here:\n        http://www.danielpovey.com/files/2015_interspeech_augmentation.pdf\n        \n        Espnet:\n        https://espnet.github.io/espnet/_modules/espnet/transform/perturb.html\n        \n        Nemo:\n        https://github.com/NVIDIA/NeMo/blob/main/nemo/collections/asr/parts/perturb.py#L92\n\n        Args:\n            rng (random.Random): Random generator object.\n            min_speed_rate (float): Lower bound of new speed rate to sample and should\n                not be smaller than 0.9.\n            max_speed_rate (float): Upper bound of new speed rate to sample and should\n                not be larger than 1.1.\n            num_rates (int, optional): Number of discrete rates to allow. \n                Can be a positive or negative integer. Defaults to 3.\n                If a positive integer greater than 0 is provided, the range of\n                speed rates will be discretized into `num_rates` values.\n                If a negative integer or 0 is provided, the full range of speed rates\n                will be sampled uniformly.\n                Note: If a positive integer is provided and the resultant discretized\n                range of rates contains the value '1.0', then those samples with rate=1.0,\n                will not be augmented at all and simply skipped. This is to unnecessary\n                augmentation and increase computation time. Effective augmentation chance\n                in such a case is = `prob * (num_rates - 1 / num_rates) * 100`% chance\n                where `prob` is the global probability of a sample being augmented.\n\n        Raises:\n            ValueError: when speed_rate error\n        \"\"\"\n        if min_speed_rate < 0.9:\n            raise ValueError(\n                \"Sampling speed below 0.9 can cause unnatural effects\")\n        if max_speed_rate > 1.1:\n            raise ValueError(\n                \"Sampling speed above 1.1 can cause unnatural effects\")\n        self._min_rate = min_speed_rate\n        self._max_rate = max_speed_rate\n        self._rng = rng\n        self._num_rates = num_rates\n        if num_rates > 0:\n            self._rates = np.linspace(\n                self._min_rate, self._max_rate, self._num_rates, endpoint=True)\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Sample a new speed rate from the given range and\n        changes the speed of the given audio clip.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegment|SpeechSegment\n        \"\"\"\n        if self._num_rates < 0:\n            speed_rate = self._rng.uniform(self._min_rate, self._max_rate)\n        else:\n            speed_rate = self._rng.choice(self._rates)\n\n        # Skip perturbation in case of identity speed rate\n        if speed_rate == 1.0:\n            return\n\n        audio_segment.change_speed(speed_rate)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/augmentor/volume_perturb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the volume perturb augmentation model.\"\"\"\nfrom paddlespeech.s2t.frontend.augmentor.base import AugmentorBase\n\n\nclass VolumePerturbAugmentor(AugmentorBase):\n    \"\"\"Augmentation model for adding random volume perturbation.\n    \n    This is used for multi-loudness training of PCEN. See\n\n    https://arxiv.org/pdf/1607.05666v1.pdf\n\n    for more details.\n\n    :param rng: Random generator object.\n    :type rng: random.Random\n    :param min_gain_dBFS: Minimal gain in dBFS.\n    :type min_gain_dBFS: float\n    :param max_gain_dBFS: Maximal gain in dBFS.\n    :type max_gain_dBFS: float\n    \"\"\"\n\n    def __init__(self, rng, min_gain_dBFS, max_gain_dBFS):\n        self._min_gain_dBFS = min_gain_dBFS\n        self._max_gain_dBFS = max_gain_dBFS\n        self._rng = rng\n\n    def __call__(self, x, uttid=None, train=True):\n        if not train:\n            return x\n        self.transform_audio(x)\n        return x\n\n    def transform_audio(self, audio_segment):\n        \"\"\"Change audio loadness.\n\n        Note that this is an in-place transformation.\n\n        :param audio_segment: Audio segment to add effects to.\n        :type audio_segment: AudioSegmenet|SpeechSegment\n        \"\"\"\n        gain = self._rng.uniform(self._min_gain_dBFS, self._max_gain_dBFS)\n        audio_segment.gain_db(gain)\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/featurizer/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .audio_featurizer import AudioFeaturizer  #noqa: F401\nfrom .speech_featurizer import SpeechFeaturizer\nfrom .text_featurizer import TextFeaturizer\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/featurizer/audio_featurizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the audio featurizer class.\"\"\"\nimport numpy as np\nimport paddle\nfrom python_speech_features import delta\nfrom python_speech_features import mfcc\n\nimport paddlespeech.audio.compliance.kaldi as kaldi\n\n\nclass AudioFeaturizer():\n    \"\"\"Audio featurizer, for extracting features from audio contents of\n    AudioSegment or SpeechSegment.\n\n    Currently, it supports feature types of linear spectrogram and mfcc.\n\n    :param spectrum_type: Specgram feature type. Options: 'linear'.\n    :type spectrum_type: str\n    :param stride_ms: Striding size (in milliseconds) for generating frames.\n    :type stride_ms: float\n    :param window_ms: Window size (in milliseconds) for generating frames.\n    :type window_ms: float\n    :param max_freq: When spectrum_type is 'linear', only FFT bins\n                     corresponding to frequencies between [0, max_freq] are\n                     returned; when spectrum_type is 'mfcc', max_feq is the\n                     highest band edge of mel filters.\n    :types max_freq: None|float\n    :param target_sample_rate: Audio are resampled (if upsampling or\n                               downsampling is allowed) to this before\n                               extracting spectrogram features.\n    :type target_sample_rate: float\n    :param use_dB_normalization: Whether to normalize the audio to a certain\n                                 decibels before extracting the features.\n    :type use_dB_normalization: bool\n    :param target_dB: Target audio decibels for normalization.\n    :type target_dB: float\n    \"\"\"\n\n    def __init__(self,\n                 spectrum_type: str='linear',\n                 feat_dim: int=None,\n                 delta_delta: bool=False,\n                 stride_ms=10.0,\n                 window_ms=20.0,\n                 n_fft=None,\n                 max_freq=None,\n                 target_sample_rate=16000,\n                 use_dB_normalization=True,\n                 target_dB=-20,\n                 dither=1.0):\n        self._spectrum_type = spectrum_type\n        # mfcc and fbank using `feat_dim`\n        self._feat_dim = feat_dim\n        # mfcc and fbank using `delta-delta`\n        self._delta_delta = delta_delta\n        self._stride_ms = stride_ms\n        self._window_ms = window_ms\n        self._max_freq = max_freq\n        self._target_sample_rate = target_sample_rate\n        self._use_dB_normalization = use_dB_normalization\n        self._target_dB = target_dB\n        self._fft_point = n_fft\n        self._dither = dither\n\n    def featurize(self,\n                  audio_segment,\n                  allow_downsampling=True,\n                  allow_upsampling=True):\n        \"\"\"Extract audio features from AudioSegment or SpeechSegment.\n\n        :param audio_segment: Audio/speech segment to extract features from.\n        :type audio_segment: AudioSegment|SpeechSegment\n        :param allow_downsampling: Whether to allow audio downsampling before\n                                   featurizing.\n        :type allow_downsampling: bool\n        :param allow_upsampling: Whether to allow audio upsampling before\n                                 featurizing.\n        :type allow_upsampling: bool\n        :return: Spectrogram audio feature in 2darray.\n        :rtype: ndarray\n        :raises ValueError: If audio sample rate is not supported.\n        \"\"\"\n        # upsampling or downsampling\n        if ((audio_segment.sample_rate > self._target_sample_rate and\n             allow_downsampling) or\n            (audio_segment.sample_rate < self._target_sample_rate and\n             allow_upsampling)):\n            audio_segment.resample(self._target_sample_rate)\n        if audio_segment.sample_rate != self._target_sample_rate:\n            raise ValueError(\"Audio sample rate is not supported. \"\n                             \"Turn allow_downsampling or allow up_sampling on.\")\n        # decibel normalization\n        if self._use_dB_normalization:\n            audio_segment.normalize(target_db=self._target_dB)\n        # extract spectrogram\n        return self._compute_specgram(audio_segment)\n\n    @property\n    def stride_ms(self):\n        return self._stride_ms\n\n    @property\n    def feature_size(self):\n        \"\"\"audio feature size\"\"\"\n        feat_dim = 0\n        if self._spectrum_type == 'linear':\n            fft_point = self._window_ms if self._fft_point is None else self._fft_point\n            feat_dim = int(fft_point * (self._target_sample_rate / 1000) / 2 +\n                           1)\n        elif self._spectrum_type == 'mfcc':\n            # mfcc, delta, delta-delta\n            feat_dim = int(self._feat_dim *\n                           3) if self._delta_delta else int(self._feat_dim)\n        elif self._spectrum_type == 'fbank':\n            # fbank, delta, delta-delta\n            feat_dim = int(self._feat_dim *\n                           3) if self._delta_delta else int(self._feat_dim)\n        else:\n            raise ValueError(\"Unknown spectrum_type %s. \"\n                             \"Supported values: linear.\" % self._spectrum_type)\n        return feat_dim\n\n    def _compute_specgram(self, audio_segment):\n        \"\"\"Extract various audio features.\"\"\"\n        sample_rate = audio_segment.sample_rate\n        if self._spectrum_type == 'linear':\n            samples = audio_segment.samples\n            return self._compute_linear_specgram(\n                samples,\n                sample_rate,\n                stride_ms=self._stride_ms,\n                window_ms=self._window_ms,\n                max_freq=self._max_freq)\n        elif self._spectrum_type == 'mfcc':\n            samples = audio_segment.to('int16')\n            return self._compute_mfcc(\n                samples,\n                sample_rate,\n                feat_dim=self._feat_dim,\n                stride_ms=self._stride_ms,\n                window_ms=self._window_ms,\n                max_freq=self._max_freq,\n                dither=self._dither,\n                delta_delta=self._delta_delta)\n        elif self._spectrum_type == 'fbank':\n            samples = audio_segment.to('int16')\n            return self._compute_fbank(\n                samples,\n                sample_rate,\n                feat_dim=self._feat_dim,\n                stride_ms=self._stride_ms,\n                window_ms=self._window_ms,\n                max_freq=self._max_freq,\n                dither=self._dither,\n                delta_delta=self._delta_delta)\n        else:\n            raise ValueError(\"Unknown spectrum_type %s. \"\n                             \"Supported values: linear.\" % self._spectrum_type)\n\n    def _specgram_real(self, samples, window_size, stride_size, sample_rate):\n        \"\"\"Compute the spectrogram for samples from a real signal.\"\"\"\n        # extract strided windows\n        truncate_size = (len(samples) - window_size) % stride_size\n        samples = samples[:len(samples) - truncate_size]\n        nshape = (window_size, (len(samples) - window_size) // stride_size + 1)\n        nstrides = (samples.strides[0], samples.strides[0] * stride_size)\n        windows = np.lib.stride_tricks.as_strided(\n            samples, shape=nshape, strides=nstrides)\n        assert np.all(\n            windows[:, 1] == samples[stride_size:(stride_size + window_size)])\n        # window weighting, squared Fast Fourier Transform (fft), scaling\n        weighting = np.hanning(window_size)[:, None]\n        # https://numpy.org/doc/stable/reference/generated/numpy.fft.rfft.html\n        fft = np.fft.rfft(windows * weighting, n=None, axis=0)\n        fft = np.absolute(fft)\n        fft = fft**2\n        scale = np.sum(weighting**2) * sample_rate\n        fft[1:-1, :] *= (2.0 / scale)\n        fft[(0, -1), :] /= scale\n        # prepare fft frequency list\n        freqs = float(sample_rate) / window_size * np.arange(fft.shape[0])\n        return fft, freqs\n\n    def _compute_linear_specgram(self,\n                                 samples,\n                                 sample_rate,\n                                 stride_ms=10.0,\n                                 window_ms=20.0,\n                                 max_freq=None,\n                                 eps=1e-14):\n        \"\"\"Compute the linear spectrogram from FFT energy.\n\n        Args:\n            samples ([type]): [description]\n            sample_rate ([type]): [description]\n            stride_ms (float, optional): [description]. Defaults to 10.0.\n            window_ms (float, optional): [description]. Defaults to 20.0.\n            max_freq ([type], optional): [description]. Defaults to None.\n            eps ([type], optional): [description]. Defaults to 1e-14.\n\n        Raises:\n            ValueError: [description]\n            ValueError: [description]\n\n        Returns:\n            np.ndarray: log spectrogram, (time, freq)\n        \"\"\"\n        if max_freq is None:\n            max_freq = sample_rate / 2\n        if max_freq > sample_rate / 2:\n            raise ValueError(\"max_freq must not be greater than half of \"\n                             \"sample rate.\")\n        if stride_ms > window_ms:\n            raise ValueError(\"Stride size must not be greater than \"\n                             \"window size.\")\n        stride_size = int(0.001 * sample_rate * stride_ms)\n        window_size = int(0.001 * sample_rate * window_ms)\n        specgram, freqs = self._specgram_real(\n            samples,\n            window_size=window_size,\n            stride_size=stride_size,\n            sample_rate=sample_rate)\n        ind = np.where(freqs <= max_freq)[0][-1] + 1\n        # (freq, time)\n        spec = np.log(specgram[:ind, :] + eps)\n        return np.transpose(spec)\n\n    def _concat_delta_delta(self, feat):\n        \"\"\"append delat, delta-delta feature.\n\n        Args:\n            feat (np.ndarray): (T, D)\n\n        Returns:\n            np.ndarray: feat with delta-delta, (T, 3*D)\n        \"\"\"\n        # Deltas\n        d_feat = delta(feat, 2)\n        # Deltas-Deltas\n        dd_feat = delta(feat, 2)\n        # concat above three features\n        concat_feat = np.concatenate((feat, d_feat, dd_feat), axis=1)\n        return concat_feat\n\n    def _compute_mfcc(self,\n                      samples,\n                      sample_rate,\n                      feat_dim=13,\n                      stride_ms=10.0,\n                      window_ms=25.0,\n                      max_freq=None,\n                      dither=1.0,\n                      delta_delta=True):\n        \"\"\"Compute mfcc from samples.\n\n        Args:\n            samples (np.ndarray, np.int16): the audio signal from which to compute features.\n            sample_rate (float): the sample rate of the signal we are working with, in Hz.\n            feat_dim (int): the number of cepstrum to return, default 13.\n            stride_ms (float, optional): stride length in ms. Defaults to 10.0.\n            window_ms (float, optional): window length in ms. Defaults to 25.0.\n            max_freq ([type], optional): highest band edge of mel filters. In Hz, default is samplerate/2. Defaults to None.\n            delta_delta (bool, optional): Whether with delta delta. Defaults to False.\n\n        Raises:\n            ValueError: max_freq > samplerate/2\n            ValueError: stride_ms > window_ms\n\n        Returns:\n            np.ndarray: mfcc feature, (D, T).\n        \"\"\"\n        if max_freq is None:\n            max_freq = sample_rate / 2\n        if max_freq > sample_rate / 2:\n            raise ValueError(\"max_freq must not be greater than half of \"\n                             \"sample rate.\")\n        if stride_ms > window_ms:\n            raise ValueError(\"Stride size must not be greater than \"\n                             \"window size.\")\n        # compute the 13 cepstral coefficients, and the first one is replaced\n        # by log(frame energy), (T, D)\n        mfcc_feat = mfcc(\n            signal=samples,\n            samplerate=sample_rate,\n            winlen=0.001 * window_ms,\n            winstep=0.001 * stride_ms,\n            numcep=feat_dim,\n            nfilt=23,\n            nfft=512,\n            lowfreq=20,\n            highfreq=max_freq,\n            dither=dither,\n            remove_dc_offset=True,\n            preemph=0.97,\n            ceplifter=22,\n            useEnergy=True,\n            winfunc='povey')\n        if delta_delta:\n            mfcc_feat = self._concat_delta_delta(mfcc_feat)\n        return mfcc_feat\n\n    def _compute_fbank(self,\n                       samples,\n                       sample_rate,\n                       feat_dim=40,\n                       stride_ms=10.0,\n                       window_ms=25.0,\n                       max_freq=None,\n                       dither=1.0,\n                       delta_delta=False):\n        \"\"\"Compute logfbank from samples.\n        \n        Args:\n            samples (np.ndarray, np.int16): the audio signal from which to compute features. Should be an N*1 array\n            sample_rate (float): the sample rate of the signal we are working with, in Hz.\n            feat_dim (int): the number of cepstrum to return, default 13.\n            stride_ms (float, optional): stride length in ms. Defaults to 10.0.\n            window_ms (float, optional): window length in ms. Defaults to 20.0.\n            max_freq (float, optional): highest band edge of mel filters. In Hz, default is samplerate/2. Defaults to None.\n            delta_delta (bool, optional): Whether with delta delta. Defaults to False.\n\n        Raises:\n            ValueError: max_freq > samplerate/2\n            ValueError: stride_ms > window_ms\n\n        Returns:\n            np.ndarray: mfcc feature, (D, T).\n        \"\"\"\n        if max_freq is None:\n            max_freq = sample_rate / 2\n        if max_freq > sample_rate / 2:\n            raise ValueError(\"max_freq must not be greater than half of \"\n                             \"sample rate.\")\n        if stride_ms > window_ms:\n            raise ValueError(\"Stride size must not be greater than \"\n                             \"window size.\")\n        # (T, D)\n        waveform = paddle.to_tensor(\n            np.expand_dims(samples, 0), dtype=paddle.float32)\n        mat = kaldi.fbank(\n            waveform,\n            n_mels=feat_dim,\n            frame_length=window_ms,  # default : 25\n            frame_shift=stride_ms,  # default : 10\n            dither=dither,\n            energy_floor=0.0,\n            sr=sample_rate)\n        fbank_feat = np.squeeze(mat.numpy())\n        if delta_delta:\n            fbank_feat = self._concat_delta_delta(fbank_feat)\n        return fbank_feat\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/featurizer/speech_featurizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the speech featurizer class.\"\"\"\nfrom paddlespeech.s2t.frontend.featurizer.audio_featurizer import AudioFeaturizer\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\n\n\nclass SpeechFeaturizer():\n    \"\"\"Speech and Text feature extraction.\n    \"\"\"\n\n    def __init__(self,\n                 unit_type,\n                 vocab_filepath,\n                 spm_model_prefix=None,\n                 spectrum_type='linear',\n                 feat_dim=None,\n                 delta_delta=False,\n                 stride_ms=10.0,\n                 window_ms=20.0,\n                 n_fft=None,\n                 max_freq=None,\n                 target_sample_rate=16000,\n                 use_dB_normalization=True,\n                 target_dB=-20,\n                 dither=1.0,\n                 maskctc=False):\n        self.stride_ms = stride_ms\n        self.window_ms = window_ms\n\n        self.audio_feature = AudioFeaturizer(\n            spectrum_type=spectrum_type,\n            feat_dim=feat_dim,\n            delta_delta=delta_delta,\n            stride_ms=stride_ms,\n            window_ms=window_ms,\n            n_fft=n_fft,\n            max_freq=max_freq,\n            target_sample_rate=target_sample_rate,\n            use_dB_normalization=use_dB_normalization,\n            target_dB=target_dB,\n            dither=dither)\n        self.feature_size = self.audio_feature.feature_size\n\n        self.text_feature = TextFeaturizer(\n            unit_type=unit_type,\n            vocab=vocab_filepath,\n            spm_model_prefix=spm_model_prefix,\n            maskctc=maskctc)\n        self.vocab_size = self.text_feature.vocab_size\n\n    def featurize(self, speech_segment, keep_transcription_text):\n        \"\"\"Extract features for speech segment.\n\n        1. For audio parts, extract the audio features.\n        2. For transcript parts, keep the original text or convert text string\n           to a list of token indices in char-level.\n\n        Args:\n            speech_segment (SpeechSegment): Speech segment to extract features from.\n            keep_transcription_text (bool): True, keep transcript text, False, token ids\n\n        Returns:\n            tuple: 1) spectrogram audio feature in 2darray, 2) list oftoken indices.\n        \"\"\"\n        spec_feature = self.audio_feature.featurize(speech_segment)\n\n        if keep_transcription_text:\n            return spec_feature, speech_segment.transcript\n\n        if speech_segment.has_token:\n            text_ids = speech_segment.token_ids\n        else:\n            text_ids = self.text_feature.featurize(speech_segment.transcript)\n        return spec_feature, text_ids\n\n    def text_featurize(self, text, keep_transcription_text):\n        \"\"\"Extract features for speech segment.\n\n        1. For audio parts, extract the audio features.\n        2. For transcript parts, keep the original text or convert text string\n           to a list of token indices in char-level.\n\n        Args:\n            text (str): text.\n            keep_transcription_text (bool): True, keep transcript text, False, token ids\n\n        Returns:\n            (str|List[int]): text, or list of token indices.\n        \"\"\"\n        if keep_transcription_text:\n            return text\n\n        text_ids = self.text_feature.featurize(text)\n        return text_ids\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/featurizer/text_featurizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the text featurizer class.\"\"\"\nfrom pprint import pformat\nfrom typing import Union\n\nimport sentencepiece as spm\n\nfrom ..utility import BLANK\nfrom ..utility import EOS\nfrom ..utility import load_dict\nfrom ..utility import MASKCTC\nfrom ..utility import SOS\nfrom ..utility import SPACE\nfrom ..utility import UNK\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"TextFeaturizer\"]\n\n\nclass TextFeaturizer():\n    def __init__(self, unit_type, vocab, spm_model_prefix=None, maskctc=False):\n        \"\"\"Text featurizer, for processing or extracting features from text.\n\n        Currently, it supports char/word/sentence-piece level tokenizing and conversion into\n        a list of token indices. Note that the token indexing order follows the\n        given vocabulary file.\n\n        Args:\n            unit_type (str): unit type, e.g. char, word, spm\n            vocab Option[str, list]: Filepath to load vocabulary for token indices conversion, or vocab list.\n            spm_model_prefix (str, optional): spm model prefix. Defaults to None.\n        \"\"\"\n        assert unit_type in ('char', 'spm', 'word')\n        self.unit_type = unit_type\n        self.unk = UNK\n        self.maskctc = maskctc\n        self.vocab_path_or_list = vocab\n\n        if self.vocab_path_or_list:\n            self.vocab_dict, self._id2token, self.vocab_list, self.unk_id, self.eos_id, self.blank_id = self._load_vocabulary_from_file(\n                vocab, maskctc)\n            self.vocab_size = len(self.vocab_list)\n        else:\n            logger.warning(\n                \"TextFeaturizer: not have vocab file or vocab list. Only Tokenizer can use, can not convert to token idx\"\n            )\n\n        if unit_type == 'spm':\n            spm_model = spm_model_prefix + '.model'\n            self.sp = spm.SentencePieceProcessor()\n            self.sp.Load(spm_model)\n\n    def tokenize(self, text, replace_space=True):\n        \"\"\"tokenizer split text into text tokens\"\"\"\n        if self.unit_type == 'char':\n            tokens = self.char_tokenize(text, replace_space)\n        elif self.unit_type == 'word':\n            tokens = self.word_tokenize(text)\n        else:  # spm\n            tokens = self.spm_tokenize(text)\n        return tokens\n\n    def detokenize(self, tokens):\n        \"\"\"tokenizer convert text tokens back to text\"\"\"\n        if self.unit_type == 'char':\n            text = self.char_detokenize(tokens)\n        elif self.unit_type == 'word':\n            text = self.word_detokenize(tokens)\n        else:  # spm\n            text = self.spm_detokenize(tokens)\n        return text\n\n    def featurize(self, text):\n        \"\"\"Convert text string to a list of token indices.\n\n        Args:\n            text (str): Text to process.\n\n        Returns:\n            List[int]: List of token indices.\n        \"\"\"\n        assert self.vocab_path_or_list, \"toidx need vocab path or vocab list\"\n        tokens = self.tokenize(text)\n        ids = []\n        for token in tokens:\n            if token not in self.vocab_dict:\n                logger.debug(f\"Text Token: {token} -> {self.unk}\")\n                token = self.unk\n            ids.append(self.vocab_dict[token])\n        return ids\n\n    def defeaturize(self, idxs):\n        \"\"\"Convert a list of token indices to text string,\n        ignore index after eos_id.\n\n        Args:\n            idxs (List[int]): List of token indices.\n\n        Returns:\n            str: Text.\n        \"\"\"\n        assert self.vocab_path_or_list, \"toidx need vocab path or vocab list\"\n        tokens = []\n        # unwrap `idxs`` like `[[1,2,3]]`\n        if idxs and isinstance(idxs[0], (list, tuple)) and len(idxs) == 1:\n            idxs = idxs[0]\n\n        for idx in idxs:\n            if idx == self.eos_id:\n                break\n            tokens.append(self._id2token[idx])\n        text = self.detokenize(tokens)\n        return text\n\n    def char_tokenize(self, text, replace_space=True):\n        \"\"\"Character tokenizer.\n\n        Args:\n            text (str): text string.\n            replace_space (bool): False only used by build_vocab.py.\n\n        Returns:\n            List[str]: tokens.\n        \"\"\"\n        text = text.strip()\n        if replace_space:\n            tokens = [SPACE if item == \" \" else item for item in list(text)]\n        else:\n            tokens = list(text)\n        return tokens\n\n    def char_detokenize(self, tokens):\n        \"\"\"Character detokenizer.\n\n        Args:\n            tokens (List[str]): tokens.\n\n        Returns:\n           str: text string.\n        \"\"\"\n        tokens = [t.replace(SPACE, \" \") for t in tokens]\n        return \"\".join(tokens)\n\n    def word_tokenize(self, text):\n        \"\"\"Word tokenizer, separate by <space>.\"\"\"\n        return text.strip().split()\n\n    def word_detokenize(self, tokens):\n        \"\"\"Word detokenizer, separate by <space>.\"\"\"\n        return \" \".join(tokens)\n\n    def spm_tokenize(self, text):\n        \"\"\"spm tokenize.\n\n        Args:\n            text (str): text string.\n\n        Returns:\n            List[str]: sentence pieces str code\n        \"\"\"\n        stats = {\"num_empty\": 0, \"num_filtered\": 0}\n\n        def valid(line):\n            return True\n\n        def encode(l):\n            return self.sp.EncodeAsPieces(l)\n\n        def encode_line(line):\n            line = line.strip()\n            if len(line) > 0:\n                line = encode(line)\n                if valid(line):\n                    return line\n                else:\n                    stats[\"num_filtered\"] += 1\n            else:\n                stats[\"num_empty\"] += 1\n            return None\n\n        enc_line = encode_line(text)\n        return enc_line\n\n    def spm_detokenize(self, tokens, input_format='piece'):\n        \"\"\"spm detokenize.\n\n        Args:\n            ids (List[str]): tokens.\n\n        Returns:\n            str: text\n        \"\"\"\n        if input_format == \"piece\":\n\n            def decode(l):\n                return \"\".join(self.sp.DecodePieces(l))\n        elif input_format == \"id\":\n\n            def decode(l):\n                return \"\".join(self.sp.DecodeIds(l))\n\n        return decode(tokens)\n\n    def _load_vocabulary_from_file(self, vocab: Union[str, list],\n                                   maskctc: bool):\n        \"\"\"Load vocabulary from file.\"\"\"\n        if isinstance(vocab, list):\n            vocab_list = vocab\n        else:\n            vocab_list = load_dict(vocab, maskctc)\n        assert vocab_list is not None\n        logger.debug(f\"Vocab: {pformat(vocab_list)}\")\n\n        id2token = dict(\n            [(idx, token) for (idx, token) in enumerate(vocab_list)])\n        token2id = dict(\n            [(token, idx) for (idx, token) in enumerate(vocab_list)])\n\n        blank_id = vocab_list.index(BLANK) if BLANK in vocab_list else -1\n        maskctc_id = vocab_list.index(MASKCTC) if MASKCTC in vocab_list else -1\n        unk_id = vocab_list.index(UNK) if UNK in vocab_list else -1\n        eos_id = vocab_list.index(EOS) if EOS in vocab_list else -1\n        sos_id = vocab_list.index(SOS) if SOS in vocab_list else -1\n        space_id = vocab_list.index(SPACE) if SPACE in vocab_list else -1\n\n        logger.debug(f\"BLANK id: {blank_id}\")\n        logger.debug(f\"UNK id: {unk_id}\")\n        logger.debug(f\"EOS id: {eos_id}\")\n        logger.debug(f\"SOS id: {sos_id}\")\n        logger.debug(f\"SPACE id: {space_id}\")\n        logger.debug(f\"MASKCTC id: {maskctc_id}\")\n        return token2id, id2token, vocab_list, unk_id, eos_id, blank_id\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/normalizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains feature normalizers.\"\"\"\nimport json\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle.io import DataLoader\nfrom paddle.io import Dataset\n\nfrom paddlespeech.s2t.frontend.audio import AudioSegment\nfrom paddlespeech.s2t.frontend.utility import load_cmvn\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"FeatureNormalizer\"]\n\nlogger = Log(__name__).getlog()\n\n\n# https://github.com/PaddlePaddle/Paddle/pull/31481\nclass CollateFunc(object):\n    def __init__(self, feature_func):\n        self.feature_func = feature_func\n\n    def __call__(self, batch):\n        mean_stat = None\n        var_stat = None\n        number = 0\n        for item in batch:\n            audioseg = AudioSegment.from_file(item['feat'])\n            feat = self.feature_func(audioseg)  #(T, D)\n\n            sums = np.sum(feat, axis=0)\n            if mean_stat is None:\n                mean_stat = sums\n            else:\n                mean_stat += sums\n\n            square_sums = np.sum(np.square(feat), axis=0)\n            if var_stat is None:\n                var_stat = square_sums\n            else:\n                var_stat += square_sums\n\n            number += feat.shape[0]\n        return number, mean_stat, var_stat\n\n\nclass AudioDataset(Dataset):\n    def __init__(self, manifest_path, num_samples=-1, rng=None, random_seed=0):\n        self._rng = rng if rng else np.random.RandomState(random_seed)\n\n        with jsonlines.open(manifest_path, 'r') as reader:\n            manifest = list(reader)\n\n        if num_samples == -1:\n            sampled_manifest = manifest\n        else:\n            sampled_manifest = self._rng.choice(\n                manifest, num_samples, replace=False)\n        self.items = sampled_manifest\n\n    def __len__(self):\n        return len(self.items)\n\n    def __getitem__(self, idx):\n        return self.items[idx]\n\n\nclass FeatureNormalizer(object):\n    \"\"\"Feature normalizer. Normalize features to be of zero mean and unit\n    stddev.\n\n    if mean_std_filepath is provided (not None), the normalizer will directly\n    initilize from the file. Otherwise, both manifest_path and featurize_func\n    should be given for on-the-fly mean and stddev computing.\n\n    :param mean_std_filepath: File containing the pre-computed mean and stddev.\n    :type mean_std_filepath: None|str\n    :param manifest_path: Manifest of instances for computing mean and stddev.\n    :type meanifest_path: None|str\n    :param featurize_func: Function to extract features. It should be callable\n                           with ``featurize_func(audio_segment)``.\n    :type featurize_func: None|callable\n    :param num_samples: Number of random samples for computing mean and stddev.\n    :type num_samples: int\n    :param random_seed: Random seed for sampling instances.\n    :type random_seed: int\n    :raises ValueError: If both mean_std_filepath and manifest_path\n                        (or both mean_std_filepath and featurize_func) are None.\n    \"\"\"\n\n    def __init__(self,\n                 mean_std_filepath,\n                 manifest_path=None,\n                 featurize_func=None,\n                 num_samples=500,\n                 num_workers=0,\n                 random_seed=0):\n        if not mean_std_filepath:\n            if not (manifest_path and featurize_func):\n                raise ValueError(\"If mean_std_filepath is None, meanifest_path \"\n                                 \"and featurize_func should not be None.\")\n            self._rng = np.random.RandomState(random_seed)\n            self._compute_mean_std(manifest_path, featurize_func, num_samples,\n                                   num_workers)\n        else:\n            mean_std = mean_std_filepath\n            self._read_mean_std_from_file(mean_std)\n\n    def apply(self, features):\n        \"\"\"Normalize features to be of zero mean and unit stddev.\n\n        :param features: Input features to be normalized.\n        :type features: ndarray, shape (T, D)\n        :param eps:  added to stddev to provide numerical stablibity.\n        :type eps: float\n        :return: Normalized features.\n        :rtype: ndarray\n        \"\"\"\n        return (features - self._mean) * self._istd\n\n    def _read_mean_std_from_file(self, mean_std, eps=1e-20):\n        \"\"\"Load mean and std from file.\"\"\"\n        if isinstance(mean_std, list):\n            mean = mean_std[0]['cmvn_stats']['mean']\n            istd = mean_std[0]['cmvn_stats']['istd']\n        else:\n            filetype = mean_std.split(\".\")[-1]\n            mean, istd = load_cmvn(mean_std, filetype=filetype)\n        self._mean = np.expand_dims(mean, axis=0)\n        self._istd = np.expand_dims(istd, axis=0)\n\n    def write_to_file(self, filepath):\n        \"\"\"Write the mean and stddev to the file.\n\n        :param filepath: File to write mean and stddev.\n        :type filepath: str\n        \"\"\"\n        with open(filepath, 'w') as fout:\n            fout.write(json.dumps(self.cmvn_info))\n\n    def _compute_mean_std(self,\n                          manifest_path,\n                          featurize_func,\n                          num_samples,\n                          num_workers,\n                          batch_size=64,\n                          eps=1e-20):\n        \"\"\"Compute mean and std from randomly sampled instances.\"\"\"\n        paddle.set_device('cpu')\n\n        collate_func = CollateFunc(featurize_func)\n        dataset = AudioDataset(manifest_path, num_samples, self._rng)\n        data_loader = DataLoader(\n            dataset,\n            batch_size=batch_size,\n            shuffle=False,\n            num_workers=num_workers,\n            collate_fn=collate_func)\n\n        with paddle.no_grad():\n            all_mean_stat = None\n            all_var_stat = None\n            all_number = 0\n            wav_number = 0\n            for i, batch in enumerate(data_loader):\n                number, mean_stat, var_stat = batch\n                if i == 0:\n                    all_mean_stat = mean_stat\n                    all_var_stat = var_stat\n                else:\n                    all_mean_stat += mean_stat\n                    all_var_stat += var_stat\n                all_number += number\n                wav_number += batch_size\n\n                if wav_number % 1000 == 0:\n                    logger.info(\n                        f'process {wav_number} wavs,{all_number} frames.')\n\n        self.cmvn_info = {\n            'mean_stat': list(all_mean_stat.tolist()),\n            'var_stat': list(all_var_stat.tolist()),\n            'frame_num': all_number,\n        }\n\n        return self.cmvn_info\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/speech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains the speech segment class.\"\"\"\nimport numpy as np\n\nfrom paddlespeech.s2t.frontend.audio import AudioSegment\n\n\nclass SpeechSegment(AudioSegment):\n    \"\"\"Speech Segment with Text\n\n    Args:\n        AudioSegment (AudioSegment): Audio Segment\n    \"\"\"\n\n    def __init__(self,\n                 samples,\n                 sample_rate,\n                 transcript,\n                 tokens=None,\n                 token_ids=None):\n        \"\"\"Speech segment abstraction, a subclass of AudioSegment,\n            with an additional transcript.\n\n        Args:\n            samples (ndarray.float32): Audio samples [num_samples x num_channels].\n            sample_rate (int): Audio sample rate.\n            transcript (str): Transcript text for the speech.\n            tokens (List[str], optinal): Transcript tokens for the speech.\n            token_ids (List[int], optional): Transcript token ids for the speech.\n        \"\"\"\n        AudioSegment.__init__(self, samples, sample_rate)\n        self._transcript = transcript\n        # must init `tokens` with `token_ids` at the same time\n        self._tokens = tokens\n        self._token_ids = token_ids\n\n    def __eq__(self, other):\n        \"\"\"Return whether two objects are equal.\n\n        Returns:\n            bool: True, when equal to other\n        \"\"\"\n        if not AudioSegment.__eq__(self, other):\n            return False\n        if self._transcript != other._transcript:\n            return False\n        if self.has_token and other.has_token:\n            if self._tokens != other._tokens:\n                return False\n            if self._token_ids != other._token_ids:\n                return False\n        return True\n\n    def __ne__(self, other):\n        \"\"\"Return whether two objects are unequal.\"\"\"\n        return not self.__eq__(other)\n\n    @classmethod\n    def from_file(cls,\n                  filepath,\n                  transcript,\n                  tokens=None,\n                  token_ids=None,\n                  infos=None):\n        \"\"\"Create speech segment from audio file and corresponding transcript.\n\n        Args:\n            filepath (str|file): Filepath or file object to audio file.\n            transcript (str): Transcript text for the speech.\n            tokens (List[str], optional): text tokens. Defaults to None.\n            token_ids (List[int], optional): text token ids. Defaults to None.\n            infos (TarLocalData, optional): tar2obj and tar2infos. Defaults to None.\n\n        Returns:\n            SpeechSegment: Speech segment instance.\n        \"\"\"\n        audio = AudioSegment.from_file(filepath, infos)\n        return cls(audio.samples, audio.sample_rate, transcript, tokens,\n                   token_ids)\n\n    @classmethod\n    def from_bytes(cls, bytes, transcript, tokens=None, token_ids=None):\n        \"\"\"Create speech segment from a byte string and corresponding\n\n        Args:\n            filepath (str|file): Filepath or file object to audio file.\n            transcript (str): Transcript text for the speech.\n            tokens (List[str], optional): text tokens. Defaults to None.\n            token_ids (List[int], optional): text token ids. Defaults to None.\n\n        Returns:\n            SpeechSegment: Speech segment instance.\n        \"\"\"\n        audio = AudioSegment.from_bytes(bytes)\n        return cls(audio.samples, audio.sample_rate, transcript, tokens,\n                   token_ids)\n\n    @classmethod\n    def from_pcm(cls,\n                 samples,\n                 sample_rate,\n                 transcript,\n                 tokens=None,\n                 token_ids=None):\n        \"\"\"Create speech segment from pcm on online mode \n        Args:\n            samples (numpy.ndarray): Audio samples [num_samples x num_channels].\n            sample_rate (int): Audio sample rate.\n            transcript (str): Transcript text for the speech.\n            tokens (List[str], optional): text tokens. Defaults to None.\n            token_ids (List[int], optional): text token ids. Defaults to None.\n        Returns: \n            SpeechSegment: Speech segment instance.\n        \"\"\"\n        audio = AudioSegment.from_pcm(samples, sample_rate)\n        return cls(audio.samples, audio.sample_rate, transcript, tokens,\n                   token_ids)\n\n    @classmethod\n    def concatenate(cls, *segments):\n        \"\"\"Concatenate an arbitrary number of speech segments together, both\n        audio and transcript will be concatenated.\n\n        :param *segments: Input speech segments to be concatenated.\n        :type *segments: tuple of SpeechSegment\n        :return: Speech segment instance.\n        :rtype: SpeechSegment\n        :raises ValueError: If the number of segments is zero, or if the \n                            sample_rate of any two segments does not match.\n        :raises TypeError: If any segment is not SpeechSegment instance.\n        \"\"\"\n        if len(segments) == 0:\n            raise ValueError(\"No speech segments are given to concatenate.\")\n        sample_rate = segments[0]._sample_rate\n        transcripts = \"\"\n        tokens = []\n        token_ids = []\n        for seg in segments:\n            if sample_rate != seg._sample_rate:\n                raise ValueError(\"Can't concatenate segments with \"\n                                 \"different sample rates\")\n            if type(seg) is not cls:\n                raise TypeError(\"Only speech segments of the same type \"\n                                \"instance can be concatenated.\")\n            transcripts += seg._transcript\n            if self.has_token:\n                tokens += seg._tokens\n                token_ids += seg._token_ids\n        samples = np.concatenate([seg.samples for seg in segments])\n        return cls(samples, sample_rate, transcripts, tokens, token_ids)\n\n    @classmethod\n    def slice_from_file(cls,\n                        filepath,\n                        transcript,\n                        tokens=None,\n                        token_ids=None,\n                        start=None,\n                        end=None):\n        \"\"\"Loads a small section of an speech without having to load\n        the entire file into the memory which can be incredibly wasteful.\n\n        :param filepath: Filepath or file object to audio file.\n        :type filepath: str|file\n        :param start: Start time in seconds. If start is negative, it wraps\n                      around from the end. If not provided, this function \n                      reads from the very beginning.\n        :type start: float\n        :param end: End time in seconds. If end is negative, it wraps around\n                    from the end. If not provided, the default behvaior is\n                    to read to the end of the file.\n        :type end: float\n        :param transcript: Transcript text for the speech. if not provided, \n                           the defaults is an empty string.\n        :type transript: str\n        :return: SpeechSegment instance of the specified slice of the input\n                 speech file.\n        :rtype: SpeechSegment\n        \"\"\"\n        audio = AudioSegment.slice_from_file(filepath, start, end)\n        return cls(audio.samples, audio.sample_rate, transcript, tokens,\n                   token_ids)\n\n    @classmethod\n    def make_silence(cls, duration, sample_rate):\n        \"\"\"Creates a silent speech segment of the given duration and\n        sample rate, transcript will be an empty string.\n\n        Args:\n            duration (float): Length of silence in seconds.\n            sample_rate (float): Sample rate.\n\n        Returns:\n            SpeechSegment: Silence of the given duration.\n        \"\"\"\n        audio = AudioSegment.make_silence(duration, sample_rate)\n        return cls(audio.samples, audio.sample_rate, \"\")\n\n    @property\n    def has_token(self):\n        if self._tokens and self._token_ids:\n            return True\n        return False\n\n    @property\n    def transcript(self):\n        \"\"\"Return the transcript text.\n\n        Returns:\n            str: Transcript text for the speech.\n        \"\"\"\n\n        return self._transcript\n\n    @property\n    def tokens(self):\n        \"\"\"Return the transcript text tokens.\n\n        Returns:\n            List[str]: text tokens.\n        \"\"\"\n        return self._tokens\n\n    @property\n    def token_ids(self):\n        \"\"\"Return the transcript text token ids.\n\n        Returns:\n            List[int]: text token ids.\n        \"\"\"\n        return self._token_ids\n"
  },
  {
    "path": "paddlespeech/s2t/frontend/utility.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains data helper functions.\"\"\"\nimport json\nimport math\nimport tarfile\nfrom collections import namedtuple\nfrom typing import List\nfrom typing import Optional\nfrom typing import Text\n\nimport jsonlines\nimport numpy as np\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"load_dict\", \"load_cmvn\", \"read_manifest\", \"rms_to_db\", \"rms_to_dbfs\",\n    \"max_dbfs\", \"mean_dbfs\", \"gain_db_to_ratio\", \"normalize_audio\", \"SOS\",\n    \"EOS\", \"UNK\", \"BLANK\", \"MASKCTC\", \"SPACE\", \"convert_samples_to_float32\",\n    \"convert_samples_from_float32\"\n]\n\nIGNORE_ID = -1\n# `sos` and `eos` using same token\nSOS = \"<eos>\"\nEOS = SOS\nUNK = \"<unk>\"\nBLANK = \"<blank>\"\nMASKCTC = \"<mask>\"\nSPACE = \"<space>\"\n\n\ndef load_dict(dict_path: Optional[Text], maskctc=False) -> Optional[List[Text]]:\n    if dict_path is None:\n        return None\n\n    with open(dict_path, \"r\") as f:\n        dictionary = f.readlines()\n    # first token is `<blank>`\n    # multi line: `<blank> 0\\n`\n    # one line: `<blank>`\n    # space is relpace with <space>\n    char_list = [entry[:-1].split(\" \")[0] for entry in dictionary]\n    if BLANK not in char_list:\n        char_list.insert(0, BLANK)\n    if EOS not in char_list:\n        char_list.append(EOS)\n    # for non-autoregressive maskctc model\n    if maskctc and MASKCTC not in char_list:\n        char_list.append(MASKCTC)\n    return char_list\n\n\ndef read_manifest(\n        manifest_path,\n        max_input_len=float('inf'),\n        min_input_len=0.0,\n        max_output_len=float('inf'),\n        min_output_len=0.0,\n        max_output_input_ratio=float('inf'),\n        min_output_input_ratio=0.0, ):\n    \"\"\"Load and parse manifest file.\n\n    Args:\n        manifest_path ([type]): Manifest file to load and parse.\n        max_input_len ([type], optional): maximum output seq length,\n            in seconds for raw wav, in frame numbers for feature data.\n            Defaults to float('inf').\n        min_input_len (float, optional): minimum input seq length,\n            in seconds for raw wav, in frame numbers for feature data.\n            Defaults to 0.0.\n        max_output_len (float, optional): maximum input seq length,\n            in modeling units. Defaults to 500.0.\n        min_output_len (float, optional): minimum input seq length,\n            in modeling units. Defaults to 0.0.\n        max_output_input_ratio (float, optional):\n            maximum output seq length/output seq length ratio. Defaults to 10.0.\n        min_output_input_ratio (float, optional):\n            minimum output seq length/output seq length ratio. Defaults to 0.05.\n\n    Raises:\n        IOError: If failed to parse the manifest.\n\n    Returns:\n        List[dict]: Manifest parsing results.\n    \"\"\"\n    manifest = []\n    with jsonlines.open(manifest_path, 'r') as reader:\n        for json_data in reader:\n            feat_len = json_data[\"input\"][0][\"shape\"][\n                0] if \"input\" in json_data and \"shape\" in json_data[\"input\"][\n                    0] else 1.0\n            token_len = json_data[\"output\"][0][\"shape\"][\n                0] if \"output\" in json_data and \"shape\" in json_data[\"output\"][\n                    0] else 1.0\n            conditions = [\n                feat_len >= min_input_len,\n                feat_len <= max_input_len,\n                token_len >= min_output_len,\n                token_len <= max_output_len,\n                token_len / feat_len >= min_output_input_ratio,\n                token_len / feat_len <= max_output_input_ratio,\n            ]\n            if all(conditions):\n                manifest.append(json_data)\n    return manifest\n\n\n# Tar File read\nTarLocalData = namedtuple('TarLocalData', ['tar2info', 'tar2object'])\n\n\ndef parse_tar(file):\n    \"\"\"Parse a tar file to get a tarfile object\n    and a map containing tarinfoes\n    \"\"\"\n    result = {}\n    f = tarfile.open(file)\n    for tarinfo in f.getmembers():\n        result[tarinfo.name] = tarinfo\n    return f, result\n\n\ndef subfile_from_tar(file, local_data=None):\n    \"\"\"Get subfile object from tar.\n\n    tar:tarpath#filename\n\n    It will return a subfile object from tar file\n    and cached tar file info for next reading request.\n    \"\"\"\n    tarpath, filename = file.split(':', 1)[1].split('#', 1)\n\n    if local_data is None:\n        local_data = TarLocalData(tar2info={}, tar2object={})\n\n    assert isinstance(local_data, TarLocalData)\n\n    if 'tar2info' not in local_data.__dict__:\n        local_data.tar2info = {}\n    if 'tar2object' not in local_data.__dict__:\n        local_data.tar2object = {}\n\n    if tarpath not in local_data.tar2info:\n        fobj, infos = parse_tar(tarpath)\n        local_data.tar2info[tarpath] = infos\n        local_data.tar2object[tarpath] = fobj\n    else:\n        fobj = local_data.tar2object[tarpath]\n        infos = local_data.tar2info[tarpath]\n    return fobj.extractfile(infos[filename])\n\n\ndef rms_to_db(rms: float):\n    \"\"\"Root Mean Square to dB.\n\n    Args:\n        rms ([float]): root mean square\n\n    Returns:\n        float: dB\n    \"\"\"\n    return 20.0 * math.log10(max(1e-16, rms))\n\n\ndef rms_to_dbfs(rms: float):\n    \"\"\"Root Mean Square to dBFS.\n    https://fireattack.wordpress.com/2017/02/06/replaygain-loudness-normalization-and-applications/\n    Audio is mix of sine wave, so 1 amp sine wave's Full scale is 0.7071, equal to -3.0103dB.\n\n    dB = dBFS + 3.0103\n    dBFS = db - 3.0103\n    e.g. 0 dB = -3.0103 dBFS\n\n    Args:\n        rms ([float]): root mean square\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    return rms_to_db(rms) - 3.0103\n\n\ndef max_dbfs(sample_data: np.ndarray):\n    \"\"\"Peak dBFS based on the maximum energy sample.\n\n    Args:\n        sample_data ([np.ndarray]): float array, [-1, 1].\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    # Peak dBFS based on the maximum energy sample. Will prevent overdrive if used for normalization.\n    return rms_to_dbfs(max(abs(np.min(sample_data)), abs(np.max(sample_data))))\n\n\ndef mean_dbfs(sample_data):\n    \"\"\"Peak dBFS based on the RMS energy.\n\n    Args:\n        sample_data ([np.ndarray]): float array, [-1, 1].\n\n    Returns:\n        float: dBFS\n    \"\"\"\n    return rms_to_dbfs(\n        math.sqrt(np.mean(np.square(sample_data, dtype=np.float64))))\n\n\ndef gain_db_to_ratio(gain_db: float):\n    \"\"\"dB to ratio\n\n    Args:\n        gain_db (float): gain in dB\n\n    Returns:\n        float: scale in amp\n    \"\"\"\n    return math.pow(10.0, gain_db / 20.0)\n\n\ndef normalize_audio(sample_data: np.ndarray, dbfs: float=-3.0103):\n    \"\"\"Nomalize audio to dBFS.\n\n    Args:\n        sample_data (np.ndarray): input wave samples, [-1, 1].\n        dbfs (float, optional): target dBFS. Defaults to -3.0103.\n\n    Returns:\n        np.ndarray: normalized wave\n    \"\"\"\n    return np.maximum(\n        np.minimum(sample_data * gain_db_to_ratio(dbfs - max_dbfs(sample_data)),\n                   1.0), -1.0)\n\n\ndef _load_json_cmvn(json_cmvn_file):\n    \"\"\" Load the json format cmvn stats file and calculate cmvn\n\n    Args:\n        json_cmvn_file: cmvn stats file in json format\n\n    Returns:\n        a numpy array of [means, vars]\n    \"\"\"\n    with open(json_cmvn_file) as f:\n        cmvn_stats = json.load(f)\n\n    means = cmvn_stats['mean_stat']\n    variance = cmvn_stats['var_stat']\n    count = cmvn_stats['frame_num']\n    for i in range(len(means)):\n        means[i] /= count\n        variance[i] = variance[i] / count - means[i] * means[i]\n        if variance[i] < 1.0e-20:\n            variance[i] = 1.0e-20\n        variance[i] = 1.0 / math.sqrt(variance[i])\n    cmvn = np.array([means, variance])\n    return cmvn\n\n\ndef _load_kaldi_cmvn(kaldi_cmvn_file):\n    \"\"\" Load the kaldi format cmvn stats file and calculate cmvn\n\n    Args:\n        kaldi_cmvn_file:  kaldi text style global cmvn file, which\n           is generated by:\n           compute-cmvn-stats --binary=false scp:feats.scp global_cmvn\n\n    Returns:\n        a numpy array of [means, vars]\n    \"\"\"\n    means = []\n    variance = []\n    with open(kaldi_cmvn_file, 'r') as fid:\n        # kaldi binary file start with '\\0B'\n        if fid.read(2) == '\\0B':\n            logger.error('kaldi cmvn binary file is not supported, please '\n                         'recompute it by: compute-cmvn-stats --binary=false '\n                         ' scp:feats.scp global_cmvn')\n            sys.exit(1)\n        fid.seek(0)\n        arr = fid.read().split()\n        assert (arr[0] == '[')\n        assert (arr[-2] == '0')\n        assert (arr[-1] == ']')\n        feat_dim = int((len(arr) - 2 - 2) / 2)\n        for i in range(1, feat_dim + 1):\n            means.append(float(arr[i]))\n        count = float(arr[feat_dim + 1])\n        for i in range(feat_dim + 2, 2 * feat_dim + 2):\n            variance.append(float(arr[i]))\n\n    for i in range(len(means)):\n        means[i] /= count\n        variance[i] = variance[i] / count - means[i] * means[i]\n        if variance[i] < 1.0e-20:\n            variance[i] = 1.0e-20\n        variance[i] = 1.0 / math.sqrt(variance[i])\n    cmvn = np.array([means, variance])\n    return cmvn\n\n\ndef load_cmvn(cmvn_file: str, filetype: str):\n    \"\"\"load cmvn from file.\n\n    Args:\n        cmvn_file (str): cmvn path.\n        filetype (str): file type, optional[npz, json, kaldi].\n\n    Raises:\n        ValueError: file type not support.\n\n    Returns:\n        Tuple[np.ndarray, np.ndarray]: mean, istd\n    \"\"\"\n    assert filetype in ['npz', 'json', 'kaldi'], filetype\n    filetype = filetype.lower()\n    if filetype == \"json\":\n        cmvn = _load_json_cmvn(cmvn_file)\n    elif filetype == \"kaldi\":\n        cmvn = _load_kaldi_cmvn(cmvn_file)\n    elif filetype == \"npz\":\n        eps = 1e-14\n        npzfile = np.load(cmvn_file)\n        mean = np.squeeze(npzfile[\"mean\"])\n        std = np.squeeze(npzfile[\"std\"])\n        istd = 1 / (std + eps)\n        cmvn = [mean, istd]\n    else:\n        raise ValueError(f\"cmvn file type no support: {filetype}\")\n    return cmvn[0], cmvn[1]\n\n\ndef convert_samples_to_float32(samples):\n    \"\"\"Convert sample type to float32.\n\n    Audio sample type is usually integer or float-point.\n    Integers will be scaled to [-1, 1] in float32.\n\n    PCM16 -> PCM32\n    \"\"\"\n    float32_samples = samples.astype('float32')\n    if samples.dtype in np.sctypes['int']:\n        bits = np.iinfo(samples.dtype).bits\n        float32_samples *= (1. / 2**(bits - 1))\n    elif samples.dtype in np.sctypes['float']:\n        pass\n    else:\n        raise TypeError(\"Unsupported sample type: %s.\" % samples.dtype)\n    return float32_samples\n\n\ndef convert_samples_from_float32(samples, dtype):\n    \"\"\"Convert sample type from float32 to dtype.\n\n    Audio sample type is usually integer or float-point. For integer\n    type, float32 will be rescaled from [-1, 1] to the maximum range\n    supported by the integer type.\n\n    PCM32 -> PCM16\n    \"\"\"\n    dtype = np.dtype(dtype)\n    output_samples = samples.copy()\n    if dtype in np.sctypes['int']:\n        bits = np.iinfo(dtype).bits\n        output_samples *= (2**(bits - 1) / 1.)\n        min_val = np.iinfo(dtype).min\n        max_val = np.iinfo(dtype).max\n        output_samples[output_samples > max_val] = max_val\n        output_samples[output_samples < min_val] = min_val\n    elif samples.dtype in np.sctypes['float']:\n        min_val = np.finfo(dtype).min\n        max_val = np.finfo(dtype).max\n        output_samples[output_samples > max_val] = max_val\n        output_samples[output_samples < min_val] = min_val\n    else:\n        raise TypeError(\"Unsupported sample type: %s.\" % samples.dtype)\n    return output_samples.astype(dtype)\n"
  },
  {
    "path": "paddlespeech/s2t/io/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/io/batchfy.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport itertools\n\nimport numpy as np\n\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"make_batchset\"]\n\nlogger = Log(__name__).getlog()\n\n\ndef batchfy_by_seq(\n        sorted_data,\n        batch_size,\n        max_length_in,\n        max_length_out,\n        min_batch_size=1,\n        shortest_first=False,\n        ikey=\"input\",\n        iaxis=0,\n        okey=\"output\",\n        oaxis=0, ):\n    \"\"\"Make batch set from json dictionary\n\n    :param List[(str, Dict[str, Any])] sorted_data: dictionary loaded from data.json\n    :param int batch_size: batch size\n    :param int max_length_in: maximum length of input to decide adaptive batch size\n    :param int max_length_out: maximum length of output to decide adaptive batch size\n    :param int min_batch_size: mininum batch size (for multi-gpu)\n    :param bool shortest_first: Sort from batch with shortest samples\n        to longest if true, otherwise reverse\n    :param str ikey: key to access input\n        (for ASR ikey=\"input\", for TTS, MT ikey=\"output\".)\n    :param int iaxis: dimension to access input\n        (for ASR, TTS iaxis=0, for MT iaxis=\"1\".)\n    :param str okey: key to access output\n        (for ASR, MT okey=\"output\". for TTS okey=\"input\".)\n    :param int oaxis: dimension to access output\n        (for ASR, TTS, MT oaxis=0, reserved for future research, -1 means all axis.)\n    :return: List[List[Tuple[str, dict]]] list of batches\n    \"\"\"\n    if batch_size <= 0:\n        raise ValueError(f\"Invalid batch_size={batch_size}\")\n\n    # check #utts is more than min_batch_size\n    if len(sorted_data) < min_batch_size:\n        raise ValueError(\n            f\"#utts({len(sorted_data)}) is less than min_batch_size({min_batch_size}).\"\n        )\n\n    # make list of minibatches\n    minibatches = []\n    start = 0\n    while True:\n        _, info = sorted_data[start]\n        ilen = int(info[ikey][iaxis][\"shape\"][0])\n        olen = (int(info[okey][oaxis][\"shape\"][0]) if oaxis >= 0 else\n                max(map(lambda x: int(x[\"shape\"][0]), info[okey])))\n        factor = max(int(ilen / max_length_in), int(olen / max_length_out))\n        # change batchsize depending on the input and output length\n        # if ilen = 1000 and max_length_in = 800\n        # then b = batchsize / 2\n        # and max(min_batches, .) avoids batchsize = 0\n        bs = max(min_batch_size, int(batch_size / (1 + factor)))\n        end = min(len(sorted_data), start + bs)\n        minibatch = sorted_data[start:end]\n        if shortest_first:\n            minibatch.reverse()\n\n        # check each batch is more than minimum batchsize\n        if len(minibatch) < min_batch_size:\n            mod = min_batch_size - len(minibatch) % min_batch_size\n            additional_minibatch = [\n                sorted_data[i] for i in np.random.randint(0, start, mod)\n            ]\n            if shortest_first:\n                additional_minibatch.reverse()\n            minibatch.extend(additional_minibatch)\n        minibatches.append(minibatch)\n\n        if end == len(sorted_data):\n            break\n        start = end\n\n    # batch: List[List[Tuple[str, dict]]]\n    return minibatches\n\n\ndef batchfy_by_bin(\n        sorted_data,\n        batch_bins,\n        num_batches=0,\n        min_batch_size=1,\n        shortest_first=False,\n        ikey=\"input\",\n        okey=\"output\", ):\n    \"\"\"Make variably sized batch set, which maximizes\n\n    the number of bins up to `batch_bins`.\n\n    :param List[(str, Dict[str, Any])] sorted_data: dictionary loaded from data.json\n    :param int batch_bins: Maximum frames of a batch\n    :param int num_batches: # number of batches to use (for debug)\n    :param int min_batch_size: minimum batch size (for multi-gpu)\n    :param int test: Return only every `test` batches\n    :param bool shortest_first: Sort from batch with shortest samples\n        to longest if true, otherwise reverse\n\n    :param str ikey: key to access input (for ASR ikey=\"input\", for TTS ikey=\"output\".)\n    :param str okey: key to access output (for ASR okey=\"output\". for TTS okey=\"input\".)\n\n    :return: List[Tuple[str, Dict[str, List[Dict[str, Any]]]] list of batches\n    \"\"\"\n    if batch_bins <= 0:\n        raise ValueError(f\"invalid batch_bins={batch_bins}\")\n    length = len(sorted_data)\n    idim = int(sorted_data[0][1][ikey][0][\"shape\"][1])\n    odim = int(sorted_data[0][1][okey][0][\"shape\"][1])\n    logger.info(\"# utts: \" + str(len(sorted_data)))\n    minibatches = []\n    start = 0\n    n = 0\n    while True:\n        # Dynamic batch size depending on size of samples\n        b = 0\n        next_size = 0\n        max_olen = 0\n        while next_size < batch_bins and (start + b) < length:\n            ilen = int(sorted_data[start + b][1][ikey][0][\"shape\"][0]) * idim\n            olen = int(sorted_data[start + b][1][okey][0][\"shape\"][0]) * odim\n            if olen > max_olen:\n                max_olen = olen\n            next_size = (max_olen + ilen) * (b + 1)\n            if next_size <= batch_bins:\n                b += 1\n            elif next_size == 0:\n                raise ValueError(\n                    f\"Can't fit one sample in batch_bins ({batch_bins}): \"\n                    f\"Please increase the value\")\n        end = min(length, start + max(min_batch_size, b))\n        batch = sorted_data[start:end]\n        if shortest_first:\n            batch.reverse()\n        minibatches.append(batch)\n        # Check for min_batch_size and fixes the batches if needed\n        i = -1\n        while len(minibatches[i]) < min_batch_size:\n            missing = min_batch_size - len(minibatches[i])\n            if -i == len(minibatches):\n                minibatches[i + 1].extend(minibatches[i])\n                minibatches = minibatches[1:]\n                break\n            else:\n                minibatches[i].extend(minibatches[i - 1][:missing])\n                minibatches[i - 1] = minibatches[i - 1][missing:]\n                i -= 1\n        if end == length:\n            break\n        start = end\n        n += 1\n    if num_batches > 0:\n        minibatches = minibatches[:num_batches]\n    lengths = [len(x) for x in minibatches]\n    logger.info(\n        str(len(minibatches)) + \" batches containing from \" + str(min(lengths))\n        + \" to \" + str(max(lengths)) + \" samples \" + \"(avg \" + str(\n            int(np.mean(lengths))) + \" samples).\")\n    return minibatches\n\n\ndef batchfy_by_frame(\n        sorted_data,\n        max_frames_in,\n        max_frames_out,\n        max_frames_inout,\n        num_batches=0,\n        min_batch_size=1,\n        shortest_first=False,\n        ikey=\"input\",\n        okey=\"output\", ):\n    \"\"\"Make variable batch set, which maximizes the number of frames to max_batch_frame.\n\n    :param List[(str, Dict[str, Any])] sorteddata: dictionary loaded from data.json\n    :param int max_frames_in: Maximum input frames of a batch\n    :param int max_frames_out: Maximum output frames of a batch\n    :param int max_frames_inout: Maximum input+output frames of a batch\n    :param int num_batches: # number of batches to use (for debug)\n    :param int min_batch_size: minimum batch size (for multi-gpu)\n    :param int test: Return only every `test` batches\n    :param bool shortest_first: Sort from batch with shortest samples\n        to longest if true, otherwise reverse\n\n    :param str ikey: key to access input (for ASR ikey=\"input\", for TTS ikey=\"output\".)\n    :param str okey: key to access output (for ASR okey=\"output\". for TTS okey=\"input\".)\n\n    :return: List[Tuple[str, Dict[str, List[Dict[str, Any]]]] list of batches\n    \"\"\"\n    if max_frames_in <= 0 and max_frames_out <= 0 and max_frames_inout <= 0:\n        raise ValueError(\n            \"At least, one of `--batch-frames-in`, `--batch-frames-out` or \"\n            \"`--batch-frames-inout` should be > 0\")\n    length = len(sorted_data)\n    minibatches = []\n    start = 0\n    end = 0\n    while end != length:\n        # Dynamic batch size depending on size of samples\n        b = 0\n        max_olen = 0\n        max_ilen = 0\n        while (start + b) < length:\n            ilen = int(sorted_data[start + b][1][ikey][0][\"shape\"][0])\n            if ilen > max_frames_in and max_frames_in != 0:\n                raise ValueError(\n                    f\"Can't fit one sample in --batch-frames-in ({max_frames_in}): \"\n                    f\"Please increase the value\")\n            olen = int(sorted_data[start + b][1][okey][0][\"shape\"][0])\n            if olen > max_frames_out and max_frames_out != 0:\n                raise ValueError(\n                    f\"Can't fit one sample in --batch-frames-out ({max_frames_out}): \"\n                    f\"Please increase the value\")\n            if ilen + olen > max_frames_inout and max_frames_inout != 0:\n                raise ValueError(\n                    f\"Can't fit one sample in --batch-frames-out ({max_frames_inout}): \"\n                    f\"Please increase the value\")\n            max_olen = max(max_olen, olen)\n            max_ilen = max(max_ilen, ilen)\n            in_ok = max_ilen * (b + 1) <= max_frames_in or max_frames_in == 0\n            out_ok = max_olen * (b + 1) <= max_frames_out or max_frames_out == 0\n            inout_ok = (max_ilen + max_olen) * (\n                b + 1) <= max_frames_inout or max_frames_inout == 0\n            if in_ok and out_ok and inout_ok:\n                # add more seq in the minibatch\n                b += 1\n            else:\n                # no more seq in the minibatch\n                break\n        end = min(length, start + b)\n        batch = sorted_data[start:end]\n        if shortest_first:\n            batch.reverse()\n        minibatches.append(batch)\n        # Check for min_batch_size and fixes the batches if needed\n        i = -1\n        while len(minibatches[i]) < min_batch_size:\n            missing = min_batch_size - len(minibatches[i])\n            if -i == len(minibatches):\n                minibatches[i + 1].extend(minibatches[i])\n                minibatches = minibatches[1:]\n                break\n            else:\n                minibatches[i].extend(minibatches[i - 1][:missing])\n                minibatches[i - 1] = minibatches[i - 1][missing:]\n                i -= 1\n        start = end\n    if num_batches > 0:\n        minibatches = minibatches[:num_batches]\n    lengths = [len(x) for x in minibatches]\n    logger.info(\n        str(len(minibatches)) + \" batches containing from \" + str(min(lengths))\n        + \" to \" + str(max(lengths)) + \" samples\" + \"(avg \" + str(\n            int(np.mean(lengths))) + \" samples).\")\n\n    return minibatches\n\n\ndef batchfy_shuffle(data, batch_size, min_batch_size, num_batches,\n                    shortest_first):\n    import random\n\n    logger.info(\"use shuffled batch.\")\n    sorted_data = random.sample(data.items(), len(data.items()))\n    logger.info(\"# utts: \" + str(len(sorted_data)))\n    # make list of minibatches\n    minibatches = []\n    start = 0\n    while True:\n        end = min(len(sorted_data), start + batch_size)\n        # check each batch is more than minimum batchsize\n        minibatch = sorted_data[start:end]\n        if shortest_first:\n            minibatch.reverse()\n        if len(minibatch) < min_batch_size:\n            mod = min_batch_size - len(minibatch) % min_batch_size\n            additional_minibatch = [\n                sorted_data[i] for i in np.random.randint(0, start, mod)\n            ]\n            if shortest_first:\n                additional_minibatch.reverse()\n            minibatch.extend(additional_minibatch)\n        minibatches.append(minibatch)\n        if end == len(sorted_data):\n            break\n        start = end\n\n    # for debugging\n    if num_batches > 0:\n        minibatches = minibatches[:num_batches]\n        logger.info(\"# minibatches: \" + str(len(minibatches)))\n    return minibatches\n\n\nBATCH_COUNT_CHOICES = [\"auto\", \"seq\", \"bin\", \"frame\"]\nBATCH_SORT_KEY_CHOICES = [\"input\", \"output\", \"shuffle\"]\n\n\ndef make_batchset(\n        data,\n        batch_size=0,\n        max_length_in=float(\"inf\"),\n        max_length_out=float(\"inf\"),\n        num_batches=0,\n        min_batch_size=1,\n        shortest_first=False,\n        batch_sort_key=\"input\",\n        count=\"auto\",\n        batch_bins=0,\n        batch_frames_in=0,\n        batch_frames_out=0,\n        batch_frames_inout=0,\n        iaxis=0,\n        oaxis=0, ):\n    \"\"\"Make batch set from json dictionary\n\n    if utts have \"category\" value,\n\n        >>> data = [{'category': 'A', 'input': ..., 'utt':'utt1'},\n        ...         {'category': 'B', 'input': ..., 'utt':'utt2'},\n        ...         {'category': 'B', 'input': ..., 'utt':'utt3'},\n        ...         {'category': 'A', 'input': ..., 'utt':'utt4'}]\n        >>> make_batchset(data, batchsize=2, ...)\n        [[('utt1', ...), ('utt4', ...)], [('utt2', ...), ('utt3': ...)]]\n\n    Note that if any utts doesn't have \"category\",\n    perform as same as batchfy_by_{count}\n\n    :param List[Dict[str, Any]] data: dictionary loaded from data.json\n    :param int batch_size: maximum number of sequences in a minibatch.\n    :param int batch_bins: maximum number of bins (frames x dim) in a minibatch.\n    :param int batch_frames_in:  maximum number of input frames in a minibatch.\n    :param int batch_frames_out: maximum number of output frames in a minibatch.\n    :param int batch_frames_out: maximum number of input+output frames in a minibatch.\n    :param str count: strategy to count maximum size of batch.\n        For choices, see io.batchfy.BATCH_COUNT_CHOICES\n\n    :param int max_length_in: maximum length of input to decide adaptive batch size\n    :param int max_length_out: maximum length of output to decide adaptive batch size\n    :param int num_batches: # number of batches to use (for debug)\n    :param int min_batch_size: minimum batch size (for multi-gpu)\n    :param bool shortest_first: Sort from batch with shortest samples\n        to longest if true, otherwise reverse\n    :param str batch_sort_key: how to sort data before creating minibatches\n        [\"input\", \"output\", \"shuffle\"]\n    :param bool swap_io: if True, use \"input\" as output and \"output\"\n        as input in `data` dict\n    :param bool mt: if True, use 0-axis of \"output\" as output and 1-axis of \"output\"\n        as input in `data` dict\n    :param int iaxis: dimension to access input\n        (for ASR, TTS iaxis=0, for MT iaxis=\"1\".)\n    :param int oaxis: dimension to access output (for ASR, TTS, MT oaxis=0,\n        reserved for future research, -1 means all axis.)\n    :return: List[List[Tuple[str, dict]]] list of batches\n    \"\"\"\n    # check args\n    if count not in BATCH_COUNT_CHOICES:\n        raise ValueError(\n            f\"arg 'count' ({count}) should be one of {BATCH_COUNT_CHOICES}\")\n    if batch_sort_key not in BATCH_SORT_KEY_CHOICES:\n        raise ValueError(f\"arg 'batch_sort_key' ({batch_sort_key}) should be \"\n                         f\"one of {BATCH_SORT_KEY_CHOICES}\")\n\n    ikey = \"input\"\n    okey = \"output\"\n    batch_sort_axis = 0  # index of list \n    if count == \"auto\":\n        if batch_size != 0:\n            count = \"seq\"\n        elif batch_bins != 0:\n            count = \"bin\"\n        elif batch_frames_in != 0 or batch_frames_out != 0 or batch_frames_inout != 0:\n            count = \"frame\"\n        else:\n            raise ValueError(\n                f\"cannot detect `count` manually set one of {BATCH_COUNT_CHOICES}\"\n            )\n        logger.info(f\"count is auto detected as {count}\")\n\n    if count != \"seq\" and batch_sort_key == \"shuffle\":\n        raise ValueError(\n            \"batch_sort_key=shuffle is only available if batch_count=seq\")\n\n    category2data = {}  # Dict[str, dict]\n    for v in data:\n        k = v['utt']\n        category2data.setdefault(v.get(\"category\"), {})[k] = v\n\n    batches_list = []  # List[List[List[Tuple[str, dict]]]]\n    for d in category2data.values():\n        if batch_sort_key == \"shuffle\":\n            batches = batchfy_shuffle(d, batch_size, min_batch_size,\n                                      num_batches, shortest_first)\n            batches_list.append(batches)\n            continue\n\n        # sort it by input lengths (long to short)\n        sorted_data = sorted(\n            d.items(),\n            key=lambda data: float(data[1][batch_sort_key][batch_sort_axis][\"shape\"][0]),\n            reverse=not shortest_first, )\n        logger.info(\"# utts: \" + str(len(sorted_data)))\n\n        if count == \"seq\":\n            batches = batchfy_by_seq(\n                sorted_data,\n                batch_size=batch_size,\n                max_length_in=max_length_in,\n                max_length_out=max_length_out,\n                min_batch_size=min_batch_size,\n                shortest_first=shortest_first,\n                ikey=ikey,\n                iaxis=iaxis,\n                okey=okey,\n                oaxis=oaxis, )\n        if count == \"bin\":\n            batches = batchfy_by_bin(\n                sorted_data,\n                batch_bins=batch_bins,\n                min_batch_size=min_batch_size,\n                shortest_first=shortest_first,\n                ikey=ikey,\n                okey=okey, )\n        if count == \"frame\":\n            batches = batchfy_by_frame(\n                sorted_data,\n                max_frames_in=batch_frames_in,\n                max_frames_out=batch_frames_out,\n                max_frames_inout=batch_frames_inout,\n                min_batch_size=min_batch_size,\n                shortest_first=shortest_first,\n                ikey=ikey,\n                okey=okey, )\n        batches_list.append(batches)\n\n    if len(batches_list) == 1:\n        batches = batches_list[0]\n    else:\n        # Concat list. This way is faster than \"sum(batch_list, [])\"\n        batches = list(itertools.chain(*batches_list))\n\n    # for debugging\n    if num_batches > 0:\n        batches = batches[:num_batches]\n    logger.info(\"# minibatches: \" + str(len(batches)))\n\n    # batch: List[List[Tuple[str, dict]]]\n    return batches\n"
  },
  {
    "path": "paddlespeech/s2t/io/collator.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\n\nimport numpy as np\n\nfrom paddlespeech.s2t.frontend.augmentor.augmentation import AugmentationPipeline\nfrom paddlespeech.s2t.frontend.featurizer.speech_featurizer import SpeechFeaturizer\nfrom paddlespeech.s2t.frontend.normalizer import FeatureNormalizer\nfrom paddlespeech.s2t.frontend.speech import SpeechSegment\nfrom paddlespeech.s2t.frontend.utility import IGNORE_ID\nfrom paddlespeech.s2t.frontend.utility import TarLocalData\nfrom paddlespeech.s2t.io.reader import LoadInputsAndTargets\nfrom paddlespeech.s2t.io.utility import pad_list\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"SpeechCollator\", \"TripletSpeechCollator\"]\n\nlogger = Log(__name__).getlog()\n\n\ndef _tokenids(text, keep_transcription_text):\n    # for training text is token ids\n    tokens = text  # token ids\n\n    if keep_transcription_text:\n        # text is string, convert to unicode ord\n        assert isinstance(text, str), (type(text), text)\n        tokens = [ord(t) for t in text]\n\n    tokens = np.array(tokens, dtype=np.int64)\n    return tokens\n\n\nclass SpeechCollatorBase():\n    def __init__(\n            self,\n            aug_file,\n            mean_std_filepath,\n            vocab_filepath,\n            spm_model_prefix,\n            random_seed=0,\n            unit_type=\"char\",\n            spectrum_type='linear',  # 'linear', 'mfcc', 'fbank'\n            feat_dim=0,  # 'mfcc', 'fbank'\n            delta_delta=False,  # 'mfcc', 'fbank'\n            stride_ms=10.0,  # ms\n            window_ms=20.0,  # ms\n            n_fft=None,  # fft points\n            max_freq=None,  # None for samplerate/2\n            target_sample_rate=16000,  # target sample rate\n            use_dB_normalization=True,\n            target_dB=-20,\n            dither=1.0,\n            keep_transcription_text=True):\n        \"\"\"SpeechCollator Collator\n\n        Args:\n            unit_type(str): token unit type, e.g. char, word, spm\n            vocab_filepath (str): vocab file path.\n            mean_std_filepath (str): mean and std file path, which suffix is *.npy\n            spm_model_prefix (str): spm model prefix, need if `unit_type` is spm.\n            augmentation_config (str, optional): augmentation json str. Defaults to '{}'.\n            stride_ms (float, optional): stride size in ms. Defaults to 10.0.\n            window_ms (float, optional): window size in ms. Defaults to 20.0.\n            n_fft (int, optional): fft points for rfft. Defaults to None.\n            max_freq (int, optional): max cut freq. Defaults to None.\n            target_sample_rate (int, optional): target sample rate which used for training. Defaults to 16000.\n            spectrum_type (str, optional): 'linear', 'mfcc' or 'fbank'. Defaults to 'linear'.\n            feat_dim (int, optional): audio feature dim, using by 'mfcc' or 'fbank'. Defaults to None.\n            delta_delta (bool, optional): audio feature with delta-delta, using by 'fbank' or 'mfcc'. Defaults to False.\n            use_dB_normalization (bool, optional): do dB normalization. Defaults to True.\n            target_dB (int, optional): target dB. Defaults to -20.\n            random_seed (int, optional): for random generator. Defaults to 0.\n            keep_transcription_text (bool, optional): True, when not in training mode, will not do tokenizer; Defaults to False.\n            if ``keep_transcription_text`` is False, text is token ids else is raw string.\n\n        Do augmentations\n        Padding audio features with zeros to make them have the same shape (or\n        a user-defined shape) within one batch.\n        \"\"\"\n        self.keep_transcription_text = keep_transcription_text\n        self.train_mode = not keep_transcription_text\n\n        self.stride_ms = stride_ms\n        self.window_ms = window_ms\n        self.feat_dim = feat_dim\n\n        self.loader = LoadInputsAndTargets()\n\n        # only for tar filetype\n        self._local_data = TarLocalData(tar2info={}, tar2object={})\n\n        self.augmentation = AugmentationPipeline(\n            preprocess_conf=aug_file.read(), random_seed=random_seed)\n\n        self._normalizer = FeatureNormalizer(\n            mean_std_filepath) if mean_std_filepath else None\n\n        self._speech_featurizer = SpeechFeaturizer(\n            unit_type=unit_type,\n            vocab_filepath=vocab_filepath,\n            spm_model_prefix=spm_model_prefix,\n            spectrum_type=spectrum_type,\n            feat_dim=feat_dim,\n            delta_delta=delta_delta,\n            stride_ms=stride_ms,\n            window_ms=window_ms,\n            n_fft=n_fft,\n            max_freq=max_freq,\n            target_sample_rate=target_sample_rate,\n            use_dB_normalization=use_dB_normalization,\n            target_dB=target_dB,\n            dither=dither)\n\n        self.feature_size = self._speech_featurizer.audio_feature.feature_size\n        self.text_feature = self._speech_featurizer.text_feature\n        self.vocab_dict = self.text_feature.vocab_dict\n        self.vocab_list = self.text_feature.vocab_list\n        self.vocab_size = self.text_feature.vocab_size\n\n    def process_utterance(self, audio_file, transcript):\n        \"\"\"Load, augment, featurize and normalize for speech data.\n\n        :param audio_file: Filepath or file object of audio file.\n        :type audio_file: str | file\n        :param transcript: Transcription text.\n        :type transcript: str\n        :return: Tuple of audio feature tensor and data of transcription part,\n                 where transcription part could be token ids or text.\n        :rtype: tuple of (2darray, list)\n        \"\"\"\n        filetype = self.loader.file_type(audio_file)\n\n        if filetype != 'sound':\n            spectrum = self.loader._get_from_loader(audio_file, filetype)\n            feat_dim = spectrum.shape[1]\n            assert feat_dim == self.feat_dim, f\"expect feat dim {self.feat_dim}, but got {feat_dim}\"\n\n            if self.keep_transcription_text:\n                transcript_part = transcript\n            else:\n                text_ids = self.text_feature.featurize(transcript)\n                transcript_part = text_ids\n        else:\n            # read audio\n            speech_segment = SpeechSegment.from_file(\n                audio_file, transcript, infos=self._local_data)\n            # audio augment\n            self.augmentation.transform_audio(speech_segment)\n\n            # extract speech feature\n            spectrum, transcript_part = self._speech_featurizer.featurize(\n                speech_segment, self.keep_transcription_text)\n            # CMVN spectrum\n            if self._normalizer:\n                spectrum = self._normalizer.apply(spectrum)\n\n        # spectrum augment\n        spectrum = self.augmentation.transform_feature(spectrum)\n        return spectrum, transcript_part\n\n    def __call__(self, batch):\n        \"\"\"batch examples\n\n        Args:\n            batch (List[Dict]): batch is [dict(audio, text, ...)]\n                audio (np.ndarray) shape (T, D)\n                text (List[int] or str): shape (U,)\n\n        Returns:\n            tuple(utts, xs_pad, ilens, ys_pad, olens): batched data.\n                utts: (B,)\n                xs_pad : (B, Tmax, D)\n                ilens: (B,)\n                ys_pad : (B, Umax)\n                olens: (B,)\n        \"\"\"\n        audios = []\n        audio_lens = []\n        texts = []\n        text_lens = []\n        utts = []\n        tids = []  # tokenids\n\n        for idx, item in enumerate(batch):\n            utts.append(item['utt'])\n\n            audio = item['input'][0]['feat']\n            text = item['output'][0]['text']\n            audio, text = self.process_utterance(audio, text)\n\n            audios.append(audio)  # [T, D]\n            audio_lens.append(audio.shape[0])\n\n            tokens = _tokenids(text, self.keep_transcription_text)\n            texts.append(tokens)\n            text_lens.append(tokens.shape[0])\n\n        #[B, T, D]\n        xs_pad = pad_list(audios, 0.0).astype(np.float32)\n        ilens = np.array(audio_lens).astype(np.int64)\n        ys_pad = pad_list(texts, IGNORE_ID).astype(np.int64)\n        olens = np.array(text_lens).astype(np.int64)\n        return utts, xs_pad, ilens, ys_pad, olens\n\n\nclass SpeechCollator(SpeechCollatorBase):\n    @classmethod\n    def from_config(cls, config):\n        \"\"\"Build a SpeechCollator object from a config.\n\n        Args:\n            config (yacs.config.CfgNode): configs object.\n\n        Returns:\n            SpeechCollator: collator object.\n        \"\"\"\n        assert 'augmentation_config' in config\n        assert 'keep_transcription_text' in config\n        assert 'mean_std_filepath' in config\n        assert 'vocab_filepath' in config\n        assert 'spectrum_type' in config\n        assert 'n_fft' in config\n        assert config\n\n        if isinstance(config.augmentation_config, (str, bytes)):\n            if config.augmentation_config:\n                aug_file = io.open(\n                    config.augmentation_config, mode='r', encoding='utf8')\n            else:\n                aug_file = io.StringIO(initial_value='{}', newline='')\n        else:\n            aug_file = config.augmentation_config\n            assert isinstance(aug_file, io.StringIO)\n\n        speech_collator = cls(\n            aug_file=aug_file,\n            random_seed=0,\n            mean_std_filepath=config.mean_std_filepath,\n            unit_type=config.unit_type,\n            vocab_filepath=config.vocab_filepath,\n            spm_model_prefix=config.spm_model_prefix,\n            spectrum_type=config.spectrum_type,\n            feat_dim=config.feat_dim,\n            delta_delta=config.delta_delta,\n            stride_ms=config.stride_ms,\n            window_ms=config.window_ms,\n            n_fft=config.n_fft,\n            max_freq=config.max_freq,\n            target_sample_rate=config.target_sample_rate,\n            use_dB_normalization=config.use_dB_normalization,\n            target_dB=config.target_dB,\n            dither=config.dither,\n            keep_transcription_text=config.keep_transcription_text)\n        return speech_collator\n\n\nclass TripletSpeechCollator(SpeechCollator):\n    def process_utterance(self, audio_file, translation, transcript):\n        \"\"\"Load, augment, featurize and normalize for speech data.\n\n        :param audio_file: Filepath or file object of audio file.\n        :type audio_file: str | file\n        :param translation: translation text.\n        :type translation: str\n        :return: Tuple of audio feature tensor and data of translation part,\n                    where translation part could be token ids or text.\n        :rtype: tuple of (2darray, list)\n        \"\"\"\n        spectrum, translation_part = super().process_utterance(audio_file,\n                                                               translation)\n        transcript_part = self._speech_featurizer.text_featurize(\n            transcript, self.keep_transcription_text)\n        return spectrum, translation_part, transcript_part\n\n    def __call__(self, batch):\n        \"\"\"batch examples\n\n        Args:\n            batch (List[Dict]): batch is [dict(audio, text, ...)]\n                audio (np.ndarray) shape (T, D)\n                text (List[int] or str): shape (U,)\n\n        Returns:\n            tuple(utts, xs_pad, ilens, ys_pad, olens): batched data.\n                utts: (B,)\n                xs_pad : (B, Tmax, D)\n                ilens: (B,)\n                ys_pad : [(B, Umax), (B, Umax)]\n                olens: [(B,), (B,)]\n        \"\"\"\n        utts = []\n        audios = []\n        audio_lens = []\n        translation_text = []\n        translation_text_lens = []\n        transcription_text = []\n        transcription_text_lens = []\n\n        for idx, item in enumerate(batch):\n            utts.append(item['utt'])\n\n            audio = item['input'][0]['feat']\n            translation = item['output'][0]['text']\n            transcription = item['output'][1]['text']\n\n            audio, translation, transcription = self.process_utterance(\n                audio, translation, transcription)\n\n            audios.append(audio)  # [T, D]\n            audio_lens.append(audio.shape[0])\n\n            tokens = [[], []]\n            for idx, text in enumerate([translation, transcription]):\n                tokens[idx] = _tokenids(text, self.keep_transcription_text)\n\n            translation_text.append(tokens[0])\n            translation_text_lens.append(tokens[0].shape[0])\n            transcription_text.append(tokens[1])\n            transcription_text_lens.append(tokens[1].shape[0])\n\n        xs_pad = pad_list(audios, 0.0).astype(np.float32)  #[B, T, D]\n        ilens = np.array(audio_lens).astype(np.int64)\n\n        padded_translation = pad_list(translation_text,\n                                      IGNORE_ID).astype(np.int64)\n        translation_lens = np.array(translation_text_lens).astype(np.int64)\n\n        padded_transcription = pad_list(transcription_text,\n                                        IGNORE_ID).astype(np.int64)\n        transcription_lens = np.array(transcription_text_lens).astype(np.int64)\n\n        ys_pad = (padded_translation, padded_transcription)\n        olens = (translation_lens, transcription_lens)\n        return utts, xs_pad, ilens, ys_pad, olens\n"
  },
  {
    "path": "paddlespeech/s2t/io/converter.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport numpy as np\n\nfrom paddlespeech.s2t.io.utility import pad_list\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"CustomConverter\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass CustomConverter():\n    \"\"\"Custom batch converter.\n\n    Args:\n        subsampling_factor (int): The subsampling factor.\n        dtype (np.dtype): Data type to convert.\n        \n    \"\"\"\n\n    def __init__(self,\n                 subsampling_factor=1,\n                 dtype=np.float32,\n                 load_aux_input=False,\n                 load_aux_output=False):\n        \"\"\"Construct a CustomConverter object.\"\"\"\n        self.subsampling_factor = subsampling_factor\n        self.ignore_id = -1\n        self.dtype = dtype\n        self.load_aux_input = load_aux_input\n        self.load_aux_output = load_aux_output\n\n    def __call__(self, batch):\n        \"\"\"Transform a batch and send it to a device.\n\n        Args:\n            batch (list): The batch to transform.\n\n        Returns:\n            tuple(np.ndarray, nn.ndarray, nn.ndarray)\n\n        \"\"\"\n        # batch should be located in list\n        assert len(batch) == 1\n        data, utts = batch[0]\n        xs_data, ys_data = [], []\n        for ud in data:\n            if ud[0].ndim > 1:\n                # speech data (input): (speech_len, feat_dim)\n                xs_data.append(ud)\n            else:\n                # text data (output): (text_len, )\n                ys_data.append(ud)\n\n        assert xs_data[0][\n            0] is not None, \"please check Reader and Augmentation impl.\"\n\n        xs_pad, ilens = [], []\n        for xs in xs_data:\n            # perform subsampling\n            if self.subsampling_factor > 1:\n                xs = [x[::self.subsampling_factor, :] for x in xs]\n\n            # get batch of lengths of input sequences\n            ilens.append(np.array([x.shape[0] for x in xs]))\n\n            # perform padding and convert to tensor\n            # currently only support real number\n            xs_pad.append(pad_list(xs, 0).astype(self.dtype))\n\n            if not self.load_aux_input:\n                xs_pad, ilens = xs_pad[0], ilens[0]\n                break\n\n        # NOTE: this is for multi-output (e.g., speech translation)\n        ys_pad, olens = [], []\n\n        for ys in ys_data:\n            ys_pad.append(\n                pad_list([\n                    np.array(y[0][:]) if isinstance(y, tuple) else y for y in ys\n                ], self.ignore_id))\n\n            olens.append(\n                np.array([\n                    y[0].shape[0] if isinstance(y, tuple) else y.shape[0]\n                    for y in ys\n                ]))\n\n            if not self.load_aux_output:\n                ys_pad, olens = ys_pad[0], olens[0]\n                break\n\n        return utts, xs_pad, ilens, ys_pad, olens\n"
  },
  {
    "path": "paddlespeech/s2t/io/dataloader.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Text\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddle.io import BatchSampler\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nimport paddlespeech.audio.streamdata as streamdata\nfrom paddlespeech.audio.text.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.batchfy import make_batchset\nfrom paddlespeech.s2t.io.converter import CustomConverter\nfrom paddlespeech.s2t.io.dataset import TransformDataset\nfrom paddlespeech.s2t.io.reader import LoadInputsAndTargets\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"BatchDataLoader\", \"StreamDataLoader\"]\n\nlogger = Log(__name__).getlog()\n\n\ndef feat_dim_and_vocab_size(data_json: List[Dict[Text, Any]],\n                            mode: Text=\"asr\",\n                            iaxis=0,\n                            oaxis=0):\n    if mode == 'asr':\n        feat_dim = data_json[0]['input'][oaxis]['shape'][1]\n        vocab_size = data_json[0]['output'][oaxis]['shape'][1]\n    else:\n        raise ValueError(f\"{mode} mode not support!\")\n    return feat_dim, vocab_size\n\n\ndef batch_collate(x):\n    \"\"\"de-minibatch, since user compose batch.\n\n    Args:\n        x (List[Tuple]): [(utts, xs, ilens, ys, olens)]\n\n    Returns:\n        Tuple: (utts, xs, ilens, ys, olens)\n    \"\"\"\n    return x[0]\n\n\ndef read_preprocess_cfg(preprocess_conf_file):\n    augment_conf = dict()\n    preprocess_cfg = CfgNode(new_allowed=True)\n    preprocess_cfg.merge_from_file(preprocess_conf_file)\n    for idx, process in enumerate(preprocess_cfg[\"process\"]):\n        opts = dict(process)\n        process_type = opts.pop(\"type\")\n        if process_type == 'time_warp':\n            augment_conf['max_w'] = process['max_time_warp']\n            augment_conf['w_inplace'] = process['inplace']\n            augment_conf['w_mode'] = process['mode']\n        if process_type == 'freq_mask':\n            augment_conf['max_f'] = process['F']\n            augment_conf['num_f_mask'] = process['n_mask']\n            augment_conf['f_inplace'] = process['inplace']\n            augment_conf['f_replace_with_zero'] = process['replace_with_zero']\n        if process_type == 'time_mask':\n            augment_conf['max_t'] = process['T']\n            augment_conf['num_t_mask'] = process['n_mask']\n            augment_conf['t_inplace'] = process['inplace']\n            augment_conf['t_replace_with_zero'] = process['replace_with_zero']\n    return augment_conf\n\n\nclass StreamDataLoader():\n    def __init__(self,\n                 manifest_file: str,\n                 train_mode: bool,\n                 unit_type: str='char',\n                 batch_size: int=0,\n                 preprocess_conf=None,\n                 num_mel_bins=80,\n                 frame_length=25,\n                 frame_shift=10,\n                 dither=0.0,\n                 minlen_in: float=0.0,\n                 maxlen_in: float=float('inf'),\n                 minlen_out: float=0.0,\n                 maxlen_out: float=float('inf'),\n                 resample_rate: int=16000,\n                 shuffle_size: int=10000,\n                 sort_size: int=1000,\n                 n_iter_processes: int=1,\n                 prefetch_factor: int=2,\n                 dist_sampler: bool=False,\n                 cmvn_file=\"data/mean_std.json\",\n                 vocab_filepath='data/lang_char/vocab.txt'):\n        self.manifest_file = manifest_file\n        self.train_model = train_mode\n        self.batch_size = batch_size\n        self.prefetch_factor = prefetch_factor\n        self.dist_sampler = dist_sampler\n        self.n_iter_processes = n_iter_processes\n\n        text_featurizer = TextFeaturizer(unit_type, vocab_filepath)\n        symbol_table = text_featurizer.vocab_dict\n        self.feat_dim = num_mel_bins\n        self.vocab_size = text_featurizer.vocab_size\n\n        augment_conf = read_preprocess_cfg(preprocess_conf)\n\n        # The list of shard\n        shardlist = []\n        with open(manifest_file, \"r\") as f:\n            for line in f.readlines():\n                shardlist.append(line.strip())\n        world_size = 1\n        try:\n            world_size = paddle.distributed.get_world_size()\n        except Exception as e:\n            logger.warninig(e)\n            logger.warninig(\n                \"can not get world_size using paddle.distributed.get_world_size(), use world_size=1\"\n            )\n        assert len(shardlist) >= world_size, \\\n            \"the length of shard list should >= number of gpus/xpus/...\"\n\n        update_n_iter_processes = int(\n            max(min(len(shardlist) / world_size - 1, self.n_iter_processes), 0))\n        logger.info(f\"update_n_iter_processes {update_n_iter_processes}\")\n        if update_n_iter_processes != self.n_iter_processes:\n            self.n_iter_processes = update_n_iter_processes\n            logger.info(f\"change nun_workers to {self.n_iter_processes}\")\n\n        if self.dist_sampler:\n            base_dataset = streamdata.DataPipeline(\n                streamdata.SimpleShardList(shardlist), streamdata.split_by_node\n                if train_mode else streamdata.placeholder(),\n                streamdata.split_by_worker,\n                streamdata.tarfile_to_samples(streamdata.reraise_exception))\n        else:\n            base_dataset = streamdata.DataPipeline(\n                streamdata.SimpleShardList(shardlist),\n                streamdata.split_by_worker,\n                streamdata.tarfile_to_samples(streamdata.reraise_exception))\n\n        self.dataset = base_dataset.append_list(\n            streamdata.audio_tokenize(symbol_table),\n            streamdata.audio_data_filter(\n                frame_shift=frame_shift,\n                max_length=maxlen_in,\n                min_length=minlen_in,\n                token_max_length=maxlen_out,\n                token_min_length=minlen_out),\n            streamdata.audio_resample(resample_rate=resample_rate),\n            streamdata.audio_compute_fbank(\n                num_mel_bins=num_mel_bins,\n                frame_length=frame_length,\n                frame_shift=frame_shift,\n                dither=dither),\n            streamdata.audio_spec_aug(**augment_conf)\n            if train_mode else streamdata.placeholder(\n            ),  # num_t_mask=2, num_f_mask=2, max_t=40, max_f=30, max_w=80)\n            streamdata.shuffle(shuffle_size),\n            streamdata.sort(sort_size=sort_size),\n            streamdata.batched(batch_size),\n            streamdata.audio_padding(),\n            streamdata.audio_cmvn(cmvn_file))\n\n        if paddle.__version__ >= '2.3.2':\n            self.loader = streamdata.WebLoader(\n                self.dataset,\n                num_workers=self.n_iter_processes,\n                prefetch_factor=self.prefetch_factor,\n                batch_size=None)\n        else:\n            self.loader = streamdata.WebLoader(\n                self.dataset,\n                num_workers=self.n_iter_processes,\n                batch_size=None)\n\n    def __iter__(self):\n        return self.loader.__iter__()\n\n    def __call__(self):\n        return self.__iter__()\n\n    def __len__(self):\n        logger.info(\n            \"Stream dataloader does not support calculate the length of the dataset\"\n        )\n        return -1\n\n\nclass BatchDataLoader():\n    def __init__(self,\n                 json_file: str,\n                 train_mode: bool,\n                 sortagrad: int=0,\n                 batch_size: int=0,\n                 maxlen_in: float=float('inf'),\n                 maxlen_out: float=float('inf'),\n                 minibatches: int=0,\n                 mini_batch_size: int=1,\n                 batch_count: str='auto',\n                 batch_bins: int=0,\n                 batch_frames_in: int=0,\n                 batch_frames_out: int=0,\n                 batch_frames_inout: int=0,\n                 preprocess_conf=None,\n                 n_iter_processes: int=1,\n                 subsampling_factor: int=1,\n                 load_aux_input: bool=False,\n                 load_aux_output: bool=False,\n                 num_encs: int=1,\n                 dist_sampler: bool=False,\n                 shortest_first: bool=False):\n        self.json_file = json_file\n        self.train_mode = train_mode\n        self.use_sortagrad = sortagrad == -1 or sortagrad > 0\n        self.batch_size = batch_size\n        self.maxlen_in = maxlen_in\n        self.maxlen_out = maxlen_out\n        self.batch_count = batch_count\n        self.batch_bins = batch_bins\n        self.batch_frames_in = batch_frames_in\n        self.batch_frames_out = batch_frames_out\n        self.batch_frames_inout = batch_frames_inout\n        self.subsampling_factor = subsampling_factor\n        self.num_encs = num_encs\n        self.preprocess_conf = preprocess_conf\n        self.n_iter_processes = n_iter_processes\n        self.load_aux_input = load_aux_input\n        self.load_aux_output = load_aux_output\n        self.dist_sampler = dist_sampler\n        self.shortest_first = shortest_first\n\n        # read json data\n        with jsonlines.open(json_file, 'r') as reader:\n            self.data_json = list(reader)\n\n        self.feat_dim, self.vocab_size = feat_dim_and_vocab_size(\n            self.data_json, mode='asr')\n\n        # make minibatch list (variable length)\n        self.minibaches = make_batchset(\n            self.data_json,\n            batch_size,\n            maxlen_in,\n            maxlen_out,\n            minibatches,  # for debug\n            min_batch_size=mini_batch_size,\n            shortest_first=self.shortest_first or self.use_sortagrad,\n            count=batch_count,\n            batch_bins=batch_bins,\n            batch_frames_in=batch_frames_in,\n            batch_frames_out=batch_frames_out,\n            batch_frames_inout=batch_frames_inout,\n            iaxis=0,\n            oaxis=0, )\n\n        # data reader\n        self.reader = LoadInputsAndTargets(\n            mode=\"asr\",\n            load_output=True,\n            preprocess_conf=preprocess_conf,\n            preprocess_args={\"train\":\n                             train_mode},  # Switch the mode of preprocessing\n        )\n\n        # Setup a converter\n        if num_encs == 1:\n            self.converter = CustomConverter(\n                subsampling_factor=subsampling_factor,\n                dtype=np.float32,\n                load_aux_input=load_aux_input,\n                load_aux_output=load_aux_output)\n        else:\n            assert NotImplementedError(\"not impl CustomConverterMulEnc.\")\n\n        # hack to make batchsize argument as 1\n        # actual bathsize is included in a list\n        # default collate function converts numpy array to paddle tensor\n        # we used an empty collate function instead which returns list\n        self.dataset = TransformDataset(self.minibaches, self.converter,\n                                        self.reader)\n\n        if self.dist_sampler:\n            self.batch_sampler = DistributedBatchSampler(\n                dataset=self.dataset,\n                batch_size=1,\n                shuffle=not self.use_sortagrad if self.train_mode else False,\n                drop_last=False, )\n        else:\n            self.batch_sampler = BatchSampler(\n                dataset=self.dataset,\n                batch_size=1,\n                shuffle=not self.use_sortagrad if self.train_mode else False,\n                drop_last=False, )\n\n        self.dataloader = DataLoader(\n            dataset=self.dataset,\n            batch_sampler=self.batch_sampler,\n            collate_fn=batch_collate,\n            num_workers=self.n_iter_processes, )\n\n    def __len__(self):\n        return len(self.dataloader)\n\n    def __iter__(self):\n        return self.dataloader.__iter__()\n\n    def __call__(self):\n        return self.__iter__()\n\n    def __repr__(self):\n        echo = f\"<{self.__class__.__module__}.{self.__class__.__name__} object at {hex(id(self))}> \"\n        echo += f\"train_mode: {self.train_mode}, \"\n        echo += f\"sortagrad: {self.use_sortagrad}, \"\n        echo += f\"batch_size: {self.batch_size}, \"\n        echo += f\"maxlen_in: {self.maxlen_in}, \"\n        echo += f\"maxlen_out: {self.maxlen_out}, \"\n        echo += f\"batch_count: {self.batch_count}, \"\n        echo += f\"batch_bins: {self.batch_bins}, \"\n        echo += f\"batch_frames_in: {self.batch_frames_in}, \"\n        echo += f\"batch_frames_out: {self.batch_frames_out}, \"\n        echo += f\"batch_frames_inout: {self.batch_frames_inout}, \"\n        echo += f\"subsampling_factor: {self.subsampling_factor}, \"\n        echo += f\"num_encs: {self.num_encs}, \"\n        echo += f\"num_workers: {self.n_iter_processes}, \"\n        echo += f\"load_aux_input: {self.load_aux_input}, \"\n        echo += f\"load_aux_output: {self.load_aux_output}, \"\n        echo += f\"dist_sampler: {self.dist_sampler}, \"\n        echo += f\"shortest_first: {self.shortest_first}, \"\n        echo += f\"file: {self.json_file}\"\n        return echo\n\n\nclass DataLoaderFactory():\n    @staticmethod\n    def get_dataloader(mode: str, config, args):\n        config = config.clone()\n        use_streamdata = config.get(\"use_stream_data\", False)\n        if use_streamdata:\n            if mode == 'train':\n                config['manifest'] = config.train_manifest\n                config['train_mode'] = True\n            elif mode == 'valid':\n                config['manifest'] = config.dev_manifest\n                config['train_mode'] = False\n            elif mode == 'test' or mode == 'align':\n                config['manifest'] = config.test_manifest\n                config['train_mode'] = False\n                config['dither'] = 0.0\n                config['minlen_in'] = 0.0\n                config['maxlen_in'] = float('inf')\n                config['minlen_out'] = 0\n                config['maxlen_out'] = float('inf')\n                config['dist_sampler'] = False\n            else:\n                raise KeyError(\n                    \"not valid mode type!!, please input one of 'train, valid, test, align'\"\n                )\n            return StreamDataLoader(\n                manifest_file=config.manifest,\n                train_mode=config.train_mode,\n                unit_type=config.unit_type,\n                preprocess_conf=config.preprocess_config,\n                batch_size=config.batch_size,\n                num_mel_bins=config.feat_dim,\n                frame_length=config.window_ms,\n                frame_shift=config.stride_ms,\n                dither=config.dither,\n                minlen_in=config.minlen_in,\n                maxlen_in=config.maxlen_in,\n                minlen_out=config.minlen_out,\n                maxlen_out=config.maxlen_out,\n                resample_rate=config.resample_rate,\n                shuffle_size=config.shuffle_size,\n                sort_size=config.sort_size,\n                n_iter_processes=config.num_workers,\n                prefetch_factor=config.prefetch_factor,\n                dist_sampler=config.dist_sampler,\n                cmvn_file=config.cmvn_file,\n                vocab_filepath=config.vocab_filepath, )\n        else:\n            if mode == 'train':\n                config['manifest'] = config.train_manifest\n                config['train_mode'] = True\n                config['mini_batch_size'] = args.ngpu\n                config['subsampling_factor'] = 1\n                config['num_encs'] = 1\n                config['shortest_first'] = False\n                config['minibatches'] = 0\n                config['batch_count'] = 'auto'\n                config['batch_bins'] = 0\n                config['batch_frames_in'] = 0\n                config['batch_frames_out'] = 0\n                config['batch_frames_inout'] = 0\n            elif mode == 'valid':\n                config['manifest'] = config.dev_manifest\n                config['train_mode'] = False\n                config['sortagrad'] = False\n                config['maxlen_in'] = float('inf')\n                config['maxlen_out'] = float('inf')\n                config['minibatches'] = 0\n                config['mini_batch_size'] = args.ngpu\n                config['batch_count'] = 'auto'\n                config['batch_bins'] = 0\n                config['batch_frames_in'] = 0\n                config['batch_frames_out'] = 0\n                config['batch_frames_inout'] = 0\n                config['subsampling_factor'] = 1\n                config['num_encs'] = 1\n                config['shortest_first'] = False\n            elif mode == 'test' or mode == 'align':\n                config['manifest'] = config.test_manifest\n                config['train_mode'] = False\n                config['sortagrad'] = False\n                config['batch_size'] = config.get('decode', dict()).get(\n                    'decode_batch_size', 1)\n                config['maxlen_in'] = float('inf')\n                config['maxlen_out'] = float('inf')\n                config['minibatches'] = 0\n                config['mini_batch_size'] = 1\n                config['batch_count'] = 'auto'\n                config['batch_bins'] = 0\n                config['batch_frames_in'] = 0\n                config['batch_frames_out'] = 0\n                config['batch_frames_inout'] = 0\n                config['num_workers'] = 1\n                config['subsampling_factor'] = 1\n                config['num_encs'] = 1\n                config['dist_sampler'] = False\n                config['shortest_first'] = False\n            else:\n                raise KeyError(\n                    \"not valid mode type!!, please input one of 'train, valid, test, align'\"\n                )\n\n            return BatchDataLoader(\n                json_file=config.manifest,\n                train_mode=config.train_mode,\n                sortagrad=config.sortagrad,\n                batch_size=config.batch_size,\n                maxlen_in=config.maxlen_in,\n                maxlen_out=config.maxlen_out,\n                minibatches=config.minibatches,\n                mini_batch_size=config.mini_batch_size,\n                batch_count=config.batch_count,\n                batch_bins=config.batch_bins,\n                batch_frames_in=config.batch_frames_in,\n                batch_frames_out=config.batch_frames_out,\n                batch_frames_inout=config.batch_frames_inout,\n                preprocess_conf=config.preprocess_config,\n                n_iter_processes=config.num_workers,\n                subsampling_factor=config.subsampling_factor,\n                load_aux_output=config.get('load_transcript', None),\n                num_encs=config.num_encs,\n                dist_sampler=config.get('dist_sampler', None),\n                shortest_first=config.shortest_first)\n"
  },
  {
    "path": "paddlespeech/s2t/io/dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nimport jsonlines\nfrom paddle.io import Dataset\n\nfrom paddlespeech.s2t.frontend.utility import read_manifest\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"ManifestDataset\", \"TransformDataset\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass ManifestDataset(Dataset):\n    @classmethod\n    def from_config(cls, config):\n        \"\"\"Build a ManifestDataset object from a config.\n\n        Args:\n            config (yacs.config.CfgNode): configs object.\n\n        Returns:\n            ManifestDataset: dataet object.\n        \"\"\"\n        assert 'manifest' in config\n        assert config.manifest\n\n        dataset = cls(\n            manifest_path=config.manifest,\n            max_input_len=config.max_input_len,\n            min_input_len=config.min_input_len,\n            max_output_len=config.max_output_len,\n            min_output_len=config.min_output_len,\n            max_output_input_ratio=config.max_output_input_ratio,\n            min_output_input_ratio=config.min_output_input_ratio, )\n        return dataset\n\n    def __init__(self,\n                 manifest_path,\n                 max_input_len=float('inf'),\n                 min_input_len=0.0,\n                 max_output_len=float('inf'),\n                 min_output_len=0.0,\n                 max_output_input_ratio=float('inf'),\n                 min_output_input_ratio=0.0):\n        \"\"\"Manifest Dataset\n\n        Args:\n            manifest_path (str): manifest josn file path\n            max_input_len ([type], optional): maximum output seq length,\n                in seconds for raw wav, in frame numbers for feature data. Defaults to float('inf').\n            min_input_len (float, optional): minimum input seq length,\n                in seconds for raw wav, in frame numbers for feature data. Defaults to 0.0.\n            max_output_len (float, optional): maximum input seq length,\n                in modeling units. Defaults to 500.0.\n            min_output_len (float, optional): minimum input seq length,\n                in modeling units. Defaults to 0.0.\n            max_output_input_ratio (float, optional): maximum output seq length/output seq length ratio.\n                Defaults to 10.0.\n            min_output_input_ratio (float, optional): minimum output seq length/output seq length ratio.\n                Defaults to 0.05.\n\n        \"\"\"\n        super().__init__()\n\n        # read manifest\n        self._manifest = read_manifest(\n            manifest_path=manifest_path,\n            max_input_len=max_input_len,\n            min_input_len=min_input_len,\n            max_output_len=max_output_len,\n            min_output_len=min_output_len,\n            max_output_input_ratio=max_output_input_ratio,\n            min_output_input_ratio=min_output_input_ratio)\n        self._manifest.sort(key=lambda x: x[\"input\"][0][\"shape\"][0])\n\n    def __len__(self):\n        return len(self._manifest)\n\n    def __getitem__(self, idx):\n        return self._manifest[idx]\n\n\nclass TransformDataset(Dataset):\n    \"\"\"Transform Dataset.\n\n    Args:\n        data: list object from make_batchset\n        converter: batch function\n        reader: read data\n    \"\"\"\n\n    def __init__(self, data, converter, reader):\n        \"\"\"Init function.\"\"\"\n        super().__init__()\n        self.data = data\n        self.converter = converter\n        self.reader = reader\n\n    def __len__(self):\n        \"\"\"Len function.\"\"\"\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        \"\"\"[] operator.\"\"\"\n        return self.converter([self.reader(self.data[idx], return_uttid=True)])\n\n\nclass AudioDataset(Dataset):\n    def __init__(self,\n                 data_file,\n                 max_length=10240,\n                 min_length=0,\n                 token_max_length=200,\n                 token_min_length=1,\n                 batch_type='static',\n                 batch_size=1,\n                 max_frames_in_batch=0,\n                 sort=True,\n                 raw_wav=True,\n                 stride_ms=10):\n        \"\"\"Dataset for loading audio data.\n        Attributes::\n            data_file: input data file\n                Plain text data file, each line contains following 7 fields,\n                which is split by '\\t':\n                    utt:utt1\n                    feat:tmp/data/file1.wav or feat:tmp/data/fbank.ark:30\n                    feat_shape: 4.95(in seconds) or feat_shape:495,80(495 is in frames)\n                    text:i love you\n                    token: i <space> l o v e <space> y o u\n                    tokenid: int id of this token\n                    token_shape: M,N    # M is the number of token, N is vocab size\n            max_length: drop utterance which is greater than max_length(10ms), unit 10ms.\n            min_length: drop utterance which is less than min_length(10ms), unit 10ms.\n            token_max_length: drop utterance which is greater than token_max_length,\n                especially when use char unit for english modeling\n            token_min_length: drop utterance which is less than token_max_length\n            batch_type: static or dynamic, see max_frames_in_batch(dynamic)\n            batch_size: number of utterances in a batch,\n               it's for static batch size.\n            max_frames_in_batch: max feature frames in a batch,\n               when batch_type is dynamic, it's for dynamic batch size.\n               Then batch_size is ignored, we will keep filling the\n               batch until the total frames in batch up to max_frames_in_batch.\n            sort: whether to sort all data, so the utterance with the same\n               length could be filled in a same batch.\n            raw_wav: use raw wave or extracted featute.\n                if raw wave is used, dynamic waveform-level augmentation could be used\n                and the feature is extracted by torchaudio.\n                if extracted featute(e.g. by kaldi) is used, only feature-level\n                augmentation such as specaug could be used.\n        \"\"\"\n        assert batch_type in ['static', 'dynamic']\n        # read manifest\n        with jsonlines.open(data_file, 'r') as reader:\n            data = list(reader)\n        if sort:\n            data = sorted(data, key=lambda x: x[\"feat_shape\"][0])\n        if raw_wav:\n            path_suffix = data[0]['feat'].split(':')[0].splitext()[-1]\n            assert path_suffix not in ('.ark', '.scp')\n            # m second to n frame\n            data = list(\n                map(lambda x: (float(x['feat_shape'][0]) * 1000 / stride_ms),\n                    data))\n\n        self.input_dim = data[0]['feat_shape'][1]\n        self.output_dim = data[0]['token_shape'][1]\n\n        valid_data = []\n        for i in range(len(data)):\n            length = data[i]['feat_shape'][0]\n            token_length = data[i]['token_shape'][0]\n            # remove too lang or too short utt for both input and output\n            # to prevent from out of memory\n            if length > max_length or length < min_length:\n                pass\n            elif token_length > token_max_length or token_length < token_min_length:\n                pass\n            else:\n                valid_data.append(data[i])\n        logger.info(f\"raw dataset len: {len(data)}\")\n        data = valid_data\n        num_data = len(data)\n        logger.info(f\"dataset len after filter: {num_data}\")\n\n        self.minibatch = []\n        # Dynamic batch size\n        if batch_type == 'dynamic':\n            assert (max_frames_in_batch > 0)\n            self.minibatch.append([])\n            num_frames_in_batch = 0\n            for i in range(num_data):\n                length = data[i]['feat_shape'][0]\n                num_frames_in_batch += length\n                if num_frames_in_batch > max_frames_in_batch:\n                    self.minibatch.append([])\n                    num_frames_in_batch = length\n                self.minibatch[-1].append(data[i])\n        # Static batch size\n        else:\n            cur = 0\n            while cur < num_data:\n                end = min(cur + batch_size, num_data)\n                item = []\n                for i in range(cur, end):\n                    item.append(data[i])\n                self.minibatch.append(item)\n                cur = end\n\n    def __len__(self):\n        \"\"\"number of example(batch)\"\"\"\n        return len(self.minibatch)\n\n    def __getitem__(self, idx):\n        \"\"\"batch example of idx\"\"\"\n        return self.minibatch[idx]\n"
  },
  {
    "path": "paddlespeech/s2t/io/reader.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom collections import OrderedDict\n\nimport io\nimport os\nimport kaldiio\nimport numpy as np\nimport soundfile\nimport h5py\n\nfrom .utility import feat_type\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.s2t.utils.log import Log\n# from paddlespeech.s2t.frontend.augmentor.augmentation import AugmentationPipeline as Transformation\n\n__all__ = [\"LoadInputsAndTargets\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass LoadInputsAndTargets():\n    \"\"\"Create a mini-batch from a list of dicts\n\n    >>> batch = [('utt1',\n    ...           dict(input=[dict(feat='some.ark:123',\n    ...                            filetype='mat',\n    ...                            name='input1',\n    ...                            shape=[100, 80])],\n    ...                output=[dict(tokenid='1 2 3 4',\n    ...                             name='target1',\n    ...                             shape=[4, 31])]]))\n    >>> l = LoadInputsAndTargets()\n    >>> feat, target = l(batch)\n\n    :param: str mode: Specify the task mode, \"asr\" or \"tts\"\n    :param: str preprocess_conf: The path of a json file for pre-processing\n    :param: bool load_input: If False, not to load the input data\n    :param: bool load_output: If False, not to load the output data\n    :param: bool sort_in_input_length: Sort the mini-batch in descending order\n        of the input length\n    :param: bool use_speaker_embedding: Used for tts mode only\n    :param: bool use_second_target: Used for tts mode only\n    :param: dict preprocess_args: Set some optional arguments for preprocessing\n    :param: Optional[dict] preprocess_args: Used for tts mode only\n    \"\"\"\n\n    def __init__(\n            self,\n            mode=\"asr\",\n            preprocess_conf=None,\n            load_input=True,\n            load_output=True,\n            sort_in_input_length=True,\n            preprocess_args=None,\n            keep_all_data_on_mem=False, ):\n        self._loaders = {}\n\n        if mode not in [\"asr\"]:\n            raise ValueError(\"Only asr are allowed: mode={}\".format(mode))\n\n        if preprocess_conf:\n            self.preprocessing = Transformation(preprocess_conf)\n            logger.warning(\n                \"[Experimental feature] Some preprocessing will be done \"\n                \"for the mini-batch creation using {}\".format(\n                    self.preprocessing))\n        else:\n            # If conf doesn't exist, this function don't touch anything.\n            self.preprocessing = None\n\n        self.mode = mode\n        self.load_output = load_output\n        self.load_input = load_input\n        self.sort_in_input_length = sort_in_input_length\n        if preprocess_args:\n            assert isinstance(preprocess_args, dict), type(preprocess_args)\n            self.preprocess_args = dict(preprocess_args)\n        else:\n            self.preprocess_args = {}\n        self.keep_all_data_on_mem = keep_all_data_on_mem\n\n    def __call__(self, batch, return_uttid=False):\n        \"\"\"Function to load inputs and targets from list of dicts\n\n        :param List[Tuple[str, dict]] batch: list of dict which is subset of\n            loaded data.json\n        :param bool return_uttid: return utterance ID information for visualization\n        :return: list of input token id sequences [(L_1), (L_2), ..., (L_B)]\n        :return: list of input feature sequences\n            [(T_1, D), (T_2, D), ..., (T_B, D)]\n        :rtype: list of float ndarray\n        :return: list of target token id sequences [(L_1), (L_2), ..., (L_B)]\n        :rtype: list of int ndarray\n\n        \"\"\"\n        x_feats_dict = OrderedDict()  # OrderedDict[str, List[np.ndarray]]\n        y_feats_dict = OrderedDict()  # OrderedDict[str, List[np.ndarray]]\n        uttid_list = []  # List[str]\n\n        for uttid, info in batch:\n            uttid_list.append(uttid)\n\n            if self.load_input:\n                # Note(kamo): This for-loop is for multiple inputs\n                for idx, inp in enumerate(info[\"input\"]):\n                    # {\"input\":\n                    #  [{\"feat\": \"some/path.h5:F01_050C0101_PED_REAL\",\n                    #    \"filetype\": \"hdf5\",\n                    #    \"name\": \"input1\", ...}], ...}\n                    x = self._get_from_loader(\n                        filepath=inp[\"feat\"],\n                        filetype=inp.get(\"filetype\", \"mat\"))\n                    x_feats_dict.setdefault(inp[\"name\"], []).append(x)\n\n            if self.load_output:\n                for idx, inp in enumerate(info[\"output\"]):\n                    if \"tokenid\" in inp:\n                        # ======= Legacy format for output =======\n                        # {\"output\": [{\"tokenid\": \"1 2 3 4\"}])\n                        x = np.fromiter(\n                            map(int, inp[\"tokenid\"].split()), dtype=np.int64)\n                    else:\n                        # ======= New format =======\n                        # {\"input\":\n                        #  [{\"feat\": \"some/path.h5:F01_050C0101_PED_REAL\",\n                        #    \"filetype\": \"hdf5\",\n                        #    \"name\": \"target1\", ...}], ...}\n                        x = self._get_from_loader(\n                            filepath=inp[\"feat\"],\n                            filetype=inp.get(\"filetype\", \"mat\"))\n\n                    y_feats_dict.setdefault(inp[\"name\"], []).append(x)\n\n        if self.mode == \"asr\":\n            return_batch, uttid_list = self._create_batch_asr(\n                x_feats_dict, y_feats_dict, uttid_list)\n        else:\n            raise NotImplementedError(self.mode)\n\n        if self.preprocessing is not None:\n            # Apply pre-processing all input features\n            for x_name in return_batch.keys():\n                if x_name.startswith(\"input\"):\n                    return_batch[x_name] = self.preprocessing(\n                        return_batch[x_name], uttid_list,\n                        **self.preprocess_args)\n\n        if return_uttid:\n            return tuple(return_batch.values()), uttid_list\n\n        # Doesn't return the names now.\n        return tuple(return_batch.values())\n\n    def _create_batch_asr(self, x_feats_dict, y_feats_dict, uttid_list):\n        \"\"\"Create a OrderedDict for the mini-batch\n\n        :param OrderedDict x_feats_dict:\n            e.g. {\"input1\": [ndarray, ndarray, ...],\n                  \"input2\": [ndarray, ndarray, ...]}\n        :param OrderedDict y_feats_dict:\n            e.g. {\"target1\": [ndarray, ndarray, ...],\n                  \"target2\": [ndarray, ndarray, ...]}\n        :param: List[str] uttid_list:\n            Give uttid_list to sort in the same order as the mini-batch\n        :return: batch, uttid_list\n        :rtype: Tuple[OrderedDict, List[str]]\n        \"\"\"\n        # handle single-input and multi-input (paralell) asr mode\n        xs = list(x_feats_dict.values())\n\n        if self.load_output:\n            ys = list(y_feats_dict.values())\n            assert len(xs[0]) == len(ys[0]), (len(xs[0]), len(ys[0]))\n\n            # get index of non-zero length samples\n            nonzero_idx = list(\n                filter(lambda i: len(ys[0][i]) > 0, range(len(ys[0]))))\n            for n in range(1, len(y_feats_dict)):\n                nonzero_idx = filter(lambda i: len(ys[n][i]) > 0, nonzero_idx)\n        else:\n            # Note(kamo): Be careful not to make nonzero_idx to a generator\n            nonzero_idx = list(range(len(xs[0])))\n\n        if self.sort_in_input_length:\n            # sort in input lengths based on the first input\n            nonzero_sorted_idx = sorted(\n                nonzero_idx, key=lambda i: -len(xs[0][i]))\n        else:\n            nonzero_sorted_idx = nonzero_idx\n\n        if len(nonzero_sorted_idx) != len(xs[0]):\n            logger.warning(\n                \"Target sequences include empty tokenid (batch {} -> {}).\".\n                format(len(xs[0]), len(nonzero_sorted_idx)))\n\n        # remove zero-length samples\n        xs = [[x[i] for i in nonzero_sorted_idx] for x in xs]\n        uttid_list = [uttid_list[i] for i in nonzero_sorted_idx]\n\n        x_names = list(x_feats_dict.keys())\n        if self.load_output:\n            ys = [[y[i] for i in nonzero_sorted_idx] for y in ys]\n            y_names = list(y_feats_dict.keys())\n\n            # Keeping x_name and y_name, e.g. input1, for future extension\n            return_batch = OrderedDict([\n                * [(x_name, x) for x_name, x in zip(x_names, xs)],\n                * [(y_name, y) for y_name, y in zip(y_names, ys)],\n            ])\n        else:\n            return_batch = OrderedDict(\n                [(x_name, x) for x_name, x in zip(x_names, xs)])\n        return return_batch, uttid_list\n\n    def _get_from_loader(self, filepath, filetype):\n        \"\"\"Return ndarray\n\n        In order to make the fds to be opened only at the first referring,\n        the loader are stored in self._loaders\n\n        >>> ndarray = loader.get_from_loader(\n        ...     'some/path.h5:F01_050C0101_PED_REAL', filetype='hdf5')\n\n        :param: str filepath:\n        :param: str filetype:\n        :return:\n        :rtype: np.ndarray\n        \"\"\"\n        if filetype == \"hdf5\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.h5:F01_050C0101_PED_REAL\",\n            #                \"filetype\": \"hdf5\",\n            # -> filepath = \"some/path.h5\", key = \"F01_050C0101_PED_REAL\"\n            filepath, key = filepath.split(\":\", 1)\n\n            loader = self._loaders.get(filepath)\n            if loader is None:\n                # To avoid disk access, create loader only for the first time\n                loader = h5py.File(filepath, \"r\")\n                self._loaders[filepath] = loader\n            return loader[key][()]\n        elif filetype == \"sound.hdf5\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.h5:F01_050C0101_PED_REAL\",\n            #                \"filetype\": \"sound.hdf5\",\n            # -> filepath = \"some/path.h5\", key = \"F01_050C0101_PED_REAL\"\n            filepath, key = filepath.split(\":\", 1)\n\n            loader = self._loaders.get(filepath)\n            if loader is None:\n                # To avoid disk access, create loader only for the first time\n                loader = SoundHDF5File(filepath, \"r\", dtype=\"int16\")\n                self._loaders[filepath] = loader\n            array, rate = loader[key]\n            return array\n        elif filetype == \"sound\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.wav\",\n            #                \"filetype\": \"sound\"},\n            # Assume PCM16\n            if not self.keep_all_data_on_mem:\n                array, _ = soundfile.read(filepath, dtype=\"int16\")\n                return array\n            if filepath not in self._loaders:\n                array, _ = soundfile.read(filepath, dtype=\"int16\")\n                self._loaders[filepath] = array\n            return self._loaders[filepath]\n        elif filetype == \"npz\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.npz:F01_050C0101_PED_REAL\",\n            #                \"filetype\": \"npz\",\n            filepath, key = filepath.split(\":\", 1)\n\n            loader = self._loaders.get(filepath)\n            if loader is None:\n                # To avoid disk access, create loader only for the first time\n                loader = np.load(filepath)\n                self._loaders[filepath] = loader\n            return loader[key]\n        elif filetype == \"npy\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.npy\",\n            #                \"filetype\": \"npy\"},\n            if not self.keep_all_data_on_mem:\n                return np.load(filepath)\n            if filepath not in self._loaders:\n                self._loaders[filepath] = np.load(filepath)\n            return self._loaders[filepath]\n        elif filetype in [\"mat\", \"vec\"]:\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.ark:123\",\n            #                \"filetype\": \"mat\"}]},\n            # In this case, \"123\" indicates the starting points of the matrix\n            # load_mat can load both matrix and vector\n            if not self.keep_all_data_on_mem:\n                return kaldiio.load_mat(filepath)\n            if filepath not in self._loaders:\n                self._loaders[filepath] = kaldiio.load_mat(filepath)\n            return self._loaders[filepath]\n        elif filetype == \"scp\":\n            # e.g.\n            #    {\"input\": [{\"feat\": \"some/path.scp:F01_050C0101_PED_REAL\",\n            #                \"filetype\": \"scp\",\n            filepath, key = filepath.split(\":\", 1)\n            loader = self._loaders.get(filepath)\n            if loader is None:\n                # To avoid disk access, create loader only for the first time\n                loader = kaldiio.load_scp(filepath)\n                self._loaders[filepath] = loader\n            return loader[key]\n        else:\n            raise NotImplementedError(\n                \"Not supported: loader_type={}\".format(filetype))\n\n    def file_type(self, filepath):\n        return feat_type(filepath)\n\n\nclass SoundHDF5File():\n    \"\"\"Collecting sound files to a HDF5 file\n\n    >>> f = SoundHDF5File('a.flac.h5', mode='a')\n    >>> array = np.random.randint(0, 100, 100, dtype=np.int16)\n    >>> f['id'] = (array, 16000)\n    >>> array, rate = f['id']\n\n\n    :param: str filepath:\n    :param: str mode:\n    :param: str format: The type used when saving wav. flac, nist, htk, etc.\n    :param: str dtype:\n\n    \"\"\"\n\n    def __init__(self,\n                 filepath,\n                 mode=\"r+\",\n                 format=None,\n                 dtype=\"int16\",\n                 **kwargs):\n        self.filepath = filepath\n        self.mode = mode\n        self.dtype = dtype\n\n        self.file = h5py.File(filepath, mode, **kwargs)\n        if format is None:\n            # filepath = a.flac.h5 -> format = flac\n            second_ext = os.path.splitext(os.path.splitext(filepath)[0])[1]\n            format = second_ext[1:]\n            if format.upper() not in soundfile.available_formats():\n                # If not found, flac is selected\n                format = \"flac\"\n\n        # This format affects only saving\n        self.format = format\n\n    def __repr__(self):\n        return '<SoundHDF5 file \"{}\" (mode {}, format {}, type {})>'.format(\n            self.filepath, self.mode, self.format, self.dtype)\n\n    def create_dataset(self, name, shape=None, data=None, **kwds):\n        f = io.BytesIO()\n        array, rate = data\n        soundfile.write(f, array, rate, format=self.format)\n        self.file.create_dataset(\n            name, shape=shape, data=np.void(f.getvalue()), **kwds)\n\n    def __setitem__(self, name, data):\n        self.create_dataset(name, data=data)\n\n    def __getitem__(self, key):\n        data = self.file[key][()]\n        f = io.BytesIO(data.tobytes())\n        array, rate = soundfile.read(f, dtype=self.dtype)\n        return array, rate\n\n    def keys(self):\n        return self.file.keys()\n\n    def values(self):\n        for k in self.file:\n            yield self[k]\n\n    def items(self):\n        for k in self.file:\n            yield k, self[k]\n\n    def __iter__(self):\n        return iter(self.file)\n\n    def __contains__(self, item):\n        return item in self.file\n\n    def __len__(self):\n        return len(self.file)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.file.close()\n\n    def close(self):\n        self.file.close()\n"
  },
  {
    "path": "paddlespeech/s2t/io/sampler.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport numpy as np\nfrom paddle import distributed as dist\nfrom paddle.io import BatchSampler\nfrom paddle.io import DistributedBatchSampler\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"SortagradDistributedBatchSampler\",\n    \"SortagradBatchSampler\",\n]\n\n\ndef _batch_shuffle(indices, batch_size, epoch, clipped=False):\n    \"\"\"Put similarly-sized instances into minibatches for better efficiency\n    and make a batch-wise shuffle.\n\n    1. Sort the audio clips by duration.\n    2. Generate a random number `k`, k in [0, batch_size).\n    3. Randomly shift `k` instances in order to create different batches\n        for different epochs. Create minibatches.\n    4. Shuffle the minibatches.\n\n    :param indices: indexes. List of int.\n    :type indices: list\n    :param batch_size: Batch size. This size is also used for generate\n                        a random number for batch shuffle.\n    :type batch_size: int\n    :param clipped: Whether to clip the heading (small shift) and trailing\n                    (incomplete batch) instances.\n    :type clipped: bool\n    :return: Batch shuffled mainifest.\n    :rtype: list\n    \"\"\"\n    rng = np.random.RandomState(epoch)\n    shift_len = rng.randint(0, batch_size - 1)\n    batch_indices = list(zip(* [iter(indices[shift_len:])] * batch_size))\n    rng.shuffle(batch_indices)\n    batch_indices = [item for batch in batch_indices for item in batch]\n    assert clipped is False\n    if not clipped:\n        res_len = len(indices) - shift_len - len(batch_indices)\n        # when res_len is 0, will return whole list, len(List[-0:]) = len(List[:])\n        if res_len != 0:\n            batch_indices.extend(indices[-res_len:])\n        batch_indices.extend(indices[0:shift_len])\n        assert len(indices) == len(\n            batch_indices\n        ), f\"_batch_shuffle: {len(indices)} : {len(batch_indices)} : {res_len} - {shift_len}\"\n    return batch_indices\n\n\nclass SortagradDistributedBatchSampler(DistributedBatchSampler):\n    def __init__(self,\n                 dataset,\n                 batch_size,\n                 num_replicas=None,\n                 rank=None,\n                 shuffle=False,\n                 drop_last=False,\n                 sortagrad=False,\n                 shuffle_method=\"batch_shuffle\"):\n        \"\"\"Sortagrad Sampler for multi gpus.\n\n        Args:\n            dataset (paddle.io.Dataset): \n            batch_size (int): batch size for one gpu\n            num_replicas (int, optional): world size or numbers of gpus. Defaults to None.\n            rank (int, optional): rank id. Defaults to None.\n            shuffle (bool, optional): True for do shuffle, or else. Defaults to False.\n            drop_last (bool, optional): whether drop last batch which is less than batch size. Defaults to False.\n            sortagrad (bool, optional): True, do sortgrad in first epoch, then shuffle as usual; or else. Defaults to False.\n            shuffle_method (str, optional): shuffle method, \"instance_shuffle\" or \"batch_shuffle\". Defaults to \"batch_shuffle\".\n        \"\"\"\n        super().__init__(dataset, batch_size, num_replicas, rank, shuffle,\n                         drop_last)\n        self._sortagrad = sortagrad\n        self._shuffle_method = shuffle_method\n\n    def __iter__(self):\n        num_samples = len(self.dataset)\n        indices = np.arange(num_samples).tolist()\n        indices += indices[:(self.total_size - len(indices))]\n        assert len(indices) == self.total_size\n\n        # sort (by duration) or batch-wise shuffle the manifest\n        if self.shuffle:\n            if self.epoch == 0 and self._sortagrad:\n                logger.info(\n                    f'rank: {dist.get_rank()} dataset sortagrad! epoch {self.epoch}'\n                )\n            else:\n                logger.info(\n                    f'rank: {dist.get_rank()} dataset shuffle! epoch {self.epoch}'\n                )\n                if self._shuffle_method == \"batch_shuffle\":\n                    # using `batch_size * nrank`, or will cause instability loss and nan or inf grad, \n                    # since diff batch examlpe length in batches case instability loss in diff rank, \n                    # e.g. rank0 maxlength 20, rank3 maxlength 1000\n                    indices = _batch_shuffle(\n                        indices,\n                        self.batch_size * self.nranks,\n                        self.epoch,\n                        clipped=False)\n                elif self._shuffle_method == \"instance_shuffle\":\n                    np.random.RandomState(self.epoch).shuffle(indices)\n                else:\n                    raise ValueError(\"Unknown shuffle method %s.\" %\n                                     self._shuffle_method)\n        assert len(\n            indices\n        ) == self.total_size, f\"batch shuffle examples error: {len(indices)} : {self.total_size}\"\n\n        # slice `self.batch_size` examples by rank id\n        def _get_indices_by_batch_size(indices):\n            subsampled_indices = []\n            last_batch_size = self.total_size % (self.batch_size * self.nranks)\n            assert last_batch_size % self.nranks == 0\n            last_local_batch_size = last_batch_size // self.nranks\n\n            for i in range(self.local_rank * self.batch_size,\n                           len(indices) - last_batch_size,\n                           self.batch_size * self.nranks):\n                subsampled_indices.extend(indices[i:i + self.batch_size])\n\n            indices = indices[len(indices) - last_batch_size:]\n            subsampled_indices.extend(\n                indices[self.local_rank * last_local_batch_size:(\n                    self.local_rank + 1) * last_local_batch_size])\n            return subsampled_indices\n\n        if self.nranks > 1:\n            indices = _get_indices_by_batch_size(indices)\n\n        assert len(indices) == self.num_samples\n        _sample_iter = iter(indices)\n\n        batch_indices = []\n        for idx in _sample_iter:\n            batch_indices.append(idx)\n            if len(batch_indices) == self.batch_size:\n                logger.debug(\n                    f\"rank: {dist.get_rank()} batch index: {batch_indices} \")\n                yield batch_indices\n                batch_indices = []\n        if not self.drop_last and len(batch_indices) > 0:\n            yield batch_indices\n\n    def __len__(self):\n        num_samples = self.num_samples\n        num_samples += int(not self.drop_last) * (self.batch_size - 1)\n        return num_samples // self.batch_size\n\n\nclass SortagradBatchSampler(BatchSampler):\n    def __init__(self,\n                 dataset,\n                 batch_size,\n                 shuffle=False,\n                 drop_last=False,\n                 sortagrad=False,\n                 shuffle_method=\"batch_shuffle\"):\n        \"\"\"Sortagrad Sampler for one gpu.\n\n        Args:\n            dataset (paddle.io.Dataset): \n            batch_size (int): batch size for one gpu\n            shuffle (bool, optional): True for do shuffle, or else. Defaults to False.\n            drop_last (bool, optional): whether drop last batch which is less than batch size. Defaults to False.\n            sortagrad (bool, optional): True, do sortgrad in first epoch, then shuffle as usual; or else. Defaults to False.\n            shuffle_method (str, optional): shuffle method, \"instance_shuffle\" or \"batch_shuffle\". Defaults to \"batch_shuffle\".\n        \"\"\"\n        self.dataset = dataset\n\n        assert isinstance(batch_size, int) and batch_size > 0, \\\n            \"batch_size should be a positive integer\"\n        self.batch_size = batch_size\n        assert isinstance(shuffle, bool), \\\n            \"shuffle should be a boolean value\"\n        self.shuffle = shuffle\n        assert isinstance(drop_last, bool), \\\n            \"drop_last should be a boolean number\"\n\n        self.drop_last = drop_last\n        self.epoch = 0\n        self.num_samples = int(math.ceil(len(self.dataset) * 1.0))\n        self.total_size = self.num_samples\n        self._sortagrad = sortagrad\n        self._shuffle_method = shuffle_method\n\n    def __iter__(self):\n        num_samples = len(self.dataset)\n        indices = np.arange(num_samples).tolist()\n        indices += indices[:(self.total_size - len(indices))]\n        assert len(indices) == self.total_size\n\n        # sort (by duration) or batch-wise shuffle the manifest\n        if self.shuffle:\n            if self.epoch == 0 and self._sortagrad:\n                logger.info(f'dataset sortagrad! epoch {self.epoch}')\n            else:\n                logger.info(f'dataset shuffle! epoch {self.epoch}')\n                if self._shuffle_method == \"batch_shuffle\":\n                    indices = _batch_shuffle(\n                        indices, self.batch_size, self.epoch, clipped=False)\n                elif self._shuffle_method == \"instance_shuffle\":\n                    np.random.RandomState(self.epoch).shuffle(indices)\n                else:\n                    raise ValueError(\"Unknown shuffle method %s.\" %\n                                     self._shuffle_method)\n        assert len(\n            indices\n        ) == self.total_size, f\"batch shuffle examples error: {len(indices)} : {self.total_size}\"\n\n        assert len(indices) == self.num_samples\n        _sample_iter = iter(indices)\n\n        batch_indices = []\n        for idx in _sample_iter:\n            batch_indices.append(idx)\n            if len(batch_indices) == self.batch_size:\n                logger.debug(\n                    f\"rank: {dist.get_rank()} batch index: {batch_indices} \")\n                yield batch_indices\n                batch_indices = []\n        if not self.drop_last and len(batch_indices) > 0:\n            yield batch_indices\n\n        self.epoch += 1\n\n    def __len__(self):\n        num_samples = self.num_samples\n        num_samples += int(not self.drop_last) * (self.batch_size - 1)\n        return num_samples // self.batch_size\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/batch.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/dataio/batch.py)\n\"\"\"Batch collation\n\nAuthors\n  * Aku Rouhe 2020\n\"\"\"\nimport collections\n\nimport paddle\n\nfrom paddlespeech.s2t.io.speechbrain.data_utils import batch_pad_right\nfrom paddlespeech.s2t.io.speechbrain.data_utils import mod_default_collate\n\nPaddedData = collections.namedtuple(\"PaddedData\", [\"data\", \"lengths\"])\n\n\nclass PaddedBatch:\n    \"\"\"Collate_fn when examples are dicts and have variable-length sequences.\n\n    Different elements in the examples get matched by key.\n    All numpy tensors get converted to paddle.Tensor \n    Then, by default, all paddle.Tensor valued elements get padded and support\n    collective pin_memory() and to() calls.\n    Regular Python data types are just collected in a list.\n\n    Arguments\n    ---------\n    examples : list\n        List of example dicts, as produced by Dataloader.\n    padded_keys : list, None\n        (Optional) List of keys to pad on. If None, pad all paddle.Tensors\n    device_prep_keys : list, None\n        (Optional) Only these keys participate in collective memory pinning and moving with\n        to().\n        If None, defaults to all items with paddle.Tensor values.\n    padding_func : callable, optional\n        Called with a list of tensors to be padded together. Needs to return\n        two tensors: the padded data, and another tensor for the data lengths.\n    padding_kwargs : dict\n        (Optional) Extra kwargs to pass to padding_func. E.G. mode, value\n    nonpadded_stack : bool\n        Whether to apply Tensor stacking on values that didn't get padded. \n        This stacks if it can, but doesn't error out if it cannot. \n        Default:True, usually does the right thing.\n    \"\"\"\n\n    def __init__(\n            self,\n            examples,\n            padded_keys=None,\n            device_prep_keys=None,\n            padding_func=batch_pad_right,\n            padding_kwargs={},\n            nonpadded_stack=True, ):\n        self.__length = len(examples)\n        self.__keys = list(examples[0].keys())\n        self.__padded_keys = []\n        self.__device_prep_keys = []\n        for key in self.__keys:\n            values = [example[key] for example in examples]\n            # Default convert usually does the right thing (numpy2tensor etc.)\n            values = paddle.to_tensor(values)\n\n            if (padded_keys is not None and key in padded_keys) or (\n                    padded_keys is None and\n                    isinstance(values[0], paddle.Tensor)):\n                # Padding and PaddedData\n                self.__padded_keys.append(key)\n                padded = PaddedData(*padding_func(values, **padding_kwargs))\n                setattr(self, key, padded)\n            else:\n                if nonpadded_stack:\n                    values = mod_default_collate(values)\n                setattr(self, key, values)\n            if (device_prep_keys is not None and key in device_prep_keys) or (\n                    device_prep_keys is None and\n                    isinstance(values[0], paddle.Tensor)):\n                self.__device_prep_keys.append(key)\n\n    def __len__(self):\n        return self.__length\n\n    def __getitem__(self, key):\n        if key in self.__keys:\n            return getattr(self, key)\n        else:\n            raise KeyError(f\"Batch doesn't have key: {key}\")\n\n    def __iter__(self):\n        \"\"\"Iterates over the different elements of the batch.\n        \"\"\"\n        return iter((getattr(self, key) for key in self.__keys))\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/data_pipeline.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/utils/data_pipeline.py)\n\"\"\"A pipeline for data transformations.\n\nAuthor:\n    * Aku Rouhe\n\"\"\"\nimport inspect\nfrom dataclasses import dataclass\n\nfrom paddlespeech.s2t.io.speechbrain.depgraph import DependencyGraph\n\n\n@dataclass\nclass StaticItem:\n    \"\"\"Data class that represents a static item.\n\n    Static items are in-memory items so they don't need to be computed\n    dynamically.\n    \"\"\"\n\n    key: str\n\n\nclass DynamicItem:\n    \"\"\"Essentially represents a data transformation function.\n\n    A DynamicItem takes some arguments and computes its value dynamically when\n    called. A straight-forward use-case is to load something from disk\n    dynamically; take the path and provide the loaded data.\n\n    Instances of this class are often created implicitly via the\n    @takes and @provides decorators or otherwise from specifying the taken and\n    provided arguments and the function.\n\n    A counterpart is the GeneratorDynamicItem, which should be used for\n    generator functions.\n\n    Arguments\n    ---------\n    takes : list\n        The keys of the items that this needs to compute its output.\n    func : callable\n        The function that is used to compute the output.\n    provides : list\n        The keys that this provides.\n    \"\"\"\n\n    def __init__(self, takes=[], func=None, provides=[]):\n        self.takes = takes\n        self.func = func\n        self.provides = provides\n\n    def __call__(self, *args):\n        return self.func(*args)\n\n    # The next methods are more about supporting GeneratorDynamicItems\n    def next_takes(self):\n        \"\"\"The next argkeys to provide to this, when called.\"\"\"\n        # Regular function DynamicItems always just need the same set of args\n        return self.takes\n\n    def next_provides(self):\n        \"\"\"The next keys that this provides, when called.\"\"\"\n        # Regular function DynamicItems always just provide the same set of keys\n        return self.provides\n\n    def provided_in_order(self):\n        \"\"\"Assuming that this may need to be called multiple times; which keys\n        does it provide at that call. Returns a list, with len equal to the\n        number of times that this may be called.\"\"\"\n        # Regular function DynamicItems are only called once:\n        return [self.provides]\n\n    def reset(self):\n        \"\"\"Signals that this will not be called any more times on this pipeline\n        call.\"\"\"\n        # Regular function DynamicItems don't need special resets.\n        pass\n\n\nclass GeneratorDynamicItem(DynamicItem):\n    \"\"\"Essentially represents a multi-step data transformation.\n\n    This is the generator function counterpart for DynamicItem (which should be\n    used for regular functions).\n\n    A GeneratorDynamicItem first takes some arguments and then uses those in\n    multiple steps to incrementally compute some values when called.\n\n    A typical use-case is a pipeline of transformations on data: e.g. taking in\n    text as a string, and first a tokenized version, and then on the second\n    call providing an integer-encoded version. This can be used even though the\n    integer-encoder needs to be trained on the first outputs.\n\n    The main benefit is to be able to define the pipeline in a clear function,\n    even if parts of the pipeline depend on others for their initialization.\n\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        # Doesn't generate electricity, only stores the currently active\n        # generator:\n        self.current_generator = None\n        self.num_provided_items = 0\n\n    def __call__(self, *args):\n        if self.num_provided_items == len(self.provides):\n            raise RuntimeError(\"DynamicItemPipeline called too many times!\")\n        if not self.current_generator:\n            self.current_generator = self.func(*args)\n        # NOTE: Not supporting sending new values to the pipeline.\n        out = next(self.current_generator)\n        self.num_provided_items += 1\n        return out\n\n    def next_takes(self):\n        \"\"\"The next argkeys to provide to this, when called.\"\"\"\n        if not self.current_generator:\n            return self.takes\n        else:\n            return []\n\n    def next_provides(self):\n        \"\"\"The next keys that this provides, when called.\"\"\"\n        keys = self.provides[self.num_provided_items]\n        # Support multiple yielded values like:\n        # @yields(\"wav_read\", [\"left_ch\", \"right_ch\"])\n        if isinstance(keys, str):\n            return [keys]\n        else:\n            return keys\n\n    def provided_in_order(self):\n        \"\"\"Assuming that this may need to be called multiple times; which keys\n        does it provide at that call. Returns a list, with len equal to the\n        number of times that this may be called.\"\"\"\n        in_order = []\n        for keys in self.provides:\n            # Support multiple yielded values like:\n            # @provides(\"wav_read\", [\"left_ch\", \"right_ch\"])\n            if isinstance(keys, str):\n                in_order.append([keys])\n            else:\n                in_order.append(keys)\n        return in_order\n\n    def reset(self):\n        \"\"\"Signals that this will not be called any more times on this pipeline\n        call.\"\"\"\n        if self.current_generator is not None:\n            self.current_generator.close()\n        self.current_generator = None\n        self.num_provided_items = 0\n\n\ndef takes(*argkeys):\n    \"\"\"Decorator which makes a DynamicItem and specifies its argkeys.\n\n    If the wrapped object is a generator function (has a yield statement),\n    Creates a GeneratorDynamicItem. If the object is already a DynamicItem,\n    just specifies the argkeys for that. Otherwise creates a new regular\n    DynamicItem, with argkeys specified.\n\n    The args are always passed to the function at the start. Generators could\n    support sending new arguments, but for such use cases, simply create a new\n    dynamic item. The GeneratorDynamicItem class is meant for pipelines which\n    take in an input and transform it in multiple ways, where the intermediate\n    representations may be needed for e.g. fitting a BPE segmenter.\n\n    Example\n    -------\n    >>> @takes(\"text\")\n    ... def tokenize(text):\n    ...     return text.strip().lower().split()\n    >>> tokenize.provides = [\"tokenized\"]\n    >>> tokenize('\\tThis Example gets tokenized')\n    ['this', 'example', 'gets', 'tokenized']\n    \"\"\"\n\n    def decorator(obj):\n        \"\"\"Decorator definition.\"\"\"\n        if isinstance(obj, DynamicItem):\n            if obj.takes:\n                raise ValueError(\"Can't overwrite DynamicItem.takes\")\n            obj.takes = argkeys\n            return obj\n        elif inspect.isgeneratorfunction(obj):\n            return GeneratorDynamicItem(takes=argkeys, func=obj)\n        else:\n            return DynamicItem(takes=argkeys, func=obj)\n\n    return decorator\n\n\ntakes_decorator = takes  # Just for DataPipeline.add_dynamic_item\n\n\ndef provides(*output_keys):\n    \"\"\"Decorator which makes a DynamicItem and specifies what keys it provides.\n\n    If the wrapped object is a generator function (has a yield statement),\n    Creates a GeneratorDynamicItem. If the object is already a DynamicItem,\n    just specifies the provided keys for that. Otherwise creates a new regular\n    DynamicItem, with provided keys specified.\n\n    NOTE\n    ----\n    The behavior is slightly different for generators and regular functions, if\n    many output keys are specified, e.g. @provides(\"signal\", \"mfcc\"). Regular\n    functions should return a tuple with len equal to len(output_keys), while\n    generators should yield the items one by one.\n\n    >>> @provides(\"signal\", \"feat\")\n    ... def read_feat():\n    ...     wav = [.1,.2,-.1]\n    ...     feat = [s**2 for s in wav]\n    ...     return wav, feat\n    >>> @provides(\"signal\", \"feat\")\n    ... def read_feat():\n    ...     wav = [.1,.2,-.1]\n    ...     yield wav\n    ...     feat = [s**2 for s in wav]\n    ...     yield feat\n\n    If multiple keys are yielded at once, write e.g.,\n\n    >>> @provides(\"wav_read\", [\"left_channel\", \"right_channel\"])\n    ... def read_multi_channel():\n    ...     wav = [[.1,.2,-.1],[.2,.1,-.1]]\n    ...     yield wav\n    ...     yield wav[0], wav[1]\n\n    \"\"\"\n\n    def decorator(obj):\n        \"\"\"Decorator definition.\"\"\"\n        if isinstance(obj, DynamicItem):\n            if obj.provides:\n                raise ValueError(\"Can't overwrite DynamicItem provides-list.\")\n            obj.provides = output_keys\n            return obj\n        elif inspect.isgeneratorfunction(obj):\n            return GeneratorDynamicItem(func=obj, provides=output_keys)\n        else:\n            return DynamicItem(func=obj, provides=output_keys)\n\n    return decorator\n\n\nprovides_decorator = provides  # Just for DataPipeline.add_dynamic_item\n\n\nclass DataPipeline:\n    \"\"\"Organises data transformations into a pipeline.\n\n    Example\n    -------\n    >>> pipeline = DataPipeline(\n    ...     static_data_keys=[\"text\"],\n    ...     dynamic_items=[\n    ...     {\"func\": lambda x: x.lower(), \"takes\": \"text\", \"provides\": \"foo\"},\n    ...     {\"func\": lambda x: x[::-1], \"takes\": \"foo\", \"provides\": \"bar\"},\n    ...     ],\n    ...     output_keys=[\"bar\"],\n    ... )\n    >>> pipeline({\"text\": \"Test\"})\n    {'bar': 'tset'}\n    \"\"\"\n\n    def __init__(self, static_data_keys, dynamic_items=[], output_keys=[]):\n        self.dg = DependencyGraph()\n        self._exec_order = None\n        self.key_to_node = {}\n        self.unaccounted_keys = {}\n        self.dynamic_items = []\n        self.output_mapping = {}\n        self.add_static_keys(static_data_keys)\n        self.add_dynamic_items(dynamic_items)\n        self.set_output_keys(output_keys)\n\n    def add_static_keys(self, static_keys):\n        \"\"\"Informs the pipeline about static items.\n\n        Static items are the ones provided to __call__ as data.\n        \"\"\"\n        for key in static_keys:\n            node_id = self.dg.add_node(data=StaticItem(key=key))\n            self.key_to_node[key] = node_id\n\n    def add_dynamic_items(self, dynamic_items):\n        \"\"\"Add multiple dynamic items at once.\"\"\"\n        for item in dynamic_items:\n            try:\n                self.add_dynamic_item(**item)\n            except TypeError:\n                self.add_dynamic_item(item)\n\n    def add_dynamic_item(self, func, takes=None, provides=None):\n        \"\"\"Adds a dynamic item to the Pipeline.\n\n        Two calling conventions. For DynamicItem objects, just use:\n        add_dynamic_item(dynamic_item)\n        But otherwise, should use:\n        add_dynamic_item(func, takes, provides)\n\n        Arguments\n        ---------\n        func : callable, DynamicItem\n            If a DynamicItem is given, adds that directly. Otherwise a\n            DynamicItem is created, and this specifies the callable to use. If\n            a generator function is given, then create a GeneratorDynamicItem.\n            Otherwise creates a normal DynamicItem.\n        takes : list, str\n            List of keys. When func is called, each key is resolved to\n            either an entry in the data or the output of another dynamic_item.\n            The func is then called with these as positional arguments,\n            in the same order as specified here.\n            A single key can be given as a bare string.\n        provides : str, list\n            For regular functions, the key or list of keys that it provides.\n            If you give a generator function, key or list of keys that it\n            yields, in order. Also see the provides decorator.\n            A single key can be given as a bare string.\n        \"\"\"\n        if isinstance(func, DynamicItem):\n            if takes is not None or provides is not None:\n                raise ValueError(\"If providing a DynamicItem directly, don't \"\n                                 \"specify takes or provides\")\n            else:\n                self._add_dynamic_item_object(func)\n                return\n        if isinstance(takes, str):\n            takes = [takes]\n        if isinstance(provides, str):\n            provides = [provides]\n        di = takes_decorator(*takes)(provides_decorator(*provides)(func))\n        self._add_dynamic_item_object(di)\n\n    def _add_dynamic_item_object(self, obj):\n        \"\"\"Internally adds the object.\n\n        There is a node in the dependency graph for each call of the\n        DynamicItem. Each call may return multiple keys and depend on multiple\n        keys. An internal dict maps key to the id of the node that produces it.\n        \"\"\"\n        if not obj.provides:\n            raise ValueError(\"Won't add redundant dynamic item which doesn't \"\n                             \"provide anything.\")\n        depended = []\n        for key in obj.takes:\n            # Might not be accounted for, yet:\n            if key not in self.key_to_node:\n                dependee_keys = self.unaccounted_keys.setdefault(key, [])\n                dependee_keys.extend(obj.next_provides())\n            else:\n                depended.append(self.key_to_node[key])\n        for provided in obj.provided_in_order():\n            node_id = self.dg.add_node(data=obj)\n            for key in provided:\n                self.key_to_node[key] = node_id\n                # This key may also be unaccounted for, so account for it now:\n                if key in self.unaccounted_keys:\n                    for dependee_key in self.unaccounted_keys[key]:\n                        dependee_node = self.key_to_node[dependee_key]\n                        self.dg.add_edge(dependee_node, node_id)\n                    del self.unaccounted_keys[key]  # Now accounted for!\n            for dep_id in depended:\n                self.dg.add_edge(node_id, dep_id)\n            # Next call will depend on this call:\n            depended = [node_id]\n        # Keep a reference to the item in this object, as well:\n        self.dynamic_items.append(obj)\n\n    def set_output_keys(self, keys):\n        \"\"\"Use this to change the output keys.\n\n        Also re-evaluates execution order.\n        So if you request different outputs, some parts of the\n        data pipeline may be skipped.\n\n        Arguments\n        ---------\n        keys : dict, list, None\n            List of keys (str) to produce in output.\n\n            If a dict is given; it is used to map internal keys to output keys.\n            From the output_keys dict key:value pairs the key appears outside,\n            and value is the internal key.\n        \"\"\"\n        self.output_mapping = self._output_keys_to_mapping(keys)\n        self._exec_order = None\n\n    @staticmethod\n    def _output_keys_to_mapping(keys):\n        # Ensure a mapping (accept a list for convenience, too)\n        if keys is None:\n            output_mapping = {}\n        elif isinstance(keys, dict):\n            output_mapping = keys\n        else:\n            output_mapping = {key: key for key in keys}\n        return output_mapping\n\n    def compute_outputs(self, data):\n        \"\"\"\n        Arguments\n        ---------\n        data : dict\n            Dictionary with data entries by key.\n\n        Returns\n        -------\n        dict\n            With the keys that were set.\n        \"\"\"\n        if self._exec_order is None:\n            self._prepare_run(data)\n        return self._compute(data, self._exec_order, self.output_mapping)\n\n    def compute_specific(self, keys, data):\n        \"\"\"Compute output of specific item, without changing output_keys.\"\"\"\n        output_mapping = self._output_keys_to_mapping(keys)\n        order = self.dg.get_evaluation_order(\n            selected_keys=self.get_selected_node_ids(keys))\n        return self._compute(data, order, output_mapping)\n\n    def _compute(self, data, order, output_mapping):\n        if self.unaccounted_keys:\n            MSG = \"These keys are still unaccounted for in the data pipeline: \"\n            MSG += \", \".join(self.unaccounted_keys)\n            raise RuntimeError(MSG)\n        intermediate = {}\n        for node_id, edges, item in order:\n            if isinstance(item, StaticItem):\n                # Static item in data.\n                # Just check that key is found.\n                try:\n                    data[item.key]\n                    continue\n                except KeyError:\n                    raise KeyError(f\"Expected key {item.key} in data!\")\n            # A dynamic item, which we should compute:\n            args = [\n                data[argkey] if argkey in data else intermediate[argkey]\n                for argkey in item.next_takes()\n            ]\n            # This needs to be called BEFORE the dynamic item is called.\n            provided_keys = item.next_provides()\n            values = item(*args)  # Call the DynamicItem to produce output\n            # If there is just one output value, wrap in a list so that\n            # it can be zipped as well:\n            if len(provided_keys) == 1:\n                values = [values]\n            intermediate.update(zip(provided_keys, values))\n        for dynamic_item in self.dynamic_items:\n            dynamic_item.reset()\n        return {\n            outkey: data[inkey] if inkey in data else intermediate[inkey]\n            for outkey, inkey in output_mapping.items()\n        }\n\n    def get_selected_node_ids(self, selected_keys):\n        \"\"\"Translates selected keys to dependency graph keys.\"\"\"\n        return [self.key_to_node[key] for key in selected_keys]\n\n    def __call__(self, data):\n        return self.compute_outputs(data)\n\n    def _prepare_run(self, data):\n        self._exec_order = list(\n            self.dg.get_evaluation_order(\n                self.get_selected_node_ids(self.output_mapping.values())))\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/data_utils.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/utils/data_utils.py)\nimport collections.abc\nimport csv\nimport os\nimport pathlib\nimport re\nimport shutil\nimport urllib.request\n\nimport numpy as np\nimport paddle\nimport tqdm\n\n\ndef batch_pad_right(array: list, mode=\"constant\", value=0):\n    \"\"\"Given a list of paddle tensors it batches them together by padding to the right\n    on each dimension in order to get same length for all.\n\n    Parameters\n    ----------\n    array : list\n        List of tensor we wish to pad together.\n    mode : str\n        Padding mode see numpy.pad documentation.\n    value : float\n        Padding value see numpy.pad documentation.\n\n    Returns\n    -------\n    batched : numpy array\n        Padded numpy array.\n    valid_vals : list\n        List containing proportion for each dimension of original, non-padded values.\n\n    \"\"\"\n\n    if not len(array):\n        raise IndexError(\"Tensors list must not be empty\")\n\n    if len(array) == 1:\n        # if there is only one tensor in the batch we simply unsqueeze it.\n        return np.expand_dims(array[0], 0), np.array([1.0], dtype=\"float32\")\n    if not (any(\n        [array[i].ndim == array[0].ndim for i in range(1, len(array))])):\n        raise IndexError(\"All array must have same number of dimensions\")\n\n    # FIXME we limit the support here: we allow padding of only the first dimension\n    # need to remove this when feat extraction is updated to handle multichannel.\n    max_shape = []\n    for dim in range(array[0].ndim):\n        if dim != 0:\n            if not all(\n                [x.shape[dim] == array[0].shape[dim] for x in array[1:]]):\n                raise EnvironmentError(\n                    \"Tensors should have same dimensions except for the first one\"\n                )\n        max_shape.append(max([x.shape[dim] for x in array]))\n\n    batched = []\n    valid = []\n    for t in array:\n        # for each tensor we apply pad_right_to\n        padded, valid_percent = pad_right_to(\n            t, max_shape, mode=mode, value=value)\n        batched.append(padded)\n        valid.append(valid_percent[0])\n\n    batched = np.stack(batched)\n\n    return batched, np.array(valid, dtype=\"float32\")\n\n\nnp_str_obj_array_pattern = re.compile(r\"[SaUO]\")\n\n\ndef pad_right_to(\n        array: np.ndarray,\n        target_shape: (list, tuple),\n        mode=\"constant\",\n        value=0, ):\n    \"\"\"\n    This function takes a numpy of arbitrary shape and pads it to target\n    shape by appending values on the right.\n\n    Parameters\n    ----------\n    array : input numpy array\n        Input tensor whose dimension we need to pad.\n    target_shape : (list, tuple)\n        Target shape we want for the target tensor its len must be equal to tensor.ndim\n    mode : str\n        Pad mode, please refer to numpy.pad documentation.\n    value : float\n        Pad value, please refer to numpy.pad documentation.\n\n    Returns\n    -------\n    array : numpy array\n        Padded numpy array.\n    valid_vals : list\n        List containing proportion for each dimension of original, non-padded values.\n    \"\"\"\n    assert len(target_shape) == array.ndim\n    pads = []  # this contains the abs length of the padding for each dimension.\n    valid_vals = []  # this contains the relative lengths for each dimension.\n    i = len(target_shape) - 1  # iterating over target_shape ndims\n    j = 0\n    while i >= 0:\n        assert (target_shape[i] >= array.shape[i]\n                ), \"Target shape must be >= original shape for every dim\"\n        pads.extend([0, target_shape[i] - array.shape[i]])\n        valid_vals.append(array.shape[j] / target_shape[j])\n        i -= 1\n        j += 1\n    array = np.pad(array, pads, mode, constant_values=(value, value))\n\n    return array, valid_vals\n\n\ndef mod_default_collate(batch):\n    \"\"\"Makes a tensor from list of batch values.\n\n    Note that this doesn't need to zip(*) values together\n    as PaddedBatch connects them already (by key).\n\n    Here the idea is not to error out.\n    \"\"\"\n    elem = batch[0]\n    elem_type = type(elem)\n    if isinstance(elem, paddle.Tensor):\n        out = None\n        try:\n            if paddle.io.get_worker_info() is not None:\n\n                # If we're in a background process, concatenate directly into a\n                # shared memory tensor to avoid an extra copy\n                numel = sum([x.numel() for x in batch])\n                storage = elem.storage()._new_shared(numel)\n                out = elem.new(storage)\n            return paddle.stack(batch, 0, name=out)\n        except RuntimeError:  # Unequal size:\n            return batch\n    elif (elem_type.__module__ == \"numpy\" and elem_type.__name__ != \"str_\" and\n          elem_type.__name__ != \"string_\"):\n        try:\n            if (elem_type.__name__ == \"ndarray\" or\n                    elem_type.__name__ == \"memmap\"):\n                # array of string classes and object\n                if np_str_obj_array_pattern.search(elem.dtype.str) is not None:\n                    return batch\n                return mod_default_collate(\n                    [paddle.to_tensor(b, dtype=b.dtype) for b in batch])\n            elif elem.shape == ():  # scalars\n                return paddle.to_tensor(batch, dtype=batch.dtype)\n        except RuntimeError:  # Unequal size\n            return batch\n    elif isinstance(elem, float):\n        return paddle.to_tensor(batch, dtype=paddle.float64)\n    elif isinstance(elem, int):\n        return paddle.to_tensor(batch, dtype=paddle.int64)\n    else:\n        return batch\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/dataio.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/dataio/dataio.py)\n\"\"\"\nData reading and writing.\n\nAuthors\n * Mirco Ravanelli 2020\n * Aku Rouhe 2020\n * Ju-Chieh Chou 2020\n * Samuele Cornell 2020\n * Abdel HEBA 2020\n\"\"\"\nimport csv\nimport hashlib\nimport json\nimport logging\nimport os\nimport pickle\nimport re\nimport time\n\nimport numpy as np\nimport soundfile\nlogger = logging.getLogger(__name__)\nimport paddle\n\n\ndef load_data_json(json_path, replacements={}):\n    \"\"\"Loads JSON and recursively formats string values.\n\n    Arguments\n    ----------\n    json_path : str\n        Path to CSV file.\n    replacements : dict\n        (Optional dict), e.g., {\"data_folder\": \"/home/PaddleSpeech/data\"}.\n        This is used to recursively format all string values in the data.\n\n    Returns\n    -------\n    dict\n        JSON data with replacements applied.\n\n\n    \"\"\"\n    with open(json_path, \"r\") as f:\n        out_json = json.load(f)\n    _recursive_format(out_json, replacements)\n    return out_json\n\n\ndef _recursive_format(data, replacements):\n    # Data: dict or list, replacements : dict\n    # Replaces string keys in replacements by their values\n    # at all levels of data (in str values)\n    # Works in-place.\n    if isinstance(data, dict):\n        for key, item in data.items():\n            if isinstance(item, dict) or isinstance(item, list):\n                _recursive_format(item, replacements)\n            elif isinstance(item, str):\n                data[key] = item.format_map(replacements)\n            # If not dict, list or str, do nothing\n    if isinstance(data, list):\n        for i, item in enumerate(data):\n            if isinstance(item, dict) or isinstance(item, list):\n                _recursive_format(item, replacements)\n            elif isinstance(item, str):\n                data[i] = item.format_map(replacements)\n            # If not dict, list or str, do nothing\n\n\ndef load_data_csv(csv_path, replacements={}):\n    \"\"\"Loads CSV and formats string values.\n\n    Uses the legacy CSV data format, where the CSV must have an\n    'ID' field.\n    If there is a field called duration, it is interpreted as a float.\n    The rest of the fields are left as they are (legacy _format and _opts fields\n    are not used to load the data in any special way).\n\n    Bash-like string replacements with $to_replace are supported.\n\n    Arguments\n    ----------\n    csv_path : str\n        Path to CSV file.\n    replacements : dict\n        (Optional dict), e.g., {\"data_folder\": \"/home/PaddleSpeech/data\"}\n        This is used to recursively format all string values in the data.\n\n    Returns\n    -------\n    dict\n        CSV data with replacements applied.\n    \"\"\"\n\n    with open(csv_path, newline=\"\") as csvfile:\n        result = {}\n        reader = csv.DictReader(csvfile, skipinitialspace=True)\n        variable_finder = re.compile(r\"\\$([\\w.]+)\")\n        for row in reader:\n            # ID:\n            try:\n                data_id = row[\"ID\"]\n                del row[\"ID\"]  # This is used as a key in result, instead.\n            except KeyError:\n                raise KeyError(\"CSV has to have an 'ID' field, with unique ids\"\n                               \" for all data points\")\n            if data_id in result:\n                raise ValueError(f\"Duplicate id: {data_id}\")\n            # Replacements:\n            for key, value in row.items():\n                try:\n                    row[key] = variable_finder.sub(\n                        lambda match: str(replacements[match[1]]), value)\n                except KeyError:\n                    raise KeyError(f\"The item {value} requires replacements \"\n                                   \"which were not supplied.\")\n            # Duration:\n            if \"duration\" in row:\n                row[\"duration\"] = float(row[\"duration\"])\n            result[data_id] = row\n    return result\n\n\ndef read_audio(waveforms_obj):\n    \"\"\"General audio loading, based on a custom notation.\n\n    Expected use case is in conjunction with Datasets\n    specified by JSON.\n\n    The custom notation:\n\n    The annotation can be just a path to a file:\n    \"/path/to/wav1.wav\"\n\n    Or can specify more options in a dict:\n    {\"file\": \"/path/to/wav2.wav\",\n    \"start\": 8000,\n    \"stop\": 16000\n    }\n\n    Arguments\n    ----------\n    waveforms_obj : str, dict\n        Audio reading annotation, see above for format.\n\n    Returns\n    -------\n    paddle.Tensor\n        Audio tensor with shape: (samples, ).\n    \"\"\"\n    if isinstance(waveforms_obj, str):\n        audio, _ = soundfile.read(waveforms_obj, dtype=\"float32\")\n        return audio\n\n    path = waveforms_obj[\"file\"]\n    start = waveforms_obj.get(\"start\", 0)\n    # Default stop to start -> if not specified, num_frames becomes 0\n    stop = waveforms_obj.get(\"stop\", start)\n    num_frames = stop - start\n    audio, fs = soundfile.read(\n        path, start=start, stop=start + num_frames, dtype=\"float32\")\n    return audio\n\n\ndef read_audio_multichannel(waveforms_obj):\n    \"\"\"General audio loading, based on a custom notation.\n\n    Expected use case is in conjunction with Datasets\n    specified by JSON.\n\n    The custom notation:\n\n    The annotation can be just a path to a file:\n    \"/path/to/wav1.wav\"\n\n    Multiple (possibly multi-channel) files can be specified, as long as they\n    have the same length:\n    {\"files\": [\n        \"/path/to/wav1.wav\",\n        \"/path/to/wav2.wav\"\n        ]\n    }\n\n    Or you can specify a single file more succinctly:\n    {\"files\": \"/path/to/wav2.wav\"}\n\n    Offset number samples and stop number samples also can be specified to read\n    only a segment within the files.\n    {\"files\": [\n        \"/path/to/wav1.wav\",\n        \"/path/to/wav2.wav\"\n        ]\n    \"start\": 8000\n    \"stop\": 16000\n    }\n\n    Arguments\n    ----------\n    waveforms_obj : str, dict\n        Audio reading annotation, see above for format.\n\n    Returns\n    -------\n    paddle.Tensor\n        Audio tensor with shape: (samples, ).\n    \"\"\"\n    if isinstance(waveforms_obj, str):\n        audio, _ = soundfile.read(waveforms_obj, dtype=\"float32\")\n        audio = paddle.to_tensor(audio)\n        return audio\n\n    files = waveforms_obj[\"files\"]\n    if not isinstance(files, list):\n        files = [files]\n\n    waveforms = []\n    start = waveforms_obj.get(\"start\", 0)\n    # Default stop to start -> if not specified, num_frames becomes 0\n    stop = waveforms_obj.get(\"stop\", start - 1)\n    num_frames = stop - start\n    for f in files:\n        audio, fs = soundfile.read(\n            path, start=start, stop=start + num_frames, dtype=\"float32\")\n        audio = paddle.to_tensor(audio)\n        waveforms.append(audio)\n\n    out = paddle.concat(waveforms, 0)\n    return out\n\n\ndef write_audio(filepath, audio, samplerate):\n    \"\"\"Write audio on disk. It is basically a wrapper to support saving\n    audio signals in format (audio, channels).\n\n    Arguments\n    ---------\n    filepath: path\n        Path where to save the audio file.\n    audio : paddle.Tensor\n        Audio file in the expected format (signal, channels).\n    samplerate: int\n        Sample rate (e.g., 16000).\n\n    \"\"\"\n    if len(audio.shape) == 2:\n        audio = audio.transpose([1, 0])\n    elif len(audio.shape) == 1:\n        audio = audio.unsqueeze(0)\n\n    soundfile.write(filepath, audio, samplerate)\n\n\ndef load_pickle(pickle_path):\n    \"\"\"Utility function for loading .pkl pickle files.\n\n    Arguments\n    ---------\n    pickle_path : str\n        Path to pickle file.\n\n    Returns\n    -------\n    out : object\n        Python object loaded from pickle.\n    \"\"\"\n    with open(pickle_path, \"rb\") as f:\n        out = pickle.load(f)\n    return out\n\n\ndef to_floatTensor(x: (list, tuple, np.ndarray)):\n    \"\"\"\n    Arguments\n    ---------\n    x : (list, tuple, np.ndarray)\n        Input data to be converted to paddle float.\n\n    Returns\n    -------\n    tensor : paddle.tensor\n        Data now in paddle.tensor float datatype.\n    \"\"\"\n    return paddle.to_tensor(x, dtype='float32')\n\n\ndef to_doubleTensor(x: (list, tuple, np.ndarray)):\n    \"\"\"\n    Arguments\n    ---------\n    x : (list, tuple, np.ndarray)\n        Input data to be converted to paddle double.\n\n    Returns\n    -------\n    tensor : paddle.tensor\n        Data now in paddle.tensor double datatype.\n    \"\"\"\n    return paddle.to_tensor(x, dtype='float64')\n\n\ndef to_longTensor(x: (list, tuple, np.ndarray)):\n    \"\"\"\n    Arguments\n    ---------\n    x : (list, tuple, np.ndarray)\n        Input data to be converted to paddle long.\n\n    Returns\n    -------\n    tensor : paddle.tensor\n        Data now in paddle.tensor long datatype.\n    \"\"\"\n    return paddle.to_tensor(x, dtype='int64')\n\n\ndef convert_index_to_lab(batch, ind2lab):\n    \"\"\"Convert a batch of integer IDs to string labels.\n\n    Arguments\n    ---------\n    batch : list\n        List of lists, a batch of sequences.\n    ind2lab : dict\n        Mapping from integer IDs to labels.\n\n    Returns\n    -------\n    list\n        List of lists, same size as batch, with labels from ind2lab.\n\n    \"\"\"\n    return [[ind2lab[int(index)] for index in seq] for seq in batch]\n\n\ndef relative_time_to_absolute(batch, relative_lens, rate):\n    \"\"\"Converts relative length to the absolute duration.\n\n    Operates on batch level.\n\n    Arguments\n    ---------\n    batch : paddle.tensor\n        Sequences to determine the duration for.\n    relative_lens : paddle.tensor\n        The relative length of each sequence in batch. The longest sequence in\n        the batch needs to have relative length 1.0.\n    rate : float\n        The rate at which sequence elements occur in real-world time. Sample\n        rate, if batch is raw wavs (recommended) or 1/frame_shift if batch is\n        features. This has to have 1/s as the unit.\n\n    Returns\n    ------:\n    paddle.tensor\n        Duration of each sequence in seconds.\n\n    \"\"\"\n    max_len = batch.shape[1]\n    durations = paddle.round(relative_lens * max_len) / rate\n    return durations\n\n\nclass IterativeCSVWriter:\n    \"\"\"Write CSV files a line at a time.\n\n    Arguments\n    ---------\n    outstream : file-object\n        A writeable stream\n    data_fields : list\n        List of the optional keys to write. Each key will be expanded, \n        producing three fields: key, key_format, key_opts.\n    \"\"\"\n\n    def __init__(self, outstream, data_fields, defaults={}):\n        self._outstream = outstream\n        self.fields = [\"ID\", \"duration\"] + self._expand_data_fields(data_fields)\n        self.defaults = defaults\n        self._outstream.write(\",\".join(self.fields))\n\n    def set_default(self, field, value):\n        \"\"\"Sets a default value for the given CSV field.\n\n        Arguments\n        ---------\n        field : str\n            A field in the CSV.\n        value\n            The default value.\n        \"\"\"\n        if field not in self.fields:\n            raise ValueError(f\"{field} is not a field in this CSV!\")\n        self.defaults[field] = value\n\n    def write(self, *args, **kwargs):\n        \"\"\"Writes one data line into the CSV.\n\n        Arguments\n        ---------\n        *args\n            Supply every field with a value in positional form OR.\n        **kwargs\n            Supply certain fields by key. The ID field is mandatory for all\n            lines, but others can be left empty.\n        \"\"\"\n        if args and kwargs:\n            raise ValueError(\n                \"Use either positional fields or named fields, but not both.\")\n        if args:\n            if len(args) != len(self.fields):\n                raise ValueError(\"Need consistent fields\")\n            to_write = [str(arg) for arg in args]\n        if kwargs:\n            if \"ID\" not in kwargs:\n                raise ValueError(\"I'll need to see some ID\")\n            full_vals = self.defaults.copy()\n            full_vals.update(kwargs)\n            to_write = [str(full_vals.get(field, \"\")) for field in self.fields]\n        self._outstream.write(\"\\n\")\n        self._outstream.write(\",\".join(to_write))\n\n    def write_batch(self, *args, **kwargs):\n        \"\"\"Writes a batch of lines into the CSV.\n\n        Here each argument should be a list with the same length.\n\n        Arguments\n        ---------\n        *args\n            Supply every field with a value in positional form OR.\n        **kwargs\n            Supply certain fields by key. The ID field is mandatory for all\n            lines, but others can be left empty.\n        \"\"\"\n        if args and kwargs:\n            raise ValueError(\n                \"Use either positional fields or named fields, but not both.\")\n        if args:\n            if len(args) != len(self.fields):\n                raise ValueError(\"Need consistent fields\")\n            for arg_row in zip(*args):\n                self.write(*arg_row)\n        if kwargs:\n            if \"ID\" not in kwargs:\n                raise ValueError(\"I'll need to see some ID\")\n            keys = kwargs.keys()\n            for value_row in zip(*kwargs.values()):\n                kwarg_row = dict(zip(keys, value_row))\n                self.write(**kwarg_row)\n\n    @staticmethod\n    def _expand_data_fields(data_fields):\n        expanded = []\n        for data_field in data_fields:\n            expanded.append(data_field)\n            expanded.append(data_field + \"_format\")\n            expanded.append(data_field + \"_opts\")\n        return expanded\n\n\ndef write_txt_file(data, filename, sampling_rate=None):\n    \"\"\"Write data in text format.\n\n    Arguments\n    ---------\n    data : str, list, paddle.tensor, numpy.ndarray\n        The data to write in the text file.\n    filename : str\n        Path to file where to write the data.\n    sampling_rate : None\n        Not used, just here for interface compatibility.\n\n    Returns\n    -------\n    None\n\n    \"\"\"\n    del sampling_rate  # Not used.\n    # Check if the path of filename exists\n    os.makedirs(os.path.dirname(filename), exist_ok=True)\n    with open(filename, \"w\") as fout:\n        if isinstance(data, paddle.Tensor):\n            data = data.tolist()\n        if isinstance(data, np.ndarray):\n            data = data.tolist()\n        if isinstance(data, list):\n            for line in data:\n                print(line, file=fout)\n        if isinstance(data, str):\n            print(data, file=fout)\n\n\ndef write_stdout(data, filename=None, sampling_rate=None):\n    \"\"\"Write data to standard output.\n\n    Arguments\n    ---------\n    data : str, list, paddle.Tensor, numpy.ndarray\n        The data to write in the text file.\n    filename : None\n        Not used, just here for compatibility.\n    sampling_rate : None\n        Not used, just here for compatibility.\n\n    Returns\n    -------\n    None\n\n    \"\"\"\n    # Managing paddle.Tensor\n    if isinstance(data, paddle.Tensor):\n        data = data.tolist()\n    # Managing np.ndarray\n    if isinstance(data, np.ndarray):\n        data = data.tolist()\n    if isinstance(data, list):\n        for line in data:\n            print(line)\n    if isinstance(data, str):\n        print(data)\n\n\ndef length_to_mask(length, max_len=None, dtype=None, device=None):\n    \"\"\"Creates a binary mask for each sequence.\n    Arguments\n    ---------\n    length : LongTensor\n        Containing the length of each sequence in the batch. Must be 1D.\n    max_len : int\n        Max length for the mask, also the size of the second dimension.\n    dtype : dtype, default: None\n        The dtype of the generated mask.\n    device: device, default: None\n        The device to put the mask variable.\n\n    Returns\n    -------\n    mask : tensor\n        The binary mask.\n\n    \"\"\"\n    assert len(length.shape) == 1\n\n    if max_len is None:\n        max_len = length.max().long().item()  # using arange to generate mask\n    mask = paddle.arange(\n        max_len, dtype=length.dtype).expand(\n            [len(length), max_len]) < length.unsqueeze(1)\n\n    if dtype is None:\n        dtype = length.dtype\n\n    if device is None:\n        device = length.device\n\n    mask = paddle.to_tensor(mask, dtype=dtype)\n    return mask\n\n\ndef read_kaldi_lab(kaldi_ali, kaldi_lab_opts):\n    \"\"\"Read labels in kaldi format.\n\n    Uses kaldi IO.\n\n    Arguments\n    ---------\n    kaldi_ali : str\n        Path to directory where kaldi alignments are stored.\n    kaldi_lab_opts : str\n        A string that contains the options for reading the kaldi alignments.\n\n    Returns\n    -------\n    lab : dict\n        A dictionary containing the labels.\n\n    Note\n    ----\n    This depends on kaldi-io-for-python. Install it separately.\n    See: https://github.com/vesis84/kaldi-io-for-python\n    ```\n    \"\"\"\n    # EXTRA TOOLS\n    try:\n        import kaldi_io\n    except ImportError:\n        raise ImportError(\"Could not import kaldi_io. Install it to use this.\")\n    # Reading the Kaldi labels\n    lab = {\n        k: v\n        for k, v in kaldi_io.read_vec_int_ark(\n            \"gunzip -c \" + kaldi_ali + \"/ali*.gz | \" + kaldi_lab_opts + \" \" +\n            kaldi_ali + \"/final.mdl ark:- ark:-|\")\n    }\n    return lab\n\n\ndef get_md5(file):\n    \"\"\"Get the md5 checksum of an input file.\n\n    Arguments\n    ---------\n    file : str\n        Path to file for which compute the checksum.\n\n    Returns\n    -------\n    md5\n        Checksum for the given filepath.\n    \"\"\"\n    # Lets read stuff in 64kb chunks!\n    BUF_SIZE = 65536\n    md5 = hashlib.md5()\n    # Computing md5\n    with open(file, \"rb\") as f:\n        while True:\n            data = f.read(BUF_SIZE)\n            if not data:\n                break\n            md5.update(data)\n    return md5.hexdigest()\n\n\ndef save_md5(files, out_file):\n    \"\"\"Saves the md5 of a list of input files as a pickled dict into a file.\n\n    Arguments\n    ---------\n    files : list\n        List of input files from which we will compute the md5.\n    outfile : str\n        The path where to store the output pkl file.\n\n    Returns\n    -------\n    None\n    \"\"\"\n    # Initialization of the dictionary\n    md5_dict = {}\n    # Computing md5 for all the files in the list\n    for file in files:\n        md5_dict[file] = get_md5(file)\n    # Saving dictionary in pkl format\n    save_pkl(md5_dict, out_file)\n\n\ndef save_pkl(obj, file):\n    \"\"\"Save an object in pkl format.\n\n    Arguments\n    ---------\n    obj : object\n        Object to save in pkl format\n    file : str\n        Path to the output file\n    sampling_rate : int\n        Sampling rate of the audio file, TODO: this is not used?\n\n    \"\"\"\n    with open(file, \"wb\") as f:\n        pickle.dump(obj, f)\n\n\ndef load_pkl(file):\n    \"\"\"Loads a pkl file.\n\n    For an example, see `save_pkl`.\n\n    Arguments\n    ---------\n    file : str\n        Path to the input pkl file.\n\n    Returns\n    -------\n    The loaded object.\n    \"\"\"\n\n    # Deals with the situation where two processes are trying\n    # to access the same label dictionary by creating a lock\n    count = 100\n    while count > 0:\n        if os.path.isfile(file + \".lock\"):\n            time.sleep(1)\n            count -= 1\n        else:\n            break\n\n    try:\n        open(file + \".lock\", \"w\").close()\n        with open(file, \"rb\") as f:\n            return pickle.load(f)\n    finally:\n        if os.path.isfile(file + \".lock\"):\n            os.remove(file + \".lock\")\n\n\ndef prepend_bos_token(label, bos_index):\n    \"\"\"Create labels with <bos> token at the beginning.\n\n    Arguments\n    ---------\n    label : IntTensor\n        Containing the original labels. Must be of size: [batch_size, max_length].\n    bos_index : int\n        The index for <bos> token.\n\n    Returns\n    -------\n    new_label : tensor\n        The new label with <bos> at the beginning.\n\n    \"\"\"\n    new_label = label.long().clone()\n    batch_size = label.shape[0]\n\n    bos = new_label.new_zeros(batch_size, 1).fill_(bos_index)\n    new_label = paddle.concat([bos, new_label], axis=1)\n    return new_label\n\n\ndef append_eos_token(label, length, eos_index):\n    \"\"\"Create labels with <eos> token appended.\n\n    Arguments\n    ---------\n    label : IntTensor\n        Containing the original labels. Must be of size: [batch_size, max_length]\n    length : LongTensor\n        Containing the original length of each label sequences. Must be 1D.\n    eos_index : int\n        The index for <eos> token.\n\n    Returns\n    -------\n    new_label : tensor\n        The new label with <eos> appended.\n\n    \"\"\"\n    new_label = paddle.to_tensor(label, dtype=\"int32\").clone()\n    batch_size = label.shape[0]\n\n    pad = paddle.zeros([batch_size, 1], dtype=new_label.dtype)\n\n    new_label = paddle.concat([new_label, pad], dim=1)\n    new_label[paddle.arange(batch_size), paddle.to_tensor(\n        length, dtype=\"int64\")] = eos_index\n    return new_label\n\n\ndef merge_char(sequences, space=\"_\"):\n    \"\"\"Merge characters sequences into word sequences.\n\n    Arguments\n    ---------\n    sequences : list\n        Each item contains a list, and this list contains a character sequence.\n    space : string\n        The token represents space. Default: _\n\n    Returns\n    -------\n    The list contains word sequences for each sentence.\n\n    \"\"\"\n    results = []\n    for seq in sequences:\n        words = \"\".join(seq).split(space)\n        results.append(words)\n    return results\n\n\ndef merge_csvs(data_folder, csv_lst, merged_csv):\n    \"\"\"Merging several csv files into one file.\n\n    Arguments\n    ---------\n    data_folder : string\n        The folder to store csv files to be merged and after merging.\n    csv_lst : list\n        Filenames of csv file to be merged.\n    merged_csv : string\n        The filename to write the merged csv file.\n\n    \"\"\"\n    write_path = os.path.join(data_folder, merged_csv)\n    if os.path.isfile(write_path):\n        logger.info(\"Skipping merging. Completed in previous run.\")\n    with open(os.path.join(data_folder, csv_lst[0])) as f:\n        header = f.readline()\n    lines = []\n    for csv_file in csv_lst:\n        with open(os.path.join(data_folder, csv_file)) as f:\n            for i, line in enumerate(f):\n                if i == 0:\n                    # Checking header\n                    if line != header:\n                        raise ValueError(\"Different header for \"\n                                         f\"{csv_lst[0]} and {csv}.\")\n                    continue\n                lines.append(line)\n    with open(write_path, \"w\") as f:\n        f.write(header)\n        for line in lines:\n            f.write(line)\n    logger.info(f\"{write_path} is created.\")\n\n\ndef split_word(sequences, space=\"_\"):\n    \"\"\"Split word sequences into character sequences.\n\n    Arguments\n    ---------\n    sequences : list\n        Each item contains a list, and this list contains a words sequence.\n    space : string\n        The token represents space. Default: _\n\n    Returns\n    -------\n    The list contains word sequences for each sentence.\n\n    \"\"\"\n    results = []\n    for seq in sequences:\n        chars = list(space.join(seq))\n        results.append(chars)\n    return results\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/dataloader.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/dataio/dataloader.py)\n\"\"\"Paddle compatible DataLoaders\n\nEssentially we extend Paddle DataLoader by adding the ability to save the\ndata loading state, so that a checkpoint may be saved in the middle of an\nepoch.\n\nAuthors:\n  * Aku Rouhe 2020\n\"\"\"\nimport collections\nimport functools\nimport logging\nimport warnings\n\nimport paddle\nfrom paddle.io import DataLoader\n\nfrom paddlespeech.s2t.io.speechbrain.data_utils import batch_pad_right\nfrom paddlespeech.s2t.io.speechbrain.data_utils import mod_default_collate\nfrom paddlespeech.s2t.io.speechbrain.dataset import DynamicItemDataset\nfrom paddlespeech.s2t.io.speechbrain.sampler import ReproducibleRandomSampler\nPaddedData = collections.namedtuple(\"PaddedData\", [\"data\", \"lengths\"])\nimport numpy\n\n\nclass Wav2vec2DataLoader(DataLoader):\n    def __init__(self,\n                 dataset,\n                 batch_size=1,\n                 shuffle=False,\n                 sampler=None,\n                 batch_sampler=None,\n                 num_workers=0,\n                 collate_fn=None,\n                 pin_memory=False,\n                 drop_last=False,\n                 timeout=0,\n                 worker_init_fn=None,\n                 multiprocessing_context=None,\n                 generator=None):\n        if isinstance(dataset[0], (tuple, list)):\n            return_list = True\n        else:\n            return_list = False\n\n        super().__init__(\n            dataset,\n            feed_list=None,\n            places=None,\n            return_list=return_list,\n            batch_sampler=batch_sampler,\n            batch_size=batch_size,\n            shuffle=shuffle,\n            drop_last=drop_last,\n            collate_fn=collate_fn,\n            num_workers=num_workers,\n            use_buffer_reader=True,\n            use_shared_memory=False,\n            timeout=timeout,\n            worker_init_fn=worker_init_fn)\n        if sampler is not None:\n            self.batch_sampler.sampler = sampler\n\n\ndef PaddedBatch(\n        examples,\n        padded_keys=None,\n        device_prep_keys=None,\n        padding_func=batch_pad_right,\n        padding_kwargs={},\n        nonpadded_stack=True, ):\n    __length = len(examples)\n    __keys = list(examples[0].keys())\n    __padded_keys = []\n    __device_prep_keys = []\n    res = {}\n    for key in __keys:\n        values = [example[key] for example in examples]\n        # Default convert usually does the right thing (numpy2tensor etc.)\n        # values = default_convert(values)\n        if (padded_keys is not None and key in padded_keys) or (\n                padded_keys is None and isinstance(values[0], numpy.ndarray)):\n            # Padding and PaddedData\n            __padded_keys.append(key)\n\n            padded = PaddedData(*padding_func(values, **padding_kwargs))\n            res[key] = padded\n        else:\n            # Default collate usually does the right thing\n            # (convert lists of equal sized tensors to batch tensors, etc.)\n            if nonpadded_stack:\n                values = mod_default_collate(values)\n            res[key] = values\n        if (device_prep_keys is not None and key in device_prep_keys) or (\n                device_prep_keys is None and\n                isinstance(values[0], paddle.Tensor)):\n            __device_prep_keys.append(key)\n    return res\n\n\ndef make_dataloader(dataset, stage, **loader_kwargs):\n    \"\"\"Makes a basic DataLoader.\n\n    For DynamicItemDatasets (which return dicts), use\n    PaddedBatch as the default collate_fn.\n\n    Shuffling gets implemented by ReproducibleRandomSampler.\n\n    If the Dataset is not an IterableDataset, the DataLoader\n    is a SaveableDataLoader.\n\n    If the Dataset is a webdataset.dataset.Composable, set default\n    batch_size = None.\n\n    Can also loop over the underlying dataloader continuously,\n    and stop iterations at nominal epoch lengths.\n\n    Arguments\n    ---------\n    dataset : Dataset\n        The dataset to make a DataLoader for.\n    looped_nominal_epoch : None, int\n        If an integer is given, loop the underlying DataLoader infinitely and\n        set a nominal epoch length in batches (or whatever the DataLoader\n        yields).\n    **loader_kwargs : dict\n        Keyword args to DataLoader, see Paddle DataLoader for\n        options.\n\n    Returns\n    -------\n    DataLoader\n        If looped_nominal_epoch is None\n    LoopedLoader\n        If looped_nominal_epoch is not None\n    \"\"\"\n    # PaddedBatch as default collation for DynamicItemDataset\n    if \"collate_fn\" not in loader_kwargs and isinstance(dataset,\n                                                        DynamicItemDataset):\n        loader_kwargs[\"collate_fn\"] = PaddedBatch\n    # Reproducible random sampling\n    if loader_kwargs.get(\"shuffle\", False):\n        if loader_kwargs.get(\"sampler\") is not None:\n            raise ValueError(\"Cannot specify both shuffle=True and a \"\n                             \"sampler in loader_kwargs\")\n        sampler = ReproducibleRandomSampler(dataset)\n        loader_kwargs[\"sampler\"] = sampler\n        # Should delete shuffle because you can't set both Sampler and\n        # shuffle\n        # NOTE: the dict of loader options may get used elsewhere!\n        # However, this del doesn't touch those because loader_kwargs comes\n        # from a **kwargs dict.\n        del loader_kwargs[\"shuffle\"]\n    # Create the loader\n    dataloader = Wav2vec2DataLoader(dataset, **loader_kwargs)\n    return dataloader\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/dataset.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/dataio/dataset.py)\nimport contextlib\nimport copy\nimport logging\nfrom types import MethodType\n\nfrom paddle.io import Dataset\n\nfrom paddlespeech.s2t.io.speechbrain.data_pipeline import DataPipeline\nfrom paddlespeech.s2t.io.speechbrain.dataio import load_data_csv\nfrom paddlespeech.s2t.io.speechbrain.dataio import load_data_json\n\nlogger = logging.getLogger(__name__)\n\n\nclass DynamicItemDataset(Dataset):\n    \"\"\"Dataset that reads, wrangles, and produces dicts.\n\n    Each data point dict provides some items (by key), for example, a path to a\n    wavefile with the key \"wav_file\". When a data point is fetched from this\n    Dataset, more items are produced dynamically, based on pre-existing items\n    and other dynamic created items. For example, a dynamic item could take the\n    wavfile path and load the audio from the disk.\n\n    The dynamic items can depend on other dynamic items: a suitable evaluation\n    order is used automatically,  as long as there are no circular dependencies.\n\n    A specified list of keys is collected in the output dict. These can be items\n    in the original data or dynamic items. If some dynamic items are not\n    requested, nor depended on by other requested items, they won't be computed.\n    So for example if a user simply wants to iterate over the text, the\n    time-consuming audio loading can be skipped.\n\n    About the format:\n    Takes a dict of dicts as the collection of data points to read/wrangle.\n    The top level keys are data point IDs.\n    Each data point (example) dict should have the same keys, corresponding to\n    different items in that data point.\n\n    Altogether the data collection could look like this:\n\n    >>> data = {\n    ...  \"spk1utt1\": {\n    ...      \"wav_file\": \"/path/to/spk1utt1.wav\",\n    ...      \"text\": \"hello world\",\n    ...      \"speaker\": \"spk1\",\n    ...      },\n    ...  \"spk1utt2\": {\n    ...      \"wav_file\": \"/path/to/spk1utt2.wav\",\n    ...      \"text\": \"how are you world\",\n    ...      \"speaker\": \"spk1\",\n    ...      }\n    ... }\n\n    NOTE\n    ----\n        The top-level key, the data point id, is implicitly added as an item\n        in the data point, with the key \"id\"\n\n    Each dynamic item is configured by three things: a key, a func, and a list\n    of argkeys. The key should be unique among all the items (dynamic or not) in\n    each data point. The func is any callable, and it returns the dynamic item's\n    value. The callable is called with the values of other items as specified\n    by the argkeys list (as positional args, passed in the order specified by\n    argkeys).\n\n    Arguments\n    ---------\n    data : dict\n        Dictionary containing single data points (e.g. utterances).\n    dynamic_items : list, optional\n        Configuration for the dynamic items produced when fetching an example.\n        List of DynamicItems or dicts with the format::\n            func: <callable> # To be called\n            takes: <list> # key or list of keys of args this takes\n            provides: key # key or list of keys that this provides\n    output_keys : dict, list, optional\n        List of keys (either directly available in data or dynamic items)\n        to include in the output dict when data points are fetched.\n\n        If a dict is given; it is used to map internal keys to output keys.\n        From the output_keys dict key:value pairs the key appears outside,\n        and value is the internal key.\n    \"\"\"\n\n    def __init__(\n            self,\n            data,\n            dynamic_items=[],\n            output_keys=[], ):\n        self.data = data\n        self.data_ids = list(self.data.keys())\n        static_keys = list(self.data[self.data_ids[0]].keys())\n        if \"id\" in static_keys:\n            raise ValueError(\"The key 'id' is reserved for the data point id.\")\n        else:\n            static_keys.append(\"id\")\n        self.pipeline = DataPipeline(static_keys, dynamic_items)\n        self.set_output_keys(output_keys)\n\n    def __len__(self):\n        return len(self.data_ids)\n\n    def __getitem__(self, index):\n        data_id = self.data_ids[index]\n        data_point = self.data[data_id]\n        return self.pipeline.compute_outputs({\"id\": data_id, **data_point})\n\n    def add_dynamic_item(self, func, takes=None, provides=None):\n        \"\"\"Makes a new dynamic item available on the dataset.\n\n        Two calling conventions. For DynamicItem objects, just use:\n        add_dynamic_item(dynamic_item).\n        But otherwise, should use:\n        add_dynamic_item(func, takes, provides).\n\n        Arguments\n        ---------\n        func : callable, DynamicItem\n            If a DynamicItem is given, adds that directly. Otherwise a\n            DynamicItem is created, and this specifies the callable to use. If\n            a generator function is given, then create a GeneratorDynamicItem.\n            Otherwise creates a normal DynamicItem.\n        takes : list, str\n            List of keys. When func is called, each key is resolved to\n            either an entry in the data or the output of another dynamic_item.\n            The func is then called with these as positional arguments,\n            in the same order as specified here.\n            A single arg can be given directly.\n        provides : str\n            Unique key or keys that this provides.\n        \"\"\"\n        self.pipeline.add_dynamic_item(func, takes, provides)\n\n    def set_output_keys(self, keys):\n        \"\"\"Use this to change the output keys.\n\n        These are the keys that are actually evaluated when a data point\n        is fetched from the dataset.\n\n        Arguments\n        ---------\n        keys : dict, list\n            List of keys (str) to produce in output.\n\n            If a dict is given; it is used to map internal keys to output keys.\n            From the output_keys dict key:value pairs the key appears outside,\n            and value is the internal key.\n        \"\"\"\n        self.pipeline.set_output_keys(keys)\n\n    @contextlib.contextmanager\n    def output_keys_as(self, keys):\n        \"\"\"Context manager to temporarily set output keys.\n\n        NOTE\n        ----\n        Not thread-safe. While in this context manager, the output keys\n        are affected for any call.\n        \"\"\"\n        saved_output = self.pipeline.output_mapping\n        self.pipeline.set_output_keys(keys)\n        yield self\n        self.pipeline.set_output_keys(saved_output)\n\n    def filtered_sorted(\n            self,\n            key_min_value={},\n            key_max_value={},\n            key_test={},\n            sort_key=None,\n            reverse=False,\n            select_n=None, ):\n        \"\"\"Get a filtered and/or sorted version of this, shares static data.\n\n        The reason to implement these operations in the same method is that\n        computing some dynamic items may be expensive, and this way the\n        filtering and sorting steps don't need to compute the dynamic items\n        twice.\n\n        Arguments\n        ---------\n        key_min_value : dict\n            Map from key (in data or in dynamic items) to limit, will only keep\n            data_point if data_point[key] >= limit\n        key_max_value : dict\n            Map from key (in data or in dynamic items) to limit, will only keep\n            data_point if data_point[key] <= limit\n        key_test : dict\n            Map from key (in data or in dynamic items) to func, will only keep\n            data_point if bool(func(data_point[key])) == True\n        sort_key : None, str\n            If not None, sort by data_point[sort_key]. Default is ascending\n            order.\n        reverse : bool\n            If True, sort in descending order.\n        select_n : None, int\n            If not None, only keep (at most) the first n filtered data_points.\n            The possible sorting is applied, but only on the first n data\n            points found. Meant for debugging.\n\n        Returns\n        -------\n        FilteredSortedDynamicItemDataset\n            Shares the static data, but has its own output keys and\n            dynamic items (initially deep copied from this, so they have the\n            same dynamic items available)\n\n        NOTE\n        ----\n        Temporarily changes the output keys!\n        \"\"\"\n        filtered_sorted_ids = self._filtered_sorted_ids(\n            key_min_value,\n            key_max_value,\n            key_test,\n            sort_key,\n            reverse,\n            select_n, )\n        return FilteredSortedDynamicItemDataset(\n            self, filtered_sorted_ids)  # NOTE: defined below\n\n    def _filtered_sorted_ids(\n            self,\n            key_min_value={},\n            key_max_value={},\n            key_test={},\n            sort_key=None,\n            reverse=False,\n            select_n=None, ):\n        \"\"\"Returns a list of data ids, fulfilling the sorting and filtering.\"\"\"\n\n        def combined_filter(computed):\n            \"\"\"Applies filter.\"\"\"\n            for key, limit in key_min_value.items():\n                # NOTE: docstring promises >= so using that.\n                # Mathematically could also use < for nicer syntax, but\n                # maybe with some super special weird edge case some one can\n                # depend on the >= operator\n                if computed[key] >= limit:\n                    continue\n                return False\n            for key, limit in key_max_value.items():\n                if computed[key] <= limit:\n                    continue\n                return False\n            for key, func in key_test.items():\n                if bool(func(computed[key])):\n                    continue\n                return False\n            return True\n\n        temp_keys = (set(key_min_value.keys()) | set(key_max_value.keys()) |\n                     set(key_test.keys()) |\n                     set([] if sort_key is None else [sort_key]))\n        filtered_ids = []\n        with self.output_keys_as(temp_keys):\n            for i, data_id in enumerate(self.data_ids):\n                if select_n is not None and len(filtered_ids) == select_n:\n                    break\n                data_point = self.data[data_id]\n                data_point[\"id\"] = data_id\n                computed = self.pipeline.compute_outputs(data_point)\n                if combined_filter(computed):\n                    if sort_key is not None:\n                        # Add (main sorting index, current index, data_id)\n                        # So that we maintain current sorting and don't compare\n                        # data_id values ever.\n                        filtered_ids.append((computed[sort_key], i, data_id))\n                    else:\n                        filtered_ids.append(data_id)\n        if sort_key is not None:\n            filtered_sorted_ids = [\n                tup[2] for tup in sorted(filtered_ids, reverse=reverse)\n            ]\n        else:\n            filtered_sorted_ids = filtered_ids\n        return filtered_sorted_ids\n\n    @classmethod\n    def from_json(cls,\n                  json_path,\n                  replacements={},\n                  dynamic_items=[],\n                  output_keys=[]):\n        \"\"\"Load a data prep JSON file and create a Dataset based on it.\"\"\"\n        data = load_data_json(json_path, replacements)\n        return cls(data, dynamic_items, output_keys)\n\n    @classmethod\n    def from_csv(cls,\n                 csv_path,\n                 replacements={},\n                 dynamic_items=[],\n                 output_keys=[]):\n        \"\"\"Load a data prep CSV file and create a Dataset based on it.\"\"\"\n        data = load_data_csv(csv_path, replacements)\n        return cls(data, dynamic_items, output_keys)\n\n    @classmethod\n    def from_arrow_dataset(cls,\n                           dataset,\n                           replacements={},\n                           dynamic_items=[],\n                           output_keys=[]):\n        \"\"\"Loading a prepared huggingface dataset\"\"\"\n\n        # define an unbound method to generate puesdo keys\n        def keys(self):\n            \"Returns the keys.\"\n            return [i for i in range(dataset.__len__())]\n\n        # bind this method to arrow dataset\n        dataset.keys = MethodType(keys, dataset)\n        return cls(dataset, dynamic_items, output_keys)\n\n\nclass FilteredSortedDynamicItemDataset(DynamicItemDataset):\n    \"\"\"Possibly filtered, possibly sorted DynamicItemDataset.\n\n    Shares the static data (reference).\n    Has its own dynamic_items and output_keys (deepcopy).\n    \"\"\"\n\n    def __init__(self, from_dataset, data_ids):\n        self.data = from_dataset.data\n        self.data_ids = data_ids\n        self.pipeline = copy.deepcopy(from_dataset.pipeline)\n\n    @classmethod\n    def from_json(cls,\n                  json_path,\n                  replacements={},\n                  dynamic_items=None,\n                  output_keys=None):\n        raise TypeError(\"Cannot create SubsetDynamicItemDataset directly!\")\n\n    @classmethod\n    def from_csv(cls,\n                 csv_path,\n                 replacements={},\n                 dynamic_items=None,\n                 output_keys=None):\n        raise TypeError(\"Cannot create SubsetDynamicItemDataset directly!\")\n\n\ndef add_dynamic_item(datasets, func, takes=None, provides=None):\n    \"\"\"Helper for adding the same item to multiple datasets.\"\"\"\n    for dataset in datasets:\n        dataset.add_dynamic_item(func, takes, provides)\n\n\ndef set_output_keys(datasets, output_keys):\n    \"\"\"Helper for setting the same item to multiple datasets.\"\"\"\n    for dataset in datasets:\n        dataset.set_output_keys(output_keys)\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/depgraph.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/utils/depgraph.py)\n\"\"\"A dependency graph for finding evaluation order.\n\nAuthors:\n    * Aku Rouhe 2020\n\"\"\"\nimport collections\nimport uuid\n\n\nclass CircularDependencyError(ValueError):\n    \"\"\"\n    An error caused by running into circular dependencies while searching for\n    an evaluation order in a DependencyGraph.\n    \"\"\"\n\n    pass\n\n\nDGNode = collections.namedtuple(\"DGNode\", [\"key\", \"edges\", \"data\"])\n\n# A node in DependencyGraph.\n\n\nclass DependencyGraph:\n    \"\"\"General-purpose dependency graph.\n\n    Essentially a directed acyclic graph.\n    Usually used to find an evaluation order for e.g. variable substitution\n    The relation that an edge between A and B represents is:\n    \"A depends on B, i.e. B should be evaluated before A\"\n\n    Nodes can be added explicitly or they can be created implicitly\n    while adding edges.\n    Nodes have keys, which should be some hashable value that identifies\n    the elements the graph represents in your use case. E.G. they can just\n    be the variable name you want to substitute.\n    However, if needed, more generally you can attach any data to a node\n    (e.g. a path in your tree), and if so desired, a unique key can be\n    created for you. You'll only need to know that key while adding edges\n    to/from it.\n    Implicit keys and explicit keys can also be mixed.\n    \"\"\"\n\n    def __init__(self):\n        self.digraph = []\n        self.key2ind = {}\n        # Guard for manual duplicates (but not implicitly added ones)\n        self._manually_added_keys = []\n\n    @staticmethod\n    def get_unique_key():\n        \"\"\"Returns a unique hashable identifier.\"\"\"\n        return uuid.uuid4()\n\n    def add_node(self, key=None, data=None):\n        \"\"\"Adds a node explicitly.\n\n        Arguments\n        ---------\n        key : hashable, optional\n            If not given, a key is created for you.\n        data : Any, optional\n            Any additional data you wish to attach to this node.\n\n        Returns\n        -------\n        hashable\n            The key that was used (either yours or generated).\n\n        Raises\n        ------\n        ValueError\n            If node with the given key has already been added explicitly\n            (with this method, not \"add_edge\").\n        \"\"\"\n        if key is None:\n            key = self.get_unique_key()\n        elif key in self._manually_added_keys:\n            raise ValueError(\"Adding duplicate node: {key}\".format(key=key))\n        else:\n            self._manually_added_keys.append(key)\n        if key in self.key2ind:  # Implicitly added already; don't add again.\n            ind = self.key2ind[key]\n            node = self.digraph[ind]\n            # All that this operation can do is add data:\n            self.digraph[ind] = DGNode(node.key, node.edges, data)\n            return key\n        self.key2ind[key] = len(self.digraph)\n        self.digraph.append(DGNode(key, [], data))\n        return key\n\n    def add_edge(self, from_key, to_key):\n        \"\"\"Adds an edge, and implicitly also creates nodes for keys which have\n        not been seen before. This will not let you add data to your nodes.\n        The relation encodes: \"from_key depends on to_key\"\n        (to_key must be evaluated before from_key).\n\n        Arguments\n        ---------\n        from_key : hashable\n            The key which depends on.\n        to_key : hashable\n            The key which is depended on.\n\n        Returns\n        -------\n        None\n        \"\"\"\n        from_ind = self._get_ind_and_add_if_new(from_key)\n        to_ind = self._get_ind_and_add_if_new(to_key)\n        edges_list = self.digraph[from_ind].edges\n        if to_ind not in edges_list:\n            edges_list.append(to_ind)\n\n    def _get_ind_and_add_if_new(self, key):\n        # Used internally to implicitly add nodes for unseen keys\n        if key not in self.key2ind:\n            self.key2ind[key] = len(self.digraph)\n            self.digraph.append(DGNode(key, [], None))\n        return self.key2ind[key]\n\n    def is_valid(self):\n        \"\"\"Checks if an evaluation order can be found.\n\n        A dependency graph is evaluatable if there are no circular\n        dependencies, i.e., the graph is acyclic.\n\n        Returns\n        -------\n        bool\n            Indicating if the graph is evaluatable.\n        \"\"\"\n        return not self._find_first_cycle()\n\n    def get_evaluation_order(self, selected_keys=None):\n        \"\"\"Finds one valid evaluation order.\n\n        There can be many different valid\n        orders.\n        NOTE: Generates output one DGNode at a time. May generate DGNodes\n        before it finds a circular dependency. If you really need to know\n        whether an order can be found, check is_valid() first. However,\n        the algorithm for finding cycles is essentially the same as the one\n        used for finding an evaluation order, so for very large graphs...\n        Ah well, but maybe then you should be using some other solution\n        anyway.\n\n        Arguments\n        ---------\n        selected_keys : list, None\n            List of keys. If not None, only the selected keys are guaranteed\n            in the evaluation order (along with the keys they depend on).\n\n        Yields\n        ------\n        DGNode\n            The added DGNodes in a valid evaluation order.\n            See the DGNode namedtuple above.\n\n        Raises\n        ------\n        CircularDependencyError\n            If a circular dependency is found.\n        \"\"\"\n        seen_ever = set()\n\n        def toposort(root_ind, visited):\n            \"\"\"Implementation of topsort.\"\"\"\n            nonlocal seen_ever\n            here = visited + [root_ind]\n            if root_ind in visited:\n                raise CircularDependencyError(\"{cycle}\".format(\n                    cycle=\" -> \".join(str(self.digraph[i].key) for i in here)))\n            if root_ind in seen_ever:\n                return  # Yield nothing\n            seen_ever = seen_ever.union(set([root_ind]))\n            for to_ind in self.digraph[root_ind].edges:\n                for ind in toposort(to_ind, visited=here):\n                    yield ind\n            yield root_ind\n\n        if selected_keys is None:\n            start_inds = range(len(self.digraph))\n        else:\n            start_inds = [self.key2ind[key] for key in selected_keys]\n\n        for start_ind in start_inds:\n            for ind in toposort(start_ind, []):\n                yield self.digraph[ind]\n\n    def _find_first_cycle(self):\n        \"\"\"Depth-first search based algorithm for finding cycles in the graph.\"\"\"\n        seen_ever = set()\n\n        def cycle_dfs(root_ind, visited):\n            \"\"\"Implementation of cycle_dfs.\"\"\"\n            nonlocal seen_ever\n            print(root_ind, visited)\n            here = visited + [root_ind]\n            if root_ind in visited:\n                return here\n            if root_ind in seen_ever:\n                return []\n            seen_ever = seen_ever.union(set([root_ind]))\n            for to_ind in self.digraph[root_ind].edges:\n                cycle = cycle_dfs(to_ind, here)\n                if cycle:\n                    return cycle\n            return []\n\n        for ind in range(len(self.digraph)):\n            if ind not in seen_ever:\n                cycle = cycle_dfs(ind, [])\n                if cycle:\n                    return cycle\n        return []\n\n    def __contains__(self, key):\n        # Allows the syntax:\n        # 'key' in dependency_graph\n        return key in self.key2ind\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/make_dataloader.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/core.py)\nimport paddlespeech.s2t.io.speechbrain.dataloader\n\n\ndef _train_loader_specifics(self, dataset, loader_kwargs):\n    sampler = loader_kwargs.get(\"sampler\", None)\n    # Shuffling should really only matter for the train stage. Shuffling\n    # will also lead to more padding in batches if the order was otherwise\n    # sorted by length.\n    shuffle = loader_kwargs.get(\"shuffle\", False)\n    if shuffle and not self.distributed_launch:\n        if sampler is not None:\n            raise ValueError(\"Cannot specify both shuffle=True\"\n                             \"and a sampler in loader_kwargs\")\n        sampler = ReproducibleRandomSampler(dataset)\n        self.train_sampler = sampler\n        loader_kwargs[\"sampler\"] = self.train_sampler\n        # Delete the shuffle flag, since you cannot specify both a sampler and\n        # shuffling:\n        del loader_kwargs[\"shuffle\"]\n\n    # Possibly make a DistributedSampler or a wrapper for some other sampler\n    if self.distributed_launch and not isinstance(dataset, IterableDataset):\n        drop_last = loader_kwargs.get(\"drop_last\", False)\n        # num_replicas arg is equal to world_size\n        # and retrieved automatically within\n        # DistributedSampler obj.\n        if sampler is not None:\n            self.train_sampler = DistributedSamplerWrapper(\n                sampler,\n                rank=self.rank,\n                drop_last=drop_last,\n                shuffle=shuffle, )\n\n            # with DistributedSamplerWrapper, one must disable shuffling for dataloader\n            loader_kwargs[\"shuffle\"] = False\n            loader_kwargs[\"sampler\"] = self.train_sampler\n        elif loader_kwargs.get(\"batch_sampler\") is None:\n            # no sampler and batch-sampler\n            self.train_sampler = DistributedSampler(\n                dataset, rank=self.rank, shuffle=True, drop_last=drop_last)\n\n            # with DistributedSamplerWrapper, one must disable shuffling for dataloader\n            loader_kwargs[\"shuffle\"] = False\n            loader_kwargs[\"sampler\"] = self.train_sampler\n        else:  # batch_sampler was specified\n            self.train_sampler = DistributedSamplerWrapper(\n                loader_kwargs.get(\"batch_sampler\", None),\n                rank=self.rank,\n                shuffle=True, )\n            loader_kwargs[\"batch_sampler\"] = self.train_sampler\n    elif self.distributed_launch and isinstance(dataset, IterableDataset):\n        logger.warning(\"Cannot automatically solve distributed sampling \"\n                       \"for IterableDataset.\")\n    return loader_kwargs\n\n\ndef make_dataloader(self, dataset, stage, **loader_kwargs):\n    \"\"\"Creates DataLoaders for Datasets.\n\n        This is used by ``fit()`` and ``evaluate()`` if they just receive\n        Datasets.\n\n        Alternatively, this can be called from outside the Brain subclass.\n        In that case, the DataLoader should be passed to ``fit()`` in place\n        of the dataset.\n\n        The Stage.TRAIN DataLoader is handled specially. It has extra args for\n        shuffle and drop_last. In DDP a DistributedSampler is created (unless\n        the dataset is an IterableDataset).\n\n        NOTE\n        ----\n        Some important DataLoader arguments are passed via **loader_kwargs,\n        e.g., batch_size, num_workers, pin_memory.\n\n        NOTE\n        ----\n        By default, ``evaluate()`` specifies ckpt_prefix=None to stop the test\n        DataLoader being added to the checkpointer. If you need to add a\n        recoverable after saving checkpoints (e.g., at test time, after\n        checkpointing the training), and still be able to recover reasonably,\n        you should probably specify ``allow_partial_load=True``.\n\n        Arguments\n        ---------\n        dataset : Dataset\n            A set of data to use to create data loader. If the Dataset is a\n            DynamicItemDataset, PaddedBatch is used as the default collate_fn,\n            unless specified in loader_kwargs.\n        stage : Stage\n            The stage of the experiment: Stage.TRAIN, Stage.VALID, Stage.TEST\n        ckpt_prefix : str, None\n            Prefix to use for SaveableDataLoader Checkpoint name. The Stage\n            name is added to this to create the full key. Set to None to not\n            save the DataLoader.\n        **loader_kwargs : dict\n            Additional keyword arguments to the DataLoader.\n            E.g., batch_size, num_workers, pin_memory.\n        \"\"\"\n\n    dataloader_ = dataloader.make_dataloader(dataset, **loader_kwargs)\n    return dataloader_\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/sampler.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/dataio/sampler.py)\n\"\"\"compatible samplers.\n\nThese determine the order of iteration through a dataset.\n\nAuthors:\n  * Aku Rouhe 2020\n  * Samuele Cornell 2020\n  * Ralf Leibold 2020\n  * Artem Ploujnikov 2021\n  * Andreas Nautsch 2021\n\"\"\"\nimport logging\nfrom collections import Counter\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom paddle.io import RandomSampler\nfrom paddle.io import Sampler\nfrom paddle.io import WeightedRandomSampler\nfrom scipy.stats import lognorm\n\nfrom paddlespeech.s2t.io.speechbrain.dataset import DynamicItemDataset\n\nlogger = logging.getLogger(__name__)\n\n\nclass ReproducibleRandomSampler(RandomSampler):\n    \"\"\"A modification of RandomSampler which always returns the same values.\n\n    Also look at `paddle.io.RandomSampler`. This has mostly\n    the same behaviour and arguments, except for adding 'seed' and 'epoch' and\n    not supporting 'generator'.\n\n    Note\n    ----\n    Call `set_epoch` before every epoch. Otherwise, the sampler will produce the\n    same sequence of indices every epoch.\n\n    Arguments\n    ---------\n    data_source : Dataset\n        The data source to sample indices for.\n    seed : int\n        The base seed to use for the random number generator. It is recommended\n        to use a value which has a good mix of 0 and 1 bits.\n    epoch : int\n        The epoch to start at.\n\n    \"\"\"\n\n    def __init__(self, data_source, seed=563375142, epoch=0, **kwargs):\n        if \"generator\" in kwargs:\n            MSG = (\"Cannot give a separate generator when using \" +\n                   \"ReproducibleRandomSampler\")\n            raise ValueError(MSG)\n        super().__init__(data_source, **kwargs)\n        self.seed = int(seed)\n        self.epoch = epoch\n        self.gen = paddle.seed(1)\n\n    def set_epoch(self, epoch):\n        \"\"\"\n        You can also just access self.epoch, but we maintain this interface\n        to mirror paddle.io.DistributedBatchSampler\n        \"\"\"\n        self.epoch = epoch\n\n    def __iter__(self):\n        self.gen.manual_seed(self.seed + self.epoch)\n        return super().__iter__()\n\n\nclass ReproducibleWeightedRandomSampler(WeightedRandomSampler):\n    \"\"\"A reproducible modification of WeightedRandomSampler.\n\n    Also look at `paddle.io.WeightedRandomSampler`. This has the\n    the same behaviour and arguments, except for adding 'seed' and 'epoch' and\n    not supporting 'generator'.\n\n    Note\n    ----\n    Call `set_epoch` before every epoch. Otherwise, the sampler will produce the\n    same sequence of indices every epoch.\n\n    Arguments\n    ---------\n    weights : sequence of float\n        Weights for each index. Doesn't need to sum to one.\n    num_samples : int\n        Number of samples to draw\n    replacement : bool\n        To draw with replacement or not (within an epoch of num_samples).\n    seed : int\n        The base seed to use for the random number generator. It is recommended\n        to use a value which has a good mix of 0 and 1 bits.\n    epoch : int\n        The epoch to start at.\n    \"\"\"\n\n    def __init__(\n            self,\n            weights,\n            num_samples,\n            replacement,\n            seed=129491412,\n            epoch=0,\n            **kwargs, ):\n        if \"generator\" in kwargs:\n            MSG = (\"Cannot give a separate generator when using \" +\n                   \"ReproducibleRandomSampler\")\n            raise ValueError(MSG)\n        super().__init__(weights, num_samples, replacement, **kwargs)\n        self.seed = int(seed)\n        self.epoch = epoch\n        self.gen = paddle.seed(1)\n\n    def set_epoch(self, epoch):\n        \"\"\"\n        You can also just access self.epoch, but we maintain this interface\n        to mirror paddle.io.DistributedBatchSampler\n        \"\"\"\n        self.epoch = epoch\n\n    def __iter__(self):\n        self.gen.manual_seed(self.seed + self.epoch)\n        return super().__iter__()\n\n\nclass DynamicBatchSampler(Sampler):\n    \"\"\"This BatchSampler batches examples together by grouping them by their length.\n\n    Every example in the batch have approximately the same length and\n    thus padding is minimized.\n    This enables faster training on datasets\n    where length of examples can vary significantly (e.g Librispeech).\n    Inspired by: https://www.tensorflow.org/api_docs/python/tf/data/experimental/bucket_by_sequence_length\n\n    Dynamic batching is performed by specifying a max_batch_length which is the\n    upper limit for the sum of the length of examples in a batch:\n    e.g., if ex1 has length 4, ex2 length 5 and if max_batch_length is set to 6\n    ex1 and ex2 will be placed, alone, in two distinct batches.\n\n    Length for each example can be obtained in two manners.\n    If the input dataset is a DynamicItemDataset it can be obtained by specifying a\n    length_func. Default assumes a \"duration\" entry is in the annotation.\n    Length for each example can also be passed to this class upon instantiation\n    by specifying a list containing the length for each example and passing it to\n    lengths_list.\n\n    Examples are grouped together by defining a set of possible discrete intervals\n    (buckets). Examples whose length fall into these intervals can be batched together.\n\n    The number of buckets can be specified by using the arg num_buckets.\n    There is usually an optimal range for the value of this argument.\n\n    If num_buckets == 1, all examples can be batched together. You have maximum randomization\n    but your training speed will be slower due to the fact that a large amount of the values will be padding\n    as long and short examples can be batched together.\n    As the number of buckets grows only examples with similar\n    length can be grouped together.\n    This trades-off speed with randomization.\n    TLDR: Low number -> better randomization, High number -> faster training.\n    NOTE THAT: if set too high the training speed will decrease. If num_buckets -> number of examples in the \n    dataset the batch size will be small impacting training speed and possibly performance.\n\n    The buckets can also be specified by passing a list to the bucket_boundaries\n    argument instead of specifying a left_bucket_length and a bucket_length_multiplier.\n\n    \"\"\"\n\n    def __init__(\n            self,\n            dataset,\n            max_batch_length: int,\n            num_buckets: int=None,\n            length_func=lambda x: x[\"duration\"],\n            shuffle: bool=True,\n            batch_ordering: str=\"random\",\n            max_batch_ex: int=None,\n            bucket_boundaries: List[int]=[],\n            lengths_list: List[int]=None,\n            seed: int=42,\n            epoch: int=0,\n            drop_last: bool=False,\n            verbose: bool=False, ):\n        self._dataset = dataset\n        self._ex_lengths = {}\n        ex_ids = self._dataset.data_ids\n        self.verbose = verbose\n\n        # We do not put a default on num_buckets to encourage users to play with this parameter\n        if num_buckets is None and len(bucket_boundaries) == 0:\n            raise RuntimeError(\n                \"Please specify either num_buckets or bucket boundaries.\"\n                \"Check the docs, and/or the tutorial !\")\n\n        if lengths_list is not None:\n            # take length of examples from this argument and bypass length_key\n            for indx in range(len(lengths_list)):\n                self._ex_lengths[str(indx)] = lengths_list[indx]\n        else:\n            # use length func\n            if not isinstance(dataset, DynamicItemDataset):\n                raise NotImplementedError(\n                    \"Dataset should be a DynamicItemDataset when using length function\"\n                )\n            for indx in range(len(self._dataset)):\n                self._ex_lengths[str(indx)] = length_func(\n                    self._dataset.data[ex_ids[indx]])\n\n        if len(bucket_boundaries) > 0:\n            if not all([x >= 0 for x in bucket_boundaries]):\n                raise ValueError(\n                    \"All elements in bucket boundaries should be non-negative (>= 0).\"\n                )\n            if not len(set(bucket_boundaries)) == len(bucket_boundaries):\n                raise ValueError(\n                    \"Bucket_boundaries should not contain duplicates.\")\n            np.testing.assert_array_equal(\n                np.array(bucket_boundaries),\n                np.array(sorted(bucket_boundaries)),\n                err_msg=\"The arg bucket_boundaries should be an ascending sorted list of non negative values values!\",\n            )\n            self._bucket_boundaries = np.array(sorted(bucket_boundaries))\n        else:\n            # use num_buckets\n            self._bucket_boundaries = np.array(\n                self._get_boundaries_through_warping(\n                    max_batch_length=max_batch_length,\n                    num_quantiles=num_buckets, ))\n\n        self._max_batch_length = max_batch_length\n        self._shuffle_ex = shuffle\n        self._batch_ordering = batch_ordering\n        self._seed = seed\n        self._drop_last = drop_last\n        if max_batch_ex is None:\n            max_batch_ex = np.inf\n        self._max_batch_ex = max_batch_ex\n        # Calculate bucket lengths - how often does one bucket boundary fit into max_batch_length?\n        self._bucket_lens = [\n            max(1, int(max_batch_length / self._bucket_boundaries[i]))\n            for i in range(len(self._bucket_boundaries))\n        ] + [1]\n        self._epoch = epoch\n        self._generate_batches()\n\n    def get_durations(self, batch):\n        \"\"\"Gets durations of the elements in the batch.\"\"\"\n        return [self._ex_lengths[str(idx)] for idx in batch]\n\n    def _get_boundaries_through_warping(\n            self,\n            max_batch_length: int,\n            num_quantiles: int, ) -> List[int]:\n\n        # NOTE: the following lines do not cover that there is only one example in the dataset\n        # warp frames (duration) distribution of train data\n        logger.info(\"Batch quantisation in latent space\")\n        # linspace set-up\n        num_boundaries = num_quantiles + 1\n        # create latent linearly equal spaced buckets\n        latent_boundaries = np.linspace(\n            1 / num_boundaries,\n            num_quantiles / num_boundaries,\n            num_quantiles, )\n        # get quantiles using lognormal distribution\n        quantiles = lognorm.ppf(latent_boundaries, 1)\n        # scale up to max_batch_length\n        bucket_boundaries = quantiles * max_batch_length / quantiles[-1]\n        # compute resulting bucket length multipliers\n        length_multipliers = [\n            bucket_boundaries[x + 1] / bucket_boundaries[x]\n            for x in range(num_quantiles - 1)\n        ]\n        # logging\n        logger.info(\n            \"Latent bucket boundary - buckets: {} - length multipliers: {}\".\n            format(\n                list(map(\"{:.2f}\".format, bucket_boundaries)),\n                list(map(\"{:.2f}\".format, length_multipliers)), ))\n        return list(sorted(bucket_boundaries))\n\n    def _permute_batches(self):\n\n        if self._batch_ordering == \"random\":\n            # deterministically shuffle based on epoch and seed\n            gen = paddle.seed(1)\n            gen.manual_seed(self._seed + self._epoch)\n            sampler = paddle.randperm(\n                len(self._batches)).tolist()  # type: ignore\n            tmp = []\n            for idx in sampler:\n                tmp.append(self._batches[idx])\n            self._batches = tmp\n\n        elif self._batch_ordering == \"ascending\":\n            self._batches = sorted(\n                self._batches,\n                key=lambda x: max([self._ex_lengths[str(idx)] for idx in x]), )\n        elif self._batch_ordering == \"descending\":\n            self._batches = sorted(\n                self._batches,\n                key=lambda x: max([self._ex_lengths[str(idx)] for idx in x]),\n                reverse=True, )\n        else:\n            raise NotImplementedError\n\n    def _generate_batches(self):\n        logger.info(\"DynamicBatchSampler: Generating dynamic batches\")\n        if self._shuffle_ex:\n            # deterministically shuffle based on epoch and seed\n            gen = paddle.seed(1)\n            gen.manual_seed(self._seed + self._epoch)\n            sampler = paddle.randperm(\n                len(self._dataset)).tolist()  # type: ignore\n        else:\n            # take examples as they are: e.g. they have been sorted\n            sampler = range(len(self._dataset))  # type: ignore\n\n        self._batches = []\n        bucket_batches = [[] for i in self._bucket_lens]\n\n        stats_tracker = [{\n            \"min\": np.inf,\n            \"max\": -np.inf,\n            \"tot\": 0,\n            \"n_ex\": 0\n        } for i in self._bucket_lens]\n\n        for idx in sampler:\n            # length of pre-sampled audio\n            item_len = self._ex_lengths[str(idx)]\n            # bucket to fill up most padding\n            bucket_id = np.searchsorted(self._bucket_boundaries, item_len)\n            # fill audio's duration into that bucket\n            bucket_batches[bucket_id].append(idx)\n\n            stats_tracker[bucket_id][\"min\"] = min(\n                stats_tracker[bucket_id][\"min\"], item_len)\n            stats_tracker[bucket_id][\"max\"] = max(\n                stats_tracker[bucket_id][\"max\"], item_len)\n            stats_tracker[bucket_id][\"tot\"] += item_len\n            stats_tracker[bucket_id][\"n_ex\"] += 1\n            # track #samples - why not duration/#frames; rounded up?\n            # keep track of durations, if necessary\n\n            if (len(bucket_batches[bucket_id]) >= self._bucket_lens[bucket_id]\n                    or len(bucket_batches[bucket_id]) >= self._max_batch_ex):\n                self._batches.append(bucket_batches[bucket_id])\n                bucket_batches[bucket_id] = []\n                # keep track of durations\n\n            # Dump remaining batches\n        if not self._drop_last:\n            for batch in bucket_batches:\n                if batch:\n                    self._batches.append(batch)\n\n        self._permute_batches()  # possibly reorder batches\n\n        if self._epoch == 0:  # only log at first epoch\n            # frames per batch & their padding remaining\n            boundaries = [0] + self._bucket_boundaries.tolist()\n\n            for bucket_indx in range(len(self._bucket_boundaries)):\n                try:\n                    num_batches = stats_tracker[bucket_indx][\"tot\"] // (\n                        self._max_batch_length)\n                    pad_factor = (stats_tracker[bucket_indx][\"max\"] -\n                                  stats_tracker[bucket_indx][\"min\"]) / (\n                                      stats_tracker[bucket_indx][\"tot\"] /\n                                      stats_tracker[bucket_indx][\"n_ex\"])\n                except ZeroDivisionError:\n                    num_batches = 0\n                    pad_factor = 0\n\n                logger.info((\n                    \"DynamicBatchSampler: Bucket {} with boundary {:.1f}-{:.1f} and \"\n                    +\n                    \"batch_size {}: Num Examples {:.1f}, Num Full Batches {:.3f}, Pad Factor {:.3f}.\"\n                ).format(\n                    bucket_indx,\n                    boundaries[bucket_indx],\n                    boundaries[bucket_indx + 1],\n                    self._bucket_lens[bucket_indx],\n                    stats_tracker[bucket_indx][\"n_ex\"],\n                    num_batches,\n                    pad_factor * 100, ))\n\n            if self.verbose:\n                batch_stats = {\n                    \"tot_frames\": [],\n                    \"tot_pad_frames\": [],\n                    \"pad_%\": [],\n                }\n                for batch in self._batches:\n                    tot_frames = sum(\n                        [self._ex_lengths[str(idx)] for idx in batch])\n                    batch_stats[\"tot_frames\"].append(tot_frames)\n                    max_frames = max(\n                        [self._ex_lengths[str(idx)] for idx in batch])\n                    tot_pad = sum([\n                        max_frames - self._ex_lengths[str(idx)] for idx in batch\n                    ])\n                    batch_stats[\"tot_pad_frames\"].append(tot_pad)\n                    batch_stats[\"pad_%\"].append(tot_pad / tot_frames * 100)\n\n                padding_details = \"Batch {} with {:.1f} frames with {} files - {:.1f} padding, {:.2f} (%) of total.\"\n                padding_details = \"DynamicBatchSampler: \" + padding_details\n                for i in range(len(self._batches)):\n                    logger.info(\n                        padding_details.format(\n                            i,\n                            batch_stats[\"tot_frames\"][i],\n                            len(self._batches[i]),\n                            batch_stats[\"tot_pad_frames\"][i],\n                            batch_stats[\"pad_%\"][i], ))\n\n    def __iter__(self):\n        for batch in self._batches:\n            yield batch\n        if self._shuffle_ex:  # re-generate examples if ex_ordering == \"random\"\n            self._generate_batches()\n        if self._batch_ordering == \"random\":\n            # we randomly permute the batches only --> faster\n            self._permute_batches()\n\n    def set_epoch(self, epoch):\n        \"\"\"\n        You can also just access self.epoch, but we maintain this interface\n        to mirror paddle.io.DistributedBatchSampler\n        \"\"\"\n        self._epoch = epoch\n        self._generate_batches()\n\n    def __len__(self):\n        return len(self._batches)\n\n\nclass BalancingDataSampler(ReproducibleWeightedRandomSampler):\n    \"\"\"A data sampler that takes a single key from the dataset and\n    ensures an approximately equal distribution by that key\n\n    Arguments\n    ---------\n    dataset: DynamicItemDataset\n        the dataset form which samples will be drawn\n    key: str\n        the key from which samples will be taken\n    num_samples : int\n        Number of samples to draw\n    replacement : bool\n        To draw with replacement or not (within an epoch of num_samples).\n    seed : int\n        The base seed to use for the random number generator. It is recommended\n        to use a value which has a good mix of 0 and 1 bits.\n    epoch : int\n        The epoch to start at.\n\n    \"\"\"\n\n    def __init__(\n            self,\n            dataset,\n            key,\n            num_samples=None,\n            replacement=True,\n            seed=563375142,\n            epoch=0,\n            **kwargs, ):\n        self.dataset = dataset\n        self.key = key\n        if not num_samples:\n            num_samples = len(dataset)\n        weights = self._compute_weights()\n        super().__init__(weights, num_samples, replacement, seed, epoch,\n                         **kwargs)\n\n    def _compute_weights(self):\n        with self.dataset.output_keys_as([self.key]):\n            class_ids = [item[self.key] for item in self.dataset]\n            class_counter = Counter(class_ids)\n        weights = 1 / paddle.to_tensor(\n            [class_counter[class_id] for class_id in class_ids])\n        return weights\n"
  },
  {
    "path": "paddlespeech/s2t/io/speechbrain/sb_pipeline.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# \n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/recipes/AISHELL-1/ASR/CTC/train_with_wav2vec.py)\nimport data_pipeline\nimport dataio\nimport numpy\nimport paddle\nimport tqdm\nimport transformers\nfrom dataloader import make_dataloader\nfrom hyperpyyaml import load_hyperpyyaml\n\nimport dataset\n\n\ndef dataio_prepare(hparams):\n    \"\"\"This function prepares the datasets to be used in the brain class.\n    It also defines the data processing pipeline through user-defined functions.\"\"\"\n    data_folder = hparams[\"data_folder\"]\n\n    train_data = dataset.DynamicItemDataset.from_csv(\n        csv_path=hparams[\"train_data\"],\n        replacements={\"data_root\": data_folder}, )\n\n    if hparams[\"sorting\"] == \"ascending\":\n        # we sort training data to speed up training and get better results.\n        train_data = train_data.filtered_sorted(sort_key=\"duration\")\n        # when sorting do not shuffle in dataloader ! otherwise is pointless\n        hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n    elif hparams[\"sorting\"] == \"descending\":\n        train_data = train_data.filtered_sorted(\n            sort_key=\"duration\", reverse=True)\n        # when sorting do not shuffle in dataloader ! otherwise is pointless\n        hparams[\"train_dataloader_opts\"][\"shuffle\"] = False\n\n    elif hparams[\"sorting\"] == \"random\":\n        pass\n\n    else:\n        raise NotImplementedError(\n            \"sorting must be random, ascending or descending\")\n\n    valid_data = dataset.DynamicItemDataset.from_csv(\n        csv_path=hparams[\"valid_data\"],\n        replacements={\"data_root\": data_folder}, )\n    valid_data = valid_data.filtered_sorted(sort_key=\"duration\")\n\n    test_data = dataset.DynamicItemDataset.from_csv(\n        csv_path=hparams[\"test_data\"],\n        replacements={\"data_root\": data_folder}, )\n    test_data = test_data.filtered_sorted(sort_key=\"duration\")\n\n    datasets = [train_data, valid_data, test_data]\n\n    # Defining tokenizer and loading it\n    tokenizer = transformers.BertTokenizer.from_pretrained('bert-base-chinese')\n\n    # 2. Define audio pipeline:\n    @data_pipeline.takes(\"wav\")\n    @data_pipeline.provides(\"sig\")\n    def audio_pipeline(wav):\n        sig = dataio.read_audio(wav)\n        return sig\n\n    dataset.add_dynamic_item(datasets, audio_pipeline)\n\n    # 3. Define text pipeline:\n    @data_pipeline.takes(\"transcript\")\n    @data_pipeline.provides(\"wrd\", \"tokens_list\", \"tokens\")\n    def text_pipeline(wrd):\n        wrd = \"\".join(wrd.split(\" \"))\n        yield wrd\n        tokens_list = tokenizer(wrd)[\"input_ids\"]\n        yield tokens_list\n        tokens = numpy.array(tokens_list, dtype=\"int64\")\n        yield tokens\n\n    dataset.add_dynamic_item(datasets, text_pipeline)\n\n    # 4. Set output:\n    dataset.set_output_keys(\n        datasets,\n        [\"id\", \"sig\", \"wrd\", \"tokens\"], )\n\n    # 5. If Dynamic Batching is used, we instantiate the needed samplers.\n    train_batch_sampler = None\n    valid_batch_sampler = None\n    if hparams[\"dynamic_batching\"]:\n        from sampler import DynamicBatchSampler  # noqa\n\n        dynamic_hparams = hparams[\"dynamic_batch_sampler\"]\n        num_buckets = dynamic_hparams[\"num_buckets\"]\n\n        train_batch_sampler = DynamicBatchSampler(\n            train_data,\n            dynamic_hparams[\"max_batch_len\"],\n            num_buckets=num_buckets,\n            length_func=lambda x: x[\"duration\"],\n            shuffle=dynamic_hparams[\"shuffle_ex\"],\n            batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n        valid_batch_sampler = DynamicBatchSampler(\n            valid_data,\n            dynamic_hparams[\"max_batch_len\"],\n            num_buckets=num_buckets,\n            length_func=lambda x: x[\"duration\"],\n            shuffle=dynamic_hparams[\"shuffle_ex\"],\n            batch_ordering=dynamic_hparams[\"batch_ordering\"], )\n\n    return (train_data, valid_data, test_data, tokenizer, train_batch_sampler,\n            valid_batch_sampler, )\n\n\nhparams_file = 'train_with_wav2vec.yaml'\nwith open(hparams_file) as fin:\n    hparams = load_hyperpyyaml(fin, None)\n\n(train_data, valid_data, test_data, tokenizer, train_bsampler,\n valid_bsampler, ) = dataio_prepare(hparams)\n\ntrain_dataloader_opts = hparams[\"train_dataloader_opts\"]\nvalid_dataloader_opts = hparams[\"valid_dataloader_opts\"]\n\nif train_bsampler is not None:\n    train_dataloader_opts = {\n        \"batch_sampler\": train_bsampler,\n        \"num_workers\": hparams[\"num_workers\"],\n    }\n\nif valid_bsampler is not None:\n    valid_dataloader_opts = {\"batch_sampler\": valid_bsampler}\n\ntrain_set = make_dataloader(train_data, stage='train', **train_dataloader_opts)\n\nvalid_set = make_dataloader(\n    valid_data,\n    stage='train',\n    **valid_dataloader_opts, )\n\nfor batch in valid_set:\n    print(batch)\nprint('done')  # exit()\n"
  },
  {
    "path": "paddlespeech/s2t/io/utility.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom io import BytesIO\nfrom typing import List\n\nimport numpy as np\n\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"pad_list\", \"pad_sequence\", \"feat_type\"]\n\nlogger = Log(__name__).getlog()\n\n\ndef pad_list(sequences: List[np.ndarray],\n             padding_value: float=0.0) -> np.ndarray:\n    return pad_sequence(sequences, True, padding_value)\n\n\ndef pad_sequence(sequences: List[np.ndarray],\n                 batch_first: bool=True,\n                 padding_value: float=0.0) -> np.ndarray:\n    r\"\"\"Pad a list of variable length Tensors with ``padding_value``\n\n    ``pad_sequence`` stacks a list of Tensors along a new dimension,\n    and pads them to equal length. For example, if the input is list of\n    sequences with size ``L x *`` and if batch_first is False, and ``T x B x *``\n    otherwise.\n\n    `B` is batch size. It is equal to the number of elements in ``sequences``.\n    `T` is length of the longest sequence.\n    `L` is length of the sequence.\n    `*` is any number of trailing dimensions, including none.\n\n    Example:\n        >>> a = np.ones([25, 300])\n        >>> b = np.ones([22, 300])\n        >>> c = np.ones([15, 300])\n        >>> pad_sequence([a, b, c]).shape\n        [25, 3, 300]\n\n    Note:\n        This function returns a np.ndarray of size ``T x B x *`` or ``B x T x *``\n        where `T` is the length of the longest sequence. This function assumes\n        trailing dimensions and type of all the Tensors in sequences are same.\n\n    Args:\n        sequences (list[np.ndarray]): list of variable length sequences.\n        batch_first (bool, optional): output will be in ``B x T x *`` if True, or in\n            ``T x B x *`` otherwise\n        padding_value (float, optional): value for padded elements. Default: 0.\n\n    Returns:\n        np.ndarray of size ``T x B x *`` if :attr:`batch_first` is ``False``.\n        np.ndarray of size ``B x T x *`` otherwise\n    \"\"\"\n\n    # assuming trailing dimensions and type of all the Tensors\n    # in sequences are same and fetching those from sequences[0]\n    max_size = sequences[0].shape\n    trailing_dims = max_size[1:]\n    max_len = max([s.shape[0] for s in sequences])\n    if batch_first:\n        out_dims = (len(sequences), max_len) + trailing_dims\n    else:\n        out_dims = (max_len, len(sequences)) + trailing_dims\n\n    out_tensor = np.full(out_dims, padding_value, dtype=sequences[0].dtype)\n    for i, tensor in enumerate(sequences):\n        length = tensor.shape[0]\n        # use index notation to prevent duplicate references to the tensor\n        if batch_first:\n            out_tensor[i, :length, ...] = tensor\n        else:\n            out_tensor[:length, i, ...] = tensor\n\n    return out_tensor\n\n\ndef feat_type(filepath):\n    # deal with Byteio type for paddlespeech server\n    if isinstance(filepath, BytesIO):\n        return 'sound'\n\n    suffix = filepath.split(\":\")[0].split('.')[-1].lower()\n    if suffix == 'ark':\n        return 'mat'\n    elif suffix == 'scp':\n        return 'scp'\n    elif suffix == 'npy':\n        return 'npy'\n    elif suffix == 'npz':\n        return 'npz'\n    elif suffix in ['wav', 'flac']:\n        # PCM16\n        return 'sound'\n    else:\n        raise ValueError(f\"Not support filetype: {suffix}\")\n"
  },
  {
    "path": "paddlespeech/s2t/models/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/models/asr_interface.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"ASR Interface module.\"\"\"\nimport argparse\n\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\n\nclass ASRInterface:\n    \"\"\"ASR Interface model implementation.\"\"\"\n\n    @staticmethod\n    def add_arguments(parser):\n        \"\"\"Add arguments to parser.\"\"\"\n        return parser\n\n    @classmethod\n    def build(cls, idim: int, odim: int, **kwargs):\n        \"\"\"Initialize this class with python-level args.\n\n        Args:\n            idim (int): The number of an input feature dim.\n            odim (int): The number of output vocab.\n\n        Returns:\n            ASRinterface: A new instance of ASRInterface.\n\n        \"\"\"\n        args = argparse.Namespace(**kwargs)\n        return cls(idim, odim, args)\n\n    def forward(self, xs, ilens, ys, olens):\n        \"\"\"Compute loss for training.\n\n        :param xs: batch of padded source sequences paddle.Tensor (B, Tmax, idim)\n        :param ilens: batch of lengths of source sequences (B), paddle.Tensor\n        :param ys: batch of padded target sequences paddle.Tensor (B, Lmax)\n        :param olens: batch of lengths of target sequences (B), paddle.Tensor\n        :return: loss value\n        :rtype: paddle.Tensor\n        \"\"\"\n        raise NotImplementedError(\"forward method is not implemented\")\n\n    def recognize(self, x, recog_args, char_list=None, rnnlm=None):\n        \"\"\"Recognize x for evaluation.\n\n        :param ndarray x: input acouctic feature (B, T, D) or (T, D)\n        :param namespace recog_args: argment namespace contraining options\n        :param list char_list: list of characters\n        :param paddle.nn.Layer rnnlm: language model module\n        :return: N-best decoding results\n        :rtype: list\n        \"\"\"\n        raise NotImplementedError(\"recognize method is not implemented\")\n\n    def recognize_batch(self, x, recog_args, char_list=None, rnnlm=None):\n        \"\"\"Beam search implementation for batch.\n\n        :param paddle.Tensor x: encoder hidden state sequences (B, Tmax, Henc)\n        :param namespace recog_args: argument namespace containing options\n        :param list char_list: list of characters\n        :param paddle.nn.Module rnnlm: language model module\n        :return: N-best decoding results\n        :rtype: list\n        \"\"\"\n        raise NotImplementedError(\"Batch decoding is not supported yet.\")\n\n    def calculate_all_attentions(self, xs, ilens, ys):\n        \"\"\"Calculate attention.\n\n        :param list xs: list of padded input sequences [(T1, idim), (T2, idim), ...]\n        :param ndarray ilens: batch of lengths of input sequences (B)\n        :param list ys: list of character id sequence tensor [(L1), (L2), (L3), ...]\n        :return: attention weights (B, Lmax, Tmax)\n        :rtype: float ndarray\n        \"\"\"\n        raise NotImplementedError(\n            \"calculate_all_attentions method is not implemented\")\n\n    def calculate_all_ctc_probs(self, xs, ilens, ys):\n        \"\"\"Calculate CTC probability.\n\n        :param list xs_pad: list of padded input sequences [(T1, idim), (T2, idim), ...]\n        :param ndarray ilens: batch of lengths of input sequences (B)\n        :param list ys: list of character id sequence tensor [(L1), (L2), (L3), ...]\n        :return: CTC probabilities (B, Tmax, vocab)\n        :rtype: float ndarray\n        \"\"\"\n        raise NotImplementedError(\n            \"calculate_all_ctc_probs method is not implemented\")\n\n    @property\n    def attention_plot_class(self):\n        \"\"\"Get attention plot class.\"\"\"\n        from paddlespeech.s2t.training.extensions.plot import PlotAttentionReport\n\n        return PlotAttentionReport\n\n    @property\n    def ctc_plot_class(self):\n        \"\"\"Get CTC plot class.\"\"\"\n        from paddlespeech.s2t.training.extensions.plot import PlotCTCReport\n\n        return PlotCTCReport\n\n    def get_total_subsampling_factor(self):\n        \"\"\"Get total subsampling factor.\"\"\"\n        raise NotImplementedError(\n            \"get_total_subsampling_factor method is not implemented\")\n\n    def encode(self, feat):\n        \"\"\"Encode feature in `beam_search` (optional).\n\n        Args:\n            x (numpy.ndarray): input feature (T, D)\n        Returns:\n            paddle.Tensor: encoded feature (T, D)\n        \"\"\"\n        raise NotImplementedError(\"encode method is not implemented\")\n\n    def scorers(self):\n        \"\"\"Get scorers for `beam_search` (optional).\n\n        Returns:\n            dict[str, ScorerInterface]: dict of `ScorerInterface` objects\n\n        \"\"\"\n        raise NotImplementedError(\"decoders method is not implemented\")\n\n\npredefined_asr = {\n    \"transformer\": \"paddlespeech.s2t.models.u2:U2Model\",\n    \"conformer\": \"paddlespeech.s2t.models.u2:U2Model\",\n}\n\n\ndef dynamic_import_asr(module):\n    \"\"\"Import ASR models dynamically.\n\n    Args:\n        module (str): asr name. e.g., transformer, conformer\n\n    Returns:\n        type: ASR class\n\n    \"\"\"\n    model_class = dynamic_import(module, predefined_asr)\n    assert issubclass(model_class,\n                      ASRInterface), f\"{module} does not implement ASRInterface\"\n    return model_class\n"
  },
  {
    "path": "paddlespeech/s2t/models/ds2/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nfrom .deepspeech2 import DeepSpeech2InferModel\nfrom .deepspeech2 import DeepSpeech2Model\nfrom paddlespeech.s2t.utils import dynamic_pip_install\n\ntry:\n    import paddlespeech_ctcdecoders\nexcept ImportError:\n    try:\n        package_name = 'paddlespeech_ctcdecoders'\n        if sys.platform != \"win32\":\n            dynamic_pip_install.install(package_name)\n    except Exception:\n        raise RuntimeError(\n            \"Can not install package paddlespeech_ctcdecoders on your system. \\\n                The DeepSpeech2 model is not supported for your system\")\n\n__all__ = ['DeepSpeech2Model', 'DeepSpeech2InferModel']\n"
  },
  {
    "path": "paddlespeech/s2t/models/ds2/conv.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\n\nfrom paddlespeech.s2t.modules.subsampling import Conv2dSubsampling4\n\n\nclass Conv2dSubsampling4Pure(Conv2dSubsampling4):\n    def __init__(self, idim: int, odim: int, dropout_rate: float):\n        super().__init__(idim, odim, dropout_rate, None)\n        self.output_dim = ((idim - 1) // 2 - 1) // 2 * odim\n        self.receptive_field_length = 2 * (\n            3 - 1) + 3  # stride_1 * (kernel_size_2 - 1) + kerel_size_1\n\n    def forward(self, x: paddle.Tensor,\n                x_len: paddle.Tensor) -> [paddle.Tensor, paddle.Tensor]:\n        x = x.unsqueeze(1)  # (b, c=1, t, f)\n        x = self.conv(x)\n        #b, c, t, f = paddle.shape(x) #not work under jit\n        x = x.transpose([0, 2, 1, 3]).reshape([0, 0, -1])\n        x_len = ((x_len - 1) // 2 - 1) // 2\n        return x, x_len\n"
  },
  {
    "path": "paddlespeech/s2t/models/ds2/deepspeech2.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Deepspeech2 ASR Model\"\"\"\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.s2t.models.ds2.conv import Conv2dSubsampling4Pure\nfrom paddlespeech.s2t.modules.ctc import CTCDecoder\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils.checkpoint import Checkpoint\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n__all__ = ['DeepSpeech2Model', 'DeepSpeech2InferModel']\n\n\nclass CRNNEncoder(nn.Layer):\n    def __init__(self,\n                 feat_size,\n                 dict_size,\n                 num_conv_layers=2,\n                 num_rnn_layers=4,\n                 rnn_size=1024,\n                 rnn_direction='forward',\n                 num_fc_layers=2,\n                 fc_layers_size_list=[512, 256],\n                 use_gru=False):\n        super().__init__()\n        self.rnn_size = rnn_size\n        self.feat_size = feat_size  # 161 for linear\n        self.dict_size = dict_size\n        self.num_rnn_layers = num_rnn_layers\n        self.num_fc_layers = num_fc_layers\n        self.rnn_direction = rnn_direction\n        self.fc_layers_size_list = fc_layers_size_list\n        self.use_gru = use_gru\n        self.conv = Conv2dSubsampling4Pure(feat_size, 32, dropout_rate=0.0)\n\n        self.output_dim = self.conv.output_dim\n\n        i_size = self.conv.output_dim\n        self.rnn = nn.LayerList()\n        self.layernorm_list = nn.LayerList()\n        self.fc_layers_list = nn.LayerList()\n        if rnn_direction == 'bidirect' or rnn_direction == 'bidirectional':\n            layernorm_size = 2 * rnn_size\n        elif rnn_direction == 'forward':\n            layernorm_size = rnn_size\n        else:\n            raise Exception(\"Wrong rnn direction\")\n        for i in range(0, num_rnn_layers):\n            if i == 0:\n                rnn_input_size = i_size\n            else:\n                rnn_input_size = layernorm_size\n            if use_gru is True:\n                self.rnn.append(\n                    nn.GRU(\n                        input_size=rnn_input_size,\n                        hidden_size=rnn_size,\n                        num_layers=1,\n                        direction=rnn_direction))\n            else:\n                self.rnn.append(\n                    nn.LSTM(\n                        input_size=rnn_input_size,\n                        hidden_size=rnn_size,\n                        num_layers=1,\n                        direction=rnn_direction))\n            self.layernorm_list.append(nn.LayerNorm(layernorm_size))\n            self.output_dim = layernorm_size\n\n        fc_input_size = layernorm_size\n        for i in range(self.num_fc_layers):\n            self.fc_layers_list.append(\n                nn.Linear(fc_input_size, fc_layers_size_list[i]))\n            fc_input_size = fc_layers_size_list[i]\n            self.output_dim = fc_layers_size_list[i]\n\n    @property\n    def output_size(self):\n        return self.output_dim\n\n    def forward(self, x, x_lens, init_state_h_box=None, init_state_c_box=None):\n        \"\"\"Compute Encoder outputs\n\n        Args:\n            x (Tensor): [B, T, D]\n            x_lens (Tensor): [B]\n            init_state_h_box(Tensor): init_states h for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n            init_state_c_box(Tensor): init_states c for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n        Return:\n            x (Tensor): encoder outputs, [B, T, D]\n            x_lens (Tensor): encoder length, [B]\n            final_state_h_box(Tensor): final_states h for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n            final_state_c_box(Tensor): final_states c for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n        \"\"\"\n        if init_state_h_box is not None:\n            init_state_list = None\n\n            if self.use_gru is True:\n                init_state_h_list = paddle.split(\n                    init_state_h_box, self.num_rnn_layers, axis=0)\n                init_state_list = init_state_h_list\n            else:\n                init_state_h_list = paddle.split(\n                    init_state_h_box, self.num_rnn_layers, axis=0)\n                init_state_c_list = paddle.split(\n                    init_state_c_box, self.num_rnn_layers, axis=0)\n                init_state_list = [(init_state_h_list[i], init_state_c_list[i])\n                                   for i in range(self.num_rnn_layers)]\n        else:\n            init_state_list = [None] * self.num_rnn_layers\n\n        x, x_lens = self.conv(x, x_lens)\n        final_chunk_state_list = []\n        for i in range(0, self.num_rnn_layers):\n            x, final_state = self.rnn[i](x, init_state_list[i],\n                                         x_lens)  #[B, T, D]\n            final_chunk_state_list.append(final_state)\n            x = self.layernorm_list[i](x)\n\n        for i in range(self.num_fc_layers):\n            x = self.fc_layers_list[i](x)\n            x = F.relu(x)\n\n        if self.use_gru is True:\n            final_chunk_state_h_box = paddle.concat(\n                final_chunk_state_list, axis=0)\n            final_chunk_state_c_box = init_state_c_box\n        else:\n            final_chunk_state_h_list = [\n                final_chunk_state_list[i][0] for i in range(self.num_rnn_layers)\n            ]\n            final_chunk_state_c_list = [\n                final_chunk_state_list[i][1] for i in range(self.num_rnn_layers)\n            ]\n            final_chunk_state_h_box = paddle.concat(\n                final_chunk_state_h_list, axis=0)\n            final_chunk_state_c_box = paddle.concat(\n                final_chunk_state_c_list, axis=0)\n\n        return x, x_lens, final_chunk_state_h_box, final_chunk_state_c_box\n\n    def forward_chunk_by_chunk(self, x, x_lens, decoder_chunk_size=8):\n        \"\"\"Compute Encoder outputs\n\n        Args:\n            x (Tensor): [B, T, D]\n            x_lens (Tensor): [B]\n            decoder_chunk_size: The chunk size of decoder\n        Returns:\n            eouts_list (List of Tensor): The list of encoder outputs in chunk_size: [B, chunk_size, D] * num_chunks\n            eouts_lens_list (List of Tensor): The list of  encoder length in chunk_size: [B] * num_chunks\n            final_state_h_box(Tensor): final_states h for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n            final_state_c_box(Tensor): final_states c for RNN layers: [num_rnn_layers * num_directions, batch_size, hidden_size]\n        \"\"\"\n        subsampling_rate = self.conv.subsampling_rate\n        receptive_field_length = self.conv.receptive_field_length\n        chunk_size = (decoder_chunk_size - 1\n                      ) * subsampling_rate + receptive_field_length\n        chunk_stride = subsampling_rate * decoder_chunk_size\n        max_len = x.shape[1]\n        assert (chunk_size <= max_len)\n\n        eouts_chunk_list = []\n        eouts_chunk_lens_list = []\n        if (max_len - chunk_size) % chunk_stride != 0:\n            padding_len = chunk_stride - (max_len - chunk_size) % chunk_stride\n        else:\n            padding_len = 0\n        padding = paddle.zeros((x.shape[0], padding_len, x.shape[2]))\n        padded_x = paddle.concat([x, padding], axis=1)\n        num_chunk = (max_len + padding_len - chunk_size) / chunk_stride + 1\n        num_chunk = int(num_chunk)\n        chunk_state_h_box = None\n        chunk_state_c_box = None\n        final_state_h_box = None\n        final_state_c_box = None\n        for i in range(0, num_chunk):\n            start = i * chunk_stride\n            end = start + chunk_size\n            x_chunk = padded_x[:, start:end, :]\n\n            x_len_left = paddle.where(x_lens - i * chunk_stride < 0,\n                                      paddle.zeros_like(x_lens),\n                                      x_lens - i * chunk_stride)\n            x_chunk_len_tmp = paddle.ones_like(x_lens) * chunk_size\n            x_chunk_lens = paddle.where(x_len_left < x_chunk_len_tmp,\n                                        x_len_left, x_chunk_len_tmp)\n\n            eouts_chunk, eouts_chunk_lens, chunk_state_h_box, chunk_state_c_box = self.forward(\n                x_chunk, x_chunk_lens, chunk_state_h_box, chunk_state_c_box)\n\n            eouts_chunk_list.append(eouts_chunk)\n            eouts_chunk_lens_list.append(eouts_chunk_lens)\n        final_state_h_box = chunk_state_h_box\n        final_state_c_box = chunk_state_c_box\n        return eouts_chunk_list, eouts_chunk_lens_list, final_state_h_box, final_state_c_box\n\n\nclass DeepSpeech2Model(nn.Layer):\n    \"\"\"The DeepSpeech2 network structure.\n\n    :param audio: Audio spectrogram data layer.\n    :type audio: Variable\n    :param text: Transcription text data layer.\n    :type text: Variable\n    :param audio_len: Valid sequence length data layer.\n    :type audio_len: Variable\n    :param feat_size: feature size for audio.\n    :type feat_size: int\n    :param dict_size: Dictionary size for tokenized transcription.\n    :type dict_size: int\n    :param num_conv_layers: Number of stacking convolution layers.\n    :type num_conv_layers: int\n    :param num_rnn_layers: Number of stacking RNN layers.\n    :type num_rnn_layers: int\n    :param rnn_size: RNN layer size (dimension of RNN cells).\n    :type rnn_size: int\n    :param num_fc_layers: Number of stacking FC layers.\n    :type num_fc_layers: int\n    :param fc_layers_size_list: The list of FC layer sizes.\n    :type fc_layers_size_list: [int,]\n    :param use_gru: Use gru if set True. Use simple rnn if set False.\n    :type use_gru: bool\n    :return: A tuple of an output unnormalized log probability layer (\n             before softmax) and a ctc cost layer.\n    :rtype: tuple of LayerOutput\n    \"\"\"\n\n    def __init__(\n            self,\n            feat_size,\n            dict_size,\n            num_conv_layers=2,\n            num_rnn_layers=4,\n            rnn_size=1024,\n            rnn_direction='forward',\n            num_fc_layers=2,\n            fc_layers_size_list=[512, 256],\n            use_gru=False,\n            blank_id=0,\n            ctc_grad_norm_type=None, ):\n        super().__init__()\n        self.encoder = CRNNEncoder(\n            feat_size=feat_size,\n            dict_size=dict_size,\n            num_conv_layers=num_conv_layers,\n            num_rnn_layers=num_rnn_layers,\n            rnn_direction=rnn_direction,\n            num_fc_layers=num_fc_layers,\n            fc_layers_size_list=fc_layers_size_list,\n            rnn_size=rnn_size,\n            use_gru=use_gru)\n\n        self.decoder = CTCDecoder(\n            odim=dict_size,  # <blank> is in  vocab\n            enc_n_units=self.encoder.output_size,\n            blank_id=blank_id,\n            dropout_rate=0.0,\n            reduction=True,  # sum\n            batch_average=True,  # sum / batch_size\n            grad_norm_type=ctc_grad_norm_type)\n\n    def forward(self, audio, audio_len, text, text_len):\n        \"\"\"Compute Model loss\n\n        Args:\n            audio (Tensor): [B, T, D]\n            audio_len (Tensor): [B]\n            text (Tensor): [B, U]\n            text_len (Tensor): [B]\n\n        Returns:\n            loss (Tensor): [1]\n        \"\"\"\n        eouts, eouts_len, final_state_h_box, final_state_c_box = self.encoder(\n            audio, audio_len, None, None)\n        loss = self.decoder(eouts, eouts_len, text, text_len)\n        return loss\n\n    @paddle.no_grad()\n    def decode(self, audio, audio_len):\n        # decoders only accept string encoded in utf-8\n        # Make sure the decoder has been initialized\n        eouts, eouts_len, final_state_h_box, final_state_c_box = self.encoder(\n            audio, audio_len, None, None)\n        probs = self.decoder.softmax(eouts)\n        batch_size = probs.shape[0]\n        self.decoder.reset_decoder(batch_size=batch_size)\n        self.decoder.next(probs, eouts_len)\n        trans_best, trans_beam = self.decoder.decode()\n        return trans_best\n\n    @classmethod\n    def from_pretrained(cls, dataloader, config, checkpoint_path):\n        \"\"\"Build a DeepSpeech2Model model from a pretrained model.\n        Parameters\n        ----------\n        dataloader: paddle.io.DataLoader\n\n        config: yacs.config.CfgNode\n            model configs\n\n        checkpoint_path: Path or str\n            the path of pretrained model checkpoint, without extension name\n\n        Returns\n        -------\n        DeepSpeech2Model\n            The model built from pretrained result.\n        \"\"\"\n        model = cls(\n            feat_size=dataloader.feat_dim,\n            dict_size=dataloader.vocab_size,\n            num_conv_layers=config.num_conv_layers,\n            num_rnn_layers=config.num_rnn_layers,\n            rnn_size=config.rnn_layer_size,\n            rnn_direction=config.rnn_direction,\n            num_fc_layers=config.num_fc_layers,\n            fc_layers_size_list=config.fc_layers_size_list,\n            use_gru=config.use_gru,\n            blank_id=config.blank_id,\n            ctc_grad_norm_type=config.get('ctc_grad_norm_type', None), )\n        infos = Checkpoint().load_parameters(\n            model, checkpoint_path=checkpoint_path)\n        logger.info(f\"checkpoint info: {infos}\")\n        layer_tools.summary(model)\n        return model\n\n    @classmethod\n    def from_config(cls, config):\n        \"\"\"Build a DeepSpeec2Model from config\n        Parameters\n\n        config: yacs.config.CfgNode\n            config\n        Returns\n        -------\n        DeepSpeech2Model\n            The model built from config.\n        \"\"\"\n        model = cls(\n            feat_size=config.input_dim,\n            dict_size=config.output_dim,\n            num_conv_layers=config.num_conv_layers,\n            num_rnn_layers=config.num_rnn_layers,\n            rnn_size=config.rnn_layer_size,\n            rnn_direction=config.rnn_direction,\n            num_fc_layers=config.num_fc_layers,\n            fc_layers_size_list=config.fc_layers_size_list,\n            use_gru=config.use_gru,\n            blank_id=config.blank_id,\n            ctc_grad_norm_type=config.get('ctc_grad_norm_type', None), )\n        return model\n\n\nclass DeepSpeech2InferModel(DeepSpeech2Model):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n    def forward(self,\n                audio_chunk,\n                audio_chunk_lens,\n                chunk_state_h_box=None,\n                chunk_state_c_box=None):\n        if self.encoder.rnn_direction == \"forward\":\n            eouts_chunk, eouts_chunk_lens, final_state_h_box, final_state_c_box = self.encoder(\n                audio_chunk, audio_chunk_lens, chunk_state_h_box,\n                chunk_state_c_box)\n            probs_chunk = self.decoder.softmax(eouts_chunk)\n            return probs_chunk, eouts_chunk_lens, final_state_h_box, final_state_c_box\n        elif self.encoder.rnn_direction == \"bidirect\":\n            eouts, eouts_len, _, _ = self.encoder(audio_chunk, audio_chunk_lens)\n            probs = self.decoder.softmax(eouts)\n            return probs, eouts_len\n        else:\n            raise Exception(\"wrong model type\")\n\n    def export(self):\n        if self.encoder.rnn_direction == \"forward\":\n            static_model = paddle.jit.to_static(\n                self,\n                input_spec=[\n                    paddle.static.InputSpec(\n                        shape=[None, None, self.encoder.feat_size\n                               ],  #[B, chunk_size, feat_dim]\n                        dtype='float32', ),\n                    paddle.static.InputSpec(shape=[None],\n                                            dtype='int64'),  # audio_length, [B]\n                    paddle.static.InputSpec(\n                        shape=[None, None, None], dtype='float32'),\n                    paddle.static.InputSpec(\n                        shape=[None, None, None], dtype='float32')\n                ],\n                full_graph=True)\n        elif self.encoder.rnn_direction == \"bidirect\":\n            static_model = paddle.jit.to_static(\n                self,\n                input_spec=[\n                    paddle.static.InputSpec(\n                        shape=[None, None, self.encoder.feat_size],\n                        dtype='float32'),  # audio, [B,T,D]\n                    paddle.static.InputSpec(shape=[None],\n                                            dtype='int64'),  # audio_length, [B]\n                ],\n                full_graph=True)\n        else:\n            raise Exception(\"wrong model type\")\n        return static_model\n"
  },
  {
    "path": "paddlespeech/s2t/models/hubert/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .hubert_ASR import HubertASR\nfrom .hubert_ASR import HubertBase\n\n__all__ = [\"HubertASR\", \"HubertBase\"]\n"
  },
  {
    "path": "paddlespeech/s2t/models/hubert/hubert_ASR.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"HubertASR model.\"\"\"\nfrom collections import defaultdict\nfrom copy import deepcopy\nfrom dataclasses import dataclass\nfrom dataclasses import is_dataclass\nfrom typing import Dict\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.s2t.models.hubert.modules.hubert_model import HubertConfig\nfrom paddlespeech.s2t.models.hubert.modules.hubert_model import HubertModel\nfrom paddlespeech.s2t.models.hubert.modules.hubert_model import HubertPretrainingConfig\nfrom paddlespeech.s2t.models.wav2vec2.modules.VanillaNN import VanillaNN\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import SpecAugment\nfrom paddlespeech.s2t.modules.ctc import CTCDecoderBase as CTC\nfrom paddlespeech.s2t.modules.initializer import DefaultInitializerContext\nfrom paddlespeech.s2t.utils.ctc_utils import remove_duplicates_and_blank\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import log_add\n\nlogger = Log(__name__).getlog()\n\n\nclass HubertASR(nn.Layer):\n    def __init__(self, config: dict):\n        super().__init__()\n        init_type = config.get(\"init_type\", None)\n        with DefaultInitializerContext(init_type):\n            self.config = config\n            task_cfg = self.merge_with_parent(HubertPretrainingConfig,\n                                              dict(self.config.task_cfg))\n            model_cfg = self.merge_with_parent(HubertConfig,\n                                               dict(self.config.model_cfg))\n            hubert = HubertModel(model_cfg, task_cfg, [None])\n\n            self.normalize_wav = config.normalize_wav\n            self.output_norm = config.output_norm\n            if hasattr(config, 'spec_augment'):\n                self.spec_augment = SpecAugment(**config.spec_augment)\n\n            if config.freeze_hubert:\n                hubert.eval()\n                for parm in hubert.parameters():\n                    parm.trainable = False\n            self.hubert = hubert\n            self.enc = VanillaNN(**config.enc)\n            self.ctc = CTC(**config.ctc,\n                           odim=config.output_dim,\n                           batch_average=False,\n                           reduction='mean')\n\n    def merge_with_parent(self, dc: dataclass, cfg: dict):\n        assert is_dataclass(dc)\n        assert type(cfg) == dict\n        cfg = deepcopy(cfg)\n\n        def fix_cfg(cfg):\n            target_keys = set(dc.__dataclass_fields__.keys())\n            for k in list(cfg.keys()):\n                if k not in target_keys:\n                    del cfg[k]\n\n        fix_cfg(cfg)\n        assert len(cfg) > 0\n        return dc(**cfg)\n\n    def forward(self, wav, wavs_lens_rate, target, target_lens):\n\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n\n        # Extract wav2vec output\n        out = self.hubert.extract_features(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n\n        if self.training and hasattr(self.config, 'spec_augment'):\n            feats = self.spec_augment(out)\n        else:\n            feats = out\n\n        x = self.enc(feats)\n\n        x_lens = (wavs_lens_rate * x.shape[1]).round().astype(paddle.int64)\n\n        ctc_loss = self.ctc(x, x_lens, target, target_lens)\n\n        return ctc_loss\n\n    @paddle.no_grad()\n    def decode(self,\n               feats: paddle.Tensor,\n               text_feature: Dict[str, int],\n               decoding_method: str,\n               beam_size: int,\n               tokenizer: str=None,\n               sb_pipeline=False):\n        batch_size = feats.shape[0]\n\n        if decoding_method == 'ctc_prefix_beam_search' and batch_size > 1:\n            logger.error(\n                f\"decoding mode {decoding_method} must be running with batch_size == 1\"\n            )\n            logger.error(f\"current batch_size is {batch_size}\")\n\n        if decoding_method == 'ctc_greedy_search':\n            if tokenizer is None and sb_pipeline is False:\n                hyps = self.ctc_greedy_search(feats)\n                res = [text_feature.defeaturize(hyp) for hyp in hyps]\n                res_tokenids = [hyp for hyp in hyps]\n            else:\n                if sb_pipeline is True:\n                    hyps = self.ctc_greedy_search(feats.unsqueeze(-1))\n                else:\n                    hyps = self.ctc_greedy_search(feats)\n                res = []\n                res_tokenids = []\n                for sequence in hyps:\n                    # Decode token terms to words \n                    predicted_tokens = text_feature.convert_ids_to_tokens(\n                        sequence)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n\n        # ctc_prefix_beam_search and attention_rescoring only return one\n        # result in List[int], change it to List[List[int]] for compatible\n        # with other batch decoding mode\n        elif decoding_method == 'ctc_prefix_beam_search':\n            assert feats.shape[0] == 1\n            if tokenizer is None and sb_pipeline is False:\n                hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = [text_feature.defeaturize(hyp)]\n                res_tokenids = [hyp]\n            else:\n                if sb_pipeline is True:\n                    hyp = self.ctc_prefix_beam_search(\n                        feats.unsqueeze(-1), beam_size)\n                else:\n                    hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = []\n                res_tokenids = []\n                predicted_tokens = text_feature.convert_ids_to_tokens(hyp)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n        else:\n            raise ValueError(\n                f\"wav2vec2 not support decoding method: {decoding_method}\")\n\n        return res, res_tokenids\n\n    @classmethod\n    def from_config(cls, config):\n        model = cls(config)\n        return model\n\n    def ctc_greedy_search(self, wav) -> List[List[int]]:\n        \"\"\" Apply CTC greedy search\n        Args:\n            speech (paddle.Tensor): (batch, max_len)\n            speech_length (paddle.Tensor): (batch, )\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        batch_size = wav.shape[0]\n        wav = wav[:, :, 0]\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wav2vec output\n        out = self.hubert.extract_features(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n        x = self.enc(feats)\n        x_lens = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (B, maxlen, vocab_size)\n        topk_prob, topk_index = ctc_probs.topk(1, axis=2)  # (B, maxlen, 1)\n        topk_index = topk_index.reshape([batch_size, x_lens])  # (B, maxlen)\n\n        hyps = [hyp.tolist() for hyp in topk_index]\n        hyps = [remove_duplicates_and_blank(hyp) for hyp in hyps]\n        return hyps\n\n    def _ctc_prefix_beam_search(\n            self,\n            wav,\n            beam_size,\n            blank_id: int=0, ) -> Tuple[List[Tuple[int, float]], paddle.Tensor]:\n        \"\"\" CTC prefix beam search inner implementation\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[Tuple[int, float]]: nbest results, (N,1), (text, likelihood)\n            paddle.Tensor: encoder output, (1, max_len, encoder_dim),\n                it will be used for rescoring in attention rescoring mode\n        \"\"\"\n        wav = wav[:, :, 0]\n\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wav2vec output\n        out = self.hubert.extract_features(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n\n        x = self.enc(feats)\n        maxlen = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (1, maxlen, vocab_size)\n        ctc_probs = ctc_probs.squeeze(0)\n\n        # cur_hyps: (prefix, (blank_ending_score, none_blank_ending_score))\n        # blank_ending_score and  none_blank_ending_score in ln domain\n        cur_hyps = [(tuple(), (0.0, -float('inf')))]\n        # 2. CTC beam search step by step\n        for t in range(0, maxlen):\n            logp = ctc_probs[t]  # (vocab_size,)\n            # key: prefix, value (pb, pnb), default value(-inf, -inf)\n            next_hyps = defaultdict(lambda: (-float('inf'), -float('inf')))\n            # 2.1 First beam prune: select topk best\n            top_k_logp, top_k_index = logp.topk(beam_size)  # (beam_size,)\n            for s in top_k_index:\n                s = s.item()\n                ps = logp[s].item()\n                for prefix, (pb, pnb) in cur_hyps:\n                    last = prefix[-1] if len(prefix) > 0 else None\n                    if s == blank_id:  # blank\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pb = log_add([n_pb, pb + ps, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                    elif s == last:\n                        #  Update *ss -> *s;\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pnb = log_add([n_pnb, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                        # Update *s-s -> *ss, - is for blank\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n                    else:\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps, pnb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n\n            # 2.2 Second beam prune\n            next_hyps = sorted(\n                next_hyps.items(),\n                key=lambda x: log_add(list(x[1])),\n                reverse=True)\n            cur_hyps = next_hyps[:beam_size]\n\n        hyps = [(y[0], log_add([y[1][0], y[1][1]])) for y in cur_hyps]\n        return hyps\n\n    def ctc_prefix_beam_search(self, wav, beam_size) -> List[int]:\n        \"\"\" Apply CTC prefix beam search\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[int]: CTC prefix beam search nbest results\n        \"\"\"\n        hyps = self._ctc_prefix_beam_search(wav, beam_size)\n        return hyps[0][0]\n\n\nclass HubertBase(nn.Layer):\n    \"\"\"Hubert model\"\"\"\n\n    def __init__(self, config: dict):\n        super().__init__()\n        self.config = config\n        task_cfg = self.merge_with_parent(HubertPretrainingConfig,\n                                          dict(self.config.task_cfg))\n        model_cfg = self.merge_with_parent(HubertConfig,\n                                           dict(self.config.model_cfg))\n        hubert = HubertModel(model_cfg, task_cfg, [None])\n        self.hubert = hubert\n\n    @classmethod\n    def from_config(cls, configs: dict):\n        \"\"\"init model.\n        Args:\n            configs (dict): config dict.\n        Raises:\n            ValueError: raise when using not support encoder type.\n        Returns:\n            nn.Layer: HubertBase\n        \"\"\"\n        model = cls(configs)\n        return model\n\n    def merge_with_parent(self, dc: dataclass, cfg: dict):\n        assert is_dataclass(dc)\n        assert type(cfg) == dict\n        cfg = deepcopy(cfg)\n\n        def fix_cfg(cfg):\n            target_keys = set(dc.__dataclass_fields__.keys())\n            for k in list(cfg.keys()):\n                if k not in target_keys:\n                    del cfg[k]\n\n        fix_cfg(cfg)\n        assert len(cfg) > 0\n        return dc(**cfg)\n\n    def forward(self, wav):\n        out = self.hubert.extract_features(wav)\n        return out\n"
  },
  {
    "path": "paddlespeech/s2t/models/hubert/modules/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/models/hubert/modules/hubert_model.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Paddle Hubert model.\"\"\"\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\n\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import ChoiceEnum\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import compute_mask_indices\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import ConvFeatureExtractionModel\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import EXTRACTOR_MODE_CHOICES\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import get_available_activation_fns\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import GLU\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import GradMultiply\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import LAYER_TYPE_CHOICES\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import MASKING_DISTRIBUTION_CHOICES\nfrom paddlespeech.s2t.models.wav2vec2.modules.wav2vec2_model import TransformerEncoder\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\n@dataclass\nclass HubertPretrainingConfig:\n    label_rate: float = field(\n        default=-1.0,\n        metadata={\"help\": \"label frame rate. -1.0 for sequence label\"}, )\n    sample_rate: int = field(\n        default=16_000,\n        metadata={\n            \"help\":\n            \"target sample rate. audio files will be up/down \"\n            \"sampled to this rate\"\n        }, )\n    normalize: bool = field(\n        default=False,\n        metadata={\n            \"help\": \"if set, normalizes input to have 0 mean and unit variance\"\n        }, )\n    enable_padding: bool = field(\n        default=False,\n        metadata={\"help\": \"pad shorter samples instead of cropping\"}, )\n    max_keep_size: Optional[int] = field(\n        default=None,\n        metadata={\"help\": \"exclude sample longer than this\"}, )\n    max_sample_size: Optional[int] = field(\n        default=None,\n        metadata={\"help\": \"max sample size to crop to for batching\"}, )\n    min_sample_size: Optional[int] = field(\n        default=None,\n        metadata={\"help\": \"min sample size to crop to for batching\"}, )\n    random_crop: Optional[bool] = field(\n        default=True,\n        metadata={\"help\": \"always crop from the beginning if false\"}, )\n    pad_audio: Optional[bool] = field(\n        default=False,\n        metadata={\"help\": \"pad audio to the longest one in the batch if true\"},\n    )\n\n\n@dataclass\nclass HubertConfig:\n    label_rate: float\n\n    extractor_mode: EXTRACTOR_MODE_CHOICES = field(\n        default=\"default\",\n        metadata={\n            \"help\":\n            \"mode for feature extractor. default has a single group \"\n            \"norm with d groups in the first conv block, whereas layer_norm \"\n            \"has layer norms in every block (meant to use with normalize=True)\"\n        }, )\n    encoder_layers: int = field(\n        default=12, metadata={\"help\": \"num encoder layers in the transformer\"})\n    encoder_embed_dim: int = field(\n        default=768, metadata={\"help\": \"encoder embedding dimension\"})\n    encoder_ffn_embed_dim: int = field(\n        default=3072, metadata={\"help\": \"encoder embedding dimension for FFN\"})\n    encoder_attention_heads: int = field(\n        default=12, metadata={\"help\": \"num encoder attention heads\"})\n    activation_fn: ChoiceEnum(get_available_activation_fns()) = field(\n        default=\"gelu\", metadata={\"help\": \"activation function to use\"})\n    layer_type: LAYER_TYPE_CHOICES = field(\n        default=\"transformer\", metadata={\"help\": \"layer type in encoder\"})\n\n    # dropouts\n    dropout: float = field(\n        default=0.1,\n        metadata={\"help\": \"dropout probability for the transformer\"}, )\n    attention_dropout: float = field(\n        default=0.1,\n        metadata={\"help\": \"dropout probability for attention weights\"}, )\n    activation_dropout: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout probability after activation in FFN\"}, )\n    encoder_layerdrop: float = field(\n        default=0.0,\n        metadata={\"help\": \"probability of dropping a tarnsformer layer\"}, )\n    dropout_input: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout to apply to the input (after feat extr)\"}, )\n    dropout_features: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout to apply to the features (after feat extr)\"},\n    )\n\n    final_dim: int = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"project final representations and targets to this many \"\n            \"dimensions. set to encoder_embed_dim is <= 0\"\n        }, )\n    untie_final_proj: bool = field(\n        default=False,\n        metadata={\"help\": \"use separate projection for each target\"}, )\n    layer_norm_first: bool = field(\n        default=False,\n        metadata={\"help\": \"apply layernorm first in the transformer\"}, )\n    conv_feature_layers: str = field(\n        default=\"[(512,10,5)] + [(512,3,2)] * 4 + [(512,2,2)] * 2\",\n        metadata={\n            \"help\":\n            \"string describing convolutional feature extraction \"\n            \"layers in form of a python list that contains \"\n            \"[(dim, kernel_size, stride), ...]\"\n        }, )\n    conv_bias: bool = field(\n        default=False, metadata={\"help\": \"include bias in conv encoder\"})\n    logit_temp: float = field(\n        default=0.1, metadata={\"help\": \"temperature to divide logits by\"})\n    target_glu: bool = field(\n        default=False, metadata={\"help\": \"adds projection + glu to targets\"})\n    feature_grad_mult: float = field(\n        default=1.0,\n        metadata={\"help\": \"multiply feature extractor var grads by this\"}, )\n\n    # masking\n    mask_length: int = field(default=10, metadata={\"help\": \"mask length\"})\n    mask_prob: float = field(\n        default=0.65,\n        metadata={\"help\": \"probability of replacing a token with mask\"}, )\n    mask_selection: MASKING_DISTRIBUTION_CHOICES = field(\n        default=\"static\", metadata={\"help\": \"how to choose mask length\"})\n    mask_other: float = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"secondary mask argument \"\n            \"(used for more complex distributions), \"\n            \"see help in compute_mask_indicesh\"\n        }, )\n    no_mask_overlap: bool = field(\n        default=False, metadata={\"help\": \"whether to allow masks to overlap\"})\n    mask_min_space: int = field(\n        default=1,\n        metadata={\"help\": \"min space between spans (if no overlap is enabled)\"},\n    )\n\n    # channel masking\n    mask_channel_length: int = field(\n        default=10,\n        metadata={\"help\": \"length of the mask for features (channels)\"}, )\n    mask_channel_prob: float = field(\n        default=0.0,\n        metadata={\"help\": \"probability of replacing a feature with 0\"}, )\n    mask_channel_selection: MASKING_DISTRIBUTION_CHOICES = field(\n        default=\"static\",\n        metadata={\"help\": \"how to choose mask length for channel masking\"}, )\n    mask_channel_other: float = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"secondary mask argument \"\n            \"(used for more complex distributions), \"\n            \"see help in compute_mask_indicesh\"\n        }, )\n    no_mask_channel_overlap: bool = field(\n        default=False,\n        metadata={\"help\": \"whether to allow channel masks to overlap\"}, )\n    mask_channel_min_space: int = field(\n        default=1,\n        metadata={\"help\": \"min space between spans (if no overlap is enabled)\"},\n    )\n\n    # positional embeddings\n    conv_pos: int = field(\n        default=128,\n        metadata={\n            \"help\": \"number of filters for convolutional positional embeddings\"\n        }, )\n    conv_pos_groups: int = field(\n        default=16,\n        metadata={\n            \"help\": \"number of groups for convolutional positional embedding\"\n        }, )\n\n    latent_temp: Tuple[float, float, float] = field(\n        default=(2, 0.5, 0.999995),\n        metadata={\"help\": \"legacy (to be removed)\"}, )\n\n    # loss computation\n    skip_masked: bool = field(\n        default=False,\n        metadata={\"help\": \"skip computing losses over masked frames\"}, )\n    skip_nomask: bool = field(\n        default=False,\n        metadata={\"help\": \"skip computing losses over unmasked frames\"}, )\n\n    checkpoint_activations: bool = field(\n        default=False,\n        metadata={\n            \"help\": \"recompute activations and save memory for extra compute\"\n        }, )\n\n    # FP16 optimization\n    required_seq_len_multiple: int = field(\n        default=2,\n        metadata={\n            \"help\":\n            \"pad the input to encoder such that the sequence length is divisible by multiple\"\n        }, )\n\n    # Conformer\n    depthwise_conv_kernel_size: int = field(\n        default=31,\n        metadata={\n            \"help\":\n            \"depthwise-conv-kernel-size for convolution in conformer layer\"\n        }, )\n    attn_type: str = field(\n        default=\"\",\n        metadata={\"help\": \"if espnet use ESPNET MHA\"}, )\n    pos_enc_type: str = field(\n        default=\"abs\",\n        metadata={\"help\": \"Positional encoding type to use in conformer\"}, )\n    fp16: bool = field(\n        default=False, metadata={\"help\": \"If fp16 is being used\"})\n\n\nclass HubertModel(nn.Layer):\n    def __init__(\n            self,\n            cfg: HubertConfig,\n            task_cfg: HubertPretrainingConfig,\n            dictionaries: List[Any], ) -> None:\n        super().__init__()\n        logger.info(f\"HubertModel Config: {cfg}\")\n\n        feature_enc_layers = eval(cfg.conv_feature_layers)  # noqa\n        self.embed = feature_enc_layers[-1][0]\n\n        self.feature_extractor = ConvFeatureExtractionModel(\n            conv_layers=feature_enc_layers,\n            dropout=0.0,\n            mode=cfg.extractor_mode,\n            conv_bias=cfg.conv_bias, )\n        feature_ds_rate = np.prod([s for _, _, s in feature_enc_layers])\n        self.feat2tar_ratio = cfg.label_rate * feature_ds_rate / task_cfg.sample_rate\n\n        self.post_extract_proj = (Linear(self.embed, cfg.encoder_embed_dim) if\n                                  self.embed != cfg.encoder_embed_dim else None)\n\n        self.mask_prob = cfg.mask_prob\n        self.mask_selection = cfg.mask_selection\n        self.mask_other = cfg.mask_other\n        self.mask_length = cfg.mask_length\n        self.no_mask_overlap = cfg.no_mask_overlap\n        self.mask_min_space = cfg.mask_min_space\n\n        self.mask_channel_prob = cfg.mask_channel_prob\n        self.mask_channel_selection = cfg.mask_channel_selection\n        self.mask_channel_other = cfg.mask_channel_other\n        self.mask_channel_length = cfg.mask_channel_length\n        self.no_mask_channel_overlap = cfg.no_mask_channel_overlap\n        self.mask_channel_min_space = cfg.mask_channel_min_space\n\n        self.dropout_input = nn.Dropout(cfg.dropout_input)\n        self.dropout_features = nn.Dropout(cfg.dropout_features)\n\n        self.feature_grad_mult = cfg.feature_grad_mult\n        self.logit_temp = cfg.logit_temp\n        self.skip_masked = cfg.skip_masked\n        self.skip_nomask = cfg.skip_nomask\n\n        final_dim = cfg.final_dim if cfg.final_dim > 0 else cfg.encoder_embed_dim\n\n        self.mask_emb = paddle.create_parameter(\n            shape=[cfg.encoder_embed_dim],\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.Uniform(low=0), )\n\n        self.encoder = TransformerEncoder(cfg)\n        self.layer_norm = LayerNorm(self.embed)\n\n        self.target_glu = None\n        if cfg.target_glu:\n            self.target_glu = nn.Sequential(\n                Linear(final_dim, final_dim * 2), GLU())\n\n        self.untie_final_proj = cfg.untie_final_proj\n        if self.untie_final_proj:\n            self.final_proj = Linear(cfg.encoder_embed_dim,\n                                     final_dim * len(dictionaries))\n        else:\n            self.final_proj = Linear(cfg.encoder_embed_dim, final_dim)\n\n        # modules below are not needed during fine-tuning\n        if any([d is None for d in dictionaries]):\n            logger.info(\n                \"cannot find dictionary. assume will be used for fine-tuning\")\n        else:\n            self.num_classes = [len(d) for d in dictionaries]\n            self.label_embs_concat = paddle.create_parameter(\n                shape=[sum(self.num_classes), final_dim],\n                dtype='float32',\n                default_initializer=paddle.nn.initializer.Uniform(low=0), )\n\n    @classmethod\n    def build_model(cls, cfg: HubertConfig, task):\n        \"\"\"Build a new model instance.\"\"\"\n\n        model = HubertModel(cfg, task.cfg, task.dictionaries)\n        return model\n\n    def apply_mask(self, x, padding_mask, target_list):\n        B, T, C = x.shape\n        if self.mask_prob > 0:\n            mask_indices = compute_mask_indices(\n                (B, T),\n                padding_mask,\n                self.mask_prob,\n                self.mask_length,\n                self.mask_selection,\n                self.mask_other,\n                min_masks=2,\n                no_overlap=self.no_mask_overlap,\n                min_space=self.mask_min_space, )\n\n            mask_indices = paddle.to_tensor(\n                mask_indices, dtype='int64', place=x.place)\n            x[mask_indices] = self.mask_emb\n        else:\n            mask_indices = None\n\n        if self.mask_channel_prob > 0:\n            mask_channel_indices = compute_mask_indices(\n                (B, C),\n                None,\n                self.mask_channel_prob,\n                self.mask_channel_length,\n                self.mask_channel_selection,\n                self.mask_channel_other,\n                no_overlap=self.no_mask_channel_overlap,\n                min_space=self.mask_channel_min_space, )\n            mask_channel_indices = (paddle.to_tensor(\n                mask_channel_indices, dtype='int64', place=x.place).unsqueeze(1)\n                                    .expand([-1, T, -1]))\n            x[mask_channel_indices] = 0\n\n        return x, mask_indices\n\n    def compute_nce(self, x, pos, negs):\n        neg_is_pos = (pos == negs).all(-1)\n        pos = pos.unsqueeze(0)\n        targets = paddle.concat([pos, negs], axis=0)\n\n        logits = paddle.nn.functional.cosine_similarity(\n            x.astype('float32'), targets.astype('float32'), axis=-1)\n        logits /= self.logit_temp\n        if paddle.any(neg_is_pos):\n            logits[1:][neg_is_pos] = float(\"-inf\")\n        logits = logits.transpose([1, 0])  # (num_x, num_cls+1)\n        return logits\n\n    def forward_features(self, source: paddle.Tensor) -> paddle.Tensor:\n        if self.feature_grad_mult > 0:\n            features = self.feature_extractor(source)\n            if self.feature_grad_mult != 1.0:\n                features = GradMultiply.apply(features, self.feature_grad_mult)\n        else:\n            with paddle.no_grad():\n                features = self.feature_extractor(source)\n        return features\n\n    def forward_targets(\n            self,\n            features: paddle.Tensor,\n            target_list: List[paddle.Tensor],\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        # Trim features to ensure labels exist and then get aligned labels\n        feat_tsz = features.shape[2]\n        targ_tsz = min([t.shape[1] for t in target_list])\n        if self.feat2tar_ratio * feat_tsz > targ_tsz:\n            feat_tsz = int(targ_tsz / self.feat2tar_ratio)\n            features = features[:, :, :feat_tsz]\n        target_inds = paddle.arange(feat_tsz).astype(\n            'float32') * self.feat2tar_ratio\n        target_list = [t[:, target_inds.astype('int64')] for t in target_list]\n        return features, target_list\n\n    def forward_padding_mask(\n            self,\n            features: paddle.Tensor,\n            padding_mask: paddle.Tensor, ) -> paddle.Tensor:\n        extra = padding_mask.shape[1] % features.shape[1]\n        if extra > 0:\n            padding_mask = padding_mask[:, :-extra]\n        padding_mask = paddle.reshape(\n            padding_mask, [padding_mask.shape[0], features.shape[1], -1])\n        padding_mask = paddle.all(padding_mask, axis=-1)\n        return padding_mask\n\n    def forward(\n            self,\n            source: paddle.Tensor,\n            target_list: Optional[List[paddle.Tensor]]=None,\n            padding_mask: Optional[paddle.Tensor]=None,\n            mask: bool=True,\n            features_only: bool=False,\n            output_layer: Optional[int]=None, ) -> Dict[str, paddle.Tensor]:\n        \"\"\"output layer is 1-based\"\"\"\n        features = self.forward_features(source)\n        if target_list is not None:\n            features, target_list = self.forward_targets(features, target_list)\n\n        features_pen = features.pow(2).mean()\n\n        features = features.transpose([0, 2, 1])\n        features = self.layer_norm(features)\n        unmasked_features = features.clone()\n\n        if padding_mask is not None:\n            padding_mask = self.forward_padding_mask(features, padding_mask)\n\n        if self.post_extract_proj is not None:\n            features = self.post_extract_proj(features)\n\n        features = self.dropout_input(features)\n        unmasked_features = self.dropout_features(unmasked_features)\n\n        if mask:\n            x, mask_indices = self.apply_mask(features, padding_mask,\n                                              target_list)\n        else:\n            x = features\n            mask_indices = None\n\n        # feature: (B, T, D), float\n        # target: (B, T), long\n        # x: (B, T, D), float\n        # padding_mask: (B, T), bool\n        # mask_indices: (B, T), bool\n        x, _ = self.encoder(\n            x,\n            padding_mask=padding_mask,\n            layer=None if output_layer is None else output_layer - 1, )\n\n        if features_only:\n            return {\"x\": x, \"padding_mask\": padding_mask, \"features\": features}\n\n        def compute_pred(self, proj_x, target, label_embs):\n            # compute logits for the i-th label set\n            y = paddle.index_select(\n                label_embs, index=target.astype('int64'), axis=0)\n            negs = paddle.expand(\n                label_embs.unsqueeze(1),\n                [label_embs.shape[0], proj_x.shape[0], label_embs.shape[-1]])\n            if self.target_glu:\n                y = self.target_glu(y)\n                negs = self.target_glu(negs)\n            # proj_x: (S, D)\n            # y: (S, D)\n            # negs: (Neg, S, D)\n            return self.compute_nce(proj_x, y, negs)\n\n        label_embs_list = self.label_embs_concat.split(self.num_classes, 0)\n\n        if not self.skip_masked:\n            masked_indices = paddle.logical_and(~padding_mask, mask_indices)\n            proj_x_m = self.final_proj(x[masked_indices])\n            if self.untie_final_proj:\n                proj_x_m_list = proj_x_m.chunk(len(target_list), dim=-1)\n            else:\n                proj_x_m_list = [proj_x_m for _ in range(len(target_list))]\n            logit_m_list = [\n                compute_pred(proj_x_m, t[masked_indices], label_embs_list[i])\n                for i, (proj_x_m, t\n                        ) in enumerate(zip(proj_x_m_list, target_list))\n            ]\n        else:\n            logit_m_list = [None for _ in target_list]\n\n        if not self.skip_nomask:\n            nomask_indices = paddle.logical_and(~padding_mask, ~mask_indices)\n            proj_x_u = self.final_proj(x[nomask_indices])\n            if self.untie_final_proj:\n                proj_x_u_list = proj_x_u.chunk(len(target_list), dim=-1)\n            else:\n                proj_x_u_list = [proj_x_u for _ in range(len(target_list))]\n\n            logit_u_list = [\n                compute_pred(proj_x_u, t[nomask_indices], label_embs_list[i])\n                for i, (proj_x_u, t\n                        ) in enumerate(zip(proj_x_u_list, target_list))\n            ]\n        else:\n            logit_u_list = [None for _ in target_list]\n\n        result = {\n            \"logit_m_list\": logit_m_list,\n            \"logit_u_list\": logit_u_list,\n            \"padding_mask\": padding_mask,\n            \"features_pen\": features_pen,\n        }\n        return result\n\n    def extract_features(\n            self,\n            source: paddle.Tensor,\n            padding_mask: Optional[paddle.Tensor]=None,\n            mask: bool=False,\n            ret_conv: bool=False,\n            output_layer: Optional[int]=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        res = self.forward(\n            source,\n            padding_mask=padding_mask,\n            mask=mask,\n            features_only=True,\n            output_layer=output_layer, )\n        feature = res[\"features\"] if ret_conv else res[\"x\"]\n        return feature, res[\"padding_mask\"]\n\n    def get_logits(self, net_output, is_masked=True):\n        if is_masked:\n            logits_list = net_output[\"logit_m_list\"]\n        else:\n            logits_list = net_output[\"logit_u_list\"]\n        logits_list = [\n            paddle.cast(x, 'float32') for x in logits_list if x is not None\n        ]\n        return logits_list\n\n    def get_targets(self, net_output, is_masked=True):\n        logits_list = self.get_logits(net_output, is_masked)\n        targets_list = [\n            paddle.zeros_like(x, dtype='int64') for x in logits_list\n        ]\n        return targets_list\n\n    def get_extra_losses(self, net_output):\n        extra_losses = []\n        names = []\n\n        if \"features_pen\" in net_output:\n            extra_losses.append(net_output[\"features_pen\"])\n            names.append(\"features_pen\")\n\n        return extra_losses, names\n\n    def remove_pretraining_modules(self):\n        self.target_glu = None\n        self.final_proj = None\n"
  },
  {
    "path": "paddlespeech/s2t/models/lm/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/models/lm/dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom paddle.io import Dataset\n\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.io.utility import pad_list\n\n\nclass TextDataset(Dataset):\n    @classmethod\n    def from_file(cls, file_path):\n        dataset = cls(file_path)\n        return dataset\n\n    def __init__(self, file_path):\n        self._manifest = []\n        with open(file_path) as f:\n            for line in f:\n                self._manifest.append(line.strip())\n\n    def __len__(self):\n        return len(self._manifest)\n\n    def __getitem__(self, idx):\n        return self._manifest[idx]\n\n\nclass TextCollatorSpm():\n    def __init__(self, unit_type, vocab_filepath, spm_model_prefix):\n        assert (vocab_filepath is not None)\n        self.text_featurizer = TextFeaturizer(\n            unit_type=unit_type,\n            vocab=vocab_filepath,\n            spm_model_prefix=spm_model_prefix)\n        self.eos_id = self.text_featurizer.eos_id\n        self.blank_id = self.text_featurizer.blank_id\n\n    def __call__(self, batch):\n        \"\"\"\n        return type  [List, np.array [B, T], np.array [B, T], np.array[B]]\n        \"\"\"\n        keys = []\n        texts = []\n        texts_input = []\n        texts_output = []\n        text_lens = []\n\n        for idx, item in enumerate(batch):\n            key = item.split(\" \")[0].strip()\n            text = \" \".join(item.split(\" \")[1:])\n            keys.append(key)\n            token_ids = self.text_featurizer.featurize(text)\n            texts_input.append(\n                np.array([self.eos_id] + token_ids).astype(np.int64))\n            texts_output.append(\n                np.array(token_ids + [self.eos_id]).astype(np.int64))\n            text_lens.append(len(token_ids) + 1)\n\n        ys_input_pad = pad_list(texts_input, self.blank_id).astype(np.int64)\n        ys_output_pad = pad_list(texts_output, self.blank_id).astype(np.int64)\n        y_lens = np.array(text_lens).astype(np.int64)\n        return keys, ys_input_pad, ys_output_pad, y_lens\n"
  },
  {
    "path": "paddlespeech/s2t/models/lm/transformer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import Any\nfrom typing import List\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.s2t.decoders.scorers.scorer_interface import BatchScorerInterface\nfrom paddlespeech.s2t.models.lm_interface import LMInterface\nfrom paddlespeech.s2t.modules.encoder import TransformerEncoder\nfrom paddlespeech.s2t.modules.mask import subsequent_mask\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\nclass TransformerLM(nn.Layer, LMInterface, BatchScorerInterface):\n    def __init__(self,\n                 n_vocab: int,\n                 pos_enc: str=None,\n                 embed_unit: int=128,\n                 att_unit: int=256,\n                 head: int=2,\n                 unit: int=1024,\n                 layer: int=4,\n                 dropout_rate: float=0.5,\n                 emb_dropout_rate: float=0.0,\n                 att_dropout_rate: float=0.0,\n                 tie_weights: bool=False,\n                 **kwargs):\n        nn.Layer.__init__(self)\n\n        if pos_enc == \"sinusoidal\":\n            pos_enc_layer_type = \"abs_pos\"\n        elif pos_enc is None:\n            pos_enc_layer_type = \"no_pos\"\n        else:\n            raise ValueError(f\"unknown pos-enc option: {pos_enc}\")\n\n        self.embed = nn.Embedding(n_vocab, embed_unit)\n\n        if emb_dropout_rate == 0.0:\n            self.embed_drop = None\n        else:\n            self.embed_drop = nn.Dropout(emb_dropout_rate)\n\n        self.encoder = TransformerEncoder(\n            input_size=embed_unit,\n            output_size=att_unit,\n            attention_heads=head,\n            linear_units=unit,\n            num_blocks=layer,\n            dropout_rate=dropout_rate,\n            attention_dropout_rate=att_dropout_rate,\n            input_layer=\"linear\",\n            pos_enc_layer_type=pos_enc_layer_type,\n            concat_after=False,\n            static_chunk_size=1,\n            use_dynamic_chunk=False,\n            use_dynamic_left_chunk=False)\n\n        self.decoder = nn.Linear(att_unit, n_vocab)\n\n        logger.info(\"Tie weights set to {}\".format(tie_weights))\n        logger.info(\"Dropout set to {}\".format(dropout_rate))\n        logger.info(\"Emb Dropout set to {}\".format(emb_dropout_rate))\n        logger.info(\"Att Dropout set to {}\".format(att_dropout_rate))\n\n        if tie_weights:\n            assert (\n                att_unit == embed_unit\n            ), \"Tie Weights: True need embedding and final dimensions to match\"\n            self.decoder.weight = self.embed.weight\n\n    def _target_mask(self, ys_in_pad):\n        ys_mask = ys_in_pad != 0\n        m = subsequent_mask(paddle.shape(ys_mask)[-1]).unsqueeze(0)\n        return ys_mask.unsqueeze(-2) & m\n\n    def forward(self, x: paddle.Tensor, t: paddle.Tensor\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute LM loss value from buffer sequences.\n\n        Args:\n            x (paddle.Tensor): Input ids. (batch, len)\n            t (paddle.Tensor): Target ids. (batch, len)\n\n        Returns:\n            tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]: Tuple of\n                loss to backward (scalar),\n                negative log-likelihood of t: -log p(t) (scalar) and\n                the number of elements in x (scalar)\n\n        Notes:\n            The last two return values are used\n            in perplexity: p(t)^{-n} = exp(-log p(t) / n)\n\n        \"\"\"\n        batch_size = paddle.shape(x)[0]\n        xm = x != 0\n        xlen = xm.sum(axis=1)\n        if self.embed_drop is not None:\n            emb = self.embed_drop(self.embed(x))\n        else:\n            emb = self.embed(x)\n        h, _ = self.encoder(emb, xlen)\n        y = self.decoder(h)\n        loss = F.cross_entropy(\n            y.reshape([-1, paddle.shape(y)[-1]]),\n            t.reshape([-1]),\n            reduction=\"none\")\n        mask = xm.to(loss.dtype)\n        logp = loss * mask.reshape([-1])\n        nll = logp.reshape([batch_size, -1]).sum(-1)\n        nll_count = mask.sum(-1)\n        logp = logp.sum()\n        count = mask.sum()\n        return logp / count, logp, count, nll, nll_count\n\n    # beam search API (see ScorerInterface)\n    def score(self, y: paddle.Tensor, state: Any,\n              x: paddle.Tensor) -> Tuple[paddle.Tensor, Any]:\n        \"\"\"Score new token.\n\n        Args:\n            y (paddle.Tensor): 1D paddle.int64 prefix tokens.\n            state: Scorer state for prefix tokens\n            x (paddle.Tensor): encoder feature that generates ys.\n\n        Returns:\n            tuple[paddle.Tensor, Any]: Tuple of\n                paddle.float32 scores for next token (n_vocab)\n                and next state for ys\n\n        \"\"\"\n        y = y.unsqueeze(0)\n\n        if self.embed_drop is not None:\n            emb = self.embed_drop(self.embed(y))\n        else:\n            emb = self.embed(y)\n\n        h, _, cache = self.encoder.forward_one_step(\n            emb, self._target_mask(y), cache=state)\n        h = self.decoder(h[:, -1])\n        logp = F.log_softmax(h).squeeze(0)\n        return logp, cache\n\n    # batch beam search API (see BatchScorerInterface)\n    def batch_score(self,\n                    ys: paddle.Tensor,\n                    states: List[Any],\n                    xs: paddle.Tensor) -> Tuple[paddle.Tensor, List[Any]]:\n        \"\"\"Score new token batch (required).\n\n        Args:\n            ys (paddle.Tensor): paddle.int64 prefix tokens (n_batch, ylen).\n            states (List[Any]): Scorer states for prefix tokens.\n            xs (paddle.Tensor):\n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        # merge states\n        n_batch = len(ys)\n        n_layers = len(self.encoder.encoders)\n        if states[0] is None:\n            batch_state = None\n        else:\n            # transpose state of [batch, layer] into [layer, batch]\n            batch_state = [\n                paddle.stack([states[b][i] for b in range(n_batch)])\n                for i in range(n_layers)\n            ]\n\n        if self.embed_drop is not None:\n            emb = self.embed_drop(self.embed(ys))\n        else:\n            emb = self.embed(ys)\n\n        # batch decoding\n        h, _, states = self.encoder.forward_one_step(\n            emb, self._target_mask(ys), cache=batch_state)\n        h = self.decoder(h[:, -1])\n        logp = F.log_softmax(h)\n\n        # transpose state of [layer, batch] into [batch, layer]\n        state_list = [[states[i][b] for i in range(n_layers)]\n                      for b in range(n_batch)]\n        return logp, state_list\n\n\nif __name__ == \"__main__\":\n    tlm = TransformerLM(\n        n_vocab=5002,\n        pos_enc=None,\n        embed_unit=128,\n        att_unit=512,\n        head=8,\n        unit=2048,\n        layer=16,\n        dropout_rate=0.5, )\n\n    #     n_vocab: int,\n    # pos_enc: str=None,\n    # embed_unit: int=128,\n    # att_unit: int=256,\n    # head: int=2,\n    # unit: int=1024,\n    # layer: int=4,\n    # dropout_rate: float=0.5,\n    # emb_dropout_rate: float = 0.0,\n    # att_dropout_rate: float = 0.0,\n    # tie_weights: bool = False,):\n    paddle.set_device(\"cpu\")\n    model_dict = paddle.load(\"transformerLM.pdparams\")\n    tlm.set_state_dict(model_dict)\n\n    tlm.eval()\n    #Test the score\n    input2 = np.array([5])\n    input2 = paddle.to_tensor(input2)\n    state = None\n    output, state = tlm.score(input2, state, None)\n\n    input3 = np.array([5, 10])\n    input3 = paddle.to_tensor(input3)\n    output, state = tlm.score(input3, state, None)\n\n    input4 = np.array([5, 10, 0])\n    input4 = paddle.to_tensor(input4)\n    output, state = tlm.score(input4, state, None)\n    print(\"output\", output)\n    \"\"\"\n    #Test the batch score\n    batch_size = 2\n    inp2 = np.array([[5], [10]])\n    inp2 = paddle.to_tensor(inp2)\n    output, states = tlm.batch_score(\n        inp2, [(None,None,0)] * batch_size)\n    inp3 = np.array([[100], [30]])\n    inp3 = paddle.to_tensor(inp3)\n    output, states = tlm.batch_score(\n        inp3, states)\n    print(\"output\", output)\n    #print(\"cache\", cache)\n    #np.save(\"output_pd.npy\", output)\n    \"\"\"\n"
  },
  {
    "path": "paddlespeech/s2t/models/lm_interface.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Language model interface.\"\"\"\nimport argparse\n\nfrom paddlespeech.s2t.decoders.scorers.scorer_interface import ScorerInterface\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\n\nclass LMInterface(ScorerInterface):\n    \"\"\"LM Interface model implementation.\"\"\"\n\n    @staticmethod\n    def add_arguments(parser):\n        \"\"\"Add arguments to command line argument parser.\"\"\"\n        return parser\n\n    @classmethod\n    def build(cls, n_vocab: int, **kwargs):\n        \"\"\"Initialize this class with python-level args.\n\n        Args:\n            idim (int): The number of vocabulary.\n\n        Returns:\n            LMinterface: A new instance of LMInterface.\n\n        \"\"\"\n        args = argparse.Namespace(**kwargs)\n        return cls(n_vocab, args)\n\n    def forward(self, x, t):\n        \"\"\"Compute LM loss value from buffer sequences.\n\n        Args:\n            x (torch.Tensor): Input ids. (batch, len)\n            t (torch.Tensor): Target ids. (batch, len)\n\n        Returns:\n            tuple[torch.Tensor, torch.Tensor, torch.Tensor]: Tuple of\n                loss to backward (scalar),\n                negative log-likelihood of t: -log p(t) (scalar) and\n                the number of elements in x (scalar)\n\n        Notes:\n            The last two return values are used\n            in perplexity: p(t)^{-n} = exp(-log p(t) / n)\n\n        \"\"\"\n        raise NotImplementedError(\"forward method is not implemented\")\n\n\npredefined_lms = {\n    \"transformer\": \"paddlespeech.s2t.models.lm.transformer:TransformerLM\",\n}\n\n\ndef dynamic_import_lm(module):\n    \"\"\"Import LM class dynamically.\n\n    Args:\n        module (str): module_name:class_name or alias in `predefined_lms`\n\n    Returns:\n        type: LM class\n\n    \"\"\"\n    model_class = dynamic_import(module, predefined_lms)\n    assert issubclass(model_class,\n                      LMInterface), f\"{module} does not implement LMInterface\"\n    return model_class\n"
  },
  {
    "path": "paddlespeech/s2t/models/st_interface.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"ST Interface module.\"\"\"\nfrom .asr_interface import ASRInterface\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\n\n\nclass STInterface(ASRInterface):\n    \"\"\"ST Interface model implementation.\n\n    NOTE: This class is inherited from ASRInterface to enable joint translation\n    and recognition when performing multi-task learning with the ASR task.\n\n    \"\"\"\n\n    def translate(self,\n                  x,\n                  trans_args,\n                  char_list=None,\n                  rnnlm=None,\n                  ensemble_models=[]):\n        \"\"\"Recognize x for evaluation.\n\n        :param ndarray x: input acouctic feature (B, T, D) or (T, D)\n        :param namespace trans_args: argment namespace contraining options\n        :param list char_list: list of characters\n        :param paddle.nn.Layer rnnlm: language model module\n        :return: N-best decoding results\n        :rtype: list\n        \"\"\"\n        raise NotImplementedError(\"translate method is not implemented\")\n\n    def translate_batch(self, x, trans_args, char_list=None, rnnlm=None):\n        \"\"\"Beam search implementation for batch.\n\n        :param paddle.Tensor x: encoder hidden state sequences (B, Tmax, Henc)\n        :param namespace trans_args: argument namespace containing options\n        :param list char_list: list of characters\n        :param paddle.nn.Layer rnnlm: language model module\n        :return: N-best decoding results\n        :rtype: list\n        \"\"\"\n        raise NotImplementedError(\"Batch decoding is not supported yet.\")\n\n\npredefined_st = {\n    \"transformer\": \"paddlespeech.s2t.models.u2_st:U2STModel\",\n}\n\n\ndef dynamic_import_st(module):\n    \"\"\"Import ST models dynamically.\n\n    Args:\n        module (str): module_name:class_name or alias in `predefined_st`\n\n    Returns:\n        type: ST class\n\n    \"\"\"\n    model_class = dynamic_import(module, predefined_st)\n    assert issubclass(model_class,\n                      STInterface), f\"{module} does not implement STInterface\"\n    return model_class\n"
  },
  {
    "path": "paddlespeech/s2t/models/u2/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .u2 import U2InferModel\nfrom .u2 import U2Model\nfrom .updater import U2Evaluator\nfrom .updater import U2Updater\n\n__all__ = [\"U2Model\", \"U2InferModel\", \"U2Evaluator\", \"U2Updater\"]\n"
  },
  {
    "path": "paddlespeech/s2t/models/u2/u2.py",
    "content": "# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"U2 ASR Model\nUnified Streaming and Non-streaming Two-pass End-to-end Model for Speech Recognition\n(https://arxiv.org/pdf/2012.05481.pdf)\n\"\"\"\nimport sys\nimport time\nfrom collections import defaultdict\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import jit\nfrom paddle import nn\n\nfrom paddlespeech.audio.utils.tensor_utils import add_sos_eos\nfrom paddlespeech.audio.utils.tensor_utils import pad_sequence\nfrom paddlespeech.audio.utils.tensor_utils import reverse_pad_list\nfrom paddlespeech.audio.utils.tensor_utils import st_reverse_pad_list\nfrom paddlespeech.audio.utils.tensor_utils import th_accuracy\nfrom paddlespeech.s2t.decoders.scorers.ctc import CTCPrefixScorer\nfrom paddlespeech.s2t.frontend.utility import IGNORE_ID\nfrom paddlespeech.s2t.frontend.utility import load_cmvn\nfrom paddlespeech.s2t.models.asr_interface import ASRInterface\nfrom paddlespeech.s2t.modules.cmvn import GlobalCMVN\nfrom paddlespeech.s2t.modules.ctc import CTCDecoderBase\nfrom paddlespeech.s2t.modules.decoder import BiTransformerDecoder\nfrom paddlespeech.s2t.modules.decoder import TransformerDecoder\nfrom paddlespeech.s2t.modules.encoder import ConformerEncoder\nfrom paddlespeech.s2t.modules.encoder import SqueezeformerEncoder\nfrom paddlespeech.s2t.modules.encoder import TransformerEncoder\nfrom paddlespeech.s2t.modules.initializer import DefaultInitializerContext\nfrom paddlespeech.s2t.modules.loss import LabelSmoothingLoss\nfrom paddlespeech.s2t.modules.mask import make_pad_mask\nfrom paddlespeech.s2t.modules.mask import mask_finished_preds\nfrom paddlespeech.s2t.modules.mask import mask_finished_scores\nfrom paddlespeech.s2t.modules.mask import subsequent_mask\nfrom paddlespeech.s2t.utils import checkpoint\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils.ctc_utils import remove_duplicates_and_blank\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import log_add\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = [\"U2Model\", \"U2InferModel\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass U2BaseModel(ASRInterface, nn.Layer):\n    \"\"\"CTC-Attention hybrid Encoder-Decoder model\"\"\"\n\n    def __init__(self,\n                 vocab_size: int,\n                 encoder: TransformerEncoder,\n                 decoder: TransformerDecoder,\n                 ctc: CTCDecoderBase,\n                 ctc_weight: float=0.5,\n                 ignore_id: int=IGNORE_ID,\n                 reverse_weight: float=0.0,\n                 lsm_weight: float=0.0,\n                 length_normalized_loss: bool=False,\n                 **kwargs):\n        assert 0.0 <= ctc_weight <= 1.0, ctc_weight\n\n        nn.Layer.__init__(self)\n\n        # note that eos is the same as sos (equivalent ID)\n        self.sos = vocab_size - 1\n        self.eos = vocab_size - 1\n        self.vocab_size = vocab_size\n        self.ignore_id = ignore_id\n        self.ctc_weight = ctc_weight\n        self.reverse_weight = reverse_weight\n\n        self.encoder = encoder\n        self.decoder = decoder\n        self.ctc = ctc\n        self.criterion_att = LabelSmoothingLoss(\n            size=vocab_size,\n            padding_idx=ignore_id,\n            smoothing=lsm_weight,\n            normalize_length=length_normalized_loss, )\n\n    def forward(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n    ) -> Tuple[Optional[paddle.Tensor], Optional[paddle.Tensor], Optional[\n            paddle.Tensor]]:\n        \"\"\"Frontend + Encoder + Decoder + Calc loss\n        Args:\n            speech: (Batch, Length, ...)\n            speech_lengths: (Batch, )\n            text: (Batch, Length)\n            text_lengths: (Batch,)\n        Returns:\n            total_loss, attention_loss, ctc_loss\n        \"\"\"\n        assert text_lengths.dim() == 1, text_lengths.shape\n        # Check that batch_size is unified\n        assert (speech.shape[0] == speech_lengths.shape[0] == text.shape[0] ==\n                text_lengths.shape[0]), (speech.shape, speech_lengths.shape,\n                                         text.shape, text_lengths.shape)\n        # 1. Encoder\n        start = time.time()\n        encoder_out, encoder_mask = self.encoder(speech, speech_lengths)\n        encoder_time = time.time() - start\n        #logger.debug(f\"encoder time: {encoder_time}\")\n        encoder_out_lens = encoder_mask.squeeze(1).sum(1)  #[B, 1, T] -> [B]\n\n        # 2a. Attention-decoder branch\n        loss_att = None\n        if self.ctc_weight != 1.0:\n            start = time.time()\n            loss_att, acc_att = self._calc_att_loss(encoder_out, encoder_mask,\n                                                    text, text_lengths,\n                                                    self.reverse_weight)\n            decoder_time = time.time() - start\n            #logger.debug(f\"decoder time: {decoder_time}\")\n\n        # 2b. CTC branch\n        loss_ctc = None\n        if self.ctc_weight != 0.0:\n            start = time.time()\n            loss_ctc = self.ctc(encoder_out, encoder_out_lens, text,\n                                text_lengths)\n            ctc_time = time.time() - start\n            #logger.debug(f\"ctc time: {ctc_time}\")\n        if loss_ctc is None:\n            loss = loss_att\n        elif loss_att is None:\n            loss = loss_ctc\n        else:\n            loss = self.ctc_weight * loss_ctc + (1 - self.ctc_weight) * loss_att\n        return loss, loss_att, loss_ctc\n\n    def _calc_att_loss(self,\n                       encoder_out: paddle.Tensor,\n                       encoder_mask: paddle.Tensor,\n                       ys_pad: paddle.Tensor,\n                       ys_pad_lens: paddle.Tensor,\n                       reverse_weight: float) -> Tuple[paddle.Tensor, float]:\n        \"\"\"Calc attention loss.\n\n        Args:\n            encoder_out (paddle.Tensor): [B, Tmax, D]\n            encoder_mask (paddle.Tensor): [B, 1, Tmax]\n            ys_pad (paddle.Tensor): [B, Umax]\n            ys_pad_lens (paddle.Tensor): [B]\n            reverse_weight (float): reverse decoder weight.\n\n        Returns:\n            Tuple[paddle.Tensor, float]: attention_loss, accuracy rate\n        \"\"\"\n        ys_in_pad, ys_out_pad = add_sos_eos(ys_pad, self.sos, self.eos,\n                                            self.ignore_id)\n        ys_in_lens = ys_pad_lens + 1\n\n        r_ys_pad = reverse_pad_list(ys_pad, ys_pad_lens, float(self.ignore_id))\n        r_ys_in_pad, r_ys_out_pad = add_sos_eos(r_ys_pad, self.sos, self.eos,\n                                                self.ignore_id)\n        # 1. Forward decoder\n        decoder_out, r_decoder_out, _ = self.decoder(\n            encoder_out, encoder_mask, ys_in_pad, ys_in_lens, r_ys_in_pad,\n            reverse_weight)\n\n        # 2. Compute attention loss\n        loss_att = self.criterion_att(decoder_out, ys_out_pad)\n        r_loss_att = paddle.to_tensor(0.0)\n        if reverse_weight > 0.0:\n            r_loss_att = self.criterion_att(r_decoder_out, r_ys_out_pad)\n        loss_att = loss_att * (1 - reverse_weight) + r_loss_att * reverse_weight\n        acc_att = th_accuracy(\n            decoder_out.reshape([-1, self.vocab_size]),\n            ys_out_pad,\n            ignore_label=self.ignore_id, )\n        return loss_att, acc_att\n\n    def _forward_encoder(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Encoder pass.\n\n        Args:\n            speech (paddle.Tensor): [B, Tmax, D]\n            speech_lengths (paddle.Tensor): [B]\n            decoding_chunk_size (int, optional): chuck size. Defaults to -1.\n            num_decoding_left_chunks (int, optional): nums chunks. Defaults to -1.\n            simulate_streaming (bool, optional): streaming or not. Defaults to False.\n\n        Returns:\n            Tuple[paddle.Tensor, paddle.Tensor]:\n                encoder hiddens (B, Tmax, D),\n                encoder hiddens mask (B, 1, Tmax).\n        \"\"\"\n        # Let's assume B = batch_size\n        # 1. Encoder\n        if simulate_streaming and decoding_chunk_size > 0:\n            encoder_out, encoder_mask = self.encoder.forward_chunk_by_chunk(\n                speech,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks\n            )  # (B, maxlen, encoder_dim)\n        else:\n            encoder_out, encoder_mask = self.encoder(\n                speech,\n                speech_lengths,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks\n            )  # (B, maxlen, encoder_dim)\n        return encoder_out, encoder_mask\n\n    def recognize(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            beam_size: int=10,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False, ) -> paddle.Tensor:\n        \"\"\" Apply beam search on attention decoder\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            paddle.Tensor: decoding result, (batch, max_result_len)\n        \"\"\"\n        assert speech.shape[0] == speech_lengths.shape[0]\n        assert decoding_chunk_size != 0\n        device = speech.place\n        batch_size = speech.shape[0]\n\n        # Let's assume B = batch_size and N = beam_size\n        # 1. Encoder\n        encoder_out, encoder_mask = self._forward_encoder(\n            speech, speech_lengths, decoding_chunk_size,\n            num_decoding_left_chunks,\n            simulate_streaming)  # (B, maxlen, encoder_dim)\n        maxlen = encoder_out.shape[1]\n        encoder_dim = encoder_out.shape[2]\n        running_size = batch_size * beam_size\n        encoder_out = encoder_out.unsqueeze(1).repeat(\n            1, beam_size, 1, 1).reshape(\n                [running_size, maxlen,\n                 encoder_dim])  # (B*N, maxlen, encoder_dim)\n        encoder_mask = encoder_mask.unsqueeze(1).repeat(\n            1, beam_size, 1, 1).reshape([running_size, 1,\n                                         maxlen])  # (B*N, 1, max_len)\n\n        hyps = paddle.ones(\n            [running_size, 1], dtype=paddle.long).fill_(self.sos)  # (B*N, 1)\n        # log scale score\n        scores = paddle.to_tensor(\n            [0.0] + [-float('inf')] * (beam_size - 1), dtype=paddle.float)\n        scores = scores.to(device).repeat(batch_size).unsqueeze(1).to(\n            device)  # (B*N, 1)\n        end_flag = paddle.zeros_like(scores, dtype=paddle.bool)  # (B*N, 1)\n        cache: Optional[List[paddle.Tensor]] = None\n        # 2. Decoder forward step by step\n        for i in range(1, maxlen + 1):\n            # Stop if all batch and all beam produce eos\n            if end_flag.sum() == running_size:\n                break\n\n            # 2.1 Forward decoder step\n            hyps_mask = subsequent_mask(i).unsqueeze(0).repeat(\n                running_size, 1, 1).to(device)  # (B*N, i, i)\n            # logp: (B*N, vocab)\n            logp, cache = self.decoder.forward_one_step(\n                encoder_out, encoder_mask, hyps, hyps_mask, cache)\n            # 2.2 First beam prune: select topk best prob at current time\n            top_k_logp, top_k_index = logp.topk(beam_size)  # (B*N, N)\n            top_k_logp = mask_finished_scores(top_k_logp, end_flag)\n            top_k_index = mask_finished_preds(top_k_index, end_flag, self.eos)\n\n            # 2.3 Seconde beam prune: select topk score with history\n            scores = scores + top_k_logp  # (B*N, N), broadcast add\n            scores = scores.reshape(\n                [batch_size, beam_size * beam_size])  # (B, N*N)\n            scores, offset_k_index = scores.topk(k=beam_size)  # (B, N)\n            scores = scores.reshape([-1, 1])  # (B*N, 1)\n\n            # 2.4. Compute base index in top_k_index,\n            # regard top_k_index as (B*N*N),regard offset_k_index as (B*N),\n            # then find offset_k_index in top_k_index\n            base_k_index = paddle.arange(batch_size).reshape([-1, 1]).repeat(\n                1, beam_size)  # (B, N)\n            base_k_index = base_k_index * beam_size * beam_size\n            best_k_index = base_k_index.reshape([-1]) + offset_k_index.reshape(\n                [-1])  # (B*N)\n\n            # 2.5 Update best hyps\n            best_k_pred = paddle.index_select(\n                top_k_index.reshape([-1]), index=best_k_index, axis=0)  # (B*N)\n            best_hyps_index = best_k_index // beam_size\n            last_best_k_hyps = paddle.index_select(\n                hyps, index=best_hyps_index, axis=0)  # (B*N, i)\n            hyps = paddle.cat(\n                (last_best_k_hyps, best_k_pred.reshape([-1, 1])),\n                dim=1)  # (B*N, i+1)\n\n            # 2.6 Update end flag\n            end_flag = paddle.equal(hyps[:, -1], self.eos).reshape([-1, 1])\n\n        # 3. Select best of best\n        scores = scores.reshape([batch_size, beam_size])\n        # TODO: length normalization\n        best_index = paddle.argmax(scores, axis=-1).long()  # (B)\n        best_hyps_index = best_index + paddle.arange(\n            batch_size, dtype=paddle.long) * beam_size\n        best_hyps = paddle.index_select(hyps, index=best_hyps_index, axis=0)\n        best_hyps = best_hyps[:, 1:]\n        return best_hyps\n\n    def ctc_greedy_search(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False, ) -> List[List[int]]:\n        \"\"\" Apply CTC greedy search\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        assert speech.shape[0] == speech_lengths.shape[0]\n        assert decoding_chunk_size != 0\n        batch_size = speech.shape[0]\n\n        # Let's assume B = batch_size\n        # encoder_out: (B, maxlen, encoder_dim)\n        # encoder_mask: (B, 1, Tmax)\n\n        encoder_out, encoder_mask = self._forward_encoder(\n            speech, speech_lengths, decoding_chunk_size,\n            num_decoding_left_chunks, simulate_streaming)\n        maxlen = encoder_out.shape[1]\n        encoder_out_lens = encoder_mask.squeeze(1).sum(1)\n        ctc_probs = self.ctc.log_softmax(encoder_out)  # (B, maxlen, vocab_size)\n\n        topk_prob, topk_index = ctc_probs.topk(1, axis=2)  # (B, maxlen, 1)\n        topk_index = topk_index.reshape([batch_size, maxlen])  # (B, maxlen)\n        pad_mask = make_pad_mask(encoder_out_lens)  # (B, maxlen)\n        topk_index = topk_index.masked_fill_(pad_mask, self.eos)  # (B, maxlen)\n\n        hyps = [hyp.tolist() for hyp in topk_index]\n        hyps = [remove_duplicates_and_blank(hyp) for hyp in hyps]\n        return hyps\n\n    def _ctc_prefix_beam_search(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            beam_size: int,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False,\n            blank_id: int=0, ) -> Tuple[List[Tuple[int, float]], paddle.Tensor]:\n        \"\"\" CTC prefix beam search inner implementation\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[Tuple[int, float]]: nbest results, (N,1), (text, likelihood)\n            paddle.Tensor: encoder output, (1, max_len, encoder_dim),\n                it will be used for rescoring in attention rescoring mode\n        \"\"\"\n        assert speech.shape[0] == speech_lengths.shape[0]\n        assert decoding_chunk_size != 0\n        batch_size = speech.shape[0]\n        # For CTC prefix beam search, we only support batch_size=1\n        assert batch_size == 1\n\n        # Let's assume B = batch_size and N = beam_size\n        # 1. Encoder forward and get CTC score\n        encoder_out, encoder_mask = self._forward_encoder(\n            speech, speech_lengths, decoding_chunk_size,\n            num_decoding_left_chunks,\n            simulate_streaming)  # (B, maxlen, encoder_dim)\n        maxlen = encoder_out.shape[1]\n        ctc_probs = self.ctc.log_softmax(encoder_out)  # (1, maxlen, vocab_size)\n        ctc_probs = ctc_probs.squeeze(0)\n\n        # cur_hyps: (prefix, (blank_ending_score, none_blank_ending_score))\n        # blank_ending_score and  none_blank_ending_score in ln domain\n        cur_hyps = [(tuple(), (0.0, -float('inf')))]\n        # 2. CTC beam search step by step\n        for t in range(0, maxlen):\n            logp = ctc_probs[t]  # (vocab_size,)\n            # key: prefix, value (pb, pnb), default value(-inf, -inf)\n            next_hyps = defaultdict(lambda: (-float('inf'), -float('inf')))\n            # 2.1 First beam prune: select topk best\n            top_k_logp, top_k_index = logp.topk(beam_size)  # (beam_size,)\n            for s in top_k_index:\n                s = s.item()\n                ps = logp[s].item()\n                for prefix, (pb, pnb) in cur_hyps:\n                    last = prefix[-1] if len(prefix) > 0 else None\n                    if s == blank_id:  # blank\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pb = log_add([n_pb, pb + ps, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                    elif s == last:\n                        #  Update *ss -> *s;\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pnb = log_add([n_pnb, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                        # Update *s-s -> *ss, - is for blank\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n                    else:\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps, pnb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n\n            # 2.2 Second beam prune\n            next_hyps = sorted(\n                next_hyps.items(),\n                key=lambda x: log_add(list(x[1])),\n                reverse=True)\n            cur_hyps = next_hyps[:beam_size]\n\n        hyps = [(y[0], log_add([y[1][0], y[1][1]])) for y in cur_hyps]\n        return hyps, encoder_out\n\n    def ctc_prefix_beam_search(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            beam_size: int,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False, ) -> List[int]:\n        \"\"\" Apply CTC prefix beam search\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[int]: CTC prefix beam search nbest results\n        \"\"\"\n        hyps, _ = self._ctc_prefix_beam_search(\n            speech, speech_lengths, beam_size, decoding_chunk_size,\n            num_decoding_left_chunks, simulate_streaming)\n        return hyps[0][0]\n\n    def attention_rescoring(self,\n                            speech: paddle.Tensor,\n                            speech_lengths: paddle.Tensor,\n                            beam_size: int,\n                            decoding_chunk_size: int=-1,\n                            num_decoding_left_chunks: int=-1,\n                            ctc_weight: float=0.0,\n                            simulate_streaming: bool=False,\n                            reverse_weight: float=0.0) -> List[int]:\n        \"\"\" Apply attention rescoring decoding, CTC prefix beam search\n            is applied first to get nbest, then we resoring the nbest on\n            attention decoder with corresponding encoder out\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n            reverse_weight (float): reverse deocder weight.\n        Returns:\n            List[int]: Attention rescoring result\n        \"\"\"\n        assert speech.shape[0] == speech_lengths.shape[0]\n        assert decoding_chunk_size != 0\n        if reverse_weight > 0.0:\n            # decoder should be a bitransformer decoder if reverse_weight > 0.0\n            assert hasattr(self.decoder, 'right_decoder')\n        device = speech.place\n        batch_size = speech.shape[0]\n        # For attention rescoring we only support batch_size=1\n        assert batch_size == 1\n\n        # len(hyps) = beam_size, encoder_out: (1, maxlen, encoder_dim)\n        hyps, encoder_out = self._ctc_prefix_beam_search(\n            speech, speech_lengths, beam_size, decoding_chunk_size,\n            num_decoding_left_chunks, simulate_streaming)\n        assert len(hyps) == beam_size\n\n        hyp_list = []\n        for hyp in hyps:\n            hyp_content = hyp[0]\n            # Prevent the hyp is empty\n            if len(hyp_content) == 0:\n                hyp_content = (self.ctc.blank_id, )\n            hyp_content = paddle.to_tensor(\n                hyp_content, place=device, dtype=paddle.long)\n            hyp_list.append(hyp_content)\n        hyps_pad = pad_sequence(hyp_list, True, self.ignore_id)\n        hyps_lens = paddle.to_tensor(\n            [len(hyp[0]) for hyp in hyps], place=device,\n            dtype=paddle.long)  # (beam_size,)\n        hyps_pad, _ = add_sos_eos(hyps_pad, self.sos, self.eos, self.ignore_id)\n        hyps_lens = hyps_lens + 1  # Add <sos> at beginning\n        logger.debug(\n            f\"hyps pad: {hyps_pad} {self.sos} {self.eos} {self.ignore_id}\")\n\n        # ctc score in ln domain\n        # (beam_size, max_hyps_len, vocab_size)\n        decoder_out, r_decoder_out = self.forward_attention_decoder(\n            hyps_pad, hyps_lens, encoder_out, reverse_weight)\n\n        decoder_out = decoder_out.numpy()\n        # r_decoder_out will be 0.0, if reverse_weight is 0.0 or decoder is a\n        # conventional transformer decoder.\n        r_decoder_out = r_decoder_out.numpy()\n\n        # Only use decoder score for rescoring\n        best_score = -float('inf')\n        best_index = 0\n        # hyps is List[(Text=List[int], Score=float)], len(hyps)=beam_size\n        for i, hyp in enumerate(hyps):\n            score = 0.0\n            for j, w in enumerate(hyp[0]):\n                score += decoder_out[i][j][w]\n            # last decoder output token is `eos`, for laste decoder input token.\n            score += decoder_out[i][len(hyp[0])][self.eos]\n\n            logger.debug(\n                f\"hyp {i} len {len(hyp[0])} l2r score: {score} ctc_score: {hyp[1]} reverse_weight: {reverse_weight}\"\n            )\n\n            if reverse_weight > 0:\n                r_score = 0.0\n                for j, w in enumerate(hyp[0]):\n                    r_score += r_decoder_out[i][len(hyp[0]) - j - 1][w]\n                r_score += r_decoder_out[i][len(hyp[0])][self.eos]\n\n                logger.debug(\n                    f\"hyp {i} len {len(hyp[0])} r2l score: {r_score} ctc_score: {hyp[1]} reverse_weight: {reverse_weight}\"\n                )\n\n                score = score * (1 - reverse_weight) + r_score * reverse_weight\n            # add ctc score (which in ln domain)\n            score += hyp[1] * ctc_weight\n            if score > best_score:\n                best_score = score\n                best_index = i\n\n        logger.debug(f\"result: {hyps[best_index]}\")\n        return hyps[best_index][0]\n\n    @jit.to_static(property=True)\n    def subsampling_rate(self) -> int:\n        \"\"\" Export interface for c++ call, return subsampling_rate of the\n            model\n        \"\"\"\n        return self.encoder.embed.subsampling_rate\n\n    @jit.to_static(property=True)\n    def right_context(self) -> int:\n        \"\"\" Export interface for c++ call, return right_context of the model\n        \"\"\"\n        return self.encoder.embed.right_context\n\n    @jit.to_static(property=True)\n    def sos_symbol(self) -> int:\n        \"\"\" Export interface for c++ call, return sos symbol id of the model\n        \"\"\"\n        return self.sos\n\n    @jit.to_static(property=True)\n    def eos_symbol(self) -> int:\n        \"\"\" Export interface for c++ call, return eos symbol id of the model\n        \"\"\"\n        return self.eos\n\n    @jit.to_static(property=True)\n    def is_bidirectional_decoder(self) -> bool:\n        \"\"\"\n        Returns:\n            paddle.Tensor: decoder output\n        \"\"\"\n        if hasattr(self.decoder, 'right_decoder'):\n            return True\n        else:\n            return False\n\n    # @jit.to_static\n    def forward_encoder_chunk(\n            self,\n            xs: paddle.Tensor,\n            offset: int,\n            required_cache_size: int,\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\" Export interface for c++ call, give input chunk xs, and return\n            output from time 0 to current chunk.\n\n        Args:\n            xs (paddle.Tensor): chunk input, with shape (b=1, time, mel-dim),\n                where `time == (chunk_size - 1) * subsample_rate + \\\n                        subsample.right_context + 1`\n            offset (int): current offset in encoder output time stamp\n            required_cache_size (int): cache size required for next chunk\n                compuation\n                >=0: actual cache size\n                <0: means all history cache is required\n            att_cache (paddle.Tensor): cache tensor for KEY & VALUE in\n                transformer/conformer attention, with shape\n                (elayers, head, cache_t1, d_k * 2), where\n                `head * d_k == hidden-dim` and\n                `cache_t1 == chunk_size * num_decoding_left_chunks`.\n                `d_k * 2` for att key & value. \n            cnn_cache (paddle.Tensor): cache tensor for cnn_module in conformer,\n                (elayers, b=1, hidden-dim, cache_t2), where\n                `cache_t2 == cnn.lorder - 1`. \n                \n        Returns:\n            paddle.Tensor: output of current input xs,\n                with shape (b=1, chunk_size, hidden-dim).\n            paddle.Tensor: new attention cache required for next chunk, with\n                dynamic shape (elayers, head, T(?), d_k * 2)\n                depending on required_cache_size.\n            paddle.Tensor: new conformer cnn cache required for next chunk, with\n                same shape as the original cnn_cache.\n        \"\"\"\n        return self.encoder.forward_chunk(xs, offset, required_cache_size,\n                                          att_cache, cnn_cache)\n\n    # @jit.to_static\n    def ctc_activation(self, xs: paddle.Tensor) -> paddle.Tensor:\n        \"\"\" Export interface for c++ call, apply linear transform and log\n            softmax before ctc\n        Args:\n            xs (paddle.Tensor): encoder output, (B, T, D)\n        Returns:\n            paddle.Tensor: activation before ctc. (B, Tmax, odim)\n        \"\"\"\n        return self.ctc.log_softmax(xs)\n\n    # @jit.to_static\n    def forward_attention_decoder(self,\n                                  hyps: paddle.Tensor,\n                                  hyps_lens: paddle.Tensor,\n                                  encoder_out: paddle.Tensor,\n                                  reverse_weight: float=0.0) -> paddle.Tensor:\n        \"\"\" Export interface for c++ call, forward decoder with multiple\n            hypothesis from ctc prefix beam search and one encoder output\n        Args:\n            hyps (paddle.Tensor): hyps from ctc prefix beam search, already\n                pad sos at the beginning, (B, T)\n            hyps_lens (paddle.Tensor): length of each hyp in hyps, (B)\n            encoder_out (paddle.Tensor): corresponding encoder output, (B=1, T, D)\n        Returns:\n            paddle.Tensor: decoder output, (B, L)\n        \"\"\"\n        assert encoder_out.shape[0] == 1\n        num_hyps = hyps.shape[0]\n        assert hyps_lens.shape[0] == num_hyps\n        encoder_out = encoder_out.repeat(num_hyps, 1, 1)\n        # (B, 1, T)\n        encoder_mask = paddle.ones(\n            [num_hyps, 1, encoder_out.shape[1]], dtype=paddle.bool)\n\n        # input for right to left decoder\n        # this hyps_lens has count <sos> token, we need minus it.\n        r_hyps_lens = hyps_lens - 1\n        # this hyps has included <sos> token, so it should be\n        # convert the original hyps.\n        r_hyps = hyps[:, 1:]\n        # (num_hyps, max_hyps_len, vocab_size)\n\n        r_hyps = st_reverse_pad_list(r_hyps, r_hyps_lens, self.sos, self.eos)\n\n        decoder_out, r_decoder_out, _ = self.decoder(\n            encoder_out, encoder_mask, hyps, hyps_lens, r_hyps, reverse_weight)\n        decoder_out = paddle.nn.functional.log_softmax(decoder_out, axis=-1)\n        r_decoder_out = paddle.nn.functional.log_softmax(r_decoder_out, axis=-1)\n        return decoder_out, r_decoder_out\n\n    @paddle.no_grad()\n    def decode(self,\n               feats: paddle.Tensor,\n               feats_lengths: paddle.Tensor,\n               text_feature: Dict[str, int],\n               decoding_method: str,\n               beam_size: int,\n               ctc_weight: float=0.0,\n               decoding_chunk_size: int=-1,\n               num_decoding_left_chunks: int=-1,\n               simulate_streaming: bool=False,\n               reverse_weight: float=0.0):\n        \"\"\"u2 decoding.\n\n        Args:\n            feats (Tensor): audio features, (B, T, D)\n            feats_lengths (Tensor): (B)\n            text_feature (TextFeaturizer): text feature object.\n            decoding_method (str): decoding mode, e.g.\n                    'attention', 'ctc_greedy_search',\n                    'ctc_prefix_beam_search', 'attention_rescoring'\n            beam_size (int): beam size for search\n            ctc_weight (float, optional): ctc weight for attention rescoring decode mode. Defaults to 0.0.\n            decoding_chunk_size (int, optional): decoding chunk size. Defaults to -1.\n                    <0: for decoding, use full chunk.\n                    >0: for decoding, use fixed chunk size as set.\n                    0: used for training, it's prohibited here.\n            num_decoding_left_chunks (int, optional):\n                    number of left chunks for decoding. Defaults to -1.\n            simulate_streaming (bool, optional): simulate streaming inference. Defaults to False.\n            reverse_weight (float, optional): reverse decoder weight, used by `attention_rescoring`.\n\n        Raises:\n            ValueError: when not support decoding_method.\n\n        Returns:\n            List[List[int]]: transcripts.\n        \"\"\"\n        batch_size = feats.shape[0]\n        if decoding_method in ['ctc_prefix_beam_search',\n                               'attention_rescoring'] and batch_size > 1:\n            logger.error(\n                f'decoding mode {decoding_method} must be running with batch_size == 1'\n            )\n            logger.error(f\"current batch_size is {batch_size}\")\n            sys.exit(1)\n        if decoding_method == 'attention':\n            hyps = self.recognize(\n                feats,\n                feats_lengths,\n                beam_size=beam_size,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks,\n                simulate_streaming=simulate_streaming)\n            hyps = [hyp.tolist() for hyp in hyps]\n        elif decoding_method == 'ctc_greedy_search':\n            hyps = self.ctc_greedy_search(\n                feats,\n                feats_lengths,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks,\n                simulate_streaming=simulate_streaming)\n        # ctc_prefix_beam_search and attention_rescoring only return one\n        # result in List[int], change it to List[List[int]] for compatible\n        # with other batch decoding mode\n        elif decoding_method == 'ctc_prefix_beam_search':\n            assert feats.shape[0] == 1\n            hyp = self.ctc_prefix_beam_search(\n                feats,\n                feats_lengths,\n                beam_size,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks,\n                simulate_streaming=simulate_streaming)\n            hyps = [hyp]\n        elif decoding_method == 'attention_rescoring':\n            assert feats.shape[0] == 1\n            hyp = self.attention_rescoring(\n                feats,\n                feats_lengths,\n                beam_size,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks,\n                ctc_weight=ctc_weight,\n                simulate_streaming=simulate_streaming,\n                reverse_weight=reverse_weight)\n            hyps = [hyp]\n        else:\n            raise ValueError(f\"Not support decoding method: {decoding_method}\")\n\n        res = [text_feature.defeaturize(hyp) for hyp in hyps]\n        res_tokenids = [hyp for hyp in hyps]\n        return res, res_tokenids\n\n\nclass U2DecodeModel(U2BaseModel):\n    def scorers(self):\n        \"\"\"Scorers.\"\"\"\n        return dict(\n            decoder=self.decoder, ctc=CTCPrefixScorer(self.ctc, self.eos))\n\n    def encode(self, x):\n        \"\"\"Encode acoustic features.\n\n        :param ndarray x: source acoustic feature (T, D)\n        :return: encoder outputs\n        :rtype: paddle.Tensor\n        \"\"\"\n        self.eval()\n        x = paddle.to_tensor(x).unsqueeze(0)\n        ilen = paddle.shape(x)[1]\n        enc_output, _ = self._forward_encoder(x, ilen)\n        return enc_output.squeeze(0)\n\n\nclass U2Model(U2DecodeModel):\n    def __init__(self, configs: dict):\n        model_conf = configs.get('model_conf', dict())\n        init_type = model_conf.get(\"init_type\", None)\n        with DefaultInitializerContext(init_type):\n            vocab_size, encoder, decoder, ctc = U2Model._init_from_config(\n                configs)\n        super().__init__(\n            vocab_size=vocab_size,\n            encoder=encoder,\n            decoder=decoder,\n            ctc=ctc,\n            **model_conf)\n\n    @classmethod\n    def _init_from_config(cls, configs: dict):\n        \"\"\"init sub module for model.\n\n        Args:\n            configs (dict): config dict.\n\n        Raises:\n            ValueError: raise when using not support encoder type.\n\n        Returns:\n            int, nn.Layer, nn.Layer, nn.Layer: vocab size, encoder, decoder, ctc\n        \"\"\"\n        # cmvn\n        if 'cmvn_file' in configs and configs['cmvn_file']:\n            mean, istd = load_cmvn(configs['cmvn_file'],\n                                   configs['cmvn_file_type'])\n            global_cmvn = GlobalCMVN(\n                paddle.to_tensor(mean, dtype=paddle.float),\n                paddle.to_tensor(istd, dtype=paddle.float))\n        else:\n            global_cmvn = None\n\n        # input & output dim\n        input_dim = configs['input_dim']\n        vocab_size = configs['output_dim']\n        assert input_dim != 0, input_dim\n        assert vocab_size != 0, vocab_size\n\n        # encoder\n        encoder_type = configs.get('encoder', 'transformer')\n        logger.debug(f\"U2 Encoder type: {encoder_type}\")\n        if encoder_type == 'transformer':\n            encoder = TransformerEncoder(\n                input_dim, global_cmvn=global_cmvn, **configs['encoder_conf'])\n        elif encoder_type == 'conformer':\n            encoder = ConformerEncoder(\n                input_dim, global_cmvn=global_cmvn, **configs['encoder_conf'])\n        elif encoder_type == 'squeezeformer':\n            encoder = SqueezeformerEncoder(\n                input_dim, global_cmvn=global_cmvn, **configs['encoder_conf'])\n        else:\n            raise ValueError(f\"not support encoder type:{encoder_type}\")\n\n        # decoder\n        decoder_type = configs.get('decoder', 'transformer')\n        logger.debug(f\"U2 Decoder type: {decoder_type}\")\n        if decoder_type == 'transformer':\n            configs['model_conf'].pop('reverse_weight', None)\n            configs['decoder_conf'].pop('r_num_blocks', None)\n            decoder = TransformerDecoder(vocab_size,\n                                         encoder.output_size(),\n                                         **configs['decoder_conf'])\n        elif decoder_type == 'bitransformer':\n            assert 0.0 < configs['model_conf']['reverse_weight'] < 1.0\n            assert configs['decoder_conf']['r_num_blocks'] > 0\n            decoder = BiTransformerDecoder(vocab_size,\n                                           encoder.output_size(),\n                                           **configs['decoder_conf'])\n        else:\n            raise ValueError(f\"not support decoder type:{decoder_type}\")\n        # ctc decoder and ctc loss\n        model_conf = configs.get('model_conf', dict())\n        dropout_rate = model_conf.get('ctc_dropout_rate', 0.0)\n        grad_norm_type = model_conf.get('ctc_grad_norm_type', None)\n        ctc = CTCDecoderBase(\n            odim=vocab_size,\n            enc_n_units=encoder.output_size(),\n            blank_id=0,\n            dropout_rate=dropout_rate,\n            reduction=True,  # sum\n            batch_average=True,  # sum / batch_size\n            grad_norm_type=grad_norm_type)\n\n        return vocab_size, encoder, decoder, ctc\n\n    @classmethod\n    def from_config(cls, configs: dict):\n        \"\"\"init model.\n\n        Args:\n            configs (dict): config dict.\n\n        Raises:\n            ValueError: raise when using not support encoder type.\n\n        Returns:\n            nn.Layer: U2Model\n        \"\"\"\n        model = cls(configs)\n        return model\n\n    @classmethod\n    def from_pretrained(cls, dataloader, config, checkpoint_path):\n        \"\"\"Build a DeepSpeech2Model model from a pretrained model.\n\n        Args:\n            dataloader (paddle.io.DataLoader): not used.\n            config (yacs.config.CfgNode):  model configs\n            checkpoint_path (Path or str): the path of pretrained model checkpoint, without extension name\n\n        Returns:\n            DeepSpeech2Model: The model built from pretrained result.\n        \"\"\"\n        with UpdateConfig(config):\n            config.input_dim = dataloader.feat_dim\n            config.output_dim = dataloader.vocab_size\n\n        model = cls.from_config(config)\n\n        if checkpoint_path:\n            infos = checkpoint.Checkpoint().load_parameters(\n                model, checkpoint_path=checkpoint_path)\n            logger.debug(f\"checkpoint info: {infos}\")\n        layer_tools.summary(model)\n        return model\n\n\nclass U2InferModel(U2Model):\n    def __init__(self, configs: dict):\n        super().__init__(configs)\n\n        from paddlespeech.s2t.modules.fbank import KaldiFbank\n        import yaml\n        import json\n        import numpy as np\n\n        input_dim = configs['input_dim']\n        process = configs['preprocess_config']\n        with open(process, encoding=\"utf-8\") as f:\n            conf = yaml.safe_load(f)\n            assert isinstance(conf, dict), type(self.conf)\n\n        for idx, process in enumerate(conf['process']):\n            assert isinstance(process, dict), type(process)\n            opts = dict(process)\n            process_type = opts.pop(\"type\")\n\n            if process_type == 'fbank_kaldi':\n                opts.update({'n_mels': input_dim})\n                opts['dither'] = 0.0\n                self.fbank = KaldiFbank(**opts)\n                logger.info(f\"{self.__class__.__name__} export: {self.fbank}\")\n            if process_type == 'cmvn_json':\n                # align with paddlespeech.audio.transform.cmvn:GlobalCMVN\n                std_floor = 1.0e-20\n\n                cmvn = opts['cmvn_path']\n                if isinstance(cmvn, dict):\n                    cmvn_stats = cmvn\n                else:\n                    with open(cmvn) as f:\n                        cmvn_stats = json.load(f)\n                count = cmvn_stats['frame_num']\n                mean = np.array(cmvn_stats['mean_stat']) / count\n                square_sums = np.array(cmvn_stats['var_stat'])\n                var = square_sums / count - mean**2\n                std = np.maximum(np.sqrt(var), std_floor)\n                istd = 1.0 / std\n                self.global_cmvn = GlobalCMVN(\n                    paddle.to_tensor(mean, dtype=paddle.float),\n                    paddle.to_tensor(istd, dtype=paddle.float))\n                logger.info(\n                    f\"{self.__class__.__name__} export: {self.global_cmvn}\")\n\n    def forward(self,\n                feats,\n                feats_lengths,\n                decoding_chunk_size=-1,\n                num_decoding_left_chunks=-1,\n                simulate_streaming=False):\n        \"\"\"export model function\n\n        Args:\n            feats (Tensor): [B, T, D]\n            feats_lengths (Tensor): [B]\n\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        # dummy code for dy2st\n        # return self.ctc_greedy_search(\n        #     feats,\n        #     feats_lengths,\n        #     decoding_chunk_size=decoding_chunk_size,\n        #     num_decoding_left_chunks=num_decoding_left_chunks,\n        #     simulate_streaming=simulate_streaming)\n        return feats, feats_lengths\n\n    def forward_feature(self, x):\n        \"\"\"feature pipeline.\n\n        Args:\n            x (paddle.Tensor): waveform (T,).\n\n        Return:\n            feat (paddle.Tensor): feature (T, D) \n        \"\"\"\n        x = paddle.cast(x, paddle.float32)\n        feat = self.fbank(x)\n        feat = self.global_cmvn(feat)\n        return feat\n"
  },
  {
    "path": "paddlespeech/s2t/models/u2/updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom contextlib import nullcontext\n\nimport paddle\nfrom paddle import distributed as dist\n\nfrom paddlespeech.s2t.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\nclass U2Evaluator(StandardEvaluator):\n    def __init__(self, model, dataloader):\n        super().__init__(model, dataloader)\n        self.msg = \"\"\n        self.num_seen_utts = 0\n        self.total_loss = 0.0\n\n    def evaluate_core(self, batch):\n        self.msg = \"Valid: Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        loss, attention_loss, ctc_loss = self.model(*batch[1:])\n        if paddle.isfinite(loss):\n            num_utts = batch[1].shape[0]\n            self.num_seen_utts += num_utts\n            self.total_loss += float(loss) * num_utts\n\n            losses_dict['loss'] = float(loss)\n            if attention_loss:\n                losses_dict['att_loss'] = float(attention_loss)\n            if ctc_loss:\n                losses_dict['ctc_loss'] = float(ctc_loss)\n\n            for k, v in losses_dict.items():\n                report(\"eval/\" + k, v)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        logger.info(self.msg)\n        return self.total_loss, self.num_seen_utts\n\n\nclass U2Updater(StandardUpdater):\n    def __init__(self,\n                 model,\n                 optimizer,\n                 scheduler,\n                 dataloader,\n                 init_state=None,\n                 accum_grad=1,\n                 **kwargs):\n        super().__init__(\n            model, optimizer, scheduler, dataloader, init_state=init_state)\n        self.accum_grad = accum_grad\n        self.forward_count = 0\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        \"\"\"One Step\n\n        Args:\n            batch (List[Object]): utts, xs, xlens, ys, ylens\n        \"\"\"\n        losses_dict = {}\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n\n        # forward\n        batch_size = batch[1].shape[0]\n        loss, attention_loss, ctc_loss = self.model(*batch[1:])\n        # loss div by `batch_size * accum_grad`\n        loss /= self.accum_grad\n\n        # loss backward\n        if (self.forward_count + 1) != self.accum_grad:\n            # Disable gradient synchronizations across DDP processes.\n            # Within this context, gradients will be accumulated on module\n            # variables, which will later be synchronized.\n            context = self.model.no_sync\n        else:\n            # Used for single gpu training and DDP gradient synchronization\n            # processes.\n            context = nullcontext\n\n        with context():\n            loss.backward()\n            layer_tools.print_grads(self.model, print_func=None)\n\n        # loss info\n        losses_dict['loss'] = float(loss) * self.accum_grad\n        if attention_loss:\n            losses_dict['att_loss'] = float(attention_loss)\n        if ctc_loss:\n            losses_dict['ctc_loss'] = float(ctc_loss)\n        # report loss\n        for k, v in losses_dict.items():\n            report(\"train/\" + k, v)\n        # loss msg\n        self.msg += \"batch size: {}, \".format(batch_size)\n        self.msg += \"accum: {}, \".format(self.accum_grad)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n        # Truncate the graph\n        loss.detach()\n\n        # update parameters\n        self.forward_count += 1\n        if self.forward_count != self.accum_grad:\n            return\n        self.forward_count = 0\n\n        self.optimizer.step()\n        self.optimizer.clear_grad()\n        self.scheduler.step()\n\n    def update(self):\n        # model is default in train mode\n\n        # training for a step is implemented here\n        with Timer(\"data time cost:{}\"):\n            batch = self.read_batch()\n        with Timer(\"step time cost:{}\"):\n            self.update_core(batch)\n\n        # #iterations with accum_grad > 1\n        # Ref.: https://github.com/espnet/espnet/issues/777\n        if self.forward_count == 0:\n            self.state.iteration += 1\n        if self.updates_per_epoch is not None:\n            if self.state.iteration % self.updates_per_epoch == 0:\n                self.state.epoch += 1\n"
  },
  {
    "path": "paddlespeech/s2t/models/u2_st/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .u2_st import U2STInferModel\nfrom .u2_st import U2STModel\n"
  },
  {
    "path": "paddlespeech/s2t/models/u2_st/u2_st.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"U2 ASR Model\nUnified Streaming and Non-streaming Two-pass End-to-end Model for Speech Recognition\n(https://arxiv.org/pdf/2012.05481.pdf)\n\"\"\"\nimport time\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import jit\nfrom paddle import nn\n\nfrom paddlespeech.audio.utils.tensor_utils import add_sos_eos\nfrom paddlespeech.audio.utils.tensor_utils import th_accuracy\nfrom paddlespeech.s2t.frontend.utility import IGNORE_ID\nfrom paddlespeech.s2t.frontend.utility import load_cmvn\nfrom paddlespeech.s2t.modules.cmvn import GlobalCMVN\nfrom paddlespeech.s2t.modules.ctc import CTCDecoderBase\nfrom paddlespeech.s2t.modules.decoder import TransformerDecoder\nfrom paddlespeech.s2t.modules.encoder import ConformerEncoder\nfrom paddlespeech.s2t.modules.encoder import TransformerEncoder\nfrom paddlespeech.s2t.modules.loss import LabelSmoothingLoss\nfrom paddlespeech.s2t.modules.mask import subsequent_mask\nfrom paddlespeech.s2t.utils import checkpoint\nfrom paddlespeech.s2t.utils import layer_tools\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = [\"U2STModel\", \"U2STInferModel\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass U2STBaseModel(nn.Layer):\n    \"\"\"CTC-Attention hybrid Encoder-Decoder model\"\"\"\n\n    def __init__(self,\n                 vocab_size: int,\n                 encoder: TransformerEncoder,\n                 st_decoder: TransformerDecoder,\n                 decoder: TransformerDecoder=None,\n                 ctc: CTCDecoderBase=None,\n                 ctc_weight: float=0.0,\n                 asr_weight: float=0.0,\n                 ignore_id: int=IGNORE_ID,\n                 lsm_weight: float=0.0,\n                 length_normalized_loss: bool=False,\n                 **kwargs):\n        assert 0.0 <= ctc_weight <= 1.0, ctc_weight\n\n        super().__init__()\n        # note that eos is the same as sos (equivalent ID)\n        self.sos = vocab_size - 1\n        self.eos = vocab_size - 1\n        self.vocab_size = vocab_size\n        self.ignore_id = ignore_id\n        self.ctc_weight = ctc_weight\n        self.asr_weight = asr_weight\n\n        self.encoder = encoder\n        self.st_decoder = st_decoder\n        self.decoder = decoder\n        self.ctc = ctc\n        self.criterion_att = LabelSmoothingLoss(\n            size=vocab_size,\n            padding_idx=ignore_id,\n            smoothing=lsm_weight,\n            normalize_length=length_normalized_loss, )\n\n    def forward(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            asr_text: paddle.Tensor=None,\n            asr_text_lengths: paddle.Tensor=None,\n    ) -> Tuple[Optional[paddle.Tensor], Optional[paddle.Tensor], Optional[\n            paddle.Tensor]]:\n        \"\"\"Frontend + Encoder + Decoder + Calc loss\n        Args:\n            speech: (Batch, Length, ...)\n            speech_lengths: (Batch, )\n            text: (Batch, Length)\n            text_lengths: (Batch,)\n        Returns:\n            total_loss, attention_loss, ctc_loss\n        \"\"\"\n        assert text_lengths.dim() == 1, text_lengths.shape\n        # Check that batch_size is unified\n        assert (speech.shape[0] == speech_lengths.shape[0] == text.shape[0] ==\n                text_lengths.shape[0]), (speech.shape, speech_lengths.shape,\n                                         text.shape, text_lengths.shape)\n        # 1. Encoder\n        start = time.time()\n        encoder_out, encoder_mask = self.encoder(speech, speech_lengths)\n        encoder_time = time.time() - start\n        #logger.debug(f\"encoder time: {encoder_time}\")\n        encoder_out_lens = encoder_mask.squeeze(1).sum(1)  #[B, 1, T] -> [B]\n\n        # 2a. ST-decoder branch\n        start = time.time()\n        loss_st, acc_st = self._calc_st_loss(encoder_out, encoder_mask, text,\n                                             text_lengths)\n        decoder_time = time.time() - start\n\n        loss_asr_att = None\n        loss_asr_ctc = None\n        # 2b. ASR Attention-decoder branch\n        if self.asr_weight > 0.:\n            if self.ctc_weight != 1.0:\n                start = time.time()\n                loss_asr_att, acc_att = self._calc_att_loss(\n                    encoder_out, encoder_mask, asr_text, asr_text_lengths)\n                decoder_time = time.time() - start\n\n            # 2c. CTC branch\n            if self.ctc_weight != 0.0:\n                start = time.time()\n                loss_asr_ctc = self.ctc(encoder_out, encoder_out_lens, asr_text,\n                                        asr_text_lengths)\n                ctc_time = time.time() - start\n\n            if loss_asr_ctc is None:\n                loss_asr = loss_asr_att\n            elif loss_asr_att is None:\n                loss_asr = loss_asr_ctc\n            else:\n                loss_asr = self.ctc_weight * loss_asr_ctc + (1 - self.ctc_weight\n                                                             ) * loss_asr_att\n            loss = self.asr_weight * loss_asr + (1 - self.asr_weight) * loss_st\n        else:\n            loss = loss_st\n        return loss, loss_st, loss_asr_att, loss_asr_ctc\n\n    def _calc_st_loss(\n            self,\n            encoder_out: paddle.Tensor,\n            encoder_mask: paddle.Tensor,\n            ys_pad: paddle.Tensor,\n            ys_pad_lens: paddle.Tensor, ) -> Tuple[paddle.Tensor, float]:\n        \"\"\"Calc attention loss.\n\n        Args:\n            encoder_out (paddle.Tensor): [B, Tmax, D]\n            encoder_mask (paddle.Tensor): [B, 1, Tmax]\n            ys_pad (paddle.Tensor): [B, Umax]\n            ys_pad_lens (paddle.Tensor): [B]\n\n        Returns:\n            Tuple[paddle.Tensor, float]: attention_loss, accuracy rate\n        \"\"\"\n        ys_in_pad, ys_out_pad = add_sos_eos(ys_pad, self.sos, self.eos,\n                                            self.ignore_id)\n        ys_in_lens = ys_pad_lens + 1\n\n        # 1. Forward decoder\n        decoder_out, *_ = self.st_decoder(encoder_out, encoder_mask, ys_in_pad,\n                                          ys_in_lens)\n\n        # 2. Compute attention loss\n        loss_att = self.criterion_att(decoder_out, ys_out_pad)\n        acc_att = th_accuracy(\n            decoder_out.reshape([-1, self.vocab_size]),\n            ys_out_pad,\n            ignore_label=self.ignore_id, )\n        return loss_att, acc_att\n\n    def _calc_att_loss(\n            self,\n            encoder_out: paddle.Tensor,\n            encoder_mask: paddle.Tensor,\n            ys_pad: paddle.Tensor,\n            ys_pad_lens: paddle.Tensor, ) -> Tuple[paddle.Tensor, float]:\n        \"\"\"Calc attention loss.\n\n        Args:\n            encoder_out (paddle.Tensor): [B, Tmax, D]\n            encoder_mask (paddle.Tensor): [B, 1, Tmax]\n            ys_pad (paddle.Tensor): [B, Umax]\n            ys_pad_lens (paddle.Tensor): [B]\n\n        Returns:\n            Tuple[paddle.Tensor, float]: attention_loss, accuracy rate\n        \"\"\"\n        ys_in_pad, ys_out_pad = add_sos_eos(ys_pad, self.sos, self.eos,\n                                            self.ignore_id)\n        ys_in_lens = ys_pad_lens + 1\n\n        # 1. Forward decoder\n        decoder_out, *_ = self.decoder(encoder_out, encoder_mask, ys_in_pad,\n                                       ys_in_lens)\n\n        # 2. Compute attention loss\n        loss_att = self.criterion_att(decoder_out, ys_out_pad)\n        acc_att = th_accuracy(\n            decoder_out.reshape([-1, self.vocab_size]),\n            ys_out_pad,\n            ignore_label=self.ignore_id, )\n        return loss_att, acc_att\n\n    def _forward_encoder(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Encoder pass.\n\n        Args:\n            speech (paddle.Tensor): [B, Tmax, D]\n            speech_lengths (paddle.Tensor): [B]\n            decoding_chunk_size (int, optional): chuck size. Defaults to -1.\n            num_decoding_left_chunks (int, optional): nums chunks. Defaults to -1.\n            simulate_streaming (bool, optional): streaming or not. Defaults to False.\n\n        Returns:\n            Tuple[paddle.Tensor, paddle.Tensor]:\n                encoder hiddens (B, Tmax, D),\n                encoder hiddens mask (B, 1, Tmax).\n        \"\"\"\n        # Let's assume B = batch_size\n        # 1. Encoder\n        if simulate_streaming and decoding_chunk_size > 0:\n            encoder_out, encoder_mask = self.encoder.forward_chunk_by_chunk(\n                speech,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks\n            )  # (B, maxlen, encoder_dim)\n        else:\n            encoder_out, encoder_mask = self.encoder(\n                speech,\n                speech_lengths,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks\n            )  # (B, maxlen, encoder_dim)\n        return encoder_out, encoder_mask\n\n    def translate(\n            self,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            beam_size: int=10,\n            word_reward: float=0.0,\n            maxlenratio: float=0.5,\n            decoding_chunk_size: int=-1,\n            num_decoding_left_chunks: int=-1,\n            simulate_streaming: bool=False, ) -> paddle.Tensor:\n        \"\"\" Apply beam search on attention decoder with length penalty\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            word_reward (float): word reward used in beam search\n            maxlenratio (float): max length ratio to bound the length of translated text\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            paddle.Tensor: decoding result, (batch, max_result_len)\n        \"\"\"\n        assert speech.shape[0] == speech_lengths.shape[0]\n        assert decoding_chunk_size != 0\n        assert speech.shape[0] == 1\n        device = speech.place\n\n        # Let's assume B = batch_size and N = beam_size\n        # 1. Encoder and init hypothesis\n        encoder_out, encoder_mask = self._forward_encoder(\n            speech, speech_lengths, decoding_chunk_size,\n            num_decoding_left_chunks,\n            simulate_streaming)  # (B, maxlen, encoder_dim)\n\n        maxlen = max(int(encoder_out.shape[1] * maxlenratio), 5)\n\n        hyp = {\"score\": 0.0, \"yseq\": [self.sos], \"cache\": None}\n        hyps = [hyp]\n        ended_hyps = []\n        cur_best_score = -float(\"inf\")\n        cache = None\n\n        # 2. Decoder forward step by step\n        for i in range(1, maxlen + 1):\n            ys = paddle.ones((len(hyps), i), dtype=paddle.long)\n\n            if hyps[0][\"cache\"] is not None:\n                cache = [\n                    paddle.ones(\n                        (len(hyps), i - 1, hyp_cache.shape[-1]),\n                        dtype=paddle.float32) for hyp_cache in hyps[0][\"cache\"]\n                ]\n            for j, hyp in enumerate(hyps):\n                ys[j, :] = paddle.to_tensor(hyp[\"yseq\"])\n                if hyps[0][\"cache\"] is not None:\n                    for k in range(len(cache)):\n                        cache[k][j] = hyps[j][\"cache\"][k]\n            ys_mask = subsequent_mask(i).unsqueeze(0).to(device)\n\n            logp, cache = self.st_decoder.forward_one_step(\n                encoder_out.repeat(len(hyps), 1, 1),\n                encoder_mask.repeat(len(hyps), 1, 1), ys, ys_mask, cache)\n\n            hyps_best_kept = []\n            for j, hyp in enumerate(hyps):\n                top_k_logp, top_k_index = logp[j:j + 1].topk(beam_size)\n\n                for b in range(beam_size):\n                    new_hyp = {}\n                    new_hyp[\"score\"] = hyp[\"score\"] + float(top_k_logp[0, b])\n                    new_hyp[\"yseq\"] = [0] * (1 + len(hyp[\"yseq\"]))\n                    new_hyp[\"yseq\"][:len(hyp[\"yseq\"])] = hyp[\"yseq\"]\n                    new_hyp[\"yseq\"][len(hyp[\"yseq\"])] = int(top_k_index[0, b])\n                    new_hyp[\"cache\"] = [cache_[j] for cache_ in cache]\n                    # will be (2 x beam) hyps at most\n                    hyps_best_kept.append(new_hyp)\n\n                hyps_best_kept = sorted(\n                    hyps_best_kept, key=lambda x: -x[\"score\"])[:beam_size]\n\n            # sort and get nbest\n            hyps = hyps_best_kept\n            if i == maxlen:\n                for hyp in hyps:\n                    hyp[\"yseq\"].append(self.eos)\n\n            # finalize the ended hypotheses with word reward (by length)\n            remained_hyps = []\n            for hyp in hyps:\n                if hyp[\"yseq\"][-1] == self.eos:\n                    hyp[\"score\"] += (i - 1) * word_reward\n                    cur_best_score = max(cur_best_score, hyp[\"score\"])\n                    ended_hyps.append(hyp)\n                else:\n                    # stop while guarantee the optimality\n                    if hyp[\"score\"] + maxlen * word_reward > cur_best_score:\n                        remained_hyps.append(hyp)\n\n            # stop predition when there is no unended hypothesis\n            if not remained_hyps:\n                break\n            hyps = remained_hyps\n\n        # 3. Select best of best\n        best_hyp = max(ended_hyps, key=lambda x: x[\"score\"])\n\n        return paddle.to_tensor([best_hyp[\"yseq\"][1:]])\n\n    # @jit.to_static\n    def subsampling_rate(self) -> int:\n        \"\"\" Export interface for c++ call, return subsampling_rate of the\n            model\n        \"\"\"\n        return self.encoder.embed.subsampling_rate\n\n    # @jit.to_static\n    def right_context(self) -> int:\n        \"\"\" Export interface for c++ call, return right_context of the model\n        \"\"\"\n        return self.encoder.embed.right_context\n\n    # @jit.to_static\n    def sos_symbol(self) -> int:\n        \"\"\" Export interface for c++ call, return sos symbol id of the model\n        \"\"\"\n        return self.sos\n\n    # @jit.to_static\n    def eos_symbol(self) -> int:\n        \"\"\" Export interface for c++ call, return eos symbol id of the model\n        \"\"\"\n        return self.eos\n\n    @jit.to_static\n    def forward_encoder_chunk(\n            self,\n            xs: paddle.Tensor,\n            offset: int,\n            required_cache_size: int,\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\" Export interface for c++ call, give input chunk xs, and return\n            output from time 0 to current chunk.\n\n        Args:\n            xs (paddle.Tensor): chunk input, with shape (b=1, time, mel-dim),\n                where `time == (chunk_size - 1) * subsample_rate + \\\n                        subsample.right_context + 1`\n            offset (int): current offset in encoder output time stamp\n            required_cache_size (int): cache size required for next chunk\n                compuation\n                >=0: actual cache size\n                <0: means all history cache is required\n            att_cache (paddle.Tensor): cache tensor for KEY & VALUE in\n                transformer/conformer attention, with shape\n                (elayers, head, cache_t1, d_k * 2), where\n                `head * d_k == hidden-dim` and\n                `cache_t1 == chunk_size * num_decoding_left_chunks`.\n                `d_k * 2` for att key & value.\n            cnn_cache (paddle.Tensor): cache tensor for cnn_module in conformer,\n                (elayers, b=1, hidden-dim, cache_t2), where\n                `cache_t2 == cnn.lorder - 1`\n\n        Returns:\n            paddle.Tensor: output of current input xs,\n                with shape (b=1, chunk_size, hidden-dim).\n            paddle.Tensor: new attention cache required for next chunk, with\n                dynamic shape (elayers, head, T(?), d_k * 2)\n                depending on required_cache_size.\n            paddle.Tensor: new conformer cnn cache required for next chunk, with\n                same shape as the original cnn_cache.\n        \"\"\"\n        return self.encoder.forward_chunk(xs, offset, required_cache_size,\n                                          att_cache, cnn_cache)\n\n    # @jit.to_static\n    def ctc_activation(self, xs: paddle.Tensor) -> paddle.Tensor:\n        \"\"\" Export interface for c++ call, apply linear transform and log\n            softmax before ctc\n        Args:\n            xs (paddle.Tensor): encoder output\n        Returns:\n            paddle.Tensor: activation before ctc\n        \"\"\"\n        return self.ctc.log_softmax(xs)\n\n    @jit.to_static\n    def forward_attention_decoder(\n            self,\n            hyps: paddle.Tensor,\n            hyps_lens: paddle.Tensor,\n            encoder_out: paddle.Tensor, ) -> paddle.Tensor:\n        \"\"\" Export interface for c++ call, forward decoder with multiple\n            hypothesis from ctc prefix beam search and one encoder output\n        Args:\n            hyps (paddle.Tensor): hyps from ctc prefix beam search, already\n                pad sos at the beginning, (B, T)\n            hyps_lens (paddle.Tensor): length of each hyp in hyps, (B)\n            encoder_out (paddle.Tensor): corresponding encoder output, (B=1, T, D)\n        Returns:\n            paddle.Tensor: decoder output, (B, L)\n        \"\"\"\n        assert encoder_out.shape[0] == 1\n        num_hyps = hyps.shape[0]\n        assert hyps_lens.shape[0] == num_hyps\n        encoder_out = encoder_out.repeat(num_hyps, 1, 1)\n        # (B, 1, T)\n        encoder_mask = paddle.ones(\n            [num_hyps, 1, encoder_out.shape[1]], dtype=paddle.bool)\n        # (num_hyps, max_hyps_len, vocab_size)\n        decoder_out, _ = self.decoder(encoder_out, encoder_mask, hyps,\n                                      hyps_lens)\n        decoder_out = paddle.nn.functional.log_softmax(decoder_out, dim=-1)\n        return decoder_out\n\n    @paddle.no_grad()\n    def decode(self,\n               feats: paddle.Tensor,\n               feats_lengths: paddle.Tensor,\n               text_feature: Dict[str, int],\n               decoding_method: str,\n               beam_size: int,\n               word_reward: float=0.0,\n               maxlenratio: float=0.5,\n               decoding_chunk_size: int=-1,\n               num_decoding_left_chunks: int=-1,\n               simulate_streaming: bool=False):\n        \"\"\"u2 decoding.\n\n        Args:\n            feats (Tensor): audio features, (B, T, D)\n            feats_lengths (Tensor): (B)\n            text_feature (TextFeaturizer): text feature object.\n            decoding_method (str): decoding mode, e.g.\n                    'fullsentence',\n                    'simultaneous'\n            beam_size (int): beam size for search\n            decoding_chunk_size (int, optional): decoding chunk size. Defaults to -1.\n                    <0: for decoding, use full chunk.\n                    >0: for decoding, use fixed chunk size as set.\n                    0: used for training, it's prohibited here.\n            num_decoding_left_chunks (int, optional):\n                    number of left chunks for decoding. Defaults to -1.\n            simulate_streaming (bool, optional): simulate streaming inference. Defaults to False.\n\n        Raises:\n            ValueError: when not support decoding_method.\n\n        Returns:\n            List[List[int]]: transcripts.\n        \"\"\"\n        batch_size = feats.shape[0]\n\n        if decoding_method == 'fullsentence':\n            hyps = self.translate(\n                feats,\n                feats_lengths,\n                beam_size=beam_size,\n                word_reward=word_reward,\n                maxlenratio=maxlenratio,\n                decoding_chunk_size=decoding_chunk_size,\n                num_decoding_left_chunks=num_decoding_left_chunks,\n                simulate_streaming=simulate_streaming)\n            hyps = [hyp.tolist() for hyp in hyps]\n        else:\n            raise ValueError(f\"Not support decoding method: {decoding_method}\")\n\n        res = [text_feature.defeaturize(hyp) for hyp in hyps]\n        return res\n\n\nclass U2STModel(U2STBaseModel):\n    def __init__(self, configs: dict):\n        vocab_size, encoder, decoder = U2STModel._init_from_config(configs)\n\n        if isinstance(decoder, Tuple):\n            st_decoder, asr_decoder, ctc = decoder\n            super().__init__(\n                vocab_size=vocab_size,\n                encoder=encoder,\n                st_decoder=st_decoder,\n                decoder=asr_decoder,\n                ctc=ctc,\n                **configs['model_conf'])\n        else:\n            super().__init__(\n                vocab_size=vocab_size,\n                encoder=encoder,\n                st_decoder=decoder,\n                **configs['model_conf'])\n\n    @classmethod\n    def _init_from_config(cls, configs: dict):\n        \"\"\"init sub module for model.\n\n        Args:\n            configs (dict): config dict.\n\n        Raises:\n            ValueError: raise when using not support encoder type.\n\n        Returns:\n            int, nn.Layer, nn.Layer, nn.Layer: vocab size, encoder, decoder, ctc\n        \"\"\"\n        if configs['cmvn_file'] is not None:\n            mean, istd = load_cmvn(configs['cmvn_file'],\n                                   configs['cmvn_file_type'])\n            global_cmvn = GlobalCMVN(\n                paddle.to_tensor(mean, dtype=paddle.float),\n                paddle.to_tensor(istd, dtype=paddle.float))\n        else:\n            global_cmvn = None\n\n        input_dim = configs['input_dim']\n        vocab_size = configs['output_dim']\n        assert input_dim != 0, input_dim\n        assert vocab_size != 0, vocab_size\n\n        encoder_type = configs.get('encoder', 'transformer')\n        logger.info(f\"U2 Encoder type: {encoder_type}\")\n        if encoder_type == 'transformer':\n            encoder = TransformerEncoder(\n                input_dim, global_cmvn=global_cmvn, **configs['encoder_conf'])\n        elif encoder_type == 'conformer':\n            encoder = ConformerEncoder(\n                input_dim, global_cmvn=global_cmvn, **configs['encoder_conf'])\n        else:\n            raise ValueError(f\"not support encoder type:{encoder_type}\")\n\n        st_decoder = TransformerDecoder(vocab_size,\n                                        encoder.output_size(),\n                                        **configs['decoder_conf'])\n\n        asr_weight = configs['model_conf']['asr_weight']\n        logger.info(f\"ASR Joint Training Weight: {asr_weight}\")\n\n        if asr_weight > 0.:\n            decoder = TransformerDecoder(vocab_size,\n                                         encoder.output_size(),\n                                         **configs['decoder_conf'])\n            # ctc decoder and ctc loss\n            model_conf = configs['model_conf']\n            dropout_rate = model_conf.get('ctc_dropout_rate', 0.0)\n            grad_norm_type = model_conf.get('ctc_grad_norm_type', None)\n            ctc = CTCDecoderBase(\n                odim=vocab_size,\n                enc_n_units=encoder.output_size(),\n                blank_id=0,\n                dropout_rate=dropout_rate,\n                reduction=True,  # sum\n                batch_average=True,  # sum / batch_size\n                grad_norm_type=grad_norm_type)\n\n            return vocab_size, encoder, (st_decoder, decoder, ctc)\n        else:\n            return vocab_size, encoder, st_decoder\n\n    @classmethod\n    def from_config(cls, configs: dict):\n        \"\"\"init model.\n\n        Args:\n            configs (dict): config dict.\n\n        Raises:\n            ValueError: raise when using not support encoder type.\n\n        Returns:\n            nn.Layer: U2STModel\n        \"\"\"\n        model = cls(configs)\n        return model\n\n    @classmethod\n    def from_pretrained(cls, dataloader, config, checkpoint_path):\n        \"\"\"Build a DeepSpeech2Model model from a pretrained model.\n\n        Args:\n            dataloader (paddle.io.DataLoader): not used.\n            config (yacs.config.CfgNode):  model configs\n            checkpoint_path (Path or str): the path of pretrained model checkpoint, without extension name\n\n        Returns:\n            DeepSpeech2Model: The model built from pretrained result.\n        \"\"\"\n        with UpdateConfig(config):\n            config.input_dim = dataloader.collate_fn.feature_size\n            config.output_dim = dataloader.collate_fn.vocab_size\n\n        model = cls.from_config(config)\n\n        if checkpoint_path:\n            infos = checkpoint.load_parameters(\n                model, checkpoint_path=checkpoint_path)\n            logger.info(f\"checkpoint info: {infos}\")\n        layer_tools.summary(model)\n        return model\n\n\nclass U2STInferModel(U2STModel):\n    def __init__(self, configs: dict):\n        super().__init__(configs)\n\n    def forward(self,\n                feats,\n                feats_lengths,\n                decoding_chunk_size=-1,\n                num_decoding_left_chunks=-1,\n                simulate_streaming=False):\n        \"\"\"export model function\n\n        Args:\n            feats (Tensor): [B, T, D]\n            feats_lengths (Tensor): [B]\n\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        return self.translate(\n            feats,\n            feats_lengths,\n            decoding_chunk_size=decoding_chunk_size,\n            num_decoding_left_chunks=num_decoding_left_chunks,\n            simulate_streaming=simulate_streaming)\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .wav2vec2_ASR import Wav2vec2ASR\nfrom .wav2vec2_ASR import Wav2vec2Base\n\n__all__ = [\"Wav2vec2ASR\", \"Wav2vec2Base\"]\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/VanillaNN.py",
    "content": "# Authors\n# * Elena Rastorgueva 2020\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/lobes/models/VanillaNN.py).\nimport paddle\n\nfrom paddlespeech.s2t.models.wav2vec2.modules import containers\nfrom paddlespeech.s2t.models.wav2vec2.modules import linear\nfrom paddlespeech.s2t.models.wav2vec2.modules.normalization import BatchNorm1d\n\n\nclass VanillaNN(containers.Sequential):\n    \"\"\"A simple vanilla Deep Neural Network.\n    Arguments\n    ---------\n    activation : paddle class\n        A class used for constructing the activation layers.\n    dnn_blocks : int\n        The number of linear neural blocks to include.\n    dnn_neurons : int\n        The number of neurons in the linear layers.\n    Example\n    -------\n    >>> inputs = paddle.rand([10, 120, 60])\n    >>> model = VanillaNN(input_shape=inputs.shape)\n    >>> outputs = model(inputs)\n    >>> outputs.shape\n    paddle.shape([10, 120, 512])\n    \"\"\"\n\n    def __init__(self,\n                 input_shape,\n                 dnn_blocks=2,\n                 dnn_neurons=512,\n                 activation=True,\n                 normalization=False,\n                 dropout_rate=0.5):\n        super().__init__(input_shape=[None, None, input_shape])\n\n        if not isinstance(dropout_rate, list):\n            dropout_rate = [dropout_rate] * dnn_blocks\n        else:\n            assert len(\n                dropout_rate\n            ) == dnn_blocks, \"len(dropout_rate) must equal to dnn_blocks\"\n\n        for block_index in range(dnn_blocks):\n            self.append(\n                linear.Linear,\n                n_neurons=dnn_neurons,\n                bias_attr=None,\n                layer_name=\"linear\", )\n            if normalization:\n                self.append(\n                    BatchNorm1d, input_size=dnn_neurons, layer_name='bn')\n            if activation:\n                self.append(paddle.nn.LeakyReLU(), layer_name=\"act\")\n            self.append(\n                paddle.nn.Dropout(p=dropout_rate[block_index]),\n                layer_name='dropout')\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/activations.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2020 The HuggingFace Team. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nfrom paddle import nn\nfrom paddle import Tensor\n\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n\nclass NewGELUActivation(nn.Layer):\n    \"\"\"\n    Implementation of the GELU activation function currently in Google BERT repo (identical to OpenAI GPT). Also see\n    the Gaussian Error Linear Units paper: https://arxiv.org/abs/1606.08415\n    \"\"\"\n\n    def forward(self, input: Tensor) -> Tensor:\n        return 0.5 * input * (1.0 + paddle.tanh(\n            math.sqrt(2.0 / math.pi) *\n            (input + 0.044715 * paddle.pow(input, 3.0))))\n\n\nclass GELUActivation(nn.Layer):\n    \"\"\"\n    Original Implementation of the GELU activation function in Google BERT repo when initially created. For\n    information: OpenAI GPT's GELU is slightly different (and gives slightly different results): 0.5 * x * (1 +\n    paddle.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * paddle.pow(x, 3)))) This is now written in C in nn.functional\n    Also see the Gaussian Error Linear Units paper: https://arxiv.org/abs/1606.08415\n    \"\"\"\n\n    def __init__(self, use_gelu_python: bool=False):\n        super().__init__()\n        self.act = nn.functional.gelu\n\n    def _gelu_python(self, input: Tensor) -> Tensor:\n        return input * 0.5 * (1.0 + paddle.erf(input / math.sqrt(2.0)))\n\n    def forward(self, input: Tensor) -> Tensor:\n        return self.act(input)\n\n\nclass FastGELUActivation(nn.Layer):\n    \"\"\"\n    Applies GELU approximation that is slower than QuickGELU but more accurate. See: https://github.com/hendrycks/GELUs\n    \"\"\"\n\n    def forward(self, input: Tensor) -> Tensor:\n        return 0.5 * input * (\n            1.0 + paddle.tanh(input * 0.7978845608 *\n                              (1.0 + 0.044715 * input * input)))\n\n\nclass QuickGELUActivation(nn.Layer):\n    \"\"\"\n    Applies GELU approximation that is fast but somewhat inaccurate. See: https://github.com/hendrycks/GELUs\n    \"\"\"\n\n    def forward(self, input: Tensor) -> Tensor:\n        return input * paddle.sigmoid(1.702 * input)\n\n\nclass ClippedGELUActivation(nn.Layer):\n    \"\"\"\n    Clip the range of possible GeLU outputs between [min, max]. This is especially useful for quantization purpose, as\n    it allows mapping negatives values in the GeLU spectrum. For more information on this trick, please refer to\n    https://arxiv.org/abs/2004.09602.\n\n    Gaussian Error Linear Unit. Original Implementation of the gelu activation function in Google Bert repo when\n    initially created.\n\n    For information: OpenAI GPT's gelu is slightly different (and gives slightly different results): 0.5 * x * (1 +\n    paddle.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * paddle.pow(x, 3)))). See https://arxiv.org/abs/1606.08415\n    \"\"\"\n\n    def __init__(self, min: float, max: float):\n        if min > max:\n            raise ValueError(\n                f\"min should be < max (got min: {min}, max: {max})\")\n\n        super().__init__()\n        self.min = min\n        self.max = max\n\n    def forward(self, x: Tensor) -> Tensor:\n        return paddle.clip(gelu(x), self.min, self.max)\n\n\nclass SiLUActivation(nn.Layer):\n    \"\"\"\n    See Gaussian Error Linear Units (Hendrycks et al., https://arxiv.org/abs/1606.08415) where the SiLU (Sigmoid Linear\n    Unit) was originally introduced and coined, and see Sigmoid-Weighted Linear Units for Neural Network Function\n    Approximation in Reinforcement Learning (Elfwing et al., https://arxiv.org/abs/1702.03118) and Swish: a Self-Gated\n    Activation Function (Ramachandran et al., https://arxiv.org/abs/1710.05941v1) where the SiLU was experimented with\n    later.\n    \"\"\"\n\n    def __init__(self):\n        super().__init__()\n        self.act = nn.functional.silu\n\n    def _silu_python(self, input: Tensor) -> Tensor:\n        return input * paddle.sigmoid(input)\n\n    def forward(self, input: Tensor) -> Tensor:\n        return self.act(input)\n\n\nclass MishActivation(nn.Layer):\n    \"\"\"\n    See Mish: A Self-Regularized Non-Monotonic Activation Function (Misra., https://arxiv.org/abs/1908.08681). Also\n    visit the official repository for the paper: https://github.com/digantamisra98/Mish\n    \"\"\"\n\n    def __init__(self):\n        super().__init__()\n        self.act = nn.functional.mish\n\n    def _mish_python(self, input: Tensor) -> Tensor:\n        return input * paddle.tanh(nn.functional.softplus(input))\n\n    def forward(self, input: Tensor) -> Tensor:\n        return self.act(input)\n\n\nclass LinearActivation(nn.Layer):\n    \"\"\"\n    Applies the linear activation function, i.e. forwarding input directly to output.\n    \"\"\"\n\n    def forward(self, input: Tensor) -> Tensor:\n        return input\n\n\nACT2FN = {\n    \"gelu\": GELUActivation(),\n    \"gelu_10\": ClippedGELUActivation(-10, 10),\n    \"gelu_fast\": FastGELUActivation(),\n    \"gelu_new\": NewGELUActivation(),\n    \"gelu_python\": GELUActivation(use_gelu_python=True),\n    \"linear\": LinearActivation(),\n    \"mish\": MishActivation(),\n    \"quick_gelu\": QuickGELUActivation(),\n    \"relu\": nn.ReLU(),\n    \"sigmoid\": nn.Sigmoid(),\n    \"silu\": SiLUActivation(),\n    \"swish\": SiLUActivation(),\n    \"tanh\": nn.Tanh(),\n}\n\n\ndef get_activation(activation_string):\n    if activation_string in ACT2FN:\n        return ACT2FN[activation_string]\n    else:\n        raise KeyError(\n            f\"function {activation_string} not found in ACT2FN mapping {list(ACT2FN.keys())}\"\n        )\n\n\n# For backwards compatibility with: from activations import gelu_python\ngelu_python = get_activation(\"gelu_python\")\ngelu_new = get_activation(\"gelu_new\")\ngelu = get_activation(\"gelu\")\ngelu_fast = get_activation(\"gelu_fast\")\nquick_gelu = get_activation(\"quick_gelu\")\nsilu = get_activation(\"silu\")\nmish = get_activation(\"mish\")\nlinear_act = get_activation(\"linear\")\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/containers.py",
    "content": "# Authors\n#  * Peter Plantinga 2020\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/nnet/containers.py).\nimport inspect\n\nimport paddle\n\n\nclass Sequential(paddle.nn.LayerDict):\n    \"\"\"A sequence of modules with potentially inferring shape on construction.\n    If layers are passed with names, these can be referenced with dot notation.\n    Arguments\n    ---------\n    input_shape : iterable\n        A list or tuple of ints or None, representing the expected shape of an\n        input tensor. None represents a variable-length dimension. If no\n        ``input_shape`` is passed, no shape inference will be performed.\n    *layers, **named_layers\n        The inputs are treated as a list of layers to be\n        applied in sequence. The output shape of each layer is used to\n        infer the shape of the following layer. If a tuple is returned,\n        only the shape of the first element is used to determine input\n        shape of the next layer (e.g. RNN returns output, hidden).\n    Example\n    -------\n    >>> inputs = paddle.rand(10, 40, 50)\n    >>> model = Sequential(input_shape=inputs.shape)\n    >>> model.append(Linear, n_neurons=100, layer_name=\"layer1\")\n    >>> model.append(Linear, n_neurons=200, layer_name=\"layer2\")\n    >>> outputs = model(inputs)\n    >>> outputs.shape\n    paddle.shape([10, 40, 200])\n    >>> outputs = model.layer1(inputs)\n    >>> outputs.shape\n    paddle.shape([10, 40, 100])\n    \"\"\"\n\n    def __init__(self, *layers, input_shape=None, **named_layers):\n        super().__init__()\n\n        # Make sure either layers or input_shape is passed\n        if not layers and input_shape is None and not named_layers:\n            raise ValueError(\"Must pass either layers or input shape\")\n\n        # Keep track of what layers need \"lengths\" passed\n        self.length_layers = []\n\n        # Replace None dimensions with arbitrary value\n        self.input_shape = input_shape\n        if input_shape and None in input_shape:\n            self.input_shape = list(input_shape)\n            for i, dim in enumerate(self.input_shape):\n\n                # To reduce size of dummy tensors, use 1 for batch dim\n                if i == 0 and dim is None:\n                    dim = 1\n\n                # Use 64 as nice round arbitrary value, big enough that\n                # halving this dimension a few times doesn't reach 1\n                self.input_shape[i] = dim or 256\n\n        # Append non-named layers\n        for layer in layers:\n            self.append(layer)\n\n        # Append named layers\n        for name, layer in named_layers.items():\n            self.append(layer, layer_name=name)\n\n    def append(self, layer, *args, layer_name=None, **kwargs):\n        \"\"\"Add a layer to the list of layers, inferring shape if necessary.\n        Arguments\n        ---------\n        layer : A paddle.nn.Module class or object\n            If the layer is a class, it should accept an argument called\n            ``input_shape`` which will be inferred and passed. If the layer\n            is a module object, it is added as-is.\n        layer_name : str\n            The name of the layer, for reference. If the name is in use,\n            ``_{count}`` will be appended.\n        *args, **kwargs\n            These are passed to the layer if it is constructed.\n        \"\"\"\n\n        # Compute layer_name\n        if layer_name is None:\n            layer_name = str(len(self))\n        elif layer_name in self:\n            index = 0\n            while f\"{layer_name}_{index}\" in self:\n                index += 1\n            layer_name = f\"{layer_name}_{index}\"\n        # Check if it needs to be constructed with input shape\n        if self.input_shape:\n            argspec = inspect.getfullargspec(layer)\n            if \"input_shape\" in argspec.args + argspec.kwonlyargs:\n                input_shape = self.get_output_shape()\n                layer = layer(*args, input_shape=input_shape, **kwargs)\n\n        # Finally, append the layer.\n        try:\n            self[layer_name] = layer\n        # self.add_module(layer_name, layer)\n        except TypeError:\n            raise ValueError(\n                \"Must pass `input_shape` at initialization and use \"\n                \"modules that take `input_shape` to infer shape when \"\n                \"using `append()`.\")\n\n    def get_output_shape(self):\n        \"\"\"Returns expected shape of the output.\n        Computed by passing dummy input constructed with the\n        ``self.input_shape`` attribute.\n        \"\"\"\n        with paddle.no_grad():\n            dummy_input = paddle.zeros(self.input_shape)\n            dummy_output = self(dummy_input)\n        return dummy_output.shape\n\n    def forward(self, x):\n        \"\"\"Applies layers in sequence, passing only the first element of tuples.\n        Arguments\n        ---------\n        x : paddle.Tensor\n            The input tensor to run through the network.\n        \"\"\"\n        for layer in self.values():\n            x = layer(x)\n            if isinstance(x, tuple):\n                x = x[0]\n        return x\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/linear.py",
    "content": "# Authors\n#  * Mirco Ravanelli 2020\n#  * Davide Borra 2021\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/nnet/linear.py).\nimport logging\n\nimport paddle\n\nfrom paddlespeech.s2t.modules import align\n\nlogger = logging.getLogger(__name__)\n\n\nclass Linear(paddle.nn.Layer):\n    \"\"\"Computes a linear transformation y = wx + b.\n    Arguments\n    ---------\n    n_neurons : int\n        It is the number of output neurons (i.e, the dimensionality of the\n        output).\n    input_shape: tuple\n        It is the shape of the input tensor.\n    input_size: int\n        Size of the input tensor.\n    bias : bool\n        If True, the additive bias b is adopted.\n    combine_dims : bool\n        If True and the input is 4D, combine 3rd and 4th dimensions of input.\n    Example\n    -------\n    >>> inputs = paddle.rand(10, 50, 40)\n    >>> lin_t = Linear(input_shape=(10, 50, 40), n_neurons=100)\n    >>> output = lin_t(inputs)\n    >>> output.shape\n    paddle.shape([10, 50, 100])\n    \"\"\"\n\n    def __init__(\n            self,\n            n_neurons,\n            input_shape=None,\n            input_size=None,\n            bias_attr=None,\n            combine_dims=False, ):\n        super().__init__()\n        self.combine_dims = combine_dims\n\n        if input_shape is None and input_size is None:\n            raise ValueError(\"Expected one of input_shape or input_size\")\n\n        if input_size is None:\n            input_size = input_shape[-1]\n            if len(input_shape) == 4 and self.combine_dims:\n                input_size = input_shape[2] * input_shape[3]\n\n        # Weights are initialized following paddle approach\n        self.w = align.Linear(input_size, n_neurons, bias_attr=bias_attr)\n\n    def forward(self, x):\n        \"\"\"Returns the linear transformation of input tensor.\n        Arguments\n        ---------\n        x : paddle.Tensor\n            Input to transform linearly.\n        \"\"\"\n        if x.rank == 4 and self.combine_dims:\n            x = x.reshape(x.shape[0], x.shape[1], x.shape[2] * x.shape[3])\n\n        wx = self.w(x)\n\n        return wx\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/modeling_outputs.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2020 The HuggingFace Team. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import OrderedDict\nfrom dataclasses import dataclass\nfrom dataclasses import fields\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\n\n\nclass ModelOutput(OrderedDict):\n    \"\"\"\n    Base class for all model outputs as dataclass. Has a `__getitem__` that allows indexing by integer or slice (like a\n    tuple) or strings (like a dictionary) that will ignore the `None` attributes. Otherwise behaves like a regular\n    python dictionary.\n\n    <Tip warning={true}>\n\n    You can't unpack a `ModelOutput` directly. Use the [`~utils.ModelOutput.to_tuple`] method to convert it to a tuple\n    before.\n\n    </Tip>\n    \"\"\"\n\n    def __post_init__(self):\n        class_fields = fields(self)\n\n        # Safety and consistency checks\n        if not len(class_fields):\n            raise ValueError(f\"{self.__class__.__name__} has no fields.\")\n        if not all(field.default is None for field in class_fields[1:]):\n            raise ValueError(\n                f\"{self.__class__.__name__} should not have more than one required field.\"\n            )\n\n        first_field = getattr(self, class_fields[0].name)\n        other_fields_are_none = all(\n            getattr(self, field.name) is None for field in class_fields[1:])\n\n        if other_fields_are_none and not paddle.is_tensor(first_field):\n            if isinstance(first_field, dict):\n                iterator = first_field.items()\n                first_field_iterator = True\n            else:\n                try:\n                    iterator = iter(first_field)\n                    first_field_iterator = True\n                except TypeError:\n                    first_field_iterator = False\n\n            # if we provided an iterator as first field and the iterator is a (key, value) iterator\n            # set the associated fields\n            if first_field_iterator:\n                for element in iterator:\n                    if (not isinstance(element, (list, tuple)) or\n                            not len(element) == 2 or\n                            not isinstance(element[0], str)):\n                        break\n                    setattr(self, element[0], element[1])\n                    if element[1] is not None:\n                        self[element[0]] = element[1]\n            elif first_field is not None:\n                self[class_fields[0].name] = first_field\n        else:\n            for field in class_fields:\n                v = getattr(self, field.name)\n                if v is not None:\n                    self[field.name] = v\n\n    def __delitem__(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``__delitem__`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def setdefault(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``setdefault`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def pop(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``pop`` on a {self.__class__.__name__} instance.\")\n\n    def update(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``update`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def __getitem__(self, k):\n        if isinstance(k, str):\n            inner_dict = {k: v for (k, v) in self.items()}\n            return inner_dict[k]\n        else:\n            return self.to_tuple()[k]\n\n    def __setattr__(self, name, value):\n        if name in self.keys() and value is not None:\n            # Don't call self.__setitem__ to avoid recursion errors\n            super().__setitem__(name, value)\n        super().__setattr__(name, value)\n\n    def __setitem__(self, key, value):\n        # Will raise a KeyException if needed\n        super().__setitem__(key, value)\n        # Don't call self.__setattr__ to avoid recursion errors\n        super().__setattr__(key, value)\n\n    def to_tuple(self) -> Tuple:\n        \"\"\"\n        Convert self to a tuple containing all the attributes/keys that are not `None`.\n        \"\"\"\n        return tuple(self[k] for k in self.keys())\n\n\n@dataclass\nclass BaseModelOutput(ModelOutput):\n    \"\"\"\n    Base class for model's outputs, with potential hidden states and attentions.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithNoAttention(ModelOutput):\n    \"\"\"\n    Base class for model's outputs, with potential hidden states.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, num_channels, height, width)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, num_channels, height, width)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n    \"\"\"\n\n    last_hidden_state: paddle = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithPooling(ModelOutput):\n    \"\"\"\n    Base class for model's outputs that also contains a pooling of the last hidden states.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        pooler_output (`paddle.Tensor` of shape `(batch_size, hidden_size)`):\n            Last layer hidden-state of the first token of the sequence (classification token) after further processing\n            through the layers used for the auxiliary pretraining task. E.g. for BERT-family of models, this returns\n            the classification token after processing through a linear layer and a tanh activation function. The linear\n            layer weights are trained from the next sentence prediction (classification) objective during pretraining.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    pooler_output: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithPoolingAndNoAttention(ModelOutput):\n    \"\"\"\n    Base class for model's outputs that also contains a pooling of the last hidden states.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, num_channels, height, width)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        pooler_output (`paddle.Tensor` of shape `(batch_size, hidden_size)`):\n            Last layer hidden-state after a pooling operation on the spatial dimensions.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, num_channels, height, width)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    pooler_output: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithPast(ModelOutput):\n    \"\"\"\n    Base class for model's outputs that may also contain a past key/values (to speed up sequential decoding).\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n\n            If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,\n            hidden_size)` is output.\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and optionally if\n            `config.is_encoder_decoder=True` 2 additional tensors of shape `(batch_size, num_heads,\n            encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if\n            `config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`\n            input) to speed up sequential decoding.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithCrossAttentions(ModelOutput):\n    \"\"\"\n    Base class for model's outputs, with potential hidden states and attentions.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithPoolingAndCrossAttentions(ModelOutput):\n    \"\"\"\n    Base class for model's outputs that also contains a pooling of the last hidden states.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        pooler_output (`paddle.Tensor` of shape `(batch_size, hidden_size)`):\n            Last layer hidden-state of the first token of the sequence (classification token) after further processing\n            through the layers used for the auxiliary pretraining task. E.g. for BERT-family of models, this returns\n            the classification token after processing through a linear layer and a tanh activation function. The linear\n            layer weights are trained from the next sentence prediction (classification) objective during pretraining.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and optionally if\n            `config.is_encoder_decoder=True` 2 additional tensors of shape `(batch_size, num_heads,\n            encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if\n            `config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`\n            input) to speed up sequential decoding.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    pooler_output: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass BaseModelOutputWithPastAndCrossAttentions(ModelOutput):\n    \"\"\"\n    Base class for model's outputs that may also contain a past key/values (to speed up sequential decoding).\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n\n            If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,\n            hidden_size)` is output.\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and optionally if\n            `config.is_encoder_decoder=True` 2 additional tensors of shape `(batch_size, num_heads,\n            encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if\n            `config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`\n            input) to speed up sequential decoding.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass Seq2SeqModelOutput(ModelOutput):\n    \"\"\"\n    Base class for model encoder's outputs that also contains : pre-computed hidden states that can speed up sequential\n    decoding.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the decoder of the model.\n\n            If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,\n            hidden_size)` is output.\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape\n            `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention\n            blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.\n        decoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the decoder at the output of each layer plus the optional initial embedding outputs.\n        decoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n        encoder_last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):\n            Sequence of hidden-states at the output of the last layer of the encoder of the model.\n        encoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the encoder at the output of each layer plus the optional initial embedding outputs.\n        encoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    decoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    decoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n    encoder_last_hidden_state: Optional[paddle.Tensor] = None\n    encoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    encoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass CausalLMOutput(ModelOutput):\n    \"\"\"\n    Base class for causal language model (or autoregressive) outputs.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Language modeling loss (for next-token prediction).\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.vocab_size)`):\n            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass CausalLMOutputWithPast(ModelOutput):\n    \"\"\"\n    Base class for causal language model (or autoregressive) outputs.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Language modeling loss (for next-token prediction).\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.vocab_size)`):\n            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`)\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see\n            `past_key_values` input) to speed up sequential decoding.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass CausalLMOutputWithCrossAttentions(ModelOutput):\n    \"\"\"\n    Base class for causal language model (or autoregressive) outputs.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Language modeling loss (for next-token prediction).\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.vocab_size)`):\n            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Cross attentions weights after the attention softmax, used to compute the weighted average in the\n            cross-attention heads.\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `paddle.Tensor` tuples of length `config.n_layers`, with each tuple containing the cached key,\n            value states of the self-attention and the cross-attention layers if model is used in encoder-decoder\n            setting. Only relevant if `config.is_decoder = True`.\n\n            Contains pre-computed hidden-states (key and values in the attention blocks) that can be used (see\n            `past_key_values` input) to speed up sequential decoding.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass SequenceClassifierOutputWithPast(ModelOutput):\n    \"\"\"\n    Base class for outputs of sentence classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels)`):\n            Classification (or regression if config.num_labels==1) scores (before SoftMax).\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`)\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see\n            `past_key_values` input) to speed up sequential decoding.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass MaskedLMOutput(ModelOutput):\n    \"\"\"\n    Base class for masked language models outputs.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Masked language modeling (MLM) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.vocab_size)`):\n            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass Seq2SeqLMOutput(ModelOutput):\n    \"\"\"\n    Base class for sequence-to-sequence language models outputs.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Language modeling loss.\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.vocab_size)`):\n            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape\n            `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention\n            blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.\n        decoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.\n        decoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n        encoder_last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):\n            Sequence of hidden-states at the output of the last layer of the encoder of the model.\n        encoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.\n        encoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    decoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    decoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n    encoder_last_hidden_state: Optional[paddle.Tensor] = None\n    encoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    encoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass NextSentencePredictorOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of models predicting if two sentences are consecutive or not.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `next_sentence_label` is provided):\n            Next sequence prediction (classification) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, 2)`):\n            Prediction scores of the next sequence prediction (classification) head (scores of True/False continuation\n            before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass SequenceClassifierOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of sentence classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels)`):\n            Classification (or regression if config.num_labels==1) scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass Seq2SeqSequenceClassifierOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of sequence-to-sequence sentence classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `label` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels)`):\n            Classification (or regression if config.num_labels==1) scores (before SoftMax).\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape\n            `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention\n            blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.\n        decoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.\n        decoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n        encoder_last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):\n            Sequence of hidden-states at the output of the last layer of the encoder of the model.\n        encoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.\n        encoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    decoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    decoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n    encoder_last_hidden_state: Optional[paddle.Tensor] = None\n    encoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    encoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass MultipleChoiceModelOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of multiple choice models.\n\n    Args:\n        loss (`paddle.Tensor` of shape *(1,)*, *optional*, returned when `labels` is provided):\n            Classification loss.\n        logits (`paddle.Tensor` of shape `(batch_size, num_choices)`):\n            *num_choices* is the second dimension of the input tensors. (see *input_ids* above).\n\n            Classification scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass TokenClassifierOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of token classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided) :\n            Classification loss.\n        logits (`paddle.Tensor` of shape `(batch_size, sequence_length, config.num_labels)`):\n            Classification scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass QuestionAnsweringModelOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of question answering models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Total span extraction loss is the sum of a Cross-Entropy for the start and end positions.\n        start_logits (`paddle.Tensor` of shape `(batch_size, sequence_length)`):\n            Span-start scores (before SoftMax).\n        end_logits (`paddle.Tensor` of shape `(batch_size, sequence_length)`):\n            Span-end scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    start_logits: paddle.Tensor = None\n    end_logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass Seq2SeqQuestionAnsweringModelOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of sequence-to-sequence question answering models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Total span extraction loss is the sum of a Cross-Entropy for the start and end positions.\n        start_logits (`paddle.Tensor` of shape `(batch_size, sequence_length)`):\n            Span-start scores (before SoftMax).\n        end_logits (`paddle.Tensor` of shape `(batch_size, sequence_length)`):\n            Span-end scores (before SoftMax).\n        past_key_values (`tuple(tuple(paddle.Tensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):\n            Tuple of `tuple(paddle.Tensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape\n            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape\n            `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.\n\n            Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention\n            blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.\n        decoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.\n        decoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n        cross_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the\n            weighted average in the cross-attention heads.\n        encoder_last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):\n            Sequence of hidden-states at the output of the last layer of the encoder of the model.\n        encoder_hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.\n        encoder_attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the\n            self-attention heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    start_logits: paddle.Tensor = None\n    end_logits: paddle.Tensor = None\n    past_key_values: Optional[Tuple[Tuple[paddle.Tensor]]] = None\n    decoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    decoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n    cross_attentions: Optional[Tuple[paddle.Tensor]] = None\n    encoder_last_hidden_state: Optional[paddle.Tensor] = None\n    encoder_hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    encoder_attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass SemanticSegmenterOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of semantic segmentation models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels, logits_height, logits_width)`):\n            Classification scores for each pixel.\n\n            <Tip warning={true}>\n\n            The logits returned do not necessarily have the same size as the `pixel_values` passed as inputs. This is\n            to avoid doing two interpolations and lose some quality when a user needs to resize the logits to the\n            original image size as post-processing. You should always check your logits shape and resize as needed.\n\n            </Tip>\n\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, patch_size, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, patch_size,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass ImageClassifierOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of image classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels)`):\n            Classification (or regression if config.num_labels==1) scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each stage) of shape `(batch_size, sequence_length, hidden_size)`. Hidden-states\n            (also called feature maps) of the model at the output of each stage.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, patch_size,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass ImageClassifierOutputWithNoAttention(ModelOutput):\n    \"\"\"\n    Base class for outputs of image classification models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.num_labels)`):\n            Classification (or regression if config.num_labels==1) scores (before SoftMax).\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each stage) of shape `(batch_size, num_channels, height, width)`. Hidden-states (also\n            called feature maps) of the model at the output of each stage.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass DepthEstimatorOutput(ModelOutput):\n    \"\"\"\n    Base class for outputs of depth estimation models.\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification (or regression if config.num_labels==1) loss.\n        predicted_depth (`paddle.Tensor` of shape `(batch_size, height, width)`):\n            Predicted depth for each pixel.\n\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings, if the model has an embedding layer, +\n            one for the output of each layer) of shape `(batch_size, num_channels, height, width)`.\n\n            Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, patch_size,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    predicted_depth: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass Wav2Vec2BaseModelOutput(ModelOutput):\n    \"\"\"\n    Base class for models that have been trained with the Wav2Vec2 loss objective.\n\n    Args:\n        last_hidden_state (`paddle.Tensor` of shape `(batch_size, sequence_length, hidden_size)`):\n            Sequence of hidden-states at the output of the last layer of the model.\n        extract_features (`paddle.Tensor` of shape `(batch_size, sequence_length, conv_dim[-1])`):\n            Sequence of extracted feature vectors of the last convolutional layer of the model.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings + one for the output of each layer) of\n            shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    last_hidden_state: paddle.Tensor = None\n    extract_features: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n\n\n@dataclass\nclass XVectorOutput(ModelOutput):\n    \"\"\"\n    Output type of [`Wav2Vec2ForXVector`].\n\n    Args:\n        loss (`paddle.Tensor` of shape `(1,)`, *optional*, returned when `labels` is provided):\n            Classification loss.\n        logits (`paddle.Tensor` of shape `(batch_size, config.xvector_output_dim)`):\n            Classification hidden states before AMSoftmax.\n        embeddings (`paddle.Tensor` of shape `(batch_size, config.xvector_output_dim)`):\n            Utterance embeddings used for vector similarity-based retrieval.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings + one for the output of each layer) of\n            shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    logits: paddle.Tensor = None\n    embeddings: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/modeling_wav2vec2.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2021 The Fairseq Authors and the HuggingFace Inc. team. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Paddle Wav2Vec2 model.\"\"\"\nfrom dataclasses import dataclass\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.models.wav2vec2.modules.activations import ACT2FN\nfrom paddlespeech.s2t.models.wav2vec2.modules.modeling_outputs import BaseModelOutput\nfrom paddlespeech.s2t.models.wav2vec2.modules.modeling_outputs import ModelOutput\nfrom paddlespeech.s2t.models.wav2vec2.modules.modeling_outputs import Wav2Vec2BaseModelOutput\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n\n@dataclass\nclass Wav2Vec2ForPreTrainingOutput(ModelOutput):\n    \"\"\"\n    Output type of [`Wav2Vec2ForPreTraining`], with potential hidden states and attentions.\n\n    Args:\n        loss (*optional*, returned when `sample_negative_indices` are passed, `paddle.Tensor` of shape `(1,)`):\n            Total loss as the sum of the contrastive loss (L_m) and the diversity loss (L_d) as stated in the [official\n            paper](https://arxiv.org/pdf/2006.11477.pdf) . (classification) loss.\n        projected_states (`paddle.Tensor` of shape `(batch_size, sequence_length, config.proj_codevector_dim)`):\n            Hidden-states of the model projected to *config.proj_codevector_dim* that can be used to predict the masked\n            projected quantized states.\n        projected_quantized_states (`paddle.Tensor` of shape `(batch_size, sequence_length, config.proj_codevector_dim)`):\n            Quantized extracted feature vectors projected to *config.proj_codevector_dim* representing the positive\n            target vectors for contrastive loss.\n        hidden_states (`tuple(paddle.Tensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):\n            Tuple of `paddle.Tensor` (one for the output of the embeddings + one for the output of each layer) of\n            shape `(batch_size, sequence_length, hidden_size)`.\n\n            Hidden-states of the model at the output of each layer plus the initial embedding outputs.\n        attentions (`tuple(paddle.Tensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):\n            Tuple of `paddle.Tensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,\n            sequence_length)`.\n\n            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention\n            heads.\n        contrastive_loss (*optional*, returned when `sample_negative_indices` are passed, `paddle.Tensor` of shape `(1,)`):\n            The contrastive loss (L_m) as stated in the [official paper](https://arxiv.org/pdf/2006.11477.pdf) .\n        diversity_loss (*optional*, returned when `sample_negative_indices` are passed, `paddle.Tensor` of shape `(1,)`):\n            The diversity loss (L_d) as stated in the [official paper](https://arxiv.org/pdf/2006.11477.pdf) .\n    \"\"\"\n\n    loss: Optional[paddle.Tensor] = None\n    projected_states: paddle.Tensor = None\n    projected_quantized_states: paddle.Tensor = None\n    codevector_perplexity: paddle.Tensor = None\n    hidden_states: Optional[Tuple[paddle.Tensor]] = None\n    attentions: Optional[Tuple[paddle.Tensor]] = None\n    contrastive_loss: Optional[paddle.Tensor] = None\n    diversity_loss: Optional[paddle.Tensor] = None\n\n\ndef _compute_mask_indices(\n        shape: Tuple[int, int],\n        mask_prob: float,\n        mask_length: int,\n        attention_mask: Optional[paddle.Tensor]=None,\n        min_masks: int=0, ) -> np.ndarray:\n    \"\"\"\n    Computes random mask spans for a given shape. Used to implement [SpecAugment: A Simple Data Augmentation Method for\n    ASR](https://arxiv.org/abs/1904.08779). Note that this method is not optimized to run on TPU and should be run on\n    CPU as part of the preprocessing during training.\n\n    Args:\n        shape: The shape for which to compute masks. This should be of a tuple of size 2 where\n               the first element is the batch size and the second element is the length of the axis to span.\n        mask_prob:  The percentage of the whole axis (between 0 and 1) which will be masked. The number of\n                    independently generated mask spans of length `mask_length` is computed by\n                    `mask_prob*shape[1]/mask_length`. Note that due to overlaps, `mask_prob` is an upper bound and the\n                    actual percentage will be smaller.\n        mask_length: size of the mask\n        min_masks: minimum number of masked spans\n        attention_mask: A (right-padded) attention mask which independently shortens the feature axis of\n                        each batch dimension.\n    \"\"\"\n    batch_size, sequence_length = shape\n\n    if mask_length < 1:\n        raise ValueError(\"`mask_length` has to be bigger than 0.\")\n\n    if mask_length > sequence_length:\n        raise ValueError(\n            f\"`mask_length` has to be smaller than `sequence_length`, but got `mask_length`: {mask_length}\"\n            f\" and `sequence_length`: {sequence_length}`\")\n\n    # epsilon is used for probabilistic rounding\n    epsilon = np.random.rand(1).item()\n\n    def compute_num_masked_span(input_length):\n        \"\"\"Given input length, compute how many spans should be masked\"\"\"\n        num_masked_span = int(mask_prob * input_length / mask_length + epsilon)\n        num_masked_span = max(num_masked_span, min_masks)\n\n        # make sure num masked span <= sequence_length\n        if num_masked_span * mask_length > sequence_length:\n            num_masked_span = sequence_length // mask_length\n\n        # make sure num_masked span is also <= input_length - (mask_length - 1)\n        if input_length - (mask_length - 1) < num_masked_span:\n            num_masked_span = max(input_length - (mask_length - 1), 0)\n\n        return num_masked_span\n\n    # compute number of masked spans in batch\n    input_lengths = (attention_mask.sum(-1).detach().tolist()\n                     if attention_mask is not None else\n                     [sequence_length for _ in range(batch_size)])\n\n    # SpecAugment mask to fill\n    spec_aug_mask = np.zeros((batch_size, sequence_length), dtype=np.bool_)\n    spec_aug_mask_idxs = []\n\n    max_num_masked_span = compute_num_masked_span(sequence_length)\n\n    if max_num_masked_span == 0:\n        return spec_aug_mask\n\n    for input_length in input_lengths:\n        # compute num of masked spans for this input\n        num_masked_span = compute_num_masked_span(input_length)\n\n        # get random indices to mask\n        spec_aug_mask_idx = np.random.choice(\n            np.arange(input_length - (mask_length - 1)),\n            num_masked_span,\n            replace=False)\n\n        # pick first sampled index that will serve as a dummy index to pad vector\n        # to ensure same dimension for all batches due to probabilistic rounding\n        # Picking first sample just pads those vectors twice.\n        if len(spec_aug_mask_idx) == 0:\n            # this case can only happen if `input_length` is strictly smaller then\n            # `sequence_length` in which case the last token has to be a padding\n            # token which we can use as a dummy mask id\n            dummy_mask_idx = sequence_length - 1\n        else:\n            dummy_mask_idx = spec_aug_mask_idx[0]\n\n        spec_aug_mask_idx = np.concatenate([\n            spec_aug_mask_idx,\n            np.ones(max_num_masked_span - num_masked_span, dtype=np.int32) *\n            dummy_mask_idx\n        ])\n        spec_aug_mask_idxs.append(spec_aug_mask_idx)\n\n    spec_aug_mask_idxs = np.array(spec_aug_mask_idxs)\n\n    # expand masked indices to masked spans\n    spec_aug_mask_idxs = np.broadcast_to(\n        spec_aug_mask_idxs[:, :, None],\n        (batch_size, max_num_masked_span, mask_length))\n    spec_aug_mask_idxs = spec_aug_mask_idxs.reshape(\n        (batch_size, max_num_masked_span * mask_length))\n\n    # add offset to the starting indexes so that indexes now create a span\n    offsets = np.arange(mask_length)[None, None, :]\n    offsets = np.broadcast_to(offsets, (\n        batch_size, max_num_masked_span, mask_length)).reshape(\n            (batch_size, max_num_masked_span * mask_length))\n    spec_aug_mask_idxs = spec_aug_mask_idxs + offsets\n\n    # ensure that we cannot have indices larger than sequence_length\n    if spec_aug_mask_idxs.max() > sequence_length - 1:\n        spec_aug_mask_idxs[spec_aug_mask_idxs >\n                           sequence_length - 1] = sequence_length - 1\n\n    # scatter indices to mask\n    np.put_along_axis(spec_aug_mask, spec_aug_mask_idxs, 1, -1)\n\n    return spec_aug_mask\n\n\ndef _sample_negative_indices(features_shape: Tuple,\n                             num_negatives: int,\n                             mask_time_indices: Optional[np.ndarray]=None):\n    \"\"\"\n    Sample `num_negatives` vectors from feature vectors.\n    \"\"\"\n    batch_size, sequence_length = features_shape\n\n    # generate indices of the positive vectors themselves, repeat them `num_negatives` times\n    sequence_length_range = np.arange(sequence_length)\n\n    # get `num_negatives` random vector indices from the same utterance\n    sampled_negative_indices = np.zeros(\n        shape=(batch_size, sequence_length, num_negatives), dtype=np.int32)\n\n    mask_time_indices = (mask_time_indices.astype(np.bool_)\n                         if mask_time_indices is not None else\n                         np.ones(features_shape, dtype=np.bool_))\n\n    for batch_idx in range(batch_size):\n        high = mask_time_indices[batch_idx].sum() - 1\n        mapped_masked_indices = sequence_length_range[mask_time_indices[\n            batch_idx]]\n\n        feature_indices = np.broadcast_to(\n            np.arange(high + 1)[:, None], (high + 1, num_negatives))\n        sampled_indices = np.random.randint(\n            0, high, size=(high + 1, num_negatives))\n        # avoid sampling the same positive vector, but keep the distribution uniform\n        sampled_indices[sampled_indices >= feature_indices] += 1\n\n        # remap to actual indices\n        sampled_negative_indices[batch_idx][mask_time_indices[\n            batch_idx]] = mapped_masked_indices[sampled_indices]\n\n        # correct for batch size\n        sampled_negative_indices[batch_idx] += batch_idx * sequence_length\n\n    return sampled_negative_indices\n\n\nclass Wav2Vec2NoLayerNormConvLayer(nn.Layer):\n    def __init__(self, config, layer_id=0):\n        super().__init__()\n        self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1\n        self.out_conv_dim = config.conv_dim[layer_id]\n\n        self.conv = nn.Conv1D(\n            self.in_conv_dim,\n            self.out_conv_dim,\n            kernel_size=config.conv_kernel[layer_id],\n            stride=config.conv_stride[layer_id],\n            bias_attr=config.conv_bias, )\n        self.activation = ACT2FN[config.feat_extract_activation]\n\n    def forward(self, hidden_states):\n        hidden_states = self.conv(hidden_states)\n        hidden_states = self.activation(hidden_states)\n        return hidden_states\n\n\nclass Wav2Vec2LayerNormConvLayer(nn.Layer):\n    def __init__(self, config, layer_id=0):\n        super().__init__()\n        self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1\n        self.out_conv_dim = config.conv_dim[layer_id]\n\n        self.conv = nn.Conv1D(\n            self.in_conv_dim,\n            self.out_conv_dim,\n            kernel_size=config.conv_kernel[layer_id],\n            stride=config.conv_stride[layer_id],\n            bias_attr=config.conv_bias, )\n        self.layer_norm = nn.LayerNorm(self.out_conv_dim)\n        self.activation = ACT2FN[config.feat_extract_activation]\n\n    def forward(self, hidden_states):\n        hidden_states = self.conv(hidden_states)\n        hidden_states = hidden_states.transpose([0, 2, 1])\n        hidden_states = self.layer_norm(hidden_states)\n        hidden_states = hidden_states.transpose([0, 2, 1])\n\n        hidden_states = self.activation(hidden_states)\n        return hidden_states\n\n\nclass Wav2Vec2GroupNormConvLayer(nn.Layer):\n    def __init__(self, config, layer_id=0):\n        super().__init__()\n        self.in_conv_dim = config.conv_dim[layer_id - 1] if layer_id > 0 else 1\n        self.out_conv_dim = config.conv_dim[layer_id]\n\n        self.conv = nn.Conv1D(\n            self.in_conv_dim,\n            self.out_conv_dim,\n            kernel_size=config.conv_kernel[layer_id],\n            stride=config.conv_stride[layer_id],\n            bias_attr=config.conv_bias, )\n        self.activation = ACT2FN[config.feat_extract_activation]\n\n        self.layer_norm = nn.GroupNorm(\n            num_groups=self.out_conv_dim, num_channels=self.out_conv_dim)\n\n    def forward(self, hidden_states):\n        hidden_states = self.conv(hidden_states)\n        hidden_states = self.layer_norm(hidden_states)\n        hidden_states = self.activation(hidden_states)\n        return hidden_states\n\n\nclass Wav2Vec2PositionalConvEmbedding(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.conv = nn.Conv1D(\n            config.hidden_size,\n            config.hidden_size,\n            kernel_size=config.num_conv_pos_embeddings,\n            padding=config.num_conv_pos_embeddings // 2,\n            groups=config.num_conv_pos_embedding_groups, )\n\n        self.conv = nn.utils.weight_norm(self.conv, name=\"weight\", dim=2)\n\n        self.padding = Wav2Vec2SamePadLayer(config.num_conv_pos_embeddings)\n        self.activation = ACT2FN[config.feat_extract_activation]\n\n    def forward(self, hidden_states):\n        hidden_states = hidden_states.transpose([0, 2, 1])\n\n        hidden_states = self.conv(hidden_states)\n        hidden_states = self.padding(hidden_states)\n        hidden_states = self.activation(hidden_states)\n\n        hidden_states = hidden_states.transpose([0, 2, 1])\n        return hidden_states\n\n\nclass Wav2Vec2SamePadLayer(nn.Layer):\n    def __init__(self, num_conv_pos_embeddings):\n        super().__init__()\n        self.num_pad_remove = 1 if num_conv_pos_embeddings % 2 == 0 else 0\n\n    def forward(self, hidden_states):\n        if self.num_pad_remove > 0:\n            hidden_states = hidden_states[:, :, :-self.num_pad_remove]\n        return hidden_states\n\n\nclass Wav2Vec2FeatureEncoder(nn.Layer):\n    \"\"\"Construct the features from raw audio waveform\"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n\n        if config.feat_extract_norm == \"group\":\n            conv_layers = [Wav2Vec2GroupNormConvLayer(config, layer_id=0)] + [\n                Wav2Vec2NoLayerNormConvLayer(config, layer_id=i + 1)\n                for i in range(config.num_feat_extract_layers - 1)\n            ]\n        elif config.feat_extract_norm == \"layer\":\n            conv_layers = [\n                Wav2Vec2LayerNormConvLayer(config, layer_id=i)\n                for i in range(config.num_feat_extract_layers)\n            ]\n        else:\n            raise ValueError(\n                f\"`config.feat_extract_norm` is {config.feat_extract_norm}, but has to be one of ['group', 'layer']\"\n            )\n        self.conv_layers = nn.LayerList(conv_layers)\n        self.gradient_checkpointing = False\n\n    def _freeze_parameters(self):\n        for param in self.parameters():\n            param.trainable = False\n\n    def forward(self, input_values):\n        hidden_states = input_values[:, None]\n        for conv_layer in self.conv_layers:\n            hidden_states = conv_layer(hidden_states)\n\n        return hidden_states\n\n\nclass Wav2Vec2FeatureProjection(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.layer_norm = nn.LayerNorm(\n            config.conv_dim[-1], epsilon=config.layer_norm_eps)\n        self.projection = nn.Linear(config.conv_dim[-1], config.hidden_size)\n        self.dropout = nn.Dropout(config.feat_proj_dropout)\n\n    def forward(self, hidden_states):\n        # non-projected hidden states are needed for quantization\n        norm_hidden_states = self.layer_norm(hidden_states)\n        hidden_states = self.projection(norm_hidden_states)\n        hidden_states = self.dropout(hidden_states)\n        return hidden_states, norm_hidden_states\n\n\n# Copied from transformers.models.bart.modeling_bart.BartAttention with Bart->Wav2Vec2\nclass Wav2Vec2Attention(nn.Layer):\n    \"\"\"Multi-headed attention from 'Attention Is All You Need' paper\"\"\"\n\n    def __init__(\n            self,\n            embed_dim: int,\n            num_heads: int,\n            dropout: float=0.0,\n            is_decoder: bool=False,\n            bias: bool=True, ):\n        super().__init__()\n        self.embed_dim = embed_dim\n        self.num_heads = num_heads\n        self.dropout = dropout\n        self.head_dim = embed_dim // num_heads\n\n        if (self.head_dim * num_heads) != self.embed_dim:\n            raise ValueError(\n                f\"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim}\"\n                f\" and `num_heads`: {num_heads}).\")\n        self.scaling = self.head_dim**-0.5\n        self.is_decoder = is_decoder\n\n        self.k_proj = nn.Linear(embed_dim, embed_dim, bias_attr=bias)\n        self.v_proj = nn.Linear(embed_dim, embed_dim, bias_attr=bias)\n        self.q_proj = nn.Linear(embed_dim, embed_dim, bias_attr=bias)\n        self.out_proj = nn.Linear(embed_dim, embed_dim, bias_attr=bias)\n\n    def _shape(self, tensor: paddle.Tensor, seq_len: int, bsz: int):\n        return paddle.reshape(tensor, (bsz, seq_len, self.num_heads,\n                                       self.head_dim)).transpose([0, 2, 1, 3])\n\n    def forward(\n            self,\n            hidden_states: paddle.Tensor,\n            key_value_states: Optional[paddle.Tensor]=None,\n            past_key_value: Optional[Tuple[paddle.Tensor]]=None,\n            attention_mask: Optional[paddle.Tensor]=None,\n            layer_head_mask: Optional[paddle.Tensor]=None,\n            output_attentions: bool=False, ) -> Tuple[paddle.Tensor, Optional[\n                paddle.Tensor], Optional[Tuple[paddle.Tensor]]]:\n        \"\"\"Input shape: Batch x Time x Channel\"\"\"\n\n        # if key_value_states are provided this layer is used as a cross-attention layer\n        # for the decoder\n        is_cross_attention = key_value_states is not None\n\n        bsz, tgt_len, _ = hidden_states.shape\n\n        # get query proj\n        query_states = self.q_proj(hidden_states) * self.scaling\n        # get key, value proj\n        if is_cross_attention and past_key_value is not None:\n            # reuse k,v, cross_attentions\n            key_states = past_key_value[0]\n            value_states = past_key_value[1]\n        elif is_cross_attention:\n            # cross_attentions\n            key_states = self._shape(self.k_proj(key_value_states), -1, bsz)\n            value_states = self._shape(self.v_proj(key_value_states), -1, bsz)\n        elif past_key_value is not None:\n            # reuse k, v, self_attention\n            key_states = self._shape(self.k_proj(hidden_states), -1, bsz)\n            value_states = self._shape(self.v_proj(hidden_states), -1, bsz)\n            key_states = paddle.concat([past_key_value[0], key_states], axis=2)\n            value_states = paddle.concat(\n                [past_key_value[1], value_states], axis=2)\n        else:\n            # self_attention\n            key_states = self._shape(self.k_proj(hidden_states), -1, bsz)\n            value_states = self._shape(self.v_proj(hidden_states), -1, bsz)\n\n        if self.is_decoder:\n            # if cross_attention save Tuple(paddle.Tensor, paddle.Tensor) of all cross attention key/value_states.\n            # Further calls to cross_attention layer can then reuse all cross-attention\n            # key/value_states (first \"if\" case)\n            # if uni-directional self-attention (decoder) save Tuple(paddle.Tensor, paddle.Tensor) of\n            # all previous decoder key/value_states. Further calls to uni-directional self-attention\n            # can concat previous decoder key/value_states to current projected key/value_states (third \"elif\" case)\n            # if encoder bi-directional self-attention `past_key_value` is always `None`\n            past_key_value = (key_states, value_states)\n\n        proj_shape = (bsz * self.num_heads, -1, self.head_dim)\n        query_states = self._shape(query_states, tgt_len,\n                                   bsz).reshape(proj_shape)\n        key_states = key_states.reshape(proj_shape)\n        value_states = value_states.reshape(proj_shape)\n\n        src_len = key_states.shape[1]\n        attn_weights = paddle.bmm(query_states, key_states.transpose([0, 2, 1]))\n\n        if attn_weights.shape != [bsz * self.num_heads, tgt_len, src_len]:\n            raise ValueError(\n                f\"Attention weights should be of size {(bsz * self.num_heads, tgt_len, src_len)}, but is\"\n                f\" {attn_weights.shape}\")\n\n        if attention_mask is not None:\n            if attention_mask.shape != [bsz, 1, tgt_len, src_len]:\n                raise ValueError(\n                    f\"Attention mask should be of size {[bsz, 1, tgt_len, src_len]}, but is {attention_mask.shape}\"\n                )\n            attn_weights = attn_weights.reshape(bsz, self.num_heads, tgt_len,\n                                                src_len) + attention_mask\n            attn_weights = attn_weights.reshape(bsz * self.num_heads, tgt_len,\n                                                src_len)\n\n        attn_weights = nn.functional.softmax(attn_weights, axis=-1)\n\n        if layer_head_mask is not None:\n            if layer_head_mask.shape != [\n                    self.num_heads,\n            ]:\n                raise ValueError(\n                    f\"Head mask for a single layer should be of size {[self.num_heads,]}, but is\"\n                    f\" {layer_head_mask.shape}\")\n            attn_weights = layer_head_mask.reshape(\n                (1, -1, 1, 1)) * attn_weights.reshape(\n                    (bsz, self.num_heads, tgt_len, src_len))\n            attn_weights = attn_weights.reshape(\n                (bsz * self.num_heads, tgt_len, src_len))\n\n        if output_attentions:\n            # this operation is a bit awkward, but it's required to\n            # make sure that attn_weights keeps its gradient.\n            # In order to do so, attn_weights have to be reshaped\n            # twice and have to be reused in the following\n            attn_weights_reshaped = attn_weights.reshape(\n                (bsz, self.num_heads, tgt_len, src_len))\n            attn_weights = attn_weights_reshaped.reshape(\n                (bsz * self.num_heads, tgt_len, src_len))\n        else:\n            attn_weights_reshaped = None\n\n        attn_probs = nn.functional.dropout(\n            attn_weights, p=self.dropout, training=self.training)\n\n        attn_output = paddle.bmm(attn_probs, value_states)\n\n        if attn_output.shape != [bsz * self.num_heads, tgt_len, self.head_dim]:\n            raise ValueError(\n                f\"`attn_output` should be of size {[bsz, self.num_heads, tgt_len, self.head_dim]}, but is\"\n                f\" {attn_output.shape}\")\n\n        attn_output = attn_output.reshape(\n            (bsz, self.num_heads, tgt_len, self.head_dim))\n        attn_output = attn_output.transpose([0, 2, 1, 3])\n\n        # Use the `embed_dim` from the config (stored in the class) rather than `hidden_state` because `attn_output` can be\n        # partitioned aross GPUs when using tensor-parallelism.\n        attn_output = attn_output.reshape((bsz, tgt_len, self.embed_dim))\n\n        attn_output = self.out_proj(attn_output)\n\n        return attn_output, attn_weights_reshaped, past_key_value\n\n\nclass Wav2Vec2FeedForward(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.intermediate_dropout = nn.Dropout(config.activation_dropout)\n\n        self.intermediate_dense = nn.Linear(config.hidden_size,\n                                            config.intermediate_size)\n        if isinstance(config.hidden_act, str):\n            self.intermediate_act_fn = ACT2FN[config.hidden_act]\n        else:\n            self.intermediate_act_fn = config.hidden_act\n\n        self.output_dense = nn.Linear(config.intermediate_size,\n                                      config.hidden_size)\n        self.output_dropout = nn.Dropout(config.hidden_dropout)\n\n    def forward(self, hidden_states):\n        hidden_states = self.intermediate_dense(hidden_states)\n        hidden_states = self.intermediate_act_fn(hidden_states)\n        hidden_states = self.intermediate_dropout(hidden_states)\n\n        hidden_states = self.output_dense(hidden_states)\n        hidden_states = self.output_dropout(hidden_states)\n        return hidden_states\n\n\nclass Wav2Vec2EncoderLayer(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.attention = Wav2Vec2Attention(\n            embed_dim=config.hidden_size,\n            num_heads=config.num_attention_heads,\n            dropout=config.attention_dropout,\n            is_decoder=False, )\n        self.dropout = nn.Dropout(config.hidden_dropout)\n        self.layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n        self.feed_forward = Wav2Vec2FeedForward(config)\n        self.final_layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n\n    def forward(self,\n                hidden_states,\n                attention_mask=None,\n                output_attentions=False):\n        attn_residual = hidden_states\n        hidden_states, attn_weights, _ = self.attention(\n            hidden_states,\n            attention_mask=attention_mask,\n            output_attentions=output_attentions)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = attn_residual + hidden_states\n\n        hidden_states = self.layer_norm(hidden_states)\n        hidden_states = hidden_states + self.feed_forward(hidden_states)\n        hidden_states = self.final_layer_norm(hidden_states)\n\n        outputs = (hidden_states, )\n\n        if output_attentions:\n            outputs += (attn_weights, )\n\n        return outputs\n\n\nclass Wav2Vec2EncoderLayerStableLayerNorm(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.attention = Wav2Vec2Attention(\n            embed_dim=config.hidden_size,\n            num_heads=config.num_attention_heads,\n            dropout=config.attention_dropout,\n            is_decoder=False, )\n        self.dropout = nn.Dropout(config.hidden_dropout)\n        self.layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n        self.feed_forward = Wav2Vec2FeedForward(config)\n        self.final_layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n\n    def forward(self,\n                hidden_states,\n                attention_mask=None,\n                output_attentions=False):\n        attn_residual = hidden_states\n        hidden_states = self.layer_norm(hidden_states)\n        hidden_states, attn_weights, _ = self.attention(\n            hidden_states,\n            attention_mask=attention_mask,\n            output_attentions=output_attentions)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = attn_residual + hidden_states\n        hidden_states = hidden_states + self.feed_forward(\n            self.final_layer_norm(hidden_states))\n\n        outputs = (hidden_states, )\n\n        if output_attentions:\n            outputs += (attn_weights, )\n\n        return outputs\n\n\nclass Wav2Vec2Encoder(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.pos_conv_embed = Wav2Vec2PositionalConvEmbedding(config)\n        self.layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout)\n        self.layers = nn.LayerList([\n            Wav2Vec2EncoderLayer(config)\n            for _ in range(config.num_hidden_layers)\n        ])\n        self.gradient_checkpointing = False\n\n    def forward(\n            self,\n            hidden_states,\n            attention_mask=None,\n            output_attentions=False,\n            output_hidden_states=False,\n            return_dict=True, ):\n        all_hidden_states = () if output_hidden_states else None\n        all_self_attentions = () if output_attentions else None\n\n        if attention_mask is not None:\n            # make sure padded tokens output 0\n            expand_attention_mask = attention_mask.unsqueeze(-1).repeat(\n                1, 1, hidden_states.shape[2])\n            hidden_states[~expand_attention_mask] = 0\n\n            # extend attention_mask\n            attention_mask = 1.0 - attention_mask[:, None, None, :].to(\n                dtype=hidden_states.dtype)\n            attention_mask = attention_mask * np.iinfo(np.float32).min\n            attention_mask = attention_mask.expand(attention_mask.shape[0], 1,\n                                                   attention_mask.shape[-1],\n                                                   attention_mask.shape[-1])\n\n        position_embeddings = self.pos_conv_embed(hidden_states)\n        hidden_states = hidden_states + position_embeddings\n        hidden_states = self.layer_norm(hidden_states)\n        hidden_states = self.dropout(hidden_states)\n\n        #deepspeed_zero3_is_enabled = is_deepspeed_zero3_enabled()\n\n        for layer in self.layers:\n            if output_hidden_states:\n                all_hidden_states = all_hidden_states + (hidden_states, )\n\n            # add LayerDrop (see https://arxiv.org/abs/1909.11556 for description)\n            dropout_probability = np.random.uniform(0, 1)\n\n            skip_the_layer = True if self.training and (\n                dropout_probability < self.config.layerdrop) else False\n            if not skip_the_layer:  # or deepspeed_zero3_is_enabled:\n                # under deepspeed zero3 all gpus must run in sync\n                if self.gradient_checkpointing and self.training:\n                    # create gradient checkpointing function\n                    def create_custom_forward(module):\n                        def custom_forward(*inputs):\n                            return module(*inputs, output_attentions)\n\n                        return custom_forward\n                else:\n                    layer_outputs = layer(\n                        hidden_states,\n                        attention_mask=attention_mask,\n                        output_attentions=output_attentions)\n                hidden_states = layer_outputs[0]\n\n            if skip_the_layer:\n                layer_outputs = (None, None)\n\n            if output_attentions:\n                all_self_attentions = all_self_attentions + (layer_outputs[1], )\n\n        if output_hidden_states:\n            all_hidden_states = all_hidden_states + (hidden_states, )\n\n        if not return_dict:\n            return tuple(\n                v\n                for v in\n                [hidden_states, all_hidden_states, all_self_attentions]\n                if v is not None)\n        return BaseModelOutput(\n            last_hidden_state=hidden_states,\n            hidden_states=all_hidden_states,\n            attentions=all_self_attentions, )\n\n\nclass Wav2Vec2EncoderStableLayerNorm(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.pos_conv_embed = Wav2Vec2PositionalConvEmbedding(config)\n        self.layer_norm = nn.LayerNorm(\n            config.hidden_size, epsilon=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout)\n        self.layers = nn.LayerList([\n            Wav2Vec2EncoderLayerStableLayerNorm(config)\n            for _ in range(config.num_hidden_layers)\n        ])\n        self.gradient_checkpointing = False\n\n    def forward(\n            self,\n            hidden_states,\n            attention_mask=None,\n            output_attentions=False,\n            output_hidden_states=False,\n            return_dict=True, ):\n        all_hidden_states = () if output_hidden_states else None\n        all_self_attentions = () if output_attentions else None\n\n        if attention_mask is not None:\n            # make sure padded tokens are not attended to\n            expand_attention_mask = attention_mask.unsqueeze(\n                -1).repeat_interleave(\n                    hidden_states.shape[2], axis=2)\n            hidden_states[~expand_attention_mask] = 0\n\n            # extend attention_mask\n            attention_mask = 1.0 - attention_mask[:, None, None, :].to(\n                dtype=hidden_states.dtype)\n            attention_mask = attention_mask * np.iinfo(np.float32).min\n            attention_mask = attention_mask.expand(attention_mask.shape[0], 1,\n                                                   attention_mask.shape[-1],\n                                                   attention_mask.shape[-1])\n\n        position_embeddings = self.pos_conv_embed(hidden_states)\n        hidden_states = hidden_states + position_embeddings\n        hidden_states = self.dropout(hidden_states)\n\n        for layer in self.layers:\n            if output_hidden_states:\n                all_hidden_states = all_hidden_states + (hidden_states, )\n\n            # add LayerDrop (see https://arxiv.org/abs/1909.11556 for description)\n            dropout_probability = np.random.uniform(0, 1)\n\n            skip_the_layer = True if self.training and (\n                dropout_probability < self.config.layerdrop) else False\n            if not skip_the_layer:  # or deepspeed_zero3_is_enabled:\n                # under deepspeed zero3 all gpus must run in sync\n                # XXX: could optimize this like synced_gpus in generate_utils but not sure if it's worth the code complication\n                if self.gradient_checkpointing and self.training:\n                    # create gradient checkpointing function\n                    def create_custom_forward(module):\n                        def custom_forward(*inputs):\n                            return module(*inputs, output_attentions)\n\n                        return custom_forward\n                else:\n                    layer_outputs = layer(\n                        hidden_states,\n                        attention_mask=attention_mask,\n                        output_attentions=output_attentions)\n                hidden_states = layer_outputs[0]\n\n            if skip_the_layer:\n                layer_outputs = (None, None)\n\n            if output_attentions:\n                all_self_attentions = all_self_attentions + (layer_outputs[1], )\n\n        hidden_states = self.layer_norm(hidden_states)\n\n        if output_hidden_states:\n            all_hidden_states = all_hidden_states + (hidden_states, )\n\n        if not return_dict:\n            return tuple(\n                v\n                for v in\n                [hidden_states, all_hidden_states, all_self_attentions]\n                if v is not None)\n        return BaseModelOutput(\n            last_hidden_state=hidden_states,\n            hidden_states=all_hidden_states,\n            attentions=all_self_attentions, )\n\n\nclass Wav2Vec2GumbelVectorQuantizer(nn.Layer):\n    \"\"\"\n    Vector quantization using gumbel softmax. See `[CATEGORICAL REPARAMETERIZATION WITH\n    GUMBEL-SOFTMAX](https://arxiv.org/pdf/1611.01144.pdf) for more information.\n    \"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n        self.num_groups = config.num_codevector_groups\n        self.num_vars = config.num_codevectors_per_group\n\n        if config.codevector_dim % self.num_groups != 0:\n            raise ValueError(\n                f\"`config.codevector_dim {config.codevector_dim} must be divisible \"\n                f\"by `config.num_codevector_groups` {self.num_groups} for concatenation\"\n            )\n\n        # storage for codebook variables (codewords)\n        self.codevectors = paddle.static.create_parameter(\n            shape=[\n                1, self.num_groups * self.num_vars,\n                config.codevector_dim // self.num_groups\n            ],\n            dtype='float32')\n        self.weight_proj = nn.Linear(config.conv_dim[-1],\n                                     self.num_groups * self.num_vars)\n\n        # can be decayed for training\n        self.temperature = 2\n\n    @staticmethod\n    def _compute_perplexity(probs, mask=None):\n        if mask is not None:\n            mask_extended = mask.flatten()[:, None, None].expand(probs.shape)\n            probs = paddle.where(mask_extended, probs, paddle.zeros_like(probs))\n            marginal_probs = probs.sum(dim=0) / mask.sum()\n        else:\n            marginal_probs = probs.mean(dim=0)\n\n        perplexity = paddle.exp(-paddle.sum(\n            marginal_probs * paddle.log(marginal_probs + 1e-7), dim=-1)).sum()\n        return perplexity\n\n    def forward(self, hidden_states, mask_time_indices=None):\n        batch_size, sequence_length, hidden_size = hidden_states.shape\n\n        # project to codevector dim\n        hidden_states = self.weight_proj(hidden_states)\n        hidden_states = hidden_states.reshape(\n            (batch_size * sequence_length * self.num_groups, -1))\n\n        if self.training:\n            # sample code vector probs via gumbel in differentiateable way\n            codevector_probs = nn.functional.gumbel_softmax(\n                hidden_states.float(), tau=self.temperature,\n                hard=True).type_as(hidden_states)\n\n            # compute perplexity\n            codevector_soft_dist = paddle.nn.functional.softmax(\n                hidden_states.reshape((batch_size * sequence_length,\n                                       self.num_groups, -1)).float(),\n                axis=-1)\n            perplexity = self._compute_perplexity(codevector_soft_dist,\n                                                  mask_time_indices)\n        else:\n            # take argmax in non-differentiable way\n            # comptute hard codevector distribution (one hot)\n            codevector_idx = hidden_states.argmax(dim=-1)\n            codevector_probs = hidden_states.new_zeros(\n                *hidden_states.shape).scatter_(-1,\n                                               codevector_idx.reshape((-1, 1)),\n                                               1.0)\n            codevector_probs = codevector_probs.reshape(\n                (batch_size * sequence_length, self.num_groups, -1))\n\n            perplexity = self._compute_perplexity(codevector_probs,\n                                                  mask_time_indices)\n\n        codevector_probs = codevector_probs.reshape(\n            (batch_size * sequence_length, -1))\n        # use probs to retrieve codevectors\n        codevectors_per_group = codevector_probs.unsqueeze(\n            -1) * self.codevectors\n        codevectors = codevectors_per_group.reshape(\n            (batch_size * sequence_length, self.num_groups, self.num_vars, -1))\n        codevectors = codevectors.sum(-2).reshape(\n            (batch_size, sequence_length, -1))\n\n        return codevectors, perplexity\n\n\nclass Wav2Vec2Adapter(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n\n        # feature dim might need to be down-projected\n        if config.output_hidden_size != config.hidden_size:\n            self.proj = nn.Linear(config.hidden_size, config.output_hidden_size)\n            self.proj_layer_norm = nn.LayerNorm(config.output_hidden_size)\n        else:\n            self.proj = self.proj_layer_norm = None\n\n        self.layers = nn.LayerList(\n            Wav2Vec2AdapterLayer(config)\n            for _ in range(config.num_adapter_layers))\n        self.layerdrop = config.layerdrop\n\n    def forward(self, hidden_states):\n        # down project hidden_states if necessary\n        if self.proj is not None and self.proj_layer_norm is not None:\n            hidden_states = self.proj(hidden_states)\n            hidden_states = self.proj_layer_norm(hidden_states)\n\n        hidden_states = hidden_states.transpose([0, 2, 1])\n\n        for layer in self.layers:\n            layerdrop_prob = np.random.random()\n            if not self.training or (layerdrop_prob > self.layerdrop):\n                hidden_states = layer(hidden_states)\n\n        hidden_states = hidden_states.transpose([0, 2, 1])\n        return hidden_states\n\n\nclass Wav2Vec2AdapterLayer(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.conv = nn.Conv1D(\n            config.output_hidden_size,\n            2 * config.output_hidden_size,\n            config.adapter_kernel_size,\n            stride=config.adapter_stride,\n            padding=1, )\n\n    def forward(self, hidden_states):\n        hidden_states = self.conv(hidden_states)\n        hidden_states = nn.functional.glu(hidden_states, axis=1)\n\n        return hidden_states\n\n\nclass Wav2Vec2Model(nn.Layer):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.feature_extractor = Wav2Vec2FeatureEncoder(config)\n        self.feature_projection = Wav2Vec2FeatureProjection(config)\n\n        # model only needs masking vector if mask prob is > 0.0\n        if config.mask_time_prob > 0.0 or config.mask_feature_prob > 0.0:\n            #  self.masked_spec_embed = nn.Parameter(paddle.Tensor(config.hidden_size).uniform_())\n            #self.masked_spec_embed = paddle.uniform([config.hidden_size])\n            self.masked_spec_embed = paddle.static.create_parameter(\n                shape=[config.hidden_size],\n                dtype='float32',\n                default_initializer=paddle.nn.initializer.Uniform(\n                    low=0, high=1.0))\n        if config.do_stable_layer_norm:\n            self.encoder = Wav2Vec2EncoderStableLayerNorm(config)\n        else:\n            self.encoder = Wav2Vec2Encoder(config)\n\n        self.adapter = Wav2Vec2Adapter(config) if config.add_adapter else None\n\n        # Initialize weights and apply final processing\n        self.post_init()\n\n    def freeze_feature_encoder(self):\n        \"\"\"\n        Calling this function will disable the gradient computation for the feature encoder so that its parameter will\n        not be updated during training.\n        \"\"\"\n        self.feature_extractor._freeze_parameters()\n\n    def _mask_hidden_states(\n            self,\n            hidden_states: paddle.Tensor,\n            mask_time_indices: Optional[paddle.Tensor]=None,\n            attention_mask: Optional[paddle.Tensor]=None, ):\n        \"\"\"\n        Masks extracted features along time axis and/or along feature axis according to\n        [SpecAugment](https://arxiv.org/abs/1904.08779).\n        \"\"\"\n        # `config.apply_spec_augment` can set masking to False\n        if not getattr(self.config, \"apply_spec_augment\", True):\n            return hidden_states\n\n        # generate indices & apply SpecAugment along time axis\n        batch_size, sequence_length, hidden_size = hidden_states.shape\n        if mask_time_indices is not None:\n            # apply SpecAugment along time axis with given mask_time_indices\n            hidden_states[mask_time_indices] = self.masked_spec_embed.to(\n                hidden_states.dtype)\n        elif self.config.mask_time_prob > 0 and self.training:\n            mask_time_indices = _compute_mask_indices(\n                (batch_size, sequence_length),\n                mask_prob=self.config.mask_time_prob,\n                mask_length=self.config.mask_time_length,\n                attention_mask=attention_mask,\n                min_masks=self.config.mask_time_min_masks, )\n            mask_time_indices = paddle.to_tensor(\n                mask_time_indices, dtype=paddle.bool)\n            hidden_states[mask_time_indices] = self.masked_spec_embed.to(\n                hidden_states.dtype)\n\n        if self.config.mask_feature_prob > 0 and self.training:\n            # generate indices & apply SpecAugment along feature axis\n            mask_feature_indices = _compute_mask_indices(\n                (batch_size, hidden_size),\n                mask_prob=self.config.mask_feature_prob,\n                mask_length=self.config.mask_feature_length,\n                min_masks=self.config.mask_feature_min_masks, )\n            mask_feature_indices = paddle.to_tensor(\n                mask_feature_indices, dtype=paddle.bool)\n            mask_feature_indices = mask_feature_indices[:, None].expand(\n                -1, sequence_length, -1)\n            hidden_states[mask_feature_indices] = 0\n\n        return hidden_states\n\n    def forward(\n            self,\n            input_values: Optional[paddle.Tensor],\n            attention_mask: Optional[paddle.Tensor]=None,\n            mask_time_indices: Optional[paddle.Tensor]=None,\n            output_attentions: Optional[bool]=None,\n            output_hidden_states: Optional[bool]=None,\n            return_dict: Optional[bool]=None,\n    ) -> Union[Tuple, Wav2Vec2BaseModelOutput]:\n        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions\n        output_hidden_states = (output_hidden_states\n                                if output_hidden_states is not None else\n                                self.config.output_hidden_states)\n        return_dict = return_dict if return_dict is not None else self.config.use_return_dict\n        extract_features = self.feature_extractor(input_values)\n        extract_features = extract_features.transpose([0, 2, 1])\n\n        if attention_mask is not None:\n            # compute reduced attention_mask corresponding to feature vectors\n            attention_mask = self._get_feature_vector_attention_mask(\n                extract_features.shape[1], attention_mask, add_adapter=False)\n        hidden_states, extract_features = self.feature_projection(\n            extract_features)\n        hidden_states = self._mask_hidden_states(\n            hidden_states,\n            mask_time_indices=mask_time_indices,\n            attention_mask=attention_mask)\n\n        encoder_outputs = self.encoder(\n            hidden_states,\n            attention_mask=attention_mask,\n            output_attentions=output_attentions,\n            output_hidden_states=output_hidden_states,\n            return_dict=return_dict, )\n\n        hidden_states = encoder_outputs[0]\n\n        if self.adapter is not None:\n            hidden_states = self.adapter(hidden_states)\n\n        if not return_dict:\n            return (hidden_states, extract_features) + encoder_outputs[1:]\n\n        return Wav2Vec2BaseModelOutput(\n            last_hidden_state=hidden_states,\n            extract_features=extract_features,\n            hidden_states=encoder_outputs.hidden_states,\n            attentions=encoder_outputs.attentions, )\n\n    def post_init(self):\n        \"\"\"\n        A method executed at the end of each Transformer model initialization, to execute code that needs the model's\n        modules properly initialized (such as weight initialization).\n        \"\"\"\n        #   self.init_weights()\n        #   self._backward_compatibility_gradient_checkpointing()\n        pass\n\n\nclass Wav2Vec2ConfigPure():\n    model_type = \"wav2vec2\"\n\n    def __init__(self, config):\n        self.output_attentions = False\n        self.output_hidden_states = False\n        self.use_return_dict = True\n\n        self.hidden_size = config.hidden_size\n        self.feat_extract_norm = config.feat_extract_norm\n        self.feat_extract_activation = config.feat_extract_activation\n        self.conv_dim = config.conv_dim\n        self.conv_stride = config.conv_stride\n        self.conv_kernel = config.conv_kernel\n        self.conv_bias = config.conv_bias\n        self.num_conv_pos_embeddings = config.num_conv_pos_embeddings\n        self.num_conv_pos_embedding_groups = config.num_conv_pos_embedding_groups\n        self.num_feat_extract_layers = len(self.conv_dim)\n        self.num_hidden_layers = config.num_hidden_layers\n        self.intermediate_size = config.intermediate_size\n        self.hidden_act = config.hidden_act\n        self.num_attention_heads = config.num_attention_heads\n        self.hidden_dropout = config.hidden_dropout\n        self.attention_dropout = config.attention_dropout\n        self.activation_dropout = config.activation_dropout\n        self.feat_proj_dropout = config.feat_proj_dropout\n        self.final_dropout = config.final_dropout\n        self.layerdrop = config.layerdrop\n        self.layer_norm_eps = config.layer_norm_eps\n        self.initializer_range = config.initializer_range\n        self.do_stable_layer_norm = config.do_stable_layer_norm\n        self.use_weighted_layer_sum = config.use_weighted_layer_sum\n\n        if ((len(self.conv_stride) != self.num_feat_extract_layers) or\n            (len(self.conv_kernel) != self.num_feat_extract_layers) or\n            (len(self.conv_dim) != self.num_feat_extract_layers)):\n            raise ValueError(\n                \"Configuration for convolutional layers is incorrect. It is required that `len(config.conv_dim)` ==\"\n                \" `len(config.conv_stride)` == `len(config.conv_kernel)`, but is `len(config.conv_dim) =\"\n                f\" {len(self.conv_dim)}`, `len(config.conv_stride) = {len(self.conv_stride)}`,\"\n                f\" `len(config.conv_kernel) = {len(self.conv_kernel)}`.\")\n\n        # fine-tuning config parameters for SpecAugment: https://arxiv.org/abs/1904.08779\n        self.apply_spec_augment = config.apply_spec_augment\n        self.mask_time_prob = config.mask_time_prob\n        self.mask_time_length = config.mask_time_length\n        self.mask_time_min_masks = config.mask_time_min_masks\n        self.mask_feature_prob = config.mask_feature_prob\n        self.mask_feature_length = config.mask_feature_length\n        self.mask_feature_min_masks = config.mask_feature_min_masks\n\n        # parameters for pretraining with codevector quantized representations\n        self.num_codevectors_per_group = config.num_codevectors_per_group\n        self.num_codevector_groups = config.num_codevector_groups\n        self.contrastive_logits_temperature = config.contrastive_logits_temperature\n        self.feat_quantizer_dropout = config.feat_quantizer_dropout\n        self.num_negatives = config.num_negatives\n        self.codevector_dim = config.codevector_dim\n        self.proj_codevector_dim = config.proj_codevector_dim\n        self.diversity_loss_weight = config.diversity_loss_weight\n\n        # adapter\n        self.add_adapter = config.add_adapter\n        self.adapter_kernel_size = config.adapter_kernel_size\n        self.adapter_stride = config.adapter_stride\n        self.num_adapter_layers = config.num_adapter_layers\n        self.output_hidden_size = config.output_hidden_size or config.hidden_size\n\n    @property\n    def inputs_to_logits_ratio(self):\n        return functools.reduce(operator.mul, self.conv_stride, 1)\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/normalization.py",
    "content": "# Authors\n#  * Mirco Ravanelli 2020\n#  * Guillermo Cámbara 2021\n#  * Sarthak Yadav 2022\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/nnet/normalization.py)\nimport paddle.nn as nn\n\nfrom paddlespeech.s2t.modules.align import BatchNorm1D\n\n\nclass BatchNorm1d(nn.Layer):\n    \"\"\"Applies 1d batch normalization to the input tensor.\n    Arguments\n    ---------\n    input_shape : tuple\n        The expected shape of the input. Alternatively, use ``input_size``.\n    input_size : int\n        The expected size of the input. Alternatively, use ``input_shape``.\n    eps : float\n        This value is added to std deviation estimation to improve the numerical\n        stability.\n    momentum : float\n        It is a value used for the running_mean and running_var computation.\n    affine : bool\n        When set to True, the affine parameters are learned.\n    track_running_stats : bool\n        When set to True, this module tracks the running mean and variance,\n        and when set to False, this module does not track such statistics.\n    combine_batch_time : bool\n        When true, it combines batch an time axis.\n    Example\n    -------\n    >>> input = paddle.randn([100, 10])\n    >>> norm = BatchNorm1d(input_shape=input.shape)\n    >>> output = norm(input)\n    >>> output.shape\n    Paddle.Shape([100, 10])\n    \"\"\"\n\n    def __init__(\n            self,\n            input_shape=None,\n            input_size=None,\n            eps=1e-05,\n            momentum=0.9,\n            combine_batch_time=False,\n            skip_transpose=False, ):\n        super().__init__()\n        self.combine_batch_time = combine_batch_time\n        self.skip_transpose = skip_transpose\n\n        if input_size is None and skip_transpose:\n            input_size = input_shape[1]\n        elif input_size is None:\n            input_size = input_shape[-1]\n\n        self.norm = BatchNorm1D(input_size, momentum=momentum, epsilon=eps)\n\n    def forward(self, x):\n        \"\"\"Returns the normalized input tensor.\n        Arguments\n        ---------\n        x : paddle.Tensor (batch, time, [channels])\n            input to normalize. 2d or 3d tensors are expected in input\n            4d tensors can be used when combine_dims=True.\n        \"\"\"\n        shape_or = x.shape\n        if self.combine_batch_time:\n            if x.ndim == 3:\n                x = x.reshape(shape_or[0] * shape_or[1], shape_or[2])\n            else:\n                x = x.reshape(shape_or[0] * shape_or[1], shape_or[3],\n                              shape_or[2])\n\n        elif not self.skip_transpose:\n            x = x.transpose([0, 2, 1])\n\n        x_n = self.norm(x)\n        if self.combine_batch_time:\n            x_n = x_n.reshape(shape_or)\n        elif not self.skip_transpose:\n            x_n = x_n.transpose([0, 2, 1])\n\n        return x_n\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/modules/wav2vec2_model.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Paddle Wav2Vec2 model.\"\"\"\nimport math\nimport uuid\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom enum import Enum\nfrom enum import EnumMeta\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\nfrom paddle import Tensor\n\nfrom paddlespeech.s2t.modules.align import Conv1D\nfrom paddlespeech.s2t.modules.align import Conv2D\nfrom paddlespeech.s2t.modules.align import Embedding\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n\nclass GLU(nn.Layer):\n    r\"\"\"Applies the gated linear unit function\n    :math:`{GLU}(a, b)= a \\otimes \\sigma(b)` where :math:`a` is the first half\n    of the input matrices and :math:`b` is the second half.\n\n    Args:\n        axis (int): the dimension on which to split the input. Default: -1\n\n    Shape:\n        - Input: :math:`(\\ast_1, N, \\ast_2)` where `*` means, any number of additional\n          dimensions\n        - Output: :math:`(\\ast_1, M, \\ast_2)` where :math:`M=N/2`\n\n    Examples::\n\n        >>> m = nn.GLU()\n        >>> input = paddle.randn([4, 2])\n        >>> output = m(input)\n    \"\"\"\n\n    def __init__(self, axis: int=-1) -> None:\n        super().__init__()\n        self.axis = axis\n\n    def forward(self, input: Tensor) -> Tensor:\n        return F.glu(input, self.axis)\n\n\nclass FairseqIncrementalState(object):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.init_incremental_state()\n\n    def init_incremental_state(self):\n        self._incremental_state_id = str(uuid.uuid4())\n\n    def _get_full_incremental_state_key(self, key: str) -> str:\n        return \"{}.{}\".format(self._incremental_state_id, key)\n\n    def get_incremental_state(\n            self,\n            incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]],\n            key: str, ) -> Optional[Dict[str, Optional[Tensor]]]:\n        \"\"\"Helper for getting incremental state for an nn.Layer.\"\"\"\n        full_key = self._get_full_incremental_state_key(key)\n        if incremental_state is None or full_key not in incremental_state:\n            return None\n        return incremental_state[full_key]\n\n    def set_incremental_state(\n            self,\n            incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]],\n            key: str,\n            value: Dict[str, Optional[Tensor]],\n    ) -> Optional[Dict[str, Dict[str, Optional[Tensor]]]]:\n        \"\"\"Helper for setting incremental state for an nn.Layer.\"\"\"\n        if incremental_state is not None:\n            full_key = self._get_full_incremental_state_key(key)\n            incremental_state[full_key] = value\n        return incremental_state\n\n\ndef with_incremental_state(cls):\n    cls.__bases__ = (FairseqIncrementalState, ) + tuple(\n        b for b in cls.__bases__ if b != FairseqIncrementalState)\n    return cls\n\n\nclass FairseqDropout(paddle.nn.Layer):\n    def __init__(self, p, module_name=None):\n        super().__init__()\n        self.p = p\n        self.module_name = module_name\n        self.apply_during_inference = False\n\n    def forward(self, x):\n        if self.p > 0 and (self.training or self.apply_during_inference):\n            return F.dropout(x, p=self.p, training=True)\n        else:\n            return x\n\n    def make_generation_fast_(\n            self,\n            name: str,\n            retain_dropout: bool=False,\n            retain_dropout_modules: Optional[List[str]]=None,\n            **kwargs, ):\n        if retain_dropout:\n            if retain_dropout_modules is not None and self.module_name is None:\n                logger.warning(\n                    \"Cannot enable dropout during inference for module {} \"\n                    \"because module_name was not set\".format(name))\n            elif (retain_dropout_modules is\n                  None  # if None, apply to all modules\n                  or self.module_name in retain_dropout_modules):\n                logger.info(\"Enabling dropout during inference for module: {}\".\n                            format(name))\n                self.apply_during_inference = True\n            else:\n                logger.info(\"Disabling dropout for module: {}\".format(name))\n\n\ndef quant_noise(module, p, block_size):\n    \"\"\"\n    Wraps modules and applies quantization noise to the weights for\n    subsequent quantization with Iterative Product Quantization as\n    described in \"Training with Quantization Noise for Extreme Model Compression\"\n\n    Args:\n        - module: nn.Layer\n        - p: amount of Quantization Noise\n        - block_size: size of the blocks for subsequent quantization with iPQ\n\n    Remarks:\n        - Layer weights must have the right sizes wrt the block size\n        - Only Linear, Embedding and Conv2d modules are supported for the moment\n        - For more detail on how to quantize by blocks with convolutional weights,\n          see \"And the Bit Goes Down: Revisiting the Quantization of Neural Networks\"\n        - We implement the simplest form of noise here as stated in the paper\n          which consists in randomly dropping blocks\n    \"\"\"\n\n    # if no quantization noise, don't register hook\n    if p <= 0:\n        return module\n\n    # supported modules\n    assert isinstance(module, (Linear, Embedding, Conv2D))\n\n    # test whether module.weight has the right sizes wrt block_size\n    is_conv = len(module.weight.shape) == 4\n\n    # 2D matrix\n    if not is_conv:\n        if isinstance(module, Linear):\n            features_weight = module.weight.shape[0]\n        else:\n            features_weight = module.weight.shape[1]\n        assert (\n            features_weight %\n            block_size == 0), \"Input features must be a multiple of block sizes\"\n\n    # 4D matrix\n    else:\n        # 1x1 convolutions\n        if module.weight.shape[2:] == (1, 1):\n            assert (module.weight.shape[1] % block_size == 0\n                    ), \"Input channels must be a multiple of block sizes\"\n        # regular convolutions\n        else:\n            k = module.weight.shape[2] * module.weight.shape[3]\n            assert k % block_size == 0, \"Kernel size must be a multiple of block size\"\n\n    def _forward_pre_hook(mod, input):\n        # no noise for evaluation\n        if mod.training:\n            if not is_conv:\n                # gather weight and sizes\n                weight = mod.weight\n                if isinstance(module, Linear):\n                    in_features = weight.shape[0]\n                    out_features = weight.shape[1]\n                else:\n                    in_features = weight.shape[1]\n                    out_features = weight.shape[0]\n\n                # split weight matrix into blocks and randomly drop selected blocks\n                mask = paddle.zeros(\n                    [in_features // block_size * out_features],\n                    dtype=paddle.bool)\n                # the implementation of bernoulli_, p=0.5\n                mask = paddle.ones_like(mask) * 0.5\n                mask = paddle.bernoulli(mask)\n                mask = mask.unsqueeze(1).tile([1, block_size]).reshape(\n                    [-1, in_features])\n\n            else:\n                # gather weight and sizes\n                weight = mod.weight\n                in_channels = mod.weight.shape[1]\n                out_channels = mod.weight.shape[0]\n\n                # split weight matrix into blocks and randomly drop selected blocks\n                if module.weight.shape[2:] == (1, 1):\n                    mask = paddle.zeros(\n                        [in_channels // block_size * out_channels],\n                        dtype=paddle.bool)\n\n                    # the implementation of bernoulli_, p=0.5\n                    mask = paddle.ones_like(mask) * 0.5\n                    mask = paddle.bernoulli(mask)\n                    mask = mask.unsqueeze(1).tile([1, block_size]).reshape(\n                        [-1, in_channels])\n                else:\n                    mask = paddle.zeros(weight.shape)\n\n                    # the implementation of bernoulli_, p=0.5\n                    mask = paddle.ones_like(mask) * 0.5\n                    mask = paddle.bernoulli(mask)\n                    mask = mask.unsqueeze(1).tile([1, in_channels, 1, 1])\n\n            # scale weights and apply mask\n            s = 1 / (1 - p)\n            mod.weight.set_value(s * weight.masked_fill(mask, 0))\n\n    module.register_forward_pre_hook(_forward_pre_hook)\n    return module\n\n\n@with_incremental_state\nclass MultiheadAttention(nn.Layer):\n    \"\"\"Multi-headed attention.\n\n    See \"Attention Is All You Need\" for more details.\n    \"\"\"\n\n    def __init__(\n            self,\n            embed_dim,\n            num_heads,\n            kdim=None,\n            vdim=None,\n            dropout=0.0,\n            bias=True,\n            add_bias_kv=False,\n            add_zero_attn=False,\n            self_attention=False,\n            encoder_decoder_attention=False,\n            q_noise=0.0,\n            qn_block_size=8,\n            # TODO: pass in config rather than string.\n            # config defined in xformers.components.attention.AttentionConfig\n            xformers_att_config: Optional[str]=None,\n            xformers_blocksparse_layout: Optional[\n                paddle.Tensor]=None,  # This should be part of the config\n            xformers_blocksparse_blocksize: Optional[\n                int]=16,  # This should be part of the config\n    ):\n        super().__init__()\n\n        def eval_str_dict(x, type=dict):\n            if x is None:\n                return None\n            if isinstance(x, str):\n                x = eval(x)\n            return x\n\n        xformers_att_config = eval_str_dict(xformers_att_config)\n        self.use_xformers = xformers_att_config is not None\n        assert not self.use_xformers, \"Do not use xformers in PaddleSpeech\"\n\n        self.embed_dim = embed_dim\n        self.kdim = kdim if kdim is not None else embed_dim\n        self.vdim = vdim if vdim is not None else embed_dim\n        self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim\n\n        self.num_heads = num_heads\n        self.dropout_module = FairseqDropout(\n            dropout, module_name=self.__class__.__name__)\n\n        self.head_dim = embed_dim // num_heads\n        assert (self.head_dim * num_heads == self.embed_dim\n                ), \"embed_dim must be divisible by num_heads\"\n        self.scaling = self.head_dim**-0.5\n\n        self.self_attention = self_attention\n        self.encoder_decoder_attention = encoder_decoder_attention\n\n        assert not self.self_attention or self.qkv_same_dim, (\n            \"Self-attention requires query, key and \"\n            \"value to be of the same size\")\n\n        # Todo scaled initialization\n        # Empirically observed the convergence to be much better with\n        # the scaled initialization\n        weight_attr = nn.initializer.XavierUniform()\n        kv_proj_bias_attr = nn.initializer.XavierUniform()\n        out_proj_bias_attr = nn.initializer.Constant(0)\n\n        self.k_proj = quant_noise(\n            nn.Linear(\n                self.kdim,\n                embed_dim,\n                weight_attr=weight_attr,\n                bias_attr=bias\n                if not bias else kv_proj_bias_attr), q_noise, qn_block_size)\n        self.v_proj = quant_noise(\n            nn.Linear(\n                self.vdim,\n                embed_dim,\n                weight_attr=weight_attr,\n                bias_attr=bias\n                if not bias else kv_proj_bias_attr), q_noise, qn_block_size)\n        self.q_proj = quant_noise(\n            nn.Linear(\n                embed_dim, embed_dim, weight_attr=weight_attr, bias_attr=bias),\n            q_noise, qn_block_size)\n\n        self.out_proj = quant_noise(\n            nn.Linear(\n                embed_dim,\n                embed_dim,\n                weight_attr=weight_attr,\n                bias_attr=bias\n                if not bias else out_proj_bias_attr), q_noise, qn_block_size)\n\n        #         nn.initializer.XavierUniform(self.k_proj.weight, gain=1 / math.sqrt(2))\n        #         nn.initializer.XavierUniform(self.v_proj.weight, gain=1 / math.sqrt(2))\n        #         nn.initializer.XavierUniform(self.q_proj.weight, gain=1 / math.sqrt(2))\n        #     else:\n        #         self.k_proj.weight = paddle.ParamAttr()\n        #     nn.initializer.XavierUniform(self.k_proj.weight)\n        #     nn.initializer.XavierUniform(self.v_proj.weight)\n        #     nn.initializer.XavierUniform(self.q_proj.weight)\n\n        #     nn.initializer.XavierUniform(self.out_proj.weight)\n        # if self.out_proj.bias is not None:\n        #     nn.initializer.Constant(self.out_proj.bias)\n        # if self.bias_k is not None:\n        #     nn.initializer.XavierNormal(self.bias_k)\n        # if self.bias_v is not None:\n        #     nn.initializer.XavierNormal(self.bias_v)\n\n        # self.k_proj = Linear(self.kdim, embed_dim)\n\n        # self.v_proj = Linear(self.vdim, embed_dim)\n\n        # self.q_proj = Linear(embed_dim, embed_dim)\n\n        # self.out_proj = Linear(embed_dim, embed_dim)\n\n        if add_bias_kv:\n            self.bias_k = paddle.create_parameter(\n                shape=[1, 1, embed_dim],\n                dtype='float32',\n                initializer=nn.initializer.XavierUniform)\n            self.bias_v = paddle.create_parameter(\n                shape=[1, 1, embed_dim],\n                dtype='float32',\n                initializer=nn.initializer.XavierUniform)\n        else:\n            self.bias_k = self.bias_v = None\n\n        self.add_zero_attn = add_zero_attn\n        self.beam_size = 1\n        # self.reset_parameters()\n\n        self.onnx_trace = False\n        self.skip_embed_dim_check = False\n\n    def prepare_for_onnx_export_(self):\n        self.onnx_trace = True\n\n    def reset_parameters(self):\n        if self.qkv_same_dim:\n            # Empirically observed the convergence to be much better with\n            # the scaled initialization\n            nn.initializer.XavierUniform(\n                self.k_proj.weight, gain=1 / math.sqrt(2))\n            nn.initializer.XavierUniform(\n                self.v_proj.weight, gain=1 / math.sqrt(2))\n            nn.initializer.XavierUniform(\n                self.q_proj.weight, gain=1 / math.sqrt(2))\n        else:\n            self.k_proj.weight = paddle.ParamAttr()\n            nn.initializer.XavierUniform(self.k_proj.weight)\n            nn.initializer.XavierUniform(self.v_proj.weight)\n            nn.initializer.XavierUniform(self.q_proj.weight)\n\n            nn.initializer.XavierUniform(self.out_proj.weight)\n        if self.out_proj.bias is not None:\n            nn.initializer.Constant(self.out_proj.bias)\n        if self.bias_k is not None:\n            nn.initializer.XavierNormal(self.bias_k)\n        if self.bias_v is not None:\n            nn.initializer.XavierNormal(self.bias_v)\n\n    def _get_reserve_head_index(self, num_heads_to_keep: int):\n        k_proj_heads_norm = []\n        q_proj_heads_norm = []\n        v_proj_heads_norm = []\n\n        for i in range(self.num_heads):\n            start_idx = i * self.head_dim\n            end_idx = (i + 1) * self.head_dim\n            k_proj_heads_norm.append(\n                paddle.sum(\n                    paddle.abs(self.k_proj.weight[:, start_idx:end_idx]))\n                .tolist() + paddle.sum(\n                    paddle.abs(self.k_proj.bias[start_idx:end_idx])).tolist())\n            q_proj_heads_norm.append(\n                paddle.sum(\n                    paddle.abs(self.q_proj.weight[:, start_idx:end_idx]))\n                .tolist() + paddle.sum(\n                    paddle.abs(self.q_proj.bias[start_idx:end_idx])).tolist())\n            v_proj_heads_norm.append(\n                paddle.sum(\n                    paddle.abs(self.v_proj.weight[:, start_idx:end_idx]))\n                .tolist() + paddle.sum(\n                    paddle.abs(self.v_proj.bias[start_idx:end_idx])).tolist())\n\n        heads_norm = []\n        for i in range(self.num_heads):\n            heads_norm.append(k_proj_heads_norm[i] + q_proj_heads_norm[i] +\n                              v_proj_heads_norm[i])\n\n        sorted_head_index = sorted(\n            range(self.num_heads), key=lambda k: heads_norm[k], reverse=True)\n        reserve_head_index = []\n        for i in range(num_heads_to_keep):\n            start = sorted_head_index[i] * self.head_dim\n            end = (sorted_head_index[i] + 1) * self.head_dim\n            reserve_head_index.append((start, end))\n\n        return reserve_head_index\n\n    def _adaptive_prune_heads(self, reserve_head_index: List[Tuple[int, int]]):\n        new_q_weight = []\n        new_q_bias = []\n        new_k_weight = []\n        new_k_bias = []\n        new_v_weight = []\n        new_v_bias = []\n        new_out_proj_weight = []\n\n        for ele in reserve_head_index:\n            start_idx, end_idx = ele\n            new_q_weight.append(self.q_proj.weight[:, start_idx:end_idx])\n            new_q_bias.append(self.q_proj.bias[start_idx:end_idx])\n\n            new_k_weight.append(self.k_proj.weight[:, start_idx:end_idx])\n\n            new_k_bias.append(self.k_proj.bias[start_idx:end_idx])\n\n            new_v_weight.append(self.v_proj.weight[:, start_idx:end_idx])\n            new_v_bias.append(self.v_proj.bias[start_idx:end_idx])\n\n            new_out_proj_weight.append(\n                self.out_proj.weight[start_idx:end_idx, ])\n\n        new_q_weight = paddle.concat(new_q_weight, axis=-1).detach()\n        new_k_weight = paddle.concat(new_k_weight, axis=-1).detach()\n        new_v_weight = paddle.concat(new_v_weight, axis=-1).detach()\n        new_out_proj_weight = paddle.concat(new_out_proj_weight).detach()\n        new_q_weight.stop_gradient = False\n        new_k_weight.stop_gradient = False\n        new_v_weight.stop_gradient = False\n        new_out_proj_weight.stop_gradient = False\n\n        new_q_bias = paddle.concat(new_q_bias).detach()\n        new_q_bias.stop_gradient = False\n\n        new_k_bias = paddle.concat(new_k_bias).detach()\n        new_k_bias.stop_gradient = False\n\n        new_v_bias = paddle.concat(new_v_bias).detach()\n        new_v_bias.stop_gradient = False\n\n        self.q_proj.weight = paddle.create_parameter(\n            shape=new_q_weight.shape,\n            dtype=new_q_weight.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_q_weight))\n        self.q_proj.bias = paddle.create_parameter(\n            shape=new_q_bias.shape,\n            dtype=new_q_bias.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_q_bias))\n\n        self.k_proj.weight = paddle.create_parameter(\n            shape=new_k_weight.shape,\n            dtype=new_k_weight.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_k_weight))\n        self.k_proj.bias = paddle.create_parameter(\n            shape=new_k_bias.shape,\n            dtype=new_k_bias.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_k_bias))\n\n        self.v_proj.weight = paddle.create_parameter(\n            shape=new_v_weight.shape,\n            dtype=new_v_weight.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_v_weight))\n        self.v_proj.bias = paddle.create_parameter(\n            shape=new_v_bias.shape,\n            dtype=new_v_bias.dtype,\n            default_initializer=paddle.nn.initializer.Assign(new_v_bias))\n\n        self.out_proj.weight = paddle.create_parameter(\n            shape=new_out_proj_weight.shape,\n            dtype=new_out_proj_weight.dtype,\n            default_initializer=paddle.nn.initializer.Assign(\n                new_out_proj_weight))\n\n        self.num_heads = len(reserve_head_index)\n        self.embed_dim = self.head_dim * self.num_heads\n        self.q_proj.out_features = self.embed_dim\n        self.k_proj.out_features = self.embed_dim\n        self.v_proj.out_features = self.embed_dim\n\n    def _set_skip_embed_dim_check(self):\n        self.skip_embed_dim_check = True\n\n    def _pad_masks(\n            self,\n            key_padding_mask: Optional[Tensor],\n            attn_mask: Optional[Tensor],\n    ) -> Tuple[Optional[Tensor], Optional[Tensor]]:\n        if attn_mask is not None:\n            shape = attn_mask.shape[:-1] + [\n                1,\n            ]\n            attn_mask = paddle.concat(\n                [attn_mask, paddle.zeros(shape, dtype=attn_mask.dtype)],\n                axis=-1)\n        if key_padding_mask is not None:\n            shape = key_padding_mask.shape[:-1] + [\n                1,\n            ]\n            key_padding_mask = paddle.concat(\n                [\n                    key_padding_mask, paddle.zeros(\n                        shape, dtype=key_padding_mask.dtype)\n                ],\n                axis=-1)\n        return key_padding_mask, attn_mask\n\n    def _add_bias(\n            self,\n            k: Tensor,\n            v: Tensor,\n            key_padding_mask: Optional[Tensor],\n            attn_mask: Optional[Tensor],\n            bsz: int,\n    ) -> Tuple[Tensor, Tensor, Optional[Tensor], Optional[Tensor]]:\n        assert self.bias_k is not None\n        assert self.bias_v is not None\n        k = paddle.concat([k, self.bias_k.tile([1, bsz, 1])], axis=-1)\n        v = paddle.concat([v, self.bias_v.tile([1, bsz, 1])], axis=-1)\n        key_padding_mask, attn_mask = self._pad_masks(\n            key_padding_mask=key_padding_mask, attn_mask=attn_mask)\n        return k, v, key_padding_mask, attn_mask\n\n    def _append_zero_attn(\n            self,\n            k: Tensor,\n            v: Tensor,\n            key_padding_mask: Optional[Tensor],\n            attn_mask: Optional[Tensor],\n    ) -> Tuple[Tensor, Tensor, Optional[Tensor], Optional[Tensor]]:\n        zero_attn_shape = k.shape[:-2] + [1] + k.shape[-1:]\n        k = paddle.concat(\n            [k, paddle.zeros(zero_attn_shape, dtype=k.dtype)], axis=-2)\n        v = paddle.concat(\n            [v, paddle.zeros(zero_attn_shape, dtype=v.dtype)], axis=-2)\n        key_padding_mask, attn_mask = self._pad_masks(\n            key_padding_mask=key_padding_mask, attn_mask=attn_mask)\n        return k, v, key_padding_mask, attn_mask\n\n    def forward(\n            self,\n            query,\n            key: Optional[Tensor],\n            value: Optional[Tensor],\n            key_padding_mask: Optional[Tensor]=None,\n            incremental_state: Optional[Dict[str, Dict[str, Optional[\n                Tensor]]]]=None,\n            need_weights: bool=True,\n            static_kv: bool=False,\n            attn_mask: Optional[Tensor]=None,\n            before_softmax: bool=False,\n            need_head_weights: bool=False, ) -> Tuple[Tensor, Optional[Tensor]]:\n        \"\"\"Input shape: Time x Batch x Channel\n\n        Args:\n            key_padding_mask (ByteTensor, optional): mask to exclude\n                keys that are pads, of shape `(batch, src_len)`, where\n                padding elements are indicated by 1s.\n            need_weights (bool, optional): return the attention weights,\n                averaged over heads (default: False).\n            attn_mask (ByteTensor, optional): typically used to\n                implement causal attention, where the mask prevents the\n                attention from looking forward in time (default: None).\n            before_softmax (bool, optional): return the raw attention\n                weights and values before the attention softmax.\n            need_head_weights (bool, optional): return the attention\n                weights for each head. Implies *need_weights*. Default:\n                return the average attention weights over all heads.\n        \"\"\"\n        if need_head_weights:\n            need_weights = True\n\n        is_tpu = query.place == \"xla\"\n\n        tgt_len, bsz, embed_dim = query.shape\n        src_len = tgt_len\n        if not self.skip_embed_dim_check:\n            assert (embed_dim == self.embed_dim\n                    ), f\"query dim {embed_dim} != {self.embed_dim}\"\n        assert list(query.shape) == [tgt_len, bsz, embed_dim]\n        if key is not None:\n            src_len, key_bsz, _ = key.shape\n            # if not torch.jit.is_scripting():\n            #     assert value is not None\n            #     assert src_len, key_bsz == value.shape[:2]\n\n        # if (\n        #     not self.onnx_trace\n        #     and not is_tpu  # don't use PyTorch version on TPUs\n        #     and incremental_state is None\n        #     and not static_kv\n        #     # A workaround for quantization to work. Otherwise JIT compilation\n        #     # treats bias in linear module as method.\n        #     and not torch.jit.is_scripting()\n        #     # The Multihead attention implemented in pytorch forces strong dimension check\n        #     # for input embedding dimention and K,Q,V projection dimension.\n        #     # Since pruning will break the dimension check and it is not easy to modify the pytorch API,\n        #     # it is preferred to bypass the pytorch MHA when we need to skip embed_dim_check\n        #     and not self.skip_embed_dim_check\n        # ):\n        #     assert key is not None and value is not None\n\n        # if self.use_xformers:\n        #     return self._xformers_attn_forward(\n        #         query, key, value, key_padding_mask, need_weights, attn_mask\n        #     )\n\n        # else:\n        #     return F.multi_head_attention_forward(\n        #         query,\n        #         key,\n        #         value,\n        #         self.embed_dim,\n        #         self.num_heads,\n        #         torch.empty([0]),\n        #         torch.cat((self.q_proj.bias, self.k_proj.bias, self.v_proj.bias)),\n        #         self.bias_k,\n        #         self.bias_v,\n        #         self.add_zero_attn,\n        #         self.dropout_module.p,\n        #         self.out_proj.weight,\n        #         self.out_proj.bias,\n        #         self.training or self.dropout_module.apply_during_inference,\n        #         key_padding_mask,\n        #         need_weights,\n        #         attn_mask,\n        #         use_separate_proj_weight=True,\n        #         q_proj_weight=self.q_proj.weight,\n        #         k_proj_weight=self.k_proj.weight,\n        #         v_proj_weight=self.v_proj.weight,\n        #     )\n\n        if incremental_state is not None:\n            saved_state = self._get_input_buffer(incremental_state)\n            if saved_state is not None and \"prev_key\" in saved_state:\n                # previous time steps are cached - no need to recompute\n                # key and value if they are static\n                if static_kv:\n                    assert self.encoder_decoder_attention and not self.self_attention\n                    key = value = None\n        else:\n            saved_state = None\n\n        if self.self_attention:\n            q = self.q_proj(query)\n            k = self.k_proj(query)\n            v = self.v_proj(query)\n        elif self.encoder_decoder_attention:\n            # encoder-decoder attention\n            q = self.q_proj(query)\n            if key is None:\n                assert value is None\n                k = v = None\n            else:\n                if self.beam_size > 1 and bsz == key.size(1):\n                    # key is [T, bsz*beam_size, C], reduce to [T, bsz, C]\n                    key = key.reshape(\n                        [key.size(0), -1, self.beam_size,\n                         key.size(2)])[:, :, 0, :]\n                    if key_padding_mask is not None:\n                        key_padding_mask = key_padding_mask.reshape(\n                            [-1, self.beam_size,\n                             key_padding_mask.size(1)])[:, 0, :]\n                k = self.k_proj(key)\n                v = self.v_proj(key)\n\n        else:\n            assert key is not None and value is not None\n            q = self.q_proj(query)\n            k = self.k_proj(key)\n            v = self.v_proj(value)\n        q *= self.scaling\n\n        if self.bias_k is not None:\n            assert self.bias_v is not None\n            k, v, attn_mask, key_padding_mask = self._add_bias(\n                k, v, attn_mask, key_padding_mask, bsz)\n\n        q = paddle.reshape(\n            q, [tgt_len, bsz * self.num_heads, self.head_dim]).transpose(\n                [1, 0, 2])\n        kv_bsz = bsz  # need default value for scripting\n        if k is not None:\n            kv_bsz = k.shape[1]\n            k = paddle.reshape(\n                k, [-1, kv_bsz * self.num_heads, self.head_dim]).transpose(\n                    [1, 0, 2])\n        if v is not None:\n            v = paddle.reshape(\n                v, [-1, kv_bsz * self.num_heads, self.head_dim]).transpose(\n                    [1, 0, 2])\n\n        if saved_state is not None:\n            # saved states are stored with shape (bsz, num_heads, seq_len, head_dim)\n            if \"prev_key\" in saved_state:\n                _prev_key = saved_state[\"prev_key\"]\n                assert _prev_key is not None\n                kv_bsz = _prev_key.shape[0]\n                prev_key = _prev_key.reshape(\n                    [kv_bsz * self.num_heads, -1, self.head_dim])\n                if static_kv:\n                    k = prev_key\n                else:\n                    assert k is not None\n                    k = paddle.concat([prev_key, k], axis=1)\n                src_len = k.shape[1]\n            if \"prev_value\" in saved_state:\n                _prev_value = saved_state[\"prev_value\"]\n                assert _prev_value is not None\n                assert kv_bsz == _prev_value.size(0)\n                prev_value = _prev_value.reshape(\n                    [kv_bsz * self.num_heads, -1, self.head_dim])\n                if static_kv:\n                    v = prev_value\n                else:\n                    assert v is not None\n                    v = paddle.concat([prev_value, v], axis=1)\n            prev_key_padding_mask: Optional[Tensor] = None\n            if \"prev_key_padding_mask\" in saved_state:\n                prev_key_padding_mask = saved_state[\"prev_key_padding_mask\"]\n            assert k is not None and v is not None\n            key_padding_mask = MultiheadAttention._append_prev_key_padding_mask(\n                key_padding_mask=key_padding_mask,\n                prev_key_padding_mask=prev_key_padding_mask,\n                batch_size=kv_bsz,\n                src_len=k.shape[1],\n                static_kv=static_kv, )\n\n            saved_state[\"prev_key\"] = k.reshape(\n                [kv_bsz, self.num_heads, -1, self.head_dim])\n            saved_state[\"prev_value\"] = v.reshape(\n                [kv_bsz, self.num_heads, -1, self.head_dim])\n            saved_state[\"prev_key_padding_mask\"] = key_padding_mask\n            # In this branch incremental_state is never None\n            assert incremental_state is not None\n            incremental_state = self._set_input_buffer(incremental_state,\n                                                       saved_state)\n        assert k is not None\n        assert k.shape[1] == src_len\n\n        # This is part of a workaround to get around fork/join parallelism\n        # not supporting Optional types.\n        if key_padding_mask is not None and key_padding_mask.dim() == 0:\n            key_padding_mask = None\n\n        if key_padding_mask is not None:\n            assert key_padding_mask.shape[0] == kv_bsz\n            assert key_padding_mask.shape[1] == src_len\n\n        if self.add_zero_attn:\n            assert v is not None\n            src_len += 1\n            k, v, key_padding_mask, attn_mask = self._append_zero_attn(\n                k=k,\n                v=v,\n                key_padding_mask=key_padding_mask,\n                attn_mask=attn_mask)\n\n        if self.encoder_decoder_attention and bsz != kv_bsz:\n            attn_weights = paddle.einsum(\n                \"bxhtd,bhsd->bxhts\",\n                q.reshape([kv_bsz, -1, self.num_heads] + q.shape[1:]),\n                k.reshape([kv_bsz, self.num_heads] + k.shape[1:]), )\n            attn_weights = attn_weights.reshape([\n                -1,\n            ] + attn_weights.shape[-2:])\n        else:\n            attn_weights = paddle.bmm(q, k.transpose([0, 2, 1]))\n        attn_weights = self.apply_sparse_mask(attn_weights, tgt_len, src_len,\n                                              bsz)\n\n        assert list(\n            attn_weights.shape) == [bsz * self.num_heads, tgt_len, src_len]\n\n        if attn_mask is not None:\n            attn_mask = attn_mask.unsqueeze(0)\n            if self.onnx_trace:\n                attn_mask = attn_mask.tile([attn_weights.shape[0], 1, 1])\n            attn_weights += attn_mask\n\n        if key_padding_mask is not None:\n            # don't attend to padding symbols\n            attn_weights = attn_weights.reshape(\n                [bsz, self.num_heads, tgt_len, src_len])\n            if not is_tpu:\n                attn_weights = attn_weights.reshape(\n                    [kv_bsz, -1, self.num_heads, tgt_len, src_len])\n                attn_weights = paddle.where(\n                    key_padding_mask.unsqueeze(1).unsqueeze(2).unsqueeze(3)\n                    .astype('bool'),\n                    float('-inf') * paddle.ones_like(attn_weights),\n                    attn_weights)\n            else:\n                attn_weights = attn_weights.transpose([2, 1, 0])\n                attn_weights = paddle.where(key_padding_mask,\n                                            float('-inf') *\n                                            paddle.ones_like(attn_weights),\n                                            attn_weights)\n                attn_weights = attn_weights.transpose([2, 1, 0])\n            attn_weights = attn_weights.reshape(\n                [bsz * self.num_heads, tgt_len, src_len])\n\n        if before_softmax:\n            return attn_weights, v\n\n        def softmax_supporting_onnx_trace(x, dim: int, onnx_trace: bool=False):\n            if onnx_trace:\n                return F.softmax(x, axis=dim)\n            else:\n                return F.softmax(x, axis=dim, dtype='float32')\n\n        attn_weights_float = softmax_supporting_onnx_trace(\n            attn_weights, dim=-1, onnx_trace=self.onnx_trace)\n        attn_weights = paddle.cast(attn_weights_float, attn_weights.dtype)\n        attn_probs = self.dropout_module(attn_weights)\n\n        assert v is not None\n        if self.encoder_decoder_attention and bsz != kv_bsz:\n            attn = paddle.einsum(\n                \"bxhts,bhsd->bxhtd\",\n                attn_probs.reshape([kv_bsz, -1, self.num_heads] +\n                                   attn_probs.shape[1:]),\n                v.reshape([kv_bsz, self.num_heads] + v.shape[1:]), )\n            attn = attn.reshape([\n                -1,\n            ] + attn.shape[-2:])\n        else:\n            attn = paddle.bmm(attn_probs, v)\n        assert list(\n            attn.shape) == [bsz * self.num_heads, tgt_len, self.head_dim]\n        if self.onnx_trace and attn.shape[1] == 1:\n            # when ONNX tracing a single decoder step (sequence length == 1)\n            # the transpose is a no-op copy before view, thus unnecessary\n            attn = attn.reshape([tgt_len, bsz, self.embed_dim])\n        else:\n            attn = attn.transpose([1, 0, 2]).reshape(\n                [tgt_len, bsz, self.embed_dim])\n        attn = self.out_proj(attn)\n        attn_weights: Optional[Tensor] = None\n        if need_weights:\n            attn_weights = attn_weights_float.reshape(\n                [bsz, self.num_heads, tgt_len, src_len]).transpose([1, 0, 2, 3])\n            if not need_head_weights:\n                # average attention weights over heads\n                attn_weights = attn_weights.mean(axis=0)\n\n        return attn, attn_weights\n\n    @staticmethod\n    def _append_prev_key_padding_mask(\n            key_padding_mask: Optional[Tensor],\n            prev_key_padding_mask: Optional[Tensor],\n            batch_size: int,\n            src_len: int,\n            static_kv: bool, ) -> Optional[Tensor]:\n        # saved key padding masks have shape (bsz, seq_len)\n        if prev_key_padding_mask is not None and static_kv:\n            new_key_padding_mask = prev_key_padding_mask\n        elif prev_key_padding_mask is not None and key_padding_mask is not None:\n            new_key_padding_mask = paddle.concat(\n                [\n                    paddle.cast(prev_key_padding_mask, 'float32'),\n                    paddle.cast(key_padding_mask, 'float32')\n                ],\n                axis=1)\n        # During incremental decoding, as the padding token enters and\n        # leaves the frame, there will be a time when prev or current\n        # is None\n        elif prev_key_padding_mask is not None:\n            if src_len > prev_key_padding_mask.shape[1]:\n                filler = paddle.zeros(\n                    [batch_size, src_len - prev_key_padding_mask.shape[1]], )\n                new_key_padding_mask = paddle.concat(\n                    [\n                        paddle.cast(prev_key_padding_mask, 'float32'),\n                        paddle.cast(filler, 'float32')\n                    ],\n                    axis=1)\n            else:\n                new_key_padding_mask = prev_key_padding_mask\n        elif key_padding_mask is not None:\n            if src_len > key_padding_mask.shape[1]:\n                filler = paddle.zeros(\n                    [batch_size, src_len - key_padding_mask.shape[1]], )\n                new_key_padding_mask = paddle.concat(\n                    [\n                        paddle.cast(filler, 'float32'),\n                        paddle.cast(key_padding_mask, 'float32')\n                    ],\n                    axis=1)\n            else:\n                new_key_padding_mask = paddle.cast(key_padding_mask, 'float32')\n        else:\n            new_key_padding_mask = prev_key_padding_mask\n        return new_key_padding_mask\n\n    @paddle.jit.to_static\n    def reorder_incremental_state(\n            self,\n            incremental_state: Dict[str, Dict[str, Optional[Tensor]]],\n            new_order: Tensor, ):\n        \"\"\"Reorder buffered internal state (for incremental generation).\"\"\"\n        input_buffer = self._get_input_buffer(incremental_state)\n        if input_buffer is not None:\n            for k in input_buffer.keys():\n                input_buffer_k = input_buffer[k]\n                if input_buffer_k is not None:\n                    if self.encoder_decoder_attention:\n                        if input_buffer_k.shape[\n                                0] * self.beam_size == new_order.shape[0]:\n                            return incremental_state\n                        elif self.beam_size > 1:\n                            input_buffer[k] = paddle.index_select(\n                                input_buffer_k,\n                                index=new_order.reshape(\n                                    [-1, self.beam_size])[:, 0] //\n                                self.beam_size,\n                                axis=0, )\n                        else:\n                            input_buffer[k] = paddle.index_select(\n                                input_buffer_k, index=new_order, axis=0)\n                    else:\n                        input_buffer[k] = paddle.index_select(\n                            input_buffer_k, index=new_order, axis=0)\n            incremental_state = self._set_input_buffer(incremental_state,\n                                                       input_buffer)\n        return incremental_state\n\n    def set_beam_size(self, beam_size):\n        \"\"\"Used for effiecient beamable enc-dec attention\"\"\"\n        self.beam_size = beam_size\n\n    def _get_input_buffer(\n            self,\n            incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]]\n    ) -> Dict[str, Optional[Tensor]]:\n        result = self.get_incremental_state(incremental_state, \"attn_state\")\n        if result is not None:\n            return result\n        else:\n            empty_result: Dict[str, Optional[Tensor]] = {}\n            return empty_result\n\n    def _set_input_buffer(\n            self,\n            incremental_state: Dict[str, Dict[str, Optional[Tensor]]],\n            buffer: Dict[str, Optional[Tensor]], ):\n        return self.set_incremental_state(incremental_state, \"attn_state\",\n                                          buffer)\n\n    def apply_sparse_mask(self,\n                          attn_weights,\n                          tgt_len: int,\n                          src_len: int,\n                          bsz: int):\n        return attn_weights\n\n    def upgrade_state_dict_named(self, state_dict, name):\n        prefix = name + \".\" if name != \"\" else \"\"\n        items_to_add = {}\n        keys_to_remove = []\n        for k in state_dict.keys():\n            if k.endswith(prefix + \"in_proj_weight\"):\n                # in_proj_weight used to be q + k + v with same dimensions\n                dim = int(state_dict[k].shape[0] / 3)\n                items_to_add[prefix + \"q_proj.weight\"] = state_dict[k][:dim]\n                items_to_add[prefix +\n                             \"k_proj.weight\"] = state_dict[k][dim:2 * dim]\n                items_to_add[prefix + \"v_proj.weight\"] = state_dict[k][2 * dim:]\n\n                keys_to_remove.append(k)\n\n                k_bias = prefix + \"in_proj_bias\"\n                if k_bias in state_dict.keys():\n                    dim = int(state_dict[k].shape[0] / 3)\n                    items_to_add[prefix +\n                                 \"q_proj.bias\"] = state_dict[k_bias][:dim]\n                    items_to_add[prefix + \"k_proj.bias\"] = state_dict[k_bias][\n                        dim:2 * dim]\n                    items_to_add[prefix +\n                                 \"v_proj.bias\"] = state_dict[k_bias][2 * dim:]\n\n                    keys_to_remove.append(prefix + \"in_proj_bias\")\n\n        for k in keys_to_remove:\n            del state_dict[k]\n\n        for key, value in items_to_add.items():\n            state_dict[key] = value\n\n\nclass GumbelVectorQuantizer(nn.Layer):\n    def __init__(\n            self,\n            dim,\n            num_vars,\n            temp,\n            groups,\n            combine_groups,\n            vq_dim,\n            time_first,\n            activation=nn.GELU(),\n            weight_proj_depth=1,\n            weight_proj_factor=1, ):\n        \"\"\"Vector quantization using gumbel softmax\n\n        Args:\n            dim: input dimension (channels)\n            num_vars: number of quantized vectors per group\n            temp: temperature for training. this should be a tuple of 3 elements: (start, stop, decay factor)\n            groups: number of groups for vector quantization\n            combine_groups: whether to use the vectors for all groups\n            vq_dim: dimensionality of the resulting quantized vector\n            time_first: if true, expect input in BxTxC format, otherwise in BxCxT\n            activation: what activation to use (should be a module). this is only used if weight_proj_depth is > 1\n            weight_proj_depth: number of layers (with activation in between) to project input before computing logits\n            weight_proj_factor: this is used only if weight_proj_depth is > 1. scales the inner dimensionality of\n                                projections by this factor\n        \"\"\"\n        super().__init__()\n\n        self.groups = groups\n        self.combine_groups = combine_groups\n        self.input_dim = dim\n        self.num_vars = num_vars\n        self.time_first = time_first\n\n        assert (\n            vq_dim % groups == 0\n        ), f\"dim {vq_dim} must be divisible by groups {groups} for concatenation\"\n\n        var_dim = vq_dim // groups\n        num_groups = groups if not combine_groups else 1\n\n        self.vars = self.create_parameter(\n            (1, num_groups * num_vars, var_dim),\n            default_initializer=nn.initializer.Uniform())\n\n        if weight_proj_depth > 1:\n\n            def block(input_dim, output_dim):\n                return nn.Sequential(Linear(input_dim, output_dim), activation)\n\n            inner_dim = self.input_dim * weight_proj_factor\n            self.weight_proj = nn.Sequential(\n                *[\n                    block(self.input_dim if i == 0 else inner_dim, inner_dim)\n                    for i in range(weight_proj_depth - 1)\n                ],\n                Linear(inner_dim, groups * num_vars), )\n        else:\n            self.weight_proj = Linear(\n                self.input_dim,\n                groups * num_vars,\n                weight_attr=nn.initializer.Normal(mean=0, std=1),\n                bias_attr=nn.initializer.Zero())\n\n        if isinstance(temp, str):\n            import ast\n\n            temp = ast.literal_eval(temp)\n        assert len(temp) == 3, f\"{temp}, {len(temp)}\"\n\n        self.max_temp, self.min_temp, self.temp_decay = temp\n        self.curr_temp = self.max_temp\n        self.codebook_indices = None\n\n    def set_num_updates(self, num_updates):\n        self.curr_temp = max(self.max_temp * self.temp_decay**num_updates,\n                             self.min_temp)\n\n    def get_codebook_indices(self):\n        if self.codebook_indices is None:\n            from itertools import product\n\n            p = [range(self.num_vars)] * self.groups\n            inds = list(product(*p))\n            self.codebook_indices = paddle.to_tensor(\n                inds, dtype='int64', place=self.vars.place).flatten()\n\n            if not self.combine_groups:\n                self.codebook_indices = self.codebook_indices.reshape(\n                    self.num_vars**self.groups, -1)\n                for b in range(1, self.groups):\n                    self.codebook_indices[:, b] += self.num_vars * b\n                self.codebook_indices = self.codebook_indices.flatten()\n        return self.codebook_indices\n\n    def codebook(self):\n        indices = self.get_codebook_indices()\n        return (self.vars.squeeze(0).index_select(0, indices)\n                .reshape(self.num_vars**self.groups, -1))\n\n    def sample_from_codebook(self, b, n):\n        indices = self.get_codebook_indices()\n        indices = indices.reshape(-1, self.groups)\n        cb_size = indices.shape[0]\n        assert (n < cb_size\n                ), f\"sample size {n} is greater than size of codebook {cb_size}\"\n        sample_idx = paddle.randint(low=0, high=cb_size, shape=(b * n, ))\n        indices = indices[sample_idx]\n\n        z = self.vars.squeeze(0).index_select(0, indices.flatten()).reshape(\n            b, n, -1)\n        return z\n\n    def to_codebook_index(self, indices):\n        res = paddle.full(indices.shape[:-1], 0, dtype=indices.dtype)\n        for i in range(self.groups):\n            exponent = self.groups - i - 1\n            res += indices[..., i] * (self.num_vars**exponent)\n        return res\n\n    def forward_idx(self, x):\n        res = self.forward(x, produce_targets=True)\n        return res[\"x\"], res[\"targets\"]\n\n    def forward(self, x, produce_targets=False):\n        result = {\"num_vars\": self.num_vars * self.groups}\n\n        if not self.time_first:\n            x = x.transpose([0, 2, 1])\n\n        bsz, tsz, fsz = x.shape\n        x = x.reshape([-1, fsz])\n        x = self.weight_proj(x)\n        x = x.reshape([bsz * tsz * self.groups, -1])\n\n        _, k = x.max(-1)\n        hard_x = paddle.zeros_like(x)\n        hard_x.scatter_(-1, k.reshape([-1, 1]), 1.0)\n        hard_x = hard_x.reshape([bsz * tsz, self.groups, -1])\n        hard_probs = paddle.mean(hard_x.astype('float32'), axis=0)\n        result[\"code_perplexity\"] = paddle.exp(-paddle.sum(\n            hard_probs * paddle.log(hard_probs + 1e-7), axis=-1)).sum()\n\n        avg_probs = F.softmax(\n            x.reshape([bsz * tsz, self.groups, -1]).astype('float32'),\n            axis=-1).mean(axis=0)\n        result[\"prob_perplexity\"] = paddle.exp(-paddle.sum(\n            avg_probs * paddle.log(avg_probs + 1e-7), axis=-1)).sum()\n\n        result[\"temp\"] = self.curr_temp\n\n        if self.training:\n            x = F.gumbel_softmax(\n                x.astype('float32'), temperature=self.curr_temp,\n                hard=True).astype(x.dtype)\n        else:\n            x = hard_x\n\n        x = x.reshape([bsz * tsz, -1])\n\n        vars = self.vars\n        if self.combine_groups:\n            vars = vars.tile([1, self.groups, 1])\n\n        if produce_targets:\n            result[\"targets\"] = (x.reshape([bsz * tsz * self.groups, -1])\n                                 .argmax(axis=-1)\n                                 .reshape([bsz, tsz, self.groups]).detach())\n\n        x = x.unsqueeze(-1) * vars\n        x = x.reshape([bsz * tsz, self.groups, self.num_vars, -1])\n        x = x.sum(axis=-2)\n        x = x.reshape([bsz, tsz, -1])\n\n        if not self.time_first:\n            x = x.transpose([0, 2, 1])\n\n        result[\"x\"] = x\n\n        return result\n\n\nclass GradMultiply(paddle.autograd.PyLayer):\n    @staticmethod\n    def forward(ctx, x, scale):\n        ctx.scale = scale\n        res = x.numpy().copy()\n        return paddle.to_tensor(res, dtype=x.dtype)\n\n    @staticmethod\n    def backward(ctx, grad):\n        return grad * ctx.scale, None\n\n\nclass SamePad(nn.Layer):\n    def __init__(self, kernel_size, causal=False):\n        super().__init__()\n        if causal:\n            self.remove = kernel_size - 1\n        else:\n            self.remove = 1 if kernel_size % 2 == 0 else 0\n\n    def forward(self, x):\n        if self.remove > 0:\n            x = x[:, :, :-self.remove]\n        return x\n\n\nclass TransposeLast(nn.Layer):\n    def __init__(self, deconstruct_idx=None):\n        super().__init__()\n        self.deconstruct_idx = deconstruct_idx\n\n    def forward(self, x):\n        if self.deconstruct_idx is not None:\n            x = x[self.deconstruct_idx]\n        trans_dim = np.arange(x.dim())\n        trans_dim[-1], trans_dim[-2] = trans_dim[-2], trans_dim[-1]\n        return x.transpose(trans_dim)\n\n\nclass Fp32LayerNorm(LayerNorm):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n    def forward(self, input):\n        output = F.layer_norm(\n            input.astype('float32'),\n            self._normalized_shape,\n            self.weight.astype('float32') if self.weight is not None else None,\n            self.bias.astype('float32') if self.bias is not None else None,\n            self._epsilon, )\n        return output.astype(input.dtype)\n\n\n# Todo: change this when paddle supports F.group_norm\nclass Fp32GroupNorm(nn.Layer):\n    def __init__(self, *args, **kwargs):\n        super().__init__()\n        self.group_norm = paddle.nn.GroupNorm(*args, **kwargs)\n        fp32_weight = paddle.create_parameter(\n            shape=self.group_norm.weight.shape,\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.Assign(\n                self.group_norm.weight))\n        fp32_bias = paddle.create_parameter(\n            shape=self.group_norm.bias.shape,\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.Assign(\n                self.group_norm.bias))\n        self.group_norm.weight = fp32_weight\n        self.group_norm.bias = fp32_bias\n\n    def forward(self, input):\n        output = self.group_norm(input.astype('float32'))\n        return output.astype(input.dtype)\n\n\nclass StrEnumMeta(EnumMeta):\n    # this is workaround for submitit pickling leading to instance checks failing in hydra for StrEnum, see\n    # https://github.com/facebookresearch/hydra/issues/1156\n    @classmethod\n    def __instancecheck__(cls, other):\n        return \"enum\" in str(type(other))\n\n\nclass StrEnum(Enum, metaclass=StrEnumMeta):\n    def __str__(self):\n        return self.value\n\n    def __eq__(self, other: str):\n        return self.value == other\n\n    def __repr__(self):\n        return self.value\n\n    def __hash__(self):\n        return hash(str(self))\n\n\ndef ChoiceEnum(choices: List[str]):\n    \"\"\"return the Enum class used to enforce list of choices\"\"\"\n    return StrEnum(\"Choices\", {k: k for k in choices})\n\n\ndef relu_squared(x: paddle.Tensor):\n    return F.relu(x).pow(2)\n\n\ndef get_activation_fn(activation: str) -> Callable:\n    \"\"\"Returns the activation function corresponding to `activation`\"\"\"\n\n    def gelu_accurate(x):\n        if not hasattr(gelu_accurate, \"_a\"):\n            gelu_accurate._a = math.sqrt(2 / math.pi)\n        return (0.5 * x * (1 + paddle.tanh(gelu_accurate._a *\n                                           (x + 0.044715 * paddle.pow(x, 3)))))\n\n    def gelu(x: paddle.Tensor) -> paddle.Tensor:\n        return paddle.nn.functional.gelu(x.astype('float32')).astype(x.dtype)\n\n    if activation == \"relu\":\n        return F.relu\n    elif activation == \"relu_squared\":\n        return relu_squared\n    elif activation == \"gelu\":\n        return gelu\n    elif activation == \"gelu_fast\":\n        return gelu_accurate\n    elif activation == \"gelu_accurate\":\n        return gelu_accurate\n    elif activation == \"tanh\":\n        return paddle.tanh\n    elif activation == \"linear\":\n        return lambda x: x\n    elif activation == \"swish\":\n        return paddle.nn.Swish\n    else:\n        raise RuntimeError(\n            \"--activation-fn {} not supported\".format(activation))\n\n\ndef get_available_activation_fns() -> List:\n    return [\n        \"relu\",\n        \"gelu\",\n        \"gelu_fast\",  # deprecated\n        \"gelu_accurate\",\n        \"tanh\",\n        \"linear\",\n    ]\n\n\ndef compute_mask_indices(\n        shape: Tuple[int, int],\n        padding_mask: Optional[paddle.Tensor],\n        mask_prob: float,\n        mask_length: int,\n        mask_type: str=\"static\",\n        mask_other: float=0.0,\n        min_masks: int=0,\n        no_overlap: bool=False,\n        min_space: int=0,\n        require_same_masks: bool=True,\n        mask_dropout: float=0.0, ) -> np.ndarray:\n    \"\"\"\n    Computes random mask spans for a given shape\n\n    Args:\n        shape: the the shape for which to compute masks.\n            should be of size 2 where first element is batch size and 2nd is timesteps\n        padding_mask: optional padding mask of the same size as shape, which will prevent masking padded elements\n        mask_prob: probability for each token to be chosen as start of the span to be masked. this will be multiplied by\n            number of timesteps divided by length of mask span to mask approximately this percentage of all elements.\n            however due to overlaps, the actual number will be smaller (unless no_overlap is True)\n        mask_type: how to compute mask lengths\n            static = fixed size\n            uniform = sample from uniform distribution [mask_other, mask_length*2]\n            normal = sample from normal distribution with mean mask_length and stdev mask_other. mask is min 1 element\n            poisson = sample from possion distribution with lambda = mask length\n        min_masks: minimum number of masked spans\n        no_overlap: if false, will switch to an alternative recursive algorithm that prevents spans from overlapping\n        min_space: only used if no_overlap is True, this is how many elements to keep unmasked between spans\n        require_same_masks: if true, will randomly drop out masks until same amount of masks remains in each sample\n        mask_dropout: randomly dropout this percentage of masks in each example\n    \"\"\"\n\n    bsz, all_sz = shape\n    mask = np.full((bsz, all_sz), False)\n\n    all_num_mask = int(\n        # add a random number for probabilistic rounding\n        mask_prob * all_sz / float(mask_length) + np.random.rand())\n\n    all_num_mask = max(min_masks, all_num_mask)\n\n    mask_idcs = []\n    for i in range(bsz):\n        if padding_mask is not None:\n            sz = all_sz - padding_mask[i].long().sum().item()\n            num_mask = int(\n                # add a random number for probabilistic rounding\n                mask_prob * sz / float(mask_length) + np.random.rand())\n            num_mask = max(min_masks, num_mask)\n        else:\n            sz = all_sz\n            num_mask = all_num_mask\n\n        if mask_type == \"static\":\n            lengths = np.full(num_mask, mask_length)\n        elif mask_type == \"uniform\":\n            lengths = np.random.randint(\n                mask_other, mask_length * 2 + 1, size=num_mask)\n        elif mask_type == \"normal\":\n            lengths = np.random.normal(mask_length, mask_other, size=num_mask)\n            lengths = [max(1, int(round(x))) for x in lengths]\n        elif mask_type == \"poisson\":\n            lengths = np.random.poisson(mask_length, size=num_mask)\n            lengths = [int(round(x)) for x in lengths]\n        else:\n            raise Exception(\"unknown mask selection \" + mask_type)\n\n        if sum(lengths) == 0:\n            lengths[0] = min(mask_length, sz - 1)\n\n        if no_overlap:\n            mask_idc = []\n\n            def arrange(s, e, length, keep_length):\n                span_start = np.random.randint(s, e - length)\n                mask_idc.extend(span_start + i for i in range(length))\n\n                new_parts = []\n                if span_start - s - min_space >= keep_length:\n                    new_parts.append((s, span_start - min_space + 1))\n                if e - span_start - length - min_space > keep_length:\n                    new_parts.append((span_start + length + min_space, e))\n                return new_parts\n\n            parts = [(0, sz)]\n            min_length = min(lengths)\n            for length in sorted(lengths, reverse=True):\n                lens = np.fromiter(\n                    (e - s if e - s >= length + min_space else 0\n                     for s, e in parts),\n                    np.int_, )\n                l_sum = np.sum(lens)\n                if l_sum == 0:\n                    break\n                probs = lens / np.sum(lens)\n                c = np.random.choice(len(parts), p=probs)\n                s, e = parts.pop(c)\n                parts.extend(arrange(s, e, length, min_length))\n            mask_idc = np.asarray(mask_idc)\n        else:\n            min_len = min(lengths)\n            if sz - min_len <= num_mask:\n                min_len = sz - num_mask - 1\n\n            mask_idc = np.random.choice(sz - min_len, num_mask, replace=False)\n\n            mask_idc = np.asarray([\n                mask_idc[j] + offset\n                for j in range(len(mask_idc)) for offset in range(lengths[j])\n            ])\n\n        mask_idcs.append(np.unique(mask_idc[mask_idc < sz]))\n\n    min_len = min([len(m) for m in mask_idcs])\n    for i, mask_idc in enumerate(mask_idcs):\n        if len(mask_idc) > min_len and require_same_masks:\n            mask_idc = np.random.choice(mask_idc, min_len, replace=False)\n        if mask_dropout > 0:\n            num_holes = np.rint(len(mask_idc) * mask_dropout).astype(int)\n            mask_idc = np.random.choice(\n                mask_idc, len(mask_idc) - num_holes, replace=False)\n\n        mask[i, mask_idc] = True\n\n    return mask\n\n\ndef index_put(tensor, indices, value):\n    tensor[indices] = value\n    return tensor\n\n\n# ToDo if faster?\ndef buffered_arange(max):\n    if not hasattr(buffered_arange, \"buf\"):\n        buffered_arange.buf = paddle.empty([max], dtype='int64')\n    if max > buffered_arange.buf.numel():\n        buffered_arange.buf = paddle.arange(max)\n    return buffered_arange.buf[:max]\n\n\ndef pad_to_multiple(x, multiple, dim=-1, value=0):\n    # Inspired from https://github.com/lucidrains/local-attention/blob/master/local_attention/local_attention.py#L41\n    if x is None:\n        return None, 0\n    tsz = x.shape[dim]\n    m = tsz / multiple\n    remainder = math.ceil(m) * multiple - tsz\n    if m.is_integer():\n        return x, 0\n    pad_offset = (0, ) * (-1 - dim) * 2\n    return F.pad(\n        x,\n        pad=[*pad_offset, 0, remainder, *pad_offset],\n        value=value,\n        data_format='NLC'), remainder\n\n\nEXTRACTOR_MODE_CHOICES = ChoiceEnum([\"default\", \"layer_norm\"])\nMASKING_DISTRIBUTION_CHOICES = ChoiceEnum(\n    [\"static\", \"uniform\", \"normal\", \"poisson\"])\nLAYER_TYPE_CHOICES = ChoiceEnum([\"transformer\"])  # ToDo: conformer \n\n\n@dataclass\nclass Wav2Vec2Config:\n    extractor_mode: EXTRACTOR_MODE_CHOICES = field(\n        default=\"default\",\n        metadata={\n            \"help\":\n            \"mode for feature extractor. default has a single group norm with d \"\n            \"groups in the first conv block, whereas layer_norm has layer norms in \"\n            \"every block (meant to use with normalize=True)\"\n        }, )\n    encoder_layers: int = field(\n        default=12, metadata={\"help\": \"num encoder layers in the transformer\"})\n    encoder_embed_dim: int = field(\n        default=768, metadata={\"help\": \"encoder embedding dimension\"})\n    encoder_ffn_embed_dim: int = field(\n        default=3072, metadata={\"help\": \"encoder embedding dimension for FFN\"})\n    encoder_attention_heads: int = field(\n        default=12, metadata={\"help\": \"num encoder attention heads\"})\n    activation_fn: ChoiceEnum(get_available_activation_fns()) = field(\n        default=\"gelu\", metadata={\"help\": \"activation function to use\"})\n    layer_type: LAYER_TYPE_CHOICES = field(\n        default=\"transformer\", metadata={\"help\": \"layer type in encoder\"})\n    # dropouts\n    dropout: float = field(\n        default=0.1,\n        metadata={\"help\": \"dropout probability for the transformer\"})\n    attention_dropout: float = field(\n        default=0.1,\n        metadata={\"help\": \"dropout probability for attention weights\"})\n    activation_dropout: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout probability after activation in FFN\"})\n    encoder_layerdrop: float = field(\n        default=0.0,\n        metadata={\"help\": \"probability of dropping a tarnsformer layer\"})\n    dropout_input: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout to apply to the input (after feat extr)\"}, )\n    dropout_features: float = field(\n        default=0.0,\n        metadata={\"help\": \"dropout to apply to the features (after feat extr)\"},\n    )\n\n    final_dim: int = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"project final representations and targets to this many dimensions.\"\n            \"set to encoder_embed_dim is <= 0\"\n        }, )\n    layer_norm_first: bool = field(\n        default=False,\n        metadata={\"help\": \"apply layernorm first in the transformer\"})\n    conv_feature_layers: str = field(\n        default=\"[(512, 10, 5)] + [(512, 3, 2)] * 4 + [(512,2,2)] + [(512,2,2)]\",\n        metadata={\n            \"help\":\n            \"string describing convolutional feature extraction layers in form of a python list that contains \"\n            \"[(dim, kernel_size, stride), ...]\"\n        }, )\n    conv_bias: bool = field(\n        default=False, metadata={\"help\": \"include bias in conv encoder\"})\n    logit_temp: float = field(\n        default=0.1, metadata={\"help\": \"temperature to divide logits by\"})\n    quantize_targets: bool = field(\n        default=False, metadata={\"help\": \"use quantized targets\"})\n    quantize_input: bool = field(\n        default=False, metadata={\"help\": \"use quantized inputs\"})\n    same_quantizer: bool = field(\n        default=False,\n        metadata={\"help\": \"use same quantizer for inputs and targets\"})\n    target_glu: bool = field(\n        default=False, metadata={\"help\": \"adds projection + glu to targets\"})\n    feature_grad_mult: float = field(\n        default=1.0,\n        metadata={\"help\": \"multiply feature extractor var grads by this\"})\n    quantizer_depth: int = field(\n        default=1,\n        metadata={\"help\": \"number of quantizer layers\"}, )\n    quantizer_factor: int = field(\n        default=3,\n        metadata={\n            \"help\":\n            \"dimensionality increase for inner quantizer layers (if depth > 1)\"\n        }, )\n    latent_vars: int = field(\n        default=320,\n        metadata={\n            \"help\": \"number of latent variables V in each group of the codebook\"\n        }, )\n    latent_groups: int = field(\n        default=2,\n        metadata={\n            \"help\": \"number of groups G of latent variables in the codebook\"\n        }, )\n    latent_dim: int = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"if > 0, uses this dimensionality for latent variables. \"\n            \"otherwise uses final_dim / latent_groups\"\n        }, )\n\n    # masking\n    mask_length: int = field(default=10, metadata={\"help\": \"mask length\"})\n    mask_prob: float = field(\n        default=0.65,\n        metadata={\"help\": \"probability of replacing a token with mask\"})\n    mask_selection: MASKING_DISTRIBUTION_CHOICES = field(\n        default=\"static\", metadata={\"help\": \"how to choose mask length\"})\n    mask_other: float = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"secondary mask argument (used for more complex distributions), \"\n            \"see help in compute_mask_indices\"\n        }, )\n    no_mask_overlap: bool = field(\n        default=False, metadata={\"help\": \"whether to allow masks to overlap\"})\n    mask_min_space: int = field(\n        default=1,\n        metadata={\"help\": \"min space between spans (if no overlap is enabled)\"},\n    )\n    require_same_masks: bool = field(\n        default=True,\n        metadata={\n            \"help\":\n            \"whether to number of masked timesteps must be the same across all \"\n            \"examples in a batch\"\n        }, )\n    mask_dropout: float = field(\n        default=0.0,\n        metadata={\"help\": \"percent of masks to unmask for each sample\"}, )\n\n    # channel masking\n    mask_channel_length: int = field(\n        default=10,\n        metadata={\"help\": \"length of the mask for features (channels)\"})\n    mask_channel_prob: float = field(\n        default=0.0,\n        metadata={\"help\": \"probability of replacing a feature with 0\"})\n    mask_channel_before: bool = False\n    mask_channel_selection: MASKING_DISTRIBUTION_CHOICES = field(\n        default=\"static\",\n        metadata={\"help\": \"how to choose mask length for channel masking\"}, )\n    mask_channel_other: float = field(\n        default=0,\n        metadata={\n            \"help\":\n            \"secondary mask argument (used for more complex distributions), \"\n            \"see help in compute_mask_indicesh\"\n        }, )\n    no_mask_channel_overlap: bool = field(\n        default=False,\n        metadata={\"help\": \"whether to allow channel masks to overlap\"})\n    mask_channel_min_space: int = field(\n        default=1,\n        metadata={\"help\": \"min space between spans (if no overlap is enabled)\"},\n    )\n\n    # negative selection\n    num_negatives: int = field(\n        default=100,\n        metadata={\"help\": \"number of negative examples from the same sample\"}, )\n    negatives_from_everywhere: bool = field(\n        default=False,\n        metadata={\n            \"help\": \"sample negatives from everywhere, not just masked states\"\n        }, )\n    cross_sample_negatives: int = field(\n        default=0,\n        metadata={\"help\": \"number of negative examples from the any sample\"})\n    codebook_negatives: int = field(\n        default=0, metadata={\"help\": \"number of negative examples codebook\"})\n\n    # positional embeddings\n    conv_pos: int = field(\n        default=128,\n        metadata={\n            \"help\": \"number of filters for convolutional positional embeddings\"\n        }, )\n    conv_pos_groups: int = field(\n        default=16,\n        metadata={\n            \"help\": \"number of groups for convolutional positional embedding\"\n        }, )\n    pos_conv_depth: int = field(\n        default=1,\n        metadata={\"help\": \"depth of positional encoder network\"}, )\n\n    latent_temp: Tuple[float, float, float] = field(\n        default=(2, 0.5, 0.999995),\n        metadata={\n            \"help\":\n            \"temperature for latent variable sampling. \"\n            \"can be tuple of 3 values (start, end, decay)\"\n        }, )\n    max_positions: int = field(\n        default=100000, metadata={\"help\": \"Max positions\"})\n    checkpoint_activations: bool = field(\n        default=False,\n        metadata={\n            \"help\": \"recompute activations and save memory for extra compute\"\n        }, )\n\n    # FP16 optimization\n    required_seq_len_multiple: int = field(\n        default=2,\n        metadata={\n            \"help\":\n            \"pad the input to encoder such that the sequence length is divisible by multiple\"\n        }, )\n    crop_seq_to_multiple: int = field(\n        default=1,\n        metadata={\n            \"help\":\n            \"crop convolutional feature extractor output such that the sequence length is divisible by multiple\"\n        }, )\n\n    # Conformer\n    depthwise_conv_kernel_size: int = field(\n        default=31,\n        metadata={\n            \"help\":\n            \"depthwise-conv-kernel-size for convolution in conformer layer\"\n        }, )\n    attn_type: str = field(\n        default=\"\",\n        metadata={\"help\": \"if espnet use ESPNET MHA\"}, )\n    pos_enc_type: str = field(\n        default=\"abs\",\n        metadata={\"help\": \"Positional encoding type to use in conformer\"}, )\n    fp16: bool = field(\n        default=False, metadata={\"help\": \"If fp16 is being used\"})\n\n\nclass Wav2Vec2Model(nn.Layer):\n    def __init__(self, cfg: Wav2Vec2Config):\n        super().__init__()\n        self.cfg = cfg\n\n        feature_enc_layers = eval(cfg.conv_feature_layers)\n        self.embed = feature_enc_layers[-1][0]\n\n        self.feature_extractor = ConvFeatureExtractionModel(\n            conv_layers=feature_enc_layers,\n            dropout=0.0,\n            mode=cfg.extractor_mode,\n            conv_bias=cfg.conv_bias, )\n\n        self.post_extract_proj = (Linear(self.embed, cfg.encoder_embed_dim)\n                                  if self.embed != cfg.encoder_embed_dim and\n                                  not cfg.quantize_input else None)\n\n        self.crop_seq_to_multiple = cfg.crop_seq_to_multiple\n\n        self.mask_prob = cfg.mask_prob\n        self.mask_selection = cfg.mask_selection\n        self.mask_other = cfg.mask_other\n        self.mask_length = cfg.mask_length\n        self.no_mask_overlap = cfg.no_mask_overlap\n        self.mask_min_space = cfg.mask_min_space\n\n        self.mask_channel_prob = cfg.mask_channel_prob\n        self.mask_channel_before = cfg.mask_channel_before\n        self.mask_channel_selection = cfg.mask_channel_selection\n        self.mask_channel_other = cfg.mask_channel_other\n        self.mask_channel_length = cfg.mask_channel_length\n        self.no_mask_channel_overlap = cfg.no_mask_channel_overlap\n        self.mask_channel_min_space = cfg.mask_channel_min_space\n\n        self.dropout_input = nn.Dropout(cfg.dropout_input)\n        self.dropout_features = nn.Dropout(cfg.dropout_features)\n\n        self.feature_grad_mult = cfg.feature_grad_mult\n\n        self.quantizer = None\n        self.input_quantizer = None\n\n        self.n_negatives = cfg.num_negatives\n        self.cross_sample_negatives = cfg.cross_sample_negatives\n        self.codebook_negatives = cfg.codebook_negatives\n        self.negatives_from_everywhere = cfg.negatives_from_everywhere\n\n        self.logit_temp = cfg.logit_temp\n\n        final_dim = cfg.final_dim if cfg.final_dim > 0 else cfg.encoder_embed_dim\n\n        if cfg.quantize_targets:\n            vq_dim = cfg.latent_dim if cfg.latent_dim > 0 else final_dim\n            self.quantizer = GumbelVectorQuantizer(\n                dim=self.embed,\n                num_vars=cfg.latent_vars,\n                temp=cfg.latent_temp,\n                groups=cfg.latent_groups,\n                combine_groups=False,\n                vq_dim=vq_dim,\n                time_first=True,\n                weight_proj_depth=cfg.quantizer_depth,\n                weight_proj_factor=cfg.quantizer_factor, )\n            self.project_q = Linear(vq_dim, final_dim)\n        else:\n            self.project_q = Linear(self.embed, final_dim)\n\n        if cfg.quantize_input:\n            if cfg.same_quantizer and self.quantizer is not None:\n                vq_dim = final_dim\n                self.input_quantizer = self.quantizer\n            else:\n                vq_dim = cfg.latent_dim if cfg.latent_dim > 0 else cfg.encoder_embed_dim\n                self.input_quantizer = GumbelVectorQuantizer(\n                    dim=self.embed,\n                    num_vars=cfg.latent_vars,\n                    temp=cfg.latent_temp,\n                    groups=cfg.latent_groups,\n                    combine_groups=False,\n                    vq_dim=vq_dim,\n                    time_first=True,\n                    weight_proj_depth=cfg.quantizer_depth,\n                    weight_proj_factor=cfg.quantizer_factor, )\n            self.project_inp = Linear(vq_dim, cfg.encoder_embed_dim)\n\n        self.mask_emb = self.create_parameter(\n            shape=[cfg.encoder_embed_dim],\n            default_initializer=paddle.nn.initializer.Uniform(),\n            dtype='float32', )\n\n        encoder_cls = TransformerEncoder\n\n        self.encoder = encoder_cls(cfg)\n        self.layer_norm = LayerNorm(self.embed)\n\n        self.target_glu = None\n        if cfg.target_glu:\n            self.target_glu = nn.Sequential(\n                Linear(final_dim, final_dim * 2), GLU())\n\n        self.final_proj = Linear(cfg.encoder_embed_dim, final_dim)\n\n    def upgrade_state_dict_named(self, state_dict, name):\n        super().upgrade_state_dict_named(state_dict, name)\n        \"\"\"Upgrade a (possibly old) state dict for new versions of fairseq.\"\"\"\n        return state_dict\n\n    @classmethod\n    def build_model(cls, cfg: Wav2Vec2Config, task=None):\n        \"\"\"Build a new model instance.\"\"\"\n        return cls(cfg)\n\n    def apply_mask(\n            self,\n            x,\n            padding_mask,\n            mask_indices=None,\n            mask_channel_indices=None, ):\n        B, T, C = x.shape\n\n        if self.mask_channel_prob > 0 and self.mask_channel_before:\n            mask_channel_indices = compute_mask_indices(\n                (B, C),\n                None,\n                self.mask_channel_prob,\n                self.mask_channel_length,\n                self.mask_channel_selection,\n                self.mask_channel_other,\n                no_overlap=self.no_mask_channel_overlap,\n                min_space=self.mask_channel_min_space, )\n            mask_channel_indices = (\n                paddle.to_tensor(mask_channel_indices, plcae=x.plcae)\n                .unsqueeze(1).expand([-1, T, -1]))\n            x[mask_channel_indices] = 0\n\n        if self.mask_prob > 0:\n            if mask_indices is None:\n                mask_indices = compute_mask_indices(\n                    (B, T),\n                    padding_mask,\n                    self.mask_prob,\n                    self.mask_length,\n                    self.mask_selection,\n                    self.mask_other,\n                    min_masks=2,\n                    no_overlap=self.no_mask_overlap,\n                    min_space=self.mask_min_space,\n                    require_same_masks=self.cfg.require_same_masks,\n                    mask_dropout=self.cfg.mask_dropout, )\n                mask_indices = paddle.to_tensor(mask_indices, place=x.place)\n            x = index_put(x, mask_indices, self.mask_emb)\n        else:\n            mask_indices = None\n\n        if self.mask_channel_prob > 0 and not self.mask_channel_before:\n            if mask_channel_indices is None:\n                mask_channel_indices = compute_mask_indices(\n                    (B, C),\n                    None,\n                    self.mask_channel_prob,\n                    self.mask_channel_length,\n                    self.mask_channel_selection,\n                    self.mask_channel_other,\n                    no_overlap=self.no_mask_channel_overlap,\n                    min_space=self.mask_channel_min_space, )\n                mask_channel_indices = (\n                    paddle.to_tensor(mask_channel_indices, place=x.place)\n                    .unsqueeze(1).expand([-1, T, -1]))\n            x = index_put(x, mask_channel_indices, 0)\n\n        return x, mask_indices\n\n    def sample_negatives(self, y, num, padding_count=None):\n\n        if self.n_negatives == 0 and self.cross_sample_negatives == 0:\n            return paddle.empty([0], dtype=y.dtype)\n\n        bsz, tsz, fsz = y.shape\n        y = y.reshape([-1, fsz])  # BTC => (BxT)C\n\n        # FIXME: what happens if padding_count is specified?\n        cross_high = tsz * bsz\n        high = tsz - (padding_count or 0)\n        with paddle.no_grad():\n            assert high > 1, f\"{bsz,tsz,fsz}\"\n\n            if self.n_negatives > 0:\n                tszs = (buffered_arange(num).unsqueeze(-1)\n                        .expand([-1, self.n_negatives]).flatten())\n\n                neg_idxs = paddle.randint(\n                    low=0, high=high - 1, shape=[bsz, self.n_negatives * num])\n                neg_idxs[neg_idxs >= tszs] += 1\n\n            if self.cross_sample_negatives > 0:\n                tszs = (buffered_arange(num).unsqueeze(-1)\n                        .expand([-1, self.cross_sample_negatives]).flatten())\n\n                cross_neg_idxs = paddle.randint(\n                    low=0,\n                    high=cross_high - 1,\n                    shape=[bsz, self.cross_sample_negatives * num], )\n                cross_neg_idxs[cross_neg_idxs >= tszs] += 1\n\n        if self.n_negatives > 0:\n            neg_idxs = neg_idxs + (paddle.arange(bsz).unsqueeze(1) * high)\n        else:\n            neg_idxs = cross_neg_idxs\n\n        if self.cross_sample_negatives > 0 and self.n_negatives > 0:\n            neg_idxs = paddle.concat([neg_idxs, cross_neg_idxs], axis=1)\n\n        negs = y[neg_idxs.reshape([-1])]\n        negs = negs.reshape(\n            [bsz, num, self.n_negatives + self.cross_sample_negatives,\n             fsz]).transpose([2, 0, 1, 3])  # to NxBxTxC\n        return negs, neg_idxs\n\n    def compute_preds(self, x, y, negatives):\n        neg_is_pos = (y == negatives).all(-1)\n        y = y.unsqueeze(0)\n        targets = paddle.concat([y, negatives], axis=0)\n\n        logits = paddle.nn.functional.cosine_similarity(x, targets, axis=-1)\n        logits = logits / self.logit_temp\n        logits = logits.astype(x.dtype)\n\n        return logits\n\n    def _get_feat_extract_output_lengths(self, input_lengths: paddle.Tensor):\n        \"\"\"\n        Computes the output length of the convolutional layers\n        \"\"\"\n\n        def _conv_out_length(input_length, kernel_size, stride):\n            return paddle.floor((input_length - kernel_size) / stride + 1)\n\n        conv_cfg_list = eval(self.cfg.conv_feature_layers)\n\n        for i in range(len(conv_cfg_list)):\n            input_lengths = _conv_out_length(input_lengths, conv_cfg_list[i][1],\n                                             conv_cfg_list[i][2])\n\n        return paddle.cast(input_lengths, 'int64')\n\n    def forward(\n            self,\n            source,\n            padding_mask=None,\n            mask=True,\n            features_only=False,\n            layer=None,\n            mask_indices=None,\n            mask_channel_indices=None,\n            padding_count=None, ):\n\n        if self.feature_grad_mult > 0:\n            features = self.feature_extractor(source)\n            if self.feature_grad_mult != 1.0:\n                features = GradMultiply.apply(features, self.feature_grad_mult)\n        else:\n            with paddle.no_grad():\n                features = self.feature_extractor(source)\n\n        features_pen = features.pow(2).mean()\n\n        features = features.transpose([0, 2, 1])\n        features = self.layer_norm(features)\n        unmasked_features = features.clone()\n\n        if padding_mask is not None and padding_mask.any():\n            input_lengths = (1 - paddle.cast(padding_mask, 'int64')).sum(-1)\n            # apply conv formula to get real output_lengths\n            output_lengths = self._get_feat_extract_output_lengths(\n                input_lengths)\n\n            padding_mask = paddle.zeros(\n                features.shape[:2], dtype=features.dtype)\n\n            # these two operations makes sure that all values\n            # before the output lengths indices are attended to\n            padding_mask[(paddle.arange(padding_mask.shape[0]),\n                          output_lengths - 1, )] = 1\n            padding_mask = paddle.cast(\n                (1 - padding_mask.flip([-1]).cumsum(-1).flip([-1])), 'bool')\n        else:\n            padding_mask = None\n\n        time_steps_to_drop = features.shape[1] % self.crop_seq_to_multiple\n        if time_steps_to_drop != 0:\n            features = features[:, :-time_steps_to_drop]\n            unmasked_features = unmasked_features[:, :-time_steps_to_drop]\n            if padding_mask is not None:\n                padding_mask = padding_mask[:, :-time_steps_to_drop]\n\n        if self.post_extract_proj is not None:\n            features = self.post_extract_proj(features)\n\n        features = self.dropout_input(features)\n        unmasked_features = self.dropout_features(unmasked_features)\n\n        num_vars = None\n        code_ppl = None\n        prob_ppl = None\n        curr_temp = None\n\n        if self.input_quantizer:\n            q = self.input_quantizer(features, produce_targets=False)\n            features = q[\"x\"]\n            num_vars = q[\"num_vars\"]\n            code_ppl = q[\"code_perplexity\"]\n            prob_ppl = q[\"prob_perplexity\"]\n            curr_temp = q[\"temp\"]\n            features = self.project_inp(features)\n\n        if mask:\n            x, mask_indices = self.apply_mask(\n                features,\n                padding_mask,\n                mask_indices=mask_indices,\n                mask_channel_indices=mask_channel_indices, )\n            if mask_indices is not None:\n                y = unmasked_features[mask_indices].reshape([\n                    unmasked_features.shape[0], -1, unmasked_features.shape[-1]\n                ])\n        else:\n            x = features\n            y = unmasked_features\n            mask_indices = None\n\n        x, layer_results = self.encoder(\n            x, padding_mask=padding_mask, layer=layer)\n\n        if features_only:\n            return {\n                \"x\": x,\n                \"padding_mask\": padding_mask,\n                \"features\": unmasked_features,\n                \"layer_results\": layer_results,\n            }\n\n        if self.quantizer:\n            if self.negatives_from_everywhere:\n                q = self.quantizer(unmasked_features, produce_targets=False)\n                y = q[\"x\"]\n                num_vars = q[\"num_vars\"]\n                code_ppl = q[\"code_perplexity\"]\n                prob_ppl = q[\"prob_perplexity\"]\n                curr_temp = q[\"temp\"]\n                y = self.project_q(y)\n\n                negs, _ = self.sample_negatives(\n                    y,\n                    mask_indices[0].sum(),\n                    padding_count=padding_count, )\n                y = y[mask_indices].reshape([y.shape[0], -1, y.shape[-1]])\n\n            else:\n                q = self.quantizer(y, produce_targets=False)\n                y = q[\"x\"]\n                num_vars = q[\"num_vars\"]\n                code_ppl = q[\"code_perplexity\"]\n                prob_ppl = q[\"prob_perplexity\"]\n                curr_temp = q[\"temp\"]\n\n                y = self.project_q(y)\n\n                negs, _ = self.sample_negatives(\n                    y,\n                    y.shape[1],\n                    padding_count=padding_count, )\n\n            if self.codebook_negatives > 0:\n                cb_negs = self.quantizer.sample_from_codebook(\n                    y.shape[0] * y.shape[1], self.codebook_negatives)\n                cb_negs = cb_negs.reshape(\n                    [self.codebook_negatives, y.shape[0], y.shape[1],\n                     -1])  # order doesnt matter\n                cb_negs = self.project_q(cb_negs)\n                negs = paddle.concat([negs, cb_negs], axis=0)\n        else:\n            y = self.project_q(y)\n\n            if self.negatives_from_everywhere:\n                negs, _ = self.sample_negatives(\n                    unmasked_features,\n                    y.shape[1],\n                    padding_count=padding_count, )\n                negs = self.project_q(negs)\n            else:\n                negs, _ = self.sample_negatives(\n                    y,\n                    y.shape[1],\n                    padding_count=padding_count, )\n\n        x = x[mask_indices].reshape([x.shape[0], -1, x.shape[-1]])\n\n        if self.target_glu:\n            y = self.target_glu(y)\n            negs = self.target_glu(negs)\n\n        x = self.final_proj(x)\n        x = self.compute_preds(x, y, negs)\n\n        result = {\n            \"x\": x,\n            \"padding_mask\": padding_mask,\n            \"features_pen\": features_pen,\n        }\n\n        if prob_ppl is not None:\n            result[\"prob_perplexity\"] = prob_ppl\n            result[\"code_perplexity\"] = code_ppl\n            result[\"num_vars\"] = num_vars\n            result[\"temp\"] = curr_temp\n\n        return result\n\n    def quantize(self, x):\n        assert self.quantizer is not None\n        x = self.feature_extractor(x)\n        x = x.transpose([0, 2, 1])\n        x = self.layer_norm(x)\n        return self.quantizer.forward_idx(x)\n\n    def extract_features(self, source, padding_mask, mask=False, layer=None):\n        res = self.forward(\n            source, padding_mask, mask=mask, features_only=True, layer=layer)\n        return res\n\n    def get_logits(self, net_output):\n        logits = net_output[\"x\"]\n        logits = logits.transpose([2, 1, 0])\n        logits = logits.reshape([-1, logits.shape[-1]])\n        return logits\n\n    def get_targets(self, sample, net_output, expand_steps=True):\n        x = net_output[\"x\"]\n        return paddle.zeros(x.shape[1] * x.shape[2], dtype='int64')\n\n    def get_extra_losses(self, net_output):\n        pen = []\n\n        if \"prob_perplexity\" in net_output:\n            pen.append((net_output[\"num_vars\"] - net_output[\"prob_perplexity\"])\n                       / net_output[\"num_vars\"])\n\n        if \"features_pen\" in net_output:\n            pen.append(net_output[\"features_pen\"])\n\n        return pen\n\n    def remove_pretraining_modules(self, last_layer=None):\n        self.quantizer = None\n        self.project_q = None\n        self.target_glu = None\n        self.final_proj = None\n\n        if last_layer is not None:\n            self.encoder.layers = nn.LayerList(\n                l for i, l in enumerate(self.encoder.layers) if i <= last_layer)\n\n\nclass ConvFeatureExtractionModel(nn.Layer):\n    def __init__(\n            self,\n            conv_layers: List[Tuple[int, int, int]],\n            dropout: float=0.0,\n            mode: str=\"default\",\n            conv_bias: bool=False, ):\n        super().__init__()\n\n        assert mode in {\"default\", \"layer_norm\"}\n\n        def block(\n                n_in,\n                n_out,\n                k,\n                stride,\n                is_layer_norm=False,\n                is_group_norm=False,\n                conv_bias=False, ):\n            def make_conv():\n                conv = Conv1D(\n                    n_in,\n                    n_out,\n                    k,\n                    stride=stride,\n                    bias_attr=conv_bias\n                    if not conv_bias else paddle.ParamAttr())\n                # nn.initializer.KaimingNormal()(conv.weight)\n                return conv\n\n            assert (is_layer_norm and is_group_norm\n                    ) is False, \"layer norm and group norm are exclusive\"\n\n            if is_layer_norm:\n                return nn.Sequential(\n                    make_conv(),\n                    nn.Dropout(p=dropout),\n                    nn.Sequential(\n                        TransposeLast(),\n                        Fp32LayerNorm(dim),\n                        TransposeLast(), ),\n                    nn.GELU(), )\n            elif is_group_norm:\n                return nn.Sequential(\n                    make_conv(),\n                    nn.Dropout(p=dropout),\n                    Fp32GroupNorm(dim, dim),\n                    nn.GELU(), )\n            else:\n                return nn.Sequential(\n                    make_conv(), nn.Dropout(p=dropout), nn.GELU())\n\n        in_d = 1\n        self.conv_layers = nn.LayerList()\n        for i, cl in enumerate(conv_layers):\n            assert len(cl) == 3, \"invalid conv definition: \" + str(cl)\n            (dim, k, stride) = cl\n\n            self.conv_layers.append(\n                block(\n                    in_d,\n                    dim,\n                    k,\n                    stride,\n                    is_layer_norm=mode == \"layer_norm\",\n                    is_group_norm=mode == \"default\" and i == 0,\n                    conv_bias=conv_bias, ))\n            in_d = dim\n\n    def forward(self, x):\n\n        # BxT -> BxCxT\n        x = x.unsqueeze(1)\n        for conv in self.conv_layers:\n            x = conv(x)\n\n        return x\n\n\ndef make_conv_pos(e, k, g):\n    dropout = 0\n    std = math.sqrt((4 * (1.0 - dropout)) / (k * e))\n    pos_conv = Conv1D(\n        e,\n        e,\n        kernel_size=k,\n        padding=k // 2,\n        groups=g,\n        weight_attr=nn.initializer.Normal(mean=0, std=std),\n        bias_attr=nn.initializer.Constant(0))\n    pos_conv = nn.utils.weight_norm(pos_conv, name=\"weight\", dim=2)\n    pos_conv = nn.Sequential(pos_conv, SamePad(k), nn.GELU())\n\n    return pos_conv\n\n\nclass TransformerEncoder(nn.Layer):\n    def build_encoder_layer(self, args: Wav2Vec2Config):\n        layer = TransformerSentenceEncoderLayer(\n            embedding_dim=self.embedding_dim,\n            ffn_embedding_dim=args.encoder_ffn_embed_dim,\n            num_attention_heads=args.encoder_attention_heads,\n            dropout=self.dropout,\n            attention_dropout=args.attention_dropout,\n            activation_dropout=args.activation_dropout,\n            activation_fn=args.activation_fn,\n            layer_norm_first=args.layer_norm_first, )\n        return layer\n\n    def __init__(self, args: Wav2Vec2Config):\n        super().__init__()\n\n        self.dropout = args.dropout\n        self.embedding_dim = args.encoder_embed_dim\n        self.required_seq_len_multiple = args.required_seq_len_multiple\n\n        pos_conv_depth = getattr(args, \"pos_conv_depth\", 1)\n        if pos_conv_depth > 1:\n            num_layers = args.pos_conv_depth\n            k = max(3, args.conv_pos // num_layers)\n\n            def make_conv_block(e, k, g, l):\n                return nn.Sequential(*[\n                    nn.Sequential(\n                        Conv1D(\n                            e,\n                            e,\n                            kernel_size=k,\n                            padding=k // 2,\n                            groups=g, ),\n                        SamePad(k),\n                        TransposeLast(),\n                        LayerNorm(e, elementwise_affine=False),\n                        TransposeLast(),\n                        nn.GELU(), ) for _ in range(l)\n                ])\n\n            self.pos_conv = make_conv_block(self.embedding_dim, k,\n                                            args.conv_pos_groups, num_layers)\n\n        else:\n            self.pos_conv = make_conv_pos(\n                self.embedding_dim,\n                args.conv_pos,\n                args.conv_pos_groups, )\n\n        self.layers = nn.LayerList([\n            self.build_encoder_layer(args) for _ in range(args.encoder_layers)\n        ])\n        self.layer_norm_first = args.layer_norm_first\n        self.layer_norm = LayerNorm(self.embedding_dim)\n        self.layerdrop = args.encoder_layerdrop\n\n    def forward(self, x, padding_mask=None, layer=None):\n        x, layer_results = self.extract_features(x, padding_mask, layer)\n        if self.layer_norm_first and layer is None:\n            x = self.layer_norm(x)\n\n        return x, layer_results\n\n    def extract_features(\n            self,\n            x,\n            padding_mask=None,\n            tgt_layer=None,\n            min_layer=0, ):\n        if padding_mask is not None:\n            x = index_put(x, padding_mask, 0)\n\n        x_conv = self.pos_conv(x.transpose([0, 2, 1]))\n        x_conv = x_conv.transpose([0, 2, 1])\n        x = x + x_conv\n\n        if not self.layer_norm_first:\n            x = self.layer_norm(x)\n\n        # pad to the sequence length dimension\n        x, pad_length = pad_to_multiple(\n            x, self.required_seq_len_multiple, dim=-2, value=0)\n        if pad_length > 0 and padding_mask is None:\n            padding_mask = paddle.zeros([x.shape[0], x.shape[1]], dtype='bool')\n            padding_mask[:, -pad_length:] = True\n        else:\n            padding_mask, _ = pad_to_multiple(\n                padding_mask,\n                self.required_seq_len_multiple,\n                dim=-1,\n                value=True)\n        x = F.dropout(x, p=self.dropout, training=self.training)\n\n        # B x T x C -> T x B x C\n        x = x.transpose([1, 0, 2])\n\n        layer_results = []\n        r = None\n        for i, layer in enumerate(self.layers):\n            dropout_probability = np.random.random() if self.layerdrop > 0 else 1\n            if not self.training or (dropout_probability > self.layerdrop):\n                x, (z, lr) = layer(\n                    x, self_attn_padding_mask=padding_mask, need_weights=False)\n                if i >= min_layer:\n                    layer_results.append((x, z, lr))\n            if i == tgt_layer:\n                r = x\n                break\n\n        if r is not None:\n            x = r\n\n        # T x B x C -> B x T x C\n        x = x.transpose([1, 0, 2])\n\n        # undo paddding\n        if pad_length > 0:\n            x = x[:, :-pad_length]\n\n            def undo_pad(a, b, c):\n                return (a[:-pad_length], b[:-pad_length]\n                        if b is not None else b, c[:-pad_length], )\n\n            layer_results = [undo_pad(*u) for u in layer_results]\n\n        return x, layer_results\n\n    def max_positions(self):\n        \"\"\"Maximum output length supported by the encoder.\"\"\"\n        return self.args.max_positions\n\n    def upgrade_state_dict_named(self, state_dict, name):\n        \"\"\"Upgrade a (possibly old) state dict for new versions of fairseq.\"\"\"\n        return state_dict\n\n\nclass TransformerSentenceEncoderLayer(nn.Layer):\n    \"\"\"\n    Implements a Transformer Encoder Layer used in BERT/XLM style pre-trained\n    models.\n    \"\"\"\n\n    def __init__(\n            self,\n            embedding_dim: float=768,\n            ffn_embedding_dim: float=3072,\n            num_attention_heads: int=8,\n            dropout: float=0.1,\n            attention_dropout: float=0.1,\n            activation_dropout: float=0.1,\n            activation_fn: str=\"relu\",\n            layer_norm_first: bool=False, ) -> None:\n\n        super().__init__()\n        # Initialize parameters\n        self.embedding_dim = embedding_dim\n        self.dropout = dropout\n        self.activation_dropout = activation_dropout\n\n        # Initialize blocks\n        self.activation_fn = get_activation_fn(activation_fn)\n        self.self_attn = MultiheadAttention(\n            self.embedding_dim,\n            num_attention_heads,\n            dropout=attention_dropout,\n            self_attention=True, )\n\n        self.dropout1 = nn.Dropout(dropout)\n        self.dropout2 = nn.Dropout(self.activation_dropout)\n        self.dropout3 = nn.Dropout(dropout)\n\n        self.layer_norm_first = layer_norm_first\n\n        # layer norm associated with the self attention layer\n        self.self_attn_layer_norm = LayerNorm(self.embedding_dim)\n        self.fc1 = Linear(self.embedding_dim, ffn_embedding_dim)\n        self.fc2 = Linear(ffn_embedding_dim, self.embedding_dim)\n\n        # layer norm associated with the position wise feed-forward NN\n        self.final_layer_norm = LayerNorm(self.embedding_dim)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            self_attn_mask: paddle.Tensor=None,\n            self_attn_padding_mask: paddle.Tensor=None,\n            need_weights: bool=False,\n            att_args=None, ):\n        \"\"\"\n        LayerNorm is applied either before or after the self-attention/ffn\n        modules similar to the original Transformer imlementation.\n        \"\"\"\n        residual = x\n\n        if self.layer_norm_first:\n            x = self.self_attn_layer_norm(x)\n            x, attn = self.self_attn(\n                query=x,\n                key=x,\n                value=x,\n                key_padding_mask=self_attn_padding_mask,\n                attn_mask=self_attn_mask,\n                need_weights=False, )\n            x = self.dropout1(x)\n            x = residual + x\n\n            residual = x\n            x = self.final_layer_norm(x)\n            x = self.activation_fn(self.fc1(x))\n            x = self.dropout2(x)\n            x = self.fc2(x)\n\n            layer_result = x\n\n            x = self.dropout3(x)\n            x = residual + x\n        else:\n            x, attn = self.self_attn(\n                query=x,\n                key=x,\n                value=x,\n                key_padding_mask=self_attn_padding_mask,\n                need_weights=False, )\n\n            x = self.dropout1(x)\n            x = residual + x\n\n            x = self.self_attn_layer_norm(x)\n\n            residual = x\n            x = self.activation_fn(self.fc1(x))\n            x = self.dropout2(x)\n            x = self.fc2(x)\n\n            layer_result = x\n\n            x = self.dropout3(x)\n            x = residual + x\n            x = self.final_layer_norm(x)\n\n        return x, (attn, layer_result)\n\n\n@dataclass\nclass AudioPretrainingConfig:\n    sample_rate: int = field(\n        default=16_000,\n        metadata={\n            \"help\":\n            \"target sample rate. audio files will be up/down sampled to this rate\"\n        }, )\n    normalize: bool = field(\n        default=False,\n        metadata={\n            \"help\": \"if set, normalizes input to have 0 mean and unit variance\"\n        }, )\n    enable_padding: bool = field(\n        default=False,\n        metadata={\"help\": \"pad shorter samples instead of cropping\"})\n    max_sample_size: Optional[int] = field(\n        default=None,\n        metadata={\"help\": \"max sample size to crop to for batching\"})\n    min_sample_size: Optional[int] = field(\n        default=None,\n        metadata={\"help\": \"min sample size to skip small examples\"})\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/processing/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/processing/signal_processing.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain 2023 (https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/processing/signal_processing.py)\n\"\"\"\nLow level signal processing utilities\nAuthors\n * Peter Plantinga 2020\n * Francois Grondin 2020\n * William Aris 2020\n * Samuele Cornell 2020\n * Sarthak Yadav 2022\n\"\"\"\nimport numpy as np\nimport paddle\n\n\ndef blackman_window(window_length, periodic=True):\n    \"\"\"Blackman window function.\n    Arguments\n    ---------\n    window_length : int\n        Controlling the returned window size. \n    periodic : bool\n        Determines whether the returned window trims off the\n        last duplicate value from the symmetric window\n\n    Returns\n    -------\n    A 1-D tensor of size (window_length) containing the window\n    \"\"\"\n    if window_length == 0:\n        return []\n    if window_length == 1:\n        return paddle.ones([1])\n    if periodic:\n        window_length += 1\n    window = paddle.arange(window_length) * (np.pi / (window_length - 1))\n    window = 0.08 * paddle.cos(window * 4) - 0.5 * paddle.cos(window * 2) + 0.42\n    return window[:-1] if periodic else window\n\n\ndef compute_amplitude(waveforms, lengths=None, amp_type=\"avg\", scale=\"linear\"):\n    \"\"\"Compute amplitude of a batch of waveforms.\n    Arguments\n    ---------\n    waveform : tensor\n        The waveforms used for computing amplitude.\n        Shape should be `[time]` or `[batch, time]` or\n        `[batch, time, channels]`.\n    lengths : tensor\n        The lengths of the waveforms excluding the padding.\n        Shape should be a single dimension, `[batch]`.\n    amp_type : str\n        Whether to compute \"avg\" average or \"peak\" amplitude.\n        Choose between [\"avg\", \"peak\"].\n    scale : str\n        Whether to compute amplitude in \"dB\" or \"linear\" scale.\n        Choose between [\"linear\", \"dB\"].\n    Returns\n    -------\n    The average amplitude of the waveforms.\n    Example\n    -------\n    >>> signal = paddle.sin(paddle.arange(16000.0)).unsqueeze(0)\n    >>> compute_amplitude(signal, signal.size(1))\n    tensor([[0.6366]])\n    \"\"\"\n    if len(waveforms.shape) == 1:\n        waveforms = waveforms.unsqueeze(0)\n\n    assert amp_type in [\"avg\", \"peak\"]\n    assert scale in [\"linear\", \"dB\"]\n\n    if amp_type == \"avg\":\n        if lengths is None:\n            out = paddle.mean(paddle.abs(waveforms), axis=1, keepdim=True)\n        else:\n            wav_sum = paddle.sum(paddle.abs(waveforms), axis=1, keepdim=True)\n            out = wav_sum / lengths.astype(wav_sum.dtype)\n    elif amp_type == \"peak\":\n        out = paddle.max(paddle.abs(waveforms), axis=1, keepdim=True)[0]\n    else:\n        raise NotImplementedError\n\n    if scale == \"linear\":\n        return out\n    elif scale == \"dB\":\n        return paddle.clip(20 * paddle.log10(out), min=-80)  # clamp zeros\n    else:\n        raise NotImplementedError\n\n\ndef convolve1d(\n        waveform,\n        kernel,\n        padding=0,\n        pad_type=\"constant\",\n        stride=1,\n        groups=1,\n        use_fft=False,\n        rotation_index=0, ):\n    \"\"\"Use paddle.nn.functional to perform 1d padding and conv.\n    Arguments\n    ---------\n    waveform : tensor\n        The tensor to perform operations on.\n    kernel : tensor\n        The filter to apply during convolution.\n    padding : int or tuple\n        The padding (pad_left, pad_right) to apply.\n        If an integer is passed instead, this is passed\n        to the conv1d function and pad_type is ignored.\n    pad_type : str\n        The type of padding to use. Passed directly to\n        `paddle.nn.functional.pad`, see Paddle documentation\n        for available options.\n    stride : int\n        The number of units to move each time convolution is applied.\n        Passed to conv1d. Has no effect if `use_fft` is True.\n    groups : int\n        This option is passed to `conv1d` to split the input into groups for\n        convolution. Input channels should be divisible by the number of groups.\n    use_fft : bool\n        When `use_fft` is passed `True`, then compute the convolution in the\n        spectral domain using complex multiply. This is more efficient on CPU\n        when the size of the kernel is large (e.g. reverberation). WARNING:\n        Without padding, circular convolution occurs. This makes little\n        difference in the case of reverberation, but may make more difference\n        with different kernels.\n    rotation_index : int\n        This option only applies if `use_fft` is true. If so, the kernel is\n        rolled by this amount before convolution to shift the output location.\n    Returns\n    -------\n    The convolved waveform.\n    Example\n    -------\n    >>> from speechbrain.dataio.dataio import read_audio\n    >>> signal = read_audio('tests/samples/single-mic/example1.wav')\n    >>> signal = signal.unsqueeze(0).unsqueeze(2)\n    >>> kernel = paddle.rand([1, 10, 1])\n    >>> signal = convolve1d(signal, kernel, padding=(9, 0))\n    \"\"\"\n    if len(waveform.shape) != 3:\n        raise ValueError(\"Convolve1D expects a 3-dimensional tensor\")\n\n    # Move time dimension last, which pad and fft and conv expect.\n    waveform = waveform.transpose([0, 2, 1])\n    kernel = kernel.transpose([0, 2, 1])\n    # Padding can be a tuple (left_pad, right_pad) or an int\n    if isinstance(padding, tuple):\n        waveform = paddle.nn.functional.pad(\n            x=waveform, pad=padding, mode=pad_type, data_format='NCL')\n\n    # This approach uses FFT, which is more efficient if the kernel is large\n    if use_fft:\n        # Pad kernel to same length as signal, ensuring correct alignment\n        zero_length = waveform.shape[-1] - kernel.shape[-1]\n\n        # Handle case where signal is shorter\n        if zero_length < 0:\n            kernel = kernel[..., :zero_length]\n            zero_length = 0\n\n        # Perform rotation to ensure alignment\n        zeros = paddle.zeros(\n            [kernel.shape[0], kernel.shape[1], zero_length], dtype=kernel.dtype)\n        after_index = kernel[..., rotation_index:]\n        before_index = kernel[..., :rotation_index]\n        kernel = paddle.concat((after_index, zeros, before_index), axis=-1)\n\n        # Multiply in frequency domain to convolve in time domain\n        import paddle.fft as fft\n\n        result = fft.rfft(waveform) * fft.rfft(kernel)\n        convolved = fft.irfft(result, n=waveform.shape[-1])\n\n    # Use the implementation given by paddle, which should be efficient on GPU\n    else:\n        convolved = paddle.nn.functional.conv1d(\n            x=waveform,\n            weight=kernel,\n            stride=stride,\n            groups=groups,\n            padding=padding if not isinstance(padding, tuple) else 0, )\n\n    # Return time dimension to the second dimension.\n    return convolved.transpose([0, 2, 1])\n\n\ndef notch_filter(notch_freq, filter_width=101, notch_width=0.05):\n    \"\"\"Returns a notch filter constructed from a high-pass and low-pass filter.\n    (from https://tomroelandts.com/articles/\n    how-to-create-simple-band-pass-and-band-reject-filters)\n    Arguments\n    ---------\n    notch_freq : float\n        frequency to put notch as a fraction of the\n        sampling rate / 2. The range of possible inputs is 0 to 1.\n    filter_width : int\n        Filter width in samples. Longer filters have\n        smaller transition bands, but are more inefficient.\n    notch_width : float\n        Width of the notch, as a fraction of the sampling_rate / 2.\n    \"\"\"\n\n    # Check inputs\n    assert 0 < notch_freq <= 1\n    assert filter_width % 2 != 0\n    pad = filter_width // 2\n    inputs = paddle.arange(filter_width) - pad\n\n    # Avoid frequencies that are too low\n    notch_freq += notch_width\n\n    # Define sinc function, avoiding division by zero\n    def sinc(x):\n        \"Computes the sinc function.\"\n\n        def _sinc(x):\n            return paddle.sin(x) / x\n\n        # The zero is at the middle index\n        return paddle.concat(\n            [_sinc(x[:pad]), paddle.ones([1]), _sinc(x[pad + 1:])])\n\n    # Compute a low-pass filter with cutoff frequency notch_freq.\n    hlpf = sinc(3 * (notch_freq - notch_width) * inputs)\n    hlpf *= blackman_window(filter_width)\n    hlpf /= paddle.sum(hlpf)\n\n    # Compute a high-pass filter with cutoff frequency notch_freq.\n    hhpf = sinc(3 * (notch_freq + notch_width) * inputs)\n    hhpf *= blackman_window(filter_width)\n    hhpf /= -paddle.sum(hhpf)\n    hhpf[pad] += 1\n\n    # Adding filters creates notch filter\n    return (hlpf + hhpf).reshape([1, -1, 1])\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/processing/speech_augmentation.py",
    "content": "# Copyright (c) 2023 speechbrain Authors. All Rights Reserved.\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain/blob/develop/speechbrain/processing/speech_augmentation.py)\n\"\"\"Classes for mutating speech data for data augmentation.\nThis module provides classes that produce realistic distortions of speech\ndata for the purpose of training speech processing models. The list of\ndistortions includes adding noise, adding reverberation, changing speed,\nand more. All the classes are of type `torch.nn.Module`. This gives the\npossibility to have end-to-end differentiability and\nbackpropagate the gradient through them. In addition, all operations\nare expected to be performed on the GPU (where available) for efficiency.\n\nAuthors\n * Peter Plantinga 2020\n\"\"\"\nimport math\n\nimport paddle\nimport paddle.nn as nn\n\nfrom paddlespeech.s2t.models.wav2vec2.processing.signal_processing import compute_amplitude\nfrom paddlespeech.s2t.models.wav2vec2.processing.signal_processing import convolve1d\nfrom paddlespeech.s2t.models.wav2vec2.processing.signal_processing import notch_filter\n\n\nclass SpeedPerturb(nn.Layer):\n    \"\"\"Slightly speed up or slow down an audio signal.\n    Resample the audio signal at a rate that is similar to the original rate,\n    to achieve a slightly slower or slightly faster signal. This technique is\n    outlined in the paper: \"Audio Augmentation for Speech Recognition\"\n    Arguments\n    ---------\n    orig_freq : int\n        The frequency of the original signal.\n    speeds : list\n        The speeds that the signal should be changed to, as a percentage of the\n        original signal (i.e. `speeds` is divided by 100 to get a ratio).\n    perturb_prob : float\n        The chance that the batch will be speed-\n        perturbed. By default, every batch is perturbed.\n    Example\n    -------\n    >>> from speechbrain.dataio.dataio import read_audio\n    >>> signal = read_audio('tests/samples/single-mic/example1.wav')\n    >>> perturbator = SpeedPerturb(orig_freq=16000, speeds=[90])\n    >>> clean = signal.unsqueeze(0)\n    >>> perturbed = perturbator(clean)\n    >>> clean.shape\n    paddle.shape([1, 52173])\n    >>> perturbed.shape\n    paddle.shape([1, 46956])\n    \"\"\"\n\n    def __init__(\n            self,\n            orig_freq,\n            speeds=[90, 100, 110],\n            perturb_prob=1.0, ):\n        super().__init__()\n        self.orig_freq = orig_freq\n        self.speeds = speeds\n        self.perturb_prob = perturb_prob\n\n        # Initialize index of perturbation\n        self.samp_index = 0\n        # Initialize resamplers\n        self.resamplers = []\n        for speed in self.speeds:\n            config = {\n                \"orig_freq\": self.orig_freq,\n                \"new_freq\": self.orig_freq * speed // 100,\n            }\n            self.resamplers.append(Resample(**config))\n\n    def forward(self, waveform):\n        \"\"\"\n        Arguments\n        ---------\n        waveforms : tensor\n            Shape should be `[batch, time]` or `[batch, time, channels]`.\n        lengths : tensor\n            Shape should be a single dimension, `[batch]`.\n        Returns\n        -------\n        Tensor of shape `[batch, time]` or `[batch, time, channels]`.\n        \"\"\"\n\n        # Don't perturb (return early) 1-`perturb_prob` portion of the batches\n        if paddle.rand([1]) > self.perturb_prob:\n            return waveform.clone()\n        # Perform a random perturbation\n        self.samp_index = paddle.randint(len(self.speeds), shape=(1, ))[0]\n        perturbed_waveform = self.resamplers[self.samp_index](waveform)\n\n        return perturbed_waveform\n\n\nclass Resample(nn.Layer):\n    \"\"\"This class resamples an audio signal using sinc-based interpolation.\n\n    It is a modification of the `resample` function from torchaudio\n    (https://pytorch.org/audio/stable/tutorials/audio_resampling_tutorial.html)\n\n    Arguments\n    ---------\n    orig_freq : int\n        the sampling frequency of the input signal.\n    new_freq : int\n        the new sampling frequency after this operation is performed.\n    lowpass_filter_width : int\n        Controls the sharpness of the filter, larger numbers result in a\n        sharper filter, but they are less efficient. Values from 4 to 10 are allowed.\n    \"\"\"\n\n    def __init__(\n            self,\n            orig_freq=16000,\n            new_freq=16000,\n            lowpass_filter_width=6, ):\n        super().__init__()\n        self.orig_freq = orig_freq\n        self.new_freq = new_freq\n        self.lowpass_filter_width = lowpass_filter_width\n\n        # Compute rate for striding\n        self._compute_strides()\n        assert self.orig_freq % self.conv_stride == 0\n        assert self.new_freq % self.conv_transpose_stride == 0\n\n    def _compute_strides(self):\n        \"\"\"Compute the phases in polyphase filter.\n\n        (almost directly from torchaudio.compliance.kaldi)\n        \"\"\"\n\n        # Compute new unit based on ratio of in/out frequencies\n        base_freq = math.gcd(self.orig_freq, self.new_freq)\n        input_samples_in_unit = self.orig_freq // base_freq\n        self.output_samples = self.new_freq // base_freq\n\n        # Store the appropriate stride based on the new units\n        self.conv_stride = input_samples_in_unit\n        self.conv_transpose_stride = self.output_samples\n\n    def forward(self, waveforms):\n        \"\"\"\n        Arguments\n        ---------\n        waveforms : tensor\n            Shape should be `[batch, time]` or `[batch, time, channels]`.\n        lengths : tensor\n            Shape should be a single dimension, `[batch]`.\n\n        Returns\n        -------\n        Tensor of shape `[batch, time]` or `[batch, time, channels]`.\n        \"\"\"\n\n        if not hasattr(self, \"first_indices\"):\n            self._indices_and_weights(waveforms)\n\n        # Don't do anything if the frequencies are the same\n        if self.orig_freq == self.new_freq:\n            return waveforms\n        unsqueezed = False\n        if len(waveforms.shape) == 2:\n            waveforms = waveforms.unsqueeze(1)\n            unsqueezed = True\n        elif len(waveforms.shape) == 3:\n            waveforms = waveforms.transpose([0, 2, 1])\n        else:\n            raise ValueError(\"Input must be 2 or 3 dimensions\")\n\n        # Do resampling\n        resampled_waveform = self._perform_resample(waveforms)\n\n        if unsqueezed:\n            resampled_waveform = resampled_waveform.squeeze(1)\n        else:\n            resampled_waveform = resampled_waveform.transpose([0, 2, 1])\n\n        return resampled_waveform\n\n    def _perform_resample(self, waveforms):\n        \"\"\"Resamples the waveform at the new frequency.\n\n        This matches Kaldi's OfflineFeatureTpl ResampleWaveform which uses a\n        LinearResample (resample a signal at linearly spaced intervals to\n        up/downsample a signal). LinearResample (LR) means that the output\n        signal is at linearly spaced intervals (i.e the output signal has a\n        frequency of `new_freq`). It uses sinc/bandlimited interpolation to\n        upsample/downsample the signal.\n\n        (almost directly from torchaudio.compliance.kaldi)\n\n        https://ccrma.stanford.edu/~jos/resample/\n        Theory_Ideal_Bandlimited_Interpolation.html\n\n        https://github.com/kaldi-asr/kaldi/blob/master/src/feat/resample.h#L56\n\n        Arguments\n        ---------\n        waveforms : tensor\n            The batch of audio signals to resample.\n\n        Returns\n        -------\n        The waveforms at the new frequency.\n        \"\"\"\n\n        # Compute output size and initialize\n        batch_size, num_channels, wave_len = waveforms.shape\n        window_size = self.weights.shape[1]\n        tot_output_samp = self._output_samples(wave_len)\n        resampled_waveform = paddle.zeros(\n            (batch_size, num_channels, tot_output_samp))\n        # self.weights = self.weights.to(waveforms.device)\n\n        # Check weights are on correct device\n        # if waveforms.device != self.weights.device:\n        #     self.weights = self.weights.to(waveforms.device)\n\n        # eye size: (num_channels, num_channels, 1)\n        eye = paddle.eye(num_channels).unsqueeze(2)\n\n        # Iterate over the phases in the polyphase filter\n        for i in range(self.first_indices.shape[0]):\n            wave_to_conv = waveforms\n            first_index = int(self.first_indices[i].item())\n            if first_index >= 0:\n                # trim the signal as the filter will not be applied\n                # before the first_index\n                wave_to_conv = wave_to_conv[..., first_index:]\n\n            # pad the right of the signal to allow partial convolutions\n            # meaning compute values for partial windows (e.g. end of the\n            # window is outside the signal length)\n            max_index = (tot_output_samp - 1) // self.output_samples\n            end_index = max_index * self.conv_stride + window_size\n            current_wave_len = wave_len - first_index\n            right_padding = max(0, end_index + 1 - current_wave_len)\n            left_padding = max(0, -first_index)\n            wave_to_conv = paddle.nn.functional.pad(\n                wave_to_conv, (left_padding, right_padding), data_format='NCL')\n            conv_wave = paddle.nn.functional.conv1d(\n                x=wave_to_conv,\n                weight=self.weights[i].repeat(num_channels, 1, 1),\n                stride=self.conv_stride,\n                groups=num_channels, )\n\n            # we want conv_wave[:, i] to be at\n            # output[:, i + n*conv_transpose_stride]\n            dilated_conv_wave = paddle.nn.functional.conv1d_transpose(\n                conv_wave, eye, stride=self.conv_transpose_stride)\n\n            # pad dilated_conv_wave so it reaches the output length if needed.\n            left_padding = i\n            previous_padding = left_padding + dilated_conv_wave.shape[-1]\n            right_padding = max(0, tot_output_samp - previous_padding)\n            dilated_conv_wave = paddle.nn.functional.pad(\n                dilated_conv_wave, (left_padding, right_padding),\n                data_format='NCL')\n            dilated_conv_wave = dilated_conv_wave[..., :tot_output_samp]\n\n            resampled_waveform += dilated_conv_wave\n\n        return resampled_waveform\n\n    def _output_samples(self, input_num_samp):\n        \"\"\"Based on LinearResample::GetNumOutputSamples.\n\n        LinearResample (LR) means that the output signal is at\n        linearly spaced intervals (i.e the output signal has a\n        frequency of ``new_freq``). It uses sinc/bandlimited\n        interpolation to upsample/downsample the signal.\n\n        (almost directly from torchaudio.compliance.kaldi)\n\n        Arguments\n        ---------\n        input_num_samp : int\n            The number of samples in each example in the batch.\n\n        Returns\n        -------\n        Number of samples in the output waveform.\n        \"\"\"\n\n        # For exact computation, we measure time in \"ticks\" of 1.0 / tick_freq,\n        # where tick_freq is the least common multiple of samp_in and\n        # samp_out.\n        samp_in = int(self.orig_freq)\n        samp_out = int(self.new_freq)\n\n        tick_freq = abs(samp_in * samp_out) // math.gcd(samp_in, samp_out)\n        ticks_per_input_period = tick_freq // samp_in\n\n        # work out the number of ticks in the time interval\n        # [ 0, input_num_samp/samp_in ).\n        interval_length = input_num_samp * ticks_per_input_period\n        if interval_length <= 0:\n            return 0\n        ticks_per_output_period = tick_freq // samp_out\n\n        # Get the last output-sample in the closed interval,\n        # i.e. replacing [ ) with [ ]. Note: integer division rounds down.\n        # See http://en.wikipedia.org/wiki/Interval_(mathematics) for an\n        # explanation of the notation.\n        last_output_samp = interval_length // ticks_per_output_period\n\n        # We need the last output-sample in the open interval, so if it\n        # takes us to the end of the interval exactly, subtract one.\n        if last_output_samp * ticks_per_output_period == interval_length:\n            last_output_samp -= 1\n\n        # First output-sample index is zero, so the number of output samples\n        # is the last output-sample plus one.\n        num_output_samp = last_output_samp + 1\n\n        return num_output_samp\n\n    def _indices_and_weights(self, waveforms):\n        \"\"\"Based on LinearResample::SetIndexesAndWeights\n\n        Retrieves the weights for resampling as well as the indices in which\n        they are valid. LinearResample (LR) means that the output signal is at\n        linearly spaced intervals (i.e the output signal has a frequency\n        of ``new_freq``). It uses sinc/bandlimited interpolation to\n        upsample/downsample the signal.\n\n        Returns\n        -------\n        - the place where each filter should start being applied\n        - the filters to be applied to the signal for resampling\n        \"\"\"\n\n        # Lowpass filter frequency depends on smaller of two frequencies\n        min_freq = min(self.orig_freq, self.new_freq)\n        lowpass_cutoff = 0.99 * 0.5 * min_freq\n\n        assert lowpass_cutoff * 2 <= min_freq\n        window_width = self.lowpass_filter_width / (2.0 * lowpass_cutoff)\n\n        assert lowpass_cutoff < min(self.orig_freq, self.new_freq) / 2\n        output_t = paddle.arange(\n            start=0.0, end=self.output_samples, dtype='int64')\n        output_t /= self.new_freq\n        min_t = output_t - window_width\n        max_t = output_t + window_width\n\n        min_input_index = paddle.ceil(min_t * self.orig_freq)\n        max_input_index = paddle.floor(max_t * self.orig_freq)\n        num_indices = max_input_index - min_input_index + 1\n\n        max_weight_width = num_indices.max()\n        j = paddle.arange(max_weight_width)\n        input_index = min_input_index.unsqueeze(1) + j.unsqueeze(0)\n        delta_t = (input_index / self.orig_freq) - output_t.unsqueeze(1)\n\n        weights = paddle.zeros_like(delta_t)\n\n        inside_window_indices = delta_t.abs() < (window_width)\n        # raised-cosine (Hanning) window with width `window_width`\n        weights[inside_window_indices] = 0.5 * (1 + paddle.cos(\n            2 * math.pi * lowpass_cutoff / self.lowpass_filter_width *\n            delta_t[inside_window_indices]))\n        t_eq_zero_indices = delta_t == 0.0\n        t_not_eq_zero_indices = ~t_eq_zero_indices\n\n        # sinc filter function\n        weights[t_not_eq_zero_indices] *= paddle.sin(\n            2 * math.pi * lowpass_cutoff * delta_t[t_not_eq_zero_indices]) / (\n                math.pi * delta_t[t_not_eq_zero_indices])\n\n        # limit of the function at t = 0\n        weights[t_eq_zero_indices] *= 2 * lowpass_cutoff\n\n        # size (output_samples, max_weight_width)\n        weights /= self.orig_freq\n\n        self.first_indices = min_input_index\n        self.weights = weights\n\n\nclass DropFreq(nn.Layer):\n    \"\"\"This class drops a random frequency from the signal.\n    The purpose of this class is to teach models to learn to rely on all parts\n    of the signal, not just a few frequency bands.\n    Arguments\n    ---------\n    drop_freq_low : float\n        The low end of frequencies that can be dropped,\n        as a fraction of the sampling rate / 2.\n    drop_freq_high : float\n        The high end of frequencies that can be\n        dropped, as a fraction of the sampling rate / 2.\n    drop_count_low : int\n        The low end of number of frequencies that could be dropped.\n    drop_count_high : int\n        The high end of number of frequencies that could be dropped.\n    drop_width : float\n        The width of the frequency band to drop, as\n        a fraction of the sampling_rate / 2.\n    drop_prob : float\n        The probability that the batch of signals will  have a frequency\n        dropped. By default, every batch has frequencies dropped.\n    Example\n    -------\n    >>> from speechbrain.dataio.dataio import read_audio\n    >>> dropper = DropFreq()\n    >>> signal = read_audio('tests/samples/single-mic/example1.wav')\n    >>> dropped_signal = dropper(signal.unsqueeze(0))\n    \"\"\"\n\n    def __init__(\n            self,\n            drop_freq_low=1e-14,\n            drop_freq_high=1,\n            drop_count_low=1,\n            drop_count_high=2,\n            drop_width=0.05,\n            drop_prob=1, ):\n        super().__init__()\n        self.drop_freq_low = drop_freq_low\n        self.drop_freq_high = drop_freq_high\n        self.drop_count_low = drop_count_low\n        self.drop_count_high = drop_count_high\n        self.drop_width = drop_width\n        self.drop_prob = drop_prob\n\n    def forward(self, waveforms):\n        \"\"\"\n        Arguments\n        ---------\n        waveforms : tensor\n            Shape should be `[batch, time]` or `[batch, time, channels]`.\n        Returns\n        -------\n        Tensor of shape `[batch, time]` or `[batch, time, channels]`.\n        \"\"\"\n\n        # Don't drop (return early) 1-`drop_prob` portion of the batches\n        dropped_waveform = waveforms.clone()\n        if paddle.rand([1]) > self.drop_prob:\n            return dropped_waveform\n\n        # Add channels dimension\n        if len(waveforms.shape) == 2:\n            dropped_waveform = dropped_waveform.unsqueeze(-1)\n\n        # Pick number of frequencies to drop\n        drop_count = paddle.randint(\n            low=self.drop_count_low,\n            high=self.drop_count_high + 1,\n            shape=(1, ), )\n\n        # Filter parameters\n        filter_length = 101\n        pad = filter_length // 2\n\n        # Start with delta function\n        drop_filter = paddle.zeros([1, filter_length, 1])\n        drop_filter[0, pad, 0] = 1\n\n        if drop_count.shape == 0:\n            # Pick a frequency to drop\n            drop_range = self.drop_freq_high - self.drop_freq_low\n            drop_frequency = (\n                paddle.rand(drop_count) * drop_range + self.drop_freq_low)\n            # Subtract each frequency\n            for frequency in drop_frequency:\n                notch_kernel = notch_filter(\n                    frequency,\n                    filter_length,\n                    self.drop_width, )\n                drop_filter = convolve1d(drop_filter, notch_kernel, pad)\n\n        # Apply filter\n        dropped_waveform = convolve1d(dropped_waveform, drop_filter, pad)\n\n        # Remove channels dimension if added\n        return dropped_waveform.squeeze(-1)\n\n\nclass DropChunk(nn.Layer):\n    \"\"\"This class drops portions of the input signal.\n    Using `DropChunk` as an augmentation strategy helps a models learn to rely\n    on all parts of the signal, since it can't expect a given part to be\n    present.\n    Arguments\n    ---------\n    drop_length_low : int\n        The low end of lengths for which to set the\n        signal to zero, in samples.\n    drop_length_high : int\n        The high end of lengths for which to set the\n        signal to zero, in samples.\n    drop_count_low : int\n        The low end of number of times that the signal\n        can be dropped to zero.\n    drop_count_high : int\n        The high end of number of times that the signal\n        can be dropped to zero.\n    drop_start : int\n        The first index for which dropping will be allowed.\n    drop_end : int\n        The last index for which dropping will be allowed.\n    drop_prob : float\n        The probability that the batch of signals will\n        have a portion dropped. By default, every batch\n        has portions dropped.\n    noise_factor : float\n        The factor relative to average amplitude of an utterance\n        to use for scaling the white noise inserted. 1 keeps\n        the average amplitude the same, while 0 inserts all 0's.\n    Example\n    -------\n    >>> from speechbrain.dataio.dataio import read_audio\n    >>> dropper = DropChunk(drop_start=100, drop_end=200, noise_factor=0.)\n    >>> signal = read_audio('tests/samples/single-mic/example1.wav')\n    >>> signal = signal.unsqueeze(0) # [batch, time, channels]\n    >>> length = paddle.ones([1])\n    >>> dropped_signal = dropper(signal, length)\n    >>> float(dropped_signal[:, 150])\n    0.0\n    \"\"\"\n\n    def __init__(\n            self,\n            drop_length_low=100,\n            drop_length_high=1000,\n            drop_count_low=1,\n            drop_count_high=10,\n            drop_start=0,\n            drop_end=None,\n            drop_prob=1,\n            noise_factor=0.0, ):\n        super().__init__()\n        self.drop_length_low = drop_length_low\n        self.drop_length_high = drop_length_high\n        self.drop_count_low = drop_count_low\n        self.drop_count_high = drop_count_high\n        self.drop_start = drop_start\n        self.drop_end = drop_end\n        self.drop_prob = drop_prob\n        self.noise_factor = noise_factor\n\n        # Validate low < high\n        if drop_length_low > drop_length_high:\n            raise ValueError(\"Low limit must not be more than high limit\")\n        if drop_count_low > drop_count_high:\n            raise ValueError(\"Low limit must not be more than high limit\")\n\n        # Make sure the length doesn't exceed end - start\n        if drop_end is not None and drop_end >= 0:\n            if drop_start > drop_end:\n                raise ValueError(\"Low limit must not be more than high limit\")\n\n            drop_range = drop_end - drop_start\n            self.drop_length_low = min(drop_length_low, drop_range)\n            self.drop_length_high = min(drop_length_high, drop_range)\n\n    def forward(self, waveforms, lengths):\n        \"\"\"\n        Arguments\n        ---------\n        waveforms : tensor\n            Shape should be `[batch, time]` or `[batch, time, channels]`.\n        lengths : tensor\n            Shape should be a single dimension, `[batch]`.\n        Returns\n        -------\n        Tensor of shape `[batch, time]` or\n            `[batch, time, channels]`\n        \"\"\"\n\n        # Reading input list\n        lengths = (lengths * waveforms.shape[1]).long()\n        batch_size = waveforms.shape[0]\n        dropped_waveform = waveforms.clone()\n\n        # Don't drop (return early) 1-`drop_prob` portion of the batches\n        if paddle.rand([1]) > self.drop_prob:\n            return dropped_waveform\n\n        # Store original amplitude for computing white noise amplitude\n        clean_amplitude = compute_amplitude(waveforms, lengths.unsqueeze(1))\n\n        # Pick a number of times to drop\n        drop_times = paddle.randint(\n            low=self.drop_count_low,\n            high=self.drop_count_high + 1,\n            shape=(batch_size, ), )\n\n        # Iterate batch to set mask\n        for i in range(batch_size):\n            if drop_times[i] == 0:\n                continue\n\n            # Pick lengths\n            length = paddle.randint(\n                low=self.drop_length_low,\n                high=self.drop_length_high + 1,\n                shape=(drop_times[i], ), )\n\n            # Compute range of starting locations\n            start_min = self.drop_start\n            if start_min < 0:\n                start_min += lengths[i]\n            start_max = self.drop_end\n            if start_max is None:\n                start_max = lengths[i]\n            if start_max < 0:\n                start_max += lengths[i]\n            start_max = max(0, start_max - length.max())\n\n            # Pick starting locations\n            start = paddle.randint(\n                low=start_min,\n                high=start_max + 1,\n                shape=(drop_times[i], ), )\n\n            end = start + length\n\n            # Update waveform\n            if not self.noise_factor:\n                for j in range(drop_times[i]):\n                    dropped_waveform[i, start[j]:end[j]] = 0.0\n            else:\n                # Uniform distribution of -2 to +2 * avg amplitude should\n                # preserve the average for normalization\n                noise_max = 2 * clean_amplitude[i] * self.noise_factor\n                for j in range(drop_times[i]):\n                    # zero-center the noise distribution\n                    noise_vec = paddle.rand([length[j]])\n                    noise_vec = 2 * noise_max * noise_vec - noise_max\n                    dropped_waveform[i, start[j]:end[j]] = noise_vec\n\n        return dropped_waveform\n\n\nclass SpecAugment(paddle.nn.Layer):\n    \"\"\"An implementation of the SpecAugment algorithm.\n    Reference:\n        https://arxiv.org/abs/1904.08779\n    Arguments\n    ---------\n    time_warp : bool\n        Whether applying time warping.\n    time_warp_window : int\n        Time warp window.\n    time_warp_mode : str\n        Interpolation mode for time warping (default \"bicubic\").\n    freq_mask : bool\n        Whether applying freq mask.\n    freq_mask_width : int or tuple\n        Freq mask width range.\n    n_freq_mask : int\n        Number of freq mask.\n    time_mask : bool\n        Whether applying time mask.\n    time_mask_width : int or tuple\n        Time mask width range.\n    n_time_mask : int\n        Number of time mask.\n    replace_with_zero : bool\n        If True, replace masked value with 0, else replace masked value with mean of the input tensor.\n    Example\n    -------\n    >>> aug = SpecAugment()\n    >>> a = paddle.rand([8, 120, 80])\n    >>> a = aug(a)\n    >>> print(a.shape)\n    paddle.Size([8, 120, 80])\n    \"\"\"\n\n    def __init__(\n            self,\n            time_warp=True,\n            time_warp_window=5,\n            time_warp_mode=\"bicubic\",\n            freq_mask=True,\n            freq_mask_width=(0, 20),\n            n_freq_mask=2,\n            time_mask=True,\n            time_mask_width=(0, 100),\n            n_time_mask=2,\n            replace_with_zero=True, ):\n        super().__init__()\n        assert (\n            time_warp or freq_mask or time_mask\n        ), \"at least one of time_warp, time_mask, or freq_mask should be applied\"\n\n        self.apply_time_warp = time_warp\n        self.time_warp_window = time_warp_window\n        self.time_warp_mode = time_warp_mode\n\n        self.freq_mask = freq_mask\n        if isinstance(freq_mask_width, int):\n            freq_mask_width = (0, freq_mask_width)\n        self.freq_mask_width = freq_mask_width\n        self.n_freq_mask = n_freq_mask\n\n        self.time_mask = time_mask\n        if isinstance(time_mask_width, int):\n            time_mask_width = (0, time_mask_width)\n        self.time_mask_width = time_mask_width\n        self.n_time_mask = n_time_mask\n\n        self.replace_with_zero = replace_with_zero\n\n    def forward(self, x):\n        \"\"\"Takes in input a tensors and returns an augmented one.\"\"\"\n        if self.apply_time_warp:\n            x = self.time_warp(x)\n        if self.freq_mask:\n            x = self.mask_along_axis(x, dim=2)\n        if self.time_mask:\n            x = self.mask_along_axis(x, dim=1)\n        return x\n\n    def time_warp(self, x):\n        \"\"\"Time warping with paddle.nn.functional.interpolate\"\"\"\n        original_size = x.shape\n        window = self.time_warp_window\n\n        # 2d interpolation requires 4D or higher dimension tensors\n        # x: (Batch, Time, Freq) -> (Batch, 1, Time, Freq)\n        if x.dim() == 3:\n            x = x.unsqueeze(1)\n\n        time = x.shape[2]\n        if time - window <= window:\n            return x.reshape([*original_size])\n\n        # compute center and corresponding window\n        c = paddle.randint(window, time - window, (1, ))[0]\n        w = paddle.randint(c - window, c + window, (1, ))[0] + 1\n\n        left = paddle.nn.functional.interpolate(\n            x[:, :, :c],\n            (w, x.shape[3]),\n            mode=self.time_warp_mode,\n            align_corners=True, )\n        right = paddle.nn.functional.interpolate(\n            x[:, :, c:],\n            (time - w, x.shape[3]),\n            mode=self.time_warp_mode,\n            align_corners=True, )\n\n        x[:, :, :w] = left\n        x[:, :, w:] = right\n        return x.reshape([*original_size])\n\n    def mask_along_axis(self, x, dim):\n        \"\"\"Mask along time or frequency axis.\n        Arguments\n        ---------\n        x : tensor\n            Input tensor.\n        dim : int\n            Corresponding dimension to mask.\n        \"\"\"\n        original_size = x.shape\n        if x.dim() == 4:\n            x = x.reshape([-1, x.shape[2], x.shape[3]])\n\n        batch, time, fea = x.shape\n\n        if dim == 1:\n            D = time\n            n_mask = self.n_time_mask\n            width_range = self.time_mask_width\n        else:\n            D = fea\n            n_mask = self.n_freq_mask\n            width_range = self.freq_mask_width\n\n        mask_len = paddle.randint(width_range[0], width_range[1],\n                                  (batch, n_mask)).unsqueeze(2)\n\n        mask_pos = paddle.randint(0, max(1, D - mask_len.max()),\n                                  (batch, n_mask)).unsqueeze(2)\n\n        # compute masks\n        arange = paddle.arange(end=D).reshape([1, 1, -1])\n        mask = (mask_pos <= arange) * (arange < (mask_pos + mask_len))\n        mask = mask.any(axis=1)\n\n        if dim == 1:\n            mask = mask.unsqueeze(2)\n        else:\n            mask = mask.unsqueeze(1)\n\n        if self.replace_with_zero:\n            val = 0.0\n        else:\n            val = x.mean()\n        # same to x.masked_fill_(mask, val)\n        y = paddle.full(x.shape, val, x.dtype)\n        x = paddle.where(mask, y, x)\n        return x.reshape([*original_size])\n\n\nclass TimeDomainSpecAugment(nn.Layer):\n    \"\"\"A time-domain approximation of the SpecAugment algorithm.\n    This augmentation module implements three augmentations in\n    the time-domain.\n     1. Drop chunks of the audio (zero amplitude or white noise)\n     2. Drop frequency bands (with band-drop filters)\n     3. Speed peturbation (via resampling to slightly different rate)\n    Arguments\n    ---------\n    perturb_prob : float from 0 to 1\n        The probability that a batch will have speed perturbation applied.\n    drop_freq_prob : float from 0 to 1\n        The probability that a batch will have frequencies dropped.\n    drop_chunk_prob : float from 0 to 1\n        The probability that a batch will have chunks dropped.\n    speeds : list of ints\n        A set of different speeds to use to perturb each batch.\n        See ``speechbrain.processing.speech_augmentation.SpeedPerturb``\n    sample_rate : int\n        Sampling rate of the input waveforms.\n    drop_freq_count_low : int\n        Lowest number of frequencies that could be dropped.\n    drop_freq_count_high : int\n        Highest number of frequencies that could be dropped.\n    drop_chunk_count_low : int\n        Lowest number of chunks that could be dropped.\n    drop_chunk_count_high : int\n        Highest number of chunks that could be dropped.\n    drop_chunk_length_low : int\n        Lowest length of chunks that could be dropped.\n    drop_chunk_length_high : int\n        Highest length of chunks that could be dropped.\n    drop_chunk_noise_factor : float\n        The noise factor used to scale the white noise inserted, relative to\n        the average amplitude of the utterance. Default 0 (no noise inserted).\n    Example\n    -------\n    >>> inputs = paddle.randn([10, 16000])\n    >>> feature_maker = TimeDomainSpecAugment(speeds=[80])\n    >>> feats = feature_maker(inputs, paddle.ones(10))\n    >>> feats.shape\n    paddle.shape([10, 12800])\n    \"\"\"\n\n    def __init__(\n            self,\n            perturb_prob=1.0,\n            drop_freq_prob=1.0,\n            drop_chunk_prob=1.0,\n            speeds=[95, 100, 105],\n            sample_rate=16000,\n            drop_freq_count_low=0,\n            drop_freq_count_high=3,\n            drop_chunk_count_low=0,\n            drop_chunk_count_high=5,\n            drop_chunk_length_low=1000,\n            drop_chunk_length_high=2000,\n            drop_chunk_noise_factor=0, ):\n        super().__init__()\n        self.speed_perturb = SpeedPerturb(\n            perturb_prob=perturb_prob, orig_freq=sample_rate, speeds=speeds)\n        self.drop_freq = DropFreq(\n            drop_prob=drop_freq_prob,\n            drop_count_low=drop_freq_count_low,\n            drop_count_high=drop_freq_count_high, )\n        self.drop_chunk = DropChunk(\n            drop_prob=drop_chunk_prob,\n            drop_count_low=drop_chunk_count_low,\n            drop_count_high=drop_chunk_count_high,\n            drop_length_low=drop_chunk_length_low,\n            drop_length_high=drop_chunk_length_high,\n            noise_factor=drop_chunk_noise_factor, )\n\n    def forward(self, waveforms, lengths):\n        \"\"\"Returns the distorted waveforms.\n        Arguments\n        ---------\n        waveforms : tensor\n            The waveforms to distort\n        \"\"\"\n        # Augmentation\n        with paddle.no_grad():\n            waveforms = self.speed_perturb(waveforms)\n            waveforms = self.drop_freq(waveforms)\n            waveforms = self.drop_chunk(waveforms, lengths)\n        return waveforms\n"
  },
  {
    "path": "paddlespeech/s2t/models/wav2vec2/wav2vec2_ASR.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import defaultdict\nfrom typing import Dict\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.s2t.models.wav2vec2.modules.modeling_wav2vec2 import Wav2Vec2ConfigPure\nfrom paddlespeech.s2t.models.wav2vec2.modules.modeling_wav2vec2 import Wav2Vec2Model\nfrom paddlespeech.s2t.models.wav2vec2.modules.VanillaNN import VanillaNN\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import SpecAugment\nfrom paddlespeech.s2t.modules.ctc import CTCDecoderBase as CTC\nfrom paddlespeech.s2t.modules.initializer import DefaultInitializerContext\nfrom paddlespeech.s2t.utils.ctc_utils import remove_duplicates_and_blank\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import log_add\n\nlogger = Log(__name__).getlog()\n\n\nclass Wav2vec2ASR(nn.Layer):\n    def __init__(self, config: dict):\n        super().__init__()\n        init_type = config.get(\"init_type\", None)\n        with DefaultInitializerContext(init_type):\n            self.config = config\n            wav2vec2_config = Wav2Vec2ConfigPure(config)\n            wav2vec2 = Wav2Vec2Model(wav2vec2_config)\n            self.normalize_wav = config.normalize_wav\n            self.output_norm = config.output_norm\n            if hasattr(config, 'spec_augment'):\n                self.spec_augment = SpecAugment(**config.spec_augment)\n\n            if config.freeze_wav2vec2:\n                wav2vec2.eval()\n                for parm in wav2vec2.parameters():\n                    parm.trainable = False\n            self.wav2vec2 = wav2vec2\n            self.enc = VanillaNN(**config.enc)\n            self.ctc = CTC(**config.ctc,\n                           odim=config.output_dim,\n                           batch_average=False,\n                           reduction='mean')\n\n    def forward(self, wav, wavs_lens_rate, target, target_lens):\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n\n        # Extract wav2vec output\n        out = self.wav2vec2(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n\n        if self.training and hasattr(self.config, 'spec_augment'):\n            feats = self.spec_augment(out)\n        else:\n            feats = out\n\n        x = self.enc(feats)\n\n        x_lens = (wavs_lens_rate * x.shape[1]).round().astype(paddle.int64)\n\n        ctc_loss = self.ctc(x, x_lens, target, target_lens)\n\n        return ctc_loss\n\n    @paddle.no_grad()\n    def decode(self,\n               feats: paddle.Tensor,\n               text_feature: Dict[str, int],\n               decoding_method: str,\n               beam_size: int,\n               tokenizer: str=None,\n               sb_pipeline=False):\n        batch_size = feats.shape[0]\n\n        if decoding_method == 'ctc_prefix_beam_search' and batch_size > 1:\n            logger.error(\n                f\"decoding mode {decoding_method} must be running with batch_size == 1\"\n            )\n            logger.error(f\"current batch_size is {batch_size}\")\n\n        if decoding_method == 'ctc_greedy_search':\n            if tokenizer is None and sb_pipeline is False:\n                hyps = self.ctc_greedy_search(feats)\n                res = [text_feature.defeaturize(hyp) for hyp in hyps]\n                res_tokenids = [hyp for hyp in hyps]\n            else:\n                if sb_pipeline is True:\n                    hyps = self.ctc_greedy_search(feats.unsqueeze(-1))\n                else:\n                    hyps = self.ctc_greedy_search(feats)\n                res = []\n                res_tokenids = []\n                for sequence in hyps:\n                    # Decode token terms to words \n                    predicted_tokens = text_feature.convert_ids_to_tokens(\n                        sequence)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n\n        # ctc_prefix_beam_search and attention_rescoring only return one\n        # result in List[int], change it to List[List[int]] for compatible\n        # with other batch decoding mode\n        elif decoding_method == 'ctc_prefix_beam_search':\n            assert feats.shape[0] == 1\n            if tokenizer is None and sb_pipeline is False:\n                hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = [text_feature.defeaturize(hyp)]\n                res_tokenids = [hyp]\n            else:\n                if sb_pipeline is True:\n                    hyp = self.ctc_prefix_beam_search(\n                        feats.unsqueeze(-1), beam_size)\n                else:\n                    hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = []\n                res_tokenids = []\n                predicted_tokens = text_feature.convert_ids_to_tokens(hyp)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n        else:\n            raise ValueError(\n                f\"wav2vec2 not support decoding method: {decoding_method}\")\n\n        return res, res_tokenids\n\n    @classmethod\n    def from_config(cls, config):\n        model = cls(config)\n        return model\n\n    def ctc_greedy_search(self, wav) -> List[List[int]]:\n        \"\"\" Apply CTC greedy search\n        Args:\n            speech (paddle.Tensor): (batch, max_len)\n            speech_length (paddle.Tensor): (batch, )\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        batch_size = wav.shape[0]\n        wav = wav[:, :, 0]\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wav2vec output\n        out = self.wav2vec2(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n        x = self.enc(feats)\n        x_lens = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (B, maxlen, vocab_size)\n        topk_prob, topk_index = ctc_probs.topk(1, axis=2)  # (B, maxlen, 1)\n        topk_index = topk_index.reshape([batch_size, x_lens])  # (B, maxlen)\n\n        hyps = [hyp.tolist() for hyp in topk_index]\n        hyps = [remove_duplicates_and_blank(hyp) for hyp in hyps]\n        return hyps\n\n    def _ctc_prefix_beam_search(\n            self,\n            wav,\n            beam_size,\n            blank_id: int=0, ) -> Tuple[List[Tuple[int, float]], paddle.Tensor]:\n        \"\"\" CTC prefix beam search inner implementation\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[Tuple[int, float]]: nbest results, (N,1), (text, likelihood)\n            paddle.Tensor: encoder output, (1, max_len, encoder_dim),\n                it will be used for rescoring in attention rescoring mode\n        \"\"\"\n        wav = wav[:, :, 0]\n\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wav2vec output\n        out = self.wav2vec2(wav)[0]\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n\n        x = self.enc(feats)\n        maxlen = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (1, maxlen, vocab_size)\n        ctc_probs = ctc_probs.squeeze(0)\n\n        # cur_hyps: (prefix, (blank_ending_score, none_blank_ending_score))\n        # blank_ending_score and  none_blank_ending_score in ln domain\n        cur_hyps = [(tuple(), (0.0, -float('inf')))]\n        # 2. CTC beam search step by step\n        for t in range(0, maxlen):\n            logp = ctc_probs[t]  # (vocab_size,)\n            # key: prefix, value (pb, pnb), default value(-inf, -inf)\n            next_hyps = defaultdict(lambda: (-float('inf'), -float('inf')))\n            # 2.1 First beam prune: select topk best\n            top_k_logp, top_k_index = logp.topk(beam_size)  # (beam_size,)\n            for s in top_k_index:\n                s = s.item()\n                ps = logp[s].item()\n                for prefix, (pb, pnb) in cur_hyps:\n                    last = prefix[-1] if len(prefix) > 0 else None\n                    if s == blank_id:  # blank\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pb = log_add([n_pb, pb + ps, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                    elif s == last:\n                        #  Update *ss -> *s;\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pnb = log_add([n_pnb, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                        # Update *s-s -> *ss, - is for blank\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n                    else:\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps, pnb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n\n            # 2.2 Second beam prune\n            next_hyps = sorted(\n                next_hyps.items(),\n                key=lambda x: log_add(list(x[1])),\n                reverse=True)\n            cur_hyps = next_hyps[:beam_size]\n\n        hyps = [(y[0], log_add([y[1][0], y[1][1]])) for y in cur_hyps]\n        return hyps\n\n    def ctc_prefix_beam_search(self, wav, beam_size) -> List[int]:\n        \"\"\" Apply CTC prefix beam search\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[int]: CTC prefix beam search nbest results\n        \"\"\"\n        hyps = self._ctc_prefix_beam_search(wav, beam_size)\n        return hyps[0][0]\n\n\nclass Wav2vec2Base(nn.Layer):\n    \"\"\"Wav2vec2 model\"\"\"\n\n    def __init__(self, config: dict):\n        super().__init__()\n        wav2vec2_config = Wav2Vec2ConfigPure(config)\n        wav2vec2 = Wav2Vec2Model(wav2vec2_config)\n        self.wav2vec2 = wav2vec2\n\n    @classmethod\n    def from_config(cls, configs: dict):\n        \"\"\"init model.\n        Args:\n            configs (dict): config dict.\n        Raises:\n            ValueError: raise when using not support encoder type.\n        Returns:\n            nn.Layer: Wav2Vec2Base\n        \"\"\"\n        model = cls(configs)\n        return model\n\n    def forward(self, wav):\n        out = self.wav2vec2(wav)\n        return out\n"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/__init__.py",
    "content": "from .wavlm_paddle import WavLM, WavLMConfig\nfrom .wavlm_asr import WavLMASR, WavLMBase"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/modules/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/modules/activations.py",
    "content": "# Copyright 2020 The HuggingFace Team. All rights reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport math\n\nimport paddle\nimport paddle.nn.functional as F\n\n\ndef _gelu_python(x):\n    \"\"\"\n    Original Implementation of the GELU activation function in Google BERT repo when initially created. For\n    information: OpenAI GPT's GELU is slightly different (and gives slightly different results): 0.5 * x * (1 +\n    torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) This is now written in C in\n    torch.nn.functional Also see the Gaussian Error Linear Units paper: https://arxiv.org/abs/1606.08415\n    \"\"\"\n    return x * 0.5 * (1.0 + paddle.erf(x / math.sqrt(2.0)))\n\n\n\n\ndef gelu_new(x):\n    \"\"\"\n    Implementation of the GELU activation function currently in Google BERT repo (identical to OpenAI GPT). Also see\n    the Gaussian Error Linear Units paper: https://arxiv.org/abs/1606.08415\n    \"\"\"\n    return 0.5 * x * (1.0 + paddle.tanh(\n        math.sqrt(2.0 / math.pi) * (x + 0.044715 * paddle.pow(x, 3.0))))\n\n\ndef gelu_fast(x):\n    return 0.5 * x * (1.0 + paddle.tanh(x * 0.7978845608 *\n                                        (1.0 + 0.044715 * x * x)))\n\ngelu = gelu_fast\n\ndef _silu_python(x):\n    \"\"\"\n    See Gaussian Error Linear Units (Hendrycks et al., https://arxiv.org/abs/1606.08415) where the SiLU (Sigmoid Linear\n    Unit) was originally introduced and coined, and see Sigmoid-Weighted Linear Units for Neural Network Function\n    Approximation in Reinforcement Learning (Elfwing et al., https://arxiv.org/abs/1702.03118) and Swish: a Self-Gated\n    Activation Function (Ramachandran et al., https://arxiv.org/abs/1710.05941v1) where the SiLU was experimented with\n    later.\n    \"\"\"\n    return x * paddle.nn.functional.sigmoid(x)\n\n\ndef mish(x):\n    return x * paddle.tanh(paddle.nn.functional.softplus(x))\n\n\ndef linear_act(x):\n    return x\n\n\nACT2FN = {\n    \"relu\": F.relu,\n    \"silu\": _silu_python,\n    \"swish\": _silu_python,\n    \"gelu\": gelu,\n    \"tanh\": paddle.tanh,\n    \"gelu_new\": gelu_new,\n    \"gelu_fast\": gelu_fast,\n    \"mish\": mish,\n    \"linear\": linear_act,\n    \"sigmoid\": paddle.nn.functional.sigmoid,\n}\n\n\ndef get_activation(activation_string):\n    if activation_string in ACT2FN:\n        return ACT2FN[activation_string]\n    else:\n        raise KeyError(\n            f\"function {activation_string} not found in ACT2FN mapping {list(ACT2FN.keys())}\"\n        )"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/modules/functional.py",
    "content": "import paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\nfrom typing import Optional, List, Tuple\nimport math\n\ndef _mha_shape_check(query: paddle.Tensor, key: paddle.Tensor, value: paddle.Tensor,\n                     key_padding_mask: Optional[paddle.Tensor], attn_mask: Optional[paddle.Tensor], num_heads: int):\n    # Verifies the expected shape for `query, `key`, `value`, `key_padding_mask` and `attn_mask`\n    # and returns if the input is batched or not.\n    # Raises an error if `query` is not 2-D (unbatched) or 3-D (batched) tensor.\n\n    # Shape check.\n    if query.dim() == 3:\n        # Batched Inputs\n        is_batched = True\n        assert key.dim() == 3 and value.dim() == 3, \\\n            (\"For batched (3-D) `query`, expected `key` and `value` to be 3-D\"\n             f\" but found {key.dim()}-D and {value.dim()}-D tensors respectively\")\n        if key_padding_mask is not None:\n            assert key_padding_mask.dim() == 2, \\\n                (\"For batched (3-D) `query`, expected `key_padding_mask` to be `None` or 2-D\"\n                 f\" but found {key_padding_mask.dim()}-D tensor instead\")\n        if attn_mask is not None:\n            assert attn_mask.dim() in (2, 3), \\\n                (\"For batched (3-D) `query`, expected `attn_mask` to be `None`, 2-D or 3-D\"\n                 f\" but found {attn_mask.dim()}-D tensor instead\")\n    elif query.dim() == 2:\n        # Unbatched Inputs\n        is_batched = False\n        assert key.dim() == 2 and value.dim() == 2, \\\n            (\"For unbatched (2-D) `query`, expected `key` and `value` to be 2-D\"\n             f\" but found {key.dim()}-D and {value.dim()}-D tensors respectively\")\n\n        if key_padding_mask is not None:\n            assert key_padding_mask.dim() == 1, \\\n                (\"For unbatched (2-D) `query`, expected `key_padding_mask` to be `None` or 1-D\"\n                 f\" but found {key_padding_mask.dim()}-D tensor instead\")\n\n        if attn_mask is not None:\n            assert attn_mask.dim() in (2, 3), \\\n                (\"For unbatched (2-D) `query`, expected `attn_mask` to be `None`, 2-D or 3-D\"\n                 f\" but found {attn_mask.dim()}-D tensor instead\")\n            if attn_mask.dim() == 3:\n                expected_shape = (num_heads, query.shape[0], key.shape[0])\n                assert attn_mask.shape == expected_shape, \\\n                    (f\"Expected `attn_mask` shape to be {expected_shape} but got {attn_mask.shape}\")\n    else:\n        raise AssertionError(\n            f\"query should be unbatched 2D or batched 3D tensor but received {query.dim()}-D query tensor\")\n\n\ndef scaled_dot_product_attention(q, k, v, attn_mask, dropout_p, is_causal):\n    \"\"\"\n    Scaled Dot-Product Attention\n    \"\"\"\n    \n    d_key = k.shape[-1]\n    scaled_q = paddle.scale(x=q, scale=d_key ** -0.5)\n    product = paddle.matmul(x=scaled_q, y=k, transpose_y=True)\n    weights = F.softmax(x=product + attn_mask)\n    if dropout_p:\n        weights = F.dropout(\n            weights,\n            p=dropout_p,\n            training=True,\n            mode=\"upscale_in_train\"\n        )\n    out = paddle.matmul(x=weights, y=v)\n    return out\n\n    \ndef addr(input, vec1, vec2, beta=1, alpha=1, out=None):\n    \"\"\"\n    A helper function to calculate alpha*(vec1*vec2^T) + beta*input\n    \"\"\"\n    row = vec1.shape[0]\n    column = vec2.shape[0]\n    vec1 = paddle.unsqueeze(vec1, 0)\n    vec1 = paddle.transpose(vec1, [1, 0])\n    vec1 = paddle.expand(vec1, [row, column])\n    new_vec2 = paddle.zeros([column, column], dtype=vec2.dtype)\n    new_vec2[0, :] = vec2\n    out = alpha * paddle.matmul(vec1, new_vec2)\n    out = beta * input + out\n    return out\n\ndef multi_head_attention_forward(\n    x: paddle.Tensor,\n    num_heads: int,\n    q_proj: nn.Linear,\n    k_proj: nn.Linear,\n    v_proj: nn.Linear,\n    c_proj: nn.Linear,\n    attn_mask: Optional[paddle.Tensor] = None,\n):\n    max_len, batch_size, emb_dim = x.shape\n    head_dim = emb_dim // num_heads\n    scaling = float(head_dim) ** -0.5\n    q = q_proj(x)  # L, N, E\n    k = k_proj(x)  # L, N, E\n    v = v_proj(x)  # L, N, E\n\n    v = v.reshape((-1, batch_size * num_heads, head_dim)).transpose((1, 0, 2))\n    k = k.reshape((-1, batch_size * num_heads, head_dim)).transpose((1, 0, 2))\n    q = q.reshape((-1, batch_size * num_heads, head_dim)).transpose((1, 0, 2))\n\n    q = q * scaling\n    qk = paddle.matmul(q, k, transpose_y=True)\n    if attn_mask is not None:\n        if attn_mask.ndim == 2:\n            attn_mask.unsqueeze_(0)\n        assert attn_mask.shape[0] == 1 and attn_mask.shape[1] == max_len and attn_mask.shape[2] == max_len\n        qk += attn_mask\n\n    qk = F.softmax(qk, axis=-1)\n    atten = paddle.bmm(qk, v)\n    atten = atten.transpose((1, 0, 2))\n    atten = atten.reshape((max_len, batch_size, emb_dim))\n    atten = c_proj(atten)\n    return atten\n\ndef linear(input, weight, bias=None):\n    # compute y = x A^T + b\n    # Input: (N, in_feature) paddle tensor\n    # weight: (out_feature, in_feature) paddle tensor\n    # bias: (out_feature) paddle tensor\n    if input.dim() == 2 and bias is not None:\n        # fused op is marginally faster\n        return paddle.addmm(bias, input, weight)\n    output = paddle.matmul(input, weight)\n    if bias is not None:\n        output += bias\n    return output\n\n\ndef _in_projection_packed(\n    q: paddle.Tensor,\n    k: paddle.Tensor,\n    v: paddle.Tensor,\n    w: paddle.Tensor,\n    b: Optional[paddle.Tensor] = None,\n) -> List[paddle.Tensor]:\n    r\"\"\"\n    Performs the in-projection step of the attention operation, using packed weights.\n    Output is a triple containing projection tensors for query, key and value.\n    Args:\n        q, k, v: query, key and value tensors to be projected. For self-attention,\n            these are typically the same tensor; for encoder-decoder attention,\n            k and v are typically the same tensor. (We take advantage of these\n            identities for performance if they are present.) Regardless, q, k and v\n            must share a common embedding dimension; otherwise their shapes may vary.\n        w: projection weights for q, k and v, packed into a single tensor. Weights\n            are packed along dimension 0, in q, k, v order.\n        b: optional projection biases for q, k and v, packed into a single tensor\n            in q, k, v order.\n    Shape:\n        Inputs:\n        - q: :math:`(..., E)` where E is the embedding dimension\n        - k: :math:`(..., E)` where E is the embedding dimension\n        - v: :math:`(..., E)` where E is the embedding dimension\n        - w: :math:`(E * 3, E)` where E is the embedding dimension\n        - b: :math:`E * 3` where E is the embedding dimension\n        Output:\n        - in output list :math:`[q', k', v']`, each output tensor will have the\n            same shape as the corresponding input tensor.\n    \"\"\"\n    E = q.shape[-1]\n    if k is v:\n        if q is k:\n            # self-attention\n            proj = F.linear(q, w, b)\n            # reshape to 3, E and not E, 3 is deliberate for better memory coalescing and keeping same order as chunk()\n            proj = proj.unflatten(-1, (3, E)).unsqueeze(0).transpose([2, 1, 0]).squeeze(-2).contiguous()\n            return proj[0], proj[1], proj[2]\n        else:\n            # encoder-decoder attention\n            w_q, w_kv = w.split([E, E * 2])\n            if b is None:\n                b_q = b_kv = None\n            else:\n                b_q, b_kv = b.split([E, E * 2])\n            q_proj = F.linear(q, w_q, b_q)\n            kv_proj = F.linear(k, w_kv, b_kv)\n            # reshape to 2, E and not E, 2 is deliberate for better memory coalescing and keeping same order as chunk()\n            kv_proj = kv_proj.unflatten(-1, (2, E)).unsqueeze(0).transpose([2, 1, 0]).squeeze(-2).contiguous()\n            return (q_proj, kv_proj[0], kv_proj[1])\n    else:\n        w_q, w_k, w_v = w.chunk(3)\n        if b is None:\n            b_q = b_k = b_v = None\n        else:\n            b_q, b_k, b_v = b.chunk(3)\n        return F.linear(q, w_q, b_q), F.linear(k, w_k, b_k), F.linear(v, w_v, b_v)\n    \ndef _in_projection(\n    q: paddle.Tensor,\n    k: paddle.Tensor,\n    v: paddle.Tensor,\n    w_q: paddle.Tensor,\n    w_k: paddle.Tensor,\n    w_v: paddle.Tensor,\n    b_q: Optional[paddle.Tensor] = None,\n    b_k: Optional[paddle.Tensor] = None,\n    b_v: Optional[paddle.Tensor] = None,\n) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n    A, B, C = F.linear(q, w_q, b_q), F.linear(k, w_k, b_k), F.linear(v, w_v, b_v)    \n    return A, B, C\n    \ndef multi_head_attention_forward_paddle(\n    query: paddle.Tensor,\n    key: paddle.Tensor,\n    value: paddle.Tensor,\n    embed_dim_to_check: int,\n    num_heads: int,\n    in_proj_weight: Optional[paddle.Tensor],\n    in_proj_bias: Optional[paddle.Tensor],\n    bias_k: Optional[paddle.Tensor],\n    bias_v: Optional[paddle.Tensor],\n    add_zero_attn: bool,\n    dropout_p: float,\n    out_proj_weight: paddle.Tensor,\n    out_proj_bias: Optional[paddle.Tensor],\n    training: bool = True,\n    key_padding_mask: Optional[paddle.Tensor] = None,\n    need_weights: bool = True,\n    attn_mask: Optional[paddle.Tensor] = None,\n    use_separate_proj_weight: bool = False,\n    q_proj_weight: Optional[paddle.Tensor] = None,\n    k_proj_weight: Optional[paddle.Tensor] = None,\n    v_proj_weight: Optional[paddle.Tensor] = None,\n    static_k: Optional[paddle.Tensor] = None,\n    static_v: Optional[paddle.Tensor] = None,\n    average_attn_weights: bool = True,\n    is_causal: bool = False,\n) -> Tuple[paddle.Tensor, Optional[paddle.Tensor]]:\n    r\"\"\"\n    Args:\n        query, key, value: map a query and a set of key-value pairs to an output.\n            See \"Attention Is All You Need\" for more details.\n        embed_dim_to_check: total dimension of the model.\n        num_heads: parallel attention heads.\n        in_proj_weight, in_proj_bias: input projection weight and bias.\n        bias_k, bias_v: bias of the key and value sequences to be added at dim=0.\n        add_zero_attn: add a new batch of zeros to the key and\n                       value sequences at dim=1.\n        dropout_p: probability of an element to be zeroed.\n        out_proj_weight, out_proj_bias: the output projection weight and bias.\n        training: apply dropout if is ``True``.\n        key_padding_mask: if provided, specified padding elements in the key will\n            be ignored by the attention. This is an binary mask. When the value is True,\n            the corresponding value on the attention layer will be filled with -inf.\n        need_weights: output attn_output_weights.\n        attn_mask: 2D or 3D mask that prevents attention to certain positions. A 2D mask will be broadcasted for all\n            the batches while a 3D mask allows to specify a different mask for the entries of each batch.\n        is_causal: If specified, applies a causal mask as attention mask, and ignores\n            attn_mask for computing scaled dot product attention.\n            Default: ``False``.\n        use_separate_proj_weight: the function accept the proj. weights for query, key,\n            and value in different forms. If false, in_proj_weight will be used, which is\n            a combination of q_proj_weight, k_proj_weight, v_proj_weight.\n        q_proj_weight, k_proj_weight, v_proj_weight, in_proj_bias: input projection weight and bias.\n        static_k, static_v: static key and value used for attention operators.\n        average_attn_weights: If true, indicates that the returned ``attn_weights`` should be averaged across heads.\n            Otherwise, ``attn_weights`` are provided separately per head. Note that this flag only has an effect\n            when ``need_weights=True.``. Default: True\n    Shape:\n        Inputs:\n        - query: :math:`(L, E)` or :math:`(L, N, E)` where L is the target sequence length, N is the batch size, E is\n          the embedding dimension.\n        - key: :math:`(S, E)` or :math:`(S, N, E)`, where S is the source sequence length, N is the batch size, E is\n          the embedding dimension.\n        - value: :math:`(S, E)` or :math:`(S, N, E)` where S is the source sequence length, N is the batch size, E is\n          the embedding dimension.\n        - key_padding_mask: :math:`(S)` or :math:`(N, S)` where N is the batch size, S is the source sequence length.\n          If a FloatTensor is provided, it will be directly added to the value.\n          If a BoolTensor is provided, the positions with the\n          value of ``True`` will be ignored while the position with the value of ``False`` will be unchanged.\n        - attn_mask: 2D mask :math:`(L, S)` where L is the target sequence length, S is the source sequence length.\n          3D mask :math:`(N*num_heads, L, S)` where N is the batch size, L is the target sequence length,\n          S is the source sequence length. attn_mask ensures that position i is allowed to attend the unmasked\n          positions. If a BoolTensor is provided, positions with ``True``\n          are not allowed to attend while ``False`` values will be unchanged. If a FloatTensor\n          is provided, it will be added to the attention weight.\n        - static_k: :math:`(N*num_heads, S, E/num_heads)`, where S is the source sequence length,\n          N is the batch size, E is the embedding dimension. E/num_heads is the head dimension.\n        - static_v: :math:`(N*num_heads, S, E/num_heads)`, where S is the source sequence length,\n          N is the batch size, E is the embedding dimension. E/num_heads is the head dimension.\n        Outputs:\n        - attn_output: :math:`(L, E)` or :math:`(L, N, E)` where L is the target sequence length, N is the batch size,\n          E is the embedding dimension.\n        - attn_output_weights: Only returned when ``need_weights=True``. If ``average_attn_weights=True``, returns\n          attention weights averaged across heads of shape :math:`(L, S)` when input is unbatched or\n          :math:`(N, L, S)`, where :math:`N` is the batch size, :math:`L` is the target sequence length, and\n          :math:`S` is the source sequence length. If ``average_attn_weights=False``, returns attention weights per\n          head of shape :math:`(num_heads, L, S)` when input is unbatched or :math:`(N, num_heads, L, S)`.\n    \"\"\"\n    \n    is_batched = _mha_shape_check(query, key, value, key_padding_mask, attn_mask, num_heads)\n    tgt_len, bsz, embed_dim = query.shape\n    src_len, _, _ = key.shape\n\n    if is_causal:\n        attn_mask = None\n\n    assert embed_dim == embed_dim_to_check, \\\n        f\"was expecting embedding dimension of {embed_dim_to_check}, but got {embed_dim}\"\n    if isinstance(embed_dim, paddle.Tensor):\n        # embed_dim can be a tensor when JIT tracing\n        head_dim = embed_dim.div(num_heads, rounding_mode='trunc')\n    else:\n        head_dim = embed_dim // num_heads\n    assert head_dim * num_heads == embed_dim, f\"embed_dim {embed_dim} not divisible by num_heads {num_heads}\"\n    if use_separate_proj_weight:\n        # allow MHA to have different embedding dimensions when separate projection weights are used\n        assert key.shape[:2] == value.shape[:2], \\\n            f\"key's sequence and batch dims {key.shape[:2]} do not match value's {value.shape[:2]}\"\n    else:\n        assert key.shape == value.shape, f\"key shape {key.shape} does not match value shape {value.shape}\"\n\n    #\n    # compute in-projection\n    #\n    if not use_separate_proj_weight:\n        assert in_proj_weight is not None, \"use_separate_proj_weight is False but in_proj_weight is None\"\n        q, k, v = _in_projection_packed(query, key, value, in_proj_weight, in_proj_bias)\n        \n    else:\n        assert q_proj_weight is not None, \"use_separate_proj_weight is True but q_proj_weight is None\"\n        assert k_proj_weight is not None, \"use_separate_proj_weight is True but k_proj_weight is None\"\n        assert v_proj_weight is not None, \"use_separate_proj_weight is True but v_proj_weight is None\"\n        if in_proj_bias is None:\n            b_q = b_k = b_v = None\n        else:\n            b_q, b_k, b_v = in_proj_bias.chunk(3)\n        \n        q, k, v = _in_projection(query, key, value, q_proj_weight, k_proj_weight, v_proj_weight, b_q, b_k, b_v)\n    \n    # prep attention mask\n\n    if attn_mask is not None:\n        # ensure attn_mask's dim is 3\n        if attn_mask.dim() == 2:\n            correct_2d_size = (tgt_len, src_len)\n            if attn_mask.shape != correct_2d_size:\n                raise RuntimeError(f\"The shape of the 2D attn_mask is {attn_mask.shape}, but should be {correct_2d_size}.\")\n            attn_mask = attn_mask.unsqueeze(0)\n        elif attn_mask.dim() == 3:\n            correct_3d_size = (bsz * num_heads, tgt_len, src_len)\n            if tuple(attn_mask.shape) != correct_3d_size:\n                raise RuntimeError(f\"The shape of the 3D attn_mask is {attn_mask.shape}, but should be {correct_3d_size}.\")\n        else:\n            raise RuntimeError(f\"attn_mask's dimension {attn_mask.dim()} is not supported\")\n\n    # add bias along batch dimension (currently second)\n    if bias_k is not None and bias_v is not None:\n        assert static_k is None, \"bias cannot be added to static key.\"\n        assert static_v is None, \"bias cannot be added to static value.\"\n        k = paddle.concat([k, bias_k.repeat(1, bsz, 1)], axis=1)\n        v = paddle.concat([v, bias_v.repeat(1, bsz, 1)], axis=1)\n        if attn_mask is not None:\n            # attn_mask = pad(attn_mask, (0, 1))\n            # pad last dim with 0 on one side and 1 on the other\n            attn_mask = paddle.concat([attn_mask, paddle.zeros_like(attn_mask[:, :, -1:])], axis=2)\n        if key_padding_mask is not None:\n            # key_padding_mask = pad(key_padding_mask, (0, 1))\n            # pad last dim with 0 on one side and 1 on the other\n            key_padding_mask = paddle.concat([key_padding_mask, paddle.zeros_like(key_padding_mask[:, -1:])], axis=1)\n    else:\n        assert bias_k is None\n        assert bias_v is None\n\n    #\n    # reshape q, k, v for multihead attention and make em batch first\n    #\n    q = q.reshape([tgt_len, bsz * num_heads, head_dim]).transpose([1, 0, 2])\n\n    \n    if static_k is None:\n        k = k.reshape([k.shape[0], bsz * num_heads, head_dim]).transpose([1, 0, 2])\n    else:\n        assert static_k.size(0) == bsz * num_heads, \\\n            f\"expecting static_k.size(0) of {bsz * num_heads}, but got {static_k.size(0)}\"\n        assert static_k.size(2) == head_dim, \\\n            f\"expecting static_k.size(2) of {head_dim}, but got {static_k.size(2)}\"\n        k = static_k\n    if static_v is None:\n        v = v.reshape([v.shape[0], bsz * num_heads, head_dim]).transpose([1, 0, 2])\n    else:\n        # TODO finish disentangling control flow so we don't do in-projections when statics are passed\n        assert static_v.size(0) == bsz * num_heads, \\\n            f\"expecting static_v.size(0) of {bsz * num_heads}, but got {static_v.size(0)}\"\n        assert static_v.size(2) == head_dim, \\\n            f\"expecting static_v.size(2) of {head_dim}, but got {static_v.size(2)}\"\n        v = static_v\n\n    # add zero attention along batch dimension (now first)\n    if add_zero_attn:\n        zero_attn_shape = (bsz * num_heads, 1, head_dim)\n        k = paddle.concat([k, paddle.zeros(zero_attn_shape, dtype=k.dtype, device=k.device)], axis=1)\n        v = paddle.concat([v, paddle.zeros(zero_attn_shape, dtype=v.dtype, device=v.device)], axis=1)\n        if attn_mask is not None:\n            # attn_mask = pad(attn_mask, (0, 1))\n            attn_mask = paddle.concat([attn_mask, paddle.zeros_like(attn_mask[:, :, -1:])], axis=2)\n        if key_padding_mask is not None:\n            # key_padding_mask = pad(key_padding_mask, (0, 1))\n            key_padding_mask = paddle.concat([key_padding_mask, paddle.zeros_like(key_padding_mask[:, -1:])], axis=1)\n\n    # update source sequence length after adjustments\n    src_len = k.shape[1]\n\n    # merge key padding and attention masks\n    if key_padding_mask is not None:\n        assert key_padding_mask.shape == (bsz, src_len), \\\n            f\"expecting key_padding_mask shape of {(bsz, src_len)}, but got {key_padding_mask.shape}\"\n        key_padding_mask = key_padding_mask.reshape([bsz, 1, 1, src_len]).expand([-1, num_heads, -1, -1]).reshape([bsz * num_heads, 1, src_len])\n        if attn_mask is None:\n            attn_mask = key_padding_mask\n        else:\n            attn_mask = attn_mask + key_padding_mask\n\n    # adjust dropout probability\n    if not training:\n        dropout_p = 0.0\n\n    #\n    # (deep breath) calculate attention and out projection\n    #\n    if need_weights:\n        B, Nt, E = q.shape\n        q_scaled = q / math.sqrt(E)\n        if attn_mask is not None:\n            attn_output_weights = addr(q_scaled, k.transpose(-2, -1))\n        else:\n            attn_output_weights = paddle.bmm(q_scaled, k.transpose(0, 2, 1))\n        attn_output_weights = F.softmax(attn_output_weights, axis=-1)\n        if dropout_p > 0.0:\n            attn_output_weights = F.dropout(attn_output_weights, p=dropout_p)\n\n        attn_output = paddle.bmm(attn_output_weights, v)\n        attn_output = attn_output.transpose([1, 0, 2]).reshape([tgt_len * bsz, embed_dim])\n        # attn_output = linear(attn_output, out_proj_weight, out_proj_bias)\n        attn_output = F.linear(attn_output, out_proj_weight, out_proj_bias)\n        attn_output = attn_output.reshape([tgt_len, bsz, attn_output.shape[1]])\n\n        # optionally average attention weights over heads\n        attn_output_weights = attn_output_weights.reshape([bsz, num_heads, tgt_len, src_len])\n        if average_attn_weights:\n            attn_output_weights = attn_output_weights.mean(dim=1)\n\n        if not is_batched:\n            # squeeze the output if input was unbatched\n            attn_output = attn_output.squeeze(1)\n            attn_output_weights = attn_output_weights.squeeze(0)\n        return attn_output, attn_output_weights\n    else:\n        # attn_mask can be either (L,S) or (N*num_heads, L, S)\n        # if attn_mask's shape is (1, L, S) we need to unsqueeze to (1, 1, L, S)\n        # in order to match the input for SDPA of (N, num_heads, L, S)\n        if attn_mask is not None:\n            if attn_mask.shape[0] == 1 and attn_mask.dim() == 3:\n                attn_mask = attn_mask.unsqueeze(0)\n            else:\n                attn_mask = attn_mask.reshape([bsz, num_heads, -1, src_len])\n\n        q = q.reshape([bsz, num_heads, tgt_len, head_dim])\n        k = k.reshape([bsz, num_heads, src_len, head_dim])\n        v = v.reshape([bsz, num_heads, src_len, head_dim])\n        attn_output = scaled_dot_product_attention(q, k, v, attn_mask, dropout_p, is_causal)\n        attn_output = attn_output.transpose(perm=[2, 0, 1, 3]).reshape([bsz * tgt_len, embed_dim])\n        attn_output = F.linear(attn_output, out_proj_weight, out_proj_bias)\n        attn_output = attn_output.reshape([tgt_len, bsz, attn_output.shape[1]])\n        return attn_output, None"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/modules/modules.py",
    "content": "# --------------------------------------------------------\n# paddle: Large-Scale Self-Supervised  Pre-training  for Full Stack Speech Processing (https://arxiv.org/abs/2110.13900.pdf)\n# Github source: https://github.com/microsoft/unilm/tree/master/paddle\n# Copyright (c) 2021 Microsoft\n# Licensed under The MIT License [see LICENSE for details]\n# Based on fairseq code bases\n# https://github.com/pytorch/fairseq\n# --------------------------------------------------------\nimport math\nimport warnings\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\nfrom paddle import Tensor\n\nfrom .functional import multi_head_attention_forward_paddle\n\n\nclass TransposeLast(nn.Layer):\n    def __init__(self, deconstruct_idx=None):\n        super().__init__()\n        self.deconstruct_idx = deconstruct_idx\n\n    def forward(self, x):\n        if self.deconstruct_idx is not None:\n            x = x[self.deconstruct_idx]\n        return paddle.transpose(x, perm=[0, 2, 1])\n\n\nclass Fp32LayerNorm(nn.LayerNorm):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n    def forward(self, input):\n        output = F.layer_norm(\n            input.float(),\n            self.normalized_shape,\n            self.weight.float() if self.weight is not None else None,\n            self.bias.float() if self.bias is not None else None,\n            self.eps, )\n        return output.type_as(input)\n\n\nclass Fp32GroupNorm(nn.GroupNorm):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n    def forward(self, input):\n        output = F.group_norm(\n            input.float(),\n            self.num_groups,\n            self.weight.float() if self.weight is not None else None,\n            self.bias.float() if self.bias is not None else None,\n            self.eps, )\n        return output.type_as(input)\n\n\nclass SamePad(nn.Layer):\n    def __init__(self, kernel_size, causal=False):\n        super().__init__()\n        if causal:\n            self.remove = kernel_size - 1\n        else:\n            self.remove = 1 if kernel_size % 2 == 0 else 0\n\n    def forward(self, x):\n        if self.remove > 0:\n            x = x[:, :, :-self.remove]\n        return x\n\n\nclass Swish(nn.Layer):\n    \"\"\"Swish function\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"Construct an MultiHeadedAttention object.\"\"\"\n        super(Swish, self).__init__()\n        self.act = nn.Sigmoid()\n\n    def forward(self, x):\n        return x * self.act(x)\n\n\nclass GLU_Linear(nn.Layer):\n    def __init__(self,\n                 input_dim,\n                 output_dim,\n                 glu_type=\"sigmoid\",\n                 bias_in_glu=True):\n        super(GLU_Linear, self).__init__()\n\n        self.glu_type = glu_type\n        self.output_dim = output_dim\n\n        if glu_type == \"sigmoid\":\n            self.glu_act = nn.Sigmoid()\n        elif glu_type == \"swish\":\n            self.glu_act = Swish()\n        elif glu_type == \"relu\":\n            self.glu_act = nn.ReLU()\n        elif glu_type == \"gelu\":\n            self.glu_act = nn.GELU()\n\n        if bias_in_glu:\n            self.linear = nn.Linear(input_dim, output_dim * 2, True)\n        else:\n            self.linear = nn.Linear(input_dim, output_dim * 2, False)\n\n    def forward(self, x):\n        # to be consistent with GLU_Linear, we assume the input always has the #channel (#dim) in the last dimension of the tensor, so need to switch the dimension first for 1D-Conv case\n        x = self.linear(x)\n\n        if self.glu_type == \"bilinear\":\n            x = (x[:, :, 0:self.output_dim] *\n                 x[:, :, self.output_dim:self.output_dim * 2])\n        else:\n            x = (x[:, :, 0:self.output_dim] *\n                 self.glu_act(x[:, :, self.output_dim:self.output_dim * 2]))\n\n        return x\n\n\ndef gelu_accurate(x):\n    if not hasattr(gelu_accurate, \"_a\"):\n        gelu_accurate._a = math.sqrt(2 / math.pi)\n    return (0.5 * x * (1 + paddle.tanh(gelu_accurate._a *\n                                       (x + 0.044715 * paddle.pow(x, 3)))))\n\n\ndef gelu(x: Tensor) -> Tensor:\n    return nn.functional.gelu(x.astype(\"float32\")).astype(x.dtype)\n\n\ndef get_activation_fn(activation: str):\n    \"\"\"Returns the activation function corresponding to `activation`\"\"\"\n\n    if activation == \"relu\":\n        return F.relu\n    elif activation == \"gelu\":\n        return gelu\n    elif activation == \"gelu_fast\":\n        warnings.warn(\n            \"--activation-fn=gelu_fast has been renamed to gelu_accurate\")\n        return gelu_accurate\n    elif activation == \"gelu_accurate\":\n        return gelu_accurate\n    elif activation == \"tanh\":\n        return paddle.tanh\n    elif activation == \"linear\":\n        return lambda x: x\n    elif activation == \"glu\":\n        return lambda x: x\n    else:\n        raise RuntimeError(\n            \"--activation-fn {} not supported\".format(activation))\n\n\ndef quant_noise(module, p, block_size):\n    \"\"\"\n    Wraps modules and applies quantization noise to the weights for\n    subsequent quantization with Iterative Product Quantization as\n    described in \"Training with Quantization Noise for Extreme Model Compression\"\n\n    Args:\n        - module: nn.Layer\n        - p: amount of Quantization Noise\n        - block_size: size of the blocks for subsequent quantization with iPQ\n\n    Remarks:\n        - Module weights must have the right sizes wrt the block size\n        - Only Linear, Embedding and Conv2d modules are supported for the moment\n        - For more detail on how to quantize by blocks with convolutional weights,\n          see \"And the Bit Goes Down: Revisiting the Quantization of Neural Networks\"\n        - We implement the simplest form of noise here as stated in the paper\n          which consists in randomly dropping blocks\n    \"\"\"\n\n    # if no quantization noise, don't register hook\n    if p <= 0:\n        return module\n\n    # supported modules\n    assert isinstance(module, (nn.Linear, nn.Embedding, nn.Conv2d))\n\n    # test whether module.weight has the right sizes wrt block_size\n    is_conv = module.weight.ndim == 4\n\n    # 2D matrix\n    if not is_conv:\n        assert (\n            module.weight.size(1) %\n            block_size == 0), \"Input features must be a multiple of block sizes\"\n\n    # 4D matrix\n    else:\n        # 1x1 convolutions\n        if module.kernel_size == (1, 1):\n            assert (module.in_channels % block_size == 0\n                    ), \"Input channels must be a multiple of block sizes\"\n        # regular convolutions\n        else:\n            k = module.kernel_size[0] * module.kernel_size[1]\n            assert k % block_size == 0, \"Kernel size must be a multiple of block size\"\n\n    def _forward_pre_hook(mod, input):\n        # no noise for evaluation\n        if mod.training:\n            if not is_conv:\n                # gather weight and sizes\n                weight = mod.weight\n                in_features = weight.size(1)\n                out_features = weight.size(0)\n\n                # split weight matrix into blocks and randomly drop selected blocks\n                mask = paddle.zeros(\n                    in_features // block_size * out_features,\n                    device=weight.device)\n                mask.bernoulli_(p)\n                mask = mask.repeat_interleave(block_size, -1).reshape(\n                    [-1, in_features])\n\n            else:\n                # gather weight and sizes\n                weight = mod.weight\n                in_channels = mod.in_channels\n                out_channels = mod.out_channels\n\n                # split weight matrix into blocks and randomly drop selected blocks\n                if mod.kernel_size == (1, 1):\n                    mask = paddle.zeros(\n                        int(in_channels // block_size * out_channels),\n                        device=weight.device, )\n                    mask.bernoulli_(p)\n                    mask = mask.repeat_interleave(block_size, -1).reshape(\n                        [-1, in_channels])\n                else:\n                    mask = paddle.zeros(\n                        weight.size(0), weight.size(1), device=weight.device)\n\n                    mask.bernoulli_(p)\n                    mask = (\n                        mask.unsqueeze(2).unsqueeze(3)\n                        .repeat(1, 1, mod.kernel_size[0], mod.kernel_size[1]))\n\n            # scale weights and apply mask\n            mask = mask.to(paddle.bool)\n            s = 1 / (1 - p)\n            mod.weight.data = s * weight.masked_fill(mask, 0)\n\n    module.register_forward_pre_hook(_forward_pre_hook)\n    return module\n\n\nclass MultiheadAttention(nn.Layer):\n    \"\"\"Multi-headed attention.\n\n    See \"Attention Is All You Need\" for more details.\n    \"\"\"\n\n    def __init__(\n            self,\n            embed_dim,\n            num_heads,\n            kdim=None,\n            vdim=None,\n            dropout=0.0,\n            bias=True,\n            add_bias_kv=False,\n            add_zero_attn=False,\n            self_attention=False,\n            encoder_decoder_attention=False,\n            q_noise=0.0,\n            qn_block_size=8,\n            has_relative_attention_bias=True,\n            num_buckets=32,\n            max_distance=128,\n            gru_rel_pos=True,\n            rescale_init=False, ):\n        super().__init__()\n        self.embed_dim = embed_dim\n        self.kdim = kdim if kdim is not None else embed_dim\n        self.vdim = vdim if vdim is not None else embed_dim\n        self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim\n\n        self.num_heads = num_heads\n        self.dropout_module = nn.Dropout(dropout)\n\n        self.has_relative_attention_bias = has_relative_attention_bias\n        self.num_buckets = num_buckets\n        self.max_distance = max_distance\n        if self.has_relative_attention_bias:\n            self.relative_attention_bias = nn.Embedding(num_buckets, num_heads)\n\n        self.head_dim = embed_dim // num_heads\n        self.q_head_dim = self.head_dim\n        self.k_head_dim = self.head_dim\n        assert (self.head_dim * num_heads == self.embed_dim\n                ), \"embed_dim must be divisible by num_heads\"\n        self.scaling = self.head_dim**-0.5\n\n        self.self_attention = self_attention\n        self.encoder_decoder_attention = encoder_decoder_attention\n\n        assert not self.self_attention or self.qkv_same_dim, (\n            \"Self-attention requires query, key and \"\n            \"value to be of the same size\")\n\n        k_bias = True\n        if rescale_init:\n            k_bias = False\n\n        k_embed_dim = embed_dim\n        q_embed_dim = embed_dim\n\n        self.k_proj = quant_noise(\n            nn.Linear(self.kdim, k_embed_dim, bias_attr=k_bias), q_noise,\n            qn_block_size)\n        self.v_proj = quant_noise(\n            nn.Linear(self.vdim, embed_dim, bias_attr=bias), q_noise,\n            qn_block_size)\n        self.q_proj = quant_noise(\n            nn.Linear(embed_dim, q_embed_dim, bias_attr=bias), q_noise,\n            qn_block_size)\n\n        self.out_proj = quant_noise(\n            nn.Linear(embed_dim, embed_dim, bias_attr=bias), q_noise,\n            qn_block_size)\n\n        if add_bias_kv:\n            self.bias_k = self.create_parameter(\n                shape=[1, 1, embed_dim], dtype=\"float32\")\n            self.bias_v = self.create_parameter(\n                shape=[1, 1, embed_dim], dtype=\"float32\")\n\n        else:\n            self.bias_k = self.bias_v = None\n\n        self.add_zero_attn = add_zero_attn\n\n        self.gru_rel_pos = gru_rel_pos\n        if self.gru_rel_pos:\n            self.grep_linear = nn.Linear(self.q_head_dim, 8)\n            self.grep_a = self.create_parameter(\n                shape=[1, num_heads, 1, 1], dtype=\"float32\")\n\n        self.reset_parameters()\n\n    def reset_parameters(self):\n        pass\n\n    def _relative_positions_bucket(self, relative_positions,\n                                   bidirectional=True):\n        num_buckets = self.num_buckets\n        max_distance = self.max_distance\n        relative_buckets = 0\n\n        if bidirectional:\n            num_buckets = num_buckets // 2\n            relative_buckets += (\n                relative_positions > 0).astype(\"int64\") * num_buckets\n            relative_positions = paddle.abs(relative_positions)\n        else:\n            relative_positions = -paddle.minimum(\n                relative_positions, paddle.zeros_like(relative_positions))\n\n        max_exact = num_buckets // 2\n        is_small = relative_positions < max_exact\n\n        relative_postion_if_large = max_exact + (\n            paddle.log(relative_positions.astype(\"float32\") /\n                       max_exact) / math.log(max_distance / max_exact) *\n            (num_buckets - max_exact)).astype(\"int64\")\n        relative_postion_if_large = paddle.minimum(\n            relative_postion_if_large,\n            paddle.full_like(relative_postion_if_large, num_buckets - 1))\n\n        relative_buckets += paddle.where(is_small, relative_positions,\n                                         relative_postion_if_large)\n        return relative_buckets\n\n    def compute_bias(self, query_length, key_length):\n        context_position = paddle.arange(query_length, dtype=\"int64\")[:, None]\n        memory_position = paddle.arange(key_length, dtype=\"int64\")[None, :]\n        relative_position = memory_position - context_position\n        relative_position_bucket = self._relative_positions_bucket(\n            relative_position, bidirectional=True)\n        # relative_position_bucket = relative_position_bucket.to(self.relative_attention_bias.weight.device)\n        values = self.relative_attention_bias(relative_position_bucket)\n        values = values.transpose([2, 0, 1])\n        return values\n\n    def forward(self,\n                query,\n                key: Optional[Tensor],\n                value: Optional[Tensor],\n                key_padding_mask: Optional[Tensor]=None,\n                incremental_state: Optional[Dict[str, Dict[str, Optional[\n                    Tensor]]]]=None,\n                need_weights: bool=True,\n                static_kv: bool=False,\n                attn_mask: Optional[Tensor]=None,\n                before_softmax: bool=False,\n                need_head_weights: bool=False,\n                position_bias: Optional[Tensor]=None\n                ) -> Tuple[Tensor, Optional[Tensor], Optional[Tensor]]:\n        \"\"\"Input shape: Time x Batch x Channel\n\n        Args:\n            key_padding_mask (ByteTensor, optional): mask to exclude\n                keys that are pads, of shape `(batch, src_len)`, where\n                padding elements are indicated by 1s.\n            need_weights (bool, optional): return the attention weights,\n                averaged over heads (default: False).\n            attn_mask (ByteTensor, optional): typically used to\n                implement causal attention, where the mask prevents the\n                attention from looking forward in time (default: None).\n            before_softmax (bool, optional): return the raw attention\n                weights and values before the attention softmax.\n            need_head_weights (bool, optional): return the attention\n                weights for each head. Implies *need_weights*. Default:\n                return the average attention weights over all heads.\n        \"\"\"\n        if need_head_weights:\n            need_weights = True\n\n        tgt_len, bsz, embed_dim = query.shape\n        src_len = tgt_len\n        assert embed_dim == self.embed_dim\n        assert list(query.shape) == [tgt_len, bsz, embed_dim]\n        if key is not None:\n            src_len, key_bsz, _ = key.shape\n\n        if self.has_relative_attention_bias and position_bias is None:\n            position_bias = self.compute_bias(tgt_len, src_len)\n            position_bias_ = position_bias.unsqueeze(0)\n            position_bias = paddle.concat(\n                [position_bias_ for _ in range(bsz)], axis=0)\n            position_bias = position_bias.reshape(\n                [bsz * self.num_heads, tgt_len, src_len])\n        if (incremental_state is None and not static_kv and\n                self.q_head_dim == self.head_dim):\n            assert key is not None and value is not None\n            assert attn_mask is None\n\n            attn_mask_rel_pos = None\n            if position_bias is not None:\n                attn_mask_rel_pos = position_bias\n                if self.gru_rel_pos:\n                    query_layer = query.transpose([1, 0, 2])\n                    new_x_shape = query_layer.shape[:-1] + [self.num_heads, -1]\n                    query_layer = query_layer.reshape(new_x_shape)\n                    query_layer = query_layer.transpose([0, 2, 1, 3])\n                    _B, _H, _L, __ = query_layer.shape\n\n                    gate_a, gate_b = paddle.nn.functional.sigmoid(\n                        self.grep_linear(query_layer).reshape(\n                            [_B, _H, _L, 2, 4]).sum(-1, keepdim=False)).chunk(\n                                2, axis=-1)\n\n                    gate_a_1 = gate_a * (gate_b * self.grep_a - 1.0) + 2.0\n                    attn_mask_rel_pos = gate_a_1.reshape(\n                        [bsz * self.num_heads, -1, 1]) * position_bias\n\n                attn_mask_rel_pos = attn_mask_rel_pos.reshape(\n                    (-1, tgt_len, tgt_len))\n            k_proj_bias = self.k_proj.bias\n            if k_proj_bias is None:\n                k_proj_bias = paddle.zeros_like(self.q_proj.bias)\n\n            x, attn = multi_head_attention_forward_paddle(\n                query,\n                key,\n                value,\n                self.embed_dim,\n                self.num_heads,\n                paddle.empty([0]),\n                paddle.concat(\n                    (self.q_proj.bias, self.k_proj.bias, self.v_proj.bias),\n                    axis=0),\n                self.bias_k,\n                self.bias_v,\n                self.add_zero_attn,\n                self.dropout_module.p,\n                self.out_proj.weight,\n                self.out_proj.bias,\n                self.training,\n                key_padding_mask,\n                need_weights,\n                attn_mask_rel_pos,\n                use_separate_proj_weight=True,\n                q_proj_weight=self.q_proj.weight,\n                k_proj_weight=self.k_proj.weight,\n                v_proj_weight=self.v_proj.weight, )\n\n            return x, attn, position_bias\n\n        if incremental_state is not None:\n            saved_state = self._get_input_buffer(incremental_state)\n            if saved_state is not None and \"prev_key\" in saved_state:\n                # previous time steps are cached - no need to recompute\n                # key and value if they are static\n                if static_kv:\n                    assert self.encoder_decoder_attention and not self.self_attention\n                    key = value = None\n        else:\n            saved_state = None\n\n        if self.self_attention:\n            q = self.q_proj(query)\n            k = self.k_proj(query)\n            v = self.v_proj(query)\n        elif self.encoder_decoder_attention:\n            # encoder-decoder attention\n            q = self.q_proj(query)\n            if key is None:\n                assert value is None\n                k = v = None\n            else:\n                k = self.k_proj(key)\n                v = self.v_proj(key)\n\n        else:\n            assert key is not None and value is not None\n            q = self.q_proj(query)\n            k = self.k_proj(key)\n            v = self.v_proj(value)\n        q *= self.scaling\n\n        if self.bias_k is not None:\n            assert self.bias_v is not None\n            k = paddle.concat([k, self.bias_k.repeat(1, bsz, 1)], axis=0)\n            v = paddle.concat([v, self.bias_v.repeat(1, bsz, 1)], axis=0)\n            if attn_mask is not None:\n                attn_mask = paddle.concat(\n                    [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)],\n                    axis=1)\n\n            if key_padding_mask is not None:\n                key_padding_mask = paddle.concat(\n                    [\n                        key_padding_mask,\n                        key_padding_mask.new_zeros(key_padding_mask.size(0), 1),\n                    ],\n                    axis=1, )\n\n        q = (q.contiguous()\n             .reshape([tgt_len, bsz * self.num_heads, self.q_head_dim])\n             .transpose([1, 0, 2]))\n        if k is not None:\n            k = (k.contiguous()\n                 .reshape([-1, bsz * self.num_heads, self.k_head_dim])\n                 .transpose([1, 0, 2]))\n        if v is not None:\n            v = (v.contiguous()\n                 .reshape([-1, bsz * self.num_heads, self.head_dim])\n                 .transpose([1, 0, 2]))\n\n        if saved_state is not None:\n            # saved states are stored with shape (bsz, num_heads, seq_len, head_dim)\n            if \"prev_key\" in saved_state:\n                _prev_key = saved_state[\"prev_key\"]\n                assert _prev_key is not None\n                prev_key = _prev_key.reshape(\n                    [bsz * self.num_heads, -1, self.head_dim])\n                if static_kv:\n                    k = prev_key\n                else:\n                    assert k is not None\n                    k = paddle.concat([prev_key, k], axis=1)\n                src_len = k.size(1)\n            if \"prev_value\" in saved_state:\n                _prev_value = saved_state[\"prev_value\"]\n                assert _prev_value is not None\n                prev_value = _prev_value.reshape(\n                    [bsz * self.num_heads, -1, self.head_dim])\n                if static_kv:\n                    v = prev_value\n                else:\n                    assert v is not None\n                    v = paddle.concat([prev_value, v], axis=1)\n            prev_key_padding_mask: Optional[Tensor] = None\n            if \"prev_key_padding_mask\" in saved_state:\n                prev_key_padding_mask = saved_state[\"prev_key_padding_mask\"]\n            assert k is not None and v is not None\n            key_padding_mask = MultiheadAttention._append_prev_key_padding_mask(\n                key_padding_mask=key_padding_mask,\n                prev_key_padding_mask=prev_key_padding_mask,\n                batch_size=bsz,\n                src_len=k.size(1),\n                static_kv=static_kv, )\n\n            saved_state[\"prev_key\"] = k.reshape(\n                [bsz, self.num_heads, -1, self.head_dim])\n            saved_state[\"prev_value\"] = v.reshape(\n                [bsz, self.num_heads, -1, self.head_dim])\n            saved_state[\"prev_key_padding_mask\"] = key_padding_mask\n            # In this branch incremental_state is never None\n            assert incremental_state is not None\n            incremental_state = self._set_input_buffer(incremental_state,\n                                                       saved_state)\n        assert k is not None\n        assert k.size(1) == src_len\n\n        # This is part of a workaround to get around fork/join parallelism\n        # not supporting Optional types.\n        if key_padding_mask is not None and key_padding_mask.dim() == 0:\n            key_padding_mask = None\n\n        if key_padding_mask is not None:\n            assert key_padding_mask.size(0) == bsz\n            assert key_padding_mask.size(1) == src_len\n\n        if self.add_zero_attn:\n            assert v is not None\n            src_len += 1\n            k = paddle.concat(\n                [k, k.new_zeros((k.size(0), 1) + k.shape[2:])], axis=1)\n            v = paddle.concat(\n                [v, v.new_zeros((v.size(0), 1) + v.shape[2:])], axis=1)\n            if attn_mask is not None:\n                attn_mask = paddle.concat(\n                    [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)],\n                    axis=1)\n\n            if key_padding_mask is not None:\n                key_padding_mask = paddle.concat(\n                    [\n                        key_padding_mask,\n                        paddle.zeros(key_padding_mask.size(0),\n                                     1).type_as(key_padding_mask),\n                    ],\n                    axis=1, )\n\n        attn_weights = paddle.matmul(q, k.transpose([0, 2, 1]))\n\n        attn_weights = self.apply_sparse_mask(attn_weights, tgt_len, src_len,\n                                              bsz)\n\n        assert list(\n            attn_weights.shape) == [bsz * self.num_heads, tgt_len, src_len]\n\n        if attn_mask is not None:\n            attn_mask = attn_mask.unsqueeze(0)\n            attn_weights += attn_mask\n\n        if key_padding_mask is not None:\n            # don't attend to padding symbols\n            attn_weights = attn_weights.reshape(\n                [bsz, self.num_heads, tgt_len, src_len])\n            attn_weights = attn_weights.masked_fill(\n                key_padding_mask.unsqueeze(1).unsqueeze(2).to(paddle.bool),\n                float(\"-inf\"), )\n            attn_weights = attn_weights.reshape(\n                [bsz * self.num_heads, tgt_len, src_len])\n\n        if before_softmax:\n            return attn_weights, v, position_bias\n\n        if position_bias is not None:\n            if self.gru_rel_pos == 1:\n                query_layer = q.reshape(\n                    [bsz, self.num_heads, tgt_len, self.q_head_dim])\n                _B, _H, _L, __ = query_layer.shape\n                gate_a, gate_b = paddle.sigmoid(\n                    self.grep_linear(query_layer).reshape([_B, _H, _L, 2, 4])\n                    .sum(-1, keepdim=False)).chunk(\n                        2, axis=-1)\n\n                gate_a_1 = gate_a * (gate_b * self.grep_a - 1.0) + 2.0\n                position_bias = gate_a_1.reshape(\n                    [bsz * self.num_heads, -1, 1]) * position_bias\n\n            position_bias = position_bias.reshape(attn_weights.shape)\n\n            attn_weights = attn_weights + position_bias\n\n        attn_weights_float = F.softmax(attn_weights, dim=-1)\n        attn_weights = attn_weights_float.type_as(attn_weights)\n        attn_probs = self.dropout_module(attn_weights)\n\n        assert v is not None\n        attn = paddle.bmm(attn_probs, v)\n        assert list(\n            attn.shape) == [bsz * self.num_heads, tgt_len, self.head_dim]\n        attn = attn.transpose([1, 0, 2]).reshape([tgt_len, bsz, embed_dim])\n        attn = self.out_proj(attn)\n        attn_weights: Optional[Tensor] = None\n        if need_weights:\n            attn_weights = attn_weights_float.reshape(\n                [bsz, self.num_heads, tgt_len, src_len]).transpose([1, 0, 2, 3])\n            if not need_head_weights:\n                # average attention weights over heads\n                attn_weights = attn_weights.mean(dim=0)\n\n        return attn, attn_weights, position_bias\n\n    @staticmethod\n    def _append_prev_key_padding_mask(\n            key_padding_mask: Optional[Tensor],\n            prev_key_padding_mask: Optional[Tensor],\n            batch_size: int,\n            src_len: int,\n            static_kv: bool, ) -> Optional[Tensor]:\n        # saved key padding masks have shape (bsz, seq_len)\n        if prev_key_padding_mask is not None and static_kv:\n            new_key_padding_mask = prev_key_padding_mask\n        elif prev_key_padding_mask is not None and key_padding_mask is not None:\n            new_key_padding_mask = paddle.concat(\n                [prev_key_padding_mask.float(), key_padding_mask.float()],\n                axis=1)\n        # During incremental decoding, as the padding token enters and\n        # leaves the frame, there will be a time when prev or current\n        # is None\n        elif prev_key_padding_mask is not None:\n            if src_len > prev_key_padding_mask.size(1):\n                filler = paddle.zeros(\n                    (batch_size, src_len - prev_key_padding_mask.size(1)),\n                    device=prev_key_padding_mask.device, )\n                new_key_padding_mask = paddle.concat(\n                    [prev_key_padding_mask.float(), filler.float()], axis=1)\n\n            else:\n                new_key_padding_mask = prev_key_padding_mask.float()\n        elif key_padding_mask is not None:\n            if src_len > key_padding_mask.size(1):\n                filler = paddle.zeros(\n                    (batch_size, src_len - key_padding_mask.size(1)),\n                    device=key_padding_mask.device, )\n                new_key_padding_mask = paddle.concat(\n                    [filler.float(), key_padding_mask.float()], axis=1)\n\n            else:\n                new_key_padding_mask = key_padding_mask.float()\n        else:\n            new_key_padding_mask = prev_key_padding_mask\n        return new_key_padding_mask\n\n    def _get_input_buffer(\n            self,\n            incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]]\n    ) -> Dict[str, Optional[Tensor]]:\n        result = self.get_incremental_state(incremental_state, \"attn_state\")\n        if result is not None:\n            return result\n        else:\n            empty_result: Dict[str, Optional[Tensor]] = {}\n            return empty_result\n\n    def _set_input_buffer(\n            self,\n            incremental_state: Dict[str, Dict[str, Optional[Tensor]]],\n            buffer: Dict[str, Optional[Tensor]], ):\n        return self.set_incremental_state(incremental_state, \"attn_state\",\n                                          buffer)\n\n    def apply_sparse_mask(self,\n                          attn_weights,\n                          tgt_len: int,\n                          src_len: int,\n                          bsz: int):\n        return attn_weights\n"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/wavlm_asr.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import defaultdict\nfrom typing import Dict\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom .wavlm_paddle import WavLM\nfrom .wavlm_paddle import WavLMConfig\nfrom paddlespeech.s2t.models.wav2vec2.modules.VanillaNN import VanillaNN\nfrom paddlespeech.s2t.models.wav2vec2.processing.speech_augmentation import SpecAugment\nfrom paddlespeech.s2t.modules.ctc import CTCDecoderBase as CTC\nfrom paddlespeech.s2t.modules.initializer import DefaultInitializerContext\nfrom paddlespeech.s2t.utils.ctc_utils import remove_duplicates_and_blank\nfrom paddlespeech.s2t.utils.utility import log_add\n\n\nclass WavLMASR(nn.Layer):\n    def __init__(self, config: dict):\n        super().__init__()\n        init_type = config.get(\"init_type\", None)\n        with DefaultInitializerContext(init_type):\n            self.config = config\n            wavlm_config = WavLMConfig(config)\n            wavlm = WavLM(wavlm_config)\n\n            self.normalize_wav = config.normalize_wav\n            self.output_norm = config.output_norm\n            if hasattr(config, 'spec_augment'):\n                self.spec_augment = SpecAugment(**config.spec_augment)\n\n            if config.freeze_wavlm:\n                wavlm.eval()\n                for parm in wavlm.parameters():\n                    parm.trainable = False\n            self.wavlm = wavlm\n            self.enc = VanillaNN(**config.enc)\n            self.ctc = CTC(**config.ctc,\n                           odim=config.output_dim,\n                           batch_average=False,\n                           reduction='mean')\n\n    def forward(self, wav, wavs_lens_rate, target, target_lens):\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n\n        # Extract wav2vec output\n        out = self.wavlm(wav)\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n\n        if self.training and hasattr(self.config, 'spec_augment'):\n            feats = self.spec_augment(out)\n        else:\n            feats = out\n\n        x = self.enc(feats)\n        # x = feats\n\n        x_lens = (wavs_lens_rate * x.shape[1]).round().astype(paddle.int64)\n        target_lens = target_lens.astype(paddle.int64)\n        # target = target.astype(paddle.int32)\n        ctc_loss = self.ctc(x, x_lens, target, target_lens)\n\n        return ctc_loss\n\n    @paddle.no_grad()\n    def decode(self,\n               feats: paddle.Tensor,\n               text_feature: Dict[str, int],\n               decoding_method: str,\n               beam_size: int,\n               tokenizer: str=None,\n               sb_pipeline=False):\n        batch_size = feats.shape[0]\n\n        if decoding_method == 'ctc_prefix_beam_search' and batch_size > 1:\n            print(\n                f\"decoding mode {decoding_method} must be running with batch_size == 1\"\n            )\n            print(f\"current batch_size is {batch_size}\")\n\n        if decoding_method == 'ctc_greedy_search':\n            if tokenizer is None and sb_pipeline is False:\n                hyps = self.ctc_greedy_search(feats)\n                res = [text_feature.defeaturize(hyp) for hyp in hyps]\n                res_tokenids = [hyp for hyp in hyps]\n            else:\n                if sb_pipeline is True:\n                    hyps = self.ctc_greedy_search(feats.unsqueeze(-1))\n                else:\n                    hyps = self.ctc_greedy_search(feats)\n                res = []\n                res_tokenids = []\n                for sequence in hyps:\n                    # Decode token terms to words \n                    predicted_tokens = text_feature.convert_ids_to_tokens(\n                        sequence)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n\n        # ctc_prefix_beam_search and attention_rescoring only return one\n        # result in List[int], change it to List[List[int]] for compatible\n        # with other batch decoding mode\n        elif decoding_method == 'ctc_prefix_beam_search':\n            assert feats.shape[0] == 1\n            if tokenizer is None and sb_pipeline is False:\n                hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = [text_feature.defeaturize(hyp)]\n                res_tokenids = [hyp]\n            else:\n                if sb_pipeline is True:\n                    hyp = self.ctc_prefix_beam_search(\n                        feats.unsqueeze(-1), beam_size)\n                else:\n                    hyp = self.ctc_prefix_beam_search(feats, beam_size)\n                res = []\n                res_tokenids = []\n                predicted_tokens = text_feature.convert_ids_to_tokens(hyp)\n                tmp_res = []\n                tmp_res_tokenids = []\n                for c in predicted_tokens:\n                    if c == \"[CLS]\":\n                        continue\n                    elif c == \"[SEP]\" or c == \"[PAD]\":\n                        break\n                    else:\n                        tmp_res.append(c)\n                        tmp_res_tokenids.append(text_feature.vocab[c])\n                res.append(''.join(tmp_res))\n                res_tokenids.append(tmp_res_tokenids)\n        else:\n            raise ValueError(\n                f\"WavLM not support decoding method: {decoding_method}\")\n\n        return res, res_tokenids\n\n    @classmethod\n    def from_config(cls, config):\n        model = cls(config)\n        return model\n\n    def ctc_greedy_search(self, wav) -> List[List[int]]:\n        \"\"\" Apply CTC greedy search\n        Args:\n            speech (paddle.Tensor): (batch, max_len)\n            speech_length (paddle.Tensor): (batch, )\n        Returns:\n            List[List[int]]: best path result\n        \"\"\"\n        batch_size = wav.shape[0]\n        wav = wav[:, :, 0]\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wavlm output\n        out = self.wavlm(wav)\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n        x = self.enc(feats)\n        x_lens = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (B, maxlen, vocab_size)\n        topk_prob, topk_index = ctc_probs.topk(1, axis=2)  # (B, maxlen, 1)\n        topk_index = topk_index.reshape([batch_size, x_lens])  # (B, maxlen)\n\n        hyps = [hyp.tolist() for hyp in topk_index]\n        hyps = [remove_duplicates_and_blank(hyp) for hyp in hyps]\n        return hyps\n\n    def _ctc_prefix_beam_search(\n            self,\n            wav,\n            beam_size,\n            blank_id: int=0, ) -> Tuple[List[Tuple[int, float]], paddle.Tensor]:\n        \"\"\" CTC prefix beam search inner implementation\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[Tuple[int, float]]: nbest results, (N,1), (text, likelihood)\n            paddle.Tensor: encoder output, (1, max_len, encoder_dim),\n                it will be used for rescoring in attention rescoring mode\n        \"\"\"\n        wav = wav[:, :, 0]\n\n        if self.normalize_wav:\n            wav = F.layer_norm(wav, wav.shape[1:])\n        # Extract wavlm output\n        out = self.wavlm(wav)\n        # We normalize the output if required\n        if self.output_norm:\n            out = F.layer_norm(out, out.shape[1:])\n        feats = out\n\n        x = self.enc(feats)\n        maxlen = x.shape[1]\n        ctc_probs = self.ctc.log_softmax(x)  # (1, maxlen, vocab_size)\n        ctc_probs = ctc_probs.squeeze(0)\n\n        # cur_hyps: (prefix, (blank_ending_score, none_blank_ending_score))\n        # blank_ending_score and  none_blank_ending_score in ln domain\n        cur_hyps = [(tuple(), (0.0, -float('inf')))]\n        # 2. CTC beam search step by step\n        for t in range(0, maxlen):\n            logp = ctc_probs[t]  # (vocab_size,)\n            # key: prefix, value (pb, pnb), default value(-inf, -inf)\n            next_hyps = defaultdict(lambda: (-float('inf'), -float('inf')))\n            # 2.1 First beam prune: select topk best\n            top_k_logp, top_k_index = logp.topk(beam_size)  # (beam_size,)\n            for s in top_k_index:\n                s = s.item()\n                ps = logp[s].item()\n                for prefix, (pb, pnb) in cur_hyps:\n                    last = prefix[-1] if len(prefix) > 0 else None\n                    if s == blank_id:  # blank\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pb = log_add([n_pb, pb + ps, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                    elif s == last:\n                        #  Update *ss -> *s;\n                        n_pb, n_pnb = next_hyps[prefix]\n                        n_pnb = log_add([n_pnb, pnb + ps])\n                        next_hyps[prefix] = (n_pb, n_pnb)\n                        # Update *s-s -> *ss, - is for blank\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n                    else:\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb = next_hyps[n_prefix]\n                        n_pnb = log_add([n_pnb, pb + ps, pnb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb)\n\n            # 2.2 Second beam prune\n            next_hyps = sorted(\n                next_hyps.items(),\n                key=lambda x: log_add(list(x[1])),\n                reverse=True)\n            cur_hyps = next_hyps[:beam_size]\n\n        hyps = [(y[0], log_add([y[1][0], y[1][1]])) for y in cur_hyps]\n        return hyps\n\n    def ctc_prefix_beam_search(self, wav, beam_size) -> List[int]:\n        \"\"\" Apply CTC prefix beam search\n        Args:\n            speech (paddle.Tensor): (batch, max_len, feat_dim)\n            speech_length (paddle.Tensor): (batch, )\n            beam_size (int): beam size for beam search\n            decoding_chunk_size (int): decoding chunk for dynamic chunk\n                trained model.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n                0: used for training, it's prohibited here\n            simulate_streaming (bool): whether do encoder forward in a\n                streaming fashion\n        Returns:\n            List[int]: CTC prefix beam search nbest results\n        \"\"\"\n        hyps = self._ctc_prefix_beam_search(wav, beam_size)\n        return hyps[0][0]\n\n\nclass WavLMBase(nn.Layer):\n    \"\"\"WavLM model\"\"\"\n\n    def __init__(self, config: dict):\n        super().__init__()\n        wavlm_config = WavLMConfig(config)\n        wavlm = WavLM(wavlm_config)\n        self.wavlm = wavlm\n\n    @classmethod\n    def from_config(cls, configs: dict):\n        \"\"\"init model.\n        Args:\n            configs (dict): config dict.\n        Raises:\n            ValueError: raise when using not support encoder type.\n        Returns:\n            nn.Layer: WavLMBase\n        \"\"\"\n        model = cls(configs)\n        return model\n\n    def forward(self, wav):\n        out = self.wavlm(wav)\n        return out\n"
  },
  {
    "path": "paddlespeech/s2t/models/wavlm/wavlm_paddle.py",
    "content": "# --------------------------------------------------------\n# WavLM: Large-Scale Self-Supervised  Pre-training  for Full Stack Speech Processing (https://arxiv.org/abs/2110.13900.pdf)\n# Github source: https://github.com/microsoft/unilm/tree/master/wavlm\n# Copyright (c) 2021 Microsoft\n# Licensed under The MIT License [see LICENSE for details]\n# Based on fairseq code bases\n# https://github.com/pytorch/fairseq\n# --------------------------------------------------------\nimport logging\nimport math\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\nfrom paddle import Tensor\nfrom paddle.nn import LayerNorm\n\nfrom .modules.modules import get_activation_fn\nfrom .modules.modules import GLU_Linear\nfrom .modules.modules import MultiheadAttention\nfrom .modules.modules import SamePad\nfrom .modules.modules import TransposeLast\n\nlogger = logging.getLogger(__name__)\n\n\ndef compute_mask_indices(\n        shape: Tuple[int, int],\n        padding_mask: Optional[Tensor],\n        mask_prob: float,\n        mask_length: int,\n        mask_type: str=\"static\",\n        mask_other: float=0.0,\n        min_masks: int=0,\n        no_overlap: bool=False,\n        min_space: int=0, ) -> np.ndarray:\n    \"\"\"\n    Computes random mask spans for a given shape\n\n    Args:\n        shape: the the shape for which to compute masks.\n            should be of size 2 where first element is batch size and 2nd is timesteps\n        padding_mask: optional padding mask of the same size as shape, which will prevent masking padded elements\n        mask_prob: probability for each token to be chosen as start of the span to be masked. this will be multiplied by\n            number of timesteps divided by length of mask span to mask approximately this percentage of all elements.\n            however due to overlaps, the actual number will be smaller (unless no_overlap is True)\n        mask_type: how to compute mask lengths\n            static = fixed size\n            uniform = sample from uniform distribution [mask_other, mask_length*2]\n            normal = sample from normal distribution with mean mask_length and stdev mask_other. mask is min 1 element\n            poisson = sample from possion distribution with lambda = mask length\n        min_masks: minimum number of masked spans\n        no_overlap: if false, will switch to an alternative recursive algorithm that prevents spans from overlapping\n        min_space: only used if no_overlap is True, this is how many elements to keep unmasked between spans\n    \"\"\"\n\n    bsz, all_sz = shape\n    mask = np.full((bsz, all_sz), False)\n\n    all_num_mask = int(\n        # add a random number for probabilistic rounding\n        mask_prob * all_sz / float(mask_length) + np.random.rand())\n\n    all_num_mask = max(min_masks, all_num_mask)\n\n    mask_idcs = []\n    for i in range(bsz):\n        if padding_mask is not None:\n            sz = all_sz - padding_mask[i].long().sum().item()\n            num_mask = int(\n                # add a random number for probabilistic rounding\n                mask_prob * sz / float(mask_length) + np.random.rand())\n            num_mask = max(min_masks, num_mask)\n        else:\n            sz = all_sz\n            num_mask = all_num_mask\n\n        if mask_type == \"static\":\n            lengths = np.full(num_mask, mask_length)\n        elif mask_type == \"uniform\":\n            lengths = np.random.randint(\n                mask_other, mask_length * 2 + 1, size=num_mask)\n        elif mask_type == \"normal\":\n            lengths = np.random.normal(mask_length, mask_other, size=num_mask)\n            lengths = [max(1, int(round(x))) for x in lengths]\n        elif mask_type == \"poisson\":\n            lengths = np.random.poisson(mask_length, size=num_mask)\n            lengths = [int(round(x)) for x in lengths]\n        else:\n            raise Exception(\"unknown mask selection \" + mask_type)\n\n        if sum(lengths) == 0:\n            lengths[0] = min(mask_length, sz - 1)\n\n        if no_overlap:\n            mask_idc = []\n\n            def arrange(s, e, length, keep_length):\n                span_start = np.random.randint(s, e - length)\n                mask_idc.extend(span_start + i for i in range(length))\n\n                new_parts = []\n                if span_start - s - min_space >= keep_length:\n                    new_parts.append((s, span_start - min_space + 1))\n                if e - span_start - keep_length - min_space > keep_length:\n                    new_parts.append((span_start + length + min_space, e))\n                return new_parts\n\n            parts = [(0, sz)]\n            min_length = min(lengths)\n            for length in sorted(lengths, reverse=True):\n                lens = np.fromiter(\n                    (e - s if e - s >= length + min_space else 0\n                     for s, e in parts),\n                    np.int_, )\n                l_sum = np.sum(lens)\n                if l_sum == 0:\n                    break\n                probs = lens / np.sum(lens)\n                c = np.random.choice(len(parts), p=probs)\n                s, e = parts.pop(c)\n                parts.extend(arrange(s, e, length, min_length))\n            mask_idc = np.asarray(mask_idc)\n        else:\n            min_len = min(lengths)\n            if sz - min_len <= num_mask:\n                min_len = sz - num_mask - 1\n\n            mask_idc = np.random.choice(sz - min_len, num_mask, replace=False)\n\n            mask_idc = np.asarray([\n                mask_idc[j] + offset\n                for j in range(len(mask_idc)) for offset in range(lengths[j])\n            ])\n\n        mask_idcs.append(np.unique(mask_idc[mask_idc < sz]))\n\n    min_len = min([len(m) for m in mask_idcs])\n    for i, mask_idc in enumerate(mask_idcs):\n        if len(mask_idc) > min_len:\n            mask_idc = np.random.choice(mask_idc, min_len, replace=False)\n        mask[i, mask_idc] = True\n\n    return mask\n\n\nclass WavLMConfig:\n    def __init__(self, cfg=None):\n        self.extractor_mode: str = \"default\"  # mode for feature extractor. default has a single group norm with d groups in the first conv block, whereas layer_norm has layer norms in every block (meant to use with normalize=True)\n        self.encoder_layers: int = 12  # num encoder layers in the transformer\n\n        self.encoder_embed_dim: int = 768  # encoder embedding dimension\n        self.encoder_ffn_embed_dim: int = 3072  # encoder embedding dimension for FFN\n        self.encoder_attention_heads: int = 12  # num encoder attention heads\n        self.activation_fn: str = \"gelu\"  # activation function to use\n\n        self.layer_norm_first: bool = False  # apply layernorm first in the transformer\n        self.conv_feature_layers: str = \"[(512,10,5)] + [(512,3,2)] * 4 + [(512,2,2)] * 2\"  # string describing convolutional feature extraction layers in form of a python list that contains [(dim, kernel_size, stride), ...]\n        self.conv_bias: bool = False  # include bias in conv encoder\n        self.feature_grad_mult: float = 1.0  # multiply feature extractor var grads by this\n\n        self.normalize: bool = False  # normalize input to have 0 mean and unit variance during training\n\n        # dropouts\n        self.dropout: float = 0.1  # dropout probability for the transformer\n        self.attention_dropout: float = 0.1  # dropout probability for attention weights\n        self.activation_dropout: float = 0.0  # dropout probability after activation in FFN\n        self.encoder_layerdrop: float = 0.0  # probability of dropping a tarnsformer layer\n        self.dropout_input: float = 0.0  # dropout to apply to the input (after feat extr)\n        self.dropout_features: float = 0.0  # dropout to apply to the features (after feat extr)\n\n        # masking\n        self.mask_length: int = 10  # mask length\n        self.mask_prob: float = 0.65  # probability of replacing a token with mask\n        self.mask_selection: str = \"static\"  # how to choose mask length\n        self.mask_other: float = 0  # secondary mask argument (used for more complex distributions), see help in compute_mask_indicesh\n        self.no_mask_overlap: bool = False  # whether to allow masks to overlap\n        self.mask_min_space: int = 1  # min space between spans (if no overlap is enabled)\n\n        # channel masking\n        self.mask_channel_length: int = 10  # length of the mask for features (channels)\n        self.mask_channel_prob: float = 0.0  # probability of replacing a feature with 0\n        self.mask_channel_selection: str = \"static\"  # how to choose mask length for channel masking\n        self.mask_channel_other: float = 0  # secondary mask argument (used for more complex distributions), see help in compute_mask_indices\n        self.no_mask_channel_overlap: bool = False  # whether to allow channel masks to overlap\n        self.mask_channel_min_space: int = 1  # min space between spans (if no overlap is enabled)\n\n        # positional embeddings\n        self.conv_pos: int = 128  # number of filters for convolutional positional embeddings\n        self.conv_pos_groups: int = 16  # number of groups for convolutional positional embedding\n\n        # relative position embedding\n        self.relative_position_embedding: bool = True  # apply relative position embedding\n        self.num_buckets: int = 320  # number of buckets for relative position embedding\n        self.max_distance: int = 1280  # maximum distance for relative position embedding\n        self.gru_rel_pos: bool = True  # apply gated relative position embedding\n\n        if cfg is not None:\n            self.update(cfg)\n\n    def update(self, cfg: dict):\n        self.__dict__.update(cfg)\n\n\nclass WavLM(nn.Layer):\n    def __init__(\n            self,\n            cfg: WavLMConfig, ) -> None:\n        super().__init__()\n        logger.info(f\"WavLM Config: {cfg.__dict__}\")\n\n        self.cfg = cfg\n        feature_enc_layers = eval(cfg.conv_feature_layers)\n        self.embed = feature_enc_layers[-1][0]\n\n        self.feature_extractor = ConvFeatureExtractionModel(\n            conv_layers=feature_enc_layers,\n            dropout=0.0,\n            mode=cfg.extractor_mode,\n            conv_bias=cfg.conv_bias, )\n\n        self.post_extract_proj = (nn.Linear(self.embed, cfg.encoder_embed_dim)\n                                  if self.embed != cfg.encoder_embed_dim else\n                                  None)\n\n        self.mask_prob = cfg.mask_prob\n        self.mask_selection = cfg.mask_selection\n        self.mask_other = cfg.mask_other\n        self.mask_length = cfg.mask_length\n        self.no_mask_overlap = cfg.no_mask_overlap\n        self.mask_min_space = cfg.mask_min_space\n\n        self.mask_channel_prob = cfg.mask_channel_prob\n        self.mask_channel_selection = cfg.mask_channel_selection\n        self.mask_channel_other = cfg.mask_channel_other\n        self.mask_channel_length = cfg.mask_channel_length\n        self.no_mask_channel_overlap = cfg.no_mask_channel_overlap\n        self.mask_channel_min_space = cfg.mask_channel_min_space\n\n        self.dropout_input = nn.Dropout(cfg.dropout_input)\n        self.dropout_features = nn.Dropout(cfg.dropout_features)\n\n        self.feature_grad_mult = cfg.feature_grad_mult\n\n        self.mask_emb = self.create_parameter(\n            shape=[cfg.encoder_embed_dim],\n            default_initializer=nn.initializer.Uniform(), )\n\n        self.encoder = TransformerEncoder(cfg)\n        self.layer_norm = LayerNorm(self.embed)\n\n    def apply_mask(self, x, padding_mask):\n        B, T, C = x.shape\n        if self.mask_prob > 0:\n            mask_indices = compute_mask_indices(\n                (B, T),\n                padding_mask,\n                self.mask_prob,\n                self.mask_length,\n                self.mask_selection,\n                self.mask_other,\n                min_masks=2,\n                no_overlap=self.no_mask_overlap,\n                min_space=self.mask_min_space, )\n            # mask_indices = torch.from_numpy(mask_indices).to(x.device)\n            mask_indices = paddle.to_tensor(mask_indices, dtype='int64')\n            x[mask_indices] = self.mask_emb\n        else:\n            mask_indices = None\n\n        if self.mask_channel_prob > 0:\n            mask_channel_indices = compute_mask_indices(\n                (B, C),\n                None,\n                self.mask_channel_prob,\n                self.mask_channel_length,\n                self.mask_channel_selection,\n                self.mask_channel_other,\n                no_overlap=self.no_mask_channel_overlap,\n                min_space=self.mask_channel_min_space, )\n            mask_channel_indices = (\n                # torch.from_numpy(mask_channel_indices)\n                paddle.to_tensor(mask_channel_indices, dtype='int64')\n                .to(x.device).unsqueeze(1).expand(-1, T, -1))\n            x[mask_channel_indices] = 0\n\n        return x, mask_indices\n\n    def forward_padding_mask(\n            self,\n            features: Tensor,\n            padding_mask: Tensor, ) -> Tensor:\n        extra = padding_mask.size(1) % features.size(1)\n        if extra > 0:\n            padding_mask = padding_mask[:, :-extra]\n        padding_mask = padding_mask.reshape(\n            [padding_mask.size(0), features.size(1), -1])\n        padding_mask = padding_mask.all(-1)\n        return padding_mask\n\n    def extract_features(\n            self,\n            source: Tensor,\n            padding_mask: Optional[Tensor]=None,\n            mask: bool=False,\n            ret_conv: bool=False,\n            output_layer: Optional[int]=None,\n            ret_layer_results: bool=False, ):\n\n        if self.feature_grad_mult > 0:\n            features = self.feature_extractor(source)\n            # if self.feature_grad_mult != 1.0:\n            #     features = GradMultiply.apply(features, self.feature_grad_mult)\n        else:\n            # with torch.no_grad():\n            with paddle.no_grad():\n                features = self.feature_extractor(source)\n\n        features = features.transpose([0, 2, 1])  # [1, 49, 512]\n        features = self.layer_norm(features)\n\n        if padding_mask is not None:\n            padding_mask = self.forward_padding_mask(features, padding_mask)\n\n        if self.post_extract_proj is not None:\n            features = self.post_extract_proj(features)\n        # [1, 49, 768]\n        features = self.dropout_input(features)\n\n        if mask:\n            x, mask_indices = self.apply_mask(features, padding_mask)\n        else:\n            x = features\n\n        # feature: (B, T, D), float\n        # target: (B, T), long\n        # x: (B, T, D), float\n        # padding_mask: (B, T), bool\n        # mask_indices: (B, T), bool\n\n        x, layer_results = self.encoder(\n            x,\n            padding_mask=padding_mask,\n            layer=None if output_layer is None else output_layer - 1)\n        # print(f\"Debugging: x.shape: {x.shape}, x.mean(): {x.mean()}, x.std(): {x.std()}\")\n        res = {\n            \"x\": x,\n            \"padding_mask\": padding_mask,\n            \"features\": features,\n            \"layer_results\": layer_results\n        }\n\n        feature = res[\"features\"] if ret_conv else res[\"x\"]\n        if ret_layer_results:\n            feature = (feature, res[\"layer_results\"])\n        return feature, res[\"padding_mask\"]\n\n    def forward(self, x):\n        return self.extract_features(x)[0]\n\n\nclass ConvFeatureExtractionModel(nn.Layer):\n    def __init__(self,\n                 conv_layers: List[Tuple[int, int, int]],\n                 dropout: float=0.0,\n                 mode: str=\"default\",\n                 conv_bias: bool=False,\n                 conv_type: str=\"default\"):\n        super().__init__()\n\n        assert mode in {\"default\", \"layer_norm\"}\n\n        def block(\n                n_in,\n                n_out,\n                k,\n                stride,\n                is_layer_norm=False,\n                is_group_norm=False,\n                conv_bias=False, ):\n            def make_conv():\n                conv = nn.Conv1D(\n                    n_in,\n                    n_out,\n                    k,\n                    stride=stride,\n                    bias_attr=conv_bias,\n                    weight_attr=nn.initializer.KaimingNormal())\n                # nn.init.kaiming_normal_(conv.weight)\n                return conv\n\n            assert (is_layer_norm and is_group_norm\n                    ) == False, \"layer norm and group norm are exclusive\"\n\n            if is_layer_norm:\n                return nn.Sequential(\n                    make_conv(),\n                    nn.Dropout(p=dropout),\n                    nn.Sequential(\n                        TransposeLast(),\n                        nn.LayerNorm(normalized_shape=dim, epsilon=1e-5),\n                        TransposeLast(), ),\n                    nn.GELU(), )\n            elif is_group_norm:\n                return nn.Sequential(\n                    make_conv(),\n                    nn.Dropout(p=dropout),\n                    nn.GroupNorm(\n                        num_groups=dim, num_channels=dim, epsilon=1e-5),\n                    nn.GELU(), )\n            else:\n                return nn.Sequential(\n                    make_conv(), nn.Dropout(p=dropout), nn.GELU())\n\n        self.conv_type = conv_type\n        if self.conv_type == \"default\":\n            in_d = 1\n            self.conv_layers = nn.LayerList()\n            for i, cl in enumerate(conv_layers):\n                assert len(cl) == 3, \"invalid conv definition: \" + str(cl)\n                (dim, k, stride) = cl\n\n                self.conv_layers.append(\n                    block(\n                        in_d,\n                        dim,\n                        k,\n                        stride,\n                        is_layer_norm=mode == \"layer_norm\",\n                        is_group_norm=mode == \"default\" and i == 0,\n                        conv_bias=conv_bias, ))\n                in_d = dim\n        elif self.conv_type == \"conv2d\":\n            in_d = 1\n            self.conv_layers = nn.LayerList()\n            for i, cl in enumerate(conv_layers):\n                assert len(cl) == 3\n                (dim, k, stride) = cl\n\n                self.conv_layers.append(paddle.nn.Conv2D(in_d, dim, k, stride))\n                self.conv_layers.append(paddle.nn.ReLU())\n                in_d = dim\n        elif self.conv_type == \"custom\":\n            in_d = 1\n            idim = 80\n            self.conv_layers = nn.LayerList()\n            for i, cl in enumerate(conv_layers):\n                assert len(cl) == 3\n                (dim, k, stride) = cl\n                self.conv_layers.append(\n                    paddle.nn.Conv2D(in_d, dim, k, stride, padding=1))\n                self.conv_layers.append(paddle.nn.LayerNorm([dim, idim]))\n                self.conv_layers.append(paddle.nn.ReLU())\n                in_d = dim\n                if (i + 1) % 2 == 0:\n                    self.conv_layers.append(\n                        paddle.nn.MaxPool2D(2, stride=2, ceil_mode=True))\n                    idim = int(math.ceil(idim / 2))\n        else:\n            pass\n\n    def forward(self, x, mask=None):\n\n        # BxT -> BxCxT\n        x = x.unsqueeze(1)\n        if self.conv_type == \"custom\":\n            for conv in self.conv_layers:\n                if isinstance(conv, nn.LayerNorm):\n                    x = x.transpose([0, 2, 1])\n                    x = conv(x).transpose([0, 2, 1])\n                else:\n                    x = conv(x)\n            x = x.transpose([0, 1, 3, 2]).contiguous()\n            x = x.reshape([x.size(0), -1, x.size(-1)])\n        else:\n            for conv in self.conv_layers:\n                x = conv(x)\n            if self.conv_type == \"conv2d\":\n                b, c, t, f = x.size()\n                # x = x.transpose(2, 3).contiguous().reshape([b, c * f, t])\n                x = x.transpose([0, 1, 3, 2]).contiguous().reshape(\n                    [b, c * f, t])\n        return x\n\n\nclass TransformerEncoder(nn.Layer):\n    def __init__(self, args):\n        super().__init__()\n\n        self.dropout = args.dropout\n        self.embedding_dim = args.encoder_embed_dim\n        dropout = 0\n        std = math.sqrt(\n            (4 * (1.0 - dropout)) / (args.conv_pos * self.embedding_dim))\n\n        self.pos_conv = nn.Conv1D(\n            self.embedding_dim,\n            self.embedding_dim,\n            kernel_size=args.conv_pos,\n            padding=args.conv_pos // 2,\n            groups=args.conv_pos_groups,\n            weight_attr=nn.initializer.Normal(mean=0, std=std),\n            bias_attr=True)\n        # nn.init.normal_(self.pos_conv.weight, mean=0, std=std)\n        # nn.init.constant_(self.pos_conv.bias, 0)\n\n        # self.pos_conv = nn.utils.weight_norm(self.pos_conv, name=\"weight\", dim=2)\n        # self.pos_conv.weight_g = self.pos_conv.weight_g.unsqueeze(0).unsqueeze(0)\n        self.pos_conv = nn.utils.weight_norm(\n            self.pos_conv, name=\"weight\", dim=2)\n        self.pos_conv = nn.Sequential(self.pos_conv,\n                                      SamePad(args.conv_pos), nn.GELU())\n\n        if hasattr(args, \"relative_position_embedding\"):\n            self.relative_position_embedding = args.relative_position_embedding\n            self.num_buckets = args.num_buckets\n            self.max_distance = args.max_distance\n        else:\n            self.relative_position_embedding = False\n            self.num_buckets = 0\n            self.max_distance = 0\n\n        self.layers = nn.LayerList([\n            TransformerSentenceEncoderLayer(\n                embedding_dim=self.embedding_dim,\n                ffn_embedding_dim=args.encoder_ffn_embed_dim,\n                num_attention_heads=args.encoder_attention_heads,\n                dropout=self.dropout,\n                attention_dropout=args.attention_dropout,\n                activation_dropout=args.activation_dropout,\n                activation_fn=args.activation_fn,\n                layer_norm_first=args.layer_norm_first,\n                has_relative_attention_bias=(\n                    self.relative_position_embedding and i == 0),\n                num_buckets=self.num_buckets,\n                max_distance=self.max_distance,\n                gru_rel_pos=args.gru_rel_pos, )\n            for i in range(args.encoder_layers)\n        ])\n\n        self.layer_norm_first = args.layer_norm_first\n        self.layer_norm = LayerNorm(self.embedding_dim)\n        self.layerdrop = args.encoder_layerdrop\n\n        # self.apply(init_bert_params)\n\n    def forward(self, x, padding_mask=None, streaming_mask=None, layer=None):\n        x, layer_results = self.extract_features(x, padding_mask,\n                                                 streaming_mask, layer)\n        # print(\"x.shape\", x.shape)\n        if self.layer_norm_first and layer is None:\n            x = self.layer_norm(x)\n\n        return x, layer_results\n\n    def extract_features(self,\n                         x,\n                         padding_mask=None,\n                         streaming_mask=None,\n                         tgt_layer=None):\n\n        if padding_mask is not None:\n            x[padding_mask] = 0\n\n        x_conv = self.pos_conv(x.transpose([0, 2, 1]))\n        x_conv = x_conv.transpose([0, 2, 1])\n        x += x_conv\n        if not self.layer_norm_first:\n            x = self.layer_norm(x)\n\n        x = F.dropout(x, p=self.dropout, training=self.training)\n\n        # B x T x C -> T x B x C\n        # x = x.transpose(0, 1)\n        x = x.transpose([1, 0, 2])\n\n        layer_results = []\n        z = None\n        if tgt_layer is not None:\n            layer_results.append((x, z))\n        r = None\n        pos_bias = None\n        for i, layer in enumerate(self.layers):\n            dropout_probability = np.random.random()\n            if not self.training or (dropout_probability > self.layerdrop):\n                x, z, pos_bias = layer(\n                    x,\n                    self_attn_padding_mask=padding_mask,\n                    need_weights=False,\n                    self_attn_mask=streaming_mask,\n                    pos_bias=pos_bias)\n            if tgt_layer is not None:\n                layer_results.append((x, z))\n            if i == tgt_layer:\n                r = x\n                break\n\n        if r is not None:\n            x = r\n\n        # T x B x C -> B x T x C\n        # x = x.transpose(0, 1)\n        x = x.transpose([1, 0, 2])\n\n        return x, layer_results\n\n\nclass TransformerSentenceEncoderLayer(nn.Layer):\n    \"\"\"\n    Implements a Transformer Encoder Layer used in BERT/XLM style pre-trained\n    models.\n    \"\"\"\n\n    def __init__(\n            self,\n            embedding_dim: float=768,\n            ffn_embedding_dim: float=3072,\n            num_attention_heads: float=8,\n            dropout: float=0.1,\n            attention_dropout: float=0.1,\n            activation_dropout: float=0.1,\n            activation_fn: str=\"relu\",\n            layer_norm_first: bool=False,\n            has_relative_attention_bias: bool=True,\n            num_buckets: int=0,\n            max_distance: int=0,\n            rescale_init: bool=False,\n            gru_rel_pos: bool=True, ) -> None:\n\n        super().__init__()\n        # Initialize parameters\n        self.embedding_dim = embedding_dim\n        self.dropout = dropout\n        self.activation_dropout = activation_dropout\n\n        # Initialize blocks\n        self.activation_name = activation_fn\n        self.activation_fn = get_activation_fn(activation_fn)\n        self.self_attn = MultiheadAttention(\n            self.embedding_dim,\n            num_attention_heads,\n            dropout=attention_dropout,\n            self_attention=True,\n            has_relative_attention_bias=has_relative_attention_bias,\n            num_buckets=num_buckets,\n            max_distance=max_distance,\n            rescale_init=rescale_init,\n            gru_rel_pos=gru_rel_pos, )\n\n        self.dropout1 = nn.Dropout(dropout)\n        self.dropout2 = nn.Dropout(self.activation_dropout)\n        self.dropout3 = nn.Dropout(dropout)\n\n        self.layer_norm_first = layer_norm_first\n\n        # layer norm associated with the self attention layer\n        self.self_attn_layer_norm = LayerNorm(self.embedding_dim)\n\n        if self.activation_name == \"glu\":\n            self.fc1 = GLU_Linear(self.embedding_dim, ffn_embedding_dim,\n                                  \"swish\")\n        else:\n            self.fc1 = nn.Linear(self.embedding_dim, ffn_embedding_dim)\n        self.fc2 = nn.Linear(ffn_embedding_dim, self.embedding_dim)\n\n        # layer norm associated with the position wise feed-forward NN\n        self.final_layer_norm = LayerNorm(self.embedding_dim)\n\n    def forward(self,\n                x: Tensor,\n                self_attn_mask: Tensor=None,\n                self_attn_padding_mask: Tensor=None,\n                need_weights: bool=False,\n                pos_bias=None):\n        \"\"\"\n        LayerNorm is applied either before or after the self-attention/ffn\n        modules similar to the original Transformer imlementation.\n        \"\"\"\n        residual = x\n        if self.layer_norm_first:\n\n            x = self.self_attn_layer_norm(x)\n            x, attn, pos_bias = self.self_attn(\n                query=x,\n                key=x,\n                value=x,\n                key_padding_mask=self_attn_padding_mask,\n                need_weights=False,\n                attn_mask=self_attn_mask,\n                position_bias=pos_bias)\n            # import pdb; pdb.set_trace()\n            x = self.dropout1(x)\n            x = residual + x\n\n            residual = x\n            x = self.final_layer_norm(x)\n            if self.activation_name == \"glu\":\n                x = self.fc1(x)\n            else:\n                x = self.activation_fn(self.fc1(x))\n            x = self.dropout2(x)\n            x = self.fc2(x)\n            x = self.dropout3(x)\n            x = residual + x\n        else:\n            x, attn, pos_bias = self.self_attn(\n                query=x,\n                key=x,\n                value=x,\n                key_padding_mask=self_attn_padding_mask,\n                need_weights=need_weights,\n                attn_mask=self_attn_mask,\n                position_bias=pos_bias)\n\n            x = self.dropout1(x)\n            x = residual + x\n\n            x = self.self_attn_layer_norm(x)\n\n            residual = x\n            if self.activation_name == \"glu\":\n                x = self.fc1(x)\n            else:\n                x = self.activation_fn(self.fc1(x))\n            x = self.dropout2(x)\n            x = self.fc2(x)\n            x = self.dropout3(x)\n            x = residual + x\n            x = self.final_layer_norm(x)\n\n        return x, attn, pos_bias\n"
  },
  {
    "path": "paddlespeech/s2t/models/whisper/__init__.py",
    "content": "# MIT License, Copyright (c) 2022 OpenAI.\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# \n# Modified from OpenAI Whisper 2022 (https://github.com/openai/whisper/whisper/__init__.py)\nfrom paddlespeech.s2t.models.whisper.whisper import decode\nfrom paddlespeech.s2t.models.whisper.whisper import DecodingOptions\nfrom paddlespeech.s2t.models.whisper.whisper import DecodingResult\nfrom paddlespeech.s2t.models.whisper.whisper import detect_language\nfrom paddlespeech.s2t.models.whisper.whisper import log_mel_spectrogram\nfrom paddlespeech.s2t.models.whisper.whisper import ModelDimensions\nfrom paddlespeech.s2t.models.whisper.whisper import transcribe\nfrom paddlespeech.s2t.models.whisper.whisper import Whisper\n"
  },
  {
    "path": "paddlespeech/s2t/models/whisper/tokenizer.py",
    "content": "# MIT License, Copyright (c) 2022 OpenAI.\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# \n# Modified from OpenAI Whisper 2022 (https://github.com/openai/whisper/whisper/tokenizer.py)\nimport base64\nimport os\nimport string\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom functools import cached_property\nfrom functools import lru_cache\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport tiktoken\n\nLANGUAGES = {\n    \"en\": \"english\",\n    \"zh\": \"chinese\",\n    \"de\": \"german\",\n    \"es\": \"spanish\",\n    \"ru\": \"russian\",\n    \"ko\": \"korean\",\n    \"fr\": \"french\",\n    \"ja\": \"japanese\",\n    \"pt\": \"portuguese\",\n    \"tr\": \"turkish\",\n    \"pl\": \"polish\",\n    \"ca\": \"catalan\",\n    \"nl\": \"dutch\",\n    \"ar\": \"arabic\",\n    \"sv\": \"swedish\",\n    \"it\": \"italian\",\n    \"id\": \"indonesian\",\n    \"hi\": \"hindi\",\n    \"fi\": \"finnish\",\n    \"vi\": \"vietnamese\",\n    \"he\": \"hebrew\",\n    \"uk\": \"ukrainian\",\n    \"el\": \"greek\",\n    \"ms\": \"malay\",\n    \"cs\": \"czech\",\n    \"ro\": \"romanian\",\n    \"da\": \"danish\",\n    \"hu\": \"hungarian\",\n    \"ta\": \"tamil\",\n    \"no\": \"norwegian\",\n    \"th\": \"thai\",\n    \"ur\": \"urdu\",\n    \"hr\": \"croatian\",\n    \"bg\": \"bulgarian\",\n    \"lt\": \"lithuanian\",\n    \"la\": \"latin\",\n    \"mi\": \"maori\",\n    \"ml\": \"malayalam\",\n    \"cy\": \"welsh\",\n    \"sk\": \"slovak\",\n    \"te\": \"telugu\",\n    \"fa\": \"persian\",\n    \"lv\": \"latvian\",\n    \"bn\": \"bengali\",\n    \"sr\": \"serbian\",\n    \"az\": \"azerbaijani\",\n    \"sl\": \"slovenian\",\n    \"kn\": \"kannada\",\n    \"et\": \"estonian\",\n    \"mk\": \"macedonian\",\n    \"br\": \"breton\",\n    \"eu\": \"basque\",\n    \"is\": \"icelandic\",\n    \"hy\": \"armenian\",\n    \"ne\": \"nepali\",\n    \"mn\": \"mongolian\",\n    \"bs\": \"bosnian\",\n    \"kk\": \"kazakh\",\n    \"sq\": \"albanian\",\n    \"sw\": \"swahili\",\n    \"gl\": \"galician\",\n    \"mr\": \"marathi\",\n    \"pa\": \"punjabi\",\n    \"si\": \"sinhala\",\n    \"km\": \"khmer\",\n    \"sn\": \"shona\",\n    \"yo\": \"yoruba\",\n    \"so\": \"somali\",\n    \"af\": \"afrikaans\",\n    \"oc\": \"occitan\",\n    \"ka\": \"georgian\",\n    \"be\": \"belarusian\",\n    \"tg\": \"tajik\",\n    \"sd\": \"sindhi\",\n    \"gu\": \"gujarati\",\n    \"am\": \"amharic\",\n    \"yi\": \"yiddish\",\n    \"lo\": \"lao\",\n    \"uz\": \"uzbek\",\n    \"fo\": \"faroese\",\n    \"ht\": \"haitian creole\",\n    \"ps\": \"pashto\",\n    \"tk\": \"turkmen\",\n    \"nn\": \"nynorsk\",\n    \"mt\": \"maltese\",\n    \"sa\": \"sanskrit\",\n    \"lb\": \"luxembourgish\",\n    \"my\": \"myanmar\",\n    \"bo\": \"tibetan\",\n    \"tl\": \"tagalog\",\n    \"mg\": \"malagasy\",\n    \"as\": \"assamese\",\n    \"tt\": \"tatar\",\n    \"haw\": \"hawaiian\",\n    \"ln\": \"lingala\",\n    \"ha\": \"hausa\",\n    \"ba\": \"bashkir\",\n    \"jw\": \"javanese\",\n    \"su\": \"sundanese\",\n    \"yue\": \"cantonese\",\n}\n\n# language code lookup by name, with a few language aliases\nTO_LANGUAGE_CODE = {\n    **{language: code for code, language in LANGUAGES.items()},\n    \"burmese\": \"my\",\n    \"valencian\": \"ca\",\n    \"flemish\": \"nl\",\n    \"haitian\": \"ht\",\n    \"letzeburgesch\": \"lb\",\n    \"pushto\": \"ps\",\n    \"panjabi\": \"pa\",\n    \"moldavian\": \"ro\",\n    \"moldovan\": \"ro\",\n    \"sinhalese\": \"si\",\n    \"castilian\": \"es\",\n    \"mandarin\": \"zh\",\n}\n\n\n@dataclass\nclass Tokenizer:\n    \"\"\"A thin wrapper around `tiktoken` providing quick access to special tokens\"\"\"\n\n    encoding: tiktoken.Encoding\n    num_languages: int\n    language: Optional[str] = None\n    task: Optional[str] = None\n    sot_sequence: Tuple[int] = ()\n    special_tokens: Dict[str, int] = field(default_factory=dict)\n\n    def __post_init__(self):\n        for special in self.encoding.special_tokens_set:\n            special_token = self.encoding.encode_single_token(special)\n            self.special_tokens[special] = special_token\n\n        sot: int = self.special_tokens[\"<|startoftranscript|>\"]\n        translate: int = self.special_tokens[\"<|translate|>\"]\n        transcribe: int = self.special_tokens[\"<|transcribe|>\"]\n        langs = tuple(LANGUAGES.keys())[:self.num_languages]\n        sot_sequence = [sot]\n        if self.language is not None:\n            sot_sequence.append(sot + 1 + langs.index(self.language))\n        if self.task is not None:\n            task_token: int = transcribe if self.task == \"transcribe\" else translate\n            sot_sequence.append(task_token)\n\n        self.sot_sequence = tuple(sot_sequence)\n\n    def encode(self, text, **kwargs):\n        return self.encoding.encode(text, **kwargs)\n\n    def decode(self, token_ids: List[int], **kwargs) -> str:\n        token_ids = [t for t in token_ids if t < self.timestamp_begin]\n        return self.encoding.decode(token_ids, **kwargs)\n\n    def decode_with_timestamps(self, token_ids: List[int], **kwargs) -> str:\n        \"\"\"\n        Timestamp tokens are above other special tokens' id range and are ignored by `decode()`.\n        This method decodes given tokens with timestamps tokens annotated, e.g. \"<|1.08|>\".\n        \"\"\"\n        return self.encoding.decode(token_ids, **kwargs)\n\n    @cached_property\n    def eot(self) -> int:\n        return self.encoding.eot_token\n\n    @cached_property\n    def transcribe(self) -> int:\n        return self.special_tokens[\"<|transcribe|>\"]\n\n    @cached_property\n    def translate(self) -> int:\n        return self.special_tokens[\"<|translate|>\"]\n\n    @cached_property\n    def sot(self) -> int:\n        return self.special_tokens[\"<|startoftranscript|>\"]\n\n    @cached_property\n    def sot_lm(self) -> int:\n        return self.special_tokens[\"<|startoflm|>\"]\n\n    @cached_property\n    def sot_prev(self) -> int:\n        return self.special_tokens[\"<|startofprev|>\"]\n\n    @cached_property\n    def no_speech(self) -> int:\n        return self.special_tokens[\"<|nospeech|>\"]\n\n    @cached_property\n    def no_timestamps(self) -> int:\n        return self.special_tokens[\"<|notimestamps|>\"]\n\n    @cached_property\n    def timestamp_begin(self) -> int:\n        return self.special_tokens[\"<|0.00|>\"]\n\n    @cached_property\n    def language_token(self) -> int:\n        \"\"\"Returns the token id corresponding to the value of the `language` field\"\"\"\n        if self.language is None:\n            raise ValueError(\n                \"This tokenizer does not have language token configured\")\n\n        return self.to_language_token(self.language)\n\n    def to_language_token(self, language):\n        if token := self.special_tokens.get(f\"<|{language}|>\", None):\n            return token\n\n        raise KeyError(f\"Language {language} not found in tokenizer.\")\n\n    @cached_property\n    def all_language_tokens(self) -> Tuple[int]:\n        result = []\n        for token, token_id in self.special_tokens.items():\n            if token.strip(\"<|>\") in LANGUAGES:\n                result.append(token_id)\n        return tuple(result)[:self.num_languages]\n\n    @cached_property\n    def all_language_codes(self) -> Tuple[str]:\n        return tuple(\n            self.decode([_l]).strip(\"<|>\") for _l in self.all_language_tokens)\n\n    @cached_property\n    def sot_sequence_including_notimestamps(self) -> Tuple[int]:\n        return tuple(list(self.sot_sequence) + [self.no_timestamps])\n\n    @cached_property\n    def non_speech_tokens(self) -> Tuple[int]:\n        \"\"\"\n        Returns the list of tokens to suppress in order to avoid any speaker tags or non-speech\n        annotations, to prevent sampling texts that are not actually spoken in the audio, e.g.\n\n        - ♪♪♪\n        - ( SPEAKING FOREIGN LANGUAGE )\n        - [DAVID] Hey there,\n\n        keeping basic punctuations like commas, periods, question marks, exclamation points, etc.\n        \"\"\"\n        symbols = list('\"#()*+/:;<=>@[\\\\]^_`{|}~「」『』')\n        symbols += (\n            \"<< >> <<< >>> -- --- -( -[ (' (\\\" (( )) ((( ))) [[ ]] {{ }} ♪♪ ♪♪♪\".\n            split())\n\n        # symbols that may be a single token or multiple tokens depending on the tokenizer.\n        # In case they're multiple tokens, suppress the first token, which is safe because:\n        # These are between U+2640 and U+267F miscellaneous symbols that are okay to suppress\n        # in generations, and in the 3-byte UTF-8 representation they share the first two bytes.\n        miscellaneous = set(\"♩♪♫♬♭♮♯\")\n        assert all(0x2640 <= ord(c) <= 0x267F for c in miscellaneous)\n\n        # allow hyphens \"-\" and single quotes \"'\" between words, but not at the beginning of a word\n        result = {self.encoding.encode(\" -\")[0], self.encoding.encode(\" '\")[0]}\n        for symbol in symbols + list(miscellaneous):\n            for tokens in [\n                    self.encoding.encode(symbol),\n                    self.encoding.encode(\" \" + symbol),\n            ]:\n                if len(tokens) == 1 or symbol in miscellaneous:\n                    result.add(tokens[0])\n\n        return tuple(sorted(result))\n\n    def split_to_word_tokens(self, tokens: List[int]):\n        if self.language in {\"zh\", \"ja\", \"th\", \"lo\", \"my\", \"yue\"}:\n            # These languages don't typically use spaces, so it is difficult to split words\n            # without morpheme analysis. Here, we instead split words at any\n            # position where the tokens are decoded as valid unicode points\n            return self.split_tokens_on_unicode(tokens)\n\n        return self.split_tokens_on_spaces(tokens)\n\n    def split_tokens_on_unicode(self, tokens: List[int]):\n        decoded_full = self.decode_with_timestamps(tokens)\n        replacement_char = \"\\ufffd\"\n\n        words = []\n        word_tokens = []\n        current_tokens = []\n        unicode_offset = 0\n\n        for token in tokens:\n            current_tokens.append(token)\n            decoded = self.decode_with_timestamps(current_tokens)\n\n            if (replacement_char not in decoded or\n                    decoded_full[unicode_offset + decoded.index(\n                        replacement_char)] == replacement_char):\n                words.append(decoded)\n                word_tokens.append(current_tokens)\n                current_tokens = []\n                unicode_offset += len(decoded)\n\n        return words, word_tokens\n\n    def split_tokens_on_spaces(self, tokens: List[int]):\n        subwords, subword_tokens_list = self.split_tokens_on_unicode(tokens)\n        words = []\n        word_tokens = []\n\n        for subword, subword_tokens in zip(subwords, subword_tokens_list):\n            special = subword_tokens[0] >= self.eot\n            with_space = subword.startswith(\" \")\n            punctuation = subword.strip() in string.punctuation\n            if special or with_space or punctuation or len(words) == 0:\n                words.append(subword)\n                word_tokens.append(subword_tokens)\n            else:\n                words[-1] = words[-1] + subword\n                word_tokens[-1].extend(subword_tokens)\n\n        return words, word_tokens\n\n\n@lru_cache(maxsize=None)\ndef get_encoding(resource_path: str, name: str=\"gpt2\", num_languages: int=99):\n    vocab_path = os.path.join(resource_path, \"assets\", f\"{name}.tiktoken\")\n    ranks = {\n        base64.b64decode(token): int(rank)\n        for token, rank in (line.split() for line in open(vocab_path) if line)\n    }\n\n    n_vocab = len(ranks)\n    special_tokens = {}\n    specials = [\n        \"<|endoftext|>\",\n        \"<|startoftranscript|>\",\n        * [f\"<|{lang}|>\" for lang in list(LANGUAGES.keys())[:num_languages]],\n        \"<|translate|>\",\n        \"<|transcribe|>\",\n        \"<|startoflm|>\",\n        \"<|startofprev|>\",\n        \"<|nospeech|>\",\n        \"<|notimestamps|>\",\n        * [f\"<|{i * 0.02:.2f}|>\" for i in range(1501)],\n    ]\n    for token in specials:\n        special_tokens[token] = n_vocab\n        n_vocab += 1\n    return tiktoken.Encoding(\n        name=os.path.basename(vocab_path),\n        explicit_n_vocab=n_vocab,\n        pat_str=r\"\"\"'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+\"\"\",\n        mergeable_ranks=ranks,\n        special_tokens=special_tokens, )\n\n\n@lru_cache(maxsize=None)\ndef get_tokenizer(\n        multilingual: bool,\n        resource_path: str,\n        *,\n        num_languages: int=99,\n        language: Optional[str]=None,\n        task: Optional[str]=None,  # Literal[\"transcribe\", \"translate\", None]\n) -> Tokenizer:\n\n    if language is not None:\n        language = language.lower()\n        if language not in LANGUAGES:\n            if language in TO_LANGUAGE_CODE:\n                language = TO_LANGUAGE_CODE[language]\n            else:\n                raise ValueError(f\"Unsupported language: {language}\")\n\n    if multilingual:\n        encoding_name = \"multilingual\"\n        language = language or \"en\"\n        task = task or \"transcribe\"\n    else:\n        encoding_name = \"gpt2\"\n        language = None\n        task = None\n\n    encoding = get_encoding(\n        resource_path=resource_path,\n        name=encoding_name,\n        num_languages=num_languages)\n\n    return Tokenizer(\n        encoding=encoding,\n        num_languages=num_languages,\n        language=language,\n        task=task)\n"
  },
  {
    "path": "paddlespeech/s2t/models/whisper/utils.py",
    "content": "# MIT License, Copyright (c) 2022 OpenAI.\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n# \n# Modified from OpenAI Whisper 2022 (https://github.com/openai/whisper/whisper/utils.py)\nimport zlib\nfrom typing import Iterator\nfrom typing import TextIO\n\n\ndef exact_div(x, y):\n    assert x % y == 0\n    return x // y\n\n\ndef str2bool(string):\n    str2val = {\"True\": True, \"False\": False}\n    if string in str2val:\n        return str2val[string]\n    else:\n        raise ValueError(f\"Expected one of {set(str2val.keys())}, got {string}\")\n\n\ndef optional_int(string):\n    return None if string == \"None\" else int(string)\n\n\ndef optional_float(string):\n    return None if string == \"None\" else float(string)\n\n\ndef compression_ratio(text) -> float:\n    return len(text) / len(zlib.compress(text.encode(\"utf-8\")))\n\n\ndef format_timestamp(seconds: float,\n                     always_include_hours: bool=False,\n                     decimal_marker: str='.'):\n    assert seconds >= 0, \"non-negative timestamp expected\"\n    milliseconds = round(seconds * 1000.0)\n\n    hours = milliseconds // 3_600_000\n    milliseconds -= hours * 3_600_000\n\n    minutes = milliseconds // 60_000\n    milliseconds -= minutes * 60_000\n\n    seconds = milliseconds // 1_000\n    milliseconds -= seconds * 1_000\n\n    hours_marker = f\"{hours:02d}:\" if always_include_hours or hours > 0 else \"\"\n    return f\"{hours_marker}{minutes:02d}:{seconds:02d}{decimal_marker}{milliseconds:03d}\"\n\n\ndef write_txt(transcript: Iterator[dict], file: TextIO):\n    for segment in transcript:\n        print(segment['text'].strip(), file=file, flush=True)\n\n\ndef write_vtt(transcript: Iterator[dict], file: TextIO):\n    print(\"WEBVTT\\n\", file=file)\n    for segment in transcript:\n        print(\n            f\"{format_timestamp(segment['start'])} --> {format_timestamp(segment['end'])}\\n\"\n            f\"{segment['text'].strip().replace('-->', '->')}\\n\",\n            file=file,\n            flush=True, )\n\n\ndef write_srt(transcript: Iterator[dict], file: TextIO):\n    \"\"\"\n    Write a transcript to a file in SRT format.\n\n    Example usage:\n        from pathlib import Path\n        from whisper.utils import write_srt\n\n        result = transcribe(model, audio_path, temperature=temperature, **args)\n\n        # save SRT\n        audio_basename = Path(audio_path).stem\n        with open(Path(output_dir) / (audio_basename + \".srt\"), \"w\", encoding=\"utf-8\") as srt:\n            write_srt(result[\"segments\"], file=srt)\n    \"\"\"\n    for i, segment in enumerate(transcript, start=1):\n        # write srt lines\n        print(\n            f\"{i}\\n\"\n            f\"{format_timestamp(segment['start'], always_include_hours=True, decimal_marker=',')} --> \"\n            f\"{format_timestamp(segment['end'], always_include_hours=True, decimal_marker=',')}\\n\"\n            f\"{segment['text'].strip().replace('-->', '->')}\\n\",\n            file=file,\n            flush=True, )\n"
  },
  {
    "path": "paddlespeech/s2t/models/whisper/whisper.py",
    "content": "# MIT License, Copyright (c) 2022 OpenAI.\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Modified from OpenAI Whisper 2022 (https://github.com/openai/whisper/whisper)\nimport os\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom functools import lru_cache\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nimport soundfile\nimport tqdm\nfrom paddle import nn\nfrom paddle.distribution import Categorical\n\nimport paddlespeech.s2t.modules.align as paddlespeech_nn\nfrom paddlespeech.s2t.models.whisper import utils\nfrom paddlespeech.s2t.models.whisper.tokenizer import get_tokenizer\nfrom paddlespeech.s2t.models.whisper.tokenizer import LANGUAGES\nfrom paddlespeech.s2t.models.whisper.tokenizer import Tokenizer\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n_MODELS = [\"large\"]\nSAMPLE_RATE = 16000\nN_FFT = 400\nHOP_LENGTH = 160\nCHUNK_LENGTH = 30\nN_SAMPLES = CHUNK_LENGTH * SAMPLE_RATE  # 480000: number of samples in a chunk\nN_FRAMES = utils.exact_div(\n    N_SAMPLES, HOP_LENGTH)  # 3000: number of frames in a mel spectrogram input\n\nN_SAMPLES_PER_TOKEN = HOP_LENGTH * 2  # the initial convolutions has stride 2\nFRAMES_PER_SECOND = utils.exact_div(SAMPLE_RATE,\n                                    HOP_LENGTH)  # 10ms per audio frame\nTOKENS_PER_SECOND = utils.exact_div(SAMPLE_RATE,\n                                    N_SAMPLES_PER_TOKEN)  # 20ms per audio token\n\n\n@dataclass\nclass ModelDimensions:\n    n_mels: int\n    n_audio_ctx: int\n    n_audio_state: int\n    n_audio_head: int\n    n_audio_layer: int\n    n_vocab: int\n    n_text_ctx: int\n    n_text_state: int\n    n_text_head: int\n    n_text_layer: int\n\n\nclass LayerNorm(paddlespeech_nn.LayerNorm):\n    def forward(self, x: paddle.Tensor) -> paddle.Tensor:\n        return super().forward(x)\n\n\nclass Linear(paddlespeech_nn.Linear):\n    def forward(self, x: paddle.Tensor) -> paddle.Tensor:\n        return F.linear(x, self.weight, None\n                        if self.bias is None else self.bias)\n\n\nclass Conv1d(paddlespeech_nn.Conv1D):\n    def forward(self, x: paddle.Tensor) -> paddle.Tensor:\n        return super().forward(x)\n\n\nclass MultiHeadAttention(nn.Layer):\n    def __init__(self, n_state: int, n_head: int):\n        super().__init__()\n        self.n_head = n_head\n        self.query = Linear(n_state, n_state, bias_attr=True)\n        self.key = Linear(n_state, n_state, bias_attr=False)\n        self.value = Linear(n_state, n_state, bias_attr=True)\n        self.out = Linear(n_state, n_state, bias_attr=True)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            xa: Optional[paddle.Tensor]=None,\n            mask: Optional[paddle.Tensor]=None,\n            kv_cache: Optional[dict]=None, ):\n        q = self.query(x)\n\n        if kv_cache is None or xa is None or self.key not in kv_cache:\n            # hooks, if installed (i.e. kv_cache is not None), will prepend the cached kv tensors;\n            # otherwise, perform key/value projections for self- or cross-attention as usual.\n            k = self.key(x if xa is None else xa)\n            v = self.value(x if xa is None else xa)\n        else:\n            # for cross-attention, calculate keys and values once and reuse in subsequent calls.\n            k = kv_cache[self.key]\n            v = kv_cache[self.value]\n\n        wv = self.qkv_attention(q, k, v, mask)\n        return self.out(wv)\n\n    def qkv_attention(self,\n                      q: paddle.Tensor,\n                      k: paddle.Tensor,\n                      v: paddle.Tensor,\n                      mask: Optional[paddle.Tensor]=None):\n        n_batch, n_ctx, n_state = q.shape\n        scale = (n_state // self.n_head)**-0.25\n        q = paddle.transpose(\n            q.reshape([*q.shape[:2], self.n_head, -1]), (0, 2, 1, 3)) * scale\n        k = paddle.transpose(\n            k.reshape([*k.shape[:2], self.n_head, -1]), (0, 2, 3, 1)) * scale\n        v = paddle.transpose(\n            v.reshape([*v.shape[:2], self.n_head, -1]), (0, 2, 1, 3))\n\n        qk = q @ k\n        if mask is not None:\n            qk = qk + mask[:n_ctx, :n_ctx]\n\n        w = F.softmax(qk.float(), axis=-1).to(q.dtype)\n        return paddle.transpose((w @ v), (0, 2, 1, 3)).flatten(start_axis=2)\n\n\nclass ResidualAttentionBlock(nn.Layer):\n    def __init__(self, n_state: int, n_head: int, cross_attention: bool=False):\n        super().__init__()\n\n        self.attn = MultiHeadAttention(n_state, n_head)\n        self.attn_ln = LayerNorm(n_state)\n\n        self.cross_attn = MultiHeadAttention(\n            n_state, n_head) if cross_attention else None\n        self.cross_attn_ln = LayerNorm(n_state) if cross_attention else None\n\n        n_mlp = n_state * 4\n        self.mlp = nn.Sequential(\n            Linear(n_state, n_mlp, bias_attr=True),\n            nn.GELU(), Linear(n_mlp, n_state, bias_attr=True))\n        self.mlp_ln = LayerNorm(n_state)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            xa: Optional[paddle.Tensor]=None,\n            mask: Optional[paddle.Tensor]=None,\n            kv_cache: Optional[dict]=None, ):\n        x = x + self.attn(self.attn_ln(x), mask=mask, kv_cache=kv_cache)\n        if self.cross_attn:\n            x = x + self.cross_attn(\n                self.cross_attn_ln(x), xa, kv_cache=kv_cache)\n        x = x + self.mlp(self.mlp_ln(x))\n        return x\n\n\ndef sinusoids(length, channels, max_timescale=10000):\n    \"\"\"Returns sinusoids for positional embedding\"\"\"\n    assert channels % 2 == 0\n    log_timescale_increment = np.log(max_timescale) / (channels // 2 - 1)\n    inv_timescales = paddle.exp(-log_timescale_increment * paddle.arange(\n        channels // 2, dtype=paddle.float32))\n    scaled_time = paddle.arange(\n        length,\n        dtype=paddle.float32)[:, np.newaxis] * inv_timescales[np.newaxis, :]\n    return paddle.to_tensor(\n        paddle.concat(\n            [paddle.sin(scaled_time), paddle.cos(scaled_time)], axis=1))\n\n\nclass AudioEncoder(nn.Layer):\n    def __init__(self,\n                 n_mels: int,\n                 n_ctx: int,\n                 n_state: int,\n                 n_head: int,\n                 n_layer: int):\n        super().__init__()\n        self.conv1 = Conv1d(\n            n_mels, n_state, kernel_size=3, stride=1, padding=1, bias_attr=True)\n        self.conv2 = Conv1d(\n            n_state,\n            n_state,\n            kernel_size=3,\n            stride=2,\n            padding=1,\n            bias_attr=True)\n        self.register_buffer(\"positional_embedding\", sinusoids(n_ctx, n_state))\n\n        self.blocks: Iterable[ResidualAttentionBlock] = nn.LayerList(\n            [ResidualAttentionBlock(n_state, n_head) for _ in range(n_layer)])\n        self.ln_post = LayerNorm(n_state)\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"\n        x : paddle.Tensor, shape = (batch_size, n_mels, n_ctx)\n            the mel spectrogram of the audio\n        \"\"\"\n        x = F.gelu(self.conv1(x))\n        x = F.gelu(self.conv2(x))\n        x = paddle.transpose(x, (0, 2, 1))\n\n        assert x.shape[\n            1:] == self.positional_embedding.shape, \"incorrect audio shape\"\n        x = (x + self.positional_embedding)\n\n        for block in self.blocks:\n            x = block(x)\n\n        x = self.ln_post(x)\n        return x\n\n\nclass TextDecoder(nn.Layer):\n    def __init__(self,\n                 n_vocab: int,\n                 n_ctx: int,\n                 n_state: int,\n                 n_head: int,\n                 n_layer: int):\n        super().__init__()\n\n        self.token_embedding = nn.Embedding(n_vocab, n_state)\n        self.positional_embedding = paddle.create_parameter(\n            shape=[n_ctx, n_state], dtype='float32')\n\n        self.blocks: Iterable[ResidualAttentionBlock] = nn.LayerList([\n            ResidualAttentionBlock(n_state, n_head, cross_attention=True)\n            for _ in range(n_layer)\n        ])\n        self.ln = LayerNorm(n_state)\n\n        mask = paddle.full(\n            shape=[n_ctx, n_state], fill_value=-np.inf, dtype='float32')\n        mask = paddle.triu(mask, diagonal=1)\n        self.register_buffer(\"mask\", mask, persistable=False)\n\n    def forward(self,\n                x: paddle.Tensor,\n                xa: paddle.Tensor,\n                kv_cache: Optional[dict]=None):\n        \"\"\"\n        x : paddle.LongTensor, shape = (batch_size, <= n_ctx)\n            the text tokens\n        xa : paddle.Tensor, shape = (batch_size, n_mels, n_audio_ctx)\n            the encoded audio features to be attended on\n        \"\"\"\n        offset = next(iter(kv_cache.values())).shape[1] if kv_cache else 0\n        x = self.token_embedding(x) + self.positional_embedding[offset:offset +\n                                                                x.shape[-1]]\n        x = x.to(xa.dtype)\n\n        for block in self.blocks:\n            x = block(x, xa, mask=self.mask, kv_cache=kv_cache)\n\n        x = self.ln(x)\n        logits = (x @ paddle.transpose(self.token_embedding.weight, (1, 0)))\n\n        return logits\n\n\n@dataclass(frozen=True)\nclass DecodingOptions:\n    task: str = \"transcribe\"  # whether to perform X->X \"transcribe\" or X->English \"translate\"\n    language: Optional[\n        str] = None  # language that the audio is in; uses detected language if None\n    # sampling-related options\n    temperature: float = 0.0\n    sample_len: Optional[int] = None  # maximum number of tokens to sample\n    best_of: Optional[\n        int] = None  # number of independent samples to collect, when t > 0\n    beam_size: Optional[\n        int] = None  # number of beams in beam search, when t == 0\n    patience: Optional[\n        float] = None  # patience in beam search (https://arxiv.org/abs/2204.05424)\n\n    # options for ranking generations (either beams or best-of-N samples)\n    length_penalty: Optional[\n        float] = None  # \"alpha\" in Google NMT, None defaults to length norm\n\n    # prompt, prefix, and token suppression\n    prompt: Optional[Union[str, List[\n        int]]] = None  # text or tokens for the previous context\n    prefix: Optional[Union[str, List[\n        int]]] = None  # text or tokens to prefix the current context\n    suppress_blank: bool = True  # this will suppress blank outputs\n\n    # list of tokens ids (or comma-separated token ids) to suppress\n    # \"-1\" will suppress a set of symbols as defined in `tokenizer.non_speech_tokens()`\n    suppress_tokens: Optional[Union[str, Iterable[int]]] = \"-1\"\n\n    # timestamp sampling options\n    without_timestamps: bool = False  # use <|notimestamps|> to sample text tokens only\n    max_initial_timestamp: Optional[\n        float] = 1.0  # the initial timestamp cannot be later than this\n\n    # implementation details\n    fp16: bool = False  # use fp16 for most of the calculation\n\n\n@dataclass(frozen=True)\nclass DecodingResult:\n    audio_features: paddle.Tensor\n    language: str\n    language_probs: Optional[Dict[str, float]] = None\n    tokens: List[int] = field(default_factory=list)\n    text: str = \"\"\n    avg_logprob: float = np.nan\n    no_speech_prob: float = np.nan\n    temperature: float = np.nan\n    compression_ratio: float = np.nan\n\n\nclass Inference:\n    def logits(self, tokens: paddle.Tensor,\n               audio_features: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Perform a forward pass on the decoder and return per-token logits\"\"\"\n        raise NotImplementedError\n\n    def rearrange_kv_cache(self, source_indices) -> None:\n        \"\"\"Update the key-value cache according to the updated beams\"\"\"\n        raise NotImplementedError\n\n    def cleanup_caching(self) -> None:\n        \"\"\"Clean up any resources or hooks after decoding is finished\"\"\"\n        pass\n\n\nclass WhisperInference(Inference):\n    def __init__(self, model: \"Whisper\", initial_token_length: int):\n        self.model: \"Whisper\" = model\n        self.initial_token_length = initial_token_length\n        self.kv_cache = {}\n        self.hooks = []\n\n    def logits(self, tokens: paddle.Tensor,\n               audio_features: paddle.Tensor) -> paddle.Tensor:\n        if not self.kv_cache:\n            self.kv_cache, self.hooks = self.model.install_kv_cache_hooks()\n\n        if tokens.shape[-1] > self.initial_token_length:\n            # only need to use the last token except in the first forward pass\n            tokens = tokens[:, -1:]\n\n        return self.model.decoder(\n            tokens, audio_features, kv_cache=self.kv_cache)\n\n    def cleanup_caching(self):\n        for hook in self.hooks:\n            hook.remove()\n\n        self.kv_cache = {}\n        self.hooks = []\n\n    def rearrange_kv_cache(self, source_indices):\n        for module, tensor in self.kv_cache.items():\n            # update the key/value cache to contain the selected sequences\n            self.kv_cache[module] = tensor[source_indices].detach()\n\n\n@paddle.no_grad()\ndef detect_language(\n        model: \"Whisper\",\n        mel: paddle.Tensor,\n        resource_path: str,\n        tokenizer: Tokenizer=None) -> Tuple[paddle.Tensor, List[dict]]:\n    \"\"\"\n    Detect the spoken language in the audio, and return them as list of strings, along with the ids\n    of the most probable language tokens and the probability distribution over all language tokens.\n    This is performed outside the main decode loop in order to not interfere with kv-caching.\n\n    Returns\n    -------\n    language_tokens : Tensor, shape = (batch_size,)\n        ids of the most probable language tokens, which appears after the startoftranscript token.\n    language_probs : List[Dict[str, float]], length = batch_size\n        list of dictionaries containing the probability distribution over all languages.\n    \"\"\"\n    if tokenizer is None:\n        tokenizer = get_tokenizer(\n            multilingual=model.is_multilingual,\n            resource_path=resource_path,\n            num_languages=model.num_languages)\n    if tokenizer.language is None or tokenizer.language_token not in tokenizer.sot_sequence:\n        raise ValueError(\n            \"This model doesn't have language tokens so it can't perform lang id\"\n        )\n\n    single = mel.ndim == 2\n    if single:\n        mel = mel.unsqueeze(0)\n\n    # skip encoder forward pass if already-encoded audio features were given\n    if mel.shape[-2:] != (model.dims.n_audio_ctx, model.dims.n_audio_state):\n        mel = model.encoder(mel)\n\n    # forward pass using a single token, startoftranscript\n    batch_size = mel.shape[0]\n    x = paddle.to_tensor([[tokenizer.sot]] * batch_size)  # [batch_size, 1]\n    logits = model.logits(x, mel)[:, 0]\n\n    # collect detected languages; suppress all non-language tokens\n    mask = paddle.ones(paddle.to_tensor(logits.shape[-1]), dtype=bool)\n    mask[list(tokenizer.all_language_tokens)] = False\n    logits.contiguous()\n    logits[:, mask] = -np.inf\n    language_tokens = paddle.argmax(logits, axis=-1)\n    language_token_probs = F.softmax(logits, axis=-1)\n    language_probs = [{\n        c: language_token_probs[i, j].tolist()\n        for j, c in zip(tokenizer.all_language_tokens,\n                        tokenizer.all_language_codes)\n    } for i in range(batch_size)]\n\n    if single:\n        language_tokens = language_tokens[0]\n        language_probs = language_probs[0]\n\n    return language_tokens, language_probs\n\n\ndef transcribe(\n        model: \"Whisper\",\n        mel: paddle.Tensor,\n        resource_path: str,\n        *,\n        verbose: Optional[bool]=None,\n        temperature: Union[float, Tuple[float, ...]]=(0.0, 0.2, 0.4, 0.6, 0.8,\n                                                      1.0),\n        compression_ratio_threshold: Optional[float]=2.4,\n        logprob_threshold: Optional[float]=-1.0,\n        no_speech_threshold: Optional[float]=0.6,\n        condition_on_previous_text: bool=True,\n        initial_prompt: Optional[str]=None,\n        carry_initial_prompt: bool=False,\n        word_timestamps: bool=False,\n        prepend_punctuations: str=\"\\\"'“¿([{-\",\n        append_punctuations: str=\"\\\"'.。,，!！?？:：”)]}、\",\n        clip_timestamps: Union[str, List[float]]=\"0\",\n        hallucination_silence_threshold: Optional[float]=None,\n        **decode_options, ):\n    \"\"\"\n    Transcribe an audio file using Whisper\n\n    Parameters\n    ----------\n    model: Whisper\n        The Whisper model instance\n\n    mel: paddle.Tensor\n        The audio feature\n\n    verbose: bool\n        Whether to display the text being decoded to the console. If True, displays all the details,\n        If False, displays minimal details. If None, does not display anything\n\n    temperature: Union[float, Tuple[float, ...]]\n        Temperature for sampling. It can be a tuple of temperatures, which will be successfully used\n        upon failures according to either `compression_ratio_threshold` or `logprob_threshold`.\n\n    compression_ratio_threshold: float\n        If the gzip compression ratio is above this value, treat as failed\n\n    logprob_threshold: float\n        If the average log probability over sampled tokens is below this value, treat as failed\n\n    no_speech_threshold: float\n        If the no_speech probability is higher than this value AND the average log probability\n        over sampled tokens is below `logprob_threshold`, consider the segment as silent\n\n    condition_on_previous_text: bool\n        if True, the previous output of the model is provided as a prompt for the next window;\n        disabling may make the text inconsistent across windows, but the model becomes less prone to\n        getting stuck in a failure loop, such as repetition looping or timestamps going out of sync.\n\n    decode_options: dict\n        Keyword arguments to construct `DecodingOptions` instances\n\n    Returns\n    -------\n    A dictionary containing the resulting text (\"text\") and segment-level details (\"segments\"), and\n    the spoken language (\"language\"), which is detected when `decode_options[\"language\"]` is None.\n    \"\"\"\n    dtype = np.float32  #paddle only support float32\n\n    if dtype == np.float32:\n        decode_options[\"fp16\"] = False\n\n    content_frames = mel.shape[-1] - N_FRAMES\n    content_duration = float(content_frames * HOP_LENGTH / SAMPLE_RATE)\n    if decode_options.get(\"language\", None) in {None, \"None\"}:\n        if not model.is_multilingual:\n            decode_options[\"language\"] = \"en\"\n        else:\n            if verbose:\n                print(\n                    \"Detecting language using up to the first 30 seconds. Use `--language` to specify the language\"\n                )\n            mel_segment = pad_or_trim(mel,\n                                      N_FRAMES).to(model.device).astype(dtype)\n            _, probs = model.detect_language(mel_segment, resource_path)\n            decode_options[\"language\"] = max(probs, key=probs.get)\n            if verbose is not None:\n                print(\n                    f\"Detected language: {LANGUAGES[decode_options['language']].title()}\"\n                )\n\n    language: str = decode_options[\"language\"]\n    task: str = decode_options.get(\"task\", \"transcribe\")\n    tokenizer = get_tokenizer(\n        multilingual=model.is_multilingual,\n        resource_path=resource_path,\n        num_languages=model.num_languages,\n        language=language,\n        task=task, )\n\n    if isinstance(clip_timestamps, str):\n        clip_timestamps = [\n            float(ts)\n            for ts in (clip_timestamps.split(\",\") if clip_timestamps else [])\n        ]\n    seek_points: List[\n        int] = [round(ts * FRAMES_PER_SECOND) for ts in clip_timestamps]\n    if len(seek_points) == 0:\n        seek_points.append(0)\n    if len(seek_points) % 2 == 1:\n        seek_points.append(content_frames)\n    seek_clips: List[Tuple[int, int]] = list(\n        zip(seek_points[::2], seek_points[1::2]))\n\n    punctuation = \"\\\"'“¿([{-\\\"'.。,，!！?？:：”)]}、\"\n\n    if word_timestamps and task == \"translate\":\n        warnings.warn(\n            \"Word-level timestamps on translations may not be reliable.\")\n\n    def decode_with_fallback(segment: paddle.Tensor) -> DecodingResult:\n        temperatures = ([temperature] if isinstance(temperature, (int, float))\n                        else temperature)\n        decode_result = None\n\n        for t in temperatures:\n            kwargs = {**decode_options}\n            if t > 0:\n                # disable beam_size and patience when t > 0\n                kwargs.pop(\"beam_size\", None)\n                kwargs.pop(\"patience\", None)\n            else:\n                # disable best_of when t == 0\n                kwargs.pop(\"best_of\", None)\n\n            options = DecodingOptions(**kwargs, temperature=t)\n\n            decode_result = model.decode(segment, options, resource_path)\n\n            needs_fallback = False\n            if (compression_ratio_threshold is not None and\n                    decode_result.compression_ratio >\n                    compression_ratio_threshold):\n                needs_fallback = True  # too repetitive\n            if (logprob_threshold is not None and\n                    decode_result.avg_logprob < logprob_threshold):\n                needs_fallback = True  # average log probability is too low\n            if (no_speech_threshold is not None and\n                    decode_result.no_speech_prob > no_speech_threshold and\n                    logprob_threshold is not None and\n                    decode_result.avg_logprob < logprob_threshold):\n                needs_fallback = False  # silence\n            if not needs_fallback:\n                break\n\n        return decode_result\n\n    clip_idx = 0\n    seek = seek_clips[clip_idx][0]\n    input_stride = utils.exact_div(\n        N_FRAMES, model.dims.n_audio_ctx)  # mel frames per output token: 2\n    time_precision = (input_stride * HOP_LENGTH /\n                      SAMPLE_RATE)  # time per output token: 0.02 (seconds)\n    all_tokens = []\n    all_segments = []\n    prompt_reset_since = 0\n\n    remaining_prompt_length = model.dims.n_text_ctx // 2 - 1\n    if initial_prompt is not None:\n        initial_prompt_tokens = tokenizer.encode(\" \" + initial_prompt.strip())\n        all_tokens.extend(initial_prompt_tokens)\n        remaining_prompt_length -= len(initial_prompt_tokens)\n    else:\n        initial_prompt_tokens = []\n\n    def new_segment(*,\n                    start: float,\n                    end: float,\n                    tokens: paddle.Tensor,\n                    result: DecodingResult):\n        tokens = tokens.tolist()\n        text_tokens = [token for token in tokens if token < tokenizer.eot]\n        return {\n            \"seek\": seek,\n            \"start\": start,\n            \"end\": end,\n            \"text\": tokenizer.decode(text_tokens),\n            \"tokens\": tokens,\n            \"temperature\": result.temperature,\n            \"avg_logprob\": result.avg_logprob,\n            \"compression_ratio\": result.compression_ratio,\n            \"no_speech_prob\": result.no_speech_prob,\n        }\n\n    # show the progress bar when verbose is False (if True, transcribed text will be printed)\n    with tqdm.tqdm(\n            total=content_frames, unit=\"frames\",\n            disable=verbose is not False) as pbar:\n        last_speech_timestamp = 0.0\n        # NOTE: This loop is obscurely flattened to make the diff readable.\n        # A later commit should turn this into a simpler nested loop.\n        # for seek_clip_start, seek_clip_end in seek_clips:\n        #     while seek < seek_clip_end\n        while clip_idx < len(seek_clips):\n            seek_clip_start, seek_clip_end = seek_clips[clip_idx]\n            if seek < seek_clip_start:\n                seek = seek_clip_start\n            if seek >= seek_clip_end:\n                clip_idx += 1\n                if clip_idx < len(seek_clips):\n                    seek = seek_clips[clip_idx][0]\n                continue\n            time_offset = float(seek * HOP_LENGTH / SAMPLE_RATE)\n            window_end_time = float(\n                (seek + N_FRAMES) * HOP_LENGTH / SAMPLE_RATE)\n            segment_size = min(N_FRAMES, content_frames - seek,\n                               seek_clip_end - seek)\n            mel_segment = mel[:, seek:seek + segment_size]\n            segment_duration = segment_size * HOP_LENGTH / SAMPLE_RATE\n            mel_segment = pad_or_trim(mel_segment,\n                                      N_FRAMES).to(model.device).astype(dtype)\n\n            if carry_initial_prompt:\n                nignored = max(len(initial_prompt_tokens), prompt_reset_since)\n                remaining_prompt = all_tokens[nignored:][\n                    -remaining_prompt_length:]\n                decode_options[\n                    \"prompt\"] = initial_prompt_tokens + remaining_prompt\n            else:\n                decode_options[\"prompt\"] = all_tokens[prompt_reset_since:]\n            result: DecodingResult = decode_with_fallback(mel_segment)\n            tokens = paddle.to_tensor(result.tokens)\n\n            if no_speech_threshold is not None:\n                # no voice activity check\n                should_skip = result.no_speech_prob > no_speech_threshold\n                if (logprob_threshold is not None and\n                        result.avg_logprob > logprob_threshold):\n                    # don't skip if the logprob is high enough, despite the no_speech_prob\n                    should_skip = False\n\n                if should_skip:\n                    seek += segment_size  # fast-forward to the next segment boundary\n                    continue\n\n            previous_seek = seek\n            current_segments = []\n\n            # anomalous words are very long/short/improbable\n            def word_anomaly_score(word: dict) -> float:\n                probability = word.get(\"probability\", 0.0)\n                duration = word[\"end\"] - word[\"start\"]\n                score = 0.0\n                if probability < 0.15:\n                    score += 1.0\n                if duration < 0.133:\n                    score += (0.133 - duration) * 15\n                if duration > 2.0:\n                    score += duration - 2.0\n                return score\n\n            def is_segment_anomaly(segment: Optional[dict]) -> bool:\n                if segment is None or not segment[\"words\"]:\n                    return False\n                words = [\n                    w for w in segment[\"words\"] if w[\"word\"] not in punctuation\n                ]\n                words = words[:8]\n                score = sum(word_anomaly_score(w) for w in words)\n                return score >= 3 or score + 0.01 >= len(words)\n\n            def next_words_segment(segments: List[dict]) -> Optional[dict]:\n                return next((s for s in segments if s[\"words\"]), None)\n\n            timestamp_tokens: paddle.Tensor = tokens.greater_equal(\n                paddle.to_tensor(tokenizer.timestamp_begin))\n            single_timestamp_ending = timestamp_tokens[\n                -2:].tolist() == [False, True]\n\n            consecutive = paddle.where(timestamp_tokens[:-1] & timestamp_tokens[\n                1:])[0]\n            if consecutive.numel() != 0:\n                consecutive = paddle.add(consecutive, paddle.to_tensor(1))\n            if len(consecutive) > 0:\n                # if the output contains two consecutive timestamp tokens\n                slices = consecutive.tolist()\n                if single_timestamp_ending:\n                    slices.append(len(tokens))\n\n                last_slice = 0\n                for current_slice in slices:\n                    sliced_tokens = tokens[last_slice:current_slice]\n                    start_timestamp_pos = (\n                        sliced_tokens[0].item() - tokenizer.timestamp_begin)\n                    end_timestamp_pos = (\n                        sliced_tokens[-1].item() - tokenizer.timestamp_begin)\n                    current_segments.append(\n                        new_segment(\n                            start=time_offset + start_timestamp_pos *\n                            time_precision,\n                            end=time_offset + end_timestamp_pos *\n                            time_precision,\n                            tokens=sliced_tokens,\n                            result=result, ))\n                    last_slice = current_slice\n\n                if single_timestamp_ending:\n                    # single timestamp at the end means no speech after the last timestamp.\n                    seek += segment_size\n                else:\n                    # otherwise, ignore the unfinished segment and seek to the last timestamp\n                    last_timestamp_pos = (tokens[last_slice - 1].item() -\n                                          tokenizer.timestamp_begin)\n                    seek += last_timestamp_pos * input_stride\n            else:\n                duration = segment_duration\n                timestamps = tokens[timestamp_tokens.nonzero().flatten()]\n                if (len(timestamps) > 0 and\n                        timestamps[-1].item() != tokenizer.timestamp_begin):\n                    # no consecutive timestamps but it has a timestamp; use the last one.\n                    last_timestamp_pos = (\n                        timestamps[-1].item() - tokenizer.timestamp_begin)\n                    duration = last_timestamp_pos * time_precision\n\n                current_segments.append(\n                    new_segment(\n                        start=time_offset,\n                        end=time_offset + duration,\n                        tokens=tokens,\n                        result=result, ))\n                seek += segment_size\n\n            if verbose:\n                for segment in current_segments:\n                    start, end, text = segment[\"start\"], segment[\n                        \"end\"], segment[\"text\"]\n                    line = f\"[{utils.format_timestamp(start)} --> {utils.format_timestamp(end)}] {text}\"\n                    print(line)\n\n            # if a segment is instantaneous or does not contain text, clear it\n            for i, segment in enumerate(current_segments):\n                if segment[\"start\"] == segment[\"end\"] or segment[\n                        \"text\"].strip() == \"\":\n                    segment[\"text\"] = \"\"\n                    segment[\"tokens\"] = []\n                    segment[\"words\"] = []\n\n            all_segments.extend(\n                [{\n                    \"id\": i,\n                    **\n                    segment\n                }\n                 for i, segment in enumerate(\n                     current_segments, start=len(all_segments))])\n            all_tokens.extend([\n                token\n                for segment in current_segments for token in segment[\"tokens\"]\n            ])\n\n            if not condition_on_previous_text or result.temperature > 0.5:\n                # do not feed the prompt tokens if a high temperature was used\n                prompt_reset_since = len(all_tokens)\n\n            # update progress bar\n            pbar.update(min(content_frames, seek) - previous_seek)\n\n    return dict(\n        text=tokenizer.decode(all_tokens[len(initial_prompt_tokens):]),\n        segments=all_segments,\n        language=language, )\n\n\nclass SequenceRanker:\n    def rank(self,\n             tokens: List[List[paddle.Tensor]],\n             sum_logprobs: List[List[float]]) -> List[int]:\n        \"\"\"\n        Given a list of groups of samples and their cumulative log probabilities,\n        return the indices of the samples in each group to select as the final result\n        \"\"\"\n        raise NotImplementedError\n\n\nclass MaximumLikelihoodRanker(SequenceRanker):\n    \"\"\"\n    Select the sample with the highest log probabilities, penalized using either\n    a simple length normalization or Google NMT paper's length penalty\n    \"\"\"\n\n    def __init__(self, length_penalty: Optional[float]):\n        self.length_penalty = length_penalty\n\n    def rank(self,\n             tokens: List[List[paddle.Tensor]],\n             sum_logprobs: List[List[float]]):\n        def scores(logprobs, lengths):\n            result = []\n            for logprob, length in zip(logprobs, lengths):\n                if self.length_penalty is None:\n                    penalty = length\n                else:\n                    # from the Google NMT paper\n                    penalty = ((5 + length) / 6)**self.length_penalty\n                result.append(logprob / penalty)\n            return result\n\n        # get the sequence with the highest score\n        lengths = [[len(t) for t in s] for s in tokens]\n        return [np.argmax(scores(p, l)) for p, l in zip(sum_logprobs, lengths)]\n\n\nclass TokenDecoder:\n    def reset(self):\n        \"\"\"Initialize any stateful variables for decoding a new sequence\"\"\"\n\n    def update(self,\n               tokens: paddle.Tensor,\n               logits: paddle.Tensor,\n               sum_logprobs: paddle.Tensor) -> Tuple[paddle.Tensor, bool]:\n        \"\"\"Specify how to select the next token, based on the current trace and logits\n\n        Parameters\n        ----------\n        tokens : Tensor, shape = (n_batch, current_sequence_length)\n            all tokens in the context so far, including the prefix and sot_sequence tokens\n\n        logits : Tensor, shape = (n_batch, vocab_size)\n            per-token logits of the probability distribution at the current step\n\n        sum_logprobs : Tensor, shape = (n_batch)\n            cumulative log probabilities for each sequence\n\n        Returns\n        -------\n        tokens : Tensor, shape = (n_batch, current_sequence_length + 1)\n            the tokens, appended with the selected next token\n\n        completed : bool\n            True if all sequences has reached the end of text\n\n        \"\"\"\n        raise NotImplementedError\n\n    def finalize(\n            self, tokens: paddle.Tensor, sum_logprobs: paddle.Tensor\n    ) -> Tuple[Sequence[Sequence[paddle.Tensor]], List[List[float]]]:\n        \"\"\"Finalize search and return the final candidate sequences\n\n        Parameters\n        ----------\n        tokens : Tensor, shape = (batch_size, beam_size, current_sequence_length)\n            all tokens in the context so far, including the prefix and sot_sequence\n\n        sum_logprobs : Tensor, shape = (batch_size, beam_size)\n            cumulative log probabilities for each sequence\n\n        Returns\n        -------\n        tokens : Sequence[Sequence[Tensor]], length = batch_size\n            sequence of Tensors containing candidate token sequences, for each audio input\n\n        sum_logprobs : List[List[float]], length = batch_size\n            sequence of cumulative log probabilities corresponding to the above\n\n        \"\"\"\n        raise NotImplementedError\n\n\nclass GreedyDecoder(TokenDecoder):\n    def __init__(self, temperature: float, eot: int):\n        self.temperature = temperature\n        self.eot = eot\n\n    def update(self,\n               tokens: paddle.Tensor,\n               logits: paddle.Tensor,\n               sum_logprobs: paddle.Tensor) -> Tuple[paddle.Tensor, bool]:\n        temperature = self.temperature\n        if temperature == 0:\n            next_tokens = paddle.argmax(logits, axis=-1)\n        else:\n            next_tokens = Categorical(logits=logits / temperature).sample([1])\n            next_tokens = paddle.reshape(next_tokens, [\n                next_tokens.shape[0] * next_tokens.shape[1],\n            ])\n\n        logprobs = F.log_softmax(logits, axis=-1, dtype=\"float32\")\n        current_logprobs = logprobs[paddle.arange(logprobs.shape[0]),\n                                    next_tokens]\n        sum_logprobs += current_logprobs * paddle.to_tensor(\n            (tokens[:, -1] != self.eot), dtype=\"float32\")\n\n        next_tokens[tokens[:, -1] == self.eot] = self.eot\n        tokens = paddle.concat([tokens, next_tokens[:, None]], axis=-1)\n\n        completed = paddle.all((tokens[:, -1] == self.eot))\n        return tokens, completed\n\n    def finalize(self, tokens: paddle.Tensor, sum_logprobs: paddle.Tensor):\n        # make sure each sequence has at least one EOT token at the end\n        tokens = F.pad(tokens, (0, 1), value=self.eot, data_format=\"NCL\")\n        return tokens, sum_logprobs.tolist()\n\n\nclass BeamSearchDecoder(TokenDecoder):\n    def __init__(self,\n                 beam_size: int,\n                 eot: int,\n                 inference: Inference,\n                 patience: Optional[float]=None):\n        self.beam_size = beam_size\n        self.eot = eot\n        self.inference = inference\n        self.patience = patience or 1.0\n        self.max_candidates: int = round(beam_size * self.patience)\n        self.finished_sequences = None\n\n        assert self.max_candidates > 0, f\"Invalid beam size ({beam_size}) or patience ({patience})\"\n\n    def reset(self):\n        self.finished_sequences = None\n\n    def update(self,\n               tokens: paddle.Tensor,\n               logits: paddle.Tensor,\n               sum_logprobs: paddle.Tensor) -> Tuple[paddle.Tensor, bool]:\n        if tokens.shape[0] % self.beam_size != 0:\n            raise ValueError(f\"{tokens.shape}[0] % {self.beam_size} != 0\")\n\n        batch_size = tokens.shape[0] // self.beam_size\n        if self.finished_sequences is None:  # for the first update\n            self.finished_sequences = [{} for _ in range(batch_size)]\n\n        logprobs = F.log_softmax(logits, axis=-1, dtype='float32')\n        next_tokens, source_indices, finished_sequences = [], [], []\n        for i in range(batch_size):\n            scores, sources, finished = {}, {}, {}\n\n            # STEP 1: calculate the cumulative log probabilities for possible candidates\n            for j in range(self.beam_size):\n                idx = i * self.beam_size + j\n                prefix = tokens[idx].tolist()\n                logprob, token = paddle.topk(\n                    logprobs[idx], k=self.beam_size + 1)\n                for logprob, token in zip(logprob, token):\n                    # after Paddle 3.0, tolist in 0-D tensor will return a float/int value instead of a list\n                    new_logprob = (sum_logprobs[idx] + logprob).tolist()\n                    new_logprob = new_logprob if isinstance(\n                        new_logprob, float) else new_logprob[0]\n                    new_token = token.tolist()\n                    new_token = new_token if isinstance(new_token,\n                                                        int) else new_token[0]\n                    sequence = tuple(prefix + [new_token])\n                    scores[sequence] = new_logprob\n                    sources[sequence] = idx\n\n            # STEP 2: rank the candidates and keep the top beam_size sequences for each audio\n            saved = 0\n            for sequence in sorted(scores, key=scores.get, reverse=True):\n                if sequence[-1] == self.eot:\n                    finished[sequence] = scores[sequence]\n                else:\n                    sum_logprobs[len(next_tokens)] = scores[sequence]\n                    next_tokens.append(sequence)\n                    source_indices.append(sources[sequence])\n\n                    saved += 1\n                    if saved == self.beam_size:\n                        break\n\n            finished_sequences.append(finished)\n\n        tokens = paddle.to_tensor(next_tokens)\n        self.inference.rearrange_kv_cache(source_indices)\n\n        # add newly finished sequences to self.finished_sequences\n        assert len(self.finished_sequences) == len(finished_sequences)\n        for previously_finished, newly_finished in zip(self.finished_sequences,\n                                                       finished_sequences):\n            for seq in sorted(\n                    newly_finished, key=newly_finished.get, reverse=True):\n                if len(previously_finished) >= self.max_candidates:\n                    break  # the candidate list is full\n                previously_finished[seq] = newly_finished[seq]\n\n        # mark as completed if all audio has enough number of samples\n        completed = all(\n            len(sequences) >= self.max_candidates\n            for sequences in self.finished_sequences)\n        return tokens, completed\n\n    def finalize(self,\n                 preceding_tokens: paddle.Tensor,\n                 sum_logprobs: paddle.Tensor):\n        # collect all finished sequences, including patience, and add unfinished ones if not enough\n        sum_logprobs = sum_logprobs.cpu()\n        for i, sequences in enumerate(self.finished_sequences):\n            if len(sequences\n                   ) < self.beam_size:  # when not enough sequences are finished\n                for j in list(np.argsort(sum_logprobs[i]))[::-1]:\n                    sequence = preceding_tokens[i, j].tolist() + [self.eot]\n                    sequences[tuple(sequence)] = sum_logprobs[i][j].item()\n                    if len(sequences) >= self.beam_size:\n                        break\n\n        tokens: List[List[paddle.Tensor]] = [\n            [paddle.to_tensor(seq) for seq in sequences.keys()]\n            for sequences in self.finished_sequences\n        ]\n        sum_logprobs: List[List[float]] = [\n            list(sequences.values()) for sequences in self.finished_sequences\n        ]\n        return tokens, sum_logprobs\n\n\nclass LogitFilter:\n    def apply(self, logits: paddle.Tensor, tokens: paddle.Tensor) -> None:\n        \"\"\"Apply any filtering or masking to logits in-place\n\n        Parameters\n        ----------\n        logits : Tensor, shape = (n_batch, vocab_size)\n            per-token logits of the probability distribution at the current step\n\n        tokens : Tensor, shape = (n_batch, current_sequence_length)\n            all tokens in the context so far, including the prefix and sot_sequence tokens\n\n        \"\"\"\n        raise NotImplementedError\n\n\nclass SuppressBlank(LogitFilter):\n    def __init__(self, tokenizer: Tokenizer, sample_begin: int):\n        self.tokenizer = tokenizer\n        self.sample_begin = sample_begin\n\n    def apply(self, logits: paddle.Tensor, tokens: paddle.Tensor):\n        if tokens.shape[1] == self.sample_begin:\n            logits.contiguous()\n            logits[:, self.tokenizer.encode(\" \") + [self.tokenizer.eot\n                                                    ]] = -np.inf\n\n\nclass SuppressTokens(LogitFilter):\n    def __init__(self, suppress_tokens: Sequence[int]):\n        self.suppress_tokens = list(suppress_tokens)\n\n    def apply(self, logits: paddle.Tensor, tokens: paddle.Tensor):\n        logits.contiguous()\n        logits[:, self.suppress_tokens] = -np.inf\n\n\nclass ApplyTimestampRules(LogitFilter):\n    def __init__(self,\n                 tokenizer: Tokenizer,\n                 sample_begin: int,\n                 max_initial_timestamp_index: Optional[int]):\n        self.tokenizer = tokenizer\n        self.sample_begin = sample_begin\n        self.max_initial_timestamp_index = max_initial_timestamp_index\n\n    def apply(self, logits: paddle.Tensor, tokens: paddle.Tensor):\n        # suppress <|notimestamps|> which is handled by without_timestamps\n        if self.tokenizer.no_timestamps is not None:\n            logits.contiguous()\n            logits[:, self.tokenizer.no_timestamps] = -np.inf\n\n        # timestamps have to appear in pairs, except directly before EOT; mask logits accordingly\n        for k in range(tokens.shape[0]):\n            seq = [t for t in tokens[k, self.sample_begin:].tolist()]\n            last_was_timestamp = len(seq) >= 1 and seq[\n                -1] >= self.tokenizer.timestamp_begin\n            penultimate_was_timestamp = len(seq) < 2 or seq[\n                -2] >= self.tokenizer.timestamp_begin\n\n            if last_was_timestamp:\n                if penultimate_was_timestamp:  # has to be non-timestamp\n                    logits[k, self.tokenizer.timestamp_begin:] = -np.inf\n                else:  # cannot be normal text tokens\n                    logits[k, :self.tokenizer.eot] = -np.inf\n\n        # apply the `max_initial_timestamp` option\n        if tokens.shape[\n                1] == self.sample_begin and self.max_initial_timestamp_index is not None:\n            last_allowed = self.tokenizer.timestamp_begin + self.max_initial_timestamp_index\n            logits.contiguous()\n            logits[:, last_allowed + 1:] = -np.inf\n\n        # if sum of probability over timestamps is above any other token, sample timestamp\n        logprobs = F.log_softmax(logits, axis=-1, dtype='float32')\n        for k in range(tokens.shape[0]):\n            # When using paddle.logsumexp on a 32GB Tesla-V100 GPU, we encountered CUDA error 700. \n            # To bypass this issue in CI, we have decomposed the operation into separate steps. \n            # It will raise 2e-6 difference in precision.\n            # TODO: revert this after logsumexp been fixed.\n            timestamp_logprob = paddle.exp(\n                logprobs[k, self.tokenizer.timestamp_begin:])\n            timestamp_logprob = paddle.sum(timestamp_logprob, axis=-1)\n            timestamp_logprob = paddle.log(timestamp_logprob)\n            max_text_token_logprob = paddle.max(\n                logprobs[k, :self.tokenizer.timestamp_begin])\n            if timestamp_logprob > max_text_token_logprob:\n                logits[k, :self.tokenizer.timestamp_begin] = -np.inf\n\n\nclass DecodingTask:\n    inference: Inference\n    sequence_ranker: SequenceRanker\n    decoder: TokenDecoder\n    logit_filters: List[LogitFilter]\n\n    def __init__(self,\n                 model: \"Whisper\",\n                 options: DecodingOptions,\n                 resource_path: str):\n        self.model = model\n\n        language = options.language or \"en\"\n        tokenizer = get_tokenizer(\n            multilingual=model.is_multilingual,\n            resource_path=resource_path,\n            language=language,\n            task=options.task,\n            num_languages=model.num_languages)\n        self.tokenizer: Tokenizer = tokenizer\n        self.options: DecodingOptions = self._verify_options(options)\n        self.resource_path: str = resource_path\n\n        self.n_group: int = options.beam_size or options.best_of or 1\n        self.n_ctx: int = model.dims.n_text_ctx\n        self.sample_len: int = options.sample_len or model.dims.n_text_ctx // 2\n\n        self.sot_sequence: Tuple[int] = tokenizer.sot_sequence\n        if self.options.without_timestamps:\n            self.sot_sequence = tokenizer.sot_sequence_including_notimestamps\n\n        self.initial_tokens: Tuple[int] = self._get_initial_tokens()\n        self.sample_begin: int = len(self.initial_tokens)\n        self.sot_index: int = self.initial_tokens.index(tokenizer.sot)\n\n        # inference: implements the forward pass through the decoder, including kv caching\n        self.inference = WhisperInference(model, len(self.initial_tokens))\n\n        # sequence ranker: implements how to rank a group of sampled sequences\n        self.sequence_ranker = MaximumLikelihoodRanker(options.length_penalty)\n\n        # decoder: implements how to select the next tokens, given the autoregressive distribution\n        if options.beam_size is not None:\n            self.decoder = BeamSearchDecoder(options.beam_size, tokenizer.eot,\n                                             self.inference, options.patience)\n        else:\n            self.decoder = GreedyDecoder(options.temperature, tokenizer.eot)\n\n        # logit filters: applies various rules to suppress or penalize certain tokens\n        self.logit_filters = []\n        if self.options.suppress_blank:\n            self.logit_filters.append(\n                SuppressBlank(self.tokenizer, self.sample_begin))\n        if self.options.suppress_tokens:\n            self.logit_filters.append(\n                SuppressTokens(self._get_suppress_tokens()))\n        if not options.without_timestamps:\n            precision = CHUNK_LENGTH / model.dims.n_audio_ctx  # usually 0.02 seconds\n            max_initial_timestamp_index = None\n            if options.max_initial_timestamp:\n                max_initial_timestamp_index = round(\n                    self.options.max_initial_timestamp / precision)\n            self.logit_filters.append(\n                ApplyTimestampRules(tokenizer, self.sample_begin,\n                                    max_initial_timestamp_index))\n\n    def _verify_options(self, options: DecodingOptions) -> DecodingOptions:\n        if options.beam_size is not None and options.best_of is not None:\n            raise ValueError(\"beam_size and best_of can't be given together\")\n        if options.temperature == 0:\n            if options.best_of is not None:\n                raise ValueError(\n                    \"best_of with greedy sampling (T=0) is not compatible\")\n        if options.patience is not None and options.beam_size is None:\n            raise ValueError(\"patience requires beam_size to be given\")\n        if options.length_penalty is not None and not (\n                0 <= options.length_penalty <= 1):\n            raise ValueError(\n                \"length_penalty (alpha) should be a value between 0 and 1\")\n\n        return options\n\n    def _get_initial_tokens(self) -> Tuple[int]:\n        tokens = list(self.sot_sequence)\n        prefix = self.options.prefix\n        prompt = self.options.prompt\n\n        if prefix:\n            prefix_tokens = (\n                self.tokenizer.encode(\" \" + prefix.strip().input_ids)\n                if isinstance(prefix, str) else prefix)\n            if self.sample_len is not None:\n                max_prefix_len = self.n_ctx // 2 - self.sample_len\n                prefix_tokens = prefix_tokens[-max_prefix_len:]\n            tokens = tokens + prefix_tokens\n\n        if prompt:\n            prompt_tokens = (\n                self.tokenizer.encode(\" \" + prompt.strip().input_ids)\n                if isinstance(prompt, str) else prompt)\n            tokens = [self.tokenizer.sot_prev] + prompt_tokens[-(self.n_ctx // 2\n                                                                 - 1):] + tokens\n\n        return tuple(tokens)\n\n    def _get_suppress_tokens(self) -> Tuple[int]:\n        suppress_tokens = self.options.suppress_tokens\n\n        if isinstance(suppress_tokens, str):\n            suppress_tokens = [int(t) for t in suppress_tokens.split(\",\")]\n\n        if -1 in suppress_tokens:\n            suppress_tokens = [t for t in suppress_tokens if t >= 0]\n            suppress_tokens.extend(self.tokenizer.non_speech_tokens)\n        elif suppress_tokens is None or len(suppress_tokens) == 0:\n            suppress_tokens = []  # interpret empty string as an empty list\n        else:\n            assert isinstance(suppress_tokens,\n                              list), \"suppress_tokens must be a list\"\n\n        suppress_tokens.extend([\n            self.tokenizer.sot, self.tokenizer.sot_prev, self.tokenizer.sot_lm\n        ])\n        if self.tokenizer.no_speech is not None:\n            # no-speech probability is collected separately\n            suppress_tokens.append(self.tokenizer.no_speech)\n\n        return tuple(sorted(set(suppress_tokens)))\n\n    def _get_audio_features(self, mel: paddle.Tensor):\n        #if self.options.fp16:\n        #    mel = mel.half()\n\n        if mel.shape[-2:] == (self.model.dims.n_audio_ctx,\n                              self.model.dims.n_audio_state):\n            # encoded audio features are given; skip audio encoding\n            audio_features = mel\n        else:\n            audio_features = self.model.encoder(mel)\n\n        #if audio_features.dtype != (np.float16 if self.options.fp16 else np.float32):\n        #    return TypeError(f\"audio_features has an incorrect dtype: {audio_features.dtype}\")\n\n        return audio_features\n\n    def _detect_language(self,\n                         audio_features: paddle.Tensor,\n                         tokens: paddle.Tensor,\n                         resource_path: str):\n        languages = [self.options.language] * audio_features.shape[0]\n        lang_probs = None\n\n        if self.options.language is None or self.options.task == \"lang_id\":\n            lang_tokens, lang_probs = self.model.detect_language(\n                audio_features, self.tokenizer, self.resource_path)\n            languages = [max(probs, key=probs.get) for probs in lang_probs]\n            if self.options.language is None:\n                tokens[:, self.sot_index +\n                       1] = lang_tokens  # write language tokens\n\n        return languages, lang_probs\n\n    def _main_loop(self, audio_features: paddle.Tensor, tokens: paddle.Tensor):\n        assert audio_features.shape[0] == tokens.shape[0]\n        n_batch = tokens.shape[0]\n        sum_logprobs: paddle.Tensor = paddle.zeros(\n            paddle.to_tensor(n_batch), dtype=paddle.float32)\n        no_speech_probs = [np.nan] * n_batch\n        try:\n            for i in range(self.sample_len):\n                logits = self.inference.logits(tokens, audio_features)\n                logits.contiguous()\n\n                if i == 0 and self.tokenizer.no_speech is not None:  # save no_speech_probs\n                    probs_at_sot = F.softmax(\n                        logits[:, self.sot_index],\n                        axis=-1,\n                        dtype=paddle.float32)\n                    no_speech_probs = probs_at_sot[:, self.tokenizer.\n                                                   no_speech].tolist()\n\n                # now we need to consider the logits at the last token only\n                logits = logits[:, -1]\n\n                # apply the logit filters, e.g. for suppressing or applying penalty to\n                for logit_filter in self.logit_filters:\n                    logit_filter.apply(logits, tokens)\n\n                # expand the tokens tensor with the selected next tokens\n                tokens, completed = self.decoder.update(tokens, logits,\n                                                        sum_logprobs)\n                if completed or tokens.shape[-1] > self.n_ctx:\n                    break\n        finally:\n            self.inference.cleanup_caching()\n\n        return tokens, sum_logprobs, no_speech_probs\n\n    @paddle.no_grad()\n    def run(self, mel: paddle.Tensor) -> List[DecodingResult]:\n        self.decoder.reset()\n        tokenizer: Tokenizer = self.tokenizer\n        batch_size: int = mel.shape[0]\n\n        audio_features: paddle.Tensor = self._get_audio_features(\n            mel)  # encoder forward pass\n\n        tokens: Tensor = paddle.to_tensor([self.initial_tokens]).repeat(\n            batch_size, 1)\n\n        # detect language if requested, overwriting the language token\n        languages, language_probs = self._detect_language(\n            paddle.to_tensor(audio_features),\n            paddle.to_tensor(tokens), self.resource_path)\n\n        if self.options.task == \"lang_id\":\n            return [\n                DecodingResult(\n                    audio_features=features,\n                    language=language,\n                    language_probs=probs)\n                for features, language, probs in zip(audio_features, languages,\n                                                     language_probs)\n            ]\n\n        # repeat text tensors by the group size, for beam search or best-of-n sampling\n        tokens = tokens.repeat_interleave(self.n_group, axis=0)\n\n        # call the main sampling loop\n        tokens, sum_logprobs, no_speech_probs = self._main_loop(audio_features,\n                                                                tokens)\n\n        # reshape the tensors to have (batch_size, n_group) as the first two dimensions\n        audio_features = audio_features[::self.n_group]\n        no_speech_probs = no_speech_probs[::self.n_group]\n        assert audio_features.shape[0] == len(no_speech_probs) == batch_size\n\n        tokens = tokens.reshape([batch_size, self.n_group, -1])\n        sum_logprobs = sum_logprobs.reshape([batch_size, self.n_group])\n\n        # get the final candidates for each group, and slice between the first sampled token and EOT\n        tokens, sum_logprobs = self.decoder.finalize(tokens, sum_logprobs)\n        tokens: List[List[Tensor]] = [[\n            t[self.sample_begin:(t == tokenizer.eot).nonzero()[0, 0]] for t in s\n        ] for s in tokens]\n        # select the top-ranked sample in each group\n        selected = self.sequence_ranker.rank(tokens, sum_logprobs)\n        tokens: List[List[\n            int]] = [t[i].tolist() for i, t in zip(selected, tokens)]\n        texts: List[str] = [tokenizer.decode(t).strip() for t in tokens]\n\n        sum_logprobs: List[\n            float] = [lp[i] for i, lp in zip(selected, sum_logprobs)]\n        avg_logprobs: List[float] = [\n            lp / (len(t) + 1) for t, lp in zip(tokens, sum_logprobs)\n        ]\n\n        fields = (texts, languages, tokens, audio_features, avg_logprobs,\n                  no_speech_probs, )\n        if len(set(map(len, fields))) != 1:\n            raise RuntimeError(\n                f\"inconsistent result lengths: {list(map(len, fields))}\")\n\n        return [\n            DecodingResult(\n                audio_features=features,\n                language=language,\n                tokens=tokens,\n                text=text,\n                avg_logprob=avg_logprob,\n                no_speech_prob=no_speech_prob,\n                temperature=self.options.temperature,\n                compression_ratio=utils.compression_ratio(text), )\n            for text, language, tokens, features, avg_logprob, no_speech_prob in\n            zip(*fields)\n        ]\n\n\n@paddle.no_grad()\ndef decode(\n        model: \"Whisper\",\n        mel: paddle.Tensor,\n        options: DecodingOptions=DecodingOptions(),\n        resource_path=str, ) -> Union[DecodingResult, List[DecodingResult]]:\n    \"\"\"\n    Performs decoding of 30-second audio segment(s), provided as Mel spectrogram(s).\n\n    Parameters\n    ----------\n    model: Whisper\n        the Whisper model instance\n\n    mel: paddle.Tensor, shape = (80, 3000) or (*, 80, 3000) or (128, 3000) or (*, 128, 3000)\n        A tensor containing the Mel spectrogram(s)\n\n    options: DecodingOptions\n        A dataclass that contains all necessary options for decoding 30-second segments\n\n    Returns\n    -------\n    result: Union[DecodingResult, List[DecodingResult]]\n        The result(s) of decoding contained in `DecodingResult` dataclass instance(s)\n    \"\"\"\n    single = mel.ndim == 2\n    if single:\n        mel = mel.unsqueeze(0)\n\n    result = DecodingTask(model, options, resource_path).run(mel)\n\n    if single:\n        result = result[0]\n\n    return result\n\n\nclass Whisper(nn.Layer):\n    def __init__(self, dims: ModelDimensions):\n        super().__init__()\n        self.dims = dims\n        self.encoder = AudioEncoder(\n            self.dims.n_mels,\n            self.dims.n_audio_ctx,\n            self.dims.n_audio_state,\n            self.dims.n_audio_head,\n            self.dims.n_audio_layer, )\n        self.decoder = TextDecoder(\n            self.dims.n_vocab,\n            self.dims.n_text_ctx,\n            self.dims.n_text_state,\n            self.dims.n_text_head,\n            self.dims.n_text_layer, )\n\n    def embed_audio(self, mel: paddle.Tensor):\n        return self.encoder.forward(mel)\n\n    def logits(self, tokens: paddle.Tensor, audio_features: paddle.Tensor):\n        return self.decoder.forward(tokens, audio_features)\n\n    def forward(self, mel: paddle.Tensor,\n                tokens: paddle.Tensor) -> Dict[str, paddle.Tensor]:\n        return self.decoder(tokens, self.encoder(mel))\n\n    @property\n    def device(self):\n        return paddle.device.get_device()\n\n    @property\n    def is_multilingual(self):\n        return self.dims.n_vocab >= 51865\n\n    @property\n    def num_languages(self):\n        return self.dims.n_vocab - 51765 - int(self.is_multilingual)\n\n    def install_kv_cache_hooks(self, cache: Optional[dict]=None):\n        \"\"\"\n        The `MultiHeadAttention` module optionally accepts `kv_cache` which stores the key and value\n        tensors calculated for the previous positions. This method returns a dictionary that stores\n        all caches, and the necessary hooks for the key and value projection modules that save the\n        intermediate tensors to be reused during later calculations.\n\n        Returns\n        -------\n        cache : Dict[nn.Layer, paddle.Tensor]\n            A dictionary object mapping the key/value projection modules to its cache\n        hooks : List[RemovableHandle]\n            List of Paddle RemovableHandle objects to stop the hooks to be called\n        \"\"\"\n        cache = {**cache} if cache is not None else {}\n        hooks = []\n\n        def save_to_cache(module, _, output):\n            if module not in cache or output.shape[\n                    1] > self.decoder.positional_embedding.shape[0]:\n                cache[\n                    module] = output  # save as-is, for the first token or cross attention\n            else:\n                cache[module] = paddle.concat(\n                    [cache[module], output], axis=1).detach()\n            return cache[module]\n\n        def install_hooks(layer: nn.Layer):\n            if isinstance(layer, MultiHeadAttention):\n                hooks.append(\n                    layer.key.register_forward_post_hook(save_to_cache))\n                hooks.append(\n                    layer.value.register_forward_post_hook(save_to_cache))\n\n        self.decoder.apply(install_hooks)\n        return cache, hooks\n\n    detect_language = detect_language\n    transcribe = transcribe\n    decode = decode\n\n\ndef pad_or_trim(array, length: int=N_SAMPLES, *, axis: int=-1):\n    \"\"\"\n    Pad or trim the audio array to N_SAMPLES, as expected by the encoder.\n    \"\"\"\n    if paddle.is_tensor(array):\n        if array.shape[axis] > length:\n            array = array.index_select(axis=axis, index=paddle.arange(length))\n\n        if array.shape[axis] < length:\n            pad_widths = [(0, 0)] * array.ndim\n            pad_widths[axis] = (0, length - array.shape[axis])\n            array = paddle.transpose(array, (1, 0))\n            array = F.pad(\n                array, [pad for sizes in pad_widths[::-1] for pad in sizes],\n                data_format='NLC')\n            array = paddle.transpose(array, (1, 0))\n    else:\n        if array.shape[axis] > length:\n            array = array.take(indices=range(length), axis=axis)\n\n        if array.shape[axis] < length:\n            pad_widths = [(0, 0)] * array.ndim\n            pad_widths[axis] = (0, length - array.shape[axis])\n            array = paddle.transpose(array, (1, 0))\n            array = np.pad(array, pad_widths)\n            array = paddle.transpose(array, (1, 0))\n\n    return array\n\n\ndef hann_window(n_fft: int=N_FFT):\n    \"\"\"\n    hanning window\n    n_fft:  The number of frequency components of the discrete Fourier transform.\n    \"\"\"\n    return paddle.to_tensor(\n        [0.5 - 0.5 * np.cos(2 * np.pi * n / n_fft) for n in range(n_fft)],\n        dtype=\"float32\")\n\n\n@lru_cache(maxsize=None)\ndef mel_filters(resource_path: str, n_mels: int) -> paddle.Tensor:\n    \"\"\"\n    load the mel filterbank matrix for projecting STFT into a Mel spectrogram.\n    Allows decoupling librosa dependency; saved using:\n\n        np.savez_compressed(\n            \"mel_filters.npz\",\n            mel_80=librosa.filters.mel(sr=16000, n_fft=400, n_mels=80),\n        )\n    \"\"\"\n    assert n_mels in {80, 128}, f\"Unsupported n_mels: {n_mels}\"\n\n    filters_path = os.path.join(resource_path, \"assets\", \"mel_filters.npz\")\n    with np.load(filters_path, allow_pickle=False) as f:\n        return paddle.to_tensor(f[f\"mel_{n_mels}\"])\n\n\ndef log_mel_spectrogram(audio: Union[str, np.ndarray, paddle.Tensor],\n                        n_mels: int=80,\n                        padding: int=0,\n                        resource_path: str=None):\n    \"\"\"\n    Compute the log-Mel spectrogram of\n\n    Parameters\n    ----------\n    audio: Union[str, np.ndarray, paddle.Tensor], shape = (*)\n        The path to audio or either a NumPy array or Tensor containing the audio waveform in 16 kHz\n\n    n_mels: int\n        The number of Mel-frequency filters, only 80 and 128 is supported\n\n    Returns\n    -------\n    paddle.Tensor, shape = (n_mels, n_frames)\n        A Tensor that contains the Mel spectrogram\n    \"\"\"\n    if not paddle.is_tensor(audio):\n        if isinstance(audio, str):\n            audio, _ = soundfile.read(audio, dtype=\"float32\", always_2d=True)\n            audio = audio[:, 0]\n            logger.info(f\"audio shape: {audio.shape}\")\n        audio = paddle.to_tensor(audio)\n    if padding > 0:\n        audio = F.pad(audio, (0, padding), data_format=\"NLC\")\n    window = hann_window(N_FFT)\n    stft = paddle.signal.stft(audio, N_FFT, HOP_LENGTH, window=window)\n\n    magnitudes = stft[:, :-1].abs()**2\n\n    filters = mel_filters(resource_path, n_mels)\n    mel_spec = paddle.to_tensor(\n        filters.numpy()\n        @ magnitudes.numpy())  # Use numpy to reduce precision difference\n    mel_spec = paddle.to_tensor(mel_spec.numpy().tolist())\n\n    log_spec = paddle.clip(mel_spec, min=1e-10).log10()\n    log_spec = paddle.maximum(log_spec, log_spec.max() - 8.0)\n    log_spec = (log_spec + 4.0) / 4.0\n    return log_spec\n"
  },
  {
    "path": "paddlespeech/s2t/models/whisper/whisper_LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 OpenAI\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "paddlespeech/s2t/modules/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/modules/activation.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import OrderedDict\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.s2t.modules.align import Conv2D\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"get_activation\", \"brelu\", \"LinearGLUBlock\", \"ConvGLUBlock\", \"GLU\"]\n\n\ndef brelu(x, t_min=0.0, t_max=24.0, name=None):\n    # paddle.to_tensor is dygraph_only can not work under JIT\n    t_min = paddle.full(shape=[1], fill_value=t_min, dtype='float32')\n    t_max = paddle.full(shape=[1], fill_value=t_max, dtype='float32')\n    return x.maximum(t_min).minimum(t_max)\n\n\nclass GLU(nn.Layer):\n    \"\"\"Gated Linear Units (GLU) Layer\"\"\"\n\n    def __init__(self, dim: int=-1):\n        super().__init__()\n        self.dim = dim\n\n    def forward(self, xs):\n        return F.glu(xs, axis=self.dim)\n\n\nclass LinearGLUBlock(nn.Layer):\n    \"\"\"A linear Gated Linear Units (GLU) block.\"\"\"\n\n    def __init__(self, idim: int):\n        \"\"\" GLU.\n        Args:\n            idim (int): input and output dimension\n        \"\"\"\n        super().__init__()\n        self.fc = Linear(idim, idim * 2)\n\n    def forward(self, xs):\n        return glu(self.fc(xs), dim=-1)\n\n\nclass ConvGLUBlock(nn.Layer):\n    def __init__(self, kernel_size, in_ch, out_ch, bottlececk_dim=0,\n                 dropout=0.):\n        \"\"\"A convolutional Gated Linear Units (GLU) block.\n\n        Args:\n            kernel_size (int): kernel size\n            in_ch (int): number of input channels\n            out_ch (int): number of output channels\n            bottlececk_dim (int): dimension of the bottleneck layers for computational efficiency. Defaults to 0.\n            dropout (float): dropout probability. Defaults to 0..\n        \"\"\"\n\n        super().__init__()\n\n        self.conv_residual = None\n        if in_ch != out_ch:\n            self.conv_residual = nn.utils.weight_norm(\n                Conv2D(\n                    in_channels=in_ch, out_channels=out_ch, kernel_size=(1, 1)),\n                name='weight',\n                dim=0)\n            self.dropout_residual = nn.Dropout(p=dropout)\n\n        self.pad_left = nn.Pad2d((0, 0, kernel_size - 1, 0), 0)\n\n        layers = OrderedDict()\n        if bottlececk_dim == 0:\n            layers['conv'] = nn.utils.weight_norm(\n                Conv2D(\n                    in_channels=in_ch,\n                    out_channels=out_ch * 2,\n                    kernel_size=(kernel_size, 1)),\n                name='weight',\n                dim=0)\n            # TODO(hirofumi0810): padding?\n            layers['dropout'] = nn.Dropout(p=dropout)\n            layers['glu'] = GLU()\n\n        elif bottlececk_dim > 0:\n            layers['conv_in'] = nn.utils.weight_norm(\n                nn.Conv2D(\n                    in_channels=in_ch,\n                    out_channels=bottlececk_dim,\n                    kernel_size=(1, 1)),\n                name='weight',\n                dim=0)\n            layers['dropout_in'] = nn.Dropout(p=dropout)\n            layers['conv_bottleneck'] = nn.utils.weight_norm(\n                Conv2D(\n                    in_channels=bottlececk_dim,\n                    out_channels=bottlececk_dim,\n                    kernel_size=(kernel_size, 1)),\n                name='weight',\n                dim=0)\n            layers['dropout'] = nn.Dropout(p=dropout)\n            layers['glu'] = GLU()\n            layers['conv_out'] = nn.utils.weight_norm(\n                Conv2D(\n                    in_channels=bottlececk_dim,\n                    out_channels=out_ch * 2,\n                    kernel_size=(1, 1)),\n                name='weight',\n                dim=0)\n            layers['dropout_out'] = nn.Dropout(p=dropout)\n\n        self.layers = nn.Sequential(layers)\n\n    def forward(self, xs):\n        \"\"\"Forward pass.\n        Args:\n            xs (FloatTensor): `[B, in_ch, T, feat_dim]`\n        Returns:\n            out (FloatTensor): `[B, out_ch, T, feat_dim]`\n        \"\"\"\n        residual = xs\n        if self.conv_residual is not None:\n            residual = self.dropout_residual(self.conv_residual(residual))\n        xs = self.pad_left(xs)  # `[B, embed_dim, T+kernel-1, 1]`\n        xs = self.layers(xs)  # `[B, out_ch * 2, T ,1]`\n        xs = xs + residual\n        return xs\n\n\ndef get_activation(act):\n    \"\"\"Return activation function.\"\"\"\n    # Lazy load to avoid unused import\n    activation_funcs = {\n        \"hardshrink\": paddle.nn.Hardshrink,\n        \"hardswish\": paddle.nn.Hardswish,\n        \"hardtanh\": paddle.nn.Hardtanh,\n        \"tanh\": paddle.nn.Tanh,\n        \"relu\": paddle.nn.ReLU,\n        \"relu6\": paddle.nn.ReLU6,\n        \"leakyrelu\": paddle.nn.LeakyReLU,\n        \"selu\": paddle.nn.SELU,\n        \"swish\": paddle.nn.Swish,\n        \"gelu\": paddle.nn.GELU,\n        \"glu\": GLU,\n        \"elu\": paddle.nn.ELU,\n    }\n\n    return activation_funcs[act]()\n"
  },
  {
    "path": "paddlespeech/s2t/modules/align.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport paddle\nfrom paddle import nn\n\"\"\"\n    To align the initializer between paddle and torch, \n    the API below are set default initializer with priority higger than global initializer.\n\"\"\"\nglobal_init_type = None\n\n\nclass LayerNorm(nn.LayerNorm):\n    def __init__(self,\n                 normalized_shape,\n                 epsilon=1e-05,\n                 weight_attr=None,\n                 bias_attr=None,\n                 name=None):\n        if weight_attr is None:\n            weight_attr = paddle.ParamAttr(\n                initializer=nn.initializer.Constant(1.0))\n        if bias_attr is None:\n            bias_attr = paddle.ParamAttr(\n                initializer=nn.initializer.Constant(0.0))\n        super(LayerNorm, self).__init__(\n            normalized_shape=normalized_shape,\n            epsilon=epsilon,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            name=name)\n\n\nclass BatchNorm1D(nn.BatchNorm1D):\n    def __init__(self,\n                 num_features,\n                 momentum=0.9,\n                 epsilon=1e-05,\n                 weight_attr=None,\n                 bias_attr=None,\n                 data_format='NCL',\n                 name=None):\n        if weight_attr is None:\n            weight_attr = paddle.ParamAttr(\n                initializer=nn.initializer.Constant(1.0))\n        if bias_attr is None:\n            bias_attr = paddle.ParamAttr(\n                initializer=nn.initializer.Constant(0.0))\n        super(BatchNorm1D, self).__init__(\n            num_features=num_features,\n            momentum=momentum,\n            epsilon=epsilon,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format,\n            name=name)\n\n\nclass Embedding(nn.Embedding):\n    def __init__(self,\n                 num_embeddings,\n                 embedding_dim,\n                 padding_idx=None,\n                 sparse=False,\n                 weight_attr=None,\n                 name=None):\n        if weight_attr is None:\n            weight_attr = paddle.ParamAttr(initializer=nn.initializer.Normal())\n        super(Embedding, self).__init__(\n            num_embeddings=num_embeddings,\n            embedding_dim=embedding_dim,\n            padding_idx=padding_idx,\n            sparse=sparse,\n            weight_attr=weight_attr,\n            name=name)\n\n\nclass Linear(nn.Linear):\n    def __init__(self,\n                 in_features,\n                 out_features,\n                 weight_attr=None,\n                 bias_attr=None,\n                 name=None):\n        if weight_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                weight_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        if bias_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                bias_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        super(Linear, self).__init__(\n            in_features=in_features,\n            out_features=out_features,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            name=name)\n\n\nclass Conv1D(nn.Conv1D):\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 kernel_size,\n                 stride=1,\n                 padding=0,\n                 dilation=1,\n                 groups=1,\n                 padding_mode='zeros',\n                 weight_attr=None,\n                 bias_attr=None,\n                 data_format='NCL'):\n        if weight_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                weight_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        if bias_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                bias_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        super(Conv1D, self).__init__(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=padding,\n            dilation=dilation,\n            groups=groups,\n            padding_mode=padding_mode,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format)\n\n\nclass Conv2D(nn.Conv2D):\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 kernel_size,\n                 stride=1,\n                 padding=0,\n                 dilation=1,\n                 groups=1,\n                 padding_mode='zeros',\n                 weight_attr=None,\n                 bias_attr=None,\n                 data_format='NCHW'):\n        if weight_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                weight_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        if bias_attr is None:\n            if global_init_type == \"kaiming_uniform\":\n                bias_attr = paddle.ParamAttr(\n                    initializer=nn.initializer.KaimingUniform(\n                        fan_in=None,\n                        negative_slope=math.sqrt(5),\n                        nonlinearity='leaky_relu'))\n        super(Conv2D, self).__init__(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=padding,\n            dilation=dilation,\n            groups=groups,\n            padding_mode=padding_mode,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format)\n"
  },
  {
    "path": "paddlespeech/s2t/modules/attention.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Multi-Head Attention layer definition.\"\"\"\nimport math\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import initializer as I\n\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"MultiHeadedAttention\", \"RelPositionMultiHeadedAttention\",\n    \"RoPERelPositionMultiHeadedAttention\"\n]\n\n# Relative Positional Encodings\n# https://www.jianshu.com/p/c0608efcc26f\n# https://zhuanlan.zhihu.com/p/344604604\n\n\nclass MultiHeadedAttention(nn.Layer):\n    \"\"\"Multi-Head Attention layer.\"\"\"\n\n    def __init__(self, n_head: int, n_feat: int, dropout_rate: float):\n        \"\"\"Construct an MultiHeadedAttention object.\n        Args:\n            n_head (int): The number of heads.\n            n_feat (int): The number of features.\n            dropout_rate (float): Dropout rate.\n        \"\"\"\n        super().__init__()\n        assert n_feat % n_head == 0\n        self.n_feat = n_feat\n        # We assume d_v always equals d_k\n        self.d_k = n_feat // n_head\n        self.h = n_head\n        self.linear_q = Linear(n_feat, n_feat)\n        self.linear_k = Linear(n_feat, n_feat)\n        self.linear_v = Linear(n_feat, n_feat)\n        self.linear_out = Linear(n_feat, n_feat)\n        self.dropout = nn.Dropout(p=dropout_rate)\n\n    def forward_qkv(self,\n                    query: paddle.Tensor,\n                    key: paddle.Tensor,\n                    value: paddle.Tensor\n                    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Transform query, key and value.\n        Args:\n            query (paddle.Tensor): Query tensor (#batch, time1, size).\n            key (paddle.Tensor): Key tensor (#batch, time2, size).\n            value (paddle.Tensor): Value tensor (#batch, time2, size).\n        Returns:\n            paddle.Tensor: Transformed query tensor, size\n                (#batch, n_head, time1, d_k).\n            paddle.Tensor: Transformed key tensor, size\n                (#batch, n_head, time2, d_k).\n            paddle.Tensor: Transformed value tensor, size\n                (#batch, n_head, time2, d_k).\n        \"\"\"\n        n_batch = query.shape[0]\n\n        q = self.linear_q(query).reshape([n_batch, -1, self.h, self.d_k])\n        k = self.linear_k(key).reshape([n_batch, -1, self.h, self.d_k])\n        v = self.linear_v(value).reshape([n_batch, -1, self.h, self.d_k])\n\n        q = q.transpose([0, 2, 1, 3])  # (batch, head, time1, d_k)\n        k = k.transpose([0, 2, 1, 3])  # (batch, head, time2, d_k)\n        v = v.transpose([0, 2, 1, 3])  # (batch, head, time2, d_k)\n\n        return q, k, v\n\n    def forward_attention(\n            self,\n            value: paddle.Tensor,\n            scores: paddle.Tensor,\n            mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool)\n    ) -> paddle.Tensor:\n        \"\"\"Compute attention context vector.\n        Args:\n            value (paddle.Tensor): Transformed value, size\n                (#batch, n_head, time2, d_k).\n            scores (paddle.Tensor): Attention score, size\n                (#batch, n_head, time1, time2).\n            mask (paddle.Tensor): Mask, size (#batch, 1, time2) or\n                (#batch, time1, time2), (0, 0, 0) means fake mask.\n        Returns:\n            paddle.Tensor: Transformed value (#batch, time1, d_model)\n                weighted by the attention score (#batch, time1, time2).\n        \"\"\"\n        n_batch = value.shape[0]\n\n        # When `if mask.size(2) > 0` be True:\n        # 1. training.\n        # 2. oonx(16/4, chunk_size/history_size), feed real cache and real mask for the 1st chunk.\n        # When will `if mask.size(2) > 0` be False?\n        # 1. onnx(16/-1, -1/-1, 16/0)\n        # 2. jit (16/-1, -1/-1, 16/0, 16/4)\n        if mask.shape[2] > 0:  # time2 > 0\n            mask = mask.unsqueeze(1).equal(0)  # (batch, 1, *, time2)\n            # for last chunk, time2 might be larger than scores.size(-1)\n            mask = mask[:, :, :, :scores.shape[-1]]\n            scores = scores.masked_fill(mask, -float('inf'))\n            attn = paddle.nn.functional.softmax(\n                scores, axis=-1).masked_fill(mask,\n                                             0.0)  # (batch, head, time1, time2)\n        else:\n            attn = paddle.nn.functional.softmax(\n                scores, axis=-1)  # (batch, head, time1, time2)\n\n        p_attn = self.dropout(attn)\n        x = paddle.matmul(p_attn, value)  # (batch, head, time1, d_k)\n        x = x.transpose([0, 2, 1, 3]).reshape(\n            [n_batch, -1, self.h * self.d_k])  # (batch, time1, d_model)\n\n        return self.linear_out(x)  # (batch, time1, d_model)\n\n    def forward(self,\n                query: paddle.Tensor,\n                key: paddle.Tensor,\n                value: paddle.Tensor,\n                mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n                pos_emb: paddle.Tensor=paddle.empty([0]),\n                cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n                ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute scaled dot product attention.\n       Args:\n            query (paddle.Tensor): Query tensor (#batch, time1, size).\n            key (paddle.Tensor): Key tensor (#batch, time2, size).\n            value (paddle.Tensor): Value tensor (#batch, time2, size).\n            mask (paddle.Tensor): Mask tensor (#batch, 1, time2) or\n                (#batch, time1, time2).\n                1.When applying cross attention between decoder and encoder,\n                the batch padding mask for input is in (#batch, 1, T) shape.\n                2.When applying self attention of encoder,\n                the mask is in (#batch, T, T)  shape.\n                3.When applying self attention of decoder,\n                the mask is in (#batch, L, L)  shape.\n                4.If the different position in decoder see different block\n                of the encoder, such as Mocha, the passed in mask could be\n                in (#batch, L, T) shape. But there is no such case in current\n                Wenet.\n            cache (paddle.Tensor): Cache tensor (1, head, cache_t, d_k * 2),\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n        Returns:\n            paddle.Tensor: Output tensor (#batch, time1, d_model).\n            paddle.Tensor: Cache tensor (1, head, cache_t + time1, d_k * 2)\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n\n        \"\"\"\n        # (B,T,D) -> (B,T,H,D/H)\n        q, k, v = self.forward_qkv(query, key, value)\n\n        #   when export onnx model, for 1st chunk, we feed\n        #       cache(1, head, 0, d_k * 2) (16/-1, -1/-1, 16/0 mode)\n        #       or cache(1, head, real_cache_t, d_k * 2) (16/4 mode).\n        #       In all modes, `if cache.size(0) > 0` will alwayse be `True`\n        #       and we will always do splitting and\n        #       concatnation(this will simplify onnx export). Note that\n        #       it's OK to concat & split zero-shaped tensors(see code below).\n        #   when export jit  model, for 1st chunk, we always feed\n        #       cache(0, 0, 0, 0) since jit supports dynamic if-branch.\n        # >>> a = torch.ones((1, 2, 0, 4))\n        # >>> b = torch.ones((1, 2, 3, 4))\n        # >>> c = torch.cat((a, b), dim=2)\n        # >>> torch.equal(b, c)        # True\n        # >>> d = torch.split(a, 2, dim=-1)\n        # >>> torch.equal(d[0], d[1])  # True\n        if cache.shape[0] > 0:\n            # last dim `d_k * 2` for (key, val)\n            key_cache, value_cache = paddle.split(cache, 2, axis=-1)\n            k = paddle.concat([key_cache, k], axis=2)\n            v = paddle.concat([value_cache, v], axis=2)\n        # We do cache slicing in encoder.forward_chunk, since it's\n        #   non-trivial to calculate `next_cache_start` here.\n        new_cache = paddle.concat((k, v), axis=-1)\n\n        # scores = paddle.matmul(q,\n        #    k.transpose([0, 1, 3, 2])) / math.sqrt(self.d_k)\n        scores = paddle.matmul(q, k, transpose_y=True) / math.sqrt(self.d_k)\n        return self.forward_attention(v, scores, mask), new_cache\n\n\nclass RelPositionMultiHeadedAttention(MultiHeadedAttention):\n    \"\"\"Multi-Head Attention layer with relative position encoding.\"\"\"\n\n    def __init__(self,\n                 n_head,\n                 n_feat,\n                 dropout_rate,\n                 adaptive_scale=False,\n                 init_weights=False):\n        \"\"\"Construct an RelPositionMultiHeadedAttention object.\n        Paper: https://arxiv.org/abs/1901.02860\n        Args:\n            n_head (int): The number of heads.\n            n_feat (int): The number of features.\n            dropout_rate (float): Dropout rate.\n        \"\"\"\n        super().__init__(n_head, n_feat, dropout_rate)\n        # linear transformation for positional encoding\n        self.linear_pos = Linear(n_feat, n_feat, bias_attr=False)\n        # these two learnable bias are used in matrix c and matrix d\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n        #self.pos_bias_u = nn.Parameter(torch.Tensor(self.h, self.d_k))\n        #self.pos_bias_v = nn.Parameter(torch.Tensor(self.h, self.d_k))\n        #torch.nn.init.xavier_uniform_(self.pos_bias_u)\n        #torch.nn.init.xavier_uniform_(self.pos_bias_v)\n        pos_bias_u = self.create_parameter(\n            [self.h, self.d_k], default_initializer=I.XavierUniform())\n        self.add_parameter('pos_bias_u', pos_bias_u)\n        pos_bias_v = self.create_parameter(\n            (self.h, self.d_k), default_initializer=I.XavierUniform())\n        self.add_parameter('pos_bias_v', pos_bias_v)\n        self.adaptive_scale = adaptive_scale\n        if self.adaptive_scale:\n            ada_scale = self.create_parameter(\n                [1, 1, n_feat], default_initializer=I.Constant(1.0))\n            self.add_parameter('ada_scale', ada_scale)\n            ada_bias = self.create_parameter(\n                [1, 1, n_feat], default_initializer=I.Constant(0.0))\n            self.add_parameter('ada_bias', ada_bias)\n        if init_weights:\n            self.init_weights()\n\n    def init_weights(self):\n        input_max = (self.h * self.d_k)**-0.5\n        self.linear_q._param_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_q._bias_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_k._param_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_k._bias_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_v._param_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_v._bias_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_pos._param_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_pos._bias_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_out._param_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n        self.linear_out._bias_attr = paddle.nn.initializer.Uniform(\n            low=-input_max, high=input_max)\n\n    def rel_shift(self, x, zero_triu: bool=False):\n        \"\"\"Compute relative positinal encoding.\n        Args:\n            x (paddle.Tensor): Input tensor (batch, head, time1, time1).\n            zero_triu (bool): If true, return the lower triangular part of\n                the matrix.\n        Returns:\n            paddle.Tensor: Output tensor. (batch, head, time1, time1)\n        \"\"\"\n        zero_pad = paddle.zeros(\n            (x.shape[0], x.shape[1], x.shape[2], 1), dtype=x.dtype)\n        x_padded = paddle.cat([zero_pad, x], dim=-1)\n\n        x_padded = x_padded.reshape(\n            [x.shape[0], x.shape[1], x.shape[3] + 1, x.shape[2]])\n        x = x_padded[:, :, 1:].view_as(x)  # [B, H, T1, T1]\n\n        if zero_triu:\n            ones = paddle.ones((x.shape[2], x.shape[3]))\n            x = x * paddle.tril(ones, x.shape[3] - x.shape[2])[None, None, :, :]\n\n        return x\n\n    def forward(self,\n                query: paddle.Tensor,\n                key: paddle.Tensor,\n                value: paddle.Tensor,\n                mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n                pos_emb: paddle.Tensor=paddle.empty([0]),\n                cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n                ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute 'Scaled Dot Product Attention' with rel. positional encoding.\n        Args:\n            query (paddle.Tensor): Query tensor (#batch, time1, size).\n            key (paddle.Tensor): Key tensor (#batch, time2, size).\n            value (paddle.Tensor): Value tensor (#batch, time2, size).\n            mask (paddle.Tensor): Mask tensor (#batch, 1, time2) or\n                (#batch, time1, time2), (0, 0, 0) means fake mask.\n            pos_emb (paddle.Tensor): Positional embedding tensor\n                (#batch, time2, size).\n            cache (paddle.Tensor): Cache tensor (1, head, cache_t, d_k * 2),\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n        Returns:\n            paddle.Tensor: Output tensor (#batch, time1, d_model).\n            paddle.Tensor: Cache tensor (1, head, cache_t + time1, d_k * 2)\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n        \"\"\"\n        if self.adaptive_scale:\n            query = self.ada_scale * query + self.ada_bias\n            key = self.ada_scale * key + self.ada_bias\n            value = self.ada_scale * value + self.ada_bias\n\n        q, k, v = self.forward_qkv(query, key, value)\n        # q = q.transpose([0, 2, 1, 3])  # (batch, time1, head, d_k)\n\n        #   when export onnx model, for 1st chunk, we feed\n        #       cache(1, head, 0, d_k * 2) (16/-1, -1/-1, 16/0 mode)\n        #       or cache(1, head, real_cache_t, d_k * 2) (16/4 mode).\n        #       In all modes, `if cache.size(0) > 0` will alwayse be `True`\n        #       and we will always do splitting and\n        #       concatnation(this will simplify onnx export). Note that\n        #       it's OK to concat & split zero-shaped tensors(see code below).\n        #   when export jit  model, for 1st chunk, we always feed\n        #       cache(0, 0, 0, 0) since jit supports dynamic if-branch.\n        # >>> a = torch.ones((1, 2, 0, 4))\n        # >>> b = torch.ones((1, 2, 3, 4))\n        # >>> c = torch.cat((a, b), dim=2)\n        # >>> torch.equal(b, c)        # True\n        # >>> d = torch.split(a, 2, dim=-1)\n        # >>> torch.equal(d[0], d[1])  # True\n        if cache.shape[0] > 0:\n            # last dim `d_k * 2` for (key, val)\n            key_cache, value_cache = paddle.split(cache, 2, axis=-1)\n            k = paddle.concat([key_cache, k], axis=2)\n            v = paddle.concat([value_cache, v], axis=2)\n        # We do cache slicing in encoder.forward_chunk, since it's\n        #   non-trivial to calculate `next_cache_start` here.\n        new_cache = paddle.concat((k, v), axis=-1)\n\n        n_batch_pos = pos_emb.shape[0]\n        p = self.linear_pos(pos_emb).reshape(\n            [n_batch_pos, -1, self.h, self.d_k])\n        p = p.transpose([0, 2, 1, 3])  # (batch, head, time1, d_k)\n\n        # (batch, head, time1, d_k)\n        # q_with_bias_u = (q + self.pos_bias_u).transpose([0, 2, 1, 3])\n        q_with_bias_u = q + self.pos_bias_u.unsqueeze(1)\n        # (batch, head, time1, d_k)\n        # q_with_bias_v = (q + self.pos_bias_v).transpose([0, 2, 1, 3])\n        q_with_bias_v = q + self.pos_bias_v.unsqueeze(1)\n\n        # compute attention score\n        # first compute matrix a and matrix c\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n        # (batch, head, time1, time2)\n        # matrix_ac = paddle.matmul(q_with_bias_u, k.transpose([0, 1, 3, 2]))\n        matrix_ac = paddle.matmul(q_with_bias_u, k, transpose_y=True)\n\n        # compute matrix b and matrix d\n        # (batch, head, time1, time2)\n        # matrix_bd = paddle.matmul(q_with_bias_v, p.transpose([0, 1, 3, 2]))\n        matrix_bd = paddle.matmul(q_with_bias_v, p, transpose_y=True)\n        # Remove rel_shift since it is useless in speech recognition,\n        # and it requires special attention for streaming.\n        # matrix_bd = self.rel_shift(matrix_bd)\n\n        scores = (matrix_ac + matrix_bd) / math.sqrt(\n            self.d_k)  # (batch, head, time1, time2)\n\n        return self.forward_attention(v, scores, mask), new_cache\n\n\nclass RoPERelPositionMultiHeadedAttention(MultiHeadedAttention):\n    \"\"\"Multi-Head Attention layer with RoPE relative position encoding.\"\"\"\n\n    def __init__(self,\n                 n_head,\n                 n_feat,\n                 dropout_rate,\n                 adaptive_scale=False,\n                 init_weights=False):\n        \"\"\"Construct an RelPositionMultiHeadedAttention object.\n        Paper: https://arxiv.org/abs/1901.02860\n        Args:\n            n_head (int): The number of heads.\n            n_feat (int): The number of features.\n            dropout_rate (float): Dropout rate.\n        \"\"\"\n        super().__init__(n_head, n_feat, dropout_rate)\n\n    def align(self, tensor: paddle.Tensor, axes: List[int], ndim=None):\n        \"\"\"重新对齐tensor（批量版expand_dims）\n        axes：原来的第i维对齐新tensor的第axes[i]维；\n        ndim：新tensor的维度。\n        \"\"\"\n        assert len(axes) == tensor.dim()\n        assert ndim or min(axes) >= 0\n\n        ndim = ndim or max(axes) + 1\n\n        # a[0, None, 1] = a[0, np.newaxis, 1]\n        indices = [None] * ndim\n        for i in axes:\n            # slice nothing, a[0, slice(None), 1] = a[0, :, 1]\n            indices[i] = slice(None)\n\n        return tensor[indices]\n\n    def apply_rotary_position_embeddings(self, sinusoidal, *tensors):\n        \"\"\"应用RoPE到tensors中\n        其中，sinusoidal.shape=[B, T, D]，tensors为tensor的列表，而\n        tensor.shape=[B, T, ..., D], or (B,H,T,D/H)\n        \"\"\"\n        assert len(tensors) > 0, 'at least one input tensor'\n        assert all(\n            [tensor.shape == tensors[0].shape\n             for tensor in tensors[1:]]), 'all tensors must have the same shape'\n\n        # (B,H,T,D)\n        ndim = tensors[0].dim()\n        _, H, T, D = tensors[0].shape\n\n        # sinusoidal shape same with tensors[0]\n        # [B,T,D] -> [B,T,H,D/H] -> (B,H,T,D/H)\n        # sinusoidal = self.align(sinusoidal, [0, 1, -1], ndim)\n        sinusoidal = sinusoidal.reshape((1, T, H, D)).transpose([0, 2, 1, 3])\n\n        # http://man.hubwiz.com/docset/TensorFlow.docset/Contents/Resources/Documents/api_docs/python/tf/keras/backend/repeat_elements.html\n        # like np.repeat, x (s1, s2, s3), axis 1, (s1, s2*rep, s3)\n        # [b,T, ..., d/2] -> [b,T, ..., d]\n        cos_pos = paddle.repeat_interleave(sinusoidal[..., 1::2], 2, axis=-1)\n        sin_pos = paddle.repeat_interleave(sinusoidal[..., 0::2], 2, axis=-1)\n        outputs = []\n        for tensor in tensors:\n            # x2 = [-x2, x1, -x4, x3, ..., -x_d, x_{d-1}]\n            tensor2 = paddle.stack([-tensor[..., 1::2], tensor[..., ::2]], ndim)\n            tensor2 = paddle.reshape(tensor2, paddle.shape(tensor))\n\n            # 公式 34, out = x * cos_pos + x2 * sin_pos\n            outputs.append(tensor * cos_pos + tensor2 * sin_pos)\n        return outputs[0] if len(outputs) == 1 else outputs\n\n    def forward(self,\n                query: paddle.Tensor,\n                key: paddle.Tensor,\n                value: paddle.Tensor,\n                mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n                pos_emb: paddle.Tensor=paddle.empty([0]),\n                cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n                ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute 'Scaled Dot Product Attention' with rel. positional encoding.\n        Ref: https://github.com/facebookresearch/llama/blob/main/llama/model.py\n        Args:\n            query (paddle.Tensor): Query tensor (#batch, time1, size).\n            key (paddle.Tensor): Key tensor (#batch, time2, size).\n            value (paddle.Tensor): Value tensor (#batch, time2, size).\n            mask (paddle.Tensor): Mask tensor (#batch, 1, time2) or\n                (#batch, time1, time2), (0, 0, 0) means fake mask.\n            pos_emb (paddle.Tensor): Positional embedding tensor\n                (#batch, time2, size).\n            cache (paddle.Tensor): Cache tensor (1, head, cache_t, d_k * 2),\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n        Returns:\n            paddle.Tensor: Output tensor (#batch, time1, d_model).\n            paddle.Tensor: Cache tensor (1, head, cache_t + time1, d_k * 2)\n                where `cache_t == chunk_size * num_decoding_left_chunks`\n                and `head * d_k == size`\n        \"\"\"\n        q, k, v = self.forward_qkv(query, key, value)\n        # q = q.transpose([0, 2, 1, 3])  # (batch, time1, head, d_k)\n\n        # f{q,k}(x_m, m) = R^d_{\\theta, m} W_{q,k} x_m, m is position index\n        # q_t always is chunk_size\n        q_t = q.shape[2]\n        q = self.apply_rotary_position_embeddings(pos_emb[:, -q_t:, :], q)\n        # k will increase when in streaming decoding.\n        k = self.apply_rotary_position_embeddings(pos_emb[:, -q_t:, :], k)\n\n        #   when export onnx model, for 1st chunk, we feed\n        #       cache(1, head, 0, d_k * 2) (16/-1, -1/-1, 16/0 mode)\n        #       or cache(1, head, real_cache_t, d_k * 2) (16/4 mode).\n        #       In all modes, `if cache.size(0) > 0` will alwayse be `True`\n        #       and we will always do splitting and\n        #       concatnation(this will simplify onnx export). Note that\n        #       it's OK to concat & split zero-shaped tensors(see code below).\n        #   when export jit  model, for 1st chunk, we always feed\n        #       cache(0, 0, 0, 0) since jit supports dynamic if-branch.\n        # >>> a = torch.ones((1, 2, 0, 4))\n        # >>> b = torch.ones((1, 2, 3, 4))\n        # >>> c = torch.cat((a, b), dim=2)\n        # >>> torch.equal(b, c)        # True\n        # >>> d = torch.split(a, 2, dim=-1)\n        # >>> torch.equal(d[0], d[1])  # True\n        if cache.shape[0] > 0:\n            # last dim `d_k * 2` for (key, val)\n            key_cache, value_cache = paddle.split(cache, 2, axis=-1)\n            k = paddle.concat([key_cache, k], axis=2)\n            v = paddle.concat([value_cache, v], axis=2)\n        # We do cache slicing in encoder.forward_chunk, since it's\n        #   non-trivial to calculate `next_cache_start` here.\n        new_cache = paddle.concat((k, v), axis=-1)\n\n        # dot(q, k)\n        scores = paddle.matmul(q, k, transpose_y=True) / math.sqrt(self.d_k)\n        return self.forward_attention(v, scores, mask), new_cache\n"
  },
  {
    "path": "paddlespeech/s2t/modules/cmvn.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = ['GlobalCMVN']\n\n\nclass GlobalCMVN(nn.Layer):\n    def __init__(self,\n                 mean: paddle.Tensor,\n                 istd: paddle.Tensor,\n                 norm_var: bool=True):\n        \"\"\"\n        Args:\n            mean (paddle.Tensor): mean stats\n            istd (paddle.Tensor): inverse std, std which is 1.0 / std\n        \"\"\"\n        super().__init__()\n        assert mean.shape == istd.shape\n        self.norm_var = norm_var\n        # The buffer can be accessed from this module using self.mean\n        self.register_buffer(\"mean\", mean)\n        self.register_buffer(\"istd\", istd)\n\n    def __repr__(self):\n        return (\"{name}(mean={mean}, istd={istd}, norm_var={norm_var})\".format(\n            name=self.__class__.__name__,\n            mean=self.mean,\n            istd=self.istd,\n            norm_var=self.norm_var))\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"\n        Args:\n            x (paddle.Tensor): (batch, max_len, feat_dim)\n        Returns:\n            (paddle.Tensor): normalized feature\n        \"\"\"\n        x = x - self.mean\n        if self.norm_var:\n            x = x * self.istd\n        return x\n"
  },
  {
    "path": "paddlespeech/s2t/modules/conformer_convolution.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"ConvolutionModule definition.\"\"\"\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import initializer as I\nfrom typeguard import typechecked\n\nfrom paddlespeech.s2t.modules.align import BatchNorm1D\nfrom paddlespeech.s2t.modules.align import Conv1D\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = ['ConvolutionModule']\n\n\nclass ConvolutionModule(nn.Layer):\n    \"\"\"ConvolutionModule in Conformer model.\"\"\"\n\n    @typechecked\n    def __init__(self,\n                 channels: int,\n                 kernel_size: int=15,\n                 activation: nn.Layer=nn.ReLU(),\n                 norm: str=\"batch_norm\",\n                 causal: bool=False,\n                 bias: bool=True,\n                 adaptive_scale: bool=False,\n                 init_weights: bool=False):\n        \"\"\"Construct an ConvolutionModule object.\n        Args:\n            channels (int): The number of channels of conv layers.\n            kernel_size (int): Kernel size of conv layers.\n            activation (nn.Layer): Activation Layer.\n            norm (str): Normalization type, 'batch_norm' or 'layer_norm'\n            causal (bool): Whether use causal convolution or not\n            bias (bool): Whether Conv with bias or not\n        \"\"\"\n        super().__init__()\n        self.bias = bias\n        self.channels = channels\n        self.kernel_size = kernel_size\n        self.adaptive_scale = adaptive_scale\n        if self.adaptive_scale:\n            ada_scale = self.create_parameter(\n                [1, 1, channels], default_initializer=I.Constant(1.0))\n            self.add_parameter('ada_scale', ada_scale)\n            ada_bias = self.create_parameter(\n                [1, 1, channels], default_initializer=I.Constant(0.0))\n            self.add_parameter('ada_bias', ada_bias)\n\n        self.pointwise_conv1 = Conv1D(\n            channels,\n            2 * channels,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            bias_attr=None\n            if bias else False,  # None for True, using bias as default config\n        )\n\n        # self.lorder is used to distinguish if it's a causal convolution,\n        # if self.lorder > 0:\n        #    it's a causal convolution, the input will be padded with\n        #    `self.lorder` frames on the left in forward (causal conv impl).\n        # else: it's a symmetrical convolution\n        if causal:\n            padding = 0\n            self.lorder = kernel_size - 1\n        else:\n            # kernel_size should be an odd number for none causal convolution\n            assert (kernel_size - 1) % 2 == 0\n            padding = (kernel_size - 1) // 2\n            self.lorder = 0\n\n        self.depthwise_conv = Conv1D(\n            channels,\n            channels,\n            kernel_size,\n            stride=1,\n            padding=padding,\n            groups=channels,\n            bias_attr=None\n            if bias else False,  # None for True, using bias as default config\n        )\n\n        assert norm in ['batch_norm', 'layer_norm']\n        if norm == \"batch_norm\":\n            self.use_layer_norm = False\n            self.norm = BatchNorm1D(channels)\n        else:\n            self.use_layer_norm = True\n            self.norm = LayerNorm(channels)\n\n        self.pointwise_conv2 = Conv1D(\n            channels,\n            channels,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            bias_attr=None\n            if bias else False,  # None for True, using bias as default config\n        )\n        self.activation = activation\n\n        if init_weights:\n            self.init_weights()\n\n    def init_weights(self):\n        pw_max = self.channels**-0.5\n        dw_max = self.kernel_size**-0.5\n        self.pointwise_conv1._param_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n        if self.bias:\n            self.pointwise_conv1._bias_attr = paddle.nn.initializer.Uniform(\n                low=-pw_max, high=pw_max)\n        self.depthwise_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        if self.bias:\n            self.depthwise_conv._bias_attr = paddle.nn.initializer.Uniform(\n                low=-dw_max, high=dw_max)\n        self.pointwise_conv2._param_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n        if self.bias:\n            self.pointwise_conv2._bias_attr = paddle.nn.initializer.Uniform(\n                low=-pw_max, high=pw_max)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            mask_pad: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n            cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute convolution module.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, channels).\n            mask_pad (paddle.Tensor): used for batch padding (#batch, 1, time),\n                (0, 0, 0) means fake mask.\n            cache (paddle.Tensor): left context cache, it is only\n                used in causal convolution (#batch, channels, cache_t),\n                (0, 0, 0) meas fake cache.\n        Returns:\n            paddle.Tensor: Output tensor (#batch, time, channels).\n            paddle.Tensor: Output cache tensor (#batch, channels, time')\n        \"\"\"\n        if self.adaptive_scale:\n            x = self.ada_scale * x + self.ada_bias\n\n        # exchange the temporal dimension and the feature dimension\n        x = x.transpose([0, 2, 1])  # [B, C, T]\n\n        # mask batch padding\n        if mask_pad.shape[2] > 0:  # time > 0\n            x = x.masked_fill(mask_pad, 0.0)\n\n        if self.lorder > 0:\n            if cache.shape[2] == 0:  # cache_t == 0\n                x = nn.functional.pad(\n                    x, [self.lorder, 0], 'constant', 0.0, data_format='NCL')\n            else:\n                assert cache.shape[0] == x.shape[0]  # B\n                assert cache.shape[1] == x.shape[1]  # C\n                x = paddle.concat((cache, x), axis=2)\n\n            assert (x.shape[2] > self.lorder)\n            new_cache = x[:, :, -self.lorder:]  #[B, C, T]\n        else:\n            # It's better we just return None if no cache is requried,\n            # However, for JIT export, here we just fake one tensor instead of\n            # None.\n            new_cache = paddle.zeros([0, 0, 0], dtype=x.dtype)\n\n        # GLU mechanism\n        x = self.pointwise_conv1(x)  # (batch, 2*channel, dim)\n        x = nn.functional.glu(x, axis=1)  # (batch, channel, dim)\n\n        # 1D Depthwise Conv\n        x = self.depthwise_conv(x)\n        if self.use_layer_norm:\n            x = x.transpose([0, 2, 1])  # [B, T, C]\n        x = self.activation(self.norm(x))\n        if self.use_layer_norm:\n            x = x.transpose([0, 2, 1])  # [B, C, T]\n        x = self.pointwise_conv2(x)\n\n        # mask batch padding\n        if mask_pad.shape[2] > 0:  # time > 0\n            x = x.masked_fill(mask_pad, 0.0)\n\n        x = x.transpose([0, 2, 1])  # [B, T, C]\n        return x, new_cache\n"
  },
  {
    "path": "paddlespeech/s2t/modules/conv2d.py",
    "content": "from typing import Optional\nfrom typing import Union\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle.nn.layer.conv import _ConvNd\n\n__all__ = ['Conv2DValid']\n\n\nclass Conv2DValid(_ConvNd):\n    \"\"\"\n    Conv2d operator for VALID mode padding.\n    \"\"\"\n\n    def __init__(self,\n                 in_channels: int,\n                 out_channels: int,\n                 kernel_size: int,\n                 stride: int=1,\n                 padding: Union[str, int]=0,\n                 dilation: int=1,\n                 groups: int=1,\n                 padding_mode: str='zeros',\n                 weight_attr=None,\n                 bias_attr=None,\n                 data_format=\"NCHW\",\n                 valid_trigx: bool=False,\n                 valid_trigy: bool=False) -> None:\n        super(Conv2DValid, self).__init__(\n            in_channels,\n            out_channels,\n            kernel_size,\n            False,\n            2,\n            stride=stride,\n            padding=padding,\n            padding_mode=padding_mode,\n            dilation=dilation,\n            groups=groups,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format)\n        self.valid_trigx = valid_trigx\n        self.valid_trigy = valid_trigy\n\n    def _conv_forward(self,\n                      input: paddle.Tensor,\n                      weight: paddle.Tensor,\n                      bias: Optional[paddle.Tensor]):\n        validx, validy = 0, 0\n        if self.valid_trigx:\n            validx = (input.shape[-2] *\n                      (self._stride[-2] - 1) - 1 + self._kernel_size[-2]) // 2\n        if self.valid_trigy:\n            validy = (input.shape[-1] *\n                      (self._stride[-1] - 1) - 1 + self._kernel_size[-1]) // 2\n        return F.conv2d(input, weight, bias, self._stride, (validx, validy),\n                        self._dilation, self._groups)\n\n    def forward(self, input: paddle.Tensor) -> paddle.Tensor:\n        return self._conv_forward(input, self.weight, self.bias)\n"
  },
  {
    "path": "paddlespeech/s2t/modules/crf.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = ['CRF']\n\n\nclass CRF(nn.Layer):\n    \"\"\"\n    Linear-chain Conditional Random Field (CRF).\n    \n    Args:\n        nb_labels (int): number of labels in your tagset, including special symbols.\n        bos_tag_id (int): integer representing the beginning of sentence symbol in\n            your tagset.\n        eos_tag_id (int): integer representing the end of sentence symbol in your tagset.\n        pad_tag_id (int, optional): integer representing the pad symbol in your tagset.\n            If None, the model will treat the PAD as a normal tag. Otherwise, the model\n            will apply constraints for PAD transitions.\n        batch_first (bool): Whether the first dimension represents the batch dimension.\n    \"\"\"\n\n    def __init__(self,\n                 nb_labels: int,\n                 bos_tag_id: int,\n                 eos_tag_id: int,\n                 pad_tag_id: int=None,\n                 batch_first: bool=True):\n        super().__init__()\n\n        self.nb_labels = nb_labels\n        self.BOS_TAG_ID = bos_tag_id\n        self.EOS_TAG_ID = eos_tag_id\n        self.PAD_TAG_ID = pad_tag_id\n        self.batch_first = batch_first\n\n        # initialize transitions from a random uniform distribution between -0.1 and 0.1\n        self.transitions = self.create_parameter(\n            [self.nb_labels, self.nb_labels],\n            default_initializer=nn.initializer.Uniform(-0.1, 0.1))\n        self.init_weights()\n\n    def init_weights(self):\n        # enforce contraints (rows=from, columns=to) with a big negative number\n        # so exp(-10000) will tend to zero\n\n        # no transitions allowed to the beginning of sentence\n        self.transitions[:, self.BOS_TAG_ID] = -10000.0\n        # no transition alloed from the end of sentence\n        self.transitions[self.EOS_TAG_ID, :] = -10000.0\n\n        if self.PAD_TAG_ID is not None:\n            # no transitions from padding\n            self.transitions[self.PAD_TAG_ID, :] = -10000.0\n            # no transitions to padding\n            self.transitions[:, self.PAD_TAG_ID] = -10000.0\n            # except if the end of sentence is reached\n            # or we are already in a pad position\n            self.transitions[self.PAD_TAG_ID, self.EOS_TAG_ID] = 0.0\n            self.transitions[self.PAD_TAG_ID, self.PAD_TAG_ID] = 0.0\n\n    def forward(self,\n                emissions: paddle.Tensor,\n                tags: paddle.Tensor,\n                mask: paddle.Tensor=None) -> paddle.Tensor:\n        \"\"\"Compute the negative log-likelihood. See `log_likelihood` method.\"\"\"\n        nll = -self.log_likelihood(emissions, tags, mask=mask)\n        return nll\n\n    def log_likelihood(self, emissions, tags, mask=None):\n        \"\"\"Compute the probability of a sequence of tags given a sequence of\n        emissions scores.\n\n        Args:\n            emissions (paddle.Tensor): Sequence of emissions for each label.\n                Shape of (batch_size, seq_len, nb_labels) if batch_first is True,\n                (seq_len, batch_size, nb_labels) otherwise.\n            tags (paddle.LongTensor): Sequence of labels.\n                Shape of (batch_size, seq_len) if batch_first is True,\n                (seq_len, batch_size) otherwise.\n            mask (paddle.FloatTensor, optional): Tensor representing valid positions.\n                If None, all positions are considered valid.\n                Shape of (batch_size, seq_len) if batch_first is True,\n                (seq_len, batch_size) otherwise.\n\n        Returns:\n            paddle.Tensor: sum of the log-likelihoods for each sequence in the batch.\n                Shape of ()\n        \"\"\"\n        # fix tensors order by setting batch as the first dimension\n        if not self.batch_first:\n            emissions = emissions.transpose(0, 1)\n            tags = tags.transpose(0, 1)\n\n        if mask is None:\n            mask = paddle.ones(emissions.shape[:2], dtype=paddle.float)\n\n        scores = self._compute_scores(emissions, tags, mask=mask)\n        partition = self._compute_log_partition(emissions, mask=mask)\n        return paddle.sum(scores - partition)\n\n    def decode(self, emissions, mask=None):\n        \"\"\"Find the most probable sequence of labels given the emissions using\n        the Viterbi algorithm.\n\n        Args:\n            emissions (paddle.Tensor): Sequence of emissions for each label.\n                Shape (batch_size, seq_len, nb_labels) if batch_first is True,\n                (seq_len, batch_size, nb_labels) otherwise.\n            mask (paddle.FloatTensor, optional): Tensor representing valid positions.\n                If None, all positions are considered valid.\n                Shape (batch_size, seq_len) if batch_first is True,\n                (seq_len, batch_size) otherwise.\n\n        Returns:\n            paddle.Tensor: the viterbi score for the for each batch.\n                Shape of (batch_size,)\n            list of lists: the best viterbi sequence of labels for each batch. [B, T]\n        \"\"\"\n        # fix tensors order by setting batch as the first dimension\n        if not self.batch_first:\n            emissions = emissions.transpose(0, 1)\n            tags = tags.transpose(0, 1)\n\n        if mask is None:\n            mask = paddle.ones(emissions.shape[:2], dtype=paddle.float)\n\n        scores, sequences = self._viterbi_decode(emissions, mask)\n        return scores, sequences\n\n    def _compute_scores(self, emissions, tags, mask):\n        \"\"\"Compute the scores for a given batch of emissions with their tags.\n\n        Args:\n            emissions (paddle.Tensor): (batch_size, seq_len, nb_labels)\n            tags (Paddle.LongTensor): (batch_size, seq_len)\n            mask (Paddle.FloatTensor): (batch_size, seq_len)\n\n        Returns:\n            paddle.Tensor: Scores for each batch.\n                Shape of (batch_size,)\n        \"\"\"\n        batch_size, seq_length = tags.shape\n        scores = paddle.zeros([batch_size])\n\n        # save first and last tags to be used later\n        first_tags = tags[:, 0]\n        last_valid_idx = mask.int().sum(1) - 1\n\n        # TODO(Hui Zhang): not support fancy index. \n        # last_tags = tags.gather(last_valid_idx.unsqueeze(1), axis=1).squeeze()\n        batch_idx = paddle.arange(batch_size, dtype=last_valid_idx.dtype)\n        gather_last_valid_idx = paddle.stack(\n            [batch_idx, last_valid_idx], axis=-1)\n        last_tags = tags.gather_nd(gather_last_valid_idx)\n\n        # add the transition from BOS to the first tags for each batch\n        # t_scores = self.transitions[self.BOS_TAG_ID, first_tags]\n        t_scores = self.transitions[self.BOS_TAG_ID].gather(first_tags)\n\n        # add the [unary] emission scores for the first tags for each batch\n        # for all batches, the first word, see the correspondent emissions\n        # for the first tags (which is a list of ids):\n        # emissions[:, 0, [tag_1, tag_2, ..., tag_nblabels]]\n        # e_scores = emissions[:, 0].gather(1, first_tags.unsqueeze(1)).squeeze()\n        gather_first_tags_idx = paddle.stack([batch_idx, first_tags], axis=-1)\n        e_scores = emissions[:, 0].gather_nd(gather_first_tags_idx)\n\n        # the scores for a word is just the sum of both scores\n        scores += e_scores + t_scores\n\n        # now lets do this for each remaining word\n        for i in range(1, seq_length):\n\n            # we could: iterate over batches, check if we reached a mask symbol\n            # and stop the iteration, but vecotrizing is faster due to gpu,\n            # so instead we perform an element-wise multiplication\n            is_valid = mask[:, i]\n\n            previous_tags = tags[:, i - 1]\n            current_tags = tags[:, i]\n\n            # calculate emission and transition scores as we did before\n            # e_scores = emissions[:, i].gather(1, current_tags.unsqueeze(1)).squeeze()\n            gather_current_tags_idx = paddle.stack(\n                [batch_idx, current_tags], axis=-1)\n            e_scores = emissions[:, i].gather_nd(gather_current_tags_idx)\n            # t_scores = self.transitions[previous_tags, current_tags]\n            gather_transitions_idx = paddle.stack(\n                [previous_tags, current_tags], axis=-1)\n            t_scores = self.transitions.gather_nd(gather_transitions_idx)\n\n            # apply the mask\n            e_scores = e_scores * is_valid\n            t_scores = t_scores * is_valid\n\n            scores += e_scores + t_scores\n\n        # add the transition from the end tag to the EOS tag for each batch\n        # scores += self.transitions[last_tags, self.EOS_TAG_ID]\n        scores += self.transitions.gather(last_tags)[:, self.EOS_TAG_ID]\n\n        return scores\n\n    def _compute_log_partition(self, emissions, mask):\n        \"\"\"Compute the partition function in log-space using the forward-algorithm.\n\n        Args:\n            emissions (paddle.Tensor): (batch_size, seq_len, nb_labels)\n            mask (Paddle.FloatTensor): (batch_size, seq_len)\n\n        Returns:\n            paddle.Tensor: the partition scores for each batch.\n                Shape of (batch_size,)\n        \"\"\"\n        batch_size, seq_length, nb_labels = emissions.shape\n\n        # in the first iteration, BOS will have all the scores\n        alphas = self.transitions[self.BOS_TAG_ID, :].unsqueeze(\n            0) + emissions[:, 0]\n\n        for i in range(1, seq_length):\n            # (bs, nb_labels) -> (bs, 1, nb_labels)\n            e_scores = emissions[:, i].unsqueeze(1)\n\n            # (nb_labels, nb_labels) -> (bs, nb_labels, nb_labels)\n            t_scores = self.transitions.unsqueeze(0)\n\n            # (bs, nb_labels)  -> (bs, nb_labels, 1)\n            a_scores = alphas.unsqueeze(2)\n\n            scores = e_scores + t_scores + a_scores\n            new_alphas = paddle.logsumexp(scores, axis=1)\n\n            # set alphas if the mask is valid, otherwise keep the current values\n            is_valid = mask[:, i].unsqueeze(-1)\n            alphas = is_valid * new_alphas + (1 - is_valid) * alphas\n\n        # add the scores for the final transition\n        last_transition = self.transitions[:, self.EOS_TAG_ID]\n        end_scores = alphas + last_transition.unsqueeze(0)\n\n        # return a *log* of sums of exps\n        return paddle.logsumexp(end_scores, axis=1)\n\n    def _viterbi_decode(self, emissions, mask):\n        \"\"\"Compute the viterbi algorithm to find the most probable sequence of labels\n        given a sequence of emissions.\n\n        Args:\n            emissions (paddle.Tensor): (batch_size, seq_len, nb_labels)\n            mask (Paddle.FloatTensor): (batch_size, seq_len)\n\n        Returns:\n            paddle.Tensor: the viterbi score for the for each batch.\n                Shape of (batch_size,)\n            list of lists of ints: the best viterbi sequence of labels for each batch\n        \"\"\"\n        batch_size, seq_length, nb_labels = emissions.shape\n\n        # in the first iteration, BOS will have all the scores and then, the max\n        alphas = self.transitions[self.BOS_TAG_ID, :].unsqueeze(\n            0) + emissions[:, 0]\n\n        backpointers = []\n\n        for i in range(1, seq_length):\n            # (bs, nb_labels) -> (bs, 1, nb_labels)\n            e_scores = emissions[:, i].unsqueeze(1)\n\n            # (nb_labels, nb_labels) -> (bs, nb_labels, nb_labels)\n            t_scores = self.transitions.unsqueeze(0)\n\n            # (bs, nb_labels)  -> (bs, nb_labels, 1)\n            a_scores = alphas.unsqueeze(2)\n\n            # combine current scores with previous alphas\n            scores = e_scores + t_scores + a_scores\n\n            # so far is exactly like the forward algorithm,\n            # but now, instead of calculating the logsumexp,\n            # we will find the highest score and the tag associated with it\n            # max_scores, max_score_tags = paddle.max(scores, axis=1)\n            max_scores = paddle.max(scores, axis=1)\n            max_score_tags = paddle.argmax(scores, axis=1)\n\n            # set alphas if the mask is valid, otherwise keep the current values\n            is_valid = mask[:, i].unsqueeze(-1)\n            alphas = is_valid * max_scores + (1 - is_valid) * alphas\n\n            # add the max_score_tags for our list of backpointers\n            # max_scores has shape (batch_size, nb_labels) so we transpose it to\n            # be compatible with our previous loopy version of viterbi\n            backpointers.append(max_score_tags.t())\n\n        # add the scores for the final transition\n        last_transition = self.transitions[:, self.EOS_TAG_ID]\n        end_scores = alphas + last_transition.unsqueeze(0)\n\n        # get the final most probable score and the final most probable tag\n        # max_final_scores, max_final_tags = paddle.max(end_scores, axis=1)\n        max_final_scores = paddle.max(end_scores, axis=1)\n        max_final_tags = paddle.argmax(end_scores, axis=1)\n\n        # find the best sequence of labels for each sample in the batch\n        best_sequences = []\n        emission_lengths = mask.int().sum(axis=1)\n        for i in range(batch_size):\n\n            # recover the original sentence length for the i-th sample in the batch\n            sample_length = emission_lengths[i].item()\n\n            # recover the max tag for the last timestep\n            sample_final_tag = max_final_tags[i].item()\n\n            # limit the backpointers until the last but one\n            # since the last corresponds to the sample_final_tag\n            sample_backpointers = backpointers[:sample_length - 1]\n\n            # follow the backpointers to build the sequence of labels\n            sample_path = self._find_best_path(i, sample_final_tag,\n                                               sample_backpointers)\n\n            # add this path to the list of best sequences\n            best_sequences.append(sample_path)\n\n        return max_final_scores, best_sequences\n\n    def _find_best_path(self, sample_id, best_tag, backpointers):\n        \"\"\"Auxiliary function to find the best path sequence for a specific sample.\n\n            Args:\n                sample_id (int): sample index in the range [0, batch_size)\n                best_tag (int): tag which maximizes the final score\n                backpointers (list of lists of tensors): list of pointers with\n                shape (seq_len_i-1, nb_labels, batch_size) where seq_len_i\n                represents the length of the ith sample in the batch\n\n            Returns:\n                list of ints: a list of tag indexes representing the bast path\n        \"\"\"\n        # add the final best_tag to our best path\n        best_path = [best_tag]\n\n        # traverse the backpointers in backwards\n        for backpointers_t in reversed(backpointers):\n\n            # recover the best_tag at this timestep\n            best_tag = backpointers_t[best_tag][sample_id].item()\n\n            # append to the beginning of the list so we don't need to reverse it later\n            best_path.insert(0, best_tag)\n\n        return best_path\n"
  },
  {
    "path": "paddlespeech/s2t/modules/ctc.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\nfrom typeguard import typechecked\n\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.modules.loss import CTCLoss\nfrom paddlespeech.s2t.utils import ctc_utils\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\ntry:\n    from paddlespeech.s2t.decoders.ctcdecoder import ctc_beam_search_decoding_batch  # noqa: F401\n    from paddlespeech.s2t.decoders.ctcdecoder import ctc_greedy_decoding  # noqa: F401\n    from paddlespeech.s2t.decoders.ctcdecoder import Scorer  # noqa: F401\n    from paddlespeech.s2t.decoders.ctcdecoder import CTCBeamSearchDecoder  # noqa: F401\nexcept ImportError:\n    try:\n        from paddlespeech.s2t.utils import dynamic_pip_install\n        package_name = 'paddlespeech_ctcdecoders'\n        if sys.platform != \"win32\":\n            dynamic_pip_install.install(package_name)\n        from paddlespeech.s2t.decoders.ctcdecoder import ctc_beam_search_decoding_batch  # noqa: F401\n        from paddlespeech.s2t.decoders.ctcdecoder import ctc_greedy_decoding  # noqa: F401\n        from paddlespeech.s2t.decoders.ctcdecoder import Scorer  # noqa: F401\n        from paddlespeech.s2t.decoders.ctcdecoder import CTCBeamSearchDecoder  # noqa: F401\n    except Exception as e:\n        logger.info(\"paddlespeech_ctcdecoders not installed!\")\n\n__all__ = ['CTCDecoder']\n\n\nclass CTCDecoderBase(nn.Layer):\n    @typechecked\n    def __init__(self,\n                 odim,\n                 enc_n_units,\n                 blank_id=0,\n                 dropout_rate: float=0.0,\n                 reduction: Union[str, bool]=True,\n                 batch_average: bool=True,\n                 grad_norm_type: Union[str, None]=None):\n        \"\"\"CTC decoder\n\n        Args:\n            odim ([int]): text vocabulary size\n            enc_n_units ([int]): encoder output dimention\n            dropout_rate (float): dropout rate (0.0 ~ 1.0)\n            reduction (bool): reduce the CTC loss into a scalar, True for 'sum' or 'none'\n            batch_average (bool): do batch dim wise average.\n            grad_norm_type (str): Default, None. one of 'instance', 'batch', 'frame', None.\n        \"\"\"\n        super().__init__()\n\n        self.blank_id = blank_id\n        self.odim = odim\n        self.dropout = nn.Dropout(dropout_rate)\n        self.ctc_lo = Linear(enc_n_units, self.odim)\n        if isinstance(reduction, bool):\n            reduction_type = \"sum\" if reduction else \"none\"\n        else:\n            reduction_type = reduction\n        self.criterion = CTCLoss(\n            blank=self.blank_id,\n            reduction=reduction_type,\n            batch_average=batch_average,\n            grad_norm_type=grad_norm_type)\n\n    def forward(self, hs_pad, hlens, ys_pad, ys_lens):\n        \"\"\"Calculate CTC loss.\n\n        Args:\n            hs_pad (Tensor): batch of padded hidden state sequences (B, Tmax, D)\n            hlens (Tensor): batch of lengths of hidden state sequences (B)\n            ys_pad (Tensor): batch of padded character id sequence tensor (B, Lmax)\n            ys_lens (Tensor): batch of lengths of character sequence (B)\n        Returns:\n            loss (Tensor): ctc loss value, scalar.\n        \"\"\"\n        logits = self.ctc_lo(self.dropout(hs_pad))\n        loss = self.criterion(logits, ys_pad, hlens, ys_lens)\n        return loss\n\n    def softmax(self, eouts: paddle.Tensor, temperature: float=1.0):\n        \"\"\"Get CTC probabilities.\n        Args:\n            eouts (FloatTensor): `[B, T, enc_units]`\n        Returns:\n            probs (FloatTensor): `[B, T, odim]`\n        \"\"\"\n        self.probs = F.softmax(self.ctc_lo(eouts) / temperature, axis=2)\n        return self.probs\n\n    def log_softmax(self, hs_pad: paddle.Tensor,\n                    temperature: float=1.0) -> paddle.Tensor:\n        \"\"\"log_softmax of frame activations\n        Args:\n            Tensor hs_pad: 3d tensor (B, Tmax, eprojs)\n        Returns:\n            paddle.Tensor: log softmax applied 3d tensor (B, Tmax, odim)\n        \"\"\"\n        return F.log_softmax(self.ctc_lo(hs_pad) / temperature, axis=2)\n\n    def argmax(self, hs_pad: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"argmax of frame activations\n        Args:\n            paddle.Tensor hs_pad: 3d tensor (B, Tmax, eprojs)\n        Returns:\n            paddle.Tensor: argmax applied 2d tensor (B, Tmax)\n        \"\"\"\n        return paddle.argmax(self.ctc_lo(hs_pad), dim=2)\n\n    def forced_align(self,\n                     ctc_probs: paddle.Tensor,\n                     y: paddle.Tensor,\n                     blank_id=0) -> list:\n        \"\"\"ctc forced alignment.\n        Args:\n            ctc_probs (paddle.Tensor): hidden state sequence, 2d tensor (T, D)\n            y (paddle.Tensor): label id sequence tensor, 1d tensor (L)\n            blank_id (int): blank symbol index\n        Returns:\n            paddle.Tensor: best alignment result, (T).\n        \"\"\"\n        return ctc_utils.forced_align(ctc_probs, y, blank_id)\n\n\nclass CTCDecoder(CTCDecoderBase):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        # CTCDecoder LM Score handle\n        self._ext_scorer = None\n        self.beam_search_decoder = None\n\n    def _decode_batch_greedy_offline(self, probs_split, vocab_list):\n        \"\"\"This function will be deprecated in future.\n        Decode by best path for a batch of probs matrix input.\n        :param probs_split: List of 2-D probability matrix, and each consists\n                            of prob vectors for one speech utterancce.\n        :param probs_split: List of matrix\n        :param vocab_list: List of tokens in the vocabulary, for decoding.\n        :type vocab_list: list\n        :return: List of transcription texts.\n        :rtype: List of str\n        \"\"\"\n        results = []\n        for i, probs in enumerate(probs_split):\n            output_transcription = ctc_greedy_decoding(\n                probs_seq=probs, vocabulary=vocab_list, blank_id=self.blank_id)\n            results.append(output_transcription)\n        return results\n\n    def _init_ext_scorer(self, beam_alpha, beam_beta, language_model_path,\n                         vocab_list):\n        \"\"\"Initialize the external scorer.\n        :param beam_alpha: Parameter associated with language model.\n        :type beam_alpha: float\n        :param beam_beta: Parameter associated with word count.\n        :type beam_beta: float\n        :param language_model_path: Filepath for language model. If it is\n                                    empty, the external scorer will be set to\n                                    None, and the decoding method will be pure\n                                    beam search without scorer.\n        :type language_model_path: str|None\n        :param vocab_list: List of tokens in the vocabulary, for decoding.\n        :type vocab_list: list\n        \"\"\"\n        # init once\n        if self._ext_scorer is not None:\n            return\n\n        if language_model_path != '':\n            logger.info(\"begin to initialize the external scorer \"\n                        \"for decoding\")\n            self._ext_scorer = Scorer(beam_alpha, beam_beta,\n                                      language_model_path, vocab_list)\n            lm_char_based = self._ext_scorer.is_character_based()\n            lm_max_order = self._ext_scorer.get_max_order()\n            lm_dict_size = self._ext_scorer.get_dict_size()\n            logger.info(\"language model: \"\n                        \"is_character_based = %d,\" % lm_char_based +\n                        \" max_order = %d,\" % lm_max_order + \" dict_size = %d\" %\n                        lm_dict_size)\n            logger.info(\"end initializing scorer\")\n        else:\n            self._ext_scorer = None\n            logger.info(\"no language model provided, \"\n                        \"decoding by pure beam search without scorer.\")\n\n    def _decode_batch_beam_search_offline(\n            self, probs_split, beam_alpha, beam_beta, beam_size, cutoff_prob,\n            cutoff_top_n, vocab_list, num_processes):\n        \"\"\"\n        This function will be deprecated in future.\n        Decode by beam search for a batch of probs matrix input.\n        :param probs_split: List of 2-D probability matrix, and each consists\n                            of prob vectors for one speech utterancce.\n        :param probs_split: List of matrix\n        :param beam_alpha: Parameter associated with language model.\n        :type beam_alpha: float\n        :param beam_beta: Parameter associated with word count.\n        :type beam_beta: float\n        :param beam_size: Width for Beam search.\n        :type beam_size: int\n        :param cutoff_prob: Cutoff probability in pruning,\n                            default 1.0, no pruning.\n        :type cutoff_prob: float\n        :param cutoff_top_n: Cutoff number in pruning, only top cutoff_top_n\n                        characters with highest probs in vocabulary will be\n                        used in beam search, default 40.\n        :type cutoff_top_n: int\n        :param vocab_list: List of tokens in the vocabulary, for decoding.\n        :type vocab_list: list\n        :param num_processes: Number of processes (CPU) for decoder.\n        :type num_processes: int\n        :return: List of transcription texts.\n        :rtype: List of str\n        \"\"\"\n        if self._ext_scorer is not None:\n            self._ext_scorer.reset_params(beam_alpha, beam_beta)\n\n        # beam search decode\n        num_processes = min(num_processes, len(probs_split))\n        beam_search_results = ctc_beam_search_decoding_batch(\n            probs_split=probs_split,\n            vocabulary=vocab_list,\n            beam_size=beam_size,\n            num_processes=num_processes,\n            ext_scoring_func=self._ext_scorer,\n            cutoff_prob=cutoff_prob,\n            cutoff_top_n=cutoff_top_n,\n            blank_id=self.blank_id)\n\n        results = [result[0][1] for result in beam_search_results]\n        return results\n\n    def init_decoder(self, batch_size, vocab_list, decoding_method,\n                     lang_model_path, beam_alpha, beam_beta, beam_size,\n                     cutoff_prob, cutoff_top_n, num_processes):\n        \"\"\"\n        init ctc decoders\n        Args:\n            batch_size(int): Batch size for input data\n            vocab_list (list): List of tokens in the vocabulary, for decoding\n            decoding_method (str): ctc_beam_search\n            lang_model_path (str): language model path\n            beam_alpha (float): beam_alpha\n            beam_beta (float): beam_beta\n            beam_size (int): beam_size\n            cutoff_prob (float): cutoff probability in beam search\n            cutoff_top_n (int): cutoff_top_n\n            num_processes (int): num_processes\n\n        Raises:\n            ValueError: when decoding_method not support.\n\n        Returns:\n            CTCBeamSearchDecoder\n        \"\"\"\n        self.batch_size = batch_size\n        self.vocab_list = vocab_list\n        self.decoding_method = decoding_method\n        self.beam_size = beam_size\n        self.cutoff_prob = cutoff_prob\n        self.cutoff_top_n = cutoff_top_n\n        self.num_processes = num_processes\n        if decoding_method == \"ctc_beam_search\":\n            self._init_ext_scorer(beam_alpha, beam_beta, lang_model_path,\n                                  vocab_list)\n            if self.beam_search_decoder is None:\n                self.beam_search_decoder = self.get_decoder(\n                    vocab_list, batch_size, beam_alpha, beam_beta, beam_size,\n                    num_processes, cutoff_prob, cutoff_top_n)\n            return self.beam_search_decoder\n        elif decoding_method == \"ctc_greedy\":\n            self._init_ext_scorer(beam_alpha, beam_beta, lang_model_path,\n                                  vocab_list)\n        else:\n            raise ValueError(f\"Not support: {decoding_method}\")\n\n    def decode_probs_offline(self, probs, logits_lens, vocab_list,\n                             decoding_method, lang_model_path, beam_alpha,\n                             beam_beta, beam_size, cutoff_prob, cutoff_top_n,\n                             num_processes):\n        \"\"\"\n        This function will be deprecated in future.\n        ctc decoding with probs.\n        Args:\n            probs (Tensor): activation after softmax\n            logits_lens (Tensor): audio output lens\n            vocab_list (list): List of tokens in the vocabulary, for decoding\n            decoding_method (str): ctc_beam_search\n            lang_model_path (str): language model path\n            beam_alpha (float): beam_alpha\n            beam_beta (float): beam_beta\n            beam_size (int): beam_size\n            cutoff_prob (float): cutoff probability in beam search\n            cutoff_top_n (int): cutoff_top_n\n            num_processes (int): num_processes\n\n        Raises:\n            ValueError: when decoding_method not support.\n\n        Returns:\n            List[str]: transcripts.\n        \"\"\"\n        logger.warn(\n            \"This function will be deprecated in future: decode_probs_offline\")\n        probs_split = [probs[i, :l, :] for i, l in enumerate(logits_lens)]\n        if decoding_method == \"ctc_greedy\":\n            result_transcripts = self._decode_batch_greedy_offline(\n                probs_split=probs_split, vocab_list=vocab_list)\n        elif decoding_method == \"ctc_beam_search\":\n            result_transcripts = self._decode_batch_beam_search_offline(\n                probs_split=probs_split,\n                beam_alpha=beam_alpha,\n                beam_beta=beam_beta,\n                beam_size=beam_size,\n                cutoff_prob=cutoff_prob,\n                cutoff_top_n=cutoff_top_n,\n                vocab_list=vocab_list,\n                num_processes=num_processes)\n        else:\n            raise ValueError(f\"Not support: {decoding_method}\")\n        return result_transcripts\n\n    def get_decoder(self, vocab_list, batch_size, beam_alpha, beam_beta,\n                    beam_size, num_processes, cutoff_prob, cutoff_top_n):\n        \"\"\"\n        init get ctc decoder\n        Args:\n            vocab_list (list): List of tokens in the vocabulary, for decoding.\n            batch_size(int): Batch size for input data\n            beam_alpha (float): beam_alpha\n            beam_beta (float): beam_beta\n            beam_size (int): beam_size\n            num_processes (int): num_processes\n            cutoff_prob (float): cutoff probability in beam search\n            cutoff_top_n (int): cutoff_top_n\n\n        Raises:\n            ValueError: when decoding_method not support.\n\n        Returns:\n            CTCBeamSearchDecoder\n        \"\"\"\n        num_processes = min(num_processes, batch_size)\n        if self._ext_scorer is not None:\n            self._ext_scorer.reset_params(beam_alpha, beam_beta)\n        if self.decoding_method == \"ctc_beam_search\":\n            beam_search_decoder = CTCBeamSearchDecoder(\n                vocab_list, batch_size, beam_size, num_processes, cutoff_prob,\n                cutoff_top_n, self._ext_scorer, self.blank_id)\n        else:\n            raise ValueError(f\"Not support: {decoding_method}\")\n        return beam_search_decoder\n\n    def next(self, probs, logits_lens):\n        \"\"\"\n        Input probs into ctc decoder\n        Args:\n            probs (list(list(float))): probs for a batch of data\n            logits_lens (list(int)): logits lens for a batch of data\n        Raises:\n            Exception: when the ctc decoder is not initialized\n            ValueError: when decoding_method not support.\n        \"\"\"\n\n        if self.beam_search_decoder is None:\n            raise Exception(\n                \"You need to initialize the beam_search_decoder firstly\")\n        beam_search_decoder = self.beam_search_decoder\n\n        has_value = (logits_lens > 0).tolist()\n        has_value = [\n            \"true\" if has_value[i] is True else \"false\"\n            for i in range(len(has_value))\n        ]\n        probs_split = [\n            probs[i, :l, :].tolist() if has_value[i] else probs[i].tolist()\n            for i, l in enumerate(logits_lens)\n        ]\n        if self.decoding_method == \"ctc_beam_search\":\n            beam_search_decoder.next(probs_split, has_value)\n        else:\n            raise ValueError(f\"Not support: {decoding_method}\")\n\n        return\n\n    def decode(self):\n        \"\"\"\n        Get the decoding result\n        Raises:\n            Exception: when the ctc decoder is not initialized\n            ValueError: when decoding_method not support.\n        Returns:\n            results_best (list(str)): The best result for a batch of data\n            results_beam (list(list(str))): The beam search result for a batch of data\n        \"\"\"\n        if self.beam_search_decoder is None:\n            raise Exception(\n                \"You need to initialize the beam_search_decoder firstly\")\n\n        beam_search_decoder = self.beam_search_decoder\n        if self.decoding_method == \"ctc_beam_search\":\n            batch_beam_results = beam_search_decoder.decode()\n            batch_beam_results = [[(res[0], res[1]) for res in beam_results]\n                                  for beam_results in batch_beam_results]\n            results_best = [result[0][1] for result in batch_beam_results]\n            results_beam = [[trans[1] for trans in result]\n                            for result in batch_beam_results]\n\n        else:\n            raise ValueError(f\"Not support: {decoding_method}\")\n\n        return results_best, results_beam\n\n    def reset_decoder(self,\n                      batch_size=-1,\n                      beam_size=-1,\n                      num_processes=-1,\n                      cutoff_prob=-1.0,\n                      cutoff_top_n=-1):\n        if batch_size > 0:\n            self.batch_size = batch_size\n        if beam_size > 0:\n            self.beam_size = beam_size\n        if num_processes > 0:\n            self.num_processes = num_processes\n        if cutoff_prob > 0:\n            self.cutoff_prob = cutoff_prob\n        if cutoff_top_n > 0:\n            self.cutoff_top_n = cutoff_top_n\n        \"\"\"\n        Reset the decoder state\n        Args:\n            batch_size(int): Batch size for input data\n            beam_size (int): beam_size\n            num_processes (int): num_processes\n            cutoff_prob (float): cutoff probability in beam search\n            cutoff_top_n (int): cutoff_top_n\n        Raises:\n            Exception: when the ctc decoder is not initialized\n        \"\"\"\n        if self.beam_search_decoder is None:\n            raise Exception(\n                \"You need to initialize the beam_search_decoder firstly\")\n        self.beam_search_decoder.reset_state(\n            self.batch_size, self.beam_size, self.num_processes,\n            self.cutoff_prob, self.cutoff_top_n)\n\n    def del_decoder(self):\n        \"\"\"\n        Delete the decoder\n        \"\"\"\n        if self.beam_search_decoder is not None:\n            del self.beam_search_decoder\n            self.beam_search_decoder = None\n"
  },
  {
    "path": "paddlespeech/s2t/modules/decoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Decoder definition.\"\"\"\nfrom typing import Any\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.s2t.decoders.scorers.scorer_interface import BatchScorerInterface\nfrom paddlespeech.s2t.modules.align import Embedding\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.modules.attention import MultiHeadedAttention\nfrom paddlespeech.s2t.modules.decoder_layer import DecoderLayer\nfrom paddlespeech.s2t.modules.embedding import PositionalEncoding\nfrom paddlespeech.s2t.modules.mask import make_non_pad_mask\nfrom paddlespeech.s2t.modules.mask import make_xs_mask\nfrom paddlespeech.s2t.modules.mask import subsequent_mask\nfrom paddlespeech.s2t.modules.positionwise_feed_forward import PositionwiseFeedForward\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n__all__ = [\"TransformerDecoder\"]\n\n\nclass TransformerDecoder(BatchScorerInterface, nn.Layer):\n    \"\"\"Base class of Transfomer decoder module.\n    Args:\n        vocab_size: output dim\n        encoder_output_size: dimension of attention\n        attention_heads: the number of heads of multi head attention\n        linear_units: the hidden units number of position-wise feedforward\n        num_blocks: the number of decoder blocks\n        dropout_rate: dropout rate\n        self_attention_dropout_rate: dropout rate for attention\n        input_layer: input layer type, `embed`\n        use_output_layer: whether to use output layer\n        pos_enc_class: PositionalEncoding module\n        normalize_before:\n            True: use layer_norm before each sub-block of a layer.\n            False: use layer_norm after each sub-block of a layer.\n        concat_after: whether to concat attention layer's input and output\n            True: x -> x + linear(concat(x, att(x)))\n            False: x -> x + att(x)\n    \"\"\"\n\n    @typechecked\n    def __init__(self,\n                 vocab_size: int,\n                 encoder_output_size: int,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 self_attention_dropout_rate: float=0.0,\n                 src_attention_dropout_rate: float=0.0,\n                 input_layer: str=\"embed\",\n                 use_output_layer: bool=True,\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 max_len: int=5000):\n\n        nn.Layer.__init__(self)\n        self.selfattention_layer_type = 'selfattn'\n        attention_dim = encoder_output_size\n\n        if input_layer == \"embed\":\n            self.embed = nn.Sequential(\n                Embedding(vocab_size, attention_dim),\n                PositionalEncoding(\n                    attention_dim, positional_dropout_rate, max_len=max_len), )\n        else:\n            raise ValueError(f\"only 'embed' is supported: {input_layer}\")\n\n        self.normalize_before = normalize_before\n        self.after_norm = LayerNorm(attention_dim, epsilon=1e-12)\n        self.use_output_layer = use_output_layer\n        self.output_layer = Linear(attention_dim, vocab_size)\n\n        self.decoders = nn.LayerList([\n            DecoderLayer(\n                size=attention_dim,\n                self_attn=MultiHeadedAttention(attention_heads, attention_dim,\n                                               self_attention_dropout_rate),\n                src_attn=MultiHeadedAttention(attention_heads, attention_dim,\n                                              src_attention_dropout_rate),\n                feed_forward=PositionwiseFeedForward(\n                    attention_dim, linear_units, dropout_rate),\n                dropout_rate=dropout_rate,\n                normalize_before=normalize_before,\n                concat_after=concat_after, ) for _ in range(num_blocks)\n        ])\n\n    def forward(self,\n                memory: paddle.Tensor,\n                memory_mask: paddle.Tensor,\n                ys_in_pad: paddle.Tensor,\n                ys_in_lens: paddle.Tensor,\n                r_ys_in_pad: paddle.Tensor=paddle.empty([0]),\n                reverse_weight: float=0.0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Forward decoder.\n        Args:\n            memory: encoded memory, float32  (batch, maxlen_in, feat)\n            memory_mask: encoder memory mask, (batch, 1, maxlen_in)\n            ys_in_pad: padded input token ids, int64 (batch, maxlen_out)\n            ys_in_lens: input lengths of this batch (batch)\n            r_ys_in_pad: not used in transformer decoder, in order to unify api\n                with bidirectional decoder\n            reverse_weight: not used in transformer decoder, in order to unify\n                api with bidirectional decode\n        Returns:\n            (tuple): tuple containing:\n                x: decoded token score before softmax (batch, maxlen_out, vocab_size)\n                    if use_output_layer is True,\n                olens: (batch, )\n        \"\"\"\n        tgt = ys_in_pad\n        # tgt_mask: (B, 1, L)\n        tgt_mask = (make_non_pad_mask(ys_in_lens).unsqueeze(1))\n        # m: (1, L, L)\n        m = subsequent_mask(tgt_mask.shape[-1]).unsqueeze(0)\n        # tgt_mask: (B, L, L)\n        tgt_mask = tgt_mask & m\n\n        x, _ = self.embed(tgt)\n        for layer in self.decoders:\n            x, tgt_mask, memory, memory_mask = layer(x, tgt_mask, memory,\n                                                     memory_mask)\n        if self.normalize_before:\n            x = self.after_norm(x)\n        if self.use_output_layer:\n            x = self.output_layer(x)\n\n        olens = tgt_mask.sum(1)\n        return x, paddle.to_tensor(0.0), olens\n\n    def forward_one_step(\n            self,\n            memory: paddle.Tensor,\n            memory_mask: paddle.Tensor,\n            tgt: paddle.Tensor,\n            tgt_mask: paddle.Tensor,\n            cache: Optional[List[paddle.Tensor]]=None,\n    ) -> Tuple[paddle.Tensor, List[paddle.Tensor]]:\n        \"\"\"Forward one step.\n            This is only used for decoding.\n        Args:\n            memory: encoded memory, float32  (batch, maxlen_in, feat)\n            memory_mask: encoded memory mask, (batch, 1, maxlen_in)\n            tgt: input token ids, int64 (batch, maxlen_out)\n            tgt_mask: input token mask,  (batch, maxlen_out, maxlen_out)\n                      dtype=paddle.bool\n            cache: cached output list of (batch, max_time_out-1, size)\n        Returns:\n            y, cache: NN output value and cache per `self.decoders`.\n                y.shape` is (batch, token)\n        \"\"\"\n        x, _ = self.embed(tgt)\n        new_cache = []\n        for i, decoder in enumerate(self.decoders):\n            if cache is None:\n                c = None\n            else:\n                c = cache[i]\n            x, tgt_mask, memory, memory_mask = decoder(\n                x, tgt_mask, memory, memory_mask, cache=c)\n            new_cache.append(x)\n        if self.normalize_before:\n            y = self.after_norm(x[:, -1])\n        else:\n            y = x[:, -1]\n        if self.use_output_layer:\n            y = paddle.nn.functional.log_softmax(self.output_layer(y), axis=-1)\n        return y, new_cache\n\n    # beam search API (see ScorerInterface)\n    def score(self, ys, state, x):\n        \"\"\"Score.\n        ys: (ylen,)\n        x: (xlen, n_feat)\n        \"\"\"\n        ys_mask = subsequent_mask(len(ys)).unsqueeze(0)  # (B,L,L)\n        x_mask = make_xs_mask(x.unsqueeze(0)).unsqueeze(1)  # (B,1,T)\n        if self.selfattention_layer_type != \"selfattn\":\n            # TODO(karita): implement cache\n            logging.warning(\n                f\"{self.selfattention_layer_type} does not support cached decoding.\"\n            )\n            state = None\n        logp, state = self.forward_one_step(\n            x.unsqueeze(0), x_mask, ys.unsqueeze(0), ys_mask, cache=state)\n        return logp.squeeze(0), state\n\n    # batch beam search API (see BatchScorerInterface)\n    def batch_score(self,\n                    ys: paddle.Tensor,\n                    states: List[Any],\n                    xs: paddle.Tensor) -> Tuple[paddle.Tensor, List[Any]]:\n        \"\"\"Score new token batch (required).\n\n        Args:\n            ys (paddle.Tensor): paddle.int64 prefix tokens (n_batch, ylen).\n            states (List[Any]): Scorer states for prefix tokens.\n            xs (paddle.Tensor):\n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[paddle.Tensor, List[Any]]: Tuple of\n                batchfied scores for next token with shape of `(n_batch, n_vocab)`\n                and next state list for ys.\n\n        \"\"\"\n        # merge states\n        n_batch = len(ys)\n        n_layers = len(self.decoders)\n        if states[0] is None:\n            batch_state = None\n        else:\n            # transpose state of [batch, layer] into [layer, batch]\n            batch_state = [\n                paddle.stack([states[b][i] for b in range(n_batch)])\n                for i in range(n_layers)\n            ]\n\n        # batch decoding\n        ys_mask = subsequent_mask(ys.shape[-1]).unsqueeze(0)  # (B,L,L)\n        xs_mask = make_xs_mask(xs).unsqueeze(1)  # (B,1,T)\n        logp, states = self.forward_one_step(\n            xs, xs_mask, ys, ys_mask, cache=batch_state)\n\n        # transpose state of [layer, batch] into [batch, layer]\n        state_list = [[states[i][b] for i in range(n_layers)]\n                      for b in range(n_batch)]\n        return logp, state_list\n\n\nclass BiTransformerDecoder(BatchScorerInterface, nn.Layer):\n    \"\"\"Base class of Transfomer decoder module.\n    Args:\n        vocab_size: output dim\n        encoder_output_size: dimension of attention\n        attention_heads: the number of heads of multi head attention\n        linear_units: the hidden units number of position-wise feedforward\n        num_blocks: the number of decoder blocks\n        r_num_blocks: the number of right to left decoder blocks\n        dropout_rate: dropout rate\n        self_attention_dropout_rate: dropout rate for attention\n        input_layer: input layer type\n        use_output_layer: whether to use output layer\n        pos_enc_class: PositionalEncoding or ScaledPositionalEncoding\n        normalize_before:\n            True: use layer_norm before each sub-block of a layer.\n            False: use layer_norm after each sub-block of a layer.\n        concat_after: whether to concat attention layer's input and output\n            True: x -> x + linear(concat(x, att(x)))\n            False: x -> x + att(x)\n    \"\"\"\n\n    @typechecked\n    def __init__(self,\n                 vocab_size: int,\n                 encoder_output_size: int,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 r_num_blocks: int=0,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 self_attention_dropout_rate: float=0.0,\n                 src_attention_dropout_rate: float=0.0,\n                 input_layer: str=\"embed\",\n                 use_output_layer: bool=True,\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 max_len: int=5000):\n\n        nn.Layer.__init__(self)\n        self.left_decoder = TransformerDecoder(\n            vocab_size, encoder_output_size, attention_heads, linear_units,\n            num_blocks, dropout_rate, positional_dropout_rate,\n            self_attention_dropout_rate, src_attention_dropout_rate,\n            input_layer, use_output_layer, normalize_before, concat_after,\n            max_len)\n\n        self.right_decoder = TransformerDecoder(\n            vocab_size, encoder_output_size, attention_heads, linear_units,\n            r_num_blocks, dropout_rate, positional_dropout_rate,\n            self_attention_dropout_rate, src_attention_dropout_rate,\n            input_layer, use_output_layer, normalize_before, concat_after,\n            max_len)\n\n    def forward(\n            self,\n            memory: paddle.Tensor,\n            memory_mask: paddle.Tensor,\n            ys_in_pad: paddle.Tensor,\n            ys_in_lens: paddle.Tensor,\n            r_ys_in_pad: paddle.Tensor,\n            reverse_weight: float=0.0,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Forward decoder.\n        Args:\n            memory: encoded memory, float32  (batch, maxlen_in, feat)\n            memory_mask: encoder memory mask, (batch, 1, maxlen_in)\n            ys_in_pad: padded input token ids, int64 (batch, maxlen_out)\n            ys_in_lens: input lengths of this batch (batch)\n            r_ys_in_pad: padded input token ids, int64 (batch, maxlen_out),\n                used for right to left decoder\n            reverse_weight: used for right to left decoder\n        Returns:\n            (tuple): tuple containing:\n                x: decoded token score before softmax (batch, maxlen_out,\n                    vocab_size) if use_output_layer is True,\n                r_x: x: decoded token score (right to left decoder)\n                    before softmax (batch, maxlen_out, vocab_size)\n                    if use_output_layer is True,\n                olens: (batch, )\n        \"\"\"\n        l_x, _, olens = self.left_decoder(memory, memory_mask, ys_in_pad,\n                                          ys_in_lens)\n        r_x = paddle.zeros([1])\n        if reverse_weight > 0.0:\n            r_x, _, olens = self.right_decoder(memory, memory_mask, r_ys_in_pad,\n                                               ys_in_lens)\n        return l_x, r_x, olens\n\n    def forward_one_step(\n            self,\n            memory: paddle.Tensor,\n            memory_mask: paddle.Tensor,\n            tgt: paddle.Tensor,\n            tgt_mask: paddle.Tensor,\n            cache: Optional[List[paddle.Tensor]]=None,\n    ) -> Tuple[paddle.Tensor, List[paddle.Tensor]]:\n        \"\"\"Forward one step.\n            This is only used for decoding.\n        Args:\n            memory: encoded memory, float32  (batch, maxlen_in, feat)\n            memory_mask: encoded memory mask, (batch, 1, maxlen_in)\n            tgt: input token ids, int64 (batch, maxlen_out)\n            tgt_mask: input token mask,  (batch, maxlen_out, maxlen_out)\n                      dtype=paddle.bool\n            cache: cached output list of (batch, max_time_out-1, size)\n        Returns:\n            y, cache: NN output value and cache per `self.decoders`.\n            y.shape` is (batch, maxlen_out, token)\n        \"\"\"\n        return self.left_decoder.forward_one_step(memory, memory_mask, tgt,\n                                                  tgt_mask, cache)\n"
  },
  {
    "path": "paddlespeech/s2t/modules/decoder_layer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Decoder self-attention layer definition.\"\"\"\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"DecoderLayer\"]\n\n\nclass DecoderLayer(nn.Layer):\n    \"\"\"Single decoder layer module.\n    Args:\n        size (int): Input dimension.\n        self_attn (nn.Layer): Self-attention module instance.\n            `MultiHeadedAttention` instance can be used as the argument.\n        src_attn (nn.Layer): Self-attention module instance.\n            `MultiHeadedAttention` instance can be used as the argument.\n        feed_forward (nn.Layer): Feed-forward module instance.\n            `PositionwiseFeedForward` instance can be used as the argument.\n        dropout_rate (float): Dropout rate.\n        normalize_before (bool):\n            True: use layer_norm before each sub-block.\n            False: to use layer_norm after each sub-block.\n        concat_after (bool): Whether to concat attention layer's input\n            and output.\n            True: x -> x + linear(concat(x, att(x)))\n            False: x -> x + att(x)\n    \"\"\"\n\n    def __init__(\n            self,\n            size: int,\n            self_attn: nn.Layer,\n            src_attn: nn.Layer,\n            feed_forward: nn.Layer,\n            dropout_rate: float,\n            normalize_before: bool=True,\n            concat_after: bool=False, ):\n        \"\"\"Construct an DecoderLayer object.\"\"\"\n        super().__init__()\n        self.size = size\n        self.self_attn = self_attn\n        self.src_attn = src_attn\n        self.feed_forward = feed_forward\n        self.norm1 = LayerNorm(size, epsilon=1e-12)\n        self.norm2 = LayerNorm(size, epsilon=1e-12)\n        self.norm3 = LayerNorm(size, epsilon=1e-12)\n        self.dropout = nn.Dropout(dropout_rate)\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        self.concat_linear1 = Linear(size + size, size)\n        self.concat_linear2 = Linear(size + size, size)\n\n    def forward(\n            self,\n            tgt: paddle.Tensor,\n            tgt_mask: paddle.Tensor,\n            memory: paddle.Tensor,\n            memory_mask: paddle.Tensor,\n            cache: Optional[paddle.Tensor]=None\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute decoded features.\n        Args:\n            tgt (paddle.Tensor): Input tensor (#batch, maxlen_out, size).\n            tgt_mask (paddle.Tensor): Mask for input tensor\n                (#batch, maxlen_out).\n            memory (paddle.Tensor): Encoded memory\n                (#batch, maxlen_in, size).\n            memory_mask (paddle.Tensor): Encoded memory mask\n                (#batch, maxlen_in).\n            cache (paddle.Tensor): cached tensors.\n                (#batch, maxlen_out - 1, size).\n        Returns:\n            paddle.Tensor: Output tensor (#batch, maxlen_out, size).\n            paddle.Tensor: Mask for output tensor (#batch, maxlen_out).\n            paddle.Tensor: Encoded memory (#batch, maxlen_in, size).\n            paddle.Tensor: Encoded memory mask (#batch, maxlen_in).\n        \"\"\"\n        residual = tgt\n        if self.normalize_before:\n            tgt = self.norm1(tgt)\n\n        if cache is None:\n            tgt_q = tgt\n            tgt_q_mask = tgt_mask\n        else:\n            # compute only the last frame query keeping dim: max_time_out -> 1\n            assert cache.shape == [\n                tgt.shape[0],\n                tgt.shape[1] - 1,\n                self.size,\n            ], f\"{cache.shape} == {[tgt.shape[0], tgt.shape[1] - 1, self.size]}\"\n            tgt_q = tgt[:, -1:, :]\n            residual = residual[:, -1:, :]\n            tgt_q_mask = tgt_mask[:, -1:, :]\n\n        if self.concat_after:\n            tgt_concat = paddle.cat(\n                (tgt_q, self.self_attn(tgt_q, tgt, tgt, tgt_q_mask)[0]), dim=-1)\n            x = residual + self.concat_linear1(tgt_concat)\n        else:\n            x = residual + self.dropout(\n                self.self_attn(tgt_q, tgt, tgt, tgt_q_mask)[0])\n        if not self.normalize_before:\n            x = self.norm1(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm2(x)\n        if self.concat_after:\n            x_concat = paddle.cat(\n                (x, self.src_attn(x, memory, memory, memory_mask)[0]), dim=-1)\n            x = residual + self.concat_linear2(x_concat)\n        else:\n            x = residual + self.dropout(\n                self.src_attn(x, memory, memory, memory_mask)[0])\n        if not self.normalize_before:\n            x = self.norm2(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm3(x)\n        x = residual + self.dropout(self.feed_forward(x))\n        if not self.normalize_before:\n            x = self.norm3(x)\n\n        if cache is not None:\n            x = paddle.cat([cache, x], dim=1)\n\n        return x, tgt_mask, memory, memory_mask\n"
  },
  {
    "path": "paddlespeech/s2t/modules/embedding.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Positonal Encoding Module.\"\"\"\nimport math\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"PositionalEncodingInterface\", \"NoPositionalEncoding\", \"PositionalEncoding\",\n    \"RelPositionalEncoding\"\n]\n\n\nclass PositionalEncodingInterface:\n    def forward(self, x: paddle.Tensor,\n                offset: int=0) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute positional encoding.\n        Args:\n            x (paddle.Tensor): Input tensor (batch, time, `*`).\n        Returns:\n            paddle.Tensor: Encoded tensor (batch, time, `*`).\n            paddle.Tensor: Positional embedding tensor (1, time, `*`).\n        \"\"\"\n        raise NotImplementedError(\"forward method is not implemented\")\n\n    def position_encoding(self, offset: int, size: int) -> paddle.Tensor:\n        \"\"\" For getting encoding in a streaming fashion\n        Args:\n            offset (int): start offset\n            size (int): requried size of position encoding\n        Returns:\n            paddle.Tensor: Corresponding position encoding\n        \"\"\"\n        raise NotImplementedError(\"position_encoding method is not implemented\")\n\n\nclass NoPositionalEncoding(nn.Layer, PositionalEncodingInterface):\n    def __init__(self,\n                 d_model: int,\n                 dropout_rate: float,\n                 max_len: int=5000,\n                 reverse: bool=False):\n        nn.Layer.__init__(self)\n\n    def forward(self, x: paddle.Tensor,\n                offset: int=0) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        return x, None\n\n    def position_encoding(self, offset: int, size: int) -> paddle.Tensor:\n        return None\n\n\nclass PositionalEncoding(nn.Layer, PositionalEncodingInterface):\n    def __init__(self,\n                 d_model: int,\n                 dropout_rate: float,\n                 max_len: int=5000,\n                 reverse: bool=False):\n        \"\"\"Positional encoding.\n            PE(pos, 2i)   = sin(pos/(10000^(2i/dmodel)))\n            PE(pos, 2i+1) = cos(pos/(10000^(2i/dmodel)))\n        Args:\n            d_model (int): embedding dim.\n            dropout_rate (float): dropout rate.\n            max_len (int, optional): maximum input length. Defaults to 5000.\n            reverse (bool, optional): Not used. Defaults to False.\n        \"\"\"\n        nn.Layer.__init__(self)\n        self.d_model = paddle.to_tensor(d_model)\n        self.max_len = max_len\n        self.xscale = paddle.to_tensor(math.sqrt(self.d_model))\n        self.dropout = nn.Dropout(p=dropout_rate)\n        self.base = paddle.to_tensor(10000.0)\n        self.pe = paddle.zeros([1, self.max_len, self.d_model])  #[B=1,T,D]\n\n        position = paddle.arange(\n            0, self.max_len, dtype=paddle.float32).unsqueeze(1)  #[T, 1]\n        # base^{-2(i-1)/d)}, i \\in (1,2...,d/2)\n        div_term = paddle.exp(\n            -paddle.arange(0, self.d_model, 2, dtype=paddle.float32) *\n            (paddle.log(self.base) / self.d_model))\n\n        # [B,T,D]\n        self.pe[:, :, 0::2] = paddle.sin(position * div_term)\n        self.pe[:, :, 1::2] = paddle.cos(position * div_term)\n\n    def forward(self, x: paddle.Tensor,\n                offset: int=0) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Add positional encoding.\n        Args:\n            x (paddle.Tensor): Input. Its shape is (batch, time, ...)\n            offset (int): position offset\n        Returns:\n            paddle.Tensor: Encoded tensor. Its shape is (batch, time, ...)\n            paddle.Tensor: for compatibility to RelPositionalEncoding, (batch=1, time, ...)\n        \"\"\"\n        assert offset + x.shape[\n            1] < self.max_len, \"offset: {} + x.shape[1]: {} is larger than the max_len: {}\".format(\n                offset, x.shape[1], self.max_len)\n        pos_emb = self.pe[:, offset:offset + x.shape[1]]\n        x = x * self.xscale + pos_emb\n        return self.dropout(x), self.dropout(pos_emb)\n\n    def position_encoding(self, offset: int, size: int) -> paddle.Tensor:\n        \"\"\" For getting encoding in a streaming fashion\n        Attention!!!!!\n        we apply dropout only once at the whole utterance level in a none\n        streaming way, but will call this function several times with\n        increasing input size in a streaming scenario, so the dropout will\n        be applied several times.\n        Args:\n            offset (int): start offset\n            size (int): requried size of position encoding\n        Returns:\n            paddle.Tensor: Corresponding position encoding, #[1, T, D].\n        \"\"\"\n        assert offset + size < self.max_len\n        return self.dropout(self.pe[:, offset:offset + size])\n\n\nclass RelPositionalEncoding(PositionalEncoding):\n    \"\"\"Relative positional encoding module.\n    See : Appendix B in https://arxiv.org/abs/1901.02860\n    \"\"\"\n\n    def __init__(self, d_model: int, dropout_rate: float, max_len: int=5000):\n        \"\"\"\n        Args:\n            d_model (int): Embedding dimension.\n            dropout_rate (float): Dropout rate.\n            max_len (int, optional): [Maximum input length.]. Defaults to 5000.\n        \"\"\"\n        super().__init__(d_model, dropout_rate, max_len, reverse=True)\n        logger.info(f\"max len: {max_len}\")\n\n    def forward(self, x: paddle.Tensor,\n                offset: int=0) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute positional encoding.\n        Args:\n            x (paddle.Tensor): Input tensor (batch, time, `*`).\n        Returns:\n            paddle.Tensor: Encoded tensor (batch, time, `*`).\n            paddle.Tensor: Positional embedding tensor (1, time, `*`).\n        \"\"\"\n        assert offset + x.shape[\n            1] < self.max_len, \"offset: {} + x.shape[1]: {} is larger than the max_len: {}\".format(\n                offset, x.shape[1], self.max_len)\n\n        x = x * self.xscale\n        pos_emb = self.pe[:, offset:offset + x.shape[1]]\n        return self.dropout(x), self.dropout(pos_emb)\n\n\n# RotaryRelPositionalEncoding is same to RelPositionalEncoding\nclass ScaledRotaryRelPositionalEncoding(RelPositionalEncoding):\n    \"\"\"Scaled Rotary Relative positional encoding module.\n    POSITION INTERPOLATION:  : https://arxiv.org/pdf/2306.15595v2.pdf\n    \"\"\"\n\n    def __init__(self,\n                 d_model: int,\n                 dropout_rate: float,\n                 max_len: int=5000,\n                 scale=1):\n        \"\"\"\n        Args:\n            d_model (int): Embedding dimension.\n            dropout_rate (float): Dropout rate.\n            max_len (int, optional): [Maximum input length.]. Defaults to 5000.\n            scale (int): Interpolation max input length to `scale * max_len` positions.\n        \"\"\"\n        super().__init__(d_model, dropout_rate, max_len, reverse=True)\n        self.pscale = paddle.to_tensor(scale)\n        self.max_len = max_len * scale\n\n    def sinusoidal_embeddings(self,\n                              pos: paddle.Tensor,\n                              dim: paddle.Tensor,\n                              base=10000) -> paddle.Tensor:\n        \"\"\"计算pos位置的dim维sinusoidal编码\"\"\"\n        assert dim % 2 == 0\n        # (d/2,)\n        indices = paddle.arange(0, dim // 2, dtype=pos.dtype)\n        indices = paddle.pow(paddle.cast(base, pos.dtype), -2 * indices / dim)\n        # pos (1, T), indices (d/2,) -> (1, T, d/2)\n        embeddings = paddle.einsum('...,d->...d', pos, indices)\n        # (1, T, d/2, 2)\n        embeddings = paddle.stack(\n            [paddle.sin(embeddings), paddle.cos(embeddings)], axis=-1)\n        # (1, T, d)\n        embeddings = paddle.flatten(embeddings, start_axis=-2, stop_axis=-1)\n        return embeddings\n\n    def forward(self, x: paddle.Tensor,\n                offset: int=0) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute positional encoding.\n        Args:\n            x (paddle.Tensor): Input tensor (batch, time, `*`).\n        Returns:\n            paddle.Tensor: Encoded tensor (batch, time, `*`).\n            paddle.Tensor: Positional embedding tensor (1, time, `*`).\n        \"\"\"\n        x = x * self.xscale\n\n        B, T, D = x.shape\n        assert D == self.d_model\n\n        # postion interploation\n        start = 0\n        end = T * self.pscale\n        assert end <= self.max_len\n        position = paddle.arange(start, end, dtype=x.dtype).unsqueeze(0)\n        position *= 1.0 / self.pscale\n        pe = self.sinusoidal_embeddings(position, self.d_model, base=self.base)\n\n        pos_emb = pe[:, offset:offset + x.shape[1]]\n        return self.dropout(x), self.dropout(pos_emb)\n\n    def position_encoding(self, offset: int, size: int) -> paddle.Tensor:\n        \"\"\" For getting encoding in a streaming fashion\n        Attention!!!!!\n        we apply dropout only once at the whole utterance level in a none\n        streaming way, but will call this function several times with\n        increasing input size in a streaming scenario, so the dropout will\n        be applied several times.\n        Args:\n            offset (int): start offset\n            size (int): requried size of position encoding\n        Returns:\n            paddle.Tensor: Corresponding position encoding, #[1, T, D].\n        \"\"\"\n        # postion interploation\n        start = offset\n        end = (offset + size) * self.pscale\n        assert end <= self.max_len\n        position = paddle.arange(\n            start, end, dtype=paddle.get_default_dtype()).unsqueeze(0)\n        position *= 1.0 / self.pscale\n\n        pe = self.sinusoidal_embeddings(position, self.d_model, base=self.base)\n\n        return self.dropout(pe)\n"
  },
  {
    "path": "paddlespeech/s2t/modules/encoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Encoder definition.\"\"\"\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.s2t.modules.activation import get_activation\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.modules.attention import MultiHeadedAttention\nfrom paddlespeech.s2t.modules.attention import RelPositionMultiHeadedAttention\nfrom paddlespeech.s2t.modules.attention import RoPERelPositionMultiHeadedAttention\nfrom paddlespeech.s2t.modules.conformer_convolution import ConvolutionModule\nfrom paddlespeech.s2t.modules.embedding import NoPositionalEncoding\nfrom paddlespeech.s2t.modules.embedding import PositionalEncoding\nfrom paddlespeech.s2t.modules.embedding import RelPositionalEncoding\nfrom paddlespeech.s2t.modules.encoder_layer import ConformerEncoderLayer\nfrom paddlespeech.s2t.modules.encoder_layer import SqueezeformerEncoderLayer\nfrom paddlespeech.s2t.modules.encoder_layer import TransformerEncoderLayer\nfrom paddlespeech.s2t.modules.mask import add_optional_chunk_mask\nfrom paddlespeech.s2t.modules.mask import make_non_pad_mask\nfrom paddlespeech.s2t.modules.positionwise_feed_forward import PositionwiseFeedForward\nfrom paddlespeech.s2t.modules.subsampling import Conv2dSubsampling4\nfrom paddlespeech.s2t.modules.subsampling import Conv2dSubsampling6\nfrom paddlespeech.s2t.modules.subsampling import Conv2dSubsampling8\nfrom paddlespeech.s2t.modules.subsampling import DepthwiseConv2DSubsampling4\nfrom paddlespeech.s2t.modules.subsampling import LinearNoSubsampling\nfrom paddlespeech.s2t.modules.time_reduction import TimeReductionLayer1D\nfrom paddlespeech.s2t.modules.time_reduction import TimeReductionLayer2D\nfrom paddlespeech.s2t.modules.time_reduction import TimeReductionLayerStream\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"BaseEncoder\", 'TransformerEncoder', \"ConformerEncoder\",\n    \"SqueezeformerEncoder\"\n]\n\n\nclass BaseEncoder(nn.Layer):\n    @typechecked\n    def __init__(self,\n                 input_size: int,\n                 output_size: int=256,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 attention_dropout_rate: float=0.0,\n                 input_layer: str=\"conv2d\",\n                 pos_enc_layer_type: str=\"abs_pos\",\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 static_chunk_size: int=0,\n                 use_dynamic_chunk: bool=False,\n                 global_cmvn: Optional[nn.Layer]=None,\n                 use_dynamic_left_chunk: bool=False,\n                 max_len: int=5000):\n        \"\"\"\n        Args:\n            input_size (int): input dim, d_feature\n            output_size (int): dimension of attention, d_model\n            attention_heads (int): the number of heads of multi head attention\n            linear_units (int): the hidden units number of position-wise feed\n                forward\n            num_blocks (int): the number of encoder blocks\n            dropout_rate (float): dropout rate\n            attention_dropout_rate (float): dropout rate in attention\n            positional_dropout_rate (float): dropout rate after adding\n                positional encoding\n            input_layer (str): input layer type.\n                optional [linear, conv2d, conv2d6, conv2d8]\n            pos_enc_layer_type (str): Encoder positional encoding layer type.\n                opitonal [abs_pos, scaled_abs_pos, rel_pos, no_pos]\n            normalize_before (bool):\n                True: use layer_norm before each sub-block of a layer.\n                False: use layer_norm after each sub-block of a layer.\n            concat_after (bool): whether to concat attention layer's input\n                and output.\n                True: x -> x + linear(concat(x, att(x)))\n                False: x -> x + att(x)\n            static_chunk_size (int): chunk size for static chunk training and\n                decoding\n            use_dynamic_chunk (bool): whether use dynamic chunk size for\n                training or not, You can only use fixed chunk(chunk_size > 0)\n                or dyanmic chunk size(use_dynamic_chunk = True)\n            global_cmvn (Optional[paddle.nn.Layer]): Optional GlobalCMVN layer\n            use_dynamic_left_chunk (bool): whether use dynamic left chunk in\n                dynamic chunk training\n        \"\"\"\n        super().__init__()\n        self._output_size = output_size\n\n        if pos_enc_layer_type == \"abs_pos\":\n            pos_enc_class = PositionalEncoding\n        elif pos_enc_layer_type == \"rel_pos\":\n            pos_enc_class = RelPositionalEncoding\n        elif pos_enc_layer_type == \"rope_pos\":\n            pos_enc_class = RelPositionalEncoding\n        elif pos_enc_layer_type == \"no_pos\":\n            pos_enc_class = NoPositionalEncoding\n        else:\n            raise ValueError(\"unknown pos_enc_layer: \" + pos_enc_layer_type)\n\n        if input_layer == \"linear\":\n            subsampling_class = LinearNoSubsampling\n        elif input_layer == \"conv2d\":\n            subsampling_class = Conv2dSubsampling4\n        elif input_layer == \"conv2d6\":\n            subsampling_class = Conv2dSubsampling6\n        elif input_layer == \"conv2d8\":\n            subsampling_class = Conv2dSubsampling8\n        else:\n            raise ValueError(\"unknown input_layer: \" + input_layer)\n\n        self.global_cmvn = global_cmvn\n        self.embed = subsampling_class(\n            idim=input_size,\n            odim=output_size,\n            dropout_rate=dropout_rate,\n            pos_enc_class=pos_enc_class(\n                d_model=output_size,\n                dropout_rate=positional_dropout_rate,\n                max_len=max_len), )\n\n        self.normalize_before = normalize_before\n        self.after_norm = LayerNorm(output_size, epsilon=1e-12)\n        self.static_chunk_size = static_chunk_size\n        self.use_dynamic_chunk = use_dynamic_chunk\n        self.use_dynamic_left_chunk = use_dynamic_left_chunk\n\n    def output_size(self) -> int:\n        return self._output_size\n\n    def forward(\n            self,\n            xs: paddle.Tensor,\n            xs_lens: paddle.Tensor,\n            decoding_chunk_size: int=0,\n            num_decoding_left_chunks: int=-1,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Embed positions in tensor.\n        Args:\n            xs: padded input tensor (B, L, D)\n            xs_lens: input length (B)\n            decoding_chunk_size: decoding chunk size for dynamic chunk\n                0: default for training, use random dynamic chunk.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n            num_decoding_left_chunks: number of left chunks, this is for decoding,\n                the chunk size is decoding_chunk_size.\n                >=0: use num_decoding_left_chunks\n                <0: use all left chunks\n        Returns:\n            encoder output tensor, lens and mask\n        \"\"\"\n        masks = make_non_pad_mask(xs_lens).unsqueeze(1)  # (B, 1, L)\n\n        if self.global_cmvn is not None:\n            xs = self.global_cmvn(xs)\n        xs, pos_emb, masks = self.embed(xs, masks, offset=0)\n        mask_pad = ~masks\n        chunk_masks = add_optional_chunk_mask(\n            xs, masks, self.use_dynamic_chunk, self.use_dynamic_left_chunk,\n            decoding_chunk_size, self.static_chunk_size,\n            num_decoding_left_chunks)\n        for layer in self.encoders:\n            xs, chunk_masks, _, _ = layer(xs, chunk_masks, pos_emb, mask_pad)\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n        # Here we assume the mask is not changed in encoder layers, so just\n        # return the masks before encoder layers, and the masks will be used\n        # for cross attention with decoder later\n        return xs, masks\n\n    def forward_chunk(\n            self,\n            xs: paddle.Tensor,\n            offset: int,\n            required_cache_size: int,\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            att_mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool)\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\" Forward just one chunk\n        Args:\n            xs (paddle.Tensor): chunk audio feat input, [B=1, T, D], where \n                `T==(chunk_size-1)*subsampling_rate + subsample.right_context + 1`\n            offset (int): current offset in encoder output time stamp\n            required_cache_size (int): cache size required for next chunk\n                compuation\n                >=0: actual cache size\n                <0: means all history cache is required\n            att_cache(paddle.Tensor): cache tensor for key & val in \n                transformer/conformer attention. Shape is \n                (elayers, head, cache_t1, d_k * 2), where`head * d_k == hidden-dim` \n                and `cache_t1 == chunk_size * num_decoding_left_chunks`.\n            cnn_cache (paddle.Tensor): cache tensor for cnn_module in conformer, \n                (elayers, B=1, hidden-dim, cache_t2), where `cache_t2 == cnn.lorder - 1`\n        Returns:\n            paddle.Tensor: output of current input xs, (B=1, chunk_size, hidden-dim)\n            paddle.Tensor: new attention cache required for next chunk, dyanmic shape \n                (elayers, head, T, d_k*2) depending on required_cache_size\n            paddle.Tensor: new conformer cnn cache required for next chunk, with\n                same shape as the original cnn_cache\n        \"\"\"\n        assert xs.shape[0] == 1  # batch size must be one\n        # tmp_masks is just for interface compatibility, [B=1, C=1, T]\n        tmp_masks = paddle.ones([1, 1, xs.shape[1]], dtype=paddle.bool)\n\n        if self.global_cmvn is not None:\n            xs = self.global_cmvn(xs)\n\n        # before embed, xs=(B, T, D1), pos_emb=(B=1, T, D)\n        xs, _, _ = self.embed(xs, tmp_masks, offset=offset)\n        # after embed, xs=(B=1, chunk_size, hidden-dim)\n\n        elayers, _, cache_t1, _ = att_cache.shape\n        chunk_size = xs.shape[1]\n        attention_key_size = cache_t1 + chunk_size\n\n        # only used when using `RelPositionMultiHeadedAttention` and `RoPERelPositionMultiHeadedAttention`\n        pos_emb = self.embed.position_encoding(\n            offset=offset - cache_t1, size=attention_key_size)\n\n        if required_cache_size < 0:\n            next_cache_start = 0\n        elif required_cache_size == 0:\n            next_cache_start = attention_key_size\n        else:\n            next_cache_start = max(attention_key_size - required_cache_size, 0)\n\n        r_att_cache = []\n        r_cnn_cache = []\n        for i, layer in enumerate(self.encoders):\n            # att_cache[i:i+1] = (1, head, cache_t1, d_k*2)\n            # cnn_cache[i:i+1] = (1, B=1, hidden-dim, cache_t2)\n\n            # WARNING: eliminate if-else cond op in graph\n            # tensor zeros([0,0,0,0]) support [i:i+1] slice, will return zeros([0,0,0,0]) tensor\n            # raw code as below:\n            #   att_cache=att_cache[i:i+1] if elayers > 0 else att_cache,\n            #   cnn_cache=cnn_cache[i:i+1] if cnn_cache.shape[0] > 0 else cnn_cache,\n            xs, _, new_att_cache, new_cnn_cache = layer(\n                xs,\n                att_mask,\n                pos_emb,\n                att_cache=att_cache[i:i + 1],\n                cnn_cache=cnn_cache[i:i + 1], )\n            # new_att_cache = (1, head, attention_key_size, d_k*2)\n            # new_cnn_cache = (B=1, hidden-dim, cache_t2)\n            r_att_cache.append(new_att_cache[:, :, next_cache_start:, :])\n            r_cnn_cache.append(new_cnn_cache)  # add elayer dim\n\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n\n        # r_att_cache (elayers, head, T, d_k*2)\n        # r_cnn_cache (elayers, B=1, hidden-dim, cache_t2)\n        r_att_cache = paddle.concat(r_att_cache, axis=0)\n        r_cnn_cache = paddle.stack(r_cnn_cache, axis=0)\n        return xs, r_att_cache, r_cnn_cache\n\n    def forward_chunk_by_chunk(\n            self,\n            xs: paddle.Tensor,\n            decoding_chunk_size: int,\n            num_decoding_left_chunks: int=-1,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\" Forward input chunk by chunk with chunk_size like a streaming\n            fashion\n        Here we should pay special attention to computation cache in the\n        streaming style forward chunk by chunk. Three things should be taken\n        into account for computation in the current network:\n            1. transformer/conformer encoder layers output cache\n            2. convolution in conformer\n            3. convolution in subsampling\n        However, we don't implement subsampling cache for:\n            1. We can control subsampling module to output the right result by\n               overlapping input instead of cache left context, even though it\n               wastes some computation, but subsampling only takes a very\n               small fraction of computation in the whole model.\n            2. Typically, there are several covolution layers with subsampling\n               in subsampling module, it is tricky and complicated to do cache\n               with different convolution layers with different subsampling\n               rate.\n            3. Currently, nn.Sequential is used to stack all the convolution\n               layers in subsampling, we need to rewrite it to make it work\n               with cache, which is not prefered.\n        Args:\n            xs (paddle.Tensor): (1, max_len, dim)\n            chunk_size (int): decoding chunk size.\n            num_left_chunks (int): decoding with num left chunks.\n        \"\"\"\n        assert decoding_chunk_size > 0\n        # The model is trained by static or dynamic chunk\n        assert self.static_chunk_size > 0 or self.use_dynamic_chunk\n\n        # feature stride and window for `subsampling` module\n        subsampling = self.embed.subsampling_rate\n        context = self.embed.right_context + 1  # Add current frame\n        stride = subsampling * decoding_chunk_size\n        decoding_window = (decoding_chunk_size - 1) * subsampling + context\n\n        num_frames = xs.shape[1]\n        required_cache_size = decoding_chunk_size * num_decoding_left_chunks\n\n        att_cache: paddle.Tensor = paddle.zeros([0, 0, 0, 0])\n        cnn_cache: paddle.Tensor = paddle.zeros([0, 0, 0, 0])\n\n        outputs = []\n        offset = 0\n        # Feed forward overlap input step by step\n        for cur in range(0, num_frames - context + 1, stride):\n            end = min(cur + decoding_window, num_frames)\n            chunk_xs = xs[:, cur:end, :]\n\n            (y, att_cache, cnn_cache) = self.forward_chunk(\n                chunk_xs, offset, required_cache_size, att_cache, cnn_cache)\n\n            outputs.append(y)\n            offset += y.shape[1]\n        ys = paddle.cat(outputs, 1)\n        masks = paddle.ones([1, 1, ys.shape[1]], dtype=paddle.bool)\n        return ys, masks\n\n\nclass TransformerEncoder(BaseEncoder):\n    \"\"\"Transformer encoder module.\"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            input_size: int,\n            output_size: int=256,\n            attention_heads: int=4,\n            linear_units: int=2048,\n            num_blocks: int=6,\n            dropout_rate: float=0.1,\n            positional_dropout_rate: float=0.1,\n            attention_dropout_rate: float=0.0,\n            input_layer: str=\"conv2d\",\n            pos_enc_layer_type: str=\"abs_pos\",\n            normalize_before: bool=True,\n            concat_after: bool=False,\n            static_chunk_size: int=0,\n            use_dynamic_chunk: bool=False,\n            global_cmvn: Optional[nn.Layer]=None,\n            use_dynamic_left_chunk: bool=False, ):\n        \"\"\" Construct TransformerEncoder\n        See Encoder for the meaning of each parameter.\n        \"\"\"\n        super().__init__(input_size, output_size, attention_heads, linear_units,\n                         num_blocks, dropout_rate, positional_dropout_rate,\n                         attention_dropout_rate, input_layer,\n                         pos_enc_layer_type, normalize_before, concat_after,\n                         static_chunk_size, use_dynamic_chunk, global_cmvn,\n                         use_dynamic_left_chunk)\n        self.encoders = nn.LayerList([\n            TransformerEncoderLayer(\n                size=output_size,\n                self_attn=MultiHeadedAttention(attention_heads, output_size,\n                                               attention_dropout_rate),\n                feed_forward=PositionwiseFeedForward(output_size, linear_units,\n                                                     dropout_rate),\n                dropout_rate=dropout_rate,\n                normalize_before=normalize_before,\n                concat_after=concat_after) for _ in range(num_blocks)\n        ])\n\n    def forward_one_step(\n            self,\n            xs: paddle.Tensor,\n            masks: paddle.Tensor,\n            cache=None, ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Encode input frame.\n\n        Args:\n            xs (paddle.Tensor): (Prefix) Input tensor. (B, T, D)\n            masks (paddle.Tensor): Mask tensor. (B, T, T)\n            cache (List[paddle.Tensor]): List of cache tensors.\n\n        Returns:\n            paddle.Tensor: Output tensor.\n            paddle.Tensor: Mask tensor.\n            List[paddle.Tensor]: List of new cache tensors.\n        \"\"\"\n        if self.global_cmvn is not None:\n            xs = self.global_cmvn(xs)\n\n        xs, pos_emb, masks = self.embed(xs, masks, offset=0)\n        if cache is None:\n            cache = [None for _ in range(len(self.encoders))]\n        new_cache = []\n        for c, e in zip(cache, self.encoders):\n            xs, masks, _ = e(xs, masks, output_cache=c)\n            new_cache.append(xs)\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n        return xs, masks, new_cache\n\n\nclass ConformerEncoder(BaseEncoder):\n    \"\"\"Conformer encoder module.\"\"\"\n\n    @typechecked\n    def __init__(self,\n                 input_size: int,\n                 output_size: int=256,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 attention_dropout_rate: float=0.0,\n                 input_layer: str=\"conv2d\",\n                 pos_enc_layer_type: str=\"rel_pos\",\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 static_chunk_size: int=0,\n                 use_dynamic_chunk: bool=False,\n                 global_cmvn: Optional[nn.Layer]=None,\n                 use_dynamic_left_chunk: bool=False,\n                 positionwise_conv_kernel_size: int=1,\n                 macaron_style: bool=True,\n                 selfattention_layer_type: str=\"rel_selfattn\",\n                 activation_type: str=\"swish\",\n                 use_cnn_module: bool=True,\n                 cnn_module_kernel: int=15,\n                 causal: bool=False,\n                 cnn_module_norm: str=\"batch_norm\",\n                 max_len: int=5000):\n        \"\"\"Construct ConformerEncoder\n        Args:\n            input_size to use_dynamic_chunk, see in BaseEncoder\n            positionwise_conv_kernel_size (int): Kernel size of positionwise\n                conv1d layer.\n            macaron_style (bool): Whether to use macaron style for\n                positionwise layer.\n            selfattention_layer_type (str): Encoder attention layer type,\n                the parameter has no effect now, it's just for configure\n                compatibility.\n            activation_type (str): Encoder activation function type.\n            use_cnn_module (bool): Whether to use convolution module.\n            cnn_module_kernel (int): Kernel size of convolution module.\n            causal (bool): whether to use causal convolution or not.\n            cnn_module_norm (str): cnn conv norm type, Optional['batch_norm','layer_norm']\n        \"\"\"\n        super().__init__(input_size, output_size, attention_heads, linear_units,\n                         num_blocks, dropout_rate, positional_dropout_rate,\n                         attention_dropout_rate, input_layer,\n                         pos_enc_layer_type, normalize_before, concat_after,\n                         static_chunk_size, use_dynamic_chunk, global_cmvn,\n                         use_dynamic_left_chunk, max_len)\n        activation = get_activation(activation_type)\n\n        # self-attention module definition\n        encoder_dim = output_size\n        if pos_enc_layer_type == \"abs_pos\":\n            encoder_selfattn_layer = MultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, encoder_dim,\n                                           attention_dropout_rate)\n        elif pos_enc_layer_type == \"rel_pos\":\n            encoder_selfattn_layer = RelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, encoder_dim,\n                                           attention_dropout_rate)\n        elif pos_enc_layer_type == \"rope_pos\":\n            encoder_selfattn_layer = RoPERelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, encoder_dim,\n                                           attention_dropout_rate)\n        else:\n            raise ValueError(\n                f\"pos_enc_layer_type {pos_enc_layer_type} not supported.\")\n\n        # feed-forward module definition\n        positionwise_layer = PositionwiseFeedForward\n        positionwise_layer_args = (encoder_dim, linear_units, dropout_rate,\n                                   activation)\n        # convolution module definition\n        convolution_layer = ConvolutionModule\n        convolution_layer_args = (encoder_dim, cnn_module_kernel, activation,\n                                  cnn_module_norm, causal)\n\n        self.encoders = nn.LayerList([\n            ConformerEncoderLayer(\n                size=encoder_dim,\n                self_attn=encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                feed_forward=positionwise_layer(*positionwise_layer_args),\n                feed_forward_macaron=positionwise_layer(\n                    *positionwise_layer_args) if macaron_style else None,\n                conv_module=convolution_layer(*convolution_layer_args)\n                if use_cnn_module else None,\n                dropout_rate=dropout_rate,\n                normalize_before=normalize_before,\n                concat_after=concat_after) for _ in range(num_blocks)\n        ])\n\n\nclass SqueezeformerEncoder(nn.Layer):\n    @typechecked\n    def __init__(self,\n                 input_size: int,\n                 encoder_dim: int=256,\n                 output_size: int=256,\n                 attention_heads: int=4,\n                 num_blocks: int=12,\n                 reduce_idx: Optional[Union[int, List[int]]]=5,\n                 recover_idx: Optional[Union[int, List[int]]]=11,\n                 feed_forward_expansion_factor: int=4,\n                 dw_stride: bool=False,\n                 input_dropout_rate: float=0.1,\n                 pos_enc_layer_type: str=\"rel_pos\",\n                 time_reduction_layer_type: str=\"conv1d\",\n                 feed_forward_dropout_rate: float=0.1,\n                 attention_dropout_rate: float=0.1,\n                 cnn_module_kernel: int=31,\n                 cnn_norm_type: str=\"layer_norm\",\n                 dropout: float=0.1,\n                 causal: bool=False,\n                 adaptive_scale: bool=True,\n                 activation_type: str=\"swish\",\n                 init_weights: bool=True,\n                 global_cmvn: Optional[nn.Layer]=None,\n                 normalize_before: bool=False,\n                 use_dynamic_chunk: bool=False,\n                 concat_after: bool=False,\n                 static_chunk_size: int=0,\n                 use_dynamic_left_chunk: bool=False):\n        \"\"\"Construct SqueezeformerEncoder\n\n        Args:\n            input_size to use_dynamic_chunk, see in Transformer BaseEncoder.\n            encoder_dim (int): The hidden dimension of encoder layer.\n            output_size (int): The output dimension of final projection layer.\n            attention_heads (int): Num of attention head in attention module.\n            num_blocks (int): Num of encoder layers.\n            reduce_idx Optional[Union[int, List[int]]]:\n                reduce layer index, from 40ms to 80ms per frame.\n            recover_idx Optional[Union[int, List[int]]]:\n                recover layer index, from 80ms to 40ms per frame.\n            feed_forward_expansion_factor (int): Enlarge coefficient of FFN.\n            dw_stride (bool): Whether do depthwise convolution\n                              on subsampling module.\n            input_dropout_rate (float): Dropout rate of input projection layer.\n            pos_enc_layer_type (str): Self attention type.\n            time_reduction_layer_type (str): Conv1d or Conv2d reduction layer.\n            cnn_module_kernel (int): Kernel size of CNN module.\n            activation_type (str): Encoder activation function type.\n            cnn_module_kernel (int): Kernel size of convolution module.\n            adaptive_scale (bool): Whether to use adaptive scale.\n            init_weights (bool): Whether to initialize weights.\n            causal (bool): whether to use causal convolution or not.\n        \"\"\"\n        super().__init__()\n        self.global_cmvn = global_cmvn\n        self.reduce_idx: Optional[Union[int, List[int]]] = [reduce_idx] \\\n            if type(reduce_idx) == int else reduce_idx\n        self.recover_idx: Optional[Union[int, List[int]]] = [recover_idx] \\\n            if type(recover_idx) == int else recover_idx\n        self.check_ascending_list()\n        if reduce_idx is None:\n            self.time_reduce = None\n        else:\n            if recover_idx is None:\n                self.time_reduce = 'normal'  # no recovery at the end\n            else:\n                self.time_reduce = 'recover'  # recovery at the end\n                assert len(self.reduce_idx) == len(self.recover_idx)\n            self.reduce_stride = 2\n        self._output_size = output_size\n        self.normalize_before = normalize_before\n        self.static_chunk_size = static_chunk_size\n        self.use_dynamic_chunk = use_dynamic_chunk\n        self.use_dynamic_left_chunk = use_dynamic_left_chunk\n        activation = get_activation(activation_type)\n\n        # self-attention module definition\n        if pos_enc_layer_type == \"abs_pos\":\n            encoder_selfattn_layer = MultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, output_size,\n                                           attention_dropout_rate)\n        elif pos_enc_layer_type == \"rel_pos\":\n            encoder_selfattn_layer = RelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, encoder_dim,\n                                           attention_dropout_rate,\n                                           adaptive_scale, init_weights)\n        elif pos_enc_layer_type == \"rope_pos\":\n            encoder_selfattn_layer = RoPERelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, encoder_dim,\n                                           attention_dropout_rate,\n                                           adaptive_scale, init_weights)\n        else:\n            raise ValueError(\n                f\"pos_enc_layer_type {pos_enc_layer_type} not supported.\")\n\n        # feed-forward module definition\n        positionwise_layer = PositionwiseFeedForward\n        positionwise_layer_args = (\n            encoder_dim, encoder_dim * feed_forward_expansion_factor,\n            feed_forward_dropout_rate, activation, adaptive_scale, init_weights)\n\n        # convolution module definition\n        convolution_layer = ConvolutionModule\n        convolution_layer_args = (encoder_dim, cnn_module_kernel, activation,\n                                  cnn_norm_type, causal, True, adaptive_scale,\n                                  init_weights)\n\n        self.embed = DepthwiseConv2DSubsampling4(\n            1, encoder_dim,\n            RelPositionalEncoding(encoder_dim, dropout_rate=0.1), dw_stride,\n            input_size, input_dropout_rate, init_weights)\n\n        self.preln = LayerNorm(encoder_dim)\n        self.encoders = paddle.nn.LayerList([\n            SqueezeformerEncoderLayer(\n                encoder_dim,\n                encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                positionwise_layer(*positionwise_layer_args),\n                convolution_layer(*convolution_layer_args),\n                positionwise_layer(*positionwise_layer_args), normalize_before,\n                dropout, concat_after) for _ in range(num_blocks)\n        ])\n        if time_reduction_layer_type == 'conv1d':\n            time_reduction_layer = TimeReductionLayer1D\n            time_reduction_layer_args = {\n                'channel': encoder_dim,\n                'out_dim': encoder_dim,\n            }\n        elif time_reduction_layer_type == 'stream':\n            time_reduction_layer = TimeReductionLayerStream\n            time_reduction_layer_args = {\n                'channel': encoder_dim,\n                'out_dim': encoder_dim,\n            }\n        else:\n            time_reduction_layer = TimeReductionLayer2D\n            time_reduction_layer_args = {'encoder_dim': encoder_dim}\n\n        self.time_reduction_layer = time_reduction_layer(\n            **time_reduction_layer_args)\n        self.time_recover_layer = Linear(encoder_dim, encoder_dim)\n        self.final_proj = None\n        if output_size != encoder_dim:\n            self.final_proj = Linear(encoder_dim, output_size)\n\n    def output_size(self) -> int:\n        return self._output_size\n\n    def forward(\n            self,\n            xs: paddle.Tensor,\n            xs_lens: paddle.Tensor,\n            decoding_chunk_size: int=0,\n            num_decoding_left_chunks: int=-1,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Embed positions in tensor.\n        Args:\n            xs: padded input tensor (B, L, D)\n            xs_lens: input length (B)\n            decoding_chunk_size: decoding chunk size for dynamic chunk\n                0: default for training, use random dynamic chunk.\n                <0: for decoding, use full chunk.\n                >0: for decoding, use fixed chunk size as set.\n            num_decoding_left_chunks: number of left chunks, this is for decoding,\n                the chunk size is decoding_chunk_size.\n                >=0: use num_decoding_left_chunks\n                <0: use all left chunks\n        Returns:\n            encoder output tensor, lens and mask\n        \"\"\"\n        masks = make_non_pad_mask(xs_lens).unsqueeze(1)  # (B, 1, L)\n\n        if self.global_cmvn is not None:\n            xs = self.global_cmvn(xs)\n        xs, pos_emb, masks = self.embed(xs, masks)\n        mask_pad = masks\n        chunk_masks = add_optional_chunk_mask(\n            xs, masks, self.use_dynamic_chunk, self.use_dynamic_left_chunk,\n            decoding_chunk_size, self.static_chunk_size,\n            num_decoding_left_chunks)\n        xs_lens = chunk_masks.squeeze(1).sum(1)\n        xs = self.preln(xs)\n        recover_activations: \\\n            List[Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]] = []\n        index = 0\n        for i, layer in enumerate(self.encoders):\n            if self.reduce_idx is not None:\n                if self.time_reduce is not None and i in self.reduce_idx:\n                    recover_activations.append(\n                        (xs, chunk_masks, pos_emb, mask_pad))\n                    xs, xs_lens, chunk_masks, mask_pad = self.time_reduction_layer(\n                        xs, xs_lens, chunk_masks, mask_pad)\n                    pos_emb = pos_emb[:, ::2, :]\n                    index += 1\n\n            if self.recover_idx is not None:\n                if self.time_reduce == 'recover' and i in self.recover_idx:\n                    index -= 1\n                    recover_tensor, recover_chunk_masks, recover_pos_emb, recover_mask_pad = recover_activations[\n                        index]\n                    # recover output length for ctc decode\n                    xs = paddle.repeat_interleave(xs, repeats=2, axis=1)\n                    xs = self.time_recover_layer(xs)\n                    recoverd_t = recover_tensor.shape[1]\n                    xs = recover_tensor + xs[:, :recoverd_t, :]\n                    chunk_masks = recover_chunk_masks\n                    pos_emb = recover_pos_emb\n                    mask_pad = recover_mask_pad\n\n            xs, chunk_masks, _, _ = layer(xs, chunk_masks, pos_emb, mask_pad)\n\n        if self.final_proj is not None:\n            xs = self.final_proj(xs)\n        return xs, masks\n\n    def check_ascending_list(self):\n        if self.reduce_idx is not None:\n            assert self.reduce_idx == sorted(self.reduce_idx), \\\n                \"reduce_idx should be int or ascending list\"\n        if self.recover_idx is not None:\n            assert self.recover_idx == sorted(self.recover_idx), \\\n                \"recover_idx should be int or ascending list\"\n\n    def calculate_downsampling_factor(self, i: int) -> int:\n        if self.reduce_idx is None:\n            return 1\n        else:\n            reduce_exp, recover_exp = 0, 0\n            for exp, rd_idx in enumerate(self.reduce_idx):\n                if i >= rd_idx:\n                    reduce_exp = exp + 1\n            if self.recover_idx is not None:\n                for exp, rc_idx in enumerate(self.recover_idx):\n                    if i >= rc_idx:\n                        recover_exp = exp + 1\n            return int(2**(reduce_exp - recover_exp))\n\n    def forward_chunk(\n            self,\n            xs: paddle.Tensor,\n            offset: int,\n            required_cache_size: int,\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            att_mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\" Forward just one chunk\n\n        Args:\n            xs (paddle.Tensor): chunk input, with shape (b=1, time, mel-dim),\n                where `time == (chunk_size - 1) * subsample_rate + \\\n                        subsample.right_context + 1`\n            offset (int): current offset in encoder output time stamp\n            required_cache_size (int): cache size required for next chunk\n                compuation\n                >=0: actual cache size\n                <0: means all history cache is required\n            att_cache (paddle.Tensor): cache tensor for KEY & VALUE in\n                transformer/conformer attention, with shape\n                (elayers, head, cache_t1, d_k * 2), where\n                `head * d_k == hidden-dim` and\n                `cache_t1 == chunk_size * num_decoding_left_chunks`.\n            cnn_cache (paddle.Tensor): cache tensor for cnn_module in conformer,\n                (elayers, b=1, hidden-dim, cache_t2), where\n                `cache_t2 == cnn.lorder - 1`\n\n        Returns:\n            paddle.Tensor: output of current input xs,\n                with shape (b=1, chunk_size, hidden-dim).\n            paddle.Tensor: new attention cache required for next chunk, with\n                dynamic shape (elayers, head, ?, d_k * 2)\n                depending on required_cache_size.\n            paddle.Tensor: new conformer cnn cache required for next chunk, with\n                same shape as the original cnn_cache.\n        \"\"\"\n        assert xs.shape[0] == 1  # batch size must be one\n\n        if self.global_cmvn is not None:\n            xs = self.global_cmvn(xs)\n\n        # tmp_masks is just for interface compatibility, [B=1, C=1, T]\n        tmp_masks = paddle.ones([1, 1, xs.shape[1]], dtype=paddle.bool)\n        # before embed, xs=(B, T, D1), pos_emb=(B=1, T, D)\n        xs, pos_emb, _ = self.embed(xs, tmp_masks, offset=offset)\n\n        # NOTE(xcsong): After  embed, shape(xs) is (b=1, chunk_size, hidden-dim)\n        elayers, cache_t1 = att_cache.shape[0], att_cache.shape[2]\n        chunk_size = xs.shape[1]\n        attention_key_size = cache_t1 + chunk_size\n        pos_emb = self.embed.position_encoding(\n            offset=offset - cache_t1, size=attention_key_size)\n        if required_cache_size < 0:\n            next_cache_start = 0\n        elif required_cache_size == 0:\n            next_cache_start = attention_key_size\n        else:\n            next_cache_start = max(attention_key_size - required_cache_size, 0)\n\n        r_att_cache = []\n        r_cnn_cache = []\n\n        mask_pad = paddle.ones([1, xs.shape[1]], dtype=paddle.bool)\n        mask_pad = mask_pad.unsqueeze(1)\n        max_att_len: int = 0\n        recover_activations: \\\n            List[Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]] = []\n        index = 0\n        xs_lens = paddle.to_tensor([xs.shape[1]], dtype=paddle.int32)\n        xs = self.preln(xs)\n        for i, layer in enumerate(self.encoders):\n            # NOTE(xcsong): Before layer.forward\n            #   shape(att_cache[i:i + 1]) is (1, head, cache_t1, d_k * 2),\n            #   shape(cnn_cache[i])       is (b=1, hidden-dim, cache_t2)\n            if self.reduce_idx is not None:\n                if self.time_reduce is not None and i in self.reduce_idx:\n                    recover_activations.append(\n                        (xs, att_mask, pos_emb, mask_pad))\n                    xs, xs_lens, att_mask, mask_pad = self.time_reduction_layer(\n                        xs, xs_lens, att_mask, mask_pad)\n                    pos_emb = pos_emb[:, ::2, :]\n                    index += 1\n\n            if self.recover_idx is not None:\n                if self.time_reduce == 'recover' and i in self.recover_idx:\n                    index -= 1\n                    recover_tensor, recover_att_mask, recover_pos_emb, recover_mask_pad = recover_activations[\n                        index]\n                    # recover output length for ctc decode\n                    xs = paddle.repeat_interleave(xs, repeats=2, axis=1)\n                    xs = self.time_recover_layer(xs)\n                    recoverd_t = recover_tensor.shape[1]\n                    xs = recover_tensor + xs[:, :recoverd_t, :]\n                    att_mask = recover_att_mask\n                    pos_emb = recover_pos_emb\n                    mask_pad = recover_mask_pad\n\n            factor = self.calculate_downsampling_factor(i)\n            att_cache1 = att_cache[\n                i:i + 1][:, :, ::factor, :][:, :, :pos_emb.shape[1] - xs.shape[\n                    1], :]\n            cnn_cache1 = cnn_cache[i] if cnn_cache.shape[0] > 0 else cnn_cache\n            xs, _, new_att_cache, new_cnn_cache = layer(\n                xs,\n                att_mask,\n                pos_emb,\n                att_cache=att_cache1,\n                cnn_cache=cnn_cache1)\n            # NOTE(xcsong): After layer.forward\n            #   shape(new_att_cache) is (1, head, attention_key_size, d_k * 2),\n            #   shape(new_cnn_cache) is (b=1, hidden-dim, cache_t2)\n            cached_att = new_att_cache[:, :, next_cache_start // factor:, :]\n            cached_cnn = new_cnn_cache.unsqueeze(0)\n            cached_att = cached_att.repeat_interleave(repeats=factor, axis=2)\n            if i == 0:\n                # record length for the first block as max length\n                max_att_len = cached_att.shape[2]\n            r_att_cache.append(cached_att[:, :, :max_att_len, :])\n            r_cnn_cache.append(cached_cnn)\n        # NOTE(xcsong): shape(r_att_cache) is (elayers, head, ?, d_k * 2),\n        #   ? may be larger than cache_t1, it depends on required_cache_size\n        r_att_cache = paddle.concat(r_att_cache, axis=0)\n        # NOTE(xcsong): shape(r_cnn_cache) is (e, b=1, hidden-dim, cache_t2)\n        r_cnn_cache = paddle.concat(r_cnn_cache, axis=0)\n\n        if self.final_proj is not None:\n            xs = self.final_proj(xs)\n        return xs, r_att_cache, r_cnn_cache\n"
  },
  {
    "path": "paddlespeech/s2t/modules/encoder_layer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Encoder self-attention layer definition.\"\"\"\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"TransformerEncoderLayer\", \"ConformerEncoderLayer\",\n    \"SqueezeformerEncoderLayer\"\n]\n\n\nclass TransformerEncoderLayer(nn.Layer):\n    \"\"\"Encoder layer module.\"\"\"\n\n    def __init__(\n            self,\n            size: int,\n            self_attn: nn.Layer,\n            feed_forward: nn.Layer,\n            dropout_rate: float,\n            normalize_before: bool=True,\n            concat_after: bool=False, ):\n        \"\"\"Construct an EncoderLayer object.\n\n        Args:\n            size (int): Input dimension.\n            self_attn (nn.Layer): Self-attention module instance.\n                `MultiHeadedAttention`, `RelPositionMultiHeadedAttention` or `RoPERelPositionMultiHeadedAttention`\n                instance can be used as the argument.\n            feed_forward (nn.Layer): Feed-forward module instance.\n                `PositionwiseFeedForward`, instance can be used as the argument.\n            dropout_rate (float): Dropout rate.\n            normalize_before (bool):\n                True: use layer_norm before each sub-block.\n                False: to use layer_norm after each sub-block.\n            concat_after (bool): Whether to concat attention layer's input and\n                output.\n                True: x -> x + linear(concat(x, att(x)))\n                False: x -> x + att(x)\n        \"\"\"\n        super().__init__()\n        self.self_attn = self_attn\n        self.feed_forward = feed_forward\n        self.norm1 = LayerNorm(size, epsilon=1e-12)\n        self.norm2 = LayerNorm(size, epsilon=1e-12)\n        self.dropout = nn.Dropout(dropout_rate)\n        self.size = size\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        # concat_linear may be not used in forward fuction,\n        # but will be saved in the *.pt\n        self.concat_linear = Linear(size + size, size)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            mask: paddle.Tensor,\n            pos_emb: paddle.Tensor,\n            mask_pad: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute encoded features.\n        Args:\n            x (paddle.Tensor): (#batch, time, size)\n            mask (paddle.Tensor): Mask tensor for the input (#batch, time，time),\n                (0, 0, 0) means fake mask.\n            pos_emb (paddle.Tensor): just for interface compatibility\n                to ConformerEncoderLayer\n            mask_pad (paddle.Tensor): does not used in transformer layer,\n                just for unified api with conformer.\n            att_cache (paddle.Tensor): Cache tensor of the KEY & VALUE\n                (#batch=1, head, cache_t1, d_k * 2), head * d_k == size.\n            cnn_cache (paddle.Tensor): Convolution cache in conformer layer\n                (#batch=1, size, cache_t2), not used here, it's for interface\n                compatibility to ConformerEncoderLayer.\n        Returns:\n            paddle.Tensor: Output tensor (#batch, time, size).\n            paddle.Tensor: Mask tensor (#batch, time, time).\n            paddle.Tensor: att_cache tensor,\n                (#batch=1, head, cache_t1 + time, d_k * 2).\n            paddle.Tensor: cnn_cahce tensor (#batch=1, size, cache_t2).\n        \"\"\"\n        residual = x\n        if self.normalize_before:\n            x = self.norm1(x)\n\n        x_att, new_att_cache = self.self_attn(x, x, x, mask, cache=att_cache)\n\n        if self.concat_after:\n            x_concat = paddle.concat((x, x_att), axis=-1)\n            x = residual + self.concat_linear(x_concat)\n        else:\n            x = residual + self.dropout(x_att)\n        if not self.normalize_before:\n            x = self.norm1(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm2(x)\n        x = residual + self.dropout(self.feed_forward(x))\n        if not self.normalize_before:\n            x = self.norm2(x)\n\n        fake_cnn_cache = paddle.zeros([0, 0, 0], dtype=x.dtype)\n        return x, mask, new_att_cache, fake_cnn_cache\n\n\nclass ConformerEncoderLayer(nn.Layer):\n    \"\"\"Encoder layer module.\"\"\"\n\n    def __init__(\n            self,\n            size: int,\n            self_attn: nn.Layer,\n            feed_forward: Optional[nn.Layer]=None,\n            feed_forward_macaron: Optional[nn.Layer]=None,\n            conv_module: Optional[nn.Layer]=None,\n            dropout_rate: float=0.1,\n            normalize_before: bool=True,\n            concat_after: bool=False, ):\n        \"\"\"Construct an EncoderLayer object.\n\n        Args:\n            size (int): Input dimension.\n            self_attn (nn.Layer): Self-attention module instance.\n                `MultiHeadedAttention`, `RelPositionMultiHeadedAttention` or `RoPERelPositionMultiHeadedAttention`\n                instance can be used as the argument.\n            feed_forward (nn.Layer): Feed-forward module instance.\n                `PositionwiseFeedForward` instance can be used as the argument.\n            feed_forward_macaron (nn.Layer): Additional feed-forward module\n                instance.\n                `PositionwiseFeedForward` instance can be used as the argument.\n            conv_module (nn.Layer): Convolution module instance.\n                `ConvlutionModule` instance can be used as the argument.\n            dropout_rate (float): Dropout rate.\n            normalize_before (bool):\n                True: use layer_norm before each sub-block.\n                False: use layer_norm after each sub-block.\n            concat_after (bool): Whether to concat attention layer's input and\n                output.\n                True: x -> x + linear(concat(x, att(x)))\n                False: x -> x + att(x)\n        \"\"\"\n        super().__init__()\n        self.self_attn = self_attn\n        self.feed_forward = feed_forward\n        self.feed_forward_macaron = feed_forward_macaron\n        self.conv_module = conv_module\n        self.norm_ff = LayerNorm(size, epsilon=1e-12)  # for the FNN module\n        self.norm_mha = LayerNorm(size, epsilon=1e-12)  # for the MHA module\n        if feed_forward_macaron is not None:\n            self.norm_ff_macaron = LayerNorm(size, epsilon=1e-12)\n            self.ff_scale = 0.5\n        else:\n            self.ff_scale = 1.0\n        if self.conv_module is not None:\n            self.norm_conv = LayerNorm(\n                size, epsilon=1e-12)  # for the CNN module\n            self.norm_final = LayerNorm(\n                size, epsilon=1e-12)  # for the final output of the block\n        self.dropout = nn.Dropout(dropout_rate)\n        self.size = size\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        if self.concat_after:\n            self.concat_linear = Linear(size + size, size)\n        else:\n            self.concat_linear = nn.Identity()\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            mask: paddle.Tensor,\n            pos_emb: paddle.Tensor,\n            mask_pad: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0])\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute encoded features.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, size).\n            mask (paddle.Tensor): Mask tensor for the input (#batch, time, time).\n                (0,0,0) means fake mask.\n            pos_emb (paddle.Tensor): postional encoding, must not be None \n                for ConformerEncoderLayer\n            mask_pad (paddle.Tensor): batch padding mask used for conv module.\n               (#batch, 1，time), (0, 0, 0) means fake mask.\n            att_cache (paddle.Tensor): Cache tensor of the KEY & VALUE\n                (#batch=1, head, cache_t1, d_k * 2), head * d_k == size.\n            cnn_cache (paddle.Tensor): Convolution cache in conformer layer\n                (1, #batch=1, size, cache_t2). First dim will not be used, just\n                for dy2st.\n        Returns:\n           paddle.Tensor: Output tensor (#batch, time, size).\n           paddle.Tensor: Mask tensor (#batch, time, time).\n           paddle.Tensor: att_cache tensor,\n                (#batch=1, head, cache_t1 + time, d_k * 2).\n           paddle.Tensor: cnn_cahce tensor (#batch, size, cache_t2).\n        \"\"\"\n        # (1, #batch=1, size, cache_t2) -> (#batch=1, size, cache_t2)\n        cnn_cache = paddle.squeeze(cnn_cache, axis=0)\n\n        # whether to use macaron style FFN\n        if self.feed_forward_macaron is not None:\n            residual = x\n            if self.normalize_before:\n                x = self.norm_ff_macaron(x)\n            x = residual + self.ff_scale * self.dropout(\n                self.feed_forward_macaron(x))\n            if not self.normalize_before:\n                x = self.norm_ff_macaron(x)\n\n        # multi-headed self-attention module\n        residual = x\n        if self.normalize_before:\n            x = self.norm_mha(x)\n\n        x_att, new_att_cache = self.self_attn(\n            x, x, x, mask, pos_emb, cache=att_cache)\n\n        if self.concat_after:\n            x_concat = paddle.concat((x, x_att), axis=-1)\n            x = residual + self.concat_linear(x_concat)\n        else:\n            x = residual + self.dropout(x_att)\n\n        if not self.normalize_before:\n            x = self.norm_mha(x)\n\n        # convolution module\n        # Fake new cnn cache here, and then change it in conv_module\n        new_cnn_cache = paddle.zeros([0, 0, 0], dtype=x.dtype)\n        if self.conv_module is not None:\n            residual = x\n            if self.normalize_before:\n                x = self.norm_conv(x)\n\n            x, new_cnn_cache = self.conv_module(x, mask_pad, cnn_cache)\n            x = residual + self.dropout(x)\n\n            if not self.normalize_before:\n                x = self.norm_conv(x)\n\n        # feed forward module\n        residual = x\n        if self.normalize_before:\n            x = self.norm_ff(x)\n\n        x = residual + self.ff_scale * self.dropout(self.feed_forward(x))\n\n        if not self.normalize_before:\n            x = self.norm_ff(x)\n\n        if self.conv_module is not None:\n            x = self.norm_final(x)\n\n        return x, mask, new_att_cache, new_cnn_cache\n\n\nclass SqueezeformerEncoderLayer(nn.Layer):\n    \"\"\"Encoder layer module.\"\"\"\n\n    def __init__(self,\n                 size: int,\n                 self_attn: paddle.nn.Layer,\n                 feed_forward1: Optional[nn.Layer]=None,\n                 conv_module: Optional[nn.Layer]=None,\n                 feed_forward2: Optional[nn.Layer]=None,\n                 normalize_before: bool=False,\n                 dropout_rate: float=0.1,\n                 concat_after: bool=False):\n        \"\"\"Construct an EncoderLayer object.\n\n        Args:\n            size (int): Input dimension.\n            self_attn (paddle.nn.Layer): Self-attention module instance.\n                `MultiHeadedAttention`, `RelPositionMultiHeadedAttention` or `RoPERelPositionMultiHeadedAttention`\n                instance can be used as the argument.\n            feed_forward1 (paddle.nn.Layer): Feed-forward module instance.\n                `PositionwiseFeedForward` instance can be used as the argument.\n            conv_module (paddle.nn.Layer): Convolution module instance.\n                `ConvlutionLayer` instance can be used as the argument.\n            feed_forward2 (paddle.nn.Layer): Feed-forward module instance.\n                `PositionwiseFeedForward` instance can be used as the argument.\n            dropout_rate (float): Dropout rate.\n            normalize_before (bool):\n                True: use layer_norm before each sub-block.\n                False: use layer_norm after each sub-block.\n        \"\"\"\n        super().__init__()\n        self.size = size\n        self.self_attn = self_attn\n        self.layer_norm1 = LayerNorm(size)\n        self.ffn1 = feed_forward1\n        self.layer_norm2 = LayerNorm(size)\n        self.conv_module = conv_module\n        self.layer_norm3 = LayerNorm(size)\n        self.ffn2 = feed_forward2\n        self.layer_norm4 = LayerNorm(size)\n        self.normalize_before = normalize_before\n        self.dropout = nn.Dropout(dropout_rate)\n        self.concat_after = concat_after\n        if concat_after:\n            self.concat_linear = Linear(size + size, size)\n        else:\n            self.concat_linear = nn.Identity()\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            mask: paddle.Tensor,\n            pos_emb: paddle.Tensor,\n            mask_pad: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n            att_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n            cnn_cache: paddle.Tensor=paddle.zeros([0, 0, 0, 0]),\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Compute encoded features.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, size).\n            mask (paddle.Tensor): Mask tensor for the input (#batch, time, time).\n                (0,0,0) means fake mask.\n            pos_emb (paddle.Tensor): postional encoding, must not be None\n                for ConformerEncoderLayer\n            mask_pad (paddle.Tensor): batch padding mask used for conv module.\n               (#batch, 1，time), (0, 0, 0) means fake mask.\n            att_cache (paddle.Tensor): Cache tensor of the KEY & VALUE\n                (#batch=1, head, cache_t1, d_k * 2), head * d_k == size.\n            cnn_cache (paddle.Tensor): Convolution cache in conformer layer\n                (1, #batch=1, size, cache_t2). First dim will not be used, just\n                for dy2st.\n        Returns:\n           paddle.Tensor: Output tensor (#batch, time, size).\n           paddle.Tensor: Mask tensor (#batch, time, time).\n           paddle.Tensor: att_cache tensor,\n                (#batch=1, head, cache_t1 + time, d_k * 2).\n           paddle.Tensor: cnn_cahce tensor (#batch, size, cache_t2).\n        \"\"\"\n        # self attention module\n        residual = x\n        if self.normalize_before:\n            x = self.layer_norm1(x)\n        x_att, new_att_cache = self.self_attn(x, x, x, mask, pos_emb, att_cache)\n        if self.concat_after:\n            x_concat = paddle.concat((x, x_att), axis=-1)\n            x = residual + self.concat_linear(x_concat)\n        else:\n            x = residual + self.dropout(x_att)\n        if not self.normalize_before:\n            x = self.layer_norm1(x)\n\n        # ffn module\n        residual = x\n        if self.normalize_before:\n            x = self.layer_norm2(x)\n        x = self.ffn1(x)\n        x = residual + self.dropout(x)\n        if not self.normalize_before:\n            x = self.layer_norm2(x)\n\n        # conv module\n        residual = x\n        if self.normalize_before:\n            x = self.layer_norm3(x)\n        x, new_cnn_cache = self.conv_module(x, mask_pad, cnn_cache)\n        x = residual + self.dropout(x)\n        if not self.normalize_before:\n            x = self.layer_norm3(x)\n\n        # ffn module\n        residual = x\n        if self.normalize_before:\n            x = self.layer_norm4(x)\n        x = self.ffn2(x)\n        # we do not use dropout here since it is inside feed forward function\n        x = residual + self.dropout(x)\n        if not self.normalize_before:\n            x = self.layer_norm4(x)\n\n        return x, mask, new_att_cache, new_cnn_cache\n"
  },
  {
    "path": "paddlespeech/s2t/modules/fbank.py",
    "content": "import paddle\nfrom paddle import nn\n\nfrom paddlespeech.audio.compliance import kaldi\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = ['KaldiFbank']\n\n\nclass KaldiFbank(nn.Layer):\n    def __init__(\n            self,\n            fs=16000,\n            n_mels=80,\n            n_shift=160,  # unit:sample, 10ms\n            win_length=400,  # unit:sample, 25ms\n            energy_floor=0.0,\n            dither=0.0):\n        \"\"\"\n        Args:\n            fs (int): sample rate of the audio\n            n_mels (int): number of mel filter banks\n            n_shift (int): number of points in a frame shift\n            win_length (int): number of points in a frame windows\n            energy_floor (float): Floor on energy in Spectrogram computation (absolute)\n            dither (float): Dithering constant. Default 0.0\n        \"\"\"\n        super().__init__()\n        self.fs = fs\n        self.n_mels = n_mels\n        num_point_ms = fs / 1000\n        self.n_frame_length = win_length / num_point_ms\n        self.n_frame_shift = n_shift / num_point_ms\n        self.energy_floor = energy_floor\n        self.dither = dither\n\n    def __repr__(self):\n        return (\n            \"{name}(fs={fs}, n_mels={n_mels}, \"\n            \"n_frame_shift={n_frame_shift}, n_frame_length={n_frame_length}, \"\n            \"dither={dither}))\".format(\n                name=self.__class__.__name__,\n                fs=self.fs,\n                n_mels=self.n_mels,\n                n_frame_shift=self.n_frame_shift,\n                n_frame_length=self.n_frame_length,\n                dither=self.dither, ))\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"\n        Args:\n            x (paddle.Tensor): shape (Ti). \n                Not support: [Time, Channel] and Batch mode.\n\n        Returns:\n            paddle.Tensor: (T, D)\n        \"\"\"\n        assert x.ndim == 1\n\n        feat = kaldi.fbank(\n            x.unsqueeze(0),  # append channel dim, (C, Ti)\n            n_mels=self.n_mels,\n            frame_length=self.n_frame_length,\n            frame_shift=self.n_frame_shift,\n            dither=self.dither,\n            energy_floor=self.energy_floor,\n            sr=self.fs)\n\n        assert feat.ndim == 2  # (T,D)\n        return feat\n"
  },
  {
    "path": "paddlespeech/s2t/modules/initializer.py",
    "content": "#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nclass DefaultInitializerContext(object):\n    \"\"\"\n        egs:\n        with DefaultInitializerContext(\"kaiming_uniform\"):\n            code for setup_model\n    \"\"\"\n\n    def __init__(self, init_type=None):\n        self.init_type = init_type\n\n    def __enter__(self):\n        if self.init_type is None:\n            return\n        else:\n            from paddlespeech.s2t.modules import align\n            align.global_init_type = self.init_type\n            return\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        from paddlespeech.s2t.modules import align\n        align.global_init_type = None\n"
  },
  {
    "path": "paddlespeech/s2t/modules/loss.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nimport inspect\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = ['CTCLoss', \"LabelSmoothingLoss\"]\n\n\nclass CTCLoss(nn.Layer):\n    def __init__(self,\n                 blank=0,\n                 reduction='sum',\n                 batch_average=False,\n                 grad_norm_type=None):\n        super().__init__()\n        # last token id as blank id\n        self.loss = nn.CTCLoss(blank=blank, reduction=reduction)\n        self.batch_average = batch_average\n\n        logger.debug(\n            f\"CTCLoss Loss reduction: {reduction}, div-bs: {batch_average}\")\n        logger.debug(f\"CTCLoss Grad Norm Type: {grad_norm_type}\")\n\n        assert grad_norm_type in ('instance', 'batch', 'frame', None)\n        self.norm_by_times = False\n        self.norm_by_batchsize = False\n        self.norm_by_total_logits_len = False\n        if grad_norm_type is None:\n            # no grad norm\n            pass\n        elif grad_norm_type == 'instance':\n            self.norm_by_times = True\n        elif grad_norm_type == 'batch':\n            self.norm_by_batchsize = True\n        elif grad_norm_type == 'frame':\n            self.norm_by_total_logits_len = True\n        else:\n            raise ValueError(f\"CTCLoss Grad Norm no support {grad_norm_type}\")\n        kwargs = {\n            \"norm_by_times\": self.norm_by_times,\n            \"norm_by_batchsize\": self.norm_by_batchsize,\n            \"norm_by_total_logits_len\": self.norm_by_total_logits_len,\n        }\n\n        # Derive only the args which the func has\n        try:\n            param = inspect.signature(self.loss.forward).parameters\n        except ValueError:\n            # Some function, e.g. built-in function, are failed\n            param = {}\n        self._kwargs = {k: v for k, v in kwargs.items() if k in param}\n        _notin = {k: v for k, v in kwargs.items() if k not in param}\n        logger.debug(\n            f\"{self.loss} kwargs:{self._kwargs}, not support: {_notin}\")\n\n    def forward(self, logits, ys_pad, hlens, ys_lens):\n        \"\"\"Compute CTC loss.\n\n        Args:\n            logits ([paddle.Tensor]): [B, Tmax, D]\n            ys_pad ([paddle.Tensor]): [B, Tmax]\n            hlens ([paddle.Tensor]): [B]\n            ys_lens ([paddle.Tensor]): [B]\n\n        Returns:\n            [paddle.Tensor]: scalar. If reduction is 'none', then (N), where N = \\text{batch size}.\n        \"\"\"\n        B = logits.shape[0]\n        # warp-ctc need logits, and do softmax on logits by itself\n        # warp-ctc need activation with shape [T, B, V + 1]\n        # logits: (B, L, D) -> (L, B, D)\n        logits = logits.transpose([1, 0, 2])\n        ys_pad = ys_pad.astype(paddle.int32)\n        loss = self.loss(logits, ys_pad, hlens, ys_lens, **self._kwargs)\n        if self.batch_average:\n            # Batch-size average\n            loss = loss / B\n        return loss\n\n\nclass LabelSmoothingLoss(nn.Layer):\n    \"\"\"Label-smoothing loss.\n    In a standard CE loss, the label's data distribution is:\n        [0,1,2] ->\n        [\n            [1.0, 0.0, 0.0],\n            [0.0, 1.0, 0.0],\n            [0.0, 0.0, 1.0],\n        ]\n    In the smoothing version CE Loss,some probabilities\n    are taken from the true label prob (1.0) and are divided\n    among other labels.\n        e.g.\n        smoothing=0.1\n        [0,1,2] ->\n        [\n            [0.9, 0.05, 0.05],\n            [0.05, 0.9, 0.05],\n            [0.05, 0.05, 0.9],\n        ]\n\n    \"\"\"\n\n    def __init__(self,\n                 size: int,\n                 padding_idx: int,\n                 smoothing: float,\n                 normalize_length: bool=False):\n        \"\"\"Label-smoothing loss.\n\n        Args:\n            size (int): the number of class\n            padding_idx (int): padding class id which will be ignored for loss\n            smoothing (float): smoothing rate (0.0 means the conventional CE)\n            normalize_length (bool):\n                True, normalize loss by sequence length;\n                False, normalize loss by batch size.\n                Defaults to False.\n        \"\"\"\n        super().__init__()\n        self.size = size\n        self.padding_idx = padding_idx\n        self.smoothing = smoothing\n        self.confidence = 1.0 - smoothing\n        self.normalize_length = normalize_length\n        self.criterion = nn.KLDivLoss(reduction=\"none\")\n\n    def forward(self, x: paddle.Tensor, target: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Compute loss between x and target.\n        The model outputs and data labels tensors are flatten to\n        (batch*seqlen, class) shape and a mask is applied to the\n        padding part which should not be calculated for loss.\n\n        Args:\n            x (paddle.Tensor): prediction (batch, seqlen, class)\n            target (paddle.Tensor):\n                target signal masked with self.padding_id (batch, seqlen)\n        Returns:\n            loss (paddle.Tensor) : The KL loss, scalar float value\n        \"\"\"\n        B, T, D = x.shape\n        assert D == self.size\n        x = x.reshape((-1, self.size))\n        target = target.reshape([-1])\n\n        # use zeros_like instead of torch.no_grad() for true_dist,\n        # since no_grad() can not be exported by JIT\n        true_dist = paddle.full_like(x, self.smoothing / (self.size - 1))\n        ignore = target == self.padding_idx  # (B,)\n\n        #TODO(Hui Zhang): target = target * (1 - ignore)  # avoid -1 index\n        target = target.masked_fill(ignore, 0)  # avoid -1 index\n        # true_dist.scatter_(1, target.unsqueeze(1), self.confidence)\n        target_mask = F.one_hot(target, self.size)\n        true_dist *= (1 - target_mask)\n        true_dist += target_mask * self.confidence\n\n        kl = self.criterion(F.log_softmax(x, axis=1), true_dist)\n\n        #TODO(Hui Zhang): sum not support bool type\n        #total = len(target) - int(ignore.sum())\n        total = len(target) - int(ignore.type_as(target).sum())\n        denom = total if self.normalize_length else B\n        #numer = (kl * (1 - ignore)).sum()\n        numer = kl.masked_fill(ignore.unsqueeze(1), 0).sum()\n        return numer / denom\n"
  },
  {
    "path": "paddlespeech/s2t/modules/mask.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nimport paddle\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"make_xs_mask\", \"make_pad_mask\", \"make_non_pad_mask\", \"subsequent_mask\",\n    \"subsequent_chunk_mask\", \"add_optional_chunk_mask\", \"mask_finished_scores\",\n    \"mask_finished_preds\"\n]\n\n\ndef make_xs_mask(xs: paddle.Tensor, pad_value=0.0) -> paddle.Tensor:\n    \"\"\"Maks mask tensor containing indices of non-padded part.\n    Args:\n        xs (paddle.Tensor): (B, T, D), zeros for pad.\n    Returns:\n        paddle.Tensor: Mask Tensor indices of non-padded part. (B, T)\n    \"\"\"\n    pad_frame = paddle.full([1, 1, xs.shape[-1]], pad_value, dtype=xs.dtype)\n    mask = xs != pad_frame\n    mask = mask.all(axis=-1)\n    return mask\n\n\ndef make_pad_mask(lengths: paddle.Tensor) -> paddle.Tensor:\n    \"\"\"Make mask tensor containing indices of padded part.\n    See description of make_non_pad_mask.\n    Args:\n        lengths (paddle.Tensor): Batch of lengths (B,).\n    Returns:\n        paddle.Tensor: Mask tensor containing indices of padded part.\n        (B, T)\n    Examples:\n        >>> lengths = [5, 3, 2]\n        >>> make_pad_mask(lengths)\n        masks = [[0, 0, 0, 0 ,0],\n                 [0, 0, 0, 1, 1],\n                 [0, 0, 1, 1, 1]]\n    \"\"\"\n    # (TODO: Hui Zhang): jit not support Tensor.dim() and Tensor.ndim\n    # assert lengths.dim() == 1\n    batch_size = int(lengths.shape[0])\n    max_len = int(lengths.max())\n    seq_range = paddle.arange(0, max_len, dtype=paddle.int64)\n    seq_range_expand = seq_range.unsqueeze(0).expand([batch_size, max_len])\n    seq_length_expand = lengths.unsqueeze(-1)\n    mask = seq_range_expand >= seq_length_expand\n    return mask\n\n\ndef make_non_pad_mask(lengths: paddle.Tensor) -> paddle.Tensor:\n    \"\"\"Make mask tensor containing indices of non-padded part.\n    The sequences in a batch may have different lengths. To enable\n    batch computing, padding is need to make all sequence in same\n    size. To avoid the padding part pass value to context dependent\n    block such as attention or convolution , this padding part is\n    masked.\n    This pad_mask is used in both encoder and decoder.\n    1 for non-padded part and 0 for padded part.\n    Args:\n        lengths (paddle.Tensor): Batch of lengths (B,).\n    Returns:\n        paddle.Tensor: mask tensor containing indices of padded part.\n        (B, T)\n    Examples:\n        >>> lengths = [5, 3, 2]\n        >>> make_non_pad_mask(lengths)\n        masks = [[1, 1, 1, 1 ,1],\n                 [1, 1, 1, 0, 0],\n                 [1, 1, 0, 0, 0]]\n    \"\"\"\n    #return ~make_pad_mask(lengths)\n    return make_pad_mask(lengths).logical_not()\n\n\ndef subsequent_mask(size: int) -> paddle.Tensor:\n    \"\"\"Create mask for subsequent steps (size, size).\n    This mask is used only in decoder which works in an auto-regressive mode.\n    This means the current step could only do attention with its left steps.\n    In encoder, fully attention is used when streaming is not necessary and\n    the sequence is not long. In this case, no attention mask is needed.\n    When streaming is need, chunk-based attention is used in encoder. See\n    subsequent_chunk_mask for the chunk-based attention mask.\n    Args:\n        size (int): size of mask\n    Returns:\n        paddle.Tensor: mask, [size, size]\n    Examples:\n        >>> subsequent_mask(3)\n        [[1, 0, 0],\n         [1, 1, 0],\n         [1, 1, 1]]\n    \"\"\"\n    ret = paddle.ones([size, size], dtype=paddle.bool)\n    return paddle.tril(ret)\n\n\ndef subsequent_chunk_mask(\n        size: int,\n        chunk_size: int,\n        num_left_chunks: int=-1, ) -> paddle.Tensor:\n    \"\"\"Create mask for subsequent steps (size, size) with chunk size,\n       this is for streaming encoder\n    Args:\n        size (int): size of mask\n        chunk_size (int): size of chunk\n        num_left_chunks (int): number of left chunks\n            <0: use full chunk\n            >=0: use num_left_chunks\n    Returns:\n        paddle.Tensor: mask, [size, size]\n    Examples:\n        >>> subsequent_chunk_mask(4, 2)\n        [[1, 1, 0, 0],\n         [1, 1, 0, 0],\n         [1, 1, 1, 1],\n         [1, 1, 1, 1]]\n    \"\"\"\n    ret = paddle.zeros([size, size], dtype=paddle.bool)\n    for i in range(size):\n        if num_left_chunks < 0:\n            start = 0\n        else:\n            start = max(0, (i // chunk_size - num_left_chunks) * chunk_size)\n        ending = min(size, (i // chunk_size + 1) * chunk_size)\n        ret[i, start:ending] = True\n    return ret\n\n\ndef add_optional_chunk_mask(xs: paddle.Tensor,\n                            masks: paddle.Tensor,\n                            use_dynamic_chunk: bool,\n                            use_dynamic_left_chunk: bool,\n                            decoding_chunk_size: int,\n                            static_chunk_size: int,\n                            num_decoding_left_chunks: int):\n    \"\"\" Apply optional mask for encoder.\n    Args:\n        xs (paddle.Tensor): padded input, (B, L, D), L for max length\n        mask (paddle.Tensor): mask for xs, (B, 1, L)\n        use_dynamic_chunk (bool): whether to use dynamic chunk or not\n        use_dynamic_left_chunk (bool): whether to use dynamic left chunk for\n            training.\n        decoding_chunk_size (int): decoding chunk size for dynamic chunk, it's\n            0: default for training, use random dynamic chunk.\n            <0: for decoding, use full chunk.\n            >0: for decoding, use fixed chunk size as set.\n        static_chunk_size (int): chunk size for static chunk training/decoding\n            if it's greater than 0, if use_dynamic_chunk is true,\n            this parameter will be ignored\n        num_decoding_left_chunks (int): number of left chunks, this is for decoding,\n            the chunk size is decoding_chunk_size.\n            >=0: use num_decoding_left_chunks\n            <0: use all left chunks\n    Returns:\n        paddle.Tensor: chunk mask of the input xs.\n    \"\"\"\n    # Whether to use chunk mask or not\n    if use_dynamic_chunk:\n        max_len = xs.shape[1]\n        if decoding_chunk_size < 0:\n            chunk_size = max_len\n            num_left_chunks = -1\n        elif decoding_chunk_size > 0:\n            chunk_size = decoding_chunk_size\n            num_left_chunks = num_decoding_left_chunks\n        else:\n            # chunk size is either [1, 25] or full context(max_len).\n            # Since we use 4 times subsampling and allow up to 1s(100 frames)\n            # delay, the maximum frame is 100 / 4 = 25.\n            chunk_size = int(paddle.randint(1, max_len, (1, )))\n            num_left_chunks = -1\n            if chunk_size > max_len // 2:\n                chunk_size = max_len\n            else:\n                chunk_size = chunk_size % 25 + 1\n                if use_dynamic_left_chunk:\n                    max_left_chunks = (max_len - 1) // chunk_size\n                    num_left_chunks = int(\n                        paddle.randint(0, max_left_chunks, (1, )))\n        chunk_masks = subsequent_chunk_mask(xs.shape[1], chunk_size,\n                                            num_left_chunks)  # (L, L)\n        chunk_masks = chunk_masks.unsqueeze(0)  # (1, L, L)\n        # chunk_masks = masks & chunk_masks  # (B, L, L)\n        chunk_masks = masks.logical_and(chunk_masks)  # (B, L, L)\n    elif static_chunk_size > 0:\n        num_left_chunks = num_decoding_left_chunks\n        chunk_masks = subsequent_chunk_mask(xs.shape[1], static_chunk_size,\n                                            num_left_chunks)  # (L, L)\n        chunk_masks = chunk_masks.unsqueeze(0)  # (1, L, L)\n        # chunk_masks = masks & chunk_masks  # (B, L, L)\n        chunk_masks = masks.logical_and(chunk_masks)  # (B, L, L)\n    else:\n        chunk_masks = masks\n    return chunk_masks\n\n\ndef mask_finished_scores(score: paddle.Tensor,\n                         flag: paddle.Tensor) -> paddle.Tensor:\n    \"\"\"\n    If a sequence is finished, we only allow one alive branch. This function\n    aims to give one branch a zero score and the rest -inf score.\n    Args:\n        score (paddle.Tensor): A real value array with shape\n            (batch_size * beam_size, beam_size).\n        flag (paddle.Tensor): A bool array with shape\n            (batch_size * beam_size, 1).\n    Returns:\n        paddle.Tensor: (batch_size * beam_size, beam_size).\n    Examples:\n        flag: tensor([[ True],\n                      [False]])\n        score: tensor([[-0.3666, -0.6664,  0.6019],\n                       [-1.1490, -0.2948,  0.7460]])\n        unfinished: tensor([[False,  True,  True],\n                            [False, False, False]])\n        finished: tensor([[ True, False, False],\n                          [False, False, False]])\n        return: tensor([[ 0.0000,    -inf,    -inf],\n                        [-1.1490, -0.2948,  0.7460]])\n    \"\"\"\n    beam_size = score.shape[-1]\n    zero_mask = paddle.zeros_like(flag, dtype=paddle.bool)\n    if beam_size > 1:\n        unfinished = paddle.concat(\n            (zero_mask, flag.tile([1, beam_size - 1])), axis=1)\n        finished = paddle.concat(\n            (flag, zero_mask.tile([1, beam_size - 1])), axis=1)\n    else:\n        unfinished = zero_mask\n        finished = flag\n\n    # infs = paddle.ones_like(score) * -float('inf')\n    # score = paddle.where(unfinished, infs, score)\n    # score = paddle.where(finished, paddle.zeros_like(score), score)\n    score.masked_fill_(unfinished, -float('inf'))\n    score.masked_fill_(finished, 0)\n    return score\n\n\ndef mask_finished_preds(pred: paddle.Tensor, flag: paddle.Tensor,\n                        eos: int) -> paddle.Tensor:\n    \"\"\"\n    If a sequence is finished, all of its branch should be <eos>\n    Args:\n        pred (paddle.Tensor): A int array with shape\n            (batch_size * beam_size, beam_size).\n        flag (paddle.Tensor): A bool array with shape\n            (batch_size * beam_size, 1).\n    Returns:\n        paddle.Tensor: (batch_size * beam_size).\n    \"\"\"\n    beam_size = pred.shape[-1]\n    finished = flag.repeat(1, beam_size)\n    return pred.masked_fill_(finished, eos)\n"
  },
  {
    "path": "paddlespeech/s2t/modules/positionwise_feed_forward.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Positionwise feed forward layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import initializer as I\n\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"PositionwiseFeedForward\"]\n\n\nclass PositionwiseFeedForward(nn.Layer):\n    \"\"\"Positionwise feed forward layer.\"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 hidden_units: int,\n                 dropout_rate: float,\n                 activation: nn.Layer=nn.ReLU(),\n                 adaptive_scale: bool=False,\n                 init_weights: bool=False):\n        \"\"\"Construct a PositionwiseFeedForward object.\n\n        FeedForward are appied on each position of the sequence.\n        The output dim is same with the input dim.\n\n        Args:\n            idim (int): Input dimenstion.\n            hidden_units (int): The number of hidden units.\n            dropout_rate (float): Dropout rate.\n            activation (paddle.nn.Layer): Activation function\n        \"\"\"\n        super().__init__()\n        self.idim = idim\n        self.hidden_units = hidden_units\n        self.w_1 = Linear(idim, hidden_units)\n        self.activation = activation\n        self.dropout = nn.Dropout(dropout_rate)\n        self.w_2 = Linear(hidden_units, idim)\n        self.adaptive_scale = adaptive_scale\n        if self.adaptive_scale:\n            ada_scale = self.create_parameter(\n                [1, 1, idim], default_initializer=I.XavierUniform())\n            self.add_parameter('ada_scale', ada_scale)\n            ada_bias = self.create_parameter(\n                [1, 1, idim], default_initializer=I.XavierUniform())\n            self.add_parameter('ada_bias', ada_bias)\n\n        if init_weights:\n            self.init_weights()\n\n    def init_weights(self):\n        ffn1_max = self.idim**-0.5\n        ffn2_max = self.hidden_units**-0.5\n        self.w_1._param_attr = paddle.nn.initializer.Uniform(\n            low=-ffn1_max, high=ffn1_max)\n        self.w_1._bias_attr = paddle.nn.initializer.Uniform(\n            low=-ffn1_max, high=ffn1_max)\n        self.w_2._param_attr = paddle.nn.initializer.Uniform(\n            low=-ffn2_max, high=ffn2_max)\n        self.w_2._bias_attr = paddle.nn.initializer.Uniform(\n            low=-ffn2_max, high=ffn2_max)\n\n    def forward(self, xs: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Forward function.\n        Args:\n            xs: input tensor (B, Lmax, D)\n        Returns:\n            output tensor, (B, Lmax, D)\n        \"\"\"\n        if self.adaptive_scale:\n            xs = self.ada_scale * xs + self.ada_bias\n        return self.w_2(self.dropout(self.activation(self.w_1(xs))))\n"
  },
  {
    "path": "paddlespeech/s2t/modules/subsampling.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Subsampling layer definition.\"\"\"\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.s2t.modules.align import Conv2D\nfrom paddlespeech.s2t.modules.align import LayerNorm\nfrom paddlespeech.s2t.modules.align import Linear\nfrom paddlespeech.s2t.modules.embedding import PositionalEncoding\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"LinearNoSubsampling\", \"Conv2dSubsampling4\", \"Conv2dSubsampling6\",\n    \"Conv2dSubsampling8\", \"DepthwiseConv2DSubsampling4\"\n]\n\n\nclass BaseSubsampling(nn.Layer):\n    def __init__(self, pos_enc_class: nn.Layer=PositionalEncoding):\n        super().__init__()\n        self.pos_enc = pos_enc_class\n        # window size = (1 + right_context) + (chunk_size -1) * subsampling_rate\n        self.right_context = 0\n        # stride = subsampling_rate * chunk_size\n        self.subsampling_rate = 1\n\n    def position_encoding(self, offset: int, size: int) -> paddle.Tensor:\n        return self.pos_enc.position_encoding(offset, size)\n\n\nclass LinearNoSubsampling(BaseSubsampling):\n    \"\"\"Linear transform the input without subsampling.\"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 odim: int,\n                 dropout_rate: float,\n                 pos_enc_class: nn.Layer=PositionalEncoding):\n        \"\"\"Construct an linear object.\n        Args:\n            idim (int): Input dimension.\n            odim (int): Output dimension.\n            dropout_rate (float): Dropout rate.\n            pos_enc_class (PositionalEncoding): position encoding class\n        \"\"\"\n        super().__init__(pos_enc_class)\n        self.out = nn.Sequential(\n            Linear(idim, odim),\n            LayerNorm(odim, epsilon=1e-12),\n            nn.Dropout(dropout_rate),\n            nn.ReLU(), )\n        self.right_context = 0\n        self.subsampling_rate = 1\n\n    def forward(self, x: paddle.Tensor, x_mask: paddle.Tensor, offset: int=0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Input x.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, idim).\n            x_mask (paddle.Tensor): Input mask (#batch, 1, time).\n            offset (int): position encoding offset.\n        Returns:\n            paddle.Tensor: linear input tensor (#batch, time', odim),\n                where time' = time .\n            paddle.Tensor: positional encoding\n            paddle.Tensor: linear input mask (#batch, 1, time'),\n                where time' = time .\n        \"\"\"\n        x = self.out(x)\n        x, pos_emb = self.pos_enc(x, offset)\n        return x, pos_emb, x_mask\n\n\nclass Conv2dSubsampling(BaseSubsampling):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n\nclass Conv2dSubsampling4(Conv2dSubsampling):\n    \"\"\"Convolutional 2D subsampling (to 1/4 length).\"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 odim: int,\n                 dropout_rate: float,\n                 pos_enc_class: nn.Layer=PositionalEncoding):\n        \"\"\"Construct an Conv2dSubsampling4 object.\n\n        Args:\n            idim (int): Input dimension.\n            odim (int): Output dimension.\n            dropout_rate (float): Dropout rate.\n        \"\"\"\n        super().__init__(pos_enc_class)\n        self.conv = nn.Sequential(\n            Conv2D(1, odim, 3, 2),\n            nn.ReLU(),\n            Conv2D(odim, odim, 3, 2),\n            nn.ReLU(), )\n        self.out = nn.Sequential(\n            Linear(odim * (((idim - 1) // 2 - 1) // 2), odim))\n        self.subsampling_rate = 4\n        # The right context for every conv layer is computed by:\n        # (kernel_size - 1) * frame_rate_of_this_layer\n        # 6 = (3 - 1) * 1 + (3 - 1) * 2\n        self.right_context = 6\n\n    def forward(self, x: paddle.Tensor, x_mask: paddle.Tensor, offset: int=0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Subsample x.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, idim).\n            x_mask (paddle.Tensor): Input mask (#batch, 1, time).\n            offset (int): position encoding offset.\n        Returns:\n            paddle.Tensor: Subsampled tensor (#batch, time', odim),\n                where time' = time // 4.\n            paddle.Tensor: positional encoding\n            paddle.Tensor: Subsampled mask (#batch, 1, time'),\n                where time' = time // 4.\n        \"\"\"\n        x = x.unsqueeze(1)  # (b, c=1, t, f)\n        x = self.conv(x)\n        b, c, t, f = x.shape\n        x = self.out(x.transpose([0, 2, 1, 3]).reshape([b, -1, c * f]))\n        x, pos_emb = self.pos_enc(x, offset)\n        return x, pos_emb, x_mask[:, :, :-2:2][:, :, :-2:2]\n\n\nclass Conv2dSubsampling6(Conv2dSubsampling):\n    \"\"\"Convolutional 2D subsampling (to 1/6 length).\"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 odim: int,\n                 dropout_rate: float,\n                 pos_enc_class: nn.Layer=PositionalEncoding):\n        \"\"\"Construct an Conv2dSubsampling6 object.\n\n        Args:\n            idim (int): Input dimension.\n            odim (int): Output dimension.\n            dropout_rate (float): Dropout rate.\n            pos_enc (PositionalEncoding): Custom position encoding layer.\n        \"\"\"\n        super().__init__(pos_enc_class)\n        self.conv = nn.Sequential(\n            Conv2D(1, odim, 3, 2),\n            nn.ReLU(),\n            Conv2D(odim, odim, 5, 3),\n            nn.ReLU(), )\n        # O = (I - F + Pstart + Pend) // S + 1\n        # when Padding == 0, O = (I - F - S) // S\n        self.linear = Linear(odim * (((idim - 1) // 2 - 2) // 3), odim)\n        # The right context for every conv layer is computed by:\n        # (kernel_size - 1) * frame_rate_of_this_layer\n        # 10 = (3 - 1) * 1 + (5 - 1) * 2\n        self.subsampling_rate = 6\n        self.right_context = 10\n\n    def forward(self, x: paddle.Tensor, x_mask: paddle.Tensor, offset: int=0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Subsample x.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, idim).\n            x_mask (paddle.Tensor): Input mask (#batch, 1, time).\n            offset (int): position encoding offset.\n        Returns:\n            paddle.Tensor: Subsampled tensor (#batch, time', odim),\n                where time' = time // 6.\n            paddle.Tensor: positional encoding\n            paddle.Tensor: Subsampled mask (#batch, 1, time'),\n                where time' = time // 6.\n        \"\"\"\n        x = x.unsqueeze(1)  # (b, c, t, f)\n        x = self.conv(x)\n        b, c, t, f = x.shape\n        x = self.linear(x.transpose([0, 2, 1, 3]).reshape([b, -1, c * f]))\n        x, pos_emb = self.pos_enc(x, offset)\n        return x, pos_emb, x_mask[:, :, :-2:2][:, :, :-4:3]\n\n\nclass Conv2dSubsampling8(Conv2dSubsampling):\n    \"\"\"Convolutional 2D subsampling (to 1/8 length).\"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 odim: int,\n                 dropout_rate: float,\n                 pos_enc_class: nn.Layer=PositionalEncoding):\n        \"\"\"Construct an Conv2dSubsampling8 object.\n\n        Args:\n            idim (int): Input dimension.\n            odim (int): Output dimension.\n            dropout_rate (float): Dropout rate.\n        \"\"\"\n        super().__init__(pos_enc_class)\n        self.conv = nn.Sequential(\n            Conv2D(1, odim, 3, 2),\n            nn.ReLU(),\n            Conv2D(odim, odim, 3, 2),\n            nn.ReLU(),\n            Conv2D(odim, odim, 3, 2),\n            nn.ReLU(), )\n        self.linear = Linear(odim * ((((idim - 1) // 2 - 1) // 2 - 1) // 2),\n                             odim)\n        self.subsampling_rate = 8\n        # The right context for every conv layer is computed by:\n        # (kernel_size - 1) * frame_rate_of_this_layer\n        # 14 = (3 - 1) * 1 + (3 - 1) * 2 + (3 - 1) * 4\n        self.right_context = 14\n\n    def forward(self, x: paddle.Tensor, x_mask: paddle.Tensor, offset: int=0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Subsample x.\n        Args:\n            x (paddle.Tensor): Input tensor (#batch, time, idim).\n            x_mask (paddle.Tensor): Input mask (#batch, 1, time).\n            offset (int): position encoding offset.\n        Returns:\n            paddle.Tensor: Subsampled tensor (#batch, time', odim),\n                where time' = time // 8.\n            paddle.Tensor: positional encoding\n            paddle.Tensor: Subsampled mask (#batch, 1, time'),\n                where time' = time // 8.\n        \"\"\"\n        x = x.unsqueeze(1)  # (b, c, t, f)\n        x = self.conv(x)\n        b, c, t, f = x.shape\n        x = self.linear(x.transpose([0, 2, 1, 3]).reshape([b, -1, c * f]))\n        x, pos_emb = self.pos_enc(x, offset)\n        return x, pos_emb, x_mask[:, :, :-2:2][:, :, :-2:2][:, :, :-2:2]\n\n\nclass DepthwiseConv2DSubsampling4(BaseSubsampling):\n    \"\"\"Depthwise Convolutional 2D subsampling (to 1/4 length).\n\n        Args:\n            idim (int): Input dimension.\n            odim (int): Output dimension.\n            pos_enc_class (nn.Layer): position encoding class.\n            dw_stride (int): Whether do depthwise convolution.\n            input_size (int): filter bank dimension.\n\n        \"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 odim: int,\n                 pos_enc_class: nn.Layer,\n                 dw_stride: bool=False,\n                 input_size: int=80,\n                 input_dropout_rate: float=0.1,\n                 init_weights: bool=True):\n        super(DepthwiseConv2DSubsampling4, self).__init__()\n        self.idim = idim\n        self.odim = odim\n        self.pw_conv = Conv2D(\n            in_channels=idim, out_channels=odim, kernel_size=3, stride=2)\n        self.act1 = nn.ReLU()\n        self.dw_conv = Conv2D(\n            in_channels=odim,\n            out_channels=odim,\n            kernel_size=3,\n            stride=2,\n            groups=odim if dw_stride else 1)\n        self.act2 = nn.ReLU()\n        self.pos_enc = pos_enc_class\n        self.input_proj = nn.Sequential(\n            Linear(odim * (((input_size - 1) // 2 - 1) // 2), odim),\n            nn.Dropout(p=input_dropout_rate))\n        if init_weights:\n            linear_max = (odim * input_size / 4)**-0.5\n            self.input_proj.state_dict()[\n                '0.weight'] = paddle.nn.initializer.Uniform(\n                    low=-linear_max, high=linear_max)\n            self.input_proj.state_dict()[\n                '0.bias'] = paddle.nn.initializer.Uniform(\n                    low=-linear_max, high=linear_max)\n\n        self.subsampling_rate = 4\n        # 6 = (3 - 1) * 1 + (3 - 1) * 2\n        self.right_context = 6\n\n    def forward(self, x: paddle.Tensor, x_mask: paddle.Tensor, offset: int=0\n                ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        x = x.unsqueeze(1)  # (b, c=1, t, f)\n        x = self.pw_conv(x)\n        x = self.act1(x)\n        x = self.dw_conv(x)\n        x = self.act2(x)\n        b, c, t, f = x.shape\n        x = x.transpose([0, 2, 1, 3]).reshape([b, -1, c * f])\n        x, pos_emb = self.pos_enc(x, offset)\n        x = self.input_proj(x)\n        return x, pos_emb, x_mask[:, :, :-2:2][:, :, :-2:2]\n"
  },
  {
    "path": "paddlespeech/s2t/modules/time_reduction.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n# Copyright 2019 Mobvoi Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\n\"\"\"Subsampling layer definition.\"\"\"\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.s2t import masked_fill\nfrom paddlespeech.s2t.modules.align import Conv1D\nfrom paddlespeech.s2t.modules.conv2d import Conv2DValid\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\n    \"TimeReductionLayerStream\", \"TimeReductionLayer1D\", \"TimeReductionLayer2D\"\n]\n\n\nclass TimeReductionLayer1D(nn.Layer):\n    \"\"\"\n    Modified NeMo,\n    Squeezeformer Time Reduction procedure.\n    Downsamples the audio by `stride` in the time dimension.\n    Args:\n        channel (int): input dimension of\n                       MultiheadAttentionMechanism and PositionwiseFeedForward\n        out_dim (int): Output dimension of the module.\n        kernel_size (int): Conv kernel size for\n                           depthwise convolution in convolution module\n        stride (int): Downsampling factor in time dimension.\n    \"\"\"\n\n    def __init__(self,\n                 channel: int,\n                 out_dim: int,\n                 kernel_size: int=5,\n                 stride: int=2):\n        super(TimeReductionLayer1D, self).__init__()\n\n        self.channel = channel\n        self.out_dim = out_dim\n        self.kernel_size = kernel_size\n        self.stride = stride\n        self.padding = max(0, self.kernel_size - self.stride)\n\n        self.dw_conv = Conv1D(\n            in_channels=channel,\n            out_channels=channel,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=self.padding,\n            groups=channel, )\n\n        self.pw_conv = Conv1D(\n            in_channels=channel,\n            out_channels=out_dim,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            groups=1, )\n\n        self.init_weights()\n\n    def init_weights(self):\n        dw_max = self.kernel_size**-0.5\n        pw_max = self.channel**-0.5\n        self.dw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.dw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.pw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n        self.pw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n\n    def forward(\n            self,\n            xs,\n            xs_lens: paddle.Tensor,\n            mask: paddle.Tensor=paddle.ones((0, 0, 0), dtype=paddle.bool),\n            mask_pad: paddle.Tensor=paddle.ones((0, 0, 0),\n                                                dtype=paddle.bool), ):\n        xs = xs.transpose([0, 2, 1])  # [B, C, T]\n        xs = masked_fill(xs, mask_pad.equal(0), 0.0)\n\n        xs = self.dw_conv(xs)\n        xs = self.pw_conv(xs)\n\n        xs = xs.transpose([0, 2, 1])  # [B, T, C]\n\n        B, T, D = xs.shape\n        mask = mask[:, ::self.stride, ::self.stride]\n        mask_pad = mask_pad[:, :, ::self.stride]\n        L = mask_pad.shape[-1]\n        # For JIT exporting, we remove F.pad operator.\n        if L - T < 0:\n            xs = xs[:, :L - T, :]\n        else:\n            dummy_pad = paddle.zeros([B, L - T, D], dtype=paddle.float32)\n            xs = paddle.concat([xs, dummy_pad], axis=1)\n\n        xs_lens = (xs_lens + 1) // 2\n        return xs, xs_lens, mask, mask_pad\n\n\nclass TimeReductionLayer2D(nn.Layer):\n    def __init__(self, kernel_size: int=5, stride: int=2, encoder_dim: int=256):\n        super(TimeReductionLayer2D, self).__init__()\n        self.encoder_dim = encoder_dim\n        self.kernel_size = kernel_size\n        self.dw_conv = Conv2DValid(\n            in_channels=encoder_dim,\n            out_channels=encoder_dim,\n            kernel_size=(kernel_size, 1),\n            stride=stride,\n            valid_trigy=True)\n        self.pw_conv = Conv2DValid(\n            in_channels=encoder_dim,\n            out_channels=encoder_dim,\n            kernel_size=1,\n            stride=1,\n            valid_trigx=False,\n            valid_trigy=False)\n\n        self.kernel_size = kernel_size\n        self.stride = stride\n        self.init_weights()\n\n    def init_weights(self):\n        dw_max = self.kernel_size**-0.5\n        pw_max = self.encoder_dim**-0.5\n        self.dw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.dw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.pw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n        self.pw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n\n    def forward(\n            self,\n            xs: paddle.Tensor,\n            xs_lens: paddle.Tensor,\n            mask: paddle.Tensor=paddle.ones((0, 0, 0), dtype=paddle.bool),\n            mask_pad: paddle.Tensor=paddle.ones((0, 0, 0), dtype=paddle.bool),\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        xs = masked_fill(xs, mask_pad.transpose([0, 2, 1]).equal(0), 0.0)\n        xs = xs.unsqueeze(1)\n        padding1 = self.kernel_size - self.stride\n        xs = F.pad(\n            xs, (0, 0, 0, 0, 0, padding1, 0, 0), mode='constant', value=0.)\n        xs = self.dw_conv(xs.transpose([0, 3, 2, 1]))\n        xs = self.pw_conv(xs).transpose([0, 3, 2, 1]).squeeze(1)\n        tmp_length = xs.shape[1]\n        xs_lens = (xs_lens + 1) // 2\n        padding2 = max(0, (xs_lens.max() - tmp_length).item())\n        batch_size, hidden = xs.shape[0], xs.shape[-1]\n        dummy_pad = paddle.zeros(\n            [batch_size, padding2, hidden], dtype=paddle.float32)\n        xs = paddle.concat([xs, dummy_pad], axis=1)\n        mask = mask[:, ::2, ::2]\n        mask_pad = mask_pad[:, :, ::2]\n        return xs, xs_lens, mask, mask_pad\n\n\nclass TimeReductionLayerStream(nn.Layer):\n    \"\"\"\n    Squeezeformer Time Reduction procedure.\n    Downsamples the audio by `stride` in the time dimension.\n    Args:\n        channel (int): input dimension of\n            MultiheadAttentionMechanism and PositionwiseFeedForward\n        out_dim (int): Output dimension of the module.\n        kernel_size (int): Conv kernel size for\n            depthwise convolution in convolution module\n        stride (int): Downsampling factor in time dimension.\n    \"\"\"\n\n    def __init__(self,\n                 channel: int,\n                 out_dim: int,\n                 kernel_size: int=1,\n                 stride: int=2):\n        super(TimeReductionLayerStream, self).__init__()\n\n        self.channel = channel\n        self.out_dim = out_dim\n        self.kernel_size = kernel_size\n        self.stride = stride\n\n        self.dw_conv = Conv1D(\n            in_channels=channel,\n            out_channels=channel,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=0,\n            groups=channel)\n\n        self.pw_conv = Conv1D(\n            in_channels=channel,\n            out_channels=out_dim,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            groups=1)\n        self.init_weights()\n\n    def init_weights(self):\n        dw_max = self.kernel_size**-0.5\n        pw_max = self.channel**-0.5\n        self.dw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.dw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-dw_max, high=dw_max)\n        self.pw_conv._param_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n        self.pw_conv._bias_attr = paddle.nn.initializer.Uniform(\n            low=-pw_max, high=pw_max)\n\n    def forward(\n            self,\n            xs,\n            xs_lens: paddle.Tensor,\n            mask: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool),\n            mask_pad: paddle.Tensor=paddle.ones([0, 0, 0], dtype=paddle.bool)):\n        xs = xs.transpose([0, 2, 1])  # [B, C, T]\n        xs = masked_fill(xs, mask_pad.equal(0), 0.0)\n\n        xs = self.dw_conv(xs)\n        xs = self.pw_conv(xs)\n\n        xs = xs.transpose([0, 2, 1])  # [B, T, C]\n\n        B, T, D = xs.shape\n        mask = mask[:, ::self.stride, ::self.stride]\n        mask_pad = mask_pad[:, :, ::self.stride]\n        L = mask_pad.shape[-1]\n        # For JIT exporting, we remove F.pad operator.\n        if L - T < 0:\n            xs = xs[:, :L - T, :]\n        else:\n            dummy_pad = paddle.zeros([B, L - T, D], dtype=paddle.float32)\n            xs = paddle.concat([xs, dummy_pad], axis=1)\n\n        xs_lens = (xs_lens + 1) // 2\n        return xs, xs_lens, mask, mask_pad\n"
  },
  {
    "path": "paddlespeech/s2t/training/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/training/cli.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport distutils\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.utils.argparse import strtobool\n\n\nclass ExtendAction(argparse.Action):\n    \"\"\"\n    [Since Python 3.8, the \"extend\" is available directly in stdlib]\n    (https://docs.python.org/3.8/library/argparse.html#action).\n    If you only have to support 3.8+ then defining it yourself is no longer required. \n    Usage of stdlib \"extend\" action is exactly the same way as this answer originally described:\n    \"\"\"\n\n    def __call__(self, parser, namespace, values, option_string=None):\n        items = getattr(namespace, self.dest) or []\n        items.extend(values)\n        setattr(namespace, self.dest, items)\n\n\nclass LoadFromFile(argparse.Action):\n    def __call__(self, parser, namespace, values, option_string=None):\n        with values as f:\n            # parse arguments in the file and store them in the target namespace\n            parser.parse_args(f.read().split(), namespace)\n\n\ndef default_argument_parser(parser=None):\n    r\"\"\"A simple yet genral argument parser for experiments with t2s.\n\n    This is used in examples with t2s. And it is intended to be used by\n    other experiments with t2s. It requires a minimal set of command line\n    arguments to start a training script.\n\n    The ``--config`` and ``--opts`` are used for overwrite the default\n    configuration.\n\n    The ``--data`` and ``--output`` specifies the data path and output path.\n    Resuming training from existing progress at the output directory is the\n    intended default behavior.\n\n    The ``--checkpoint_path`` specifies the checkpoint to load from.\n\n    The ``--ngpu`` specifies how to run the training.\n\n\n    See Also\n    --------\n    paddlespeech.t2s.training.experiment\n    Returns\n    -------\n    argparse.ArgumentParser\n        the parser\n    \"\"\"\n    if parser is None:\n        parser = argparse.ArgumentParser()\n\n    parser.register('action', 'extend', ExtendAction)\n    parser.add_argument(\n        '--conf', type=open, action=LoadFromFile, help=\"config file.\")\n    parser.add_argument(\n        \"--debug\",\n        type=strtobool,\n        default=False,\n        help=\"logging with debug mode.\")\n    parser.add_argument(\n        \"--dump_path\", type=str, default=None, help=\"path to dump config file.\")\n\n    # train group\n    train_group = parser.add_argument_group(\n        title='Train Options', description=None)\n    train_group.add_argument(\n        \"--seed\",\n        type=int,\n        default=None,\n        help=\"seed to use for paddle, np and random. None or 0 for random, else set seed.\"\n    )\n    train_group.add_argument(\n        \"--ngpu\",\n        type=int,\n        default=1,\n        help=\"number of parallel processes. 0 for cpu.\")\n    train_group.add_argument(\n        '--nxpu',\n        type=int,\n        default=0,\n        choices=[0, 1],\n        help=\"if nxpu == 0 and ngpu == 0, use cpu.\")\n    train_group.add_argument(\n        \"--config\", metavar=\"CONFIG_FILE\", help=\"config file.\")\n    train_group.add_argument(\n        \"--output\", metavar=\"CKPT_DIR\", help=\"path to save checkpoint.\")\n    train_group.add_argument(\n        \"--checkpoint_path\", type=str, help=\"path to load checkpoint\")\n    train_group.add_argument(\n        \"--opts\",\n        action='extend',\n        nargs=2,\n        metavar=('key', 'val'),\n        help=\"overwrite --config field, passing (KEY VALUE) pairs\")\n    train_group.add_argument(\n        \"--dump-config\", metavar=\"FILE\", help=\"dump config to `this` file.\")\n\n    # test group\n    test_group = parser.add_argument_group(\n        title='Test Options', description=None)\n    test_group.add_argument(\n        \"--decode_cfg\",\n        metavar=\"DECODE_CONFIG_FILE\",\n        help=\"decode config file.\")\n    test_group.add_argument(\n        \"--result_file\", type=str, help=\"path of save the asr result\")\n    test_group.add_argument(\n        \"--audio_file\", type=str, help=\"path of the input audio file\")\n\n    # quant & export\n    quant_group = parser.add_argument_group(\n        title='Quant Options', description=None)\n    quant_group.add_argument(\n        \"--audio_scp\", type=str, help=\"path of the input audio scp file\")\n    quant_group.add_argument(\n        \"--num_utts\",\n        type=int,\n        default=200,\n        help=\"num utts for quant calibrition.\")\n    quant_group.add_argument(\n        \"--export_path\",\n        type=str,\n        default='export.jit.quant',\n        help=\"path of the jit model to save\")\n\n    # profile group\n    profile_group = parser.add_argument_group(\n        title='Benchmark Options', description=None)\n    profile_group.add_argument(\n        '--profiler-options',\n        type=str,\n        default=None,\n        help='The option of profiler, which should be in format \\\"key1=value1;key2=value2;key3=value3\\\".'\n    )\n    profile_group.add_argument(\n        '--benchmark-batch-size',\n        type=int,\n        default=None,\n        help='batch size for benchmark.')\n    profile_group.add_argument(\n        '--benchmark-max-step',\n        type=int,\n        default=None,\n        help='max iteration for benchmark.')\n\n    return parser\n\n\ndef config_from_args(args):\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n\n    if args.config:\n        config.merge_from_file(args.config)\n\n    if args.decode_cfg:\n        decode_confs = CfgNode(new_allowed=True)\n        decode_confs.merge_from_file(args.decode_cfg)\n        config.decode = decode_confs\n\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    return config\n\n\ndef maybe_dump_config(dump_path, config):\n    if dump_path:\n        with open(dump_path, 'w') as f:\n            print(config, file=f)\n        print(f\"save config to {dump_path}\")\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Callable\n\nfrom .extension import Extension\n\n\ndef make_extension(trigger: Callable=None,\n                   default_name: str=None,\n                   priority: int=None,\n                   finalizer: Callable=None,\n                   initializer: Callable=None,\n                   on_error: Callable=None):\n    \"\"\"Make an Extension-like object by injecting required attributes to it.\n    \"\"\"\n    if trigger is None:\n        trigger = Extension.trigger\n    if priority is None:\n        priority = Extension.priority\n\n    def decorator(ext):\n        ext.trigger = trigger\n        ext.default_name = default_name or ext.__name__\n        ext.priority = priority\n        ext.finalize = finalizer\n        ext.on_error = on_error\n        ext.initialize = initializer\n        return ext\n\n    return decorator\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/evaluator.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\n\nfrom . import extension\nfrom ..reporter import DictSummary\nfrom ..reporter import ObsScope\nfrom ..reporter import report\nfrom ..timer import Timer\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n\nclass StandardEvaluator(extension.Extension):\n\n    trigger = (1, 'epoch')\n    default_name = 'validation'\n    priority = extension.PRIORITY_WRITER\n\n    name = None\n\n    def __init__(self, model: Layer, dataloader: DataLoader):\n        # it is designed to hold multiple models\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        self.model = model\n\n        # dataloaders\n        self.dataloader = dataloader\n\n    def evaluate_core(self, batch):\n        # compute\n        self.model(batch)  # you may report here\n        return\n\n    def evaluate_sync(self, data):\n        # dist sync `evaluate_core` outputs\n        if data is None:\n            return\n\n        numerator, denominator = data\n        if dist.get_world_size() > 1:\n            numerator = paddle.to_tensor(numerator)\n            denominator = paddle.to_tensor(denominator)\n            # the default operator in all_reduce function is sum.\n            dist.all_reduce(numerator)\n            dist.all_reduce(denominator)\n            value = numerator / denominator\n            value = float(value)\n        else:\n            value = numerator / denominator\n        # used for `snapshort` to do kbest save.\n        report(\"VALID/LOSS\", value)\n        logger.info(f\"Valid: all-reduce loss {value}\")\n\n    def evaluate(self):\n        # switch to eval mode\n        for model in self.models.values():\n            model.eval()\n\n        # to average evaluation metrics\n        summary = DictSummary()\n        for batch in self.dataloader:\n            observation = {}\n            with ObsScope(observation):\n                # main evaluation computation here.\n                with paddle.no_grad():\n                    self.evaluate_sync(self.evaluate_core(batch))\n            summary.add(observation)\n        summary = summary.compute_mean()\n\n        # switch to train mode\n        for model in self.models.values():\n            model.train()\n        return summary\n\n    def __call__(self, trainer=None):\n        # evaluate and report the averaged metric to current observation\n        # if it is used to extend a trainer, the metrics is reported to\n        # to observation of the trainer\n        # or otherwise, you can use your own observation\n        with Timer(\"Eval Time Cost: {}\"):\n            summary = self.evaluate()\n        for k, v in summary.items():\n            report(k, v)\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/extension.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nPRIORITY_WRITER = 300\nPRIORITY_EDITOR = 200\nPRIORITY_READER = 100\n\n\nclass Extension():\n    \"\"\"Extension to customize the behavior of Trainer.\"\"\"\n    trigger = (1, 'iteration')\n    priority = PRIORITY_READER\n    name = None\n\n    @property\n    def default_name(self):\n        \"\"\"Default name of the extension, class name by default.\"\"\"\n        return type(self).__name__\n\n    def __call__(self, trainer):\n        \"\"\"Main action of the extention. After each update, it is executed\n        when the trigger fires.\"\"\"\n        raise NotImplementedError(\n            'Extension implementation must override __call__.')\n\n    def initialize(self, trainer):\n        \"\"\"Action that is executed once to get the corect trainer state.\n        It is called before training normally, but if the trainer restores\n        states with an Snapshot extension, this method should also be called.\n        \"\"\"\n        pass\n\n    def on_error(self, trainer, exc, tb):\n        \"\"\"Handles the error raised during training before finalization.\n        \"\"\"\n        pass\n\n    def finalize(self, trainer):\n        \"\"\"Action that is executed when training is done.\n        For example, visualizers would need to be closed.\n        \"\"\"\n        pass\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/plot.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport copy\nimport os\n\nimport numpy as np\n\nfrom . import extension\n\n\nclass PlotAttentionReport(extension.Extension):\n    \"\"\"Plot attention reporter.\n\n    Args:\n        att_vis_fn (espnet.nets.*_backend.e2e_asr.E2E.calculate_all_attentions):\n            Function of attention visualization.\n        data (list[tuple(str, dict[str, list[Any]])]): List json utt key items.\n        outdir (str): Directory to save figures.\n        converter (espnet.asr.*_backend.asr.CustomConverter):\n            Function to convert data.\n        device (int | torch.device): Device.\n        reverse (bool): If True, input and output length are reversed.\n        ikey (str): Key to access input\n            (for ASR/ST ikey=\"input\", for MT ikey=\"output\".)\n        iaxis (int): Dimension to access input\n            (for ASR/ST iaxis=0, for MT iaxis=1.)\n        okey (str): Key to access output\n            (for ASR/ST okey=\"input\", MT okay=\"output\".)\n        oaxis (int): Dimension to access output\n            (for ASR/ST oaxis=0, for MT oaxis=0.)\n        subsampling_factor (int): subsampling factor in encoder\n\n    \"\"\"\n\n    def __init__(\n            self,\n            att_vis_fn,\n            data,\n            outdir,\n            converter,\n            transform,\n            device,\n            reverse=False,\n            ikey=\"input\",\n            iaxis=0,\n            okey=\"output\",\n            oaxis=0,\n            subsampling_factor=1, ):\n        self.att_vis_fn = att_vis_fn\n        self.data = copy.deepcopy(data)\n        self.data_dict = {k: v for k, v in copy.deepcopy(data)}\n        # key is utterance ID\n        self.outdir = outdir\n        self.converter = converter\n        self.transform = transform\n        self.device = device\n        self.reverse = reverse\n        self.ikey = ikey\n        self.iaxis = iaxis\n        self.okey = okey\n        self.oaxis = oaxis\n        self.factor = subsampling_factor\n        if not os.path.exists(self.outdir):\n            os.makedirs(self.outdir)\n\n    def __call__(self, trainer):\n        \"\"\"Plot and save image file of att_ws matrix.\"\"\"\n        att_ws, uttid_list = self.get_attention_weights()\n        if isinstance(att_ws, list):  # multi-encoder case\n            num_encs = len(att_ws) - 1\n            # atts\n            for i in range(num_encs):\n                for idx, att_w in enumerate(att_ws[i]):\n                    filename = \"%s/%s.ep.{.updater.epoch}.att%d.png\" % (\n                        self.outdir, uttid_list[idx], i + 1, )\n                    att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                    np_filename = \"%s/%s.ep.{.updater.epoch}.att%d.npy\" % (\n                        self.outdir, uttid_list[idx], i + 1, )\n                    np.save(np_filename.format(trainer), att_w)\n                    self._plot_and_save_attention(att_w,\n                                                  filename.format(trainer))\n            # han\n            for idx, att_w in enumerate(att_ws[num_encs]):\n                filename = \"%s/%s.ep.{.updater.epoch}.han.png\" % (\n                    self.outdir, uttid_list[idx], )\n                att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                np_filename = \"%s/%s.ep.{.updater.epoch}.han.npy\" % (\n                    self.outdir, uttid_list[idx], )\n                np.save(np_filename.format(trainer), att_w)\n                self._plot_and_save_attention(\n                    att_w, filename.format(trainer), han_mode=True)\n        else:\n            for idx, att_w in enumerate(att_ws):\n                filename = \"%s/%s.ep.{.updater.epoch}.png\" % (self.outdir,\n                                                              uttid_list[idx], )\n                att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                np_filename = \"%s/%s.ep.{.updater.epoch}.npy\" % (\n                    self.outdir, uttid_list[idx], )\n                np.save(np_filename.format(trainer), att_w)\n                self._plot_and_save_attention(att_w, filename.format(trainer))\n\n    def log_attentions(self, logger, step):\n        \"\"\"Add image files of att_ws matrix to the tensorboard.\"\"\"\n        att_ws, uttid_list = self.get_attention_weights()\n        if isinstance(att_ws, list):  # multi-encoder case\n            num_encs = len(att_ws) - 1\n            # atts\n            for i in range(num_encs):\n                for idx, att_w in enumerate(att_ws[i]):\n                    att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                    plot = self.draw_attention_plot(att_w)\n                    logger.add_figure(\n                        \"%s_att%d\" % (uttid_list[idx], i + 1),\n                        plot.gcf(),\n                        step, )\n            # han\n            for idx, att_w in enumerate(att_ws[num_encs]):\n                att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                plot = self.draw_han_plot(att_w)\n                logger.add_figure(\n                    \"%s_han\" % (uttid_list[idx]),\n                    plot.gcf(),\n                    step, )\n        else:\n            for idx, att_w in enumerate(att_ws):\n                att_w = self.trim_attention_weight(uttid_list[idx], att_w)\n                plot = self.draw_attention_plot(att_w)\n                logger.add_figure(\"%s\" % (uttid_list[idx]), plot.gcf(), step)\n\n    def get_attention_weights(self):\n        \"\"\"Return attention weights.\n\n        Returns:\n            numpy.ndarray: attention weights. float. Its shape would be\n                differ from backend.\n                * pytorch-> 1) multi-head case => (B, H, Lmax, Tmax), 2)\n                    other case => (B, Lmax, Tmax).\n                * chainer-> (B, Lmax, Tmax)\n\n        \"\"\"\n        return_batch, uttid_list = self.transform(self.data, return_uttid=True)\n        batch = self.converter([return_batch], self.device)\n        if isinstance(batch, tuple):\n            att_ws = self.att_vis_fn(*batch)\n        else:\n            att_ws = self.att_vis_fn(**batch)\n        return att_ws, uttid_list\n\n    def trim_attention_weight(self, uttid, att_w):\n        \"\"\"Transform attention matrix with regard to self.reverse.\"\"\"\n        if self.reverse:\n            enc_key, enc_axis = self.okey, self.oaxis\n            dec_key, dec_axis = self.ikey, self.iaxis\n        else:\n            enc_key, enc_axis = self.ikey, self.iaxis\n            dec_key, dec_axis = self.okey, self.oaxis\n        dec_len = int(self.data_dict[uttid][dec_key][dec_axis][\"shape\"][0])\n        enc_len = int(self.data_dict[uttid][enc_key][enc_axis][\"shape\"][0])\n        if self.factor > 1:\n            enc_len //= self.factor\n        if len(att_w.shape) == 3:\n            att_w = att_w[:, :dec_len, :enc_len]\n        else:\n            att_w = att_w[:dec_len, :enc_len]\n        return att_w\n\n    def draw_attention_plot(self, att_w):\n        \"\"\"Plot the att_w matrix.\n\n        Returns:\n            matplotlib.pyplot: pyplot object with attention matrix image.\n\n        \"\"\"\n        import matplotlib\n\n        matplotlib.use(\"Agg\")\n        import matplotlib.pyplot as plt\n\n        plt.clf()\n        att_w = att_w.astype(np.float32)\n        if len(att_w.shape) == 3:\n            for h, aw in enumerate(att_w, 1):\n                plt.subplot(1, len(att_w), h)\n                plt.imshow(aw, aspect=\"auto\")\n                plt.xlabel(\"Encoder Index\")\n                plt.ylabel(\"Decoder Index\")\n        else:\n            plt.imshow(att_w, aspect=\"auto\")\n            plt.xlabel(\"Encoder Index\")\n            plt.ylabel(\"Decoder Index\")\n        plt.tight_layout()\n        return plt\n\n    def draw_han_plot(self, att_w):\n        \"\"\"Plot the att_w matrix for hierarchical attention.\n\n        Returns:\n            matplotlib.pyplot: pyplot object with attention matrix image.\n\n        \"\"\"\n        import matplotlib\n\n        matplotlib.use(\"Agg\")\n        import matplotlib.pyplot as plt\n\n        plt.clf()\n        if len(att_w.shape) == 3:\n            for h, aw in enumerate(att_w, 1):\n                legends = []\n                plt.subplot(1, len(att_w), h)\n                for i in range(aw.shape[1]):\n                    plt.plot(aw[:, i])\n                    legends.append(\"Att{}\".format(i))\n                plt.ylim([0, 1.0])\n                plt.xlim([0, aw.shape[0]])\n                plt.grid(True)\n                plt.ylabel(\"Attention Weight\")\n                plt.xlabel(\"Decoder Index\")\n                plt.legend(legends)\n        else:\n            legends = []\n            for i in range(att_w.shape[1]):\n                plt.plot(att_w[:, i])\n                legends.append(\"Att{}\".format(i))\n            plt.ylim([0, 1.0])\n            plt.xlim([0, att_w.shape[0]])\n            plt.grid(True)\n            plt.ylabel(\"Attention Weight\")\n            plt.xlabel(\"Decoder Index\")\n            plt.legend(legends)\n        plt.tight_layout()\n        return plt\n\n    def _plot_and_save_attention(self, att_w, filename, han_mode=False):\n        if han_mode:\n            plt = self.draw_han_plot(att_w)\n        else:\n            plt = self.draw_attention_plot(att_w)\n        plt.savefig(filename)\n        plt.close()\n\n\nclass PlotCTCReport(extension.Extension):\n    \"\"\"Plot CTC reporter.\n\n    Args:\n        ctc_vis_fn (espnet.nets.*_backend.e2e_asr.E2E.calculate_all_ctc_probs):\n            Function of CTC visualization.\n        data (list[tuple(str, dict[str, list[Any]])]): List json utt key items.\n        outdir (str): Directory to save figures.\n        converter (espnet.asr.*_backend.asr.CustomConverter):\n            Function to convert data.\n        device (int | torch.device): Device.\n        reverse (bool): If True, input and output length are reversed.\n        ikey (str): Key to access input\n            (for ASR/ST ikey=\"input\", for MT ikey=\"output\".)\n        iaxis (int): Dimension to access input\n            (for ASR/ST iaxis=0, for MT iaxis=1.)\n        okey (str): Key to access output\n            (for ASR/ST okey=\"input\", MT okay=\"output\".)\n        oaxis (int): Dimension to access output\n            (for ASR/ST oaxis=0, for MT oaxis=0.)\n        subsampling_factor (int): subsampling factor in encoder\n\n    \"\"\"\n\n    def __init__(\n            self,\n            ctc_vis_fn,\n            data,\n            outdir,\n            converter,\n            transform,\n            device,\n            reverse=False,\n            ikey=\"input\",\n            iaxis=0,\n            okey=\"output\",\n            oaxis=0,\n            subsampling_factor=1, ):\n        self.ctc_vis_fn = ctc_vis_fn\n        self.data = copy.deepcopy(data)\n        self.data_dict = {k: v for k, v in copy.deepcopy(data)}\n        # key is utterance ID\n        self.outdir = outdir\n        self.converter = converter\n        self.transform = transform\n        self.device = device\n        self.reverse = reverse\n        self.ikey = ikey\n        self.iaxis = iaxis\n        self.okey = okey\n        self.oaxis = oaxis\n        self.factor = subsampling_factor\n        if not os.path.exists(self.outdir):\n            os.makedirs(self.outdir)\n\n    def __call__(self, trainer):\n        \"\"\"Plot and save image file of ctc prob.\"\"\"\n        ctc_probs, uttid_list = self.get_ctc_probs()\n        if isinstance(ctc_probs, list):  # multi-encoder case\n            num_encs = len(ctc_probs) - 1\n            for i in range(num_encs):\n                for idx, ctc_prob in enumerate(ctc_probs[i]):\n                    filename = \"%s/%s.ep.{.updater.epoch}.ctc%d.png\" % (\n                        self.outdir, uttid_list[idx], i + 1, )\n                    ctc_prob = self.trim_ctc_prob(uttid_list[idx], ctc_prob)\n                    np_filename = \"%s/%s.ep.{.updater.epoch}.ctc%d.npy\" % (\n                        self.outdir, uttid_list[idx], i + 1, )\n                    np.save(np_filename.format(trainer), ctc_prob)\n                    self._plot_and_save_ctc(ctc_prob, filename.format(trainer))\n        else:\n            for idx, ctc_prob in enumerate(ctc_probs):\n                filename = \"%s/%s.ep.{.updater.epoch}.png\" % (self.outdir,\n                                                              uttid_list[idx], )\n                ctc_prob = self.trim_ctc_prob(uttid_list[idx], ctc_prob)\n                np_filename = \"%s/%s.ep.{.updater.epoch}.npy\" % (\n                    self.outdir, uttid_list[idx], )\n                np.save(np_filename.format(trainer), ctc_prob)\n                self._plot_and_save_ctc(ctc_prob, filename.format(trainer))\n\n    def log_ctc_probs(self, logger, step):\n        \"\"\"Add image files of ctc probs to the tensorboard.\"\"\"\n        ctc_probs, uttid_list = self.get_ctc_probs()\n        if isinstance(ctc_probs, list):  # multi-encoder case\n            num_encs = len(ctc_probs) - 1\n            for i in range(num_encs):\n                for idx, ctc_prob in enumerate(ctc_probs[i]):\n                    ctc_prob = self.trim_ctc_prob(uttid_list[idx], ctc_prob)\n                    plot = self.draw_ctc_plot(ctc_prob)\n                    logger.add_figure(\n                        \"%s_ctc%d\" % (uttid_list[idx], i + 1),\n                        plot.gcf(),\n                        step, )\n        else:\n            for idx, ctc_prob in enumerate(ctc_probs):\n                ctc_prob = self.trim_ctc_prob(uttid_list[idx], ctc_prob)\n                plot = self.draw_ctc_plot(ctc_prob)\n                logger.add_figure(\"%s\" % (uttid_list[idx]), plot.gcf(), step)\n\n    def get_ctc_probs(self):\n        \"\"\"Return CTC probs.\n\n        Returns:\n            numpy.ndarray: CTC probs. float. Its shape would be\n                differ from backend. (B, Tmax, vocab).\n\n        \"\"\"\n        return_batch, uttid_list = self.transform(self.data, return_uttid=True)\n        batch = self.converter([return_batch], self.device)\n        if isinstance(batch, tuple):\n            probs = self.ctc_vis_fn(*batch)\n        else:\n            probs = self.ctc_vis_fn(**batch)\n        return probs, uttid_list\n\n    def trim_ctc_prob(self, uttid, prob):\n        \"\"\"Trim CTC posteriors accoding to input lengths.\"\"\"\n        enc_len = int(self.data_dict[uttid][self.ikey][self.iaxis][\"shape\"][0])\n        if self.factor > 1:\n            enc_len //= self.factor\n        prob = prob[:enc_len]\n        return prob\n\n    def draw_ctc_plot(self, ctc_prob):\n        \"\"\"Plot the ctc_prob matrix.\n\n        Returns:\n            matplotlib.pyplot: pyplot object with CTC prob matrix image.\n\n        \"\"\"\n        import matplotlib\n\n        matplotlib.use(\"Agg\")\n        import matplotlib.pyplot as plt\n\n        ctc_prob = ctc_prob.astype(np.float32)\n\n        plt.clf()\n        topk_ids = np.argsort(ctc_prob, axis=1)\n        n_frames, vocab = ctc_prob.shape\n        times_probs = np.arange(n_frames)\n\n        plt.figure(figsize=(20, 8))\n\n        # NOTE: index 0 is reserved for blank\n        for idx in set(topk_ids.reshape(-1).tolist()):\n            if idx == 0:\n                plt.plot(\n                    times_probs,\n                    ctc_prob[:, 0],\n                    \":\",\n                    label=\"<blank>\",\n                    color=\"grey\")\n            else:\n                plt.plot(times_probs, ctc_prob[:, idx])\n        plt.xlabel(u\"Input [frame]\", fontsize=12)\n        plt.ylabel(\"Posteriors\", fontsize=12)\n        plt.xticks(list(range(0, int(n_frames) + 1, 10)))\n        plt.yticks(list(range(0, 2, 1)))\n        plt.tight_layout()\n        return plt\n\n    def _plot_and_save_ctc(self, ctc_prob, filename):\n        plt = self.draw_ctc_plot(ctc_prob)\n        plt.savefig(filename)\n        plt.close()\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/snapshot.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport os\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\n\nfrom . import extension\nfrom ..reporter import get_observations\nfrom ..updaters.trainer import Trainer\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.mp_tools import rank_zero_only\n\nlogger = Log(__name__).getlog()\n\n\ndef load_records(records_fp):\n    \"\"\"Load record files (json lines.)\"\"\"\n    with jsonlines.open(records_fp, 'r') as reader:\n        records = list(reader)\n    return records\n\n\nclass Snapshot(extension.Extension):\n    \"\"\"An extension to make snapshot of the updater object inside\n    the trainer. It is done by calling the updater's `save` method.\n    An Updater save its state_dict by default, which contains the\n    updater state, (i.e. epoch and iteration) and all the model\n    parameters and optimizer states. If the updater inside the trainer\n    subclasses StandardUpdater, everything is good to go.\n    Parameters\n    ----------\n    checkpoint_dir : Union[str, Path]\n        The directory to save checkpoints into.\n    \"\"\"\n\n    trigger = (1, 'epoch')\n    priority = -100\n    default_name = \"snapshot\"\n\n    def __init__(self,\n                 mode='latest',\n                 max_size: int=5,\n                 indicator=None,\n                 less_better=True,\n                 snapshot_on_error: bool=False):\n        self.records: List[Dict[str, Any]] = []\n        assert mode in ('latest', 'kbest'), mode\n        if mode == 'kbest':\n            assert indicator is not None\n        self.mode = mode\n        self.indicator = indicator\n        self.less_is_better = less_better\n        self.max_size = max_size\n        self._snapshot_on_error = snapshot_on_error\n        self._save_all = (max_size == -1)\n        self.checkpoint_dir = None\n\n    def initialize(self, trainer: Trainer):\n        \"\"\"Setting up this extention.\"\"\"\n        self.checkpoint_dir = trainer.out / \"checkpoints\"\n\n        # load existing records\n        record_path: Path = self.checkpoint_dir / \"records.jsonl\"\n        if record_path.exists():\n            self.records = load_records(record_path)\n            ckpt_path = self.records[-1]['path']\n            logger.info(f\"Loading from an existing checkpoint {ckpt_path}\")\n            trainer.updater.load(ckpt_path)\n\n    def on_error(self, trainer, exc, tb):\n        if self._snapshot_on_error:\n            self.save_checkpoint_and_update(trainer, 'latest')\n\n    def __call__(self, trainer: Trainer):\n        self.save_checkpoint_and_update(trainer, self.mode)\n\n    def full(self):\n        \"\"\"Whether the number of snapshots it keeps track of is greater\n        than the max_size.\"\"\"\n        return (not self._save_all) and len(self.records) > self.max_size\n\n    @rank_zero_only\n    def save_checkpoint_and_update(self, trainer: Trainer, mode: str):\n        \"\"\"Saving new snapshot and remove the oldest snapshot if needed.\"\"\"\n        iteration = trainer.updater.state.iteration\n        epoch = trainer.updater.state.epoch\n        num = epoch if self.trigger[1] == 'epoch' else iteration\n        path = self.checkpoint_dir / f\"{num}.np\"\n\n        # add the new one\n        trainer.updater.save(path)\n        record = {\n            \"time\": str(datetime.now()),\n            'path': str(path.resolve()),  # use absolute path\n            'iteration': iteration,\n            'epoch': epoch,\n            'indicator': get_observations()[self.indicator]\n        }\n        self.records.append(record)\n\n        # remove the earist\n        if self.full():\n            if mode == 'kbest':\n                self.records = sorted(\n                    self.records,\n                    key=lambda record: record['indicator'],\n                    reverse=not self.less_is_better)\n            eariest_record = self.records[0]\n            os.remove(eariest_record[\"path\"])\n            self.records.pop(0)\n\n        # update the record file\n        record_path = self.checkpoint_dir / \"records.jsonl\"\n        with jsonlines.open(record_path, 'w') as writer:\n            for record in self.records:\n                # jsonlines.open may return a Writer or a Reader\n                writer.write(record)  # pylint: disable=no-member\n"
  },
  {
    "path": "paddlespeech/s2t/training/extensions/visualizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom visualdl import LogWriter\n\nfrom . import extension\nfrom ..updaters.trainer import Trainer\n\n\nclass VisualDL(extension.Extension):\n    \"\"\"A wrapper of visualdl log writer. It assumes that the metrics to be visualized\n    are all scalars which are recorded into the `.observation` dictionary of the\n    trainer object. The dictionary is created for each step, thus the visualdl log\n    writer uses the iteration from the updater's `iteration` as the global step to\n    add records.\n    \"\"\"\n    trigger = (1, 'iteration')\n    default_name = 'visualdl'\n    priority = extension.PRIORITY_READER\n\n    def __init__(self, output_dir):\n        self.writer = LogWriter(str(output_dir))\n\n    def __call__(self, trainer: Trainer):\n        for k, v in trainer.observation.items():\n            self.writer.add_scalar(k, v, step=trainer.updater.state.iteration)\n\n    def finalize(self, trainer):\n        self.writer.close()\n"
  },
  {
    "path": "paddlespeech/s2t/training/optimizer/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Text\n\nimport paddle\nfrom paddle.optimizer import Optimizer\nfrom paddle.regularizer import L2Decay\n\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\nfrom paddlespeech.s2t.utils.dynamic_import import instance_class\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"OptimizerFactory\"]\n\nlogger = Log(__name__).getlog()\n\nOPTIMIZER_DICT = {\n    \"sgd\": \"paddle.optimizer:SGD\",\n    \"momentum\": \"paddle.optimizer:Momentum\",\n    \"adadelta\": \"paddle.optimizer:Adadelta\",\n    \"adam\": \"paddle.optimizer:Adam\",\n    \"adamw\": \"paddle.optimizer:AdamW\",\n}\n\n\ndef register_optimizer(cls):\n    \"\"\"Register optimizer.\"\"\"\n    alias = cls.__name__.lower()\n    OPTIMIZER_DICT[cls.__name__.lower()] = cls.__module__ + \":\" + cls.__name__\n    return cls\n\n\n@register_optimizer\nclass Noam(paddle.optimizer.Adam):\n    \"\"\"Seem to: espnet/nets/pytorch_backend/transformer/optimizer.py \"\"\"\n\n    def __init__(self,\n                 learning_rate=0,\n                 beta1=0.9,\n                 beta2=0.98,\n                 epsilon=1e-9,\n                 parameters=None,\n                 weight_decay=None,\n                 grad_clip=None,\n                 lazy_mode=False,\n                 multi_precision=False,\n                 name=None):\n        super().__init__(\n            learning_rate=learning_rate,\n            beta1=beta1,\n            beta2=beta2,\n            epsilon=epsilon,\n            parameters=parameters,\n            weight_decay=weight_decay,\n            grad_clip=grad_clip,\n            lazy_mode=lazy_mode,\n            multi_precision=multi_precision,\n            name=name)\n\n    def __repr__(self):\n        echo = f\"<{self.__class__.__module__}.{self.__class__.__name__} object at {hex(id(self))}> \"\n        echo += f\"learning_rate: {self._learning_rate}, \"\n        echo += f\"(beta1: {self._beta1} beta2: {self._beta2}), \"\n        echo += f\"epsilon: {self._epsilon}\"\n\n\ndef dynamic_import_optimizer(module):\n    \"\"\"Import Optimizer class dynamically.\n\n    Args:\n        module (str): module_name:class_name or alias in `OPTIMIZER_DICT`\n\n    Returns:\n        type: Optimizer class\n\n    \"\"\"\n    module_class = dynamic_import(module, OPTIMIZER_DICT)\n    assert issubclass(module_class,\n                      Optimizer), f\"{module} does not implement Optimizer\"\n    return module_class\n\n\nclass OptimizerFactory():\n    @classmethod\n    def from_args(cls, name: str, args: Dict[Text, Any]):\n        assert \"parameters\" in args, \"parameters not in args.\"\n        assert \"learning_rate\" in args, \"learning_rate not in args.\"\n\n        grad_clip = paddle.nn.ClipGradByGlobalNorm(\n            args['grad_clip']) if \"grad_clip\" in args else None\n        weight_decay = args.get(\"weight_decay\", None)\n        if weight_decay:\n            logger.info(f'<WeightDecay - {weight_decay}>')\n        if grad_clip:\n            logger.info(f'<GradClip - {grad_clip}>')\n\n        module_class = dynamic_import_optimizer(name.lower())\n        args.update({\"grad_clip\": grad_clip, \"weight_decay\": weight_decay})\n        opt = instance_class(module_class, args)\n        if \"__repr__\" in vars(opt):\n            logger.info(f\"{opt}\")\n        else:\n            logger.info(\n                f\"<Optimizer {module_class.__module__}.{module_class.__name__}> LR: {args['learning_rate']}\"\n            )\n        return opt\n"
  },
  {
    "path": "paddlespeech/s2t/training/optimizer/adadelta.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import framework\nfrom paddle.optimizer import Optimizer\n\n__all__ = []\n\n\nclass SimpleAdadelta(Optimizer):\n    r\"\"\"\n    **Notes: This API does not support sparse parameter optimization.**\n\n    Adadelta Optimizer. Please refer to this for details:\n    `ADADELTA: AN ADAPTIVE LEARNING RATE METHOD <https://arxiv.org/abs/1212.5701>`_.\n\n    The update is done as follows:\n\n    .. math::\n\n        E(g_t^2) &= \\rho * E(g_{t-1}^2) + (1-\\rho) * g^2\n\n        learning\\_rate &= \\sqrt{ ( E(dx_{t-1}^2) + \\epsilon ) / ( E(g_t^2) + \\epsilon ) }\n\n        E(dx_t^2) &= \\rho * E(dx_{t-1}^2) + (1-\\rho) * (-g*learning\\_rate)^2\n\n    Args:\n        learning_rate (float|Tensor|LearningRateDecay, optional): The learning rate used to update ``Parameter``.\n            It can be a float value, a ``Tensor`` with a float type or a LearningRateDecay. The default value is 0.001.\n        epsilon (float): a small float number for numeric stability. Default 1.0e-6.\n        rho (float): a floating point value indicating the decay rate. Default 0.95.\n        parameters (list|tuple, optional): List/Tuple of ``Tensor`` to update to minimize ``loss``. \\\n            This parameter is required in dygraph mode. And you can specify different options for \\\n            different parameter groups such as the learning rate, weight decay, etc, \\\n            then the parameters are list of dict. Note that the learning_rate in paramter groups \\\n            represents the scale of base learning_rate. \\\n            The default value is None in static mode, at this time all parameters will be updated.\n        weight_decay (float|WeightDecayRegularizer, optional): The strategy of regularization. \\\n            It canbe a float value as coeff of L2 regularization or \\\n            :ref:`api_fluid_regularizer_L1Decay`, :ref:`api_fluid_regularizer_L2Decay`.\n            If a parameter has set regularizer using :ref:`api_fluid_ParamAttr` already, \\\n            the regularization setting here in optimizer will be ignored for this parameter. \\\n            Otherwise, the regularization setting here in optimizer will take effect. \\\n            Default None, meaning there is no regularization.\n        foreach (bool, optional): whether foreach implementation of optimizer is used. The default value is None.\n        maximize (bool, optional): maximize the params based on the objective, instead of minimizing.\n            The default value is False.\n        name (str, optional): The default value is None. Normally there is no need for user\n                to set this property. For more information, please refer to\n                :ref:`api_guide_Name` .\n\n    Examples:\n        .. code-block:: python\n\n            import paddle\n            from paddlespeech.s2t.training.optimizer.adadelta import SimpleAdadelta\n\n            inp = paddle.uniform([10, 10], dtype=\"float32\", min=-0.1, max=0.1)\n            linear = paddle.nn.Linear(10, 10)\n            out = linear(inp)\n            loss = paddle.mean(out)\n            adadelta = SimpleAdadelta(learning_rate=0.1, parameters=linear.parameters(), weight_decay=0.01)\n            out.backward()\n            adadelta.step()\n            adadelta.clear_grad()\n\n    \"\"\"\n\n    def __init__(\n            self,\n            learning_rate=0.001,\n            epsilon=1.0e-6,\n            rho=0.95,\n            parameters=None,\n            weight_decay=0.0,\n            foreach=None,\n            maximize=False,\n            name=None, ):\n        if learning_rate is None:\n            raise ValueError(\"learning_rate is not set.\")\n        if epsilon is None:\n            raise ValueError(\"epsilon is not set.\")\n        if rho is None:\n            raise ValueError(\"rho is not set.\")\n        super(SimpleAdadelta, self).__init__(\n            learning_rate=learning_rate,\n            parameters=parameters,\n            weight_decay=weight_decay,\n            name=name, )\n\n        self._epsilon = epsilon\n        self._rho = rho\n\n        self.state = 0  # self.state is 0 or 1, use to control init square_avgs and acc_deltas\n        self._weight_decay = weight_decay\n        self._learning_rate = learning_rate\n        self._foreach = foreach\n        self._maximize = maximize\n        self.square_avgs = []\n        self.acc_deltas = []\n\n    @paddle.no_grad()\n    @framework.dygraph_only\n    def step(self):\n        \"\"\"Performs a single optimization step.\n\n        Args:\n            closure (Callable, optional): A closure that reevaluates the model\n                and returns the loss.\n        \"\"\"\n        if not isinstance(self._parameter_list[0], dict):\n            params_grads = []\n            for param in self._parameter_list:\n                if param.stop_gradient:\n                    continue\n                if param._grad_ivar() is not None:\n                    grad_var = param._grad_ivar()\n\n                    params_grads.append((param, grad_var))\n                    if self.state == 0:\n                        self.square_avg = paddle.zeros_like(param)\n                        self.acc_delta = paddle.zeros_like(param)\n                        self.square_avgs.append(self.square_avg)\n                        self.acc_deltas.append(self.acc_delta)\n\n        else:\n            # optimize parameters in groups\n            params_grads = []\n            for idx, param_group in enumerate(self._param_groups):\n                for param in param_group['params']:\n                    if param.stop_gradient:\n                        continue\n                    if param._grad_ivar() is not None:\n                        grad_var = param._grad_ivar()\n                        params_grads.append((param, grad_var))\n                        if self.state == 0:\n                            self.square_avg = paddle.zeros_like(param)\n                            self.acc_delta = paddle.zeros_like(param)\n                            self.square_avgs.append(self.square_avg)\n                            self.acc_deltas.append(self.acc_delta)\n\n        self.state = 1\n        adadelta(\n            params_grads,\n            square_avgs=self.square_avgs,\n            acc_deltas=self.acc_deltas,\n            learning_rate=self._learning_rate,\n            rho=self._rho,\n            epsilon=self._epsilon,\n            weight_decay=self._weight_decay,\n            foreach=self._foreach,\n            maximize=self._maximize)\n\n\ndef adadelta(params_grads,\n             square_avgs,\n             acc_deltas,\n             foreach=None,\n             *,\n             learning_rate: float,\n             rho: float,\n             epsilon: float,\n             weight_decay: float,\n             maximize: bool):\n\n    if foreach is None:\n        # if foreach is None, set False\n        foreach = False\n    if not foreach:\n        # optimizer is used\n        func = _single_tensor_adadelta\n\n    func(\n        params_grads,\n        square_avgs,\n        acc_deltas,\n        learning_rate=learning_rate,\n        rho=rho,\n        epsilon=epsilon,\n        weight_decay=weight_decay,\n        maximize=maximize)\n\n\ndef _single_tensor_adadelta(params_grads,\n                            square_avgs,\n                            acc_deltas,\n                            *,\n                            learning_rate: float,\n                            rho: float,\n                            epsilon: float,\n                            weight_decay: float,\n                            maximize: bool):\n    \"\"\"\n    Calculate variables(square_avgs, acc_deltas) and update parameters.\n    \"\"\"\n\n    for (params_grad, square_avg, acc_delta) in zip(params_grads, square_avgs,\n                                                    acc_deltas):\n        param, grad = params_grad\n        grad = grad if not maximize else -grad\n        if weight_decay != 0:\n            grad.set_value(grad.add(paddle.multiply(param, weight_decay)))\n\n        if paddle.is_complex(param):\n            square_avg = paddle.as_real(square_avg)\n            acc_delta = paddle.as_real(acc_delta)\n            grad = paddle.as_real(grad)\n        # square_avg = square_avg * rho + (1-rho) * grad * grad\n        square_avg.set_value(\n            paddle.multiply(square_avg, paddle.to_tensor(rho)).add(\n                paddle.multiply(paddle.to_tensor(1 - rho), grad.square())))\n        # std = (square_avg + eps).sqrt()\n        std = square_avg.add(paddle.to_tensor(epsilon)).sqrt_()\n        # delta = std / (acc_delta + eps).sqrt() * grad\n        delta = (paddle.multiply(\n            paddle.divide(\n                acc_delta.add(paddle.to_tensor(epsilon)).sqrt_(), std), grad))\n        # acc_delta = acc_delta * rho + (1-rho) * delta * delta\n        acc_delta.set_value(\n            paddle.multiply(acc_delta, paddle.to_tensor(rho)).add(\n                paddle.multiply(paddle.to_tensor(1 - rho), delta.square())))\n        if paddle.is_complex(param):\n            delta = paddle.as_real(delta)\n        # param = param - delta*learning_rate\n        param.set_value(\n            param.add(\n                paddle.multiply(\n                    delta.astype('float32'), paddle.to_tensor(-learning_rate))))\n"
  },
  {
    "path": "paddlespeech/s2t/training/reporter.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport contextlib\nimport math\nfrom collections import defaultdict\n\nOBSERVATIONS = None\n\n\n@contextlib.contextmanager\ndef ObsScope(observations):\n    # make `observation` the target to report to.\n    # it is basically a dictionary that stores temporary observations\n    global OBSERVATIONS\n    old = OBSERVATIONS\n    OBSERVATIONS = observations\n\n    try:\n        yield\n    finally:\n        OBSERVATIONS = old\n\n\ndef get_observations():\n    global OBSERVATIONS\n    return OBSERVATIONS\n\n\ndef report(name, value):\n    # a simple function to report named value\n    # you can use it everywhere, it will get the default target and writ to it\n    # you can think of it as std.out\n    observations = get_observations()\n    if observations is None:\n        return\n    else:\n        observations[name] = value\n\n\nclass Summary():\n    \"\"\"Online summarization of a sequence of scalars.\n    Summary computes the statistics of given scalars online.\n    \"\"\"\n\n    def __init__(self):\n        self._x = 0.0\n        self._x2 = 0.0\n        self._n = 0\n\n    def add(self, value, weight=1):\n        \"\"\"Adds a scalar value.\n        Args:\n            value: Scalar value to accumulate. It is either a NumPy scalar or\n                a zero-dimensional array (on CPU or GPU).\n            weight: An optional weight for the value. It is a NumPy scalar or\n                a zero-dimensional array (on CPU or GPU).\n                Default is 1 (integer).\n        \"\"\"\n        self._x += weight * value\n        self._x2 += weight * value * value\n        self._n += weight\n\n    def compute_mean(self):\n        \"\"\"Computes the mean.\"\"\"\n        x, n = self._x, self._n\n        return x / n\n\n    def make_statistics(self):\n        \"\"\"Computes and returns the mean and standard deviation values.\n        Returns:\n            tuple: Mean and standard deviation values.\n        \"\"\"\n        x, n = self._x, self._n\n        mean = x / n\n        var = self._x2 / n - mean * mean\n        std = math.sqrt(var)\n        return mean, std\n\n\nclass DictSummary():\n    \"\"\"Online summarization of a sequence of dictionaries.\n    ``DictSummary`` computes the statistics of a given set of scalars online.\n    It only computes the statistics for scalar values and variables of scalar\n    values in the dictionaries.\n    \"\"\"\n\n    def __init__(self):\n        self._summaries = defaultdict(Summary)\n\n    def add(self, d):\n        \"\"\"Adds a dictionary of scalars.\n        Args:\n            d (dict): Dictionary of scalars to accumulate. Only elements of\n               scalars, zero-dimensional arrays, and variables of\n               zero-dimensional arrays are accumulated. When the value\n               is a tuple, the second element is interpreted as a weight.\n        \"\"\"\n        summaries = self._summaries\n        for k, v in d.items():\n            w = 1\n            if isinstance(v, tuple):\n                v = v[0]\n                w = v[1]\n            summaries[k].add(v, weight=w)\n\n    def compute_mean(self):\n        \"\"\"Creates a dictionary of mean values.\n        It returns a single dictionary that holds a mean value for each entry\n        added to the summary.\n        Returns:\n            dict: Dictionary of mean values.\n        \"\"\"\n        return {\n            name: summary.compute_mean()\n            for name, summary in self._summaries.items()\n        }\n\n    def make_statistics(self):\n        \"\"\"Creates a dictionary of statistics.\n        It returns a single dictionary that holds mean and standard deviation\n        values for every entry added to the summary. For an entry of name\n        ``'key'``, these values are added to the dictionary by names ``'key'``\n        and ``'key.std'``, respectively.\n        Returns:\n            dict: Dictionary of statistics of all entries.\n        \"\"\"\n        stats = {}\n        for name, summary in self._summaries.items():\n            mean, std = summary.make_statistics()\n            stats[name] = mean\n            stats[name + '.std'] = std\n\n        return stats\n"
  },
  {
    "path": "paddlespeech/s2t/training/scheduler.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Text\nfrom typing import Union\n\nimport paddle\nfrom paddle.optimizer.lr import LRScheduler\nfrom typeguard import typechecked\n\nfrom paddlespeech.s2t.utils.dynamic_import import dynamic_import\nfrom paddlespeech.s2t.utils.dynamic_import import instance_class\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"WarmupLR\", \"LRSchedulerFactory\"]\n\nlogger = Log(__name__).getlog()\n\nSCHEDULER_DICT = {\n    \"noam\": \"paddle.optimizer.lr:NoamDecay\",\n    \"expdecaylr\": \"paddle.optimizer.lr:ExponentialDecay\",\n    \"piecewisedecay\": \"paddle.optimizer.lr:PiecewiseDecay\",\n}\n\n\ndef register_scheduler(cls):\n    \"\"\"Register scheduler.\"\"\"\n    alias = cls.__name__.lower()\n    SCHEDULER_DICT[cls.__name__.lower()] = cls.__module__ + \":\" + cls.__name__\n    return cls\n\n\n@register_scheduler\nclass WarmupLR(LRScheduler):\n    \"\"\"The WarmupLR scheduler\n    This scheduler is almost same as NoamLR Scheduler except for following\n    difference:\n    NoamLR:\n        lr = optimizer.lr * model_size ** -0.5\n             * min(step ** -0.5, step * warmup_step ** -1.5)\n    WarmupLR:\n        lr = optimizer.lr * warmup_step ** 0.5\n             * min(step ** -0.5, step * warmup_step ** -1.5)\n    Note that the maximum lr equals to optimizer.lr in this scheduler.\n    \"\"\"\n\n    @typechecked\n    def __init__(self,\n                 warmup_steps: Union[int, float]=25000,\n                 learning_rate=1.0,\n                 last_epoch=-1,\n                 verbose=False,\n                 **kwargs):\n        self.warmup_steps = warmup_steps\n        super().__init__(learning_rate, last_epoch, verbose)\n\n    def __repr__(self):\n        return f\"{self.__class__.__name__}(warmup_steps={self.warmup_steps}, lr={self.base_lr}, last_epoch={self.last_epoch})\"\n\n    def get_lr(self):\n        # self.last_epoch start from zero\n        step_num = self.last_epoch + 1\n        return self.base_lr * self.warmup_steps**0.5 * min(\n            step_num**-0.5, step_num * self.warmup_steps**-1.5)\n\n    def set_step(self, step: int=None):\n        '''\n        It will update the learning rate in optimizer according to current ``epoch`` .\n        The new learning rate will take effect on next ``optimizer.step`` .\n\n        Args:\n            step (int, None): specify current epoch. Default: None. Auto-increment from last_epoch=-1.\n        Returns:\n            None\n        '''\n        self.step(epoch=step)\n\n\n@register_scheduler\nclass ConstantLR(LRScheduler):\n    \"\"\"\n    Args:\n        learning_rate (float): The initial learning rate. It is a python float number.\n        last_epoch (int, optional):  The index of last epoch. Can be set to restart training. Default: -1, means initial learning rate.\n        verbose (bool, optional): If ``True``, prints a message to stdout for each update. Default: ``False`` .\n\n    Returns:\n        ``ConstantLR`` instance to schedule learning rate.\n    \"\"\"\n\n    def __init__(self, learning_rate, last_epoch=-1, verbose=False):\n        super().__init__(learning_rate, last_epoch, verbose)\n\n    def get_lr(self):\n        return self.base_lr\n\n\n@register_scheduler\nclass NewBobScheduler(LRScheduler):\n    \"\"\"Scheduler with new-bob technique, used for LR annealing.\n\n    The learning rate is annealed based on the validation performance.\n    In particular: if (past_loss-current_loss)/past_loss< impr_threshold:\n    lr=lr * annealing_factor.\n\n    Arguments\n    ---------\n    initial_value : float\n        The initial hyperparameter value.\n    annealing_factor : float\n        It is annealing factor used in new_bob strategy.\n    improvement_threshold : float\n        It is the improvement rate between losses used to perform learning\n        annealing in new_bob strategy.\n    patient : int\n        When the annealing condition is violated patient times,\n        the learning rate is finally reduced.\n\n    Example\n    -------\n    >>> scheduler = NewBobScheduler(initial_value=1.0)\n    >>> scheduler(metric_value=10.0)\n    (1.0, 1.0)\n    >>> scheduler(metric_value=2.0)\n    (1.0, 1.0)\n    >>> scheduler(metric_value=2.5)\n    (1.0, 0.5)\n    \"\"\"\n\n    def __init__(\n            self,\n            learning_rate,\n            last_epoch=-1,\n            verbose=False,\n            annealing_factor=0.5,\n            improvement_threshold=0.0025,\n            patient=0, ):\n        self.hyperparam_value = learning_rate\n        self.annealing_factor = annealing_factor\n        self.improvement_threshold = improvement_threshold\n        self.patient = patient\n        self.metric_values = []\n        self.current_patient = self.patient\n        super().__init__(learning_rate, last_epoch, verbose)\n\n    def step(self, metric_value=None):\n        \"\"\"\n\n        ``step`` should be called after ``optimizer.step`` . It will update the learning rate in optimizer according to current ``epoch`` .\n        The new learning rate will take effect on next ``optimizer.step`` .\n\n        Args:\n            epoch (int, None): specify current epoch. Default: None. Auto-increment from last_epoch=-1.\n\n        Returns:\n            None\n        \"\"\"\n        if metric_value is None:\n            self.last_epoch += 1\n            self.last_lr = self.hyperparam_value\n        else:\n            self.last_epoch += 1\n            self.last_lr = self.get_lr(metric_value)\n\n        if self.verbose:\n            print('Epoch {}: {} set learning rate to {}.'.format(\n                self.last_epoch, self.__class__.__name__, self.last_lr))\n\n    def get_lr(self, metric_value):\n        \"\"\"Returns the current and new value for the hyperparameter.\n\n        Arguments\n        ---------\n        metric_value : int\n            A number for determining whether to change the hyperparameter value.\n        \"\"\"\n        new_value = self.hyperparam_value\n        if len(self.metric_values) > 0:\n            prev_metric = self.metric_values[-1]\n            # Update value if improvement too small and patience is 0\n            if prev_metric == 0:  # Prevent division by zero\n                improvement = 0\n            else:\n                improvement = (prev_metric - metric_value) / prev_metric\n            if improvement < self.improvement_threshold:\n                if self.current_patient == 0:\n                    new_value *= self.annealing_factor\n                    self.current_patient = self.patient\n                else:\n                    self.current_patient -= 1\n\n        # Store relevant info\n        self.metric_values.append(metric_value)\n        self.hyperparam_value = new_value\n\n        return new_value\n\n    def save(self):\n        \"\"\"Saves the current metrics on the specified path.\"\"\"\n        data = {\n            \"current_epoch_index\": self.last_epoch,\n            \"hyperparam_value\": self.hyperparam_value,\n            \"metric_values\": self.metric_values,\n            \"current_patient\": self.current_patient\n        }\n        return data\n\n    def load(self, data):\n        \"\"\"Loads the needed information.\"\"\"\n        self.last_epoch = data[\"current_epoch_index\"]\n        self.hyperparam_value = data[\"hyperparam_value\"]\n        self.metric_values = data[\"metric_values\"]\n        self.current_patient = data[\"current_patient\"]\n\n\ndef dynamic_import_scheduler(module):\n    \"\"\"Import Scheduler class dynamically.\n\n    Args:\n        module (str): module_name:class_name or alias in `SCHEDULER_DICT`\n\n    Returns:\n        type: Scheduler class\n\n    \"\"\"\n    module_class = dynamic_import(module, SCHEDULER_DICT)\n    assert issubclass(module_class,\n                      LRScheduler), f\"{module} does not implement LRScheduler\"\n    return module_class\n\n\nclass LRSchedulerFactory():\n    @classmethod\n    def from_args(cls, name: str, args: Dict[Text, Any]):\n        module_class = dynamic_import_scheduler(name.lower())\n        return instance_class(module_class, args)\n"
  },
  {
    "path": "paddlespeech/s2t/training/timer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport datetime\nimport time\n\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"Timer\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass Timer():\n    \"\"\"To be used like this: \n        with Timer(\"Message\") as value:\n            do some thing\n    \"\"\"\n\n    def __init__(self, message=None):\n        self.message = message\n\n    def duration(self) -> str:\n        elapsed_time = time.time() - self.start\n        time_str = str(datetime.timedelta(seconds=elapsed_time))\n        return time_str\n\n    def __enter__(self):\n        self.start = time.time()\n        return self\n\n    def __exit__(self, type, value, traceback):\n        if self.message:\n            logger.info(self.message.format(self.duration()))\n\n    def __call__(self) -> float:\n        return time.time() - self.start\n\n    def __str__(self):\n        return self.duration()\n"
  },
  {
    "path": "paddlespeech/s2t/training/trainer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\nimport time\nfrom collections import OrderedDict\nfrom contextlib import contextmanager\nfrom pathlib import Path\n\nimport paddle\nfrom paddle import distributed as dist\nworld_size = dist.get_world_size()\nif world_size > 1:\n    dist.init_parallel_env()\n\nfrom visualdl import LogWriter\n\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.timer import Timer\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils import profiler\nfrom paddlespeech.s2t.utils.checkpoint import Checkpoint\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.utility import all_version\nfrom paddlespeech.s2t.utils.utility import seed_all\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\n\n__all__ = [\"Trainer\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass Trainer():\n    \"\"\"\n    An experiment template in order to structure the training code and take\n    care of saving, loading, logging, visualization stuffs. It's intended to\n    be flexible and simple.\n\n    So it only handles output directory (create directory for the output,\n    create a checkpoint directory, dump the config in use and create\n    visualizer and logger) in a standard way without enforcing any\n    input-output protocols to the model and dataloader. It leaves the main\n    part for the user to implement their own (setup the model, criterion,\n    optimizer, define a training step, define a validation function and\n    customize all the text and visual logs).\n    It does not save too much boilerplate code. The users still have to write\n    the forward/backward/update mannually, but they are free to add\n    non-standard behaviors if needed.\n    We have some conventions to follow.\n    1. Experiment should have ``model``, ``optimizer``, ``train_loader`` and\n    ``valid_loader``, ``config`` and ``args`` attributes.\n    2. The config should have a ``training`` field, which has\n    ``valid_interval``, ``save_interval`` and ``max_iteration`` keys. It is\n    used as the trigger to invoke validation, checkpointing and stop of the\n    experiment.\n    3. There are four methods, namely ``train_batch``, ``valid``,\n    ``setup_model`` and ``setup_dataloader`` that should be implemented.\n    Feel free to add/overwrite other methods and standalone functions if you\n    need.\n\n    Parameters\n    ----------\n    config: yacs.config.CfgNode\n        The configuration used for the experiment.\n\n    args: argparse.Namespace\n        The parsed command line arguments.\n    Examples\n    --------\n    >>> def main_sp(config, args):\n    >>>     exp = Trainer(config, args)\n    >>>     exp.setup()\n    >>>     exp.run()\n    >>>\n    >>> config = get_cfg_defaults()\n    >>> parser = default_argument_parser()\n    >>> args = parser.parse_args()\n    >>> if args.config:\n    >>>     config.merge_from_file(args.config)\n    >>> if args.opts:\n    >>>     config.merge_from_list(args.opts)\n    >>> config.freeze()\n    >>>\n    >>> if args.ngpu > 1:\n    >>>     dist.spawn(main_sp, args=(config, args), nprocs=args.ngpu)\n    >>> else:\n    >>>     main_sp(config, args)\n    \"\"\"\n\n    def __init__(self, config, args):\n        self.config = config\n        self.args = args\n        self.optimizer = None\n        self.visualizer = None\n        self.output_dir = None\n        self.checkpoint_dir = None\n        self.iteration = 0\n        self.epoch = 0\n        self.rank = dist.get_rank()\n        self.world_size = dist.get_world_size()\n        self._train = True\n        self.scaler = None\n\n        # print deps version\n        all_version()\n        logger.info(f\"Rank: {self.rank}/{self.world_size}\")\n\n        # set device\n        if self.args.ngpu == 0:\n            if self.args.nxpu == 0:\n                paddle.set_device('cpu')\n            else:\n                paddle.set_device('xpu')\n        elif self.args.ngpu > 0:\n            paddle.set_device(\"gpu\")\n        else:\n            raise Exception(\"invalid device\")\n\n        self.checkpoint = Checkpoint(\n            kbest_n=self.config.checkpoint.kbest_n,\n            latest_n=self.config.checkpoint.latest_n)\n\n        # set random seed if needed\n        if args.seed:\n            seed_all(args.seed)\n            logger.info(f\"Set seed {args.seed}\")\n\n        # profiler and benchmark options\n        if hasattr(self.args,\n                   \"benchmark_batch_size\") and self.args.benchmark_batch_size:\n            with UpdateConfig(self.config):\n                self.config.batch_size = self.args.benchmark_batch_size\n                self.config.log_interval = 1\n            logger.info(\n                f\"Benchmark reset batch-size: {self.args.benchmark_batch_size}\")\n\n    @property\n    def train(self):\n        return self._train\n\n    @contextmanager\n    def eval(self):\n        self._train = False\n        yield\n        self._train = True\n\n    def setup(self):\n        \"\"\"Setup the experiment.\n        \"\"\"\n        self.setup_output_dir()\n        self.dump_config()\n        self.setup_visualizer()\n\n        self.setup_dataloader()\n        self.setup_model()\n\n        self.iteration = 0\n        self.epoch = 0\n\n    @property\n    def parallel(self):\n        \"\"\"A flag indicating whether the experiment should run with\n        multiprocessing.\n        \"\"\"\n        return self.args.ngpu > 1\n\n    @mp_tools.rank_zero_only\n    def save(self, tag=None, infos: dict=None):\n        \"\"\"Save checkpoint (model parameters and optimizer states).\n\n        Args:\n            tag (int or str, optional): None for step, else using tag, e.g epoch. Defaults to None.\n            infos (dict, optional): meta data to save. Defaults to None.\n        \"\"\"\n\n        infos = infos if infos else dict()\n        infos.update({\n            \"step\": self.iteration,\n            \"epoch\": self.epoch,\n            \"lr\": self.optimizer.get_lr(),\n        })\n        if self.scaler:\n            scaler_path = os.path.join(self.checkpoint_dir,\n                                       \"{}\".format(self.epoch)) + '.scaler'\n            paddle.save(self.scaler.state_dict(), scaler_path)\n\n        self.checkpoint.save_parameters(self.checkpoint_dir, self.iteration\n                                        if tag is None else tag, self.model,\n                                        self.optimizer, infos)\n\n    def resume_or_scratch(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        scratch = None\n        infos = self.checkpoint.load_latest_parameters(\n            self.model,\n            self.optimizer,\n            checkpoint_dir=self.checkpoint_dir,\n            checkpoint_path=self.args.checkpoint_path)\n        if infos:\n            # just restore ckpt\n            # lr will restore from optimizer ckpt\n            self.iteration = infos[\"step\"]\n            self.epoch = infos[\"epoch\"]\n\n            scaler_path = os.path.join(self.checkpoint_dir,\n                                       \"{}\".format(self.epoch)) + '.scaler'\n            if os.path.exists(scaler_path):\n                scaler_state_dict = paddle.load(scaler_path)\n                self.scaler.load_state_dict(scaler_state_dict)\n\n            scratch = False\n            logger.info(\n                f\"Restore ckpt: epoch {self.epoch }, step {self.iteration}!\")\n        else:\n            self.iteration = 0\n            self.epoch = 0\n            scratch = True\n            logger.info(\"Init from scratch!\")\n        return scratch\n\n    def maybe_batch_sampler_step(self):\n        \"\"\" batch_sampler seed by epoch \"\"\"\n        if hasattr(self.train_loader, \"batch_sampler\"):\n            batch_sampler = self.train_loader.batch_sampler\n            if isinstance(batch_sampler, paddle.io.DistributedBatchSampler):\n                logger.debug(\n                    f\"train_loader.batch_sample.set_epoch: {self.epoch}\")\n                batch_sampler.set_epoch(self.epoch)\n\n    def before_train(self):\n        from_scratch = self.resume_or_scratch()\n        if from_scratch:\n            # scratch: save init model, i.e. 0 epoch\n            self.save(tag='init', infos=None)\n        else:\n            # resume: train next_epoch and next_iteration\n            self.epoch += 1\n            self.iteration += 1\n            logger.info(\n                f\"Resume train: epoch {self.epoch }, step {self.iteration}!\")\n\n        self.maybe_batch_sampler_step()\n\n    def new_epoch(self):\n        \"\"\"Reset the train loader seed and increment `epoch`.\n        \"\"\"\n        # `iteration` increased by train step\n        self.epoch += 1\n        self.maybe_batch_sampler_step()\n\n    def after_train_batch(self):\n        if self.args.benchmark_max_step:\n            profiler.add_profiler_step(self.args.profiler_options)\n        if self.args.benchmark_max_step and self.iteration > self.args.benchmark_max_step:\n            logger.info(\n                f\"Reach benchmark-max-step: {self.args.benchmark_max_step}\")\n            sys.exit(0)\n\n    def do_train(self):\n        \"\"\"The training process control by epoch.\"\"\"\n        self.before_train()\n\n        logger.info(f\"Train Total Examples: {len(self.train_loader.dataset)}\")\n        while self.epoch < self.config.n_epoch:\n            with Timer(\"Epoch-Train Time Cost: {}\"):\n                self.model.train()\n                try:\n                    data_start_time = time.time()\n                    for batch_index, batch in enumerate(self.train_loader):\n                        dataload_time = time.time() - data_start_time\n                        msg = \"Train:\"\n                        observation = OrderedDict()\n                        with ObsScope(observation):\n                            report(\"Rank\", dist.get_rank())\n                            report(\"epoch\", self.epoch)\n                            report('step', self.iteration)\n                            report(\"lr\", self.lr_scheduler())\n                            self.train_batch(batch_index, batch, msg)\n                            self.after_train_batch()\n                            report('iter', batch_index + 1)\n                            report('total', len(self.train_loader))\n                            report('reader_cost', dataload_time)\n                        observation['batch_cost'] = observation[\n                            'reader_cost'] + observation['step_cost']\n                        observation['samples'] = observation['batch_size']\n                        observation['ips samples/s'] = observation[\n                            'batch_size'] / observation['batch_cost']\n                        for k, v in observation.items():\n                            msg += f\" {k}: \"\n                            msg += f\"{v:>.8f}\" if isinstance(v,\n                                                             float) else f\"{v}\"\n                            msg += \",\"\n                        msg = msg[:-1]  # remove the last \",\"\n                        if (batch_index + 1) % self.config.log_interval == 0:\n                            logger.info(msg)\n                        data_start_time = time.time()\n                except Exception as e:\n                    logger.error(e)\n                    raise e\n\n            with Timer(\"Eval Time Cost: {}\"):\n                total_loss, num_seen_utts = self.valid()\n                if dist.get_world_size() > 1:\n                    num_seen_utts = paddle.to_tensor(num_seen_utts)\n                    # the default operator in all_reduce function is sum.\n                    dist.all_reduce(num_seen_utts)\n                    total_loss = paddle.to_tensor(total_loss)\n                    dist.all_reduce(total_loss)\n                    cv_loss = total_loss / num_seen_utts\n                    cv_loss = float(cv_loss)\n                else:\n                    cv_loss = total_loss / num_seen_utts\n\n            logger.info(\n                'Epoch {} Val info val_loss {}'.format(self.epoch, cv_loss))\n            if self.visualizer:\n                self.visualizer.add_scalar(\n                    tag='eval/cv_loss', value=cv_loss, step=self.epoch)\n                self.visualizer.add_scalar(\n                    tag='eval/lr', value=self.lr_scheduler(), step=self.epoch)\n\n            # step lr every epoch\n            self.lr_scheduler.step()\n            # after epoch\n            self.save(tag=self.epoch, infos={'val_loss': cv_loss})\n            self.new_epoch()\n\n    def run(self):\n        \"\"\"The routine of the experiment after setup. This method is intended\n        to be used by the user.\n        \"\"\"\n        try:\n            with Timer(\"Training Done: {}\"):\n                self.do_train()\n        except KeyboardInterrupt:\n            exit(-1)\n        finally:\n            self.destory()\n\n    def restore(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        assert self.args.checkpoint_path\n        infos = self.checkpoint.load_latest_parameters(\n            self.model, checkpoint_path=self.args.checkpoint_path)\n        return infos\n\n    def run_test(self):\n        \"\"\"Do Test/Decode\"\"\"\n        try:\n            with Timer(\"Test/Decode Done: {}\"):\n                with self.eval():\n                    self.restore()\n                    self.test()\n        except KeyboardInterrupt:\n            exit(-1)\n\n    def run_export(self):\n        \"\"\"Do Model Export\"\"\"\n        try:\n            with Timer(\"Export Done: {}\"):\n                with self.eval():\n                    self.restore()\n                    self.export()\n        except KeyboardInterrupt:\n            exit(-1)\n\n    def run_align(self):\n        \"\"\"Do CTC alignment\"\"\"\n        try:\n            with Timer(\"Align Done: {}\"):\n                with self.eval():\n                    self.restore()\n                    self.align()\n        except KeyboardInterrupt:\n            sys.exit(-1)\n\n    def setup_output_dir(self):\n        \"\"\"Create a directory used for output.\n        \"\"\"\n        if self.args.output:\n            output_dir = Path(self.args.output).expanduser()\n        elif self.args.checkpoint_path:\n            output_dir = Path(\n                self.args.checkpoint_path).expanduser().parent.parent\n        elif self.args.export_path:\n            output_dir = Path(self.args.export_path).expanduser().parent.parent\n        self.output_dir = output_dir\n        self.output_dir.mkdir(parents=True, exist_ok=True)\n\n        self.checkpoint_dir = self.output_dir / \"checkpoints\"\n        self.checkpoint_dir.mkdir(parents=True, exist_ok=True)\n\n        self.log_dir = output_dir / \"log\"\n        self.log_dir.mkdir(parents=True, exist_ok=True)\n\n        self.test_dir = output_dir / \"test\"\n        self.test_dir.mkdir(parents=True, exist_ok=True)\n\n        self.decode_dir = output_dir / \"decode\"\n        self.decode_dir.mkdir(parents=True, exist_ok=True)\n\n        self.export_dir = output_dir / \"export\"\n        self.export_dir.mkdir(parents=True, exist_ok=True)\n\n        self.visual_dir = output_dir / \"visual\"\n        self.visual_dir.mkdir(parents=True, exist_ok=True)\n\n        self.config_dir = output_dir / \"conf\"\n        self.config_dir.mkdir(parents=True, exist_ok=True)\n\n    @mp_tools.rank_zero_only\n    def destory(self):\n        \"\"\"Close visualizer to avoid hanging after training\"\"\"\n        # https://github.com/pytorch/fairseq/issues/2357\n        if self.visualizer:\n            self.visualizer.close()\n\n    @mp_tools.rank_zero_only\n    def setup_visualizer(self):\n        \"\"\"Initialize a visualizer to log the experiment.\n\n        The visual log is saved in the output directory.\n\n        Notes\n        ------\n        Only the main process has a visualizer with it. Use multiple\n        visualizers in multiprocess to write to a same log file may cause\n        unexpected behaviors.\n        \"\"\"\n        # visualizer\n        visualizer = LogWriter(logdir=str(self.visual_dir))\n        self.visualizer = visualizer\n\n    @mp_tools.rank_zero_only\n    def dump_config(self):\n        \"\"\"Save the configuration used for this experiment.\n\n        It is saved in to ``config.yaml`` in the output directory at the\n        beginning of the experiment.\n        \"\"\"\n        config_file = self.config_dir / \"config.yaml\"\n        if self.train and config_file.exists():\n            time_stamp = time.strftime(\"%Y_%m_%d_%H_%M_%s\", time.gmtime())\n            target_path = self.config_dir / \".\".join(\n                [time_stamp, \"config.yaml\"])\n            config_file.rename(target_path)\n\n        with open(config_file, 'wt') as f:\n            print(self.config, file=f)\n\n    def train_batch(self):\n        \"\"\"The training loop. A subclass should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"train_batch should be implemented.\")\n\n    @paddle.no_grad()\n    def valid(self):\n        \"\"\"The validation. A subclass should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"valid should be implemented.\")\n\n    @paddle.no_grad()\n    def test(self):\n        \"\"\"The test. A subclass should implement this method in Tester.\n        \"\"\"\n        raise NotImplementedError(\"test should be implemented.\")\n\n    @paddle.no_grad()\n    def export(self):\n        \"\"\"The test. A subclass should implement this method in Tester.\n        \"\"\"\n        raise NotImplementedError(\"export should be implemented.\")\n\n    @paddle.no_grad()\n    def align(self):\n        \"\"\"The align. A subclass should implement this method in Tester.\n        \"\"\"\n        raise NotImplementedError(\"align should be implemented.\")\n\n    def setup_model(self):\n        \"\"\"Setup model, criterion and optimizer, etc. A subclass should\n        implement this method.\n        \"\"\"\n        raise NotImplementedError(\"setup_model should be implemented.\")\n\n    def setup_dataloader(self):\n        \"\"\"Setup training dataloader and validation dataloader. A subclass\n        should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"setup_dataloader should be implemented.\")\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/compare_value_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom ..reporter import DictSummary\nfrom .utils import get_trigger\n\n\nclass CompareValueTrigger():\n    \"\"\"Trigger invoked when key value getting bigger or lower than before.\n\n    Args:\n        key (str) : Key of value.\n        compare_fn ((float, float) -> bool) : Function to compare the values.\n        trigger (tuple(int, str)) : Trigger that decide the comparison interval.\n\n    \"\"\"\n\n    def __init__(self, key, compare_fn, trigger=(1, \"epoch\")):\n        self._key = key\n        self._best_value = None\n        self._interval_trigger = get_trigger(trigger)\n        self._init_summary()\n        self._compare_fn = compare_fn\n\n    def __call__(self, trainer):\n        \"\"\"Get value related to the key and compare with current value.\"\"\"\n        observation = trainer.observation\n        summary = self._summary\n        key = self._key\n        if key in observation:\n            summary.add({key: observation[key]})\n\n        if not self._interval_trigger(trainer):\n            return False\n\n        stats = summary.compute_mean()\n        value = float(stats[key])  # copy to CPU\n        self._init_summary()\n\n        if self._best_value is None:\n            # initialize best value\n            self._best_value = value\n            return False\n        elif self._compare_fn(self._best_value, value):\n            return True\n        else:\n            self._best_value = value\n            return False\n\n    def _init_summary(self):\n        self._summary = DictSummary()\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/interval_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass IntervalTrigger():\n    \"\"\"A Predicate to do something every N cycle.\"\"\"\n\n    def __init__(self, period: int, unit: str):\n        if unit not in (\"iteration\", \"epoch\"):\n            raise ValueError(\"unit should be 'iteration' or 'epoch'\")\n        if period <= 0:\n            raise ValueError(\"period should be a positive integer.\")\n        self.period = period\n        self.unit = unit\n        self.last_index = None\n\n    def __call__(self, trainer):\n        if self.last_index is None:\n            last_index = getattr(trainer.updater.state, self.unit)\n            self.last_index = last_index\n\n        last_index = self.last_index\n        index = getattr(trainer.updater.state, self.unit)\n        fire = index // self.period != last_index // self.period\n\n        self.last_index = index\n        return fire\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/limit_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass LimitTrigger():\n    \"\"\"A Predicate to decide whether to stop.\"\"\"\n\n    def __init__(self, limit: int, unit: str):\n        if unit not in (\"iteration\", \"epoch\"):\n            raise ValueError(\"unit should be 'iteration' or 'epoch'\")\n        if limit <= 0:\n            raise ValueError(\"limit should be a positive integer.\")\n        self.limit = limit\n        self.unit = unit\n\n    def __call__(self, trainer):\n        state = trainer.updater.state\n        index = getattr(state, self.unit)\n        fire = index >= self.limit\n        return fire\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/time_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass TimeTrigger():\n    \"\"\"Trigger based on a fixed time interval.\n    This trigger accepts iterations with a given interval time.\n    Args:\n        period (float): Interval time. It is given in seconds.\n    \"\"\"\n\n    def __init__(self, period):\n        self._period = period\n        self._next_time = self._period\n\n    def __call__(self, trainer):\n        if self._next_time < trainer.elapsed_time:\n            self._next_time += self._period\n            return True\n        else:\n            return False\n\n    def state_dict(self):\n        state_dict = {\n            \"next_time\": self._next_time,\n        }\n        return state_dict\n\n    def set_state_dict(self, state_dict):\n        self._next_time = state_dict['next_time']\n"
  },
  {
    "path": "paddlespeech/s2t/training/triggers/utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .interval_trigger import IntervalTrigger\n\n\ndef never_fail_trigger(trainer):\n    return False\n\n\ndef get_trigger(trigger):\n    if trigger is None:\n        return never_fail_trigger\n    if callable(trigger):\n        return trigger\n    else:\n        trigger = IntervalTrigger(*trigger)\n        return trigger\n"
  },
  {
    "path": "paddlespeech/s2t/training/updaters/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/training/updaters/standard_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom typing import Dict\nfrom typing import Optional\n\nimport paddle\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.s2t.training.reporter import report\nfrom paddlespeech.s2t.training.updaters.updater import UpdaterBase\nfrom paddlespeech.s2t.training.updaters.updater import UpdaterState\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"StandardUpdater\"]\n\nlogger = Log(__name__).getlog()\n\n\nclass StandardUpdater(UpdaterBase):\n    \"\"\"An example of over-simplification. Things may not be that simple, but\n    you can subclass it to fit your need.\n    \"\"\"\n\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 scheduler: LRScheduler,\n                 dataloader: DataLoader,\n                 init_state: Optional[UpdaterState]=None):\n        super().__init__(init_state)\n        # it is designed to hold multiple models\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        self.model = model\n\n        # it is designed to hold multiple optimizers\n        optimizers = {\"main\": optimizer}\n        self.optimizer = optimizer\n        self.optimizers: Dict[str, Optimizer] = optimizers\n\n        # it is designed to hold multiple scheduler\n        schedulers = {\"main\": scheduler}\n        self.scheduler = scheduler\n        self.schedulers: Dict[str, LRScheduler] = schedulers\n\n        # dataloaders\n        self.dataloader = dataloader\n\n        self.train_iterator = iter(dataloader)\n\n    def update(self):\n        # We increase the iteration index after updating and before extension.\n        # Here are the reasons.\n\n        # 0. Snapshotting(as well as other extensions, like visualizer) is\n        #    executed after a step of updating;\n        # 1. We decide to increase the iteration index after updating and\n        #    before any all extension is executed. \n        # 3. We do not increase the iteration after extension because we\n        #    prefer a consistent resume behavior, when load from a\n        #    `snapshot_iter_100.pdz` then the next step to train is `101`,\n        #    naturally. But if iteration is increased increased after\n        #    extension(including snapshot), then, a `snapshot_iter_99` is\n        #    loaded. You would need a extra increasing of the iteration idex\n        #    before training to avoid another iteration `99`, which has been\n        #    done before snapshotting.\n        # 4. Thus iteration index represrnts \"currently how mant epochs has\n        #    been done.\"\n        # NOTE: use report to capture the correctly value. If you want to\n        # report the learning rate used for a step, you must report it before\n        # the learning rate scheduler's step() has been called. In paddle's\n        # convention, we do not use an extension to change the learning rate.\n        # so if you want to report it, do it in the updater.\n\n        # Then here comes the next question. When is the proper time to\n        # increase the epoch index? Since all extensions are executed after\n        # updating, it is the time that after updating is the proper time to\n        # increase epoch index.\n        # 1. If we increase the epoch index before updating, then an extension\n        #    based ot epoch would miss the correct timing. It could only be\n        #    triggerd after an extra updating.\n        # 2. Theoretically, when an epoch is done, the epoch index should be\n        #    increased. So it would be increase after updating.\n        # 3. Thus, eppoch index represents \"currently how many epochs has been\n        #    done.\" So it starts from 0.\n\n        # switch to training mode\n        for model in self.models.values():\n            model.train()\n\n        # training for a step is implemented here\n        with Timier(\"data time cost:{}\"):\n            batch = self.read_batch()\n        with Timier(\"step time cost:{}\"):\n            self.update_core(batch)\n\n        self.state.iteration += 1\n        if self.updates_per_epoch is not None:\n            if self.state.iteration % self.updates_per_epoch == 0:\n                self.state.epoch += 1\n\n    def update_core(self, batch):\n        \"\"\"A simple case for a training step. Basic assumptions are:\n        Single model;\n        Single optimizer;\n        Single scheduler, and update learning rate each step;\n        A batch from the dataloader is just the input of the model;\n        The model return a single loss, or a dict containing serval losses.\n        Parameters updates at every batch, no gradient accumulation.\n        \"\"\"\n        loss = self.model(*batch)\n\n        if isinstance(loss, paddle.Tensor):\n            loss_dict = {\"main\": loss}\n        else:\n            # Dict[str, Tensor]\n            loss_dict = loss\n            if \"main\" not in loss_dict:\n                main_loss = 0\n                for loss_item in loss.values():\n                    main_loss += loss_item\n                loss_dict[\"main\"] = main_loss\n\n        for name, loss_item in loss_dict.items():\n            report(name, float(loss_item))\n\n        self.optimizer.clear_grad()\n        loss_dict[\"main\"].backward()\n        self.optimizer.step()\n        self.scheduler.step()\n\n    @property\n    def updates_per_epoch(self):\n        \"\"\"Number of steps per epoch, \n        determined by the length of the dataloader.\"\"\"\n        length_of_dataloader = None\n        try:\n            length_of_dataloader = len(self.dataloader)\n        except TypeError:\n            logger.debug(\"This dataloader has no __len__.\")\n        finally:\n            return length_of_dataloader\n\n    def new_epoch(self):\n        \"\"\"Start a new epoch.\"\"\"\n        # NOTE: all batch sampler for distributed training should\n        # subclass DistributedBatchSampler and implement `set_epoch` method\n        if hasattr(self.dataloader, \"batch_sampler\"):\n            batch_sampler = self.dataloader.batch_sampler\n            if isinstance(batch_sampler, DistributedBatchSampler):\n                batch_sampler.set_epoch(self.state.epoch)\n        self.train_iterator = iter(self.dataloader)\n\n    def read_batch(self):\n        \"\"\"Read a batch from the data loader, auto renew when data is exhausted.\"\"\"\n        try:\n            batch = next(self.train_iterator)\n        except StopIteration:\n            self.new_epoch()\n            batch = next(self.train_iterator)\n        return batch\n\n    def state_dict(self):\n        \"\"\"State dict of a Updater, model, optimizers/schedulers \n        and updater state are included.\"\"\"\n        state_dict = super().state_dict()\n        for name, model in self.models.items():\n            state_dict[f\"{name}_params\"] = model.state_dict()\n        for name, optim in self.optimizers.items():\n            state_dict[f\"{name}_optimizer\"] = optim.state_dict()\n        return state_dict\n\n    def set_state_dict(self, state_dict):\n        \"\"\"Set state dict for a Updater. Parameters of models, states for\n        optimizers/schedulers and UpdaterState are restored.\"\"\"\n        for name, model in self.models.items():\n            model.set_state_dict(state_dict[f\"{name}_params\"])\n        for name, optim in self.optimizers.items():\n            optim.set_state_dict(state_dict[f\"{name}_optimizer\"])\n        super().set_state_dict(state_dict)\n"
  },
  {
    "path": "paddlespeech/s2t/training/updaters/trainer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport sys\nimport traceback\nfrom collections import OrderedDict\nfrom pathlib import Path\nfrom typing import Callable\nfrom typing import List\nfrom typing import Union\n\nimport six\nimport tqdm\n\nfrom paddlespeech.s2t.training.extensions.extension import Extension\nfrom paddlespeech.s2t.training.extensions.extension import PRIORITY_READER\nfrom paddlespeech.s2t.training.reporter import ObsScope\nfrom paddlespeech.s2t.training.triggers import get_trigger\nfrom paddlespeech.s2t.training.triggers.limit_trigger import LimitTrigger\nfrom paddlespeech.s2t.training.updaters.updater import UpdaterBase\n\n\nclass _ExtensionEntry():\n    def __init__(self, extension, trigger, priority):\n        self.extension = extension\n        self.trigger = trigger\n        self.priority = priority\n\n\nclass Trainer():\n    def __init__(self,\n                 updater: UpdaterBase,\n                 stop_trigger: Callable=None,\n                 out: Union[str, Path]='result',\n                 extensions: List[Extension]=None):\n        self.updater = updater\n        self.extensions = OrderedDict()\n        self.stop_trigger = LimitTrigger(*stop_trigger)\n        self.out = Path(out)\n        self.observation = None\n\n        self._done = False\n        if extensions:\n            for ext in extensions:\n                self.extend(ext)\n\n    @property\n    def is_before_training(self):\n        return self.updater.state.iteration == 0\n\n    def extend(self, extension, name=None, trigger=None, priority=None):\n        # get name for the extension\n        # argument \\\n        # -> extention's name \\\n        # -> default_name (class name, when it is an object) \\\n        # -> function name when it is a function \\\n        # -> error\n\n        if name is None:\n            name = getattr(extension, 'name', None)\n            if name is None:\n                name = getattr(extension, 'default_name', None)\n                if name is None:\n                    name = getattr(extension, '__name__', None)\n                    if name is None:\n                        raise ValueError(\"Name is not given for the extension.\")\n        if name == 'training':\n            raise ValueError(\"training is a reserved name.\")\n\n        if trigger is None:\n            trigger = getattr(extension, 'trigger', (1, 'iteration'))\n        trigger = get_trigger(trigger)\n\n        if priority is None:\n            priority = getattr(extension, 'priority', PRIORITY_READER)\n\n        # add suffix to avoid nameing conflict\n        ordinal = 0\n        modified_name = name\n        while modified_name in self.extensions:\n            ordinal += 1\n            modified_name = f\"{name}_{ordinal}\"\n        extension.name = modified_name\n\n        self.extensions[modified_name] = _ExtensionEntry(extension, trigger,\n                                                         priority)\n\n    def get_extension(self, name):\n        \"\"\"get extension by name.\"\"\"\n        extensions = self.extensions\n        if name in extensions:\n            return extensions[name].extension\n        else:\n            raise ValueError(f'extension {name} not found')\n\n    def run(self):\n        if self._done:\n            raise RuntimeError(\"Training is already done!.\")\n\n        self.out.mkdir(parents=True, exist_ok=True)\n\n        # sort extensions by priorities once\n        extension_order = sorted(\n            self.extensions.keys(),\n            key=lambda name: self.extensions[name].priority,\n            reverse=True)\n        extensions = [(name, self.extensions[name]) for name in extension_order]\n\n        # initializing all extensions\n        for name, entry in extensions:\n            if hasattr(entry.extension, \"initialize\"):\n                entry.extension.initialize(self)\n\n        update = self.updater.update  # training step\n        stop_trigger = self.stop_trigger\n\n        # display only one progress bar\n        max_iteration = None\n        if isinstance(stop_trigger, LimitTrigger):\n            if stop_trigger.unit == 'epoch':\n                max_epoch = self.stop_trigger.limit\n                updates_per_epoch = getattr(self.updater, \"updates_per_epoch\",\n                                            None)\n                max_iteration = max_epoch * updates_per_epoch if updates_per_epoch else None\n            else:\n                max_iteration = self.stop_trigger.limit\n\n        p = tqdm.tqdm(initial=self.updater.state.iteration, total=max_iteration)\n\n        try:\n            while not stop_trigger(self):\n                self.observation = {}\n                # set observation as the `report` target\n                # you can use `report` freely in Updater.update()\n\n                # updating parameters and state\n                with ObsScope(self.observation):\n                    update()\n                    p.update()\n\n                    # execute extension when necessary\n                    for name, entry in extensions:\n                        if entry.trigger(self):\n                            entry.extension(self)\n\n                # print(\"###\", self.observation)\n        except Exception as e:\n            f = sys.stderr\n            f.write(f\"Exception in main training loop: {e}\\n\")\n            f.write(\"Traceback (most recent call last):\\n\")\n            traceback.print_tb(sys.exc_info()[2])\n            f.write(\n                \"Trainer extensions will try to handle the extension. Then all extensions will finalize.\"\n            )\n\n            # capture the exception in the mian training loop\n            exc_info = sys.exc_info()\n\n            # try to handle it\n            for name, entry in extensions:\n                if hasattr(entry.extension, \"on_error\"):\n                    try:\n                        entry.extension.on_error(self, e, sys.exc_info()[2])\n                    except Exception as ee:\n                        f.write(f\"Exception in error handler: {ee}\\n\")\n                        f.write('Traceback (most recent call last):\\n')\n                        traceback.print_tb(sys.exc_info()[2])\n\n            # raise exception in main training loop\n            six.reraise(*exc_info)\n        finally:\n            for name, entry in extensions:\n                if hasattr(entry.extension, \"finalize\"):\n                    entry.extension.finalize(self)\n"
  },
  {
    "path": "paddlespeech/s2t/training/updaters/updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom dataclasses import dataclass\n\nimport paddle\n\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"UpdaterBase\", \"UpdaterState\"]\n\nlogger = Log(__name__).getlog()\n\n\n@dataclass\nclass UpdaterState:\n    iteration: int = 0\n    epoch: int = 0\n\n\nclass UpdaterBase():\n    \"\"\"An updater is the abstraction of how a model is trained given the\n    dataloader and the optimizer.\n    The `update_core` method is a step in the training loop with only necessary\n    operations (get a batch, forward and backward, update the parameters).\n    Other stuffs are made extensions. Visualization, saving, loading and\n    periodical validation and evaluation are not considered here.\n    But even in such simplist case, things are not that simple. There is an\n    attempt to standardize this process and requires only the model and\n    dataset and do all the stuffs automatically. But this may hurt flexibility.\n    If we assume a batch yield from the dataloader is just the input to the\n    model, we will find that some model requires more arguments, or just some\n    keyword arguments. But this prevents us from over-simplifying it.\n    From another perspective, the batch may includes not just the input, but\n    also the target. But the model's forward method may just need the input.\n    We can pass a dict or a super-long tuple to the model and let it pick what\n    it really needs. But this is an abuse of lazy interface.\n    After all, we care about how a model is trained. But just how the model is\n    used for inference. We want to control how a model is trained. We just\n    don't want to be messed up with other auxiliary code.\n    So the best practice is to define a model and define a updater for it.\n    \"\"\"\n\n    def __init__(self, init_state=None):\n        # init state\n        if init_state is None:\n            self.state = UpdaterState()\n        else:\n            self.state = init_state\n\n    def update(self, batch):\n        raise NotImplementedError(\n            \"Implement your own `update` method for training a step.\")\n\n    def state_dict(self):\n        state_dict = {\n            \"epoch\": self.state.epoch,\n            \"iteration\": self.state.iteration,\n        }\n        return state_dict\n\n    def set_state_dict(self, state_dict):\n        self.state.epoch = state_dict[\"epoch\"]\n        self.state.iteration = state_dict[\"iteration\"]\n\n    def save(self, path):\n        logger.debug(f\"Saving to {path}.\")\n        archive = self.state_dict()\n        paddle.save(archive, str(path))\n\n    def load(self, path):\n        logger.debug(f\"Loading from {path}.\")\n        archive = paddle.load(str(path))\n        self.set_state_dict(archive)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/utils/asr_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference espnet Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\nimport json\n\nimport numpy as np\n\n__all__ = [\"label_smoothing_dist\"]\n\n\ndef label_smoothing_dist(odim, lsm_type, transcript=None, blank=0):\n    \"\"\"Obtain label distribution for loss smoothing.\n\n    :param odim:\n    :param lsm_type:\n    :param blank:\n    :param transcript:\n    :return:\n    \"\"\"\n    if transcript is not None:\n        with open(transcript, \"rb\") as f:\n            trans_json = json.load(f)[\"utts\"]\n\n    if lsm_type == \"unigram\":\n        assert transcript is not None, (\n            \"transcript is required for %s label smoothing\" % lsm_type)\n        labelcount = np.zeros(odim)\n        for k, v in trans_json.items():\n            ids = np.array([int(n) for n in v[\"output\"][0][\"tokenid\"].split()])\n            # to avoid an error when there is no text in an uttrance\n            if len(ids) > 0:\n                labelcount[ids] += 1\n        labelcount[odim - 1] = len(transcript)  # count <eos>\n        labelcount[labelcount == 0] = 1  # flooring\n        labelcount[blank] = 0  # remove counts for blank\n        labeldist = labelcount.astype(np.float32) / np.sum(labelcount)\n    else:\n        logging.error(\"Error: unexpected label smoothing type: %s\" % lsm_type)\n        sys.exit()\n\n    return labeldist\n"
  },
  {
    "path": "paddlespeech/s2t/utils/bleu_score.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"This module provides functions to calculate bleu score in different level.\ne.g. wer for word-level, cer for char-level.\n\"\"\"\nimport numpy as np\nimport sacrebleu\n\n__all__ = ['bleu', 'char_bleu', \"ErrorCalculator\"]\n\n\ndef bleu(hypothesis, reference):\n    \"\"\"Calculate BLEU. BLEU compares reference text and\n    hypothesis text in word-level using scarebleu.\n\n    :param reference: The reference sentences.\n    :type reference: list[list[str]]\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: list[str]\n    :raises ValueError: If the reference length is zero.\n    \"\"\"\n\n    return sacrebleu.corpus_bleu(hypothesis, reference)\n\n\ndef char_bleu(hypothesis, reference):\n    \"\"\"Calculate BLEU. BLEU compares reference text and\n    hypothesis text in char-level using scarebleu.\n\n    :param reference: The reference sentences.\n    :type reference: list[list[str]]\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: list[str]\n    :raises ValueError: If the reference number is zero.\n    \"\"\"\n    hypothesis = [' '.join(list(hyp.replace(' ', ''))) for hyp in hypothesis]\n    reference = [[' '.join(list(ref_i.replace(' ', ''))) for ref_i in ref]\n                 for ref in reference]\n\n    return sacrebleu.corpus_bleu(hypothesis, reference)\n\n\nclass ErrorCalculator():\n    \"\"\"Calculate BLEU for ST and MT models during training.\n\n    :param y_hats: numpy array with predicted text\n    :param y_pads: numpy array with true (target) text\n    :param char_list: vocabulary list\n    :param sym_space: space symbol\n    :param sym_pad: pad symbol\n    :param report_bleu: report BLUE score if True\n    \"\"\"\n\n    def __init__(self, char_list, sym_space, sym_pad, report_bleu=False):\n        \"\"\"Construct an ErrorCalculator object.\"\"\"\n        super().__init__()\n        self.char_list = char_list\n        self.space = sym_space\n        self.pad = sym_pad\n        self.report_bleu = report_bleu\n        if self.space in self.char_list:\n            self.idx_space = self.char_list.index(self.space)\n        else:\n            self.idx_space = None\n\n    def __call__(self, ys_hat, ys_pad):\n        \"\"\"Calculate corpus-level BLEU score.\n\n        :param torch.Tensor ys_hat: prediction (batch, seqlen)\n        :param torch.Tensor ys_pad: reference (batch, seqlen)\n        :return: corpus-level BLEU score in a mini-batch\n        :rtype float\n        \"\"\"\n        bleu = None\n        if not self.report_bleu:\n            return bleu\n\n        bleu = self.calculate_corpus_bleu(ys_hat, ys_pad)\n        return bleu\n\n    def calculate_corpus_bleu(self, ys_hat, ys_pad):\n        \"\"\"Calculate corpus-level BLEU score in a mini-batch.\n\n        :param torch.Tensor seqs_hat: prediction (batch, seqlen)\n        :param torch.Tensor seqs_true: reference (batch, seqlen)\n        :return: corpus-level BLEU score\n        :rtype float\n        \"\"\"\n        seqs_hat, seqs_true = [], []\n        for i, y_hat in enumerate(ys_hat):\n            y_true = ys_pad[i]\n            eos_true = np.where(y_true == -1)[0]\n            ymax = eos_true[0] if len(eos_true) > 0 else len(y_true)\n            # NOTE: padding index (-1) in y_true is used to pad y_hat\n            # because y_hats is not padded with -1\n            seq_hat = [self.char_list[int(idx)] for idx in y_hat[:ymax]]\n            seq_true = [\n                self.char_list[int(idx)] for idx in y_true if int(idx) != -1\n            ]\n            seq_hat_text = \"\".join(seq_hat).replace(self.space, \" \")\n            seq_hat_text = seq_hat_text.replace(self.pad, \"\")\n            seq_true_text = \"\".join(seq_true).replace(self.space, \" \")\n            seqs_hat.append(seq_hat_text)\n            seqs_true.append(seq_true_text)\n        bleu = sacrebleu.corpus_bleu(seqs_hat, [[ref] for ref in seqs_true])\n        return bleu.score * 100\n"
  },
  {
    "path": "paddlespeech/s2t/utils/check_kwargs.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport inspect\n\n\ndef check_kwargs(func, kwargs, name=None):\n    \"\"\"check kwargs are valid for func\n\n    If kwargs are invalid, raise TypeError as same as python default\n    :param function func: function to be validated\n    :param dict kwargs: keyword arguments for func\n    :param str name: name used in TypeError (default is func name)\n    \"\"\"\n    try:\n        params = inspect.signature(func).parameters\n    except ValueError:\n        return\n    if name is None:\n        name = func.__name__\n    for k in kwargs.keys():\n        if k not in params:\n            raise TypeError(\n                f\"{name}() got an unexpected keyword argument '{k}'\")\n"
  },
  {
    "path": "paddlespeech/s2t/utils/checkpoint.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport glob\nimport json\nimport os\nimport re\nfrom pathlib import Path\nfrom typing import Text\nfrom typing import Union\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.s2t.utils import mp_tools\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"Checkpoint\"]\n\n\nclass Checkpoint():\n    def __init__(self, kbest_n: int=5, latest_n: int=1):\n        self.best_records: Mapping[Path, float] = {}\n        self.latest_records = []\n        self.kbest_n = kbest_n\n        self.latest_n = latest_n\n        self._save_all = (kbest_n == -1)\n\n    def save_parameters(self,\n                        checkpoint_dir,\n                        tag_or_iteration: Union[int, Text],\n                        model: paddle.nn.Layer,\n                        optimizer: Optimizer=None,\n                        infos: dict=None,\n                        metric_type=\"val_loss\"):\n        \"\"\"Save checkpoint in best_n and latest_n.\n\n        Args:\n            checkpoint_dir (str): the directory where checkpoint is saved.\n            tag_or_iteration (int or str): the latest iteration(step or epoch) number or tag.\n            model (Layer):  model to be checkpointed.\n            optimizer (Optimizer, optional): optimizer to be checkpointed.\n            infos (dict or None)):  any info you want to save.\n            metric_type (str, optional): metric type. Defaults to \"val_loss\".\n        \"\"\"\n        if (metric_type not in infos.keys()):\n            self._save_parameters(checkpoint_dir, tag_or_iteration, model,\n                                  optimizer, infos)\n            return\n\n        #save best\n        if self._should_save_best(infos[metric_type]):\n            self._save_best_checkpoint_and_update(\n                infos[metric_type], checkpoint_dir, tag_or_iteration, model,\n                optimizer, infos)\n        #save latest\n        self._save_latest_checkpoint_and_update(\n            checkpoint_dir, tag_or_iteration, model, optimizer, infos)\n\n        if isinstance(tag_or_iteration, int):\n            self._save_checkpoint_record(checkpoint_dir, tag_or_iteration)\n\n    def load_parameters(self,\n                        model,\n                        optimizer=None,\n                        checkpoint_dir=None,\n                        checkpoint_path=None,\n                        record_file=\"checkpoint_latest\"):\n        \"\"\"Load a last model checkpoint from disk.\n        Args:\n            model (Layer): model to load parameters.\n            optimizer (Optimizer, optional): optimizer to load states if needed.\n                Defaults to None.\n            checkpoint_dir (str, optional): the directory where checkpoint is saved.\n            checkpoint_path (str, optional): if specified, load the checkpoint\n                stored in the checkpoint_path(prefix) and the argument 'checkpoint_dir' will\n                be ignored. Defaults to None.\n            record_file \"checkpoint_latest\" or \"checkpoint_best\"\n        Returns:\n            configs (dict): epoch or step, lr and other meta info should be saved.\n        \"\"\"\n        configs = {}\n\n        if checkpoint_path:\n            pass\n        elif checkpoint_dir is not None and record_file is not None:\n            # load checkpint from record file\n            checkpoint_record = os.path.join(checkpoint_dir, record_file)\n            iteration = self._load_checkpoint_idx(checkpoint_record)\n            if iteration == -1:\n                return configs\n            checkpoint_path = os.path.join(checkpoint_dir,\n                                           \"{}\".format(iteration))\n        else:\n            raise ValueError(\n                \"At least one of 'checkpoint_path' or 'checkpoint_dir' should be specified!\"\n            )\n\n        rank = dist.get_rank()\n\n        params_path = checkpoint_path + \".pdparams\"\n        model_dict = paddle.load(params_path)\n        model.set_state_dict(model_dict)\n        logger.info(\"Rank {}: Restore model from {}\".format(rank, params_path))\n\n        optimizer_path = checkpoint_path + \".pdopt\"\n        if optimizer and os.path.isfile(optimizer_path):\n            optimizer_dict = paddle.load(optimizer_path)\n            optimizer.set_state_dict(optimizer_dict)\n            logger.info(\"Rank {}: Restore optimizer state from {}\".format(\n                rank, optimizer_path))\n\n        info_path = re.sub('.pdparams$', '.json', params_path)\n        if os.path.exists(info_path):\n            with open(info_path, 'r') as fin:\n                configs = json.load(fin)\n        return configs\n\n    def load_latest_parameters(self,\n                               model,\n                               optimizer=None,\n                               checkpoint_dir=None,\n                               checkpoint_path=None):\n        \"\"\"Load a last model checkpoint from disk.\n        Args:\n            model (Layer): model to load parameters.\n            optimizer (Optimizer, optional): optimizer to load states if needed.\n                Defaults to None.\n            checkpoint_dir (str, optional): the directory where checkpoint is saved.\n            checkpoint_path (str, optional): if specified, load the checkpoint\n                stored in the checkpoint_path(prefix) and the argument 'checkpoint_dir' will\n                be ignored. Defaults to None.\n        Returns:\n            configs (dict): epoch or step, lr and other meta info should be saved.\n        \"\"\"\n        return self.load_parameters(model, optimizer, checkpoint_dir,\n                                    checkpoint_path, \"checkpoint_latest\")\n\n    def load_best_parameters(self,\n                             model,\n                             optimizer=None,\n                             checkpoint_dir=None,\n                             checkpoint_path=None):\n        \"\"\"Load a last model checkpoint from disk.\n        Args:\n            model (Layer): model to load parameters.\n            optimizer (Optimizer, optional): optimizer to load states if needed.\n                Defaults to None.\n            checkpoint_dir (str, optional): the directory where checkpoint is saved.\n            checkpoint_path (str, optional): if specified, load the checkpoint\n                stored in the checkpoint_path(prefix) and the argument 'checkpoint_dir' will\n                be ignored. Defaults to None.\n        Returns:\n            configs (dict): epoch or step, lr and other meta info should be saved.\n        \"\"\"\n        return self.load_parameters(model, optimizer, checkpoint_dir,\n                                    checkpoint_path, \"checkpoint_best\")\n\n    def _should_save_best(self, metric: float) -> bool:\n        if not self._best_full():\n            return True\n\n        # already full\n        worst_record_path = max(self.best_records, key=self.best_records.get)\n        # worst_record_path = max(self.best_records.iteritems(), key=operator.itemgetter(1))[0]\n        worst_metric = self.best_records[worst_record_path]\n        return metric < worst_metric\n\n    def _best_full(self):\n        return (not self._save_all) and len(self.best_records) == self.kbest_n\n\n    def _latest_full(self):\n        return len(self.latest_records) == self.latest_n\n\n    def _save_best_checkpoint_and_update(self, metric, checkpoint_dir,\n                                         tag_or_iteration, model, optimizer,\n                                         infos):\n        # remove the worst\n        if self._best_full():\n            worst_record_path = max(self.best_records,\n                                    key=self.best_records.get)\n            self.best_records.pop(worst_record_path)\n            if (worst_record_path not in self.latest_records):\n                logger.info(\n                    \"remove the worst checkpoint: {}\".format(worst_record_path))\n                self._del_checkpoint(checkpoint_dir, worst_record_path)\n\n        # add the new one\n        self._save_parameters(checkpoint_dir, tag_or_iteration, model,\n                              optimizer, infos)\n        self.best_records[tag_or_iteration] = metric\n\n    def _save_latest_checkpoint_and_update(\n            self, checkpoint_dir, tag_or_iteration, model, optimizer, infos):\n        # remove the old\n        if self._latest_full():\n            to_del_fn = self.latest_records.pop(0)\n            if (to_del_fn not in self.best_records.keys()):\n                logger.info(\n                    \"remove the latest checkpoint: {}\".format(to_del_fn))\n                self._del_checkpoint(checkpoint_dir, to_del_fn)\n        self.latest_records.append(tag_or_iteration)\n\n        self._save_parameters(checkpoint_dir, tag_or_iteration, model,\n                              optimizer, infos)\n\n    def _del_checkpoint(self, checkpoint_dir, tag_or_iteration):\n        checkpoint_path = os.path.join(checkpoint_dir,\n                                       \"{}\".format(tag_or_iteration))\n        for filename in glob.glob(checkpoint_path + \".*\"):\n            os.remove(filename)\n            logger.info(\"delete file: {}\".format(filename))\n\n    def _load_checkpoint_idx(self, checkpoint_record: str) -> int:\n        \"\"\"Get the iteration number corresponding to the latest saved checkpoint.\n        Args:\n            checkpoint_path (str): the saved path of checkpoint.\n        Returns:\n            int: the latest iteration number. -1 for no checkpoint to load.\n        \"\"\"\n        if not os.path.isfile(checkpoint_record):\n            return -1\n\n        # Fetch the latest checkpoint index.\n        with open(checkpoint_record, \"rt\") as handle:\n            latest_checkpoint = handle.readlines()[-1].strip()\n            iteration = int(latest_checkpoint.split(\":\")[-1])\n        return iteration\n\n    def _save_checkpoint_record(self, checkpoint_dir: str, iteration: int):\n        \"\"\"Save the iteration number of the latest model to be checkpoint record.\n        Args:\n            checkpoint_dir (str): the directory where checkpoint is saved.\n            iteration (int): the latest iteration number.\n        Returns:\n            None\n        \"\"\"\n        checkpoint_record_latest = os.path.join(checkpoint_dir,\n                                                \"checkpoint_latest\")\n        checkpoint_record_best = os.path.join(checkpoint_dir, \"checkpoint_best\")\n\n        with open(checkpoint_record_best, \"w\") as handle:\n            for i in self.best_records.keys():\n                handle.write(\"model_checkpoint_path:{}\\n\".format(i))\n        with open(checkpoint_record_latest, \"w\") as handle:\n            for i in self.latest_records:\n                handle.write(\"model_checkpoint_path:{}\\n\".format(i))\n\n    @mp_tools.rank_zero_only\n    def _save_parameters(self,\n                         checkpoint_dir: str,\n                         tag_or_iteration: Union[int, str],\n                         model: paddle.nn.Layer,\n                         optimizer: Optimizer=None,\n                         infos: dict=None):\n        \"\"\"Checkpoint the latest trained model parameters.\n        Args:\n            checkpoint_dir (str): the directory where checkpoint is saved.\n            tag_or_iteration (int or str): the latest iteration(step or epoch) number.\n            model (Layer): model to be checkpointed.\n            optimizer (Optimizer, optional): optimizer to be checkpointed.\n                Defaults to None.\n            infos (dict or None): any info you want to save.\n        Returns:\n            None\n        \"\"\"\n        checkpoint_path = os.path.join(checkpoint_dir,\n                                       \"{}\".format(tag_or_iteration))\n\n        model_dict = model.state_dict()\n        params_path = checkpoint_path + \".pdparams\"\n        paddle.save(model_dict, params_path)\n        logger.info(\"Saved model to {}\".format(params_path))\n\n        if optimizer:\n            opt_dict = optimizer.state_dict()\n            optimizer_path = checkpoint_path + \".pdopt\"\n            paddle.save(opt_dict, optimizer_path)\n            logger.info(\"Saved optimzier state to {}\".format(optimizer_path))\n\n        info_path = re.sub('.pdparams$', '.json', params_path)\n        infos = {} if infos is None else infos\n        with open(info_path, 'w') as fout:\n            data = json.dumps(infos)\n            fout.write(data)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/cli_readers.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport io\nimport logging\nimport sys\n\nimport h5py\nimport kaldiio\nimport soundfile\n\nfrom paddlespeech.s2t.io.reader import SoundHDF5File\n\n\ndef file_reader_helper(\n        rspecifier: str,\n        filetype: str=\"mat\",\n        return_shape: bool=False,\n        segments: str=None, ):\n    \"\"\"Read uttid and array in kaldi style\n\n    This function might be a bit confusing as \"ark\" is used\n    for HDF5 to imitate \"kaldi-rspecifier\".\n\n    Args:\n        rspecifier: Give as \"ark:feats.ark\" or \"scp:feats.scp\"\n        filetype: \"mat\" is kaldi-martix, \"hdf5\": HDF5\n        return_shape: Return the shape of the matrix,\n            instead of the matrix. This can reduce IO cost for HDF5.\n        segments (str): The file format is\n            \"<segment-id> <recording-id> <start-time> <end-time>\\n\"\n            \"e.g. call-861225-A-0050-0065 call-861225-A 5.0 6.5\\n\"\n    Returns:\n        Generator[Tuple[str, np.ndarray], None, None]:\n\n    Examples:\n        Read from kaldi-matrix ark file:\n\n        >>> for u, array in file_reader_helper('ark:feats.ark', 'mat'):\n        ...     array\n\n        Read from HDF5 file:\n\n        >>> for u, array in file_reader_helper('ark:feats.h5', 'hdf5'):\n        ...     array\n\n    \"\"\"\n    if filetype == \"mat\":\n        return KaldiReader(\n            rspecifier, return_shape=return_shape, segments=segments)\n    elif filetype == \"hdf5\":\n        return HDF5Reader(rspecifier, return_shape=return_shape)\n    elif filetype == \"sound.hdf5\":\n        return SoundHDF5Reader(rspecifier, return_shape=return_shape)\n    elif filetype == \"sound\":\n        return SoundReader(rspecifier, return_shape=return_shape)\n    else:\n        raise NotImplementedError(f\"filetype={filetype}\")\n\n\nclass KaldiReader:\n    def __init__(self, rspecifier, return_shape=False, segments=None):\n        self.rspecifier = rspecifier\n        self.return_shape = return_shape\n        self.segments = segments\n\n    def __iter__(self):\n        with kaldiio.ReadHelper(\n                self.rspecifier, segments=self.segments) as reader:\n            for key, array in reader:\n                if self.return_shape:\n                    array = array.shape\n                yield key, array\n\n\nclass HDF5Reader:\n    def __init__(self, rspecifier, return_shape=False):\n        if \":\" not in rspecifier:\n            raise ValueError('Give \"rspecifier\" such as \"ark:some.ark: {}\"'.\n                             format(self.rspecifier))\n        self.rspecifier = rspecifier\n        self.ark_or_scp, self.filepath = self.rspecifier.split(\":\", 1)\n        if self.ark_or_scp not in [\"ark\", \"scp\"]:\n            raise ValueError(f\"Must be scp or ark: {self.ark_or_scp}\")\n\n        self.return_shape = return_shape\n\n    def __iter__(self):\n        if self.ark_or_scp == \"scp\":\n            hdf5_dict = {}\n            with open(self.filepath, \"r\", encoding=\"utf-8\") as f:\n                for line in f:\n                    key, value = line.rstrip().split(None, 1)\n\n                    if \":\" not in value:\n                        raise RuntimeError(\n                            \"scp file for hdf5 should be like: \"\n                            '\"uttid filepath.h5:key\": {}({})'.format(\n                                line, self.filepath))\n                    path, h5_key = value.split(\":\", 1)\n\n                    hdf5_file = hdf5_dict.get(path)\n                    if hdf5_file is None:\n                        try:\n                            hdf5_file = h5py.File(path, \"r\")\n                        except Exception:\n                            logging.error(\"Error when loading {}\".format(path))\n                            raise\n                        hdf5_dict[path] = hdf5_file\n\n                    try:\n                        data = hdf5_file[h5_key]\n                    except Exception:\n                        logging.error(\"Error when loading {} with key={}\".\n                                      format(path, h5_key))\n                        raise\n\n                    if self.return_shape:\n                        yield key, data.shape\n                    else:\n                        yield key, data[()]\n\n            # Closing all files\n            for k in hdf5_dict:\n                try:\n                    hdf5_dict[k].close()\n                except Exception:\n                    pass\n\n        else:\n            if self.filepath == \"-\":\n                # Required h5py>=2.9\n                filepath = io.BytesIO(sys.stdin.buffer.read())\n            else:\n                filepath = self.filepath\n            with h5py.File(filepath, \"r\") as f:\n                for key in f:\n                    if self.return_shape:\n                        yield key, f[key].shape\n                    else:\n                        yield key, f[key][()]\n\n\nclass SoundHDF5Reader:\n    def __init__(self, rspecifier, return_shape=False):\n        if \":\" not in rspecifier:\n            raise ValueError('Give \"rspecifier\" such as \"ark:some.ark: {}\"'.\n                             format(rspecifier))\n        self.ark_or_scp, self.filepath = rspecifier.split(\":\", 1)\n        if self.ark_or_scp not in [\"ark\", \"scp\"]:\n            raise ValueError(f\"Must be scp or ark: {self.ark_or_scp}\")\n        self.return_shape = return_shape\n\n    def __iter__(self):\n        if self.ark_or_scp == \"scp\":\n            hdf5_dict = {}\n            with open(self.filepath, \"r\", encoding=\"utf-8\") as f:\n                for line in f:\n                    key, value = line.rstrip().split(None, 1)\n\n                    if \":\" not in value:\n                        raise RuntimeError(\n                            \"scp file for hdf5 should be like: \"\n                            '\"uttid filepath.h5:key\": {}({})'.format(\n                                line, self.filepath))\n                    path, h5_key = value.split(\":\", 1)\n\n                    hdf5_file = hdf5_dict.get(path)\n                    if hdf5_file is None:\n                        try:\n                            hdf5_file = SoundHDF5File(path, \"r\")\n                        except Exception:\n                            logging.error(\"Error when loading {}\".format(path))\n                            raise\n                        hdf5_dict[path] = hdf5_file\n\n                    try:\n                        data = hdf5_file[h5_key]\n                    except Exception:\n                        logging.error(\"Error when loading {} with key={}\".\n                                      format(path, h5_key))\n                        raise\n\n                    # Change Tuple[ndarray, int] -> Tuple[int, ndarray]\n                    # (soundfile style -> scipy style)\n                    array, rate = data\n                    if self.return_shape:\n                        array = array.shape\n                    yield key, (rate, array)\n\n            # Closing all files\n            for k in hdf5_dict:\n                try:\n                    hdf5_dict[k].close()\n                except Exception:\n                    pass\n\n        else:\n            if self.filepath == \"-\":\n                # Required h5py>=2.9\n                filepath = io.BytesIO(sys.stdin.buffer.read())\n            else:\n                filepath = self.filepath\n            for key, (a, r) in SoundHDF5File(filepath, \"r\").items():\n                if self.return_shape:\n                    a = a.shape\n                yield key, (r, a)\n\n\nclass SoundReader:\n    def __init__(self, rspecifier, return_shape=False):\n        if \":\" not in rspecifier:\n            raise ValueError('Give \"rspecifier\" such as \"scp:some.scp: {}\"'.\n                             format(rspecifier))\n        self.ark_or_scp, self.filepath = rspecifier.split(\":\", 1)\n        if self.ark_or_scp != \"scp\":\n            raise ValueError('Only supporting \"scp\" for sound file: {}'.format(\n                self.ark_or_scp))\n        self.return_shape = return_shape\n\n    def __iter__(self):\n        with open(self.filepath, \"r\", encoding=\"utf-8\") as f:\n            for line in f:\n                key, sound_file_path = line.rstrip().split(None, 1)\n                # Assume PCM16\n                array, rate = soundfile.read(sound_file_path, dtype=\"int16\")\n                # Change Tuple[ndarray, int] -> Tuple[int, ndarray]\n                # (soundfile style -> scipy style)\n                if self.return_shape:\n                    array = array.shape\n                yield key, (rate, array)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/cli_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport sys\nfrom collections.abc import Sequence\n\nimport numpy\n\nfrom paddlespeech.utils.argparse import strtobool as dist_strtobool\n\n\ndef strtobool(x):\n    # paddlespeech.utils.argparse.strtobool returns integer, but it's confusing,\n    return bool(dist_strtobool(x))\n\n\ndef get_commandline_args():\n    extra_chars = [\n        \" \",\n        \";\",\n        \"&\",\n        \"(\",\n        \")\",\n        \"|\",\n        \"^\",\n        \"<\",\n        \">\",\n        \"?\",\n        \"*\",\n        \"[\",\n        \"]\",\n        \"$\",\n        \"`\",\n        '\"',\n        \"\\\\\",\n        \"!\",\n        \"{\",\n        \"}\",\n    ]\n\n    # Escape the extra characters for shell\n    argv = [\n        arg.replace(\"'\", \"'\\\\''\") if all(char not in arg\n                                         for char in extra_chars) else\n        \"'\" + arg.replace(\"'\", \"'\\\\''\") + \"'\" for arg in sys.argv\n    ]\n\n    return sys.executable + \" \" + \" \".join(argv)\n\n\ndef is_scipy_wav_style(value):\n    # If Tuple[int, numpy.ndarray] or not\n    return (isinstance(value, Sequence) and len(value) == 2 and\n            isinstance(value[0], int) and isinstance(value[1], numpy.ndarray))\n\n\ndef assert_scipy_wav_style(value):\n    assert is_scipy_wav_style(\n        value), \"Must be Tuple[int, numpy.ndarray], but got {}\".format(\n            type(value) if not isinstance(value, Sequence) else \"{}[{}]\".format(\n                type(value), \", \".join(str(type(v)) for v in value)))\n"
  },
  {
    "path": "paddlespeech/s2t/utils/cli_writers.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom pathlib import Path\nfrom typing import Dict\n\nimport h5py\nimport kaldiio\nimport numpy\nimport soundfile\n\nfrom paddlespeech.s2t.io.reader import SoundHDF5File\nfrom paddlespeech.s2t.utils.cli_utils import assert_scipy_wav_style\n\n\ndef file_writer_helper(\n        wspecifier: str,\n        filetype: str=\"mat\",\n        write_num_frames: str=None,\n        compress: bool=False,\n        compression_method: int=2,\n        pcm_format: str=\"wav\", ):\n    \"\"\"Write matrices in kaldi style\n\n    Args:\n        wspecifier: e.g. ark,scp:out.ark,out.scp\n        filetype: \"mat\" is kaldi-martix, \"hdf5\": HDF5\n        write_num_frames: e.g. 'ark,t:num_frames.txt'\n        compress: Compress or not\n        compression_method: Specify compression level\n\n    Write in kaldi-matrix-ark with \"kaldi-scp\" file:\n\n    >>> with file_writer_helper('ark,scp:out.ark,out.scp') as f:\n    >>>     f['uttid'] = array\n\n    This \"scp\" has the following format:\n\n        uttidA out.ark:1234\n        uttidB out.ark:2222\n\n    where, 1234 and 2222 points the strating byte address of the matrix.\n    (For detail, see official documentation of Kaldi)\n\n    Write in HDF5 with \"scp\" file:\n\n    >>> with file_writer_helper('ark,scp:out.h5,out.scp', 'hdf5') as f:\n    >>>     f['uttid'] = array\n\n    This \"scp\" file is created as:\n\n        uttidA out.h5:uttidA\n        uttidB out.h5:uttidB\n\n    HDF5 can be, unlike \"kaldi-ark\", accessed to any keys,\n    so originally \"scp\" is not required for random-reading.\n    Nevertheless we create \"scp\" for HDF5 because it is useful\n    for some use-case. e.g. Concatenation, Splitting.\n\n    \"\"\"\n    if filetype == \"mat\":\n        return KaldiWriter(\n            wspecifier,\n            write_num_frames=write_num_frames,\n            compress=compress,\n            compression_method=compression_method, )\n    elif filetype == \"hdf5\":\n        return HDF5Writer(\n            wspecifier, write_num_frames=write_num_frames, compress=compress)\n    elif filetype == \"sound.hdf5\":\n        return SoundHDF5Writer(\n            wspecifier,\n            write_num_frames=write_num_frames,\n            pcm_format=pcm_format)\n    elif filetype == \"sound\":\n        return SoundWriter(\n            wspecifier,\n            write_num_frames=write_num_frames,\n            pcm_format=pcm_format)\n    else:\n        raise NotImplementedError(f\"filetype={filetype}\")\n\n\nclass BaseWriter:\n    def __setitem__(self, key, value):\n        raise NotImplementedError\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n\n    def close(self):\n        try:\n            self.writer.close()\n        except Exception:\n            pass\n\n        if self.writer_scp is not None:\n            try:\n                self.writer_scp.close()\n            except Exception:\n                pass\n\n        if self.writer_nframe is not None:\n            try:\n                self.writer_nframe.close()\n            except Exception:\n                pass\n\n\ndef get_num_frames_writer(write_num_frames: str):\n    \"\"\"get_num_frames_writer\n\n    Examples:\n        >>> get_num_frames_writer('ark,t:num_frames.txt')\n    \"\"\"\n    if write_num_frames is not None:\n        if \":\" not in write_num_frames:\n            raise ValueError('Must include \":\", write_num_frames={}'.format(\n                write_num_frames))\n\n        nframes_type, nframes_file = write_num_frames.split(\":\", 1)\n        if nframes_type != \"ark,t\":\n            raise ValueError(\"Only supporting text mode. \"\n                             \"e.g. --write-num-frames=ark,t:foo.txt :\"\n                             \"{}\".format(nframes_type))\n\n    return open(nframes_file, \"w\", encoding=\"utf-8\")\n\n\nclass KaldiWriter(BaseWriter):\n    def __init__(self,\n                 wspecifier,\n                 write_num_frames=None,\n                 compress=False,\n                 compression_method=2):\n        if compress:\n            self.writer = kaldiio.WriteHelper(\n                wspecifier, compression_method=compression_method)\n        else:\n            self.writer = kaldiio.WriteHelper(wspecifier)\n        self.writer_scp = None\n        if write_num_frames is not None:\n            self.writer_nframe = get_num_frames_writer(write_num_frames)\n        else:\n            self.writer_nframe = None\n\n    def __setitem__(self, key, value):\n        self.writer[key] = value\n        if self.writer_nframe is not None:\n            self.writer_nframe.write(f\"{key} {len(value)}\\n\")\n\n\ndef parse_wspecifier(wspecifier: str) -> Dict[str, str]:\n    \"\"\"Parse wspecifier to dict\n\n    Examples:\n        >>> parse_wspecifier('ark,scp:out.ark,out.scp')\n        {'ark': 'out.ark', 'scp': 'out.scp'}\n\n    \"\"\"\n    ark_scp, filepath = wspecifier.split(\":\", 1)\n    if ark_scp not in [\"ark\", \"scp,ark\", \"ark,scp\"]:\n        raise ValueError(\"{} is not allowed: {}\".format(ark_scp, wspecifier))\n    ark_scps = ark_scp.split(\",\")\n    filepaths = filepath.split(\",\")\n    if len(ark_scps) != len(filepaths):\n        raise ValueError(\"Mismatch: {} and {}\".format(ark_scp, filepath))\n    spec_dict = dict(zip(ark_scps, filepaths))\n    return spec_dict\n\n\nclass HDF5Writer(BaseWriter):\n    \"\"\"HDF5Writer\n\n    Examples:\n        >>> with HDF5Writer('ark:out.h5', compress=True) as f:\n        ...     f['key'] = array\n    \"\"\"\n\n    def __init__(self, wspecifier, write_num_frames=None, compress=False):\n        spec_dict = parse_wspecifier(wspecifier)\n        self.filename = spec_dict[\"ark\"]\n\n        if compress:\n            self.kwargs = {\"compression\": \"gzip\"}\n        else:\n            self.kwargs = {}\n        self.writer = h5py.File(spec_dict[\"ark\"], \"w\")\n        if \"scp\" in spec_dict:\n            self.writer_scp = open(spec_dict[\"scp\"], \"w\", encoding=\"utf-8\")\n        else:\n            self.writer_scp = None\n        if write_num_frames is not None:\n            self.writer_nframe = get_num_frames_writer(write_num_frames)\n        else:\n            self.writer_nframe = None\n\n    def __setitem__(self, key, value):\n        self.writer.create_dataset(key, data=value, **self.kwargs)\n\n        if self.writer_scp is not None:\n            self.writer_scp.write(f\"{key} {self.filename}:{key}\\n\")\n        if self.writer_nframe is not None:\n            self.writer_nframe.write(f\"{key} {len(value)}\\n\")\n\n\nclass SoundHDF5Writer(BaseWriter):\n    \"\"\"SoundHDF5Writer\n\n    Examples:\n        >>> fs = 16000\n        >>> with SoundHDF5Writer('ark:out.h5') as f:\n        ...     f['key'] = fs, array\n    \"\"\"\n\n    def __init__(self, wspecifier, write_num_frames=None, pcm_format=\"wav\"):\n        self.pcm_format = pcm_format\n        spec_dict = parse_wspecifier(wspecifier)\n        self.filename = spec_dict[\"ark\"]\n        self.writer = SoundHDF5File(\n            spec_dict[\"ark\"], \"w\", format=self.pcm_format)\n        if \"scp\" in spec_dict:\n            self.writer_scp = open(spec_dict[\"scp\"], \"w\", encoding=\"utf-8\")\n        else:\n            self.writer_scp = None\n        if write_num_frames is not None:\n            self.writer_nframe = get_num_frames_writer(write_num_frames)\n        else:\n            self.writer_nframe = None\n\n    def __setitem__(self, key, value):\n        assert_scipy_wav_style(value)\n        # Change Tuple[int, ndarray] -> Tuple[ndarray, int]\n        # (scipy style -> soundfile style)\n        value = (value[1], value[0])\n        self.writer.create_dataset(key, data=value)\n\n        if self.writer_scp is not None:\n            self.writer_scp.write(f\"{key} {self.filename}:{key}\\n\")\n        if self.writer_nframe is not None:\n            self.writer_nframe.write(f\"{key} {len(value[0])}\\n\")\n\n\nclass SoundWriter(BaseWriter):\n    \"\"\"SoundWriter\n\n    Examples:\n        >>> fs = 16000\n        >>> with SoundWriter('ark,scp:outdir,out.scp') as f:\n        ...     f['key'] = fs, array\n    \"\"\"\n\n    def __init__(self, wspecifier, write_num_frames=None, pcm_format=\"wav\"):\n        self.pcm_format = pcm_format\n        spec_dict = parse_wspecifier(wspecifier)\n        # e.g. ark,scp:dirname,wav.scp\n        # -> The wave files are found in dirname/*.wav\n        self.dirname = spec_dict[\"ark\"]\n        Path(self.dirname).mkdir(parents=True, exist_ok=True)\n        self.writer = None\n\n        if \"scp\" in spec_dict:\n            self.writer_scp = open(spec_dict[\"scp\"], \"w\", encoding=\"utf-8\")\n        else:\n            self.writer_scp = None\n        if write_num_frames is not None:\n            self.writer_nframe = get_num_frames_writer(write_num_frames)\n        else:\n            self.writer_nframe = None\n\n    def __setitem__(self, key, value):\n        assert_scipy_wav_style(value)\n        rate, signal = value\n        wavfile = Path(self.dirname) / (key + \".\" + self.pcm_format)\n        soundfile.write(wavfile, signal.astype(numpy.int16), rate)\n\n        if self.writer_scp is not None:\n            self.writer_scp.write(f\"{key} {wavfile}\\n\")\n        if self.writer_nframe is not None:\n            self.writer_nframe.write(f\"{key} {len(signal)}\\n\")\n"
  },
  {
    "path": "paddlespeech/s2t/utils/ctc_utils.py",
    "content": "# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nfrom pathlib import Path\nfrom typing import List\n\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.s2t.utils import text_grid\nfrom paddlespeech.s2t.utils import utility\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"forced_align\", \"remove_duplicates_and_blank\", \"insert_blank\"]\n\n\ndef remove_duplicates_and_blank(hyp: List[int], blank_id=0) -> List[int]:\n    \"\"\"ctc alignment to ctc label ids.\n\n    \"abaa-acee-\" -> \"abaace\"\n\n    Args:\n        hyp (List[int]): hypotheses ids, (L)\n        blank_id (int, optional): blank id. Defaults to 0.\n\n    Returns:\n        List[int]: remove dupicate ids, then remove blank id.\n    \"\"\"\n    new_hyp: List[int] = []\n    cur = 0\n    while cur < len(hyp):\n        # add non-blank into new_hyp\n        if hyp[cur] != blank_id:\n            new_hyp.append(hyp[cur])\n        # skip repeat label\n        prev = cur\n        while cur < len(hyp) and hyp[cur] == hyp[prev]:\n            cur += 1\n    return new_hyp\n\n\ndef insert_blank(label: np.ndarray, blank_id: int=0) -> np.ndarray:\n    \"\"\"Insert blank token between every two label token.\n\n    \"abcdefg\" -> \"-a-b-c-d-e-f-g-\"\n\n    Args:\n        label ([np.ndarray]): label ids, List[int], (L).\n        blank_id (int, optional): blank id. Defaults to 0.\n\n    Returns:\n        [np.ndarray]: (2L+1).\n    \"\"\"\n    label = np.expand_dims(label, 1)  #[L, 1]\n    blanks = np.zeros((label.shape[0], 1), dtype=np.int64) + blank_id\n    label = np.concatenate([blanks, label], axis=1)  #[L, 2]\n    label = label.reshape(-1)  #[2L], -l-l-l\n    label = np.append(label, label[0])  #[2L + 1], -l-l-l-\n    return label\n\n\ndef forced_align(ctc_probs: paddle.Tensor, y: paddle.Tensor,\n                 blank_id=0) -> List[int]:\n    \"\"\"ctc forced alignment.\n\n    https://distill.pub/2017/ctc/\n\n    Args:\n        ctc_probs (paddle.Tensor): hidden state sequence, 2d tensor (T, D)\n        y (paddle.Tensor): label id sequence tensor, 1d tensor (L)\n        blank_id (int): blank symbol index\n    Returns:\n        List[int]: best alignment result, (T).\n    \"\"\"\n    y_insert_blank = insert_blank(y, blank_id)  #(2L+1)\n\n    log_alpha = paddle.zeros(\n        (ctc_probs.shape[0], len(y_insert_blank)))  #(T, 2L+1)\n    log_alpha = log_alpha - float('inf')  # log of zero\n\n    # TODO(Hui Zhang): zeros not support paddle.int16\n    # self.__setitem_varbase__(item, value) When assign a value to a paddle.Tensor, the data type of the paddle.Tensor not support int16\n    state_path = (paddle.zeros(\n        (ctc_probs.shape[0], len(y_insert_blank)), dtype=paddle.int32) - 1\n                  )  # state path, Tuple((T, 2L+1))\n\n    # init start state\n    # TODO(Hui Zhang): VarBase.__getitem__() not support np.int64\n    log_alpha[0, 0] = ctc_probs[0][int(y_insert_blank[0])]  # State-b, Sb\n    log_alpha[0, 1] = ctc_probs[0][int(y_insert_blank[1])]  # State-nb, Snb\n\n    for t in range(1, ctc_probs.shape[0]):  # T\n        for s in range(len(y_insert_blank)):  # 2L+1\n            if y_insert_blank[s] == blank_id or s < 2 or y_insert_blank[\n                    s] == y_insert_blank[s - 2]:\n                candidates = paddle.to_tensor(\n                    [log_alpha[t - 1, s], log_alpha[t - 1, s - 1]])\n                prev_state = [s, s - 1]\n            else:\n                candidates = paddle.to_tensor([\n                    log_alpha[t - 1, s],\n                    log_alpha[t - 1, s - 1],\n                    log_alpha[t - 1, s - 2],\n                ])\n                prev_state = [s, s - 1, s - 2]\n            # TODO(Hui Zhang): VarBase.__getitem__() not support np.int64\n            log_alpha[t, s] = paddle.max(candidates) + ctc_probs[t][int(\n                y_insert_blank[s])]\n            state_path[t, s] = prev_state[paddle.argmax(candidates)]\n    # TODO(Hui Zhang): zeros not support paddle.int16\n    # self.__setitem_varbase__(item, value) When assign a value to a paddle.Tensor, the data type of the paddle.Tensor not support int16\n    state_seq = -1 * paddle.ones((ctc_probs.shape[0], 1), dtype=paddle.int32)\n\n    candidates = paddle.to_tensor([\n        log_alpha[-1, len(y_insert_blank) - 1],  # Sb\n        log_alpha[-1, len(y_insert_blank) - 2]  # Snb\n    ])\n    prev_state = [len(y_insert_blank) - 1, len(y_insert_blank) - 2]\n    state_seq[-1] = prev_state[paddle.argmax(candidates)]\n    for t in range(ctc_probs.shape[0] - 2, -1, -1):\n        state_seq[t] = state_path[t + 1, state_seq[t + 1, 0]]\n\n    output_alignment = []\n    for t in range(0, ctc_probs.shape[0]):\n        output_alignment.append(y_insert_blank[state_seq[t, 0]])\n\n    return output_alignment\n\n\ndef ctc_align(config, model, dataloader, batch_size, stride_ms, token_dict,\n              result_file):\n    \"\"\"ctc alignment.\n\n    Args:\n        config (cfgNode): config \n        model (nn.Layer): U2 Model.\n        dataloader (io.DataLoader): dataloader.\n        batch_size (int): decoding batchsize.\n        stride_ms (int): audio feature stride in ms unit.\n        token_dict (List[str]): vocab list, e.g. ['blank', 'unk', 'a', 'b', '<eos>'].\n        result_file (str): alignment output file, e.g. /path/to/xxx.align.\n    \"\"\"\n    if batch_size > 1:\n        logger.fatal('alignment mode must be running with batch_size == 1')\n        sys.exit(1)\n    assert result_file and result_file.endswith('.align')\n\n    model.eval()\n    # conv subsampling rate\n    subsample = utility.get_subsample(config)\n    logger.info(f\"Align Total Examples: {len(dataloader.dataset)}\")\n\n    with open(result_file, 'w') as fout:\n        # one example in batch\n        for i, batch in enumerate(dataloader):\n            key, feat, feats_length, target, target_length = batch\n\n            # 1. Encoder\n            encoder_out, encoder_mask = model._forward_encoder(\n                feat, feats_length)  # (B, maxlen, encoder_dim)\n            maxlen = encoder_out.shape[1]\n            ctc_probs = model.ctc.log_softmax(\n                encoder_out)  # (1, maxlen, vocab_size)\n\n            # 2. alignment\n            ctc_probs = ctc_probs.squeeze(0)\n            target = target.squeeze(0)\n            alignment = forced_align(ctc_probs, target)\n\n            logger.info(f\"align ids: {key[0]} {alignment}\")\n            fout.write('{} {}\\n'.format(key[0], alignment))\n\n            # 3. gen praat\n            # segment alignment\n            align_segs = text_grid.segment_alignment(alignment)\n            logger.info(f\"align tokens: {key[0]}, {align_segs}\")\n\n            # IntervalTier, List[\"start end token\\n\"]\n            tierformat = text_grid.align_to_tierformat(align_segs, subsample,\n                                                       token_dict)\n\n            # write tier\n            align_output_path = Path(result_file).parent / \"align\"\n            align_output_path.mkdir(parents=True, exist_ok=True)\n            tier_path = align_output_path / (key[0] + \".tier\")\n            with tier_path.open('w') as f:\n                f.writelines(tierformat)\n\n            # write textgrid\n            textgrid_path = align_output_path / (key[0] + \".TextGrid\")\n            second_per_frame = 1. / (1000. /\n                                     stride_ms)  # 25ms window, 10ms stride\n            second_per_example = (\n                len(alignment) + 1) * subsample * second_per_frame\n            text_grid.generate_textgrid(\n                maxtime=second_per_example,\n                intervals=tierformat,\n                output=str(textgrid_path))\n"
  },
  {
    "path": "paddlespeech/s2t/utils/dynamic_import.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport importlib\nimport inspect\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Text\n\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.s2t.utils.tensor_utils import has_tensor\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"dynamic_import\", \"instance_class\"]\n\n\ndef dynamic_import(import_path, alias=dict()):\n    \"\"\"dynamic import module and class\n\n    :param str import_path: syntax 'module_name:class_name'\n        e.g., 'paddlespeech.s2t.models.u2:U2Model'\n    :param dict alias: shortcut for registered class\n    :return: imported class\n    \"\"\"\n    if import_path not in alias and \":\" not in import_path:\n        raise ValueError(\n            \"import_path should be one of {} or \"\n            'include \":\", e.g. \"paddlespeech.s2t.models.u2:U2Model\" : '\n            \"{}\".format(set(alias), import_path))\n    if \":\" not in import_path:\n        import_path = alias[import_path]\n\n    module_name, objname = import_path.split(\":\")\n    m = importlib.import_module(module_name)\n    return getattr(m, objname)\n\n\ndef filter_valid_args(args: Dict[Text, Any], valid_keys: List[Text]):\n    # filter by `valid_keys` and filter `val` is not None\n    new_args = {\n        key: val\n        for key, val in args.items() if (key in valid_keys and val is not None)\n    }\n    return new_args\n\n\ndef filter_out_tensor(args: Dict[Text, Any]):\n    return {key: val for key, val in args.items() if not has_tensor(val)}\n\n\ndef instance_class(module_class, args: Dict[Text, Any]):\n    valid_keys = inspect.signature(module_class).parameters.keys()\n    new_args = filter_valid_args(args, valid_keys)\n    logger.info(\n        f\"Instance: {module_class.__name__} {filter_out_tensor(new_args)}.\")\n    return module_class(**new_args)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/dynamic_pip_install.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport pip\n\n\ndef install(package_name):\n    if int(pip.__version__.split('.')[0]) > 9:\n        from pip._internal import main\n    else:\n        from pip import main\n    main(['install', package_name])\n"
  },
  {
    "path": "paddlespeech/s2t/utils/error_rate.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"This module provides functions to calculate error rate in different level.\ne.g. wer for word-level, cer for char-level.\n\"\"\"\nfrom itertools import groupby\n\nimport editdistance\nimport numpy as np\n\n__all__ = ['word_errors', 'char_errors', 'wer', 'cer', \"ErrorCalculator\"]\n\n\ndef _levenshtein_distance(ref, hyp):\n    \"\"\"Levenshtein distance is a string metric for measuring the difference\n    between two sequences. Informally, the levenshtein disctance is defined as\n    the minimum number of single-character edits (substitutions, insertions or\n    deletions) required to change one word into the other. We can naturally\n    extend the edits to word level when calculate levenshtein disctance for\n    two sentences.\n    \"\"\"\n    m = len(ref)\n    n = len(hyp)\n\n    # special case\n    if ref == hyp:\n        return 0\n    if m == 0:\n        return n\n    if n == 0:\n        return m\n\n    if m < n:\n        ref, hyp = hyp, ref\n        m, n = n, m\n\n    # use O(min(m, n)) space\n    distance = np.zeros((2, n + 1), dtype=np.int32)\n\n    # initialize distance matrix\n    for j in range(n + 1):\n        distance[0][j] = j\n\n    # calculate levenshtein distance\n    for i in range(1, m + 1):\n        prev_row_idx = (i - 1) % 2\n        cur_row_idx = i % 2\n        distance[cur_row_idx][0] = i\n        for j in range(1, n + 1):\n            if ref[i - 1] == hyp[j - 1]:\n                distance[cur_row_idx][j] = distance[prev_row_idx][j - 1]\n            else:\n                s_num = distance[prev_row_idx][j - 1] + 1\n                i_num = distance[cur_row_idx][j - 1] + 1\n                d_num = distance[prev_row_idx][j] + 1\n                distance[cur_row_idx][j] = min(s_num, i_num, d_num)\n\n    return distance[m % 2][n]\n\n\ndef word_errors(reference, hypothesis, ignore_case=False, delimiter=' '):\n    \"\"\"Compute the levenshtein distance between reference sequence and\n    hypothesis sequence in word-level.\n\n    :param reference: The reference sentence.\n    :type reference: str\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: str\n    :param ignore_case: Whether case-sensitive or not.\n    :type ignore_case: bool\n    :param delimiter: Delimiter of input sentences.\n    :type delimiter: char\n    :return: Levenshtein distance and word number of reference sentence.\n    :rtype: list\n    \"\"\"\n    if ignore_case:\n        reference = reference.lower()\n        hypothesis = hypothesis.lower()\n\n    ref_words = list(filter(None, reference.split(delimiter)))\n    hyp_words = list(filter(None, hypothesis.split(delimiter)))\n\n    edit_distance = _levenshtein_distance(ref_words, hyp_words)\n    # `editdistance.eavl precision` less than `_levenshtein_distance`\n    # edit_distance = editdistance.eval(ref_words, hyp_words)\n    return float(edit_distance), len(ref_words)\n\n\ndef char_errors(reference, hypothesis, ignore_case=False, remove_space=False):\n    \"\"\"Compute the levenshtein distance between reference sequence and\n    hypothesis sequence in char-level.\n\n    :param reference: The reference sentence.\n    :type reference: str\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: str\n    :param ignore_case: Whether case-sensitive or not.\n    :type ignore_case: bool\n    :param remove_space: Whether remove internal space characters\n    :type remove_space: bool\n    :return: Levenshtein distance and length of reference sentence.\n    :rtype: list\n    \"\"\"\n    if ignore_case:\n        reference = reference.lower()\n        hypothesis = hypothesis.lower()\n\n    join_char = ' '\n    if remove_space:\n        join_char = ''\n\n    reference = join_char.join(list(filter(None, reference.split(' '))))\n    hypothesis = join_char.join(list(filter(None, hypothesis.split(' '))))\n\n    edit_distance = _levenshtein_distance(reference, hypothesis)\n    # `editdistance.eavl precision` less than `_levenshtein_distance`\n    # edit_distance = editdistance.eval(reference, hypothesis)\n    return float(edit_distance), len(reference)\n\n\ndef wer(reference, hypothesis, ignore_case=False, delimiter=' '):\n    \"\"\"Calculate word error rate (WER). WER compares reference text and\n    hypothesis text in word-level. WER is defined as:\n\n    .. math::\n        WER = (Sw + Dw + Iw) / Nw\n\n    where\n\n    .. code-block:: text\n\n        Sw is the number of words subsituted,\n        Dw is the number of words deleted,\n        Iw is the number of words inserted,\n        Nw is the number of words in the reference\n\n    We can use levenshtein distance to calculate WER. Please draw an attention\n    that empty items will be removed when splitting sentences by delimiter.\n\n    :param reference: The reference sentence.\n    :type reference: str\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: str\n    :param ignore_case: Whether case-sensitive or not.\n    :type ignore_case: bool\n    :param delimiter: Delimiter of input sentences.\n    :type delimiter: char\n    :return: Word error rate.\n    :rtype: float\n    :raises ValueError: If word number of reference is zero.\n    \"\"\"\n    edit_distance, ref_len = word_errors(reference, hypothesis, ignore_case,\n                                         delimiter)\n\n    if ref_len == 0:\n        raise ValueError(\"Reference's word number should be greater than 0.\")\n\n    wer = float(edit_distance) / ref_len\n    return wer\n\n\ndef cer(reference, hypothesis, ignore_case=False, remove_space=False):\n    \"\"\"Calculate character error rate (CER). CER compares reference text and\n    hypothesis text in char-level. CER is defined as:\n\n    .. math::\n        CER = (Sc + Dc + Ic) / Nc\n\n    where\n\n    .. code-block:: text\n\n        Sc is the number of characters substituted,\n        Dc is the number of characters deleted,\n        Ic is the number of characters inserted\n        Nc is the number of characters in the reference\n\n    We can use levenshtein distance to calculate CER. Chinese input should be\n    encoded to unicode. Please draw an attention that the leading and tailing\n    space characters will be truncated and multiple consecutive space\n    characters in a sentence will be replaced by one space character.\n\n    :param reference: The reference sentence.\n    :type reference: str\n    :param hypothesis: The hypothesis sentence.\n    :type hypothesis: str\n    :param ignore_case: Whether case-sensitive or not.\n    :type ignore_case: bool\n    :param remove_space: Whether remove internal space characters\n    :type remove_space: bool\n    :return: Character error rate.\n    :rtype: float\n    :raises ValueError: If the reference length is zero.\n    \"\"\"\n    edit_distance, ref_len = char_errors(reference, hypothesis, ignore_case,\n                                         remove_space)\n\n    if ref_len == 0:\n        raise ValueError(\"Length of reference should be greater than 0.\")\n\n    cer = float(edit_distance) / ref_len\n    return cer\n\n\nclass ErrorCalculator():\n    \"\"\"Calculate CER and WER for E2E_ASR and CTC models during training.\n\n    :param y_hats: numpy array with predicted text\n    :param y_pads: numpy array with true (target) text\n    :param char_list: List[str]\n    :param sym_space: <space>\n    :param sym_blank: <blank>\n    :return:\n    \"\"\"\n\n    def __init__(self,\n                 char_list,\n                 sym_space,\n                 sym_blank,\n                 report_cer=False,\n                 report_wer=False):\n        \"\"\"Construct an ErrorCalculator object.\"\"\"\n        super().__init__()\n\n        self.report_cer = report_cer\n        self.report_wer = report_wer\n\n        self.char_list = char_list\n        self.space = sym_space\n        self.blank = sym_blank\n        self.idx_blank = self.char_list.index(self.blank)\n        if self.space in self.char_list:\n            self.idx_space = self.char_list.index(self.space)\n        else:\n            self.idx_space = None\n\n    def __call__(self, ys_hat, ys_pad, is_ctc=False):\n        \"\"\"Calculate sentence-level WER/CER score.\n\n        :param paddle.Tensor ys_hat: prediction (batch, seqlen)\n        :param paddle.Tensor ys_pad: reference (batch, seqlen)\n        :param bool is_ctc: calculate CER score for CTC\n        :return: sentence-level WER score\n        :rtype float\n        :return: sentence-level CER score\n        :rtype float\n        \"\"\"\n        cer, wer = None, None\n        if is_ctc:\n            return self.calculate_cer_ctc(ys_hat, ys_pad)\n        elif not self.report_cer and not self.report_wer:\n            return cer, wer\n\n        seqs_hat, seqs_true = self.convert_to_char(ys_hat, ys_pad)\n        if self.report_cer:\n            cer = self.calculate_cer(seqs_hat, seqs_true)\n\n        if self.report_wer:\n            wer = self.calculate_wer(seqs_hat, seqs_true)\n        return cer, wer\n\n    def calculate_cer_ctc(self, ys_hat, ys_pad):\n        \"\"\"Calculate sentence-level CER score for CTC.\n\n        :param paddle.Tensor ys_hat: prediction (batch, seqlen)\n        :param paddle.Tensor ys_pad: reference (batch, seqlen)\n        :return: average sentence-level CER score\n        :rtype float\n        \"\"\"\n        cers, char_ref_lens = [], []\n        for i, y in enumerate(ys_hat):\n            y_hat = [x[0] for x in groupby(y)]\n            y_true = ys_pad[i]\n            seq_hat, seq_true = [], []\n            for idx in y_hat:\n                idx = int(idx)\n                if idx != -1 and idx != self.idx_blank and idx != self.idx_space:\n                    seq_hat.append(self.char_list[int(idx)])\n\n            for idx in y_true:\n                idx = int(idx)\n                if idx != -1 and idx != self.idx_blank and idx != self.idx_space:\n                    seq_true.append(self.char_list[int(idx)])\n\n            hyp_chars = \"\".join(seq_hat)\n            ref_chars = \"\".join(seq_true)\n            if len(ref_chars) > 0:\n                cers.append(editdistance.eval(hyp_chars, ref_chars))\n                char_ref_lens.append(len(ref_chars))\n\n        cer_ctc = float(sum(cers)) / sum(char_ref_lens) if cers else None\n        return cer_ctc\n\n    def convert_to_char(self, ys_hat, ys_pad):\n        \"\"\"Convert index to character.\n\n        :param paddle.Tensor seqs_hat: prediction (batch, seqlen)\n        :param paddle.Tensor seqs_true: reference (batch, seqlen)\n        :return: token list of prediction\n        :rtype list\n        :return: token list of reference\n        :rtype list\n        \"\"\"\n        seqs_hat, seqs_true = [], []\n        for i, y_hat in enumerate(ys_hat):\n            y_true = ys_pad[i]\n            eos_true = np.where(y_true == -1)[0]\n            ymax = eos_true[0] if len(eos_true) > 0 else len(y_true)\n            # NOTE: padding index (-1) in y_true is used to pad y_hat\n            seq_hat = [self.char_list[int(idx)] for idx in y_hat[:ymax]]\n            seq_true = [\n                self.char_list[int(idx)] for idx in y_true if int(idx) != -1\n            ]\n            seq_hat_text = \"\".join(seq_hat).replace(self.space, \" \")\n            seq_hat_text = seq_hat_text.replace(self.blank, \"\")\n            seq_true_text = \"\".join(seq_true).replace(self.space, \" \")\n            seqs_hat.append(seq_hat_text)\n            seqs_true.append(seq_true_text)\n        return seqs_hat, seqs_true\n\n    def calculate_cer(self, seqs_hat, seqs_true):\n        \"\"\"Calculate sentence-level CER score.\n\n        :param list seqs_hat: prediction\n        :param list seqs_true: reference\n        :return: average sentence-level CER score\n        :rtype float\n        \"\"\"\n        char_eds, char_ref_lens = [], []\n        for i, seq_hat_text in enumerate(seqs_hat):\n            seq_true_text = seqs_true[i]\n            hyp_chars = seq_hat_text.replace(\" \", \"\")\n            ref_chars = seq_true_text.replace(\" \", \"\")\n            char_eds.append(editdistance.eval(hyp_chars, ref_chars))\n            char_ref_lens.append(len(ref_chars))\n        return float(sum(char_eds)) / sum(char_ref_lens)\n\n    def calculate_wer(self, seqs_hat, seqs_true):\n        \"\"\"Calculate sentence-level WER score.\n\n        :param list seqs_hat: prediction\n        :param list seqs_true: reference\n        :return: average sentence-level WER score\n        :rtype float\n        \"\"\"\n        word_eds, word_ref_lens = [], []\n        for i, seq_hat_text in enumerate(seqs_hat):\n            seq_true_text = seqs_true[i]\n            hyp_words = seq_hat_text.split()\n            ref_words = seq_true_text.split()\n            word_eds.append(editdistance.eval(hyp_words, ref_words))\n            word_ref_lens.append(len(ref_words))\n        return float(sum(word_eds)) / sum(word_ref_lens)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/layer_tools.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom paddle import nn\n\n__all__ = [\n    \"summary\", \"gradient_norm\", \"freeze\", \"unfreeze\", \"print_grads\",\n    \"print_params\"\n]\n\n\ndef summary(layer: nn.Layer, print_func=print):\n    if print_func is None:\n        return\n    num_params = num_elements = 0\n    for name, param in layer.state_dict().items():\n        if print_func:\n            print_func(\n                \"{} | {} | {}\".format(name, param.shape, np.prod(param.shape)))\n        num_elements += np.prod(param.shape)\n        num_params += 1\n    if print_func:\n        num_elements = num_elements / 1024**2\n        print_func(\n            f\"Total parameters: {num_params}, {num_elements:.2f}M elements.\")\n\n\ndef print_grads(model, print_func=print):\n    if print_func is None:\n        return\n    for n, p in model.named_parameters():\n        msg = f\"param grad: {n}: shape: {p.shape} grad: {p.grad}\"\n        print_func(msg)\n\n\ndef print_params(model, print_func=print):\n    if print_func is None:\n        return\n    total = 0.0\n    num_params = 0.0\n    for n, p in model.named_parameters():\n        msg = f\"{n} | {p.shape} | {np.prod(p.shape)} | {not p.stop_gradient}\"\n        total += np.prod(p.shape)\n        num_params += 1\n        if print_func:\n            print_func(msg)\n    if print_func:\n        total = total / 1024**2\n        print_func(f\"Total parameters: {num_params}, {total:.2f}M elements.\")\n\n\ndef gradient_norm(layer: nn.Layer):\n    grad_norm_dict = {}\n    for name, param in layer.state_dict().items():\n        if param.trainable:\n            grad = param.gradient()  # return numpy.ndarray\n            grad_norm_dict[name] = np.linalg.norm(grad) / grad.size\n    return grad_norm_dict\n\n\ndef recursively_remove_weight_norm(layer: nn.Layer):\n    for layer in layer.sublayers():\n        try:\n            nn.utils.remove_weight_norm(layer)\n        except ValueError as e:\n            # ther is not weight norm hoom in this layer\n            pass\n\n\ndef freeze(layer: nn.Layer):\n    for param in layer.parameters():\n        param.trainable = False\n\n\ndef unfreeze(layer: nn.Layer):\n    for param in layer.parameters():\n        param.trainable = True\n"
  },
  {
    "path": "paddlespeech/s2t/utils/log.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport getpass\nimport inspect\nimport os\nimport socket\nimport sys\n\nfrom loguru import logger\nfrom paddle import inference\n\n\ndef find_log_dir(log_dir=None):\n    \"\"\"Returns the most suitable directory to put log files into.\n    Args:\n        log_dir: str|None, if specified, the logfile(s) will be created in that\n            directory.  Otherwise if the --log_dir command-line flag is provided,\n            the logfile will be created in that directory.  Otherwise the logfile\n            will be created in a standard location.\n    Raises:\n        FileNotFoundError: raised when it cannot find a log directory.\n  \"\"\"\n    # Get a list of possible log dirs (will try to use them in order).\n    if log_dir:\n        # log_dir was explicitly specified as an arg, so use it and it alone.\n        dirs = [log_dir]\n    else:\n        dirs = ['/tmp/', './']\n\n    # Find the first usable log dir.\n    for d in dirs:\n        if os.path.isdir(d) and os.access(d, os.W_OK):\n            return d\n    raise FileNotFoundError(\n        \"Can't find a writable directory for logs, tried %s\" % dirs)\n\n\ndef find_log_dir_and_names(program_name=None, log_dir=None):\n    \"\"\"Computes the directory and filename prefix for log file.\n    Args:\n        program_name: str|None, the filename part of the path to the program that\n            is running without its extension.  e.g: if your program is called\n            'usr/bin/foobar.py' this method should probably be called with\n            program_name='foobar' However, this is just a convention, you can\n            pass in any string you want, and it will be used as part of the\n            log filename. If you don't pass in anything, the default behavior\n            is as described in the example.  In python standard logging mode,\n            the program_name will be prepended with py_ if it is the program_name\n            argument is omitted.\n        log_dir: str|None, the desired log directory.\n    Returns:\n        (log_dir, file_prefix, symlink_prefix)\n    Raises:\n        FileNotFoundError: raised in Python 3 when it cannot find a log directory.\n        OSError: raised in Python 2 when it cannot find a log directory.\n  \"\"\"\n    if not program_name:\n        # Strip the extension (foobar.par becomes foobar, and\n        # fubar.py becomes fubar). We do this so that the log\n        # file names are similar to C++ log file names.\n        program_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]\n\n        # Prepend py_ to files so that python code gets a unique file, and\n        # so that C++ libraries do not try to write to the same log files as us.\n        program_name = 'py_%s' % program_name\n\n    actual_log_dir = find_log_dir(log_dir=log_dir)\n\n    try:\n        username = getpass.getuser()\n    except KeyError:\n        # This can happen, e.g. when running under docker w/o passwd file.\n        if hasattr(os, 'getuid'):\n            # Windows doesn't have os.getuid\n            username = str(os.getuid())\n        else:\n            username = 'unknown'\n    hostname = socket.gethostname()\n    file_prefix = '%s.%s.%s.log' % (program_name, hostname, username)\n\n    return actual_log_dir, file_prefix, program_name\n\n\nclass Log():\n    \"\"\"Default Logger for all.\"\"\"\n    logger.remove()\n\n    _call_from_cli = False\n    _frame = inspect.currentframe()\n    while _frame:\n        if 'paddlespeech/cli/entry.py' in _frame.f_code.co_filename or 'paddlespeech/t2s' in _frame.f_code.co_filename:\n            _call_from_cli = True\n            break\n        _frame = _frame.f_back\n\n    if _call_from_cli:\n        logger.add(\n            sys.stdout,\n            level='ERROR',\n            enqueue=True,\n            filter=lambda record: record['level'].no >= 20)\n    else:\n        logger.add(\n            sys.stdout,\n            level='INFO',\n            enqueue=True,\n            filter=lambda record: record['level'].no >= 20)\n        _, file_prefix, _ = find_log_dir_and_names()\n        sink_prefix = os.path.join(\"exp/log\", file_prefix)\n        sink_path = sink_prefix[:-3] + \"{time}.log\"\n        logger.add(sink_path, level='DEBUG', enqueue=True, rotation=\"500 MB\")\n\n    def __init__(self, name=None):\n        pass\n\n    def getlog(self):\n        return logger\n\n\nclass Autolog:\n    \"\"\"Just used by fullchain project\"\"\"\n\n    def __init__(self,\n                 batch_size,\n                 model_name=\"DeepSpeech\",\n                 model_precision=\"fp32\"):\n        import auto_log\n        pid = os.getpid()\n        if os.environ.get('CUDA_VISIBLE_DEVICES', None):\n            gpu_id = int(os.environ['CUDA_VISIBLE_DEVICES'].split(',')[0])\n            infer_config = inference.Config()\n            infer_config.enable_use_gpu(100, gpu_id)\n        else:\n            gpu_id = None\n            infer_config = inference.Config()\n\n        self.autolog = auto_log.AutoLogger(\n            model_name=model_name,\n            model_precision=model_precision,\n            batch_size=batch_size,\n            data_shape=\"dynamic\",\n            save_path=\"./output/auto_log.lpg\",\n            inference_config=infer_config,\n            pids=pid,\n            process_name=None,\n            gpu_ids=gpu_id,\n            time_keys=['preprocess_time', 'inference_time', 'postprocess_time'],\n            warmup=0)\n\n    def getlog(self):\n        return self.autolog\n"
  },
  {
    "path": "paddlespeech/s2t/utils/mp_tools.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom functools import wraps\n\nfrom paddle import distributed as dist\n\n__all__ = [\"rank_zero_only\"]\n\n\ndef rank_zero_only(func):\n    @wraps(func)\n    def wrapper(*args, **kwargs):\n        rank = dist.get_rank()\n        if rank != 0:\n            return\n        result = func(*args, **kwargs)\n        return result\n\n    return wrapper\n"
  },
  {
    "path": "paddlespeech/s2t/utils/profiler.py",
    "content": "# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\n\nimport paddle\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n# A global variable to record the number of calling times for profiler\n# functions. It is used to specify the tracing range of training steps.\n_profiler_step_id = 0\n\n# A global variable to avoid parsing from string every time.\n_profiler_options = None\n\n\nclass ProfilerOptions(object):\n    '''\n    Use a string to initialize a ProfilerOptions.\n    The string should be in the format: \"key1=value1;key2=value;key3=value3\".\n    For example:\n      \"profile_path=model.profile\"\n      \"batch_range=[50, 60]; profile_path=model.profile\"\n      \"batch_range=[50, 60]; tracer_option=OpDetail; profile_path=model.profile\"\n    ProfilerOptions supports following key-value pair:\n      batch_range      - a integer list, e.g. [100, 110].\n      state            - a string, the optional values are 'CPU', 'GPU' or 'All'. \n      sorted_key       - a string, the optional values are 'calls', 'total',\n                         'max', 'min' or 'ave.\n      tracer_option    - a string, the optional values are 'Default', 'OpDetail',\n                         'AllOpDetail'.\n      profile_path     - a string, the path to save the serialized profile data,\n                         which can be used to generate a timeline.\n      exit_on_finished - a boolean.\n    '''\n\n    def __init__(self, options_str):\n        assert isinstance(options_str, str)\n\n        self._options = {\n            'batch_range': [10, 20],\n            'state': 'All',\n            'sorted_key': 'total',\n            'tracer_option': 'Default',\n            'profile_path': '/tmp/profile',\n            'exit_on_finished': True\n        }\n        self._parse_from_string(options_str)\n\n    def _parse_from_string(self, options_str):\n        if not options_str:\n            return\n\n        for kv in options_str.replace(' ', '').split(';'):\n            key, value = kv.split('=')\n            if key == 'batch_range':\n                value_list = value.replace('[', '').replace(']', '').split(',')\n                value_list = list(map(int, value_list))\n                if len(value_list) >= 2 and value_list[0] >= 0 and value_list[\n                        1] > value_list[0]:\n                    self._options[key] = value_list\n            elif key == 'exit_on_finished':\n                self._options[key] = value.lower() in (\"yes\", \"true\", \"t\", \"1\")\n            elif key in [\n                    'state', 'sorted_key', 'tracer_option', 'profile_path'\n            ]:\n                self._options[key] = value\n\n    def __getitem__(self, name):\n        if self._options.get(name, None) is None:\n            raise ValueError(\n                \"ProfilerOptions does not have an option named %s.\" % name)\n        return self._options[name]\n\n\ndef add_profiler_step(options_str=None):\n    '''\n    Enable the operator-level timing using PaddlePaddle's profiler.\n    The profiler uses a independent variable to count the profiler steps.\n    One call of this function is treated as a profiler step.\n    \n    Args:\n      profiler_options - a string to initialize the ProfilerOptions.\n                         Default is None, and the profiler is disabled.\n    '''\n    if options_str is None:\n        return\n\n    global _profiler_step_id\n    global _profiler_options\n\n    if _profiler_options is None:\n        _profiler_options = ProfilerOptions(options_str)\n        logger.info(f\"Profiler: {options_str}\")\n        logger.info(f\"Profiler: {_profiler_options._options}\")\n\n    if _profiler_step_id == _profiler_options['batch_range'][0]:\n        paddle.utils.profiler.start_profiler(_profiler_options['state'],\n                                             _profiler_options['tracer_option'])\n    elif _profiler_step_id == _profiler_options['batch_range'][1]:\n        paddle.utils.profiler.stop_profiler(_profiler_options['sorted_key'],\n                                            _profiler_options['profile_path'])\n        if _profiler_options['exit_on_finished']:\n            sys.exit(0)\n\n    _profiler_step_id += 1\n"
  },
  {
    "path": "paddlespeech/s2t/utils/socket_server.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport random\nimport socket\nimport socketserver\nimport struct\nimport time\nimport wave\nfrom time import gmtime\nfrom time import strftime\n\nimport jsonlines\n\n__all__ = [\"socket_send\", \"warm_up_test\", \"AsrTCPServer\", \"AsrRequestHandler\"]\n\n\ndef socket_send(server_ip: str, server_port: str, data: bytes):\n    # Connect to server and send data\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.connect((server_ip, server_port))\n    sent = data\n    sock.sendall(struct.pack('>i', len(sent)) + sent)\n    print('Speech[length=%d] Sent.' % len(sent))\n    # Receive data from the server and shut down\n    received = sock.recv(1024)\n    print(\"Recognition Results: {}\".format(received.decode('utf8')))\n    sock.close()\n\n\ndef warm_up_test(audio_process_handler,\n                 manifest_path,\n                 num_test_cases,\n                 random_seed=0):\n    \"\"\"Warming-up test.\"\"\"\n    with jsonlines.open(manifest_path) as reader:\n        manifest = list(reader)\n    rng = random.Random(random_seed)\n    samples = rng.sample(manifest, num_test_cases)\n    for idx, sample in enumerate(samples):\n        print(\"Warm-up Test Case %d: %s\" % (idx, sample['feat']))\n        start_time = time.time()\n        transcript = audio_process_handler(sample['feat'])\n        finish_time = time.time()\n        print(\"Response Time: %f, Transcript: %s\" %\n              (finish_time - start_time, transcript))\n\n\nclass AsrTCPServer(socketserver.TCPServer):\n    \"\"\"The ASR TCP Server.\"\"\"\n\n    def __init__(self,\n                 server_address,\n                 RequestHandlerClass,\n                 speech_save_dir,\n                 audio_process_handler,\n                 bind_and_activate=True):\n        self.speech_save_dir = speech_save_dir\n        self.audio_process_handler = audio_process_handler\n        socketserver.TCPServer.__init__(\n            self, server_address, RequestHandlerClass, bind_and_activate=True)\n\n\nclass AsrRequestHandler(socketserver.BaseRequestHandler):\n    \"\"\"The ASR request handler.\"\"\"\n\n    def handle(self):\n        # receive data through TCP socket\n        chunk = self.request.recv(1024)\n        target_len = struct.unpack('>i', chunk[:4])[0]\n        data = chunk[4:]\n        while len(data) < target_len:\n            chunk = self.request.recv(1024)\n            data += chunk\n        # write to file\n        filename = self._write_to_file(data)\n\n        print(\"Received utterance[length=%d] from %s, saved to %s.\" %\n              (len(data), self.client_address[0], filename))\n        start_time = time.time()\n        transcript = self.server.audio_process_handler(filename)\n        finish_time = time.time()\n        print(\"Response Time: %f, Transcript: %s\" %\n              (finish_time - start_time, transcript))\n        self.request.sendall(transcript.encode('utf-8'))\n\n    def _write_to_file(self, data):\n        # prepare save dir and filename\n        if not os.path.exists(self.server.speech_save_dir):\n            os.mkdir(self.server.speech_save_dir)\n        timestamp = strftime(\"%Y%m%d%H%M%S\", gmtime())\n        out_filename = os.path.join(\n            self.server.speech_save_dir,\n            timestamp + \"_\" + self.client_address[0] + \".wav\")\n        # write to wav file\n        file = wave.open(out_filename, 'wb')\n        file.setnchannels(1)\n        file.setsampwidth(2)\n        file.setframerate(16000)\n        file.writeframes(data)\n        file.close()\n        return out_filename\n"
  },
  {
    "path": "paddlespeech/s2t/utils/spec_augment.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/s2t/utils/tensor_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Unility functions for Transformer.\"\"\"\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\n\nfrom paddlespeech.s2t.utils.log import Log\n\n__all__ = [\"pad_sequence\", \"add_sos_eos\", \"th_accuracy\", \"has_tensor\"]\n\nlogger = Log(__name__).getlog()\n\n\ndef has_tensor(val):\n    if isinstance(val, (list, tuple)):\n        for item in val:\n            if has_tensor(item):\n                return True\n    elif isinstance(val, dict):\n        for k, v in val.items():\n            print(k)\n            if has_tensor(v):\n                return True\n    else:\n        return paddle.is_tensor(val)\n\n\ndef pad_sequence(sequences: List[paddle.Tensor],\n                 batch_first: bool=False,\n                 padding_value: float=0.0) -> paddle.Tensor:\n    r\"\"\"Pad a list of variable length Tensors with ``padding_value``\n\n    ``pad_sequence`` stacks a list of Tensors along a new dimension,\n    and pads them to equal length. For example, if the input is list of\n    sequences with size ``L x *`` and if batch_first is False, and ``T x B x *``\n    otherwise.\n\n    `B` is batch size. It is equal to the number of elements in ``sequences``.\n    `T` is length of the longest sequence.\n    `L` is length of the sequence.\n    `*` is any number of trailing dimensions, including none.\n\n    Example:\n        >>> from paddle.nn.utils.rnn import pad_sequence\n        >>> a = paddle.ones(25, 300)\n        >>> b = paddle.ones(22, 300)\n        >>> c = paddle.ones(15, 300)\n        >>> pad_sequence([a, b, c]).shape\n        paddle.Tensor([25, 3, 300])\n\n    Note:\n        This function returns a Tensor of size ``T x B x *`` or ``B x T x *``\n        where `T` is the length of the longest sequence. This function assumes\n        trailing dimensions and type of all the Tensors in sequences are same.\n\n    Args:\n        sequences (list[Tensor]): list of variable length sequences.\n        batch_first (bool, optional): output will be in ``B x T x *`` if True, or in\n            ``T x B x *`` otherwise\n        padding_value (float, optional): value for padded elements. Default: 0.\n\n    Returns:\n        Tensor of size ``T x B x *`` if :attr:`batch_first` is ``False``.\n        Tensor of size ``B x T x *`` otherwise\n    \"\"\"\n\n    # assuming trailing dimensions and type of all the Tensors\n    # in sequences are same and fetching those from sequences[0]\n    max_size = paddle.shape(sequences[0])\n    # (TODO Hui Zhang): slice not support `end==start`\n    # trailing_dims = max_size[1:]\n    trailing_dims = tuple(\n        max_size[1:].numpy().tolist()) if sequences[0].ndim >= 2 else ()\n    max_len = max([s.shape[0] for s in sequences])\n    if batch_first:\n        out_dims = (len(sequences), max_len) + trailing_dims\n    else:\n        out_dims = (max_len, len(sequences)) + trailing_dims\n\n    out_tensor = sequences[0].new_full(out_dims, padding_value)\n    for i, tensor in enumerate(sequences):\n        length = tensor.shape[0]\n        # use index notation to prevent duplicate references to the tensor\n        logger.debug(\n            f\"length {length}, out_tensor {out_tensor.shape}, tensor {tensor.shape}\"\n        )\n        if batch_first:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # TODO (Hui Zhang): set_value op not support int16\n            # TODO (Hui Zhang): set_varbase 2 rank not support [0,0,...]\n            # out_tensor[i, :length, ...] = tensor\n            if length != 0:\n                out_tensor[i, :length] = tensor\n            else:\n                out_tensor[i, length] = tensor\n        else:\n            # TODO (Hui Zhang): set_value op not support `end==start`\n            # out_tensor[:length, i, ...] = tensor\n            if length != 0:\n                out_tensor[:length, i] = tensor\n            else:\n                out_tensor[length, i] = tensor\n\n    return out_tensor\n\n\ndef add_sos_eos(ys_pad: paddle.Tensor, sos: int, eos: int,\n                ignore_id: int) -> Tuple[paddle.Tensor, paddle.Tensor]:\n    \"\"\"Add <sos> and <eos> labels.\n    Args:\n        ys_pad (paddle.Tensor): batch of padded target sequences (B, Lmax)\n        sos (int): index of <sos>\n        eos (int): index of <eeos>\n        ignore_id (int): index of padding\n    Returns:\n        ys_in (paddle.Tensor) : (B, Lmax + 1)\n        ys_out (paddle.Tensor) : (B, Lmax + 1)\n    Examples:\n        >>> sos_id = 10\n        >>> eos_id = 11\n        >>> ignore_id = -1\n        >>> ys_pad\n        tensor([[ 1,  2,  3,  4,  5],\n                [ 4,  5,  6, -1, -1],\n                [ 7,  8,  9, -1, -1]], dtype=paddle.int32)\n        >>> ys_in,ys_out=add_sos_eos(ys_pad, sos_id , eos_id, ignore_id)\n        >>> ys_in\n        tensor([[10,  1,  2,  3,  4,  5],\n                [10,  4,  5,  6, 11, 11],\n                [10,  7,  8,  9, 11, 11]])\n        >>> ys_out\n        tensor([[ 1,  2,  3,  4,  5, 11],\n                [ 4,  5,  6, 11, -1, -1],\n                [ 7,  8,  9, 11, -1, -1]])\n    \"\"\"\n    # TODO(Hui Zhang): using comment code,\n    #_sos = paddle.to_tensor(\n    #    [sos], dtype=paddle.long, stop_gradient=True, place=ys_pad.place)\n    #_eos = paddle.to_tensor(\n    #    [eos], dtype=paddle.long, stop_gradient=True, place=ys_pad.place)\n    #ys = [y[y != ignore_id] for y in ys_pad]  # parse padded ys\n    #ys_in = [paddle.cat([_sos, y], dim=0) for y in ys]\n    #ys_out = [paddle.cat([y, _eos], dim=0) for y in ys]\n    #return pad_sequence(ys_in, padding_value=eos), pad_sequence(ys_out, padding_value=ignore_id)\n    B = ys_pad.shape[0]\n    _sos = paddle.ones([B, 1], dtype=ys_pad.dtype) * sos\n    _eos = paddle.ones([B, 1], dtype=ys_pad.dtype) * eos\n    ys_in = paddle.cat([_sos, ys_pad], dim=1)\n    mask_pad = (ys_in == ignore_id)\n    ys_in = ys_in.masked_fill(mask_pad, eos)\n\n    ys_out = paddle.cat([ys_pad, _eos], dim=1)\n    ys_out = ys_out.masked_fill(mask_pad, eos)\n    mask_eos = (ys_out == ignore_id)\n    ys_out = ys_out.masked_fill(mask_eos, eos)\n    ys_out = ys_out.masked_fill(mask_pad, ignore_id)\n    return ys_in, ys_out\n\n\ndef th_accuracy(pad_outputs: paddle.Tensor,\n                pad_targets: paddle.Tensor,\n                ignore_label: int) -> float:\n    \"\"\"Calculate accuracy.\n    Args:\n        pad_outputs (Tensor): Prediction tensors (B * Lmax, D).\n        pad_targets (LongTensor): Target label tensors (B, Lmax, D).\n        ignore_label (int): Ignore label id.\n    Returns:\n        float: Accuracy value (0.0 - 1.0).\n    \"\"\"\n    pad_pred = pad_outputs.reshape(\n        [pad_targets.shape[0], pad_targets.shape[1],\n         pad_outputs.shape[1]]).argmax(2)\n    mask = pad_targets != ignore_label\n\n    numerator = paddle.sum(\n        pad_pred.masked_select(mask) == pad_targets.masked_select(mask))\n    denominator = paddle.sum(mask)\n    return float(numerator) / float(denominator)\n"
  },
  {
    "path": "paddlespeech/s2t/utils/text_grid.py",
    "content": "# Copyright 2021 Mobvoi Inc. All Rights Reserved.\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from wenet(https://github.com/wenet-e2e/wenet)\nfrom typing import Dict\nfrom typing import List\nfrom typing import Text\n\nimport textgrid\n\n\ndef segment_alignment(alignment: List[int], blank_id=0) -> List[List[int]]:\n    \"\"\"segment ctc alignment ids by continuous blank and repeat label.\n\n    Args:\n        alignment (List[int]): ctc alignment id sequence. \n            e.g. [0, 0, 0, 1, 1, 1, 2, 0, 0, 3]\n        blank_id (int, optional): blank id. Defaults to 0.\n\n    Returns:\n        List[List[int]]: token align, segment aligment id sequence. \n            e.g. [[0, 0, 0, 1, 1, 1], [2], [0, 0, 3]]\n    \"\"\"\n    # convert alignment to a praat format, which is a doing phonetics\n    # by computer and helps analyzing alignment\n    align_segs = []\n    # get frames level duration for each token\n    start = 0\n    end = 0\n    while end < len(alignment):\n        while end < len(alignment) and alignment[end] == blank_id:  # blank\n            end += 1\n        if end == len(alignment):\n            align_segs[-1].extend(alignment[start:])\n            break\n        end += 1\n        while end < len(alignment) and alignment[end - 1] == alignment[\n                end]:  # repeat label\n            end += 1\n        align_segs.append(alignment[start:end])\n        start = end\n    return align_segs\n\n\ndef align_to_tierformat(align_segs: List[List[int]],\n                        subsample: int,\n                        token_dict: Dict[int, Text],\n                        blank_id=0) -> List[Text]:\n    \"\"\"Generate textgrid.Interval format from alignment segmentations.\n\n    Args:\n        align_segs (List[List[int]]): segmented ctc alignment ids.\n        subsample (int): 25ms frame_length, 10ms hop_length, 1/subsample\n        token_dict (Dict[int, Text]): int -> str map.\n\n    Returns:\n        List[Text]: list of textgrid.Interval text, str(start, end, text).\n    \"\"\"\n    hop_length = 10  # ms\n    second_ms = 1000  # ms\n    frame_per_second = second_ms / hop_length  # 25ms frame_length, 10ms hop_length\n    second_per_frame = 1.0 / frame_per_second\n\n    begin = 0\n    duration = 0\n    tierformat = []\n\n    for idx, tokens in enumerate(align_segs):\n        token_len = len(tokens)\n        token = tokens[-1]\n        # time duration in second\n        duration = token_len * subsample * second_per_frame\n        if idx < len(align_segs) - 1:\n            print(f\"{begin:.2f} {begin + duration:.2f} {token_dict[token]}\")\n            tierformat.append(\n                f\"{begin:.2f} {begin + duration:.2f} {token_dict[token]}\\n\")\n        else:\n            for i in tokens:\n                if i != blank_id:\n                    token = i\n                    break\n            print(f\"{begin:.2f} {begin + duration:.2f} {token_dict[token]}\")\n            tierformat.append(\n                f\"{begin:.2f} {begin + duration:.2f} {token_dict[token]}\\n\")\n        begin = begin + duration\n\n    return tierformat\n\n\ndef generate_textgrid(maxtime: float,\n                      intervals: List[Text],\n                      output: Text,\n                      name: Text='ali') -> None:\n    \"\"\"Create alignment textgrid file.\n\n    Args:\n        maxtime (float): audio duartion.\n        intervals (List[Text]): ctc output alignment. e.g. \"start-time end-time word\" per item.\n        output (Text): textgrid filepath.\n        name (Text, optional): tier or layer name. Defaults to 'ali'.\n    \"\"\"\n    # Download Praat: https://www.fon.hum.uva.nl/praat/\n    avg_interval = maxtime / (len(intervals) + 1)\n    print(f\"average second/token: {avg_interval}\")\n    margin = 0.0001\n\n    tg = textgrid.TextGrid(maxTime=maxtime)\n    tier = textgrid.IntervalTier(name=name, maxTime=maxtime)\n\n    i = 0\n    for dur in intervals:\n        s, e, text = dur.split()\n        tier.add(minTime=float(s) + margin, maxTime=float(e), mark=text)\n\n    tg.append(tier)\n\n    tg.write(output)\n    print(\"successfully generator textgrid {}.\".format(output))\n"
  },
  {
    "path": "paddlespeech/s2t/utils/utility.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Contains common utility functions.\"\"\"\nimport math\nimport os\nimport random\nimport sys\nfrom contextlib import contextmanager\nfrom pprint import pformat\nfrom typing import List\n\nimport distutils.util\nimport numpy as np\nimport paddle\nimport soundfile\n\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\n\n__all__ = [\"all_version\", \"UpdateConfig\", \"seed_all\", \"log_add\"]\n\n\ndef all_version():\n    vers = {\n        \"python\": sys.version,\n        \"paddle\": paddle.__version__,\n        \"paddle_commit\": paddle.version.commit,\n        \"soundfile\": soundfile.__version__,\n    }\n    logger.info(f\"Deps Module Version:{pformat(list(vers.items()))}\")\n\n\n@contextmanager\ndef UpdateConfig(config):\n    \"\"\"Update yacs config\"\"\"\n    config.defrost()\n    yield\n    config.freeze()\n\n\ndef seed_all(seed: int=20210329):\n    \"\"\"freeze random generator seed.\"\"\"\n    np.random.seed(seed)\n    random.seed(seed)\n    paddle.seed(seed)\n\n\ndef log_add(args: List[int]) -> float:\n    \"\"\"Stable log add\n\n    Args:\n        args (List[int]): log scores\n\n    Returns:\n        float: sum of log scores\n    \"\"\"\n    if all(a == -float('inf') for a in args):\n        return -float('inf')\n    a_max = max(args)\n    lsp = math.log(sum(math.exp(a - a_max) for a in args))\n    return a_max + lsp\n\n\ndef get_subsample(config):\n    \"\"\"Subsample rate from config.\n\n    Args:\n        config (yacs.config.CfgNode): yaml config\n\n    Returns:\n        int: subsample rate.\n    \"\"\"\n    if config['encoder'] == 'squeezeformer':\n        return 4\n    else:\n        input_layer = config[\"encoder_conf\"][\"input_layer\"]\n        assert input_layer in [\"conv2d\", \"conv2d6\", \"conv2d8\"]\n    if input_layer == \"conv2d\":\n        return 4\n    elif input_layer == \"conv2d6\":\n        return 6\n    elif input_layer == \"conv2d8\":\n        return 8\n"
  },
  {
    "path": "paddlespeech/server/README.md",
    "content": "# PaddleSpeech Server Command Line\n\n([简体中文](./README_cn.md)|English)\n\n The simplest approach to use PaddleSpeech Server including server and client.\n\n ## PaddleSpeech Server\n ### Help\n ```bash\n paddlespeech_server help\n ```\n ### Start the server\n First set the service-related configuration parameters, similar to `./conf/application.yaml`. Set `engine_list`, which represents the speech tasks included in the service to be started.\n **Note:** If the service can be started normally in the container, but the client access IP is unreachable, you can try to replace the `host` address in the configuration file with the local IP address.\n\n Then start the service:\n ```bash\n paddlespeech_server start --config_file ./conf/application.yaml\n ```\n\n ## PaddleSpeech Client\n ### Help\n ```bash\n paddlespeech_client help\n ```\n ### Access speech recognition services \n ```\n paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n ```\n \n ### Access text to speech services\n ```bash\n paddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n ```\n \n ### Access audio classification services\n ```bash\n paddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input input.wav\n ```\n\n ## Online ASR Server\n\n### Lanuch online asr server\n```\npaddlespeech_server start --config_file conf/ws_conformer_application.yaml\n```\n\n### Access online asr server\n\n```\npaddlespeech_client asr_online  --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n```\n\n## Online TTS Server\n\n### Lanuch online tts server\n```\npaddlespeech_server start --config_file conf/tts_online_application.yaml\n```\n\n### Access online tts server\n\n```\npaddlespeech_client tts_online  --server_ip 127.0.0.1 --port 8092 --input \"您好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n```\n\n\n## Speaker Verification\n\n### Lanuch speaker verification server\n\n```\npaddlespeech_server start --config_file conf/vector_application.yaml\n```\n\n### Extract speaker embedding from aduio\n\n```\npaddlespeech_client vector --task spk  --server_ip 127.0.0.1 --port 8090 --input 85236145389.wav\n```\n\n### Get score with speaker audio embedding\n\n```\npaddlespeech_client vector --task score  --server_ip 127.0.0.1 --port 8090 --enroll 123456789.wav --test 85236145389.wav\n```\n"
  },
  {
    "path": "paddlespeech/server/README_cn.md",
    "content": "# PaddleSpeech Server 命令行工具\n\n(简体中文|[English](./README.md))\n\n它提供了最简便的方式调用 PaddleSpeech 语音服务用一行命令就可以轻松启动服务和调用服务。\n\n ## 服务端命令行使用\n ### 帮助\n ```bash\n paddlespeech_server help\n ```\n ### 启动服务\n 首先设置服务相关配置文件，类似于 `./conf/application.yaml`，设置 `engine_list`，该值表示即将启动的服务中包含的语音任务。\n **注意：** 如果在容器里可正常启动服务，但客户端访问 ip 不可达，可尝试将配置文件中 `host` 地址换成本地 ip 地址。\n 然后启动服务：\n ```bash\n paddlespeech_server start --config_file ./conf/application.yaml\n ```\n\n ## 客户端命令行使用\n ### 帮助\n ```bash\n paddlespeech_client help\n ```\n ### 访问语音识别服务 \n ```\n paddlespeech_client asr --server_ip 127.0.0.1 --port 8090 --input input_16k.wav\n ```\n \n ### 访问语音合成服务\n ```bash\n paddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input \"你好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n ```\n\n ### 访问音频分类服务\n ```bash\n paddlespeech_client cls --server_ip 127.0.0.1 --port 8090 --input input.wav\n ```\n\n## 流式ASR\n\n### 启动流式语音识别服务\n\n```\npaddlespeech_server start --config_file conf/ws_conformer_application.yaml\n```\n\n### 访问流式语音识别服务\n\n```\npaddlespeech_client asr_online  --server_ip 127.0.0.1 --port 8090 --input zh.wav\n```\n\n## 流式TTS\n\n### 启动流式语音合成服务\n\n```\npaddlespeech_server start --config_file conf/tts_online_application.yaml\n```\n\n### 访问流式语音合成服务\n\n```\npaddlespeech_client tts_online  --server_ip 127.0.0.1 --port 8092 --input \"您好，欢迎使用百度飞桨深度学习框架！\" --output output.wav\n```\n\n## 声纹识别\n\n### 启动声纹识别服务\n\n```\npaddlespeech_server start --config_file conf/vector_application.yaml\n```\n\n### 获取说话人音频声纹\n\n```\npaddlespeech_client vector --task spk  --server_ip 127.0.0.1 --port 8090 --input 85236145389.wav\n```\n\n### 两个说话人音频声纹打分\n\n```\npaddlespeech_client vector --task score  --server_ip 127.0.0.1 --port 8090 --enroll 123456789.wav --test 85236145389.wav\n```\n"
  },
  {
    "path": "paddlespeech/server/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport _locale\n\nfrom .base_commands import ClientBaseCommand\nfrom .base_commands import ClientHelpCommand\nfrom .base_commands import ServerBaseCommand\nfrom .base_commands import ServerHelpCommand\nfrom .bin.paddlespeech_client import ASRClientExecutor\nfrom .bin.paddlespeech_client import CLSClientExecutor\nfrom .bin.paddlespeech_client import TTSClientExecutor\nfrom .bin.paddlespeech_server import ServerExecutor\n\n_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])\n"
  },
  {
    "path": "paddlespeech/server/base_commands.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nfrom .entry import client_commands\nfrom .entry import server_commands\nfrom .util import cli_client_register\nfrom .util import cli_server_register\nfrom .util import get_client_command\nfrom .util import get_server_command\n\n__all__ = [\n    'ServerBaseCommand',\n    'ServerHelpCommand',\n    'ClientBaseCommand',\n    'ClientHelpCommand',\n]\n\n\n@cli_server_register(name='paddlespeech_server')\nclass ServerBaseCommand:\n    def execute(self, argv: List[str]) -> bool:\n        help = get_server_command('paddlespeech_server.help')\n        return help().execute(argv)\n\n\n@cli_server_register(\n    name='paddlespeech_server.help', description='Show help for commands.')\nclass ServerHelpCommand:\n    def execute(self, argv: List[str]) -> bool:\n        msg = 'Usage:\\n'\n        msg += '    paddlespeech_server <command> <options>\\n\\n'\n        msg += 'Commands:\\n'\n        for command, detail in server_commands['paddlespeech_server'].items():\n            if command.startswith('_'):\n                continue\n\n            if '_description' not in detail:\n                continue\n            msg += '    {:<15}        {}\\n'.format(command,\n                                                   detail['_description'])\n\n        print(msg)\n        return True\n\n\n@cli_client_register(name='paddlespeech_client')\nclass ClientBaseCommand:\n    def execute(self, argv: List[str]) -> bool:\n        help = get_client_command('paddlespeech_client.help')\n        return help().execute(argv)\n\n\n@cli_client_register(\n    name='paddlespeech_client.help', description='Show help for commands.')\nclass ClientHelpCommand:\n    def execute(self, argv: List[str]) -> bool:\n        msg = 'Usage:\\n'\n        msg += '    paddlespeech_client <command> <options>\\n\\n'\n        msg += 'Commands:\\n'\n        for command, detail in client_commands['paddlespeech_client'].items():\n            if command.startswith('_'):\n                continue\n\n            if '_description' not in detail:\n                continue\n            msg += '    {:<15}        {}\\n'.format(command,\n                                                   detail['_description'])\n\n        print(msg)\n        return True\n"
  },
  {
    "path": "paddlespeech/server/bin/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .paddlespeech_client import ASRClientExecutor\nfrom .paddlespeech_client import TTSClientExecutor\nfrom .paddlespeech_server import ServerExecutor\nfrom .paddlespeech_server import ServerStatsExecutor\n"
  },
  {
    "path": "paddlespeech/server/bin/paddlespeech_client.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport asyncio\nimport base64\nimport io\nimport json\nimport os\nimport random\nimport sys\nimport time\nimport warnings\nfrom typing import List\n\nimport numpy as np\nimport requests\nimport soundfile\n\nfrom ..executor import BaseExecutor\nfrom ..util import cli_client_register\nfrom ..util import stats_wrapper\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.utils.audio_handler import ASRWsAudioHandler\nfrom paddlespeech.server.utils.audio_process import wav2pcm\nfrom paddlespeech.server.utils.util import compute_delay\nfrom paddlespeech.server.utils.util import wav2base64\nwarnings.filterwarnings(\"ignore\")\n\n__all__ = [\n    'TTSClientExecutor', 'TTSOnlineClientExecutor', 'ASRClientExecutor',\n    'ASROnlineClientExecutor', 'CLSClientExecutor', 'VectorClientExecutor'\n]\n\n\n@cli_client_register(\n    name='paddlespeech_client.tts', description='visit tts service')\nclass TTSClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(TTSClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.tts', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Text to be synthesized.',\n            required=True)\n        self.parser.add_argument(\n            '--spk_id', type=int, default=0, help='Speaker id')\n        self.parser.add_argument(\n            '--speed',\n            type=float,\n            default=1.0,\n            help='Audio speed, the value should be set between 0 and 3')\n        self.parser.add_argument(\n            '--volume',\n            type=float,\n            default=1.0,\n            help='Audio volume, the value should be set between 0 and 3')\n        self.parser.add_argument(\n            '--sample_rate',\n            type=int,\n            default=0,\n            choices=[0, 8000, 16000],\n            help='Sampling rate, the default is the same as the model')\n        self.parser.add_argument(\n            '--output', type=str, default=None, help='Synthesized audio file')\n\n    def postprocess(self, wav_base64: str, outfile: str) -> float:\n        audio_data_byte = base64.b64decode(wav_base64)\n        # from byte\n        samples, sample_rate = soundfile.read(\n            io.BytesIO(audio_data_byte), dtype='float32')\n\n        # transform audio\n        if outfile.endswith(\".wav\"):\n            soundfile.write(outfile, samples, sample_rate)\n        elif outfile.endswith(\".pcm\"):\n            temp_wav = str(random.getrandbits(128)) + \".wav\"\n            soundfile.write(temp_wav, samples, sample_rate)\n            wav2pcm(temp_wav, outfile, data_type=np.int16)\n            os.remove(temp_wav)\n        else:\n            logger.error(\"The format for saving audio only supports wav or pcm\")\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        spk_id = args.spk_id\n        speed = args.speed\n        volume = args.volume\n        sample_rate = args.sample_rate\n        output = args.output\n\n        try:\n            time_start = time.time()\n            res = self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                spk_id=spk_id,\n                speed=speed,\n                volume=volume,\n                sample_rate=sample_rate,\n                output=output)\n            time_end = time.time()\n            time_consume = time_end - time_start\n            response_dict = res.json()\n            logger.info(\"Save synthesized audio successfully on %s.\" % (output))\n            logger.info(\"Audio duration: %f s.\" %\n                        (response_dict['result']['duration']))\n            logger.info(\"Response time: %f s.\" % (time_consume))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to synthesized audio.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8090,\n                 spk_id: int=0,\n                 speed: float=1.0,\n                 volume: float=1.0,\n                 sample_rate: int=0,\n                 output: str=None):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n\n        url = 'http://' + server_ip + \":\" + str(port) + '/paddlespeech/tts'\n        request = {\n            \"text\": input,\n            \"spk_id\": spk_id,\n            \"speed\": speed,\n            \"volume\": volume,\n            \"sample_rate\": sample_rate,\n            \"save_path\": output\n        }\n\n        res = requests.post(url, json.dumps(request))\n        response_dict = res.json()\n        if output is not None:\n            self.postprocess(response_dict[\"result\"][\"audio\"], output)\n        return res\n\n\n@cli_client_register(\n    name='paddlespeech_client.tts_online',\n    description='visit tts online service')\nclass TTSOnlineClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(TTSOnlineClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.tts_online', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8092, help='server port')\n        self.parser.add_argument(\n            '--protocol',\n            type=str,\n            default=\"http\",\n            choices=[\"http\", \"websocket\"],\n            help='server protocol')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Text to be synthesized.',\n            required=True)\n        self.parser.add_argument(\n            '--spk_id', type=int, default=0, help='Speaker id')\n        self.parser.add_argument(\n            '--output',\n            type=str,\n            default=None,\n            help='Client saves synthesized audio')\n        self.parser.add_argument(\n            \"--play\", type=bool, help=\"whether to play audio\", default=False)\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        protocol = args.protocol\n        spk_id = args.spk_id\n        output = args.output\n        play = args.play\n\n        try:\n            self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                protocol=protocol,\n                spk_id=spk_id,\n                output=output,\n                play=play)\n            return True\n        except Exception as e:\n            logger.error(\"Failed to synthesized audio.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8092,\n                 protocol: str=\"http\",\n                 spk_id: int=0,\n                 output: str=None,\n                 play: bool=False):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n\n        if protocol == \"http\":\n            logger.info(\"tts http client start\")\n            from paddlespeech.server.utils.audio_handler import TTSHttpHandler\n            handler = TTSHttpHandler(server_ip, port, play)\n            first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list = handler.run(\n                input, spk_id, output)\n            delay_time_list = compute_delay(receive_time_list,\n                                            chunk_duration_list)\n\n        elif protocol == \"websocket\":\n            from paddlespeech.server.utils.audio_handler import TTSWsHandler\n            logger.info(\"tts websocket client start\")\n            handler = TTSWsHandler(server_ip, port, play)\n            loop = asyncio.get_event_loop()\n            first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list = loop.run_until_complete(\n                handler.run(input, spk_id, output))\n            delay_time_list = compute_delay(receive_time_list,\n                                            chunk_duration_list)\n\n        else:\n            logger.error(\"Please set correct protocol, http or websocket\")\n            sys.exit(-1)\n\n        logger.info(f\"sentence: {input}\")\n        logger.info(f\"duration: {duration} s\")\n        logger.info(f\"first response: {first_response} s\")\n        logger.info(f\"final response: {final_response} s\")\n        logger.info(f\"RTF: {final_response/duration}\")\n        if output is not None:\n            if save_audio_success:\n                logger.info(f\"Audio successfully saved in {output}\")\n            else:\n                logger.error(\"Audio save failed.\")\n\n        if delay_time_list != []:\n            logger.info(\n                f\"Delay situation: total number of packages: {len(receive_time_list)}, the number of delayed packets: {len(delay_time_list)}, minimum delay time: {min(delay_time_list)} s, maximum delay time: {max(delay_time_list)} s, average delay time: {sum(delay_time_list)/len(delay_time_list)} s, delay rate:{len(delay_time_list)/len(receive_time_list)}\"\n            )\n        else:\n            logger.info(\"The sentence has no delay in streaming synthesis.\")\n\n\n@cli_client_register(\n    name='paddlespeech_client.asr', description='visit asr service')\nclass ASRClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(ASRClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.asr', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Audio file to be recognized',\n            required=True)\n        self.parser.add_argument(\n            '--protocol',\n            type=str,\n            default=\"http\",\n            choices=[\"http\", \"websocket\"],\n            help='server protocol')\n        self.parser.add_argument(\n            '--sample_rate', type=int, default=16000, help='audio sample rate')\n        self.parser.add_argument(\n            '--lang', type=str, default=\"zh_cn\", help='language')\n        self.parser.add_argument(\n            '--audio_format', type=str, default=\"wav\", help='audio format')\n\n        self.parser.add_argument(\n            '--punc.server_ip',\n            type=str,\n            default=None,\n            dest=\"punc_server_ip\",\n            help='Punctuation server ip')\n        self.parser.add_argument(\n            '--punc.port',\n            type=int,\n            default=8091,\n            dest=\"punc_server_port\",\n            help='Punctuation server port')\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        sample_rate = args.sample_rate\n        lang = args.lang\n        audio_format = args.audio_format\n        protocol = args.protocol\n\n        try:\n            time_start = time.time()\n            res = self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                sample_rate=sample_rate,\n                lang=lang,\n                audio_format=audio_format,\n                protocol=protocol,\n                punc_server_ip=args.punc_server_ip,\n                punc_server_port=args.punc_server_port)\n            time_end = time.time()\n            logger.info(f\"ASR result: {res}\")\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to speech recognition.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8090,\n                 sample_rate: int=16000,\n                 lang: str=\"zh_cn\",\n                 audio_format: str=\"wav\",\n                 protocol: str=\"http\",\n                 punc_server_ip: str=None,\n                 punc_server_port: int=None):\n        \"\"\"Python API to call an executor.\n\n        Args:\n            input (str): The input audio file path\n            server_ip (str, optional): The ASR server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): The ASR server port. Defaults to 8090.\n            sample_rate (int, optional): The audio sample rate. Defaults to 16000.\n            lang (str, optional): The audio language type. Defaults to \"zh_cn\".\n            audio_format (str, optional): The audio format information. Defaults to \"wav\".\n            protocol (str, optional): The ASR server. Defaults to \"http\".\n\n        Returns:\n            str: The ASR results\n        \"\"\"\n        # we use the asr server to recognize the audio text content\n        # and paddlespeech_client asr only support http protocol\n        protocol = \"http\"\n        if protocol.lower() == \"http\":\n            from paddlespeech.server.utils.audio_handler import ASRHttpHandler\n            logger.info(\"asr http client start\")\n            handler = ASRHttpHandler(server_ip=server_ip, port=port)\n            res = handler.run(input, audio_format, sample_rate, lang)\n            res = res['result']['transcription']\n            logger.info(\"asr http client finished\")\n        else:\n            logger.error(f\"Sorry, we have not support protocol: {protocol},\"\n                         \"please use http or websocket protocol\")\n            sys.exit(-1)\n\n        return res\n\n\n@cli_client_register(\n    name='paddlespeech_client.asr_online',\n    description='visit asr online service')\nclass ASROnlineClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(ASROnlineClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.asr_online', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8091, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Audio file to be recognized',\n            required=True)\n        self.parser.add_argument(\n            '--sample_rate', type=int, default=16000, help='audio sample rate')\n        self.parser.add_argument(\n            '--lang', type=str, default=\"zh_cn\", help='language')\n        self.parser.add_argument(\n            '--audio_format', type=str, default=\"wav\", help='audio format')\n        self.parser.add_argument(\n            '--punc.server_ip',\n            type=str,\n            default=None,\n            dest=\"punc_server_ip\",\n            help='Punctuation server ip')\n        self.parser.add_argument(\n            '--punc.port',\n            type=int,\n            default=8190,\n            dest=\"punc_server_port\",\n            help='Punctuation server port')\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        sample_rate = args.sample_rate\n        lang = args.lang\n        audio_format = args.audio_format\n        try:\n            time_start = time.time()\n            res = self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                sample_rate=sample_rate,\n                lang=lang,\n                audio_format=audio_format,\n                punc_server_ip=args.punc_server_ip,\n                punc_server_port=args.punc_server_port)\n            time_end = time.time()\n            logger.info(res)\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to speech recognition.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8091,\n                 sample_rate: int=16000,\n                 lang: str=\"zh_cn\",\n                 audio_format: str=\"wav\",\n                 punc_server_ip: str=None,\n                 punc_server_port: str=None):\n        \"\"\"Python API to call asr online executor.\n\n        Args:\n            input (str): the audio file to be send to streaming asr service.\n            server_ip (str, optional): streaming asr server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): streaming asr server port. Defaults to 8091.\n            sample_rate (int, optional): audio sample rate. Defaults to 16000.\n            lang (str, optional): audio language type. Defaults to \"zh_cn\".\n            audio_format (str, optional): audio format. Defaults to \"wav\".\n            punc_server_ip (str, optional): punctuation server ip. Defaults to None.\n            punc_server_port (str, optional): punctuation server port. Defaults to None.\n\n        Returns:\n            str: the audio text\n        \"\"\"\n\n        logger.info(\"asr websocket client start\")\n        handler = ASRWsAudioHandler(\n            server_ip,\n            port,\n            punc_server_ip=punc_server_ip,\n            punc_server_port=punc_server_port)\n        loop = asyncio.get_event_loop()\n        res = loop.run_until_complete(handler.run(input))\n        logger.info(\"asr websocket client finished\")\n\n        return res['result']\n\n\n@cli_client_register(\n    name='paddlespeech_client.cls', description='visit cls service')\nclass CLSClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(CLSClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.cls', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Audio file to classify.',\n            required=True)\n        self.parser.add_argument(\n            '--topk',\n            type=int,\n            default=1,\n            help='Return topk scores of classification result.')\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        topk = args.topk\n\n        try:\n            time_start = time.time()\n            res = self(input=input_, server_ip=server_ip, port=port, topk=topk)\n            time_end = time.time()\n            logger.info(res.json())\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to speech classification.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8090,\n                 topk: int=1):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        url = 'http://' + server_ip + \":\" + str(port) + '/paddlespeech/cls'\n        audio = wav2base64(input)\n        data = {\"audio\": audio, \"topk\": topk}\n        res = requests.post(url=url, data=json.dumps(data))\n        return res\n\n\n@cli_client_register(\n    name='paddlespeech_client.text', description='visit the text service')\nclass TextClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(TextClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.text', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='sentence to be process by text server.',\n            required=True)\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"Execute the request from the argv.\n\n        Args:\n            argv (List): the request arguments\n\n        Returns:\n            str: the request flag\n        \"\"\"\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n\n        try:\n            time_start = time.time()\n            res = self(input=input_, server_ip=server_ip, port=port)\n            time_end = time.time()\n            logger.info(f\"The punc text: {res}\")\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to Text punctuation.\")\n            return False\n\n    @stats_wrapper\n    def __call__(self, input: str, server_ip: str=\"127.0.0.1\", port: int=8090):\n        \"\"\"\n        Python API to call text executor.\n\n        Args:\n            input (str): the request sentence text\n            server_ip (str, optional): the server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the server port. Defaults to 8090.\n\n        Returns:\n            str: the punctuation text\n        \"\"\"\n\n        url = 'http://' + server_ip + \":\" + str(port) + '/paddlespeech/text'\n        request = {\n            \"text\": input,\n        }\n\n        res = requests.post(url=url, data=json.dumps(request))\n        response_dict = res.json()\n        punc_text = response_dict[\"result\"][\"punc_text\"]\n        return punc_text\n\n\n@cli_client_register(\n    name='paddlespeech_client.vector', description='visit the vector service')\nclass VectorClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(VectorClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.vector', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='sentence to be process by text server.')\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default=\"spk\",\n            choices=[\"spk\", \"score\"],\n            help=\"The vector service task\")\n        self.parser.add_argument(\n            \"--enroll\", type=str, default=None, help=\"The enroll audio\")\n        self.parser.add_argument(\n            \"--test\", type=str, default=None, help=\"The test audio\")\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"Execute the request from the argv.\n\n        Args:\n            argv (List): the request arguments\n\n        Returns:\n            str: the request flag\n        \"\"\"\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        task = args.task\n\n        try:\n            time_start = time.time()\n            res = self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                enroll_audio=args.enroll,\n                test_audio=args.test,\n                task=task)\n            time_end = time.time()\n            logger.info(res.json())\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to extract vector.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(self,\n                 input: str,\n                 server_ip: str=\"127.0.0.1\",\n                 port: int=8090,\n                 audio_format: str=\"wav\",\n                 sample_rate: int=16000,\n                 enroll_audio: str=None,\n                 test_audio: str=None,\n                 task=\"spk\"):\n        \"\"\"\n        Python API to call text executor.\n\n        Args:\n            input (str): the request audio data\n            server_ip (str, optional): the server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the server port. Defaults to 8090.\n            audio_format (str, optional): audio format. Defaults to \"wav\".\n            sample_rate (str, optional): audio sample rate. Defaults to 16000.\n            enroll_audio (str, optional): enroll audio data. Defaults to None.\n            test_audio (str, optional): test audio data. Defaults to None.\n            task (str, optional): the task type, \"spk\" or \"socre\". Defaults to \"spk\"\n        Returns:\n            str: the audio embedding or score between enroll and test audio\n        \"\"\"\n\n        if task == \"spk\":\n            from paddlespeech.server.utils.audio_handler import VectorHttpHandler\n            logger.info(\"vector http client start\")\n            logger.info(f\"the input audio: {input}\")\n            handler = VectorHttpHandler(server_ip=server_ip, port=port)\n            res = handler.run(input, audio_format, sample_rate)\n            return res\n        elif task == \"score\":\n            from paddlespeech.server.utils.audio_handler import VectorScoreHttpHandler\n            logger.info(\"vector score http client start\")\n            logger.info(\n                f\"enroll audio: {enroll_audio}, test audio: {test_audio}\")\n            handler = VectorScoreHttpHandler(server_ip=server_ip, port=port)\n            res = handler.run(enroll_audio, test_audio, audio_format,\n                              sample_rate)\n            return res\n        else:\n            logger.error(f\"Sorry, we have not support such task {task}\")\n\n\n@cli_client_register(\n    name='paddlespeech_client.acs', description='visit acs service')\nclass ACSClientExecutor(BaseExecutor):\n    def __init__(self):\n        super(ACSClientExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_client.acs', add_help=True)\n        self.parser.add_argument(\n            '--server_ip', type=str, default='127.0.0.1', help='server ip')\n        self.parser.add_argument(\n            '--port', type=int, default=8090, help='server port')\n        self.parser.add_argument(\n            '--input',\n            type=str,\n            default=None,\n            help='Audio file to be recognized',\n            required=True)\n        self.parser.add_argument(\n            '--sample_rate', type=int, default=16000, help='audio sample rate')\n        self.parser.add_argument(\n            '--lang', type=str, default=\"zh_cn\", help='language')\n        self.parser.add_argument(\n            '--audio_format', type=str, default=\"wav\", help='audio format')\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        input_ = args.input\n        server_ip = args.server_ip\n        port = args.port\n        sample_rate = args.sample_rate\n        lang = args.lang\n        audio_format = args.audio_format\n\n        try:\n            time_start = time.time()\n            res = self(\n                input=input_,\n                server_ip=server_ip,\n                port=port,\n                sample_rate=sample_rate,\n                lang=lang,\n                audio_format=audio_format, )\n            time_end = time.time()\n            logger.info(f\"ACS result: {res}\")\n            logger.info(\"Response time %f s.\" % (time_end - time_start))\n            return True\n        except Exception as e:\n            logger.error(\"Failed to speech recognition.\")\n            logger.error(e)\n            return False\n\n    @stats_wrapper\n    def __call__(\n            self,\n            input: str,\n            server_ip: str=\"127.0.0.1\",\n            port: int=8090,\n            sample_rate: int=16000,\n            lang: str=\"zh_cn\",\n            audio_format: str=\"wav\", ):\n        \"\"\"Python API to call an executor.\n\n        Args:\n            input (str): The input audio file path\n            server_ip (str, optional): The ASR server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): The ASR server port. Defaults to 8090.\n            sample_rate (int, optional): The audio sample rate. Defaults to 16000.\n            lang (str, optional): The audio language type. Defaults to \"zh_cn\".\n            audio_format (str, optional): The audio format information. Defaults to \"wav\".\n\n        Returns:\n            str: The ACS results\n        \"\"\"\n        # we use the acs server to get the key word time stamp in audio text content\n        logger.info(\"acs http client start\")\n        from paddlespeech.server.utils.audio_handler import ASRHttpHandler\n        handler = ASRHttpHandler(\n            server_ip=server_ip, port=port, endpoint=\"/paddlespeech/asr/search\")\n        res = handler.run(input, audio_format, sample_rate, lang)\n        res = res['result']\n        logger.info(\"acs http client finished\")\n\n        return res\n"
  },
  {
    "path": "paddlespeech/server/bin/paddlespeech_server.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport sys\nimport warnings\nfrom typing import List\n\nimport numpy\nimport uvicorn\nfrom fastapi import FastAPI\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.server.engine.engine_pool import init_engine_pool\nfrom paddlespeech.server.engine.engine_warmup import warm_up\nfrom paddlespeech.server.restful.api import setup_router as setup_http_router\nfrom paddlespeech.server.utils.config import get_config\nfrom paddlespeech.server.ws.api import setup_router as setup_ws_router\nfrom prettytable import PrettyTable\nfrom starlette.middleware.cors import CORSMiddleware\n\nfrom ..executor import BaseExecutor\nfrom ..util import cli_server_register\nfrom ..util import stats_wrapper\nwarnings.filterwarnings(\"ignore\")\n\n__all__ = ['ServerExecutor', 'ServerStatsExecutor']\n\napp = FastAPI(\n    title=\"PaddleSpeech Serving API\", description=\"Api\", version=\"0.0.1\")\n\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"])\n\n\n@cli_server_register(\n    name='paddlespeech_server.start', description='Start the service')\nclass ServerExecutor(BaseExecutor):\n    def __init__(self):\n        super(ServerExecutor, self).__init__()\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_server.start', add_help=True)\n        self.parser.add_argument(\n            \"--config_file\",\n            action=\"store\",\n            help=\"yaml file of the app\",\n            default=None,\n            required=True)\n\n        self.parser.add_argument(\n            \"--log_file\",\n            action=\"store\",\n            help=\"log file\",\n            default=\"./log/paddlespeech.log\")\n\n    def init(self, config) -> bool:\n        \"\"\"system initialization\n\n        Args:\n            config (CfgNode): config object\n\n        Returns:\n            bool: \n        \"\"\"\n        # init api\n        api_list = list(engine.split(\"_\")[0] for engine in config.engine_list)\n        if config.protocol == \"websocket\":\n            api_router = setup_ws_router(api_list)\n        elif config.protocol == \"http\":\n            api_router = setup_http_router(api_list)\n        else:\n            raise Exception(\"unsupported protocol\")\n        app.include_router(api_router)\n        logger.info(\"start to init the engine\")\n        if not init_engine_pool(config):\n            return False\n\n        # warm up\n        for engine_and_type in config.engine_list:\n            if not warm_up(engine_and_type):\n                return False\n\n        return True\n\n    def execute(self, argv: List[str]) -> bool:\n        args = self.parser.parse_args(argv)\n        try:\n            self(args.config_file, args.log_file)\n        except Exception as e:\n            logger.error(\"Failed to start server.\")\n            logger.error(e)\n            sys.exit(-1)\n\n    @stats_wrapper\n    def __call__(self,\n                 config_file: str=\"./conf/application.yaml\",\n                 log_file: str=\"./log/paddlespeech.log\"):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        config = get_config(config_file)\n        if self.init(config):\n            uvicorn.run(app, host=config.host, port=config.port)\n\n\n@cli_server_register(\n    name='paddlespeech_server.stats',\n    description='Get the models supported by each speech task in the service.')\nclass ServerStatsExecutor():\n    def __init__(self):\n        super(ServerStatsExecutor, self).__init__()\n\n        self.parser = argparse.ArgumentParser(\n            prog='paddlespeech_server.stats', add_help=True)\n        self.parser.add_argument(\n            '--task',\n            type=str,\n            default=None,\n            choices=['asr', 'tts', 'cls', 'text', 'vector'],\n            help='Choose speech task.',\n            required=True)\n        self.task_choices = ['asr', 'tts', 'cls', 'text', 'vector']\n        self.model_name_format = {\n            'asr': 'Model-Size-Code Switch-Multilingual-Language-Sample Rate',\n            'tts': 'Model-Language',\n            'cls': 'Model-Sample Rate',\n            'text': 'Model-Task-Language',\n            'vector': 'Model-Sample Rate'\n        }\n\n    def show_support_models(self, pretrained_models: dict):\n        fields = self.model_name_format[self.task].split(\"-\")\n        table = PrettyTable(fields)\n        for key in pretrained_models:\n            line = key.split(\"-\")\n            if self.task == \"asr\" and len(line) < len(fields):\n                for i in range(len(line), len(fields)):\n                    line.append(\"-\")\n                if \"codeswitch\" in key:\n                    line[3], line[1] = line[1].split(\"_\")[0], line[1].split(\n                        \"_\")[1:]\n                elif \"multilingual\" in key:\n                    line[4], line[1] = line[1].split(\"_\")[0], line[1].split(\n                        \"_\")[1:]\n                tmp = numpy.array(line)\n                idx = [0, 5, 3, 4, 1, 2]\n                line = tmp[idx]\n            table.add_row(line)\n        print(table)\n\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n            Command line entry.\n        \"\"\"\n        parser_args = self.parser.parse_args(argv)\n        self.task = parser_args.task\n        if self.task not in self.task_choices:\n            logger.error(\n                \"Please input correct speech task, choices = ['asr', 'tts']\")\n            return False\n\n        try:\n            # Dynamic models\n            dynamic_pretrained_models = CommonTaskResource(\n                task=self.task, model_format='dynamic').pretrained_models\n\n            if len(dynamic_pretrained_models) > 0:\n                logger.info(\n                    \"Here is the table of {} pretrained models supported in the service.\".\n                    format(self.task.upper()))\n                self.show_support_models(dynamic_pretrained_models)\n\n            # Static models\n            static_pretrained_models = CommonTaskResource(\n                task=self.task, model_format='static').pretrained_models\n            if len(static_pretrained_models) > 0:\n                logger.info(\n                    \"Here is the table of {} static pretrained models supported in the service.\".\n                    format(self.task.upper()))\n                self.show_support_models(static_pretrained_models)\n\n            return True\n\n        except BaseException:\n            logger.error(\n                \"Failed to get the table of {} pretrained models supported in the service.\".\n                format(self.task.upper()))\n            return False\n"
  },
  {
    "path": "paddlespeech/server/conf/application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Offline Serving..\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_python', 'asr_inference', 'tts_python', 'tts_inference', 'cls_python', 'cls_inference']\nprotocol: 'http'\nengine_list: ['asr_python', 'tts_python', 'cls_python', 'text_python', 'vector_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: python #######################\nasr_python:\n    model: 'conformer_wenetspeech'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    decode_method: 'attention_rescoring'\n    num_decoding_left_chunks: -1\n    force_yes: True\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: asr; engine_type: inference #######################\nasr_inference:\n    # model_type choices=['deepspeech2offline_aishell']\n    model_type: 'deepspeech2offline_aishell'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    num_decoding_left_chunks: -1\n    decode_method: \n    force_yes: True\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: python #######################\ntts_python: \n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc', \n    #                              'fastspeech2_ljspeech', 'fastspeech2_aishell3',\n    #                              'fastspeech2_vctk']        \n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'pwgan_ljspeech', 'pwgan_aishell3',\n    #                        'pwgan_vctk', 'mb_melgan_csmsc']\n    voc: 'pwgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: tts; engine_type: inference #######################\ntts_inference:\n    # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc']\n    am: 'fastspeech2_csmsc'   \n    am_model: # the pdmodel file of your am static model (XX.pdmodel)\n    am_params: # the pdiparams file of your am static model (XX.pdipparams)\n    am_sample_rate: 24000\n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # voc (vocoder) choices=['pwgan_csmsc', 'mb_melgan_csmsc','hifigan_csmsc']\n    voc: 'pwgan_csmsc'\n    voc_model: # the pdmodel file of your vocoder static model (XX.pdmodel)\n    voc_params: # the pdiparams file of your vocoder static model (XX.pdipparams)\n    voc_sample_rate: 24000\n\n    voc_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'  \n        switch_ir_optim: True  \n        glog_info: False # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    # others\n    lang: 'zh'\n\n\n################################### CLS #########################################\n################### speech task: cls; engine_type: python #######################\ncls_python:\n    # model choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model: 'panns_cnn14'\n    cfg_path: # [optional] Config of cls task.\n    ckpt_path: # [optional] Checkpoint file of model.\n    label_file: # [optional] Label file of cls task.\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################### speech task: cls; engine_type: inference #######################\ncls_inference:\n    # model_type choices=['panns_cnn14', 'panns_cnn10', 'panns_cnn6']\n    model_type: 'panns_cnn14' \n    cfg_path: \n    model_path:  # the pdmodel file of am static model [optional]\n    params_path:  # the pdiparams file of am static model [optional]\n    label_file:  # [optional] Label file of cls task.\n\n    predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n\n################################### Text #########################################\n################### text task: punc; engine_type: python #######################\ntext_python:\n    task: punc\n    model_type: 'ernie_linear_p3_wudao'\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    vocab_file: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n\n\n################################### Vector ######################################\n################### Vector task: spk; engine_type: python #######################\nvector_python:\n    task: spk\n    model_type: 'ecapatdnn_voxceleb12'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    device:  # set 'gpu:id' or 'cpu'\n"
  },
  {
    "path": "paddlespeech/server/conf/tts_online_application.yaml",
    "content": "# This is the parameter configuration file for streaming tts server.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8092\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# engine_list choices = ['tts_online', 'tts_online-onnx'], the inference speed of tts_online-onnx is faster than tts_online.\n# protocol choices = ['websocket', 'http'] \nprotocol: 'http'\nengine_list: ['tts_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online #######################\ntts_online: \n    # am (acoustic model) choices=['fastspeech2_csmsc', 'fastspeech2_cnndecoder_csmsc']   \n    # fastspeech2_cnndecoder_csmsc support streaming am infer.     \n    am: 'fastspeech2_csmsc'   \n    am_config: \n    am_ckpt: \n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n\n    # voc (vocoder) choices=['mb_melgan_csmsc, hifigan_csmsc']\n    # Both mb_melgan_csmsc and hifigan_csmsc support streaming voc inference\n    voc: 'mb_melgan_csmsc'\n    voc_config: \n    voc_ckpt: \n    voc_stat: \n\n    # others\n    lang: 'zh'\n    device: 'cpu' # set 'gpu:id' or 'cpu'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    \n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### TTS #########################################\n################### speech task: tts; engine_type: online-onnx #######################\ntts_online-onnx: \n    # am (acoustic model) choices=['fastspeech2_csmsc_onnx', 'fastspeech2_cnndecoder_csmsc_onnx']\n    # fastspeech2_cnndecoder_csmsc_onnx support streaming am infer.        \n    am: 'fastspeech2_cnndecoder_csmsc_onnx' \n    # am_ckpt is a list, if am is fastspeech2_cnndecoder_csmsc_onnx, am_ckpt = [encoder model, decoder model, postnet model];\n    # if am is fastspeech2_csmsc_onnx, am_ckpt = [ckpt model];\n    am_ckpt:   # list\n    am_stat: \n    phones_dict: \n    tones_dict: \n    speaker_dict: \n    spk_id: 0\n    am_sample_rate: 24000\n    am_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # voc (vocoder) choices=['mb_melgan_csmsc_onnx, hifigan_csmsc_onnx']\n    # Both mb_melgan_csmsc_onnx and hifigan_csmsc_onnx support streaming voc inference\n    voc: 'hifigan_csmsc_onnx'\n    voc_ckpt: \n    voc_sample_rate: 24000\n    voc_sess_conf:\n        device: \"cpu\" # set 'gpu:id' or 'cpu'\n        use_trt: False\n        cpu_threads: 4\n\n    # others\n    lang: 'zh'\n    # am_block and am_pad only for fastspeech2_cnndecoder_onnx model to streaming am infer,\n    # when am_pad set 12, streaming synthetic audio is the same as non-streaming synthetic audio\n    am_block: 72\n    am_pad: 12\n    # voc_pad and voc_block voc model to streaming voc infer,\n    # when voc model is mb_melgan_csmsc_onnx, voc_pad set 14, streaming synthetic audio is the same as non-streaming synthetic audio; The minimum value of pad can be set to 7, streaming synthetic audio sounds normal\n    # when voc model is hifigan_csmsc_onnx, voc_pad set 19, streaming synthetic audio is the same as non-streaming synthetic audio; voc_pad set 14, streaming synthetic audio sounds normal\n    voc_block: 36\n    voc_pad: 14\n    # voc_upsample should be same as n_shift on voc config.\n    voc_upsample: 300\n    \n"
  },
  {
    "path": "paddlespeech/server/conf/vector_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# protocol = ['http'] (only one can be selected). \n# http only support offline engine type.\nprotocol: 'http'\nengine_list: ['vector_python']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### Vector ######################################\n################### Vector task: spk; engine_type: python #######################\nvector_python:\n    task: spk\n    model_type: 'ecapatdnn_voxceleb12'\n    sample_rate: 16000\n    cfg_path: # [optional]\n    ckpt_path: # [optional]\n    device: # set 'gpu:id' or 'cpu'\n\n\n\n\n"
  },
  {
    "path": "paddlespeech/server/conf/ws_conformer_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online', 'tts_online']\n# protocol = ['websocket', 'http'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_multicn'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: -1\n    force_yes: True\n    device: cpu # cpu or gpu:id\n    continuous_decoding: True # enable continue decoding when endpoint detected\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "paddlespeech/server/conf/ws_conformer_wenetspeech_application_faster.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online #######################\nasr_online:\n    model_type: 'conformer_online_wenetspeech'\n    am_model: # the pdmodel file of am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n    decode_method: \"attention_rescoring\"\n    continuous_decoding: True # enable continue decoding when endpoint detected\n    num_decoding_left_chunks: 16\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n        sample_rate: 16000\n        sample_width: 2\n"
  },
  {
    "path": "paddlespeech/server/conf/ws_ds2_application.yaml",
    "content": "# This is the parameter configuration file for PaddleSpeech Serving.\n\n#################################################################################\n#                             SERVER SETTING                                    #\n#################################################################################\nhost: 0.0.0.0\nport: 8090\n\n# The task format in the engin_list is: <speech task>_<engine type>\n# task choices = ['asr_online-inference', 'asr_online-onnx']\n# protocol = ['websocket'] (only one can be selected).\n# websocket only support online engine type.\nprotocol: 'websocket'\nengine_list: ['asr_online-onnx']\n\n\n#################################################################################\n#                                ENGINE CONFIG                                  #\n#################################################################################\n\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online-onnx #######################\nasr_online-onnx:\n    model_type: 'deepspeech2online_wenetspeech'\n    am_model:  # the pdmodel file of onnx am static model [optional]\n    am_params:  # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n\n    # https://onnxruntime.ai/docs/api/python/api_summary.html#inferencesession\n    am_predictor_conf:\n        device: 'cpu' # set 'gpu:id' or 'cpu'\n        graph_optimization_level: 0 \n        intra_op_num_threads: 0 # Sets the number of threads used to parallelize the execution within nodes.\n        inter_op_num_threads: 0 # Sets the number of threads used to parallelize the execution of the graph (across nodes).\n        log_severity_level: 2   # Log severity level. Applies to session load, initialization, etc. 0:Verbose, 1:Info, 2:Warning. 3:Error, 4:Fatal. Default is 2.\n        log_verbosity_level: 0  # VLOG level if DEBUG build and session_log_severity_level is 0. Applies to session load, initialization, etc. Default is 0.\n\n    chunk_buffer_conf:\n        frame_duration_ms: 85\n        shift_ms: 40\n        sample_rate: 16000\n        sample_width: 2\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms\n\n\n################################### ASR #########################################\n################### speech task: asr; engine_type: online-inference #######################\nasr_online-inference:\n    model_type: 'deepspeech2online_wenetspeech'\n    am_model:    # the pdmodel file of am static model [optional]\n    am_params:   # the pdiparams file of am static model [optional]\n    lang: 'zh'\n    sample_rate: 16000\n    cfg_path: \n    decode_method: \n    num_decoding_left_chunks: \n    force_yes: True\n    device: 'cpu' # cpu or gpu:id\n\n    am_predictor_conf:\n        device:  # set 'gpu:id' or 'cpu'\n        switch_ir_optim: True\n        glog_info: False  # True -> print glog\n        summary: True  # False -> do not show predictor config\n\n    chunk_buffer_conf:\n        frame_duration_ms: 85\n        shift_ms: 40\n        sample_rate: 16000\n        sample_width: 2\n        window_n: 7     # frame\n        shift_n: 4      # frame\n        window_ms: 25   # ms\n        shift_ms: 10    # ms"
  },
  {
    "path": "paddlespeech/server/engine/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/acs/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/acs/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/acs/python/acs_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nimport json\nimport os\nimport re\n\nimport numpy as np\nimport paddle\nimport soundfile\nimport websocket\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.base_engine import BaseEngine\n\n\nclass ACSEngine(BaseEngine):\n    def __init__(self):\n        \"\"\"The ACSEngine Engine\n        \"\"\"\n        super(ACSEngine, self).__init__()\n        logger.debug(\"Create the ACSEngine Instance\")\n        self.word_list = []\n\n    def init(self, config: dict):\n        \"\"\"Init the ACSEngine Engine\n\n        Args:\n            config (dict): The server configuation\n\n        Returns:\n            bool: The engine instance flag\n        \"\"\"\n        logger.debug(\"Init the acs engine\")\n        try:\n            self.config = config\n            self.device = self.config.get(\"device\", paddle.get_device())\n\n            # websocket default ping timeout is 20 seconds\n            self.ping_timeout = self.config.get(\"ping_timeout\", 20)\n            paddle.set_device(self.device)\n            logger.debug(f\"ACS Engine set the device: {self.device}\")\n\n        except BaseException as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize Text server engine Failed on device: %s.\" %\n                         (self.device))\n            return False\n\n        self.read_search_words()\n\n        # init the asr url\n        self.url = \"ws://\" + self.config.asr_server_ip + \":\" + str(\n            self.config.asr_server_port) + \"/paddlespeech/asr/streaming\"\n\n        logger.info(\"Initialize acs server engine successfully on device: %s.\" %\n                    (self.device))\n\n        return True\n\n    def read_search_words(self):\n        word_list = self.config.word_list\n        if word_list is None:\n            logger.error(\n                \"No word list file in config, please set the word list parameter\"\n            )\n            return\n\n        if not os.path.exists(word_list):\n            logger.error(\"Please input correct word list file\")\n            return\n\n        with open(word_list, 'r') as fp:\n            self.word_list = [line.strip() for line in fp.readlines()]\n\n        logger.info(f\"word list: {self.word_list}\")\n\n    def get_asr_content(self, audio_data):\n        \"\"\"Get the streaming asr result\n\n        Args:\n            audio_data (_type_): _description_\n\n        Returns:\n            _type_: _description_\n        \"\"\"\n        logger.debug(\"send a message to the server\")\n        if self.url is None:\n            logger.error(\"No asr server, please input valid ip and port\")\n            return \"\"\n        ws = websocket.WebSocket()\n        logger.debug(f\"set the ping timeout: {self.ping_timeout} seconds\")\n        ws.connect(self.url, ping_timeout=self.ping_timeout)\n        audio_info = json.dumps(\n            {\n                \"name\": \"test.wav\",\n                \"signal\": \"start\",\n                \"nbest\": 1\n            },\n            sort_keys=True,\n            indent=4,\n            separators=(',', ': '))\n        ws.send(audio_info)\n        msg = ws.recv()\n        logger.info(\"client receive msg={}\".format(msg))\n\n        # send the total audio data\n        for chunk_data in self.read_wave(audio_data):\n            ws.send_binary(chunk_data.tobytes())\n            msg = ws.recv()\n            msg = json.loads(msg)\n            logger.info(f\"audio result: {msg}\")\n\n        # 3. send chunk audio data to engine\n        logger.debug(\"send the end signal\")\n        audio_info = json.dumps(\n            {\n                \"name\": \"test.wav\",\n                \"signal\": \"end\",\n                \"nbest\": 1\n            },\n            sort_keys=True,\n            indent=4,\n            separators=(',', ': '))\n        ws.send(audio_info)\n        msg = ws.recv()\n        msg = json.loads(msg)\n\n        logger.info(f\"the final result: {msg}\")\n        ws.close()\n\n        return msg\n\n    def read_wave(self, audio_data: str):\n        \"\"\"read the audio file from specific wavfile path\n\n        Args:\n            audio_data (str): the audio data, \n                                 we assume that audio sample rate matches the model\n\n        Yields:\n            numpy.array: the samall package audio pcm data\n        \"\"\"\n        samples, sample_rate = soundfile.read(audio_data, dtype='int16')\n        x_len = len(samples)\n        assert sample_rate == 16000\n\n        chunk_size = int(85 * sample_rate / 1000)  # 85ms, sample_rate = 16kHz\n\n        if x_len % chunk_size != 0:\n            padding_len_x = chunk_size - x_len % chunk_size\n        else:\n            padding_len_x = 0\n\n        padding = np.zeros((padding_len_x), dtype=samples.dtype)\n        padded_x = np.concatenate([samples, padding], axis=0)\n\n        assert (x_len + padding_len_x) % chunk_size == 0\n        num_chunk = (x_len + padding_len_x) / chunk_size\n        num_chunk = int(num_chunk)\n        for i in range(0, num_chunk):\n            start = i * chunk_size\n            end = start + chunk_size\n            x_chunk = padded_x[start:end]\n            yield x_chunk\n\n    def get_macthed_word(self, msg):\n        \"\"\"Get the matched info in msg\n\n        Args:\n            msg (dict): the asr info, including the asr result and time stamp\n\n        Returns:\n            acs_result, asr_result: the acs result and the asr result\n        \"\"\"\n        asr_result = msg['result']\n        time_stamp = msg['times']\n        acs_result = []\n\n        # search for each word in self.word_list\n        offset = self.config.offset\n        # last time in time_stamp\n        max_ed = time_stamp[-1]['ed']\n        for w in self.word_list:\n            # search the w in asr_result and the index in asr_result\n            # https://docs.python.org/3/library/re.html#re.finditer\n            for m in re.finditer(w, asr_result):\n                # match start and end char index in timestamp\n                # https://docs.python.org/3/library/re.html#re.Match.start\n                start = max(time_stamp[m.start(0)]['bg'] - offset, 0)\n                end = min(time_stamp[m.end(0) - 1]['ed'] + offset, max_ed)\n                logger.debug(f'start: {start}, end: {end}')\n                acs_result.append({'w': w, 'bg': start, 'ed': end})\n\n        return acs_result, asr_result\n\n    def run(self, audio_data):\n        \"\"\"process the audio data in acs engine\n           the engine does not store any data, so all the request use the self.run api\n\n        Args:\n            audio_data (str): the audio data\n\n        Returns:\n            acs_result, asr_result: the acs result and the asr result\n        \"\"\"\n        logger.debug(\"start to process the audio content search\")\n        msg = self.get_asr_content(io.BytesIO(audio_data))\n\n        acs_result, asr_result = self.get_macthed_word(msg)\n        logger.info(f'the asr result {asr_result}')\n        logger.info(f'the acs result: {acs_result}')\n        return acs_result, asr_result\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/ctc_endpoint.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom dataclasses import dataclass\nfrom dataclasses import field\n\nimport numpy as np\n\nfrom paddlespeech.cli.log import logger\n\n\n@dataclass\nclass OnlineCTCEndpointRule:\n    must_contain_nonsilence: bool = True\n    min_trailing_silence: int = 1000\n    min_utterance_length: int = 0\n\n\n@dataclass\nclass OnlineCTCEndpoingOpt:\n    frame_shift_in_ms: int = 10\n\n    blank: int = 0  # blank id, that we consider as silence for purposes of endpointing.\n    blank_threshold: float = 0.8  # above blank threshold is silence\n\n    # We support three rules.  We terminate decoding if ANY of these rules\n    # evaluates to \"true\". If you want to add more rules, do it by changing this\n    # code.  If you want to disable a rule, you can set the silence-timeout for\n    # that rule to a very large number.\n\n    # rule1 times out after 5 seconds of silence, even if we decoded nothing.\n    rule1: OnlineCTCEndpointRule = field(\n        default_factory=lambda: OnlineCTCEndpointRule(False, 5000, 0))\n    # rule2 times out after 1.0 seconds of silence after decoding something,\n    # even if we did not reach a final-state at all.\n    rule2: OnlineCTCEndpointRule = field(\n        default_factory=lambda: OnlineCTCEndpointRule(True, 1000, 0))\n    # rule3 times out after the utterance is 20 seconds long, regardless of\n    # anything else.\n    rule3: OnlineCTCEndpointRule = field(\n        default_factory=lambda: OnlineCTCEndpointRule(False, 0, 20000))\n\n\nclass OnlineCTCEndpoint:\n    \"\"\"\n    [END-TO-END AUTOMATIC SPEECH RECOGNITION INTEGRATED WITH CTC-BASED VOICE ACTIVITY DETECTION](https://arxiv.org/pdf/2002.00551.pdf)\n    \"\"\"\n\n    def __init__(self, opts: OnlineCTCEndpoingOpt):\n        self.opts = opts\n        logger.info(f\"Endpont Opts: {opts}\")\n        self.frame_shift_in_ms = opts.frame_shift_in_ms\n\n        self.num_frames_decoded = 0\n        self.trailing_silence_frames = 0\n\n        self.reset()\n\n    def reset(self):\n        self.num_frames_decoded = 0\n        self.trailing_silence_frames = 0\n\n    def rule_activated(self,\n                       rule: OnlineCTCEndpointRule,\n                       rule_name: str,\n                       decoding_something: bool,\n                       trailine_silence: int,\n                       utterance_length: int) -> bool:\n        ans = (\n            decoding_something or (not rule.must_contain_nonsilence)\n        ) and trailine_silence >= rule.min_trailing_silence and utterance_length >= rule.min_utterance_length\n        if (ans):\n            logger.info(f\"Endpoint Rule: {rule_name} activated: {rule}\")\n        return ans\n\n    def endpoint_detected(self,\n                          ctc_log_probs: np.ndarray,\n                          decoding_something: bool) -> bool:\n        \"\"\"detect endpoint.\n\n        Args:\n            ctc_log_probs (np.ndarray): (T, D)\n            decoding_something (bool): contain nonsilince.\n\n        Returns:\n            bool: whether endpoint detected.\n        \"\"\"\n        for logprob in ctc_log_probs:\n            blank_prob = np.exp(logprob[self.opts.blank])\n\n            self.num_frames_decoded += 1\n            if blank_prob > self.opts.blank_threshold:\n                self.trailing_silence_frames += 1\n            else:\n                self.trailing_silence_frames = 0\n\n        assert self.num_frames_decoded >= self.trailing_silence_frames\n        assert self.frame_shift_in_ms > 0\n\n        decoding_something = (\n            self.num_frames_decoded > self.trailing_silence_frames\n        ) and decoding_something\n        utterance_length = self.num_frames_decoded * self.frame_shift_in_ms\n        trailing_silence = self.trailing_silence_frames * self.frame_shift_in_ms\n\n        if self.rule_activated(self.opts.rule1, 'rule1', decoding_something,\n                               trailing_silence, utterance_length):\n            return True\n        if self.rule_activated(self.opts.rule2, 'rule2', decoding_something,\n                               trailing_silence, utterance_length):\n            return True\n        if self.rule_activated(self.opts.rule3, 'rule3', decoding_something,\n                               trailing_silence, utterance_length):\n            return True\n        return False\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/ctc_search.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport copy\nfrom collections import defaultdict\n\nimport paddle\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.s2t.utils.utility import log_add\n\n__all__ = ['CTCPrefixBeamSearch']\n\n\nclass CTCPrefixBeamSearch:\n    def __init__(self, config):\n        \"\"\"Implement the ctc prefix beam search\n\n        Args:\n            config (yacs.config.CfgNode): the ctc prefix beam search configuration\n        \"\"\"\n        self.config = config\n\n        # beam size\n        self.first_beam_size = self.config.beam_size\n        # TODO(support second beam size)\n        self.second_beam_size = int(self.first_beam_size * 1.0)\n        logger.info(\n            f\"first and second beam size: {self.first_beam_size}, {self.second_beam_size}\"\n        )\n\n        # state\n        self.cur_hyps = None\n        self.hyps = None\n        self.abs_time_step = 0\n\n        self.reset()\n\n    def reset(self):\n        \"\"\"Rest the search cache value\n        \"\"\"\n        self.cur_hyps = None\n        self.hyps = None\n        self.abs_time_step = 0\n\n    @paddle.no_grad()\n    def search(self, ctc_probs, device, blank_id=0):\n        \"\"\"ctc prefix beam search method decode a chunk feature\n\n        Args:\n            xs (paddle.Tensor): feature data\n            ctc_probs (paddle.Tensor): the ctc probability of all the tokens\n            device (paddle.fluid.core_avx.Place): the feature host device, such as CUDAPlace(0).\n            blank_id (int, optional): the blank id in the vocab. Defaults to 0.\n\n        Returns:\n            list: the search result\n        \"\"\"\n        # decode \n        logger.info(\"start to ctc prefix search\")\n        assert len(ctc_probs.shape) == 2\n        batch_size = 1\n\n        vocab_size = ctc_probs.shape[1]\n        first_beam_size = min(self.first_beam_size, vocab_size)\n        second_beam_size = min(self.second_beam_size, vocab_size)\n        logger.info(\n            f\"effect first and second beam size: {self.first_beam_size}, {self.second_beam_size}\"\n        )\n\n        maxlen = ctc_probs.shape[0]\n\n        # cur_hyps: (prefix, (blank_ending_score, none_blank_ending_score))\n        # 0. blank_ending_score,\n        # 1. none_blank_ending_score, \n        # 2. viterbi_blank ending score, \n        # 3. viterbi_non_blank score, \n        # 4. current_token_prob, \n        # 5. times_viterbi_blank, times_b\n        # 6. times_titerbi_non_blank, times_nb\n        if self.cur_hyps is None:\n            self.cur_hyps = [(tuple(), (0.0, -float('inf'), 0.0, 0.0,\n                                        -float('inf'), [], []))]\n            # self.cur_hyps = [(tuple(), (0.0, -float('inf')))]\n        # 2. CTC beam search step by step\n        for t in range(0, maxlen):\n            logp = ctc_probs[t]  # (vocab_size,)\n            # next_hyps = defaultdict(lambda: (-float('inf'), -float('inf')))\n            next_hyps = defaultdict(\n                        lambda: (-float('inf'), -float('inf'), -float('inf'), -float('inf'), -float('inf'), [], []))\n\n            # 2.1 First beam prune: select topk best\n            #     do token passing process\n            top_k_logp, top_k_index = logp.topk(\n                first_beam_size)  # (first_beam_size,)\n            for s in top_k_index:\n                s = s.item()\n                ps = logp[s].item()\n                for prefix, (pb, pnb, v_b_s, v_nb_s, cur_token_prob, times_b,\n                             times_nb) in self.cur_hyps:\n                    last = prefix[-1] if len(prefix) > 0 else None\n                    if s == blank_id:  # blank\n                        n_pb, n_pnb, n_v_b, n_v_nb, n_cur_token_prob, n_times_b, n_times_nb = next_hyps[\n                            prefix]\n                        n_pb = log_add([n_pb, pb + ps, pnb + ps])\n\n                        pre_times = times_b if v_b_s > v_nb_s else times_nb\n                        n_times_b = copy.deepcopy(pre_times)\n                        viterbi_score = v_b_s if v_b_s > v_nb_s else v_nb_s\n                        n_v_b = viterbi_score + ps\n                        next_hyps[prefix] = (n_pb, n_pnb, n_v_b, n_v_nb,\n                                             n_cur_token_prob, n_times_b,\n                                             n_times_nb)\n                    elif s == last:\n                        #  Update *ss -> *s;\n                        # case1: *a + a => *a\n                        n_pb, n_pnb, n_v_b, n_v_nb, n_cur_token_prob, n_times_b, n_times_nb = next_hyps[\n                            prefix]\n                        n_pnb = log_add([n_pnb, pnb + ps])\n                        if n_v_nb < v_nb_s + ps:\n                            n_v_nb = v_nb_s + ps\n                            if n_cur_token_prob < ps:\n                                n_cur_token_prob = ps\n                                n_times_nb = copy.deepcopy(times_nb)\n                                n_times_nb[\n                                    -1] = self.abs_time_step  # 注意，这里要重新使用绝对时间\n                        next_hyps[prefix] = (n_pb, n_pnb, n_v_b, n_v_nb,\n                                             n_cur_token_prob, n_times_b,\n                                             n_times_nb)\n\n                        # Update *s-s -> *ss, - is for blank\n                        # Case 2: *aε + a => *aa\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb, n_v_b, n_v_nb, n_cur_token_prob, n_times_b, n_times_nb = next_hyps[\n                            n_prefix]\n                        if n_v_nb < v_b_s + ps:\n                            n_v_nb = v_b_s + ps\n                            n_cur_token_prob = ps\n                            n_times_nb = copy.deepcopy(times_b)\n                            n_times_nb.append(self.abs_time_step)\n                        n_pnb = log_add([n_pnb, pb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb, n_v_b, n_v_nb,\n                                               n_cur_token_prob, n_times_b,\n                                               n_times_nb)\n                    else:\n                        # Case 3: *a + b => *ab, *aε + b => *ab\n                        n_prefix = prefix + (s, )\n                        n_pb, n_pnb, n_v_b, n_v_nb, n_cur_token_prob, n_times_b, n_times_nb = next_hyps[\n                            n_prefix]\n                        viterbi_score = v_b_s if v_b_s > v_nb_s else v_nb_s\n                        pre_times = times_b if v_b_s > v_nb_s else times_nb\n                        if n_v_nb < viterbi_score + ps:\n                            n_v_nb = viterbi_score + ps\n                            n_cur_token_prob = ps\n                            n_times_nb = copy.deepcopy(pre_times)\n                            n_times_nb.append(self.abs_time_step)\n\n                        n_pnb = log_add([n_pnb, pb + ps, pnb + ps])\n                        next_hyps[n_prefix] = (n_pb, n_pnb, n_v_b, n_v_nb,\n                                               n_cur_token_prob, n_times_b,\n                                               n_times_nb)\n\n            # 2.2 Second beam prune\n            next_hyps = sorted(\n                next_hyps.items(),\n                key=lambda x: log_add([x[1][0], x[1][1]]),\n                reverse=True)\n            self.cur_hyps = next_hyps[:second_beam_size]\n\n            # 2.3 update the absolute time step\n            self.abs_time_step += 1\n\n        self.hyps = [(y[0], log_add([y[1][0], y[1][1]]), y[1][2], y[1][3],\n                      y[1][4], y[1][5], y[1][6]) for y in self.cur_hyps]\n\n        logger.info(\"ctc prefix search success\")\n        return self.hyps\n\n    def get_one_best_hyps(self):\n        \"\"\"Return the one best result\n\n        Returns:\n            list: the one best result, List[str]\n        \"\"\"\n        return [self.hyps[0][0]]\n\n    def get_hyps(self):\n        \"\"\"Return the search hyps\n\n        Returns:\n            list: return the search hyps, List[Tuple[str, float, ...]]\n        \"\"\"\n        return self.hyps\n\n    def finalize_search(self):\n        \"\"\"do nothing in ctc_prefix_beam_search\n        \"\"\"\n        pass\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/onnx/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/onnx/asr_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\nfrom typing import ByteString\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nfrom numpy import float32\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.cli.asr.infer import ASRExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.modules.ctc import CTCDecoder\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils import onnx_infer\nfrom paddlespeech.utils.env import MODEL_HOME\n\n__all__ = ['PaddleASRConnectionHanddler', 'ASRServerExecutor', 'ASREngine']\n\n\n# ASR server connection process class\nclass PaddleASRConnectionHanddler:\n    def __init__(self, asr_engine):\n        \"\"\"Init a Paddle ASR Connection Handler instance\n\n        Args:\n            asr_engine (ASREngine): the global asr engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"create an paddle asr connection handler to process the websocket connection\"\n        )\n        self.config = asr_engine.config  # server config\n        self.model_config = asr_engine.executor.config\n        self.asr_engine = asr_engine\n\n        # model_type, sample_rate and text_feature is shared for deepspeech2 and conformer\n        self.model_type = self.asr_engine.executor.model_type\n        self.sample_rate = self.asr_engine.executor.sample_rate\n        # tokens to text\n        self.text_feature = self.asr_engine.executor.text_feature\n\n        # extract feat, new only fbank in conformer model\n        self.preprocess_conf = self.model_config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n\n        # frame window and frame shift, in samples unit\n        self.win_length = self.preprocess_conf.process[0]['win_length']\n        self.n_shift = self.preprocess_conf.process[0]['n_shift']\n\n        assert self.preprocess_conf.process[0]['fs'] == self.sample_rate, (\n            self.sample_rate, self.preprocess_conf.process[0]['fs'])\n        self.frame_shift_in_ms = int(\n            self.n_shift / self.preprocess_conf.process[0]['fs'] * 1000)\n\n        self.continuous_decoding = self.config.get(\"continuous_decoding\", False)\n        self.init_decoder()\n        self.reset()\n\n    def init_decoder(self):\n        if \"deepspeech2\" in self.model_type:\n            assert self.continuous_decoding is False, \"ds2 model not support endpoint\"\n            self.am_predictor = self.asr_engine.executor.am_predictor\n\n            self.decoder = CTCDecoder(\n                odim=self.model_config.output_dim,  # <blank> is in  vocab\n                enc_n_units=self.model_config.rnn_layer_size * 2,\n                blank_id=self.model_config.blank_id,\n                dropout_rate=0.0,\n                reduction=True,  # sum\n                batch_average=True,  # sum / batch_size\n                grad_norm_type=self.model_config.get('ctc_grad_norm_type',\n                                                     None))\n\n            cfg = self.model_config.decode\n            decode_batch_size = 1  # for online\n            self.decoder.init_decoder(\n                decode_batch_size, self.text_feature.vocab_list,\n                cfg.decoding_method, cfg.lang_model_path, cfg.alpha, cfg.beta,\n                cfg.beam_size, cfg.cutoff_prob, cfg.cutoff_top_n,\n                cfg.num_proc_bsearch)\n        else:\n            raise ValueError(f\"Not supported: {self.model_type}\")\n\n    def model_reset(self):\n        # cache for audio and feat\n        self.remained_wav = None\n        self.cached_feat = None\n\n    def output_reset(self):\n        ## outputs\n        # partial/ending decoding results\n        self.result_transcripts = ['']\n\n    def reset_continuous_decoding(self):\n        \"\"\"\n        when in continous decoding, reset for next utterance.\n        \"\"\"\n        self.global_frame_offset = self.num_frames\n        self.model_reset()\n\n    def reset(self):\n        if \"deepspeech2\" in self.model_type:\n            # for deepspeech2\n            # init state\n            self.chunk_state_h_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.chunk_state_c_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.decoder.reset_decoder(batch_size=1)\n        else:\n            raise NotImplementedError(f\"{self.model_type} not support.\")\n\n        self.device = None\n\n        ## common\n        # global sample and frame step\n        self.num_samples = 0\n        self.global_frame_offset = 0\n        # frame step of cur utterance\n        self.num_frames = 0\n\n        ## endpoint\n        self.endpoint_state = False  # True for detect endpoint\n\n        ## conformer\n        self.model_reset()\n\n        ## outputs\n        self.output_reset()\n\n    def extract_feat(self, samples: ByteString):\n        logger.debug(\"Online ASR extract the feat\")\n        samples = np.frombuffer(samples, dtype=np.int16)\n        assert samples.ndim == 1\n\n        self.num_samples += samples.shape[0]\n        logger.debug(\n            f\"This package receive {samples.shape[0]} pcm data. Global samples:{self.num_samples}\"\n        )\n\n        # self.reamined_wav stores all the samples,\n        # include the original remained_wav and this package samples\n        if self.remained_wav is None:\n            self.remained_wav = samples\n        else:\n            assert self.remained_wav.ndim == 1  # (T,)\n            self.remained_wav = np.concatenate([self.remained_wav, samples])\n        logger.debug(\n            f\"The concatenation of remain and now audio samples length is: {self.remained_wav.shape}\"\n        )\n\n        if len(self.remained_wav) < self.win_length:\n            # samples not enough for feature window\n            return 0\n\n        # fbank\n        x_chunk = self.preprocessing(self.remained_wav, **self.preprocess_args)\n        x_chunk = paddle.to_tensor(x_chunk, dtype=\"float32\").unsqueeze(axis=0)\n\n        # feature cache\n        if self.cached_feat is None:\n            self.cached_feat = x_chunk\n        else:\n            assert (len(x_chunk.shape) == 3)  # (B,T,D)\n            assert (len(self.cached_feat.shape) == 3)  # (B,T,D)\n            self.cached_feat = paddle.concat(\n                [self.cached_feat, x_chunk], axis=1)\n\n        # set the feat device\n        if self.device is None:\n            self.device = self.cached_feat.place\n\n        # cur frame step\n        num_frames = x_chunk.shape[1]\n\n        # global frame step\n        self.num_frames += num_frames\n\n        # update remained wav\n        self.remained_wav = self.remained_wav[self.n_shift * num_frames:]\n\n        logger.debug(\n            f\"process the audio feature success, the cached feat shape: {self.cached_feat.shape}\"\n        )\n        logger.debug(\n            f\"After extract feat, the cached remain the audio samples: {self.remained_wav.shape}\"\n        )\n        logger.debug(f\"global samples: {self.num_samples}\")\n        logger.debug(f\"global frames: {self.num_frames}\")\n\n    def decode(self, is_finished=False):\n        \"\"\"advance decoding\n\n        Args:\n            is_finished (bool, optional): Is last frame or not. Defaults to False.\n\n        Returns:\n            None: \n        \"\"\"\n        if \"deepspeech2\" in self.model_type:\n            decoding_chunk_size = 1  # decoding chunk size = 1. int decoding frame unit\n\n            context = 7  # context=7, in audio frame unit\n            subsampling = 4  # subsampling=4, in audio frame unit\n\n            cached_feature_num = context - subsampling\n            # decoding window for model, in audio frame unit\n            decoding_window = (decoding_chunk_size - 1) * subsampling + context\n            # decoding stride for model, in audio frame unit\n            stride = subsampling * decoding_chunk_size\n\n            if self.cached_feat is None:\n                logger.info(\"no audio feat, please input more pcm data\")\n                return\n\n            num_frames = self.cached_feat.shape[1]\n            logger.debug(\n                f\"Required decoding window {decoding_window} frames, and the connection has {num_frames} frames\"\n            )\n\n            # the cached feat must be larger decoding_window\n            if num_frames < decoding_window and not is_finished:\n                logger.info(\n                    f\"frame feat num is less than {decoding_window}, please input more pcm data\"\n                )\n                return None, None\n\n            # if is_finished=True, we need at least context frames\n            if num_frames < context:\n                logger.info(\n                    \"flast {num_frames} is less than context {context} frames, and we cannot do model forward\"\n                )\n                return None, None\n\n            logger.info(\"start to do model forward\")\n            # num_frames - context + 1 ensure that current frame can get context window\n            if is_finished:\n                # if get the finished chunk, we need process the last context\n                left_frames = context\n            else:\n                # we only process decoding_window frames for one chunk\n                left_frames = decoding_window\n\n            end = None\n            for cur in range(0, num_frames - left_frames + 1, stride):\n                end = min(cur + decoding_window, num_frames)\n\n                # extract the audio\n                x_chunk = self.cached_feat[:, cur:end, :].numpy()\n                x_chunk_lens = np.array([x_chunk.shape[1]])\n\n                trans_best = self.decode_one_chunk(x_chunk, x_chunk_lens)\n\n            self.result_transcripts = [trans_best]\n\n            # update feat cache\n            self.cached_feat = self.cached_feat[:, end - cached_feature_num:, :]\n\n            # return trans_best[0]\n        else:\n            raise Exception(f\"{self.model_type} not support paddleinference.\")\n\n    @paddle.no_grad()\n    def decode_one_chunk(self, x_chunk, x_chunk_lens):\n        \"\"\"forward one chunk frames\n\n        Args:\n            x_chunk (np.ndarray): (B,T,D), audio frames.\n            x_chunk_lens ([type]): (B,), audio frame lens\n\n        Returns:\n            logprob: poster probability.\n        \"\"\"\n        logger.info(\"start to decoce one chunk for deepspeech2\")\n        # state_c, state_h, audio_lens, audio\n        # 'chunk_state_c_box', 'chunk_state_h_box', 'audio_chunk_lens', 'audio_chunk'\n        input_names = [n.name for n in self.am_predictor.get_inputs()]\n        logger.info(f\"ort inputs: {input_names}\")\n        # 'softmax_0.tmp_0', 'tmp_5', 'concat_0.tmp_0', 'concat_1.tmp_0'\n        # audio, audio_lens, state_h, state_c\n        output_names = [n.name for n in self.am_predictor.get_outputs()]\n        logger.info(f\"ort outpus: {output_names}\")\n        assert (len(input_names) == len(output_names))\n        assert isinstance(input_names[0], str)\n\n        input_datas = [\n            self.chunk_state_c_box, self.chunk_state_h_box, x_chunk_lens,\n            x_chunk\n        ]\n        feeds = dict(zip(input_names, input_datas))\n\n        outputs = self.am_predictor.run([*output_names], {**feeds})\n\n        output_chunk_probs, output_chunk_lens, self.chunk_state_h_box, self.chunk_state_c_box = outputs\n        self.decoder.next(output_chunk_probs, output_chunk_lens)\n        trans_best, trans_beam = self.decoder.decode()\n        logger.info(f\"decode one best result for deepspeech2: {trans_best[0]}\")\n        return trans_best[0]\n\n    def get_result(self):\n        \"\"\"return partial/ending asr result.\n\n        Returns:\n            str: one best result of partial/ending.\n        \"\"\"\n        if len(self.result_transcripts) > 0:\n            return self.result_transcripts[0]\n        else:\n            return ''\n\n    def get_word_time_stamp(self):\n        return []\n\n    @paddle.no_grad()\n    def rescoring(self):\n        ...\n\n\nclass ASRServerExecutor(ASRExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='asr', model_format='onnx', inference_mode='online')\n\n    def update_config(self) -> None:\n        if \"deepspeech2\" in self.model_type:\n            with UpdateConfig(self.config):\n                # download lm\n                self.config.decode.lang_model_path = os.path.join(\n                    MODEL_HOME, 'language_model',\n                    self.config.decode.lang_model_path)\n\n            lm_url = self.task_resource.res_dict['lm_url']\n            lm_md5 = self.task_resource.res_dict['lm_md5']\n            logger.debug(f\"Start to load language model {lm_url}\")\n            self.download_lm(\n                lm_url,\n                os.path.dirname(self.config.decode.lang_model_path), lm_md5)\n        else:\n            raise NotImplementedError(\n                f\"{self.model_type} not support paddleinference.\")\n\n    def init_model(self) -> None:\n\n        if \"deepspeech2\" in self.model_type:\n            # AM predictor\n            logger.debug(\"ASR engine start to init the am predictor\")\n            self.am_predictor = onnx_infer.get_sess(\n                model_path=self.am_model, sess_conf=self.am_predictor_conf)\n        else:\n            raise NotImplementedError(\n                f\"{self.model_type} not support paddleinference.\")\n\n    def _init_from_path(self,\n                        model_type: str=None,\n                        am_model: Optional[os.PathLike]=None,\n                        am_params: Optional[os.PathLike]=None,\n                        lang: str='zh',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='attention_rescoring',\n                        num_decoding_left_chunks: int=-1,\n                        am_predictor_conf: dict=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if not model_type or not lang or not sample_rate:\n            logger.error(\n                \"The model type or lang or sample rate is None, please input an valid server parameter yaml\"\n            )\n            return False\n        assert am_params is None, \"am_params not used in onnx engine\"\n\n        self.model_type = model_type\n        self.sample_rate = sample_rate\n        self.decode_method = decode_method\n        self.num_decoding_left_chunks = num_decoding_left_chunks\n        # conf for paddleinference predictor or onnx\n        self.am_predictor_conf = am_predictor_conf\n        logger.debug(f\"model_type: {self.model_type}\")\n\n        sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n        tag = model_type + '-' + lang + '-' + sample_rate_str\n        self.task_resource.set_task_model(model_tag=tag)\n\n        if cfg_path is None:\n            self.res_path = self.task_resource.res_dir\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        self.am_model = os.path.join(self.res_path, self.task_resource.res_dict[\n            'onnx_model']) if am_model is None else os.path.abspath(am_model)\n\n        # self.am_params = os.path.join(\n        #     self.res_path, self.task_resource.res_dict[\n        #         'params']) if am_params is None else os.path.abspath(am_params)\n\n        logger.debug(\"Load the pretrained model:\")\n        logger.debug(f\"  tag = {tag}\")\n        logger.debug(f\"  res_path: {self.res_path}\")\n        logger.debug(f\"  cfg path: {self.cfg_path}\")\n        logger.debug(f\"  am_model path: {self.am_model}\")\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        if self.config.spm_model_prefix:\n            self.config.spm_model_prefix = os.path.join(\n                self.res_path, self.config.spm_model_prefix)\n            logger.debug(f\"spm model path: {self.config.spm_model_prefix}\")\n\n        self.vocab = self.config.vocab_filepath\n\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n\n        self.update_config()\n\n        # AM predictor\n        self.init_model()\n\n        logger.debug(f\"create the {model_type} model success\")\n        return True\n\n\nclass ASREngine(BaseEngine):\n    \"\"\"ASR model resource\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(ASREngine, self).__init__()\n\n    def init_model(self) -> bool:\n        if not self.executor._init_from_path(\n                model_type=self.config.model_type,\n                am_model=self.config.am_model,\n                am_params=self.config.am_params,\n                lang=self.config.lang,\n                sample_rate=self.config.sample_rate,\n                cfg_path=self.config.cfg_path,\n                decode_method=self.config.decode_method,\n                num_decoding_left_chunks=self.config.num_decoding_left_chunks,\n                am_predictor_conf=self.config.am_predictor_conf):\n            return False\n        return True\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.config = config\n        self.executor = ASRServerExecutor()\n\n        try:\n            self.device = self.config.get(\"device\", paddle.get_device())\n            paddle.set_device(self.device)\n        except BaseException as e:\n            logger.error(\n                f\"Set device failed, please check if device '{self.device}' is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\n                \"If all GPU or XPU is used, you can set the server to 'cpu'\")\n            sys.exit(-1)\n\n        logger.debug(f\"paddlespeech_server set the device: {self.device}\")\n\n        if not self.init_model():\n            logger.error(\n                \"Init the ASR server occurs error, please check the server configuration yaml\"\n            )\n            return False\n\n        logger.info(\"Initialize ASR server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n    def new_handler(self):\n        \"\"\"New handler from model.\n\n        Returns:\n            PaddleASRConnectionHanddler: asr handler instance\n        \"\"\"\n        return PaddleASRConnectionHanddler(self)\n\n    def preprocess(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def run(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def postprocess(self):\n        raise NotImplementedError(\"Online not using this.\")\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/paddleinference/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/paddleinference/asr_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\nfrom typing import ByteString\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nfrom numpy import float32\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.cli.asr.infer import ASRExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.modules.ctc import CTCDecoder\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.paddle_predictor import init_predictor\nfrom paddlespeech.utils.env import MODEL_HOME\n\n__all__ = ['PaddleASRConnectionHanddler', 'ASRServerExecutor', 'ASREngine']\n\n\n# ASR server connection process class\nclass PaddleASRConnectionHanddler:\n    def __init__(self, asr_engine):\n        \"\"\"Init a Paddle ASR Connection Handler instance\n\n        Args:\n            asr_engine (ASREngine): the global asr engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"create an paddle asr connection handler to process the websocket connection\"\n        )\n        self.config = asr_engine.config  # server config\n        self.model_config = asr_engine.executor.config\n        self.asr_engine = asr_engine\n\n        # model_type, sample_rate and text_feature is shared for deepspeech2 and conformer\n        self.model_type = self.asr_engine.executor.model_type\n        self.sample_rate = self.asr_engine.executor.sample_rate\n        # tokens to text\n        self.text_feature = self.asr_engine.executor.text_feature\n\n        # extract feat, new only fbank in conformer model\n        self.preprocess_conf = self.model_config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n\n        # frame window and frame shift, in samples unit\n        self.win_length = self.preprocess_conf.process[0]['win_length']\n        self.n_shift = self.preprocess_conf.process[0]['n_shift']\n\n        assert self.preprocess_conf.process[0]['fs'] == self.sample_rate, (\n            self.sample_rate, self.preprocess_conf.process[0]['fs'])\n        self.frame_shift_in_ms = int(\n            self.n_shift / self.preprocess_conf.process[0]['fs'] * 1000)\n\n        self.continuous_decoding = self.config.get(\"continuous_decoding\", False)\n        self.init_decoder()\n        self.reset()\n\n    def init_decoder(self):\n        if \"deepspeech2\" in self.model_type:\n            assert self.continuous_decoding is False, \"ds2 model not support endpoint\"\n            self.am_predictor = self.asr_engine.executor.am_predictor\n\n            self.decoder = CTCDecoder(\n                odim=self.model_config.output_dim,  # <blank> is in  vocab\n                enc_n_units=self.model_config.rnn_layer_size * 2,\n                blank_id=self.model_config.blank_id,\n                dropout_rate=0.0,\n                reduction=True,  # sum\n                batch_average=True,  # sum / batch_size\n                grad_norm_type=self.model_config.get('ctc_grad_norm_type',\n                                                     None))\n\n            cfg = self.model_config.decode\n            decode_batch_size = 1  # for online\n            self.decoder.init_decoder(\n                decode_batch_size, self.text_feature.vocab_list,\n                cfg.decoding_method, cfg.lang_model_path, cfg.alpha, cfg.beta,\n                cfg.beam_size, cfg.cutoff_prob, cfg.cutoff_top_n,\n                cfg.num_proc_bsearch)\n        else:\n            raise ValueError(f\"Not supported: {self.model_type}\")\n\n    def model_reset(self):\n        # cache for audio and feat\n        self.remained_wav = None\n        self.cached_feat = None\n\n    def output_reset(self):\n        ## outputs\n        # partial/ending decoding results\n        self.result_transcripts = ['']\n\n    def reset_continuous_decoding(self):\n        \"\"\"\n        when in continous decoding, reset for next utterance.\n        \"\"\"\n        self.global_frame_offset = self.num_frames\n        self.model_reset()\n\n    def reset(self):\n        if \"deepspeech2\" in self.model_type:\n            # for deepspeech2\n            # init state\n            self.chunk_state_h_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.chunk_state_c_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.decoder.reset_decoder(batch_size=1)\n        else:\n            raise NotImplementedError(f\"{self.model_type} not support.\")\n\n        self.device = None\n\n        ## common\n        # global sample and frame step\n        self.num_samples = 0\n        self.global_frame_offset = 0\n        # frame step of cur utterance\n        self.num_frames = 0\n\n        ## endpoint\n        self.endpoint_state = False  # True for detect endpoint\n\n        ## conformer\n        self.model_reset()\n\n        ## outputs\n        self.output_reset()\n\n    def extract_feat(self, samples: ByteString):\n        logger.info(\"Online ASR extract the feat\")\n        samples = np.frombuffer(samples, dtype=np.int16)\n        assert samples.ndim == 1\n\n        self.num_samples += samples.shape[0]\n        logger.debug(\n            f\"This package receive {samples.shape[0]} pcm data. Global samples:{self.num_samples}\"\n        )\n\n        # self.reamined_wav stores all the samples,\n        # include the original remained_wav and this package samples\n        if self.remained_wav is None:\n            self.remained_wav = samples\n        else:\n            assert self.remained_wav.ndim == 1  # (T,)\n            self.remained_wav = np.concatenate([self.remained_wav, samples])\n        logger.debug(\n            f\"The concatenation of remain and now audio samples length is: {self.remained_wav.shape}\"\n        )\n\n        if len(self.remained_wav) < self.win_length:\n            # samples not enough for feature window\n            return 0\n\n        # fbank\n        x_chunk = self.preprocessing(self.remained_wav, **self.preprocess_args)\n        x_chunk = paddle.to_tensor(x_chunk, dtype=\"float32\").unsqueeze(axis=0)\n\n        # feature cache\n        if self.cached_feat is None:\n            self.cached_feat = x_chunk\n        else:\n            assert (len(x_chunk.shape) == 3)  # (B,T,D)\n            assert (len(self.cached_feat.shape) == 3)  # (B,T,D)\n            self.cached_feat = paddle.concat(\n                [self.cached_feat, x_chunk], axis=1)\n\n        # set the feat device\n        if self.device is None:\n            self.device = self.cached_feat.place\n\n        # cur frame step\n        num_frames = x_chunk.shape[1]\n\n        # global frame step\n        self.num_frames += num_frames\n\n        # update remained wav\n        self.remained_wav = self.remained_wav[self.n_shift * num_frames:]\n\n        logger.debug(\n            f\"process the audio feature success, the cached feat shape: {self.cached_feat.shape}\"\n        )\n        logger.debug(\n            f\"After extract feat, the cached remain the audio samples: {self.remained_wav.shape}\"\n        )\n        logger.debug(f\"global samples: {self.num_samples}\")\n        logger.debug(f\"global frames: {self.num_frames}\")\n\n    def decode(self, is_finished=False):\n        \"\"\"advance decoding\n\n        Args:\n            is_finished (bool, optional): Is last frame or not. Defaults to False.\n\n        Returns:\n            None: \n        \"\"\"\n        if \"deepspeech2\" in self.model_type:\n            decoding_chunk_size = 1  # decoding chunk size = 1. int decoding frame unit\n\n            context = 7  # context=7, in audio frame unit\n            subsampling = 4  # subsampling=4, in audio frame unit\n\n            cached_feature_num = context - subsampling\n            # decoding window for model, in audio frame unit\n            decoding_window = (decoding_chunk_size - 1) * subsampling + context\n            # decoding stride for model, in audio frame unit\n            stride = subsampling * decoding_chunk_size\n\n            if self.cached_feat is None:\n                logger.info(\"no audio feat, please input more pcm data\")\n                return\n\n            num_frames = self.cached_feat.shape[1]\n            logger.debug(\n                f\"Required decoding window {decoding_window} frames, and the connection has {num_frames} frames\"\n            )\n\n            # the cached feat must be larger decoding_window\n            if num_frames < decoding_window and not is_finished:\n                logger.debug(\n                    f\"frame feat num is less than {decoding_window}, please input more pcm data\"\n                )\n                return None, None\n\n            # if is_finished=True, we need at least context frames\n            if num_frames < context:\n                logger.info(\n                    \"flast {num_frames} is less than context {context} frames, and we cannot do model forward\"\n                )\n                return None, None\n\n            logger.info(\"start to do model forward\")\n            # num_frames - context + 1 ensure that current frame can get context window\n            if is_finished:\n                # if get the finished chunk, we need process the last context\n                left_frames = context\n            else:\n                # we only process decoding_window frames for one chunk\n                left_frames = decoding_window\n\n            end = None\n            for cur in range(0, num_frames - left_frames + 1, stride):\n                end = min(cur + decoding_window, num_frames)\n\n                # extract the audio\n                x_chunk = self.cached_feat[:, cur:end, :].numpy()\n                x_chunk_lens = np.array([x_chunk.shape[1]])\n\n                trans_best = self.decode_one_chunk(x_chunk, x_chunk_lens)\n\n            self.result_transcripts = [trans_best]\n\n            # update feat cache\n            self.cached_feat = self.cached_feat[:, end - cached_feature_num:, :]\n\n            # return trans_best[0]\n        else:\n            raise Exception(f\"{self.model_type} not support paddleinference.\")\n\n    @paddle.no_grad()\n    def decode_one_chunk(self, x_chunk, x_chunk_lens):\n        \"\"\"forward one chunk frames\n\n        Args:\n            x_chunk (np.ndarray): (B,T,D), audio frames.\n            x_chunk_lens ([type]): (B,), audio frame lens\n\n        Returns:\n            logprob: poster probability.\n        \"\"\"\n        logger.debug(\"start to decoce one chunk for deepspeech2\")\n        input_names = self.am_predictor.get_input_names()\n        audio_handle = self.am_predictor.get_input_handle(input_names[0])\n        audio_len_handle = self.am_predictor.get_input_handle(input_names[1])\n        h_box_handle = self.am_predictor.get_input_handle(input_names[2])\n        c_box_handle = self.am_predictor.get_input_handle(input_names[3])\n\n        audio_handle.reshape(x_chunk.shape)\n        audio_handle.copy_from_cpu(x_chunk)\n\n        audio_len_handle.reshape(x_chunk_lens.shape)\n        audio_len_handle.copy_from_cpu(x_chunk_lens)\n\n        h_box_handle.reshape(self.chunk_state_h_box.shape)\n        h_box_handle.copy_from_cpu(self.chunk_state_h_box)\n\n        c_box_handle.reshape(self.chunk_state_c_box.shape)\n        c_box_handle.copy_from_cpu(self.chunk_state_c_box)\n\n        output_names = self.am_predictor.get_output_names()\n        output_handle = self.am_predictor.get_output_handle(output_names[0])\n        output_lens_handle = self.am_predictor.get_output_handle(\n            output_names[1])\n        output_state_h_handle = self.am_predictor.get_output_handle(\n            output_names[2])\n        output_state_c_handle = self.am_predictor.get_output_handle(\n            output_names[3])\n\n        self.am_predictor.run()\n\n        output_chunk_probs = output_handle.copy_to_cpu()\n        output_chunk_lens = output_lens_handle.copy_to_cpu()\n        self.chunk_state_h_box = output_state_h_handle.copy_to_cpu()\n        self.chunk_state_c_box = output_state_c_handle.copy_to_cpu()\n\n        self.decoder.next(output_chunk_probs, output_chunk_lens)\n        trans_best, trans_beam = self.decoder.decode()\n        logger.info(f\"decode one best result for deepspeech2: {trans_best[0]}\")\n        return trans_best[0]\n\n    def get_result(self):\n        \"\"\"return partial/ending asr result.\n\n        Returns:\n            str: one best result of partial/ending.\n        \"\"\"\n        if len(self.result_transcripts) > 0:\n            return self.result_transcripts[0]\n        else:\n            return ''\n\n    def get_word_time_stamp(self):\n        return []\n\n    @paddle.no_grad()\n    def rescoring(self):\n        ...\n\n\nclass ASRServerExecutor(ASRExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='asr', model_format='static', inference_mode='online')\n\n    def update_config(self) -> None:\n        if \"deepspeech2\" in self.model_type:\n            with UpdateConfig(self.config):\n                # download lm\n                self.config.decode.lang_model_path = os.path.join(\n                    MODEL_HOME, 'language_model',\n                    self.config.decode.lang_model_path)\n\n            lm_url = self.task_resource.res_dict['lm_url']\n            lm_md5 = self.task_resource.res_dict['lm_md5']\n            logger.debug(f\"Start to load language model {lm_url}\")\n            self.download_lm(\n                lm_url,\n                os.path.dirname(self.config.decode.lang_model_path), lm_md5)\n        else:\n            raise NotImplementedError(\n                f\"{self.model_type} not support paddleinference.\")\n\n    def init_model(self) -> None:\n\n        if \"deepspeech2\" in self.model_type:\n            # AM predictor\n            logger.debug(\"ASR engine start to init the am predictor\")\n            self.am_predictor = init_predictor(\n                model_file=self.am_model,\n                params_file=self.am_params,\n                predictor_conf=self.am_predictor_conf)\n        else:\n            raise NotImplementedError(\n                f\"{self.model_type} not support paddleinference.\")\n\n    def _init_from_path(self,\n                        model_type: str=None,\n                        am_model: Optional[os.PathLike]=None,\n                        am_params: Optional[os.PathLike]=None,\n                        lang: str='zh',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='attention_rescoring',\n                        num_decoding_left_chunks: int=-1,\n                        am_predictor_conf: dict=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if not model_type or not lang or not sample_rate:\n            logger.error(\n                \"The model type or lang or sample rate is None, please input an valid server parameter yaml\"\n            )\n            return False\n\n        self.model_type = model_type\n        self.sample_rate = sample_rate\n        self.decode_method = decode_method\n        self.num_decoding_left_chunks = num_decoding_left_chunks\n        # conf for paddleinference predictor or onnx\n        self.am_predictor_conf = am_predictor_conf\n        logger.debug(f\"model_type: {self.model_type}\")\n\n        sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n        tag = model_type + '-' + lang + '-' + sample_rate_str\n        self.task_resource.set_task_model(model_tag=tag)\n\n        if cfg_path is None or am_model is None or am_params is None:\n            self.res_path = self.task_resource.res_dir\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n\n            self.am_model = os.path.join(self.res_path,\n                                         self.task_resource.res_dict['model'])\n            self.am_params = os.path.join(self.res_path,\n                                          self.task_resource.res_dict['params'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.am_model = os.path.abspath(am_model)\n            self.am_params = os.path.abspath(am_params)\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        logger.debug(\"Load the pretrained model:\")\n        logger.debug(f\"  tag = {tag}\")\n        logger.debug(f\"  res_path: {self.res_path}\")\n        logger.debug(f\"  cfg path: {self.cfg_path}\")\n        logger.debug(f\"  am_model path: {self.am_model}\")\n        logger.debug(f\"  am_params path: {self.am_params}\")\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        if self.config.spm_model_prefix:\n            self.config.spm_model_prefix = os.path.join(\n                self.res_path, self.config.spm_model_prefix)\n            logger.debug(f\"spm model path: {self.config.spm_model_prefix}\")\n\n        self.vocab = self.config.vocab_filepath\n\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n\n        self.update_config()\n\n        # AM predictor\n        self.init_model()\n\n        logger.debug(f\"create the {model_type} model success\")\n        return True\n\n\nclass ASREngine(BaseEngine):\n    \"\"\"ASR model resource\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(ASREngine, self).__init__()\n\n    def init_model(self) -> bool:\n        if not self.executor._init_from_path(\n                model_type=self.config.model_type,\n                am_model=self.config.am_model,\n                am_params=self.config.am_params,\n                lang=self.config.lang,\n                sample_rate=self.config.sample_rate,\n                cfg_path=self.config.cfg_path,\n                decode_method=self.config.decode_method,\n                num_decoding_left_chunks=self.config.num_decoding_left_chunks,\n                am_predictor_conf=self.config.am_predictor_conf):\n            return False\n        return True\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.config = config\n        self.executor = ASRServerExecutor()\n\n        try:\n            self.device = self.config.get(\"device\", paddle.get_device())\n            paddle.set_device(self.device)\n        except BaseException as e:\n            logger.error(\n                f\"Set device failed, please check if device '{self.device}' is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\n                \"If all GPU or XPU is used, you can set the server to 'cpu'\")\n            sys.exit(-1)\n\n        logger.debug(f\"paddlespeech_server set the device: {self.device}\")\n\n        if not self.init_model():\n            logger.error(\n                \"Init the ASR server occurs error, please check the server configuration yaml\"\n            )\n            return False\n\n        logger.info(\"Initialize ASR server engine successfully on device: %s.\" %\n                    (self.device))\n\n        return True\n\n    def new_handler(self):\n        \"\"\"New handler from model.\n\n        Returns:\n            PaddleASRConnectionHanddler: asr handler instance\n        \"\"\"\n        return PaddleASRConnectionHanddler(self)\n\n    def preprocess(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def run(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def postprocess(self):\n        raise NotImplementedError(\"Online not using this.\")\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/online/python/asr_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport sys\nfrom typing import ByteString\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nfrom numpy import float32\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.transform.transformation import Transformation\nfrom paddlespeech.cli.asr.infer import ASRExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.modules.ctc import CTCDecoder\nfrom paddlespeech.s2t.utils.tensor_utils import add_sos_eos\nfrom paddlespeech.s2t.utils.tensor_utils import pad_sequence\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nfrom paddlespeech.server.engine.asr.online.ctc_endpoint import OnlineCTCEndpoingOpt\nfrom paddlespeech.server.engine.asr.online.ctc_endpoint import OnlineCTCEndpoint\nfrom paddlespeech.server.engine.asr.online.ctc_search import CTCPrefixBeamSearch\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.paddle_predictor import init_predictor\nfrom paddlespeech.utils.env import MODEL_HOME\n\n__all__ = ['PaddleASRConnectionHanddler', 'ASRServerExecutor', 'ASREngine']\n\n\n# ASR server connection process class\nclass PaddleASRConnectionHanddler:\n    def __init__(self, asr_engine):\n        \"\"\"Init a Paddle ASR Connection Handler instance\n\n        Args:\n            asr_engine (ASREngine): the global asr engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"create an paddle asr connection handler to process the websocket connection\"\n        )\n        self.config = asr_engine.config  # server config\n        self.model_config = asr_engine.executor.config\n        self.asr_engine = asr_engine\n\n        # model_type, sample_rate and text_feature is shared for deepspeech2 and conformer\n        self.model_type = self.asr_engine.executor.model_type\n        self.sample_rate = self.asr_engine.executor.sample_rate\n        # tokens to text\n        self.text_feature = self.asr_engine.executor.text_feature\n\n        # extract feat, new only fbank in conformer model\n        self.preprocess_conf = self.model_config.preprocess_config\n        self.preprocess_args = {\"train\": False}\n        self.preprocessing = Transformation(self.preprocess_conf)\n\n        # frame window and frame shift, in samples unit\n        self.win_length = self.preprocess_conf.process[0]['win_length']\n        self.n_shift = self.preprocess_conf.process[0]['n_shift']\n\n        assert self.preprocess_conf.process[0]['fs'] == self.sample_rate, (\n            self.sample_rate, self.preprocess_conf.process[0]['fs'])\n        self.frame_shift_in_ms = int(\n            self.n_shift / self.preprocess_conf.process[0]['fs'] * 1000)\n\n        self.continuous_decoding = self.config.get(\"continuous_decoding\", False)\n        self.init_decoder()\n        self.reset()\n\n    def init_decoder(self):\n        if \"deepspeech2\" in self.model_type:\n            assert self.continuous_decoding is False, \"ds2 model not support endpoint\"\n            self.am_predictor = self.asr_engine.executor.am_predictor\n\n            self.decoder = CTCDecoder(\n                odim=self.model_config.output_dim,  # <blank> is in  vocab\n                enc_n_units=self.model_config.rnn_layer_size * 2,\n                blank_id=self.model_config.blank_id,\n                dropout_rate=0.0,\n                reduction=True,  # sum\n                batch_average=True,  # sum / batch_size\n                grad_norm_type=self.model_config.get('ctc_grad_norm_type',\n                                                     None))\n\n            cfg = self.model_config.decode\n            decode_batch_size = 1  # for online\n            self.decoder.init_decoder(\n                decode_batch_size, self.text_feature.vocab_list,\n                cfg.decoding_method, cfg.lang_model_path, cfg.alpha, cfg.beta,\n                cfg.beam_size, cfg.cutoff_prob, cfg.cutoff_top_n,\n                cfg.num_proc_bsearch)\n\n        elif \"conformer\" in self.model_type or \"transformer\" in self.model_type:\n            # acoustic model\n            self.model = self.asr_engine.executor.model\n            self.continuous_decoding = self.config.continuous_decoding\n            logger.debug(f\"continue decoding: {self.continuous_decoding}\")\n\n            # ctc decoding config\n            self.ctc_decode_config = self.asr_engine.executor.config.decode\n            self.searcher = CTCPrefixBeamSearch(self.ctc_decode_config)\n\n            # ctc endpoint\n            self.endpoint_opt = OnlineCTCEndpoingOpt(\n                frame_shift_in_ms=self.frame_shift_in_ms, blank=0)\n            self.endpointer = OnlineCTCEndpoint(self.endpoint_opt)\n        else:\n            raise ValueError(f\"Not supported: {self.model_type}\")\n\n    def model_reset(self):\n        # cache for audio and feat\n        self.remained_wav = None\n        self.cached_feat = None\n\n        if \"deepspeech2\" in self.model_type:\n            return\n\n        ## conformer\n        # cache for conformer online\n        self.att_cache = paddle.zeros([0, 0, 0, 0])\n        self.cnn_cache = paddle.zeros([0, 0, 0, 0])\n\n        self.encoder_out = None\n        # conformer decoding state\n        self.offset = 0  # global offset in decoding frame unit\n\n        ## just for record info\n        self.chunk_num = 0  # global decoding chunk num, not used\n\n    def output_reset(self):\n        ## outputs\n        # partial/ending decoding results\n        self.result_transcripts = ['']\n        # token timestamp result\n        self.word_time_stamp = []\n\n        ## just for record\n        self.hyps = []\n\n        # one best timestamp viterbi prob is large.\n        self.time_stamp = []\n\n    def reset_continuous_decoding(self):\n        \"\"\"\n        when in continous decoding, reset for next utterance.\n        \"\"\"\n        self.global_frame_offset = self.num_frames\n        self.model_reset()\n        self.searcher.reset()\n        self.endpointer.reset()\n\n        # reset hys will trancate history transcripts.\n        # self.output_reset()\n\n    def reset(self):\n        if \"deepspeech2\" in self.model_type:\n            # for deepspeech2\n            # init state\n            self.chunk_state_h_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.chunk_state_c_box = np.zeros(\n                (self.model_config.num_rnn_layers, 1,\n                 self.model_config.rnn_layer_size),\n                dtype=float32)\n            self.decoder.reset_decoder(batch_size=1)\n\n        if \"conformer\" in self.model_type or \"transformer\" in self.model_type:\n            self.searcher.reset()\n            self.endpointer.reset()\n\n        self.device = None\n\n        ## common\n        # global sample and frame step\n        self.num_samples = 0\n        self.global_frame_offset = 0\n        # frame step of cur utterance\n        self.num_frames = 0\n\n        ## endpoint\n        self.endpoint_state = False  # True for detect endpoint\n\n        ## conformer\n        self.model_reset()\n\n        ## outputs\n        self.output_reset()\n\n    def extract_feat(self, samples: ByteString):\n        logger.info(\"Online ASR extract the feat\")\n        samples = np.frombuffer(samples, dtype=np.int16)\n        assert samples.ndim == 1\n\n        self.num_samples += samples.shape[0]\n        logger.debug(\n            f\"This package receive {samples.shape[0]} pcm data. Global samples:{self.num_samples}\"\n        )\n\n        # self.reamined_wav stores all the samples,\n        # include the original remained_wav and this package samples\n        if self.remained_wav is None:\n            self.remained_wav = samples\n        else:\n            assert self.remained_wav.ndim == 1  # (T,)\n            self.remained_wav = np.concatenate([self.remained_wav, samples])\n        logger.debug(\n            f\"The concatenation of remain and now audio samples length is: {self.remained_wav.shape}\"\n        )\n\n        if len(self.remained_wav) < self.win_length:\n            # samples not enough for feature window\n            return 0\n\n        # fbank\n        x_chunk = self.preprocessing(self.remained_wav, **self.preprocess_args)\n        x_chunk = paddle.to_tensor(x_chunk, dtype=\"float32\").unsqueeze(axis=0)\n\n        # feature cache\n        if self.cached_feat is None:\n            self.cached_feat = x_chunk\n        else:\n            assert (len(x_chunk.shape) == 3)  # (B,T,D)\n            assert (len(self.cached_feat.shape) == 3)  # (B,T,D)\n            self.cached_feat = paddle.concat(\n                [self.cached_feat, x_chunk], axis=1)\n\n        # set the feat device\n        if self.device is None:\n            self.device = self.cached_feat.place\n\n        # cur frame step\n        num_frames = x_chunk.shape[1]\n\n        # global frame step\n        self.num_frames += num_frames\n\n        # update remained wav\n        self.remained_wav = self.remained_wav[self.n_shift * num_frames:]\n\n        logger.debug(\n            f\"process the audio feature success, the cached feat shape: {self.cached_feat.shape}\"\n        )\n        logger.debug(\n            f\"After extract feat, the cached remain the audio samples: {self.remained_wav.shape}\"\n        )\n        logger.debug(f\"global samples: {self.num_samples}\")\n        logger.debug(f\"global frames: {self.num_frames}\")\n\n    def decode(self, is_finished=False):\n        \"\"\"advance decoding\n\n        Args:\n            is_finished (bool, optional): Is last frame or not. Defaults to False.\n\n        Returns:\n            None: \n        \"\"\"\n        if \"deepspeech2\" in self.model_type:\n            decoding_chunk_size = 1  # decoding chunk size = 1. int decoding frame unit\n\n            context = 7  # context=7, in audio frame unit\n            subsampling = 4  # subsampling=4, in audio frame unit\n\n            cached_feature_num = context - subsampling\n            # decoding window for model, in audio frame unit\n            decoding_window = (decoding_chunk_size - 1) * subsampling + context\n            # decoding stride for model, in audio frame unit\n            stride = subsampling * decoding_chunk_size\n\n            if self.cached_feat is None:\n                logger.debug(\"no audio feat, please input more pcm data\")\n                return\n\n            num_frames = self.cached_feat.shape[1]\n            logger.debug(\n                f\"Required decoding window {decoding_window} frames, and the connection has {num_frames} frames\"\n            )\n\n            # the cached feat must be larger decoding_window\n            if num_frames < decoding_window and not is_finished:\n                logger.debug(\n                    f\"frame feat num is less than {decoding_window}, please input more pcm data\"\n                )\n                return None, None\n\n            # if is_finished=True, we need at least context frames\n            if num_frames < context:\n                logger.debug(\n                    \"flast {num_frames} is less than context {context} frames, and we cannot do model forward\"\n                )\n                return None, None\n\n            logger.info(\"start to do model forward\")\n            # num_frames - context + 1 ensure that current frame can get context window\n            if is_finished:\n                # if get the finished chunk, we need process the last context\n                left_frames = context\n            else:\n                # we only process decoding_window frames for one chunk\n                left_frames = decoding_window\n\n            end = None\n            for cur in range(0, num_frames - left_frames + 1, stride):\n                end = min(cur + decoding_window, num_frames)\n\n                # extract the audio\n                x_chunk = self.cached_feat[:, cur:end, :].numpy()\n                x_chunk_lens = np.array([x_chunk.shape[1]])\n\n                trans_best = self.decode_one_chunk(x_chunk, x_chunk_lens)\n\n            self.result_transcripts = [trans_best]\n\n            # update feat cache\n            self.cached_feat = self.cached_feat[:, end - cached_feature_num:, :]\n\n            # return trans_best[0]\n        elif \"conformer\" in self.model_type or \"transformer\" in self.model_type:\n            try:\n                logger.info(\n                    f\"we will use the transformer like model : {self.model_type}\"\n                )\n                self.advance_decoding(is_finished)\n                self.update_result()\n\n            except Exception as e:\n                logger.exception(e)\n        else:\n            raise Exception(\"invalid model name\")\n\n    @paddle.no_grad()\n    def decode_one_chunk(self, x_chunk, x_chunk_lens):\n        \"\"\"forward one chunk frames\n\n        Args:\n            x_chunk (np.ndarray): (B,T,D), audio frames.\n            x_chunk_lens ([type]): (B,), audio frame lens\n\n        Returns:\n            logprob: poster probability.\n        \"\"\"\n        logger.debug(\"start to decoce one chunk for deepspeech2\")\n        input_names = self.am_predictor.get_input_names()\n        audio_handle = self.am_predictor.get_input_handle(input_names[0])\n        audio_len_handle = self.am_predictor.get_input_handle(input_names[1])\n        h_box_handle = self.am_predictor.get_input_handle(input_names[2])\n        c_box_handle = self.am_predictor.get_input_handle(input_names[3])\n\n        audio_handle.reshape(x_chunk.shape)\n        audio_handle.copy_from_cpu(x_chunk)\n\n        audio_len_handle.reshape(x_chunk_lens.shape)\n        audio_len_handle.copy_from_cpu(x_chunk_lens)\n\n        h_box_handle.reshape(self.chunk_state_h_box.shape)\n        h_box_handle.copy_from_cpu(self.chunk_state_h_box)\n\n        c_box_handle.reshape(self.chunk_state_c_box.shape)\n        c_box_handle.copy_from_cpu(self.chunk_state_c_box)\n\n        output_names = self.am_predictor.get_output_names()\n        output_handle = self.am_predictor.get_output_handle(output_names[0])\n        output_lens_handle = self.am_predictor.get_output_handle(\n            output_names[1])\n        output_state_h_handle = self.am_predictor.get_output_handle(\n            output_names[2])\n        output_state_c_handle = self.am_predictor.get_output_handle(\n            output_names[3])\n\n        self.am_predictor.run()\n\n        output_chunk_probs = output_handle.copy_to_cpu()\n        output_chunk_lens = output_lens_handle.copy_to_cpu()\n        self.chunk_state_h_box = output_state_h_handle.copy_to_cpu()\n        self.chunk_state_c_box = output_state_c_handle.copy_to_cpu()\n\n        self.decoder.next(output_chunk_probs, output_chunk_lens)\n        trans_best, trans_beam = self.decoder.decode()\n        logger.debug(f\"decode one best result for deepspeech2: {trans_best[0]}\")\n        return trans_best[0]\n\n    @paddle.no_grad()\n    def advance_decoding(self, is_finished=False):\n        if \"deepspeech\" in self.model_type:\n            return\n\n        # reset endpiont state\n        self.endpoint_state = False\n\n        logger.debug(\n            \"Conformer/Transformer: start to decode with advanced_decoding method\"\n        )\n        cfg = self.ctc_decode_config\n\n        # cur chunk size, in decoding frame unit, e.g. 16\n        decoding_chunk_size = cfg.decoding_chunk_size\n        # using num of history chunks, e.g -1\n        num_decoding_left_chunks = cfg.num_decoding_left_chunks\n        assert decoding_chunk_size > 0\n\n        # e.g. 4\n        subsampling = self.model.encoder.embed.subsampling_rate\n        # e.g. 7\n        context = self.model.encoder.embed.right_context + 1\n\n        # processed chunk feature cached for next chunk, e.g. 3\n        cached_feature_num = context - subsampling\n\n        # decoding window, in audio frame unit\n        decoding_window = (decoding_chunk_size - 1) * subsampling + context\n        # decoding stride, in audio frame unit\n        stride = subsampling * decoding_chunk_size\n\n        if self.cached_feat is None:\n            logger.debug(\"no audio feat, please input more pcm data\")\n            return\n\n        # (B=1,T,D)\n        num_frames = self.cached_feat.shape[1]\n        logger.debug(\n            f\"Required decoding window {decoding_window} frames, and the connection has {num_frames} frames\"\n        )\n\n        # the cached feat must be larger decoding_window\n        if num_frames < decoding_window and not is_finished:\n            logger.debug(\n                f\"frame feat num is less than {decoding_window}, please input more pcm data\"\n            )\n            return None, None\n\n        # if is_finished=True, we need at least context frames\n        if num_frames < context:\n            logger.debug(\n                \"flast {num_frames} is less than context {context} frames, and we cannot do model forward\"\n            )\n            return None, None\n\n        logger.info(\"start to do model forward\")\n\n        # num_frames - context + 1 ensure that current frame can get context window\n        if is_finished:\n            # if get the finished chunk, we need process the last context\n            left_frames = context\n        else:\n            # we only process decoding_window frames for one chunk\n            left_frames = decoding_window\n\n        # hist of chunks, in deocding frame unit\n        required_cache_size = decoding_chunk_size * num_decoding_left_chunks\n\n        # record the end for removing the processed feat\n        outputs = []\n        end = None\n        for cur in range(0, num_frames - left_frames + 1, stride):\n            end = min(cur + decoding_window, num_frames)\n\n            # global chunk_num\n            self.chunk_num += 1\n            # cur chunk\n            chunk_xs = self.cached_feat[:, cur:end, :]\n            # forward chunk\n            (y, self.att_cache,\n             self.cnn_cache) = self.model.encoder.forward_chunk(\n                 chunk_xs,\n                 self.offset,\n                 required_cache_size,\n                 att_cache=self.att_cache,\n                 cnn_cache=self.cnn_cache)\n            outputs.append(y)\n\n            # update the global offset, in decoding frame unit\n            self.offset += y.shape[1]\n\n        ys = paddle.cat(outputs, 1)\n        if self.encoder_out is None:\n            self.encoder_out = ys\n        else:\n            self.encoder_out = paddle.concat([self.encoder_out, ys], axis=1)\n        logger.debug(\n            f\"This connection handler encoder out shape: {self.encoder_out.shape}\"\n        )\n\n        # get the ctc probs\n        ctc_probs = self.model.ctc.log_softmax(ys)  # (1, maxlen, vocab_size)\n        ctc_probs = ctc_probs.squeeze(0)\n\n        ## decoding\n        # advance decoding\n        self.searcher.search(ctc_probs, self.cached_feat.place)\n        # get one best hyps\n        self.hyps = self.searcher.get_one_best_hyps()\n\n        # endpoint\n        if not is_finished:\n\n            def contain_nonsilence():\n                return len(self.hyps) > 0 and len(self.hyps[0]) > 0\n\n            decoding_something = contain_nonsilence()\n            if self.endpointer.endpoint_detected(ctc_probs.numpy(),\n                                                 decoding_something):\n                self.endpoint_state = True\n                logger.debug(\n                    f\"Endpoint is detected at {self.num_frames} frame.\")\n\n        # advance cache of feat\n        assert self.cached_feat.shape[0] == 1  #(B=1,T,D)\n        assert end >= cached_feature_num\n        self.cached_feat = self.cached_feat[:, end - cached_feature_num:, :]\n        assert len(\n            self.cached_feat.shape\n        ) == 3, f\"current cache feat shape is: {self.cached_feat.shape}\"\n\n    def update_result(self):\n        \"\"\"Conformer/Transformer hyps to result.\n        \"\"\"\n        logger.debug(\"update the final result\")\n        hyps = self.hyps\n\n        # output results and tokenids\n        self.result_transcripts = [\n            self.text_feature.defeaturize(hyp) for hyp in hyps\n        ]\n        self.result_tokenids = [hyp for hyp in hyps]\n\n    def get_result(self):\n        \"\"\"return partial/ending asr result.\n\n        Returns:\n            str: one best result of partial/ending.\n        \"\"\"\n        if len(self.result_transcripts) > 0:\n            return self.result_transcripts[0]\n        else:\n            return ''\n\n    def get_word_time_stamp(self):\n        \"\"\"return token timestamp result.\n\n        Returns:\n            list: List of ('w':token, 'bg':time, 'ed':time)\n        \"\"\"\n        return self.word_time_stamp\n\n    @paddle.no_grad()\n    def rescoring(self):\n        \"\"\"Second-Pass Decoding,\n        only for conformer and transformer model.\n        \"\"\"\n        if \"deepspeech2\" in self.model_type:\n            logger.debug(\"deepspeech2 not support rescoring decoding.\")\n            return\n\n        if \"attention_rescoring\" != self.ctc_decode_config.decoding_method:\n            logger.debug(\n                f\"decoding method not match: {self.ctc_decode_config.decoding_method}, need attention_rescoring\"\n            )\n            return\n\n        logger.debug(\"rescoring the final result\")\n\n        # last decoding for last audio\n        self.searcher.finalize_search()\n        # update beam search results\n        self.update_result()\n\n        beam_size = self.ctc_decode_config.beam_size\n        reverse_weight = getattr(self.ctc_decode_config, 'reverse_weight', 0.0)\n        hyps = self.searcher.get_hyps()\n        if hyps is None or len(hyps) == 0:\n            logger.info(\"No Hyps!\")\n            return\n\n        # rescore by decoder post probability\n\n        # assert len(hyps) == beam_size\n        # list of Tensor\n        hyp_list = []\n        for hyp in hyps:\n            hyp_content = hyp[0]\n            # Prevent the hyp is empty\n            if len(hyp_content) == 0:\n                hyp_content = (self.model.ctc.blank_id, )\n\n            hyp_content = paddle.to_tensor(\n                hyp_content, place=self.device, dtype=paddle.long)\n            hyp_list.append(hyp_content)\n\n        hyps_pad = pad_sequence(\n            hyp_list, batch_first=True, padding_value=self.model.ignore_id)\n        ori_hyps_pad = hyps_pad\n        hyps_lens = paddle.to_tensor(\n            [len(hyp[0]) for hyp in hyps], place=self.device,\n            dtype=paddle.long)  # (beam_size,)\n        hyps_pad, _ = add_sos_eos(hyps_pad, self.model.sos, self.model.eos,\n                                  self.model.ignore_id)\n        hyps_lens = hyps_lens + 1  # Add <sos> at beginning\n\n        # ctc score in ln domain\n        # (beam_size, max_hyps_len, vocab_size)\n        decoder_out, r_decoder_out = self.model.forward_attention_decoder(\n            hyps_pad, hyps_lens, self.encoder_out, reverse_weight)\n\n        decoder_out = decoder_out.numpy()\n        # r_decoder_out will be 0.0, if reverse_weight is 0.0 or decoder is a\n        # conventional transformer decoder.\n        r_decoder_out = r_decoder_out.numpy()\n\n        # Only use decoder score for rescoring\n        best_score = -float('inf')\n        best_index = 0\n        # hyps is List[(Text=List[int], Score=float)], len(hyps)=beam_size\n        for i, hyp in enumerate(hyps):\n            score = 0.0\n            for j, w in enumerate(hyp[0]):\n                score += decoder_out[i][j][w]\n\n            # last decoder output token is `eos`, for laste decoder input token.\n            score += decoder_out[i][len(hyp[0])][self.model.eos]\n            if reverse_weight > 0:\n                r_score = 0.0\n                for j, w in enumerate(hyp[0]):\n                    r_score += r_decoder_out[i][len(hyp[0]) - j - 1][w]\n                r_score += r_decoder_out[i][len(hyp[0])][self.model.eos]\n                score = score * (1 - reverse_weight) + r_score * reverse_weight\n            # add ctc score (which in ln domain)\n            score += hyp[1] * self.ctc_decode_config.ctc_weight\n\n            if score > best_score:\n                best_score = score\n                best_index = i\n\n        # update the one best result\n        # hyps stored the beam results and each fields is:\n\n        logger.info(f\"best hyp index: {best_index}\")\n        # logger.info(f'best result: {hyps[best_index]}')\n        # the field of the hyps is:\n        ## asr results\n        # hyps[0][0]: the sentence word-id in the vocab with a tuple\n        # hyps[0][1]: the sentence decoding probability with all paths\n        ## timestamp\n        # hyps[0][2]: viterbi_blank ending probability\n        # hyps[0][3]: viterbi_non_blank dending probability\n        # hyps[0][4]: current_token_prob,\n        # hyps[0][5]: times_viterbi_blank ending timestamp,\n        # hyps[0][6]: times_titerbi_non_blank encding timestamp.\n        self.hyps = [hyps[best_index][0]]\n        logger.info(f\"best hyp ids: {self.hyps}\")\n\n        # update the hyps time stamp\n        self.time_stamp = hyps[best_index][5] if hyps[best_index][2] > hyps[\n            best_index][3] else hyps[best_index][6]\n        logger.info(f\"time stamp: {self.time_stamp}\")\n\n        # update one best result\n        self.update_result()\n\n        # update each word start and end time stamp\n        # decoding frame to audio frame\n        decode_frame_shift = self.model.encoder.embed.subsampling_rate\n        decode_frame_shift_in_sec = decode_frame_shift * (self.n_shift /\n                                                          self.sample_rate)\n        logger.info(f\"decode frame shift in sec: {decode_frame_shift_in_sec}\")\n\n        global_offset_in_sec = self.global_frame_offset * self.frame_shift_in_ms / 1000.0\n        logger.info(f\"global offset: {global_offset_in_sec} sec.\")\n\n        word_time_stamp = []\n        for idx, _ in enumerate(self.time_stamp):\n            start = (self.time_stamp[idx - 1] + self.time_stamp[idx]\n                     ) / 2.0 if idx > 0 else 0\n            start = start * decode_frame_shift_in_sec\n\n            end = (self.time_stamp[idx] + self.time_stamp[idx + 1]\n                   ) / 2.0 if idx < len(self.time_stamp) - 1 else self.offset\n\n            end = end * decode_frame_shift_in_sec\n            word_time_stamp.append({\n                \"w\": self.result_transcripts[0][idx],\n                \"bg\": global_offset_in_sec + start,\n                \"ed\": global_offset_in_sec + end\n            })\n\n        self.word_time_stamp = word_time_stamp\n        logger.info(f\"word time stamp: {self.word_time_stamp}\")\n\n\nclass ASRServerExecutor(ASRExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='asr', model_format='dynamic', inference_mode='online')\n\n    def update_config(self) -> None:\n        if \"deepspeech2\" in self.model_type:\n            with UpdateConfig(self.config):\n                # download lm\n                self.config.decode.lang_model_path = os.path.join(\n                    MODEL_HOME, 'language_model',\n                    self.config.decode.lang_model_path)\n\n            lm_url = self.task_resource.res_dict['lm_url']\n            lm_md5 = self.task_resource.res_dict['lm_md5']\n            logger.debug(f\"Start to load language model {lm_url}\")\n            self.download_lm(\n                lm_url,\n                os.path.dirname(self.config.decode.lang_model_path), lm_md5)\n        elif \"conformer\" in self.model_type or \"transformer\" in self.model_type:\n            with UpdateConfig(self.config):\n                logger.debug(\"start to create the stream conformer asr engine\")\n                # update the decoding method\n                if self.decode_method:\n                    self.config.decode.decoding_method = self.decode_method\n                # update num_decoding_left_chunks\n                if self.num_decoding_left_chunks:\n                    assert self.num_decoding_left_chunks == -1 or self.num_decoding_left_chunks >= 0, \"num_decoding_left_chunks should be -1 or >=0\"\n                    self.config.decode.num_decoding_left_chunks = self.num_decoding_left_chunks\n                # we only support ctc_prefix_beam_search and attention_rescoring dedoding method\n                # Generally we set the decoding_method to attention_rescoring\n                if self.config.decode.decoding_method not in [\n                        \"ctc_prefix_beam_search\", \"attention_rescoring\"\n                ]:\n                    logger.debug(\n                        \"we set the decoding_method to attention_rescoring\")\n                    self.config.decode.decoding_method = \"attention_rescoring\"\n\n                assert self.config.decode.decoding_method in [\n                    \"ctc_prefix_beam_search\", \"attention_rescoring\"\n                ], f\"we only support ctc_prefix_beam_search and attention_rescoring dedoding method, current decoding method is {self.config.decode.decoding_method}\"\n        else:\n            raise Exception(f\"not support: {self.model_type}\")\n\n    def init_model(self) -> None:\n        if \"deepspeech2\" in self.model_type:\n            # AM predictor\n            logger.debug(\"ASR engine start to init the am predictor\")\n            self.am_predictor = init_predictor(\n                model_file=self.am_model,\n                params_file=self.am_params,\n                predictor_conf=self.am_predictor_conf)\n        elif \"conformer\" in self.model_type or \"transformer\" in self.model_type:\n            # load model\n            # model_type: {model_name}_{dataset}\n            model_name = self.model_type[:self.model_type.rindex('_')]\n            logger.debug(f\"model name: {model_name}\")\n            model_class = self.task_resource.get_model_class(model_name)\n            model = model_class.from_config(self.config)\n            self.model = model\n            self.model.set_state_dict(paddle.load(self.am_model))\n            self.model.eval()\n        else:\n            raise Exception(f\"not support: {self.model_type}\")\n\n    def _init_from_path(self,\n                        model_type: str=None,\n                        am_model: Optional[os.PathLike]=None,\n                        am_params: Optional[os.PathLike]=None,\n                        lang: str='zh',\n                        codeswitch: Optional[bool]=False,\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='attention_rescoring',\n                        num_decoding_left_chunks: int=-1,\n                        am_predictor_conf: dict=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if not model_type or not lang or not sample_rate:\n            logger.error(\n                \"The model type or lang or sample rate is None, please input an valid server parameter yaml\"\n            )\n            return False\n\n        self.model_type = model_type\n        self.sample_rate = sample_rate\n        self.decode_method = decode_method\n        self.num_decoding_left_chunks = num_decoding_left_chunks\n        # conf for paddleinference predictor or onnx\n        self.am_predictor_conf = am_predictor_conf\n        logger.debug(f\"model_type: {self.model_type}\")\n\n        sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n        if lang == \"zh_en\" and codeswitch is True:\n            tag = model_type + '-' + 'codeswitch_' + lang + '-' + sample_rate_str\n        elif lang == \"zh_en\" or codeswitch is True:\n            raise Exception(\"codeswitch is true only in zh_en model\")\n        else:\n            tag = model_type + '-' + lang + '-' + sample_rate_str\n        self.task_resource.set_task_model(model_tag=tag)\n\n        if cfg_path is None or am_model is None or am_params is None:\n            self.res_path = self.task_resource.res_dir\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n\n            self.am_model = os.path.join(self.res_path,\n                                         self.task_resource.res_dict['model'])\n            self.am_params = os.path.join(self.res_path,\n                                          self.task_resource.res_dict['params'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.am_model = os.path.abspath(am_model)\n            self.am_params = os.path.abspath(am_params)\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        logger.debug(\"Load the pretrained model:\")\n        logger.debug(f\"  tag = {tag}\")\n        logger.debug(f\"  res_path: {self.res_path}\")\n        logger.debug(f\"  cfg path: {self.cfg_path}\")\n        logger.debug(f\"  am_model path: {self.am_model}\")\n        logger.debug(f\"  am_params path: {self.am_params}\")\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        if self.config.spm_model_prefix:\n            self.config.spm_model_prefix = os.path.join(\n                self.res_path, self.config.spm_model_prefix)\n            logger.debug(f\"spm model path: {self.config.spm_model_prefix}\")\n\n        self.vocab = self.config.vocab_filepath\n\n        self.text_feature = TextFeaturizer(\n            unit_type=self.config.unit_type,\n            vocab=self.config.vocab_filepath,\n            spm_model_prefix=self.config.spm_model_prefix)\n\n        self.update_config()\n\n        # AM predictor\n        self.init_model()\n\n        logger.debug(f\"create the {model_type} model success\")\n        return True\n\n\nclass ASREngine(BaseEngine):\n    \"\"\"ASR server resource\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(ASREngine, self).__init__()\n\n    def init_model(self) -> bool:\n        if not self.executor._init_from_path(\n                model_type=self.config.model_type,\n                am_model=self.config.am_model,\n                am_params=self.config.am_params,\n                lang=self.config.lang,\n                codeswitch=self.config.get(\"codeswitch\", False),\n                sample_rate=self.config.sample_rate,\n                cfg_path=self.config.cfg_path,\n                decode_method=self.config.decode_method,\n                num_decoding_left_chunks=self.config.num_decoding_left_chunks,\n                am_predictor_conf=self.config.am_predictor_conf):\n            return False\n        return True\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.config = config\n        self.executor = ASRServerExecutor()\n\n        try:\n            self.device = self.config.get(\"device\", paddle.get_device())\n            paddle.set_device(self.device)\n        except BaseException as e:\n            logger.error(\n                f\"Set device failed, please check if device '{self.device}' is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\n                \"If all GPU or XPU is used, you can set the server to 'cpu'\")\n            sys.exit(-1)\n\n        logger.debug(f\"paddlespeech_server set the device: {self.device}\")\n\n        if not self.init_model():\n            logger.error(\n                \"Init the ASR server occurs error, please check the server configuration yaml\"\n            )\n            return False\n\n        logger.info(\"Initialize ASR server engine successfully on device: %s.\" %\n                    (self.device))\n\n        return True\n\n    def new_handler(self):\n        \"\"\"New handler from model.\n\n        Returns:\n            PaddleASRConnectionHanddler: asr handler instance\n        \"\"\"\n        return PaddleASRConnectionHanddler(self)\n\n    def preprocess(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def run(self, *args, **kwargs):\n        raise NotImplementedError(\"Online not using this.\")\n\n    def postprocess(self):\n        raise NotImplementedError(\"Online not using this.\")\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/paddleinference/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/paddleinference/asr_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nimport os\nimport time\nfrom typing import Optional\n\nimport paddle\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.asr.infer import ASRExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.s2t.frontend.featurizer.text_featurizer import TextFeaturizer\nfrom paddlespeech.s2t.modules.ctc import CTCDecoder\nfrom paddlespeech.s2t.utils.utility import UpdateConfig\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.paddle_predictor import init_predictor\nfrom paddlespeech.server.utils.paddle_predictor import run_model\nfrom paddlespeech.utils.env import MODEL_HOME\n\n__all__ = ['ASREngine', 'PaddleASRConnectionHandler']\n\n\nclass ASRServerExecutor(ASRExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='asr', model_format='static')\n\n    def _init_from_path(self,\n                        model_type: str='wenetspeech',\n                        am_model: Optional[os.PathLike]=None,\n                        am_params: Optional[os.PathLike]=None,\n                        lang: str='zh',\n                        sample_rate: int=16000,\n                        cfg_path: Optional[os.PathLike]=None,\n                        decode_method: str='attention_rescoring',\n                        am_predictor_conf: dict=None):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        self.max_len = 50\n        sample_rate_str = '16k' if sample_rate == 16000 else '8k'\n        tag = model_type + '-' + lang + '-' + sample_rate_str\n        self.max_len = 50\n        self.task_resource.set_task_model(model_tag=tag)\n        if cfg_path is None or am_model is None or am_params is None:\n            self.res_path = self.task_resource.res_dir\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n\n            self.am_model = os.path.join(self.res_path,\n                                         self.task_resource.res_dict['model'])\n            self.am_params = os.path.join(self.res_path,\n                                          self.task_resource.res_dict['params'])\n            logger.debug(self.res_path)\n            logger.debug(self.cfg_path)\n            logger.debug(self.am_model)\n            logger.debug(self.am_params)\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.am_model = os.path.abspath(am_model)\n            self.am_params = os.path.abspath(am_params)\n            self.res_path = os.path.dirname(\n                os.path.dirname(os.path.abspath(self.cfg_path)))\n\n        #Init body.\n        self.config = CfgNode(new_allowed=True)\n        self.config.merge_from_file(self.cfg_path)\n\n        with UpdateConfig(self.config):\n            if \"deepspeech2\" in model_type:\n                self.vocab = self.config.vocab_filepath\n                if self.config.spm_model_prefix:\n                    self.config.spm_model_prefix = os.path.join(\n                        self.res_path, self.config.spm_model_prefix)\n                self.text_feature = TextFeaturizer(\n                    unit_type=self.config.unit_type,\n                    vocab=self.vocab,\n                    spm_model_prefix=self.config.spm_model_prefix)\n                self.config.decode.lang_model_path = os.path.join(\n                    MODEL_HOME, 'language_model',\n                    self.config.decode.lang_model_path)\n\n                lm_url = self.task_resource.res_dict['lm_url']\n                lm_md5 = self.task_resource.res_dict['lm_md5']\n                self.download_lm(\n                    lm_url,\n                    os.path.dirname(self.config.decode.lang_model_path), lm_md5)\n            elif \"conformer\" in model_type or \"transformer\" in model_type:\n                raise Exception(\"wrong type\")\n            else:\n                raise Exception(\"wrong type\")\n\n        # AM predictor\n        self.am_predictor_conf = am_predictor_conf\n        self.am_predictor = init_predictor(\n            model_file=self.am_model,\n            params_file=self.am_params,\n            predictor_conf=self.am_predictor_conf)\n\n        # decoder\n        self.decoder = CTCDecoder(\n            odim=self.config.output_dim,  # <blank> is in  vocab\n            enc_n_units=self.config.rnn_layer_size * 2,\n            blank_id=self.config.blank_id,\n            dropout_rate=0.0,\n            reduction=True,  # sum\n            batch_average=True,  # sum / batch_size\n            grad_norm_type=self.config.get('ctc_grad_norm_type', None))\n\n    @paddle.no_grad()\n    def infer(self, model_type: str):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        cfg = self.config.decode\n        audio = self._inputs[\"audio\"]\n        audio_len = self._inputs[\"audio_len\"]\n        if \"deepspeech2\" in model_type:\n            decode_batch_size = audio.shape[0]\n            # init once\n            self.decoder.init_decoder(\n                decode_batch_size, self.text_feature.vocab_list,\n                cfg.decoding_method, cfg.lang_model_path, cfg.alpha, cfg.beta,\n                cfg.beam_size, cfg.cutoff_prob, cfg.cutoff_top_n,\n                cfg.num_proc_bsearch)\n\n            output_data = run_model(self.am_predictor,\n                                    [audio.numpy(), audio_len.numpy()])\n\n            probs = output_data[0]\n            eouts_len = output_data[1]\n\n            batch_size = probs.shape[0]\n            self.decoder.reset_decoder(batch_size=batch_size)\n            self.decoder.next(probs, eouts_len)\n            trans_best, trans_beam = self.decoder.decode()\n\n            # self.model.decoder.del_decoder()\n            self._outputs[\"result\"] = trans_best[0]\n\n        elif \"conformer\" in model_type or \"transformer\" in model_type:\n            raise Exception(\"invalid model name\")\n        else:\n            raise Exception(\"invalid model name\")\n\n\nclass ASREngine(BaseEngine):\n    \"\"\"ASR server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(ASREngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.executor = ASRServerExecutor()\n        self.config = config\n        self.engine_type = \"inference\"\n\n        try:\n            if self.config.am_predictor_conf.device is not None:\n                self.device = self.config.am_predictor_conf.device\n            else:\n                self.device = paddle.get_device()\n\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(e)\n            return False\n\n        self.executor._init_from_path(\n            model_type=self.config.model_type,\n            am_model=self.config.am_model,\n            am_params=self.config.am_params,\n            lang=self.config.lang,\n            sample_rate=self.config.sample_rate,\n            cfg_path=self.config.cfg_path,\n            decode_method=self.config.decode_method,\n            am_predictor_conf=self.config.am_predictor_conf)\n\n        logger.info(\"Initialize ASR server engine successfully.\")\n        return True\n\n\nclass PaddleASRConnectionHandler(ASRServerExecutor):\n    def __init__(self, asr_engine):\n        \"\"\"The PaddleSpeech ASR Server Connection Handler\n           This connection process every asr server request\n        Args:\n            asr_engine (ASREngine): The ASR engine\n        \"\"\"\n        super().__init__()\n        self.input = None\n        self.output = None\n        self.asr_engine = asr_engine\n        self.executor = self.asr_engine.executor\n        self.config = self.executor.config\n        self.max_len = self.executor.max_len\n        self.decoder = self.executor.decoder\n        self.am_predictor = self.executor.am_predictor\n        self.text_feature = self.executor.text_feature\n\n    def run(self, audio_data):\n        \"\"\"engine run\n\n        Args:\n            audio_data (bytes): base64.b64decode\n        \"\"\"\n        if self._check(\n                io.BytesIO(audio_data), self.asr_engine.config.sample_rate,\n                self.asr_engine.config.force_yes):\n            logger.debug(\"start running asr engine\")\n            self.preprocess(self.asr_engine.config.model_type,\n                            io.BytesIO(audio_data))\n            st = time.time()\n            self.infer(self.asr_engine.config.model_type)\n            infer_time = time.time() - st\n            self.output = self.postprocess()  # Retrieve result of asr.\n            logger.debug(\"end inferring asr engine\")\n        else:\n            logger.error(\"file check failed!\")\n            self.output = None\n\n        logger.info(\"inference time: {}\".format(infer_time))\n        logger.info(\"asr engine type: paddle inference\")\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/asr/python/asr_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nimport sys\nimport time\n\nimport paddle\n\nfrom paddlespeech.cli.asr.infer import ASRExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.base_engine import BaseEngine\n\n__all__ = ['ASREngine', 'PaddleASRConnectionHandler']\n\n\nclass ASRServerExecutor(ASRExecutor):\n    def __init__(self):\n        super().__init__()\n        pass\n\n\nclass ASREngine(BaseEngine):\n    \"\"\"ASR server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(ASREngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.executor = ASRServerExecutor()\n        self.config = config\n        self.engine_type = \"python\"\n\n        try:\n            if self.config.device is not None:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(e)\n            return False\n\n        cs = False\n\n        if self.config.lang == \"zh_en\" :\n            cs=True\n\n        self.executor._init_from_path(\n            model_type=self.config.model,\n            lang=self.config.lang,\n            sample_rate=self.config.sample_rate,\n            cfg_path=self.config.cfg_path,\n            decode_method=self.config.decode_method,\n            ckpt_path=self.config.ckpt_path,\n            codeswitch=cs )\n\n        logger.info(\"Initialize ASR server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n\nclass PaddleASRConnectionHandler(ASRServerExecutor):\n    def __init__(self, asr_engine):\n        \"\"\"The PaddleSpeech ASR Server Connection Handler\n           This connection process every asr server request\n        Args:\n            asr_engine (ASREngine): The ASR engine\n        \"\"\"\n        super().__init__()\n        self.input = None\n        self.output = None\n        self.asr_engine = asr_engine\n        self.executor = self.asr_engine.executor\n        self.max_len = self.executor.max_len\n        self.text_feature = self.executor.text_feature\n        self.model = self.executor.model\n        self.config = self.executor.config\n\n    def run(self, audio_data):\n        \"\"\"engine run \n\n        Args:\n            audio_data (bytes): base64.b64decode\n        \"\"\"\n        try:\n            if self._check(\n                    io.BytesIO(audio_data), self.asr_engine.config.sample_rate,\n                    self.asr_engine.config.force_yes):\n                logger.debug(\"start run asr engine\")\n                self.preprocess(self.asr_engine.config.model,\n                                io.BytesIO(audio_data))\n                st = time.time()\n                self.infer(self.asr_engine.config.model)\n                infer_time = time.time() - st\n                self.output = self.postprocess()  # Retrieve result of asr.\n            else:\n                logger.error(\"file check failed!\")\n                self.output = None\n\n            logger.info(\"inference time: {}\".format(infer_time))\n            logger.info(\"asr engine type: python\")\n        except Exception as e:\n            logger.info(e)\n            sys.exit(-1)\n"
  },
  {
    "path": "paddlespeech/server/engine/base_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import Union\n\nfrom pattern_singleton import Singleton\n\n__all__ = ['BaseEngine']\n\n\nclass BaseEngine(metaclass=Singleton):\n    \"\"\"\n        An base engine class\n    \"\"\"\n\n    def __init__(self):\n        self._inputs = dict()\n        self._outputs = dict()\n\n    def init(self, *args, **kwargs):\n        \"\"\"\n        init the engine\n        \n        Returns:\n            bool: true or false\n        \"\"\"\n        pass\n\n    def postprocess(self, *args, **kwargs) -> Union[str, os.PathLike]:\n        \"\"\"\n        Output postprocess and return results.\n        This method get model output from self._outputs and convert it into human-readable results.\n\n        Returns:\n            Union[str, os.PathLike]: Human-readable results such as texts and audio files.\n        \"\"\"\n        pass\n\n    def run(self, *args, **kwargs) -> Union[str, os.PathLike]:\n        \"\"\"\n        Output postprocess and return results.\n        This method get model output from self._outputs and convert it into human-readable results.\n\n        Returns:\n            Union[str, os.PathLike]: Human-readable results such as texts and audio files.\n        \"\"\"\n        pass\n"
  },
  {
    "path": "paddlespeech/server/engine/cls/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/cls/paddleinference/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/cls/paddleinference/cls_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nimport os\nimport time\nfrom collections import OrderedDict\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nimport yaml\n\nfrom paddlespeech.cli.cls.infer import CLSExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.paddle_predictor import init_predictor\nfrom paddlespeech.server.utils.paddle_predictor import run_model\n\n__all__ = ['CLSEngine', 'PaddleCLSConnectionHandler']\n\n\nclass CLSServerExecutor(CLSExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='cls', model_format='static')\n\n    def _init_from_path(\n            self,\n            model_type: str='panns_cnn14_audioset',\n            cfg_path: Optional[os.PathLike]=None,\n            model_path: Optional[os.PathLike]=None,\n            params_path: Optional[os.PathLike]=None,\n            label_file: Optional[os.PathLike]=None,\n            predictor_conf: dict=None, ):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n\n        if cfg_path is None or model_path is None or params_path is None or label_file is None:\n            tag = model_type + '-' + '32k'\n            self.task_resource.set_task_model(model_tag=tag)\n            self.res_path = self.task_resource.res_dir\n            self.cfg_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['cfg_path'])\n            self.model_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['model_path'])\n            self.params_path = os.path.join(\n                self.res_path, self.task_resource.res_dict['params_path'])\n            self.label_file = os.path.join(\n                self.res_path, self.task_resource.res_dict['label_file'])\n        else:\n            self.cfg_path = os.path.abspath(cfg_path)\n            self.model_path = os.path.abspath(model_path)\n            self.params_path = os.path.abspath(params_path)\n            self.label_file = os.path.abspath(label_file)\n\n        logger.debug(self.cfg_path)\n        logger.debug(self.model_path)\n        logger.debug(self.params_path)\n        logger.debug(self.label_file)\n\n        # config\n        with open(self.cfg_path, 'r') as f:\n            self._conf = yaml.safe_load(f)\n        logger.debug(\"Read cfg file successfully.\")\n\n        # labels\n        self._label_list = []\n        with open(self.label_file, 'r') as f:\n            for line in f:\n                self._label_list.append(line.strip())\n        logger.debug(\"Read label file successfully.\")\n\n        # Create predictor\n        self.predictor_conf = predictor_conf\n        self.predictor = init_predictor(\n            model_file=self.model_path,\n            params_file=self.params_path,\n            predictor_conf=self.predictor_conf)\n        logger.debug(\"Create predictor successfully.\")\n\n    @paddle.no_grad()\n    def infer(self):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        output = run_model(self.predictor, [self._inputs['feats'].numpy()])\n        self._outputs['logits'] = output[0]\n\n\nclass CLSEngine(BaseEngine):\n    \"\"\"CLS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(CLSEngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.executor = CLSServerExecutor()\n        self.config = config\n        self.engine_type = \"inference\"\n\n        try:\n            if self.config.predictor_conf.device is not None:\n                self.device = self.config.predictor_conf.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                self.config.model_type, self.config.cfg_path,\n                self.config.model_path, self.config.params_path,\n                self.config.label_file, self.config.predictor_conf)\n\n        except Exception as e:\n            logger.error(\"Initialize CLS server engine Failed.\")\n            logger.error(e)\n            return False\n\n        logger.info(\"Initialize CLS server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n\nclass PaddleCLSConnectionHandler(CLSServerExecutor):\n    def __init__(self, cls_engine):\n        \"\"\"The PaddleSpeech CLS Server Connection Handler\n           This connection process every cls server request\n        Args:\n            cls_engine (CLSEngine): The CLS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleCLSConnectionHandler to process the cls request\")\n\n        self._inputs = OrderedDict()\n        self._outputs = OrderedDict()\n        self.cls_engine = cls_engine\n        self.executor = self.cls_engine.executor\n        self._conf = self.executor._conf\n        self._label_list = self.executor._label_list\n        self.predictor = self.executor.predictor\n\n    def run(self, audio_data):\n        \"\"\"engine run \n\n        Args:\n            audio_data (bytes): base64.b64decode\n        \"\"\"\n\n        self.preprocess(io.BytesIO(audio_data))\n        st = time.time()\n        self.infer()\n        infer_time = time.time() - st\n\n        logger.debug(\"inference time: {}\".format(infer_time))\n        logger.info(\"cls engine type: inference\")\n\n    def postprocess(self, topk: int):\n        \"\"\"postprocess\n        \"\"\"\n        assert topk <= len(\n            self._label_list), 'Value of topk is larger than number of labels.'\n\n        result = np.squeeze(self._outputs['logits'], axis=0)\n        topk_idx = (-result).argsort()[:topk]\n        topk_results = []\n        for idx in topk_idx:\n            res = {}\n            label, score = self._label_list[idx], result[idx]\n            res['class_name'] = label\n            res['prob'] = score\n            topk_results.append(res)\n\n        return topk_results\n"
  },
  {
    "path": "paddlespeech/server/engine/cls/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/cls/python/cls_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nimport time\nfrom collections import OrderedDict\n\nimport paddle\n\nfrom paddlespeech.cli.cls.infer import CLSExecutor\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.base_engine import BaseEngine\n\n__all__ = ['CLSEngine', 'PaddleCLSConnectionHandler']\n\n\nclass CLSServerExecutor(CLSExecutor):\n    def __init__(self):\n        super().__init__()\n        pass\n\n\nclass CLSEngine(BaseEngine):\n    \"\"\"CLS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        super(CLSEngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        \"\"\"init engine resource\n\n        Args:\n            config_file (str): config file\n\n        Returns:\n            bool: init failed or success\n        \"\"\"\n        self.executor = CLSServerExecutor()\n        self.config = config\n        self.engine_type = \"python\"\n\n        try:\n            if self.config.device is not None:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                self.config.model, self.config.cfg_path, self.config.ckpt_path,\n                self.config.label_file)\n        except Exception as e:\n            logger.error(\"Initialize CLS server engine Failed.\")\n            logger.error(e)\n            return False\n\n        logger.info(\"Initialize CLS server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n\nclass PaddleCLSConnectionHandler(CLSServerExecutor):\n    def __init__(self, cls_engine):\n        \"\"\"The PaddleSpeech CLS Server Connection Handler\n           This connection process every cls server request\n        Args:\n            cls_engine (CLSEngine): The CLS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleCLSConnectionHandler to process the cls request\")\n\n        self._inputs = OrderedDict()\n        self._outputs = OrderedDict()\n        self.cls_engine = cls_engine\n        self.executor = self.cls_engine.executor\n        self._conf = self.executor._conf\n        self._label_list = self.executor._label_list\n        self.model = self.executor.model\n\n    def run(self, audio_data):\n        \"\"\"engine run \n\n        Args:\n            audio_data (bytes): base64.b64decode\n        \"\"\"\n        self.preprocess(io.BytesIO(audio_data))\n        st = time.time()\n        self.infer()\n        infer_time = time.time() - st\n\n        logger.debug(\"inference time: {}\".format(infer_time))\n        logger.info(\"cls engine type: python\")\n\n    def postprocess(self, topk: int):\n        \"\"\"postprocess\n        \"\"\"\n        assert topk <= len(\n            self._label_list), 'Value of topk is larger than number of labels.'\n\n        result = self._outputs['logits'].squeeze(0).numpy()\n        topk_idx = (-result).argsort()[:topk]\n        topk_results = []\n        for idx in topk_idx:\n            res = {}\n            label, score = self._label_list[idx], result[idx]\n            res['class_name'] = label\n            res['prob'] = score\n            topk_results.append(res)\n\n        return topk_results\n"
  },
  {
    "path": "paddlespeech/server/engine/engine_factory.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Text\n\nfrom paddlespeech.cli.log import logger\n\n__all__ = ['EngineFactory']\n\n\nclass EngineFactory(object):\n    @staticmethod\n    def get_engine(engine_name: Text, engine_type: Text):\n        logger.info(f\"{engine_name} : {engine_type} engine.\")\n\n        if engine_name == 'asr' and engine_type == 'inference':\n            from paddlespeech.server.engine.asr.paddleinference.asr_engine import ASREngine\n            return ASREngine()\n        elif engine_name == 'asr' and engine_type == 'python':\n            from paddlespeech.server.engine.asr.python.asr_engine import ASREngine\n            return ASREngine()\n        elif engine_name == 'asr' and engine_type == 'online':\n            from paddlespeech.server.engine.asr.online.python.asr_engine import ASREngine\n            return ASREngine()\n        elif engine_name == 'asr' and engine_type == 'online-inference':\n            from paddlespeech.server.engine.asr.online.paddleinference.asr_engine import ASREngine\n            return ASREngine()\n        elif engine_name == 'asr' and engine_type == 'online-onnx':\n            from paddlespeech.server.engine.asr.online.onnx.asr_engine import ASREngine\n            return ASREngine()\n        elif engine_name == 'tts' and engine_type == 'inference':\n            from paddlespeech.server.engine.tts.paddleinference.tts_engine import TTSEngine\n            return TTSEngine()\n        elif engine_name == 'tts' and engine_type == 'python':\n            from paddlespeech.server.engine.tts.python.tts_engine import TTSEngine\n            return TTSEngine()\n        elif engine_name == 'tts' and engine_type == 'online':\n            from paddlespeech.server.engine.tts.online.python.tts_engine import TTSEngine\n            return TTSEngine()\n        elif engine_name == 'tts' and engine_type == 'online-onnx':\n            from paddlespeech.server.engine.tts.online.onnx.tts_engine import TTSEngine\n            return TTSEngine()\n        elif engine_name == 'cls' and engine_type == 'inference':\n            from paddlespeech.server.engine.cls.paddleinference.cls_engine import CLSEngine\n            return CLSEngine()\n        elif engine_name == 'cls' and engine_type == 'python':\n            from paddlespeech.server.engine.cls.python.cls_engine import CLSEngine\n            return CLSEngine()\n        elif engine_name.lower() == 'text' and engine_type.lower() == 'python':\n            from paddlespeech.server.engine.text.python.text_engine import TextEngine\n            return TextEngine()\n        elif engine_name.lower() == 'vector' and engine_type.lower() == 'python':\n            from paddlespeech.server.engine.vector.python.vector_engine import VectorEngine\n            return VectorEngine()\n        elif engine_name.lower() == 'acs' and engine_type.lower() == 'python':\n            from paddlespeech.server.engine.acs.python.acs_engine import ACSEngine\n            return ACSEngine()\n        else:\n            return None\n"
  },
  {
    "path": "paddlespeech/server/engine/engine_pool.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.server.engine.engine_factory import EngineFactory\n\n# global value\nENGINE_POOL = {}\n\n\ndef get_engine_pool() -> dict:\n    \"\"\" Get engine pool\n    \"\"\"\n    global ENGINE_POOL\n    return ENGINE_POOL\n\n\ndef init_engine_pool(config) -> bool:\n    \"\"\" Init engine pool\n    \"\"\"\n    global ENGINE_POOL\n\n    for engine_and_type in config.engine_list:\n        engine = engine_and_type.split(\"_\")[0]\n        engine_type = engine_and_type.split(\"_\")[1]\n        ENGINE_POOL[engine] = EngineFactory.get_engine(\n            engine_name=engine, engine_type=engine_type)\n\n        if not ENGINE_POOL[engine].init(config=config[engine_and_type]):\n            return False\n\n    return True\n"
  },
  {
    "path": "paddlespeech/server/engine/engine_warmup.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\n\n\ndef warm_up(engine_and_type: str, warm_up_time: int=3) -> bool:\n    engine_pool = get_engine_pool()\n\n    if \"tts\" in engine_and_type:\n        tts_engine = engine_pool['tts']\n        flag_online = False\n        if tts_engine.lang == 'zh':\n            sentence = \"您好，欢迎使用语音合成服务。\"\n        elif tts_engine.lang == 'en':\n            sentence = \"Hello and welcome to the speech synthesis service.\"\n        elif tts_engine.lang == 'mix':\n            sentence = \"您好，欢迎使用TTS多语种服务。\"\n        else:\n            logger.error(\"tts engine only support lang: zh or en or mix.\")\n            sys.exit(-1)\n\n        if engine_and_type == \"tts_python\":\n            from paddlespeech.server.engine.tts.python.tts_engine import PaddleTTSConnectionHandler\n        elif engine_and_type == \"tts_inference\":\n            from paddlespeech.server.engine.tts.paddleinference.tts_engine import PaddleTTSConnectionHandler\n        elif engine_and_type == \"tts_online\":\n            from paddlespeech.server.engine.tts.online.python.tts_engine import PaddleTTSConnectionHandler\n            flag_online = True\n        elif engine_and_type == \"tts_online-onnx\":\n            from paddlespeech.server.engine.tts.online.onnx.tts_engine import PaddleTTSConnectionHandler\n            flag_online = True\n        else:\n            logger.error(\"Please check tte engine type.\")\n\n        try:\n            logger.debug(\"Start to warm up tts engine.\")\n            for i in range(warm_up_time):\n                connection_handler = PaddleTTSConnectionHandler(tts_engine)\n                if flag_online:\n                    for wav in connection_handler.infer(\n                            text=sentence,\n                            lang=tts_engine.lang,\n                            am=tts_engine.config.am):\n                        logger.debug(\n                            f\"The first response time of the {i} warm up: {connection_handler.first_response_time} s\"\n                        )\n                        break\n\n                else:\n                    st = time.time()\n                    connection_handler.infer(\n                        text=sentence,\n                        lang=tts_engine.lang,\n                        am=tts_engine.config.am)\n                    et = time.time()\n                    logger.debug(\n                        f\"The response time of the {i} warm up: {et - st} s\")\n        except Exception as e:\n            logger.error(\"Failed to warm up on tts engine.\")\n            logger.error(e)\n            return False\n\n    else:\n        pass\n\n    return True\n"
  },
  {
    "path": "paddlespeech/server/engine/text/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/text/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/text/python/text_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import OrderedDict\n\nimport paddle\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.text.infer import TextExecutor\nfrom paddlespeech.server.engine.base_engine import BaseEngine\n\n\nclass PaddleTextConnectionHandler:\n    def __init__(self, text_engine):\n        \"\"\"The PaddleSpeech Text Server Connection Handler\n           This connection process every server request\n        Args:\n            text_engine (TextEngine): The Text engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleTextConnectionHandler to process the text request\")\n        self.text_engine = text_engine\n        self.task = self.text_engine.executor.task\n        self.model = self.text_engine.executor.model\n        self.tokenizer = self.text_engine.executor.tokenizer\n        self._punc_list = self.text_engine.executor._punc_list\n        self._inputs = OrderedDict()\n        self._outputs = OrderedDict()\n\n    @paddle.no_grad()\n    def run(self, text):\n        \"\"\"The connection process the request text\n\n        Args:\n            text (str): the request text\n\n        Returns:\n            str: the punctuation text\n        \"\"\"\n        self.preprocess(text)\n        self.infer()\n        res = self.postprocess()\n\n        return res\n\n    @paddle.no_grad()\n    def preprocess(self, text):\n        \"\"\"\n            Input preprocess and return paddle.Tensor stored in self.input.\n            Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).\n\n        Args:\n            text (str): the request text\n        \"\"\"\n        if self.task == 'punc':\n            clean_text = self.text_engine.executor._clean_text(text)\n            assert len(clean_text) > 0, f'Invalid input string: {text}'\n\n            tokenized_input = self.tokenizer(\n                list(clean_text), return_length=True, is_split_into_words=True)\n\n            self._inputs['input_ids'] = tokenized_input['input_ids']\n            self._inputs['seg_ids'] = tokenized_input['token_type_ids']\n            self._inputs['seq_len'] = tokenized_input['seq_len']\n        else:\n            raise NotImplementedError\n\n    @paddle.no_grad()\n    def infer(self):\n        \"\"\"Model inference and result stored in self.output.\n        \"\"\"\n        if self.task == 'punc':\n            input_ids = paddle.to_tensor(self._inputs['input_ids']).unsqueeze(0)\n            seg_ids = paddle.to_tensor(self._inputs['seg_ids']).unsqueeze(0)\n            logits, _ = self.model(input_ids, seg_ids)\n            preds = paddle.argmax(logits, axis=-1).squeeze(0)\n\n            self._outputs['preds'] = preds\n        else:\n            raise NotImplementedError\n\n    def postprocess(self):\n        \"\"\"Output postprocess and return human-readable results such as texts and audio files.\n\n        Returns:\n            str: The punctuation text\n        \"\"\"\n        if self.task == 'punc':\n            input_ids = self._inputs['input_ids']\n            seq_len = self._inputs['seq_len']\n            preds = self._outputs['preds']\n\n            tokens = self.tokenizer.convert_ids_to_tokens(\n                input_ids[1:seq_len - 1])\n            labels = preds[1:seq_len - 1].tolist()\n            assert len(tokens) == len(labels)\n\n            text = ''\n            is_fast_model = 'fast' in self.text_engine.config.model_type\n            for t, l in zip(tokens, labels):\n                text += t\n                if l != 0:  # Non punc.\n                    if is_fast_model:\n                        text += self._punc_list[l - 1]\n                    else:\n                        text += self._punc_list[l]\n            return text\n        else:\n            raise NotImplementedError\n\n\nclass TextServerExecutor(TextExecutor):\n    def __init__(self):\n        \"\"\"The wrapper for TextEcutor\n        \"\"\"\n        super().__init__()\n        pass\n\n\nclass TextEngine(BaseEngine):\n    def __init__(self):\n        \"\"\"The Text Engine\n        \"\"\"\n        super(TextEngine, self).__init__()\n        logger.debug(\"Create the TextEngine Instance\")\n\n    def init(self, config: dict):\n        \"\"\"Init the Text Engine\n\n        Args:\n            config (dict): The server configuation\n\n        Returns:\n            bool: The engine instance flag\n        \"\"\"\n        logger.debug(\"Init the text engine\")\n        try:\n            self.config = config\n            if self.config.device:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n\n            paddle.set_device(self.device)\n            logger.debug(f\"Text Engine set the device: {self.device}\")\n        except BaseException as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize Text server engine Failed on device: %s.\" %\n                         (self.device))\n            return False\n\n        self.executor = TextServerExecutor()\n        if 'fast' in config.model_type:\n            self.executor._init_from_path_new(\n                task=config.task,\n                model_type=config.model_type,\n                lang=config.lang,\n                cfg_path=config.cfg_path,\n                ckpt_path=config.ckpt_path,\n                vocab_file=config.vocab_file)\n        else:\n            self.executor._init_from_path(\n                task=config.task,\n                model_type=config.model_type,\n                lang=config.lang,\n                cfg_path=config.cfg_path,\n                ckpt_path=config.ckpt_path,\n                vocab_file=config.vocab_file)\n        logger.info(\"Using model: %s.\" % (config.model_type))\n        logger.info(\"Initialize Text server engine successfully on device: %s.\"\n                    % (self.device))\n        return True\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/online/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/online/onnx/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/online/onnx/tts_engine.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport math\nimport os\nimport time\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.tts.infer import TTSExecutor\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.audio_process import float2pcm\nfrom paddlespeech.server.utils.onnx_infer import get_sess\nfrom paddlespeech.server.utils.util import denorm\nfrom paddlespeech.server.utils.util import get_chunks\nfrom paddlespeech.t2s.frontend.en_frontend import English\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\n__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']\n\n\nclass TTSServerExecutor(TTSExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(task='tts', model_format='onnx')\n\n    def _init_from_path(\n            self,\n            am: str='fastspeech2_csmsc_onnx',\n            am_ckpt: Optional[list]=None,\n            am_stat: Optional[os.PathLike]=None,\n            phones_dict: Optional[os.PathLike]=None,\n            tones_dict: Optional[os.PathLike]=None,\n            speaker_dict: Optional[os.PathLike]=None,\n            am_sample_rate: int=24000,\n            am_sess_conf: dict=None,\n            voc: str='mb_melgan_csmsc_onnx',\n            voc_ckpt: Optional[os.PathLike]=None,\n            voc_sample_rate: int=24000,\n            voc_sess_conf: dict=None,\n            lang: str='zh', ):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n\n        if (hasattr(self, 'am_sess') or\n            (hasattr(self, 'am_encoder_infer_sess') and\n             hasattr(self, 'am_decoder_sess') and hasattr(\n                 self, 'am_postnet_sess'))) and hasattr(self, 'voc_inference'):\n            logger.debug('Models had been initialized.')\n            return\n\n        # am\n        am_tag = am + '-' + lang\n        if am == \"fastspeech2_csmsc_onnx\":\n            # get model info\n            if am_ckpt is None or phones_dict is None:\n                self.task_resource.set_task_model(\n                    model_tag=am_tag,\n                    model_type=0,  # am\n                    version=None,  # default version\n                )\n                self.am_res_path = self.task_resource.res_dir\n                self.am_ckpt = os.path.join(self.am_res_path,\n                                            self.task_resource.res_dict['ckpt'])\n                # must have phones_dict in acoustic\n                self.phones_dict = os.path.join(\n                    self.am_res_path,\n                    self.task_resource.res_dict['phones_dict'])\n\n            else:\n                self.am_ckpt = os.path.abspath(am_ckpt[0])\n                self.phones_dict = os.path.abspath(phones_dict)\n                self.am_res_path = os.path.dirname(os.path.abspath(am_ckpt))\n\n            # create am sess\n            self.am_sess = get_sess(self.am_ckpt, am_sess_conf)\n\n        elif am == \"fastspeech2_cnndecoder_csmsc_onnx\":\n            if am_ckpt is None or am_stat is None or phones_dict is None:\n                self.task_resource.set_task_model(\n                    model_tag=am_tag,\n                    model_type=0,  # am\n                    version=None,  # default version\n                )\n                self.am_res_path = self.task_resource.res_dir\n                self.am_encoder_infer = os.path.join(\n                    self.am_res_path, self.task_resource.res_dict['ckpt'][0])\n                self.am_decoder = os.path.join(\n                    self.am_res_path, self.task_resource.res_dict['ckpt'][1])\n                self.am_postnet = os.path.join(\n                    self.am_res_path, self.task_resource.res_dict['ckpt'][2])\n                # must have phones_dict in acoustic\n                self.phones_dict = os.path.join(\n                    self.am_res_path,\n                    self.task_resource.res_dict['phones_dict'])\n                self.am_stat = os.path.join(\n                    self.am_res_path,\n                    self.task_resource.res_dict['speech_stats'])\n\n            else:\n                self.am_encoder_infer = os.path.abspath(am_ckpt[0])\n                self.am_decoder = os.path.abspath(am_ckpt[1])\n                self.am_postnet = os.path.abspath(am_ckpt[2])\n                self.phones_dict = os.path.abspath(phones_dict)\n                self.am_stat = os.path.abspath(am_stat)\n                self.am_res_path = os.path.dirname(os.path.abspath(am_ckpt[0]))\n\n            # create am sess\n            self.am_encoder_infer_sess = get_sess(self.am_encoder_infer,\n                                                  am_sess_conf)\n            self.am_decoder_sess = get_sess(self.am_decoder, am_sess_conf)\n            self.am_postnet_sess = get_sess(self.am_postnet, am_sess_conf)\n\n            self.am_mu, self.am_std = np.load(self.am_stat)\n\n        logger.debug(f\"self.phones_dict: {self.phones_dict}\")\n        logger.debug(f\"am model dir: {self.am_res_path}\")\n        logger.debug(\"Create am sess successfully.\")\n\n        # voc model info\n        voc_tag = voc + '-' + lang\n\n        if voc_ckpt is None:\n            self.task_resource.set_task_model(\n                model_tag=voc_tag,\n                model_type=1,  # vocoder\n                version=None,  # default version\n            )\n            self.voc_res_path = self.task_resource.voc_res_dir\n            self.voc_ckpt = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['ckpt'])\n        else:\n            self.voc_ckpt = os.path.abspath(voc_ckpt)\n            self.voc_res_path = os.path.dirname(os.path.abspath(self.voc_ckpt))\n        logger.debug(self.voc_res_path)\n\n        # create voc sess\n        self.voc_sess = get_sess(self.voc_ckpt, voc_sess_conf)\n        logger.debug(\"Create voc sess successfully.\")\n\n        with open(self.phones_dict, \"r\", encoding='utf-8') as f:\n            phn_id = [line.strip().split() for line in f.readlines()]\n        self.vocab_size = len(phn_id)\n        logger.debug(f\"vocab_size: {self.vocab_size}\")\n\n        # frontend\n        self.tones_dict = None\n        if lang == 'zh':\n            self.frontend = Frontend(\n                phone_vocab_path=self.phones_dict,\n                tone_vocab_path=self.tones_dict)\n\n        elif lang == 'en':\n            self.frontend = English(phone_vocab_path=self.phones_dict)\n        logger.debug(\"frontend done!\")\n\n\nclass TTSEngine(BaseEngine):\n    \"\"\"TTS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self, name=None):\n        \"\"\"Initialize TTS server engine\n        \"\"\"\n        super().__init__()\n\n    def init(self, config: dict) -> bool:\n        self.executor = TTSServerExecutor()\n        self.config = config\n        self.lang = self.config.lang\n        self.engine_type = \"online-onnx\"\n\n        self.am_block = self.config.am_block\n        self.am_pad = self.config.am_pad\n        self.voc_block = self.config.voc_block\n        self.voc_pad = self.config.voc_pad\n        self.am_upsample = 1\n        self.voc_upsample = self.config.voc_upsample\n\n        assert (\n            self.config.am == \"fastspeech2_csmsc_onnx\" or\n            self.config.am == \"fastspeech2_cnndecoder_csmsc_onnx\"\n        ) and (\n            self.config.voc == \"hifigan_csmsc_onnx\" or\n            self.config.voc == \"mb_melgan_csmsc_onnx\"\n        ), 'Please check config, am support: fastspeech2, voc support: hifigan_csmsc-zh or mb_melgan_csmsc.'\n\n        assert (\n            self.config.voc_block > 0 and self.config.voc_pad > 0\n        ), \"Please set correct voc_block and voc_pad, they should be more than 0.\"\n\n        assert (\n            self.config.voc_sample_rate == self.config.am_sample_rate\n        ), \"The sample rate of AM and Vocoder model are different, please check model.\"\n\n        self.sample_rate = self.config.voc_sample_rate\n\n        try:\n            if self.config.am_sess_conf.device is not None:\n                self.device = self.config.am_sess_conf.device\n            elif self.config.voc_sess_conf.device is not None:\n                self.device = self.config.voc_sess_conf.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                am=self.config.am,\n                am_ckpt=self.config.am_ckpt,\n                am_stat=self.config.am_stat,\n                phones_dict=self.config.phones_dict,\n                tones_dict=self.config.tones_dict,\n                speaker_dict=self.config.speaker_dict,\n                am_sample_rate=self.config.am_sample_rate,\n                am_sess_conf=self.config.am_sess_conf,\n                voc=self.config.voc,\n                voc_ckpt=self.config.voc_ckpt,\n                voc_sample_rate=self.config.voc_sample_rate,\n                voc_sess_conf=self.config.voc_sess_conf,\n                lang=self.config.lang)\n\n        except Exception as e:\n            logger.error(\"Failed to get model related files.\")\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.config.voc_sess_conf.device))\n            logger(e)\n            return False\n\n        logger.info(\"Initialize TTS server engine successfully on device: %s.\" %\n                    (self.config.voc_sess_conf.device))\n\n        return True\n\n\nclass PaddleTTSConnectionHandler:\n    def __init__(self, tts_engine):\n        \"\"\"The PaddleSpeech TTS Server Connection Handler\n           This connection process every tts server request\n        Args:\n            tts_engine (TTSEngine): The TTS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleTTSConnectionHandler to process the tts request\")\n\n        self.tts_engine = tts_engine\n        self.executor = self.tts_engine.executor\n        self.config = self.tts_engine.config\n        self.am_block = self.tts_engine.am_block\n        self.am_pad = self.tts_engine.am_pad\n        self.voc_block = self.tts_engine.voc_block\n        self.voc_pad = self.tts_engine.voc_pad\n        self.am_upsample = self.tts_engine.am_upsample\n        self.voc_upsample = self.tts_engine.voc_upsample\n\n    def depadding(self, data, chunk_num, chunk_id, block, pad, upsample):\n        \"\"\" \n        Streaming inference removes the result of pad inference\n        \"\"\"\n        front_pad = min(chunk_id * block, pad)\n        # first chunk\n        if chunk_id == 0:\n            data = data[:block * upsample]\n        # last chunk\n        elif chunk_id == chunk_num - 1:\n            data = data[front_pad * upsample:]\n        # middle chunk\n        else:\n            data = data[front_pad * upsample:(front_pad + block) * upsample]\n\n        return data\n\n    @paddle.no_grad()\n    def infer(\n            self,\n            text: str,\n            lang: str='zh',\n            am: str='fastspeech2_csmsc_onnx',\n            spk_id: int=0, ):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n\n        # first_flag 用于标记首包\n        first_flag = 1\n        get_tone_ids = False\n        merge_sentences = False\n\n        # front \n        frontend_st = time.time()\n        if lang == 'zh':\n            input_ids = self.executor.frontend.get_input_ids(\n                text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids)\n            phone_ids = input_ids[\"phone_ids\"]\n            if get_tone_ids:\n                tone_ids = input_ids[\"tone_ids\"]\n        elif lang == 'en':\n            input_ids = self.executor.frontend.get_input_ids(\n                text, merge_sentences=merge_sentences)\n            phone_ids = input_ids[\"phone_ids\"]\n        else:\n            logger.error(\"lang should in {'zh', 'en'}!\")\n        frontend_et = time.time()\n        self.frontend_time = frontend_et - frontend_st\n\n        for i in range(len(phone_ids)):\n            part_phone_ids = phone_ids[i].numpy()\n            voc_chunk_id = 0\n\n            # fastspeech2_csmsc\n            if am == \"fastspeech2_csmsc_onnx\":\n                # am \n                mel = self.executor.am_sess.run(\n                    output_names=None, input_feed={'text': part_phone_ids})\n                mel = mel[0]\n                if first_flag == 1:\n                    first_am_et = time.time()\n                    self.first_am_infer = first_am_et - frontend_et\n\n                # voc streaming\n                mel_chunks = get_chunks(mel, self.voc_block, self.voc_pad,\n                                        \"voc\")\n                voc_chunk_num = len(mel_chunks)\n                voc_st = time.time()\n                for i, mel_chunk in enumerate(mel_chunks):\n                    sub_wav = self.executor.voc_sess.run(\n                        output_names=None, input_feed={'logmel': mel_chunk})\n                    sub_wav = self.depadding(sub_wav[0], voc_chunk_num, i,\n                                             self.voc_block, self.voc_pad,\n                                             self.voc_upsample)\n                    if first_flag == 1:\n                        first_voc_et = time.time()\n                        self.first_voc_infer = first_voc_et - first_am_et\n                        self.first_response_time = first_voc_et - frontend_st\n                        first_flag = 0\n\n                    yield sub_wav\n\n            # fastspeech2_cnndecoder_csmsc \n            elif am == \"fastspeech2_cnndecoder_csmsc_onnx\":\n                # am \n                orig_hs = self.executor.am_encoder_infer_sess.run(\n                    None, input_feed={'text': part_phone_ids})\n                orig_hs = orig_hs[0]\n\n                # streaming voc chunk info\n                mel_len = orig_hs.shape[1]\n                voc_chunk_num = math.ceil(mel_len / self.voc_block)\n                start = 0\n                end = min(self.voc_block + self.voc_pad, mel_len)\n\n                # streaming am\n                hss = get_chunks(orig_hs, self.am_block, self.am_pad, \"am\")\n                am_chunk_num = len(hss)\n                for i, hs in enumerate(hss):\n                    am_decoder_output = self.executor.am_decoder_sess.run(\n                        None, input_feed={'xs': hs})\n                    am_postnet_output = self.executor.am_postnet_sess.run(\n                        None,\n                        input_feed={\n                            'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                        })\n                    am_output_data = am_decoder_output + np.transpose(\n                        am_postnet_output[0], (0, 2, 1))\n                    normalized_mel = am_output_data[0][0]\n\n                    sub_mel = denorm(normalized_mel, self.executor.am_mu,\n                                     self.executor.am_std)\n                    sub_mel = self.depadding(sub_mel, am_chunk_num, i,\n                                             self.am_block, self.am_pad,\n                                             self.am_upsample)\n\n                    if i == 0:\n                        mel_streaming = sub_mel\n                    else:\n                        mel_streaming = np.concatenate(\n                            (mel_streaming, sub_mel), axis=0)\n\n                    # streaming voc\n                    # 当流式AM推理的mel帧数大于流式voc推理的chunk size，开始进行流式voc 推理\n                    while (mel_streaming.shape[0] >= end and\n                           voc_chunk_id < voc_chunk_num):\n                        if first_flag == 1:\n                            first_am_et = time.time()\n                            self.first_am_infer = first_am_et - frontend_et\n                        voc_chunk = mel_streaming[start:end, :]\n\n                        sub_wav = self.executor.voc_sess.run(\n                            output_names=None, input_feed={'logmel': voc_chunk})\n                        sub_wav = self.depadding(\n                            sub_wav[0], voc_chunk_num, voc_chunk_id,\n                            self.voc_block, self.voc_pad, self.voc_upsample)\n                        if first_flag == 1:\n                            first_voc_et = time.time()\n                            self.first_voc_infer = first_voc_et - first_am_et\n                            self.first_response_time = first_voc_et - frontend_st\n                            first_flag = 0\n\n                        yield sub_wav\n\n                        voc_chunk_id += 1\n                        start = max(\n                            0, voc_chunk_id * self.voc_block - self.voc_pad)\n                        end = min(\n                            (voc_chunk_id + 1) * self.voc_block + self.voc_pad,\n                            mel_len)\n\n            else:\n                logger.error(\n                    \"Only support fastspeech2_csmsc or fastspeech2_cnndecoder_csmsc on streaming tts.\"\n                )\n\n        self.final_response_time = time.time() - frontend_st\n\n    def run(self, sentence: str, spk_id: int=0):\n        \"\"\" run include inference and postprocess.\n\n        Args:\n            sentence (str): text to be synthesized\n            spk_id (int, optional): speaker id for multi-speaker speech synthesis. Defaults to 0.\n            \n        Returns:\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n        wav_list = []\n\n        for wav in self.infer(\n                text=sentence,\n                lang=self.config.lang,\n                am=self.config.am,\n                spk_id=spk_id, ):\n\n            # wav type: <class 'numpy.ndarray'>  float32, convert to pcm (base64)\n            wav = float2pcm(wav)  # float32 to int16\n            wav_bytes = wav.tobytes()  # to bytes\n            wav_base64 = base64.b64encode(wav_bytes).decode('utf8')  # to base64\n            wav_list.append(wav)\n\n            yield wav_base64\n\n        wav_all = np.concatenate(wav_list, axis=0)\n        duration = len(wav_all) / self.tts_engine.sample_rate\n        logger.info(f\"sentence: {sentence}\")\n        logger.info(f\"The durations of audio is: {duration} s\")\n        logger.info(f\"first response time: {self.first_response_time} s\")\n        logger.info(f\"final response time: {self.final_response_time} s\")\n        logger.info(f\"RTF: {self.final_response_time / duration}\")\n        logger.info(\n            f\"Other info: front time: {self.frontend_time} s, first am infer time: {self.first_am_infer} s, first voc infer time: {self.first_voc_infer} s,\"\n        )\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/online/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/online/python/tts_engine.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport math\nimport os\nimport time\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.tts.infer import TTSExecutor\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.audio_process import float2pcm\nfrom paddlespeech.server.utils.util import denorm\nfrom paddlespeech.server.utils.util import get_chunks\nfrom paddlespeech.t2s.frontend.en_frontend import English\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']\n\n\nclass TTSServerExecutor(TTSExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='tts', model_format='dynamic', inference_mode='online')\n\n    def get_model_info(self,\n                       field: str,\n                       model_name: str,\n                       ckpt: Optional[os.PathLike],\n                       stat: Optional[os.PathLike]):\n        \"\"\"get model information\n\n        Args:\n            field (str): am or voc\n            model_name (str): model type, support fastspeech2, higigan, mb_melgan\n            ckpt (Optional[os.PathLike]): ckpt file\n            stat (Optional[os.PathLike]): stat file, including mean and standard deviation\n\n        Returns:\n            [module]: model module\n            [Tensor]: mean\n            [Tensor]: standard deviation\n        \"\"\"\n\n        model_class = self.task_resource.get_model_class(model_name)\n\n        if field == \"am\":\n            odim = self.am_config.n_mels\n            model = model_class(\n                idim=self.vocab_size, odim=odim, **self.am_config[\"model\"])\n            model.set_state_dict(paddle.load(ckpt)[\"main_params\"])\n\n        elif field == \"voc\":\n            model = model_class(**self.voc_config[\"generator_params\"])\n            model.set_state_dict(paddle.load(ckpt)[\"generator_params\"])\n            model.remove_weight_norm()\n\n        else:\n            logger.error(\"Please set correct field, am or voc\")\n\n        model.eval()\n        model_mu, model_std = np.load(stat)\n        model_mu = paddle.to_tensor(model_mu)\n        model_std = paddle.to_tensor(model_std)\n\n        return model, model_mu, model_std\n\n    def _init_from_path(\n            self,\n            am: str='fastspeech2_csmsc',\n            am_config: Optional[os.PathLike]=None,\n            am_ckpt: Optional[os.PathLike]=None,\n            am_stat: Optional[os.PathLike]=None,\n            phones_dict: Optional[os.PathLike]=None,\n            tones_dict: Optional[os.PathLike]=None,\n            speaker_dict: Optional[os.PathLike]=None,\n            voc: str='mb_melgan_csmsc',\n            voc_config: Optional[os.PathLike]=None,\n            voc_ckpt: Optional[os.PathLike]=None,\n            voc_stat: Optional[os.PathLike]=None,\n            lang: str='zh', ):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'am_inference') and hasattr(self, 'voc_inference'):\n            logger.debug('Models had been initialized.')\n            return\n        # am model info\n        if am_ckpt is None or am_config is None or am_stat is None or phones_dict is None:\n            use_pretrained_am = True\n        else:\n            use_pretrained_am = False\n\n        am_tag = am + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=am_tag,\n            model_type=0,  # am\n            skip_download=not use_pretrained_am,\n            version=None,  # default version\n        )\n        if use_pretrained_am:\n            self.am_res_path = self.task_resource.res_dir\n            self.am_config = os.path.join(self.am_res_path,\n                                          self.task_resource.res_dict['config'])\n            self.am_ckpt = os.path.join(self.am_res_path,\n                                        self.task_resource.res_dict['ckpt'])\n            self.am_stat = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['speech_stats'])\n            # must have phones_dict in acoustic\n            self.phones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['phones_dict'])\n            logger.debug(self.am_res_path)\n            logger.debug(self.am_config)\n            logger.debug(self.am_ckpt)\n        else:\n            self.am_config = os.path.abspath(am_config)\n            self.am_ckpt = os.path.abspath(am_ckpt)\n            self.am_stat = os.path.abspath(am_stat)\n            self.phones_dict = os.path.abspath(phones_dict)\n            self.am_res_path = os.path.dirname(os.path.abspath(self.am_config))\n\n        self.tones_dict = None\n        self.speaker_dict = None\n\n        # voc model info\n        if voc_ckpt is None or voc_config is None or voc_stat is None:\n            use_pretrained_voc = True\n        else:\n            use_pretrained_voc = False\n\n        voc_tag = voc + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=voc_tag,\n            model_type=1,  # vocoder\n            skip_download=not use_pretrained_voc,\n            version=None,  # default version\n        )\n        if use_pretrained_voc:\n            self.voc_res_path = self.task_resource.voc_res_dir\n            self.voc_config = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['config'])\n            self.voc_ckpt = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['ckpt'])\n            self.voc_stat = os.path.join(\n                self.voc_res_path,\n                self.task_resource.voc_res_dict['speech_stats'])\n            logger.debug(self.voc_res_path)\n            logger.debug(self.voc_config)\n            logger.debug(self.voc_ckpt)\n        else:\n            self.voc_config = os.path.abspath(voc_config)\n            self.voc_ckpt = os.path.abspath(voc_ckpt)\n            self.voc_stat = os.path.abspath(voc_stat)\n            self.voc_res_path = os.path.dirname(\n                os.path.abspath(self.voc_config))\n\n        # Init body.\n        with open(self.am_config) as f:\n            self.am_config = CfgNode(yaml.safe_load(f))\n        with open(self.voc_config) as f:\n            self.voc_config = CfgNode(yaml.safe_load(f))\n\n        with open(self.phones_dict, \"r\") as f:\n            phn_id = [line.strip().split() for line in f.readlines()]\n        self.vocab_size = len(phn_id)\n\n        # frontend\n        if lang == 'zh':\n            self.frontend = Frontend(\n                phone_vocab_path=self.phones_dict,\n                tone_vocab_path=self.tones_dict)\n\n        elif lang == 'en':\n            self.frontend = English(phone_vocab_path=self.phones_dict)\n\n        # am infer info\n        self.am_name = am[:am.rindex('_')]\n        if self.am_name == \"fastspeech2_cnndecoder\":\n            self.am_inference, self.am_mu, self.am_std = self.get_model_info(\n                \"am\", \"fastspeech2\", self.am_ckpt, self.am_stat)\n        else:\n            am, am_mu, am_std = self.get_model_info(\"am\", self.am_name,\n                                                    self.am_ckpt, self.am_stat)\n            am_normalizer = ZScore(am_mu, am_std)\n            am_inference_class = self.task_resource.get_model_class(\n                self.am_name + '_inference')\n            self.am_inference = am_inference_class(am_normalizer, am)\n            self.am_inference.eval()\n\n        # voc infer info\n        self.voc_name = voc[:voc.rindex('_')]\n        voc, voc_mu, voc_std = self.get_model_info(\"voc\", self.voc_name,\n                                                   self.voc_ckpt, self.voc_stat)\n        voc_normalizer = ZScore(voc_mu, voc_std)\n        voc_inference_class = self.task_resource.get_model_class(self.voc_name +\n                                                                 '_inference')\n        self.voc_inference = voc_inference_class(voc_normalizer, voc)\n        self.voc_inference.eval()\n\n\nclass TTSEngine(BaseEngine):\n    \"\"\"TTS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self, name=None):\n        \"\"\"Initialize TTS server engine\n        \"\"\"\n        super().__init__()\n\n    def init(self, config: dict) -> bool:\n        self.executor = TTSServerExecutor()\n        self.config = config\n        self.lang = self.config.lang\n        self.engine_type = \"online\"\n\n        assert (\n            config.am == \"fastspeech2_csmsc\" or\n            config.am == \"fastspeech2_cnndecoder_csmsc\"\n        ) and (\n            config.voc == \"hifigan_csmsc\" or config.voc == \"mb_melgan_csmsc\"\n        ), 'Please check config, am support: fastspeech2, voc support: hifigan_csmsc-zh or mb_melgan_csmsc.'\n\n        assert (\n            config.voc_block > 0 and config.voc_pad > 0\n        ), \"Please set correct voc_block and voc_pad, they should be more than 0.\"\n\n        try:\n            if self.config.device is not None:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                am=self.config.am,\n                am_config=self.config.am_config,\n                am_ckpt=self.config.am_ckpt,\n                am_stat=self.config.am_stat,\n                phones_dict=self.config.phones_dict,\n                tones_dict=self.config.tones_dict,\n                speaker_dict=self.config.speaker_dict,\n                voc=self.config.voc,\n                voc_config=self.config.voc_config,\n                voc_ckpt=self.config.voc_ckpt,\n                voc_stat=self.config.voc_stat,\n                lang=self.config.lang)\n        except Exception as e:\n            logger.error(\"Failed to get model related files.\")\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        assert (\n            self.executor.am_config.fs == self.executor.voc_config.fs\n        ), \"The sample rate of AM and Vocoder model are different, please check model.\"\n\n        self.sample_rate = self.executor.am_config.fs\n\n        self.am_block = self.config.am_block\n        self.am_pad = self.config.am_pad\n        self.voc_block = self.config.voc_block\n        self.voc_pad = self.config.voc_pad\n        self.am_upsample = 1\n        self.voc_upsample = self.executor.voc_config.n_shift\n\n        logger.info(\"Initialize TTS server engine successfully on device: %s.\" %\n                    (self.device))\n\n        return True\n\n\nclass PaddleTTSConnectionHandler:\n    def __init__(self, tts_engine):\n        \"\"\"The PaddleSpeech TTS Server Connection Handler\n           This connection process every tts server request\n        Args:\n            tts_engine (TTSEngine): The TTS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleTTSConnectionHandler to process the tts request\")\n\n        self.tts_engine = tts_engine\n        self.executor = self.tts_engine.executor\n        self.config = self.tts_engine.config\n        self.am_block = self.tts_engine.am_block\n        self.am_pad = self.tts_engine.am_pad\n        self.voc_block = self.tts_engine.voc_block\n        self.voc_pad = self.tts_engine.voc_pad\n        self.am_upsample = self.tts_engine.am_upsample\n        self.voc_upsample = self.tts_engine.voc_upsample\n\n    def depadding(self, data, chunk_num, chunk_id, block, pad, upsample):\n        \"\"\" \n        Streaming inference removes the result of pad inference\n        \"\"\"\n        front_pad = min(chunk_id * block, pad)\n        # first chunk\n        if chunk_id == 0:\n            data = data[:block * upsample]\n        # last chunk\n        elif chunk_id == chunk_num - 1:\n            data = data[front_pad * upsample:]\n        # middle chunk\n        else:\n            data = data[front_pad * upsample:(front_pad + block) * upsample]\n\n        return data\n\n    @paddle.no_grad()\n    def infer(\n            self,\n            text: str,\n            lang: str='zh',\n            am: str='fastspeech2_csmsc',\n            spk_id: int=0, ):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n\n        # first_flag 用于标记首包\n        first_flag = 1\n\n        get_tone_ids = False\n        merge_sentences = False\n        frontend_st = time.time()\n        if lang == 'zh':\n            input_ids = self.executor.frontend.get_input_ids(\n                text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids)\n            phone_ids = input_ids[\"phone_ids\"]\n            if get_tone_ids:\n                tone_ids = input_ids[\"tone_ids\"]\n        elif lang == 'en':\n            input_ids = self.executor.frontend.get_input_ids(\n                text, merge_sentences=merge_sentences)\n            phone_ids = input_ids[\"phone_ids\"]\n        else:\n            logger.error(\"lang should in {'zh', 'en'}!\")\n        frontend_et = time.time()\n        self.frontend_time = frontend_et - frontend_st\n\n        for i in range(len(phone_ids)):\n            part_phone_ids = phone_ids[i]\n            voc_chunk_id = 0\n\n            # fastspeech2_csmsc\n            if am == \"fastspeech2_csmsc\":\n                # am \n                mel = self.executor.am_inference(part_phone_ids)\n                if first_flag == 1:\n                    first_am_et = time.time()\n                    self.first_am_infer = first_am_et - frontend_et\n\n                # voc streaming\n                mel_chunks = get_chunks(mel, self.voc_block, self.voc_pad,\n                                        \"voc\")\n                voc_chunk_num = len(mel_chunks)\n                voc_st = time.time()\n                for i, mel_chunk in enumerate(mel_chunks):\n                    sub_wav = self.executor.voc_inference(mel_chunk)\n                    sub_wav = self.depadding(sub_wav, voc_chunk_num, i,\n                                             self.voc_block, self.voc_pad,\n                                             self.voc_upsample)\n                    if first_flag == 1:\n                        first_voc_et = time.time()\n                        self.first_voc_infer = first_voc_et - first_am_et\n                        self.first_response_time = first_voc_et - frontend_st\n                        first_flag = 0\n\n                    yield sub_wav\n\n            # fastspeech2_cnndecoder_csmsc \n            elif am == \"fastspeech2_cnndecoder_csmsc\":\n                # am \n                orig_hs = self.executor.am_inference.encoder_infer(\n                    part_phone_ids)\n\n                # streaming voc chunk info\n                mel_len = orig_hs.shape[1]\n                voc_chunk_num = math.ceil(mel_len / self.voc_block)\n                start = 0\n                end = min(self.voc_block + self.voc_pad, mel_len)\n\n                # streaming am\n                hss = get_chunks(orig_hs, self.am_block, self.am_pad, \"am\")\n                am_chunk_num = len(hss)\n                for i, hs in enumerate(hss):\n                    before_outs = self.executor.am_inference.decoder(hs)\n                    after_outs = before_outs + self.executor.am_inference.postnet(\n                        before_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n                    normalized_mel = after_outs[0]\n                    sub_mel = denorm(normalized_mel, self.executor.am_mu,\n                                     self.executor.am_std)\n                    sub_mel = self.depadding(sub_mel, am_chunk_num, i,\n                                             self.am_block, self.am_pad,\n                                             self.am_upsample)\n\n                    if i == 0:\n                        mel_streaming = sub_mel\n                    else:\n                        mel_streaming = np.concatenate(\n                            (mel_streaming, sub_mel), axis=0)\n\n                    # streaming voc\n                    # 当流式AM推理的mel帧数大于流式voc推理的chunk size，开始进行流式voc 推理\n                    while (mel_streaming.shape[0] >= end and\n                           voc_chunk_id < voc_chunk_num):\n                        if first_flag == 1:\n                            first_am_et = time.time()\n                            self.first_am_infer = first_am_et - frontend_et\n                        voc_chunk = mel_streaming[start:end, :]\n                        voc_chunk = paddle.to_tensor(voc_chunk)\n                        sub_wav = self.executor.voc_inference(voc_chunk)\n\n                        sub_wav = self.depadding(\n                            sub_wav, voc_chunk_num, voc_chunk_id,\n                            self.voc_block, self.voc_pad, self.voc_upsample)\n                        if first_flag == 1:\n                            first_voc_et = time.time()\n                            self.first_voc_infer = first_voc_et - first_am_et\n                            self.first_response_time = first_voc_et - frontend_st\n                            first_flag = 0\n\n                        yield sub_wav\n\n                        voc_chunk_id += 1\n                        start = max(\n                            0, voc_chunk_id * self.voc_block - self.voc_pad)\n                        end = min(\n                            (voc_chunk_id + 1) * self.voc_block + self.voc_pad,\n                            mel_len)\n\n            else:\n                logger.error(\n                    \"Only support fastspeech2_csmsc or fastspeech2_cnndecoder_csmsc on streaming tts.\"\n                )\n\n        self.final_response_time = time.time() - frontend_st\n\n    def run(\n            self,\n            sentence: str,\n            spk_id: int=0, ):\n        \"\"\" run include inference and postprocess.\n\n        Args:\n            sentence (str): text to be synthesized\n            spk_id (int, optional): speaker id for multi-speaker speech synthesis. Defaults to 0.\n\n        Returns:\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n\n        wav_list = []\n\n        for wav in self.infer(\n                text=sentence,\n                lang=self.config.lang,\n                am=self.config.am,\n                spk_id=spk_id, ):\n\n            # wav type: <class 'numpy.ndarray'>  float32, convert to pcm (base64)\n            wav = float2pcm(wav)  # float32 to int16\n            wav_bytes = wav.tobytes()  # to bytes\n            wav_base64 = base64.b64encode(wav_bytes).decode('utf8')  # to base64\n            wav_list.append(wav)\n\n            yield wav_base64\n\n        wav_all = np.concatenate(wav_list, axis=0)\n        duration = len(wav_all) / self.tts_engine.sample_rate\n\n        logger.info(f\"sentence: {sentence}\")\n        logger.info(f\"The durations of audio is: {duration} s\")\n        logger.info(f\"first response time: {self.first_response_time} s\")\n        logger.info(f\"final response time: {self.final_response_time} s\")\n        logger.info(f\"RTF: {self.final_response_time / duration}\")\n        logger.info(\n            f\"Other info: front time: {self.frontend_time} s, first am infer time: {self.first_am_infer} s, first voc infer time: {self.first_voc_infer} s,\"\n        )\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/paddleinference/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/paddleinference/tts_engine.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport io\nimport os\nimport sys\nimport time\nfrom typing import Optional\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile as sf\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.tts.infer import TTSExecutor\nfrom paddlespeech.resource import CommonTaskResource\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.audio_process import change_speed\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.exception import ServerBaseException\nfrom paddlespeech.server.utils.paddle_predictor import init_predictor\nfrom paddlespeech.server.utils.paddle_predictor import run_model\nfrom paddlespeech.t2s.frontend.en_frontend import English\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\n__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']\n\n\nclass TTSServerExecutor(TTSExecutor):\n    def __init__(self):\n        super().__init__()\n        self.task_resource = CommonTaskResource(\n            task='tts', model_format='static')\n\n    def _init_from_path(\n            self,\n            am: str='fastspeech2_csmsc',\n            am_model: Optional[os.PathLike]=None,\n            am_params: Optional[os.PathLike]=None,\n            am_sample_rate: int=24000,\n            phones_dict: Optional[os.PathLike]=None,\n            tones_dict: Optional[os.PathLike]=None,\n            speaker_dict: Optional[os.PathLike]=None,\n            voc: str='pwgan_csmsc',\n            voc_model: Optional[os.PathLike]=None,\n            voc_params: Optional[os.PathLike]=None,\n            voc_sample_rate: int=24000,\n            lang: str='zh',\n            am_predictor_conf: dict=None,\n            voc_predictor_conf: dict=None, ):\n        \"\"\"\n        Init model and other resources from a specific path.\n        \"\"\"\n        if hasattr(self, 'am_predictor') and hasattr(self, 'voc_predictor'):\n            logger.debug('Models had been initialized.')\n            return\n        # am\n        if am_model is None or am_params is None or phones_dict is None:\n            use_pretrained_am = True\n        else:\n            use_pretrained_am = False\n\n        am_tag = am + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=am_tag,\n            model_type=0,  # am\n            skip_download=not use_pretrained_am,\n            version=None,  # default version\n        )\n        if use_pretrained_am:\n            self.am_res_path = self.task_resource.res_dir\n            self.am_model = os.path.join(self.am_res_path,\n                                         self.task_resource.res_dict['model'])\n            self.am_params = os.path.join(self.am_res_path,\n                                          self.task_resource.res_dict['params'])\n            # must have phones_dict in acoustic\n            self.phones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['phones_dict'])\n            self.am_sample_rate = self.task_resource.res_dict['sample_rate']\n\n            logger.debug(self.am_res_path)\n            logger.debug(self.am_model)\n            logger.debug(self.am_params)\n        else:\n            self.am_model = os.path.abspath(am_model)\n            self.am_params = os.path.abspath(am_params)\n            self.phones_dict = os.path.abspath(phones_dict)\n            self.am_sample_rate = am_sample_rate\n            self.am_res_path = os.path.dirname(os.path.abspath(self.am_model))\n        logger.debug(\"self.phones_dict: {}\".format(self.phones_dict))\n\n        # for speedyspeech\n        self.tones_dict = None\n        if 'tones_dict' in self.task_resource.res_dict:\n            self.tones_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['tones_dict'])\n            if tones_dict:\n                self.tones_dict = tones_dict\n\n        # for multi speaker fastspeech2\n        self.speaker_dict = None\n        if 'speaker_dict' in self.task_resource.res_dict:\n            self.speaker_dict = os.path.join(\n                self.am_res_path, self.task_resource.res_dict['speaker_dict'])\n            if speaker_dict:\n                self.speaker_dict = speaker_dict\n\n        # voc\n        if voc_model is None or voc_params is None:\n            use_pretrained_voc = True\n        else:\n            use_pretrained_voc = False\n\n        voc_tag = voc + '-' + lang\n        self.task_resource.set_task_model(\n            model_tag=voc_tag,\n            model_type=1,  # vocoder\n            skip_download=not use_pretrained_voc,\n            version=None,  # default version\n        )\n        if use_pretrained_voc:\n            self.voc_res_path = self.task_resource.voc_res_dir\n            self.voc_model = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['model'])\n            self.voc_params = os.path.join(\n                self.voc_res_path, self.task_resource.voc_res_dict['params'])\n            self.voc_sample_rate = self.task_resource.voc_res_dict[\n                'sample_rate']\n            logger.debug(self.voc_res_path)\n            logger.debug(self.voc_model)\n            logger.debug(self.voc_params)\n        else:\n            self.voc_model = os.path.abspath(voc_model)\n            self.voc_params = os.path.abspath(voc_params)\n            self.voc_sample_rate = voc_sample_rate\n            self.voc_res_path = os.path.dirname(os.path.abspath(self.voc_model))\n\n        assert (\n            self.voc_sample_rate == self.am_sample_rate\n        ), \"The sample rate of AM and Vocoder model are different, please check model.\"\n\n        # Init body.\n        with open(self.phones_dict, \"r\") as f:\n            phn_id = [line.strip().split() for line in f.readlines()]\n        vocab_size = len(phn_id)\n        logger.debug(\"vocab_size: {}\".format(vocab_size))\n\n        tone_size = None\n        if self.tones_dict:\n            with open(self.tones_dict, \"r\") as f:\n                tone_id = [line.strip().split() for line in f.readlines()]\n            tone_size = len(tone_id)\n            logger.debug(\"tone_size: {}\".format(tone_size))\n\n        spk_num = None\n        if self.speaker_dict:\n            with open(self.speaker_dict, 'rt') as f:\n                spk_id = [line.strip().split() for line in f.readlines()]\n            spk_num = len(spk_id)\n            logger.debug(\"spk_num: {}\".format(spk_num))\n\n        # frontend\n        if lang == 'zh':\n            self.frontend = Frontend(\n                phone_vocab_path=self.phones_dict,\n                tone_vocab_path=self.tones_dict)\n\n        elif lang == 'en':\n            self.frontend = English(phone_vocab_path=self.phones_dict)\n        logger.debug(\"frontend done!\")\n\n        # Create am predictor\n        self.am_predictor_conf = am_predictor_conf\n        self.am_predictor = init_predictor(\n            model_file=self.am_model,\n            params_file=self.am_params,\n            predictor_conf=self.am_predictor_conf)\n        logger.debug(\"Create AM predictor successfully.\")\n\n        # Create voc predictor\n        self.voc_predictor_conf = voc_predictor_conf\n        self.voc_predictor = init_predictor(\n            model_file=self.voc_model,\n            params_file=self.voc_params,\n            predictor_conf=self.voc_predictor_conf)\n        logger.debug(\"Create Vocoder predictor successfully.\")\n\n    @paddle.no_grad()\n    def infer(self,\n              text: str,\n              lang: str='zh',\n              am: str='fastspeech2_csmsc',\n              spk_id: int=0):\n        \"\"\"\n        Model inference and result stored in self.output.\n        \"\"\"\n        am_name = am[:am.rindex('_')]\n        am_dataset = am[am.rindex('_') + 1:]\n        get_tone_ids = False\n        merge_sentences = False\n        frontend_st = time.time()\n        if am_name == 'speedyspeech':\n            get_tone_ids = True\n        if lang == 'zh':\n            input_ids = self.frontend.get_input_ids(\n                text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids)\n            phone_ids = input_ids[\"phone_ids\"]\n            if get_tone_ids:\n                tone_ids = input_ids[\"tone_ids\"]\n        elif lang == 'en':\n            input_ids = self.frontend.get_input_ids(\n                text, merge_sentences=merge_sentences)\n            phone_ids = input_ids[\"phone_ids\"]\n        else:\n            logger.error(\"lang should in {'zh', 'en'}!\")\n        self.frontend_time = time.time() - frontend_st\n\n        self.am_time = 0\n        self.voc_time = 0\n        flags = 0\n        for i in range(len(phone_ids)):\n            am_st = time.time()\n            part_phone_ids = phone_ids[i]\n            # am\n            if am_name == 'speedyspeech':\n                part_tone_ids = tone_ids[i]\n                am_result = run_model(\n                    self.am_predictor,\n                    [part_phone_ids.numpy(), part_tone_ids.numpy()])\n                mel = am_result[0]\n\n            # fastspeech2\n            else:\n                # multi speaker  do not have static model\n                if am_dataset in {\"aishell3\", \"vctk\"}:\n                    am_result = run_model(\n                        self.am_predictor,\n                        [part_phone_ids.numpy(), np.array([spk_id])])\n                else:\n                    am_result = run_model(self.am_predictor,\n                                          [part_phone_ids.numpy()])\n                mel = am_result[0]\n            self.am_time += (time.time() - am_st)\n\n            # voc\n            voc_st = time.time()\n            voc_result = run_model(self.voc_predictor, [mel])\n            wav = voc_result[0]\n            wav = paddle.to_tensor(wav)\n\n            if flags == 0:\n                wav_all = wav\n                flags = 1\n            else:\n                wav_all = paddle.concat([wav_all, wav])\n            self.voc_time += (time.time() - voc_st)\n        self._outputs[\"wav\"] = wav_all\n\n\nclass TTSEngine(BaseEngine):\n    \"\"\"TTS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize TTS server engine\n        \"\"\"\n        super(TTSEngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        self.executor = TTSServerExecutor()\n        self.config = config\n        self.lang = self.config.lang\n        self.engine_type = \"inference\"\n\n        try:\n            if self.config.am_predictor_conf.device is not None:\n                self.device = self.config.am_predictor_conf.device\n            elif self.config.voc_predictor_conf.device is not None:\n                self.device = self.config.voc_predictor_conf.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                am=self.config.am,\n                am_model=self.config.am_model,\n                am_params=self.config.am_params,\n                am_sample_rate=self.config.am_sample_rate,\n                phones_dict=self.config.phones_dict,\n                tones_dict=self.config.tones_dict,\n                speaker_dict=self.config.speaker_dict,\n                voc=self.config.voc,\n                voc_model=self.config.voc_model,\n                voc_params=self.config.voc_params,\n                voc_sample_rate=self.config.voc_sample_rate,\n                lang=self.config.lang,\n                am_predictor_conf=self.config.am_predictor_conf,\n                voc_predictor_conf=self.config.voc_predictor_conf, )\n        except Exception as e:\n            logger.error(\"Failed to get model related files.\")\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        logger.info(\"Initialize TTS server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n\nclass PaddleTTSConnectionHandler(TTSServerExecutor):\n    def __init__(self, tts_engine):\n        \"\"\"The PaddleSpeech TTS Server Connection Handler\n           This connection process every tts server request\n        Args:\n            tts_engine (TTSEngine): The TTS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleTTSConnectionHandler to process the tts request\")\n\n        self.tts_engine = tts_engine\n        self.executor = self.tts_engine.executor\n        self.config = self.tts_engine.config\n        self.frontend = self.executor.frontend\n        self.am_predictor = self.executor.am_predictor\n        self.voc_predictor = self.executor.voc_predictor\n\n    def postprocess(self,\n                    wav,\n                    original_fs: int,\n                    target_fs: int=0,\n                    volume: float=1.0,\n                    speed: float=1.0,\n                    audio_path: str=None):\n        \"\"\"Post-processing operations, including speech, volume, sample rate, save audio file\n\n        Args:\n            wav (numpy(float)): Synthesized audio sample points\n            original_fs (int): original audio sample rate\n            target_fs (int): target audio sample rate\n            volume (float): target volume\n            speed (float): target speed\n\n        Raises:\n            ServerBaseException: Throws an exception if the change speed unsuccessfully.\n\n        Returns:\n            target_fs: target sample rate for synthesized audio.\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n\n        # transform sample_rate\n        if target_fs == 0 or target_fs > original_fs:\n            target_fs = original_fs\n            wav_tar_fs = wav\n            logger.debug(\n                \"The sample rate of synthesized audio is the same as model, which is {}Hz\".\n                format(original_fs))\n        else:\n            wav_tar_fs = librosa.resample(\n                np.squeeze(wav), original_fs, target_fs)\n            logger.debug(\n                \"The sample rate of model is {}Hz and the target sample rate is {}Hz. Converting the sample rate of the synthesized audio successfully.\".\n                format(original_fs, target_fs))\n        # transform volume\n        wav_vol = wav_tar_fs * volume\n        logger.debug(\"Transform the volume of the audio successfully.\")\n\n        # transform speed\n        try:  # windows not support soxbindings\n            wav_speed = change_speed(wav_vol, speed, target_fs)\n            logger.debug(\"Transform the speed of the audio successfully.\")\n        except ServerBaseException:\n            raise ServerBaseException(\n                ErrorCode.SERVER_INTERNAL_ERR,\n                \"Failed to transform speed. Can not install soxbindings on your system. \\\n                 You need to set speed value 1.0.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"Failed to transform speed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        # wav to base64\n        buf = io.BytesIO()\n        sf.write(buf, wav_speed, target_fs, format=\"wav\")\n        buf.seek(0)\n        base64_bytes = base64.b64encode(buf.read())\n        wav_base64 = base64_bytes.decode('utf-8')\n        logger.debug(\"Audio to string successfully.\")\n\n        # save audio\n        if audio_path is not None:\n            if audio_path.endswith(\".wav\"):\n                sf.write(audio_path, wav_speed, target_fs)\n            elif audio_path.endswith(\".pcm\"):\n                wav_norm = wav_speed * (32767 / max(0.001,\n                                                    np.max(np.abs(wav_speed))))\n                with open(audio_path, \"wb\") as f:\n                    f.write(wav_norm.astype(np.int16))\n            logger.info(\"Save audio to {} successfully.\".format(audio_path))\n        else:\n            logger.info(\"There is no need to save audio.\")\n\n        return target_fs, wav_base64\n\n    def run(self,\n            sentence: str,\n            spk_id: int=0,\n            speed: float=1.0,\n            volume: float=1.0,\n            sample_rate: int=0,\n            save_path: str=None):\n        \"\"\"get the result of the server response\n\n        Args:\n            sentence (str): sentence to be synthesized\n            spk_id (int, optional): speaker id. Defaults to 0.\n            speed (float, optional): audio speed, 0 < speed <=3.0. Defaults to 1.0.\n            volume (float, optional): The volume relative to the audio synthesized by the model, \n            0 < volume <=3.0. Defaults to 1.0.\n            sample_rate (int, optional): Set the sample rate of the synthesized audio. \n            0 represents the sample rate for model synthesis. Defaults to 0.\n            save_path (str, optional): The save path of the synthesized audio. Defaults to None.\n\n        Raises:\n            ServerBaseException: Throws an exception if tts inference unsuccessfully.\n            ServerBaseException: Throws an exception if postprocess unsuccessfully.\n\n        Returns:\n            lang: model language \n            target_sample_rate: target sample rate for synthesized audio.\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n\n        lang = self.config.lang\n\n        try:\n            infer_st = time.time()\n            self.infer(\n                text=sentence, lang=lang, am=self.config.am, spk_id=spk_id)\n            infer_et = time.time()\n            infer_time = infer_et - infer_st\n\n        except ServerBaseException:\n            raise ServerBaseException(ErrorCode.SERVER_INTERNAL_ERR,\n                                      \"tts infer failed.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"tts infer failed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        try:\n            postprocess_st = time.time()\n            target_sample_rate, wav_base64 = self.postprocess(\n                wav=self._outputs[\"wav\"].numpy(),\n                original_fs=self.executor.am_sample_rate,\n                target_fs=sample_rate,\n                volume=volume,\n                speed=speed,\n                audio_path=save_path)\n            postprocess_et = time.time()\n            postprocess_time = postprocess_et - postprocess_st\n            duration = len(\n                self._outputs[\"wav\"].numpy()) / self.executor.am_sample_rate\n            rtf = infer_time / duration\n\n        except ServerBaseException:\n            raise ServerBaseException(ErrorCode.SERVER_INTERNAL_ERR,\n                                      \"tts postprocess failed.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"tts postprocess failed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        logger.debug(\"AM model: {}\".format(self.config.am))\n        logger.debug(\"Vocoder model: {}\".format(self.config.voc))\n        logger.debug(\"Language: {}\".format(lang))\n        logger.info(\"tts engine type: python\")\n\n        logger.info(\"audio duration: {}\".format(duration))\n        logger.debug(\"frontend inference time: {}\".format(self.frontend_time))\n        logger.debug(\"AM inference time: {}\".format(self.am_time))\n        logger.debug(\"Vocoder inference time: {}\".format(self.voc_time))\n        logger.info(\"total inference time: {}\".format(infer_time))\n        logger.info(\n            \"postprocess (change speed, volume, target sample rate) time: {}\".\n            format(postprocess_time))\n        logger.info(\"total generate audio time: {}\".format(infer_time +\n                                                           postprocess_time))\n        logger.info(\"RTF: {}\".format(rtf))\n        logger.debug(\"device: {}\".format(self.tts_engine.device))\n\n        return lang, target_sample_rate, duration, wav_base64\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/tts/python/tts_engine.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport io\nimport sys\nimport time\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile as sf\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.tts.infer import TTSExecutor\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.server.utils.audio_process import change_speed\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.exception import ServerBaseException\n\n__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']\n\n\nclass TTSServerExecutor(TTSExecutor):\n    def __init__(self):\n        super().__init__()\n        pass\n\n\nclass TTSEngine(BaseEngine):\n    \"\"\"TTS server engine\n\n    Args:\n        metaclass: Defaults to Singleton.\n    \"\"\"\n\n    def __init__(self, name=None):\n        \"\"\"Initialize TTS server engine\n        \"\"\"\n        super(TTSEngine, self).__init__()\n\n    def init(self, config: dict) -> bool:\n        self.executor = TTSServerExecutor()\n        self.config = config\n        self.lang = self.config.lang\n        self.engine_type = \"python\"\n\n        try:\n            if self.config.device is not None:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n            paddle.set_device(self.device)\n        except Exception as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        try:\n            self.executor._init_from_path(\n                am=self.config.am,\n                am_config=self.config.am_config,\n                am_ckpt=self.config.am_ckpt,\n                am_stat=self.config.am_stat,\n                phones_dict=self.config.phones_dict,\n                tones_dict=self.config.tones_dict,\n                speaker_dict=self.config.speaker_dict,\n                voc=self.config.voc,\n                voc_config=self.config.voc_config,\n                voc_ckpt=self.config.voc_ckpt,\n                voc_stat=self.config.voc_stat,\n                lang=self.config.lang)\n        except Exception as e:\n            logger.error(\"Failed to get model related files.\")\n            logger.error(\"Initialize TTS server engine Failed on device: %s.\" %\n                         (self.device))\n            logger.error(e)\n            return False\n\n        logger.info(\"Initialize TTS server engine successfully on device: %s.\" %\n                    (self.device))\n        return True\n\n\nclass PaddleTTSConnectionHandler(TTSServerExecutor):\n    def __init__(self, tts_engine):\n        \"\"\"The PaddleSpeech TTS Server Connection Handler\n           This connection process every tts server request\n        Args:\n            tts_engine (TTSEngine): The TTS engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleTTSConnectionHandler to process the tts request\")\n\n        self.tts_engine = tts_engine\n        self.executor = self.tts_engine.executor\n        self.config = self.tts_engine.config\n        self.frontend = self.executor.frontend\n        self.am_inference = self.executor.am_inference\n        self.voc_inference = self.executor.voc_inference\n\n    def postprocess(self,\n                    wav,\n                    original_fs: int,\n                    target_fs: int=0,\n                    volume: float=1.0,\n                    speed: float=1.0,\n                    audio_path: str=None):\n        \"\"\"Post-processing operations, including speech, volume, sample rate, save audio file\n\n        Args:\n            wav (numpy(float)): Synthesized audio sample points\n            original_fs (int): original audio sample rate\n            target_fs (int): target audio sample rate\n            volume (float): target volume\n            speed (float): target speed\n\n        Raises:\n            ServerBaseException: Throws an exception if the change speed unsuccessfully.\n\n        Returns:\n            target_fs: target sample rate for synthesized audio.\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n\n        # transform sample_rate\n        if target_fs == 0 or target_fs > original_fs:\n            target_fs = original_fs\n            wav_tar_fs = wav\n            logger.debug(\n                \"The sample rate of synthesized audio is the same as model, which is {}Hz\".\n                format(original_fs))\n        else:\n            wav_tar_fs = librosa.resample(\n                np.squeeze(wav), orig_sr=original_fs, target_sr=target_fs)\n            logger.debug(\n                \"The sample rate of model is {}Hz and the target sample rate is {}Hz. Converting the sample rate of the synthesized audio successfully.\".\n                format(original_fs, target_fs))\n        # transform volume\n        wav_vol = wav_tar_fs * volume\n        logger.debug(\"Transform the volume of the audio successfully.\")\n\n        # transform speed\n        try:  # windows not support soxbindings\n            wav_speed = change_speed(wav_vol, speed, target_fs)\n            logger.debug(\"Transform the speed of the audio successfully.\")\n        except ServerBaseException:\n            raise ServerBaseException(\n                ErrorCode.SERVER_INTERNAL_ERR,\n                \"Failed to transform speed. Can not install soxbindings on your system. \\\n                 You need to set speed value 1.0.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"Failed to transform speed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        # wav to base64\n        buf = io.BytesIO()\n        sf.write(buf, wav_speed, target_fs, format=\"wav\")\n        buf.seek(0)\n\n        base64_bytes = base64.b64encode(buf.read())\n        wav_base64 = base64_bytes.decode('utf-8')\n        logger.debug(\"Audio to string successfully.\")\n\n        # save audio\n        if audio_path is not None:\n            if audio_path.endswith(\".wav\"):\n                sf.write(audio_path, wav_speed, target_fs)\n            elif audio_path.endswith(\".pcm\"):\n                wav_norm = wav_speed * (32767 / max(0.001,\n                                                    np.max(np.abs(wav_speed))))\n                with open(audio_path, \"wb\") as f:\n                    f.write(wav_norm.astype(np.int16))\n            logger.info(\"Save audio to {} successfully.\".format(audio_path))\n        else:\n            logger.info(\"There is no need to save audio.\")\n\n        return target_fs, wav_base64\n\n    def run(self,\n            sentence: str,\n            spk_id: int=0,\n            speed: float=1.0,\n            volume: float=1.0,\n            sample_rate: int=0,\n            save_path: str=None):\n        \"\"\" run include inference and postprocess.\n\n        Args:\n            sentence (str): text to be synthesized\n            spk_id (int, optional): speaker id for multi-speaker speech synthesis. Defaults to 0.\n            speed (float, optional): speed. Defaults to 1.0.\n            volume (float, optional): volume. Defaults to 1.0.\n            sample_rate (int, optional): target sample rate for synthesized audio, \n            0 means the same as the model sampling rate. Defaults to 0.\n            save_path (str, optional): The save path of the synthesized audio. \n            None means do not save audio. Defaults to None.\n\n        Raises:\n            ServerBaseException: Throws an exception if tts inference unsuccessfully.\n            ServerBaseException: Throws an exception if postprocess unsuccessfully.\n\n        Returns:\n            lang: model language \n            target_sample_rate: target sample rate for synthesized audio.\n            wav_base64: The base64 format of the synthesized audio.\n        \"\"\"\n\n        lang = self.config.lang\n\n        try:\n            infer_st = time.time()\n            self.infer(\n                text=sentence, lang=lang, am=self.config.am, spk_id=spk_id)\n            infer_et = time.time()\n            infer_time = infer_et - infer_st\n            duration = len(\n                self._outputs[\"wav\"].numpy()) / self.executor.am_config.fs\n            rtf = infer_time / duration\n\n        except ServerBaseException:\n            raise ServerBaseException(ErrorCode.SERVER_INTERNAL_ERR,\n                                      \"tts infer failed.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"tts infer failed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        try:\n            postprocess_st = time.time()\n            target_sample_rate, wav_base64 = self.postprocess(\n                wav=self._outputs[\"wav\"].numpy(),\n                original_fs=self.executor.am_config.fs,\n                target_fs=sample_rate,\n                volume=volume,\n                speed=speed,\n                audio_path=save_path)\n            postprocess_et = time.time()\n            postprocess_time = postprocess_et - postprocess_st\n\n        except ServerBaseException:\n            raise ServerBaseException(ErrorCode.SERVER_INTERNAL_ERR,\n                                      \"tts postprocess failed.\")\n            sys.exit(-1)\n        except Exception as e:\n            logger.error(\"tts postprocess failed.\")\n            logger.error(e)\n            sys.exit(-1)\n\n        logger.debug(\"AM model: {}\".format(self.config.am))\n        logger.debug(\"Vocoder model: {}\".format(self.config.voc))\n        logger.debug(\"Language: {}\".format(lang))\n        logger.info(\"tts engine type: python\")\n\n        logger.info(\"audio duration: {}\".format(duration))\n        logger.debug(\"frontend inference time: {}\".format(self.frontend_time))\n        logger.debug(\"AM inference time: {}\".format(self.am_time))\n        logger.debug(\"Vocoder inference time: {}\".format(self.voc_time))\n        logger.info(\"total inference time: {}\".format(infer_time))\n        logger.info(\n            \"postprocess (change speed, volume, target sample rate) time: {}\".\n            format(postprocess_time))\n        logger.info(\"total generate audio time: {}\".format(infer_time +\n                                                           postprocess_time))\n        logger.info(\"RTF: {}\".format(rtf))\n        logger.debug(\"device: {}\".format(self.tts_engine.device))\n\n        return lang, target_sample_rate, duration, wav_base64\n"
  },
  {
    "path": "paddlespeech/server/engine/vector/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/vector/python/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/engine/vector/python/vector_engine.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport io\nfrom collections import OrderedDict\n\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.cli.vector.infer import VectorExecutor\nfrom paddlespeech.server.engine.base_engine import BaseEngine\nfrom paddlespeech.vector.io.batch import feature_normalize\n\n\nclass PaddleVectorConnectionHandler:\n    def __init__(self, vector_engine):\n        \"\"\"The PaddleSpeech Vector Server Connection Handler\n           This connection process every server request\n        Args:\n            vector_engine (VectorEngine): The Vector engine\n        \"\"\"\n        super().__init__()\n        logger.debug(\n            \"Create PaddleVectorConnectionHandler to process the vector request\")\n        self.vector_engine = vector_engine\n        self.executor = self.vector_engine.executor\n        self.task = self.vector_engine.executor.task\n        self.model = self.vector_engine.executor.model\n        self.config = self.vector_engine.executor.config\n\n        self._inputs = OrderedDict()\n        self._outputs = OrderedDict()\n\n    @paddle.no_grad()\n    def run(self, audio_data, task=\"spk\"):\n        \"\"\"The connection process the http request audio\n\n        Args:\n            audio_data (bytes): base64.b64decode\n\n        Returns:\n            str: the punctuation text\n        \"\"\"\n        logger.debug(\n            f\"start to extract the do vector {self.task} from the http request\")\n        if self.task == \"spk\" and task == \"spk\":\n            embedding = self.extract_audio_embedding(audio_data)\n            return embedding\n        else:\n            logger.error(\n                \"The request task is not matched with server model task\")\n            logger.error(\n                f\"The server model task is: {self.task}, but the request task is: {task}\"\n            )\n\n        return np.array([\n            0.0,\n        ])\n\n    @paddle.no_grad()\n    def get_enroll_test_score(self, enroll_audio, test_audio):\n        \"\"\"Get the enroll and test audio score\n\n        Args:\n            enroll_audio (str): the base64 format enroll audio\n            test_audio (str): the base64 format test audio\n\n        Returns:\n            float: the score between enroll and test audio\n        \"\"\"\n        logger.debug(\"start to extract the enroll audio embedding\")\n        enroll_emb = self.extract_audio_embedding(enroll_audio)\n\n        logger.debug(\"start to extract the test audio embedding\")\n        test_emb = self.extract_audio_embedding(test_audio)\n\n        logger.debug(\n            \"start to get the score between the enroll and test embedding\")\n        score = self.executor.get_embeddings_score(enroll_emb, test_emb)\n\n        logger.debug(f\"get the enroll vs test score: {score}\")\n        return score\n\n    @paddle.no_grad()\n    def extract_audio_embedding(self, audio: str, sample_rate: int=16000):\n        \"\"\"extract the audio embedding\n\n        Args:\n            audio (str): the audio data\n            sample_rate (int, optional): the audio sample rate. Defaults to 16000.\n        \"\"\"\n        # we can not reuse the cache io.BytesIO(audio) data, \n        # because the soundfile will change the io.BytesIO(audio) to the end\n        # thus we should convert the base64 string to io.BytesIO when we need the audio data\n        if not self.executor._check(\n                io.BytesIO(audio), sample_rate, force_yes=True):\n            logger.debug(\"check the audio sample rate occurs error\")\n            return np.array([0.0])\n\n        waveform, sr = load_audio(io.BytesIO(audio))\n        logger.debug(\n            f\"load the audio sample points, shape is: {waveform.shape}\")\n\n        # stage 2: get the audio feat\n        # Note: Now we only support fbank feature\n        try:\n            feats = melspectrogram(\n                x=waveform,\n                sr=self.config.sr,\n                n_mels=self.config.n_mels,\n                window_size=self.config.window_size,\n                hop_length=self.config.hop_size)\n            logger.debug(f\"extract the audio feats, shape is: {feats.shape}\")\n        except Exception as e:\n            logger.error(f\"feats occurs exception {e}\")\n            sys.exit(-1)\n\n        feats = paddle.to_tensor(feats).unsqueeze(0)\n        # in inference period, the lengths is all one without padding\n        lengths = paddle.ones([1])\n\n        # stage 3: we do feature normalize,\n        #          Now we assume that the feats must do normalize\n        feats = feature_normalize(feats, mean_norm=True, std_norm=False)\n\n        # stage 4: store the feats and length in the _inputs,\n        #          which will be used in other function\n        logger.info(f\"feats shape: {feats.shape}\")\n        logger.info(\"audio extract the feats success\")\n\n        logger.info(\"start to extract the audio embedding\")\n        embedding = self.model.backbone(feats, lengths).squeeze().numpy()\n        logger.info(f\"embedding size: {embedding.shape}\")\n\n        return embedding\n\n\nclass VectorServerExecutor(VectorExecutor):\n    def __init__(self):\n        \"\"\"The wrapper for TextEcutor\n        \"\"\"\n        super().__init__()\n        pass\n\n\nclass VectorEngine(BaseEngine):\n    def __init__(self):\n        \"\"\"The Vector Engine\n        \"\"\"\n        super(VectorEngine, self).__init__()\n        logger.debug(\"Create the VectorEngine Instance\")\n\n    def init(self, config: dict):\n        \"\"\"Init the Vector Engine\n\n        Args:\n            config (dict): The server configuation\n\n        Returns:\n            bool: The engine instance flag\n        \"\"\"\n        logger.debug(\"Init the vector engine\")\n        try:\n            self.config = config\n            if self.config.device:\n                self.device = self.config.device\n            else:\n                self.device = paddle.get_device()\n\n            paddle.set_device(self.device)\n            logger.debug(f\"Vector Engine set the device: {self.device}\")\n        except BaseException as e:\n            logger.error(\n                \"Set device failed, please check if device is already used and the parameter 'device' in the yaml file\"\n            )\n            logger.error(\"Initialize Vector server engine Failed on device: %s.\"\n                         % (self.device))\n            return False\n\n        self.executor = VectorServerExecutor()\n\n        self.executor._init_from_path(\n            model_type=config.model_type,\n            cfg_path=config.cfg_path,\n            ckpt_path=config.ckpt_path,\n            task=config.task)\n\n        logger.info(\n            \"Initialize Vector server engine successfully on device: %s.\" %\n            (self.device))\n        return True\n"
  },
  {
    "path": "paddlespeech/server/entry.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nfrom collections import defaultdict\n\n__all__ = ['server_commands', 'client_commands']\n\n\ndef _CommandDict():\n    return defaultdict(_CommandDict)\n\n\ndef server_execute():\n    com = server_commands\n    idx = 0\n    for _argv in (['paddlespeech_server'] + sys.argv[1:]):\n        if _argv not in com:\n            break\n        idx += 1\n        com = com[_argv]\n\n    # The method 'execute' of a command instance returns 'True' for a success\n    # while 'False' for a failure. Here converts this result into a exit status\n    # in bash: 0 for a success and 1 for a failure.\n    status = 0 if com['_entry']().execute(sys.argv[idx:]) else 1\n    return status\n\n\ndef client_execute():\n    com = client_commands\n    idx = 0\n    for _argv in (['paddlespeech_client'] + sys.argv[1:]):\n        if _argv not in com:\n            break\n        idx += 1\n        com = com[_argv]\n\n    # The method 'execute' of a command instance returns 'True' for a success\n    # while 'False' for a failure. Here converts this result into a exit status\n    # in bash: 0 for a success and 1 for a failure.\n    status = 0 if com['_entry']().execute(sys.argv[idx:]) else 1\n    return status\n\n\nserver_commands = _CommandDict()\nclient_commands = _CommandDict()\n"
  },
  {
    "path": "paddlespeech/server/executor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom abc import ABC\nfrom abc import abstractmethod\nfrom typing import List\n\n\nclass BaseExecutor(ABC):\n    \"\"\"\n        An abstract executor of paddlespeech server tasks.\n    \"\"\"\n\n    def __init__(self):\n        self.parser = argparse.ArgumentParser()\n\n    @abstractmethod\n    def execute(self, argv: List[str]) -> bool:\n        \"\"\"\n        Command line entry. This method can only be accessed by a command line such as `paddlespeech asr`.\n\n        Args:\n            argv (List[str]): Arguments from command line.\n\n        Returns:\n            int: Result of the command execution. `True` for a success and `False` for a failure.\n        \"\"\"\n        pass\n\n    @abstractmethod\n    def __call__(self, *arg, **kwargs):\n        \"\"\"\n        Python API to call an executor.\n        \"\"\"\n        pass\n"
  },
  {
    "path": "paddlespeech/server/restful/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/restful/acs_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nfrom typing import Union\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.restful.request import ASRRequest\nfrom paddlespeech.server.restful.response import ACSResponse\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\n\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/asr/search/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: the audio content search result\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"result\": {\n            \"description\": \"acs server\",\n            \"input\": \"base64 string of wavfile\",\n            \"output\": {\n                \"asr_result\": \"你好\",\n                \"acs_result\": [{\n                    'w': '你',\n                    'bg': 0.0,\n                    'ed': 1.2\n                }]\n            }\n        }\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/asr/search\",\n    response_model=Union[ACSResponse, ErrorResponse])\ndef acs(request_body: ASRRequest):\n    \"\"\"acs api \n\n    Args:\n        request_body (ASRRequest): the acs request, we reuse the http ASRRequest\n\n    Returns:\n        json: the acs result\n    \"\"\"\n    try:\n        # 1. get the audio data via base64 decoding\n        audio_data = base64.b64decode(request_body.audio)\n\n        # 2. get single engine from engine pool\n        engine_pool = get_engine_pool()\n        acs_engine = engine_pool['acs']\n\n        # 3. no data stored in acs_engine, so we need to create the another instance process the data\n        acs_result, asr_result = acs_engine.run(audio_data)\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"transcription\": asr_result,\n                \"acs\": acs_result\n            }\n        }\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException as e:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        logger.error(e)\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/restful/api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nfrom typing import List\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.restful.acs_api import router as acs_router\nfrom paddlespeech.server.restful.asr_api import router as asr_router\nfrom paddlespeech.server.restful.cls_api import router as cls_router\nfrom paddlespeech.server.restful.text_api import router as text_router\nfrom paddlespeech.server.restful.tts_api import router as tts_router\nfrom paddlespeech.server.restful.vector_api import router as vec_router\n_router = APIRouter()\n\n\ndef setup_router(api_list: List):\n    \"\"\"setup router for fastapi\n\n    Args:\n        api_list (List): [asr, tts, cls, text, vecotr]\n\n    Returns:\n        APIRouter\n    \"\"\"\n    for api_name in api_list:\n        if api_name.lower() == 'asr':\n            _router.include_router(asr_router)\n        elif api_name.lower() == 'tts':\n            _router.include_router(tts_router)\n        elif api_name.lower() == 'cls':\n            _router.include_router(cls_router)\n        elif api_name.lower() == 'text':\n            _router.include_router(text_router)\n        elif api_name.lower() == 'vector':\n            _router.include_router(vec_router)\n        elif api_name.lower() == 'acs':\n            _router.include_router(acs_router)\n        else:\n            logger.error(\n                f\"PaddleSpeech has not support such service: {api_name}\")\n            sys.exit(-1)\n\n    return _router\n"
  },
  {
    "path": "paddlespeech/server/restful/asr_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport sys\nimport traceback\nfrom typing import Union\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.restful.request import ASRRequest\nfrom paddlespeech.server.restful.response import ASRResponse\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\n\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/asr/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: [description]\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"result\": {\n            \"description\": \"asr server\",\n            \"input\": \"base64 string of wavfile\",\n            \"output\": \"transcription\"\n        }\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/asr\", response_model=Union[ASRResponse, ErrorResponse])\ndef asr(request_body: ASRRequest):\n    \"\"\"asr api \n\n    Args:\n        request_body (ASRRequest): [description]\n\n    Returns:\n        json: [description]\n    \"\"\"\n    try:\n        audio_data = base64.b64decode(request_body.audio)\n\n        # get single engine from engine pool\n        engine_pool = get_engine_pool()\n        asr_engine = engine_pool['asr']\n\n        if asr_engine.engine_type == \"python\":\n            from paddlespeech.server.engine.asr.python.asr_engine import PaddleASRConnectionHandler\n        elif asr_engine.engine_type == \"inference\":\n            from paddlespeech.server.engine.asr.paddleinference.asr_engine import PaddleASRConnectionHandler\n        else:\n            logger.error(\"Offline asr engine only support python or inference.\")\n            sys.exit(-1)\n\n        connection_handler = PaddleASRConnectionHandler(asr_engine)\n\n        connection_handler.run(audio_data)\n        asr_results = connection_handler.postprocess()\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"transcription\": asr_results\n            }\n        }\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/restful/cls_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport sys\nimport traceback\nfrom typing import Union\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.restful.request import CLSRequest\nfrom paddlespeech.server.restful.response import CLSResponse\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\n\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/cls/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: [description]\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"result\": {\n            \"description\": \"cls server\",\n            \"input\": \"base64 string of wavfile\",\n            \"output\": \"classification result\"\n        }\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/cls\", response_model=Union[CLSResponse, ErrorResponse])\ndef cls(request_body: CLSRequest):\n    \"\"\"cls api \n\n    Args:\n        request_body (CLSRequest): [description]\n\n    Returns:\n        json: [description]\n    \"\"\"\n    try:\n        audio_data = base64.b64decode(request_body.audio)\n\n        # get single engine from engine pool\n        engine_pool = get_engine_pool()\n        cls_engine = engine_pool['cls']\n\n        if cls_engine.engine_type == \"python\":\n            from paddlespeech.server.engine.cls.python.cls_engine import PaddleCLSConnectionHandler\n        elif cls_engine.engine_type == \"inference\":\n            from paddlespeech.server.engine.cls.paddleinference.cls_engine import PaddleCLSConnectionHandler\n        else:\n            logger.error(\"Offline cls engine only support python or inference.\")\n            sys.exit(-1)\n\n        connection_handler = PaddleCLSConnectionHandler(cls_engine)\n\n        connection_handler.run(audio_data)\n        cls_results = connection_handler.postprocess(request_body.topk)\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"topk\": request_body.topk,\n                \"results\": cls_results\n            }\n        }\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n        logger.error(e)\n        sys.exit(-1)\n    except Exception as e:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        logger.error(e)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/restful/request.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Optional\n\nfrom pydantic import BaseModel\n\n__all__ = [\n    'ASRRequest', 'TTSRequest', 'CLSRequest', 'VectorRequest',\n    'VectorScoreRequest'\n]\n\n\n#****************************************************************************************/\n#************************************ ASR request ***************************************/\n#****************************************************************************************/\nclass ASRRequest(BaseModel):\n    \"\"\"\n    request body example\n    {\n        \"audio\": \"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf...\",\n        \"audio_format\": \"wav\",\n        \"sample_rate\": 16000,\n        \"lang\": \"zh_cn\",\n        \"punc\":false\n    }\n    \"\"\"\n    audio: str\n    audio_format: str\n    sample_rate: int\n    lang: str\n    punc: Optional[bool] = None\n\n\n#****************************************************************************************/\n#************************************ TTS request ***************************************/\n#****************************************************************************************/\nclass TTSRequest(BaseModel):\n    \"\"\"TTS request\n\n    request body example\n    {\n        \"text\": \"你好，欢迎使用百度飞桨语音合成服务。\",\n        \"spk_id\": 0,\n        \"speed\": 1.0,\n        \"volume\": 1.0,\n        \"sample_rate\": 0,\n        \"tts_audio_path\": \"./tts.wav\"\n    }\n    \n    \"\"\"\n\n    text: str\n    spk_id: int = 0\n    speed: float = 1.0\n    volume: float = 1.0\n    sample_rate: int = 0\n    save_path: Optional[str] = None\n\n\n#****************************************************************************************/\n#************************************ CLS request ***************************************/\n#****************************************************************************************/\nclass CLSRequest(BaseModel):\n    \"\"\"\n    request body example\n    {\n        \"audio\": \"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf...\",\n        \"topk\": 1\n    }\n    \"\"\"\n    audio: str\n    topk: int = 1\n\n\n#****************************************************************************************/\n#************************************ Text request **************************************/\n#****************************************************************************************/\nclass TextRequest(BaseModel):\n    text: str\n\n\n#****************************************************************************************/\n#************************************ Vecotr request ************************************/\n#****************************************************************************************/\nclass VectorRequest(BaseModel):\n    \"\"\"\n    request body example\n    {\n        \"audio\": \"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf...\",\n        \"task\": \"spk\",\n        \"audio_format\": \"wav\",\n        \"sample_rate\": 16000,\n    }\n    \"\"\"\n    audio: str\n    task: str\n    audio_format: str\n    sample_rate: int\n\n\nclass VectorScoreRequest(BaseModel):\n    \"\"\"\n    request body example\n    {\n        \"enroll_audio\": \"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf...\",\n        \"test_audio\": \"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf...\",\n        \"task\": \"score\",\n        \"audio_format\": \"wav\",\n        \"sample_rate\": 16000,\n    }\n    \"\"\"\n    enroll_audio: str\n    test_audio: str\n    task: str\n    audio_format: str\n    sample_rate: int\n"
  },
  {
    "path": "paddlespeech/server/restful/response.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\nfrom typing import Optional\n\nfrom pydantic import BaseModel\n\n__all__ = [\n    'ASRResponse', 'TTSResponse', 'CLSResponse', 'TextResponse',\n    'VectorResponse', 'VectorScoreResponse', 'ACSResponse'\n]\n\n\nclass Message(BaseModel):\n    description: str\n\n\n#****************************************************************************************/\n#************************************ ASR response **************************************/\n#****************************************************************************************/\nclass AsrResult(BaseModel):\n    transcription: str\n\n\nclass ASRResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"transcription\": \"你好，飞桨\"\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: AsrResult\n\n\n#****************************************************************************************/\n#************************************ TTS response **************************************/\n#****************************************************************************************/\nclass TTSResult(BaseModel):\n    lang: str = \"zh\"\n    spk_id: int = 0\n    speed: float = 1.0\n    volume: float = 1.0\n    sample_rate: int\n    duration: float\n    save_path: Optional[str] = None\n    audio: str\n\n\nclass TTSResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 200,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"lang\": \"zh\",\n            \"spk_id\": 0,\n            \"speed\": 1.0,\n            \"volume\": 1.0,\n            \"sample_rate\": 24000,\n            \"duration\": 3.6125,\n            \"audio\": \"LTI1OTIuNjI1OTUwMzQsOTk2OS41NDk4...\",\n            \"save_path\": \"./tts.wav\"\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: TTSResult\n\n\n#****************************************************************************************/\n#************************************ CLS response **************************************/\n#****************************************************************************************/\nclass CLSResults(BaseModel):\n    class_name: str\n    prob: float\n\n\nclass CLSResult(BaseModel):\n    topk: int\n    results: List[CLSResults]\n\n\nclass CLSResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            topk: 1\n            results: [\n            {\n                \"class\":\"Speech\",\n                \"prob\": 0.9027184844017029\n            }\n            ]\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: CLSResult\n\n\n#****************************************************************************************/\n#************************************ Text response **************************************/\n#****************************************************************************************/\n\n\nclass TextResult(BaseModel):\n    punc_text: str\n\n\nclass TextResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"punc_text\": \"你好，飞桨\"\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: TextResult\n\n\n#****************************************************************************************/\n#************************************ Vector response **************************************/\n#****************************************************************************************/\n\n\nclass VectorResult(BaseModel):\n    vec: list\n\n\nclass VectorResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"vec\": [1.0, 1.0]\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: VectorResult\n\n\nclass VectorScoreResult(BaseModel):\n    score: float\n\n\nclass VectorScoreResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"score\": 1.0\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: VectorScoreResult\n\n\n#****************************************************************************************/\n#********************************** Error response **************************************/\n#****************************************************************************************/\nclass ErrorResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": false,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"Unknown error occurred.\"\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n\n\n#****************************************************************************************/\n#************************************ ACS response **************************************/\n#****************************************************************************************/\nclass AcsResult(BaseModel):\n    transcription: str\n    acs: list\n\n\nclass ACSResponse(BaseModel):\n    \"\"\"\n    response example\n    {\n        \"success\": true,\n        \"code\": 0,\n        \"message\": {\n            \"description\": \"success\" \n        },\n        \"result\": {\n            \"transcription\": \"你好，飞桨\"\n            \"acs\": [(你好, 0.0, 0.45)]\n        }\n    }\n    \"\"\"\n    success: bool\n    code: int\n    message: Message\n    result: AcsResult\n"
  },
  {
    "path": "paddlespeech/server/restful/text_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport traceback\nfrom typing import Union\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.engine.text.python.text_engine import PaddleTextConnectionHandler\nfrom paddlespeech.server.restful.request import TextRequest\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.restful.response import TextResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/text/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: The /paddlespeech/text api response content\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"result\": {\n            \"punc_text\": \"The punctuation text content\"\n        }\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/text\", response_model=Union[TextResponse, ErrorResponse])\ndef asr(request_body: TextRequest):\n    \"\"\"asr api \n\n    Args:\n        request_body (TextRequest): the punctuation request body\n\n    Returns:\n        json: the punctuation response body\n    \"\"\"\n    try:\n        # 1. we get the sentence content from the request\n        text = request_body.text\n        logger.info(f\"Text service receive the {text}\")\n\n        # 2. get single engine from engine pool\n        #    and each request has its own connection to process the text\n        engine_pool = get_engine_pool()\n        text_engine = engine_pool['text']\n        connection_handler = PaddleTextConnectionHandler(text_engine)\n        punc_text = connection_handler.run(text)\n        logger.info(f\"Get the Text Connection result {punc_text}\")\n\n        # 3. create the response\n        if punc_text is None:\n            punc_text = text\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"punc_text\": punc_text\n            }\n        }\n\n        logger.info(f\"The Text Service final response: {response}\")\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/restful/tts_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nimport traceback\nfrom typing import Union\n\nfrom fastapi import APIRouter\nfrom fastapi.responses import StreamingResponse\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.restful.request import TTSRequest\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.restful.response import TTSResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\n\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/tts/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: [description]\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"result\": {\n            \"description\": \"tts server\",\n            \"text\": \"sentence to be synthesized\",\n            \"audio\": \"the base64 of audio\"\n        }\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/tts\", response_model=Union[TTSResponse, ErrorResponse])\ndef tts(request_body: TTSRequest):\n    \"\"\"tts api\n\n    Args:\n        request_body (TTSRequest): [description]\n\n    Returns:\n        json: [description]\n    \"\"\"\n\n    logger.info(\"request: {}\".format(request_body))\n\n    # get params\n    text = request_body.text\n    spk_id = request_body.spk_id\n    speed = request_body.speed\n    volume = request_body.volume\n    sample_rate = request_body.sample_rate\n    save_path = request_body.save_path\n\n    # Check parameters\n    if speed <= 0 or speed > 3:\n        return failed_response(\n            ErrorCode.SERVER_PARAM_ERR,\n            \"invalid speed value, the value should be between 0 and 3.\")\n    if volume <= 0 or volume > 3:\n        return failed_response(\n            ErrorCode.SERVER_PARAM_ERR,\n            \"invalid volume value, the value should be between 0 and 3.\")\n    if sample_rate not in [0, 16000, 8000]:\n        return failed_response(\n            ErrorCode.SERVER_PARAM_ERR,\n            \"invalid sample_rate value, the choice of value is 0, 8000, 16000.\")\n    if save_path is not None and not save_path.endswith(\n            \"pcm\") and not save_path.endswith(\"wav\"):\n        return failed_response(\n            ErrorCode.SERVER_PARAM_ERR,\n            \"invalid save_path, saved audio formats support pcm and wav\")\n\n    # run\n    try:\n        # get single engine from engine pool\n        engine_pool = get_engine_pool()\n        tts_engine = engine_pool['tts']\n        logger.info(\"Get tts engine successfully.\")\n\n        if tts_engine.engine_type == \"python\":\n            from paddlespeech.server.engine.tts.python.tts_engine import PaddleTTSConnectionHandler\n        elif tts_engine.engine_type == \"inference\":\n            from paddlespeech.server.engine.tts.paddleinference.tts_engine import PaddleTTSConnectionHandler\n        else:\n            logger.error(\"Offline tts engine only support python or inference.\")\n            sys.exit(-1)\n\n        connection_handler = PaddleTTSConnectionHandler(tts_engine)\n        lang, target_sample_rate, duration, wav_base64 = connection_handler.run(\n            text, spk_id, speed, volume, sample_rate, save_path)\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success.\"\n            },\n            \"result\": {\n                \"lang\": lang,\n                \"spk_id\": spk_id,\n                \"speed\": speed,\n                \"volume\": volume,\n                \"sample_rate\": target_sample_rate,\n                \"duration\": duration,\n                \"save_path\": save_path,\n                \"audio\": wav_base64\n            }\n        }\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n\n\n@router.post(\"/paddlespeech/tts/streaming\")\nasync def stream_tts(request_body: TTSRequest):\n    # get params\n    text = request_body.text\n    spk_id = request_body.spk_id\n\n    engine_pool = get_engine_pool()\n    tts_engine = engine_pool['tts']\n    logger.info(\"Get tts engine successfully.\")\n\n    if tts_engine.engine_type == \"online\":\n        from paddlespeech.server.engine.tts.online.python.tts_engine import PaddleTTSConnectionHandler\n    elif tts_engine.engine_type == \"online-onnx\":\n        from paddlespeech.server.engine.tts.online.onnx.tts_engine import PaddleTTSConnectionHandler\n    else:\n        logger.error(\"Online tts engine only support online or online-onnx.\")\n        sys.exit(-1)\n\n    connection_handler = PaddleTTSConnectionHandler(tts_engine)\n\n    return StreamingResponse(\n        connection_handler.run(sentence=text, spk_id=spk_id))\n\n\n@router.get(\"/paddlespeech/tts/streaming/samplerate\")\ndef get_samplerate():\n    try:\n        engine_pool = get_engine_pool()\n        tts_engine = engine_pool['tts']\n        logger.info(\"Get tts engine successfully.\")\n        sample_rate = tts_engine.sample_rate\n\n        response = {\"sample_rate\": sample_rate}\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/restful/vector_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport traceback\nfrom typing import Union\n\nimport numpy as np\nfrom fastapi import APIRouter\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nfrom paddlespeech.server.engine.vector.python.vector_engine import PaddleVectorConnectionHandler\nfrom paddlespeech.server.restful.request import VectorRequest\nfrom paddlespeech.server.restful.request import VectorScoreRequest\nfrom paddlespeech.server.restful.response import ErrorResponse\nfrom paddlespeech.server.restful.response import VectorResponse\nfrom paddlespeech.server.restful.response import VectorScoreResponse\nfrom paddlespeech.server.utils.errors import ErrorCode\nfrom paddlespeech.server.utils.errors import failed_response\nfrom paddlespeech.server.utils.exception import ServerBaseException\nrouter = APIRouter()\n\n\n@router.get('/paddlespeech/vector/help')\ndef help():\n    \"\"\"help\n\n    Returns:\n        json: The /paddlespeech/vector api response content\n    \"\"\"\n    response = {\n        \"success\": \"True\",\n        \"code\": 200,\n        \"message\": {\n            \"global\": \"success\"\n        },\n        \"vector\": [2.3, 3.5, 5.5, 6.2, 2.8, 1.2, 0.3, 3.6]\n    }\n    return response\n\n\n@router.post(\n    \"/paddlespeech/vector\", response_model=Union[VectorResponse, ErrorResponse])\ndef vector(request_body: VectorRequest):\n    \"\"\"vector api \n\n    Args:\n        request_body (VectorRequest): the vector request body\n\n    Returns:\n        json: the vector response body\n    \"\"\"\n    try:\n        # 1. get the audio data\n        #    the audio must be base64 format\n        audio_data = base64.b64decode(request_body.audio)\n\n        # 2. get single engine from engine pool\n        #    and we use the vector_engine to create an connection handler to process the request\n        engine_pool = get_engine_pool()\n        vector_engine = engine_pool['vector']\n        connection_handler = PaddleVectorConnectionHandler(vector_engine)\n\n        # 3. we use the connection handler to process the audio\n        audio_vec = connection_handler.run(audio_data, request_body.task)\n\n        # 4. we need the result of the vector instance be numpy.ndarray\n        if not isinstance(audio_vec, np.ndarray):\n            logger.error(\n                f\"the vector type is not numpy.array, that is: {type(audio_vec)}\"\n            )\n            error_reponse = ErrorResponse()\n            error_reponse.message.description = f\"the vector type is not numpy.array, that is: {type(audio_vec)}\"\n            return error_reponse\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"vec\": audio_vec.tolist()\n            }\n        }\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n\n\n@router.post(\n    \"/paddlespeech/vector/score\",\n    response_model=Union[VectorScoreResponse, ErrorResponse])\ndef score(request_body: VectorScoreRequest):\n    \"\"\"vector api \n\n    Args:\n        request_body (VectorScoreRequest): the punctuation request body\n\n    Returns:\n        json: the punctuation response body\n    \"\"\"\n    try:\n        # 1. get the audio data\n        #    the audio must be base64 format\n        enroll_data = base64.b64decode(request_body.enroll_audio)\n        test_data = base64.b64decode(request_body.test_audio)\n\n        # 2. get single engine from engine pool\n        #    and we use the vector_engine to create an connection handler to process the request\n        engine_pool = get_engine_pool()\n        vector_engine = engine_pool['vector']\n        connection_handler = PaddleVectorConnectionHandler(vector_engine)\n\n        # 3. we use the connection handler to process the audio\n        score = connection_handler.get_enroll_test_score(enroll_data, test_data)\n\n        response = {\n            \"success\": True,\n            \"code\": 200,\n            \"message\": {\n                \"description\": \"success\"\n            },\n            \"result\": {\n                \"score\": score\n            }\n        }\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/server/tests/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/offline/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/offline/http_client.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the \nimport base64\nimport json\nimport time\n\nimport requests\n\n\ndef readwav2base64(wav_file):\n    \"\"\"\n    read wave file and covert to base64 string\n    \"\"\"\n    with open(wav_file, 'rb') as f:\n        base64_bytes = base64.b64encode(f.read())\n        base64_string = base64_bytes.decode('utf-8')\n    return base64_string\n\n\ndef main():\n    \"\"\"\n    main func\n    \"\"\"\n    url = \"http://127.0.0.1:8090/paddlespeech/asr\"\n\n    # start Timestamp\n    time_start = time.time()\n\n    test_audio_dir = \"./16_audio.wav\"\n    audio = readwav2base64(test_audio_dir)\n\n    data = {\n        \"audio\": audio,\n        \"audio_format\": \"wav\",\n        \"sample_rate\": 16000,\n        \"lang\": \"zh_cn\",\n    }\n\n    r = requests.post(url=url, data=json.dumps(data))\n\n    # ending Timestamp\n    time_end = time.time()\n    print('time cost', time_end - time_start, 's')\n\n    print(r.json())\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/online/README.md",
    "content": "([简体中文](./README_cn.md)|English)\n\n# Speech Service\n\n## Introduction\n\nThis document introduces a client for streaming asr service: microphone\n\n\n## Usage\n### 1. Install\nRefer [Install](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\n **paddlepaddle 2.4rc** 或以上版本。\nIt is recommended to use **paddlepaddle 2.4rc** or above.\nYou can choose one way from meduim and hard to install paddlespeech.\n\n\n### 2. Prepare config File\n\n\nThe input of  ASR client demo should be a WAV file(`.wav`), and the sample rate must be the same as the model.\n\nHere are sample files for thisASR client demo that can be downloaded:\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 2. Streaming ASR Client Usage\n\n- microphone\n   ```\n   python microphone_client.py\n\n   ```\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/online/README_cn.md",
    "content": "([English](./README.md)|中文)\n\n# 语音服务\n\n## 介绍\n本文档介绍如何使用流式ASR的一种不同客户端:麦克风。 \n\n\n## 使用方法\n### 1. 安装\n请看 [安装文档](https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install.md).\n\n推荐使用 **paddlepaddle 2.4rc** 或以上版本。\n你可以从 medium，hard 三中方式中选择一种方式安装 PaddleSpeech。\n\n\n### 2. 准备测试文件\n\n这个 ASR client 的输入应该是一个 WAV 文件（`.wav`），并且采样率必须与模型的采样率相同。\n\n可以下载此 ASR client的示例音频：\n```bash\nwget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n```\n\n### 2. 流式 ASR 客户端使用方法\n\n- Python模拟流式服务命令行\n   ```\n\n   # 流式ASR\n   paddlespeech_client asr_online --server_ip 127.0.0.1 --port 8091 --input ./zh.wav\n\n   ```\n\n\n- 麦克风\n   ```\n   # 直接调用麦克风设备\n   python microphone_client.py\n\n   ```\n"
  },
  {
    "path": "paddlespeech/server/tests/asr/online/microphone_client.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nrecord wave from the mic\n\"\"\"\nimport asyncio\nimport json\nimport logging\nimport threading\nimport wave\nfrom signal import SIGINT\nfrom signal import SIGTERM\n\nimport pyaudio\nimport websockets\n\n\nclass ASRWsAudioHandler(threading.Thread):\n    def __init__(self, url=\"127.0.0.1\", port=8091):\n        threading.Thread.__init__(self)\n        self.url = url\n        self.port = port\n        self.url = \"ws://\" + self.url + \":\" + str(self.port) + \"/ws/asr\"\n        self.fileName = \"./output.wav\"\n        self.chunk = 5120\n        self.format = pyaudio.paInt16\n        self.channels = 1\n        self.rate = 16000\n        self._running = True\n        self._frames = []\n        self.data_backup = []\n\n    def startrecord(self):\n        \"\"\"\n        start a new thread to record wave\n        \"\"\"\n        threading._start_new_thread(self.recording, ())\n\n    def recording(self):\n        \"\"\"\n        recording wave\n        \"\"\"\n        self._running = True\n        self._frames = []\n        p = pyaudio.PyAudio()\n        stream = p.open(\n            format=self.format,\n            channels=self.channels,\n            rate=self.rate,\n            input=True,\n            frames_per_buffer=self.chunk)\n        while (self._running):\n            data = stream.read(self.chunk)\n            self._frames.append(data)\n            self.data_backup.append(data)\n\n        stream.stop_stream()\n        stream.close()\n        p.terminate()\n\n    def save(self):\n        \"\"\"\n        save wave data\n        \"\"\"\n        p = pyaudio.PyAudio()\n        wf = wave.open(self.fileName, 'wb')\n        wf.setnchannels(self.channels)\n        wf.setsampwidth(p.get_sample_size(self.format))\n        wf.setframerate(self.rate)\n        wf.writeframes(b''.join(self.data_backup))\n        wf.close()\n        p.terminate()\n\n    def stoprecord(self):\n        \"\"\"\n        stop recording\n        \"\"\"\n        self._running = False\n\n    async def run(self):\n        aa = input(\"是否开始录音？   (y/n)\")\n        if aa.strip() == \"y\":\n            self.startrecord()\n            logging.info(\"*\" * 10 + \"开始录音，请输入语音\")\n\n            async with websockets.connect(self.url) as ws:\n                # 发送开始指令\n                audio_info = json.dumps(\n                    {\n                        \"name\": \"test.wav\",\n                        \"signal\": \"start\",\n                        \"nbest\": 5\n                    },\n                    sort_keys=True,\n                    indent=4,\n                    separators=(',', ': '))\n                await ws.send(audio_info)\n                msg = await ws.recv()\n                logging.info(\"receive msg={}\".format(msg))\n\n                # send bytes data\n                logging.info(\"结束录音请: Ctrl + c。继续请按回车。\")\n                try:\n                    while True:\n                        while len(self._frames) > 0:\n                            await ws.send(self._frames.pop(0))\n                            msg = await ws.recv()\n                            logging.info(\"receive msg={}\".format(msg))\n                except asyncio.CancelledError:\n                    # quit\n                    # send finished \n                    audio_info = json.dumps(\n                        {\n                            \"name\": \"test.wav\",\n                            \"signal\": \"end\",\n                            \"nbest\": 5\n                        },\n                        sort_keys=True,\n                        indent=4,\n                        separators=(',', ': '))\n                    await ws.send(audio_info)\n                    msg = await ws.recv()\n                    logging.info(\"receive msg={}\".format(msg))\n\n                    self.stoprecord()\n                    logging.info(\"*\" * 10 + \"录音结束\")\n                    self.save()\n        elif aa.strip() == \"n\":\n            exit()\n        else:\n            print(\"无效输入!\")\n            exit()\n\n\nif __name__ == \"__main__\":\n\n    logging.basicConfig(level=logging.INFO)\n    logging.info(\"asr websocket client start\")\n\n    handler = ASRWsAudioHandler(\"127.0.0.1\", 8091)\n    loop = asyncio.get_event_loop()\n    main_task = asyncio.ensure_future(handler.run())\n    for signal in [SIGINT, SIGTERM]:\n        loop.add_signal_handler(signal, main_task.cancel)\n    try:\n        loop.run_until_complete(main_task)\n    finally:\n        loop.close()\n\n    logging.info(\"asr websocket client finished\")\n"
  },
  {
    "path": "paddlespeech/server/tests/text/http_client.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport json\nimport time\n\nimport requests\n\nfrom paddlespeech.cli.log import logger\n\n\n# Request and response\ndef text_client(args):\n    \"\"\" Request and response\n    Args:\n        text: A sentence to be processed by PaddleSpeech Text Server\n        outfile: The punctuation text\n    \"\"\"\n    url = \"http://\" + str(args.server) + \":\" + str(\n        args.port) + \"/paddlespeech/text\"\n    request = {\n        \"text\": args.text,\n    }\n\n    response = requests.post(url, json.dumps(request))\n    response_dict = response.json()\n    punc_text = response_dict[\"result\"][\"punc_text\"]\n\n    # transform audio\n    outfile = args.output\n    if outfile:\n        with open(outfile, 'w') as w:\n            w.write(punc_text + \"\\n\")\n\n    logger.info(f\"The punc text is: {punc_text}\")\n    return punc_text\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        '--text',\n        type=str,\n        default=\"今天的天气真不错啊你下午有空吗我想约你一起去吃饭\",\n        help='A sentence to be synthesized')\n    parser.add_argument(\n        '--output', type=str, default=\"./punc_text\", help='Punc text file')\n    parser.add_argument(\n        \"--server\", type=str, help=\"server ip\", default=\"127.0.0.1\")\n    parser.add_argument(\"--port\", type=int, help=\"server port\", default=8090)\n    args = parser.parse_args()\n\n    st = time.time()\n    try:\n        punc_text = text_client(args)\n        time_consume = time.time() - st\n        time_per_word = time_consume / len(args.text)\n        print(\"Text Process successfully.\")\n        print(\"Inference time: %f\" % (time_consume))\n        print(\"The text length: %f\" % (len(args.text)))\n        print(\"The time per work is: %f\" % (time_per_word))\n    except BaseException as e:\n        logger.info(\"Failed to Process text.\")\n        logger.info(e)\n"
  },
  {
    "path": "paddlespeech/server/tests/tts/offline/http_client.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport base64\nimport io\nimport json\nimport os\nimport random\nimport time\n\nimport numpy as np\nimport requests\nimport soundfile\n\nfrom paddlespeech.server.utils.audio_process import wav2pcm\n\n\n# Request and response\ndef tts_client(args):\n    \"\"\" Request and response\n    Args:\n        text: A sentence to be synthesized\n        outfile: Synthetic audio file\n    \"\"\"\n    url = \"http://\" + str(args.server) + \":\" + str(\n        args.port) + \"/paddlespeech/tts\"\n    request = {\n        \"text\": args.text,\n        \"spk_id\": args.spk_id,\n        \"speed\": args.speed,\n        \"volume\": args.volume,\n        \"sample_rate\": args.sample_rate,\n        \"save_path\": args.output\n    }\n\n    response = requests.post(url, json.dumps(request))\n    response_dict = response.json()\n    wav_base64 = response_dict[\"result\"][\"audio\"]\n\n    audio_data_byte = base64.b64decode(wav_base64)\n    # from byte\n    samples, sample_rate = soundfile.read(\n        io.BytesIO(audio_data_byte), dtype='float32')\n\n    # transform audio\n    outfile = args.output\n    if outfile.endswith(\".wav\"):\n        soundfile.write(outfile, samples, sample_rate)\n    elif outfile.endswith(\".pcm\"):\n        temp_wav = str(random.getrandbits(128)) + \".wav\"\n        soundfile.write(temp_wav, samples, sample_rate)\n        wav2pcm(temp_wav, outfile, data_type=np.int16)\n        os.remove(temp_wav)\n    else:\n        print(\"The format for saving audio only supports wav or pcm\")\n\n    return len(samples), sample_rate\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        '--text',\n        type=str,\n        default=\"您好，欢迎使用语音合成服务。\",\n        help='A sentence to be synthesized')\n    parser.add_argument('--spk_id', type=int, default=0, help='Speaker id')\n    parser.add_argument('--speed', type=float, default=1.0, help='Audio speed')\n    parser.add_argument(\n        '--volume', type=float, default=1.0, help='Audio volume')\n    parser.add_argument(\n        '--sample_rate',\n        type=int,\n        default=0,\n        help='Sampling rate, the default is the same as the model')\n    parser.add_argument(\n        '--output',\n        type=str,\n        default=\"./out.wav\",\n        help='Synthesized audio file')\n    parser.add_argument(\n        \"--server\", type=str, help=\"server ip\", default=\"127.0.0.1\")\n    parser.add_argument(\"--port\", type=int, help=\"server port\", default=8090)\n    args = parser.parse_args()\n\n    st = time.time()\n    try:\n        samples_length, sample_rate = tts_client(args)\n        time_consume = time.time() - st\n        duration = samples_length / sample_rate\n        rtf = time_consume / duration\n        print(\"Synthesized audio successfully.\")\n        print(\"Inference time: %f\" % (time_consume))\n        print(\"The duration of synthesized audio: %f\" % (duration))\n        print(\"The RTF is: %f\" % (rtf))\n    except BaseException:\n        print(\"Failed to synthesized audio.\")\n"
  },
  {
    "path": "paddlespeech/server/tests/tts/online/http_client.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nfrom paddlespeech.server.utils.audio_handler import TTSHttpHandler\nfrom paddlespeech.server.utils.util import compute_delay\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"A sentence to be synthesized\",\n        default=\"您好，欢迎使用语音合成服务。\")\n    parser.add_argument(\n        \"--server\", type=str, help=\"server ip\", default=\"127.0.0.1\")\n    parser.add_argument(\"--port\", type=int, help=\"server port\", default=8092)\n    parser.add_argument('--spk_id', type=int, default=0, help='Speaker id')\n    parser.add_argument('--speed', type=float, default=1.0, help='Audio speed')\n    parser.add_argument(\n        '--volume', type=float, default=1.0, help='Audio volume')\n    parser.add_argument(\n        '--sample_rate',\n        type=int,\n        default=0,\n        choices=[0, 8000, 16000],\n        help='Sampling rate, the default is the same as the model')\n    parser.add_argument(\n        \"--output\", type=str, help=\"save audio path\", default=None)\n    parser.add_argument(\n        \"--play\", type=bool, help=\"whether to play audio\", default=False)\n    args = parser.parse_args()\n\n    print(\"tts http client start\")\n    handler = TTSHttpHandler(args.server, args.port, args.play)\n    first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list = handler.run(\n        args.text, args.spk_id, args.speed, args.volume, args.sample_rate,\n        args.output)\n    delay_time_list = compute_delay(receive_time_list, chunk_duration_list)\n\n    print(f\"sentence: {args.text}\")\n    print(f\"duration: {duration} s\")\n    print(f\"first response: {first_response} s\")\n    print(f\"final response: {final_response} s\")\n    print(f\"RTF: {final_response/duration}\")\n    if args.output is not None:\n        if save_audio_success:\n            print(f\"Audio successfully saved in {args.output}\")\n        else:\n            print(\"Audio save failed.\")\n\n    if delay_time_list != []:\n        print(\n            f\"Delay situation: total number of packages: {len(receive_time_list)}, the number of delayed packets: {len(delay_time_list)}, minimum delay time: {min(delay_time_list)} s, maximum delay time: {max(delay_time_list)} s, average delay time: {sum(delay_time_list)/len(delay_time_list)} s, delay rate:{len(delay_time_list)/len(receive_time_list)}\"\n        )\n    else:\n        print(\"The sentence has no delay in streaming synthesis.\")\n"
  },
  {
    "path": "paddlespeech/server/tests/tts/online/ws_client.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport asyncio\n\nfrom paddlespeech.server.utils.audio_handler import TTSWsHandler\nfrom paddlespeech.server.utils.util import compute_delay\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"A sentence to be synthesized\",\n        default=\"您好，欢迎使用语音合成服务。\")\n    parser.add_argument(\n        \"--server\", type=str, help=\"server ip\", default=\"127.0.0.1\")\n    parser.add_argument(\"--port\", type=int, help=\"server port\", default=8092)\n    parser.add_argument(\n        \"--output\", type=str, help=\"save audio path\", default=None)\n    parser.add_argument(\n        \"--play\", type=bool, help=\"whether to play audio\", default=False)\n    args = parser.parse_args()\n\n    print(\"tts websocket client start\")\n    handler = TTSWsHandler(args.server, args.port, args.play)\n    loop = asyncio.get_event_loop()\n    first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list = loop.run_until_complete(\n        handler.run(args.text, args.output))\n    delay_time_list = compute_delay(receive_time_list, chunk_duration_list)\n\n    print(f\"sentence: {args.text}\")\n    print(f\"duration: {duration} s\")\n    print(f\"first response: {first_response} s\")\n    print(f\"final response: {final_response} s\")\n    print(f\"RTF: {final_response/duration}\")\n    if args.output is not None:\n        if save_audio_success:\n            print(f\"Audio successfully saved in {args.output}\")\n        else:\n            print(\"Audio save failed.\")\n\n    if delay_time_list != []:\n        print(\n            f\"Delay situation: total number of packages: {len(receive_time_list)}, the number of delayed packets: {len(delay_time_list)}, minimum delay time: {min(delay_time_list)} s, maximum delay time: {max(delay_time_list)} s, average delay time: {sum(delay_time_list)/len(delay_time_list)} s, delay rate:{len(delay_time_list)/len(receive_time_list)}\"\n        )\n    else:\n        print(\"The sentence has no delay in streaming synthesis.\")\n"
  },
  {
    "path": "paddlespeech/server/util.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport hashlib\nimport inspect\nimport json\nimport os\nimport tarfile\nimport threading\nimport time\nimport uuid\nimport zipfile\nfrom typing import Any\nfrom typing import Dict\n\nimport paddle\nimport requests\nimport yaml\nfrom paddle.framework import load\n\nfrom .entry import client_commands\nfrom .entry import server_commands\nfrom paddlespeech.audio.backends import soundfile_load\nfrom paddlespeech.cli import download\ntry:\n    from .. import __version__\nexcept ImportError:\n    __version__ = \"0.0.0\"  # for develop branch\n\nrequests.adapters.DEFAULT_RETRIES = 3\n\n__all__ = [\n    'cli_server_register',\n    'get_server_command',\n    'cli_client_register',\n    'get_client_command',\n    'download_and_decompress',\n    'load_state_dict_from_url',\n    'stats_wrapper',\n]\n\n\ndef cli_server_register(name: str, description: str='') -> Any:\n    def _warpper(command):\n        items = name.split('.')\n\n        com = server_commands\n        for item in items:\n            com = com[item]\n        com['_entry'] = command\n        if description:\n            com['_description'] = description\n        return command\n\n    return _warpper\n\n\ndef get_server_command(name: str) -> Any:\n    items = name.split('.')\n    com = server_commands\n    for item in items:\n        com = com[item]\n\n    return com['_entry']\n\n\ndef cli_client_register(name: str, description: str='') -> Any:\n    def _warpper(command):\n        items = name.split('.')\n\n        com = client_commands\n        for item in items:\n            com = com[item]\n        com['_entry'] = command\n        if description:\n            com['_description'] = description\n        return command\n\n    return _warpper\n\n\ndef get_client_command(name: str) -> Any:\n    items = name.split('.')\n    com = client_commands\n    for item in items:\n        com = com[item]\n\n    return com['_entry']\n\n\ndef _get_uncompress_path(filepath: os.PathLike) -> os.PathLike:\n    file_dir = os.path.dirname(filepath)\n    is_zip_file = False\n    if tarfile.is_tarfile(filepath):\n        files = tarfile.open(filepath, \"r:*\")\n        file_list = files.getnames()\n    elif zipfile.is_zipfile(filepath):\n        files = zipfile.ZipFile(filepath, 'r')\n        file_list = files.namelist()\n        is_zip_file = True\n    else:\n        return file_dir\n\n    if download._is_a_single_file(file_list):\n        rootpath = file_list[0]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n    elif download._is_a_single_dir(file_list):\n        if is_zip_file:\n            rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[0]\n        else:\n            rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n    else:\n        rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]\n        uncompressed_path = os.path.join(file_dir, rootpath)\n\n    files.close()\n    return uncompressed_path\n\n\ndef download_and_decompress(archive: Dict[str, str], path: str) -> os.PathLike:\n    \"\"\"\n    Download archieves and decompress to specific path.\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    assert 'url' in archive and 'md5' in archive, \\\n        'Dictionary keys of \"url\" and \"md5\" are required in the archive, but got: {}'.format(list(archive.keys()))\n\n    filepath = os.path.join(path, os.path.basename(archive['url']))\n    if os.path.isfile(filepath) and download._md5check(filepath,\n                                                       archive['md5']):\n        uncompress_path = _get_uncompress_path(filepath)\n        if not os.path.isdir(uncompress_path):\n            download._decompress(filepath)\n    else:\n        StatsWorker(\n            task='download',\n            version=__version__,\n            extra_info={\n                'download_url': archive['url'],\n                'paddle_version': paddle.__version__\n            }).start()\n        uncompress_path = download.get_path_from_url(archive['url'], path,\n                                                     archive['md5'])\n\n    return uncompress_path\n\n\ndef load_state_dict_from_url(url: str, path: str, md5: str=None) -> os.PathLike:\n    \"\"\"\n    Download and load a state dict from url\n    \"\"\"\n    if not os.path.isdir(path):\n        os.makedirs(path)\n\n    download.get_path_from_url(url, path, md5)\n    return load(os.path.join(path, os.path.basename(url)))\n\n\ndef _get_user_home():\n    return os.path.expanduser('~')\n\n\ndef _get_paddlespcceh_home():\n    if 'PPSPEECH_HOME' in os.environ:\n        home_path = os.environ['PPSPEECH_HOME']\n        if os.path.exists(home_path):\n            if os.path.isdir(home_path):\n                return home_path\n            else:\n                raise RuntimeError(\n                    'The environment variable PPSPEECH_HOME {} is not a directory.'.\n                    format(home_path))\n        else:\n            return home_path\n    return os.path.join(_get_user_home(), '.paddlespeech')\n\n\ndef _get_sub_home(directory):\n    home = os.path.join(_get_paddlespcceh_home(), directory)\n    if not os.path.exists(home):\n        os.makedirs(home)\n    return home\n\n\nPPSPEECH_HOME = _get_paddlespcceh_home()\nMODEL_HOME = _get_sub_home('models')\nCONF_HOME = _get_sub_home('conf')\n\n\ndef _md5(text: str):\n    '''Calculate the md5 value of the input text.'''\n    md5code = hashlib.md5(text.encode())\n    return md5code.hexdigest()\n\n\nclass ConfigCache:\n    def __init__(self):\n        self._data = {}\n        self._initialize()\n        self.file = os.path.join(CONF_HOME, 'cache.yaml')\n        if not os.path.exists(self.file):\n            self.flush()\n            return\n\n        with open(self.file, 'r') as file:\n            try:\n                cfg = yaml.load(file, Loader=yaml.FullLoader)\n                self._data.update(cfg)\n            except BaseException:\n                self.flush()\n\n    @property\n    def cache_info(self):\n        return self._data['cache_info']\n\n    def _initialize(self):\n        # Set default configuration values.\n        cache_info = _md5(str(uuid.uuid1())[-12:]) + \"-\" + str(int(time.time()))\n        self._data['cache_info'] = cache_info\n\n    def flush(self):\n        '''Flush the current configuration into the configuration file.'''\n        with open(self.file, 'w') as file:\n            cfg = json.loads(json.dumps(self._data))\n            yaml.dump(cfg, file)\n\n\nstats_api = \"http://paddlepaddle.org.cn/paddlehub/stat\"\ncache_info = ConfigCache().cache_info\n\n\nclass StatsWorker(threading.Thread):\n    def __init__(self,\n                 task=\"asr\",\n                 model=None,\n                 version=__version__,\n                 extra_info={}):\n        threading.Thread.__init__(self)\n        self._task = task\n        self._model = model\n        self._version = version\n        self._extra_info = extra_info\n\n    def run(self):\n        params = {\n            'task': self._task,\n            'version': self._version,\n            'from': 'ppspeech'\n        }\n        if self._model:\n            params['model'] = self._model\n\n        self._extra_info.update({\n            'cache_info': cache_info,\n        })\n        params.update({\"extra\": json.dumps(self._extra_info)})\n\n        try:\n            requests.get(stats_api, params)\n        except Exception:\n            pass\n\n        return\n\n\ndef _note_one_stat(cls_name, params={}):\n    task = cls_name.replace('Executor', '').lower()  # XXExecutor\n    extra_info = {\n        'paddle_version': paddle.__version__,\n    }\n\n    if 'model' in params:\n        model = params['model']\n    else:\n        model = None\n\n    if 'audio_file' in params:\n        try:\n            _, sr = soundfile_load(params['audio_file'])\n        except Exception:\n            sr = -1\n\n    if task == 'asr':\n        extra_info.update({\n            'lang': params['lang'],\n            'inp_sr': sr,\n            'model_sr': params['sample_rate'],\n        })\n    elif task == 'st':\n        extra_info.update({\n            'lang':\n            params['src_lang'] + '-' + params['tgt_lang'],\n            'inp_sr':\n            sr,\n            'model_sr':\n            params['sample_rate'],\n        })\n    elif task == 'tts':\n        model = params['am']\n        extra_info.update({\n            'lang': params['lang'],\n            'vocoder': params['voc'],\n        })\n    elif task == 'cls':\n        extra_info.update({\n            'inp_sr': sr,\n        })\n    elif task == 'text':\n        extra_info.update({\n            'sub_task': params['task'],\n            'lang': params['lang'],\n        })\n    else:\n        return\n\n    StatsWorker(\n        task=task,\n        model=model,\n        version=__version__,\n        extra_info=extra_info, ).start()\n\n\ndef _parse_args(func, *args, **kwargs):\n    # FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)\n    argspec = inspect.getfullargspec(func)\n\n    keys = argspec[0]\n    if keys[0] == 'self':  # Remove self pointer.\n        keys = keys[1:]\n\n    default_values = argspec[3]\n    values = [None] * (len(keys) - len(default_values))\n    values.extend(list(default_values))\n    params = dict(zip(keys, values))\n\n    for idx, v in enumerate(args):\n        params[keys[idx]] = v\n    for k, v in kwargs.items():\n        params[k] = v\n\n    return params\n\n\ndef stats_wrapper(executor_func):\n    def _warpper(self, *args, **kwargs):\n        try:\n            _note_one_stat(\n                type(self).__name__, _parse_args(executor_func, *args,\n                                                 **kwargs))\n        except Exception:\n            pass\n        return executor_func(self, *args, **kwargs)\n\n    return _warpper\n"
  },
  {
    "path": "paddlespeech/server/utils/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/utils/audio_handler.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport base64\nimport json\nimport logging\nimport threading\nimport time\n\nimport numpy as np\nimport requests\nimport soundfile\nimport websockets\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.utils.audio_process import save_audio\nfrom paddlespeech.server.utils.util import wav2base64\n\n\nclass TextHttpHandler:\n    def __init__(self, server_ip=\"127.0.0.1\", port=8090):\n        \"\"\"Text http client request \n\n        Args:\n            server_ip (str, optional): the text server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the text server port. Defaults to 8090.\n        \"\"\"\n        super().__init__()\n        self.server_ip = server_ip\n        self.port = port\n        if server_ip is None or port is None:\n            self.url = None\n        else:\n            self.url = 'http://' + self.server_ip + \":\" + str(\n                self.port) + '/paddlespeech/text'\n        logger.info(f\"endpoint: {self.url}\")\n\n    def run(self, text):\n        \"\"\"Call the text server to process the specific text\n\n        Args:\n            text (str): the text to be processed\n\n        Returns:\n            str: punctuation text\n        \"\"\"\n        if self.server_ip is None or self.port is None:\n            return text\n        request = {\n            \"text\": text,\n        }\n        try:\n            res = requests.post(url=self.url, data=json.dumps(request))\n            response_dict = res.json()\n            punc_text = response_dict[\"result\"][\"punc_text\"]\n        except Exception as e:\n            logger.error(f\"Call punctuation {self.url} occurs error\")\n            logger.error(e)\n            punc_text = text\n\n        return punc_text\n\n\nclass ASRWsAudioHandler:\n    def __init__(self,\n                 url=None,\n                 port=None,\n                 endpoint=\"/paddlespeech/asr/streaming\",\n                 punc_server_ip=None,\n                 punc_server_port=None):\n        \"\"\"PaddleSpeech Online ASR Server Client  audio handler\n           Online asr server use the websocket protocol\n        Args:\n            url (str, optional): the server ip. Defaults to None.\n            port (int, optional): the server port. Defaults to None.\n            endpoint(str, optional): to compatiable with python server and c++ server.\n            punc_server_ip(str, optional): the punctuation server ip. Defaults to None. \n            punc_server_port(int, optional): the punctuation port. Defaults to None\n        \"\"\"\n        self.url = url\n        self.port = port\n        if url is None or port is None or endpoint is None:\n            self.url = None\n        else:\n            self.url = \"ws://\" + self.url + \":\" + str(self.port) + endpoint\n        self.punc_server = TextHttpHandler(punc_server_ip, punc_server_port)\n        logger.info(f\"endpoint: {self.url}\")\n\n    def read_wave(self, wavfile_path: str):\n        \"\"\"read the audio file from specific wavfile path\n\n        Args:\n            wavfile_path (str): the audio wavfile, \n                                 we assume that audio sample rate matches the model\n\n        Yields:\n            numpy.array: the samall package audio pcm data\n        \"\"\"\n        samples, sample_rate = soundfile.read(wavfile_path, dtype='int16')\n        x_len = len(samples)\n        assert sample_rate == 16000\n\n        chunk_size = int(85 * sample_rate / 1000)  # 85ms, sample_rate = 16kHz\n\n        if x_len % chunk_size != 0:\n            padding_len_x = chunk_size - x_len % chunk_size\n        else:\n            padding_len_x = 0\n\n        padding = np.zeros((padding_len_x), dtype=samples.dtype)\n        padded_x = np.concatenate([samples, padding], axis=0)\n\n        assert (x_len + padding_len_x) % chunk_size == 0\n        num_chunk = (x_len + padding_len_x) / chunk_size\n        num_chunk = int(num_chunk)\n        for i in range(0, num_chunk):\n            start = i * chunk_size\n            end = start + chunk_size\n            x_chunk = padded_x[start:end]\n            yield x_chunk\n\n    async def run(self, wavfile_path: str):\n        \"\"\"Send a audio file to online server\n\n        Args:\n            wavfile_path (str): audio path\n\n        Returns:\n            str: the final asr result\n        \"\"\"\n        logging.debug(\"send a message to the server\")\n\n        if self.url is None:\n            logger.error(\"No asr server, please input valid ip and port\")\n            return \"\"\n\n        # 1. send websocket handshake protocol\n        start_time = time.time()\n        async with websockets.connect(self.url) as ws:\n            # 2. server has already received handshake protocol\n            # client start to send the command\n            audio_info = json.dumps(\n                {\n                    \"name\": \"test.wav\",\n                    \"signal\": \"start\",\n                    \"nbest\": 1\n                },\n                sort_keys=True,\n                indent=4,\n                separators=(',', ': '))\n            await ws.send(audio_info)\n            msg = await ws.recv()\n            logger.info(\"client receive msg={}\".format(msg))\n\n            # 3. send chunk audio data to engine\n            for chunk_data in self.read_wave(wavfile_path):\n                await ws.send(chunk_data.tobytes())\n                msg = await ws.recv()\n                msg = json.loads(msg)\n                logger.info(\"client receive msg={}\".format(msg))\n            #client start to punctuation restore\n            if self.punc_server and len(msg['result']) > 0:\n                msg[\"result\"] = self.punc_server.run(msg[\"result\"])\n                logger.info(\"client punctuation restored msg={}\".format(msg))\n            # 4. we must send finished signal to the server\n            audio_info = json.dumps(\n                {\n                    \"name\": \"test.wav\",\n                    \"signal\": \"end\",\n                    \"nbest\": 1\n                },\n                sort_keys=True,\n                indent=4,\n                separators=(',', ': '))\n            await ws.send(audio_info)\n            msg = await ws.recv()\n\n            # 5. decode the bytes to str\n            msg = json.loads(msg)\n\n            if self.punc_server:\n                msg[\"result\"] = self.punc_server.run(msg[\"result\"])\n\n            # 6. logging the final result and comptute the statstics\n            elapsed_time = time.time() - start_time\n            audio_info = soundfile.info(wavfile_path)\n            logger.info(\"client final receive msg={}\".format(msg))\n            logger.info(\n                f\"audio duration: {audio_info.duration}, elapsed time: {elapsed_time}, RTF={elapsed_time/audio_info.duration}\"\n            )\n\n            result = msg\n\n            return result\n\n\nclass ASRHttpHandler:\n    def __init__(self, server_ip=None, port=None, endpoint=\"/paddlespeech/asr\"):\n        \"\"\"The ASR client http request\n\n        Args:\n            server_ip (str, optional): the http asr server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the http asr server port. Defaults to 8090.\n        \"\"\"\n        super().__init__()\n        self.server_ip = server_ip\n        self.port = port\n        if server_ip is None or port is None:\n            self.url = None\n        else:\n            self.url = 'http://' + self.server_ip + \":\" + str(\n                self.port) + endpoint\n        logger.info(f\"endpoint: {self.url}\")\n\n    def run(self, input, audio_format, sample_rate, lang):\n        \"\"\"Call the http asr to process the audio\n\n        Args:\n            input (str): the audio file path\n            audio_format (str): the audio format\n            sample_rate (str): the audio sample rate\n            lang (str): the audio language type\n\n        Returns:\n            str: the final asr result\n        \"\"\"\n        if self.url is None:\n            logger.error(\n                \"No punctuation server, please input valid ip and port\")\n            return \"\"\n\n        audio = wav2base64(input)\n        data = {\n            \"audio\": audio,\n            \"audio_format\": audio_format,\n            \"sample_rate\": sample_rate,\n            \"lang\": lang,\n        }\n\n        res = requests.post(url=self.url, data=json.dumps(data))\n\n        return res.json()\n\n\nclass TTSWsHandler:\n    def __init__(self, server=\"127.0.0.1\", port=8092, play: bool=False):\n        \"\"\"PaddleSpeech Online TTS Server Client  audio handler\n           Online tts server use the websocket protocol\n        Args:\n            server (str, optional): the server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the server port. Defaults to 8092.\n            play (bool, optional): whether to play audio. Defaults False\n        \"\"\"\n        self.server = server\n        self.port = port\n        self.url = \"ws://\" + self.server + \":\" + str(\n            self.port) + \"/paddlespeech/tts/streaming\"\n        self.play = play\n\n        # get model sample rate\n        self.url_get_sr = \"http://\" + str(self.server) + \":\" + str(\n            self.port) + \"/paddlespeech/tts/streaming/samplerate\"\n        self.sample_rate = requests.get(self.url_get_sr).json()[\"sample_rate\"]\n\n        if self.play:\n            import pyaudio\n            self.buffer = b''\n            self.p = pyaudio.PyAudio()\n            self.stream = self.p.open(\n                format=self.p.get_format_from_width(2),\n                channels=1,\n                rate=self.sample_rate,\n                output=True)\n            self.mutex = threading.Lock()\n            self.start_play = True\n            self.t = threading.Thread(target=self.play_audio)\n            self.max_fail = 50\n        logger.info(f\"endpoint: {self.url}\")\n\n    def play_audio(self):\n        while True:\n            if not self.buffer:\n                self.max_fail -= 1\n                time.sleep(0.05)\n                if self.max_fail < 0:\n                    break\n            self.mutex.acquire()\n            self.stream.write(self.buffer)\n            self.buffer = b''\n            self.mutex.release()\n\n    async def run(self, text: str, spk_id=0, output: str=None):\n        \"\"\"Send a text to online server\n\n        Args:\n            text (str): sentence to be synthesized\n            spk_id (int, optional): speaker id. Defaults to 0.\n            output (str, optional): client save audio path. Defaults to None.\n        \"\"\"\n        all_bytes = b''\n        receive_time_list = []\n        chunk_duration_list = []\n\n        # 1. Send websocket handshake request\n        async with websockets.connect(self.url) as ws:\n            # 2. Server has already received handshake response, send start request\n            start_request = json.dumps({\"task\": \"tts\", \"signal\": \"start\"})\n            await ws.send(start_request)\n            msg = await ws.recv()\n            logger.info(f\"client receive msg={msg}\")\n            msg = json.loads(msg)\n            session = msg[\"session\"]\n\n            # 3. send speech synthesis request \n            #text_base64 = str(base64.b64encode((text).encode('utf-8')), \"UTF8\")\n            params = {\n                \"text\": text,\n                \"spk_id\": spk_id,\n            }\n\n            request = json.dumps(params)\n            st = time.time()\n            await ws.send(request)\n            logging.debug(\"send a message to the server\")\n\n            # 4. Process the received response\n            message = await ws.recv()\n            first_response = time.time() - st\n            message = json.loads(message)\n            status = message[\"status\"]\n            while True:\n                # When throw an exception\n                if status == -1:\n                    # send end request\n                    end_request = json.dumps({\n                        \"task\": \"tts\",\n                        \"signal\": \"end\",\n                        \"session\": session\n                    })\n                    await ws.send(end_request)\n                    break\n\n                # Rerutn last packet normally, no audio information\n                elif status == 2:\n                    final_response = time.time() - st\n                    duration = len(all_bytes) / 2.0 / self.sample_rate\n\n                    if output is not None:\n                        save_audio_success = save_audio(all_bytes, output,\n                                                        self.sample_rate)\n                    else:\n                        save_audio_success = False\n\n                    # send end request\n                    end_request = json.dumps({\n                        \"task\": \"tts\",\n                        \"signal\": \"end\",\n                        \"session\": session\n                    })\n                    await ws.send(end_request)\n                    break\n\n                # Return the audio stream normally\n                elif status == 1:\n                    receive_time_list.append(time.time())\n                    audio = message[\"audio\"]\n                    audio = base64.b64decode(audio)  # bytes\n                    chunk_duration_list.append(\n                        len(audio) / 2.0 / self.sample_rate)\n                    all_bytes += audio\n                    if self.play:\n                        self.mutex.acquire()\n                        self.buffer += audio\n                        self.mutex.release()\n                        if self.start_play:\n                            self.t.start()\n                            self.start_play = False\n\n                    message = await ws.recv()\n                    message = json.loads(message)\n                    status = message[\"status\"]\n\n                else:\n                    logger.error(\"infer error, return status is invalid.\")\n\n            if self.play:\n                self.t.join()\n                self.stream.stop_stream()\n                self.stream.close()\n                self.p.terminate()\n\n        return first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list\n\n\nclass TTSHttpHandler:\n    def __init__(self, server=\"127.0.0.1\", port=8092, play: bool=False):\n        \"\"\"PaddleSpeech Online TTS Server Client  audio handler\n           Online tts server use the websocket protocol\n        Args:\n            server (str, optional): the server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the server port. Defaults to 8092.\n            play (bool, optional): whether to play audio. Defaults False\n        \"\"\"\n        self.server = server\n        self.port = port\n        self.url = \"http://\" + str(self.server) + \":\" + str(\n            self.port) + \"/paddlespeech/tts/streaming\"\n        self.play = play\n\n        # get model sample rate\n        self.url_get_sr = \"http://\" + str(self.server) + \":\" + str(\n            self.port) + \"/paddlespeech/tts/streaming/samplerate\"\n        self.sample_rate = requests.get(self.url_get_sr).json()[\"sample_rate\"]\n\n        if self.play:\n            import pyaudio\n            self.buffer = b''\n            self.p = pyaudio.PyAudio()\n            self.start_play = True\n            self.max_fail = 50\n\n            self.stream = self.p.open(\n                format=self.p.get_format_from_width(2),\n                channels=1,\n                rate=self.sample_rate,\n                output=True)\n            self.mutex = threading.Lock()\n            self.t = threading.Thread(target=self.play_audio)\n\n        logger.info(f\"endpoint: {self.url}\")\n\n    def play_audio(self):\n        while True:\n            if not self.buffer:\n                self.max_fail -= 1\n                time.sleep(0.05)\n                if self.max_fail < 0:\n                    break\n            self.mutex.acquire()\n            self.stream.write(self.buffer)\n            self.buffer = b''\n            self.mutex.release()\n\n    def run(self, text: str, spk_id=0, output: str=None):\n        \"\"\"Send a text to tts online server\n\n        Args:\n            text (str): sentence to be synthesized.\n            spk_id (int, optional): speaker id. Defaults to 0.\n            output (str, optional): client save audio path. Defaults to None.\n        \"\"\"\n\n        # 1. Create request\n        params = {\n            \"text\": text,\n            \"spk_id\": spk_id,\n        }\n\n        all_bytes = b''\n        first_flag = 1\n        receive_time_list = []\n        chunk_duration_list = []\n\n        # 2. Send request\n        st = time.time()\n        html = requests.post(self.url, json.dumps(params), stream=True)\n\n        # 3. Process the received response \n        for chunk in html.iter_content(chunk_size=None):\n            receive_time_list.append(time.time())\n            audio = base64.b64decode(chunk)  # bytes\n            if first_flag:\n                first_response = time.time() - st\n                first_flag = 0\n\n            if self.play:\n                self.mutex.acquire()\n                self.buffer += audio\n                self.mutex.release()\n                if self.start_play:\n                    self.t.start()\n                    self.start_play = False\n            all_bytes += audio\n            chunk_duration_list.append(len(audio) / 2.0 / self.sample_rate)\n\n        final_response = time.time() - st\n        duration = len(all_bytes) / 2.0 / self.sample_rate\n        html.close()  # when stream=True\n\n        if output is not None:\n            save_audio_success = save_audio(all_bytes, output, self.sample_rate)\n        else:\n            save_audio_success = False\n\n        if self.play:\n            self.t.join()\n            self.stream.stop_stream()\n            self.stream.close()\n            self.p.terminate()\n\n        return first_response, final_response, duration, save_audio_success, receive_time_list, chunk_duration_list\n\n\nclass VectorHttpHandler:\n    def __init__(self, server_ip=None, port=None):\n        \"\"\"The Vector client http request\n\n        Args:\n            server_ip (str, optional): the http vector server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the http vector server port. Defaults to 8090.\n        \"\"\"\n        super().__init__()\n        self.server_ip = server_ip\n        self.port = port\n        if server_ip is None or port is None:\n            self.url = None\n        else:\n            self.url = 'http://' + self.server_ip + \":\" + str(\n                self.port) + '/paddlespeech/vector'\n        logger.info(f\"endpoint: {self.url}\")\n\n    def run(self, input, audio_format, sample_rate, task=\"spk\"):\n        \"\"\"Call the http asr to process the audio\n\n        Args:\n            input (str): the audio file path\n            audio_format (str): the audio format\n            sample_rate (str): the audio sample rate\n\n        Returns:\n            list: the audio vector\n        \"\"\"\n        if self.url is None:\n            logger.error(\"No vector server, please input valid ip and port\")\n            return \"\"\n\n        audio = wav2base64(input)\n        data = {\n            \"audio\": audio,\n            \"task\": task,\n            \"audio_format\": audio_format,\n            \"sample_rate\": sample_rate,\n        }\n\n        res = requests.post(url=self.url, data=json.dumps(data))\n\n        return res\n\n\nclass VectorScoreHttpHandler:\n    def __init__(self, server_ip=None, port=None):\n        \"\"\"The Vector score client http request\n\n        Args:\n            server_ip (str, optional): the http vector server ip. Defaults to \"127.0.0.1\".\n            port (int, optional): the http vector server port. Defaults to 8090.\n        \"\"\"\n        super().__init__()\n        self.server_ip = server_ip\n        self.port = port\n        if server_ip is None or port is None:\n            self.url = None\n        else:\n            self.url = 'http://' + self.server_ip + \":\" + str(\n                self.port) + '/paddlespeech/vector/score'\n        logger.info(f\"endpoint: {self.url}\")\n\n    def run(self, enroll_audio, test_audio, audio_format, sample_rate):\n        \"\"\"Call the http asr to process the audio\n\n        Args:\n            input (str): the audio file path\n            audio_format (str): the audio format\n            sample_rate (str): the audio sample rate\n\n        Returns:\n            list: the audio vector\n        \"\"\"\n        if self.url is None:\n            logger.error(\"No vector server, please input valid ip and port\")\n            return \"\"\n\n        enroll_audio = wav2base64(enroll_audio)\n        test_audio = wav2base64(test_audio)\n        data = {\n            \"enroll_audio\": enroll_audio,\n            \"test_audio\": test_audio,\n            \"task\": \"score\",\n            \"audio_format\": audio_format,\n            \"sample_rate\": sample_rate,\n        }\n\n        res = requests.post(url=self.url, data=json.dumps(data))\n\n        return res\n"
  },
  {
    "path": "paddlespeech/server/utils/audio_process.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport wave\n\nimport numpy as np\n\nfrom paddlespeech.cli.log import logger\n\n\ndef wav2pcm(wavfile, pcmfile, data_type=np.int16):\n    \"\"\" Save the wav file as a pcm file\n\n    Args:\n        wavfile (str): wav file path\n        pcmfile (str): pcm file save path\n        data_type (type, optional): pcm sample type. Defaults to np.int16.\n    \"\"\"\n    with open(wavfile, \"rb\") as f:\n        f.seek(0)\n        f.read(44)\n        data = np.fromfile(f, dtype=data_type)\n        data.tofile(pcmfile)\n\n\ndef pcm2wav(pcm_file, wav_file, channels=1, bits=16, sample_rate=16000):\n    \"\"\"Save the pcm file as a wav file\n\n    Args:\n        pcm_file (str): pcm file path\n        wav_file (str): wav file save path\n        channels (int, optional): audio channel. Defaults to 1.\n        bits (int, optional): Bit depth. Defaults to 16.\n        sample_rate (int, optional): sample rate. Defaults to 16000.\n    \"\"\"\n    pcmf = open(pcm_file, 'rb')\n    pcmdata = pcmf.read()\n    pcmf.close()\n\n    if bits % 8 != 0:\n        logger.error(\"bits % 8 must == 0. now bits:\" + str(bits))\n\n    wavfile = wave.open(wav_file, 'wb')\n    wavfile.setnchannels(channels)\n    wavfile.setsampwidth(bits // 8)\n    wavfile.setframerate(sample_rate)\n    wavfile.writeframes(pcmdata)\n    wavfile.close()\n\n\ndef change_speed(sample_raw, speed_rate, sample_rate):\n    \"\"\"Change the audio speed by linear interpolation.\n    Note that this is an in-place transformation.\n    :param speed_rate: Rate of speed change:\n                       speed_rate > 1.0, speed up the audio;\n                       speed_rate = 1.0, unchanged;\n                       speed_rate < 1.0, slow down the audio;\n                       speed_rate <= 0.0, not allowed, raise ValueError.\n    :type speed_rate: float\n    :raises ValueError: If speed_rate <= 0.0.\n    \"\"\"\n    if speed_rate == 1.0:\n        return sample_raw\n    if speed_rate <= 0:\n        raise ValueError(\"speed_rate should be greater than zero.\")\n\n    # numpy\n    # old_length = self._samples.shape[0]\n    # new_length = int(old_length / speed_rate)\n    # old_indices = np.arange(old_length)\n    # new_indices = np.linspace(start=0, stop=old_length, num=new_length)\n    # self._samples = np.interp(new_indices, old_indices, self._samples)\n\n    # sox, slow\n    try:\n        import soxbindings as sox\n    except ImportError:\n        try:\n            from paddlespeech.s2t.utils import dynamic_pip_install\n            package = \"sox\"\n            dynamic_pip_install.install(package)\n            package = \"soxbindings\"\n            dynamic_pip_install.install(package)\n            import soxbindings as sox\n        except Exception:\n            raise RuntimeError(\"Can not install soxbindings on your system.\")\n\n    tfm = sox.Transformer()\n    tfm.set_globals(multithread=False)\n    tfm.tempo(speed_rate)\n    sample_speed = tfm.build_array(\n        input_array=sample_raw,\n        sample_rate_in=sample_rate).squeeze(-1).astype(np.float32).copy()\n\n    return sample_speed\n\n\ndef float2pcm(sig, dtype='int16'):\n    \"\"\"Convert floating point signal with a range from -1 to 1 to PCM16.\n\n    Args:\n        sig (array): Input array, must have floating point type.\n        dtype (str, optional): Desired (integer) data type. Defaults to 'int16'.\n\n    Returns:\n        numpy.ndarray: Integer data, scaled and clipped to the range of the given\n    \"\"\"\n    sig = np.asarray(sig)\n    if sig.dtype.kind != 'f':\n        raise TypeError(\"'sig' must be a float array\")\n    dtype = np.dtype(dtype)\n    if dtype.kind not in 'iu':\n        raise TypeError(\"'dtype' must be an integer type\")\n\n    i = np.iinfo(dtype)\n    abs_max = 2**(i.bits - 1)\n    offset = i.min + abs_max\n    return (sig * abs_max + offset).clip(i.min, i.max).astype(dtype)\n\n\ndef pcm2float(data):\n    \"\"\"pcm int16 to float32\n    Args:\n        audio(numpy.array): numpy.int16\n    Returns:\n        audio(numpy.array): numpy.float32\n    \"\"\"\n    if data.dtype == np.int16:\n        data = data.astype(\"float32\")\n        bits = np.iinfo(np.int16).bits\n        data = data / (2**(bits - 1))\n    return data\n\n\ndef save_audio(bytes_data, audio_path, sample_rate: int=24000) -> bool:\n    \"\"\"save byte to audio file.\n\n    Args:\n        bytes_data (bytes): audio samples, bytes format\n        audio_path (str): save audio path\n        sample_rate (int, optional): audio sample rate. Defaults to 24000.\n\n    Returns:\n        bool: Whether the audio was saved successfully\n    \"\"\"\n\n    if audio_path.endswith(\"pcm\"):\n        with open(audio_path, \"wb\") as f:\n            f.write(bytes_data)\n    elif audio_path.endswith(\"wav\"):\n        with open(\"./tmp.pcm\", \"wb\") as f:\n            f.write(bytes_data)\n        pcm2wav(\n            \"./tmp.pcm\",\n            audio_path,\n            channels=1,\n            bits=16,\n            sample_rate=sample_rate)\n        os.remove(\"./tmp.pcm\")\n    else:\n        logger.error(\"Only supports saved audio format is pcm or wav\")\n        return False\n\n    return True\n"
  },
  {
    "path": "paddlespeech/server/utils/buffer.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nclass Frame(object):\n    \"\"\"Represents a \"frame\" of audio data.\"\"\"\n\n    def __init__(self, bytes, timestamp, duration):\n        self.bytes = bytes\n        self.timestamp = timestamp\n        self.duration = duration\n\n\nclass ChunkBuffer(object):\n    def __init__(self,\n                 window_n=7,\n                 shift_n=4,\n                 window_ms=20,\n                 shift_ms=10,\n                 sample_rate=16000,\n                 sample_width=2):\n        \"\"\"audio sample data point buffer\n\n        Args:\n            window_n (int, optional): decode window frame length. Defaults to 7 frame.\n            shift_n (int, optional): decode shift frame length. Defaults to 4 frame.\n            window_ms (int, optional): frame length, ms. Defaults to 20 ms.\n            shift_ms (int, optional): shift length, ms. Defaults to 10 ms.\n            sample_rate (int, optional): audio sample rate. Defaults to 16000.\n            sample_width (int, optional): sample point bytes. Defaults to 2 bytes.\n        \"\"\"\n        self.window_n = window_n\n        self.shift_n = shift_n\n        self.window_ms = window_ms\n        self.shift_ms = shift_ms\n        self.sample_rate = sample_rate\n        self.sample_width = sample_width  # int16 = 2; float32 = 4\n\n        self.window_sec = float((self.window_n - 1) * self.shift_ms +\n                                self.window_ms) / 1000.0\n        self.shift_sec = float(self.shift_n * self.shift_ms / 1000.0)\n\n        self.window_bytes = int(self.window_sec * self.sample_rate *\n                                self.sample_width)\n        self.shift_bytes = int(self.shift_sec * self.sample_rate *\n                               self.sample_width)\n\n        self.remained_audio = b''\n        # abs timestamp from `start` or latest `reset`\n        self.timestamp = 0.0\n\n    def reset(self):\n        \"\"\"\n            reset buffer state.\n        \"\"\"\n        self.timestamp = 0.0\n        self.remained_audio = b''\n\n    def frame_generator(self, audio):\n        \"\"\"Generates audio frames from PCM audio data.\n        Takes the desired frame duration in milliseconds, the PCM data, and\n        the sample rate.\n        Yields Frames of the requested duration.\n        \"\"\"\n        audio = self.remained_audio + audio\n        self.remained_audio = b''\n\n        offset = 0\n        while offset + self.window_bytes <= len(audio):\n            yield Frame(audio[offset:offset + self.window_bytes],\n                        self.timestamp, self.window_sec)\n            self.timestamp += self.shift_sec\n            offset += self.shift_bytes\n\n        self.remained_audio += audio[offset:]\n"
  },
  {
    "path": "paddlespeech/server/utils/config.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport yaml\nfrom yacs.config import CfgNode\n\n\ndef get_config(config_file: str):\n    \"\"\"[summary]\n\n    Args:\n        config_file (str): config_file\n\n    Returns:\n        CfgNode: \n    \"\"\"\n    with open(config_file, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    return config\n"
  },
  {
    "path": "paddlespeech/server/utils/errors.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport json\nfrom enum import IntEnum\n\nfrom fastapi import Response\n\n\nclass ErrorCode(IntEnum):\n    SERVER_OK = 200  # success.\n\n    SERVER_PARAM_ERR = 400  # Input parameters are not valid.\n    SERVER_TASK_NOT_EXIST = 404  # Task is not exist.\n\n    SERVER_INTERNAL_ERR = 500  # Internal error.\n    SERVER_NETWORK_ERR = 502  # Network exception.\n    SERVER_UNKOWN_ERR = 509  # Unknown error occurred.\n\n\nErrorMsg = {\n    ErrorCode.SERVER_OK: \"success.\",\n    ErrorCode.SERVER_PARAM_ERR: \"Input parameters are not valid.\",\n    ErrorCode.SERVER_TASK_NOT_EXIST: \"Task is not exist.\",\n    ErrorCode.SERVER_INTERNAL_ERR: \"Internal error.\",\n    ErrorCode.SERVER_NETWORK_ERR: \"Network exception.\",\n    ErrorCode.SERVER_UNKOWN_ERR: \"Unknown error occurred.\"\n}\n\n\ndef failed_response(code, msg=\"\"):\n    \"\"\"Interface call failure response\n\n    Args:\n        code (int): error code number\n        msg (str, optional): Interface call failure information. Defaults to \"\".\n\n    Returns:\n        Response (json): failure json information.\n    \"\"\"\n\n    if not msg:\n        msg = ErrorMsg.get(code, \"Unknown error occurred.\")\n\n    res = {\"success\": False, \"code\": int(code), \"message\": {\"description\": msg}}\n\n    return Response(content=json.dumps(res), media_type=\"application/json\")\n"
  },
  {
    "path": "paddlespeech/server/utils/exception.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport traceback\n\nfrom paddlespeech.server.utils.errors import ErrorMsg\n\n\nclass ServerBaseException(Exception):\n    \"\"\" Server Base exception\n    \"\"\"\n\n    def __init__(self, error_code, msg=None):\n        #if msg:\n        #log.error(msg)\n        msg = msg if msg else ErrorMsg.get(error_code, \"\")\n        super(ServerBaseException, self).__init__(error_code, msg)\n        self.error_code = error_code\n        self.msg = msg\n        traceback.print_exc()\n"
  },
  {
    "path": "paddlespeech/server/utils/onnx_infer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import Optional\n\nimport onnxruntime as ort\n\nfrom paddlespeech.cli.log import logger\n\n\ndef get_sess(model_path: Optional[os.PathLike]=None, sess_conf: dict=None):\n    logger.debug(f\"ort sessconf: {sess_conf}\")\n    sess_options = ort.SessionOptions()\n    sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL\n    if sess_conf.get('graph_optimization_level', 99) == 0:\n        sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL\n    sess_options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n\n    # \"gpu:0\"\n    providers = ['CPUExecutionProvider']\n    if \"gpu\" in sess_conf.get(\"device\", \"\"):\n        device_id = int(sess_conf[\"device\"].split(\":\")[1])\n        providers = [('CUDAExecutionProvider', {'device_id': device_id})]\n\n        # fastspeech2/mb_melgan can't use trt now!\n        if sess_conf.get(\"use_trt\", 0):\n            providers = ['TensorrtExecutionProvider']\n    logger.debug(f\"ort providers: {providers}\")\n\n    if 'cpu_threads' in sess_conf:\n        sess_options.intra_op_num_threads = sess_conf.get(\"cpu_threads\", 0)\n    else:\n        sess_options.intra_op_num_threads = sess_conf.get(\n            \"intra_op_num_threads\", 0)\n\n    sess_options.inter_op_num_threads = sess_conf.get(\"inter_op_num_threads\", 0)\n\n    sess = ort.InferenceSession(\n        model_path, providers=providers, sess_options=sess_options)\n    return sess\n"
  },
  {
    "path": "paddlespeech/server/utils/paddle_predictor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nfrom typing import List\nfrom typing import Optional\n\nimport paddle\nfrom paddle.inference import Config\nfrom paddle.inference import create_predictor\n\n\ndef init_predictor(model_dir: Optional[os.PathLike]=None,\n                   model_file: Optional[os.PathLike]=None,\n                   params_file: Optional[os.PathLike]=None,\n                   predictor_conf: dict=None):\n    \"\"\"Create predictor with Paddle inference\n\n    Args:\n        model_dir (Optional[os.PathLike], optional): The path of the static model saved in the model layer. Defaults to None.\n        model_file (Optional[os.PathLike], optional): *.pdmodel file path. Defaults to None.\n        params_file (Optional[os.PathLike], optional): *.pdiparams file path.. Defaults to None.\n        predictor_conf (dict, optional): The configuration parameters of predictor. Defaults to None.\n\n    Returns:\n        predictor (PaddleInferPredictor): created predictor\n    \"\"\"\n    if model_dir is not None:\n        assert os.path.isdir(model_dir), 'Please check model dir.'\n        config = Config(args.model_dir)\n    else:\n        assert os.path.isfile(model_file) and os.path.isfile(\n            params_file), 'Please check model and parameter files.'\n        config = Config(model_file, params_file)\n\n    # set device\n    if predictor_conf[\"device\"]:\n        device = predictor_conf[\"device\"]\n    else:\n        device = paddle.get_device()\n    if \"gpu\" in device:\n        gpu_id = device.split(\":\")[-1]\n        config.enable_use_gpu(1000, int(gpu_id))\n\n    # IR optim\n    if predictor_conf[\"switch_ir_optim\"]:\n        config.switch_ir_optim()\n\n    # glog\n    if not predictor_conf[\"glog_info\"]:\n        config.disable_glog_info()\n\n    # config summary\n    if predictor_conf[\"summary\"]:\n        print(config.summary())\n\n    # memory optim\n    config.enable_memory_optim()\n\n    predictor = create_predictor(config)\n    return predictor\n\n\ndef run_model(predictor, input: List) -> List:\n    \"\"\" run predictor\n\n    Args:\n        predictor: paddle inference predictor\n        input (list): The input of predictor\n\n    Returns:\n        list: result list\n    \"\"\"\n    input_names = predictor.get_input_names()\n    for i, name in enumerate(input_names):\n        input_handle = predictor.get_input_handle(name)\n        input_handle.copy_from_cpu(input[i])\n    # do the inference\n    predictor.run()\n    results = []\n    # get out data from output tensor\n    output_names = predictor.get_output_names()\n    for i, name in enumerate(output_names):\n        output_handle = predictor.get_output_handle(name)\n        output_data = output_handle.copy_to_cpu()\n        results.append(output_data)\n\n    return results\n"
  },
  {
    "path": "paddlespeech/server/utils/util.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the \nimport base64\nimport math\n\nfrom paddlespeech.cli.log import logger\n\n\ndef wav2base64(wav_file: str):\n    \"\"\"\n    read wave file and covert to base64 string\n    \"\"\"\n    with open(wav_file, 'rb') as f:\n        base64_bytes = base64.b64encode(f.read())\n        base64_string = base64_bytes.decode('utf-8')\n    return base64_string\n\n\ndef base64towav(base64_string: str):\n    pass\n\n\ndef self_check():\n    \"\"\" self check resource\n    \"\"\"\n    return True\n\n\ndef denorm(data, mean, std):\n    \"\"\"stream am model need to denorm\n    \"\"\"\n    return data * std + mean\n\n\ndef get_chunks(data, block_size, pad_size, step):\n    \"\"\"Divide data into multiple chunks\n\n    Args:\n        data (tensor): data\n        block_size (int): [description]\n        pad_size (int): [description]\n        step (str): set \"am\" or \"voc\", generate chunk for step am or vocoder(voc)\n\n    Returns:\n        list: chunks list\n    \"\"\"\n\n    if block_size == -1:\n        return [data]\n\n    if step == \"am\":\n        data_len = data.shape[1]\n    elif step == \"voc\":\n        data_len = data.shape[0]\n    else:\n        logger.error(\"Please set correct type to get chunks, am or voc\")\n\n    chunks = []\n    n = math.ceil(data_len / block_size)\n    for i in range(n):\n        start = max(0, i * block_size - pad_size)\n        end = min((i + 1) * block_size + pad_size, data_len)\n        if step == \"am\":\n            chunks.append(data[:, start:end, :])\n        elif step == \"voc\":\n            chunks.append(data[start:end, :])\n        else:\n            logger.error(\"Please set correct type to get chunks, am or voc\")\n    return chunks\n\n\ndef compute_delay(receive_time_list, chunk_duration_list):\n    \"\"\"compute delay \n        Args:\n            receive_time_list (list): Time to receive each packet\n            chunk_duration_list (list): The audio duration corresponding to each packet\n        Returns:\n            [list]: Delay time list\n        \"\"\"\n    assert (len(receive_time_list) == len(chunk_duration_list))\n    delay_time_list = []\n    play_time = receive_time_list[0] + chunk_duration_list[0]\n    for i in range(1, len(receive_time_list)):\n        receive_time = receive_time_list[i]\n        delay_time = receive_time - play_time\n        # 有延迟\n        if delay_time > 0:\n            play_time = play_time + delay_time + chunk_duration_list[i]\n            delay_time_list.append(delay_time)\n        # 没有延迟\n        else:\n            play_time = play_time + chunk_duration_list[i]\n\n    return delay_time_list\n\n\ndef count_engine(logfile: str=\"./nohup.out\"):\n    \"\"\"For inference on the statistical engine side\n    Args:\n        logfile (str, optional): server log. Defaults to \"./nohup.out\".\n    \"\"\"\n    first_response_list = []\n    final_response_list = []\n    duration_list = []\n\n    with open(logfile, \"r\") as f:\n        for line in f.readlines():\n            if \"- first response time:\" in line:\n                first_response = float(line.splie(\" \")[-2])\n                first_response_list.append(first_response)\n            elif \"- final response time:\" in line:\n                final_response = float(line.splie(\" \")[-2])\n                final_response_list.append(final_response)\n            elif \"- The durations of audio is:\" in line:\n                duration = float(line.splie(\" \")[-2])\n                duration_list.append(duration)\n\n    assert (len(first_response_list) == len(final_response_list) and\n            len(final_response_list) == len(duration_list))\n\n    avg_first_response = sum(first_response_list) / len(first_response_list)\n    avg_final_response = sum(final_response_list) / len(final_response_list)\n    avg_duration = sum(duration_list) / len(duration_list)\n    RTF = sum(final_response_list) / sum(duration_list)\n\n    print(\n        \"************************* engine result ***************************************\"\n    )\n    print(\n        f\"test num: {len(duration_list)}, avg first response: {avg_first_response} s, avg final response: {avg_final_response} s, avg duration: {avg_duration}, RTF: {RTF}\"\n    )\n    print(\n        f\"min duration: {min(duration_list)} s, max duration: {max(duration_list)} s\"\n    )\n    print(\n        f\"max first response: {max(first_response_list)} s, min first response: {min(first_response_list)} s\"\n    )\n    print(\n        f\"max final response: {max(final_response_list)} s, min final response: {min(final_response_list)} s\"\n    )\n"
  },
  {
    "path": "paddlespeech/server/utils/vad.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport collections\n\nimport webrtcvad\n\n\nclass VADAudio():\n    def __init__(self,\n                 aggressiveness=2,\n                 rate=16000,\n                 frame_duration_ms=20,\n                 sample_width=2,\n                 padding_ms=200,\n                 padding_ratio=0.9):\n        \"\"\"Initializes VAD with given aggressivenes and sets up internal queues\"\"\"\n        self.vad = webrtcvad.Vad(aggressiveness)\n        self.rate = rate\n        self.sample_width = sample_width\n        self.frame_duration_ms = frame_duration_ms\n        self._frame_length = int(rate * (frame_duration_ms / 1000.0) *\n                                 self.sample_width)\n        self._buffer_queue = collections.deque()\n        self.ring_buffer = collections.deque(maxlen=padding_ms //\n                                             frame_duration_ms)\n        self._ratio = padding_ratio\n        self.triggered = False\n\n    def add_audio(self, audio):\n        \"\"\"Adds new audio to internal queue\"\"\"\n        for x in audio:\n            self._buffer_queue.append(x)\n\n    def frame_generator(self):\n        \"\"\"Generator that yields audio frames of frame_duration_ms\"\"\"\n        while len(self._buffer_queue) > self._frame_length:\n            frame = bytearray()\n            for _ in range(self._frame_length):\n                frame.append(self._buffer_queue.popleft())\n            yield bytes(frame)\n\n    def vad_collector(self):\n        \"\"\"Generator that yields series of consecutive audio frames comprising each utterence, separated by yielding a single None.\n            Determines voice activity by ratio of frames in padding_ms. Uses a buffer to include padding_ms prior to being triggered.\n            Example: (frame, ..., frame, None, frame, ..., frame, None, ...)\n                      |---utterence---|        |---utterence---|\n        \"\"\"\n        for frame in self.frame_generator():\n            is_speech = self.vad.is_speech(frame, self.rate)\n            if not self.triggered:\n                self.ring_buffer.append((frame, is_speech))\n                num_voiced = len(\n                    [f for f, speech in self.ring_buffer if speech])\n                if num_voiced > self._ratio * self.ring_buffer.maxlen:\n                    self.triggered = True\n                    for f, s in self.ring_buffer:\n                        yield f\n                    self.ring_buffer.clear()\n            else:\n                yield frame\n                self.ring_buffer.append((frame, is_speech))\n                num_unvoiced = len(\n                    [f for f, speech in self.ring_buffer if not speech])\n                if num_unvoiced > self._ratio * self.ring_buffer.maxlen:\n                    self.triggered = False\n                    yield None\n                    self.ring_buffer.clear()\n"
  },
  {
    "path": "paddlespeech/server/ws/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/server/ws/api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nfrom fastapi import APIRouter\n\nfrom paddlespeech.server.ws.asr_api import router as asr_router\nfrom paddlespeech.server.ws.tts_api import router as tts_router\n\n_router = APIRouter()\n\n\ndef setup_router(api_list: List):\n    \"\"\"setup router for fastapi\n    Args:\n        api_list (List): [asr, tts]\n    Returns:\n        APIRouter\n    \"\"\"\n    for api_name in api_list:\n        if api_name == 'asr':\n            _router.include_router(asr_router)\n        elif api_name == 'tts':\n            _router.include_router(tts_router)\n        else:\n            pass\n\n    return _router\n"
  },
  {
    "path": "paddlespeech/server/ws/asr_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport json\n\nfrom fastapi import APIRouter\nfrom fastapi import WebSocket\nfrom fastapi import WebSocketDisconnect\nfrom starlette.websockets import WebSocketState as WebSocketState\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\nrouter = APIRouter()\n\n\n@router.websocket('/paddlespeech/asr/streaming')\nasync def websocket_endpoint(websocket: WebSocket):\n    \"\"\"PaddleSpeech Online ASR Server api\n\n    Args:\n        websocket (WebSocket): the websocket instance\n    \"\"\"\n\n    #1. the interface wait to accept the websocket protocol header\n    #   and only we receive the header, it establish the connection with specific thread\n    await websocket.accept()\n\n    #2. if we accept the websocket headers, we will get the online asr engine instance\n    engine_pool = get_engine_pool()\n    asr_model = engine_pool['asr']\n\n    #3. each websocket connection, we will create an PaddleASRConnectionHanddler to process such audio\n    #   and each connection has its own connection instance to process the request\n    #   and only if client send the start signal, we create the PaddleASRConnectionHanddler instance\n    connection_handler = None\n\n    try:\n        #4. we do a loop to process the audio package by package according the protocol\n        #   and only if the client send finished signal, we will break the loop\n        while True:\n            # careful here, changed the source code from starlette.websockets\n            # 4.1 we wait for the client signal for the specific action\n            assert websocket.application_state == WebSocketState.CONNECTED\n            message = await websocket.receive()\n            websocket._raise_on_disconnect(message)\n\n            #4.2 text for the action command and bytes for pcm data\n            if \"text\" in message:\n                # we first parse the specific command\n                message = json.loads(message[\"text\"])\n                if 'signal' not in message:\n                    resp = {\"status\": \"ok\", \"message\": \"no valid json data\"}\n                    await websocket.send_json(resp)\n\n                # start command, we create the PaddleASRConnectionHanddler instance to process the audio data\n                # end command, we process the all the last audio pcm and return the final result\n                #              and we break the loop\n                if message['signal'] == 'start':\n                    resp = {\"status\": \"ok\", \"signal\": \"server_ready\"}\n                    # do something at beginning here\n                    # create the instance to process the audio\n                    #connection_handler = PaddleASRConnectionHanddler(asr_model)\n                    connection_handler = asr_model.new_handler()\n                    await websocket.send_json(resp)\n                elif message['signal'] == 'end':\n                    # reset single  engine for an new connection\n                    # and we will destroy the connection\n                    connection_handler.decode(is_finished=True)\n                    connection_handler.rescoring()\n                    asr_results = connection_handler.get_result()\n                    word_time_stamp = connection_handler.get_word_time_stamp()\n                    connection_handler.reset()\n\n                    resp = {\n                        \"status\": \"ok\",\n                        \"signal\": \"finished\",\n                        'result': asr_results,\n                        'times': word_time_stamp\n                    }\n                    await websocket.send_json(resp)\n                    break\n                else:\n                    resp = {\"status\": \"ok\", \"message\": \"no valid json data\"}\n                    await websocket.send_json(resp)\n\n            elif \"bytes\" in message:\n                # bytes for the pcm data\n                message = message[\"bytes\"]\n\n                # we extract the remained audio pcm \n                # and decode for the result in this package data\n                connection_handler.extract_feat(message)\n                connection_handler.decode(is_finished=False)\n\n                if connection_handler.endpoint_state:\n                    logger.info(\"endpoint: detected and rescoring.\")\n                    connection_handler.rescoring()\n                    word_time_stamp = connection_handler.get_word_time_stamp()\n\n                asr_results = connection_handler.get_result()\n\n                if connection_handler.endpoint_state:\n                    if connection_handler.continuous_decoding:\n                        logger.info(\"endpoint: continue decoding\")\n                        connection_handler.reset_continuous_decoding()\n                    else:\n                        logger.info(\"endpoint: exit decoding\")\n                        # ending by endpoint\n                        resp = {\n                            \"status\": \"ok\",\n                            \"signal\": \"finished\",\n                            'result': asr_results,\n                            'times': word_time_stamp\n                        }\n                        await websocket.send_json(resp)\n                        break\n\n                # return the current partial result\n                # if the engine create the vad instance, this connection will have many partial results \n                resp = {'result': asr_results}\n                await websocket.send_json(resp)\n\n    except WebSocketDisconnect as e:\n        logger.error(e)\n"
  },
  {
    "path": "paddlespeech/server/ws/tts_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport json\nimport uuid\n\nfrom fastapi import APIRouter\nfrom fastapi import WebSocket\nfrom starlette.websockets import WebSocketState as WebSocketState\n\nfrom paddlespeech.cli.log import logger\nfrom paddlespeech.server.engine.engine_pool import get_engine_pool\n\nrouter = APIRouter()\n\n\n@router.websocket('/paddlespeech/tts/streaming')\nasync def websocket_endpoint(websocket: WebSocket):\n    \"\"\"PaddleSpeech Online TTS Server api\n\n    Args:\n        websocket (WebSocket): the websocket instance\n    \"\"\"\n\n    #1. the interface wait to accept the websocket protocol header\n    #   and only we receive the header, it establish the connection with specific thread\n    await websocket.accept()\n\n    #2. if we accept the websocket headers, we will get the online tts engine instance\n    engine_pool = get_engine_pool()\n    tts_engine = engine_pool['tts']\n\n    connection_handler = None\n\n    if tts_engine.engine_type == \"online\":\n        from paddlespeech.server.engine.tts.online.python.tts_engine import PaddleTTSConnectionHandler\n    elif tts_engine.engine_type == \"online-onnx\":\n        from paddlespeech.server.engine.tts.online.onnx.tts_engine import PaddleTTSConnectionHandler\n    else:\n        logger.error(\"Online tts engine only support online or online-onnx.\")\n        sys.exit(-1)\n\n    try:\n        while True:\n            # careful here, changed the source code from starlette.websockets\n            assert websocket.application_state == WebSocketState.CONNECTED\n            message = await websocket.receive()\n            websocket._raise_on_disconnect(message)\n            message = json.loads(message[\"text\"])\n\n            if 'signal' in message:\n                # start request\n                if message['signal'] == 'start':\n                    session = uuid.uuid1().hex\n                    resp = {\n                        \"status\": 0,\n                        \"signal\": \"server ready\",\n                        \"session\": session\n                    }\n\n                    connection_handler = PaddleTTSConnectionHandler(tts_engine)\n                    await websocket.send_json(resp)\n\n                # end request\n                elif message['signal'] == 'end':\n                    connection_handler = None\n                    resp = {\n                        \"status\": 0,\n                        \"signal\": \"connection will be closed\",\n                        \"session\": session\n                    }\n                    await websocket.send_json(resp)\n                    break\n                else:\n                    resp = {\"status\": 0, \"signal\": \"no valid json data\"}\n                    await websocket.send_json(resp)\n\n            # speech synthesis request \n            elif 'text' in message:\n                text = message[\"text\"]\n                spk_id = message[\"spk_id\"]\n\n                # run\n                wav_generator = connection_handler.run(\n                    sentence=text, spk_id=spk_id)\n\n                while True:\n                    try:\n                        tts_results = next(wav_generator)\n                        resp = {\"status\": 1, \"audio\": tts_results}\n                        await websocket.send_json(resp)\n                    except StopIteration as e:\n                        resp = {\"status\": 2, \"audio\": ''}\n                        await websocket.send_json(resp)\n                        logger.info(\n                            \"Complete the synthesis of the audio streams\")\n                        break\n                    except Exception as e:\n                        resp = {\"status\": -1, \"audio\": ''}\n                        await websocket.send_json(resp)\n                        break\n\n            else:\n                logger.error(\n                    \"Invalid request, please check if the request is correct.\")\n\n    except Exception as e:\n        logger.error(e)\n\n\n@router.get(\"/paddlespeech/tts/streaming/samplerate\")\ndef get_samplerate():\n    try:\n        engine_pool = get_engine_pool()\n        tts_engine = engine_pool['tts']\n        logger.info(\"Get tts engine successfully.\")\n        sample_rate = tts_engine.sample_rate\n\n        response = {\"sample_rate\": sample_rate}\n\n    except ServerBaseException as e:\n        response = failed_response(e.error_code, e.msg)\n    except BaseException:\n        response = failed_response(ErrorCode.SERVER_UNKOWN_ERR)\n        traceback.print_exc()\n\n    return response\n"
  },
  {
    "path": "paddlespeech/t2s/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\n\nfrom . import datasets\nfrom . import exps\nfrom . import frontend\nfrom . import models\nfrom . import modules\nfrom . import training\nfrom . import utils\n"
  },
  {
    "path": "paddlespeech/t2s/assets/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/assets/csmsc_test.txt",
    "content": "009901 昨日，这名伤者与医生全部被警方依法刑事拘留。\n009902 钱伟长想到上海来办学校是经过深思熟虑的。\n009903 她见我一进门就骂，吃饭时也骂，骂得我抬不起头。\n009904 李述德在离开之前，只说了一句柱驼杀父亲了。\n009905 这种车票和保险单捆绑出售属于重复性购买。\n009906 戴佩妮的男友西米露接唱情歌，让她非常开心。\n009907 观大势，谋大局，出大策始终是该院的办院方针。\n009908 他们骑着摩托回家，正好为农忙时的父母帮忙。\n009909 但是因为还没到退休年龄，只能掰着指头捱日子。\n009910 这几天雨水不断，人们恨不得待在家里不出门。\n009911 没想到徐赟，张海翔两人就此玩起了人间蒸发。\n009912 藤村此番发言可能是为了凸显野田的领导能力。\n009913 程长庚，生在清王朝嘉庆年间，安徽的潜山小县。\n009914 南海海域综合补给基地码头项目正在论证中。\n009915 也就是说今晚成都市民极有可能再次看到飘雪。\n009916 随着天气转热，各地的游泳场所开始人头攒动。\n009917 更让徐先生纳闷的是，房客的手机也打不通了。\n009918 遇到颠簸时，应听从乘务员的安全指令，回座位坐好。\n009919 他在后面呆惯了，怕自己一插身后的人会不满，不敢排进去。\n009920 傍晚七个小人回来了，白雪公主说，你们就是我命中的七个小矮人吧。\n009921 他本想说，教育局管这个，他们是一路的，这样一管岂不是妓女起嫖客？\n009922 一种表示商品所有权的财物证券，也称商品证券，如提货单，交货单。\n009923 会有很丰富的东西留下来，说都说不完。\n009924 这句话像从天而降，吓得四周一片寂静。\n009925 记者所在的是受害人家属所在的右区。\n009926 不管哈大爷去哪，它都一步不离地跟着。\n009927 大家抬头望去，一只老鼠正趴在吊顶上。\n009928 我决定过年就辞职，接手我爸的废品站！\n009929 最终，中国男子乒乓球队获得此奖项。\n009930 防汛抗旱两手抓，抗旱相对抓的不够。\n009931 图们江下游地区开发开放的进展如何？\n009932 这要求中国必须有一个坚强的政党领导。\n009933 再说，关于利益上的事俺俩都不好开口。\n009934 明代瓦剌，鞑靼入侵明境也是通过此地。\n009935 咪咪舔着孩子，把它身上的毛舔干净。\n009936 是否这次的国标修订被大企业绑架了？\n009937 判决后，姚某妻子胡某不服，提起上诉。\n009938 由此可以看出邯钢的经济效益来自何处。\n009939 琳达说，是瑜伽改变了她和马儿的生活。\n009940 楼下的保安告诉记者，这里不租也不卖。\n009941 习近平说，中斯两国人民传统友谊深厚。\n009942 传闻越来越多，后来连老汉儿自己都怕了。\n009943 我怒吼一声冲上去，举起砖头砸了过去。\n009944 我现在还不会，这就回去问问发明我的人。\n009945 显然，洛阳性奴案不具备上述两个前提。\n009946 另外，杰克逊有文唇线，眼线，眉毛的动作。\n009947 昨晚，华西都市报记者电话采访了尹琪。\n009948 涅拉季科未透露这些航空公司的名称。\n009949 从运行轨迹上来说，它也不可能是星星。\n009950 目前看，如果继续加息也存在两难问题。\n009951 曾宝仪在节目录制现场大爆观众糗事。\n009952 但任凭周某怎么叫，男子仍酣睡不醒。\n009953 老大爷说，小子，你挡我财路了，知道不？\n009954 没料到，闯下大头佛的阿伟还不知悔改。\n009955 卡扎菲部落式统治已遭遇部落内讧。\n009956 这个孩子的生命一半来源于另一位女士捐赠的冷冻卵子。\n009957 出现这种泥鳅内阁的局面既是野田有意为之，也实属无奈。\n009958 济青高速济南，华山，章丘，邹平，周村，淄博，临淄站。\n009959 赵凌飞的话，反映了沈阳赛区所有奥运志愿者的共同心声。\n009960 因为，我们所发出的力量必会因难度加大而减弱。\n009961 发生事故的楼梯拐角处仍可看到血迹。\n009962 想过进公安，可能身高不够，老汉儿也不让我进去。\n009963 路上关卡很多，为了方便撤离，只好轻装前进。\n009964 原来比尔盖茨就是美国微软公司联合创始人呀。\n009965 之后他们一家三口将与双方父母往峇里岛旅游。\n009966 谢谢总理，也感谢广大网友的参与，我们明年再见。\n009967 事实上是，从来没有一个欺善怕恶的人能作出过稍大一点的成就。\n009968 我会打开邮件，你可以从那里继续。\n009969 美方对近期东海局势表示关切。\n009970 据悉，奥巴马一家人对这座冬季白宫极为满意。\n009971 打扫完你会很有成就感的，试一试，你就信了。\n009972 诺曼站在滑板车上，各就各位，准备出发啦！\n009973 塔河的寒夜，气温降到了零下三十多摄氏度。\n009974 其间，连破六点六，六点五，六点四，六点三五等多个重要关口。\n009975 算命其实只是人们的一种自我安慰和自我暗示而已，我们还是要相信科学才好。\n009976 这一切都令人欢欣鼓舞，阿讷西没理由不坚持到最后。\n009977 直至公元前一万一千年，它又再次出现。\n009978 尽量少玩电脑，少看电视，少打游戏。\n009979 从五到七，前后也就是六个月的时间。\n009980 一进咖啡店，他就遇见一张熟悉的脸。\n009981 好在众弟兄看到了把她追了回来。\n009982 有一个人说，哥们儿我们跑过它才能活。\n009983 捅了她以后，模糊记得她没咋动了。\n009984 从小到大，葛启义没有收到过压岁钱。\n009985 舞台下的你会对舞台上的你说什么？\n009986 但考生普遍认为，试题的怪多过难。\n009987 我希望每个人都能够尊重我们的隐私。\n009988 漫天的红霞使劲给两人增添气氛。\n009989 晚上加完班开车回家，太累了，迷迷糊糊开着车，走一半的时候，铛一声！\n009990 该车将三人撞倒后，在大雾中逃窜。\n009991 这人一哆嗦，方向盘也把不稳了，差点撞上了高速边道护栏。\n009992 那女孩儿委屈的说，我一回头见你已经进去了我不敢进去啊！\n009993 小明摇摇头说，不是，我只是美女看多了，想换个口味而已。\n009994 接下来，红娘要求记者交费，记者表示不知表姐身份证号码。\n009995 李东蓊表示，自己当时在法庭上发表了一次独特的公诉意见。\n009996 另一男子扑了上来，手里拿着明晃晃的长刀，向他胸口直刺。\n009997 今天，快递员拿着一个快递在办公室喊，秦王是哪个，有他快递？\n009998 这场抗议活动究竟是如何发展演变的，又究竟是谁伤害了谁？\n009999 因华国锋肖鸡，墓地设计根据其属相设计。\n010000 在狱中，张明宝悔恨交加，写了一份忏悔书。\n"
  },
  {
    "path": "paddlespeech/t2s/assets/sentences.txt",
    "content": "001 凯莫瑞安联合体的经济崩溃，迫在眉睫。\n002 对于所有想要离开那片废土，去寻找更美好生活的人来说。\n003 克哈，是你们所有人安全的港湾。\n004 为了保护尤摩扬人民不受异虫的残害，我所做的，比他们自己的领导委员会都多。\n005 无论他们如何诽谤我，我将继续为所有泰伦人的最大利益，而努力奋斗。\n006 身为你们的元首，我带领泰伦人实现了人类统治领地和经济的扩张。\n007 我们将继续成长，用行动回击那些只会说风凉话，不愿意和我们相向而行的害群之马。\n008 帝国武装力量，无数的优秀儿女，正时刻守卫着我们的家园大门，但是他们孤木难支。\n009 凡是今天应征入伍者，所获的所有刑罚罪责，减半。\n010 激进分子和异见者希望你们一听见枪声，就背弃多年的和平与繁荣。\n011 他们没有勇气和能力，带领人类穿越一个充满危险的星系。\n012 法治是我们的命脉，然而它却受到前所未有的挑战。\n013 我将恢复我们帝国的荣光，绝不会向任何外星势力低头。\n014 我已经驯服了异虫，荡平了星灵。如今它们的创造者，想要夺走我们拥有的一切。\n015 永远记住，谁才是最能保护你们的人。\n016 不要听信别人的谗言，我不是什么克隆人。"
  },
  {
    "path": "paddlespeech/t2s/assets/sentences_canton.txt",
    "content": "001 白云山爬过一次嘅，好远啊，爬上去都成两个钟\n002 睇书咯，番屋企，而家好多人好少睇书噶喎\n003 因为如果唔考试嘅话，工资好低噶\n004 冇固定噶，你中意休边日就边日噶\n005 即系太迟嘅话咧，落班太迟嘅话就喺出边食啲咯\n006 是非有公理，慎言莫冒犯别人\n007 遇上冷风雨，休太认真\n008 痴线蜘蛛条蜘蛛丝痴住枝树枝\n009 一蚊一斤鸡，一蚊一斤龟，究竟係鸡贵定係龟贵\n010 错就要认，打要企定\n011 宜家唔系事必要你讲，但系你所讲嘅说话将会成为呈堂证供\n012 人生有几多个十年，不如活得痛快\n013 嘢可以乱食，话唔可以乱讲\n014 你唔好噉心急入市先喇，淡淡定，有钱剩，睇定啲先再决定喇\n015 仔，你唔好喺度搞搞震，冇帮衬喇\n016 米话我地人穷就要任人踩，滴水都会成流水浸街\n017 佢晨早啪奶茶，同场追加奶绿，又狂怼西米露，喫啫啫猪脚煲\n018 喂！三点几嚟，饮茶先啦，做咁多都冇用嘅，老细唔锡你嘅嚟\n019 嗱嗱声即刻走去搵嘢做，人必须知道自己嘅用途\n020 人人都揸住枝苏格兰场非工业用国际线路自动溶雪16哇佬风油軚垂直升降镭射彩色洗衣干衣气垫毛笔一枝\n021 各个国家有各个国家嘅国歌"
  },
  {
    "path": "paddlespeech/t2s/assets/sentences_en.txt",
    "content": "001 Life was like a box of chocolates, you never know what you're gonna get.\n002 With great power there must come great responsibility.\n003 To be or not to be, that’s a question.\n004 A man can be destroyed but not defeated\n005 Do not, for one repulse, give up the purpose that you resolved to effort.\n006 Death is just a part of life, something we're all destined to do.\n007 I think it's hard winning a war with words. \n008 Don’t argue with the people of strong determination, because they may change the fact!\n009 Love you three thousand times."
  },
  {
    "path": "paddlespeech/t2s/assets/sentences_mix.txt",
    "content": "001 你好，欢迎使用 Paddle Speech 中英文混合 T T S 功能，开始你的合成之旅吧!\n002 我们的声学模型使用了 Fast Speech Two, 声码器使用了 Parallel Wave GAN and Hifi GAN.\n003 Paddle N L P 发布 ERNIE Tiny 全系列中文预训练小模型，快速提升预训练模型部署效率，通用信息抽取技术 U I E Tiny 系列模型全新升级，支持速度更快效果更好的 U I E 小模型。\n004 Paddle Speech 发布 P P A S R 流式语音识别系统、P P T T S 流式语音合成系统、P P V P R 全链路声纹识别系统。\n005 Paddle Bo Bo: 使用 Paddle Speech 的语音合成模块生成虚拟人的声音。\n006 热烈欢迎您在 Discussions 中提交问题，并在 Issues 中指出发现的 bug。此外，我们非常希望您参与到 Paddle Speech 的开发中！\n007 我喜欢 eat apple, 你喜欢 drink milk。\n008 我们要去云南 team building, 非常非常 happy.\n009 AI for Sceience 平台。"
  },
  {
    "path": "paddlespeech/t2s/assets/sentences_sing.txt",
    "content": "{\"utt_id\": \"2093003457\", \"input_type\": \"word\", \"text\": \"小酒窝长睫毛AP是你最美的记号\", \"notes\": \"C#4/Db4 | F#4/Gb4 | G#4/Ab4 | A#4/Bb4 F#4/Gb4 | F#4/Gb4 C#4/Db4 | C#4/Db4 | rest | C#4/Db4 | A#4/Bb4 | G#4/Ab4 | A#4/Bb4 | G#4/Ab4 | F4 | C#4/Db4\", \"note_durs\": \"0.407140 | 0.376190 | 0.242180 | 0.509550 0.183420 | 0.315400 0.235020 | 0.361660 | 0.223070 | 0.377270 | 0.340550 | 0.299620 | 0.344510 | 0.283770 | 0.323390 | 0.360340\"}\n{\"utt_id\": \"2093003458\", \"input_type\": \"phoneme\", \"phones\": \"w o m ei t ian sh ui ui b u u zh ao AP x iang n ian n i d e w ei x iao iao AP\" , \"notes\": \"C#4/Db4 C#4/Db4 D#4/Eb4 D#4/Eb4 F4 F4 F#4/Gb4 F#4/Gb4 D#4/Eb4 D#4/Eb4 D#4/Eb4 A#3/Bb3 A#3/Bb3 A#3/Bb3 rest F#4/Gb4 F#4/Gb4 F4 F4 F#4/Gb4 F#4/Gb4 F4 F4 G#4/Ab4 G#4/Ab4 D#4/Eb4 D#4/Eb4 C#4/Db4 rest\", \"note_durs\": \"0.221750 0.221750 0.414460 0.414460 0.223160 0.223160 0.430900 0.430900 0.335990 0.269270 0.269270 0.289060 0.522690 0.522690 0.355060 0.397130 0.397130 0.247690 0.247690 0.406720 0.406720 0.246830 0.246830 0.307540 0.307540 0.429910 0.429910 0.519130 0.342300\", \"is_slurs\": \"0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\"}"
  },
  {
    "path": "paddlespeech/t2s/assets/sentences_ssml.txt",
    "content": "0001 考古人员<speak>西<say-as pinyin='zang4'>藏</say-as>布达拉宫里发现一个被隐<say-as pinyin=\"cang2\">藏</say-as>的装有宝<say-as pinyin=\"zang4\">藏</say-as></speak>箱子。\r\n0002 <speak>有人询问中国银<say-as pinyin='hang2'>行</say-as>北京分<say-as pinyin='hang2 hang2'>行行</say-as>长是否叫任我<say-as pinyin='xing2'>行</say-as></speak>。\r\n0003 <speak>市委书记亲自<say-as pinyin='shuai4'>率</say-as>领审计员对这家公司进行财务审计，发现企业的利润<say-as pinyin='lv4'>率</say-as>数据虚假</speak>。\r\n0004 <speak>学生们对代<say-as pinyin='shu4'>数</say-as>理解不深刻，特别是小<say-as pinyin='shu4'>数</say-as>点，在<say-as pinyin='shu3 shu4'>数数</say-as>时容易弄错</speak>。\r\n0005 <speak>赵<say-as pinyin='chang2'>长</say-as>军从小学习武术，擅<say-as pinyin='chang2'>长</say-as>散打，<say-as pinyin='zhang3'>长</say-as>大后参军，担任连<say-as pinyin='zhang3'>长</say-as></speak>。\r\n0006 <speak>我说她<say-as pinyin='zhang3'>涨</say-as>了工资，她就<say-as pinyin='zhang4'>涨</say-as>红着脸，摇头否认</speak>。\r\n0007 <speak>请把这封信交<say-as pinyin='gei3'>给</say-as>团长，告诉他，前线的供<say-as pinyin='ji3'>给</say-as>一定要有保障</speak>。\r\n0008 <speak>矿下的<say-as pinyin='hang4'>巷</say-as>道，与北京四合院的小<say-as pinyin='xiang4'>巷</say-as>有点相似</speak>。\r\n0009 <speak>他常叹自己命<say-as pinyin='bo2'>薄</say-as>,几亩<say-as pinyin='bao2'>薄</say-as>田，种点<say-as pinyin='bo4'>薄</say-as>荷</speak>。\r\n0010 <speak>小明对天相很有研究，在<say-as pinyin='su4'>宿</say-as>舍说了一<say-as pinyin='xiu3'>宿</say-as>有关星<say-as pinyin='xiu4'>宿</say-as>的常识</speak>。"
  },
  {
    "path": "paddlespeech/t2s/audio/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .audio import AudioProcessor\nfrom .codec import *\nfrom .spec_normalizer import LogMagnitude\nfrom .spec_normalizer import NormalizerBase\n"
  },
  {
    "path": "paddlespeech/t2s/audio/audio.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport librosa\nimport numpy as np\nimport soundfile as sf\n\n__all__ = [\"AudioProcessor\"]\n\n\nclass AudioProcessor(object):\n    def __init__(self,\n                 sample_rate: int,\n                 n_fft: int,\n                 win_length: int,\n                 hop_length: int,\n                 n_mels: int=80,\n                 fmin: int=0,\n                 fmax: int=None,\n                 window=\"hann\",\n                 center=True,\n                 pad_mode=\"reflect\",\n                 normalize=True):\n        # read & write\n        self.sample_rate = sample_rate\n        self.normalize = normalize\n\n        # stft\n        self.n_fft = n_fft\n        self.win_length = win_length\n        self.hop_length = hop_length\n        self.window = window\n        self.center = center\n        self.pad_mode = pad_mode\n\n        # mel\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax\n\n        self.mel_filter = self._create_mel_filter()\n        self.inv_mel_filter = np.linalg.pinv(self.mel_filter)\n\n    def _create_mel_filter(self):\n        mel_filter = librosa.filters.mel(\n            sr=self.sample_rate,\n            n_fft=self.n_fft,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=self.fmax)\n        return mel_filter\n\n    def read_wav(self, filename):\n        # resampling may occur\n        wav, _ = librosa.load(filename, sr=self.sample_rate)\n\n        # normalize the volume\n        if self.normalize:\n            wav = wav / np.max(np.abs(wav)) * 0.999\n        return wav\n\n    def write_wav(self, path, wav):\n        sf.write(path, wav, samplerate=self.sample_rate)\n\n    def stft(self, wav):\n        D = librosa.core.stft(\n            wav,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center,\n            pad_mode=self.pad_mode)\n        return D\n\n    def istft(self, D):\n        wav = librosa.core.istft(\n            D,\n            hop_length=self.hop_length,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center)\n        return wav\n\n    def spectrogram(self, wav):\n        D = self.stft(wav)\n        return np.abs(D)\n\n    def mel_spectrogram(self, wav):\n        S = self.spectrogram(wav)\n        mel = np.dot(self.mel_filter, S)\n        return mel\n"
  },
  {
    "path": "paddlespeech/t2s/audio/codec.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport numpy as np\nimport paddle\n\n\n# x: [0: 2**bit-1], return: [-1, 1]\ndef label_2_float(x, bits):\n    return 2 * x / (2**bits - 1.) - 1.\n\n\n#x: [-1, 1], return: [0, 2**bits-1]\ndef float_2_label(x, bits):\n    assert abs(x).max() <= 1.0\n    x = (x + 1.) * (2**bits - 1) / 2\n    return x.clip(0, 2**bits - 1)\n\n\n# y: [-1, 1], mu: 2**bits, return: [0, 2**bits-1]\n# see https://en.wikipedia.org/wiki/%CE%9C-law_algorithm\n# be careful the input `mu` here, which is +1 than that of the link above\ndef encode_mu_law(x, mu):\n    mu = mu - 1\n    fx = np.sign(x) * np.log(1 + mu * np.abs(x)) / np.log(1 + mu)\n    return np.floor((fx + 1) / 2 * mu + 0.5)\n\n\n# from_labels = True:\n# y: [0: 2**bit-1], mu: 2**bits, return: [-1,1]\n# from_labels = False:\n# y: [-1, 1], return: [-1, 1]\ndef decode_mu_law(y, mu, from_labels=True):\n    # TODO: get rid of log2 - makes no sense\n    if from_labels:\n        y = label_2_float(y, math.log2(mu))\n    mu = mu - 1\n    x = paddle.sign(y) / mu * ((1 + mu)**paddle.abs(y) - 1)\n    return x\n"
  },
  {
    "path": "paddlespeech/t2s/audio/spec_normalizer.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis modules contains normalizers for spectrogram magnitude.\nNormalizers are invertible transformations. They can be used to process \nmagnitude of spectrogram before training and can also be used to recover from \nthe generated spectrogram so as to be used with vocoders like griffin lim.\n\nThe base class describe the interface. `transform` is used to perform \ntransformation and `inverse` is used to perform the inverse transformation.\n\ncheck issues:\nhttps://github.com/mozilla/TTS/issues/377\n\"\"\"\nimport numpy as np\n\n__all__ = [\"NormalizerBase\", \"LogMagnitude\", \"UnitMagnitude\"]\n\n\nclass NormalizerBase(object):\n    def transform(self, spec):\n        raise NotImplementedError(\"transform must be implemented\")\n\n    def inverse(self, normalized):\n        raise NotImplementedError(\"inverse must be implemented\")\n\n\nclass LogMagnitude(NormalizerBase):\n    \"\"\"\n    This is a simple normalizer used in Waveglow, Waveflow, tacotron2...\n    \"\"\"\n\n    def __init__(self, min=1e-5):\n        self.min = min\n\n    def transform(self, x):\n        x = np.maximum(x, self.min)\n        x = np.log(x)\n        return x\n\n    def inverse(self, x):\n        return np.exp(x)\n\n\nclass UnitMagnitude(NormalizerBase):\n    # dbscale and (0, 1) normalization\n    \"\"\"\n    This is the normalizer used in the \n    \"\"\"\n\n    def __init__(self, min=1e-5):\n        self.min = min\n\n    def transform(self, x):\n        db_scale = 20 * np.log10(np.maximum(self.min, x)) - 20\n        normalized = (db_scale + 100) / 100\n        clipped = np.clip(normalized, 0, 1)\n        return clipped\n\n    def inverse(self, x):\n        denormalized = np.clip(x, 0, 1) * 100 - 100\n        out = np.exp((denormalized + 20) / 20 * np.log(10))\n        return out\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .ljspeech import *\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/am_batch_fn.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.t2s.datasets.batch import batch_sequences\nfrom paddlespeech.t2s.modules.nets_utils import get_seg_pos\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.nets_utils import phones_masking\nfrom paddlespeech.t2s.modules.nets_utils import phones_text_masking\n\n\n# 因为要传参数，所以需要额外构建\ndef build_erniesat_collate_fn(mlm_prob: float=0.8,\n                              mean_phn_span: int=8,\n                              seg_emb: bool=False,\n                              text_masking: bool=False):\n\n    return ErnieSATCollateFn(\n        mlm_prob=mlm_prob,\n        mean_phn_span=mean_phn_span,\n        seg_emb=seg_emb,\n        text_masking=text_masking)\n\n\nclass ErnieSATCollateFn:\n    \"\"\"Functor class of common_collate_fn()\"\"\"\n\n    def __init__(self,\n                 mlm_prob: float=0.8,\n                 mean_phn_span: int=8,\n                 seg_emb: bool=False,\n                 text_masking: bool=False):\n        self.mlm_prob = mlm_prob\n        self.mean_phn_span = mean_phn_span\n        self.seg_emb = seg_emb\n        self.text_masking = text_masking\n\n    def __call__(self, exmaples):\n        return erniesat_batch_fn(\n            exmaples,\n            mlm_prob=self.mlm_prob,\n            mean_phn_span=self.mean_phn_span,\n            seg_emb=self.seg_emb,\n            text_masking=self.text_masking)\n\n\ndef erniesat_batch_fn(examples,\n                      mlm_prob: float=0.8,\n                      mean_phn_span: int=8,\n                      seg_emb: bool=False,\n                      text_masking: bool=False):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"align_start\", \"align_end\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    align_start = [\n        np.array(item[\"align_start\"], dtype=np.int64) for item in examples\n    ]\n\n    align_end = [\n        np.array(item[\"align_end\"], dtype=np.int64) for item in examples\n    ]\n\n    align_start_lengths = [\n        np.array(len(item[\"align_start\"]), dtype=np.int64) for item in examples\n    ]\n\n    # add_pad\n    text = batch_sequences(text)\n    speech = batch_sequences(speech)\n    align_start = batch_sequences(align_start)\n    align_end = batch_sequences(align_end)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    speech = paddle.to_tensor(speech)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n    align_start_lengths = paddle.to_tensor(align_start_lengths)\n\n    speech_pad = speech\n    text_pad = text\n\n    text_mask = make_non_pad_mask(\n        text_lengths, text_pad, length_dim=1).unsqueeze(-2)\n    speech_mask = make_non_pad_mask(\n        speech_lengths, speech_pad[:, :, 0], length_dim=1).unsqueeze(-2)\n\n    # for training\n    span_bdy = None\n    # for inference\n    if 'span_bdy' in examples[0].keys():\n        span_bdy = [\n            np.array(item[\"span_bdy\"], dtype=np.int64) for item in examples\n        ]\n        span_bdy = paddle.to_tensor(span_bdy)\n\n    # dual_mask 的是混合中英时候同时 mask 语音和文本\n    # ernie sat 在实现跨语言的时候都 mask 了\n    if text_masking:\n        masked_pos, text_masked_pos = phones_text_masking(\n            xs_pad=speech_pad,\n            src_mask=speech_mask,\n            text_pad=text_pad,\n            text_mask=text_mask,\n            align_start=align_start,\n            align_end=align_end,\n            align_start_lens=align_start_lengths,\n            mlm_prob=mlm_prob,\n            mean_phn_span=mean_phn_span,\n            span_bdy=span_bdy)\n    # 训练纯中文和纯英文的 -> a3t 没有对 phoneme 做 mask, 只对语音 mask 了\n    # a3t 和 ernie sat 的区别主要在于做 mask 的时候\n    else:\n        masked_pos = phones_masking(\n            xs_pad=speech_pad,\n            src_mask=speech_mask,\n            align_start=align_start,\n            align_end=align_end,\n            align_start_lens=align_start_lengths,\n            mlm_prob=mlm_prob,\n            mean_phn_span=mean_phn_span,\n            span_bdy=span_bdy)\n        text_masked_pos = paddle.zeros(paddle.shape(text_pad))\n\n    speech_seg_pos, text_seg_pos = get_seg_pos(\n        speech_pad=speech_pad,\n        text_pad=text_pad,\n        align_start=align_start,\n        align_end=align_end,\n        align_start_lens=align_start_lengths,\n        seg_emb=seg_emb)\n\n    batch = {\n        \"text\": text,\n        \"speech\": speech,\n        # need to generate\n        \"masked_pos\": masked_pos,\n        \"speech_mask\": speech_mask,\n        \"text_mask\": text_mask,\n        \"speech_seg_pos\": speech_seg_pos,\n        \"text_seg_pos\": text_seg_pos,\n        \"text_masked_pos\": text_masked_pos\n    }\n\n    return batch\n\n\ndef tacotron2_single_spk_batch_fn(examples):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    speech = paddle.to_tensor(speech)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n    }\n    return batch\n\n\ndef tacotron2_multi_spk_batch_fn(examples):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    speech = paddle.to_tensor(speech)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n    }\n    # spk_emb has a higher priority than spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = batch_sequences(spk_emb)\n        spk_emb = paddle.to_tensor(spk_emb)\n        batch[\"spk_emb\"] = spk_emb\n    elif \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\ndef speedyspeech_single_spk_batch_fn(examples):\n    # fields = [\"phones\", \"tones\", \"num_phones\", \"num_frames\", \"feats\", \"durations\"]\n    phones = [np.array(item[\"phones\"], dtype=np.int64) for item in examples]\n    tones = [np.array(item[\"tones\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    num_phones = [\n        np.array(item[\"num_phones\"], dtype=np.int64) for item in examples\n    ]\n    num_frames = [\n        np.array(item[\"num_frames\"], dtype=np.int64) for item in examples\n    ]\n\n    phones = batch_sequences(phones)\n    tones = batch_sequences(tones)\n    feats = batch_sequences(feats)\n    durations = batch_sequences(durations)\n\n    # convert each batch to paddle.Tensor\n    phones = paddle.to_tensor(phones)\n    tones = paddle.to_tensor(tones)\n    feats = paddle.to_tensor(feats)\n    durations = paddle.to_tensor(durations)\n    num_phones = paddle.to_tensor(num_phones)\n    num_frames = paddle.to_tensor(num_frames)\n    batch = {\n        \"phones\": phones,\n        \"tones\": tones,\n        \"num_phones\": num_phones,\n        \"num_frames\": num_frames,\n        \"feats\": feats,\n        \"durations\": durations,\n    }\n    return batch\n\n\ndef speedyspeech_multi_spk_batch_fn(examples):\n    # fields = [\"phones\", \"tones\", \"num_phones\", \"num_frames\", \"feats\", \"durations\", \"spk_id\"]\n    phones = [np.array(item[\"phones\"], dtype=np.int64) for item in examples]\n    tones = [np.array(item[\"tones\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    num_phones = [\n        np.array(item[\"num_phones\"], dtype=np.int64) for item in examples\n    ]\n    num_frames = [\n        np.array(item[\"num_frames\"], dtype=np.int64) for item in examples\n    ]\n\n    phones = batch_sequences(phones)\n    tones = batch_sequences(tones)\n    feats = batch_sequences(feats)\n    durations = batch_sequences(durations)\n\n    # convert each batch to paddle.Tensor\n    phones = paddle.to_tensor(phones)\n    tones = paddle.to_tensor(tones)\n    feats = paddle.to_tensor(feats)\n    durations = paddle.to_tensor(durations)\n    num_phones = paddle.to_tensor(num_phones)\n    num_frames = paddle.to_tensor(num_frames)\n    batch = {\n        \"phones\": phones,\n        \"tones\": tones,\n        \"num_phones\": num_phones,\n        \"num_frames\": num_frames,\n        \"feats\": feats,\n        \"durations\": durations,\n    }\n    if \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\ndef fastspeech2_single_spk_batch_fn(examples):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"durations\", \"pitch\", \"energy\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    pitch = batch_sequences(pitch)\n    speech = batch_sequences(speech)\n    durations = batch_sequences(durations)\n    energy = batch_sequences(energy)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    pitch = paddle.to_tensor(pitch)\n    speech = paddle.to_tensor(speech)\n    durations = paddle.to_tensor(durations)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"durations\": durations,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy\n    }\n    return batch\n\n\ndef fastspeech2_multi_spk_batch_fn(examples):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"durations\", \"pitch\", \"energy\", \"spk_id\"/\"spk_emb\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    pitch = batch_sequences(pitch)\n    speech = batch_sequences(speech)\n    durations = batch_sequences(durations)\n    energy = batch_sequences(energy)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    pitch = paddle.to_tensor(pitch)\n    speech = paddle.to_tensor(speech)\n    durations = paddle.to_tensor(durations)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"durations\": durations,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy\n    }\n    # spk_emb has a higher priority than spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = batch_sequences(spk_emb)\n        spk_emb = paddle.to_tensor(spk_emb)\n        batch[\"spk_emb\"] = spk_emb\n    elif \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\ndef diffsinger_single_spk_batch_fn(examples):\n    # fields = [\"text\", \"note\", \"note_dur\", \"is_slur\", \"text_lengths\", \\\n    # \"speech\", \"speech_lengths\", \"durations\", \"pitch\", \"energy\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    note = [np.array(item[\"note\"], dtype=np.int64) for item in examples]\n    note_dur = [\n        np.array(item[\"note_dur\"], dtype=np.float32) for item in examples\n    ]\n    is_slur = [np.array(item[\"is_slur\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    note = batch_sequences(note)\n    note_dur = batch_sequences(note_dur)\n    is_slur = batch_sequences(is_slur)\n    pitch = batch_sequences(pitch)\n    speech = batch_sequences(speech)\n    durations = batch_sequences(durations)\n    energy = batch_sequences(energy)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    note = paddle.to_tensor(note)\n    note_dur = paddle.to_tensor(note_dur)\n    is_slur = paddle.to_tensor(is_slur)\n    pitch = paddle.to_tensor(pitch)\n    speech = paddle.to_tensor(speech)\n    durations = paddle.to_tensor(durations)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"note\": note,\n        \"note_dur\": note_dur,\n        \"is_slur\": is_slur,\n        \"text_lengths\": text_lengths,\n        \"durations\": durations,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy\n    }\n    return batch\n\n\ndef diffsinger_multi_spk_batch_fn(examples):\n    # fields = [\"text\", \"note\", \"note_dur\", \"is_slur\", \"text_lengths\", \"speech\", \\\n    # \"speech_lengths\", \"durations\", \"pitch\", \"energy\", \"spk_id\"/\"spk_emb\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    note = [np.array(item[\"note\"], dtype=np.int64) for item in examples]\n    note_dur = [\n        np.array(item[\"note_dur\"], dtype=np.float32) for item in examples\n    ]\n    is_slur = [np.array(item[\"is_slur\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    note = batch_sequences(note)\n    note_dur = batch_sequences(note_dur)\n    is_slur = batch_sequences(is_slur)\n    pitch = batch_sequences(pitch)\n    speech = batch_sequences(speech)\n    durations = batch_sequences(durations)\n    energy = batch_sequences(energy)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    note = paddle.to_tensor(note)\n    note_dur = paddle.to_tensor(note_dur)\n    is_slur = paddle.to_tensor(is_slur)\n    pitch = paddle.to_tensor(pitch)\n    speech = paddle.to_tensor(speech)\n    durations = paddle.to_tensor(durations)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"note\": note,\n        \"note_dur\": note_dur,\n        \"is_slur\": is_slur,\n        \"text_lengths\": text_lengths,\n        \"durations\": durations,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy\n    }\n    # spk_emb has a higher priority than spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = batch_sequences(spk_emb)\n        spk_emb = paddle.to_tensor(spk_emb)\n        batch[\"spk_emb\"] = spk_emb\n    elif \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\ndef transformer_single_spk_batch_fn(examples):\n    # fields = [\"text\", \"text_lengths\", \"speech\", \"speech_lengths\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    speech = [np.array(item[\"speech\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    speech_lengths = [\n        np.array(item[\"speech_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    speech = paddle.to_tensor(speech)\n    text_lengths = paddle.to_tensor(text_lengths)\n    speech_lengths = paddle.to_tensor(speech_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"speech\": speech,\n        \"speech_lengths\": speech_lengths,\n    }\n    return batch\n\n\ndef vits_single_spk_batch_fn(examples):\n    \"\"\"\n    Returns:\n        Dict[str, Any]:\n            - text (Tensor): Text index tensor (B, T_text).\n            - text_lengths (Tensor): Text length tensor (B,).\n            - feats (Tensor): Feature tensor (B, T_feats, aux_channels).\n            - feats_lengths (Tensor): Feature length tensor (B,).\n            - speech (Tensor): Speech waveform tensor (B, T_wav).\n\n    \"\"\"\n    # fields = [\"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"speech\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    speech = [np.array(item[\"wave\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    feats_lengths = [\n        np.array(item[\"feats_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    feats = batch_sequences(feats)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    feats = paddle.to_tensor(feats)\n    text_lengths = paddle.to_tensor(text_lengths)\n    feats_lengths = paddle.to_tensor(feats_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"feats\": feats,\n        \"feats_lengths\": feats_lengths,\n        \"speech\": speech\n    }\n    return batch\n\n\ndef vits_multi_spk_batch_fn(examples):\n    \"\"\"\n    Returns:\n        Dict[str, Any]:\n            - text (Tensor): Text index tensor (B, T_text).\n            - text_lengths (Tensor): Text length tensor (B,).\n            - feats (Tensor): Feature tensor (B, T_feats, aux_channels).\n            - feats_lengths (Tensor): Feature length tensor (B,).\n            - speech (Tensor): Speech waveform tensor (B, T_wav).\n            - spk_id (Optional[Tensor]): Speaker index tensor (B,) or (B, 1).\n            - spk_emb (Optional[Tensor]): Speaker embedding tensor (B, spk_embed_dim).\n    \"\"\"\n    # fields = [\"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"speech\", \"spk_id\"/\"spk_emb\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    speech = [np.array(item[\"wave\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    feats_lengths = [\n        np.array(item[\"feats_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    feats = batch_sequences(feats)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    feats = paddle.to_tensor(feats)\n    text_lengths = paddle.to_tensor(text_lengths)\n    feats_lengths = paddle.to_tensor(feats_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"feats\": feats,\n        \"feats_lengths\": feats_lengths,\n        \"speech\": speech\n    }\n    # spk_emb has a higher priority than spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = batch_sequences(spk_emb)\n        spk_emb = paddle.to_tensor(spk_emb)\n        batch[\"spk_emb\"] = spk_emb\n    elif \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\ndef jets_single_spk_batch_fn(examples):\n    \"\"\"\n    Returns:\n        Dict[str, Any]:\n            - text (Tensor): Text index tensor (B, T_text).\n            - text_lengths (Tensor): Text length tensor (B,).\n            - feats (Tensor): Feature tensor (B, T_feats, aux_channels).\n            - feats_lengths (Tensor): Feature length tensor (B,).\n            - durations (Tensor): Feature tensor (B, T_text,).\n            - durations_lengths (Tensor): Durations length tensor (B,).\n            - pitch (Tensor): Feature tensor (B, pitch_length,).\n            - energy (Tensor): Feature tensor (B, energy_length,).\n            - speech (Tensor): Speech waveform tensor (B, T_wav).\n\n    \"\"\"\n    # fields = [\"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"durations\", \"pitch\", \"energy\", \"speech\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    speech = [np.array(item[\"wave\"], dtype=np.float32) for item in examples]\n\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    feats_lengths = [\n        np.array(item[\"feats_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    feats = batch_sequences(feats)\n    durations = batch_sequences(durations)\n    pitch = batch_sequences(pitch)\n    energy = batch_sequences(energy)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    feats = paddle.to_tensor(feats)\n    durations = paddle.to_tensor(durations)\n    pitch = paddle.to_tensor(pitch)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    feats_lengths = paddle.to_tensor(feats_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"feats\": feats,\n        \"feats_lengths\": feats_lengths,\n        \"durations\": durations,\n        \"durations_lengths\": text_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy,\n        \"speech\": speech,\n    }\n    return batch\n\n\ndef jets_multi_spk_batch_fn(examples):\n    \"\"\"\n    Returns:\n        Dict[str, Any]:\n            - text (Tensor): Text index tensor (B, T_text).\n            - text_lengths (Tensor): Text length tensor (B,).\n            - feats (Tensor): Feature tensor (B, T_feats, aux_channels).\n            - feats_lengths (Tensor): Feature length tensor (B,).\n            - durations (Tensor): Feature tensor (B, T_text,).\n            - durations_lengths (Tensor): Durations length tensor (B,).\n            - pitch (Tensor): Feature tensor (B, pitch_length,).\n            - energy (Tensor): Feature tensor (B, energy_length,).\n            - speech (Tensor): Speech waveform tensor (B, T_wav).\n            - spk_id (Optional[Tensor]): Speaker index tensor (B,) or (B, 1).\n            - spk_emb (Optional[Tensor]): Speaker embedding tensor (B, spk_embed_dim).\n    \"\"\"\n    # fields = [\"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"durations\", \"pitch\", \"energy\", \"speech\", \"spk_id\"/\"spk_emb\"]\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    feats = [np.array(item[\"feats\"], dtype=np.float32) for item in examples]\n    durations = [\n        np.array(item[\"durations\"], dtype=np.int64) for item in examples\n    ]\n    pitch = [np.array(item[\"pitch\"], dtype=np.float32) for item in examples]\n    energy = [np.array(item[\"energy\"], dtype=np.float32) for item in examples]\n    speech = [np.array(item[\"wave\"], dtype=np.float32) for item in examples]\n    text_lengths = [\n        np.array(item[\"text_lengths\"], dtype=np.int64) for item in examples\n    ]\n    feats_lengths = [\n        np.array(item[\"feats_lengths\"], dtype=np.int64) for item in examples\n    ]\n\n    text = batch_sequences(text)\n    feats = batch_sequences(feats)\n    durations = batch_sequences(durations)\n    pitch = batch_sequences(pitch)\n    energy = batch_sequences(energy)\n    speech = batch_sequences(speech)\n\n    # convert each batch to paddle.Tensor\n    text = paddle.to_tensor(text)\n    feats = paddle.to_tensor(feats)\n    durations = paddle.to_tensor(durations)\n    pitch = paddle.to_tensor(pitch)\n    energy = paddle.to_tensor(energy)\n    text_lengths = paddle.to_tensor(text_lengths)\n    feats_lengths = paddle.to_tensor(feats_lengths)\n\n    batch = {\n        \"text\": text,\n        \"text_lengths\": text_lengths,\n        \"feats\": feats,\n        \"feats_lengths\": feats_lengths,\n        \"durations\": durations,\n        \"durations_lengths\": text_lengths,\n        \"pitch\": pitch,\n        \"energy\": energy,\n        \"speech\": speech,\n    }\n    # spk_emb has a higher priority than spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = batch_sequences(spk_emb)\n        spk_emb = paddle.to_tensor(spk_emb)\n        batch[\"spk_emb\"] = spk_emb\n    elif \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = paddle.to_tensor(spk_id)\n        batch[\"spk_id\"] = spk_id\n    return batch\n\n\n# 因为要传参数，所以需要额外构建\ndef build_starganv2_vc_collate_fn(latent_dim: int=16, max_mel_length: int=192):\n\n    return StarGANv2VCCollateFn(\n        latent_dim=latent_dim, max_mel_length=max_mel_length)\n\n\nclass StarGANv2VCCollateFn:\n    \"\"\"Functor class of common_collate_fn()\"\"\"\n\n    def __init__(self, latent_dim: int=16, max_mel_length: int=192):\n        self.latent_dim = latent_dim\n        self.max_mel_length = max_mel_length\n\n    def random_clip(self, mel: np.array):\n        # [T, 80]\n        mel_length = mel.shape[0]\n        if mel_length > self.max_mel_length:\n            random_start = np.random.randint(0,\n                                             mel_length - self.max_mel_length)\n\n            mel = mel[random_start:random_start + self.max_mel_length, :]\n        return mel\n\n    def __call__(self, exmaples):\n        return self.starganv2_vc_batch_fn(exmaples)\n\n    def starganv2_vc_batch_fn(self, examples):\n        batch_size = len(examples)\n\n        label = [np.array(item[\"label\"], dtype=np.int64) for item in examples]\n        ref_label = [\n            np.array(item[\"ref_label\"], dtype=np.int64) for item in examples\n        ]\n\n        # 需要对 mel 进行裁剪\n        mel = [self.random_clip(item[\"mel\"]) for item in examples]\n        ref_mel = [self.random_clip(item[\"ref_mel\"]) for item in examples]\n        ref_mel_2 = [self.random_clip(item[\"ref_mel_2\"]) for item in examples]\n        mel = batch_sequences(mel)\n        ref_mel = batch_sequences(ref_mel)\n        ref_mel_2 = batch_sequences(ref_mel_2)\n\n        # convert each batch to paddle.Tensor\n        # (B,)\n        label = paddle.to_tensor(label)\n        ref_label = paddle.to_tensor(ref_label)\n        # [B, T, 80] -> [B, 1, 80, T]\n        mel = paddle.to_tensor(mel).transpose([0, 2, 1]).unsqueeze(1)\n        ref_mel = paddle.to_tensor(ref_mel).transpose([0, 2, 1]).unsqueeze(1)\n        ref_mel_2 = paddle.to_tensor(ref_mel_2).transpose(\n            [0, 2, 1]).unsqueeze(1)\n\n        z_trg = paddle.randn([batch_size, self.latent_dim])\n        z_trg2 = paddle.randn([batch_size, self.latent_dim])\n\n        batch = {\n            \"x_real\": mel,\n            \"y_org\": label,\n            \"x_ref\": ref_mel,\n            \"x_ref2\": ref_mel_2,\n            \"y_trg\": ref_label,\n            \"z_trg\": z_trg,\n            \"z_trg2\": z_trg2\n        }\n\n        return batch\n\n\n# for PaddleSlim\ndef fastspeech2_single_spk_batch_fn_static(examples):\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    text = np.array(text)\n    # do not need batch axis in infer\n    text = text[0]\n    batch = {\n        \"text\": text,\n    }\n    return batch\n\n\ndef fastspeech2_multi_spk_batch_fn_static(examples):\n    text = [np.array(item[\"text\"], dtype=np.int64) for item in examples]\n    text = np.array(text)\n    text = text[0]\n    batch = {\n        \"text\": text,\n    }\n    if \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = np.array(spk_id)\n        spk_id = spk_id[0]\n        batch[\"spk_id\"] = spk_id\n    if \"spk_emb\" in examples[0]:\n        spk_emb = [\n            np.array(item[\"spk_emb\"], dtype=np.float32) for item in examples\n        ]\n        spk_emb = np.array(spk_emb)\n        spk_emb = spk_id[spk_emb]\n        batch[\"spk_emb\"] = spk_emb\n    return batch\n\n\ndef speedyspeech_single_spk_batch_fn_static(examples):\n    phones = [np.array(item[\"phones\"], dtype=np.int64) for item in examples]\n    tones = [np.array(item[\"tones\"], dtype=np.int64) for item in examples]\n    phones = np.array(phones)\n    tones = np.array(tones)\n    phones = phones[0]\n    tones = tones[0]\n    batch = {\n        \"phones\": phones,\n        \"tones\": tones,\n    }\n    return batch\n\n\ndef speedyspeech_multi_spk_batch_fn_static(examples):\n    phones = [np.array(item[\"phones\"], dtype=np.int64) for item in examples]\n    tones = [np.array(item[\"tones\"], dtype=np.int64) for item in examples]\n    phones = np.array(phones)\n    tones = np.array(tones)\n    phones = phones[0]\n    tones = tones[0]\n    batch = {\n        \"phones\": phones,\n        \"tones\": tones,\n    }\n    if \"spk_id\" in examples[0]:\n        spk_id = [np.array(item[\"spk_id\"], dtype=np.int64) for item in examples]\n        spk_id = np.array(spk_id)\n        spk_id = spk_id[0]\n        batch[\"spk_id\"] = spk_id\n    return batch\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/batch.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nUtility functions to create batch for arrays which satisfy some conditions.\nBatch functions for text sequences, audio and spectrograms are provided.\n\"\"\"\nimport numpy as np\n\n__all__ = [\n    \"batch_text_id\",\n    \"batch_wav\",\n    \"batch_spec\",\n    \"TextIDBatcher\",\n    \"WavBatcher\",\n    \"SpecBatcher\",\n]\n\n\nclass TextIDBatcher(object):\n    \"\"\"A wrapper class for `batch_text_id`.\"\"\"\n\n    def __init__(self, pad_id=0, dtype=np.int64):\n        self.pad_id = pad_id\n        self.dtype = dtype\n\n    def __call__(self, minibatch):\n        out = batch_text_id(minibatch, pad_id=self.pad_id, dtype=self.dtype)\n        return out\n\n\ndef batch_text_id(minibatch, pad_id=0, dtype=np.int64):\n    \"\"\"Pad sequences to text_ids to the largest length and batch them.\n    \n    Args:\n        minibatch (List[np.ndarray]): list of rank-1 arrays, shape(T,), dtype np.int64, text_ids.\n        pad_id (int, optional): the id which correspond to the special pad token. Defaults to 0.\n        dtype (np.dtype, optional): the data dtype of the output. Defaults to np.int64.\n\n    Returns:\n        np.ndarray: rank-2 array of text_ids, shape(B, T), B stands for batch_size, T stands for length. The output batch.\n    \"\"\"\n    peek_example = minibatch[0]\n    assert len(peek_example.shape) == 1, \"text example is an 1D tensor\"\n    # assume (channel, n_samples) or (n_samples, )\n    lengths = [example.shape[0] for example in minibatch]\n    max_len = np.max(lengths)\n\n    batch = []\n    for example in minibatch:\n        pad_len = max_len - example.shape[0]\n        batch.append(\n            np.pad(\n                example, [(0, pad_len)],\n                mode='constant',\n                constant_values=pad_id))\n\n    return np.array(batch, dtype=dtype), np.array(lengths, dtype=np.int64)\n\n\nclass WavBatcher(object):\n    \"\"\"A wrapper class for `batch_wav`.\"\"\"\n\n    def __init__(self, pad_value=0., dtype=np.float32):\n        self.pad_value = pad_value\n        self.dtype = dtype\n\n    def __call__(self, minibatch):\n        out = batch_wav(minibatch, pad_value=self.pad_value, dtype=self.dtype)\n        return out\n\n\ndef batch_wav(minibatch, pad_value=0., dtype=np.float32):\n    \"\"\"pad audios to the largest length and batch them.\n\n    Args:\n        minibatch (List[np.ndarray]): list of rank-1 float arrays(mono-channel audio, shape(T,)), dtype float.\n        pad_value (float, optional): the pad value. Defaults to 0..\n        dtype (np.dtype, optional): the data type of the output. Defaults to np.float32.\n\n    Returns:\n        np.ndarray: shape(B, T), the output batch.\n    \"\"\"\n\n    peek_example = minibatch[0]\n    assert len(peek_example.shape) == 1, \"we only handles mono-channel wav\"\n\n    # assume (channel, n_samples) or (n_samples, )\n    lengths = [example.shape[-1] for example in minibatch]\n    max_len = np.max(lengths)\n\n    batch = []\n    for example in minibatch:\n        pad_len = max_len - example.shape[-1]\n        batch.append(\n            np.pad(\n                example, [(0, pad_len)],\n                mode='constant',\n                constant_values=pad_value))\n    return np.array(batch, dtype=dtype), np.array(lengths, dtype=np.int64)\n\n\nclass SpecBatcher(object):\n    \"\"\"A wrapper class for `batch_spec`\"\"\"\n\n    def __init__(self, pad_value=0., time_major=False, dtype=np.float32):\n        self.pad_value = pad_value\n        self.dtype = dtype\n        self.time_major = time_major\n\n    def __call__(self, minibatch):\n        out = batch_spec(\n            minibatch,\n            pad_value=self.pad_value,\n            time_major=self.time_major,\n            dtype=self.dtype)\n        return out\n\n\ndef batch_spec(minibatch, pad_value=0., time_major=False, dtype=np.float32):\n    \"\"\"Pad spectra to the largest length and batch them.\n\n    Args:\n        minibatch (List[np.ndarray]): list of rank-2 arrays of shape(F, T) for mono-channel spectrograms, or list of rank-3 arrays of shape(C, F, T) for multi-channel spectrograms(F stands for frequency bands.), dtype float.\n        pad_value (float, optional): the pad value. Defaults to 0..\n        dtype (np.dtype, optional): data type of the output. Defaults to np.float32.\n\n    Returns:\n        np.ndarray: a rank-3 array of shape(B, F, T) or (B, T, F).\n    \"\"\"\n    # assume (F, T) or (T, F)\n    peek_example = minibatch[0]\n    assert len(\n        peek_example.shape) == 2, \"we only handles mono channel spectrogram\"\n\n    # assume (F, n_frame) or (n_frame, F)\n    time_idx = 0 if time_major else -1\n    lengths = [example.shape[time_idx] for example in minibatch]\n    max_len = np.max(lengths)\n\n    batch = []\n    for example in minibatch:\n        pad_len = max_len - example.shape[time_idx]\n        if time_major:\n            batch.append(\n                np.pad(\n                    example, [(0, pad_len), (0, 0)],\n                    mode='constant',\n                    constant_values=pad_value))\n        else:\n            batch.append(\n                np.pad(\n                    example, [(0, 0), (0, pad_len)],\n                    mode='constant',\n                    constant_values=pad_value))\n    return np.array(batch, dtype=dtype), np.array(lengths, dtype=np.int64)\n\n\ndef batch_sequences(sequences, axis=0, pad_value=0):\n    seq = sequences[0]\n    ndim = seq.ndim\n    if axis < 0:\n        axis += ndim\n    dtype = seq.dtype\n    pad_value = dtype.type(pad_value)\n    seq_lengths = [seq.shape[axis] for seq in sequences]\n    max_length = np.max(seq_lengths)\n\n    padded_sequences = []\n    for seq, length in zip(sequences, seq_lengths):\n        padding = [(0, 0)] * axis + [(0, max_length - length)] + [(0, 0)] * (\n            ndim - axis - 1)\n        padded_seq = np.pad(\n            seq, padding, mode='constant', constant_values=pad_value)\n        padded_sequences.append(padded_seq)\n    batch = np.stack(padded_sequences)\n    return batch\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/data_table.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport random\nfrom multiprocessing import Manager\nfrom typing import Any\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import List\n\nimport numpy as np\nfrom paddle.io import Dataset\n\n\nclass DataTable(Dataset):\n    \"\"\"Dataset to load and convert data for general purpose.\n    Args:\n        data (List[Dict[str, Any]]): Metadata, a list of meta datum, each of which is composed of  several fields\n        fields (List[str], optional): Fields to use, if not specified, all the fields in the data are used, by default None\n        converters (Dict[str, Callable], optional): Converters used to process each field, by default None\n        use_cache (bool, optional): Whether to use cache, by default False\n\n    Raises:\n        ValueError:\n            If there is some field that does not exist in data. \n        ValueError:\n            If there is some field in converters that does not exist in fields.\n    \"\"\"\n\n    def __init__(self,\n                 data: List[Dict[str, Any]],\n                 fields: List[str]=None,\n                 converters: Dict[str, Callable]=None,\n                 use_cache: bool=False):\n        # metadata\n        self.data = data\n        assert len(data) > 0, \"This dataset has no examples\"\n\n        # peak an example to get existing fields.\n        first_example = self.data[0]\n        fields_in_data = first_example.keys()\n\n        # check all the requested fields exist\n        if fields is None:\n            self.fields = fields_in_data\n        else:\n            for field in fields:\n                if field not in fields_in_data:\n                    raise ValueError(\n                        f\"The requested field ({field}) is not found\"\n                        f\"in the data. Fields in the data is {fields_in_data}\")\n            self.fields = fields\n\n        # check converters\n        if converters is None:\n            self.converters = {}\n        else:\n            for field in converters.keys():\n                if field not in self.fields:\n                    raise ValueError(\n                        f\"The converter has a non existing field ({field})\")\n            self.converters = converters\n\n        self.use_cache = use_cache\n        if use_cache:\n            self._initialize_cache()\n\n    def _initialize_cache(self):\n        self.manager = Manager()\n        self.caches = self.manager.list()\n        self.caches += [None for _ in range(len(self))]\n\n    def _get_metadata(self, idx: int) -> Dict[str, Any]:\n        \"\"\"Return a meta-datum given an index.\"\"\"\n        return self.data[idx]\n\n    def _convert(self, meta_datum: Dict[str, Any]) -> Dict[str, Any]:\n        \"\"\"Convert a meta datum to an example by applying the corresponding \n        converters to each fields requested.\n\n        Args:\n            meta_datum (Dict[str, Any]): Meta datum\n\n        Returns:\n            Dict[str, Any]: Converted example\n        \"\"\"\n        example = {}\n        for field in self.fields:\n            converter = self.converters.get(field, None)\n            meta_datum_field = meta_datum[field]\n            if converter is not None:\n                converted_field = converter(meta_datum_field)\n            else:\n                converted_field = meta_datum_field\n            example[field] = converted_field\n        return example\n\n    def __getitem__(self, idx: int) -> Dict[str, Any]:\n        \"\"\"Get an example given an index.\n        Args:\n            idx (int): Index of the example to get\n\n        Returns:\n            Dict[str, Any]: A converted example\n        \"\"\"\n        if self.use_cache and self.caches[idx] is not None:\n            return self.caches[idx]\n\n        meta_datum = self._get_metadata(idx)\n        example = self._convert(meta_datum)\n\n        if self.use_cache:\n            self.caches[idx] = example\n\n        return example\n\n    def __len__(self) -> int:\n        \"\"\"Returns the size of the dataset.\n\n        Returns\n        -------\n        int\n            The length of the dataset\n        \"\"\"\n        return len(self.data)\n\n\nclass StarGANv2VCDataTable(DataTable):\n    def __init__(self, data: List[Dict[str, Any]]):\n        super().__init__(data)\n        raw_data = data\n        spk_id_set = list(set([item['spk_id'] for item in raw_data]))\n        data_list_per_class = {}\n        for spk_id in spk_id_set:\n            data_list_per_class[spk_id] = []\n        for item in raw_data:\n            for spk_id in spk_id_set:\n                if item['spk_id'] == spk_id:\n                    data_list_per_class[spk_id].append(item)\n        self.data_list_per_class = data_list_per_class\n\n    def __getitem__(self, idx: int) -> Dict[str, Any]:\n        \"\"\"Get an example given an index.\n        Args:\n            idx (int): Index of the example to get\n\n        Returns:\n            Dict[str, Any]: A converted example\n        \"\"\"\n        if self.use_cache and self.caches[idx] is not None:\n            return self.caches[idx]\n\n        data = self._get_metadata(idx)\n\n        # 裁剪放到 batch_fn 里面\n        # 返回一个字典\n        \"\"\"\n        {'utt_id': 'p225_111', 'spk_id': '1', 'speech': 'path of *.npy'}\n        \"\"\"\n        ref_data = random.choice(self.data)\n        ref_label = ref_data['spk_id']\n        ref_data_2 = random.choice(self.data_list_per_class[ref_label])\n        # mel_tensor, label, ref_mel_tensor, ref2_mel_tensor, ref_label\n        new_example = {\n            'utt_id': data['utt_id'],\n            'mel': np.load(data['speech']),\n            'label': int(data['spk_id']),\n            'ref_mel': np.load(ref_data['speech']),\n            'ref_mel_2': np.load(ref_data_2['speech']),\n            'ref_label': int(ref_label)\n        }\n\n        if self.use_cache:\n            self.caches[idx] = new_example\n\n        return new_example\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/dataset.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport six\nfrom paddle.io import Dataset\n\n__all__ = [\n    \"split\",\n    \"TransformDataset\",\n    \"CacheDataset\",\n    \"TupleDataset\",\n    \"DictDataset\",\n    \"SliceDataset\",\n    \"SubsetDataset\",\n    \"FilterDataset\",\n    \"ChainDataset\",\n]\n\n\ndef split(dataset, first_size):\n    \"\"\"A utility function to split a dataset into two datasets.\"\"\"\n    first = SliceDataset(dataset, 0, first_size)\n    second = SliceDataset(dataset, first_size, len(dataset))\n    return first, second\n\n\nclass TransformDataset(Dataset):\n    def __init__(self, dataset, transform):\n        \"\"\"Dataset which is transformed from another with a transform.\n\n        Args:\n            dataset (Dataset): the base dataset.\n            transform (callable): the transform which takes an example of the base dataset as parameter and return a new example.\n        \"\"\"\n        self._dataset = dataset\n        self._transform = transform\n\n    def __len__(self):\n        return len(self._dataset)\n\n    def __getitem__(self, i):\n        in_data = self._dataset[i]\n        return self._transform(in_data)\n\n\nclass CacheDataset(Dataset):\n    def __init__(self, dataset):\n        \"\"\"A lazy cache of the base dataset.\n\n        Args:\n            dataset (Dataset): the base dataset to cache.\n        \"\"\"\n        self._dataset = dataset\n        self._cache = dict()\n\n    def __len__(self):\n        return len(self._dataset)\n\n    def __getitem__(self, i):\n        if i not in self._cache:\n            self._cache[i] = self._dataset[i]\n        return self._cache[i]\n\n\nclass TupleDataset(Dataset):\n    def __init__(self, *datasets):\n        \"\"\"A compound dataset made from several datasets of the same length. An example of the `TupleDataset` is a tuple of examples from the constituent datasets.\n\n        Args:\n            datasets: tuple[Dataset], the constituent datasets.\n        \"\"\"\n        if not datasets:\n            raise ValueError(\"no datasets are given\")\n        length = len(datasets[0])\n        for i, dataset in enumerate(datasets):\n            if len(dataset) != length:\n                raise ValueError(\"all the datasets should have the same length.\"\n                                 \"dataset {} has a different length\".format(i))\n        self._datasets = datasets\n        self._length = length\n\n    def __getitem__(self, index):\n        # SOA\n        batches = [dataset[index] for dataset in self._datasets]\n        if isinstance(index, slice):\n            length = len(batches[0])\n            # AOS\n            return [\n                tuple([batch[i] for batch in batches])\n                for i in six.moves.range(length)\n            ]\n        else:\n            return tuple(batches)\n\n    def __len__(self):\n        return self._length\n\n\nclass DictDataset(Dataset):\n    def __init__(self, **datasets):\n        \"\"\"\n        A compound dataset made from several datasets of the same length. An \n        example of the `DictDataset` is a dict of examples from the constituent \n        datasets.\n\n        WARNING: paddle does not have a good support for DictDataset, because\n        every batch yield from a DataLoader is a list, but it cannot be a dict.\n        So you have to provide a collate function because you cannot use the\n        default one.\n\n        Args:\n            datasets: Dict[Dataset], the constituent datasets.\n        \"\"\"\n        if not datasets:\n            raise ValueError(\"no datasets are given\")\n        length = None\n        for key, dataset in six.iteritems(datasets):\n            if length is None:\n                length = len(dataset)\n            elif len(dataset) != length:\n                raise ValueError(\n                    \"all the datasets should have the same length.\"\n                    \"dataset {} has a different length\".format(key))\n        self._datasets = datasets\n        self._length = length\n\n    def __getitem__(self, index):\n        batches = {\n            key: dataset[index]\n            for key, dataset in six.iteritems(self._datasets)\n        }\n        if isinstance(index, slice):\n            length = len(six.next(six.itervalues(batches)))\n            return [{key: batch[i]\n                     for key, batch in six.iteritems(batches)}\n                    for i in six.moves.range(length)]\n        else:\n            return batches\n\n    def __len__(self):\n        return self._length\n\n\nclass SliceDataset(Dataset):\n    def __init__(self, dataset, start, finish, order=None):\n        \"\"\"A Dataset which is a slice of the base dataset.\n\n        Args:\n            dataset (Dataset): the base dataset.\n            start (int): the start of the slice.\n            finish (int): the end of the slice, not inclusive.\n            order (List[int], optional): the order, it is a permutation of the valid example ids of the base dataset. If `order` is provided, the slice is taken in `order`. Defaults to None.\n        \"\"\"\n        if start < 0 or finish > len(dataset):\n            raise ValueError(\"subset overruns the dataset.\")\n        self._dataset = dataset\n        self._start = start\n        self._finish = finish\n        self._size = finish - start\n\n        if order is not None and len(order) != len(dataset):\n            raise ValueError(\n                \"order should have the same length as the dataset\"\n                \"len(order) = {} which does not euqals len(dataset) = {} \".\n                format(len(order), len(dataset)))\n        self._order = order\n\n    def __len__(self):\n        return self._size\n\n    def __getitem__(self, i):\n        if i >= 0:\n            if i >= self._size:\n                raise IndexError('dataset index out of range')\n            index = self._start + i\n        else:\n            if i < -self._size:\n                raise IndexError('dataset index out of range')\n            index = self._finish + i\n\n        if self._order is not None:\n            index = self._order[index]\n        return self._dataset[index]\n\n\nclass SubsetDataset(Dataset):\n    def __init__(self, dataset, indices):\n        \"\"\"A Dataset which is a subset of the base dataset.\n\n        Args:\n            dataset (Dataset): the base dataset.\n            indices (Iterable[int]): the indices of the examples to pick.\n        \"\"\"\n        self._dataset = dataset\n        if len(indices) > len(dataset):\n            raise ValueError(\"subset's size larger that dataset's size!\")\n        self._indices = indices\n        self._size = len(indices)\n\n    def __len__(self):\n        return self._size\n\n    def __getitem__(self, i):\n        index = self._indices[i]\n        return self._dataset[index]\n\n\nclass FilterDataset(Dataset):\n    def __init__(self, dataset, filter_fn):\n        \"\"\"A filtered dataset.\n\n        Args:\n            dataset (Dataset): the base dataset.\n            filter_fn (callable): a callable which takes an example of the base dataset and return a boolean.\n        \"\"\"\n        self._dataset = dataset\n        self._indices = [\n            i for i in range(len(dataset)) if filter_fn(dataset[i])\n        ]\n        self._size = len(self._indices)\n\n    def __len__(self):\n        return self._size\n\n    def __getitem__(self, i):\n        index = self._indices[i]\n        return self._dataset[index]\n\n\nclass ChainDataset(Dataset):\n    def __init__(self, *datasets):\n        \"\"\"A concatenation of the several datasets which the same structure.\n\n        Args:\n            datasets (Iterable[Dataset]): datasets to concat.\n        \"\"\"\n        self._datasets = datasets\n\n    def __len__(self):\n        return sum(len(dataset) for dataset in self._datasets)\n\n    def __getitem__(self, i):\n        if i < 0:\n            raise IndexError(\"ChainDataset doesnot support negative indexing.\")\n\n        for dataset in self._datasets:\n            if i < len(dataset):\n                return dataset[i]\n            i -= len(dataset)\n\n        raise IndexError(\"dataset index out of range\")\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/get_feats.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import List\nfrom typing import Optional\nfrom typing import Union\n\nimport librosa\nimport numpy as np\nimport pyworld\nfrom scipy.interpolate import interp1d\nfrom typing_extensions import Literal\n\n\nclass LogMelFBank():\n    def __init__(self,\n                 sr: int=24000,\n                 n_fft: int=2048,\n                 hop_length: int=300,\n                 win_length: int=None,\n                 window: str=\"hann\",\n                 n_mels: int=80,\n                 fmin: int=80,\n                 fmax: int=7600,\n                 norm: Optional[Union[Literal[\"slaney\"], float]]=\"slaney\",\n                 htk: bool=False,\n                 power: float=1.0):\n        self.sr = sr\n        # stft\n        self.n_fft = n_fft\n        self.win_length = win_length\n        self.hop_length = hop_length\n        self.window = window\n        self.center = True\n        self.pad_mode = \"reflect\"\n        self.norm = norm\n        self.htk = htk\n\n        # mel\n        self.n_mels = n_mels\n        self.fmin = 0 if fmin is None else fmin\n        self.fmax = sr / 2 if fmax is None else fmax\n        self.power = power\n\n        self.mel_filter = self._create_mel_filter()\n\n    def _create_mel_filter(self):\n        mel_filter = librosa.filters.mel(\n            sr=self.sr,\n            n_fft=self.n_fft,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=self.fmax,\n            norm=self.norm,\n            htk=self.htk)\n        return mel_filter\n\n    def _stft(self, wav: np.ndarray):\n        D = librosa.core.stft(\n            wav,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center,\n            pad_mode=self.pad_mode)\n        return D\n\n    def _spectrogram(self, wav: np.ndarray):\n        D = self._stft(wav)\n        return np.abs(D)**self.power\n\n    def _mel_spectrogram(self, wav: np.ndarray):\n        S = self._spectrogram(wav)\n        mel = np.dot(self.mel_filter, S)\n        return mel\n\n    # We use different definition for log-spec between TTS and ASR\n    #   TTS: log_10(abs(stft))\n    #   ASR: log_e(power(stft))\n\n    def get_log_mel_fbank(self, wav, base='10'):\n        mel = self._mel_spectrogram(wav)\n        mel = np.clip(mel, a_min=1e-10, a_max=float(\"inf\"))\n        if base == '10':\n            mel = np.log10(mel.T)\n        elif base == 'e':\n            mel = np.log(mel.T)\n        # (num_frames, n_mels)\n        return mel\n\n\nclass Pitch():\n    def __init__(self,\n                 sr: int=24000,\n                 hop_length: int=300,\n                 f0min: int=80,\n                 f0max: int=7600):\n\n        self.sr = sr\n        self.hop_length = hop_length\n        self.f0min = f0min\n        self.f0max = f0max\n\n    def _convert_to_continuous_f0(self, f0: np.ndarray) -> np.ndarray:\n        if (f0 == 0).all():\n            print(\"All frames seems to be unvoiced, this utt will be removed.\")\n            return f0\n        # padding start and end of f0 sequence\n        start_f0 = f0[f0 != 0][0]\n        end_f0 = f0[f0 != 0][-1]\n        start_idx = np.where(f0 == start_f0)[0][0]\n        end_idx = np.where(f0 == end_f0)[0][-1]\n        f0[:start_idx] = start_f0\n        f0[end_idx:] = end_f0\n\n        # get non-zero frame index\n        nonzero_idxs = np.where(f0 != 0)[0]\n\n        # perform linear interpolation\n        interp_fn = interp1d(nonzero_idxs, f0[nonzero_idxs])\n        f0 = interp_fn(np.arange(0, f0.shape[0]))\n\n        return f0\n\n    def _calculate_f0(self,\n                      input: np.ndarray,\n                      use_continuous_f0: bool=True,\n                      use_log_f0: bool=True) -> np.ndarray:\n        input = input.astype(np.float_)\n        frame_period = 1000 * self.hop_length / self.sr\n        f0, timeaxis = pyworld.dio(\n            input,\n            fs=self.sr,\n            f0_floor=self.f0min,\n            f0_ceil=self.f0max,\n            frame_period=frame_period)\n        f0 = pyworld.stonemask(input, f0, timeaxis, self.sr)\n        if use_continuous_f0:\n            f0 = self._convert_to_continuous_f0(f0)\n        if use_log_f0:\n            nonzero_idxs = np.where(f0 != 0)[0]\n            f0[nonzero_idxs] = np.log(f0[nonzero_idxs])\n        return f0.reshape(-1)\n\n    def _average_by_duration(self, input: np.ndarray,\n                             d: np.ndarray) -> np.ndarray:\n        d_cumsum = np.pad(d.cumsum(0), (1, 0), 'constant')\n        arr_list = []\n        for start, end in zip(d_cumsum[:-1], d_cumsum[1:]):\n            arr = input[start:end]\n            mask = arr == 0\n            arr[mask] = 0\n            avg_arr = np.mean(arr, axis=0) if len(arr) != 0 else np.array(0)\n            arr_list.append(avg_arr)\n        # shape (T,1)\n        arr_list = np.expand_dims(np.array(arr_list), 0).T\n\n        return arr_list\n\n    def get_pitch(self,\n                  wav: np.ndarray,\n                  use_continuous_f0: bool=True,\n                  use_log_f0: bool=True,\n                  use_token_averaged_f0: bool=True,\n                  duration: np.ndarray=None):\n        f0 = self._calculate_f0(wav, use_continuous_f0, use_log_f0)\n        if use_token_averaged_f0 and duration is not None:\n            f0 = self._average_by_duration(f0, duration)\n        else:\n            f0 = np.expand_dims(np.array(f0), 0).T\n        return f0\n\n\nclass Energy():\n    def __init__(self,\n                 n_fft: int=2048,\n                 hop_length: int=300,\n                 win_length: int=None,\n                 window: str=\"hann\",\n                 center: bool=True,\n                 pad_mode: str=\"reflect\"):\n\n        self.n_fft = n_fft\n        self.win_length = win_length\n        self.hop_length = hop_length\n        self.window = window\n        self.center = center\n        self.pad_mode = pad_mode\n\n    def _stft(self, wav: np.ndarray):\n        D = librosa.core.stft(\n            wav,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center,\n            pad_mode=self.pad_mode)\n        return D\n\n    def _calculate_energy(self, input: np.ndarray):\n        input = input.astype(np.float32)\n        input_stft = self._stft(input)\n        input_power = np.abs(input_stft)**2\n        energy = np.sqrt(\n            np.clip(\n                np.sum(input_power, axis=0), a_min=1.0e-10, a_max=float('inf')))\n        return energy\n\n    def _average_by_duration(self, input: np.ndarray,\n                             d: np.ndarray) -> np.ndarray:\n        d_cumsum = np.pad(d.cumsum(0), (1, 0), 'constant')\n        arr_list = []\n        for start, end in zip(d_cumsum[:-1], d_cumsum[1:]):\n            arr = input[start:end]\n            avg_arr = np.mean(arr, axis=0) if len(arr) != 0 else np.array(0)\n            arr_list.append(avg_arr)\n        # shape (T,1)\n        arr_list = np.expand_dims(np.array(arr_list), 0).T\n        return arr_list\n\n    def get_energy(self,\n                   wav: np.ndarray,\n                   use_token_averaged_energy: bool=True,\n                   duration: np.ndarray=None):\n        energy = self._calculate_energy(wav)\n        if use_token_averaged_energy and duration is not None:\n            energy = self._average_by_duration(energy, duration)\n        else:\n            energy = np.expand_dims(np.array(energy), 0).T\n        return energy\n\n\nclass LinearSpectrogram():\n    def __init__(\n            self,\n            n_fft: int=1024,\n            win_length: int=None,\n            hop_length: int=256,\n            window: str=\"hann\",\n            center: bool=True, ):\n        self.n_fft = n_fft\n        self.hop_length = hop_length\n        self.win_length = win_length\n        self.window = window\n        self.center = center\n        self.n_fft = n_fft\n        self.pad_mode = \"reflect\"\n\n    def _stft(self, wav: np.ndarray):\n        D = librosa.core.stft(\n            wav,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            win_length=self.win_length,\n            window=self.window,\n            center=self.center,\n            pad_mode=self.pad_mode)\n        return D\n\n    def _spectrogram(self, wav: np.ndarray):\n        D = self._stft(wav)\n        return np.abs(D)\n\n    def get_linear_spectrogram(self, wav: np.ndarray):\n        linear_spectrogram = self._spectrogram(wav)\n        linear_spectrogram = np.clip(\n            linear_spectrogram, a_min=1e-10, a_max=float(\"inf\"))\n        return linear_spectrogram.T\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/ljspeech.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom pathlib import Path\n\nfrom paddle.io import Dataset\n\n__all__ = [\"LJSpeechMetaData\"]\n\n\nclass LJSpeechMetaData(Dataset):\n    def __init__(self, root):\n        self.root = Path(root).expanduser()\n        wav_dir = self.root / \"wavs\"\n        csv_path = self.root / \"metadata.csv\"\n        records = []\n        speaker_name = \"ljspeech\"\n        with open(str(csv_path), 'rt', encoding='utf-8') as f:\n            for line in f:\n                filename, _, normalized_text = line.strip().split(\"|\")\n                filename = str(wav_dir / (filename + \".wav\"))\n                records.append([filename, normalized_text, speaker_name])\n        self.records = records\n\n    def __getitem__(self, i):\n        return self.records[i]\n\n    def __len__(self):\n        return len(self.records)\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/preprocess_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nfrom typing import List\n\nimport librosa\nimport numpy as np\n\n\n# speaker|utt_id|phn dur phn dur ...\ndef get_phn_dur(file_name):\n    '''\n    read MFA duration.txt\n    Args:\n        file_name (str or Path): path of gen_duration_from_textgrid.py's result\n    Returns: \n        Dict: sentence: {'utt': ([char], [int])}\n    '''\n    f = open(file_name, 'r')\n    sentence = {}\n    speaker_set = set()\n    for line in f:\n        line_list = line.strip().split('|')\n        utt = line_list[0]\n        speaker = line_list[1]\n        p_d = line_list[-1]\n        speaker_set.add(speaker)\n        phn_dur = p_d.split()\n        phn = phn_dur[::2]\n        dur = phn_dur[1::2]\n        assert len(phn) == len(dur)\n        sentence[utt] = (phn, [int(i) for i in dur], speaker)\n    f.close()\n    return sentence, speaker_set\n\n\ndef note2midi(notes: List[str]) -> List[str]:\n    \"\"\"Covert note string to note id, for example: [\"C1\"] -> [24]\n\n    Args:\n        notes (List[str]): the list of note string\n\n    Returns:\n        List[str]: the list of note id\n    \"\"\"\n    midis = []\n    for note in notes:\n        if note == 'rest':\n            midi = 0\n        else:\n            midi = librosa.note_to_midi(note.split(\"/\")[0])\n        midis.append(midi)\n\n    return midis\n\n\ndef time2frame(\n        times: List[float],\n        sample_rate: int=24000,\n        n_shift: int=128, ) -> List[int]:\n    \"\"\"Convert the phoneme duration of time(s) into frames\n\n    Args:\n        times (List[float]): phoneme duration of time(s)\n        sample_rate (int, optional): sample rate. Defaults to 24000.\n        n_shift (int, optional): frame shift. Defaults to 128.\n\n    Returns:\n        List[int]: phoneme duration of frame\n    \"\"\"\n    end = 0.0\n    ends = []\n    for t in times:\n        end += t\n        ends.append(end)\n    frame_pos = librosa.time_to_frames(ends, sr=sample_rate, hop_length=n_shift)\n    durations = np.diff(frame_pos, prepend=0)\n    return durations\n\n\ndef get_sentences_svs(\n        file_name,\n        dataset: str='opencpop',\n        sample_rate: int=24000,\n        n_shift: int=128, ):\n    '''\n    read label file\n    Args:\n        file_name (str or Path): path of gen_duration_from_textgrid.py's result\n        dataset (str): dataset name\n    Returns: \n        Dict: the information of sentence, include [phone id (int)], [the frame of phone (int)], [note id (int)], [note duration (float)], [is slur (int)], text(str), speaker name (str)\n        tuple: speaker name\n    '''\n    f = open(file_name, 'r')\n    sentence = {}\n    speaker_set = set()\n    if dataset == 'opencpop':\n        speaker_set.add(\"opencpop\")\n        for line in f:\n            line_list = line.strip().split('|')\n            utt = line_list[0]\n            text = line_list[1]\n            ph = line_list[2].split()\n            midi = note2midi(line_list[3].split())\n            midi_dur = line_list[4].split()\n            ph_dur = time2frame([float(t) for t in line_list[5].split()], sample_rate=sample_rate, n_shift=n_shift)\n            is_slur = line_list[6].split()\n            assert len(ph) == len(midi) == len(midi_dur) == len(is_slur)\n            sentence[utt] = (ph, [int(i) for i in ph_dur],\n                             [int(i) for i in midi],\n                             [float(i) for i in midi_dur],\n                             [int(i) for i in is_slur], text, \"opencpop\")\n    else:\n        print(\"dataset should in {opencpop} now!\")\n\n    f.close()\n    return sentence, speaker_set\n\n\ndef merge_silence(sentence):\n    '''\n    merge silences\n    Args:\n        sentence (Dict): sentence: {'utt': (([char], [int]), str)}\n    '''\n    for utt in sentence:\n        cur_phn, cur_dur, speaker = sentence[utt]\n        new_phn = []\n        new_dur = []\n\n        # merge sp and sil\n        for i, p in enumerate(cur_phn):\n            if i > 0 and 'sil' == p and cur_phn[i - 1] in {\"sil\", \"sp\"}:\n                new_dur[-1] += cur_dur[i]\n                new_phn[-1] = 'sil'\n            else:\n                new_phn.append(p)\n                new_dur.append(cur_dur[i])\n\n        for i, (p, d) in enumerate(zip(new_phn, new_dur)):\n            if p in {\"sp\"}:\n                if d < 14:\n                    new_phn[i] = 'sp'\n                else:\n                    new_phn[i] = 'spl'\n\n        assert len(new_phn) == len(new_dur)\n        sentence[utt] = [new_phn, new_dur, speaker]\n\n\ndef get_input_token(sentence, output_path, dataset=\"baker\"):\n    '''\n    get phone set from training data and save it\n    Args:\n        sentence (Dict): sentence: {'utt': ([char], [int])}\n        output_path (str or path):path to save phone_id_map\n    '''\n    phn_token = set()\n    for utt in sentence:\n        for phn in sentence[utt][0]:\n            phn_token.add(phn)\n    phn_token = list(phn_token)\n    phn_token.sort()\n    phn_token = [\"<pad>\", \"<unk>\"] + phn_token\n    if dataset in {\"baker\", \"aishell3\"}:\n        phn_token += [\"，\", \"。\", \"？\", \"！\"]\n    # svs dataset\n    elif dataset in {\"opencpop\"}:\n        pass\n    else:\n        phn_token += [\",\", \".\", \"?\", \"!\"]\n    phn_token += [\"<eos>\"]\n\n    with open(output_path, 'w') as f:\n        for i, phn in enumerate(phn_token):\n            f.write(phn + ' ' + str(i) + '\\n')\n\n\ndef get_phones_tones(sentence,\n                     phones_output_path,\n                     tones_output_path,\n                     dataset=\"baker\"):\n    '''\n    get phone set and tone set from training data and save it\n    Args:\n        sentence (Dict): sentence: {'utt': ([char], [int])}\n        phones_output_path (str or path): path to save phone_id_map\n        tones_output_path (str or path): path to save tone_id_map\n    '''\n    phn_token = set()\n    tone_token = set()\n    for utt in sentence:\n        for label in sentence[utt][0]:\n            # split tone from finals\n            match = re.match(r'^(\\w+)([012345])$', label)\n            if match:\n                phn_token.add(match.group(1))\n                tone_token.add(match.group(2))\n            else:\n                phn_token.add(label)\n                tone_token.add('0')\n    phn_token = list(phn_token)\n    tone_token = list(tone_token)\n    phn_token.sort()\n    tone_token.sort()\n    phn_token = [\"<pad>\", \"<unk>\"] + phn_token\n    if dataset in {\"baker\", \"aishell3\"}:\n        phn_token += [\"，\", \"。\", \"？\", \"！\"]\n    else:\n        phn_token += [\",\", \".\", \"?\", \"!\"]\n    phn_token += [\"<eos>\"]\n\n    with open(phones_output_path, 'w') as f:\n        for i, phn in enumerate(phn_token):\n            f.write(phn + ' ' + str(i) + '\\n')\n    with open(tones_output_path, 'w') as f:\n        for i, tone in enumerate(tone_token):\n            f.write(tone + ' ' + str(i) + '\\n')\n\n\ndef get_spk_id_map(speaker_set, output_path):\n    speakers = sorted(list(speaker_set))\n    with open(output_path, 'w') as f:\n        for i, spk in enumerate(speakers):\n            f.write(spk + ' ' + str(i) + '\\n')\n\n\ndef compare_duration_and_mel_length(sentences, utt, mel):\n    '''\n    check duration error, correct sentences[utt] if possible, else pop sentences[utt]\n    Args:\n        sentences (Dict): sentences[utt] = [phones_list ,durations_list]\n        utt (str): utt_id\n        mel (np.ndarry): features (num_frames, n_mels)\n    '''\n\n    if utt in sentences:\n        len_diff = mel.shape[0] - sum(sentences[utt][1])\n        if len_diff != 0:\n            if len_diff > 0:\n                sentences[utt][1][-1] += len_diff\n            elif sentences[utt][1][-1] + len_diff > 0:\n                sentences[utt][1][-1] += len_diff\n            elif sentences[utt][1][0] + len_diff > 0:\n                sentences[utt][1][0] += len_diff\n            else:\n                print(\"the len_diff is unable to correct:\", len_diff)\n                sentences.pop(utt)\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/sampler.py",
    "content": "import math\n\nimport numpy as np\nfrom paddle.io import BatchSampler\n\n\nclass ErnieSATSampler(BatchSampler):\n    \"\"\"Sampler that restricts data loading to a subset of the dataset.\n    In such case, each process can pass a DistributedBatchSampler instance \n    as a DataLoader sampler, and load a subset of the original dataset that \n    is exclusive to it.\n    .. note::\n        Dataset is assumed to be of constant size.\n        \n    Args:\n        dataset(paddle.io.Dataset): this could be a `paddle.io.Dataset` implement\n                     or other python object which implemented\n                     `__len__` for BatchSampler to get sample\n                     number of data source.\n        batch_size(int): sample indice number in a mini-batch indices.\n        num_replicas(int, optional): porcess number in distributed training.\n            If :attr:`num_replicas` is None, :attr:`num_replicas` will be\n            retrieved from :code:`paddle.distributed.ParallenEnv`.\n            Default None.\n        rank(int, optional): the rank of the current process among :attr:`num_replicas`\n            processes. If :attr:`rank` is None, :attr:`rank` is retrieved from\n            :code:`paddle.distributed.ParallenEnv`. Default None.\n        shuffle(bool): whther to shuffle indices order before genrating\n            batch indices. Default False.\n        drop_last(bool): whether drop the last incomplete batch dataset size\n            is not divisible by the batch size. Default False\n    Examples:\n        .. code-block:: python\n            import numpy as np\n            from paddle.io import Dataset, DistributedBatchSampler\n            # init with dataset\n            class RandomDataset(Dataset):\n                def __init__(self, num_samples):\n                    self.num_samples = num_samples\n            \n                def __getitem__(self, idx):\n                    image = np.random.random([784]).astype('float32')\n                    label = np.random.randint(0, 9, (1, )).astype('int64')\n                    return image, label\n                \n                def __len__(self):\n                    return self.num_samples\n  \n            dataset = RandomDataset(100)\n            sampler = DistributedBatchSampler(dataset, batch_size=64)\n            for data in sampler:\n                # do something\n                break\n    \"\"\"\n\n    def __init__(self,\n                 dataset,\n                 batch_size,\n                 num_replicas=None,\n                 rank=None,\n                 shuffle=False,\n                 drop_last=False):\n        self.dataset = dataset\n\n        assert isinstance(batch_size, int) and batch_size > 0, \\\n                \"batch_size should be a positive integer\"\n        self.batch_size = batch_size\n        assert isinstance(shuffle, bool), \\\n                \"shuffle should be a boolean value\"\n        self.shuffle = shuffle\n        assert isinstance(drop_last, bool), \\\n                \"drop_last should be a boolean number\"\n\n        from paddle.distributed import ParallelEnv\n\n        if num_replicas is not None:\n            assert isinstance(num_replicas, int) and num_replicas > 0, \\\n                    \"num_replicas should be a positive integer\"\n            self.nranks = num_replicas\n        else:\n            self.nranks = ParallelEnv().nranks\n\n        if rank is not None:\n            assert isinstance(rank, int) and rank >= 0, \\\n                    \"rank should be a non-negative integer\"\n            self.local_rank = rank\n        else:\n            self.local_rank = ParallelEnv().local_rank\n\n        self.drop_last = drop_last\n        self.epoch = 0\n        self.num_samples = int(math.ceil(len(self.dataset) * 1.0 / self.nranks))\n        self.total_size = self.num_samples * self.nranks\n\n    def __iter__(self):\n        num_samples = len(self.dataset)\n        indices = np.arange(num_samples).tolist()\n        indices += indices[:(self.total_size - len(indices))]\n        assert len(indices) == self.total_size\n\n        # subsample\n        def _get_indices_by_batch_size(indices):\n            subsampled_indices = []\n            last_batch_size = self.total_size % (self.batch_size * self.nranks)\n            assert last_batch_size % self.nranks == 0\n            last_local_batch_size = last_batch_size // self.nranks\n\n            for i in range(self.local_rank * self.batch_size,\n                           len(indices) - last_batch_size,\n                           self.batch_size * self.nranks):\n                subsampled_indices.extend(indices[i:i + self.batch_size])\n\n            indices = indices[len(indices) - last_batch_size:]\n            subsampled_indices.extend(\n                indices[self.local_rank * last_local_batch_size:(\n                    self.local_rank + 1) * last_local_batch_size])\n            return subsampled_indices\n\n        if self.nranks > 1:\n            indices = _get_indices_by_batch_size(indices)\n\n        assert len(indices) == self.num_samples\n        _sample_iter = iter(indices)\n\n        batch_indices_list = []\n        batch_indices = []\n        for idx in _sample_iter:\n            batch_indices.append(idx)\n            if len(batch_indices) == self.batch_size:\n                batch_indices_list.append(batch_indices)\n                batch_indices = []\n        if not self.drop_last and len(batch_indices) > 0:\n            batch_indices_list.append(batch_indices)\n\n        if self.shuffle:\n            np.random.RandomState(self.epoch).shuffle(batch_indices_list)\n            self.epoch += 1\n\n        for batch_indices in batch_indices_list:\n            yield batch_indices\n\n    def __len__(self):\n        num_samples = self.num_samples\n        num_samples += int(not self.drop_last) * (self.batch_size - 1)\n        return num_samples // self.batch_size\n\n    def set_epoch(self, epoch):\n        \"\"\"\n        Sets the epoch number. When :attr:`shuffle=True`, this number is used\n        as seeds of random numbers. By default, users may not set this, all\n        replicas (workers) use a different random ordering for each epoch.\n        If set same number at each epoch, this sampler will yield the same\n        ordering at all epoches.\n        Arguments:\n            epoch (int): Epoch number.\n        Examples:\n            .. code-block:: python\n    \n                import numpy as np\n    \n                from paddle.io import Dataset, DistributedBatchSampler\n    \n                # init with dataset\n                class RandomDataset(Dataset):\n                    def __init__(self, num_samples):\n                        self.num_samples = num_samples\n                \n                    def __getitem__(self, idx):\n                        image = np.random.random([784]).astype('float32')\n                        label = np.random.randint(0, 9, (1, )).astype('int64')\n                        return image, label\n                    \n                    def __len__(self):\n                        return self.num_samples\n      \n                dataset = RandomDataset(100)\n                sampler = DistributedBatchSampler(dataset, batch_size=64)\n    \n                for epoch in range(10):\n                    sampler.set_epoch(epoch)\n        \"\"\"\n        self.epoch = epoch\n"
  },
  {
    "path": "paddlespeech/t2s/datasets/vocoder_batch_fn.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.t2s.audio.codec import encode_mu_law\nfrom paddlespeech.t2s.audio.codec import float_2_label\nfrom paddlespeech.t2s.audio.codec import label_2_float\n\n\nclass Clip(object):\n    \"\"\"Collate functor for training vocoders.\n    \"\"\"\n\n    def __init__(\n            self,\n            batch_max_steps=20480,\n            hop_size=256,\n            aux_context_window=0, ):\n        \"\"\"Initialize customized collater for DataLoader.\n        Args:\n\n            batch_max_steps (int): The maximum length of input signal in batch.\n            hop_size (int): Hop size of auxiliary features.\n            aux_context_window (int): Context window size for auxiliary feature conv.\n\n        \"\"\"\n        if batch_max_steps % hop_size != 0:\n            batch_max_steps += -(batch_max_steps % hop_size)\n        assert batch_max_steps % hop_size == 0\n        self.batch_max_steps = batch_max_steps\n        self.batch_max_frames = batch_max_steps // hop_size\n        self.hop_size = hop_size\n        self.aux_context_window = aux_context_window\n\n        # set useful values in random cutting\n        self.start_offset = aux_context_window\n        self.end_offset = -(self.batch_max_frames + aux_context_window)\n        self.mel_threshold = self.batch_max_frames + 2 * aux_context_window\n\n    def __call__(self, batch):\n        \"\"\"Convert into batch tensors.\n\n        Args:\n            batch (list): list of tuple of the pair of audio and features. Audio shape (T, ), features shape(T', C).\n\n        Returns:\n            Tensor:\n                Target signal batch (B, 1, T).\n            Tensor:\n                Auxiliary feature batch (B, C, T'), where\n                T = (T' - 2 * aux_context_window) * hop_size.\n        \"\"\"\n        # check length\n        batch = [\n            self._adjust_length(b['wave'], b['feats']) for b in batch\n            if b['feats'].shape[0] > self.mel_threshold\n        ]\n        xs, cs = [b[0] for b in batch], [b[1] for b in batch]\n\n        # make batch with random cut\n        c_lengths = [c.shape[0] for c in cs]\n        start_frames = np.array([\n            np.random.randint(self.start_offset, cl + self.end_offset)\n            for cl in c_lengths\n        ])\n        x_starts = start_frames * self.hop_size\n        x_ends = x_starts + self.batch_max_steps\n\n        c_starts = start_frames - self.aux_context_window\n        c_ends = start_frames + self.batch_max_frames + self.aux_context_window\n        y_batch = np.stack(\n            [x[start:end] for x, start, end in zip(xs, x_starts, x_ends)])\n        c_batch = np.stack(\n            [c[start:end] for c, start, end in zip(cs, c_starts, c_ends)])\n\n        # convert each batch to tensor, assume that each item in batch has the same length\n        y_batch = paddle.to_tensor(\n            y_batch, dtype=paddle.float32).unsqueeze(1)  # (B, 1, T)\n        c_batch = paddle.to_tensor(\n            c_batch, dtype=paddle.float32).transpose([0, 2, 1])  # (B, C, T')\n\n        return y_batch, c_batch\n\n    def _adjust_length(self, x, c):\n        \"\"\"Adjust the audio and feature lengths.\n\n        Note:\n            Basically we assume that the length of x and c are adjusted\n            through preprocessing stage, but if we use other library processed\n            features, this process will be needed.\n\n        \"\"\"\n        if len(x) < c.shape[0] * self.hop_size:\n            x = np.pad(x, (0, c.shape[0] * self.hop_size - len(x)), mode=\"edge\")\n        elif len(x) > c.shape[0] * self.hop_size:\n            x = x[:c.shape[0] * self.hop_size]\n        # check the legnth is valid\n        assert len(x) == c.shape[\n            0] * self.hop_size, f\"wave length: ({len(x)}), mel length: ({c.shape[0]})\"\n\n        return x, c\n\n\nclass WaveRNNClip(Clip):\n    def __init__(self,\n                 mode: str='RAW',\n                 batch_max_steps: int=4500,\n                 hop_size: int=300,\n                 aux_context_window: int=2,\n                 bits: int=9,\n                 mu_law: bool=True):\n        self.mode = mode\n        self.mel_win = batch_max_steps // hop_size + 2 * aux_context_window\n        self.batch_max_steps = batch_max_steps\n        self.hop_size = hop_size\n        self.aux_context_window = aux_context_window\n        self.mu_law = mu_law\n        self.batch_max_frames = batch_max_steps // hop_size\n        self.mel_threshold = self.batch_max_frames + 2 * aux_context_window\n        if self.mode == 'MOL':\n            self.bits = 16\n        else:\n            self.bits = bits\n\n    def to_quant(self, wav):\n        if self.mode == 'RAW':\n            if self.mu_law:\n                quant = encode_mu_law(wav, mu=2**self.bits)\n            else:\n                quant = float_2_label(wav, bits=self.bits)\n        elif self.mode == 'MOL':\n            quant = float_2_label(wav, bits=16)\n        quant = quant.astype(np.int64)\n        return quant\n\n    def __call__(self, batch):\n        # voc_pad = 2  this will pad the input so that the resnet can 'see' wider than input length\n        # max_offsets = n_frames - 2 - (mel_win + 2 * hp.voc_pad) = n_frames - 15\n        \"\"\"Convert into batch tensors.\n        Args:\n            batch (list): list of tuple of the pair of audio and features. Audio shape (T, ), features shape(T', C).\n\n        Returns:\n            Tensor: Input signal batch (B, 1, T).\n            Tensor: Target signal batch (B, 1, T).\n            Tensor: Auxiliary feature batch (B, C, T'), \n                where T = (T' - 2 * aux_context_window) * hop_size.\n\n        \"\"\"\n        # check length\n        batch = [\n            self._adjust_length(b['wave'], b['feats']) for b in batch\n            if b['feats'].shape[0] > self.mel_threshold\n        ]\n        wav, mel = [b[0] for b in batch], [b[1] for b in batch]\n        # mel 此处需要转置\n        mel = [x.T for x in mel]\n        max_offsets = [\n            x.shape[-1] - 2 - (self.mel_win + 2 * self.aux_context_window)\n            for x in mel\n        ]\n        # the slice point of mel selecting randomly \n        mel_offsets = [np.random.randint(0, offset) for offset in max_offsets]\n        # the slice point of wav selecting randomly, which is behind 2(=pad) frames \n        sig_offsets = [(offset + self.aux_context_window) * self.hop_size\n                       for offset in mel_offsets]\n        # mels.shape[1] = voc_seq_len // hop_length + 2 * voc_pad\n        mels = [\n            x[:, mel_offsets[i]:mel_offsets[i] + self.mel_win]\n            for i, x in enumerate(mel)\n        ]\n        # label.shape[1] = voc_seq_len + 1\n        wav = [self.to_quant(x) for x in wav]\n\n        labels = [\n            x[sig_offsets[i]:sig_offsets[i] + self.batch_max_steps + 1]\n            for i, x in enumerate(wav)\n        ]\n\n        mels = np.stack(mels).astype(np.float32)\n        labels = np.stack(labels).astype(np.int64)\n\n        mels = paddle.to_tensor(mels)\n        labels = paddle.to_tensor(labels, dtype='int64')\n        # x is input, y is label\n        x = labels[:, :self.batch_max_steps]\n        y = labels[:, 1:]\n        '''\n        mode = RAW:\n            mu_law = True:\n                quant: bits = 9   0, 1, 2, ..., 509, 510, 511  int\n            mu_law = False\n                quant bits = 9    [0， 511]  float\n        mode = MOL:\n            quant: bits = 16  [0. 65536]  float\n        '''\n        # x should be normalizes in.[0, 1] in RAW mode\n        x = label_2_float(paddle.cast(x, dtype='float32'), self.bits)\n        # y should be normalizes in.[0, 1] in MOL mode\n        if self.mode == 'MOL':\n            y = label_2_float(paddle.cast(y, dtype='float32'), self.bits)\n\n        return x, y, mels\n\n\n# for paddleslim\n\n\nclass Clip_static(Clip):\n    \"\"\"Collate functor for training vocoders.\n    \"\"\"\n\n    def __call__(self, batch):\n        \"\"\"Convert into batch tensors.\n\n        Args:\n            batch (list): list of tuple of the pair of audio and features. Audio shape (T, ), features shape(T', C).\n\n        Returns: \n            Dict[str, np.array]:\n                Auxiliary feature batch (B, C, T'), where\n                T = (T' - 2 * aux_context_window) * hop_size.\n        \"\"\"\n        # check length\n        batch = [\n            self._adjust_length(b['wave'], b['feats']) for b in batch\n            if b['feats'].shape[0] > self.mel_threshold\n        ]\n        xs, cs = [b[0] for b in batch], [b[1] for b in batch]\n\n        # make batch with random cut\n        c_lengths = [c.shape[0] for c in cs]\n        start_frames = np.array([\n            np.random.randint(self.start_offset, cl + self.end_offset)\n            for cl in c_lengths\n        ])\n\n        c_starts = start_frames - self.aux_context_window\n        c_ends = start_frames + self.batch_max_frames + self.aux_context_window\n        c_batch = np.stack(\n            [c[start:end] for c, start, end in zip(cs, c_starts, c_ends)])\n        # infer axis (T',C) is different with train axis (B, C, T')\n        # c_batch = c_batch.transpose([0, 2, 1])  # (B, C, T')\n        # do not need batch axis in infer\n        c_batch = c_batch[0]\n        batch = {\"logmel\": c_batch}\n        return batch\n"
  },
  {
    "path": "paddlespeech/t2s/exps/PTQ_dynamic.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport paddle\nfrom paddleslim.quant import quant_post_dynamic\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Slim Dynamic with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--model_name',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'fastspeech2_csmsc',\n            'fastspeech2_aishell3',\n            'fastspeech2_ljspeech',\n            'fastspeech2_vctk',\n            'tacotron2_csmsc',\n            'fastspeech2_mix',\n            'pwgan_csmsc',\n            'pwgan_aishell3',\n            'pwgan_ljspeech',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_aishell3',\n            'hifigan_ljspeech',\n            'hifigan_vctk',\n            'wavernn_csmsc',\n        ],\n        help='Choose model type of tts task.')\n\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--weight_bits\",\n        type=int,\n        default=8,\n        choices=[8, 16],\n        help=\"The bits for the quantized weight, and it should be 8 or 16. Default is 8.\",\n    )\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n    paddle.enable_static()\n    quant_post_dynamic(\n        model_dir=args.inference_dir,\n        save_model_dir=args.inference_dir,\n        model_filename=args.model_name + \".pdmodel\",\n        params_filename=args.model_name + \".pdiparams\",\n        save_model_filename=args.model_name + \"_\" + str(args.weight_bits) +\n        \"bits.pdmodel\",\n        save_params_filename=args.model_name + \"_\" + str(args.weight_bits) +\n        \"bits.pdiparams\",\n        weight_bits=args.weight_bits, )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/PTQ_static.py",
    "content": "import argparse\nimport random\n\nimport jsonlines\nimport numpy as np\nimport paddle\nfrom paddleslim.quant import quant_post_static\n\nfrom paddlespeech.t2s.exps.syn_utils import get_dev_dataloader\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Slim Static with acoustic model & vocoder.\")\n\n    parser.add_argument(\n        \"--batch_size\", type=int, default=1, help=\"Minibatch size.\")\n    parser.add_argument(\"--batch_num\", type=int, default=1, help=\"Batch number\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n    # model_path save_path\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        '--model_name',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'fastspeech2_csmsc',\n            'fastspeech2_aishell3',\n            'fastspeech2_ljspeech',\n            'fastspeech2_vctk',\n            'fastspeech2_mix',\n            'pwgan_csmsc',\n            'pwgan_aishell3',\n            'pwgan_ljspeech',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_aishell3',\n            'hifigan_ljspeech',\n            'hifigan_vctk',\n            'pwgan_opencpop',\n            'hifigan_opencpop',\n        ],\n        help='Choose model type of tts task.')\n\n    parser.add_argument(\n        \"--algo\", type=str, default='avg', help=\"calibration algorithm.\")\n    parser.add_argument(\n        \"--round_type\",\n        type=str,\n        default='round',\n        help=\"The method of converting the quantized weights.\")\n    parser.add_argument(\n        \"--hist_percent\",\n        type=float,\n        default=0.9999,\n        help=\"The percentile of algo:hist.\")\n    parser.add_argument(\n        \"--is_full_quantize\",\n        type=str2bool,\n        default=False,\n        help=\"Whether is full quantization or not.\")\n    parser.add_argument(\n        \"--bias_correction\",\n        type=str2bool,\n        default=False,\n        help=\"Whether to use bias correction.\")\n    parser.add_argument(\n        \"--ce_test\", type=str2bool, default=False, help=\"Whether to CE test.\")\n    parser.add_argument(\n        \"--onnx_format\",\n        type=str2bool,\n        default=False,\n        help=\"Whether to export the quantized model with format of ONNX.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\n        \"--quantizable_op_type\",\n        type=list,\n        nargs='+',\n        default=[\n            \"conv2d_transpose\", \"conv2d\", \"depthwise_conv2d\", \"mul\", \"matmul\",\n            \"matmul_v2\"\n        ],\n        help=\"The list of op types that will be quantized.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef quantize(args):\n    shuffle = True\n    if args.ce_test:\n        # set seed\n        seed = 111\n        np.random.seed(seed)\n        paddle.seed(seed)\n        random.seed(seed)\n        shuffle = False\n\n    place = paddle.CUDAPlace(0) if args.ngpu > 0 else paddle.CPUPlace()\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n\n    dataloader = get_dev_dataloader(\n        dev_metadata=dev_metadata,\n        am=args.model_name,\n        batch_size=args.batch_size,\n        speaker_dict=args.speaker_dict,\n        shuffle=shuffle)\n\n    exe = paddle.static.Executor(place)\n    exe.run()\n\n    print(\"onnx_format:\", args.onnx_format)\n\n    quant_post_static(\n        executor=exe,\n        model_dir=args.inference_dir,\n        quantize_model_path=args.inference_dir + \"/\" + args.model_name +\n        \"_quant\",\n        data_loader=dataloader,\n        model_filename=args.model_name + \".pdmodel\",\n        params_filename=args.model_name + \".pdiparams\",\n        save_model_filename=args.model_name + \".pdmodel\",\n        save_params_filename=args.model_name + \".pdiparams\",\n        batch_size=args.batch_size,\n        algo=args.algo,\n        round_type=args.round_type,\n        hist_percent=args.hist_percent,\n        is_full_quantize=args.is_full_quantize,\n        bias_correction=args.bias_correction,\n        onnx_format=args.onnx_format,\n        quantizable_op_type=args.quantizable_op_type)\n\n\ndef main():\n    args = parse_args()\n    new_quantizable_op_type = []\n    for item in args.quantizable_op_type:\n        new_quantizable_op_type.append(''.join(item))\n    args.quantizable_op_type = new_quantizable_op_type\n    paddle.enable_static()\n    quantize(args)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/gen_gta_mel.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# generate mels using durations.txt\n# for mb melgan finetune\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_sentences_svs\nfrom paddlespeech.t2s.models.diffsinger import DiffSinger\nfrom paddlespeech.t2s.models.diffsinger import DiffSingerInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args, diffsinger_config):\n    rootdir = Path(args.rootdir).expanduser()\n    assert rootdir.is_dir()\n\n    # construct dataset for evaluation\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    phone_dict = {}\n    for phn, id in phn_id:\n        phone_dict[phn] = int(id)\n\n    if args.speaker_dict:\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id_list = [line.strip().split() for line in f.readlines()]\n            spk_num = len(spk_id_list)\n    else:\n        spk_num = None\n\n    with open(args.diffsinger_stretch, \"r\") as f:\n        spec_min = np.load(args.diffsinger_stretch)[0]\n        spec_max = np.load(args.diffsinger_stretch)[1]\n        spec_min = paddle.to_tensor(spec_min)\n        spec_max = paddle.to_tensor(spec_max)\n    print(\"min and max spec done!\")\n\n    odim = diffsinger_config.n_mels\n    diffsinger_config[\"model\"][\"fastspeech2_params\"][\"spk_num\"] = spk_num\n    model = DiffSinger(\n        spec_min=spec_min,\n        spec_max=spec_max,\n        idim=vocab_size,\n        odim=odim,\n        **diffsinger_config[\"model\"], )\n\n    model.set_state_dict(paddle.load(args.diffsinger_checkpoint)[\"main_params\"])\n    model.eval()\n\n    stat = np.load(args.diffsinger_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    diffsinger_normalizer = ZScore(mu, std)\n\n    diffsinger_inference = DiffSingerInference(diffsinger_normalizer, model)\n    diffsinger_inference.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences, speaker_set = get_sentences_svs(\n        args.dur_file,\n        dataset=args.dataset,\n        sample_rate=diffsinger_config.fs,\n        n_shift=diffsinger_config.n_shift, )\n\n    if args.dataset == \"opencpop\":\n        wavdir = rootdir / \"wavs\"\n        # split data into 3 sections\n        train_file = rootdir / \"train.txt\"\n        train_wav_files = []\n        with open(train_file, \"r\") as f_train:\n            for line in f_train.readlines():\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                train_wav_files.append(wav_path)\n\n        test_file = rootdir / \"test.txt\"\n        dev_wav_files = []\n        test_wav_files = []\n        num_dev = 106\n        count = 0\n        with open(test_file, \"r\") as f_test:\n            for line in f_test.readlines():\n                count += 1\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                if count > num_dev:\n                    test_wav_files.append(wav_path)\n                else:\n                    dev_wav_files.append(wav_path)\n    else:\n        print(\"dataset should in {opencpop} now!\")\n\n    train_wav_files = [\n        os.path.basename(str(str_path)) for str_path in train_wav_files\n    ]\n    dev_wav_files = [\n        os.path.basename(str(str_path)) for str_path in dev_wav_files\n    ]\n    test_wav_files = [\n        os.path.basename(str(str_path)) for str_path in test_wav_files\n    ]\n\n    for i, utt_id in enumerate(tqdm(sentences)):\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        note = sentences[utt_id][2]\n        note_dur = sentences[utt_id][3]\n        is_slur = sentences[utt_id][4]\n        speaker = sentences[utt_id][-1]\n\n        phone_ids = [phone_dict[phn] for phn in phones]\n        phone_ids = paddle.to_tensor(np.array(phone_ids))\n\n        if args.speaker_dict:\n            speaker_id = int(\n                [item[1] for item in spk_id_list if speaker == item[0]][0])\n            speaker_id = paddle.to_tensor(speaker_id)\n        else:\n            speaker_id = None\n\n        durations = paddle.to_tensor(np.array(durations))\n        note = paddle.to_tensor(np.array(note))\n        note_dur = paddle.to_tensor(np.array(note_dur))\n        is_slur = paddle.to_tensor(np.array(is_slur))\n        # 生成的和真实的可能有 1, 2 帧的差距，但是 batch_fn 会修复\n        # split data into 3 sections\n\n        wav_path = utt_id + \".wav\"\n\n        if wav_path in train_wav_files:\n            sub_output_dir = output_dir / (\"train/raw\")\n        elif wav_path in dev_wav_files:\n            sub_output_dir = output_dir / (\"dev/raw\")\n        elif wav_path in test_wav_files:\n            sub_output_dir = output_dir / (\"test/raw\")\n\n        sub_output_dir.mkdir(parents=True, exist_ok=True)\n\n        with paddle.no_grad():\n            mel = diffsinger_inference(\n                text=phone_ids,\n                note=note,\n                note_dur=note_dur,\n                is_slur=is_slur,\n                get_mel_fs2=False)\n        np.save(sub_output_dir / (utt_id + \"_feats.npy\"), mel)\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Generate mel with diffsinger.\")\n    parser.add_argument(\n        \"--dataset\",\n        default=\"opencpop\",\n        type=str,\n        help=\"name of dataset, should in {opencpop} now\")\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n    parser.add_argument(\n        \"--diffsinger-config\", type=str, help=\"diffsinger config file.\")\n    parser.add_argument(\n        \"--diffsinger-checkpoint\",\n        type=str,\n        help=\"diffsinger checkpoint to load.\")\n    parser.add_argument(\n        \"--diffsinger-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training diffsinger.\"\n    )\n    parser.add_argument(\n        \"--diffsinger-stretch\",\n        type=str,\n        help=\"min and max mel used to stretch before training diffusion.\")\n\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.diffsinger_config) as f:\n        diffsinger_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(diffsinger_config)\n\n    evaluate(args, diffsinger_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/get_minmax.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\n\nimport jsonlines\nimport numpy as np\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef get_minmax(spec, min_spec, max_spec):\n    # spec: [T, 80]\n    for i in range(spec.shape[1]):\n        min_value = np.min(spec[:, i])\n        max_value = np.max(spec[:, i])\n        min_spec[i] = min(min_value, min_spec[i])\n        max_spec[i] = max(max_value, max_spec[i])\n\n    return min_spec, max_spec\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--speech-stretchs\",\n        type=str,\n        required=True,\n        help=\"min max spec file. only computer on train data\")\n\n    args = parser.parse_args()\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata, converters={\n            \"speech\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    n_mel = 80\n    min_spec = 100.0 * np.ones(shape=(n_mel), dtype=np.float32)\n    max_spec = -100.0 * np.ones(shape=(n_mel), dtype=np.float32)\n\n    for item in tqdm(dataset):\n        spec = item['speech']\n        min_spec, max_spec = get_minmax(spec, min_spec, max_spec)\n\n    # Using min_spec=-6.0 training effect is better so far\n    min_spec = -6.0 * np.ones(shape=(n_mel), dtype=np.float32)\n    min_max_spec = np.stack([min_spec, max_spec], axis=0)\n    np.save(\n        str(args.speech_stretchs),\n        min_max_spec.astype(np.float32),\n        allow_pickle=False)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/normalize.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--speech-stats\",\n        type=str,\n        required=True,\n        help=\"speech statistics file.\")\n    parser.add_argument(\n        \"--pitch-stats\", type=str, required=True, help=\"pitch statistics file.\")\n    parser.add_argument(\n        \"--energy-stats\",\n        type=str,\n        required=True,\n        help=\"energy statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        \"--norm-feats\",\n        type=str2bool,\n        default=False,\n        help=\"whether to norm features\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        converters={\n            \"speech\": np.load,\n            \"pitch\": np.load,\n            \"energy\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    speech_scaler = StandardScaler()\n    if args.norm_feats:\n        speech_scaler.mean_ = np.load(args.speech_stats)[0]\n        speech_scaler.scale_ = np.load(args.speech_stats)[1]\n    else:\n        speech_scaler.mean_ = np.zeros(\n            np.load(args.speech_stats)[0].shape, dtype=\"float32\")\n        speech_scaler.scale_ = np.ones(\n            np.load(args.speech_stats)[1].shape, dtype=\"float32\")\n    speech_scaler.n_features_in_ = speech_scaler.mean_.shape[0]\n\n    pitch_scaler = StandardScaler()\n    if args.norm_feats:\n        pitch_scaler.mean_ = np.load(args.pitch_stats)[0]\n        pitch_scaler.scale_ = np.load(args.pitch_stats)[1]\n    else:\n        pitch_scaler.mean_ = np.zeros(\n            np.load(args.pitch_stats)[0].shape, dtype=\"float32\")\n        pitch_scaler.scale_ = np.ones(\n            np.load(args.pitch_stats)[1].shape, dtype=\"float32\")\n    pitch_scaler.n_features_in_ = pitch_scaler.mean_.shape[0]\n\n    energy_scaler = StandardScaler()\n    if args.norm_feats:\n        energy_scaler.mean_ = np.load(args.energy_stats)[0]\n        energy_scaler.scale_ = np.load(args.energy_stats)[1]\n    else:\n        energy_scaler.mean_ = np.zeros(\n            np.load(args.energy_stats)[0].shape, dtype=\"float32\")\n        energy_scaler.scale_ = np.ones(\n            np.load(args.energy_stats)[1].shape, dtype=\"float32\")\n    energy_scaler.n_features_in_ = energy_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n        pitch = item['pitch']\n        energy = item['energy']\n        # normalize\n        speech = speech_scaler.transform(speech)\n        speech_dir = dumpdir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        pitch = pitch_scaler.transform(pitch)\n        pitch_dir = dumpdir / \"data_pitch\"\n        pitch_dir.mkdir(parents=True, exist_ok=True)\n        pitch_path = pitch_dir / f\"{utt_id}_pitch.npy\"\n        np.save(pitch_path, pitch.astype(np.float32), allow_pickle=False)\n\n        energy = energy_scaler.transform(energy)\n        energy_dir = dumpdir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / f\"{utt_id}_energy.npy\"\n        np.save(energy_path, energy.astype(np.float32), allow_pickle=False)\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"speech_lengths\": item['speech_lengths'],\n            \"durations\": item['durations'],\n            \"speech\": str(speech_path),\n            \"pitch\": str(pitch_path),\n            \"energy\": str(energy_path),\n            \"note\": item['note'],\n            \"note_dur\": item['note_dur'],\n            \"is_slur\": item['is_slur'],\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/preprocess.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import Energy\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.get_feats import Pitch\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_sentences_svs\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.utils import str2bool\n\nALL_INITIALS = [\n    'zh', 'ch', 'sh', 'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h',\n    'j', 'q', 'x', 'r', 'z', 'c', 's', 'y', 'w'\n]\nALL_FINALS = [\n    'a', 'ai', 'an', 'ang', 'ao', 'e', 'ei', 'en', 'eng', 'er', 'i', 'ia',\n    'ian', 'iang', 'iao', 'ie', 'in', 'ing', 'iong', 'iu', 'ng', 'o', 'ong',\n    'ou', 'u', 'ua', 'uai', 'uan', 'uang', 'ui', 'un', 'uo', 'v', 'van', 've',\n    'vn'\n]\n\n\ndef process_sentence(\n        config: Dict[str, Any],\n        fp: Path,\n        sentences: Dict,\n        output_dir: Path,\n        mel_extractor=None,\n        pitch_extractor=None,\n        energy_extractor=None,\n        cut_sil: bool=True,\n        spk_emb_dir: Path=None, ):\n    utt_id = fp.stem\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        note = sentences[utt_id][2]\n        note_dur = sentences[utt_id][3]\n        is_slur = sentences[utt_id][4]\n        speaker = sentences[utt_id][-1]\n\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n\n        assert sum(\n            durations\n        ) == num_frames, \"the sum of durations doesn't equal to the num of mel frames. \"\n        speech_dir = output_dir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / (utt_id + \"_speech.npy\")\n        np.save(speech_path, logmel)\n        # extract pitch and energy\n        pitch = pitch_extractor.get_pitch(wav)\n        assert pitch.shape[0] == num_frames\n        pitch_dir = output_dir / \"data_pitch\"\n        pitch_dir.mkdir(parents=True, exist_ok=True)\n        pitch_path = pitch_dir / (utt_id + \"_pitch.npy\")\n        np.save(pitch_path, pitch)\n        energy = energy_extractor.get_energy(wav)\n        assert energy.shape[0] == num_frames\n        energy_dir = output_dir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / (utt_id + \"_energy.npy\")\n        np.save(energy_path, energy)\n\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"speech_lengths\": num_frames,\n            \"durations\": durations,\n            \"speech\": str(speech_path),\n            \"pitch\": str(pitch_path),\n            \"energy\": str(energy_path),\n            \"speaker\": speaker,\n            \"note\": note,\n            \"note_dur\": note_dur,\n            \"is_slur\": is_slur,\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(\n        config,\n        fps: List[Path],\n        sentences: Dict,\n        output_dir: Path,\n        mel_extractor=None,\n        pitch_extractor=None,\n        energy_extractor=None,\n        nprocs: int=1,\n        cut_sil: bool=True,\n        spk_emb_dir: Path=None,\n        write_metadata_method: str='w', ):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                pitch_extractor=pitch_extractor,\n                energy_extractor=energy_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir, )\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(\n                        process_sentence,\n                        config,\n                        fp,\n                        sentences,\n                        output_dir,\n                        mel_extractor,\n                        pitch_extractor,\n                        energy_extractor,\n                        cut_sil,\n                        spk_emb_dir, )\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\",\n                        write_metadata_method) as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"opencpop\",\n        type=str,\n        help=\"name of dataset, should in {opencpop} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n\n    parser.add_argument(\n        \"--label-file\", default=None, type=str, help=\"path to label file.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"diffsinger config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n\n    parser.add_argument(\n        \"--write_metadata_method\",\n        default=\"w\",\n        type=str,\n        choices=[\"w\", \"a\"],\n        help=\"How the metadata.jsonl file is written.\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    label_file = Path(args.label_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert label_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_sentences_svs(\n        label_file,\n        dataset=args.dataset,\n        sample_rate=config.fs,\n        n_shift=config.n_shift, )\n\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"opencpop\":\n        wavdir = rootdir / \"wavs\"\n        # split data into 3 sections\n        train_file = rootdir / \"train.txt\"\n        train_wav_files = []\n        with open(train_file, \"r\") as f_train:\n            for line in f_train.readlines():\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                train_wav_files.append(wav_path)\n\n        test_file = rootdir / \"test.txt\"\n        dev_wav_files = []\n        test_wav_files = []\n        num_dev = 106\n        count = 0\n        with open(test_file, \"r\") as f_test:\n            for line in f_test.readlines():\n                count += 1\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                if count > num_dev:\n                    test_wav_files.append(wav_path)\n                else:\n                    dev_wav_files.append(wav_path)\n\n    else:\n        print(\"dataset should in {opencpop} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n    pitch_extractor = Pitch(\n        sr=config.fs,\n        hop_length=config.n_shift,\n        f0min=config.f0min,\n        f0max=config.f0max)\n    energy_extractor = Energy(\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/diffsinger/train.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import AdamW\nfrom paddle.optimizer.lr import StepDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import diffsinger_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import diffsinger_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.diffsinger import DiffSinger\nfrom paddlespeech.t2s.models.diffsinger import DiffSingerEvaluator\nfrom paddlespeech.t2s.models.diffsinger import DiffSingerUpdater\nfrom paddlespeech.t2s.models.diffsinger import DiffusionLoss\nfrom paddlespeech.t2s.models.diffsinger.fastspeech2midi import FastSpeech2MIDILoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n    fields = [\n        \"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"durations\",\n        \"pitch\", \"energy\", \"note\", \"note_dur\", \"is_slur\"\n    ]\n    converters = {\"speech\": np.load, \"pitch\": np.load, \"energy\": np.load}\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker diffsinger!\")\n        collate_fn = diffsinger_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    else:\n        collate_fn = diffsinger_single_spk_batch_fn\n        print(\"single speaker diffsinger!\")\n\n    print(\"spk_num:\", spk_num)\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    with open(args.speech_stretchs, \"r\") as f:\n        spec_min = np.load(args.speech_stretchs)[0]\n        spec_max = np.load(args.speech_stretchs)[1]\n        spec_min = paddle.to_tensor(spec_min)\n        spec_max = paddle.to_tensor(spec_max)\n    print(\"min and max spec done!\")\n\n    odim = config.n_mels\n    config[\"model\"][\"fastspeech2_params\"][\"spk_num\"] = spk_num\n    model = DiffSinger(\n        spec_min=spec_min,\n        spec_max=spec_max,\n        idim=vocab_size,\n        odim=odim,\n        **config[\"model\"], )\n    model_fs2 = model.fs2\n    model_ds = model.diffusion\n    if world_size > 1:\n        model = DataParallel(model)\n        model_fs2 = model._layers.fs2\n        model_ds = model._layers.diffusion\n    print(\"models done!\")\n\n    criterion_fs2 = FastSpeech2MIDILoss(**config[\"fs2_updater\"])\n    criterion_ds = DiffusionLoss(**config[\"ds_updater\"])\n    print(\"criterions done!\")\n\n    optimizer_fs2 = build_optimizers(model_fs2, **config[\"fs2_optimizer\"])\n    lr_schedule_ds = StepDecay(**config[\"ds_scheduler_params\"])\n    gradient_clip_ds = nn.ClipGradByGlobalNorm(config[\"ds_grad_norm\"])\n    optimizer_ds = AdamW(\n        learning_rate=lr_schedule_ds,\n        grad_clip=gradient_clip_ds,\n        parameters=model_ds.parameters(),\n        **config[\"ds_optimizer_params\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = DiffSingerUpdater(\n        model=model,\n        optimizers={\n            \"fs2\": optimizer_fs2,\n            \"ds\": optimizer_ds,\n        },\n        criterions={\n            \"fs2\": criterion_fs2,\n            \"ds\": criterion_ds,\n        },\n        dataloader=train_dataloader,\n        ds_train_start_steps=config.ds_train_start_steps,\n        output_dir=output_dir,\n        only_train_diffusion=config[\"only_train_diffusion\"])\n\n    evaluator = DiffSingerEvaluator(\n        model=model,\n        criterions={\n            \"fs2\": criterion_fs2,\n            \"ds\": criterion_ds,\n        },\n        dataloader=dev_dataloader,\n        output_dir=output_dir, )\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir, )\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train a DiffSinger model.\")\n    parser.add_argument(\"--config\", type=str, help=\"diffsinger config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n    parser.add_argument(\n        \"--speech-stretchs\",\n        type=str,\n        help=\"The min and max values of the mel spectrum.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/dygraph_to_static.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import am_to_static\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.exps.syn_utils import voc_to_static\n\n\ndef am_dygraph_to_static(args):\n    with open(args.am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n    am_inference = get_am_inference(\n        am=args.am,\n        am_config=am_config,\n        am_ckpt=args.am_ckpt,\n        am_stat=args.am_stat,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict,\n        speaker_dict=args.speaker_dict)\n    print(\"acoustic model done!\")\n\n    # dygraph to static\n    am_inference = am_to_static(\n        am_inference=am_inference,\n        am=args.am,\n        inference_dir=args.inference_dir,\n        speaker_dict=args.speaker_dict)\n    print(\"finish to convert dygraph acoustic model to static!\")\n\n\ndef voc_dygraph_to_static(args):\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n    print(\"voc done!\")\n\n    # dygraph to static\n    voc_inference = voc_to_static(\n        voc_inference=voc_inference,\n        voc=args.voc,\n        inference_dir=args.inference_dir)\n    print(\"finish to convert dygraph vocoder model to static!\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    parser.add_argument(\n        '--type',\n        type=str,\n        required=True,\n        choices=[\"am\", \"voc\"],\n        help='Choose the model type of dynamic to static, am or voc')\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'speedyspeech_aishell3',\n            'fastspeech2_csmsc',\n            'fastspeech2_ljspeech',\n            'fastspeech2_aishell3',\n            'fastspeech2_vctk',\n            'tacotron2_csmsc',\n            'tacotron2_ljspeech',\n            'fastspeech2_mix',\n            'fastspeech2_canton',\n            'fastspeech2_male-zh',\n            'fastspeech2_male-en',\n            'fastspeech2_male-mix',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        '--am_config', type=str, default=None, help='Config of acoustic model.')\n    parser.add_argument(\n        '--am_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_ljspeech',\n            'pwgan_aishell3',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'style_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_ljspeech',\n            'hifigan_aishell3',\n            'hifigan_vctk',\n            'wavernn_csmsc',\n            'pwgan_male',\n            'hifigan_male',\n            'pwgan_opencpop',\n            'hifigan_opencpop',\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        \"--inference_dir\",\n        type=str,\n        default=None,\n        help=\"dir to save inference models\")\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.type == \"am\":\n        am_dygraph_to_static(args)\n    elif args.type == \"voc\":\n        voc_dygraph_to_static(args)\n    else:\n        print(\"type should be in ['am', 'voc'] !\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/__init__.py",
    "content": ""
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/align.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport librosa\nimport numpy as np\nimport pypinyin\nfrom praatio import textgrid\n\nfrom paddlespeech.t2s.exps.ernie_sat.utils import get_dict\nfrom paddlespeech.t2s.exps.ernie_sat.utils import get_tmp_name\n\nDICT_EN = 'tools/aligner/cmudict-0.7b'\nDICT_ZH = 'tools/aligner/simple.lexicon'\nMODEL_DIR_EN = 'tools/aligner/vctk_model.zip'\nMODEL_DIR_ZH = 'tools/aligner/aishell3_model.zip'\nMFA_PATH = 'tools/montreal-forced-aligner/bin'\nos.environ['PATH'] = MFA_PATH + '/:' + os.environ['PATH']\n\n\ndef _get_max_idx(dic):\n    return sorted([int(key.split('_')[0]) for key in dic.keys()])[-1]\n\n\ndef _readtg(tg_path: str, lang: str='en', fs: int=24000, n_shift: int=300):\n    alignment = textgrid.openTextgrid(tg_path, includeEmptyIntervals=True)\n    phones = []\n    ends = []\n    words = []\n\n    for interval in alignment.getTier('words').entries:\n        word = interval.label\n        if word:\n            words.append(word)\n    for interval in alignment.getTier('phones').entries:\n        phone = interval.label\n        phones.append(phone)\n        ends.append(interval.end)\n    frame_pos = librosa.time_to_frames(ends, sr=fs, hop_length=n_shift)\n    durations = np.diff(frame_pos, prepend=0)\n    assert len(durations) == len(phones)\n    # merge '' and sp in the end\n    if phones[-1] == '' and len(phones) > 1 and phones[-2] == 'sp':\n        phones = phones[:-1]\n        durations[-2] += durations[-1]\n        durations = durations[:-1]\n\n    # replace '' and 'sil' with 'sp'\n    phones = ['sp' if (phn == '' or phn == 'sil') else phn for phn in phones]\n\n    if lang == 'en':\n        DICT = DICT_EN\n\n    elif lang == 'zh':\n        DICT = DICT_ZH\n\n    word2phns_dict = get_dict(DICT)\n\n    phn2word_dict = []\n    for word in words:\n        if lang == 'en':\n            word = word.upper()\n        phn2word_dict.append([word2phns_dict[word].split(), word])\n\n    non_sp_idx = 0\n    word_idx = 0\n    i = 0\n    word2phns = {}\n    while i < len(phones):\n        phn = phones[i]\n        if phn == 'sp':\n            word2phns[str(word_idx) + '_sp'] = ['sp']\n            i += 1\n        else:\n            phns, word = phn2word_dict[non_sp_idx]\n            word2phns[str(word_idx) + '_' + word] = phns\n            non_sp_idx += 1\n            i += len(phns)\n        word_idx += 1\n    sum_phn = sum(len(word2phns[k]) for k in word2phns)\n    assert sum_phn == len(phones)\n\n    results = ''\n    for (p, d) in zip(phones, durations):\n        results += p + ' ' + str(d) + ' '\n    return results.strip(), word2phns\n\n\ndef alignment(wav_path: str,\n              text: str,\n              fs: int=24000,\n              lang='en',\n              n_shift: int=300):\n    wav_name = os.path.basename(wav_path)\n    utt = wav_name.split('.')[0]\n    # prepare data for MFA\n    tmp_name = get_tmp_name(text=text)\n    tmpbase = './tmp_dir/' + tmp_name\n    tmpbase = Path(tmpbase)\n    tmpbase.mkdir(parents=True, exist_ok=True)\n    print(\"tmp_name in alignment:\", tmp_name)\n\n    shutil.copyfile(wav_path, tmpbase / wav_name)\n    txt_name = utt + '.txt'\n    txt_path = tmpbase / txt_name\n    with open(txt_path, 'w') as wf:\n        wf.write(text + '\\n')\n    # MFA\n    if lang == 'en':\n        DICT = DICT_EN\n        MODEL_DIR = MODEL_DIR_EN\n\n    elif lang == 'zh':\n        DICT = DICT_ZH\n        MODEL_DIR = MODEL_DIR_ZH\n    else:\n        print('please input right lang!!')\n\n    CMD = 'mfa_align' + ' ' + str(\n        tmpbase) + ' ' + DICT + ' ' + MODEL_DIR + ' ' + str(tmpbase)\n    os.system(CMD)\n    tg_path = str(tmpbase) + '/' + tmp_name + '/' + utt + '.TextGrid'\n    phn_dur, word2phns = _readtg(tg_path, lang=lang)\n    phn_dur = phn_dur.split()\n    phns = phn_dur[::2]\n    durs = phn_dur[1::2]\n    durs = [int(d) for d in durs]\n    assert len(phns) == len(durs)\n    return phns, durs, word2phns\n\n\ndef words2phns(text: str, lang='en'):\n    '''\n    Args:\n        text (str): \n            input text.\n            eg: for that reason cover is impossible to be given.\n        lang (str):\n            'en' or 'zh'\n    Returns:\n        List[str]: phones of input text.\n            eg:\n            ['F', 'AO1', 'R', 'DH', 'AE1', 'T', 'R', 'IY1', 'Z', 'AH0', 'N', 'K', 'AH1', 'V', 'ER0',\n            'IH1', 'Z', 'IH2', 'M', 'P', 'AA1', 'S', 'AH0', 'B', 'AH0', 'L', 'T', 'UW1', 'B', 'IY1', \n            'G', 'IH1', 'V', 'AH0', 'N']\n\n        Dict(str, str): key - idx_word\n                        value - phones\n            eg:\n            {'0_FOR': ['F', 'AO1', 'R'], '1_THAT': ['DH', 'AE1', 'T'], \n            '2_REASON': ['R', 'IY1', 'Z', 'AH0', 'N'],'3_COVER': ['K', 'AH1', 'V', 'ER0'], '4_IS': ['IH1', 'Z'], \n            '5_IMPOSSIBLE': ['IH2', 'M', 'P', 'AA1', 'S', 'AH0', 'B', 'AH0', 'L'],\n            '6_TO': ['T', 'UW1'], '7_BE': ['B', 'IY1'], '8_GIVEN': ['G', 'IH1', 'V', 'AH0', 'N']}\n    '''\n    text = text.strip()\n    words = []\n    for pun in [\n            ',', '.', ':', ';', '!', '?', '\"', '(', ')', '--', '---', u'，',\n            u'。', u'：', u'；', u'！', u'？', u'（', u'）'\n    ]:\n        text = text.replace(pun, ' ')\n    for wrd in text.split():\n        if (wrd[-1] == '-'):\n            wrd = wrd[:-1]\n        if (wrd[0] == \"'\"):\n            wrd = wrd[1:]\n        if wrd:\n            words.append(wrd)\n    if lang == 'en':\n        dictfile = DICT_EN\n    elif lang == 'zh':\n        dictfile = DICT_ZH\n    else:\n        print('please input right lang!!')\n\n    word2phns_dict = get_dict(dictfile)\n    ds = word2phns_dict.keys()\n    phns = []\n    wrd2phns = {}\n    for index, wrd in enumerate(words):\n        if lang == 'en':\n            wrd = wrd.upper()\n        if (wrd not in ds):\n            wrd2phns[str(index) + '_' + wrd] = 'spn'\n            phns.extend(['spn'])\n        else:\n            wrd2phns[str(index) + '_' + wrd] = word2phns_dict[wrd].split()\n            phns.extend(word2phns_dict[wrd].split())\n    return phns, wrd2phns\n\n\ndef get_phns_spans(wav_path: str,\n                   old_str: str='',\n                   new_str: str='',\n                   source_lang: str='en',\n                   target_lang: str='en',\n                   fs: int=24000,\n                   n_shift: int=300):\n    is_append = (old_str == new_str[:len(old_str)])\n    old_phns, mfa_start, mfa_end = [], [], []\n    # source\n    lang = source_lang\n    phn, dur, w2p = alignment(\n        wav_path=wav_path, text=old_str, lang=lang, fs=fs, n_shift=n_shift)\n\n    new_d_cumsum = np.pad(np.array(dur).cumsum(0), (1, 0), 'constant').tolist()\n    mfa_start = new_d_cumsum[:-1]\n    mfa_end = new_d_cumsum[1:]\n    old_phns = phn\n\n    # target\n    if is_append and (source_lang != target_lang):\n        cross_lingual_clone = True\n    else:\n        cross_lingual_clone = False\n\n    if cross_lingual_clone:\n        str_origin = new_str[:len(old_str)]\n        str_append = new_str[len(old_str):]\n\n        if target_lang == 'zh':\n            phns_origin, origin_w2p = words2phns(str_origin, lang='en')\n            phns_append, append_w2p_tmp = words2phns(str_append, lang='zh')\n        elif target_lang == 'en':\n            # 原始句子\n            phns_origin, origin_w2p = words2phns(str_origin, lang='zh')\n            # clone 句子 \n            phns_append, append_w2p_tmp = words2phns(str_append, lang='en')\n        else:\n            assert target_lang == 'zh' or target_lang == 'en', \\\n                'cloning is not support for this language, please check it.'\n\n        new_phns = phns_origin + phns_append\n\n        append_w2p = {}\n        length = len(origin_w2p)\n        for key, value in append_w2p_tmp.items():\n            idx, wrd = key.split('_')\n            append_w2p[str(int(idx) + length) + '_' + wrd] = value\n        new_w2p = origin_w2p.copy()\n        new_w2p.update(append_w2p)\n\n    else:\n        if source_lang == target_lang:\n            new_phns, new_w2p = words2phns(new_str, lang=source_lang)\n        else:\n            assert source_lang == target_lang, \\\n                'source language is not same with target language...'\n\n    span_to_repl = [0, len(old_phns) - 1]\n    span_to_add = [0, len(new_phns) - 1]\n    left_idx = 0\n    new_phns_left = []\n    sp_count = 0\n    # find the left different index\n    # 因为可能 align 时候的 words2phns 和直接 words2phns, 前者会有 sp？\n    for key in w2p.keys():\n        idx, wrd = key.split('_')\n        if wrd == 'sp':\n            sp_count += 1\n            new_phns_left.append('sp')\n        else:\n            idx = str(int(idx) - sp_count)\n            if idx + '_' + wrd in new_w2p:\n                # 是 new_str phn 序列的 index\n                left_idx += len(new_w2p[idx + '_' + wrd])\n                # old phn 序列\n                new_phns_left.extend(w2p[key])\n            else:\n                span_to_repl[0] = len(new_phns_left)\n                span_to_add[0] = len(new_phns_left)\n                break\n\n    # reverse w2p and new_w2p\n    right_idx = len(new_phns)\n    new_phns_right = []\n    sp_count = 0\n    w2p_max_idx = _get_max_idx(w2p)\n    new_w2p_max_idx = _get_max_idx(new_w2p)\n    new_phns_mid = []\n    if is_append:\n        new_phns_right = []\n        new_phns_mid = new_phns[left_idx:]\n        span_to_repl[0] = len(new_phns_left)\n        span_to_add[0] = len(new_phns_left)\n        span_to_add[1] = len(new_phns_left) + len(new_phns_mid)\n        span_to_repl[1] = len(old_phns) - len(new_phns_right)\n    # speech edit\n    else:\n        for key in list(w2p.keys())[::-1]:\n            idx, wrd = key.split('_')\n            if wrd == 'sp':\n                sp_count += 1\n                new_phns_right = ['sp'] + new_phns_right\n            else:\n                idx = str(new_w2p_max_idx - (w2p_max_idx - int(idx) - sp_count))\n                if idx + '_' + wrd in new_w2p:\n                    right_idx -= len(new_w2p[idx + '_' + wrd])\n                    new_phns_right = w2p[key] + new_phns_right\n                else:\n                    span_to_repl[1] = len(old_phns) - len(new_phns_right)\n                    new_phns_mid = new_phns[left_idx:right_idx]\n                    span_to_add[1] = len(new_phns_left) + len(new_phns_mid)\n                    if len(new_phns_mid) == 0:\n                        span_to_add[1] = min(span_to_add[1] + 1, len(new_phns))\n                        span_to_add[0] = max(0, span_to_add[0] - 1)\n                        span_to_repl[0] = max(0, span_to_repl[0] - 1)\n                        span_to_repl[1] = min(span_to_repl[1] + 1,\n                                              len(old_phns))\n                    break\n    new_phns = new_phns_left + new_phns_mid + new_phns_right\n    '''\n    For that reason cover should not be given.\n    For that reason cover is impossible to be given.\n    span_to_repl: [17, 23] \"should not\"\n    span_to_add: [17, 30]  \"is impossible to\"\n    '''\n    outs = {}\n    outs['mfa_start'] = mfa_start\n    outs['mfa_end'] = mfa_end\n    outs['old_phns'] = old_phns\n    outs['new_phns'] = new_phns\n    outs['span_to_repl'] = span_to_repl\n    outs['span_to_add'] = span_to_add\n\n    return outs\n\n\nif __name__ == '__main__':\n    text = \"For that reason cover should not be given.\"\n    phn, dur, word2phns = alignment(\"source/p243_313.wav\", text, lang='en')\n    print(phn, dur)\n    print(word2phns)\n    print(\"---------------------------------\")\n    # 这里可以用我们的中文前端得到 pinyin 序列\n    text_zh = \"卡尔普陪外孙玩滑梯。\"\n    text_zh = pypinyin.lazy_pinyin(\n        text_zh,\n        neutral_tone_with_five=True,\n        style=pypinyin.Style.TONE3,\n        tone_sandhi=True)\n    text_zh = \" \".join(text_zh)\n    phn, dur, word2phns = alignment(\"source/000001.wav\", text_zh, lang='zh')\n    print(phn, dur)\n    print(word2phns)\n    print(\"---------------------------------\")\n    phns, wrd2phns = words2phns(text, lang='en')\n    print(\"phns:\", phns)\n    print(\"wrd2phns:\", wrd2phns)\n    print(\"---------------------------------\")\n\n    phns, wrd2phns = words2phns(text_zh, lang='zh')\n    print(\"phns:\", phns)\n    print(\"wrd2phns:\", wrd2phns)\n    print(\"---------------------------------\")\n\n    outs = get_phns_spans(\n        wav_path=\"source/p243_313.wav\",\n        old_str=\"For that reason cover should not be given.\",\n        new_str=\"for that reason cover is impossible to be given.\")\n\n    mfa_start = outs[\"mfa_start\"]\n    mfa_end = outs[\"mfa_end\"]\n    old_phns = outs[\"old_phns\"]\n    new_phns = outs[\"new_phns\"]\n    span_to_repl = outs[\"span_to_repl\"]\n    span_to_add = outs[\"span_to_add\"]\n    print(\"mfa_start:\", mfa_start)\n    print(\"mfa_end:\", mfa_end)\n    print(\"old_phns:\", old_phns)\n    print(\"new_phns:\", new_phns)\n    print(\"span_to_repl:\", span_to_repl)\n    print(\"span_to_add:\", span_to_add)\n    print(\"---------------------------------\")\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--speech-stats\",\n        type=str,\n        required=True,\n        help=\"speech statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata, converters={\n            \"speech\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    speech_scaler = StandardScaler()\n    speech_scaler.mean_ = np.load(args.speech_stats)[0]\n    speech_scaler.scale_ = np.load(args.speech_stats)[1]\n    speech_scaler.n_features_in_ = speech_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n\n        # normalize\n        speech = speech_scaler.transform(speech)\n        speech_dir = dumpdir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"speech_lengths\": item['speech_lengths'],\n            \"durations\": item['durations'],\n            \"speech\": str(speech_path),\n            \"align_start\": item['align_start'],\n            \"align_end\": item['align_end'],\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('speech_lengths'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     cut_sil: bool=True,\n                     spk_emb_dir: Path=None):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n        assert sum(durations) == num_frames\n\n        new_d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        align_start = new_d_cumsum[:-1]\n        align_end = new_d_cumsum[1:]\n        assert len(align_start) == len(align_end) == len(durations)\n\n        mel_dir = output_dir / \"data_speech\"\n        mel_dir.mkdir(parents=True, exist_ok=True)\n        mel_path = mel_dir / (utt_id + \"_speech.npy\")\n        np.save(mel_path, logmel)\n        # align_start_lengths == text_lengths\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"speech_lengths\": num_frames,\n            \"durations\": durations,\n            \"speech\": str(mel_path),\n            \"speaker\": speaker,\n            \"align_start\": align_start.tolist(),\n            \"align_end\": align_end.tolist(),\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      spk_emb_dir: Path=None):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         cut_sil, spk_emb_dir)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"speech_lengths\"))\n    # replace 'w' with 'a' to write from the end of file\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'a') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {baker, aishell3, ljspeech, vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/synthesize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import build_erniesat_collate_fn\nfrom paddlespeech.t2s.exps.syn_utils import denorm\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_test_dataset\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\n\n\ndef evaluate(args):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n\n    # Init body.\n    with open(args.erniesat_config) as f:\n        erniesat_config = CfgNode(yaml.safe_load(f))\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(erniesat_config)\n    print(voc_config)\n\n    # ernie sat model\n    erniesat_inference = get_am_inference(\n        am='erniesat_dataset',\n        am_config=erniesat_config,\n        am_ckpt=args.erniesat_ckpt,\n        am_stat=args.erniesat_stat,\n        phones_dict=args.phones_dict)\n\n    test_dataset = get_test_dataset(\n        test_metadata=test_metadata, am='erniesat_dataset')\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    collate_fn = build_erniesat_collate_fn(\n        mlm_prob=erniesat_config.mlm_prob,\n        mean_phn_span=erniesat_config.mean_phn_span,\n        seg_emb=erniesat_config.model['enc_input_layer'] == 'sega_mlm',\n        text_masking=False)\n\n    gen_raw = True\n    erniesat_mu, erniesat_std = np.load(args.erniesat_stat)\n\n    for datum in test_dataset:\n        # collate function and dataloader\n        utt_id = datum[\"utt_id\"]\n        speech_len = datum[\"speech_lengths\"]\n\n        # mask the middle 1/3 speech\n        left_bdy, right_bdy = speech_len // 3, 2 * speech_len // 3\n        span_bdy = [left_bdy, right_bdy]\n        datum.update({\"span_bdy\": span_bdy})\n\n        batch = collate_fn([datum])\n        with paddle.no_grad():\n            out_mels = erniesat_inference(\n                speech=batch[\"speech\"],\n                text=batch[\"text\"],\n                masked_pos=batch[\"masked_pos\"],\n                speech_mask=batch[\"speech_mask\"],\n                text_mask=batch[\"text_mask\"],\n                speech_seg_pos=batch[\"speech_seg_pos\"],\n                text_seg_pos=batch[\"text_seg_pos\"],\n                span_bdy=span_bdy)\n\n            # vocoder\n            wav_list = []\n            for mel in out_mels:\n                part_wav = voc_inference(mel)\n                wav_list.append(part_wav)\n            wav = paddle.concat(wav_list)\n            wav = wav.numpy()\n            if gen_raw:\n                speech = datum['speech']\n                denorm_mel = denorm(speech, erniesat_mu, erniesat_std)\n                denorm_mel = paddle.to_tensor(denorm_mel)\n                wav_raw = voc_inference(denorm_mel)\n                wav_raw = wav_raw.numpy()\n\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            wav,\n            samplerate=erniesat_config.fs)\n        if gen_raw:\n            sf.write(\n                str(output_dir / (utt_id + \"_raw\" + \".wav\")),\n                wav_raw,\n                samplerate=erniesat_config.fs)\n\n        print(f\"{utt_id} done!\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    # ernie sat\n\n    parser.add_argument(\n        '--erniesat_config',\n        type=str,\n        default=None,\n        help='Config of acoustic model.')\n    parser.add_argument(\n        '--erniesat_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--erniesat_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_aishell3',\n            'pwgan_vctk',\n            'hifigan_aishell3',\n            'hifigan_vctk',\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\"--test_metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n\n    args = parse_args()\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/synthesize_e2e.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import List\n\nimport librosa\nimport numpy as np\nimport paddle\nimport pypinyin\nimport soundfile as sf\nimport yaml\nfrom pypinyin_dict.phrase_pinyin_data import large_pinyin\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import build_erniesat_collate_fn\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.exps.ernie_sat.align import get_phns_spans\nfrom paddlespeech.t2s.exps.ernie_sat.utils import eval_durs\nfrom paddlespeech.t2s.exps.ernie_sat.utils import get_dur_adj_factor\nfrom paddlespeech.t2s.exps.ernie_sat.utils import get_span_bdy\nfrom paddlespeech.t2s.exps.ernie_sat.utils import get_tmp_name\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.exps.syn_utils import norm\nfrom paddlespeech.t2s.utils import str2bool\nlarge_pinyin.load()\n\n\ndef _p2id(phonemes: List[str]) -> np.ndarray:\n    # replace unk phone with sp\n    phonemes = [phn if phn in vocab_phones else \"sp\" for phn in phonemes]\n    phone_ids = [vocab_phones[item] for item in phonemes]\n    return np.array(phone_ids, np.int64)\n\n\ndef prep_feats_with_dur(wav_path: str,\n                        old_str: str='',\n                        new_str: str='',\n                        source_lang: str='en',\n                        target_lang: str='en',\n                        duration_adjust: bool=True,\n                        fs: int=24000,\n                        n_shift: int=300):\n    '''\n    Returns:\n        np.ndarray: new wav, replace the part to be edited in original wav with 0\n        List[str]: new phones\n        List[float]: mfa start of new wav\n        List[float]: mfa end of new wav\n        List[int]: masked mel boundary of original wav\n        List[int]: masked mel boundary of new wav\n    '''\n    wav_org, _ = librosa.load(wav_path, sr=fs)\n    phns_spans_outs = get_phns_spans(\n        wav_path=wav_path,\n        old_str=old_str,\n        new_str=new_str,\n        source_lang=source_lang,\n        target_lang=target_lang,\n        fs=fs,\n        n_shift=n_shift)\n\n    mfa_start = phns_spans_outs['mfa_start']\n    mfa_end = phns_spans_outs['mfa_end']\n    old_phns = phns_spans_outs['old_phns']\n    new_phns = phns_spans_outs['new_phns']\n    span_to_repl = phns_spans_outs['span_to_repl']\n    span_to_add = phns_spans_outs['span_to_add']\n\n    # 中文的 phns 不一定都在 fastspeech2 的字典里, 用 sp 代替\n    if target_lang in {'en', 'zh'}:\n        old_durs = eval_durs(old_phns, target_lang=source_lang)\n    else:\n        assert target_lang in {'en', 'zh'}, \\\n            \"calculate duration_predict is not support for this language...\"\n\n    orig_old_durs = [e - s for e, s in zip(mfa_end, mfa_start)]\n\n    if duration_adjust:\n        d_factor = get_dur_adj_factor(\n            orig_dur=orig_old_durs, pred_dur=old_durs, phns=old_phns)\n        d_factor = d_factor * 1.25\n    else:\n        d_factor = 1\n\n    if target_lang in {'en', 'zh'}:\n        new_durs = eval_durs(new_phns, target_lang=target_lang)\n    else:\n        assert target_lang == \"zh\" or target_lang == \"en\", \\\n            \"calculate duration_predict is not support for this language...\"\n\n    # duration 要是整数\n    new_durs_adjusted = [int(np.ceil(d_factor * i)) for i in new_durs]\n\n    new_span_dur_sum = sum(new_durs_adjusted[span_to_add[0]:span_to_add[1]])\n    old_span_dur_sum = sum(orig_old_durs[span_to_repl[0]:span_to_repl[1]])\n    dur_offset = new_span_dur_sum - old_span_dur_sum\n    new_mfa_start = mfa_start[:span_to_repl[0]]\n    new_mfa_end = mfa_end[:span_to_repl[0]]\n\n    for dur in new_durs_adjusted[span_to_add[0]:span_to_add[1]]:\n        if len(new_mfa_end) == 0:\n            new_mfa_start.append(0)\n            new_mfa_end.append(dur)\n        else:\n            new_mfa_start.append(new_mfa_end[-1])\n            new_mfa_end.append(new_mfa_end[-1] + dur)\n\n    new_mfa_start += [i + dur_offset for i in mfa_start[span_to_repl[1]:]]\n    new_mfa_end += [i + dur_offset for i in mfa_end[span_to_repl[1]:]]\n\n    # 3. get new wav\n    # 在原始句子后拼接\n    if span_to_repl[0] >= len(mfa_start):\n        wav_left_idx = len(wav_org)\n        wav_right_idx = wav_left_idx\n    # 在原始句子中间替换\n    else:\n        wav_left_idx = int(np.floor(mfa_start[span_to_repl[0]] * n_shift))\n        wav_right_idx = int(np.ceil(mfa_end[span_to_repl[1] - 1] * n_shift))\n    blank_wav = np.zeros(\n        (int(np.ceil(new_span_dur_sum * n_shift)), ), dtype=wav_org.dtype)\n    # 原始音频，需要编辑的部分替换成空音频，空音频的时间由 fs2 的 duration_predictor 决定\n    new_wav = np.concatenate(\n        [wav_org[:wav_left_idx], blank_wav, wav_org[wav_right_idx:]])\n\n    # 4. get old and new mel span to be mask\n    old_span_bdy = get_span_bdy(\n        mfa_start=mfa_start, mfa_end=mfa_end, span_to_repl=span_to_repl)\n\n    new_span_bdy = get_span_bdy(\n        mfa_start=new_mfa_start, mfa_end=new_mfa_end, span_to_repl=span_to_add)\n\n    # old_span_bdy, new_span_bdy 是帧级别的范围\n    outs = {}\n    outs['new_wav'] = new_wav\n    outs['new_phns'] = new_phns\n    outs['new_mfa_start'] = new_mfa_start\n    outs['new_mfa_end'] = new_mfa_end\n    outs['old_span_bdy'] = old_span_bdy\n    outs['new_span_bdy'] = new_span_bdy\n    return outs\n\n\ndef prep_feats(wav_path: str,\n               old_str: str='',\n               new_str: str='',\n               source_lang: str='en',\n               target_lang: str='en',\n               duration_adjust: bool=True,\n               fs: int=24000,\n               n_shift: int=300):\n\n    with_dur_outs = prep_feats_with_dur(\n        wav_path=wav_path,\n        old_str=old_str,\n        new_str=new_str,\n        source_lang=source_lang,\n        target_lang=target_lang,\n        duration_adjust=duration_adjust,\n        fs=fs,\n        n_shift=n_shift)\n\n    wav_name = os.path.basename(wav_path)\n    utt_id = wav_name.split('.')[0]\n\n    wav = with_dur_outs['new_wav']\n    phns = with_dur_outs['new_phns']\n    mfa_start = with_dur_outs['new_mfa_start']\n    mfa_end = with_dur_outs['new_mfa_end']\n    old_span_bdy = with_dur_outs['old_span_bdy']\n    new_span_bdy = with_dur_outs['new_span_bdy']\n    span_bdy = np.array(new_span_bdy)\n\n    mel = mel_extractor.get_log_mel_fbank(wav)\n    erniesat_mean, erniesat_std = np.load(erniesat_stat)\n    normed_mel = norm(mel, erniesat_mean, erniesat_std)\n    tmp_name = get_tmp_name(text=old_str)\n    tmpbase = './tmp_dir/' + tmp_name\n    tmpbase = Path(tmpbase)\n    tmpbase.mkdir(parents=True, exist_ok=True)\n\n    mel_path = tmpbase / 'mel.npy'\n    np.save(mel_path, normed_mel)\n    durations = [e - s for e, s in zip(mfa_end, mfa_start)]\n    text = _p2id(phns)\n\n    datum = {\n        \"utt_id\": utt_id,\n        \"spk_id\": 0,\n        \"text\": text,\n        \"text_lengths\": len(text),\n        \"speech_lengths\": len(normed_mel),\n        \"durations\": durations,\n        \"speech\": np.load(mel_path),\n        \"align_start\": mfa_start,\n        \"align_end\": mfa_end,\n        \"span_bdy\": span_bdy\n    }\n\n    batch = collate_fn([datum])\n    outs = dict()\n    outs['batch'] = batch\n    outs['old_span_bdy'] = old_span_bdy\n    outs['new_span_bdy'] = new_span_bdy\n    return outs\n\n\ndef get_mlm_output(wav_path: str,\n                   old_str: str='',\n                   new_str: str='',\n                   source_lang: str='en',\n                   target_lang: str='en',\n                   duration_adjust: bool=True,\n                   fs: int=24000,\n                   n_shift: int=300):\n\n    prep_feats_outs = prep_feats(\n        wav_path=wav_path,\n        old_str=old_str,\n        new_str=new_str,\n        source_lang=source_lang,\n        target_lang=target_lang,\n        duration_adjust=duration_adjust,\n        fs=fs,\n        n_shift=n_shift)\n\n    batch = prep_feats_outs['batch']\n    new_span_bdy = prep_feats_outs['new_span_bdy']\n    old_span_bdy = prep_feats_outs['old_span_bdy']\n\n    out_mels = erniesat_inference(\n        speech=batch['speech'],\n        text=batch['text'],\n        masked_pos=batch['masked_pos'],\n        speech_mask=batch['speech_mask'],\n        text_mask=batch['text_mask'],\n        speech_seg_pos=batch['speech_seg_pos'],\n        text_seg_pos=batch['text_seg_pos'],\n        span_bdy=new_span_bdy)\n\n    # 拼接音频\n    output_feat = paddle.concat(x=out_mels, axis=0)\n    wav_org, _ = librosa.load(wav_path, sr=fs)\n    outs = dict()\n    outs['wav_org'] = wav_org\n    outs['output_feat'] = output_feat\n    outs['old_span_bdy'] = old_span_bdy\n    outs['new_span_bdy'] = new_span_bdy\n\n    return outs\n\n\ndef get_wav(wav_path: str,\n            source_lang: str='en',\n            target_lang: str='en',\n            old_str: str='',\n            new_str: str='',\n            duration_adjust: bool=True,\n            fs: int=24000,\n            n_shift: int=300,\n            task_name: str='synthesize'):\n\n    outs = get_mlm_output(\n        wav_path=wav_path,\n        old_str=old_str,\n        new_str=new_str,\n        source_lang=source_lang,\n        target_lang=target_lang,\n        duration_adjust=duration_adjust,\n        fs=fs,\n        n_shift=n_shift)\n\n    wav_org = outs['wav_org']\n    output_feat = outs['output_feat']\n    old_span_bdy = outs['old_span_bdy']\n    new_span_bdy = outs['new_span_bdy']\n\n    masked_feat = output_feat[new_span_bdy[0]:new_span_bdy[1]]\n\n    with paddle.no_grad():\n        alt_wav = voc_inference(masked_feat)\n    alt_wav = np.squeeze(alt_wav)\n\n    old_time_bdy = [n_shift * x for x in old_span_bdy]\n    if task_name == 'edit':\n        wav_replaced = np.concatenate(\n            [wav_org[:old_time_bdy[0]], alt_wav, wav_org[old_time_bdy[1]:]])\n    else:\n        wav_replaced = alt_wav\n    wav_dict = {\"origin\": wav_org, \"output\": wav_replaced}\n    return wav_dict\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    # ernie sat\n\n    parser.add_argument(\n        '--erniesat_config',\n        type=str,\n        default=None,\n        help='Config of acoustic model.')\n    parser.add_argument(\n        '--erniesat_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--erniesat_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_aishell3',\n            'pwgan_vctk',\n            'hifigan_aishell3',\n            'hifigan_vctk',\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    # ernie sat related\n    parser.add_argument(\n        \"--task_name\",\n        type=str,\n        choices=['edit', 'synthesize'],\n        help=\"task name.\")\n    parser.add_argument(\"--wav_path\", type=str, help=\"path of old wav\")\n    parser.add_argument(\"--old_str\", type=str, help=\"old string\")\n    parser.add_argument(\"--new_str\", type=str, help=\"new string\")\n    parser.add_argument(\n        \"--source_lang\", type=str, default=\"en\", help=\"source language\")\n    parser.add_argument(\n        \"--target_lang\", type=str, default=\"en\", help=\"target language\")\n    parser.add_argument(\n        \"--duration_adjust\",\n        type=str2bool,\n        default=True,\n        help=\"whether to adjust duration.\")\n    parser.add_argument(\"--output_name\", type=str, default=\"output.wav\")\n\n    args = parser.parse_args()\n    return args\n\n\nif __name__ == '__main__':\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    # evaluate(args)\n    with open(args.erniesat_config) as f:\n        erniesat_config = CfgNode(yaml.safe_load(f))\n    old_str = args.old_str\n    new_str = args.new_str\n\n    # convert Chinese characters to pinyin\n    if args.source_lang == 'zh':\n        old_str = pypinyin.lazy_pinyin(\n            old_str,\n            neutral_tone_with_five=True,\n            style=pypinyin.Style.TONE3,\n            tone_sandhi=True)\n        old_str = ' '.join(old_str)\n    if args.target_lang == 'zh':\n        new_str = pypinyin.lazy_pinyin(\n            new_str,\n            neutral_tone_with_five=True,\n            style=pypinyin.Style.TONE3,\n            tone_sandhi=True)\n        new_str = ' '.join(new_str)\n\n    if args.task_name == 'edit':\n        new_str = new_str\n    elif args.task_name == 'synthesize':\n        new_str = old_str + ' ' + new_str\n    else:\n        new_str = old_str + ' ' + new_str\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=erniesat_config.fs,\n        n_fft=erniesat_config.n_fft,\n        hop_length=erniesat_config.n_shift,\n        win_length=erniesat_config.win_length,\n        window=erniesat_config.window,\n        n_mels=erniesat_config.n_mels,\n        fmin=erniesat_config.fmin,\n        fmax=erniesat_config.fmax)\n\n    collate_fn = build_erniesat_collate_fn(\n        mlm_prob=erniesat_config.mlm_prob,\n        mean_phn_span=erniesat_config.mean_phn_span,\n        seg_emb=erniesat_config.model['enc_input_layer'] == 'sega_mlm',\n        text_masking=False)\n\n    vocab_phones = {}\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    # ernie sat model\n    erniesat_inference = get_am_inference(\n        am='erniesat_dataset',\n        am_config=erniesat_config,\n        am_ckpt=args.erniesat_ckpt,\n        am_stat=args.erniesat_stat,\n        phones_dict=args.phones_dict)\n\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    erniesat_stat = args.erniesat_stat\n\n    wav_dict = get_wav(\n        wav_path=args.wav_path,\n        source_lang=args.source_lang,\n        target_lang=args.target_lang,\n        old_str=old_str,\n        new_str=new_str,\n        duration_adjust=args.duration_adjust,\n        fs=erniesat_config.fs,\n        n_shift=erniesat_config.n_shift,\n        task_name=args.task_name)\n\n    sf.write(\n        args.output_name, wav_dict['output'], samplerate=erniesat_config.fs)\n    print(\n        f\"\\033[1;32;m Generated audio saved into {args.output_name} ! \\033[0m\")\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.optimizer import Adam\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import build_erniesat_collate_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.sampler import ErnieSATSampler\nfrom paddlespeech.t2s.models.ernie_sat import ErnieSAT\nfrom paddlespeech.t2s.models.ernie_sat import ErnieSATEvaluator\nfrom paddlespeech.t2s.models.ernie_sat import ErnieSATUpdater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n    fields = [\n        \"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"align_start\",\n        \"align_end\"\n    ]\n    converters = {\"speech\": np.load}\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    collate_fn = build_erniesat_collate_fn(\n        mlm_prob=config.mlm_prob,\n        mean_phn_span=config.mean_phn_span,\n        seg_emb=config.model['enc_input_layer'] == 'sega_mlm',\n        text_masking=config[\"model\"][\"text_masking\"])\n\n    train_sampler = ErnieSATSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    model = ErnieSAT(idim=vocab_size, odim=odim, **config[\"model\"])\n\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    scheduler = paddle.optimizer.lr.NoamDecay(\n        d_model=config[\"scheduler_params\"][\"d_model\"],\n        warmup_steps=config[\"scheduler_params\"][\"warmup_steps\"])\n    grad_clip = nn.ClipGradByGlobalNorm(config[\"grad_clip\"])\n    optimizer = Adam(\n        learning_rate=scheduler,\n        grad_clip=grad_clip,\n        parameters=model.parameters())\n\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = ErnieSATUpdater(\n        model=model,\n        optimizer=optimizer,\n        scheduler=scheduler,\n        dataloader=train_dataloader,\n        text_masking=config[\"model\"][\"text_masking\"],\n        odim=odim,\n        vocab_size=vocab_size,\n        output_dir=output_dir)\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = ErnieSATEvaluator(\n        model=model,\n        dataloader=dev_dataloader,\n        text_masking=config[\"model\"][\"text_masking\"],\n        odim=odim,\n        vocab_size=vocab_size,\n        output_dir=output_dir, )\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train an ErnieSAT model.\")\n    parser.add_argument(\"--config\", type=str, help=\"ErnieSAT config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ernie_sat/utils.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport hashlib\nimport os\nfrom pathlib import Path\nfrom typing import Dict\nfrom typing import List\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\n\n\ndef _get_user():\n    return os.path.expanduser('~').split('/')[-1]\n\n\ndef str2md5(string):\n    md5_val = hashlib.md5(string.encode('utf8')).hexdigest()\n    return md5_val\n\n\ndef get_tmp_name(text: str):\n    return _get_user() + '_' + str(os.getpid()) + '_' + str2md5(text)\n\n\ndef get_dict(dictfile: str):\n    word2phns_dict = {}\n    with open(dictfile, 'r') as fid:\n        for line in fid:\n            line_lst = line.split()\n            word, phn_lst = line_lst[0], line.split()[1:]\n            if word not in word2phns_dict.keys():\n                word2phns_dict[word] = ' '.join(phn_lst)\n    return word2phns_dict\n\n\n# 获取需要被 mask 的 mel 帧的范围\ndef get_span_bdy(mfa_start: List[float],\n                 mfa_end: List[float],\n                 span_to_repl: List[List[int]]):\n    if span_to_repl[0] >= len(mfa_start):\n        span_bdy = [mfa_end[-1], mfa_end[-1]]\n    else:\n        span_bdy = [mfa_start[span_to_repl[0]], mfa_end[span_to_repl[1] - 1]]\n    return span_bdy\n\n\n# mfa 获得的 duration 和 fs2 的 duration_predictor 获取的 duration 可能不同\n# 此处获得一个缩放比例, 用于预测值和真实值之间的缩放\ndef get_dur_adj_factor(orig_dur: List[int],\n                       pred_dur: List[int],\n                       phns: List[str]):\n    length = 0\n    factor_list = []\n    for orig, pred, phn in zip(orig_dur, pred_dur, phns):\n        if pred == 0 or phn == 'sp':\n            continue\n        else:\n            factor_list.append(orig / pred)\n    factor_list = np.array(factor_list)\n    factor_list.sort()\n    if len(factor_list) < 5:\n        return 1\n    length = 2\n    avg = np.average(factor_list[length:-length])\n    return avg\n\n\ndef read_2col_text(path: Union[Path, str]) -> Dict[str, str]:\n    \"\"\"Read a text file having 2 column as dict object.\n\n    Examples:\n        wav.scp:\n            key1 /some/path/a.wav\n            key2 /some/path/b.wav\n\n        >>> read_2col_text('wav.scp')\n        {'key1': '/some/path/a.wav', 'key2': '/some/path/b.wav'}\n\n    \"\"\"\n\n    data = {}\n    with Path(path).open(\"r\", encoding=\"utf-8\") as f:\n        for linenum, line in enumerate(f, 1):\n            sps = line.rstrip().split(maxsplit=1)\n            if len(sps) == 1:\n                k, v = sps[0], \"\"\n            else:\n                k, v = sps\n            if k in data:\n                raise RuntimeError(f\"{k} is duplicated ({path}:{linenum})\")\n            data[k] = v\n    return data\n\n\ndef load_num_sequence_text(path: Union[Path, str], loader_type: str=\"csv_int\"\n                           ) -> Dict[str, List[Union[float, int]]]:\n    \"\"\"Read a text file indicating sequences of number\n\n    Examples:\n        key1 1 2 3\n        key2 34 5 6\n\n        >>> d = load_num_sequence_text('text')\n        >>> np.testing.assert_array_equal(d[\"key1\"], np.array([1, 2, 3]))\n    \"\"\"\n    if loader_type == \"text_int\":\n        delimiter = \" \"\n        dtype = int\n    elif loader_type == \"text_float\":\n        delimiter = \" \"\n        dtype = float\n    elif loader_type == \"csv_int\":\n        delimiter = \",\"\n        dtype = int\n    elif loader_type == \"csv_float\":\n        delimiter = \",\"\n        dtype = float\n    else:\n        raise ValueError(f\"Not supported loader_type={loader_type}\")\n\n    # path looks like:\n    #   utta 1,0\n    #   uttb 3,4,5\n    # -> return {'utta': np.ndarray([1, 0]),\n    #            'uttb': np.ndarray([3, 4, 5])}\n    d = read_2column_text(path)\n    # Using for-loop instead of dict-comprehension for debuggability\n    retval = {}\n    for k, v in d.items():\n        try:\n            retval[k] = [dtype(i) for i in v.split(delimiter)]\n        except TypeError:\n            print(f'Error happened with path=\"{path}\", id=\"{k}\", value=\"{v}\"')\n            raise\n    return retval\n\n\ndef is_chinese(ch):\n    if u'\\u4e00' <= ch <= u'\\u9fff':\n        return True\n    else:\n        return False\n\n\ndef get_voc_out(mel):\n    # vocoder\n    args = parse_args()\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    with paddle.no_grad():\n        wav = voc_inference(mel)\n    return np.squeeze(wav)\n\n\ndef eval_durs(phns, target_lang: str='zh', fs: int=24000, n_shift: int=300):\n\n    if target_lang == 'en':\n        am = \"fastspeech2_ljspeech\"\n        am_config = \"download/fastspeech2_nosil_ljspeech_ckpt_0.5/default.yaml\"\n        am_ckpt = \"download/fastspeech2_nosil_ljspeech_ckpt_0.5/snapshot_iter_100000.pdz\"\n        am_stat = \"download/fastspeech2_nosil_ljspeech_ckpt_0.5/speech_stats.npy\"\n        phones_dict = \"download/fastspeech2_nosil_ljspeech_ckpt_0.5/phone_id_map.txt\"\n\n    elif target_lang == 'zh':\n        am = \"fastspeech2_csmsc\"\n        am_config = \"download/fastspeech2_conformer_baker_ckpt_0.5/conformer.yaml\"\n        am_ckpt = \"download/fastspeech2_conformer_baker_ckpt_0.5/snapshot_iter_76000.pdz\"\n        am_stat = \"download/fastspeech2_conformer_baker_ckpt_0.5/speech_stats.npy\"\n        phones_dict = \"download/fastspeech2_conformer_baker_ckpt_0.5/phone_id_map.txt\"\n\n    # Init body.\n    with open(am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n\n    am_inference, am = get_am_inference(\n        am=am,\n        am_config=am_config,\n        am_ckpt=am_ckpt,\n        am_stat=am_stat,\n        phones_dict=phones_dict,\n        return_am=True)\n\n    vocab_phones = {}\n    with open(phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for tone, id in phn_id:\n        vocab_phones[tone] = int(id)\n    vocab_size = len(vocab_phones)\n    phonemes = [phn if phn in vocab_phones else \"sp\" for phn in phns]\n\n    phone_ids = [vocab_phones[item] for item in phonemes]\n    phone_ids = paddle.to_tensor(np.array(phone_ids, np.int64))\n    _, d_outs, _, _ = am.inference(phone_ids)\n    d_outs = d_outs.tolist()\n    return d_outs\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/gen_gta_mel.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# generate mels using durations.txt\n# for mb melgan finetune\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import StyleFastSpeech2Inference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args, fastspeech2_config):\n    rootdir = Path(args.rootdir).expanduser()\n    assert rootdir.is_dir()\n\n    # construct dataset for evaluation\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    phone_dict = {}\n    for phn, id in phn_id:\n        phone_dict[phn] = int(id)\n\n    if args.speaker_dict:\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id_list = [line.strip().split() for line in f.readlines()]\n            spk_num = len(spk_id_list)\n    else:\n        spk_num = None\n\n    odim = fastspeech2_config.n_mels\n    model = FastSpeech2(\n        idim=vocab_size,\n        odim=odim,\n        **fastspeech2_config[\"model\"],\n        spk_num=spk_num)\n\n    model.set_state_dict(\n        paddle.load(args.fastspeech2_checkpoint)[\"main_params\"])\n    model.eval()\n\n    stat = np.load(args.fastspeech2_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    fastspeech2_normalizer = ZScore(mu, std)\n\n    fastspeech2_inference = StyleFastSpeech2Inference(fastspeech2_normalizer,\n                                                      model)\n    fastspeech2_inference.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences, speaker_set = get_phn_dur(args.dur_file)\n    merge_silence(sentences)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    train_wav_files = [\n        os.path.basename(str(str_path)) for str_path in train_wav_files\n    ]\n    dev_wav_files = [\n        os.path.basename(str(str_path)) for str_path in dev_wav_files\n    ]\n    test_wav_files = [\n        os.path.basename(str(str_path)) for str_path in test_wav_files\n    ]\n\n    for i, utt_id in enumerate(tqdm(sentences)):\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        # 裁剪掉开头和结尾的 sil\n        if args.cut_sil:\n            if phones[0] == \"sil\" and len(durations) > 1:\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                durations = durations[:-1]\n                phones = phones[:-1]\n            # sentences[utt_id][0] = phones\n            # sentences[utt_id][1] = durations\n\n        phone_ids = [phone_dict[phn] for phn in phones]\n        phone_ids = paddle.to_tensor(np.array(phone_ids))\n\n        if args.speaker_dict:\n            speaker_id = int(\n                [item[1] for item in spk_id_list if speaker == item[0]][0])\n            speaker_id = paddle.to_tensor(speaker_id)\n        else:\n            speaker_id = None\n\n        durations = paddle.to_tensor(np.array(durations))\n        # 生成的和真实的可能有 1, 2 帧的差距，但是 batch_fn 会修复\n        # split data into 3 sections\n\n        wav_path = utt_id + \".wav\"\n\n        if wav_path in train_wav_files:\n            sub_output_dir = output_dir / (\"train/raw\")\n        elif wav_path in dev_wav_files:\n            sub_output_dir = output_dir / (\"dev/raw\")\n        elif wav_path in test_wav_files:\n            sub_output_dir = output_dir / (\"test/raw\")\n\n        sub_output_dir.mkdir(parents=True, exist_ok=True)\n\n        with paddle.no_grad():\n            mel = fastspeech2_inference(\n                phone_ids, durations=durations, spk_id=speaker_id)\n        np.save(sub_output_dir / (utt_id + \"_feats.npy\"), mel)\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with fastspeech2 & parallel wavegan.\")\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, ljspeech, vctk} now\")\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n    parser.add_argument(\n        \"--fastspeech2-config\", type=str, help=\"fastspeech2 config file.\")\n    parser.add_argument(\n        \"--fastspeech2-checkpoint\",\n        type=str,\n        help=\"fastspeech2 checkpoint to load.\")\n    parser.add_argument(\n        \"--fastspeech2-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training fastspeech2.\"\n    )\n\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.fastspeech2_config) as f:\n        fastspeech2_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(fastspeech2_config)\n\n    evaluate(args, fastspeech2_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--speech-stats\",\n        type=str,\n        required=True,\n        help=\"speech statistics file.\")\n    parser.add_argument(\n        \"--pitch-stats\", type=str, required=True, help=\"pitch statistics file.\")\n    parser.add_argument(\n        \"--energy-stats\",\n        type=str,\n        required=True,\n        help=\"energy statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        converters={\n            \"speech\": np.load,\n            \"pitch\": np.load,\n            \"energy\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    speech_scaler = StandardScaler()\n    speech_scaler.mean_ = np.load(args.speech_stats)[0]\n    speech_scaler.scale_ = np.load(args.speech_stats)[1]\n    speech_scaler.n_features_in_ = speech_scaler.mean_.shape[0]\n\n    pitch_scaler = StandardScaler()\n    pitch_scaler.mean_ = np.load(args.pitch_stats)[0]\n    pitch_scaler.scale_ = np.load(args.pitch_stats)[1]\n    pitch_scaler.n_features_in_ = pitch_scaler.mean_.shape[0]\n\n    energy_scaler = StandardScaler()\n    energy_scaler.mean_ = np.load(args.energy_stats)[0]\n    energy_scaler.scale_ = np.load(args.energy_stats)[1]\n    energy_scaler.n_features_in_ = energy_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n        pitch = item['pitch']\n        energy = item['energy']\n        # normalize\n        speech = speech_scaler.transform(speech)\n        speech_dir = dumpdir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        pitch = pitch_scaler.transform(pitch)\n        pitch_dir = dumpdir / \"data_pitch\"\n        pitch_dir.mkdir(parents=True, exist_ok=True)\n        pitch_path = pitch_dir / f\"{utt_id}_pitch.npy\"\n        np.save(pitch_path, pitch.astype(np.float32), allow_pickle=False)\n\n        energy = energy_scaler.transform(energy)\n        energy_dir = dumpdir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / f\"{utt_id}_energy.npy\"\n        np.save(energy_path, energy.astype(np.float32), allow_pickle=False)\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"speech_lengths\": item['speech_lengths'],\n            \"durations\": item['durations'],\n            \"speech\": str(speech_path),\n            \"pitch\": str(pitch_path),\n            \"energy\": str(energy_path)\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import Energy\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.get_feats import Pitch\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     pitch_extractor=None,\n                     energy_extractor=None,\n                     cut_sil: bool=True,\n                     spk_emb_dir: Path=None):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(\n            str(fp), sr=config.fs,\n            mono=False) if \"canton\" in str(fp) else librosa.load(\n                str(fp), sr=config.fs)\n        if len(wav.shape) == 2 and \"canton\" in str(fp):\n            # Remind that Cantonese datasets should be placed in ~/datasets/canton_all. Otherwise, it may cause problem.\n            wav = wav[0]\n            wav = np.ascontiguousarray(wav)\n        elif len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n        assert sum(durations) == num_frames\n        mel_dir = output_dir / \"data_speech\"\n        mel_dir.mkdir(parents=True, exist_ok=True)\n        mel_path = mel_dir / (utt_id + \"_speech.npy\")\n        np.save(mel_path, logmel)\n        # extract pitch and energy\n        f0 = pitch_extractor.get_pitch(wav, duration=np.array(durations))\n        if (f0 == 0).all():\n            return None\n        assert f0.shape[0] == len(durations)\n        f0_dir = output_dir / \"data_pitch\"\n        f0_dir.mkdir(parents=True, exist_ok=True)\n        f0_path = f0_dir / (utt_id + \"_pitch.npy\")\n        np.save(f0_path, f0)\n        energy = energy_extractor.get_energy(wav, duration=np.array(durations))\n        assert energy.shape[0] == len(durations)\n        energy_dir = output_dir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / (utt_id + \"_energy.npy\")\n        np.save(energy_path, energy)\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"speech_lengths\": num_frames,\n            \"durations\": durations,\n            \"speech\": str(mel_path),\n            \"pitch\": str(f0_path),\n            \"energy\": str(energy_path),\n            \"speaker\": speaker\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      pitch_extractor=None,\n                      energy_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      spk_emb_dir: Path=None,\n                      write_metadata_method: str='w'):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                pitch_extractor=pitch_extractor,\n                energy_extractor=energy_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         pitch_extractor, energy_extractor,\n                                         cut_sil, spk_emb_dir)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\",\n                        write_metadata_method) as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n\n    parser.add_argument(\n        \"--write_metadata_method\",\n        default=\"w\",\n        type=str,\n        choices=[\"w\", \"a\"],\n        help=\"How the metadata.jsonl file is written.\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"canton\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"WAV\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {baker, aishell3, ljspeech, vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n    pitch_extractor = Pitch(\n        sr=config.fs,\n        hop_length=config.n_shift,\n        f0min=config.f0min,\n        f0max=config.f0max)\n    energy_extractor = Energy(\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import fastspeech2_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import fastspeech2_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Evaluator\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Updater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if args.ngpu > 0 and paddle.is_compiled_with_cuda():\n        paddle.set_device(\"gpu\")\n    elif args.nxpu > 0 and paddle.is_compiled_with_xpu():\n        paddle.set_device(\"xpu\")\n    elif args.ngpu == 0 and args.nxpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        raise ValueError(\n            \"Please make sure that the paddle you installed matches the device type you set, \"\n            \"and that ngpu and nxpu cannot be negative at the same time.\")\n\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n    fields = [\n        \"text\", \"text_lengths\", \"speech\", \"speech_lengths\", \"durations\",\n        \"pitch\", \"energy\"\n    ]\n    converters = {\"speech\": np.load, \"pitch\": np.load, \"energy\": np.load}\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker fastspeech2!\")\n        collate_fn = fastspeech2_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Training voice cloning!\")\n        collate_fn = fastspeech2_multi_spk_batch_fn\n        fields += [\"spk_emb\"]\n        converters[\"spk_emb\"] = np.load\n    else:\n        print(\"single speaker fastspeech2!\")\n        collate_fn = fastspeech2_single_spk_batch_fn\n    print(\"spk_num:\", spk_num)\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    model = FastSpeech2(\n        idim=vocab_size, odim=odim, spk_num=spk_num, **config[\"model\"])\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    optimizer = build_optimizers(model, **config[\"optimizer\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    if \"enable_speaker_classifier\" in config.model:\n        enable_spk_cls = config.model.enable_speaker_classifier\n    else:\n        enable_spk_cls = False\n\n    updater = FastSpeech2Updater(\n        model=model,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir,\n        enable_spk_cls=enable_spk_cls,\n        **config[\"updater\"], )\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = FastSpeech2Evaluator(\n        model,\n        dev_dataloader,\n        output_dir=output_dir,\n        enable_spk_cls=enable_spk_cls,\n        **config[\"updater\"], )\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train a FastSpeech2 model.\")\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu or xpu.\")\n    parser.add_argument(\n        \"--nxpu\",\n        type=int,\n        default=0,\n        help=\"if ngpu=0 and nxpu > 0, use xpu. if ngpu=0 and nxpu=0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/fastspeech2/vc2_infer.py",
    "content": "import argparse\nfrom concurrent.futures import ThreadPoolExecutor\nfrom pathlib import Path\n\nimport numpy as np\nimport tqdm\n\nfrom paddlespeech.cli.vector import VectorExecutor\n\n\ndef _process_utterance(ifpath: Path,\n                       input_dir: Path,\n                       output_dir: Path,\n                       vec_executor):\n    rel_path = ifpath.relative_to(input_dir)\n    ofpath = (output_dir / rel_path).with_suffix(\".npy\")\n    ofpath.parent.mkdir(parents=True, exist_ok=True)\n    embed = vec_executor(audio_file=ifpath, force_yes=True)\n    np.save(ofpath, embed)\n    return ofpath\n\n\ndef main(args):\n    # input output preparation\n    input_dir = Path(args.input).expanduser()\n    ifpaths = list(input_dir.rglob(args.pattern))\n    print(f\"{len(ifpaths)} utterances in total\")\n    output_dir = Path(args.output).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    vec_executor = VectorExecutor()\n    nprocs = args.num_cpu\n\n    # warm up\n    vec_executor(audio_file=ifpaths[0], force_yes=True)\n\n    if nprocs == 1:\n        results = []\n        for ifpath in tqdm.tqdm(ifpaths, total=len(ifpaths)):\n            _process_utterance(\n                ifpath=ifpath,\n                input_dir=input_dir,\n                output_dir=output_dir,\n                vec_executor=vec_executor)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            with tqdm.tqdm(total=len(ifpaths)) as progress:\n                for ifpath in ifpaths:\n                    future = pool.submit(_process_utterance, ifpath, input_dir,\n                                         output_dir, vec_executor)\n                    future.add_done_callback(lambda p: progress.update())\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"compute utterance embed.\")\n    parser.add_argument(\n        \"--input\", type=str, help=\"path of the audio_file folder.\")\n    parser.add_argument(\n        \"--pattern\",\n        type=str,\n        default=\"*.wav\",\n        help=\"pattern to filter audio files.\")\n    parser.add_argument(\n        \"--output\",\n        metavar=\"OUTPUT_DIR\",\n        help=\"path to save spk embedding results.\")\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n    args = parser.parse_args()\n\n    main(args)\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/README.md",
    "content": "different GAN Vocoders have the same preprocess.py and normalize.py\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/hifigan/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/hifigan/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import Adam\nfrom paddle.optimizer.lr import MultiStepDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import Clip\nfrom paddlespeech.t2s.models.hifigan import HiFiGANEvaluator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANGenerator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiScaleMultiPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANUpdater\nfrom paddlespeech.t2s.modules.losses import DiscriminatorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import FeatureMatchLoss\nfrom paddlespeech.t2s.modules.losses import GeneratorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import MelSpectrogramLoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    dev_sampler = DistributedBatchSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    if \"aux_context_window\" in config.generator_params:\n        aux_context_window = config.generator_params.aux_context_window\n    else:\n        aux_context_window = 0\n    train_batch_fn = Clip(\n        batch_max_steps=config.batch_max_steps,\n        hop_size=config.n_shift,\n        aux_context_window=aux_context_window)\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    generator = HiFiGANGenerator(**config[\"generator_params\"])\n    discriminator = HiFiGANMultiScaleMultiPeriodDiscriminator(\n        **config[\"discriminator_params\"])\n    if world_size > 1:\n        generator = DataParallel(generator)\n        discriminator = DataParallel(discriminator)\n    print(\"models done!\")\n\n    criterion_feat_match = FeatureMatchLoss(**config[\"feat_match_loss_params\"])\n    criterion_mel = MelSpectrogramLoss(\n        fs=config.fs,\n        fft_size=config.n_fft,\n        hop_size=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        num_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax, )\n    criterion_gen_adv = GeneratorAdversarialLoss(\n        **config[\"generator_adv_loss_params\"])\n    criterion_dis_adv = DiscriminatorAdversarialLoss(\n        **config[\"discriminator_adv_loss_params\"])\n    print(\"criterions done!\")\n\n    lr_schedule_g = MultiStepDecay(**config[\"generator_scheduler_params\"])\n    # Compared to multi_band_melgan.v1 config, Adam optimizer without gradient norm is used\n    generator_grad_norm = config[\"generator_grad_norm\"]\n    gradient_clip_g = nn.ClipGradByGlobalNorm(\n        generator_grad_norm) if generator_grad_norm > 0 else None\n    print(\"gradient_clip_g:\", gradient_clip_g)\n\n    optimizer_g = Adam(\n        learning_rate=lr_schedule_g,\n        grad_clip=gradient_clip_g,\n        parameters=generator.parameters(),\n        **config[\"generator_optimizer_params\"])\n    lr_schedule_d = MultiStepDecay(**config[\"discriminator_scheduler_params\"])\n    discriminator_grad_norm = config[\"discriminator_grad_norm\"]\n    gradient_clip_d = nn.ClipGradByGlobalNorm(\n        discriminator_grad_norm) if discriminator_grad_norm > 0 else None\n    print(\"gradient_clip_d:\", gradient_clip_d)\n    optimizer_d = Adam(\n        learning_rate=lr_schedule_d,\n        grad_clip=gradient_clip_d,\n        parameters=discriminator.parameters(),\n        **config[\"discriminator_optimizer_params\"])\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = HiFiGANUpdater(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        discriminator_train_start_steps=config.discriminator_train_start_steps,\n        # only hifigan have generator_train_start_steps\n        generator_train_start_steps=config.generator_train_start_steps,\n        lambda_adv=config.lambda_adv,\n        lambda_aux=config.lambda_aux,\n        lambda_feat_match=config.lambda_feat_match,\n        output_dir=output_dir)\n\n    evaluator = HiFiGANEvaluator(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        lambda_aux=config.lambda_aux,\n        lambda_feat_match=config.lambda_feat_match,\n        output_dir=output_dir)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a HiFiGAN model.\")\n    parser.add_argument(\"--config\", type=str, help=\"HiFiGAN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/multi_band_melgan/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/multi_band_melgan/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import Adam\nfrom paddle.optimizer.lr import MultiStepDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import Clip\nfrom paddlespeech.t2s.models.melgan import MBMelGANEvaluator\nfrom paddlespeech.t2s.models.melgan import MBMelGANUpdater\nfrom paddlespeech.t2s.models.melgan import MelGANGenerator\nfrom paddlespeech.t2s.models.melgan import MelGANMultiScaleDiscriminator\nfrom paddlespeech.t2s.modules.losses import DiscriminatorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import GeneratorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import MultiResolutionSTFTLoss\nfrom paddlespeech.t2s.modules.pqmf import PQMF\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    dev_sampler = DistributedBatchSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    if \"aux_context_window\" in config.generator_params:\n        aux_context_window = config.generator_params.aux_context_window\n    else:\n        aux_context_window = 0\n    train_batch_fn = Clip(\n        batch_max_steps=config.batch_max_steps,\n        hop_size=config.n_shift,\n        aux_context_window=aux_context_window)\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    generator = MelGANGenerator(**config[\"generator_params\"])\n    discriminator = MelGANMultiScaleDiscriminator(\n        **config[\"discriminator_params\"])\n    if world_size > 1:\n        generator = DataParallel(generator)\n        discriminator = DataParallel(discriminator)\n    print(\"models done!\")\n    criterion_stft = MultiResolutionSTFTLoss(**config[\"stft_loss_params\"])\n    criterion_sub_stft = MultiResolutionSTFTLoss(\n        **config[\"subband_stft_loss_params\"])\n    criterion_gen_adv = GeneratorAdversarialLoss()\n    criterion_dis_adv = DiscriminatorAdversarialLoss()\n    # define special module for subband processing\n    criterion_pqmf = PQMF(subbands=config[\"generator_params\"][\"out_channels\"])\n    print(\"criterions done!\")\n\n    lr_schedule_g = MultiStepDecay(**config[\"generator_scheduler_params\"])\n    # Compared to multi_band_melgan.v1 config, Adam optimizer without gradient norm is used\n    generator_grad_norm = config[\"generator_grad_norm\"]\n    gradient_clip_g = nn.ClipGradByGlobalNorm(\n        generator_grad_norm) if generator_grad_norm > 0 else None\n    print(\"gradient_clip_g:\", gradient_clip_g)\n\n    optimizer_g = Adam(\n        learning_rate=lr_schedule_g,\n        grad_clip=gradient_clip_g,\n        parameters=generator.parameters(),\n        **config[\"generator_optimizer_params\"])\n    lr_schedule_d = MultiStepDecay(**config[\"discriminator_scheduler_params\"])\n    discriminator_grad_norm = config[\"discriminator_grad_norm\"]\n    gradient_clip_d = nn.ClipGradByGlobalNorm(\n        discriminator_grad_norm) if discriminator_grad_norm > 0 else None\n    print(\"gradient_clip_d:\", gradient_clip_d)\n    optimizer_d = Adam(\n        learning_rate=lr_schedule_d,\n        grad_clip=gradient_clip_d,\n        parameters=discriminator.parameters(),\n        **config[\"discriminator_optimizer_params\"])\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = MBMelGANUpdater(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"sub_stft\": criterion_sub_stft,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"pqmf\": criterion_pqmf\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        discriminator_train_start_steps=config.discriminator_train_start_steps,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n\n    evaluator = MBMelGANEvaluator(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"sub_stft\": criterion_sub_stft,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"pqmf\": criterion_pqmf\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(\n        description=\"Train a Multi-Band MelGAN model.\")\n    parser.add_argument(\n        \"--config\", type=str, help=\"Multi-Band MelGAN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features.\")\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--stats\", type=str, required=True, help=\"statistics file.\")\n    parser.add_argument(\n        \"--skip-wav-copy\",\n        default=False,\n        action=\"store_true\",\n        help=\"whether to skip the copy of wav files.\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        fields=[\"utt_id\", \"wave\", \"feats\"],\n        converters={\n            'utt_id': None,\n            'wave': None if args.skip_wav_copy else np.load,\n            'feats': np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    scaler = StandardScaler()\n    scaler.mean_ = np.load(args.stats)[0]\n    scaler.scale_ = np.load(args.stats)[1]\n\n    # from version 0.23.0, this information is needed\n    scaler.n_features_in_ = scaler.mean_.shape[0]\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        wave = item['wave']\n        mel = item['feats']\n        # normalize\n        mel = scaler.transform(mel)\n\n        # save\n        mel_path = dumpdir / f\"{utt_id}_feats.npy\"\n        np.save(mel_path, mel.astype(np.float32), allow_pickle=False)\n        if not args.skip_wav_copy:\n            wav_path = dumpdir / f\"{utt_id}_wave.npy\"\n            np.save(wav_path, wave.astype(np.float32), allow_pickle=False)\n        else:\n            wav_path = wave\n        output_metadata.append({\n            'utt_id': utt_id,\n            'wave': str(wav_path),\n            'feats': str(mel_path),\n        })\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan/synthesize_from_wav.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nfrom pathlib import Path\n\nimport librosa\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n\ndef evaluate(args, config):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    vocoder = PWGGenerator(**config[\"generator_params\"])\n    state_dict = paddle.load(args.checkpoint)\n    vocoder.set_state_dict(state_dict[\"generator_params\"])\n    vocoder.remove_weight_norm()\n    vocoder.eval()\n    print(\"model done!\")\n\n    stat = np.load(args.stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    normalizer = ZScore(mu, std)\n\n    pwg_inference = PWGInference(normalizer, vocoder)\n\n    input_dir = Path(args.input_dir)\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    for utt_name in os.listdir(input_dir):\n        wav, _ = librosa.load(str(input_dir / utt_name), sr=config.fs)\n        # extract mel feats\n        mel = mel_extractor.get_log_mel_fbank(wav)\n        mel = paddle.to_tensor(mel)\n        with paddle.no_grad():\n            gen_wav = pwg_inference(mel)\n        sf.write(\n            str(output_dir / (\"gen_\" + utt_name)),\n            gen_wav.numpy(),\n            samplerate=config.fs)\n        print(f\"{utt_name} done!\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with parallel wavegan.\")\n\n    parser.add_argument(\n        \"--config\", type=str, help=\"parallel wavegan config file.\")\n    parser.add_argument(\"--checkpoint\", type=str, help=\"snapshot to load.\")\n    parser.add_argument(\n        \"--stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training parallel wavegan.\"\n    )\n    parser.add_argument(\"--input-dir\", type=str, help=\"input dir of wavs.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    evaluate(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import Adam  # No RAdaom\nfrom paddle.optimizer.lr import StepDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import Clip\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGDiscriminator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGEvaluator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGUpdater\nfrom paddlespeech.t2s.modules.losses import MultiResolutionSTFTLoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    dev_sampler = DistributedBatchSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    train_batch_fn = Clip(\n        batch_max_steps=config.batch_max_steps,\n        hop_size=config.n_shift,\n        aux_context_window=config.generator_params.aux_context_window)\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    generator = PWGGenerator(**config[\"generator_params\"])\n    discriminator = PWGDiscriminator(**config[\"discriminator_params\"])\n    if world_size > 1:\n        generator = DataParallel(generator)\n        discriminator = DataParallel(discriminator)\n    print(\"models done!\")\n\n    criterion_stft = MultiResolutionSTFTLoss(**config[\"stft_loss_params\"])\n    criterion_mse = nn.MSELoss()\n    print(\"criterions done!\")\n\n    lr_schedule_g = StepDecay(**config[\"generator_scheduler_params\"])\n    gradient_clip_g = nn.ClipGradByGlobalNorm(config[\"generator_grad_norm\"])\n    optimizer_g = Adam(\n        learning_rate=lr_schedule_g,\n        grad_clip=gradient_clip_g,\n        parameters=generator.parameters(),\n        **config[\"generator_optimizer_params\"])\n    lr_schedule_d = StepDecay(**config[\"discriminator_scheduler_params\"])\n    gradient_clip_d = nn.ClipGradByGlobalNorm(config[\"discriminator_grad_norm\"])\n    optimizer_d = Adam(\n        learning_rate=lr_schedule_d,\n        grad_clip=gradient_clip_d,\n        parameters=discriminator.parameters(),\n        **config[\"discriminator_optimizer_params\"])\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = PWGUpdater(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"mse\": criterion_mse,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        discriminator_train_start_steps=config.discriminator_train_start_steps,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n\n    evaluator = PWGEvaluator(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"mse\": criterion_mse,\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir,\n        profiler_options=args.profiler_options)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(\n        description=\"Train a ParallelWaveGAN model.\")\n    parser.add_argument(\n        \"--config\", type=str, help=\"ParallelWaveGAN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    benchmark_group = parser.add_argument_group(\n        'benchmark', 'arguments related to benchmark.')\n    benchmark_group.add_argument(\n        \"--batch-size\", type=int, default=8, help=\"batch size.\")\n    benchmark_group.add_argument(\n        \"--max-iter\", type=int, default=400000, help=\"train max steps.\")\n\n    benchmark_group.add_argument(\n        \"--run-benchmark\",\n        type=str2bool,\n        default=False,\n        help=\"runing benchmark or not, if True, use the --batch-size and --max-iter.\"\n    )\n    benchmark_group.add_argument(\n        \"--profiler_options\",\n        type=str,\n        default=None,\n        help=\"The option of profiler, which should be in format \\\"key1=value1;key2=value2;key3=value3\\\".\"\n    )\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    # 增加 --batch_size --max_iter 用于 benchmark 调用\n    if args.run_benchmark:\n        config.batch_size = args.batch_size\n        config.train_max_steps = args.max_iter\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_sentences_svs\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     cut_sil: bool=True):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        y, _ = librosa.load(str(fp), sr=config.fs)\n        if len(y.shape) != 1:\n            return record\n        max_value = np.abs(y).max()\n        if max_value > 1.0:\n            y = y / max_value\n        assert len(y.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(y).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            y = y[start:end]\n\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(y)\n\n        # adjust time to make num_samples == num_frames * hop_length\n        num_frames = logmel.shape[0]\n        if y.size < num_frames * config.n_shift:\n            y = np.pad(\n                y, (0, num_frames * config.n_shift - y.size), mode=\"reflect\")\n        else:\n            y = y[:num_frames * config.n_shift]\n        num_samples = y.shape[0]\n\n        mel_path = output_dir / (utt_id + \"_feats.npy\")\n        wav_path = output_dir / (utt_id + \"_wave.npy\")\n        # (num_samples, )\n        np.save(wav_path, y)\n        # (num_frames, n_mels)\n        np.save(mel_path, logmel)\n        record = {\n            \"utt_id\": utt_id,\n            \"num_samples\": num_samples,\n            \"num_frames\": num_frames,\n            \"feats\": str(mel_path),\n            \"wave\": str(wav_path),\n        }\n        return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True):\n\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                cut_sil=cut_sil)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         cut_sil)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'w') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features .\")\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\"--config\", type=str, help=\"vocoder config file.\")\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    if args.dataset == \"opencpop\":\n        sentences, speaker_set = get_sentences_svs(\n            dur_file,\n            dataset=args.dataset,\n            sample_rate=config.fs,\n            n_shift=config.n_shift, )\n    else:\n        sentences, speaker_set = get_phn_dur(dur_file)\n        merge_silence(sentences)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"opencpop\":\n        wavdir = rootdir / \"wavs\"\n        # split data into 3 sections\n        train_file = rootdir / \"train.txt\"\n        train_wav_files = []\n        with open(train_file, \"r\") as f_train:\n            for line in f_train.readlines():\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                train_wav_files.append(wav_path)\n\n        test_file = rootdir / \"test.txt\"\n        dev_wav_files = []\n        test_wav_files = []\n        num_dev = 106\n        count = 0\n        with open(test_file, \"r\") as f_test:\n            for line in f_test.readlines():\n                count += 1\n                utt = line.split(\"|\")[0]\n                wav_name = utt + \".wav\"\n                wav_path = wavdir / wav_name\n                if count > num_dev:\n                    test_wav_files.append(wav_path)\n                else:\n                    dev_wav_files.append(wav_path)\n    else:\n        print(\"dataset should in {baker, ljspeech, vctk, aishell3} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/style_melgan/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/style_melgan/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import Adam\nfrom paddle.optimizer.lr import MultiStepDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import Clip\nfrom paddlespeech.t2s.models.melgan import StyleMelGANDiscriminator\nfrom paddlespeech.t2s.models.melgan import StyleMelGANEvaluator\nfrom paddlespeech.t2s.models.melgan import StyleMelGANGenerator\nfrom paddlespeech.t2s.models.melgan import StyleMelGANUpdater\nfrom paddlespeech.t2s.modules.losses import DiscriminatorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import GeneratorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import MultiResolutionSTFTLoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    dev_sampler = DistributedBatchSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    if \"aux_context_window\" in config.generator_params:\n        aux_context_window = config.generator_params.aux_context_window\n    else:\n        aux_context_window = 0\n    train_batch_fn = Clip(\n        batch_max_steps=config.batch_max_steps,\n        hop_size=config.n_shift,\n        aux_context_window=aux_context_window)\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=train_batch_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    generator = StyleMelGANGenerator(**config[\"generator_params\"])\n    discriminator = StyleMelGANDiscriminator(**config[\"discriminator_params\"])\n    if world_size > 1:\n        generator = DataParallel(generator)\n        discriminator = DataParallel(discriminator)\n    print(\"models done!\")\n    criterion_stft = MultiResolutionSTFTLoss(**config[\"stft_loss_params\"])\n\n    criterion_gen_adv = GeneratorAdversarialLoss(\n        **config[\"generator_adv_loss_params\"])\n    criterion_dis_adv = DiscriminatorAdversarialLoss(\n        **config[\"discriminator_adv_loss_params\"])\n    print(\"criterions done!\")\n\n    lr_schedule_g = MultiStepDecay(**config[\"generator_scheduler_params\"])\n    # Compared to multi_band_melgan.v1 config, Adam optimizer without gradient norm is used\n    generator_grad_norm = config[\"generator_grad_norm\"]\n    gradient_clip_g = nn.ClipGradByGlobalNorm(\n        generator_grad_norm) if generator_grad_norm > 0 else None\n    print(\"gradient_clip_g:\", gradient_clip_g)\n\n    optimizer_g = Adam(\n        learning_rate=lr_schedule_g,\n        grad_clip=gradient_clip_g,\n        parameters=generator.parameters(),\n        **config[\"generator_optimizer_params\"])\n    lr_schedule_d = MultiStepDecay(**config[\"discriminator_scheduler_params\"])\n    discriminator_grad_norm = config[\"discriminator_grad_norm\"]\n    gradient_clip_d = nn.ClipGradByGlobalNorm(\n        discriminator_grad_norm) if discriminator_grad_norm > 0 else None\n    print(\"gradient_clip_d:\", gradient_clip_d)\n    optimizer_d = Adam(\n        learning_rate=lr_schedule_d,\n        grad_clip=gradient_clip_d,\n        parameters=discriminator.parameters(),\n        **config[\"discriminator_optimizer_params\"])\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = StyleMelGANUpdater(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        discriminator_train_start_steps=config.discriminator_train_start_steps,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n\n    evaluator = StyleMelGANEvaluator(\n        models={\n            \"generator\": generator,\n            \"discriminator\": discriminator,\n        },\n        criterions={\n            \"stft\": criterion_stft,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        output_dir=output_dir)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a Style MelGAN model.\")\n    parser.add_argument(\"--config\", type=str, help=\"Style MelGAN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/gan_vocoder/synthesize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom paddle import distributed as dist\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nimport paddlespeech\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Synthesize with GANVocoder.\")\n    parser.add_argument(\n        \"--generator-type\",\n        type=str,\n        default=\"pwgan\",\n        help=\"type of GANVocoder, should in {pwgan, mb_melgan, style_melgan, hifigan, } now\"\n    )\n    parser.add_argument(\"--config\", type=str, help=\"GANVocoder config file.\")\n    parser.add_argument(\"--checkpoint\", type=str, help=\"snapshot to load.\")\n    parser.add_argument(\"--test-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    class_map = {\n        \"hifigan\": \"HiFiGANGenerator\",\n        \"mb_melgan\": \"MelGANGenerator\",\n        \"pwgan\": \"PWGGenerator\",\n        \"style_melgan\": \"StyleMelGANGenerator\",\n    }\n\n    generator_type = args.generator_type\n\n    assert generator_type in class_map\n\n    print(\"generator_type:\", generator_type)\n\n    generator_class = getattr(paddlespeech.t2s.models,\n                              class_map[generator_type])\n    generator = generator_class(**config[\"generator_params\"])\n    state_dict = paddle.load(args.checkpoint)\n    generator.set_state_dict(state_dict[\"generator_params\"])\n    generator.remove_weight_norm()\n    generator.eval()\n\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        metadata = list(reader)\n    test_dataset = DataTable(\n        metadata,\n        fields=['utt_id', 'feats'],\n        converters={\n            'utt_id': None,\n            'feats': np.load,\n        })\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    N = 0\n    T = 0\n    for example in test_dataset:\n        utt_id = example['utt_id']\n        mel = example['feats']\n        mel = paddle.to_tensor(mel)  # (T, C)\n        with timer() as t:\n            with paddle.no_grad():\n                wav = generator.inference(c=mel)\n            wav = wav.numpy()\n            N += wav.size\n            T += t.elapse\n            speed = wav.size / t.elapse\n            rtf = config.fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/inference.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import get_am_output\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_predictor\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_output\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'fastspeech2_csmsc',\n            'fastspeech2_aishell3',\n            'fastspeech2_ljspeech',\n            'fastspeech2_vctk',\n            'tacotron2_csmsc',\n            'fastspeech2_mix',\n            'fastspeech2_male-zh',\n            'fastspeech2_male-en',\n            'fastspeech2_male-mix',\n            'fastspeech2_canton',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_aishell3',\n            'pwgan_ljspeech',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_aishell3',\n            'hifigan_ljspeech',\n            'hifigan_vctk',\n            'wavernn_csmsc',\n            'pwgan_male',\n            'hifigan_male',\n        ],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en or mix')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use TensorRT or not in GPU\", )\n    parser.add_argument(\n        \"--use_mkldnn\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use MKLDNN or not in CPU.\", )\n    parser.add_argument(\n        \"--precision\",\n        type=str,\n        default='fp32',\n        choices=['fp32', 'fp16', 'bf16', 'int8'],\n        help=\"mode of running\")\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\", \"xpu\", \"npu\", \"mlu\", \"gcu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    # am_predictor\n    am_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \".pdmodel\",\n        params_file=args.am + \".pdiparams\",\n        device=args.device,\n        use_trt=args.use_trt,\n        use_mkldnn=args.use_mkldnn,\n        cpu_threads=args.cpu_threads,\n        precision=args.precision)\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    # voc_predictor\n    voc_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.voc + \".pdmodel\",\n        params_file=args.voc + \".pdiparams\",\n        device=args.device,\n        use_trt=args.use_trt,\n        use_mkldnn=args.use_mkldnn,\n        cpu_threads=args.cpu_threads,\n        precision=args.precision)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            mel = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n            wav = get_voc_output(voc_predictor=voc_predictor, input=mel)\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            mel = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n            wav = get_voc_output(voc_predictor=voc_predictor, input=mel)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/inference_streaming.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import denorm\nfrom paddlespeech.t2s.exps.syn_utils import get_am_sublayer_output\nfrom paddlespeech.t2s.exps.syn_utils import get_chunks\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_predictor\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_streaming_am_output\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_output\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_csmsc'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=['pwgan_csmsc', 'mb_melgan_csmsc', 'hifigan_csmsc'],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    # inference\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    # streaming related\n    parser.add_argument(\n        \"--am_streaming\",\n        type=str2bool,\n        default=False,\n        help=\"whether use streaming acoustic model\")\n    parser.add_argument(\n        \"--block_size\", type=int, default=42, help=\"block size of am streaming\")\n    parser.add_argument(\n        \"--pad_size\", type=int, default=12, help=\"pad size of am streaming\")\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    # am_predictor\n\n    am_encoder_infer_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_encoder_infer\" + \".pdmodel\",\n        params_file=args.am + \"_am_encoder_infer\" + \".pdiparams\",\n        device=args.device)\n    am_decoder_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_decoder\" + \".pdmodel\",\n        params_file=args.am + \"_am_decoder\" + \".pdiparams\",\n        device=args.device)\n    am_postnet_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_postnet\" + \".pdmodel\",\n        params_file=args.am + \"_am_postnet\" + \".pdiparams\",\n        device=args.device)\n    am_mu, am_std = np.load(args.am_stat)\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    # voc_predictor\n    voc_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.voc + \".pdmodel\",\n        params_file=args.voc + \".pdiparams\",\n        device=args.device)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            normalized_mel = get_streaming_am_output(\n                input=sentence,\n                am_encoder_infer_predictor=am_encoder_infer_predictor,\n                am_decoder_predictor=am_decoder_predictor,\n                am_postnet_predictor=am_postnet_predictor,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences, )\n            mel = denorm(normalized_mel, am_mu, am_std)\n            wav = get_voc_output(voc_predictor=voc_predictor, input=mel)\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    block_size = args.block_size\n    pad_size = args.pad_size\n    get_tone_ids = False\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            # frontend\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=sentence,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang)\n            phone_ids = frontend_dict['phone_ids']\n            phones = phone_ids[0].numpy()\n            # acoustic model\n            orig_hs = get_am_sublayer_output(\n                am_encoder_infer_predictor, input=phones)\n\n            if args.am_streaming:\n                hss = get_chunks(orig_hs, block_size, pad_size)\n                chunk_num = len(hss)\n                mel_list = []\n                for i, hs in enumerate(hss):\n                    am_decoder_output = get_am_sublayer_output(\n                        am_decoder_predictor, input=hs)\n                    am_postnet_output = get_am_sublayer_output(\n                        am_postnet_predictor,\n                        input=np.transpose(am_decoder_output, (0, 2, 1)))\n                    am_output_data = am_decoder_output + np.transpose(\n                        am_postnet_output, (0, 2, 1))\n                    normalized_mel = am_output_data[0]\n\n                    sub_mel = denorm(normalized_mel, am_mu, am_std)\n                    # clip output part of pad\n                    if i == 0:\n                        sub_mel = sub_mel[:-pad_size]\n                    elif i == chunk_num - 1:\n                        # 最后一块的右侧一定没有 pad 够\n                        sub_mel = sub_mel[pad_size:]\n                    else:\n                        # 倒数几块的右侧也可能没有 pad 够\n                        sub_mel = sub_mel[pad_size:(block_size + pad_size) -\n                                          sub_mel.shape[0]]\n                    mel_list.append(sub_mel)\n                mel = np.concatenate(mel_list, axis=0)\n\n            else:\n                am_decoder_output = get_am_sublayer_output(\n                    am_decoder_predictor, input=orig_hs)\n\n                am_postnet_output = get_am_sublayer_output(\n                    am_postnet_predictor,\n                    input=np.transpose(am_decoder_output, (0, 2, 1)))\n                am_output_data = am_decoder_output + np.transpose(\n                    am_postnet_output, (0, 2, 1))\n                normalized_mel = am_output_data[0]\n                mel = denorm(normalized_mel, am_mu, am_std)\n            # vocoder\n            wav = get_voc_output(voc_predictor=voc_predictor, input=mel)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=24000)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/inference.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import get_am_output\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_predictor\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='jets_csmsc',\n        choices=['jets_csmsc', 'jets_aishell3'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en or mix')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--add-blank\",\n        type=str2bool,\n        default=True,\n        help=\"whether to add blank between phones\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use TensorRT or not in GPU\", )\n    parser.add_argument(\n        \"--use_mkldnn\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use MKLDNN or not in CPU.\", )\n    parser.add_argument(\n        \"--precision\",\n        type=str,\n        default='fp32',\n        choices=['fp32', 'fp16', 'bf16', 'int8'],\n        help=\"mode of running\")\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    # frontend\n    frontend = get_frontend(lang=args.lang, phones_dict=args.phones_dict)\n\n    # am_predictor\n    am_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \".pdmodel\",\n        params_file=args.am + \".pdiparams\",\n        device=args.device,\n        use_trt=args.use_trt,\n        use_mkldnn=args.use_mkldnn,\n        cpu_threads=args.cpu_threads,\n        precision=args.precision)\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n    add_blank = args.add_blank\n    # jets's fs is 22050\n    fs = 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            wav = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            wav = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--feats-stats\", type=str, required=True, help=\"feats statistics file.\")\n    parser.add_argument(\n        \"--pitch-stats\", type=str, required=True, help=\"pitch statistics file.\")\n    parser.add_argument(\n        \"--energy-stats\",\n        type=str,\n        required=True,\n        help=\"energy statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        converters={\n            \"feats\": np.load,\n            \"pitch\": np.load,\n            \"energy\": np.load,\n            \"wave\": str,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    feats_scaler = StandardScaler()\n    feats_scaler.mean_ = np.load(args.feats_stats)[0]\n    feats_scaler.scale_ = np.load(args.feats_stats)[1]\n    feats_scaler.n_features_in_ = feats_scaler.mean_.shape[0]\n\n    pitch_scaler = StandardScaler()\n    pitch_scaler.mean_ = np.load(args.pitch_stats)[0]\n    pitch_scaler.scale_ = np.load(args.pitch_stats)[1]\n    pitch_scaler.n_features_in_ = pitch_scaler.mean_.shape[0]\n\n    energy_scaler = StandardScaler()\n    energy_scaler.mean_ = np.load(args.energy_stats)[0]\n    energy_scaler.scale_ = np.load(args.energy_stats)[1]\n    energy_scaler.n_features_in_ = energy_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        feats = item['feats']\n        pitch = item['pitch']\n        energy = item['energy']\n        wave_path = item['wave']\n        # normalize\n        feats = feats_scaler.transform(feats)\n        feats_dir = dumpdir / \"data_feats\"\n        feats_dir.mkdir(parents=True, exist_ok=True)\n        feats_path = feats_dir / f\"{utt_id}_feats.npy\"\n        np.save(feats_path, feats.astype(np.float32), allow_pickle=False)\n\n        pitch = pitch_scaler.transform(pitch)\n        pitch_dir = dumpdir / \"data_pitch\"\n        pitch_dir.mkdir(parents=True, exist_ok=True)\n        pitch_path = pitch_dir / f\"{utt_id}_pitch.npy\"\n        np.save(pitch_path, pitch.astype(np.float32), allow_pickle=False)\n\n        energy = energy_scaler.transform(energy)\n        energy_dir = dumpdir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / f\"{utt_id}_energy.npy\"\n        np.save(energy_path, energy.astype(np.float32), allow_pickle=False)\n\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"feats_lengths\": item['feats_lengths'],\n            \"durations\": item['durations'],\n            \"feats\": str(feats_path),\n            \"pitch\": str(pitch_path),\n            \"energy\": str(energy_path),\n            \"wave\": str(wave_path),\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import Energy\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.get_feats import Pitch\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     pitch_extractor=None,\n                     energy_extractor=None,\n                     cut_sil: bool=True,\n                     spk_emb_dir: Path=None,\n                     token_average: bool=True):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(\n            str(fp), sr=config.fs,\n            mono=False) if \"canton\" in str(fp) else librosa.load(\n                str(fp), sr=config.fs)\n        if len(wav.shape) == 2 and \"canton\" in str(fp):\n            # Remind that Cantonese datasets should be placed in ~/datasets/canton_all. Otherwise, it may cause problem.\n            wav = wav[0]\n            wav = np.ascontiguousarray(wav)\n        elif len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n        assert sum(durations) == num_frames\n        mel_dir = output_dir / \"data_feats\"\n        mel_dir.mkdir(parents=True, exist_ok=True)\n        mel_path = mel_dir / (utt_id + \"_feats.npy\")\n        np.save(mel_path, logmel)\n\n        if wav.size < num_frames * config.n_shift:\n            wav = np.pad(\n                wav, (0, num_frames * config.n_shift - wav.size),\n                mode=\"reflect\")\n        else:\n            wav = wav[:num_frames * config.n_shift]\n        wave_dir = output_dir / \"data_wave\"\n        wave_dir.mkdir(parents=True, exist_ok=True)\n        wav_path = wave_dir / (utt_id + \"_wave.npy\")\n        # (num_samples, )\n        np.save(wav_path, wav)\n        # extract pitch and energy\n        if token_average == True:\n            f0 = pitch_extractor.get_pitch(\n                wav,\n                duration=np.array(durations),\n                use_token_averaged_f0=token_average)\n            if (f0 == 0).all():\n                return None\n            assert f0.shape[0] == len(durations)\n        else:\n            f0 = pitch_extractor.get_pitch(\n                wav, use_token_averaged_f0=token_average)\n            if (f0 == 0).all():\n                return None\n            f0 = f0[:num_frames]\n            assert f0.shape[0] == num_frames\n        f0_dir = output_dir / \"data_pitch\"\n        f0_dir.mkdir(parents=True, exist_ok=True)\n        f0_path = f0_dir / (utt_id + \"_pitch.npy\")\n        np.save(f0_path, f0)\n        if token_average == True:\n            energy = energy_extractor.get_energy(\n                wav,\n                duration=np.array(durations),\n                use_token_averaged_energy=token_average)\n            assert energy.shape[0] == len(durations)\n        else:\n            energy = energy_extractor.get_energy(\n                wav, use_token_averaged_energy=token_average)\n            energy = energy[:num_frames]\n            assert energy.shape[0] == num_frames\n\n        energy_dir = output_dir / \"data_energy\"\n        energy_dir.mkdir(parents=True, exist_ok=True)\n        energy_path = energy_dir / (utt_id + \"_energy.npy\")\n        np.save(energy_path, energy)\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"feats_lengths\": num_frames,\n            \"durations\": durations,\n            \"feats\": str(mel_path),\n            \"pitch\": str(f0_path),\n            \"energy\": str(energy_path),\n            \"wave\": str(wav_path),\n            \"speaker\": speaker\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      pitch_extractor=None,\n                      energy_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      spk_emb_dir: Path=None,\n                      write_metadata_method: str='w',\n                      token_average: bool=True):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                pitch_extractor=pitch_extractor,\n                energy_extractor=energy_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir,\n                token_average=token_average)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         pitch_extractor, energy_extractor,\n                                         cut_sil, spk_emb_dir)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\",\n                        write_metadata_method) as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n\n    parser.add_argument(\n        \"--write_metadata_method\",\n        default=\"w\",\n        type=str,\n        choices=[\"w\", \"a\"],\n        help=\"How the metadata.jsonl file is written.\")\n\n    parser.add_argument(\n        \"--token_average\",\n        type=str2bool,\n        default=False,\n        help=\"Average the energy and pitch accroding to durations\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"canton\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"WAV\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {baker, aishell3, ljspeech, vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n    pitch_extractor = Pitch(\n        sr=config.fs,\n        hop_length=config.n_shift,\n        f0min=config.f0min,\n        f0max=config.f0max)\n    energy_extractor = Energy(\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method,\n            token_average=args.token_average)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method,\n            token_average=args.token_average)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            pitch_extractor=pitch_extractor,\n            energy_extractor=energy_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir,\n            write_metadata_method=args.write_metadata_method,\n            token_average=args.token_average)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/synthesize.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.jets import JETS\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n    # Init body.\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    fields = [\"utt_id\", \"text\"]\n    converters = {}\n\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker jets!\")\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Evaluating voice cloning!\")\n        fields += [\"spk_emb\"]\n    else:\n        print(\"single speaker jets!\")\n    print(\"spk_num:\", spk_num)\n\n    test_dataset = DataTable(\n        data=test_metadata,\n        fields=fields,\n        converters=converters, )\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_fft // 2 + 1\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n\n    jets = JETS(idim=vocab_size, odim=odim, **config[\"model\"])\n    jets.set_state_dict(paddle.load(args.ckpt)[\"main_params\"])\n    jets.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    N = 0\n    T = 0\n\n    for datum in test_dataset:\n        utt_id = datum[\"utt_id\"]\n        phone_ids = paddle.to_tensor(datum[\"text\"])\n        with timer() as t:\n            with paddle.no_grad():\n                spk_emb = None\n                spk_id = None\n                # multi speaker\n                if args.voice_cloning and \"spk_emb\" in datum:\n                    spk_emb = paddle.to_tensor(np.load(datum[\"spk_emb\"]))\n                elif \"spk_id\" in datum:\n                    spk_id = paddle.to_tensor(datum[\"spk_id\"])\n                out = jets.inference(\n                    text=phone_ids, sids=spk_id, spembs=spk_emb)\n            wav = out[\"wav\"]\n            wav = wav.numpy()\n            N += wav.size\n            T += t.elapse\n            speed = wav.size / t.elapse\n            rtf = config.fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.size}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(description=\"Synthesize with JETS\")\n    # model\n    parser.add_argument(\n        '--config', type=str, default=None, help='Config of JETS.')\n    parser.add_argument(\n        '--ckpt', type=str, default=None, help='Checkpoint file of JETS.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n    # other\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\"--test_metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/synthesize_e2e.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import am_to_static\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.models.jets import JETS\nfrom paddlespeech.t2s.models.jets import JETSInference\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n    # Init body.\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    # frontend\n    frontend = get_frontend(lang=args.lang, phones_dict=args.phones_dict)\n    # acoustic model\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker jets!\")\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n    else:\n        print(\"single speaker jets!\")\n    print(\"spk_num:\", spk_num)\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_fft // 2 + 1\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n\n    jets = JETS(idim=vocab_size, odim=odim, **config[\"model\"])\n    jets.set_state_dict(paddle.load(args.ckpt)[\"main_params\"])\n    jets.eval()\n\n    jets_inference = JETSInference(jets)\n    # whether dygraph to static\n    if args.inference_dir:\n        jets_inference = am_to_static(\n            am_inference=jets_inference,\n            am=args.am,\n            inference_dir=args.inference_dir,\n            speaker_dict=args.speaker_dict)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    merge_sentences = False\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            if args.lang == 'zh':\n                input_ids = frontend.get_input_ids(\n                    sentence, merge_sentences=merge_sentences)\n                phone_ids = input_ids[\"phone_ids\"]\n            elif args.lang == 'en':\n                input_ids = frontend.get_input_ids(\n                    sentence, merge_sentences=merge_sentences)\n                phone_ids = input_ids[\"phone_ids\"]\n            else:\n                print(\"lang should in {'zh', 'en'}!\")\n            with paddle.no_grad():\n                flags = 0\n                for i in range(len(phone_ids)):\n                    part_phone_ids = phone_ids[i]\n                    spk_id = None\n                    if am_dataset in {\"aishell3\",\n                                      \"vctk\"} and spk_num is not None:\n                        spk_id = paddle.to_tensor(args.spk_id)\n                        wav = jets_inference(part_phone_ids, spk_id)\n                    else:\n                        wav = jets_inference(part_phone_ids)\n                    if flags == 0:\n                        wav_all = wav\n                        flags = 1\n                    else:\n                        wav_all = paddle.concat([wav_all, wav])\n        wav = wav_all.numpy()\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = config.fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config \n    parser = argparse.ArgumentParser(description=\"Synthesize with JETS\")\n\n    # model\n    parser.add_argument(\n        '--config', type=str, default=None, help='Config of JETS.')\n    parser.add_argument(\n        '--ckpt', type=str, default=None, help='Checkpoint file of JETS.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n\n    parser.add_argument(\n        \"--inference_dir\",\n        type=str,\n        default=None,\n        help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='jets_csmsc',\n        help='Choose acoustic model type of tts task.')\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/jets/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.optimizer import AdamW\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import jets_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import jets_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.sampler import ErnieSATSampler\nfrom paddlespeech.t2s.models.jets import JETS\nfrom paddlespeech.t2s.models.jets import JETSEvaluator\nfrom paddlespeech.t2s.models.jets import JETSUpdater\nfrom paddlespeech.t2s.modules.losses import DiscriminatorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import FeatureMatchLoss\nfrom paddlespeech.t2s.modules.losses import ForwardSumLoss\nfrom paddlespeech.t2s.modules.losses import GeneratorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import MelSpectrogramLoss\nfrom paddlespeech.t2s.modules.losses import VarianceLoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import scheduler_classes\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    fields = [\n        \"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"wave\", \"durations\",\n        \"pitch\", \"energy\"\n    ]\n\n    converters = {\n        \"wave\": np.load,\n        \"feats\": np.load,\n        \"pitch\": np.load,\n        \"energy\": np.load,\n    }\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker jets!\")\n        collate_fn = jets_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Training voice cloning!\")\n        collate_fn = jets_multi_spk_batch_fn\n        fields += [\"spk_emb\"]\n        converters[\"spk_emb\"] = np.load\n    else:\n        print(\"single speaker jets!\")\n        collate_fn = jets_single_spk_batch_fn\n    print(\"spk_num:\", spk_num)\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    train_sampler = ErnieSATSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=True)\n    dev_sampler = ErnieSATSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n    model = JETS(idim=vocab_size, odim=odim, **config[\"model\"])\n    gen_parameters = model.generator.parameters()\n    dis_parameters = model.discriminator.parameters()\n    if world_size > 1:\n        model = DataParallel(model)\n        gen_parameters = model._layers.generator.parameters()\n        dis_parameters = model._layers.discriminator.parameters()\n\n    print(\"model done!\")\n\n    # loss\n    criterion_mel = MelSpectrogramLoss(\n        **config[\"mel_loss_params\"], )\n    criterion_feat_match = FeatureMatchLoss(\n        **config[\"feat_match_loss_params\"], )\n    criterion_gen_adv = GeneratorAdversarialLoss(\n        **config[\"generator_adv_loss_params\"], )\n    criterion_dis_adv = DiscriminatorAdversarialLoss(\n        **config[\"discriminator_adv_loss_params\"], )\n    criterion_var = VarianceLoss()\n    criterion_forwardsum = ForwardSumLoss()\n\n    print(\"criterions done!\")\n\n    lr_schedule_g = scheduler_classes[config[\"generator_scheduler\"]](\n        **config[\"generator_scheduler_params\"])\n    optimizer_g = AdamW(\n        learning_rate=lr_schedule_g,\n        parameters=gen_parameters,\n        **config[\"generator_optimizer_params\"])\n\n    lr_schedule_d = scheduler_classes[config[\"discriminator_scheduler\"]](\n        **config[\"discriminator_scheduler_params\"])\n    optimizer_d = AdamW(\n        learning_rate=lr_schedule_d,\n        parameters=dis_parameters,\n        **config[\"discriminator_optimizer_params\"])\n\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = JETSUpdater(\n        model=model,\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"var\": criterion_var,\n            \"forwardsum\": criterion_forwardsum,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        lambda_adv=config.lambda_adv,\n        lambda_mel=config.lambda_mel,\n        lambda_feat_match=config.lambda_feat_match,\n        lambda_var=config.lambda_var,\n        lambda_align=config.lambda_align,\n        generator_first=config.generator_first,\n        use_alignment_module=config.use_alignment_module,\n        output_dir=output_dir)\n\n    evaluator = JETSEvaluator(\n        model=model,\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"var\": criterion_var,\n            \"forwardsum\": criterion_forwardsum,\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        lambda_mel=config.lambda_mel,\n        lambda_feat_match=config.lambda_feat_match,\n        lambda_var=config.lambda_var,\n        lambda_align=config.lambda_align,\n        generator_first=config.generator_first,\n        use_alignment_module=config.use_alignment_module,\n        output_dir=output_dir)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a JETS model.\")\n    parser.add_argument(\"--config\", type=str, help=\"JETS config file\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/lite_predict.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_am_output\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_predictor\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_voc_output\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'fastspeech2_csmsc',\n            'fastspeech2_aishell3',\n            'fastspeech2_ljspeech',\n            'fastspeech2_vctk',\n            'fastspeech2_mix',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_aishell3',\n            'pwgan_ljspeech',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_aishell3',\n            'hifigan_ljspeech',\n            'hifigan_vctk',\n        ],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en or mix')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    # am_predictor\n    am_predictor = get_lite_predictor(\n        model_dir=args.inference_dir, model_file=args.am + \"_x86.nb\")\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    # voc_predictor\n    voc_predictor = get_lite_predictor(\n        model_dir=args.inference_dir, model_file=args.voc + \"_x86.nb\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            mel = get_lite_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n            wav = get_lite_voc_output(voc_predictor=voc_predictor, input=mel)\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            mel = get_lite_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id, )\n            wav = get_lite_voc_output(voc_predictor=voc_predictor, input=mel)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/lite_predict_streaming.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_am_sublayer_output\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_predictor\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_streaming_am_output\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_voc_output\nfrom paddlespeech.t2s.exps.syn_utils import denorm\nfrom paddlespeech.t2s.exps.syn_utils import get_chunks\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_csmsc'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=['pwgan_csmsc', 'mb_melgan_csmsc', 'hifigan_csmsc'],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    # inference\n\n    # streaming related\n    parser.add_argument(\n        \"--am_streaming\",\n        type=str2bool,\n        default=False,\n        help=\"whether use streaming acoustic model\")\n    parser.add_argument(\n        \"--block_size\", type=int, default=42, help=\"block size of am streaming\")\n    parser.add_argument(\n        \"--pad_size\", type=int, default=12, help=\"pad size of am streaming\")\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    # am_predictor\n    am_encoder_infer_predictor = get_lite_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_encoder_infer\" + \"_x86.nb\")\n    am_decoder_predictor = get_lite_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_decoder\" + \"_x86.nb\")\n    am_postnet_predictor = get_lite_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \"_am_postnet\" + \"_x86.nb\")\n    am_mu, am_std = np.load(args.am_stat)\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    # voc_predictor\n    voc_predictor = get_lite_predictor(\n        model_dir=args.inference_dir, model_file=args.voc + \"_x86.nb\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            normalized_mel = get_lite_streaming_am_output(\n                input=sentence,\n                am_encoder_infer_predictor=am_encoder_infer_predictor,\n                am_decoder_predictor=am_decoder_predictor,\n                am_postnet_predictor=am_postnet_predictor,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences, )\n            mel = denorm(normalized_mel, am_mu, am_std)\n            wav = get_lite_voc_output(voc_predictor=voc_predictor, input=mel)\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    block_size = args.block_size\n    pad_size = args.pad_size\n    get_tone_ids = False\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            # frontend\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=sentence,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang)\n            phone_ids = frontend_dict['phone_ids']\n            phones = phone_ids[0].numpy()\n            # acoustic model\n            orig_hs = get_lite_am_sublayer_output(\n                am_encoder_infer_predictor, input=phones)\n\n            if args.am_streaming:\n                hss = get_chunks(orig_hs, block_size, pad_size)\n                chunk_num = len(hss)\n                mel_list = []\n                for i, hs in enumerate(hss):\n                    am_decoder_output = get_lite_am_sublayer_output(\n                        am_decoder_predictor, input=hs)\n                    am_postnet_output = get_lite_am_sublayer_output(\n                        am_postnet_predictor,\n                        input=np.transpose(am_decoder_output, (0, 2, 1)))\n                    am_output_data = am_decoder_output + np.transpose(\n                        am_postnet_output, (0, 2, 1))\n                    normalized_mel = am_output_data[0]\n\n                    sub_mel = denorm(normalized_mel, am_mu, am_std)\n                    # clip output part of pad\n                    if i == 0:\n                        sub_mel = sub_mel[:-pad_size]\n                    elif i == chunk_num - 1:\n                        # 最后一块的右侧一定没有 pad 够\n                        sub_mel = sub_mel[pad_size:]\n                    else:\n                        # 倒数几块的右侧也可能没有 pad 够\n                        sub_mel = sub_mel[pad_size:(block_size + pad_size) -\n                                          sub_mel.shape[0]]\n                    mel_list.append(sub_mel)\n                mel = np.concatenate(mel_list, axis=0)\n\n            else:\n                am_decoder_output = get_lite_am_sublayer_output(\n                    am_decoder_predictor, input=orig_hs)\n                am_postnet_output = get_lite_am_sublayer_output(\n                    am_postnet_predictor,\n                    input=np.transpose(am_decoder_output, (0, 2, 1)))\n                am_output_data = am_decoder_output + np.transpose(\n                    am_postnet_output, (0, 2, 1))\n                normalized_mel = am_output_data[0]\n                mel = denorm(normalized_mel, am_mu, am_std)\n            # vocoder\n            wav = get_lite_voc_output(voc_predictor=voc_predictor, input=mel)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=24000)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/lite_syn_utils.py",
    "content": "import os\nfrom pathlib import Path\nfrom typing import Optional\n\nimport numpy as np\nfrom paddlelite.lite import create_paddle_predictor\nfrom paddlelite.lite import MobileConfig\n\nfrom .syn_utils import run_frontend\n\n\n# Paddle-Lite\ndef get_lite_predictor(model_dir: Optional[os.PathLike]=None,\n                       model_file: Optional[os.PathLike]=None,\n                       cpu_threads: int=1):\n    config = MobileConfig()\n    config.set_model_from_file(str(Path(model_dir) / model_file))\n    predictor = create_paddle_predictor(config)\n    return predictor\n\n\ndef get_lite_am_output(input: str,\n                       am_predictor,\n                       am: str,\n                       frontend: object,\n                       lang: str='zh',\n                       merge_sentences: bool=True,\n                       speaker_dict: Optional[os.PathLike]=None,\n                       spk_id: int=0,\n                       add_blank: bool=False):\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    get_spk_id = False\n    get_tone_ids = False\n    if am_name == 'speedyspeech':\n        get_tone_ids = True\n    if am_dataset in {\"aishell3\", \"vctk\", \"mix\"} and speaker_dict:\n        get_spk_id = True\n        spk_id = np.array([spk_id])\n\n    frontend_dict = run_frontend(\n        frontend=frontend,\n        text=input,\n        merge_sentences=merge_sentences,\n        get_tone_ids=get_tone_ids,\n        lang=lang,\n        add_blank=add_blank, )\n\n    if get_tone_ids:\n        tone_ids = frontend_dict['tone_ids']\n        tones = tone_ids[0].numpy()\n        tones_handle = am_predictor.get_input(1)\n        tones_handle.from_numpy(tones)\n\n    if get_spk_id:\n        spk_id_handle = am_predictor.get_input(1)\n        spk_id_handle.from_numpy(spk_id)\n    phone_ids = frontend_dict['phone_ids']\n    phones = phone_ids[0].numpy()\n    phones_handle = am_predictor.get_input(0)\n    phones_handle.from_numpy(phones)\n    am_predictor.run()\n    am_output_handle = am_predictor.get_output(0)\n    am_output_data = am_output_handle.numpy()\n    return am_output_data\n\n\ndef get_lite_voc_output(voc_predictor, input):\n    mel_handle = voc_predictor.get_input(0)\n    mel_handle.from_numpy(input)\n    voc_predictor.run()\n    voc_output_handle = voc_predictor.get_output(0)\n    wav = voc_output_handle.numpy()\n    return wav\n\n\ndef get_lite_am_sublayer_output(am_sublayer_predictor, input):\n    input_handle = am_sublayer_predictor.get_input(0)\n    input_handle.from_numpy(input)\n\n    am_sublayer_predictor.run()\n    am_sublayer_handle = am_sublayer_predictor.get_output(0)\n    am_sublayer_output = am_sublayer_handle.numpy()\n    return am_sublayer_output\n\n\ndef get_lite_streaming_am_output(input: str,\n                                 am_encoder_infer_predictor,\n                                 am_decoder_predictor,\n                                 am_postnet_predictor,\n                                 frontend,\n                                 lang: str='zh',\n                                 merge_sentences: bool=True):\n    get_tone_ids = False\n    frontend_dict = run_frontend(\n        frontend=frontend,\n        text=input,\n        merge_sentences=merge_sentences,\n        get_tone_ids=get_tone_ids,\n        lang=lang)\n    phone_ids = frontend_dict['phone_ids']\n    phones = phone_ids[0].numpy()\n    am_encoder_infer_output = get_lite_am_sublayer_output(\n        am_encoder_infer_predictor, input=phones)\n    am_decoder_output = get_lite_am_sublayer_output(\n        am_decoder_predictor, input=am_encoder_infer_output)\n    am_postnet_output = get_lite_am_sublayer_output(\n        am_postnet_predictor, input=np.transpose(am_decoder_output, (0, 2, 1)))\n    am_output_data = am_decoder_output + np.transpose(am_postnet_output,\n                                                      (0, 2, 1))\n    normalized_mel = am_output_data[0]\n    return normalized_mel\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ort_predict.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import get_sess\nfrom paddlespeech.t2s.exps.syn_utils import get_test_dataset\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef ort_predict(args):\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n    test_dataset = get_test_dataset(test_metadata=test_metadata, am=args.am)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n\n    # am\n    am_sess = get_sess(\n        model_path=str(Path(args.inference_dir) / (args.am + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    # vocoder\n    voc_sess = get_sess(\n        model_path=str(Path(args.inference_dir) / (args.voc + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    # am warmup\n    for T in [27, 38, 54]:\n        am_input_feed = {}\n        if am_name == 'fastspeech2':\n            phone_ids = np.random.randint(1, 266, size=(T, ))\n            am_input_feed.update({'text': phone_ids})\n        elif am_name == 'speedyspeech':\n            phone_ids = np.random.randint(1, 92, size=(T, ))\n            tone_ids = np.random.randint(1, 5, size=(T, ))\n            am_input_feed.update({'phones': phone_ids, 'tones': tone_ids})\n        am_sess.run(None, input_feed=am_input_feed)\n\n    # voc warmup\n    for T in [227, 308, 544]:\n        data = np.random.rand(T, 80).astype(\"float32\")\n        voc_sess.run(None, {\"logmel\": data})\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    am_input_feed = {}\n    for example in test_dataset:\n        utt_id = example['utt_id']\n        if am_name == 'fastspeech2':\n            phone_ids = example[\"text\"]\n            am_input_feed.update({'text': phone_ids})\n        elif am_name == 'speedyspeech':\n            phone_ids = example[\"phones\"]\n            tone_ids = example[\"tones\"]\n            am_input_feed.update({'phones': phone_ids, 'tones': tone_ids})\n        with timer() as t:\n            mel = am_sess.run(output_names=None, input_feed=am_input_feed)\n            mel = mel[0]\n            wav = voc_sess.run(output_names=None, input_feed={'logmel': mel})\n            N += len(wav[0])\n            T += t.elapse\n            speed = len(wav[0]) / t.elapse\n            rtf = fs / speed\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            np.array(wav)[0],\n            samplerate=fs)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {len(wav[0])}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(description=\"Infernce with onnxruntime.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_csmsc', 'speedyspeech_csmsc'],\n        help='Choose acoustic model type of tts task.')\n\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='hifigan_csmsc',\n        choices=['hifigan_csmsc', 'mb_melgan_csmsc', 'pwgan_csmsc'],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--test_metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"Whether to use inference engin TensorRT.\", )\n\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    ort_predict(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ort_predict_e2e.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_sess\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef ort_predict(args):\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n\n    am_sess = get_sess(\n        model_path=str(Path(args.inference_dir) / (args.am + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    # vocoder\n    voc_sess = get_sess(\n        model_path=str(Path(args.inference_dir) / (args.voc + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    merge_sentences = True\n\n    # frontend warmup\n    # Loading model cost 0.5+ seconds\n    if args.lang == 'zh':\n        frontend.get_input_ids(\n            \"你好，欢迎使用飞桨框架进行深度学习研究！\", merge_sentences=merge_sentences)\n    else:\n        frontend.get_input_ids(\n            \"hello, thank you, thank you very much\",\n            merge_sentences=merge_sentences)\n\n    # am warmup\n    spk_id = [args.spk_id]\n    for T in [27, 38, 54]:\n        am_input_feed = {}\n        if am_name == 'fastspeech2':\n            if args.lang == 'en':\n                phone_ids = np.random.randint(1, 78, size=(T, ))\n            else:\n                phone_ids = np.random.randint(1, 266, size=(T, ))\n            am_input_feed.update({'text': phone_ids})\n            if am_dataset in {\"aishell3\", \"vctk\", \"mix\", \"canton\"}:\n                am_input_feed.update({'spk_id': spk_id})\n        elif am_name == 'speedyspeech':\n            phone_ids = np.random.randint(1, 92, size=(T, ))\n            tone_ids = np.random.randint(1, 5, size=(T, ))\n            am_input_feed.update({'phones': phone_ids, 'tones': tone_ids})\n        am_sess.run(None, input_feed=am_input_feed)\n\n    # voc warmup\n    for T in [227, 308, 544]:\n        data = np.random.rand(T, 80).astype(\"float32\")\n        voc_sess.run(None, input_feed={\"logmel\": data})\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    merge_sentences = False\n    get_tone_ids = False\n    if am_name == 'speedyspeech':\n        get_tone_ids = True\n    am_input_feed = {}\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=sentence,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang)\n            phone_ids = frontend_dict['phone_ids']\n            flags = 0\n            for i in range(len(phone_ids)):\n                part_phone_ids = phone_ids[i].numpy()\n                if am_name == 'fastspeech2':\n                    am_input_feed.update({'text': part_phone_ids})\n                    if am_dataset in {\"aishell3\", \"vctk\", \"mix\", \"canton\"}:\n                        am_input_feed.update({'spk_id': spk_id})\n                elif am_name == 'speedyspeech':\n                    part_tone_ids = frontend_dict['tone_ids'][i].numpy()\n                    am_input_feed.update({\n                        'phones': part_phone_ids,\n                        'tones': part_tone_ids\n                    })\n                mel = am_sess.run(output_names=None, input_feed=am_input_feed)\n                mel = mel[0]\n                wav = voc_sess.run(\n                    output_names=None, input_feed={'logmel': mel})\n                wav = wav[0]\n                if flags == 0:\n                    wav_all = wav\n                    flags = 1\n                else:\n                    wav_all = np.concatenate([wav_all, wav])\n        wav = wav_all\n        N += len(wav)\n        T += t.elapse\n        speed = len(wav) / t.elapse\n        rtf = fs / speed\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {len(wav)}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(description=\"Infernce with onnxruntime.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'fastspeech2_csmsc',\n            'fastspeech2_aishell3',\n            'fastspeech2_ljspeech',\n            'fastspeech2_vctk',\n            'speedyspeech_csmsc',\n            'fastspeech2_mix',\n            'fastspeech2_male-zh',\n            'fastspeech2_male-en',\n            'fastspeech2_male-mix',\n            'fastspeech2_canton',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='hifigan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_aishell3',\n            'pwgan_ljspeech',\n            'pwgan_vctk',\n            'hifigan_csmsc',\n            'hifigan_aishell3',\n            'hifigan_ljspeech',\n            'hifigan_vctk',\n            'mb_melgan_csmsc',\n            'pwgan_male',\n            'hifigan_male',\n        ],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"Whether to use inference engin TensorRT.\", )\n\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    ort_predict(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/ort_predict_streaming.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import denorm\nfrom paddlespeech.t2s.exps.syn_utils import get_chunks\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_sess\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef ort_predict(args):\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n    fs = 24000 if am_dataset != 'ljspeech' else 22050\n\n    # streaming acoustic model\n    am_encoder_infer_sess = get_sess(\n        model_path=str(\n            Path(args.inference_dir) /\n            (args.am + '_am_encoder_infer' + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n    am_decoder_sess = get_sess(\n        model_path=str(\n            Path(args.inference_dir) / (args.am + '_am_decoder' + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    am_postnet_sess = get_sess(\n        model_path=str(\n            Path(args.inference_dir) / (args.am + '_am_postnet' + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n    am_mu, am_std = np.load(args.am_stat)\n\n    # vocoder\n    voc_sess = get_sess(\n        model_path=str(Path(args.inference_dir) / (args.voc + '.onnx')),\n        device=args.device,\n        cpu_threads=args.cpu_threads,\n        use_trt=args.use_trt)\n\n    # frontend warmup\n    # Loading model cost 0.5+ seconds\n    if args.lang == 'zh':\n        frontend.get_input_ids(\"你好，欢迎使用飞桨框架进行深度学习研究！\", merge_sentences=True)\n    else:\n        print(\"lang should in be 'zh' here!\")\n\n    # am warmup\n    for T in [27, 38, 54]:\n        phone_ids = np.random.randint(1, 266, size=(T, ))\n        am_encoder_infer_sess.run(None, input_feed={'text': phone_ids})\n\n        am_decoder_input = np.random.rand(1, T * 15, 384).astype('float32')\n        am_decoder_sess.run(None, input_feed={'xs': am_decoder_input})\n\n        am_postnet_input = np.random.rand(1, 80, T * 15).astype('float32')\n        am_postnet_sess.run(None, input_feed={'xs': am_postnet_input})\n\n    # voc warmup\n    for T in [227, 308, 544]:\n        data = np.random.rand(T, 80).astype(\"float32\")\n        voc_sess.run(None, input_feed={\"logmel\": data})\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    merge_sentences = True\n    get_tone_ids = False\n    block_size = args.block_size\n    pad_size = args.pad_size\n\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=sentence,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang)\n            phone_ids = frontend_dict['phone_ids']\n            # merge_sentences=True here, so we only use the first item of phone_ids\n            phone_ids = phone_ids[0].numpy()\n            orig_hs = am_encoder_infer_sess.run(\n                None, input_feed={'text': phone_ids})\n            if args.am_streaming:\n                hss = get_chunks(orig_hs[0], block_size, pad_size)\n                chunk_num = len(hss)\n                mel_list = []\n                for i, hs in enumerate(hss):\n                    am_decoder_output = am_decoder_sess.run(\n                        None, input_feed={'xs': hs})\n                    am_postnet_output = am_postnet_sess.run(\n                        None,\n                        input_feed={\n                            'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                        })\n                    am_output_data = am_decoder_output + np.transpose(\n                        am_postnet_output[0], (0, 2, 1))\n                    normalized_mel = am_output_data[0][0]\n\n                    sub_mel = denorm(normalized_mel, am_mu, am_std)\n                    # clip output part of pad\n                    if i == 0:\n                        sub_mel = sub_mel[:-pad_size]\n                    elif i == chunk_num - 1:\n                        # 最后一块的右侧一定没有 pad 够\n                        sub_mel = sub_mel[pad_size:]\n                    else:\n                        # 倒数几块的右侧也可能没有 pad 够\n                        sub_mel = sub_mel[pad_size:(block_size + pad_size) -\n                                          sub_mel.shape[0]]\n                    mel_list.append(sub_mel)\n                mel = np.concatenate(mel_list, axis=0)\n            else:\n                am_decoder_output = am_decoder_sess.run(\n                    None, input_feed={'xs': orig_hs[0]})\n                am_postnet_output = am_postnet_sess.run(\n                    None,\n                    input_feed={\n                        'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                    })\n                am_output_data = am_decoder_output + np.transpose(\n                    am_postnet_output[0], (0, 2, 1))\n                normalized_mel = am_output_data[0]\n                mel = denorm(normalized_mel, am_mu, am_std)\n                mel = mel[0]\n            # vocoder\n\n            wav = voc_sess.run(output_names=None, input_feed={'logmel': mel})\n\n            N += len(wav[0])\n            T += t.elapse\n            speed = len(wav[0]) / t.elapse\n            rtf = fs / speed\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            np.array(wav)[0],\n            samplerate=fs)\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {len(wav[0])}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(description=\"Infernce with onnxruntime.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_csmsc'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n\n    # voc\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='hifigan_csmsc',\n        choices=['hifigan_csmsc', 'mb_melgan_csmsc', 'pwgan_csmsc'],\n        help='Choose vocoder type of tts task.')\n    # other\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"Whether to use inference engin TensorRT.\", )\n\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    # streaming related\n    parser.add_argument(\n        \"--am_streaming\",\n        type=str2bool,\n        default=False,\n        help=\"whether use streaming acoustic model\")\n    parser.add_argument(\n        \"--block_size\", type=int, default=42, help=\"block size of am streaming\")\n    parser.add_argument(\n        \"--pad_size\", type=int, default=12, help=\"pad size of am streaming\")\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    ort_predict(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/gen_gta_mel.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# generate mels using durations.txt\n# for mb melgan finetune\n# 长度和原本的 mel 不一致怎么办？\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport yaml\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeech\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeechInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args, speedyspeech_config):\n    rootdir = Path(args.rootdir).expanduser()\n    assert rootdir.is_dir()\n\n    # construct dataset for evaluation\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    phone_dict = {}\n    for phn, id in phn_id:\n        phone_dict[phn] = int(id)\n\n    with open(args.tones_dict, \"r\") as f:\n        tone_id = [line.strip().split() for line in f.readlines()]\n    tone_size = len(tone_id)\n    print(\"tone_size:\", tone_size)\n\n    frontend = Frontend(\n        phone_vocab_path=args.phones_dict, tone_vocab_path=args.tones_dict)\n\n    if args.speaker_dict:\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id_list = [line.strip().split() for line in f.readlines()]\n            spk_num = len(spk_id_list)\n    else:\n        spk_num = None\n\n    model = SpeedySpeech(\n        vocab_size=vocab_size,\n        tone_size=tone_size,\n        **speedyspeech_config[\"model\"],\n        spk_num=spk_num)\n\n    model.set_state_dict(\n        paddle.load(args.speedyspeech_checkpoint)[\"main_params\"])\n    model.eval()\n\n    stat = np.load(args.speedyspeech_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    speedyspeech_normalizer = ZScore(mu, std)\n\n    speedyspeech_inference = SpeedySpeechInference(speedyspeech_normalizer,\n                                                   model)\n    speedyspeech_inference.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences, speaker_set = get_phn_dur(args.dur_file)\n    merge_silence(sentences)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    train_wav_files = [\n        os.path.basename(str(str_path)) for str_path in train_wav_files\n    ]\n    dev_wav_files = [\n        os.path.basename(str(str_path)) for str_path in dev_wav_files\n    ]\n    test_wav_files = [\n        os.path.basename(str(str_path)) for str_path in test_wav_files\n    ]\n\n    for i, utt_id in enumerate(tqdm(sentences)):\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        # 裁剪掉开头和结尾的 sil\n        if args.cut_sil:\n            if phones[0] == \"sil\" and len(durations) > 1:\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                durations = durations[:-1]\n                phones = phones[:-1]\n\n        phones, tones = frontend._get_phone_tone(phones, get_tone_ids=True)\n        if tones:\n            tone_ids = frontend._t2id(tones)\n            tone_ids = paddle.to_tensor(tone_ids)\n        if phones:\n            phone_ids = frontend._p2id(phones)\n            phone_ids = paddle.to_tensor(phone_ids)\n\n        if args.speaker_dict:\n            speaker_id = int(\n                [item[1] for item in spk_id_list if speaker == item[0]][0])\n            speaker_id = paddle.to_tensor(speaker_id)\n        else:\n            speaker_id = None\n\n        durations = paddle.to_tensor(np.array(durations))\n        durations = paddle.unsqueeze(durations, axis=0)\n\n        # 生成的和真实的可能有 1, 2 帧的差距，但是 batch_fn 会修复\n        # split data into 3 sections\n\n        wav_path = utt_id + \".wav\"\n\n        if wav_path in train_wav_files:\n            sub_output_dir = output_dir / (\"train/raw\")\n        elif wav_path in dev_wav_files:\n            sub_output_dir = output_dir / (\"dev/raw\")\n        elif wav_path in test_wav_files:\n            sub_output_dir = output_dir / (\"test/raw\")\n\n        sub_output_dir.mkdir(parents=True, exist_ok=True)\n\n        with paddle.no_grad():\n            mel = speedyspeech_inference(\n                phone_ids, tone_ids, durations=durations, spk_id=speaker_id)\n        np.save(sub_output_dir / (utt_id + \"_feats.npy\"), mel)\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with speedyspeech & parallel wavegan.\")\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, ljspeech, vctk} now\")\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n    parser.add_argument(\n        \"--speedyspeech-config\", type=str, help=\"speedyspeech config file.\")\n    parser.add_argument(\n        \"--speedyspeech-checkpoint\",\n        type=str,\n        help=\"speedyspeech checkpoint to load.\")\n    parser.add_argument(\n        \"--speedyspeech-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training speedyspeech.\"\n    )\n\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones-dict\",\n        type=str,\n        default=\"tone_id_map.txt\",\n        help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.speedyspeech_config) as f:\n        speedyspeech_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(speedyspeech_config)\n\n    evaluate(args, speedyspeech_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/inference.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# remain for chains\nimport argparse\nfrom pathlib import Path\n\nimport soundfile as sf\nfrom paddle import inference\n\nimport paddlespeech.utils\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with speedyspeech & parallel wavegan.\")\n    parser.add_argument(\n        \"--inference-dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir\")\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phones.txt\",\n        help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones-dict\",\n        type=str,\n        default=\"tones.txt\",\n        help=\"tone vocabulary file.\")\n\n    args, _ = parser.parse_known_args()\n\n    frontend = Frontend(\n        phone_vocab_path=args.phones_dict, tone_vocab_path=args.tones_dict)\n    print(\"frontend done!\")\n\n    # after paddle 3.0, support new inference interface\n    if paddlespeech.utils.satisfy_paddle_version('3.0.0-beta'):\n        speedyspeech_config = inference.Config(\n            str(Path(args.inference_dir)), \"speedyspeech\")\n    else:\n        speedyspeech_config = inference.Config(\n            str(Path(args.inference_dir) / \"speedyspeech.pdmodel\"),\n            str(Path(args.inference_dir) / \"speedyspeech.pdiparams\"))\n\n    speedyspeech_config.enable_use_gpu(100, 0)\n    speedyspeech_config.enable_memory_optim()\n    speedyspeech_predictor = inference.create_predictor(speedyspeech_config)\n\n    # after paddle 3.0, support new inference interface\n    if paddlespeech.utils.satisfy_paddle_version('3.0.0-beta'):\n        pwg_config = inference.Config(str(Path(args.inference_dir)), \"pwg\")\n    else:\n        pwg_config = inference.Config(\n            str(Path(args.inference_dir) / \"pwg.pdmodel\"),\n            str(Path(args.inference_dir) / \"pwg.pdiparams\"))\n\n    pwg_config.enable_use_gpu(100, 0)\n    pwg_config.enable_memory_optim()\n    pwg_predictor = inference.create_predictor(pwg_config)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    sentences = []\n\n    with open(args.text, 'rt') as f:\n        for line in f:\n            items = line.strip().split()\n            utt_id = items[0]\n            sentence = \"\".join(items[1:])\n            sentences.append((utt_id, sentence))\n\n    for utt_id, sentence in sentences:\n        input_ids = frontend.get_input_ids(\n            sentence, merge_sentences=True, get_tone_ids=True)\n        phone_ids = input_ids[\"phone_ids\"]\n        tone_ids = input_ids[\"tone_ids\"]\n        phones = phone_ids[0].numpy()\n        tones = tone_ids[0].numpy()\n\n        input_names = speedyspeech_predictor.get_input_names()\n        phones_handle = speedyspeech_predictor.get_input_handle(input_names[0])\n        tones_handle = speedyspeech_predictor.get_input_handle(input_names[1])\n\n        phones_handle.reshape(phones.shape)\n        phones_handle.copy_from_cpu(phones)\n        tones_handle.reshape(tones.shape)\n        tones_handle.copy_from_cpu(tones)\n\n        speedyspeech_predictor.run()\n        output_names = speedyspeech_predictor.get_output_names()\n        output_handle = speedyspeech_predictor.get_output_handle(\n            output_names[0])\n        output_data = output_handle.copy_to_cpu()\n\n        input_names = pwg_predictor.get_input_names()\n        mel_handle = pwg_predictor.get_input_handle(input_names[0])\n        mel_handle.reshape(output_data.shape)\n        mel_handle.copy_from_cpu(output_data)\n\n        pwg_predictor.run()\n        output_names = pwg_predictor.get_output_names()\n        output_handle = pwg_predictor.get_output_handle(output_names[0])\n        wav = output_data = output_handle.copy_to_cpu()\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=24000)\n\n        print(f\"{utt_id} done!\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--stats\", type=str, required=True, help=\"statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones-dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    parser.add_argument(\n        \"--use-relative-path\",\n        type=str2bool,\n        default=False,\n        help=\"whether use relative path in metadata\")\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    if args.use_relative_path:\n        # if use_relative_path in preprocess, covert it to absolute path here\n        metadata_dir = Path(args.metadata).parent\n        for item in metadata:\n            item[\"feats\"] = str(metadata_dir / item[\"feats\"])\n\n    dataset = DataTable(\n        metadata, converters={\n            'feats': np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    scaler = StandardScaler()\n    scaler.mean_ = np.load(args.stats)[0]\n    scaler.scale_ = np.load(args.stats)[1]\n    # from version 0.23.0, this information is needed\n    scaler.n_features_in_ = scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_tones = {}\n    with open(args.tones_dict, 'rt') as f:\n        tone_id = [line.strip().split() for line in f.readlines()]\n    for tone, id in tone_id:\n        vocab_tones[tone] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        mel = item['feats']\n        # normalize\n        mel = scaler.transform(mel)\n\n        # save\n        mel_path = dumpdir / f\"{utt_id}_feats.npy\"\n        np.save(mel_path, mel.astype(np.float32), allow_pickle=False)\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        tone_ids = [vocab_tones[p] for p in item['tones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        if args.use_relative_path:\n            # convert absolute path to relative path:\n            mel_path = mel_path.relative_to(dumpdir)\n        output_metadata.append({\n            'utt_id': utt_id,\n            \"spk_id\": spk_id,\n            'phones': phone_ids,\n            'tones': tone_ids,\n            'num_phones': item['num_phones'],\n            'num_frames': item['num_frames'],\n            'durations': item['durations'],\n            'feats': str(mel_path),\n        })\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport re\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phones_tones\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     cut_sil: bool=True):\n    utt_id = fp.stem\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        labels = sentences[utt_id][0]\n        # extract phone and duration\n        phones = []\n        tones = []\n        for label in labels:\n            # split tone from finals\n            match = re.match(r'^(\\w+)([012345])$', label)\n            if match:\n                phones.append(match.group(1))\n                tones.append(match.group(2))\n            else:\n                phones.append(label)\n                tones.append('0')\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n        assert sum(durations) == num_frames\n        assert len(phones) == len(tones) == len(durations)\n\n        mel_path = output_dir / (utt_id + \"_feats.npy\")\n        np.save(mel_path, logmel)  # (num_frames, n_mels)\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"tones\": tones,\n            \"speaker\": speaker,\n            \"num_phones\": len(phones),\n            \"num_frames\": num_frames,\n            \"durations\": durations,\n            \"feats\": str(mel_path),  # Path object\n        }\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      use_relative_path: bool=False):\n\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                cut_sil=cut_sil)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         cut_sil)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    output_dir = Path(output_dir)\n    metadata_path = output_dir / \"metadata.jsonl\"\n    # NOTE: use relative path to the meta jsonlines file for Full Chain Project\n    with jsonlines.open(metadata_path, 'w') as writer:\n        for item in results:\n            if use_relative_path:\n                item[\"feats\"] = str(Path(item[\"feats\"]).relative_to(output_dir))\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n\n    parser.add_argument(\n        \"--dur-file\",\n        default=None,\n        type=str,\n        help=\"path to baker durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--use-relative-path\",\n        type=str2bool,\n        default=False,\n        help=\"whether use relative path in metadata\")\n\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    tone_id_map_path = dumpdir / \"tone_id_map.txt\"\n    get_phones_tones(sentences, phone_id_map_path, tone_id_map_path,\n                     args.dataset)\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            use_relative_path=args.use_relative_path)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            use_relative_path=args.use_relative_path)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            use_relative_path=args.use_relative_path)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/synthesize_e2e.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# remain for chains\nimport argparse\nimport logging\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom paddle import jit\nfrom paddle.static import InputSpec\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGInference\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeech\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeechInference\nfrom paddlespeech.t2s.modules.normalizer import ZScore\n\n\ndef evaluate(args, speedyspeech_config, pwg_config):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for evaluation\n    sentences = []\n    with open(args.text, 'rt', encoding='utf-8') as f:\n        for line in f:\n            items = line.strip().split()\n            utt_id = items[0]\n            sentence = \"\".join(items[1:])\n            sentences.append((utt_id, sentence))\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n    with open(args.tones_dict, 'rt', encoding='utf-8') as f:\n        tone_id = [line.strip().split() for line in f.readlines()]\n    tone_size = len(tone_id)\n    print(\"tone_size:\", tone_size)\n\n    model = SpeedySpeech(\n        vocab_size=vocab_size,\n        tone_size=tone_size,\n        **speedyspeech_config[\"model\"])\n    model.set_state_dict(\n        paddle.load(args.speedyspeech_checkpoint)[\"main_params\"])\n    model.eval()\n\n    vocoder = PWGGenerator(**pwg_config[\"generator_params\"])\n    vocoder.set_state_dict(paddle.load(args.pwg_checkpoint)[\"generator_params\"])\n    vocoder.remove_weight_norm()\n    vocoder.eval()\n    print(\"model done!\")\n\n    stat = np.load(args.speedyspeech_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    speedyspeech_normalizer = ZScore(mu, std)\n\n    stat = np.load(args.pwg_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    pwg_normalizer = ZScore(mu, std)\n\n    speedyspeech_inference = SpeedySpeechInference(speedyspeech_normalizer,\n                                                   model)\n    speedyspeech_inference.eval()\n    speedyspeech_inference = jit.to_static(\n        speedyspeech_inference,\n        input_spec=[\n            InputSpec([-1], dtype=paddle.int64), InputSpec(\n                [-1], dtype=paddle.int64)\n        ])\n    paddle.jit.save(speedyspeech_inference,\n                    os.path.join(args.inference_dir, \"speedyspeech\"))\n    speedyspeech_inference = paddle.jit.load(\n        os.path.join(args.inference_dir, \"speedyspeech\"))\n\n    pwg_inference = PWGInference(pwg_normalizer, vocoder)\n    pwg_inference.eval()\n    pwg_inference = jit.to_static(\n        pwg_inference, input_spec=[\n            InputSpec([-1, 80], dtype=paddle.float32),\n        ])\n    paddle.jit.save(pwg_inference, os.path.join(args.inference_dir, \"pwg\"))\n    pwg_inference = paddle.jit.load(os.path.join(args.inference_dir, \"pwg\"))\n\n    frontend = Frontend(\n        phone_vocab_path=args.phones_dict, tone_vocab_path=args.tones_dict)\n    print(\"frontend done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    for utt_id, sentence in sentences:\n        input_ids = frontend.get_input_ids(\n            sentence, merge_sentences=True, get_tone_ids=True)\n        phone_ids = input_ids[\"phone_ids\"]\n        tone_ids = input_ids[\"tone_ids\"]\n\n        flags = 0\n        for i in range(len(phone_ids)):\n            part_phone_ids = phone_ids[i]\n            part_tone_ids = tone_ids[i]\n            with paddle.no_grad():\n                mel = speedyspeech_inference(part_phone_ids, part_tone_ids)\n                temp_wav = pwg_inference(mel)\n            if flags == 0:\n                wav = temp_wav\n                flags = 1\n            else:\n                wav = paddle.concat([wav, temp_wav])\n        sf.write(\n            output_dir / (utt_id + \".wav\"),\n            wav.numpy(),\n            samplerate=speedyspeech_config.fs)\n        print(f\"{utt_id} done!\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with speedyspeech & parallel wavegan.\")\n    parser.add_argument(\n        \"--speedyspeech-config\", type=str, help=\"config file for speedyspeech.\")\n    parser.add_argument(\n        \"--speedyspeech-checkpoint\",\n        type=str,\n        help=\"speedyspeech checkpoint to load.\")\n    parser.add_argument(\n        \"--speedyspeech-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training speedyspeech.\"\n    )\n    parser.add_argument(\n        \"--pwg-config\", type=str, help=\"config file for parallelwavegan.\")\n    parser.add_argument(\n        \"--pwg-checkpoint\",\n        type=str,\n        help=\"parallel wavegan checkpoint to load.\")\n    parser.add_argument(\n        \"--pwg-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training speedyspeech.\"\n    )\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones-dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir\")\n    parser.add_argument(\n        \"--inference-dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu or xpu.\")\n    parser.add_argument(\n        \"--nxpu\",\n        type=int,\n        default=0,\n        help=\"if nxpu == 0 and ngpu == 0, use cpu.\")\n\n    args, _ = parser.parse_known_args()\n\n    if args.ngpu == 0:\n        if args.nxpu == 0:\n            paddle.set_device(\"cpu\")\n        else:\n            paddle.set_device(\"xpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.speedyspeech_config) as f:\n        speedyspeech_config = CfgNode(yaml.safe_load(f))\n    with open(args.pwg_config) as f:\n        pwg_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(speedyspeech_config)\n    print(pwg_config)\n\n    evaluate(args, speedyspeech_config, pwg_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/speedyspeech/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import speedyspeech_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import speedyspeech_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeech\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeechEvaluator\nfrom paddlespeech.t2s.models.speedyspeech import SpeedySpeechUpdater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if paddle.is_compiled_with_cuda() and args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n    elif paddle.is_compiled_with_xpu() and args.nxpu > 0:\n        paddle.device.set_device(\"xpu\")\n    elif args.nnpu > 0:\n        paddle.device.set_device(\"npu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n    elif args.nmlu > 0:\n        paddle.device.set_device(\"mlu\")\n    else:\n        paddle.set_device(\"cpu\")\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    fields = [\n        \"phones\", \"tones\", \"num_phones\", \"num_frames\", \"feats\", \"durations\"\n    ]\n\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker speedyspeech!\")\n        collate_fn = speedyspeech_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    else:\n        print(\"single speaker speedyspeech!\")\n        collate_fn = speedyspeech_single_spk_batch_fn\n    print(\"spk_num:\", spk_num)\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    if args.use_relative_path:\n        # if use_relative_path in preprocess, covert it to absolute path here\n        metadata_dir = Path(args.train_metadata).parent\n        for item in train_metadata:\n            item[\"feats\"] = str(metadata_dir / item[\"feats\"])\n\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters={\n            \"feats\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    if args.use_relative_path:\n        # if use_relative_path in preprocess, covert it to absolute path here\n        metadata_dir = Path(args.dev_metadata).parent\n        for item in dev_metadata:\n            item[\"feats\"] = str(metadata_dir / item[\"feats\"])\n\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters={\n            \"feats\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n    with open(args.tones_dict, 'rt', encoding='utf-8') as f:\n        tone_id = [line.strip().split() for line in f.readlines()]\n    tone_size = len(tone_id)\n    print(\"tone_size:\", tone_size)\n\n    model = SpeedySpeech(\n        vocab_size=vocab_size,\n        tone_size=tone_size,\n        spk_num=spk_num,\n        **config[\"model\"])\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n    optimizer = build_optimizers(model, **config[\"optimizer\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = SpeedySpeechUpdater(\n        model=model,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir)\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = SpeedySpeechEvaluator(\n        model, dev_dataloader, output_dir=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Train a Speedyspeech model with a single speaker dataset.\")\n    parser.add_argument(\"--config\", type=str, help=\"config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--nxpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use xpu, set ngpu == 0 and nxpu > 0, otherwise use gpu, npu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nnpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use npu, set ngpu == 0 and nnpu > 0, otherwise use gpu, xpu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nmlu\",\n        type=int,\n        default=1,\n        help=\"if wish to use npu, set ngpu == 0 and nmlu > 0, otherwise use gpu, xpu, npu or cpu.\"\n    )\n    parser.add_argument(\n        \"--ngpu\",\n        type=int,\n        default=1,\n        help=\"if wish to use gpu, set ngpu > 0, otherwise use xpu, npu or cpu.\")\n\n    parser.add_argument(\n        \"--use-relative-path\",\n        type=str2bool,\n        default=False,\n        help=\"whether use relative path in metadata\")\n\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n\n    parser.add_argument(\n        \"--tones-dict\", type=str, default=None, help=\"tone vocabulary file.\")\n\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n\n    # 这里可以多传入 max_epoch 等\n    args, rest = parser.parse_known_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    if rest:\n        extra = []\n        # to support key=value format\n        for item in rest:\n            # remove \"--\"\n            item = item[2:]\n            extra.extend(item.split(\"=\", maxsplit=1))\n        config.merge_from_list(extra)\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/starganv2_vc/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/starganv2_vc/normalize.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata, converters={\n            \"speech\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm.tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n\n        # normalize\n        # 这里暂时写死\n        mean, std = -4, 4\n        speech = (speech - mean) / std\n        speech_path = dumpdir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"speech\": str(speech_path),\n        }\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/starganv2_vc/preprocess.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\n\nspeaker_set = set()\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     output_dir: Path,\n                     mel_extractor=None):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n        speaker = utt_id.split('_')[0]\n        speaker_set.add(speaker)\n    # 需要额外获取 speaker\n    record = None\n    # reading, resampling may occur\n    # 源码的 bug, 读取的时候按照 24000 读取，但是提取 mel 的时候按照 16000 提取\n    # 具体参考 https://github.com/PaddlePaddle/PaddleSpeech/blob/c7d24ba42c377fe4c0765c6b1faa202a9aeb136f/paddlespeech/t2s/exps/starganv2_vc/vc.py#L165\n    # 之后需要换成按照 24000 读取和按照 24000 提取 mel\n    wav, _ = librosa.load(str(fp), sr=24000)\n    max_value = np.abs(wav).max()\n    if max_value > 1.0:\n        wav = wav / max_value\n    assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n    assert np.abs(\n        wav).max() <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n    # extract mel feats\n    # 注意这里 base = 'e', 后续需要换成 base='10', 我们其他 TTS 模型都是 base='10'\n    logmel = mel_extractor.get_log_mel_fbank(wav, base='e')\n    mel_path = output_dir / (utt_id + \"_speech.npy\")\n    np.save(mel_path, logmel)\n    record = {\"utt_id\": utt_id, \"speech\": str(mel_path), \"speaker\": speaker}\n    return record\n\n\ndef process_sentences(\n        config,\n        fps: List[Path],\n        output_dir: Path,\n        mel_extractor=None,\n        nprocs: int=1, ):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         output_dir, mel_extractor)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'w') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"vctk\",\n        type=str,\n        help=\"name of dataset, should in {vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"StarGANv2VC config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    assert rootdir.is_dir()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    if args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        # only for test\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax,\n        # None here\n        norm=config.norm,\n        htk=config.htk,\n        power=config.power)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/starganv2_vc/train.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import AdamW\nfrom paddle.optimizer.lr import OneCycleLR\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.utils import download_and_decompress\nfrom paddlespeech.resource.pretrained_models import StarGANv2VC_source\nfrom paddlespeech.t2s.datasets.am_batch_fn import build_starganv2_vc_collate_fn\nfrom paddlespeech.t2s.datasets.data_table import StarGANv2VCDataTable\nfrom paddlespeech.t2s.models.starganv2_vc import ASRCNN\nfrom paddlespeech.t2s.models.starganv2_vc import Discriminator\nfrom paddlespeech.t2s.models.starganv2_vc import Generator\nfrom paddlespeech.t2s.models.starganv2_vc import JDCNet\nfrom paddlespeech.t2s.models.starganv2_vc import MappingNetwork\nfrom paddlespeech.t2s.models.starganv2_vc import StarGANv2VCEvaluator\nfrom paddlespeech.t2s.models.starganv2_vc import StarGANv2VCUpdater\nfrom paddlespeech.t2s.models.starganv2_vc import StyleEncoder\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.utils.env import MODEL_HOME\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n    # to edit\n    fields = [\"speech\", \"speech_lengths\"]\n    converters = {\"speech\": np.load}\n\n    collate_fn = build_starganv2_vc_collate_fn(\n        latent_dim=config['mapping_network_params']['latent_dim'],\n        max_mel_length=config['max_mel_length'])\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = StarGANv2VCDataTable(data=train_metadata)\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = StarGANv2VCDataTable(data=dev_metadata)\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    print(\"dataloaders done!\")\n\n    # load model\n    model_version = '1.0'\n    uncompress_path = download_and_decompress(StarGANv2VC_source[model_version],\n                                              MODEL_HOME)\n    # 根据 speaker 的个数修改 num_domains\n    # 源码的预训练模型和 default.yaml 里面默认是 20\n    if args.speaker_dict is not None:\n        with open(args.speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        print(\"spk_num:\", spk_num)\n        config['mapping_network_params']['num_domains'] = spk_num\n        config['style_encoder_params']['num_domains'] = spk_num\n        config['discriminator_params']['num_domains'] = spk_num\n\n    generator = Generator(**config['generator_params'])\n    mapping_network = MappingNetwork(**config['mapping_network_params'])\n    style_encoder = StyleEncoder(**config['style_encoder_params'])\n    discriminator = Discriminator(**config['discriminator_params'])\n\n    # load pretrained model\n    jdc_model_dir = os.path.join(uncompress_path, 'jdcnet.pdz')\n    asr_model_dir = os.path.join(uncompress_path, 'asr.pdz')\n\n    F0_model = JDCNet(num_class=1, seq_len=config['max_mel_length'])\n    F0_model.set_state_dict(paddle.load(jdc_model_dir)['main_params'])\n    F0_model.eval()\n\n    asr_model = ASRCNN(**config['asr_params'])\n    asr_model.set_state_dict(paddle.load(asr_model_dir)['main_params'])\n    asr_model.eval()\n\n    if world_size > 1:\n        generator = DataParallel(generator)\n        discriminator = DataParallel(discriminator)\n    print(\"models done!\")\n\n    lr_schedule_g = OneCycleLR(**config[\"generator_scheduler_params\"])\n    optimizer_g = AdamW(\n        learning_rate=lr_schedule_g,\n        parameters=generator.parameters(),\n        **config[\"generator_optimizer_params\"])\n\n    lr_schedule_s = OneCycleLR(**config[\"style_encoder_scheduler_params\"])\n    optimizer_s = AdamW(\n        learning_rate=lr_schedule_s,\n        parameters=style_encoder.parameters(),\n        **config[\"style_encoder_optimizer_params\"])\n\n    lr_schedule_m = OneCycleLR(**config[\"mapping_network_scheduler_params\"])\n    optimizer_m = AdamW(\n        learning_rate=lr_schedule_m,\n        parameters=mapping_network.parameters(),\n        **config[\"mapping_network_optimizer_params\"])\n\n    lr_schedule_d = OneCycleLR(**config[\"discriminator_scheduler_params\"])\n    optimizer_d = AdamW(\n        learning_rate=lr_schedule_d,\n        parameters=discriminator.parameters(),\n        **config[\"discriminator_optimizer_params\"])\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = StarGANv2VCUpdater(\n        models={\n            \"generator\": generator,\n            \"style_encoder\": style_encoder,\n            \"mapping_network\": mapping_network,\n            \"discriminator\": discriminator,\n            \"F0_model\": F0_model,\n            \"asr_model\": asr_model,\n        },\n        optimizers={\n            \"generator\": optimizer_g,\n            \"style_encoder\": optimizer_s,\n            \"mapping_network\": optimizer_m,\n            \"discriminator\": optimizer_d,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"style_encoder\": lr_schedule_s,\n            \"mapping_network\": lr_schedule_m,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        g_loss_params=config.loss_params.g_loss,\n        d_loss_params=config.loss_params.d_loss,\n        adv_cls_epoch=config.loss_params.adv_cls_epoch,\n        con_reg_epoch=config.loss_params.con_reg_epoch,\n        output_dir=output_dir)\n\n    evaluator = StarGANv2VCEvaluator(\n        models={\n            \"generator\": generator,\n            \"style_encoder\": style_encoder,\n            \"mapping_network\": mapping_network,\n            \"discriminator\": discriminator,\n            \"F0_model\": F0_model,\n            \"asr_model\": asr_model,\n        },\n        dataloader=dev_dataloader,\n        g_loss_params=config.loss_params.g_loss,\n        d_loss_params=config.loss_params.d_loss,\n        adv_cls_epoch=config.loss_params.adv_cls_epoch,\n        con_reg_epoch=config.loss_params.con_reg_epoch,\n        output_dir=output_dir)\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    print(\"Trainer Done!\")\n\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a HiFiGAN model.\")\n    parser.add_argument(\"--config\", type=str, help=\"HiFiGAN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/starganv2_vc/vc.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport time\nfrom pathlib import Path\n\nimport librosa\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.utils import download_and_decompress\nfrom paddlespeech.resource.pretrained_models import StarGANv2VC_source\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.models.parallel_wavegan import PWGGenerator\nfrom paddlespeech.t2s.models.starganv2_vc import Generator\nfrom paddlespeech.t2s.models.starganv2_vc import JDCNet\nfrom paddlespeech.t2s.models.starganv2_vc import MappingNetwork\nfrom paddlespeech.t2s.models.starganv2_vc import StyleEncoder\nfrom paddlespeech.utils.env import MODEL_HOME\n\n\ndef get_mel_extractor():\n    sr = 16000\n    n_fft = 2048\n    win_length = 1200\n    hop_length = 300\n    n_mels = 80\n    fmin = 0\n    fmax = sr // 2\n\n    mel_extractor = LogMelFBank(\n        sr=sr,\n        n_fft=n_fft,\n        hop_length=hop_length,\n        win_length=win_length,\n        n_mels=n_mels,\n        fmin=fmin,\n        fmax=fmax,\n        norm=None,\n        htk=True,\n        power=2.0)\n    return mel_extractor\n\n\ndef preprocess(wave, mel_extractor):\n    # (T, 80)\n    logmel = mel_extractor.get_log_mel_fbank(wave, base='e')\n    mean, std = -4, 4\n    # [1, 80, T]\n    mel_tensor = (paddle.to_tensor(logmel.T).unsqueeze(0) - mean) / std\n    return mel_tensor\n\n\ndef compute_style(speaker_dicts, mel_extractor, style_encoder, mapping_network):\n    reference_embeddings = {}\n    for key, (path, speaker) in speaker_dicts.items():\n        # path = ''\n        if path == '':\n            label = paddle.to_tensor([speaker], dtype=paddle.int64)\n            latent_dim = mapping_network.shared[0].weight.shape[0]\n            ref = mapping_network(paddle.randn([1, latent_dim]), label)\n        else:\n            wave, sr = librosa.load(path, sr=24000)\n            audio, index = librosa.effects.trim(wave, top_db=30)\n            if sr != 24000:\n                wave = librosa.resample(wave, sr, 24000)\n            mel_tensor = preprocess(wave=wave, mel_extractor=mel_extractor)\n            with paddle.no_grad():\n                label = paddle.to_tensor([speaker], dtype=paddle.int64)\n                ref = style_encoder(mel_tensor.unsqueeze(1), label)\n        reference_embeddings[key] = (ref, label)\n\n    return reference_embeddings\n\n\ndef get_models(args, uncompress_path):\n    model_dict = {}\n    jdc_model_dir = os.path.join(uncompress_path, 'jdcnet.pdz')\n    voc_model_dir = os.path.join(uncompress_path, 'Vocoder/')\n    starganv2vc_model_dir = os.path.join(uncompress_path, 'starganv2vc.pdz')\n\n    F0_model = JDCNet(num_class=1, seq_len=192)\n    F0_model.set_state_dict(paddle.load(jdc_model_dir)['main_params'])\n    F0_model.eval()\n\n    voc_config_path = os.path.join(voc_model_dir, 'config.yml')\n    with open(voc_config_path) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n    voc_config[\"generator_params\"].pop(\"upsample_net\")\n    voc_config[\"generator_params\"][\"upsample_scales\"] = voc_config[\n        \"generator_params\"].pop(\"upsample_params\")[\"upsample_scales\"]\n    vocoder = PWGGenerator(**voc_config[\"generator_params\"])\n    vocoder.remove_weight_norm()\n    vocoder.eval()\n    voc_model_path = os.path.join(voc_model_dir, 'checkpoint-400000steps.pd')\n    vocoder.set_state_dict(paddle.load(voc_model_path))\n\n    with open(args.config_path) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    generator = Generator(**config['generator_params'])\n    mapping_network = MappingNetwork(**config['mapping_network_params'])\n    style_encoder = StyleEncoder(**config['style_encoder_params'])\n\n    starganv2vc_model_param = paddle.load(starganv2vc_model_dir)\n\n    generator.set_state_dict(starganv2vc_model_param['generator_params'])\n    mapping_network.set_state_dict(\n        starganv2vc_model_param['mapping_network_params'])\n    style_encoder.set_state_dict(\n        starganv2vc_model_param['style_encoder_params'])\n\n    generator.eval()\n    mapping_network.eval()\n    style_encoder.eval()\n\n    model_dict['F0_model'] = F0_model\n    model_dict['vocoder'] = vocoder\n    model_dict['generator'] = generator\n    model_dict['mapping_network'] = mapping_network\n    model_dict['style_encoder'] = style_encoder\n    return model_dict\n\n\ndef voice_conversion(args, uncompress_path):\n    speakers = [\n        225, 228, 229, 230, 231, 233, 236, 239, 240, 244, 226, 227, 232, 243,\n        254, 256, 258, 259, 270, 273\n    ]\n    demo_dir = os.path.join(uncompress_path, 'Demo/VCTK-corpus/')\n    model_dict = get_models(args, uncompress_path=uncompress_path)\n    style_encoder = model_dict['style_encoder']\n    mapping_network = model_dict['mapping_network']\n    generator = model_dict['generator']\n    vocoder = model_dict['vocoder']\n    F0_model = model_dict['F0_model']\n\n    # 计算 Demo 文件夹下的说话人的风格\n    speaker_dicts = {}\n    selected_speakers = [273, 259, 258, 243, 254, 244, 236, 233, 230, 228]\n    for s in selected_speakers:\n        k = s\n        speaker_dicts['p' + str(s)] = (\n            demo_dir + 'p' + str(k) + '/p' + str(k) + '_023.wav',\n            speakers.index(s))\n    mel_extractor = get_mel_extractor()\n    reference_embeddings = compute_style(\n        speaker_dicts=speaker_dicts,\n        mel_extractor=mel_extractor,\n        style_encoder=style_encoder,\n        mapping_network=mapping_network)\n\n    wave, sr = librosa.load(args.source_path, sr=24000)\n    source = preprocess(wave=wave, mel_extractor=mel_extractor)\n    # # 测试 preprocess.py 的输出是否 ok\n    # # 直接用 raw 然后 norm 的在这里 ok\n    # # 直接用 norm 在这里 ok\n    # import numpy as np\n    # source = np.load(\"~/PaddleSpeech_stargan_preprocess/PaddleSpeech/examples/vctk/vc3/dump/train/norm/p329_414_speech.npy\")\n    # # ！！！对 mel_extractor norm 后的操作\n    # # [1, 80, T]\n    # source = paddle.to_tensor(source.T).unsqueeze(0)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    orig_wav_name = str(output_dir / 'orig_voc.wav')\n    print('原始语音 (使用声码器解码): %s' % orig_wav_name)\n    c = source.transpose([0, 2, 1]).squeeze()\n    with paddle.no_grad():\n        recon = vocoder.inference(c)\n        recon = recon.reshape([-1]).numpy()\n    sf.write(orig_wav_name, recon, samplerate=24000)\n\n    keys = []\n    converted_samples = {}\n    reconstructed_samples = {}\n    converted_mels = {}\n    start = time.time()\n\n    for key, (ref, _) in reference_embeddings.items():\n        with paddle.no_grad():\n            # F0_model 输入的特征是否可以不带 norm，或者 norm 是否一定要和 stargan 原作保持一致？\n            # !! 需要，ASR 和 F0_model 用的是一样的数据预处理方式\n            # 如果不想要重新训练 ASR 和 F0_model, 则我们的数据预处理需要和 stargan 原作保持一致\n            # 但是 vocoder 就无法复用\n            # 是否因为 asr 的输入是 16k 的，所以 torchaudio 的参数也是 16k 的？\n            f0_feat = F0_model.get_feature_GAN(source.unsqueeze(1))\n            # 输出是带 norm 的 mel, 所以可以直接用 vocoder.inference\n            out = generator(source.unsqueeze(1), ref, F0=f0_feat)\n            c = out.transpose([0, 1, 3, 2]).squeeze()\n            y_out = vocoder.inference(c)\n            y_out = y_out.reshape([-1])\n            if key not in speaker_dicts or speaker_dicts[key][0] == \"\":\n                recon = None\n            else:\n                wave, sr = librosa.load(speaker_dicts[key][0], sr=24000)\n                mel = preprocess(wave=wave, mel_extractor=mel_extractor)\n                c = mel.transpose([0, 2, 1]).squeeze()\n                recon = vocoder.inference(c)\n                recon = recon.reshape([-1]).numpy()\n\n        converted_samples[key] = y_out.numpy()\n        reconstructed_samples[key] = recon\n        converted_mels[key] = out\n        keys.append(key)\n    end = time.time()\n    print('总共花费时间: %.3f sec' % (end - start))\n    for key, wave in converted_samples.items():\n        wav_name = str(output_dir / ('vc_result_' + key + '.wav'))\n        print('语音转换结果: %s' % wav_name)\n        sf.write(wav_name, wave, samplerate=24000)\n        ref_wav_name = str(output_dir / ('ref_voc_' + key + '.wav'))\n        print('参考的说话人 (使用声码器解码): %s' % ref_wav_name)\n        if reconstructed_samples[key] is not None:\n            sf.write(ref_wav_name, reconstructed_samples[key], samplerate=24000)\n\n\ndef parse_args():\n    # parse args and config  \n    parser = argparse.ArgumentParser(\n        description=\"StarGANv2-VC Voice Conversion.\")\n    parser.add_argument(\"--source_path\", type=str, help=\"source audio's path.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        '--config_path',\n        type=str,\n        default=None,\n        help='Config of StarGANv2-VC model.')\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n    model_version = '1.0'\n    uncompress_path = download_and_decompress(StarGANv2VC_source[model_version],\n                                              MODEL_HOME)\n    voice_conversion(args, uncompress_path=uncompress_path)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/stream_play_tts.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# stream play TTS\n# Before first execution, download and decompress the models in the execution directory\n# wget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\n# wget https://paddlespeech.cdn.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_onnx_0.2.0.zip\n# unzip fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip\n# unzip mb_melgan_csmsc_onnx_0.2.0.zip\nimport math\nimport time\n\nimport numpy as np\nimport onnxruntime as ort\nimport pyaudio\nimport soundfile as sf\n\nfrom paddlespeech.server.utils.audio_process import float2pcm\nfrom paddlespeech.server.utils.util import denorm\nfrom paddlespeech.server.utils.util import get_chunks\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\n\nvoc_block = 36\nvoc_pad = 14\nam_block = 72\nam_pad = 12\nvoc_upsample = 300\n\nphones_dict = \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/phone_id_map.txt\"\nfrontend = Frontend(phone_vocab_path=phones_dict, tone_vocab_path=None)\n\nam_stat_path = \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/speech_stats.npy\"\nam_mu, am_std = np.load(am_stat_path)\n\n# 模型路径\nonnx_am_encoder = \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_encoder_infer.onnx\"\nonnx_am_decoder = \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_decoder.onnx\"\nonnx_am_postnet = \"fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/fastspeech2_csmsc_am_postnet.onnx\"\nonnx_voc_melgan = \"mb_melgan_csmsc_onnx_0.2.0/mb_melgan_csmsc.onnx\"\n\n# 用CPU推理\nproviders = ['CPUExecutionProvider']\n\n# 配置ort session\nsess_options = ort.SessionOptions()\n\n# 创建session\nam_encoder_infer_sess = ort.InferenceSession(\n    onnx_am_encoder, providers=providers, sess_options=sess_options)\nam_decoder_sess = ort.InferenceSession(\n    onnx_am_decoder, providers=providers, sess_options=sess_options)\nam_postnet_sess = ort.InferenceSession(\n    onnx_am_postnet, providers=providers, sess_options=sess_options)\nvoc_melgan_sess = ort.InferenceSession(\n    onnx_voc_melgan, providers=providers, sess_options=sess_options)\n\n\ndef depadding(data, chunk_num, chunk_id, block, pad, upsample):\n    \"\"\" \n    Streaming inference removes the result of pad inference\n    \"\"\"\n    front_pad = min(chunk_id * block, pad)\n    # first chunk\n    if chunk_id == 0:\n        data = data[:block * upsample]\n    # last chunk\n    elif chunk_id == chunk_num - 1:\n        data = data[front_pad * upsample:]\n    # middle chunk\n    else:\n        data = data[front_pad * upsample:(front_pad + block) * upsample]\n\n    return data\n\n\ndef inference_stream(text):\n    input_ids = frontend.get_input_ids(\n        text, merge_sentences=False, get_tone_ids=False)\n    phone_ids = input_ids[\"phone_ids\"]\n    for i in range(len(phone_ids)):\n        part_phone_ids = phone_ids[i].numpy()\n        voc_chunk_id = 0\n\n        orig_hs = am_encoder_infer_sess.run(\n            None, input_feed={'text': part_phone_ids})\n        orig_hs = orig_hs[0]\n\n        # streaming voc chunk info\n        mel_len = orig_hs.shape[1]\n        voc_chunk_num = math.ceil(mel_len / voc_block)\n        start = 0\n        end = min(voc_block + voc_pad, mel_len)\n\n        # streaming am\n        hss = get_chunks(orig_hs, am_block, am_pad, \"am\")\n        am_chunk_num = len(hss)\n        for i, hs in enumerate(hss):\n            am_decoder_output = am_decoder_sess.run(None, input_feed={'xs': hs})\n            am_postnet_output = am_postnet_sess.run(\n                None,\n                input_feed={\n                    'xs': np.transpose(am_decoder_output[0], (0, 2, 1))\n                })\n            am_output_data = am_decoder_output + np.transpose(\n                am_postnet_output[0], (0, 2, 1))\n            normalized_mel = am_output_data[0][0]\n\n            sub_mel = denorm(normalized_mel, am_mu, am_std)\n            sub_mel = depadding(sub_mel, am_chunk_num, i, am_block, am_pad, 1)\n\n            if i == 0:\n                mel_streaming = sub_mel\n            else:\n                mel_streaming = np.concatenate((mel_streaming, sub_mel), axis=0)\n\n            # streaming voc\n            # 当流式AM推理的mel帧数大于流式voc推理的chunk size，开始进行流式voc 推理\n            while (mel_streaming.shape[0] >= end and\n                   voc_chunk_id < voc_chunk_num):\n                voc_chunk = mel_streaming[start:end, :]\n\n                sub_wav = voc_melgan_sess.run(\n                    output_names=None, input_feed={'logmel': voc_chunk})\n                sub_wav = depadding(sub_wav[0], voc_chunk_num, voc_chunk_id,\n                                    voc_block, voc_pad, voc_upsample)\n\n                yield sub_wav\n\n                voc_chunk_id += 1\n                start = max(0, voc_chunk_id * voc_block - voc_pad)\n                end = min((voc_chunk_id + 1) * voc_block + voc_pad, mel_len)\n\n\nif __name__ == '__main__':\n\n    text = \"欢迎使用飞桨语音合成系统，测试一下合成效果。\"\n    # warm up\n    # onnxruntime 第一次时间会长一些，建议先 warmup 一下\n    for sub_wav in inference_stream(text=\"哈哈哈哈\"):\n        continue\n\n    # pyaudio 播放\n    p = pyaudio.PyAudio()\n    stream = p.open(\n        format=p.get_format_from_width(2),  # int16\n        channels=1,\n        rate=24000,\n        output=True)\n\n    # 计时\n    wavs = []\n    t1 = time.time()\n    for sub_wav in inference_stream(text):\n        print(\"响应时间：\", time.time() - t1)\n        t1 = time.time()\n        wavs.append(sub_wav.flatten())\n        # float32 to int16\n        wav = float2pcm(sub_wav)\n        # to bytes  \n        wav_bytes = wav.tobytes()\n        stream.write(wav_bytes)\n\n    # 关闭 pyaudio 播放器\n    stream.stop_stream()\n    stream.close()\n    p.terminate()\n\n    # 流式合成的结果导出\n    wav = np.concatenate(wavs)\n    print(wav.shape)\n    sf.write(\"demo_stream.wav\", data=wav, samplerate=24000)\n"
  },
  {
    "path": "paddlespeech/t2s/exps/syn_utils.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport os\nimport re\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nimport jsonlines\nimport numpy as np\nimport onnxruntime as ort\nimport paddle\nfrom paddle import inference\nfrom paddle import jit\nfrom paddle.io import DataLoader\nfrom paddle.static import InputSpec\nfrom yacs.config import CfgNode\n\nimport paddlespeech.utils\nfrom paddlespeech.t2s.datasets.am_batch_fn import *\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import Clip_static\nfrom paddlespeech.t2s.frontend.canton_frontend import CantonFrontend\nfrom paddlespeech.t2s.frontend.en_frontend import English\nfrom paddlespeech.t2s.frontend.mix_frontend import MixFrontend\nfrom paddlespeech.t2s.frontend.sing_frontend import SingFrontend\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.utils.dynamic_import import dynamic_import\n\n# remove [W:onnxruntime: xxx] from ort\nort.set_default_logger_severity(3)\n\nmodel_alias = {\n    # acoustic model\n    \"speedyspeech\":\n    \"paddlespeech.t2s.models.speedyspeech:SpeedySpeech\",\n    \"speedyspeech_inference\":\n    \"paddlespeech.t2s.models.speedyspeech:SpeedySpeechInference\",\n    \"fastspeech2\":\n    \"paddlespeech.t2s.models.fastspeech2:FastSpeech2\",\n    \"fastspeech2_inference\":\n    \"paddlespeech.t2s.models.fastspeech2:FastSpeech2Inference\",\n    \"tacotron2\":\n    \"paddlespeech.t2s.models.tacotron2:Tacotron2\",\n    \"tacotron2_inference\":\n    \"paddlespeech.t2s.models.tacotron2:Tacotron2Inference\",\n    \"diffsinger\":\n    \"paddlespeech.t2s.models.diffsinger:DiffSinger\",\n    \"diffsinger_inference\":\n    \"paddlespeech.t2s.models.diffsinger:DiffSingerInference\",\n\n    # voc\n    \"pwgan\":\n    \"paddlespeech.t2s.models.parallel_wavegan:PWGGenerator\",\n    \"pwgan_inference\":\n    \"paddlespeech.t2s.models.parallel_wavegan:PWGInference\",\n    \"mb_melgan\":\n    \"paddlespeech.t2s.models.melgan:MelGANGenerator\",\n    \"mb_melgan_inference\":\n    \"paddlespeech.t2s.models.melgan:MelGANInference\",\n    \"style_melgan\":\n    \"paddlespeech.t2s.models.melgan:StyleMelGANGenerator\",\n    \"style_melgan_inference\":\n    \"paddlespeech.t2s.models.melgan:StyleMelGANInference\",\n    \"hifigan\":\n    \"paddlespeech.t2s.models.hifigan:HiFiGANGenerator\",\n    \"hifigan_inference\":\n    \"paddlespeech.t2s.models.hifigan:HiFiGANInference\",\n    \"wavernn\":\n    \"paddlespeech.t2s.models.wavernn:WaveRNN\",\n    \"wavernn_inference\":\n    \"paddlespeech.t2s.models.wavernn:WaveRNNInference\",\n    \"erniesat\":\n    \"paddlespeech.t2s.models.ernie_sat:ErnieSAT\",\n    \"erniesat_inference\":\n    \"paddlespeech.t2s.models.ernie_sat:ErnieSATInference\",\n}\n\n\ndef denorm(data, mean, std):\n    return data * std + mean\n\n\ndef norm(data, mean, std):\n    return (data - mean) / std\n\n\ndef get_chunks(mel, chunk_size: int, pad_size: int):\n    \"\"\"\n    Split mel by chunk size with left and right context.\n\n    Args:\n        mel (paddle.Tensor): mel spectrogram, shape (B, T, D)\n        chunk_size (int): chunk size\n        pad_size (int): size for left and right context.\n    \"\"\"\n    T = mel.shape[1]\n    n = math.ceil(T / chunk_size)\n\n    chunks = []\n    for i in range(n):\n        start = max(0, i * chunk_size - pad_size)\n        end = min((i + 1) * chunk_size + pad_size, T)\n        chunks.append(mel[:, start:end, :])\n    return chunks\n\n\n# input\ndef get_sentences(text_file: Optional[os.PathLike], lang: str='zh'):\n    # construct dataset for evaluation\n    sentences = []\n    with open(text_file, 'rt', encoding='utf-8') as f:\n        for line in f:\n            if line.strip() != \"\":\n                items = re.split(r\"\\s+\", line.strip(), maxsplit=1)\n                assert len(items) == 2\n                utt_id = items[0]\n                sentence = items[1]\n            sentences.append((utt_id, sentence))\n    return sentences\n\n\n# input for svs\ndef get_sentences_svs(text_file: Optional[os.PathLike]):\n    # construct dataset for evaluation\n    sentences = []\n    with jsonlines.open(text_file, 'r') as reader:\n        svs_inputs = list(reader)\n    for svs_input in svs_inputs:\n        utt_id = svs_input['utt_id']\n        sentence = svs_input\n        sentences.append((utt_id, sentence))\n    return sentences\n\n\n# am only\ndef get_test_dataset(test_metadata: List[Dict[str, Any]],\n                     am: str,\n                     speaker_dict: Optional[os.PathLike]=None,\n                     voice_cloning: bool=False):\n    # model: {model_name}_{dataset}\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    converters = {}\n    if am_name == 'fastspeech2':\n        fields = [\"utt_id\", \"text\"]\n        if am_dataset in {\"aishell3\", \"vctk\", \"mix\",\n                          \"canton\"} and speaker_dict is not None:\n            print(\"multiple speaker fastspeech2!\")\n            fields += [\"spk_id\"]\n        elif voice_cloning:\n            print(\"voice cloning!\")\n            fields += [\"spk_emb\"]\n        else:\n            print(\"single speaker fastspeech2!\")\n    elif am_name == 'diffsinger':\n        fields = [\"utt_id\", \"text\", \"note\", \"note_dur\", \"is_slur\"]\n    elif am_name == 'speedyspeech':\n        fields = [\"utt_id\", \"phones\", \"tones\"]\n    elif am_name == 'tacotron2':\n        fields = [\"utt_id\", \"text\"]\n        if voice_cloning:\n            print(\"voice cloning!\")\n            fields += [\"spk_emb\"]\n    elif am_name == 'erniesat':\n        fields = [\n            \"utt_id\", \"text\", \"text_lengths\", \"speech\", \"speech_lengths\",\n            \"align_start\", \"align_end\"\n        ]\n        converters = {\"speech\": np.load}\n    else:\n        print(\"wrong am, please input right am!!!\")\n\n    test_dataset = DataTable(\n        data=test_metadata, fields=fields, converters=converters)\n    return test_dataset\n\n\n# am and voc, for PTQ_static\ndef get_dev_dataloader(dev_metadata: List[Dict[str, Any]],\n                       am: str,\n                       batch_size: int=1,\n                       speaker_dict: Optional[os.PathLike]=None,\n                       voice_cloning: bool=False,\n                       n_shift: int=300,\n                       batch_max_steps: int=16200,\n                       shuffle: bool=True):\n    # model: {model_name}_{dataset}\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    converters = {}\n    if am_name == 'fastspeech2':\n        fields = [\"utt_id\", \"text\"]\n        if am_dataset in {\"aishell3\", \"vctk\", \"mix\",\n                          \"canton\"} and speaker_dict is not None:\n            print(\"multiple speaker fastspeech2!\")\n            collate_fn = fastspeech2_multi_spk_batch_fn_static\n            fields += [\"spk_id\"]\n        elif voice_cloning:\n            print(\"voice cloning!\")\n            collate_fn = fastspeech2_multi_spk_batch_fn_static\n            fields += [\"spk_emb\"]\n        else:\n            print(\"single speaker fastspeech2!\")\n            collate_fn = fastspeech2_single_spk_batch_fn_static\n    elif am_name == 'speedyspeech':\n        fields = [\"utt_id\", \"phones\", \"tones\"]\n        if am_dataset in {\"aishell3\", \"vctk\",\n                          \"mix\"} and speaker_dict is not None:\n            print(\"multiple speaker speedyspeech!\")\n            collate_fn = speedyspeech_multi_spk_batch_fn_static\n            fields += [\"spk_id\"]\n        else:\n            print(\"single speaker speedyspeech!\")\n            collate_fn = speedyspeech_single_spk_batch_fn_static\n        fields = [\"utt_id\", \"phones\", \"tones\"]\n    elif am_name == 'tacotron2':\n        fields = [\"utt_id\", \"text\"]\n        if voice_cloning:\n            print(\"voice cloning!\")\n            collate_fn = tacotron2_multi_spk_batch_fn_static\n            fields += [\"spk_emb\"]\n        else:\n            print(\"single speaker tacotron2!\")\n            collate_fn = tacotron2_single_spk_batch_fn_static\n    else:\n        print(\"voc dataloader\")\n\n    # am\n    if am_name not in {'pwgan', 'mb_melgan', 'hifigan'}:\n        dev_dataset = DataTable(\n            data=dev_metadata,\n            fields=fields,\n            converters=converters, )\n\n        dev_dataloader = DataLoader(\n            dev_dataset,\n            shuffle=shuffle,\n            drop_last=False,\n            batch_size=batch_size,\n            collate_fn=collate_fn)\n    # vocoder\n    else:\n        # pwgan: batch_max_steps: 25500 aux_context_window: 2\n        # mb_melgan: batch_max_steps: 16200 aux_context_window 0\n        # hifigan: batch_max_steps: 8400 aux_context_window 0\n        aux_context_window = 0\n        if am_name == 'pwgan':\n            aux_context_window = 2\n\n        train_batch_fn = Clip_static(\n            batch_max_steps=batch_max_steps,\n            hop_size=n_shift,\n            aux_context_window=aux_context_window)\n        dev_dataset = DataTable(\n            data=dev_metadata,\n            fields=[\"wave\", \"feats\"],\n            converters={\n                \"wave\": np.load,\n                \"feats\": np.load,\n            }, )\n\n        dev_dataloader = DataLoader(\n            dev_dataset,\n            shuffle=shuffle,\n            drop_last=False,\n            batch_size=batch_size,\n            collate_fn=train_batch_fn)\n\n    return dev_dataloader\n\n\n# frontend\ndef get_frontend(lang: str='zh',\n                 phones_dict: Optional[os.PathLike]=None,\n                 tones_dict: Optional[os.PathLike]=None,\n                 pinyin_phone: Optional[os.PathLike]=None,\n                 use_rhy=False):\n    if lang == 'zh':\n        frontend = Frontend(\n            phone_vocab_path=phones_dict,\n            tone_vocab_path=tones_dict,\n            use_rhy=use_rhy)\n    elif lang == 'canton':\n        frontend = CantonFrontend(phone_vocab_path=phones_dict)\n    elif lang == 'en':\n        frontend = English(phone_vocab_path=phones_dict)\n    elif lang == 'mix':\n        frontend = MixFrontend(\n            phone_vocab_path=phones_dict, tone_vocab_path=tones_dict)\n    elif lang == 'sing':\n        frontend = SingFrontend(\n            pinyin_phone_path=pinyin_phone, phone_vocab_path=phones_dict)\n    else:\n        print(\"wrong lang!\")\n    return frontend\n\n\ndef run_frontend(\n        frontend: object,\n        text: str,\n        merge_sentences: bool=False,\n        get_tone_ids: bool=False,\n        lang: str='zh',\n        to_tensor: bool=True,\n        add_blank: bool=False,\n        svs_input: Dict[str, str]=None, ):\n    outs = dict()\n    if lang == 'zh':\n        input_ids = {}\n        if text.strip() != \"\" and re.match(r\".*?<speak>.*?</speak>.*\", text,\n                                           re.DOTALL):\n            # using ssml\n            input_ids = frontend.get_input_ids_ssml(\n                text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                to_tensor=to_tensor)\n        else:\n            input_ids = frontend.get_input_ids(\n                text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                to_tensor=to_tensor,\n                add_blank=add_blank)\n        phone_ids = input_ids[\"phone_ids\"]\n        if get_tone_ids:\n            tone_ids = input_ids[\"tone_ids\"]\n            outs.update({'tone_ids': tone_ids})\n    elif lang == 'canton':\n        input_ids = frontend.get_input_ids(\n            text, merge_sentences=merge_sentences, to_tensor=to_tensor)\n        phone_ids = input_ids[\"phone_ids\"]\n    elif lang == 'en':\n        input_ids = frontend.get_input_ids(\n            text, merge_sentences=merge_sentences, to_tensor=to_tensor)\n        phone_ids = input_ids[\"phone_ids\"]\n    elif lang == 'mix':\n        input_ids = frontend.get_input_ids(\n            text, merge_sentences=merge_sentences, to_tensor=to_tensor)\n        phone_ids = input_ids[\"phone_ids\"]\n    elif lang == 'sing':\n        input_ids = frontend.get_input_ids(\n            svs_input=svs_input, to_tensor=to_tensor)\n        phone_ids = input_ids[\"phone_ids\"]\n        note_ids = input_ids[\"note_ids\"]\n        note_durs = input_ids[\"note_durs\"]\n        is_slurs = input_ids[\"is_slurs\"]\n        outs.update({'note_ids': note_ids})\n        outs.update({'note_durs': note_durs})\n        outs.update({'is_slurs': is_slurs})\n    else:\n        print(\"lang should in {'zh', 'en', 'mix', 'canton', 'sing'}!\")\n\n    outs.update({'phone_ids': phone_ids})\n    return outs\n\n\n# dygraph\ndef get_am_inference(\n        am: str='fastspeech2_csmsc',\n        am_config: CfgNode=None,\n        am_ckpt: Optional[os.PathLike]=None,\n        am_stat: Optional[os.PathLike]=None,\n        phones_dict: Optional[os.PathLike]=None,\n        tones_dict: Optional[os.PathLike]=None,\n        speaker_dict: Optional[os.PathLike]=None,\n        return_am: bool=False,\n        speech_stretchs: Optional[os.PathLike]=None, ):\n    with open(phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    tone_size = None\n    if tones_dict is not None:\n        with open(tones_dict, 'rt', encoding='utf-8') as f:\n            tone_id = [line.strip().split() for line in f.readlines()]\n        tone_size = len(tone_id)\n    spk_num = None\n    if speaker_dict is not None:\n        with open(speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n    odim = am_config.n_mels\n    # model: {model_name}_{dataset}\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    am_class = dynamic_import(am_name, model_alias)\n    am_inference_class = dynamic_import(am_name + '_inference', model_alias)\n    if am_name == 'fastspeech2':\n        am = am_class(\n            idim=vocab_size, odim=odim, spk_num=spk_num, **am_config[\"model\"])\n    elif am_name == 'diffsinger':\n        with open(speech_stretchs, \"r\") as f:\n            spec_min = np.load(speech_stretchs)[0]\n            spec_max = np.load(speech_stretchs)[1]\n            spec_min = paddle.to_tensor(spec_min)\n            spec_max = paddle.to_tensor(spec_max)\n        am_config[\"model\"][\"fastspeech2_params\"][\"spk_num\"] = spk_num\n        am = am_class(\n            spec_min=spec_min,\n            spec_max=spec_max,\n            idim=vocab_size,\n            odim=odim,\n            **am_config[\"model\"], )\n    elif am_name == 'speedyspeech':\n        am = am_class(\n            vocab_size=vocab_size,\n            tone_size=tone_size,\n            spk_num=spk_num,\n            **am_config[\"model\"])\n    elif am_name == 'tacotron2':\n        am = am_class(idim=vocab_size, odim=odim, **am_config[\"model\"])\n    elif am_name == 'erniesat':\n        am = am_class(idim=vocab_size, odim=odim, **am_config[\"model\"])\n\n    am.set_state_dict(paddle.load(am_ckpt)[\"main_params\"])\n    am.eval()\n    am_mu, am_std = np.load(am_stat)\n    am_mu = paddle.to_tensor(am_mu)\n    am_std = paddle.to_tensor(am_std)\n    am_normalizer = ZScore(am_mu, am_std)\n    am_inference = am_inference_class(am_normalizer, am)\n    am_inference.eval()\n    if return_am:\n        return am_inference, am\n    else:\n        return am_inference\n\n\ndef get_voc_inference(\n        voc: str='pwgan_csmsc',\n        voc_config: Optional[os.PathLike]=None,\n        voc_ckpt: Optional[os.PathLike]=None,\n        voc_stat: Optional[os.PathLike]=None, ):\n    # model: {model_name}_{dataset}\n    voc_name = voc[:voc.rindex('_')]\n    voc_class = dynamic_import(voc_name, model_alias)\n    voc_inference_class = dynamic_import(voc_name + '_inference', model_alias)\n\n    # npu only support mode=constant right now\n    # this code has been adapted to support 'paddlespeech.t2s.models.melgan.melgan.MelGANGenerator'\n    npu_pad_mode = {\n        \"mode\": \"constant\"\n    } if paddle.get_device().startswith('npu') else {}\n\n    if voc_name != 'wavernn':\n        if npu_pad_mode:\n            voc_config[\"generator_params\"].setdefault(\"pad_params\", {})\n            voc_config[\"generator_params\"][\"pad_params\"].update(npu_pad_mode)\n\n        voc = voc_class(**voc_config[\"generator_params\"])\n        voc.set_state_dict(paddle.load(voc_ckpt)[\"generator_params\"])\n        voc.remove_weight_norm()\n        voc.eval()\n    else:\n        if npu_pad_mode:\n            voc_config[\"model\"].setdefault(\"pad_params\", {})\n            voc_config[\"model\"][\"pad_params\"].update(npu_pad_mode)\n\n        voc = voc_class(**voc_config[\"model\"])\n        voc.set_state_dict(paddle.load(voc_ckpt)[\"main_params\"])\n        voc.eval()\n\n    voc_mu, voc_std = np.load(voc_stat)\n    voc_mu = paddle.to_tensor(voc_mu)\n    voc_std = paddle.to_tensor(voc_std)\n    voc_normalizer = ZScore(voc_mu, voc_std)\n    voc_inference = voc_inference_class(voc_normalizer, voc)\n    voc_inference.eval()\n    return voc_inference\n\n\n# dygraph to static graph\ndef am_to_static(am_inference,\n                 am: str='fastspeech2_csmsc',\n                 inference_dir=Optional[os.PathLike],\n                 speaker_dict: Optional[os.PathLike]=None):\n    # model: {model_name}_{dataset}\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    if am_name == 'fastspeech2':\n        if am_dataset in {\"aishell3\", \"vctk\", \"mix\",\n                          \"canton\"} and speaker_dict is not None:\n            am_inference = jit.to_static(\n                am_inference,\n                input_spec=[\n                    InputSpec([-1], dtype=paddle.int64),\n                    InputSpec([1], dtype=paddle.int64),\n                ], )\n        else:\n            am_inference = jit.to_static(\n                am_inference, input_spec=[InputSpec([-1], dtype=paddle.int64)])\n\n    elif am_name == 'speedyspeech':\n        if am_dataset in {\"aishell3\", \"vctk\", \"mix\",\n                          \"canton\"} and speaker_dict is not None:\n            am_inference = jit.to_static(\n                am_inference,\n                input_spec=[\n                    InputSpec([-1], dtype=paddle.int64),  # text\n                    InputSpec([-1], dtype=paddle.int64),  # tone\n                    InputSpec([1], dtype=paddle.int64),  # spk_id\n                    None  # duration\n                ])\n        else:\n            am_inference = jit.to_static(\n                am_inference,\n                input_spec=[\n                    InputSpec([-1], dtype=paddle.int64),\n                    InputSpec([-1], dtype=paddle.int64)\n                ])\n\n    elif am_name == 'tacotron2':\n        am_inference = jit.to_static(\n            am_inference, input_spec=[InputSpec([-1], dtype=paddle.int64)])\n\n    elif am_name == 'vits' or am_name == 'jets':\n        if am_dataset in {\"aishell3\", \"vctk\"} and speaker_dict is not None:\n            am_inference = jit.to_static(\n                am_inference,\n                input_spec=[\n                    InputSpec([-1], dtype=paddle.int64),\n                    InputSpec([1], dtype=paddle.int64),\n                ])\n        else:\n            am_inference = jit.to_static(\n                am_inference, input_spec=[InputSpec([-1], dtype=paddle.int64)])\n\n    elif am_name == 'diffsinger':\n        am_inference = jit.to_static(\n            am_inference,\n            input_spec=[\n                InputSpec([-1], dtype=paddle.int64),  # phone\n                InputSpec([-1], dtype=paddle.int64),  # note\n                InputSpec([-1], dtype=paddle.float32),  # note_dur\n                InputSpec([-1], dtype=paddle.int64),  # is_slur\n            ])\n\n    jit.save(am_inference, os.path.join(inference_dir, am))\n    am_inference = jit.load(os.path.join(inference_dir, am))\n\n    return am_inference\n\n\ndef voc_to_static(voc_inference,\n                  voc: str='pwgan_csmsc',\n                  inference_dir=Optional[os.PathLike]):\n    voc_inference = jit.to_static(\n        voc_inference, input_spec=[\n            InputSpec([-1, 80], dtype=paddle.float32),\n        ])\n    jit.save(voc_inference, os.path.join(inference_dir, voc))\n    voc_inference = jit.load(os.path.join(inference_dir, voc))\n    return voc_inference\n\n\n# inference\ndef get_predictor(\n        model_dir: Optional[os.PathLike]=None,\n        model_file: Optional[os.PathLike]=None,\n        params_file: Optional[os.PathLike]=None,\n        device: str='cpu',\n        # for gpu\n        use_trt: bool=False,\n        device_id: int=0,\n        # for trt\n        use_dynamic_shape: bool=True,\n        min_subgraph_size: int=5,\n        # for cpu\n        cpu_threads: int=1,\n        use_mkldnn: bool=False,\n        # for trt or mkldnn\n        precision: int=\"fp32\"):\n    \"\"\"\n    Args:\n        model_dir (os.PathLike): root path of model.pdmodel and model.pdiparams.\n        model_file (os.PathLike): name of model_file.\n        params_file (os.PathLike): name of params_file.\n        device (str): Choose the device you want to run, it can be: cpu/gpu, default is cpu.\n        use_trt (bool): whether to use TensorRT or not in GPU.\n        device_id (int): Choose your device id, only valid when the device is gpu, default 0.\n        use_dynamic_shape (bool): use dynamic shape or not in TensorRT.\n        use_mkldnn (bool): whether to use MKLDNN or not in CPU.\n        cpu_threads (int): num of thread when use CPU.\n        precision (str): mode of running (fp32/fp16/bf16/int8).  \n    \"\"\"\n    rerun_flag = False\n    if device != \"gpu\" and use_trt:\n        raise ValueError(\n            \"Predict by TensorRT mode: {}, expect device=='gpu', but device == {}\".\n            format(precision, device))\n\n    # after paddle 3.0, support new inference interface\n    if paddlespeech.utils.satisfy_paddle_version('3.0.0-beta'):\n        model_name = str(model_file).rsplit('.', 1)[0]\n        assert model_name == str(params_file).rstrip(\n            '.pdiparams'\n        ), \"The prefix of model_file and params_file should be same.\"\n        config = inference.Config(model_dir, model_name)\n    else:\n        config = inference.Config(\n            str(Path(model_dir) / model_file),\n            str(Path(model_dir) / params_file))\n    if paddle.__version__ <= \"2.5.2\" and paddle.__version__ != \"0.0.0\":\n        config.enable_memory_optim()\n    config.switch_ir_optim(True)\n    if device == \"gpu\":\n        config.enable_use_gpu(100, device_id)\n    else:\n        config.disable_gpu()\n        config.set_cpu_math_library_num_threads(cpu_threads)\n        if use_mkldnn:\n            # fp32\n            config.enable_mkldnn()\n            if precision == \"int8\":\n                config.enable_mkldnn_int8({\n                    \"conv2d_transpose\", \"conv2d\", \"depthwise_conv2d\", \"pool2d\",\n                    \"transpose2\", \"elementwise_mul\"\n                })\n                # config.enable_mkldnn_int8()\n            elif precision in {\"fp16\", \"bf16\"}:\n                config.enable_mkldnn_bfloat16()\n            print(\"MKLDNN with {}\".format(precision))\n    if use_trt:\n        if precision == \"bf16\":\n            print(\"paddle trt does not support bf16, switching to fp16.\")\n            precision = \"fp16\"\n        precision_map = {\n            \"int8\": inference.Config.Precision.Int8,\n            \"fp32\": inference.Config.Precision.Float32,\n            \"fp16\": inference.Config.Precision.Half,\n        }\n        assert precision in precision_map.keys()\n        pdtxt_name = model_file.split(\".\")[0] + \"_\" + precision + \".txt\"\n        if use_dynamic_shape:\n            dynamic_shape_file = os.path.join(model_dir, pdtxt_name)\n            if os.path.exists(dynamic_shape_file):\n                config.enable_tuned_tensorrt_dynamic_shape(dynamic_shape_file,\n                                                           True)\n                # for fastspeech2\n                config.exp_disable_tensorrt_ops([\"reshape2\"])\n                print(\"trt set dynamic shape done!\")\n            else:\n                # In order to avoid memory overflow when collecting dynamic shapes, it is changed to use CPU.\n                config.disable_gpu()\n                config.set_cpu_math_library_num_threads(10)\n                config.collect_shape_range_info(dynamic_shape_file)\n                print(\"Start collect dynamic shape...\")\n                rerun_flag = True\n\n        if not rerun_flag:\n            print(\"Tensor RT with {}\".format(precision))\n            config.enable_tensorrt_engine(\n                workspace_size=1 << 30,\n                max_batch_size=1,\n                min_subgraph_size=min_subgraph_size,\n                precision_mode=precision_map[precision],\n                use_static=True,\n                use_calib_mode=False, )\n\n    predictor = inference.create_predictor(config)\n    return predictor\n\n\ndef get_am_output(input: str,\n                  am_predictor: paddle.nn.Layer,\n                  am: str,\n                  frontend: object,\n                  lang: str='zh',\n                  merge_sentences: bool=True,\n                  speaker_dict: Optional[os.PathLike]=None,\n                  spk_id: int=0,\n                  add_blank: bool=False):\n    am_name = am[:am.rindex('_')]\n    am_dataset = am[am.rindex('_') + 1:]\n    am_input_names = am_predictor.get_input_names()\n    get_spk_id = False\n    get_tone_ids = False\n    if am_name == 'speedyspeech':\n        get_tone_ids = True\n    if am_dataset in {\"aishell3\", \"vctk\", \"mix\", \"canton\"} and speaker_dict:\n        get_spk_id = True\n        spk_id = np.array([spk_id])\n\n    frontend_dict = run_frontend(\n        frontend=frontend,\n        text=input,\n        merge_sentences=merge_sentences,\n        get_tone_ids=get_tone_ids,\n        lang=lang,\n        add_blank=add_blank, )\n\n    if get_tone_ids:\n        tone_ids = frontend_dict['tone_ids']\n        tones = tone_ids[0].numpy()\n        tones_handle = am_predictor.get_input_handle(am_input_names[1])\n        tones_handle.reshape(tones.shape)\n        tones_handle.copy_from_cpu(tones)\n    if get_spk_id:\n        spk_id_handle = am_predictor.get_input_handle(am_input_names[1])\n        spk_id_handle.reshape(spk_id.shape)\n        spk_id_handle.copy_from_cpu(spk_id)\n    phone_ids = frontend_dict['phone_ids']\n    phones = phone_ids[0].numpy()\n    phones_handle = am_predictor.get_input_handle(am_input_names[0])\n    phones_handle.reshape(phones.shape)\n    phones_handle.copy_from_cpu(phones)\n\n    am_predictor.run()\n    am_output_names = am_predictor.get_output_names()\n    am_output_handle = am_predictor.get_output_handle(am_output_names[0])\n    am_output_data = am_output_handle.copy_to_cpu()\n    return am_output_data\n\n\ndef get_voc_output(voc_predictor, input):\n    voc_input_names = voc_predictor.get_input_names()\n    mel_handle = voc_predictor.get_input_handle(voc_input_names[0])\n    mel_handle.reshape(input.shape)\n    mel_handle.copy_from_cpu(input)\n\n    voc_predictor.run()\n    voc_output_names = voc_predictor.get_output_names()\n    voc_output_handle = voc_predictor.get_output_handle(voc_output_names[0])\n    wav = voc_output_handle.copy_to_cpu()\n    return wav\n\n\ndef get_am_sublayer_output(am_sublayer_predictor, input):\n    am_sublayer_input_names = am_sublayer_predictor.get_input_names()\n    input_handle = am_sublayer_predictor.get_input_handle(\n        am_sublayer_input_names[0])\n    input_handle.reshape(input.shape)\n    input_handle.copy_from_cpu(input)\n\n    am_sublayer_predictor.run()\n    am_sublayer_names = am_sublayer_predictor.get_output_names()\n    am_sublayer_handle = am_sublayer_predictor.get_output_handle(\n        am_sublayer_names[0])\n    am_sublayer_output = am_sublayer_handle.copy_to_cpu()\n    return am_sublayer_output\n\n\ndef get_streaming_am_output(input: str,\n                            am_encoder_infer_predictor,\n                            am_decoder_predictor,\n                            am_postnet_predictor,\n                            frontend,\n                            lang: str='zh',\n                            merge_sentences: bool=True):\n    get_tone_ids = False\n    frontend_dict = run_frontend(\n        frontend=frontend,\n        text=input,\n        merge_sentences=merge_sentences,\n        get_tone_ids=get_tone_ids,\n        lang=lang)\n    phone_ids = frontend_dict['phone_ids']\n    phones = phone_ids[0].numpy()\n    am_encoder_infer_output = get_am_sublayer_output(\n        am_encoder_infer_predictor, input=phones)\n\n    am_decoder_output = get_am_sublayer_output(\n        am_decoder_predictor, input=am_encoder_infer_output)\n\n    am_postnet_output = get_am_sublayer_output(\n        am_postnet_predictor, input=np.transpose(am_decoder_output, (0, 2, 1)))\n    am_output_data = am_decoder_output + np.transpose(am_postnet_output,\n                                                      (0, 2, 1))\n    normalized_mel = am_output_data[0]\n    return normalized_mel\n\n\n# onnx\ndef get_sess(model_path: Optional[os.PathLike],\n             device: str='cpu',\n             cpu_threads: int=1,\n             use_trt: bool=False):\n    sess_options = ort.SessionOptions()\n    sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL\n    sess_options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n    if 'gpu' in device.lower():\n        device_id = int(device.split(':')[1]) if len(\n            device.split(':')) == 2 else 0\n        # fastspeech2/mb_melgan can't use trt now!\n        if use_trt:\n            provider_name = 'TensorrtExecutionProvider'\n        else:\n            provider_name = 'CUDAExecutionProvider'\n        providers = [(provider_name, {'device_id': device_id})]\n    elif device.lower() == 'cpu':\n        providers = ['CPUExecutionProvider']\n    sess_options.intra_op_num_threads = cpu_threads\n    sess = ort.InferenceSession(\n        model_path, providers=providers, sess_options=sess_options)\n    return sess\n"
  },
  {
    "path": "paddlespeech/t2s/exps/synthesize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_test_dataset\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n\n    # Init body.\n    with open(args.am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(am_config)\n    print(voc_config)\n\n    # acoustic model\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    am_inference = get_am_inference(\n        am=args.am,\n        am_config=am_config,\n        am_ckpt=args.am_ckpt,\n        am_stat=args.am_stat,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict,\n        speaker_dict=args.speaker_dict,\n        speech_stretchs=args.speech_stretchs, )\n    test_dataset = get_test_dataset(\n        test_metadata=test_metadata,\n        am=args.am,\n        speaker_dict=args.speaker_dict,\n        voice_cloning=args.voice_cloning)\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    N = 0\n    T = 0\n\n    for datum in test_dataset:\n        utt_id = datum[\"utt_id\"]\n        with timer() as t:\n            with paddle.no_grad():\n                # acoustic model\n                if am_name == 'fastspeech2':\n                    phone_ids = paddle.to_tensor(datum[\"text\"])\n                    spk_emb = None\n                    spk_id = None\n                    # multi speaker\n                    if args.voice_cloning and \"spk_emb\" in datum:\n                        spk_emb = paddle.to_tensor(np.load(datum[\"spk_emb\"]))\n                    elif \"spk_id\" in datum:\n                        spk_id = paddle.to_tensor(datum[\"spk_id\"])\n                    mel = am_inference(\n                        phone_ids, spk_id=spk_id, spk_emb=spk_emb)\n                elif am_name == 'speedyspeech':\n                    phone_ids = paddle.to_tensor(datum[\"phones\"])\n                    tone_ids = paddle.to_tensor(datum[\"tones\"])\n                    mel = am_inference(phone_ids, tone_ids)\n                elif am_name == 'tacotron2':\n                    phone_ids = paddle.to_tensor(datum[\"text\"])\n                    spk_emb = None\n                    # multi speaker\n                    if args.voice_cloning and \"spk_emb\" in datum:\n                        spk_emb = paddle.to_tensor(np.load(datum[\"spk_emb\"]))\n                    mel = am_inference(phone_ids, spk_emb=spk_emb)\n                elif am_name == 'diffsinger':\n                    phone_ids = paddle.to_tensor(datum[\"text\"])\n                    note = paddle.to_tensor(datum[\"note\"])\n                    note_dur = paddle.to_tensor(datum[\"note_dur\"])\n                    is_slur = paddle.to_tensor(datum[\"is_slur\"])\n                    # get_mel_fs2 = False, means mel from diffusion, get_mel_fs2 = True, means mel from fastspeech2.\n                    get_mel_fs2 = False\n                    # mel: [T, mel_bin]\n                    mel = am_inference(\n                        phone_ids,\n                        note=note,\n                        note_dur=note_dur,\n                        is_slur=is_slur,\n                        get_mel_fs2=get_mel_fs2)\n                # vocoder\n                wav = voc_inference(mel)\n\n            wav = wav.numpy()\n            N += wav.size\n            T += t.elapse\n            speed = wav.size / t.elapse\n            rtf = am_config.fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.size}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")), wav, samplerate=am_config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {am_config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'fastspeech2_csmsc',\n            'fastspeech2_ljspeech',\n            'fastspeech2_aishell3',\n            'fastspeech2_vctk',\n            'tacotron2_csmsc',\n            'tacotron2_ljspeech',\n            'tacotron2_aishell3',\n            'fastspeech2_mix',\n            'fastspeech2_canton',\n            'diffsinger_opencpop',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        '--am_config', type=str, default=None, help='Config of acoustic model.')\n    parser.add_argument(\n        '--am_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_ljspeech',\n            'pwgan_aishell3',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'wavernn_csmsc',\n            'hifigan_csmsc',\n            'hifigan_ljspeech',\n            'hifigan_aishell3',\n            'hifigan_vctk',\n            'style_melgan_csmsc',\n            \"pwgan_opencpop\",\n            \"hifigan_opencpop\",\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        \"--ngpu\",\n        type=int,\n        default=1,\n        help=\"if wish to use gpu, set ngpu > 0, otherwise use xpu, npu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nxpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use xpu, set ngpu == 0 and nxpu > 0, otherwise use gpu, npu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nnpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use npu, set ngpu == 0 and nnpu > 0, otherwise use gpu, xpu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nmlu\",\n        type=int,\n        default=0,\n        help=\"if wish to use xpu, set ngpu == 0 and nmlu > 0, otherwise use gpu, xpu, npu or cpu.\"\n    )\n    parser.add_argument(\"--test_metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--speech_stretchs\",\n        type=str,\n        default=None,\n        help=\"The min and max values of the mel spectrum.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n\n    args = parse_args()\n    if args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    elif args.nxpu > 0:\n        paddle.set_device(\"xpu\")\n    elif args.nnpu > 0:\n        paddle.set_device(\"npu\")\n    elif args.nmlu > 0:\n        paddle.set_device(\"mlu\")\n    elif args.ngpu == 0 and args.nxpu == 0 and args.nnpu == 0 and args.nmlu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        print(\n            \"one of ngpu, nxpu, nnpu or nmlu should be greater than 0 or all of them equal to 0\"\n        )\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/synthesize_e2e.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\nfrom pprint import pprint\n\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import am_to_static\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences_svs\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.exps.syn_utils import voc_to_static\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n\n    # Init body.\n    with open(args.am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(am_config)\n    print(voc_config)\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict,\n        pinyin_phone=args.pinyin_phone,\n        use_rhy=args.use_rhy)\n    print(\"frontend done!\")\n\n    # acoustic model\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n    am_inference = get_am_inference(\n        am=args.am,\n        am_config=am_config,\n        am_ckpt=args.am_ckpt,\n        am_stat=args.am_stat,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict,\n        speaker_dict=args.speaker_dict,\n        speech_stretchs=args.speech_stretchs, )\n    print(\"acoustic model done!\")\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n    print(\"voc done!\")\n\n    # whether dygraph to static\n    if args.inference_dir:\n        print(\"convert am and voc to static model.\")\n        # acoustic model\n        am_inference = am_to_static(\n            am_inference=am_inference,\n            am=args.am,\n            inference_dir=args.inference_dir,\n            speaker_dict=args.speaker_dict)\n        # vocoder\n        voc_inference = voc_to_static(\n            voc_inference=voc_inference,\n            voc=args.voc,\n            inference_dir=args.inference_dir)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    merge_sentences = False\n    # Avoid not stopping at the end of a sub sentence when tacotron2_ljspeech dygraph to static graph\n    # but still not stopping in the end (NOTE by yuantian01 Feb 9 2022)\n    if am_name == 'tacotron2':\n        merge_sentences = True\n\n    get_tone_ids = False\n    if am_name == 'speedyspeech':\n        get_tone_ids = True\n\n    # wav samples\n    N = 0\n    # inference time cost\n    T = 0\n\n    # [(uid, text), ]\n    if am_name == 'diffsinger':\n        sentences = get_sentences_svs(text_file=args.text)\n    else:\n        sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    for utt_id, sentence in sentences:\n        print(f\"{utt_id} {sentence}\")\n        with timer() as t:\n            if am_name == \"diffsinger\":\n                text = \"\"\n                svs_input = sentence\n            else:\n                text = sentence\n                svs_input = None\n\n            # frontend\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=text,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang,\n                svs_input=svs_input)\n            phone_ids = frontend_dict['phone_ids']\n            # pprint(f\"{utt_id} {phone_ids}\")\n\n            with paddle.no_grad():\n                flags = 0\n                for i in range(len(phone_ids)):\n                    # sub phone, split by `sp` or punctuation.\n                    part_phone_ids = phone_ids[i]\n\n                    # acoustic model\n                    if am_name == 'fastspeech2':\n                        # multi speaker\n                        if am_dataset in {\"aishell3\", \"vctk\", \"mix\", \"canton\"}:\n                            # multi-speaker\n                            spk_id = paddle.to_tensor([args.spk_id])\n                            mel = am_inference(part_phone_ids, spk_id)\n                        else:\n                            # single-speaker\n                            mel = am_inference(part_phone_ids)\n                    elif am_name == 'speedyspeech':\n                        part_tone_ids = frontend_dict['tone_ids'][i]\n                        if am_dataset in {\"aishell3\", \"vctk\", \"mix\"}:\n                            # multi-speaker\n                            spk_id = paddle.to_tensor([args.spk_id])\n                            mel = am_inference(part_phone_ids, part_tone_ids,\n                                               spk_id)\n                        else:\n                            # single-speaker\n                            mel = am_inference(part_phone_ids, part_tone_ids)\n                    elif am_name == 'tacotron2':\n                        mel = am_inference(part_phone_ids)\n                    elif am_name == 'diffsinger':\n                        part_note_ids = frontend_dict['note_ids'][i]\n                        part_note_durs = frontend_dict['note_durs'][i]\n                        part_is_slurs = frontend_dict['is_slurs'][i]\n                        mel = am_inference(\n                            text=part_phone_ids,\n                            note=part_note_ids,\n                            note_dur=part_note_durs,\n                            is_slur=part_is_slurs, )\n\n                    # vocoder\n                    wav = voc_inference(mel)\n                    if flags == 0:\n                        wav_all = wav\n                        flags = 1\n                    else:\n                        wav_all = paddle.concat([wav_all, wav])\n\n        wav = wav_all.numpy()\n        N += wav.size\n        T += t.elapse\n\n        # samples per second\n        speed = wav.size / t.elapse\n        # generate one second wav need `RTF` seconds\n        rtf = am_config.fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")), wav, samplerate=am_config.fs)\n        print(f\"{utt_id} done!\")\n\n    print(f\"generation speed: {N / T}Hz, RTF: {am_config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=[\n            'speedyspeech_csmsc',\n            'speedyspeech_aishell3',\n            'fastspeech2_csmsc',\n            'fastspeech2_ljspeech',\n            'fastspeech2_aishell3',\n            'fastspeech2_vctk',\n            'tacotron2_csmsc',\n            'tacotron2_ljspeech',\n            'fastspeech2_mix',\n            'fastspeech2_canton',\n            'fastspeech2_male-zh',\n            'fastspeech2_male-en',\n            'fastspeech2_male-mix',\n            'diffsinger_opencpop',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        '--am_config', type=str, default=None, help='Config of acoustic model.')\n    parser.add_argument(\n        '--am_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'pwgan_ljspeech',\n            'pwgan_aishell3',\n            'pwgan_vctk',\n            'mb_melgan_csmsc',\n            'style_melgan_csmsc',\n            'hifigan_csmsc',\n            'hifigan_ljspeech',\n            'hifigan_aishell3',\n            'hifigan_vctk',\n            'wavernn_csmsc',\n            'pwgan_male',\n            'hifigan_male',\n            'pwgan_opencpop',\n            'hifigan_opencpop',\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        choices=['zh', 'en', 'mix', 'canton', 'sing'],\n        help='Choose model language. zh or en or mix')\n\n    parser.add_argument(\n        \"--inference_dir\",\n        type=str,\n        default=None,\n        help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--ngpu\",\n        type=int,\n        default=1,\n        help=\"if wish to use gpu, set ngpu > 0, otherwise use xpu, npu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nxpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use xpu, set ngpu == 0 and nxpu > 0, otherwise use gpu, npu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nnpu\",\n        type=int,\n        default=0,\n        help=\"if wish to use npu, set ngpu == 0 and nnpu > 0, otherwise use gpu, xpu, mlu or cpu.\"\n    )\n    parser.add_argument(\n        \"--nmlu\",\n        type=int,\n        default=0,\n        help=\"if wish to use xpu, set ngpu == 0 and nmlu > 0, otherwise use gpu, xpu, npu or cpu.\"\n    )\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--use_rhy\",\n        type=str2bool,\n        default=False,\n        help=\"run rhythm frontend or not\")\n    parser.add_argument(\n        \"--pinyin_phone\",\n        type=str,\n        default=None,\n        help=\"pinyin to phone map file, using on sing_frontend.\")\n    parser.add_argument(\n        \"--speech_stretchs\",\n        type=str,\n        default=None,\n        help=\"The min and max values of the mel spectrum, using on diffusion of diffsinger.\"\n    )\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    elif args.nxpu > 0:\n        paddle.set_device(\"xpu\")\n    elif args.nnpu > 0:\n        paddle.set_device(\"npu\")\n    elif args.nmlu > 0:\n        paddle.set_device(\"mlu\")\n    elif args.ngpu == 0 and args.nxpu == 0 and args.nnpu == 0 and args.nmlu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        print(\n            \"one of ngpu, nxpu, nnpu or nmlu should be greater than 0 or all of them equal to 0\"\n        )\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/synthesize_streaming.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom paddle import jit\nfrom paddle.static import InputSpec\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import denorm\nfrom paddlespeech.t2s.exps.syn_utils import get_chunks\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.exps.syn_utils import model_alias\nfrom paddlespeech.t2s.exps.syn_utils import run_frontend\nfrom paddlespeech.t2s.exps.syn_utils import voc_to_static\nfrom paddlespeech.t2s.utils import str2bool\nfrom paddlespeech.utils.dynamic_import import dynamic_import\n\n\ndef evaluate(args):\n\n    # Init body.\n    with open(args.am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(am_config)\n    print(voc_config)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict,\n        tones_dict=args.tones_dict)\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    # acoustic model, only support fastspeech2 here now!\n    # model: {model_name}_{dataset}\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n    odim = am_config.n_mels\n\n    am_class = dynamic_import(am_name, model_alias)\n    am = am_class(idim=vocab_size, odim=odim, **am_config[\"model\"])\n    am.set_state_dict(paddle.load(args.am_ckpt)[\"main_params\"])\n    am.eval()\n    am_mu, am_std = np.load(args.am_stat)\n    am_mu = paddle.to_tensor(am_mu)\n    am_std = paddle.to_tensor(am_std)\n\n    # am sub layers\n    am_encoder_infer = am.encoder_infer\n    am_decoder = am.decoder\n    am_postnet = am.postnet\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    # whether dygraph to static\n    if args.inference_dir:\n        # fastspeech2 cnndecoder to static\n        # am.encoder_infer\n        am_encoder_infer = jit.to_static(\n            am_encoder_infer, input_spec=[InputSpec([-1], dtype=paddle.int64)])\n        paddle.jit.save(am_encoder_infer,\n                        os.path.join(args.inference_dir,\n                                     args.am + \"_am_encoder_infer\"))\n        am_encoder_infer = paddle.jit.load(\n            os.path.join(args.inference_dir, args.am + \"_am_encoder_infer\"))\n\n        # am.decoder\n        am_decoder = jit.to_static(\n            am_decoder,\n            input_spec=[InputSpec([1, -1, 384], dtype=paddle.float32)])\n        paddle.jit.save(am_decoder,\n                        os.path.join(args.inference_dir,\n                                     args.am + \"_am_decoder\"))\n        am_decoder = paddle.jit.load(\n            os.path.join(args.inference_dir, args.am + \"_am_decoder\"))\n\n        # am.postnet\n        am_postnet = jit.to_static(\n            am_postnet,\n            input_spec=[InputSpec([1, 80, -1], dtype=paddle.float32)])\n        paddle.jit.save(am_postnet,\n                        os.path.join(args.inference_dir,\n                                     args.am + \"_am_postnet\"))\n        am_postnet = paddle.jit.load(\n            os.path.join(args.inference_dir, args.am + \"_am_postnet\"))\n\n        # vocoder\n        voc_inference = voc_to_static(\n            voc_inference=voc_inference,\n            voc=args.voc,\n            inference_dir=args.inference_dir)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    merge_sentences = True\n    get_tone_ids = False\n\n    N = 0\n    T = 0\n    block_size = args.block_size\n    pad_size = args.pad_size\n\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            frontend_dict = run_frontend(\n                frontend=frontend,\n                text=sentence,\n                merge_sentences=merge_sentences,\n                get_tone_ids=get_tone_ids,\n                lang=args.lang)\n            phone_ids = frontend_dict['phone_ids']\n            # merge_sentences=True here, so we only use the first item of phone_ids\n            phone_ids = phone_ids[0]\n            with paddle.no_grad():\n                # acoustic model\n                orig_hs = am_encoder_infer(phone_ids)\n                if args.am_streaming:\n                    hss = get_chunks(orig_hs, block_size, pad_size)\n                    chunk_num = len(hss)\n                    mel_list = []\n                    for i, hs in enumerate(hss):\n                        before_outs = am_decoder(hs)\n                        after_outs = before_outs + am_postnet(\n                            before_outs.transpose((0, 2, 1))).transpose(\n                                (0, 2, 1))\n                        normalized_mel = after_outs[0]\n                        sub_mel = denorm(normalized_mel, am_mu, am_std)\n                        # clip output part of pad\n                        if i == 0:\n                            sub_mel = sub_mel[:-pad_size]\n                        elif i == chunk_num - 1:\n                            # 最后一块的右侧一定没有 pad 够\n                            sub_mel = sub_mel[pad_size:]\n                        else:\n                            # 倒数几块的右侧也可能没有 pad 够\n                            sub_mel = sub_mel[pad_size:(block_size + pad_size) -\n                                              sub_mel.shape[0]]\n                        mel_list.append(sub_mel)\n                    mel = paddle.concat(mel_list, axis=0)\n\n                else:\n                    before_outs = am_decoder(orig_hs)\n                    after_outs = before_outs + am_postnet(\n                        before_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n                    normalized_mel = after_outs[0]\n                    mel = denorm(normalized_mel, am_mu, am_std)\n\n                # vocoder\n                wav = voc_inference(mel)\n\n        wav = wav.numpy()\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = am_config.fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")), wav, samplerate=am_config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {am_config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with acoustic model & vocoder\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_csmsc'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        '--am_config', type=str, default=None, help='Config of acoustic model.')\n    parser.add_argument(\n        '--am_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--tones_dict\", type=str, default=None, help=\"tone vocabulary file.\")\n\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=[\n            'pwgan_csmsc',\n            'mb_melgan_csmsc',\n            'style_melgan_csmsc',\n            'hifigan_csmsc',\n        ],\n        help='Choose vocoder type of tts task.')\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n\n    parser.add_argument(\n        \"--inference_dir\",\n        type=str,\n        default=None,\n        help=\"dir to save inference models\")\n\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    # streaming related\n    parser.add_argument(\n        \"--am_streaming\",\n        type=str2bool,\n        default=False,\n        help=\"whether use streaming acoustic model\")\n    parser.add_argument(\n        \"--block_size\", type=int, default=42, help=\"block size of am streaming\")\n    parser.add_argument(\n        \"--pad_size\", type=int, default=12, help=\"pad size of am streaming\")\n\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/tacotron2/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/tacotron2/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None,\n                     cut_sil: bool=True,\n                     spk_emb_dir: Path=None):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n        # extract mel feats\n        logmel = mel_extractor.get_log_mel_fbank(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, logmel)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = logmel.shape[0]\n        assert sum(durations) == num_frames\n        mel_dir = output_dir / \"data_speech\"\n        mel_dir.mkdir(parents=True, exist_ok=True)\n        mel_path = mel_dir / (utt_id + \"_speech.npy\")\n        np.save(mel_path, logmel)\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"speech_lengths\": num_frames,\n            \"speech\": str(mel_path),\n            \"speaker\": speaker\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      spk_emb_dir: Path=None):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor,\n                                         cut_sil, spk_emb_dir)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'w') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {baker, aishell3, ljspeech, vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/tacotron2/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import tacotron2_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import tacotron2_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.tacotron2 import Tacotron2\nfrom paddlespeech.t2s.models.tacotron2 import Tacotron2Evaluator\nfrom paddlespeech.t2s.models.tacotron2 import Tacotron2Updater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    fields = [\n        \"text\",\n        \"text_lengths\",\n        \"speech\",\n        \"speech_lengths\",\n    ]\n\n    converters = {\n        \"speech\": np.load,\n    }\n    if args.voice_cloning:\n        print(\"Training voice cloning!\")\n        collate_fn = tacotron2_multi_spk_batch_fn\n        fields += [\"spk_emb\"]\n        converters[\"spk_emb\"] = np.load\n    else:\n        print(\"single speaker tacotron2!\")\n        collate_fn = tacotron2_single_spk_batch_fn\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    model = Tacotron2(idim=vocab_size, odim=odim, **config[\"model\"])\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    optimizer = build_optimizers(model, **config[\"optimizer\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = Tacotron2Updater(\n        model=model,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir,\n        **config[\"updater\"])\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = Tacotron2Evaluator(\n        model, dev_dataloader, output_dir=output_dir, **config[\"updater\"])\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train a Tacotron2 model.\")\n    parser.add_argument(\"--config\", type=str, help=\"tacotron2 config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--speech-stats\",\n        type=str,\n        required=True,\n        help=\"speech statistics file.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n\n    args = parser.parse_args()\n\n    # check directory existence\n    dumpdir = Path(args.dumpdir).resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata, converters={\n            \"speech\": np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    speech_scaler = StandardScaler()\n    speech_scaler.mean_ = np.load(args.speech_stats)[0]\n    speech_scaler.scale_ = np.load(args.speech_stats)[1]\n    speech_scaler.n_features_in_ = speech_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        speech = item['speech']\n        # normalize\n        speech = speech_scaler.transform(speech)\n        speech_dir = dumpdir / \"data_speech\"\n        speech_dir.mkdir(parents=True, exist_ok=True)\n        speech_path = speech_dir / f\"{utt_id}_speech.npy\"\n        np.save(speech_path, speech.astype(np.float32), allow_pickle=False)\n\n        phone_ids = [vocab_phones[p] for p in item['phones']]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"spk_id\": spk_id,\n            \"text\": phone_ids,\n            \"text_lengths\": item['text_lengths'],\n            \"speech_lengths\": item['speech_lengths'],\n            \"speech\": str(speech_path),\n        }\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('utt_id'))\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode as Configuration\n\nfrom paddlespeech.t2s.datasets.get_feats import LogMelFBank\nfrom paddlespeech.t2s.frontend.en_frontend import English\n\n\ndef get_lj_sentences(file_name, frontend):\n    '''read MFA duration.txt\n\n    Args:\n        file_name (str or Path)\n    Returns:\n        Dict: sentence: {'utt': ([char], [int])}\n    '''\n    f = open(file_name, 'r')\n    sentence = {}\n    speaker_set = set()\n    for line in f:\n        line_list = line.strip().split('|')\n        utt = line_list[0]\n        speaker = utt.split(\"-\")[0][:2]\n        speaker_set.add(speaker)\n        raw_text = line_list[-1]\n        phonemes = frontend.phoneticize(raw_text)\n        phonemes = phonemes[1:-1]\n        phonemes = [phn for phn in phonemes if not phn.isspace()]\n        sentence[utt] = (phonemes, speaker)\n    f.close()\n    return sentence, speaker_set\n\n\ndef get_input_token(sentence, output_path):\n    '''get phone set from training data and save it\n    \n    Args:\n        sentence (Dict): sentence: {'utt': ([char], str)}\n        output_path (str or path): path to save phone_id_map\n    '''\n    phn_token = set()\n    for utt in sentence:\n        for phn in sentence[utt][0]:\n            if phn != \"<eos>\":\n                phn_token.add(phn)\n    phn_token = list(phn_token)\n    phn_token.sort()\n    phn_token = [\"<pad>\", \"<unk>\"] + phn_token\n    phn_token += [\"<eos>\"]\n\n    with open(output_path, 'w') as f:\n        for i, phn in enumerate(phn_token):\n            f.write(phn + ' ' + str(i) + '\\n')\n\n\ndef get_spk_id_map(speaker_set, output_path):\n    speakers = sorted(list(speaker_set))\n    with open(output_path, 'w') as f:\n        for i, spk in enumerate(speakers):\n            f.write(spk + ' ' + str(i) + '\\n')\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     mel_extractor=None):\n    utt_id = fp.stem\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1 or np.abs(wav).max() > 1.0:\n            return record\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        speaker = sentences[utt_id][1]\n        logmel = mel_extractor.get_log_mel_fbank(wav, base='e')\n        # change duration according to mel_length\n        num_frames = logmel.shape[0]\n        mel_dir = output_dir / \"data_speech\"\n        mel_dir.mkdir(parents=True, exist_ok=True)\n        mel_path = mel_dir / (utt_id + \"_speech.npy\")\n        np.save(mel_path, logmel)\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"speech_lengths\": num_frames,\n            \"speech\": str(mel_path),\n            \"speaker\": speaker\n        }\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      mel_extractor=None,\n                      nprocs: int=1):\n\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                mel_extractor=mel_extractor)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, mel_extractor)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"utt_id\"))\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'w') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"ljspeech\",\n        type=str,\n        help=\"name of dataset, should in {ljspeech} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n\n    parser.add_argument(\n        \"--config-path\",\n        default=\"conf/default.yaml\",\n        type=str,\n        help=\"yaml format configuration file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    args = parser.parse_args()\n\n    config_path = Path(args.config_path).resolve()\n    root_dir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    assert root_dir.is_dir()\n\n    with open(config_path, 'rt') as f:\n        _C = yaml.safe_load(f)\n        _C = Configuration(_C)\n        config = _C.clone()\n\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n\n    if args.dataset == \"ljspeech\":\n        wav_files = sorted(list((root_dir / \"wavs\").rglob(\"*.wav\")))\n        frontend = English()\n        sentences, speaker_set = get_lj_sentences(root_dir / \"metadata.csv\",\n                                                  frontend)\n        get_input_token(sentences, phone_id_map_path)\n        get_spk_id_map(speaker_set, speaker_id_map_path)\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n    mel_extractor = LogMelFBank(\n        sr=config.fs,\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window,\n        n_mels=config.n_mels,\n        fmin=config.fmin,\n        fmax=config.fmax)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            mel_extractor=mel_extractor,\n            nprocs=args.num_cpu)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/synthesize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTS\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTSInference\nfrom paddlespeech.t2s.models.waveflow import ConditionalWaveFlow\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.t2s.utils import layer_tools\n\n\ndef evaluate(args, acoustic_model_config, vocoder_config):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n    test_dataset = DataTable(data=test_metadata, fields=[\"utt_id\", \"text\"])\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n    odim = acoustic_model_config.n_mels\n    model = TransformerTTS(\n        idim=vocab_size, odim=odim, **acoustic_model_config[\"model\"])\n\n    model.set_state_dict(\n        paddle.load(args.transformer_tts_checkpoint)[\"main_params\"])\n    model.eval()\n    # remove \".pdparams\" in waveflow_checkpoint\n    vocoder_checkpoint_path = args.waveflow_checkpoint[:-9] if args.waveflow_checkpoint.endswith(\n        \".pdparams\") else args.waveflow_checkpoint\n    vocoder = ConditionalWaveFlow.from_pretrained(vocoder_config,\n                                                  vocoder_checkpoint_path)\n    layer_tools.recursively_remove_weight_norm(vocoder)\n    vocoder.eval()\n    print(\"model done!\")\n\n    stat = np.load(args.transformer_tts_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    transformer_tts_normalizer = ZScore(mu, std)\n\n    transformer_tts_inference = TransformerTTSInference(\n        transformer_tts_normalizer, model)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    for datum in test_dataset:\n        utt_id = datum[\"utt_id\"]\n        text = paddle.to_tensor(datum[\"text\"])\n\n        with paddle.no_grad():\n            mel = transformer_tts_inference(text)\n            # mel shape is (T, feats) and waveflow's input shape is (batch, feats, T)\n            mel = mel.unsqueeze(0).transpose([0, 2, 1])\n            # wavflow's output shape is (B, T)\n            wav = vocoder.infer(mel)[0]\n\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            wav.numpy(),\n            samplerate=acoustic_model_config.fs)\n        print(f\"{utt_id} done!\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with transformer tts & waveflow.\")\n    parser.add_argument(\n        \"--transformer-tts-config\",\n        type=str,\n        help=\"transformer tts config file.\")\n    parser.add_argument(\n        \"--transformer-tts-checkpoint\",\n        type=str,\n        help=\"transformer tts checkpoint to load.\")\n    parser.add_argument(\n        \"--transformer-tts-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training transformer tts.\"\n    )\n    parser.add_argument(\n        \"--waveflow-config\", type=str, help=\"waveflow config file.\")\n    # not normalize when training waveflow\n    parser.add_argument(\n        \"--waveflow-checkpoint\", type=str, help=\"waveflow checkpoint to load.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n\n    parser.add_argument(\"--test-metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.transformer_tts_config) as f:\n        transformer_tts_config = CfgNode(yaml.safe_load(f))\n    with open(args.waveflow_config) as f:\n        waveflow_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(transformer_tts_config)\n    print(waveflow_config)\n\n    evaluate(args, transformer_tts_config, waveflow_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/synthesize_e2e.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.frontend.en_frontend import English\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTS\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTSInference\nfrom paddlespeech.t2s.models.waveflow import ConditionalWaveFlow\nfrom paddlespeech.t2s.modules.normalizer import ZScore\nfrom paddlespeech.t2s.utils import layer_tools\n\n\ndef evaluate(args, acoustic_model_config, vocoder_config):\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for evaluation\n    sentences = []\n    with open(args.text, 'rt') as f:\n        for line in f:\n            line_list = line.strip().split()\n            utt_id = line_list[0]\n            sentence = \" \".join(line_list[1:])\n            sentences.append((utt_id, sentence))\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n\n    vocab_size = len(phn_id)\n    phone_id_map = {}\n    for phn, id in phn_id:\n        phone_id_map[phn] = int(id)\n    print(\"vocab_size:\", vocab_size)\n    odim = acoustic_model_config.n_mels\n    model = TransformerTTS(\n        idim=vocab_size, odim=odim, **acoustic_model_config[\"model\"])\n\n    model.set_state_dict(\n        paddle.load(args.transformer_tts_checkpoint)[\"main_params\"])\n    model.eval()\n\n    # remove \".pdparams\" in waveflow_checkpoint\n    vocoder_checkpoint_path = args.waveflow_checkpoint[:-9] if args.waveflow_checkpoint.endswith(\n        \".pdparams\") else args.waveflow_checkpoint\n    vocoder = ConditionalWaveFlow.from_pretrained(vocoder_config,\n                                                  vocoder_checkpoint_path)\n    layer_tools.recursively_remove_weight_norm(vocoder)\n    vocoder.eval()\n    print(\"model done!\")\n\n    frontend = English()\n    print(\"frontend done!\")\n\n    stat = np.load(args.transformer_tts_stat)\n    mu, std = stat\n    mu = paddle.to_tensor(mu)\n    std = paddle.to_tensor(std)\n    transformer_tts_normalizer = ZScore(mu, std)\n\n    transformer_tts_inference = TransformerTTSInference(\n        transformer_tts_normalizer, model)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    for utt_id, sentence in sentences:\n        phones = frontend.phoneticize(sentence)\n        # remove start_symbol and end_symbol\n        phones = phones[1:-1]\n        phones = [phn for phn in phones if not phn.isspace()]\n        phones = [phn if phn in phone_id_map else \",\" for phn in phones]\n        phone_ids = [phone_id_map[phn] for phn in phones]\n        with paddle.no_grad():\n            mel = transformer_tts_inference(paddle.to_tensor(phone_ids))\n            # mel shape is (T, feats) and waveflow's input shape is (batch, feats, T)\n            mel = mel.unsqueeze(0).transpose([0, 2, 1])\n            # wavflow's output shape is (B, T)\n            wav = vocoder.infer(mel)[0]\n\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            wav.numpy(),\n            samplerate=acoustic_model_config.fs)\n        print(f\"{utt_id} done!\")\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(\n        description=\"Synthesize with transformer tts & waveflow.\")\n    parser.add_argument(\n        \"--transformer-tts-config\",\n        type=str,\n        help=\"transformer tts config file.\")\n    parser.add_argument(\n        \"--transformer-tts-checkpoint\",\n        type=str,\n        help=\"transformer tts checkpoint to load.\")\n    parser.add_argument(\n        \"--transformer-tts-stat\",\n        type=str,\n        help=\"mean and standard deviation used to normalize spectrogram when training transformer tts.\"\n    )\n    parser.add_argument(\n        \"--waveflow-config\", type=str, help=\"waveflow config file.\")\n    # not normalize when training waveflow\n    parser.add_argument(\n        \"--waveflow-checkpoint\", type=str, help=\"waveflow checkpoint to load.\")\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    with open(args.transformer_tts_config) as f:\n        transformer_tts_config = CfgNode(yaml.safe_load(f))\n    with open(args.waveflow_config) as f:\n        waveflow_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(transformer_tts_config)\n    print(waveflow_config)\n\n    evaluate(args, transformer_tts_config, waveflow_config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/transformer_tts/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import transformer_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTS\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTSEvaluator\nfrom paddlespeech.t2s.models.transformer_tts import TransformerTTSUpdater\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import build_optimizers\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if paddle.is_compiled_with_cuda() and args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    elif paddle.is_compiled_with_npu() and args.ngpu > 0:\n        paddle.set_device(\"npu\")\n    else:\n        paddle.set_device(\"cpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\n            \"text\",\n            \"text_lengths\",\n            \"speech\",\n            \"speech_lengths\",\n        ],\n        converters={\n            \"speech\": np.load,\n        }, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\n            \"text\",\n            \"text_lengths\",\n            \"speech\",\n            \"speech_lengths\",\n        ],\n        converters={\n            \"speech\": np.load,\n        }, )\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=transformer_single_spk_batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        shuffle=False,\n        drop_last=False,\n        batch_size=config.batch_size,\n        collate_fn=transformer_single_spk_batch_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_mels\n    model = TransformerTTS(idim=vocab_size, odim=odim, **config[\"model\"])\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    optimizer = build_optimizers(model, **config[\"optimizer\"])\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = TransformerTTSUpdater(\n        model=model,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir,\n        **config[\"updater\"])\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = TransformerTTSEvaluator(\n        model, dev_dataloader, output_dir=output_dir, **config[\"updater\"])\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train a TransformerTTS \"\n                                     \"model with LJSpeech TTS dataset.\")\n    parser.add_argument(\n        \"--config\", type=str, help=\"TransformerTTS config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/inference.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.syn_utils import get_am_output\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_predictor\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='vits_csmsc',\n        choices=['vits_csmsc', 'vits_aishell3'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en or mix')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--add-blank\",\n        type=str2bool,\n        default=True,\n        help=\"whether to add blank between phones\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n    # inference\n    parser.add_argument(\n        \"--use_trt\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use TensorRT or not in GPU\", )\n    parser.add_argument(\n        \"--use_mkldnn\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use MKLDNN or not in CPU.\", )\n    parser.add_argument(\n        \"--precision\",\n        type=str,\n        default='fp32',\n        choices=['fp32', 'fp16', 'bf16', 'int8'],\n        help=\"mode of running\")\n    parser.add_argument(\n        \"--device\",\n        default=\"gpu\",\n        choices=[\"gpu\", \"cpu\"],\n        help=\"Device selected for inference.\", )\n    parser.add_argument('--cpu_threads', type=int, default=1)\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    paddle.set_device(args.device)\n\n    # frontend\n    frontend = get_frontend(lang=args.lang, phones_dict=args.phones_dict)\n\n    # am_predictor\n    am_predictor = get_predictor(\n        model_dir=args.inference_dir,\n        model_file=args.am + \".pdmodel\",\n        params_file=args.am + \".pdiparams\",\n        device=args.device,\n        use_trt=args.use_trt,\n        use_mkldnn=args.use_mkldnn,\n        cpu_threads=args.cpu_threads,\n        precision=args.precision)\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n    add_blank = args.add_blank\n    # vits's fs is 22050\n    fs = 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            wav = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id,\n                add_blank=add_blank)\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            wav = get_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id,\n                add_blank=add_blank)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/lite_predict.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport soundfile as sf\nfrom timer import timer\n\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_am_output\nfrom paddlespeech.t2s.exps.lite_syn_utils import get_lite_predictor\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Paddle Infernce with acoustic model & vocoder.\")\n    # acoustic model\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='vits_csmsc',\n        choices=[\n            'vits_csmsc',\n            'vits_aishell3',\n        ],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en or mix')\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line\")\n    parser.add_argument(\n        \"--add-blank\",\n        type=str2bool,\n        default=True,\n        help=\"whether to add blank between phones\")\n    parser.add_argument(\n        \"--inference_dir\", type=str, help=\"dir to save inference models\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir\")\n\n    args, _ = parser.parse_known_args()\n    return args\n\n\n# only inference for models trained with csmsc now\ndef main():\n    args = parse_args()\n\n    # frontend\n    frontend = get_frontend(\n        lang=args.lang,\n        phones_dict=args.phones_dict)\n\n    # am_predictor\n    # vits can only run in arm\n    am_predictor = get_lite_predictor(\n        model_dir=args.inference_dir, model_file=args.am + \"_arm.nb\")\n    # model: {model_name}_{dataset}\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    merge_sentences = True\n    add_blank = args.add_blank\n    fs = 22050\n    # warmup\n    for utt_id, sentence in sentences[:3]:\n        with timer() as t:\n            wav = get_lite_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id,\n                add_blank=add_blank)\n\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n    print(\"warm up done!\")\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            wav = get_lite_am_output(\n                input=sentence,\n                am_predictor=am_predictor,\n                am=args.am,\n                frontend=frontend,\n                lang=args.lang,\n                merge_sentences=merge_sentences,\n                speaker_dict=args.speaker_dict,\n                spk_id=args.spk_id,\n                add_blank=add_blank)\n\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = fs / speed\n\n        sf.write(output_dir / (utt_id + \".wav\"), wav, samplerate=fs)\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/normalize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Normalize feature files and dump them.\"\"\"\nimport argparse\nimport logging\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import List\n\nimport jsonlines\nimport numpy as np\nfrom sklearn.preprocessing import StandardScaler\nfrom tqdm import tqdm\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.utils import str2bool\n\nINITIALS = [\n    'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'zh', 'ch', 'sh',\n    'r', 'z', 'c', 's', 'j', 'q', 'x'\n]\nINITIALS += ['y', 'w', 'sp', 'spl', 'spn', 'sil']\n\n\ndef intersperse(lst, item):\n    result = [item] * (len(lst) * 2 + 1)\n    result[1::2] = lst\n    return result\n\n\ndef insert_after_character(lst, item):\n    result = [item]\n    for phone in lst:\n        result.append(phone)\n        if phone not in INITIALS:\n            # finals has tones\n            assert phone[-1] in \"12345\"\n            result.append(item)\n    return result\n\n\ndef add_blank(phones: List[str],\n              filed: str=\"character\",\n              blank_token: str=\"<pad>\"):\n    if filed == \"phone\":\n        \"\"\"\n        add blank after phones\n        input: [\"n\", \"i3\", \"h\", \"ao3\", \"m\", \"a5\"]\n        output: [\"n\", \"<pad>\", \"i3\", \"<pad>\", \"h\", \"<pad>\", \"ao3\", \"<pad>\", \"m\", \"<pad>\", \"a5\"]\n        \"\"\"\n        phones = intersperse(phones, blank_token)\n    elif filed == \"character\":\n        \"\"\"\n        add blank after characters\n        input: [\"n\", \"i3\", \"h\", \"ao3\"]\n        output: [\"n\", \"i3\", \"<pad>\", \"h\", \"ao3\", \"<pad>\", \"m\", \"a5\"]\n        \"\"\"\n        phones = insert_after_character(phones, blank_token)\n    return phones\n\n\ndef main():\n    \"\"\"Run preprocessing process.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Normalize dumped raw features (See detail in parallel_wavegan/bin/normalize.py).\"\n    )\n    parser.add_argument(\n        \"--metadata\",\n        type=str,\n        required=True,\n        help=\"directory including feature files to be normalized. \"\n        \"you need to specify either *-scp or rootdir.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump normalized feature files.\")\n    parser.add_argument(\n        \"--feats-stats\",\n        type=str,\n        required=True,\n        help=\"speech statistics file.\")\n    parser.add_argument(\n        \"--skip-wav-copy\",\n        default=False,\n        action=\"store_true\",\n        help=\"whether to skip the copy of wav files.\")\n\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        \"--add-blank\",\n        type=str2bool,\n        default=True,\n        help=\"whether to add blank between phones\")\n\n    args = parser.parse_args()\n\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n\n    # get dataset\n    with jsonlines.open(args.metadata, 'r') as reader:\n        metadata = list(reader)\n    dataset = DataTable(\n        metadata,\n        converters={\n            \"feats\": np.load,\n            \"wave\": None if args.skip_wav_copy else np.load,\n        })\n    logging.info(f\"The number of files = {len(dataset)}.\")\n\n    # restore scaler\n    feats_scaler = StandardScaler()\n    feats_scaler.mean_ = np.load(args.feats_stats)[0]\n    feats_scaler.scale_ = np.load(args.feats_stats)[1]\n    feats_scaler.n_features_in_ = feats_scaler.mean_.shape[0]\n\n    vocab_phones = {}\n    with open(args.phones_dict, 'rt') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    for phn, id in phn_id:\n        vocab_phones[phn] = int(id)\n\n    vocab_speaker = {}\n    with open(args.speaker_dict, 'rt') as f:\n        spk_id = [line.strip().split() for line in f.readlines()]\n    for spk, id in spk_id:\n        vocab_speaker[spk] = int(id)\n\n    # process each file\n    output_metadata = []\n\n    for item in tqdm(dataset):\n        utt_id = item['utt_id']\n        feats = item['feats']\n        wave = item['wave']\n\n        # normalize\n        feats = feats_scaler.transform(feats)\n        feats_path = dumpdir / f\"{utt_id}_feats.npy\"\n        np.save(feats_path, feats.astype(np.float32), allow_pickle=False)\n\n        if not args.skip_wav_copy:\n            wav_path = dumpdir / f\"{utt_id}_wave.npy\"\n            np.save(wav_path, wave.astype(np.float32), allow_pickle=False)\n        else:\n            wav_path = wave\n\n        phones = item['phones']\n        text_lengths = item['text_lengths']\n        if args.add_blank:\n            phones = add_blank(phones, filed=\"character\")\n            text_lengths = len(phones)\n\n        phone_ids = [vocab_phones[p] for p in phones]\n        spk_id = vocab_speaker[item[\"speaker\"]]\n\n        record = {\n            \"utt_id\": item['utt_id'],\n            \"text\": phone_ids,\n            \"text_lengths\": text_lengths,\n            'feats': str(feats_path),\n            \"feats_lengths\": item['feats_lengths'],\n            \"wave\": str(wav_path),\n            \"spk_id\": spk_id,\n        }\n\n        # add spk_emb for voice cloning\n        if \"spk_emb\" in item:\n            record[\"spk_emb\"] = str(item[\"spk_emb\"])\n\n        output_metadata.append(record)\n    output_metadata.sort(key=itemgetter('feats_lengths'), reverse=True)\n    output_metadata_path = Path(args.dumpdir) / \"metadata.jsonl\"\n    with jsonlines.open(output_metadata_path, 'w') as writer:\n        for item in output_metadata:\n            writer.write(item)\n    logging.info(f\"metadata dumped into {output_metadata_path}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/preprocess.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom operator import itemgetter\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\nimport librosa\nimport numpy as np\nimport tqdm\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.get_feats import LinearSpectrogram\nfrom paddlespeech.t2s.datasets.preprocess_utils import compare_duration_and_mel_length\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_input_token\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_phn_dur\nfrom paddlespeech.t2s.datasets.preprocess_utils import get_spk_id_map\nfrom paddlespeech.t2s.datasets.preprocess_utils import merge_silence\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef process_sentence(config: Dict[str, Any],\n                     fp: Path,\n                     sentences: Dict,\n                     output_dir: Path,\n                     spec_extractor=None,\n                     cut_sil: bool=True,\n                     spk_emb_dir: Path=None):\n    utt_id = fp.stem\n    # for vctk\n    if utt_id.endswith(\"_mic2\"):\n        utt_id = utt_id[:-5]\n    record = None\n    if utt_id in sentences:\n        # reading, resampling may occur\n        wav, _ = librosa.load(str(fp), sr=config.fs)\n        if len(wav.shape) != 1:\n            return record\n        max_value = np.abs(wav).max()\n        if max_value > 1.0:\n            wav = wav / max_value\n        assert len(wav.shape) == 1, f\"{utt_id} is not a mono-channel audio.\"\n        assert np.abs(wav).max(\n        ) <= 1.0, f\"{utt_id} is seems to be different that 16 bit PCM.\"\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        speaker = sentences[utt_id][2]\n        d_cumsum = np.pad(np.array(durations).cumsum(0), (1, 0), 'constant')\n        # little imprecise than use *.TextGrid directly\n        times = librosa.frames_to_time(\n            d_cumsum, sr=config.fs, hop_length=config.n_shift)\n        if cut_sil:\n            start = 0\n            end = d_cumsum[-1]\n            if phones[0] == \"sil\" and len(durations) > 1:\n                start = times[1]\n                durations = durations[1:]\n                phones = phones[1:]\n            if phones[-1] == 'sil' and len(durations) > 1:\n                end = times[-2]\n                durations = durations[:-1]\n                phones = phones[:-1]\n            sentences[utt_id][0] = phones\n            sentences[utt_id][1] = durations\n            start, end = librosa.time_to_samples([start, end], sr=config.fs)\n            wav = wav[start:end]\n        # extract mel feats\n        spec = spec_extractor.get_linear_spectrogram(wav)\n        # change duration according to mel_length\n        compare_duration_and_mel_length(sentences, utt_id, spec)\n        # utt_id may be popped in compare_duration_and_mel_length\n        if utt_id not in sentences:\n            return None\n        phones = sentences[utt_id][0]\n        durations = sentences[utt_id][1]\n        num_frames = spec.shape[0]\n        assert sum(durations) == num_frames\n\n        if wav.size < num_frames * config.n_shift:\n            wav = np.pad(\n                wav, (0, num_frames * config.n_shift - wav.size),\n                mode=\"reflect\")\n        else:\n            wav = wav[:num_frames * config.n_shift]\n        num_samples = wav.shape[0]\n\n        spec_path = output_dir / (utt_id + \"_feats.npy\")\n        wav_path = output_dir / (utt_id + \"_wave.npy\")\n        # (num_samples, )\n        np.save(wav_path, wav)\n        # (num_frames, aux_channels)\n        np.save(spec_path, spec)\n\n        record = {\n            \"utt_id\": utt_id,\n            \"phones\": phones,\n            \"text_lengths\": len(phones),\n            \"feats\": str(spec_path),\n            \"feats_lengths\": num_frames,\n            \"wave\": str(wav_path),\n            \"speaker\": speaker\n        }\n        if spk_emb_dir:\n            if speaker in os.listdir(spk_emb_dir):\n                embed_name = utt_id + \".npy\"\n                embed_path = spk_emb_dir / speaker / embed_name\n                if embed_path.is_file():\n                    record[\"spk_emb\"] = str(embed_path)\n                else:\n                    return None\n    return record\n\n\ndef process_sentences(config,\n                      fps: List[Path],\n                      sentences: Dict,\n                      output_dir: Path,\n                      spec_extractor=None,\n                      nprocs: int=1,\n                      cut_sil: bool=True,\n                      spk_emb_dir: Path=None):\n    if nprocs == 1:\n        results = []\n        for fp in tqdm.tqdm(fps, total=len(fps)):\n            record = process_sentence(\n                config=config,\n                fp=fp,\n                sentences=sentences,\n                output_dir=output_dir,\n                spec_extractor=spec_extractor,\n                cut_sil=cut_sil,\n                spk_emb_dir=spk_emb_dir)\n            if record:\n                results.append(record)\n    else:\n        with ThreadPoolExecutor(nprocs) as pool:\n            futures = []\n            with tqdm.tqdm(total=len(fps)) as progress:\n                for fp in fps:\n                    future = pool.submit(process_sentence, config, fp,\n                                         sentences, output_dir, spec_extractor,\n                                         cut_sil, spk_emb_dir)\n                    future.add_done_callback(lambda p: progress.update())\n                    futures.append(future)\n\n                results = []\n                for ft in futures:\n                    record = ft.result()\n                    if record:\n                        results.append(record)\n\n    results.sort(key=itemgetter(\"feats_lengths\"), reverse=True)\n    with jsonlines.open(output_dir / \"metadata.jsonl\", 'w') as writer:\n        for item in results:\n            writer.write(item)\n    print(\"Done\")\n\n\ndef main():\n    # parse config and args\n    parser = argparse.ArgumentParser(\n        description=\"Preprocess audio and then extract features.\")\n\n    parser.add_argument(\n        \"--dataset\",\n        default=\"baker\",\n        type=str,\n        help=\"name of dataset, should in {baker, aishell3, ljspeech, vctk} now\")\n\n    parser.add_argument(\n        \"--rootdir\", default=None, type=str, help=\"directory to dataset.\")\n\n    parser.add_argument(\n        \"--dumpdir\",\n        type=str,\n        required=True,\n        help=\"directory to dump feature files.\")\n    parser.add_argument(\n        \"--dur-file\", default=None, type=str, help=\"path to durations.txt.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"fastspeech2 config file.\")\n\n    parser.add_argument(\n        \"--num-cpu\", type=int, default=1, help=\"number of process.\")\n\n    parser.add_argument(\n        \"--cut-sil\",\n        type=str2bool,\n        default=True,\n        help=\"whether cut sil in the edge of audio\")\n\n    parser.add_argument(\n        \"--spk_emb_dir\",\n        default=None,\n        type=str,\n        help=\"directory to speaker embedding files.\")\n    args = parser.parse_args()\n\n    rootdir = Path(args.rootdir).expanduser()\n    dumpdir = Path(args.dumpdir).expanduser()\n    # use absolute path\n    dumpdir = dumpdir.resolve()\n    dumpdir.mkdir(parents=True, exist_ok=True)\n    dur_file = Path(args.dur_file).expanduser()\n\n    if args.spk_emb_dir:\n        spk_emb_dir = Path(args.spk_emb_dir).expanduser().resolve()\n    else:\n        spk_emb_dir = None\n\n    assert rootdir.is_dir()\n    assert dur_file.is_file()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    sentences, speaker_set = get_phn_dur(dur_file)\n\n    merge_silence(sentences)\n    phone_id_map_path = dumpdir / \"phone_id_map.txt\"\n    speaker_id_map_path = dumpdir / \"speaker_id_map.txt\"\n    get_input_token(sentences, phone_id_map_path, args.dataset)\n    get_spk_id_map(speaker_set, speaker_id_map_path)\n\n    if args.dataset == \"baker\":\n        wav_files = sorted(list((rootdir / \"Wave\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 9800\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"aishell3\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"train\" / \"wav\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*.wav\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    elif args.dataset == \"ljspeech\":\n        wav_files = sorted(list((rootdir / \"wavs\").rglob(\"*.wav\")))\n        # split data into 3 sections\n        num_train = 12900\n        num_dev = 100\n        train_wav_files = wav_files[:num_train]\n        dev_wav_files = wav_files[num_train:num_train + num_dev]\n        test_wav_files = wav_files[num_train + num_dev:]\n    elif args.dataset == \"vctk\":\n        sub_num_dev = 5\n        wav_dir = rootdir / \"wav48_silence_trimmed\"\n        train_wav_files = []\n        dev_wav_files = []\n        test_wav_files = []\n        for speaker in os.listdir(wav_dir):\n            wav_files = sorted(list((wav_dir / speaker).rglob(\"*_mic2.flac\")))\n            if len(wav_files) > 100:\n                train_wav_files += wav_files[:-sub_num_dev * 2]\n                dev_wav_files += wav_files[-sub_num_dev * 2:-sub_num_dev]\n                test_wav_files += wav_files[-sub_num_dev:]\n            else:\n                train_wav_files += wav_files\n\n    else:\n        print(\"dataset should in {baker, aishell3, ljspeech, vctk} now!\")\n\n    train_dump_dir = dumpdir / \"train\" / \"raw\"\n    train_dump_dir.mkdir(parents=True, exist_ok=True)\n    dev_dump_dir = dumpdir / \"dev\" / \"raw\"\n    dev_dump_dir.mkdir(parents=True, exist_ok=True)\n    test_dump_dir = dumpdir / \"test\" / \"raw\"\n    test_dump_dir.mkdir(parents=True, exist_ok=True)\n\n    # Extractor\n\n    spec_extractor = LinearSpectrogram(\n        n_fft=config.n_fft,\n        hop_length=config.n_shift,\n        win_length=config.win_length,\n        window=config.window)\n\n    # process for the 3 sections\n    if train_wav_files:\n        process_sentences(\n            config=config,\n            fps=train_wav_files,\n            sentences=sentences,\n            output_dir=train_dump_dir,\n            spec_extractor=spec_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if dev_wav_files:\n        process_sentences(\n            config=config,\n            fps=dev_wav_files,\n            sentences=sentences,\n            output_dir=dev_dump_dir,\n            spec_extractor=spec_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n    if test_wav_files:\n        process_sentences(\n            config=config,\n            fps=test_wav_files,\n            sentences=sentences,\n            output_dir=test_dump_dir,\n            spec_extractor=spec_extractor,\n            nprocs=args.num_cpu,\n            cut_sil=args.cut_sil,\n            spk_emb_dir=spk_emb_dir)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/synthesize.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.vits import VITS\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n\n    # construct dataset for evaluation\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        test_metadata = list(reader)\n    # Init body.\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    fields = [\"utt_id\", \"text\"]\n    converters = {}\n\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker vits!\")\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Evaluating voice cloning!\")\n        fields += [\"spk_emb\"]\n    else:\n        print(\"single speaker vits!\")\n    print(\"spk_num:\", spk_num)\n\n    test_dataset = DataTable(\n        data=test_metadata,\n        fields=fields,\n        converters=converters, )\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_fft // 2 + 1\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n\n    vits = VITS(idim=vocab_size, odim=odim, **config[\"model\"])\n    vits.set_state_dict(paddle.load(args.ckpt)[\"main_params\"])\n    vits.eval()\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    N = 0\n    T = 0\n\n    for datum in test_dataset:\n        utt_id = datum[\"utt_id\"]\n        phone_ids = paddle.to_tensor(datum[\"text\"])\n        with timer() as t:\n            with paddle.no_grad():\n                spk_emb = None\n                spk_id = None\n                # multi speaker\n                if args.voice_cloning and \"spk_emb\" in datum:\n                    spk_emb = paddle.to_tensor(np.load(datum[\"spk_emb\"]))\n                elif \"spk_id\" in datum:\n                    spk_id = paddle.to_tensor(datum[\"spk_id\"])\n                out = vits.inference(\n                    text=phone_ids, sids=spk_id, spembs=spk_emb)\n            wav = out[\"wav\"]\n            wav = wav.numpy()\n            N += wav.size\n            T += t.elapse\n            speed = wav.size / t.elapse\n            rtf = config.fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.size}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(description=\"Synthesize with VITS\")\n    # model\n    parser.add_argument(\n        '--config', type=str, default=None, help='Config of VITS.')\n    parser.add_argument(\n        '--ckpt', type=str, default=None, help='Checkpoint file of VITS.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n    # other\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\"--test_metadata\", type=str, help=\"test metadata.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/synthesize_e2e.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.exps.syn_utils import am_to_static\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\nfrom paddlespeech.t2s.exps.syn_utils import get_sentences\nfrom paddlespeech.t2s.models.vits import VITS\nfrom paddlespeech.t2s.models.vits import VITSInference\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef evaluate(args):\n    # Init body.\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    sentences = get_sentences(text_file=args.text, lang=args.lang)\n\n    # frontend\n    frontend = get_frontend(lang=args.lang, phones_dict=args.phones_dict)\n    # acoustic model\n    am_name = args.am[:args.am.rindex('_')]\n    am_dataset = args.am[args.am.rindex('_') + 1:]\n\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker vits!\")\n        with open(args.speaker_dict, 'rt') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n    else:\n        print(\"single speaker vits!\")\n    print(\"spk_num:\", spk_num)\n\n    with open(args.phones_dict, \"r\") as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_fft // 2 + 1\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n\n    vits = VITS(idim=vocab_size, odim=odim, **config[\"model\"])\n    vits.set_state_dict(paddle.load(args.ckpt)[\"main_params\"])\n    vits.eval()\n\n    vits_inference = VITSInference(vits)\n    # whether dygraph to static\n    if args.inference_dir:\n        vits_inference = am_to_static(\n            am_inference=vits_inference,\n            am=args.am,\n            inference_dir=args.inference_dir,\n            speaker_dict=args.speaker_dict)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    merge_sentences = False\n    add_blank = args.add_blank\n\n    N = 0\n    T = 0\n    for utt_id, sentence in sentences:\n        with timer() as t:\n            if args.lang == 'zh':\n                input_ids = frontend.get_input_ids(\n                    sentence,\n                    merge_sentences=merge_sentences,\n                    add_blank=add_blank)\n                phone_ids = input_ids[\"phone_ids\"]\n            elif args.lang == 'en':\n                input_ids = frontend.get_input_ids(\n                    sentence, merge_sentences=merge_sentences)\n                phone_ids = input_ids[\"phone_ids\"]\n            else:\n                print(\"lang should in {'zh', 'en'}!\")\n            with paddle.no_grad():\n                flags = 0\n                for i in range(len(phone_ids)):\n                    part_phone_ids = phone_ids[i]\n                    spk_id = None\n                    if am_dataset in {\"aishell3\",\n                                      \"vctk\"} and spk_num is not None:\n                        spk_id = paddle.to_tensor(args.spk_id)\n                        wav = vits_inference(part_phone_ids, spk_id)\n                    else:\n                        wav = vits_inference(part_phone_ids)\n                    if flags == 0:\n                        wav_all = wav\n                        flags = 1\n                    else:\n                        wav_all = paddle.concat([wav_all, wav])\n        wav = wav_all.numpy()\n        N += wav.size\n        T += t.elapse\n        speed = wav.size / t.elapse\n        rtf = config.fs / speed\n        print(\n            f\"{utt_id}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n        print(f\"{utt_id} done!\")\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\ndef parse_args():\n    # parse args and config \n    parser = argparse.ArgumentParser(description=\"Synthesize with VITS\")\n\n    # model\n    parser.add_argument(\n        '--config', type=str, default=None, help='Config of VITS.')\n    parser.add_argument(\n        '--ckpt', type=str, default=None, help='Checkpoint file of VITS.')\n    parser.add_argument(\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker_dict\", type=str, default=None, help=\"speaker id map file.\")\n    parser.add_argument(\n        '--spk_id',\n        type=int,\n        default=0,\n        help='spk id for multi speaker acoustic model')\n    # other\n    parser.add_argument(\n        '--lang',\n        type=str,\n        default='zh',\n        help='Choose model language. zh or en')\n\n    parser.add_argument(\n        \"--inference_dir\",\n        type=str,\n        default=None,\n        help=\"dir to save inference models\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        help=\"text to synthesize, a 'utt_id sentence' pair per line.\")\n    parser.add_argument(\"--output_dir\", type=str, help=\"output dir.\")\n\n    parser.add_argument(\n        \"--add-blank\",\n        type=str2bool,\n        default=True,\n        help=\"whether to add blank between phones\")\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='vits_csmsc',\n        help='Choose acoustic model type of tts task.')\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    evaluate(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.optimizer import AdamW\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.am_batch_fn import vits_multi_spk_batch_fn\nfrom paddlespeech.t2s.datasets.am_batch_fn import vits_single_spk_batch_fn\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.sampler import ErnieSATSampler\nfrom paddlespeech.t2s.models.vits import VITS\nfrom paddlespeech.t2s.models.vits import VITSEvaluator\nfrom paddlespeech.t2s.models.vits import VITSUpdater\nfrom paddlespeech.t2s.modules.losses import DiscriminatorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import FeatureMatchLoss\nfrom paddlespeech.t2s.modules.losses import GeneratorAdversarialLoss\nfrom paddlespeech.t2s.modules.losses import KLDivergenceLoss\nfrom paddlespeech.t2s.modules.losses import MelSpectrogramLoss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.optimizer import scheduler_classes\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils import str2bool\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n\n    fields = [\"text\", \"text_lengths\", \"feats\", \"feats_lengths\", \"wave\"]\n\n    converters = {\n        \"wave\": np.load,\n        \"feats\": np.load,\n    }\n    spk_num = None\n    if args.speaker_dict is not None:\n        print(\"multiple speaker vits!\")\n        collate_fn = vits_multi_spk_batch_fn\n        with open(args.speaker_dict, 'rt', encoding='utf-8') as f:\n            spk_id = [line.strip().split() for line in f.readlines()]\n        spk_num = len(spk_id)\n        fields += [\"spk_id\"]\n    elif args.voice_cloning:\n        print(\"Training voice cloning!\")\n        collate_fn = vits_multi_spk_batch_fn\n        fields += [\"spk_emb\"]\n        converters[\"spk_emb\"] = np.load\n    else:\n        print(\"single speaker vits!\")\n        collate_fn = vits_single_spk_batch_fn\n    print(\"spk_num:\", spk_num)\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=fields,\n        converters=converters, )\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=fields,\n        converters=converters, )\n\n    # collate function and dataloader\n    train_sampler = ErnieSATSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=True)\n    dev_sampler = ErnieSATSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_sampler=dev_sampler,\n        collate_fn=collate_fn,\n        num_workers=config.num_workers)\n    print(\"dataloaders done!\")\n\n    with open(args.phones_dict, 'rt', encoding='utf-8') as f:\n        phn_id = [line.strip().split() for line in f.readlines()]\n    vocab_size = len(phn_id)\n    print(\"vocab_size:\", vocab_size)\n\n    odim = config.n_fft // 2 + 1\n    config[\"model\"][\"generator_params\"][\"spks\"] = spk_num\n    model = VITS(idim=vocab_size, odim=odim, **config[\"model\"])\n    gen_parameters = model.generator.parameters()\n    dis_parameters = model.discriminator.parameters()\n    if world_size > 1:\n        model = DataParallel(model)\n        gen_parameters = model._layers.generator.parameters()\n        dis_parameters = model._layers.discriminator.parameters()\n\n    print(\"model done!\")\n\n    # loss\n    criterion_mel = MelSpectrogramLoss(\n        **config[\"mel_loss_params\"], )\n    criterion_feat_match = FeatureMatchLoss(\n        **config[\"feat_match_loss_params\"], )\n    criterion_gen_adv = GeneratorAdversarialLoss(\n        **config[\"generator_adv_loss_params\"], )\n    criterion_dis_adv = DiscriminatorAdversarialLoss(\n        **config[\"discriminator_adv_loss_params\"], )\n    criterion_kl = KLDivergenceLoss()\n\n    print(\"criterions done!\")\n\n    lr_schedule_g = scheduler_classes[config[\"generator_scheduler\"]](\n        **config[\"generator_scheduler_params\"])\n    optimizer_g = AdamW(\n        learning_rate=lr_schedule_g,\n        parameters=gen_parameters,\n        **config[\"generator_optimizer_params\"])\n\n    lr_schedule_d = scheduler_classes[config[\"discriminator_scheduler\"]](\n        **config[\"discriminator_scheduler_params\"])\n    optimizer_d = AdamW(\n        learning_rate=lr_schedule_d,\n        parameters=dis_parameters,\n        **config[\"discriminator_optimizer_params\"])\n\n    print(\"optimizers done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = VITSUpdater(\n        model=model,\n        optimizers={\n            \"generator\": optimizer_g,\n            \"discriminator\": optimizer_d,\n        },\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"kl\": criterion_kl,\n        },\n        schedulers={\n            \"generator\": lr_schedule_g,\n            \"discriminator\": lr_schedule_d,\n        },\n        dataloader=train_dataloader,\n        lambda_adv=config.lambda_adv,\n        lambda_mel=config.lambda_mel,\n        lambda_kl=config.lambda_kl,\n        lambda_feat_match=config.lambda_feat_match,\n        lambda_dur=config.lambda_dur,\n        generator_first=config.generator_first,\n        output_dir=output_dir)\n\n    evaluator = VITSEvaluator(\n        model=model,\n        criterions={\n            \"mel\": criterion_mel,\n            \"feat_match\": criterion_feat_match,\n            \"gen_adv\": criterion_gen_adv,\n            \"dis_adv\": criterion_dis_adv,\n            \"kl\": criterion_kl,\n        },\n        dataloader=dev_dataloader,\n        lambda_adv=config.lambda_adv,\n        lambda_mel=config.lambda_mel,\n        lambda_kl=config.lambda_kl,\n        lambda_feat_match=config.lambda_feat_match,\n        lambda_dur=config.lambda_dur,\n        generator_first=config.generator_first,\n        output_dir=output_dir)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a VITS model.\")\n    parser.add_argument(\"--config\", type=str, help=\"VITS config file\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n    parser.add_argument(\n        \"--phones-dict\", type=str, default=None, help=\"phone vocabulary file.\")\n    parser.add_argument(\n        \"--speaker-dict\",\n        type=str,\n        default=None,\n        help=\"speaker id map file for multiple speaker model.\")\n\n    parser.add_argument(\n        \"--voice-cloning\",\n        type=str2bool,\n        default=False,\n        help=\"whether training voice cloning model.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/vits/voice_cloning.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n#     http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\nimport argparse\r\nimport os\r\nfrom pathlib import Path\r\n\r\nimport librosa\r\nimport numpy as np\r\nimport paddle\r\nimport soundfile as sf\r\nimport yaml\r\nfrom yacs.config import CfgNode\r\n\r\nfrom paddlespeech.t2s.datasets.get_feats import LinearSpectrogram\r\nfrom paddlespeech.t2s.exps.syn_utils import get_frontend\r\nfrom paddlespeech.t2s.models.vits import VITS\r\nfrom paddlespeech.t2s.utils import str2bool\r\nfrom paddlespeech.vector.exps.ge2e.audio_processor import SpeakerVerificationPreprocessor\r\nfrom paddlespeech.vector.models.lstm_speaker_encoder import LSTMSpeakerEncoder\r\n\r\n\r\ndef voice_cloning(args):\r\n\r\n    # Init body.\r\n    with open(args.config) as f:\r\n        config = CfgNode(yaml.safe_load(f))\r\n\r\n    print(\"========Args========\")\r\n    print(yaml.safe_dump(vars(args)))\r\n    print(\"========Config========\")\r\n    print(config)\r\n\r\n    # speaker encoder\r\n    spec_extractor = LinearSpectrogram(\r\n        n_fft=config.n_fft,\r\n        hop_length=config.n_shift,\r\n        win_length=config.win_length,\r\n        window=config.window)\r\n    p = SpeakerVerificationPreprocessor(\r\n        sampling_rate=16000,\r\n        audio_norm_target_dBFS=-30,\r\n        vad_window_length=30,\r\n        vad_moving_average_width=8,\r\n        vad_max_silence_length=6,\r\n        mel_window_length=25,\r\n        mel_window_step=10,\r\n        n_mels=40,\r\n        partial_n_frames=160,\r\n        min_pad_coverage=0.75,\r\n        partial_overlap_ratio=0.5)\r\n    print(\"Audio Processor Done!\")\r\n\r\n    speaker_encoder = LSTMSpeakerEncoder(\r\n        n_mels=40, num_layers=3, hidden_size=256, output_size=256)\r\n    speaker_encoder.set_state_dict(paddle.load(args.ge2e_params_path))\r\n    speaker_encoder.eval()\r\n    print(\"GE2E Done!\")\r\n\r\n    frontend = get_frontend(lang=args.lang, phones_dict=args.phones_dict)\r\n    print(\"frontend done!\")\r\n\r\n    with open(args.phones_dict, \"r\") as f:\r\n        phn_id = [line.strip().split() for line in f.readlines()]\r\n    vocab_size = len(phn_id)\r\n    print(\"vocab_size:\", vocab_size)\r\n\r\n    odim = config.n_fft // 2 + 1\r\n\r\n    vits = VITS(idim=vocab_size, odim=odim, **config[\"model\"])\r\n    vits.set_state_dict(paddle.load(args.ckpt)[\"main_params\"])\r\n    vits.eval()\r\n\r\n    output_dir = Path(args.output_dir)\r\n    output_dir.mkdir(parents=True, exist_ok=True)\r\n\r\n    input_dir = Path(args.input_dir)\r\n\r\n    if args.audio_path == \"\":\r\n        args.audio_path = None\r\n    if args.audio_path is None:\r\n        sentence = args.text\r\n        merge_sentences = True\r\n        add_blank = args.add_blank\r\n\r\n        if args.lang == 'zh':\r\n            input_ids = frontend.get_input_ids(\r\n                sentence, merge_sentences=merge_sentences, add_blank=add_blank)\r\n        elif args.lang == 'en':\r\n            input_ids = frontend.get_input_ids(\r\n                sentence, merge_sentences=merge_sentences)\r\n        phone_ids = input_ids[\"phone_ids\"][0]\r\n    else:\r\n        wav, _ = librosa.load(str(args.audio_path), sr=config.fs)\r\n        feats = paddle.to_tensor(spec_extractor.get_linear_spectrogram(wav))\r\n\r\n        mel_sequences = p.extract_mel_partials(\r\n            p.preprocess_wav(args.audio_path))\r\n        with paddle.no_grad():\r\n            spk_emb_src = speaker_encoder.embed_utterance(\r\n                paddle.to_tensor(mel_sequences))\r\n\r\n    for name in os.listdir(input_dir):\r\n        utt_id = name.split(\".\")[0]\r\n        ref_audio_path = input_dir / name\r\n        mel_sequences = p.extract_mel_partials(p.preprocess_wav(ref_audio_path))\r\n        # print(\"mel_sequences: \", mel_sequences.shape)\r\n        with paddle.no_grad():\r\n            spk_emb = speaker_encoder.embed_utterance(\r\n                paddle.to_tensor(mel_sequences))\r\n        # print(\"spk_emb shape: \", spk_emb.shape)\r\n\r\n        with paddle.no_grad():\r\n            if args.audio_path is None:\r\n                out = vits.inference(text=phone_ids, spembs=spk_emb)\r\n            else:\r\n                out = vits.voice_conversion(\r\n                    feats=feats, spembs_src=spk_emb_src, spembs_tgt=spk_emb)\r\n            wav = out[\"wav\"]\r\n\r\n        sf.write(\r\n            str(output_dir / (utt_id + \".wav\")),\r\n            wav.numpy(),\r\n            samplerate=config.fs)\r\n        print(f\"{utt_id} done!\")\r\n    # Randomly generate numbers of 0 ~ 0.2, 256 is the dim of spk_emb\r\n    random_spk_emb = np.random.rand(256) * 0.2\r\n    random_spk_emb = paddle.to_tensor(random_spk_emb, dtype='float32')\r\n    utt_id = \"random_spk_emb\"\r\n    with paddle.no_grad():\r\n        if args.audio_path is None:\r\n            out = vits.inference(text=phone_ids, spembs=random_spk_emb)\r\n        else:\r\n            out = vits.voice_conversion(\r\n                feats=feats, spembs_src=spk_emb_src, spembs_tgt=random_spk_emb)\r\n        wav = out[\"wav\"]\r\n    sf.write(\r\n        str(output_dir / (utt_id + \".wav\")), wav.numpy(), samplerate=config.fs)\r\n    print(f\"{utt_id} done!\")\r\n\r\n\r\ndef parse_args():\r\n    # parse args and config\r\n    parser = argparse.ArgumentParser(description=\"\")\r\n    parser.add_argument(\r\n        '--config', type=str, default=None, help='Config of VITS.')\r\n    parser.add_argument(\r\n        '--ckpt', type=str, default=None, help='Checkpoint file of VITS.')\r\n    parser.add_argument(\r\n        \"--phones_dict\", type=str, default=None, help=\"phone vocabulary file.\")\r\n    parser.add_argument(\r\n        \"--text\",\r\n        type=str,\r\n        default=\"每当你觉得，想要批评什么人的时候，你切要记着，这个世界上的人，并非都具备你禀有的条件。\",\r\n        help=\"text to synthesize, a line\")\r\n    parser.add_argument(\r\n        '--lang',\r\n        type=str,\r\n        default='zh',\r\n        help='Choose model language. zh or en')\r\n    parser.add_argument(\r\n        \"--audio-path\",\r\n        type=str,\r\n        default=None,\r\n        help=\"audio as content to synthesize\")\r\n\r\n    parser.add_argument(\r\n        \"--ge2e_params_path\", type=str, help=\"ge2e params path.\")\r\n\r\n    parser.add_argument(\r\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\r\n\r\n    parser.add_argument(\r\n        \"--input-dir\",\r\n        type=str,\r\n        help=\"input dir of *.wav, the sample rate will be resample to 16k.\")\r\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\r\n\r\n    parser.add_argument(\r\n        \"--add-blank\",\r\n        type=str2bool,\r\n        default=True,\r\n        help=\"whether to add blank between phones\")\r\n\r\n    args = parser.parse_args()\r\n    return args\r\n\r\n\r\ndef main():\r\n    args = parse_args()\r\n\r\n    if args.ngpu == 0:\r\n        paddle.set_device(\"cpu\")\r\n    elif args.ngpu > 0:\r\n        paddle.set_device(\"gpu\")\r\n    else:\r\n        print(\"ngpu should >= 0 !\")\r\n\r\n    voice_cloning(args)\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n"
  },
  {
    "path": "paddlespeech/t2s/exps/voice_cloning.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.vector import VectorExecutor\nfrom paddlespeech.t2s.exps.syn_utils import get_am_inference\nfrom paddlespeech.t2s.exps.syn_utils import get_voc_inference\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend\nfrom paddlespeech.t2s.utils import str2bool\nfrom paddlespeech.vector.exps.ge2e.audio_processor import SpeakerVerificationPreprocessor\nfrom paddlespeech.vector.models.lstm_speaker_encoder import LSTMSpeakerEncoder\n\n\ndef gen_random_embed(use_ecapa: bool=False):\n    if use_ecapa:\n        # Randomly generate numbers of -25 ~ 25, 192 is the dim of spk_emb\n        random_spk_emb = (-1 + 2 * np.random.rand(192)) * 25\n\n    # GE2E\n    else:\n        # Randomly generate numbers of 0 ~ 0.2, 256 is the dim of spk_emb\n        random_spk_emb = np.random.rand(256) * 0.2\n    random_spk_emb = paddle.to_tensor(random_spk_emb, dtype='float32')\n    return random_spk_emb\n\n\ndef voice_cloning(args):\n    # Init body.\n    with open(args.am_config) as f:\n        am_config = CfgNode(yaml.safe_load(f))\n    with open(args.voc_config) as f:\n        voc_config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(am_config)\n    print(voc_config)\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    input_dir = Path(args.input_dir)\n\n    # speaker encoder\n    if args.use_ecapa:\n        vec_executor = VectorExecutor()\n        # warm up\n        vec_executor(\n            audio_file=input_dir / os.listdir(input_dir)[0], force_yes=True)\n        print(\"ECAPA-TDNN Done!\")\n    # use GE2E\n    else:\n        p = SpeakerVerificationPreprocessor(\n            sampling_rate=16000,\n            audio_norm_target_dBFS=-30,\n            vad_window_length=30,\n            vad_moving_average_width=8,\n            vad_max_silence_length=6,\n            mel_window_length=25,\n            mel_window_step=10,\n            n_mels=40,\n            partial_n_frames=160,\n            min_pad_coverage=0.75,\n            partial_overlap_ratio=0.5)\n        print(\"Audio Processor Done!\")\n\n        speaker_encoder = LSTMSpeakerEncoder(\n            n_mels=40, num_layers=3, hidden_size=256, output_size=256)\n        speaker_encoder.set_state_dict(paddle.load(args.ge2e_params_path))\n        speaker_encoder.eval()\n        print(\"GE2E Done!\")\n\n    frontend = Frontend(phone_vocab_path=args.phones_dict)\n    print(\"frontend done!\")\n\n    sentence = args.text\n    input_ids = frontend.get_input_ids(sentence, merge_sentences=True)\n    phone_ids = input_ids[\"phone_ids\"][0]\n\n    # acoustic model\n    am_inference = get_am_inference(\n        am=args.am,\n        am_config=am_config,\n        am_ckpt=args.am_ckpt,\n        am_stat=args.am_stat,\n        phones_dict=args.phones_dict)\n\n    # vocoder\n    voc_inference = get_voc_inference(\n        voc=args.voc,\n        voc_config=voc_config,\n        voc_ckpt=args.voc_ckpt,\n        voc_stat=args.voc_stat)\n\n    for name in os.listdir(input_dir):\n        utt_id = name.split(\".\")[0]\n        ref_audio_path = input_dir / name\n        if args.use_ecapa:\n            spk_emb = vec_executor(audio_file=ref_audio_path, force_yes=True)\n            spk_emb = paddle.to_tensor(spk_emb)\n        # GE2E\n        else:\n            mel_sequences = p.extract_mel_partials(\n                p.preprocess_wav(ref_audio_path))\n            with paddle.no_grad():\n                spk_emb = speaker_encoder.embed_utterance(\n                    paddle.to_tensor(mel_sequences))\n        with paddle.no_grad():\n            wav = voc_inference(am_inference(phone_ids, spk_emb=spk_emb))\n\n        sf.write(\n            str(output_dir / (utt_id + \".wav\")),\n            wav.numpy(),\n            samplerate=am_config.fs)\n        print(f\"{utt_id} done!\")\n\n    # generate 5 random_spk_emb\n    # for i in range(5):\n    #     random_spk_emb = gen_random_embed(args.use_ecapa)\n    #     utt_id = \"random_spk_emb\"\n    #     with paddle.no_grad():\n    #         wav = voc_inference(am_inference(phone_ids, spk_emb=random_spk_emb))\n    #     sf.write(\n    #         str(output_dir / (utt_id + \"_\" + str(i) + \".wav\")),\n    #         wav.numpy(),\n    #         samplerate=am_config.fs)\n    # print(f\"{utt_id} done!\")\n\n\ndef parse_args():\n    # parse args and config\n    parser = argparse.ArgumentParser(description=\"\")\n    parser.add_argument(\n        '--am',\n        type=str,\n        default='fastspeech2_csmsc',\n        choices=['fastspeech2_aishell3', 'tacotron2_aishell3'],\n        help='Choose acoustic model type of tts task.')\n    parser.add_argument(\n        '--am_config', type=str, default=None, help='Config of acoustic model.')\n    parser.add_argument(\n        '--am_ckpt',\n        type=str,\n        default=None,\n        help='Checkpoint file of acoustic model.')\n    parser.add_argument(\n        \"--am_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training acoustic model.\"\n    )\n    parser.add_argument(\n        \"--phones-dict\",\n        type=str,\n        default=\"phone_id_map.txt\",\n        help=\"phone vocabulary file.\")\n    # vocoder\n    parser.add_argument(\n        '--voc',\n        type=str,\n        default='pwgan_csmsc',\n        choices=['pwgan_aishell3'],\n        help='Choose vocoder type of tts task.')\n\n    parser.add_argument(\n        '--voc_config', type=str, default=None, help='Config of voc.')\n    parser.add_argument(\n        '--voc_ckpt', type=str, default=None, help='Checkpoint file of voc.')\n    parser.add_argument(\n        \"--voc_stat\",\n        type=str,\n        default=None,\n        help=\"mean and standard deviation used to normalize spectrogram when training voc.\"\n    )\n    parser.add_argument(\n        \"--text\",\n        type=str,\n        default=\"每当你觉得，想要批评什么人的时候，你切要记着，这个世界上的人，并非都具备你禀有的条件。\",\n        help=\"text to synthesize, a line\")\n    parser.add_argument(\n        \"--ge2e_params_path\", type=str, help=\"ge2e params path.\")\n    parser.add_argument(\n        \"--use_ecapa\",\n        type=str2bool,\n        default=False,\n        help=\"whether to use ECAPA-TDNN as speaker encoder.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n    parser.add_argument(\n        \"--input-dir\",\n        type=str,\n        help=\"input dir of *.wav, the sample rate will be resample to 16k.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n\n    args = parser.parse_args()\n    return args\n\n\ndef main():\n    args = parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    voice_cloning(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/config.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom yacs.config import CfgNode as CN\n\n_C = CN()\n_C.data = CN(\n    dict(\n        batch_size=8,  # batch size\n        valid_size=16,  # the first N examples are reserved for validation\n        sample_rate=22050,  # Hz, sample rate\n        n_fft=1024,  # fft frame size\n        win_length=1024,  # window size\n        hop_length=256,  # hop size between ajacent frame\n        fmin=0,\n        fmax=8000,  # Hz, max frequency when converting to mel\n        n_mels=80,  # mel bands\n        clip_frames=65,  # mel clip frames\n    ))\n\n_C.model = CN(\n    dict(\n        upsample_factors=[16, 16],\n        n_flows=8,  # number of flows in WaveFlow\n        n_layers=8,  # number of conv block in each flow\n        n_group=16,  # folding factor of audio and spectrogram\n        channels=128,  # resiaudal channel in each flow\n        kernel_size=[3, 3],  # kernel size in each conv block\n        sigma=1.0,  # stddev of the random noise\n    ))\n\n_C.training = CN(\n    dict(\n        lr=2e-4,  # learning rates\n        valid_interval=1000,  # validation\n        save_interval=10000,  # checkpoint\n        max_iteration=3000000,  # max iteration to train\n    ))\n\n\ndef get_cfg_defaults():\n    \"\"\"Get a yacs CfgNode object with default values for my_project.\"\"\"\n    # Return a clone so that the defaults will not be altered\n    # This is for the \"local variable\" use pattern\n    return _C.clone()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/ljspeech.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom pathlib import Path\n\nimport numpy as np\nimport pandas\nfrom paddle.io import Dataset\n\nfrom paddlespeech.t2s.datasets.batch import batch_spec\nfrom paddlespeech.t2s.datasets.batch import batch_wav\n\n\nclass LJSpeech(Dataset):\n    \"\"\"A simple dataset adaptor for the processed ljspeech dataset.\"\"\"\n\n    def __init__(self, root):\n        self.root = Path(root).expanduser()\n        meta_data = pandas.read_csv(\n            str(self.root / \"metadata.csv\"),\n            sep=\"\\t\",\n            header=None,\n            names=[\"fname\", \"frames\", \"samples\"])\n\n        records = []\n        for row in meta_data.itertuples():\n            mel_path = str(self.root / \"mel\" / (row.fname + \".npy\"))\n            wav_path = str(self.root / \"wav\" / (row.fname + \".npy\"))\n            records.append((mel_path, wav_path))\n        self.records = records\n\n    def __getitem__(self, i):\n        mel_name, wav_name = self.records[i]\n        mel = np.load(mel_name)\n        wav = np.load(wav_name)\n        return mel, wav\n\n    def __len__(self):\n        return len(self.records)\n\n\nclass LJSpeechCollector(object):\n    \"\"\"A simple callable to batch LJSpeech examples.\"\"\"\n\n    def __init__(self, padding_value=0.):\n        self.padding_value = padding_value\n\n    def __call__(self, examples):\n        mels = [example[0] for example in examples]\n        wavs = [example[1] for example in examples]\n        mels, _ = batch_spec(mels, pad_value=self.padding_value)\n        wavs, _ = batch_wav(wavs, pad_value=self.padding_value)\n        return mels, wavs\n\n\nclass LJSpeechClipCollector(object):\n    def __init__(self, clip_frames=65, hop_length=256):\n        self.clip_frames = clip_frames\n        self.hop_length = hop_length\n\n    def __call__(self, examples):\n        mels = []\n        wavs = []\n        for example in examples:\n            mel_clip, wav_clip = self.clip(example)\n            mels.append(mel_clip)\n            wavs.append(wav_clip)\n        mels = np.stack(mels)\n        wavs = np.stack(wavs)\n        return mels, wavs\n\n    def clip(self, example):\n        mel, wav = example\n        frames = mel.shape[-1]\n        start = np.random.randint(0, frames - self.clip_frames)\n        mel_clip = mel[:, start:start + self.clip_frames]\n        wav_clip = wav[start * self.hop_length:(start + self.clip_frames) *\n                       self.hop_length]\n        return mel_clip, wav_clip\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/preprocess.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport librosa\nimport numpy as np\nimport pandas as pd\nimport tqdm\n\nfrom paddlespeech.t2s.audio import LogMagnitude\nfrom paddlespeech.t2s.datasets import LJSpeechMetaData\nfrom paddlespeech.t2s.exps.waveflow.config import get_cfg_defaults\n\n\nclass Transform(object):\n    def __init__(self, sample_rate, n_fft, win_length, hop_length, n_mels, fmin,\n                 fmax):\n        self.sample_rate = sample_rate\n        self.n_fft = n_fft\n        self.win_length = win_length\n        self.hop_length = hop_length\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax\n\n        self.spec_normalizer = LogMagnitude(min=1e-5)\n\n    def __call__(self, example):\n        wav_path, _, _ = example\n\n        sr = self.sample_rate\n        n_fft = self.n_fft\n        win_length = self.win_length\n        hop_length = self.hop_length\n        n_mels = self.n_mels\n        fmin = self.fmin\n        fmax = self.fmax\n\n        wav, loaded_sr = librosa.load(wav_path, sr=None)\n        assert loaded_sr == sr, \"sample rate does not match, resampling applied\"\n\n        # Pad audio to the right size.\n        frames = int(np.ceil(float(wav.size) / hop_length))\n        fft_padding = (n_fft - hop_length) // 2  # sound\n        desired_length = frames * hop_length + fft_padding * 2\n        pad_amount = (desired_length - wav.size) // 2\n\n        if wav.size % 2 == 0:\n            wav = np.pad(wav, (pad_amount, pad_amount), mode='reflect')\n        else:\n            wav = np.pad(wav, (pad_amount, pad_amount + 1), mode='reflect')\n\n        # Normalize audio.\n        wav = wav / np.abs(wav).max() * 0.999\n\n        # Compute mel-spectrogram.\n        # Turn center to False to prevent internal padding.\n        spectrogram = librosa.core.stft(\n            wav,\n            hop_length=hop_length,\n            win_length=win_length,\n            n_fft=n_fft,\n            center=False)\n        spectrogram_magnitude = np.abs(spectrogram)\n\n        # Compute mel-spectrograms.\n        mel_filter_bank = librosa.filters.mel(\n            sr=sr, n_fft=n_fft, n_mels=n_mels, fmin=fmin, fmax=fmax)\n        mel_spectrogram = np.dot(mel_filter_bank, spectrogram_magnitude)\n\n        # log scale mel_spectrogram.\n        mel_spectrogram = self.spec_normalizer.transform(mel_spectrogram)\n\n        # Extract the center of audio that corresponds to mel spectrograms.\n        audio = wav[fft_padding:-fft_padding]\n        assert mel_spectrogram.shape[1] * hop_length == audio.size\n\n        # there is no clipping here\n        return audio, mel_spectrogram\n\n\ndef create_dataset(config, input_dir, output_dir):\n    input_dir = Path(input_dir).expanduser()\n    dataset = LJSpeechMetaData(input_dir)\n\n    output_dir = Path(output_dir).expanduser()\n    output_dir.mkdir(exist_ok=True)\n\n    transform = Transform(config.sample_rate, config.n_fft, config.win_length,\n                          config.hop_length, config.n_mels, config.fmin,\n                          config.fmax)\n    file_names = []\n\n    for example in tqdm.tqdm(dataset):\n        fname, _, _ = example\n        base_name = os.path.splitext(os.path.basename(fname))[0]\n        wav_dir = output_dir / \"wav\"\n        mel_dir = output_dir / \"mel\"\n        wav_dir.mkdir(exist_ok=True)\n        mel_dir.mkdir(exist_ok=True)\n\n        audio, mel = transform(example)\n        np.save(str(wav_dir / base_name), audio)\n        np.save(str(mel_dir / base_name), mel)\n\n        file_names.append((base_name, mel.shape[-1], audio.shape[-1]))\n\n    meta_data = pd.DataFrame.from_records(file_names)\n    meta_data.to_csv(\n        str(output_dir / \"metadata.csv\"), sep=\"\\t\", index=None, header=None)\n    print(\"saved meta data in to {}\".format(\n        os.path.join(output_dir, \"metadata.csv\")))\n\n    print(\"Done!\")\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"create dataset\")\n    parser.add_argument(\n        \"--config\",\n        type=str,\n        metavar=\"FILE\",\n        help=\"extra config to overwrite the default config\")\n    parser.add_argument(\n        \"--input\", type=str, help=\"path of the ljspeech dataset\")\n    parser.add_argument(\n        \"--output\", type=str, help=\"path to save output dataset\")\n    parser.add_argument(\n        \"--opts\",\n        nargs=argparse.REMAINDER,\n        help=\"options to overwrite --config file and the default config, passing in KEY VALUE pairs\"\n    )\n\n    config = get_cfg_defaults()\n    args = parser.parse_args()\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n\n    create_dataset(config.data, args.input, args.output)\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/synthesize.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport soundfile as sf\n\nfrom paddlespeech.t2s.exps.waveflow.config import get_cfg_defaults\nfrom paddlespeech.t2s.models.waveflow import ConditionalWaveFlow\nfrom paddlespeech.t2s.utils import layer_tools\n\n\ndef main(config, args):\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    model = ConditionalWaveFlow.from_pretrained(config, args.checkpoint_path)\n    layer_tools.recursively_remove_weight_norm(model)\n    model.eval()\n\n    mel_dir = Path(args.input).expanduser()\n    output_dir = Path(args.output).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n    for file_path in mel_dir.glob(\"*.npy\"):\n        mel = np.load(str(file_path))\n        with paddle.amp.auto_cast():\n            audio = model.predict(mel)\n        audio_path = output_dir / (os.path.splitext(file_path.name)[0] + \".wav\")\n        sf.write(audio_path, audio, config.data.sample_rate)\n        print(\"[synthesize] {} -> {}\".format(file_path, audio_path))\n\n\nif __name__ == \"__main__\":\n    config = get_cfg_defaults()\n\n    parser = argparse.ArgumentParser(\n        description=\"generate mel spectrogram with TransformerTTS.\")\n    parser.add_argument(\n        \"--config\",\n        type=str,\n        metavar=\"FILE\",\n        help=\"extra config to overwrite the default config\")\n    parser.add_argument(\n        \"--checkpoint_path\", type=str, help=\"path of the checkpoint to load.\")\n    parser.add_argument(\n        \"--input\",\n        type=str,\n        help=\"path of directory containing mel spectrogram (in .npy format)\")\n    parser.add_argument(\"--output\", type=str, help=\"path to save outputs\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n    parser.add_argument(\n        \"--opts\",\n        nargs=argparse.REMAINDER,\n        help=\"options to overwrite --config file and the default config, passing in KEY VALUE pairs\"\n    )\n\n    args = parser.parse_args()\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    print(args)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/t2s/exps/waveflow/train.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\n\nimport numpy as np\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\n\nfrom paddlespeech.t2s.datasets import dataset\nfrom paddlespeech.t2s.exps.waveflow.config import get_cfg_defaults\nfrom paddlespeech.t2s.exps.waveflow.ljspeech import LJSpeech\nfrom paddlespeech.t2s.exps.waveflow.ljspeech import LJSpeechClipCollector\nfrom paddlespeech.t2s.exps.waveflow.ljspeech import LJSpeechCollector\nfrom paddlespeech.t2s.models.waveflow import ConditionalWaveFlow\nfrom paddlespeech.t2s.models.waveflow import WaveFlowLoss\nfrom paddlespeech.t2s.training.cli import default_argument_parser\nfrom paddlespeech.t2s.training.experiment import ExperimentBase\nfrom paddlespeech.t2s.utils import mp_tools\n\n\nclass Experiment(ExperimentBase):\n    def setup_model(self):\n        config = self.config\n        model = ConditionalWaveFlow(\n            upsample_factors=config.model.upsample_factors,\n            n_flows=config.model.n_flows,\n            n_layers=config.model.n_layers,\n            n_group=config.model.n_group,\n            channels=config.model.channels,\n            n_mels=config.data.n_mels,\n            kernel_size=config.model.kernel_size)\n\n        if self.parallel:\n            model = paddle.DataParallel(model)\n        optimizer = paddle.optimizer.Adam(\n            config.training.lr, parameters=model.parameters())\n        criterion = WaveFlowLoss(sigma=config.model.sigma)\n\n        self.model = model\n        self.optimizer = optimizer\n        self.criterion = criterion\n\n    def setup_dataloader(self):\n        config = self.config\n        args = self.args\n\n        ljspeech_dataset = LJSpeech(args.data)\n        valid_set, train_set = dataset.split(ljspeech_dataset,\n                                             config.data.valid_size)\n\n        batch_fn = LJSpeechClipCollector(config.data.clip_frames,\n                                         config.data.hop_length)\n\n        if not self.parallel:\n            train_loader = DataLoader(\n                train_set,\n                batch_size=config.data.batch_size,\n                shuffle=True,\n                drop_last=True,\n                collate_fn=batch_fn)\n        else:\n            sampler = DistributedBatchSampler(\n                train_set,\n                batch_size=config.data.batch_size,\n                num_replicas=dist.get_world_size(),\n                rank=dist.get_rank(),\n                shuffle=True,\n                drop_last=True)\n            train_loader = DataLoader(\n                train_set, batch_sampler=sampler, collate_fn=batch_fn)\n\n        valid_batch_fn = LJSpeechCollector()\n        valid_loader = DataLoader(\n            valid_set, batch_size=1, collate_fn=valid_batch_fn)\n\n        self.train_loader = train_loader\n        self.valid_loader = valid_loader\n\n    def compute_outputs(self, mel, wav):\n        # model_core = model._layers if isinstance(model, paddle.DataParallel) else model\n        z, log_det_jocobian = self.model(wav, mel)\n        return z, log_det_jocobian\n\n    def train_batch(self):\n        start = time.time()\n        batch = self.read_batch()\n        data_loader_time = time.time() - start\n\n        self.model.train()\n        self.optimizer.clear_grad()\n        mel, wav = batch\n        z, log_det_jocobian = self.compute_outputs(mel, wav)\n        loss = self.criterion(z, log_det_jocobian)\n        loss.backward()\n        self.optimizer.step()\n        iteration_time = time.time() - start\n\n        loss_value = float(loss)\n        msg = \"Rank: {}, \".format(dist.get_rank())\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"time: {:>.3f}s/{:>.3f}s, \".format(data_loader_time,\n                                                  iteration_time)\n        msg += \"loss: {:>.6f}\".format(loss_value)\n        self.logger.info(msg)\n        if dist.get_rank() == 0:\n            self.visualizer.add_scalar(\"train/loss\", loss_value, self.iteration)\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def valid(self):\n        valid_iterator = iter(self.valid_loader)\n        valid_losses = []\n        mel, wav = next(valid_iterator)\n        z, log_det_jocobian = self.compute_outputs(mel, wav)\n        loss = self.criterion(z, log_det_jocobian)\n        valid_losses.append(float(loss))\n        valid_loss = np.mean(valid_losses)\n        self.visualizer.add_scalar(\"valid/loss\", valid_loss, self.iteration)\n\n\ndef main_sp(config, args):\n    exp = Experiment(config, args)\n    exp.setup()\n    exp.resume_or_load()\n    exp.run()\n\n\ndef main(config, args):\n    if args.ngpu > 1:\n        dist.spawn(main_sp, args=(config, args), nprocs=args.ngpu)\n    else:\n        main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    config = get_cfg_defaults()\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    print(args)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/t2s/exps/wavernn/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/exps/wavernn/synthesize.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport soundfile as sf\nimport yaml\nfrom paddle import distributed as dist\nfrom timer import timer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.models.wavernn import WaveRNN\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Synthesize with WaveRNN.\")\n\n    parser.add_argument(\"--config\", type=str, help=\"Vocoder config file.\")\n    parser.add_argument(\"--checkpoint\", type=str, help=\"snapshot to load.\")\n    parser.add_argument(\"--test-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    model = WaveRNN(**config[\"model\"])\n    state_dict = paddle.load(args.checkpoint)\n    model.set_state_dict(state_dict[\"main_params\"])\n\n    model.eval()\n\n    with jsonlines.open(args.test_metadata, 'r') as reader:\n        metadata = list(reader)\n    test_dataset = DataTable(\n        metadata,\n        fields=['utt_id', 'feats'],\n        converters={\n            'utt_id': None,\n            'feats': np.load,\n        })\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    N = 0\n    T = 0\n    for example in test_dataset:\n        utt_id = example['utt_id']\n        mel = example['feats']\n        mel = paddle.to_tensor(mel)  # (T, C)\n        with timer() as t:\n            with paddle.no_grad():\n                wav = model.generate(\n                    c=mel,\n                    batched=config.inference.gen_batched,\n                    target=config.inference.target,\n                    overlap=config.inference.overlap,\n                    mu_law=config.mu_law,\n                    gen_display=False)\n            wav = wav.numpy()\n            N += wav.size\n            T += t.elapse\n            speed = wav.size / t.elapse\n            rtf = config.fs / speed\n        print(\n            f\"{utt_id}, mel: {mel.shape}, wave: {wav.shape}, time: {t.elapse}s, Hz: {speed}, RTF: {rtf}.\"\n        )\n        sf.write(str(output_dir / (utt_id + \".wav\")), wav, samplerate=config.fs)\n    print(f\"generation speed: {N / T}Hz, RTF: {config.fs / (N / T) }\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/exps/wavernn/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport jsonlines\nimport numpy as np\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.optimizer import Adam\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.datasets.data_table import DataTable\nfrom paddlespeech.t2s.datasets.vocoder_batch_fn import WaveRNNClip\nfrom paddlespeech.t2s.models.wavernn import WaveRNN\nfrom paddlespeech.t2s.models.wavernn import WaveRNNEvaluator\nfrom paddlespeech.t2s.models.wavernn import WaveRNNUpdater\nfrom paddlespeech.t2s.modules.losses import discretized_mix_logistic_loss\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    world_size = paddle.distributed.get_world_size()\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n        if world_size > 1:\n            paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank: {dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\",\n    )\n\n    # construct dataset for training and validation\n    with jsonlines.open(args.train_metadata, 'r') as reader:\n        train_metadata = list(reader)\n    train_dataset = DataTable(\n        data=train_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    with jsonlines.open(args.dev_metadata, 'r') as reader:\n        dev_metadata = list(reader)\n    dev_dataset = DataTable(\n        data=dev_metadata,\n        fields=[\"wave\", \"feats\"],\n        converters={\n            \"wave\": np.load,\n            \"feats\": np.load,\n        }, )\n\n    batch_fn = WaveRNNClip(\n        mode=config.model.mode,\n        aux_context_window=config.model.aux_context_window,\n        hop_size=config.n_shift,\n        batch_max_steps=config.batch_max_steps,\n        bits=config.model.bits)\n\n    # collate function and dataloader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=True)\n    dev_sampler = DistributedBatchSampler(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    print(\"samplers done!\")\n\n    train_dataloader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        collate_fn=batch_fn,\n        num_workers=config.num_workers)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        collate_fn=batch_fn,\n        batch_sampler=dev_sampler,\n        num_workers=config.num_workers)\n\n    valid_generate_loader = DataLoader(dev_dataset, batch_size=1)\n\n    print(\"dataloaders done!\")\n\n    model = WaveRNN(\n        hop_length=config.n_shift, sample_rate=config.fs, **config[\"model\"])\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    if config.model.mode == 'RAW':\n        criterion = paddle.nn.CrossEntropyLoss(axis=1)\n    elif config.model.mode == 'MOL':\n        criterion = discretized_mix_logistic_loss\n    else:\n        criterion = None\n        RuntimeError('Unknown model mode value - ', config.model.mode)\n    print(\"criterions done!\")\n    clip = paddle.nn.ClipGradByGlobalNorm(config.grad_clip)\n    optimizer = Adam(\n        parameters=model.parameters(),\n        learning_rate=config.learning_rate,\n        grad_clip=clip)\n\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = WaveRNNUpdater(\n        model=model,\n        optimizer=optimizer,\n        criterion=criterion,\n        dataloader=train_dataloader,\n        output_dir=output_dir,\n        mode=config.model.mode)\n\n    evaluator = WaveRNNEvaluator(\n        model=model,\n        dataloader=dev_dataloader,\n        criterion=criterion,\n        output_dir=output_dir,\n        valid_generate_loader=valid_generate_loader,\n        config=config)\n\n    trainer = Trainer(\n        updater,\n        stop_trigger=(config.train_max_steps, \"iteration\"),\n        out=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(\n            evaluator, trigger=(config.eval_interval_steps, 'iteration'))\n        trainer.extend(VisualDL(output_dir), trigger=(1, 'iteration'))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots),\n        trigger=(config.save_interval_steps, 'iteration'))\n\n    print(\"Trainer Done!\")\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n\n    parser = argparse.ArgumentParser(description=\"Train a WaveRNN model.\")\n    parser.add_argument(\"--config\", type=str, help=\"WaveRNN config file.\")\n    parser.add_argument(\"--train-metadata\", type=str, help=\"training data.\")\n    parser.add_argument(\"--dev-metadata\", type=str, help=\"dev data.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config, 'rt') as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .generate_lexicon import *\nfrom .normalizer import *\nfrom .punctuation import *\nfrom .ssml import *\nfrom .tone_sandhi import *\nfrom .vocab import *\nfrom .zh_normalization import *\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/arpabet.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nA phonology system with ARPABET symbols and limited punctuations. The G2P \nconversion is done by g2p_en.\n\nNote that g2p_en does not handle words with hypen well. So make sure the input\nsentence is first normalized.\n\"\"\"\nfrom g2p_en import G2p\n\nfrom paddlespeech.t2s.frontend.phonectic import Phonetics\nfrom paddlespeech.t2s.frontend.vocab import Vocab\n\n\nclass ARPABET(Phonetics):\n    \"\"\"A phonology for English that uses ARPABET without stress as the phoneme vocabulary.\n\n    47 symbols = 39 phones + 4 punctuations + 4 special tokens(<pad> <unk> <s> </s>)\n\n    The current phoneme set contains 39 phonemes, vowels carry a lexical stress marker:\n        0    — No stress\n        1    — Primary stress\n        2    — Secondary stress\n\n    Phoneme Set:\n        Phoneme Example Translation\n            ------- ------- -----------\n            AA\todd     AA D\n            AE\tat\tAE T\n            AH\thut\tHH AH T\n            AO\tought\tAO T\n            AW\tcow\tK AW\n            AY\thide\tHH AY D\n            B \tbe\tB IY\n            CH\tcheese\tCH IY Z\n            D \tdee\tD IY\n            DH\tthee\tDH IY\n            EH\tEd\tEH D\n            ER\thurt\tHH ER T\n            EY\tate\tEY T\n            F \tfee\tF IY\n            G \tgreen\tG R IY N\n            HH\the\tHH IY\n            IH\tit\tIH T\n            IY\teat\tIY T\n            JH\tgee\tJH IY\n            K \tkey\tK IY\n            L \tlee\tL IY\n            M \tme\tM IY\n            N \tknee\tN IY\n            NG\tping\tP IH NG\n            OW\toat\tOW T\n            OY\ttoy\tT OY\n            P \tpee\tP IY\n            R \tread\tR IY D\n            S \tsea\tS IY\n            SH\tshe\tSH IY\n            T \ttea\tT IY\n            TH\ttheta\tTH EY T AH\n            UH\thood\tHH UH D\n            UW\ttwo\tT UW\n            V \tvee\tV IY\n            W \twe\tW IY\n            Y \tyield\tY IY L D\n            Z \tzee\tZ IY\n            ZH\tseizure\tS IY ZH ER\n\n    See http://www.speech.cs.cmu.edu/cgi-bin/cmudict for more details.\n    \"\"\"\n    # 39 phonemes\n    phonemes = [\n        'AA', 'AE', 'AH', 'AO', 'AW', 'AY', 'B', 'CH', 'D', 'DH', 'EH', 'ER',\n        'EY', 'F', 'G', 'HH', 'IH', 'IY', 'JH', 'K', 'L', 'M', 'N', 'NG', 'OW',\n        'OY', 'P', 'R', 'S', 'SH', 'T', 'TH', 'UW', 'UH', 'V', 'W', 'Y', 'Z',\n        'ZH'\n    ]\n    punctuations = [',', '.', '?', '!']\n    symbols = phonemes + punctuations\n    # vowels carry a lexical stress marker：\n    # 0 unstressed（无重音）, 1 primary stress（主重音）和 2 secondary stress（次重音）\n    _stress_to_no_stress_ = {\n        'AA0': 'AA',\n        'AA1': 'AA',\n        'AA2': 'AA',\n        'AE0': 'AE',\n        'AE1': 'AE',\n        'AE2': 'AE',\n        'AH0': 'AH',\n        'AH1': 'AH',\n        'AH2': 'AH',\n        'AO0': 'AO',\n        'AO1': 'AO',\n        'AO2': 'AO',\n        'AW0': 'AW',\n        'AW1': 'AW',\n        'AW2': 'AW',\n        'AY0': 'AY',\n        'AY1': 'AY',\n        'AY2': 'AY',\n        'EH0': 'EH',\n        'EH1': 'EH',\n        'EH2': 'EH',\n        'ER0': 'ER',\n        'ER1': 'ER',\n        'ER2': 'ER',\n        'EY0': 'EY',\n        'EY1': 'EY',\n        'EY2': 'EY',\n        'IH0': 'IH',\n        'IH1': 'IH',\n        'IH2': 'IH',\n        'IY0': 'IY',\n        'IY1': 'IY',\n        'IY2': 'IY',\n        'OW0': 'OW',\n        'OW1': 'OW',\n        'OW2': 'OW',\n        'OY0': 'OY',\n        'OY1': 'OY',\n        'OY2': 'OY',\n        'UH0': 'UH',\n        'UH1': 'UH',\n        'UH2': 'UH',\n        'UW0': 'UW',\n        'UW1': 'UW',\n        'UW2': 'UW'\n    }\n\n    def __repr__(self):\n        fmt = \"ARPABETWithoutStress(phonemes: {}, punctuations: {})\"\n        return fmt.format(len(phonemes), punctuations)\n\n    def __init__(self):\n        # https://github.com/Kyubyong/g2p/blob/master/g2p_en/g2p.py\n        self.backend = G2p()\n        self.vocab = Vocab(self.phonemes + self.punctuations)\n\n    def _remove_vowels(self, phone):\n        return self._stress_to_no_stress_.get(phone, phone)\n\n    def phoneticize(self, sentence, add_start_end=False):\n        \"\"\" Normalize the input text sequence and convert it into pronunciation sequence.\n        Args:\n            sentence (str): The input text sequence.\n    \n        Returns:\n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        # g2p and remove vowel stress\n        phonemes = [\n            self._remove_vowels(item) for item in self.backend(sentence)\n        ]\n        if add_start_end:\n            start = self.vocab.start_symbol\n            end = self.vocab.end_symbol\n            phonemes = [start] + phonemes + [end]\n        phonemes = [item for item in phonemes if item in self.vocab.stoi]\n        return phonemes\n\n    def numericalize(self, phonemes):\n        \"\"\" Convert pronunciation sequence into pronunciation id sequence.\n\n        Args:\n            phonemes (List[str]): The list of pronunciation sequence.\n    \n        Returns:\n            List[int]: The list of pronunciation id sequence.\n        \"\"\"\n        # phonemes to ids\n        ids = [self.vocab.lookup(item) for item in phonemes]\n        return ids\n\n    def reverse(self, ids):\n        \"\"\" Reverse the list of pronunciation id sequence to a list of pronunciation sequence.\n        \n        Args:\n            ids( List[int]): The list of pronunciation id sequence.\n    \n        Returns: \n            List[str]: \n                The list of pronunciation sequence.\n        \"\"\"\n        return [self.vocab.reverse(i) for i in ids]\n\n    def __call__(self, sentence, add_start_end=False):\n        \"\"\" Convert the input text sequence into pronunciation id sequence.\n    \n        Args:\n            sentence (str): The input text sequence.\n    \n        Returns:\n            List[str]: The list of pronunciation id sequence.\n        \"\"\"\n        return self.numericalize(\n            self.phoneticize(sentence, add_start_end=add_start_end))\n\n    @property\n    def vocab_size(self):\n        \"\"\" Vocab size.\n        \"\"\"\n        # 47 = 39 phones + 4 punctuations + 4 special tokens(<pad> <unk> <s> </s>)\n        return len(self.vocab)\n\n\nclass ARPABETWithStress(Phonetics):\n    \"\"\"\n    A phonology for English that uses ARPABET with stress as the phoneme vocabulary.\n\n    77 symbols = 69 phones + 4 punctuations + 4 special tokens\n    \"\"\"\n    phonemes = [\n        'AA0', 'AA1', 'AA2', 'AE0', 'AE1', 'AE2', 'AH0', 'AH1', 'AH2', 'AO0',\n        'AO1', 'AO2', 'AW0', 'AW1', 'AW2', 'AY0', 'AY1', 'AY2', 'B', 'CH', 'D',\n        'DH', 'EH0', 'EH1', 'EH2', 'ER0', 'ER1', 'ER2', 'EY0', 'EY1', 'EY2',\n        'F', 'G', 'HH', 'IH0', 'IH1', 'IH2', 'IY0', 'IY1', 'IY2', 'JH', 'K',\n        'L', 'M', 'N', 'NG', 'OW0', 'OW1', 'OW2', 'OY0', 'OY1', 'OY2', 'P', 'R',\n        'S', 'SH', 'T', 'TH', 'UH0', 'UH1', 'UH2', 'UW0', 'UW1', 'UW2', 'V',\n        'W', 'Y', 'Z', 'ZH'\n    ]\n    punctuations = [',', '.', '?', '!']\n    symbols = phonemes + punctuations\n\n    def __repr__(self):\n        fmt = \"ARPABETWithStress(phonemes: {}, punctuations: {})\"\n        return fmt.format(len(phonemes), punctuations)\n\n    def __init__(self):\n        self.backend = G2p()\n        self.vocab = Vocab(self.phonemes + self.punctuations)\n\n    def phoneticize(self, sentence, add_start_end=False):\n        \"\"\" Normalize the input text sequence and convert it into pronunciation sequence.\n    \n        Args: \n            sentence (str): The input text sequence.\n    \n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        phonemes = self.backend(sentence)\n        if add_start_end:\n            start = self.vocab.start_symbol\n            end = self.vocab.end_symbol\n            phonemes = [start] + phonemes + [end]\n        phonemes = [item for item in phonemes if item in self.vocab.stoi]\n        return phonemes\n\n    def numericalize(self, phonemes):\n        \"\"\" Convert pronunciation sequence into pronunciation id sequence.\n\n        Args:\n            phonemes (List[str]): The list of pronunciation sequence.\n    \n        Returns:\n            List[int]: The list of pronunciation id sequence.\n        \"\"\"\n        ids = [self.vocab.lookup(item) for item in phonemes]\n        return ids\n\n    def reverse(self, ids):\n        \"\"\" Reverse the list of pronunciation id sequence to a list of pronunciation sequence.\n        Args:\n            ids (List[int]): The list of pronunciation id sequence.\n    \n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        return [self.vocab.reverse(i) for i in ids]\n\n    def __call__(self, sentence, add_start_end=False):\n        \"\"\" Convert the input text sequence into pronunciation id sequence.\n        Args:\n            sentence (str): The input text sequence.\n    \n        Returns: \n            List[str]: The list of pronunciation id sequence.\n        \"\"\"\n        return self.numericalize(\n            self.phoneticize(sentence, add_start_end=add_start_end))\n\n    @property\n    def vocab_size(self):\n        \"\"\" Vocab size.\n        \"\"\"\n        # 77 = 69 phones + 4 punctuations + 4 special tokens\n        return len(self.vocab)\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/canton_frontend.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Dict\nfrom typing import List\n\nimport numpy as np\nimport paddle\nimport ToJyutping\n\nfrom paddlespeech.t2s.frontend.zh_normalization.text_normlization import TextNormalizer\n\nINITIALS = [\n    'aa', 'aai', 'aak', 'aap', 'aat', 'aau', 'ai', 'au', 'ap', 'at', 'ak', 'a',\n    'p', 'b', 'e', 'ts', 't', 'dz', 'd', 'kw', 'k', 'gw', 'g', 'f', 'h', 'l',\n    'm', 'ng', 'n', 's', 'y', 'w', 'c', 'z', 'j', 'ong', 'on', 'ou', 'oi', 'ok',\n    'o', 'uk', 'ung'\n]\nINITIALS += ['sp', 'spl', 'spn', 'sil']\n\n\ndef jyuping_to_phonemes(cantons: List[str]):\n    # jyuping to inital and final\n    phones = []\n    for canton in cantons:\n        for consonant in INITIALS:\n            if canton.startswith(consonant):\n                if canton.startswith(\"nga\"):\n                    c, v = canton[:len(consonant)], canton[len(consonant):]\n                    phones = phones + [canton[2:]]\n                else:\n                    c, v = canton[:len(consonant)], canton[len(consonant):]\n                    phones = phones + [c, v]\n                break\n    return phones\n\n\nclass CantonFrontend():\n    def __init__(self, phone_vocab_path: str):\n        self.text_normalizer = TextNormalizer()\n        self.punc = \"、：，；。？！“”‘’':,;.?!\"\n\n        self.vocab_phones = {}\n        if phone_vocab_path:\n            with open(phone_vocab_path, 'rt', encoding='utf-8') as f:\n                phn_id = [line.strip().split() for line in f.readlines()]\n            for phn, id in phn_id:\n                self.vocab_phones[phn] = int(id)\n\n    # if merge_sentences, merge all sentences into one phone sequence\n    def _g2p(self, sentences: List[str],\n             merge_sentences: bool=True) -> List[List[str]]:\n        phones_list = []\n        for sentence in sentences:\n            # jyuping\n            # 'gam3 ngaam1 lou5 sai3 jiu1 kau4 keoi5 dang2 zan6 jiu3 hoi1 wui2, zing6 dai1 ge2 je5 ngo5 wui5 gaau2 dim6 ga3 laa3.'\n            phones_str = ToJyutping.get_jyutping_text(sentence)\n            # phonemes \n            phones_split = jyuping_to_phonemes(phones_str.split(' '))\n            phones_list.append(phones_split)\n        return phones_list\n\n    def _p2id(self, phonemes: List[str]) -> np.ndarray:\n        # replace unk phone with sp\n        phonemes = [\n            phn if phn in self.vocab_phones else \"sp\" for phn in phonemes\n        ]\n        phone_ids = [self.vocab_phones[item] for item in phonemes]\n        return np.array(phone_ids, np.int64)\n\n    def get_phonemes(self,\n                     sentence: str,\n                     merge_sentences: bool=True,\n                     print_info: bool=False) -> List[List[str]]:\n        # TN & Text Segmentation\n        sentences = self.text_normalizer.normalize(sentence)\n        # G2P\n        phonemes = self._g2p(sentences, merge_sentences=merge_sentences)\n\n        if print_info:\n            print(\"----------------------------\")\n            print(\"text norm results:\")\n            print(sentences)\n            print(\"----------------------------\")\n            print(\"g2p results:\")\n            print(phonemes)\n            print(\"----------------------------\")\n\n        return phonemes\n\n    def get_input_ids(self,\n                      sentence: str,\n                      merge_sentences: bool=True,\n                      print_info: bool=False,\n                      to_tensor: bool=True) -> Dict[str, List[paddle.Tensor]]:\n\n        phonemes = self.get_phonemes(\n            sentence, merge_sentences=merge_sentences, print_info=print_info)\n\n        result = {}\n        temp_phone_ids = []\n        for phones in phonemes:\n            if phones:\n                phone_ids = self._p2id(phones)\n                # if use paddle.to_tensor() in onnxruntime, the first time will be too low\n                if to_tensor:\n                    phone_ids = paddle.to_tensor(phone_ids)\n                temp_phone_ids.append(phone_ids)\n\n        if temp_phone_ids:\n            result[\"phone_ids\"] = temp_phone_ids\n\n        return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/en_frontend.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n#     http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\nfrom .phonectic import English\r\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/g2pw/__init__.py",
    "content": "from .onnx_api import G2PWOnnxConverter\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/g2pw/dataset.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCredits\n    This code is modified from https://github.com/GitYCC/g2pW\n\"\"\"\nfrom typing import Dict\nfrom typing import List\nfrom typing import Tuple\n\nimport numpy as np\n\nfrom paddlespeech.t2s.frontend.g2pw.utils import tokenize_and_map\n\nANCHOR_CHAR = '▁'\n\n\ndef prepare_onnx_input(tokenizer,\n                       labels: List[str],\n                       char2phonemes: Dict[str, List[int]],\n                       chars: List[str],\n                       texts: List[str],\n                       query_ids: List[int],\n                       use_mask: bool=False,\n                       window_size: int=None,\n                       max_len: int=512) -> Dict[str, np.array]:\n    if window_size is not None:\n        truncated_texts, truncated_query_ids = _truncate_texts(\n            window_size=window_size, texts=texts, query_ids=query_ids)\n    input_ids = []\n    token_type_ids = []\n    attention_masks = []\n    phoneme_masks = []\n    char_ids = []\n    position_ids = []\n\n    for idx in range(len(texts)):\n        text = (truncated_texts if window_size else texts)[idx].lower()\n        query_id = (truncated_query_ids if window_size else query_ids)[idx]\n\n        try:\n            tokens, text2token, token2text = tokenize_and_map(\n                tokenizer=tokenizer, text=text)\n        except Exception:\n            print(f'warning: text \"{text}\" is invalid')\n            return {}\n\n        text, query_id, tokens, text2token, token2text = _truncate(\n            max_len=max_len,\n            text=text,\n            query_id=query_id,\n            tokens=tokens,\n            text2token=text2token,\n            token2text=token2text)\n\n        processed_tokens = ['[CLS]'] + tokens + ['[SEP]']\n\n        input_id = list(\n            np.array(tokenizer.convert_tokens_to_ids(processed_tokens)))\n        token_type_id = list(np.zeros((len(processed_tokens), ), dtype=int))\n        attention_mask = list(np.ones((len(processed_tokens), ), dtype=int))\n\n        query_char = text[query_id]\n        phoneme_mask = [1 if i in char2phonemes[query_char] else 0 for i in range(len(labels))] \\\n            if use_mask else [1] * len(labels)\n        char_id = chars.index(query_char)\n        position_id = text2token[\n            query_id] + 1  # [CLS] token locate at first place\n\n        input_ids.append(input_id)\n        token_type_ids.append(token_type_id)\n        attention_masks.append(attention_mask)\n        phoneme_masks.append(phoneme_mask)\n        char_ids.append(char_id)\n        position_ids.append(position_id)\n\n    outputs = {\n        'input_ids': np.array(input_ids).astype(np.int64),\n        'token_type_ids': np.array(token_type_ids).astype(np.int64),\n        'attention_masks': np.array(attention_masks).astype(np.int64),\n        'phoneme_masks': np.array(phoneme_masks).astype(np.float32),\n        'char_ids': np.array(char_ids).astype(np.int64),\n        'position_ids': np.array(position_ids).astype(np.int64),\n    }\n    return outputs\n\n\ndef _truncate_texts(window_size: int, texts: List[str],\n                    query_ids: List[int]) -> Tuple[List[str], List[int]]:\n    truncated_texts = []\n    truncated_query_ids = []\n    for text, query_id in zip(texts, query_ids):\n        start = max(0, query_id - window_size // 2)\n        end = min(len(text), query_id + window_size // 2)\n        truncated_text = text[start:end]\n        truncated_texts.append(truncated_text)\n\n        truncated_query_id = query_id - start\n        truncated_query_ids.append(truncated_query_id)\n    return truncated_texts, truncated_query_ids\n\n\ndef _truncate(max_len: int,\n              text: str,\n              query_id: int,\n              tokens: List[str],\n              text2token: List[int],\n              token2text: List[Tuple[int]]):\n    truncate_len = max_len - 2\n    if len(tokens) <= truncate_len:\n        return (text, query_id, tokens, text2token, token2text)\n\n    token_position = text2token[query_id]\n\n    token_start = token_position - truncate_len // 2\n    token_end = token_start + truncate_len\n    font_exceed_dist = -token_start\n    back_exceed_dist = token_end - len(tokens)\n    if font_exceed_dist > 0:\n        token_start += font_exceed_dist\n        token_end += font_exceed_dist\n    elif back_exceed_dist > 0:\n        token_start -= back_exceed_dist\n        token_end -= back_exceed_dist\n\n    start = token2text[token_start][0]\n    end = token2text[token_end - 1][1]\n\n    return (text[start:end], query_id - start, tokens[token_start:token_end], [\n        i - token_start if i is not None else None\n        for i in text2token[start:end]\n    ], [(s - start, e - start) for s, e in token2text[token_start:token_end]])\n\n\ndef get_phoneme_labels(polyphonic_chars: List[List[str]]\n                       ) -> Tuple[List[str], Dict[str, List[int]]]:\n    labels = sorted(list(set([phoneme for char, phoneme in polyphonic_chars])))\n    char2phonemes = {}\n    for char, phoneme in polyphonic_chars:\n        if char not in char2phonemes:\n            char2phonemes[char] = []\n        char2phonemes[char].append(labels.index(phoneme))\n    return labels, char2phonemes\n\n\ndef get_char_phoneme_labels(polyphonic_chars: List[List[str]]\n                            ) -> Tuple[List[str], Dict[str, List[int]]]:\n    labels = sorted(\n        list(set([f'{char} {phoneme}' for char, phoneme in polyphonic_chars])))\n    char2phonemes = {}\n    for char, phoneme in polyphonic_chars:\n        if char not in char2phonemes:\n            char2phonemes[char] = []\n        char2phonemes[char].append(labels.index(f'{char} {phoneme}'))\n    return labels, char2phonemes\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/g2pw/onnx_api.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCredits\n    This code is modified from https://github.com/GitYCC/g2pW\n\"\"\"\nimport json\nimport os\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Tuple\n\nimport numpy as np\nimport onnxruntime\nfrom opencc import OpenCC\nfrom paddlenlp.transformers import BertTokenizer\nfrom pypinyin import pinyin\nfrom pypinyin import Style\n\nfrom paddlespeech.cli.utils import download_and_decompress\nfrom paddlespeech.resource.pretrained_models import g2pw_onnx_models\nfrom paddlespeech.t2s.frontend.g2pw.dataset import get_char_phoneme_labels\nfrom paddlespeech.t2s.frontend.g2pw.dataset import get_phoneme_labels\nfrom paddlespeech.t2s.frontend.g2pw.dataset import prepare_onnx_input\nfrom paddlespeech.t2s.frontend.g2pw.utils import load_config\nfrom paddlespeech.t2s.frontend.zh_normalization.char_convert import tranditional_to_simplified\nfrom paddlespeech.utils.env import MODEL_HOME\n\nmodel_version = '1.1'\n\n\ndef get_g2pw_model_path(model_dir: os.PathLike, model_version: str) -> str:\n    \"\"\"Resolve the G2PW ONNX model directory path.\n\n    Checks if the model file 'g2pW.onnx' exists in the expected location.\n    If not, downloads and decompresses the model archive\n\n    Args:\n        model_dir (os.PathLike): Base directory to store models (e.g., ~/.paddlespeech).\n        model_version (str): Model version string (e.g., '1.1').\n\n    Returns:\n        str: Path to the model directory containing 'g2pW.onnx'.\n    \"\"\"\n\n    archive_info = g2pw_onnx_models['G2PWModel'][model_version]\n    archive_fname = os.path.basename(\n        archive_info['url'])  # e.g., \"G2PWModel_1.1.zip\"\n    expected_extract_name = os.path.splitext(archive_fname)[\n        0]  # e.g., \"G2PWModel_1.1\"\n    expected_model_dir = os.path.join(model_dir, expected_extract_name)\n    uncompress_path = expected_model_dir\n    onnx_file_path = os.path.join(expected_model_dir, 'g2pW.onnx')\n    if not os.path.isfile(onnx_file_path):\n        uncompress_path = download_and_decompress(archive_info, model_dir)\n    return uncompress_path\n\n\ndef predict(session, onnx_input: Dict[str, Any],\n            labels: List[str]) -> Tuple[List[str], List[float]]:\n    all_preds = []\n    all_confidences = []\n    probs = session.run([], {\n        \"input_ids\": onnx_input['input_ids'],\n        \"token_type_ids\": onnx_input['token_type_ids'],\n        \"attention_mask\": onnx_input['attention_masks'],\n        \"phoneme_mask\": onnx_input['phoneme_masks'],\n        \"char_ids\": onnx_input['char_ids'],\n        \"position_ids\": onnx_input['position_ids']\n    })[0]\n\n    preds = np.argmax(probs, axis=1).tolist()\n    max_probs = []\n    for index, arr in zip(preds, probs.tolist()):\n        max_probs.append(arr[index])\n    all_preds += [labels[pred] for pred in preds]\n    all_confidences += max_probs\n\n    return all_preds, all_confidences\n\n\nclass G2PWOnnxConverter:\n    def __init__(self,\n                 model_dir: os.PathLike=MODEL_HOME,\n                 style: str='bopomofo',\n                 model_source: str=None,\n                 enable_non_tradional_chinese: bool=False):\n        uncompress_path = get_g2pw_model_path(model_dir, model_version)\n\n        sess_options = onnxruntime.SessionOptions()\n        sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL\n        sess_options.execution_mode = onnxruntime.ExecutionMode.ORT_SEQUENTIAL\n        sess_options.intra_op_num_threads = 2\n        self.session_g2pW = onnxruntime.InferenceSession(\n            os.path.join(uncompress_path, 'g2pW.onnx'),\n            sess_options=sess_options)\n        self.config = load_config(\n            config_path=os.path.join(uncompress_path, 'config.py'),\n            use_default=True)\n\n        self.model_source = model_source if model_source else self.config.model_source\n        self.enable_opencc = enable_non_tradional_chinese\n\n        self.tokenizer = BertTokenizer.from_pretrained(self.config.model_source)\n\n        polyphonic_chars_path = os.path.join(uncompress_path,\n                                             'POLYPHONIC_CHARS.txt')\n        monophonic_chars_path = os.path.join(uncompress_path,\n                                             'MONOPHONIC_CHARS.txt')\n        self.polyphonic_chars = [\n            line.split('\\t')\n            for line in open(polyphonic_chars_path, encoding='utf-8').read()\n            .strip().split('\\n')\n        ]\n        self.non_polyphonic = {\n            '一', '不', '和', '咋', '嗲', '剖', '差', '攢', '倒', '難', '奔', '勁', '拗',\n            '肖', '瘙', '誒', '泊', '听', '噢'\n        }\n        self.non_monophonic = {'似', '攢'}\n        self.monophonic_chars = [\n            line.split('\\t')\n            for line in open(monophonic_chars_path, encoding='utf-8').read()\n            .strip().split('\\n')\n        ]\n        self.labels, self.char2phonemes = get_char_phoneme_labels(\n            polyphonic_chars=self.polyphonic_chars\n        ) if self.config.use_char_phoneme else get_phoneme_labels(\n            polyphonic_chars=self.polyphonic_chars)\n\n        self.chars = sorted(list(self.char2phonemes.keys()))\n\n        self.polyphonic_chars_new = set(self.chars)\n        for char in self.non_polyphonic:\n            if char in self.polyphonic_chars_new:\n                self.polyphonic_chars_new.remove(char)\n\n        self.monophonic_chars_dict = {\n            char: phoneme\n            for char, phoneme in self.monophonic_chars\n        }\n        for char in self.non_monophonic:\n            if char in self.monophonic_chars_dict:\n                self.monophonic_chars_dict.pop(char)\n\n        self.pos_tags = [\n            'UNK', 'A', 'C', 'D', 'I', 'N', 'P', 'T', 'V', 'DE', 'SHI'\n        ]\n\n        with open(\n                os.path.join(uncompress_path,\n                             'bopomofo_to_pinyin_wo_tune_dict.json'),\n                'r',\n                encoding='utf-8') as fr:\n            self.bopomofo_convert_dict = json.load(fr)\n        self.style_convert_func = {\n            'bopomofo': lambda x: x,\n            'pinyin': self._convert_bopomofo_to_pinyin,\n        }[style]\n\n        with open(\n                os.path.join(uncompress_path, 'char_bopomofo_dict.json'),\n                'r',\n                encoding='utf-8') as fr:\n            self.char_bopomofo_dict = json.load(fr)\n\n        if self.enable_opencc:\n            self.cc = OpenCC('s2tw')\n\n    def _convert_bopomofo_to_pinyin(self, bopomofo: str) -> str:\n        tone = bopomofo[-1]\n        assert tone in '12345'\n        component = self.bopomofo_convert_dict.get(bopomofo[:-1])\n        if component:\n            return component + tone\n        else:\n            print(f'Warning: \"{bopomofo}\" cannot convert to pinyin')\n            return None\n\n    def __call__(self, sentences: List[str]) -> List[List[str]]:\n        if isinstance(sentences, str):\n            sentences = [sentences]\n\n        if self.enable_opencc:\n            translated_sentences = []\n            for sent in sentences:\n                translated_sent = self.cc.convert(sent)\n                assert len(translated_sent) == len(sent)\n                translated_sentences.append(translated_sent)\n            sentences = translated_sentences\n\n        texts, query_ids, sent_ids, partial_results = self._prepare_data(\n            sentences=sentences)\n        if len(texts) == 0:\n            # sentences no polyphonic words\n            return partial_results\n\n        onnx_input = prepare_onnx_input(\n            tokenizer=self.tokenizer,\n            labels=self.labels,\n            char2phonemes=self.char2phonemes,\n            chars=self.chars,\n            texts=texts,\n            query_ids=query_ids,\n            use_mask=self.config.use_mask,\n            window_size=None)\n\n        preds, confidences = predict(\n            session=self.session_g2pW,\n            onnx_input=onnx_input,\n            labels=self.labels)\n        if self.config.use_char_phoneme:\n            preds = [pred.split(' ')[1] for pred in preds]\n\n        results = partial_results\n        for sent_id, query_id, pred in zip(sent_ids, query_ids, preds):\n            results[sent_id][query_id] = self.style_convert_func(pred)\n\n        return results\n\n    def _prepare_data(\n            self, sentences: List[str]\n    ) -> Tuple[List[str], List[int], List[int], List[List[str]]]:\n        texts, query_ids, sent_ids, partial_results = [], [], [], []\n        for sent_id, sent in enumerate(sentences):\n            # pypinyin works well for Simplified Chinese than Traditional Chinese\n            sent_s = tranditional_to_simplified(sent)\n            pypinyin_result = pinyin(\n                sent_s, neutral_tone_with_five=True, style=Style.TONE3)\n            partial_result = [None] * len(sent)\n            for i, char in enumerate(sent):\n                if char in self.polyphonic_chars_new:\n                    texts.append(sent)\n                    query_ids.append(i)\n                    sent_ids.append(sent_id)\n                elif char in self.monophonic_chars_dict:\n                    partial_result[i] = self.style_convert_func(\n                        self.monophonic_chars_dict[char])\n                elif char in self.char_bopomofo_dict:\n                    partial_result[i] = pypinyin_result[i][0]\n                    # partial_result[i] =  self.style_convert_func(self.char_bopomofo_dict[char][0])\n                else:\n                    partial_result[i] = pypinyin_result[i][0]\n\n            partial_results.append(partial_result)\n        return texts, query_ids, sent_ids, partial_results\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/g2pw/utils.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCredits\n    This code is modified from https://github.com/GitYCC/g2pW\n\"\"\"\nimport os\nimport re\n\n\ndef wordize_and_map(text: str):\n    words = []\n    index_map_from_text_to_word = []\n    index_map_from_word_to_text = []\n    while len(text) > 0:\n        match_space = re.match(r'^ +', text)\n        if match_space:\n            space_str = match_space.group(0)\n            index_map_from_text_to_word += [None] * len(space_str)\n            text = text[len(space_str):]\n            continue\n\n        match_en = re.match(r'^[a-zA-Z0-9]+', text)\n        if match_en:\n            en_word = match_en.group(0)\n\n            word_start_pos = len(index_map_from_text_to_word)\n            word_end_pos = word_start_pos + len(en_word)\n            index_map_from_word_to_text.append((word_start_pos, word_end_pos))\n\n            index_map_from_text_to_word += [len(words)] * len(en_word)\n\n            words.append(en_word)\n            text = text[len(en_word):]\n        else:\n            word_start_pos = len(index_map_from_text_to_word)\n            word_end_pos = word_start_pos + 1\n            index_map_from_word_to_text.append((word_start_pos, word_end_pos))\n\n            index_map_from_text_to_word += [len(words)]\n\n            words.append(text[0])\n            text = text[1:]\n    return words, index_map_from_text_to_word, index_map_from_word_to_text\n\n\ndef tokenize_and_map(tokenizer, text: str):\n    words, text2word, word2text = wordize_and_map(text=text)\n\n    tokens = []\n    index_map_from_token_to_text = []\n    for word, (word_start, word_end) in zip(words, word2text):\n        word_tokens = tokenizer.tokenize(word)\n\n        if len(word_tokens) == 0 or word_tokens == ['[UNK]']:\n            index_map_from_token_to_text.append((word_start, word_end))\n            tokens.append('[UNK]')\n        else:\n            current_word_start = word_start\n            for word_token in word_tokens:\n                word_token_len = len(re.sub(r'^##', '', word_token))\n                index_map_from_token_to_text.append(\n                    (current_word_start, current_word_start + word_token_len))\n                current_word_start = current_word_start + word_token_len\n                tokens.append(word_token)\n\n    index_map_from_text_to_token = text2word\n    for i, (token_start, token_end) in enumerate(index_map_from_token_to_text):\n        for token_pos in range(token_start, token_end):\n            index_map_from_text_to_token[token_pos] = i\n\n    return tokens, index_map_from_text_to_token, index_map_from_token_to_text\n\n\ndef _load_config(config_path: os.PathLike):\n    import importlib.util\n    spec = importlib.util.spec_from_file_location('__init__', config_path)\n    config = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(config)\n    return config\n\n\ndefault_config_dict = {\n    'manual_seed': 1313,\n    'model_source': 'bert-base-chinese',\n    'window_size': 32,\n    'num_workers': 2,\n    'use_mask': True,\n    'use_char_phoneme': False,\n    'use_conditional': True,\n    'param_conditional': {\n        'affect_location': 'softmax',\n        'bias': True,\n        'char-linear': True,\n        'pos-linear': False,\n        'char+pos-second': True,\n        'char+pos-second_lowrank': False,\n        'lowrank_size': 0,\n        'char+pos-second_fm': False,\n        'fm_size': 0,\n        'fix_mode': None,\n        'count_json': 'train.count.json'\n    },\n    'lr': 5e-5,\n    'val_interval': 200,\n    'num_iter': 10000,\n    'use_focal': False,\n    'param_focal': {\n        'alpha': 0.0,\n        'gamma': 0.7\n    },\n    'use_pos': True,\n    'param_pos ': {\n        'weight': 0.1,\n        'pos_joint_training': True,\n        'train_pos_path': 'train.pos',\n        'valid_pos_path': 'dev.pos',\n        'test_pos_path': 'test.pos'\n    }\n}\n\n\ndef load_config(config_path: os.PathLike, use_default: bool=False):\n    config = _load_config(config_path)\n    if use_default:\n        for attr, val in default_config_dict.items():\n            if not hasattr(config, attr):\n                setattr(config, attr, val)\n            elif isinstance(val, dict):\n                d = getattr(config, attr)\n                for dict_k, dict_v in val.items():\n                    if dict_k not in d:\n                        d[dict_k] = dict_v\n    return config\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/generate_lexicon.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Design principles: https://zhuanlan.zhihu.com/p/349600439\n\"\"\"Generate lexicon and symbols for Mandarin Chinese phonology.\nThe lexicon is used for Montreal Force Aligner.\nNote that syllables are used as word in this lexicon. Since syllables rather \nthan words are used in transcriptions produced by `reorganize_baker.py`.\nWe make this choice to better leverage other software for chinese text to \npinyin tools like pypinyin. This is the convention for G2P in Chinese.\n\"\"\"\nimport re\nfrom collections import OrderedDict\n\nINITIALS = [\n    'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'zh', 'ch', 'sh',\n    'r', 'z', 'c', 's', 'j', 'q', 'x'\n]\n\nFINALS = [\n    'a', 'ai', 'ao', 'an', 'ang', 'e', 'er', 'ei', 'en', 'eng', 'o', 'ou',\n    'ong', 'ii', 'iii', 'i', 'ia', 'iao', 'ian', 'iang', 'ie', 'io', 'iou',\n    'iong', 'in', 'ing', 'u', 'ua', 'uai', 'uan', 'uang', 'uei', 'uo', 'uen',\n    'ueng', 'v', 've', 'van', 'vn'\n]\n\nSPECIALS = ['sil', 'sp']\n\n\ndef rule(C, V, R, T):\n    \"\"\"Generate a syllable given the initial, the final, erhua indicator, and tone.\n    Orthographical rules for pinyin are applied. (special case for y, w, ui, un, iu)\n\n    Note that in this system, 'ü' is alway written as 'v' when appeared in phoneme, but converted to \n    'u' in syllables when certain conditions are satisfied.\n\n    'i' is distinguished when appeared in phonemes, and separated into 3 categories, 'i', 'ii' and 'iii'.\n    Erhua is possibly applied to every finals, except for finals that already ends with 'r'.\n    When a syllable is impossible or does not have any characters with this pronunciation, return None\n    to filter it out.\n    \"\"\"\n\n    # 不可拼的音节, ii 只能和 z, c, s 拼\n    if V in [\"ii\"] and (C not in ['z', 'c', 's']):\n        return None\n    # iii 只能和 zh, ch, sh, r 拼\n    if V in ['iii'] and (C not in ['zh', 'ch', 'sh', 'r']):\n        return None\n\n    # 齐齿呼或者撮口呼不能和 f, g, k, h, zh, ch, sh, r, z, c, s\n    if (V not in ['ii', 'iii']) and V[0] in ['i', 'v'] and (\n            C in ['f', 'g', 'k', 'h', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's']):\n        return None\n\n    # 撮口呼只能和 j, q, x l, n 拼\n    if V.startswith(\"v\"):\n        # v, ve 只能和 j ,q , x, n, l 拼\n        if V in ['v', 've']:\n            if C not in ['j', 'q', 'x', 'n', 'l', '']:\n                return None\n        # 其他只能和 j, q, x 拼\n        else:\n            if C not in ['j', 'q', 'x', '']:\n                return None\n\n    # j, q, x 只能和齐齿呼或者撮口呼拼\n    if (C in ['j', 'q', 'x']) and not (\n        (V not in ['ii', 'iii']) and V[0] in ['i', 'v']):\n        return None\n\n    # b, p ,m, f 不能和合口呼拼，除了 u 之外\n    # bm p, m, f 不能和撮口呼拼\n    if (C in ['b', 'p', 'm', 'f']) and ((V[0] in ['u', 'v'] and V != \"u\") or\n                                        V == 'ong'):\n        return None\n\n    # ua, uai, uang 不能和 d, t, n, l, r, z, c, s 拼\n    if V in ['ua', 'uai',\n             'uang'] and C in ['d', 't', 'n', 'l', 'r', 'z', 'c', 's']:\n        return None\n\n    # sh 和 ong 不能拼\n    if V == 'ong' and C in ['sh']:\n        return None\n\n    # o 和 gkh, zh ch sh r z c s 不能拼\n    if V == \"o\" and C in [\n            'd', 't', 'n', 'g', 'k', 'h', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's'\n    ]:\n        return None\n\n    # ueng 只是 weng 这个 ad-hoc 其他情况下都是 ong\n    if V == 'ueng' and C != '':\n        return\n\n    # 非儿化的 er 只能单独存在\n    if V == 'er' and C != '':\n        return None\n\n    if C == '':\n        if V in [\"i\", \"in\", \"ing\"]:\n            C = 'y'\n        elif V == 'u':\n            C = 'w'\n        elif V.startswith('i') and V not in [\"ii\", \"iii\"]:\n            C = 'y'\n            V = V[1:]\n        elif V.startswith('u'):\n            C = 'w'\n            V = V[1:]\n        elif V.startswith('v'):\n            C = 'yu'\n            V = V[1:]\n    else:\n        if C in ['j', 'q', 'x']:\n            if V.startswith('v'):\n                V = re.sub('v', 'u', V)\n        if V == 'iou':\n            V = 'iu'\n        elif V == 'uei':\n            V = 'ui'\n        elif V == 'uen':\n            V = 'un'\n    result = C + V\n\n    # Filter  er 不能再儿化\n    if result.endswith('r') and R == 'r':\n        return None\n\n    # ii and iii, change back to i\n    result = re.sub(r'i+', 'i', result)\n\n    result = result + R + T\n    return result\n\n\ndef generate_lexicon(with_tone=False, with_erhua=False):\n    \"\"\"Generate lexicon for Mandarin Chinese.\"\"\"\n    syllables = OrderedDict()\n\n    for C in [''] + INITIALS:\n        for V in FINALS:\n            for R in [''] if not with_erhua else ['', 'r']:\n                for T in [''] if not with_tone else ['1', '2', '3', '4', '5']:\n                    result = rule(C, V, R, T)\n                    if result:\n                        syllables[result] = f'{C} {V}{R}{T}'\n    return syllables\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/mix_frontend.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nfrom typing import Dict\nfrom typing import List\n\nimport numpy as np\nimport paddle\n\nfrom paddlespeech.t2s.frontend.en_frontend import English as EnFrontend\nfrom paddlespeech.t2s.frontend.ssml.xml_processor import MixTextProcessor\nfrom paddlespeech.t2s.frontend.zh_frontend import Frontend as ZhFrontend\n\n\nclass MixFrontend():\n    def __init__(self,\n                 g2p_model=\"pypinyin\",\n                 phone_vocab_path=None,\n                 tone_vocab_path=None):\n        self.zh_frontend = ZhFrontend(\n            phone_vocab_path=phone_vocab_path, tone_vocab_path=tone_vocab_path)\n        self.en_frontend = EnFrontend(phone_vocab_path=phone_vocab_path)\n        self.sp_id = self.zh_frontend.vocab_phones[\"sp\"]\n        self.sp_id_numpy = np.array([self.sp_id])\n        self.sp_id_tensor = paddle.to_tensor([self.sp_id])\n\n    def is_chinese(self, char):\n        if char >= '\\u4e00' and char <= '\\u9fa5':\n            return True\n        else:\n            return False\n\n    def is_alphabet(self, char):\n        if (char >= '\\u0041' and char <= '\\u005a') or (char >= '\\u0061' and\n                                                       char <= '\\u007a'):\n            return True\n        else:\n            return False\n\n    def is_other(self, char):\n        if not (self.is_chinese(char) or self.is_alphabet(char)):\n            return True\n        else:\n            return False\n\n    def split_by_lang(self, text: str) -> List[str]:\n        # sentence --> [ch_part, en_part, ch_part, ...]\n        segments = []\n        types = []\n\n        # Determine the type of each character. type: chinese, alphabet, other.\n        for ch in text:\n            if self.is_chinese(ch):\n                types.append(\"zh\")\n            elif self.is_alphabet(ch):\n                types.append(\"en\")\n            else:\n                types.append(\"other\")\n\n        assert len(types) == len(text)\n\n        flag = 0\n        temp_seg = \"\"\n        temp_lang = \"\"\n\n        for i in range(len(text)):\n            # find the first char of the seg\n            if flag == 0:\n                temp_seg += text[i]\n                temp_lang = types[i]\n                flag = 1\n            else:\n                if temp_lang == \"other\":\n                    # text start is not lang.\n                    temp_seg += text[i]\n                    if types[i] != temp_lang:\n                        temp_lang = types[i]\n                else:\n                    if types[i] == temp_lang or types[i] == \"other\":\n                        # merge same lang or other\n                        temp_seg += text[i]\n                    else:\n                        # change lang\n                        segments.append((temp_seg, temp_lang))\n                        temp_seg = text[i]\n                        temp_lang = types[i]  # new lang\n\n        segments.append((temp_seg, temp_lang))\n\n        return segments\n\n    def get_input_ids(self,\n                      sentence: str,\n                      merge_sentences: bool=False,\n                      get_tone_ids: bool=False,\n                      add_sp: bool=True,\n                      to_tensor: bool=True) -> Dict[str, List[paddle.Tensor]]:\n        # XML Document Object Model (DOM)\n        doms = MixTextProcessor.get_dom_split(sentence)\n\n        lang_splits = []\n        for dom in doms:\n            if dom.lower().startswith(\"<say-as pinyin=\"):\n                # `<say-as pinyin=` for zh lang\n                lang_splits.append((dom, \"zh\"))\n            else:\n                # process zh, en and zh/en\n                lang_splits.extend(self.split_by_lang(dom))\n\n        # merge adjacent zh segment\n        segments = []\n        currentSeg = [\"\", \"\"]\n        for seg in lang_splits:\n            if seg[1] == \"en\" or seg[1] == \"other\":\n                if currentSeg[0] == '':\n                    # first see\n                    segments.append(seg)\n                else:\n                    # zh\n                    currentSeg[0] = \"<speak>\" + currentSeg[0] + \"</speak>\"\n                    segments.append(tuple(currentSeg))\n                    # en\n                    segments.append(seg)\n                    # reset\n                    currentSeg = [\"\", \"\"]\n            else:\n                # zh\n                if currentSeg[0] == '':\n                    # first see\n                    currentSeg[0] = seg[0]\n                    currentSeg[1] = seg[1]\n                else:\n                    # merge zh \n                    currentSeg[0] = currentSeg[0] + seg[0]\n\n        if currentSeg[0] != '':\n            # last zh\n            currentSeg[0] = \"<speak>\" + currentSeg[0] + \"</speak>\"\n            segments.append(tuple(currentSeg))\n\n        phones_list = []\n        result = {}\n\n        # 008 我们要去云南 team building, 非常非常 happy.\n        # seg ('我们要去云南 ', 'zh')\n        # seg ('team building, ', 'en')\n        # seg ('非常非常 ', 'zh')\n        # seg ('happy.', 'en')\n        # [('<speak>我们要去云南 </speak>', 'zh'), ('team building, ', 'en'), ('<speak>非常非常 </speak>', 'zh'), ('happy.', 'en')]\n        for seg in segments:\n            content = seg[0]\n            lang = seg[1]\n\n            if not content:\n                continue\n\n            if lang == \"en\":\n                input_ids = self.en_frontend.get_input_ids(\n                    content, merge_sentences=False, to_tensor=to_tensor)\n            else:\n                if content.strip() != \"\" and \\\n                    re.match(r\".*?<speak>.*?</speak>.*\", content, re.DOTALL):\n                    # process ssml\n                    input_ids = self.zh_frontend.get_input_ids_ssml(\n                        content,\n                        merge_sentences=False,\n                        get_tone_ids=get_tone_ids,\n                        to_tensor=to_tensor)\n                else:\n                    # process plain text\n                    input_ids = self.zh_frontend.get_input_ids(\n                        content,\n                        merge_sentences=False,\n                        get_tone_ids=get_tone_ids,\n                        to_tensor=to_tensor)\n\n            if add_sp:\n                # add sp between zh and en\n                if to_tensor:\n                    input_ids[\"phone_ids\"][-1] = paddle.concat(\n                        [input_ids[\"phone_ids\"][-1], self.sp_id_tensor])\n                else:\n                    input_ids[\"phone_ids\"][-1] = np.concatenate(\n                        (input_ids[\"phone_ids\"][-1], self.sp_id_numpy))\n\n            phones_list.extend(input_ids[\"phone_ids\"])\n\n        if merge_sentences:\n            merge_list = paddle.concat(phones_list)\n            # rm the last 'sp' to avoid the noise at the end\n            # cause in the training data, no 'sp' in the end\n            if (to_tensor and merge_list[-1] == self.sp_id_tensor) or (\n                    not to_tensor and merge_list[-1] == self.sp_id_numpy):\n                merge_list = merge_list[:-1]\n            phones_list = []\n            phones_list.append(merge_list)\n\n        result[\"phone_ids\"] = phones_list\n\n        return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.t2s.frontend.normalizer.normalizer import *\nfrom paddlespeech.t2s.frontend.normalizer.numbers import *\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/abbrrviation.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/acronyms.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/normalizer.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nimport unicodedata\nfrom builtins import str as unicode\n\nfrom paddlespeech.t2s.frontend.normalizer.numbers import normalize_numbers\n\n\ndef normalize(sentence):\n    \"\"\" Normalize English text.\n    \"\"\"\n    # preprocessing\n    sentence = unicode(sentence)\n    sentence = normalize_numbers(sentence)\n    sentence = ''.join(\n        char for char in unicodedata.normalize('NFD', sentence)\n        if unicodedata.category(char) != 'Mn')  # Strip accents\n    sentence = sentence.lower()\n    sentence = re.sub(r\"[^ a-z'.,?!\\-]\", \"\", sentence)\n    sentence = sentence.replace(\"i.e.\", \"that is\")\n    sentence = sentence.replace(\"e.g.\", \"for example\")\n    return sentence\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/numbers.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# number expansion is not that easy\nimport re\n\nimport inflect\n\n_inflect = inflect.engine()\n_comma_number_re = re.compile(r'([0-9][0-9\\,]+[0-9])')\n_decimal_number_re = re.compile(r'([0-9]+\\.[0-9]+)')\n_pounds_re = re.compile(r'£([0-9\\,]*[0-9]+)')\n_dollars_re = re.compile(r'\\$([0-9\\.\\,]*[0-9]+)')\n_ordinal_re = re.compile(r'[0-9]+(st|nd|rd|th)')\n_number_re = re.compile(r'[0-9]+')\n\n\ndef _remove_commas(m):\n    return m.group(1).replace(',', '')\n\n\ndef _expand_decimal_point(m):\n    return m.group(1).replace('.', ' point ')\n\n\ndef _expand_dollars(m):\n    match = m.group(1)\n    parts = match.split('.')\n    if len(parts) > 2:\n        return match + ' dollars'  # Unexpected format\n    dollars = int(parts[0]) if parts[0] else 0\n    cents = int(parts[1]) if len(parts) > 1 and parts[1] else 0\n    if dollars and cents:\n        dollar_unit = 'dollar' if dollars == 1 else 'dollars'\n        cent_unit = 'cent' if cents == 1 else 'cents'\n        return '%s %s, %s %s' % (dollars, dollar_unit, cents, cent_unit)\n    elif dollars:\n        dollar_unit = 'dollar' if dollars == 1 else 'dollars'\n        return '%s %s' % (dollars, dollar_unit)\n    elif cents:\n        cent_unit = 'cent' if cents == 1 else 'cents'\n        return '%s %s' % (cents, cent_unit)\n    else:\n        return 'zero dollars'\n\n\ndef _expand_ordinal(m):\n    return _inflect.number_to_words(m.group(0))\n\n\ndef _expand_number(m):\n    num = int(m.group(0))\n    if num > 1000 and num < 3000:\n        if num == 2000:\n            return 'two thousand'\n        elif num > 2000 and num < 2010:\n            return 'two thousand ' + _inflect.number_to_words(num % 100)\n        elif num % 100 == 0:\n            return _inflect.number_to_words(num // 100) + ' hundred'\n        else:\n            return _inflect.number_to_words(\n                num, andword='', zero='oh', group=2).replace(', ', ' ')\n    else:\n        return _inflect.number_to_words(num, andword='')\n\n\ndef normalize_numbers(text):\n    \"\"\" Normalize numbers in English text.\n    \"\"\"\n    text = re.sub(_comma_number_re, _remove_commas, text)\n    text = re.sub(_pounds_re, r'\\1 pounds', text)\n    text = re.sub(_dollars_re, _expand_dollars, text)\n    text = re.sub(_decimal_number_re, _expand_decimal_point, text)\n    text = re.sub(_ordinal_re, _expand_ordinal, text)\n    text = re.sub(_number_re, _expand_number, text)\n    return text\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/normalizer/width.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\ndef full2half_width(ustr):\n    half = []\n    for u in ustr:\n        num = ord(u)\n        if num == 0x3000:  # 全角空格变半角\n            num = 32\n        elif 0xFF01 <= num <= 0xFF5E:\n            num -= 0xfee0\n        u = chr(num)\n        half.append(u)\n    return ''.join(half)\n\n\ndef half2full_width(ustr):\n    full = []\n    for u in ustr:\n        num = ord(u)\n        if num == 32:  # 半角空格变全角\n            num = 0x3000\n        elif 0x21 <= num <= 0x7E:\n            num += 0xfee0\n        u = chr(num)  # to unicode\n        full.append(u)\n\n    return ''.join(full)\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/phonectic.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom abc import ABC\nfrom abc import abstractmethod\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom g2p_en import G2p\nfrom g2pM import G2pM\n\nfrom paddlespeech.t2s.frontend.normalizer.normalizer import normalize\nfrom paddlespeech.t2s.frontend.punctuation import get_punctuations\nfrom paddlespeech.t2s.frontend.vocab import Vocab\nfrom paddlespeech.t2s.frontend.zh_normalization.text_normlization import TextNormalizer\n\n# discard opencc untill we find an easy solution to install it on windows\n# from opencc import OpenCC\n\n__all__ = [\"Phonetics\", \"English\", \"EnglishCharacter\", \"Chinese\"]\n\n\nclass Phonetics(ABC):\n    @abstractmethod\n    def __call__(self, sentence):\n        pass\n\n    @abstractmethod\n    def phoneticize(self, sentence):\n        pass\n\n    @abstractmethod\n    def numericalize(self, phonemes):\n        pass\n\n\nclass English(Phonetics):\n    \"\"\" Normalize the input text sequence and convert into pronunciation id sequence.\n\n    https://github.com/Kyubyong/g2p/blob/master/g2p_en/g2p.py\n\n    phonemes = [\"<pad>\", \"<unk>\", \"<s>\", \"</s>\"] + [   \n        'AA0', 'AA1', 'AA2', 'AE0', 'AE1', 'AE2', 'AH0', 'AH1', 'AH2', 'AO0',\n        'AO1', 'AO2', 'AW0', 'AW1', 'AW2', 'AY0', 'AY1', 'AY2', 'B', 'CH', 'D', 'DH',\n        'EH0', 'EH1', 'EH2', 'ER0', 'ER1', 'ER2', 'EY0', 'EY1',\n        'EY2', 'F', 'G', 'HH',\n        'IH0', 'IH1', 'IH2', 'IY0', 'IY1', 'IY2', 'JH', 'K', 'L',\n        'M', 'N', 'NG', 'OW0', 'OW1',\n        'OW2', 'OY0', 'OY1', 'OY2', 'P', 'R', 'S', 'SH', 'T', 'TH',\n        'UH0', 'UH1', 'UH2', 'UW',\n        'UW0', 'UW1', 'UW2', 'V', 'W', 'Y', 'Z', 'ZH']\n    \"\"\"\n\n    LEXICON = {\n        # key using lowercase\n        \"AI\".lower(): [[\"EY0\", \"AY1\"]],\n    }\n\n    def __init__(self, phone_vocab_path=None):\n        self.backend = G2p()\n        self.backend.cmu.update(English.LEXICON)\n        self.phonemes = list(self.backend.phonemes)\n        self.punctuations = get_punctuations(\"en\")\n        self.vocab = Vocab(self.phonemes + self.punctuations)\n        self.vocab_phones = {}\n        self.punc = \"、：，；。？！“”‘’':,;.?!\"\n        self.text_normalizer = TextNormalizer()\n        if phone_vocab_path:\n            with open(phone_vocab_path, 'rt', encoding='utf-8') as f:\n                phn_id = [line.strip().split() for line in f.readlines()]\n            for phn, id in phn_id:\n                self.vocab_phones[phn] = int(id)\n\n    def phoneticize(self, sentence):\n        \"\"\" Normalize the input text sequence and convert it into pronunciation sequence.\n        Args:\n            sentence (str): The input text sequence.\n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        start = self.vocab.start_symbol\n        end = self.vocab.end_symbol\n        phonemes = ([] if start is None else [start]) \\\n                   + self.backend(sentence) \\\n                   + ([] if end is None else [end])\n        phonemes = [item for item in phonemes if item in self.vocab.stoi]\n        return phonemes\n\n    def _p2id(self, phonemes: List[str]) -> np.array:\n        phone_ids = [self.vocab_phones[item] for item in phonemes]\n        return np.array(phone_ids, np.int64)\n\n    def get_input_ids(self,\n                      sentence: str,\n                      merge_sentences: bool=False,\n                      to_tensor: bool=True) -> paddle.Tensor:\n        sentences = self.text_normalizer._split(sentence, lang=\"en\")\n\n        phones_list = []\n        temp_phone_ids = []\n        for sentence in sentences:\n            phones = self.phoneticize(sentence)\n            # remove start_symbol and end_symbol\n            phones = phones[1:-1]\n            phones = [phn for phn in phones if not phn.isspace()]\n            # replace unk phone with sp\n            phones = [\n                phn\n                if (phn in self.vocab_phones and phn not in self.punc) else \"sp\"\n                for phn in phones\n            ]\n            if len(phones) != 0:\n                phones_list.append(phones)\n\n        if merge_sentences:\n            merge_list = sum(phones_list, [])\n            # rm the last 'sp' to avoid the noise at the end\n            # cause in the training data, no 'sp' in the end\n            if merge_list[-1] == 'sp':\n                merge_list = merge_list[:-1]\n            phones_list = []\n            phones_list.append(merge_list)\n\n        for part_phones_list in phones_list:\n            phone_ids = self._p2id(part_phones_list)\n            if to_tensor:\n                phone_ids = paddle.to_tensor(phone_ids)\n            temp_phone_ids.append(phone_ids)\n\n        result = {}\n        result[\"phone_ids\"] = temp_phone_ids\n\n        return result\n\n    def numericalize(self, phonemes):\n        \"\"\" Convert pronunciation sequence into pronunciation id sequence.\n        Args:\n            phonemes (List[str]): The list of pronunciation sequence.\n        Returns: \n            List[int]: The list of pronunciation id sequence.\n        \"\"\"\n        ids = [\n            self.vocab.lookup(item) for item in phonemes\n            if item in self.vocab.stoi\n        ]\n        return ids\n\n    def reverse(self, ids):\n        \"\"\" Reverse the list of pronunciation id sequence to a list of pronunciation sequence.\n        Args:\n            ids (List[int]): The list of pronunciation id sequence.\n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        return [self.vocab.reverse(i) for i in ids]\n\n    def __call__(self, sentence):\n        \"\"\" Convert the input text sequence into pronunciation id sequence.\n        Args:\n            sentence(str): The input text sequence.\n        Returns: \n            List[str]: The list of pronunciation id sequence.\n        \"\"\"\n        return self.numericalize(self.phoneticize(sentence))\n\n    @property\n    def vocab_size(self):\n        \"\"\" Vocab size.\n        \"\"\"\n        return len(self.vocab)\n\n\nclass EnglishCharacter(Phonetics):\n    \"\"\" Normalize the input text sequence and convert it into character id sequence.\n    \"\"\"\n\n    def __init__(self):\n        self.backend = G2p()\n        self.graphemes = list(self.backend.graphemes)\n        self.punctuations = get_punctuations(\"en\")\n        self.vocab = Vocab(self.graphemes + self.punctuations)\n\n    def phoneticize(self, sentence):\n        \"\"\" Normalize the input text sequence.\n        Args:\n            sentence(str): The input text sequence.\n        Returns:\n            str: A text sequence after normalize.\n        \"\"\"\n        words = normalize(sentence)\n        return words\n\n    def numericalize(self, sentence):\n        \"\"\" Convert a text sequence into ids.\n        Args:\n            sentence (str): The input text sequence.\n        Returns:\n            List[int]:\n                List of a character id sequence.\n        \"\"\"\n        ids = [\n            self.vocab.lookup(item) for item in sentence\n            if item in self.vocab.stoi\n        ]\n        return ids\n\n    def reverse(self, ids):\n        \"\"\" Convert a character id sequence into text.\n        Args:\n            ids (List[int]): List of a character id sequence.\n        Returns:\n            str: The input text sequence.\n        \"\"\"\n        return [self.vocab.reverse(i) for i in ids]\n\n    def __call__(self, sentence):\n        \"\"\" Normalize the input text sequence and convert it into character id sequence.\n        Args:\n            sentence (str): The input text sequence.\n        Returns: \n            List[int]: List of a character id sequence.\n        \"\"\"\n        return self.numericalize(self.phoneticize(sentence))\n\n    @property\n    def vocab_size(self):\n        \"\"\" Vocab size.\n        \"\"\"\n        return len(self.vocab)\n\n\nclass Chinese(Phonetics):\n    \"\"\"Normalize Chinese text sequence and convert it into ids.\n    \"\"\"\n\n    def __init__(self):\n        # self.opencc_backend = OpenCC('t2s.json')\n        self.backend = G2pM()\n        self.phonemes = self._get_all_syllables()\n        self.punctuations = get_punctuations(\"cn\")\n        self.vocab = Vocab(self.phonemes + self.punctuations)\n\n    def _get_all_syllables(self):\n        all_syllables = set([\n            syllable for k, v in self.backend.cedict.items() for syllable in v\n        ])\n        return list(all_syllables)\n\n    def phoneticize(self, sentence):\n        \"\"\" Normalize the input text sequence and convert it into pronunciation sequence.\n        Args:\n            sentence(str): The input text sequence.\n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        # simplified = self.opencc_backend.convert(sentence)\n        simplified = sentence\n        phonemes = self.backend(simplified)\n        start = self.vocab.start_symbol\n        end = self.vocab.end_symbol\n        phonemes = ([] if start is None else [start]) \\\n                   + phonemes \\\n                   + ([] if end is None else [end])\n        return self._filter_symbols(phonemes)\n\n    def _filter_symbols(self, phonemes):\n        cleaned_phonemes = []\n        for item in phonemes:\n            if item in self.vocab.stoi:\n                cleaned_phonemes.append(item)\n            else:\n                for char in item:\n                    if char in self.vocab.stoi:\n                        cleaned_phonemes.append(char)\n        return cleaned_phonemes\n\n    def numericalize(self, phonemes):\n        \"\"\" Convert pronunciation sequence into pronunciation id sequence.\n        Args:\n            phonemes(List[str]): The list of pronunciation sequence.\n        Returns:\n                List[int]: The list of pronunciation id sequence.\n        \"\"\"\n        ids = [self.vocab.lookup(item) for item in phonemes]\n        return ids\n\n    def __call__(self, sentence):\n        \"\"\" Convert the input text sequence into pronunciation id sequence.\n        Args:\n            sentence (str): The input text sequence.\n        Returns:\n            List[str]: The list of pronunciation id sequence.\n        \"\"\"\n        return self.numericalize(self.phoneticize(sentence))\n\n    @property\n    def vocab_size(self):\n        \"\"\" Vocab size.\n        \"\"\"\n        return len(self.vocab)\n\n    def reverse(self, ids):\n        \"\"\" Reverse the list of pronunciation id sequence to a list of pronunciation sequence.\n        Args:\n        ids (List[int]): The list of pronunciation id sequence.\n        Returns: \n            List[str]: The list of pronunciation sequence.\n        \"\"\"\n        return [self.vocab.reverse(i) for i in ids]\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/polyphonic.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport yaml\n\n\nclass Polyphonic():\n    def __init__(self):\n        with open(\n                os.path.join(\n                    os.path.dirname(os.path.abspath(__file__)),\n                    'polyphonic.yaml'),\n                'r',\n                encoding='utf-8') as polyphonic_file:\n            # 解析yaml\n            polyphonic_dict = yaml.load(polyphonic_file, Loader=yaml.FullLoader)\n        self.polyphonic_words = polyphonic_dict[\"polyphonic\"]\n\n    def correct_pronunciation(self, word, pinyin):\n        # 词汇被词典收录则返回纠正后的读音\n        if word in self.polyphonic_words.keys():\n            pinyin = self.polyphonic_words[word]\n        # 否则返回原读音\n        return pinyin\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/polyphonic.yaml",
    "content": "polyphonic:\n    湖泊: ['hu2','po1']\n    地壳: ['di4','qiao4']\n    柏树: ['bai3','shu4']\n    曝光: ['bao4','guang1']\n    弹力: ['tan2','li4']\n    字帖: ['zi4','tie4']\n    口吃: ['kou3','chi1']\n    包扎: ['bao1','za1']\n    哪吒: ['ne2','zha1']\n    说服: ['shuo1','fu2']\n    识字: ['shi2','zi4']\n    骨头: ['gu3','tou5']\n    对称: ['dui4','chen4']\n    口供: ['kou3','gong4']\n    抹布: ['ma1','bu4']\n    露背: ['lu4','bei4']\n    圈养: ['juan4', 'yang3']\n    眼眶: ['yan3', 'kuang4']\n    品行: ['pin3','xing2']\n    颤抖: ['chan4','dou3']\n    差不多: ['cha4','bu5','duo1']\n    鸭绿江: ['ya1','lu4','jiang1']\n    撒切尔: ['sa4','qie4','er3']\n    比比皆是: ['bi3','bi3','jie1','shi4']\n    身无长物: ['shen1','wu2','chang2','wu4']\n    手里: ['shou2','li3']\n    关卡: ['guan1','qia3']\n    怀揣: ['huai2','chuai1']\n    挑剔: ['tiao1','ti4']\n    供称: ['gong4','cheng1']\n    作坊: ['zuo1', 'fang5']\n    中医: ['zhong1','yi1']\n    嚷嚷: ['rang1','rang5']\n    商厦: ['shang1','sha4']\n    大厦: ['da4','sha4']\n    刹车: ['sha1','che1']\n    嘚瑟: ['de4','se5']\n    朝鲜: ['chao2','xian3']\n    阿房宫: ['e1','pang2','gong1']\n    阿胶: ['e1','jiao1']\n    咖喱: ['ga1','li5']\n    时分: ['shi2','fen1']\n    蚌埠: ['beng4','bu4']\n    驯服: ['xun4','fu2']\n    幸免于难: ['xing4','mian3','yu2','nan4']\n    恶行: ['e4','xing2']\n    唉: ['ai4']\n    扎实: ['zha1','shi2']\n    干将: ['gan4','jiang4']\n    陈威行: ['chen2', 'wei1', 'hang2']\n    郭晟: ['guo1', 'sheng4']\n    中标: ['zhong4', 'biao1']\n    抗住: ['kang2', 'zhu4']"
  },
  {
    "path": "paddlespeech/t2s/frontend/punctuation.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = [\"get_punctuations\"]\n\nEN_PUNCT = [\n    \" \",\n    \"-\",\n    \"...\",\n    \",\",\n    \".\",\n    \"?\",\n    \"!\",\n]\n\nCN_PUNCT = [\"、\", \"，\", \"；\", \"：\", \"。\", \"？\", \"！\"]\n\n\ndef get_punctuations(lang):\n    if lang == \"en\":\n        return EN_PUNCT\n    elif lang == \"cn\":\n        return CN_PUNCT\n    else:\n        raise ValueError(f\"language {lang} Not supported\")\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/rhy_prediction/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .rhy_predictor import *\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/rhy_prediction/rhy_predictor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport re\n\nimport paddle\nimport yaml\nfrom paddlenlp.transformers import ErnieTokenizer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.cli.utils import download_and_decompress\nfrom paddlespeech.resource.pretrained_models import rhy_frontend_models\nfrom paddlespeech.text.models.ernie_linear import ErnieLinear\nfrom paddlespeech.utils.env import MODEL_HOME\n\nDefinedClassifier = {\n    'ErnieLinear': ErnieLinear,\n}\n\nmodel_version = '1.0'\n\n\nclass RhyPredictor():\n    def __init__(\n            self,\n            model_dir: os.PathLike=MODEL_HOME, ):\n        uncompress_path = download_and_decompress(\n            rhy_frontend_models['rhy_e2e'][model_version], model_dir)\n        with open(os.path.join(uncompress_path, 'rhy_default.yaml')) as f:\n            config = CfgNode(yaml.safe_load(f))\n        self.punc_list = []\n        with open(os.path.join(uncompress_path, 'rhy_token'), 'r') as f:\n            for line in f:\n                self.punc_list.append(line.strip())\n        self.punc_list = [0] + self.punc_list\n        self.make_rhy_dict()\n        self.model = DefinedClassifier[\"ErnieLinear\"](**config[\"model\"])\n        pretrained_token = config['data_params']['pretrained_token']\n        self.tokenizer = ErnieTokenizer.from_pretrained(pretrained_token)\n        state_dict = paddle.load(\n            os.path.join(uncompress_path, 'snapshot_iter_2600_main_params.pdz'))\n        self.model.set_state_dict(state_dict)\n        self.model.eval()\n\n    def _clean_text(self, text):\n        text = text.lower()\n        text = re.sub('[^A-Za-z0-9\\u4e00-\\u9fa5]', '', text)\n        text = re.sub(f'[{\"\".join([p for p in self.punc_list][1:])}]', '', text)\n        return text\n\n    def preprocess(self, text, tokenizer):\n        clean_text = self._clean_text(text)\n        assert len(clean_text) > 0, f'Invalid input string: {text}'\n        tokenized_input = tokenizer(\n            list(clean_text), return_length=True, is_split_into_words=True)\n        _inputs = dict()\n        _inputs['input_ids'] = tokenized_input['input_ids']\n        _inputs['seg_ids'] = tokenized_input['token_type_ids']\n        _inputs['seq_len'] = tokenized_input['seq_len']\n        return _inputs\n\n    def get_prediction(self, raw_text):\n        _inputs = self.preprocess(raw_text, self.tokenizer)\n        seq_len = _inputs['seq_len']\n        input_ids = paddle.to_tensor(_inputs['input_ids']).unsqueeze(0)\n        seg_ids = paddle.to_tensor(_inputs['seg_ids']).unsqueeze(0)\n        logits, _ = self.model(input_ids, seg_ids)\n        preds = paddle.argmax(logits, axis=-1).squeeze(0)\n        tokens = self.tokenizer.convert_ids_to_tokens(\n            _inputs['input_ids'][1:seq_len - 1])\n        labels = preds[1:seq_len - 1].tolist()\n        assert len(tokens) == len(labels)\n        # add 0 for non punc\n        text = ''\n        for t, l in zip(tokens, labels):\n            text += t\n            if l != 0:  # Non punc.\n                text += self.punc_list[l]\n        return text\n\n    def make_rhy_dict(self):\n        self.rhy_dict = {}\n        for i, p in enumerate(self.punc_list[1:]):\n            self.rhy_dict[p] = 'sp' + str(i + 1)\n\n    def pinyin_align(self, pinyins, rhy_pre):\n        final_py = []\n        j = 0\n        for i in range(len(rhy_pre)):\n            if rhy_pre[i] in self.rhy_dict:\n                final_py.append(self.rhy_dict[rhy_pre[i]])\n            else:\n                final_py.append(pinyins[j])\n                j += 1\n        return final_py\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/sing_frontend.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nfrom typing import Dict\nfrom typing import List\n\nimport librosa\nimport numpy as np\nimport paddle\nfrom pypinyin import lazy_pinyin\n\n\nclass SingFrontend():\n    def __init__(self, pinyin_phone_path: str, phone_vocab_path: str):\n        \"\"\"SVS Frontend\n\n        Args:\n            pinyin_phone_path (str): pinyin to phone file path, a 'pinyin|phones' (like: ba|b a ) pair per line.\n            phone_vocab_path (str): phone to phone id file path, a 'phone phone id' (like: a 4 ) pair per line.\n        \"\"\"\n        self.punc = '[、：，；。？！“”‘’\\':,;.?!]'\n\n        self.pinyin_phones = {'AP': 'AP', 'SP': 'SP'}\n        if pinyin_phone_path:\n            with open(pinyin_phone_path, 'rt', encoding='utf-8') as f:\n                for line in f.readlines():\n                    pinyin_phn = [\n                        x.strip() for x in line.split('|') if x.strip() != ''\n                    ]\n                    self.pinyin_phones[pinyin_phn[0]] = pinyin_phn[1]\n\n        self.vocab_phones = {}\n        if phone_vocab_path:\n            with open(phone_vocab_path, 'rt', encoding='utf-8') as f:\n                phn_id = [line.strip().split() for line in f.readlines()]\n            for phn, id in phn_id:\n                self.vocab_phones[phn] = int(id)\n\n    def get_phones(self, sentence: str) -> List[int]:\n        \"\"\"get phone list\n\n        Args:\n            sentence (str): sentence\n\n        Returns:\n            List[int]: phones list\n\n        Example:\n            sentence = \"你好\"\n            phones = ['n i', 'h ao']\n        \"\"\"\n        # remove all punc\n        sentence = re.sub(self.punc, \"\", sentence)\n\n        # Pypinyin can't solve polyphonic words\n        sentence = sentence.replace('最长', '最常').replace('长睫毛', '常睫毛') \\\n            .replace('那么长', '那么常').replace('多长', '多常') \\\n            .replace('很长', '很常')\n\n        # lyric\n        pinyins = lazy_pinyin(sentence, strict=False)\n        # replace unk word with SP\n        pinyins = [\n            pinyin if pinyin in self.pinyin_phones.keys() else \"SP\"\n            for pinyin in pinyins\n        ]\n        phones = [\n            self.pinyin_phones[pinyin.strip()] for pinyin in pinyins\n            if pinyin.strip() in self.pinyin_phones\n        ]\n\n        return phones\n\n    def get_note_info(self, note_info: str) -> List[str]:\n        note_info = [x.strip() for x in note_info.split('|') if x.strip() != '']\n        return note_info\n\n    def process(\n            self,\n            phones: List[int],\n            notes: List[str],\n            note_durs: List[float], ) -> Dict[str, List[paddle.Tensor]]:\n        new_phones = []\n        new_notes = []\n        new_note_durs = []\n        is_slurs = []\n        assert len(phones) == len(notes) == len(\n            note_durs\n        ), \"Please check the input, text, notes, note_durs should be the same length.\"\n        for i in range(len(phones)):\n            phone = phones[i].split()\n            note = notes[i].split()\n            note_dur = note_durs[i].split()\n\n            for phn in phone:\n                new_phones.append(phn)\n                new_notes.append(note[0])\n                new_note_durs.append(note_dur[0])\n                is_slurs.append(0)\n\n            if len(note) > 1:\n                for i in range(1, len(note)):\n                    new_phones.append(phone[-1])\n                    new_notes.append(note[i])\n                    new_note_durs.append(note_dur[i])\n                    is_slurs.append(1)\n\n        return new_phones, new_notes, new_note_durs, is_slurs\n\n    def get_input_ids(self, svs_input: Dict[str, str],\n                      to_tensor: bool=True) -> Dict[str, List[paddle.Tensor]]:\n        \"\"\"convert input to int/float.\n\n        Args:\n            svs_input (Dict[str, str]): include keys: if input_type is phones, phones, notes, note_durs and is_slurs are needed.\n            if  input_type is word, text, notes, and note_durs sre needed.\n            to_tensor (bool, optional): whether to convert to Tensor. Defaults to True.\n\n        Returns:\n            Dict[str, List[paddle.Tensor]]: result include phone_ids, note_ids, note_durs, is_slurs.\n        \"\"\"\n        result = {}\n        input_type = svs_input['input_type']\n        if input_type == 'phoneme':\n            assert \"phones\" in svs_input.keys() and \"notes\" in svs_input.keys() and \"note_durs\" in svs_input.keys() and \"is_slurs\" in svs_input.keys(), \\\n                \"When input_type is phoneme, phones, notes, note_durs, is_slurs should be in the svs_input.\"\n            phones = svs_input[\"phones\"].split()\n            notes = svs_input[\"notes\"].split()\n            note_durs = svs_input[\"note_durs\"].split()\n            is_slurs = svs_input[\"is_slurs\"].split()\n            assert len(phones) == len(notes) == len(note_durs) == len(\n                is_slurs\n            ), \"Please check the input, phones, notes, note_durs is_slurs should be the same length.\"\n        elif input_type == \"word\":\n            assert \"text\" in svs_input.keys() and \"notes\" in svs_input.keys() and \"note_durs\" in svs_input.keys(), \\\n                \"When input_type is word, text, notes, note_durs, should be in the svs_input.\"\n            phones = self.get_phones(svs_input['text'])\n            notes = self.get_note_info(svs_input['notes'])\n            note_durs = self.get_note_info(svs_input['note_durs'])\n            phones, notes, note_durs, is_slurs = self.process(\n                phones=phones, notes=notes, note_durs=note_durs)\n\n        phone_ids = [self.vocab_phones[phn] for phn in phones]\n        phone_ids = np.array(phone_ids, np.int64)\n        note_ids = [\n            librosa.note_to_midi(note.split(\"/\")[0]) if note != 'rest' else 0\n            for note in notes\n        ]\n        note_ids = np.array(note_ids, np.int64)\n        note_durs = np.array(note_durs, np.float32)\n        is_slurs = np.array(is_slurs, np.int64)\n\n        if to_tensor:\n            phone_ids = paddle.to_tensor(phone_ids)\n            note_ids = paddle.to_tensor(note_ids)\n            note_durs = paddle.to_tensor(note_durs)\n            is_slurs = paddle.to_tensor(is_slurs)\n\n        result['phone_ids'] = [phone_ids]\n        result['note_ids'] = [note_ids]\n        result['note_durs'] = [note_durs]\n        result['is_slurs'] = [is_slurs]\n\n        return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/ssml/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .xml_processor import *\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/ssml/xml_processor.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nimport xml.dom.minidom\nimport xml.parsers.expat\nfrom xml.dom.minidom import Node\nfrom xml.dom.minidom import parseString\n'''\nNote:  xml 有5种特殊字符， &<>\"'\n其一，采用<![CDATA[ ]]>特殊标签，将包含特殊字符的字符串封装起来。\n例如：\n<TitleName><![CDATA[\"姓名\"]]></TitleName>\n其二，使用XML转义序列表示这些特殊的字符，这5个特殊字符所对应XML转义序列为：\n&  &amp;\n<  &lt;\n>  &gt;\n\"  &quot;\n'  &apos;\n例如：\n<TitleName>&quot;姓名&quot;</TitleName>\n'''\n\n\nclass MixTextProcessor():\n    def __repr__(self):\n        print(\"@an MixTextProcessor class\")\n\n    def get_xml_content(self, mixstr):\n        '''返回字符串的 xml 内容'''\n        xmlptn = re.compile(r\"<speak>.*?</speak>\", re.M | re.S)\n        ctn = re.search(xmlptn, mixstr)\n        if ctn:\n            return ctn.group(0)\n        else:\n            return None\n\n    def get_content_split(self, mixstr):\n        ''' 文本分解，顺序加了列表中，按非 xml 和 xml 分开，对应的字符串,带标点符号\n        不能去除空格，因为 xml 中tag 属性带空格\n        '''\n        ctlist = []\n        # print(\"Testing:\",mixstr[:20])\n        patn = re.compile(r'(.*\\s*?)(<speak>.*?</speak>)(.*\\s*)$', re.M | re.S)\n        mat = re.match(patn, mixstr)\n        if mat:\n            pre_xml = mat.group(1)\n            in_xml = mat.group(2)\n            after_xml = mat.group(3)\n\n            ctlist.append(pre_xml)\n            ctlist.append(in_xml)\n            ctlist.append(after_xml)\n            return ctlist\n        else:\n            ctlist.append(mixstr)\n        return ctlist\n\n    @classmethod\n    def get_pinyin_split(self, mixstr):\n        ctlist = []\n        patn = re.compile(r'(.*\\s*?)(<speak>.*?</speak>)(.*\\s*)$', re.M | re.S)\n        mat = re.match(patn, mixstr)\n        if mat:\n            # pre <speak>\n            pre_xml = mat.group(1)\n            # between <speak> ... </speak>\n            in_xml = mat.group(2)\n            # post </speak>\n            after_xml = mat.group(3)\n\n            # pre with none syllable\n            if pre_xml:\n                ctlist.append([pre_xml, []])\n\n            # between with syllable\n            # [(sub sentence, [syllables]), ...]\n            dom = DomXml(in_xml)\n            pinyinlist = dom.get_pinyins_for_xml()\n            ctlist = ctlist + pinyinlist\n\n            # post with none syllable\n            if after_xml:\n                ctlist.append([after_xml, []])\n        else:\n            ctlist.append([mixstr, []])\n\n        return ctlist\n\n    @classmethod\n    def get_dom_split(self, mixstr):\n        ''' 文本分解，顺序加了列表中，返回文本和say-as标签\n        '''\n        ctlist = []\n        patn = re.compile(r'(.*\\s*?)(<speak>.*?</speak>)(.*\\s*)$', re.M | re.S)\n        mat = re.match(patn, mixstr)\n        if mat:\n            pre_xml = mat.group(1)\n            in_xml = mat.group(2)\n            after_xml = mat.group(3)\n\n            if pre_xml:\n                ctlist.append(pre_xml)\n\n            dom = DomXml(in_xml)\n            tags = dom.get_text_and_sayas_tags()\n            ctlist.extend(tags)\n\n            if after_xml:\n                ctlist.append(after_xml)\n        else:\n            ctlist.append(mixstr)\n\n        return ctlist\n\n\nclass DomXml():\n    def __init__(self, xmlstr):\n        self.tdom = parseString(xmlstr)  #Document\n        self.root = self.tdom.documentElement  #Element\n        self.rnode = self.tdom.childNodes  #NodeList\n\n    def get_text(self):\n        '''返回 xml 内容的所有文本内容的列表'''\n        res = []\n\n        for x1 in self.rnode:\n            if x1.nodeType == Node.TEXT_NODE:\n                res.append(x1.value)\n            else:\n                for x2 in x1.childNodes:\n                    if isinstance(x2, xml.dom.minidom.Text):\n                        res.append(x2.data)\n                    else:\n                        for x3 in x2.childNodes:\n                            if isinstance(x3, xml.dom.minidom.Text):\n                                res.append(x3.data)\n                            else:\n                                print(\"len(nodes of x3):\", len(x3.childNodes))\n\n        return res\n\n    def get_xmlchild_list(self):\n        '''返回 xml 内容的列表，包括所有文本内容(不带 tag)'''\n        res = []\n\n        for x1 in self.rnode:\n            if x1.nodeType == Node.TEXT_NODE:\n                res.append(x1.value)\n            else:\n                for x2 in x1.childNodes:\n                    if isinstance(x2, xml.dom.minidom.Text):\n                        res.append(x2.data)\n                    else:\n                        for x3 in x2.childNodes:\n                            if isinstance(x3, xml.dom.minidom.Text):\n                                res.append(x3.data)\n                            else:\n                                print(\"len(nodes of x3):\", len(x3.childNodes))\n        print(res)\n        return res\n\n    def get_pinyins_for_xml(self):\n        '''返回 xml 内容，字符串和拼音的 list '''\n        res = []\n\n        for x1 in self.rnode:\n            if x1.nodeType == Node.TEXT_NODE:\n                t = re.sub(r\"\\s+\", \"\", x1.value)\n                res.append([t, []])\n            else:\n                for x2 in x1.childNodes:\n                    if isinstance(x2, xml.dom.minidom.Text):\n                        t = re.sub(r\"\\s+\", \"\", x2.data)\n                        res.append([t, []])\n                    else:\n                        # print(\"x2\",x2,x2.tagName)\n                        if x2.hasAttribute('pinyin'):\n                            pinyin_value = x2.getAttribute(\"pinyin\")\n                            pinyins = pinyin_value.split(\" \")\n                        for x3 in x2.childNodes:\n                            # print('x3',x3)\n                            if isinstance(x3, xml.dom.minidom.Text):\n                                t = re.sub(r\"\\s+\", \"\", x3.data)\n                                res.append([t, pinyins])\n                            else:\n                                print(\"len(nodes of x3):\", len(x3.childNodes))\n\n        return res\n\n    def get_all_tags(self, tag_name):\n        '''获取所有的 tag 及属性值'''\n        alltags = self.root.getElementsByTagName(tag_name)\n        for x in alltags:\n            if x.hasAttribute('pinyin'):  # pinyin\n                print(x.tagName, 'pinyin',\n                      x.getAttribute('pinyin'), x.firstChild.data)\n\n    def get_text_and_sayas_tags(self):\n        '''返回 xml 内容的列表，包括所有文本内容和<say-as> tag'''\n        res = []\n\n        for x1 in self.rnode:\n            if x1.nodeType == Node.TEXT_NODE:\n                res.append(x1.value)\n            else:\n                for x2 in x1.childNodes:\n                    res.append(x2.toxml())\n        return res\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/tone_sandhi.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\nfrom typing import Tuple\n\nimport jieba\nfrom pypinyin import lazy_pinyin\nfrom pypinyin import Style\n\n\nclass ToneSandhi():\n    def __repr__(self):\n        return \"MandarinToneSandhi\"\n\n    def __init__(self):\n        self.must_neural_tone_words = {\n            '麻烦', '麻利', '鸳鸯', '高粱', '骨头', '骆驼', '马虎', '首饰', '馒头', '馄饨', '风筝',\n            '难为', '队伍', '阔气', '闺女', '门道', '锄头', '铺盖', '铃铛', '铁匠', '钥匙', '里脊',\n            '里头', '部分', '那么', '道士', '造化', '迷糊', '连累', '这么', '这个', '运气', '过去',\n            '软和', '转悠', '踏实', '跳蚤', '跟头', '趔趄', '财主', '豆腐', '讲究', '记性', '记号',\n            '认识', '规矩', '见识', '裁缝', '补丁', '衣裳', '衣服', '衙门', '街坊', '行李', '行当',\n            '蛤蟆', '蘑菇', '薄荷', '葫芦', '葡萄', '萝卜', '荸荠', '苗条', '苗头', '苍蝇', '芝麻',\n            '舒服', '舒坦', '舌头', '自在', '膏药', '脾气', '脑袋', '脊梁', '能耐', '胳膊', '胭脂',\n            '胡萝', '胡琴', '胡同', '聪明', '耽误', '耽搁', '耷拉', '耳朵', '老爷', '老实', '老婆',\n            '戏弄', '将军', '翻腾', '罗嗦', '罐头', '编辑', '结实', '红火', '累赘', '糨糊', '糊涂',\n            '精神', '粮食', '簸箕', '篱笆', '算计', '算盘', '答应', '笤帚', '笑语', '笑话', '窟窿',\n            '窝囊', '窗户', '稳当', '稀罕', '称呼', '秧歌', '秀气', '秀才', '福气', '祖宗', '砚台',\n            '码头', '石榴', '石头', '石匠', '知识', '眼睛', '眯缝', '眨巴', '眉毛', '相声', '盘算',\n            '白净', '痢疾', '痛快', '疟疾', '疙瘩', '疏忽', '畜生', '生意', '甘蔗', '琵琶', '琢磨',\n            '琉璃', '玻璃', '玫瑰', '玄乎', '狐狸', '状元', '特务', '牲口', '牙碜', '牌楼', '爽快',\n            '爱人', '热闹', '烧饼', '烟筒', '烂糊', '点心', '炊帚', '灯笼', '火候', '漂亮', '滑溜',\n            '溜达', '温和', '清楚', '消息', '浪头', '活泼', '比方', '正经', '欺负', '模糊', '槟榔',\n            '棺材', '棒槌', '棉花', '核桃', '栅栏', '柴火', '架势', '枕头', '枇杷', '机灵', '本事',\n            '木头', '木匠', '朋友', '月饼', '月亮', '暖和', '明白', '时候', '新鲜', '故事', '收拾',\n            '收成', '提防', '挖苦', '挑剔', '指甲', '指头', '拾掇', '拳头', '拨弄', '招牌', '招呼',\n            '抬举', '护士', '折腾', '扫帚', '打量', '打算', '打扮', '打听', '打发', '扎实', '扁担',\n            '戒指', '懒得', '意识', '意思', '悟性', '怪物', '思量', '怎么', '念头', '念叨', '别人',\n            '快活', '忙活', '志气', '心思', '得罪', '张罗', '弟兄', '开通', '应酬', '庄稼', '干事',\n            '帮手', '帐篷', '希罕', '师父', '师傅', '巴结', '巴掌', '差事', '工夫', '岁数', '屁股',\n            '尾巴', '少爷', '小气', '小伙', '将就', '对头', '对付', '寡妇', '家伙', '客气', '实在',\n            '官司', '学问', '字号', '嫁妆', '媳妇', '媒人', '婆家', '娘家', '委屈', '姑娘', '姐夫',\n            '妯娌', '妥当', '妖精', '奴才', '女婿', '头发', '太阳', '大爷', '大方', '大意', '大夫',\n            '多少', '多么', '外甥', '壮实', '地道', '地方', '在乎', '困难', '嘴巴', '嘱咐', '嘟囔',\n            '嘀咕', '喜欢', '喇嘛', '喇叭', '商量', '唾沫', '哑巴', '哈欠', '哆嗦', '咳嗽', '和尚',\n            '告诉', '告示', '含糊', '吓唬', '后头', '名字', '名堂', '合同', '吆喝', '叫唤', '口袋',\n            '厚道', '厉害', '千斤', '包袱', '包涵', '匀称', '勤快', '动静', '动弹', '功夫', '力气',\n            '前头', '刺猬', '刺激', '别扭', '利落', '利索', '利害', '分析', '出息', '凑合', '凉快',\n            '冷战', '冤枉', '冒失', '养活', '关系', '先生', '兄弟', '便宜', '使唤', '佩服', '作坊',\n            '体面', '位置', '似的', '伙计', '休息', '什么', '人家', '亲戚', '亲家', '交情', '云彩',\n            '事情', '买卖', '主意', '丫头', '丧气', '两口', '东西', '东家', '世故', '不由', '下水',\n            '下巴', '上头', '上司', '丈夫', '丈人', '一辈', '那个', '菩萨', '父亲', '母亲', '咕噜',\n            '邋遢', '费用', '冤家', '甜头', '介绍', '荒唐', '大人', '泥鳅', '幸福', '熟悉', '计划',\n            '扑腾', '蜡烛', '姥爷', '照顾', '喉咙', '吉他', '弄堂', '蚂蚱', '凤凰', '拖沓', '寒碜',\n            '糟蹋', '倒腾', '报复', '逻辑', '盘缠', '喽啰', '牢骚', '咖喱', '扫把', '惦记'\n        }\n        self.must_not_neural_tone_words = {\n            '男子', '女子', '分子', '原子', '量子', '莲子', '石子', '瓜子', '电子', '人人', '虎虎',\n            '幺幺', '干嘛', '学子', '哈哈', '数数', '袅袅', '局地', '以下', '娃哈哈', '花花草草', '留得',\n            '耕地', '想想', '熙熙', '攘攘', '卵子', '死死', '冉冉', '恳恳', '佼佼', '吵吵', '打打',\n            '考考', '整整', '莘莘', '落地', '算子', '家家户户', '青青'\n        }\n        self.punc = \"、：，；。？！“”‘’':,;.?!\"\n\n    def _split_word(self, word: str) -> List[str]:\n        word_list = jieba.cut_for_search(word)\n        word_list = sorted(word_list, key=lambda i: len(i), reverse=False)\n        first_subword = word_list[0]\n        first_begin_idx = word.find(first_subword)\n        if first_begin_idx == 0:\n            second_subword = word[len(first_subword):]\n            new_word_list = [first_subword, second_subword]\n        else:\n            second_subword = word[:-len(first_subword)]\n            new_word_list = [second_subword, first_subword]\n        return new_word_list\n\n    # the meaning of jieba pos tag: https://blog.csdn.net/weixin_44174352/article/details/113731041\n    # e.g.\n    # word: \"家里\"\n    # pos: \"s\"\n    # finals: ['ia1', 'i3']\n    def _neural_sandhi(self, word: str, pos: str,\n                       finals: List[str]) -> List[str]:\n        if word in self.must_not_neural_tone_words:\n            return finals\n        # reduplication words for n. and v. e.g. 奶奶, 试试, 旺旺\n        for j, item in enumerate(word):\n            if j - 1 >= 0 and item == word[j - 1] and pos[0] in {\"n\", \"v\", \"a\"}:\n                finals[j] = finals[j][:-1] + \"5\"\n        ge_idx = word.find(\"个\")\n        if len(word) >= 1 and word[-1] in \"吧呢啊呐噻嘛吖嗨呐哦哒滴哩哟喽啰耶喔诶\":\n            finals[-1] = finals[-1][:-1] + \"5\"\n        elif len(word) >= 1 and word[-1] in \"的地得\":\n            finals[-1] = finals[-1][:-1] + \"5\"\n        # e.g. 走了, 看着, 去过\n        elif len(word) == 1 and word in \"了着过\" and pos in {\"ul\", \"uz\", \"ug\"}:\n            finals[-1] = finals[-1][:-1] + \"5\"\n        elif len(word) > 1 and word[-1] in \"们子\" and pos in {\"r\", \"n\"}:\n            finals[-1] = finals[-1][:-1] + \"5\"\n        # e.g. 桌上, 地下\n        elif len(word) > 1 and word[-1] in \"上下\" and pos in {\"s\", \"l\", \"f\"}:\n            finals[-1] = finals[-1][:-1] + \"5\"\n        # e.g. 上来, 下去\n        elif len(word) > 1 and word[-1] in \"来去\" and word[-2] in \"上下进出回过起开\":\n            finals[-1] = finals[-1][:-1] + \"5\"\n        # 个做量词\n        elif (ge_idx >= 1 and\n              (word[ge_idx - 1].isnumeric() or\n               word[ge_idx - 1] in \"几有两半多各整每做是\")) or word == '个':\n            finals[ge_idx] = finals[ge_idx][:-1] + \"5\"\n        else:\n            if word in self.must_neural_tone_words or word[\n                    -2:] in self.must_neural_tone_words:\n                finals[-1] = finals[-1][:-1] + \"5\"\n\n        word_list = self._split_word(word)\n        finals_list = [finals[:len(word_list[0])], finals[len(word_list[0]):]]\n        for i, word in enumerate(word_list):\n            # conventional neural in Chinese\n            if word in self.must_neural_tone_words or word[\n                    -2:] in self.must_neural_tone_words:\n                finals_list[i][-1] = finals_list[i][-1][:-1] + \"5\"\n        finals = sum(finals_list, [])\n        return finals\n\n    def _bu_sandhi(self, word: str, finals: List[str]) -> List[str]:\n        # e.g. 看不懂\n        if len(word) == 3 and word[1] == \"不\":\n            finals[1] = finals[1][:-1] + \"5\"\n        else:\n            for i, char in enumerate(word):\n                # \"不\" before tone4 should be bu2, e.g. 不怕\n                if char == \"不\" and i + 1 < len(word) and finals[i +\n                                                                1][-1] == \"4\":\n                    finals[i] = finals[i][:-1] + \"2\"\n        return finals\n\n    def _yi_sandhi(self, word: str, finals: List[str]) -> List[str]:\n        # \"一\" in number sequences, e.g. 一零零, 二一零\n        if word.find(\"一\") != -1 and all(\n            [item.isnumeric() for item in word if item != \"一\"]):\n            return finals\n        # \"一\" between reduplication words shold be yi5, e.g. 看一看\n        elif len(word) == 3 and word[1] == \"一\" and word[0] == word[-1]:\n            finals[1] = finals[1][:-1] + \"5\"\n        # when \"一\" is ordinal word, it should be yi1\n        elif word.startswith(\"第一\"):\n            finals[1] = finals[1][:-1] + \"1\"\n        else:\n            for i, char in enumerate(word):\n                if char == \"一\" and i + 1 < len(word):\n                    # \"一\" before tone4 should be yi2, e.g. 一段\n                    if finals[i + 1][-1] in {'4', '5'}:\n                        finals[i] = finals[i][:-1] + \"2\"\n                    # \"一\" before non-tone4 should be yi4, e.g. 一天\n                    else:\n                        # \"一\" 后面如果是标点，还读一声\n                        if word[i + 1] not in self.punc:\n                            finals[i] = finals[i][:-1] + \"4\"\n        return finals\n\n    def _all_tone_three(self, finals: List[str]) -> bool:\n        return all(x[-1] == \"3\" for x in finals)\n\n    def _three_sandhi(self, word: str, finals: List[str]) -> List[str]:\n\n        if len(word) == 2 and self._all_tone_three(finals):\n            finals[0] = finals[0][:-1] + \"2\"\n        elif len(word) == 3:\n            word_list = self._split_word(word)\n            if self._all_tone_three(finals):\n                #  disyllabic + monosyllabic, e.g. 蒙古/包\n                if len(word_list[0]) == 2:\n                    finals[0] = finals[0][:-1] + \"2\"\n                    finals[1] = finals[1][:-1] + \"2\"\n                #  monosyllabic + disyllabic, e.g. 纸/老虎\n                elif len(word_list[0]) == 1:\n                    finals[1] = finals[1][:-1] + \"2\"\n            else:\n                finals_list = [\n                    finals[:len(word_list[0])], finals[len(word_list[0]):]\n                ]\n                if len(finals_list) == 2:\n                    for i, sub in enumerate(finals_list):\n                        # e.g. 所有/人\n                        if self._all_tone_three(sub) and len(sub) == 2:\n                            finals_list[i][0] = finals_list[i][0][:-1] + \"2\"\n                        # e.g. 好/喜欢\n                        elif i == 1 and not self._all_tone_three(sub) and finals_list[i][0][-1] == \"3\" and \\\n                                finals_list[0][-1][-1] == \"3\":\n\n                            finals_list[0][-1] = finals_list[0][-1][:-1] + \"2\"\n                        finals = sum(finals_list, [])\n        # split idiom into two words who's length is 2\n        elif len(word) == 4:\n            finals_list = [finals[:2], finals[2:]]\n            finals = []\n            for sub in finals_list:\n                if self._all_tone_three(sub):\n                    sub[0] = sub[0][:-1] + \"2\"\n                finals += sub\n\n        return finals\n\n    # merge \"不\" and the word behind it\n    # if don't merge, \"不\" sometimes appears alone according to jieba, which may occur sandhi error\n    def _merge_bu(self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        last_word = \"\"\n        for word, pos in seg:\n            if last_word == \"不\":\n                word = last_word + word\n            if word != \"不\":\n                new_seg.append((word, pos))\n            last_word = word[:]\n        if last_word == \"不\":\n            new_seg.append((last_word, 'd'))\n            last_word = \"\"\n        return new_seg\n\n    # function 1: merge \"一\" and reduplication words in it's left and right, e.g. \"听\",\"一\",\"听\" ->\"听一听\"\n    # function 2: merge single  \"一\" and the word behind it\n    # if don't merge, \"一\" sometimes appears alone according to jieba, which may occur sandhi error\n    # e.g.\n    # input seg: [('听', 'v'), ('一', 'm'), ('听', 'v')]\n    # output seg: [['听一听', 'v']]\n    def _merge_yi(self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        skip_next = False\n        # function 1\n        for i, (word, pos) in enumerate(seg):\n            if skip_next:\n                skip_next = False\n                continue\n            if i - 1 >= 0 and word == \"一\" and i + 1 < len(seg) and seg[i - 1][\n                    0] == seg[i + 1][0] and seg[i - 1][1] == \"v\":\n                new_seg[-1] = (new_seg[-1][0] + \"一\" + seg[i + 1][0],\n                               new_seg[-1][1])\n                skip_next = True\n            else:\n                new_seg.append((word, pos))\n        seg = new_seg\n        new_seg = []\n        # function 2\n        for i, (word, pos) in enumerate(seg):\n            if new_seg and new_seg[-1][0] == \"一\":\n                new_seg[-1] = (new_seg[-1][0] + word, new_seg[-1][1])\n            else:\n                new_seg.append((word, pos))\n        return new_seg\n\n    # the first and the second words are all_tone_three\n    def _merge_continuous_three_tones(\n            self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        sub_finals_list = []\n        for (word, pos) in seg:\n            orig_finals = lazy_pinyin(\n                word, neutral_tone_with_five=True, style=Style.FINALS_TONE3)\n            # after pypinyin==0.44.0, '嗯' need to be n2, cause the initial and final consonants cannot be empty at the same time\n            en_index = [index for index, c in enumerate(word) if c == \"嗯\"]\n            for i in en_index:\n                orig_finals[i] = \"n2\"\n            sub_finals_list.append(orig_finals)\n\n        assert len(sub_finals_list) == len(seg)\n        merge_last = [False] * len(seg)\n        for i, (word, pos) in enumerate(seg):\n            if i - 1 >= 0 and self._all_tone_three(\n                    sub_finals_list[i - 1]) and self._all_tone_three(\n                        sub_finals_list[i]) and not merge_last[i - 1]:\n                # if the last word is reduplication, not merge, because reduplication need to be _neural_sandhi\n                if not self._is_reduplication(seg[i - 1][0]) and len(\n                        seg[i - 1][0]) + len(seg[i][0]) <= 3:\n                    new_seg[-1][0] = new_seg[-1][0] + seg[i][0]\n                    merge_last[i] = True\n                else:\n                    new_seg.append([word, pos])\n            else:\n                new_seg.append([word, pos])\n\n        return new_seg\n\n    def _is_reduplication(self, word: str) -> bool:\n        return len(word) == 2 and word[0] == word[1]\n\n    # the last char of first word and the first char of second word is tone_three\n    def _merge_continuous_three_tones_2(\n            self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        sub_finals_list = []\n        for (word, pos) in seg:\n            orig_finals = lazy_pinyin(\n                word, neutral_tone_with_five=True, style=Style.FINALS_TONE3)\n            # after pypinyin==0.44.0, '嗯' need to be n2, cause the initial and final consonants cannot be empty at the same time\n            en_index = [index for index, c in enumerate(word) if c == \"嗯\"]\n            for i in en_index:\n                orig_finals[i] = \"n2\"\n            sub_finals_list.append(orig_finals)\n        assert len(sub_finals_list) == len(seg)\n        merge_last = [False] * len(seg)\n        for i, (word, pos) in enumerate(seg):\n            if i - 1 >= 0 and sub_finals_list[i - 1][-1][-1] == \"3\" and sub_finals_list[i][0][-1] == \"3\" and not \\\n                    merge_last[i - 1]:\n                # if the last word is reduplication, not merge, because reduplication need to be _neural_sandhi\n                if not self._is_reduplication(seg[i - 1][0]) and len(\n                        seg[i - 1][0]) + len(seg[i][0]) <= 3:\n                    new_seg[-1][0] = new_seg[-1][0] + seg[i][0]\n                    merge_last[i] = True\n                else:\n                    new_seg.append([word, pos])\n            else:\n                new_seg.append([word, pos])\n        return new_seg\n\n    def _merge_er(self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        for i, (word, pos) in enumerate(seg):\n            if i - 1 >= 0 and word == \"儿\":\n                new_seg[-1][0] = new_seg[-1][0] + seg[i][0]\n            else:\n                new_seg.append([word, pos])\n        return new_seg\n\n    def _merge_reduplication(\n            self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        new_seg = []\n        for i, (word, pos) in enumerate(seg):\n            if new_seg and word == new_seg[-1][0]:\n                new_seg[-1][0] = new_seg[-1][0] + seg[i][0]\n            else:\n                new_seg.append([word, pos])\n        return new_seg\n\n    def pre_merge_for_modify(\n            self, seg: List[Tuple[str, str]]) -> List[Tuple[str, str]]:\n        \"\"\"\n            seg: [(word, pos), ...]\n        \"\"\"\n        seg = self._merge_bu(seg)\n        seg = self._merge_yi(seg)\n        seg = self._merge_reduplication(seg)\n        seg = self._merge_continuous_three_tones(seg)\n        seg = self._merge_continuous_three_tones_2(seg)\n        seg = self._merge_er(seg)\n        return seg\n\n    def modified_tone(self, word: str, pos: str,\n                      finals: List[str]) -> List[str]:\n        \"\"\"\n            word: 分词\n            pos: 词性\n            finals: 带调韵母, [final1, ..., finaln]\n        \"\"\"\n        finals = self._bu_sandhi(word, finals)\n        finals = self._yi_sandhi(word, finals)\n        finals = self._neural_sandhi(word, pos, finals)\n        finals = self._three_sandhi(word, finals)\n        return finals\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/vocab.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom collections import OrderedDict\nfrom typing import Iterable\n\n__all__ = [\"Vocab\"]\n\n\nclass Vocab(object):\n    \"\"\"  Vocabulary.\n\n    Args:\n        symbols (Iterable[str]): Common symbols.\n        padding_symbol (str, optional): Symbol for pad. Defaults to \"<pad>\".\n        unk_symbol (str, optional): Symbol for unknow. Defaults to \"<unk>\"\n        start_symbol (str, optional): Symbol for start. Defaults to \"<s>\"\n        end_symbol (str, optional): Symbol for end. Defaults to \"</s>\"\n    \"\"\"\n\n    def __init__(self,\n                 symbols: Iterable[str],\n                 padding_symbol=\"<pad>\",\n                 unk_symbol=\"<unk>\",\n                 start_symbol=\"<s>\",\n                 end_symbol=\"</s>\"):\n        self.special_symbols = OrderedDict()\n        for i, item in enumerate(\n            [padding_symbol, unk_symbol, start_symbol, end_symbol]):\n            if item:\n                self.special_symbols[item] = len(self.special_symbols)\n\n        self.padding_symbol = padding_symbol\n        self.unk_symbol = unk_symbol\n        self.start_symbol = start_symbol\n        self.end_symbol = end_symbol\n\n        self.stoi = OrderedDict()\n        self.stoi.update(self.special_symbols)\n\n        for i, s in enumerate(symbols):\n            if s not in self.stoi:\n                self.stoi[s] = len(self.stoi)\n        self.itos = {v: k for k, v in self.stoi.items()}\n\n    def __len__(self):\n        return len(self.stoi)\n\n    @property\n    def num_specials(self):\n        \"\"\" The number of special symbols.\n        \"\"\"\n        return len(self.special_symbols)\n\n    # special tokens\n    @property\n    def padding_index(self):\n        \"\"\" The index of padding symbol\n        \"\"\"\n        return self.stoi.get(self.padding_symbol, -1)\n\n    @property\n    def unk_index(self):\n        \"\"\"The index of unknow symbol.\n        \"\"\"\n        return self.stoi.get(self.unk_symbol, -1)\n\n    @property\n    def start_index(self):\n        \"\"\"The index of start symbol.\n        \"\"\"\n        return self.stoi.get(self.start_symbol, -1)\n\n    @property\n    def end_index(self):\n        \"\"\" The index of end symbol.\n        \"\"\"\n        return self.stoi.get(self.end_symbol, -1)\n\n    def __repr__(self):\n        fmt = \"Vocab(size: {},\\nstoi:\\n{})\"\n        return fmt.format(len(self), self.stoi)\n\n    def __str__(self):\n        return self.__repr__()\n\n    def lookup(self, symbol):\n        \"\"\" The index that symbol correspond.\n        \"\"\"\n        return self.stoi[symbol]\n\n    def reverse(self, index):\n        \"\"\" The symbol thar index cottespond.\n        \"\"\"\n        return self.itos[index]\n\n    def add_symbol(self, symbol):\n        \"\"\" Add a new symbol in vocab.\n        \"\"\"\n        if symbol in self.stoi:\n            return\n        N = len(self.stoi)\n        self.stoi[symbol] = N\n        self.itos[N] = symbol\n\n    def add_symbols(self, symbols):\n        \"\"\" Add multiple symbols in vocab.\n        \"\"\"\n        for symbol in symbols:\n            self.add_symbol(symbol)\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_frontend.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport re\nfrom operator import itemgetter\nfrom pprint import pprint\nfrom typing import Dict\nfrom typing import List\n\nimport jieba.posseg as psg\nimport numpy as np\nimport paddle\nimport yaml\nfrom g2pM import G2pM\nfrom pypinyin import lazy_pinyin\nfrom pypinyin import load_phrases_dict\nfrom pypinyin import load_single_dict\nfrom pypinyin import Style\nfrom pypinyin_dict.phrase_pinyin_data import large_pinyin\n\nfrom paddlespeech.t2s.frontend.g2pw import G2PWOnnxConverter\nfrom paddlespeech.t2s.frontend.generate_lexicon import generate_lexicon\nfrom paddlespeech.t2s.frontend.polyphonic import Polyphonic\nfrom paddlespeech.t2s.frontend.rhy_prediction.rhy_predictor import RhyPredictor\nfrom paddlespeech.t2s.frontend.ssml.xml_processor import MixTextProcessor\nfrom paddlespeech.t2s.frontend.tone_sandhi import ToneSandhi\nfrom paddlespeech.t2s.frontend.zh_normalization.text_normlization import TextNormalizer\n\nINITIALS = [\n    'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'zh', 'ch', 'sh',\n    'r', 'z', 'c', 's', 'j', 'q', 'x'\n]\nINITIALS += ['y', 'w', 'sp', 'spl', 'spn', 'sil']\n\n# 0 for None, 5 for neutral\nTONES = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\"]\n\n\ndef intersperse(lst, item):\n    result = [item] * (len(lst) * 2 + 1)\n    result[1::2] = lst\n    return result\n\n\ndef insert_after_character(lst, item):\n    \"\"\"\n    inset `item` after finals.\n    \"\"\"\n    result = [item]\n\n    for phone in lst:\n        result.append(phone)\n        if phone not in INITIALS:\n            # finals has tones\n            # assert phone[-1] in \"12345\"\n            result.append(item)\n\n    return result\n\n\nclass Frontend():\n    def __init__(self,\n                 g2p_model=\"g2pW\",\n                 phone_vocab_path=None,\n                 tone_vocab_path=None,\n                 use_rhy=False):\n\n        self.punc = \"、：，；。？！“”‘’':,;.?!\"\n        self.rhy_phns = ['sp1', 'sp2', 'sp3', 'sp4']\n        self.phrases_dict = {\n            '开户行': [['ka1i'], ['hu4'], ['hang2']],\n            '发卡行': [['fa4'], ['ka3'], ['hang2']],\n            '放款行': [['fa4ng'], ['kua3n'], ['hang2']],\n            '茧行': [['jia3n'], ['hang2']],\n            '行号': [['hang2'], ['ha4o']],\n            '各地': [['ge4'], ['di4']],\n            '借还款': [['jie4'], ['hua2n'], ['kua3n']],\n            '时间为': [['shi2'], ['jia1n'], ['we2i']],\n            '为准': [['we2i'], ['zhu3n']],\n            '色差': [['se4'], ['cha1']],\n            '嗲': [['dia3']],\n            '呗': [['bei5']],\n            '不': [['bu4']],\n            '咗': [['zuo5']],\n            '嘞': [['lei5']],\n            '掺和': [['chan1'], ['huo5']]\n        }\n\n        self.must_erhua = {\n            \"小院儿\", \"胡同儿\", \"范儿\", \"老汉儿\", \"撒欢儿\", \"寻老礼儿\", \"妥妥儿\", \"媳妇儿\"\n        }\n        self.not_erhua = {\n            \"虐儿\", \"为儿\", \"护儿\", \"瞒儿\", \"救儿\", \"替儿\", \"有儿\", \"一儿\", \"我儿\", \"俺儿\", \"妻儿\",\n            \"拐儿\", \"聋儿\", \"乞儿\", \"患儿\", \"幼儿\", \"孤儿\", \"婴儿\", \"婴幼儿\", \"连体儿\", \"脑瘫儿\",\n            \"流浪儿\", \"体弱儿\", \"混血儿\", \"蜜雪儿\", \"舫儿\", \"祖儿\", \"美儿\", \"应采儿\", \"可儿\", \"侄儿\",\n            \"孙儿\", \"侄孙儿\", \"女儿\", \"男儿\", \"红孩儿\", \"花儿\", \"虫儿\", \"马儿\", \"鸟儿\", \"猪儿\", \"猫儿\",\n            \"狗儿\", \"少儿\"\n        }\n\n        self.vocab_phones = {}\n        self.vocab_tones = {}\n        if phone_vocab_path:\n            with open(phone_vocab_path, 'rt', encoding='utf-8') as f:\n                phn_id = [line.strip().split() for line in f.readlines()]\n            for phn, id in phn_id:\n                self.vocab_phones[phn] = int(id)\n        if tone_vocab_path:\n            with open(tone_vocab_path, 'rt', encoding='utf-8') as f:\n                tone_id = [line.strip().split() for line in f.readlines()]\n            for tone, id in tone_id:\n                self.vocab_tones[tone] = int(id)\n\n        # SSML\n        self.mix_ssml_processor = MixTextProcessor()\n        # tone sandhi\n        self.tone_modifier = ToneSandhi()\n        # TN\n        self.text_normalizer = TextNormalizer()\n\n        # prosody\n        self.use_rhy = use_rhy\n        if use_rhy:\n            self.rhy_predictor = RhyPredictor()\n            print(\"Rhythm predictor loaded.\")\n\n        # g2p\n        assert g2p_model in ('pypinyin', 'g2pM', 'g2pW')\n        self.g2p_model = g2p_model\n        if self.g2p_model == \"g2pM\":\n            self.g2pM_model = G2pM()\n            self.pinyin2phone = generate_lexicon(\n                with_tone=True, with_erhua=False)\n        elif self.g2p_model == \"g2pW\":\n            # use pypinyin as backup for non polyphonic characters in g2pW\n            self._init_pypinyin()\n            self.corrector = Polyphonic()\n            self.g2pM_model = G2pM()\n            self.g2pW_model = G2PWOnnxConverter(\n                style='pinyin', enable_non_tradional_chinese=True)\n            self.pinyin2phone = generate_lexicon(\n                with_tone=True, with_erhua=False)\n        else:\n            self._init_pypinyin()\n\n    def _init_pypinyin(self):\n        \"\"\"\n        Load pypinyin G2P module.\n        \"\"\"\n        large_pinyin.load()\n        load_phrases_dict(self.phrases_dict)\n        # 调整字的拼音顺序\n        load_single_dict({ord(u'地'): u'de,di4'})\n\n    def _get_initials_finals(self, word: str) -> List[List[str]]:\n        \"\"\"\n        Get word initial and final by pypinyin or g2pM\n        \"\"\"\n        initials = []\n        finals = []\n        if self.g2p_model == \"pypinyin\":\n            orig_initials = lazy_pinyin(\n                word, neutral_tone_with_five=True, style=Style.INITIALS)\n            orig_finals = lazy_pinyin(\n                word, neutral_tone_with_five=True, style=Style.FINALS_TONE3)\n            # after pypinyin==0.44.0, '嗯' need to be n2, cause the initial and final consonants cannot be empty at the same time\n            en_index = [index for index, c in enumerate(word) if c == \"嗯\"]\n            for i in en_index:\n                orig_finals[i] = \"n2\"\n\n            for c, v in zip(orig_initials, orig_finals):\n                if re.match(r'i\\d', v):\n                    if c in ['z', 'c', 's']:\n                        # zi, ci, si\n                        v = re.sub('i', 'ii', v)\n                    elif c in ['zh', 'ch', 'sh', 'r']:\n                        # zhi, chi, shi\n                        v = re.sub('i', 'iii', v)\n                initials.append(c)\n                finals.append(v)\n\n        elif self.g2p_model == \"g2pM\":\n            pinyins = self.g2pM_model(word, tone=True, char_split=False)\n            for pinyin in pinyins:\n                pinyin = pinyin.replace(\"u:\", \"v\")\n                if pinyin in self.pinyin2phone:\n                    initial_final_list = self.pinyin2phone[pinyin].split(\" \")\n                    if len(initial_final_list) == 2:\n                        initials.append(initial_final_list[0])\n                        finals.append(initial_final_list[1])\n                    elif len(initial_final_list) == 1:\n                        initials.append('')\n                        finals.append(initial_final_list[1])\n                else:\n                    # If it's not pinyin (possibly punctuation) or no conversion is required\n                    initials.append(pinyin)\n                    finals.append(pinyin)\n\n        return initials, finals\n\n    def _merge_erhua(self,\n                     initials: List[str],\n                     finals: List[str],\n                     word: str,\n                     pos: str) -> List[List[str]]:\n        \"\"\"\n        Do erhub.\n        \"\"\"\n        # fix er1\n        for i, phn in enumerate(finals):\n            if i == len(finals) - 1 and word[i] == \"儿\" and phn == 'er1':\n                finals[i] = 'er2'\n\n        # 发音\n        if word not in self.must_erhua and (word in self.not_erhua or\n                                            pos in {\"a\", \"j\", \"nr\"}):\n            return initials, finals\n\n        # \"……\" 等情况直接返回\n        if len(finals) != len(word):\n            return initials, finals\n\n        assert len(finals) == len(word)\n\n        # 不发音\n        new_initials = []\n        new_finals = []\n        for i, phn in enumerate(finals):\n            if i == len(finals) - 1 and word[i] == \"儿\" and phn in {\n                    \"er2\", \"er5\"\n            } and word[-2:] not in self.not_erhua and new_finals:\n                new_finals[-1] = new_finals[-1][:-1] + \"r\" + new_finals[-1][-1]\n            else:\n                new_initials.append(initials[i])\n                new_finals.append(phn)\n\n        return new_initials, new_finals\n\n    # if merge_sentences, merge all sentences into one phone sequence\n    def _g2p(self,\n             sentences: List[str],\n             merge_sentences: bool=True,\n             with_erhua: bool=True) -> List[List[str]]:\n        \"\"\"\n        Return: list of list phonemes.\n            [['w', 'o3', 'm', 'en2', 'sp'], ...]\n        \"\"\"\n        segments = sentences\n        phones_list = []\n\n        # split by punctuation\n        for seg in segments:\n            if self.use_rhy:\n                seg = self.rhy_predictor._clean_text(seg)\n\n            # remove all English words in the sentence\n            seg = re.sub('[a-zA-Z]+', '', seg)\n\n            # add prosody mark\n            if self.use_rhy:\n                seg = self.rhy_predictor.get_prediction(seg)\n\n            # [(word, pos), ...]\n            seg_cut = psg.lcut(seg)\n            # fix wordseg bad case for sandhi\n            seg_cut = self.tone_modifier.pre_merge_for_modify(seg_cut)\n\n            # 为了多音词获得更好的效果，这里采用整句预测\n            phones = []\n            initials = []\n            finals = []\n            if self.g2p_model == \"g2pW\":\n                try:\n                    # undo prosody \n                    if self.use_rhy:\n                        seg = self.rhy_predictor._clean_text(seg)\n\n                    # g2p\n                    pinyins = self.g2pW_model(seg)[0]\n                except Exception:\n                    # g2pW 模型采用繁体输入，如果有cover不了的简体词，采用g2pM预测\n                    print(\"[%s] not in g2pW dict,use g2pM\" % seg)\n                    pinyins = self.g2pM_model(seg, tone=True, char_split=False)\n\n                # do prosody\n                if self.use_rhy:\n                    rhy_text = self.rhy_predictor.get_prediction(seg)\n                    final_py = self.rhy_predictor.pinyin_align(pinyins,\n                                                               rhy_text)\n                    pinyins = final_py\n\n                pre_word_length = 0\n                for word, pos in seg_cut:\n                    sub_initials = []\n                    sub_finals = []\n                    now_word_length = pre_word_length + len(word)\n\n                    # skip english word\n                    if pos == 'eng':\n                        pre_word_length = now_word_length\n                        continue\n\n                    word_pinyins = pinyins[pre_word_length:now_word_length]\n\n                    # 多音字消歧\n                    word_pinyins = self.corrector.correct_pronunciation(\n                        word, word_pinyins)\n\n                    for pinyin, char in zip(word_pinyins, word):\n                        if pinyin is None:\n                            pinyin = char\n\n                        pinyin = pinyin.replace(\"u:\", \"v\")\n\n                        if pinyin in self.pinyin2phone:\n                            initial_final_list = self.pinyin2phone[\n                                pinyin].split(\" \")\n                            if len(initial_final_list) == 2:\n                                sub_initials.append(initial_final_list[0])\n                                sub_finals.append(initial_final_list[1])\n                            elif len(initial_final_list) == 1:\n                                sub_initials.append('')\n                                sub_finals.append(initial_final_list[1])\n                        else:\n                            # If it's not pinyin (possibly punctuation) or no conversion is required\n                            sub_initials.append(pinyin)\n                            sub_finals.append(pinyin)\n\n                    pre_word_length = now_word_length\n                    # tone sandhi\n                    sub_finals = self.tone_modifier.modified_tone(word, pos,\n                                                                  sub_finals)\n                    # er hua                                \n                    if with_erhua:\n                        sub_initials, sub_finals = self._merge_erhua(\n                            sub_initials, sub_finals, word, pos)\n\n                    initials.append(sub_initials)\n                    finals.append(sub_finals)\n                    # assert len(sub_initials) == len(sub_finals) == len(word)\n            else:\n                # pypinyin, g2pM\n                for word, pos in seg_cut:\n                    if pos == 'eng':\n                        # skip english word\n                        continue\n\n                    # g2p\n                    sub_initials, sub_finals = self._get_initials_finals(word)\n                    # tone sandhi\n                    sub_finals = self.tone_modifier.modified_tone(word, pos,\n                                                                  sub_finals)\n                    # er hua\n                    if with_erhua:\n                        sub_initials, sub_finals = self._merge_erhua(\n                            sub_initials, sub_finals, word, pos)\n\n                    initials.append(sub_initials)\n                    finals.append(sub_finals)\n                    # assert len(sub_initials) == len(sub_finals) == len(word)\n\n                # sum(iterable[, start])\n            initials = sum(initials, [])\n            finals = sum(finals, [])\n\n            for c, v in zip(initials, finals):\n                # NOTE: post process for pypinyin outputs\n                # we discriminate i, ii and iii\n                if c and c not in self.punc:\n                    phones.append(c)\n                # replace punctuation by `sp`\n                if c and c in self.punc:\n                    phones.append('sp')\n\n                if v and v not in self.punc and v not in self.rhy_phns:\n                    phones.append(v)\n\n            phones_list.append(phones)\n\n        # merge split sub sentence into one sentence.\n        if merge_sentences:\n            # sub sentence phonemes\n            merge_list = sum(phones_list, [])\n            # rm the last 'sp' to avoid the noise at the end\n            # cause in the training data, no 'sp' in the end\n            if merge_list[-1] == 'sp':\n                merge_list = merge_list[:-1]\n\n            # sentence phonemes\n            phones_list = []\n            phones_list.append(merge_list)\n\n        return phones_list\n\n    def _p2id(self, phonemes: List[str]) -> np.ndarray:\n        \"\"\"\n        Phoneme to Index\n        \"\"\"\n        # replace unk phone with sp\n        phonemes = [\n            phn if phn in self.vocab_phones else \"sp\" for phn in phonemes\n        ]\n        phone_ids = [self.vocab_phones[item] for item in phonemes]\n        return np.array(phone_ids, np.int64)\n\n    def _t2id(self, tones: List[str]) -> np.ndarray:\n        \"\"\"\n        Tone to Index.\n        \"\"\"\n        # replace unk phone with sp\n        tones = [tone if tone in self.vocab_tones else \"0\" for tone in tones]\n        tone_ids = [self.vocab_tones[item] for item in tones]\n        return np.array(tone_ids, np.int64)\n\n    def _get_phone_tone(self, phonemes: List[str],\n                        get_tone_ids: bool=False) -> List[List[str]]:\n        \"\"\"\n        Get tone from phonemes.\n        \"\"\"\n        phones = []\n        tones = []\n        if get_tone_ids and self.vocab_tones:\n            for full_phone in phonemes:\n                # split tone from finals\n                match = re.match(r'^(\\w+)([012345])$', full_phone)\n                if match:\n                    phone = match.group(1)\n                    tone = match.group(2)\n                    # if the merged erhua not in the vocab\n                    # assume that the input is ['iaor3'] and 'iaor' not in self.vocab_phones, we split 'iaor' into ['iao','er']\n                    # and the tones accordingly change from ['3'] to ['3','2'], while '2' is the tone of 'er2'\n                    if len(phone) >= 2 and phone != \"er\" and phone[\n                            -1] == 'r' and phone not in self.vocab_phones and phone[:\n                                                                                    -1] in self.vocab_phones:\n                        phones.append(phone[:-1])\n                        tones.append(tone)\n                        phones.append(\"er\")\n                        tones.append(\"2\")\n                    else:\n                        phones.append(phone)\n                        tones.append(tone)\n                else:\n                    # initals with 0 tone.\n                    phones.append(full_phone)\n                    tones.append('0')\n        else:\n            for phone in phonemes:\n                # if the merged erhua not in the vocab\n                # assume that the input is ['iaor3'] and 'iaor' not in self.vocab_phones, change ['iaor3'] to ['iao3','er2']\n                if len(phone) >= 3 and phone[:-1] != \"er\" and phone[\n                        -2] == 'r' and phone not in self.vocab_phones and (\n                            phone[:-2] + phone[-1]) in self.vocab_phones:\n                    phones.append((phone[:-2] + phone[-1]))\n                    phones.append(\"er2\")\n                else:\n                    phones.append(phone)\n\n        return phones, tones\n\n    def get_phonemes(self,\n                     sentence: str,\n                     merge_sentences: bool=True,\n                     with_erhua: bool=True,\n                     robot: bool=False,\n                     print_info: bool=False) -> List[List[str]]:\n        \"\"\"\n        Main function to do G2P\n        \"\"\"\n        # TN & Text Segmentation\n        sentences = self.text_normalizer.normalize(sentence)\n        # Prosody & WS & g2p & tone sandhi\n        phonemes = self._g2p(\n            sentences, merge_sentences=merge_sentences, with_erhua=with_erhua)\n\n        # simulate robot pronunciation, change all tones to `1`\n        if robot:\n            new_phonemes = []\n            for sentence in phonemes:\n                new_sentence = []\n                for item in sentence:\n                    # `er` only have tone `2`\n                    if item[-1] in \"12345\" and item != \"er2\":\n                        item = item[:-1] + \"1\"\n                    new_sentence.append(item)\n                new_phonemes.append(new_sentence)\n            phonemes = new_phonemes\n\n        if print_info:\n            print(\"----------------------------\")\n            print(\"text norm results:\")\n            print(sentences)\n            print(\"----------------------------\")\n            print(\"g2p results:\")\n            print(phonemes)\n            print(\"----------------------------\")\n        return phonemes\n\n    def _split_word_to_char(self, words):\n        res = []\n        for x in words:\n            res.append(x)\n        return res\n\n    # if using ssml, have pingyin specified, assign pinyin to words\n    def _g2p_assign(self,\n                    words: List[str],\n                    pinyin_spec: List[str],\n                    merge_sentences: bool=True) -> List[List[str]]:\n        \"\"\"\n        Replace phoneme by SSML\n        \"\"\"\n        phones_list = []\n        initials = []\n        finals = []\n\n        # to character list\n        words = self._split_word_to_char(words[0])\n\n        for pinyin, char in zip(pinyin_spec, words):\n            sub_initials = []\n            sub_finals = []\n            pinyin = pinyin.replace(\"u:\", \"v\")\n\n            #self.pinyin2phone: is a dict with all pinyin mapped with sheng_mu yun_mu\n            if pinyin in self.pinyin2phone:\n                initial_final_list = self.pinyin2phone[pinyin].split(\" \")\n                if len(initial_final_list) == 2:\n                    sub_initials.append(initial_final_list[0])\n                    sub_finals.append(initial_final_list[1])\n                elif len(initial_final_list) == 1:\n                    sub_initials.append('')\n                    sub_finals.append(initial_final_list[1])\n            else:\n                # If it's not pinyin (possibly punctuation) or no conversion is required\n                sub_initials.append(pinyin)\n                sub_finals.append(pinyin)\n\n            initials.append(sub_initials)\n            finals.append(sub_finals)\n\n        initials = sum(initials, [])\n        finals = sum(finals, [])\n\n        phones = []\n        for c, v in zip(initials, finals):\n            # c for consonant, v for vowel\n            # NOTE: post process for pypinyin outputs\n            # we discriminate i, ii and iii\n            if c and c not in self.punc:\n                phones.append(c)\n            # replace punc to `sp`\n            if c and c in self.punc:\n                phones.append('sp')\n            if v and v not in self.punc and v not in self.rhy_phns:\n                phones.append(v)\n        phones_list.append(phones)\n\n        if merge_sentences:\n            merge_list = sum(phones_list, [])\n            # rm the last 'sp' to avoid the noise at the end\n            # cause in the training data, no 'sp' in the end\n            if merge_list[-1] == 'sp':\n                merge_list = merge_list[:-1]\n            phones_list = []\n            phones_list.append(merge_list)\n\n        return phones_list\n\n    def get_phonemes_ssml(self,\n                          ssml_inputs: list,\n                          merge_sentences: bool=True,\n                          with_erhua: bool=True,\n                          robot: bool=False,\n                          print_info: bool=False) -> List[List[str]]:\n        \"\"\"\n         Main function to do G2P with SSML support.\n        \"\"\"\n        all_phonemes = []\n        for word_pinyin_item in ssml_inputs:\n            phonemes = []\n\n            # ['你喜欢', []] -> 你喜欢 []\n            sentence, pinyin_spec = itemgetter(0, 1)(word_pinyin_item)\n\n            # TN & Text Segmentation\n            sentences = self.text_normalizer.normalize(sentence)\n\n            if len(pinyin_spec) == 0:\n                # g2p word w/o specified <say-as>\n                phonemes = self._g2p(\n                    sentences,\n                    merge_sentences=merge_sentences,\n                    with_erhua=with_erhua)\n            else:\n                # word phonemes specified by <say-as>\n                phonemes = self._g2p_assign(\n                    sentences, pinyin_spec, merge_sentences=merge_sentences)\n\n            all_phonemes = all_phonemes + phonemes\n\n        if robot:\n            new_phonemes = []\n            for sentence in all_phonemes:\n                new_sentence = []\n                for item in sentence:\n                    # `er` only have tone `2`\n                    if item[-1] in \"12345\" and item != \"er2\":\n                        item = item[:-1] + \"1\"\n                    new_sentence.append(item)\n                new_phonemes.append(new_sentence)\n            all_phonemes = new_phonemes\n\n        if merge_sentences:\n            all_phonemes = [sum(all_phonemes, [])]\n\n        if print_info:\n            print(\"----------------------------\")\n            print(\"text norm results:\")\n            print(sentences)\n            print(\"----------------------------\")\n            print(\"g2p results:\")\n            print(all_phonemes)\n            print(\"----------------------------\")\n\n        return all_phonemes\n\n    def add_sp_if_no(self, phonemes):\n        \"\"\"\n        Prosody mark #4 added at sentence end.\n        \"\"\"\n        if not phonemes[-1][-1].startswith('sp'):\n            phonemes[-1].append('sp4')\n        return phonemes\n\n    def get_input_ids(self,\n                      sentence: str,\n                      merge_sentences: bool=True,\n                      get_tone_ids: bool=False,\n                      robot: bool=False,\n                      print_info: bool=False,\n                      add_blank: bool=False,\n                      blank_token: str=\"<pad>\",\n                      to_tensor: bool=True) -> Dict[str, List[paddle.Tensor]]:\n\n        phonemes = self.get_phonemes(\n            sentence,\n            merge_sentences=merge_sentences,\n            print_info=print_info,\n            robot=robot)\n\n        # add #4 for sentence end.\n        if self.use_rhy:\n            phonemes = self.add_sp_if_no(phonemes)\n\n        result = {}\n        phones = []\n        tones = []\n        temp_phone_ids = []\n        temp_tone_ids = []\n\n        for part_phonemes in phonemes:\n\n            phones, tones = self._get_phone_tone(\n                part_phonemes, get_tone_ids=get_tone_ids)\n\n            if add_blank:\n                phones = insert_after_character(phones, blank_token)\n\n            if tones:\n                tone_ids = self._t2id(tones)\n                if to_tensor:\n                    tone_ids = paddle.to_tensor(tone_ids)\n                temp_tone_ids.append(tone_ids)\n\n            if phones:\n                phone_ids = self._p2id(phones)\n                # if use paddle.to_tensor() in onnxruntime, the first time will be too low\n                if to_tensor:\n                    phone_ids = paddle.to_tensor(phone_ids)\n                temp_phone_ids.append(phone_ids)\n\n        if temp_tone_ids:\n            result[\"tone_ids\"] = temp_tone_ids\n        if temp_phone_ids:\n            result[\"phone_ids\"] = temp_phone_ids\n\n        return result\n\n    def get_input_ids_ssml(\n            self,\n            sentence: str,\n            merge_sentences: bool=True,\n            get_tone_ids: bool=False,\n            robot: bool=False,\n            print_info: bool=False,\n            add_blank: bool=False,\n            blank_token: str=\"<pad>\",\n            to_tensor: bool=True) -> Dict[str, List[paddle.Tensor]]:\n\n        # split setence by SSML tag.\n        texts = MixTextProcessor.get_pinyin_split(sentence)\n\n        phonemes = self.get_phonemes_ssml(\n            texts,\n            merge_sentences=merge_sentences,\n            print_info=print_info,\n            robot=robot)\n\n        result = {}\n        phones = []\n        tones = []\n        temp_phone_ids = []\n        temp_tone_ids = []\n\n        for part_phonemes in phonemes:\n            phones, tones = self._get_phone_tone(\n                part_phonemes, get_tone_ids=get_tone_ids)\n\n            if add_blank:\n                phones = insert_after_character(phones, blank_token)\n\n            if tones:\n                tone_ids = self._t2id(tones)\n                if to_tensor:\n                    tone_ids = paddle.to_tensor(tone_ids)\n                temp_tone_ids.append(tone_ids)\n\n            if phones:\n                phone_ids = self._p2id(phones)\n                # if use paddle.to_tensor() in onnxruntime, the first time will be too low\n                if to_tensor:\n                    phone_ids = paddle.to_tensor(phone_ids)\n                temp_phone_ids.append(phone_ids)\n\n        if temp_tone_ids:\n            result[\"tone_ids\"] = temp_tone_ids\n        if temp_phone_ids:\n            result[\"phone_ids\"] = temp_phone_ids\n\n        return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/README.md",
    "content": "## Supported NSW (Non-Standard-Word) Normalization\n\n|NSW type|raw|normalized|\n|:--|:-|:-|\n|serial number|电影中梁朝伟扮演的陈永仁的编号27149|电影中梁朝伟扮演的陈永仁的编号二七一四九|\n|cardinal|这块黄金重达324.75克<br>我们班的最高总分为583分|这块黄金重达三百二十四点七五克<br>我们班的最高总分为五百八十三分|\n|numeric range |12\\~23<br>-1.5\\~2|十二到二十三<br>负一点五到二|\n|date|她出生于86年8月18日，她弟弟出生于1995年3月1日|她出生于八六年八月十八日， 她弟弟出生于一九九五年三月一日|\n|time|等会请在12:05请通知我|等会请在十二点零五分请通知我\n|temperature|今天的最低气温达到-10°C|今天的最低气温达到零下十度\n|fraction|现场有7/12的观众投出了赞成票|现场有十二分之七的观众投出了赞成票|\n|percentage|明天有62％的概率降雨|明天有百分之六十二的概率降雨|\n|money|随便来几个价格12块5，34.5元，20.1万|随便来几个价格十二块五，三十四点五元，二十点一万|\n|telephone|这是固话0421-33441122<br>这是手机+86 18544139121|这是固话零四二一三三四四一一二二<br>这是手机八六一八五四四一三九一二一|\n## References\n[Pull requests #658 of DeepSpeech](https://github.com/PaddlePaddle/DeepSpeech/pull/658/files)\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.t2s.frontend.zh_normalization.text_normlization import *\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/char_convert.py",
    "content": "# coding=utf-8\n# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Traditional and simplified Chinese conversion, a simplified character may correspond to multiple traditional characters.\n\"\"\"\nsimplified_charcters = '制咖片型超声盘鉴定仔点他命书歌粉巾字帐恤手指记忆棒形转弯沟光○〇㐄㐅㐆㐌㐖毒㐜㐡㐤㐰㐺㑇㑳㒳㒸㔾㗂㗎㝵㞎㞙㞞以㢲㢴㤅㥁㥯㨗㫺㬎㮎㮚㮸㲋㲱㲾㳮涧㵪㶸㷖㷭㹢㹴犬㺢狓㺵碗㽮㿝䍃䔢䖟䖸䗈䗥䗪䝓射䥯䦉䯝鲃鱼䲔䳗鹅䵹鼄䶑一对应映射丁不识下儿子做二休世丘之貉并中台原则串为甚谓干净了百事无成八变五十些人得道鸡升天代如并来去个国政策劲幽灵在欧洲游荡接样萝卜坑侧化传价元论醇共再准刀两断切分耕耘收获钱货物向看旧就绪险刻千金动劳永逸匙零夜半卡通回复返影踪反常态口咬气句话同吐快吹周味呼诺呜品红锅哄而散起唱和问三知生熟团漆黑火糟堆场空块面塌糊涂尘染壁厢夔已足多情露水大早到晚夫妻当关万莫开失古恨套所料既往孔见提师要家主审寸阴难买斗牛小撮部阵局展身层巴掌帆风顺席地带过年计于春头载四季期被蛇怕井绳度愿式份弹顷深前律径心意念差愁孤行俱全房厅交遮打技长把抓死拿眼泪鼻涕钥锁折段抿拍即合扫排掬挥拨拥上入击洞掷揽改故辙败文值名斑方面旁族日秋餐隔雅里终父旦时晌会霎间晃暴寒曝更月望垠际朝夕本正经利杯羹东西板枝独秀根筋杆进条龙服务概模次函数又性程总付步脚印趋登毛拔呵氧氮碳决雌雄波未平派谎言流清楚白准溜烟潭有获闻是处降琴鹤甲病发可拾沙目然了直以相眨穿睹瞥瞬矢的解石鸟神教秉虔诚秘种窝蜂穷窍笑置笔苟勾销抹杀煞等奖箍节吃箭仇双雕诗筹箩筐系列纸级士官统丝毫挂维网尽线微吭响股脑胎脉承腔臂力致效资源址器举功投般说讲规贸易叶障着慎满皆输号木电池衣倾钟高低视仁觉醒览遗角银币触溃九鼎蔽抄出驷马追重语破贫洗贯走路安蹴至几蹶振跃役胆汗较辈轮辞赞退六连遍递边针血锤音错门思闪真倒项栽雾类保护川先惊乍体哄鳞爪鸣滴泡邻域党专鼓作齐炒丑烯亥克内酯冬加奴卯肝炎基尺梁街裤镐客宠庭巳汝昌烷玲磊糖肇酉醛啷青县韪良香骨鲷丂七集河市弦喜嘴张舌堵区工业姊妹星架构巧彩扭歪拼凑余热曜武州爷浮屠美乡老阶树荤素碎落能魄鳃鳗珠丄丅丆万俟丈尚摸母娘量管群亚虎必我堂令申件装伏位博侠义界表女墟台戏臭皮匠胜诸葛亮赛顶倍催请运算包立叉戟离疫苗土史志演围揭瓦晒夷姑婆帝村宝烂尖杉碱屉桌山岔岛由纪峡坝库镇废从德后拗汤治旬食明昧曹朋友框栏极权幂曲归依猫民氟硼氯磷铁江侗自旅法司洋浦梅园温暖湾焦班幸用田略番叠皇炮捶硝苯酸腺苷棱草镜穗跳远索锦纲聚氰胺联店胚膲爱色堇紫罗兰芝茶饭菱云虫藏藩乱叛苏亲债凳学座恐恋柱测肌腹衩锥系貂企乌跪叩军车农题迭都甘油屯奏键短阿姨陪姐只顾茅庐槽驾魂鲜鹿页其菜单乘任供势午齿汉组织吊调泻唇坡城报坟外夸将尉建筑岸岗公床扬新剑升杭林栗校楼标款汽社浣海商馆剧院钢华港机械广媒环球融第医科证券综财乐育游涨犹岭疏瘾睑确兵领导缴肢膛船艾瑟尔苍蔡虞效衫覆访诉课谕议轨述野钩限敌鞋颌颔颚饶首龈站例修凡划垂届属崽颏厨拜挫摆放旋削棋榻槛礼沉注滑营狱画确仪聘花葬诏员跌辖周达酒锚闸陷陆雨雪飞威丌于丹久乏予理评产亢卑亦乎舞己悲矩圆词害志但住佞佳便俗信票案幅翁倦伦假偏倚斜亏鬼敲停备伤脾胃仅此像俭匮免宜穴焉戴兼容许冻伯仲负彼昼皂轩轾实刊划颠卫战哥比省非好黄饰别拘束掩奶睬选择摇扰烦苦枚写协厌及格受欢迎约只估侵犯割状告或缺抗拒挽撤救药喻磨灭端倪少逆逾越避靠适吉誉吝玉含延咎歹听啻渊善谋均匀堪忍够太惹妙妥妨孕症孝术室完纳推冠积宣疑辩栗碴称屈挠屑干涉衡待很忙恶忿怎么怠急耻恭息悦惑惜惟想愉愧怍慌愤启懂懈怀材才紧招认扣抵拉舍也罢插揣冒搭撞南墙扩核支攻敢雷攀敬里吗需景智暇曾罪遇朽枉止况竞争辱求愈渝溶济左右袒困补爽特寂寞示弱找谢畏强疾徐痛痒冤符眠睦瞅董何厚云措活疲羞者轻玻璃祥兆禁移稂莠稳佛换答简结果盟绝缕途给谈否羁翼耐肖胫毋宁兴舒若菲莱痕迹窠臼虚衰脸兔撒鹰棺范该详讳抬泰让须眉象众赀账费灰赖奇虑训辍辨菽麦辛近送透逞徒速续逮捕遂遑违逊斧钺艰醉锈随观弃显饱脂肪使丏丐帮丒且慢末丕替桃宗王尊凉爵各图屋脊粮署录坛吾禄职胄袭君厦丗北壑桐疹损逢陵鹬丙寅戌氨腈唑纶辰酮脱氢酶醚丞丢现掉纱帽弄扯炮碗丠両丣坐存激肩臻蒂莲悖序驱丨丩丫挺杈髻鬟细介俄伊犁京尼布订普渡央委监察检查剂圈设警队斯督剩震境航舶革防托播促质版蝾螈锋研艺历残消频谱精密制造陲邮候埔坚压坜凹汇执府究邦俘摄寮彬狼岳肺肿庸英讯诊埋粒胞括控码韩暑枪枢砥澳哇牟寿甸钻探篇签缀缝继耳肯照妇埃悬璧轴柜台辣搁浅邪跑纤阮阳私囊魔丮丰姿采丱烧丳丵丶丷丸参寨朗桂瑞砂衷霞貌凤仆舰因嫌宰峰干络牌持旨祭祷簿编罚宾办丼丿乀乂乃乄仰慕盛旷留考验阔乆乇么丑麽乊湖燃乑乒乓乕乖僻忤戾离谬迕乗危肥劫除隙浪婿乙炔肠酰吡咯盐乚乛乜嘢卿玄宫尾狐龟塔嶷兄弟泉章霄钉耙乞扎哀怜恕讨乢乣乤乥乧乨乩童乪乫乭乳晕汁液瑶浆牙癌突窦罩腐胶猪酪蛋糕菌瘤乴乵乶乷乸乹乺乼乾俸冰嘉哕嚎坤妈尸垒旱枯涸俐渴潮涩煸豆燥爹瘦瘪癣瞪袋脆姜贝隆馏乿亀亁叫咕攘扔搞男砸窜蓬麻亃亄亅却亇迟典今临繁累卵奉婚聪躬巨与迁添裂副宿岁怪恶尕仑愣杆硅硫钛铀锰芑杂异钠砷胂磺琥珀舱棍簧胡茬盗浩盆贩郎腿亍洪亐互欠助勉惠操斥诿系户译亓墓碑刑铃卅渠缤纷斗米旗宪钒灯徽瘟祖拳福谷丰脏腑绑肉腌苓蕴桥铺霸颜闹判喷冈底蛙陉矿亖亘亜罕们娜桑那努哈喀弗烈曼松森杜氏杯奥琛敦戊穆圣裔汇薛孙亟亡佚虏羊牢奋释卷卸契媾感额睫缠谊趾塞挤纽阻还配驰庄亨洛祚亪享津沪畿郊慈菴枇杷膏亭阁锃丽亳亶亹诛初责翻疯偶杰丛稠妖拖寰居吸授慧蜗吞壮魅狗矛盾益渣患忧稀描猿梦暂涯畜祸缘沸搜引擎臣横纭谁混援蒸兽狮税剖亻亼亽亡什献刹邡么仂仃仄仆富怨仈仉毕昔晨壳绍仍仏仒仕宦仗欺恃腰叹叹炬梓讫施仙后琼逝仚仝仞仟悔仡佬偿填泊拓扑簇羔购顿钦佩发棻阃驭养亿儆尤借帧赈凌叙帖李柔刚沃眦睚戒讹取飨读仨仫仮著泳卧躺韶夏裁仳仵唯贤凭钓诞仿似宋佛讽伀硕盼鹅伄儅伈伉俪柯始娃迈戈坦堡帕茨萨庙玛莉莎藤霍姆伋伍奢胥廷芳豪伎俩侍汛勒希羲雏伐憩整谟闲闲伕伙伴颐伜伝伢叔恒兹恩翰伱伲侣伶俜悧鼬伸懒缩喇叭伹伺伻伽倻辐伾似佃伫布乔妮墨佉卢佌贷劣廉昂档浓矮伞洼缓耗胸谷迷挡率龋宅沫舍疗佐贰佑占优据铧尝呢须鲁晓佗佘余坪寺瓜铳僧蒙芒陀龛哼呕坊奸孽弊揖祟茧缚誓贼佝偻瞀佟你夺赶佡佢佣佤佧贾佪佫佯佰佱洁绩酿肴佴卷佶佷佸佹佺佻佼佽佾具唤窘坏娱怒慨硬习惯聋膨胀蔓骇贵痹侀侁侂侃侄侅鸿燕侇侈糜靡侉侌妾侏儒仓鼠侐侑侔仑侘侚链侜偎傍钴循柳葫芦附価侮骂蔑侯岩截蚀局贴壶嬛宴捷携桶笺酌俣狭膝狄俅俉俊俏俎俑俓俔谚俚俛黎健呈固墒增守康箱湿祐镖镳杠盒靖膜龄俞豹猎噪孚封札筒托衍鸽剪撰稿炼厂禊练缮葺俯瞰撑冲效俳俴俵俶俷俺备俾伥倂倅储卒惶敷猝逃颉蓄崇隐倌倏忽刺蜡烛噍嚼坍扁抽毙葱楣灌灶粪背薮卖赔闭霉腾倓倔幸倘倜傥倝借箸挹浇阅倡狂倢倣値倥偬倨傲倩匡嗣冲柝珍倬倭寇猩倮倶倷倹勤赞偁偃充伪吏嗓寐惺扮拱芫茜藉虢钞偈伟晶偌宕距析滤殿疼瘫注颇偓偕鸭歇滞偝偟偢忘怡旺偨偩逼偫偭偯偰偱偲侦缉蹄偷减惰漏窥窃偸偺迹傀儡傅傈僳骂篱傎奎琳迪叟芭傒傔傕伧悉荒傜傞傢傣芽逼佣婢傮睨寄檄诵谣颂伛担辜弓惨蒿悼疤傺傻屄臆巢泄箧羡盖轧颓傿㑩僄僇佥僊働僎侨僔僖僚僝伪僣僤侥僦猴偾僩僬僭僮僯僰雇僵殖签静僾僿征陇儁侬儃儇侩朴薄儊儋儌儍傧儓俦侪拟尽儜儞儤儦儩汰哉寡渥裕酷儭儱罐儳儵儹傩俨儽兀臬臲鹫允勋勋宙宵帅憝彝谐嫂阋畅沛溢盈饥赫凶悍狠猛顽愚妣斩秦遣鞭耀敏荣槃泽爆碟磁秃缆辉霁卤朵娄孜烽酱勃汀箕裘钳耶蒙蕾彻兑软遭黜兎児韵媳爸兕觥兖兙兛兜售鍪肚兝兞兟兡兢兣樽殓涅睡禀籍赘泌啡肽奸幕涵涝熵疚眷稃衬讧赴焕椒歼植跏没试误猜栖窗肋袖颊兪卦撇胡岐廓轿疸枫茴珑厕秩募勺吨寓斤历亩迫筷厘最淫螺韬兮宽匪筛襄赢轭复兲诈刃堰戎痞蚁饷它冀铸冂冃円冇冉册嫁厉砺竭醮冏牧冑冓冔冕冖冗冘冞冢窄抑诬冥冫烘菇蛰冷凝坨橇淇淋炭饼砖碛窖醋雕雹霜冱冶炉艳嘲峻滩淡漠煖飕饮冼冽凃凄怆梗凅凇净凊凋敝蒙凔凛遵汞脢凞几凢処凰凯凵凶焰凸折刷纹预丧喽奔巡榜殡芙蓉租笼辑鞘萃凼锯镬刁蛮刂娩崩批拆摊掰蘖骤歧颗秒袂赃勿嘱忌磋琢肤刈羽刎讼戮舂桨艇刓刖霹雳刜创犊刡恙墅帜筵致劫劫刨昏默攸尿欲熏润薰圭删刮痧铲刱刲刳刴刵踏磅戳柏槐绣芹苋猬舟铭鹄鹜劫剁剃辫刭锉履铅克剌姻咽哨廊掠桅沿召瞻翅赵卜渺茫郭剒剔剕沥剚愎毅讷才剜剥啄采剞剟剡剣剤䌽剐肾驶黏剰袍剀紊铲剸剺剽剿劁劂札劈啪柴扳啦刘奭姥夼昫涓熙禅禹锡翔雁鹗刽刿弩柄蜻蛉劒劓劖劘劙澜篑赏矶釜晋甜薪逐劦熔纣虐赤囚劬劭労劵效劻劼劾峭艮勅勇励勍勐腊脖庞漫饲荡粥辄勖勗勘骄馁碌泮雇捐竹骑殊阱绩朴恳谨剿勧勩勯勰劢勋勷劝惩慰诫谏勹芡践阑匁庇拯粟扎袱裹饺匆遽匈匉匊匋匍匐茎匏匕妆痰脓蛹斋苑烤蹈塘羌熊阀螳螂疆碚竿纬荷茵邙魏匚匜匝匟扶稷匣匦拢匸匹耦匽匾匿卂叮疮禧轸堤棚迢钧炼卄卆遐卉瓷盲瓶当胱腱裸卋卌卍卐怯污贱鄙龌龊陋卓溪唐梯渔陈枣泥漳浔涧梨芬谯赡辕迦郑単驴弈洽鳌卛占筮卝卞卟吩啉屎翠厄卣卨卪卬卮榫袄玺绶钮蚤惧殆笃耸卲帘帙绕恤卼卽厂厎厓厔厖厗奚厘厍厜厝谅厕厤厥厪腻孢厮厰厳厣厹厺粕垢芜菁厼厾叁悟茸薯叄吵笄悌哺讥坫垄弧芯杠潜婴刍袁诘贪谍煽馈驳収岳缔灾贿骗叚叡吻拦蘑蜜诀燧玩砚筝椎蔺铜逗骊另觅叨唠谒杵姓喊嚷嚣咚咛塑寻恼憎擦只泣渗蝠叱吒咄咤喝籀黛舵舷叵叶铎懿昭穰苴辽叻叼吁堑嫖赌瞧爬众抒吅吆夥卺橡涤抱纵摩郡唁坠扇篮膀袜颈吋忾谘酬哭妓媛暗表缰迩妃羿絮蕃浑拐葵暮隅吔吖啶嗪戚吜啬噬咽吟哦咏吠吧唧嗒咐吪隽咀征燐苞茹钙哧吮吰吱嘎吲哚吴栋娇窟孟箫忠晗淞阖闾趼宇呐睛嘘拂捧疵熄竽笛糠吼吽呀吕韦蒙呃呆笨呇贡呉罄呋喃呎呏呔呠呡痴呣呤呦呧瑛眩扒晬淑姬瑜璇鹃呪呫哔嚅嗫呬呯呰呱呲咧噌钝呴呶呷呸呺呻哱咻啸噜吁坎坷逻呿咁咂咆哮咇咈咋蟹煦珅蔼咍咑咒诅咔哒嚓咾哝哩喱咗咠咡咢咣咥咦咨嗟询咩咪咫啮啮咭咮咱咲咳呛嗽咴啕咸咹咺呙喉咿婉恸悯赋矜绿茗蓝哂抢瞒哆嗦啰噻啾滨彗哋哌哎唷哟哏哐哞哢哤哪里哫啼喘哰哲萎蚌哳咩哽哿呗唅唆唈唉唎唏哗尧棣殇璜睿肃唔睇唕吣唞唣喳唪唬唰喏唲唳唵嘛唶唸唹唻唼唾唿啁啃鹦鹉啅埠栈榷祺铺鞅飙啊啍啎啐啓啕啖啗啜哑祈啢衔啤啥啫啱啲啵啺饥啽噶昆沁喁喂喆裙喈咙喋喌喎喑喒喓喔粗喙幛庆滋鹊喟喣喤喥喦喧骚喨喩梆吃葡萄喭驼挑吓碰枞瓣纯疱藻趟铬喵営喹喺喼喿嗀嗃嗄嗅嗈嗉嗊嗍嗐嗑嗔诟嗕嗖嗙嗛嗜痂癖嗝嗡嗤嗥嗨唢嗬嗯嗰嗲嗵叽嗷嗹嗾嗿嘀嘁嘂嘅惋嘈峪禾荫啀嘌嘏嘐嘒啯啧嘚唛嘞嘟囔嘣嘥嘦嘧嘬嘭这谑严敞馋松哓嘶嗥呒虾嘹嘻啴嘿噀噂噅噇噉噎噏噔噗噘噙噚咝噞噢噤蝉皿噩噫噭嗳噱哙噳嚏涌洒欲巫霏噷噼嚃嚄嚆抖哜尝嚔苏嚚嚜嚞嚟呖嚬嚭嚮嚯亸喾饬按竣苛嚵嘤啭冁呓膪谦囍囒囓囗囘萧酚飘溅谛囝溯眸纥銮鹘囟殉囡団囤囥囧囨囱囫囵囬囮囯囲図囶囷囸囹圄圉拟囻囿圀圂圃圊粹蠹赦圌垦圏滚鲱凿枘圕圛圜圞坯埂壤骸炕祠窑豚绅魠鲮鳖圧握圩圪垯圬圮圯炸岬幔毯祇窨菩溉圳圴圻圾坂坆沾坋坌舛壈昆垫墩椅坒坓坩埚坭坰坱坳坴坵坻坼杨挣涎帘垃垈垌垍垓垔垕垗垚垛垝垣垞垟垤垧垮垵垺垾垿埀畔埄埆埇埈埌殃隍埏埒埕埗埜垭埤埦埧埭埯埰埲埳埴埵埶绋埸培怖桩础辅埼埽堀诃侄庑堃堄摧磐贞韧砌堈堉垩堋堌堍堎垴堙堞堠礁堧堨舆堭堮蜓摘堲堳堽堿塁塄塈煤茔棵塍垲埘塓绸塕鸦沽虱塙冢塝缪塡坞埙塥塩塬塱场螨塼塽塾塿墀墁墈墉墐夯増毁墝墠墦渍钵墫墬堕墰墺墙橱壅壆壊壌壎壒榨蒜壔壕壖圹垆壜壝垅壡壬壭壱売壴壹壻壸寝壿夂夅夆変夊夌漱邑夓腕泄甥御骼夗夘夙衮瑙妊娠醣枭珊莺鹭戗幻魇夤蹀秘擂鸫姚宛闺屿庾挞拇賛蛤裨菠氅漓捞湄蚊霆鲨箐篆篷荆肆舅荔鲆巷惭骰辟邱镕镰阪漂烩鲵鲽鳄鸨胪鹏妒峨谭枰晏玑癸祝秤竺牡籁恢罡蝼蝎赐绒御梭夬夭砣榆怙枕夶夹馅奄崛葩谲奈贺祀赠奌奂奓奕䜣詝奘奜奠奡奣陶奨奁魁奫奬奰娲孩贬隶酥宄狡猾她姹嫣妁毡荼皋膻蝇嫔妄妍嫉媚娆妗趣妚妞妤碍妬娅妯娌妲妳妵妺姁姅姉姗姒姘姙姜姝姞姣姤姧姫姮娥姱姸姺姽婀娀诱慑胁娉婷娑娓娟娣娭娯娵娶娸娼婊婐婕婞婤婥溪孺婧婪婬婹婺婼婽媁媄媊媕媞媟媠媢媬媮妫媲媵媸媺媻媪眯媿嫄嫈袅嫏嫕妪嫘嫚嫜嫠嫡嫦嫩嫪毐嫫嫬嫰妩嫺娴嫽嫿妫嬃嬅嬉耍婵痴艳嬔嬖嬗嫱袅嫒嬢嬷嬦嬬嬭幼嬲嬴婶嬹嬾嬿孀娘孅娈孏曰癫屏孑孓雀孖斟篓谜摺孛矻鸠崮轲祜鸾孥邈毓棠膑孬孭孰孱孳孵泛罔衔孻孪宀宁冗拙株薇掣抚琪瓿榴谧弥宊濂祁瑕宍宏碁宓邸谳実潢町宥宧宨宬徵崎骏掖阙臊煮禽蚕宸豫寀寁寥寃檐庶寎暄碜寔寖寘寙寛寠苫寤肘洱滥蒗陕核寪弘绰螽宝擅疙瘩晷対檐専尃尅赎绌缭畴衅尌峙醌襟痲碧屁昊槌淘恵瀑牝畑莓缸羚觑蔻脏躁尔尓锐尗尙尜尟尢尥尨尪尬尭尰擒尲尶尴尸尹潽蠖蛾尻扣梢蚴鳍脬蹲屇屌蚵屐屃挪屖屘屙屛屝屡屣峦嶂岩舄屧屦屩屪屃屮戍驻钾崖嵛巅旮旯楂榄榉芋茱萸靛麓屴屹屺屼岀岊岌岍阜岑彭巩岒岝岢岚岣岧岨岫岱岵岷峁峇峋峒峓峞峠嵋峨峰峱岘峹峿崀崁崆祯崋崌崃岖昆崒崔嵬巍萤颢崚崞崟崠峥巆崤崦崧殂岽崱崳崴崶崿嵂嵇嵊泗嵌嵎嵒嵓岁嵙嵞嵡嵩嵫嵯嵴嵼嵾嵝崭崭晴嶋嶌嶒嶓嵚崂嶙嶝嶞峤嶡嶢峄嶨嶭嶮嶰嶲岙嵘巂巃巇巉岿巌巓巘巛滇芎巟巠弋回巣巤炊擘蜥蟒蛊觋巰蜀彦淖杏茂甫楞巻巽帼巿帛斐鲫蕊帑帔帗帚琉汶帟帡帣帨裙帯帰帷帹暆帏幄帮幋幌幏帻幙帮幞幠幡幢幦幨幩幪帱幭幯幰遥蹉跎馀庚鉴幵幷稚邃庀庁広庄庈庉笠庋跋庖牺庠庤庥鲸庬庱庳庴庵馨衢庹庿廃厩廆廋廌廎廏廐廑廒荫廖廛厮搏锣廞弛袤廥廧廨廪廱绵踵髓廸迫瓯邺廻廼廾廿躔弁皱弇弌弍弎弐弑吊诡憾荐弝弢弣弤弨弭弮弰弪霖繇焘斌旭溥骞弶弸弼弾彀彄别累纠强彔彖彘彟彟陌彤贻彧绘虹彪炳雕蔚鸥彰瘅彲彳彴仿彷徉徨彸彽踩敛旆徂徇徊渭畲铉裼従筌徘徙徜徕膳苏萌渐徬徭醺徯徳徴潘徻徼忀瘁胖燎怦悸颤扉犀澎湃砰恍惚绞隘忉惮挨饿忐忑忒忖応忝忞耿忡忪忭忮忱忸怩忻悠懑怏遏怔怗怚怛怞怼黍讶怫怭懦怱怲恍怵惕怸怹恁恂恇恉恌恏恒恓恔恘恚恛恝恞恟恠恣恧眄恪恫恬澹恰恿悀悁悃悄悆悊悐悒晦悚悛悜悝悤您悩悪悮悰悱凄恻德悴怅惘闷悻悾惄愫钟蒐惆惇惌惎惏惓惔惙惛耄惝疟浊恿惦德恽惴蠢惸拈愀愃愆愈愊愍愐愑愒愓愔愕恪氓蠢騃昵惬赧悫愬愮愯恺愼慁恿慅慆慇霭慉慊愠慝慥怄怂慬慱悭慴慵慷戚焚憀灼郁憃惫憋憍眺捏轼愦憔憖憙憧憬憨憪憭怃憯憷憸憹憺懃懅懆邀懊懋怿懔懐懞懠懤懥恹懫懮懰懱毖懵遁梁雍忏懽戁戄戆戉戋戕戛戝戛戠戡戢戣戤戥戦戬戭戯轰戱披菊牖戸戹戺戻卯戽锹扂楔扃扆扈扊杖牵绢铐镯赉扐搂搅烊盹瞌跟趸镲靶鼾払扗玫腮扛扞扠扡扢盔押扤扦扱罾揄绥鞍郤窾扻扼扽抃抆抈抉抌抏瞎抔缳缢擞抜拗択抨摔歉蹿牾抶抻搐泵菸拃拄拊髀抛拌脯拎拏拑擢秧沓曳挛迂拚拝拠拡拫拭拮踢拴拶拷攒拽掇芥橐簪摹疔挈瓢骥捺蹻挌挍挎挐拣挓挖掘浚挙揍聩挲挶挟挿捂捃捄捅捆捉捋胳膊揎捌捍捎躯蛛捗捘捙捜捥捩扪捭据捱捻捼捽掀掂抡臀膘掊掎掏掐笙掔掗掞棉芍掤搪阐掫掮掯揉掱掲掽掾揃揅揆搓揌诨揕揗揘揜揝揞揠揥揩揪揫橥遒麈揰揲揵揶揸背揺搆搉搊搋搌搎搔搕撼橹捣搘搠搡搢搣搤搥搦搧搨搬楦裢讪赸掏搰搲搳搴揾搷搽搾搿摀摁摂摃摎掴摒摓跤摙摛掼摞摠摦喉羯摭摮挚摰摲抠摴抟摷掺摽撂撃撅稻撊撋挦锏泼撕撙撚㧑挢撢掸撦撅撩撬撱朔揿蚍蜉挝捡擀掳闯擉缶觚擐擕擖擗擡擣擤澡腚擧擨擩擫擭摈拧撷擸撸擽擿攃摅撵攉攥攐攓撄搀撺每攩攫辔澄攮攰攲攴轶攷砭讦攽碘敁敃敇敉叙敎筏敔敕敖闰诲敜煌敧敪敳敹敺敻敿斁衽斄牒绉诌斉斎斓鹑谰驳鳢斒筲斛斝斞斠斡斢斨斫斮晾沂潟颖绛邵斲斸釳於琅斾斿旀旗旃旄涡旌旎旐旒旓旖旛旝旟旡旣浴旰獭魃旴时旻旼旽昀昃昄昇昉晰躲澈熹皎皓矾昑昕昜昝昞昡昤晖笋昦昨是昱昳昴昶昺昻晁蹇隧蔬髦晄晅晒晛晜晞晟晡晢晤晥曦晩萘莹顗晿暁暋暌暍暐暔暕煅旸暝暠暡曚暦暨暪朦胧昵暲殄冯暵暸暹暻暾曀晔昙曈曌曏曐暧曘曙曛叠昽曩骆曱甴肱曷牍禺锟曽沧耽朁朅朆杪栓夸竟粘绦朊膺朏朐朓朕朘朙瞄觐溘饔飧朠朢朣栅椆淀虱朩朮朰朱炆璋钰炽鹮朳槿朵朾朿杅杇杌陧欣钊湛漼楷瀍煜玟缨翱肇舜贽适逵杓杕杗杙荀蘅杝杞脩珓筊杰榔狍閦颦缅莞杲杳眇杴杶杸杻杼枋枌枒枓衾葄翘纾逋枙狸桠枟槁枲枳枴枵枷枸橼枹枻柁柂柃柅柈柊柎某柑橘柒柘柙柚柜柞栎柟柢柣柤柩柬柮柰柲橙柶柷柸柺査柿栃栄栒栔栘栝栟柏栩栫栭栱栲栳栴檀栵栻桀骜桁镁桄桉桋桎梏椹葚桓桔桕桜桟桫椤桭杯桯桲桴桷桹湘溟梃梊梍梐潼栀枧梜梠梡梣梧梩梱梲梳梴梵梹棁棃樱棐棑棕榈簑绷蓑枨棘棜棨棩棪棫棬棯棰棱棳棸棹椁棼碗椄苕椈椊椋椌椐椑椓椗検椤椪椰椳椴椵椷椸椽椿楀匾楅篪楋楍楎楗楘楙楛楝楟楠楢楥桢楩楪楫楬楮楯楰梅楸楹楻楽榀榃榊榎槺榕榖榘榛狉莽搒笞榠榡榤榥榦榧杩榭榰榱梿霰榼榾桤槊闩槎槑槔槖様槜槢槥椠槪槭椮槱槲槻槼槾樆樊樏樑樕樗樘樛樟樠樧樨権樲樴樵猢狲桦樻罍樾樿橁橄橆桡笥龠橕橚橛辆椭橤橧竖膈跨橾橿檩檃檇柽檍檎檑檖檗桧槚檠樯檨檫檬梼槟檴檵柠棹櫆櫌栉櫜椟櫡槠栌枥榇栊櫹棂茄櫽欀欂欃欐欑栾欙棂溴欨欬欱欵欶欷歔欸欹欻欼欿歁歃歆艎歈歊莳蝶歓歕歘歙歛歜欤歠蹦诠镶蹒跚升陟歩歮歯歰歳歴璞歺瞑歾殁夭殈殍殑殗殜殙殛殒殢殣殥殪殚僵殰殳荃殷殸殹蛟殻肴谤殴毈毉喂毎毑蕈毗毘毚茛邓毧毬毳毷毹毽毾毵牦氄氆靴氉氊氇氍氐聊氕氖気氘氙氚氛氜氝氡汹焊痉氤氲氥氦铝锌氪烃氩铵痤汪浒漉痘盂碾菖蒲蕹蛭螅氵冰氹氺氽烫氾氿渚汆汊汋汍汎汏汐汔汕褟汙汚汜蓠沼秽蔑汧汨汩汭汲汳汴堤汾沄沅沆瀣沇沈葆浸沦湎溺痼疴沌沍沏沐沔沕沘浜畹砾沚沢沬沭沮沰沱灢沴沷籽沺烹濡洄泂肛泅泆涌肓泐泑泒泓泔泖泙泚泜泝泠漩馍涛粼泞藓鳅泩泫泭泯铢泱泲洇洊泾琵琶荽蓟箔洌洎洏洑潄濯洙洚洟洢洣洧洨洩痢滔洫洮洳洴洵洸洹洺洼洿淌蜚浄浉浙赣渫浠浡浤浥淼瀚浬浭翩萍浯浰蜃淀苔蛞蝓蜇螵蛸煲鲤浃浼浽溦涂涊涐涑涒涔滂莅涘涙涪涫涬涮涴涶涷涿淄淅淆淊凄黯淓淙涟淜淝淟淠淢淤渌淦淩猥藿亵淬淮淯淰淳诣涞纺淸淹炖癯绮渇済渉渋渓渕涣渟渢滓渤澥渧渨渮渰渲渶渼湅湉湋湍湑湓湔黔湜湝浈湟湢湣湩湫湮麟湱湲湴涅満沩溍溎溏溛舐漭溠溤溧驯溮溱溲溳溵溷溻溼溽溾滁滃滉滊荥滏稽滕滘汇滝滫滮羼耷卤滹浐煎漈漊漎绎漕漖漘漙沤漜漪漾漥漦漯漰溆漶漷濞潀颍潎潏潕潗潚潝潞潠潦祉疡潲潵滗潸潺潾涠澁澂澃澉澌澍澐澒澔澙渑澣澦澧澨澫澬浍澰澴澶澼熏郁濆濇濈濉濊貊濔疣濜濠濩觞浚濮盥潍濲泺瀁滢渎渖瀌浏瀒瀔濒泸瀛潇潆瀡潴泷濑瀬弥潋瀳瀵瀹瀺瀼沣滠灉灋灒漓灖灏灞灠滦灥灨滟灪蜴灮烬獴灴灸灺炁炅鱿炗炘炙炤炫疽烙钎炯炰炱炲炴炷毁炻烀烋瘴鲳烓烔焙烜烝烳饪烺焃焄耆焌焐焓焗焜焞焠焢焮焯焱焼煁煃煆煇煊熠煍熬煐炜煕暖熏硷霾煚煝煟煠茕矸煨琐炀萁煳煺煻熀熅熇熉罴荧穹炝熘熛熜稔谙烁熤熨熯熰眶蚂颎熳熸熿燀烨燂燄盏燊燋燏燔隼燖焖燠燡灿燨燮燹燻燽燿爇爊爓爚爝爟爨蟾爯爰为爻丬爿牀牁牂牄牋窗牏牓窗釉牚腩蒡虻牠虽蛎牣牤牮牯牲牳牴牷牸牼绊牿靬犂犄犆犇犉犍犎犒荦犗犛犟犠犨犩犪犮犰狳犴犵犺狁甩狃狆狎狒獾狘狙黠狨狩狫狴狷狺狻豕狈蜘猁猇猈猊猋猓猖獗猗猘狰狞犸猞猟獕猭猱猲猳猷猸猹猺玃獀獃獉獍獏獐獒毙獙獚獜獝獞獠獢獣獧鼇蹊狯猃獬豸狝獯鬻獳犷猕猡玁菟玅玆玈珉糁禛郅玍玎玓瓅玔玕玖玗玘玞玠玡玢玤玥玦珏瑰玭玳瑁玶玷玹玼珂珇珈瑚珌馐馔珔珖珙珛珞珡珣珥珧珩珪佩珶珷珺珽琀琁陨玡琇琖琚琠琤琦琨琫琬琭琮琯琰琱琲琅琴珐珲瑀瑂瑄瑉玮瑑瑔瑗瑢瑭瑱瑲瑳瑽瑾瑿璀璨璁璅璆璈琏璊璐璘璚璝璟璠璡璥瑷璩璪璫璯璲玙璸璺璿瓀璎瓖瓘瓒瓛脐瓞瓠瓤瓧瓩瓮瓰瓱瓴瓸瓻瓼甀甁甃甄甇甋甍甎甏甑甒甓甔瓮甖甗饴蔗甙诧钜粱盎锈团甡褥産甪甬甭甮宁铠甹甽甾甿畀畁畇畈畊畋畎畓畚畛畟鄂畤畦畧荻畯畳畵畷畸畽畾疃叠疋疍疎箪疐疒疕疘疝疢疥疧疳疶疿痁痄痊痌痍痏痐痒痔痗瘢痚痠痡痣痦痩痭痯痱痳痵痻痿瘀痖瘃瘈瘉瘊瘌瘏瘐痪瘕瘖瘙瘚瘛疭瘜瘝瘗瘠瘥瘨瘭瘆瘯瘰疬瘳疠瘵瘸瘺瘘瘼癃痨痫癈癎癐癔癙癜癠疖症癞蟆癪瘿痈発踔绀蔫酵皙砬砒翎翳蔹钨镴皑鹎驹暨粤褶皀皁荚皃镈皈皌皋皒朱皕皖皘皜皝皞皤皦皨皪皫皭糙绽皴皲皻皽盅盋碗盍盚盝踞盦盩秋千盬盭眦睁瞤盯盱眙裰盵盻睐眂眅眈眊県眑眕眚眛眞眢眣眭眳眴眵眹瞓眽郛睃睅睆睊睍睎困睒睖睙睟睠睢睥睪睾睯睽睾眯瞈瞋瞍逛瞏瞕瞖眍䁖瞟瞠瞢瞫瞭瞳瞵瞷瞹瞽阇瞿眬矉矍铄矔矗矙瞩矞矟矠矣矧矬矫矰矱硪碇磙罅舫阡、矼矽礓砃砅砆砉砍砑砕砝砟砠砢砦砧砩砫砮砳艏砵砹砼硇硌硍硎硏硐硒硜硖砗磲茚钡硭硻硾碃碉碏碣碓碔碞碡碪碫碬砀碯碲砜碻礴磈磉磎硙磔磕磖磛磟磠磡磤磥蹭磪磬磴磵磹磻硗礀硚礅礌礐礚礜礞礤礧礮砻礲礵礽礿祂祄祅祆禳祊祍祏祓祔祕祗祘祛祧祫祲祻祼饵脔锢禂禇禋祦禔祎隋禖禘禚禜禝禠祃禢禤禥禨禫祢禴禸秆秈秊闱飒秋秏秕笈蘵赁秠秣秪秫秬秭秷秸稊稌稍稑稗稙稛稞稬秸稲稹稼颡稿穂穄穇穈穉穋稣贮穏穜穟秾穑穣穤穧穨穭穮穵穸窿阒窀窂窅窆窈窕窊窋窌窒窗窔窞窣窬黩蹙窑窳窴窵窭窸窗竁竃竈竑竜并竦竖篦篾笆鲛竾笉笊笎笏笐靥笓笤箓笪笫笭笮笰笱笲笳笵笸笻筀筅筇筈筎筑筘筠筤筥筦笕筒筭箸筰筱筳筴宴筸箂个箊箎箑箒箘箙箛箜篌箝箠箬镞箯箴箾篁筼筜篘篙篚篛篜篝篟篠篡篢篥篧篨篭篰篲筚篴篶篹篼箦簁簃簆簉簋簌簏簜簟簠簥簦簨簬簰簸簻籊藤籒籓籔签籚篯箨籣籥籧笾簖籫籯芾麴籵籸籹籼粁秕粋粑粔粝粛粞粢粧粨粲粳稗粻粽辟粿糅糆糈糌糍糒糔萼糗蛆蹋糢糨糬粽糯糱籴粜糸糺紃蹼鲣霉纡纨绔纫闽襻紑纰纮锭鸢鹞纴紞紟扎紩紬绂绁纻紽紾绐絁絃絅経絍绗絏缡褵絓絖絘絜绚絣螯絪絫聒絰絵绝絺絻絿綀绡綅绠绨绣綌綍綎捆綖綘継続缎绻綦綪线綮綯绾罟蝽綷縩绺绫緁绲緅緆缁绯緌緎総緑绱緖缃缄缂绵缗緤褓缌纂緪緰缑缈缏缇縁縃縄萦缙缒縏缣縕缞縚缜缟缛縠縡縢縦绦縯縰骋缧縳纤缦絷缥縻衙縿繄缫繈繊繋繐缯繖繘繙繠缋繣繨缰缲繸繻缱纁纆纇缬缵纩纑纕缵纙纚纛缾罃罆坛罋罂罎罏罖罘罛罝罠罣罥罦罨罫罭锾罳罶罹罻罽罿羂羃羇芈蕉５１鸵羑羖羌羜羝羢羣羟羧羭羮羰羱羵羶羸藜鲐翀翃翅翊翌翏翕翛翟翡翣翥翦跹翪翫翚翮翯翱翽翾翿板饕鸹锨耋耇耎耏专耒耜耔耞耡耤耨耩耪耧耰鬓耵聍聃聆聎聝聡聦聱聴聂聼阈聿肄肏肐肕腋肙肜肟肧胛肫肬肭肰肴肵肸肼胊胍胏胑胔胗胙胝胠铨胤胦胩胬胭胯胰胲胴胹胻胼胾脇脘脝脞脡脣脤脥脧脰脲脳腆腊腌臜腍腒腓胨腜腠脶腥腧腬腯踝蹬镣腴腶蠕诽膂腽嗉膇膋膔腘膗膙膟黐膣膦膫膰膴膵膷脍臃臄臇臈臌臐臑臓膘臖臙臛臝臞臧蓐诩臽臾臿舀舁鳑鲏舋舎舔舗馆舝舠舡舢舨舭舲舳舴舸舺艁艄艅艉艋艑艕艖艗艘艚艜艟艣舣艨艩舻艬艭荏艴艳艸艹艻艿芃芄芊萰陂藭芏芔芘芚蕙芟芣芤茉芧芨芩芪芮芰鲢芴芷芸荛豢芼芿苄苒苘苙苜蓿苠苡苣荬苤苎苪镑苶苹苺苻苾茀茁范蠡萣茆茇茈茌茍茖茞茠茢茥茦菰茭茯茳藨茷藘茼荁荄荅荇荈菅蜢鸮荍荑荘豆荵荸荠莆莒莔莕莘莙莚莛莜莝莦莨菪莩莪莭莰莿菀菆菉菎菏菐菑菓菔芲菘菝菡菢菣菥蓂菧菫毂蓥菶菷菹醢菺菻菼菾萅萆苌萋萏萐萑萜萩萱萴莴扁萻葇葍葎葑荭葖葙葠葥苇葧葭药葳葴葶葸葹葽蒄蒎莼茏薹莅蒟蒻蒢蒦蒨蒭藁蒯蒱鉾蒴蒹蒺蒽荪蓁蓆蓇蓊蓌蓍蓏蓓蓖蓧蓪蓫荜跣藕苁蓰蓱莼蓷蓺蓼蔀蔂蔃蔆蔇蔉蔊蔋蔌蔎蔕蔘蔙蒌蔟锷蒋雯茑蔯蔳麻蔵蔸蔾荨蒇蕋蕍荞蕐蕑芸莸蕖蕗蕝蕞蕠蕡蒉蕣蕤蕨蕳蓣蕸蕺蕻薀薁薃薅薆荟薉芗薏薐蔷薖薘剃谔钗薜薠薢薤薧薨薫薬薳薶薷薸薽薾薿藄藇藋荩藐藙藚藟藦藳藴苈藷藾蘀蘁蕲苹蘗蘘蘝蘤蘧蘩蘸蘼虀虆虍蟠虒虓虖虡虣虥虩虬虰蛵蛇虷鳟虺虼蚆蚈蚋蚓蚔蚖蚘蚜蚡蚣蚧蚨蚩蚪蚯蚰蜒蚱蚳蚶蚹蚺蚻蚿蛀蛁蛄蛅蝮蛌蛍蛐蟮蛑蛓蛔蛘蛚蛜蛡蛣蜊蛩蛱蜕螫蜅蚬蜈蝣蜋蜍蜎蜑蠊蜛饯蜞蜣蜨蜩蜮蜱蜷蜺蜾蜿蝀蝃蝋蝌蝍蝎蝏蝗蝘蝙蝝鲼蝡蝤蝥猿蝰虻蝲蝴蝻螃蠏蛳螉螋螒螓螗螘螙螚蟥螟螣螥螬螭䗖螾螀蟀蟅蝈蟊蟋蟑蟓蟛蟜蟟蟢虮蟨蟪蟭蛲蟳蛏蟷蟺蟿蠁蠂蠃虿蠋蛴蠓蚝蠗蠙蠚蠛蠜蠧蟏蠩蜂蠮蠰蠲蠵蠸蠼蠽衁衄衄衇衈衉衋衎衒同衖胡衞裳钩衭衲衵衹衺衿袈裟袗袚袟袢袪袮袲袴袷袺袼褙袽裀裉袅裋夹裍裎裒裛裯裱裲裴裾褀褂褉褊裈褎褐褒褓褔褕袆褚褡褢褦褧褪褫袅褯褰褱裆褛褽褾襁褒襆裥襉襋襌襏襚襛襜裣襞襡襢褴襦襫襬襭襮襕襶襼襽襾覂覃覅霸覉覊覌覗觇覚覜觍觎覧覩觊觏覰観觌觔觕觖觜觽觝觡酲觩觫觭觱觳觯觷觼觾觿言赅讣訇訏訑訒诂讬訧訬訳訹证訾詀詅诋毁詈詊讵詑诒诐詗诎察詨诜詶詸詹詻诙诖誂誃诔锄诓誋诳诶悖誙诮诰誧説読誯谇訚谄谆諆諌诤诹诼諕谂谀諝谝諟喧谥諴諵谌谖誊謆謇歌謍謏謑谡谥謡謦謪谪讴謷謼谩哗譅譆譈譊讹譒撰谮鑫譞噪譩谵譬譱譲谴譸譹谫讅讆詟䜩雠讐谗谶讙谠讟谽豁豉豇岂豊豋豌豏豔豞豖豗豜豝豣豦豨豭豱豳豵豶豷豺豻貅貆狸猊貔貘䝙貜貤餍贳餸贶贲赂賏赊赇赒賝赓赕賨赍斗賮賵賸赚赙赜赟贉赆赑贕赝赬赭赱赳迄趁趂趄趐趑趒趔趡趦趫趮趯趱趴趵趷趹趺趿跁跂跅跆踬跄跐跕跖跗跙跛跦跧跩跫跬跮跱跲跴跺跼跽踅踆踈踉踊踒踖踘踜踟躇蹰踠踡踣踤踥踦踧跷踫踮逾踱踊踶踹踺踼踽躞蹁蹂躏蹎蹐蹓蹔跸蹚蹜蹝迹蹠蹡蹢跶蹧蹩蹪蹯鞠蹽躃躄躅踌跻躐踯跞躘躙躗躝躠蹑躜躧躩躭躰躬躶軃軆辊軏轫軘軜軝腭転軥軨軭軱轱辘軷轵轺軽軿輀輂辇辂辁輈挽輗辄辎辋輠輤輬輭輮辏輴輵輶輹輼辗辒轇轏轑轒辚轕轖轗轘轙轝轞轹轳罪辣辞辵辶辺込辿迅迋迍麿迓迣迤逦迥迨迮迸迺迻迿逄逅逌逍逑逓迳逖逡逭逯逴逶逹遄遅侦遘遛遝遢遨遫遯遰遴绕遹遻邂邅邉邋邎邕邗邘邛邠邢邧邨邯郸邰邲邳邴邶邷邽邾邿郃郄郇郈郔郕郗郙郚郜郝郞郏郠郢郪郫郯郰郲郳郴郷郹郾郿鄀鄄郓鄇鄈鄋鄍鄎鄏鄐鄑邹邬鄕郧鄗鄘鄚鄜鄞鄠鄢鄣鄤鄦鄩鄫鄬鄮鄯鄱郐鄷鄹邝鄻鄾鄿酃酅酆酇郦酊酋酎酏酐酣酔酕醄酖酗酞酡酢酤酩酴酹酺醁醅醆醊醍醐醑醓醖醝酝醡醤醨醪醭醯醰酦醲醴醵醸醹醼醽醾釂酾酽釆釈鲈镏阊钆钇钌钯钋鼢鼹钐钏釪釬釭釱钍釸钕钫鈃钭鈆鈇钚鈊鈌钤钣鈒鈤钬钪鈬铌铈钶铛钹铍钸钿鉄鉆铊铇鉌铋鉏铂钷铆钵鉥钲鉨钼钽鉱鉲鉶铰铒鉼铪銍銎铣銕镂铫铦铑铷銤铱铟銧铥铕铯銭銰焊銶锑锉汞鋂锒鋆鋈鋊铤鋍铗鋐鋑鋕鋘鋙锊锓锔锇铓鋭铖锆锂铽鋳鋹鋺鉴镚钎錀锞锖锫锩錍铔锕錔锱铮锛錞锬锜錤錩錬録铼錼锝钔锴鍉镀鍏鍐铡鍚锻锽锸锲锘鍫鍭鍱鍴锶鍹锗针锺锿镅鎉鎋鎌鎍鎏鎒鎓鎗镉鎚鎞镃鎤铩锼鎭鎯镒镍鎴镓鎸鎹镎镟鏊镆镠镝鏖铿锵鏚镗镘镛鏠鏦錾镤鏸镪鏻鏽鏾铙鐄鐇鐏铹镦镡鐗馗镫镢镨鐡锎镄鐩镌鐬鐱镭鐶鐻鐽镱鑀鑅镔鑐鑕鑚鑛鑢鑤镥鑪镧鑯鑱鑴鑵镊镢钃镻闫闬闶闳閒闵閗閟阂関合閤哄阆閲阉閺阎阏阍阌暗闉阕阗闑闒闿闘闚阚闟闠闤闼阞阢阤阨阬阯阹阼阽陁陑陔陛陜陡陥陬骘陴険陼陾阴隃隈隒隗隞隠隣隤隩隮隰颧隳隷隹雂雈雉雊雎雑雒雗雘雚雝雟雩雰雱驿霂霅霈霊沾霒霓霙霝霢霣霤霨霩霪霫霮靁叇叆靑靓靣腼靪靮靰靳靷靸靺靼靿鞀鞃鞄鞍鞗鞙鞚鞝鞞鞡鞣鞨鞫鞬鞮鞶鞹鞾鞑韅鞯驮韍韎韔韖韘韝韫韡韣韭韭韱韹韺頀刮頄顸顼頍颀颃颁頖頞頠頫頬颅頯頲颕頼悴顋顑颙颛颜顕顚顜颟顣颥颞飐飑台飓颸飏飖颽颾颿飀飂飚飌翻飡飣饲飥饨饫飮飧飶餀餂饸饹餇餈饽哺馂餖餗餚馄馃餟餠餤餧餩餪餫糊餮糇餲饧馎糕饩馈馊馌馒饇馑馓膳饎饐饘饟馕馘馥馝馡馣骝骡馵馹駃駄駅駆駉駋驽駓驵駗骀驸駜骂骈駪駬骃駴骎駹駽駾騂騄骓騆騉騋骒骐麟騑騒験騕骛騠騢騣騤騧骧騵驺骟騺蓦骖骠骢驆驈骅驌骁驎骣驒驔驖驙驦驩驫骺鲠骫骭肮骱骴骶骷髅骾髁髂髄髆膀髇髑髌髋髙髝髞髟髡髣髧髪髫髭髯髲髳髹髺髽髾鬁鬃鬅鬈鬋鬎鬏鬐鬑鬒鬖鬗鬘鬙鬠鬣斗鬫鬬阄鬯鬰鬲鬵鬷魆魈魊魋魍魉魑魖鳔魛魟魣魦魨魬鲂魵魸鮀鲅鮆鲧鲇鲍鲋鮓鲒鲕鮟鱇鮠鮦鮨鲔鲑鮶鮸鮿鲧鯄鯆鲩鯈鲻鯕鲭鲞鯙鯠鲲鯥鲰鲶鳀鯸鳊鲗䲠鹣鳇鰋鳄鳆鰕鰛鰜鲥鰤鳏鰦鳎鳐鳁鳓鰶鲦鲡鰼鰽鱀鱄鳙鱆鳕鱎鱐鳝鳝鳜鲟鲎鱠鳣鱨鲚鱮鱲鱵鱻鲅鳦凫鳯鳲鳷鳻鴂鴃鴄鸩鴈鴎鸰鴔鴗鸳鸯鸲鹆鸱鴠鴢鸪鴥鸸鹋鴳鸻鴷鴽鵀鵁鸺鹁鵖鵙鹈鹕鹅鵟鵩鹌鵫鵵鵷鵻鹍鶂鶊鶏鶒鹙鶗鶡鶤鶦鶬鶱鹟鶵鶸鶹鹡鶿鹚鷁鷃鷄鷇䴘䴘鷊鷏鹧鷕鹥鸷鷞鷟鸶鹪鹩鷩鷫鷭鹇鹇鸴鷾䴙鸂鸇䴙鸏鸑鸒鸓鸬鹳鸜鹂鹸咸鹾麀麂麃麄麇麋麌麐麑麒麚麛麝麤麸面麫麮麯麰麺麾黁黈黉黢黒黓黕黙黝黟黥黦黧黮黰黱黪黶黹黻黼黾鼋鼂鼃鼅鼈鼍鼏鼐鼒冬鼖鼙鼚鼛鼡鼩鼱鼪鼫鼯鼷鼽齁齆齇齈齉齌赍齑龀齕齗龅齚龇齞龃龉龆齢出齧齩齮齯齰齱齵齾厐龑龒龚龖龘龝龡龢龤'\n\ntraditional_characters = '制咖片型超聲盤鑒定仔點他命書歌粉巾字帳恤手指記憶棒形轉彎溝光○〇㐄㐅㐆㐌㐖毒㐜㐡㐤㐰㐺㑇㑳㒳㒸㔾㗂㗎㝵㞎㞙㞞㠯㢲㢴㤅㥁㥯㨗㫺㬎㮎㮚㮸㲋㲱㲾㳮㵎㵪㶸㷖㷭㹢㹴犬㺢狓㺵㼝㽮㿝䍃䔢䖟䖸䗈䗥䗪䝓䠶䥯䦉䯝䰾魚䲔䳗䳘䵹鼄䶑一對應映射丁不識下兒子做二休世丘之貉並中台原則串為甚謂乾淨了百事無成八變五十些人得道雞升天代如併來去個國政策勁幽靈在歐洲遊蕩接樣蘿蔔坑側化傳價元論醇共再准刀兩斷切分耕耘收穫錢貨物向看舊就緒險刻千金動勞永逸匙零夜半卡通回復返影蹤反常態口咬氣句話同吐快吹周味呼諾嗚品紅鍋哄而散起唱和問三知生熟團漆黑火糟堆場空塊麵塌糊塗塵染壁廂夔已足多情露水大早到晚夫妻當關萬莫開失古恨套所料既往孔見提師要家主審寸陰難買鬥牛小撮部陣局展身層巴掌帆風順席地帶過年計於春頭載四季期被蛇怕井繩度願式份彈頃深前律徑心意念差愁孤行俱全房廳交遮打技長把抓死拿眼淚鼻涕鑰鎖折段抿拍即合掃排掬揮撥擁上入擊洞擲攬改故轍敗文值名斑方面旁族日秋餐隔雅里終父旦時晌會霎間晃暴寒曝更月望垠際朝夕本正經利杯羹東西板枝獨秀根筋桿進條龍服務概模次函數又性程總付步腳印趨登毛拔呵氧氮碳決雌雄波未平派謊言流清楚白準溜煙潭有獲聞是處降琴鶴甲病發可拾沙目然瞭直以相眨穿睹瞥瞬矢的解石鳥神教秉虔誠秘種窩蜂窮竅笑置筆苟勾銷抹殺煞等獎箍節吃箭仇雙鵰詩籌籮筐系列紙級士官統絲毫掛維網盡線微吭響股腦胎脈承腔臂力致效資源址器舉功投般說講規貿易葉障著慎滿皆輸號木電池衣傾鐘高低視仁覺醒覽遺角銀幣觸潰九鼎蔽抄出駟馬追重語破貧洗貫走路安蹴至幾蹶振躍役膽汗較輩輪辭贊退六連遍遞邊針血錘音錯門思閃真倒項栽霧類保護川先驚乍體鬨鱗爪鳴滴泡鄰域黨專鼓作齊炒丑烯亥克內酯冬加奴卯肝炎基尺梁街褲鎬客寵庭巳汝昌烷玲磊糖肇酉醛啷青縣韙良香骨鯛丂七集河市弦喜嘴張舌堵區工業姊妹星架構巧彩扭歪拼湊餘熱曜武州爺浮屠美鄉老階樹葷素碎落能魄鰓鰻珠丄丅丆万俟丈尚摸母娘量管群亞虎必我堂令申件裝伏位博俠義界表女墟臺戲臭皮匠勝諸葛亮賽頂倍催請運算包立叉戟離疫苗土史志演圍揭瓦曬夷姑婆帝村寶爛尖杉鹼屜桌山岔島由紀峽壩庫鎮廢從德後拗湯治旬食明昧曹朋友框欄極權冪曲歸依貓民氟硼氯磷鐵江侗自旅法司洋浦梅園溫暖灣焦班幸用田略番疊皇炮捶硝苯酸腺苷稜草鏡穗跳遠索錦綱聚氰胺聯店胚膲愛色堇紫羅蘭芝茶飯菱雲蟲藏藩亂叛蘇親債凳學座恐戀柱測肌腹衩錐係貂企烏跪叩軍車農題迭都甘油屯奏鍵短阿姨陪姐隻顧茅廬槽駕魂鮮鹿頁其菜單乘任供勢午齒漢組織吊調瀉唇坡城報墳外夸將尉建築岸崗公床揚新劍昇杭林栗校樓標款汽社浣海商館劇院鋼華港機械廣媒環球融第醫科證券綜財樂育游漲猶嶺疏癮瞼確兵領導繳肢膛船艾瑟爾蒼蔡虞傚衫覆訪訴課諭議軌述野鉤限敵鞋頜頷顎饒首齦站例修凡劃垂屆屬崽頦廚拜挫擺放旋削棋榻檻禮沉注滑營獄畫确儀聘花葬詔員跌轄週達酒錨閘陷陸雨雪飛威丌于丹久乏予理評產亢卑亦乎舞己悲矩圓詞害誌但住佞佳便俗信票案幅翁倦倫假偏倚斜虧鬼敲停備傷脾胃僅此像儉匱免宜穴焉戴兼容許凍伯仲負彼晝皂軒輊實刊划顛衛戰哥比省非好黃飾別拘束掩奶睬選擇搖擾煩苦枚寫協厭及格受歡迎約只估侵犯割狀告或缺抗拒挽撤救藥喻磨滅端倪少逆逾越避靠適吉譽吝玉含延咎歹聽啻淵善謀均勻堪忍夠太惹妙妥妨孕症孝術室完納推冠積宣疑辯慄碴稱屈撓屑干涉衡待很忙惡忿怎麼怠急恥恭息悅惑惜惟想愉愧怍慌憤啟懂懈懷材才緊招認扣抵拉捨也罷插揣冒搭撞南牆擴核支攻敢雷攀敬裡嗎需景智暇曾罪遇朽枉止況競爭辱求癒渝溶濟左右袒困補爽特寂寞示弱找謝畏強疾徐痛癢冤符眠睦瞅董何厚云措活疲羞者輕玻璃祥兆禁移稂莠穩佛換答簡結果盟絕縷途給談否羈翼耐肖脛毋寧興舒若菲萊痕跡窠臼虛衰臉兔撒鷹棺範該詳諱抬泰讓鬚眉象眾貲賬費灰賴奇慮訓輟辨菽麥辛近送透逞徒速續逮捕遂遑違遜斧鉞艱醉鏽隨觀棄顯飽脂肪使丏丐幫丒且慢末丕替桃宗王尊涼爵各圖屋脊糧署錄壇吾祿職胄襲君廈丗北壑桐疹損逢陵鷸丙寅戌氨腈唑綸辰酮脫氫酶醚丞丟現掉紗帽弄扯砲碗丠両丣坐存激肩臻蒂蓮悖序驅丨丩丫挺杈髻鬟細介俄伊犁京尼布訂普渡央委監察檢查劑圈設警隊斯督剩震境航舶革防托播促質版蠑螈鋒研藝歷殘消頻譜精密製造陲郵候埔堅壓壢凹匯執府究邦俘攝寮彬狼嶽肺腫庸英訊診埋粒胞括控碼韓暑槍樞砥澳哇牟壽甸鑽探篇簽綴縫繼耳肯照婦埃懸璧軸櫃檯辣擱淺邪跑纖阮陽私囊魔丮丰姿采丱燒丳丵丶丷丸參寨朗桂瑞砂衷霞貌鳳僕艦因嫌宰峰幹絡牌持旨祭禱簿編罰賓辦丼丿乀乂乃乄仰慕盛曠留考驗闊乆乇么醜麼乊湖燃乑乒乓乕乖僻忤戾离謬迕乗危肥劫除隙浪婿乙炔腸酰吡咯鹽乚乛乜嘢卿玄宮尾狐龜塔嶷兄弟泉章霄釘耙乞扎哀憐恕討乢乣乤乥乧乨乩童乪乫乭乳暈汁液瑤漿牙癌突竇罩腐膠豬酪蛋糕菌瘤乴乵乶乷乸乹乺乼乾俸冰嘉噦嚎坤媽屍壘旱枯涸俐渴潮澀煸豆燥爹瘦癟癬瞪袋脆薑貝隆餾乿亀亁叫咕攘扔搞男砸竄蓬麻亃亄亅卻亇遲典今臨繁累卵奉婚聰躬巨與遷添裂副宿歲怪噁尕崙愣杆硅硫鈦鈾錳芑雜異鈉砷胂磺琥珀艙棍簧胡茬盜浩盆販郎腿亍洪亐互欠助勉惠操斥諉繫戶譯亓墓碑刑鈴卅渠繽紛斗米旗憲釩燈徽瘟祖拳福穀豐臟腑綁肉醃苓蘊橋鋪霸顏鬧判噴岡底蛙陘礦亖亙亜罕們娜桑那努哈喀弗烈曼松森杜氏盃奧琛敦戊穆聖裔彙薛孫亟亡佚虜羊牢奮釋卷卸契媾感額睫纏誼趾塞擠紐阻還配馳莊亨洛祚亪享津滬畿郊慈菴枇杷膏亭閣鋥麗亳亶亹誅初責翻瘋偶傑叢稠妖拖寰居吸授慧蝸吞壯魅狗矛盾益渣患憂稀描猿夢暫涯畜禍緣沸搜引擎臣橫紜誰混援蒸獸獅稅剖亻亼亽亾什獻剎邡麽仂仃仄仆富怨仈仉畢昔晨殼紹仍仏仒仕宦仗欺恃腰嘆歎炬梓訖施仙后瓊逝仚仝仞仟悔仡佬償填泊拓撲簇羔購頓欽佩髮棻閫馭養億儆尤藉幀賑凌敘帖李柔剛沃眥睚戒訛取饗讀仨仫仮著泳臥躺韶夏裁仳仵唯賢憑釣誕仿似宋彿諷伀碩盼鵝伄儅伈伉儷柯始娃邁戈坦堡帕茨薩廟瑪莉莎藤霍姆伋伍奢胥廷芳豪伎倆侍汛勒希羲雛伐憩整謨閑閒伕伙伴頤伜伝伢叔恆茲恩翰伱伲侶伶俜悧鼬伸懶縮喇叭伹伺伻伽倻輻伾佀佃佇佈喬妮墨佉盧佌貸劣廉昂檔濃矮傘窪緩耗胸谷迷擋率齲宅沫舍療佐貳佑佔優據鏵嘗呢須魯曉佗佘余坪寺瓜銃僧蒙芒陀龕哼嘔坊姦孽弊揖祟繭縛誓賊佝僂瞀佟你奪趕佡佢佣佤佧賈佪佫佯佰佱潔績釀餚佴捲佶佷佸佹佺佻佼佽佾具喚窘壞娛怒慨硬習慣聾膨脹蔓駭貴痺侀侁侂侃侄侅鴻燕侇侈糜靡侉侌妾侏儒倉鼠侐侑侔侖侘侚鏈侜偎傍鈷循柳葫蘆附価侮罵蔑侯岩截蝕侷貼壺嬛宴捷攜桶箋酌俁狹膝狄俅俉俊俏俎俑俓俔諺俚俛黎健呈固墒增守康箱濕祐鏢鑣槓盒靖膜齡俞豹獵噪孚封札筒託衍鴿剪撰稿煉廠禊練繕葺俯瞰撐衝俲俳俴俵俶俷俺俻俾倀倂倅儲卒惶敷猝逃頡蓄崇隱倌倏忽刺蠟燭噍嚼坍扁抽斃蔥楣灌灶糞背藪賣賠閉霉騰倓倔倖倘倜儻倝借箸挹澆閱倡狂倢倣値倥傯倨傲倩匡嗣沖柝珍倬倭寇猩倮倶倷倹勤讚偁偃充偽吏嗓寐惺扮拱芫茜藉虢鈔偈偉晶偌宕距析濾殿疼癱註頗偓偕鴨歇滯偝偟偢忘怡旺偨偩偪偫偭偯偰偱偲偵緝蹄偷減惰漏窺竊偸偺迹傀儡傅傈僳傌籬傎奎琳迪叟芭傒傔傕傖悉荒傜傞傢傣芽逼傭婢傮睨寄檄誦謠頌傴擔辜弓慘蒿悼疤傺傻屄臆巢洩篋羨蓋軋頹傿儸僄僇僉僊働僎僑僔僖僚僝僞僣僤僥僦猴僨僩僬僭僮僯僰僱僵殖籤靜僾僿征隴儁儂儃儇儈朴薄儊儋儌儍儐儓儔儕儗儘儜儞儤儦儩汰哉寡渥裕酷儭儱罐儳儵儹儺儼儽兀臬臲鷲允勛勳宙宵帥憝彞諧嫂鬩暢沛溢盈飢赫兇悍狠猛頑愚妣斬秦遣鞭耀敏榮槃澤爆碟磁禿纜輝霽鹵朵婁孜烽醬勃汀箕裘鉗耶懞蕾徹兌軟遭黜兎児韻媳爸兕觥兗兙兛兜售鍪肚兝兞兟兡兢兣樽殮涅睡稟籍贅泌啡肽奸幕涵澇熵疚眷稃襯訌赴煥椒殲植跏沒試誤猜棲窗肋袖頰兪卦撇鬍岐廓轎疸楓茴瓏廁秩募勺噸寓斤曆畝迫筷釐最淫螺韜兮寬匪篩襄贏軛複兲詐刃堰戎痞蟻餉它冀鑄冂冃円冇冉冊嫁厲礪竭醮冏牧冑冓冔冕冖冗冘冞冢窄抑誣冥冫烘菇蟄冷凝坨橇淇淋炭餅磚磧窖醋雕雹霜冱冶爐艷嘲峻灘淡漠煖颼飲冼冽凃凄愴梗凅凇凈凊凋敝濛凔凜遵汞脢凞几凢処凰凱凵凶焰凸摺刷紋預喪嘍奔巡榜殯芙蓉租籠輯鞘萃凼鋸鑊刁蠻刂娩崩批拆攤掰櫱驟歧顆秒袂贓勿囑忌磋琢膚刈羽刎訟戮舂槳艇刓刖霹靂刜創犢刡恙墅幟筵緻刦刧刨昏默攸尿慾薰潤薰圭刪刮痧鏟刱刲刳刴刵踏磅戳柏槐繡芹莧蝟舟銘鵠鶩刼剁剃辮剄剉履鉛剋剌姻咽哨廊掠桅沿召瞻翅趙卜渺茫郭剒剔剕瀝剚愎毅訥纔剜剝啄採剞剟剡剣剤綵剮腎駛黏剰袍剴紊剷剸剺剽剿劁劂劄劈啪柴扳啦劉奭姥夼昫涓熙禪禹錫翔雁鶚劊劌弩柄蜻蛉劒劓劖劘劙瀾簣賞磯釜晉甜薪逐劦熔紂虐赤囚劬劭労劵効劻劼劾峭艮勅勇勵勍勐臘脖龐漫飼盪粥輒勖勗勘驕餒碌泮雇捐竹騎殊阱勣樸懇謹勦勧勩勯勰勱勲勷勸懲慰誡諫勹芡踐闌匁庇拯粟紮袱裹餃匆遽匈匉匊匋匍匐莖匏匕妝痰膿蛹齋苑烤蹈塘羌熊閥螳螂疆碚竿緯荷茵邙魏匚匜匝匟扶稷匣匭攏匸匹耦匽匾匿卂叮瘡禧軫堤棚迢鈞鍊卄卆遐卉瓷盲瓶噹胱腱裸卋卌卍卐怯污賤鄙齷齪陋卓溪唐梯漁陳棗泥漳潯澗梨芬譙贍轅迦鄭単驢弈洽鰲卛占筮卝卞卟吩啉屎翠厄卣卨卪卬卮榫襖璽綬鈕蚤懼殆篤聳卲帘帙繞卹卼卽厂厎厓厔厖厗奚厘厙厜厝諒厠厤厥厪膩孢厮厰厳厴厹厺粕垢蕪菁厼厾叁悟茸薯叄吵笄悌哺譏坫壟弧芯杠潛嬰芻袁詰貪諜煽饋駁収岳締災賄騙叚叡吻攔蘑蜜訣燧玩硯箏椎藺銅逗驪另覓叨嘮謁杵姓喊嚷囂咚嚀塑尋惱憎擦祇泣滲蝠叱吒咄咤喝籀黛舵舷叵叶鐸懿昭穰苴遼叻叼吁塹嫖賭瞧爬衆抒吅吆夥巹橡滌抱縱摩郡唁墜扇籃膀襪頸吋愾諮酬哭妓媛暗錶韁邇妃羿絮蕃渾拐葵暮隅吔吖啶嗪戚吜嗇噬嚥吟哦詠吠吧唧嗒咐吪雋咀徵燐苞茹鈣哧吮吰吱嘎吲哚吳棟嬌窟孟簫忠晗淞闔閭趼宇吶睛噓拂捧疵熄竽笛糠吼吽呀呂韋矇呃呆笨呇貢呉罄呋喃呎呏呔呠呡癡呣呤呦呧瑛眩扒晬淑姬瑜璇鵑呪呫嗶嚅囁呬呯呰呱呲咧噌鈍呴呶呷呸呺呻哱咻嘯嚕籲坎坷邏呿咁咂咆哮咇咈咋蟹煦珅藹咍咑咒詛咔噠嚓咾噥哩喱咗咠咡咢咣咥咦咨嗟詢咩咪咫嚙齧咭咮咱咲咳嗆嗽咴咷咸咹咺咼喉咿婉慟憫賦矜綠茗藍哂搶瞞哆嗦囉噻啾濱彗哋哌哎唷喲哏哐哞哢哤哪裏哫啼喘哰哲萎蚌哳哶哽哿唄唅唆唈唉唎唏嘩堯棣殤璜睿肅唔睇唕唚唞唣喳唪唬唰喏唲唳唵嘛唶唸唹唻唼唾唿啁啃鸚鵡啅埠棧榷祺舖鞅飆啊啍啎啐啓啕啖啗啜啞祈啢啣啤啥啫啱啲啵啺饑啽噶崑沁喁喂喆裙喈嚨喋喌喎喑喒喓喔粗喙幛慶滋鵲喟喣喤喥喦喧騷喨喩梆喫葡萄喭駝挑嚇碰樅瓣純皰藻趟鉻喵営喹喺喼喿嗀嗃嗄嗅嗈嗉嗊嗍嗐嗑嗔詬嗕嗖嗙嗛嗜痂癖嗝嗡嗤嗥嗨嗩嗬嗯嗰嗲嗵嘰嗷嗹嗾嗿嘀嘁嘂嘅惋嘈峪禾蔭嘊嘌嘏嘐嘒嘓嘖嘚嘜嘞嘟囔嘣嘥嘦嘧嘬嘭這謔嚴敞饞鬆嘵嘶嘷嘸蝦嘹嘻嘽嘿噀噂噅噇噉噎噏噔噗噘噙噚噝噞噢噤蟬皿噩噫噭噯噱噲噳嚏涌灑欲巫霏噷噼嚃嚄嚆抖嚌嚐嚔囌嚚嚜嚞嚟嚦嚬嚭嚮嚯嚲嚳飭按竣苛嚵嚶囀囅囈膪謙囍囒囓囗囘蕭酚飄濺諦囝溯眸紇鑾鶻囟殉囡団囤囥囧囨囪囫圇囬囮囯囲図囶囷囸囹圄圉擬囻囿圀圂圃圊粹蠹赦圌墾圏滾鯡鑿枘圕圛圜圞坯埂壤骸炕祠窯豚紳魠鯪鱉圧握圩圪垯圬圮圯炸岬幔毯祇窨菩溉圳圴圻圾坂坆沾坋坌舛壈昆墊墩椅坒坓坩堝坭坰坱坳坴坵坻坼楊掙涎簾垃垈垌垍垓垔垕垗垚垛垝垣垞垟垤垧垮垵垺垾垿埀畔埄埆埇埈埌殃隍埏埒埕埗埜埡埤埦埧埭埯埰埲埳埴埵埶紼埸培怖樁礎輔埼埽堀訶姪廡堃堄摧磐貞韌砌堈堉堊堋堌堍堎堖堙堞堠礁堧堨輿堭堮蜓摘堲堳堽堿塁塄塈煤塋棵塍塏塒塓綢塕鴉沽虱塙塚塝繆塡塢塤塥塩塬塱塲蟎塼塽塾塿墀墁墈墉墐夯増毀墝墠墦漬缽墫墬墮墰墺墻櫥壅壆壊壌壎壒榨蒜壔壕壖壙壚壜壝壠壡壬壭壱売壴壹壻壼寢壿夂夅夆変夊夌漱邑夓腕泄甥禦骼夗夘夙袞瑙妊娠醣梟珊鶯鷺戧幻魘夤蹀祕擂鶇姚宛閨嶼庾撻拇賛蛤裨菠氅漓撈湄蚊霆鯊箐篆篷荊肆舅荔鮃巷慚骰辟邱鎔鐮阪漂燴鯢鰈鱷鴇臚鵬妒峨譚枰晏璣癸祝秤竺牡籟恢罡螻蠍賜絨御梭夬夭砣榆怙枕夶夾餡奄崛葩譎奈賀祀贈奌奐奓奕訢詝奘奜奠奡奣陶奨奩魁奫奬奰媧孩貶隸酥宄狡猾她奼嫣妁氈荼皋膻蠅嬪妄妍嫉媚嬈妗趣妚妞妤礙妬婭妯娌妲妳妵妺姁姅姉姍姒姘姙姜姝姞姣姤姧姫姮娥姱姸姺姽婀娀誘懾脅娉婷娑娓娟娣娭娯娵娶娸娼婊婐婕婞婤婥谿孺婧婪婬婹婺婼婽媁媄媊媕媞媟媠媢媬媮媯媲媵媸媺媻媼眯媿嫄嫈嫋嫏嫕嫗嫘嫚嫜嫠嫡嫦嫩嫪毐嫫嫬嫰嫵嫺嫻嫽嫿嬀嬃嬅嬉耍嬋痴豔嬔嬖嬗嬙嬝嬡嬢嬤嬦嬬嬭幼嬲嬴嬸嬹嬾嬿孀孃孅孌孏曰癲屏孑孓雀孖斟簍謎摺孛矻鳩崮軻祜鸞孥邈毓棠臏孬孭孰孱孳孵泛罔銜孻孿宀宁宂拙株薇掣撫琪瓿榴謐彌宊濂祁瑕宍宏碁宓邸讞実潢町宥宧宨宬徵崎駿掖闕臊煮禽蠶宸豫寀寁寥寃簷庶寎暄磣寔寖寘寙寛寠苫寤肘洱濫蒗陝覈寪弘綽螽寳擅疙瘩晷対檐専尃尅贖絀繚疇釁尌峙醌襟痲碧屁昊槌淘恵瀑牝畑莓缸羚覷蔻髒躁尒尓銳尗尙尜尟尢尥尨尪尬尭尰擒尲尶尷尸尹潽蠖蛾尻釦梢蚴鰭脬蹲屇屌蚵屐屓挪屖屘屙屛屝屢屣巒嶂巖舄屧屨屩屪屭屮戍駐鉀崖嵛巔旮旯楂欖櫸芋茱萸靛麓屴屹屺屼岀岊岌岍阜岑彭鞏岒岝岢嵐岣岧岨岫岱岵岷峁峇峋峒峓峞峠嵋峩峯峱峴峹峿崀崁崆禎崋崌崍嶇崐崒崔嵬巍螢顥崚崞崟崠崢巆崤崦崧殂崬崱崳崴崶崿嵂嵇嵊泗嵌嵎嵒嵓嵗嵙嵞嵡嵩嵫嵯嵴嵼嵾嶁嶃嶄晴嶋嶌嶒嶓嶔嶗嶙嶝嶞嶠嶡嶢嶧嶨嶭嶮嶰嶲嶴嶸巂巃巇巉巋巌巓巘巛滇芎巟巠弋迴巣巤炊擘蜥蟒蠱覡巰蜀彥淖杏茂甫楞巻巽幗巿帛斐鯽蕊帑帔帗帚琉汶帟帡帣帨帬帯帰帷帹暆幃幄幇幋幌幏幘幙幚幞幠幡幢幦幨幩幪幬幭幯幰遙蹉跎餘庚鑑幵幷稚邃庀庁広庄庈庉笠庋跋庖犧庠庤庥鯨庬庱庳庴庵馨衢庹庿廃廄廆廋廌廎廏廐廑廒廕廖廛廝搏鑼廞弛袤廥廧廨廩廱綿踵髓廸廹甌鄴廻廼廾廿躔弁皺弇弌弍弎弐弒弔詭憾薦弝弢弣弤弨弭弮弰弳霖繇燾斌旭溥騫弶弸弼弾彀彄彆纍糾彊彔彖彘彟彠陌彤貽彧繪虹彪炳彫蔚鷗彰癉彲彳彴彷彷徉徨彸彽踩斂旆徂徇徊渭畬鉉裼従筌徘徙徜徠膳甦萌漸徬徭醺徯徳徴潘徻徼忀瘁胖燎怦悸顫扉犀澎湃砰恍惚絞隘忉憚挨餓忐忑忒忖応忝忞耿忡忪忭忮忱忸怩忻悠懣怏遏怔怗怚怛怞懟黍訝怫怭懦怱怲怳怵惕怸怹恁恂恇恉恌恏恒恓恔恘恚恛恝恞恟恠恣恧眄恪恫恬澹恰恿悀悁悃悄悆悊悐悒晦悚悛悜悝悤您悩悪悮悰悱悽惻悳悴悵惘悶悻悾惄愫鍾蒐惆惇惌惎惏惓惔惙惛耄惝瘧濁惥惦惪惲惴惷惸拈愀愃愆愈愊愍愐愑愒愓愔愕愙氓蠢騃昵愜赧愨愬愮愯愷愼慁慂慅慆慇靄慉慊慍慝慥慪慫慬慱慳慴慵慷慼焚憀灼鬱憃憊憋憍眺捏軾憒憔憖憙憧憬憨憪憭憮憯憷憸憹憺懃懅懆邀懊懋懌懍懐懞懠懤懥懨懫懮懰懱毖懵遁樑雍懺懽戁戄戇戉戔戕戛戝戞戠戡戢戣戤戥戦戩戭戯轟戱披菊牖戸戹戺戻戼戽鍬扂楔扃扆扈扊杖牽絹銬鐲賚扐摟攪烊盹瞌跟躉鑔靶鼾払扗玫腮扛扞扠扡扢盔押扤扦扱罾揄綏鞍郤窾扻扼扽抃抆抈抉抌抏瞎抔繯縊擻抜抝択抨摔歉躥牾抶抻搐泵菸拃拄拊髀拋拌脯拎拏拑擢秧沓曳攣迂拚拝拠拡拫拭拮踢拴拶拷攢拽掇芥橐簪摹疔挈瓢驥捺蹻挌挍挎挐揀挓挖掘浚挙揍聵挲挶挾挿捂捃捄捅捆捉捋胳膊揎捌捍捎軀蛛捗捘捙捜捥捩捫捭据捱捻捼捽掀掂掄臀膘掊掎掏掐笙掔掗掞棉芍掤搪闡掫掮掯揉掱掲掽掾揃揅揆搓揌諢揕揗揘揜揝揞揠揥揩揪揫櫫遒麈揰揲揵揶揸揹揺搆搉搊搋搌搎搔搕撼櫓搗搘搠搡搢搣搤搥搦搧搨搬楦褳訕赸搯搰搲搳搴搵搷搽搾搿摀摁摂摃摎摑摒摓跤摙摛摜摞摠摦睺羯摭摮摯摰摲摳摴摶摷摻摽撂撃撅稻撊撋撏鐧潑撕撙撚撝撟撢撣撦撧撩撬撱朔撳蚍蜉撾撿擀擄闖擉缶觚擐擕擖擗擡擣擤澡腚擧擨擩擫擭擯擰擷擸擼擽擿攃攄攆攉攥攐攓攖攙攛每攩攫轡澄攮攰攲攴軼攷砭訐攽碘敁敃敇敉敍敎筏敔敕敖閏誨敜煌敧敪敱敹敺敻敿斁衽斄牒縐謅斉斎斕鶉讕駮鱧斒筲斛斝斞斠斡斢斨斫斮晾沂潟穎絳邵斲斸釳於琅斾斿旀旂旃旄渦旌旎旐旒旓旖旛旝旟旡旣浴旰獺魃旴旹旻旼旽昀昃昄昇昉晰躲澈熹皎皓礬昑昕昜昝昞昡昤暉筍昦昨昰昱昳昴昶昺昻晁蹇隧蔬髦晄晅晒晛晜晞晟晡晢晤晥曦晩萘瑩顗晿暁暋暌暍暐暔暕煅暘暝暠暡曚暦暨暪朦朧暱暲殄馮暵暸暹暻暾曀曄曇曈曌曏曐曖曘曙曛曡曨曩駱曱甴肱曷牘禺錕曽滄耽朁朅朆杪栓誇竟粘絛朊膺朏朐朓朕朘朙瞄覲溘饔飧朠朢朣柵椆澱蝨朩朮朰朱炆璋鈺熾鹮朳槿朶朾朿杅杇杌隉欣釗湛漼楷瀍煜玟纓翱肈舜贄适逵杓杕杗杙荀蘅杝杞脩珓筊杰榔狍閦顰緬莞杲杳眇杴杶杸杻杼枋枌枒枓衾葄翹紓逋枙狸椏枟槁枲枳枴枵枷枸櫞枹枻柁柂柃柅柈柊柎某柑橘柒柘柙柚柜柞櫟柟柢柣柤柩柬柮柰柲橙柶柷柸柺査柿栃栄栒栔栘栝栟栢栩栫栭栱栲栳栴檀栵栻桀驁桁鎂桄桉桋桎梏椹葚桓桔桕桜桟桫欏桭桮桯桲桴桷桹湘溟梃梊梍梐潼梔梘梜梠梡梣梧梩梱梲梳梴梵梹棁棃櫻棐棑棕櫚簑繃蓑棖棘棜棨棩棪棫棬棯棰棱棳棸棹槨棼椀椄苕椈椊椋椌椐椑椓椗検椤椪椰椳椴椵椷椸椽椿楀楄楅篪楋楍楎楗楘楙楛楝楟楠楢楥楨楩楪楫楬楮楯楰楳楸楹楻楽榀榃榊榎槺榕榖榘榛狉莽榜笞榠榡榤榥榦榧榪榭榰榱槤霰榼榾榿槊閂槎槑槔槖様槜槢槥槧槪槭槮槱槲槻槼槾樆樊樏樑樕樗樘樛樟樠樧樨権樲樴樵猢猻樺樻罍樾樿橁橄橆橈笥龠橕橚橛輛橢橤橧豎膈跨橾橿檁檃檇檉檍檎檑檖檗檜檟檠檣檨檫檬檮檳檴檵檸櫂櫆櫌櫛櫜櫝櫡櫧櫨櫪櫬櫳櫹櫺茄櫽欀欂欃欐欑欒欙欞溴欨欬欱欵欶欷歔欸欹欻欼欿歁歃歆艎歈歊蒔蝶歓歕歘歙歛歜歟歠蹦詮鑲蹣跚陞陟歩歮歯歰歳歴璞歺瞑歾歿殀殈殍殑殗殜殙殛殞殢殣殥殪殫殭殰殳荃殷殸殹蛟殻殽謗毆毈毉餵毎毑蕈毗毘毚茛鄧毧毬毳毷毹毽毾毿氂氄氆靴氉氊氌氍氐聊氕氖気氘氙氚氛氜氝氡洶焊痙氤氳氥氦鋁鋅氪烴氬銨痤汪滸漉痘盂碾菖蒲蕹蛭螅氵氷氹氺氽燙氾氿渚汆汊汋汍汎汏汐汔汕褟汙汚汜蘺沼穢衊汧汨汩汭汲汳汴隄汾沄沅沆瀣沇沈葆浸淪湎溺痼痾沌沍沏沐沔沕沘浜畹礫沚沢沬沭沮沰沱灢沴沷籽沺烹濡洄泂肛泅泆湧肓泐泑泒泓泔泖泙泚泜泝泠漩饃濤粼濘蘚鰍泩泫泭泯銖泱泲洇洊涇琵琶荽薊箔洌洎洏洑潄濯洙洚洟洢洣洧洨洩痢滔洫洮洳洴洵洸洹洺洼洿淌蜚浄浉浙贛渫浠浡浤浥淼瀚浬浭翩萍浯浰蜃淀苔蛞蝓蜇螵蛸煲鯉浹浼浽溦涂涊涐涑涒涔滂涖涘涙涪涫涬涮涴涶涷涿淄淅淆淊淒黯淓淙漣淜淝淟淠淢淤淥淦淩猥藿褻淬淮淯淰淳詣淶紡淸淹燉癯綺渇済渉渋渓渕渙渟渢滓渤澥渧渨渮渰渲渶渼湅湉湋湍湑湓湔黔湜湝湞湟湢湣湩湫湮麟湱湲湴湼満溈溍溎溏溛舐漭溠溤溧馴溮溱溲溳溵溷溻溼溽溾滁滃滉滊滎滏稽滕滘滙滝滫滮羼耷滷滹滻煎漈漊漎繹漕漖漘漙漚漜漪漾漥漦漯漰漵漶漷濞潀潁潎潏潕潗潚潝潞潠潦祉瘍潲潵潷潸潺潾潿澁澂澃澉澌澍澐澒澔澙澠澣澦澧澨澫澬澮澰澴澶澼熏郁濆濇濈濉濊貊濔疣濜濠濩觴濬濮盥濰濲濼瀁瀅瀆瀋瀌瀏瀒瀔瀕瀘瀛瀟瀠瀡瀦瀧瀨瀬瀰瀲瀳瀵瀹瀺瀼灃灄灉灋灒灕灖灝灞灠灤灥灨灩灪蜴灮燼獴灴灸灺炁炅魷炗炘炙炤炫疽烙釺炯炰炱炲炴炷燬炻烀烋瘴鯧烓烔焙烜烝烳飪烺焃焄耆焌焐焓焗焜焞焠焢焮焯焱焼煁煃煆煇煊熠煍熬煐煒煕煗燻礆霾煚煝煟煠煢矸煨瑣煬萁煳煺煻熀熅熇熉羆熒穹熗熘熛熜稔諳爍熤熨熯熰眶螞熲熳熸熿燀燁燂燄盞燊燋燏燔隼燖燜燠燡燦燨燮燹燻燽燿爇爊爓爚爝爟爨蟾爯爰爲爻爿爿牀牁牂牄牋牎牏牓牕釉牚腩蒡虻牠雖蠣牣牤牮牯牲牳牴牷牸牼絆牿靬犂犄犆犇犉犍犎犒犖犗犛犟犠犨犩犪犮犰狳犴犵犺狁甩狃狆狎狒獾狘狙黠狨狩狫狴狷狺狻豕狽蜘猁猇猈猊猋猓猖獗猗猘猙獰獁猞猟獕猭猱猲猳猷猸猹猺玃獀獃獉獍獏獐獒獘獙獚獜獝獞獠獢獣獧鼇蹊獪獫獬豸獮獯鬻獳獷獼玀玁菟玅玆玈珉糝禛郅玍玎玓瓅玔玕玖玗玘玞玠玡玢玤玥玦玨瑰玭玳瑁玶玷玹玼珂珇珈瑚珌饈饌珔珖珙珛珞珡珣珥珧珩珪珮珶珷珺珽琀琁隕琊琇琖琚琠琤琦琨琫琬琭琮琯琰琱琲瑯琹琺琿瑀瑂瑄瑉瑋瑑瑔瑗瑢瑭瑱瑲瑳瑽瑾瑿璀璨璁璅璆璈璉璊璐璘璚璝璟璠璡璥璦璩璪璫璯璲璵璸璺璿瓀瓔瓖瓘瓚瓛臍瓞瓠瓤瓧瓩瓮瓰瓱瓴瓸瓻瓼甀甁甃甄甇甋甍甎甏甑甒甓甔甕甖甗飴蔗甙詫鉅粱盎銹糰甡褥産甪甬甭甮甯鎧甹甽甾甿畀畁畇畈畊畋畎畓畚畛畟鄂畤畦畧荻畯畳畵畷畸畽畾疃疉疋疍疎簞疐疒疕疘疝疢疥疧疳疶疿痁痄痊痌痍痏痐痒痔痗瘢痚痠痡痣痦痩痭痯痱痳痵痻痿瘀瘂瘃瘈瘉瘊瘌瘏瘐瘓瘕瘖瘙瘚瘛瘲瘜瘝瘞瘠瘥瘨瘭瘮瘯瘰癧瘳癘瘵瘸瘺瘻瘼癃癆癇癈癎癐癔癙癜癠癤癥癩蟆癪癭癰発踔紺蔫酵皙砬砒翎翳蘞鎢鑞皚鵯駒鱀粵褶皀皁莢皃鎛皈皌皐皒硃皕皖皘皜皝皞皤皦皨皪皫皭糙綻皴皸皻皽盅盋盌盍盚盝踞盦盩鞦韆盬盭眦睜瞤盯盱眙裰盵盻睞眂眅眈眊県眑眕眚眛眞眢眣眭眳眴眵眹瞓眽郛睃睅睆睊睍睎睏睒睖睙睟睠睢睥睪睪睯睽睾瞇瞈瞋瞍逛瞏瞕瞖瞘瞜瞟瞠瞢瞫瞭瞳瞵瞷瞹瞽闍瞿矓矉矍鑠矔矗矙矚矞矟矠矣矧矬矯矰矱硪碇磙罅舫阡、矼矽礓砃砅砆砉砍砑砕砝砟砠砢砦砧砩砫砮砳艏砵砹砼硇硌硍硎硏硐硒硜硤硨磲茚鋇硭硻硾碃碉碏碣碓碔碞碡碪碫碬碭碯碲碸碻礡磈磉磎磑磔磕磖磛磟磠磡磤磥蹭磪磬磴磵磹磻磽礀礄礅礌礐礚礜礞礤礧礮礱礲礵礽礿祂祄祅祆禳祊祍祏祓祔祕祗祘祛祧祫祲祻祼餌臠錮禂禇禋禑禔禕隋禖禘禚禜禝禠禡禢禤禥禨禫禰禴禸稈秈秊闈颯秌秏秕笈蘵賃秠秣秪秫秬秭秷秸稊稌稍稑稗稙稛稞稬稭稲稹稼顙稾穂穄穇穈穉穋穌貯穏穜穟穠穡穣穤穧穨穭穮穵穸窿闃窀窂窅窆窈窕窊窋窌窒窓窔窞窣窬黷蹙窰窳窴窵窶窸窻竁竃竈竑竜竝竦竪篦篾笆鮫竾笉笊笎笏笐靨笓笤籙笪笫笭笮笰笱笲笳笵笸笻筀筅筇筈筎筑筘筠筤筥筦筧筩筭筯筰筱筳筴讌筸箂箇箊箎箑箒箘箙箛箜篌箝箠箬鏃箯箴箾篁篔簹篘篙篚篛篜篝篟篠篡篢篥篧篨篭篰篲篳篴篶篹篼簀簁簃簆簉簋簌簏簜簟簠簥簦簨簬簰簸簻籊籐籒籓籔籖籚籛籜籣籥籧籩籪籫籯芾麴籵籸籹籼粁粃粋粑粔糲粛粞粢粧粨粲粳粺粻粽闢粿糅糆糈糌糍糒糔萼糗蛆蹋糢糨糬糭糯糱糴糶糸糺紃蹼鰹黴紆紈絝紉閩襻紑紕紘錠鳶鷂紝紞紟紥紩紬紱紲紵紽紾紿絁絃絅経絍絎絏縭褵絓絖絘絜絢絣螯絪絫聒絰絵絶絺絻絿綀綃綅綆綈綉綌綍綎綑綖綘継続緞綣綦綪綫綮綯綰罟蝽綷縩綹綾緁緄緅緆緇緋緌緎総緑緔緖緗緘緙緜緡緤緥緦纂緪緰緱緲緶緹縁縃縄縈縉縋縏縑縕縗縚縝縞縟縠縡縢縦縧縯縰騁縲縳縴縵縶縹縻衙縿繄繅繈繊繋繐繒繖繘繙繠繢繣繨繮繰繸繻繾纁纆纇纈纉纊纑纕纘纙纚纛缾罃罆罈罋罌罎罏罖罘罛罝罠罣罥罦罨罫罭鍰罳罶罹罻罽罿羂羃羇羋蕉５１鴕羑羖羗羜羝羢羣羥羧羭羮羰羱羵羶羸藜鮐翀翃翄翊翌翏翕翛翟翡翣翥翦躚翪翫翬翮翯翺翽翾翿闆饕鴰鍁耋耇耎耏耑耒耜耔耞耡耤耨耩耪耬耰鬢耵聹聃聆聎聝聡聦聱聴聶聼閾聿肄肏肐肕腋肙肜肟肧胛肫肬肭肰肴肵肸肼胊胍胏胑胔胗胙胝胠銓胤胦胩胬胭胯胰胲胴胹胻胼胾脇脘脝脞脡脣脤脥脧脰脲脳腆腊腌臢腍腒腓腖腜腠腡腥腧腬腯踝蹬鐐腴腶蠕誹膂膃膆膇膋膔膕膗膙膟黐膣膦膫膰膴膵膷膾臃臄臇臈臌臐臑臓臕臖臙臛臝臞臧蓐詡臽臾臿舀舁鰟鮍舋舎舔舗舘舝舠舡舢舨舭舲舳舴舸舺艁艄艅艉艋艑艕艖艗艘艚艜艟艣艤艨艩艫艬艭荏艴艶艸艹艻艿芃芄芊萰陂藭芏芔芘芚蕙芟芣芤茉芧芨芩芪芮芰鰱芴芷芸蕘豢芼芿苄苒苘苙苜蓿苠苡苣蕒苤苧苪鎊苶苹苺苻苾茀茁范蠡萣茆茇茈茌茍茖茞茠茢茥茦菰茭茯茳藨茷藘茼荁荄荅荇荈菅蜢鴞荍荑荘荳荵荸薺莆莒莔莕莘莙莚莛莜莝莦莨菪莩莪莭莰莿菀菆菉菎菏菐菑菓菔菕菘菝菡菢菣菥蓂菧菫轂鎣菶菷菹醢菺菻菼菾萅萆萇萋萏萐萑萜萩萱萴萵萹萻葇葍葎葑葒葖葙葠葥葦葧葭葯葳葴葶葸葹葽蒄蒎蒓蘢薹蒞蒟蒻蒢蒦蒨蒭藁蒯蒱鉾蒴蒹蒺蒽蓀蓁蓆蓇蓊蓌蓍蓏蓓蓖蓧蓪蓫蓽跣藕蓯蓰蓱蓴蓷蓺蓼蔀蔂蔃蔆蔇蔉蔊蔋蔌蔎蔕蔘蔙蔞蔟鍔蔣雯蔦蔯蔳蔴蔵蔸蔾蕁蕆蕋蕍蕎蕐蕑蕓蕕蕖蕗蕝蕞蕠蕡蕢蕣蕤蕨蕳蕷蕸蕺蕻薀薁薃薅薆薈薉薌薏薐薔薖薘薙諤釵薜薠薢薤薧薨薫薬薳薶薷薸薽薾薿藄藇藋藎藐藙藚藟藦藳藴藶藷藾蘀蘁蘄蘋蘗蘘蘝蘤蘧蘩蘸蘼虀虆虍蟠虒虓虖虡虣虥虩虯虰蛵虵虷鱒虺虼蚆蚈蚋蚓蚔蚖蚘蚜蚡蚣蚧蚨蚩蚪蚯蚰蜒蚱蚳蚶蚹蚺蚻蚿蛀蛁蛄蛅蝮蛌蛍蛐蟮蛑蛓蛔蛘蛚蛜蛡蛣蜊蛩蛺蛻螫蜅蜆蜈蝣蜋蜍蜎蜑蠊蜛餞蜞蜣蜨蜩蜮蜱蜷蜺蜾蜿蝀蝃蝋蝌蝍蝎蝏蝗蝘蝙蝝鱝蝡蝤蝥蝯蝰蝱蝲蝴蝻螃蠏螄螉螋螒螓螗螘螙螚蟥螟螣螥螬螭螮螾螿蟀蟅蟈蟊蟋蟑蟓蟛蟜蟟蟢蟣蟨蟪蟭蟯蟳蟶蟷蟺蟿蠁蠂蠃蠆蠋蠐蠓蠔蠗蠙蠚蠛蠜蠧蠨蠩蠭蠮蠰蠲蠵蠸蠼蠽衁衂衄衇衈衉衋衎衒衕衖衚衞裳鈎衭衲衵衹衺衿袈裟袗袚袟袢袪袮袲袴袷袺袼褙袽裀裉裊裋裌裍裎裒裛裯裱裲裴裾褀褂褉褊褌褎褐褒褓褔褕褘褚褡褢褦褧褪褫褭褯褰褱襠褸褽褾襁襃襆襇襉襋襌襏襚襛襜襝襞襡襢襤襦襫襬襭襮襴襶襼襽襾覂覃覅覇覉覊覌覗覘覚覜覥覦覧覩覬覯覰観覿觔觕觖觜觽觝觡酲觩觫觭觱觳觶觷觼觾觿言賅訃訇訏訑訒詁託訧訬訳訹証訾詀詅詆譭詈詊詎詑詒詖詗詘詧詨詵詶詸詹詻詼詿誂誃誄鋤誆誋誑誒誖誙誚誥誧説読誯誶誾諂諄諆諌諍諏諑諕諗諛諝諞諟諠諡諴諵諶諼謄謆謇謌謍謏謑謖謚謡謦謪謫謳謷謼謾譁譅譆譈譊譌譒譔譖鑫譞譟譩譫譬譱譲譴譸譹譾讅讆讋讌讎讐讒讖讙讜讟谽豁豉豇豈豊豋豌豏豔豞豖豗豜豝豣豦豨豭豱豳豵豶豷豺豻貅貆貍貎貔貘貙貜貤饜貰餸貺賁賂賏賒賕賙賝賡賧賨賫鬭賮賵賸賺賻賾贇贉贐贔贕贗赬赭赱赳迄趁趂趄趐趑趒趔趡趦趫趮趯趲趴趵趷趹趺趿跁跂跅跆躓蹌跐跕跖跗跙跛跦跧跩跫跬跮跱跲跴跺跼跽踅踆踈踉踊踒踖踘踜踟躇躕踠踡踣踤踥踦踧蹺踫踮踰踱踴踶踹踺踼踽躞蹁蹂躪蹎蹐蹓蹔蹕蹚蹜蹝蹟蹠蹡蹢躂蹧蹩蹪蹯鞠蹽躃躄躅躊躋躐躑躒躘躙躛躝躠躡躦躧躩躭躰躳躶軃軆輥軏軔軘軜軝齶転軥軨軭軱軲轆軷軹軺軽軿輀輂輦輅輇輈輓輗輙輜輞輠輤輬輭輮輳輴輵輶輹輼輾轀轇轏轑轒轔轕轖轗轘轙轝轞轢轤辠辢辤辵辶辺込辿迅迋迍麿迓迣迤邐迥迨迮迸迺迻迿逄逅逌逍逑逓逕逖逡逭逯逴逶逹遄遅遉遘遛遝遢遨遫遯遰遴遶遹遻邂邅邉邋邎邕邗邘邛邠邢邧邨邯鄲邰邲邳邴邶邷邽邾邿郃郄郇郈郔郕郗郙郚郜郝郞郟郠郢郪郫郯郰郲郳郴郷郹郾郿鄀鄄鄆鄇鄈鄋鄍鄎鄏鄐鄑鄒鄔鄕鄖鄗鄘鄚鄜鄞鄠鄢鄣鄤鄦鄩鄫鄬鄮鄯鄱鄶鄷鄹鄺鄻鄾鄿酃酅酆酇酈酊酋酎酏酐酣酔酕醄酖酗酞酡酢酤酩酴酹酺醁醅醆醊醍醐醑醓醖醝醞醡醤醨醪醭醯醰醱醲醴醵醸醹醼醽醾釂釃釅釆釈鱸鎦閶釓釔釕鈀釙鼢鼴釤釧釪釬釭釱釷釸釹鈁鈃鈄鈆鈇鈈鈊鈌鈐鈑鈒鈤鈥鈧鈬鈮鈰鈳鐺鈸鈹鈽鈿鉄鉆鉈鉋鉌鉍鉏鉑鉕鉚鉢鉥鉦鉨鉬鉭鉱鉲鉶鉸鉺鉼鉿銍銎銑銕鏤銚銛銠銣銤銥銦銧銩銪銫銭銰銲銶銻銼銾鋂鋃鋆鋈鋊鋌鋍鋏鋐鋑鋕鋘鋙鋝鋟鋦鋨鋩鋭鋮鋯鋰鋱鋳鋹鋺鋻鏰鐱錀錁錆錇錈錍錏錒錔錙錚錛錞錟錡錤錩錬録錸錼鍀鍆鍇鍉鍍鍏鍐鍘鍚鍛鍠鍤鍥鍩鍫鍭鍱鍴鍶鍹鍺鍼鍾鎄鎇鎉鎋鎌鎍鎏鎒鎓鎗鎘鎚鎞鎡鎤鎩鎪鎭鎯鎰鎳鎴鎵鎸鎹鎿鏇鏊鏌鏐鏑鏖鏗鏘鏚鏜鏝鏞鏠鏦鏨鏷鏸鏹鏻鏽鏾鐃鐄鐇鐏鐒鐓鐔鐗馗鐙鐝鐠鐡鐦鐨鐩鐫鐬鐱鐳鐶鐻鐽鐿鑀鑅鑌鑐鑕鑚鑛鑢鑤鑥鑪鑭鑯鑱鑴鑵鑷钁钃镻閆閈閌閎閒閔閗閟閡関閤閤閧閬閲閹閺閻閼閽閿闇闉闋闐闑闒闓闘闚闞闟闠闤闥阞阢阤阨阬阯阹阼阽陁陑陔陛陜陡陥陬騭陴険陼陾隂隃隈隒隗隞隠隣隤隩隮隰顴隳隷隹雂雈雉雊雎雑雒雗雘雚雝雟雩雰雱驛霂霅霈霊霑霒霓霙霝霢霣霤霨霩霪霫霮靁靆靉靑靚靣靦靪靮靰靳靷靸靺靼靿鞀鞃鞄鞌鞗鞙鞚鞝鞞鞡鞣鞨鞫鞬鞮鞶鞹鞾韃韅韉馱韍韎韔韖韘韝韞韡韣韭韮韱韹韺頀颳頄頇頊頍頎頏頒頖頞頠頫頬顱頯頲頴頼顇顋顑顒顓顔顕顚顜顢顣顬顳颭颮颱颶颸颺颻颽颾颿飀飂飈飌飜飡飣飤飥飩飫飮飱飶餀餂餄餎餇餈餑餔餕餖餗餚餛餜餟餠餤餧餩餪餫餬餮餱餲餳餺餻餼餽餿饁饅饇饉饊饍饎饐饘饟饢馘馥馝馡馣騮騾馵馹駃駄駅駆駉駋駑駓駔駗駘駙駜駡駢駪駬駰駴駸駹駽駾騂騄騅騆騉騋騍騏驎騑騒験騕騖騠騢騣騤騧驤騵騶騸騺驀驂驃驄驆驈驊驌驍驎驏驒驔驖驙驦驩驫骺鯁骫骭骯骱骴骶骷髏骾髁髂髄髆髈髐髑髕髖髙髝髞髟髡髣髧髪髫髭髯髲髳髹髺髽髾鬁鬃鬅鬈鬋鬎鬏鬐鬑鬒鬖鬗鬘鬙鬠鬣鬪鬫鬬鬮鬯鬰鬲鬵鬷魆魈魊魋魍魎魑魖鰾魛魟魣魦魨魬魴魵魸鮀鮁鮆鮌鮎鮑鮒鮓鮚鮞鮟鱇鮠鮦鮨鮪鮭鮶鮸鮿鯀鯄鯆鯇鯈鯔鯕鯖鯗鯙鯠鯤鯥鯫鯰鯷鯸鯿鰂鰆鶼鰉鰋鰐鰒鰕鰛鰜鰣鰤鰥鰦鰨鰩鰮鰳鰶鰷鱺鰼鰽鱀鱄鱅鱆鱈鱎鱐鱓鱔鱖鱘鱟鱠鱣鱨鱭鱮鱲鱵鱻鲅鳦鳧鳯鳲鳷鳻鴂鴃鴄鴆鴈鴎鴒鴔鴗鴛鴦鴝鵒鴟鴠鴢鴣鴥鴯鶓鴳鴴鴷鴽鵀鵁鵂鵓鵖鵙鵜鶘鵞鵟鵩鵪鵫鵵鵷鵻鵾鶂鶊鶏鶒鶖鶗鶡鶤鶦鶬鶱鶲鶵鶸鶹鶺鶿鷀鷁鷃鷄鷇鷈鷉鷊鷏鷓鷕鷖鷙鷞鷟鷥鷦鷯鷩鷫鷭鷳鷴鷽鷾鷿鸂鸇鸊鸏鸑鸒鸓鸕鸛鸜鸝鹸鹹鹺麀麂麃麄麇麋麌麐麑麒麚麛麝麤麩麪麫麮麯麰麺麾黁黈黌黢黒黓黕黙黝黟黥黦黧黮黰黱黲黶黹黻黼黽黿鼂鼃鼅鼈鼉鼏鼐鼒鼕鼖鼙鼚鼛鼡鼩鼱鼪鼫鼯鼷鼽齁齆齇齈齉齌齎齏齔齕齗齙齚齜齞齟齬齠齢齣齧齩齮齯齰齱齵齾龎龑龒龔龖龘龝龡龢龤'\n\nassert len(simplified_charcters) == len(simplified_charcters)\n\ns2t_dict = {}\nt2s_dict = {}\nfor i, item in enumerate(simplified_charcters):\n    s2t_dict[item] = traditional_characters[i]\n    t2s_dict[traditional_characters[i]] = item\n\n\ndef tranditional_to_simplified(text: str) -> str:\n    return \"\".join(\n        [t2s_dict[item] if item in t2s_dict else item for item in text])\n\n\ndef simplified_to_traditional(text: str) -> str:\n    return \"\".join(\n        [s2t_dict[item] if item in s2t_dict else item for item in text])\n\n\nif __name__ == \"__main__\":\n    text = \"一般是指存取一個應用程式啟動時始終顯示在網站或網頁瀏覽器中的一個或多個初始網頁等畫面存在的站點\"\n    print(text)\n    text_simple = tranditional_to_simplified(text)\n    print(text_simple)\n    text_traditional = simplified_to_traditional(text_simple)\n    print(text_traditional)\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/chronology.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\n\nfrom .num import DIGITS\nfrom .num import num2str\nfrom .num import verbalize_cardinal\nfrom .num import verbalize_digit\n\n\ndef _time_num2str(num_string: str) -> str:\n    \"\"\"A special case for verbalizing number in time.\"\"\"\n    result = num2str(num_string.lstrip('0'))\n    if num_string.startswith('0'):\n        result = DIGITS['0'] + result\n    return result\n\n\n# 时刻表达式\nRE_TIME = re.compile(r'([0-1]?[0-9]|2[0-3])'\n                     r':([0-5][0-9])'\n                     r'(:([0-5][0-9]))?')\n\n# 时间范围，如8:30-12:30\nRE_TIME_RANGE = re.compile(r'([0-1]?[0-9]|2[0-3])'\n                           r':([0-5][0-9])'\n                           r'(:([0-5][0-9]))?'\n                           r'(~|-)'\n                           r'([0-1]?[0-9]|2[0-3])'\n                           r':([0-5][0-9])'\n                           r'(:([0-5][0-9]))?')\n\n\ndef replace_time(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n\n    is_range = len(match.groups()) > 5\n\n    hour = match.group(1)\n    minute = match.group(2)\n    second = match.group(4)\n\n    if is_range:\n        hour_2 = match.group(6)\n        minute_2 = match.group(7)\n        second_2 = match.group(9)\n\n    result = f\"{num2str(hour)}点\"\n    if minute.lstrip('0'):\n        if int(minute) == 30:\n            result += \"半\"\n        else:\n            result += f\"{_time_num2str(minute)}分\"\n    if second and second.lstrip('0'):\n        result += f\"{_time_num2str(second)}秒\"\n\n    if is_range:\n        result += \"至\"\n        result += f\"{num2str(hour_2)}点\"\n        if minute_2.lstrip('0'):\n            if int(minute) == 30:\n                result += \"半\"\n            else:\n                result += f\"{_time_num2str(minute_2)}分\"\n        if second_2 and second_2.lstrip('0'):\n            result += f\"{_time_num2str(second_2)}秒\"\n\n    return result\n\n\nRE_DATE = re.compile(r'(\\d{4}|\\d{2})年'\n                     r'((0?[1-9]|1[0-2])月)?'\n                     r'(((0?[1-9])|((1|2)[0-9])|30|31)([日号]))?')\n\n\ndef replace_date(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    year = match.group(1)\n    month = match.group(3)\n    day = match.group(5)\n    result = \"\"\n    if year:\n        result += f\"{verbalize_digit(year)}年\"\n    if month:\n        result += f\"{verbalize_cardinal(month)}月\"\n    if day:\n        result += f\"{verbalize_cardinal(day)}{match.group(9)}\"\n    return result\n\n\n# 用 / 或者 - 分隔的 YY/MM/DD 或者 YY-MM-DD 日期\nRE_DATE2 = re.compile(\n    r'(\\d{4})([- /.])(0[1-9]|1[012])\\2(0[1-9]|[12][0-9]|3[01])')\n\n\ndef replace_date2(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    year = match.group(1)\n    month = match.group(3)\n    day = match.group(4)\n    result = \"\"\n    if year:\n        result += f\"{verbalize_digit(year)}年\"\n    if month:\n        result += f\"{verbalize_cardinal(month)}月\"\n    if day:\n        result += f\"{verbalize_cardinal(day)}日\"\n    return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/constants.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nimport string\n\nfrom pypinyin.constants import SUPPORT_UCS4\n\n# 全角半角转换\n# 英文字符全角 -> 半角映射表 (num: 52)\nF2H_ASCII_LETTERS = {\n    ord(char) + 65248: ord(char)\n    for char in string.ascii_letters\n}\n\n# 英文字符半角 -> 全角映射表\nH2F_ASCII_LETTERS = {value: key for key, value in F2H_ASCII_LETTERS.items()}\n\n# 数字字符全角 -> 半角映射表 (num: 10)\nF2H_DIGITS = {ord(char) + 65248: ord(char) for char in string.digits}\n# 数字字符半角 -> 全角映射表\nH2F_DIGITS = {value: key for key, value in F2H_DIGITS.items()}\n\n# 标点符号全角 -> 半角映射表 (num: 32)\nF2H_PUNCTUATIONS = {ord(char) + 65248: ord(char) for char in string.punctuation}\n# 标点符号半角 -> 全角映射表\nH2F_PUNCTUATIONS = {value: key for key, value in F2H_PUNCTUATIONS.items()}\n\n# 空格 (num: 1)\nF2H_SPACE = {'\\u3000': ' '}\nH2F_SPACE = {' ': '\\u3000'}\n\n# 非\"有拼音的汉字\"的字符串，可用于NSW提取\nif SUPPORT_UCS4:\n    RE_NSW = re.compile(r'(?:[^'\n                        r'\\u3007'  # 〇\n                        r'\\u3400-\\u4dbf'  # CJK扩展A:[3400-4DBF]\n                        r'\\u4e00-\\u9fff'  # CJK基本:[4E00-9FFF]\n                        r'\\uf900-\\ufaff'  # CJK兼容:[F900-FAFF]\n                        r'\\U00020000-\\U0002A6DF'  # CJK扩展B:[20000-2A6DF]\n                        r'\\U0002A703-\\U0002B73F'  # CJK扩展C:[2A700-2B73F]\n                        r'\\U0002B740-\\U0002B81D'  # CJK扩展D:[2B740-2B81D]\n                        r'\\U0002F80A-\\U0002FA1F'  # CJK兼容扩展:[2F800-2FA1F]\n                        r'])+')\nelse:\n    RE_NSW = re.compile(  # pragma: no cover\n        r'(?:[^'\n        r'\\u3007'  # 〇\n        r'\\u3400-\\u4dbf'  # CJK扩展A:[3400-4DBF]\n        r'\\u4e00-\\u9fff'  # CJK基本:[4E00-9FFF]\n        r'\\uf900-\\ufaff'  # CJK兼容:[F900-FAFF]\n        r'])+')\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/num.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nRules to verbalize numbers into Chinese characters.\nhttps://zh.wikipedia.org/wiki/中文数字#現代中文\n\"\"\"\nimport re\nfrom collections import OrderedDict\nfrom typing import List\n\nDIGITS = {str(i): tran for i, tran in enumerate('零一二三四五六七八九')}\nUNITS = OrderedDict({\n    1: '十',\n    2: '百',\n    3: '千',\n    4: '万',\n    8: '亿',\n})\n\nCOM_QUANTIFIERS = '(封|艘|把|目|套|段|人|所|朵|匹|张|座|回|场|尾|条|个|首|阙|阵|网|炮|顶|丘|棵|只|支|袭|辆|挑|担|颗|壳|窠|曲|墙|群|腔|砣|座|客|贯|扎|捆|刀|令|打|手|罗|坡|山|岭|江|溪|钟|队|单|双|对|出|口|头|脚|板|跳|枝|件|贴|针|线|管|名|位|身|堂|课|本|页|家|户|层|丝|毫|厘|分|钱|两|斤|担|铢|石|钧|锱|忽|(千|毫|微)克|毫|厘|(公)分|分|寸|尺|丈|里|寻|常|铺|程|(千|分|厘|毫|微)米|米|撮|勺|合|升|斗|石|盘|碗|碟|叠|桶|笼|盆|盒|杯|钟|斛|锅|簋|篮|盘|桶|罐|瓶|壶|卮|盏|箩|箱|煲|啖|袋|钵|年|月|日|季|刻|时|周|天|秒|分|小时|旬|纪|岁|世|更|夜|春|夏|秋|冬|代|伏|辈|丸|泡|粒|颗|幢|堆|条|根|支|道|面|片|张|颗|块|元|(亿|千万|百万|万|千|百)|(亿|千万|百万|万|千|百|美|)元|(亿|千万|百万|万|千|百|十|)吨|(亿|千万|百万|万|千|百|)块|角|毛|分|(公(里|引|丈|尺|寸|分|釐)))'\n\n# 分数表达式\nRE_FRAC = re.compile(r'(-?)(\\d+)/(\\d+)')\n\n\ndef replace_frac(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    sign = match.group(1)\n    nominator = match.group(2)\n    denominator = match.group(3)\n    sign: str = \"负\" if sign else \"\"\n    nominator: str = num2str(nominator)\n    denominator: str = num2str(denominator)\n    result = f\"{sign}{denominator}分之{nominator}\"\n    return result\n\n\n# 百分数表达式\nRE_PERCENTAGE = re.compile(r'(-?)(\\d+(\\.\\d+)?)%')\n\n\ndef replace_percentage(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    sign = match.group(1)\n    percent = match.group(2)\n    sign: str = \"负\" if sign else \"\"\n    percent: str = num2str(percent)\n    result = f\"{sign}百分之{percent}\"\n    return result\n\n\n# 整数表达式\n# 带负号的整数 -10\nRE_INTEGER = re.compile(r'(-)' r'(\\d+)')\n\n\ndef replace_negative_num(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    sign = match.group(1)\n    number = match.group(2)\n    sign: str = \"负\" if sign else \"\"\n    number: str = num2str(number)\n    result = f\"{sign}{number}\"\n    return result\n\n\n# 编号-无符号整形\n# 00078\nRE_DEFAULT_NUM = re.compile(r'\\d{3}\\d*')\n\n\ndef replace_default_num(match):\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    number = match.group(0)\n    return verbalize_digit(number, alt_one=True)\n\n\n# 数字表达式\n# 纯小数\nRE_DECIMAL_NUM = re.compile(r'(-?)((\\d+)(\\.\\d+))' r'|(\\.(\\d+))')\n# 正整数 + 量词\nRE_POSITIVE_QUANTIFIERS = re.compile(r\"(\\d+)([多余几\\+])?\" + COM_QUANTIFIERS)\nRE_NUMBER = re.compile(r'(-?)((\\d+)(\\.\\d+)?)' r'|(\\.(\\d+))')\n\n\ndef replace_positive_quantifier(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    number = match.group(1)\n    match_2 = match.group(2)\n    if match_2 == \"+\":\n        match_2 = \"多\"\n    match_2: str = match_2 if match_2 else \"\"\n    quantifiers: str = match.group(3)\n    number: str = num2str(number)\n    result = f\"{number}{match_2}{quantifiers}\"\n    return result\n\n\ndef replace_number(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    sign = match.group(1)\n    number = match.group(2)\n    pure_decimal = match.group(5)\n    if pure_decimal:\n        result = num2str(pure_decimal)\n    else:\n        sign: str = \"负\" if sign else \"\"\n        number: str = num2str(number)\n        result = f\"{sign}{number}\"\n    return result\n\n\n# 范围表达式\n# match.group(1) and match.group(8) are copy from RE_NUMBER\n\nRE_RANGE = re.compile(\n    r'((-?)((\\d+)(\\.\\d+)?)|(\\.(\\d+)))[-~]((-?)((\\d+)(\\.\\d+)?)|(\\.(\\d+)))')\n\n\ndef replace_range(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    first, second = match.group(1), match.group(8)\n    first = RE_NUMBER.sub(replace_number, first)\n    second = RE_NUMBER.sub(replace_number, second)\n    result = f\"{first}到{second}\"\n    return result\n\n\ndef _get_value(value_string: str, use_zero: bool=True) -> List[str]:\n    stripped = value_string.lstrip('0')\n    if len(stripped) == 0:\n        return []\n    elif len(stripped) == 1:\n        if use_zero and len(stripped) < len(value_string):\n            return [DIGITS['0'], DIGITS[stripped]]\n        else:\n            return [DIGITS[stripped]]\n    else:\n        largest_unit = next(\n            power for power in reversed(UNITS.keys()) if power < len(stripped))\n        first_part = value_string[:-largest_unit]\n        second_part = value_string[-largest_unit:]\n        return _get_value(first_part) + [UNITS[largest_unit]] + _get_value(\n            second_part)\n\n\ndef verbalize_cardinal(value_string: str) -> str:\n    if not value_string:\n        return ''\n\n    # 000 -> '零' , 0 -> '零'\n    value_string = value_string.lstrip('0')\n    if len(value_string) == 0:\n        return DIGITS['0']\n\n    result_symbols = _get_value(value_string)\n    # verbalized number starting with '一十*' is abbreviated as `十*`\n    if len(result_symbols) >= 2 and result_symbols[0] == DIGITS[\n            '1'] and result_symbols[1] == UNITS[1]:\n        result_symbols = result_symbols[1:]\n    return ''.join(result_symbols)\n\n\ndef verbalize_digit(value_string: str, alt_one=False) -> str:\n    result_symbols = [DIGITS[digit] for digit in value_string]\n    result = ''.join(result_symbols)\n    if alt_one:\n        result = result.replace(\"一\", \"幺\")\n    return result\n\n\ndef num2str(value_string: str) -> str:\n    integer_decimal = value_string.split('.')\n    if len(integer_decimal) == 1:\n        integer = integer_decimal[0]\n        decimal = ''\n    elif len(integer_decimal) == 2:\n        integer, decimal = integer_decimal\n    else:\n        raise ValueError(\n            f\"The value string: '${value_string}' has more than one point in it.\"\n        )\n\n    result = verbalize_cardinal(integer)\n\n    decimal = decimal.rstrip('0')\n    if decimal:\n        # '.22' is verbalized as '零点二二'\n        # '3.20' is verbalized as '三点二\n        result = result if result else \"零\"\n        result += '点' + verbalize_digit(decimal)\n    return result\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/phonecode.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\n\nfrom .num import verbalize_digit\n\n# 规范化固话/手机号码\n# 手机\n# http://www.jihaoba.com/news/show/13680\n# 移动：139、138、137、136、135、134、159、158、157、150、151、152、188、187、182、183、184、178、198\n# 联通：130、131、132、156、155、186、185、176\n# 电信：133、153、189、180、181、177\nRE_MOBILE_PHONE = re.compile(\n    r\"(?<!\\d)((\\+?86 ?)?1([38]\\d|5[0-35-9]|7[678]|9[89])\\d{8})(?!\\d)\")\nRE_TELEPHONE = re.compile(\n    r\"(?<!\\d)((0(10|2[1-3]|[3-9]\\d{2})-?)?[1-9]\\d{6,7})(?!\\d)\")\n\n# 全国统一的号码400开头\nRE_NATIONAL_UNIFORM_NUMBER = re.compile(r\"(400)(-)?\\d{3}(-)?\\d{4}\")\n\n\ndef phone2str(phone_string: str, mobile=True) -> str:\n    if mobile:\n        sp_parts = phone_string.strip('+').split()\n        result = '，'.join(\n            [verbalize_digit(part, alt_one=True) for part in sp_parts])\n        return result\n    else:\n        sil_parts = phone_string.split('-')\n        result = '，'.join(\n            [verbalize_digit(part, alt_one=True) for part in sil_parts])\n        return result\n\n\ndef replace_phone(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    return phone2str(match.group(0), mobile=False)\n\n\ndef replace_mobile(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    return phone2str(match.group(0))\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/quantifier.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\n\nfrom .num import num2str\n\n# 温度表达式，温度会影响负号的读法\n# -3°C 零下三度\nRE_TEMPERATURE = re.compile(r'(-?)(\\d+(\\.\\d+)?)(°C|℃|度|摄氏度)')\nmeasure_dict = {\n    \"cm2\": \"平方厘米\",\n    \"cm²\": \"平方厘米\",\n    \"cm3\": \"立方厘米\",\n    \"cm³\": \"立方厘米\",\n    \"cm\": \"厘米\",\n    \"db\": \"分贝\",\n    \"ds\": \"毫秒\",\n    \"kg\": \"千克\",\n    \"km\": \"千米\",\n    \"m2\": \"平方米\",\n    \"m²\": \"平方米\",\n    \"m³\": \"立方米\",\n    \"m3\": \"立方米\",\n    \"ml\": \"毫升\",\n    \"m\": \"米\",\n    \"mm\": \"毫米\",\n    \"s\": \"秒\",\n    \"h\": \"小时\",\n    \"mg\": \"毫克\"\n}\n\n\ndef replace_temperature(match) -> str:\n    \"\"\"\n    Args:\n        match (re.Match)\n    Returns:\n        str\n    \"\"\"\n    sign = match.group(1)\n    temperature = match.group(2)\n    unit = match.group(3)\n    sign: str = \"零下\" if sign else \"\"\n    temperature: str = num2str(temperature)\n    unit: str = \"摄氏度\" if unit == \"摄氏度\" else \"度\"\n    result = f\"{sign}{temperature}{unit}\"\n    return result\n\n\ndef replace_measure(sentence) -> str:\n    for q_notation in measure_dict:\n        if q_notation in sentence:\n            sentence = sentence.replace(q_notation, measure_dict[q_notation])\n    return sentence\n"
  },
  {
    "path": "paddlespeech/t2s/frontend/zh_normalization/text_normlization.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nfrom typing import List\n\nfrom .char_convert import tranditional_to_simplified\nfrom .chronology import RE_DATE\nfrom .chronology import RE_DATE2\nfrom .chronology import RE_TIME\nfrom .chronology import RE_TIME_RANGE\nfrom .chronology import replace_date\nfrom .chronology import replace_date2\nfrom .chronology import replace_time\nfrom .constants import F2H_ASCII_LETTERS\nfrom .constants import F2H_DIGITS\nfrom .constants import F2H_SPACE\nfrom .num import RE_DECIMAL_NUM\nfrom .num import RE_DEFAULT_NUM\nfrom .num import RE_FRAC\nfrom .num import RE_INTEGER\nfrom .num import RE_NUMBER\nfrom .num import RE_PERCENTAGE\nfrom .num import RE_POSITIVE_QUANTIFIERS\nfrom .num import RE_RANGE\nfrom .num import replace_default_num\nfrom .num import replace_frac\nfrom .num import replace_negative_num\nfrom .num import replace_number\nfrom .num import replace_percentage\nfrom .num import replace_positive_quantifier\nfrom .num import replace_range\nfrom .phonecode import RE_MOBILE_PHONE\nfrom .phonecode import RE_NATIONAL_UNIFORM_NUMBER\nfrom .phonecode import RE_TELEPHONE\nfrom .phonecode import replace_mobile\nfrom .phonecode import replace_phone\nfrom .quantifier import RE_TEMPERATURE\nfrom .quantifier import replace_measure\nfrom .quantifier import replace_temperature\n\n\nclass TextNormalizer():\n    def __init__(self):\n        self.SENTENCE_SPLITOR = re.compile(r'([：、，；。？！,;?!][”’]?)')\n\n    def _split(self, text: str, lang=\"zh\") -> List[str]:\n        \"\"\"Split long text into sentences with sentence-splitting punctuations.\n        Args:\n            text (str): The input text.\n        Returns:\n            List[str]: Sentences.\n        \"\"\"\n        # Only for pure Chinese here\n        if lang == \"zh\":\n            text = text.replace(\" \", \"\")\n            # 过滤掉特殊字符\n            text = re.sub(r'[——《》【】<=>{}()（）#&@“”^_|…\\\\]', '', text)\n        text = self.SENTENCE_SPLITOR.sub(r'\\1\\n', text)\n        text = text.strip()\n        sentences = [sentence.strip() for sentence in re.split(r'\\n+', text)]\n        return sentences\n\n    def _post_replace(self, sentence: str) -> str:\n        sentence = sentence.replace('/', '每')\n        sentence = sentence.replace('~', '至')\n        sentence = sentence.replace('～', '至')\n        sentence = sentence.replace('①', '一')\n        sentence = sentence.replace('②', '二')\n        sentence = sentence.replace('③', '三')\n        sentence = sentence.replace('④', '四')\n        sentence = sentence.replace('⑤', '五')\n        sentence = sentence.replace('⑥', '六')\n        sentence = sentence.replace('⑦', '七')\n        sentence = sentence.replace('⑧', '八')\n        sentence = sentence.replace('⑨', '九')\n        sentence = sentence.replace('⑩', '十')\n        sentence = sentence.replace('α', '阿尔法')\n        sentence = sentence.replace('β', '贝塔')\n        sentence = sentence.replace('γ', '伽玛').replace('Γ', '伽玛')\n        sentence = sentence.replace('δ', '德尔塔').replace('Δ', '德尔塔')\n        sentence = sentence.replace('ε', '艾普西龙')\n        sentence = sentence.replace('ζ', '捷塔')\n        sentence = sentence.replace('η', '依塔')\n        sentence = sentence.replace('θ', '西塔').replace('Θ', '西塔')\n        sentence = sentence.replace('ι', '艾欧塔')\n        sentence = sentence.replace('κ', '喀帕')\n        sentence = sentence.replace('λ', '拉姆达').replace('Λ', '拉姆达')\n        sentence = sentence.replace('μ', '缪')\n        sentence = sentence.replace('ν', '拗')\n        sentence = sentence.replace('ξ', '克西').replace('Ξ', '克西')\n        sentence = sentence.replace('ο', '欧米克伦')\n        sentence = sentence.replace('π', '派').replace('Π', '派')\n        sentence = sentence.replace('ρ', '肉')\n        sentence = sentence.replace('ς', '西格玛').replace('Σ', '西格玛').replace(\n            'σ', '西格玛')\n        sentence = sentence.replace('τ', '套')\n        sentence = sentence.replace('υ', '宇普西龙')\n        sentence = sentence.replace('φ', '服艾').replace('Φ', '服艾')\n        sentence = sentence.replace('χ', '器')\n        sentence = sentence.replace('ψ', '普赛').replace('Ψ', '普赛')\n        sentence = sentence.replace('ω', '欧米伽').replace('Ω', '欧米伽')\n        # re filter special characters, have one more character \"-\" than line 68\n        sentence = re.sub(r'[-——《》【】<=>{}()（）#&@“”^_|…\\\\]', '', sentence)\n        return sentence\n\n    def normalize_sentence(self, sentence: str) -> str:\n        # basic character conversions\n        sentence = tranditional_to_simplified(sentence)\n        sentence = sentence.translate(F2H_ASCII_LETTERS).translate(\n            F2H_DIGITS).translate(F2H_SPACE)\n\n        # number related NSW verbalization\n        sentence = RE_DATE.sub(replace_date, sentence)\n        sentence = RE_DATE2.sub(replace_date2, sentence)\n\n        # range first\n        sentence = RE_TIME_RANGE.sub(replace_time, sentence)\n        sentence = RE_TIME.sub(replace_time, sentence)\n\n        sentence = RE_TEMPERATURE.sub(replace_temperature, sentence)\n        sentence = replace_measure(sentence)\n        sentence = RE_FRAC.sub(replace_frac, sentence)\n        sentence = RE_PERCENTAGE.sub(replace_percentage, sentence)\n        sentence = RE_MOBILE_PHONE.sub(replace_mobile, sentence)\n\n        sentence = RE_TELEPHONE.sub(replace_phone, sentence)\n        sentence = RE_NATIONAL_UNIFORM_NUMBER.sub(replace_phone, sentence)\n\n        sentence = RE_RANGE.sub(replace_range, sentence)\n        sentence = RE_INTEGER.sub(replace_negative_num, sentence)\n        sentence = RE_DECIMAL_NUM.sub(replace_number, sentence)\n        sentence = RE_POSITIVE_QUANTIFIERS.sub(replace_positive_quantifier,\n                                               sentence)\n        sentence = RE_DEFAULT_NUM.sub(replace_default_num, sentence)\n        sentence = RE_NUMBER.sub(replace_number, sentence)\n        sentence = self._post_replace(sentence)\n\n        return sentence\n\n    def normalize(self, text: str) -> List[str]:\n        sentences = self._split(text)\n        sentences = [self.normalize_sentence(sent) for sent in sentences]\n        return sentences\n"
  },
  {
    "path": "paddlespeech/t2s/models/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .ernie_sat import *\nfrom .fastspeech2 import *\nfrom .hifigan import *\nfrom .melgan import *\nfrom .parallel_wavegan import *\nfrom .speedyspeech import *\nfrom .tacotron2 import *\nfrom .transformer_tts import *\nfrom .vits import *\nfrom .waveflow import *\nfrom .wavernn import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/diffsinger/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .diffsinger import *\nfrom .diffsinger_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/diffsinger/diffsinger.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"DiffSinger related modules for paddle\"\"\"\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.models.diffsinger.fastspeech2midi import FastSpeech2MIDI\nfrom paddlespeech.t2s.modules.diffnet import DiffNet\nfrom paddlespeech.t2s.modules.diffusion import GaussianDiffusion\n\n\nclass DiffSinger(nn.Layer):\n    \"\"\"DiffSinger module.\n\n    This is a module of DiffSinger described in `DiffSinger: Singing Voice Synthesis via Shallow Diffusion Mechanism`._\n    .. _`DiffSinger: Singing Voice Synthesis via Shallow Diffusion Mechanism`:\n        https://arxiv.org/pdf/2105.02446.pdf\n\n    Args:\n\n    Returns:\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # min and max spec for stretching before diffusion\n            spec_min: paddle.Tensor,\n            spec_max: paddle.Tensor,\n            # fastspeech2midi config\n            idim: int,\n            odim: int,\n            use_energy_pred: bool=False,\n            use_postnet: bool=False,\n            # music score related \n            note_num: int=300,\n            is_slur_num: int=2,\n            fastspeech2_params: Dict[str, Any]={\n                \"adim\": 256,\n                \"aheads\": 2,\n                \"elayers\": 4,\n                \"eunits\": 1024,\n                \"dlayers\": 4,\n                \"dunits\": 1024,\n                \"positionwise_layer_type\": \"conv1d\",\n                \"positionwise_conv_kernel_size\": 1,\n                \"use_scaled_pos_enc\": True,\n                \"use_batch_norm\": True,\n                \"encoder_normalize_before\": True,\n                \"decoder_normalize_before\": True,\n                \"encoder_concat_after\": False,\n                \"decoder_concat_after\": False,\n                \"reduction_factor\": 1,\n                # for transformer\n                \"transformer_enc_dropout_rate\": 0.1,\n                \"transformer_enc_positional_dropout_rate\": 0.1,\n                \"transformer_enc_attn_dropout_rate\": 0.1,\n                \"transformer_dec_dropout_rate\": 0.1,\n                \"transformer_dec_positional_dropout_rate\": 0.1,\n                \"transformer_dec_attn_dropout_rate\": 0.1,\n                \"transformer_activation_type\": \"gelu\",\n                # duration predictor\n                \"duration_predictor_layers\": 2,\n                \"duration_predictor_chans\": 384,\n                \"duration_predictor_kernel_size\": 3,\n                \"duration_predictor_dropout_rate\": 0.1,\n                # pitch predictor\n                \"use_pitch_embed\": True,\n                \"pitch_predictor_layers\": 2,\n                \"pitch_predictor_chans\": 384,\n                \"pitch_predictor_kernel_size\": 3,\n                \"pitch_predictor_dropout\": 0.5,\n                \"pitch_embed_kernel_size\": 9,\n                \"pitch_embed_dropout\": 0.5,\n                \"stop_gradient_from_pitch_predictor\": False,\n                # energy predictor\n                \"use_energy_embed\": False,\n                \"energy_predictor_layers\": 2,\n                \"energy_predictor_chans\": 384,\n                \"energy_predictor_kernel_size\": 3,\n                \"energy_predictor_dropout\": 0.5,\n                \"energy_embed_kernel_size\": 9,\n                \"energy_embed_dropout\": 0.5,\n                \"stop_gradient_from_energy_predictor\": False,\n                # postnet\n                \"postnet_layers\": 5,\n                \"postnet_chans\": 512,\n                \"postnet_filts\": 5,\n                \"postnet_dropout_rate\": 0.5,\n                # spk emb\n                \"spk_num\": None,\n                \"spk_embed_dim\": None,\n                \"spk_embed_integration_type\": \"add\",\n                # training related\n                \"init_type\": \"xavier_uniform\",\n                \"init_enc_alpha\": 1.0,\n                \"init_dec_alpha\": 1.0,\n                # speaker classifier\n                \"enable_speaker_classifier\": False,\n                \"hidden_sc_dim\": 256,\n            },\n            # denoiser config\n            denoiser_params: Dict[str, Any]={\n                \"in_channels\": 80,\n                \"out_channels\": 80,\n                \"kernel_size\": 3,\n                \"layers\": 20,\n                \"stacks\": 5,\n                \"residual_channels\": 256,\n                \"gate_channels\": 512,\n                \"skip_channels\": 256,\n                \"aux_channels\": 256,\n                \"dropout\": 0.,\n                \"bias\": True,\n                \"use_weight_norm\": False,\n                \"init_type\": \"kaiming_normal\",\n            },\n            # diffusion config\n            diffusion_params: Dict[str, Any]={\n                \"num_train_timesteps\": 100,\n                \"beta_start\": 0.0001,\n                \"beta_end\": 0.06,\n                \"beta_schedule\": \"squaredcos_cap_v2\",\n                \"num_max_timesteps\": 60,\n                \"stretch\": True,\n            }, ):\n        \"\"\"Initialize DiffSinger module.\n\n        Args:\n            spec_min (paddle.Tensor): The minimum value of the feature(mel) to stretch before diffusion.\n            spec_max (paddle.Tensor): The maximum value of the feature(mel) to stretch before diffusion.\n            idim (int): Dimension of the inputs (Input vocabrary size.).\n            odim (int): Dimension of the outputs (Acoustic feature dimension.).\n            use_energy_pred (bool, optional): whether use energy predictor. Defaults False.\n            use_postnet (bool, optional): whether use postnet. Defaults False.\n            note_num (int, optional): The number of note. Defaults to 300.\n            is_slur_num (int, optional): The number of slur. Defaults to 2.\n            fastspeech2_params (Dict[str, Any]): Parameter dict for fastspeech2 module.\n            denoiser_params (Dict[str, Any]): Parameter dict for dinoiser module.\n            diffusion_params (Dict[str, Any]): Parameter dict for diffusion module.\n        \"\"\"\n        super().__init__()\n        self.fs2 = FastSpeech2MIDI(\n            idim=idim,\n            odim=odim,\n            fastspeech2_params=fastspeech2_params,\n            note_num=note_num,\n            is_slur_num=is_slur_num,\n            use_energy_pred=use_energy_pred,\n            use_postnet=use_postnet, )\n        denoiser = DiffNet(**denoiser_params)\n        self.diffusion = GaussianDiffusion(\n            denoiser,\n            **diffusion_params,\n            min_values=spec_min,\n            max_values=spec_max, )\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            spk_emb: paddle.Tensor=None,\n            spk_id: paddle.Tensor=None,\n            only_train_fs2: bool=True,\n    ) -> Tuple[paddle.Tensor, Dict[str, paddle.Tensor], paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token (phone) ids (B, Tmax).\n            note(Tensor(int64)): \n                Batch of padded note (element in music score) ids (B, Tmax).\n            note_dur(Tensor(float32)): \n                Batch of padded note durations in seconds (element in music score) (B, Tmax).\n            is_slur(Tensor(int64)): \n                Batch of padded slur (element in music score) ids (B, Tmax).\n            text_lengths(Tensor(int64)): \n                Batch of phone lengths of each input (B,).\n            speech(Tensor[float32]): \n                Batch of padded target features (e.g. mel) (B, Lmax, odim).\n            speech_lengths(Tensor(int64)): \n                Batch of the lengths of each target features (B,).\n            durations(Tensor(int64)): \n                Batch of padded token durations in frame (B, Tmax).\n            pitch(Tensor[float32]): \n                Batch of padded frame-averaged pitch (B, Lmax, 1).\n            energy(Tensor[float32]): \n                Batch of padded frame-averaged energy (B, Lmax, 1).\n            spk_emb(Tensor[float32], optional): \n                Batch of speaker embeddings (B, spk_embed_dim).\n            spk_id(Tnesor[int64], optional(int64)): \n                Batch of speaker ids (B,)\n            only_train_fs2(bool):\n                Whether to train only the fastspeech2 module\n\n        Returns:\n\n        \"\"\"\n        # only train fastspeech2 module firstly\n        before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.fs2(\n            text=text,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            text_lengths=text_lengths,\n            speech=speech,\n            speech_lengths=speech_lengths,\n            durations=durations,\n            pitch=pitch,\n            energy=energy,\n            spk_id=spk_id,\n            spk_emb=spk_emb)\n        if only_train_fs2:\n            return before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits\n\n        # get the encoder output from fastspeech2 as the condition of denoiser module\n        cond_fs2, mel_masks = self.fs2.encoder_infer_batch(\n            text=text,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            text_lengths=text_lengths,\n            speech_lengths=speech_lengths,\n            ds=durations,\n            ps=pitch,\n            es=energy)\n        cond_fs2 = cond_fs2.transpose((0, 2, 1))\n\n        # get the output(final mel) from diffusion module\n        noise_pred, noise_target = self.diffusion(\n            speech.transpose((0, 2, 1)), cond_fs2)\n        return noise_pred, noise_target, mel_masks\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            get_mel_fs2: bool=False, ):\n        \"\"\"Run inference\n\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token (phone) ids (B, Tmax).\n            note(Tensor(int64)): \n                Batch of padded note (element in music score) ids (B, Tmax).\n            note_dur(Tensor(float32)): \n                Batch of padded note durations in seconds (element in music score) (B, Tmax).\n            is_slur(Tensor(int64)): \n                Batch of padded slur (element in music score) ids (B, Tmax).\n            get_mel_fs2 (bool, optional): . Defaults to False.\n                Whether to get mel from fastspeech2 module.\n\n        Returns:\n            \n        \"\"\"\n        mel_fs2, _, _, _ = self.fs2.inference(text, note, note_dur, is_slur)\n        if get_mel_fs2:\n            return mel_fs2\n        mel_fs2 = mel_fs2.unsqueeze(0).transpose((0, 2, 1))\n        cond_fs2 = self.fs2.encoder_infer(text, note, note_dur, is_slur)\n        cond_fs2 = cond_fs2.transpose((0, 2, 1))\n        noise = paddle.randn(mel_fs2.shape)\n        mel = self.diffusion.inference(\n            noise=noise,\n            cond=cond_fs2,\n            ref_x=mel_fs2,\n            scheduler_type=\"ddpm\",\n            num_inference_steps=60)\n        mel = mel.transpose((0, 2, 1))\n        return mel[0]\n\n\nclass DiffSingerInference(nn.Layer):\n    def __init__(self, normalizer, model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = model\n\n    def forward(self, text, note, note_dur, is_slur, get_mel_fs2: bool=False):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token (phone) ids (B, Tmax).\n            note(Tensor(int64)): \n                Batch of padded note (element in music score) ids (B, Tmax).\n            note_dur(Tensor(float32)): \n                Batch of padded note durations in seconds (element in music score) (B, Tmax).\n            is_slur(Tensor(int64)): \n                Batch of padded slur (element in music score) ids (B, Tmax).\n            get_mel_fs2 (bool, optional): . Defaults to False.\n                Whether to get mel from fastspeech2 module.\n\n        Returns:\n            logmel(Tensor(float32)): denorm logmel, [T, mel_bin]\n        \"\"\"\n        normalized_mel = self.acoustic_model.inference(\n            text=text,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            get_mel_fs2=get_mel_fs2)\n        logmel = normalized_mel\n        return logmel\n\n\nclass DiffusionLoss(nn.Layer):\n    \"\"\"Loss function module for Diffusion module on DiffSinger.\"\"\"\n\n    @typechecked\n    def __init__(self, use_masking: bool=True,\n                 use_weighted_masking: bool=False):\n        \"\"\"Initialize feed-forward Transformer loss module.\n        Args:\n            use_masking (bool): \n                Whether to apply masking for padded part in loss calculation.\n            use_weighted_masking (bool): \n                Whether to weighted masking in loss calculation.\n        \"\"\"\n        super().__init__()\n\n        assert (use_masking != use_weighted_masking) or not use_masking\n        self.use_masking = use_masking\n        self.use_weighted_masking = use_weighted_masking\n\n        # define criterions\n        reduction = \"none\" if self.use_weighted_masking else \"mean\"\n        self.l1_criterion = nn.L1Loss(reduction=reduction)\n\n    def forward(\n            self,\n            noise_pred: paddle.Tensor,\n            noise_target: paddle.Tensor,\n            mel_masks: paddle.Tensor, ) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            noise_pred(Tensor): \n                Batch of outputs predict noise (B, Lmax, odim).\n            noise_target(Tensor):  \n                Batch of target noise (B, Lmax, odim).\n            mel_masks(Tensor): \n                Batch of mask of real mel (B, Lmax, 1).\n        Returns:\n        \n        \"\"\"\n        # apply mask to remove padded part\n        if self.use_masking:\n            noise_pred = noise_pred.masked_select(\n                mel_masks.broadcast_to(noise_pred.shape))\n            noise_target = noise_target.masked_select(\n                mel_masks.broadcast_to(noise_target.shape))\n\n        # calculate loss\n        l1_loss = self.l1_criterion(noise_pred, noise_target)\n\n        # make weighted mask and apply it\n        if self.use_weighted_masking:\n            mel_masks = mel_masks.unsqueeze(-1)\n            out_weights = mel_masks.cast(dtype=paddle.float32) / mel_masks.cast(\n                dtype=paddle.float32).sum(\n                    axis=1, keepdim=True)\n            out_weights /= noise_target.shape[0] * noise_target.shape[2]\n\n            # apply weight\n            l1_loss = l1_loss.multiply(out_weights)\n            l1_loss = l1_loss.masked_select(\n                mel_masks.broadcast_to(l1_loss.shape)).sum()\n\n        return l1_loss\n"
  },
  {
    "path": "paddlespeech/t2s/models/diffsinger/diffsinger_updater.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass DiffSingerUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 ds_train_start_steps: int=160000,\n                 output_dir: Path=None,\n                 only_train_diffusion: bool=True):\n        super().__init__(model, optimizers, dataloader, init_state=None)\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n        self.only_train_diffusion = only_train_diffusion\n\n        self.optimizers = optimizers\n        self.optimizer_fs2: Optimizer = optimizers['fs2']\n        self.optimizer_ds: Optimizer = optimizers['ds']\n\n        self.criterions = criterions\n        self.criterion_fs2 = criterions['fs2']\n        self.criterion_ds = criterions['ds']\n\n        self.dataloader = dataloader\n\n        self.ds_train_start_steps = ds_train_start_steps\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # spk_id!=None in multiple spk diffsinger \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        # No explicit speaker identifier labels are used during voice cloning training.\n        if spk_emb is not None:\n            spk_id = None\n\n        # only train fastspeech2 module firstly\n        if self.state.iteration < self.ds_train_start_steps:\n            before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n                text=batch[\"text\"],\n                note=batch[\"note\"],\n                note_dur=batch[\"note_dur\"],\n                is_slur=batch[\"is_slur\"],\n                text_lengths=batch[\"text_lengths\"],\n                speech=batch[\"speech\"],\n                speech_lengths=batch[\"speech_lengths\"],\n                durations=batch[\"durations\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                spk_id=spk_id,\n                spk_emb=spk_emb,\n                only_train_fs2=True, )\n\n            l1_loss_fs2, ssim_loss_fs2, duration_loss, pitch_loss, energy_loss, speaker_loss = self.criterion_fs2(\n                after_outs=after_outs,\n                before_outs=before_outs,\n                d_outs=d_outs,\n                p_outs=p_outs,\n                e_outs=e_outs,\n                ys=ys,\n                ds=batch[\"durations\"],\n                ps=batch[\"pitch\"],\n                es=batch[\"energy\"],\n                ilens=batch[\"text_lengths\"],\n                olens=olens,\n                spk_logits=spk_logits,\n                spk_ids=spk_id, )\n\n            loss_fs2 = l1_loss_fs2 + ssim_loss_fs2 + duration_loss + pitch_loss + energy_loss + speaker_loss\n\n            self.optimizer_fs2.clear_grad()\n            loss_fs2.backward()\n            self.optimizer_fs2.step()\n\n            report(\"train/loss_fs2\", float(loss_fs2))\n            report(\"train/l1_loss_fs2\", float(l1_loss_fs2))\n            report(\"train/ssim_loss_fs2\", float(ssim_loss_fs2))\n            report(\"train/duration_loss\", float(duration_loss))\n            report(\"train/pitch_loss\", float(pitch_loss))\n\n            losses_dict[\"l1_loss_fs2\"] = float(l1_loss_fs2)\n            losses_dict[\"ssim_loss_fs2\"] = float(ssim_loss_fs2)\n            losses_dict[\"duration_loss\"] = float(duration_loss)\n            losses_dict[\"pitch_loss\"] = float(pitch_loss)\n\n            if speaker_loss != 0.:\n                report(\"train/speaker_loss\", float(speaker_loss))\n                losses_dict[\"speaker_loss\"] = float(speaker_loss)\n            if energy_loss != 0.:\n                report(\"train/energy_loss\", float(energy_loss))\n                losses_dict[\"energy_loss\"] = float(energy_loss)\n\n            losses_dict[\"loss_fs2\"] = float(loss_fs2)\n            self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                  for k, v in losses_dict.items())\n\n        # Then only train diffusion module, freeze fastspeech2 parameters.\n        if self.state.iteration > self.ds_train_start_steps:\n            for param in self.model.fs2.parameters():\n                param.trainable = False if self.only_train_diffusion else True\n\n            noise_pred, noise_target, mel_masks = self.model(\n                text=batch[\"text\"],\n                note=batch[\"note\"],\n                note_dur=batch[\"note_dur\"],\n                is_slur=batch[\"is_slur\"],\n                text_lengths=batch[\"text_lengths\"],\n                speech=batch[\"speech\"],\n                speech_lengths=batch[\"speech_lengths\"],\n                durations=batch[\"durations\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                spk_id=spk_id,\n                spk_emb=spk_emb,\n                only_train_fs2=False, )\n\n            noise_pred = noise_pred.transpose((0, 2, 1))\n            noise_target = noise_target.transpose((0, 2, 1))\n            mel_masks = mel_masks.transpose((0, 2, 1))\n            l1_loss_ds = self.criterion_ds(\n                noise_pred=noise_pred,\n                noise_target=noise_target,\n                mel_masks=mel_masks, )\n\n            loss_ds = l1_loss_ds\n\n            self.optimizer_ds.clear_grad()\n            loss_ds.backward()\n            self.optimizer_ds.step()\n\n            report(\"train/loss_ds\", float(loss_ds))\n            report(\"train/l1_loss_ds\", float(l1_loss_ds))\n            losses_dict[\"l1_loss_ds\"] = float(l1_loss_ds)\n            losses_dict[\"loss_ds\"] = float(loss_ds)\n            self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                                  for k, v in losses_dict.items())\n\n        self.logger.info(self.msg)\n\n\nclass DiffSingerEvaluator(StandardEvaluator):\n    def __init__(\n            self,\n            model: Layer,\n            criterions: Dict[str, Layer],\n            dataloader: DataLoader,\n            output_dir: Path=None, ):\n        super().__init__(model, dataloader)\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n\n        self.criterions = criterions\n        self.criterion_fs2 = criterions['fs2']\n        self.criterion_ds = criterions['ds']\n        self.dataloader = dataloader\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        # spk_id!=None in multiple spk diffsinger \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        if spk_emb is not None:\n            spk_id = None\n\n        # Here show fastspeech2 eval \n        before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n            text=batch[\"text\"],\n            note=batch[\"note\"],\n            note_dur=batch[\"note_dur\"],\n            is_slur=batch[\"is_slur\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"],\n            durations=batch[\"durations\"],\n            pitch=batch[\"pitch\"],\n            energy=batch[\"energy\"],\n            spk_id=spk_id,\n            spk_emb=spk_emb,\n            only_train_fs2=True, )\n\n        l1_loss_fs2, ssim_loss_fs2, duration_loss, pitch_loss, energy_loss, speaker_loss = self.criterion_fs2(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            d_outs=d_outs,\n            p_outs=p_outs,\n            e_outs=e_outs,\n            ys=ys,\n            ds=batch[\"durations\"],\n            ps=batch[\"pitch\"],\n            es=batch[\"energy\"],\n            ilens=batch[\"text_lengths\"],\n            olens=olens,\n            spk_logits=spk_logits,\n            spk_ids=spk_id, )\n\n        loss_fs2 = l1_loss_fs2 + ssim_loss_fs2 + duration_loss + pitch_loss + energy_loss + speaker_loss\n\n        report(\"eval/loss_fs2\", float(loss_fs2))\n        report(\"eval/l1_loss_fs2\", float(l1_loss_fs2))\n        report(\"eval/ssim_loss_fs2\", float(ssim_loss_fs2))\n        report(\"eval/duration_loss\", float(duration_loss))\n        report(\"eval/pitch_loss\", float(pitch_loss))\n\n        losses_dict[\"l1_loss_fs2\"] = float(l1_loss_fs2)\n        losses_dict[\"ssim_loss_fs2\"] = float(ssim_loss_fs2)\n        losses_dict[\"duration_loss\"] = float(duration_loss)\n        losses_dict[\"pitch_loss\"] = float(pitch_loss)\n\n        if speaker_loss != 0.:\n            report(\"eval/speaker_loss\", float(speaker_loss))\n            losses_dict[\"speaker_loss\"] = float(speaker_loss)\n        if energy_loss != 0.:\n            report(\"eval/energy_loss\", float(energy_loss))\n            losses_dict[\"energy_loss\"] = float(energy_loss)\n\n        losses_dict[\"loss_fs2\"] = float(loss_fs2)\n\n        # Here show diffusion eval\n        noise_pred, noise_target, mel_masks = self.model(\n            text=batch[\"text\"],\n            note=batch[\"note\"],\n            note_dur=batch[\"note_dur\"],\n            is_slur=batch[\"is_slur\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"],\n            durations=batch[\"durations\"],\n            pitch=batch[\"pitch\"],\n            energy=batch[\"energy\"],\n            spk_id=spk_id,\n            spk_emb=spk_emb,\n            only_train_fs2=False, )\n\n        noise_pred = noise_pred.transpose((0, 2, 1))\n        noise_target = noise_target.transpose((0, 2, 1))\n        mel_masks = mel_masks.transpose((0, 2, 1))\n        l1_loss_ds = self.criterion_ds(\n            noise_pred=noise_pred,\n            noise_target=noise_target,\n            mel_masks=mel_masks, )\n\n        loss_ds = l1_loss_ds\n\n        report(\"eval/loss_ds\", float(loss_ds))\n        report(\"eval/l1_loss_ds\", float(l1_loss_ds))\n        losses_dict[\"l1_loss_ds\"] = float(l1_loss_ds)\n        losses_dict[\"loss_ds\"] = float(loss_ds)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/diffsinger/fastspeech2midi.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Loss\nfrom paddlespeech.t2s.modules.losses import ssim\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\n\n\nclass FastSpeech2MIDI(FastSpeech2):\n    \"\"\"The Fastspeech2 module of DiffSinger.\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # fastspeech2 network structure related\n            idim: int,\n            odim: int,\n            fastspeech2_params: Dict[str, Any],\n            # note emb\n            note_num: int=300,\n            # is_slur emb\n            is_slur_num: int=2,\n            use_energy_pred: bool=False,\n            use_postnet: bool=False, ):\n        \"\"\"Initialize FastSpeech2 module for svs.\n        Args:\n            fastspeech2_params (Dict):\n                The config of FastSpeech2 module on DiffSinger model\n            note_num (Optional[int]): \n                Number of note. If not None, assume that the\n                note_ids will be provided as the input and use note_embedding_table.\n            is_slur_num (Optional[int]): \n                Number of note. If not None, assume that the\n                is_slur_ids will be provided as the input\n    \n        \"\"\"\n        super().__init__(idim=idim, odim=odim, **fastspeech2_params)\n        self.use_energy_pred = use_energy_pred\n        self.use_postnet = use_postnet\n        if not self.use_postnet:\n            self.postnet = None\n\n        self.note_embed_dim = self.is_slur_embed_dim = fastspeech2_params[\n            \"adim\"]\n\n        # note_ embed\n        self.note_embedding_table = nn.Embedding(\n            num_embeddings=note_num,\n            embedding_dim=self.note_embed_dim,\n            padding_idx=self.padding_idx)\n        self.note_dur_layer = nn.Linear(1, self.note_embed_dim)\n\n        # slur embed\n        self.is_slur_embedding_table = nn.Embedding(\n            num_embeddings=is_slur_num,\n            embedding_dim=self.is_slur_embed_dim,\n            padding_idx=self.padding_idx)\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            spk_emb: paddle.Tensor=None,\n            spk_id: paddle.Tensor=None,\n    ) -> Tuple[paddle.Tensor, Dict[str, paddle.Tensor], paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token (phone) ids (B, Tmax).\n            note(Tensor(int64)): \n                Batch of padded note (element in music score) ids (B, Tmax).\n            note_dur(Tensor(float32)): \n                Batch of padded note durations in seconds (element in music score) (B, Tmax).\n            is_slur(Tensor(int64)): \n                Batch of padded slur (element in music score) ids (B, Tmax).\n            text_lengths(Tensor(int64)): \n                Batch of phone lengths of each input (B,).\n            speech(Tensor[float32]): \n                Batch of padded target features (e.g. mel) (B, Lmax, odim).\n            speech_lengths(Tensor(int64)): \n                Batch of the lengths of each target features (B,).\n            durations(Tensor(int64)): \n                Batch of padded token durations in frame (B, Tmax).\n            pitch(Tensor[float32]): \n                Batch of padded frame-averaged pitch (B, Lmax, 1).\n            energy(Tensor[float32]): \n                Batch of padded frame-averaged energy (B, Lmax, 1).\n            spk_emb(Tensor[float32], optional): \n                Batch of speaker embeddings (B, spk_embed_dim).\n            spk_id(Tnesor[int64], optional(int64)): \n                Batch of speaker ids (B,)\n\n        Returns:\n\n        \"\"\"\n        xs = paddle.cast(text, 'int64')\n        note = paddle.cast(note, 'int64')\n        note_dur = paddle.cast(note_dur, 'float32')\n        is_slur = paddle.cast(is_slur, 'int64')\n        ilens = paddle.cast(text_lengths, 'int64')\n        olens = paddle.cast(speech_lengths, 'int64')\n        ds = paddle.cast(durations, 'int64')\n        ps = pitch\n        es = energy\n        ys = speech\n        olens = speech_lengths\n        if spk_id is not None:\n            spk_id = paddle.cast(spk_id, 'int64')\n        # forward propagation\n        before_outs, after_outs, d_outs, p_outs, e_outs, spk_logits = self._forward(\n            xs=xs,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            ilens=ilens,\n            olens=olens,\n            ds=ds,\n            ps=ps,\n            es=es,\n            is_inference=False,\n            spk_emb=spk_emb,\n            spk_id=spk_id, )\n        # modify mod part of groundtruth\n        if self.reduction_factor > 1:\n            olens = olens - olens % self.reduction_factor\n            max_olen = max(olens)\n            ys = ys[:, :max_olen]\n\n        return before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits\n\n    def _forward(\n            self,\n            xs: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            ilens: paddle.Tensor,\n            olens: paddle.Tensor=None,\n            ds: paddle.Tensor=None,\n            ps: paddle.Tensor=None,\n            es: paddle.Tensor=None,\n            is_inference: bool=False,\n            is_train_diffusion: bool=False,\n            return_after_enc=False,\n            alpha: float=1.0,\n            spk_emb=None,\n            spk_id=None, ) -> Sequence[paddle.Tensor]:\n\n        before_outs = after_outs = d_outs = p_outs = e_outs = spk_logits = None\n        # forward encoder\n        masks = self._source_mask(ilens)\n        note_emb = self.note_embedding_table(note)\n        note_dur_emb = self.note_dur_layer(paddle.unsqueeze(note_dur, axis=-1))\n        is_slur_emb = self.is_slur_embedding_table(is_slur)\n\n        # (B, Tmax, adim)\n        hs, _ = self.encoder(\n            xs=xs,\n            masks=masks,\n            note_emb=note_emb,\n            note_dur_emb=note_dur_emb,\n            is_slur_emb=is_slur_emb, )\n\n        if self.spk_num and self.enable_speaker_classifier and not is_inference:\n            hs_for_spk_cls = self.grad_reverse(hs)\n            spk_logits = self.speaker_classifier(hs_for_spk_cls, ilens)\n        else:\n            spk_logits = None\n\n        # integrate speaker embedding\n        if self.spk_embed_dim is not None:\n            # spk_emb has a higher priority than spk_id\n            if spk_emb is not None:\n                hs = self._integrate_with_spk_embed(hs, spk_emb)\n            elif spk_id is not None:\n                spk_emb = self.spk_embedding_table(spk_id)\n                hs = self._integrate_with_spk_embed(hs, spk_emb)\n\n        # forward duration predictor (phone-level) and variance predictors (frame-level)\n        d_masks = make_pad_mask(ilens)\n        if olens is not None:\n            pitch_masks = make_pad_mask(olens).unsqueeze(-1)\n        else:\n            pitch_masks = None\n\n        # inference for decoder input for diffusion\n        if is_train_diffusion:\n            hs = self.length_regulator(hs, ds, is_inference=False)\n            p_outs = self.pitch_predictor(hs.detach(), pitch_masks)\n            p_embs = self.pitch_embed(p_outs.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            hs += p_embs\n            if self.use_energy_pred:\n                e_outs = self.energy_predictor(hs.detach(), pitch_masks)\n                e_embs = self.energy_embed(\n                    e_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n                hs += e_embs\n\n        elif is_inference:\n            # (B, Tmax)\n            if ds is not None:\n                d_outs = ds\n            else:\n                d_outs = self.duration_predictor.inference(hs, d_masks)\n\n            # (B, Lmax, adim)\n            hs = self.length_regulator(hs, d_outs, alpha, is_inference=True)\n\n            if ps is not None:\n                p_outs = ps\n            else:\n                if self.stop_gradient_from_pitch_predictor:\n                    p_outs = self.pitch_predictor(hs.detach(), pitch_masks)\n                else:\n                    p_outs = self.pitch_predictor(hs, pitch_masks)\n            p_embs = self.pitch_embed(p_outs.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            hs += p_embs\n\n            if self.use_energy_pred:\n                if es is not None:\n                    e_outs = es\n                else:\n                    if self.stop_gradient_from_energy_predictor:\n                        e_outs = self.energy_predictor(hs.detach(), pitch_masks)\n                    else:\n                        e_outs = self.energy_predictor(hs, pitch_masks)\n                e_embs = self.energy_embed(\n                    e_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n                hs += e_embs\n\n        # training\n        else:\n            d_outs = self.duration_predictor(hs, d_masks)\n            # (B, Lmax, adim)\n            hs = self.length_regulator(hs, ds, is_inference=False)\n            if self.stop_gradient_from_pitch_predictor:\n                p_outs = self.pitch_predictor(hs.detach(), pitch_masks)\n            else:\n                p_outs = self.pitch_predictor(hs, pitch_masks)\n            p_embs = self.pitch_embed(ps.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            hs += p_embs\n\n            if self.use_energy_pred:\n                if self.stop_gradient_from_energy_predictor:\n                    e_outs = self.energy_predictor(hs.detach(), pitch_masks)\n                else:\n                    e_outs = self.energy_predictor(hs, pitch_masks)\n                e_embs = self.energy_embed(es.transpose((0, 2, 1))).transpose(\n                    (0, 2, 1))\n                hs += e_embs\n\n        # forward decoder\n        if olens is not None and not is_inference:\n            if self.reduction_factor > 1:\n                olens_in = paddle.to_tensor(\n                    [olen // self.reduction_factor for olen in olens.numpy()])\n            else:\n                olens_in = olens\n            # (B, 1, T)\n            h_masks = self._source_mask(olens_in)\n        else:\n            h_masks = None\n\n        if return_after_enc:\n            return hs, h_masks\n\n        if self.decoder_type == 'cnndecoder':\n            # remove output masks for dygraph to static graph\n            zs = self.decoder(hs, h_masks)\n            before_outs = zs\n        else:\n            # (B, Lmax, adim)\n            zs, _ = self.decoder(hs, h_masks)\n            # (B, Lmax, odim)\n            before_outs = self.feat_out(zs).reshape(\n                (paddle.shape(zs)[0], -1, self.odim))\n\n        # postnet -> (B, Lmax//r * r, odim)\n        if self.postnet is None:\n            after_outs = before_outs\n        else:\n            after_outs = before_outs + self.postnet(\n                before_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n\n        return before_outs, after_outs, d_outs, p_outs, e_outs, spk_logits\n\n    def encoder_infer(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            alpha: float=1.0,\n            spk_emb=None,\n            spk_id=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        xs = paddle.cast(text, 'int64').unsqueeze(0)\n        note = paddle.cast(note, 'int64').unsqueeze(0)\n        note_dur = paddle.cast(note_dur, 'float32').unsqueeze(0)\n        is_slur = paddle.cast(is_slur, 'int64').unsqueeze(0)\n        # setup batch axis\n        ilens = paddle.shape(xs)[1]\n\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n\n        # (1, L, odim)\n        # use *_ to avoid bug in dygraph to static graph    \n        hs, _ = self._forward(\n            xs=xs,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            ilens=ilens,\n            is_inference=True,\n            return_after_enc=True,\n            alpha=alpha,\n            spk_emb=spk_emb,\n            spk_id=spk_id, )\n        return hs\n\n    # get encoder output for diffusion training\n    def encoder_infer_batch(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            ds: paddle.Tensor=None,\n            ps: paddle.Tensor=None,\n            es: paddle.Tensor=None,\n            alpha: float=1.0,\n            spk_emb=None,\n            spk_id=None, ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n\n        xs = paddle.cast(text, 'int64')\n        note = paddle.cast(note, 'int64')\n        note_dur = paddle.cast(note_dur, 'float32')\n        is_slur = paddle.cast(is_slur, 'int64')\n        ilens = paddle.cast(text_lengths, 'int64')\n        olens = paddle.cast(speech_lengths, 'int64')\n\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n\n        # (1, L, odim)\n        # use *_ to avoid bug in dygraph to static graph    \n        hs, h_masks = self._forward(\n            xs=xs,\n            note=note,\n            note_dur=note_dur,\n            is_slur=is_slur,\n            ilens=ilens,\n            olens=olens,\n            ds=ds,\n            ps=ps,\n            es=es,\n            return_after_enc=True,\n            is_train_diffusion=True,\n            alpha=alpha,\n            spk_emb=spk_emb,\n            spk_id=spk_id, )\n        return hs, h_masks\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            note: paddle.Tensor,\n            note_dur: paddle.Tensor,\n            is_slur: paddle.Tensor,\n            durations: paddle.Tensor=None,\n            pitch: paddle.Tensor=None,\n            energy: paddle.Tensor=None,\n            alpha: float=1.0,\n            use_teacher_forcing: bool=False,\n            spk_emb=None,\n            spk_id=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Generate the sequence of features given the sequences of characters.\n\n        Args:\n            text(Tensor(int64)): \n                Input sequence of characters (T,).\n            note(Tensor(int64)): \n                Input note (element in music score) ids (T,).\n            note_dur(Tensor(float32)): \n               Input note durations in seconds (element in music score) (T,).\n            is_slur(Tensor(int64)): \n                Input slur (element in music score) ids (T,).\n            durations(Tensor, optional (int64)): \n                Groundtruth of duration (T,).\n            pitch(Tensor, optional): \n                Groundtruth of token-averaged pitch (T, 1).\n            energy(Tensor, optional): \n                Groundtruth of token-averaged energy (T, 1).\n            alpha(float, optional): \n                Alpha to control the speed.\n            use_teacher_forcing(bool, optional): \n                Whether to use teacher forcing.\n                If true, groundtruth of duration, pitch and energy will be used.\n            spk_emb(Tensor, optional, optional): \n                peaker embedding vector (spk_embed_dim,). (Default value = None)\n            spk_id(Tensor, optional(int64), optional): \n                spk ids (1,). (Default value = None)\n\n        Returns:\n\n        \"\"\"\n        xs = paddle.cast(text, 'int64').unsqueeze(0)\n        note = paddle.cast(note, 'int64').unsqueeze(0)\n        note_dur = paddle.cast(note_dur, 'float32').unsqueeze(0)\n        is_slur = paddle.cast(is_slur, 'int64').unsqueeze(0)\n        d, p, e = durations, pitch, energy\n        # setup batch axis\n        ilens = paddle.shape(xs)[1]\n\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n\n        if use_teacher_forcing:\n            # use groundtruth of duration, pitch, and energy\n            ds = d.unsqueeze(0) if d is not None else None\n            ps = p.unsqueeze(0) if p is not None else None\n            es = e.unsqueeze(0) if e is not None else None\n\n            # (1, L, odim)\n            _, outs, d_outs, p_outs, e_outs, _ = self._forward(\n                xs=xs,\n                note=note,\n                note_dur=note_dur,\n                is_slur=is_slur,\n                ilens=ilens,\n                ds=ds,\n                ps=ps,\n                es=es,\n                spk_emb=spk_emb,\n                spk_id=spk_id,\n                is_inference=True)\n        else:\n            # (1, L, odim)\n            _, outs, d_outs, p_outs, e_outs, _ = self._forward(\n                xs=xs,\n                note=note,\n                note_dur=note_dur,\n                is_slur=is_slur,\n                ilens=ilens,\n                is_inference=True,\n                alpha=alpha,\n                spk_emb=spk_emb,\n                spk_id=spk_id, )\n\n        if e_outs is None:\n            e_outs = [None]\n\n        return outs[0], d_outs[0], p_outs[0], e_outs[0]\n\n\nclass FastSpeech2MIDILoss(FastSpeech2Loss):\n    \"\"\"Loss function module for DiffSinger.\"\"\"\n\n    @typechecked\n    def __init__(self, use_masking: bool=True,\n                 use_weighted_masking: bool=False):\n        \"\"\"Initialize feed-forward Transformer loss module.\n        Args:\n            use_masking (bool): \n                Whether to apply masking for padded part in loss calculation.\n            use_weighted_masking (bool): \n                Whether to weighted masking in loss calculation.\n        \"\"\"\n        super().__init__(use_masking, use_weighted_masking)\n\n    def forward(\n            self,\n            after_outs: paddle.Tensor,\n            before_outs: paddle.Tensor,\n            d_outs: paddle.Tensor,\n            p_outs: paddle.Tensor,\n            e_outs: paddle.Tensor,\n            ys: paddle.Tensor,\n            ds: paddle.Tensor,\n            ps: paddle.Tensor,\n            es: paddle.Tensor,\n            ilens: paddle.Tensor,\n            olens: paddle.Tensor,\n            spk_logits: paddle.Tensor=None,\n            spk_ids: paddle.Tensor=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n               paddle.Tensor, ]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            after_outs(Tensor):  \n                Batch of outputs after postnets (B, Lmax, odim).\n            before_outs(Tensor): \n                Batch of outputs before postnets (B, Lmax, odim).\n            d_outs(Tensor): \n                Batch of outputs of duration predictor (B, Tmax).\n            p_outs(Tensor): \n                Batch of outputs of pitch predictor (B, Lmax, 1).\n            e_outs(Tensor): \n                Batch of outputs of energy predictor (B, Lmax, 1).\n            ys(Tensor): \n                Batch of target features (B, Lmax, odim).\n            ds(Tensor): \n                Batch of durations (B, Tmax).\n            ps(Tensor): \n                Batch of target frame-averaged pitch (B, Lmax, 1).\n            es(Tensor): \n                Batch of target frame-averaged energy (B, Lmax, 1).\n            ilens(Tensor): \n                Batch of the lengths of each input (B,).\n            olens(Tensor): \n                Batch of the lengths of each target (B,).\n            spk_logits(Option[Tensor]):\n                Batch of outputs after speaker classifier (B, Lmax, num_spk)\n            spk_ids(Option[Tensor]):\n                Batch of target spk_id (B,)\n        \n\n        Returns:\n\n        \n        \"\"\"\n        l1_loss = duration_loss = pitch_loss = energy_loss = speaker_loss = ssim_loss = 0.0\n\n        # apply mask to remove padded part\n        if self.use_masking:\n            # make feature for ssim loss\n            out_pad_masks = make_pad_mask(olens).unsqueeze(-1)\n            before_outs_ssim = masked_fill(before_outs, out_pad_masks, 0.0)\n            if not paddle.equal_all(after_outs, before_outs):\n                after_outs_ssim = masked_fill(after_outs, out_pad_masks, 0.0)\n            ys_ssim = masked_fill(ys, out_pad_masks, 0.0)\n\n            out_masks = make_non_pad_mask(olens).unsqueeze(-1)\n            before_outs = before_outs.masked_select(\n                out_masks.broadcast_to(before_outs.shape))\n            if not paddle.equal_all(after_outs, before_outs):\n                after_outs = after_outs.masked_select(\n                    out_masks.broadcast_to(after_outs.shape))\n            ys = ys.masked_select(out_masks.broadcast_to(ys.shape))\n            duration_masks = make_non_pad_mask(ilens)\n            d_outs = d_outs.masked_select(\n                duration_masks.broadcast_to(d_outs.shape))\n            ds = ds.masked_select(duration_masks.broadcast_to(ds.shape))\n            pitch_masks = out_masks\n            p_outs = p_outs.masked_select(\n                pitch_masks.broadcast_to(p_outs.shape))\n            ps = ps.masked_select(pitch_masks.broadcast_to(ps.shape))\n            if e_outs is not None:\n                e_outs = e_outs.masked_select(\n                    pitch_masks.broadcast_to(e_outs.shape))\n                es = es.masked_select(pitch_masks.broadcast_to(es.shape))\n\n            if spk_logits is not None and spk_ids is not None:\n                batch_size = spk_ids.shape[0]\n                spk_ids = paddle.repeat_interleave(spk_ids, spk_logits.shape[1],\n                                                   None)\n                spk_logits = paddle.reshape(spk_logits,\n                                            [-1, spk_logits.shape[-1]])\n                mask_index = spk_logits.abs().sum(axis=1) != 0\n                spk_ids = spk_ids[mask_index]\n                spk_logits = spk_logits[mask_index]\n\n        # calculate loss\n        l1_loss = self.l1_criterion(before_outs, ys)\n        ssim_loss = 1.0 - ssim(\n            before_outs_ssim.unsqueeze(1), ys_ssim.unsqueeze(1))\n        if not paddle.equal_all(after_outs, before_outs):\n            l1_loss += self.l1_criterion(after_outs, ys)\n            ssim_loss += (\n                1.0 - ssim(after_outs_ssim.unsqueeze(1), ys_ssim.unsqueeze(1)))\n        l1_loss = l1_loss * 0.5\n        ssim_loss = ssim_loss * 0.5\n\n        duration_loss = self.duration_criterion(d_outs, ds)\n        pitch_loss = self.l1_criterion(p_outs, ps)\n        if e_outs is not None:\n            energy_loss = self.l1_criterion(e_outs, es)\n\n        if spk_logits is not None and spk_ids is not None:\n            speaker_loss = self.ce_criterion(spk_logits, spk_ids) / batch_size\n\n        # make weighted mask and apply it\n        if self.use_weighted_masking:\n            out_masks = make_non_pad_mask(olens).unsqueeze(-1)\n            out_weights = out_masks.cast(dtype=paddle.float32) / out_masks.cast(\n                dtype=paddle.float32).sum(\n                    axis=1, keepdim=True)\n            out_weights /= ys.shape[0] * ys.shape[2]\n            duration_masks = make_non_pad_mask(ilens)\n            duration_weights = (duration_masks.cast(dtype=paddle.float32) /\n                                duration_masks.cast(dtype=paddle.float32).sum(\n                                    axis=1, keepdim=True))\n            duration_weights /= ds.shape[0]\n\n            # apply weight\n            l1_loss = l1_loss.multiply(out_weights)\n            l1_loss = l1_loss.masked_select(\n                out_masks.broadcast_to(l1_loss.shape)).sum()\n            ssim_loss = ssim_loss.multiply(out_weights)\n            ssim_loss = ssim_loss.masked_select(\n                out_masks.broadcast_to(ssim_loss.shape)).sum()\n            duration_loss = (duration_loss.multiply(duration_weights)\n                             .masked_select(duration_masks).sum())\n            pitch_masks = out_masks\n            pitch_weights = out_weights\n            pitch_loss = pitch_loss.multiply(pitch_weights)\n            pitch_loss = pitch_loss.masked_select(\n                pitch_masks.broadcast_to(pitch_loss.shape)).sum()\n            if e_outs is not None:\n                energy_loss = energy_loss.multiply(pitch_weights)\n                energy_loss = energy_loss.masked_select(\n                    pitch_masks.broadcast_to(energy_loss.shape)).sum()\n\n        return l1_loss, ssim_loss, duration_loss, pitch_loss, energy_loss, speaker_loss\n"
  },
  {
    "path": "paddlespeech/t2s/models/ernie_sat/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .ernie_sat import *\nfrom .ernie_sat_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/ernie_sat/ernie_sat.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.conformer.convolution import ConvolutionModule\nfrom paddlespeech.t2s.modules.conformer.encoder_layer import EncoderLayer\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.tacotron2.decoder import Postnet\nfrom paddlespeech.t2s.modules.transformer.attention import LegacyRelPositionMultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.attention import MultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.attention import RelPositionMultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.embedding import LegacyRelPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import RelPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import ScaledPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.multi_layer_conv import Conv1dLinear\nfrom paddlespeech.t2s.modules.transformer.multi_layer_conv import MultiLayeredConv1d\nfrom paddlespeech.t2s.modules.transformer.positionwise_feed_forward import PositionwiseFeedForward\nfrom paddlespeech.t2s.modules.transformer.repeat import repeat\nfrom paddlespeech.t2s.modules.transformer.subsampling import Conv2dSubsampling\n\n\n# MLM -> Mask Language Model\nclass mySequential(nn.Sequential):\n    def forward(self, *inputs):\n        for module in self._sub_layers.values():\n            if type(inputs) == tuple:\n                inputs = module(*inputs)\n            else:\n                inputs = module(inputs)\n        return inputs\n\n\nclass MaskInputLayer(nn.Layer):\n    def __init__(self, out_features: int) -> None:\n        super().__init__()\n        self.mask_feature = paddle.create_parameter(\n            shape=(1, 1, out_features),\n            dtype=paddle.float32,\n            default_initializer=paddle.nn.initializer.Assign(\n                paddle.normal(shape=(1, 1, out_features))))\n\n    def forward(self, input: paddle.Tensor,\n                masked_pos: paddle.Tensor=None) -> paddle.Tensor:\n        masked_pos = paddle.expand_as(paddle.unsqueeze(masked_pos, -1), input)\n        masked_input = masked_fill(input, masked_pos, 0) + masked_fill(\n            paddle.expand_as(self.mask_feature, input), ~masked_pos, 0)\n        return masked_input\n\n\nclass MLMEncoder(nn.Layer):\n    \"\"\"Conformer encoder module.\n\n    Args:\n        idim (int): \n            Input dimension.\n        attention_dim (int): \n            Dimension of attention.\n        attention_heads (int): \n            The number of heads of multi head attention.\n        linear_units (int): \n            The number of units of position-wise feed forward.\n        num_blocks (int): \n            The number of decoder blocks.\n        dropout_rate (float): \n            Dropout rate.\n        positional_dropout_rate (float): \n            Dropout rate after adding positional encoding.\n        attention_dropout_rate (float): \n            Dropout rate in attention.\n        input_layer (Union[str, paddle.nn.Layer]): \n            Input layer type.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n        positionwise_layer_type (str): \n            \"linear\", \"conv1d\", or \"conv1d-linear\".\n        positionwise_conv_kernel_size (int): \n            Kernel size of positionwise conv1d layer.\n        macaron_style (bool): \n            Whether to use macaron style for positionwise layer.\n        pos_enc_layer_type (str): \n            Encoder positional encoding layer type.\n        selfattention_layer_type (str): \n            Encoder attention layer type.\n        activation_type (str): \n            Encoder activation function type.\n        use_cnn_module (bool): \n            Whether to use convolution module.\n        zero_triu (bool): \n            Whether to zero the upper triangular part of attention matrix.\n        cnn_module_kernel (int): \n            Kernerl size of convolution module.\n        padding_idx (int): \n            Padding idx for input_layer=embed.\n        stochastic_depth_rate (float): \n            Maximum probability to skip the encoder layer.\n\n    \"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 vocab_size: int=0,\n                 pre_speech_layer: int=0,\n                 attention_dim: int=256,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 attention_dropout_rate: float=0.0,\n                 input_layer: str=\"conv2d\",\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 positionwise_layer_type: str=\"linear\",\n                 positionwise_conv_kernel_size: int=1,\n                 macaron_style: bool=False,\n                 pos_enc_layer_type: str=\"abs_pos\",\n                 pos_enc_class=None,\n                 selfattention_layer_type: str=\"selfattn\",\n                 activation_type: str=\"swish\",\n                 use_cnn_module: bool=False,\n                 zero_triu: bool=False,\n                 cnn_module_kernel: int=31,\n                 padding_idx: int=-1,\n                 stochastic_depth_rate: float=0.0,\n                 text_masking: bool=False):\n        \"\"\"Construct an Encoder object.\"\"\"\n        super().__init__()\n        self._output_size = attention_dim\n        self.text_masking = text_masking\n        if self.text_masking:\n            self.text_masking_layer = MaskInputLayer(attention_dim)\n        activation = get_activation(activation_type)\n        if pos_enc_layer_type == \"abs_pos\":\n            pos_enc_class = PositionalEncoding\n        elif pos_enc_layer_type == \"scaled_abs_pos\":\n            pos_enc_class = ScaledPositionalEncoding\n        elif pos_enc_layer_type == \"rel_pos\":\n            assert selfattention_layer_type == \"rel_selfattn\"\n            pos_enc_class = RelPositionalEncoding\n        elif pos_enc_layer_type == \"legacy_rel_pos\":\n            pos_enc_class = LegacyRelPositionalEncoding\n            assert selfattention_layer_type == \"legacy_rel_selfattn\"\n        else:\n            raise ValueError(\"unknown pos_enc_layer: \" + pos_enc_layer_type)\n\n        self.conv_subsampling_factor = 1\n        if input_layer == \"linear\":\n            self.embed = nn.Sequential(\n                nn.Linear(idim, attention_dim),\n                nn.LayerNorm(attention_dim),\n                nn.Dropout(dropout_rate),\n                nn.ReLU(),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer == \"conv2d\":\n            self.embed = Conv2dSubsampling(\n                idim,\n                attention_dim,\n                dropout_rate,\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n            self.conv_subsampling_factor = 4\n        elif input_layer == \"embed\":\n            self.embed = nn.Sequential(\n                nn.Embedding(idim, attention_dim, padding_idx=padding_idx),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer == \"mlm\":\n            self.segment_emb = None\n            self.speech_embed = mySequential(\n                MaskInputLayer(idim),\n                nn.Linear(idim, attention_dim),\n                nn.LayerNorm(attention_dim),\n                nn.ReLU(),\n                pos_enc_class(attention_dim, positional_dropout_rate))\n            self.text_embed = nn.Sequential(\n                nn.Embedding(\n                    vocab_size, attention_dim, padding_idx=padding_idx),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer == \"sega_mlm\":\n            self.segment_emb = nn.Embedding(\n                500, attention_dim, padding_idx=padding_idx)\n            self.speech_embed = mySequential(\n                MaskInputLayer(idim),\n                nn.Linear(idim, attention_dim),\n                nn.LayerNorm(attention_dim),\n                nn.ReLU(),\n                pos_enc_class(attention_dim, positional_dropout_rate))\n            self.text_embed = nn.Sequential(\n                nn.Embedding(\n                    vocab_size, attention_dim, padding_idx=padding_idx),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif isinstance(input_layer, nn.Layer):\n            self.embed = nn.Sequential(\n                input_layer,\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer is None:\n            self.embed = nn.Sequential(\n                pos_enc_class(attention_dim, positional_dropout_rate))\n        else:\n            raise ValueError(\"unknown input_layer: \" + input_layer)\n        self.normalize_before = normalize_before\n\n        # self-attention module definition\n        if selfattention_layer_type == \"selfattn\":\n            encoder_selfattn_layer = MultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, attention_dim,\n                                           attention_dropout_rate, )\n        elif selfattention_layer_type == \"legacy_rel_selfattn\":\n            assert pos_enc_layer_type == \"legacy_rel_pos\"\n            encoder_selfattn_layer = LegacyRelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, attention_dim,\n                                           attention_dropout_rate, )\n        elif selfattention_layer_type == \"rel_selfattn\":\n            assert pos_enc_layer_type == \"rel_pos\"\n            encoder_selfattn_layer = RelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, attention_dim,\n                                           attention_dropout_rate, zero_triu, )\n        else:\n            raise ValueError(\"unknown encoder_attn_layer: \" +\n                             selfattention_layer_type)\n\n        # feed-forward module definition\n        if positionwise_layer_type == \"linear\":\n            positionwise_layer = PositionwiseFeedForward\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       dropout_rate, activation, )\n        elif positionwise_layer_type == \"conv1d\":\n            positionwise_layer = MultiLayeredConv1d\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       positionwise_conv_kernel_size,\n                                       dropout_rate, )\n        elif positionwise_layer_type == \"conv1d-linear\":\n            positionwise_layer = Conv1dLinear\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       positionwise_conv_kernel_size,\n                                       dropout_rate, )\n        else:\n            raise NotImplementedError(\"Support only linear or conv1d.\")\n\n        # convolution module definition\n        convolution_layer = ConvolutionModule\n        convolution_layer_args = (attention_dim, cnn_module_kernel, activation)\n\n        self.encoders = repeat(\n            num_blocks,\n            lambda lnum: EncoderLayer(\n                attention_dim,\n                encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                positionwise_layer(*positionwise_layer_args),\n                positionwise_layer(*positionwise_layer_args) if macaron_style else None,\n                convolution_layer(*convolution_layer_args) if use_cnn_module else None,\n                dropout_rate,\n                normalize_before,\n                concat_after,\n                stochastic_depth_rate * float(1 + lnum) / num_blocks, ), )\n        self.pre_speech_layer = pre_speech_layer\n        self.pre_speech_encoders = repeat(\n            self.pre_speech_layer,\n            lambda lnum: EncoderLayer(\n                attention_dim,\n                encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                positionwise_layer(*positionwise_layer_args),\n                positionwise_layer(*positionwise_layer_args) if macaron_style else None,\n                convolution_layer(*convolution_layer_args) if use_cnn_module else None,\n                dropout_rate,\n                normalize_before,\n                concat_after,\n                stochastic_depth_rate * float(1 + lnum) / self.pre_speech_layer, ),\n        )\n        if self.normalize_before:\n            self.after_norm = LayerNorm(attention_dim)\n\n    def forward(self,\n                speech: paddle.Tensor,\n                text: paddle.Tensor,\n                masked_pos: paddle.Tensor,\n                speech_mask: paddle.Tensor=None,\n                text_mask: paddle.Tensor=None,\n                speech_seg_pos: paddle.Tensor=None,\n                text_seg_pos: paddle.Tensor=None):\n        \"\"\"Encode input sequence.\n\n        \"\"\"\n        if masked_pos is not None:\n            speech = self.speech_embed(speech, masked_pos)\n        else:\n            speech = self.speech_embed(speech)\n        if text is not None:\n            text = self.text_embed(text)\n        if speech_seg_pos is not None and text_seg_pos is not None and self.segment_emb:\n            speech_seg_emb = self.segment_emb(speech_seg_pos)\n            text_seg_emb = self.segment_emb(text_seg_pos)\n            text = (text[0] + text_seg_emb, text[1])\n            speech = (speech[0] + speech_seg_emb, speech[1])\n        if self.pre_speech_encoders:\n            speech, _ = self.pre_speech_encoders(speech, speech_mask)\n\n        if text is not None:\n            xs = paddle.concat([speech[0], text[0]], axis=1)\n            xs_pos_emb = paddle.concat([speech[1], text[1]], axis=1)\n            masks = paddle.concat([speech_mask, text_mask], axis=-1)\n        else:\n            xs = speech[0]\n            xs_pos_emb = speech[1]\n            masks = speech_mask\n\n        xs, masks = self.encoders((xs, xs_pos_emb), masks)\n\n        if isinstance(xs, tuple):\n            xs = xs[0]\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n\n        return xs, masks\n\n\nclass MLMDecoder(MLMEncoder):\n    def forward(self, xs: paddle.Tensor, masks: paddle.Tensor):\n        \"\"\"Encode input sequence.\n\n        Args:\n            xs (paddle.Tensor): \n                Input tensor (#batch, time, idim).\n            masks (paddle.Tensor): \n                Mask tensor (#batch, time).\n\n        Returns:\n            paddle.Tensor: \n                Output tensor (#batch, time, attention_dim).\n            paddle.Tensor: \n                Mask tensor (#batch, time).\n\n        \"\"\"\n        xs = self.embed(xs)\n        xs, masks = self.encoders(xs, masks)\n\n        if isinstance(xs, tuple):\n            xs = xs[0]\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n\n        return xs, masks\n\n\n# encoder and decoder is nn.Layer, not str\nclass MLM(nn.Layer):\n    def __init__(self,\n                 odim: int,\n                 encoder: nn.Layer,\n                 decoder: Optional[nn.Layer],\n                 postnet_layers: int=0,\n                 postnet_chans: int=0,\n                 postnet_filts: int=0,\n                 text_masking: bool=False):\n\n        super().__init__()\n        self.odim = odim\n        self.encoder = encoder\n        self.decoder = decoder\n        self.vocab_size = encoder.text_embed[0]._num_embeddings\n\n        if self.decoder is None or not (hasattr(self.decoder,\n                                                'output_layer') and\n                                        self.decoder.output_layer is not None):\n            self.sfc = nn.Linear(self.encoder._output_size, odim)\n        else:\n            self.sfc = None\n        if text_masking:\n            self.text_sfc = nn.Linear(\n                self.encoder.text_embed[0]._embedding_dim,\n                self.vocab_size,\n                weight_attr=self.encoder.text_embed[0]._weight_attr)\n        else:\n            self.text_sfc = None\n\n        self.postnet = (None if postnet_layers == 0 else Postnet(\n            idim=self.encoder._output_size,\n            odim=odim,\n            n_layers=postnet_layers,\n            n_chans=postnet_chans,\n            n_filts=postnet_filts,\n            use_batch_norm=True,\n            dropout_rate=0.5, ))\n\n    def inference(\n            self,\n            speech: paddle.Tensor,\n            text: paddle.Tensor,\n            masked_pos: paddle.Tensor,\n            speech_mask: paddle.Tensor,\n            text_mask: paddle.Tensor,\n            speech_seg_pos: paddle.Tensor,\n            text_seg_pos: paddle.Tensor,\n            span_bdy: List[int],\n            use_teacher_forcing: bool=True, ) -> List[paddle.Tensor]:\n        '''\n        Args:\n            speech (paddle.Tensor): \n                input speech (1, Tmax, D).\n            text (paddle.Tensor): \n                input text (1, Tmax2).\n            masked_pos (paddle.Tensor): \n                masked position of input speech (1, Tmax)\n            speech_mask (paddle.Tensor): \n                mask of speech (1, 1, Tmax).\n            text_mask (paddle.Tensor): \n                mask of text (1, 1, Tmax2).\n            speech_seg_pos (paddle.Tensor): \n                n-th phone of each mel, 0<=n<=Tmax2 (1, Tmax).\n            text_seg_pos (paddle.Tensor): \n                n-th phone of each phone, 0<=n<=Tmax2 (1, Tmax2).\n            span_bdy (List[int]): \n                masked mel boundary of input speech (2,)\n            use_teacher_forcing (bool): \n                whether to use teacher forcing\n        Returns:\n            List[Tensor]:\n                eg: [Tensor(shape=[1, 181, 80]), Tensor(shape=[80, 80]), Tensor(shape=[1, 67, 80])]\n        '''\n\n        z_cache = None\n        if use_teacher_forcing:\n            before_outs, zs, *_ = self.forward(\n                speech=speech,\n                text=text,\n                masked_pos=masked_pos,\n                speech_mask=speech_mask,\n                text_mask=text_mask,\n                speech_seg_pos=speech_seg_pos,\n                text_seg_pos=text_seg_pos)\n            if zs is None:\n                zs = before_outs\n\n            speech = speech.squeeze(0)\n            outs = [speech[:span_bdy[0]]]\n            outs += [zs[0][span_bdy[0]:span_bdy[1]]]\n            outs += [speech[span_bdy[1]:]]\n            return outs\n        return None\n\n\nclass MLMEncAsDecoder(MLM):\n    def forward(self,\n                speech: paddle.Tensor,\n                text: paddle.Tensor,\n                masked_pos: paddle.Tensor,\n                speech_mask: paddle.Tensor,\n                text_mask: paddle.Tensor,\n                speech_seg_pos: paddle.Tensor,\n                text_seg_pos: paddle.Tensor):\n        # feats: (Batch, Length, Dim)\n        # -> encoder_out: (Batch, Length2, Dim2)\n        encoder_out, h_masks = self.encoder(\n            speech=speech,\n            text=text,\n            masked_pos=masked_pos,\n            speech_mask=speech_mask,\n            text_mask=text_mask,\n            speech_seg_pos=speech_seg_pos,\n            text_seg_pos=text_seg_pos)\n        if self.decoder is not None:\n            zs, _ = self.decoder(encoder_out, h_masks)\n        else:\n            zs = encoder_out\n        speech_hidden_states = zs[:, :paddle.shape(speech)[1], :]\n        if self.sfc is not None:\n            before_outs = paddle.reshape(\n                self.sfc(speech_hidden_states),\n                (paddle.shape(speech_hidden_states)[0], -1, self.odim))\n        else:\n            before_outs = speech_hidden_states\n        if self.postnet is not None:\n            after_outs = before_outs + paddle.transpose(\n                self.postnet(paddle.transpose(before_outs, [0, 2, 1])),\n                [0, 2, 1])\n        else:\n            after_outs = None\n        return before_outs, after_outs, None\n\n\nclass MLMDualMaksing(MLM):\n    def forward(self,\n                speech: paddle.Tensor,\n                text: paddle.Tensor,\n                masked_pos: paddle.Tensor,\n                speech_mask: paddle.Tensor,\n                text_mask: paddle.Tensor,\n                speech_seg_pos: paddle.Tensor,\n                text_seg_pos: paddle.Tensor):\n        # feats: (Batch, Length, Dim)\n        # -> encoder_out: (Batch, Length2, Dim2)\n        encoder_out, h_masks = self.encoder(\n            speech=speech,\n            text=text,\n            masked_pos=masked_pos,\n            speech_mask=speech_mask,\n            text_mask=text_mask,\n            speech_seg_pos=speech_seg_pos,\n            text_seg_pos=text_seg_pos)\n        if self.decoder is not None:\n            zs, _ = self.decoder(encoder_out, h_masks)\n        else:\n            zs = encoder_out\n        speech_hidden_states = zs[:, :paddle.shape(speech)[1], :]\n        if self.text_sfc:\n            text_hiddent_states = zs[:, paddle.shape(speech)[1]:, :]\n            text_outs = paddle.reshape(\n                self.text_sfc(text_hiddent_states),\n                (paddle.shape(text_hiddent_states)[0], -1, self.vocab_size))\n        if self.sfc is not None:\n            before_outs = paddle.reshape(\n                self.sfc(speech_hidden_states),\n                (paddle.shape(speech_hidden_states)[0], -1, self.odim))\n        else:\n            before_outs = speech_hidden_states\n        if self.postnet is not None:\n            after_outs = before_outs + paddle.transpose(\n                self.postnet(paddle.transpose(before_outs, [0, 2, 1])),\n                [0, 2, 1])\n        else:\n            after_outs = None\n        return before_outs, after_outs, text_outs\n\n\nclass ErnieSAT(nn.Layer):\n    def __init__(\n            self,\n            # network structure related\n            idim: int,\n            odim: int,\n            postnet_layers: int=5,\n            postnet_filts: int=5,\n            postnet_chans: int=256,\n            use_scaled_pos_enc: bool=False,\n            encoder_type: str='conformer',\n            decoder_type: str='conformer',\n            enc_input_layer: str='sega_mlm',\n            enc_pre_speech_layer: int=0,\n            enc_cnn_module_kernel: int=7,\n            enc_attention_dim: int=384,\n            enc_attention_heads: int=2,\n            enc_linear_units: int=1536,\n            enc_num_blocks: int=4,\n            enc_dropout_rate: float=0.2,\n            enc_positional_dropout_rate: float=0.2,\n            enc_attention_dropout_rate: float=0.2,\n            enc_normalize_before: bool=True,\n            enc_macaron_style: bool=True,\n            enc_use_cnn_module: bool=True,\n            enc_selfattention_layer_type: str='legacy_rel_selfattn',\n            enc_activation_type: str='swish',\n            enc_pos_enc_layer_type: str='legacy_rel_pos',\n            enc_positionwise_layer_type: str='conv1d',\n            enc_positionwise_conv_kernel_size: int=3,\n            text_masking: bool=False,\n            dec_cnn_module_kernel: int=31,\n            dec_attention_dim: int=384,\n            dec_attention_heads: int=2,\n            dec_linear_units: int=1536,\n            dec_num_blocks: int=4,\n            dec_dropout_rate: float=0.2,\n            dec_positional_dropout_rate: float=0.2,\n            dec_attention_dropout_rate: float=0.2,\n            dec_macaron_style: bool=True,\n            dec_use_cnn_module: bool=True,\n            dec_selfattention_layer_type: str='legacy_rel_selfattn',\n            dec_activation_type: str='swish',\n            dec_pos_enc_layer_type: str='legacy_rel_pos',\n            dec_positionwise_layer_type: str='conv1d',\n            dec_positionwise_conv_kernel_size: int=3,\n            init_type: str=\"xavier_uniform\", ):\n        super().__init__()\n        # store hyperparameters\n        self.odim = odim\n\n        self.use_scaled_pos_enc = use_scaled_pos_enc\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # Encoder\n        if encoder_type == \"conformer\":\n            encoder = MLMEncoder(\n                idim=odim,\n                vocab_size=idim,\n                pre_speech_layer=enc_pre_speech_layer,\n                attention_dim=enc_attention_dim,\n                attention_heads=enc_attention_heads,\n                linear_units=enc_linear_units,\n                num_blocks=enc_num_blocks,\n                dropout_rate=enc_dropout_rate,\n                positional_dropout_rate=enc_positional_dropout_rate,\n                attention_dropout_rate=enc_attention_dropout_rate,\n                input_layer=enc_input_layer,\n                normalize_before=enc_normalize_before,\n                positionwise_layer_type=enc_positionwise_layer_type,\n                positionwise_conv_kernel_size=enc_positionwise_conv_kernel_size,\n                macaron_style=enc_macaron_style,\n                pos_enc_layer_type=enc_pos_enc_layer_type,\n                selfattention_layer_type=enc_selfattention_layer_type,\n                activation_type=enc_activation_type,\n                use_cnn_module=enc_use_cnn_module,\n                cnn_module_kernel=enc_cnn_module_kernel,\n                text_masking=text_masking)\n        else:\n            raise ValueError(f\"{encoder_type} is not supported.\")\n\n        # Decoder\n        if decoder_type != 'no_decoder':\n            decoder = MLMDecoder(\n                idim=0,\n                input_layer=None,\n                cnn_module_kernel=dec_cnn_module_kernel,\n                attention_dim=dec_attention_dim,\n                attention_heads=dec_attention_heads,\n                linear_units=dec_linear_units,\n                num_blocks=dec_num_blocks,\n                dropout_rate=dec_dropout_rate,\n                positional_dropout_rate=dec_positional_dropout_rate,\n                macaron_style=dec_macaron_style,\n                use_cnn_module=dec_use_cnn_module,\n                selfattention_layer_type=dec_selfattention_layer_type,\n                activation_type=dec_activation_type,\n                pos_enc_layer_type=dec_pos_enc_layer_type,\n                positionwise_layer_type=dec_positionwise_layer_type,\n                positionwise_conv_kernel_size=dec_positionwise_conv_kernel_size)\n\n        else:\n            decoder = None\n\n        model_class = MLMDualMaksing if text_masking else MLMEncAsDecoder\n\n        self.model = model_class(\n            odim=odim,\n            encoder=encoder,\n            decoder=decoder,\n            postnet_layers=postnet_layers,\n            postnet_filts=postnet_filts,\n            postnet_chans=postnet_chans,\n            text_masking=text_masking)\n\n        nn.initializer.set_global_initializer(None)\n\n    def forward(self,\n                speech: paddle.Tensor,\n                text: paddle.Tensor,\n                masked_pos: paddle.Tensor,\n                speech_mask: paddle.Tensor,\n                text_mask: paddle.Tensor,\n                speech_seg_pos: paddle.Tensor,\n                text_seg_pos: paddle.Tensor):\n        return self.model(\n            speech=speech,\n            text=text,\n            masked_pos=masked_pos,\n            speech_mask=speech_mask,\n            text_mask=text_mask,\n            speech_seg_pos=speech_seg_pos,\n            text_seg_pos=text_seg_pos)\n\n    def inference(\n            self,\n            speech: paddle.Tensor,\n            text: paddle.Tensor,\n            masked_pos: paddle.Tensor,\n            speech_mask: paddle.Tensor,\n            text_mask: paddle.Tensor,\n            speech_seg_pos: paddle.Tensor,\n            text_seg_pos: paddle.Tensor,\n            span_bdy: List[int],\n            use_teacher_forcing: bool=True, ) -> Dict[str, paddle.Tensor]:\n        return self.model.inference(\n            speech=speech,\n            text=text,\n            masked_pos=masked_pos,\n            speech_mask=speech_mask,\n            text_mask=text_mask,\n            speech_seg_pos=speech_seg_pos,\n            text_seg_pos=text_seg_pos,\n            span_bdy=span_bdy,\n            use_teacher_forcing=use_teacher_forcing)\n\n\nclass ErnieSATInference(nn.Layer):\n    def __init__(self, normalizer, model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = model\n\n    def forward(\n            self,\n            speech: paddle.Tensor,\n            text: paddle.Tensor,\n            masked_pos: paddle.Tensor,\n            speech_mask: paddle.Tensor,\n            text_mask: paddle.Tensor,\n            speech_seg_pos: paddle.Tensor,\n            text_seg_pos: paddle.Tensor,\n            span_bdy: List[int],\n            use_teacher_forcing: bool=True, ):\n        outs = self.acoustic_model.inference(\n            speech=speech,\n            text=text,\n            masked_pos=masked_pos,\n            speech_mask=speech_mask,\n            text_mask=text_mask,\n            speech_seg_pos=speech_seg_pos,\n            text_seg_pos=text_seg_pos,\n            span_bdy=span_bdy,\n            use_teacher_forcing=use_teacher_forcing)\n\n        normed_mel_pre, normed_mel_masked, normed_mel_post = outs\n        logmel_pre = self.normalizer.inverse(normed_mel_pre)\n        logmel_masked = self.normalizer.inverse(normed_mel_masked)\n        logmel_post = self.normalizer.inverse(normed_mel_post)\n        return logmel_pre, logmel_masked, logmel_post\n"
  },
  {
    "path": "paddlespeech/t2s/models/ernie_sat/ernie_sat_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\n\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.modules.losses import MLMLoss\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass ErnieSATUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 scheduler: LRScheduler,\n                 dataloader: DataLoader,\n                 init_state=None,\n                 text_masking: bool=False,\n                 odim: int=80,\n                 vocab_size: int=100,\n                 output_dir: Path=None):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n        self.scheduler = scheduler\n\n        self.criterion = MLMLoss(\n            text_masking=text_masking, odim=odim, vocab_size=vocab_size)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        before_outs, after_outs, text_outs = self.model(\n            speech=batch[\"speech\"],\n            text=batch[\"text\"],\n            masked_pos=batch[\"masked_pos\"],\n            speech_mask=batch[\"speech_mask\"],\n            text_mask=batch[\"text_mask\"],\n            speech_seg_pos=batch[\"speech_seg_pos\"],\n            text_seg_pos=batch[\"text_seg_pos\"])\n\n        mlm_loss, text_mlm_loss = self.criterion(\n            speech=batch[\"speech\"],\n            before_outs=before_outs,\n            after_outs=after_outs,\n            masked_pos=batch[\"masked_pos\"],\n            text=batch[\"text\"],\n            # maybe None\n            text_outs=text_outs,\n            # maybe None\n            text_masked_pos=batch[\"text_masked_pos\"])\n\n        loss = mlm_loss + text_mlm_loss if text_mlm_loss is not None else mlm_loss\n\n        self.optimizer.clear_grad()\n\n        loss.backward()\n        self.optimizer.step()\n        self.scheduler.step()\n        scheduler_msg = 'lr: {}'.format(self.scheduler.last_lr)\n\n        report(\"train/loss\", float(loss))\n        report(\"train/mlm_loss\", float(mlm_loss))\n        if text_mlm_loss is not None:\n            report(\"train/text_mlm_loss\", float(text_mlm_loss))\n            losses_dict[\"text_mlm_loss\"] = float(text_mlm_loss)\n\n        losses_dict[\"mlm_loss\"] = float(mlm_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.msg += ', ' + scheduler_msg\n\n\nclass ErnieSATEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 dataloader: DataLoader,\n                 text_masking: bool=False,\n                 odim: int=80,\n                 vocab_size: int=100,\n                 output_dir: Path=None):\n        super().__init__(model, dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n        self.criterion = MLMLoss(\n            text_masking=text_masking, odim=odim, vocab_size=vocab_size)\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        before_outs, after_outs, text_outs = self.model(\n            speech=batch[\"speech\"],\n            text=batch[\"text\"],\n            masked_pos=batch[\"masked_pos\"],\n            speech_mask=batch[\"speech_mask\"],\n            text_mask=batch[\"text_mask\"],\n            speech_seg_pos=batch[\"speech_seg_pos\"],\n            text_seg_pos=batch[\"text_seg_pos\"])\n\n        mlm_loss, text_mlm_loss = self.criterion(\n            speech=batch[\"speech\"],\n            before_outs=before_outs,\n            after_outs=after_outs,\n            masked_pos=batch[\"masked_pos\"],\n            text=batch[\"text\"],\n            # maybe None\n            text_outs=text_outs,\n            # maybe None\n            text_masked_pos=batch[\"text_masked_pos\"])\n        loss = mlm_loss + text_mlm_loss if text_mlm_loss is not None else mlm_loss\n\n        report(\"eval/loss\", float(loss))\n        report(\"eval/mlm_loss\", float(mlm_loss))\n        if text_mlm_loss is not None:\n            report(\"eval/text_mlm_loss\", float(text_mlm_loss))\n            losses_dict[\"text_mlm_loss\"] = float(text_mlm_loss)\n\n        losses_dict[\"mlm_loss\"] = float(mlm_loss)\n        losses_dict[\"loss\"] = float(loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/fastspeech2/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .fastspeech2 import *\nfrom .fastspeech2_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/fastspeech2/fastspeech2.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Fastspeech2 related modules for paddle\"\"\"\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.modules.adversarial_loss.gradient_reversal import GradientReversalLayer\nfrom paddlespeech.t2s.modules.adversarial_loss.speaker_classifier import SpeakerClassifier\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\nfrom paddlespeech.t2s.modules.predictor.duration_predictor import DurationPredictor\nfrom paddlespeech.t2s.modules.predictor.duration_predictor import DurationPredictorLoss\nfrom paddlespeech.t2s.modules.predictor.length_regulator import LengthRegulator\nfrom paddlespeech.t2s.modules.predictor.variance_predictor import VariancePredictor\nfrom paddlespeech.t2s.modules.tacotron2.decoder import Postnet\nfrom paddlespeech.t2s.modules.transformer.encoder import CNNDecoder\nfrom paddlespeech.t2s.modules.transformer.encoder import CNNPostnet\nfrom paddlespeech.t2s.modules.transformer.encoder import ConformerEncoder\nfrom paddlespeech.t2s.modules.transformer.encoder import TransformerEncoder\n\n\nclass FastSpeech2(nn.Layer):\n    \"\"\"FastSpeech2 module.\n    \n    This is a module of FastSpeech2 described in `FastSpeech 2: Fast and\n    High-Quality End-to-End Text to Speech`_. Instead of quantized pitch and\n    energy, we use token-averaged value introduced in `FastPitch: Parallel\n    Text-to-speech with Pitch Prediction`_.\n    \n    .. _`FastSpeech 2: Fast and High-Quality End-to-End Text to Speech`:\n        https://arxiv.org/abs/2006.04558\n    .. _`FastPitch: Parallel Text-to-speech with Pitch Prediction`:\n        https://arxiv.org/abs/2006.06873\n\n    Args:\n    \n    Returns:\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # network structure related\n            idim: int,\n            odim: int,\n            adim: int=384,\n            aheads: int=4,\n            elayers: int=6,\n            eunits: int=1536,\n            dlayers: int=6,\n            dunits: int=1536,\n            postnet_layers: int=5,\n            postnet_chans: int=512,\n            postnet_filts: int=5,\n            postnet_dropout_rate: float=0.5,\n            positionwise_layer_type: str=\"conv1d\",\n            positionwise_conv_kernel_size: int=1,\n            use_scaled_pos_enc: bool=True,\n            use_batch_norm: bool=True,\n            encoder_normalize_before: bool=True,\n            decoder_normalize_before: bool=True,\n            encoder_concat_after: bool=False,\n            decoder_concat_after: bool=False,\n            reduction_factor: int=1,\n            encoder_type: str=\"transformer\",\n            decoder_type: str=\"transformer\",\n            # for transformer\n            transformer_enc_dropout_rate: float=0.1,\n            transformer_enc_positional_dropout_rate: float=0.1,\n            transformer_enc_attn_dropout_rate: float=0.1,\n            transformer_dec_dropout_rate: float=0.1,\n            transformer_dec_positional_dropout_rate: float=0.1,\n            transformer_dec_attn_dropout_rate: float=0.1,\n            transformer_activation_type: str=\"relu\",\n            # for conformer\n            conformer_pos_enc_layer_type: str=\"rel_pos\",\n            conformer_self_attn_layer_type: str=\"rel_selfattn\",\n            conformer_activation_type: str=\"swish\",\n            use_macaron_style_in_conformer: bool=True,\n            use_cnn_in_conformer: bool=True,\n            zero_triu: bool=False,\n            conformer_enc_kernel_size: int=7,\n            conformer_dec_kernel_size: int=31,\n            # for CNN Decoder\n            cnn_dec_dropout_rate: float=0.2,\n            cnn_postnet_dropout_rate: float=0.2,\n            cnn_postnet_resblock_kernel_sizes: List[int]=[256, 256],\n            cnn_postnet_kernel_size: int=5,\n            cnn_decoder_embedding_dim: int=256,\n            # duration predictor\n            duration_predictor_layers: int=2,\n            duration_predictor_chans: int=384,\n            duration_predictor_kernel_size: int=3,\n            duration_predictor_dropout_rate: float=0.1,\n            # energy predictor\n            energy_predictor_layers: int=2,\n            energy_predictor_chans: int=384,\n            energy_predictor_kernel_size: int=3,\n            energy_predictor_dropout: float=0.5,\n            energy_embed_kernel_size: int=9,\n            energy_embed_dropout: float=0.5,\n            stop_gradient_from_energy_predictor: bool=False,\n            # pitch predictor\n            pitch_predictor_layers: int=2,\n            pitch_predictor_chans: int=384,\n            pitch_predictor_kernel_size: int=3,\n            pitch_predictor_dropout: float=0.5,\n            pitch_embed_kernel_size: int=9,\n            pitch_embed_dropout: float=0.5,\n            stop_gradient_from_pitch_predictor: bool=False,\n            # spk emb\n            spk_num: Optional[int]=None,\n            spk_embed_dim: Optional[int]=None,\n            spk_embed_integration_type: str=\"add\",\n            # tone emb\n            tone_num: Optional[int]=None,\n            tone_embed_dim: Optional[int]=None,\n            tone_embed_integration_type: str=\"add\",\n            # training related\n            init_type: str=\"xavier_uniform\",\n            init_enc_alpha: float=1.0,\n            init_dec_alpha: float=1.0,\n            # speaker classifier\n            enable_speaker_classifier: bool=False,\n            hidden_sc_dim: int=256, ):\n        \"\"\"Initialize FastSpeech2 module.\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            odim (int): \n                Dimension of the outputs.\n            adim (int): \n                Attention dimension.\n            aheads (int): \n                Number of attention heads.\n            elayers (int): \n                Number of encoder layers.\n            eunits (int): \n                Number of encoder hidden units.\n            dlayers (int): \n                Number of decoder layers.\n            dunits (int): \n                Number of decoder hidden units.\n            postnet_layers (int): \n                Number of postnet layers.\n            postnet_chans (int): \n                Number of postnet channels.\n            postnet_filts (int): \n                Kernel size of postnet.\n            postnet_dropout_rate (float): \n                Dropout rate in postnet.\n            use_scaled_pos_enc (bool): \n                Whether to use trainable scaled pos encoding.\n            use_batch_norm (bool): \n                Whether to use batch normalization in encoder prenet.\n            encoder_normalize_before (bool): \n                Whether to apply layernorm layer before encoder block.\n            decoder_normalize_before (bool): \n                Whether to apply layernorm layer before decoder block.\n            encoder_concat_after (bool): \n                Whether to concatenate attention layer's input and output in encoder.\n            decoder_concat_after (bool): \n                Whether to concatenate attention layer's input  and output in decoder.\n            reduction_factor (int): \n                Reduction factor.\n            encoder_type (str): \n                Encoder type (\"transformer\" or \"conformer\").\n            decoder_type (str): \n                Decoder type (\"transformer\" or \"conformer\").\n            transformer_enc_dropout_rate (float): \n                Dropout rate in encoder except attention and positional encoding.\n            transformer_enc_positional_dropout_rate (float): \n                Dropout rate after encoder positional encoding.\n            transformer_enc_attn_dropout_rate (float): \n                Dropout rate in encoder self-attention module.\n            transformer_dec_dropout_rate (float): \n                Dropout rate in decoder except attention & positional encoding.\n            transformer_dec_positional_dropout_rate (float):\n                Dropout rate after decoder positional encoding.\n            transformer_dec_attn_dropout_rate (float): \n                Dropout rate in decoder self-attention module.\n            transformer_activation_type (str): \n                Activation function type in transformer.\n            conformer_pos_enc_layer_type (str): \n                Pos encoding layer type in conformer.\n            conformer_self_attn_layer_type (str): \n                Self-attention layer type in conformer\n            conformer_activation_type (str): \n                Activation function type in conformer.\n            use_macaron_style_in_conformer (bool): \n                Whether to use macaron style FFN.\n            use_cnn_in_conformer (bool): \n                Whether to use CNN in conformer.\n            zero_triu (bool): \n                Whether to use zero triu in relative self-attention module.\n            conformer_enc_kernel_size (int): \n                Kernel size of encoder conformer.\n            conformer_dec_kernel_size (int): \n                Kernel size of decoder conformer.\n            duration_predictor_layers (int): \n                Number of duration predictor layers.\n            duration_predictor_chans (int): \n                Number of duration predictor channels.\n            duration_predictor_kernel_size (int): \n                Kernel size of duration predictor.\n            duration_predictor_dropout_rate (float): \n                Dropout rate in duration predictor.\n            pitch_predictor_layers (int): \n                Number of pitch predictor layers.\n            pitch_predictor_chans (int):\n                Number of pitch predictor channels.\n            pitch_predictor_kernel_size (int): \n                Kernel size of pitch predictor.\n            pitch_predictor_dropout_rate (float): \n                Dropout rate in pitch predictor.\n            pitch_embed_kernel_size (float): \n                Kernel size of pitch embedding.\n            pitch_embed_dropout_rate (float): \n                Dropout rate for pitch embedding.\n            stop_gradient_from_pitch_predictor (bool): \n                Whether to stop gradient from pitch predictor to encoder.\n            energy_predictor_layers (int): \n                Number of energy predictor layers.\n            energy_predictor_chans (int): \n                Number of energy predictor channels.\n            energy_predictor_kernel_size (int): \n                Kernel size of energy predictor.\n            energy_predictor_dropout_rate (float): \n                Dropout rate in energy predictor.\n            energy_embed_kernel_size (float): \n                Kernel size of energy embedding.\n            energy_embed_dropout_rate (float): \n                Dropout rate for energy embedding.\n            stop_gradient_from_energy_predictor (bool): \n                Whether to stop gradient from energy predictor to encoder.\n            spk_num (Optional[int]): \n                Number of speakers. If not None, assume that the spk_embed_dim is not None,\n                spk_ids will be provided as the input and use spk_embedding_table.\n            spk_embed_dim (Optional[int]): \n                Speaker embedding dimension. If not None, \n                assume that spk_emb will be provided as the input or spk_num is not None.\n            spk_embed_integration_type (str): \n                How to integrate speaker embedding.\n            tone_num (Optional[int]): \n                Number of tones. If not None, assume that the\n                tone_ids will be provided as the input and use tone_embedding_table.\n            tone_embed_dim (Optional[int]):\n                Tone embedding dimension. If not None, assume that tone_num is not None.\n            tone_embed_integration_type (str): \n                How to integrate tone embedding.\n            init_type (str): \n                How to initialize transformer parameters.\n            init_enc_alpha (float): \n                Initial value of alpha in scaled pos encoding of the encoder.\n            init_dec_alpha (float): \n                Initial value of alpha in scaled pos encoding of the decoder.\n            enable_speaker_classifier (bool):\n                Whether to use speaker classifier module\n            hidden_sc_dim (int):\n                The hidden layer dim of speaker classifier\n    \n        \"\"\"\n        super().__init__()\n\n        # store hyperparameters\n        self.odim = odim\n        self.reduction_factor = reduction_factor\n        self.encoder_type = encoder_type\n        self.decoder_type = decoder_type\n        self.stop_gradient_from_pitch_predictor = stop_gradient_from_pitch_predictor\n        self.stop_gradient_from_energy_predictor = stop_gradient_from_energy_predictor\n        self.use_scaled_pos_enc = use_scaled_pos_enc\n        self.hidden_sc_dim = hidden_sc_dim\n        self.spk_num = spk_num\n        self.enable_speaker_classifier = enable_speaker_classifier\n\n        self.spk_embed_dim = spk_embed_dim\n        if self.spk_embed_dim is not None:\n            self.spk_embed_integration_type = spk_embed_integration_type\n\n        self.tone_embed_dim = tone_embed_dim\n        if self.tone_embed_dim is not None:\n            self.tone_embed_integration_type = tone_embed_integration_type\n\n        # use idx 0 as padding idx\n        self.padding_idx = 0\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        if spk_num and self.spk_embed_dim:\n            self.spk_embedding_table = nn.Embedding(\n                num_embeddings=spk_num,\n                embedding_dim=self.spk_embed_dim,\n                padding_idx=self.padding_idx)\n\n        if self.tone_embed_dim is not None:\n            self.tone_embedding_table = nn.Embedding(\n                num_embeddings=tone_num,\n                embedding_dim=self.tone_embed_dim,\n                padding_idx=self.padding_idx)\n\n        # get positional encoding layer type\n        transformer_pos_enc_layer_type = \"scaled_abs_pos\" if self.use_scaled_pos_enc else \"abs_pos\"\n\n        # define encoder\n        encoder_input_layer = nn.Embedding(\n            num_embeddings=idim,\n            embedding_dim=adim,\n            padding_idx=self.padding_idx)\n\n        if encoder_type == \"transformer\":\n            self.encoder = TransformerEncoder(\n                idim=idim,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=eunits,\n                num_blocks=elayers,\n                input_layer=encoder_input_layer,\n                dropout_rate=transformer_enc_dropout_rate,\n                positional_dropout_rate=transformer_enc_positional_dropout_rate,\n                attention_dropout_rate=transformer_enc_attn_dropout_rate,\n                pos_enc_layer_type=transformer_pos_enc_layer_type,\n                normalize_before=encoder_normalize_before,\n                concat_after=encoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                activation_type=transformer_activation_type)\n        elif encoder_type == \"conformer\":\n            self.encoder = ConformerEncoder(\n                idim=idim,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=eunits,\n                num_blocks=elayers,\n                input_layer=encoder_input_layer,\n                dropout_rate=transformer_enc_dropout_rate,\n                positional_dropout_rate=transformer_enc_positional_dropout_rate,\n                attention_dropout_rate=transformer_enc_attn_dropout_rate,\n                normalize_before=encoder_normalize_before,\n                concat_after=encoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                macaron_style=use_macaron_style_in_conformer,\n                pos_enc_layer_type=conformer_pos_enc_layer_type,\n                selfattention_layer_type=conformer_self_attn_layer_type,\n                activation_type=conformer_activation_type,\n                use_cnn_module=use_cnn_in_conformer,\n                cnn_module_kernel=conformer_enc_kernel_size,\n                zero_triu=zero_triu, )\n        else:\n            raise ValueError(f\"{encoder_type} is not supported.\")\n\n        # define additional projection for speaker embedding\n        if self.spk_embed_dim is not None:\n            if self.spk_embed_integration_type == \"add\":\n                self.spk_projection = nn.Linear(self.spk_embed_dim, adim)\n            else:\n                self.spk_projection = nn.Linear(adim + self.spk_embed_dim, adim)\n\n        # define additional projection for tone embedding\n        if self.tone_embed_dim is not None:\n            if self.tone_embed_integration_type == \"add\":\n                self.tone_projection = nn.Linear(self.tone_embed_dim, adim)\n            else:\n                self.tone_projection = nn.Linear(adim + self.tone_embed_dim,\n                                                 adim)\n\n        if self.spk_num and self.enable_speaker_classifier:\n            # set lambda = 1\n            self.grad_reverse = GradientReversalLayer(1)\n            self.speaker_classifier = SpeakerClassifier(\n                idim=adim, hidden_sc_dim=self.hidden_sc_dim, spk_num=spk_num)\n\n        # define duration predictor\n        self.duration_predictor = DurationPredictor(\n            idim=adim,\n            n_layers=duration_predictor_layers,\n            n_chans=duration_predictor_chans,\n            kernel_size=duration_predictor_kernel_size,\n            dropout_rate=duration_predictor_dropout_rate, )\n\n        # define pitch predictor\n        self.pitch_predictor = VariancePredictor(\n            idim=adim,\n            n_layers=pitch_predictor_layers,\n            n_chans=pitch_predictor_chans,\n            kernel_size=pitch_predictor_kernel_size,\n            dropout_rate=pitch_predictor_dropout, )\n        #  We use continuous pitch + FastPitch style avg\n        self.pitch_embed = nn.Sequential(\n            nn.Conv1D(\n                in_channels=1,\n                out_channels=adim,\n                kernel_size=pitch_embed_kernel_size,\n                padding=(pitch_embed_kernel_size - 1) // 2, ),\n            nn.Dropout(pitch_embed_dropout), )\n\n        # define energy predictor\n        self.energy_predictor = VariancePredictor(\n            idim=adim,\n            n_layers=energy_predictor_layers,\n            n_chans=energy_predictor_chans,\n            kernel_size=energy_predictor_kernel_size,\n            dropout_rate=energy_predictor_dropout, )\n        # We use continuous enegy + FastPitch style avg\n        self.energy_embed = nn.Sequential(\n            nn.Conv1D(\n                in_channels=1,\n                out_channels=adim,\n                kernel_size=energy_embed_kernel_size,\n                padding=(energy_embed_kernel_size - 1) // 2, ),\n            nn.Dropout(energy_embed_dropout), )\n\n        # define length regulator\n        self.length_regulator = LengthRegulator()\n\n        # define decoder\n        # NOTE: we use encoder as decoder\n        # because fastspeech's decoder is the same as encoder\n        if decoder_type == \"transformer\":\n            self.decoder = TransformerEncoder(\n                idim=0,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=dunits,\n                num_blocks=dlayers,\n                # in decoder, don't need layer before pos_enc_class (we use embedding here in encoder)\n                input_layer=None,\n                dropout_rate=transformer_dec_dropout_rate,\n                positional_dropout_rate=transformer_dec_positional_dropout_rate,\n                attention_dropout_rate=transformer_dec_attn_dropout_rate,\n                pos_enc_layer_type=transformer_pos_enc_layer_type,\n                normalize_before=decoder_normalize_before,\n                concat_after=decoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                activation_type=conformer_activation_type, )\n        elif decoder_type == \"conformer\":\n            self.decoder = ConformerEncoder(\n                idim=0,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=dunits,\n                num_blocks=dlayers,\n                input_layer=None,\n                dropout_rate=transformer_dec_dropout_rate,\n                positional_dropout_rate=transformer_dec_positional_dropout_rate,\n                attention_dropout_rate=transformer_dec_attn_dropout_rate,\n                normalize_before=decoder_normalize_before,\n                concat_after=decoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                macaron_style=use_macaron_style_in_conformer,\n                pos_enc_layer_type=conformer_pos_enc_layer_type,\n                selfattention_layer_type=conformer_self_attn_layer_type,\n                activation_type=conformer_activation_type,\n                use_cnn_module=use_cnn_in_conformer,\n                cnn_module_kernel=conformer_dec_kernel_size, )\n        elif decoder_type == 'cnndecoder':\n            self.decoder = CNNDecoder(\n                emb_dim=adim,\n                odim=odim,\n                kernel_size=cnn_postnet_kernel_size,\n                dropout_rate=cnn_dec_dropout_rate,\n                resblock_kernel_sizes=cnn_postnet_resblock_kernel_sizes)\n        else:\n            raise ValueError(f\"{decoder_type} is not supported.\")\n\n        # define final projection\n        self.feat_out = nn.Linear(adim, odim * reduction_factor)\n\n        # define postnet\n        if decoder_type == 'cnndecoder':\n            self.postnet = CNNPostnet(\n                odim=odim,\n                kernel_size=cnn_postnet_kernel_size,\n                dropout_rate=cnn_postnet_dropout_rate,\n                resblock_kernel_sizes=cnn_postnet_resblock_kernel_sizes)\n        else:\n            self.postnet = (None if postnet_layers == 0 else Postnet(\n                idim=idim,\n                odim=odim,\n                n_layers=postnet_layers,\n                n_chans=postnet_chans,\n                n_filts=postnet_filts,\n                use_batch_norm=use_batch_norm,\n                dropout_rate=postnet_dropout_rate, ))\n\n        nn.initializer.set_global_initializer(None)\n\n        self._reset_parameters(\n            init_enc_alpha=init_enc_alpha,\n            init_dec_alpha=init_dec_alpha, )\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            tone_id: paddle.Tensor=None,\n            spk_emb: paddle.Tensor=None,\n            spk_id: paddle.Tensor=None\n    ) -> Tuple[paddle.Tensor, Dict[str, paddle.Tensor], paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token ids (B, Tmax).\n            text_lengths(Tensor(int64)): \n                Batch of lengths of each input (B,).\n            speech(Tensor): \n                Batch of padded target features (B, Lmax, odim).\n            speech_lengths(Tensor(int64)): \n                Batch of the lengths of each target (B,).\n            durations(Tensor(int64)): \n                Batch of padded durations (B, Tmax).\n            pitch(Tensor): \n                Batch of padded token-averaged pitch (B, Tmax, 1).\n            energy(Tensor): \n                Batch of padded token-averaged energy (B, Tmax, 1).\n            tone_id(Tensor, optional(int64)): \n                Batch of padded tone ids  (B, Tmax).\n            spk_emb(Tensor, optional): \n                Batch of speaker embeddings (B, spk_embed_dim).\n            spk_id(Tnesor, optional(int64)): \n                Batch of speaker ids (B,)\n\n        Returns:\n\n        \"\"\"\n\n        # input of embedding must be int64\n        xs = paddle.cast(text, 'int64')\n        ilens = paddle.cast(text_lengths, 'int64')\n        ds = paddle.cast(durations, 'int64')\n        olens = paddle.cast(speech_lengths, 'int64')\n        ys = speech\n        ps = pitch\n        es = energy\n        if spk_id is not None:\n            spk_id = paddle.cast(spk_id, 'int64')\n        if tone_id is not None:\n            tone_id = paddle.cast(tone_id, 'int64')\n        # forward propagation\n        before_outs, after_outs, d_outs, p_outs, e_outs, spk_logits = self._forward(\n            xs,\n            ilens,\n            olens,\n            ds,\n            ps,\n            es,\n            is_inference=False,\n            spk_emb=spk_emb,\n            spk_id=spk_id,\n            tone_id=tone_id)\n        # modify mod part of groundtruth\n        if self.reduction_factor > 1:\n            olens = olens - olens % self.reduction_factor\n            max_olen = max(olens)\n            ys = ys[:, :max_olen]\n\n        return before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits\n\n    def _forward(self,\n                 xs: paddle.Tensor,\n                 ilens: paddle.Tensor,\n                 olens: paddle.Tensor=None,\n                 ds: paddle.Tensor=None,\n                 ps: paddle.Tensor=None,\n                 es: paddle.Tensor=None,\n                 is_inference: bool=False,\n                 return_after_enc=False,\n                 alpha: float=1.0,\n                 spk_emb=None,\n                 spk_id=None,\n                 tone_id=None) -> Sequence[paddle.Tensor]:\n        # forward encoder\n        x_masks = self._source_mask(ilens)\n        # (B, Tmax, adim)\n        hs, _ = self.encoder(xs, x_masks)\n\n        if self.spk_num and self.enable_speaker_classifier and not is_inference:\n            hs_for_spk_cls = self.grad_reverse(hs)\n            spk_logits = self.speaker_classifier(hs_for_spk_cls, ilens)\n        else:\n            spk_logits = None\n\n        # integrate speaker embedding\n        if self.spk_embed_dim is not None:\n            # spk_emb has a higher priority than spk_id\n            if spk_emb is not None:\n                hs = self._integrate_with_spk_embed(hs, spk_emb)\n            elif spk_id is not None:\n                spk_emb = self.spk_embedding_table(spk_id)\n                hs = self._integrate_with_spk_embed(hs, spk_emb)\n\n        # integrate tone embedding\n        if self.tone_embed_dim is not None:\n            if tone_id is not None:\n                tone_embs = self.tone_embedding_table(tone_id)\n                hs = self._integrate_with_tone_embed(hs, tone_embs)\n        # forward duration predictor and variance predictors\n        d_masks = make_pad_mask(ilens)\n\n        if self.stop_gradient_from_pitch_predictor:\n            p_outs = self.pitch_predictor(hs.detach(), d_masks.unsqueeze(-1))\n        else:\n            p_outs = self.pitch_predictor(hs, d_masks.unsqueeze(-1))\n        if self.stop_gradient_from_energy_predictor:\n            e_outs = self.energy_predictor(hs.detach(), d_masks.unsqueeze(-1))\n        else:\n            e_outs = self.energy_predictor(hs, d_masks.unsqueeze(-1))\n\n        if is_inference:\n            # (B, Tmax)\n            if ds is not None:\n                d_outs = ds\n            else:\n                d_outs = self.duration_predictor.inference(hs, d_masks)\n            if ps is not None:\n                p_outs = ps\n            if es is not None:\n                e_outs = es\n\n            # use prediction in inference\n            # (B, Tmax, 1)\n\n            p_embs = self.pitch_embed(p_outs.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            e_embs = self.energy_embed(e_outs.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            hs = hs + e_embs + p_embs\n\n            # (B, Lmax, adim)\n            hs = self.length_regulator(hs, d_outs, alpha, is_inference=True)\n        else:\n            d_outs = self.duration_predictor(hs, d_masks)\n            # use groundtruth in training\n            p_embs = self.pitch_embed(ps.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            e_embs = self.energy_embed(es.transpose((0, 2, 1))).transpose(\n                (0, 2, 1))\n            hs = hs + e_embs + p_embs\n\n            # (B, Lmax, adim)\n            hs = self.length_regulator(hs, ds, is_inference=False)\n\n        # forward decoder\n        if olens is not None and not is_inference:\n            if self.reduction_factor > 1:\n                olens_in = paddle.to_tensor(\n                    [olen // self.reduction_factor for olen in olens.numpy()])\n            else:\n                olens_in = olens\n            # (B, 1, T)\n            h_masks = self._source_mask(olens_in)\n        else:\n            h_masks = None\n        if return_after_enc:\n            return hs, h_masks\n\n        if self.decoder_type == 'cnndecoder':\n            # remove output masks for dygraph to static graph\n            zs = self.decoder(hs, h_masks)\n            before_outs = zs\n        else:\n            # (B, Lmax, adim)\n            zs, _ = self.decoder(hs, h_masks)\n            # (B, Lmax, odim)\n            before_outs = self.feat_out(zs).reshape(\n                (paddle.shape(zs)[0], -1, self.odim))\n\n        # postnet -> (B, Lmax//r * r, odim)\n        if self.postnet is None:\n            after_outs = before_outs\n        else:\n            after_outs = before_outs + self.postnet(\n                before_outs.transpose((0, 2, 1))).transpose((0, 2, 1))\n\n        return before_outs, after_outs, d_outs, p_outs, e_outs, spk_logits\n\n    def encoder_infer(\n            self,\n            text: paddle.Tensor,\n            spk_id=None,\n            alpha: float=1.0,\n            spk_emb=None,\n            tone_id=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        # input of embedding must be int64\n        x = paddle.cast(text, 'int64')\n        # setup batch axis\n        ilens = paddle.shape(x)[0]\n\n        xs = x.unsqueeze(0)\n\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n\n        if tone_id is not None:\n            tone_id = tone_id.unsqueeze(0)\n\n        # (1, L, odim)\n        # use *_ to avoid bug in dygraph to static graph    \n        hs, *_ = self._forward(\n            xs,\n            ilens,\n            is_inference=True,\n            return_after_enc=True,\n            alpha=alpha,\n            spk_emb=spk_emb,\n            spk_id=spk_id,\n            tone_id=tone_id)\n        return hs\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            durations: paddle.Tensor=None,\n            pitch: paddle.Tensor=None,\n            energy: paddle.Tensor=None,\n            alpha: float=1.0,\n            use_teacher_forcing: bool=False,\n            spk_emb=None,\n            spk_id=None,\n            tone_id=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Generate the sequence of features given the sequences of characters.\n\n        Args:\n            text(Tensor(int64)): \n                Input sequence of characters (T,).\n            durations(Tensor, optional (int64)): \n                Groundtruth of duration (T,).\n            pitch(Tensor, optional): \n                Groundtruth of token-averaged pitch (T, 1).\n            energy(Tensor, optional): \n                Groundtruth of token-averaged energy (T, 1).\n            alpha(float, optional): \n                Alpha to control the speed.\n            use_teacher_forcing(bool, optional): \n                Whether to use teacher forcing.\n                If true, groundtruth of duration, pitch and energy will be used.\n            spk_emb(Tensor, optional, optional): \n                peaker embedding vector (spk_embed_dim,). (Default value = None)\n            spk_id(Tensor, optional(int64), optional): \n                spk ids (1,). (Default value = None)\n            tone_id(Tensor, optional(int64), optional): \n                tone ids (T,). (Default value = None)\n\n        Returns:\n\n        \"\"\"\n        # input of embedding must be int64\n        x = paddle.cast(text, 'int64')\n        d, p, e = durations, pitch, energy\n        # setup batch axis\n        ilens = paddle.shape(x)[0:1]\n\n        xs = x.unsqueeze(0)\n\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n\n        if tone_id is not None:\n            tone_id = tone_id.unsqueeze(0)\n\n        if use_teacher_forcing:\n            # use groundtruth of duration, pitch, and energy\n            ds = d.unsqueeze(0) if d is not None else None\n            ps = p.unsqueeze(0) if p is not None else None\n            es = e.unsqueeze(0) if e is not None else None\n\n            # (1, L, odim)\n            _, outs, d_outs, p_outs, e_outs, _ = self._forward(\n                xs,\n                ilens,\n                ds=ds,\n                ps=ps,\n                es=es,\n                spk_emb=spk_emb,\n                spk_id=spk_id,\n                tone_id=tone_id,\n                is_inference=True)\n        else:\n            # (1, L, odim)\n            _, outs, d_outs, p_outs, e_outs, _ = self._forward(\n                xs,\n                ilens,\n                is_inference=True,\n                alpha=alpha,\n                spk_emb=spk_emb,\n                spk_id=spk_id,\n                tone_id=tone_id)\n\n        return outs[0], d_outs[0], p_outs[0], e_outs[0]\n\n    def _integrate_with_spk_embed(self, hs, spk_emb):\n        \"\"\"Integrate speaker embedding with hidden states.\n\n        Args:\n            hs(Tensor): \n                Batch of hidden state sequences (B, Tmax, adim).\n            spk_emb(Tensor): \n                Batch of speaker embeddings (B, spk_embed_dim).\n\n        Returns:\n\n        \n        \"\"\"\n        if self.spk_embed_integration_type == \"add\":\n            # apply projection and then add to hidden states\n            spk_emb = self.spk_projection(F.normalize(spk_emb))\n            hs = hs + spk_emb.unsqueeze(1)\n        elif self.spk_embed_integration_type == \"concat\":\n            # one wave `spk_emb` under synthesize, the dim is `1`\n            if spk_emb.dim() == 1:\n                spk_emb = spk_emb.unsqueeze(0)\n            # concat hidden states with spk embeds and then apply projection\n            spk_emb = F.normalize(spk_emb).unsqueeze(1).expand(\n                shape=[-1, paddle.shape(hs)[1], -1])\n            hs = self.spk_projection(paddle.concat([hs, spk_emb], axis=-1))\n        else:\n            raise NotImplementedError(\"support only add or concat.\")\n\n        return hs\n\n    def _integrate_with_tone_embed(self, hs, tone_embs):\n        \"\"\"Integrate speaker embedding with hidden states.\n\n        Args:\n            hs(Tensor): \n                Batch of hidden state sequences (B, Tmax, adim).\n            tone_embs(Tensor): \n                Batch of speaker embeddings (B, Tmax, tone_embed_dim).\n\n        Returns:\n\n        \"\"\"\n        if self.tone_embed_integration_type == \"add\":\n            # apply projection and then add to hidden states\n            tone_embs = self.tone_projection(F.normalize(tone_embs))\n            hs = hs + tone_embs\n\n        elif self.tone_embed_integration_type == \"concat\":\n            # concat hidden states with tone embeds and then apply projection\n            tone_embs = F.normalize(tone_embs).expand(\n                shape=[-1, hs.shape[1], -1])\n            hs = self.tone_projection(paddle.concat([hs, tone_embs], axis=-1))\n        else:\n            raise NotImplementedError(\"support only add or concat.\")\n        return hs\n\n    def _source_mask(self, ilens: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Make masks for self-attention.\n\n        Args:\n            ilens(Tensor): \n                Batch of lengths (B,).\n\n        Returns:\n            Tensor: \n                Mask tensor for self-attention. dtype=paddle.bool\n\n        Examples:\n            >>> ilens = [5, 3]\n            >>> self._source_mask(ilens)\n            tensor([[[1, 1, 1, 1, 1],\n                        [1, 1, 1, 0, 0]]]) bool\n        \"\"\"\n        x_masks = make_non_pad_mask(ilens)\n        return x_masks.unsqueeze(-2)\n\n    def _reset_parameters(self, init_enc_alpha: float, init_dec_alpha: float):\n\n        # initialize alpha in scaled positional encoding\n        if self.encoder_type == \"transformer\" and self.use_scaled_pos_enc:\n            init_enc_alpha = paddle.to_tensor(init_enc_alpha).reshape([1])\n            self.encoder.embed[-1].alpha = paddle.create_parameter(\n                shape=init_enc_alpha.shape,\n                dtype=str(init_enc_alpha.numpy().dtype),\n                default_initializer=paddle.nn.initializer.Assign(\n                    init_enc_alpha))\n        if self.decoder_type == \"transformer\" and self.use_scaled_pos_enc:\n            init_dec_alpha = paddle.to_tensor(init_dec_alpha).reshape([1])\n            self.decoder.embed[-1].alpha = paddle.create_parameter(\n                shape=init_dec_alpha.shape,\n                dtype=str(init_dec_alpha.numpy().dtype),\n                default_initializer=paddle.nn.initializer.Assign(\n                    init_dec_alpha))\n\n\nclass FastSpeech2Inference(nn.Layer):\n    def __init__(self, normalizer, model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = model\n\n    def forward(self, text, spk_id=None, spk_emb=None):\n        normalized_mel, d_outs, p_outs, e_outs = self.acoustic_model.inference(\n            text, spk_id=spk_id, spk_emb=spk_emb)\n        logmel = self.normalizer.inverse(normalized_mel)\n        return logmel\n\n\nclass StyleFastSpeech2Inference(FastSpeech2Inference):\n    def __init__(self,\n                 normalizer,\n                 model,\n                 pitch_stats_path=None,\n                 energy_stats_path=None):\n        super().__init__(normalizer, model)\n        if pitch_stats_path:\n            pitch_mean, pitch_std = np.load(pitch_stats_path)\n            self.pitch_mean = paddle.to_tensor(pitch_mean)\n            self.pitch_std = paddle.to_tensor(pitch_std)\n        if energy_stats_path:\n            energy_mean, energy_std = np.load(energy_stats_path)\n            self.energy_mean = paddle.to_tensor(energy_mean)\n            self.energy_std = paddle.to_tensor(energy_std)\n\n    def denorm(self, data, mean, std):\n        return data * std + mean\n\n    def norm(self, data, mean, std):\n        return (data - mean) / std\n\n    def forward(self,\n                text: paddle.Tensor,\n                durations: Union[paddle.Tensor, np.ndarray]=None,\n                durations_scale: Union[int, float]=None,\n                durations_bias: Union[int, float]=None,\n                pitch: Union[paddle.Tensor, np.ndarray]=None,\n                pitch_scale: Union[int, float]=None,\n                pitch_bias: Union[int, float]=None,\n                energy: Union[paddle.Tensor, np.ndarray]=None,\n                energy_scale: Union[int, float]=None,\n                energy_bias: Union[int, float]=None,\n                robot: bool=False,\n                spk_emb=None,\n                spk_id=None):\n        \"\"\"\n\n        Args:\n            text(Tensor(int64)): \n                Input sequence of characters (T,).\n            durations(paddle.Tensor/np.ndarray, optional (int64)): \n                Groundtruth of duration (T,), this will overwrite the set of durations_scale and durations_bias\n            durations_scale(int/float, optional): \n\n            durations_bias(int/float, optional): \n\n            pitch(paddle.Tensor/np.ndarray, optional): \n                Groundtruth of token-averaged pitch (T, 1), this will overwrite the set of pitch_scale and pitch_bias\n            pitch_scale(int/float, optional): \n                In denormed HZ domain.\n            pitch_bias(int/float, optional): \n                In denormed HZ domain.\n            energy(paddle.Tensor/np.ndarray, optional): \n                Groundtruth of token-averaged energy (T, 1), this will overwrite the set of energy_scale and energy_bias\n            energy_scale(int/float, optional): \n                In denormed domain.\n            energy_bias(int/float, optional): \n                In denormed domain.\n            robot(bool) (Default value = False):\n\n            spk_emb(Default value = None):\n\n            spk_id(Default value = None):\n\n\n        Returns:\n            Tensor: logmel\n\n        \"\"\"\n        normalized_mel, d_outs, p_outs, e_outs = self.acoustic_model.inference(\n            text,\n            durations=None,\n            pitch=None,\n            energy=None,\n            spk_emb=spk_emb,\n            spk_id=spk_id)\n        # priority: groundtruth > scale/bias > previous output\n        # set durations\n        if isinstance(durations, np.ndarray):\n            durations = paddle.to_tensor(durations)\n        elif isinstance(durations, paddle.Tensor):\n            durations = durations\n        elif durations_scale or durations_bias:\n            durations_scale = durations_scale if durations_scale is not None else 1\n            durations_bias = durations_bias if durations_bias is not None else 0\n            durations = durations_scale * d_outs + durations_bias\n        else:\n            durations = d_outs\n\n        if robot:\n            # set normed pitch to zeros have the same effect with set denormd ones to mean\n            pitch = paddle.zeros(p_outs.shape)\n\n        # set pitch, can overwrite robot set  \n        if isinstance(pitch, np.ndarray):\n            pitch = paddle.to_tensor(pitch)\n        elif isinstance(pitch, paddle.Tensor):\n            pitch = pitch\n        elif pitch_scale or pitch_bias:\n            pitch_scale = pitch_scale if pitch_scale is not None else 1\n            pitch_bias = pitch_bias if pitch_bias is not None else 0\n            p_Hz = paddle.exp(\n                self.denorm(p_outs, self.pitch_mean, self.pitch_std))\n            p_HZ = pitch_scale * p_Hz + pitch_bias\n            pitch = self.norm(paddle.log(p_HZ), self.pitch_mean, self.pitch_std)\n        else:\n            pitch = p_outs\n\n        # set energy\n        if isinstance(energy, np.ndarray):\n            energy = paddle.to_tensor(energy)\n        elif isinstance(energy, paddle.Tensor):\n            energy = energy\n        elif energy_scale or energy_bias:\n            energy_scale = energy_scale if energy_scale is not None else 1\n            energy_bias = energy_bias if energy_bias is not None else 0\n            e_dnorm = self.denorm(e_outs, self.energy_mean, self.energy_std)\n            e_dnorm = energy_scale * e_dnorm + energy_bias\n            energy = self.norm(e_dnorm, self.energy_mean, self.energy_std)\n        else:\n            energy = e_outs\n\n        normalized_mel, d_outs, p_outs, e_outs = self.acoustic_model.inference(\n            text,\n            durations=durations,\n            pitch=pitch,\n            energy=energy,\n            use_teacher_forcing=True,\n            spk_emb=spk_emb,\n            spk_id=spk_id)\n\n        logmel = self.normalizer.inverse(normalized_mel)\n        return logmel\n\n\nclass FastSpeech2Loss(nn.Layer):\n    \"\"\"Loss function module for FastSpeech2.\"\"\"\n\n    @typechecked\n    def __init__(self, use_masking: bool=True,\n                 use_weighted_masking: bool=False):\n        \"\"\"Initialize feed-forward Transformer loss module.\n        Args:\n            use_masking (bool): \n                Whether to apply masking for padded part in loss calculation.\n            use_weighted_masking (bool): \n                Whether to weighted masking in loss calculation.\n        \"\"\"\n        super().__init__()\n\n        assert (use_masking != use_weighted_masking) or not use_masking\n        self.use_masking = use_masking\n        self.use_weighted_masking = use_weighted_masking\n\n        # define criterions\n        reduction = \"none\" if self.use_weighted_masking else \"mean\"\n        self.l1_criterion = nn.L1Loss(reduction=reduction)\n        self.mse_criterion = nn.MSELoss(reduction=reduction)\n        self.duration_criterion = DurationPredictorLoss(reduction=reduction)\n        self.ce_criterion = nn.CrossEntropyLoss()\n\n    def forward(\n            self,\n            after_outs: paddle.Tensor,\n            before_outs: paddle.Tensor,\n            d_outs: paddle.Tensor,\n            p_outs: paddle.Tensor,\n            e_outs: paddle.Tensor,\n            ys: paddle.Tensor,\n            ds: paddle.Tensor,\n            ps: paddle.Tensor,\n            es: paddle.Tensor,\n            ilens: paddle.Tensor,\n            olens: paddle.Tensor,\n            spk_logits: paddle.Tensor=None,\n            spk_ids: paddle.Tensor=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n               paddle.Tensor, ]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            after_outs(Tensor):  \n                Batch of outputs after postnets (B, Lmax, odim).\n            before_outs(Tensor): \n                Batch of outputs before postnets (B, Lmax, odim).\n            d_outs(Tensor): \n                Batch of outputs of duration predictor (B, Tmax).\n            p_outs(Tensor): \n                Batch of outputs of pitch predictor (B, Tmax, 1).\n            e_outs(Tensor): \n                Batch of outputs of energy predictor (B, Tmax, 1).\n            ys(Tensor): \n                Batch of target features (B, Lmax, odim).\n            ds(Tensor): \n                Batch of durations (B, Tmax).\n            ps(Tensor): \n                Batch of target token-averaged pitch (B, Tmax, 1).\n            es(Tensor): \n                Batch of target token-averaged energy (B, Tmax, 1).\n            ilens(Tensor): \n                Batch of the lengths of each input (B,).\n            olens(Tensor): \n                Batch of the lengths of each target (B,).\n            spk_logits(Option[Tensor]):\n                Batch of outputs after speaker classifier (B, Lmax, num_spk)\n            spk_ids(Option[Tensor]):\n                Batch of target spk_id (B,)\n            \n\n        Returns:\n\n        \n        \"\"\"\n        speaker_loss = 0.0\n\n        # apply mask to remove padded part\n        if self.use_masking:\n            out_masks = make_non_pad_mask(olens).unsqueeze(-1)\n            before_outs = before_outs.masked_select(\n                out_masks.broadcast_to(before_outs.shape))\n            if after_outs is not None:\n                after_outs = after_outs.masked_select(\n                    out_masks.broadcast_to(after_outs.shape))\n            ys = ys.masked_select(out_masks.broadcast_to(ys.shape))\n            duration_masks = make_non_pad_mask(ilens)\n            d_outs = d_outs.masked_select(\n                duration_masks.broadcast_to(d_outs.shape))\n            ds = ds.masked_select(duration_masks.broadcast_to(ds.shape))\n            pitch_masks = make_non_pad_mask(ilens).unsqueeze(-1)\n            p_outs = p_outs.masked_select(\n                pitch_masks.broadcast_to(p_outs.shape))\n            e_outs = e_outs.masked_select(\n                pitch_masks.broadcast_to(e_outs.shape))\n            ps = ps.masked_select(pitch_masks.broadcast_to(ps.shape))\n            es = es.masked_select(pitch_masks.broadcast_to(es.shape))\n\n            if spk_logits is not None and spk_ids is not None:\n                batch_size = spk_ids.shape[0]\n                spk_ids = paddle.repeat_interleave(spk_ids, spk_logits.shape[1],\n                                                   None)\n                spk_logits = paddle.reshape(spk_logits,\n                                            [-1, spk_logits.shape[-1]])\n                mask_index = spk_logits.abs().sum(axis=1) != 0\n                spk_ids = spk_ids[mask_index]\n                spk_logits = spk_logits[mask_index]\n\n        # calculate loss\n        l1_loss = self.l1_criterion(before_outs, ys)\n        if after_outs is not None:\n            l1_loss += self.l1_criterion(after_outs, ys)\n        duration_loss = self.duration_criterion(d_outs, ds)\n        pitch_loss = self.mse_criterion(p_outs, ps)\n        energy_loss = self.mse_criterion(e_outs, es)\n\n        if spk_logits is not None and spk_ids is not None:\n            speaker_loss = self.ce_criterion(spk_logits, spk_ids) / batch_size\n\n        # make weighted mask and apply it\n        if self.use_weighted_masking:\n            out_masks = make_non_pad_mask(olens).unsqueeze(-1)\n            out_weights = out_masks.cast(dtype=paddle.float32) / out_masks.cast(\n                dtype=paddle.float32).sum(\n                    axis=1, keepdim=True)\n            out_weights /= ys.shape[0] * ys.shape[2]\n            duration_masks = make_non_pad_mask(ilens)\n            duration_weights = (duration_masks.cast(dtype=paddle.float32) /\n                                duration_masks.cast(dtype=paddle.float32).sum(\n                                    axis=1, keepdim=True))\n            duration_weights /= ds.shape[0]\n\n            # apply weight\n\n            l1_loss = l1_loss.multiply(out_weights)\n            l1_loss = l1_loss.masked_select(\n                out_masks.broadcast_to(l1_loss.shape)).sum()\n            duration_loss = (duration_loss.multiply(duration_weights)\n                             .masked_select(duration_masks).sum())\n            pitch_masks = duration_masks.unsqueeze(-1)\n            pitch_weights = duration_weights.unsqueeze(-1)\n            pitch_loss = pitch_loss.multiply(pitch_weights)\n            pitch_loss = pitch_loss.masked_select(\n                pitch_masks.broadcast_to(pitch_loss.shape)).sum()\n            energy_loss = energy_loss.multiply(pitch_weights)\n            energy_loss = energy_loss.masked_select(\n                pitch_masks.broadcast_to(energy_loss.shape)).sum()\n\n        return l1_loss, duration_loss, pitch_loss, energy_loss, speaker_loss\n"
  },
  {
    "path": "paddlespeech/t2s/models/fastspeech2/fastspeech2_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\n\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.models.fastspeech2 import FastSpeech2Loss\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass FastSpeech2Updater(StandardUpdater):\n    def __init__(\n            self,\n            model: Layer,\n            optimizer: Optimizer,\n            dataloader: DataLoader,\n            init_state=None,\n            use_masking: bool=False,\n            spk_loss_scale: float=0.02,\n            use_weighted_masking: bool=False,\n            output_dir: Path=None,\n            enable_spk_cls: bool=False, ):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n\n        self.criterion = FastSpeech2Loss(\n            use_masking=use_masking,\n            use_weighted_masking=use_weighted_masking, )\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n        self.spk_loss_scale = spk_loss_scale\n        self.enable_spk_cls = enable_spk_cls\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # spk_id!=None in multiple spk fastspeech2 \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        # No explicit speaker identifier labels are used during voice cloning training.\n        if spk_emb is not None:\n            spk_id = None\n\n        if type(\n                self.model\n        ) == DataParallel and self.model._layers.spk_num and self.model._layers.enable_speaker_classifier:\n            with self.model.no_sync():\n                before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n                    text=batch[\"text\"],\n                    text_lengths=batch[\"text_lengths\"],\n                    speech=batch[\"speech\"],\n                    speech_lengths=batch[\"speech_lengths\"],\n                    durations=batch[\"durations\"],\n                    pitch=batch[\"pitch\"],\n                    energy=batch[\"energy\"],\n                    spk_id=spk_id,\n                    spk_emb=spk_emb)\n        else:\n            before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                speech=batch[\"speech\"],\n                speech_lengths=batch[\"speech_lengths\"],\n                durations=batch[\"durations\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                spk_id=spk_id,\n                spk_emb=spk_emb)\n\n        l1_loss, duration_loss, pitch_loss, energy_loss, speaker_loss = self.criterion(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            d_outs=d_outs,\n            p_outs=p_outs,\n            e_outs=e_outs,\n            ys=ys,\n            ds=batch[\"durations\"],\n            ps=batch[\"pitch\"],\n            es=batch[\"energy\"],\n            ilens=batch[\"text_lengths\"],\n            olens=olens,\n            spk_logits=spk_logits,\n            spk_ids=spk_id, )\n\n        scaled_speaker_loss = self.spk_loss_scale * speaker_loss\n        loss = l1_loss + duration_loss + pitch_loss + energy_loss + scaled_speaker_loss\n\n        optimizer = self.optimizer\n        optimizer.clear_grad()\n        loss.backward()\n        optimizer.step()\n\n        report(\"train/loss\", float(loss))\n        report(\"train/l1_loss\", float(l1_loss))\n        report(\"train/duration_loss\", float(duration_loss))\n        report(\"train/pitch_loss\", float(pitch_loss))\n        report(\"train/energy_loss\", float(energy_loss))\n        if self.enable_spk_cls:\n            report(\"train/speaker_loss\", float(speaker_loss))\n            report(\"train/scaled_speaker_loss\", float(scaled_speaker_loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"duration_loss\"] = float(duration_loss)\n        losses_dict[\"pitch_loss\"] = float(pitch_loss)\n        losses_dict[\"energy_loss\"] = float(energy_loss)\n        losses_dict[\"energy_loss\"] = float(energy_loss)\n        if self.enable_spk_cls:\n            losses_dict[\"speaker_loss\"] = float(speaker_loss)\n            losses_dict[\"scaled_speaker_loss\"] = float(scaled_speaker_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass FastSpeech2Evaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 dataloader: DataLoader,\n                 use_masking: bool=False,\n                 use_weighted_masking: bool=False,\n                 spk_loss_scale: float=0.02,\n                 output_dir: Path=None,\n                 enable_spk_cls: bool=False):\n        super().__init__(model, dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n        self.spk_loss_scale = spk_loss_scale\n        self.enable_spk_cls = enable_spk_cls\n\n        self.criterion = FastSpeech2Loss(\n            use_masking=use_masking, use_weighted_masking=use_weighted_masking)\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        # spk_id!=None in multiple spk fastspeech2 \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        if spk_emb is not None:\n            spk_id = None\n\n        if type(\n                self.model\n        ) == DataParallel and self.model._layers.spk_num and self.model._layers.enable_speaker_classifier:\n            with self.model.no_sync():\n                before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n                    text=batch[\"text\"],\n                    text_lengths=batch[\"text_lengths\"],\n                    speech=batch[\"speech\"],\n                    speech_lengths=batch[\"speech_lengths\"],\n                    durations=batch[\"durations\"],\n                    pitch=batch[\"pitch\"],\n                    energy=batch[\"energy\"],\n                    spk_id=spk_id,\n                    spk_emb=spk_emb)\n        else:\n            before_outs, after_outs, d_outs, p_outs, e_outs, ys, olens, spk_logits = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                speech=batch[\"speech\"],\n                speech_lengths=batch[\"speech_lengths\"],\n                durations=batch[\"durations\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                spk_id=spk_id,\n                spk_emb=spk_emb)\n\n        l1_loss, duration_loss, pitch_loss, energy_loss, speaker_loss = self.criterion(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            d_outs=d_outs,\n            p_outs=p_outs,\n            e_outs=e_outs,\n            ys=ys,\n            ds=batch[\"durations\"],\n            ps=batch[\"pitch\"],\n            es=batch[\"energy\"],\n            ilens=batch[\"text_lengths\"],\n            olens=olens,\n            spk_logits=spk_logits,\n            spk_ids=spk_id, )\n\n        scaled_speaker_loss = self.spk_loss_scale * speaker_loss\n        loss = l1_loss + duration_loss + pitch_loss + energy_loss + scaled_speaker_loss\n\n        report(\"eval/loss\", float(loss))\n        report(\"eval/l1_loss\", float(l1_loss))\n        report(\"eval/duration_loss\", float(duration_loss))\n        report(\"eval/pitch_loss\", float(pitch_loss))\n        report(\"eval/energy_loss\", float(energy_loss))\n        if self.enable_spk_cls:\n            report(\"train/speaker_loss\", float(speaker_loss))\n            report(\"train/scaled_speaker_loss\", float(scaled_speaker_loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"duration_loss\"] = float(duration_loss)\n        losses_dict[\"pitch_loss\"] = float(pitch_loss)\n        losses_dict[\"energy_loss\"] = float(energy_loss)\n        if self.enable_spk_cls:\n            losses_dict[\"speaker_loss\"] = float(speaker_loss)\n            losses_dict[\"scaled_speaker_loss\"] = float(scaled_speaker_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/hifigan/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .hifigan import *\nfrom .hifigan_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/hifigan/hifigan.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# This code is based on https://github.com/jik876/hifi-gan.\nimport copy\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.residual_block import HiFiGANResidualBlock as ResidualBlock\n\n\nclass HiFiGANGenerator(nn.Layer):\n    \"\"\"HiFiGAN generator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=80,\n            out_channels: int=1,\n            channels: int=512,\n            global_channels: int=-1,\n            kernel_size: int=7,\n            upsample_scales: List[int]=(5, 5, 4, 3),\n            upsample_kernel_sizes: List[int]=(10, 10, 8, 6),\n            resblock_kernel_sizes: List[int]=(3, 7, 11),\n            resblock_dilations: List[List[int]]=[(1, 3, 5), (1, 3, 5),\n                                                 (1, 3, 5)],\n            use_additional_convs: bool=True,\n            bias: bool=True,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.1},\n            use_weight_norm: bool=True,\n            init_type: str=\"xavier_uniform\",\n            use_istft: bool=False,\n            istft_layer_id: int=2,\n            n_fft: int=2048,\n            win_length: int=1200, ):\n        \"\"\"Initialize HiFiGANGenerator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels.\n            channels (int): \n                Number of hidden representation channels.\n            global_channels (int): \n                Number of global conditioning channels.\n            kernel_size (int): \n                Kernel size of initial and final conv layer.\n            upsample_scales (list): \n                List of upsampling scales.\n            upsample_kernel_sizes (list): \n                List of kernel sizes for upsampling layers.\n            resblock_kernel_sizes (list): \n                List of kernel sizes for residual blocks.\n            resblock_dilations (list): \n                List of dilation list for residual blocks.\n            use_additional_convs (bool): \n                Whether to use additional conv layers in residual blocks.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n            use_weight_norm (bool): \n                Whether to use weight norm.\n                If set to true, it will be applied to all of the conv layers.\n            use_istft (bool):\n                If set to true, it will be a iSTFTNet based on hifigan.\n            istft_layer_id (int):\n                Use istft after istft_layer_id layers of upsample layer if use_istft=True\n            n_fft (int):\n                Number of fft points in feature extraction\n            win_length (int):\n                Window length in feature extraction\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # check hyperparameters are valid\n        assert kernel_size % 2 == 1, \"Kernel size must be odd number.\"\n        assert len(upsample_scales) == len(upsample_kernel_sizes)\n        assert len(resblock_dilations) == len(resblock_kernel_sizes)\n        assert len(upsample_scales) >= istft_layer_id if use_istft else True\n\n        # define modules\n        self.num_upsamples = len(\n            upsample_kernel_sizes) if not use_istft else istft_layer_id\n        self.num_blocks = len(resblock_kernel_sizes)\n        self.input_conv = nn.Conv1D(\n            in_channels,\n            channels,\n            kernel_size,\n            1,\n            padding=(kernel_size - 1) // 2, )\n        self.upsamples = nn.LayerList()\n        self.blocks = nn.LayerList()\n        for i in range(self.num_upsamples):\n            assert upsample_kernel_sizes[i] == 2 * upsample_scales[i]\n            self.upsamples.append(\n                nn.Sequential(\n                    get_activation(nonlinear_activation, **\n                                   nonlinear_activation_params),\n                    nn.Conv1DTranspose(\n                        channels // (2**i),\n                        channels // (2**(i + 1)),\n                        upsample_kernel_sizes[i],\n                        upsample_scales[i],\n                        padding=upsample_scales[i] // 2 + upsample_scales[i] %\n                        2,\n                        output_padding=upsample_scales[i] % 2, ), ))\n            for j in range(len(resblock_kernel_sizes)):\n                self.blocks.append(\n                    ResidualBlock(\n                        kernel_size=resblock_kernel_sizes[j],\n                        channels=channels // (2**(i + 1)),\n                        dilations=resblock_dilations[j],\n                        bias=bias,\n                        use_additional_convs=use_additional_convs,\n                        nonlinear_activation=nonlinear_activation,\n                        nonlinear_activation_params=nonlinear_activation_params,\n                    ))\n        self.use_istft = use_istft\n        if self.use_istft:\n            self.istft_hop_size = 1\n            for j in range(istft_layer_id, len(upsample_scales)):\n                self.istft_hop_size *= upsample_scales[j]\n            s = 1\n            for j in range(istft_layer_id):\n                s *= upsample_scales[j]\n            self.istft_n_fft = int(n_fft / s) if (\n                n_fft / s) % 2 == 0 else int((n_fft / s + 2) - n_fft / s % 2)\n            self.istft_win_length = int(win_length / s) if (\n                win_length /\n                s) % 2 == 0 else int((win_length / s + 2) - win_length / s % 2)\n            self.reflection_pad = nn.Pad1D(padding=[1, 0], mode='reflect')\n            self.output_conv = nn.Conv1D(\n                channels // (2**(i + 1)),\n                (self.istft_n_fft // 2 + 1) * 2,\n                kernel_size,\n                1,\n                padding=(kernel_size - 1) // 2, )\n        else:\n            self.output_conv = nn.Sequential(\n                nn.LeakyReLU(),\n                nn.Conv1D(\n                    channels // (2**(i + 1)),\n                    out_channels,\n                    kernel_size,\n                    1,\n                    padding=(kernel_size - 1) // 2, ),\n                nn.Tanh(), )\n\n        if global_channels > 0:\n            self.global_conv = nn.Conv1D(global_channels, channels, 1)\n\n        nn.initializer.set_global_initializer(None)\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # reset parameters\n        self.reset_parameters()\n\n    def forward(self, c, g: Optional[paddle.Tensor]=None):\n        \"\"\"Calculate forward propagation.\n        \n        Args:\n            c (Tensor): Input tensor (B, in_channels, T).\n            g (Optional[Tensor]): Global conditioning tensor (B, global_channels, 1).\n        Returns:\n            Tensor: Output tensor (B, out_channels, T).\n        \"\"\"\n        c = self.input_conv(c)\n        if g is not None:\n            c = c + self.global_conv(g)\n        for i in range(self.num_upsamples):\n            c = self.upsamples[i](c)\n            # initialize\n            cs = 0.0\n            for j in range(self.num_blocks):\n                cs += self.blocks[i * self.num_blocks + j](c)\n            c = cs / self.num_blocks\n\n        if self.use_istft:\n            c = F.leaky_relu(c)\n            c = self.reflection_pad(c)\n            c = self.output_conv(c)\n            \"\"\"\n            Input of Exp operator, an N-D Tensor, with data type float32, float64 or float16.\n            https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/exp_en.html\n            Use Euler's formula to implement spec*paddle.exp(1j*phase)\n            \"\"\"\n            spec = paddle.exp(c[:, :self.istft_n_fft // 2 + 1, :])\n            phase = paddle.sin(c[:, self.istft_n_fft // 2 + 1:, :])\n\n            c = paddle.complex(spec * (paddle.cos(phase)),\n                               spec * (paddle.sin(phase)))\n            c = paddle.signal.istft(\n                c,\n                n_fft=self.istft_n_fft,\n                hop_length=self.istft_hop_size,\n                win_length=self.istft_win_length)\n            c = c.unsqueeze(1)\n        else:\n            c = self.output_conv(c)\n\n        return c\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\n        This initialization follows official implementation manner.\n        https://github.com/jik876/hifi-gan/blob/master/models.py\n        \"\"\"\n        # 定义参数为float的正态分布。\n        dist = paddle.distribution.Normal(loc=0.0, scale=0.01)\n\n        def _reset_parameters(m):\n            if isinstance(m, nn.Conv1D) or isinstance(m, nn.Conv1DTranspose):\n                w = dist.sample(m.weight.shape)\n                m.weight.set_value(w)\n\n        self.apply(_reset_parameters)\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def inference(self, c, g: Optional[paddle.Tensor]=None):\n        \"\"\"Perform inference.\n        Args:\n            c (Tensor): \n                Input tensor (T, in_channels).\n            g (Optional[Tensor]): \n                Global conditioning tensor (global_channels, 1).\n        Returns:\n            Tensor:\n                Output tensor (T ** prod(upsample_scales), out_channels).\n        \"\"\"\n        if g is not None:\n            g = g.unsqueeze(0)\n        c = self.forward(c.transpose([1, 0]).unsqueeze(0), g=g)\n        return c.squeeze(0).transpose([1, 0])\n\n\nclass HiFiGANPeriodDiscriminator(nn.Layer):\n    \"\"\"HiFiGAN period discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            period: int=3,\n            kernel_sizes: List[int]=[5, 3],\n            channels: int=32,\n            downsample_scales: List[int]=[3, 3, 3, 3, 1],\n            max_downsample_channels: int=1024,\n            bias: bool=True,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.1},\n            use_weight_norm: bool=True,\n            use_spectral_norm: bool=False,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initialize HiFiGANPeriodDiscriminator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels.\n            period (int): \n                Period.\n            kernel_sizes (list): \n                Kernel sizes of initial conv layers and the final conv layer.\n            channels (int): \n                Number of initial channels.\n            downsample_scales (list): \n                List of downsampling scales.\n            max_downsample_channels (int): \n                Number of maximum downsampling channels.\n            use_additional_convs (bool): \n                Whether to use additional conv layers in residual blocks.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n            use_weight_norm (bool): \n                Whether to use weight norm.\n                If set to true, it will be applied to all of the conv layers.\n            use_spectral_norm (bool): \n                Whether to use spectral norm.\n                If set to true, it will be applied to all of the conv layers.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        assert len(kernel_sizes) == 2\n        assert kernel_sizes[0] % 2 == 1, \"Kernel size must be odd number.\"\n        assert kernel_sizes[1] % 2 == 1, \"Kernel size must be odd number.\"\n\n        self.period = period\n        self.convs = nn.LayerList()\n        in_chs = in_channels\n        out_chs = channels\n        for downsample_scale in downsample_scales:\n            self.convs.append(\n                nn.Sequential(\n                    nn.Conv2D(\n                        in_chs,\n                        out_chs,\n                        (kernel_sizes[0], 1),\n                        (downsample_scale, 1),\n                        padding=((kernel_sizes[0] - 1) // 2, 0), ),\n                    get_activation(nonlinear_activation, **\n                                   nonlinear_activation_params), ))\n            in_chs = out_chs\n            # NOTE: Use downsample_scale + 1?\n            out_chs = min(out_chs * 4, max_downsample_channels)\n        self.output_conv = nn.Conv2D(\n            out_chs,\n            out_channels,\n            (kernel_sizes[1] - 1, 1),\n            1,\n            padding=((kernel_sizes[1] - 1) // 2, 0), )\n\n        if use_weight_norm and use_spectral_norm:\n            raise ValueError(\"Either use use_weight_norm or use_spectral_norm.\")\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # apply spectral norm\n        if use_spectral_norm:\n            self.apply_spectral_norm()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            c (Tensor): \n                Input tensor (B, in_channels, T).\n        Returns:\n            list: List of each layer's tensors.\n        \"\"\"\n        # transform 1d to 2d -> (B, C, T/P, P)\n        b, c, t = paddle.shape(x)\n        if t % self.period != 0:\n            n_pad = self.period - (t % self.period)\n            x = F.pad(x, (0, n_pad), \"reflect\", data_format=\"NCL\")\n            t += n_pad\n        x = x.reshape([b, c, t // self.period, self.period])\n\n        # forward conv\n        outs = []\n        for layer in self.convs:\n            x = layer(x)\n            outs += [x]\n        x = self.output_conv(x)\n        x = paddle.flatten(x, 1, -1)\n        outs += [x]\n\n        return outs\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def apply_spectral_norm(self):\n        \"\"\"Apply spectral normalization module from all of the layers.\"\"\"\n\n        def _apply_spectral_norm(m):\n            if isinstance(m, nn.Conv2D):\n                nn.utils.spectral_norm(m)\n\n        self.apply(_apply_spectral_norm)\n\n\nclass HiFiGANMultiPeriodDiscriminator(nn.Layer):\n    \"\"\"HiFiGAN multi-period discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            periods: List[int]=[2, 3, 5, 7, 11],\n            discriminator_params: Dict[str, Any]={\n                \"in_channels\": 1,\n                \"out_channels\": 1,\n                \"kernel_sizes\": [5, 3],\n                \"channels\": 32,\n                \"downsample_scales\": [3, 3, 3, 3, 1],\n                \"max_downsample_channels\": 1024,\n                \"bias\": True,\n                \"nonlinear_activation\": \"leakyrelu\",\n                \"nonlinear_activation_params\": {\n                    \"negative_slope\": 0.1\n                },\n                \"use_weight_norm\": True,\n                \"use_spectral_norm\": False,\n            },\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initialize HiFiGANMultiPeriodDiscriminator module.\n\n        Args:\n            periods (list): \n                List of periods.\n            discriminator_params (dict): \n                Parameters for hifi-gan period discriminator module.\n                The period parameter will be overwritten.\n        \"\"\"\n        super().__init__()\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.discriminators = nn.LayerList()\n        for period in periods:\n            params = copy.deepcopy(discriminator_params)\n            params[\"period\"] = period\n            self.discriminators.append(HiFiGANPeriodDiscriminator(**params))\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Input noise signal (B, 1, T).\n        Returns:\n            List: List of list of each discriminator outputs, which consists of each layer output tensors.\n        \"\"\"\n        outs = []\n        for f in self.discriminators:\n            outs += [f(x)]\n\n        return outs\n\n\nclass HiFiGANScaleDiscriminator(nn.Layer):\n    \"\"\"HiFi-GAN scale discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_sizes: List[int]=[15, 41, 5, 3],\n            channels: int=128,\n            max_downsample_channels: int=1024,\n            max_groups: int=16,\n            bias: bool=True,\n            downsample_scales: List[int]=[2, 2, 4, 4, 1],\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.1},\n            use_weight_norm: bool=True,\n            use_spectral_norm: bool=False,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize HiFiGAN scale discriminator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels.\n            kernel_sizes (list): \n                List of four kernel sizes. The first will be used for the first conv layer,\n                and the second is for downsampling part, and the remaining two are for output layers.\n            channels (int): \n                Initial number of channels for conv layer.\n            max_downsample_channels (int): \n                Maximum number of channels for downsampling layers.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            downsample_scales (list): \n                List of downsampling scales.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n            use_weight_norm (bool): Whether to use weight norm.\n                If set to true, it will be applied to all of the conv layers.\n            use_spectral_norm (bool): Whether to use spectral norm.\n                If set to true, it will be applied to all of the conv layers.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.layers = nn.LayerList()\n\n        # check kernel size is valid\n        assert len(kernel_sizes) == 4\n        for ks in kernel_sizes:\n            assert ks % 2 == 1\n\n        # add first layer\n        self.layers.append(\n            nn.Sequential(\n                nn.Conv1D(\n                    in_channels,\n                    channels,\n                    # NOTE: Use always the same kernel size\n                    kernel_sizes[0],\n                    bias_attr=bias,\n                    padding=(kernel_sizes[0] - 1) // 2, ),\n                get_activation(nonlinear_activation, **\n                               nonlinear_activation_params), ))\n\n        # add downsample layers\n        in_chs = channels\n        out_chs = channels\n        # NOTE(kan-bayashi): Remove hard coding?\n        groups = 4\n        for downsample_scale in downsample_scales:\n            self.layers.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        in_chs,\n                        out_chs,\n                        kernel_size=kernel_sizes[1],\n                        stride=downsample_scale,\n                        padding=(kernel_sizes[1] - 1) // 2,\n                        groups=groups,\n                        bias_attr=bias, ),\n                    get_activation(nonlinear_activation, **\n                                   nonlinear_activation_params), ))\n            in_chs = out_chs\n            # NOTE: Remove hard coding?\n            out_chs = min(in_chs * 2, max_downsample_channels)\n            # NOTE: Remove hard coding?\n            groups = min(groups * 4, max_groups)\n\n        # add final layers\n        out_chs = min(in_chs * 2, max_downsample_channels)\n        self.layers.append(\n            nn.Sequential(\n                nn.Conv1D(\n                    in_chs,\n                    out_chs,\n                    kernel_size=kernel_sizes[2],\n                    stride=1,\n                    padding=(kernel_sizes[2] - 1) // 2,\n                    bias_attr=bias, ),\n                get_activation(nonlinear_activation, **\n                               nonlinear_activation_params), ))\n        self.layers.append(\n            nn.Conv1D(\n                out_chs,\n                out_channels,\n                kernel_size=kernel_sizes[3],\n                stride=1,\n                padding=(kernel_sizes[3] - 1) // 2,\n                bias_attr=bias, ), )\n\n        if use_weight_norm and use_spectral_norm:\n            raise ValueError(\"Either use use_weight_norm or use_spectral_norm.\")\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # apply spectral norm\n        if use_spectral_norm:\n            self.apply_spectral_norm()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): Input noise signal (B, 1, T).\n        Returns:\n            List: List of output tensors of each layer.\n        \"\"\"\n        outs = []\n        for f in self.layers:\n            x = f(x)\n            outs += [x]\n\n        return outs\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def apply_spectral_norm(self):\n        \"\"\"Apply spectral normalization module from all of the layers.\"\"\"\n\n        def _apply_spectral_norm(m):\n            if isinstance(m, nn.Conv2D):\n                nn.utils.spectral_norm(m)\n\n        self.apply(_apply_spectral_norm)\n\n\nclass HiFiGANMultiScaleDiscriminator(nn.Layer):\n    \"\"\"HiFi-GAN multi-scale discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            scales: int=3,\n            downsample_pooling: str=\"AvgPool1D\",\n            # follow the official implementation setting\n            downsample_pooling_params: Dict[str, Any]={\n                \"kernel_size\": 4,\n                \"stride\": 2,\n                \"padding\": 2,\n            },\n            discriminator_params: Dict[str, Any]={\n                \"in_channels\": 1,\n                \"out_channels\": 1,\n                \"kernel_sizes\": [15, 41, 5, 3],\n                \"channels\": 128,\n                \"max_downsample_channels\": 1024,\n                \"max_groups\": 16,\n                \"bias\": True,\n                \"downsample_scales\": [2, 2, 4, 4, 1],\n                \"nonlinear_activation\": \"leakyrelu\",\n                \"nonlinear_activation_params\": {\n                    \"negative_slope\": 0.1\n                },\n            },\n            follow_official_norm: bool=False,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize HiFiGAN multi-scale discriminator module.\n   \n        Args:\n            scales (int): Number of multi-scales.\n            downsample_pooling (str): Pooling module name for downsampling of the inputs.\n            downsample_pooling_params (dict): Parameters for the above pooling module.\n            discriminator_params (dict): Parameters for hifi-gan scale discriminator module.\n            follow_official_norm (bool): Whether to follow the norm setting of the official\n                implementaion. The first discriminator uses spectral norm and the other discriminators use weight norm.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.discriminators = nn.LayerList()\n\n        # add discriminators\n        for i in range(scales):\n            params = copy.deepcopy(discriminator_params)\n            if follow_official_norm:\n                if i == 0:\n                    params[\"use_weight_norm\"] = False\n                    params[\"use_spectral_norm\"] = True\n                else:\n                    params[\"use_weight_norm\"] = True\n                    params[\"use_spectral_norm\"] = False\n            self.discriminators.append(HiFiGANScaleDiscriminator(**params))\n        self.pooling = getattr(nn, downsample_pooling)(\n            **downsample_pooling_params)\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Input noise signal (B, 1, T).\n        Returns:\n            List: List of list of each discriminator outputs, which consists of each layer output tensors.\n        \"\"\"\n        outs = []\n        for f in self.discriminators:\n            outs += [f(x)]\n            x = self.pooling(x)\n\n        return outs\n\n\nclass HiFiGANMultiScaleMultiPeriodDiscriminator(nn.Layer):\n    \"\"\"HiFi-GAN multi-scale + multi-period discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            # Multi-scale discriminator related\n            scales: int=3,\n            scale_downsample_pooling: str=\"AvgPool1D\",\n            scale_downsample_pooling_params: Dict[str, Any]={\n                \"kernel_size\": 4,\n                \"stride\": 2,\n                \"padding\": 2,\n            },\n            scale_discriminator_params: Dict[str, Any]={\n                \"in_channels\": 1,\n                \"out_channels\": 1,\n                \"kernel_sizes\": [15, 41, 5, 3],\n                \"channels\": 128,\n                \"max_downsample_channels\": 1024,\n                \"max_groups\": 16,\n                \"bias\": True,\n                \"downsample_scales\": [2, 2, 4, 4, 1],\n                \"nonlinear_activation\": \"leakyrelu\",\n                \"nonlinear_activation_params\": {\n                    \"negative_slope\": 0.1\n                },\n            },\n            follow_official_norm: bool=True,\n            # Multi-period discriminator related\n            periods: List[int]=[2, 3, 5, 7, 11],\n            period_discriminator_params: Dict[str, Any]={\n                \"in_channels\": 1,\n                \"out_channels\": 1,\n                \"kernel_sizes\": [5, 3],\n                \"channels\": 32,\n                \"downsample_scales\": [3, 3, 3, 3, 1],\n                \"max_downsample_channels\": 1024,\n                \"bias\": True,\n                \"nonlinear_activation\": \"leakyrelu\",\n                \"nonlinear_activation_params\": {\n                    \"negative_slope\": 0.1\n                },\n                \"use_weight_norm\": True,\n                \"use_spectral_norm\": False,\n            },\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize HiFiGAN multi-scale + multi-period discriminator module.\n\n        Args:\n            scales (int): \n                Number of multi-scales.\n            scale_downsample_pooling (str): \n                Pooling module name for downsampling of the inputs.\n            scale_downsample_pooling_params (dict): \n                Parameters for the above pooling module.\n            scale_discriminator_params (dict): \n                Parameters for hifi-gan scale discriminator module.\n            follow_official_norm （bool): \n                Whether to follow the norm setting of the official implementaion. \n                The first discriminator uses spectral norm and the other discriminators use weight norm.\n            periods (list): \n                List of periods.\n            period_discriminator_params (dict): \n                Parameters for hifi-gan period discriminator module.\n                The period parameter will be overwritten.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.msd = HiFiGANMultiScaleDiscriminator(\n            scales=scales,\n            downsample_pooling=scale_downsample_pooling,\n            downsample_pooling_params=scale_downsample_pooling_params,\n            discriminator_params=scale_discriminator_params,\n            follow_official_norm=follow_official_norm, )\n        self.mpd = HiFiGANMultiPeriodDiscriminator(\n            periods=periods,\n            discriminator_params=period_discriminator_params, )\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Input noise signal (B, 1, T).\n        Returns:\n            List:\n                List of list of each discriminator outputs,\n                which consists of each layer output tensors.\n                Multi scale and multi period ones are concatenated.\n        \"\"\"\n        msd_outs = self.msd(x)\n        mpd_outs = self.mpd(x)\n        return msd_outs + mpd_outs\n\n\nclass HiFiGANInference(nn.Layer):\n    def __init__(self, normalizer, hifigan_generator):\n        super().__init__()\n        self.normalizer = normalizer\n        self.hifigan_generator = hifigan_generator\n\n    def forward(self, logmel):\n        normalized_mel = self.normalizer(logmel)\n        wav = self.hifigan_generator.inference(normalized_mel)\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/hifigan/hifigan_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass HiFiGANUpdater(StandardUpdater):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 lambda_feat_match: float=1.0,\n                 output_dir=None):\n        self.models = models\n        self.generator: Layer = models['generator']\n        self.discriminator: Layer = models['discriminator']\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_mel = criterions['mel']\n\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n        self.lambda_feat_match = lambda_feat_match\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        wav, mel = batch\n\n        # Generator\n        if self.state.iteration > self.generator_train_start_steps:\n            # (B, out_channels, T ** prod(upsample_scales)\n            wav_ = self.generator(mel)\n\n            # initialize\n            gen_loss = 0.0\n            aux_loss = 0.0\n\n            # mel spectrogram loss\n            mel_loss = self.criterion_mel(wav_, wav)\n            aux_loss += mel_loss\n            report(\"train/mel_loss\", float(mel_loss))\n            losses_dict[\"mel_loss\"] = float(mel_loss)\n\n            gen_loss += aux_loss * self.lambda_aux\n\n            # adversarial loss\n            if self.state.iteration > self.discriminator_train_start_steps:\n                p_ = self.discriminator(wav_)\n                adv_loss = self.criterion_gen_adv(p_)\n                report(\"train/adversarial_loss\", float(adv_loss))\n                losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n                # feature matching loss\n                # no need to track gradients\n                with paddle.no_grad():\n                    p = self.discriminator(wav)\n                fm_loss = self.criterion_feat_match(p_, p)\n                report(\"train/feature_matching_loss\", float(fm_loss))\n                losses_dict[\"feature_matching_loss\"] = float(fm_loss)\n\n                adv_loss += self.lambda_feat_match * fm_loss\n\n                gen_loss += self.lambda_adv * adv_loss\n\n            report(\"train/generator_loss\", float(gen_loss))\n            losses_dict[\"generator_loss\"] = float(gen_loss)\n\n            self.optimizer_g.clear_grad()\n            gen_loss.backward()\n\n            self.optimizer_g.step()\n            self.scheduler_g.step()\n\n        # Disctiminator\n        if self.state.iteration > self.discriminator_train_start_steps:\n            # re-compute wav_ which leads better quality\n            with paddle.no_grad():\n                wav_ = self.generator(mel)\n\n            p = self.discriminator(wav)\n            p_ = self.discriminator(wav_.detach())\n            real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n            dis_loss = real_loss + fake_loss\n            report(\"train/real_loss\", float(real_loss))\n            report(\"train/fake_loss\", float(fake_loss))\n            report(\"train/discriminator_loss\", float(dis_loss))\n            losses_dict[\"real_loss\"] = float(real_loss)\n            losses_dict[\"fake_loss\"] = float(fake_loss)\n            losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n            self.optimizer_d.clear_grad()\n            dis_loss.backward()\n\n            self.optimizer_d.step()\n            self.scheduler_d.step()\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass HiFiGANEvaluator(StandardEvaluator):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 lambda_feat_match: float=1.0,\n                 output_dir=None):\n        self.models = models\n        self.generator = models['generator']\n        self.discriminator = models['discriminator']\n\n        self.criterions = criterions\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_mel = criterions['mel']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n        self.lambda_feat_match = lambda_feat_match\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        wav, mel = batch\n\n        # Generator\n        # (B, out_channels, T ** prod(upsample_scales)\n        wav_ = self.generator(mel)\n\n        # initialize\n        gen_loss = 0.0\n        aux_loss = 0.0\n\n        ## Adversarial loss\n        p_ = self.discriminator(wav_)\n        adv_loss = self.criterion_gen_adv(p_)\n        report(\"eval/adversarial_loss\", float(adv_loss))\n        losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n        # feature matching loss\n        p = self.discriminator(wav)\n        fm_loss = self.criterion_feat_match(p_, p)\n        report(\"eval/feature_matching_loss\", float(fm_loss))\n        losses_dict[\"feature_matching_loss\"] = float(fm_loss)\n        adv_loss += self.lambda_feat_match * fm_loss\n\n        gen_loss += self.lambda_adv * adv_loss\n\n        # mel spectrogram loss\n        mel_loss = self.criterion_mel(wav_, wav)\n        aux_loss += mel_loss\n        report(\"eval/mel_loss\", float(mel_loss))\n        losses_dict[\"mel_loss\"] = float(mel_loss)\n\n        gen_loss += aux_loss * self.lambda_aux\n\n        report(\"eval/generator_loss\", float(gen_loss))\n        losses_dict[\"generator_loss\"] = float(gen_loss)\n\n        # Disctiminator\n        p = self.discriminator(wav)\n        real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n        dis_loss = real_loss + fake_loss\n        report(\"eval/real_loss\", float(real_loss))\n        report(\"eval/fake_loss\", float(fake_loss))\n        report(\"eval/discriminator_loss\", float(dis_loss))\n\n        losses_dict[\"real_loss\"] = float(real_loss)\n        losses_dict[\"fake_loss\"] = float(fake_loss)\n        losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .jets import *\nfrom .jets_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/alignments.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in JETS.\n\nThis code is based on https://github.com/imdanboy/jets.\n\n\"\"\"\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom numba import jit\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\n\nclass AlignmentModule(nn.Layer):\n    \"\"\"Alignment Learning Framework proposed for parallel TTS models in:\n    https://arxiv.org/abs/2108.10447\n    \"\"\"\n\n    def __init__(self, adim, odim):\n        super().__init__()\n        self.t_conv1 = nn.Conv1D(adim, adim, kernel_size=3, padding=1)\n        self.t_conv2 = nn.Conv1D(adim, adim, kernel_size=1, padding=0)\n\n        self.f_conv1 = nn.Conv1D(odim, adim, kernel_size=3, padding=1)\n        self.f_conv2 = nn.Conv1D(adim, adim, kernel_size=3, padding=1)\n        self.f_conv3 = nn.Conv1D(adim, adim, kernel_size=1, padding=0)\n\n    def forward(self, text, feats, x_masks=None):\n        \"\"\"\n        Args:\n            text (Tensor): Batched text embedding (B, T_text, adim)\n            feats (Tensor): Batched acoustic feature (B, T_feats, odim)\n            x_masks (Tensor): Mask tensor (B, T_text)\n\n        Returns:\n            Tensor: log probability of attention matrix (B, T_feats, T_text)\n        \"\"\"\n\n        text = text.transpose((0, 2, 1))\n        text = F.relu(self.t_conv1(text))\n        text = self.t_conv2(text)\n        text = text.transpose((0, 2, 1))\n\n        feats = feats.transpose((0, 2, 1))\n        feats = F.relu(self.f_conv1(feats))\n        feats = F.relu(self.f_conv2(feats))\n        feats = self.f_conv3(feats)\n        feats = feats.transpose((0, 2, 1))\n\n        dist = feats.unsqueeze(2) - text.unsqueeze(1)\n        dist = paddle.linalg.norm(dist, p=2, axis=3)\n        score = -dist\n\n        if x_masks is not None:\n            x_masks = x_masks.unsqueeze(-2)\n            score = masked_fill(score, x_masks, -np.inf)\n        log_p_attn = F.log_softmax(score, axis=-1)\n        return log_p_attn, score\n\n\n@jit(nopython=True)\ndef _monotonic_alignment_search(log_p_attn):\n    # https://arxiv.org/abs/2005.11129\n    T_mel = log_p_attn.shape[0]\n    T_inp = log_p_attn.shape[1]\n    Q = np.full((T_inp, T_mel), fill_value=-np.inf)\n\n    log_prob = log_p_attn.transpose(1, 0)  # -> (T_inp,T_mel)\n    # 1.  Q <- init first row for all j\n    for j in range(T_mel):\n        Q[0, j] = log_prob[0, :j + 1].sum()\n\n    # 2. \n    for j in range(1, T_mel):\n        for i in range(1, min(j + 1, T_inp)):\n            Q[i, j] = max(Q[i - 1, j - 1], Q[i, j - 1]) + log_prob[i, j]\n\n    # 3.\n    A = np.full((T_mel, ), fill_value=T_inp - 1)\n    for j in range(T_mel - 2, -1, -1):  # T_mel-2, ..., 0\n        # 'i' in {A[j+1]-1, A[j+1]}\n        i_a = A[j + 1] - 1\n        i_b = A[j + 1]\n        if i_b == 0:\n            argmax_i = 0\n        elif Q[i_a, j] >= Q[i_b, j]:\n            argmax_i = i_a\n        else:\n            argmax_i = i_b\n        A[j] = argmax_i\n    return A\n\n\ndef viterbi_decode(log_p_attn, text_lengths, feats_lengths):\n    \"\"\"\n    Args:\n        log_p_attn (Tensor): \n            Batched log probability of attention matrix (B, T_feats, T_text)\n        text_lengths (Tensor): \n            Text length tensor (B,)\n        feats_legnths (Tensor): \n            Feature length tensor (B,)\n    Returns:\n        Tensor: \n            Batched token duration extracted from `log_p_attn` (B,T_text)\n        Tensor: \n            binarization loss tensor ()\n    \"\"\"\n    B = log_p_attn.shape[0]\n    T_text = log_p_attn.shape[2]\n    device = log_p_attn.place\n\n    bin_loss = 0\n    ds = paddle.zeros((B, T_text), dtype=\"int32\")\n    for b in range(B):\n        cur_log_p_attn = log_p_attn[b, :feats_lengths[b], :text_lengths[b]]\n        viterbi = _monotonic_alignment_search(cur_log_p_attn.numpy())\n        _ds = np.bincount(viterbi)\n        ds[b, :len(_ds)] = paddle.to_tensor(\n            _ds, place=device, dtype=\"int32\")  \n\n        t_idx = paddle.arange(feats_lengths[b])\n        bin_loss = bin_loss - cur_log_p_attn[t_idx, viterbi].mean()\n    bin_loss = bin_loss / B\n    return ds, bin_loss\n\n\n@jit(nopython=True)\ndef _average_by_duration(ds, xs, text_lengths, feats_lengths):\n    B = ds.shape[0]\n    # xs_avg = np.zeros_like(ds)\n    xs_avg = np.zeros(shape=ds.shape, dtype=np.float32)\n    ds = ds.astype(np.int32)\n    for b in range(B):\n        t_text = text_lengths[b]\n        t_feats = feats_lengths[b]\n        d = ds[b, :t_text]\n        d_cumsum = d.cumsum()\n        d_cumsum = [0] + list(d_cumsum)\n        x = xs[b, :t_feats]\n        for n, (start, end) in enumerate(zip(d_cumsum[:-1], d_cumsum[1:])):\n            if len(x[start:end]) != 0:\n                xs_avg[b, n] = x[start:end].mean()\n            else:\n                xs_avg[b, n] = 0\n    return xs_avg\n\n\ndef average_by_duration(ds, xs, text_lengths, feats_lengths):\n    \"\"\"\n    Args:\n        ds (Tensor): \n            Batched token duration (B,T_text)\n        xs (Tensor): \n            Batched feature sequences to be averaged (B,T_feats)\n        text_lengths (Tensor): \n            Text length tensor (B,)\n        feats_lengths (Tensor): \n            Feature length tensor (B,)\n    Returns:\n        Tensor: Batched feature averaged according to the token duration (B, T_text)\n    \"\"\"\n    device = ds.place\n    args = [ds, xs, text_lengths, feats_lengths]\n    args = [arg.numpy() for arg in args]\n    xs_avg = _average_by_duration(*args)\n    xs_avg = paddle.to_tensor(xs_avg, place=device)\n    return xs_avg\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/generator.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in JETS.\n\nThis code is based on https://github.com/imdanboy/jets.\n\n\"\"\"\nimport logging\nimport math\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.hifigan import HiFiGANGenerator\nfrom paddlespeech.t2s.models.jets.alignments import AlignmentModule\nfrom paddlespeech.t2s.models.jets.alignments import average_by_duration\nfrom paddlespeech.t2s.models.jets.alignments import viterbi_decode\nfrom paddlespeech.t2s.models.jets.length_regulator import GaussianUpsampling\nfrom paddlespeech.t2s.modules.nets_utils import get_random_segments\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\nfrom paddlespeech.t2s.modules.predictor.duration_predictor import DurationPredictor\nfrom paddlespeech.t2s.modules.predictor.length_regulator import LengthRegulator\nfrom paddlespeech.t2s.modules.predictor.variance_predictor import VariancePredictor\nfrom paddlespeech.t2s.modules.style_encoder import StyleEncoder\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import ScaledPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.encoder import ConformerEncoder\nfrom paddlespeech.t2s.modules.transformer.encoder import TransformerEncoder\n\n\nclass JETSGenerator(nn.Layer):\n    \"\"\"Generator module in JETS.\n    \"\"\"\n\n    def __init__(\n            self,\n            idim: int,\n            odim: int,\n            adim: int=256,\n            aheads: int=2,\n            elayers: int=4,\n            eunits: int=1024,\n            dlayers: int=4,\n            dunits: int=1024,\n            positionwise_layer_type: str=\"conv1d\",\n            positionwise_conv_kernel_size: int=1,\n            use_scaled_pos_enc: bool=True,\n            use_batch_norm: bool=True,\n            encoder_normalize_before: bool=True,\n            decoder_normalize_before: bool=True,\n            encoder_concat_after: bool=False,\n            decoder_concat_after: bool=False,\n            reduction_factor: int=1,\n            encoder_type: str=\"transformer\",\n            decoder_type: str=\"transformer\",\n            transformer_enc_dropout_rate: float=0.1,\n            transformer_enc_positional_dropout_rate: float=0.1,\n            transformer_enc_attn_dropout_rate: float=0.1,\n            transformer_dec_dropout_rate: float=0.1,\n            transformer_dec_positional_dropout_rate: float=0.1,\n            transformer_dec_attn_dropout_rate: float=0.1,\n            transformer_activation_type: str=\"relu\",\n            # only for conformer\n            conformer_rel_pos_type: str=\"legacy\",\n            conformer_pos_enc_layer_type: str=\"rel_pos\",\n            conformer_self_attn_layer_type: str=\"rel_selfattn\",\n            conformer_activation_type: str=\"swish\",\n            use_macaron_style_in_conformer: bool=True,\n            use_cnn_in_conformer: bool=True,\n            zero_triu: bool=False,\n            conformer_enc_kernel_size: int=7,\n            conformer_dec_kernel_size: int=31,\n            # duration predictor\n            duration_predictor_layers: int=2,\n            duration_predictor_chans: int=384,\n            duration_predictor_kernel_size: int=3,\n            duration_predictor_dropout_rate: float=0.1,\n            # energy predictor\n            energy_predictor_layers: int=2,\n            energy_predictor_chans: int=384,\n            energy_predictor_kernel_size: int=3,\n            energy_predictor_dropout: float=0.5,\n            energy_embed_kernel_size: int=9,\n            energy_embed_dropout: float=0.5,\n            stop_gradient_from_energy_predictor: bool=False,\n            # pitch predictor\n            pitch_predictor_layers: int=2,\n            pitch_predictor_chans: int=384,\n            pitch_predictor_kernel_size: int=3,\n            pitch_predictor_dropout: float=0.5,\n            pitch_embed_kernel_size: int=9,\n            pitch_embed_dropout: float=0.5,\n            stop_gradient_from_pitch_predictor: bool=False,\n            # extra embedding related\n            spks: Optional[int]=None,\n            langs: Optional[int]=None,\n            spk_embed_dim: Optional[int]=None,\n            spk_embed_integration_type: str=\"add\",\n            use_gst: bool=False,\n            gst_tokens: int=10,\n            gst_heads: int=4,\n            gst_conv_layers: int=6,\n            gst_conv_chans_list: Sequence[int]=(32, 32, 64, 64, 128, 128),\n            gst_conv_kernel_size: int=3,\n            gst_conv_stride: int=2,\n            gst_gru_layers: int=1,\n            gst_gru_units: int=128,\n            # training related\n            init_type: str=\"xavier_uniform\",\n            init_enc_alpha: float=1.0,\n            init_dec_alpha: float=1.0,\n            use_masking: bool=False,\n            use_weighted_masking: bool=False,\n            segment_size: int=64,\n            # hifigan generator\n            generator_out_channels: int=1,\n            generator_channels: int=512,\n            generator_global_channels: int=-1,\n            generator_kernel_size: int=7,\n            generator_upsample_scales: List[int]=[8, 8, 2, 2],\n            generator_upsample_kernel_sizes: List[int]=[16, 16, 4, 4],\n            generator_resblock_kernel_sizes: List[int]=[3, 7, 11],\n            generator_resblock_dilations: List[List[int]]=[[1, 3, 5], [1, 3, 5],\n                                                           [1, 3, 5]],\n            generator_use_additional_convs: bool=True,\n            generator_bias: bool=True,\n            generator_nonlinear_activation: str=\"LeakyReLU\",\n            generator_nonlinear_activation_params: Dict[\n                str, Any]={\"negative_slope\": 0.1},\n            generator_use_weight_norm: bool=True, ):\n        \"\"\"Initialize JETS generator module.\n\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            odim (int): \n                Dimension of the outputs.\n            adim (int): \n                Attention dimension.\n            aheads (int): \n                Number of attention heads.\n            elayers (int): \n                Number of encoder layers.\n            eunits (int): \n                Number of encoder hidden units.\n            dlayers (int): \n                Number of decoder layers.\n            dunits (int): \n                Number of decoder hidden units.\n            use_scaled_pos_enc (bool): \n                Whether to use trainable scaled pos encoding.\n            use_batch_norm (bool): \n                Whether to use batch normalization in encoder prenet.\n            encoder_normalize_before (bool): \n                Whether to apply layernorm layer before encoder block.\n            decoder_normalize_before (bool): \n                Whether to apply layernorm layer before decoder block.\n            encoder_concat_after (bool): \n                Whether to concatenate attention layer's input and output in encoder.\n            decoder_concat_after (bool): \n                Whether to concatenate attention layer's input and output in decoder.\n            reduction_factor (int): \n                Reduction factor.\n            encoder_type (str): \n                Encoder type (\"transformer\" or \"conformer\").\n            decoder_type (str): \n                Decoder type (\"transformer\" or \"conformer\").\n            transformer_enc_dropout_rate (float): \n                Dropout rate in encoder except attention and positional encoding.\n            transformer_enc_positional_dropout_rate (float): \n                Dropout rate after encoder positional encoding.\n            transformer_enc_attn_dropout_rate (float): \n                Dropout rate in encoder self-attention module.\n            transformer_dec_dropout_rate (float): \n                Dropout rate in decoder except attention & positional encoding.\n            transformer_dec_positional_dropout_rate (float): \n                Dropout rate after decoder positional encoding.\n            transformer_dec_attn_dropout_rate (float): \n                Dropout rate in decoder self-attention module.\n            conformer_rel_pos_type (str): \n                Relative pos encoding type in conformer.\n            conformer_pos_enc_layer_type (str): \n                Pos encoding layer type in conformer.\n            conformer_self_attn_layer_type (str): \n                Self-attention layer type in conformer\n            conformer_activation_type (str): \n                Activation function type in conformer.\n            use_macaron_style_in_conformer: \n                Whether to use macaron style FFN.\n            use_cnn_in_conformer: \n                Whether to use CNN in conformer.\n            zero_triu: \n                Whether to use zero triu in relative self-attention module.\n            conformer_enc_kernel_size: \n                Kernel size of encoder conformer.\n            conformer_dec_kernel_size: \n                Kernel size of decoder conformer.\n            duration_predictor_layers (int): \n                Number of duration predictor layers.\n            duration_predictor_chans (int): \n                Number of duration predictor channels.\n            duration_predictor_kernel_size (int): \n                Kernel size of duration predictor.\n            duration_predictor_dropout_rate (float): \n                Dropout rate in duration predictor.\n            pitch_predictor_layers (int): \n                Number of pitch predictor layers.\n            pitch_predictor_chans (int): \n                Number of pitch predictor channels.\n            pitch_predictor_kernel_size (int): \n                Kernel size of pitch predictor.\n            pitch_predictor_dropout_rate (float): \n                Dropout rate in pitch predictor.\n            pitch_embed_kernel_size (float): \n                Kernel size of pitch embedding.\n            pitch_embed_dropout_rate (float): \n                Dropout rate for pitch embedding.\n            stop_gradient_from_pitch_predictor: \n                Whether to stop gradient from pitch predictor to encoder.\n            energy_predictor_layers (int): \n                Number of energy predictor layers.\n            energy_predictor_chans (int): \n                Number of energy predictor channels.\n            energy_predictor_kernel_size (int): \n                Kernel size of energy predictor.\n            energy_predictor_dropout_rate (float): \n                Dropout rate in energy predictor.\n            energy_embed_kernel_size (float): \n                Kernel size of energy embedding.\n            energy_embed_dropout_rate (float): \n                Dropout rate for energy embedding.\n            stop_gradient_from_energy_predictor: \n                Whether to stop gradient from energy predictor to encoder.\n            spks (Optional[int]): \n                Number of speakers. If set to > 1, assume that the sids will be provided as the input and use sid embedding layer.\n            langs (Optional[int]): \n                Number of languages. If set to > 1, assume that the lids will be provided as the input and use sid embedding layer.\n            spk_embed_dim (Optional[int]): \n                Speaker embedding dimension. If set to > 0, assume that spembs will be provided as the input.\n            spk_embed_integration_type: \n                How to integrate speaker embedding.\n            use_gst (str): \n                Whether to use global style token.\n            gst_tokens (int): \n                The number of GST embeddings.\n            gst_heads (int): \n                The number of heads in GST multihead attention.\n            gst_conv_layers (int): \n                The number of conv layers in GST.\n            gst_conv_chans_list: (Sequence[int]):\n                List of the number of channels of conv layers in GST.\n            gst_conv_kernel_size (int): \n                Kernel size of conv layers in GST.\n            gst_conv_stride (int): \n                Stride size of conv layers in GST.\n            gst_gru_layers (int): \n                The number of GRU layers in GST.\n            gst_gru_units (int): \n                The number of GRU units in GST.\n            init_type (str): \n                How to initialize transformer parameters.\n            init_enc_alpha (float): \n                Initial value of alpha in scaled pos encoding of the encoder.\n            init_dec_alpha (float): \n                Initial value of alpha in scaled pos encoding of the decoder.\n            use_masking (bool): \n                Whether to apply masking for padded part in loss calculation.\n            use_weighted_masking (bool): \n                Whether to apply weighted masking in loss calculation.\n            segment_size (int): \n                Segment size for random windowed discriminator\n            generator_out_channels (int): \n                Number of output channels.\n            generator_channels (int): \n                Number of hidden representation channels.\n            generator_global_channels (int): \n                Number of global conditioning channels.\n            generator_kernel_size (int): \n                Kernel size of initial and final conv layer.\n            generator_upsample_scales (List[int]): \n                List of upsampling scales.\n            generator_upsample_kernel_sizes (List[int]): \n                List of kernel sizes for upsample layers.\n            generator_resblock_kernel_sizes (List[int]): \n                List of kernel sizes for residual blocks.\n            generator_resblock_dilations (List[List[int]]): \n                List of list of dilations for residual blocks.\n            generator_use_additional_convs (bool): \n                Whether to use additional conv layers in residual blocks.\n            generator_bias (bool): \n                Whether to add bias parameter in convolution layers.\n            generator_nonlinear_activation (str): \n                Activation function module name.\n            generator_nonlinear_activation_params (Dict[str, Any]): \n                Hyperparameters for activation function.\n            generator_use_weight_norm (bool): \n                Whether to use weight norm. If set to true, it will be applied to all of the conv layers.\n\n        \"\"\"\n        super().__init__()\n        self.segment_size = segment_size\n        self.upsample_factor = int(np.prod(generator_upsample_scales))\n        self.idim = idim\n        self.odim = odim\n        self.reduction_factor = reduction_factor\n        self.encoder_type = encoder_type\n        self.decoder_type = decoder_type\n        self.stop_gradient_from_pitch_predictor = stop_gradient_from_pitch_predictor\n        self.stop_gradient_from_energy_predictor = stop_gradient_from_energy_predictor\n        self.use_scaled_pos_enc = use_scaled_pos_enc\n        self.use_gst = use_gst\n\n        # use idx 0 as padding idx\n        self.padding_idx = 0\n\n        # get positional encoding layer type\n        transformer_pos_enc_layer_type = \"scaled_abs_pos\" if self.use_scaled_pos_enc else \"abs_pos\"\n\n        # check relative positional encoding compatibility\n        if \"conformer\" in [encoder_type, decoder_type]:\n            if conformer_rel_pos_type == \"legacy\":\n                if conformer_pos_enc_layer_type == \"rel_pos\":\n                    conformer_pos_enc_layer_type = \"legacy_rel_pos\"\n                    logging.warning(\n                        \"Fallback to conformer_pos_enc_layer_type = 'legacy_rel_pos' \"\n                        \"due to the compatibility. If you want to use the new one, \"\n                        \"please use conformer_pos_enc_layer_type = 'latest'.\")\n                if conformer_self_attn_layer_type == \"rel_selfattn\":\n                    conformer_self_attn_layer_type = \"legacy_rel_selfattn\"\n                    logging.warning(\n                        \"Fallback to \"\n                        \"conformer_self_attn_layer_type = 'legacy_rel_selfattn' \"\n                        \"due to the compatibility. If you want to use the new one, \"\n                        \"please use conformer_pos_enc_layer_type = 'latest'.\")\n            elif conformer_rel_pos_type == \"latest\":\n                assert conformer_pos_enc_layer_type != \"legacy_rel_pos\"\n                assert conformer_self_attn_layer_type != \"legacy_rel_selfattn\"\n            else:\n                raise ValueError(\n                    f\"Unknown rel_pos_type: {conformer_rel_pos_type}\")\n\n        # define encoder\n        encoder_input_layer = nn.Embedding(\n            num_embeddings=idim,\n            embedding_dim=adim,\n            padding_idx=self.padding_idx)\n        if encoder_type == \"transformer\":\n            self.encoder = TransformerEncoder(\n                idim=idim,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=eunits,\n                num_blocks=elayers,\n                input_layer=encoder_input_layer,\n                dropout_rate=transformer_enc_dropout_rate,\n                positional_dropout_rate=transformer_enc_positional_dropout_rate,\n                attention_dropout_rate=transformer_enc_attn_dropout_rate,\n                pos_enc_layer_type=transformer_pos_enc_layer_type,\n                normalize_before=encoder_normalize_before,\n                concat_after=encoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                activation_type=transformer_activation_type)\n        elif encoder_type == \"conformer\":\n            self.encoder = ConformerEncoder(\n                idim=idim,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=eunits,\n                num_blocks=elayers,\n                input_layer=encoder_input_layer,\n                dropout_rate=transformer_enc_dropout_rate,\n                positional_dropout_rate=transformer_enc_positional_dropout_rate,\n                attention_dropout_rate=transformer_enc_attn_dropout_rate,\n                normalize_before=encoder_normalize_before,\n                concat_after=encoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                macaron_style=use_macaron_style_in_conformer,\n                pos_enc_layer_type=conformer_pos_enc_layer_type,\n                selfattention_layer_type=conformer_self_attn_layer_type,\n                activation_type=conformer_activation_type,\n                use_cnn_module=use_cnn_in_conformer,\n                cnn_module_kernel=conformer_enc_kernel_size,\n                zero_triu=zero_triu, )\n        else:\n            raise ValueError(f\"{encoder_type} is not supported.\")\n\n        # define GST\n        if self.use_gst:\n            self.gst = StyleEncoder(\n                idim=odim,  # the input is mel-spectrogram\n                gst_tokens=gst_tokens,\n                gst_token_dim=adim,\n                gst_heads=gst_heads,\n                conv_layers=gst_conv_layers,\n                conv_chans_list=gst_conv_chans_list,\n                conv_kernel_size=gst_conv_kernel_size,\n                conv_stride=gst_conv_stride,\n                gru_layers=gst_gru_layers,\n                gru_units=gst_gru_units, )\n\n        # define spk and lang embedding\n        self.spks = None\n        if spks is not None and spks > 1:\n            self.spks = spks\n            self.sid_emb = nn.Embedding(spks, adim)\n        self.langs = None\n        if langs is not None and langs > 1:\n            self.langs = langs\n            self.lid_emb = nn.Embedding(langs, adim)\n\n        # define additional projection for speaker embedding\n        self.spk_embed_dim = None\n        if spk_embed_dim is not None and spk_embed_dim > 0:\n            self.spk_embed_dim = spk_embed_dim\n            self.spk_embed_integration_type = spk_embed_integration_type\n        if self.spk_embed_dim is not None:\n            if self.spk_embed_integration_type == \"add\":\n                self.projection = nn.Linear(self.spk_embed_dim, adim)\n            else:\n                self.projection = nn.Linear(adim + self.spk_embed_dim, adim)\n\n        # define duration predictor\n        self.duration_predictor = DurationPredictor(\n            idim=adim,\n            n_layers=duration_predictor_layers,\n            n_chans=duration_predictor_chans,\n            kernel_size=duration_predictor_kernel_size,\n            dropout_rate=duration_predictor_dropout_rate, )\n\n        # define pitch predictor\n        self.pitch_predictor = VariancePredictor(\n            idim=adim,\n            n_layers=pitch_predictor_layers,\n            n_chans=pitch_predictor_chans,\n            kernel_size=pitch_predictor_kernel_size,\n            dropout_rate=pitch_predictor_dropout, )\n        # NOTE(kan-bayashi): We use continuous pitch + FastPitch style avg\n        self.pitch_embed = nn.Sequential(\n            nn.Conv1D(\n                in_channels=1,\n                out_channels=adim,\n                kernel_size=pitch_embed_kernel_size,\n                padding=(pitch_embed_kernel_size - 1) // 2, ),\n            nn.Dropout(pitch_embed_dropout), )\n\n        # define energy predictor\n        self.energy_predictor = VariancePredictor(\n            idim=adim,\n            n_layers=energy_predictor_layers,\n            n_chans=energy_predictor_chans,\n            kernel_size=energy_predictor_kernel_size,\n            dropout_rate=energy_predictor_dropout, )\n        # NOTE(kan-bayashi): We use continuous enegy + FastPitch style avg\n        self.energy_embed = nn.Sequential(\n            nn.Conv1D(\n                in_channels=1,\n                out_channels=adim,\n                kernel_size=energy_embed_kernel_size,\n                padding=(energy_embed_kernel_size - 1) // 2, ),\n            nn.Dropout(energy_embed_dropout), )\n\n        # define length regulator\n        self.length_regulator = GaussianUpsampling()\n\n        # define decoder\n        # NOTE: we use encoder as decoder\n        # because fastspeech's decoder is the same as encoder\n        if decoder_type == \"transformer\":\n            self.decoder = TransformerEncoder(\n                idim=0,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=dunits,\n                num_blocks=dlayers,\n                # in decoder, don't need layer before pos_enc_class (we use embedding here in encoder)\n                input_layer=None,\n                dropout_rate=transformer_dec_dropout_rate,\n                positional_dropout_rate=transformer_dec_positional_dropout_rate,\n                attention_dropout_rate=transformer_dec_attn_dropout_rate,\n                pos_enc_layer_type=transformer_pos_enc_layer_type,\n                normalize_before=decoder_normalize_before,\n                concat_after=decoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                activation_type=conformer_activation_type, )\n\n        elif decoder_type == \"conformer\":\n            self.decoder = ConformerEncoder(\n                idim=0,\n                attention_dim=adim,\n                attention_heads=aheads,\n                linear_units=dunits,\n                num_blocks=dlayers,\n                input_layer=None,\n                dropout_rate=transformer_dec_dropout_rate,\n                positional_dropout_rate=transformer_dec_positional_dropout_rate,\n                attention_dropout_rate=transformer_dec_attn_dropout_rate,\n                normalize_before=decoder_normalize_before,\n                concat_after=decoder_concat_after,\n                positionwise_layer_type=positionwise_layer_type,\n                positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n                macaron_style=use_macaron_style_in_conformer,\n                pos_enc_layer_type=conformer_pos_enc_layer_type,\n                selfattention_layer_type=conformer_self_attn_layer_type,\n                activation_type=conformer_activation_type,\n                use_cnn_module=use_cnn_in_conformer,\n                cnn_module_kernel=conformer_dec_kernel_size, )\n        else:\n            raise ValueError(f\"{decoder_type} is not supported.\")\n\n        self.generator = HiFiGANGenerator(\n            in_channels=adim,\n            out_channels=generator_out_channels,\n            channels=generator_channels,\n            global_channels=generator_global_channels,\n            kernel_size=generator_kernel_size,\n            upsample_scales=generator_upsample_scales,\n            upsample_kernel_sizes=generator_upsample_kernel_sizes,\n            resblock_kernel_sizes=generator_resblock_kernel_sizes,\n            resblock_dilations=generator_resblock_dilations,\n            use_additional_convs=generator_use_additional_convs,\n            bias=generator_bias,\n            nonlinear_activation=generator_nonlinear_activation,\n            nonlinear_activation_params=generator_nonlinear_activation_params,\n            use_weight_norm=generator_use_weight_norm, )\n\n        self.alignment_module = AlignmentModule(adim, odim)\n\n        # initialize parameters\n        self._reset_parameters(\n            init_type=init_type,\n            init_enc_alpha=init_enc_alpha,\n            init_dec_alpha=init_dec_alpha, )\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            durations_lengths: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            use_alignment_module: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n               paddle.Tensor, paddle.Tensor,\n               Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n                     paddle.Tensor, paddle.Tensor, ], ]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, aux_channels, T_feats).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            pitch (Tensor): \n                Batch of padded token-averaged pitch (B, T_text, 1).\n            energy (Tensor):\n                Batch of padded token-averaged energy (B, T_text, 1).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            use_alignment_module (bool):\n                Whether to use alignment module.\n                \n        Returns:\n            Tensor: \n                Waveform tensor (B, 1, segment_size * upsample_factor).\n            Tensor: \n                binarization loss ()\n            Tensor: \n                log probability attention matrix (B,T_feats,T_text)\n            Tensor: \n                Segments start index tensor (B,).\n            Tensor: \n                predicted duration (B,T_text)\n            Tensor: \n                ground-truth duration obtained from an alignment module (B,T_text)\n            Tensor: \n                predicted pitch (B,T_text,1)\n            Tensor: \n                ground-truth averaged pitch (B,T_text,1)\n            Tensor: \n                predicted energy (B,T_text,1)\n            Tensor: \n                ground-truth averaged energy (B,T_text,1)\n        \"\"\"\n        if use_alignment_module:\n            text = text[:, :text_lengths.max()]  # for data-parallel\n            feats = feats[:, :feats_lengths.max()]  # for data-parallel\n            pitch = pitch[:, :durations_lengths.max()]  # for data-parallel\n            energy = energy[:, :durations_lengths.max()]  # for data-parallel\n        else:\n            text = text[:, :text_lengths.max()]  # for data-parallel\n            feats = feats[:, :feats_lengths.max()]  # for data-parallel\n            pitch = pitch[:, :feats_lengths.max()]  # for data-parallel\n            energy = energy[:, :feats_lengths.max()]  # for data-parallel\n\n        # forward encoder\n        x_masks = self._source_mask(text_lengths)\n        hs, _ = self.encoder(text, x_masks)  # (B, T_text, adim)\n\n        # integrate with GST\n        if self.use_gst:\n            style_embs = self.gst(ys)\n            hs = hs + style_embs.unsqueeze(1)\n\n        # integrate with SID and LID embeddings\n        if self.spks is not None:\n            sid_embs = self.sid_emb(sids.reshape([-1]))\n            hs = hs + sid_embs.unsqueeze(1)\n        if self.langs is not None:\n            lid_embs = self.lid_emb(lids.reshape([-1]))\n            hs = hs + lid_embs.unsqueeze(1)\n\n        # integrate speaker embedding\n        if self.spk_embed_dim is not None:\n            hs = self._integrate_with_spk_embed(hs, spembs)\n\n        # forward alignment module and obtain duration, averaged pitch, energy\n        h_masks = make_pad_mask(text_lengths)\n        if use_alignment_module:\n            log_p_attn = self.alignment_module(hs, feats, h_masks)\n            ds, bin_loss = viterbi_decode(log_p_attn, text_lengths,\n                                          feats_lengths)\n            ps = average_by_duration(ds,\n                                     pitch.squeeze(-1), text_lengths,\n                                     feats_lengths).unsqueeze(-1)\n            es = average_by_duration(ds,\n                                     energy.squeeze(-1), text_lengths,\n                                     feats_lengths).unsqueeze(-1)\n        else:\n            ds = durations\n            ps = pitch\n            es = energy\n            log_p_attn = attn = bin_loss = None\n\n        # forward duration predictor and variance predictors\n        if self.stop_gradient_from_pitch_predictor:\n            p_outs = self.pitch_predictor(hs.detach(), h_masks.unsqueeze(-1))\n        else:\n            p_outs = self.pitch_predictor(hs, h_masks.unsqueeze(-1))\n        if self.stop_gradient_from_energy_predictor:\n            e_outs = self.energy_predictor(hs.detach(), h_masks.unsqueeze(-1))\n        else:\n            e_outs = self.energy_predictor(hs, h_masks.unsqueeze(-1))\n\n        d_outs = self.duration_predictor(hs, h_masks)\n\n        # use groundtruth in training\n        p_embs = self.pitch_embed(ps.transpose([0, 2, 1])).transpose([0, 2, 1])\n        e_embs = self.energy_embed(es.transpose([0, 2, 1])).transpose([0, 2, 1])\n        hs = hs + e_embs + p_embs\n\n        # upsampling\n        h_masks = make_non_pad_mask(feats_lengths)\n        # d_masks = make_non_pad_mask(text_lengths).to(ds.device)\n        d_masks = make_non_pad_mask(text_lengths)\n        hs = self.length_regulator(hs, ds, h_masks,\n                                   d_masks)  # (B, T_feats, adim)\n\n        # forward decoder\n        h_masks = self._source_mask(feats_lengths)\n        zs, _ = self.decoder(hs, h_masks)  # (B, T_feats, adim)\n\n        # get random segments\n        z_segments, z_start_idxs = get_random_segments(\n            zs.transpose([0, 2, 1]),\n            feats_lengths,\n            self.segment_size, )\n        # forward generator\n        wav = self.generator(z_segments)\n        if use_alignment_module:\n            return wav, bin_loss, log_p_attn, z_start_idxs, d_outs, ds, p_outs, ps, e_outs, es\n        else:\n            return wav, None, None, z_start_idxs, d_outs, ds, p_outs, ps, e_outs, es\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: Optional[paddle.Tensor]=None,\n            feats_lengths: Optional[paddle.Tensor]=None,\n            pitch: Optional[paddle.Tensor]=None,\n            energy: Optional[paddle.Tensor]=None,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            use_alignment_module: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Run inference.\n\n        Args:\n            text (Tensor): Input text index tensor (B, T_text,).\n            text_lengths (Tensor): Text length tensor (B,).\n            feats (Tensor): Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor): Feature length tensor (B,).\n            pitch (Tensor): Pitch tensor (B, T_feats, 1)\n            energy (Tensor): Energy tensor (B, T_feats, 1)\n            sids (Optional[Tensor]): Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]): Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]): Language index tensor (B,) or (B, 1).\n            use_alignment_module (bool): Whether to use alignment module.\n\n        Returns:\n            Tensor: Generated waveform tensor (B, T_wav).\n            Tensor: Duration tensor (B, T_text).\n\n        \"\"\"\n        # forward encoder\n        x_masks = self._source_mask(text_lengths)\n        hs, _ = self.encoder(text, x_masks)  # (B, T_text, adim)\n\n        # integrate with GST\n        if self.use_gst:\n            style_embs = self.gst(ys)\n            hs = hs + style_embs.unsqueeze(1)\n\n        # integrate with SID and LID embeddings\n        if self.spks is not None:\n            sid_embs = self.sid_emb(sids.reshape([-1]))\n            hs = hs + sid_embs.unsqueeze(1)\n        if self.langs is not None:\n            lid_embs = self.lid_emb(lids.reshape([-1]))\n            hs = hs + lid_embs.unsqueeze(1)\n\n        # integrate speaker embedding\n        if self.spk_embed_dim is not None:\n            hs = self._integrate_with_spk_embed(hs, spembs)\n\n        h_masks = make_pad_mask(text_lengths)\n        if use_alignment_module:\n            # forward alignment module and obtain duration, averaged pitch, energy\n            log_p_attn, attn = self.alignment_module(hs, feats, h_masks)\n            d_outs, _ = viterbi_decode(log_p_attn, text_lengths, feats_lengths)\n            p_outs = average_by_duration(d_outs,\n                                         pitch.squeeze(-1), text_lengths,\n                                         feats_lengths).unsqueeze(-1)\n            e_outs = average_by_duration(d_outs,\n                                         energy.squeeze(-1), text_lengths,\n                                         feats_lengths).unsqueeze(-1)\n        else:\n            # forward duration predictor and variance predictors\n            p_outs = self.pitch_predictor(hs, h_masks.unsqueeze(-1))\n            e_outs = self.energy_predictor(hs, h_masks.unsqueeze(-1))\n            d_outs = self.duration_predictor.inference(hs, h_masks)\n\n        p_embs = self.pitch_embed(p_outs.transpose([0, 2, 1])).transpose(\n            [0, 2, 1])\n        e_embs = self.energy_embed(e_outs.transpose([0, 2, 1])).transpose(\n            [0, 2, 1])\n        hs = hs + e_embs + p_embs\n\n        # upsampling\n        if feats_lengths is not None:\n            h_masks = make_non_pad_mask(feats_lengths)\n        else:\n            h_masks = None\n        d_masks = make_non_pad_mask(text_lengths)\n        hs = self.length_regulator(hs, d_outs, h_masks,\n                                   d_masks)  # (B, T_feats, adim)\n\n        # forward decoder\n        if feats_lengths is not None:\n            h_masks = self._source_mask(feats_lengths)\n        else:\n            h_masks = None\n        zs, _ = self.decoder(hs, h_masks)  # (B, T_feats, adim)\n\n        # forward generator\n        wav = self.generator(zs.transpose([0, 2, 1]))\n\n        return wav.squeeze(1), d_outs\n\n    def _integrate_with_spk_embed(self,\n                                  hs: paddle.Tensor,\n                                  spembs: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Integrate speaker embedding with hidden states.\n\n        Args:\n            hs (Tensor): Batch of hidden state sequences (B, T_text, adim).\n            spembs (Tensor): Batch of speaker embeddings (B, spk_embed_dim).\n\n        Returns:\n            Tensor: Batch of integrated hidden state sequences (B, T_text, adim).\n\n        \"\"\"\n        if self.spk_embed_integration_type == \"add\":\n            # apply projection and then add to hidden states\n            spembs = self.projection(F.normalize(spembs))\n            hs = hs + spembs.unsqueeze(1)\n        elif self.spk_embed_integration_type == \"concat\":\n            # concat hidden states with spk embeds and then apply projection\n            spembs = F.normalize(spembs).unsqueeze(1).expand(-1, hs.shape[1],\n                                                             -1)\n            hs = self.projection(paddle.concat([hs, spembs], axis=-1))\n        else:\n            raise NotImplementedError(\"support only add or concat.\")\n\n        return hs\n\n    def _generate_path(self, dur: paddle.Tensor,\n                       mask: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Generate path a.k.a. monotonic attention.\n        Args:\n            dur (Tensor):\n                Duration tensor (B, 1, T_text).\n            mask (Tensor):\n                Attention mask tensor (B, 1, T_feats, T_text).\n        Returns:\n            Tensor:\n                Path tensor (B, 1, T_feats, T_text).\n        \"\"\"\n        b, _, t_y, t_x = paddle.shape(mask)\n        cum_dur = paddle.cumsum(dur, -1)\n        cum_dur_flat = paddle.reshape(cum_dur, [b * t_x])\n\n        path = paddle.arange(t_y, dtype=dur.dtype)\n        path = path.unsqueeze(0) < cum_dur_flat.unsqueeze(1)\n        path = paddle.reshape(path, [b, t_x, t_y])\n        '''\n        path will be like (t_x = 3, t_y = 5):\n        [[[1., 1., 0., 0., 0.],      [[[1., 1., 0., 0., 0.],\n          [1., 1., 1., 1., 0.],  -->   [0., 0., 1., 1., 0.],\n          [1., 1., 1., 1., 1.]]]       [0., 0., 0., 0., 1.]]]\n        '''\n\n        path = paddle.cast(path, dtype='float32')\n        pad_tmp = self.pad1d(path)[:, :-1]\n        path = path - pad_tmp\n        return path.unsqueeze(1).transpose([0, 1, 3, 2]) * mask\n\n    def _source_mask(self, ilens: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Make masks for self-attention.\n\n        Args:\n            ilens (LongTensor): Batch of lengths (B,).\n\n        Returns:\n            Tensor: Mask tensor for self-attention.\n                dtype=paddle.uint8 \n\n        Examples:\n            >>> ilens = [5, 3]\n            >>> self._source_mask(ilens)\n            tensor([[[1, 1, 1, 1, 1],\n                     [1, 1, 1, 0, 0]]], dtype=torch.uint8)\n\n        \"\"\"\n        x_masks = paddle.to_tensor(make_non_pad_mask(ilens))\n        return x_masks.unsqueeze(-2)\n\n    def _reset_parameters(self,\n                          init_type: str,\n                          init_enc_alpha: float,\n                          init_dec_alpha: float):\n        # initialize parameters\n        initialize(self, init_type)\n\n        # initialize alpha in scaled positional encoding\n        if self.encoder_type == \"transformer\" and self.use_scaled_pos_enc:\n            self.encoder.embed[-1].alpha.data = paddle.to_tensor(init_enc_alpha)\n        if self.decoder_type == \"transformer\" and self.use_scaled_pos_enc:\n            self.decoder.embed[-1].alpha.data = paddle.to_tensor(init_dec_alpha)\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/jets.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in JETS.\n\nThis code is based on https://github.com/imdanboy/jets.\n\n\"\"\"\n\"\"\"JETS module\"\"\"\nimport math\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Optional\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiScaleDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiScaleMultiPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANScaleDiscriminator\nfrom paddlespeech.t2s.models.jets.generator import JETSGenerator\nfrom paddlespeech.utils.initialize import _calculate_fan_in_and_fan_out\nfrom paddlespeech.utils.initialize import kaiming_uniform_\nfrom paddlespeech.utils.initialize import normal_\nfrom paddlespeech.utils.initialize import ones_\nfrom paddlespeech.utils.initialize import uniform_\nfrom paddlespeech.utils.initialize import zeros_\n\nAVAILABLE_GENERATERS = {\n    \"jets_generator\": JETSGenerator,\n}\nAVAILABLE_DISCRIMINATORS = {\n    \"hifigan_period_discriminator\":\n    HiFiGANPeriodDiscriminator,\n    \"hifigan_scale_discriminator\":\n    HiFiGANScaleDiscriminator,\n    \"hifigan_multi_period_discriminator\":\n    HiFiGANMultiPeriodDiscriminator,\n    \"hifigan_multi_scale_discriminator\":\n    HiFiGANMultiScaleDiscriminator,\n    \"hifigan_multi_scale_multi_period_discriminator\":\n    HiFiGANMultiScaleMultiPeriodDiscriminator,\n}\n\n\nclass JETS(nn.Layer):\n    \"\"\"JETS module (generator + discriminator).\n    This is a module of JETS described in `JETS: Jointly Training FastSpeech2 \n    and HiFi-GAN for End to End Text to Speech`_.\n    .. _`JETS: Jointly Training FastSpeech2 and HiFi-GAN for End to End Text to Speech\n        Text-to-Speech`: https://arxiv.org/abs/2203.16852v1\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # generator related\n            idim: int,\n            odim: int,\n            sampling_rate: int=22050,\n            generator_type: str=\"jets_generator\",\n            generator_params: Dict[str, Any]={\n                \"adim\": 256,\n                \"aheads\": 2,\n                \"elayers\": 4,\n                \"eunits\": 1024,\n                \"dlayers\": 4,\n                \"dunits\": 1024,\n                \"positionwise_layer_type\": \"conv1d\",\n                \"positionwise_conv_kernel_size\": 1,\n                \"use_scaled_pos_enc\": True,\n                \"use_batch_norm\": True,\n                \"encoder_normalize_before\": True,\n                \"decoder_normalize_before\": True,\n                \"encoder_concat_after\": False,\n                \"decoder_concat_after\": False,\n                \"reduction_factor\": 1,\n                \"encoder_type\": \"transformer\",\n                \"decoder_type\": \"transformer\",\n                \"transformer_enc_dropout_rate\": 0.1,\n                \"transformer_enc_positional_dropout_rate\": 0.1,\n                \"transformer_enc_attn_dropout_rate\": 0.1,\n                \"transformer_dec_dropout_rate\": 0.1,\n                \"transformer_dec_positional_dropout_rate\": 0.1,\n                \"transformer_dec_attn_dropout_rate\": 0.1,\n                \"conformer_rel_pos_type\": \"latest\",\n                \"conformer_pos_enc_layer_type\": \"rel_pos\",\n                \"conformer_self_attn_layer_type\": \"rel_selfattn\",\n                \"conformer_activation_type\": \"swish\",\n                \"use_macaron_style_in_conformer\": True,\n                \"use_cnn_in_conformer\": True,\n                \"zero_triu\": False,\n                \"conformer_enc_kernel_size\": 7,\n                \"conformer_dec_kernel_size\": 31,\n                \"duration_predictor_layers\": 2,\n                \"duration_predictor_chans\": 384,\n                \"duration_predictor_kernel_size\": 3,\n                \"duration_predictor_dropout_rate\": 0.1,\n                \"energy_predictor_layers\": 2,\n                \"energy_predictor_chans\": 384,\n                \"energy_predictor_kernel_size\": 3,\n                \"energy_predictor_dropout\": 0.5,\n                \"energy_embed_kernel_size\": 1,\n                \"energy_embed_dropout\": 0.5,\n                \"stop_gradient_from_energy_predictor\": False,\n                \"pitch_predictor_layers\": 5,\n                \"pitch_predictor_chans\": 384,\n                \"pitch_predictor_kernel_size\": 5,\n                \"pitch_predictor_dropout\": 0.5,\n                \"pitch_embed_kernel_size\": 1,\n                \"pitch_embed_dropout\": 0.5,\n                \"stop_gradient_from_pitch_predictor\": True,\n                \"generator_out_channels\": 1,\n                \"generator_channels\": 512,\n                \"generator_global_channels\": -1,\n                \"generator_kernel_size\": 7,\n                \"generator_upsample_scales\": [8, 8, 2, 2],\n                \"generator_upsample_kernel_sizes\": [16, 16, 4, 4],\n                \"generator_resblock_kernel_sizes\": [3, 7, 11],\n                \"generator_resblock_dilations\":\n                [[1, 3, 5], [1, 3, 5], [1, 3, 5]],\n                \"generator_use_additional_convs\": True,\n                \"generator_bias\": True,\n                \"generator_nonlinear_activation\": \"LeakyReLU\",\n                \"generator_nonlinear_activation_params\": {\n                    \"negative_slope\": 0.1\n                },\n                \"generator_use_weight_norm\": True,\n                \"segment_size\": 64,\n                \"spks\": -1,\n                \"langs\": -1,\n                \"spk_embed_dim\": None,\n                \"spk_embed_integration_type\": \"add\",\n                \"use_gst\": False,\n                \"gst_tokens\": 10,\n                \"gst_heads\": 4,\n                \"gst_conv_layers\": 6,\n                \"gst_conv_chans_list\": [32, 32, 64, 64, 128, 128],\n                \"gst_conv_kernel_size\": 3,\n                \"gst_conv_stride\": 2,\n                \"gst_gru_layers\": 1,\n                \"gst_gru_units\": 128,\n                \"init_type\": \"xavier_uniform\",\n                \"init_enc_alpha\": 1.0,\n                \"init_dec_alpha\": 1.0,\n                \"use_masking\": False,\n                \"use_weighted_masking\": False,\n            },\n            # discriminator related\n            discriminator_type: str=\"hifigan_multi_scale_multi_period_discriminator\",\n            discriminator_params: Dict[str, Any]={\n                \"scales\": 1,\n                \"scale_downsample_pooling\": \"AvgPool1D\",\n                \"scale_downsample_pooling_params\": {\n                    \"kernel_size\": 4,\n                    \"stride\": 2,\n                    \"padding\": 2,\n                },\n                \"scale_discriminator_params\": {\n                    \"in_channels\": 1,\n                    \"out_channels\": 1,\n                    \"kernel_sizes\": [15, 41, 5, 3],\n                    \"channels\": 128,\n                    \"max_downsample_channels\": 1024,\n                    \"max_groups\": 16,\n                    \"bias\": True,\n                    \"downsample_scales\": [2, 2, 4, 4, 1],\n                    \"nonlinear_activation\": \"leakyrelu\",\n                    \"nonlinear_activation_params\": {\n                        \"negative_slope\": 0.1\n                    },\n                    \"use_weight_norm\": True,\n                    \"use_spectral_norm\": False,\n                },\n                \"follow_official_norm\": False,\n                \"periods\": [2, 3, 5, 7, 11],\n                \"period_discriminator_params\": {\n                    \"in_channels\": 1,\n                    \"out_channels\": 1,\n                    \"kernel_sizes\": [5, 3],\n                    \"channels\": 32,\n                    \"downsample_scales\": [3, 3, 3, 3, 1],\n                    \"max_downsample_channels\": 1024,\n                    \"bias\": True,\n                    \"nonlinear_activation\": \"leakyrelu\",\n                    \"nonlinear_activation_params\": {\n                        \"negative_slope\": 0.1\n                    },\n                    \"use_weight_norm\": True,\n                    \"use_spectral_norm\": False,\n                },\n            },\n            cache_generator_outputs: bool=True, ):\n        \"\"\"Initialize JETS module.\n        Args:\n            idim (int):\n                Input vocabrary size.\n            odim (int):\n                Acoustic feature dimension. The actual output channels will\n                be 1 since JETS is the end-to-end text-to-wave model but for the\n                compatibility odim is used to indicate the acoustic feature dimension.\n            sampling_rate (int):\n                Sampling rate, not used for the training but it will\n                be referred in saving waveform during the inference.\n            generator_type (str):\n                Generator type.\n            generator_params (Dict[str, Any]):\n                Parameter dict for generator.\n            discriminator_type (str):\n                Discriminator type.\n            discriminator_params (Dict[str, Any]):\n                Parameter dict for discriminator.\n            cache_generator_outputs (bool):\n                Whether to cache generator outputs.\n        \"\"\"\n        super().__init__()\n\n        # define modules\n        generator_class = AVAILABLE_GENERATERS[generator_type]\n        if generator_type == \"jets_generator\":\n            # NOTE: Update parameters for the compatibility.\n            #   The idim and odim is automatically decided from input data,\n            #   where idim represents #vocabularies and odim represents\n            #   the input acoustic feature dimension.\n            generator_params.update(idim=idim, odim=odim)\n        self.generator = generator_class(\n            **generator_params, )\n        discriminator_class = AVAILABLE_DISCRIMINATORS[discriminator_type]\n        self.discriminator = discriminator_class(\n            **discriminator_params, )\n\n        # cache\n        self.cache_generator_outputs = cache_generator_outputs\n        self._cache = None\n\n        # store sampling rate for saving wav file\n        # (not used for the training)\n        self.fs = sampling_rate\n\n        # store parameters for test compatibility\n        self.spks = self.generator.spks\n        self.langs = self.generator.langs\n        self.spk_embed_dim = self.generator.spk_embed_dim\n\n        self.reuse_cache_gen = True\n        self.reuse_cache_dis = True\n\n        self.reset_parameters()\n        self.generator._reset_parameters(\n            init_type=generator_params[\"init_type\"],\n            init_enc_alpha=generator_params[\"init_enc_alpha\"],\n            init_dec_alpha=generator_params[\"init_dec_alpha\"], )\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            durations_lengths: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            forward_generator: bool=True,\n            use_alignment_module: bool=False,\n            **kwargs, ) -> Dict[str, Any]:\n        \"\"\"Perform generator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            durations(Tensor(int64)): \n                Batch of padded durations (B, Tmax).\n            durations_lengths (Tensor):\n                durations length tensor (B,).\n            pitch(Tensor): \n                Batch of padded token-averaged pitch (B, Tmax, 1).\n            energy(Tensor): \n                Batch of padded token-averaged energy (B, Tmax, 1).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            forward_generator (bool):\n                Whether to forward generator.\n            use_alignment_module (bool):\n                Whether to use alignment module.\n        Returns:\n\n        \"\"\"\n        if forward_generator:\n            return self._forward_generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                durations=durations,\n                durations_lengths=durations_lengths,\n                pitch=pitch,\n                energy=energy,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                use_alignment_module=use_alignment_module, )\n        else:\n            return self._forward_discrminator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                durations=durations,\n                durations_lengths=durations_lengths,\n                pitch=pitch,\n                energy=energy,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                use_alignment_module=use_alignment_module, )\n\n    def _forward_generator(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            durations_lengths: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            use_alignment_module: bool=False,\n            **kwargs, ) -> Dict[str, Any]:\n        \"\"\"Perform generator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            durations(Tensor(int64)): \n                Batch of padded durations (B, Tmax).\n            durations_lengths (Tensor):\n                durations length tensor (B,).\n            pitch(Tensor): \n                Batch of padded token-averaged pitch (B, Tmax, 1).\n            energy(Tensor): \n                Batch of padded token-averaged energy (B, Tmax, 1).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            use_alignment_module (bool):\n                Whether to use alignment module.\n        Returns:\n\n        \"\"\"\n        # setup\n        # calculate generator outputs\n        self.reuse_cache_gen = True\n        if not self.cache_generator_outputs or self._cache is None:\n            self.reuse_cache_gen = False\n            outs = self.generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                durations=durations,\n                durations_lengths=durations_lengths,\n                pitch=pitch,\n                energy=energy,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                use_alignment_module=use_alignment_module, )\n        else:\n            outs = self._cache\n\n        # store cache\n        if self.training and self.cache_generator_outputs and not self.reuse_cache_gen:\n            self._cache = outs\n\n        return outs\n\n    def _forward_discrminator(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            durations: paddle.Tensor,\n            durations_lengths: paddle.Tensor,\n            pitch: paddle.Tensor,\n            energy: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            use_alignment_module: bool=False,\n            **kwargs, ) -> Dict[str, Any]:\n        \"\"\"Perform discriminator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            durations(Tensor(int64)): \n                Batch of padded durations (B, Tmax).\n            durations_lengths (Tensor):\n                durations length tensor (B,).\n            pitch(Tensor): \n                Batch of padded token-averaged pitch (B, Tmax, 1).\n            energy(Tensor): \n                Batch of padded token-averaged energy (B, Tmax, 1).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            use_alignment_module (bool):\n                Whether to use alignment module.\n        Returns:\n\n        \"\"\"\n        # setup\n        # calculate generator outputs\n        self.reuse_cache_dis = True\n        if not self.cache_generator_outputs or self._cache is None:\n            self.reuse_cache_dis = False\n            outs = self.generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                durations=durations,\n                durations_lengths=durations_lengths,\n                pitch=pitch,\n                energy=energy,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                use_alignment_module=use_alignment_module,\n                **kwargs, )\n        else:\n            outs = self._cache\n\n        # store cache\n        if self.cache_generator_outputs and not self.reuse_cache_dis:\n            self._cache = outs\n\n        return outs\n\n    def inference(self,\n                  text: paddle.Tensor,\n                  feats: Optional[paddle.Tensor]=None,\n                  pitch: Optional[paddle.Tensor]=None,\n                  energy: Optional[paddle.Tensor]=None,\n                  use_alignment_module: bool=False,\n                  **kwargs) -> Dict[str, paddle.Tensor]:\n        \"\"\"Run inference.\n        Args:\n            text (Tensor):\n                Input text index tensor (T_text,).\n            feats (Tensor):\n                Feature tensor (T_feats, aux_channels).\n            pitch (Tensor):\n                Pitch tensor (T_feats, 1).\n            energy (Tensor): \n                Energy tensor (T_feats, 1).\n            use_alignment_module (bool):\n                Whether to use alignment module.\n        Returns:\n            Dict[str, Tensor]:\n                * wav (Tensor):\n                    Generated waveform tensor (T_wav,).\n                * duration (Tensor):\n                    Predicted duration tensor (T_text,).\n        \"\"\"\n        # setup\n        text = text[None]\n        text_lengths = paddle.to_tensor(paddle.shape(text)[1])\n\n        # inference\n        if use_alignment_module:\n            assert feats is not None\n            feats = feats[None]\n            feats_lengths = paddle.to_tensor(paddle.shape(feats)[1])\n            pitch = pitch[None]\n            energy = energy[None]\n            wav, dur = self.generator.inference(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                pitch=pitch,\n                energy=energy,\n                use_alignment_module=use_alignment_module,\n                **kwargs)\n        else:\n            wav, dur = self.generator.inference(\n                text=text,\n                text_lengths=text_lengths,\n                **kwargs, )\n        return dict(wav=paddle.reshape(wav, [-1]), duration=dur[0])\n\n    def reset_parameters(self):\n        def _reset_parameters(module):\n            if isinstance(\n                    module,\n                (nn.Conv1D, nn.Conv1DTranspose, nn.Conv2D, nn.Conv2DTranspose)):\n                kaiming_uniform_(module.weight, a=math.sqrt(5))\n                if module.bias is not None:\n                    fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n                    if fan_in != 0:\n                        bound = 1 / math.sqrt(fan_in)\n                        uniform_(module.bias, -bound, bound)\n\n            if isinstance(\n                    module,\n                (nn.BatchNorm1D, nn.BatchNorm2D, nn.GroupNorm, nn.LayerNorm)):\n                ones_(module.weight)\n                zeros_(module.bias)\n\n            if isinstance(module, nn.Linear):\n                kaiming_uniform_(module.weight, a=math.sqrt(5))\n                if module.bias is not None:\n                    fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n                    bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0\n                    uniform_(module.bias, -bound, bound)\n\n            if isinstance(module, nn.Embedding):\n                normal_(module.weight)\n                if module._padding_idx is not None:\n                    with paddle.no_grad():\n                        module.weight[module._padding_idx] = 0\n\n        self.apply(_reset_parameters)\n\n\nclass JETSInference(nn.Layer):\n    def __init__(self, model):\n        super().__init__()\n        self.acoustic_model = model\n\n    def forward(self, text, sids=None):\n        out = self.acoustic_model.inference(text)\n        wav = out['wav']\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/jets_updater.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in JETS.\n\nThis code is based on https://github.com/imdanboy/jets.\n\n\"\"\"\nimport logging\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.modules.nets_utils import get_segments\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass JETSUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_adv: float=1.0,\n                 lambda_mel: float=45.0,\n                 lambda_feat_match: float=2.0,\n                 lambda_var: float=1.0,\n                 lambda_align: float=2.0,\n                 generator_first: bool=False,\n                 use_alignment_module: bool=False,\n                 output_dir=None):\n        # it is designed to hold multiple models\n        # 因为输入的是单模型，但是没有用到父类的 init(), 所以需要重新写这部分\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        # self.model = model\n\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_mel = criterions['mel']\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n        self.criterion_var = criterions[\"var\"]\n        self.criterion_forwardsum = criterions[\"forwardsum\"]\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n\n        self.lambda_adv = lambda_adv\n        self.lambda_mel = lambda_mel\n        self.lambda_feat_match = lambda_feat_match\n        self.lambda_var = lambda_var\n        self.lambda_align = lambda_align\n\n        self.use_alignment_module = use_alignment_module\n\n        if generator_first:\n            self.turns = [\"generator\", \"discriminator\"]\n        else:\n            self.turns = [\"discriminator\", \"generator\"]\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        for turn in self.turns:\n            speech = batch[\"speech\"]\n            speech = speech.unsqueeze(1)\n            text_lengths = batch[\"text_lengths\"]\n            feats_lengths = batch[\"feats_lengths\"]\n            outs = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                feats=batch[\"feats\"],\n                feats_lengths=batch[\"feats_lengths\"],\n                durations=batch[\"durations\"],\n                durations_lengths=batch[\"durations_lengths\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                sids=batch.get(\"spk_id\", None),\n                spembs=batch.get(\"spk_emb\", None),\n                forward_generator=turn == \"generator\",\n                use_alignment_module=self.use_alignment_module)\n            # Generator\n            if turn == \"generator\":\n                # parse outputs\n                speech_hat_, bin_loss, log_p_attn, start_idxs, d_outs, ds, p_outs, ps, e_outs, es = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_)\n                with paddle.no_grad():\n                    # do not store discriminator gradient in generator turn\n                    p = self.model.discriminator(speech_)\n\n                # calculate losses\n                mel_loss = self.criterion_mel(speech_hat_, speech_)\n\n                adv_loss = self.criterion_gen_adv(p_hat)\n                feat_match_loss = self.criterion_feat_match(p_hat, p)\n                dur_loss, pitch_loss, energy_loss = self.criterion_var(\n                    d_outs, ds, p_outs, ps, e_outs, es, text_lengths)\n\n                mel_loss = mel_loss * self.lambda_mel\n                adv_loss = adv_loss * self.lambda_adv\n                feat_match_loss = feat_match_loss * self.lambda_feat_match\n                g_loss = mel_loss + adv_loss + feat_match_loss\n                var_loss = (\n                    dur_loss + pitch_loss + energy_loss) * self.lambda_var\n\n                gen_loss = g_loss + var_loss  #+ align_loss\n\n                report(\"train/generator_loss\", float(gen_loss))\n                report(\"train/generator_generator_loss\", float(g_loss))\n                report(\"train/generator_variance_loss\", float(var_loss))\n                report(\"train/generator_generator_mel_loss\", float(mel_loss))\n                report(\"train/generator_generator_adv_loss\", float(adv_loss))\n                report(\"train/generator_generator_feat_match_loss\",\n                       float(feat_match_loss))\n                report(\"train/generator_variance_dur_loss\", float(dur_loss))\n                report(\"train/generator_variance_pitch_loss\", float(pitch_loss))\n                report(\"train/generator_variance_energy_loss\",\n                       float(energy_loss))\n\n                losses_dict[\"generator_loss\"] = float(gen_loss)\n                losses_dict[\"generator_generator_loss\"] = float(g_loss)\n                losses_dict[\"generator_variance_loss\"] = float(var_loss)\n                losses_dict[\"generator_generator_mel_loss\"] = float(mel_loss)\n                losses_dict[\"generator_generator_adv_loss\"] = float(adv_loss)\n                losses_dict[\"generator_generator_feat_match_loss\"] = float(\n                    feat_match_loss)\n                losses_dict[\"generator_variance_dur_loss\"] = float(dur_loss)\n                losses_dict[\"generator_variance_pitch_loss\"] = float(pitch_loss)\n                losses_dict[\"generator_variance_energy_loss\"] = float(\n                    energy_loss)\n\n                if self.use_alignment_module == True:\n                    forwardsum_loss = self.criterion_forwardsum(\n                        log_p_attn, text_lengths, feats_lengths)\n                    align_loss = (\n                        forwardsum_loss + bin_loss) * self.lambda_align\n                    report(\"train/generator_alignment_loss\", float(align_loss))\n                    report(\"train/generator_alignment_forwardsum_loss\",\n                           float(forwardsum_loss))\n                    report(\"train/generator_alignment_bin_loss\",\n                           float(bin_loss))\n                    losses_dict[\"generator_alignment_loss\"] = float(align_loss)\n                    losses_dict[\"generator_alignment_forwardsum_loss\"] = float(\n                        forwardsum_loss)\n                    losses_dict[\"generator_alignment_bin_loss\"] = float(\n                        bin_loss)\n\n                self.optimizer_g.clear_grad()\n                gen_loss.backward()\n\n                self.optimizer_g.step()\n                self.scheduler_g.step()\n\n                # reset cache\n                if self.model.reuse_cache_gen or not self.model.training:\n                    self.model._cache = None\n\n            # Disctiminator\n            elif turn == \"discriminator\":\n                # parse outputs\n                speech_hat_, _, _, start_idxs, *_ = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_.detach())\n                p = self.model.discriminator(speech_)\n\n                # calculate losses\n                real_loss, fake_loss = self.criterion_dis_adv(p_hat, p)\n                dis_loss = real_loss + fake_loss\n\n                report(\"train/real_loss\", float(real_loss))\n                report(\"train/fake_loss\", float(fake_loss))\n                report(\"train/discriminator_loss\", float(dis_loss))\n                losses_dict[\"real_loss\"] = float(real_loss)\n                losses_dict[\"fake_loss\"] = float(fake_loss)\n                losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n                self.optimizer_d.clear_grad()\n                dis_loss.backward()\n\n                self.optimizer_d.step()\n                self.scheduler_d.step()\n\n                # reset cache\n                if self.model.reuse_cache_dis or not self.model.training:\n                    self.model._cache = None\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass JETSEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model,\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_adv: float=1.0,\n                 lambda_mel: float=45.0,\n                 lambda_feat_match: float=2.0,\n                 lambda_var: float=1.0,\n                 lambda_align: float=2.0,\n                 generator_first: bool=False,\n                 use_alignment_module: bool=False,\n                 output_dir=None):\n        # 因为输入的是单模型，但是没有用到父类的 init(), 所以需要重新写这部分\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        # self.model = model\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n\n        self.criterions = criterions\n        self.criterion_mel = criterions['mel']\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n        self.criterion_var = criterions[\"var\"]\n        self.criterion_forwardsum = criterions[\"forwardsum\"]\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_mel = lambda_mel\n        self.lambda_feat_match = lambda_feat_match\n        self.lambda_var = lambda_var\n        self.lambda_align = lambda_align\n        self.use_alignment_module = use_alignment_module\n\n        if generator_first:\n            self.turns = [\"generator\", \"discriminator\"]\n        else:\n            self.turns = [\"discriminator\", \"generator\"]\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        for turn in self.turns:\n            speech = batch[\"speech\"]\n            speech = speech.unsqueeze(1)\n            text_lengths = batch[\"text_lengths\"]\n            feats_lengths = batch[\"feats_lengths\"]\n            outs = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                feats=batch[\"feats\"],\n                feats_lengths=batch[\"feats_lengths\"],\n                durations=batch[\"durations\"],\n                durations_lengths=batch[\"durations_lengths\"],\n                pitch=batch[\"pitch\"],\n                energy=batch[\"energy\"],\n                sids=batch.get(\"spk_id\", None),\n                spembs=batch.get(\"spk_emb\", None),\n                forward_generator=turn == \"generator\",\n                use_alignment_module=self.use_alignment_module)\n            # Generator\n            if turn == \"generator\":\n                # parse outputs\n                speech_hat_, bin_loss, log_p_attn, start_idxs, d_outs, ds, p_outs, ps, e_outs, es = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_)\n                with paddle.no_grad():\n                    # do not store discriminator gradient in generator turn\n                    p = self.model.discriminator(speech_)\n\n                # calculate losses\n                mel_loss = self.criterion_mel(speech_hat_, speech_)\n\n                adv_loss = self.criterion_gen_adv(p_hat)\n                feat_match_loss = self.criterion_feat_match(p_hat, p)\n                dur_loss, pitch_loss, energy_loss = self.criterion_var(\n                    d_outs, ds, p_outs, ps, e_outs, es, text_lengths)\n\n                mel_loss = mel_loss * self.lambda_mel\n                adv_loss = adv_loss * self.lambda_adv\n                feat_match_loss = feat_match_loss * self.lambda_feat_match\n                g_loss = mel_loss + adv_loss + feat_match_loss\n                var_loss = (\n                    dur_loss + pitch_loss + energy_loss) * self.lambda_var\n\n                gen_loss = g_loss + var_loss  #+ align_loss\n\n                report(\"eval/generator_loss\", float(gen_loss))\n                report(\"eval/generator_generator_loss\", float(g_loss))\n                report(\"eval/generator_variance_loss\", float(var_loss))\n                report(\"eval/generator_generator_mel_loss\", float(mel_loss))\n                report(\"eval/generator_generator_adv_loss\", float(adv_loss))\n                report(\"eval/generator_generator_feat_match_loss\",\n                       float(feat_match_loss))\n                report(\"eval/generator_variance_dur_loss\", float(dur_loss))\n                report(\"eval/generator_variance_pitch_loss\", float(pitch_loss))\n                report(\"eval/generator_variance_energy_loss\",\n                       float(energy_loss))\n\n                losses_dict[\"generator_loss\"] = float(gen_loss)\n                losses_dict[\"generator_generator_loss\"] = float(g_loss)\n                losses_dict[\"generator_variance_loss\"] = float(var_loss)\n                losses_dict[\"generator_generator_mel_loss\"] = float(mel_loss)\n                losses_dict[\"generator_generator_adv_loss\"] = float(adv_loss)\n                losses_dict[\"generator_generator_feat_match_loss\"] = float(\n                    feat_match_loss)\n                losses_dict[\"generator_variance_dur_loss\"] = float(dur_loss)\n                losses_dict[\"generator_variance_pitch_loss\"] = float(pitch_loss)\n                losses_dict[\"generator_variance_energy_loss\"] = float(\n                    energy_loss)\n\n                if self.use_alignment_module == True:\n                    forwardsum_loss = self.criterion_forwardsum(\n                        log_p_attn, text_lengths, feats_lengths)\n                    align_loss = (\n                        forwardsum_loss + bin_loss) * self.lambda_align\n                    report(\"eval/generator_alignment_loss\", float(align_loss))\n                    report(\"eval/generator_alignment_forwardsum_loss\",\n                           float(forwardsum_loss))\n                    report(\"eval/generator_alignment_bin_loss\", float(bin_loss))\n                    losses_dict[\"generator_alignment_loss\"] = float(align_loss)\n                    losses_dict[\"generator_alignment_forwardsum_loss\"] = float(\n                        forwardsum_loss)\n                    losses_dict[\"generator_alignment_bin_loss\"] = float(\n                        bin_loss)\n\n                # reset cache\n                if self.model.reuse_cache_gen or not self.model.training:\n                    self.model._cache = None\n\n            # Disctiminator\n            elif turn == \"discriminator\":\n                # parse outputs\n                speech_hat_, _, _, start_idxs, *_ = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_.detach())\n                p = self.model.discriminator(speech_)\n\n                # calculate losses\n                real_loss, fake_loss = self.criterion_dis_adv(p_hat, p)\n                dis_loss = real_loss + fake_loss\n\n                report(\"eval/real_loss\", float(real_loss))\n                report(\"eval/fake_loss\", float(fake_loss))\n                report(\"eval/discriminator_loss\", float(dis_loss))\n                losses_dict[\"real_loss\"] = float(real_loss)\n                losses_dict[\"fake_loss\"] = float(fake_loss)\n                losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n                # reset cache\n                if self.model.reuse_cache_dis or not self.model.training:\n                    self.model._cache = None\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/jets/length_regulator.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in JETS.\n\nThis code is based on https://github.com/imdanboy/jets.\n\n\"\"\"\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\n\nclass GaussianUpsampling(nn.Layer):\n    \"\"\"\n    Gaussian upsampling with fixed temperature as in:\n    https://arxiv.org/abs/2010.04301\n    \"\"\"\n\n    def __init__(self, delta=0.1):\n        super().__init__()\n        self.delta = delta\n\n    def forward(self, hs, ds, h_masks=None, d_masks=None):\n        \"\"\"\n        Args:\n            hs (Tensor): Batched hidden state to be expanded (B, T_text, adim)\n            ds (Tensor): Batched token duration (B, T_text)\n            h_masks (Tensor): Mask tensor (B,T_feats)\n            d_masks (Tensor): Mask tensor (B,T_text)\n        Returns:\n            Tensor: Expanded hidden state (B, T_feat, adim)\n        \"\"\"\n        B = ds.shape[0]\n\n        if h_masks is None:\n            T_feats = paddle.to_tensor(ds.sum(), dtype=\"int32\")\n        else:\n            T_feats = h_masks.shape[-1]\n        t = paddle.to_tensor(\n            paddle.arange(0, T_feats).unsqueeze(0).tile([B, 1]),\n            dtype=\"float32\")\n        if h_masks is not None:\n            t = t * paddle.to_tensor(h_masks, dtype=\"float32\")\n\n        ds_cumsum = ds.cumsum(axis=-1)\n        ds_half = ds / 2\n        c = ds_cumsum.astype(ds_half.dtype) - ds_half\n        energy = -1 * self.delta * (t.unsqueeze(-1) - c.unsqueeze(1))**2\n        if d_masks is not None:\n            d_masks = ~(d_masks.unsqueeze(1))\n            d_masks.stop_gradient = True\n            d_masks = d_masks.tile([1, T_feats, 1])\n            energy = masked_fill(energy, d_masks, -float(\"inf\"))\n        p_attn = F.softmax(energy, axis=2)  # (B, T_feats, T_text)\n        hs = paddle.matmul(p_attn, hs)\n        return hs\n"
  },
  {
    "path": "paddlespeech/t2s/models/melgan/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .melgan import *\nfrom .multi_band_melgan_updater import *\nfrom .style_melgan import *\nfrom .style_melgan_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/melgan/melgan.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"MelGAN Modules.\"\"\"\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.causal_conv import CausalConv1D\nfrom paddlespeech.t2s.modules.causal_conv import CausalConv1DTranspose\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.pqmf import PQMF\nfrom paddlespeech.t2s.modules.residual_stack import ResidualStack\n\n\nclass MelGANGenerator(nn.Layer):\n    \"\"\"MelGAN generator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=80,\n            out_channels: int=1,\n            kernel_size: int=7,\n            channels: int=512,\n            bias: bool=True,\n            upsample_scales: List[int]=[8, 8, 2, 2],\n            stack_kernel_size: int=3,\n            stacks: int=3,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            pad: str=\"Pad1D\",\n            pad_params: Dict[str, Any]={\"mode\": \"reflect\"},\n            use_final_nonlinear_activation: bool=True,\n            use_weight_norm: bool=True,\n            use_causal_conv: bool=False,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initialize MelGANGenerator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels,\n                the number of sub-band is out_channels in multi-band melgan.\n            kernel_size (int): \n                Kernel size of initial and final conv layer.\n            channels (int): \n                Initial number of channels for conv layer.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            upsample_scales (List[int]): \n                List of upsampling scales.\n            stack_kernel_size (int): \n                Kernel size of dilated conv layers in residual stack.\n            stacks (int): \n                Number of stacks in a single residual stack.\n            nonlinear_activation (Optional[str], optional): \n                Non linear activation in upsample network, by default None\n            nonlinear_activation_params (Dict[str, Any], optional): \n                Parameters passed to the linear activation in the upsample network, by default {}\n            pad (str): \n                Padding function module name before dilated convolution layer.\n            pad_params (dict): \n                Hyperparameters for padding function.\n            use_final_nonlinear_activation (nn.Layer): \n                Activation function for the final layer.\n            use_weight_norm (bool): \n                Whether to use weight norm.\n                If set to true, it will be applied to all of the conv layers.\n            use_causal_conv (bool):\n                Whether to use causal convolution.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        # check hyper parameters is valid\n        assert channels >= np.prod(upsample_scales)\n        assert channels % (2**len(upsample_scales)) == 0\n        if not use_causal_conv:\n            assert (kernel_size - 1\n                    ) % 2 == 0, \"Not support even number kernel size.\"\n\n        layers = []\n        if not use_causal_conv:\n            layers += [\n                getattr(paddle.nn, pad)((kernel_size - 1) // 2, **pad_params),\n                nn.Conv1D(in_channels, channels, kernel_size, bias_attr=bias),\n            ]\n        else:\n            layers += [\n                CausalConv1D(\n                    in_channels,\n                    channels,\n                    kernel_size,\n                    bias=bias,\n                    pad=pad,\n                    pad_params=pad_params, ),\n            ]\n\n        for i, upsample_scale in enumerate(upsample_scales):\n            # add upsampling layer\n            layers += [\n                get_activation(nonlinear_activation,\n                               **nonlinear_activation_params)\n            ]\n            if not use_causal_conv:\n                layers += [\n                    nn.Conv1DTranspose(\n                        channels // (2**i),\n                        channels // (2**(i + 1)),\n                        upsample_scale * 2,\n                        stride=upsample_scale,\n                        padding=upsample_scale // 2 + upsample_scale % 2,\n                        output_padding=upsample_scale % 2,\n                        bias_attr=bias, )\n                ]\n            else:\n                layers += [\n                    CausalConv1DTranspose(\n                        channels // (2**i),\n                        channels // (2**(i + 1)),\n                        upsample_scale * 2,\n                        stride=upsample_scale,\n                        bias=bias, )\n                ]\n\n            # add residual stack\n            for j in range(stacks):\n                layers += [\n                    ResidualStack(\n                        kernel_size=stack_kernel_size,\n                        channels=channels // (2**(i + 1)),\n                        dilation=stack_kernel_size**j,\n                        bias=bias,\n                        nonlinear_activation=nonlinear_activation,\n                        nonlinear_activation_params=nonlinear_activation_params,\n                        pad=pad,\n                        pad_params=pad_params,\n                        use_causal_conv=use_causal_conv, )\n                ]\n\n        # add final layer\n        layers += [\n            get_activation(nonlinear_activation, **nonlinear_activation_params)\n        ]\n        if not use_causal_conv:\n            layers += [\n                getattr(nn, pad)((kernel_size - 1) // 2, **pad_params),\n                nn.Conv1D(\n                    channels // (2**(i + 1)),\n                    out_channels,\n                    kernel_size,\n                    bias_attr=bias),\n            ]\n        else:\n            layers += [\n                CausalConv1D(\n                    channels // (2**(i + 1)),\n                    out_channels,\n                    kernel_size,\n                    bias=bias,\n                    pad=pad,\n                    pad_params=pad_params, ),\n            ]\n        if use_final_nonlinear_activation:\n            layers += [nn.Tanh()]\n\n        # define the model as a single function        \n        self.melgan = nn.Sequential(*layers)\n        nn.initializer.set_global_initializer(None)\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # reset parameters\n        self.reset_parameters()\n\n        # initialize pqmf for multi-band melgan inference\n        if out_channels > 1:\n            self.pqmf = PQMF(subbands=out_channels)\n        else:\n            self.pqmf = None\n\n    def forward(self, c):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            c (Tensor): \n                Input tensor (B, in_channels, T).\n        Returns:\n            Tensor: Output tensor (B, out_channels, T ** prod(upsample_scales)).\n        \"\"\"\n        out = self.melgan(c)\n        return out\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\n        This initialization follows official implementation manner.\n        https://github.com/descriptinc/melgan-neurips/blob/master/mel2wav/modules.py\n        \"\"\"\n        # 定义参数为float的正态分布。\n        dist = paddle.distribution.Normal(loc=0.0, scale=0.02)\n\n        def _reset_parameters(m):\n            if isinstance(m, nn.Conv1D) or isinstance(m, nn.Conv1DTranspose):\n                w = dist.sample(m.weight.shape)\n                m.weight.set_value(w)\n\n        self.apply(_reset_parameters)\n\n    def inference(self, c):\n        \"\"\"Perform inference.\n\n        Args:\n            c (Union[Tensor, ndarray]): \n                Input tensor (T, in_channels).\n        Returns:\n            Tensor: Output tensor (out_channels*T ** prod(upsample_scales), 1).\n        \"\"\"\n        # pseudo batch\n        c = c.transpose([1, 0]).unsqueeze(0)\n        # (B, out_channels, T ** prod(upsample_scales)\n        out = self.melgan(c)\n        if self.pqmf is not None:\n            # (B, 1, out_channels * T ** prod(upsample_scales)\n            out = self.pqmf(out)\n        out = out.squeeze(0).transpose([1, 0])\n        return out\n\n\nclass MelGANDiscriminator(nn.Layer):\n    \"\"\"MelGAN discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_sizes: List[int]=[5, 3],\n            channels: int=16,\n            max_downsample_channels: int=1024,\n            bias: bool=True,\n            downsample_scales: List[int]=[4, 4, 4, 4],\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            pad: str=\"Pad1D\",\n            pad_params: Dict[str, Any]={\"mode\": \"reflect\"},\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize MelGAN discriminator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels.\n            kernel_sizes (List[int]): List of two kernel sizes. The prod will be used for the first conv layer,\n                and the first and the second kernel sizes will be used for the last two layers.\n                For example if kernel_sizes = [5, 3], the first layer kernel size will be 5 * 3 = 15,\n                the last two layers' kernel size will be 5 and 3, respectively.\n            channels (int): \n                Initial number of channels for conv layer.\n            max_downsample_channels (int): \n                Maximum number of channels for downsampling layers.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            downsample_scales (List[int]): \n                List of downsampling scales.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n            pad (str): \n                Padding function module name before dilated convolution layer.\n            pad_params (dict): \n                Hyperparameters for padding function.\n        \"\"\"\n        super().__init__()\n\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.layers = nn.LayerList()\n\n        # check kernel size is valid\n        assert len(kernel_sizes) == 2\n        assert kernel_sizes[0] % 2 == 1\n        assert kernel_sizes[1] % 2 == 1\n\n        # add first layer\n        self.layers.append(\n            nn.Sequential(\n                getattr(nn, pad)((np.prod(kernel_sizes) - 1) // 2, **\n                                 pad_params),\n                nn.Conv1D(\n                    in_channels,\n                    channels,\n                    int(np.prod(kernel_sizes)),\n                    bias_attr=bias),\n                get_activation(nonlinear_activation, **\n                               nonlinear_activation_params), ))\n\n        # add downsample layers\n        in_chs = channels\n        for downsample_scale in downsample_scales:\n            out_chs = min(in_chs * downsample_scale, max_downsample_channels)\n            self.layers.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        in_chs,\n                        out_chs,\n                        kernel_size=downsample_scale * 10 + 1,\n                        stride=downsample_scale,\n                        padding=downsample_scale * 5,\n                        groups=in_chs // 4,\n                        bias_attr=bias, ),\n                    get_activation(nonlinear_activation, **\n                                   nonlinear_activation_params), ))\n            in_chs = out_chs\n\n        # add final layers\n        out_chs = min(in_chs * 2, max_downsample_channels)\n        self.layers.append(\n            nn.Sequential(\n                nn.Conv1D(\n                    in_chs,\n                    out_chs,\n                    kernel_sizes[0],\n                    padding=(kernel_sizes[0] - 1) // 2,\n                    bias_attr=bias, ),\n                get_activation(nonlinear_activation, **\n                               nonlinear_activation_params), ))\n        self.layers.append(\n            nn.Conv1D(\n                out_chs,\n                out_channels,\n                kernel_sizes[1],\n                padding=(kernel_sizes[1] - 1) // 2,\n                bias_attr=bias, ), )\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input noise signal (B, 1, T).\n        Returns:\n            List: List of output tensors of each layer (for feat_match_loss).\n        \"\"\"\n        outs = []\n        for f in self.layers:\n            x = f(x)\n            outs += [x]\n\n        return outs\n\n\nclass MelGANMultiScaleDiscriminator(nn.Layer):\n    \"\"\"MelGAN multi-scale discriminator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            scales: int=3,\n            downsample_pooling: str=\"AvgPool1D\",\n            # follow the official implementation setting\n            downsample_pooling_params: Dict[str, Any]={\n                \"kernel_size\": 4,\n                \"stride\": 2,\n                \"padding\": 1,\n                \"exclusive\": True,\n            },\n            kernel_sizes: List[int]=[5, 3],\n            channels: int=16,\n            max_downsample_channels: int=1024,\n            bias: bool=True,\n            downsample_scales: List[int]=[4, 4, 4, 4],\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            pad: str=\"Pad1D\",\n            pad_params: Dict[str, Any]={\"mode\": \"reflect\"},\n            use_weight_norm: bool=True,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize MelGAN multi-scale discriminator module.\n\n        Args:\n            in_channels (int): \n                Number of input channels.\n            out_channels (int): \n                Number of output channels.\n            scales (int): \n                Number of multi-scales.\n            downsample_pooling (str): \n                Pooling module name for downsampling of the inputs.\n            downsample_pooling_params (dict): \n                Parameters for the above pooling module.\n            kernel_sizes (List[int]): \n                List of two kernel sizes. The sum will be used for the first conv layer,\n                and the first and the second kernel sizes will be used for the last two layers.\n            channels (int): \n                Initial number of channels for conv layer.\n            max_downsample_channels (int): \n                Maximum number of channels for downsampling layers.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            downsample_scales (List[int]): \n                List of downsampling scales.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n            pad (str): \n                Padding function module name before dilated convolution layer.\n            pad_params (dict): \n                Hyperparameters for padding function.\n            use_causal_conv (bool): \n                Whether to use causal convolution.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # for \n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        self.discriminators = nn.LayerList()\n\n        # add discriminators\n        for _ in range(scales):\n            self.discriminators.append(\n                MelGANDiscriminator(\n                    in_channels=in_channels,\n                    out_channels=out_channels,\n                    kernel_sizes=kernel_sizes,\n                    channels=channels,\n                    max_downsample_channels=max_downsample_channels,\n                    bias=bias,\n                    downsample_scales=downsample_scales,\n                    nonlinear_activation=nonlinear_activation,\n                    nonlinear_activation_params=nonlinear_activation_params,\n                    pad=pad,\n                    pad_params=pad_params, ))\n        self.pooling = getattr(nn, downsample_pooling)(\n            **downsample_pooling_params)\n\n        nn.initializer.set_global_initializer(None)\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # reset parameters\n        self.reset_parameters()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input noise signal (B, 1, T).\n        Returns:\n            List: List of list of each discriminator outputs, which consists of each layer output tensors.\n        \"\"\"\n        outs = []\n        for f in self.discriminators:\n            outs += [f(x)]\n            x = self.pooling(x)\n\n        return outs\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\n        This initialization follows official implementation manner.\n        https://github.com/descriptinc/melgan-neurips/blob/master/mel2wav/modules.py\n        \"\"\"\n\n        # 定义参数为float的正态分布。\n        dist = paddle.distribution.Normal(loc=0.0, scale=0.02)\n\n        def _reset_parameters(m):\n            if isinstance(m, nn.Conv1D) or isinstance(m, nn.Conv1DTranspose):\n                w = dist.sample(m.weight.shape)\n                m.weight.set_value(w)\n\n        self.apply(_reset_parameters)\n\n\nclass MelGANInference(nn.Layer):\n    def __init__(self, normalizer, melgan_generator):\n        super().__init__()\n        self.normalizer = normalizer\n        self.melgan_generator = melgan_generator\n\n    def forward(self, logmel):\n        normalized_mel = self.normalizer(logmel)\n        wav = self.melgan_generator.inference(normalized_mel)\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/melgan/multi_band_melgan_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass MBMelGANUpdater(StandardUpdater):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_aux: float=1.0,\n                 lambda_adv: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator: Layer = models['generator']\n        self.discriminator: Layer = models['discriminator']\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_sub_stft = criterions['sub_stft']\n        self.criterion_pqmf = criterions['pqmf']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        wav, mel = batch\n\n        # Generator\n        if self.state.iteration > self.generator_train_start_steps:\n            # (B, out_channels, T ** prod(upsample_scales)\n            wav_ = self.generator(mel)\n            wav_mb_ = wav_\n            # (B, 1, out_channels*T ** prod(upsample_scales)\n            wav_ = self.criterion_pqmf.synthesis(wav_mb_)\n\n            # initialize\n            gen_loss = 0.0\n            aux_loss = 0.0\n\n            # full band Multi-resolution stft loss\n            sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n            # for balancing with subband stft loss\n            # Eq.(9) in paper\n            aux_loss += 0.5 * (sc_loss + mag_loss)\n            report(\"train/spectral_convergence_loss\", float(sc_loss))\n            report(\"train/log_stft_magnitude_loss\", float(mag_loss))\n            losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n            losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n\n            # sub band Multi-resolution stft loss\n            # (B, subbands, T // subbands)\n            wav_mb = self.criterion_pqmf.analysis(wav)\n            sub_sc_loss, sub_mag_loss = self.criterion_sub_stft(wav_mb_, wav_mb)\n            # Eq.(9) in paper\n            aux_loss += 0.5 * (sub_sc_loss + sub_mag_loss)\n            report(\"train/sub_spectral_convergence_loss\", float(sub_sc_loss))\n            report(\"train/sub_log_stft_magnitude_loss\", float(sub_mag_loss))\n            losses_dict[\"sub_spectral_convergence_loss\"] = float(sub_sc_loss)\n            losses_dict[\"sub_log_stft_magnitude_loss\"] = float(sub_mag_loss)\n\n            gen_loss += aux_loss * self.lambda_aux\n\n            # adversarial loss\n            if self.state.iteration > self.discriminator_train_start_steps:\n                p_ = self.discriminator(wav_)\n                adv_loss = self.criterion_gen_adv(p_)\n                report(\"train/adversarial_loss\", float(adv_loss))\n                losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n                gen_loss += self.lambda_adv * adv_loss\n\n            report(\"train/generator_loss\", float(gen_loss))\n            losses_dict[\"generator_loss\"] = float(gen_loss)\n\n            self.optimizer_g.clear_grad()\n            gen_loss.backward()\n\n            self.optimizer_g.step()\n            self.scheduler_g.step()\n\n        # Disctiminator\n        if self.state.iteration > self.discriminator_train_start_steps:\n            # re-compute wav_ which leads better quality\n            with paddle.no_grad():\n                wav_ = self.generator(mel)\n            wav_ = self.criterion_pqmf.synthesis(wav_)\n            p = self.discriminator(wav)\n            p_ = self.discriminator(wav_.detach())\n            real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n            dis_loss = real_loss + fake_loss\n            report(\"train/real_loss\", float(real_loss))\n            report(\"train/fake_loss\", float(fake_loss))\n            report(\"train/discriminator_loss\", float(dis_loss))\n            losses_dict[\"real_loss\"] = float(real_loss)\n            losses_dict[\"fake_loss\"] = float(fake_loss)\n            losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n            self.optimizer_d.clear_grad()\n            dis_loss.backward()\n\n            self.optimizer_d.step()\n            self.scheduler_d.step()\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass MBMelGANEvaluator(StandardEvaluator):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_aux: float=1.0,\n                 lambda_adv: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator = models['generator']\n        self.discriminator = models['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_sub_stft = criterions['sub_stft']\n        self.criterion_pqmf = criterions['pqmf']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        wav, mel = batch\n\n        # Generator\n        # (B, out_channels, T ** prod(upsample_scales)\n        wav_ = self.generator(mel)\n        wav_mb_ = wav_\n        # (B, 1, out_channels*T ** prod(upsample_scales)\n        wav_ = self.criterion_pqmf.synthesis(wav_mb_)\n\n        # initialize\n        gen_loss = 0.0\n        aux_loss = 0.0\n\n        # adversarial loss\n        p_ = self.discriminator(wav_)\n        adv_loss = self.criterion_gen_adv(p_)\n        report(\"eval/adversarial_loss\", float(adv_loss))\n        losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n        gen_loss += self.lambda_adv * adv_loss\n\n        # Multi-resolution stft loss\n        sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n        # Eq.(9) in paper\n        aux_loss += 0.5 * (sc_loss + mag_loss)\n        report(\"eval/spectral_convergence_loss\", float(sc_loss))\n        report(\"eval/log_stft_magnitude_loss\", float(mag_loss))\n        losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n        losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n\n        # sub band Multi-resolution stft loss\n        # (B, subbands, T // subbands)\n        wav_mb = self.criterion_pqmf.analysis(wav)\n        sub_sc_loss, sub_mag_loss = self.criterion_sub_stft(wav_mb_, wav_mb)\n        # Eq.(9) in paper\n        aux_loss += 0.5 * (sub_sc_loss + sub_mag_loss)\n        report(\"eval/sub_spectral_convergence_loss\", float(sub_sc_loss))\n        report(\"eval/sub_log_stft_magnitude_loss\", float(sub_mag_loss))\n        losses_dict[\"sub_spectral_convergence_loss\"] = float(sub_sc_loss)\n        losses_dict[\"sub_log_stft_magnitude_loss\"] = float(sub_mag_loss)\n\n        gen_loss += aux_loss * self.lambda_aux\n\n        report(\"eval/generator_loss\", float(gen_loss))\n        losses_dict[\"generator_loss\"] = float(gen_loss)\n\n        # Disctiminator\n        p = self.discriminator(wav)\n        real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n        dis_loss = real_loss + fake_loss\n        report(\"eval/real_loss\", float(real_loss))\n        report(\"eval/fake_loss\", float(fake_loss))\n        report(\"eval/discriminator_loss\", float(dis_loss))\n\n        losses_dict[\"real_loss\"] = float(real_loss)\n        losses_dict[\"fake_loss\"] = float(fake_loss)\n        losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/melgan/style_melgan.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"StyleMelGAN Modules.\"\"\"\nimport copy\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.melgan import MelGANDiscriminator as BaseDiscriminator\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.pqmf import PQMF\nfrom paddlespeech.t2s.modules.tade_res_block import TADEResBlock\n\n\nclass StyleMelGANGenerator(nn.Layer):\n    \"\"\"Style MelGAN generator module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=128,\n            aux_channels: int=80,\n            channels: int=64,\n            out_channels: int=1,\n            kernel_size: int=9,\n            dilation: int=2,\n            bias: bool=True,\n            noise_upsample_scales: List[int]=[11, 2, 2, 2],\n            noise_upsample_activation: str=\"leakyrelu\",\n            noise_upsample_activation_params: Dict[str,\n                                                   Any]={\"negative_slope\": 0.2},\n            upsample_scales: List[int]=[2, 2, 2, 2, 2, 2, 2, 2, 1],\n            upsample_mode: str=\"linear\",\n            gated_function: str=\"softmax\",\n            use_weight_norm: bool=True,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize Style MelGAN generator.\n\n        Args:\n            in_channels (int): \n                Number of input noise channels.\n            aux_channels (int): \n                Number of auxiliary input channels.\n            channels (int): \n                Number of channels for conv layer.\n            out_channels (int): \n                Number of output channels.\n            kernel_size (int): \n                Kernel size of conv layers.\n            dilation (int): \n                Dilation factor for conv layers.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            noise_upsample_scales (list): \n                List of noise upsampling scales.\n            noise_upsample_activation (str): \n                Activation function module name for noise upsampling.\n            noise_upsample_activation_params (dict): \n                Hyperparameters for the above activation function.\n            upsample_scales (list): \n                List of upsampling scales.\n            upsample_mode (str): \n                Upsampling mode in TADE layer.\n            gated_function (str): \n                Gated function in TADEResBlock (\"softmax\" or \"sigmoid\").\n            use_weight_norm (bool): \n                Whether to use weight norm.\n                If set to true, it will be applied to all of the conv layers.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.in_channels = in_channels\n        noise_upsample = []\n        in_chs = in_channels\n        for noise_upsample_scale in noise_upsample_scales:\n            noise_upsample.append(\n                nn.Conv1DTranspose(\n                    in_chs,\n                    channels,\n                    noise_upsample_scale * 2,\n                    stride=noise_upsample_scale,\n                    padding=noise_upsample_scale // 2 + noise_upsample_scale %\n                    2,\n                    output_padding=noise_upsample_scale % 2,\n                    bias_attr=bias, ))\n            noise_upsample.append(\n                get_activation(noise_upsample_activation, **\n                               noise_upsample_activation_params))\n            in_chs = channels\n        self.noise_upsample = nn.Sequential(*noise_upsample)\n        self.noise_upsample_factor = np.prod(noise_upsample_scales)\n\n        self.blocks = nn.LayerList()\n        aux_chs = aux_channels\n        for upsample_scale in upsample_scales:\n            self.blocks.append(\n                TADEResBlock(\n                    in_channels=channels,\n                    aux_channels=aux_chs,\n                    kernel_size=kernel_size,\n                    dilation=dilation,\n                    bias=bias,\n                    upsample_factor=upsample_scale,\n                    upsample_mode=upsample_mode,\n                    gated_function=gated_function, ), )\n            aux_chs = channels\n        self.upsample_factor = np.prod(upsample_scales)\n\n        self.output_conv = nn.Sequential(\n            nn.Conv1D(\n                channels,\n                out_channels,\n                kernel_size,\n                1,\n                bias_attr=bias,\n                padding=(kernel_size - 1) // 2, ),\n            nn.Tanh(), )\n\n        nn.initializer.set_global_initializer(None)\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # reset parameters\n        self.reset_parameters()\n\n    def forward(self, c, z=None):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            c (Tensor): Auxiliary input tensor (B, channels, T).\n            z (Tensor): Input noise tensor (B, in_channels, 1).\n        Returns:\n            Tensor: Output tensor (B, out_channels, T ** prod(upsample_scales)).\n        \"\"\"\n        # batch_max_steps(24000) == noise_upsample_factor(80) * upsample_factor(300)\n        if z is None:\n            z = paddle.randn([paddle.shape(c)[0], self.in_channels, 1])\n        # (B, in_channels, noise_upsample_factor).\n        x = self.noise_upsample(z)\n        for block in self.blocks:\n            x, c = block(x, c)\n        x = self.output_conv(x)\n        return x\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                if layer:\n                    nn.utils.remove_weight_norm(layer)\n            # add AttributeError to bypass https://github.com/PaddlePaddle/Paddle/issues/38532 temporarily\n            except (ValueError, AttributeError):\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\n        This initialization follows official implementation manner.\n        https://github.com/descriptinc/melgan-neurips/blob/master/mel2wav/modules.py\n        \"\"\"\n        # 定义参数为float的正态分布。\n        dist = paddle.distribution.Normal(loc=0.0, scale=0.02)\n\n        def _reset_parameters(m):\n            if isinstance(m, nn.Conv1D) or isinstance(m, nn.Conv1DTranspose):\n                w = dist.sample(m.weight.shape)\n                m.weight.set_value(w)\n\n        self.apply(_reset_parameters)\n\n    def inference(self, c):\n        \"\"\"Perform inference.\n        Args:\n            c (Tensor): \n                Input tensor (T, in_channels).\n        Returns:\n            Tensor: Output tensor (T ** prod(upsample_scales), out_channels).\n        \"\"\"\n        # (1, in_channels, T)\n        c = c.transpose([1, 0]).unsqueeze(0)\n        c_shape = paddle.shape(c)\n        # prepare noise input\n        # there is a bug in Paddle int division, we must convert a int tensor to int here\n        noise_T = paddle.cast(\n            paddle.ceil(c_shape[2] / int(self.noise_upsample_factor)),\n            dtype='int64')\n        noise_size = (1, self.in_channels, noise_T)\n        # (1, in_channels, T/noise_upsample_factor)\n        noise = paddle.randn(noise_size)\n        # (1, in_channels, T)\n        x = self.noise_upsample(noise)\n        x_shape = paddle.shape(x)\n        total_length = c_shape[2] * self.upsample_factor\n        # Dygraph to Static Graph bug here, 2021.12.15\n        c = F.pad(\n            c, (0, x_shape[2] - c_shape[2]), \"replicate\", data_format=\"NCL\")\n        # \bc.shape[2] == x.shape[2] here\n        # (1, in_channels, T*prod(upsample_scales))\n        for block in self.blocks:\n            x, c = block(x, c)\n        x = self.output_conv(x)[..., :total_length]\n        return x.squeeze(0).transpose([1, 0])\n\n\nclass StyleMelGANDiscriminator(nn.Layer):\n    \"\"\"Style MelGAN disciminator module.\"\"\"\n\n    def __init__(\n            self,\n            repeats: int=2,\n            window_sizes: List[int]=[512, 1024, 2048, 4096],\n            pqmf_params: List[List[int]]=[\n                [1, None, None, None],\n                [2, 62, 0.26700, 9.0],\n                [4, 62, 0.14200, 9.0],\n                [8, 62, 0.07949, 9.0],\n            ],\n            discriminator_params: Dict[str, Any]={\n                \"out_channels\": 1,\n                \"kernel_sizes\": [5, 3],\n                \"channels\": 16,\n                \"max_downsample_channels\": 512,\n                \"bias\": True,\n                \"downsample_scales\": [4, 4, 4, 1],\n                \"nonlinear_activation\": \"leakyrelu\",\n                \"nonlinear_activation_params\": {\n                    \"negative_slope\": 0.2\n                },\n                \"pad\": \"Pad1D\",\n                \"pad_params\": {\n                    \"mode\": \"reflect\"\n                },\n            },\n            use_weight_norm: bool=True,\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initilize Style MelGAN discriminator.\n\n        Args:\n            repeats (int): \n                Number of repititons to apply RWD.\n            window_sizes (list): \n                List of random window sizes.\n            pqmf_params (list): \n                List of list of Parameters for PQMF modules\n            discriminator_params (dict): \n                Parameters for base discriminator module.\n            use_weight_nom (bool): \n                Whether to apply weight normalization.\n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # window size check\n        assert len(window_sizes) == len(pqmf_params)\n        sizes = [ws // p[0] for ws, p in zip(window_sizes, pqmf_params)]\n        assert len(window_sizes) == sum([sizes[0] == size for size in sizes])\n\n        self.repeats = repeats\n        self.window_sizes = window_sizes\n        self.pqmfs = nn.LayerList()\n        self.discriminators = nn.LayerList()\n        for pqmf_param in pqmf_params:\n            d_params = copy.deepcopy(discriminator_params)\n            d_params[\"in_channels\"] = pqmf_param[0]\n            if pqmf_param[0] == 1:\n                self.pqmfs.append(nn.Identity())\n            else:\n                self.pqmfs.append(PQMF(*pqmf_param))\n            self.discriminators.append(BaseDiscriminator(**d_params))\n\n        nn.initializer.set_global_initializer(None)\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n        # reset parameters\n        self.reset_parameters()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input tensor (B, 1, T).\n        Returns:\n            List: List of discriminator outputs, #items in the list will be\n                equal to repeats * #discriminators.\n        \"\"\"\n        outs = []\n        for _ in range(self.repeats):\n            outs += self._forward(x)\n        return outs\n\n    def _forward(self, x):\n        outs = []\n        for idx, (ws, pqmf, disc) in enumerate(\n                zip(self.window_sizes, self.pqmfs, self.discriminators)):\n            start_idx = int(np.random.randint(paddle.shape(x)[-1] - ws))\n            x_ = x[:, :, start_idx:start_idx + ws]\n            if idx == 0:\n                # nn.Identity()\n                x_ = pqmf(x_)\n            else:\n                x_ = pqmf.analysis(x_)\n            outs += [disc(x_)]\n        return outs\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv1DTranspose)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\n        This initialization follows official implementation manner.\n        https://github.com/descriptinc/melgan-neurips/blob/master/mel2wav/modules.py\n        \"\"\"\n        # 定义参数为float的正态分布。\n        dist = paddle.distribution.Normal(loc=0.0, scale=0.02)\n\n        def _reset_parameters(m):\n            if isinstance(m, nn.Conv1D) or isinstance(m, nn.Conv1DTranspose):\n                w = dist.sample(m.weight.shape)\n                m.weight.set_value(w)\n\n        self.apply(_reset_parameters)\n\n\nclass StyleMelGANInference(nn.Layer):\n    def __init__(self, normalizer, style_melgan_generator):\n        super().__init__()\n        self.normalizer = normalizer\n        self.style_melgan_generator = style_melgan_generator\n\n    def forward(self, logmel):\n        normalized_mel = self.normalizer(logmel)\n        wav = self.style_melgan_generator.inference(normalized_mel)\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/melgan/style_melgan_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass StyleMelGANUpdater(StandardUpdater):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator: Layer = models['generator']\n        self.discriminator: Layer = models['discriminator']\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        wav, mel = batch\n\n        # Generator\n        if self.state.iteration > self.generator_train_start_steps:\n            # (B, out_channels, T ** prod(upsample_scales)\n            wav_ = self.generator(mel)\n\n            # initialize\n            gen_loss = 0.0\n            aux_loss = 0.0\n\n            # full band multi-resolution stft loss\n            sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n            aux_loss += sc_loss + mag_loss\n            report(\"train/spectral_convergence_loss\", float(sc_loss))\n            report(\"train/log_stft_magnitude_loss\", float(mag_loss))\n            losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n            losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n\n            gen_loss += aux_loss * self.lambda_aux\n\n            # adversarial loss\n            if self.state.iteration > self.discriminator_train_start_steps:\n                p_ = self.discriminator(wav_)\n                adv_loss = self.criterion_gen_adv(p_)\n                report(\"train/adversarial_loss\", float(adv_loss))\n                losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n                gen_loss += self.lambda_adv * adv_loss\n\n            report(\"train/generator_loss\", float(gen_loss))\n            losses_dict[\"generator_loss\"] = float(gen_loss)\n\n            self.optimizer_g.clear_grad()\n            gen_loss.backward()\n\n            self.optimizer_g.step()\n            self.scheduler_g.step()\n\n        # Disctiminator\n        if self.state.iteration > self.discriminator_train_start_steps:\n            # re-compute wav_ which leads better quality\n            with paddle.no_grad():\n                wav_ = self.generator(mel)\n\n            p = self.discriminator(wav)\n            p_ = self.discriminator(wav_.detach())\n            real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n            dis_loss = real_loss + fake_loss\n            report(\"train/real_loss\", float(real_loss))\n            report(\"train/fake_loss\", float(fake_loss))\n            report(\"train/discriminator_loss\", float(dis_loss))\n            losses_dict[\"real_loss\"] = float(real_loss)\n            losses_dict[\"fake_loss\"] = float(fake_loss)\n            losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n            self.optimizer_d.clear_grad()\n            dis_loss.backward()\n\n            self.optimizer_d.step()\n            self.scheduler_d.step()\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass StyleMelGANEvaluator(StandardEvaluator):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator = models['generator']\n        self.discriminator = models['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        wav, mel = batch\n\n        # Generator\n        # (B, out_channels, T ** prod(upsample_scales)\n        wav_ = self.generator(mel)\n\n        # initialize\n        gen_loss = 0.0\n        aux_loss = 0.0\n\n        # adversarial loss\n        p_ = self.discriminator(wav_)\n        adv_loss = self.criterion_gen_adv(p_)\n        report(\"eval/adversarial_loss\", float(adv_loss))\n        losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n        gen_loss += self.lambda_adv * adv_loss\n\n        # multi-resolution stft loss\n        sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n        aux_loss += sc_loss + mag_loss\n        report(\"eval/spectral_convergence_loss\", float(sc_loss))\n        report(\"eval/log_stft_magnitude_loss\", float(mag_loss))\n        losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n        losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n\n        gen_loss += aux_loss * self.lambda_aux\n\n        report(\"eval/generator_loss\", float(gen_loss))\n        losses_dict[\"generator_loss\"] = float(gen_loss)\n\n        # Disctiminator\n        p = self.discriminator(wav)\n        real_loss, fake_loss = self.criterion_dis_adv(p_, p)\n        dis_loss = real_loss + fake_loss\n        report(\"eval/real_loss\", float(real_loss))\n        report(\"eval/fake_loss\", float(fake_loss))\n        report(\"eval/discriminator_loss\", float(dis_loss))\n\n        losses_dict[\"real_loss\"] = float(real_loss)\n        losses_dict[\"fake_loss\"] = float(fake_loss)\n        losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/parallel_wavegan/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .parallel_wavegan import *\nfrom .parallel_wavegan_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/parallel_wavegan/parallel_wavegan.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport math\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.residual_block import WaveNetResidualBlock as ResidualBlock\nfrom paddlespeech.t2s.modules.upsample import ConvInUpsampleNet\n\n\nclass PWGGenerator(nn.Layer):\n    \"\"\"Wave Generator for Parallel WaveGAN\n\n    Args:\n        in_channels (int, optional): \n            Number of channels of the input waveform, by default 1\n        out_channels (int, optional): \n            Number of channels of the output waveform, by default 1\n        kernel_size (int, optional): \n            Kernel size of the residual blocks inside, by default 3\n        layers (int, optional): \n            Number of residual blocks inside, by default 30\n        stacks (int, optional):\n            The number of groups to split the residual blocks into, by default 3\n            Within each group, the dilation of the residual block grows exponentially.\n        residual_channels (int, optional): \n            Residual channel of the residual blocks, by default 64\n        gate_channels (int, optional): \n            Gate channel of the residual blocks, by default 128\n        skip_channels (int, optional): \n            Skip channel of the residual blocks, by default 64\n        aux_channels (int, optional): \n            Auxiliary channel of the residual blocks, by default 80\n        aux_context_window (int, optional): \n            The context window size of the first convolution applied to the auxiliary input, by default 2\n        dropout (float, optional): \n            Dropout of the residual blocks, by default 0.\n        bias (bool, optional): \n            Whether to use bias in residual blocks, by default True\n        use_weight_norm (bool, optional): \n            Whether to use weight norm in all convolutions, by default True\n        use_causal_conv (bool, optional): \n            Whether to use causal padding in the upsample network and residual blocks, by default False\n        upsample_scales (List[int], optional): \n            Upsample scales of the upsample network, by default [4, 4, 4, 4]\n        nonlinear_activation (Optional[str], optional): \n            Non linear activation in upsample network, by default None\n        nonlinear_activation_params (Dict[str, Any], optional): \n            Parameters passed to the linear activation in the upsample network, by default {}\n        interpolate_mode (str, optional): \n            Interpolation mode of the upsample network, by default \"nearest\"\n        freq_axis_kernel_size (int, optional): \n            Kernel size along the frequency axis of the upsample network, by default 1\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_size: int=3,\n            layers: int=30,\n            stacks: int=3,\n            residual_channels: int=64,\n            gate_channels: int=128,\n            skip_channels: int=64,\n            aux_channels: int=80,\n            aux_context_window: int=2,\n            dropout: float=0.,\n            bias: bool=True,\n            use_weight_norm: bool=True,\n            use_causal_conv: bool=False,\n            upsample_scales: List[int]=[4, 4, 4, 4],\n            nonlinear_activation: Optional[str]=None,\n            nonlinear_activation_params: Dict[str, Any]={},\n            interpolate_mode: str=\"nearest\",\n            freq_axis_kernel_size: int=1,\n            init_type: str=\"xavier_uniform\", ):\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.aux_channels = aux_channels\n        self.aux_context_window = aux_context_window\n        self.layers = layers\n        self.stacks = stacks\n        self.kernel_size = kernel_size\n\n        assert layers % stacks == 0\n        layers_per_stack = layers // stacks\n\n        self.first_conv = nn.Conv1D(\n            in_channels, residual_channels, 1, bias_attr=True)\n        self.upsample_net = ConvInUpsampleNet(\n            upsample_scales=upsample_scales,\n            nonlinear_activation=nonlinear_activation,\n            nonlinear_activation_params=nonlinear_activation_params,\n            interpolate_mode=interpolate_mode,\n            freq_axis_kernel_size=freq_axis_kernel_size,\n            aux_channels=aux_channels,\n            aux_context_window=aux_context_window,\n            use_causal_conv=use_causal_conv)\n        self.upsample_factor = np.prod(upsample_scales)\n\n        self.conv_layers = nn.LayerList()\n        for layer in range(layers):\n            dilation = 2**(layer % layers_per_stack)\n            conv = ResidualBlock(\n                kernel_size=kernel_size,\n                residual_channels=residual_channels,\n                gate_channels=gate_channels,\n                skip_channels=skip_channels,\n                aux_channels=aux_channels,\n                dilation=dilation,\n                dropout=dropout,\n                bias=bias,\n                use_causal_conv=use_causal_conv)\n            self.conv_layers.append(conv)\n\n        self.last_conv_layers = nn.Sequential(nn.ReLU(),\n                                              nn.Conv1D(\n                                                  skip_channels,\n                                                  skip_channels,\n                                                  1,\n                                                  bias_attr=True),\n                                              nn.ReLU(),\n                                              nn.Conv1D(\n                                                  skip_channels,\n                                                  out_channels,\n                                                  1,\n                                                  bias_attr=True))\n\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n    def forward(self, x, c):\n        \"\"\"Generate waveform.\n\n        Args:\n            x(Tensor): \n                Shape (N, C_in, T), The input waveform.\n            c(Tensor): \n                Shape (N, C_aux, T'). The auxiliary input (e.g. spectrogram). \n                It is upsampled to match the time resolution of the input.\n\n        Returns:\n            Tensor: Shape (N, C_out, T), the generated waveform.\n        \"\"\"\n        c = self.upsample_net(c)\n        assert c.shape[-1] == x.shape[-1]\n\n        x = self.first_conv(x)\n        skips = 0\n        for f in self.conv_layers:\n            x, s = f(x, c)\n            skips += s\n        skips *= math.sqrt(1.0 / len(self.conv_layers))\n\n        x = self.last_conv_layers(skips)\n        return x\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n    def inference(self, c=None):\n        \"\"\"Waveform generation. This function is used for single instance inference.\n\n        Args:\n            c(Tensor, optional, optional): \n                Shape (T', C_aux), the auxiliary input, by default None\n            x(Tensor, optional): \n                Shape (T, C_in), the noise waveform, by default None\n\n        Returns:\n            Tensor: Shape (T, C_out), the generated waveform\n        \"\"\"\n        # when to static, can not input x, see https://github.com/PaddlePaddle/Parakeet/pull/132/files\n        x = paddle.randn(\n            [1, self.in_channels, paddle.shape(c)[0] * self.upsample_factor])\n        c = paddle.transpose(c, [1, 0]).unsqueeze(0)  # pseudo batch\n        c = nn.Pad1D(self.aux_context_window, mode='replicate')(c)\n        out = self(x, c).squeeze(0).transpose([1, 0])\n        return out\n\n\nclass PWGDiscriminator(nn.Layer):\n    \"\"\"A convolutional discriminator for audio.\n\n    Args:\n        in_channels (int, optional): \n            Number of channels of the input audio, by default 1\n        out_channels (int, optional): \n            Output feature size, by default 1\n        kernel_size (int, optional): \n            Kernel size of convolutional sublayers, by default 3\n        layers (int, optional): \n            Number of layers, by default 10\n        conv_channels (int, optional): \n            Feature size of the convolutional sublayers, by default 64\n        dilation_factor (int, optional): \n            The factor with which dilation of each convolutional sublayers grows \n            exponentially if it is greater than 1, else the dilation of each convolutional sublayers grows linearly, \n            by default 1\n        nonlinear_activation (str, optional): \n            The activation after each convolutional sublayer, by default \"leakyrelu\"\n        nonlinear_activation_params (Dict[str, Any], optional): \n            The parameters passed to the activation's initializer, by default {\"negative_slope\": 0.2}\n        bias (bool, optional): \n            Whether to use bias in convolutional sublayers, by default True\n        use_weight_norm (bool, optional): \n            Whether to use weight normalization at all convolutional sublayers, by default True\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_size: int=3,\n            layers: int=10,\n            conv_channels: int=64,\n            dilation_factor: int=1,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            bias: bool=True,\n            use_weight_norm: bool=True,\n            init_type: str=\"xavier_uniform\", ):\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        assert kernel_size % 2 == 1\n        assert dilation_factor > 0\n        conv_layers = []\n        conv_in_channels = in_channels\n        for i in range(layers - 1):\n            if i == 0:\n                dilation = 1\n            else:\n                dilation = i if dilation_factor == 1 else dilation_factor**i\n                conv_in_channels = conv_channels\n            padding = (kernel_size - 1) // 2 * dilation\n            conv_layer = nn.Conv1D(\n                conv_in_channels,\n                conv_channels,\n                kernel_size,\n                padding=padding,\n                dilation=dilation,\n                bias_attr=bias)\n            nonlinear = get_activation(nonlinear_activation,\n                                       **nonlinear_activation_params)\n            conv_layers.append(conv_layer)\n            conv_layers.append(nonlinear)\n        padding = (kernel_size - 1) // 2\n        last_conv = nn.Conv1D(\n            conv_in_channels,\n            out_channels,\n            kernel_size,\n            padding=padding,\n            bias_attr=bias)\n        conv_layers.append(last_conv)\n        self.conv_layers = nn.Sequential(*conv_layers)\n\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n    def forward(self, x):\n        \"\"\"\n\n        Args:\n            x (Tensor): \n                Shape (N, in_channels, num_samples), the input audio.\n\n        Returns:\n            Tensor: Shape (N, out_channels, num_samples), the predicted logits.\n        \"\"\"\n        return self.conv_layers(x)\n\n    def apply_weight_norm(self):\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n\nclass ResidualPWGDiscriminator(nn.Layer):\n    \"\"\"A wavenet-style discriminator for audio.\n\n    Args:\n        in_channels (int, optional): \n            Number of channels of the input audio, by default 1\n        out_channels (int, optional): \n            Output feature size, by default 1\n        kernel_size (int, optional): \n            Kernel size of residual blocks, by default 3\n        layers (int, optional): \n            Number of residual blocks, by default 30\n        stacks (int, optional): \n            Number of groups of residual blocks, within which the dilation \n            of each residual blocks grows exponentially, by default 3\n        residual_channels (int, optional): \n            Residual channels of residual blocks, by default 64\n        gate_channels (int, optional): \n            Gate channels of residual blocks, by default 128\n        skip_channels (int, optional): \n            Skip channels of residual blocks, by default 64\n        dropout (float, optional): \n            Dropout probability of residual blocks, by default 0.\n        bias (bool, optional): \n            Whether to use bias in residual blocks, by default True\n        use_weight_norm (bool, optional): \n            Whether to use weight normalization in all convolutional layers, by default True\n        use_causal_conv (bool, optional): \n            Whether to use causal convolution in residual blocks, by default False\n        nonlinear_activation (str, optional): \n            Activation after convolutions other than those in residual blocks, by default \"leakyrelu\"\n        nonlinear_activation_params (Dict[str, Any], optional): \n            Parameters to pass to the activation, by default {\"negative_slope\": 0.2}\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_size: int=3,\n            layers: int=30,\n            stacks: int=3,\n            residual_channels: int=64,\n            gate_channels: int=128,\n            skip_channels: int=64,\n            dropout: float=0.,\n            bias: bool=True,\n            use_weight_norm: bool=True,\n            use_causal_conv: bool=False,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            init_type: str=\"xavier_uniform\", ):\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        assert kernel_size % 2 == 1\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.layers = layers\n        self.stacks = stacks\n        self.kernel_size = kernel_size\n\n        assert layers % stacks == 0\n        layers_per_stack = layers // stacks\n\n        self.first_conv = nn.Sequential(\n            nn.Conv1D(in_channels, residual_channels, 1, bias_attr=True),\n            get_activation(nonlinear_activation, **nonlinear_activation_params))\n\n        self.conv_layers = nn.LayerList()\n        for layer in range(layers):\n            dilation = 2**(layer % layers_per_stack)\n            conv = ResidualBlock(\n                kernel_size=kernel_size,\n                residual_channels=residual_channels,\n                gate_channels=gate_channels,\n                skip_channels=skip_channels,\n                aux_channels=None,  # no auxiliary input\n                dropout=dropout,\n                dilation=dilation,\n                bias=bias,\n                use_causal_conv=use_causal_conv)\n            self.conv_layers.append(conv)\n\n        self.last_conv_layers = nn.Sequential(\n            get_activation(nonlinear_activation, **nonlinear_activation_params),\n            nn.Conv1D(skip_channels, skip_channels, 1, bias_attr=True),\n            get_activation(nonlinear_activation, **nonlinear_activation_params),\n            nn.Conv1D(skip_channels, out_channels, 1, bias_attr=True))\n\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n    def forward(self, x):\n        \"\"\"\n        Args:\n            x(Tensor): \n                Shape (N, in_channels, num_samples), the input audio.↩\n\n        Returns:\n            Tensor: Shape (N, out_channels, num_samples), the predicted logits.\n        \"\"\"\n        x = self.first_conv(x)\n        skip = 0\n        for f in self.conv_layers:\n            x, h = f(x, None)\n            skip += h\n        skip *= math.sqrt(1 / len(self.conv_layers))\n\n        x = skip\n        x = self.last_conv_layers(x)\n        return x\n\n    def apply_weight_norm(self):\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n\n\nclass PWGInference(nn.Layer):\n    def __init__(self, normalizer, pwg_generator):\n        super().__init__()\n        self.normalizer = normalizer\n        self.pwg_generator = pwg_generator\n\n    def forward(self, logmel):\n        normalized_mel = self.normalizer(logmel)\n        wav = self.pwg_generator.inference(normalized_mel)\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/parallel_wavegan/parallel_wavegan_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass PWGUpdater(StandardUpdater):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator: Layer = models['generator']\n        self.discriminator: Layer = models['discriminator']\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_mse = criterions['mse']\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        wav, mel = batch\n\n        # Generator\n        if self.state.iteration > self.generator_train_start_steps:\n            noise = paddle.randn(wav.shape)\n            wav_ = self.generator(noise, mel)\n\n            # initialize\n            gen_loss = 0.0\n            aux_loss = 0.0\n\n            # multi-resolution stft loss\n            sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n            aux_loss += sc_loss + mag_loss\n            report(\"train/spectral_convergence_loss\", float(sc_loss))\n            report(\"train/log_stft_magnitude_loss\", float(mag_loss))\n\n            gen_loss += aux_loss * self.lambda_aux\n\n            losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n            losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n\n            # adversarial loss\n            if self.state.iteration > self.discriminator_train_start_steps:\n                p_ = self.discriminator(wav_)\n                adv_loss = self.criterion_mse(p_, paddle.ones_like(p_))\n                report(\"train/adversarial_loss\", float(adv_loss))\n                losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n                gen_loss += self.lambda_adv * adv_loss\n\n            report(\"train/generator_loss\", float(gen_loss))\n            losses_dict[\"generator_loss\"] = float(gen_loss)\n\n            self.optimizer_g.clear_grad()\n            gen_loss.backward()\n\n            self.optimizer_g.step()\n            self.scheduler_g.step()\n\n        # Disctiminator\n        if self.state.iteration > self.discriminator_train_start_steps:\n            with paddle.no_grad():\n                wav_ = self.generator(noise, mel)\n            p = self.discriminator(wav)\n            p_ = self.discriminator(wav_.detach())\n            real_loss = self.criterion_mse(p, paddle.ones_like(p))\n            fake_loss = self.criterion_mse(p_, paddle.zeros_like(p_))\n            dis_loss = real_loss + fake_loss\n            report(\"train/real_loss\", float(real_loss))\n            report(\"train/fake_loss\", float(fake_loss))\n            report(\"train/discriminator_loss\", float(dis_loss))\n            losses_dict[\"real_loss\"] = float(real_loss)\n            losses_dict[\"fake_loss\"] = float(fake_loss)\n            losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n            self.optimizer_d.clear_grad()\n            dis_loss.backward()\n\n            self.optimizer_d.step()\n            self.scheduler_d.step()\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass PWGEvaluator(StandardEvaluator):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_adv: float=1.0,\n                 lambda_aux: float=1.0,\n                 output_dir: Path=None):\n        self.models = models\n        self.generator = models['generator']\n        self.discriminator = models['discriminator']\n\n        self.criterions = criterions\n        self.criterion_stft = criterions['stft']\n        self.criterion_mse = criterions['mse']\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_aux = lambda_aux\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        wav, mel = batch\n        noise = paddle.randn(wav.shape)\n\n        # Generator\n        wav_ = self.generator(noise, mel)\n\n        # initialize\n        gen_loss = 0.0\n        aux_loss = 0.0\n\n        # adversarial loss\n        p_ = self.discriminator(wav_)\n        adv_loss = self.criterion_mse(p_, paddle.ones_like(p_))\n        report(\"eval/adversarial_loss\", float(adv_loss))\n        losses_dict[\"adversarial_loss\"] = float(adv_loss)\n\n        gen_loss += self.lambda_adv * adv_loss\n\n        # multi-resolution stft loss\n        sc_loss, mag_loss = self.criterion_stft(wav_, wav)\n        report(\"eval/spectral_convergence_loss\", float(sc_loss))\n        report(\"eval/log_stft_magnitude_loss\", float(mag_loss))\n        losses_dict[\"spectral_convergence_loss\"] = float(sc_loss)\n        losses_dict[\"log_stft_magnitude_loss\"] = float(mag_loss)\n        aux_loss += sc_loss + mag_loss\n\n        gen_loss += aux_loss * self.lambda_aux\n\n        report(\"eval/generator_loss\", float(gen_loss))\n        losses_dict[\"generator_loss\"] = float(gen_loss)\n\n        # Disctiminator\n        p = self.discriminator(wav)\n        real_loss = self.criterion_mse(p, paddle.ones_like(p))\n        fake_loss = self.criterion_mse(p_, paddle.zeros_like(p_))\n        dis_loss = real_loss + fake_loss\n        report(\"eval/real_loss\", float(real_loss))\n        report(\"eval/fake_loss\", float(fake_loss))\n        report(\"eval/discriminator_loss\", float(dis_loss))\n\n        losses_dict[\"real_loss\"] = float(real_loss)\n        losses_dict[\"fake_loss\"] = float(fake_loss)\n        losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/speedyspeech/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .speedyspeech import *\nfrom .speedyspeech_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/speedyspeech/speedyspeech.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import List\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.predictor.length_regulator import LengthRegulator\nfrom paddlespeech.t2s.modules.transformer.embedding import ScaledPositionalEncoding\n\n\nclass ResidualBlock(nn.Layer):\n    def __init__(self,\n                 channels: int=128,\n                 kernel_size: int=3,\n                 dilation: int=3,\n                 n: int=2):\n        \"\"\"SpeedySpeech encoder module.\n        Args:\n            channels (int, optional): \n                Feature size of the residual output(and also the input).\n            kernel_size (int, optional): \n                Kernel size of the 1D convolution.\n            dilation (int, optional): \n                Dilation of the 1D convolution.\n            n (int): \n                Number of blocks.\n        \"\"\"\n\n        super().__init__()\n        total_pad = (dilation * (kernel_size - 1))\n        begin = total_pad // 2\n        end = total_pad - begin\n        # remove padding='same' here, cause onnx don't support dilation + 'same' padding\n        blocks = [\n            nn.Sequential(\n                nn.Conv1D(\n                    channels,\n                    channels,\n                    kernel_size,\n                    dilation=dilation,\n                    # make sure output T == input T\n                    padding=((0, 0), (0, 0), (begin, end))),\n                nn.ReLU(),\n                nn.BatchNorm1D(channels), ) for _ in range(n)\n        ]\n        self.blocks = nn.Sequential(*blocks)\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor): \n                Batch of input sequences (B, hidden_size, Tmax).\n        Returns:\n            Tensor: The residual output (B, hidden_size, Tmax).\n        \"\"\"\n        return x + self.blocks(x)\n\n\nclass TextEmbedding(nn.Layer):\n    def __init__(self,\n                 vocab_size: int,\n                 embedding_size: int,\n                 tone_vocab_size: int=None,\n                 tone_embedding_size: int=None,\n                 padding_idx: int=None,\n                 tone_padding_idx: int=None,\n                 concat: bool=False):\n        super().__init__()\n        self.text_embedding = nn.Embedding(vocab_size, embedding_size,\n                                           padding_idx)\n        if tone_vocab_size:\n            tone_embedding_size = tone_embedding_size or embedding_size\n            if tone_embedding_size != embedding_size and not concat:\n                raise ValueError(\n                    \"embedding size != tone_embedding size, only conat is avaiable.\"\n                )\n            self.tone_embedding = nn.Embedding(\n                tone_vocab_size, tone_embedding_size, tone_padding_idx)\n        self.concat = concat\n\n    def forward(self, text: paddle.Tensor, tone: paddle.Tensor=None):\n        \"\"\"Calculate forward propagation.\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token ids (B, Tmax).\n            tones(Tensor, optional(int64)): \n                Batch of padded tone ids (B, Tmax).\n        Returns:\n            Tensor: The residual output (B, Tmax, embedding_size).\n        \"\"\"\n\n        text_embed = self.text_embedding(text)\n        if tone is None:\n            return text_embed\n        tone_embed = self.tone_embedding(tone)\n        if self.concat:\n            embed = paddle.concat([text_embed, tone_embed], -1)\n        else:\n            embed = text_embed + tone_embed\n        return embed\n\n\nclass SpeedySpeechEncoder(nn.Layer):\n    \"\"\"SpeedySpeech encoder module.\n    Args:\n        vocab_size (int): \n            Dimension of the inputs.\n        tone_size (Optional[int]): \n            Number of tones.\n        hidden_size (int): \n            Number of encoder hidden units.\n        kernel_size (int): \n            Kernel size of encoder.\n        dilations (List[int]): \n            Dilations of encoder.\n        spk_num (Optional[int]): \n            Number of speakers. \n    \"\"\"\n\n    def __init__(self,\n                 vocab_size: int,\n                 tone_size: int,\n                 hidden_size: int=128,\n                 kernel_size: int=3,\n                 dilations: List[int]=[1, 3, 9, 27, 1, 3, 9, 27, 1, 1],\n                 spk_num=None):\n\n        super().__init__()\n        self.embedding = TextEmbedding(\n            vocab_size,\n            hidden_size,\n            tone_size,\n            padding_idx=0,\n            tone_padding_idx=0)\n\n        if spk_num:\n            self.spk_emb = nn.Embedding(\n                num_embeddings=spk_num,\n                embedding_dim=hidden_size,\n                padding_idx=0)\n        else:\n            self.spk_emb = None\n\n        self.prenet = nn.Sequential(\n            nn.Linear(hidden_size, hidden_size),\n            nn.ReLU(), )\n        res_blocks = [\n            ResidualBlock(hidden_size, kernel_size, d, n=2) for d in dilations\n        ]\n        self.res_blocks = nn.Sequential(*res_blocks)\n\n        self.postnet1 = nn.Sequential(nn.Linear(hidden_size, hidden_size))\n        self.postnet2 = nn.Sequential(\n            nn.ReLU(),\n            nn.BatchNorm1D(hidden_size), )\n        self.linear = nn.Linear(hidden_size, hidden_size)\n\n    def forward(self,\n                text: paddle.Tensor,\n                tones: paddle.Tensor,\n                spk_id: paddle.Tensor=None):\n        \"\"\"Encoder input sequence.\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token ids (B, Tmax).\n            tones(Tensor, optional(int64)): \n                Batch of padded tone ids (B, Tmax).\n            spk_id(Tnesor, optional(int64)): \n                Batch of speaker ids (B,)\n\n        Returns:\n            Tensor: Output tensor (B, Tmax, hidden_size).\n        \"\"\"\n        embedding = self.embedding(text, tones)\n        if self.spk_emb:\n            embedding += self.spk_emb(spk_id).unsqueeze(1)\n        embedding = self.prenet(embedding)\n        x = self.res_blocks(embedding.transpose([0, 2, 1])).transpose([0, 2, 1])\n        # (B, T, dim)\n        x = embedding + self.postnet1(x)\n        x = self.postnet2(x.transpose([0, 2, 1])).transpose([0, 2, 1])\n        x = self.linear(x)\n        return x\n\n\nclass DurationPredictor(nn.Layer):\n    def __init__(self, hidden_size: int=128):\n        super().__init__()\n        self.layers = nn.Sequential(\n            ResidualBlock(hidden_size, 4, 1, n=1),\n            ResidualBlock(hidden_size, 3, 1, n=1),\n            ResidualBlock(hidden_size, 1, 1, n=1), )\n        self.linear = nn.Linear(hidden_size, 1)\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor): \n                Batch of input sequences (B, Tmax, hidden_size).\n\n        Returns:\n            Tensor: Batch of predicted durations in log domain (B, Tmax).\n        \"\"\"\n        x = self.layers(x.transpose([0, 2, 1])).transpose([0, 2, 1])\n        x = self.linear(x)\n        return paddle.squeeze(x, -1)\n\n\nclass SpeedySpeechDecoder(nn.Layer):\n    def __init__(self,\n                 hidden_size: int=128,\n                 output_size: int=80,\n                 kernel_size: int=3,\n                 dilations: List[int]=[\n                     1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 1\n                 ]):\n        \"\"\"SpeedySpeech decoder module.\n        Args:\n            hidden_size (int): \n                Number of decoder hidden units.\n            kernel_size (int): \n                Kernel size of decoder.\n            output_size (int): \n                Dimension of the outputs.\n            dilations (List[int]): \n                Dilations of decoder.\n        \"\"\"\n        super().__init__()\n        res_blocks = [\n            ResidualBlock(hidden_size, kernel_size, d, n=2) for d in dilations\n        ]\n        self.res_blocks = nn.Sequential(*res_blocks)\n\n        self.postnet1 = nn.Sequential(nn.Linear(hidden_size, hidden_size))\n        self.postnet2 = ResidualBlock(hidden_size, kernel_size, 1, n=2)\n        self.linear = nn.Linear(hidden_size, output_size)\n\n    def forward(self, x):\n        \"\"\"Decoder input sequence.\n        Args:\n            x(Tensor): \n                Input tensor (B, time, hidden_size).\n\n        Returns:\n            Tensor: Output tensor (B, time, output_size).\n        \"\"\"\n        xx = self.res_blocks(x.transpose([0, 2, 1])).transpose([0, 2, 1])\n        x = x + self.postnet1(xx)\n        x = self.postnet2(x.transpose([0, 2, 1])).transpose([0, 2, 1])\n        x = self.linear(x)\n        return x\n\n\nclass SpeedySpeech(nn.Layer):\n    def __init__(\n            self,\n            vocab_size,\n            encoder_hidden_size: int=128,\n            encoder_kernel_size: int=3,\n            encoder_dilations: List[int]=[1, 3, 9, 27, 1, 3, 9, 27, 1, 1],\n            duration_predictor_hidden_size: int=128,\n            decoder_hidden_size: int=128,\n            decoder_output_size: int=80,\n            decoder_kernel_size: int=3,\n            decoder_dilations: List[\n                int]=[1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 3, 9, 27, 1, 1],\n            tone_size: int=None,\n            spk_num: int=None,\n            init_type: str=\"xavier_uniform\",\n            positional_dropout_rate: int=0.1):\n        \"\"\"Initialize SpeedySpeech module.\n        Args:\n            vocab_size (int): \n                Dimension of the inputs.\n            encoder_hidden_size (int): \n                Number of encoder hidden units.\n            encoder_kernel_size (int): \n                Kernel size of encoder.\n            encoder_dilations (List[int]): \n                Dilations of encoder.\n            duration_predictor_hidden_size (int):\n                Number of duration predictor hidden units.\n            decoder_hidden_size (int): \n                Number of decoder hidden units.\n            decoder_kernel_size (int): \n                Kernel size of decoder.\n            decoder_dilations (List[int]): \n                Dilations of decoder.\n            decoder_output_size (int): \n                Dimension of the outputs.\n            tone_size (Optional[int]): \n                Number of tones.\n            spk_num (Optional[int]): \n                Number of speakers. \n            init_type (str): \n                How to initialize transformer parameters.\n    \n        \"\"\"\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        encoder = SpeedySpeechEncoder(vocab_size, tone_size,\n                                      encoder_hidden_size, encoder_kernel_size,\n                                      encoder_dilations, spk_num)\n        duration_predictor = DurationPredictor(duration_predictor_hidden_size)\n        decoder = SpeedySpeechDecoder(decoder_hidden_size, decoder_output_size,\n                                      decoder_kernel_size, decoder_dilations)\n        self.position_enc = ScaledPositionalEncoding(encoder_hidden_size,\n                                                     positional_dropout_rate)\n\n        self.encoder = encoder\n        self.duration_predictor = duration_predictor\n        self.decoder = decoder\n        # define length regulator\n        self.length_regulator = LengthRegulator()\n\n        nn.initializer.set_global_initializer(None)\n\n    def forward(self,\n                text: paddle.Tensor,\n                tones: paddle.Tensor,\n                durations: paddle.Tensor,\n                spk_id: paddle.Tensor=None):\n        \"\"\"Calculate forward propagation.\n        Args:\n            text(Tensor(int64)): \n                Batch of padded token ids (B, Tmax).\n            durations(Tensor(int64)): \n                Batch of padded durations (B, Tmax).\n            tones(Tensor, optional(int64)): \n                Batch of padded tone ids  (B, Tmax).\n            spk_id(Tnesor, optional(int64)): \n                Batch of speaker ids (B,)\n\n        Returns:\n            Tensor: \n                Output tensor (B, T_frames, decoder_output_size).\n            Tensor: \n                Predicted durations (B, Tmax).\n        \"\"\"\n        # input of embedding must be int64\n        text = paddle.cast(text, 'int64')\n        tones = paddle.cast(tones, 'int64')\n        if spk_id is not None:\n            spk_id = paddle.cast(spk_id, 'int64')\n        durations = paddle.cast(durations, 'int64')\n        encodings = self.encoder(text, tones, spk_id)\n        pred_durations = self.duration_predictor(encodings.detach())\n        # expand encodings\n        durations_to_expand = durations\n        encodings = self.length_regulator(encodings, durations_to_expand)\n        encodings = self.position_enc(encodings)\n        # decode\n        decoded = self.decoder(encodings)\n        return decoded, pred_durations\n\n    def inference(self,\n                  text: paddle.Tensor,\n                  tones: paddle.Tensor=None,\n                  durations: paddle.Tensor=None,\n                  spk_id: paddle.Tensor=None):\n        \"\"\"Generate the sequence of features given the sequences of characters.\n        Args:\n            text(Tensor(int64)): \n                Input sequence of characters (T,).\n            tones(Tensor, optional(int64)): \n                Batch of padded tone ids (T, ).\n            durations(Tensor, optional (int64)): \n                Groundtruth of duration (T,).\n            spk_id(Tensor, optional(int64), optional): \n                spk ids (1,). (Default value = None)\n\n        Returns:\n            Tensor: logmel (T, decoder_output_size).\n        \"\"\"\n        # input of embedding must be int64\n        text = paddle.cast(text, 'int64')\n        text = text.unsqueeze(0)\n        if tones is not None:\n            tones = paddle.cast(tones, 'int64')\n            tones = tones.unsqueeze(0)\n\n        encodings = self.encoder(text, tones, spk_id)\n\n        if durations is None:\n            # (1, T)\n            pred_durations = self.duration_predictor(encodings)\n            durations_to_expand = paddle.round(pred_durations.exp())\n            durations_to_expand = durations_to_expand.astype(paddle.int64)\n        else:\n            durations_to_expand = durations\n        encodings = self.length_regulator(\n            encodings, durations_to_expand, is_inference=True)\n        encodings = self.position_enc(encodings)\n        decoded = self.decoder(encodings)\n        return decoded[0]\n\n\nclass SpeedySpeechInference(nn.Layer):\n    def __init__(self, normalizer, speedyspeech_model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = speedyspeech_model\n\n    def forward(self, phones, tones, spk_id=None, durations=None):\n        normalized_mel = self.acoustic_model.inference(\n            phones, tones, durations=durations, spk_id=spk_id)\n        logmel = self.normalizer.inverse(normalized_mel)\n        return logmel\n"
  },
  {
    "path": "paddlespeech/t2s/models/speedyspeech/speedyspeech_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import functional as F\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.modules.losses import masked_l1_loss\nfrom paddlespeech.t2s.modules.losses import ssim\nfrom paddlespeech.t2s.modules.losses import weighted_mean\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass SpeedySpeechUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 dataloader: DataLoader,\n                 init_state=None,\n                 output_dir: Path=None):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        # spk_id!=None in multiple spk speedyspeech \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n\n        decoded, predicted_durations = self.model(\n            text=batch[\"phones\"],\n            tones=batch[\"tones\"],\n            durations=batch[\"durations\"],\n            spk_id=spk_id)\n\n        target_mel = batch[\"feats\"]\n        spec_mask = F.sequence_mask(\n            batch[\"num_frames\"], dtype=target_mel.dtype).unsqueeze(-1)\n        text_mask = F.sequence_mask(\n            batch[\"num_phones\"], dtype=predicted_durations.dtype)\n\n        # spec loss\n        l1_loss = masked_l1_loss(decoded, target_mel, spec_mask)\n\n        # duration loss\n        target_durations = batch[\"durations\"]\n        target_durations = paddle.maximum(\n            target_durations.astype(predicted_durations.dtype),\n            paddle.to_tensor([1.0]))\n        duration_loss = weighted_mean(\n            F.smooth_l1_loss(\n                predicted_durations,\n                paddle.log(target_durations),\n                delta=1.0,\n                reduction='none', ),\n            text_mask, )\n\n        # ssim loss\n        ssim_loss = 1.0 - ssim((decoded * spec_mask).unsqueeze(1),\n                               (target_mel * spec_mask).unsqueeze(1))\n\n        loss = l1_loss + ssim_loss + duration_loss\n\n        optimizer = self.optimizer\n        optimizer.clear_grad()\n        loss.backward()\n        optimizer.step()\n\n        report(\"train/loss\", float(loss))\n        report(\"train/l1_loss\", float(l1_loss))\n        report(\"train/duration_loss\", float(duration_loss))\n        report(\"train/ssim_loss\", float(ssim_loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"duration_loss\"] = float(duration_loss)\n        losses_dict[\"ssim_loss\"] = float(ssim_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass SpeedySpeechEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 dataloader: DataLoader,\n                 output_dir: Path=None):\n        super().__init__(model, dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n\n        decoded, predicted_durations = self.model(\n            text=batch[\"phones\"],\n            tones=batch[\"tones\"],\n            durations=batch[\"durations\"],\n            spk_id=spk_id)\n\n        target_mel = batch[\"feats\"]\n        spec_mask = F.sequence_mask(\n            batch[\"num_frames\"], dtype=target_mel.dtype).unsqueeze(-1)\n        text_mask = F.sequence_mask(\n            batch[\"num_phones\"], dtype=predicted_durations.dtype)\n\n        # spec loss\n        l1_loss = masked_l1_loss(decoded, target_mel, spec_mask)\n\n        # duration loss\n        target_durations = batch[\"durations\"]\n        target_durations = paddle.maximum(\n            target_durations.astype(predicted_durations.dtype),\n            paddle.to_tensor([1.0]))\n        duration_loss = weighted_mean(\n            F.smooth_l1_loss(\n                predicted_durations,\n                paddle.log(target_durations),\n                delta=1.0,\n                reduction='none', ),\n            text_mask, )\n\n        # ssim loss\n        ssim_loss = 1.0 - ssim((decoded * spec_mask).unsqueeze(1),\n                               (target_mel * spec_mask).unsqueeze(1))\n\n        loss = l1_loss + ssim_loss + duration_loss\n\n        # import pdb; pdb.set_trace()\n\n        report(\"eval/loss\", float(loss))\n        report(\"eval/l1_loss\", float(l1_loss))\n        report(\"eval/duration_loss\", float(duration_loss))\n        report(\"eval/ssim_loss\", float(ssim_loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"duration_loss\"] = float(duration_loss)\n        losses_dict[\"ssim_loss\"] = float(ssim_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/AuxiliaryASR/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/AuxiliaryASR/config.yml",
    "content": "log_dir: \"logs\"\nsave_freq: 20\ndevice: \"cuda\"\nepochs: 180\nbatch_size: 48\npretrained_model: \"\"\ntrain_data: \"asr_train_list.txt\"\nval_data: \"asr_val_list.txt\"\n\ndataset_params:\n  data_augmentation: true\n\npreprocess_parasm:\n  sr: 24000\n  spect_params:\n    n_fft: 2048\n    win_length: 1200\n    hop_length: 300\n  mel_params:\n    n_mels: 80\n\nmodel_params:\n   input_dim: 80\n   hidden_dim: 256\n   n_token: 80\n   token_embedding_dim: 256\n\noptimizer_params:\n  lr: 0.0005"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/AuxiliaryASR/layers.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.audio.functional import create_dct\nfrom paddlespeech.utils.initialize import _calculate_gain\nfrom paddlespeech.utils.initialize import xavier_uniform_\n\n\ndef _get_activation_fn(activ):\n    if activ == 'relu':\n        return nn.ReLU()\n    elif activ == 'lrelu':\n        return nn.LeakyReLU(0.2)\n    elif activ == 'swish':\n        return nn.Swish()\n    else:\n        raise RuntimeError(\n            'Unexpected activ type %s, expected [relu, lrelu, swish]' % activ)\n\n\nclass LinearNorm(nn.Layer):\n    def __init__(self,\n                 in_dim: int,\n                 out_dim: int,\n                 bias: bool=True,\n                 w_init_gain: str='linear'):\n        super().__init__()\n        self.linear_layer = nn.Linear(in_dim, out_dim, bias_attr=bias)\n        xavier_uniform_(\n            self.linear_layer.weight, gain=_calculate_gain(w_init_gain))\n\n    def forward(self, x: paddle.Tensor):\n        out = self.linear_layer(x)\n        return out\n\n\nclass ConvNorm(nn.Layer):\n    def __init__(self,\n                 in_channels: int,\n                 out_channels: int,\n                 kernel_size: int=1,\n                 stride: int=1,\n                 padding: int=None,\n                 dilation: int=1,\n                 bias: bool=True,\n                 w_init_gain: str='linear',\n                 param=None):\n        super().__init__()\n        if padding is None:\n            assert (kernel_size % 2 == 1)\n            padding = int(dilation * (kernel_size - 1) / 2)\n\n        self.conv = nn.Conv1D(\n            in_channels,\n            out_channels,\n            kernel_size=kernel_size,\n            stride=stride,\n            padding=padding,\n            dilation=dilation,\n            bias_attr=bias)\n\n        xavier_uniform_(\n            self.conv.weight, gain=_calculate_gain(w_init_gain, param=param))\n\n    def forward(self, signal: paddle.Tensor):\n        conv_signal = self.conv(signal)\n        return conv_signal\n\n\nclass ConvBlock(nn.Layer):\n    def __init__(self,\n                 hidden_dim: int,\n                 n_conv: int=3,\n                 dropout_p: float=0.2,\n                 activ: str='relu'):\n        super().__init__()\n        self._n_groups = 8\n        self.blocks = nn.LayerList([\n            self._get_conv(\n                hidden_dim=hidden_dim,\n                dilation=3**i,\n                activ=activ,\n                dropout_p=dropout_p) for i in range(n_conv)\n        ])\n\n    def forward(self, x: paddle.Tensor):\n        for block in self.blocks:\n            res = x\n            x = block(x)\n            x += res\n        return x\n\n    def _get_conv(self,\n                  hidden_dim: int,\n                  dilation: int,\n                  activ: str='relu',\n                  dropout_p: float=0.2):\n        layers = [\n            ConvNorm(\n                in_channels=hidden_dim,\n                out_channels=hidden_dim,\n                kernel_size=3,\n                padding=dilation,\n                dilation=dilation), _get_activation_fn(activ),\n            nn.GroupNorm(num_groups=self._n_groups, num_channels=hidden_dim),\n            nn.Dropout(p=dropout_p), ConvNorm(\n                hidden_dim, hidden_dim, kernel_size=3, padding=1,\n                dilation=1), _get_activation_fn(activ), nn.Dropout(p=dropout_p)\n        ]\n        return nn.Sequential(*layers)\n\n\nclass LocationLayer(nn.Layer):\n    def __init__(self,\n                 attention_n_filters: int,\n                 attention_kernel_size: int,\n                 attention_dim: int):\n        super().__init__()\n        padding = int((attention_kernel_size - 1) / 2)\n        self.location_conv = ConvNorm(\n            in_channels=2,\n            out_channels=attention_n_filters,\n            kernel_size=attention_kernel_size,\n            padding=padding,\n            bias=False,\n            stride=1,\n            dilation=1)\n        self.location_dense = LinearNorm(\n            in_dim=attention_n_filters,\n            out_dim=attention_dim,\n            bias=False,\n            w_init_gain='tanh')\n\n    def forward(self, attention_weights_cat: paddle.Tensor):\n        processed_attention = self.location_conv(attention_weights_cat)\n        processed_attention = processed_attention.transpose([0, 2, 1])\n        processed_attention = self.location_dense(processed_attention)\n        return processed_attention\n\n\nclass Attention(nn.Layer):\n    def __init__(self,\n                 attention_rnn_dim: int,\n                 embedding_dim: int,\n                 attention_dim: int,\n                 attention_location_n_filters: int,\n                 attention_location_kernel_size: int):\n        super().__init__()\n        self.query_layer = LinearNorm(\n            in_dim=attention_rnn_dim,\n            out_dim=attention_dim,\n            bias=False,\n            w_init_gain='tanh')\n        self.memory_layer = LinearNorm(\n            in_dim=embedding_dim,\n            out_dim=attention_dim,\n            bias=False,\n            w_init_gain='tanh')\n        self.v = LinearNorm(in_dim=attention_dim, out_dim=1, bias=False)\n        self.location_layer = LocationLayer(\n            attention_n_filters=attention_location_n_filters,\n            attention_kernel_size=attention_location_kernel_size,\n            attention_dim=attention_dim)\n        self.score_mask_value = -float(\"inf\")\n\n    def get_alignment_energies(self,\n                               query: paddle.Tensor,\n                               processed_memory: paddle.Tensor,\n                               attention_weights_cat: paddle.Tensor):\n        \"\"\"\n        Args:\n            query: \n                decoder output (B, n_mel_channels * n_frames_per_step)\n            processed_memory: \n                processed encoder outputs (B, T_in, attention_dim)\n            attention_weights_cat: \n                cumulative and prev. att weights (B, 2, max_time)\n        Returns:\n            Tensor: \n                alignment (B, max_time)\n        \"\"\"\n\n        processed_query = self.query_layer(query.unsqueeze(1))\n        processed_attention_weights = self.location_layer(attention_weights_cat)\n        energies = self.v(\n            paddle.tanh(processed_query + processed_attention_weights +\n                        processed_memory))\n\n        energies = energies.squeeze(-1)\n        return energies\n\n    def forward(self,\n                attention_hidden_state: paddle.Tensor,\n                memory: paddle.Tensor,\n                processed_memory: paddle.Tensor,\n                attention_weights_cat: paddle.Tensor,\n                mask: paddle.Tensor):\n        \"\"\"\n        Args:\n            attention_hidden_state: \n                attention rnn last output\n            memory: \n                encoder outputs\n            processed_memory: \n                processed encoder outputs\n            attention_weights_cat: \n                previous and cummulative attention weights\n            mask: \n                binary mask for padded data\n        \"\"\"\n        alignment = self.get_alignment_energies(\n            query=attention_hidden_state,\n            processed_memory=processed_memory,\n            attention_weights_cat=attention_weights_cat)\n\n        if mask is not None:\n            alignment.data.masked_fill_(mask, self.score_mask_value)\n\n        attention_weights = F.softmax(alignment, axis=1)\n        attention_context = paddle.bmm(attention_weights.unsqueeze(1), memory)\n        attention_context = attention_context.squeeze(1)\n\n        return attention_context, attention_weights\n\n\nclass MFCC(nn.Layer):\n    def __init__(self, n_mfcc: int=40, n_mels: int=80):\n        super().__init__()\n        self.n_mfcc = n_mfcc\n        self.n_mels = n_mels\n        self.norm = 'ortho'\n        dct_mat = create_dct(self.n_mfcc, self.n_mels, self.norm)\n        self.register_buffer('dct_mat', dct_mat)\n\n    def forward(self, mel_specgram: paddle.Tensor):\n        if len(mel_specgram.shape) == 2:\n            mel_specgram = mel_specgram.unsqueeze(0)\n            unsqueezed = True\n        else:\n            unsqueezed = False\n        # (channel, n_mels, time).tranpose(...) dot (n_mels, n_mfcc)\n        # -> (channel, time, n_mfcc).tranpose(...)\n        mfcc = paddle.matmul(mel_specgram.transpose([0, 2, 1]),\n                             self.dct_mat).transpose([0, 2, 1])\n        # unpack batch\n        if unsqueezed:\n            mfcc = mfcc.squeeze(0)\n        return mfcc\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/AuxiliaryASR/model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom .layers import Attention\nfrom .layers import ConvBlock\nfrom .layers import ConvNorm\nfrom .layers import LinearNorm\nfrom .layers import MFCC\nfrom paddlespeech.t2s.modules.nets_utils import _reset_parameters\nfrom paddlespeech.utils.initialize import uniform_\n\n\nclass ASRCNN(nn.Layer):\n    def __init__(\n            self,\n            input_dim: int=80,\n            hidden_dim: int=256,\n            n_token: int=35,\n            n_layers: int=6,\n            token_embedding_dim: int=256, ):\n        super().__init__()\n        self.n_token = n_token\n        self.n_down = 1\n        self.to_mfcc = MFCC()\n        self.init_cnn = ConvNorm(\n            in_channels=input_dim // 2,\n            out_channels=hidden_dim,\n            kernel_size=7,\n            padding=3,\n            stride=2)\n        self.cnns = nn.Sequential(* [\n            nn.Sequential(\n                ConvBlock(hidden_dim),\n                nn.GroupNorm(num_groups=1, num_channels=hidden_dim))\n            for n in range(n_layers)\n        ])\n        self.projection = ConvNorm(\n            in_channels=hidden_dim, out_channels=hidden_dim // 2)\n        self.ctc_linear = nn.Sequential(\n            LinearNorm(in_dim=hidden_dim // 2, out_dim=hidden_dim),\n            nn.ReLU(), LinearNorm(in_dim=hidden_dim, out_dim=n_token))\n        self.asr_s2s = ASRS2S(\n            embedding_dim=token_embedding_dim,\n            hidden_dim=hidden_dim // 2,\n            n_token=n_token)\n\n        self.reset_parameters()\n        self.asr_s2s.reset_parameters()\n\n    def forward(self,\n                x: paddle.Tensor,\n                src_key_padding_mask: paddle.Tensor=None,\n                text_input: paddle.Tensor=None):\n        x = self.to_mfcc(x)\n        x = self.init_cnn(x)\n        x = self.cnns(x)\n        x = self.projection(x)\n        x = x.transpose([0, 2, 1])\n        ctc_logit = self.ctc_linear(x)\n        if text_input is not None:\n            _, s2s_logit, s2s_attn = self.asr_s2s(\n                memory=x,\n                memory_mask=src_key_padding_mask,\n                text_input=text_input)\n            return ctc_logit, s2s_logit, s2s_attn\n        else:\n            return ctc_logit\n\n    def get_feature(self, x: paddle.Tensor):\n        x = self.to_mfcc(x.squeeze(1))\n        x = self.init_cnn(x)\n        x = self.cnns(x)\n        x = self.projection(x)\n        return x\n\n    def length_to_mask(self, lengths: paddle.Tensor):\n        mask = paddle.arange(lengths.max()).unsqueeze(0).expand(\n            (lengths.shape[0], -1)).astype(lengths.dtype)\n        mask = paddle.greater_than(mask + 1, lengths.unsqueeze(1))\n        return mask\n\n    def get_future_mask(self, out_length: int, unmask_future_steps: int=0):\n        \"\"\"\n        Args:\n            out_length (int):\n                returned mask shape is (out_length, out_length).\n            unmask_futre_steps (int): \n                unmasking future step size.\n        Return:\n            Tensor (paddle.Tensor(bool)): \n                mask future timesteps mask[i, j] = True if i > j + unmask_future_steps else False\n        \"\"\"\n        index_tensor = paddle.arange(out_length).unsqueeze(0).expand(\n            [out_length, -1])\n        mask = paddle.greater_than(index_tensor,\n                                   index_tensor.T + unmask_future_steps)\n        return mask\n\n    def reset_parameters(self):\n        self.apply(_reset_parameters)\n\n\nclass ASRS2S(nn.Layer):\n    def __init__(self,\n                 embedding_dim: int=256,\n                 hidden_dim: int=512,\n                 n_location_filters: int=32,\n                 location_kernel_size: int=63,\n                 n_token: int=40):\n        super().__init__()\n        self.embedding = nn.Embedding(n_token, embedding_dim)\n        self.val_range = math.sqrt(6 / hidden_dim)\n\n        self.decoder_rnn_dim = hidden_dim\n        self.project_to_n_symbols = nn.Linear(self.decoder_rnn_dim, n_token)\n        self.attention_layer = Attention(\n            attention_rnn_dim=self.decoder_rnn_dim,\n            embedding_dim=hidden_dim,\n            attention_dim=hidden_dim,\n            attention_location_n_filters=n_location_filters,\n            attention_location_kernel_size=location_kernel_size)\n        self.decoder_rnn = nn.LSTMCell(self.decoder_rnn_dim + embedding_dim,\n                                       self.decoder_rnn_dim)\n        self.project_to_hidden = nn.Sequential(\n            LinearNorm(in_dim=self.decoder_rnn_dim * 2, out_dim=hidden_dim),\n            nn.Tanh())\n        self.sos = 1\n        self.eos = 2\n\n    def initialize_decoder_states(self,\n                                  memory: paddle.Tensor,\n                                  mask: paddle.Tensor):\n        \"\"\"\n        moemory.shape = (B, L, H) = (Batchsize, Maxtimestep, Hiddendim)\n        \"\"\"\n        B, L, H = memory.shape\n        dtype = memory.dtype\n        self.decoder_hidden = paddle.zeros(\n            (B, self.decoder_rnn_dim)).astype(dtype)\n        self.decoder_cell = paddle.zeros(\n            (B, self.decoder_rnn_dim)).astype(dtype)\n        self.attention_weights = paddle.zeros((B, L)).astype(dtype)\n        self.attention_weights_cum = paddle.zeros((B, L)).astype(dtype)\n        self.attention_context = paddle.zeros((B, H)).astype(dtype)\n        self.memory = memory\n        self.processed_memory = self.attention_layer.memory_layer(memory)\n        self.mask = mask\n        self.unk_index = 3\n        self.random_mask = 0.1\n\n    def forward(self,\n                memory: paddle.Tensor,\n                memory_mask: paddle.Tensor,\n                text_input: paddle.Tensor):\n        \"\"\"\n        moemory.shape = (B, L, H) = (Batchsize, Maxtimestep, Hiddendim)\n        moemory_mask.shape = (B, L, )\n        texts_input.shape = (B, T)\n        \"\"\"\n        self.initialize_decoder_states(memory, memory_mask)\n        # text random mask\n        random_mask = (paddle.rand(text_input.shape) < self.random_mask)\n        _text_input = text_input.clone()\n        _text_input[:] = paddle.where(\n            condition=random_mask,\n            x=paddle.full(\n                shape=_text_input.shape,\n                fill_value=self.unk_index,\n                dtype=_text_input.dtype),\n            y=_text_input)\n        decoder_inputs = self.embedding(_text_input).transpose(\n            [1, 0, 2])  # -> [T, B, channel]\n        start_embedding = self.embedding(\n            paddle.to_tensor(\n                [self.sos] * decoder_inputs.shape[1], dtype=paddle.long))\n        decoder_inputs = paddle.concat(\n            (start_embedding.unsqueeze(0), decoder_inputs), axis=0)\n\n        hidden_outputs, logit_outputs, alignments = [], [], []\n        while len(hidden_outputs) < decoder_inputs.shape[0]:\n            decoder_input = decoder_inputs[len(hidden_outputs)]\n            hidden, logit, attention_weights = self.decode(decoder_input)\n            hidden_outputs += [hidden]\n            logit_outputs += [logit]\n            alignments += [attention_weights]\n\n        hidden_outputs, logit_outputs, alignments = self.parse_decoder_outputs(\n            hidden_outputs, logit_outputs, alignments)\n\n        return hidden_outputs, logit_outputs, alignments\n\n    def decode(self, decoder_input: paddle.Tensor):\n        cell_input = paddle.concat((decoder_input, self.attention_context), -1)\n        self.decoder_rnn.flatten_parameters()\n        self.decoder_hidden, self.decoder_cell = self.decoder_rnn(\n            cell_input, (self.decoder_hidden, self.decoder_cell))\n\n        attention_weights_cat = paddle.concat(\n            (self.attention_weights.unsqueeze(1),\n             self.attention_weights_cum.unsqueeze(1)),\n            axis=1)\n\n        self.attention_context, self.attention_weights = self.attention_layer(\n            self.decoder_hidden, self.memory, self.processed_memory,\n            attention_weights_cat, self.mask)\n\n        self.attention_weights_cum += self.attention_weights\n\n        hidden_and_context = paddle.concat(\n            (self.decoder_hidden, self.attention_context), -1)\n        hidden = self.project_to_hidden(hidden_and_context)\n\n        # dropout to increasing g\n        logit = self.project_to_n_symbols(F.dropout(hidden, 0.5, self.training))\n\n        return hidden, logit, self.attention_weights\n\n    def parse_decoder_outputs(self,\n                              hidden: paddle.Tensor,\n                              logit: paddle.Tensor,\n                              alignments: paddle.Tensor):\n        # -> [B, T_out + 1, max_time]\n        alignments = paddle.stack(alignments).transpose([1, 0, 2])\n        # [T_out + 1, B, n_symbols] -> [B, T_out + 1,  n_symbols]\n        logit = paddle.stack(logit).transpose([1, 0, 2])\n        hidden = paddle.stack(hidden).transpose([1, 0, 2])\n\n        return hidden, logit, alignments\n\n    def reset_parameters(self):\n        uniform_(self.embedding.weight, -self.val_range, self.val_range)\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/JDCNet/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/JDCNet/model.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImplementation of model from:\nKum et al. - \"Joint Detection and Classification of Singing Voice Melody Using\nConvolutional Recurrent Neural Networks\" (2019)\nLink: https://www.semanticscholar.org/paper/Joint-Detection-and-Classification-of-Singing-Voice-Kum-Nam/60a2ad4c7db43bace75805054603747fcd062c0d\n\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass JDCNet(nn.Layer):\n    \"\"\"\n    Joint Detection and Classification Network model for singing voice melody.\n    \"\"\"\n\n    def __init__(self,\n                 num_class: int=722,\n                 seq_len: int=31,\n                 leaky_relu_slope: float=0.01):\n        super().__init__()\n        self.seq_len = seq_len\n        self.num_class = num_class\n        # input: (B, num_class, T, n_mels)\n        self.conv_block = nn.Sequential(\n            # output: (B, out_channels, T, n_mels)\n            nn.Conv2D(\n                in_channels=1,\n                out_channels=64,\n                kernel_size=3,\n                padding=1,\n                bias_attr=False),\n            nn.BatchNorm2D(num_features=64),\n            nn.LeakyReLU(leaky_relu_slope),\n            # out: (B, out_channels, T, n_mels)\n            nn.Conv2D(64, 64, 3, padding=1, bias_attr=False), )\n        # output: (B, out_channels, T, n_mels // 2)\n        self.res_block1 = ResBlock(in_channels=64, out_channels=128)\n        # output: (B, out_channels, T, n_mels // 4) \n        self.res_block2 = ResBlock(in_channels=128, out_channels=192)\n        # output: (B, out_channels, T, n_mels // 8)  \n        self.res_block3 = ResBlock(in_channels=192, out_channels=256)\n        # pool block\n        self.pool_block = nn.Sequential(\n            nn.BatchNorm2D(num_features=256),\n            nn.LeakyReLU(leaky_relu_slope),\n            # (B, num_features, T, 2)\n            nn.MaxPool2D(kernel_size=(1, 4)),\n            nn.Dropout(p=0.5), )\n        # input: (B, T, input_size), resized from (B, input_size // 2, T, 2)\n        # output: (B, T, input_size)\n        self.bilstm_classifier = nn.LSTM(\n            input_size=512,\n            hidden_size=256,\n            time_major=False,\n            direction='bidirectional')\n        # input: (B * T, in_features)\n        # output: (B * T, num_class)\n        self.classifier = nn.Linear(\n            in_features=512, out_features=self.num_class)\n\n        # initialize weights\n        self.apply(self.init_weights)\n\n    def get_feature_GAN(self, x: paddle.Tensor):\n        \"\"\"Calculate feature_GAN.\n        Args:\n            x(Tensor(float32)): \n                Shape (B, num_class, n_mels, T).\n        Returns:\n            Tensor:\n                Shape (B, num_features, n_mels // 8, T).\n        \"\"\"\n        x = x.astype(paddle.float32)\n        x = x.transpose([0, 1, 3, 2] if len(x.shape) == 4 else [0, 2, 1])\n        convblock_out = self.conv_block(x)\n        resblock1_out = self.res_block1(convblock_out)\n        resblock2_out = self.res_block2(resblock1_out)\n        resblock3_out = self.res_block3(resblock2_out)\n        poolblock_out = self.pool_block[0](resblock3_out)\n        poolblock_out = self.pool_block[1](poolblock_out)\n        GAN_feature = poolblock_out.transpose([0, 1, 3, 2] if len(\n            poolblock_out.shape) == 4 else [0, 2, 1])\n        return GAN_feature\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): \n                Shape (B, num_class, n_mels, seq_len).\n        Returns:\n            Tensor:\n                classifier output consists of predicted pitch classes per frame.\n                Shape: (B, seq_len, num_class).\n            Tensor:\n                GAN_feature. Shape: (B, num_features, n_mels // 8, seq_len)\n            Tensor:\n                poolblock_out. Shape (B, seq_len, 512)     \n        \"\"\"\n        ###############################\n        # forward pass for classifier #\n        ###############################\n        # (B, num_class, n_mels, T) -> (B, num_class, T, n_mels)\n        x = x.transpose([0, 1, 3, 2] if len(x.shape) == 4 else\n                        [0, 2, 1]).astype(paddle.float32)\n\n        convblock_out = self.conv_block(x)\n        resblock1_out = self.res_block1(convblock_out)\n        resblock2_out = self.res_block2(resblock1_out)\n        resblock3_out = self.res_block3(resblock2_out)\n        poolblock_out = self.pool_block[0](resblock3_out)\n        poolblock_out = self.pool_block[1](poolblock_out)\n        GAN_feature = poolblock_out.transpose([0, 1, 3, 2] if len(\n            poolblock_out.shape) == 4 else [0, 2, 1])\n        poolblock_out = self.pool_block[2](poolblock_out)\n        # (B, 256, seq_len, 2) => (B, seq_len, 256, 2) => (B, seq_len, 512)\n        classifier_out = poolblock_out.transpose([0, 2, 1, 3]).reshape(\n            (-1, self.seq_len, 512))\n        self.bilstm_classifier.flatten_parameters()\n        # ignore the hidden states\n        classifier_out, _ = self.bilstm_classifier(classifier_out)\n        # (B * seq_len, 512)\n        classifier_out = classifier_out.reshape((-1, 512))\n        classifier_out = self.classifier(classifier_out)\n        # (B, seq_len, num_class)\n        classifier_out = classifier_out.reshape(\n            (-1, self.seq_len, self.num_class))\n        return paddle.abs(classifier_out.squeeze()), GAN_feature, poolblock_out\n\n    @staticmethod\n    def init_weights(m):\n        if isinstance(m, nn.Linear):\n            nn.initializer.KaimingUniform()(m.weight)\n            if m.bias is not None:\n                nn.initializer.Constant(0)(m.bias)\n        elif isinstance(m, nn.Conv2D):\n            nn.initializer.XavierNormal()(m.weight)\n        elif isinstance(m, nn.LSTM) or isinstance(m, nn.LSTMCell):\n            for p in m.parameters():\n                if len(p.shape) >= 2:\n                    nn.initializer.Orthogonal()(p)\n                else:\n                    nn.initializer.Normal()(p)\n\n\nclass ResBlock(nn.Layer):\n    def __init__(self,\n                 in_channels: int,\n                 out_channels: int,\n                 leaky_relu_slope: float=0.01):\n        super().__init__()\n        self.downsample = in_channels != out_channels\n        # BN / LReLU / MaxPool layer before the conv layer - see Figure 1b in the paper\n        self.pre_conv = nn.Sequential(\n            nn.BatchNorm2D(num_features=in_channels),\n            nn.LeakyReLU(leaky_relu_slope),\n            # apply downsampling on the y axis only\n            nn.MaxPool2D(kernel_size=(1, 2)), )\n\n        # conv layers\n        self.conv = nn.Sequential(\n            nn.Conv2D(\n                in_channels=in_channels,\n                out_channels=out_channels,\n                kernel_size=3,\n                padding=1,\n                bias_attr=False),\n            nn.BatchNorm2D(out_channels),\n            nn.LeakyReLU(leaky_relu_slope),\n            nn.Conv2D(\n                in_channels=out_channels,\n                out_channels=out_channels,\n                kernel_size=3,\n                padding=1,\n                bias_attr=False), )\n        # 1 x 1 convolution layer to match the feature dimensions\n        self.conv1by1 = None\n        if self.downsample:\n            self.conv1by1 = nn.Conv2D(\n                in_channels=in_channels,\n                out_channels=out_channels,\n                kernel_size=1,\n                bias_attr=False)\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): Shape (B, in_channels, T, n_mels).\n        Returns:\n            Tensor:\n                The residual output, Shape (B, out_channels, T, n_mels // 2).\n        \"\"\"\n        x = self.pre_conv(x)\n        if self.downsample:\n            x = self.conv(x) + self.conv1by1(x)\n        else:\n            x = self.conv(x) + x\n        return x\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/__init__.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .starganv2_vc import *\nfrom .starganv2_vc_updater import *\nfrom .AuxiliaryASR.model import *\nfrom .JDCNet.model import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/losses.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Any\nfrom typing import Dict\n\nimport paddle\nimport paddle.nn.functional as F\n\nfrom .transforms import build_transforms\n\n# 这些都写到 updater 里\n\n\ndef compute_d_loss(\n        nets: Dict[str, Any],\n        x_real: paddle.Tensor,\n        y_org: paddle.Tensor,\n        y_trg: paddle.Tensor,\n        z_trg: paddle.Tensor=None,\n        x_ref: paddle.Tensor=None,\n        # TODO: should be True here, but r1_reg has some bug now \n        use_r1_reg: bool=False,\n        use_adv_cls: bool=False,\n        use_con_reg: bool=False,\n        lambda_reg: float=1.,\n        lambda_adv_cls: float=0.1,\n        lambda_con_reg: float=10.):\n\n    assert (z_trg is None) != (x_ref is None)\n    # with real audios\n    x_real.stop_gradient = False\n    out = nets['discriminator'](x_real, y_org)\n    loss_real = adv_loss(out, 1)\n    # R1 regularizaition (https://arxiv.org/abs/1801.04406v4)\n    if use_r1_reg:\n        loss_reg = r1_reg(out, x_real)\n    else:\n        # loss_reg = paddle.to_tensor([0.], dtype=paddle.float32)\n        loss_reg = paddle.zeros([1])\n\n    # consistency regularization (bCR-GAN: https://arxiv.org/abs/2002.04724)\n    loss_con_reg = paddle.zeros([1])\n    if use_con_reg:\n        t = build_transforms()\n        out_aug = nets['discriminator'](t(x_real).detach(), y_org)\n        loss_con_reg += F.smooth_l1_loss(out, out_aug)\n\n    # with fake audios\n    with paddle.no_grad():\n        if z_trg is not None:\n            s_trg = nets['mapping_network'](z_trg, y_trg)\n        else:  # x_ref is not None\n            s_trg = nets['style_encoder'](x_ref, y_trg)\n\n        F0 = nets['F0_model'].get_feature_GAN(x_real)\n        x_fake = nets['generator'](x_real, s_trg, masks=None, F0=F0)\n    out = nets['discriminator'](x_fake, y_trg)\n    loss_fake = adv_loss(out, 0)\n    if use_con_reg:\n        out_aug = nets['discriminator'](t(x_fake).detach(), y_trg)\n        loss_con_reg += F.smooth_l1_loss(out, out_aug)\n\n    # adversarial classifier loss\n    if use_adv_cls:\n        out_de = nets['discriminator'].classifier(x_fake)\n        loss_real_adv_cls = F.cross_entropy(out_de[y_org != y_trg],\n                                            y_org[y_org != y_trg])\n\n        if use_con_reg:\n            out_de_aug = nets['discriminator'].classifier(t(x_fake).detach())\n            loss_con_reg += F.smooth_l1_loss(out_de, out_de_aug)\n    else:\n        loss_real_adv_cls = paddle.zeros([1]).mean()\n\n    loss = loss_real + loss_fake + lambda_reg * loss_reg + \\\n            lambda_adv_cls * loss_real_adv_cls + \\\n            lambda_con_reg * loss_con_reg\n\n    return loss\n\n\ndef compute_g_loss(nets: Dict[str, Any],\n                   x_real: paddle.Tensor,\n                   y_org: paddle.Tensor,\n                   y_trg: paddle.Tensor,\n                   z_trgs: paddle.Tensor=None,\n                   x_refs: paddle.Tensor=None,\n                   use_adv_cls: bool=False,\n                   lambda_sty: float=1.,\n                   lambda_cyc: float=5.,\n                   lambda_ds: float=1.,\n                   lambda_norm: float=1.,\n                   lambda_asr: float=10.,\n                   lambda_f0: float=5.,\n                   lambda_f0_sty: float=0.1,\n                   lambda_adv: float=2.,\n                   lambda_adv_cls: float=0.5,\n                   norm_bias: float=0.5):\n\n    assert (z_trgs is None) != (x_refs is None)\n    if z_trgs is not None:\n        z_trg, z_trg2 = z_trgs\n    if x_refs is not None:\n        x_ref, x_ref2 = x_refs\n\n    # compute style vectors\n    if z_trgs is not None:\n        s_trg = nets['mapping_network'](z_trg, y_trg)\n    else:\n        s_trg = nets['style_encoder'](x_ref, y_trg)\n\n    # compute ASR/F0 features (real)\n    # 源码没有用 .eval(), 使用了 no_grad()\n    # 我们使用了 .eval(), 开启 with paddle.no_grad() 会报错\n    F0_real, GAN_F0_real, cyc_F0_real = nets['F0_model'](x_real)\n    ASR_real = nets['asr_model'].get_feature(x_real)\n\n    # adversarial loss\n    x_fake = nets['generator'](x_real, s_trg, masks=None, F0=GAN_F0_real)\n    out = nets['discriminator'](x_fake, y_trg)\n    loss_adv = adv_loss(out, 1)\n\n    # compute ASR/F0 features (fake)\n    F0_fake, GAN_F0_fake, _ = nets['F0_model'](x_fake)\n    ASR_fake = nets['asr_model'].get_feature(x_fake)\n\n    # norm consistency loss\n    x_fake_norm = log_norm(x_fake)\n    x_real_norm = log_norm(x_real)\n    tmp = paddle.abs(x_fake_norm - x_real_norm) - norm_bias\n    loss_norm = ((paddle.nn.ReLU()(tmp))**2).mean()\n\n    # F0 loss\n    loss_f0 = f0_loss(F0_fake, F0_real)\n\n    # style F0 loss (style initialization)\n    if x_refs is not None and lambda_f0_sty > 0 and not use_adv_cls:\n        F0_sty, _, _ = nets['F0_model'](x_ref)\n        loss_f0_sty = F.l1_loss(\n            compute_mean_f0(F0_fake), compute_mean_f0(F0_sty))\n    else:\n        loss_f0_sty = paddle.zeros([1]).mean()\n\n    # ASR loss\n    loss_asr = F.smooth_l1_loss(ASR_fake, ASR_real)\n\n    # style reconstruction loss\n    s_pred = nets['style_encoder'](x_fake, y_trg)\n    loss_sty = paddle.mean(paddle.abs(s_pred - s_trg))\n\n    # diversity sensitive loss\n    if z_trgs is not None:\n        s_trg2 = nets['mapping_network'](z_trg2, y_trg)\n    else:\n        s_trg2 = nets['style_encoder'](x_ref2, y_trg)\n    x_fake2 = nets['generator'](x_real, s_trg2, masks=None, F0=GAN_F0_real)\n    x_fake2 = x_fake2.detach()\n    _, GAN_F0_fake2, _ = nets['F0_model'](x_fake2)\n    loss_ds = paddle.mean(paddle.abs(x_fake - x_fake2))\n    loss_ds += F.smooth_l1_loss(GAN_F0_fake, GAN_F0_fake2.detach())\n\n    # cycle-consistency loss\n    s_org = nets['style_encoder'](x_real, y_org)\n    x_rec = nets['generator'](x_fake, s_org, masks=None, F0=GAN_F0_fake)\n    loss_cyc = paddle.mean(paddle.abs(x_rec - x_real))\n    # F0 loss in cycle-consistency loss\n    if lambda_f0 > 0:\n        _, _, cyc_F0_rec = nets['F0_model'](x_rec)\n        loss_cyc += F.smooth_l1_loss(cyc_F0_rec, cyc_F0_real)\n    if lambda_asr > 0:\n        ASR_recon = nets['asr_model'].get_feature(x_rec)\n        loss_cyc += F.smooth_l1_loss(ASR_recon, ASR_real)\n\n    # adversarial classifier loss\n    if use_adv_cls:\n        out_de = nets['discriminator'].classifier(x_fake)\n        loss_adv_cls = F.cross_entropy(out_de[y_org != y_trg],\n                                       y_trg[y_org != y_trg])\n    else:\n        loss_adv_cls = paddle.zeros([1]).mean()\n\n    loss = lambda_adv * loss_adv + lambda_sty * loss_sty \\\n           - lambda_ds * loss_ds + lambda_cyc * loss_cyc \\\n           + lambda_norm * loss_norm \\\n           + lambda_asr * loss_asr \\\n           + lambda_f0 * loss_f0 \\\n           + lambda_f0_sty * loss_f0_sty \\\n           + lambda_adv_cls * loss_adv_cls\n\n    return loss\n\n\n# for norm consistency loss\ndef log_norm(x: paddle.Tensor, mean: float=-4, std: float=4, axis: int=2):\n    \"\"\"\n    normalized log mel -> mel -> norm -> log(norm)\n    \"\"\"\n    x = paddle.log(paddle.exp(x * std + mean).norm(axis=axis))\n    return x\n\n\n# for adversarial loss\ndef adv_loss(logits: paddle.Tensor, target: float):\n    assert target in [1, 0]\n    if len(logits.shape) > 1:\n        logits = logits.reshape([-1])\n    targets = paddle.full_like(logits, fill_value=target)\n    logits = logits.clip(min=-10, max=10)  # prevent nan\n    loss = F.binary_cross_entropy_with_logits(logits, targets)\n    return loss\n\n\n# for R1 regularization loss\ndef r1_reg(d_out: paddle.Tensor, x_in: paddle.Tensor):\n    # zero-centered gradient penalty for real images\n    batch_size = x_in.shape[0]\n    grad_dout = paddle.grad(\n        outputs=d_out.sum(),\n        inputs=x_in,\n        create_graph=True,\n        retain_graph=True,\n        only_inputs=True)[0]\n    grad_dout2 = grad_dout.pow(2)\n    assert (grad_dout2.shape == x_in.shape)\n    reg = 0.5 * grad_dout2.reshape((batch_size, -1)).sum(1).mean(0)\n    return reg\n\n\n# for F0 consistency loss\ndef compute_mean_f0(f0: paddle.Tensor):\n    f0_mean = f0.mean(-1)\n    f0_mean = f0_mean.expand((f0.shape[-1], f0_mean.shape[0])).transpose(\n        (1, 0))  # (B, M)\n    return f0_mean\n\n\ndef f0_loss(x_f0: paddle.Tensor, y_f0: paddle.Tensor):\n    \"\"\"\n    x.shape = (B, 1, M, L): predict\n    y.shape = (B, 1, M, L): target\n    \"\"\"\n    # compute the mean\n    x_mean = compute_mean_f0(x_f0)\n    y_mean = compute_mean_f0(y_f0)\n    loss = F.l1_loss(x_f0 / x_mean, y_f0 / y_mean)\n    return loss\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/starganv2_vc.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nStarGAN v2\nCopyright (c) 2020-present NAVER Corp.\nThis work is licensed under the Creative Commons Attribution-NonCommercial\n4.0 International License. To view a copy of this license, visit\nhttp://creativecommons.org/licenses/by-nc/4.0/ or send a letter to\nCreative Commons, PO Box 1866, Mountain View, CA 94042, USA.\n\"\"\"\nimport math\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.nets_utils import _reset_parameters\n\n\nclass DownSample(nn.Layer):\n    def __init__(self, layer_type: str):\n        super().__init__()\n        self.layer_type = layer_type\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): Shape (B, dim_in, n_mels, T).\n        Returns:\n            Tensor:\n                layer_type == 'none': Shape (B, dim_in, n_mels, T)\n                layer_type == 'timepreserve': Shape (B, dim_in, n_mels // 2, T)\n                layer_type == 'half': Shape (B, dim_in, n_mels // 2, T // 2)\n        \"\"\"\n        if self.layer_type == 'none':\n            return x\n        elif self.layer_type == 'timepreserve':\n            out = F.avg_pool2d(x, (2, 1))\n            return out\n        elif self.layer_type == 'half':\n            out = F.avg_pool2d(x, 2)\n            return out\n        else:\n            raise RuntimeError(\n                'Got unexpected donwsampletype %s, expected is [none, timepreserve, half]'\n                % self.layer_type)\n\n\nclass UpSample(nn.Layer):\n    def __init__(self, layer_type: str):\n        super().__init__()\n        self.layer_type = layer_type\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): Shape (B, dim_in, n_mels, T).\n        Returns:\n            Tensor:\n                layer_type == 'none': Shape (B, dim_in, n_mels, T)\n                layer_type == 'timepreserve': Shape (B, dim_in, n_mels * 2, T)\n                layer_type == 'half': Shape (B, dim_in, n_mels * 2, T * 2)\n        \"\"\"\n        if self.layer_type == 'none':\n            return x\n        elif self.layer_type == 'timepreserve':\n            out = F.interpolate(x, scale_factor=(2, 1), mode='nearest')\n            return out\n        elif self.layer_type == 'half':\n            out = F.interpolate(x, scale_factor=2, mode='nearest')\n            return out\n        else:\n            raise RuntimeError(\n                'Got unexpected upsampletype %s, expected is [none, timepreserve, half]'\n                % self.layer_type)\n\n\nclass ResBlk(nn.Layer):\n    def __init__(self,\n                 dim_in: int,\n                 dim_out: int,\n                 actv: nn.LeakyReLU=nn.LeakyReLU(0.2),\n                 normalize: bool=False,\n                 downsample: str='none'):\n        super().__init__()\n        self.actv = actv\n        self.normalize = normalize\n        self.downsample = DownSample(layer_type=downsample)\n        self.learned_sc = dim_in != dim_out\n        self._build_weights(dim_in, dim_out)\n\n    def _build_weights(self, dim_in: int, dim_out: int):\n        self.conv1 = nn.Conv2D(\n            in_channels=dim_in,\n            out_channels=dim_in,\n            kernel_size=3,\n            stride=1,\n            padding=1)\n        self.conv2 = nn.Conv2D(\n            in_channels=dim_in,\n            out_channels=dim_out,\n            kernel_size=3,\n            stride=1,\n            padding=1)\n        if self.normalize:\n            self.norm1 = nn.InstanceNorm2D(dim_in)\n            self.norm2 = nn.InstanceNorm2D(dim_in)\n        if self.learned_sc:\n            self.conv1x1 = nn.Conv2D(\n                in_channels=dim_in,\n                out_channels=dim_out,\n                kernel_size=1,\n                stride=1,\n                padding=0,\n                bias_attr=False)\n\n    def _shortcut(self, x: paddle.Tensor):\n        if self.learned_sc:\n            x = self.conv1x1(x)\n        if self.downsample:\n            x = self.downsample(x)\n        return x\n\n    def _residual(self, x: paddle.Tensor):\n        if self.normalize:\n            x = self.norm1(x)\n        x = self.actv(x)\n        x = self.conv1(x)\n        x = self.downsample(x)\n        if self.normalize:\n            x = self.norm2(x)\n        x = self.actv(x)\n        x = self.conv2(x)\n        return x\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): Shape (B, dim_in, n_mels, T).\n        Returns:\n            Tensor:\n                downsample == 'none': Shape (B, dim_in, n_mels, T).\n                downsample == 'timepreserve': Shape (B, dim_out, T, n_mels // 2, T).\n                downsample == 'half': Shape (B, dim_out, T, n_mels // 2, T // 2).\n        \"\"\"\n        x = self._shortcut(x) + self._residual(x)\n        # unit variance\n        out = x / math.sqrt(2)\n        return out\n\n\nclass AdaIN(nn.Layer):\n    def __init__(self, style_dim: int, num_features: int):\n        super().__init__()\n        self.norm = nn.InstanceNorm2D(\n            num_features=num_features, weight_attr=False, bias_attr=False)\n        self.fc = nn.Linear(style_dim, num_features * 2)\n\n    def forward(self, x: paddle.Tensor, s: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): Shape (B, style_dim, n_mels, T).\n            s(Tensor(float32)): Shape (style_dim, ).\n        Returns:\n            Tensor:\n                Shape (B, style_dim, T, n_mels, T).\n        \"\"\"\n        if len(s.shape) == 1:\n            s = s[None]\n        h = self.fc(s)\n        h = h.reshape((h.shape[0], h.shape[1], 1, 1))\n        gamma, beta = paddle.split(h, 2, axis=1)\n        out = (1 + gamma) * self.norm(x) + beta\n        return out\n\n\nclass AdainResBlk(nn.Layer):\n    def __init__(self,\n                 dim_in: int,\n                 dim_out: int,\n                 style_dim: int=64,\n                 w_hpf: int=0,\n                 actv: nn.Layer=nn.LeakyReLU(0.2),\n                 upsample: str='none'):\n        super().__init__()\n        self.w_hpf = w_hpf\n        self.actv = actv\n        self.upsample = UpSample(layer_type=upsample)\n        self.learned_sc = dim_in != dim_out\n        self._build_weights(dim_in, dim_out, style_dim)\n        self.layer_type = upsample\n\n    def _build_weights(self, dim_in: int, dim_out: int, style_dim: int=64):\n        self.conv1 = nn.Conv2D(\n            in_channels=dim_in,\n            out_channels=dim_out,\n            kernel_size=3,\n            stride=1,\n            padding=1)\n        self.conv2 = nn.Conv2D(\n            in_channels=dim_out,\n            out_channels=dim_out,\n            kernel_size=3,\n            stride=1,\n            padding=1)\n        self.norm1 = AdaIN(style_dim=style_dim, num_features=dim_in)\n        self.norm2 = AdaIN(style_dim=style_dim, num_features=dim_out)\n        if self.learned_sc:\n            self.conv1x1 = nn.Conv2D(\n                in_channels=dim_in,\n                out_channels=dim_out,\n                kernel_size=1,\n                stride=1,\n                padding=0,\n                bias_attr=False)\n\n    def _shortcut(self, x: paddle.Tensor):\n        x = self.upsample(x)\n        if self.learned_sc:\n            x = self.conv1x1(x)\n        return x\n\n    def _residual(self, x: paddle.Tensor, s: paddle.Tensor):\n        x = self.norm1(x, s)\n        x = self.actv(x)\n        x = self.upsample(x)\n        x = self.conv1(x)\n        x = self.norm2(x, s)\n        x = self.actv(x)\n        x = self.conv2(x)\n        return x\n\n    def forward(self, x: paddle.Tensor, s: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): \n                Shape (B, dim_in, n_mels, T).\n            s(Tensor(float32)):\n                Shape (64,).\n        Returns:\n            Tensor:\n                upsample == 'none': Shape (B, dim_out, T, n_mels, T).  \n                upsample == 'timepreserve': Shape (B, dim_out, T, n_mels * 2, T).\n                upsample == 'half': Shape (B, dim_out, T, n_mels * 2, T * 2).  \n        \"\"\"\n        out = self._residual(x, s)\n        if self.w_hpf == 0:\n            out = (out + self._shortcut(x)) / math.sqrt(2)\n        return out\n\n\nclass HighPass(nn.Layer):\n    def __init__(self, w_hpf: int):\n        super().__init__()\n        self.filter = paddle.to_tensor([[-1, -1, -1], [-1, 8., -1],\n                                        [-1, -1, -1]]) / w_hpf\n\n    def forward(self, x: paddle.Tensor):\n        filter = self.filter.unsqueeze(0).unsqueeze(1).tile(\n            [x.shape[1], 1, 1, 1])\n        out = F.conv2d(x, filter, padding=1, groups=x.shape[1])\n        return out\n\n\nclass Generator(nn.Layer):\n    def __init__(self,\n                 dim_in: int=48,\n                 style_dim: int=48,\n                 max_conv_dim: int=48 * 8,\n                 w_hpf: int=1,\n                 F0_channel: int=0):\n        super().__init__()\n\n        self.stem = nn.Conv2D(\n            in_channels=1,\n            out_channels=dim_in,\n            kernel_size=3,\n            stride=1,\n            padding=1)\n        self.encode = nn.LayerList()\n        self.decode = nn.LayerList()\n        self.to_out = nn.Sequential(\n            nn.InstanceNorm2D(dim_in),\n            nn.LeakyReLU(0.2),\n            nn.Conv2D(\n                in_channels=dim_in,\n                out_channels=1,\n                kernel_size=1,\n                stride=1,\n                padding=0))\n        self.F0_channel = F0_channel\n        # down/up-sampling blocks\n        # int(np.log2(img_size)) - 4\n        repeat_num = 4\n        if w_hpf > 0:\n            repeat_num += 1\n\n        for lid in range(repeat_num):\n            if lid in [1, 3]:\n                _downtype = 'timepreserve'\n            else:\n                _downtype = 'half'\n\n            dim_out = min(dim_in * 2, max_conv_dim)\n            self.encode.append(\n                ResBlk(\n                    dim_in=dim_in,\n                    dim_out=dim_out,\n                    normalize=True,\n                    downsample=_downtype))\n            (self.decode.insert if lid else\n             lambda i, sublayer: self.decode.append(sublayer))(0, AdainResBlk(\n                 dim_in=dim_out,\n                 dim_out=dim_in,\n                 style_dim=style_dim,\n                 w_hpf=w_hpf,\n                 upsample=_downtype))  # stack-like\n            dim_in = dim_out\n        # bottleneck blocks (encoder)\n        for _ in range(2):\n            self.encode.append(\n                ResBlk(dim_in=dim_out, dim_out=dim_out, normalize=True))\n        # F0 blocks \n        if F0_channel != 0:\n            self.decode.insert(0,\n                               AdainResBlk(\n                                   dim_in=dim_out + int(F0_channel / 2),\n                                   dim_out=dim_out,\n                                   style_dim=style_dim,\n                                   w_hpf=w_hpf))\n        # bottleneck blocks (decoder)\n        for _ in range(2):\n            self.decode.insert(0,\n                               AdainResBlk(\n                                   dim_in=dim_out + int(F0_channel / 2),\n                                   dim_out=dim_out + int(F0_channel / 2),\n                                   style_dim=style_dim,\n                                   w_hpf=w_hpf))\n        if F0_channel != 0:\n            self.F0_conv = nn.Sequential(\n                ResBlk(\n                    dim_in=F0_channel,\n                    dim_out=int(F0_channel / 2),\n                    normalize=True,\n                    downsample=\"half\"), )\n        if w_hpf > 0:\n            self.hpf = HighPass(w_hpf)\n\n        self.reset_parameters()\n\n    def forward(self,\n                x: paddle.Tensor,\n                s: paddle.Tensor,\n                masks: paddle.Tensor=None,\n                F0: paddle.Tensor=None):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): \n                Shape (B, 1, n_mels, T).\n            s(Tensor(float32)):\n                Shape (64,).\n            masks:\n                None.\n            F0:\n                Shape (B, num_features(256), n_mels // 8, T).\n        Returns:\n            Tensor:\n                output of generator. Shape (B, 1, n_mels, T // 4 * 4)\n        \"\"\"\n        x = self.stem(x)\n        cache = {}\n        # output: (B, max_conv_dim, n_mels // 16, T // 4)\n        for block in self.encode:\n            if (masks is not None) and (x.shape[2] in [32, 64, 128]):\n                cache[x.shape[2]] = x\n            x = block(x)\n        if F0 is not None:\n            # input: (B, num_features(256), n_mels // 8, T)\n            # output: (B, num_features(256) // 2, n_mels // 16, T // 2)\n            F0 = self.F0_conv(F0)\n            # output: (B, num_features(256) // 2, n_mels // 16, T // 4)\n            F0 = F.adaptive_avg_pool2d(F0, [x.shape[-2], x.shape[-1]])\n            x = paddle.concat([x, F0], axis=1)\n        # input: (B, max_conv_dim+num_features(256) // 2, n_mels // 16, T // 4 * 4)\n        # output: (B, dim_in, n_mels, T // 4 * 4)\n        for block in self.decode:\n            x = block(x, s)\n            if (masks is not None) and (x.shape[2] in [32, 64, 128]):\n                mask = masks[0] if x.shape[2] in [32] else masks[1]\n                mask = F.interpolate(mask, size=x.shape[2], mode='bilinear')\n                x = x + self.hpf(mask * cache[x.shape[2]])\n        out = self.to_out(x)\n        return out\n\n    def reset_parameters(self):\n        self.apply(_reset_parameters)\n\n\nclass MappingNetwork(nn.Layer):\n    def __init__(self,\n                 latent_dim: int=16,\n                 style_dim: int=48,\n                 num_domains: int=2,\n                 hidden_dim: int=384):\n        super().__init__()\n        layers = []\n        layers += [nn.Linear(latent_dim, hidden_dim)]\n        layers += [nn.ReLU()]\n        for _ in range(3):\n            layers += [nn.Linear(hidden_dim, hidden_dim)]\n            layers += [nn.ReLU()]\n        self.shared = nn.Sequential(*layers)\n\n        self.unshared = nn.LayerList()\n        for _ in range(num_domains):\n            self.unshared.extend([\n                nn.Sequential(\n                    nn.Linear(hidden_dim, hidden_dim),\n                    nn.ReLU(),\n                    nn.Linear(hidden_dim, hidden_dim),\n                    nn.ReLU(),\n                    nn.Linear(hidden_dim, hidden_dim),\n                    nn.ReLU(), nn.Linear(hidden_dim, style_dim))\n            ])\n\n        self.reset_parameters()\n\n    def forward(self, z: paddle.Tensor, y: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            z(Tensor(float32)): \n                Shape (B, latent_dim).\n            y(Tensor(float32)):\n                speaker label. Shape (B, ).    \n        Returns:\n            Tensor:\n                Shape (style_dim, )\n        \"\"\"\n        h = self.shared(z)\n        out = []\n        for layer in self.unshared:\n            out += [layer(h)]\n        # (B, num_domains, style_dim)\n        out = paddle.stack(out, axis=1)\n        idx = paddle.arange(y.shape[0])\n        # (style_dim, )\n        s = out[idx, y]\n        return s\n\n    def reset_parameters(self):\n        self.apply(_reset_parameters)\n\n\nclass StyleEncoder(nn.Layer):\n    def __init__(self,\n                 dim_in: int=48,\n                 style_dim: int=48,\n                 num_domains: int=2,\n                 max_conv_dim: int=384):\n        super().__init__()\n        blocks = []\n        blocks += [\n            nn.Conv2D(\n                in_channels=1,\n                out_channels=dim_in,\n                kernel_size=3,\n                stride=1,\n                padding=1)\n        ]\n        repeat_num = 4\n        for _ in range(repeat_num):\n            dim_out = min(dim_in * 2, max_conv_dim)\n            blocks += [\n                ResBlk(dim_in=dim_in, dim_out=dim_out, downsample='half')\n            ]\n            dim_in = dim_out\n\n        blocks += [nn.LeakyReLU(0.2)]\n        blocks += [\n            nn.Conv2D(\n                in_channels=dim_out,\n                out_channels=dim_out,\n                kernel_size=5,\n                stride=1,\n                padding=0)\n        ]\n        blocks += [nn.AdaptiveAvgPool2D(1)]\n        blocks += [nn.LeakyReLU(0.2)]\n        self.shared = nn.Sequential(*blocks)\n        self.unshared = nn.LayerList()\n        for _ in range(num_domains):\n            self.unshared.append(nn.Linear(dim_out, style_dim))\n\n        self.reset_parameters()\n\n    def forward(self, x: paddle.Tensor, y: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)): \n                Shape (B, 1, n_mels, T).   \n            y(Tensor(float32)):\n                speaker label. Shape (B, ).\n        Returns:\n            Tensor:\n                Shape (style_dim, )\n        \"\"\"\n        h = self.shared(x)\n        h = h.reshape((h.shape[0], -1))\n        out = []\n        for layer in self.unshared:\n            out += [layer(h)]\n        # (B, num_domains, style_dim)\n        out = paddle.stack(out, axis=1)\n        idx = paddle.arange(y.shape[0])\n        # (style_dim,)\n        s = out[idx, y]\n        return s\n\n    def reset_parameters(self):\n        self.apply(_reset_parameters)\n\n\nclass Discriminator(nn.Layer):\n    def __init__(self,\n                 dim_in: int=48,\n                 num_domains: int=2,\n                 max_conv_dim: int=384,\n                 repeat_num: int=4):\n        super().__init__()\n        # real/fake discriminator\n        self.dis = Discriminator2D(\n            dim_in=dim_in,\n            num_domains=num_domains,\n            max_conv_dim=max_conv_dim,\n            repeat_num=repeat_num)\n        # adversarial classifier\n        self.cls = Discriminator2D(\n            dim_in=dim_in,\n            num_domains=num_domains,\n            max_conv_dim=max_conv_dim,\n            repeat_num=repeat_num)\n        self.num_domains = num_domains\n\n        self.reset_parameters()\n\n    def forward(self, x: paddle.Tensor, y: paddle.Tensor):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x(Tensor(float32)):\n                Shape (B, 1, 80, T).\n            y(Tensor(float32)):\n                Shape (B, ). \n        Returns:\n            Tensor:\n                Shape (B, )\n        \"\"\"\n        out = self.dis(x, y)\n        return out\n\n    def classifier(self, x: paddle.Tensor):\n        out = self.cls.get_feature(x)\n        return out\n\n    def reset_parameters(self):\n        self.apply(_reset_parameters)\n\n\nclass Discriminator2D(nn.Layer):\n    def __init__(self,\n                 dim_in: int=48,\n                 num_domains: int=2,\n                 max_conv_dim: int=384,\n                 repeat_num: int=4):\n        super().__init__()\n        blocks = []\n        blocks += [\n            nn.Conv2D(\n                in_channels=1,\n                out_channels=dim_in,\n                kernel_size=3,\n                stride=1,\n                padding=1)\n        ]\n\n        for lid in range(repeat_num):\n            dim_out = min(dim_in * 2, max_conv_dim)\n            blocks += [ResBlk(dim_in, dim_out, downsample='half')]\n            dim_in = dim_out\n\n        blocks += [nn.LeakyReLU(0.2)]\n        blocks += [\n            nn.Conv2D(\n                in_channels=dim_out,\n                out_channels=dim_out,\n                kernel_size=5,\n                stride=1,\n                padding=0)\n        ]\n        blocks += [nn.LeakyReLU(0.2)]\n        blocks += [nn.AdaptiveAvgPool2D(1)]\n        blocks += [\n            nn.Conv2D(\n                in_channels=dim_out,\n                out_channels=num_domains,\n                kernel_size=1,\n                stride=1,\n                padding=0)\n        ]\n        self.main = nn.Sequential(*blocks)\n\n    def get_feature(self, x: paddle.Tensor):\n        out = self.main(x)\n        # (B, num_domains)\n        out = out.reshape((out.shape[0], -1))\n        return out\n\n    def forward(self, x: paddle.Tensor, y: paddle.Tensor):\n        out = self.get_feature(x)\n        idx = paddle.arange(y.shape[0])\n        # (B,) ?\n        out = out[idx, y]\n        return out\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/starganv2_vc_updater.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom typing import Any\nfrom typing import Dict\n\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.models.starganv2_vc.losses import compute_d_loss\nfrom paddlespeech.t2s.models.starganv2_vc.losses import compute_g_loss\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass StarGANv2VCUpdater(StandardUpdater):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 optimizers: Dict[str, Optimizer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 g_loss_params: Dict[str, Any]={\n                     'lambda_sty': 1.,\n                     'lambda_cyc': 5.,\n                     'lambda_ds': 1.,\n                     'lambda_norm': 1.,\n                     'lambda_asr': 10.,\n                     'lambda_f0': 5.,\n                     'lambda_f0_sty': 0.1,\n                     'lambda_adv': 2.,\n                     'lambda_adv_cls': 0.5,\n                     'norm_bias': 0.5,\n                 },\n                 d_loss_params: Dict[str, Any]={\n                     'lambda_reg': 1.,\n                     'lambda_adv_cls': 0.1,\n                     'lambda_con_reg': 10.,\n                 },\n                 adv_cls_epoch: int=50,\n                 con_reg_epoch: int=30,\n                 use_r1_reg: bool=False,\n                 output_dir=None):\n        self.models = models\n\n        self.optimizers = optimizers\n        self.optimizer_g = optimizers['generator']\n        self.optimizer_s = optimizers['style_encoder']\n        self.optimizer_m = optimizers['mapping_network']\n        self.optimizer_d = optimizers['discriminator']\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_s = schedulers['style_encoder']\n        self.scheduler_m = schedulers['mapping_network']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.g_loss_params = g_loss_params\n        self.d_loss_params = d_loss_params\n\n        self.use_r1_reg = use_r1_reg\n        self.con_reg_epoch = con_reg_epoch\n        self.adv_cls_epoch = adv_cls_epoch\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def zero_grad(self):\n        self.optimizer_d.clear_grad()\n        self.optimizer_g.clear_grad()\n        self.optimizer_m.clear_grad()\n        self.optimizer_s.clear_grad()\n\n    def scheduler(self):\n        self.scheduler_d.step()\n        self.scheduler_g.step()\n        self.scheduler_m.step()\n        self.scheduler_s.step()\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        x_real = batch['x_real']\n        y_org = batch['y_org']\n        x_ref = batch['x_ref']\n        x_ref2 = batch['x_ref2']\n        y_trg = batch['y_trg']\n        z_trg = batch['z_trg']\n        z_trg2 = batch['z_trg2']\n\n        use_con_reg = (self.state.epoch >= self.con_reg_epoch)\n        use_adv_cls = (self.state.epoch >= self.adv_cls_epoch)\n\n        # Discriminator loss\n        # train the discriminator (by random reference)\n        self.zero_grad()\n        random_d_loss = compute_d_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            z_trg=z_trg,\n            use_adv_cls=use_adv_cls,\n            use_con_reg=use_con_reg,\n            **self.d_loss_params)\n        random_d_loss.backward()\n        self.optimizer_d.step()\n        # train the discriminator (by target reference)\n        self.zero_grad()\n        target_d_loss = compute_d_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            x_ref=x_ref,\n            use_adv_cls=use_adv_cls,\n            use_con_reg=use_con_reg,\n            **self.d_loss_params)\n        target_d_loss.backward()\n        self.optimizer_d.step()\n        report(\"train/random_d_loss\", float(random_d_loss))\n        report(\"train/target_d_loss\", float(target_d_loss))\n        losses_dict[\"random_d_loss\"] = float(random_d_loss)\n        losses_dict[\"target_d_loss\"] = float(target_d_loss)\n\n        # Generator\n        # train the generator (by random reference)\n        self.zero_grad()\n        random_g_loss = compute_g_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            z_trgs=[z_trg, z_trg2],\n            use_adv_cls=use_adv_cls,\n            **self.g_loss_params)\n        random_g_loss.backward()\n        self.optimizer_g.step()\n        self.optimizer_m.step()\n        self.optimizer_s.step()\n\n        # train the generator (by target reference)\n        self.zero_grad()\n        target_g_loss = compute_g_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            x_refs=[x_ref, x_ref2],\n            use_adv_cls=use_adv_cls,\n            **self.g_loss_params)\n        target_g_loss.backward()\n        # 此处是否要 optimizer_g optimizer_m optimizer_s 都写上？\n        # 源码没写上后两个是否是疏忽？\n        self.optimizer_g.step()\n        # self.optimizer_m.step()\n        # self.optimizer_s.step()\n        report(\"train/random_g_loss\", float(random_g_loss))\n        report(\"train/target_g_loss\", float(target_g_loss))\n        losses_dict[\"random_g_loss\"] = float(random_g_loss)\n        losses_dict[\"target_g_loss\"] = float(target_g_loss)\n\n        self.scheduler()\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass StarGANv2VCEvaluator(StandardEvaluator):\n    def __init__(self,\n                 models: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 g_loss_params: Dict[str, Any]={\n                     'lambda_sty': 1.,\n                     'lambda_cyc': 5.,\n                     'lambda_ds': 1.,\n                     'lambda_norm': 1.,\n                     'lambda_asr': 10.,\n                     'lambda_f0': 5.,\n                     'lambda_f0_sty': 0.1,\n                     'lambda_adv': 2.,\n                     'lambda_adv_cls': 0.5,\n                     'norm_bias': 0.5,\n                 },\n                 d_loss_params: Dict[str, Any]={\n                     'lambda_reg': 1.,\n                     'lambda_adv_cls': 0.1,\n                     'lambda_con_reg': 10.,\n                 },\n                 adv_cls_epoch: int=50,\n                 con_reg_epoch: int=30,\n                 use_r1_reg: bool=False,\n                 output_dir=None):\n        self.models = models\n\n        self.dataloader = dataloader\n\n        self.g_loss_params = g_loss_params\n        self.d_loss_params = d_loss_params\n\n        self.use_r1_reg = use_r1_reg\n        self.con_reg_epoch = con_reg_epoch\n        self.adv_cls_epoch = adv_cls_epoch\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        x_real = batch['x_real']\n        y_org = batch['y_org']\n        x_ref = batch['x_ref']\n        x_ref2 = batch['x_ref2']\n        y_trg = batch['y_trg']\n        z_trg = batch['z_trg']\n        z_trg2 = batch['z_trg2']\n\n        # eval the discriminator\n\n        random_d_loss = compute_d_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            z_trg=z_trg,\n            use_r1_reg=self.use_r1_reg,\n            use_adv_cls=use_adv_cls,\n            **self.d_loss_params)\n\n        target_d_loss = compute_d_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            x_ref=x_ref,\n            use_r1_reg=self.use_r1_reg,\n            use_adv_cls=use_adv_cls,\n            **self.d_loss_params)\n\n        report(\"eval/random_d_loss\", float(random_d_loss))\n        report(\"eval/target_d_loss\", float(target_d_loss))\n        losses_dict[\"random_d_loss\"] = float(random_d_loss)\n        losses_dict[\"target_d_loss\"] = float(target_d_loss)\n\n        # eval the generator\n\n        random_g_loss = compute_g_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            z_trgs=[z_trg, z_trg2],\n            use_adv_cls=use_adv_cls,\n            **self.g_loss_params)\n\n        target_g_loss = compute_g_loss(\n            nets=self.models,\n            x_real=x_real,\n            y_org=y_org,\n            y_trg=y_trg,\n            x_refs=[x_ref, x_ref2],\n            use_adv_cls=use_adv_cls,\n            **self.g_loss_params)\n\n        report(\"eval/random_g_loss\", float(random_g_loss))\n        report(\"eval/target_g_loss\", float(target_g_loss))\n        losses_dict[\"random_g_loss\"] = float(random_g_loss)\n        losses_dict[\"target_g_loss\"] = float(target_g_loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/starganv2_vc/transforms.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport random\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\n\n## 1. RandomTimeStrech\nclass TimeStrech(nn.Layer):\n    def __init__(self, scale):\n        super().__init__()\n        self.scale = scale\n\n    def forward(self, x: paddle.Tensor):\n        mel_size = x.shape[-1]\n\n        x = F.interpolate(\n            x,\n            scale_factor=(1, self.scale),\n            align_corners=False,\n            mode='bilinear').squeeze()\n\n        if x.shape[-1] < mel_size:\n            noise_length = (mel_size - x.shape[-1])\n            random_pos = random.randint(0, x.shape[-1]) - noise_length\n            if random_pos < 0:\n                random_pos = 0\n            noise = x[..., random_pos:random_pos + noise_length]\n            x = paddle.concat([x, noise], axis=-1)\n        else:\n            x = x[..., :mel_size]\n\n        return x.unsqueeze(1)\n\n\n## 2. PitchShift\nclass PitchShift(nn.Layer):\n    def __init__(self, shift):\n        super().__init__()\n        self.shift = shift\n\n    def forward(self, x: paddle.Tensor):\n        if len(x.shape) == 2:\n            x = x.unsqueeze(0)\n        x = x.squeeze()\n        mel_size = x.shape[1]\n        shift_scale = (mel_size + self.shift) / mel_size\n        x = F.interpolate(\n            x.unsqueeze(1),\n            scale_factor=(shift_scale, 1.),\n            align_corners=False,\n            mode='bilinear').squeeze(1)\n\n        x = x[:, :mel_size]\n        if x.shape[1] < mel_size:\n            pad_size = mel_size - x.shape[1]\n            x = paddle.cat(\n                [x, paddle.zeros(x.shape[0], pad_size, x.shape[2])], axis=1)\n        x = x.squeeze()\n        return x.unsqueeze(1)\n\n\n## 3. ShiftBias\nclass ShiftBias(nn.Layer):\n    def __init__(self, bias):\n        super().__init__()\n        self.bias = bias\n\n    def forward(self, x: paddle.Tensor):\n        return x + self.bias\n\n\n## 4. Scaling\nclass SpectScaling(nn.Layer):\n    def __init__(self, scale):\n        super().__init__()\n        self.scale = scale\n\n    def forward(self, x: paddle.Tensor):\n        return x * self.scale\n\n\n## 5. Time Flip\nclass TimeFlip(nn.Layer):\n    def __init__(self, length):\n        super().__init__()\n        self.length = round(length)\n\n    def forward(self, x: paddle.Tensor):\n        if self.length > 1:\n            start = np.random.randint(0, x.shape[-1] - self.length)\n            x_ret = x.clone()\n            x_ret[..., start:start + self.length] = paddle.flip(\n                x[..., start:start + self.length], axis=[-1])\n            x = x_ret\n        return x\n\n\nclass PhaseShuffle2D(nn.Layer):\n    def __init__(self, n: int=2):\n        super().__init__()\n        self.n = n\n        self.random = random.Random(1)\n\n    def forward(self, x: paddle.Tensor, move=None):\n        # x.size = (B, C, M, L)\n        if move is None:\n            move = self.random.randint(-self.n, self.n)\n\n        if move == 0:\n            return x\n        else:\n            left = x[:, :, :, :move]\n            right = x[:, :, :, move:]\n            shuffled = paddle.concat([right, left], axis=3)\n\n        return shuffled\n\n\ndef build_transforms():\n    transforms = [\n        lambda M: TimeStrech(1 + (np.random.random() - 0.5) * M * 0.2),\n        lambda M: SpectScaling(1 + (np.random.random() - 1) * M * 0.1),\n        lambda M: PhaseShuffle2D(192),\n    ]\n    N, M = len(transforms), np.random.random()\n    composed = nn.Sequential(\n        * [trans(M) for trans in np.random.choice(transforms, N)])\n    return composed\n"
  },
  {
    "path": "paddlespeech/t2s/models/tacotron2/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .tacotron2 import *\nfrom .tacotron2_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/tacotron2/tacotron2.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Tacotron 2 related modules for paddle\"\"\"\nimport logging\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\nfrom paddlespeech.t2s.modules.tacotron2.attentions import AttForward\nfrom paddlespeech.t2s.modules.tacotron2.attentions import AttForwardTA\nfrom paddlespeech.t2s.modules.tacotron2.attentions import AttLoc\nfrom paddlespeech.t2s.modules.tacotron2.decoder import Decoder\nfrom paddlespeech.t2s.modules.tacotron2.encoder import Encoder\n\n\nclass Tacotron2(nn.Layer):\n    \"\"\"Tacotron2 module for end-to-end text-to-speech.\n\n    This is a module of Spectrogram prediction network in Tacotron2 described\n    in `Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`_,\n    which converts the sequence of characters into the sequence of Mel-filterbanks.\n\n    .. _`Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`:\n       https://arxiv.org/abs/1712.05884\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # network structure related\n            idim: int,\n            odim: int,\n            embed_dim: int=512,\n            elayers: int=1,\n            eunits: int=512,\n            econv_layers: int=3,\n            econv_chans: int=512,\n            econv_filts: int=5,\n            atype: str=\"location\",\n            adim: int=512,\n            aconv_chans: int=32,\n            aconv_filts: int=15,\n            cumulate_att_w: bool=True,\n            dlayers: int=2,\n            dunits: int=1024,\n            prenet_layers: int=2,\n            prenet_units: int=256,\n            postnet_layers: int=5,\n            postnet_chans: int=512,\n            postnet_filts: int=5,\n            output_activation: Optional[str]=None,\n            use_batch_norm: bool=True,\n            use_concate: bool=True,\n            use_residual: bool=False,\n            reduction_factor: int=1,\n            # extra embedding related\n            spk_num: Optional[int]=None,\n            lang_num: Optional[int]=None,\n            spk_embed_dim: Optional[int]=None,\n            spk_embed_integration_type: str=\"concat\",\n            dropout_rate: float=0.5,\n            zoneout_rate: float=0.1,\n            # training related\n            init_type: str=\"xavier_uniform\", ):\n        \"\"\"Initialize Tacotron2 module.\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            odim (int): \n                Dimension of the outputs.\n            embed_dim (int): \n                Dimension of the token embedding.\n            elayers (int): \n                Number of encoder blstm layers.\n            eunits (int): \n                Number of encoder blstm units.\n            econv_layers (int): \n                Number of encoder conv layers.\n            econv_filts (int): \n                Number of encoder conv filter size.\n            econv_chans (int): \n                Number of encoder conv filter channels.\n            dlayers (int): \n                Number of decoder lstm layers.\n            dunits (int): \n                Number of decoder lstm units.\n            prenet_layers (int): \n                Number of prenet layers.\n            prenet_units (int): \n                Number of prenet units.\n            postnet_layers (int): \n                Number of postnet layers.\n            postnet_filts (int): \n                Number of postnet filter size.\n            postnet_chans (int): \n                Number of postnet filter channels.\n            output_activation (str): \n                Name of activation function for outputs.\n            adim (int): \n                Number of dimension of mlp in attention.\n            aconv_chans (int): \n                Number of attention conv filter channels.\n            aconv_filts (int): \n                Number of attention conv filter size.\n            cumulate_att_w (bool): \n                Whether to cumulate previous attention weight.\n            use_batch_norm (bool): \n                Whether to use batch normalization.\n            use_concate (bool): \n                Whether to concat enc outputs w/ dec lstm outputs.\n            reduction_factor (int): \n                Reduction factor.\n            spk_num (Optional[int]): \n                Number of speakers. If set to > 1, assume that the\n                sids will be provided as the input and use sid embedding layer.\n            lang_num (Optional[int]): \n                Number of languages. If set to > 1, assume that the\n                lids will be provided as the input and use sid embedding layer.\n            spk_embed_dim (Optional[int]): \n                Speaker embedding dimension. If set to > 0,\n                assume that spk_emb will be provided as the input.\n            spk_embed_integration_type (str): \n                How to integrate speaker embedding.\n            dropout_rate (float): \n                Dropout rate.\n            zoneout_rate (float): \n                Zoneout rate.\n        \"\"\"\n        super().__init__()\n\n        # store hyperparameters\n        self.idim = idim\n        self.odim = odim\n        self.eos = idim - 1\n        self.cumulate_att_w = cumulate_att_w\n        self.reduction_factor = reduction_factor\n\n        # define activation function for the final output\n        if output_activation is None:\n            self.output_activation_fn = None\n        elif hasattr(F, output_activation):\n            self.output_activation_fn = getattr(F, output_activation)\n        else:\n            raise ValueError(f\"there is no such an activation function. \"\n                             f\"({output_activation})\")\n\n        # set padding idx\n        padding_idx = 0\n        self.padding_idx = padding_idx\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        # define network modules\n        self.enc = Encoder(\n            idim=idim,\n            embed_dim=embed_dim,\n            elayers=elayers,\n            eunits=eunits,\n            econv_layers=econv_layers,\n            econv_chans=econv_chans,\n            econv_filts=econv_filts,\n            use_batch_norm=use_batch_norm,\n            use_residual=use_residual,\n            dropout_rate=dropout_rate,\n            padding_idx=padding_idx, )\n\n        self.spk_num = None\n        if spk_num is not None and spk_num > 1:\n            self.spk_num = spk_num\n            self.sid_emb = nn.Embedding(spk_num, eunits)\n        self.lang_num = None\n        if lang_num is not None and lang_num > 1:\n            self.lang_num = lang_num\n            self.lid_emb = nn.Embedding(lang_num, eunits)\n\n        self.spk_embed_dim = None\n        if spk_embed_dim is not None and spk_embed_dim > 0:\n            self.spk_embed_dim = spk_embed_dim\n            self.spk_embed_integration_type = spk_embed_integration_type\n        if self.spk_embed_dim is None:\n            dec_idim = eunits\n        elif self.spk_embed_integration_type == \"concat\":\n            dec_idim = eunits + spk_embed_dim\n        elif self.spk_embed_integration_type == \"add\":\n            dec_idim = eunits\n            self.projection = nn.Linear(self.spk_embed_dim, eunits)\n        else:\n            raise ValueError(f\"{spk_embed_integration_type} is not supported.\")\n\n        if atype == \"location\":\n            att = AttLoc(dec_idim, dunits, adim, aconv_chans, aconv_filts)\n        elif atype == \"forward\":\n            att = AttForward(dec_idim, dunits, adim, aconv_chans, aconv_filts)\n            if self.cumulate_att_w:\n                logging.warning(\"cumulation of attention weights is disabled \"\n                                \"in forward attention.\")\n                self.cumulate_att_w = False\n        elif atype == \"forward_ta\":\n            att = AttForwardTA(dec_idim, dunits, adim, aconv_chans, aconv_filts,\n                               odim)\n            if self.cumulate_att_w:\n                logging.warning(\"cumulation of attention weights is disabled \"\n                                \"in forward attention.\")\n                self.cumulate_att_w = False\n        else:\n            raise NotImplementedError(\"Support only location or forward\")\n        self.dec = Decoder(\n            idim=dec_idim,\n            odim=odim,\n            att=att,\n            dlayers=dlayers,\n            dunits=dunits,\n            prenet_layers=prenet_layers,\n            prenet_units=prenet_units,\n            postnet_layers=postnet_layers,\n            postnet_chans=postnet_chans,\n            postnet_filts=postnet_filts,\n            output_activation_fn=self.output_activation_fn,\n            cumulate_att_w=self.cumulate_att_w,\n            use_batch_norm=use_batch_norm,\n            use_concate=use_concate,\n            dropout_rate=dropout_rate,\n            zoneout_rate=zoneout_rate,\n            reduction_factor=reduction_factor, )\n\n        nn.initializer.set_global_initializer(None)\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            spk_emb: Optional[paddle.Tensor]=None,\n            spk_id: Optional[paddle.Tensor]=None,\n            lang_id: Optional[paddle.Tensor]=None\n    ) -> Tuple[paddle.Tensor, Dict[str, paddle.Tensor], paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text (Tensor(int64)):   \n                Batch of padded character ids (B, T_text).\n            text_lengths (Tensor(int64)): \n                Batch of lengths of each input batch (B,).\n            speech (Tensor):\n                 Batch of padded target features (B, T_feats, odim).\n            speech_lengths (Tensor(int64)): \n                Batch of the lengths of each target (B,).\n            spk_emb (Optional[Tensor]): \n                Batch of speaker embeddings (B, spk_embed_dim).\n            spk_id (Optional[Tensor]): \n                Batch of speaker IDs (B, 1).\n            lang_id (Optional[Tensor]): \n                Batch of language IDs (B, 1).\n\n        Returns:\n            Tensor: \n                Loss scalar value.\n            Dict: \n                Statistics to be monitored.\n            Tensor: \n                Weight value if not joint training else model outputs.\n\n        \"\"\"\n        text = text[:, :text_lengths.max()]\n        speech = speech[:, :speech_lengths.max()]\n\n        batch_size = paddle.shape(text)[0]\n\n        # Add eos at the last of sequence\n        xs = F.pad(text, [0, 0, 0, 1], \"constant\", self.padding_idx)\n        for i, l in enumerate(text_lengths):\n            xs[i, l] = self.eos\n        ilens = text_lengths + 1\n\n        ys = speech\n        olens = speech_lengths\n\n        # make labels for stop prediction\n        stop_labels = make_pad_mask(olens - 1)\n        # bool 类型无法切片\n        stop_labels = paddle.cast(stop_labels, dtype='float32')\n        stop_labels = F.pad(stop_labels, [0, 0, 0, 1], \"constant\", 1.0)\n\n        # calculate tacotron2 outputs\n        after_outs, before_outs, logits, att_ws = self._forward(\n            xs=xs,\n            ilens=ilens,\n            ys=ys,\n            olens=olens,\n            spk_emb=spk_emb,\n            spk_id=spk_id,\n            lang_id=lang_id, )\n\n        # modify mod part of groundtruth\n        if self.reduction_factor > 1:\n            assert olens.ge(self.reduction_factor).all(\n            ), \"Output length must be greater than or equal to reduction factor.\"\n            olens = olens - olens % self.reduction_factor\n            max_out = max(olens)\n            ys = ys[:, :max_out]\n            stop_labels = stop_labels[:, :max_out]\n            stop_labels = paddle.scatter(stop_labels, 1,\n                                         (olens - 1).unsqueeze(1), 1.0)\n            olens_in = olens // self.reduction_factor\n        else:\n            olens_in = olens\n        return after_outs, before_outs, logits, ys, stop_labels, olens, att_ws, olens_in\n\n    def _forward(\n            self,\n            xs: paddle.Tensor,\n            ilens: paddle.Tensor,\n            ys: paddle.Tensor,\n            olens: paddle.Tensor,\n            spk_emb: paddle.Tensor,\n            spk_id: paddle.Tensor,\n            lang_id: paddle.Tensor,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n\n        hs, hlens = self.enc(xs, ilens)\n        if self.spk_num is not None:\n            sid_embs = self.sid_emb(spk_id.reshape([-1]))\n            hs = hs + sid_embs.unsqueeze(1)\n        if self.lang_num is not None:\n            lid_embs = self.lid_emb(lang_id.reshape([-1]))\n            hs = hs + lid_embs.unsqueeze(1)\n        if self.spk_embed_dim is not None:\n            hs = self._integrate_with_spk_embed(hs, spk_emb)\n\n        return self.dec(hs, hlens, ys)\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            speech: Optional[paddle.Tensor]=None,\n            spk_emb: Optional[paddle.Tensor]=None,\n            spk_id: Optional[paddle.Tensor]=None,\n            lang_id: Optional[paddle.Tensor]=None,\n            threshold: float=0.5,\n            minlenratio: float=0.0,\n            maxlenratio: float=10.0,\n            use_att_constraint: bool=False,\n            backward_window: int=1,\n            forward_window: int=3,\n            use_teacher_forcing: bool=False, ) -> Dict[str, paddle.Tensor]:\n        \"\"\"Generate the sequence of features given the sequences of characters.\n\n        Args:\n            text (Tensor(int64)): \n                Input sequence of characters (T_text,).\n            speech (Optional[Tensor]): \n                Feature sequence to extract style (N, idim).\n            spk_emb (ptional[Tensor]): \n                Speaker embedding (spk_embed_dim,).\n            spk_id (Optional[Tensor]): \n                Speaker ID (1,).\n            lang_id (Optional[Tensor]): \n                Language ID (1,).\n            threshold (float): \n                Threshold in inference.\n            minlenratio (float): \n                Minimum length ratio in inference.\n            maxlenratio (float): \n                Maximum length ratio in inference.\n            use_att_constraint (bool): \n                Whether to apply attention constraint.\n            backward_window (int): \n                Backward window in attention constraint.\n            forward_window (int): \n                    Forward window in attention constraint.\n            use_teacher_forcing (bool): \n                Whether to use teacher forcing.\n\n        Returns:\n            Dict[str, Tensor]\n            Output dict including the following items:\n                * feat_gen (Tensor): Output sequence of features (T_feats, odim).\n                * prob (Tensor): Output sequence of stop probabilities (T_feats,).\n                * att_w (Tensor): Attention weights (T_feats, T).\n\n        \"\"\"\n        x = text\n        y = speech\n\n        # add eos at the last of sequence\n        x = F.pad(x, [0, 1], \"constant\", self.eos)\n\n        # inference with teacher forcing\n        if use_teacher_forcing:\n            assert speech is not None, \"speech must be provided with teacher forcing.\"\n\n            xs, ys = x.unsqueeze(0), y.unsqueeze(0)\n            spk_emb = None if spk_emb is None else spk_emb.unsqueeze(0)\n            ilens = paddle.shape(xs)[1]\n            olens = paddle.shape(ys)[1]\n            outs, _, _, att_ws = self._forward(\n                xs=xs,\n                ilens=ilens,\n                ys=ys,\n                olens=olens,\n                spk_emb=spk_emb,\n                spk_id=spk_id,\n                lang_id=lang_id, )\n\n            return dict(feat_gen=outs[0], att_w=att_ws[0])\n\n        # inference\n        h = self.enc.inference(x)\n\n        if self.spk_num is not None:\n            sid_emb = self.sid_emb(spk_id.reshape([-1]))\n            h = h + sid_emb\n        if self.lang_num is not None:\n            lid_emb = self.lid_emb(lang_id.reshape([-1]))\n            h = h + lid_emb\n        if self.spk_embed_dim is not None:\n            hs, spk_emb = h.unsqueeze(0), spk_emb.unsqueeze(0)\n            h = self._integrate_with_spk_embed(hs, spk_emb)[0]\n        out, prob, att_w = self.dec.inference(\n            h,\n            threshold=threshold,\n            minlenratio=minlenratio,\n            maxlenratio=maxlenratio,\n            use_att_constraint=use_att_constraint,\n            backward_window=backward_window,\n            forward_window=forward_window, )\n\n        return dict(feat_gen=out, prob=prob, att_w=att_w)\n\n    def _integrate_with_spk_embed(self,\n                                  hs: paddle.Tensor,\n                                  spk_emb: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Integrate speaker embedding with hidden states.\n\n        Args:\n            hs (Tensor): Batch of hidden state sequences (B, Tmax, eunits).\n            spk_emb (Tensor): Batch of speaker embeddings (B, spk_embed_dim).\n\n        Returns:\n            Tensor: Batch of integrated hidden state sequences (B, Tmax, eunits) if\n                integration_type is \"add\" else (B, Tmax, eunits + spk_embed_dim).\n\n        \"\"\"\n        if self.spk_embed_integration_type == \"add\":\n            # apply projection and then add to hidden states\n            spk_emb = self.projection(F.normalize(spk_emb))\n            hs = hs + spk_emb.unsqueeze(1)\n        elif self.spk_embed_integration_type == \"concat\":\n            # concat hidden states with spk embeds\n            spk_emb = F.normalize(spk_emb).unsqueeze(1).expand(\n                shape=[-1, paddle.shape(hs)[1], -1])\n            hs = paddle.concat([hs, spk_emb], axis=-1)\n        else:\n            raise NotImplementedError(\"support only add or concat.\")\n\n        return hs\n\n\nclass Tacotron2Inference(nn.Layer):\n    def __init__(self, normalizer, model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = model\n\n    def forward(self, text, spk_id=None, spk_emb=None):\n        out = self.acoustic_model.inference(\n            text, spk_id=spk_id, spk_emb=spk_emb)\n        normalized_mel = out[\"feat_gen\"]\n        logmel = self.normalizer.inverse(normalized_mel)\n        return logmel\n"
  },
  {
    "path": "paddlespeech/t2s/models/tacotron2/tacotron2_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\n\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.modules.losses import GuidedAttentionLoss\nfrom paddlespeech.t2s.modules.losses import Tacotron2Loss\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass Tacotron2Updater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 dataloader: DataLoader,\n                 init_state=None,\n                 use_masking: bool=True,\n                 use_weighted_masking: bool=False,\n                 bce_pos_weight: float=5.0,\n                 loss_type: str=\"L1+L2\",\n                 use_guided_attn_loss: bool=True,\n                 guided_attn_loss_sigma: float=0.4,\n                 guided_attn_loss_lambda: float=1.0,\n                 output_dir: Path=None):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n\n        self.loss_type = loss_type\n        self.use_guided_attn_loss = use_guided_attn_loss\n\n        self.taco2_loss = Tacotron2Loss(\n            use_masking=use_masking,\n            use_weighted_masking=use_weighted_masking,\n            bce_pos_weight=bce_pos_weight, )\n        if self.use_guided_attn_loss:\n            self.attn_loss = GuidedAttentionLoss(\n                sigma=guided_attn_loss_sigma,\n                alpha=guided_attn_loss_lambda, )\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # spk_id!=None in multiple spk fastspeech2 \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        if spk_emb is not None:\n            spk_id = None\n\n        after_outs, before_outs, logits, ys, stop_labels, olens, att_ws, olens_in = self.model(\n            text=batch[\"text\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"],\n            spk_id=spk_id,\n            spk_emb=spk_emb)\n\n        # calculate taco2 loss\n        l1_loss, mse_loss, bce_loss = self.taco2_loss(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            logits=logits,\n            ys=ys,\n            stop_labels=stop_labels,\n            olens=olens)\n\n        if self.loss_type == \"L1+L2\":\n            loss = l1_loss + mse_loss + bce_loss\n        elif self.loss_type == \"L1\":\n            loss = l1_loss + bce_loss\n        elif self.loss_type == \"L2\":\n            loss = mse_loss + bce_loss\n        else:\n            raise ValueError(f\"unknown --loss-type {self.loss_type}\")\n\n        # calculate attention loss\n        if self.use_guided_attn_loss:\n            # NOTE: length of output for auto-regressive\n            # input will be changed when r > 1\n            attn_loss = self.attn_loss(\n                att_ws=att_ws, ilens=batch[\"text_lengths\"] + 1, olens=olens_in)\n            loss = loss + attn_loss\n\n        optimizer = self.optimizer\n        optimizer.clear_grad()\n        loss.backward()\n        optimizer.step()\n\n        if self.use_guided_attn_loss:\n            report(\"train/attn_loss\", float(attn_loss))\n            losses_dict[\"attn_loss\"] = float(attn_loss)\n        \n        report(\"train/l1_loss\", float(l1_loss))\n        report(\"train/mse_loss\", float(mse_loss))\n        report(\"train/bce_loss\", float(bce_loss))\n        report(\"train/loss\", float(loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"mse_loss\"] = float(mse_loss)\n        losses_dict[\"bce_loss\"] = float(bce_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass Tacotron2Evaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 dataloader: DataLoader,\n                 use_masking: bool=True,\n                 use_weighted_masking: bool=False,\n                 bce_pos_weight: float=5.0,\n                 loss_type: str=\"L1+L2\",\n                 use_guided_attn_loss: bool=True,\n                 guided_attn_loss_sigma: float=0.4,\n                 guided_attn_loss_lambda: float=1.0,\n                 output_dir=None):\n        super().__init__(model, dataloader)\n\n        self.loss_type = loss_type\n        self.use_guided_attn_loss = use_guided_attn_loss\n\n        self.taco2_loss = Tacotron2Loss(\n            use_masking=use_masking,\n            use_weighted_masking=use_weighted_masking,\n            bce_pos_weight=bce_pos_weight, )\n        if self.use_guided_attn_loss:\n            self.attn_loss = GuidedAttentionLoss(\n                sigma=guided_attn_loss_sigma,\n                alpha=guided_attn_loss_lambda, )\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        # spk_id!=None in multiple spk fastspeech2 \n        spk_id = batch[\"spk_id\"] if \"spk_id\" in batch else None\n        spk_emb = batch[\"spk_emb\"] if \"spk_emb\" in batch else None\n        if spk_emb is not None:\n            spk_id = None\n\n        after_outs, before_outs, logits, ys, stop_labels, olens, att_ws, olens_in = self.model(\n            text=batch[\"text\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"],\n            spk_id=spk_id,\n            spk_emb=spk_emb)\n\n        # calculate taco2 loss\n        l1_loss, mse_loss, bce_loss = self.taco2_loss(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            logits=logits,\n            ys=ys,\n            stop_labels=stop_labels,\n            olens=olens)\n\n        if self.loss_type == \"L1+L2\":\n            loss = l1_loss + mse_loss + bce_loss\n        elif self.loss_type == \"L1\":\n            loss = l1_loss + bce_loss\n        elif self.loss_type == \"L2\":\n            loss = mse_loss + bce_loss\n        else:\n            raise ValueError(f\"unknown --loss-type {self.loss_type}\")\n\n        # calculate attention loss\n        if self.use_guided_attn_loss:\n            # NOTE: length of output for auto-regressive\n            # input will be changed when r > 1\n            attn_loss = self.attn_loss(\n                att_ws=att_ws, ilens=batch[\"text_lengths\"] + 1, olens=olens_in)\n            loss = loss + attn_loss\n        \n        if self.use_guided_attn_loss:\n            report(\"eval/attn_loss\", float(attn_loss))\n            losses_dict[\"attn_loss\"] = float(attn_loss)\n\n        report(\"eval/l1_loss\", float(l1_loss))\n        report(\"eval/mse_loss\", float(mse_loss))\n        report(\"eval/bce_loss\", float(bce_loss))\n        report(\"eval/loss\", float(loss))\n\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"mse_loss\"] = float(mse_loss)\n        losses_dict[\"bce_loss\"] = float(bce_loss)\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/transformer_tts/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .transformer_tts import *\nfrom .transformer_tts_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/transformer_tts/transformer_tts.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Fastspeech2 related modules for paddle\"\"\"\nfrom optparse import Option\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport numpy\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\nfrom paddlespeech.t2s.modules.style_encoder import StyleEncoder\nfrom paddlespeech.t2s.modules.tacotron2.decoder import Postnet\nfrom paddlespeech.t2s.modules.tacotron2.decoder import Prenet as DecoderPrenet\nfrom paddlespeech.t2s.modules.tacotron2.encoder import Encoder as EncoderPrenet\nfrom paddlespeech.t2s.modules.transformer.attention import MultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.decoder import Decoder\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import ScaledPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.encoder import TransformerEncoder\nfrom paddlespeech.t2s.modules.transformer.mask import subsequent_mask\n\n\nclass TransformerTTS(nn.Layer):\n    \"\"\"TTS-Transformer module.\n\n    This is a module of text-to-speech Transformer described in `Neural Speech Synthesis\n    with Transformer Network`_, which convert the sequence of tokens into the sequence\n    of Mel-filterbanks.\n\n    .. _`Neural Speech Synthesis with Transformer Network`:\n        https://arxiv.org/pdf/1809.08895.pdf\n\n    Args:\n        idim (int): \n            Dimension of the inputs.\n        odim (int): \n            Dimension of the outputs.\n        embed_dim (int, optional): \n            Dimension of character embedding.\n        eprenet_conv_layers (int, optional): \n            Number of encoder prenet convolution layers.\n        eprenet_conv_chans (int, optional): \n            Number of encoder prenet convolution channels.\n        eprenet_conv_filts (int, optional): \n            Filter size of encoder prenet convolution.\n        dprenet_layers (int, optional): \n            Number of decoder prenet layers.\n        dprenet_units (int, optional): \n            Number of decoder prenet hidden units.\n        elayers (int, optional): \n            Number of encoder layers.\n        eunits (int, optional): \n            Number of encoder hidden units.\n        adim (int, optional): \n            Number of attention transformation dimensions.\n        aheads (int, optional): \n            Number of heads for multi head attention.\n        dlayers (int, optional): \n            Number of decoder layers.\n        dunits (int, optional): \n            Number of decoder hidden units.\n        postnet_layers (int, optional): \n            Number of postnet layers.\n        postnet_chans (int, optional): \n            Number of postnet channels.\n        postnet_filts (int, optional): \n            Filter size of postnet.\n        use_scaled_pos_enc (pool, optional): \n            Whether to use trainable scaled positional encoding.\n        use_batch_norm (bool, optional): \n            Whether to use batch normalization in encoder prenet.\n        encoder_normalize_before (bool, optional): \n            Whether to perform layer normalization before encoder block.\n        decoder_normalize_before (bool, optional): \n            Whether to perform layer normalization before decoder block.\n        encoder_concat_after (bool, optional): \n            Whether to concatenate attention layer's input and output in encoder.\n        decoder_concat_after (bool, optional): \n            Whether to concatenate attention layer's input and output in decoder.\n        positionwise_layer_type (str, optional): \n            Position-wise operation type.\n        positionwise_conv_kernel_size (int, optional): \n            Kernel size in position wise conv 1d.\n        reduction_factor (int, optional): \n            Reduction factor.\n        spk_embed_dim (int, optional): \n            Number of speaker embedding dimenstions.\n        spk_embed_integration_type (str, optional): \n            How to integrate speaker embedding.\n        use_gst (str, optional): \n            Whether to use global style token.\n        gst_tokens (int, optional): \n            The number of GST embeddings.\n        gst_heads (int, optional): \n            The number of heads in GST multihead attention.\n        gst_conv_layers (int, optional): \n            The number of conv layers in GST.\n        gst_conv_chans_list (Sequence[int], optional): \n            List of the number of channels of conv layers in GST.\n        gst_conv_kernel_size (int, optional): \n            Kernal size of conv layers in GST.\n        gst_conv_stride (int, optional): \n            Stride size of conv layers in GST.\n        gst_gru_layers (int, optional): \n            The number of GRU layers in GST.\n        gst_gru_units (int, optional): \n            The number of GRU units in GST.\n        transformer_lr (float, optional): \n            Initial value of learning rate.\n        transformer_warmup_steps (int, optional): \n            Optimizer warmup steps.\n        transformer_enc_dropout_rate (float, optional): \n            Dropout rate in encoder except attention and positional encoding.\n        transformer_enc_positional_dropout_rate (float, optional): \n            Dropout rate after encoder positional encoding.\n        transformer_enc_attn_dropout_rate （float, optional): \n            Dropout rate in encoder self-attention module.\n        transformer_dec_dropout_rate (float, optional): \n            Dropout rate in decoder except attention & positional encoding.\n        transformer_dec_positional_dropout_rate (float, optional): \n            Dropout rate after decoder positional encoding.\n        transformer_dec_attn_dropout_rate （float, optional): \n            Dropout rate in deocoder self-attention module.\n        transformer_enc_dec_attn_dropout_rate (float, optional): \n            Dropout rate in encoder-deocoder attention module.\n        init_type (str, optional): \n            How to initialize transformer parameters.\n        init_enc_alpha （float, optional）: \n            Initial value of alpha in scaled pos encoding of the encoder.\n        init_dec_alpha (float, optional): \n            Initial value of alpha in scaled pos encoding of the decoder.\n        eprenet_dropout_rate (float, optional): \n            Dropout rate in encoder prenet.\n        dprenet_dropout_rate (float, optional): \n            Dropout rate in decoder prenet.\n        postnet_dropout_rate (float, optional): \n            Dropout rate in postnet.\n        use_masking (bool, optional): \n            Whether to apply masking for padded part in loss calculation.\n        use_weighted_masking (bool, optional): \n            Whether to apply weighted masking in loss calculation.\n        bce_pos_weight (float, optional): \n            Positive sample weight in bce calculation (only for use_masking=true).\n        loss_type (str, optional): \n            How to calculate loss.\n        use_guided_attn_loss (bool, optional): \n            Whether to use guided attention loss.\n        num_heads_applied_guided_attn (int, optional):\n            Number of heads in each layer to apply guided attention loss.\n        num_layers_applied_guided_attn (int, optional): \n            Number of layers to apply guided attention loss.\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # network structure related\n            idim: int,\n            odim: int,\n            embed_dim: int=512,\n            eprenet_conv_layers: int=3,\n            eprenet_conv_chans: int=256,\n            eprenet_conv_filts: int=5,\n            dprenet_layers: int=2,\n            dprenet_units: int=256,\n            elayers: int=6,\n            eunits: int=1024,\n            adim: int=512,\n            aheads: int=4,\n            dlayers: int=6,\n            dunits: int=1024,\n            postnet_layers: int=5,\n            postnet_chans: int=256,\n            postnet_filts: int=5,\n            positionwise_layer_type: str=\"conv1d\",\n            positionwise_conv_kernel_size: int=1,\n            use_scaled_pos_enc: bool=True,\n            use_batch_norm: bool=True,\n            encoder_normalize_before: bool=True,\n            decoder_normalize_before: bool=True,\n            encoder_concat_after: bool=False,\n            decoder_concat_after: bool=False,\n            reduction_factor: int=1,\n            spk_embed_dim: Optional[int]=None,\n            spk_embed_integration_type: str=\"add\",\n            use_gst: bool=False,\n            gst_tokens: int=10,\n            gst_heads: int=4,\n            gst_conv_layers: int=6,\n            gst_conv_chans_list: Sequence[int]=(32, 32, 64, 64, 128, 128),\n            gst_conv_kernel_size: int=3,\n            gst_conv_stride: int=2,\n            gst_gru_layers: int=1,\n            gst_gru_units: int=128,\n            # training related\n            transformer_enc_dropout_rate: float=0.1,\n            transformer_enc_positional_dropout_rate: float=0.1,\n            transformer_enc_attn_dropout_rate: float=0.1,\n            transformer_dec_dropout_rate: float=0.1,\n            transformer_dec_positional_dropout_rate: float=0.1,\n            transformer_dec_attn_dropout_rate: float=0.1,\n            transformer_enc_dec_attn_dropout_rate: float=0.1,\n            eprenet_dropout_rate: float=0.5,\n            dprenet_dropout_rate: float=0.5,\n            postnet_dropout_rate: float=0.5,\n            init_type: str=\"xavier_uniform\",\n            init_enc_alpha: float=1.0,\n            init_dec_alpha: float=1.0,\n            use_guided_attn_loss: bool=True,\n            num_heads_applied_guided_attn: int=2,\n            num_layers_applied_guided_attn: int=2, ):\n        \"\"\"Initialize Transformer module.\"\"\"\n\n        super().__init__()\n\n        # store hyperparameters\n        self.idim = idim\n        self.odim = odim\n        self.eos = idim - 1\n        self.spk_embed_dim = spk_embed_dim\n        self.reduction_factor = reduction_factor\n        self.use_gst = use_gst\n        self.use_scaled_pos_enc = use_scaled_pos_enc\n        self.use_guided_attn_loss = use_guided_attn_loss\n        if self.use_guided_attn_loss:\n            if num_layers_applied_guided_attn == -1:\n                self.num_layers_applied_guided_attn = elayers\n            else:\n                self.num_layers_applied_guided_attn = num_layers_applied_guided_attn\n            if num_heads_applied_guided_attn == -1:\n                self.num_heads_applied_guided_attn = aheads\n            else:\n                self.num_heads_applied_guided_attn = num_heads_applied_guided_attn\n        if self.spk_embed_dim is not None:\n            self.spk_embed_integration_type = spk_embed_integration_type\n\n        # use idx 0 as padding idx\n        self.padding_idx = 0\n        # set_global_initializer 会影响后面的全局，包括 create_parameter\n        initialize(self, init_type)\n\n        # get positional encoding layer type\n        transformer_pos_enc_layer_type = \"scaled_abs_pos\" if self.use_scaled_pos_enc else \"abs_pos\"\n\n        # define transformer encoder\n        if eprenet_conv_layers != 0:\n            # encoder prenet\n            encoder_input_layer = nn.Sequential(\n                EncoderPrenet(\n                    idim=idim,\n                    embed_dim=embed_dim,\n                    elayers=0,\n                    econv_layers=eprenet_conv_layers,\n                    econv_chans=eprenet_conv_chans,\n                    econv_filts=eprenet_conv_filts,\n                    use_batch_norm=use_batch_norm,\n                    dropout_rate=eprenet_dropout_rate,\n                    padding_idx=self.padding_idx, ),\n                nn.Linear(eprenet_conv_chans, adim), )\n        else:\n            encoder_input_layer = nn.Embedding(\n                num_embeddings=idim,\n                embedding_dim=adim,\n                padding_idx=self.padding_idx)\n        self.encoder = TransformerEncoder(\n            idim=idim,\n            attention_dim=adim,\n            attention_heads=aheads,\n            linear_units=eunits,\n            num_blocks=elayers,\n            input_layer=encoder_input_layer,\n            dropout_rate=transformer_enc_dropout_rate,\n            positional_dropout_rate=transformer_enc_positional_dropout_rate,\n            attention_dropout_rate=transformer_enc_attn_dropout_rate,\n            pos_enc_layer_type=transformer_pos_enc_layer_type,\n            normalize_before=encoder_normalize_before,\n            concat_after=encoder_concat_after,\n            positionwise_layer_type=positionwise_layer_type,\n            positionwise_conv_kernel_size=positionwise_conv_kernel_size, )\n\n        # define GST\n        if self.use_gst:\n            self.gst = StyleEncoder(\n                idim=odim,  # the input is mel-spectrogram\n                gst_tokens=gst_tokens,\n                gst_token_dim=adim,\n                gst_heads=gst_heads,\n                conv_layers=gst_conv_layers,\n                conv_chans_list=gst_conv_chans_list,\n                conv_kernel_size=gst_conv_kernel_size,\n                conv_stride=gst_conv_stride,\n                gru_layers=gst_gru_layers,\n                gru_units=gst_gru_units, )\n\n        # define projection layer\n        if self.spk_embed_dim is not None:\n            if self.spk_embed_integration_type == \"add\":\n                self.projection = nn.Linear(self.spk_embed_dim, adim)\n            else:\n                self.projection = nn.Linear(adim + self.spk_embed_dim, adim)\n\n        # define transformer decoder\n        if dprenet_layers != 0:\n            # decoder prenet\n            decoder_input_layer = nn.Sequential(\n                DecoderPrenet(\n                    idim=odim,\n                    n_layers=dprenet_layers,\n                    n_units=dprenet_units,\n                    dropout_rate=dprenet_dropout_rate, ),\n                nn.Linear(dprenet_units, adim), )\n        else:\n            decoder_input_layer = \"linear\"\n        # get positional encoding class\n        pos_enc_class = (ScaledPositionalEncoding\n                         if self.use_scaled_pos_enc else PositionalEncoding)\n        self.decoder = Decoder(\n            odim=odim,  # odim is needed when no prenet is used\n            attention_dim=adim,\n            attention_heads=aheads,\n            linear_units=dunits,\n            num_blocks=dlayers,\n            dropout_rate=transformer_dec_dropout_rate,\n            positional_dropout_rate=transformer_dec_positional_dropout_rate,\n            self_attention_dropout_rate=transformer_dec_attn_dropout_rate,\n            src_attention_dropout_rate=transformer_enc_dec_attn_dropout_rate,\n            input_layer=decoder_input_layer,\n            use_output_layer=False,\n            pos_enc_class=pos_enc_class,\n            normalize_before=decoder_normalize_before,\n            concat_after=decoder_concat_after, )\n\n        # define final projection\n        self.feat_out = nn.Linear(adim, odim * reduction_factor)\n        self.prob_out = nn.Linear(adim, reduction_factor)\n\n        # define postnet\n        self.postnet = (None if postnet_layers == 0 else Postnet(\n            idim=idim,\n            odim=odim,\n            n_layers=postnet_layers,\n            n_chans=postnet_chans,\n            n_filts=postnet_filts,\n            use_batch_norm=use_batch_norm,\n            dropout_rate=postnet_dropout_rate, ))\n\n        # 闭合的 initialize() 中的 set_global_initializer 的作用域，防止其影响到 self._reset_parameters()\n        nn.initializer.set_global_initializer(None)\n\n        self._reset_parameters(\n            init_enc_alpha=init_enc_alpha,\n            init_dec_alpha=init_dec_alpha, )\n\n    def _reset_parameters(self, init_enc_alpha: float, init_dec_alpha: float):\n\n        # initialize alpha in scaled positional encoding\n        if self.use_scaled_pos_enc:\n            init_enc_alpha = paddle.to_tensor(init_enc_alpha)\n            self.encoder.embed[-1].alpha = paddle.create_parameter(\n                shape=init_enc_alpha.shape,\n                dtype=str(init_enc_alpha.numpy().dtype),\n                default_initializer=paddle.nn.initializer.Assign(\n                    init_enc_alpha))\n\n            init_dec_alpha = paddle.to_tensor(init_dec_alpha)\n            self.decoder.embed[-1].alpha = paddle.create_parameter(\n                shape=init_dec_alpha.shape,\n                dtype=str(init_dec_alpha.numpy().dtype),\n                default_initializer=paddle.nn.initializer.Assign(\n                    init_dec_alpha))\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            speech: paddle.Tensor,\n            speech_lengths: paddle.Tensor,\n            spk_emb: paddle.Tensor=None,\n    ) -> Tuple[paddle.Tensor, Dict[str, paddle.Tensor], paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            text(Tensor(int64)): Batch of padded character ids (B, Tmax).\n            text_lengths(Tensor(int64)): Batch of lengths of each input batch (B,).\n            speech(Tensor): Batch of padded target features (B, Lmax, odim).\n            speech_lengths(Tensor(int64)): Batch of the lengths of each target (B,).\n            spk_emb(Tensor, optional): Batch of speaker embeddings (B, spk_embed_dim).\n\n        Returns:\n            Tensor: Loss scalar value.\n            Dict: Statistics to be monitored.\n\n        \"\"\"\n        # input of embedding must be int64\n        text_lengths = paddle.cast(text_lengths, 'int64')\n\n        # Add eos at the last of sequence\n        text = numpy.pad(text.numpy(), ((0, 0), (0, 1)), 'constant')\n        xs = paddle.to_tensor(text, dtype='int64')\n        for i, l in enumerate(text_lengths):\n            xs[i, l] = self.eos\n        ilens = text_lengths + 1\n\n        ys = speech\n        olens = paddle.cast(speech_lengths, 'int64')\n\n        # make labels for stop prediction\n        stop_labels = make_pad_mask(olens - 1)\n        # bool 类型无法切片\n        stop_labels = paddle.cast(stop_labels, dtype='float32')\n        stop_labels = F.pad(stop_labels, [0, 0, 0, 1], \"constant\", 1.0)\n\n        # calculate transformer outputs\n        after_outs, before_outs, logits = self._forward(xs, ilens, ys, olens,\n                                                        spk_emb)\n\n        # modifiy mod part of groundtruth\n\n        if self.reduction_factor > 1:\n            olens = olens - olens % self.reduction_factor\n            max_olen = max(olens)\n            ys = ys[:, :max_olen]\n            stop_labels = stop_labels[:, :max_olen]\n            stop_labels[:, -1] = 1.0  # make sure at least one frame has 1\n            olens_in = olens // self.reduction_factor\n        else:\n            olens_in = olens\n\n        need_dict = {}\n        need_dict['encoder'] = self.encoder\n        need_dict['decoder'] = self.decoder\n        need_dict[\n            'num_heads_applied_guided_attn'] = self.num_heads_applied_guided_attn\n        need_dict[\n            'num_layers_applied_guided_attn'] = self.num_layers_applied_guided_attn\n        need_dict['use_scaled_pos_enc'] = self.use_scaled_pos_enc\n\n        return after_outs, before_outs, logits, ys, stop_labels, olens, olens_in, need_dict\n\n    def _forward(\n            self,\n            xs: paddle.Tensor,\n            ilens: paddle.Tensor,\n            ys: paddle.Tensor,\n            olens: paddle.Tensor,\n            spk_emb: paddle.Tensor,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        # forward encoder\n        x_masks = self._source_mask(ilens)\n        hs, h_masks = self.encoder(xs, x_masks)\n\n        # integrate with GST\n        if self.use_gst:\n            style_embs = self.gst(ys)\n            hs = hs + style_embs.unsqueeze(1)\n\n        # integrate speaker embedding\n        if self.spk_embed_dim is not None:\n            hs = self._integrate_with_spk_embed(hs, spk_emb)\n\n        # thin out frames for reduction factor (B, Lmax, odim) ->  (B, Lmax//r, odim)\n        if self.reduction_factor > 1:\n            ys_in = ys[:, self.reduction_factor - 1::self.reduction_factor]\n            olens_in = olens // self.reduction_factor\n        else:\n            ys_in, olens_in = ys, olens\n\n        # add first zero frame and remove last frame for auto-regressive\n        ys_in = self._add_first_frame_and_remove_last_frame(ys_in)\n\n        # forward decoder\n        y_masks = self._target_mask(olens_in)\n        zs, _ = self.decoder(ys_in, y_masks, hs, h_masks)\n        # (B, Lmax//r, odim * r) -> (B, Lmax//r * r, odim)\n        before_outs = self.feat_out(zs).reshape([zs.shape[0], -1, self.odim])\n        # (B, Lmax//r, r) -> (B, Lmax//r * r)\n        logits = self.prob_out(zs).reshape([zs.shape[0], -1])\n\n        # postnet -> (B, Lmax//r * r, odim)\n        if self.postnet is None:\n            after_outs = before_outs\n        else:\n            after_outs = before_outs + self.postnet(\n                before_outs.transpose([0, 2, 1])).transpose([0, 2, 1])\n\n        return after_outs, before_outs, logits\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            speech: paddle.Tensor=None,\n            spk_emb: paddle.Tensor=None,\n            threshold: float=0.5,\n            minlenratio: float=0.0,\n            maxlenratio: float=10.0,\n            use_teacher_forcing: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Generate the sequence of features given the sequences of characters.\n\n        Args:\n            text(Tensor(int64)): Input sequence of characters (T,).\n            speech(Tensor, optional): Feature sequence to extract style (N, idim).\n            spk_emb(Tensor, optional): Speaker embedding vector (spk_embed_dim,).\n            threshold(float, optional): Threshold in inference.\n            minlenratio(float, optional): Minimum length ratio in inference.\n            maxlenratio(float, optional): Maximum length ratio in inference.\n            use_teacher_forcing(bool, optional): Whether to use teacher forcing.\n\n        Returns:\n            Tensor: Output sequence of features (L, odim).\n            Tensor: Output sequence of stop probabilities (L,).\n            Tensor: Encoder-decoder (source) attention weights (#layers, #heads, L, T).\n\n        \"\"\"\n        # input of embedding must be int64\n        y = speech\n\n        # add eos at the last of sequence\n        text = numpy.pad(\n            text.numpy(), (0, 1), 'constant', constant_values=self.eos)\n        x = paddle.to_tensor(text, dtype='int64')\n\n        # inference with teacher forcing\n        if use_teacher_forcing:\n            assert speech is not None, \"speech must be provided with teacher forcing.\"\n\n            # get teacher forcing outputs\n            xs, ys = x.unsqueeze(0), y.unsqueeze(0)\n            spk_emb = None if spk_emb is None else spk_emb.unsqueeze(0)\n            ilens = paddle.to_tensor(\n                [xs.shape[1]], dtype=paddle.int64, place=xs.place)\n            olens = paddle.to_tensor(\n                [ys.shape[1]], dtype=paddle.int64, place=ys.place)\n            outs, *_ = self._forward(xs, ilens, ys, olens, spk_emb)\n\n            # get attention weights\n            att_ws = []\n            for i in range(len(self.decoder.decoders)):\n                att_ws += [self.decoder.decoders[i].src_attn.attn]\n            # (B, L, H, T_out, T_in)\n            att_ws = paddle.stack(att_ws, axis=1)\n\n            return outs[0], None, att_ws[0]\n\n        # forward encoder\n        xs = x.unsqueeze(0)\n        hs, _ = self.encoder(xs, None)\n\n        # integrate GST\n        if self.use_gst:\n            style_embs = self.gst(y.unsqueeze(0))\n            hs = hs + style_embs.unsqueeze(1)\n\n        # integrate speaker embedding\n        if spk_emb is not None:\n            spk_emb = spk_emb.unsqueeze(0)\n            hs = self._integrate_with_spk_embed(hs, spk_emb)\n\n        # set limits of length\n        maxlen = int(hs.shape[1] * maxlenratio / self.reduction_factor)\n        minlen = int(hs.shape[1] * minlenratio / self.reduction_factor)\n\n        # initialize\n        idx = 0\n        ys = paddle.zeros([1, 1, self.odim])\n        outs, probs = [], []\n\n        # forward decoder step-by-step\n        z_cache = None\n        while True:\n            # update index\n            idx += 1\n\n            # calculate output and stop prob at idx-th step\n            y_masks = subsequent_mask(idx).unsqueeze(0)\n            z, z_cache = self.decoder.forward_one_step(\n                ys, y_masks, hs, cache=z_cache)  # (B, adim)\n            outs += [\n                self.feat_out(z).reshape([self.reduction_factor, self.odim])\n            ]  # [(r, odim), ...]\n            probs += [F.sigmoid(self.prob_out(z))[0]]  # [(r), ...]\n\n            # update next inputs\n            ys = paddle.concat(\n                (ys, outs[-1][-1].reshape([1, 1, self.odim])),\n                axis=1)  # (1, idx + 1, odim)\n\n            # get attention weights\n            att_ws_ = []\n            for name, m in self.named_sublayers():\n                if isinstance(m, MultiHeadedAttention) and \"src\" in name:\n                    # [(#heads, 1, T),...]\n                    att_ws_ += [m.attn[0, :, -1].unsqueeze(1)]\n            if idx == 1:\n                att_ws = att_ws_\n            else:\n                # [(#heads, l, T), ...]\n                att_ws = [\n                    paddle.concat([att_w, att_w_], axis=1)\n                    for att_w, att_w_ in zip(att_ws, att_ws_)\n                ]\n\n            # check whether to finish generation\n            if sum(paddle.cast(probs[-1] >= threshold,\n                               'int64')) > 0 or idx >= maxlen:\n                # check mininum length\n                if idx < minlen:\n                    continue\n                # (L, odim) -> (1, L, odim) -> (1, odim, L)\n                outs = (paddle.concat(outs, axis=0).unsqueeze(0).transpose(\n                    [0, 2, 1]))\n                if self.postnet is not None:\n                    # (1, odim, L)\n                    outs = outs + self.postnet(outs)\n                # (L, odim)\n                outs = outs.transpose([0, 2, 1]).squeeze(0)\n                probs = paddle.concat(probs, axis=0)\n                break\n\n        # concatenate attention weights -> (#layers, #heads, L, T)\n        att_ws = paddle.stack(att_ws, axis=0)\n\n        return outs, probs, att_ws\n\n    def _add_first_frame_and_remove_last_frame(\n            self, ys: paddle.Tensor) -> paddle.Tensor:\n        ys_in = paddle.concat(\n            [paddle.zeros((ys.shape[0], 1, ys.shape[2])), ys[:, :-1]], axis=1)\n        return ys_in\n\n    def _source_mask(self, ilens: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Make masks for self-attention.\n\n        Args:\n            ilens(Tensor): Batch of lengths (B,).\n\n        Returns:\n            Tensor: Mask tensor for self-attention. dtype=paddle.bool\n\n        Examples:\n            >>> ilens = [5, 3]\n            >>> self._source_mask(ilens)\n            tensor([[[1, 1, 1, 1, 1],\n                        [1, 1, 1, 0, 0]]]) bool\n\n        \"\"\"\n        x_masks = make_non_pad_mask(ilens)\n        return x_masks.unsqueeze(-2)\n\n    def _target_mask(self, olens: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Make masks for masked self-attention.\n\n        Args:\n            olens (Tensor(int64)): Batch of lengths (B,).\n\n        Returns:\n            Tensor: Mask tensor for masked self-attention.\n\n        Examples:\n            >>> olens = [5, 3]\n            >>> self._target_mask(olens)\n            tensor([[[1, 0, 0, 0, 0],\n                        [1, 1, 0, 0, 0],\n                        [1, 1, 1, 0, 0],\n                        [1, 1, 1, 1, 0],\n                        [1, 1, 1, 1, 1]],\n                    [[1, 0, 0, 0, 0],\n                        [1, 1, 0, 0, 0],\n                        [1, 1, 1, 0, 0],\n                        [1, 1, 1, 0, 0],\n                        [1, 1, 1, 0, 0]]], dtype=paddle.uint8)\n\n        \"\"\"\n        y_masks = make_non_pad_mask(olens)\n        s_masks = subsequent_mask(y_masks.shape[-1]).unsqueeze(0)\n        return paddle.logical_and(y_masks.unsqueeze(-2), s_masks)\n\n    def _integrate_with_spk_embed(self,\n                                  hs: paddle.Tensor,\n                                  spk_emb: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Integrate speaker embedding with hidden states.\n\n        Args:\n            hs(Tensor): Batch of hidden state sequences (B, Tmax, adim).\n            spk_emb(Tensor): Batch of speaker embeddings (B, spk_embed_dim).\n\n        Returns:\n            Tensor: Batch of integrated hidden state sequences (B, Tmax, adim).\n\n        \"\"\"\n        if self.spk_embed_integration_type == \"add\":\n            # apply projection and then add to hidden states\n            spk_emb = self.projection(F.normalize(spk_emb))\n            hs = hs + spk_emb.unsqueeze(1)\n        elif self.spk_embed_integration_type == \"concat\":\n            # concat hidden states with spk embeds and then apply projection\n            spk_emb = F.normalize(spk_emb).unsqueeze(1).expand(-1, hs.shape[1],\n                                                               -1)\n            hs = self.projection(paddle.concat([hs, spk_emb], axis=-1))\n        else:\n            raise NotImplementedError(\"support only add or concat.\")\n\n        return hs\n\n\nclass TransformerTTSInference(nn.Layer):\n    def __init__(self, normalizer, model):\n        super().__init__()\n        self.normalizer = normalizer\n        self.acoustic_model = model\n\n    def forward(self, text, spk_id=None):\n        normalized_mel = self.acoustic_model.inference(text)[0]\n        logmel = self.normalizer.inverse(normalized_mel)\n        return logmel\n"
  },
  {
    "path": "paddlespeech/t2s/models/transformer_tts/transformer_tts_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\nfrom typing import Sequence\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.modules.losses import GuidedMultiHeadAttentionLoss\nfrom paddlespeech.t2s.modules.losses import Tacotron2Loss as TransformerTTSLoss\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass TransformerTTSUpdater(StandardUpdater):\n    def __init__(\n            self,\n            model: Layer,\n            optimizer: Optimizer,\n            dataloader: DataLoader,\n            init_state=None,\n            use_masking: bool=False,\n            use_weighted_masking: bool=False,\n            output_dir: Path=None,\n            bce_pos_weight: float=5.0,\n            loss_type: str=\"L1\",\n            use_guided_attn_loss: bool=True,\n            modules_applied_guided_attn: Sequence[str]=(\"encoder-decoder\"),\n            guided_attn_loss_sigma: float=0.4,\n            guided_attn_loss_lambda: float=1.0, ):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n\n        self.loss_type = loss_type\n        self.use_guided_attn_loss = use_guided_attn_loss\n        self.modules_applied_guided_attn = modules_applied_guided_attn\n\n        self.criterion = TransformerTTSLoss(\n            use_masking=use_masking,\n            use_weighted_masking=use_weighted_masking,\n            bce_pos_weight=bce_pos_weight)\n\n        if self.use_guided_attn_loss:\n            self.attn_criterion = GuidedMultiHeadAttentionLoss(\n                sigma=guided_attn_loss_sigma,\n                alpha=guided_attn_loss_lambda, )\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        after_outs, before_outs, logits, ys, stop_labels, olens, olens_in, need_dict = self.model(\n            text=batch[\"text\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"], )\n\n        l1_loss, l2_loss, bce_loss = self.criterion(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            logits=logits,\n            ys=ys,\n            stop_labels=stop_labels,\n            olens=olens)\n\n        report(\"train/bce_loss\", float(bce_loss))\n        report(\"train/l1_loss\", float(l1_loss))\n        report(\"train/l2_loss\", float(l2_loss))\n        losses_dict[\"bce_loss\"] = float(bce_loss)\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"l2_loss\"] = float(l2_loss)\n        # caluculate loss values\n        if self.loss_type == \"L1\":\n            loss = l1_loss + bce_loss\n        elif self.loss_type == \"L2\":\n            loss = l2_loss + bce_loss\n        elif self.loss_type == \"L1+L2\":\n            loss = l1_loss + l2_loss + bce_loss\n        else:\n            raise ValueError(\"unknown --loss-type \" + self.loss_type)\n\n        # calculate guided attention loss\n        if self.use_guided_attn_loss:\n            # calculate for encoder\n            if \"encoder\" in self.modules_applied_guided_attn:\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['encoder'].encoders)))):\n                    att_ws += [\n                        need_dict['encoder'].encoders[layer_idx].self_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_in, T_in)\n                att_ws = paddle.concat(att_ws, axis=1)\n                enc_attn_loss = self.attn_criterion(\n                    att_ws=att_ws,\n                    ilens=batch[\"text_lengths\"] + 1,\n                    olens=batch[\"text_lengths\"] + 1)\n                loss = loss + enc_attn_loss\n                report(\"train/enc_attn_loss\", float(enc_attn_loss))\n                losses_dict[\"enc_attn_loss\"] = float(enc_attn_loss)\n            # calculate for decoder\n            if \"decoder\" in self.modules_applied_guided_attn:\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['decoder'].decoders)))):\n                    att_ws += [\n                        need_dict['decoder'].decoders[layer_idx].self_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_out, T_out)\n                att_ws = paddle.concat(att_ws, axis=1)\n                dec_attn_loss = self.attn_criterion(\n                    att_ws=att_ws, ilens=olens_in, olens=olens_in)\n                report(\"train/dec_attn_loss\", float(dec_attn_loss))\n                losses_dict[\"dec_attn_loss\"] = float(dec_attn_loss)\n                loss = loss + dec_attn_loss\n            # calculate for encoder-decoder\n            if \"encoder-decoder\" in self.modules_applied_guided_attn:\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['decoder'].decoders)))):\n                    att_ws += [\n                        need_dict['decoder'].decoders[layer_idx].src_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_out, T_in)\n                att_ws = paddle.concat(att_ws, axis=1)\n                enc_dec_attn_loss = self.attn_criterion(\n                    att_ws=att_ws,\n                    ilens=batch[\"text_lengths\"] + 1,\n                    olens=olens_in)\n                report(\"train/enc_dec_attn_loss\", float(enc_dec_attn_loss))\n                losses_dict[\"enc_dec_attn_loss\"] = float(enc_dec_attn_loss)\n                loss = loss + enc_dec_attn_loss\n        if need_dict['use_scaled_pos_enc']:\n            report(\"train/encoder_alpha\",\n                   float(need_dict['encoder'].embed[-1].alpha))\n            report(\"train/decoder_alpha\",\n                   float(need_dict['decoder'].embed[-1].alpha))\n            losses_dict[\"encoder_alpha\"] = float(\n                need_dict['encoder'].embed[-1].alpha)\n            losses_dict[\"decoder_alpha\"] = float(\n                need_dict['decoder'].embed[-1].alpha)\n\n        optimizer = self.optimizer\n        optimizer.clear_grad()\n        loss.backward()\n        optimizer.step()\n\n        report(\"train/loss\", float(loss))\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass TransformerTTSEvaluator(StandardEvaluator):\n    def __init__(\n            self,\n            model: Layer,\n            dataloader: DataLoader,\n            init_state=None,\n            use_masking: bool=False,\n            use_weighted_masking: bool=False,\n            output_dir: Path=None,\n            bce_pos_weight: float=5.0,\n            loss_type: str=\"L1\",\n            use_guided_attn_loss: bool=True,\n            modules_applied_guided_attn: Sequence[str]=(\"encoder-decoder\"),\n            guided_attn_loss_sigma: float=0.4,\n            guided_attn_loss_lambda: float=1.0, ):\n        super().__init__(model, dataloader)\n\n        self.loss_type = loss_type\n        self.use_guided_attn_loss = use_guided_attn_loss\n        self.modules_applied_guided_attn = modules_applied_guided_attn\n\n        self.criterion = TransformerTTSLoss(\n            use_masking=use_masking,\n            use_weighted_masking=use_weighted_masking,\n            bce_pos_weight=bce_pos_weight)\n\n        if self.use_guided_attn_loss:\n            self.attn_criterion = GuidedMultiHeadAttentionLoss(\n                sigma=guided_attn_loss_sigma,\n                alpha=guided_attn_loss_lambda, )\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        after_outs, before_outs, logits, ys, stop_labels, olens, olens_in, need_dict = self.model(\n            text=batch[\"text\"],\n            text_lengths=batch[\"text_lengths\"],\n            speech=batch[\"speech\"],\n            speech_lengths=batch[\"speech_lengths\"])\n\n        l1_loss, l2_loss, bce_loss = self.criterion(\n            after_outs=after_outs,\n            before_outs=before_outs,\n            logits=logits,\n            ys=ys,\n            stop_labels=stop_labels,\n            olens=olens)\n\n        report(\"eval/bce_loss\", float(bce_loss))\n        report(\"eval/l1_loss\", float(l1_loss))\n        report(\"eval/l2_loss\", float(l2_loss))\n        losses_dict[\"bce_loss\"] = float(bce_loss)\n        losses_dict[\"l1_loss\"] = float(l1_loss)\n        losses_dict[\"l2_loss\"] = float(l2_loss)\n        # caluculate loss values\n        if self.loss_type == \"L1\":\n            loss = l1_loss + bce_loss\n        elif self.loss_type == \"L2\":\n            loss = l2_loss + bce_loss\n        elif self.loss_type == \"L1+L2\":\n            loss = l1_loss + l2_loss + bce_loss\n        else:\n            raise ValueError(\"unknown --loss-type \" + self.loss_type)\n\n        # calculate guided attention loss\n        if self.use_guided_attn_loss:\n            # calculate for encoder\n            if \"encoder\" in self.modules_applied_guided_attn:\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['encoder'].encoders)))):\n                    att_ws += [\n                        need_dict['encoder'].encoders[layer_idx].self_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_in, T_in)\n                att_ws = paddle.concat(att_ws, axis=1)\n                enc_attn_loss = self.attn_criterion(\n                    att_ws=att_ws,\n                    ilens=batch[\"text_lengths\"] + 1,\n                    olens=batch[\"text_lengths\"] + 1)\n                loss = loss + enc_attn_loss\n                report(\"train/enc_attn_loss\", float(enc_attn_loss))\n                losses_dict[\"enc_attn_loss\"] = float(enc_attn_loss)\n            # calculate for decoder\n            if \"decoder\" in self.modules_applied_guided_attn:\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['decoder'].decoders)))):\n                    att_ws += [\n                        need_dict['decoder'].decoders[layer_idx].self_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_out, T_out)\n                att_ws = paddle.concat(att_ws, axis=1)\n                dec_attn_loss = self.attn_criterion(\n                    att_ws=att_ws, ilens=olens_in, olens=olens_in)\n                report(\"eval/dec_attn_loss\", float(dec_attn_loss))\n                losses_dict[\"dec_attn_loss\"] = float(dec_attn_loss)\n                loss = loss + dec_attn_loss\n            # calculate for encoder-decoder\n            if \"encoder-decoder\" in self.modules_applied_guided_attn:\n\n                att_ws = []\n                for idx, layer_idx in enumerate(\n                        reversed(range(len(need_dict['decoder'].decoders)))):\n                    att_ws += [\n                        need_dict['decoder'].decoders[layer_idx].src_attn.\n                        attn[:, :need_dict['num_heads_applied_guided_attn']]\n                    ]\n                    if idx + 1 == need_dict['num_layers_applied_guided_attn']:\n                        break\n                # (B, H*L, T_out, T_in)\n                att_ws = paddle.concat(att_ws, axis=1)\n                enc_dec_attn_loss = self.attn_criterion(\n                    att_ws=att_ws,\n                    ilens=batch[\"text_lengths\"] + 1,\n                    olens=olens_in)\n                report(\"eval/enc_dec_attn_loss\", float(enc_dec_attn_loss))\n                losses_dict[\"enc_dec_attn_loss\"] = float(enc_dec_attn_loss)\n                loss = loss + enc_dec_attn_loss\n        if need_dict['use_scaled_pos_enc']:\n            report(\"eval/encoder_alpha\",\n                   float(need_dict['encoder'].embed[-1].alpha))\n            report(\"eval/decoder_alpha\",\n                   float(need_dict['decoder'].embed[-1].alpha))\n            losses_dict[\"encoder_alpha\"] = float(\n                need_dict['encoder'].embed[-1].alpha)\n            losses_dict[\"decoder_alpha\"] = float(\n                need_dict['decoder'].embed[-1].alpha)\n        report(\"eval/loss\", float(loss))\n        losses_dict[\"loss\"] = float(loss)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .vits import *\nfrom .vits_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/duration_predictor.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Stochastic duration predictor modules in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nimport math\nfrom typing import Optional\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.vits.flow import ConvFlow\nfrom paddlespeech.t2s.models.vits.flow import DilatedDepthSeparableConv\nfrom paddlespeech.t2s.models.vits.flow import ElementwiseAffineFlow\nfrom paddlespeech.t2s.models.vits.flow import FlipFlow\nfrom paddlespeech.t2s.models.vits.flow import LogFlow\n\n\nclass StochasticDurationPredictor(nn.Layer):\n    \"\"\"Stochastic duration predictor module.\n    This is a module of stochastic duration predictor described in `Conditional\n    Variational Autoencoder with Adversarial Learning for End-to-End Text-to-Speech`_.\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2106.06103\n    \"\"\"\n\n    def __init__(\n            self,\n            channels: int=192,\n            kernel_size: int=3,\n            dropout_rate: float=0.5,\n            flows: int=4,\n            dds_conv_layers: int=3,\n            global_channels: int=-1, ):\n        \"\"\"Initialize StochasticDurationPredictor module.\n        Args:\n            channels (int):\n                Number of channels.\n            kernel_size (int):\n                Kernel size.\n            dropout_rate (float):\n                Dropout rate.\n            flows (int):\n                Number of flows.\n            dds_conv_layers (int):\n                Number of conv layers in DDS conv.\n            global_channels (int):\n                Number of global conditioning channels.\n        \"\"\"\n        super().__init__()\n\n        self.pre = nn.Conv1D(channels, channels, 1)\n        self.dds = DilatedDepthSeparableConv(\n            channels,\n            kernel_size,\n            layers=dds_conv_layers,\n            dropout_rate=dropout_rate, )\n        self.proj = nn.Conv1D(channels, channels, 1)\n\n        self.log_flow = LogFlow()\n        self.flows = nn.LayerList()\n        self.flows.append(ElementwiseAffineFlow(2))\n        for i in range(flows):\n            self.flows.append(\n                ConvFlow(\n                    2,\n                    channels,\n                    kernel_size,\n                    layers=dds_conv_layers, ))\n            self.flows.append(FlipFlow())\n\n        self.post_pre = nn.Conv1D(1, channels, 1)\n        self.post_dds = DilatedDepthSeparableConv(\n            channels,\n            kernel_size,\n            layers=dds_conv_layers,\n            dropout_rate=dropout_rate, )\n        self.post_proj = nn.Conv1D(channels, channels, 1)\n        self.post_flows = nn.LayerList()\n        self.post_flows.append(ElementwiseAffineFlow(2))\n        for i in range(flows):\n            self.post_flows.append(\n                ConvFlow(\n                    2,\n                    channels,\n                    kernel_size,\n                    layers=dds_conv_layers, ))\n            self.post_flows.append(FlipFlow())\n\n        if global_channels > 0:\n            self.global_conv = nn.Conv1D(global_channels, channels, 1)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: paddle.Tensor,\n            w: Optional[paddle.Tensor]=None,\n            g: Optional[paddle.Tensor]=None,\n            inverse: bool=False,\n            noise_scale: float=1.0, ) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, channels, T_text).\n            x_mask (Tensor):\n                Mask tensor (B, 1, T_text).\n            w (Optional[Tensor]):\n                Duration tensor (B, 1, T_text).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, channels, 1)\n            inverse (bool):\n                Whether to inverse the flow.\n            noise_scale (float):\n                Noise scale value.\n        Returns:\n            Tensor: \n                If not inverse, negative log-likelihood (NLL) tensor (B,).\n                If inverse, log-duration tensor (B, 1, T_text).\n        \"\"\"\n        # stop gradient\n        # x = x.detach()  \n        x = self.pre(x)\n        if g is not None:\n            # stop gradient\n            x = x + self.global_conv(g.detach())\n        x = self.dds(x, x_mask)\n        x = self.proj(x) * x_mask\n\n        if not inverse:\n            assert w is not None, \"w must be provided.\"\n            h_w = self.post_pre(w)\n            h_w = self.post_dds(h_w, x_mask)\n            h_w = self.post_proj(h_w) * x_mask\n            e_q = (paddle.randn([paddle.shape(w)[0], 2, paddle.shape(w)[2]]) *\n                   x_mask)\n            z_q = e_q\n            logdet_tot_q = 0.0\n            for i, flow in enumerate(self.post_flows):\n                z_q, logdet_q = flow(z_q, x_mask, g=(x + h_w))\n                logdet_tot_q += logdet_q\n            z_u, z1 = paddle.split(z_q, [1, 1], 1)\n            u = F.sigmoid(z_u) * x_mask\n            z0 = (w - u) * x_mask\n            tmp1 = (F.log_sigmoid(z_u) + F.log_sigmoid(-z_u)) * x_mask\n            logdet_tot_q += paddle.sum(tmp1, [1, 2])\n            tmp2 = -0.5 * (math.log(2 * math.pi) + (e_q**2)) * x_mask\n            logq = (paddle.sum(tmp2, [1, 2]) - logdet_tot_q)\n            logdet_tot = 0\n            z0, logdet = self.log_flow(z0, x_mask)\n            logdet_tot += logdet\n            z = paddle.concat([z0, z1], 1)\n            for flow in self.flows:\n                z, logdet = flow(z, x_mask, g=x, inverse=inverse)\n                logdet_tot = logdet_tot + logdet\n            tmp3 = 0.5 * (math.log(2 * math.pi) + (z**2)) * x_mask\n            nll = (paddle.sum(tmp3, [1, 2]) - logdet_tot)\n            # (B,)\n            return nll + logq\n        else:\n            flows = list(reversed(self.flows))\n            # remove a useless vflow\n            flows = flows[:-2] + [flows[-1]]\n            z = (paddle.randn([paddle.shape(x)[0], 2, paddle.shape(x)[2]]) *\n                 noise_scale)\n            for flow in flows:\n                z = flow(z, x_mask, g=x, inverse=inverse)\n            z0, z1 = paddle.split(z, 2, axis=1)\n            logw = z0\n            return logw\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/flow.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Basic Flow modules used in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nimport math\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.vits.transform import piecewise_rational_quadratic_transform\n\n\nclass FlipFlow(nn.Layer):\n    \"\"\"Flip flow module.\"\"\"\n\n    def forward(self, x: paddle.Tensor, *args, inverse: bool=False, **kwargs\n                ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, paddle.Tensor]]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, channels, T).\n            inverse (bool):\n                Whether to inverse the flow.\n        Returns:\n            Tensor:\n                Flipped tensor (B, channels, T).\n            Tensor:\n                Log-determinant tensor for NLL (B,) if not inverse.\n        \"\"\"\n        x = paddle.flip(x, [1])\n        if not inverse:\n            logdet = paddle.zeros(paddle.shape(x)[0], dtype=x.dtype)\n            return x, logdet\n        else:\n            return x\n\n\nclass LogFlow(nn.Layer):\n    \"\"\"Log flow module.\"\"\"\n\n    def forward(self,\n                x: paddle.Tensor,\n                x_mask: paddle.Tensor,\n                inverse: bool=False,\n                eps: float=1e-5,\n                **kwargs\n                ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, paddle.Tensor]]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, channels, T).\n            x_mask (Tensor):\n                Mask tensor (B, 1, T).\n            inverse (bool):\n                Whether to inverse the flow.\n            eps (float):\n                Epsilon for log.\n        Returns:\n            Tensor:\n                Output tensor (B, channels, T).\n            Tensor:\n                Log-determinant tensor for NLL (B,) if not inverse.\n        \"\"\"\n        if not inverse:\n            y = paddle.log(paddle.clip(x, min=eps)) * x_mask\n            logdet = paddle.sum(-y, [1, 2])\n            return y, logdet\n        else:\n            x = paddle.exp(x) * x_mask\n            return x\n\n\nclass ElementwiseAffineFlow(nn.Layer):\n    \"\"\"Elementwise affine flow module.\"\"\"\n\n    def __init__(self, channels: int):\n        \"\"\"Initialize ElementwiseAffineFlow module.\n        Args:\n            channels (int):\n                Number of channels.\n        \"\"\"\n        super().__init__()\n        self.channels = channels\n\n        m = paddle.zeros([channels, 1])\n        self.m = paddle.create_parameter(\n            shape=m.shape,\n            dtype=str(m.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(m))\n        logs = paddle.zeros([channels, 1])\n        self.logs = paddle.create_parameter(\n            shape=logs.shape,\n            dtype=str(logs.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(logs))\n\n    def forward(self,\n                x: paddle.Tensor,\n                x_mask: paddle.Tensor,\n                inverse: bool=False,\n                **kwargs\n                ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, paddle.Tensor]]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, channels, T).\n            x_mask (Tensor):\n                Mask tensor (B, 1, T).\n            inverse (bool):\n                Whether to inverse the flow.\n        Returns:\n            Tensor:\n                Output tensor (B, channels, T).\n            Tensor:\n                Log-determinant tensor for NLL (B,) if not inverse.\n        \"\"\"\n        if not inverse:\n            y = self.m + paddle.exp(self.logs) * x\n            y = y * x_mask\n            logdet = paddle.sum(self.logs * x_mask, [1, 2])\n            return y, logdet\n        else:\n            x = (x - self.m) * paddle.exp(-self.logs) * x_mask\n            return x\n\n\nclass Transpose(nn.Layer):\n    \"\"\"Transpose module for paddle.nn.Sequential().\"\"\"\n\n    def __init__(self, dim1: int, dim2: int):\n        \"\"\"Initialize Transpose module.\"\"\"\n        super().__init__()\n        self.dim1 = dim1\n        self.dim2 = dim2\n\n    def forward(self, x: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Transpose.\"\"\"\n        len_dim = len(x.shape)\n        orig_perm = list(range(len_dim))\n        new_perm = orig_perm[:]\n        temp = new_perm[self.dim1]\n        new_perm[self.dim1] = new_perm[self.dim2]\n        new_perm[self.dim2] = temp\n\n        return paddle.transpose(x, new_perm)\n\n\nclass DilatedDepthSeparableConv(nn.Layer):\n    \"\"\"Dilated depth-separable conv module.\"\"\"\n\n    def __init__(\n            self,\n            channels: int,\n            kernel_size: int,\n            layers: int,\n            dropout_rate: float=0.0,\n            eps: float=1e-5, ):\n        \"\"\"Initialize DilatedDepthSeparableConv module.\n        Args:\n            channels (int):\n                Number of channels.\n            kernel_size (int):\n                Kernel size.\n            layers (int):\n                Number of layers.\n            dropout_rate (float):\n                Dropout rate.\n            eps (float):\n                Epsilon for layer norm.\n        \"\"\"\n        super().__init__()\n\n        self.convs = nn.LayerList()\n        for i in range(layers):\n            dilation = kernel_size**i\n            padding = (kernel_size * dilation - dilation) // 2\n            self.convs.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        channels,\n                        channels,\n                        kernel_size,\n                        groups=channels,\n                        dilation=dilation,\n                        padding=padding, ),\n                    Transpose(1, 2),\n                    nn.LayerNorm(channels, epsilon=eps),\n                    Transpose(1, 2),\n                    nn.GELU(),\n                    nn.Conv1D(\n                        channels,\n                        channels,\n                        1, ),\n                    Transpose(1, 2),\n                    nn.LayerNorm(channels, epsilon=eps),\n                    Transpose(1, 2),\n                    nn.GELU(),\n                    nn.Dropout(dropout_rate), ))\n\n    def forward(self,\n                x: paddle.Tensor,\n                x_mask: paddle.Tensor,\n                g: Optional[paddle.Tensor]=None) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, in_channels, T).\n            x_mask (Tensor):\n                Mask tensor (B, 1, T).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, global_channels, 1).\n        Returns:\n            Tensor:\n                Output tensor (B, channels, T).\n        \"\"\"\n        if g is not None:\n            x = x + g\n        for f in self.convs:\n            y = f(x * x_mask)\n            x = x + y\n        return x * x_mask\n\n\nclass ConvFlow(nn.Layer):\n    \"\"\"Convolutional flow module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int,\n            hidden_channels: int,\n            kernel_size: int,\n            layers: int,\n            bins: int=10,\n            tail_bound: float=5.0, ):\n        \"\"\"Initialize ConvFlow module.\n        Args:\n            in_channels (int):\n                Number of input channels.\n            hidden_channels (int):\n                Number of hidden channels.\n            kernel_size (int):\n                Kernel size.\n            layers (int):\n                Number of layers.\n            bins (int):\n                Number of bins.\n            tail_bound (float):\n                Tail bound value.\n        \"\"\"\n        super().__init__()\n        self.half_channels = in_channels // 2\n        self.hidden_channels = hidden_channels\n        self.bins = bins\n        self.tail_bound = tail_bound\n\n        self.input_conv = nn.Conv1D(\n            self.half_channels,\n            hidden_channels,\n            1, )\n        self.dds_conv = DilatedDepthSeparableConv(\n            hidden_channels,\n            kernel_size,\n            layers,\n            dropout_rate=0.0, )\n        self.proj = nn.Conv1D(\n            hidden_channels,\n            self.half_channels * (bins * 3 - 1),\n            1, )\n\n        weight = paddle.zeros(paddle.shape(self.proj.weight))\n\n        self.proj.weight = paddle.create_parameter(\n            shape=weight.shape,\n            dtype=str(weight.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(weight))\n\n        bias = paddle.zeros(paddle.shape(self.proj.bias))\n\n        self.proj.bias = paddle.create_parameter(\n            shape=bias.shape,\n            dtype=str(bias.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(bias))\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: paddle.Tensor,\n            g: Optional[paddle.Tensor]=None,\n            inverse: bool=False,\n    ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, paddle.Tensor]]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor):\n                Input tensor (B, channels, T).\n            x_mask (Tensor):\n                Mask tensor (B, 1, T).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, channels, 1).\n            inverse (bool):\n                Whether to inverse the flow.\n        Returns:\n            Tensor:\n                Output tensor (B, channels, T).\n            Tensor:\n                Log-determinant tensor for NLL (B,) if not inverse.\n        \"\"\"\n        xa, xb = x.split(2, 1)\n        h = self.input_conv(xa)\n        h = self.dds_conv(h, x_mask, g=g)\n        # (B, half_channels * (bins * 3 - 1), T)\n        h = self.proj(h) * x_mask\n\n        b, c, t = xa.shape\n        # (B, half_channels, bins * 3 - 1, T) -> (B, half_channels, T, bins * 3 - 1)\n        h = h.reshape([b, c, -1, t]).transpose([0, 1, 3, 2])\n\n        denom = math.sqrt(self.hidden_channels)\n        unnorm_widths = h[..., :self.bins] / denom\n        unnorm_heights = h[..., self.bins:2 * self.bins] / denom\n        unnorm_derivatives = h[..., 2 * self.bins:]\n\n        xb, logdet_abs = piecewise_rational_quadratic_transform(\n            inputs=xb,\n            unnormalized_widths=unnorm_widths,\n            unnormalized_heights=unnorm_heights,\n            unnormalized_derivatives=unnorm_derivatives,\n            inverse=inverse,\n            tails=\"linear\",\n            tail_bound=self.tail_bound, )\n        x = paddle.concat([xa, xb], 1) * x_mask\n        logdet = paddle.sum(logdet_abs * x_mask, [1, 2])\n        if not inverse:\n            return x, logdet\n        else:\n            return x\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/generator.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Generator module in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nimport math\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.hifigan import HiFiGANGenerator\nfrom paddlespeech.t2s.models.vits.duration_predictor import StochasticDurationPredictor\nfrom paddlespeech.t2s.models.vits.posterior_encoder import PosteriorEncoder\nfrom paddlespeech.t2s.models.vits.residual_coupling import ResidualAffineCouplingBlock\nfrom paddlespeech.t2s.models.vits.text_encoder import TextEncoder\nfrom paddlespeech.t2s.modules.nets_utils import get_random_segments\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\n\n\nclass VITSGenerator(nn.Layer):\n    \"\"\"Generator module in VITS.\n    This is a module of VITS described in `Conditional Variational Autoencoder\n    with Adversarial Learning for End-to-End Text-to-Speech`_.\n    As text encoder, we use conformer architecture instead of the relative positional\n    Transformer, which contains additional convolution layers.\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2006.04558\n    \"\"\"\n\n    def __init__(\n            self,\n            vocabs: int,\n            aux_channels: int=513,\n            hidden_channels: int=192,\n            spks: Optional[int]=None,\n            langs: Optional[int]=None,\n            spk_embed_dim: Optional[int]=None,\n            global_channels: int=-1,\n            segment_size: int=32,\n            text_encoder_attention_heads: int=2,\n            text_encoder_ffn_expand: int=4,\n            text_encoder_blocks: int=6,\n            text_encoder_positionwise_layer_type: str=\"conv1d\",\n            text_encoder_positionwise_conv_kernel_size: int=1,\n            text_encoder_positional_encoding_layer_type: str=\"rel_pos\",\n            text_encoder_self_attention_layer_type: str=\"rel_selfattn\",\n            text_encoder_activation_type: str=\"swish\",\n            text_encoder_normalize_before: bool=True,\n            text_encoder_dropout_rate: float=0.1,\n            text_encoder_positional_dropout_rate: float=0.0,\n            text_encoder_attention_dropout_rate: float=0.0,\n            text_encoder_conformer_kernel_size: int=7,\n            use_macaron_style_in_text_encoder: bool=True,\n            use_conformer_conv_in_text_encoder: bool=True,\n            decoder_kernel_size: int=7,\n            decoder_channels: int=512,\n            decoder_upsample_scales: List[int]=[8, 8, 2, 2],\n            decoder_upsample_kernel_sizes: List[int]=[16, 16, 4, 4],\n            decoder_resblock_kernel_sizes: List[int]=[3, 7, 11],\n            decoder_resblock_dilations: List[List[int]]=[[1, 3, 5], [1, 3, 5],\n                                                         [1, 3, 5]],\n            use_weight_norm_in_decoder: bool=True,\n            posterior_encoder_kernel_size: int=5,\n            posterior_encoder_layers: int=16,\n            posterior_encoder_stacks: int=1,\n            posterior_encoder_base_dilation: int=1,\n            posterior_encoder_dropout_rate: float=0.0,\n            use_weight_norm_in_posterior_encoder: bool=True,\n            flow_flows: int=4,\n            flow_kernel_size: int=5,\n            flow_base_dilation: int=1,\n            flow_layers: int=4,\n            flow_dropout_rate: float=0.0,\n            use_weight_norm_in_flow: bool=True,\n            use_only_mean_in_flow: bool=True,\n            stochastic_duration_predictor_kernel_size: int=3,\n            stochastic_duration_predictor_dropout_rate: float=0.5,\n            stochastic_duration_predictor_flows: int=4,\n            stochastic_duration_predictor_dds_conv_layers: int=3, ):\n        \"\"\"Initialize VITS generator module.\n        Args:\n            vocabs (int):\n                Input vocabulary size.\n            aux_channels (int):\n                Number of acoustic feature channels.\n            hidden_channels (int):\n                Number of hidden channels.\n            spks (Optional[int]):\n                Number of speakers. If set to > 1, assume that the\n                sids will be provided as the input and use sid embedding layer.\n            langs (Optional[int]):\n                Number of languages. If set to > 1, assume that the\n                lids will be provided as the input and use sid embedding layer.\n            spk_embed_dim (Optional[int]):\n                Speaker embedding dimension. If set to > 0,\n                assume that spembs will be provided as the input.\n            global_channels (int):\n                Number of global conditioning channels.\n            segment_size (int):\n                Segment size for decoder.\n            text_encoder_attention_heads (int):\n                Number of heads in conformer block of text encoder.\n            text_encoder_ffn_expand (int): \n                Expansion ratio of FFN in conformer block of text encoder.\n            text_encoder_blocks (int):\n                Number of conformer blocks in text encoder.\n            text_encoder_positionwise_layer_type (str):\n                Position-wise layer type in conformer block of text encoder.\n            text_encoder_positionwise_conv_kernel_size (int):\n                Position-wise convolution kernel size in conformer block of text encoder. \n                Only used when the above layer type is conv1d or conv1d-linear.\n            text_encoder_positional_encoding_layer_type (str):\n                Positional encoding layer type in conformer block of text encoder.\n            text_encoder_self_attention_layer_type (str):\n                Self-attention layer type in conformer block of text encoder.\n            text_encoder_activation_type (str):\n                Activation function type in conformer block of text encoder.\n            text_encoder_normalize_before (bool): \n                Whether to apply layer norm before self-attention in conformer block of text encoder.\n            text_encoder_dropout_rate (float):\n                Dropout rate in conformer block of text encoder.\n            text_encoder_positional_dropout_rate (float):\n                Dropout rate for positional encoding in conformer block of text encoder.\n            text_encoder_attention_dropout_rate (float):\n                Dropout rate for attention in conformer block of text encoder.\n            text_encoder_conformer_kernel_size (int):\n                Conformer conv kernel size. It will be used when only use_conformer_conv_in_text_encoder = True.\n            use_macaron_style_in_text_encoder (bool):\n                Whether to use macaron style FFN in conformer block of text encoder.\n            use_conformer_conv_in_text_encoder (bool):\n                Whether to use covolution in conformer block of text encoder.\n            decoder_kernel_size (int):\n                Decoder kernel size.\n            decoder_channels (int):\n                Number of decoder initial channels.\n            decoder_upsample_scales (List[int]):\n                List of upsampling scales in decoder.\n            decoder_upsample_kernel_sizes (List[int]):\n                List of kernel size for upsampling layers in decoder.\n            decoder_resblock_kernel_sizes (List[int]):\n                List of kernel size for resblocks in decoder.\n            decoder_resblock_dilations (List[List[int]]):\n                List of list of dilations for resblocks in decoder.\n            use_weight_norm_in_decoder (bool):\n                Whether to apply weight normalization in decoder.\n            posterior_encoder_kernel_size (int):\n                Posterior encoder kernel size.\n            posterior_encoder_layers (int):\n                Number of layers of posterior encoder.\n            posterior_encoder_stacks (int):\n                Number of stacks of posterior encoder.\n            posterior_encoder_base_dilation (int):\n                Base dilation of posterior encoder.\n            posterior_encoder_dropout_rate (float):\n                Dropout rate for posterior encoder.\n            use_weight_norm_in_posterior_encoder (bool): \n                Whether to apply weight normalization in posterior encoder.\n            flow_flows (int):\n                Number of flows in flow.\n            flow_kernel_size (int):\n                Kernel size in flow.\n            flow_base_dilation (int):\n                Base dilation in flow.\n            flow_layers (int):\n                Number of layers in flow.\n            flow_dropout_rate (float):\n                Dropout rate in flow\n            use_weight_norm_in_flow (bool):\n                Whether to apply weight normalization in flow.\n            use_only_mean_in_flow (bool):\n                Whether to use only mean in flow.\n            stochastic_duration_predictor_kernel_size (int): \n                Kernel size in stochastic duration predictor.\n            stochastic_duration_predictor_dropout_rate (float):\n                Dropout rate in stochastic duration predictor.\n            stochastic_duration_predictor_flows (int):\n                Number of flows in stochastic duration predictor.\n            stochastic_duration_predictor_dds_conv_layers (int):\n                Number of DDS conv layers in stochastic duration predictor.\n        \"\"\"\n        super().__init__()\n        self.segment_size = segment_size\n        self.text_encoder = TextEncoder(\n            vocabs=vocabs,\n            attention_dim=hidden_channels,\n            attention_heads=text_encoder_attention_heads,\n            linear_units=hidden_channels * text_encoder_ffn_expand,\n            blocks=text_encoder_blocks,\n            positionwise_layer_type=text_encoder_positionwise_layer_type,\n            positionwise_conv_kernel_size=text_encoder_positionwise_conv_kernel_size,\n            positional_encoding_layer_type=text_encoder_positional_encoding_layer_type,\n            self_attention_layer_type=text_encoder_self_attention_layer_type,\n            activation_type=text_encoder_activation_type,\n            normalize_before=text_encoder_normalize_before,\n            dropout_rate=text_encoder_dropout_rate,\n            positional_dropout_rate=text_encoder_positional_dropout_rate,\n            attention_dropout_rate=text_encoder_attention_dropout_rate,\n            conformer_kernel_size=text_encoder_conformer_kernel_size,\n            use_macaron_style=use_macaron_style_in_text_encoder,\n            use_conformer_conv=use_conformer_conv_in_text_encoder, )\n        self.decoder = HiFiGANGenerator(\n            in_channels=hidden_channels,\n            out_channels=1,\n            channels=decoder_channels,\n            global_channels=global_channels,\n            kernel_size=decoder_kernel_size,\n            upsample_scales=decoder_upsample_scales,\n            upsample_kernel_sizes=decoder_upsample_kernel_sizes,\n            resblock_kernel_sizes=decoder_resblock_kernel_sizes,\n            resblock_dilations=decoder_resblock_dilations,\n            use_weight_norm=use_weight_norm_in_decoder, )\n        self.posterior_encoder = PosteriorEncoder(\n            in_channels=aux_channels,\n            out_channels=hidden_channels,\n            hidden_channels=hidden_channels,\n            kernel_size=posterior_encoder_kernel_size,\n            layers=posterior_encoder_layers,\n            stacks=posterior_encoder_stacks,\n            base_dilation=posterior_encoder_base_dilation,\n            global_channels=global_channels,\n            dropout_rate=posterior_encoder_dropout_rate,\n            use_weight_norm=use_weight_norm_in_posterior_encoder, )\n        self.flow = ResidualAffineCouplingBlock(\n            in_channels=hidden_channels,\n            hidden_channels=hidden_channels,\n            flows=flow_flows,\n            kernel_size=flow_kernel_size,\n            base_dilation=flow_base_dilation,\n            layers=flow_layers,\n            global_channels=global_channels,\n            dropout_rate=flow_dropout_rate,\n            use_weight_norm=use_weight_norm_in_flow,\n            use_only_mean=use_only_mean_in_flow, )\n        # TODO: Add deterministic version as an option\n        self.duration_predictor = StochasticDurationPredictor(\n            channels=hidden_channels,\n            kernel_size=stochastic_duration_predictor_kernel_size,\n            dropout_rate=stochastic_duration_predictor_dropout_rate,\n            flows=stochastic_duration_predictor_flows,\n            dds_conv_layers=stochastic_duration_predictor_dds_conv_layers,\n            global_channels=global_channels, )\n\n        self.upsample_factor = int(np.prod(decoder_upsample_scales))\n        self.spks = None\n        if spks is not None and spks > 1:\n            assert global_channels > 0\n            self.spks = spks\n            self.global_emb = nn.Embedding(spks, global_channels)\n        self.spk_embed_dim = None\n        if spk_embed_dim is not None and spk_embed_dim > 0:\n            assert global_channels > 0\n            self.spk_embed_dim = spk_embed_dim\n            self.spemb_proj = nn.Linear(spk_embed_dim, global_channels)\n        self.langs = None\n        if langs is not None and langs > 1:\n            assert global_channels > 0\n            self.langs = langs\n            self.lang_emb = nn.Embedding(langs, global_channels)\n\n        # delayed import\n        from paddlespeech.t2s.models.vits.monotonic_align import maximum_path\n\n        self.maximum_path = maximum_path\n        self.pad1d = nn.Pad1D(\n            padding=[1, 0],\n            mode='constant',\n            data_format='NLC', )\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n               paddle.Tensor, paddle.Tensor,\n               Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor,\n                     paddle.Tensor, paddle.Tensor, ], ]:\n        \"\"\"Calculate forward propagation.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, aux_channels, T_feats).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n        Returns:\n            Tensor:\n                Waveform tensor (B, 1, segment_size * upsample_factor).\n            Tensor:\n                Duration negative log-likelihood (NLL) tensor (B,).\n            Tensor:\n                Monotonic attention weight tensor (B, 1, T_feats, T_text).\n            Tensor:\n                Segments start index tensor (B,).\n            Tensor:\n                Text mask tensor (B, 1, T_text).\n            Tensor: \n                Feature mask tensor (B, 1, T_feats).\n                tuple[Tensor, Tensor, Tensor, Tensor, Tensor, Tensor]:\n                    - Tensor: Posterior encoder hidden representation (B, H, T_feats).\n                    - Tensor: Flow hidden representation (B, H, T_feats).\n                    - Tensor: Expanded text encoder projected mean (B, H, T_feats).\n                    - Tensor: Expanded text encoder projected scale (B, H, T_feats).\n                    - Tensor: Posterior encoder projected mean (B, H, T_feats).\n                    - Tensor: Posterior encoder projected scale (B, H, T_feats).\n        \"\"\"\n        # forward text encoder\n        x, m_p, logs_p, x_mask = self.text_encoder(text, text_lengths)\n\n        # calculate global conditioning\n        g = None\n        if self.spks is not None:\n            # speaker one-hot vector embedding: (B, global_channels, 1)\n            g = self.global_emb(paddle.reshape(sids, [-1])).unsqueeze(-1)\n        if self.spk_embed_dim is not None:\n            # pretreined speaker embedding, e.g., X-vector (B, global_channels, 1)\n            g_ = self.spemb_proj(F.normalize(spembs)).unsqueeze(-1)\n            if g is None:\n                g = g_\n            else:\n                g = g + g_\n        if self.langs is not None:\n            # language one-hot vector embedding: (B, global_channels, 1)\n            g_ = self.lang_emb(paddle.reshape(lids, [-1])).unsqueeze(-1)\n            if g is None:\n                g = g_\n            else:\n                g = g + g_\n\n        # forward posterior encoder\n        z, m_q, logs_q, y_mask = self.posterior_encoder(\n            feats, feats_lengths, g=g)\n\n        # forward flow\n        # (B, H, T_feats)\n        z_p = self.flow(z, y_mask, g=g)\n\n        # monotonic alignment search\n        with paddle.no_grad():\n            # negative cross-entropy\n            # (B, H, T_text)\n            s_p_sq_r = paddle.exp(-2 * logs_p)\n            # (B, 1, T_text)\n            tmp1 = -0.5 * math.log(2 * math.pi) - logs_p\n            neg_x_ent_1 = paddle.sum(\n                tmp1,\n                [1],\n                keepdim=True, )\n            # (B, T_feats, H) x (B, H, T_text) = (B, T_feats, T_text)\n            neg_x_ent_2 = paddle.matmul(\n                -0.5 * (z_p**2).transpose([0, 2, 1]),\n                s_p_sq_r, )\n            # (B, T_feats, H) x (B, H, T_text) = (B, T_feats, T_text)\n            neg_x_ent_3 = paddle.matmul(\n                z_p.transpose([0, 2, 1]),\n                (m_p * s_p_sq_r), )\n            # (B, 1, T_text)\n            tmp2 = -0.5 * (m_p**2) * s_p_sq_r\n            neg_x_ent_4 = paddle.sum(\n                tmp2,\n                [1],\n                keepdim=True, )\n            # (B, T_feats, T_text)\n            neg_x_ent = neg_x_ent_1 + neg_x_ent_2 + neg_x_ent_3 + neg_x_ent_4\n            # (B, 1, T_feats, T_text)\n            attn_mask = paddle.unsqueeze(x_mask, 2) * paddle.unsqueeze(y_mask,\n                                                                       -1)\n            # monotonic attention weight: (B, 1, T_feats, T_text)\n            attn = (self.maximum_path(\n                neg_x_ent,\n                attn_mask.squeeze(1), ).unsqueeze(1).detach())\n\n        # forward duration predictor\n        # (B, 1, T_text)\n        w = attn.sum(2)\n        dur_nll = self.duration_predictor(x, x_mask, w=w, g=g)\n        dur_nll = dur_nll / paddle.sum(x_mask)\n        # expand the length to match with the feature sequence\n        # (B, T_feats, T_text) x (B, T_text, H) -> (B, H, T_feats)\n        m_p = paddle.matmul(attn.squeeze(1),\n                            m_p.transpose([0, 2, 1])).transpose([0, 2, 1])\n        # (B, T_feats, T_text) x (B, T_text, H) -> (B, H, T_feats)\n        logs_p = paddle.matmul(attn.squeeze(1),\n                               logs_p.transpose([0, 2, 1])).transpose([0, 2, 1])\n\n        # get random segments\n        z_segments, z_start_idxs = get_random_segments(\n            z,\n            feats_lengths,\n            self.segment_size, )\n\n        # forward decoder with random segments\n        wav = self.decoder(z_segments, g=g)\n\n        return (wav, dur_nll, attn, z_start_idxs, x_mask, y_mask,\n                (z, z_p, m_p, logs_p, m_q, logs_q), )\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: Optional[paddle.Tensor]=None,\n            feats_lengths: Optional[paddle.Tensor]=None,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            dur: Optional[paddle.Tensor]=None,\n            noise_scale: float=0.667,\n            noise_scale_dur: float=0.8,\n            alpha: float=1.0,\n            max_len: Optional[int]=None,\n            use_teacher_forcing: bool=False,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Run inference.\n        Args:\n            text (Tensor):\n                Input text index tensor (B, T_text,).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, aux_channels, T_feats,).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            dur (Optional[Tensor]):\n                Ground-truth duration (B, T_text,). If provided,\n                skip the prediction of durations (i.e., teacher forcing).\n            noise_scale (float):\n                Noise scale parameter for flow.\n            noise_scale_dur (float):\n                Noise scale parameter for duration predictor.\n            alpha (float):\n                Alpha parameter to control the speed of generated speech.\n            max_len (Optional[int]):\n                Maximum length of acoustic feature sequence.\n            use_teacher_forcing (bool):\n                Whether to use teacher forcing.\n        Returns:\n            Tensor: \n                Generated waveform tensor (B, T_wav).\n            Tensor:\n                Monotonic attention weight tensor (B, T_feats, T_text).\n            Tensor:\n                Duration tensor (B, T_text).\n        \"\"\"\n        # encoder\n        x, m_p, logs_p, x_mask = self.text_encoder(text, text_lengths)\n        g = None\n        if self.spks is not None:\n            # (B, global_channels, 1)\n            g = self.global_emb(paddle.reshape(sids, [-1])).unsqueeze(-1)\n        if self.spk_embed_dim is not None:\n            # (B, global_channels, 1)\n            g_ = self.spemb_proj(F.normalize(spembs.unsqueeze(0))).unsqueeze(-1)\n            if g is None:\n                g = g_\n            else:\n                g = g + g_\n        if self.langs is not None:\n            # (B, global_channels, 1)\n            g_ = self.lang_emb(paddle.reshape(lids, [-1])).unsqueeze(-1)\n            if g is None:\n                g = g_\n            else:\n                g = g + g_\n\n        if use_teacher_forcing:\n            # forward posterior encoder\n            z, m_q, logs_q, y_mask = self.posterior_encoder(\n                feats, feats_lengths, g=g)\n\n            # forward flow\n            # (B, H, T_feats)\n            z_p = self.flow(z, y_mask, g=g)\n\n            # monotonic alignment search\n            # (B, H, T_text)\n            s_p_sq_r = paddle.exp(-2 * logs_p)\n            # (B, 1, T_text)\n            tmp3 = -0.5 * math.log(2 * math.pi) - logs_p\n            neg_x_ent_1 = paddle.sum(\n                tmp3,\n                [1],\n                keepdim=True, )\n            # (B, T_feats, H) x (B, H, T_text) = (B, T_feats, T_text)\n            neg_x_ent_2 = paddle.matmul(\n                -0.5 * (z_p**2).transpose([0, 2, 1]),\n                s_p_sq_r, )\n            # (B, T_feats, H) x (B, H, T_text) = (B, T_feats, T_text)\n            neg_x_ent_3 = paddle.matmul(\n                z_p.transpose([0, 2, 1]),\n                (m_p * s_p_sq_r), )\n            # (B, 1, T_text)\n            tmp4 = -0.5 * (m_p**2) * s_p_sq_r\n            neg_x_ent_4 = paddle.sum(\n                tmp4,\n                [1],\n                keepdim=True, )\n            # (B, T_feats, T_text)\n            neg_x_ent = neg_x_ent_1 + neg_x_ent_2 + neg_x_ent_3 + neg_x_ent_4\n            # (B, 1, T_feats, T_text)\n            attn_mask = paddle.unsqueeze(x_mask, 2) * paddle.unsqueeze(y_mask,\n                                                                       -1)\n            # monotonic attention weight: (B, 1, T_feats, T_text)\n            attn = self.maximum_path(\n                neg_x_ent,\n                attn_mask.squeeze(1), ).unsqueeze(1)\n            # (B, 1, T_text)\n            dur = attn.sum(2)\n\n            # forward decoder with random segments\n            wav = self.decoder(z * y_mask, g=g)\n        else:\n            # duration\n            if dur is None:\n                logw = self.duration_predictor(\n                    x,\n                    x_mask,\n                    g=g,\n                    inverse=True,\n                    noise_scale=noise_scale_dur, )\n                w = paddle.exp(logw) * x_mask * alpha\n                dur = paddle.ceil(w)\n            y_lengths = paddle.cast(\n                paddle.clip(paddle.sum(dur, [1, 2]), min=1), dtype='int64')\n            y_mask = make_non_pad_mask(y_lengths).unsqueeze(1)\n            tmp_a = paddle.cast(paddle.unsqueeze(x_mask, 2), dtype='int64')\n            tmp_b = paddle.cast(paddle.unsqueeze(y_mask, -1), dtype='int64')\n            attn_mask = tmp_a * tmp_b\n            attn = self._generate_path(dur, attn_mask)\n\n            # expand the length to match with the feature sequence\n            # (B, T_feats, T_text) x (B, T_text, H) -> (B, H, T_feats)\n            m_p = paddle.matmul(\n                attn.squeeze(1),\n                m_p.transpose([0, 2, 1]), ).transpose([0, 2, 1])\n            # (B, T_feats, T_text) x (B, T_text, H) -> (B, H, T_feats)\n            logs_p = paddle.matmul(\n                attn.squeeze(1),\n                logs_p.transpose([0, 2, 1]), ).transpose([0, 2, 1])\n\n            # decoder\n            z_p = m_p + paddle.randn(\n                paddle.shape(m_p)) * paddle.exp(logs_p) * noise_scale\n            z = self.flow(z_p, y_mask.astype(z_p.dtype), g=g, inverse=True)\n            wav = self.decoder(\n                (z * y_mask.astype(z.dtype))[:, :, :max_len], g=g)\n\n        return wav.squeeze(1), attn.squeeze(1), dur.squeeze(1)\n\n    def voice_conversion(\n            self,\n            feats: paddle.Tensor=None,\n            feats_lengths: paddle.Tensor=None,\n            sids_src: Optional[paddle.Tensor]=None,\n            sids_tgt: Optional[paddle.Tensor]=None,\n            spembs_src: Optional[paddle.Tensor]=None,\n            spembs_tgt: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None, ) -> paddle.Tensor:\n        \"\"\"Run voice conversion.\n        Args:\n            feats (Tensor):\n                Feature tensor (B, aux_channels, T_feats,).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids_src (Optional[Tensor]):\n                Speaker index tensor of source feature (B,) or (B, 1).\n            sids_tgt (Optional[Tensor]):\n                Speaker index tensor of target feature (B,) or (B, 1).\n            spembs_src (Optional[Tensor]):\n                Speaker embedding tensor of source feature (B, spk_embed_dim).\n            spembs_tgt (Optional[Tensor]):\n                Speaker embedding tensor of target feature (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n        Returns:\n            Tensor:\n                Generated waveform tensor (B, T_wav).\n        \"\"\"\n        # encoder\n        g_src = None\n        g_tgt = None\n        if self.spks is not None:\n            # (B, global_channels, 1)\n            g_src = self.global_emb(\n                paddle.reshape(sids_src, [-1])).unsqueeze(-1)\n            g_tgt = self.global_emb(\n                paddle.reshape(sids_tgt, [-1])).unsqueeze(-1)\n\n        if self.spk_embed_dim is not None:\n            # (B, global_channels, 1)\n            g_src_ = self.spemb_proj(\n                F.normalize(spembs_src.unsqueeze(0))).unsqueeze(-1)\n            if g_src is None:\n                g_src = g_src_\n            else:\n                g_src = g_src + g_src_\n\n            # (B, global_channels, 1)\n            g_tgt_ = self.spemb_proj(\n                F.normalize(spembs_tgt.unsqueeze(0))).unsqueeze(-1)\n            if g_tgt is None:\n                g_tgt = g_tgt_\n            else:\n                g_tgt = g_tgt + g_tgt_\n\n        if self.langs is not None:\n            # (B, global_channels, 1)\n            g_ = self.lang_emb(paddle.reshape(lids, [-1])).unsqueeze(-1)\n\n            if g_src is None:\n                g_src = g_\n            else:\n                g_src = g_src + g_\n\n            if g_tgt is None:\n                g_tgt = g_\n            else:\n                g_tgt = g_tgt + g_\n\n        # forward posterior encoder\n        z, m_q, logs_q, y_mask = self.posterior_encoder(\n            feats, feats_lengths, g=g_src)\n\n        # forward flow\n        # (B, H, T_feats)\n        z_p = self.flow(z, y_mask, g=g_src)\n\n        # decoder\n        z_hat = self.flow(z_p, y_mask, g=g_tgt, inverse=True)\n        wav = self.decoder(z_hat * y_mask, g=g_tgt)\n\n        return wav.squeeze(1)\n\n    def _generate_path(self, dur: paddle.Tensor,\n                       mask: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Generate path a.k.a. monotonic attention.\n        Args:\n            dur (Tensor):\n                Duration tensor (B, 1, T_text).\n            mask (Tensor):\n                Attention mask tensor (B, 1, T_feats, T_text).\n        Returns:\n            Tensor:\n                Path tensor (B, 1, T_feats, T_text).\n        \"\"\"\n        b, _, t_y, t_x = paddle.shape(mask)\n        cum_dur = paddle.cumsum(dur, -1)\n        cum_dur_flat = paddle.reshape(cum_dur, [b * t_x])\n\n        path = paddle.arange(t_y, dtype=dur.dtype)\n        path = path.unsqueeze(0) < cum_dur_flat.unsqueeze(1)\n        path = paddle.reshape(path, [b, t_x, t_y])\n        '''\n        path will be like (t_x = 3, t_y = 5):\n        [[[1., 1., 0., 0., 0.],      [[[1., 1., 0., 0., 0.],\n          [1., 1., 1., 1., 0.],  -->   [0., 0., 1., 1., 0.],\n          [1., 1., 1., 1., 1.]]]       [0., 0., 0., 0., 1.]]]\n        '''\n\n        path = paddle.cast(path, dtype='float32')\n        pad_tmp = self.pad1d(path)[:, :-1]\n        path = path - pad_tmp\n        return path.unsqueeze(1).transpose(\n            [0, 1, 3, 2]) * mask.astype(path.dtype)\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/monotonic_align/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Maximum path calculation module.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nimport warnings\n\nimport numpy as np\nimport paddle\nfrom numba import njit\nfrom numba import prange\n\ntry:\n    from .core import maximum_path_c\n\n    is_cython_avalable = True\nexcept ImportError:\n    is_cython_avalable = False\n    warnings.warn(\n        \"Cython version is not available. Fallback to 'EXPERIMETAL' numba version. \"\n        \"If you want to use the cython version, please build it as follows: \"\n        \"`cd paddlespeech/t2s/models/vits/monotonic_align; python setup.py build_ext --inplace`\"\n    )\n\n\ndef maximum_path(neg_x_ent: paddle.Tensor,\n                 attn_mask: paddle.Tensor) -> paddle.Tensor:\n    \"\"\"Calculate maximum path.\n\n    Args:\n        neg_x_ent (Tensor): Negative X entropy tensor (B, T_feats, T_text).\n        attn_mask (Tensor): Attention mask (B, T_feats, T_text).\n\n    Returns:\n        Tensor: Maximum path tensor (B, T_feats, T_text).\n\n    \"\"\"\n    dtype = neg_x_ent.dtype\n    neg_x_ent = neg_x_ent.numpy().astype(np.float32)\n    path = np.zeros(neg_x_ent.shape, dtype=np.int32)\n    t_t_max = attn_mask.sum(1)[:, 0].cpu().numpy().astype(np.int32)\n    t_s_max = attn_mask.sum(2)[:, 0].cpu().numpy().astype(np.int32)\n    if is_cython_avalable:\n        maximum_path_c(path, neg_x_ent, t_t_max, t_s_max)\n    else:\n        maximum_path_numba(path, neg_x_ent, t_t_max, t_s_max)\n\n    return paddle.cast(paddle.to_tensor(path), dtype=dtype)\n\n\n@njit\ndef maximum_path_each_numba(path, value, t_y, t_x, max_neg_val=-np.inf):\n    \"\"\"Calculate a single maximum path with numba.\"\"\"\n    index = t_x - 1\n    for y in range(t_y):\n        for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)):\n            if x == y:\n                v_cur = max_neg_val\n            else:\n                v_cur = value[y - 1, x]\n            if x == 0:\n                if y == 0:\n                    v_prev = 0.0\n                else:\n                    v_prev = max_neg_val\n            else:\n                v_prev = value[y - 1, x - 1]\n            value[y, x] += max(v_prev, v_cur)\n\n    for y in range(t_y - 1, -1, -1):\n        path[y, index] = 1\n        if index != 0 and (index == y or\n                           value[y - 1, index] < value[y - 1, index - 1]):\n            index = index - 1\n\n\n@njit(parallel=True)\ndef maximum_path_numba(paths, values, t_ys, t_xs):\n    \"\"\"Calculate batch maximum path with numba.\"\"\"\n    for i in prange(paths.shape[0]):\n        maximum_path_each_numba(paths[i], values[i], t_ys[i], t_xs[i])\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/monotonic_align/core.pyx",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Maximum path calculation module with cython optimization.\n\nThis code is copied from https://github.com/jaywalnut310/vits and modifed code format.\n\n\"\"\"\n\ncimport cython\n\nfrom cython.parallel import prange\n\n\n@cython.boundscheck(False)\n@cython.wraparound(False)\ncdef void maximum_path_each(int[:, ::1] path, float[:, ::1] value, int t_y, int t_x, float max_neg_val=-1e9) nogil:\n    cdef int x\n    cdef int y\n    cdef float v_prev\n    cdef float v_cur\n    cdef float tmp\n    cdef int index = t_x - 1\n\n    for y in range(t_y):\n        for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)):\n            if x == y:\n                v_cur = max_neg_val\n            else:\n                v_cur = value[y - 1, x]\n            if x == 0:\n                if y == 0:\n                    v_prev = 0.0\n                else:\n                    v_prev = max_neg_val\n            else:\n                v_prev = value[y - 1, x - 1]\n            value[y, x] += max(v_prev, v_cur)\n\n    for y in range(t_y - 1, -1, -1):\n        path[y, index] = 1\n        if index != 0 and (index == y or value[y - 1, index] < value[y - 1, index - 1]):\n            index = index - 1\n\n\n@cython.boundscheck(False)\n@cython.wraparound(False)\ncpdef void maximum_path_c(int[:, :, ::1] paths, float[:, :, ::1] values, int[::1] t_ys, int[::1] t_xs) nogil:\n    cdef int b = paths.shape[0]\n    cdef int i\n    for i in prange(b, nogil=True):\n        maximum_path_each(paths[i], values[i], t_ys[i], t_xs[i])\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/monotonic_align/setup.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Setup cython code.\"\"\"\nfrom Cython.Build import cythonize\nfrom setuptools import Extension\nfrom setuptools import setup\nfrom setuptools.command.build_ext import build_ext as _build_ext\n\n\nclass build_ext(_build_ext):\n    \"\"\"Overwrite build_ext.\"\"\"\n\n    def finalize_options(self):\n        \"\"\"Prevent numpy from thinking it is still in its setup process.\"\"\"\n        _build_ext.finalize_options(self)\n        __builtins__.__NUMPY_SETUP__ = False\n        import numpy\n\n        self.include_dirs.append(numpy.get_include())\n\n\nexts = [Extension(\n    name=\"core\",\n    sources=[\"core.pyx\"], )]\nsetup(\n    name=\"monotonic_align\",\n    ext_modules=cythonize(exts, language_level=3),\n    cmdclass={\"build_ext\": build_ext}, )\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/posterior_encoder.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Text encoder module in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.vits.wavenet.wavenet import WaveNet\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\n\n\nclass PosteriorEncoder(nn.Layer):\n    \"\"\"Posterior encoder module in VITS.\n\n    This is a module of posterior encoder described in `Conditional Variational\n    Autoencoder with Adversarial Learning for End-to-End Text-to-Speech`_.\n\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2006.04558\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=513,\n            out_channels: int=192,\n            hidden_channels: int=192,\n            kernel_size: int=5,\n            layers: int=16,\n            stacks: int=1,\n            base_dilation: int=1,\n            global_channels: int=-1,\n            dropout_rate: float=0.0,\n            bias: bool=True,\n            use_weight_norm: bool=True, ):\n        \"\"\"Initilialize PosteriorEncoder module.\n\n        Args:\n            in_channels (int):\n                Number of input channels.\n            out_channels (int):\n                Number of output channels.\n            hidden_channels (int):\n                Number of hidden channels.\n            kernel_size (int):\n                Kernel size in WaveNet.\n            layers (int):\n                Number of layers of WaveNet.\n            stacks (int):\n                Number of repeat stacking of WaveNet.\n            base_dilation (int):\n                Base dilation factor.\n            global_channels (int):\n                Number of global conditioning channels.\n            dropout_rate (float):\n                Dropout rate.\n            bias (bool):\n                Whether to use bias parameters in conv.\n            use_weight_norm (bool):\n                Whether to apply weight norm.\n\n        \"\"\"\n        super().__init__()\n\n        # define modules\n        self.input_conv = nn.Conv1D(in_channels, hidden_channels, 1)\n        self.encoder = WaveNet(\n            in_channels=-1,\n            out_channels=-1,\n            kernel_size=kernel_size,\n            layers=layers,\n            stacks=stacks,\n            base_dilation=base_dilation,\n            residual_channels=hidden_channels,\n            aux_channels=-1,\n            gate_channels=hidden_channels * 2,\n            skip_channels=hidden_channels,\n            global_channels=global_channels,\n            dropout_rate=dropout_rate,\n            bias=bias,\n            use_weight_norm=use_weight_norm,\n            use_first_conv=False,\n            use_last_conv=False,\n            scale_residual=False,\n            scale_skip_connect=True, )\n        self.proj = nn.Conv1D(hidden_channels, out_channels * 2, 1)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_lengths: paddle.Tensor,\n            g: Optional[paddle.Tensor]=None\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor):\n                Input tensor (B, in_channels, T_feats).\n            x_lengths (Tensor):\n                Length tensor (B,).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, global_channels, 1).\n\n        Returns:\n            Tensor:\n                Encoded hidden representation tensor (B, out_channels, T_feats).\n            Tensor:\n                Projected mean tensor (B, out_channels, T_feats).\n            Tensor:\n                Projected scale tensor (B, out_channels, T_feats).\n            Tensor:\n                Mask tensor for input tensor (B, 1, T_feats).\n\n        \"\"\"\n        x_mask = make_non_pad_mask(x_lengths).unsqueeze(1)\n        x_mask = x_mask.astype(x.dtype)\n        x = self.input_conv(x) * x_mask\n        x = self.encoder(x, x_mask, g=g)\n        stats = self.proj(x) * x_mask\n        m, logs = paddle.split(stats, 2, axis=1)\n        z = (m + paddle.randn(paddle.shape(m)) * paddle.exp(logs)) * x_mask\n\n        return z, m, logs, x_mask\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/residual_coupling.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Residual affine coupling modules in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.vits.flow import FlipFlow\nfrom paddlespeech.t2s.models.vits.wavenet.wavenet import WaveNet\n\n\nclass ResidualAffineCouplingBlock(nn.Layer):\n    \"\"\"Residual affine coupling block module.\n\n    This is a module of residual affine coupling block, which used as \"Flow\" in\n    `Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n    Text-to-Speech`_.\n\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2006.04558\n\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=192,\n            hidden_channels: int=192,\n            flows: int=4,\n            kernel_size: int=5,\n            base_dilation: int=1,\n            layers: int=4,\n            global_channels: int=-1,\n            dropout_rate: float=0.0,\n            use_weight_norm: bool=True,\n            bias: bool=True,\n            use_only_mean: bool=True, ):\n        \"\"\"Initilize ResidualAffineCouplingBlock module.\n\n        Args:\n            in_channels (int):\n                Number of input channels.\n            hidden_channels (int):\n                Number of hidden channels.\n            flows (int):\n                Number of flows.\n            kernel_size (int):\n                Kernel size for WaveNet.\n            base_dilation (int):\n                Base dilation factor for WaveNet.\n            layers (int):\n                Number of layers of WaveNet.\n            stacks (int):\n                Number of stacks of WaveNet.\n            global_channels (int):\n                Number of global channels.\n            dropout_rate (float):\n                Dropout rate.\n            use_weight_norm (bool):\n                Whether to use weight normalization in WaveNet.\n            bias (bool):\n                Whether to use bias parameters in WaveNet.\n            use_only_mean (bool):\n                Whether to estimate only mean.\n\n        \"\"\"\n        super().__init__()\n\n        self.flows = nn.LayerList()\n        for i in range(flows):\n            self.flows.append(\n                ResidualAffineCouplingLayer(\n                    in_channels=in_channels,\n                    hidden_channels=hidden_channels,\n                    kernel_size=kernel_size,\n                    base_dilation=base_dilation,\n                    layers=layers,\n                    stacks=1,\n                    global_channels=global_channels,\n                    dropout_rate=dropout_rate,\n                    use_weight_norm=use_weight_norm,\n                    bias=bias,\n                    use_only_mean=use_only_mean, ))\n            self.flows.append(FlipFlow())\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: paddle.Tensor,\n            g: Optional[paddle.Tensor]=None,\n            inverse: bool=False, ) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor):\n                Input tensor (B, in_channels, T).\n            x_mask (Tensor):\n                Length tensor (B, 1, T).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, global_channels, 1).\n            inverse (bool):\n                Whether to inverse the flow.\n\n        Returns:\n            Tensor: Output tensor (B, in_channels, T).\n\n        \"\"\"\n        if not inverse:\n            for flow in self.flows:\n                x, _ = flow(x, x_mask, g=g, inverse=inverse)\n        else:\n            for flow in reversed(self.flows):\n                x = flow(x, x_mask, g=g, inverse=inverse)\n        return x\n\n\nclass ResidualAffineCouplingLayer(nn.Layer):\n    \"\"\"Residual affine coupling layer.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=192,\n            hidden_channels: int=192,\n            kernel_size: int=5,\n            base_dilation: int=1,\n            layers: int=5,\n            stacks: int=1,\n            global_channels: int=-1,\n            dropout_rate: float=0.0,\n            use_weight_norm: bool=True,\n            bias: bool=True,\n            use_only_mean: bool=True, ):\n        \"\"\"Initialzie ResidualAffineCouplingLayer module.\n\n        Args:\n            in_channels (int):\n                Number of input channels.\n            hidden_channels (int):\n                Number of hidden channels.\n            kernel_size (int):\n                Kernel size for WaveNet.\n            base_dilation (int):\n                Base dilation factor for WaveNet.\n            layers (int):\n                Number of layers of WaveNet.\n            stacks (int):\n                Number of stacks of WaveNet.\n            global_channels (int):\n                Number of global channels.\n            dropout_rate (float):\n                Dropout rate.\n            use_weight_norm (bool):\n                Whether to use weight normalization in WaveNet.\n            bias (bool):\n                Whether to use bias parameters in WaveNet.\n            use_only_mean (bool):\n                Whether to estimate only mean.\n\n        \"\"\"\n        assert in_channels % 2 == 0, \"in_channels should be divisible by 2\"\n        super().__init__()\n        self.half_channels = in_channels // 2\n        self.use_only_mean = use_only_mean\n\n        # define modules\n        self.input_conv = nn.Conv1D(\n            self.half_channels,\n            hidden_channels,\n            1, )\n        self.encoder = WaveNet(\n            in_channels=-1,\n            out_channels=-1,\n            kernel_size=kernel_size,\n            layers=layers,\n            stacks=stacks,\n            base_dilation=base_dilation,\n            residual_channels=hidden_channels,\n            aux_channels=-1,\n            gate_channels=hidden_channels * 2,\n            skip_channels=hidden_channels,\n            global_channels=global_channels,\n            dropout_rate=dropout_rate,\n            bias=bias,\n            use_weight_norm=use_weight_norm,\n            use_first_conv=False,\n            use_last_conv=False,\n            scale_residual=False,\n            scale_skip_connect=True, )\n        if use_only_mean:\n            self.proj = nn.Conv1D(\n                hidden_channels,\n                self.half_channels,\n                1, )\n        else:\n            self.proj = nn.Conv1D(\n                hidden_channels,\n                self.half_channels * 2,\n                1, )\n\n        weight = paddle.zeros(paddle.shape(self.proj.weight))\n\n        self.proj.weight = paddle.create_parameter(\n            shape=weight.shape,\n            dtype=str(weight.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(weight))\n\n        bias = paddle.zeros(paddle.shape(self.proj.bias))\n\n        self.proj.bias = paddle.create_parameter(\n            shape=bias.shape,\n            dtype=str(bias.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(bias))\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: paddle.Tensor,\n            g: Optional[paddle.Tensor]=None,\n            inverse: bool=False,\n    ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, paddle.Tensor]]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor):\n                Input tensor (B, in_channels, T).\n            x_lengths (Tensor):\n                Length tensor (B,).\n            g (Optional[Tensor]):\n                Global conditioning tensor (B, global_channels, 1).\n            inverse (bool):\n                Whether to inverse the flow.\n\n        Returns:\n            Tensor:\n                Output tensor (B, in_channels, T).\n            Tensor:\n                Log-determinant tensor for NLL (B,) if not inverse.\n\n        \"\"\"\n        xa, xb = paddle.split(x, 2, axis=1)\n        h = self.input_conv(xa) * x_mask\n        h = self.encoder(h, x_mask, g=g)\n        stats = self.proj(h) * x_mask\n        if not self.use_only_mean:\n            m, logs = paddle.split(stats, 2, axis=1)\n        else:\n            m = stats\n            logs = paddle.zeros(paddle.shape(m))\n\n        if not inverse:\n            xb = m + xb * paddle.exp(logs) * x_mask\n            x = paddle.concat([xa, xb], 1)\n            logdet = paddle.sum(logs, [1, 2])\n            return x, logdet\n        else:\n            xb = (xb - m) * paddle.exp(-logs) * x_mask\n            x = paddle.concat([xa, xb], 1)\n            return x\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/text_encoder.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Text encoder module in VITS.\n\nThis code is based on https://github.com/jaywalnut310/vits.\n\n\"\"\"\nimport math\nfrom typing import Tuple\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.transformer.encoder import ConformerEncoder as Encoder\nfrom paddlespeech.utils.initialize import normal_\n\n\nclass TextEncoder(nn.Layer):\n    \"\"\"Text encoder module in VITS.\n\n    This is a module of text encoder described in `Conditional Variational Autoencoder\n    with Adversarial Learning for End-to-End Text-to-Speech`_.\n\n    Instead of the relative positional Transformer, we use conformer architecture as\n    the encoder module, which contains additional convolution layers.\n\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2006.04558\n\n    \"\"\"\n\n    def __init__(\n            self,\n            vocabs: int,\n            attention_dim: int=192,\n            attention_heads: int=2,\n            linear_units: int=768,\n            blocks: int=6,\n            positionwise_layer_type: str=\"conv1d\",\n            positionwise_conv_kernel_size: int=3,\n            positional_encoding_layer_type: str=\"rel_pos\",\n            self_attention_layer_type: str=\"rel_selfattn\",\n            activation_type: str=\"swish\",\n            normalize_before: bool=True,\n            use_macaron_style: bool=False,\n            use_conformer_conv: bool=False,\n            conformer_kernel_size: int=7,\n            dropout_rate: float=0.1,\n            positional_dropout_rate: float=0.0,\n            attention_dropout_rate: float=0.0, ):\n        \"\"\"Initialize TextEncoder module.\n\n        Args:\n            vocabs (int):\n                Vocabulary size.\n            attention_dim (int):\n                Attention dimension.\n            attention_heads (int):\n                Number of attention heads.\n            linear_units (int):\n                Number of linear units of positionwise layers.\n            blocks (int):\n                Number of encoder blocks.\n            positionwise_layer_type (str):\n                Positionwise layer type.\n            positionwise_conv_kernel_size (int):\n                Positionwise layer's kernel size.\n            positional_encoding_layer_type (str):\n                Positional encoding layer type.\n            self_attention_layer_type (str):\n                Self-attention layer type.\n            activation_type (str):\n                Activation function type.\n            normalize_before (bool):\n                Whether to apply LayerNorm before attention.\n            use_macaron_style (bool):\n                Whether to use macaron style components.\n            use_conformer_conv (bool):\n                Whether to use conformer conv layers.\n            conformer_kernel_size (int):\n                Conformer's conv kernel size.\n            dropout_rate (float):\n                Dropout rate.\n            positional_dropout_rate (float):\n                Dropout rate for positional encoding.\n            attention_dropout_rate (float):\n                Dropout rate for attention.\n\n        \"\"\"\n        super().__init__()\n        # store for forward\n        self.attention_dim = attention_dim\n\n        # define modules\n        self.emb = nn.Embedding(vocabs, attention_dim)\n\n        self.encoder = Encoder(\n            idim=-1,\n            input_layer=None,\n            attention_dim=attention_dim,\n            attention_heads=attention_heads,\n            linear_units=linear_units,\n            num_blocks=blocks,\n            dropout_rate=dropout_rate,\n            positional_dropout_rate=positional_dropout_rate,\n            attention_dropout_rate=attention_dropout_rate,\n            normalize_before=normalize_before,\n            positionwise_layer_type=positionwise_layer_type,\n            positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n            macaron_style=use_macaron_style,\n            pos_enc_layer_type=positional_encoding_layer_type,\n            selfattention_layer_type=self_attention_layer_type,\n            activation_type=activation_type,\n            use_cnn_module=use_conformer_conv,\n            cnn_module_kernel=conformer_kernel_size, )\n        self.proj = nn.Conv1D(attention_dim, attention_dim * 2, 1)\n\n        self.reset_parameters()\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_lengths: paddle.Tensor,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor):\n                Input index tensor (B, T_text).\n            x_lengths (Tensor):\n                Length tensor (B,).\n\n        Returns:\n            Tensor:\n                Encoded hidden representation (B, attention_dim, T_text).\n            Tensor:\n                Projected mean tensor (B, attention_dim, T_text).\n            Tensor:\n                Projected scale tensor (B, attention_dim, T_text).\n            Tensor:\n                Mask tensor for input tensor (B, 1, T_text).\n\n        \"\"\"\n        x = self.emb(x) * math.sqrt(self.attention_dim)\n        x_mask = make_non_pad_mask(x_lengths).unsqueeze(1)\n        x_mask = x_mask.astype(x.dtype)\n        # encoder assume the channel last (B, T_text, attention_dim)\n        # but mask shape shoud be (B, 1, T_text)\n        x, _ = self.encoder(x, x_mask)\n\n        # convert the channel first (B, attention_dim, T_text)\n        x = paddle.transpose(x, [0, 2, 1])\n        stats = self.proj(x) * x_mask\n        m, logs = paddle.split(stats, 2, axis=1)\n\n        return x, m, logs, x_mask\n\n    def reset_parameters(self):\n        normal_(self.emb.weight, mean=0.0, std=self.attention_dim**-0.5)\n        if self.emb._padding_idx is not None:\n            with paddle.no_grad():\n                self.emb.weight[self.emb._padding_idx] = 0\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/transform.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Flow-related transformation.\n\nThis code is based on https://github.com/bayesiains/nflows.\n\n\"\"\"\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.t2s.modules.nets_utils import paddle_gather\n\nDEFAULT_MIN_BIN_WIDTH = 1e-3\nDEFAULT_MIN_BIN_HEIGHT = 1e-3\nDEFAULT_MIN_DERIVATIVE = 1e-3\n\n\ndef piecewise_rational_quadratic_transform(\n        inputs,\n        unnormalized_widths,\n        unnormalized_heights,\n        unnormalized_derivatives,\n        inverse=False,\n        tails=None,\n        tail_bound=1.0,\n        # for dygraph-to-static\n        min_bin_width=1e-3,\n        min_bin_height=1e-3,\n        min_derivative=1e-3, ):\n    if tails is None:\n        spline_fn = rational_quadratic_spline\n        spline_kwargs = {}\n    else:\n        spline_fn = unconstrained_rational_quadratic_spline\n        spline_kwargs = {\"tails\": tails, \"tail_bound\": tail_bound}\n\n    outputs, logabsdet = spline_fn(\n        inputs=inputs,\n        unnormalized_widths=unnormalized_widths,\n        unnormalized_heights=unnormalized_heights,\n        unnormalized_derivatives=unnormalized_derivatives,\n        inverse=inverse,\n        min_bin_width=min_bin_width,\n        min_bin_height=min_bin_height,\n        min_derivative=min_derivative,\n        **spline_kwargs)\n    return outputs, logabsdet\n\n\ndef mask_preprocess(x, mask):\n    # bins.dtype = int32\n    B, C, T, bins = paddle.shape(x)\n    mask_int = paddle.cast(mask, dtype='int64')\n    # paddle.sum 输入是 int32 或 bool 的时候，输出是 int64\n    # paddle.zeros (fill_constant) 的 shape 会被强制转成 int32 类型\n    new_x = paddle.zeros([paddle.sum(mask_int), bins])\n    for i in range(bins):\n        new_x[:, i] = x[:, :, :, i][mask]\n    return new_x\n\n\ndef unconstrained_rational_quadratic_spline(\n        inputs,\n        unnormalized_widths,\n        unnormalized_heights,\n        unnormalized_derivatives,\n        inverse=False,\n        tails=\"linear\",\n        tail_bound=1.0,\n        # for dygraph-to-static\n        min_bin_width=1e-3,\n        min_bin_height=1e-3,\n        min_derivative=1e-3, ):\n    inside_interval_mask = (inputs >= -tail_bound) & (inputs <= tail_bound)\n    outside_interval_mask = ~inside_interval_mask\n    # for dygraph to static\n    # 这里用 paddle.shape(x) 然后调用 zeros 会得到一个全 -1 shape 的 var\n    # 如果用 x.shape 的话可以保留确定的维度\n    outputs = paddle.zeros(inputs.shape)\n    logabsdet = paddle.zeros(inputs.shape)\n    if tails == \"linear\":\n        # 注意 padding 的参数顺序\n        pad2d = nn.Pad2D(padding=[1, 1, 0, 0], mode='constant')\n        unnormalized_derivatives = pad2d(unnormalized_derivatives)\n        constant = np.log(np.exp(1 - min_derivative) - 1)\n        unnormalized_derivatives[..., 0] = constant\n        unnormalized_derivatives[..., -1] = constant\n        # for dygraph to static\n        tmp = inputs[outside_interval_mask]\n        outputs[outside_interval_mask] = tmp\n        logabsdet[outside_interval_mask] = 0\n    else:\n        raise RuntimeError(\"{} tails are not implemented.\".format(tails))\n\n    unnormalized_widths = mask_preprocess(unnormalized_widths,\n                                          inside_interval_mask)\n    unnormalized_heights = mask_preprocess(unnormalized_heights,\n                                           inside_interval_mask)\n    unnormalized_derivatives = mask_preprocess(unnormalized_derivatives,\n                                               inside_interval_mask)\n\n    (outputs[inside_interval_mask],\n     logabsdet[inside_interval_mask], ) = rational_quadratic_spline(\n         inputs=inputs[inside_interval_mask],\n         unnormalized_widths=unnormalized_widths,\n         unnormalized_heights=unnormalized_heights,\n         unnormalized_derivatives=unnormalized_derivatives,\n         inverse=inverse,\n         left=-tail_bound,\n         right=tail_bound,\n         bottom=-tail_bound,\n         top=tail_bound,\n         min_bin_width=min_bin_width,\n         min_bin_height=min_bin_height,\n         min_derivative=min_derivative, )\n\n    return outputs, logabsdet\n\n\ndef rational_quadratic_spline(\n        inputs,\n        unnormalized_widths,\n        unnormalized_heights,\n        unnormalized_derivatives,\n        inverse=False,\n        left=0.0,\n        right=1.0,\n        bottom=0.0,\n        top=1.0,\n        # for dygraph-to-static\n        min_bin_width=1e-3,\n        min_bin_height=1e-3,\n        min_derivative=1e-3, ):\n    # for dygraph to static\n    # if paddle.min(inputs) < left or paddle.max(inputs) > right:\n    #     raise ValueError(\"Input to a transform is not within its domain\")\n    pad1d = nn.Pad1D(\n        padding=[1, 0],\n        mode='constant',\n        data_format='NCL', )\n\n    num_bins = unnormalized_widths.shape[-1]\n    # for dygraph to static\n    # if min_bin_width * num_bins > 1.0:\n    #     raise ValueError(\"Minimal bin width too large for the number of bins\")\n    # if min_bin_height * num_bins > 1.0:\n    #     raise ValueError(\"Minimal bin height too large for the number of bins\")\n\n    widths = F.softmax(unnormalized_widths, axis=-1)\n    widths = min_bin_width + (1 - min_bin_width * num_bins) * widths\n    cumwidths = paddle.cumsum(widths, axis=-1)\n\n    cumwidths = pad1d(cumwidths.unsqueeze(0)).squeeze()\n    cumwidths = (right - left) * cumwidths + left\n    cumwidths[..., 0] = left\n    cumwidths[..., -1] = right\n    widths = cumwidths[..., 1:] - cumwidths[..., :-1]\n\n    derivatives = min_derivative + F.softplus(unnormalized_derivatives)\n\n    heights = F.softmax(unnormalized_heights, axis=-1)\n    heights = min_bin_height + (1 - min_bin_height * num_bins) * heights\n    cumheights = paddle.cumsum(heights, axis=-1)\n    cumheights = pad1d(cumheights.unsqueeze(0)).squeeze()\n    cumheights = (top - bottom) * cumheights + bottom\n    cumheights[..., 0] = bottom\n    cumheights[..., -1] = top\n    heights = cumheights[..., 1:] - cumheights[..., :-1]\n\n    if inverse:\n        bin_idx = _searchsorted(cumheights, inputs)[..., None]\n    else:\n        bin_idx = _searchsorted(cumwidths, inputs)[..., None]\n    input_cumwidths = paddle_gather(cumwidths, -1, bin_idx)[..., 0]\n    input_bin_widths = paddle_gather(widths, -1, bin_idx)[..., 0]\n\n    input_cumheights = paddle_gather(cumheights, -1, bin_idx)[..., 0]\n    delta = heights / widths\n    input_delta = paddle_gather(delta, -1, bin_idx)[..., 0]\n\n    input_derivatives = paddle_gather(derivatives, -1, bin_idx)[..., 0]\n    input_derivatives_plus_one = paddle_gather(derivatives[..., 1:], -1,\n                                               bin_idx)[..., 0]\n\n    input_heights = paddle_gather(heights, -1, bin_idx)[..., 0]\n\n    if inverse:\n        a = (inputs - input_cumheights) * (\n            input_derivatives + input_derivatives_plus_one - 2 * input_delta\n        ) + input_heights * (input_delta - input_derivatives)\n        b = input_heights * input_derivatives - (inputs - input_cumheights) * (\n            input_derivatives + input_derivatives_plus_one - 2 * input_delta)\n        c = -input_delta * (inputs - input_cumheights)\n\n        discriminant = b.pow(2) - 4 * a * c\n        assert (discriminant >= 0).all()\n\n        root = (2 * c) / (-b - paddle.sqrt(discriminant))\n        outputs = root * input_bin_widths + input_cumwidths\n\n        theta_one_minus_theta = root * (1 - root)\n        denominator = input_delta + (\n            (input_derivatives + input_derivatives_plus_one - 2 * input_delta\n             ) * theta_one_minus_theta)\n        derivative_numerator = input_delta.pow(2) * (\n            input_derivatives_plus_one * root.pow(2) + 2 * input_delta *\n            theta_one_minus_theta + input_derivatives * (1 - root).pow(2))\n        logabsdet = paddle.log(derivative_numerator) - 2 * paddle.log(\n            denominator)\n\n        return outputs, -logabsdet\n    else:\n        theta = (inputs - input_cumwidths) / input_bin_widths\n        theta_one_minus_theta = theta * (1 - theta)\n\n        numerator = input_heights * (input_delta * theta.pow(2) +\n                                     input_derivatives * theta_one_minus_theta)\n        denominator = input_delta + (\n            (input_derivatives + input_derivatives_plus_one - 2 * input_delta\n             ) * theta_one_minus_theta)\n        outputs = input_cumheights + numerator / denominator\n\n        derivative_numerator = input_delta.pow(2) * (\n            input_derivatives_plus_one * theta.pow(2) + 2 * input_delta *\n            theta_one_minus_theta + input_derivatives * (1 - theta).pow(2))\n        logabsdet = paddle.log(derivative_numerator) - 2 * paddle.log(\n            denominator)\n\n        return outputs, logabsdet\n\n\ndef _searchsorted(bin_locations, inputs, eps=1e-6):\n    bin_locations[..., -1] += eps\n    mask = inputs[..., None] >= bin_locations\n    mask_int = paddle.cast(mask, dtype='int64')\n    out = paddle.sum(mask_int, axis=-1) - 1\n    return out\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/vits.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"VITS module\"\"\"\nimport math\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Optional\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiScaleDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANMultiScaleMultiPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANPeriodDiscriminator\nfrom paddlespeech.t2s.models.hifigan import HiFiGANScaleDiscriminator\nfrom paddlespeech.t2s.models.vits.generator import VITSGenerator\nfrom paddlespeech.utils.initialize import _calculate_fan_in_and_fan_out\nfrom paddlespeech.utils.initialize import kaiming_uniform_\nfrom paddlespeech.utils.initialize import normal_\nfrom paddlespeech.utils.initialize import ones_\nfrom paddlespeech.utils.initialize import uniform_\nfrom paddlespeech.utils.initialize import zeros_\n\nAVAILABLE_GENERATERS = {\n    \"vits_generator\": VITSGenerator,\n}\nAVAILABLE_DISCRIMINATORS = {\n    \"hifigan_period_discriminator\":\n    HiFiGANPeriodDiscriminator,\n    \"hifigan_scale_discriminator\":\n    HiFiGANScaleDiscriminator,\n    \"hifigan_multi_period_discriminator\":\n    HiFiGANMultiPeriodDiscriminator,\n    \"hifigan_multi_scale_discriminator\":\n    HiFiGANMultiScaleDiscriminator,\n    \"hifigan_multi_scale_multi_period_discriminator\":\n    HiFiGANMultiScaleMultiPeriodDiscriminator,\n}\n\n\nclass VITS(nn.Layer):\n    \"\"\"VITS module (generator + discriminator).\n    This is a module of VITS described in `Conditional Variational Autoencoder\n    with Adversarial Learning for End-to-End Text-to-Speech`_.\n    .. _`Conditional Variational Autoencoder with Adversarial Learning for End-to-End\n        Text-to-Speech`: https://arxiv.org/abs/2006.04558\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            # generator related\n            idim: int,\n            odim: int,\n            sampling_rate: int=22050,\n            generator_type: str=\"vits_generator\",\n            generator_params: Dict[str, Any]={\n                \"hidden_channels\": 192,\n                \"spks\": None,\n                \"langs\": None,\n                \"spk_embed_dim\": None,\n                \"global_channels\": -1,\n                \"segment_size\": 32,\n                \"text_encoder_attention_heads\": 2,\n                \"text_encoder_ffn_expand\": 4,\n                \"text_encoder_blocks\": 6,\n                \"text_encoder_positionwise_layer_type\": \"conv1d\",\n                \"text_encoder_positionwise_conv_kernel_size\": 1,\n                \"text_encoder_positional_encoding_layer_type\": \"rel_pos\",\n                \"text_encoder_self_attention_layer_type\": \"rel_selfattn\",\n                \"text_encoder_activation_type\": \"swish\",\n                \"text_encoder_normalize_before\": True,\n                \"text_encoder_dropout_rate\": 0.1,\n                \"text_encoder_positional_dropout_rate\": 0.0,\n                \"text_encoder_attention_dropout_rate\": 0.0,\n                \"text_encoder_conformer_kernel_size\": 7,\n                \"use_macaron_style_in_text_encoder\": True,\n                \"use_conformer_conv_in_text_encoder\": True,\n                \"decoder_kernel_size\": 7,\n                \"decoder_channels\": 512,\n                \"decoder_upsample_scales\": [8, 8, 2, 2],\n                \"decoder_upsample_kernel_sizes\": [16, 16, 4, 4],\n                \"decoder_resblock_kernel_sizes\": [3, 7, 11],\n                \"decoder_resblock_dilations\": [[1, 3, 5], [1, 3, 5], [1, 3, 5]],\n                \"use_weight_norm_in_decoder\": True,\n                \"posterior_encoder_kernel_size\": 5,\n                \"posterior_encoder_layers\": 16,\n                \"posterior_encoder_stacks\": 1,\n                \"posterior_encoder_base_dilation\": 1,\n                \"posterior_encoder_dropout_rate\": 0.0,\n                \"use_weight_norm_in_posterior_encoder\": True,\n                \"flow_flows\": 4,\n                \"flow_kernel_size\": 5,\n                \"flow_base_dilation\": 1,\n                \"flow_layers\": 4,\n                \"flow_dropout_rate\": 0.0,\n                \"use_weight_norm_in_flow\": True,\n                \"use_only_mean_in_flow\": True,\n                \"stochastic_duration_predictor_kernel_size\": 3,\n                \"stochastic_duration_predictor_dropout_rate\": 0.5,\n                \"stochastic_duration_predictor_flows\": 4,\n                \"stochastic_duration_predictor_dds_conv_layers\": 3,\n            },\n            # discriminator related\n            discriminator_type: str=\"hifigan_multi_scale_multi_period_discriminator\",\n            discriminator_params: Dict[str, Any]={\n                \"scales\": 1,\n                \"scale_downsample_pooling\": \"AvgPool1D\",\n                \"scale_downsample_pooling_params\": {\n                    \"kernel_size\": 4,\n                    \"stride\": 2,\n                    \"padding\": 2,\n                },\n                \"scale_discriminator_params\": {\n                    \"in_channels\": 1,\n                    \"out_channels\": 1,\n                    \"kernel_sizes\": [15, 41, 5, 3],\n                    \"channels\": 128,\n                    \"max_downsample_channels\": 1024,\n                    \"max_groups\": 16,\n                    \"bias\": True,\n                    \"downsample_scales\": [2, 2, 4, 4, 1],\n                    \"nonlinear_activation\": \"leakyrelu\",\n                    \"nonlinear_activation_params\": {\n                        \"negative_slope\": 0.1\n                    },\n                    \"use_weight_norm\": True,\n                    \"use_spectral_norm\": False,\n                },\n                \"follow_official_norm\": False,\n                \"periods\": [2, 3, 5, 7, 11],\n                \"period_discriminator_params\": {\n                    \"in_channels\": 1,\n                    \"out_channels\": 1,\n                    \"kernel_sizes\": [5, 3],\n                    \"channels\": 32,\n                    \"downsample_scales\": [3, 3, 3, 3, 1],\n                    \"max_downsample_channels\": 1024,\n                    \"bias\": True,\n                    \"nonlinear_activation\": \"leakyrelu\",\n                    \"nonlinear_activation_params\": {\n                        \"negative_slope\": 0.1\n                    },\n                    \"use_weight_norm\": True,\n                    \"use_spectral_norm\": False,\n                },\n            },\n            cache_generator_outputs: bool=True, ):\n        \"\"\"Initialize VITS module.\n        Args:\n            idim (int):\n                Input vocabrary size.\n            odim (int):\n                Acoustic feature dimension. The actual output channels will\n                be 1 since VITS is the end-to-end text-to-wave model but for the\n                compatibility odim is used to indicate the acoustic feature dimension.\n            sampling_rate (int):\n                Sampling rate, not used for the training but it will\n                be referred in saving waveform during the inference.\n            generator_type (str):\n                Generator type.\n            generator_params (Dict[str, Any]):\n                Parameter dict for generator.\n            discriminator_type (str):\n                Discriminator type.\n            discriminator_params (Dict[str, Any]):\n                Parameter dict for discriminator.\n            cache_generator_outputs (bool):\n                Whether to cache generator outputs.\n        \"\"\"\n        super().__init__()\n\n        # define modules\n        generator_class = AVAILABLE_GENERATERS[generator_type]\n        if generator_type == \"vits_generator\":\n            # NOTE: Update parameters for the compatibility.\n            #   The idim and odim is automatically decided from input data,\n            #   where idim represents #vocabularies and odim represents\n            #   the input acoustic feature dimension.\n            generator_params.update(vocabs=idim, aux_channels=odim)\n        self.generator = generator_class(\n            **generator_params, )\n        discriminator_class = AVAILABLE_DISCRIMINATORS[discriminator_type]\n        self.discriminator = discriminator_class(\n            **discriminator_params, )\n\n        # cache\n        self.cache_generator_outputs = cache_generator_outputs\n        self._cache = None\n\n        # store sampling rate for saving wav file\n        # (not used for the training)\n        self.fs = sampling_rate\n\n        # store parameters for test compatibility\n        self.spks = self.generator.spks\n        self.langs = self.generator.langs\n        self.spk_embed_dim = self.generator.spk_embed_dim\n\n        self.reuse_cache_gen = True\n        self.reuse_cache_dis = True\n\n        self.reset_parameters()\n        self.generator.decoder.reset_parameters()\n        self.generator.text_encoder.reset_parameters()\n\n    def forward(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            forward_generator: bool=True, ) -> Dict[str, Any]:\n        \"\"\"Perform generator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n            forward_generator (bool):\n                    Whether to forward generator.\n        Returns:\n\n        \"\"\"\n        if forward_generator:\n            return self._forward_generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids, )\n        else:\n            return self._forward_discrminator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids, )\n\n    def _forward_generator(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None, ) -> Dict[str, Any]:\n        \"\"\"Perform generator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n        Returns:\n\n        \"\"\"\n        # setup\n        feats = feats.transpose([0, 2, 1])\n\n        # calculate generator outputs\n        self.reuse_cache_gen = True\n        if not self.cache_generator_outputs or self._cache is None:\n            self.reuse_cache_gen = False\n            outs = self.generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids, )\n        else:\n            outs = self._cache\n\n        # store cache\n        if self.training and self.cache_generator_outputs and not self.reuse_cache_gen:\n            self._cache = outs\n\n        return outs\n\n    def _forward_discrminator(\n            self,\n            text: paddle.Tensor,\n            text_lengths: paddle.Tensor,\n            feats: paddle.Tensor,\n            feats_lengths: paddle.Tensor,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None, ) -> Dict[str, Any]:\n        \"\"\"Perform discriminator forward.\n        Args:\n            text (Tensor):\n                Text index tensor (B, T_text).\n            text_lengths (Tensor):\n                Text length tensor (B,).\n            feats (Tensor):\n                Feature tensor (B, T_feats, aux_channels).\n            feats_lengths (Tensor):\n                Feature length tensor (B,).\n            sids (Optional[Tensor]):\n                Speaker index tensor (B,) or (B, 1).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (B, spk_embed_dim).\n            lids (Optional[Tensor]):\n                Language index tensor (B,) or (B, 1).\n        Returns:\n\n        \"\"\"\n        # setup\n        feats = feats.transpose([0, 2, 1])\n\n        # calculate generator outputs\n        self.reuse_cache_dis = True\n        if not self.cache_generator_outputs or self._cache is None:\n            self.reuse_cache_dis = False\n            outs = self.generator(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids, )\n        else:\n            outs = self._cache\n\n        # store cache\n        if self.cache_generator_outputs and not self.reuse_cache_dis:\n            self._cache = outs\n\n        return outs\n\n    def inference(\n            self,\n            text: paddle.Tensor,\n            feats: Optional[paddle.Tensor]=None,\n            sids: Optional[paddle.Tensor]=None,\n            spembs: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None,\n            durations: Optional[paddle.Tensor]=None,\n            noise_scale: float=0.667,\n            noise_scale_dur: float=0.8,\n            alpha: float=1.0,\n            max_len: Optional[int]=None,\n            use_teacher_forcing: bool=False, ) -> Dict[str, paddle.Tensor]:\n        \"\"\"Run inference.\n        Args:\n            text (Tensor):\n                Input text index tensor (T_text,).\n            feats (Tensor):\n                Feature tensor (T_feats, aux_channels).\n            sids (Tensor):\n                Speaker index tensor (1,).\n            spembs (Optional[Tensor]):\n                Speaker embedding tensor (spk_embed_dim,).\n            lids (Tensor):\n                Language index tensor (1,).\n            durations (Tensor):\n                Ground-truth duration tensor (T_text,).\n            noise_scale (float):\n                Noise scale value for flow.\n            noise_scale_dur (float):\n                Noise scale value for duration predictor.\n            alpha (float):\n                Alpha parameter to control the speed of generated speech.\n            max_len (Optional[int]):\n                Maximum length.\n            use_teacher_forcing (bool):\n                Whether to use teacher forcing.\n        Returns:\n            Dict[str, Tensor]:\n                * wav (Tensor):\n                    Generated waveform tensor (T_wav,).\n                * att_w (Tensor):\n                    Monotonic attention weight tensor (T_feats, T_text).\n                * duration (Tensor):\n                    Predicted duration tensor (T_text,).\n        \"\"\"\n        # setup\n        text = text[None]\n        text_lengths = paddle.to_tensor(paddle.shape(text)[1])\n\n        if durations is not None:\n            durations = paddle.reshape(durations, [1, 1, -1])\n\n        # inference\n        if use_teacher_forcing:\n            assert feats is not None\n            feats = feats[None].transpose([0, 2, 1])\n            feats_lengths = paddle.to_tensor(paddle.shape(feats)[2])\n            wav, att_w, dur = self.generator.inference(\n                text=text,\n                text_lengths=text_lengths,\n                feats=feats,\n                feats_lengths=feats_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                max_len=max_len,\n                use_teacher_forcing=use_teacher_forcing, )\n        else:\n            wav, att_w, dur = self.generator.inference(\n                text=text,\n                text_lengths=text_lengths,\n                sids=sids,\n                spembs=spembs,\n                lids=lids,\n                dur=durations,\n                noise_scale=noise_scale,\n                noise_scale_dur=noise_scale_dur,\n                alpha=alpha,\n                max_len=max_len, )\n        return dict(\n            wav=paddle.reshape(wav, [-1]), att_w=att_w[0], duration=dur[0])\n\n    def voice_conversion(\n            self,\n            feats: paddle.Tensor,\n            sids_src: Optional[paddle.Tensor]=None,\n            sids_tgt: Optional[paddle.Tensor]=None,\n            spembs_src: Optional[paddle.Tensor]=None,\n            spembs_tgt: Optional[paddle.Tensor]=None,\n            lids: Optional[paddle.Tensor]=None, ) -> paddle.Tensor:\n        \"\"\"Run voice conversion.\n        Args:\n            feats (Tensor):\n                Feature tensor (T_feats, aux_channels).\n            sids_src (Optional[Tensor]):\n                Speaker index tensor of source feature (1,).\n            sids_tgt (Optional[Tensor]):\n                Speaker index tensor of target feature (1,).\n            spembs_src (Optional[Tensor]):\n                Speaker embedding tensor of source feature (spk_embed_dim,).\n            spembs_tgt (Optional[Tensor]):\n                Speaker embedding tensor of target feature (spk_embed_dim,).\n            lids (Optional[Tensor]):\n                Language index tensor (1,).\n        Returns:\n            Dict[str, Tensor]:\n                * wav (Tensor):\n                    Generated waveform tensor (T_wav,).\n        \"\"\"\n        assert feats is not None\n        feats = feats[None].transpose([0, 2, 1])\n        feats_lengths = paddle.to_tensor(paddle.shape(feats)[2])\n\n        sids_none = sids_src is None and sids_tgt is None\n        spembs_none = spembs_src is None and spembs_tgt is None\n\n        assert not sids_none or not spembs_none\n\n        wav = self.generator.voice_conversion(\n            feats,\n            feats_lengths,\n            sids_src,\n            sids_tgt,\n            spembs_src,\n            spembs_tgt,\n            lids, )\n\n        return dict(wav=paddle.reshape(wav, [-1]))\n\n    def reset_parameters(self):\n        def _reset_parameters(module):\n            if isinstance(\n                    module,\n                (nn.Conv1D, nn.Conv1DTranspose, nn.Conv2D, nn.Conv2DTranspose)):\n                kaiming_uniform_(module.weight, a=math.sqrt(5))\n                if module.bias is not None:\n                    fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n                    if fan_in != 0:\n                        bound = 1 / math.sqrt(fan_in)\n                        uniform_(module.bias, -bound, bound)\n\n            if isinstance(\n                    module,\n                (nn.BatchNorm1D, nn.BatchNorm2D, nn.GroupNorm, nn.LayerNorm)):\n                ones_(module.weight)\n                zeros_(module.bias)\n\n            if isinstance(module, nn.Linear):\n                kaiming_uniform_(module.weight, a=math.sqrt(5))\n                if module.bias is not None:\n                    fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n                    bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0\n                    uniform_(module.bias, -bound, bound)\n\n            if isinstance(module, nn.Embedding):\n                normal_(module.weight)\n                if module._padding_idx is not None:\n                    with paddle.no_grad():\n                        module.weight[module._padding_idx] = 0\n\n        self.apply(_reset_parameters)\n\n\nclass VITSInference(nn.Layer):\n    def __init__(self, model):\n        super().__init__()\n        self.acoustic_model = model\n\n    def forward(self, text, sids=None):\n        out = self.acoustic_model.inference(text, sids=sids)\n        wav = out['wav']\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/vits_updater.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom typing import Dict\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\n\nfrom paddlespeech.t2s.modules.nets_utils import get_segments\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nfrom paddlespeech.t2s.training.updaters.standard_updater import UpdaterState\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass VITSUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizers: Dict[str, Optimizer],\n                 criterions: Dict[str, Layer],\n                 schedulers: Dict[str, LRScheduler],\n                 dataloader: DataLoader,\n                 generator_train_start_steps: int=0,\n                 discriminator_train_start_steps: int=100000,\n                 lambda_adv: float=1.0,\n                 lambda_mel: float=45.0,\n                 lambda_feat_match: float=2.0,\n                 lambda_dur: float=1.0,\n                 lambda_kl: float=1.0,\n                 generator_first: bool=False,\n                 output_dir=None):\n        # it is designed to hold multiple models\n        # 因为输入的是单模型，但是没有用到父类的 init(), 所以需要重新写这部分\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        # self.model = model\n\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n\n        self.optimizers = optimizers\n        self.optimizer_g: Optimizer = optimizers['generator']\n        self.optimizer_d: Optimizer = optimizers['discriminator']\n\n        self.criterions = criterions\n        self.criterion_mel = criterions['mel']\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n        self.criterion_kl = criterions[\"kl\"]\n\n        self.schedulers = schedulers\n        self.scheduler_g = schedulers['generator']\n        self.scheduler_d = schedulers['discriminator']\n\n        self.dataloader = dataloader\n\n        self.generator_train_start_steps = generator_train_start_steps\n        self.discriminator_train_start_steps = discriminator_train_start_steps\n\n        self.lambda_adv = lambda_adv\n        self.lambda_mel = lambda_mel\n        self.lambda_feat_match = lambda_feat_match\n        self.lambda_dur = lambda_dur\n        self.lambda_kl = lambda_kl\n\n        if generator_first:\n            self.turns = [\"generator\", \"discriminator\"]\n        else:\n            self.turns = [\"discriminator\", \"generator\"]\n\n        self.state = UpdaterState(iteration=0, epoch=0)\n        self.train_iterator = iter(self.dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        for turn in self.turns:\n            speech = batch[\"speech\"]\n            speech = speech.unsqueeze(1)\n            outs = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                feats=batch[\"feats\"],\n                feats_lengths=batch[\"feats_lengths\"],\n                sids=batch.get(\"spk_id\", None),\n                spembs=batch.get(\"spk_emb\", None),\n                forward_generator=turn == \"generator\")\n            # Generator\n            if turn == \"generator\":\n                # parse outputs\n                speech_hat_, dur_nll, _, start_idxs, _, z_mask, outs_ = outs\n                _, z_p, m_p, logs_p, _, logs_q = outs_\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_)\n                with paddle.no_grad():\n                    # do not store discriminator gradient in generator turn\n                    p = self.model.discriminator(speech_)\n\n                # calculate losses\n                mel_loss = self.criterion_mel(speech_hat_, speech_)\n                kl_loss = self.criterion_kl(z_p, logs_q, m_p, logs_p, z_mask)\n                dur_loss = paddle.sum(dur_nll)\n                adv_loss = self.criterion_gen_adv(p_hat)\n                feat_match_loss = self.criterion_feat_match(p_hat, p)\n\n                mel_loss = mel_loss * self.lambda_mel\n                kl_loss = kl_loss * self.lambda_kl\n                dur_loss = dur_loss * self.lambda_dur\n                adv_loss = adv_loss * self.lambda_adv\n                feat_match_loss = feat_match_loss * self.lambda_feat_match\n                gen_loss = mel_loss + kl_loss + dur_loss + adv_loss + feat_match_loss\n\n                report(\"train/generator_loss\", float(gen_loss))\n                report(\"train/generator_mel_loss\", float(mel_loss))\n                report(\"train/generator_kl_loss\", float(kl_loss))\n                report(\"train/generator_dur_loss\", float(dur_loss))\n                report(\"train/generator_adv_loss\", float(adv_loss))\n                report(\"train/generator_feat_match_loss\",\n                       float(feat_match_loss))\n\n                losses_dict[\"generator_loss\"] = float(gen_loss)\n                losses_dict[\"generator_mel_loss\"] = float(mel_loss)\n                losses_dict[\"generator_kl_loss\"] = float(kl_loss)\n                losses_dict[\"generator_dur_loss\"] = float(dur_loss)\n                losses_dict[\"generator_adv_loss\"] = float(adv_loss)\n                losses_dict[\"generator_feat_match_loss\"] = float(\n                    feat_match_loss)\n\n                self.optimizer_g.clear_grad()\n                gen_loss.backward()\n\n                self.optimizer_g.step()\n                # learning rate updates on each epoch.\n                if self.state.iteration % self.updates_per_epoch == 0:\n                    self.scheduler_g.step()\n\n                # reset cache\n                if self.model.reuse_cache_gen or not self.model.training:\n                    self.model._cache = None\n\n            # Disctiminator\n            elif turn == \"discriminator\":\n                # parse outputs\n                speech_hat_, _, _, start_idxs, *_ = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_.detach())\n                p = self.model.discriminator(speech_)\n\n                # calculate losses\n                real_loss, fake_loss = self.criterion_dis_adv(p_hat, p)\n                dis_loss = real_loss + fake_loss\n\n                report(\"train/real_loss\", float(real_loss))\n                report(\"train/fake_loss\", float(fake_loss))\n                report(\"train/discriminator_loss\", float(dis_loss))\n                losses_dict[\"real_loss\"] = float(real_loss)\n                losses_dict[\"fake_loss\"] = float(fake_loss)\n                losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n                self.optimizer_d.clear_grad()\n                dis_loss.backward()\n\n                self.optimizer_d.step()\n                # learning rate updates on each epoch.\n                if self.state.iteration % self.updates_per_epoch == 0:\n                    self.scheduler_d.step()\n\n                # reset cache\n                if self.model.reuse_cache_dis or not self.model.training:\n                    self.model._cache = None\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass VITSEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model,\n                 criterions: Dict[str, Layer],\n                 dataloader: DataLoader,\n                 lambda_adv: float=1.0,\n                 lambda_mel: float=45.0,\n                 lambda_feat_match: float=2.0,\n                 lambda_dur: float=1.0,\n                 lambda_kl: float=1.0,\n                 generator_first: bool=False,\n                 output_dir=None):\n        # 因为输入的是单模型，但是没有用到父类的 init(), 所以需要重新写这部分\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        # self.model = model\n        self.model = model._layers if isinstance(model,\n                                                 paddle.DataParallel) else model\n\n        self.criterions = criterions\n        self.criterion_mel = criterions['mel']\n        self.criterion_feat_match = criterions['feat_match']\n        self.criterion_gen_adv = criterions[\"gen_adv\"]\n        self.criterion_dis_adv = criterions[\"dis_adv\"]\n        self.criterion_kl = criterions[\"kl\"]\n\n        self.dataloader = dataloader\n\n        self.lambda_adv = lambda_adv\n        self.lambda_mel = lambda_mel\n        self.lambda_feat_match = lambda_feat_match\n        self.lambda_dur = lambda_dur\n        self.lambda_kl = lambda_kl\n\n        if generator_first:\n            self.turns = [\"generator\", \"discriminator\"]\n        else:\n            self.turns = [\"discriminator\", \"generator\"]\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        # logging.debug(\"Evaluate: \")\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        for turn in self.turns:\n            speech = batch[\"speech\"]\n            speech = speech.unsqueeze(1)\n            outs = self.model(\n                text=batch[\"text\"],\n                text_lengths=batch[\"text_lengths\"],\n                feats=batch[\"feats\"],\n                feats_lengths=batch[\"feats_lengths\"],\n                sids=batch.get(\"spk_id\", None),\n                spembs=batch.get(\"spk_emb\", None),\n                forward_generator=turn == \"generator\")\n            # Generator\n            if turn == \"generator\":\n                # parse outputs\n                speech_hat_, dur_nll, _, start_idxs, _, z_mask, outs_ = outs\n                _, z_p, m_p, logs_p, _, logs_q = outs_\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_)\n                with paddle.no_grad():\n                    # do not store discriminator gradient in generator turn\n                    p = self.model.discriminator(speech_)\n\n                # calculate losses\n                mel_loss = self.criterion_mel(speech_hat_, speech_)\n                kl_loss = self.criterion_kl(z_p, logs_q, m_p, logs_p, z_mask)\n                dur_loss = paddle.sum(dur_nll)\n                adv_loss = self.criterion_gen_adv(p_hat)\n                feat_match_loss = self.criterion_feat_match(p_hat, p)\n\n                mel_loss = mel_loss * self.lambda_mel\n                kl_loss = kl_loss * self.lambda_kl\n                dur_loss = dur_loss * self.lambda_dur\n                adv_loss = adv_loss * self.lambda_adv\n                feat_match_loss = feat_match_loss * self.lambda_feat_match\n                gen_loss = mel_loss + kl_loss + dur_loss + adv_loss + feat_match_loss\n\n                report(\"eval/generator_loss\", float(gen_loss))\n                report(\"eval/generator_mel_loss\", float(mel_loss))\n                report(\"eval/generator_kl_loss\", float(kl_loss))\n                report(\"eval/generator_dur_loss\", float(dur_loss))\n                report(\"eval/generator_adv_loss\", float(adv_loss))\n                report(\"eval/generator_feat_match_loss\", float(feat_match_loss))\n\n                losses_dict[\"generator_loss\"] = float(gen_loss)\n                losses_dict[\"generator_mel_loss\"] = float(mel_loss)\n                losses_dict[\"generator_kl_loss\"] = float(kl_loss)\n                losses_dict[\"generator_dur_loss\"] = float(dur_loss)\n                losses_dict[\"generator_adv_loss\"] = float(adv_loss)\n                losses_dict[\"generator_feat_match_loss\"] = float(\n                    feat_match_loss)\n\n                # reset cache\n                if self.model.reuse_cache_gen or not self.model.training:\n                    self.model._cache = None\n\n            # Disctiminator\n            elif turn == \"discriminator\":\n                # parse outputs\n                speech_hat_, _, _, start_idxs, *_ = outs\n                speech_ = get_segments(\n                    x=speech,\n                    start_idxs=start_idxs *\n                    self.model.generator.upsample_factor,\n                    segment_size=self.model.generator.segment_size *\n                    self.model.generator.upsample_factor, )\n\n                # calculate discriminator outputs\n                p_hat = self.model.discriminator(speech_hat_.detach())\n                p = self.model.discriminator(speech_)\n\n                # calculate losses\n                real_loss, fake_loss = self.criterion_dis_adv(p_hat, p)\n                dis_loss = real_loss + fake_loss\n\n                report(\"eval/real_loss\", float(real_loss))\n                report(\"eval/fake_loss\", float(fake_loss))\n                report(\"eval/discriminator_loss\", float(dis_loss))\n                losses_dict[\"real_loss\"] = float(real_loss)\n                losses_dict[\"fake_loss\"] = float(fake_loss)\n                losses_dict[\"discriminator_loss\"] = float(dis_loss)\n\n                # reset cache\n                if self.model.reuse_cache_dis or not self.model.training:\n                    self.model._cache = None\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/wavenet/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/wavenet/residual_block.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport math\nfrom typing import Optional\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\n\nclass ResidualBlock(nn.Layer):\n    \"\"\"Residual block module in WaveNet.\"\"\"\n\n    def __init__(\n            self,\n            kernel_size: int=3,\n            residual_channels: int=64,\n            gate_channels: int=128,\n            skip_channels: int=64,\n            aux_channels: int=80,\n            global_channels: int=-1,\n            dropout_rate: float=0.0,\n            dilation: int=1,\n            bias: bool=True,\n            scale_residual: bool=False, ):\n        \"\"\"Initialize ResidualBlock module.\n\n        Args:\n            kernel_size (int):\n                Kernel size of dilation convolution layer.\n            residual_channels (int):\n                Number of channels for residual connection.\n            skip_channels (int):\n                Number of channels for skip connection.\n            aux_channels (int):\n                Number of local conditioning channels.\n            dropout (float):\n                Dropout probability.\n            dilation (int):\n                Dilation factor.\n            bias (bool):\n                Whether to add bias parameter in convolution layers.\n            scale_residual (bool):\n                Whether to scale the residual outputs.\n\n        \"\"\"\n        super().__init__()\n        self.dropout_rate = dropout_rate\n        self.residual_channels = residual_channels\n        self.skip_channels = skip_channels\n        self.scale_residual = scale_residual\n\n        # check\n        assert (\n            kernel_size - 1) % 2 == 0, \"Not support even number kernel size.\"\n        assert gate_channels % 2 == 0\n\n        # dilation conv\n        padding = (kernel_size - 1) // 2 * dilation\n        self.conv = nn.Conv1D(\n            residual_channels,\n            gate_channels,\n            kernel_size,\n            padding=padding,\n            dilation=dilation,\n            bias_attr=bias, )\n\n        # local conditioning\n        if aux_channels > 0:\n            self.conv1x1_aux = nn.Conv1D(\n                aux_channels, gate_channels, kernel_size=1, bias_attr=False)\n        else:\n            self.conv1x1_aux = None\n\n        # global conditioning\n        if global_channels > 0:\n            self.conv1x1_glo = nn.Conv1D(\n                global_channels, gate_channels, kernel_size=1, bias_attr=False)\n        else:\n            self.conv1x1_glo = None\n\n        # conv output is split into two groups\n        gate_out_channels = gate_channels // 2\n\n        # NOTE: concat two convs into a single conv for the efficiency\n        #   (integrate res 1x1 + skip 1x1 convs)\n        self.conv1x1_out = nn.Conv1D(\n            gate_out_channels,\n            residual_channels + skip_channels,\n            kernel_size=1,\n            bias_attr=bias)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: Optional[paddle.Tensor]=None,\n            c: Optional[paddle.Tensor]=None,\n            g: Optional[paddle.Tensor]=None,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): Input tensor (B, residual_channels, T).\n            x_mask Optional[paddle.Tensor]: Mask tensor (B, 1, T).\n            c (Optional[Tensor]): Local conditioning tensor (B, aux_channels, T).\n            g (Optional[Tensor]): Global conditioning tensor (B, global_channels, 1).\n\n        Returns:\n            Tensor: Output tensor for residual connection (B, residual_channels, T).\n            Tensor: Output tensor for skip connection (B, skip_channels, T).\n\n        \"\"\"\n        residual = x\n        x = F.dropout(x, p=self.dropout_rate, training=self.training)\n        x = self.conv(x)\n\n        # split into two part for gated activation\n        splitdim = 1\n        xa, xb = paddle.split(x, 2, axis=splitdim)\n\n        # local conditioning\n        if c is not None:\n            c = self.conv1x1_aux(c)\n            ca, cb = paddle.split(c, 2, axis=splitdim)\n            xa, xb = xa + ca, xb + cb\n\n        # global conditioning\n        if g is not None:\n            g = self.conv1x1_glo(g)\n            ga, gb = paddle.split(g, 2, axis=splitdim)\n            xa, xb = xa + ga, xb + gb\n\n        x = paddle.tanh(xa) * F.sigmoid(xb)\n\n        # residual + skip 1x1 conv\n        x = self.conv1x1_out(x)\n        if x_mask is not None:\n            x = x * x_mask\n\n        # split integrated conv results\n        x, s = paddle.split(\n            x, [self.residual_channels, self.skip_channels], axis=1)\n\n        # for residual connection\n        x = x + residual\n        if self.scale_residual:\n            x = x * math.sqrt(0.5)\n\n        return x, s\n"
  },
  {
    "path": "paddlespeech/t2s/models/vits/wavenet/wavenet.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport math\nfrom typing import Optional\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.models.vits.wavenet.residual_block import ResidualBlock\n\n\nclass WaveNet(nn.Layer):\n    \"\"\"WaveNet with global conditioning.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=1,\n            out_channels: int=1,\n            kernel_size: int=3,\n            layers: int=30,\n            stacks: int=3,\n            base_dilation: int=2,\n            residual_channels: int=64,\n            aux_channels: int=-1,\n            gate_channels: int=128,\n            skip_channels: int=64,\n            global_channels: int=-1,\n            dropout_rate: float=0.0,\n            bias: bool=True,\n            use_weight_norm: bool=True,\n            use_first_conv: bool=False,\n            use_last_conv: bool=False,\n            scale_residual: bool=False,\n            scale_skip_connect: bool=False, ):\n        \"\"\"Initialize WaveNet module.\n\n        Args:\n            in_channels (int):\n                Number of input channels.\n            out_channels (int):\n                Number of output channels.\n            kernel_size (int):\n                Kernel size of dilated convolution.\n            layers (int):\n                Number of residual block layers.\n            stacks (int):\n                Number of stacks i.e., dilation cycles.\n            base_dilation (int):\n                Base dilation factor.\n            residual_channels (int):\n                Number of channels in residual conv.\n            gate_channels (int):\n                Number of channels in gated conv.\n            skip_channels (int):\n                Number of channels in skip conv.\n            aux_channels (int):\n                Number of channels for local conditioning feature.\n            global_channels (int):\n                Number of channels for global conditioning feature.\n            dropout_rate (float):\n                Dropout rate. 0.0 means no dropout applied.\n            bias (bool):\n                Whether to use bias parameter in conv layer.\n            use_weight_norm (bool):\n                Whether to use weight norm. If set to true, it will be applied to all of the conv layers.\n            use_first_conv (bool):\n                Whether to use the first conv layers.\n            use_last_conv (bool):\n                Whether to use the last conv layers.\n            scale_residual (bool):\n                Whether to scale the residual outputs.\n            scale_skip_connect (bool):\n                Whether to scale the skip connection outputs.\n\n        \"\"\"\n        super().__init__()\n        self.layers = layers\n        self.stacks = stacks\n        self.kernel_size = kernel_size\n        self.base_dilation = base_dilation\n        self.use_first_conv = use_first_conv\n        self.use_last_conv = use_last_conv\n        self.scale_skip_connect = scale_skip_connect\n\n        # check the number of layers and stacks\n        assert layers % stacks == 0\n        layers_per_stack = layers // stacks\n\n        # define first convolution\n        if self.use_first_conv:\n            self.first_conv = nn.Conv1D(\n                in_channels, residual_channels, kernel_size=1, bias_attr=True)\n\n        # define residual blocks\n        self.conv_layers = nn.LayerList()\n        for layer in range(layers):\n            dilation = base_dilation**(layer % layers_per_stack)\n            conv = ResidualBlock(\n                kernel_size=kernel_size,\n                residual_channels=residual_channels,\n                gate_channels=gate_channels,\n                skip_channels=skip_channels,\n                aux_channels=aux_channels,\n                global_channels=global_channels,\n                dilation=dilation,\n                dropout_rate=dropout_rate,\n                bias=bias,\n                scale_residual=scale_residual, )\n            self.conv_layers.append(conv)\n\n        # define output layers\n        if self.use_last_conv:\n            self.last_conv = nn.Sequential(\n                nn.ReLU(),\n                nn.Conv1D(\n                    skip_channels, skip_channels, kernel_size=1,\n                    bias_attr=True),\n                nn.ReLU(),\n                nn.Conv1D(\n                    skip_channels, out_channels, kernel_size=1, bias_attr=True),\n            )\n\n        # apply weight norm\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            x_mask: Optional[paddle.Tensor]=None,\n            c: Optional[paddle.Tensor]=None,\n            g: Optional[paddle.Tensor]=None, ) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor):\n                Input noise signal (B, 1, T) if use_first_conv else (B, residual_channels, T).\n            x_mask (Optional[Tensor]):\n                Mask tensor (B, 1, T).\n            c (Optional[Tensor]):\n                Local conditioning features (B, aux_channels, T).\n            g (Optional[Tensor]):\n                Global conditioning features (B, global_channels, 1).\n\n        Returns:\n            Tensor:\n                Output tensor (B, out_channels, T) if use_last_conv else(B, residual_channels, T).\n\n        \"\"\"\n        # encode to hidden representation\n        if self.use_first_conv:\n            x = self.first_conv(x)\n\n        # residual block\n        skips = 0.0\n        for f in self.conv_layers:\n            x, h = f(x, x_mask=x_mask, c=c, g=g)\n            skips = skips + h\n        x = skips\n        if self.scale_skip_connect:\n            x = x * math.sqrt(1.0 / len(self.conv_layers))\n\n        # apply final layers\n        if self.use_last_conv:\n            x = self.last_conv(x)\n\n        return x\n\n    def apply_weight_norm(self):\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n"
  },
  {
    "path": "paddlespeech/t2s/models/waveflow.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport time\nfrom typing import List\nfrom typing import Tuple\nfrom typing import Union\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\nfrom paddle.nn import initializer as I\n\nfrom paddlespeech.t2s.modules import geometry as geo\nfrom paddlespeech.t2s.utils import checkpoint\n\n__all__ = [\"WaveFlow\", \"ConditionalWaveFlow\", \"WaveFlowLoss\"]\n\n\ndef fold(x, n_group):\n    \"\"\"Fold audio or spectrogram's temporal dimension in to groups.\n\n    Args:\n        x(Tensor): \n            The input tensor. shape=(*, time_steps)\n        n_group(int): \n            The size of a group.\n\n    Returns:\n        Tensor: Folded tensor. shape=(*, time_steps // n_group, group)\n    \"\"\"\n    spatial_shape = list(x.shape[:-1])\n    time_steps = paddle.shape(x)[-1]\n    new_shape = spatial_shape + [time_steps // n_group, n_group]\n    return paddle.reshape(x, new_shape)\n\n\nclass UpsampleNet(nn.LayerList):\n    \"\"\"Layer to upsample mel spectrogram to the same temporal resolution with\n    the corresponding waveform.\n\n    It consists of several conv2dtranspose layers which perform deconvolution\n    on mel and time dimension.\n\n    Args:\n        upscale_factors(List[int], optional): \n            Time upsampling factors for each Conv2DTranspose Layer.\n            The ``UpsampleNet`` contains ``len(upscale_factor)`` Conv2DTranspose\n            Layers. Each upscale_factor is used as the ``stride`` for the\n            corresponding Conv2DTranspose. Defaults to [16, 16], this the default\n            upsampling factor is 256.\n\n    Notes:\n        ``np.prod(upscale_factors)`` should equals the ``hop_length`` of the stft\n        transformation used to extract spectrogram features from audio.\n\n        For example, ``16 * 16 = 256``, then the spectrogram extracted with a stft\n        transformation whose ``hop_length`` equals 256 is suitable.\n\n        See Also\n    \n        ``librosa.core.stft``\n    \"\"\"\n\n    def __init__(self, upsample_factors):\n        super().__init__()\n        for factor in upsample_factors:\n            std = math.sqrt(1 / (3 * 2 * factor))\n            init = I.Uniform(-std, std)\n            self.append(\n                nn.utils.weight_norm(\n                    nn.Conv2DTranspose(\n                        1,\n                        1, (3, 2 * factor),\n                        padding=(1, factor // 2),\n                        stride=(1, factor),\n                        weight_attr=init,\n                        bias_attr=init)))\n\n        # upsample factors\n        self.upsample_factor = np.prod(upsample_factors)\n        self.upsample_factors = upsample_factors\n\n    def forward(self, x, trim_conv_artifact=False):\n        \"\"\"Forward pass of the ``UpsampleNet``\n\n        Args:\n            x(Tensor): \n                The input spectrogram. shape=(batch_size, input_channels, time_steps)\n            trim_conv_artifact(bool, optional, optional): \n                Trim deconvolution artifact at each layer. Defaults to False.\n\n        Returns:\n           Tensor: The upsampled spectrogram. shape=(batch_size, input_channels, time_steps * upsample_factor)\n\n        Notes:\n            If trim_conv_artifact is ``True``, the output time steps is less\n            than ``time_steps * upsample_factors``.\n        \"\"\"\n        x = paddle.unsqueeze(x, 1)  # (B, C, T) -> (B, 1, C, T)\n        for layer in self:\n            x = layer(x)\n            if trim_conv_artifact:\n                time_cutoff = layer._kernel_size[1] - layer._stride[1]\n                x = x[:, :, :, :-time_cutoff]\n            x = F.leaky_relu(x, 0.4)\n        x = paddle.squeeze(x, 1)  # back to (B, C, T)\n        return x\n\n\nclass ResidualBlock(nn.Layer):\n    \"\"\"ResidualBlock, the basic unit of ResidualNet used in WaveFlow.\n\n    It has a conv2d layer, which has causal padding in height dimension and\n    same paddign in width dimension. It also has projection for the condition\n    and output.\n\n    Args:\n        channels (int): \n            Feature size of the input.\n        cond_channels (int): \n            Featuer size of the condition.\n        kernel_size (Tuple[int]): \n            Kernel size of the Convolution2d applied to the input.\n        dilations (int): \n            Dilations of the Convolution2d applied to the input.\n    \"\"\"\n\n    def __init__(self, channels, cond_channels, kernel_size, dilations):\n        super().__init__()\n        # input conv\n        std = math.sqrt(1 / channels * np.prod(kernel_size))\n        init = I.Uniform(-std, std)\n        receptive_field = [\n            1 + (k - 1) * d for (k, d) in zip(kernel_size, dilations)\n        ]\n        rh, rw = receptive_field\n        paddings = [rh - 1, 0, rw // 2, (rw - 1) // 2]  # causal & same\n        conv = nn.Conv2D(\n            channels,\n            2 * channels,\n            kernel_size,\n            padding=paddings,\n            dilation=dilations,\n            weight_attr=init,\n            bias_attr=init)\n        self.conv = nn.utils.weight_norm(conv)\n        self.rh = rh\n        self.rw = rw\n        self.dilations = dilations\n\n        # condition projection\n        std = math.sqrt(1 / cond_channels)\n        init = I.Uniform(-std, std)\n        condition_proj = nn.Conv2D(\n            cond_channels,\n            2 * channels, (1, 1),\n            weight_attr=init,\n            bias_attr=init)\n        self.condition_proj = nn.utils.weight_norm(condition_proj)\n\n        # parametric residual & skip connection\n        std = math.sqrt(1 / channels)\n        init = I.Uniform(-std, std)\n        out_proj = nn.Conv2D(\n            channels, 2 * channels, (1, 1), weight_attr=init, bias_attr=init)\n        self.out_proj = nn.utils.weight_norm(out_proj)\n\n    def forward(self, x, condition):\n        \"\"\"Compute output for a whole folded sequence.\n\n        Args:\n            x (Tensor): \n                The input. [shape=(batch_size, channel, height, width)]\n            condition (Tensor [shape=(batch_size, condition_channel, height, width)]): \n                The local condition.\n\n        Returns: \n            res (Tensor): \n                The residual output. [shape=(batch_size, channel, height, width)]\n            skip (Tensor): \n                The skip output. [shape=(batch_size, channel, height, width)]\n        \"\"\"\n        x_in = x\n        x = self.conv(x)\n        x += self.condition_proj(condition)\n\n        content, gate = paddle.chunk(x, 2, axis=1)\n        x = paddle.tanh(content) * F.sigmoid(gate)\n\n        x = self.out_proj(x)\n        res, skip = paddle.chunk(x, 2, axis=1)\n        res = x_in + res\n        return res, skip\n\n    def start_sequence(self):\n        \"\"\"Prepare the layer for incremental computation of causal\n        convolution. Reset the buffer for causal convolution.\n\n        Raises:\n            ValueError: If not in evaluation mode.\n        \"\"\"\n        if self.training:\n            raise ValueError(\"Only use start sequence at evaluation mode.\")\n        self._conv_buffer = paddle.zeros([1])\n\n        # NOTE: call self.conv's weight norm hook expliccitly since\n        # its weight will be visited directly in `add_input` without\n        # calling its `__call__` method. If we do not trigger the weight\n        # norm hook, the weight may be outdated. e.g. after loading from\n        # a saved checkpoint\n        # see also: https://github.com/pytorch/pytorch/issues/47588\n        for hook in self.conv._forward_pre_hooks.values():\n            hook(self.conv, None)\n\n    def add_input(self, x_row, condition_row):\n        \"\"\"Compute the output for a row and update the buffer.\n\n        Args:\n            x_row (Tensor): \n                A row of the input. shape=(batch_size, channel, 1, width)\n            condition_row (Tensor): \n                A row of the condition. shape=(batch_size, condition_channel, 1, width)\n\n        Returns:\n            res (Tensor): \n                A row of the residual output. shape=(batch_size, channel, 1, width)\n            skip (Tensor): \n                A row of the skip output. shape=(batch_size, channel, 1, width)\n\n        \"\"\"\n        x_row_in = x_row\n        if len(paddle.shape(self._conv_buffer)) == 1:\n            self._init_buffer(x_row)\n        self._update_buffer(x_row)\n        rw = self.rw\n        x_row = F.conv2d(\n            self._conv_buffer,\n            self.conv.weight,\n            self.conv.bias,\n            padding=[0, 0, rw // 2, (rw - 1) // 2],\n            dilation=self.dilations)\n        x_row += self.condition_proj(condition_row)\n        content, gate = paddle.chunk(x_row, 2, axis=1)\n        x_row = paddle.tanh(content) * F.sigmoid(gate)\n\n        x_row = self.out_proj(x_row)\n        res, skip = paddle.chunk(x_row, 2, axis=1)\n        res = x_row_in + res\n        return res, skip\n\n    def _init_buffer(self, input):\n        batch_size, channels, _, width = input.shape\n        self._conv_buffer = paddle.zeros(\n            [batch_size, channels, self.rh, width], dtype=input.dtype)\n\n    def _update_buffer(self, input):\n        self._conv_buffer = paddle.concat(\n            [self._conv_buffer[:, :, 1:, :], input], axis=2)\n\n\nclass ResidualNet(nn.LayerList):\n    \"\"\"A stack of several ResidualBlocks. It merges condition at each layer.\n\n    Args:\n        n_layer (int): \n            Number of ResidualBlocks in the ResidualNet.\n        residual_channels (int): \n            Feature size of each ResidualBlocks.\n        condition_channels (int): \n            Feature size of the condition.\n        kernel_size (Tuple[int]): \n            Kernel size of each ResidualBlock.\n        dilations_h (List[int]): \n            Dilation in height dimension of every ResidualBlock.\n\n    Raises:\n        ValueError: If the length of dilations_h does not equals n_layers.\n    \"\"\"\n\n    def __init__(self,\n                 n_layer: int,\n                 residual_channels: int,\n                 condition_channels: int,\n                 kernel_size: Tuple[int],\n                 dilations_h: List[int]):\n        if len(dilations_h) != n_layer:\n            raise ValueError(\n                \"number of dilations_h should equals num of layers\")\n        super().__init__()\n        for i in range(n_layer):\n            dilation = (dilations_h[i], 2**i)\n            layer = ResidualBlock(residual_channels, condition_channels,\n                                  kernel_size, dilation)\n            self.append(layer)\n\n    def forward(self, x, condition):\n        \"\"\"Comput the output of given the input and the condition.\n\n        Args:\n            x (Tensor): \n                The input. shape=(batch_size, channel, height, width)\n            condition (Tensor): \n                The local condition. shape=(batch_size, condition_channel, height, width)\n            \n        Returns: \n            Tensor: The output, which is an aggregation of all the skip outputs. shape=(batch_size, channel, height, width)\n            \n        \"\"\"\n        skip_connections = []\n        for layer in self:\n            x, skip = layer(x, condition)\n            skip_connections.append(skip)\n        out = paddle.sum(paddle.stack(skip_connections, 0), 0)\n        return out\n\n    def start_sequence(self):\n        \"\"\"Prepare the layer for incremental computation.\n        \"\"\"\n        for layer in self:\n            layer.start_sequence()\n\n    def add_input(self, x_row, condition_row):\n        \"\"\"Compute the output for a row and update the buffers.\n\n        Args:\n            x_row (Tensor): \n                A row of the input. shape=(batch_size, channel, 1, width)\n            condition_row (Tensor):  \n                A row of the condition. shape=(batch_size, condition_channel, 1, width)\n            \n        Returns:\n            res (Tensor): \n                A row of the residual output. shape=(batch_size, channel, 1, width) \n            skip (Tensor): \n                A row of the skip output. shape=(batch_size, channel, 1, width)\n                \n        \"\"\"\n        skip_connections = []\n        for layer in self:\n            x_row, skip = layer.add_input(x_row, condition_row)\n            skip_connections.append(skip)\n        out = paddle.sum(paddle.stack(skip_connections, 0), 0)\n        return out\n\n\nclass Flow(nn.Layer):\n    \"\"\"A bijection (Reversable layer) that transform a density of latent\n    variables p(Z) into a complex data distribution p(X).\n\n    It's an auto regressive flow. The ``forward`` method implements the\n    probability density estimation. The ``inverse`` method implements the\n    sampling.\n\n    Args:\n        n_layers (int): \n            Number of ResidualBlocks in the Flow.\n        channels (int): \n            Feature size of the ResidualBlocks.\n        mel_bands (int): \n            Feature size of the mel spectrogram (mel bands).\n        kernel_size (Tuple[int]): \n            Kernel size of each ResisualBlocks in the Flow.\n        n_group (int): \n            Number of timesteps to the folded into a group.\n    \"\"\"\n    dilations_dict = {\n        8: [1, 1, 1, 1, 1, 1, 1, 1],\n        16: [1, 1, 1, 1, 1, 1, 1, 1],\n        32: [1, 2, 4, 1, 2, 4, 1, 2],\n        64: [1, 2, 4, 8, 16, 1, 2, 4],\n        128: [1, 2, 4, 8, 16, 32, 64, 1]\n    }\n\n    def __init__(self, n_layers, channels, mel_bands, kernel_size, n_group):\n        super().__init__()\n        # input projection\n        self.input_proj = nn.utils.weight_norm(\n            nn.Conv2D(\n                1,\n                channels, (1, 1),\n                weight_attr=I.Uniform(-1., 1.),\n                bias_attr=I.Uniform(-1., 1.)))\n\n        # residual net\n        self.resnet = ResidualNet(n_layers, channels, mel_bands, kernel_size,\n                                  self.dilations_dict[n_group])\n\n        # output projection\n        self.output_proj = nn.Conv2D(\n            channels,\n            2, (1, 1),\n            weight_attr=I.Constant(0.),\n            bias_attr=I.Constant(0.))\n\n        # specs\n        self.n_group = n_group\n\n    def _predict_parameters(self, x, condition):\n        x = self.input_proj(x)\n        x = self.resnet(x, condition)\n        bijection_params = self.output_proj(x)\n        logs, b = paddle.chunk(bijection_params, 2, axis=1)\n        return logs, b\n\n    def _transform(self, x, logs, b):\n        z_0 = x[:, :, :1, :]  # the first row, just copy it\n        z_out = x[:, :, 1:, :] * paddle.exp(logs) + b\n        z_out = paddle.concat([z_0, z_out], axis=2)\n        return z_out\n\n    def forward(self, x, condition):\n        \"\"\"Probability density estimation. It is done by inversely transform\n        a sample from p(X) into a sample from p(Z).\n\n        Args:\n            x (Tensor): \n                A input sample of the distribution p(X). shape=(batch, 1, height, width)\n            condition (Tensor): \n                The local condition. shape=(batch, condition_channel, height, width)\n            \n        Returns:\n            z (Tensor): \n                shape(batch, 1, height, width), the transformed sample.\n            Tuple[Tensor, Tensor]:\n                The parameter of the transformation.\n                logs (Tensor): shape(batch, 1, height - 1, width), the log scale of the transformation from x to z.\n                b (Tensor): shape(batch, 1, height - 1, width), the shift of the transformation from x to z.\n        \"\"\"\n        # (B, C, H-1, W)\n        logs, b = self._predict_parameters(x[:, :, :-1, :],\n                                           condition[:, :, 1:, :])\n        z = self._transform(x, logs, b)\n        return z, (logs, b)\n\n    def _predict_row_parameters(self, x_row, condition_row):\n        x_row = self.input_proj(x_row)\n        x_row = self.resnet.add_input(x_row, condition_row)\n        bijection_params = self.output_proj(x_row)\n        logs, b = paddle.chunk(bijection_params, 2, axis=1)\n        return logs, b\n\n    def _inverse_transform_row(self, z_row, logs, b):\n        x_row = (z_row - b) * paddle.exp(-logs)\n        return x_row\n\n    def _inverse_row(self, z_row, x_row, condition_row):\n        logs, b = self._predict_row_parameters(x_row, condition_row)\n        x_next_row = self._inverse_transform_row(z_row, logs, b)\n        return x_next_row, (logs, b)\n\n    def _start_sequence(self):\n        self.resnet.start_sequence()\n\n    def inverse(self, z, condition):\n        \"\"\"Sampling from the distrition p(X). It is done by sample form\n        p(Z) and transform the sample. It is a auto regressive transformation.\n\n        Args:\n            z(Tensor): \n                A sample of the distribution p(Z). shape=(batch, 1, time_steps\n            condition(Tensor): \n                The local condition. shape=(batch, condition_channel, time_steps)\n        Returns:\n            Tensor:\n                The transformed sample. shape=(batch, 1, height, width)\n        \"\"\"\n        z_0 = z[:, :, :1, :]\n        x = paddle.zeros_like(z)\n        x[:, :, :1, :] = z_0\n\n        self._start_sequence()\n\n        num_step = paddle.ones([1], dtype='int32') * (self.n_group)\n        for i in range(1, num_step):\n            x_row = x[:, :, i - 1:i, :]\n            z_row = z[:, :, i:i + 1, :]\n            condition_row = condition[:, :, i:i + 1, :]\n            x_next_row, (logs, b) = self._inverse_row(z_row, x_row,\n                                                      condition_row)\n            x[:, :, i:i + 1, :] = x_next_row\n\n        return x\n\n\nclass WaveFlow(nn.LayerList):\n    \"\"\"An Deep Reversible layer that is composed of severel auto regressive\n    flows.\n\n    Args:\n        n_flows (int): \n            Number of flows in the WaveFlow model.\n        n_layers (int): \n            Number of ResidualBlocks in each Flow.\n        n_group (int): \n            Number of timesteps to fold as a group.\n        channels (int): \n            Feature size of each ResidualBlock.\n        mel_bands (int): \n            Feature size of mel spectrogram (mel bands).\n        kernel_size (Union[int, List[int]]): \n            Kernel size of the convolution layer in each ResidualBlock.\n    \"\"\"\n\n    def __init__(self, n_flows, n_layers, n_group, channels, mel_bands,\n                 kernel_size):\n        if n_group % 2 or n_flows % 2:\n            raise ValueError(\n                \"number of flows and number of group must be even \"\n                \"since a permutation along group among flows is used.\")\n        super().__init__()\n        for _ in range(n_flows):\n            self.append(\n                Flow(n_layers, channels, mel_bands, kernel_size, n_group))\n\n        # permutations in h\n        self.perms = self._create_perm(n_group, n_flows)\n\n        # specs\n        self.n_group = n_group\n        self.n_flows = n_flows\n\n    def _create_perm(self, n_group, n_flows):\n        indices = list(range(n_group))\n        half = n_group // 2\n        perms = []\n        for i in range(n_flows):\n            if i < n_flows // 2:\n                perm = indices[::-1]\n            else:\n                perm = list(reversed(indices[:half])) + list(\n                    reversed(indices[half:]))\n            perm = paddle.to_tensor(perm)\n            self.register_buffer(perm.name, perm)\n            perms.append(perm)\n        return perms\n\n    def _trim(self, x, condition):\n        assert condition.shape[-1] >= x.shape[-1]\n        pruned_len = int(paddle.shape(x)[-1] // self.n_group * self.n_group)\n\n        if x.shape[-1] > pruned_len:\n            x = x[:, :pruned_len]\n        if condition.shape[-1] > pruned_len:\n            condition = condition[:, :, :pruned_len]\n        return x, condition\n\n    def forward(self, x, condition):\n        \"\"\"Probability density estimation of random variable x given the\n        condition.\n\n        Args:\n            x (Tensor): \n                The audio. shape=(batch_size, time_steps)\n            condition (Tensor): \n                The local condition (mel spectrogram here). shape=(batch_size, condition channel, time_steps)\n                \n        Returns:\n            Tensor: \n                The transformed random variable. shape=(batch_size, time_steps)\n            Tensor: \n                The log determinant of the jacobian of the transformation from x to z. shape=(1,)\n        \"\"\"\n        # x: (B, T)\n        # condition: (B, C, T) upsampled condition\n        x, condition = self._trim(x, condition)\n\n        # to (B, C, h, T//h) layout\n        x = paddle.unsqueeze(\n            paddle.transpose(fold(x, self.n_group), [0, 2, 1]), 1)\n        condition = paddle.transpose(\n            fold(condition, self.n_group), [0, 1, 3, 2])\n\n        # flows\n        logs_list = []\n        for i, layer in enumerate(self):\n            x, (logs, b) = layer(x, condition)\n            logs_list.append(logs)\n            # permute paddle has no shuffle dim\n            x = geo.shuffle_dim(x, 2, perm=self.perms[i])\n            condition = geo.shuffle_dim(condition, 2, perm=self.perms[i])\n\n        z = paddle.squeeze(x, 1)  # (B, H, W)\n        batch_size = z.shape[0]\n        z = paddle.reshape(paddle.transpose(z, [0, 2, 1]), [batch_size, -1])\n\n        log_det_jacobian = paddle.sum(paddle.stack(logs_list))\n        return z, log_det_jacobian\n\n    def inverse(self, z, condition):\n        \"\"\"Sampling from the distrition p(X).\n\n        It is done by sample a ``z`` form p(Z) and transform it into ``x``.\n        Each Flow transform .. math:: `z_{i-1}` to .. math:: `z_{i}` in an\n        autoregressive manner.\n\n        Args:\n            z (Tensor): \n                A sample of the distribution p(Z). shape=(batch, 1, time_steps\n            condition (Tensor): \n                The local condition. shape=(batch, condition_channel, time_steps)    \n\n        Returns: \n            Tensor: The transformed sample (audio here). shape=(batch_size, time_steps)\n        \"\"\"\n\n        z, condition = self._trim(z, condition)\n        # to (B, C, h, T//h) layout\n        z = paddle.unsqueeze(\n            paddle.transpose(fold(z, self.n_group), [0, 2, 1]), 1)\n        condition = paddle.transpose(\n            fold(condition, self.n_group), [0, 1, 3, 2])\n\n        # reverse it flow by flow\n        for i in reversed(range(self.n_flows)):\n            z = geo.shuffle_dim(z, 2, perm=self.perms[i])\n            condition = geo.shuffle_dim(condition, 2, perm=self.perms[i])\n            z = self[i].inverse(z, condition)\n\n        x = paddle.squeeze(z, 1)  # (B, H, W)\n        batch_size = x.shape[0]\n        x = paddle.reshape(paddle.transpose(x, [0, 2, 1]), [batch_size, -1])\n        return x\n\n\nclass ConditionalWaveFlow(nn.LayerList):\n    \"\"\"ConditionalWaveFlow, a UpsampleNet with a WaveFlow model.\n\n    Args:\n        upsample_factors (List[int]): \n            Upsample factors for the upsample net.\n        n_flows (int): \n            Number of flows in the WaveFlow model.\n        n_layers (int): \n            Number of ResidualBlocks in each Flow.\n        n_group (int): \n            Number of timesteps to fold as a group.\n        channels (int): \n            Feature size of each ResidualBlock.\n        n_mels (int): \n            Feature size of mel spectrogram (mel bands).\n        kernel_size (Union[int, List[int]]): \n            Kernel size of the convolution layer in each ResidualBlock.\n        \"\"\"\n\n    def __init__(self,\n                 upsample_factors: List[int],\n                 n_flows: int,\n                 n_layers: int,\n                 n_group: int,\n                 channels: int,\n                 n_mels: int,\n                 kernel_size: Union[int, List[int]]):\n        super().__init__()\n        self.encoder = UpsampleNet(upsample_factors)\n        self.decoder = WaveFlow(\n            n_flows=n_flows,\n            n_layers=n_layers,\n            n_group=n_group,\n            channels=channels,\n            mel_bands=n_mels,\n            kernel_size=kernel_size)\n\n    def forward(self, audio, mel):\n        \"\"\"Compute the transformed random variable z (x to z) and the log of\n        the determinant of the jacobian of the transformation from x to z.\n\n        Args:\n            audio(Tensor): \n                The audio. shape=(B, T)\n            mel(Tensor): \n                The mel spectrogram. shape=(B, C_mel, T_mel)\n\n        Returns:\n            Tensor: \n                The inversely transformed random variable z (x to z). shape=(B, T)\n            Tensor: \n                the log of the determinant of the jacobian of the transformation from x to z. shape=(1,)\n        \"\"\"\n        condition = self.encoder(mel)\n        z, log_det_jacobian = self.decoder(audio, condition)\n        return z, log_det_jacobian\n\n    @paddle.no_grad()\n    def infer(self, mel):\n        \"\"\"Generate raw audio given mel spectrogram.\n\n        Args:\n            mel(np.ndarray): \n                Mel spectrogram of an utterance(in log-magnitude). shape=(C_mel, T_mel)\n\n        Returns:\n            Tensor: \n                The synthesized audio, where``T <= T_mel * upsample_factors``. shape=(B, T)\n        \"\"\"\n        start = time.time()\n        condition = self.encoder(mel, trim_conv_artifact=True)  # (B, C, T)\n        batch_size, _, time_steps = condition.shape\n        z = paddle.randn([batch_size, time_steps], dtype=mel.dtype)\n        x = self.decoder.inverse(z, condition)\n        end = time.time()\n        print(\"time: {}s\".format(end - start))\n        return x\n\n    @paddle.no_grad()\n    def predict(self, mel):\n        \"\"\"Generate raw audio given mel spectrogram.\n\n        Args:\n            mel(np.ndarray): \n                Mel spectrogram of an utterance(in log-magnitude). shape=(C_mel, T_mel)\n\n        Returns:\n            np.ndarray: The synthesized audio. shape=(T,)\n        \"\"\"\n        mel = paddle.to_tensor(mel)\n        mel = paddle.unsqueeze(mel, 0)\n        audio = self.infer(mel)\n        audio = audio[0].numpy()\n        return audio\n\n    @classmethod\n    def from_pretrained(cls, config, checkpoint_path):\n        \"\"\"Build a ConditionalWaveFlow model from a pretrained model.\n\n        Args:\n            config(yacs.config.CfgNode): \n                model configs\n            checkpoint_path(Path or str): \n                the path of pretrained model checkpoint, without extension name\n\n        Returns:\n            ConditionalWaveFlow The model built from pretrained result.\n        \"\"\"\n        model = cls(upsample_factors=config.model.upsample_factors,\n                    n_flows=config.model.n_flows,\n                    n_layers=config.model.n_layers,\n                    n_group=config.model.n_group,\n                    channels=config.model.channels,\n                    n_mels=config.data.n_mels,\n                    kernel_size=config.model.kernel_size)\n        checkpoint.load_parameters(model, checkpoint_path=checkpoint_path)\n        return model\n\n\nclass WaveFlowLoss(nn.Layer):\n    \"\"\"Criterion of a WaveFlow model.\n\n    Args:\n        sigma (float): \n            The standard deviation of the gaussian noise used in WaveFlow, by default 1.0.\n    \"\"\"\n\n    def __init__(self, sigma=1.0):\n        super().__init__()\n        self.sigma = sigma\n        self.const = 0.5 * np.log(2 * np.pi) + np.log(self.sigma)\n\n    def forward(self, z, log_det_jacobian):\n        \"\"\"Compute the loss given the transformed random variable z and the\n        log_det_jacobian of transformation from x to z.\n\n        Args:\n            z(Tensor): \n                The transformed random variable (x to z). shape=(B, T)\n            log_det_jacobian(Tensor): \n                The log of the determinant of the jacobian matrix of the\n                transformation from x to z.  shape=(1,)\n\n        Returns:\n            Tensor: The loss. shape=(1,)\n        \"\"\"\n        loss = paddle.sum(z * z) / (2 * self.sigma * self.sigma\n                                    ) - log_det_jacobian\n        loss = loss / np.prod(z.shape)\n        return loss + self.const\n\n\nclass ConditionalWaveFlow2Infer(ConditionalWaveFlow):\n    def forward(self, mel):\n        \"\"\"Generate raw audio given mel spectrogram.\n\n        Args:\n            mel (np.ndarray): \n                Mel spectrogram of an utterance(in log-magnitude). shape=(C_mel, T_mel)\n            \n        Returns:\n            np.ndarray: The synthesized audio. shape=(T,)\n            \n        \"\"\"\n        audio = self.predict(mel)\n        return audio\n"
  },
  {
    "path": "paddlespeech/t2s/models/wavernn/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .wavernn import *\nfrom .wavernn_updater import *\n"
  },
  {
    "path": "paddlespeech/t2s/models/wavernn/wavernn.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from https://github.com/fatchord/WaveRNN\nimport sys\nimport time\nfrom typing import List\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.t2s.audio.codec import decode_mu_law\nfrom paddlespeech.t2s.modules.losses import sample_from_discretized_mix_logistic\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.upsample import Stretch2D\n\n\nclass ResBlock(nn.Layer):\n    def __init__(self, dims):\n        super().__init__()\n        self.conv1 = nn.Conv1D(dims, dims, kernel_size=1, bias_attr=False)\n        self.conv2 = nn.Conv1D(dims, dims, kernel_size=1, bias_attr=False)\n        self.batch_norm1 = nn.BatchNorm1D(dims)\n        self.batch_norm2 = nn.BatchNorm1D(dims)\n\n    def forward(self, x):\n        '''\n        conv -> bn -> relu -> conv -> bn + residual connection\n        '''\n        residual = x\n        x = self.conv1(x)\n        x = self.batch_norm1(x)\n        x = F.relu(x)\n        x = self.conv2(x)\n        x = self.batch_norm2(x)\n        return x + residual\n\n\nclass MelResNet(nn.Layer):\n    def __init__(self,\n                 res_blocks: int=10,\n                 compute_dims: int=128,\n                 res_out_dims: int=128,\n                 aux_channels: int=80,\n                 aux_context_window: int=0):\n        super().__init__()\n        k_size = aux_context_window * 2 + 1\n        # pay attention here, the dim reduces aux_context_window * 2\n        self.conv_in = nn.Conv1D(\n            aux_channels, compute_dims, kernel_size=k_size, bias_attr=False)\n        self.batch_norm = nn.BatchNorm1D(compute_dims)\n        self.layers = nn.LayerList()\n        for _ in range(res_blocks):\n            self.layers.append(ResBlock(compute_dims))\n        self.conv_out = nn.Conv1D(compute_dims, res_out_dims, kernel_size=1)\n\n    def forward(self, x):\n        '''\n        Args:\n            x (Tensor):\n                Input tensor (B, in_dims, T).\n        Returns:\n            Tensor:\n                Output tensor (B, res_out_dims, T).\n        '''\n\n        x = self.conv_in(x)\n        x = self.batch_norm(x)\n        x = F.relu(x)\n        for f in self.layers:\n            x = f(x)\n        x = self.conv_out(x)\n        return x\n\n\nclass UpsampleNetwork(nn.Layer):\n    def __init__(self,\n                 aux_channels: int=80,\n                 upsample_scales: List[int]=[4, 5, 3, 5],\n                 compute_dims: int=128,\n                 res_blocks: int=10,\n                 res_out_dims: int=128,\n                 aux_context_window: int=2):\n        super().__init__()\n        # total_scale is the total Up sampling multiple\n        total_scale = np.prod(upsample_scales)\n        # TODO pad*total_scale is numpy.int64\n        self.indent = int(aux_context_window * total_scale)\n        self.resnet = MelResNet(\n            res_blocks=res_blocks,\n            aux_channels=aux_channels,\n            compute_dims=compute_dims,\n            res_out_dims=res_out_dims,\n            aux_context_window=aux_context_window)\n        self.resnet_stretch = Stretch2D(total_scale, 1)\n        self.up_layers = nn.LayerList()\n        for scale in upsample_scales:\n            k_size = (1, scale * 2 + 1)\n            padding = (0, scale)\n            stretch = Stretch2D(scale, 1)\n\n            conv = nn.Conv2D(\n                1, 1, kernel_size=k_size, padding=padding, bias_attr=False)\n            weight_ = paddle.full_like(conv.weight, 1. / k_size[1])\n            conv.weight.set_value(weight_)\n            self.up_layers.append(stretch)\n            self.up_layers.append(conv)\n\n    def forward(self, m):\n        '''\n        Args:\n            c (Tensor):\n                Input tensor (B, C_aux, T).\n        Returns:\n            Tensor:\n                Output tensor (B, (T - 2 * pad) *  prob(upsample_scales), C_aux).\n            Tensor:\n                Output tensor (B, (T - 2 * pad) *  prob(upsample_scales), res_out_dims).\n        '''\n        # aux: [B, C_aux, T] \n        # -> [B, res_out_dims, T - 2 * aux_context_window]\n        # -> [B, 1, res_out_dims, T - 2 * aux_context_window]\n        aux = self.resnet(m).unsqueeze(1)\n        # aux: [B, 1, res_out_dims, T - 2 * aux_context_window]\n        # -> [B, 1, res_out_dims, (T - 2 * pad) *  prob(upsample_scales)]\n        aux = self.resnet_stretch(aux)\n        # aux: [B, 1, res_out_dims, T * prob(upsample_scales)] \n        # -> [B, res_out_dims, T * prob(upsample_scales)]\n        aux = aux.squeeze(1)\n        # m: [B, C_aux, T] -> [B, 1, C_aux, T]\n        m = m.unsqueeze(1)\n        for f in self.up_layers:\n            m = f(m)\n        # m: [B, 1, C_aux, T*prob(upsample_scales)]\n        # -> [B, C_aux, T * prob(upsample_scales)]\n        # -> [B, C_aux, (T - 2 * pad) * prob(upsample_scales)]\n        m = m.squeeze(1)[:, :, self.indent:-self.indent]\n        # m: [B, (T - 2 * pad) * prob(upsample_scales), C_aux]\n        # aux: [B, (T - 2 * pad) * prob(upsample_scales), res_out_dims]\n        return m.transpose([0, 2, 1]), aux.transpose([0, 2, 1])\n\n\nclass WaveRNN(nn.Layer):\n    def __init__(\n            self,\n            rnn_dims: int=512,\n            fc_dims: int=512,\n            bits: int=9,\n            aux_context_window: int=2,\n            upsample_scales: List[int]=[4, 5, 3, 5],\n            aux_channels: int=80,\n            compute_dims: int=128,\n            res_out_dims: int=128,\n            res_blocks: int=10,\n            hop_length: int=300,\n            sample_rate: int=24000,\n            mode='RAW',\n            init_type: str=\"xavier_uniform\", ):\n        '''\n        Args:\n            rnn_dims (int, optional): \n                Hidden dims of RNN Layers.\n            fc_dims (int, optional): \n                Dims of FC Layers.\n            bits (int, optional): \n                bit depth of signal.\n            aux_context_window (int, optional): \n                The context window size of the first convolution applied to the auxiliary input, by default 2\n            upsample_scales (List[int], optional): \n                Upsample scales of the upsample network.\n            aux_channels (int, optional): \n                Auxiliary channel of the residual blocks.\n            compute_dims (int, optional): \n                Dims of Conv1D in MelResNet.\n            res_out_dims (int, optional): \n                Dims of output in MelResNet.\n            res_blocks (int, optional): \n                Number of residual blocks.\n            mode (str, optional): \n                Output mode of the WaveRNN vocoder. \n                `MOL` for Mixture of Logistic Distribution, and `RAW` for quantized bits as the model's output.\n            init_type (str): \n                How to initialize parameters.\n        '''\n        super().__init__()\n        self.mode = mode\n        self.aux_context_window = aux_context_window\n        if self.mode == 'RAW':\n            self.n_classes = 2**bits\n        elif self.mode == 'MOL':\n            self.n_classes = 10 * 3\n        else:\n            RuntimeError('Unknown model mode value - ', self.mode)\n\n        # List of rnns to call 'flatten_parameters()' on\n        self._to_flatten = []\n\n        self.rnn_dims = rnn_dims\n        self.aux_dims = res_out_dims // 4\n        self.hop_length = hop_length\n        self.sample_rate = sample_rate\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.upsample = UpsampleNetwork(\n            aux_channels=aux_channels,\n            upsample_scales=upsample_scales,\n            compute_dims=compute_dims,\n            res_blocks=res_blocks,\n            res_out_dims=res_out_dims,\n            aux_context_window=aux_context_window)\n        self.I = nn.Linear(aux_channels + self.aux_dims + 1, rnn_dims)\n\n        self.rnn1 = nn.GRU(rnn_dims, rnn_dims)\n        self.rnn2 = nn.GRU(rnn_dims + self.aux_dims, rnn_dims)\n\n        self._to_flatten += [self.rnn1, self.rnn2]\n\n        self.fc1 = nn.Linear(rnn_dims + self.aux_dims, fc_dims)\n        self.fc2 = nn.Linear(fc_dims + self.aux_dims, fc_dims)\n        self.fc3 = nn.Linear(fc_dims, self.n_classes)\n\n        # Avoid fragmentation of RNN parameters and associated warning\n        self._flatten_parameters()\n\n        nn.initializer.set_global_initializer(None)\n\n    def forward(self, x, c):\n        '''\n        Args:\n            x (Tensor): \n                wav sequence, [B, T]\n            c (Tensor): \n                mel spectrogram [B, C_aux, T']\n\n            T = (T' - 2 * aux_context_window ) * hop_length\n        Returns:\n            Tensor: [B, T, n_classes]\n        '''\n        # Although we `_flatten_parameters()` on init, when using DataParallel\n        # the model gets replicated, making it no longer guaranteed that the\n        # weights are contiguous in GPU memory. Hence, we must call it again\n        self._flatten_parameters()\n\n        bsize = paddle.shape(x)[0]\n        h1 = paddle.zeros([1, bsize, self.rnn_dims])\n        h2 = paddle.zeros([1, bsize, self.rnn_dims])\n        # c: [B, T, C_aux]\n        # aux: [B, T, res_out_dims]\n        c, aux = self.upsample(c)\n\n        aux_idx = [self.aux_dims * i for i in range(5)]\n        a1 = aux[:, :, aux_idx[0]:aux_idx[1]]\n        a2 = aux[:, :, aux_idx[1]:aux_idx[2]]\n        a3 = aux[:, :, aux_idx[2]:aux_idx[3]]\n        a4 = aux[:, :, aux_idx[3]:aux_idx[4]]\n\n        x = paddle.concat([x.unsqueeze(-1), c, a1], axis=2)\n        x = self.I(x)\n        res = x\n        x, _ = self.rnn1(x, h1)\n\n        x = x + res\n        res = x\n        x = paddle.concat([x, a2], axis=2)\n        x, _ = self.rnn2(x, h2)\n\n        x = x + res\n        x = paddle.concat([x, a3], axis=2)\n        x = F.relu(self.fc1(x))\n\n        x = paddle.concat([x, a4], axis=2)\n        x = F.relu(self.fc2(x))\n\n        return self.fc3(x)\n\n    @paddle.no_grad()\n    def generate(self,\n                 c,\n                 batched: bool=True,\n                 target: int=12000,\n                 overlap: int=600,\n                 mu_law: bool=True,\n                 gen_display: bool=False):\n        \"\"\"\n        Args:\n            c(Tensor): \n                input mels, (T', C_aux)\n            batched(bool): \n                generate in batch or not\n            target(int): \n                target number of samples to be generated in each batch entry\n            overlap(int): \n                number of samples for crossfading between batches\n            mu_law(bool)\n        Returns: \n            wav sequence:\n                Output (T' * prod(upsample_scales), out_channels, C_out).\n        \"\"\"\n\n        self.eval()\n\n        mu_law = mu_law if self.mode == 'RAW' else False\n\n        output = []\n        start = time.time()\n\n        # pseudo batch\n        # (T, C_aux) -> (1, C_aux, T)\n        c = paddle.transpose(c, [1, 0]).unsqueeze(0)\n        T = paddle.shape(c)[-1]\n        wave_len = T * self.hop_length\n        # TODO remove two transpose op by modifying function pad_tensor\n        c = self.pad_tensor(\n            c.transpose([0, 2, 1]), pad=self.aux_context_window,\n            side='both').transpose([0, 2, 1])\n\n        c, aux = self.upsample(c)\n\n        if batched:\n            # (num_folds, target + 2 * overlap, features)\n            c = self.fold_with_overlap(c, target, overlap)\n            aux = self.fold_with_overlap(aux, target, overlap)\n\n        # for dygraph to static graph, if use seq_len of `b_size, seq_len, _ = paddle.shape(c)` in for\n        # will not get TensorArray\n        # see https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/04_dygraph_to_static/case_analysis_cn.html#list-lodtensorarray\n        # b_size, seq_len, _ = paddle.shape(c)\n        b_size = paddle.shape(c)[0]\n        seq_len = paddle.shape(c)[1]\n\n        h1 = paddle.zeros([b_size, self.rnn_dims])\n        h2 = paddle.zeros([b_size, self.rnn_dims])\n        x = paddle.zeros([b_size, 1])\n\n        d = self.aux_dims\n        aux_split = [aux[:, :, d * i:d * (i + 1)] for i in range(4)]\n\n        for i in range(seq_len):\n            m_t = c[:, i, :]\n            # for dygraph to static graph\n            # a1_t, a2_t, a3_t, a4_t = (a[:, i, :] for a in aux_split)\n            a1_t = aux_split[0][:, i, :]\n            a2_t = aux_split[1][:, i, :]\n            a3_t = aux_split[2][:, i, :]\n            a4_t = aux_split[3][:, i, :]\n            x = paddle.concat([x, m_t, a1_t], axis=1)\n            x = self.I(x)\n            # use GRUCell here\n            h1, _ = self.rnn1[0].cell(x, h1)\n            x = x + h1\n            inp = paddle.concat([x, a2_t], axis=1)\n            # use GRUCell here\n            h2, _ = self.rnn2[0].cell(inp, h2)\n\n            x = x + h2\n            x = paddle.concat([x, a3_t], axis=1)\n            x = F.relu(self.fc1(x))\n\n            x = paddle.concat([x, a4_t], axis=1)\n            x = F.relu(self.fc2(x))\n\n            logits = self.fc3(x)\n\n            if self.mode == 'MOL':\n                sample = sample_from_discretized_mix_logistic(\n                    logits.unsqueeze(0).transpose([0, 2, 1]))\n                output.append(sample.reshape([-1]))\n                x = sample.transpose([1, 0, 2])\n\n            elif self.mode == 'RAW':\n                # fix bug for paddle 2.3, see https://github.com/PaddlePaddle/Paddle/commit/01f606b4f1ca3e184a59111084ed460ee0798a5a\n                # posterior = F.softmax(logits, axis=1)\n                posterior = logits\n                distrib = paddle.distribution.Categorical(posterior)\n                # corresponding operate [np.floor((fx + 1) / 2 * mu + 0.5)] in enocde_mu_law\n                # distrib.sample([1])[0].cast('float32'): [0, 2**bits-1]\n                # sample: [-1, 1]\n                sample = 2 * distrib.sample([1])[0].cast('float32') / (\n                    self.n_classes - 1.) - 1.\n                output.append(sample)\n                x = sample.unsqueeze(-1)\n            else:\n                raise RuntimeError('Unknown model mode value - ', self.mode)\n\n            if gen_display:\n                if i % 1000 == 0:\n                    self.gen_display(i, int(seq_len), int(b_size), start)\n\n        output = paddle.stack(output).transpose([1, 0])\n\n        if mu_law:\n            output = decode_mu_law(output, self.n_classes, False)\n\n        if batched:\n            output = self.xfade_and_unfold(output, target, overlap)\n        else:\n            output = output[0]\n\n        # Fade-out at the end to avoid signal cutting out suddenly\n        fade_out = paddle.linspace(1, 0, 10 * self.hop_length)\n        output = output[:wave_len]\n        output[-10 * self.hop_length:] *= fade_out\n\n        self.train()\n\n        # 增加 C_out 维度\n        return output.unsqueeze(-1)\n\n    def _flatten_parameters(self):\n        [m.flatten_parameters() for m in self._to_flatten]\n\n    def pad_tensor(self, x, pad, side='both'):\n        '''\n        Args:\n            x(Tensor): \n                mel, [1, n_frames, 80]\n            pad(int): \n                side(str, optional):  (Default value = 'both')\n\n        Returns:\n            Tensor\n        '''\n        b, t, _ = paddle.shape(x)\n        # for dygraph to static graph\n        c = x.shape[-1]\n        total = t + 2 * pad if side == 'both' else t + pad\n        padded = paddle.zeros([b, total, c])\n        if side == 'before' or side == 'both':\n            padded[:, pad:pad + t, :] = x\n        elif side == 'after':\n            padded[:, :t, :] = x\n        return padded\n\n    def fold_with_overlap(self, x, target, overlap):\n        '''\n        Fold the tensor with overlap for quick batched inference.\n        Overlap will be used for crossfading in xfade_and_unfold()\n\n        Args:\n            x(Tensor): \n                Upsampled conditioning features. mels or aux\n                shape=(1, T, features)\n                mels: [1, T, 80]\n                aux: [1, T, 128]\n            target(int): \n                Target timesteps for each index of batch\n            overlap(int): \n                Timesteps for both xfade and rnn warmup\n\n        Returns:\n            Tensor: \n                shape=(num_folds, target + 2 * overlap, features)\n                num_flods = (time_seq - overlap) // (target + overlap)\n                mel: [num_folds, target + 2 * overlap, 80]\n                aux: [num_folds, target + 2 * overlap, 128]\n\n        Details:\n            x = [[h1, h2, ... hn]]\n            Where each h is a vector of conditioning features\n            Eg: target=2, overlap=1 with x.size(1)=10\n\n            folded = [[h1, h2, h3, h4],\n                    [h4, h5, h6, h7],\n                    [h7, h8, h9, h10]]\n        '''\n\n        _, total_len, features = paddle.shape(x)\n\n        # Calculate variables needed\n        num_folds = (total_len - overlap) // (target + overlap)\n        extended_len = num_folds * (overlap + target) + overlap\n        remaining = total_len - extended_len\n\n        # Pad if some time steps poking out\n        if remaining != 0:\n            num_folds += 1\n            padding = target + 2 * overlap - remaining\n            x = self.pad_tensor(x, padding, side='after')\n\n        folded = paddle.zeros([num_folds, target + 2 * overlap, features])\n\n        # Get the values for the folded tensor\n        for i in range(num_folds):\n            start = i * (target + overlap)\n            end = start + target + 2 * overlap\n            folded[i] = x[0][start:end, :]\n        return folded\n\n    def xfade_and_unfold(self, y, target: int=12000, overlap: int=600):\n        ''' Applies a crossfade and unfolds into a 1d array.\n\n        Args:\n            y (Tensor): \n                Batched sequences of audio samples\n                shape=(num_folds, target + 2 * overlap)\n                dtype=paddle.float32\n            overlap (int): Timesteps for both xfade and rnn warmup\n\n        Returns:\n            Tensor\n                audio samples in a 1d array\n                shape=(total_len)\n                dtype=paddle.float32\n\n        Details:\n            y = [[seq1],\n                [seq2],\n                [seq3]]\n\n            Apply a gain envelope at both ends of the sequences\n\n            y = [[seq1_in, seq1_target, seq1_out],\n                [seq2_in, seq2_target, seq2_out],\n                [seq3_in, seq3_target, seq3_out]]\n\n            Stagger and add up the groups of samples:\n\n            [seq1_in, seq1_target, (seq1_out + seq2_in), seq2_target, ...]\n\n        '''\n        # num_folds = (total_len - overlap) // (target + overlap)\n        num_folds, length = paddle.shape(y)\n        target = length - 2 * overlap\n        total_len = num_folds * (target + overlap) + overlap\n\n        # Need some silence for the run warmup\n        slience_len = 0\n        linear_len = slience_len\n        fade_len = overlap - slience_len\n        slience = paddle.zeros([slience_len], dtype=paddle.float32)\n        linear = paddle.ones([linear_len], dtype=paddle.float32)\n\n        # Equal power crossfade\n        # fade_in increase from 0 to 1, fade_out reduces from 1 to 0\n        sigmoid_scale = 2.3\n        t = paddle.linspace(\n            -sigmoid_scale, sigmoid_scale, fade_len, dtype=paddle.float32)\n        # sigmoid 曲线应该更好\n        fade_in = paddle.nn.functional.sigmoid(t)\n        fade_out = 1 - paddle.nn.functional.sigmoid(t)\n        # Concat the silence to the fades\n        fade_out = paddle.concat([linear, fade_out])\n        fade_in = paddle.concat([slience, fade_in])\n\n        # Apply the gain to the overlap samples\n        y[:, :overlap] *= fade_in\n        y[:, -overlap:] *= fade_out\n\n        unfolded = paddle.zeros([total_len], dtype=paddle.float32)\n\n        # Loop to add up all the samples\n        for i in range(num_folds):\n            start = i * (target + overlap)\n            end = start + target + 2 * overlap\n            unfolded[start:end] += y[i]\n\n        return unfolded\n\n    def gen_display(self, i, seq_len, b_size, start):\n        gen_rate = (i + 1) / (time.time() - start) * b_size / 1000\n        pbar = self.progbar(i, seq_len)\n        msg = f'| {pbar} {i*b_size}/{seq_len*b_size} | Batch Size: {b_size} | Gen Rate: {gen_rate:.1f}kHz | '\n        sys.stdout.write(f\"\\r{msg}\")\n\n    def progbar(self, i, n, size=16):\n        done = int(i * size) // n\n        bar = ''\n        for i in range(size):\n            bar += '█' if i <= done else '░'\n        return bar\n\n\nclass WaveRNNInference(nn.Layer):\n    def __init__(self, normalizer, wavernn):\n        super().__init__()\n        self.normalizer = normalizer\n        self.wavernn = wavernn\n\n    def forward(self,\n                logmel,\n                batched: bool=True,\n                target: int=12000,\n                overlap: int=600,\n                mu_law: bool=True,\n                gen_display: bool=False):\n        normalized_mel = self.normalizer(logmel)\n\n        wav = self.wavernn.generate(\n            normalized_mel, )\n        # batched=batched,\n        # target=target,\n        # overlap=overlap,\n        # mu_law=mu_law,\n        # gen_display=gen_display)\n\n        return wav\n"
  },
  {
    "path": "paddlespeech/t2s/models/wavernn/wavernn_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nfrom pathlib import Path\n\nimport paddle\nimport soundfile as sf\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\ndef calculate_grad_norm(parameters, norm_type: str=2):\n    '''\n    calculate grad norm of mdoel's parameters\n    parameters:\n        model's parameters\n    norm_type: str\n    Returns\n    ------------\n    Tensor\n        grad_norm\n    '''\n\n    grad_list = [\n        paddle.to_tensor(p.grad) for p in parameters if p.grad is not None\n    ]\n    norm_list = paddle.stack(\n        [paddle.norm(grad, norm_type) for grad in grad_list])\n    total_norm = paddle.norm(norm_list)\n    return total_norm\n\n\n# for save name in gen_valid_samples()\nITERATION = 0\n\n\nclass WaveRNNUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 criterion: Layer,\n                 dataloader: DataLoader,\n                 init_state=None,\n                 output_dir: Path=None,\n                 mode='RAW'):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n\n        self.criterion = criterion\n        # self.scheduler = scheduler\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n        self.mode = mode\n\n    def update_core(self, batch):\n\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n        # parse batch\n        self.model.train()\n        self.optimizer.clear_grad()\n\n        wav, y, mel = batch\n\n        y_hat = self.model(wav, mel)\n        if self.mode == 'RAW':\n            y_hat = y_hat.transpose([0, 2, 1]).unsqueeze(-1)\n        elif self.mode == 'MOL':\n            y_hat = paddle.cast(y, dtype='float32')\n\n        y = y.unsqueeze(-1)\n        loss = self.criterion(y_hat, y)\n        loss.backward()\n        grad_norm = float(\n            calculate_grad_norm(self.model.parameters(), norm_type=2))\n\n        self.optimizer.step()\n\n        report(\"train/loss\", float(loss))\n        report(\"train/grad_norm\", float(grad_norm))\n\n        losses_dict[\"loss\"] = float(loss)\n        losses_dict[\"grad_norm\"] = float(grad_norm)\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        global ITERATION\n        ITERATION = self.state.iteration + 1\n\n\nclass WaveRNNEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 criterion: Layer,\n                 dataloader: Optimizer,\n                 output_dir: Path=None,\n                 valid_generate_loader=None,\n                 config=None):\n        super().__init__(model, dataloader)\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n        self.criterion = criterion\n        self.valid_generate_loader = valid_generate_loader\n        self.config = config\n        self.mode = config.model.mode\n\n        self.valid_samples_dir = output_dir / \"valid_samples\"\n        self.valid_samples_dir.mkdir(parents=True, exist_ok=True)\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n        # parse batch\n        wav, y, mel = batch\n        y_hat = self.model(wav, mel)\n\n        if self.mode == 'RAW':\n            y_hat = y_hat.transpose([0, 2, 1]).unsqueeze(-1)\n        elif self.mode == 'MOL':\n            y_hat = paddle.cast(y, dtype='float32')\n\n        y = y.unsqueeze(-1)\n        loss = self.criterion(y_hat, y)\n        report(\"eval/loss\", float(loss))\n\n        losses_dict[\"loss\"] = float(loss)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n\n    def gen_valid_samples(self):\n\n        for i, item in enumerate(self.valid_generate_loader):\n            if i >= self.config.generate_num:\n                break\n            print(\n                '\\n| Generating: {}/{}'.format(i + 1, self.config.generate_num))\n\n            mel = item['feats']\n            wav = item['wave']\n            wav = wav.squeeze(0)\n\n            origin_save_path = self.valid_samples_dir / '{}_steps_{}_target.wav'.format(\n                self.iteration, i)\n            sf.write(origin_save_path, wav.numpy(), samplerate=self.config.fs)\n\n            if self.config.inference.gen_batched:\n                batch_str = 'gen_batched_target{}_overlap{}'.format(\n                    self.config.inference.target, self.config.inference.overlap)\n            else:\n                batch_str = 'gen_not_batched'\n            gen_save_path = str(self.valid_samples_dir /\n                                '{}_steps_{}_{}.wav'.format(self.iteration, i,\n                                                            batch_str))\n            # (1, T, C_aux) -> (T, C_aux)\n            mel = mel.squeeze(0)\n            gen_sample = self.model.generate(\n                mel, self.config.inference.gen_batched,\n                self.config.inference.target, self.config.inference.overlap,\n                self.config.mu_law)\n            sf.write(\n                gen_save_path, gen_sample.numpy(), samplerate=self.config.fs)\n\n    def __call__(self, trainer=None):\n        summary = self.evaluate()\n        for k, v in summary.items():\n            report(k, v)\n        # gen samples at then end of evaluate\n        self.iteration = ITERATION\n        if self.iteration % self.config.gen_eval_samples_interval_steps == 0:\n            self.gen_valid_samples()\n"
  },
  {
    "path": "paddlespeech/t2s/modules/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .conv import *\nfrom .fftconv1d import *\nfrom .geometry import *\nfrom .losses import *\nfrom .positional_encoding import *\n"
  },
  {
    "path": "paddlespeech/t2s/modules/activation.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\n\nclass GLU(nn.Layer):\n    \"\"\"Gated Linear Units (GLU) Layer\"\"\"\n\n    def __init__(self, dim: int=-1):\n        super().__init__()\n        self.dim = dim\n\n    def forward(self, xs):\n        return F.glu(xs, axis=self.dim)\n\n\ndef get_activation(act, **kwargs):\n    \"\"\"Return activation function.\"\"\"\n\n    activation_funcs = {\n        \"hardtanh\": paddle.nn.Hardtanh,\n        \"tanh\": paddle.nn.Tanh,\n        \"relu\": paddle.nn.ReLU,\n        \"selu\": paddle.nn.SELU,\n        \"leakyrelu\": paddle.nn.LeakyReLU,\n        \"swish\": paddle.nn.Swish,\n        \"glu\": GLU,\n        \"gelu\": paddle.nn.GELU,\n    }\n\n    return activation_funcs[act](**kwargs)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/adversarial_loss/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/modules/adversarial_loss/gradient_reversal.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn as nn\nfrom paddle.autograd import PyLayer\n\n\nclass GradientReversalFunction(PyLayer):\n    \"\"\"Gradient Reversal Layer from:\n    Unsupervised Domain Adaptation by Backpropagation (Ganin & Lempitsky, 2015)\n\n    Forward pass is the identity function. In the backward pass,\n    the upstream gradients are multiplied by -lambda (i.e. gradient is reversed)\n    \"\"\"\n\n    @staticmethod\n    def forward(ctx, x, lambda_=1):\n        \"\"\"Forward in networks\n        \"\"\"\n        ctx.save_for_backward(lambda_)\n        return x.clone()\n\n    @staticmethod\n    def backward(ctx, grads):\n        \"\"\"Backward in networks\n        \"\"\"\n        lambda_, = ctx.saved_tensor()\n        dx = -lambda_ * grads\n        return paddle.clip(dx, min=-0.5, max=0.5)\n\n\nclass GradientReversalLayer(nn.Layer):\n    \"\"\"Gradient Reversal Layer from:\n    Unsupervised Domain Adaptation by Backpropagation (Ganin & Lempitsky, 2015)\n\n    Forward pass is the identity function. In the backward pass,\n    the upstream gradients are multiplied by -lambda (i.e. gradient is reversed)\n    \"\"\"\n\n    def __init__(self, lambda_=1):\n        super(GradientReversalLayer, self).__init__()\n        self.lambda_ = lambda_\n\n    def forward(self, x):\n        \"\"\"Forward in networks\n        \"\"\"\n        return GradientReversalFunction.apply(x, self.lambda_)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/adversarial_loss/speaker_classifier.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from Cross-Lingual-Voice-Cloning(https://github.com/deterministic-algorithms-lab/Cross-Lingual-Voice-Cloning)\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\n\nclass SpeakerClassifier(nn.Layer):\n    @typechecked\n    def __init__(\n            self,\n            idim: int,\n            hidden_sc_dim: int,\n            spk_num: int, ):\n        super().__init__()\n        # store hyperparameters\n        self.idim = idim\n        self.hidden_sc_dim = hidden_sc_dim\n        self.spk_num = spk_num\n\n        self.model = nn.Sequential(\n            nn.Linear(self.idim, self.hidden_sc_dim),\n            nn.Linear(self.hidden_sc_dim, self.spk_num))\n\n    def parse_outputs(self, out, text_lengths):\n        mask = paddle.arange(out.shape[1]).expand(\n            [out.shape[0], out.shape[1]]) < text_lengths.unsqueeze(1)\n        out = paddle.transpose(out, perm=[2, 0, 1])\n        out = out * mask\n        out = paddle.transpose(out, perm=[1, 2, 0])\n        return out\n\n    def forward(self, encoder_outputs, text_lengths):\n        \"\"\"\n        encoder_outputs = [batch_size, seq_len, encoder_embedding_size]\n        text_lengths = [batch_size]\n        \n        log probabilities of speaker classification = [batch_size, seq_len, spk_num]\n        \"\"\"\n\n        out = self.model(encoder_outputs)\n        out = self.parse_outputs(out, text_lengths)\n        return out\n"
  },
  {
    "path": "paddlespeech/t2s/modules/causal_conv.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Causal convolusion layer modules.\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass CausalConv1D(nn.Layer):\n    \"\"\"CausalConv1D module with customized initialization.\"\"\"\n\n    def __init__(\n            self,\n            in_channels,\n            out_channels,\n            kernel_size,\n            dilation=1,\n            bias=True,\n            pad=\"Pad1D\",\n            pad_params={\"value\": 0.0}, ):\n        \"\"\"Initialize CausalConv1d module.\"\"\"\n        super().__init__()\n        self.pad = getattr(paddle.nn, pad)((kernel_size - 1) * dilation,\n                                           **pad_params)\n        self.conv = nn.Conv1D(\n            in_channels,\n            out_channels,\n            kernel_size,\n            dilation=dilation,\n            bias_attr=bias)\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input tensor (B, in_channels, T).\n        Returns: \n            Tensor: Output tensor (B, out_channels, T).\n        \"\"\"\n        return self.conv(self.pad(x))[:, :, :x.shape[2]]\n\n\nclass CausalConv1DTranspose(nn.Layer):\n    \"\"\"CausalConv1DTranspose module with customized initialization.\"\"\"\n\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 kernel_size,\n                 stride,\n                 bias=True):\n        \"\"\"Initialize CausalConvTranspose1d module.\"\"\"\n        super().__init__()\n        self.deconv = nn.Conv1DTranspose(\n            in_channels, out_channels, kernel_size, stride, bias_attr=bias)\n        self.stride = stride\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input tensor (B, in_channels, T_in).\n        Returns:\n            Tensor: Output tensor (B, out_channels, T_out).\n        \"\"\"\n        return self.deconv(x)[:, :, :-self.stride]\n"
  },
  {
    "path": "paddlespeech/t2s/modules/conformer/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/modules/conformer/convolution.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"ConvolutionModule definition.\"\"\"\nfrom paddle import nn\n\n\nclass ConvolutionModule(nn.Layer):\n    \"\"\"ConvolutionModule in Conformer model.\n\n    Args:\n        channels (int): \n            The number of channels of conv layers.\n        kernel_size (int): \n            Kernerl size of conv layers.\n    \"\"\"\n\n    def __init__(self, channels, kernel_size, activation=nn.ReLU(), bias=True):\n        \"\"\"Construct an ConvolutionModule object.\"\"\"\n        super().__init__()\n        # kernerl_size should be a odd number for 'SAME' padding\n        assert (kernel_size - 1) % 2 == 0\n\n        self.pointwise_conv1 = nn.Conv1D(\n            channels,\n            2 * channels,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            bias_attr=bias, )\n        self.depthwise_conv = nn.Conv1D(\n            channels,\n            channels,\n            kernel_size,\n            stride=1,\n            padding=(kernel_size - 1) // 2,\n            groups=channels,\n            bias_attr=bias, )\n        self.norm = nn.BatchNorm1D(channels)\n        self.pointwise_conv2 = nn.Conv1D(\n            channels,\n            channels,\n            kernel_size=1,\n            stride=1,\n            padding=0,\n            bias_attr=bias, )\n        self.activation = activation\n\n    def forward(self, x):\n        \"\"\"Compute convolution module.\n\n        Args:\n            x (Tensor): \n                Input tensor (#batch, time, channels).\n        Returns:\n            Tensor: Output tensor (#batch, time, channels).\n        \"\"\"\n        # exchange the temporal dimension and the feature dimension\n        x = x.transpose([0, 2, 1])\n\n        # GLU mechanism\n        # (batch, 2*channel, time)\n        x = self.pointwise_conv1(x)\n        # (batch, channel, time)\n        x = nn.functional.glu(x, axis=1)\n\n        # 1D Depthwise Conv\n        x = self.depthwise_conv(x)\n        x = self.activation(self.norm(x))\n\n        x = self.pointwise_conv2(x)\n\n        return x.transpose([0, 2, 1])\n"
  },
  {
    "path": "paddlespeech/t2s/modules/conformer/encoder_layer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Encoder self-attention layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\n\n\nclass EncoderLayer(nn.Layer):\n    \"\"\"Encoder layer module.\n    \n    Args:\n        size (int): \n            Input dimension.\n        self_attn (nn.Layer): \n            Self-attention module instance.\n            `MultiHeadedAttention` or `RelPositionMultiHeadedAttention` instance\n            can be used as the argument.\n        feed_forward (nn.Layer): \n            Feed-forward module instance.\n            `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance\n            can be used as the argument.\n        feed_forward_macaron (nn.Layer): \n            Additional feed-forward module instance.\n            `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance\n            can be used as the argument.\n        conv_module (nn.Layer): \n            Convolution module instance.\n            `ConvlutionModule` instance can be used as the argument.\n        dropout_rate (float): \n            Dropout rate.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n        stochastic_depth_rate (float): \n            Proability to skip this layer.\n            During training, the layer may skip residual computation and return input\n            as-is with given probability.\n    \"\"\"\n\n    def __init__(\n            self,\n            size,\n            self_attn,\n            feed_forward,\n            feed_forward_macaron,\n            conv_module,\n            dropout_rate,\n            normalize_before=True,\n            concat_after=False,\n            stochastic_depth_rate=0.0, ):\n        \"\"\"Construct an EncoderLayer object.\"\"\"\n        super().__init__()\n        self.self_attn = self_attn\n        self.feed_forward = feed_forward\n        self.feed_forward_macaron = feed_forward_macaron\n        self.conv_module = conv_module\n        self.norm_ff = LayerNorm(size)  # for the FNN module\n        self.norm_mha = LayerNorm(size)  # for the MHA module\n        if feed_forward_macaron is not None:\n            self.norm_ff_macaron = LayerNorm(size)\n            self.ff_scale = 0.5\n        else:\n            self.ff_scale = 1.0\n        if self.conv_module is not None:\n            self.norm_conv = LayerNorm(size)  # for the CNN module\n            self.norm_final = LayerNorm(\n                size)  # for the final output of the block\n        self.dropout = nn.Dropout(dropout_rate)\n        self.size = size\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        if self.concat_after:\n            self.concat_linear = nn.Linear(size + size, size)\n        self.stochastic_depth_rate = stochastic_depth_rate\n\n    def forward(self, x_input, mask, cache=None):\n        \"\"\"Compute encoded features.\n\n        Args:\n            x_input(Union[Tuple, Tensor]): \n                Input tensor w/ or w/o pos emb.\n                - w/ pos emb: Tuple of tensors [(#batch, time, size), (1, time, size)].\n                - w/o pos emb: Tensor (#batch, time, size).\n            mask(Tensor): \n                Mask tensor for the input (#batch, time).\n            cache (Tensor): \n\n        Returns:\n            Tensor: \n                Output tensor (#batch, time, size).\n            Tensor: \n                Mask tensor (#batch, time).\n        \"\"\"\n        if isinstance(x_input, tuple):\n            x, pos_emb = x_input[0], x_input[1]\n        else:\n            x, pos_emb = x_input, None\n        skip_layer = False\n        # with stochastic depth, residual connection `x + f(x)` becomes\n        # `x <- x + 1 / (1 - p) * f(x)` at training time.\n        stoch_layer_coeff = 1.0\n        if self.training and self.stochastic_depth_rate > 0:\n            skip_layer = paddle.rand(1).item() < self.stochastic_depth_rate\n            stoch_layer_coeff = 1.0 / (1 - self.stochastic_depth_rate)\n        if skip_layer:\n            if cache is not None:\n                x = paddle.concat([cache, x], axis=1)\n            if pos_emb is not None:\n                return (x, pos_emb), mask\n            return x, mask\n        # whether to use macaron style\n        if self.feed_forward_macaron is not None:\n            residual = x\n            if self.normalize_before:\n                x = self.norm_ff_macaron(x)\n            x = residual + stoch_layer_coeff * self.ff_scale * self.dropout(\n                self.feed_forward_macaron(x))\n            if not self.normalize_before:\n                x = self.norm_ff_macaron(x)\n        # multi-headed self-attention module\n        residual = x\n        if self.normalize_before:\n            x = self.norm_mha(x)\n\n        if cache is None:\n            x_q = x\n        else:\n            assert cache.shape == (x.shape[0], x.shape[1] - 1, self.size)\n            x_q = x[:, -1:, :]\n            residual = residual[:, -1:, :]\n            mask = None if mask is None else mask[:, -1:, :]\n\n        if pos_emb is not None:\n            x_att = self.self_attn(x_q, x, x, pos_emb, mask)\n        else:\n            x_att = self.self_attn(x_q, x, x, mask)\n\n        if self.concat_after:\n            x_concat = paddle.concat((x, x_att), axis=-1)\n            x = residual + stoch_layer_coeff * self.concat_linear(x_concat)\n        else:\n            x = residual + stoch_layer_coeff * self.dropout(x_att)\n        if not self.normalize_before:\n            x = self.norm_mha(x)\n\n        # convolution module\n        if self.conv_module is not None:\n            residual = x\n            if self.normalize_before:\n                x = self.norm_conv(x)\n            x = residual + stoch_layer_coeff * self.dropout(self.conv_module(x))\n            if not self.normalize_before:\n                x = self.norm_conv(x)\n\n        # feed forward module\n        residual = x\n        if self.normalize_before:\n            x = self.norm_ff(x)\n        x = residual + stoch_layer_coeff * self.ff_scale * self.dropout(\n            self.feed_forward(x))\n        if not self.normalize_before:\n            x = self.norm_ff(x)\n\n        if self.conv_module is not None:\n            x = self.norm_final(x)\n\n        if cache is not None:\n            x = paddle.concat([cache, x], axis=1)\n\n        if pos_emb is not None:\n            return (x, pos_emb), mask\n\n        return x, mask\n"
  },
  {
    "path": "paddlespeech/t2s/modules/conv.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import nn\n\n__all__ = [\n    \"Conv1dCell\",\n    \"Conv1dBatchNorm\",\n]\n\n\nclass Conv1dCell(nn.Conv1D):\n    \"\"\"A subclass of Conv1D layer, which can be used in an autoregressive\n    decoder like an RNN cell. \n    \n    When used in autoregressive decoding, it performs causal temporal\n    convolution incrementally. At each time step, it takes a step input and\n    returns a step output.\n    \n    Notes\n    ------\n    It is done by caching an internal buffer of length ``receptive_file - 1``.\n    when adding a step input, the buffer is shited by one step, the latest\n    input is added to be buffer and the oldest step is discarded. And it\n    returns a step output. For single step case, convolution is equivalent to a\n    linear transformation.\n    That it can be used as a cell depends on several restrictions:\n    1. stride must be 1;\n    2. padding must be a causal padding (recpetive_field - 1, 0).\n    Thus, these arguments are removed from the ``__init__`` method of this\n    class.\n\n    Args:\n        in_channels (int): \n            The feature size of the input.\n        out_channels (int): \n            The feature size of the output.\n        kernel_size (int or Tuple[int]): \n            The size of the kernel.\n        dilation (int or Tuple[int]): \n            The dilation of the convolution, by default 1\n        weight_attr (ParamAttr, Initializer, str or bool, optional): \n            The parameter attribute of the convolution kernel, \n            by default None.\n        bias_attr (ParamAttr, Initializer, str or bool, optional):\n            The parameter attribute of the bias. \n            If ``False``, this layer does not have a bias, by default None.\n            \n    Examples: \n        >>> cell = Conv1dCell(3, 4, kernel_size=5)\n        >>> inputs = [paddle.randn([4, 3]) for _ in range(16)]\n        >>> outputs = []\n        >>> cell.eval()\n        >>> cell.start_sequence()\n        >>> for xt in inputs:\n        >>>     outputs.append(cell.add_input(xt))\n        >>> len(outputs))\n        16\n        >>> outputs[0].shape\n        [4, 4]\n    \"\"\"\n\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 kernel_size,\n                 dilation=1,\n                 weight_attr=None,\n                 bias_attr=None):\n        _dilation = dilation[0] if isinstance(dilation,\n                                              (tuple, list)) else dilation\n        _kernel_size = kernel_size[0] if isinstance(kernel_size, (\n            tuple, list)) else kernel_size\n        self._r = 1 + (_kernel_size - 1) * _dilation\n        super().__init__(\n            in_channels,\n            out_channels,\n            kernel_size,\n            padding=(self._r - 1, 0),\n            dilation=dilation,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=\"NCL\")\n\n    @property\n    def receptive_field(self):\n        \"\"\"The receptive field of the Conv1dCell.\n        \"\"\"\n        return self._r\n\n    def start_sequence(self):\n        \"\"\"Prepare the layer for a series of incremental forward.\n        \n        Warnings:\n            This method should be called before a sequence of calls to\n            ``add_input``.\n\n        Raises:\n            Exception\n                If this method is called when the layer is in training mode.\n        \"\"\"\n        if self.training:\n            raise Exception(\"only use start_sequence in evaluation\")\n        self._buffer = None\n\n        # NOTE: call self's weight norm hook expliccitly since self.weight \n        # is visited directly in this method without calling self.__call__ \n        # method. If we do not trigger the weight norm hook, the weight \n        # may be outdated. e.g. after loading from a saved checkpoint\n        # see also: https://github.com/pytorch/pytorch/issues/47588\n        for hook in self._forward_pre_hooks.values():\n            hook(self, None)\n        self._reshaped_weight = paddle.reshape(self.weight,\n                                               (self._out_channels, -1))\n\n    def initialize_buffer(self, x_t):\n        \"\"\"Initialize the buffer for the step input.\n\n        Args:\n            x_t (Tensor): \n                The step input. shape=(batch_size, in_channels)\n            \n        \"\"\"\n        batch_size, _ = x_t.shape\n        self._buffer = paddle.zeros(\n            (batch_size, self._in_channels, self.receptive_field),\n            dtype=x_t.dtype)\n\n    def update_buffer(self, x_t):\n        \"\"\"Shift the buffer by one step.\n\n        Args:\n            x_t (Tensor): T\n                he step input. shape=(batch_size, in_channels)\n            \n        \"\"\"\n        self._buffer = paddle.concat(\n            [self._buffer[:, :, 1:], paddle.unsqueeze(x_t, -1)], -1)\n\n    def add_input(self, x_t):\n        \"\"\"Add step input and compute step output.\n\n        Args:\n            x_t (Tensor): \n                The step input. shape=(batch_size, in_channels)\n          \n        Returns: \n            y_t (Tensor): \n                The step output. shape=(batch_size, out_channels)\n\n        \"\"\"\n        batch_size = x_t.shape[0]\n        if self.receptive_field > 1:\n            if self._buffer is None:\n                self.initialize_buffer(x_t)\n\n            # update buffer\n            self.update_buffer(x_t)\n            if self._dilation[0] > 1:\n                input = self._buffer[:, :, ::self._dilation[0]]\n            else:\n                input = self._buffer\n            input = paddle.reshape(input, (batch_size, -1))\n        else:\n            input = x_t\n        y_t = paddle.matmul(input, self._reshaped_weight, transpose_y=True)\n        y_t = y_t + self.bias\n        return y_t\n\n\nclass Conv1dBatchNorm(nn.Layer):\n    \"\"\"A Conv1D Layer followed by a BatchNorm1D.\n\n    Args:\n        in_channels (int): \n            The feature size of the input.\n        out_channels (int): \n            The feature size of the output.\n        kernel_size (int): \n            The size of the convolution kernel.\n        stride (int, optional): \n            The stride of the convolution, by default 1.\n        padding (int, str or Tuple[int], optional):\n            The padding of the convolution.\n            If int, a symmetrical padding is applied before convolution;\n            If str, it should be \"same\" or \"valid\";\n            If Tuple[int], its length should be 2, meaning\n            ``(pad_before, pad_after)``, by default 0.\n        weight_attr (ParamAttr, Initializer, str or bool, optional):\n            The parameter attribute of the convolution kernel,\n            by default None.\n        bias_attr (ParamAttr, Initializer, str or bool, optional):\n            The parameter attribute of the bias of the convolution,\n            by defaultNone.\n        data_format (str [\"NCL\" or \"NLC\"], optional): \n            The data layout of the input, by default \"NCL\"\n        momentum (float, optional): \n            The momentum of the BatchNorm1D layer, by default 0.9\n        epsilon (float, optional): \n            The epsilon of the BatchNorm1D layer, by default 1e-05\n    \"\"\"\n\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 kernel_size,\n                 stride=1,\n                 padding=0,\n                 weight_attr=None,\n                 bias_attr=None,\n                 data_format=\"NCL\",\n                 momentum=0.9,\n                 epsilon=1e-05):\n        super().__init__()\n        self.conv = nn.Conv1D(\n            in_channels,\n            out_channels,\n            kernel_size,\n            stride,\n            padding=padding,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format)\n        self.bn = nn.BatchNorm1D(\n            out_channels,\n            momentum=momentum,\n            epsilon=epsilon,\n            data_format=data_format)\n\n    def forward(self, x):\n        \"\"\"Forward pass of the Conv1dBatchNorm layer.\n        \n        Args:\n            x (Tensor): \n                The input tensor. Its data layout depends on ``data_format``. \n                shape=(B, C_in, T_in) or (B, T_in, C_in)\n    \n        Returns:\n            Tensor: \n                The output tensor. shape=(B, C_out, T_out) or (B, T_out, C_out)\n                \n        \"\"\"\n        x = self.conv(x)\n        x = self.bn(x)\n        return x\n"
  },
  {
    "path": "paddlespeech/t2s/modules/diffnet.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.utils.initialize import _calculate_fan_in_and_fan_out\nfrom paddlespeech.utils.initialize import kaiming_normal_\nfrom paddlespeech.utils.initialize import kaiming_uniform_\nfrom paddlespeech.utils.initialize import uniform_\nfrom paddlespeech.utils.initialize import zeros_\n\n\ndef Conv1D(*args, **kwargs):\n    layer = nn.Conv1D(*args, **kwargs)\n    # Initialize the weight to be consistent with the official\n    kaiming_normal_(layer.weight)\n\n    # Initialization is consistent with torch\n    if layer.bias is not None:\n        fan_in, _ = _calculate_fan_in_and_fan_out(layer.weight)\n        if fan_in != 0:\n            bound = 1 / math.sqrt(fan_in)\n            uniform_(layer.bias, -bound, bound)\n    return layer\n\n\n# Initialization is consistent with torch\ndef Linear(*args, **kwargs):\n    layer = nn.Linear(*args, **kwargs)\n    kaiming_uniform_(layer.weight, a=math.sqrt(5))\n    if layer.bias is not None:\n        fan_in, _ = _calculate_fan_in_and_fan_out(layer.weight)\n        bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0\n        uniform_(layer.bias, -bound, bound)\n    return layer\n\n\nclass ResidualBlock(nn.Layer):\n    \"\"\"ResidualBlock\n\n    Args:\n        encoder_hidden (int, optional): \n            Input feature size of the 1D convolution, by default 256\n        residual_channels (int, optional): \n            Feature size of the residual output(and also the input), by default 256\n        gate_channels (int, optional): \n            Output feature size of the 1D convolution, by default 512\n        kernel_size (int, optional): \n            Kernel size of the 1D convolution, by default 3\n        dilation (int, optional): \n            Dilation of the 1D convolution, by default 4\n    \"\"\"\n\n    def __init__(self,\n                 encoder_hidden: int=256,\n                 residual_channels: int=256,\n                 gate_channels: int=512,\n                 kernel_size: int=3,\n                 dilation: int=4):\n        super().__init__()\n        self.dilated_conv = Conv1D(\n            residual_channels,\n            gate_channels,\n            kernel_size,\n            padding=dilation,\n            dilation=dilation)\n        self.diffusion_projection = Linear(residual_channels, residual_channels)\n        self.conditioner_projection = Conv1D(encoder_hidden, gate_channels, 1)\n        self.output_projection = Conv1D(residual_channels, gate_channels, 1)\n\n    def forward(\n            self,\n            x: paddle.Tensor,\n            diffusion_step: paddle.Tensor,\n            cond: paddle.Tensor, ):\n        \"\"\"Calculate forward propagation.\n        Args:\n            spec (Tensor(float32)): input feature. (B, residual_channels, T)\n            diffusion_step (Tensor(int64)):  The timestep input (adding noise step). (B,)\n            cond (Tensor(float32)): The auxiliary input (e.g. fastspeech2 encoder output). (B, residual_channels, T)\n\n        Returns:\n            x (Tensor(float32)): output (B, residual_channels, T)\n\n        \"\"\"\n        diffusion_step = self.diffusion_projection(diffusion_step).unsqueeze(-1)\n        cond = self.conditioner_projection(cond)\n        y = x + diffusion_step\n\n        y = self.dilated_conv(y) + cond\n\n        gate, filter = paddle.chunk(y, 2, axis=1)\n        y = F.sigmoid(gate) * paddle.tanh(filter)\n\n        y = self.output_projection(y)\n        residual, skip = paddle.chunk(y, 2, axis=1)\n        return (x + residual) / math.sqrt(2.0), skip\n\n\nclass SinusoidalPosEmb(nn.Layer):\n    \"\"\"Positional embedding\n    \"\"\"\n\n    def __init__(self, dim: int=256):\n        super().__init__()\n        self.dim = dim\n\n    def forward(self, x: paddle.Tensor):\n        # check if x is 0-dim tensor, if so, add a dimension\n        if x.ndim == 0:\n            x = paddle.cast(x.unsqueeze(0), 'float32')\n        else:\n            x = paddle.cast(x, 'float32')\n        half_dim = self.dim // 2\n        emb = math.log(10000) / (half_dim - 1)\n        emb = paddle.exp(paddle.arange(half_dim) * -emb)\n        emb = x[:, None] * emb[None, :]\n        emb = paddle.concat([emb.sin(), emb.cos()], axis=-1)\n        return emb\n\n\nclass DiffNet(nn.Layer):\n    \"\"\"A Mel-Spectrogram Denoiser\n\n    Args:\n        in_channels (int, optional): \n            Number of channels of the input mel-spectrogram, by default 80\n        out_channels (int, optional): \n            Number of channels of the output mel-spectrogram, by default 80\n        kernel_size (int, optional): \n            Kernel size of the residual blocks inside, by default 3\n        layers (int, optional): \n            Number of residual blocks inside, by default 20\n        stacks (int, optional):\n            The number of groups to split the residual blocks into, by default 5\n            Within each group, the dilation of the residual block grows exponentially.\n        residual_channels (int, optional): \n            Residual channel of the residual blocks, by default 256\n        gate_channels (int, optional): \n            Gate channel of the residual blocks, by default 512\n        skip_channels (int, optional): \n            Skip channel of the residual blocks, by default 256\n        aux_channels (int, optional): \n            Auxiliary channel of the residual blocks, by default 256\n        dropout (float, optional): \n            Dropout of the residual blocks, by default 0.\n        bias (bool, optional): \n            Whether to use bias in residual blocks, by default True\n        use_weight_norm (bool, optional): \n            Whether to use weight norm in all convolutions, by default False\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=80,\n            out_channels: int=80,\n            kernel_size: int=3,\n            layers: int=20,\n            stacks: int=5,\n            residual_channels: int=256,\n            gate_channels: int=512,\n            skip_channels: int=256,\n            aux_channels: int=256,\n            dropout: float=0.,\n            bias: bool=True,\n            use_weight_norm: bool=False,\n            init_type: str=\"kaiming_normal\", ):\n        super().__init__()\n\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.layers = layers\n        self.aux_channels = aux_channels\n        self.residual_channels = residual_channels\n        self.gate_channels = gate_channels\n        self.kernel_size = kernel_size\n        self.dilation_cycle_length = layers // stacks\n        self.skip_channels = skip_channels\n\n        self.input_projection = Conv1D(self.in_channels, self.residual_channels,\n                                       1)\n        self.diffusion_embedding = SinusoidalPosEmb(self.residual_channels)\n        dim = self.residual_channels\n        self.mlp = nn.Sequential(\n            Linear(dim, dim * 4), nn.Mish(), Linear(dim * 4, dim))\n        self.residual_layers = nn.LayerList([\n            ResidualBlock(\n                encoder_hidden=self.aux_channels,\n                residual_channels=self.residual_channels,\n                gate_channels=self.gate_channels,\n                kernel_size=self.kernel_size,\n                dilation=2**(i % self.dilation_cycle_length))\n            for i in range(self.layers)\n        ])\n        self.skip_projection = Conv1D(self.residual_channels,\n                                      self.skip_channels, 1)\n        self.output_projection = Conv1D(self.residual_channels,\n                                        self.out_channels, 1)\n        zeros_(self.output_projection.weight)\n\n    def forward(\n            self,\n            spec: paddle.Tensor,\n            diffusion_step: paddle.Tensor,\n            cond: paddle.Tensor, ):\n        \"\"\"Calculate forward propagation.\n        Args:\n            spec (Tensor(float32)): The input mel-spectrogram. (B, n_mel, T)\n            diffusion_step (Tensor(int64)):  The timestep input (adding noise step). (B,)\n            cond (Tensor(float32)): The auxiliary input (e.g. fastspeech2 encoder output). (B, D_enc_out, T)\n\n        Returns:\n            x (Tensor(float32)): pred noise (B, n_mel, T)\n\n        \"\"\"\n        x = spec\n        x = self.input_projection(x)  # x [B, residual_channel, T]\n\n        x = F.relu(x)\n        diffusion_step = self.diffusion_embedding(diffusion_step)\n        diffusion_step = self.mlp(diffusion_step)\n        skip = []\n        for layer_id, layer in enumerate(self.residual_layers):\n            x, skip_connection = layer(\n                x=x,\n                diffusion_step=diffusion_step,\n                cond=cond, )\n            skip.append(skip_connection)\n        x = paddle.sum(\n            paddle.stack(skip), axis=0) / math.sqrt(len(self.residual_layers))\n        x = self.skip_projection(x)\n        x = F.relu(x)\n        x = self.output_projection(x)  # [B, 80, T]\n        return x\n"
  },
  {
    "path": "paddlespeech/t2s/modules/diffusion.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Diffusion denoising related modules for paddle\"\"\"\nfrom typing import Callable\nfrom typing import Optional\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nimport ppdiffusers\nfrom paddle import nn\nfrom ppdiffusers.schedulers import DDPMScheduler\n\n\nclass GaussianDiffusion(nn.Layer):\n    \"\"\"Common Gaussian Diffusion Denoising Model Module \n\n    Args:\n        denoiser (Layer, optional): \n            The model used for denoising noises.\n        num_train_timesteps (int, optional): \n            The number of timesteps between the noise and the real during training, by default 1000.\n        beta_start (float, optional): \n            beta start parameter for the scheduler, by default 0.0001.\n        beta_end (float, optional): \n            beta end parameter for the scheduler, by default 0.0001.\n        beta_schedule (str, optional): \n            beta schedule parameter for the scheduler, by default 'squaredcos_cap_v2' (cosine schedule).\n        num_max_timesteps (int, optional): \n            The max timestep transition from real to noise, by default None.\n        stretch (bool, optional): \n            Whether to stretch before diffusion, by default True.\n        min_values: (paddle.Tensor):\n            The minimum value of the feature to stretch.\n        max_values: (paddle.Tensor):\n            The maximum value of the feature to stretch.\n    \n    \n    Examples: \n        >>> import paddle\n        >>> import paddle.nn.functional as F\n        >>> from tqdm import tqdm\n        >>> \n        >>> denoiser = WaveNetDenoiser()\n        >>> diffusion = GaussianDiffusion(denoiser, num_train_timesteps=1000, num_max_timesteps=100)\n        >>> x = paddle.ones([4, 80, 192]) # [B, mel_ch, T] # real mel input\n        >>> c = paddle.randn([4, 256, 192]) # [B, fs2_encoder_out_ch, T] # fastspeech2 encoder output\n        >>> loss = F.mse_loss(*diffusion(x, c))\n        >>> loss.backward()\n        >>> print('MSE Loss:', loss.item())\n        MSE Loss: 1.6669728755950928 \n        >>> def create_progress_callback():\n        >>>     pbar = None\n        >>>     def callback(index, timestep, num_timesteps, sample):\n        >>>         nonlocal pbar\n        >>>         if pbar is None:\n        >>>             pbar = tqdm(total=num_timesteps)\n        >>>             pbar.update(index)\n        >>>         pbar.update()\n        >>> \n        >>>     return callback\n        >>> \n        >>> # ds=1000, K_step=60, scheduler=ddpm, from aux fs2 mel output\n        >>> ds = 1000\n        >>> infer_steps = 1000\n        >>> K_step = 60\n        >>> scheduler_type = 'ddpm'\n        >>> x_in = x\n        >>> diffusion = GaussianDiffusion(denoiser, num_train_timesteps=ds, num_max_timesteps=K_step)\n        >>> with paddle.no_grad():\n        >>>     sample = diffusion.inference(\n        >>>         paddle.randn(x.shape), c, ref_x=x_in, \n        >>>         num_inference_steps=infer_steps,\n        >>>         scheduler_type=scheduler_type,\n        >>>         callback=create_progress_callback())\n        100%|█████| 60/60 [00:03<00:00, 18.36it/s] \n        >>> \n        >>> # ds=100, K_step=100, scheduler=ddpm, from gaussian noise\n        >>> ds = 100\n        >>> infer_steps = 100\n        >>> K_step = 100\n        >>> scheduler_type = 'ddpm'\n        >>> x_in = None\n        >>> diffusion = GaussianDiffusion(denoiser, num_train_timesteps=ds, num_max_timesteps=K_step)\n        >>> with paddle.no_grad():\n        >>>     sample = diffusion.inference(\n        >>>         paddle.randn(x.shape), c, ref_x=x_in, \n        >>>         num_inference_steps=infer_steps,\n        >>>         scheduler_type=scheduler_type,\n        >>>         callback=create_progress_callback())\n        100%|█████| 100/100 [00:05<00:00, 18.29it/s] \n        >>> \n        >>> # ds=1000, K_step=1000, scheduler=pndm, infer_step=25, from gaussian noise\n        >>> ds = 1000\n        >>> infer_steps = 25\n        >>> K_step = 1000\n        >>> scheduler_type = 'pndm'\n        >>> x_in = None\n        >>> diffusion = GaussianDiffusion(denoiser, num_train_timesteps=ds, num_max_timesteps=K_step)\n        >>> with paddle.no_grad():\n        >>>     sample = diffusion.inference(\n        >>>         paddle.randn(x.shape), c, ref_x=x_in, \n        >>>         num_inference_steps=infer_steps,\n        >>>         scheduler_type=scheduler_type,\n        >>>         callback=create_progress_callback())\n        100%|█████| 34/34 [00:01<00:00, 19.75it/s]\n        >>> \n        >>> # ds=1000, K_step=100, scheduler=pndm, infer_step=50, from aux fs2 mel output\n        >>> ds = 1000\n        >>> infer_steps = 50\n        >>> K_step = 100\n        >>> scheduler_type = 'pndm'\n        >>> x_in = x\n        >>> diffusion = GaussianDiffusion(denoiser, num_train_timesteps=ds, num_max_timesteps=K_step)\n        >>> with paddle.no_grad():\n        >>>     sample = diffusion.inference(\n        >>>         paddle.randn(x.shape), c, ref_x=x_in, \n        >>>         num_inference_steps=infer_steps,\n        >>>         scheduler_type=scheduler_type,\n        >>>         callback=create_progress_callback())\n        100%|█████| 14/14 [00:00<00:00, 23.80it/s]\n\n    \"\"\"\n\n    def __init__(\n            self,\n            denoiser: nn.Layer,\n            num_train_timesteps: Optional[int]=1000,\n            beta_start: Optional[float]=0.0001,\n            beta_end: Optional[float]=0.02,\n            beta_schedule: Optional[str]=\"squaredcos_cap_v2\",\n            num_max_timesteps: Optional[int]=None,\n            stretch: bool=True,\n            min_values: paddle.Tensor=None,\n            max_values: paddle.Tensor=None, ):\n        super().__init__()\n\n        self.num_train_timesteps = num_train_timesteps\n        self.beta_start = beta_start\n        self.beta_end = beta_end\n        self.beta_schedule = beta_schedule\n\n        self.denoiser = denoiser\n        self.noise_scheduler = DDPMScheduler(\n            num_train_timesteps=num_train_timesteps,\n            beta_start=beta_start,\n            beta_end=beta_end,\n            beta_schedule=beta_schedule)\n        self.num_max_timesteps = num_max_timesteps\n        self.stretch = stretch\n        self.min_values = min_values\n        self.max_values = max_values\n\n    def norm_spec(self, x):\n        \"\"\"\n        Linearly map x to [-1, 1]\n        Args:\n            x: [B, T, N]\n        \"\"\"\n        return (x - self.min_values) / (self.max_values - self.min_values\n                                        ) * 2 - 1\n\n    def denorm_spec(self, x):\n        return (x + 1) / 2 * (self.max_values - self.min_values\n                              ) + self.min_values\n\n    def forward(self, x: paddle.Tensor, cond: Optional[paddle.Tensor]=None\n                ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n        \"\"\"Generate random timesteps noised x.\n\n        Args:\n            x (Tensor): \n                The input for adding noises.\n            cond (Tensor, optional):\n                Conditional input for compute noises.\n          \n        Returns: \n            y (Tensor): \n                The output with noises added in.\n            target (Tensor):\n                The noises which is added to the input.\n\n        \"\"\"\n        if self.stretch:\n            x = x.transpose((0, 2, 1))\n            x = self.norm_spec(x)\n            x = x.transpose((0, 2, 1))\n\n        noise_scheduler = self.noise_scheduler\n\n        # Sample noise that we'll add to the mel-spectrograms\n        target = noise = paddle.randn(x.shape)\n\n        # Sample a random timestep for each mel-spectrogram\n        num_timesteps = self.num_train_timesteps\n        if self.num_max_timesteps is not None:\n            num_timesteps = self.num_max_timesteps\n        timesteps = paddle.randint(0, num_timesteps, (x.shape[0], ))\n\n        # Add noise to the clean mel-spectrograms according to the noise magnitude at each timestep\n        # (this is the forward diffusion process)\n        noisy_images = noise_scheduler.add_noise(x, noise, timesteps)\n\n        y = self.denoiser(noisy_images, timesteps, cond)\n\n        # then compute loss use output y and noisy target for prediction_type == \"epsilon\"\n        return y, target\n\n    def inference(self,\n                  noise: paddle.Tensor,\n                  cond: Optional[paddle.Tensor]=None,\n                  ref_x: Optional[paddle.Tensor]=None,\n                  num_inference_steps: Optional[int]=1000,\n                  strength: Optional[float]=None,\n                  scheduler_type: Optional[str]=\"ddpm\",\n                  clip_noise: Optional[bool]=False,\n                  clip_noise_range: Optional[Tuple[float, float]]=(-1, 1),\n                  callback: Optional[Callable[[int, int, int, paddle.Tensor],\n                                              None]]=None,\n                  callback_steps: Optional[int]=1):\n        \"\"\"Denoising input from noises. Refer to ppdiffusers img2img pipeline.\n\n        Args:\n            noise (Tensor): \n                The input tensor as a starting point for denoising. \n            cond (Tensor, optional):\n                Conditional input for compute noises. (N, C_aux, T)\n            ref_x (Tensor, optional):\n                The real output for the denoising process to refer.\n            num_inference_steps (int, optional):\n                The number of timesteps between the noise and the real during inference, by default 1000.\n            strength (float, optional):\n                Mixing strength of ref_x with noise. The larger the value, the stronger the noise. \n                Range [0,1], by default None.\n            scheduler_type (str, optional):\n                Noise scheduler for generate noises. \n                Choose a great scheduler can skip many denoising step, by default 'ddpm'.\n                only support 'ddpm' now !\n            clip_noise (bool, optional):\n                Whether to clip each denoised output, by default True.\n            clip_noise_range (tuple, optional):\n                denoised output min and max value range after clip, by default (-1, 1).\n            callback (Callable[[int,int,int,Tensor], None], optional):\n                Callback function during denoising steps.\n\n                Args:\n                    index (int):\n                        Current denoising index.\n                    timestep (int):\n                        Current denoising timestep.\n                    num_timesteps (int):\n                        Number of the denoising timesteps.\n                    denoised_output (Tensor):\n                        Current intermediate result produced during denoising.\n\n            callback_steps (int, optional):\n                The step to call the callback function.\n          \n        Returns: \n            denoised_output (Tensor): \n                The denoised output tensor.\n\n        \"\"\"\n        scheduler_cls = None\n        for clsname in dir(ppdiffusers.schedulers):\n            if clsname.lower() == scheduler_type + \"scheduler\":\n                scheduler_cls = getattr(ppdiffusers.schedulers, clsname)\n                break\n\n        if scheduler_cls is None:\n            raise ValueError(f\"No such scheduler type named {scheduler_type}\")\n\n        scheduler = scheduler_cls(\n            num_train_timesteps=self.num_train_timesteps,\n            beta_start=self.beta_start,\n            beta_end=self.beta_end,\n            beta_schedule=self.beta_schedule)\n\n        # set timesteps\n        scheduler.set_timesteps(num_inference_steps)\n\n        noisy_input = noise\n        if self.stretch and ref_x is not None:\n            ref_x = ref_x.transpose((0, 2, 1))\n            ref_x = self.norm_spec(ref_x)\n            ref_x = ref_x.transpose((0, 2, 1))\n\n            # for ddpm\n            timesteps = paddle.to_tensor(\n                np.flipud(np.arange(num_inference_steps)))\n            noisy_input = scheduler.add_noise(ref_x, noise, timesteps[0])\n\n        denoised_output = noisy_input\n        if clip_noise:\n            n_min, n_max = clip_noise_range\n            denoised_output = paddle.clip(denoised_output, n_min, n_max)\n        for i, t in enumerate(timesteps):\n            denoised_output = scheduler.scale_model_input(denoised_output, t)\n            noise_pred = self.denoiser(denoised_output, t, cond)\n            # compute the previous noisy sample x_t -> x_t-1\n            denoised_output = scheduler.step(noise_pred, t,\n                                             denoised_output).prev_sample\n            if clip_noise:\n                denoised_output = paddle.clip(denoised_output, n_min, n_max)\n\n        if self.stretch:\n            denoised_output = denoised_output.transpose((0, 2, 1))\n            denoised_output = self.denorm_spec(denoised_output)\n            denoised_output = denoised_output.transpose((0, 2, 1))\n\n        return denoised_output\n"
  },
  {
    "path": "paddlespeech/t2s/modules/fftconv1d.py",
    "content": "# Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport typing\nfrom typing import Optional\nfrom typing import Sequence\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom ...utils import satisfy_paddle_version\n\n__all__ = [\n    \"fft_conv1d\",\n    \"FFTConv1D\",\n]\n\n\ndef __unfold(x, kernel_size: int, stride: int):\n    \"\"\"1D only unfolding similar to the one from Paddlepaddle.\n\n    Notes\n    ------\n    Given a tensor `x` of size `[*, T]` this will return\n    a tensor `[*, F, K]` with `K` the kernel size, and `F` the number\n    of frames. The i-th frame is a view onto `i * stride: i * stride + kernel_size`.\n    This will automatically pad `x` to cover at least once all entries in `x`.\n\n    Args:\n        x (Tensor): \n            tensor for which to return the frames.\n        kernel_size (int): \n            size of each frame.\n        stride (int): \n            stride between each frame.\n    \"\"\"\n    shape = list(x.shape)\n    length = shape.pop(-1)\n    n_frames = math.ceil((max(length, kernel_size) - kernel_size) / stride) + 1\n    tgt_length = (n_frames - 1) * stride + kernel_size\n    padded = F.pad(x, (0, tgt_length - length), data_format=\"NCL\")\n    strides: typing.List[int] = []\n    for dim in range(padded.dim()):\n        strides.append(padded.strides[dim])\n    assert strides.pop(-1) == 1, \"data should be contiguous\"\n    strides = strides + [stride, 1]\n    return padded.as_strided(shape + [n_frames, kernel_size], strides)\n\n\ndef fft_conv1d(\n        x: paddle.Tensor,\n        weight: paddle.Tensor,\n        bias: Optional[paddle.Tensor]=None,\n        stride: int=1,\n        padding: int=0,\n        block_ratio: float=5, ):\n    \"\"\"\n    Same as `paddle.nn.functional.conv1d` but using FFT for the convolution.\n    Please check PaddlePaddle documentation for more information.\n\n    Notes\n    ------\n    This function is faster than `paddle.nn.functional.conv1d` only in specific cases.\n    Typically, the kernel size should be of the order of 256 to see any real gain,\n    for a stride of 1.\n    Dilation and groups are not supported at the moment. This function might use\n    more memory than the default Conv1d implementation.\n\n    Args:\n        x (Tensor): \n            x signal of shape `[B, C, T]`.\n        weight (Tensor): \n            weight of the convolution `[D, C, K]` with `D` the number of output channels.\n        bias (Tensor or None): \n            if not None, bias term for the convolution.\n        stride (int): \n            stride of convolution.\n        padding (int): \n            padding to apply to x.\n        block_ratio (float): \n            can be tuned for speed. x is splitted in chunks with a size of `int(block_ratio * kernel_size)`.\n\n    Shape:\n\n        - Inputs: `x` is `[B, C, T]`, `weight` is `[D, C, K]` and bias is `[D]`.\n        - Output: `(*, T)`\n    \"\"\"\n    x = F.pad(x, (padding, padding), data_format=\"NCL\")\n    batch, _, length = x.shape\n    out_channels, _, kernel_size = weight.shape\n\n    if length < kernel_size:\n        raise RuntimeError(\n            f\"Input should be at least as large as the kernel size {kernel_size}, \"\n            f\"but it is only {length} samples long.\")\n    if block_ratio < 1:\n        raise RuntimeError(\"Block ratio must be greater than 1.\")\n\n    block_size: int = min(int(kernel_size * block_ratio), length)\n    fold_stride = block_size - kernel_size + 1\n    # weight = pad_to(weight, block_size)\n\n    weight = F.pad(\n        weight, (0, block_size - weight.shape[-1]),\n        mode=\"constant\",\n        value=0.0,\n        data_format=\"NCL\")\n\n    weight_z = paddle.fft.rfft(weight, axis=-1)\n\n    # We pad `x` and get the different frames, on which\n    frames = __unfold(x, block_size, fold_stride)\n\n    frames_z = paddle.fft.rfft(frames, axis=-1)\n    weight_z_coml = paddle.conj(weight_z)\n    out_z = paddle.einsum(\"bcft,dct->bdft\", frames_z, weight_z_coml)\n    out = paddle.fft.irfft(out_z, n=block_size, axis=-1)\n\n    # The last bit is invalid, because FFT will do a circular convolution.\n    out = out[..., :-kernel_size + 1]\n    out = out.reshape([batch, out_channels, -1])\n    out = out[..., ::stride]\n    target_length = (length - kernel_size) // stride + 1\n    out = out[..., :target_length]\n    if bias is not None:\n        out += bias[:, None]\n    return out\n\n\nclass FFTConv1D(paddle.nn.Layer):\n    \"\"\"\n    Same as `paddle.nn.Conv1D` but based on a custom FFT-based convolution.\n    Please check PaddlePaddle documentation for more information on `paddle.nn.Conv1D`.\n\n    Notes\n    ------\n    This module is faster than `paddle.nn.Conv1D` only in specific cases.\n    Typically, `kernel_size` should be of the order of 256 to see any real gain,\n    for a stride of 1.\n    Dilation and groups are not supported at the moment. This module might use\n    more memory than the default Conv1D implementation.\n\n    Args:\n        in_channels (int): \n            number of `x` channels.\n        out_channels (int): \n            number of output channels.\n        kernel_size (int): \n            kernel size of convolution.\n        stride (int): \n            stride of convolution.\n        padding (int): \n            padding to apply to `x`.\n        bias_attr (bool): \n            if True, use a bias term.\n\n    Examples: \n        >>> fftconv = FFTConv1D(12, 24, 128, 4)\n        >>> x = paddle.randn([4, 12, 1024])\n        >>> print(list(fftconv(x).shape))\n        [4, 24, 225]\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int,\n            out_channels: int,\n            kernel_size: int,\n            stride: int=1,\n            padding: int=0,\n            bias_attr: bool=True, ):\n        super(FFTConv1D, self).__init__()\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.kernel_size = kernel_size\n        self.stride = stride\n        self.padding = padding\n\n        # Create a Conv1D layer to initialize weights and bias\n        conv = paddle.nn.Conv1D(\n            in_channels,\n            out_channels,\n            kernel_size,\n            stride=stride,\n            padding=padding,\n            bias_attr=bias_attr)\n        self.weight = conv.weight\n        if bias_attr:\n            self.bias = conv.bias\n        else:\n            self.bias = None\n\n    def forward(self, x: paddle.Tensor):\n        return fft_conv1d(x, self.weight, self.bias, self.stride, self.padding)\n\n\n# Currently, the API unfold in Paddle is extremely slow, so __unfold is implemented \n# using the `.strides` and `.as_strided` APIs. However, these are only supported in \n# Paddle version 2.6 and above, so F.conv1d and Conv1D are used as replacements.\nif not satisfy_paddle_version('2.6'):\n    fft_conv1d = F.conv1d\n    FFTConv1D = nn.Conv1D\n"
  },
  {
    "path": "paddlespeech/t2s/modules/geometry.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\n\n\ndef shuffle_dim(x, axis, perm=None):\n    \"\"\"Permute input tensor along aixs given the permutation or randomly.\n    \n    Args:\n        x (Tensor): \n            The input tensor.\n        axis (int): \n            The axis to shuffle.\n        perm (List[int], ndarray, optional): \n            The order to reorder the tensor along the ``axis``-th dimension.\n            It is a permutation of ``[0, d)``, where d is the size of the\n            ``axis``-th dimension of the input tensor. If not provided,\n            a random permutation is used. Defaults to None.\n\n    Returns:\n        Tensor: The shuffled tensor, which has the same shape as x does.\n    \"\"\"\n    size = x.shape[axis]\n    if perm is not None and len(perm) != size:\n        raise ValueError(\"length of permutation should equals the input \"\n                         \"tensor's axis-th dimension's size\")\n    if perm is not None:\n        perm = np.array(perm)\n    else:\n        perm = np.random.permutation(size)\n\n    perm = paddle.to_tensor(perm)\n    out = paddle.gather(x, perm, axis)\n    return out\n"
  },
  {
    "path": "paddlespeech/t2s/modules/layer_norm.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Layer normalization module.\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass LayerNorm(nn.LayerNorm):\n    \"\"\"Layer normalization module.\n    Args:\n        nout (int): \n            Output dim size.\n        dim (int): \n            Dimension to be normalized.\n    \"\"\"\n\n    def __init__(self, nout, dim=-1):\n        \"\"\"Construct an LayerNorm object.\"\"\"\n        super().__init__(nout)\n        self.dim = dim\n\n    def forward(self, x):\n        \"\"\"Apply layer normalization.\n\n        Args:\n            x (Tensor):\n                Input tensor.\n\n        Returns: \n            Tensor: Normalized tensor.\n        \"\"\"\n\n        if self.dim == -1:\n            return super(LayerNorm, self).forward(x)\n        else:\n            len_dim = len(x.shape)\n            if self.dim < 0:\n                self.dim = len_dim + self.dim\n            assert self.dim >= 0\n\n            orig_perm = list(range(len_dim))\n            new_perm = orig_perm[:]\n            # Python style item change is not able when converting dygraph to static graph.\n            # new_perm[self.dim], new_perm[len_dim -1] = new_perm[len_dim -1], new_perm[self.dim]\n            # use C++ style item change here\n            temp = new_perm[self.dim]\n            new_perm[self.dim] = new_perm[len_dim - 1]\n            new_perm[len_dim - 1] = temp\n\n            return paddle.transpose(\n                super(LayerNorm, self).forward(paddle.transpose(x, new_perm)),\n                new_perm)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/losses.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nfrom typing import Callable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\nimport librosa\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\nfrom scipy import signal\nfrom scipy.stats import betabinom\nfrom typeguard import typechecked\n\nfrom paddlespeech.audiotools.core.audio_signal import AudioSignal\nfrom paddlespeech.audiotools.core.audio_signal import STFTParams\nfrom paddlespeech.t2s.modules.nets_utils import make_non_pad_mask\nfrom paddlespeech.t2s.modules.predictor.duration_predictor import (\n    DurationPredictorLoss,  # noqa: H301\n)\n\n\n# Losses for WaveRNN\ndef log_sum_exp(x):\n    \"\"\" numerically stable log_sum_exp implementation that prevents overflow \"\"\"\n    # TF ordering\n    axis = len(x.shape) - 1\n    m = paddle.max(x, axis=axis)\n    m2 = paddle.max(x, axis=axis, keepdim=True)\n    return m + paddle.log(paddle.sum(paddle.exp(x - m2), axis=axis))\n\n\n# It is adapted from https://github.com/r9y9/wavenet_vocoder/blob/master/wavenet_vocoder/mixture.py\ndef discretized_mix_logistic_loss(y_hat,\n                                  y,\n                                  num_classes=65536,\n                                  log_scale_min=None,\n                                  reduce=True):\n    if log_scale_min is None:\n        log_scale_min = float(np.log(1e-14))\n    y_hat = y_hat.transpose([0, 2, 1])\n    assert y_hat.dim() == 3\n    assert y_hat.shape[1] % 3 == 0\n    nr_mix = y_hat.shape[1] // 3\n\n    # (B x T x C)\n    y_hat = y_hat.transpose([0, 2, 1])\n\n    # unpack parameters. (B, T, num_mixtures) x 3\n    logit_probs = y_hat[:, :, :nr_mix]\n    means = y_hat[:, :, nr_mix:2 * nr_mix]\n    log_scales = paddle.clip(\n        y_hat[:, :, 2 * nr_mix:3 * nr_mix], min=log_scale_min)\n\n    # B x T x 1 -> B x T x num_mixtures\n    y = y.expand_as(means)\n    centered_y = paddle.cast(y, dtype=paddle.get_default_dtype()) - means\n    inv_stdv = paddle.exp(-log_scales)\n    plus_in = inv_stdv * (centered_y + 1. / (num_classes - 1))\n    cdf_plus = F.sigmoid(plus_in)\n    min_in = inv_stdv * (centered_y - 1. / (num_classes - 1))\n    cdf_min = F.sigmoid(min_in)\n\n    # log probability for edge case of 0 (before scaling)\n    # equivalent: torch.log(F.sigmoid(plus_in))\n    # softplus: log(1+ e^{-x})\n    log_cdf_plus = plus_in - F.softplus(plus_in)\n\n    # log probability for edge case of 255 (before scaling)\n    # equivalent: (1 - F.sigmoid(min_in)).log()\n    log_one_minus_cdf_min = -F.softplus(min_in)\n\n    # probability for all other cases\n    cdf_delta = cdf_plus - cdf_min\n\n    mid_in = inv_stdv * centered_y\n    # log probability in the center of the bin, to be used in extreme cases\n    # (not actually used in our code)\n    log_pdf_mid = mid_in - log_scales - 2. * F.softplus(mid_in)\n\n    # TODO: cdf_delta <= 1e-5 actually can happen. How can we choose the value\n    # for num_classes=65536 case? 1e-7? not sure..\n    inner_inner_cond = cdf_delta > 1e-5\n\n    inner_inner_cond = paddle.cast(\n        inner_inner_cond, dtype=paddle.get_default_dtype())\n\n    # inner_inner_out = inner_inner_cond * \\\n    #                   paddle.log(paddle.clip(cdf_delta, min=1e-12)) + \\\n    #                   (1. - inner_inner_cond) * (log_pdf_mid - np.log((num_classes - 1) / 2))\n\n    inner_inner_out = inner_inner_cond * paddle.log(\n        paddle.clip(cdf_delta, min=1e-12)) + (1. - inner_inner_cond) * (\n            log_pdf_mid - np.log((num_classes - 1) / 2))\n\n    inner_cond = y > 0.999\n\n    inner_cond = paddle.cast(inner_cond, dtype=paddle.get_default_dtype())\n\n    inner_out = inner_cond * log_one_minus_cdf_min + (1. - inner_cond\n                                                      ) * inner_inner_out\n    cond = y < -0.999\n    cond = paddle.cast(cond, dtype=paddle.get_default_dtype())\n\n    log_probs = cond * log_cdf_plus + (1. - cond) * inner_out\n    log_probs = log_probs + F.log_softmax(logit_probs, -1)\n\n    if reduce:\n        return -paddle.mean(log_sum_exp(log_probs))\n    else:\n        return -log_sum_exp(log_probs).unsqueeze(-1)\n\n\ndef sample_from_discretized_mix_logistic(y, log_scale_min=None):\n    \"\"\"\n    Sample from discretized mixture of logistic distributions\n\n    Args:\n        y(Tensor): (B, C, T)\n        log_scale_min(float, optional):  (Default value = None)\n\n    Returns:\n        Tensor: sample in range of [-1, 1].\n    \"\"\"\n    if log_scale_min is None:\n        log_scale_min = float(np.log(1e-14))\n\n    assert y.shape[1] % 3 == 0\n    nr_mix = y.shape[1] // 3\n\n    # (B, T, C)\n    y = y.transpose([0, 2, 1])\n    logit_probs = y[:, :, :nr_mix]\n\n    # sample mixture indicator from softmax\n    temp = paddle.uniform(\n        logit_probs.shape, dtype=logit_probs.dtype, min=1e-5, max=1.0 - 1e-5)\n    temp = logit_probs - paddle.log(-paddle.log(temp))\n    argmax = paddle.argmax(temp, axis=-1)\n\n    # (B, T) -> (B, T, nr_mix)\n    one_hot = F.one_hot(argmax, nr_mix)\n    one_hot = paddle.cast(one_hot, dtype=paddle.get_default_dtype())\n\n    # select logistic parameters\n    means = paddle.sum(y[:, :, nr_mix:2 * nr_mix] * one_hot, axis=-1)\n    log_scales = paddle.clip(\n        paddle.sum(y[:, :, 2 * nr_mix:3 * nr_mix] * one_hot, axis=-1),\n        min=log_scale_min)\n    # sample from logistic & clip to interval\n    # we don't actually round to the nearest 8bit value when sampling\n    u = paddle.uniform(means.shape, min=1e-5, max=1.0 - 1e-5)\n    x = means + paddle.exp(log_scales) * (paddle.log(u) - paddle.log(1. - u))\n    x = paddle.clip(x, min=-1., max=-1.)\n\n    return x\n\n\n# Loss for Tacotron2\nclass GuidedAttentionLoss(nn.Layer):\n    \"\"\"Guided attention loss function module.\n\n    This module calculates the guided attention loss described\n    in `Efficiently Trainable Text-to-Speech System Based\n    on Deep Convolutional Networks with Guided Attention`_,\n    which forces the attention to be diagonal.\n\n    .. _`Efficiently Trainable Text-to-Speech System\n        Based on Deep Convolutional Networks with Guided Attention`:\n        https://arxiv.org/abs/1710.08969\n\n    \"\"\"\n\n    def __init__(self, sigma=0.4, alpha=1.0, reset_always=True):\n        \"\"\"Initialize guided attention loss module.\n\n        Args:\n            sigma (float, optional): Standard deviation to control how close attention to a diagonal.\n            alpha (float, optional): Scaling coefficient (lambda).\n            reset_always (bool, optional): Whether to always reset masks.\n\n        \"\"\"\n        super().__init__()\n        self.sigma = sigma\n        self.alpha = alpha\n        self.reset_always = reset_always\n        self.guided_attn_masks = None\n        self.masks = None\n\n    def _reset_masks(self):\n        self.guided_attn_masks = None\n        self.masks = None\n\n    def forward(self, att_ws, ilens, olens):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            att_ws(Tensor): Batch of attention weights (B, T_max_out, T_max_in).\n            ilens(Tensor(int64)): Batch of input lenghts (B,).\n            olens(Tensor(int64)): Batch of output lenghts (B,).\n\n        Returns:\n            Tensor: Guided attention loss value.\n\n        \"\"\"\n        if self.guided_attn_masks is None:\n            self.guided_attn_masks = self._make_guided_attention_masks(ilens,\n                                                                       olens)\n        if self.masks is None:\n            self.masks = self._make_masks(ilens, olens)\n        losses = self.guided_attn_masks * att_ws\n        loss = paddle.mean(\n            losses.masked_select(self.masks.broadcast_to(losses.shape)))\n        if self.reset_always:\n            self._reset_masks()\n        return self.alpha * loss\n\n    def _make_guided_attention_masks(self, ilens, olens):\n        n_batches = len(ilens)\n        max_ilen = max(ilens)\n        max_olen = max(olens)\n        guided_attn_masks = paddle.zeros((n_batches, max_olen, max_ilen))\n\n        for idx, (ilen, olen) in enumerate(zip(ilens, olens)):\n            guided_attn_masks[idx, :olen, :\n                              ilen] = self._make_guided_attention_mask(\n                                  ilen, olen, self.sigma)\n        return guided_attn_masks\n\n    @staticmethod\n    def _make_guided_attention_mask(ilen, olen, sigma):\n        \"\"\"Make guided attention mask.\n\n        Examples\n        ----------\n        >>> guided_attn_mask =_make_guided_attention(5, 5, 0.4)\n        >>> guided_attn_mask.shape\n        [5, 5]\n        >>> guided_attn_mask\n        tensor([[0.0000, 0.1175, 0.3935, 0.6753, 0.8647],\n                [0.1175, 0.0000, 0.1175, 0.3935, 0.6753],\n                [0.3935, 0.1175, 0.0000, 0.1175, 0.3935],\n                [0.6753, 0.3935, 0.1175, 0.0000, 0.1175],\n                [0.8647, 0.6753, 0.3935, 0.1175, 0.0000]])\n        >>> guided_attn_mask =_make_guided_attention(3, 6, 0.4)\n        >>> guided_attn_mask.shape\n        [6, 3]\n        >>> guided_attn_mask\n        tensor([[0.0000, 0.2934, 0.7506],\n                [0.0831, 0.0831, 0.5422],\n                [0.2934, 0.0000, 0.2934],\n                [0.5422, 0.0831, 0.0831],\n                [0.7506, 0.2934, 0.0000],\n                [0.8858, 0.5422, 0.0831]])\n\n        \"\"\"\n        grid_x, grid_y = paddle.meshgrid(\n            paddle.arange(olen), paddle.arange(ilen))\n        grid_x = grid_x.cast(dtype=paddle.float32)\n        grid_y = grid_y.cast(dtype=paddle.float32)\n        return 1.0 - paddle.exp(-(\n            (grid_y / ilen - grid_x / olen)**2) / (2 * (sigma**2)))\n\n    @staticmethod\n    def _make_masks(ilens, olens):\n        \"\"\"Make masks indicating non-padded part.\n\n        Args:\n            ilens(Tensor(int64) or List): \n                Batch of lengths (B,).\n            olens(Tensor(int64) or List): \n                Batch of lengths (B,).\n\n        Returns:\n            Tensor: Mask tensor indicating non-padded part.\n\n        Examples:\n            >>> ilens, olens = [5, 2], [8, 5]\n            >>> _make_mask(ilens, olens)\n            tensor([[[1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1],\n                    [1, 1, 1, 1, 1]],\n\n                    [[1, 1, 0, 0, 0],\n                    [1, 1, 0, 0, 0],\n                    [1, 1, 0, 0, 0],\n                    [1, 1, 0, 0, 0],\n                    [1, 1, 0, 0, 0],\n                    [0, 0, 0, 0, 0],\n                    [0, 0, 0, 0, 0],\n                    [0, 0, 0, 0, 0]]], dtype=paddle.uint8)\n\n        \"\"\"\n        # (B, T_in)\n        in_masks = make_non_pad_mask(ilens)\n        # (B, T_out)\n        out_masks = make_non_pad_mask(olens)\n        # (B, T_out, T_in)\n\n        return paddle.logical_and(\n            out_masks.unsqueeze(-1), in_masks.unsqueeze(-2))\n\n\nclass GuidedMultiHeadAttentionLoss(GuidedAttentionLoss):\n    \"\"\"Guided attention loss function module for multi head attention.\n\n    Args:\n        sigma (float, optional): Standard deviation to controlGuidedAttentionLoss\n            how close attention to a diagonal.\n        alpha (float, optional): Scaling coefficient (lambda).\n        reset_always (bool, optional): Whether to always reset masks.\n\n    \"\"\"\n\n    def forward(self, att_ws, ilens, olens):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            att_ws(Tensor): \n                Batch of multi head attention weights (B, H, T_max_out, T_max_in).\n            ilens(Tensor): \n                Batch of input lenghts (B,).\n            olens(Tensor): \n                Batch of output lenghts (B,).\n\n        Returns:\n            Tensor: Guided attention loss value.\n\n        \"\"\"\n        if self.guided_attn_masks is None:\n            self.guided_attn_masks = (\n                self._make_guided_attention_masks(ilens, olens).unsqueeze(1))\n        if self.masks is None:\n            self.masks = self._make_masks(ilens, olens).unsqueeze(1)\n        losses = self.guided_attn_masks * att_ws\n        loss = paddle.mean(\n            losses.masked_select(self.masks.broadcast_to(losses.shape)))\n        if self.reset_always:\n            self._reset_masks()\n\n        return self.alpha * loss\n\n\nclass Tacotron2Loss(nn.Layer):\n    \"\"\"Loss function module for Tacotron2.\"\"\"\n\n    def __init__(self,\n                 use_masking=True,\n                 use_weighted_masking=False,\n                 bce_pos_weight=20.0):\n        \"\"\"Initialize Tactoron2 loss module.\n\n        Args:\n            use_masking (bool): \n                Whether to apply masking for padded part in loss calculation.\n            use_weighted_masking (bool): \n                Whether to apply weighted masking in loss calculation.\n            bce_pos_weight (float): \n                Weight of positive sample of stop token.\n        \"\"\"\n        super().__init__()\n        assert (use_masking != use_weighted_masking) or not use_masking\n        self.use_masking = use_masking\n        self.use_weighted_masking = use_weighted_masking\n\n        # define criterions\n        reduction = \"none\" if self.use_weighted_masking else \"mean\"\n        self.l1_criterion = nn.L1Loss(reduction=reduction)\n        self.mse_criterion = nn.MSELoss(reduction=reduction)\n        self.bce_criterion = nn.BCEWithLogitsLoss(\n            reduction=reduction, pos_weight=paddle.to_tensor(bce_pos_weight))\n\n    def forward(self, after_outs, before_outs, logits, ys, stop_labels, olens):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            after_outs(Tensor): \n                Batch of outputs after postnets (B, Lmax, odim).\n            before_outs(Tensor): \n                Batch of outputs before postnets (B, Lmax, odim).\n            logits(Tensor): \n                Batch of stop logits (B, Lmax).\n            ys(Tensor): \n                Batch of padded target features (B, Lmax, odim).\n            stop_labels(Tensor(int64)): \n                Batch of the sequences of stop token labels (B, Lmax).\n            olens(Tensor(int64)): \n\n        Returns:\n            Tensor: \n                L1 loss value.\n            Tensor: \n                Mean square error loss value.\n            Tensor: \n                Binary cross entropy loss value.\n        \"\"\"\n        # make mask and apply it\n        if self.use_masking:\n            masks = make_non_pad_mask(olens).unsqueeze(-1)\n            ys = ys.masked_select(masks.broadcast_to(ys.shape))\n            after_outs = after_outs.masked_select(\n                masks.broadcast_to(after_outs.shape))\n            before_outs = before_outs.masked_select(\n                masks.broadcast_to(before_outs.shape))\n            stop_labels = stop_labels.masked_select(\n                masks[:, :, 0].broadcast_to(stop_labels.shape))\n            logits = logits.masked_select(\n                masks[:, :, 0].broadcast_to(logits.shape))\n\n        # calculate loss\n        l1_loss = self.l1_criterion(after_outs, ys) + self.l1_criterion(\n            before_outs, ys)\n        mse_loss = self.mse_criterion(after_outs, ys) + self.mse_criterion(\n            before_outs, ys)\n        bce_loss = self.bce_criterion(logits, stop_labels)\n\n        # make weighted mask and apply it\n        if self.use_weighted_masking:\n            masks = make_non_pad_mask(olens).unsqueeze(-1)\n            weights = masks.float() / masks.sum(axis=1, keepdim=True).float()\n            out_weights = weights.divide(\n                paddle.shape(ys)[0] * paddle.shape(ys)[2])\n            logit_weights = weights.divide(paddle.shape(ys)[0])\n\n            # apply weight\n            l1_loss = l1_loss.multiply(out_weights)\n            l1_loss = l1_loss.masked_select(masks.broadcast_to(l1_loss)).sum()\n            mse_loss = mse_loss.multiply(out_weights)\n            mse_loss = mse_loss.masked_select(\n                masks.broadcast_to(mse_loss)).sum()\n            bce_loss = bce_loss.multiply(logit_weights.squeeze(-1))\n            bce_loss = bce_loss.masked_select(\n                masks.squeeze(-1).broadcast_to(bce_loss)).sum()\n\n        return l1_loss, mse_loss, bce_loss\n\n\n# Losses for GAN Vocoder\ndef stft(x,\n         fft_size,\n         hop_length=None,\n         win_length=None,\n         window='hann',\n         center=True,\n         pad_mode='reflect'):\n    \"\"\"Perform STFT and convert to magnitude spectrogram.\n    Args:\n        x(Tensor): \n            Input signal tensor (B, T).\n        fft_size(int): \n            FFT size.\n        hop_size(int): \n            Hop size.\n        win_length(int, optional): \n        window (str, optional):\n            (Default value = None)\n        window(str, optional): \n            Name of window function, see `scipy.signal.get_window` for more details. Defaults to \"hann\".\n        center(bool, optional, optional): center (bool, optional): \n            Whether to pad `x` to make that the\n            :math:`t \\times hop\\\\_length` at the center of :math:`t`-th frame. Default: `True`.\n        pad_mode(str, optional, optional):  \n            (Default value = 'reflect')\n        hop_length:  \n            (Default value = None)\n\n    Returns:\n        Tensor: Magnitude spectrogram (B, #frames, fft_size // 2 + 1).\n    \"\"\"\n    # calculate window\n    window = signal.get_window(window, win_length, fftbins=True)\n    window = paddle.to_tensor(window, dtype=x.dtype)\n    x_stft = paddle.signal.stft(\n        x,\n        fft_size,\n        hop_length,\n        win_length,\n        window=window,\n        center=center,\n        pad_mode=pad_mode)\n\n    real = x_stft.real()\n    imag = x_stft.imag()\n\n    return paddle.sqrt(paddle.clip(real**2 + imag**2, min=1e-7)).transpose(\n        [0, 2, 1])\n\n\nclass SpectralConvergenceLoss(nn.Layer):\n    \"\"\"Spectral convergence loss module.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initilize spectral convergence loss module.\"\"\"\n        super().__init__()\n\n    def forward(self, x_mag, y_mag):\n        \"\"\"Calculate forward propagation.\n        Args: \n            x_mag (Tensor):\n                 Magnitude spectrogram of predicted signal (B, #frames, #freq_bins).\n            y_mag (Tensor): \n                Magnitude spectrogram of groundtruth signal (B, #frames, #freq_bins).\n        Returns:\n            Tensor: Spectral convergence loss value.\n        \"\"\"\n        return paddle.norm(\n            y_mag - x_mag, p=\"fro\") / paddle.clip(\n                paddle.norm(y_mag, p=\"fro\"), min=1e-10)\n\n\nclass LogSTFTMagnitudeLoss(nn.Layer):\n    \"\"\"Log STFT magnitude loss module.\"\"\"\n\n    def __init__(self, epsilon=1e-7):\n        \"\"\"Initilize los STFT magnitude loss module.\"\"\"\n        super().__init__()\n        self.epsilon = epsilon\n\n    def forward(self, x_mag, y_mag):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x_mag (Tensor): \n                Magnitude spectrogram of predicted signal (B, #frames, #freq_bins).\n            y_mag (Tensor):\n                Magnitude spectrogram of groundtruth signal (B, #frames, #freq_bins).\n        Returns:\n            Tensor: Log STFT magnitude loss value.\n        \"\"\"\n        return F.l1_loss(\n            paddle.log(paddle.clip(y_mag, min=self.epsilon)),\n            paddle.log(paddle.clip(x_mag, min=self.epsilon)))\n\n\nclass STFTLoss(nn.Layer):\n    \"\"\"STFT loss module.\"\"\"\n\n    def __init__(self,\n                 fft_size=1024,\n                 shift_size=120,\n                 win_length=600,\n                 window=\"hann\"):\n        \"\"\"Initialize STFT loss module.\"\"\"\n        super().__init__()\n        self.fft_size = fft_size\n        self.shift_size = shift_size\n        self.win_length = win_length\n        self.window = window\n        self.spectral_convergence_loss = SpectralConvergenceLoss()\n        self.log_stft_magnitude_loss = LogSTFTMagnitudeLoss()\n\n    def forward(self, x, y):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Predicted signal (B, T).\n            y (Tensor): \n                Groundtruth signal (B, T).\n        Returns:\n            Tensor: \n                Spectral convergence loss value.\n            Tensor: \n                Log STFT magnitude loss value.\n        \"\"\"\n        x_mag = stft(x, self.fft_size, self.shift_size, self.win_length,\n                     self.window)\n        y_mag = stft(y, self.fft_size, self.shift_size, self.win_length,\n                     self.window)\n        sc_loss = self.spectral_convergence_loss(x_mag, y_mag)\n        mag_loss = self.log_stft_magnitude_loss(x_mag, y_mag)\n\n        return sc_loss, mag_loss\n\n\nclass MultiResolutionSTFTLoss(nn.Layer):\n    \"\"\"Multi resolution STFT loss module.\"\"\"\n\n    def __init__(\n            self,\n            fft_sizes=[1024, 2048, 512],\n            hop_sizes=[120, 240, 50],\n            win_lengths=[600, 1200, 240],\n            window=\"hann\", ):\n        \"\"\"Initialize Multi resolution STFT loss module.\n        Args:\n            fft_sizes (list): \n                List of FFT sizes.\n            hop_sizes (list): \n                List of hop sizes.\n            win_lengths (list): \n                List of window lengths.\n            window (str): \n                Window function type.\n        \"\"\"\n        super().__init__()\n        assert len(fft_sizes) == len(hop_sizes) == len(win_lengths)\n        self.stft_losses = nn.LayerList()\n        for fs, ss, wl in zip(fft_sizes, hop_sizes, win_lengths):\n            self.stft_losses.append(STFTLoss(fs, ss, wl, window))\n\n    def forward(self, x, y):\n        \"\"\"Calculate forward propagation.\n        \n        Args:\n            x (Tensor): \n                Predicted signal (B, T) or (B, #subband, T).\n            y (Tensor): \n                Groundtruth signal (B, T) or (B, #subband, T).\n        Returns:\n            Tensor: \n                Multi resolution spectral convergence loss value.\n            Tensor: \n                Multi resolution log STFT magnitude loss value.\n        \"\"\"\n        if len(x.shape) == 3:\n            # (B, C, T) -> (B x C, T)\n            x = x.reshape([-1, x.shape[2]])\n            # (B, C, T) -> (B x C, T)\n            y = y.reshape([-1, y.shape[2]])\n        sc_loss = 0.0\n        mag_loss = 0.0\n        for f in self.stft_losses:\n            sc_l, mag_l = f(x, y)\n            sc_loss += sc_l\n            mag_loss += mag_l\n        sc_loss /= len(self.stft_losses)\n        mag_loss /= len(self.stft_losses)\n\n        return sc_loss, mag_loss\n\n\nclass GeneratorAdversarialLoss(nn.Layer):\n    \"\"\"Generator adversarial loss module.\"\"\"\n\n    def __init__(\n            self,\n            average_by_discriminators=True,\n            loss_type=\"mse\", ):\n        \"\"\"Initialize GeneratorAversarialLoss module.\"\"\"\n        super().__init__()\n        self.average_by_discriminators = average_by_discriminators\n        assert loss_type in [\"mse\", \"hinge\"], f\"{loss_type} is not supported.\"\n        if loss_type == \"mse\":\n            self.criterion = self._mse_loss\n        else:\n            self.criterion = self._hinge_loss\n\n    def forward(self, outputs):\n        \"\"\"Calcualate generator adversarial loss.\n        Args:\n            outputs (Tensor or List): \n                Discriminator outputs or list of discriminator outputs.\n        Returns:\n            Tensor: \n                Generator adversarial loss value.\n        \"\"\"\n        if isinstance(outputs, (tuple, list)):\n            adv_loss = 0.0\n            for i, outputs_ in enumerate(outputs):\n                if isinstance(outputs_, (tuple, list)):\n                    # case including feature maps\n                    outputs_ = outputs_[-1]\n                adv_loss += self.criterion(outputs_)\n            if self.average_by_discriminators:\n                adv_loss /= i + 1\n        else:\n            adv_loss = self.criterion(outputs)\n\n        return adv_loss\n\n    def _mse_loss(self, x):\n        return F.mse_loss(x, paddle.ones_like(x))\n\n    def _hinge_loss(self, x):\n        return -x.mean()\n\n\nclass DiscriminatorAdversarialLoss(nn.Layer):\n    \"\"\"Discriminator adversarial loss module.\"\"\"\n\n    def __init__(\n            self,\n            average_by_discriminators=True,\n            loss_type=\"mse\", ):\n        \"\"\"Initialize DiscriminatorAversarialLoss module.\"\"\"\n        super().__init__()\n        self.average_by_discriminators = average_by_discriminators\n        assert loss_type in [\"mse\"], f\"{loss_type} is not supported.\"\n        if loss_type == \"mse\":\n            self.fake_criterion = self._mse_fake_loss\n            self.real_criterion = self._mse_real_loss\n\n    def forward(self, outputs_hat, outputs):\n        \"\"\"Calcualate discriminator adversarial loss.\n\n        Args:\n            outputs_hat (Tensor or list): \n                Discriminator outputs or list of discriminator outputs calculated from generator outputs.\n            outputs (Tensor or list): \n                Discriminator outputs or list of discriminator outputs calculated from groundtruth.\n        Returns:\n            Tensor: \n                Discriminator real loss value.\n            Tensor: \n                Discriminator fake loss value.\n        \"\"\"\n        if isinstance(outputs, (tuple, list)):\n            real_loss = 0.0\n            fake_loss = 0.0\n            for i, (outputs_hat_,\n                    outputs_) in enumerate(zip(outputs_hat, outputs)):\n                if isinstance(outputs_hat_, (tuple, list)):\n                    # case including feature maps\n                    outputs_hat_ = outputs_hat_[-1]\n                    outputs_ = outputs_[-1]\n                real_loss += self.real_criterion(outputs_)\n                fake_loss += self.fake_criterion(outputs_hat_)\n            if self.average_by_discriminators:\n                fake_loss /= i + 1\n                real_loss /= i + 1\n        else:\n            real_loss = self.real_criterion(outputs)\n            fake_loss = self.fake_criterion(outputs_hat)\n\n        return real_loss, fake_loss\n\n    def _mse_real_loss(self, x):\n        return F.mse_loss(x, paddle.ones_like(x))\n\n    def _mse_fake_loss(self, x):\n        return F.mse_loss(x, paddle.zeros_like(x))\n\n\n# Losses for SpeedySpeech\n# Structural Similarity Index Measure (SSIM)\ndef gaussian(window_size, sigma):\n    gauss = paddle.to_tensor([\n        math.exp(-(x - window_size // 2)**2 / float(2 * sigma**2))\n        for x in range(window_size)\n    ])\n    return gauss / gauss.sum()\n\n\ndef create_window(window_size, channel):\n    _1D_window = gaussian(window_size, 1.5).unsqueeze(1)\n    _2D_window = paddle.matmul(_1D_window, paddle.transpose(\n        _1D_window, [1, 0])).unsqueeze([0, 1])\n    window = paddle.expand(_2D_window, [channel, 1, window_size, window_size])\n    return window\n\n\ndef _ssim(img1, img2, window, window_size, channel, size_average=True):\n    mu1 = F.conv2d(img1, window, padding=window_size // 2, groups=channel)\n    mu2 = F.conv2d(img2, window, padding=window_size // 2, groups=channel)\n\n    mu1_sq = mu1.pow(2)\n    mu2_sq = mu2.pow(2)\n    mu1_mu2 = mu1 * mu2\n\n    sigma1_sq = F.conv2d(\n        img1 * img1, window, padding=window_size // 2, groups=channel) - mu1_sq\n    sigma2_sq = F.conv2d(\n        img2 * img2, window, padding=window_size // 2, groups=channel) - mu2_sq\n    sigma12 = F.conv2d(\n        img1 * img2, window, padding=window_size // 2, groups=channel) - mu1_mu2\n\n    C1 = 0.01**2\n    C2 = 0.03**2\n\n    ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) \\\n             / ((mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2))\n\n    if size_average:\n        return ssim_map.mean()\n    else:\n        return ssim_map.mean(1).mean(1).mean(1)\n\n\ndef ssim(img1, img2, window_size=11, size_average=True):\n    (_, channel, _, _) = img1.shape\n    window = create_window(window_size, channel)\n    return _ssim(img1, img2, window, window_size, channel, size_average)\n\n\ndef weighted_mean(input, weight):\n    \"\"\"Weighted mean. It can also be used as masked mean.\n\n    Args:\n        input(Tensor): The input tensor.\n        weight(Tensor): The weight tensor with broadcastable shape with the input.\n\n    Returns:\n        Tensor: Weighted mean tensor with the same dtype as input. shape=(1,)\n            \n    \"\"\"\n    weight = paddle.cast(weight, input.dtype)\n    # paddle.Tensor.size is different with torch.size() and has been overrided in s2t.__init__\n    broadcast_ratio = input.numel() / weight.numel()\n    return paddle.sum(input * weight) / (paddle.sum(weight) * broadcast_ratio)\n\n\ndef masked_l1_loss(prediction, target, mask):\n    \"\"\"Compute maksed L1 loss.\n\n    Args:\n        prediction(Tensor): \n            The prediction.\n        target(Tensor): \n            The target. The shape should be broadcastable to ``prediction``.\n        mask(Tensor): \n            The mask. The shape should be broadcatable to the broadcasted shape of\n            ``prediction`` and ``target``.\n\n    Returns:\n        Tensor: The masked L1 loss. shape=(1,)\n        \n    \"\"\"\n    abs_error = F.l1_loss(prediction, target, reduction='none')\n    loss = weighted_mean(abs_error, mask)\n    return loss\n\n\nclass MelSpectrogram(nn.Layer):\n    \"\"\"Calculate Mel-spectrogram.\"\"\"\n\n    def __init__(\n            self,\n            fs=22050,\n            fft_size=1024,\n            hop_size=256,\n            win_length=None,\n            window=\"hann\",\n            num_mels=80,\n            fmin=80,\n            fmax=7600,\n            center=True,\n            normalized=False,\n            onesided=True,\n            eps=1e-10,\n            log_base=10.0, ):\n        \"\"\"Initialize MelSpectrogram module.\"\"\"\n        super().__init__()\n        self.fft_size = fft_size\n        if win_length is None:\n            self.win_length = fft_size\n        else:\n            self.win_length = win_length\n        self.hop_size = hop_size\n        self.center = center\n        self.normalized = normalized\n        self.onesided = onesided\n\n        if window is not None and not hasattr(signal.windows, f\"{window}\"):\n            raise ValueError(f\"{window} window is not implemented\")\n        self.window = window\n        self.eps = eps\n\n        fmin = 0 if fmin is None else fmin\n        fmax = fs / 2 if fmax is None else fmax\n        melmat = librosa.filters.mel(\n            sr=fs,\n            n_fft=fft_size,\n            n_mels=num_mels,\n            fmin=fmin,\n            fmax=fmax, )\n\n        self.melmat = paddle.to_tensor(melmat.T)\n        self.stft_params = {\n            \"n_fft\": self.fft_size,\n            \"win_length\": self.win_length,\n            \"hop_length\": self.hop_size,\n            \"center\": self.center,\n            \"normalized\": self.normalized,\n            \"onesided\": self.onesided,\n        }\n\n        self.log_base = log_base\n        if self.log_base is None:\n            self.log = paddle.log\n        elif self.log_base == 2.0:\n            self.log = paddle.log2\n        elif self.log_base == 10.0:\n            self.log = paddle.log10\n        else:\n            raise ValueError(f\"log_base: {log_base} is not supported.\")\n\n    def forward(self, x):\n        \"\"\"Calculate Mel-spectrogram.\n        Args:\n        \n            x (Tensor): Input waveform tensor (B, T) or (B, 1, T).\n        Returns:\n            Tensor: Mel-spectrogram (B, #mels, #frames).\n        \"\"\"\n        if len(x.shape) == 3:\n            # (B, C, T) -> (B*C, T)\n            x = x.reshape([-1, paddle.shape(x)[2]])\n\n        if self.window is not None:\n            # calculate window\n            window = signal.get_window(\n                self.window, self.win_length, fftbins=True)\n            window = paddle.to_tensor(window, dtype=x.dtype)\n        else:\n            window = None\n\n        x_stft = paddle.signal.stft(x, window=window, **self.stft_params)\n        real = x_stft.real()\n        imag = x_stft.imag()\n        # (B, #freqs, #frames) -> (B, $frames, #freqs)\n        real = real.transpose([0, 2, 1])\n        imag = imag.transpose([0, 2, 1])\n        x_power = real**2 + imag**2\n        x_amp = paddle.sqrt(paddle.clip(x_power, min=self.eps))\n        x_mel = paddle.matmul(x_amp, self.melmat)\n        x_mel = paddle.clip(x_mel, min=self.eps)\n\n        return self.log(x_mel).transpose([0, 2, 1])\n\n\nclass MelSpectrogramLoss(nn.Layer):\n    \"\"\"Mel-spectrogram loss.\"\"\"\n\n    def __init__(\n            self,\n            fs=22050,\n            fft_size=1024,\n            hop_size=256,\n            win_length=None,\n            window=\"hann\",\n            num_mels=80,\n            fmin=80,\n            fmax=7600,\n            center=True,\n            normalized=False,\n            onesided=True,\n            eps=1e-10,\n            log_base=10.0, ):\n        \"\"\"Initialize Mel-spectrogram loss.\"\"\"\n        super().__init__()\n        self.mel_spectrogram = MelSpectrogram(\n            fs=fs,\n            fft_size=fft_size,\n            hop_size=hop_size,\n            win_length=win_length,\n            window=window,\n            num_mels=num_mels,\n            fmin=fmin,\n            fmax=fmax,\n            center=center,\n            normalized=normalized,\n            onesided=onesided,\n            eps=eps,\n            log_base=log_base, )\n\n    def forward(self, y_hat, y):\n        \"\"\"Calculate Mel-spectrogram loss.\n        Args:\n            y_hat(Tensor): \n                Generated single tensor (B, 1, T).\n            y(Tensor): \n                Groundtruth single tensor (B, 1, T).\n\n        Returns:\n            Tensor: Mel-spectrogram loss value.\n        \"\"\"\n        mel_hat = self.mel_spectrogram(y_hat)\n        mel = self.mel_spectrogram(y)\n        mel_loss = F.l1_loss(mel_hat, mel)\n\n        return mel_loss\n\n\nclass FeatureMatchLoss(nn.Layer):\n    \"\"\"Feature matching loss module.\"\"\"\n\n    def __init__(\n            self,\n            average_by_layers=True,\n            average_by_discriminators=True,\n            include_final_outputs=False, ):\n        \"\"\"Initialize FeatureMatchLoss module.\"\"\"\n        super().__init__()\n        self.average_by_layers = average_by_layers\n        self.average_by_discriminators = average_by_discriminators\n        self.include_final_outputs = include_final_outputs\n\n    def forward(self, feats_hat, feats):\n        \"\"\"Calcualate feature matching loss.\n\n        Args:\n            feats_hat(list): \n                List of list of discriminator outputs\n                calcuated from generater outputs.\n            feats(list): \n                List of list of discriminator outputs\n\n        Returns:\n            Tensor: Feature matching loss value.\n\n        \"\"\"\n        feat_match_loss = 0.0\n        for i, (feats_hat_, feats_) in enumerate(zip(feats_hat, feats)):\n            feat_match_loss_ = 0.0\n            if not self.include_final_outputs:\n                feats_hat_ = feats_hat_[:-1]\n                feats_ = feats_[:-1]\n            for j, (feat_hat_, feat_) in enumerate(zip(feats_hat_, feats_)):\n                feat_match_loss_ += F.l1_loss(feat_hat_, feat_.detach())\n            if self.average_by_layers:\n                feat_match_loss_ /= j + 1\n            feat_match_loss += feat_match_loss_\n        if self.average_by_discriminators:\n            feat_match_loss /= i + 1\n\n        return feat_match_loss\n\n\n# loss for VITS\nclass KLDivergenceLoss(nn.Layer):\n    \"\"\"KL divergence loss.\"\"\"\n\n    def forward(\n            self,\n            z_p: paddle.Tensor,\n            logs_q: paddle.Tensor,\n            m_p: paddle.Tensor,\n            logs_p: paddle.Tensor,\n            z_mask: paddle.Tensor, ) -> paddle.Tensor:\n        \"\"\"Calculate KL divergence loss.\n\n        Args:\n            z_p (Tensor): \n                Flow hidden representation (B, H, T_feats).\n            logs_q (Tensor): \n                Posterior encoder projected scale (B, H, T_feats).\n            m_p (Tensor): \n                Expanded text encoder projected mean (B, H, T_feats).\n            logs_p (Tensor): \n                Expanded text encoder projected scale (B, H, T_feats).\n            z_mask (Tensor): \n                Mask tensor (B, 1, T_feats).\n\n        Returns:\n            Tensor: KL divergence loss.\n\n        \"\"\"\n        z_p = paddle.cast(z_p, 'float32')\n        logs_q = paddle.cast(logs_q, 'float32')\n        m_p = paddle.cast(m_p, 'float32')\n        logs_p = paddle.cast(logs_p, 'float32')\n        z_mask = paddle.cast(z_mask, 'float32')\n        kl = logs_p - logs_q - 0.5\n        kl += 0.5 * ((z_p - m_p)**2) * paddle.exp(-2.0 * logs_p)\n        kl = paddle.sum(kl * z_mask)\n        loss = kl / paddle.sum(z_mask)\n\n        return loss\n\n\n# loss for ERNIE SAT\nclass MLMLoss(nn.Layer):\n    def __init__(self,\n                 odim: int,\n                 vocab_size: int=0,\n                 lsm_weight: float=0.1,\n                 ignore_id: int=-1,\n                 text_masking: bool=False):\n        super().__init__()\n        if text_masking:\n            self.text_mlm_loss = nn.CrossEntropyLoss(ignore_index=ignore_id)\n        if lsm_weight > 50:\n            self.l1_loss_func = nn.MSELoss()\n        else:\n            self.l1_loss_func = nn.L1Loss(reduction='none')\n        self.text_masking = text_masking\n        self.odim = odim\n        self.vocab_size = vocab_size\n\n    def forward(\n            self,\n            speech: paddle.Tensor,\n            before_outs: paddle.Tensor,\n            after_outs: paddle.Tensor,\n            masked_pos: paddle.Tensor,\n            # for text_loss when text_masking == True\n            text: paddle.Tensor=None,\n            text_outs: paddle.Tensor=None,\n            text_masked_pos: paddle.Tensor=None):\n\n        xs_pad = speech\n        mlm_loss_pos = masked_pos > 0\n        loss = paddle.sum(\n            self.l1_loss_func(\n                paddle.reshape(before_outs, (-1, self.odim)),\n                paddle.reshape(xs_pad, (-1, self.odim))),\n            axis=-1)\n        if after_outs is not None:\n            loss += paddle.sum(\n                self.l1_loss_func(\n                    paddle.reshape(after_outs, (-1, self.odim)),\n                    paddle.reshape(xs_pad, (-1, self.odim))),\n                axis=-1)\n        mlm_loss_pos = (mlm_loss_pos).astype(loss.dtype)\n        mlm_loss = paddle.sum((loss * paddle.reshape(\n            mlm_loss_pos,\n            [-1]).astype(loss.dtype))) / paddle.sum((mlm_loss_pos) + 1e-10)\n\n        text_mlm_loss = None\n\n        if self.text_masking:\n            assert text is not None\n            assert text_outs is not None\n            assert text_masked_pos is not None\n            text_outs = paddle.reshape(text_outs, [-1, self.vocab_size])\n            text = paddle.reshape(text, [-1])\n            text_mlm_loss = self.text_mlm_loss(text_outs, text)\n            text_masked_pos_reshape = paddle.reshape(text_masked_pos, [-1])\n            text_mlm_loss = paddle.sum(\n                text_mlm_loss *\n                text_masked_pos_reshape) / paddle.sum((text_masked_pos) + 1e-10)\n\n        return mlm_loss, text_mlm_loss\n\n\nclass VarianceLoss(nn.Layer):\n    @typechecked\n    def __init__(self, use_masking: bool=True,\n                 use_weighted_masking: bool=False):\n        \"\"\"Initialize JETS variance loss module.\n        Args:\n            use_masking (bool): Whether to apply masking for padded part in loss\n                calculation.\n            use_weighted_masking (bool): Whether to weighted masking in loss\n                calculation.\n\n        \"\"\"\n        super().__init__()\n\n        assert (use_masking != use_weighted_masking) or not use_masking\n        self.use_masking = use_masking\n        self.use_weighted_masking = use_weighted_masking\n\n        # define criterions\n        reduction = \"none\" if self.use_weighted_masking else \"mean\"\n        self.mse_criterion = nn.MSELoss(reduction=reduction)\n        self.duration_criterion = DurationPredictorLoss(reduction=reduction)\n\n    def forward(\n            self,\n            d_outs: paddle.Tensor,\n            ds: paddle.Tensor,\n            p_outs: paddle.Tensor,\n            ps: paddle.Tensor,\n            e_outs: paddle.Tensor,\n            es: paddle.Tensor,\n            ilens: paddle.Tensor,\n    ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor]:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            d_outs (LongTensor): Batch of outputs of duration predictor (B, T_text).\n            ds (LongTensor): Batch of durations (B, T_text).\n            p_outs (Tensor): Batch of outputs of pitch predictor (B, T_text, 1).\n            ps (Tensor): Batch of target token-averaged pitch (B, T_text, 1).\n            e_outs (Tensor): Batch of outputs of energy predictor (B, T_text, 1).\n            es (Tensor): Batch of target token-averaged energy (B, T_text, 1).\n            ilens (LongTensor): Batch of the lengths of each input (B,).\n\n        Returns:\n            Tensor: Duration predictor loss value.\n            Tensor: Pitch predictor loss value.\n            Tensor: Energy predictor loss value.\n\n        \"\"\"\n        # apply mask to remove padded part\n        if self.use_masking:\n            duration_masks = paddle.to_tensor(\n                make_non_pad_mask(ilens), place=ds.place)\n            d_outs = d_outs.masked_select(duration_masks)\n            ds = ds.masked_select(duration_masks)\n            pitch_masks = paddle.to_tensor(\n                make_non_pad_mask(ilens).unsqueeze(-1), place=ds.place)\n            p_outs = p_outs.masked_select(pitch_masks)\n            e_outs = e_outs.masked_select(pitch_masks)\n            ps = ps.masked_select(pitch_masks)\n            es = es.masked_select(pitch_masks)\n\n        # calculate loss\n        duration_loss = self.duration_criterion(d_outs, ds)\n        pitch_loss = self.mse_criterion(p_outs, ps)\n        energy_loss = self.mse_criterion(e_outs, es)\n\n        # make weighted mask and apply it\n        if self.use_weighted_masking:\n            duration_masks = paddle.to_tensor(\n                make_non_pad_mask(ilens), place=ds.place)\n            duration_weights = (duration_masks.float() /\n                                duration_masks.sum(dim=1, keepdim=True).float())\n            duration_weights /= ds.size(0)\n\n            # apply weight\n            duration_loss = (duration_loss.mul(duration_weights).masked_select(\n                duration_masks).sum())\n            pitch_masks = duration_masks.unsqueeze(-1)\n            pitch_weights = duration_weights.unsqueeze(-1)\n            pitch_loss = pitch_loss.mul(pitch_weights).masked_select(\n                pitch_masks).sum()\n            energy_loss = (\n                energy_loss.mul(pitch_weights).masked_select(pitch_masks).sum())\n\n        return duration_loss, pitch_loss, energy_loss\n\n\nclass ForwardSumLoss(nn.Layer):\n    \"\"\"\n    https://openreview.net/forum?id=0NQwnnwAORi\n    \"\"\"\n\n    def __init__(self, cache_prior: bool=True):\n        \"\"\"\n        Args:\n            cache_prior (bool): Whether to cache beta-binomial prior\n        \"\"\"\n        super().__init__()\n        self.cache_prior = cache_prior\n        self._cache = {}\n\n    def forward(\n            self,\n            log_p_attn: paddle.Tensor,\n            ilens: paddle.Tensor,\n            olens: paddle.Tensor,\n            blank_prob: float=np.e**-1, ) -> paddle.Tensor:\n        \"\"\"\n        Args:\n            log_p_attn (Tensor): Batch of log probability of attention matrix (B, T_feats, T_text).\n            ilens (Tensor): Batch of the lengths of each input (B,).\n            olens (Tensor): Batch of the lengths of each target (B,).\n            blank_prob (float): Blank symbol probability\n\n        Returns:\n            Tensor: forwardsum loss value.\n        \"\"\"\n\n        B = log_p_attn.shape[0]\n        # add beta-binomial prior\n        bb_prior = self._generate_prior(ilens, olens)\n        bb_prior = paddle.to_tensor(\n            bb_prior, dtype=log_p_attn.dtype, place=log_p_attn.place)\n        log_p_attn = log_p_attn + bb_prior\n\n        # a row must be added to the attention matrix to account for blank token of CTC loss\n        # (B,T_feats,T_text+1)\n        log_p_attn_pd = F.pad(\n            log_p_attn, (0, 0, 0, 0, 1, 0), value=np.log(blank_prob))\n        loss = 0\n        for bidx in range(B):\n            # construct target sequnece.\n            # Every text token is mapped to a unique sequnece number.\n            target_seq = paddle.arange(\n                1, ilens[bidx] + 1, dtype=\"int32\").unsqueeze(0)\n            cur_log_p_attn_pd = log_p_attn_pd[bidx, :olens[bidx], :ilens[\n                bidx] + 1].unsqueeze(1)  # (T_feats,1,T_text+1)\n            # The input of ctc_loss API need to be fixed\n            loss += F.ctc_loss(\n                log_probs=cur_log_p_attn_pd,\n                labels=target_seq,\n                input_lengths=olens[bidx:bidx + 1],\n                label_lengths=ilens[bidx:bidx + 1])\n        loss = loss / B\n\n        return loss\n\n    def _generate_prior(self, text_lengths, feats_lengths,\n                        w=1) -> paddle.Tensor:\n        \"\"\"Generate alignment prior formulated as beta-binomial distribution\n\n        Args:\n            text_lengths (Tensor): Batch of the lengths of each input (B,).\n            feats_lengths (Tensor): Batch of the lengths of each target (B,).\n            w (float): Scaling factor; lower -> wider the width\n\n        Returns:\n            Tensor: Batched 2d static prior matrix (B, T_feats, T_text)   \n        \"\"\"\n        B = len(text_lengths)\n        T_text = text_lengths.max()\n        T_feats = feats_lengths.max()\n\n        bb_prior = paddle.full((B, T_feats, T_text), fill_value=-np.inf)\n        for bidx in range(B):\n            T = feats_lengths[bidx].item()\n            N = text_lengths[bidx].item()\n\n            key = str(T) + ',' + str(N)\n            if self.cache_prior and key in self._cache:\n                prob = self._cache[key]\n            else:\n                alpha = w * np.arange(1, T + 1, dtype=float)  # (T,)\n                beta = w * np.array([T - t + 1 for t in alpha])\n                k = np.arange(N)\n                batched_k = k[..., None]  # (N,1)\n                prob = betabinom.pmf(batched_k, N, alpha, beta)  # (N,T)\n\n            # store cache\n            if self.cache_prior and key not in self._cache:\n                self._cache[key] = prob\n\n            prob = paddle.to_tensor(\n                prob, place=text_lengths.place, dtype=\"float32\").transpose(\n                    (1, 0))  # -> (T,N)\n            bb_prior[bidx, :T, :N] = prob\n\n        return bb_prior\n\n\nclass MultiScaleSTFTLoss(nn.Layer):\n    \"\"\"Computes the multi-scale STFT loss from [1].\n\n    References\n    ----------\n\n    1.  Engel, Jesse, Chenjie Gu, and Adam Roberts.\n        \"DDSP: Differentiable Digital Signal Processing.\"\n        International Conference on Learning Representations. 2019.\n\n    Implementation copied from: https://github.com/descriptinc/audiotools/blob/master/audiotools/metrics/spectral.py\n    \"\"\"\n\n    def __init__(\n            self,\n            window_lengths: List[int]=[2048, 512],\n            loss_fn: Callable=nn.L1Loss(),\n            clamp_eps: float=1e-5,\n            mag_weight: float=1.0,\n            log_weight: float=1.0,\n            pow: float=2.0,\n            weight: float=1.0,\n            match_stride: bool=False,\n            window_type: Optional[str]=None, ):\n        \"\"\"\n        Args:\n            window_lengths : List[int], optional\n                Length of each window of each STFT, by default [2048, 512]\n            loss_fn : typing.Callable, optional\n                How to compare each loss, by default nn.L1Loss()\n            clamp_eps : float, optional\n                Clamp on the log magnitude, below, by default 1e-5\n            mag_weight : float, optional\n                Weight of raw magnitude portion of loss, by default 1.0\n            log_weight : float, optional\n                Weight of log magnitude portion of loss, by default 1.0\n            pow : float, optional\n                Power to raise magnitude to before taking log, by default 2.0\n            weight : float, optional\n                Weight of this loss, by default 1.0\n            match_stride : bool, optional\n                Whether to match the stride of convolutional layers, by default False\n            window_type : str, optional\n                Type of window to use, by default None.\n        \"\"\"\n        super().__init__()\n\n        self.stft_params = [\n            STFTParams(\n                window_length=w,\n                hop_length=w // 4,\n                match_stride=match_stride,\n                window_type=window_type, ) for w in window_lengths\n        ]\n        self.loss_fn = loss_fn\n        self.log_weight = log_weight\n        self.mag_weight = mag_weight\n        self.clamp_eps = clamp_eps\n        self.weight = weight\n        self.pow = pow\n\n    def forward(self, x: AudioSignal, y: AudioSignal):\n        \"\"\"Computes multi-scale STFT between an estimate and a reference\n        signal.\n\n        Args:\n            x : AudioSignal\n                Estimate signal\n            y : AudioSignal\n                Reference signal\n\n        Returns:\n            paddle.Tensor\n                Multi-scale STFT loss.\n        \n        Example:\n            >>> from paddlespeech.audiotools.core.audio_signal import AudioSignal\n            >>> import paddle\n\n            >>> x = AudioSignal(\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\", 2_05)\n            >>> y = x * 0.01\n            >>> loss = MultiScaleSTFTLoss()\n            >>> loss(x, y).numpy()\n            7.562150\n        \"\"\"\n        for s in self.stft_params:\n            x.stft(s.window_length, s.hop_length, s.window_type)\n            y.stft(s.window_length, s.hop_length, s.window_type)\n            loss += self.log_weight * self.loss_fn(\n                x.magnitude.clip(self.clamp_eps).pow(self.pow).log10(),\n                y.magnitude.clip(self.clamp_eps).pow(self.pow).log10(), )\n            loss += self.mag_weight * self.loss_fn(x.magnitude, y.magnitude)\n        return loss\n\n\nclass GANLoss(nn.Layer):\n    \"\"\"\n    Computes a discriminator loss, given a discriminator on\n    generated waveforms/spectrograms compared to ground truth\n    waveforms/spectrograms. Computes the loss for both the\n    discriminator and the generator in separate functions.\n\n    Example:\n    >>> from paddlespeech.audiotools.core.audio_signal import AudioSignal\n    >>> import paddle\n\n    >>> x = AudioSignal(\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\", 2_05)\n    >>> y = x * 0.01\n    >>> class My_discriminator0:\n    >>>     def __call__(self, x):\n    >>>         return x.sum()\n    >>> loss = GANLoss(My_discriminator0())\n    >>> [loss(x, y)[0].numpy(), loss(x, y)[1].numpy()]\n    [-0.102722, -0.001027]\n\n    >>> class My_discriminator1:\n    >>>     def __call__(self, x):\n    >>>         return x.sum()\n    >>> loss = GANLoss(My_discriminator1())\n    >>> [loss.generator_loss(x, y)[0].numpy(), loss.generator_loss(x, y)[1].numpy()]\n    [1.00019, 0]\n\n    >>> loss.discriminator_loss(x, y)\n    1.000200\n    \"\"\"\n\n    def __init__(self, discriminator):\n        \"\"\"\n        Args:\n            discriminator : paddle.nn.layer\n                Discriminator model\n        \"\"\"\n        super().__init__()\n        self.discriminator = discriminator\n\n    def forward(self,\n                fake: Union[AudioSignal, paddle.Tensor],\n                real: Union[AudioSignal, paddle.Tensor]):\n        if isinstance(fake, AudioSignal):\n            d_fake = self.discriminator(fake.audio_data)\n        else:\n            d_fake = self.discriminator(fake)\n\n        if isinstance(real, AudioSignal):\n            d_real = self.discriminator(real.audio_data)\n        else:\n            d_real = self.discriminator(real)\n        return d_fake, d_real\n\n    def discriminator_loss(self, fake, real):\n        d_fake, d_real = self.forward(fake, real)\n\n        loss_d = 0\n        for x_fake, x_real in zip(d_fake, d_real):\n            loss_d += paddle.mean(x_fake[-1]**2)\n            loss_d += paddle.mean((1 - x_real[-1])**2)\n        return loss_d\n\n    def generator_loss(self, fake, real):\n        d_fake, d_real = self.forward(fake, real)\n\n        loss_g = 0\n        for x_fake in d_fake:\n            loss_g += paddle.mean((1 - x_fake[-1])**2)\n\n        loss_feature = 0\n\n        for i in range(len(d_fake)):\n            for j in range(len(d_fake[i]) - 1):\n                loss_feature += F.l1_loss(d_fake[i][j], d_real[i][j]())\n        return loss_g, loss_feature\n\n\nclass SISDRLoss(nn.Layer):\n    \"\"\"\n    Computes the Scale-Invariant Source-to-Distortion Ratio between a batch\n    of estimated and reference audio signals or aligned features.\n\n    Implementation copied from: https://github.com/descriptinc/audiotools/blob/master/audiotools/metrics/distance.py\n\n    Example:\n    >>> from paddlespeech.audiotools.core.audio_signal import AudioSignal\n    >>> import paddle\n\n    >>> x = AudioSignal(\"https://paddlespeech.cdn.bcebos.com/PaddleAudio/en.wav\", 2_05)\n    >>> y = x * 0.01\n    >>> sisdr = SISDRLoss()\n    >>> sisdr(x, y).numpy()\n    -145.377640\n    \"\"\"\n\n    def __init__(\n            self,\n            scaling: bool=True,\n            reduction: str=\"mean\",\n            zero_mean: bool=True,\n            clip_min: Optional[int]=None,\n            weight: float=1.0, ):\n        \"\"\"\n        Args:\n            scaling : bool, optional\n                Whether to use scale-invariant (True) or\n                signal-to-noise ratio (False), by default True\n            reduction : str, optional\n                How to reduce across the batch (either 'mean',\n                'sum', or none).], by default ' mean'\n            zero_mean : bool, optional\n                Zero mean the references and estimates before\n                computing the loss, by default True\n            clip_min : int, optional\n                The minimum possible loss value. Helps network\n                to not focus on making already good examples better, by default None\n            weight : float, optional\n                Weight of this loss, defaults to 1.0.\n        \"\"\"\n        self.scaling = scaling\n        self.reduction = reduction\n        self.zero_mean = zero_mean\n        self.clip_min = clip_min\n        self.weight = weight\n        super().__init__()\n\n    def forward(self,\n                x: Union[AudioSignal, paddle.Tensor],\n                y: Union[AudioSignal, paddle.Tensor]):\n        eps = 1e-8\n        # B, C, T\n        if isinstance(x, AudioSignal):\n            references = x.audio_data\n            estimates = y.audio_data\n        else:\n            references = x\n            estimates = y\n\n        nb = references.shape[0]\n        references = references.reshape([nb, 1, -1]).transpose([0, 2, 1])\n        estimates = estimates.reshape([nb, 1, -1]).transpose([0, 2, 1])\n\n        # samples now on axis 1\n        if self.zero_mean:\n            mean_reference = references.mean(axis=1, keepdim=True)\n            mean_estimate = estimates.mean(axis=1, keepdim=True)\n        else:\n            mean_reference = 0\n            mean_estimate = 0\n\n        _references = references - mean_reference\n        _estimates = estimates - mean_estimate\n\n        references_projection = (_references**2).sum(axis=-2) + eps\n        references_on_estimates = (_estimates * _references).sum(axis=-2) + eps\n\n        scale = (\n            (references_on_estimates / references_projection).unsqueeze(axis=1)\n            if self.scaling else 1)\n\n        e_true = scale * _references\n        e_res = _estimates - e_true\n\n        signal = (e_true**2).sum(axis=1)\n        noise = (e_res**2).sum(axis=1)\n        sdr = -10 * paddle.log10(signal / noise + eps)\n\n        if self.clip_min != None:\n            sdr = paddle.clip(sdr, min=self.clip_min)\n\n        if self.reduction == \"mean\":\n            sdr = sdr.mean()\n        elif self.reduction == \"sum\":\n            sdr = sdr.sum()\n        return sdr\n"
  },
  {
    "path": "paddlespeech/t2s/modules/masked_fill.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Union\n\nimport paddle\n\n\ndef is_broadcastable(shp1, shp2):\n    for a, b in zip(shp1[::-1], shp2[::-1]):\n        if a == 1 or b == 1 or a == b:\n            pass\n        else:\n            return False\n    return True\n\n\n# assume that len(shp1) == len(shp2)\ndef broadcast_shape(shp1, shp2):\n    result = []\n    for a, b in zip(shp1[::-1], shp2[::-1]):\n        is_a_int = isinstance(a, int)\n        is_b_int = isinstance(b, int)\n\n        if is_a_int and is_b_int:\n            result.append(max(a, b))\n\n        else:\n            dtype = None\n            if hasattr(a, 'dtype'):\n                dtype = a.dtype\n            if hasattr(b, 'dtype'):\n                dtype = b.dtype\n\n            if (is_a_int):\n                a = paddle.full((), a, dtype=dtype)\n\n            if (is_b_int):\n                b = paddle.full((), b, dtype=dtype)\n\n            result.append(paddle.maximum(a, b))\n\n    return result[::-1]\n\n\ndef masked_fill(xs: paddle.Tensor,\n                mask: paddle.Tensor,\n                value: Union[float, int]):\n    # comment following line for converting dygraph to static graph. \n    # assert is_broadcastable(xs.shape, mask.shape) is True\n    bshape = broadcast_shape(xs.shape, mask.shape)\n    mask.stop_gradient = True\n    mask = mask.broadcast_to(bshape)\n    trues = paddle.ones_like(xs) * value\n    mask = mask.cast(dtype=paddle.bool)\n    xs = paddle.where(mask, trues, xs)\n    return xs\n"
  },
  {
    "path": "paddlespeech/t2s/modules/nets_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport math\nfrom typing import Tuple\n\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.utils.initialize import _calculate_fan_in_and_fan_out\nfrom paddlespeech.utils.initialize import kaiming_uniform_\nfrom paddlespeech.utils.initialize import normal_\nfrom paddlespeech.utils.initialize import ones_\nfrom paddlespeech.utils.initialize import uniform_\nfrom paddlespeech.utils.initialize import zeros_\n\n\n# default init method of torch\n# copy from https://github.com/PaddlePaddle/PaddleSpeech/blob/9cf8c1985a98bb380c183116123672976bdfe5c9/paddlespeech/t2s/models/vits/vits.py#L506\ndef _reset_parameters(module):\n    if isinstance(module, (nn.Conv1D, nn.Conv1DTranspose, nn.Conv2D,\n                           nn.Conv2DTranspose)):\n        kaiming_uniform_(module.weight, a=math.sqrt(5))\n        if module.bias is not None:\n            fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n            if fan_in != 0:\n                bound = 1 / math.sqrt(fan_in)\n                uniform_(module.bias, -bound, bound)\n\n    if isinstance(module,\n                  (nn.BatchNorm1D, nn.BatchNorm2D, nn.GroupNorm, nn.LayerNorm)):\n        ones_(module.weight)\n        zeros_(module.bias)\n\n    if isinstance(module, nn.Linear):\n        kaiming_uniform_(module.weight, a=math.sqrt(5))\n        if module.bias is not None:\n            fan_in, _ = _calculate_fan_in_and_fan_out(module.weight)\n            bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0\n            uniform_(module.bias, -bound, bound)\n\n    if isinstance(module, nn.Embedding):\n        normal_(module.weight)\n        if module._padding_idx is not None:\n            with paddle.no_grad():\n                module.weight[module._padding_idx] = 0\n\n\ndef pad_list(xs, pad_value):\n    \"\"\"Perform padding for the list of tensors.\n\n    Args:\n        xs (List[Tensor]): \n            List of Tensors [(T_1, `*`), (T_2, `*`), ..., (T_B, `*`)].\n        pad_value (float): \n            Value for padding.\n\n    Returns:\n        Tensor: Padded tensor (B, Tmax, `*`).\n\n    Examples:\n        >>> x = [paddle.ones([4]), paddle.ones([2]), paddle.ones([1])]\n        >>> x\n        [tensor([1., 1., 1., 1.]), tensor([1., 1.]), tensor([1.])]\n        >>> pad_list(x, 0)\n        tensor([[1., 1., 1., 1.],\n                [1., 1., 0., 0.],\n                [1., 0., 0., 0.]])\n    \"\"\"\n    n_batch = len(xs)\n    max_len = max(x.shape[0] for x in xs)\n    pad = paddle.full(\n        [n_batch, max_len, *xs[0].shape[1:]], pad_value, dtype=xs[0].dtype)\n\n    for i in range(n_batch):\n        pad[i, :xs[i].shape[0]] = xs[i]\n\n    return pad\n\n\ndef make_pad_mask(lengths, xs=None, length_dim=-1):\n    \"\"\"Make mask tensor containing indices of padded part.\n\n    Args:\n        lengths (Tensor(int64)): \n            Batch of lengths (B,).\n        xs (Tensor, optional): \n            The reference tensor.\n            If set, masks will be the same shape as this tensor.\n        length_dim (int, optional): \n            Dimension indicator of the above tensor.\n            See the example.\n\n    Returns:\n        Tensor(bool): Mask tensor containing indices of padded part bool.\n\n    Examples:\n        With only lengths.\n\n        >>> lengths = [5, 3, 2]\n        >>> make_non_pad_mask(lengths)\n        masks = [[0, 0, 0, 0 ,0],\n                 [0, 0, 0, 1, 1],\n                 [0, 0, 1, 1, 1]]\n\n        With the reference tensor.\n\n        >>> xs = paddle.zeros((3, 2, 4))\n        >>> make_pad_mask(lengths, xs)\n        tensor([[[0, 0, 0, 0],\n                 [0, 0, 0, 0]],\n                [[0, 0, 0, 1],\n                 [0, 0, 0, 1]],\n                [[0, 0, 1, 1],\n                 [0, 0, 1, 1]]])\n        >>> xs = paddle.zeros((3, 2, 6))\n        >>> make_pad_mask(lengths, xs)\n        tensor([[[0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1]],\n                [[0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1]],\n                [[0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1]]])\n\n        With the reference tensor and dimension indicator.\n\n        >>> xs = paddle.zeros((3, 6, 6))\n        >>> make_pad_mask(lengths, xs, 1)\n        tensor([[[0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [1, 1, 1, 1, 1, 1]],\n                [[0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1]],\n                [[0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1]]])\n        >>> make_pad_mask(lengths, xs, 2)\n        tensor([[[0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1],\n                 [0, 0, 0, 0, 0, 1]],\n                [[0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1],\n                 [0, 0, 0, 1, 1, 1]],\n                [[0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1],\n                 [0, 0, 1, 1, 1, 1]]],)\n\n    \"\"\"\n    if length_dim == 0:\n        raise ValueError(\"length_dim cannot be 0: {}\".format(length_dim))\n\n    # check if lengths is 0-dim tensor, if so, add a dimension\n    if lengths.ndim == 0:\n        bs = paddle.shape(lengths.unsqueeze(0))\n    else:\n        bs = paddle.shape(lengths)\n\n    if xs is None:\n        maxlen = paddle.cast(lengths.max(), dtype=bs.dtype)\n    else:\n        maxlen = paddle.shape(xs)[length_dim]\n\n    seq_range = paddle.arange(0, maxlen, dtype=paddle.int64)\n    # VITS 最后一个 expand 的位置\n    seq_range_expand = seq_range.unsqueeze(0).expand([bs, maxlen])\n    seq_length_expand = lengths.unsqueeze(-1)\n    mask = seq_range_expand >= seq_length_expand.cast(seq_range_expand.dtype)\n\n    if xs is not None:\n        assert paddle.shape(xs)[0] == bs, (paddle.shape(xs)[0], bs)\n        if length_dim < 0:\n            length_dim = len(paddle.shape(xs)) + length_dim\n        # ind = (:, None, ..., None, :, , None, ..., None)\n        ind = tuple(\n            slice(None) if i in (0, length_dim) else None\n            for i in range(len(paddle.shape(xs))))\n        mask = paddle.expand(mask[ind], paddle.shape(xs))\n    return mask\n\n\ndef make_non_pad_mask(lengths, xs=None, length_dim=-1):\n    \"\"\"Make mask tensor containing indices of non-padded part.\n\n    Args:\n        lengths (Tensor(int64) or List): \n            Batch of lengths (B,).\n        xs (Tensor, optional): \n            The reference tensor.\n            If set, masks will be the same shape as this tensor.\n        length_dim (int, optional): \n            Dimension indicator of the above tensor.\n            See the example.\n\n    Returns:\n        Tensor(bool): \n            mask tensor containing indices of padded part bool.\n\n    Examples:\n        With only lengths.\n\n        >>> lengths = [5, 3, 2]\n        >>> make_non_pad_mask(lengths)\n        masks = [[1, 1, 1, 1 ,1],\n                 [1, 1, 1, 0, 0],\n                 [1, 1, 0, 0, 0]]\n\n        With the reference tensor.\n\n        >>> xs = paddle.zeros((3, 2, 4))\n        >>> make_non_pad_mask(lengths, xs)\n        tensor([[[1, 1, 1, 1],\n                 [1, 1, 1, 1]],\n                [[1, 1, 1, 0],\n                 [1, 1, 1, 0]],\n                [[1, 1, 0, 0],\n                 [1, 1, 0, 0]]])\n        >>> xs = paddle.zeros((3, 2, 6))\n        >>> make_non_pad_mask(lengths, xs)\n        tensor([[[1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0]],\n                [[1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0]],\n                [[1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0]]])\n\n        With the reference tensor and dimension indicator.\n\n        >>> xs = paddle.zeros((3, 6, 6))\n        >>> make_non_pad_mask(lengths, xs, 1)\n        tensor([[[1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [0, 0, 0, 0, 0, 0]],\n                [[1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0]],\n                [[1, 1, 1, 1, 1, 1],\n                 [1, 1, 1, 1, 1, 1],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0],\n                 [0, 0, 0, 0, 0, 0]]])\n        >>> make_non_pad_mask(lengths, xs, 2)\n        tensor([[[1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0],\n                 [1, 1, 1, 1, 1, 0]],\n                [[1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0],\n                 [1, 1, 1, 0, 0, 0]],\n                [[1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0],\n                 [1, 1, 0, 0, 0, 0]]])\n\n    \"\"\"\n    return paddle.logical_not(make_pad_mask(lengths, xs, length_dim))\n\n\n@typechecked\ndef initialize(model: nn.Layer, init: str):\n    \"\"\"Initialize weights of a neural network module.\n\n    Parameters are initialized using the given method or distribution.\n\n    Custom initialization routines can be implemented into submodules\n\n    Args:\n        model (nn.Layer): \n            Target.\n        init (str):\n            Method of initialization.\n    \"\"\"\n    if init == \"xavier_uniform\":\n        nn.initializer.set_global_initializer(nn.initializer.XavierUniform(),\n                                              nn.initializer.Constant())\n    elif init == \"xavier_normal\":\n        nn.initializer.set_global_initializer(nn.initializer.XavierNormal(),\n                                              nn.initializer.Constant())\n    elif init == \"kaiming_uniform\":\n        nn.initializer.set_global_initializer(nn.initializer.KaimingUniform(),\n                                              nn.initializer.Constant())\n    elif init == \"kaiming_normal\":\n        nn.initializer.set_global_initializer(nn.initializer.KaimingNormal(),\n                                              nn.initializer.Constant())\n    else:\n        raise ValueError(\"Unknown initialization: \" + init)\n\n\n# for VITS\ndef get_random_segments(\n        x: paddle.paddle,\n        x_lengths: paddle.Tensor,\n        segment_size: int, ) -> Tuple[paddle.Tensor, paddle.Tensor]:\n    \"\"\"Get random segments.\n    Args:\n        x (Tensor): \n            Input tensor (B, C, T).\n        x_lengths (Tensor): \n            Length tensor (B,).\n        segment_size (int): \n            Segment size.\n    Returns:\n        Tensor: \n            Segmented tensor (B, C, segment_size).\n        Tensor: \n            Start index tensor (B,).\n    \"\"\"\n    b, c, t = paddle.shape(x)\n    max_start_idx = x_lengths - segment_size\n    rand_number = paddle.rand([b])\n    start_idxs = paddle.cast(rand_number *\n                             max_start_idx.astype(rand_number.dtype), 'int64')\n    segments = get_segments(x, start_idxs, segment_size)\n\n    return segments, start_idxs\n\n\ndef get_segments(\n        x: paddle.Tensor,\n        start_idxs: paddle.Tensor,\n        segment_size: int, ) -> paddle.Tensor:\n    \"\"\"Get segments.\n    Args:\n        x (Tensor): \n            Input tensor (B, C, T).\n        start_idxs (Tensor): \n            Start index tensor (B,).\n        segment_size (int): \n            Segment size.\n    Returns:\n        Tensor: Segmented tensor (B, C, segment_size).\n    \"\"\"\n    b, c, t = paddle.shape(x)\n    segments = paddle.zeros([b, c, segment_size], dtype=x.dtype)\n    for i, start_idx in enumerate(start_idxs):\n        segments[i] = x[i, :, start_idx:start_idx + segment_size]\n    return segments\n\n\n# see https://github.com/PaddlePaddle/X2Paddle/blob/develop/docs/pytorch_project_convertor/API_docs/ops/torch.gather.md\ndef paddle_gather(x, dim, index):\n    index_shape = index.shape\n    index_flatten = index.flatten()\n    if dim < 0:\n        dim = len(x.shape) + dim\n    nd_index = []\n    for k in range(len(x.shape)):\n        if k == dim:\n            nd_index.append(index_flatten)\n        else:\n            reshape_shape = [1] * len(x.shape)\n            reshape_shape[k] = x.shape[k]\n            x_arange = paddle.arange(x.shape[k], dtype=index.dtype)\n            x_arange = x_arange.reshape(reshape_shape)\n            dim_index = paddle.expand(x_arange, index_shape).flatten()\n            nd_index.append(dim_index)\n    ind2 = paddle.transpose(paddle.stack(nd_index), [1, 0]).astype(\"int64\")\n    paddle_out = paddle.gather_nd(x, ind2).reshape(index_shape)\n    return paddle_out\n\n\n# for ERNIE SAT\n# mask phones\ndef phones_masking(xs_pad: paddle.Tensor,\n                   src_mask: paddle.Tensor,\n                   align_start: paddle.Tensor,\n                   align_end: paddle.Tensor,\n                   align_start_lens: paddle.Tensor,\n                   mlm_prob: float=0.8,\n                   mean_phn_span: int=8,\n                   span_bdy: paddle.Tensor=None):\n    '''\n    Args:\n        xs_pad (paddle.Tensor): \n            input speech (B, Tmax, D).\n        src_mask (paddle.Tensor): \n            mask of speech (B, 1, Tmax).\n        align_start (paddle.Tensor): \n            frame level phone alignment start (B, Tmax2).\n        align_end (paddle.Tensor): \n            frame level phone alignment end (B, Tmax2).\n        align_start_lens (paddle.Tensor): \n            length of align_start (B, ).\n        mlm_prob (float):\n        mean_phn_span (int):\n        span_bdy (paddle.Tensor): \n            masked mel boundary of input speech (B, 2).\n    Returns:\n        paddle.Tensor[bool]: masked position of input speech (B, Tmax).\n    '''\n    bz, sent_len, _ = paddle.shape(xs_pad)\n    masked_pos = paddle.zeros((bz, sent_len))\n    if mlm_prob == 1.0:\n        masked_pos += 1\n    elif mean_phn_span == 0:\n        # only speech\n        length = sent_len\n        mean_phn_span = min(length * mlm_prob // 3, 50)\n        masked_phn_idxs = random_spans_noise_mask(\n            length=length, mlm_prob=mlm_prob,\n            mean_phn_span=mean_phn_span).nonzero()\n        masked_pos[:, masked_phn_idxs] = 1\n    else:\n        for idx in range(bz):\n            # for inference\n            if span_bdy is not None:\n                for s, e in zip(span_bdy[idx][::2], span_bdy[idx][1::2]):\n                    masked_pos[idx, s:e] = 1\n            # for training\n            else:\n                length = align_start_lens[idx]\n                if length < 2:\n                    continue\n                masked_phn_idxs = random_spans_noise_mask(\n                    length=length,\n                    mlm_prob=mlm_prob,\n                    mean_phn_span=mean_phn_span).nonzero()\n                masked_start = align_start[idx][masked_phn_idxs].tolist()\n                masked_end = align_end[idx][masked_phn_idxs].tolist()\n                for s, e in zip(masked_start, masked_end):\n                    masked_pos[idx, s:e] = 1\n    non_eos_mask = paddle.reshape(src_mask, paddle.shape(xs_pad)[:2])\n    masked_pos = masked_pos * non_eos_mask.astype(masked_pos.dtype)\n    masked_pos = paddle.cast(masked_pos, 'bool')\n\n    return masked_pos\n\n\n# mask speech and phones\ndef phones_text_masking(xs_pad: paddle.Tensor,\n                        src_mask: paddle.Tensor,\n                        text_pad: paddle.Tensor,\n                        text_mask: paddle.Tensor,\n                        align_start: paddle.Tensor,\n                        align_end: paddle.Tensor,\n                        align_start_lens: paddle.Tensor,\n                        mlm_prob: float=0.8,\n                        mean_phn_span: int=8,\n                        span_bdy: paddle.Tensor=None):\n    '''\n    Args:\n        xs_pad (paddle.Tensor): \n            input speech (B, Tmax, D).\n        src_mask (paddle.Tensor): \n            mask of speech (B, 1, Tmax).\n        text_pad (paddle.Tensor): \n            input text (B, Tmax2).\n        text_mask (paddle.Tensor):\n            mask of text (B, 1, Tmax2).\n        align_start (paddle.Tensor): \n            frame level phone alignment start (B, Tmax2).\n        align_end (paddle.Tensor): \n            frame level phone alignment end (B, Tmax2).\n        align_start_lens (paddle.Tensor): \n            length of align_start (B, ).\n        mlm_prob (float):\n        mean_phn_span (int):\n        span_bdy (paddle.Tensor): \n            masked mel boundary of input speech (B, 2).\n    Returns:\n        paddle.Tensor[bool]: \n            masked position of input speech (B, Tmax).\n        paddle.Tensor[bool]: \n            masked position of input text (B, Tmax2).\n    '''\n    bz, sent_len, _ = paddle.shape(xs_pad)\n    masked_pos = paddle.zeros((bz, sent_len))\n    _, text_len = paddle.shape(text_pad)\n    text_mask_num_lower = math.ceil(text_len * (1 - mlm_prob) * 0.5)\n    text_masked_pos = paddle.zeros((bz, text_len))\n\n    if mlm_prob == 1.0:\n        masked_pos += 1\n    elif mean_phn_span == 0:\n        # only speech \n        length = sent_len\n        mean_phn_span = min(length * mlm_prob // 3, 50)\n        masked_phn_idxs = random_spans_noise_mask(\n            length=length, mlm_prob=mlm_prob,\n            mean_phn_span=mean_phn_span).nonzero()\n        masked_pos[:, masked_phn_idxs] = 1\n    else:\n        for idx in range(bz):\n            # for inference\n            if span_bdy is not None:\n                for s, e in zip(span_bdy[idx][::2], span_bdy[idx][1::2]):\n                    masked_pos[idx, s:e] = 1\n            # for training\n            else:\n                length = align_start_lens[idx]\n                if length < 2:\n                    continue\n                masked_phn_idxs = random_spans_noise_mask(\n                    length=length,\n                    mlm_prob=mlm_prob,\n                    mean_phn_span=mean_phn_span).nonzero()\n                unmasked_phn_idxs = list(\n                    set(range(length)) - set(masked_phn_idxs[0].tolist()))\n                np.random.shuffle(unmasked_phn_idxs)\n                masked_text_idxs = unmasked_phn_idxs[:text_mask_num_lower]\n                text_masked_pos[idx, masked_text_idxs] = 1\n                masked_start = align_start[idx][masked_phn_idxs].tolist()\n                masked_end = align_end[idx][masked_phn_idxs].tolist()\n                for s, e in zip(masked_start, masked_end):\n                    masked_pos[idx, s:e] = 1\n    non_eos_mask = paddle.reshape(src_mask, shape=paddle.shape(xs_pad)[:2])\n    masked_pos = masked_pos * non_eos_mask.astype(masked_pos.dtype)\n    non_eos_text_mask = paddle.reshape(\n        text_mask, shape=paddle.shape(text_pad)[:2])\n    text_masked_pos = text_masked_pos * non_eos_text_mask.astype(\n        text_masked_pos.dtype)\n    masked_pos = paddle.cast(masked_pos, 'bool')\n    text_masked_pos = paddle.cast(text_masked_pos, 'bool')\n\n    return masked_pos, text_masked_pos\n\n\ndef get_seg_pos(speech_pad: paddle.Tensor,\n                text_pad: paddle.Tensor,\n                align_start: paddle.Tensor,\n                align_end: paddle.Tensor,\n                align_start_lens: paddle.Tensor,\n                seg_emb: bool=False):\n    '''\n    Args:\n        speech_pad (paddle.Tensor): \n            input speech (B, Tmax, D).\n        text_pad (paddle.Tensor): \n            input text (B, Tmax2).\n        align_start (paddle.Tensor): \n            frame level phone alignment start (B, Tmax2).\n        align_end (paddle.Tensor): \n            frame level phone alignment end (B, Tmax2).\n        align_start_lens (paddle.Tensor): \n            length of align_start (B, ).\n        seg_emb (bool): \n            whether to use segment embedding.\n    Returns:\n        paddle.Tensor[int]: n-th phone of each mel, 0<=n<=Tmax2 (B, Tmax).\n            eg: \n            Tensor(shape=[1, 328], dtype=int64, place=Place(gpu:0), stop_gradient=True,\n            [[0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,\n            1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,\n            1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,\n            1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,\n            1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 ,\n            5 , 5 , 5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,\n            7 , 8 , 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 10, 10, 10, 10, 10,\n            10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,\n            13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15,\n            15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17,\n            17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20,\n            20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 23, 23,\n            23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,\n            25, 26, 26, 26, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29,\n            29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 32,\n            32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35,\n            35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,\n            37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,\n            38, 38, 0 , 0 ]])\n        paddle.Tensor[int]: n-th phone of each phone, 0<=n<=Tmax2 (B, Tmax2).\n            eg: \n            Tensor(shape=[1, 38], dtype=int64, place=Place(gpu:0), stop_gradient=True,\n                [[1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10, 11, 12, 13, 14, 15, 16, 17, \n                18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, \n                36, 37, 38]])\n    '''\n\n    bz, speech_len, _ = paddle.shape(speech_pad)\n    _, text_len = paddle.shape(text_pad)\n\n    text_seg_pos = paddle.zeros((bz, text_len), dtype='int64')\n    speech_seg_pos = paddle.zeros((bz, speech_len), dtype='int64')\n\n    if not seg_emb:\n        return speech_seg_pos, text_seg_pos\n    for idx in range(bz):\n        align_length = align_start_lens[idx]\n        for j in range(align_length):\n            s, e = align_start[idx][j], align_end[idx][j]\n            speech_seg_pos[idx, s:e] = j + 1\n            text_seg_pos[idx, j] = j + 1\n\n    return speech_seg_pos, text_seg_pos\n\n\n# randomly select the range of speech and text to mask during training\ndef random_spans_noise_mask(length: int,\n                            mlm_prob: float=0.8,\n                            mean_phn_span: float=8):\n    \"\"\"This function is copy of `random_spans_helper \n    <https://github.com/google-research/text-to-text-transfer-transformer/blob/84f8bcc14b5f2c03de51bd3587609ba8f6bbd1cd/t5/data/preprocessors.py#L2682>`__ .\n    Noise mask consisting of random spans of noise tokens.\n    The number of noise tokens and the number of noise spans and non-noise spans\n    are determined deterministically as follows:\n    num_noise_tokens = round(length * noise_density)\n    num_nonnoise_spans = num_noise_spans = round(num_noise_tokens / mean_noise_span_length)\n    Spans alternate between non-noise and noise, beginning with non-noise.\n    Subject to the above restrictions, all masks are equally likely.\n    Args:\n        length: an int32 scalar (length of the incoming token sequence)\n        noise_density: a float - approximate density of output mask\n        mean_noise_span_length: a number\n    Returns:\n        np.ndarray: a boolean tensor with shape [length]\n    \"\"\"\n\n    orig_length = length\n\n    num_noise_tokens = int(np.round(length * mlm_prob))\n    # avoid degeneracy by ensuring positive numbers of noise and nonnoise tokens.\n    num_noise_tokens = min(max(num_noise_tokens, 1), length - 1)\n    num_noise_spans = int(np.round(num_noise_tokens / mean_phn_span))\n\n    # avoid degeneracy by ensuring positive number of noise spans\n    num_noise_spans = max(num_noise_spans, 1)\n    num_nonnoise_tokens = length - num_noise_tokens\n\n    # pick the lengths of the noise spans and the non-noise spans\n    def _random_seg(num_items, num_segs):\n        \"\"\"Partition a sequence of items randomly into non-empty segments.\n        Args:\n            num_items: \n                an integer scalar > 0\n            num_segs: \n                an integer scalar in [1, num_items]\n        Returns:\n            a Tensor with shape [num_segs] containing positive integers that add\n            up to num_items\n        \"\"\"\n        mask_idxs = np.arange(num_items - 1) < (num_segs - 1)\n        np.random.shuffle(mask_idxs)\n        first_in_seg = np.pad(mask_idxs, [[1, 0]])\n        segment_id = np.cumsum(first_in_seg)\n        # count length of sub segments assuming that list is sorted\n        _, segment_length = np.unique(segment_id, return_counts=True)\n        return segment_length\n\n    noise_span_lens = _random_seg(num_noise_tokens, num_noise_spans)\n    nonnoise_span_lens = _random_seg(num_nonnoise_tokens, num_noise_spans)\n\n    interleaved_span_lens = np.reshape(\n        np.stack([nonnoise_span_lens, noise_span_lens], axis=1),\n        [num_noise_spans * 2])\n    span_starts = np.cumsum(interleaved_span_lens)[:-1]\n    span_start_indicator = np.zeros((length, ), dtype=np.int8)\n    span_start_indicator[span_starts] = True\n    span_num = np.cumsum(span_start_indicator)\n    is_noise = np.equal(span_num % 2, 1)\n\n    return is_noise[:orig_length]\n"
  },
  {
    "path": "paddlespeech/t2s/modules/normalizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import nn\n\n\nclass ZScore(nn.Layer):\n    # feature last\n    def __init__(self, mu, sigma):\n        super().__init__()\n        self.register_buffer(\"mu\", mu)\n        self.register_buffer(\"sigma\", sigma)\n\n    def forward(self, x):\n        # NOTE: to be compatible with paddle's to_static, we must explicitly\n        # call multiply, or add, etc, instead of +-*/, etc.\n        return paddle.divide(paddle.subtract(x, self.mu), self.sigma)\n\n    def inverse(self, x):\n        # NOTE: to be compatible with paddle's to_static, we must explicitly\n        # call multiply, or add, etc, instead of +-*/, etc.\n        return paddle.add(paddle.multiply(x, self.sigma), self.mu)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/positional_encoding.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import Tensor\n\n__all__ = [\"sinusoid_position_encoding\", \"scaled_position_encoding\"]\n\n\ndef sinusoid_position_encoding(num_positions: int,\n                               feature_size: int,\n                               omega: float=1.0,\n                               start_pos: int=0,\n                               dtype=None) -> paddle.Tensor:\n    # return tensor shape (num_positions, feature_size)\n    # NOTE: to be compatible with paddle's to_static, we cannnot raise \n    # an exception here, take care of it by yourself\n    # if (feature_size % 2 != 0):\n    #     raise ValueError(\"size should be divisible by 2\")\n    dtype = dtype or paddle.get_default_dtype()\n\n    channel = paddle.arange(0, feature_size, 2, dtype=dtype)\n    index = paddle.arange(start_pos, start_pos + num_positions, 1, dtype=dtype)\n    denominator = channel / float(feature_size)\n    denominator = paddle.to_tensor([10000.0], dtype='float32')**denominator\n    p = (paddle.unsqueeze(index, -1) * omega) / denominator\n    encodings = paddle.zeros([num_positions, feature_size], dtype=dtype)\n    encodings[:, 0::2] = paddle.sin(p)\n    encodings[:, 1::2] = paddle.cos(p)\n    return encodings\n\n\ndef scaled_position_encoding(num_positions: int,\n                             feature_size: int,\n                             omega: Tensor,\n                             start_pos: int=0,\n                             dtype=None) -> Tensor:\n    # omega: Tensor (batch_size, )\n    # return tensor shape (batch_size, num_positions, feature_size)\n    # consider renaming this as batched positioning encoding\n    if (feature_size % 2 != 0):\n        raise ValueError(\"size should be divisible by 2\")\n    dtype = dtype or paddle.get_default_dtype()\n\n    channel = paddle.arange(0, feature_size, 2, dtype=dtype)\n    index = paddle.arange(\n        start_pos, start_pos + num_positions, 1, dtype=omega.dtype)\n    batch_size = omega.shape[0]\n    omega = paddle.unsqueeze(omega, [1, 2])\n    p = (paddle.unsqueeze(index, -1) *\n         omega) / (10000.0**(channel / float(feature_size)))\n    encodings = paddle.zeros(\n        [batch_size, num_positions, feature_size], dtype=dtype)\n    # it is nice to have fancy indexing and inplace operations\n    encodings[:, :, 0::2] = paddle.sin(p)\n    encodings[:, :, 1::2] = paddle.cos(p)\n    return encodings\n"
  },
  {
    "path": "paddlespeech/t2s/modules/pqmf.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Pseudo QMF modules.\"\"\"\nimport numpy as np\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\nfrom scipy.signal.windows import kaiser\n\n\ndef design_prototype_filter(taps=62, cutoff_ratio=0.142, beta=9.0):\n    \"\"\"Design prototype filter for PQMF.\n    This method is based on `A Kaiser window approach for the design of prototype\n    filters of cosine modulated filterbanks`_.\n\n    Args:\n        taps (int): \n            The number of filter taps.\n        cutoff_ratio (float): \n            Cut-off frequency ratio.\n        beta (float): \n            Beta coefficient for kaiser window.\n    Returns:\n        ndarray:\n            Impluse response of prototype filter (taps + 1,).\n        .. _`A Kaiser window approach for the design of prototype filters of cosine modulated filterbanks`:\n            https://ieeexplore.ieee.org/abstract/document/681427\n    \"\"\"\n    # check the arguments are valid\n    assert taps % 2 == 0, \"The number of taps mush be even number.\"\n    assert 0.0 < cutoff_ratio < 1.0, \"Cutoff ratio must be > 0.0 and < 1.0.\"\n    # make initial filter\n    omega_c = np.pi * cutoff_ratio\n    with np.errstate(invalid=\"ignore\"):\n        h_i = np.sin(omega_c * (np.arange(taps + 1) - 0.5 * taps)) / (\n            np.pi * (np.arange(taps + 1) - 0.5 * taps))\n    h_i[taps //\n        2] = np.cos(0) * cutoff_ratio  # fix nan due to indeterminate form\n\n    # apply kaiser window\n    w = kaiser(taps + 1, beta)\n    h = h_i * w\n\n    return h\n\n\nclass PQMF(nn.Layer):\n    \"\"\"PQMF module.\n    This module is based on `Near-perfect-reconstruction pseudo-QMF banks`_.\n    .. _`Near-perfect-reconstruction pseudo-QMF banks`:\n        https://ieeexplore.ieee.org/document/258122\n    \"\"\"\n\n    def __init__(self, subbands=4, taps=62, cutoff_ratio=0.142, beta=9.0):\n        \"\"\"Initilize PQMF module.\n        The cutoff_ratio and beta parameters are optimized for #subbands = 4.\n        See dicussion in https://github.com/kan-bayashi/ParallelWaveGAN/issues/195.\n\n        Args:\n            subbands (int): \n                The number of subbands.\n            taps (int): \n                The number of filter taps.\n            cutoff_ratio (float): \n                Cut-off frequency ratio.\n            beta (float): \n                Beta coefficient for kaiser window.\n        \"\"\"\n        super().__init__()\n\n        h_proto = design_prototype_filter(taps, cutoff_ratio, beta)\n        h_analysis = np.zeros((subbands, len(h_proto)))\n        h_synthesis = np.zeros((subbands, len(h_proto)))\n        for k in range(subbands):\n            h_analysis[k] = (\n                2 * h_proto * np.cos((2 * k + 1) * (np.pi / (2 * subbands)) * (\n                    np.arange(taps + 1) - (taps / 2)) + (-1)**k * np.pi / 4))\n            h_synthesis[k] = (\n                2 * h_proto * np.cos((2 * k + 1) * (np.pi / (2 * subbands)) * (\n                    np.arange(taps + 1) - (taps / 2)) - (-1)**k * np.pi / 4))\n\n        # convert to tensor\n        self.analysis_filter = paddle.to_tensor(\n            h_analysis, dtype=\"float32\").unsqueeze(1)\n        self.synthesis_filter = paddle.to_tensor(\n            h_synthesis, dtype=\"float32\").unsqueeze(0)\n\n        # filter for downsampling & upsampling\n        updown_filter = paddle.zeros(\n            (subbands, subbands, subbands), dtype=\"float32\")\n        for k in range(subbands):\n            updown_filter[k, k, 0] = 1.0\n        self.updown_filter = updown_filter\n        self.subbands = subbands\n        # keep padding info\n        self.pad_fn = nn.Pad1D(taps // 2, mode='constant', value=0.0)\n\n    def analysis(self, x):\n        \"\"\"Analysis with PQMF.\n        Args:\n            x (Tensor): \n                Input tensor (B, 1, T).\n        Returns:\n            Tensor: Output tensor (B, subbands, T // subbands).\n        \"\"\"\n        x = F.conv1d(self.pad_fn(x), self.analysis_filter)\n        return F.conv1d(x, self.updown_filter, stride=self.subbands)\n\n    def synthesis(self, x):\n        \"\"\"Synthesis with PQMF.\n        Args:\n            x (Tensor): \n                Input tensor (B, subbands, T // subbands).\n        Returns:\n            Tensor: Output tensor (B, 1, T).\n        \"\"\"\n        x = F.conv1d_transpose(\n            x, self.updown_filter * self.subbands, stride=self.subbands)\n\n        return F.conv1d(self.pad_fn(x), self.synthesis_filter)\n\n    # when converting dygraph to static graph, can not use self.pqmf.synthesis directly\n    def forward(self, x):\n        return self.synthesis(x)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/predictor/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/modules/predictor/duration_predictor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Duration predictor related modules.\"\"\"\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\n\nclass DurationPredictor(nn.Layer):\n    \"\"\"Duration predictor module.\n\n    This is a module of duration predictor described\n    in `FastSpeech: Fast, Robust and Controllable Text to Speech`_.\n    The duration predictor predicts a duration of each frame in log domain\n    from the hidden embeddings of encoder.\n\n    .. _`FastSpeech: Fast, Robust and Controllable Text to Speech`:\n        https://arxiv.org/pdf/1905.09263.pdf\n\n    Note\n    ----------\n    The calculation domain of outputs is different\n    between in `forward` and in `inference`. In `forward`,\n    the outputs are calculated in log domain but in `inference`,\n    those are calculated in linear domain.\n\n    \"\"\"\n\n    def __init__(self,\n                 idim,\n                 n_layers=2,\n                 n_chans=384,\n                 kernel_size=3,\n                 dropout_rate=0.1,\n                 offset=1.0):\n        \"\"\"Initilize duration predictor module.\n\n        Args:\n            idim (int):\n                Input dimension.\n            n_layers (int, optional): \n                Number of convolutional layers.\n            n_chans (int, optional): \n                Number of channels of convolutional layers.\n            kernel_size (int, optional): \n                Kernel size of convolutional layers.\n            dropout_rate (float, optional): \n                Dropout rate.\n            offset (float, optional): \n                Offset value to avoid nan in log domain.\n\n        \"\"\"\n        super().__init__()\n        self.offset = offset\n        self.conv = nn.LayerList()\n        for idx in range(n_layers):\n            in_chans = idim if idx == 0 else n_chans\n            self.conv.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        in_chans,\n                        n_chans,\n                        kernel_size,\n                        stride=1,\n                        padding=(kernel_size - 1) // 2, ),\n                    nn.ReLU(),\n                    LayerNorm(n_chans, dim=1),\n                    nn.Dropout(dropout_rate), ))\n        self.linear = nn.Linear(n_chans, 1, bias_attr=True)\n\n    def _forward(self, xs, x_masks=None, is_inference=False):\n        # (B, idim, Tmax)\n        xs = xs.transpose([0, 2, 1])\n        # (B, C, Tmax)\n        for f in self.conv:\n            xs = f(xs)\n\n        # NOTE: calculate in log domain\n        # (B, Tmax)\n        xs = self.linear(xs.transpose([0, 2, 1])).squeeze(-1)\n\n        if is_inference:\n            # NOTE: calculate in linear domain\n            xs = paddle.clip(paddle.round(xs.exp() - self.offset), min=0)\n\n        if x_masks is not None:\n            xs = masked_fill(xs, x_masks, 0.0)\n\n        return xs\n\n    def forward(self, xs, x_masks=None):\n        \"\"\"Calculate forward propagation.\n        Args:\n            xs(Tensor): \n                Batch of input sequences (B, Tmax, idim).\n            x_masks(ByteTensor, optional, optional): \n                Batch of masks indicating padded part (B, Tmax). (Default value = None)\n\n        Returns:\n            Tensor: Batch of predicted durations in log domain (B, Tmax).\n        \"\"\"\n        return self._forward(xs, x_masks, False)\n\n    def inference(self, xs, x_masks=None):\n        \"\"\"Inference duration.\n        Args:\n            xs(Tensor): \n                Batch of input sequences (B, Tmax, idim).\n            x_masks(Tensor(bool), optional, optional): \n                Batch of masks indicating padded part (B, Tmax). (Default value = None)\n\n        Returns:\n            Tensor: Batch of predicted durations in linear domain int64 (B, Tmax).\n        \"\"\"\n        return self._forward(xs, x_masks, True)\n\n\nclass DurationPredictorLoss(nn.Layer):\n    \"\"\"Loss function module for duration predictor.\n\n    The loss value is Calculated in log domain to make it Gaussian.\n\n    \"\"\"\n\n    def __init__(self, offset=1.0, reduction=\"mean\"):\n        \"\"\"Initilize duration predictor loss module.\n        Args:\n            offset (float, optional): Offset value to avoid nan in log domain.\n            reduction (str): Reduction type in loss calculation.\n        \"\"\"\n        super().__init__()\n        self.criterion = nn.MSELoss(reduction=reduction)\n        self.offset = offset\n\n    def forward(self, outputs, targets):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            outputs(Tensor): \n                Batch of prediction durations in log domain (B, T)\n            targets(Tensor): \n                Batch of groundtruth durations in linear domain (B, T)\n\n        Returns: \n            Tensor: Mean squared error loss value.\n\n        Note: \n            `outputs` is in log domain but `targets` is in linear domain.\n        \"\"\"\n        # NOTE: outputs is in log domain while targets in linear\n        targets = paddle.log(targets.cast(dtype='float32') + self.offset)\n        loss = self.criterion(outputs, targets)\n\n        return loss\n"
  },
  {
    "path": "paddlespeech/t2s/modules/predictor/length_regulator.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Length regulator related modules.\"\"\"\nimport numpy as np\nimport paddle\nfrom paddle import nn\n\n\nclass LengthRegulator(nn.Layer):\n    \"\"\"Length regulator module for feed-forward Transformer.\n\n    This is a module of length regulator described in\n    `FastSpeech: Fast, Robust and Controllable Text to Speech`_.\n    The length regulator expands char or\n    phoneme-level embedding features to frame-level by repeating each\n    feature based on the corresponding predicted durations.\n\n    .. _`FastSpeech: Fast, Robust and Controllable Text to Speech`:\n        https://arxiv.org/pdf/1905.09263.pdf\n\n    \"\"\"\n\n    def __init__(self, pad_value=0.0):\n        \"\"\"Initilize length regulator module.\n\n        Args:\n            pad_value (float, optional): \n                Value used for padding.\n\n        \"\"\"\n        super().__init__()\n        self.pad_value = pad_value\n\n    # expand_numpy is faster than expand\n    def expand_numpy(self, encodings: paddle.Tensor,\n                     durations: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"\n        encodings: (B, T, C)\n        durations: (B, T)\n        \"\"\"\n        #batch_size, t_enc = durations.shape  # linux\n        batch_size = paddle.shape(durations)[0]  # windows and mac\n        t_enc = paddle.shape(durations)[1]  # windows and mac\n        durations = durations.numpy()\n        slens = np.sum(durations, -1)\n        t_dec = np.max(slens)\n        M = np.zeros([batch_size, t_dec, t_enc])\n        for i in range(batch_size):\n            k = 0\n            for j in range(t_enc):\n                d = durations[i, j]\n                M[i, k:k + d, j] = 1\n                k += d\n        M = paddle.to_tensor(M, dtype=encodings.dtype)\n        encodings = paddle.matmul(M, encodings)\n        return encodings\n\n    def expand(self, encodings: paddle.Tensor,\n               durations: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"\n        encodings: (B, T, C)\n        durations: (B, T)\n        \"\"\"\n        batch_size, t_enc = paddle.shape(durations)\n        slens = paddle.sum(durations, -1)\n        t_dec = paddle.max(slens)\n        t_dec_1 = t_dec + 1\n        flatten_duration = paddle.cumsum(\n            paddle.reshape(durations, [batch_size * t_enc])) + 1\n        init = paddle.zeros(t_dec_1)\n        m_batch = batch_size * t_enc\n        M = paddle.zeros([t_dec_1, m_batch])\n        for i in range(m_batch):\n            d = flatten_duration[i]\n            m = paddle.concat(\n                [paddle.ones(d), paddle.zeros(t_dec_1 - d)], axis=0)\n            M[:, i] = m - init\n            init = m\n        M = paddle.reshape(M, shape=[t_dec_1, batch_size, t_enc])\n        M = M[1:t_dec_1, :, :]\n        M = paddle.transpose(M, (1, 0, 2))\n        encodings = paddle.matmul(M, encodings)\n        return encodings\n\n    def forward(self, xs, ds, alpha=1.0, is_inference=False):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            xs (Tensor): \n                Batch of sequences of char or phoneme embeddings (B, Tmax, D).\n            ds (Tensor(int64)): \n                Batch of durations of each frame (B, T).\n            alpha (float, optional): \n                Alpha value to control speed of speech.\n\n        Returns:\n            Tensor: replicated input tensor based on durations (B, T*, D).\n        \"\"\"\n\n        if alpha != 1.0:\n            assert alpha > 0\n            ds = paddle.round(ds.cast(dtype=paddle.float32) * alpha)\n        ds = ds.cast(dtype=paddle.int64)\n        '''\n        from distutils.version import LooseVersion\n        from paddlespeech.t2s.modules.nets_utils import pad_list\n        # 这里在 paddle 2.2.2 的动转静是不通的\n        # if LooseVersion(paddle.__version__) >= \"2.3.0\" or hasattr(paddle, 'repeat_interleave'):\n        # if LooseVersion(paddle.__version__) >= \"2.3.0\":\n        if hasattr(paddle, 'repeat_interleave'):\n            repeat = [paddle.repeat_interleave(x, d, axis=0) for x, d in zip(xs, ds)]\n            return pad_list(repeat, self.pad_value)\n        '''\n        if is_inference:\n            return self.expand(xs, ds)\n        else:\n            return self.expand_numpy(xs, ds)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/predictor/variance_predictor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Variance predictor related modules.\"\"\"\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\n\nclass VariancePredictor(nn.Layer):\n    \"\"\"Variance predictor module.\n\n    This is a module of variacne predictor described in `FastSpeech 2:\n    Fast and High-Quality End-to-End Text to Speech`_.\n\n    .. _`FastSpeech 2: Fast and High-Quality End-to-End Text to Speech`:\n        https://arxiv.org/abs/2006.04558\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            idim: int,\n            n_layers: int=2,\n            n_chans: int=384,\n            kernel_size: int=3,\n            bias: bool=True,\n            dropout_rate: float=0.5, ):\n        \"\"\"Initilize duration predictor module.\n\n        Args:\n            idim (int): \n                Input dimension.\n            n_layers (int, optional): \n                Number of convolutional layers.\n            n_chans (int, optional): \n                Number of channels of convolutional layers.\n            kernel_size (int, optional): \n                Kernel size of convolutional layers.\n            dropout_rate (float, optional): \n                Dropout rate.\n        \"\"\"\n        super().__init__()\n        self.conv = nn.LayerList()\n        for idx in range(n_layers):\n            in_chans = idim if idx == 0 else n_chans\n            self.conv.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        in_chans,\n                        n_chans,\n                        kernel_size,\n                        stride=1,\n                        padding=(kernel_size - 1) // 2,\n                        bias_attr=True, ),\n                    nn.ReLU(),\n                    LayerNorm(n_chans, dim=1),\n                    nn.Dropout(dropout_rate), ))\n\n        self.linear = nn.Linear(n_chans, 1, bias_attr=True)\n\n    def forward(self, xs: paddle.Tensor,\n                x_masks: paddle.Tensor=None) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            xs (Tensor): \n                Batch of input sequences (B, Tmax, idim).\n            x_masks (Tensor(bool), optional): \n                Batch of masks indicating padded part (B, Tmax, 1).\n\n        Returns:\n            Tensor: \n                Batch of predicted sequences (B, Tmax, 1).\n        \"\"\"\n        # (B, idim, Tmax)\n        xs = xs.transpose([0, 2, 1])\n        # (B, C, Tmax)\n        for f in self.conv:\n            # (B, C, Tmax)\n            xs = f(xs)\n        # (B, Tmax, 1)\n        xs = self.linear(xs.transpose([0, 2, 1]))\n\n        if x_masks is not None:\n            xs = masked_fill(xs, x_masks, 0.0)\n        return xs\n"
  },
  {
    "path": "paddlespeech/t2s/modules/residual_block.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.t2s.modules.activation import get_activation\n\n\nclass WaveNetResidualBlock(nn.Layer):\n    \"\"\"A gated activation unit composed of an 1D convolution, a gated tanh\n    unit and parametric redidual and skip connections. For more details, \n    refer to `WaveNet: A Generative Model for Raw Audio <https://arxiv.org/abs/1609.03499>`_.\n\n    Args:\n        kernel_size (int, optional): \n            Kernel size of the 1D convolution, by default 3\n        residual_channels (int, optional): \n            Feature size of the residual output(and also the input), by default 64\n        gate_channels (int, optional): \n            Output feature size of the 1D convolution, by default 128\n        skip_channels (int, optional): \n            Feature size of the skip output, by default 64\n        aux_channels (int, optional): \n            Feature size of the auxiliary input (e.g. spectrogram), by default 80\n        dropout (float, optional): \n            Probability of the dropout before the 1D convolution, by default 0.\n        dilation (int, optional): \n            Dilation of the 1D convolution, by default 1\n        bias (bool, optional): \n            Whether to use bias in the 1D convolution, by default True\n        use_causal_conv (bool, optional): \n            Whether to use causal padding for the 1D convolution, by default False\n    \"\"\"\n\n    def __init__(self,\n                 kernel_size: int=3,\n                 residual_channels: int=64,\n                 gate_channels: int=128,\n                 skip_channels: int=64,\n                 aux_channels: int=80,\n                 dropout: float=0.,\n                 dilation: int=1,\n                 bias: bool=True,\n                 use_causal_conv: bool=False):\n        super().__init__()\n        self.dropout = dropout\n        if use_causal_conv:\n            padding = (kernel_size - 1) * dilation\n        else:\n            assert kernel_size % 2 == 1\n            padding = (kernel_size - 1) // 2 * dilation\n        self.use_causal_conv = use_causal_conv\n\n        self.conv = nn.Conv1D(\n            residual_channels,\n            gate_channels,\n            kernel_size,\n            padding=padding,\n            dilation=dilation,\n            bias_attr=bias)\n        if aux_channels is not None:\n            self.conv1x1_aux = nn.Conv1D(\n                aux_channels, gate_channels, kernel_size=1, bias_attr=False)\n        else:\n            self.conv1x1_aux = None\n\n        gate_out_channels = gate_channels // 2\n        self.conv1x1_out = nn.Conv1D(\n            gate_out_channels, residual_channels, kernel_size=1, bias_attr=bias)\n        self.conv1x1_skip = nn.Conv1D(\n            gate_out_channels, skip_channels, kernel_size=1, bias_attr=bias)\n\n    def forward(self, x, c):\n        \"\"\"\n        Args:\n            x (Tensor): \n                the input features. Shape (N, C_res, T)\n            c (Tensor):\n                the auxiliary input. Shape (N, C_aux, T)\n\n        Returns:\n            res (Tensor): \n                Shape (N, C_res, T), the residual output, which is used as the \n                input of the next ResidualBlock in a stack of ResidualBlocks.\n            skip (Tensor): \n                Shape (N, C_skip, T), the skip output, which is collected among\n                each layer in a stack of ResidualBlocks.\n        \"\"\"\n        x_input = x\n        x = F.dropout(x, self.dropout, training=self.training)\n        x = self.conv(x)\n        x = x[:, :, x_input.shape[-1]] if self.use_causal_conv else x\n        if c is not None:\n            c = self.conv1x1_aux(c)\n            x += c\n\n        a, b = paddle.chunk(x, 2, axis=1)\n        x = paddle.tanh(a) * F.sigmoid(b)\n\n        skip = self.conv1x1_skip(x)\n        res = (self.conv1x1_out(x) + x_input) * math.sqrt(0.5)\n        return res, skip\n\n\nclass HiFiGANResidualBlock(nn.Layer):\n    \"\"\"Residual block module in HiFiGAN.\"\"\"\n\n    def __init__(\n            self,\n            kernel_size: int=3,\n            channels: int=512,\n            dilations: List[int]=(1, 3, 5),\n            bias: bool=True,\n            use_additional_convs: bool=True,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.1},\n    ):\n        \"\"\"Initialize HiFiGANResidualBlock module.\n        Args:\n            kernel_size (int): \n                Kernel size of dilation convolution layer.\n            channels (int): \n                Number of channels for convolution layer.\n            dilations (List[int]): \n                List of dilation factors.\n            use_additional_convs (bool): \n                Whether to use additional convolution layers.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (dict): \n                Hyperparameters for activation function.\n        \"\"\"\n        super().__init__()\n\n        self.use_additional_convs = use_additional_convs\n        self.convs1 = nn.LayerList()\n        if use_additional_convs:\n            self.convs2 = nn.LayerList()\n        assert kernel_size % 2 == 1, \"Kernel size must be odd number.\"\n\n        for dilation in dilations:\n            self.convs1.append(\n                nn.Sequential(\n                    get_activation(nonlinear_activation, **\n                                   nonlinear_activation_params),\n                    nn.Conv1D(\n                        channels,\n                        channels,\n                        kernel_size,\n                        1,\n                        dilation=dilation,\n                        bias_attr=bias,\n                        padding=(kernel_size - 1) // 2 * dilation, ), ))\n            if use_additional_convs:\n                self.convs2.append(\n                    nn.Sequential(\n                        get_activation(nonlinear_activation, **\n                                       nonlinear_activation_params),\n                        nn.Conv1D(\n                            channels,\n                            channels,\n                            kernel_size,\n                            1,\n                            dilation=1,\n                            bias_attr=bias,\n                            padding=(kernel_size - 1) // 2, ), ))\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input tensor (B, channels, T).\n        Returns:\n            Tensor: Output tensor (B, channels, T).\n        \"\"\"\n        for idx in range(len(self.convs1)):\n            xt = self.convs1[idx](x)\n            if self.use_additional_convs:\n                xt = self.convs2[idx](xt)\n            x = xt + x\n        return x\n"
  },
  {
    "path": "paddlespeech/t2s/modules/residual_stack.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Residual stack module in MelGAN.\"\"\"\nfrom typing import Any\nfrom typing import Dict\n\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.causal_conv import CausalConv1D\n\n\nclass ResidualStack(nn.Layer):\n    \"\"\"Residual stack module introduced in MelGAN.\"\"\"\n\n    def __init__(\n            self,\n            kernel_size: int=3,\n            channels: int=32,\n            dilation: int=1,\n            bias: bool=True,\n            nonlinear_activation: str=\"leakyrelu\",\n            nonlinear_activation_params: Dict[str, Any]={\"negative_slope\": 0.2},\n            pad: str=\"Pad1D\",\n            pad_params: Dict[str, Any]={\"mode\": \"reflect\"},\n            use_causal_conv: bool=False, ):\n        \"\"\"Initialize ResidualStack module.\n\n        Args:\n            kernel_size (int): \n                Kernel size of dilation convolution layer.\n            channels (int): \n                Number of channels of convolution layers.\n            dilation (int): \n                Dilation factor.\n            bias (bool): \n                Whether to add bias parameter in convolution layers.\n            nonlinear_activation (str): \n                Activation function module name.\n            nonlinear_activation_params (Dict[str,Any]): \n                Hyperparameters for activation function.\n            pad (str): \n                Padding function module name before dilated convolution layer.\n            pad_params (Dict[str, Any]): \n                Hyperparameters for padding function.\n            use_causal_conv (bool): \n                Whether to use causal convolution.\n        \"\"\"\n        super().__init__()\n        # for compatibility\n        if nonlinear_activation:\n            nonlinear_activation = nonlinear_activation.lower()\n\n        # defile residual stack part\n        if not use_causal_conv:\n            assert (kernel_size - 1\n                    ) % 2 == 0, \"Not support even number kernel size.\"\n            self.stack = nn.Sequential(\n                get_activation(nonlinear_activation,\n                               **nonlinear_activation_params),\n                getattr(nn, pad)((kernel_size - 1) // 2 * dilation,\n                                 **pad_params),\n                nn.Conv1D(\n                    channels,\n                    channels,\n                    kernel_size,\n                    dilation=dilation,\n                    bias_attr=bias),\n                get_activation(nonlinear_activation,\n                               **nonlinear_activation_params),\n                nn.Conv1D(channels, channels, 1, bias_attr=bias), )\n        else:\n            self.stack = nn.Sequential(\n                get_activation(nonlinear_activation,\n                               **nonlinear_activation_params),\n                CausalConv1D(\n                    channels,\n                    channels,\n                    kernel_size,\n                    dilation=dilation,\n                    bias=bias,\n                    pad=pad,\n                    pad_params=pad_params, ),\n                get_activation(nonlinear_activation,\n                               **nonlinear_activation_params),\n                nn.Conv1D(channels, channels, 1, bias_attr=bias), )\n\n        # defile extra layer for skip connection\n        self.skip_layer = nn.Conv1D(channels, channels, 1, bias_attr=bias)\n\n    def forward(self, c):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            c (Tensor): \n                Input tensor (B, channels, T).\n        Returns:     \n            Tensor: Output tensor (B, chennels, T).\n        \"\"\"\n        return self.stack(c) + self.skip_layer(c)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/style_encoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Style encoder of GST-Tacotron.\"\"\"\nfrom typing import Sequence\n\nimport paddle\nfrom paddle import nn\nfrom typeguard import typechecked\n\nfrom paddlespeech.t2s.modules.transformer.attention import MultiHeadedAttention as BaseMultiHeadedAttention\n\n\nclass StyleEncoder(nn.Layer):\n    \"\"\"Style encoder.\n\n    This module is style encoder introduced in `Style Tokens: Unsupervised Style\n    Modeling, Control and Transfer in End-to-End Speech Synthesis`.\n\n    .. _`Style Tokens: Unsupervised Style Modeling, Control and Transfer in End-to-End\n        Speech Synthesis`: https://arxiv.org/abs/1803.09017\n    \n    Args:\n        idim (int, optional): \n            Dimension of the input mel-spectrogram.\n        gst_tokens (int, optional): \n            The number of GST embeddings.\n        gst_token_dim (int, optional): \n            Dimension of each GST embedding.\n        gst_heads (int, optional): \n            The number of heads in GST multihead attention.\n        conv_layers (int, optional): \n            The number of conv layers in the reference encoder.\n        conv_chans_list (Sequence[int], optional): \n            List of the number of channels of conv layers in the referece encoder.\n        conv_kernel_size (int, optional): \n            Kernal size of conv layers in the reference encoder.\n        conv_stride (int, optional): \n            Stride size of conv layers in the reference encoder.\n        gru_layers (int, optional): \n            The number of GRU layers in the reference encoder.\n        gru_units (int, optional):\n            The number of GRU units in the reference encoder.\n\n    Todo:\n        * Support manual weight specification in inference.\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            idim: int=80,\n            gst_tokens: int=10,\n            gst_token_dim: int=256,\n            gst_heads: int=4,\n            conv_layers: int=6,\n            conv_chans_list: Sequence[int]=(32, 32, 64, 64, 128, 128),\n            conv_kernel_size: int=3,\n            conv_stride: int=2,\n            gru_layers: int=1,\n            gru_units: int=128, ):\n        \"\"\"Initilize global style encoder module.\"\"\"\n        super().__init__()\n\n        self.ref_enc = ReferenceEncoder(\n            idim=idim,\n            conv_layers=conv_layers,\n            conv_chans_list=conv_chans_list,\n            conv_kernel_size=conv_kernel_size,\n            conv_stride=conv_stride,\n            gru_layers=gru_layers,\n            gru_units=gru_units, )\n        self.stl = StyleTokenLayer(\n            ref_embed_dim=gru_units,\n            gst_tokens=gst_tokens,\n            gst_token_dim=gst_token_dim,\n            gst_heads=gst_heads, )\n\n    def forward(self, speech: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            speech (Tensor): \n                Batch of padded target features (B, Lmax, odim).\n\n        Returns: \n            Tensor: Style token embeddings (B, token_dim).\n\n        \"\"\"\n        ref_embs = self.ref_enc(speech)\n        style_embs = self.stl(ref_embs)\n\n        return style_embs\n\n\nclass ReferenceEncoder(nn.Layer):\n    \"\"\"Reference encoder module.\n\n    This module is refernece encoder introduced in `Style Tokens: Unsupervised Style\n    Modeling, Control and Transfer in End-to-End Speech Synthesis`.\n\n    .. _`Style Tokens: Unsupervised Style Modeling, Control and Transfer in End-to-End\n        Speech Synthesis`: https://arxiv.org/abs/1803.09017\n    \n    Args:\n        idim (int, optional): \n            Dimension of the input mel-spectrogram.\n        conv_layers (int, optional): \n            The number of conv layers in the reference encoder.\n        conv_chans_list: (Sequence[int], optional): \n            List of the number of channels of conv layers in the referece encoder.\n        conv_kernel_size (int, optional): \n            Kernal size of conv layers in the reference encoder.\n        conv_stride (int, optional): \n            Stride size of conv layers in the reference encoder.\n        gru_layers (int, optional): \n            The number of GRU layers in the reference encoder.\n        gru_units (int, optional): \n            The number of GRU units in the reference encoder.\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            idim=80,\n            conv_layers: int=6,\n            conv_chans_list: Sequence[int]=(32, 32, 64, 64, 128, 128),\n            conv_kernel_size: int=3,\n            conv_stride: int=2,\n            gru_layers: int=1,\n            gru_units: int=128, ):\n        \"\"\"Initilize reference encoder module.\"\"\"\n        super().__init__()\n\n        # check hyperparameters are valid\n        assert conv_kernel_size % 2 == 1, \"kernel size must be odd.\"\n        assert (\n            len(conv_chans_list) == conv_layers\n        ), \"the number of conv layers and length of channels list must be the same.\"\n\n        convs = []\n        padding = (conv_kernel_size - 1) // 2\n        for i in range(conv_layers):\n            conv_in_chans = 1 if i == 0 else conv_chans_list[i - 1]\n            conv_out_chans = conv_chans_list[i]\n            convs += [\n                nn.Conv2D(\n                    conv_in_chans,\n                    conv_out_chans,\n                    kernel_size=conv_kernel_size,\n                    stride=conv_stride,\n                    padding=padding,\n                    # Do not use bias due to the following batch norm\n                    bias_attr=False, ),\n                nn.BatchNorm2D(conv_out_chans),\n                nn.ReLU(),\n            ]\n        self.convs = nn.Sequential(*convs)\n\n        self.conv_layers = conv_layers\n        self.kernel_size = conv_kernel_size\n        self.stride = conv_stride\n        self.padding = padding\n\n        # get the number of GRU input units\n        gru_in_units = idim\n        for i in range(conv_layers):\n            gru_in_units = (gru_in_units - conv_kernel_size + 2 * padding\n                            ) // conv_stride + 1\n        gru_in_units *= conv_out_chans\n        self.gru = nn.GRU(gru_in_units, gru_units, gru_layers, time_major=False)\n\n    def forward(self, speech: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n        Args:\n            speech (Tensor): \n                Batch of padded target features (B, Lmax, idim).\n\n        Returns:\n            Tensor: Reference embedding (B, gru_units)\n\n        \"\"\"\n        batch_size = speech.shape[0]\n        # (B, 1, Lmax, idim)\n        xs = speech.unsqueeze(1)\n        # (B, Lmax', conv_out_chans, idim')\n        hs = self.convs(xs).transpose([0, 2, 1, 3])\n        time_length = hs.shape[1]\n        # (B, Lmax', gru_units)\n        hs = hs.reshape(shape=[batch_size, time_length, -1])\n        self.gru.flatten_parameters()\n        # (gru_layers, batch_size, gru_units)\n        _, ref_embs = self.gru(hs)\n        # (batch_size, gru_units)\n        ref_embs = ref_embs[-1]\n\n        return ref_embs\n\n\nclass StyleTokenLayer(nn.Layer):\n    \"\"\"Style token layer module.\n\n    This module is style token layer introduced in `Style Tokens: Unsupervised Style\n    Modeling, Control and Transfer in End-to-End Speech Synthesis`.\n\n    .. _`Style Tokens: Unsupervised Style Modeling, Control and Transfer in End-to-End\n        Speech Synthesis`: https://arxiv.org/abs/1803.09017\n    Args:\n        ref_embed_dim (int, optional): \n            Dimension of the input reference embedding.\n        gst_tokens (int, optional): \n            The number of GST embeddings.\n        gst_token_dim (int, optional): \n            Dimension of each GST embedding.\n        gst_heads (int, optional): \n            The number of heads in GST multihead attention.\n        dropout_rate (float, optional): \n            Dropout rate in multi-head attention.\n\n    \"\"\"\n\n    @typechecked\n    def __init__(\n            self,\n            ref_embed_dim: int=128,\n            gst_tokens: int=10,\n            gst_token_dim: int=256,\n            gst_heads: int=4,\n            dropout_rate: float=0.0, ):\n        \"\"\"Initilize style token layer module.\"\"\"\n        super().__init__()\n\n        gst_embs = paddle.randn(shape=[gst_tokens, gst_token_dim // gst_heads])\n        self.gst_embs = paddle.create_parameter(\n            shape=gst_embs.shape,\n            dtype=str(gst_embs.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(gst_embs))\n        self.mha = MultiHeadedAttention(\n            q_dim=ref_embed_dim,\n            k_dim=gst_token_dim // gst_heads,\n            v_dim=gst_token_dim // gst_heads,\n            n_head=gst_heads,\n            n_feat=gst_token_dim,\n            dropout_rate=dropout_rate, )\n\n    def forward(self, ref_embs: paddle.Tensor) -> paddle.Tensor:\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            ref_embs (Tensor):\n                Reference embeddings (B, ref_embed_dim).\n\n        Returns: \n            Tensor: Style token embeddings (B, gst_token_dim).\n\n        \"\"\"\n        batch_size = ref_embs.shape[0]\n        # (num_tokens, token_dim) -> (batch_size, num_tokens, token_dim)\n        gst_embs = paddle.tanh(self.gst_embs).unsqueeze(0).expand(\n            [batch_size, -1, -1])\n        # (batch_size, 1 ,ref_embed_dim)\n        ref_embs = ref_embs.unsqueeze(1)\n        style_embs = self.mha(ref_embs, gst_embs, gst_embs, None)\n\n        return style_embs.squeeze(1)\n\n\nclass MultiHeadedAttention(BaseMultiHeadedAttention):\n    \"\"\"Multi head attention module with different input dimension.\"\"\"\n\n    def __init__(self, q_dim, k_dim, v_dim, n_head, n_feat, dropout_rate=0.0):\n        \"\"\"Initialize multi head attention module.\"\"\"\n        # Do not use super().__init__() here since we want to\n        # overwrite BaseMultiHeadedAttention.__init__() method.\n        nn.Layer.__init__(self)\n        assert n_feat % n_head == 0\n        # We assume d_v always equals d_k\n        self.d_k = n_feat // n_head\n        self.h = n_head\n        self.linear_q = nn.Linear(q_dim, n_feat)\n        self.linear_k = nn.Linear(k_dim, n_feat)\n        self.linear_v = nn.Linear(v_dim, n_feat)\n        self.linear_out = nn.Linear(n_feat, n_feat)\n        self.attn = None\n        self.dropout = nn.Dropout(p=dropout_rate)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/tacotron2/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/modules/tacotron2/attentions.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Attention modules for RNN.\"\"\"\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\nfrom paddlespeech.t2s.modules.nets_utils import make_pad_mask\n\n\ndef _apply_attention_constraint(e,\n                                last_attended_idx,\n                                backward_window=1,\n                                forward_window=3):\n    \"\"\"Apply monotonic attention constraint.\n\n    This function apply the monotonic attention constraint\n    introduced in `Deep Voice 3: Scaling\n    Text-to-Speech with Convolutional Sequence Learning`_.\n\n    Args:\n        e(Tensor): \n            Attention energy before applying softmax (1, T).\n        last_attended_idx(int): \n            The index of the inputs of the last attended [0, T].\n        backward_window(int, optional, optional): \n            Backward window size in attention constraint. (Default value = 1)\n        forward_window(int, optional, optional): \n            Forward window size in attetion constraint. (Default value = 3)\n\n    Returns:\n        Tensor: Monotonic constrained attention energy (1, T).\n\n    .. _`Deep Voice 3: Scaling Text-to-Speech with Convolutional Sequence Learning`:\n        https://arxiv.org/abs/1710.07654\n\n    \"\"\"\n    # for dygraph to static graph\n    # if e.shape[0] != 1:\n    #     raise NotImplementedError(\n    #         \"Batch attention constraining is not yet supported.\")\n    backward_idx = paddle.cast(\n        last_attended_idx - backward_window, dtype='int64')\n    forward_idx = paddle.cast(last_attended_idx + forward_window, dtype='int64')\n    if backward_idx > 0:\n        e[:, :backward_idx] = -float(\"inf\")\n    if forward_idx < paddle.shape(e)[1]:\n        e[:, forward_idx:] = -float(\"inf\")\n    return e\n\n\nclass AttLoc(nn.Layer):\n    \"\"\"location-aware attention module.\n\n    Reference: Attention-Based Models for Speech Recognition\n        (https://arxiv.org/pdf/1506.07503.pdf)\n\n    Args:\n        eprojs (int): \n            projection-units of encoder\n        dunits (int): \n            units of decoder\n        att_dim (int): \n            attention dimension\n        aconv_chans (int): \n            channels of attention convolution\n        aconv_filts (int): \n            filter size of attention convolution\n        han_mode (bool): \n            flag to swith on mode of hierarchical attention and not store pre_compute_enc_h\n    \"\"\"\n\n    def __init__(self,\n                 eprojs,\n                 dunits,\n                 att_dim,\n                 aconv_chans,\n                 aconv_filts,\n                 han_mode=False):\n        super().__init__()\n        self.mlp_enc = nn.Linear(eprojs, att_dim)\n        self.mlp_dec = nn.Linear(dunits, att_dim, bias_attr=False)\n        self.mlp_att = nn.Linear(aconv_chans, att_dim, bias_attr=False)\n        self.loc_conv = nn.Conv2D(\n            1,\n            aconv_chans,\n            (1, 2 * aconv_filts + 1),\n            padding=(0, aconv_filts),\n            bias_attr=False, )\n        self.gvec = nn.Linear(att_dim, 1)\n\n        self.dunits = dunits\n        self.eprojs = eprojs\n        self.att_dim = att_dim\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n        self.han_mode = han_mode\n\n    def reset(self):\n        \"\"\"reset states\"\"\"\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n\n    def forward(\n            self,\n            enc_hs_pad,\n            enc_hs_len,\n            dec_z,\n            att_prev,\n            scaling=2.0,\n            last_attended_idx=-1,\n            backward_window=1,\n            forward_window=3, ):\n        \"\"\"Calculate AttLoc forward propagation.\n        Args:\n            enc_hs_pad(Tensor): \n                padded encoder hidden state (B, T_max, D_enc)\n            enc_hs_len(Tensor): \n                padded encoder hidden state length (B)\n            dec_z(Tensor dec_z): \n                decoder hidden state (B, D_dec)\n            att_prev(Tensor): \n                previous attention weight (B, T_max)\n            scaling(float, optional): \n                scaling parameter before applying softmax (Default value = 2.0)\n            forward_window(Tensor, optional): \n                    forward window size when constraining attention (Default value = 3)\n            last_attended_idx(int, optional): \n                index of the inputs of the last attended (Default value = None)\n            backward_window(int, optional): \n                backward window size in attention constraint (Default value = 1)\n            forward_window(int, optional): \n                    forward window size in attetion constraint (Default value = 3)\n        Returns:\n            Tensor: \n                attention weighted encoder state (B, D_enc)\n            Tensor: \n                previous attention weights (B, T_max)\n        \"\"\"\n        batch = paddle.shape(enc_hs_pad)[0]\n        # pre-compute all h outside the decoder loop\n        if self.pre_compute_enc_h is None or self.han_mode:\n            # (utt, frame, hdim)\n            self.enc_h = enc_hs_pad\n            self.h_length = paddle.shape(self.enc_h)[1]\n            # (utt, frame, att_dim)\n            self.pre_compute_enc_h = self.mlp_enc(self.enc_h)\n\n        if dec_z is None:\n            dec_z = paddle.zeros([batch, self.dunits])\n        else:\n            dec_z = dec_z.reshape([batch, self.dunits])\n\n        # initialize attention weight with uniform dist.\n        if paddle.sum(att_prev) == 0:\n            # if no bias, 0 0-pad goes 0\n            att_prev = 1.0 - make_pad_mask(enc_hs_len)\n            att_prev = att_prev / enc_hs_len.unsqueeze(-1).astype(\n                att_prev.dtype)\n        else:\n            att_prev = att_prev.unsqueeze(-1)\n\n        # att_prev: (utt, frame) -> (utt, 1, 1, frame)\n        # -> (utt, att_conv_chans, 1, frame)\n        att_conv = self.loc_conv(att_prev.reshape([batch, 1, 1, self.h_length]))\n        # att_conv: (utt, att_conv_chans, 1, frame) -> (utt, frame, att_conv_chans)\n        att_conv = att_conv.squeeze(2).transpose([0, 2, 1])\n        # att_conv: (utt, frame, att_conv_chans) -> (utt, frame, att_dim)\n        att_conv = self.mlp_att(att_conv)\n        # dec_z_tiled: (utt, frame, att_dim)        \n        dec_z_tiled = self.mlp_dec(dec_z).reshape([batch, 1, self.att_dim])\n\n        # dot with gvec\n        # (utt, frame, att_dim) -> (utt, frame)\n        e = paddle.tanh(att_conv + self.pre_compute_enc_h + dec_z_tiled)\n        e = self.gvec(e).squeeze(2)\n\n        # NOTE: consider zero padding when compute w.\n        if self.mask is None:\n            self.mask = make_pad_mask(enc_hs_len)\n\n        e = masked_fill(e, self.mask, -float(\"inf\"))\n        # apply monotonic attention constraint (mainly for TTS)\n        if last_attended_idx != -1:\n            e = _apply_attention_constraint(e, last_attended_idx,\n                                            backward_window, forward_window)\n\n        w = F.softmax(scaling * e, axis=1)\n\n        # weighted sum over frames\n        # utt x hdim\n        c = paddle.sum(\n            self.enc_h * w.reshape([batch, self.h_length, 1]), axis=1)\n        return c, w\n\n\nclass AttForward(nn.Layer):\n    \"\"\"Forward attention module.\n    Reference\n    ----------\n    Forward attention in sequence-to-sequence acoustic modeling for speech synthesis\n        (https://arxiv.org/pdf/1807.06736.pdf)\n\n    Args:\n        eprojs (int): \n            projection-units of encoder\n        dunits (int): \n            units of decoder\n        att_dim (int): \n            attention dimension\n        aconv_chans (int): \n            channels of attention convolution\n        aconv_filts (int): \n            filter size of attention convolution\n    \"\"\"\n\n    def __init__(self, eprojs, dunits, att_dim, aconv_chans, aconv_filts):\n        super().__init__()\n        self.mlp_enc = nn.Linear(eprojs, att_dim)\n        self.mlp_dec = nn.Linear(dunits, att_dim, bias_attr=False)\n        self.mlp_att = nn.Linear(aconv_chans, att_dim, bias_attr=False)\n        self.loc_conv = nn.Conv2D(\n            1,\n            aconv_chans,\n            (1, 2 * aconv_filts + 1),\n            padding=(0, aconv_filts),\n            bias_attr=False, )\n        self.gvec = nn.Linear(att_dim, 1)\n        self.dunits = dunits\n        self.eprojs = eprojs\n        self.att_dim = att_dim\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n\n    def reset(self):\n        \"\"\"reset states\"\"\"\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n\n    def forward(\n            self,\n            enc_hs_pad,\n            enc_hs_len,\n            dec_z,\n            att_prev,\n            scaling=1.0,\n            last_attended_idx=None,\n            backward_window=1,\n            forward_window=3, ):\n        \"\"\"Calculate AttForward forward propagation.\n\n        Args:\n            enc_hs_pad(Tensor): \n                padded encoder hidden state (B, T_max, D_enc)\n            enc_hs_len(list): \n                padded encoder hidden state length (B,)\n            dec_z(Tensor): \n                decoder hidden state (B, D_dec)\n            att_prev(Tensor): \n                attention weights of previous step (B, T_max)\n            scaling(float, optional): \n                scaling parameter before applying softmax (Default value = 1.0)\n            last_attended_idx(int, optional): \n                index of the inputs of the last attended (Default value = None)\n            backward_window(int, optional): \n                backward window size in attention constraint (Default value = 1)\n            forward_window(int, optional):  \n                (Default value = 3)\n\n        Returns:\n            Tensor: \n                attention weighted encoder state (B, D_enc)\n            Tensor: \n                previous attention weights (B, T_max)\n        \"\"\"\n        batch = len(enc_hs_pad)\n        # pre-compute all h outside the decoder loop\n        if self.pre_compute_enc_h is None:\n            self.enc_h = enc_hs_pad  # utt x frame x hdim\n            self.h_length = paddle.shape(self.enc_h)[1]\n            # utt x frame x att_dim\n            self.pre_compute_enc_h = self.mlp_enc(self.enc_h)\n\n        if dec_z is None:\n            dec_z = paddle.zeros([batch, self.dunits])\n        else:\n            dec_z = dec_z.reshape([batch, self.dunits])\n\n        if att_prev is None:\n            # initial attention will be [1, 0, 0, ...]\n            att_prev = paddle.zeros([*paddle.shape(enc_hs_pad)[:2]])\n            att_prev[:, 0] = 1.0\n\n        # att_prev: utt x frame -> utt x 1 x 1 x frame\n        # -> utt x att_conv_chans x 1 x frame\n        att_conv = self.loc_conv(att_prev.reshape([batch, 1, 1, self.h_length]))\n        # att_conv: utt x att_conv_chans x 1 x frame -> utt x frame x att_conv_chans\n        att_conv = att_conv.squeeze(2).transpose([0, 2, 1])\n        # att_conv: utt x frame x att_conv_chans -> utt x frame x att_dim\n        att_conv = self.mlp_att(att_conv)\n\n        # dec_z_tiled: utt x frame x att_dim\n        dec_z_tiled = self.mlp_dec(dec_z).unsqueeze(1)\n\n        # dot with gvec\n        # utt x frame x att_dim -> utt x frame\n        e = self.gvec(\n            paddle.tanh(self.pre_compute_enc_h + dec_z_tiled +\n                        att_conv)).squeeze(2)\n\n        # NOTE: consider zero padding when compute w.\n        if self.mask is None:\n            self.mask = make_pad_mask(enc_hs_len)\n        e = masked_fill(e, self.mask, -float(\"inf\"))\n\n        # apply monotonic attention constraint (mainly for TTS)\n        if last_attended_idx is not None:\n            e = _apply_attention_constraint(e, last_attended_idx,\n                                            backward_window, forward_window)\n\n        w = F.softmax(scaling * e, axis=1)\n\n        # forward attention\n        att_prev_shift = F.pad(att_prev, (0, 0, 1, 0))[:, :-1]\n\n        w = (att_prev + att_prev_shift) * w\n        # NOTE: clip is needed to avoid nan gradient\n        w = F.normalize(paddle.clip(w, 1e-6), p=1, axis=1)\n\n        # weighted sum over flames\n        # utt x hdim\n        # NOTE use bmm instead of sum(*)\n        c = paddle.sum(self.enc_h * w.unsqueeze(-1), axis=1)\n\n        return c, w\n\n\nclass AttForwardTA(nn.Layer):\n    \"\"\"Forward attention with transition agent module.\n    Reference:\n        Forward attention in sequence-to-sequence acoustic modeling for speech synthesis\n            (https://arxiv.org/pdf/1807.06736.pdf)\n\n    Args:\n        eunits (int): \n            units of encoder\n        dunits (int): \n            units of decoder\n        att_dim (int): \n            attention dimension\n        aconv_chans (int):  \n            channels of attention convolution\n        aconv_filts (int): \n            filter size of attention convolution\n        odim (int): \n            output dimension\n    \"\"\"\n\n    def __init__(self, eunits, dunits, att_dim, aconv_chans, aconv_filts, odim):\n        super().__init__()\n        self.mlp_enc = nn.Linear(eunits, att_dim)\n        self.mlp_dec = nn.Linear(dunits, att_dim, bias_attr=False)\n        self.mlp_ta = nn.Linear(eunits + dunits + odim, 1)\n        self.mlp_att = nn.Linear(aconv_chans, att_dim, bias_attr=False)\n        self.loc_conv = nn.Conv2D(\n            1,\n            aconv_chans,\n            (1, 2 * aconv_filts + 1),\n            padding=(0, aconv_filts),\n            bias_attr=False, )\n        self.gvec = nn.Linear(att_dim, 1)\n        self.dunits = dunits\n        self.eunits = eunits\n        self.att_dim = att_dim\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n        self.trans_agent_prob = 0.5\n\n    def reset(self):\n        self.h_length = None\n        self.enc_h = None\n        self.pre_compute_enc_h = None\n        self.mask = None\n        self.trans_agent_prob = 0.5\n\n    def forward(\n            self,\n            enc_hs_pad,\n            enc_hs_len,\n            dec_z,\n            att_prev,\n            out_prev,\n            scaling=1.0,\n            last_attended_idx=None,\n            backward_window=1,\n            forward_window=3, ):\n        \"\"\"Calculate AttForwardTA forward propagation.\n\n        Args:\n            enc_hs_pad(Tensor): \n                padded encoder hidden state (B, Tmax, eunits)\n            enc_hs_len(list Tensor): \n                padded encoder hidden state length (B,)\n            dec_z(Tensor): \n                decoder hidden state (B, dunits)\n            att_prev(Tensor): \n                attention weights of previous step (B, T_max)\n            out_prev(Tensor): \n                decoder outputs of previous step (B, odim)\n            scaling(float, optional): \n                scaling parameter before applying softmax (Default value = 1.0)\n            last_attended_idx(int, optional): \n                index of the inputs of the last attended (Default value = None)\n            backward_window(int, optional): \n                backward window size in attention constraint (Default value = 1)\n            forward_window(int, optional):  \n                (Default value = 3)\n\n        Returns:\n            Tensor: \n                attention weighted encoder state (B, dunits)\n            Tensor: \n                previous attention weights (B, Tmax)\n        \"\"\"\n        batch = len(enc_hs_pad)\n        # pre-compute all h outside the decoder loop\n        if self.pre_compute_enc_h is None:\n            self.enc_h = enc_hs_pad  # utt x frame x hdim\n            self.h_length = paddle.shape(self.enc_h)[1]\n            # utt x frame x att_dim\n            self.pre_compute_enc_h = self.mlp_enc(self.enc_h)\n\n        if dec_z is None:\n            dec_z = paddle.zeros([batch, self.dunits])\n        else:\n            dec_z = dec_z.reshape([batch, self.dunits])\n\n        if att_prev is None:\n            # initial attention will be [1, 0, 0, ...]\n            att_prev = paddle.zeros([*paddle.shape(enc_hs_pad)[:2]])\n            att_prev[:, 0] = 1.0\n\n        # att_prev: utt x frame -> utt x 1 x 1 x frame\n        # -> utt x att_conv_chans x 1 x frame\n        att_conv = self.loc_conv(att_prev.reshape([batch, 1, 1, self.h_length]))\n        # att_conv: utt x att_conv_chans x 1 x frame -> utt x frame x att_conv_chans\n        att_conv = att_conv.squeeze(2).transpose([0, 2, 1])\n        # att_conv: utt x frame x att_conv_chans -> utt x frame x att_dim\n        att_conv = self.mlp_att(att_conv)\n\n        # dec_z_tiled: utt x frame x att_dim\n        dec_z_tiled = self.mlp_dec(dec_z).reshape([batch, 1, self.att_dim])\n\n        # dot with gvec\n        # utt x frame x att_dim -> utt x frame\n        e = self.gvec(\n            paddle.tanh(att_conv + self.pre_compute_enc_h +\n                        dec_z_tiled)).squeeze(2)\n\n        # NOTE consider zero padding when compute w.\n        if self.mask is None:\n            self.mask = make_pad_mask(enc_hs_len)\n        e = masked_fill(e, self.mask, -float(\"inf\"))\n\n        # apply monotonic attention constraint (mainly for TTS)\n        if last_attended_idx is not None:\n            e = _apply_attention_constraint(e, last_attended_idx,\n                                            backward_window, forward_window)\n\n        w = F.softmax(scaling * e, axis=1)\n\n        # forward attention\n        # att_prev_shift = F.pad(att_prev.unsqueeze(0), (1, 0), data_format='NCL').squeeze(0)[:, :-1]\n        att_prev_shift = F.pad(att_prev, (0, 0, 1, 0))[:, :-1]\n        w = (self.trans_agent_prob * att_prev +\n             (1 - self.trans_agent_prob) * att_prev_shift) * w\n        # NOTE: clip is needed to avoid nan gradient\n        w = F.normalize(paddle.clip(w, 1e-6), p=1, axis=1)\n\n        # weighted sum over flames\n        # utt x hdim\n        # NOTE use bmm instead of sum(*)\n        c = paddle.sum(\n            self.enc_h * w.reshape([batch, self.h_length, 1]), axis=1)\n\n        # update transition agent prob\n        self.trans_agent_prob = F.sigmoid(\n            self.mlp_ta(paddle.concat([c, out_prev, dec_z], axis=1)))\n\n        return c, w\n"
  },
  {
    "path": "paddlespeech/t2s/modules/tacotron2/decoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Tacotron2 decoder related modules.\"\"\"\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.tacotron2.attentions import AttForwardTA\n\n\nclass Prenet(nn.Layer):\n    \"\"\"Prenet module for decoder of Spectrogram prediction network.\n\n    This is a module of Prenet in the decoder of Spectrogram prediction network,\n    which described in `Natural TTS\n    Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`_.\n    The Prenet preforms nonlinear conversion\n    of inputs before input to auto-regressive lstm,\n    which helps to learn diagonal attentions.\n\n    Notes\n    ----------\n    This module alway applies dropout even in evaluation.\n    See the detail in `Natural TTS Synthesis by\n    Conditioning WaveNet on Mel Spectrogram Predictions`_.\n\n    .. _`Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`:\n       https://arxiv.org/abs/1712.05884\n\n    \"\"\"\n\n    def __init__(self, idim, n_layers=2, n_units=256, dropout_rate=0.5):\n        \"\"\"Initialize prenet module.\n\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            odim (int): \n                Dimension of the outputs.\n            n_layers (int, optional): \n                The number of prenet layers.\n            n_units (int, optional): \n                The number of prenet units.\n        \"\"\"\n        super().__init__()\n        self.dropout_rate = dropout_rate\n        self.prenet = nn.LayerList()\n        for layer in range(n_layers):\n            n_inputs = idim if layer == 0 else n_units\n            self.prenet.append(\n                nn.Sequential(nn.Linear(n_inputs, n_units), nn.ReLU()))\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Batch of input tensors (B, ..., idim).\n\n        Returns: \n            Tensor: Batch of output tensors (B, ..., odim).\n\n        \"\"\"\n        for i in range(len(self.prenet)):\n            # F.dropout 引入了随机, tacotron2 的 dropout 是不能去掉的\n            x = F.dropout(self.prenet[i](x))\n        return x\n\n\nclass Postnet(nn.Layer):\n    \"\"\"Postnet module for Spectrogram prediction network.\n\n    This is a module of Postnet in Spectrogram prediction network,\n    which described in `Natural TTS Synthesis by\n    Conditioning WaveNet on Mel Spectrogram Predictions`_.\n    The Postnet predicts refines the predicted\n    Mel-filterbank of the decoder,\n    which helps to compensate the detail sturcture of spectrogram.\n\n    .. _`Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`:\n       https://arxiv.org/abs/1712.05884\n\n    \"\"\"\n\n    def __init__(\n            self,\n            idim,\n            odim,\n            n_layers=5,\n            n_chans=512,\n            n_filts=5,\n            dropout_rate=0.5,\n            use_batch_norm=True, ):\n        \"\"\"Initialize postnet module.\n\n        Args:\n            idim (int): Dimension of the inputs.\n            odim (int): Dimension of the outputs.\n            n_layers (int, optional): The number of layers.\n            n_filts (int, optional): The number of filter size.\n            n_units (int, optional): The number of filter channels.\n            use_batch_norm (bool, optional): Whether to use batch normalization..\n            dropout_rate (float, optional): Dropout rate..\n        \"\"\"\n        super().__init__()\n        self.postnet = nn.LayerList()\n        for layer in range(n_layers - 1):\n            ichans = odim if layer == 0 else n_chans\n            ochans = odim if layer == n_layers - 1 else n_chans\n            if use_batch_norm:\n                self.postnet.append(\n                    nn.Sequential(\n                        nn.Conv1D(\n                            ichans,\n                            ochans,\n                            n_filts,\n                            stride=1,\n                            padding=(n_filts - 1) // 2,\n                            bias_attr=False, ),\n                        nn.BatchNorm1D(ochans),\n                        nn.Tanh(),\n                        nn.Dropout(dropout_rate), ))\n            else:\n                self.postnet.append(\n                    nn.Sequential(\n                        nn.Conv1D(\n                            ichans,\n                            ochans,\n                            n_filts,\n                            stride=1,\n                            padding=(n_filts - 1) // 2,\n                            bias_attr=False, ),\n                        nn.Tanh(),\n                        nn.Dropout(dropout_rate), ))\n        ichans = n_chans if n_layers != 1 else odim\n        if use_batch_norm:\n            self.postnet.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        ichans,\n                        odim,\n                        n_filts,\n                        stride=1,\n                        padding=(n_filts - 1) // 2,\n                        bias_attr=False, ),\n                    nn.BatchNorm1D(odim),\n                    nn.Dropout(dropout_rate), ))\n        else:\n            self.postnet.append(\n                nn.Sequential(\n                    nn.Conv1D(\n                        ichans,\n                        odim,\n                        n_filts,\n                        stride=1,\n                        padding=(n_filts - 1) // 2,\n                        bias_attr=False, ),\n                    nn.Dropout(dropout_rate), ))\n\n    def forward(self, xs):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            xs (Tensor): Batch of the sequences of padded input tensors (B, idim, Tmax).\n        Returns:\n            Tensor: Batch of padded output tensor. (B, odim, Tmax).\n        \"\"\"\n        for i in range(len(self.postnet)):\n            xs = self.postnet[i](xs)\n        return xs\n\n\nclass ZoneOutCell(nn.Layer):\n    \"\"\"ZoneOut Cell module.\n    This is a module of zoneout described in\n    `Zoneout: Regularizing RNNs by Randomly Preserving Hidden Activations`_.\n    This code is modified from `eladhoffer/seq2seq.pytorch`_.\n    Examples\n    ----------\n        >>> lstm = paddle.nn.LSTMCell(16, 32)\n        >>> lstm = ZoneOutCell(lstm, 0.5)\n    .. _`Zoneout: Regularizing RNNs by Randomly Preserving Hidden Activations`:\n        https://arxiv.org/abs/1606.01305\n    .. _`eladhoffer/seq2seq.pytorch`:\n        https://github.com/eladhoffer/seq2seq.pytorch\n    \"\"\"\n\n    def __init__(self, cell, zoneout_rate=0.1):\n        \"\"\"Initialize zone out cell module.\n\n        Args:\n            cell (nn.Layer): Paddle recurrent cell module\n                e.g. `paddle.nn.LSTMCell`.\n            zoneout_rate (float, optional): Probability of zoneout from 0.0 to 1.0.\n        \"\"\"\n        super().__init__()\n        self.cell = cell\n        self.hidden_size = cell.hidden_size\n        self.zoneout_rate = zoneout_rate\n        if zoneout_rate > 1.0 or zoneout_rate < 0.0:\n            raise ValueError(\n                \"zoneout probability must be in the range from 0.0 to 1.0.\")\n\n    def forward(self, inputs, hidden):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            inputs (Tensor): \n                Batch of input tensor (B, input_size).\n            hidden (tuple):\n                - Tensor: Batch of initial hidden states (B, hidden_size).\n                - Tensor: Batch of initial cell states (B, hidden_size).\n        Returns:\n            Tensor:\n                Batch of next hidden states (B, hidden_size).\n            tuple:\n                - Tensor: Batch of next hidden states (B, hidden_size).\n                - Tensor: Batch of next cell states (B, hidden_size).\n        \"\"\"\n        # we only use the second output of LSTMCell in paddle\n        _, next_hidden = self.cell(inputs, hidden)\n        next_hidden = self._zoneout(hidden, next_hidden, self.zoneout_rate)\n        # to have the same output format with LSTMCell in paddle\n        return next_hidden[0], next_hidden\n\n    def _zoneout(self, h, next_h, prob):\n        # apply recursively\n        if isinstance(h, tuple):\n            num_h = len(h)\n            if not isinstance(prob, tuple):\n                prob = tuple([prob] * num_h)\n            return tuple(\n                [self._zoneout(h[i], next_h[i], prob[i]) for i in range(num_h)])\n        if self.training:\n            mask = paddle.bernoulli(paddle.ones([*paddle.shape(h)]) * prob)\n            return mask * h + (1 - mask) * next_h\n        else:\n            return prob * h + (1 - prob) * next_h\n\n\nclass Decoder(nn.Layer):\n    \"\"\"Decoder module of Spectrogram prediction network.\n    This is a module of decoder of Spectrogram prediction network in Tacotron2,\n    which described in `Natural TTS\n    Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`_.\n    The decoder generates the sequence of\n    features from the sequence of the hidden states.\n    .. _`Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`:\n       https://arxiv.org/abs/1712.05884\n    \"\"\"\n\n    def __init__(\n            self,\n            idim,\n            odim,\n            att,\n            dlayers=2,\n            dunits=1024,\n            prenet_layers=2,\n            prenet_units=256,\n            postnet_layers=5,\n            postnet_chans=512,\n            postnet_filts=5,\n            output_activation_fn=None,\n            cumulate_att_w=True,\n            use_batch_norm=True,\n            use_concate=True,\n            dropout_rate=0.5,\n            zoneout_rate=0.1,\n            reduction_factor=1, ):\n        \"\"\"Initialize Tacotron2 decoder module.\n\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            odim (int): \n                Dimension of the outputs.\n            att (nn.Layer): \n                Instance of attention class.\n            dlayers (int, optional): \n                The number of decoder lstm layers.\n            dunits (int, optional): \n                The number of decoder lstm units.\n            prenet_layers (int, optional): \n                The number of prenet layers.\n            prenet_units (int, optional): \n                The number of prenet units.\n            postnet_layers (int, optional): \n                The number of postnet layers.\n            postnet_filts (int, optional): \n                The number of postnet filter size.\n            postnet_chans (int, optional): \n                The number of postnet filter channels.\n            output_activation_fn (nn.Layer, optional): \n                Activation function for outputs.\n            cumulate_att_w (bool, optional): \n                Whether to cumulate previous attention weight.\n            use_batch_norm (bool, optional): \n                Whether to use batch normalization.\n            use_concate (bool, optional):\n                Whether to concatenate encoder embedding with decoder lstm outputs.\n            dropout_rate (float, optional):\n                Dropout rate.\n            zoneout_rate (float, optional):\n                Zoneout rate.\n            reduction_factor (int, optional):\n                Reduction factor.\n        \"\"\"\n        super().__init__()\n\n        # store the hyperparameters\n        self.idim = idim\n        self.odim = odim\n        self.att = att\n        self.output_activation_fn = output_activation_fn\n        self.cumulate_att_w = cumulate_att_w\n        self.use_concate = use_concate\n        self.reduction_factor = reduction_factor\n\n        # check attention type\n        if isinstance(self.att, AttForwardTA):\n            self.use_att_extra_inputs = True\n        else:\n            self.use_att_extra_inputs = False\n\n        # define lstm network\n        prenet_units = prenet_units if prenet_layers != 0 else odim\n        self.lstm = nn.LayerList()\n        for layer in range(dlayers):\n            iunits = idim + prenet_units if layer == 0 else dunits\n            lstm = nn.LSTMCell(iunits, dunits)\n            if zoneout_rate > 0.0:\n                lstm = ZoneOutCell(lstm, zoneout_rate)\n            self.lstm.append(lstm)\n\n        # define prenet\n        if prenet_layers > 0:\n            self.prenet = Prenet(\n                idim=odim,\n                n_layers=prenet_layers,\n                n_units=prenet_units,\n                dropout_rate=dropout_rate, )\n        else:\n            self.prenet = None\n\n        # define postnet\n        if postnet_layers > 0:\n            self.postnet = Postnet(\n                idim=idim,\n                odim=odim,\n                n_layers=postnet_layers,\n                n_chans=postnet_chans,\n                n_filts=postnet_filts,\n                use_batch_norm=use_batch_norm,\n                dropout_rate=dropout_rate, )\n        else:\n            self.postnet = None\n\n        # define projection layers\n        iunits = idim + dunits if use_concate else dunits\n        self.feat_out = nn.Linear(\n            iunits, odim * reduction_factor, bias_attr=False)\n        self.prob_out = nn.Linear(iunits, reduction_factor)\n\n    def _zero_state(self, hs):\n        init_hs = paddle.zeros([paddle.shape(hs)[0], self.lstm[0].hidden_size])\n        return init_hs\n\n    def forward(self, hs, hlens, ys):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            hs (Tensor): \n                Batch of the sequences of padded hidden states (B, Tmax, idim).\n            hlens (Tensor(int64) padded): \n                Batch of lengths of each input batch (B,).\n            ys (Tensor): \n                Batch of the sequences of padded target features (B, Lmax, odim).\n\n        Returns:\n            Tensor: \n                Batch of output tensors after postnet (B, Lmax, odim).\n            Tensor: \n                Batch of output tensors before postnet (B, Lmax, odim).\n            Tensor: \n                Batch of logits of stop prediction (B, Lmax).\n            Tensor: \n                Batch of attention weights (B, Lmax, Tmax).\n            \n        Note: \n            This computation is performed in teacher-forcing manner.\n        \"\"\"\n        # thin out frames (B, Lmax, odim) ->  (B, Lmax/r, odim)\n        if self.reduction_factor > 1:\n            ys = ys[:, self.reduction_factor - 1::self.reduction_factor]\n\n        # length list should be list of int\n        # hlens = list(map(int, hlens))\n\n        # initialize hidden states of decoder\n        c_list = [self._zero_state(hs)]\n        z_list = [self._zero_state(hs)]\n        for _ in range(1, len(self.lstm)):\n            c_list.append(self._zero_state(hs))\n            z_list.append(self._zero_state(hs))\n        prev_out = paddle.zeros([paddle.shape(hs)[0], self.odim])\n\n        # initialize attention\n        prev_att_ws = []\n        prev_att_w = paddle.zeros(paddle.shape(hlens))\n        prev_att_ws.append(prev_att_w)\n        self.att.reset()\n\n        # loop for an output sequence\n        outs, logits, att_ws = [], [], []\n        for y in ys.transpose([1, 0, 2]):\n            if self.use_att_extra_inputs:\n                att_c, att_w = self.att(hs, hlens, z_list[0], prev_att_ws[-1],\n                                        prev_out)\n            else:\n                att_c, att_w = self.att(hs, hlens, z_list[0], prev_att_ws[-1])\n            prenet_out = self.prenet(\n                prev_out) if self.prenet is not None else prev_out\n            xs = paddle.concat([att_c, prenet_out], axis=1)\n            # we only use the second output of LSTMCell in paddle\n            _, next_hidden = self.lstm[0](xs, (z_list[0], c_list[0]))\n            z_list[0], c_list[0] = next_hidden\n            for i in range(1, len(self.lstm)):\n                # we only use the second output of LSTMCell in paddle\n                _, next_hidden = self.lstm[i](z_list[i - 1],\n                                              (z_list[i], c_list[i]))\n                z_list[i], c_list[i] = next_hidden\n            zcs = (paddle.concat([z_list[-1], att_c], axis=1)\n                   if self.use_concate else z_list[-1])\n            outs.append(\n                self.feat_out(zcs).reshape([paddle.shape(hs)[0], self.odim, -1\n                                            ]))\n            logits.append(self.prob_out(zcs))\n            att_ws.append(att_w)\n            # teacher forcing\n            prev_out = y\n            if self.cumulate_att_w and paddle.sum(prev_att_w) != 0:\n                prev_att_w = prev_att_w + att_w  # Note: error when use +=\n            else:\n                prev_att_w = att_w\n            prev_att_ws.append(prev_att_w)\n        # (B, Lmax)\n        logits = paddle.concat(logits, axis=1)\n        # (B, odim, Lmax) \n        before_outs = paddle.concat(outs, axis=2)\n        # (B, Lmax, Tmax)\n        att_ws = paddle.stack(att_ws, axis=1)\n\n        if self.reduction_factor > 1:\n            # (B, odim, Lmax)\n            before_outs = before_outs.reshape(\n                [paddle.shape(before_outs)[0], self.odim, -1])\n\n        if self.postnet is not None:\n            # (B, odim, Lmax)\n            after_outs = before_outs + self.postnet(before_outs)\n        else:\n            after_outs = before_outs\n        # (B, Lmax, odim)\n        before_outs = before_outs.transpose([0, 2, 1])\n        # (B, Lmax, odim)\n        after_outs = after_outs.transpose([0, 2, 1])\n        logits = logits\n\n        # apply activation function for scaling\n        if self.output_activation_fn is not None:\n            before_outs = self.output_activation_fn(before_outs)\n            after_outs = self.output_activation_fn(after_outs)\n\n        return after_outs, before_outs, logits, att_ws\n\n    def inference(\n            self,\n            h,\n            threshold=0.5,\n            minlenratio=0.0,\n            maxlenratio=10.0,\n            use_att_constraint=False,\n            backward_window=None,\n            forward_window=None, ):\n        \"\"\"Generate the sequence of features given the sequences of characters.\n        Args:\n            h(Tensor): \n                Input sequence of encoder hidden states (T, C).\n            threshold(float, optional, optional): \n                Threshold to stop generation. (Default value = 0.5)\n            minlenratio(float, optional, optional): \n                Minimum length ratio. If set to 1.0 and the length of input is 10,\n                the minimum length of outputs will be 10 * 1 = 10. (Default value = 0.0)\n            maxlenratio(float, optional, optional):\n                 Minimum length ratio. If set to 10 and the length of input is 10,\n                the maximum length of outputs will be 10 * 10 = 100. (Default value = 0.0)\n            use_att_constraint(bool, optional): \n                Whether to apply attention constraint introduced in `Deep Voice 3`_. (Default value = False)\n            backward_window(int, optional): \n                Backward window size in attention constraint. (Default value = None)\n            forward_window(int, optional):  \n                    (Default value = None)\n\n        Returns:\n            Tensor: \n                Output sequence of features (L, odim).\n            Tensor: \n                Output sequence of stop probabilities (L,).\n            Tensor: \n                Attention weights (L, T).\n\n        Note: \n            This computation is performed in auto-regressive manner.\n    .. _`Deep Voice 3`: https://arxiv.org/abs/1710.07654\n        \"\"\"\n        # setup\n\n        assert len(paddle.shape(h)) == 2\n        hs = h.unsqueeze(0)\n        ilens = paddle.shape(h)[0]\n        # 本来 maxlen 和 minlen 外面有 int()，防止动转静的问题此处删除\n        maxlen = paddle.shape(h)[0] * maxlenratio\n        minlen = paddle.shape(h)[0] * minlenratio\n        # 本来是直接使用 threshold 的，此处为了防止动转静的问题把 threshold 转成 tensor\n        threshold = paddle.ones([1]) * threshold\n\n        # initialize hidden states of decoder\n        c_list = [self._zero_state(hs)]\n        z_list = [self._zero_state(hs)]\n        for _ in range(1, len(self.lstm)):\n            c_list.append(self._zero_state(hs))\n            z_list.append(self._zero_state(hs))\n        prev_out = paddle.zeros([1, self.odim])\n\n        # initialize attention\n        prev_att_ws = []\n        prev_att_w = paddle.zeros([ilens])\n        prev_att_ws.append(prev_att_w)\n\n        self.att.reset()\n\n        # setup for attention constraint\n        if use_att_constraint:\n            last_attended_idx = 0\n        else:\n            last_attended_idx = -1\n\n        # loop for an output sequence\n        idx = 0\n        outs, att_ws, probs = [], [], []\n        prob = paddle.zeros([1])\n        while paddle.to_tensor(True):\n            z_list = z_list\n            c_list = c_list\n            # updated index\n            idx += self.reduction_factor\n\n            # decoder calculation\n            if self.use_att_extra_inputs:\n                att_c, att_w = self.att(\n                    hs,\n                    ilens,\n                    z_list[0],\n                    prev_att_ws[-1],\n                    prev_out,\n                    last_attended_idx=last_attended_idx,\n                    backward_window=backward_window,\n                    forward_window=forward_window, )\n            else:\n                att_c, att_w = self.att(\n                    hs,\n                    ilens,\n                    z_list[0],\n                    prev_att_ws[-1],\n                    last_attended_idx=last_attended_idx,\n                    backward_window=backward_window,\n                    forward_window=forward_window, )\n\n            att_ws.append(att_w)\n            prenet_out = self.prenet(\n                prev_out) if self.prenet is not None else prev_out\n            xs = paddle.concat([att_c, prenet_out], axis=1)\n            # we only use the second output of LSTMCell in paddle\n            _, next_hidden = self.lstm[0](xs, (z_list[0], c_list[0]))\n\n            z_list[0], c_list[0] = next_hidden\n            for i in range(1, len(self.lstm)):\n                # we only use the second output of LSTMCell in paddle\n                _, next_hidden = self.lstm[i](z_list[i - 1],\n                                              (z_list[i], c_list[i]))\n                z_list[i], c_list[i] = next_hidden\n            zcs = (paddle.concat([z_list[-1], att_c], axis=1)\n                   if self.use_concate else z_list[-1])\n            # [(1, odim, r), ...]\n            outs.append(self.feat_out(zcs).reshape([1, self.odim, -1]))\n\n            prob = F.sigmoid(self.prob_out(zcs))[0]\n            probs.append(prob)\n\n            if self.output_activation_fn is not None:\n                prev_out = self.output_activation_fn(\n                    outs[-1][:, :, -1])  # (1, odim)\n            else:\n                prev_out = outs[-1][:, :, -1]  # (1, odim)\n            if self.cumulate_att_w and paddle.sum(prev_att_w) != 0:\n                prev_att_w = prev_att_w + att_w  # Note: error when use +=\n            else:\n                prev_att_w = att_w\n            prev_att_ws.append(prev_att_w)\n            if use_att_constraint:\n                last_attended_idx = int(att_w.argmax())\n\n            # tacotron2 ljspeech 动转静的问题应该是这里没有正确判断 prob >= threshold 导致的\n            if prob >= threshold or idx >= maxlen:\n                # check mininum length\n                if idx < minlen:\n                    continue\n                break\n            \"\"\"\n            仅解开 665~667 行的代码块，动转静时会卡死，但是动态图时可以正确生成音频，证明模型没问题\n            同时解开 665~667 行 和 668 ~ 670 行的代码块，动转静时不会卡死，但是生成的音频末尾有多余的噪声\n            证明动转静没有进入 prob >= threshold 的判断，但是静态图可以进入 prob >= threshold 并退出循环\n            动转静时是通过 idx >= maxlen 退出循环（所以没有这个逻辑的时候会一直循环，也就是卡死），\n            没有在模型判断该结束的时候结束，而是在超出最大长度时结束，所以合成的音频末尾有很长的额外预测的噪声\n            动转静用 prob <= threshold 的条件可以退出循环（虽然结果不正确），证明条件参数的类型本身没问题，可能是 prob 有问题\n            \"\"\"\n            # if prob >= threshold:\n            #     print(\"prob >= threshold\")\n            #     break\n            # elif idx >= maxlen:\n            #     print(\"idx >= maxlen\")\n            #     break\n\n        # (1, odim, L)\n        outs = paddle.concat(outs, axis=2)\n        if self.postnet is not None:\n            # (1, odim, L)\n            outs = outs + self.postnet(outs)\n        # (L, odim)\n        outs = outs.transpose([0, 2, 1]).squeeze(0)\n        probs = paddle.concat(probs, axis=0)\n        att_ws = paddle.concat(att_ws, axis=0)\n\n        if self.output_activation_fn is not None:\n            outs = self.output_activation_fn(outs)\n\n        return outs, probs, att_ws\n\n    def calculate_all_attentions(self, hs, hlens, ys):\n        \"\"\"Calculate all of the attention weights.\n\n        Args:\n            hs (Tensor): \n                Batch of the sequences of padded hidden states (B, Tmax, idim).\n            hlens (Tensor(int64)): \n                Batch of lengths of each input batch (B,).\n            ys (Tensor): \n                Batch of the sequences of padded target features (B, Lmax, odim).\n\n        Returns:\n            numpy.ndarray:\n                Batch of attention weights (B, Lmax, Tmax).\n    \n        Note:\n            This computation is performed in teacher-forcing manner.\n        \"\"\"\n        # thin out frames (B, Lmax, odim) ->  (B, Lmax/r, odim)\n        if self.reduction_factor > 1:\n            ys = ys[:, self.reduction_factor - 1::self.reduction_factor]\n\n        # length list should be list of int\n        hlens = list(map(int, hlens))\n\n        # initialize hidden states of decoder\n        c_list = [self._zero_state(hs)]\n        z_list = [self._zero_state(hs)]\n        for _ in range(1, len(self.lstm)):\n            c_list.append(self._zero_state(hs))\n            z_list.append(self._zero_state(hs))\n        prev_out = paddle.zeros([paddle.shape(hs)[0], self.odim])\n\n        # initialize attention\n        prev_att_w = None\n        self.att.reset()\n\n        # loop for an output sequence\n        att_ws = []\n        for y in ys.transpose([1, 0, 2]):\n            if self.use_att_extra_inputs:\n                att_c, att_w = self.att(hs, hlens, z_list[0], prev_att_w,\n                                        prev_out)\n            else:\n                att_c, att_w = self.att(hs, hlens, z_list[0], prev_att_w)\n            att_ws.append(att_w)\n            prenet_out = self.prenet(\n                prev_out) if self.prenet is not None else prev_out\n            xs = paddle.concat([att_c, prenet_out], axis=1)\n            # we only use the second output of LSTMCell in paddle\n            _, next_hidden = self.lstm[0](xs, (z_list[0], c_list[0]))\n            z_list[0], c_list[0] = next_hidden\n            for i in range(1, len(self.lstm)):\n                z_list[i], c_list[i] = self.lstm[i](z_list[i - 1],\n                                                    (z_list[i], c_list[i]))\n            # teacher forcing\n            prev_out = y\n            if self.cumulate_att_w and prev_att_w is not None:\n                # Note: error when use +=\n                prev_att_w = prev_att_w + att_w\n            else:\n                prev_att_w = att_w\n        # (B, Lmax, Tmax)\n        att_ws = paddle.stack(att_ws, axis=1)\n\n        return att_ws\n"
  },
  {
    "path": "paddlespeech/t2s/modules/tacotron2/encoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Tacotron2 encoder related modules.\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass Encoder(nn.Layer):\n    \"\"\"Encoder module of Spectrogram prediction network.\n\n    This is a module of encoder of Spectrogram prediction network in Tacotron2,\n    which described in `Natural TTS Synthesis by Conditioning WaveNet on Mel\n    Spectrogram Predictions`_. This is the encoder which converts either a sequence\n    of characters or acoustic features into the sequence of hidden states.\n\n    .. _`Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions`:\n       https://arxiv.org/abs/1712.05884\n\n    \"\"\"\n\n    def __init__(\n            self,\n            idim,\n            input_layer=\"embed\",\n            embed_dim=512,\n            elayers=1,\n            eunits=512,\n            econv_layers=3,\n            econv_chans=512,\n            econv_filts=5,\n            use_batch_norm=True,\n            use_residual=False,\n            dropout_rate=0.5,\n            padding_idx=0, ):\n        \"\"\"Initialize Tacotron2 encoder module.\n        Args:\n            idim (int): \n                Dimension of the inputs.\n            input_layer (str): \n                Input layer type.\n            embed_dim (int, optional): \n                Dimension of character embedding.\n            elayers (int, optional): \n                The number of encoder blstm layers.\n            eunits (int, optional): \n                The number of encoder blstm units.\n            econv_layers (int, optional): \n                The number of encoder conv layers.\n            econv_filts (int, optional): \n                The number of encoder conv filter size.\n            econv_chans (int, optional): \n                The number of encoder conv filter channels.\n            use_batch_norm (bool, optional): \n                Whether to use batch normalization.\n            use_residual (bool, optional): \n                Whether to use residual connection.\n            dropout_rate (float, optional): \n                Dropout rate.\n\n        \"\"\"\n        super().__init__()\n        # store the hyperparameters\n        self.idim = idim\n        self.use_residual = use_residual\n\n        # define network layer modules\n        if input_layer == \"linear\":\n            self.embed = nn.Linear(idim, econv_chans)\n        elif input_layer == \"embed\":\n            self.embed = nn.Embedding(idim, embed_dim, padding_idx=padding_idx)\n        else:\n            raise ValueError(\"unknown input_layer: \" + input_layer)\n\n        if econv_layers > 0:\n            self.convs = nn.LayerList()\n            for layer in range(econv_layers):\n                ichans = (embed_dim if layer == 0 and input_layer == \"embed\"\n                          else econv_chans)\n                if use_batch_norm:\n                    self.convs.append(\n                        nn.Sequential(\n                            nn.Conv1D(\n                                ichans,\n                                econv_chans,\n                                econv_filts,\n                                stride=1,\n                                padding=(econv_filts - 1) // 2,\n                                bias_attr=False, ),\n                            nn.BatchNorm1D(econv_chans),\n                            nn.ReLU(),\n                            nn.Dropout(dropout_rate), ))\n                else:\n                    self.convs += [\n                        nn.Sequential(\n                            nn.Conv1D(\n                                ichans,\n                                econv_chans,\n                                econv_filts,\n                                stride=1,\n                                padding=(econv_filts - 1) // 2,\n                                bias_attr=False, ),\n                            nn.ReLU(),\n                            nn.Dropout(dropout_rate), )\n                    ]\n        else:\n            self.convs = None\n        if elayers > 0:\n            iunits = econv_chans if econv_layers != 0 else embed_dim\n            # batch_first=True, bidirectional=True\n            self.blstm = nn.LSTM(\n                iunits,\n                eunits // 2,\n                elayers,\n                time_major=False,\n                direction='bidirectional',\n                bias_ih_attr=True,\n                bias_hh_attr=True)\n            self.blstm.flatten_parameters()\n        else:\n            self.blstm = None\n\n        # # initialize\n        # self.apply(encoder_init)\n\n    def forward(self, xs, ilens=None):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            xs (Tensor): \n                Batch of the padded sequence. Either character ids (B, Tmax)\n                or acoustic feature (B, Tmax, idim * encoder_reduction_factor). \n                Padded value should be 0.\n            ilens (Tensor(int64)): \n                Batch of lengths of each input batch (B,).\n\n        Returns:\n            Tensor: \n                Batch of the sequences of encoder states(B, Tmax, eunits).\n            Tensor(int64): \n                Batch of lengths of each sequence (B,)\n        \"\"\"\n        xs = self.embed(xs).transpose([0, 2, 1])\n        if self.convs is not None:\n            for i in range(len(self.convs)):\n                if self.use_residual:\n                    xs += self.convs[i](xs)\n                else:\n                    xs = self.convs[i](xs)\n        if self.blstm is None:\n            return xs.transpose([0, 2, 1])\n        if not isinstance(ilens, paddle.Tensor):\n            ilens = paddle.to_tensor(ilens)\n        if ilens.ndim == 0:\n            ilens = ilens.unsqueeze(0)\n        xs = xs.transpose([0, 2, 1])\n        # for dygraph to static graph\n        # self.blstm.flatten_parameters()\n        # (B, Tmax, C)\n        # see https://www.paddlepaddle.org.cn/documentation/docs/zh/faq/train_cn.html#paddletorch-nn-utils-rnn-pack-padded-sequencetorch-nn-utils-rnn-pad-packed-sequenceapi\n        xs, _ = self.blstm(xs, sequence_length=ilens)\n        hlens = ilens\n\n        return xs, hlens\n\n    def inference(self, x):\n        \"\"\"Inference.\n\n        Args:\n            x (Tensor): \n                The sequeunce of character ids (T,) or acoustic feature (T, idim * encoder_reduction_factor).\n\n        Returns:\n            Tensor: The sequences of encoder states(T, eunits).\n\n        \"\"\"\n        xs = x.unsqueeze(0)\n        ilens = paddle.shape(x)[0]\n\n        return self.forward(xs, ilens)[0][0]\n"
  },
  {
    "path": "paddlespeech/t2s/modules/tade_res_block.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"StyleMelGAN's TADEResBlock Modules.\"\"\"\nfrom functools import partial\n\nimport paddle.nn.functional as F\nfrom paddle import nn\n\n\nclass TADELayer(nn.Layer):\n    \"\"\"TADE Layer module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=64,\n            aux_channels: int=80,\n            kernel_size: int=9,\n            bias: bool=True,\n            upsample_factor: int=2,\n            upsample_mode: str=\"nearest\", ):\n        \"\"\"Initilize TADE layer.\"\"\"\n        super().__init__()\n        self.norm = nn.InstanceNorm1D(\n            in_channels,\n            momentum=0.1,\n            data_format=\"NCL\",\n            weight_attr=False,\n            bias_attr=False)\n        self.aux_conv = nn.Sequential(\n            nn.Conv1D(\n                aux_channels,\n                in_channels,\n                kernel_size,\n                1,\n                bias_attr=bias,\n                padding=(kernel_size - 1) // 2, ), )\n        self.gated_conv = nn.Sequential(\n            nn.Conv1D(\n                in_channels,\n                in_channels * 2,\n                kernel_size,\n                1,\n                bias_attr=bias,\n                padding=(kernel_size - 1) // 2, ), )\n        self.upsample = nn.Upsample(\n            scale_factor=upsample_factor, mode=upsample_mode)\n\n    def forward(self, x, c):\n        \"\"\"Calculate forward propagation.\n        Args:\n            x (Tensor): \n                Input tensor (B, in_channels, T).\n            c (Tensor): \n                Auxiliary input tensor (B, aux_channels, T).\n        Returns:\n            Tensor: \n                Output tensor (B, in_channels, T * upsample_factor).\n            Tensor:\n                Upsampled aux tensor (B, in_channels, T * upsample_factor).\n        \"\"\"\n\n        x = self.norm(x)\n        # 'bilinear', 'bicubic' and 'nearest' only support 4-D tensor.\n        c = self.upsample(c.unsqueeze(-1))\n        c = c[:, :, :, 0]\n\n        c = self.aux_conv(c)\n        cg = self.gated_conv(c)\n        cg1, cg2 = cg.split(2, axis=1)\n        # 'bilinear', 'bicubic' and 'nearest' only support 4-D tensor.\n        y = cg1 * self.upsample(x.unsqueeze(-1))[:, :, :, 0] + cg2\n        return y, c\n\n\nclass TADEResBlock(nn.Layer):\n    \"\"\"TADEResBlock module.\"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=64,\n            aux_channels: int=80,\n            kernel_size: int=9,\n            dilation: int=2,\n            bias: bool=True,\n            upsample_factor: int=2,\n            # this is a diff in paddle, the mode only can be \"linear\" when input is 3D\n            upsample_mode: str=\"nearest\",\n            gated_function: str=\"softmax\", ):\n        \"\"\"Initialize TADEResBlock module.\"\"\"\n        super().__init__()\n        self.tade1 = TADELayer(\n            in_channels=in_channels,\n            aux_channels=aux_channels,\n            kernel_size=kernel_size,\n            bias=bias,\n            upsample_factor=1,\n            upsample_mode=upsample_mode, )\n        self.gated_conv1 = nn.Conv1D(\n            in_channels,\n            in_channels * 2,\n            kernel_size,\n            1,\n            bias_attr=bias,\n            padding=(kernel_size - 1) // 2, )\n        self.tade2 = TADELayer(\n            in_channels=in_channels,\n            aux_channels=in_channels,\n            kernel_size=kernel_size,\n            bias=bias,\n            upsample_factor=upsample_factor,\n            upsample_mode=upsample_mode, )\n        self.gated_conv2 = nn.Conv1D(\n            in_channels,\n            in_channels * 2,\n            kernel_size,\n            1,\n            bias_attr=bias,\n            dilation=dilation,\n            padding=(kernel_size - 1) // 2 * dilation, )\n        self.upsample = nn.Upsample(\n            scale_factor=upsample_factor, mode=upsample_mode)\n        if gated_function == \"softmax\":\n            self.gated_function = partial(F.softmax, axis=1)\n        elif gated_function == \"sigmoid\":\n            self.gated_function = F.sigmoid\n        else:\n            raise ValueError(f\"{gated_function} is not supported.\")\n\n    def forward(self, x, c):\n        \"\"\"Calculate forward propagation.\n        Args:\n\n            x (Tensor): \n                Input tensor (B, in_channels, T).\n            c (Tensor): \n                Auxiliary input tensor (B, aux_channels, T).\n        Returns:\n            Tensor: \n                Output tensor (B, in_channels, T * upsample_factor).\n            Tensor: \n                Upsampled auxirialy tensor (B, in_channels, T * upsample_factor).\n        \"\"\"\n        residual = x\n        x, c = self.tade1(x, c)\n        x = self.gated_conv1(x)\n        xa, xb = x.split(2, axis=1)\n        x = self.gated_function(xa) * F.tanh(xb)\n        x, c = self.tade2(x, c)\n        x = self.gated_conv2(x)\n        xa, xb = x.split(2, axis=1)\n        x = self.gated_function(xa) * F.tanh(xb)\n        # 'bilinear', 'bicubic' and 'nearest' only support 4-D tensor.\n        return self.upsample(residual.unsqueeze(-1))[:, :, :, 0] + x, c\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/attention.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Multi-Head Attention layer definition.\"\"\"\nimport math\n\nimport numpy\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\n\nclass MultiHeadedAttention(nn.Layer):\n    \"\"\"Multi-Head Attention layer.\n    Args:\n        n_head (int): \n            The number of heads.\n        n_feat (int): \n            The number of features.\n        dropout_rate (float): \n            Dropout rate.\n    \"\"\"\n\n    def __init__(self, n_head, n_feat, dropout_rate):\n        \"\"\"Construct an MultiHeadedAttention object.\"\"\"\n        super().__init__()\n        assert n_feat % n_head == 0\n        # We assume d_v always equals d_k\n        self.d_k = n_feat // n_head\n        self.h = n_head\n        self.linear_q = nn.Linear(n_feat, n_feat, bias_attr=True)\n        self.linear_k = nn.Linear(n_feat, n_feat, bias_attr=True)\n        self.linear_v = nn.Linear(n_feat, n_feat, bias_attr=True)\n        self.linear_out = nn.Linear(n_feat, n_feat, bias_attr=True)\n        self.attn = None\n        self.dropout = nn.Dropout(p=dropout_rate)\n\n    def forward_qkv(self, query, key, value):\n        \"\"\"Transform query, key and value.\n\n        Args:\n            query(Tensor): \n                query tensor (#batch, time1, size).\n            key(Tensor): \n                Key tensor (#batch, time2, size).\n            value(Tensor): \n                Value tensor (#batch, time2, size).\n\n        Returns:\n            Tensor: \n                Transformed query tensor (#batch, n_head, time1, d_k).\n            Tensor: \n                Transformed key tensor (#batch, n_head, time2, d_k).\n            Tensor: \n                Transformed value tensor (#batch, n_head, time2, d_k).\n        \"\"\"\n        n_batch = paddle.shape(query)[0]\n\n        q = paddle.reshape(\n            self.linear_q(query), [n_batch, -1, self.h, self.d_k])\n        k = paddle.reshape(self.linear_k(key), [n_batch, -1, self.h, self.d_k])\n        v = paddle.reshape(\n            self.linear_v(value), [n_batch, -1, self.h, self.d_k])\n\n        # (batch, head, time1, d_k)\n        q = q.transpose((0, 2, 1, 3))\n        # (batch, head, time2, d_k)\n        k = k.transpose((0, 2, 1, 3))\n        # (batch, head, time2, d_k)\n        v = v.transpose((0, 2, 1, 3))\n        return q, k, v\n\n    def forward_attention(self, value, scores, mask=None):\n        \"\"\"Compute attention context vector.\n\n        Args:\n            value(Tensor): \n                Transformed value (#batch, n_head, time2, d_k).\n            scores(Tensor): \n                Attention score (#batch, n_head, time1, time2).\n            mask(Tensor, optional): \n                Mask (#batch, 1, time2) or (#batch, time1, time2). (Default value = None)\n\n        Returns:\n            Tensor: Transformed value (#batch, time1, d_model) weighted by the attention score (#batch, time1, time2).\n        \"\"\"\n        n_batch = paddle.shape(value)[0]\n        softmax = paddle.nn.Softmax(axis=-1)\n        if mask is not None:\n            mask = mask.unsqueeze(1)\n            mask = paddle.logical_not(mask)\n            # assume scores.dtype==paddle.float32, we only use \"float32\" here\n            dtype = str(scores.dtype).split(\".\")[-1]\n            min_value = float(numpy.finfo(dtype).min)\n            scores = masked_fill(scores, mask, min_value)\n            # (batch, head, time1, time2)\n            self.attn = softmax(scores)\n            self.attn = masked_fill(self.attn, mask, 0.0)\n        else:\n            # (batch, head, time1, time2)\n            self.attn = softmax(scores)\n            # (batch, head, time1, time2)\n        p_attn = self.dropout(self.attn)\n        # (batch, head, time1, time2) * (batch, head, time2, d_k) -> # (batch, head, time1, d_k)\n        x = paddle.matmul(p_attn, value)\n        # (batch, time1, d_model)\n        x = (paddle.reshape(\n            x.transpose((0, 2, 1, 3)), (n_batch, -1, self.h * self.d_k)))\n        # (batch, time1, d_model)\n        return self.linear_out(x)\n\n    def forward(self, query, key, value, mask=None):\n        \"\"\"Compute scaled dot product attention.\n\n        Args:\n            query(Tensor): \n                Query tensor (#batch, time1, size).\n            key(Tensor): \n                Key tensor (#batch, time2, size).\n            value(Tensor): \n                Value tensor (#batch, time2, size).\n            mask(Tensor, optional): \n                Mask tensor (#batch, 1, time2) or (#batch, time1, time2). (Default value = None)\n\n        Returns:\n            Tensor: Output tensor (#batch, time1, d_model).\n        \"\"\"\n        q, k, v = self.forward_qkv(query, key, value)\n        scores = paddle.matmul(q, k.transpose(\n            (0, 1, 3, 2))) / math.sqrt(self.d_k)\n\n        return self.forward_attention(v, scores, mask)\n\n\nclass RelPositionMultiHeadedAttention(MultiHeadedAttention):\n    \"\"\"Multi-Head Attention layer with relative position encoding (new implementation).\n    Details can be found in https://github.com/espnet/espnet/pull/2816.\n    Paper: https://arxiv.org/abs/1901.02860\n\n    Args:\n        n_head (int): \n            The number of heads.\n        n_feat (int): \n            The number of features.\n        dropout_rate (float): \n            Dropout rate.\n        zero_triu (bool): \n            Whether to zero the upper triangular part of attention matrix.\n    \"\"\"\n\n    def __init__(self, n_head, n_feat, dropout_rate, zero_triu=False):\n        \"\"\"Construct an RelPositionMultiHeadedAttention object.\"\"\"\n        super().__init__(n_head, n_feat, dropout_rate)\n        self.zero_triu = zero_triu\n        # linear transformation for positional encoding\n        self.linear_pos = nn.Linear(n_feat, n_feat, bias_attr=False)\n        # these two learnable bias are used in matrix c and matrix d\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n\n        self.pos_bias_u = paddle.create_parameter(\n            shape=(self.h, self.d_k),\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.XavierUniform())\n        self.pos_bias_v = paddle.create_parameter(\n            shape=(self.h, self.d_k),\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.XavierUniform())\n\n    def rel_shift(self, x):\n        \"\"\"Compute relative positional encoding.\n        Args:\n            x(Tensor): \n                Input tensor (batch, head, time1, 2*time1-1).\n\n        Returns:\n            Tensor: Output tensor.\n        \"\"\"\n        b, h, t1, t2 = paddle.shape(x)\n        zero_pad = paddle.zeros((b, h, t1, 1))\n        x_padded = paddle.concat([zero_pad, x], axis=-1)\n        x_padded = x_padded.reshape([b, h, t2 + 1, t1])\n        # only keep the positions from 0 to time2\n        new_t = paddle.cast(paddle.floor(t2 / 2) + 1, dtype='int32')\n        x = x_padded[:, :, 1:].reshape([b, h, t1, t2])[:, :, :, :new_t]\n        if self.zero_triu:\n            ones = paddle.ones((t1, t2))\n            x = x * paddle.tril(ones, t2 - t1)[None, None, :, :]\n        return x\n\n    def forward(self, query, key, value, pos_emb, mask):\n        \"\"\"Compute 'Scaled Dot Product Attention' with rel. positional encoding.\n\n        Args:\n            query(Tensor): \n                Query tensor (#batch, time1, size).\n            key(Tensor): \n                Key tensor (#batch, time2, size).\n            value(Tensor): \n                Value tensor (#batch, time2, size).\n            pos_emb(Tensor): \n                Positional embedding tensor (#batch, 2*time1-1, size).\n            mask(Tensor): \n                Mask tensor (#batch, 1, time2) or (#batch, time1, time2).\n\n        Returns:\n            Tensor: Output tensor (#batch, time1, d_model).\n        \"\"\"\n        q, k, v = self.forward_qkv(query, key, value)\n        # (batch, time1, head, d_k)\n        q = q.transpose([0, 2, 1, 3])\n        n_batch_pos = paddle.shape(pos_emb)[0]\n        p = self.linear_pos(pos_emb).reshape(\n            [n_batch_pos, -1, self.h, self.d_k])\n        # (batch, head, 2*time1-1, d_k)\n        p = p.transpose([0, 2, 1, 3])\n        # (batch, head, time1, d_k)\n        q_with_bias_u = (q + self.pos_bias_u).transpose([0, 2, 1, 3])\n        # (batch, head, time1, d_k)\n        q_with_bias_v = (q + self.pos_bias_v).transpose([0, 2, 1, 3])\n\n        # compute attention score\n        # first compute matrix a and matrix c\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n        # (batch, head, time1, time2)\n        matrix_ac = paddle.matmul(q_with_bias_u, k.transpose([0, 1, 3, 2]))\n\n        # compute matrix b and matrix d\n        # (batch, head, time1, 2*time1-1)\n        matrix_bd = paddle.matmul(q_with_bias_v, p.transpose([0, 1, 3, 2]))\n        matrix_bd = self.rel_shift(matrix_bd)\n        # (batch, head, time1, time2)\n        scores = (matrix_ac + matrix_bd) / math.sqrt(self.d_k)\n\n        return self.forward_attention(v, scores, mask)\n\n\nclass LegacyRelPositionMultiHeadedAttention(MultiHeadedAttention):\n    \"\"\"Multi-Head Attention layer with relative position encoding (old version).\n    Details can be found in https://github.com/espnet/espnet/pull/2816.\n    Paper: https://arxiv.org/abs/1901.02860\n\n    Args:\n        n_head (int): \n            The number of heads.\n        n_feat (int): \n            The number of features.\n        dropout_rate (float): \n            Dropout rate.\n        zero_triu (bool): \n            Whether to zero the upper triangular part of attention matrix.\n    \"\"\"\n\n    def __init__(self, n_head, n_feat, dropout_rate, zero_triu=False):\n        \"\"\"Construct an RelPositionMultiHeadedAttention object.\"\"\"\n        super().__init__(n_head, n_feat, dropout_rate)\n        self.zero_triu = zero_triu\n        # linear transformation for positional encoding\n        self.linear_pos = nn.Linear(n_feat, n_feat, bias_attr=False)\n        # these two learnable bias are used in matrix c and matrix d\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n\n        self.pos_bias_u = paddle.create_parameter(\n            shape=(self.h, self.d_k),\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.XavierUniform())\n        self.pos_bias_v = paddle.create_parameter(\n            shape=(self.h, self.d_k),\n            dtype='float32',\n            default_initializer=paddle.nn.initializer.XavierUniform())\n\n    def rel_shift(self, x):\n        \"\"\"Compute relative positional encoding.\n        Args:\n            x(Tensor): \n                Input tensor (batch, head, time1, time2).\n        Returns:\n            Tensor:Output tensor.\n        \"\"\"\n        b, h, t1, t2 = paddle.shape(x)\n        zero_pad = paddle.zeros((b, h, t1, 1))\n        x_padded = paddle.concat([zero_pad, x], axis=-1)\n        x_padded = paddle.reshape(x_padded, [b, h, t2 + 1, t1])\n        # only keep the positions from 0 to time2\n        x = paddle.reshape(x_padded[:, :, 1:], [b, h, t1, t2])\n\n        if self.zero_triu:\n            ones = paddle.ones((t1, t2))\n            x = x * paddle.tril(ones, t2 - t1)[None, None, :, :]\n\n        return x\n\n    def forward(self, query, key, value, pos_emb, mask):\n        \"\"\"Compute 'Scaled Dot Product Attention' with rel. positional encoding.\n\n        Args:\n            query(Tensor): Query tensor (#batch, time1, size).\n            key(Tensor): Key tensor (#batch, time2, size).\n            value(Tensor): Value tensor (#batch, time2, size).\n            pos_emb(Tensor): Positional embedding tensor (#batch, time1, size).\n            mask(Tensor): Mask tensor (#batch, 1, time2) or (#batch, time1, time2).\n\n        Returns:\n            Tensor: Output tensor (#batch, time1, d_model).\n        \"\"\"\n        q, k, v = self.forward_qkv(query, key, value)\n        # (batch, time1, head, d_k)\n        q = paddle.transpose(q, [0, 2, 1, 3])\n\n        n_batch_pos = paddle.shape(pos_emb)[0]\n        p = paddle.reshape(\n            self.linear_pos(pos_emb), [n_batch_pos, -1, self.h, self.d_k])\n        # (batch, head, time1, d_k)\n        p = paddle.transpose(p, [0, 2, 1, 3])\n        # (batch, head, time1, d_k)\n        q_with_bias_u = paddle.transpose((q + self.pos_bias_u), [0, 2, 1, 3])\n        # (batch, head, time1, d_k)\n        q_with_bias_v = paddle.transpose((q + self.pos_bias_v), [0, 2, 1, 3])\n\n        # compute attention score\n        # first compute matrix a and matrix c\n        # as described in https://arxiv.org/abs/1901.02860 Section 3.3\n        # (batch, head, time1, time2)\n        matrix_ac = paddle.matmul(q_with_bias_u,\n                                  paddle.transpose(k, [0, 1, 3, 2]))\n\n        # compute matrix b and matrix d\n        # (batch, head, time1, time1)\n        matrix_bd = paddle.matmul(q_with_bias_v,\n                                  paddle.transpose(p, [0, 1, 3, 2]))\n        matrix_bd = self.rel_shift(matrix_bd)\n        # (batch, head, time1, time2)\n        scores = (matrix_ac + matrix_bd) / math.sqrt(self.d_k)\n\n        return self.forward_attention(v, scores, mask)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/decoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n# 暂时删除了 dyminic conv\n\"\"\"Decoder definition.\"\"\"\nimport logging\nfrom typing import Any\nfrom typing import List\nfrom typing import Tuple\n\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\nfrom paddlespeech.t2s.modules.transformer.attention import MultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.decoder_layer import DecoderLayer\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.lightconv import LightweightConvolution\nfrom paddlespeech.t2s.modules.transformer.mask import subsequent_mask\nfrom paddlespeech.t2s.modules.transformer.positionwise_feed_forward import PositionwiseFeedForward\nfrom paddlespeech.t2s.modules.transformer.repeat import repeat\n\n\nclass Decoder(nn.Layer):\n    \"\"\"Transfomer decoder module.\n\n    Args:\n        odim (int): \n            Output diminsion.\n        self_attention_layer_type (str): \n            Self-attention layer type.\n        attention_dim (int): \n            Dimention of attention.\n        attention_heads (int): \n            The number of heads of multi head attention.\n        conv_wshare (int):\n            The number of kernel of convolution. Only used in\n            self_attention_layer_type == \"lightconv*\" or \"dynamiconv*\".\n        conv_kernel_length (Union[int, str]):\n            Kernel size str of convolution\n            (e.g. 71_71_71_71_71_71). Only used in self_attention_layer_type == \"lightconv*\" or \"dynamiconv*\".\n        conv_usebias (bool): \n            Whether to use bias in convolution. Only used in\n            self_attention_layer_type == \"lightconv*\" or \"dynamiconv*\".\n        linear_units(int): \n            The number of units of position-wise feed forward.\n        num_blocks (int): \n            The number of decoder blocks.\n        dropout_rate (float): \n            Dropout rate.\n        positional_dropout_rate (float): \n            Dropout rate after adding positional encoding.\n        self_attention_dropout_rate (float): \n            Dropout rate in self-attention.\n        src_attention_dropout_rate (float): \n            Dropout rate in source-attention.\n        input_layer (Union[str, nn.Layer]): \n            Input layer type.\n        use_output_layer (bool): \n            Whether to use output layer.\n        pos_enc_class (nn.Layer): \n            Positional encoding module class.\n            `PositionalEncoding `or `ScaledPositionalEncoding`\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n\n    \"\"\"\n\n    def __init__(\n            self,\n            odim,\n            selfattention_layer_type=\"selfattn\",\n            attention_dim=256,\n            attention_heads=4,\n            conv_wshare=4,\n            conv_kernel_length=11,\n            conv_usebias=False,\n            linear_units=2048,\n            num_blocks=6,\n            dropout_rate=0.1,\n            positional_dropout_rate=0.1,\n            self_attention_dropout_rate=0.0,\n            src_attention_dropout_rate=0.0,\n            input_layer=\"embed\",\n            use_output_layer=True,\n            pos_enc_class=PositionalEncoding,\n            normalize_before=True,\n            concat_after=False, ):\n        \"\"\"Construct an Decoder object.\"\"\"\n        nn.Layer.__init__(self)\n        if input_layer == \"embed\":\n            self.embed = nn.Sequential(\n                nn.Embedding(odim, attention_dim),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer == \"linear\":\n            self.embed = nn.Sequential(\n                nn.Linear(odim, attention_dim),\n                nn.LayerNorm(attention_dim),\n                nn.Dropout(dropout_rate),\n                nn.ReLU(),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif isinstance(input_layer, nn.Layer):\n            self.embed = nn.Sequential(\n                input_layer,\n                pos_enc_class(attention_dim, positional_dropout_rate))\n        else:\n            raise NotImplementedError(\"only `embed` or nn.Layer is supported.\")\n        self.normalize_before = normalize_before\n\n        # self-attention module definition\n        if selfattention_layer_type == \"selfattn\":\n            logging.info(\"decoder self-attention layer type = self-attention\")\n            decoder_selfattn_layer = MultiHeadedAttention\n            decoder_selfattn_layer_args = [\n                (attention_heads, attention_dim, self_attention_dropout_rate, )\n            ] * num_blocks\n        elif selfattention_layer_type == \"lightconv\":\n            logging.info(\n                \"decoder self-attention layer type = lightweight convolution\")\n            decoder_selfattn_layer = LightweightConvolution\n            decoder_selfattn_layer_args = [(\n                conv_wshare, attention_dim, self_attention_dropout_rate,\n                int(conv_kernel_length.split(\"_\")[lnum]), True, conv_usebias, )\n                                           for lnum in range(num_blocks)]\n\n        self.decoders = repeat(\n            num_blocks,\n            lambda lnum: DecoderLayer(\n                attention_dim,\n                decoder_selfattn_layer(*decoder_selfattn_layer_args[lnum]),\n                MultiHeadedAttention(attention_heads, attention_dim, src_attention_dropout_rate),\n                PositionwiseFeedForward(attention_dim, linear_units, dropout_rate),\n                dropout_rate,\n                normalize_before,\n                concat_after, ), )\n        self.selfattention_layer_type = selfattention_layer_type\n        if self.normalize_before:\n            self.after_norm = LayerNorm(attention_dim)\n        if use_output_layer:\n            self.output_layer = nn.Linear(attention_dim, odim)\n        else:\n            self.output_layer = None\n\n    def forward(self, tgt, tgt_mask, memory, memory_mask):\n        \"\"\"Forward decoder.\n        Args:\n            tgt(Tensor): \n                Input token ids, int64 (#batch, maxlen_out) if input_layer == \"embed\".\n                In the other case, input tensor (#batch, maxlen_out, odim).\n            tgt_mask(Tensor): \n                Input token mask (#batch, maxlen_out).\n            memory(Tensor): \n                Encoded memory, float32 (#batch, maxlen_in, feat).\n            memory_mask(Tensor): \n                Encoded memory mask (#batch, maxlen_in).\n\n        Returns:\n            Tensor:\n                Decoded token score before softmax (#batch, maxlen_out, odim) if use_output_layer is True. \n                In the other case,final block outputs (#batch, maxlen_out, attention_dim).\n            Tensor: \n                Score mask before softmax (#batch, maxlen_out).\n\n        \"\"\"\n        x = self.embed(tgt)\n        x, tgt_mask, memory, memory_mask = self.decoders(x, tgt_mask, memory,\n                                                         memory_mask)\n        if self.normalize_before:\n            x = self.after_norm(x)\n        if self.output_layer is not None:\n            x = self.output_layer(x)\n        return x, tgt_mask\n\n    def forward_one_step(self, tgt, tgt_mask, memory, cache=None):\n        \"\"\"Forward one step.\n\n        Args:\n            tgt(Tensor): \n                Input token ids, int64 (#batch, maxlen_out).\n            tgt_mask(Tensor): \n                Input token mask (#batch, maxlen_out).\n            memory(Tensor): \n                Encoded memory, float32 (#batch, maxlen_in, feat).\n            cache((List[Tensor]), optional): \n                List of cached tensors. (Default value = None)\n\n        Returns:\n            Tensor: \n                Output tensor (batch, maxlen_out, odim).\n            List[Tensor]: \n                List of cache tensors of each decoder layer.\n\n        \"\"\"\n        x = self.embed(tgt)\n        if cache is None:\n            cache = [None] * len(self.decoders)\n        new_cache = []\n        for c, decoder in zip(cache, self.decoders):\n            x, tgt_mask, memory, memory_mask = decoder(\n                x, tgt_mask, memory, None, cache=c)\n            new_cache.append(x)\n\n        if self.normalize_before:\n            y = self.after_norm(x[:, -1])\n        else:\n            y = x[:, -1]\n        if self.output_layer is not None:\n            y = F.log_softmax(self.output_layer(y), axis=-1)\n\n        return y, new_cache\n\n    # beam search API (see ScorerInterface)\n    def score(self, ys, state, x):\n        \"\"\"Score.\"\"\"\n        ys_mask = subsequent_mask(len(ys)).unsqueeze(0)\n        if self.selfattention_layer_type != \"selfattn\":\n            # TODO(karita): implement cache\n            logging.warning(\n                f\"{self.selfattention_layer_type} does not support cached decoding.\"\n            )\n            state = None\n        logp, state = self.forward_one_step(\n            ys.unsqueeze(0), ys_mask, x.unsqueeze(0), cache=state)\n        return logp.squeeze(0), state\n\n    # batch beam search API (see BatchScorerInterface)\n    def batch_score(self,\n                    ys: paddle.Tensor,\n                    states: List[Any],\n                    xs: paddle.Tensor) -> Tuple[paddle.Tensor, List[Any]]:\n        \"\"\"Score new token batch (required).\n\n        Args:\n            ys(Tensor): \n                paddle.int64 prefix tokens (n_batch, ylen).\n            states(List[Any]): \n                Scorer states for prefix tokens.\n            xs(Tensor): \n                The encoder feature that generates ys (n_batch, xlen, n_feat).\n\n        Returns:\n            tuple[Tensor, List[Any]]:\n                Tuple ofbatchfied scores for next token with shape of `(n_batch, n_vocab)` and next state list for ys.\n\n        \"\"\"\n        # merge states\n        n_batch = len(ys)\n        n_layers = len(self.decoders)\n        if states[0] is None:\n            batch_state = None\n        else:\n            # transpose state of [batch, layer] into [layer, batch]\n            batch_state = [\n                paddle.stack([states[b][i] for b in range(n_batch)])\n                for i in range(n_layers)\n            ]\n\n        # batch decoding\n        ys_mask = subsequent_mask(ys.shape[-1]).unsqueeze(0)\n        logp, states = self.forward_one_step(ys, ys_mask, xs, cache=batch_state)\n\n        # transpose state of [layer, batch] into [batch, layer]\n        state_list = [[states[i][b] for i in range(n_layers)]\n                      for b in range(n_batch)]\n        return logp, state_list\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/decoder_layer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Decoder self-attention layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\n\n\nclass DecoderLayer(nn.Layer):\n    \"\"\"Single decoder layer module.\n\n \n    Args:\n        size (int): \n            Input dimension.\n        self_attn (nn.Layer): \n            Self-attention module instance.\n            `MultiHeadedAttention` instance can be used as the argument.\n        src_attn (nn.Layer): \n            Self-attention module instance.\n            `MultiHeadedAttention` instance can be used as the argument.\n        feed_forward (nn.Layer): \n            Feed-forward module instance.\n            `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance can be used as the argument.\n        dropout_rate (float):\n            Dropout rate.\n        normalize_before (bool):\n             Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n\n    \"\"\"\n\n    def __init__(\n            self,\n            size,\n            self_attn,\n            src_attn,\n            feed_forward,\n            dropout_rate,\n            normalize_before=True,\n            concat_after=False, ):\n        \"\"\"Construct an DecoderLayer object.\"\"\"\n        super().__init__()\n        self.size = size\n        self.self_attn = self_attn\n        self.src_attn = src_attn\n        self.feed_forward = feed_forward\n        self.norm1 = LayerNorm(size)\n        self.norm2 = LayerNorm(size)\n        self.norm3 = LayerNorm(size)\n        self.dropout = nn.Dropout(dropout_rate)\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        if self.concat_after:\n            self.concat_linear1 = nn.Linear(size + size, size)\n            self.concat_linear2 = nn.Linear(size + size, size)\n\n    def forward(self, tgt, tgt_mask, memory, memory_mask, cache=None):\n        \"\"\"Compute decoded features.\n\n        Args:\n            tgt(Tensor): \n                Input tensor (#batch, maxlen_out, size).\n            tgt_mask(Tensor): \n                Mask for input tensor (#batch, maxlen_out).\n            memory(Tensor): \n                Encoded memory, float32 (#batch, maxlen_in, size).\n            memory_mask(Tensor): \n                Encoded memory mask (#batch, maxlen_in).\n            cache(List[Tensor], optional): \n                List of cached tensors.\n                Each tensor shape should be (#batch, maxlen_out - 1, size). (Default value = None)\n        Returns:\n            Tensor\n                Output tensor(#batch, maxlen_out, size).\n            Tensor\n                Mask for output tensor (#batch, maxlen_out).\n            Tensor\n                Encoded memory (#batch, maxlen_in, size).\n            Tensor\n                Encoded memory mask (#batch, maxlen_in).\n\n        \"\"\"\n        residual = tgt\n        if self.normalize_before:\n            tgt = self.norm1(tgt)\n\n        if cache is None:\n            tgt_q = tgt\n            tgt_q_mask = tgt_mask\n        else:\n            # compute only the last frame query keeping dim: max_time_out -> 1\n            assert cache.shape == [\n                tgt.shape[0],\n                tgt.shape[1] - 1,\n                self.size,\n            ], f\"{cache.shape} == {(tgt.shape[0], tgt.shape[1] - 1, self.size)}\"\n            tgt_q = tgt[:, -1:, :]\n            residual = residual[:, -1:, :]\n            tgt_q_mask = None\n            if tgt_mask is not None:\n                tgt_mask = paddle.cast(tgt_mask, dtype=\"int64\")\n                tgt_q_mask = tgt_mask[:, -1:, :]\n                tgt_q_mask = paddle.cast(tgt_q_mask, dtype=\"bool\")\n\n        if self.concat_after:\n            tgt_concat = paddle.concat(\n                (tgt_q, self.self_attn(tgt_q, tgt, tgt, tgt_q_mask)), axis=-1)\n            x = residual + self.concat_linear1(tgt_concat)\n        else:\n            x = residual + self.dropout(\n                self.self_attn(tgt_q, tgt, tgt, tgt_q_mask))\n        if not self.normalize_before:\n            x = self.norm1(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm2(x)\n        if self.concat_after:\n            x_concat = paddle.concat(\n                (x, self.src_attn(x, memory, memory, memory_mask)), axis=-1)\n            x = residual + self.concat_linear2(x_concat)\n        else:\n            x = residual + self.dropout(\n                self.src_attn(x, memory, memory, memory_mask))\n        if not self.normalize_before:\n            x = self.norm2(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm3(x)\n        x = residual + self.dropout(self.feed_forward(x))\n        if not self.normalize_before:\n            x = self.norm3(x)\n\n        if cache is not None:\n            x = paddle.concat([cache, x], axis=1)\n\n        return x, tgt_mask, memory, memory_mask\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/embedding.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Positional Encoding Module.\"\"\"\nimport math\n\nimport paddle\nfrom paddle import nn\n\n\nclass PositionalEncoding(nn.Layer):\n    \"\"\"Positional encoding.\n\n    Args:\n        d_model (int):\n            Embedding dimension.\n        dropout_rate (float): \n            Dropout rate.\n        max_len (int): \n            Maximum input length.\n        reverse (bool): \n            Whether to reverse the input position.\n        type (str): \n            dtype of param\n    \"\"\"\n\n    def __init__(self,\n                 d_model,\n                 dropout_rate,\n                 max_len=5000,\n                 dtype=\"float32\",\n                 reverse=False):\n        \"\"\"Construct an PositionalEncoding object.\"\"\"\n        super().__init__()\n        self.d_model = d_model\n        self.reverse = reverse\n        self.xscale = math.sqrt(self.d_model)\n        self.dropout = nn.Dropout(p=dropout_rate)\n        self.pe = None\n        self.dtype = dtype\n        self.extend_pe(paddle.expand(paddle.zeros([1]), (1, max_len)))\n\n    def extend_pe(self, x):\n        \"\"\"Reset the positional encodings.\"\"\"\n        x_shape = paddle.shape(x)\n        pe = paddle.zeros([x_shape[1], self.d_model])\n        if self.reverse:\n            position = paddle.arange(\n                x_shape[1] - 1, -1, -1.0, dtype=self.dtype).unsqueeze(1)\n        else:\n            position = paddle.arange(\n                0, x_shape[1], dtype=self.dtype).unsqueeze(1)\n        div_term = paddle.exp(\n            paddle.arange(0, self.d_model, 2, dtype=self.dtype) *\n            -(math.log(10000.0) / self.d_model))\n        pe[:, 0::2] = paddle.sin(position * div_term)\n        pe[:, 1::2] = paddle.cos(position * div_term)\n        pe = pe.unsqueeze(0)\n        self.pe = paddle.assign(pe)\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Add positional encoding.\n\n        Args:\n            x (Tensor): \n                Input tensor (batch, time, `*`).\n\n        Returns:\n            Tensor: Encoded tensor (batch, time, `*`).\n        \"\"\"\n        self.extend_pe(x)\n        T = paddle.shape(x)[1]\n        x = x * self.xscale + self.pe[:, :T]\n        return self.dropout(x)\n\n\nclass ScaledPositionalEncoding(PositionalEncoding):\n    \"\"\"Scaled positional encoding module.\n    See Sec. 3.2  https://arxiv.org/abs/1809.08895\n\n    Args:\n        d_model (int): \n            Embedding dimension.\n        dropout_rate (float): \n            Dropout rate.\n        max_len (int): \n            Maximum input length.\n        dtype (str): \n            dtype of param\n    \"\"\"\n\n    def __init__(self, d_model, dropout_rate, max_len=5000, dtype=\"float32\"):\n        \"\"\"Initialize class.\"\"\"\n        super().__init__(\n            d_model=d_model,\n            dropout_rate=dropout_rate,\n            max_len=max_len,\n            dtype=dtype)\n        x = paddle.ones([1], dtype=self.dtype)\n        self.alpha = paddle.create_parameter(\n            shape=x.shape,\n            dtype=self.dtype,\n            default_initializer=nn.initializer.Assign(x))\n\n    def reset_parameters(self):\n        \"\"\"Reset parameters.\"\"\"\n        self.alpha = paddle.ones([1])\n\n    def forward(self, x):\n        \"\"\"Add positional encoding.\n\n        Args:\n            x (Tensor): \n                Input tensor (batch, time, `*`).\n        Returns:\n            Tensor: Encoded tensor (batch, time, `*`).\n        \"\"\"\n        self.extend_pe(x)\n        T = paddle.shape(x)[1]\n        x = x + self.alpha * self.pe[:, :T]\n        return self.dropout(x)\n\n\nclass RelPositionalEncoding(nn.Layer):\n    \"\"\"Relative positional encoding module (new implementation).\n    Details can be found in https://github.com/espnet/espnet/pull/2816.\n    See : Appendix B in https://arxiv.org/abs/1901.02860\n\n    Args:\n        d_model (int): \n            Embedding dimension.\n        dropout_rate (float): \n            Dropout rate.\n        max_len (int): \n            Maximum input length.\n    \"\"\"\n\n    def __init__(self, d_model, dropout_rate, max_len=5000, dtype=\"float32\"):\n        \"\"\"Construct an PositionalEncoding object.\"\"\"\n        super().__init__()\n        self.d_model = d_model\n        self.xscale = math.sqrt(self.d_model)\n        self.dropout = nn.Dropout(p=dropout_rate)\n        self.pe = None\n        self.dtype = dtype\n        self.extend_pe(paddle.expand(paddle.zeros([1]), (1, max_len)))\n\n    def extend_pe(self, x):\n        \"\"\"Reset the positional encodings.\"\"\"\n        if self.pe is not None:\n            # self.pe contains both positive and negative parts\n            # the length of self.pe is 2 * input_len - 1\n            if paddle.shape(self.pe)[1] >= paddle.shape(x)[1] * 2 - 1:\n                return\n        # Suppose `i` means to the position of query vecotr and `j` means the\n        # position of key vector. We use position relative positions when keys\n        # are to the left (i>j) and negative relative positions otherwise (i<j).\n        x_shape = paddle.shape(x)\n        pe_positive = paddle.zeros([x_shape[1], self.d_model])\n        pe_negative = paddle.zeros([x_shape[1], self.d_model])\n        position = paddle.arange(0, x_shape[1], dtype=self.dtype).unsqueeze(1)\n        div_term = paddle.exp(\n            paddle.arange(0, self.d_model, 2, dtype=self.dtype) *\n            -(math.log(10000.0) / self.d_model))\n        pe_positive[:, 0::2] = paddle.sin(position * div_term)\n        pe_positive[:, 1::2] = paddle.cos(position * div_term)\n        pe_negative[:, 0::2] = paddle.sin(-1 * position * div_term)\n        pe_negative[:, 1::2] = paddle.cos(-1 * position * div_term)\n\n        # Reserve the order of positive indices and concat both positive and\n        # negative indices. This is used to support the shifting trick\n        # as in https://arxiv.org/abs/1901.02860\n        pe_positive = paddle.flip(pe_positive, [0]).unsqueeze(0)\n        pe_negative = pe_negative[1:].unsqueeze(0)\n        pe = paddle.concat([pe_positive, pe_negative], axis=1)\n        self.pe = pe\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Add positional encoding.\n        Args:\n            x (Tensor):\n                Input tensor (batch, time, `*`).\n        Returns:\n            Tensor: Encoded tensor (batch, time, `*`).\n        \"\"\"\n        self.extend_pe(x)\n        x = x * self.xscale\n        T = paddle.shape(x)[1]\n        pe_size = paddle.shape(self.pe)\n        tmp = paddle.cast(paddle.floor(pe_size[1] / 2), dtype='int32')\n        pos_emb = self.pe[:, tmp - T + 1:tmp + T, ]\n        return self.dropout(x), self.dropout(pos_emb)\n\n\nclass LegacyRelPositionalEncoding(PositionalEncoding):\n    \"\"\"Relative positional encoding module (old version).\n\n    Details can be found in https://github.com/espnet/espnet/pull/2816.\n\n    See : Appendix B in https://arxiv.org/abs/1901.02860\n\n    Args:\n        d_model (int): \n            Embedding dimension.\n        dropout_rate (float): \n            Dropout rate.\n        max_len (int): \n            Maximum input length.\n\n    \"\"\"\n\n    def __init__(self, d_model: int, dropout_rate: float, max_len: int=5000):\n        \"\"\"\n        Args:\n            d_model (int): \n                Embedding dimension.\n            dropout_rate (float): \n                Dropout rate.\n            max_len (int, optional): \n                [Maximum input length.]. Defaults to 5000.\n        \"\"\"\n        super().__init__(d_model, dropout_rate, max_len, reverse=True)\n\n    def extend_pe(self, x):\n        \"\"\"Reset the positional encodings.\"\"\"\n        if self.pe is not None:\n            if paddle.shape(self.pe)[1] >= paddle.shape(x)[1]:\n                return\n        pe = paddle.zeros((paddle.shape(x)[1], self.d_model))\n        if self.reverse:\n            position = paddle.arange(\n                paddle.shape(x)[1] - 1, -1, -1.0,\n                dtype=paddle.float32).unsqueeze(1)\n        else:\n            position = paddle.arange(\n                0, paddle.shape(x)[1], dtype=paddle.float32).unsqueeze(1)\n        div_term = paddle.exp(\n            paddle.arange(0, self.d_model, 2, dtype=paddle.float32) *\n            -(math.log(10000.0) / self.d_model))\n        pe[:, 0::2] = paddle.sin(position * div_term)\n        pe[:, 1::2] = paddle.cos(position * div_term)\n        pe = pe.unsqueeze(0)\n        self.pe = pe\n\n    def forward(self, x: paddle.Tensor):\n        \"\"\"Compute positional encoding.\n        Args:\n            x (Tensor): \n                Input tensor (batch, time, `*`).\n        Returns:\n            Tensor: \n                Encoded tensor (batch, time, `*`).\n            Tensor: \n                Positional embedding tensor (1, time, `*`).\n        \"\"\"\n        self.extend_pe(x)\n        x = x * self.xscale\n        pos_emb = self.pe[:, :paddle.shape(x)[1]]\n        return self.dropout(x), self.dropout(pos_emb)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/encoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import List\nfrom typing import Union\n\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.conformer.convolution import ConvolutionModule\nfrom paddlespeech.t2s.modules.conformer.encoder_layer import EncoderLayer as ConformerEncoderLayer\nfrom paddlespeech.t2s.modules.layer_norm import LayerNorm\nfrom paddlespeech.t2s.modules.transformer.attention import MultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.attention import RelPositionMultiHeadedAttention\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import RelPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.embedding import ScaledPositionalEncoding\nfrom paddlespeech.t2s.modules.transformer.encoder_layer import EncoderLayer\nfrom paddlespeech.t2s.modules.transformer.multi_layer_conv import Conv1dLinear\nfrom paddlespeech.t2s.modules.transformer.multi_layer_conv import MultiLayeredConv1d\nfrom paddlespeech.t2s.modules.transformer.positionwise_feed_forward import PositionwiseFeedForward\nfrom paddlespeech.t2s.modules.transformer.repeat import repeat\nfrom paddlespeech.t2s.modules.transformer.subsampling import Conv2dSubsampling\n\n\nclass BaseEncoder(nn.Layer):\n    \"\"\"Base Encoder module.\n\n    Args:\n        idim (int): \n            Input dimension.\n        attention_dim (int): \n            Dimention of attention.\n        attention_heads (int): \n            The number of heads of multi head attention.\n        linear_units (int): \n            The number of units of position-wise feed forward.\n        num_blocks (int): \n            The number of decoder blocks.\n        dropout_rate (float): \n            Dropout rate.\n        positional_dropout_rate (float): \n            Dropout rate after adding positional encoding.\n        attention_dropout_rate (float): \n            Dropout rate in attention.\n        input_layer (Union[str, nn.Layer]): \n            Input layer type.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n        positionwise_layer_type (str): \n            \"linear\", \"conv1d\", or \"conv1d-linear\".\n        positionwise_conv_kernel_size (int): \n            Kernel size of positionwise conv1d layer.\n        macaron_style (bool): \n            Whether to use macaron style for positionwise layer.\n        pos_enc_layer_type (str): \n            Encoder positional encoding layer type.\n        selfattention_layer_type (str): \n            Encoder attention layer type.\n        activation_type (str): \n            Encoder activation function type.\n        use_cnn_module (bool): \n            Whether to use convolution module.\n        zero_triu (bool): \n            Whether to zero the upper triangular part of attention matrix.\n        cnn_module_kernel (int): \n            Kernerl size of convolution module.\n        padding_idx (int): \n            Padding idx for input_layer=embed.\n        stochastic_depth_rate (float): \n            Maximum probability to skip the encoder layer.\n        intermediate_layers (Union[List[int], None]): \n            indices of intermediate CTC layer.\n            indices start from 1.\n            if not None, intermediate outputs are returned (which changes return type\n            signature.)\n        encoder_type (str): \"transformer\", or \"conformer\".\n    \"\"\"\n\n    def __init__(self,\n                 idim: int,\n                 attention_dim: int=256,\n                 attention_heads: int=4,\n                 linear_units: int=2048,\n                 num_blocks: int=6,\n                 dropout_rate: float=0.1,\n                 positional_dropout_rate: float=0.1,\n                 attention_dropout_rate: float=0.0,\n                 input_layer: str=\"conv2d\",\n                 normalize_before: bool=True,\n                 concat_after: bool=False,\n                 positionwise_layer_type: str=\"linear\",\n                 positionwise_conv_kernel_size: int=1,\n                 macaron_style: bool=False,\n                 pos_enc_layer_type: str=\"abs_pos\",\n                 selfattention_layer_type: str=\"selfattn\",\n                 activation_type: str=\"swish\",\n                 use_cnn_module: bool=False,\n                 zero_triu: bool=False,\n                 cnn_module_kernel: int=31,\n                 padding_idx: int=-1,\n                 stochastic_depth_rate: float=0.0,\n                 intermediate_layers: Union[List[int], None]=None,\n                 encoder_type: str=\"transformer\"):\n        \"\"\"Construct an Base Encoder object.\"\"\"\n        super().__init__()\n        activation = get_activation(activation_type)\n        pos_enc_class = self.get_pos_enc_class(pos_enc_layer_type,\n                                               selfattention_layer_type)\n        self.encoder_type = encoder_type\n\n        self.conv_subsampling_factor = 1\n        self.embed = self.get_embed(\n            idim=idim,\n            input_layer=input_layer,\n            attention_dim=attention_dim,\n            pos_enc_class=pos_enc_class,\n            dropout_rate=dropout_rate,\n            positional_dropout_rate=positional_dropout_rate,\n            padding_idx=padding_idx)\n\n        self.normalize_before = normalize_before\n\n        # self-attention module definition\n        encoder_selfattn_layer, encoder_selfattn_layer_args = self.get_encoder_selfattn_layer(\n            selfattention_layer_type=selfattention_layer_type,\n            attention_heads=attention_heads,\n            attention_dim=attention_dim,\n            attention_dropout_rate=attention_dropout_rate,\n            zero_triu=zero_triu,\n            pos_enc_layer_type=pos_enc_layer_type)\n        # feed-forward module definition\n        positionwise_layer, positionwise_layer_args = self.get_positionwise_layer(\n            positionwise_layer_type, attention_dim, linear_units, dropout_rate,\n            positionwise_conv_kernel_size, activation)\n\n        # convolution module definition\n        convolution_layer = ConvolutionModule\n        convolution_layer_args = (attention_dim, cnn_module_kernel, activation)\n\n        if self.encoder_type == \"transformer\":\n            self.encoders = repeat(\n                num_blocks,\n                lambda lnum: EncoderLayer(\n                    attention_dim,\n                    encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                    positionwise_layer(*positionwise_layer_args),\n                    dropout_rate,\n                    normalize_before,\n                    concat_after, ), )\n\n        elif self.encoder_type == \"conformer\":\n            self.encoders = repeat(\n                num_blocks,\n                lambda lnum: ConformerEncoderLayer(\n                    attention_dim,\n                    encoder_selfattn_layer(*encoder_selfattn_layer_args),\n                    positionwise_layer(*positionwise_layer_args),\n                    positionwise_layer(*positionwise_layer_args) if macaron_style else None,\n                    convolution_layer(*convolution_layer_args) if use_cnn_module else None,\n                    dropout_rate,\n                    normalize_before,\n                    concat_after,\n                    stochastic_depth_rate * float(1 + lnum) / num_blocks, ), )\n            self.intermediate_layers = intermediate_layers\n        else:\n            raise NotImplementedError(\"Support only linear or conv1d.\")\n\n        if self.normalize_before:\n            self.after_norm = LayerNorm(attention_dim)\n\n    def get_positionwise_layer(self,\n                               positionwise_layer_type: str=\"linear\",\n                               attention_dim: int=256,\n                               linear_units: int=2048,\n                               dropout_rate: float=0.1,\n                               positionwise_conv_kernel_size: int=1,\n                               activation: nn.Layer=nn.ReLU()):\n        \"\"\"Define positionwise layer.\"\"\"\n        if positionwise_layer_type == \"linear\":\n            positionwise_layer = PositionwiseFeedForward\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       dropout_rate, activation)\n        elif positionwise_layer_type == \"conv1d\":\n            positionwise_layer = MultiLayeredConv1d\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       positionwise_conv_kernel_size,\n                                       dropout_rate, )\n        elif positionwise_layer_type == \"conv1d-linear\":\n            positionwise_layer = Conv1dLinear\n            positionwise_layer_args = (attention_dim, linear_units,\n                                       positionwise_conv_kernel_size,\n                                       dropout_rate, )\n        else:\n            raise NotImplementedError(\"Support only linear or conv1d.\")\n        return positionwise_layer, positionwise_layer_args\n\n    def get_encoder_selfattn_layer(self,\n                                   selfattention_layer_type: str=\"selfattn\",\n                                   attention_heads: int=4,\n                                   attention_dim: int=256,\n                                   attention_dropout_rate: float=0.0,\n                                   zero_triu: bool=False,\n                                   pos_enc_layer_type: str=\"abs_pos\"):\n        if selfattention_layer_type == \"selfattn\":\n            encoder_selfattn_layer = MultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, attention_dim,\n                                           attention_dropout_rate, )\n        elif selfattention_layer_type == \"rel_selfattn\":\n            assert pos_enc_layer_type == \"rel_pos\"\n            encoder_selfattn_layer = RelPositionMultiHeadedAttention\n            encoder_selfattn_layer_args = (attention_heads, attention_dim,\n                                           attention_dropout_rate, zero_triu, )\n        else:\n            raise ValueError(\"unknown encoder_attn_layer: \" +\n                             selfattention_layer_type)\n        return encoder_selfattn_layer, encoder_selfattn_layer_args\n\n    def get_pos_enc_class(self,\n                          pos_enc_layer_type: str=\"abs_pos\",\n                          selfattention_layer_type: str=\"selfattn\"):\n        if pos_enc_layer_type == \"abs_pos\":\n            pos_enc_class = PositionalEncoding\n        elif pos_enc_layer_type == \"scaled_abs_pos\":\n            pos_enc_class = ScaledPositionalEncoding\n        elif pos_enc_layer_type == \"rel_pos\":\n            assert selfattention_layer_type == \"rel_selfattn\"\n            pos_enc_class = RelPositionalEncoding\n        else:\n            raise ValueError(\"unknown pos_enc_layer: \" + pos_enc_layer_type)\n        return pos_enc_class\n\n    def get_embed(self,\n                  idim,\n                  input_layer=\"conv2d\",\n                  attention_dim: int=256,\n                  pos_enc_class=PositionalEncoding,\n                  dropout_rate: int=0.1,\n                  positional_dropout_rate: int=0.1,\n                  padding_idx: int=-1):\n\n        if input_layer == \"linear\":\n            embed = nn.Sequential(\n                nn.Linear(idim, attention_dim),\n                nn.LayerNorm(attention_dim),\n                nn.Dropout(dropout_rate),\n                nn.ReLU(),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer == \"conv2d\":\n            embed = Conv2dSubsampling(\n                idim,\n                attention_dim,\n                dropout_rate,\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n            self.conv_subsampling_factor = 4\n        elif input_layer == \"embed\":\n            embed = nn.Sequential(\n                nn.Embedding(idim, attention_dim, padding_idx=padding_idx),\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif isinstance(input_layer, nn.Layer):\n            embed = nn.Sequential(\n                input_layer,\n                pos_enc_class(attention_dim, positional_dropout_rate), )\n        elif input_layer is None:\n            embed = nn.Sequential(\n                pos_enc_class(attention_dim, positional_dropout_rate))\n        else:\n            raise ValueError(\"unknown input_layer: \" + input_layer)\n\n        return embed\n\n    def forward(self, xs, masks):\n        \"\"\"Encode input sequence.\n\n        Args:\n            xs (Tensor): \n                Input tensor (#batch, time, idim).\n            masks (Tensor): \n                Mask tensor (#batch, 1, time).\n\n        Returns: \n            Tensor: \n                Output tensor (#batch, time, attention_dim).\n            Tensor: \n                Mask tensor (#batch, 1, time).\n        \"\"\"\n        xs = self.embed(xs)\n        xs, masks = self.encoders(xs, masks)\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n        return xs, masks\n\n\nclass TransformerEncoder(BaseEncoder):\n    \"\"\"Transformer encoder module.\n\n    Args:\n        idim (int): \n            Input dimension.\n        attention_dim (int): \n            Dimention of attention.\n        attention_heads (int): \n            The number of heads of multi head attention.\n        linear_units (int): \n            The number of units of position-wise feed forward.\n        num_blocks (int): \n            The number of decoder blocks.\n        dropout_rate (float): \n            Dropout rate.\n        positional_dropout_rate (float): \n            Dropout rate after adding positional encoding.\n        attention_dropout_rate (float): \n            Dropout rate in attention.\n        input_layer (Union[str, paddle.nn.Layer]): \n            Input layer type.\n        pos_enc_layer_type (str): \n            Encoder positional encoding layer type.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n        positionwise_layer_type (str): \n            \"linear\", \"conv1d\", or \"conv1d-linear\".\n        positionwise_conv_kernel_size (int): \n            Kernel size of positionwise conv1d layer.\n        selfattention_layer_type (str): \n            Encoder attention layer type.\n        activation_type (str): \n            Encoder activation function type.\n        padding_idx (int): \n            Padding idx for input_layer=embed.\n    \"\"\"\n\n    def __init__(\n            self,\n            idim,\n            attention_dim: int=256,\n            attention_heads: int=4,\n            linear_units: int=2048,\n            num_blocks: int=6,\n            dropout_rate: float=0.1,\n            positional_dropout_rate: float=0.1,\n            attention_dropout_rate: float=0.0,\n            input_layer: str=\"conv2d\",\n            pos_enc_layer_type: str=\"abs_pos\",\n            normalize_before: bool=True,\n            concat_after: bool=False,\n            positionwise_layer_type: str=\"linear\",\n            positionwise_conv_kernel_size: int=1,\n            selfattention_layer_type: str=\"selfattn\",\n            activation_type: str=\"relu\",\n            padding_idx: int=-1, ):\n        \"\"\"Construct an Transformer Encoder object.\"\"\"\n        super().__init__(\n            idim,\n            attention_dim=attention_dim,\n            attention_heads=attention_heads,\n            linear_units=linear_units,\n            num_blocks=num_blocks,\n            dropout_rate=dropout_rate,\n            positional_dropout_rate=positional_dropout_rate,\n            attention_dropout_rate=attention_dropout_rate,\n            input_layer=input_layer,\n            pos_enc_layer_type=pos_enc_layer_type,\n            normalize_before=normalize_before,\n            concat_after=concat_after,\n            positionwise_layer_type=positionwise_layer_type,\n            positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n            selfattention_layer_type=selfattention_layer_type,\n            activation_type=activation_type,\n            padding_idx=padding_idx,\n            encoder_type=\"transformer\")\n\n    def forward(self,\n                xs: paddle.Tensor,\n                masks: paddle.Tensor,\n                note_emb: paddle.Tensor=None,\n                note_dur_emb: paddle.Tensor=None,\n                is_slur_emb: paddle.Tensor=None,\n                scale: int=16):\n        \"\"\"Encoder input sequence.\n\n        Args:\n            xs(Tensor): \n                Input tensor (#batch, time, idim).\n            masks(Tensor): \n                Mask tensor (#batch, 1, time).\n            note_emb(Tensor): \n                Input tensor (#batch, time, attention_dim).\n            note_dur_emb(Tensor): \n                Input tensor (#batch, time, attention_dim).\n            is_slur_emb(Tensor): \n                Input tensor (#batch, time, attention_dim).\n\n        Returns:\n            Tensor: \n                Output tensor (#batch, time, attention_dim).\n            Tensor: \n                Mask tensor (#batch, 1, time).\n        \"\"\"\n        xs = self.embed(xs)\n        if note_emb is not None:\n            xs = scale * xs + note_emb + note_dur_emb + is_slur_emb\n        xs, masks = self.encoders(xs, masks)\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n        return xs, masks\n\n    def forward_one_step(self, xs, masks, cache=None):\n        \"\"\"Encode input frame.\n\n        Args:\n            xs (Tensor): \n                Input tensor.\n            masks (Tensor): \n                Mask tensor.\n            cache (List[Tensor]): \n                List of cache tensors.\n\n        Returns:\n            Tensor:\n                 Output tensor.\n            Tensor:\n                 Mask tensor.\n            List[Tensor]: \n                List of new cache tensors.\n        \"\"\"\n\n        xs = self.embed(xs)\n        if cache is None:\n            cache = [None for _ in range(len(self.encoders))]\n        new_cache = []\n        for c, e in zip(cache, self.encoders):\n            xs, masks = e(xs, masks, cache=c)\n            new_cache.append(xs)\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n        return xs, masks, new_cache\n\n\nclass ConformerEncoder(BaseEncoder):\n    \"\"\"Conformer encoder module.\n\n    Args:\n        idim (int): \n            Input dimension.\n        attention_dim (int): \n            Dimention of attention.\n        attention_heads (int): \n            The number of heads of multi head attention.\n        linear_units (int): \n            The number of units of position-wise feed forward.\n        num_blocks (int): \n            The number of decoder blocks.\n        dropout_rate (float): \n            Dropout rate.\n        positional_dropout_rate (float): \n            Dropout rate after adding positional encoding.\n        attention_dropout_rate (float): \n            Dropout rate in attention.\n        input_layer (Union[str, nn.Layer]): \n            Input layer type.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool):\n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n        positionwise_layer_type (str): \n            \"linear\", \"conv1d\", or \"conv1d-linear\".\n        positionwise_conv_kernel_size (int): \n            Kernel size of positionwise conv1d layer.\n        macaron_style (bool): \n            Whether to use macaron style for positionwise layer.\n        pos_enc_layer_type (str): \n            Encoder positional encoding layer type.\n        selfattention_layer_type (str): \n            Encoder attention layer type.\n        activation_type (str): \n            Encoder activation function type.\n        use_cnn_module (bool): \n            Whether to use convolution module.\n        zero_triu (bool): \n            Whether to zero the upper triangular part of attention matrix.\n        cnn_module_kernel (int): \n            Kernerl size of convolution module.\n        padding_idx (int): \n            Padding idx for input_layer=embed.\n        stochastic_depth_rate (float): \n            Maximum probability to skip the encoder layer.\n        intermediate_layers (Union[List[int], None]):\n            indices of intermediate CTC layer. indices start from 1.\n            if not None, intermediate outputs are returned (which changes return type signature.)\n    \"\"\"\n\n    def __init__(\n            self,\n            idim: int,\n            attention_dim: int=256,\n            attention_heads: int=4,\n            linear_units: int=2048,\n            num_blocks: int=6,\n            dropout_rate: float=0.1,\n            positional_dropout_rate: float=0.1,\n            attention_dropout_rate: float=0.0,\n            input_layer: str=\"conv2d\",\n            normalize_before: bool=True,\n            concat_after: bool=False,\n            positionwise_layer_type: str=\"linear\",\n            positionwise_conv_kernel_size: int=1,\n            macaron_style: bool=False,\n            pos_enc_layer_type: str=\"rel_pos\",\n            selfattention_layer_type: str=\"rel_selfattn\",\n            activation_type: str=\"swish\",\n            use_cnn_module: bool=False,\n            zero_triu: bool=False,\n            cnn_module_kernel: int=31,\n            padding_idx: int=-1,\n            stochastic_depth_rate: float=0.0,\n            intermediate_layers: Union[List[int], None]=None, ):\n        \"\"\"Construct an Conformer Encoder object.\"\"\"\n        super().__init__(\n            idim=idim,\n            attention_dim=attention_dim,\n            attention_heads=attention_heads,\n            linear_units=linear_units,\n            num_blocks=num_blocks,\n            dropout_rate=dropout_rate,\n            positional_dropout_rate=positional_dropout_rate,\n            attention_dropout_rate=attention_dropout_rate,\n            input_layer=input_layer,\n            normalize_before=normalize_before,\n            concat_after=concat_after,\n            positionwise_layer_type=positionwise_layer_type,\n            positionwise_conv_kernel_size=positionwise_conv_kernel_size,\n            macaron_style=macaron_style,\n            pos_enc_layer_type=pos_enc_layer_type,\n            selfattention_layer_type=selfattention_layer_type,\n            activation_type=activation_type,\n            use_cnn_module=use_cnn_module,\n            zero_triu=zero_triu,\n            cnn_module_kernel=cnn_module_kernel,\n            padding_idx=padding_idx,\n            stochastic_depth_rate=stochastic_depth_rate,\n            intermediate_layers=intermediate_layers,\n            encoder_type=\"conformer\")\n\n    def forward(self, xs, masks):\n        \"\"\"Encode input sequence.\n\n        Args:\n            xs (Tensor): \n                Input tensor (#batch, time, idim).\n            masks (Tensor): \n                Mask tensor (#batch, 1, time).\n        Returns:\n            Tensor: \n                Output tensor (#batch, time, attention_dim).\n            Tensor: \n                Mask tensor (#batch, 1, time).\n        \"\"\"\n        if isinstance(self.embed, (Conv2dSubsampling)):\n            xs, masks = self.embed(xs, masks)\n        else:\n            xs = self.embed(xs)\n\n        if self.intermediate_layers is None:\n            xs, masks = self.encoders(xs, masks)\n        else:\n            intermediate_outputs = []\n            for layer_idx, encoder_layer in enumerate(self.encoders):\n                xs, masks = encoder_layer(xs, masks)\n\n                if (self.intermediate_layers is not None and\n                        layer_idx + 1 in self.intermediate_layers):\n                    # intermediate branches also require normalization.\n                    encoder_output = xs\n                    if isinstance(encoder_output, tuple):\n                        encoder_output = encoder_output[0]\n                        if self.normalize_before:\n                            encoder_output = self.after_norm(encoder_output)\n                    intermediate_outputs.append(encoder_output)\n\n        if isinstance(xs, tuple):\n            xs = xs[0]\n\n        if self.normalize_before:\n            xs = self.after_norm(xs)\n\n        if self.intermediate_layers is not None:\n            return xs, masks, intermediate_outputs\n        return xs, masks\n\n\nclass Conv1dResidualBlock(nn.Layer):\n    \"\"\"\n    Special module for simplified version of Encoder class.\n    \"\"\"\n\n    def __init__(self,\n                 idim: int=256,\n                 odim: int=256,\n                 kernel_size: int=5,\n                 dropout_rate: float=0.2):\n        super().__init__()\n        self.main_block = nn.Sequential(\n            nn.Conv1D(\n                idim, odim, kernel_size=kernel_size, padding=kernel_size // 2),\n            nn.ReLU(),\n            nn.BatchNorm1D(odim),\n            nn.Dropout(p=dropout_rate))\n        self.conv1d_residual = nn.Conv1D(idim, odim, kernel_size=1)\n\n    def forward(self, xs):\n        \"\"\"Encode input sequence.\n        Args:\n            xs (Tensor): \n                Input tensor (#batch, idim, T).\n        Returns:\n            Tensor: Output tensor (#batch, odim, T).\n        \"\"\"\n        outputs = self.main_block(xs)\n        outputs = self.conv1d_residual(xs) + outputs\n        return outputs\n\n\nclass CNNDecoder(nn.Layer):\n    \"\"\"\n    Much simplified decoder than the original one with Prenet.\n    \"\"\"\n\n    def __init__(\n            self,\n            emb_dim: int=256,\n            odim: int=80,\n            kernel_size: int=5,\n            dropout_rate: float=0.2,\n            resblock_kernel_sizes: List[int]=[256, 256], ):\n\n        super().__init__()\n\n        input_shape = emb_dim\n        out_sizes = resblock_kernel_sizes\n        out_sizes.append(out_sizes[-1])\n\n        in_sizes = [input_shape] + out_sizes[:-1]\n        self.residual_blocks = nn.LayerList([\n            Conv1dResidualBlock(\n                idim=in_channels,\n                odim=out_channels,\n                kernel_size=kernel_size,\n                dropout_rate=dropout_rate, )\n            for in_channels, out_channels in zip(in_sizes, out_sizes)\n        ])\n        self.conv1d = nn.Conv1D(\n            in_channels=out_sizes[-1], out_channels=odim, kernel_size=1)\n\n    def forward(self, xs, masks=None):\n        \"\"\"Encode input sequence.\n        Args:\n            xs (Tensor): \n                Input tensor (#batch, time, idim).\n            masks (Tensor): \n                Mask tensor (#batch, 1, time).\n        Returns:\n            Tensor: Output tensor (#batch, time, odim).\n        \"\"\"\n        # exchange the temporal dimension and the feature dimension\n        xs = xs.transpose([0, 2, 1])\n        if masks is not None:\n            xs = xs * masks\n\n        for layer in self.residual_blocks:\n            outputs = layer(xs)\n            if masks is not None:\n                # input_mask B * 1 * T\n                outputs = outputs * masks\n            xs = outputs\n        outputs = self.conv1d(outputs)\n        if masks is not None:\n            outputs = outputs * masks\n        outputs = outputs.transpose([0, 2, 1])\n        return outputs\n\n\nclass CNNPostnet(nn.Layer):\n    def __init__(\n            self,\n            odim: int=80,\n            kernel_size: int=5,\n            dropout_rate: float=0.2,\n            resblock_kernel_sizes: List[int]=[256, 256], ):\n        super().__init__()\n        out_sizes = resblock_kernel_sizes\n        in_sizes = [odim] + out_sizes[:-1]\n        self.residual_blocks = nn.LayerList([\n            Conv1dResidualBlock(\n                idim=in_channels,\n                odim=out_channels,\n                kernel_size=kernel_size,\n                dropout_rate=dropout_rate)\n            for in_channels, out_channels in zip(in_sizes, out_sizes)\n        ])\n        self.conv1d = nn.Conv1D(\n            in_channels=out_sizes[-1], out_channels=odim, kernel_size=1)\n\n    def forward(self, xs, masks=None):\n        \"\"\"Encode input sequence.\n        Args:\n            xs (Tensor): \n                Input tensor (#batch, odim, time).\n            masks (Tensor): \n                Mask tensor (#batch, 1, time).\n        Returns:\n            Tensor: Output tensor (#batch, odim, time).\n        \"\"\"\n        for layer in self.residual_blocks:\n            outputs = layer(xs)\n            if masks is not None:\n                # input_mask B * 1 * T\n                outputs = outputs * masks\n            xs = outputs\n        outputs = self.conv1d(outputs)\n        if masks is not None:\n            outputs = outputs * masks\n        return outputs\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/encoder_layer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Encoder self-attention layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass EncoderLayer(nn.Layer):\n    \"\"\"Encoder layer module.\n\n    Args:\n        size (int): \n            Input dimension.\n        self_attn (nn.Layer): \n            Self-attention module instance.\n            `MultiHeadedAttention`  instance can be used as the argument.\n        feed_forward (nn.Layer): \n            Feed-forward module instance.\n            `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance can be used as the argument.\n        dropout_rate (float): \n            Dropout rate.\n        normalize_before (bool): \n            Whether to use layer_norm before the first block.\n        concat_after (bool): \n            Whether to concat attention layer's input and output.\n            if True, additional linear will be applied.\n            i.e. x -> x + linear(concat(x, att(x)))\n            if False, no additional linear will be applied. i.e. x -> x + att(x)\n    \"\"\"\n\n    def __init__(\n            self,\n            size,\n            self_attn,\n            feed_forward,\n            dropout_rate,\n            normalize_before=True,\n            concat_after=False, ):\n        \"\"\"Construct an EncoderLayer object.\"\"\"\n        super().__init__()\n        self.self_attn = self_attn\n        self.feed_forward = feed_forward\n        self.norm1 = nn.LayerNorm(size)\n        self.norm2 = nn.LayerNorm(size)\n        self.dropout = nn.Dropout(dropout_rate)\n        self.size = size\n        self.normalize_before = normalize_before\n        self.concat_after = concat_after\n        if self.concat_after:\n            self.concat_linear = nn.Linear(size + size, size, bias_attr=True)\n\n    def forward(self, x, mask, cache=None):\n        \"\"\"Compute encoded features.\n\n        Args:\n            x(Tensor): \n                Input tensor (#batch, time, size).\n            mask(Tensor): \n                Mask tensor for the input (#batch, time).\n            cache(Tensor, optional): \n                Cache tensor of the input (#batch, time - 1, size). \n\n        Returns:\n            Tensor: \n                Output tensor (#batch, time, size).\n            Tensor: \n                Mask tensor (#batch, time).\n        \"\"\"\n        residual = x\n        if self.normalize_before:\n            x = self.norm1(x)\n\n        if cache is None:\n            x_q = x\n        else:\n            assert cache.shape == (x.shape[0], x.shape[1] - 1, self.size)\n            x_q = x[:, -1:, :]\n            residual = residual[:, -1:, :]\n            mask = None if mask is None else mask[:, -1:, :]\n\n        if self.concat_after:\n            x_concat = paddle.concat(\n                (x, self.self_attn(x_q, x, x, mask)), axis=-1)\n            x = residual + self.concat_linear(x_concat)\n        else:\n\n            x = residual + self.dropout(self.self_attn(x_q, x, x, mask))\n        if not self.normalize_before:\n            x = self.norm1(x)\n\n        residual = x\n        if self.normalize_before:\n            x = self.norm2(x)\n        x = residual + self.dropout(self.feed_forward(x))\n        if not self.normalize_before:\n            x = self.norm2(x)\n\n        if cache is not None:\n            x = paddle.concat([cache, x], axis=1)\n\n        return x, mask\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/lightconv.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Lightweight Convolution Module.\"\"\"\nimport numpy\nimport paddle\nimport paddle.nn.functional as F\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.activation import get_activation\nfrom paddlespeech.t2s.modules.masked_fill import masked_fill\n\nMIN_VALUE = float(numpy.finfo(numpy.float32).min)\n\n\nclass LightweightConvolution(nn.Layer):\n    \"\"\"Lightweight Convolution layer.\n\n    This implementation is based on\n    https://github.com/pytorch/fairseq/tree/master/fairseq\n\n    Args:\n        wshare (int): \n            the number of kernel of convolution\n        n_feat (int): \n            the number of features\n        dropout_rate (float): \n            dropout_rate\n        kernel_size (int): \n            kernel size (length)\n        use_kernel_mask (bool): \n            Use causal mask or not for convolution kernel\n        use_bias (bool): \n            Use bias term or not.\n\n    \"\"\"\n\n    def __init__(\n            self,\n            wshare,\n            n_feat,\n            dropout_rate,\n            kernel_size,\n            use_kernel_mask=False,\n            use_bias=False, ):\n        \"\"\"Construct Lightweight Convolution layer.\"\"\"\n        super().__init__()\n\n        assert n_feat % wshare == 0\n        self.wshare = wshare\n        self.use_kernel_mask = use_kernel_mask\n        self.dropout_rate = dropout_rate\n        self.kernel_size = kernel_size\n        self.padding_size = int(kernel_size / 2)\n\n        # linear -> GLU -> lightconv -> linear\n        self.linear1 = nn.Linear(n_feat, n_feat * 2)\n        self.linear2 = nn.Linear(n_feat, n_feat)\n        self.act = get_activation(\"glu\")\n\n        # lightconv related\n        self.uniform_ = nn.initializer.Uniform()\n        self.weight = paddle.to_tensor(\n            numpy.random.uniform(0, 1, size=[self.wshare, 1, kernel_size]),\n            dtype=\"float32\")\n        self.uniform_(self.weight)\n        self.weight = paddle.create_parameter(\n            shape=self.weight.shape,\n            dtype=str(self.weight.numpy().dtype),\n            default_initializer=paddle.nn.initializer.Assign(self.weight))\n        self.use_bias = use_bias\n        if self.use_bias:\n            self.bias = paddle.Tensor(n_feat)\n            self.bias = paddle.create_parameter(\n                shape=self.bias.shape,\n                dtype=str(self.bias.numpy().dtype),\n                default_initializer=paddle.nn.initializer.Assign(self.bias))\n\n        # mask of kernel\n        kernel_mask0 = paddle.zeros([self.wshare, int(kernel_size / 2)])\n        kernel_mask1 = paddle.ones([self.wshare, int(kernel_size / 2 + 1)])\n        self.kernel_mask = paddle.concat(\n            (kernel_mask1, kernel_mask0), axis=-1).unsqueeze(1)\n\n    def forward(self, query, key, value, mask):\n        \"\"\"Forward of 'Lightweight Convolution'.\n\n        This function takes query, key and value but uses only query.\n        This is just for compatibility with self-attention layer (attention.py)\n\n        Args:\n            query (Tensor): \n                input tensor. (batch, time1, d_model)\n            key (Tensor): \n                NOT USED. (batch, time2, d_model)  \n            value (Tensor): \n                NOT USED. (batch, time2, d_model) \n            mask : (Tensor):\n                (batch, time1, time2) mask\n\n        Return:\n            Tensor: output. (batch, time1, d_model) \n\n        \"\"\"\n        # linear -> GLU -> lightconv -> linear\n        x = query\n        B, T, C = x.shape\n        H = self.wshare\n\n        # first liner layer\n        x = self.linear1(x)\n\n        # GLU activation\n        x = self.act(x)\n\n        # lightconv\n        # B x C x T\n        x = x.transpose([0, 2, 1]).reshape([-1, H, T])\n        weight = F.dropout(\n            self.weight, self.dropout_rate, training=self.training)\n        if self.use_kernel_mask:\n            weight = masked_fill(weight, self.kernel_mask == 0.0, float(\"-inf\"))\n            # weight = weight.masked_fill(self.kernel_mask == 0.0, float(\"-inf\"))\n        weight = F.softmax(weight, axis=-1)\n        x = F.conv1d(\n            x, weight, padding=self.padding_size,\n            groups=self.wshare).reshape([B, C, T])\n        if self.use_bias:\n            x = x + self.bias.reshape([1, -1, 1])\n        # B x T x C\n        x = x.transpose([0, 2, 1])\n\n        if mask is not None and not self.use_kernel_mask:\n            mask = mask.transpose([0, 2, 1])\n            # x = x.masked_fill(mask == 0, 0.0)\n            x = masked_fill(x, mask == 0, 0.0)\n\n        # second linear layer\n        x = self.linear2(x)\n        return x\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/mask.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Mask module.\"\"\"\nimport paddle\n\n\ndef subsequent_mask(size, dtype=paddle.bool):\n    \"\"\"Create mask for subsequent steps (size, size).\n\n    Args:\n        size (int): \n            size of mask\n        dtype (paddle.dtype): \n            result dtype\n    \bReturn:\n        Tensor:\n            >>> subsequent_mask(3)\n            [[1, 0, 0],\n            [1, 1, 0],\n            [1, 1, 1]]\n    \"\"\"\n    ret = paddle.ones([size, size], dtype=dtype)\n    return paddle.tril(ret)\n\n\ndef target_mask(ys_in_pad, ignore_id, dtype=paddle.bool):\n    \"\"\"Create mask for decoder self-attention.\n\n    Args:\n        ys_pad (Tensor): \n            batch of padded target sequences (B, Lmax)\n        ignore_id (int): \n            index of padding\n        dtype (paddle.dtype): \n            result dtype\n    Return: \n        Tensor: (B, Lmax, Lmax)\n    \"\"\"\n    ys_mask = ys_in_pad != ignore_id\n    m = subsequent_mask(ys_mask.shape[-1]).unsqueeze(0)\n    return ys_mask.unsqueeze(-2) & m\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/multi_layer_conv.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Layer modules for FFT block in FastSpeech (Feed-forward Transformer).\"\"\"\nfrom paddle import nn\n\n\nclass MultiLayeredConv1d(nn.Layer):\n    \"\"\"Multi-layered conv1d for Transformer block.\n\n    This is a module of multi-leyered conv1d designed\n    to replace positionwise feed-forward network\n    in Transforner block, which is introduced in\n    `FastSpeech: Fast, Robust and Controllable Text to Speech`_.\n\n    .. _`FastSpeech: Fast, Robust and Controllable Text to Speech`:\n        https://arxiv.org/pdf/1905.09263.pdf\n\n    \"\"\"\n\n    def __init__(self, in_chans, hidden_chans, kernel_size, dropout_rate):\n        \"\"\"Initialize MultiLayeredConv1d module.\n\n        Args: \n            in_chans (int): \n                Number of input channels.\n            hidden_chans (int): \n                Number of hidden channels.\n            kernel_size (int): \n                Kernel size of conv1d.\n            dropout_rate (float): \n                Dropout rate.\n\n        \"\"\"\n        super().__init__()\n        self.w_1 = nn.Conv1D(\n            in_chans,\n            hidden_chans,\n            kernel_size,\n            stride=1,\n            padding=(kernel_size - 1) // 2, )\n        self.w_2 = nn.Conv1D(\n            hidden_chans,\n            in_chans,\n            kernel_size,\n            stride=1,\n            padding=(kernel_size - 1) // 2, )\n        self.dropout = nn.Dropout(dropout_rate)\n        self.relu = nn.ReLU()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Batch of input tensors (B, T, in_chans).\n\n        Returns: \n            Tensor: Batch of output tensors (B, T, in_chans).\n        \"\"\"\n        x = self.relu(self.w_1(x.transpose([0, 2, 1]))).transpose([0, 2, 1])\n        out = self.w_2(self.dropout(x).transpose([0, 2, 1])).transpose([0, 2, 1])\n        return out\n\n\nclass Conv1dLinear(nn.Layer):\n    \"\"\"Conv1D + Linear for Transformer block.\n\n    A variant of MultiLayeredConv1d, which replaces second conv-layer to linear.\n\n    \"\"\"\n\n    def __init__(self, in_chans, hidden_chans, kernel_size, dropout_rate):\n        \"\"\"Initialize Conv1dLinear module.\n\n        Args:\n            in_chans (int): \n                Number of input channels.\n            hidden_chans (int): \n                Number of hidden channels.\n            kernel_size (int): \n                Kernel size of conv1d.\n            dropout_rate (float):\n                Dropout rate.\n        \"\"\"\n        super().__init__()\n        self.w_1 = nn.Conv1D(\n            in_chans,\n            hidden_chans,\n            kernel_size,\n            stride=1,\n            padding=(kernel_size - 1) // 2, )\n        self.w_2 = nn.Linear(hidden_chans, in_chans, bias_attr=True)\n        self.dropout = nn.Dropout(dropout_rate)\n        self.relu = nn.ReLU()\n\n    def forward(self, x):\n        \"\"\"Calculate forward propagation.\n\n        Args:\n            x (Tensor): \n                Batch of input tensors (B, T, in_chans).\n\n        Returns:\n            Tensor: Batch of output tensors (B, T, in_chans).\n\n        \"\"\"\n        x = self.relu(self.w_1(x.transpose([0, 2, 1]))).transpose([0, 2, 1])\n\n        return self.w_2(self.dropout(x))\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/positionwise_feed_forward.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Positionwise feed forward layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\n\n\nclass PositionwiseFeedForward(nn.Layer):\n    \"\"\"Positionwise feed forward layer.\n\n    Args:\n        idim (int): \n            Input dimenstion.\n        hidden_units (int): \n            The number of hidden units.\n        dropout_rate (float): \n            Dropout rate.\n    \"\"\"\n\n    def __init__(self,\n                 idim,\n                 hidden_units,\n                 dropout_rate,\n                 activation=paddle.nn.ReLU()):\n        \"\"\"Construct an PositionwiseFeedForward object.\"\"\"\n        super().__init__()\n        self.w_1 = paddle.nn.Linear(idim, hidden_units, bias_attr=True)\n        self.w_2 = paddle.nn.Linear(hidden_units, idim, bias_attr=True)\n        self.dropout = paddle.nn.Dropout(dropout_rate)\n        self.activation = activation\n\n    def forward(self, x):\n        \"\"\"Forward funciton.\"\"\"\n        return self.w_2(self.dropout(self.activation(self.w_1(x))))\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/repeat.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Repeat the same layer definition.\"\"\"\nimport paddle\n\n\nclass MultiSequential(paddle.nn.Sequential):\n    \"\"\"Multi-input multi-output paddle.nn.Sequential.\"\"\"\n\n    def forward(self, *args):\n        \"\"\"Repeat.\"\"\"\n        for m in self:\n            args = m(*args)\n        return args\n\n\ndef repeat(N, fn):\n    \"\"\"Repeat module N times.\n\n    Args:\n        N (int): \n            Number of repeat time.\n        fn (Callable): \n            Function to generate module.\n\n    Returns:\n        MultiSequential: Repeated model instance.\n    \"\"\"\n    return MultiSequential(* [fn(n) for n in range(N)])\n"
  },
  {
    "path": "paddlespeech/t2s/modules/transformer/subsampling.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\n\"\"\"Subsampling layer definition.\"\"\"\nimport paddle\nfrom paddle import nn\n\nfrom paddlespeech.t2s.modules.transformer.embedding import PositionalEncoding\n\n\nclass Conv2dSubsampling(nn.Layer):\n    \"\"\"Convolutional 2D subsampling (to 1/4 length).\n\n    Args:\n        idim (int): \n            Input dimension.\n        odim (int): \n            Output dimension.\n        dropout_rate (float): \n            Dropout rate.\n        pos_enc (nn.Layer): \n            Custom position encoding layer.\n    \"\"\"\n\n    def __init__(self, idim, odim, dropout_rate, pos_enc=None):\n        \"\"\"Construct an Conv2dSubsampling object.\"\"\"\n        super().__init__()\n        self.conv = nn.Sequential(\n            nn.Conv2D(1, odim, 3, 2),\n            nn.ReLU(),\n            nn.Conv2D(odim, odim, 3, 2),\n            nn.ReLU(), )\n        self.out = nn.Sequential(\n            nn.Linear(odim * (((idim - 1) // 2 - 1) // 2), odim),\n            pos_enc if pos_enc is not None else\n            PositionalEncoding(odim, dropout_rate), )\n\n    def forward(self, x, x_mask):\n        \"\"\"Subsample x.\n        Args:\n            x (Tensor): \n                Input tensor (#batch, time, idim).\n            x_mask (Tensor): \n                Input mask (#batch, 1, time).\n        Returns:\n            Tensor: \n                Subsampled tensor (#batch, time', odim), where time' = time // 4.\n            Tensor: \n                Subsampled mask (#batch, 1, time'), where time' = time // 4.\n        \"\"\"\n        # (b, c, t, f)\n        x = x.unsqueeze(1)\n        x = self.conv(x)\n        b, c, t, f = paddle.shape(x)\n        x = self.out(x.transpose([0, 2, 1, 3]).reshape([b, t, c * f]))\n        if x_mask is None:\n            return x, None\n        return x, x_mask[:, :, :-2:2][:, :, :-2:2]\n\n    def __getitem__(self, key):\n        \"\"\"Get item.\n        When reset_parameters() is called, if use_scaled_pos_enc is used,\n            return the positioning encoding.\n        \"\"\"\n        if key != -1:\n            raise NotImplementedError(\n                \"Support only `-1` (for `reset_parameters`).\")\n        return self.out[key]\n"
  },
  {
    "path": "paddlespeech/t2s/modules/upsample.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nfrom paddle import nn\nfrom paddle.nn import functional as F\n\nfrom paddlespeech.t2s.modules.activation import get_activation\n\n\nclass Stretch2D(nn.Layer):\n    def __init__(self, w_scale: int, h_scale: int, mode: str=\"nearest\"):\n        \"\"\"Strech an image (or image-like object) with some interpolation.\n\n        Args:\n            w_scale (int): \n                Scalar of width.\n            h_scale (int): \n                Scalar of the height.\n            mode (str, optional): \n                Interpolation mode, modes suppored are \"nearest\", \"bilinear\", \n                \"trilinear\", \"bicubic\", \"linear\" and \"area\",by default \"nearest\"\n        For more details about interpolation, see \n            `paddle.nn.functional.interpolate <https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/nn/functional/interpolate_en.html>`_.\n        \"\"\"\n        super().__init__()\n        self.w_scale = w_scale\n        self.h_scale = h_scale\n        self.mode = mode\n\n    def forward(self, x):\n        \"\"\"\n\n        Args: \n            x (Tensor): \n                Shape (N, C, H, W)\n\n        Returns:\n            Tensor: \n                The stretched image. Shape (N, C, H', W'), where ``H'=h_scale * H``, ``W'=w_scale * W``.\n            \n        \"\"\"\n        out = F.interpolate(\n            x, scale_factor=(self.h_scale, self.w_scale), mode=self.mode)\n        return out\n\n\nclass UpsampleNet(nn.Layer):\n    \"\"\"A Layer to upsample spectrogram by applying consecutive stretch and\n    convolutions.\n\n    Args:\n        upsample_scales (List[int]): \n            Upsampling factors for each strech.\n        nonlinear_activation (Optional[str], optional): \n            Activation after each convolution, by default None\n        nonlinear_activation_params (Dict[str, Any], optional): \n            Parameters passed to construct the activation, by default {}\n        interpolate_mode (str, optional): \n            Interpolation mode of the strech, by default \"nearest\"\n        freq_axis_kernel_size (int, optional): \n            Convolution kernel size along the frequency axis, by default 1\n        use_causal_conv (bool, optional): \n            Whether to use causal padding before convolution, by default False\n            If True, Causal padding is used along the time axis, \n            i.e. padding amount is ``receptive field - 1`` and 0 for before and after, respectively.\n            If False, \"same\" padding is used along the time axis.\n    \"\"\"\n\n    def __init__(self,\n                 upsample_scales: List[int],\n                 nonlinear_activation: Optional[str]=None,\n                 nonlinear_activation_params: Dict[str, Any]={},\n                 interpolate_mode: str=\"nearest\",\n                 freq_axis_kernel_size: int=1,\n                 use_causal_conv: bool=False):\n        super().__init__()\n        self.use_causal_conv = use_causal_conv\n        self.up_layers = nn.LayerList()\n\n        for scale in upsample_scales:\n            stretch = Stretch2D(scale, 1, interpolate_mode)\n            assert freq_axis_kernel_size % 2 == 1\n            freq_axis_padding = (freq_axis_kernel_size - 1) // 2\n            kernel_size = (freq_axis_kernel_size, scale * 2 + 1)\n            if use_causal_conv:\n                padding = (freq_axis_padding, scale * 2)\n            else:\n                padding = (freq_axis_padding, scale)\n            conv = nn.Conv2D(\n                1, 1, kernel_size, padding=padding, bias_attr=False)\n            self.up_layers.extend([stretch, conv])\n            if nonlinear_activation is not None:\n                # for compatibility\n                nonlinear_activation = nonlinear_activation.lower()\n\n                nonlinear = get_activation(nonlinear_activation,\n                                           **nonlinear_activation_params)\n                self.up_layers.append(nonlinear)\n\n    def forward(self, c):\n        \"\"\"\n        Args:\n            c (Tensor): \n                spectrogram. Shape (N, F, T)\n\n        Returns: \n            Tensor: upsampled spectrogram.\n                Shape (N, F, T'), where ``T' = upsample_factor * T``, \n        \"\"\"\n        c = c.unsqueeze(1)\n        for f in self.up_layers:\n            if self.use_causal_conv and isinstance(f, nn.Conv2D):\n                c = f(c)[:, :, :, c.shape[-1]]\n            else:\n                c = f(c)\n        return c.squeeze(1)\n\n\nclass ConvInUpsampleNet(nn.Layer):\n    \"\"\"A Layer to upsample spectrogram composed of a convolution and an \n    UpsampleNet.\n    \n    Args:\n        upsample_scales (List[int]): \n            Upsampling factors for each strech.\n        nonlinear_activation (Optional[str], optional): \n            Activation after each convolution, by default None\n        nonlinear_activation_params (Dict[str, Any], optional): \n            Parameters passed to construct the activation, by default {}\n        interpolate_mode (str, optional): \n            Interpolation mode of the strech, by default \"nearest\"\n        freq_axis_kernel_size (int, optional): \n            Convolution kernel size along the frequency axis, by default 1\n        aux_channels (int, optional): \n            Feature size of the input, by default 80\n        aux_context_window (int, optional): \n            Context window of the first 1D convolution applied to the input. It \n            related to the kernel size of the convolution, by default 0\n            If use causal convolution, the kernel size is ``window + 1``, \n            else the kernel size is ``2 * window + 1``.\n        use_causal_conv (bool, optional):\n            Whether to use causal padding before convolution, by default False\n            If True, Causal padding is used along the time axis, i.e. padding \n            amount is ``receptive field - 1`` and 0 for before and after, respectively.\n            If False, \"same\" padding is used along the time axis.\n    \"\"\"\n\n    def __init__(self,\n                 upsample_scales: List[int],\n                 nonlinear_activation: Optional[str]=None,\n                 nonlinear_activation_params: Dict[str, Any]={},\n                 interpolate_mode: str=\"nearest\",\n                 freq_axis_kernel_size: int=1,\n                 aux_channels: int=80,\n                 aux_context_window: int=0,\n                 use_causal_conv: bool=False):\n        super().__init__()\n        self.aux_context_window = aux_context_window\n        self.use_causal_conv = use_causal_conv and aux_context_window > 0\n        kernel_size = aux_context_window + 1 if use_causal_conv else 2 * aux_context_window + 1\n        self.conv_in = nn.Conv1D(\n            aux_channels,\n            aux_channels,\n            kernel_size=kernel_size,\n            bias_attr=False)\n        self.upsample = UpsampleNet(\n            upsample_scales=upsample_scales,\n            nonlinear_activation=nonlinear_activation,\n            nonlinear_activation_params=nonlinear_activation_params,\n            interpolate_mode=interpolate_mode,\n            freq_axis_kernel_size=freq_axis_kernel_size,\n            use_causal_conv=use_causal_conv)\n\n    def forward(self, c):\n        \"\"\"\n        Args:\n            c (Tensor): \n                spectrogram. Shape (N, F, T)\n\n        Returns:\n            Tensors: upsampled spectrogram. Shape (N, F, T'), where ``T' = upsample_factor * T``, \n        \"\"\"\n        c_ = self.conv_in(c)\n        c = c_[:, :, :-self.aux_context_window] if self.use_causal_conv else c_\n        return self.upsample(c)\n"
  },
  {
    "path": "paddlespeech/t2s/modules/wavenet_denoiser.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport paddle\nfrom paddle import nn\nfrom ppdiffusers.models.embeddings import Timesteps\n\nfrom paddlespeech.t2s.modules.nets_utils import initialize\nfrom paddlespeech.t2s.modules.residual_block import WaveNetResidualBlock\n\n\nclass WaveNetDenoiser(nn.Layer):\n    \"\"\"A Mel-Spectrogram Denoiser modified from WaveNet\n\n    Args:\n        in_channels (int, optional): \n            Number of channels of the input mel-spectrogram, by default 80\n        out_channels (int, optional): \n            Number of channels of the output mel-spectrogram, by default 80\n        kernel_size (int, optional): \n            Kernel size of the residual blocks inside, by default 3\n        layers (int, optional): \n            Number of residual blocks inside, by default 20\n        stacks (int, optional):\n            The number of groups to split the residual blocks into, by default 5\n            Within each group, the dilation of the residual block grows exponentially.\n        residual_channels (int, optional): \n            Residual channel of the residual blocks, by default 256\n        gate_channels (int, optional): \n            Gate channel of the residual blocks, by default 512\n        skip_channels (int, optional): \n            Skip channel of the residual blocks, by default 256\n        aux_channels (int, optional): \n            Auxiliary channel of the residual blocks, by default 256\n        dropout (float, optional): \n            Dropout of the residual blocks, by default 0.\n        bias (bool, optional): \n            Whether to use bias in residual blocks, by default True\n        use_weight_norm (bool, optional): \n            Whether to use weight norm in all convolutions, by default False\n    \"\"\"\n\n    def __init__(\n            self,\n            in_channels: int=80,\n            out_channels: int=80,\n            kernel_size: int=3,\n            layers: int=20,\n            stacks: int=5,\n            residual_channels: int=256,\n            gate_channels: int=512,\n            skip_channels: int=256,\n            aux_channels: int=256,\n            dropout: float=0.,\n            bias: bool=True,\n            use_weight_norm: bool=False,\n            init_type: str=\"kaiming_normal\", ):\n        super().__init__()\n\n        # initialize parameters\n        initialize(self, init_type)\n\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.aux_channels = aux_channels\n        self.layers = layers\n        self.stacks = stacks\n        self.kernel_size = kernel_size\n\n        assert layers % stacks == 0\n        layers_per_stack = layers // stacks\n\n        self.first_t_emb = nn.Sequential(\n            Timesteps(\n                residual_channels,\n                flip_sin_to_cos=False,\n                downscale_freq_shift=1),\n            nn.Linear(residual_channels, residual_channels * 4),\n            nn.Mish(), nn.Linear(residual_channels * 4, residual_channels))\n        self.t_emb_layers = nn.LayerList([\n            nn.Linear(residual_channels, residual_channels)\n            for _ in range(layers)\n        ])\n\n        self.first_conv = nn.Conv1D(\n            in_channels, residual_channels, 1, bias_attr=True)\n        self.first_act = nn.ReLU()\n\n        self.conv_layers = nn.LayerList()\n        for layer in range(layers):\n            dilation = 2**(layer % layers_per_stack)\n            conv = WaveNetResidualBlock(\n                kernel_size=kernel_size,\n                residual_channels=residual_channels,\n                gate_channels=gate_channels,\n                skip_channels=skip_channels,\n                aux_channels=aux_channels,\n                dilation=dilation,\n                dropout=dropout,\n                bias=bias)\n            self.conv_layers.append(conv)\n\n        final_conv = nn.Conv1D(skip_channels, out_channels, 1, bias_attr=True)\n        nn.initializer.Constant(0.0)(final_conv.weight)\n        self.last_conv_layers = nn.Sequential(nn.ReLU(),\n                                              nn.Conv1D(\n                                                  skip_channels,\n                                                  skip_channels,\n                                                  1,\n                                                  bias_attr=True),\n                                              nn.ReLU(), final_conv)\n\n        if use_weight_norm:\n            self.apply_weight_norm()\n\n    def forward(self, x: paddle.Tensor, t: paddle.Tensor, c: paddle.Tensor):\n        \"\"\"Denoise mel-spectrogram.\n\n        Args:\n            x(Tensor): \n                Shape (B, C_in, T), The input mel-spectrogram.\n            t(Tensor): \n                Shape (B), The timestep input.\n            c(Tensor): \n                Shape (B, C_aux, T'). The auxiliary input (e.g. fastspeech2 encoder output).\n\n        Returns:\n            Tensor: Shape (B, C_out, T), the pred noise.\n        \"\"\"\n        assert c.shape[-1] == x.shape[-1]\n\n        if t.shape[0] != x.shape[0]:\n            t = t.tile([x.shape[0]])\n        t_emb = self.first_t_emb(t)\n        t_embs = [\n            t_emb_layer(t_emb)[..., None] for t_emb_layer in self.t_emb_layers\n        ]\n\n        x = self.first_conv(x)\n        x = self.first_act(x)\n        skips = 0\n        for f, t in zip(self.conv_layers, t_embs):\n            x = x + t\n            x, s = f(x, c)\n            skips += s\n        skips *= math.sqrt(1.0 / len(self.conv_layers))\n\n        x = self.last_conv_layers(skips)\n        return x\n\n    def apply_weight_norm(self):\n        \"\"\"Recursively apply weight normalization to all the Convolution layers\n        in the sublayers.\n        \"\"\"\n\n        def _apply_weight_norm(layer):\n            if isinstance(layer, (nn.Conv1D, nn.Conv2D)):\n                nn.utils.weight_norm(layer)\n\n        self.apply(_apply_weight_norm)\n\n    def remove_weight_norm(self):\n        \"\"\"Recursively remove weight normalization from all the Convolution \n        layers in the sublayers.\n        \"\"\"\n\n        def _remove_weight_norm(layer):\n            try:\n                nn.utils.remove_weight_norm(layer)\n            except ValueError:\n                pass\n\n        self.apply(_remove_weight_norm)\n"
  },
  {
    "path": "paddlespeech/t2s/training/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .cli import *\nfrom .experiment import *\n"
  },
  {
    "path": "paddlespeech/t2s/training/cli.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\n\ndef default_argument_parser():\n    r\"\"\"A simple yet genral argument parser for experiments with t2s.\n    \n    This is used in examples with t2s. And it is intended to be used by \n    other experiments with t2s. It requires a minimal set of command line \n    arguments to start a training script.\n    \n    The ``--config`` and ``--opts`` are used for overwrite the default \n    configuration.\n    \n    The ``--data`` and ``--output`` specifies the data path and output path. \n    Resuming training from existing progress at the output directory is the \n    intended default behavior.\n    \n    The ``--checkpoint_path`` specifies the checkpoint to load from.\n    \n    The ``--ngpu`` specifies how to run the training.\n    \n    See Also\n    --------\n    paddlespeech.t2s.training.experiment\n\n    Returns\n    -------\n    argparse.ArgumentParser\n        the parser\n    \"\"\"\n    parser = argparse.ArgumentParser()\n\n    # yapf: disable\n    # data and outpu\n    parser.add_argument(\"--config\", metavar=\"FILE\", help=\"path of the config file to overwrite to default config with.\")\n    parser.add_argument(\"--data\", metavar=\"DATA_DIR\", help=\"path to the datatset.\")\n    parser.add_argument(\"--output\", metavar=\"OUTPUT_DIR\", help=\"path to save checkpoint and logs.\")\n\n    # load from saved checkpoint\n    parser.add_argument(\"--checkpoint_path\", type=str, help=\"path of the checkpoint to load\")\n\n    # running\n    parser.add_argument(\"--ngpu\", type=int, default=1, help=\"if ngpu == 0, use cpu.\")\n\n    # overwrite extra config and default config\n    parser.add_argument(\"--opts\", nargs=argparse.REMAINDER, help=\"options to overwrite --config file and the default config, passing in KEY VALUE pairs\")\n    # yapd: enable\n\n    return parser\n"
  },
  {
    "path": "paddlespeech/t2s/training/default_config.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom yacs.config import CfgNode\n\n_C = CfgNode(\n    dict(\n        valid_interval=1000,  # validation\n        save_interval=10000,  # checkpoint\n        max_iteration=900000,  # max iteration to train\n    ))\n\n\ndef get_default_training_config():\n    return _C.clone()\n"
  },
  {
    "path": "paddlespeech/t2s/training/experiment.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nimport sys\nfrom pathlib import Path\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DistributedBatchSampler\nfrom visualdl import LogWriter\n\nfrom paddlespeech.t2s.utils import checkpoint\nfrom paddlespeech.t2s.utils import mp_tools\n\n__all__ = [\"ExperimentBase\"]\n\n\nclass ExperimentBase(object):\n    \"\"\"\n    An experiment template in order to structure the training code and take\n    care of saving, loading, logging, visualization stuffs. It's intended to\n    be flexible and simple.\n\n    So it only handles output directory (create directory for the output,\n    create a checkpoint directory, dump the config in use and create\n    visualizer and logger) in a standard way without enforcing any\n    input-output protocols to the model and dataloader. It leaves the main\n    part for the user to implement their own (setup the model, criterion,\n    optimizer, define a training step, define a validation function and\n    customize all the text and visual logs).\n\n    It does not save too much boilerplate code. The users still have to write\n    the forward/backward/update mannually, but they are free to add\n    non-standard behaviors if needed.\n\n    We have some conventions to follow.\n    1. Experiment should have ``model``, ``optimizer``, ``train_loader`` and\n    ``valid_loader``, ``config`` and ``args`` attributes.\n    2. The config should have a ``training`` field, which has\n    ``valid_interval``, ``save_interval`` and ``max_iteration`` keys. It is\n    used as the trigger to invoke validation, checkpointing and stop of the\n    experiment.\n    3. There are four methods, namely ``train_batch``, ``valid``,\n    ``setup_model`` and ``setup_dataloader`` that should be implemented.\n\n    Feel free to add/overwrite other methods and standalone functions if you\n    need.\n\n    Args:\n        config (yacs.config.CfgNode): \n            The configuration used for the experiment.\n        args (argparse.Namespace): \n            The parsed command line arguments.\n\n    Examples:\n        >>> def main_sp(config, args):\n        >>>     exp = Experiment(config, args)\n        >>>     exp.setup()\n        >>>     exe.resume_or_load()\n        >>>     exp.run()\n        >>>\n        >>> config = get_cfg_defaults()\n        >>> parser = default_argument_parser()\n        >>> args = parser.parse_args()\n        >>> if args.config:\n        >>>     config.merge_from_file(args.config)\n        >>> if args.opts:\n        >>>     config.merge_from_list(args.opts)\n        >>> config.freeze()\n        >>>\n        >>> if args.ngpu > 1:\n        >>>     dist.spawn(main_sp, args=(config, args), nprocs=args.ngpu)\n        >>> else:\n        >>>     main_sp(config, args)\n    \"\"\"\n\n    def __init__(self, config, args):\n        self.config = config\n        self.args = args\n\n        self.model = None\n        self.optimizer = None\n        self.iteration = 0\n        self.epoch = 0\n        self.train_loader = None\n        self.valid_loader = None\n        self.iterator = None\n        self.logger = None\n        self.visualizer = None\n        self.output_dir = None\n        self.checkpoint_dir = None\n\n    def setup(self):\n        \"\"\"Setup the experiment.\n        \"\"\"\n        if self.args.ngpu == 0:\n            paddle.set_device(\"cpu\")\n        elif self.args.ngpu > 0:\n            paddle.set_device(\"gpu\")\n        else:\n            print(\"ngpu should >= 0 !\")\n        if self.parallel:\n            self.init_parallel()\n\n        self.setup_output_dir()\n        self.dump_config()\n        self.setup_visualizer()\n        self.setup_logger()\n        self.setup_checkpointer()\n\n        self.setup_dataloader()\n        self.setup_model()\n\n        self.iteration = 0\n        self.epoch = 0\n\n    @property\n    def parallel(self):\n        \"\"\"A flag indicating whether the experiment should run with\n        multiprocessing.\n        \"\"\"\n        return self.args.ngpu > 1\n\n    def init_parallel(self):\n        \"\"\"Init environment for multiprocess training.\n        \"\"\"\n        dist.init_parallel_env()\n\n    @mp_tools.rank_zero_only\n    def save(self):\n        \"\"\"Save checkpoint (model parameters and optimizer states).\n        \"\"\"\n        checkpoint.save_parameters(self.checkpoint_dir, self.iteration,\n                                   self.model, self.optimizer)\n\n    def resume_or_load(self):\n        \"\"\"Resume from latest checkpoint at checkpoints in the output\n        directory or load a specified checkpoint.\n\n        If ``args.checkpoint_path`` is not None, load the checkpoint, else\n        resume training.\n        \"\"\"\n        iteration = checkpoint.load_parameters(\n            self.model,\n            self.optimizer,\n            checkpoint_dir=self.checkpoint_dir,\n            checkpoint_path=self.args.checkpoint_path)\n        self.iteration = iteration\n\n    def read_batch(self):\n        \"\"\"Read a batch from the train_loader.\n\n        Returns\n        -------\n        List[Tensor]\n            A batch.\n        \"\"\"\n        try:\n            batch = next(self.iterator)\n        except StopIteration:\n            self.new_epoch()\n            batch = next(self.iterator)\n        return batch\n\n    def new_epoch(self):\n        \"\"\"Reset the train loader and increment ``epoch``.\n        \"\"\"\n        self.epoch += 1\n        if self.parallel and isinstance(self.train_loader.batch_sampler,\n                                        DistributedBatchSampler):\n            self.train_loader.batch_sampler.set_epoch(self.epoch)\n        self.iterator = iter(self.train_loader)\n\n    def train(self):\n        \"\"\"The training process.\n\n        It includes forward/backward/update and periodical validation and\n        saving.\n        \"\"\"\n        self.new_epoch()\n        while self.iteration < self.config.training.max_iteration:\n            self.iteration += 1\n            self.train_batch()\n\n            if self.iteration % self.config.training.valid_interval == 0:\n                self.valid()\n\n            if self.iteration % self.config.training.save_interval == 0:\n                self.save()\n\n    def run(self):\n        \"\"\"The routine of the experiment after setup. This method is intended\n        to be used by the user.\n        \"\"\"\n        try:\n            self.train()\n        except KeyboardInterrupt as exception:\n            # delete this, because it can not save a complete model\n            # self.save()\n            self.close()\n            sys.exit(exception)\n        finally:\n            self.close()\n\n    def setup_output_dir(self):\n        \"\"\"Create a directory used for output.\n        \"\"\"\n        # output dir\n        output_dir = Path(self.args.output).expanduser()\n        output_dir.mkdir(parents=True, exist_ok=True)\n\n        self.output_dir = output_dir\n\n    def setup_checkpointer(self):\n        \"\"\"Create a directory used to save checkpoints into.\n\n        It is \"checkpoints\" inside the output directory.\n        \"\"\"\n        # checkpoint dir\n        checkpoint_dir = self.output_dir / \"checkpoints\"\n        checkpoint_dir.mkdir(exist_ok=True)\n\n        self.checkpoint_dir = checkpoint_dir\n\n    @mp_tools.rank_zero_only\n    def close(self):\n        \"\"\"Close visualizer to avoid hanging after training\"\"\"\n        # https://github.com/pytorch/fairseq/issues/2357\n        self.visualizer.close()\n\n    @mp_tools.rank_zero_only\n    def setup_visualizer(self):\n        \"\"\"Initialize a visualizer to log the experiment.\n\n        The visual log is saved in the output directory.\n\n        Notes\n        ------\n        Only the main process has a visualizer with it. Use multiple\n        visualizers in multiprocess to write to a same log file may cause\n        unexpected behaviors.\n        \"\"\"\n        # visualizer\n        visualizer = LogWriter(logdir=str(self.output_dir))\n\n        self.visualizer = visualizer\n\n    def setup_logger(self):\n        \"\"\"Initialize a text logger to log the experiment.\n\n        Each process has its own text logger. The logging message is write to\n        the standard output and a text file named ``worker_n.log`` in the\n        output directory, where ``n`` means the rank of the process.\n        \"\"\"\n        logger = logging.getLogger(__name__)\n        logger.setLevel(\"INFO\")\n        log_file = self.output_dir / 'worker_{}.log'.format(dist.get_rank())\n        logger.addHandler(logging.FileHandler(str(log_file)))\n\n        self.logger = logger\n\n    @mp_tools.rank_zero_only\n    def dump_config(self):\n        \"\"\"Save the configuration used for this experiment.\n\n        It is saved in to ``config.yaml`` in the output directory at the\n        beginning of the experiment.\n        \"\"\"\n        with open(self.output_dir / \"config.yaml\", 'wt') as f:\n            print(self.config, file=f)\n\n    def train_batch(self):\n        \"\"\"The training loop. A subclass should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"train_batch should be implemented.\")\n\n    @mp_tools.rank_zero_only\n    @paddle.no_grad()\n    def valid(self):\n        \"\"\"The validation. A subclass should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"valid should be implemented.\")\n\n    def setup_model(self):\n        \"\"\"Setup model, criterion and optimizer, etc. A subclass should\n        implement this method.\n        \"\"\"\n        raise NotImplementedError(\"setup_model should be implemented.\")\n\n    def setup_dataloader(self):\n        \"\"\"Setup training dataloader and validation dataloader. A subclass\n        should implement this method.\n        \"\"\"\n        raise NotImplementedError(\"setup_dataloader should be implemented.\")\n"
  },
  {
    "path": "paddlespeech/t2s/training/extension.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom typing import Callable\n\nPRIORITY_WRITER = 300\nPRIORITY_EDITOR = 200\nPRIORITY_READER = 100\n\n\nclass Extension(object):\n    \"\"\"Extension to customize the behavior of Trainer.\"\"\"\n    trigger = (1, 'iteration')\n    priority = PRIORITY_READER\n    name = None\n\n    @property\n    def default_name(self):\n        \"\"\"Default name of the extension, class name by default.\"\"\"\n        return type(self).__name__\n\n    def __call__(self, trainer):\n        \"\"\"Main action of the extention. After each update, it is executed\n        when the trigger fires.\"\"\"\n        raise NotImplementedError(\n            'Extension implementation must override __call__.')\n\n    def initialize(self, trainer):\n        \"\"\"Action that is executed once to get the corect trainer state.\n        It is called before training normally, but if the trainer restores\n        states with an Snapshot extension, this method should also be called.g\n        \"\"\"\n        pass\n\n    def on_error(self, trainer, exc, tb):\n        \"\"\"Handles the error raised during training before finalization.\n        \"\"\"\n        pass\n\n    def finalize(self, trainer):\n        \"\"\"Action that is executed when training is done.\n        For example, visualizers would need to be closed.\n        \"\"\"\n        pass\n\n\ndef make_extension(trigger: Callable=None,\n                   default_name: str=None,\n                   priority: int=None,\n                   finalizer: Callable=None,\n                   initializer: Callable=None,\n                   on_error: Callable=None):\n    \"\"\"Make an Extension-like object by injecting required attributes to it.\n    \"\"\"\n    if trigger is None:\n        trigger = Extension.trigger\n    if priority is None:\n        priority = Extension.priority\n\n    def decorator(ext):\n        ext.trigger = trigger\n        ext.default_name = default_name or ext.__name__\n        ext.priority = priority\n        ext.finalize = finalizer\n        ext.on_error = on_error\n        ext.initialize = initializer\n        return ext\n\n    return decorator\n"
  },
  {
    "path": "paddlespeech/t2s/training/extensions/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/training/extensions/evaluator.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nfrom typing import Dict\n\nimport paddle\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\n\nfrom paddlespeech.t2s.training import extension\nfrom paddlespeech.t2s.training.reporter import DictSummary\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.reporter import scope\n\n\nclass StandardEvaluator(extension.Extension):\n\n    trigger = (1, 'epoch')\n    default_name = 'validation'\n    priority = extension.PRIORITY_WRITER\n\n    name = None\n\n    def __init__(self, model: Layer, dataloader: DataLoader):\n        # it is designed to hold multiple models\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        self.model = model\n\n        # dataloaders\n        self.dataloader = dataloader\n\n    def evaluate_core(self, batch):\n        # compute\n        self.model(batch)  # you may report here\n\n    def evaluate(self):\n        # switch to eval mode\n        for layer in self.models.values():\n            layer.eval()\n\n        # to average evaluation metrics\n        summary = DictSummary()\n        for batch in self.dataloader:\n            observation = {}\n            with scope(observation):\n                # main evaluation computation here.\n                with paddle.no_grad():\n                    self.evaluate_core(batch)\n            summary.add(observation)\n        summary = summary.compute_mean()\n        return summary\n\n    def __call__(self, trainer=None):\n        # evaluate and report the averaged metric to current observation\n        # if it is used to extend a trainer, the metrics is reported to\n        # to observation of the trainer\n        # or otherwise, you can use your own observation\n        summary = self.evaluate()\n        for k, v in summary.items():\n            report(k, v)\n"
  },
  {
    "path": "paddlespeech/t2s/training/extensions/snapshot.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport logging\nimport os\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\n\nimport jsonlines\n\nfrom paddlespeech.t2s.training import extension\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.t2s.utils.mp_tools import rank_zero_only\n\n\ndef load_records(records_fp):\n    \"\"\"Load record files (json lines.)\"\"\"\n    with jsonlines.open(records_fp, 'r') as reader:\n        records = list(reader)\n    return records\n\n\nclass Snapshot(extension.Extension):\n    \"\"\"An extension to make snapshot of the updater object inside\n    the trainer. It is done by calling the updater's `save` method.\n\n    An Updater save its state_dict by default, which contains the\n    updater state, (i.e. epoch and iteration) and all the model\n    parameters and optimizer states. If the updater inside the trainer\n    subclasses StandardUpdater, everything is good to go.\n\n    Arsg:\n        checkpoint_dir (Union[str, Path]): The directory to save checkpoints into.\n    \"\"\"\n\n    trigger = (1, 'epoch')\n    priority = -100\n    default_name = \"snapshot\"\n\n    def __init__(self, max_size: int=5, snapshot_on_error: bool=False):\n        self.records: List[Dict[str, Any]] = []\n        self.max_size = max_size\n        self._snapshot_on_error = snapshot_on_error\n        self._save_all = (max_size == -1)\n        self.checkpoint_dir = None\n\n    def initialize(self, trainer: Trainer):\n        \"\"\"Setting up this extention.\"\"\"\n        self.checkpoint_dir = trainer.out / \"checkpoints\"\n\n        # load existing records\n        record_path: Path = self.checkpoint_dir / \"records.jsonl\"\n        if record_path.exists():\n            logging.debug(\"Loading from an existing checkpoint dir\")\n            self.records = load_records(record_path)\n            trainer.updater.load(self.records[-1]['path'])\n\n    def on_error(self, trainer, exc, tb):\n        if self._snapshot_on_error:\n            self.save_checkpoint_and_update(trainer)\n\n    def __call__(self, trainer: Trainer):\n        self.save_checkpoint_and_update(trainer)\n\n    def full(self):\n        \"\"\"Whether the number of snapshots it keeps track of is greater\n        than the max_size.\"\"\"\n        return (not self._save_all) and len(self.records) > self.max_size\n\n    @rank_zero_only\n    def save_checkpoint_and_update(self, trainer: Trainer):\n        \"\"\"Saving new snapshot and remove the oldest snapshot if needed.\"\"\"\n        iteration = trainer.updater.state.iteration\n        path = self.checkpoint_dir / f\"snapshot_iter_{iteration}.pdz\"\n\n        # add the new one\n        trainer.updater.save(path)\n        record = {\n            \"time\": str(datetime.now()),\n            'path': str(path.resolve()),  # use absolute path\n            'iteration': iteration\n        }\n        self.records.append(record)\n\n        # remove the earist\n        if self.full():\n            eariest_record = self.records[0]\n            os.remove(eariest_record[\"path\"])\n            self.records.pop(0)\n\n        # update the record file\n        record_path = self.checkpoint_dir / \"records.jsonl\"\n        with jsonlines.open(record_path, 'w') as writer:\n            for record in self.records:\n                # jsonlines.open may return a Writer or a Reader\n                writer.write(record)  # pylint: disable=no-member\n"
  },
  {
    "path": "paddlespeech/t2s/training/extensions/visualizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom visualdl import LogWriter\n\nfrom paddlespeech.t2s.training import extension\nfrom paddlespeech.t2s.training.trainer import Trainer\n\n\nclass VisualDL(extension.Extension):\n    \"\"\"A wrapper of visualdl log writer. It assumes that the metrics to be visualized\n    are all scalars which are recorded into the `.observation` dictionary of the\n    trainer object. The dictionary is created for each step, thus the visualdl log\n    writer uses the iteration from the updater's `iteration` as the global step to\n    add records.\n    \"\"\"\n    trigger = (1, 'iteration')\n    default_name = 'visualdl'\n    priority = extension.PRIORITY_READER\n\n    def __init__(self, logdir):\n        self.writer = LogWriter(str(logdir))\n\n    def __call__(self, trainer: Trainer):\n        for k, v in trainer.observation.items():\n            self.writer.add_scalar(k, v, step=trainer.updater.state.iteration)\n\n    def finalize(self, trainer):\n        self.writer.close()\n"
  },
  {
    "path": "paddlespeech/t2s/training/optimizer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nfrom paddle import nn\n\nscheduler_classes = dict(\n    ReduceOnPlateau=paddle.optimizer.lr.ReduceOnPlateau,\n    lambda_decay=paddle.optimizer.lr.LambdaDecay,\n    step_decay=paddle.optimizer.lr.StepDecay,\n    multistep_decay=paddle.optimizer.lr.MultiStepDecay,\n    exponential_decay=paddle.optimizer.lr.ExponentialDecay,\n    CosineAnnealingDecay=paddle.optimizer.lr.CosineAnnealingDecay, )\n\noptim_classes = dict(\n    adadelta=paddle.optimizer.Adadelta,\n    adagrad=paddle.optimizer.Adagrad,\n    adam=paddle.optimizer.Adam,\n    adamax=paddle.optimizer.Adamax,\n    adamw=paddle.optimizer.AdamW,\n    lamb=paddle.optimizer.Lamb,\n    momentum=paddle.optimizer.Momentum,\n    rmsprop=paddle.optimizer.RMSProp,\n    sgd=paddle.optimizer.SGD, )\n\n\ndef build_optimizers(\n        model: nn.Layer,\n        optim='adadelta',\n        max_grad_norm=None,\n        learning_rate=0.01,\n        weight_decay=None,\n        epsilon=1.0e-6, ) -> paddle.optimizer:\n    optim_class = optim_classes.get(optim)\n    if optim_class is None:\n        raise ValueError(f\"must be one of {list(optim_classes)}: {optim}\")\n    else:\n        grad_clip = None\n        if max_grad_norm:\n            grad_clip = paddle.nn.ClipGradByGlobalNorm(max_grad_norm)\n        optim_dict = {}\n        optim_dict['parameters'] = model.parameters()\n        optim_dict['learning_rate'] = learning_rate\n        optim_dict['grad_clip'] = grad_clip\n        optim_dict['weight_decay'] = weight_decay\n        if optim_class not in {'momentum', 'sgd'}:\n            optim_dict['epsilon'] = epsilon\n        optimizers = optim_class(**optim_dict)\n\n    return optimizers\n"
  },
  {
    "path": "paddlespeech/t2s/training/reporter.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport contextlib\nimport math\nfrom collections import defaultdict\n\nOBSERVATIONS = None\n\n\n@contextlib.contextmanager\ndef scope(observations):\n    # make `observation` the target to report to.\n    # it is basically a dictionary that stores temporary observations\n    global OBSERVATIONS\n    old = OBSERVATIONS\n    OBSERVATIONS = observations\n\n    try:\n        yield\n    finally:\n        OBSERVATIONS = old\n\n\ndef get_observations():\n    global OBSERVATIONS\n    return OBSERVATIONS\n\n\ndef report(name, value):\n    # a simple function to report named value\n    # you can use it everywhere, it will get the default target and writ to it\n    # you can think of it as std.out\n    observations = get_observations()\n    if observations is None:\n        return\n    else:\n        observations[name] = value\n\n\nclass Summary(object):\n    \"\"\"Online summarization of a sequence of scalars.\n    Summary computes the statistics of given scalars online.\n    \"\"\"\n\n    def __init__(self):\n        self._x = 0.0\n        self._x2 = 0.0\n        self._n = 0\n\n    def add(self, value, weight=1):\n        \"\"\"Adds a scalar value.\n\n        Args:\n            value: Scalar value to accumulate. It is either a NumPy scalar or\n                a zero-dimensional array (on CPU or GPU).\n            weight: An optional weight for the value. It is a NumPy scalar or\n                a zero-dimensional array (on CPU or GPU).\n                Default is 1 (integer).\n\n        \"\"\"\n        self._x += weight * value\n        self._x2 += weight * value * value\n        self._n += weight\n\n    def compute_mean(self):\n        \"\"\"Computes the mean.\"\"\"\n        x, n = self._x, self._n\n        return x / n\n\n    def make_statistics(self):\n        \"\"\"Computes and returns the mean and standard deviation values.\n\n        Returns:\n            tuple: Mean and standard deviation values.\n\n        \"\"\"\n        x, n = self._x, self._n\n        mean = x / n\n        var = self._x2 / n - mean * mean\n        std = math.sqrt(var)\n        return mean, std\n\n\nclass DictSummary(object):\n    \"\"\"Online summarization of a sequence of dictionaries.\n\n    ``DictSummary`` computes the statistics of a given set of scalars online.\n    It only computes the statistics for scalar values and variables of scalar\n    values in the dictionaries.\n\n    \"\"\"\n\n    def __init__(self):\n        self._summaries = defaultdict(Summary)\n\n    def add(self, d):\n        \"\"\"Adds a dictionary of scalars.\n\n        Args:\n            d (dict): Dictionary of scalars to accumulate. Only elements of\n               scalars, zero-dimensional arrays, and variables of\n               zero-dimensional arrays are accumulated. When the value\n               is a tuple, the second element is interpreted as a weight.\n\n        \"\"\"\n        summaries = self._summaries\n        for k, v in d.items():\n            w = 1\n            if isinstance(v, tuple):\n                w = v[1]\n                v = v[0]\n            summaries[k].add(v, weight=w)\n\n    def compute_mean(self):\n        \"\"\"Creates a dictionary of mean values.\n\n        It returns a single dictionary that holds a mean value for each entry\n        added to the summary.\n\n        Returns:\n            dict: Dictionary of mean values.\n\n        \"\"\"\n        return {\n            name: summary.compute_mean()\n            for name, summary in self._summaries.items()\n        }\n\n    def make_statistics(self):\n        \"\"\"Creates a dictionary of statistics.\n\n        It returns a single dictionary that holds mean and standard deviation\n        values for every entry added to the summary. For an entry of name\n        ``'key'``, these values are added to the dictionary by names ``'key'``\n        and ``'key.std'``, respectively.\n\n        Returns:\n            dict: Dictionary of statistics of all entries.\n\n        \"\"\"\n        stats = {}\n        for name, summary in self._summaries.items():\n            mean, std = summary.make_statistics()\n            stats[name] = mean\n            stats[name + '.std'] = std\n\n        return stats\n"
  },
  {
    "path": "paddlespeech/t2s/training/seeding.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nimport random\n\nimport numpy as np\nimport paddle\n\n\ndef seed_everything(seed: int):\n    \"\"\"Seed paddle, random and np.random to help reproductivity.\"\"\"\n    paddle.seed(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    logging.debug(f\"Set the seed of paddle, random, np.random to {seed}.\")\n"
  },
  {
    "path": "paddlespeech/t2s/training/trainer.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport sys\nimport traceback\nfrom collections import OrderedDict\nfrom pathlib import Path\nfrom typing import Callable\nfrom typing import List\nfrom typing import Union\n\nimport six\nimport paddle\nfrom paddlespeech.t2s.training.extension import Extension\nfrom paddlespeech.t2s.training.extension import PRIORITY_READER\nfrom paddlespeech.t2s.training.reporter import scope\nfrom paddlespeech.t2s.training.trigger import get_trigger\nfrom paddlespeech.t2s.training.triggers.limit_trigger import LimitTrigger\nfrom paddlespeech.t2s.training.updater import UpdaterBase\nfrom paddlespeech.t2s.utils import profiler\n\n\nclass _ExtensionEntry(object):\n    def __init__(self, extension, trigger, priority):\n        self.extension = extension\n        self.trigger = trigger\n        self.priority = priority\n\n\nclass Trainer(object):\n    def __init__(self,\n                 updater: UpdaterBase,\n                 stop_trigger: Callable=None,\n                 out: Union[str, Path]='result',\n                 extensions: List[Extension]=None,\n                 profiler_options: str=None):\n        self.updater = updater\n        self.extensions = OrderedDict()\n        self.stop_trigger = LimitTrigger(*stop_trigger)\n        self.out = Path(out)\n        self.observation = None\n        self.profiler_options = profiler_options\n        self._done = False\n        if extensions:\n            for ext in extensions:\n                self.extend(ext)\n\n    @property\n    def is_before_training(self):\n        return self.updater.state.iteration == 0\n\n    def extend(self, extension, name=None, trigger=None, priority=None):\n        # get name for the extension\n        # argument \\\n        # -> extention's name \\\n        # -> default_name (class name, when it is an object) \\\n        # -> function name when it is a function \\\n        # -> error\n\n        if name is None:\n            name = getattr(extension, 'name', None)\n            if name is None:\n                name = getattr(extension, 'default_name', None)\n                if name is None:\n                    name = getattr(extension, '__name__', None)\n                    if name is None:\n                        raise ValueError(\"Name is not given for the extension.\")\n        if name == 'training':\n            raise ValueError(\"training is a reserved name.\")\n\n        if trigger is None:\n            trigger = getattr(extension, 'trigger', (1, 'iteration'))\n        trigger = get_trigger(trigger)\n\n        if priority is None:\n            priority = getattr(extension, 'priority', PRIORITY_READER)\n\n        # add suffix to avoid nameing conflict\n        ordinal = 0\n        modified_name = name\n        while modified_name in self.extensions:\n            ordinal += 1\n            modified_name = f\"{name}_{ordinal}\"\n        extension.name = modified_name\n\n        self.extensions[modified_name] = _ExtensionEntry(extension, trigger,\n                                                         priority)\n\n    def get_extension(self, name):\n        \"\"\"get extension by name.\"\"\"\n        extensions = self.extensions\n        if name in extensions:\n            return extensions[name].extension\n        else:\n            raise ValueError(f'extension {name} not found')\n\n    def run(self):\n        if self._done:\n            raise RuntimeError(\"Training is already done!.\")\n\n        self.out.mkdir(parents=True, exist_ok=True)\n\n        # sort extensions by priorities once\n        extension_order = sorted(\n            self.extensions.keys(),\n            key=lambda name: self.extensions[name].priority,\n            reverse=True)\n        extensions = [(name, self.extensions[name]) for name in extension_order]\n\n        # initializing all extensions\n        for name, entry in extensions:\n            if hasattr(entry.extension, \"initialize\"):\n                entry.extension.initialize(self)\n\n        update = self.updater.update  # training step\n\n        stop_trigger = self.stop_trigger\n\n        # display only one progress bar\n        max_iteration = None\n        if isinstance(stop_trigger, LimitTrigger):\n            if stop_trigger.unit == 'epoch':\n                max_epoch = self.stop_trigger.limit\n                updates_per_epoch = getattr(self.updater, \"updates_per_epoch\",\n                                            None)\n                max_iteration = max_epoch * updates_per_epoch if updates_per_epoch else None\n            else:\n                max_iteration = self.stop_trigger.limit\n\n        try:\n            while not stop_trigger(self):\n                self.observation = {}\n                # set observation as the report target\n                # you can use report freely in Updater.update()\n\n                # updating parameters and state\n                with scope(self.observation):\n\n                    update()\n                    if self.profiler_options:\n                        profiler.add_profiler_step(self.profiler_options)\n                    batch_read_time = self.updater.batch_read_time\n                    batch_time = self.updater.batch_time\n                    avg_batch_cost = batch_read_time + batch_time\n                    logger = self.updater.logger\n                    logger.removeHandler(self.updater.filehandler)\n                    msg = self.updater.msg\n                    msg = \" iter: {}/{}, \".format(self.updater.state.iteration,\n                                                  max_iteration) + msg\n                    msg += \", avg_reader_cost: {:.5f} sec, \".format(\n                        batch_read_time\n                    ) + \"avg_batch_cost: {:.5f} sec, \".format(avg_batch_cost)\n                    msg += \"avg_samples: {}, \".format(\n                        self.updater.\n                        batch_size) + \"avg_ips: {:.5f} sequences/sec,\".format(\n                            self.updater.batch_size / avg_batch_cost)\n                    if paddle.device.is_compiled_with_cuda():\n                        max_mem_reserved_str = f\" max_mem_reserved: {paddle.device.cuda.max_memory_reserved() // (1024 ** 2)} MB\"\n                        max_mem_allocated_str = f\" max_mem_allocated: {paddle.device.cuda.max_memory_allocated() // (1024 ** 2)} MB\"\n                        msg += max_mem_reserved_str + \",\" + max_mem_allocated_str\n\n                    logger.info(msg)\n\n                    # execute extension when necessary\n                    for name, entry in extensions:\n                        if entry.trigger(self):\n                            entry.extension(self)\n\n                # print(\"###\", self.observation)\n        except Exception as e:\n            f = sys.stderr\n            f.write(f\"Exception in main training loop: {e}\\n\")\n            f.write(\"Traceback (most recent call last):\\n\")\n            traceback.print_tb(sys.exc_info()[2])\n            f.write(\n                \"Trainer extensions will try to handle the extension. Then all extensions will finalize.\"\n            )\n\n            # capture the exception in the mian training loop\n            exc_info = sys.exc_info()\n\n            # try to handle it\n            for name, entry in extensions:\n                if hasattr(entry.extension, \"on_error\"):\n                    try:\n                        entry.extension.on_error(self, e, sys.exc_info()[2])\n                    except Exception as ee:\n                        f.write(f\"Exception in error handler: {ee}\\n\")\n                        f.write('Traceback (most recent call last):\\n')\n                        traceback.print_tb(sys.exc_info()[2])\n\n            # raise exception in main training loop\n            six.reraise(*exc_info)\n        finally:\n            for name, entry in extensions:\n                if hasattr(entry.extension, \"finalize\"):\n                    entry.extension.finalize(self)\n"
  },
  {
    "path": "paddlespeech/t2s/training/trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.t2s.training.triggers.interval_trigger import IntervalTrigger\n\n\ndef never_fail_trigger(trainer):\n    return False\n\n\ndef get_trigger(trigger):\n    if trigger is None:\n        return never_fail_trigger\n    if callable(trigger):\n        return trigger\n    else:\n        trigger = IntervalTrigger(*trigger)\n        return trigger\n"
  },
  {
    "path": "paddlespeech/t2s/training/triggers/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/training/triggers/interval_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass IntervalTrigger(object):\n    \"\"\"A Predicate to do something every N cycle.\"\"\"\n\n    def __init__(self, period: int, unit: str):\n        if unit not in (\"iteration\", \"epoch\"):\n            raise ValueError(\"unit should be 'iteration' or 'epoch'\")\n        if period <= 0:\n            raise ValueError(\"period should be a positive integer.\")\n        self.period = period\n        self.unit = unit\n        self.last_index = None\n\n    def __call__(self, trainer):\n        if self.last_index is None:\n            last_index = getattr(trainer.updater.state, self.unit)\n            self.last_index = last_index\n\n        last_index = self.last_index\n        index = getattr(trainer.updater.state, self.unit)\n        fire = index // self.period != last_index // self.period\n\n        self.last_index = index\n        return fire\n"
  },
  {
    "path": "paddlespeech/t2s/training/triggers/limit_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass LimitTrigger(object):\n    \"\"\"A Predicate to decide whether to stop.\"\"\"\n\n    def __init__(self, limit: int, unit: str):\n        if unit not in (\"iteration\", \"epoch\"):\n            raise ValueError(\"unit should be 'iteration' or 'epoch'\")\n        if limit <= 0:\n            raise ValueError(\"limit should be a positive integer.\")\n        self.limit = limit\n        self.unit = unit\n\n    def __call__(self, trainer):\n        state = trainer.updater.state\n        index = getattr(state, self.unit)\n        fire = index >= self.limit\n        return fire\n"
  },
  {
    "path": "paddlespeech/t2s/training/triggers/time_trigger.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Reference chainer MIT (https://opensource.org/licenses/MIT)\n\n\nclass TimeTrigger(object):\n    \"\"\"Trigger based on a fixed time interval.\n\n    This trigger accepts iterations with a given interval time.\n\n    Args:\n        period (float): Interval time. It is given in seconds.\n\n    \"\"\"\n\n    def __init__(self, period):\n        self._period = period\n        self._next_time = self._period\n\n    def __call__(self, trainer):\n        if self._next_time < trainer.elapsed_time:\n            self._next_time += self._period\n            return True\n        else:\n            return False\n"
  },
  {
    "path": "paddlespeech/t2s/training/updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport logging\nfrom dataclasses import dataclass\n\nimport paddle\n\n\n@dataclass\nclass UpdaterState:\n    iteration: int = 0\n    epoch: int = 0\n\n\nclass UpdaterBase(object):\n    \"\"\"An updater is the abstraction of how a model is trained given the\n    dataloader and the optimizer.\n\n    The `update_core` method is a step in the training loop with only necessary\n    operations (get a batch, forward and backward, update the parameters).\n\n    Other stuffs are made extensions. Visualization, saving, loading and\n    periodical validation and evaluation are not considered here.\n\n    But even in such simplist case, things are not that simple. There is an\n    attempt to standardize this process and requires only the model and\n    dataset and do all the stuffs automatically. But this may hurt flexibility.\n\n    If we assume a batch yield from the dataloader is just the input to the\n    model, we will find that some model requires more arguments, or just some\n    keyword arguments. But this prevents us from over-simplifying it.\n\n    From another perspective, the batch may includes not just the input, but\n    also the target. But the model's forward method may just need the input.\n    We can pass a dict or a super-long tuple to the model and let it pick what\n    it really needs. But this is an abuse of lazy interface.\n\n    After all, we care about how a model is trained. But just how the model is\n    used for inference. We want to control how a model is trained. We just\n    don't want to be messed up with other auxiliary code.\n\n    So the best practice is to define a model and define a updater for it.\n    \"\"\"\n\n    def __init__(self, init_state=None):\n        if init_state is None:\n            self.state = UpdaterState()\n        else:\n            self.state = init_state\n\n    def update(self, batch):\n        raise NotImplementedError(\n            \"Implement your own `update` method for training a step.\")\n\n    def state_dict(self):\n        state_dict = {\n            \"epoch\": self.state.epoch,\n            \"iteration\": self.state.iteration,\n        }\n        return state_dict\n\n    def set_state_dict(self, state_dict):\n        self.state.epoch = state_dict[\"epoch\"]\n        self.state.iteration = state_dict[\"iteration\"]\n\n    def save(self, path):\n        logging.debug(f\"Saving to {path}.\")\n        archive = self.state_dict()\n        paddle.save(archive, str(path))\n\n    def load(self, path):\n        logging.debug(f\"Loading from {path}.\")\n        archive = paddle.load(str(path))\n        self.set_state_dict(archive)\n"
  },
  {
    "path": "paddlespeech/t2s/training/updaters/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/t2s/training/updaters/standard_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from chainer(https://github.com/chainer/chainer)\nimport logging\nimport time\nfrom typing import Dict\nfrom typing import Optional\n\nfrom paddle import Tensor\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom timer import timer\n\nfrom paddlespeech.t2s.datasets.sampler import ErnieSATSampler\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updater import UpdaterBase\nfrom paddlespeech.t2s.training.updater import UpdaterState\n\n\nclass StandardUpdater(UpdaterBase):\n    \"\"\"An example of over-simplification. Things may not be that simple, but\n    you can subclass it to fit your need.\n    \"\"\"\n\n    def __init__(self,\n                 model: Layer,\n                 optimizer: Optimizer,\n                 dataloader: DataLoader,\n                 init_state: Optional[UpdaterState]=None):\n        # it is designed to hold multiple models\n        models = {\"main\": model}\n        self.models: Dict[str, Layer] = models\n        self.model = model\n\n        # it is designed to hold multiple optimizers\n        optimizers = {\"main\": optimizer}\n        self.optimizer = optimizer\n        self.optimizers: Dict[str, Optimizer] = optimizers\n\n        # dataloaders\n        self.dataloader = dataloader\n\n        # init state\n        if init_state is None:\n            self.state = UpdaterState()\n        else:\n            self.state = init_state\n\n        self.train_iterator = iter(dataloader)\n        self.batch_read_time = 0\n        self.batch_time = 0\n\n    def update(self):\n        # We increase the iteration index after updating and before extension.\n        # Here are the reasons.\n\n        # 0. Snapshotting(as well as other extensions, like visualizer) is\n        #    executed after a step of updating;\n        # 1. We decide to increase the iteration index after updating and\n        #    before any all extension is executed. \n        # 3. We do not increase the iteration after extension because we\n        #    prefer a consistent resume behavior, when load from a\n        #    `snapshot_iter_100.pdz` then the next step to train is `101`,\n        #    naturally. But if iteration is increased increased after\n        #    extension(including snapshot), then, a `snapshot_iter_99` is\n        #    loaded. You would need a extra increasing of the iteration idex\n        #    before training to avoid another iteration `99`, which has been\n        #    done before snapshotting.\n        # 4. Thus iteration index represrnts \"currently how mant epochs has\n        #    been done.\"\n        # NOTE: use report to capture the correctly value. If you want to\n        # report the learning rate used for a step, you must report it before\n        # the learning rate scheduler's step() has been called. In paddle's\n        # convention, we do not use an extension to change the learning rate.\n        # so if you want to report it, do it in the updater.\n\n        # Then here comes the next question. When is the proper time to\n        # increase the epoch index? Since all extensions are executed after\n        # updating, it is the time that after updating is the proper time to\n        # increase epoch index.\n        # 1. If we increase the epoch index before updating, then an extension\n        #    based ot epoch would miss the correct timing. It could only be\n        #    triggerd after an extra updating.\n        # 2. Theoretically, when an epoch is done, the epoch index should be\n        #    increased. So it would be increase after updating.\n        # 3. Thus, eppoch index represents \"currently how many epochs has been\n        #    done.\" So it starts from 0.\n\n        # switch to training mode\n        for layer in self.models.values():\n            layer.train()\n\n        # training for a step is implemented here\n        time_before_read = time.time()\n        batch = self.read_batch()\n        time_before_core = time.time()\n        self.update_core(batch)\n        self.batch_time = time.time() - time_before_core\n        self.batch_read_time = time_before_core - time_before_read\n        if isinstance(batch, dict):\n            self.batch_size = len(list(batch.items())[0][-1])\n        # for pwg\n        elif isinstance(batch, list):\n            self.batch_size = batch[0].shape[0]\n\n        self.state.iteration += 1\n        if self.updates_per_epoch is not None:\n            if self.state.iteration % self.updates_per_epoch == 0:\n                self.state.epoch += 1\n\n    def update_core(self, batch):\n        \"\"\"A simple case for a training step. Basic assumptions are:\n        Single model;\n        Single optimizer;\n        A batch from the dataloader is just the input of the model;\n        The model return a single loss, or a dict containing serval losses.\n        Parameters updates at every batch, no gradient accumulation.\n        \"\"\"\n        loss = self.model(*batch)\n\n        if isinstance(loss, Tensor):\n            loss_dict = {\"main\": loss}\n        else:\n            # Dict[str, Tensor]\n            loss_dict = loss\n            if \"main\" not in loss_dict:\n                main_loss = 0\n                for loss_item in loss.values():\n                    main_loss += loss_item\n                loss_dict[\"main\"] = main_loss\n\n        for name, loss_item in loss_dict.items():\n            report(name, float(loss_item))\n\n        self.optimizer.clear_gradient()\n        loss_dict[\"main\"].backward()\n        self.optimizer.update()\n\n    @property\n    def updates_per_epoch(self):\n        \"\"\"Number of updater per epoch, determined by the length of the\n        dataloader.\"\"\"\n        length_of_dataloader = None\n        try:\n            length_of_dataloader = len(self.dataloader)\n        except TypeError:\n            logging.debug(\"This dataloader has no __len__.\")\n        finally:\n            return length_of_dataloader\n\n    def new_epoch(self):\n        \"\"\"Start a new epoch.\"\"\"\n        # NOTE: all batch sampler for distributed training should\n        # subclass DistributedBatchSampler and implement `set_epoch` method\n        batch_sampler = self.dataloader.batch_sampler\n        if isinstance(batch_sampler, DistributedBatchSampler) \\\n                or isinstance(batch_sampler, ErnieSATSampler):\n            batch_sampler.set_epoch(self.state.epoch)\n        self.train_iterator = iter(self.dataloader)\n\n    def read_batch(self):\n        \"\"\"Read a batch from the data loader, auto renew when data is exhausted.\"\"\"\n        with timer() as t:\n            try:\n                batch = next(self.train_iterator)\n            except StopIteration:\n                self.new_epoch()\n                batch = next(self.train_iterator)\n            logging.debug(\n                f\"Read a batch takes {t.elapse}s.\")  # replace it with logging\n        return batch\n\n    def state_dict(self):\n        \"\"\"State dict of a Updater, model, optimizer and updater state are included.\"\"\"\n        state_dict = super().state_dict()\n        for name, layer in self.models.items():\n            state_dict[f\"{name}_params\"] = layer.state_dict()\n        for name, optim in self.optimizers.items():\n            state_dict[f\"{name}_optimizer\"] = optim.state_dict()\n        return state_dict\n\n    def set_state_dict(self, state_dict):\n        \"\"\"Set state dict for a Updater. Parameters of models, states for\n        optimizers and UpdaterState are restored.\"\"\"\n        for name, layer in self.models.items():\n            layer.set_state_dict(state_dict[f\"{name}_params\"])\n        for name, optim in self.optimizers.items():\n            optim.set_state_dict(state_dict[f\"{name}_optimizer\"])\n        super().set_state_dict(state_dict)\n"
  },
  {
    "path": "paddlespeech/t2s/utils/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom . import checkpoint\nfrom . import display\nfrom . import layer_tools\nfrom . import mp_tools\nfrom . import scheduler\n\n\ndef str2bool(str):\n    return True if str.lower() == 'true' else False\n"
  },
  {
    "path": "paddlespeech/t2s/utils/checkpoint.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport paddle\nfrom paddle import distributed as dist\n\nfrom paddlespeech.t2s.utils import mp_tools\n\n__all__ = [\"load_parameters\", \"save_parameters\"]\n\n\ndef _load_latest_checkpoint(checkpoint_dir: str) -> int:\n    \"\"\"Get the iteration number corresponding to the latest saved checkpoint.\n\n    Args:\n        checkpoint_dir (str):\n            the directory where checkpoint is saved.\n\n    Returns:\n        int: the latest iteration number.\n    \"\"\"\n    checkpoint_record = os.path.join(checkpoint_dir, \"checkpoint\")\n    if (not os.path.isfile(checkpoint_record)):\n        return 0\n\n    # Fetch the latest checkpoint index.\n    with open(checkpoint_record, \"rt\") as handle:\n        latest_checkpoint = handle.readline().split()[-1]\n        iteration = int(latest_checkpoint.split(\"-\")[-1])\n\n    return iteration\n\n\ndef _save_checkpoint(checkpoint_dir: str, iteration: int):\n    \"\"\"Save the iteration number of the latest model to be checkpointed.\n\n    Args:\n        checkpoint_dir (str): \n            the directory where checkpoint is saved.\n        iteration (int): \n            the latest iteration number.\n\n    Returns:\n        None\n    \"\"\"\n    checkpoint_record = os.path.join(checkpoint_dir, \"checkpoint\")\n    # Update the latest checkpoint index.\n    with open(checkpoint_record, \"wt\") as handle:\n        handle.write(\"model_checkpoint_path: step-{}\".format(iteration))\n\n\ndef load_parameters(model,\n                    optimizer=None,\n                    checkpoint_dir=None,\n                    checkpoint_path=None):\n    \"\"\"Load a specific model checkpoint from disk.\n\n    Args:\n        model (Layer): \n            model to load parameters.\n        optimizer (Optimizer, optional): \n            optimizer to load states if needed. Defaults to None.\n        checkpoint_dir (str, optional): \n            the directory where checkpoint is saved.\n        checkpoint_path (str, optional): \n            if specified, load the checkpoint\n            stored in the checkpoint_path and the argument 'checkpoint_dir' will\n            be ignored. Defaults to None.\n\n    Returns:\n        iteration (int): number of iterations that the loaded checkpoint has \n            been trained.\n    \"\"\"\n    if checkpoint_path is not None:\n        iteration = int(os.path.basename(checkpoint_path).split(\"-\")[-1])\n    elif checkpoint_dir is not None:\n        iteration = _load_latest_checkpoint(checkpoint_dir)\n        if iteration == 0:\n            return iteration\n        checkpoint_path = os.path.join(checkpoint_dir,\n                                       \"step-{}\".format(iteration))\n    else:\n        raise ValueError(\n            \"At least one of 'checkpoint_dir' and 'checkpoint_path' should be specified!\"\n        )\n\n    local_rank = dist.get_rank()\n\n    params_path = checkpoint_path + \".pdparams\"\n    model_dict = paddle.load(params_path)\n    model.set_state_dict(model_dict)\n    print(\"[checkpoint] Rank {}: loaded model from {}\".format(local_rank,\n                                                              params_path))\n\n    optimizer_path = checkpoint_path + \".pdopt\"\n    if optimizer and os.path.isfile(optimizer_path):\n        optimizer_dict = paddle.load(optimizer_path)\n        optimizer.set_state_dict(optimizer_dict)\n        print(\"[checkpoint] Rank {}: loaded optimizer state from {}\".format(\n            local_rank, optimizer_path))\n\n    return iteration\n\n\n@mp_tools.rank_zero_only\ndef save_parameters(checkpoint_dir, iteration, model, optimizer=None):\n    \"\"\"Checkpoint the latest trained model parameters.\n\n    Args:\n        checkpoint_dir (str): \n            the directory where checkpoint is saved.\n        iteration (int): \n            the latest iteration number.\n        model (Layer): \n            model to be checkpointed.\n        optimizer (Optimizer, optional): \n            optimizer to be checkpointed. Defaults to None.\n\n    Returns:\n        None\n    \"\"\"\n    checkpoint_path = os.path.join(checkpoint_dir, \"step-{}\".format(iteration))\n\n    model_dict = model.state_dict()\n    params_path = checkpoint_path + \".pdparams\"\n    paddle.save(model_dict, params_path)\n    print(\"[checkpoint] Saved model to {}\".format(params_path))\n\n    if optimizer:\n        opt_dict = optimizer.state_dict()\n        optimizer_path = checkpoint_path + \".pdopt\"\n        paddle.save(opt_dict, optimizer_path)\n        print(\"[checkpoint] Saved optimzier state to {}\".format(optimizer_path))\n\n    _save_checkpoint(checkpoint_dir, iteration)\n"
  },
  {
    "path": "paddlespeech/t2s/utils/display.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport librosa.display\nimport matplotlib.pylab as plt\n\n__all__ = [\n    \"plot_alignment\",\n    \"plot_spectrogram\",\n    \"plot_waveform\",\n    \"plot_multihead_alignments\",\n    \"plot_multilayer_multihead_alignments\",\n]\n\n\ndef plot_alignment(alignment, title=None):\n    # alignment: [encoder_steps, decoder_steps)\n    fig, ax = plt.subplots(figsize=(6, 4))\n    im = ax.imshow(\n        alignment, aspect='auto', origin='lower', interpolation='none')\n    fig.colorbar(im, ax=ax)\n    xlabel = 'Decoder timestep'\n    if title is not None:\n        xlabel += '\\n\\n' + title\n    plt.xlabel(xlabel)\n    plt.ylabel('Encoder timestep')\n    plt.tight_layout()\n    return fig\n\n\ndef plot_multihead_alignments(alignments, title=None):\n    # alignments: [N, encoder_steps, decoder_steps)\n    num_subplots = alignments.shape[0]\n\n    fig, axes = plt.subplots(\n        figsize=(6 * num_subplots, 4),\n        ncols=num_subplots,\n        sharey=True,\n        squeeze=True)\n    for i, ax in enumerate(axes):\n        im = ax.imshow(\n            alignments[i], aspect='auto', origin='lower', interpolation='none')\n        fig.colorbar(im, ax=ax)\n        xlabel = 'Decoder timestep'\n        if title is not None:\n            xlabel += '\\n\\n' + title\n        ax.set_xlabel(xlabel)\n        if i == 0:\n            ax.set_ylabel('Encoder timestep')\n    plt.tight_layout()\n    return fig\n\n\ndef plot_multilayer_multihead_alignments(alignments, title=None):\n    # alignments: [num_layers, num_heads, encoder_steps, decoder_steps)\n    num_layers, num_heads, *_ = alignments.shape\n\n    fig, axes = plt.subplots(\n        figsize=(6 * num_heads, 4 * num_layers),\n        nrows=num_layers,\n        ncols=num_heads,\n        sharex=True,\n        sharey=True,\n        squeeze=True)\n    for i, row in enumerate(axes):\n        for j, ax in enumerate(row):\n            im = ax.imshow(\n                alignments[i, j],\n                aspect='auto',\n                origin='lower',\n                interpolation='none')\n            fig.colorbar(im, ax=ax)\n            xlabel = 'Decoder timestep'\n            if title is not None:\n                xlabel += '\\n\\n' + title\n            if i == num_layers - 1:\n                ax.set_xlabel(xlabel)\n            if j == 0:\n                ax.set_ylabel('Encoder timestep')\n    plt.tight_layout()\n    return fig\n\n\ndef plot_spectrogram(spec):\n    # spec: [C, T] librosa convention\n    fig, ax = plt.subplots(figsize=(12, 3))\n    im = ax.imshow(spec, aspect=\"auto\", origin=\"lower\", interpolation='none')\n    plt.colorbar(im, ax=ax)\n    plt.xlabel(\"Frames\")\n    plt.ylabel(\"Channels\")\n    plt.tight_layout()\n    return fig\n\n\ndef plot_waveform(wav, sr=22050):\n    fig, ax = plt.subplots(figsize=(12, 3))\n    im = librosa.display.waveplot(wav, sr=22050)\n    plt.colorbar(im, ax=ax)\n    plt.tight_layout()\n    return fig\n"
  },
  {
    "path": "paddlespeech/t2s/utils/error_rate.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"This module provides functions to calculate error rate in different level.\ne.g. wer for word-level, cer for char-level.\n\"\"\"\nimport numpy as np\n\n__all__ = ['word_errors', 'char_errors', 'wer', 'cer']\n\n\ndef _levenshtein_distance(ref, hyp):\n    \"\"\"Levenshtein distance is a string metric for measuring the difference\n    between two sequences. Informally, the levenshtein disctance is defined as\n    the minimum number of single-character edits (substitutions, insertions or\n    deletions) required to change one word into the other. We can naturally\n    extend the edits to word level when calculate levenshtein disctance for\n    two sentences.\n    \"\"\"\n    m = len(ref)\n    n = len(hyp)\n\n    # special case\n    if ref == hyp:\n        return 0\n    if m == 0:\n        return n\n    if n == 0:\n        return m\n\n    if m < n:\n        ref, hyp = hyp, ref\n        m, n = n, m\n\n    # use O(min(m, n)) space\n    distance = np.zeros((2, n + 1), dtype=np.int32)\n\n    # initialize distance matrix\n    for j in range(n + 1):\n        distance[0][j] = j\n\n    # calculate levenshtein distance\n    for i in range(1, m + 1):\n        prev_row_idx = (i - 1) % 2\n        cur_row_idx = i % 2\n        distance[cur_row_idx][0] = i\n        for j in range(1, n + 1):\n            if ref[i - 1] == hyp[j - 1]:\n                distance[cur_row_idx][j] = distance[prev_row_idx][j - 1]\n            else:\n                s_num = distance[prev_row_idx][j - 1] + 1\n                i_num = distance[cur_row_idx][j - 1] + 1\n                d_num = distance[prev_row_idx][j] + 1\n                distance[cur_row_idx][j] = min(s_num, i_num, d_num)\n\n    return distance[m % 2][n]\n\n\ndef word_errors(reference, hypothesis, ignore_case=False, delimiter=' '):\n    \"\"\"Compute the levenshtein distance between reference sequence and\n    hypothesis sequence in word-level.\n\n    Args:\n        reference (str): \n            The reference sentence.\n        hypothesis (str): \n            The hypothesis sentence.\n        ignore_case (bool): \n            Whether case-sensitive or not.\n        delimiter (char(str)): \n            Delimiter of input sentences.\n\n    Returns:\n        list: Levenshtein distance and word number of reference sentence.\n    \"\"\"\n    if ignore_case:\n        reference = reference.lower()\n        hypothesis = hypothesis.lower()\n\n    ref_words = list(filter(None, reference.split(delimiter)))\n    hyp_words = list(filter(None, hypothesis.split(delimiter)))\n\n    edit_distance = _levenshtein_distance(ref_words, hyp_words)\n    return float(edit_distance), len(ref_words)\n\n\ndef char_errors(reference, hypothesis, ignore_case=False, remove_space=False):\n    \"\"\"Compute the levenshtein distance between reference sequence and\n    hypothesis sequence in char-level.\n\n    Args:\n        reference (str): The reference sentence.\n        hypothesis (str): The hypothesis sentence.\n        ignore_case (bool): Whether case-sensitive or not.\n        remove_space (bool): Whether remove internal space characters\n\n    Returns:\n        list: Levenshtein distance and length of reference sentence.\n    \"\"\"\n    if ignore_case:\n        reference = reference.lower()\n        hypothesis = hypothesis.lower()\n\n    join_char = ' '\n    if remove_space:\n        join_char = ''\n\n    reference = join_char.join(list(filter(None, reference.split(' '))))\n    hypothesis = join_char.join(list(filter(None, hypothesis.split(' '))))\n\n    edit_distance = _levenshtein_distance(reference, hypothesis)\n    return float(edit_distance), len(reference)\n\n\ndef wer(reference, hypothesis, ignore_case=False, delimiter=' '):\n    \"\"\"Calculate word error rate (WER). WER compares reference text and\n    hypothesis text in word-level. WER is defined as:\n    .. math::\n        WER = (Sw + Dw + Iw) / Nw\n    where\n    .. code-block:: text\n        Sw is the number of words subsituted,\n        Dw is the number of words deleted,\n        Iw is the number of words inserted,\n        Nw is the number of words in the reference\n    We can use levenshtein distance to calculate WER. Please draw an attention\n    that empty items will be removed when splitting sentences by delimiter.\n\n    Args:\n        reference (str): The reference sentence.\n        hypothesis (str): The hypothesis sentence.\n        ignore_case (bool): Whether case-sensitive or not.\n        delimiter (char): Delimiter of input sentences.\n\n    Returns: \n        float: Word error rate.\n\n    Raises:\n        ValueError: If word number of reference is zero.\n    \"\"\"\n    edit_distance, ref_len = word_errors(reference, hypothesis, ignore_case,\n                                         delimiter)\n\n    if ref_len == 0:\n        raise ValueError(\"Reference's word number should be greater than 0.\")\n\n    wer = float(edit_distance) / ref_len\n    return wer\n\n\ndef cer(reference, hypothesis, ignore_case=False, remove_space=False):\n    \"\"\"Calculate character error rate (CER). CER compares reference text and\n    hypothesis text in char-level. CER is defined as:\n    .. math::\n        CER = (Sc + Dc + Ic) / Nc\n    where\n    .. code-block:: text\n        Sc is the number of characters substituted,\n        Dc is the number of characters deleted,\n        Ic is the number of characters inserted\n        Nc is the number of characters in the reference\n    We can use levenshtein distance to calculate CER. Chinese input should be\n    encoded to unicode. Please draw an attention that the leading and tailing\n    space characters will be truncated and multiple consecutive space\n    characters in a sentence will be replaced by one space character.\n\n    Args:\n        reference (str): The reference sentence.\n        hypothesis (str): The hypothesis sentence.\n        ignore_case (bool): Whether case-sensitive or not.\n        remove_space (bool): Whether remove internal space characters\n\n    Returns: \n        float: Character error rate.\n\n    Raises: \n        ValueError: If the reference length is zero.\n    \"\"\"\n    edit_distance, ref_len = char_errors(reference, hypothesis, ignore_case,\n                                         remove_space)\n\n    if ref_len == 0:\n        raise ValueError(\"Length of reference should be greater than 0.\")\n\n    cer = float(edit_distance) / ref_len\n    return cer\n\n\nif __name__ == \"__main__\":\n    reference = [\n        'j', 'iou4', 'zh', 'e4', 'iang5', 'x', 'v2', 'b', 'o1', 'k', 'ai1',\n        'sh', 'iii3', 'l', 'e5', 'b', 'ei3', 'p', 'iao1', 'sh', 'eng1', 'ia2'\n    ]\n    hypothesis = [\n        'j', 'iou4', 'zh', 'e4', 'iang4', 'x', 'v2', 'b', 'o1', 'k', 'ai1',\n        'sh', 'iii3', 'l', 'e5', 'b', 'ei3', 'p', 'iao1', 'sh', 'eng1', 'ia2'\n    ]\n    reference = \" \".join(reference)\n    hypothesis = \" \".join(hypothesis)\n    print(wer(reference, hypothesis))\n"
  },
  {
    "path": "paddlespeech/t2s/utils/h5_utils.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\nimport sys\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Union\n\nimport h5py\nimport numpy as np\n\n\ndef read_hdf5(filename: Union[Path, str], dataset_name: str) -> Any:\n    \"\"\"Read a dataset from a HDF5 file.\n    Args:\n        filename (Union[Path, str]): \n            Path of the HDF5 file.\n        dataset_name (str): \n            Name of the dataset to read.\n\n    Returns:\n        Any: The retrieved dataset.\n    \"\"\"\n    filename = Path(filename)\n\n    if not filename.exists():\n        logging.error(f\"There is no such a hdf5 file ({filename}).\")\n        sys.exit(1)\n\n    hdf5_file = h5py.File(filename, \"r\")\n\n    if dataset_name not in hdf5_file:\n        logging.error(f\"There is no such a data in hdf5 file. ({dataset_name})\")\n        sys.exit(1)\n\n    # [()]: a special syntax of h5py to get the dataset as-is\n    hdf5_data = hdf5_file[dataset_name][()]\n    hdf5_file.close()\n\n    return hdf5_data\n\n\ndef write_hdf5(filename: Union[Path, str],\n               dataset_name: str,\n               write_data: np.ndarray,\n               is_overwrite: bool=True) -> None:\n    \"\"\"Write dataset to HDF5 file.\n    Args:\n        filename (Union[Path, str]): Path of the HDF5 file.\n        dataset_name (str): Name of the dataset to write to.\n        write_data (np.ndarrays): The data to write.\n        is_overwrite (bool, optional): Whether to overwrite, by default True\n    \"\"\"\n    # convert to numpy array\n    filename = Path(filename)\n    write_data = np.array(write_data)\n\n    # check folder existence\n    filename.parent.mkdir(parents=True, exist_ok=True)\n\n    # check hdf5 existence\n    if filename.exists():\n        # if already exists, open with r+ mode\n        hdf5_file = h5py.File(filename, \"r+\")\n        # check dataset existence\n        if dataset_name in hdf5_file:\n            if is_overwrite:\n                logging.warning(\"Dataset in hdf5 file already exists. \"\n                                \"recreate dataset in hdf5.\")\n                hdf5_file.__delitem__(dataset_name)\n            else:\n                logging.error(\n                    \"Dataset in hdf5 file already exists. \"\n                    \"if you want to overwrite, please set is_overwrite = True.\")\n                hdf5_file.close()\n                sys.exit(1)\n    else:\n        # if not exists, open with w mode\n        hdf5_file = h5py.File(filename, \"w\")\n\n    # write data to hdf5\n    hdf5_file.create_dataset(dataset_name, data=write_data)\n    hdf5_file.flush()\n    hdf5_file.close()\n"
  },
  {
    "path": "paddlespeech/t2s/utils/internals.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom paddle.framework import core\n\n__all__ = [\"convert_dtype_to_np_dtype_\"]\n\n\ndef convert_dtype_to_np_dtype_(dtype):\n    \"\"\"\n    Convert paddle's data type to corrsponding numpy data type.\n\n    Args:\n        dtype(np.dtype): \n            the data type in paddle.\n\n    Returns:\n        type: the data type in numpy.\n\n    \"\"\"\n    if dtype is core.VarDesc.VarType.FP32:\n        return np.float32\n    elif dtype is core.VarDesc.VarType.FP64:\n        return np.float64\n    elif dtype is core.VarDesc.VarType.FP16:\n        return np.float16\n    elif dtype is core.VarDesc.VarType.BOOL:\n        return np.bool_\n    elif dtype is core.VarDesc.VarType.INT32:\n        return np.int32\n    elif dtype is core.VarDesc.VarType.INT64:\n        return np.int64\n    elif dtype is core.VarDesc.VarType.INT16:\n        return np.int16\n    elif dtype is core.VarDesc.VarType.INT8:\n        return np.int8\n    elif dtype is core.VarDesc.VarType.UINT8:\n        return np.uint8\n    elif dtype is core.VarDesc.VarType.BF16:\n        return np.uint16\n    else:\n        raise ValueError(\"Not supported dtype %s\" % dtype)\n"
  },
  {
    "path": "paddlespeech/t2s/utils/layer_tools.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom paddle import nn\n\n__all__ = [\"summary\", \"gradient_norm\", \"freeze\", \"unfreeze\"]\n\n\ndef summary(layer: nn.Layer):\n    num_params = num_elements = 0\n    print(\"layer summary:\")\n    for name, param in layer.state_dict().items():\n        print(\"{}|{}|{}\".format(name, param.shape, np.prod(param.shape)))\n        num_elements += np.prod(param.shape)\n        num_params += 1\n    print(\"layer has {} parameters, {} elements.\".format(num_params,\n                                                         num_elements))\n\n\ndef gradient_norm(layer: nn.Layer):\n    grad_norm_dict = {}\n    for name, param in layer.state_dict().items():\n        if param.trainable:\n            grad = param.gradient()\n            grad_norm_dict[name] = np.linalg.norm(grad) / grad.size\n    return grad_norm_dict\n\n\ndef recursively_remove_weight_norm(layer: nn.Layer):\n    for layer in layer.sublayers():\n        try:\n            nn.utils.remove_weight_norm(layer)\n        except Exception as e:\n            # ther is not weight norm hoom in this layer\n            pass\n\n\ndef freeze(layer: nn.Layer):\n    for param in layer.parameters():\n        param.trainable = False\n\n\ndef unfreeze(layer: nn.Layer):\n    for param in layer.parameters():\n        param.trainable = True\n"
  },
  {
    "path": "paddlespeech/t2s/utils/mp_tools.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom functools import wraps\n\nfrom paddle import distributed as dist\n\n__all__ = [\"rank_zero_only\"]\n\n\ndef rank_zero_only(func):\n    @wraps(func)\n    def wrapper(*args, **kwargs):\n        if dist.get_rank() != 0:\n            return\n        result = func(*args, **kwargs)\n        return result\n\n    return wrapper\n"
  },
  {
    "path": "paddlespeech/t2s/utils/profiler.py",
    "content": "# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport sys\nimport paddle.profiler as profiler\n\n# A global variable to record the number of calling times for profiler\n# functions. It is used to specify the tracing range of training steps.\n_profiler_step_id = 0\n\n# A global variable to avoid parsing from string every time.\n_profiler_options = None\n_prof = None\n\nclass ProfilerOptions(object):\n    '''\n    Use a string to initialize a ProfilerOptions.\n    The string should be in the format: \"key1=value1;key2=value;key3=value3\".\n    For example:\n      \"profile_path=model.profile\"\n      \"batch_range=[50, 60]; profile_path=model.profile\"\n      \"batch_range=[50, 60]; tracer_option=OpDetail; profile_path=model.profile\"\n\n    ProfilerOptions supports following key-value pair:\n      batch_range      - a integer list, e.g. [100, 110].\n      state            - a string, the optional values are 'CPU', 'GPU' or 'All'. \n      sorted_key       - a string, the optional values are 'calls', 'total',\n                         'max', 'min' or 'ave.\n      tracer_option    - a string, the optional values are 'Default', 'OpDetail',\n                         'AllOpDetail'.\n      profile_path     - a string, the path to save the serialized profile data,\n                         which can be used to generate a timeline.\n      exit_on_finished - a boolean.\n    '''\n\n    def __init__(self, options_str):\n        assert isinstance(options_str, str)\n\n        self._options = {\n            'batch_range': [10, 20],\n            'state': 'All',\n            'sorted_key': 'total',\n            'tracer_option': 'Default',\n            'profile_path': '/tmp/profile',\n            'exit_on_finished': True,\n            'timer_only': True\n        }\n        self._parse_from_string(options_str)\n\n    def _parse_from_string(self, options_str):\n        for kv in options_str.replace(' ', '').split(';'):\n            key, value = kv.split('=')\n            if key == 'batch_range':\n                value_list = value.replace('[', '').replace(']', '').split(',')\n                value_list = list(map(int, value_list))\n                if len(value_list) >= 2 and value_list[0] >= 0 and value_list[\n                        1] > value_list[0]:\n                    self._options[key] = value_list\n            elif key == 'exit_on_finished':\n                self._options[key] = value.lower() in (\"yes\", \"true\", \"t\", \"1\")\n            elif key in [\n                    'state', 'sorted_key', 'tracer_option', 'profile_path'\n            ]:\n                self._options[key] = value\n            elif key == 'timer_only':\n                self._options[key] = value\n\n    def __getitem__(self, name):\n        if self._options.get(name, None) is None:\n            raise ValueError(\n                \"ProfilerOptions does not have an option named %s.\" % name)\n        return self._options[name]\n\n\ndef add_profiler_step(options_str=None):\n    '''\n    Enable the operator-level timing using PaddlePaddle's profiler.\n    The profiler uses a independent variable to count the profiler steps.\n    One call of this function is treated as a profiler step.\n    Args:\n      profiler_options - a string to initialize the ProfilerOptions.\n                         Default is None, and the profiler is disabled.\n    '''\n    if options_str is None:\n        return\n\n    global _prof \n    global _profiler_step_id\n    global _profiler_options\n\n    if _profiler_options is None:\n        _profiler_options = ProfilerOptions(options_str)\n    # profile : https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/performance_improving/profiling_model.html#chakanxingnengshujudetongjibiaodan\n    # timer_only = True  only the model's throughput and time overhead are displayed\n    # timer_only = False calling summary can print a statistical form that presents performance data from different perspectives.\n    # timer_only = False the output Timeline information can be found in the profiler_log directory\n    if _prof is None:\n        _timer_only = str(_profiler_options['timer_only']) == str(True)\n        _prof = profiler.Profiler(\n                   scheduler = (_profiler_options['batch_range'][0], _profiler_options['batch_range'][1]),\n                   on_trace_ready = profiler.export_chrome_tracing('./profiler_log'),\n                   timer_only = _timer_only)\n        _prof.start()\n    else:\n        _prof.step()\n        \n    if _profiler_step_id == _profiler_options['batch_range'][1]:\n        _prof.stop()\n        _prof.summary(\n             op_detail=True,\n             thread_sep=False,\n             time_unit='ms')\n        _prof = None\n        if _profiler_options['exit_on_finished']:\n            sys.exit(0)\n\n    _profiler_step_id += 1\n"
  },
  {
    "path": "paddlespeech/t2s/utils/scheduler.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n__all__ = [\"SchedulerBase\", \"Constant\", \"PieceWise\", \"StepWise\"]\n\n\nclass SchedulerBase(object):\n    def __call__(self, step):\n        raise NotImplementedError(\"You should implement the __call__ method.\")\n\n\nclass Constant(SchedulerBase):\n    def __init__(self, value):\n        self.value = value\n\n    def __call__(self, step):\n        return self.value\n\n\nclass PieceWise(SchedulerBase):\n    def __init__(self, anchors):\n        anchors = list(anchors)\n        anchors = sorted(anchors, key=lambda x: x[0])\n        assert anchors[0][0] == 0, \"it must start from zero\"\n        self.xs = [item[0] for item in anchors]\n        self.ys = [item[1] for item in anchors]\n        self.num_anchors = len(self.xs)\n\n    def __call__(self, step):\n        i = 0\n        for x in self.xs:\n            if step >= x:\n                i += 1\n        if i == 0:\n            return self.ys[0]\n        if i == self.num_anchors:\n            return self.ys[-1]\n        k = (self.ys[i] - self.ys[i - 1]) / (self.xs[i] - self.xs[i - 1])\n        out = self.ys[i - 1] + (step - self.xs[i - 1]) * k\n        return out\n\n\nclass StepWise(SchedulerBase):\n    def __init__(self, anchors):\n        anchors = list(anchors)\n        anchors = sorted(anchors, key=lambda x: x[0])\n        assert anchors[0][0] == 0, \"it must start from zero\"\n        self.xs = [item[0] for item in anchors]\n        self.ys = [item[1] for item in anchors]\n        self.num_anchors = len(self.xs)\n\n    def __call__(self, step):\n        i = 0\n        for x in self.xs:\n            if step >= x:\n                i += 1\n\n        if i == self.num_anchors:\n            return self.ys[-1]\n        if i == 0:\n            return self.ys[0]\n        return self.ys[i - 1]\n"
  },
  {
    "path": "paddlespeech/text/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/text/exps/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/text/exps/ernie_linear/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/text/exps/ernie_linear/avg_model.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport glob\nimport json\nimport os\n\nimport numpy as np\nimport paddle\n\n\ndef main(args):\n    paddle.set_device('cpu')\n\n    val_scores = []\n    beat_val_scores = []\n    selected_epochs = []\n    if args.val_best:\n        jsons = glob.glob(f'{args.ckpt_dir}/[!train]*.json')\n        for y in jsons:\n            with open(y, 'r') as f:\n                dict_json = json.load(f)\n            loss = dict_json['F1']\n            epoch = dict_json['epoch']\n            if epoch >= args.min_epoch and epoch <= args.max_epoch:\n                val_scores.append((epoch, loss))\n\n        val_scores = np.array(val_scores)\n        sort_idx = np.argsort(-val_scores[:, 1])\n        sorted_val_scores = val_scores[sort_idx]\n        path_list = [\n            args.ckpt_dir + '/{}.pdparams'.format(int(epoch))\n            for epoch in sorted_val_scores[:args.num, 0]\n        ]\n\n        beat_val_scores = sorted_val_scores[:args.num, 1]\n        selected_epochs = sorted_val_scores[:args.num, 0].astype(np.int64)\n        print(\"best val scores = \" + str(beat_val_scores))\n        print(\"selected epochs = \" + str(selected_epochs))\n    else:\n        path_list = glob.glob(f'{args.ckpt_dir}/[!avg][!final]*.pdparams')\n        path_list = sorted(path_list, key=os.path.getmtime)\n        path_list = path_list[-args.num:]\n\n    print(path_list)\n\n    avg = None\n    num = args.num\n    assert num == len(path_list)\n    for path in path_list:\n        print(f'Processing {path}')\n        states = paddle.load(path)\n        if avg is None:\n            avg = states\n        else:\n            for k in avg.keys():\n                avg[k] += states[k]\n    # average\n    for k in avg.keys():\n        if avg[k] is not None:\n            avg[k] /= num\n\n    paddle.save(avg, args.dst_model)\n    print(f'Saving to {args.dst_model}')\n\n    meta_path = os.path.splitext(args.dst_model)[0] + '.avg.json'\n    with open(meta_path, 'w') as f:\n        data = json.dumps({\n            \"avg_ckpt\": args.dst_model,\n            \"ckpt\": path_list,\n            \"epoch\": selected_epochs.tolist(),\n            \"val_loss\": beat_val_scores.tolist(),\n        })\n        f.write(data + \"\\n\")\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='average model')\n    parser.add_argument('--dst_model', required=True, help='averaged model')\n    parser.add_argument(\n        '--ckpt_dir', required=True, help='ckpt model dir for average')\n    parser.add_argument(\n        '--val_best', action=\"store_true\", help='averaged model')\n    parser.add_argument(\n        '--num', default=5, type=int, help='nums for averaged model')\n    parser.add_argument(\n        '--min_epoch',\n        default=0,\n        type=int,\n        help='min epoch used for averaging model')\n    parser.add_argument(\n        '--max_epoch',\n        default=65536,  # Big enough\n        type=int,\n        help='max epoch used for averaging model')\n\n    args = parser.parse_args()\n    print(args)\n\n    main(args)\n"
  },
  {
    "path": "paddlespeech/text/exps/ernie_linear/punc_restore.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport re\n\nimport paddle\nimport yaml\nfrom paddlenlp.transformers import ErnieTokenizer\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.text.models.ernie_linear import ErnieLinear\n\nDefinedClassifier = {\n    'ErnieLinear': ErnieLinear,\n}\n\n\ndef _clean_text(text, punc_list):\n    text = text.lower()\n    text = re.sub('[^A-Za-z0-9\\u4e00-\\u9fa5]', '', text)\n    text = re.sub(f'[{\"\".join([p for p in punc_list][1:])}]', '', text)\n    return text\n\n\ndef preprocess(text, punc_list, tokenizer):\n    clean_text = _clean_text(text, punc_list)\n    assert len(clean_text) > 0, f'Invalid input string: {text}'\n    tokenized_input = tokenizer(\n        list(clean_text), return_length=True, is_split_into_words=True)\n    _inputs = dict()\n    _inputs['input_ids'] = tokenized_input['input_ids']\n    _inputs['seg_ids'] = tokenized_input['token_type_ids']\n    _inputs['seq_len'] = tokenized_input['seq_len']\n    return _inputs\n\n\ndef test(args):\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args), allow_unicode=True))\n    # print(args)\n    print(\"========Config========\")\n    print(config)\n\n    punc_list = []\n    with open(config[\"data_params\"][\"punc_path\"], 'r') as f:\n        for line in f:\n            punc_list.append(line.strip())\n\n    model = DefinedClassifier[config[\"model_type\"]](**config[\"model\"])\n    # print(model)\n\n    pretrained_token = config['data_params']['pretrained_token']\n    tokenizer = ErnieTokenizer.from_pretrained(pretrained_token)\n    # tokenizer = ErnieTokenizer.from_pretrained('ernie-1.0')\n\n    state_dict = paddle.load(args.checkpoint)\n    model.set_state_dict(state_dict[\"main_params\"])\n    model.eval()\n    _inputs = preprocess(args.text, punc_list, tokenizer)\n    seq_len = _inputs['seq_len']\n    input_ids = paddle.to_tensor(_inputs['input_ids']).unsqueeze(0)\n    seg_ids = paddle.to_tensor(_inputs['seg_ids']).unsqueeze(0)\n    logits, _ = model(input_ids, seg_ids)\n    preds = paddle.argmax(logits, axis=-1).squeeze(0)\n    tokens = tokenizer.convert_ids_to_tokens(\n        _inputs['input_ids'][1:seq_len - 1])\n    labels = preds[1:seq_len - 1].tolist()\n    assert len(tokens) == len(labels)\n    # add 0 for non punc\n    punc_list = [0] + punc_list\n    text = ''\n    for t, l in zip(tokens, labels):\n        text += t\n        if l != 0:  # Non punc.\n            text += punc_list[l]\n    print(\"Punctuation Restoration Result:\", text)\n    return text\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Run Punctuation Restoration.\")\n    parser.add_argument(\"--config\", type=str, help=\"ErnieLinear config file.\")\n    parser.add_argument(\"--checkpoint\", type=str, help=\"snapshot to load.\")\n    parser.add_argument(\"--text\", type=str, help=\"raw text to be restored.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    test(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/text/exps/ernie_linear/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\n\nimport numpy as np\nimport paddle\nimport pandas as pd\nimport yaml\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom sklearn.metrics import classification_report\nfrom sklearn.metrics import precision_recall_fscore_support\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.utils import str2bool\nfrom paddlespeech.text.models.ernie_linear import ErnieLinear\nfrom paddlespeech.text.models.ernie_linear import PuncDataset\nfrom paddlespeech.text.models.ernie_linear import PuncDatasetFromErnieTokenizer\n\nDefinedClassifier = {\n    'ErnieLinear': ErnieLinear,\n}\n\nDefinedLoss = {\n    \"ce\": nn.CrossEntropyLoss,\n}\n\nDefinedDataset = {\n    'Punc': PuncDataset,\n    'Ernie': PuncDatasetFromErnieTokenizer,\n}\n\n\ndef evaluation(y_pred, y_test):\n    precision, recall, f1, _ = precision_recall_fscore_support(\n        y_test, y_pred, average=None, labels=[1, 2, 3])\n    overall = precision_recall_fscore_support(\n        y_test, y_pred, average='macro', labels=[1, 2, 3])\n    result = pd.DataFrame(\n        np.array([precision, recall, f1]),\n        columns=list(['O', 'COMMA', 'PERIOD', 'QUESTION'])[1:],\n        index=['Precision', 'Recall', 'F1'])\n    result['OVERALL'] = overall[:3]\n    return result\n\n\ndef test(args):\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n\n    test_dataset = DefinedDataset[config[\"dataset_type\"]](\n        train_path=config[\"test_path\"], **config[\"data_params\"])\n    test_loader = DataLoader(\n        test_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False)\n    model = DefinedClassifier[config[\"model_type\"]](**config[\"model\"])\n    state_dict = paddle.load(args.checkpoint)\n    model.set_state_dict(state_dict[\"main_params\"])\n    model.eval()\n\n    punc_list = []\n    for i in range(len(test_loader.dataset.id2punc)):\n        punc_list.append(test_loader.dataset.id2punc[i])\n\n    test_total_label = []\n    test_total_predict = []\n\n    for i, batch in enumerate(test_loader):\n        input, label = batch\n        label = paddle.reshape(label, shape=[-1])\n        y, logit = model(input)\n        pred = paddle.argmax(logit, axis=1)\n        test_total_label.extend(label.numpy().tolist())\n        test_total_predict.extend(pred.numpy().tolist())\n    t = classification_report(\n        test_total_label, test_total_predict, target_names=punc_list)\n    print(t)\n    if args.print_eval:\n        t2 = evaluation(test_total_label, test_total_predict)\n        print('=========================================================')\n        print(t2)\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Test a ErnieLinear model.\")\n    parser.add_argument(\"--config\", type=str, help=\"ErnieLinear config file.\")\n    parser.add_argument(\"--checkpoint\", type=str, help=\"snapshot to load.\")\n    parser.add_argument(\"--print_eval\", type=str2bool, default=True)\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n\n    args = parser.parse_args()\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    test(args)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/text/exps/ernie_linear/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport logging\nimport os\nimport shutil\nfrom pathlib import Path\n\nimport paddle\nimport yaml\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle import nn\nfrom paddle.io import DataLoader\nfrom paddle.optimizer import Adam\nfrom paddle.optimizer.lr import ExponentialDecay\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.t2s.training.extensions.snapshot import Snapshot\nfrom paddlespeech.t2s.training.extensions.visualizer import VisualDL\nfrom paddlespeech.t2s.training.seeding import seed_everything\nfrom paddlespeech.t2s.training.trainer import Trainer\nfrom paddlespeech.text.models.ernie_linear import ErnieLinear\nfrom paddlespeech.text.models.ernie_linear import ErnieLinearEvaluator\nfrom paddlespeech.text.models.ernie_linear import ErnieLinearUpdater\nfrom paddlespeech.text.models.ernie_linear import PuncDataset\nfrom paddlespeech.text.models.ernie_linear import PuncDatasetFromErnieTokenizer\n\nDefinedClassifier = {\n    'ErnieLinear': ErnieLinear,\n}\n\nDefinedLoss = {\n    \"ce\": nn.CrossEntropyLoss,\n}\n\nDefinedDataset = {\n    'Punc': PuncDataset,\n    'Ernie': PuncDatasetFromErnieTokenizer,\n}\n\n\ndef train_sp(args, config):\n    # decides device type and whether to run in parallel\n    # setup running environment correctly\n    if (not paddle.is_compiled_with_cuda()) or args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    else:\n        paddle.set_device(\"gpu\")\n    world_size = paddle.distributed.get_world_size()\n    if world_size > 1:\n        paddle.distributed.init_parallel_env()\n\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    print(\n        f\"rank:{dist.get_rank()}, pid: {os.getpid()}, parent_pid: {os.getppid()}\"\n    )\n    # dataloader has been too verbose\n    logging.getLogger(\"DataLoader\").disabled = True\n    train_dataset = DefinedDataset[config[\"dataset_type\"]](\n        train_path=config[\"train_path\"], **config[\"data_params\"])\n    dev_dataset = DefinedDataset[config[\"dataset_type\"]](\n        train_path=config[\"dev_path\"], **config[\"data_params\"])\n    train_dataloader = DataLoader(\n        train_dataset,\n        shuffle=True,\n        num_workers=config.num_workers,\n        batch_size=config.batch_size)\n\n    dev_dataloader = DataLoader(\n        dev_dataset,\n        batch_size=config.batch_size,\n        shuffle=False,\n        drop_last=False,\n        num_workers=config.num_workers)\n\n    print(\"dataloaders done!\")\n\n    model = DefinedClassifier[config[\"model_type\"]](**config[\"model\"])\n\n    if world_size > 1:\n        model = DataParallel(model)\n    print(\"model done!\")\n\n    criterion = DefinedLoss[config[\"loss_type\"]](\n        **config[\"loss\"]) if \"loss_type\" in config else DefinedLoss[\"ce\"]()\n\n    print(\"criterions done!\")\n\n    lr_schedule = ExponentialDecay(**config[\"scheduler_params\"])\n    optimizer = Adam(\n        learning_rate=lr_schedule,\n        parameters=model.parameters(),\n        weight_decay=paddle.regularizer.L2Decay(\n            config[\"optimizer_params\"][\"weight_decay\"]))\n\n    print(\"optimizer done!\")\n\n    output_dir = Path(args.output_dir)\n    output_dir.mkdir(parents=True, exist_ok=True)\n    if dist.get_rank() == 0:\n        config_name = args.config.split(\"/\")[-1]\n        # copy conf to output_dir\n        shutil.copyfile(args.config, output_dir / config_name)\n\n    updater = ErnieLinearUpdater(\n        model=model,\n        criterion=criterion,\n        scheduler=lr_schedule,\n        optimizer=optimizer,\n        dataloader=train_dataloader,\n        output_dir=output_dir)\n\n    trainer = Trainer(updater, (config.max_epoch, 'epoch'), output_dir)\n\n    evaluator = ErnieLinearEvaluator(\n        model=model,\n        criterion=criterion,\n        dataloader=dev_dataloader,\n        output_dir=output_dir)\n\n    if dist.get_rank() == 0:\n        trainer.extend(evaluator, trigger=(1, \"epoch\"))\n        trainer.extend(VisualDL(output_dir), trigger=(1, \"iteration\"))\n    trainer.extend(\n        Snapshot(max_size=config.num_snapshots), trigger=(1, 'epoch'))\n    trainer.run()\n\n\ndef main():\n    # parse args and config and redirect to train_sp\n    parser = argparse.ArgumentParser(description=\"Train a ErnieLinear model.\")\n    parser.add_argument(\"--config\", type=str, help=\"ErnieLinear config file.\")\n    parser.add_argument(\"--output-dir\", type=str, help=\"output dir.\")\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n\n    args = parser.parse_args()\n\n    with open(args.config) as f:\n        config = CfgNode(yaml.safe_load(f))\n\n    print(\"========Args========\")\n    print(yaml.safe_dump(vars(args)))\n    print(\"========Config========\")\n    print(config)\n    print(\n        f\"master see the word size: {dist.get_world_size()}, from pid: {os.getpid()}\"\n    )\n\n    # dispatch\n    if args.ngpu > 1:\n        dist.spawn(train_sp, (args, config), nprocs=args.ngpu)\n    else:\n        train_sp(args, config)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "paddlespeech/text/models/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .ernie_crf import ErnieCrf\nfrom .ernie_linear import ErnieLinear\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_crf/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .model import ErnieCrf\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_crf/model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn as nn\nfrom paddlenlp.layers.crf import LinearChainCrf\nfrom paddlenlp.layers.crf import LinearChainCrfLoss\nfrom paddlenlp.layers.crf import ViterbiDecoder\nfrom paddlenlp.transformers import ErnieForTokenClassification\n\n\nclass ErnieCrf(nn.Layer):\n    def __init__(self,\n                 num_classes,\n                 pretrained_token='ernie-1.0',\n                 crf_lr=100,\n                 **kwargs):\n        super().__init__()\n        self.ernie = ErnieForTokenClassification.from_pretrained(\n            pretrained_token, num_labels=num_classes, **kwargs)\n        self.num_classes = num_classes\n        self.crf = LinearChainCrf(\n            self.num_classes, crf_lr=crf_lr, with_start_stop_tag=False)\n        self.crf_loss = LinearChainCrfLoss(self.crf)\n        self.viterbi_decoder = ViterbiDecoder(\n            self.crf.transitions, with_start_stop_tag=False)\n\n    def forward(self,\n                input_ids,\n                token_type_ids=None,\n                position_ids=None,\n                attention_mask=None,\n                lengths=None,\n                labels=None):\n        logits = self.ernie(\n            input_ids,\n            token_type_ids=token_type_ids,\n            attention_mask=attention_mask,\n            position_ids=position_ids)\n\n        if lengths is None:\n            lengths = paddle.ones(\n                shape=[input_ids.shape[0]],\n                dtype=paddle.int64) * input_ids.shape[1]\n\n        _, prediction = self.viterbi_decoder(logits, lengths)\n        prediction = prediction.reshape([-1])\n\n        if labels is not None:\n            labels = labels.reshape([input_ids.shape[0], -1])\n            loss = self.crf_loss(logits, lengths, labels)\n            avg_loss = paddle.mean(loss)\n            return avg_loss, prediction\n        else:\n            return prediction\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_linear/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom .dataset import *\nfrom .ernie_linear import *\nfrom .ernie_linear_updater import *\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_linear/dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\nfrom paddle.io import Dataset\nfrom paddlenlp.transformers import ErnieTokenizer\n\n__all__ = [\"PuncDataset\", \"PuncDatasetFromErnieTokenizer\"]\n\n\nclass PuncDataset(Dataset):\n    def __init__(self, train_path, vocab_path, punc_path, seq_len=100):\n        self.seq_len = seq_len\n\n        self.word2id = self.load_vocab(\n            vocab_path, extra_word_list=['<UNK>', '<END>'])\n        self.id2word = {v: k for k, v in self.word2id.items()}\n        self.punc2id = self.load_vocab(punc_path, extra_word_list=[\" \"])\n        self.id2punc = {k: v for (v, k) in self.punc2id.items()}\n\n        tmp_seqs = open(train_path, encoding='utf-8').readlines()\n        self.txt_seqs = [i for seq in tmp_seqs for i in seq.split()]\n        self.preprocess(self.txt_seqs)\n\n    def __len__(self):\n        \"\"\"return the sentence nums in .txt\n        \"\"\"\n        return self.in_len\n\n    def __getitem__(self, index):\n        return self.input_data[index], self.label[index]\n\n    def load_vocab(self, vocab_path, extra_word_list=[], encoding='utf-8'):\n        n = len(extra_word_list)\n        with open(vocab_path, encoding='utf-8') as vf:\n            vocab = {word.strip(): i + n for i, word in enumerate(vf)}\n        for i, word in enumerate(extra_word_list):\n            vocab[word] = i\n        return vocab\n\n    def preprocess(self, txt_seqs: list):\n        input_data = []\n        label = []\n        input_r = []\n        label_r = []\n\n        count = 0\n        length = len(txt_seqs)\n        for token in txt_seqs:\n            count += 1\n            if count == length:\n                break\n            if token in self.punc2id:\n                continue\n            punc = txt_seqs[count]\n            if punc not in self.punc2id:\n                label.append(self.punc2id[\" \"])\n                input_data.append(\n                    self.word2id.get(token, self.word2id[\"<UNK>\"]))\n                input_r.append(token)\n                label_r.append(' ')\n            else:\n                label.append(self.punc2id[punc])\n                input_data.append(\n                    self.word2id.get(token, self.word2id[\"<UNK>\"]))\n                input_r.append(token)\n                label_r.append(punc)\n        if len(input_data) != len(label):\n            assert 'error: length input_data != label'\n\n        self.in_len = len(input_data) // self.seq_len\n        len_tmp = self.in_len * self.seq_len\n        input_data = input_data[:len_tmp]\n        label = label[:len_tmp]\n\n        self.input_data = paddle.to_tensor(\n            np.array(input_data, dtype='int64').reshape(-1, self.seq_len))\n        self.label = paddle.to_tensor(\n            np.array(label, dtype='int64').reshape(-1, self.seq_len))\n\n\nclass PuncDatasetFromErnieTokenizer(Dataset):\n    def __init__(self,\n                 train_path,\n                 punc_path,\n                 pretrained_token='ernie-1.0',\n                 seq_len=100):\n        self.tokenizer = ErnieTokenizer.from_pretrained(pretrained_token)\n        self.paddingID = self.tokenizer.pad_token_id\n        self.seq_len = seq_len\n        self.punc2id = self.load_vocab(punc_path, extra_word_list=[\" \"])\n        self.id2punc = {k: v for (v, k) in self.punc2id.items()}\n        tmp_seqs = open(train_path, encoding='utf-8').readlines()\n        self.txt_seqs = [i for seq in tmp_seqs for i in seq.split()]\n        self.preprocess(self.txt_seqs)\n\n    def __len__(self):\n        return self.in_len\n\n    def __getitem__(self, index):\n        return self.input_data[index], self.label[index]\n\n    def load_vocab(self, vocab_path, extra_word_list=[], encoding='utf-8'):\n        n = len(extra_word_list)\n        with open(vocab_path, encoding='utf-8') as vf:\n            vocab = {word.strip(): i + n for i, word in enumerate(vf)}\n        for i, word in enumerate(extra_word_list):\n            vocab[word] = i\n        return vocab\n\n    def preprocess(self, txt_seqs: list):\n        input_data = []\n        label = []\n        count = 0\n        print(\"Preprocessing in PuncDatasetFromErnieTokenizer...\")\n        for i in range(len(txt_seqs) - 1):\n            word = txt_seqs[i]\n            punc = txt_seqs[i + 1]\n            if word in self.punc2id:\n                continue\n\n            token = self.tokenizer(word)\n            x = token[\"input_ids\"][1:-1]\n            input_data.extend(x)\n\n            for i in range(len(x) - 1):\n                label.append(self.punc2id[\" \"])\n\n            if punc not in self.punc2id:\n                label.append(self.punc2id[\" \"])\n            else:\n                label.append(self.punc2id[punc])\n\n        if len(input_data) != len(label):\n            assert 'error: length input_data != label'\n\n        self.in_len = len(input_data) // self.seq_len\n        len_tmp = self.in_len * self.seq_len\n        input_data = input_data[:len_tmp]\n        label = label[:len_tmp]\n        self.input_data = np.array(\n            input_data, dtype='int64').reshape(-1, self.seq_len)\n        self.label = np.array(label, dtype='int64').reshape(-1, self.seq_len)\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_linear/ernie_linear.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport paddle\nimport paddle.nn as nn\nfrom paddlenlp.transformers import ErnieForTokenClassification\n\n\nclass ErnieLinear(nn.Layer):\n    def __init__(self,\n                 num_classes=None,\n                 pretrained_token='ernie-1.0',\n                 cfg_path=None,\n                 ckpt_path=None,\n                 **kwargs):\n        super(ErnieLinear, self).__init__()\n\n        if cfg_path is not None and ckpt_path is not None:\n            cfg_path = os.path.abspath(os.path.expanduser(cfg_path))\n            ckpt_path = os.path.abspath(os.path.expanduser(ckpt_path))\n\n            assert os.path.isfile(\n                cfg_path), 'Config file is not valid: {}'.format(cfg_path)\n            assert os.path.isfile(\n                ckpt_path), 'Checkpoint file is not valid: {}'.format(ckpt_path)\n\n            self.ernie = ErnieForTokenClassification.from_pretrained(\n                os.path.dirname(cfg_path))\n        else:\n            assert isinstance(\n                num_classes, int\n            ) and num_classes > 0, 'Argument `num_classes` must be an integer.'\n            self.ernie = ErnieForTokenClassification.from_pretrained(\n                pretrained_token, num_labels=num_classes, **kwargs)\n\n        self.num_classes = self.ernie.num_labels\n        self.softmax = nn.Softmax()\n\n    def forward(self,\n                input_ids,\n                token_type_ids=None,\n                position_ids=None,\n                attention_mask=None):\n        y = self.ernie(\n            input_ids,\n            token_type_ids=token_type_ids,\n            attention_mask=attention_mask,\n            position_ids=position_ids)\n\n        y = paddle.reshape(y, shape=[-1, self.num_classes])\n        logits = self.softmax(y)\n\n        return y, logits\n"
  },
  {
    "path": "paddlespeech/text/models/ernie_linear/ernie_linear_updater.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\n\nimport paddle\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn import Layer\nfrom paddle.optimizer import Optimizer\nfrom paddle.optimizer.lr import LRScheduler\nfrom sklearn.metrics import f1_score\n\nfrom paddlespeech.t2s.training.extensions.evaluator import StandardEvaluator\nfrom paddlespeech.t2s.training.reporter import report\nfrom paddlespeech.t2s.training.updaters.standard_updater import StandardUpdater\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',\n    datefmt='[%Y-%m-%d %H:%M:%S]')\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logging.INFO)\n\n\nclass ErnieLinearUpdater(StandardUpdater):\n    def __init__(self,\n                 model: Layer,\n                 criterion: Layer,\n                 scheduler: LRScheduler,\n                 optimizer: Optimizer,\n                 dataloader: DataLoader,\n                 output_dir=None):\n        super().__init__(model, optimizer, dataloader, init_state=None)\n        self.model = model\n        self.dataloader = dataloader\n\n        self.criterion = criterion\n        self.scheduler = scheduler\n        self.optimizer = optimizer\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def update_core(self, batch):\n        self.msg = \"Rank: {}, \".format(dist.get_rank())\n        losses_dict = {}\n\n        input, label = batch\n        label = paddle.reshape(label, shape=[-1])\n        y, logit = self.model(input)\n        pred = paddle.argmax(logit, axis=1)\n\n        loss = self.criterion(y, label)\n\n        self.optimizer.clear_grad()\n        loss.backward()\n\n        self.optimizer.step()\n        self.scheduler.step()\n\n        F1_score = f1_score(\n            label.numpy().tolist(), pred.numpy().tolist(), average=\"macro\")\n\n        report(\"train/loss\", float(loss))\n        losses_dict[\"loss\"] = float(loss)\n        report(\"train/F1_score\", float(F1_score))\n        losses_dict[\"F1_score\"] = float(F1_score)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n\n\nclass ErnieLinearEvaluator(StandardEvaluator):\n    def __init__(self,\n                 model: Layer,\n                 criterion: Layer,\n                 dataloader: DataLoader,\n                 output_dir=None):\n        super().__init__(model, dataloader)\n        self.model = model\n        self.criterion = criterion\n        self.dataloader = dataloader\n\n        log_file = output_dir / 'worker_{}.log'.format(dist.get_rank())\n        self.filehandler = logging.FileHandler(str(log_file))\n        logger.addHandler(self.filehandler)\n        self.logger = logger\n        self.msg = \"\"\n\n    def evaluate_core(self, batch):\n        self.msg = \"Evaluate: \"\n        losses_dict = {}\n\n        input, label = batch\n        label = paddle.reshape(label, shape=[-1])\n        y, logit = self.model(input)\n        pred = paddle.argmax(logit, axis=1)\n\n        loss = self.criterion(y, label)\n\n        F1_score = f1_score(\n            label.numpy().tolist(), pred.numpy().tolist(), average=\"macro\")\n\n        report(\"eval/loss\", float(loss))\n        losses_dict[\"loss\"] = float(loss)\n        report(\"eval/F1_score\", float(F1_score))\n        losses_dict[\"F1_score\"] = float(F1_score)\n\n        self.msg += ', '.join('{}: {:>.6f}'.format(k, v)\n                              for k, v in losses_dict.items())\n        self.logger.info(self.msg)\n"
  },
  {
    "path": "paddlespeech/utils/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom packaging.version import Version\n\n\ndef satisfy_version(source: str, target: str, dev_allowed: bool=True) -> bool:\n    if dev_allowed and source.startswith('0.0.0'):\n        target_version = Version('0.0.0')\n    else:\n        target_version = Version(target)\n\n    source_version = Version(source)\n    return source_version >= target_version\n\n\ndef satisfy_paddle_version(target: str, dev_allowed: bool=True) -> bool:\n    import paddle\n    return satisfy_version(paddle.__version__, target, dev_allowed)\n"
  },
  {
    "path": "paddlespeech/utils/argparse.py",
    "content": "# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport hashlib\nimport os\nimport sys\nfrom typing import Text\n\nimport distutils\n\n__all__ = [\n    \"print_arguments\", \"add_arguments\", \"get_commandline_args\", \"strtobool\"\n]\n\n\ndef get_commandline_args():\n    extra_chars = [\n        \" \",\n        \";\",\n        \"&\",\n        \"(\",\n        \")\",\n        \"|\",\n        \"^\",\n        \"<\",\n        \">\",\n        \"?\",\n        \"*\",\n        \"[\",\n        \"]\",\n        \"$\",\n        \"`\",\n        '\"',\n        \"\\\\\",\n        \"!\",\n        \"{\",\n        \"}\",\n    ]\n\n    # Escape the extra characters for shell\n    argv = [\n        arg.replace(\"'\", \"'\\\\''\") if all(char not in arg\n                                         for char in extra_chars) else\n        \"'\" + arg.replace(\"'\", \"'\\\\''\") + \"'\" for arg in sys.argv\n    ]\n\n    return sys.executable + \" \" + \" \".join(argv)\n\n\ndef print_arguments(args, info=None):\n    \"\"\"Print argparse's arguments.\n\n    Usage:\n\n    .. code-block:: python\n\n        parser = argparse.ArgumentParser()\n        parser.add_argument(\"name\", default=\"Jonh\", type=str, help=\"User name.\")\n        args = parser.parse_args()\n        print_arguments(args)\n\n    :param args: Input argparse.Namespace for printing.\n    :type args: argparse.Namespace\n    \"\"\"\n    filename = \"\"\n    if info:\n        filename = info[\"__file__\"]\n    filename = os.path.basename(filename)\n    print(f\"----------- {filename} Configuration Arguments -----------\")\n    for arg, value in sorted(vars(args).items()):\n        print(\"%s: %s\" % (arg, value))\n    print(\"-----------------------------------------------------------\")\n\n\ndef strtobool(value):\n    \"\"\"Convert a string value to an integer boolean (1 for True, 0 for False).\n\n    The function recognizes the following strings as True (case insensitive):\n    - \"yes\"\n    - \"true\"\n    - \"1\"\n\n    All other values are considered False.\n\n    NOTE: After Python 3.10, the distutils module, particularly distutils.util, has been partially deprecated. To maintain compatibility with existing code, the strtobool function implemented here.\n    \"\"\"\n    if isinstance(value, bool):\n        return int(value)\n    value = value.strip().lower()\n    if value in ('yes', 'true', '1'):\n        return 1\n    else:\n        return 0\n\n\ndef add_arguments(argname, type, default, help, argparser, **kwargs):\n    \"\"\"Add argparse's argument.\n\n    Usage:\n\n    .. code-block:: python\n\n        parser = argparse.ArgumentParser()\n        add_argument(\"name\", str, \"Jonh\", \"User name.\", parser)\n        args = parser.parse_args()\n    \"\"\"\n    type = strtobool if type == bool else type\n    argparser.add_argument(\n        \"--\" + argname,\n        default=default,\n        type=type,\n        help=help + ' Default: %(default)s.',\n        **kwargs)\n"
  },
  {
    "path": "paddlespeech/utils/dynamic_import.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from espnet(https://github.com/espnet/espnet)\nimport importlib\n\n__all__ = [\"dynamic_import\"]\n\n\ndef dynamic_import(import_path, alias=dict()):\n    \"\"\"dynamic import module and class\n\n    :param str import_path: syntax 'module_name:class_name'\n        e.g., 'paddlespeech.s2t.models.u2:U2Model'\n    :param dict alias: shortcut for registered class\n    :return: imported class\n    \"\"\"\n    if import_path not in alias and \":\" not in import_path:\n        raise ValueError(\n            \"import_path should be one of {} or \"\n            'include \":\", e.g. \"paddlespeech.s2t.models.u2:U2Model\" : '\n            \"{}\".format(set(alias), import_path))\n    if \":\" not in import_path:\n        import_path = alias[import_path]\n\n    module_name, objname = import_path.split(\":\")\n    m = importlib.import_module(module_name)\n    return getattr(m, objname)\n"
  },
  {
    "path": "paddlespeech/utils/env.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\n\ndef _get_user_home():\n    return os.path.expanduser('~')\n\n\ndef _get_paddlespcceh_home():\n    if 'PPSPEECH_HOME' in os.environ:\n        home_path = os.environ['PPSPEECH_HOME']\n        if os.path.exists(home_path):\n            if os.path.isdir(home_path):\n                return home_path\n            else:\n                raise RuntimeError(\n                    'The environment variable PPSPEECH_HOME {} is not a directory.'.\n                    format(home_path))\n        else:\n            return home_path\n    return os.path.join(_get_user_home(), '.paddlespeech')\n\n\ndef _get_sub_home(directory):\n    home = os.path.join(_get_paddlespcceh_home(), directory)\n    if not os.path.exists(home):\n        os.makedirs(home)\n    return home\n\n\nPPSPEECH_HOME = _get_paddlespcceh_home()\nMODEL_HOME = _get_sub_home('models')\nCONF_HOME = _get_sub_home('conf')\nDATA_HOME = _get_sub_home('datasets')\n"
  },
  {
    "path": "paddlespeech/utils/initialize.py",
    "content": "#   Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis code is based on https://github.com/pytorch/pytorch/blob/master/torch/nn/init.py\nThs copyright of pytorch/pytorch is a BSD-style license, as found in the LICENSE file.\n\"\"\"\nimport math\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\n\n__all__ = [\n    \"uniform_\",\n    \"normal_\",\n    \"constant_\",\n    \"ones_\",\n    \"zeros_\",\n    \"xavier_uniform_\",\n    \"xavier_normal_\",\n    \"kaiming_uniform_\",\n    \"kaiming_normal_\",\n    \"linear_init_\",\n    \"conv_init_\",\n    \"reset_initialized_parameter\",\n    \"_calculate_fan_in_and_fan_out\",\n]\n\n\ndef _no_grad_uniform_(tensor, a, b):\n    with paddle.no_grad():\n        tensor.set_value(\n            paddle.uniform(\n                shape=tensor.shape, dtype=tensor.dtype, min=a, max=b))\n    return tensor\n\n\ndef _no_grad_normal_(tensor, mean=0.0, std=1.0):\n    with paddle.no_grad():\n        tensor.set_value(paddle.normal(mean=mean, std=std, shape=tensor.shape))\n    return tensor\n\n\ndef _no_grad_fill_(tensor, value=0.0):\n    with paddle.no_grad():\n        tensor.set_value(paddle.full_like(tensor, value, dtype=tensor.dtype))\n    return tensor\n\n\ndef uniform_(tensor, a, b):\n    \"\"\"\n    Modified tensor inspace using uniform_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        a (float|int): min value.\n        b (float|int): max value.\n    Return:\n        tensor\n    \"\"\"\n    return _no_grad_uniform_(tensor, a, b)\n\n\ndef normal_(tensor, mean=0.0, std=1.0):\n    \"\"\"\n    Modified tensor inspace using normal_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        mean (float|int): mean value.\n        std (float|int): std value.\n    Return:\n        tensor\n    \"\"\"\n    return _no_grad_normal_(tensor, mean, std)\n\n\ndef constant_(tensor, value=0.0):\n    \"\"\"\n    Modified tensor inspace using constant_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        value (float|int): value to fill tensor.\n    Return:\n        tensor\n    \"\"\"\n    return _no_grad_fill_(tensor, value)\n\n\ndef ones_(tensor):\n    \"\"\"\n    Modified tensor inspace using ones_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n    Return:\n        tensor\n    \"\"\"\n    return _no_grad_fill_(tensor, 1)\n\n\ndef zeros_(tensor):\n    \"\"\"\n    Modified tensor inspace using zeros_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n    Return:\n        tensor\n    \"\"\"\n    return _no_grad_fill_(tensor, 0)\n\n\ndef vector_(tensor, vector):\n    with paddle.no_grad():\n        tensor.set_value(paddle.to_tensor(vector, dtype=tensor.dtype))\n    return tensor\n\n\ndef _calculate_fan_in_and_fan_out(tensor, reverse=False):\n    \"\"\"\n    Calculate (fan_in, _fan_out) for tensor\n    Args:\n        tensor (Tensor): paddle.Tensor\n        reverse (bool: False): tensor data format order, False by default as [fout, fin, ...]. e.g. : conv.weight [cout, cin, kh, kw] is False; linear.weight [cin, cout] is True\n    Return:\n        Tuple[fan_in, fan_out]\n    \"\"\"\n    if tensor.ndim < 2:\n        raise ValueError(\n            \"Fan in and fan out can not be computed for tensor with fewer than 2 dimensions\"\n        )\n\n    if reverse:\n        num_input_fmaps, num_output_fmaps = tensor.shape[0], tensor.shape[1]\n    else:\n        num_input_fmaps, num_output_fmaps = tensor.shape[1], tensor.shape[0]\n\n    receptive_field_size = 1\n    if tensor.ndim > 2:\n        receptive_field_size = np.prod(tensor.shape[2:])\n\n    fan_in = num_input_fmaps * receptive_field_size\n    fan_out = num_output_fmaps * receptive_field_size\n\n    return fan_in, fan_out\n\n\ndef xavier_uniform_(tensor, gain=1.0, reverse=False):\n    \"\"\"\n    Modified tensor inspace using xavier_uniform_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        gain (float): super parameter, 1. default.\n        reverse (bool):  reverse (bool: False): tensor data format order, False by default as [fout, fin, ...].\n    Return:\n        tensor\n    \"\"\"\n    fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor, reverse=reverse)\n    std = gain * math.sqrt(2.0 / float(fan_in + fan_out))\n    k = math.sqrt(3.0) * std\n    return _no_grad_uniform_(tensor, -k, k)\n\n\ndef xavier_normal_(tensor, gain=1.0, reverse=False):\n    \"\"\"\n    Modified tensor inspace using xavier_normal_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        gain (float): super parameter, 1. default.\n        reverse (bool):  reverse (bool: False): tensor data format order, False by default as [fout, fin, ...].\n    Return:\n        tensor\n    \"\"\"\n    fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor, reverse=reverse)\n    std = gain * math.sqrt(2.0 / float(fan_in + fan_out))\n    return _no_grad_normal_(tensor, 0, std)\n\n\n# reference: https://pytorch.org/docs/stable/_modules/torch/nn/init.html\ndef _calculate_correct_fan(tensor, mode, reverse=False):\n    mode = mode.lower()\n    valid_modes = [\"fan_in\", \"fan_out\"]\n    if mode not in valid_modes:\n        raise ValueError(\"Mode {} not supported, please use one of {}\".format(\n            mode, valid_modes))\n\n    fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor, reverse)\n\n    return fan_in if mode == \"fan_in\" else fan_out\n\n\ndef _calculate_gain(nonlinearity, param=None):\n    linear_fns = [\n        \"linear\", \"conv1d\", \"conv2d\", \"conv3d\", \"conv_transpose1d\",\n        \"conv_transpose2d\", \"conv_transpose3d\"\n    ]\n    if nonlinearity in linear_fns or nonlinearity == \"sigmoid\":\n        return 1\n    elif nonlinearity == \"tanh\":\n        return 5.0 / 3\n    elif nonlinearity == \"relu\":\n        return math.sqrt(2.0)\n    elif nonlinearity == \"leaky_relu\":\n        if param is None:\n            negative_slope = 0.01\n        elif not isinstance(param, bool) and isinstance(\n                param, int) or isinstance(param, float):\n            # True/False are instances of int, hence check above\n            negative_slope = param\n        else:\n            raise ValueError(\n                \"negative_slope {} not a valid number\".format(param))\n        return math.sqrt(2.0 / (1 + negative_slope**2))\n    elif nonlinearity == \"selu\":\n        return 3.0 / 4\n    else:\n        raise ValueError(\"Unsupported nonlinearity {}\".format(nonlinearity))\n\n\ndef kaiming_uniform_(tensor,\n                     a=0,\n                     mode=\"fan_in\",\n                     nonlinearity=\"leaky_relu\",\n                     reverse=False):\n    \"\"\"\n    Modified tensor inspace using kaiming_uniform method\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        mode (str): ['fan_in', 'fan_out'], 'fin_in' default\n        nonlinearity (str): nonlinearity method name\n        reverse (bool):  reverse (bool: False): tensor data format order, False by default as [fout, fin, ...].\n    Return:\n        tensor\n    \"\"\"\n    fan = _calculate_correct_fan(tensor, mode, reverse)\n    gain = _calculate_gain(nonlinearity, a)\n    std = gain / math.sqrt(fan)\n    k = math.sqrt(3.0) * std\n    return _no_grad_uniform_(tensor, -k, k)\n\n\ndef kaiming_normal_(tensor,\n                    a=0,\n                    mode=\"fan_in\",\n                    nonlinearity=\"leaky_relu\",\n                    reverse=False):\n    \"\"\"\n    Modified tensor inspace using kaiming_normal_\n    Args:\n        tensor (paddle.Tensor): paddle Tensor\n        mode (str): ['fan_in', 'fan_out'], 'fin_in' default\n        nonlinearity (str): nonlinearity method name\n        reverse (bool):  reverse (bool: False): tensor data format order, False by default as [fout, fin, ...].\n    Return:\n        tensor\n    \"\"\"\n    fan = _calculate_correct_fan(tensor, mode, reverse)\n    gain = _calculate_gain(nonlinearity, a)\n    std = gain / math.sqrt(fan)\n    return _no_grad_normal_(tensor, 0, std)\n\n\ndef linear_init_(module):\n    bound = 1 / math.sqrt(module.weight.shape[0])\n    uniform_(module.weight, -bound, bound)\n    uniform_(module.bias, -bound, bound)\n\n\ndef conv_init_(module):\n    bound = 1 / np.sqrt(np.prod(module.weight.shape[1:]))\n    uniform_(module.weight, -bound, bound)\n    if module.bias is not None:\n        uniform_(module.bias, -bound, bound)\n\n\ndef bias_init_with_prob(prior_prob=0.01):\n    \"\"\"initialize conv/fc bias value according to a given probability value.\"\"\"\n    bias_init = float(-np.log((1 - prior_prob) / prior_prob))\n    return bias_init\n\n\n@paddle.no_grad()\ndef reset_initialized_parameter(model, include_self=True):\n    \"\"\"\n    Reset initialized parameter using following method for [conv, linear, embedding, bn]\n    Args:\n        model (paddle.Layer): paddle Layer\n        include_self (bool: False): include_self for Layer.named_sublayers method. Indicate whether including itself\n    Return:\n        None\n    \"\"\"\n    for _, m in model.named_sublayers(include_self=include_self):\n        if isinstance(m, nn.Conv2D):\n            k = float(m._groups) / (m._in_channels * m._kernel_size[0] *\n                                    m._kernel_size[1])\n            k = math.sqrt(k)\n            _no_grad_uniform_(m.weight, -k, k)\n            if hasattr(m, \"bias\") and getattr(m, \"bias\") is not None:\n                _no_grad_uniform_(m.bias, -k, k)\n\n        elif isinstance(m, nn.Linear):\n            k = math.sqrt(1.0 / m.weight.shape[0])\n            _no_grad_uniform_(m.weight, -k, k)\n            if hasattr(m, \"bias\") and getattr(m, \"bias\") is not None:\n                _no_grad_uniform_(m.bias, -k, k)\n\n        elif isinstance(m, nn.Embedding):\n            _no_grad_normal_(m.weight, mean=0.0, std=1.0)\n\n        elif isinstance(m, (nn.BatchNorm2D, nn.LayerNorm)):\n            _no_grad_fill_(m.weight, 1.0)\n            if hasattr(m, \"bias\") and getattr(m, \"bias\") is not None:\n                _no_grad_fill_(m.bias, 0)\n"
  },
  {
    "path": "paddlespeech/vector/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/cluster/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/cluster/diarization.py",
    "content": "# Copyright (c) 2022 PaddlePaddle and SpeechBrain Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# Modified from speechbrain(https://github.com/speechbrain/speechbrain)\n\"\"\"\nThis script contains basic functions used for speaker diarization.\nThis script has an optional dependency on open source sklearn library.\nA few sklearn functions are modified in this script as per requirement.\n\"\"\"\nimport argparse\nimport copy\nimport warnings\n\nimport numpy as np\nimport scipy\nimport sklearn\nfrom scipy import linalg\nfrom scipy import sparse\nfrom scipy.sparse.csgraph import connected_components\nfrom scipy.sparse.csgraph import laplacian as csgraph_laplacian\nfrom scipy.sparse.linalg import eigsh\nfrom sklearn.cluster import SpectralClustering\nfrom sklearn.cluster._kmeans import k_means\nfrom sklearn.neighbors import kneighbors_graph\n\nfrom paddlespeech.utils.argparse import strtobool\n\n\ndef _graph_connected_component(graph, node_id):\n    \"\"\"\n    Find the largest graph connected components that contains one\n    given node.\n\n    Arguments\n    ---------\n    graph : array-like, shape: (n_samples, n_samples)\n        Adjacency matrix of the graph, non-zero weight means an edge\n        between the nodes.\n    node_id : int\n        The index of the query node of the graph.\n\n    Returns\n    -------\n    connected_components_matrix : array-like\n        shape - (n_samples,).\n        An array of bool value indicating the indexes of the nodes belonging\n        to the largest connected components of the given query node.\n    \"\"\"\n\n    n_node = graph.shape[0]\n    if sparse.issparse(graph):\n        # speed up row-wise access to boolean connection mask\n        graph = graph.tocsr()\n    connected_nodes = np.zeros(n_node, dtype=bool)\n    nodes_to_explore = np.zeros(n_node, dtype=bool)\n    nodes_to_explore[node_id] = True\n    for _ in range(n_node):\n        last_num_component = connected_nodes.sum()\n        np.logical_or(connected_nodes, nodes_to_explore, out=connected_nodes)\n        if last_num_component >= connected_nodes.sum():\n            break\n        indices = np.where(nodes_to_explore)[0]\n        nodes_to_explore.fill(False)\n        for i in indices:\n            if sparse.issparse(graph):\n                neighbors = graph[i].toarray().ravel()\n            else:\n                neighbors = graph[i]\n            np.logical_or(nodes_to_explore, neighbors, out=nodes_to_explore)\n    return connected_nodes\n\n\ndef _graph_is_connected(graph):\n    \"\"\"\n    Return whether the graph is connected (True) or Not (False)\n\n    Arguments\n    ---------\n    graph : array-like or sparse matrix, shape: (n_samples, n_samples)\n        Adjacency matrix of the graph, non-zero weight means an edge between the nodes.\n\n    Returns\n    -------\n    is_connected : bool\n        True means the graph is fully connected and False means not.\n    \"\"\"\n\n    if sparse.isspmatrix(graph):\n        # sparse graph, find all the connected components\n        n_connected_components, _ = connected_components(graph)\n        return n_connected_components == 1\n    else:\n        # dense graph, find all connected components start from node 0\n        return _graph_connected_component(graph, 0).sum() == graph.shape[0]\n\n\ndef _set_diag(laplacian, value, norm_laplacian):\n    \"\"\"\n    Set the diagonal of the laplacian matrix and convert it to a sparse\n    format well suited for eigenvalue decomposition.\n\n    Arguments\n    ---------\n    laplacian : array or sparse matrix\n        The graph laplacian.\n    value : float\n        The value of the diagonal.\n    norm_laplacian : bool\n        Whether the value of the diagonal should be changed or not.\n\n    Returns\n    -------\n    laplacian : array or sparse matrix\n        An array of matrix in a form that is well suited to fast eigenvalue\n        decomposition, depending on the bandwidth of the matrix.\n    \"\"\"\n\n    n_nodes = laplacian.shape[0]\n    # We need all entries in the diagonal to values\n    if not sparse.isspmatrix(laplacian):\n        if norm_laplacian:\n            laplacian.flat[::n_nodes + 1] = value\n    else:\n        laplacian = laplacian.tocoo()\n        if norm_laplacian:\n            diag_idx = laplacian.row == laplacian.col\n            laplacian.data[diag_idx] = value\n        # If the matrix has a small number of diagonals (as in the\n        # case of structured matrices coming from images), the\n        # dia format might be best suited for matvec products:\n        n_diags = np.unique(laplacian.row - laplacian.col).size\n        if n_diags <= 7:\n            # 3 or less outer diagonals on each side\n            laplacian = laplacian.todia()\n        else:\n            # csr has the fastest matvec and is thus best suited to\n            # arpack\n            laplacian = laplacian.tocsr()\n    return laplacian\n\n\ndef _deterministic_vector_sign_flip(u):\n    \"\"\"\n    Modify the sign of vectors for reproducibility. Flips the sign of\n    elements of all the vectors (rows of u) such that the absolute\n    maximum element of each vector is positive.\n\n    Arguments\n    ---------\n    u : ndarray\n        Array with vectors as its rows.\n\n    Returns\n    -------\n    u_flipped : ndarray\n        Array with the sign flipped vectors as its rows. The same shape as `u`.\n    \"\"\"\n\n    max_abs_rows = np.argmax(np.abs(u), axis=1)\n    signs = np.sign(u[range(u.shape[0]), max_abs_rows])\n    u *= signs[:, np.newaxis]\n    return u\n\n\ndef _check_random_state(seed):\n    \"\"\"\n    Turn seed into a np.random.RandomState instance.\n\n    Arguments\n    ---------\n    seed : None | int | instance of RandomState\n        If seed is None, return the RandomState singleton used by np.random.\n        If seed is an int, return a new RandomState instance seeded with seed.\n        If seed is already a RandomState instance, return it.\n        Otherwise raise ValueError.\n    \"\"\"\n\n    if seed is None or seed is np.random:\n        return np.random.mtrand._rand\n    if isinstance(seed, numbers.Integral):\n        return np.random.RandomState(seed)\n    if isinstance(seed, np.random.RandomState):\n        return seed\n    raise ValueError(\"%r cannot be used to seed a np.random.RandomState\"\n                     \" instance\" % seed)\n\n\ndef spectral_embedding(\n        adjacency,\n        n_components=8,\n        norm_laplacian=True,\n        drop_first=True, ):\n    \"\"\"\n    Returns spectral embeddings.\n\n    Arguments\n    ---------\n    adjacency : array-like or sparse graph\n        shape - (n_samples, n_samples)\n        The adjacency matrix of the graph to embed.\n    n_components : int\n        The dimension of the projection subspace.\n    norm_laplacian : bool\n        If True, then compute normalized Laplacian.\n    drop_first : bool\n        Whether to drop the first eigenvector.\n\n    Returns\n    -------\n    embedding : array\n        Spectral embeddings for each sample.\n\n    Example\n    -------\n    >>> import numpy as np\n    >>> import diarization as diar\n    >>> affinity = np.array([[1, 1, 1, 0.5, 0, 0, 0, 0, 0, 0.5],\n    ... [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\n    ... [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\n    ... [0.5, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0.5, 0, 0, 0, 0, 0, 1, 1, 1, 1]])\n    >>> embs = diar.spectral_embedding(affinity, 3)\n    >>> # Notice similar embeddings\n    >>> print(np.around(embs , decimals=3))\n    [[ 0.075  0.244  0.285]\n     [ 0.083  0.356 -0.203]\n     [ 0.083  0.356 -0.203]\n     [ 0.26  -0.149  0.154]\n     [ 0.29  -0.218 -0.11 ]\n     [ 0.29  -0.218 -0.11 ]\n     [-0.198 -0.084 -0.122]\n     [-0.198 -0.084 -0.122]\n     [-0.198 -0.084 -0.122]\n     [-0.167 -0.044  0.316]]\n    \"\"\"\n\n    # Whether to drop the first eigenvector\n    if drop_first:\n        n_components = n_components + 1\n\n    if not _graph_is_connected(adjacency):\n        warnings.warn(\"Graph is not fully connected, spectral embedding\"\n                      \" may not work as expected.\")\n\n    laplacian, dd = csgraph_laplacian(\n        adjacency, normed=norm_laplacian, return_diag=True)\n\n    laplacian = _set_diag(laplacian, 1, norm_laplacian)\n\n    laplacian *= -1\n\n    vals, diffusion_map = eigsh(\n        laplacian,\n        k=n_components,\n        sigma=1.0,\n        which=\"LM\", )\n\n    embedding = diffusion_map.T[n_components::-1]\n\n    if norm_laplacian:\n        embedding = embedding / dd\n\n    embedding = _deterministic_vector_sign_flip(embedding)\n    if drop_first:\n        return embedding[1:n_components].T\n    else:\n        return embedding[:n_components].T\n\n\ndef spectral_clustering(\n        affinity,\n        n_clusters=8,\n        n_components=None,\n        random_state=None,\n        n_init=10, ):\n    \"\"\"\n    Performs spectral clustering.\n\n    Arguments\n    ---------\n    affinity : matrix\n        Affinity matrix.\n    n_clusters : int\n        Number of clusters for kmeans.\n    n_components : int\n        Number of components to retain while estimating spectral embeddings.\n    random_state : int\n        A pseudo random number generator used by kmeans.\n     n_init : int\n        Number of time the k-means algorithm will be run with different centroid seeds.\n\n    Returns\n    -------\n    labels : array\n        Cluster label for each sample.\n\n    Example\n    -------\n    >>> import numpy as np\n    >>> diarization as diar\n    >>> affinity = np.array([[1, 1, 1, 0.5, 0, 0, 0, 0, 0, 0.5],\n    ... [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\n    ... [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\n    ... [0.5, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\n    ... [0.5, 0, 0, 0, 0, 0, 1, 1, 1, 1]])\n    >>> labs = diar.spectral_clustering(affinity, 3)\n    >>> # print (labs) # [2 2 2 1 1 1 0 0 0 0]\n    \"\"\"\n\n    random_state = _check_random_state(random_state)\n    n_components = n_clusters if n_components is None else n_components\n\n    maps = spectral_embedding(\n        affinity,\n        n_components=n_components,\n        drop_first=False, )\n\n    _, labels, _ = k_means(\n        maps, n_clusters, random_state=random_state, n_init=n_init)\n\n    return labels\n\n\nclass EmbeddingMeta:\n    \"\"\"\n    A utility class to pack deep embeddings and meta-information in one object.\n\n    Arguments\n    ---------\n    segset : list\n        List of session IDs as an array of strings.\n    modelset : list\n        List of model IDs as an array of strings.\n    stats : tensor\n        An ndarray of float64. Each line contains embedding\n        from the corresponding session.\n    \"\"\"\n\n    def __init__(\n            self,\n            segset=None,\n            modelset=None,\n            stats=None, ):\n\n        if segset is None:\n            self.segset = np.empty(0, dtype=\"|O\")\n            self.modelset = np.empty(0, dtype=\"|O\")\n            self.stats = np.array([], dtype=np.float64)\n        else:\n            self.segset = segset\n            self.modelset = modelset\n            self.stats = stats\n\n        self.stat0 = np.array([[1.0]] * self.stats.shape[0])\n\n    def norm_stats(self):\n        \"\"\"\n        Divide all first-order statistics by their Euclidean norm.\n        \"\"\"\n\n        vect_norm = np.clip(np.linalg.norm(self.stats, axis=1), 1e-08, np.inf)\n        self.stats = (self.stats.transpose() / vect_norm).transpose()\n\n    def get_mean_stats(self):\n        \"\"\"\n        Return the mean of first order statistics.\n        \"\"\"\n        mu = np.mean(self.stats, axis=0)\n        return mu\n\n    def get_total_covariance_stats(self):\n        \"\"\"\n        Compute and return the total covariance matrix of the first-order statistics.\n        \"\"\"\n        C = self.stats - self.stats.mean(axis=0)\n        return np.dot(C.transpose(), C) / self.stats.shape[0]\n\n    def get_model_stat0(self, mod_id):\n        \"\"\"Return zero-order statistics of a given model\n\n        Arguments\n        ---------\n        mod_id : str\n            ID of the model which stat0 will be returned.\n        \"\"\"\n        S = self.stat0[self.modelset == mod_id, :]\n        return S\n\n    def get_model_stats(self, mod_id):\n        \"\"\"Return first-order statistics of a given model.\n\n        Arguments\n        ---------\n        mod_id : str\n            ID of the model which stat1 will be returned.\n        \"\"\"\n        return self.stats[self.modelset == mod_id, :]\n\n    def sum_stat_per_model(self):\n        \"\"\"\n        Sum the zero- and first-order statistics per model and store them\n        in a new EmbeddingMeta.\n        Returns a EmbeddingMeta object with the statistics summed per model\n        and a numpy array with session_per_model.\n        \"\"\"\n\n        sts_per_model = EmbeddingMeta()\n        sts_per_model.modelset = np.unique(\n            self.modelset)  # nd: get uniq spkr ids\n        sts_per_model.segset = copy.deepcopy(sts_per_model.modelset)\n        sts_per_model.stat0 = np.zeros(\n            (sts_per_model.modelset.shape[0], self.stat0.shape[1]),\n            dtype=np.float64, )\n        sts_per_model.stats = np.zeros(\n            (sts_per_model.modelset.shape[0], self.stats.shape[1]),\n            dtype=np.float64, )\n\n        session_per_model = np.zeros(np.unique(self.modelset).shape[0])\n\n        # For each model sum the stats\n        for idx, model in enumerate(sts_per_model.modelset):\n            sts_per_model.stat0[idx, :] = self.get_model_stat0(model).sum(\n                axis=0)\n            sts_per_model.stats[idx, :] = self.get_model_stats(model).sum(\n                axis=0)\n            session_per_model[idx] += self.get_model_stats(model).shape[0]\n        return sts_per_model, session_per_model\n\n    def center_stats(self, mu):\n        \"\"\"\n        Center first order statistics.\n\n        Arguments\n        ---------\n        mu : array\n            Array to center on.\n        \"\"\"\n\n        dim = self.stats.shape[1] / self.stat0.shape[1]\n        index_map = np.repeat(np.arange(self.stat0.shape[1]), dim)\n        self.stats = self.stats - (self.stat0[:, index_map] *\n                                   mu.astype(np.float64))\n\n    def rotate_stats(self, R):\n        \"\"\"\n        Rotate first-order statistics by a right-product.\n\n        Arguments\n        ---------\n        R : ndarray\n            Matrix to use for right product on the first order statistics.\n        \"\"\"\n        self.stats = np.dot(self.stats, R)\n\n    def whiten_stats(self, mu, sigma, isSqrInvSigma=False):\n        \"\"\"\n        Whiten first-order statistics\n        If sigma.ndim == 1, case of a diagonal covariance.\n        If sigma.ndim == 2, case of a single Gaussian with full covariance.\n        If sigma.ndim == 3, case of a full covariance UBM.\n\n        Arguments\n        ---------\n        mu : array\n            Mean vector to be subtracted from the statistics.\n        sigma : narray\n            Co-variance matrix or covariance super-vector.\n        isSqrInvSigma : bool\n            True if the input Sigma matrix is the inverse of the square root of a covariance matrix.\n        \"\"\"\n\n        if sigma.ndim == 1:\n            self.center_stats(mu)\n            self.stats = self.stats / np.sqrt(sigma.astype(np.float64))\n\n        elif sigma.ndim == 2:\n            # Compute the inverse square root of the co-variance matrix Sigma\n            sqr_inv_sigma = sigma\n\n            if not isSqrInvSigma:\n                # eigen_values, eigen_vectors = scipy.linalg.eigh(sigma)\n                eigen_values, eigen_vectors = linalg.eigh(sigma)\n                ind = eigen_values.real.argsort()[::-1]\n                eigen_values = eigen_values.real[ind]\n                eigen_vectors = eigen_vectors.real[:, ind]\n\n                sqr_inv_eval_sigma = 1 / np.sqrt(eigen_values.real)\n                sqr_inv_sigma = np.dot(eigen_vectors,\n                                       np.diag(sqr_inv_eval_sigma))\n            else:\n                pass\n\n            # Whitening of the first-order statistics\n            self.center_stats(mu)  # CENTERING\n            self.rotate_stats(sqr_inv_sigma)\n\n        elif sigma.ndim == 3:\n            # we assume that sigma is a 3D ndarray of size D x n x n\n            # where D is the number of distributions and n is the dimension of a single distribution\n            n = self.stats.shape[1] // self.stat0.shape[1]\n            sess_nb = self.stat0.shape[0]\n            self.center_stats(mu)\n            self.stats = (np.einsum(\"ikj,ikl->ilj\",\n                                    self.stats.T.reshape(-1, n, sess_nb), sigma)\n                          .reshape(-1, sess_nb).T)\n\n        else:\n            raise Exception(\"Wrong dimension of Sigma, must be 1 or 2\")\n\n    def align_models(self, model_list):\n        \"\"\"\n        Align models of the current EmbeddingMeta to match a list of models\n            provided as input parameter. The size of the StatServer might be\n            reduced to match the input list of models.\n\n        Arguments\n        ---------\n        model_list : ndarray of strings\n            List of models to match.\n        \"\"\"\n        indx = np.array(\n            [np.argwhere(self.modelset == v)[0][0] for v in model_list])\n        self.segset = self.segset[indx]\n        self.modelset = self.modelset[indx]\n        self.stat0 = self.stat0[indx, :]\n        self.stats = self.stats[indx, :]\n\n    def align_segments(self, segment_list):\n        \"\"\"\n        Align segments of the current EmbeddingMeta to match a list of segment\n            provided as input parameter. The size of the StatServer might be\n            reduced to match the input list of segments.\n\n        Arguments\n        ---------\n        segment_list: ndarray of strings\n            list of segments to match\n        \"\"\"\n        indx = np.array(\n            [np.argwhere(self.segset == v)[0][0] for v in segment_list])\n        self.segset = self.segset[indx]\n        self.modelset = self.modelset[indx]\n        self.stat0 = self.stat0[indx, :]\n        self.stats = self.stats[indx, :]\n\n\nclass SpecClustUnorm:\n    \"\"\"\n    This class implements the spectral clustering with unnormalized affinity matrix.\n    Useful when affinity matrix is based on cosine similarities.\n\n    Reference\n    ---------\n    Von Luxburg, U. A tutorial on spectral clustering. Stat Comput 17, 395–416 (2007).\n    https://doi.org/10.1007/s11222-007-9033-z\n\n    Example\n    -------\n    >>> import diarization as diar\n    >>> clust = diar.SpecClustUnorm(min_num_spkrs=2, max_num_spkrs=10)\n    >>> emb = [[ 2.1, 3.1, 4.1, 4.2, 3.1],\n    ... [ 2.2, 3.1, 4.2, 4.2, 3.2],\n    ... [ 2.0, 3.0, 4.0, 4.1, 3.0],\n    ... [ 8.0, 7.0, 7.0, 8.1, 9.0],\n    ... [ 8.1, 7.1, 7.2, 8.1, 9.2],\n    ... [ 8.3, 7.4, 7.0, 8.4, 9.0],\n    ... [ 0.3, 0.4, 0.4, 0.5, 0.8],\n    ... [ 0.4, 0.3, 0.6, 0.7, 0.8],\n    ... [ 0.2, 0.3, 0.2, 0.3, 0.7],\n    ... [ 0.3, 0.4, 0.4, 0.4, 0.7],]\n    >>> # Estimating similarity matrix\n    >>> sim_mat = clust.get_sim_mat(emb)\n    >>> print (np.around(sim_mat[5:,5:], decimals=3))\n    [[1.    0.957 0.961 0.904 0.966]\n     [0.957 1.    0.977 0.982 0.997]\n     [0.961 0.977 1.    0.928 0.972]\n     [0.904 0.982 0.928 1.    0.976]\n     [0.966 0.997 0.972 0.976 1.   ]]\n    >>> # Prunning\n    >>> prunned_sim_mat = clust.p_pruning(sim_mat, 0.3)\n    >>> print (np.around(prunned_sim_mat[5:,5:], decimals=3))\n    [[1.    0.    0.    0.    0.   ]\n     [0.    1.    0.    0.982 0.997]\n     [0.    0.977 1.    0.    0.972]\n     [0.    0.982 0.    1.    0.976]\n     [0.    0.997 0.    0.976 1.   ]]\n    >>> # Symmetrization\n    >>> sym_prund_sim_mat = 0.5 * (prunned_sim_mat + prunned_sim_mat.T)\n    >>> print (np.around(sym_prund_sim_mat[5:,5:], decimals=3))\n    [[1.    0.    0.    0.    0.   ]\n     [0.    1.    0.489 0.982 0.997]\n     [0.    0.489 1.    0.    0.486]\n     [0.    0.982 0.    1.    0.976]\n     [0.    0.997 0.486 0.976 1.   ]]\n    >>> # Laplacian\n    >>> laplacian = clust.get_laplacian(sym_prund_sim_mat)\n    >>> print (np.around(laplacian[5:,5:], decimals=3))\n    [[ 1.999  0.     0.     0.     0.   ]\n     [ 0.     2.468 -0.489 -0.982 -0.997]\n     [ 0.    -0.489  0.975  0.    -0.486]\n     [ 0.    -0.982  0.     1.958 -0.976]\n     [ 0.    -0.997 -0.486 -0.976  2.458]]\n    >>> # Spectral Embeddings\n    >>> spec_emb, num_of_spk = clust.get_spec_embs(laplacian, 3)\n    >>> print(num_of_spk)\n    3\n    >>> # Clustering\n    >>> clust.cluster_embs(spec_emb, num_of_spk)\n    >>> # print (clust.labels_) # [0 0 0 2 2 2 1 1 1 1]\n    >>> # Complete spectral clustering\n    >>> clust.do_spec_clust(emb, k_oracle=3, p_val=0.3)\n    >>> # print(clust.labels_) # [0 0 0 2 2 2 1 1 1 1]\n    \"\"\"\n\n    def __init__(self, min_num_spkrs=2, max_num_spkrs=10):\n\n        self.min_num_spkrs = min_num_spkrs\n        self.max_num_spkrs = max_num_spkrs\n\n    def do_spec_clust(self, X, k_oracle, p_val):\n        \"\"\"\n        Function for spectral clustering.\n\n        Arguments\n        ---------\n        X : array\n            (n_samples, n_features).\n            Embeddings extracted from the model.\n        k_oracle : int\n            Number of speakers (when oracle number of speakers).\n        p_val : float\n            p percent value to prune the affinity matrix.\n        \"\"\"\n\n        # Similarity matrix computation\n        sim_mat = self.get_sim_mat(X)\n\n        # Refining similarity matrix with p_val\n        prunned_sim_mat = self.p_pruning(sim_mat, p_val)\n\n        # Symmetrization\n        sym_prund_sim_mat = 0.5 * (prunned_sim_mat + prunned_sim_mat.T)\n\n        # Laplacian calculation\n        laplacian = self.get_laplacian(sym_prund_sim_mat)\n\n        # Get Spectral Embeddings\n        emb, num_of_spk = self.get_spec_embs(laplacian, k_oracle)\n\n        # Perform clustering\n        self.cluster_embs(emb, num_of_spk)\n\n    def get_sim_mat(self, X):\n        \"\"\"\n        Returns the similarity matrix based on cosine similarities.\n\n        Arguments\n        ---------\n        X : array\n            (n_samples, n_features).\n            Embeddings extracted from the model.\n\n        Returns\n        -------\n        M : array\n            (n_samples, n_samples).\n            Similarity matrix with cosine similarities between each pair of embedding.\n        \"\"\"\n\n        # Cosine similarities\n        M = sklearn.metrics.pairwise.cosine_similarity(X, X)\n        return M\n\n    def p_pruning(self, A, pval):\n        \"\"\"\n        Refine the affinity matrix by zeroing less similar values.\n\n        Arguments\n        ---------\n        A : array\n            (n_samples, n_samples).\n            Affinity matrix.\n        pval : float\n            p-value to be retained in each row of the affinity matrix.\n\n        Returns\n        -------\n        A : array\n            (n_samples, n_samples).\n            Prunned affinity matrix based on p_val.\n        \"\"\"\n\n        n_elems = int((1 - pval) * A.shape[0])\n\n        # For each row in a affinity matrix\n        for i in range(A.shape[0]):\n            low_indexes = np.argsort(A[i, :])\n            low_indexes = low_indexes[0:n_elems]\n\n            # Replace smaller similarity values by 0s\n            A[i, low_indexes] = 0\n\n        return A\n\n    def get_laplacian(self, M):\n        \"\"\"\n        Returns the un-normalized laplacian for the given affinity matrix.\n\n        Arguments\n        ---------\n        M : array\n            (n_samples, n_samples)\n            Affinity matrix.\n\n        Returns\n        -------\n        L : array\n            (n_samples, n_samples)\n            Laplacian matrix.\n        \"\"\"\n\n        M[np.diag_indices(M.shape[0])] = 0\n        D = np.sum(np.abs(M), axis=1)\n        D = np.diag(D)\n        L = D - M\n        return L\n\n    def get_spec_embs(self, L, k_oracle=4):\n        \"\"\"\n        Returns spectral embeddings and estimates the number of speakers\n        using maximum Eigen gap.\n\n        Arguments\n        ---------\n        L : array (n_samples, n_samples)\n            Laplacian matrix.\n        k_oracle : int\n            Number of speakers when the condition is oracle number of speakers,\n            else None.\n\n        Returns\n        -------\n        emb : array (n_samples, n_components)\n            Spectral embedding for each sample with n Eigen components.\n        num_of_spk : int\n            Estimated number of speakers. If the condition is set to the oracle\n            number of speakers then returns k_oracle.\n        \"\"\"\n\n        lambdas, eig_vecs = scipy.linalg.eigh(L)\n\n        # if params[\"oracle_n_spkrs\"] is True:\n        if k_oracle is not None:\n            num_of_spk = k_oracle\n        else:\n            lambda_gap_list = self.get_eigen_gaps(lambdas[1:self.max_num_spkrs])\n\n            num_of_spk = (np.argmax(\n                lambda_gap_list[:min(self.max_num_spkrs, len(lambda_gap_list))])\n                          + 2)\n\n            if num_of_spk < self.min_num_spkrs:\n                num_of_spk = self.min_num_spkrs\n\n        emb = eig_vecs[:, 0:num_of_spk]\n\n        return emb, num_of_spk\n\n    def cluster_embs(self, emb, k):\n        \"\"\"\n        Clusters the embeddings using kmeans.\n\n        Arguments\n        ---------\n        emb : array (n_samples, n_components)\n            Spectral embedding for each sample with n Eigen components.\n        k : int\n            Number of clusters to kmeans.\n\n        Returns\n        -------\n        self.labels_ : self\n            Labels for each sample embedding.\n        \"\"\"\n        _, self.labels_, _ = k_means(emb, k)\n\n    def get_eigen_gaps(self, eig_vals):\n        \"\"\"\n        Returns the difference (gaps) between the Eigen values.\n\n        Arguments\n        ---------\n        eig_vals : list\n            List of eigen values\n\n        Returns\n        -------\n        eig_vals_gap_list : list\n            List of differences (gaps) between adjacent Eigen values.\n        \"\"\"\n\n        eig_vals_gap_list = []\n        for i in range(len(eig_vals) - 1):\n            gap = float(eig_vals[i + 1]) - float(eig_vals[i])\n            eig_vals_gap_list.append(gap)\n\n        return eig_vals_gap_list\n\n\nclass SpecCluster(SpectralClustering):\n    def perform_sc(self, X, n_neighbors=10):\n        \"\"\"\n        Performs spectral clustering using sklearn on embeddings.\n\n        Arguments\n        ---------\n        X : array (n_samples, n_features)\n            Embeddings to be clustered.\n        n_neighbors : int\n            Number of neighbors in estimating affinity matrix.\n        \"\"\"\n\n        # Computation of affinity matrix\n        connectivity = kneighbors_graph(\n            X,\n            n_neighbors=n_neighbors,\n            include_self=True, )\n        self.affinity_matrix_ = 0.5 * (connectivity + connectivity.T)\n\n        # Perform spectral clustering on affinity matrix\n        self.labels_ = spectral_clustering(\n            self.affinity_matrix_,\n            n_clusters=self.n_clusters, )\n        return self\n\n\ndef is_overlapped(end1, start2):\n    \"\"\"\n    Returns True if segments are overlapping.\n\n    Arguments\n    ---------\n    end1 : float\n        End time of the first segment.\n    start2 : float\n        Start time of the second segment.\n\n    Returns\n    -------\n    overlapped : bool\n        True of segments overlapped else False.\n\n    Example\n    -------\n    >>> import diarization as diar\n    >>> diar.is_overlapped(5.5, 3.4)\n    True\n    >>> diar.is_overlapped(5.5, 6.4)\n    False\n    \"\"\"\n\n    if start2 > end1:\n        return False\n    else:\n        return True\n\n\ndef merge_ssegs_same_speaker(lol):\n    \"\"\"\n    Merge adjacent sub-segs from the same speaker.\n\n    Arguments\n    ---------\n    lol : list of list\n        Each list contains [rec_id, seg_start, seg_end, spkr_id].\n\n    Returns\n    -------\n    new_lol : list of list\n        new_lol contains adjacent segments merged from the same speaker ID.\n\n    Example\n    -------\n    >>> import diarization as diar\n    >>> lol=[['r1', 5.5, 7.0, 's1'],\n    ... ['r1', 6.5, 9.0, 's1'],\n    ... ['r1', 8.0, 11.0, 's1'],\n    ... ['r1', 11.5, 13.0, 's2'],\n    ... ['r1', 14.0, 15.0, 's2'],\n    ... ['r1', 14.5, 15.0, 's1']]\n    >>> diar.merge_ssegs_same_speaker(lol)\n    [['r1', 5.5, 11.0, 's1'], ['r1', 11.5, 13.0, 's2'], ['r1', 14.0, 15.0, 's2'], ['r1', 14.5, 15.0, 's1']]\n    \"\"\"\n\n    new_lol = []\n\n    # Start from the first sub-seg\n    sseg = lol[0]\n    flag = False\n    for i in range(1, len(lol)):\n        next_sseg = lol[i]\n\n        # IF sub-segments overlap AND has same speaker THEN merge\n        if is_overlapped(sseg[2], next_sseg[1]) and sseg[3] == next_sseg[3]:\n            sseg[2] = next_sseg[2]  # just update the end time\n            # This is important. For the last sseg, if it is the same speaker the merge\n            # Make sure we don't append the last segment once more. Hence, set FLAG=True\n            if i == len(lol) - 1:\n                flag = True\n                new_lol.append(sseg)\n        else:\n            new_lol.append(sseg)\n            sseg = next_sseg\n\n    # Add last segment only when it was skipped earlier.\n    if flag is False:\n        new_lol.append(lol[-1])\n\n    return new_lol\n\n\ndef write_ders_file(ref_rttm, DER, out_der_file):\n    \"\"\"Write the final DERs for individual recording.\n\n    Arguments\n    ---------\n    ref_rttm : str\n        Reference RTTM file.\n    DER : array\n        Array containing DER values of each recording.\n    out_der_file : str\n        File to write the DERs.\n    \"\"\"\n\n    rttm = read_rttm(ref_rttm)\n    spkr_info = list(filter(lambda x: x.startswith(\"SPKR-INFO\"), rttm))\n\n    rec_id_list = []\n    count = 0\n\n    with open(out_der_file, \"w\") as f:\n        for row in spkr_info:\n            a = row.split(\" \")\n            rec_id = a[1]\n            if rec_id not in rec_id_list:\n                r = [rec_id, str(round(DER[count], 2))]\n                rec_id_list.append(rec_id)\n                line_str = \" \".join(r)\n                f.write(\"%s\\n\" % line_str)\n                count += 1\n        r = [\"OVERALL \", str(round(DER[count], 2))]\n        line_str = \" \".join(r)\n        f.write(\"%s\\n\" % line_str)\n\n\ndef get_oracle_num_spkrs(rec_id, spkr_info):\n    \"\"\"\n    Returns actual number of speakers in a recording from the ground-truth.\n    This can be used when the condition is oracle number of speakers.\n\n    Arguments\n    ---------\n    rec_id : str\n        Recording ID for which the number of speakers have to be obtained.\n    spkr_info : list\n        Header of the RTTM file. Starting with `SPKR-INFO`.\n\n    Example\n    -------\n    >>> from speechbrain.processing import diarization as diar\n    >>> spkr_info = ['SPKR-INFO ES2011a 0 <NA> <NA> <NA> unknown ES2011a.A <NA> <NA>',\n    ... 'SPKR-INFO ES2011a 0 <NA> <NA> <NA> unknown ES2011a.B <NA> <NA>',\n    ... 'SPKR-INFO ES2011a 0 <NA> <NA> <NA> unknown ES2011a.C <NA> <NA>',\n    ... 'SPKR-INFO ES2011a 0 <NA> <NA> <NA> unknown ES2011a.D <NA> <NA>',\n    ... 'SPKR-INFO ES2011b 0 <NA> <NA> <NA> unknown ES2011b.A <NA> <NA>',\n    ... 'SPKR-INFO ES2011b 0 <NA> <NA> <NA> unknown ES2011b.B <NA> <NA>',\n    ... 'SPKR-INFO ES2011b 0 <NA> <NA> <NA> unknown ES2011b.C <NA> <NA>']\n    >>> diar.get_oracle_num_spkrs('ES2011a', spkr_info)\n    4\n    >>> diar.get_oracle_num_spkrs('ES2011b', spkr_info)\n    3\n    \"\"\"\n\n    num_spkrs = 0\n    for line in spkr_info:\n        if rec_id in line:\n            # Since rec_id is prefix for each speaker\n            num_spkrs += 1\n\n    return num_spkrs\n\n\ndef distribute_overlap(lol):\n    \"\"\"\n    Distributes the overlapped speech equally among the adjacent segments\n    with different speakers.\n\n    Arguments\n    ---------\n    lol : list of list\n        It has each list structure as [rec_id, seg_start, seg_end, spkr_id].\n\n    Returns\n    -------\n    new_lol : list of list\n        It contains the overlapped part equally divided among the adjacent\n        segments with different speaker IDs.\n\n    Example\n    -------\n    >>> import diarization as diar\n    >>> lol = [['r1', 5.5, 9.0, 's1'],\n    ... ['r1', 8.0, 11.0, 's2'],\n    ... ['r1', 11.5, 13.0, 's2'],\n    ... ['r1', 12.0, 15.0, 's1']]\n    >>> diar.distribute_overlap(lol)\n    [['r1', 5.5, 8.5, 's1'], ['r1', 8.5, 11.0, 's2'], ['r1', 11.5, 12.5, 's2'], ['r1', 12.5, 15.0, 's1']]\n    \"\"\"\n\n    new_lol = []\n    sseg = lol[0]\n\n    # Add first sub-segment here to avoid error at: \"if new_lol[-1] != sseg:\" when new_lol is empty\n    # new_lol.append(sseg)\n\n    for i in range(1, len(lol)):\n        next_sseg = lol[i]\n        # No need to check if they are different speakers.\n        # Because if segments are overlapped then they always have different speakers.\n        # This is because similar speaker's adjacent sub-segments are already merged by \"merge_ssegs_same_speaker()\"\n\n        if is_overlapped(sseg[2], next_sseg[1]):\n\n            # Get overlap duration.\n            # Now this overlap will be divided equally between adjacent segments.\n            overlap = sseg[2] - next_sseg[1]\n\n            # Update end time of old seg\n            sseg[2] = sseg[2] - (overlap / 2.0)\n\n            # Update start time of next seg\n            next_sseg[1] = next_sseg[1] + (overlap / 2.0)\n\n            if len(new_lol) == 0:\n                # For first sub-segment entry\n                new_lol.append(sseg)\n            else:\n                # To avoid duplicate entries\n                if new_lol[-1] != sseg:\n                    new_lol.append(sseg)\n\n            # Current sub-segment is next sub-segment\n            sseg = next_sseg\n\n        else:\n            # For the first sseg\n            if len(new_lol) == 0:\n                new_lol.append(sseg)\n            else:\n                # To avoid duplicate entries\n                if new_lol[-1] != sseg:\n                    new_lol.append(sseg)\n\n            # Update the current sub-segment\n            sseg = next_sseg\n\n    # Add the remaining last sub-segment\n    new_lol.append(next_sseg)\n\n    return new_lol\n\n\ndef read_rttm(rttm_file_path):\n    \"\"\"\n    Reads and returns RTTM in list format.\n\n    Arguments\n    ---------\n    rttm_file_path : str\n        Path to the RTTM file to be read.\n\n    Returns\n    -------\n    rttm : list\n        List containing rows of RTTM file.\n    \"\"\"\n\n    rttm = []\n    with open(rttm_file_path, \"r\") as f:\n        for line in f:\n            entry = line[:-1]\n            rttm.append(entry)\n    return rttm\n\n\ndef write_rttm(segs_list, out_rttm_file):\n    \"\"\"\n    Writes the segment list in RTTM format (A standard NIST format).\n\n    Arguments\n    ---------\n    segs_list : list of list\n        Each list contains [rec_id, seg_start, seg_end, spkr_id].\n    out_rttm_file : str\n        Path of the output RTTM file.\n    \"\"\"\n\n    rttm = []\n    rec_id = segs_list[0][0]\n\n    for seg in segs_list:\n        new_row = [\n            \"SPEAKER\",\n            rec_id,\n            \"0\",\n            str(round(seg[1], 4)),\n            str(round(seg[2] - seg[1], 4)),\n            \"<NA>\",\n            \"<NA>\",\n            seg[3],\n            \"<NA>\",\n            \"<NA>\",\n        ]\n        rttm.append(new_row)\n\n    with open(out_rttm_file, \"w\") as f:\n        for row in rttm:\n            line_str = \" \".join(row)\n            f.write(\"%s\\n\" % line_str)\n\n\ndef do_AHC(diary_obj, out_rttm_file, rec_id, k_oracle=4, p_val=0.3):\n    \"\"\"\n    Performs Agglomerative Hierarchical Clustering on embeddings.\n\n    Arguments\n    ---------\n    diary_obj : EmbeddingMeta type\n        Contains embeddings in diary_obj.stats and segment IDs in diary_obj.segset.\n    out_rttm_file : str\n        Path of the output RTTM file.\n    rec_id : str\n        Recording ID for the recording under processing.\n    k : int\n        Number of speaker (None, if it has to be estimated).\n    pval : float\n        `pval` for prunning affinity matrix. Used only when number of speakers\n        are unknown. Note that this is just for experiment. Prefer Spectral clustering\n        for better clustering results.\n    \"\"\"\n\n    from sklearn.cluster import AgglomerativeClustering\n\n    # p_val is the threshold_val (for AHC)\n    diary_obj.norm_stats()\n\n    # processing\n    if k_oracle is not None:\n        num_of_spk = k_oracle\n\n        clustering = AgglomerativeClustering(\n            n_clusters=num_of_spk,\n            affinity=\"cosine\",\n            linkage=\"average\", ).fit(diary_obj.stats)\n        labels = clustering.labels_\n\n    else:\n        # Estimate num of using max eigen gap with `cos` affinity matrix.\n        # This is just for experimentation.\n        clustering = AgglomerativeClustering(\n            n_clusters=None,\n            affinity=\"cosine\",\n            linkage=\"average\",\n            distance_threshold=p_val, ).fit(diary_obj.stats)\n        labels = clustering.labels_\n\n    # Convert labels to speaker boundaries\n    subseg_ids = diary_obj.segset\n    lol = []\n\n    for i in range(labels.shape[0]):\n        spkr_id = rec_id + \"_\" + str(labels[i])\n\n        sub_seg = subseg_ids[i]\n\n        splitted = sub_seg.rsplit(\"_\", 2)\n        rec_id = str(splitted[0])\n        sseg_start = float(splitted[1])\n        sseg_end = float(splitted[2])\n\n        a = [rec_id, sseg_start, sseg_end, spkr_id]\n        lol.append(a)\n\n    # Sorting based on start time of sub-segment\n    lol.sort(key=lambda x: float(x[1]))\n\n    # Merge and split in 2 simple steps: (i) Merge sseg of same speakers then (ii) split different speakers\n    # Step 1: Merge adjacent sub-segments that belong to same speaker (or cluster)\n    lol = merge_ssegs_same_speaker(lol)\n\n    # Step 2: Distribute duration of adjacent overlapping sub-segments belonging to different speakers (or cluster)\n    # Taking mid-point as the splitting time location.\n    lol = distribute_overlap(lol)\n\n    # logger.info(\"Completed diarizing \" + rec_id)\n    write_rttm(lol, out_rttm_file)\n\n\ndef do_spec_clustering(diary_obj, out_rttm_file, rec_id, k, pval, affinity_type,\n                       n_neighbors):\n    \"\"\"\n    Performs spectral clustering on embeddings. This function calls specific\n    clustering algorithms as per affinity.\n\n    Arguments\n    ---------\n    diary_obj : EmbeddingMeta type\n        Contains embeddings in diary_obj.stats and segment IDs in diary_obj.segset.\n    out_rttm_file : str\n        Path of the output RTTM file.\n    rec_id : str\n        Recording ID for the recording under processing.\n    k : int\n        Number of speaker (None, if it has to be estimated).\n    pval : float\n        `pval` for prunning affinity matrix.\n    affinity_type : str\n        Type of similarity to be used to get affinity matrix (cos or nn).\n    \"\"\"\n\n    if affinity_type == \"cos\":\n        clust_obj = SpecClustUnorm(min_num_spkrs=2, max_num_spkrs=10)\n        k_oracle = k  # use it only when oracle num of speakers\n        clust_obj.do_spec_clust(diary_obj.stats, k_oracle, pval)\n        labels = clust_obj.labels_\n    else:\n        clust_obj = SpecCluster(\n            n_clusters=k,\n            assign_labels=\"kmeans\",\n            random_state=1234,\n            affinity=\"nearest_neighbors\", )\n        clust_obj.perform_sc(diary_obj.stats, n_neighbors)\n        labels = clust_obj.labels_\n\n    # Convert labels to speaker boundaries\n    subseg_ids = diary_obj.segset\n    lol = []\n\n    for i in range(labels.shape[0]):\n        spkr_id = rec_id + \"_\" + str(labels[i])\n\n        sub_seg = subseg_ids[i]\n\n        splitted = sub_seg.rsplit(\"_\", 2)\n        rec_id = str(splitted[0])\n        sseg_start = float(splitted[1])\n        sseg_end = float(splitted[2])\n\n        a = [rec_id, sseg_start, sseg_end, spkr_id]\n        lol.append(a)\n\n    # Sorting based on start time of sub-segment\n    lol.sort(key=lambda x: float(x[1]))\n\n    # Merge and split in 2 simple steps: (i) Merge sseg of same speakers then (ii) split different speakers\n    # Step 1: Merge adjacent sub-segments that belong to same speaker (or cluster)\n    lol = merge_ssegs_same_speaker(lol)\n\n    # Step 2: Distribute duration of adjacent overlapping sub-segments belonging to different speakers (or cluster)\n    # Taking mid-point as the splitting time location.\n    lol = distribute_overlap(lol)\n\n    # logger.info(\"Completed diarizing \" + rec_id)\n    write_rttm(lol, out_rttm_file)\n\n\nif __name__ == '__main__':\n\n    parser = argparse.ArgumentParser(\n        prog='python diarization.py --backend AHC', description='diarizing')\n    parser.add_argument(\n        '--sys_rttm_dir',\n        required=False,\n        help='Directory to store system RTTM files')\n    parser.add_argument(\n        '--ref_rttm_dir',\n        required=False,\n        help='Directory to store reference RTTM files')\n    parser.add_argument(\n        '--backend', default=\"AHC\", help='type of backend, AHC or SC or kmeans')\n    parser.add_argument(\n        '--oracle_n_spkrs',\n        default=True,\n        type=strtobool,\n        help='Oracle num of speakers')\n    parser.add_argument(\n        '--mic_type',\n        default=\"Mix-Headset\",\n        help='Type of microphone to be used')\n    parser.add_argument(\n        '--affinity', default=\"cos\", help='affinity matrix, cos or nn')\n    parser.add_argument(\n        '--max_subseg_dur',\n        default=3.0,\n        type=float,\n        help='Duration in seconds of a subsegments to be prepared from larger segments'\n    )\n    parser.add_argument(\n        '--overlap',\n        default=1.5,\n        type=float,\n        help='Overlap duration in seconds between adjacent subsegments')\n\n    args = parser.parse_args()\n\n    pval = 0.3\n    rec_id = \"utt0001\"\n    n_neighbors = 10\n    out_rttm_file = \"./out.rttm\"\n\n    embeddings = np.empty(shape=[0, 32], dtype=np.float64)\n    segset = []\n\n    for i in range(10):\n        seg = [rec_id + \"_\" + str(i) + \"_\" + str(i + 1)]\n        segset = segset + seg\n        emb = np.random.rand(1, 32)\n        embeddings = np.concatenate((embeddings, emb), axis=0)\n\n    segset = np.array(segset, dtype=\"|O\")\n    stat_obj = EmbeddingMeta(segset, embeddings)\n    if args.oracle_n_spkrs is True:\n        num_spkrs = 2\n\n    if args.backend == \"SC\":\n        print(\"begin SC \")\n        do_spec_clustering(\n            stat_obj,\n            out_rttm_file,\n            rec_id,\n            num_spkrs,\n            pval,\n            args.affinity,\n            n_neighbors, )\n    if args.backend == \"AHC\":\n        print(\"begin AHC \")\n        do_AHC(stat_obj, out_rttm_file, rec_id, num_spkrs, pval)\n"
  },
  {
    "path": "paddlespeech/vector/cluster/plda.py",
    "content": "# Copyright (c) 2022 PaddlePaddle and SpeechBrain Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"A popular speaker recognition/diarization model (LDA and PLDA).\n\nRelevant Papers\n - This implementation of PLDA is based on the following papers.\n\n - PLDA model Training\n    * Ye Jiang et. al, \"PLDA Modeling in I-Vector and Supervector Space for Speaker Verification,\" in Interspeech, 2012.\n    * Patrick Kenny et. al, \"PLDA for speaker verification with utterances of arbitrary duration,\" in ICASSP, 2013.\n\n - PLDA scoring (fast scoring)\n    * Daniel Garcia-Romero et. al, “Analysis of i-vector length normalization in speaker recognition systems,” in Interspeech, 2011.\n    * Weiwei-LIN et. al, \"Fast Scoring for PLDA with Uncertainty Propagation,\" in Odyssey, 2016.\n    * Kong Aik Lee et. al, \"Multi-session PLDA Scoring of I-vector for Partially Open-Set Speaker Detection,\" in Interspeech 2013.\n\nCredits\n    This code is adapted from: https://git-lium.univ-lemans.fr/Larcher/sidekit\n\"\"\"\nimport copy\nimport pickle\n\nimport numpy\nfrom scipy import linalg\n\nfrom paddlespeech.vector.cluster.diarization import EmbeddingMeta\n\n\ndef ismember(list1, list2):\n    c = [item in list2 for item in list1]\n    return c\n\n\nclass Ndx:\n    \"\"\"\n    A class that encodes trial index information.  It has a list of\n    model names and a list of test segment names and a matrix\n    indicating which combinations of model and test segment are\n    trials of interest.\n\n    Arguments\n    ---------\n    modelset : list\n        List of unique models in a ndarray.\n    segset : list\n        List of unique test segments in a ndarray.\n    trialmask : 2D ndarray of bool.\n        Rows correspond to the models and columns to the test segments. True, if the trial is of interest.\n    \"\"\"\n\n    def __init__(self,\n                 ndx_file_name=\"\",\n                 models=numpy.array([]),\n                 testsegs=numpy.array([])):\n        \"\"\"\n        Initialize a Ndx object by loading information from a file.\n\n        Arguments\n        ---------\n        ndx_file_name : str\n            Name of the file to load.\n        \"\"\"\n        self.modelset = numpy.empty(0, dtype=\"|O\")\n        self.segset = numpy.empty(0, dtype=\"|O\")\n        self.trialmask = numpy.array([], dtype=\"bool\")\n\n        if ndx_file_name == \"\":\n            # This is needed to make sizes same\n            d = models.shape[0] - testsegs.shape[0]\n            if d != 0:\n                if d > 0:\n                    last = str(testsegs[-1])\n                    pad = numpy.array([last] * d)\n                    testsegs = numpy.hstack((testsegs, pad))\n                    # pad = testsegs[-d:]\n                    # testsegs = numpy.concatenate((testsegs, pad), axis=1)\n                else:\n                    d = abs(d)\n                    last = str(models[-1])\n                    pad = numpy.array([last] * d)\n                    models = numpy.hstack((models, pad))\n                    # pad = models[-d:]\n                    # models = numpy.concatenate((models, pad), axis=1)\n\n            modelset = numpy.unique(models)\n            segset = numpy.unique(testsegs)\n\n            trialmask = numpy.zeros(\n                (modelset.shape[0], segset.shape[0]), dtype=\"bool\")\n            for m in range(modelset.shape[0]):\n                segs = testsegs[numpy.array(ismember(models, modelset[m]))]\n                trialmask[m, ] = ismember(segset, segs)  # noqa E231\n\n            self.modelset = modelset\n            self.segset = segset\n            self.trialmask = trialmask\n            assert self.validate(), \"Wrong Ndx format\"\n\n        else:\n            ndx = Ndx.read(ndx_file_name)\n            self.modelset = ndx.modelset\n            self.segset = ndx.segset\n            self.trialmask = ndx.trialmask\n\n    def save_ndx_object(self, output_file_name):\n        with open(output_file_name, \"wb\") as output:\n            pickle.dump(self, output, pickle.HIGHEST_PROTOCOL)\n\n    def filter(self, modlist, seglist, keep):\n        \"\"\"\n        Removes some of the information in an Ndx. Useful for creating a\n        gender specific Ndx from a pooled gender Ndx.  Depending on the\n        value of \\'keep\\', the two input lists indicate the strings to\n        retain or the strings to discard.\n\n        Arguments\n        ---------\n        modlist : array\n            A cell array of strings which will be compared with the modelset of 'inndx'.\n        seglist : array\n            A cell array of strings which will be compared with the segset of 'inndx'.\n        keep : bool\n            Indicating whether modlist and seglist are the models to keep or discard.\n        \"\"\"\n        if keep:\n            keepmods = modlist\n            keepsegs = seglist\n        else:\n            keepmods = diff(self.modelset, modlist)\n            keepsegs = diff(self.segset, seglist)\n\n        keepmodidx = numpy.array(ismember(self.modelset, keepmods))\n        keepsegidx = numpy.array(ismember(self.segset, keepsegs))\n\n        outndx = Ndx()\n        outndx.modelset = self.modelset[keepmodidx]\n        outndx.segset = self.segset[keepsegidx]\n        tmp = self.trialmask[numpy.array(keepmodidx), :]\n        outndx.trialmask = tmp[:, numpy.array(keepsegidx)]\n\n        assert outndx.validate, \"Wrong Ndx format\"\n\n        if self.modelset.shape[0] > outndx.modelset.shape[0]:\n            print(\n                \"Number of models reduced from %d to %d\" %\n                self.modelset.shape[0],\n                outndx.modelset.shape[0], )\n        if self.segset.shape[0] > outndx.segset.shape[0]:\n            print(\n                \"Number of test segments reduced from %d to %d\",\n                self.segset.shape[0],\n                outndx.segset.shape[0], )\n        return outndx\n\n    def validate(self):\n        \"\"\"\n        Checks that an object of type Ndx obeys certain rules that\n        must always be true. Returns a boolean value indicating whether the object is valid\n        \"\"\"\n        ok = isinstance(self.modelset, numpy.ndarray)\n        ok &= isinstance(self.segset, numpy.ndarray)\n        ok &= isinstance(self.trialmask, numpy.ndarray)\n\n        ok &= self.modelset.ndim == 1\n        ok &= self.segset.ndim == 1\n        ok &= self.trialmask.ndim == 2\n\n        ok &= self.trialmask.shape == (self.modelset.shape[0],\n                                       self.segset.shape[0], )\n        return ok\n\n\nclass Scores:\n    \"\"\"\n    A class for storing scores for trials.  The modelset and segset\n    fields are lists of model and test segment names respectively.\n    The element i,j of scoremat and scoremask corresponds to the\n    trial involving model i and test segment j.\n\n    Arguments\n    ---------\n    modelset : list\n        List of unique models in a ndarray.\n    segset : list\n        List of unique test segments in a ndarray.\n    scoremask : 2D ndarray of bool\n        Indicates the trials of interest, i.e.,\n        the entry i,j in scoremat should be ignored if scoremask[i,j] is False.\n    scoremat : 2D ndarray\n        Scores matrix.\n    \"\"\"\n\n    def __init__(self, scores_file_name=\"\"):\n        \"\"\" \n        Initialize a Scores object by loading information from a file HDF5 format.\n\n        Arguments\n        ---------\n        scores_file_name : str\n            Name of the file to load.\n        \"\"\"\n        self.modelset = numpy.empty(0, dtype=\"|O\")\n        self.segset = numpy.empty(0, dtype=\"|O\")\n        self.scoremask = numpy.array([], dtype=\"bool\")\n        self.scoremat = numpy.array([])\n\n        if scores_file_name == \"\":\n            pass\n        else:\n            tmp = Scores.read(scores_file_name)\n            self.modelset = tmp.modelset\n            self.segset = tmp.segset\n            self.scoremask = tmp.scoremask\n            self.scoremat = tmp.scoremat\n\n    def __repr__(self):\n        ch = \"modelset:\\n\"\n        ch += self.modelset + \"\\n\"\n        ch += \"segset:\\n\"\n        ch += self.segset + \"\\n\"\n        ch += \"scoremask:\\n\"\n        ch += self.scoremask.__repr__() + \"\\n\"\n        ch += \"scoremat:\\n\"\n        ch += self.scoremat.__repr__() + \"\\n\"\n\n\ndef fa_model_loop(\n        batch_start,\n        mini_batch_indices,\n        factor_analyser,\n        stat0,\n        stats,\n        e_h,\n        e_hh, ):\n    \"\"\"\n    A function for PLDA estimation.\n\n    Arguments\n    ---------\n    batch_start : int\n        Index to start at in the list.\n    mini_batch_indices : list\n        Indices of the elements in the list (should start at zero).\n    factor_analyser : instance of PLDA class\n        PLDA class object.\n    stat0 : tensor\n        Matrix of zero-order statistics.\n    stats: tensor\n        Matrix of first-order statistics.\n    e_h : tensor\n        An accumulator matrix.\n    e_hh: tensor\n        An accumulator matrix.\n    \"\"\"\n    rank = factor_analyser.F.shape[1]\n    if factor_analyser.Sigma.ndim == 2:\n        A = factor_analyser.F.T.dot(factor_analyser.F)\n        inv_lambda_unique = dict()\n        for sess in numpy.unique(stat0[:, 0]):\n            inv_lambda_unique[sess] = linalg.inv(sess * A + numpy.eye(A.shape[\n                0]))\n\n    tmp = numpy.zeros(\n        (factor_analyser.F.shape[1], factor_analyser.F.shape[1]),\n        dtype=numpy.float64, )\n\n    for idx in mini_batch_indices:\n        if factor_analyser.Sigma.ndim == 1:\n            inv_lambda = linalg.inv(\n                numpy.eye(rank) + (factor_analyser.F.T * stat0[\n                    idx + batch_start, :]).dot(factor_analyser.F))\n        else:\n            inv_lambda = inv_lambda_unique[stat0[idx + batch_start, 0]]\n\n        aux = factor_analyser.F.T.dot(stats[idx + batch_start, :])\n        numpy.dot(aux, inv_lambda, out=e_h[idx])\n        e_hh[idx] = inv_lambda + numpy.outer(e_h[idx], e_h[idx], tmp)\n\n\ndef _check_missing_model(enroll, test, ndx):\n    # Remove missing models and test segments\n    clean_ndx = ndx.filter(enroll.modelset, test.segset, True)\n\n    # Align EmbeddingMeta to match the clean_ndx\n    enroll.align_models(clean_ndx.modelset)\n    test.align_segments(clean_ndx.segset)\n\n    return clean_ndx\n\n\nclass PLDA:\n    \"\"\"\n    A class to train PLDA model from embeddings.\n\n    The input is in paddlespeech.vector.cluster.diarization.EmbeddingMeta format.\n    Trains a simplified PLDA model no within-class covariance matrix but full residual covariance matrix.\n\n    Arguments\n    ---------\n    mean : tensor\n        Mean of the vectors.\n    F : tensor\n        Eigenvoice matrix.\n    Sigma : tensor\n        Residual matrix.\n    \"\"\"\n\n    def __init__(\n            self,\n            mean=None,\n            F=None,\n            Sigma=None,\n            rank_f=100,\n            nb_iter=10,\n            scaling_factor=1.0, ):\n        self.mean = None\n        self.F = None\n        self.Sigma = None\n        self.rank_f = rank_f\n        self.nb_iter = nb_iter\n        self.scaling_factor = scaling_factor\n\n        if mean is not None:\n            self.mean = mean\n        if F is not None:\n            self.F = F\n        if Sigma is not None:\n            self.Sigma = Sigma\n\n    def plda(\n            self,\n            emb_meta=None,\n            output_file_name=None, ):\n        \"\"\"\n        Trains PLDA model with no within class covariance matrix but full residual covariance matrix.\n\n        Arguments\n        ---------\n        emb_meta : paddlespeech.vector.cluster.diarization.EmbeddingMeta\n            Contains vectors and meta-information to perform PLDA\n        rank_f : int\n            Rank of the between-class covariance matrix.\n        nb_iter : int\n            Number of iterations to run.\n        scaling_factor : float\n            Scaling factor to downscale statistics (value between 0 and 1).\n        output_file_name : str\n            Name of the output file where to store PLDA model.\n        \"\"\"\n\n        # Dimension of the vector (x-vectors stored in stats)\n        vect_size = emb_meta.stats.shape[1]\n\n        # Initialize mean and residual covariance from the training data\n        self.mean = emb_meta.get_mean_stats()\n        self.Sigma = emb_meta.get_total_covariance_stats()\n\n        # Sum stat0 and stat1 for each speaker model\n        model_shifted_stat, session_per_model = emb_meta.sum_stat_per_model()\n\n        # Number of speakers (classes) in training set\n        class_nb = model_shifted_stat.modelset.shape[0]\n\n        # Multiply statistics by scaling_factor\n        model_shifted_stat.stat0 *= self.scaling_factor\n        model_shifted_stat.stats *= self.scaling_factor\n        session_per_model *= self.scaling_factor\n\n        # Covariance for stats\n        sigma_obs = emb_meta.get_total_covariance_stats()\n        evals, evecs = linalg.eigh(sigma_obs)\n\n        # Initial F (eigen voice matrix) from rank\n        idx = numpy.argsort(evals)[::-1]\n        evecs = evecs.real[:, idx[:self.rank_f]]\n        self.F = evecs[:, :self.rank_f]\n\n        # Estimate PLDA model by iterating the EM algorithm\n        for it in range(self.nb_iter):\n\n            # E-step\n\n            # Copy stats as they will be whitened with a different Sigma for each iteration\n            local_stat = copy.deepcopy(model_shifted_stat)\n\n            # Whiten statistics (with the new mean and Sigma)\n            local_stat.whiten_stats(self.mean, self.Sigma)\n\n            # Whiten the EigenVoice matrix\n            eigen_values, eigen_vectors = linalg.eigh(self.Sigma)\n            ind = eigen_values.real.argsort()[::-1]\n            eigen_values = eigen_values.real[ind]\n            eigen_vectors = eigen_vectors.real[:, ind]\n            sqr_inv_eval_sigma = 1 / numpy.sqrt(eigen_values.real)\n            sqr_inv_sigma = numpy.dot(eigen_vectors,\n                                      numpy.diag(sqr_inv_eval_sigma))\n            self.F = sqr_inv_sigma.T.dot(self.F)\n\n            # Replicate self.stat0\n            index_map = numpy.zeros(vect_size, dtype=int)\n            _stat0 = local_stat.stat0[:, index_map]\n\n            e_h = numpy.zeros((class_nb, self.rank_f))\n            e_hh = numpy.zeros((class_nb, self.rank_f, self.rank_f))\n\n            # loop on model id's\n            fa_model_loop(\n                batch_start=0,\n                mini_batch_indices=numpy.arange(class_nb),\n                factor_analyser=self,\n                stat0=_stat0,\n                stats=local_stat.stats,\n                e_h=e_h,\n                e_hh=e_hh, )\n\n            # Accumulate for minimum divergence step\n            _R = numpy.sum(e_hh, axis=0) / session_per_model.shape[0]\n\n            _C = e_h.T.dot(local_stat.stats).dot(linalg.inv(sqr_inv_sigma))\n            _A = numpy.einsum(\"ijk,i->jk\", e_hh, local_stat.stat0.squeeze())\n\n            # M-step\n            self.F = linalg.solve(_A, _C).T\n\n            # Update the residual covariance\n            self.Sigma = sigma_obs - self.F.dot(_C) / session_per_model.sum()\n\n            # Minimum Divergence step\n            self.F = self.F.dot(linalg.cholesky(_R))\n\n    def scoring(\n            self,\n            enroll,\n            test,\n            ndx,\n            test_uncertainty=None,\n            Vtrans=None,\n            p_known=0.0,\n            scaling_factor=1.0,\n            check_missing=True, ):\n        \"\"\"\n        Compute the PLDA scores between to sets of vectors. The list of\n        trials to perform is given in an Ndx object. PLDA matrices have to be\n        pre-computed. i-vectors/x-vectors are supposed to be whitened before.\n\n        Arguments\n        ---------\n        enroll : paddlespeech.vector.cluster.diarization.EmbeddingMeta\n            A EmbeddingMeta in which stats are xvectors.\n        test : paddlespeech.vector.cluster.diarization.EmbeddingMeta\n            A EmbeddingMeta in which stats are xvectors.\n        ndx : paddlespeech.vector.cluster.plda.Ndx\n            An Ndx object defining the list of trials to perform.\n        p_known : float\n            Probability of having a known speaker for open-set\n            identification case (=1 for the verification task and =0 for the\n            closed-set case).\n        check_missing : bool\n            If True, check that all models and segments exist.\n        \"\"\"\n\n        enroll_ctr = copy.deepcopy(enroll)\n        test_ctr = copy.deepcopy(test)\n\n        # Remove missing models and test segments\n        if check_missing:\n            clean_ndx = _check_missing_model(enroll_ctr, test_ctr, ndx)\n        else:\n            clean_ndx = ndx\n\n        # Center the i-vectors around the PLDA mean\n        enroll_ctr.center_stats(self.mean)\n        test_ctr.center_stats(self.mean)\n\n        # Compute constant component of the PLDA distribution\n        invSigma = linalg.inv(self.Sigma)\n        I_spk = numpy.eye(self.F.shape[1], dtype=\"float\")\n\n        K = self.F.T.dot(invSigma * scaling_factor).dot(self.F)\n        K1 = linalg.inv(K + I_spk)\n        K2 = linalg.inv(2 * K + I_spk)\n\n        # Compute the Gaussian distribution constant\n        alpha1 = numpy.linalg.slogdet(K1)[1]\n        alpha2 = numpy.linalg.slogdet(K2)[1]\n        plda_cst = alpha2 / 2.0 - alpha1\n\n        # Compute intermediate matrices\n        Sigma_ac = numpy.dot(self.F, self.F.T)\n        Sigma_tot = Sigma_ac + self.Sigma\n        Sigma_tot_inv = linalg.inv(Sigma_tot)\n\n        Tmp = linalg.inv(Sigma_tot - Sigma_ac.dot(Sigma_tot_inv).dot(Sigma_ac))\n        Phi = Sigma_tot_inv - Tmp\n        Psi = Sigma_tot_inv.dot(Sigma_ac).dot(Tmp)\n\n        # Compute the different parts of PLDA score\n        model_part = 0.5 * numpy.einsum(\"ij, ji->i\",\n                                        enroll_ctr.stats.dot(Phi),\n                                        enroll_ctr.stats.T)\n        seg_part = 0.5 * numpy.einsum(\"ij, ji->i\",\n                                      test_ctr.stats.dot(Phi), test_ctr.stats.T)\n\n        # Compute verification scores\n        score = Scores()  # noqa F821\n        score.modelset = clean_ndx.modelset\n        score.segset = clean_ndx.segset\n        score.scoremask = clean_ndx.trialmask\n\n        score.scoremat = model_part[:, numpy.newaxis] + seg_part + plda_cst\n        score.scoremat += enroll_ctr.stats.dot(Psi).dot(test_ctr.stats.T)\n        score.scoremat *= scaling_factor\n\n        # Case of open-set identification, we compute the log-likelihood\n        # by taking into account the probability of having a known impostor\n        # or an out-of set class\n        if p_known != 0:\n            N = score.scoremat.shape[0]\n            open_set_scores = numpy.empty(score.scoremat.shape)\n            tmp = numpy.exp(score.scoremat)\n            for ii in range(N):\n                # open-set term\n                open_set_scores[ii, :] = score.scoremat[ii, :] - numpy.log(\n                    p_known * tmp[~(numpy.arange(N) == ii)].sum(axis=0) / (\n                        N - 1) + (1 - p_known))\n            score.scoremat = open_set_scores\n\n        return score\n\n\nif __name__ == '__main__':\n    import random\n\n    dim, N, n_spkrs = 10, 100, 10\n    train_xv = numpy.random.rand(N, dim)\n    md = ['md' + str(random.randrange(1, n_spkrs, 1)) for i in range(N)]  # spk\n    modelset = numpy.array(md, dtype=\"|O\")\n    sg = ['sg' + str(i) for i in range(N)]  # utt\n    segset = numpy.array(sg, dtype=\"|O\")\n    stat0 = numpy.array([[1.0]] * N)\n    xvectors_stat = EmbeddingMeta(\n        modelset=modelset, segset=segset, stats=train_xv)\n    # Training PLDA model: M ~ (mean, F, Sigma)\n    plda = PLDA(rank_f=5)\n    plda.plda(xvectors_stat)\n    print(plda.mean.shape)  #(10,)\n    print(plda.F.shape)  #(10, 5)\n    print(plda.Sigma.shape)  #(10, 10)\n    # Enrollment (20 utts),\n    en_N = 20\n    en_xv = numpy.random.rand(en_N, dim)\n    en_sgs = ['en' + str(i) for i in range(en_N)]\n    en_sets = numpy.array(en_sgs, dtype=\"|O\")\n    en_stat = EmbeddingMeta(modelset=en_sets, segset=en_sets, stats=en_xv)\n    # Test (30 utts)\n    te_N = 30\n    te_xv = numpy.random.rand(te_N, dim)\n    te_sgs = ['te' + str(i) for i in range(te_N)]\n    te_sets = numpy.array(te_sgs, dtype=\"|O\")\n    te_stat = EmbeddingMeta(modelset=te_sets, segset=te_sets, stats=te_xv)\n    ndx = Ndx(models=en_sets, testsegs=te_sets)  # trials\n    # PLDA Scoring\n    scores_plda = plda.scoring(en_stat, te_stat, ndx)\n    print(scores_plda.scoremat.shape)  #(20, 30)\n"
  },
  {
    "path": "paddlespeech/vector/exps/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/exps/ecapa_tdnn/extract_emb.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport time\n\nimport paddle\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.io.batch import feature_normalize\nfrom paddlespeech.vector.models.ecapa_tdnn import EcapaTdnn\nfrom paddlespeech.vector.modules.sid_model import SpeakerIdetification\nfrom paddlespeech.vector.training.seeding import seed_everything\n\nlogger = Log(__name__).getlog()\n\n\ndef extract_audio_embedding(args, config):\n    # stage 0: set the training device, cpu or gpu\n    paddle.set_device(args.device)\n    # set the random seed, it is a must for multiprocess training\n    seed_everything(config.seed)\n\n    # stage 1: build the dnn backbone model network\n    ecapa_tdnn = EcapaTdnn(**config.model)\n\n    # stage4: build the speaker verification train instance with backbone model\n    model = SpeakerIdetification(\n        backbone=ecapa_tdnn, num_class=config.num_speakers)\n    # stage 2: load the pre-trained model\n    args.load_checkpoint = os.path.abspath(\n        os.path.expanduser(args.load_checkpoint))\n\n    # load model checkpoint to sid model\n    state_dict = paddle.load(\n        os.path.join(args.load_checkpoint, 'model.pdparams'))\n    model.set_state_dict(state_dict)\n    logger.info(f'Checkpoint loaded from {args.load_checkpoint}')\n\n    # stage 3: we must set the model to eval mode\n    model.eval()\n\n    # stage 4: read the audio data and extract the embedding\n    # wavform is one dimension numpy array \n    waveform, sr = load_audio(args.audio_path)\n\n    # feat type is numpy array, whose shape is [dim, time]\n    # we need convert the audio feat to one-batch shape [batch, dim, time], where the batch is one\n    # so the final shape is [1, dim, time]\n    start_time = time.time()\n    feat = melspectrogram(\n        x=waveform,\n        sr=config.sr,\n        n_mels=config.n_mels,\n        window_size=config.window_size,\n        hop_length=config.hop_size)\n    feat = paddle.to_tensor(feat).unsqueeze(0)\n\n    # in inference period, the lengths is all one without padding\n    lengths = paddle.ones([1])\n    feat = feature_normalize(feat, mean_norm=True, std_norm=False)\n\n    # model backbone network forward the feats and get the embedding\n    embedding = model.backbone(\n        feat, lengths).squeeze().numpy()  # (1, emb_size, 1) -> (emb_size)\n    elapsed_time = time.time() - start_time\n    audio_length = waveform.shape[0] / sr\n\n    # stage 5: do global norm with external mean and std\n    rtf = elapsed_time / audio_length\n    logger.info(f\"{args.device} rft={rtf}\")\n\n    return embedding\n\n\nif __name__ == \"__main__\":\n    # yapf: disable\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument('--device',\n                        choices=['cpu', 'gpu'],\n                        default=\"cpu\",\n                        help=\"Select which device to train model, defaults to gpu.\")\n    parser.add_argument(\"--config\",\n                        default=None,\n                        type=str,\n                        help=\"configuration file\")\n    parser.add_argument(\"--load-checkpoint\",\n                        type=str,\n                        default='',\n                        help=\"Directory to load model checkpoint to contiune trainning.\")\n    parser.add_argument(\"--audio-path\",\n                        default=\"./data/demo.wav\",\n                        type=str,\n                        help=\"Single audio file path\")\n    args = parser.parse_args()\n    # yapf: enable\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n    print(config)\n\n    extract_audio_embedding(args, config)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ecapa_tdnn/test.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\n\nimport numpy as np\nimport paddle\nfrom paddle.io import BatchSampler\nfrom paddle.io import DataLoader\nfrom sklearn.metrics import roc_curve\nfrom tqdm import tqdm\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.io.batch import batch_feature_normalize\nfrom paddlespeech.vector.io.dataset import CSVDataset\nfrom paddlespeech.vector.io.embedding_norm import InputNormalization\nfrom paddlespeech.vector.models.ecapa_tdnn import EcapaTdnn\nfrom paddlespeech.vector.modules.sid_model import SpeakerIdetification\nfrom paddlespeech.vector.training.seeding import seed_everything\n\nlogger = Log(__name__).getlog()\n\n\ndef compute_dataset_embedding(data_loader, model, mean_var_norm_emb, config,\n                              id2embedding):\n    \"\"\"compute the dataset embeddings\n\n    Args:\n        data_loader (paddle.io.Dataloader): the dataset loader to be compute the embedding\n        model (paddle.nn.Layer): the speaker verification model\n        mean_var_norm_emb : compute the embedding mean and std norm\n        config (yacs.config.CfgNode): the yaml config\n    \"\"\"\n    logger.info(\n        f'Computing embeddings on {data_loader.dataset.csv_path} dataset')\n    with paddle.no_grad():\n        for batch_idx, batch in enumerate(tqdm(data_loader)):\n\n            # stage 8-1: extrac the audio embedding\n            ids, feats, lengths = batch['ids'], batch['feats'], batch['lengths']\n            embeddings = model.backbone(feats, lengths).squeeze(\n                -1)  # (N, emb_size, 1) -> (N, emb_size)\n\n            # Global embedding normalization.\n            # if we use the global embedding norm\n            # eer can reduece about relative 10%\n            if config.global_embedding_norm and mean_var_norm_emb:\n                lengths = paddle.ones([embeddings.shape[0]])\n                embeddings = mean_var_norm_emb(embeddings, lengths)\n\n            # Update embedding dict.\n            id2embedding.update(dict(zip(ids, embeddings)))\n\n\ndef compute_verification_scores(id2embedding, train_cohort, config):\n    \"\"\"Compute the verification trial scores\n\n    Args:\n        id2embedding (dict): the utterance embedding\n        train_cohort (paddle.tensor): the cohort dataset embedding\n        config (yacs.config.CfgNode): the yaml config\n\n    Returns:\n        the scores and the trial labels, \n        1 refers the target and 0 refers the nontarget in labels\n    \"\"\"\n    labels = []\n    enroll_ids = []\n    test_ids = []\n    logger.info(f\"read the trial from {config.verification_file}\")\n    cos_sim_func = paddle.nn.CosineSimilarity(axis=-1)\n    scores = []\n    with open(config.verification_file, 'r') as f:\n        for line in f.readlines():\n            label, enroll_id, test_id = line.strip().split(' ')\n            enroll_id = enroll_id.split('.')[0].replace('/', '-')\n            test_id = test_id.split('.')[0].replace('/', '-')\n            labels.append(int(label))\n\n            enroll_emb = id2embedding[enroll_id]\n            test_emb = id2embedding[test_id]\n            score = cos_sim_func(enroll_emb, test_emb).item()\n\n            if \"score_norm\" in config:\n                # Getting norm stats for enroll impostors\n                enroll_rep = paddle.tile(\n                    enroll_emb, repeat_times=[train_cohort.shape[0], 1])\n                score_e_c = cos_sim_func(enroll_rep, train_cohort)\n                if \"cohort_size\" in config:\n                    score_e_c, _ = paddle.topk(\n                        score_e_c, k=config.cohort_size, axis=0)\n                mean_e_c = paddle.mean(score_e_c, axis=0)\n                std_e_c = paddle.std(score_e_c, axis=0)\n\n                # Getting norm stats for test impostors\n                test_rep = paddle.tile(\n                    test_emb, repeat_times=[train_cohort.shape[0], 1])\n                score_t_c = cos_sim_func(test_rep, train_cohort)\n                if \"cohort_size\" in config:\n                    score_t_c, _ = paddle.topk(\n                        score_t_c, k=config.cohort_size, axis=0)\n                mean_t_c = paddle.mean(score_t_c, axis=0)\n                std_t_c = paddle.std(score_t_c, axis=0)\n\n                if config.score_norm == \"s-norm\":\n                    score_e = (score - mean_e_c) / std_e_c\n                    score_t = (score - mean_t_c) / std_t_c\n\n                    score = 0.5 * (score_e + score_t)\n                elif config.score_norm == \"z-norm\":\n                    score = (score - mean_e_c) / std_e_c\n                elif config.score_norm == \"t-norm\":\n                    score = (score - mean_t_c) / std_t_c\n\n            scores.append(score)\n\n    return scores, labels\n\n\ndef compute_eer(labels: np.ndarray, scores: np.ndarray) -> List[float]:\n    \"\"\"Compute EER and return score threshold.\n\n    Args:\n        labels (np.ndarray): the trial label, shape: [N], one-dimension, N refer to the samples num\n        scores (np.ndarray): the trial scores, shape: [N], one-dimension, N refer to the samples num\n\n    Returns:\n        List[float]: eer and the specific threshold\n    \"\"\"\n    fpr, tpr, threshold = roc_curve(y_true=labels, y_score=scores)\n    fnr = 1 - tpr\n    eer_threshold = threshold[np.nanargmin(np.absolute((fnr - fpr)))]\n    eer = fpr[np.nanargmin(np.absolute((fnr - fpr)))]\n    return eer, eer_threshold\n\n\ndef main(args, config):\n    \"\"\"The main process for test the speaker verification model\n\n    Args:\n        args (argparse.Namespace): the command line args namespace\n        config (yacs.config.CfgNode): the yaml config\n    \"\"\"\n\n    # stage0: set the training device, cpu or gpu\n    #         if set the gpu, paddlespeech will select a gpu according the env CUDA_VISIBLE_DEVICES\n    paddle.set_device(args.device)\n    # set the random seed, it is the necessary measures for multiprocess training\n    seed_everything(config.seed)\n\n    # stage1: build the dnn backbone model network\n    #         we will extract the audio embedding from the backbone model\n    ecapa_tdnn = EcapaTdnn(**config.model)\n\n    # stage2: build the speaker verification eval instance with backbone model\n    #         because the checkpoint dict name has the SpeakerIdetification prefix\n    #         so we need to create the SpeakerIdetification instance\n    #         but we acutally use the backbone model to extact the audio embedding \n    model = SpeakerIdetification(\n        backbone=ecapa_tdnn, num_class=config.num_speakers)\n\n    # stage3: load the pre-trained model\n    #         generally, we get the last model from the epoch\n    args.load_checkpoint = os.path.abspath(\n        os.path.expanduser(args.load_checkpoint))\n\n    # load model checkpoint to sid model\n    state_dict = paddle.load(\n        os.path.join(args.load_checkpoint, 'model.pdparams'))\n    model.set_state_dict(state_dict)\n    logger.info(f'Checkpoint loaded from {args.load_checkpoint}')\n\n    # stage4: construct the enroll and test dataloader\n    #         Now, wo think the enroll dataset is in the {args.data_dir}/vox/csv/enroll.csv,\n    #         and the test dataset is in the {args.data_dir}/vox/csv/test.csv\n    enroll_dataset = CSVDataset(\n        os.path.join(args.data_dir, \"vox/csv/enroll.csv\"),\n        feat_type='melspectrogram',\n        random_chunk=False,\n        n_mels=config.n_mels,\n        window_size=config.window_size,\n        hop_length=config.hop_size)\n    enroll_sampler = BatchSampler(\n        enroll_dataset, batch_size=config.batch_size, shuffle=False)\n    enroll_loader = DataLoader(enroll_dataset,\n                    batch_sampler=enroll_sampler,\n                    collate_fn=lambda x: batch_feature_normalize(\n                                x, mean_norm=True, std_norm=False),\n                    num_workers=config.num_workers,\n                    return_list=True,)\n\n    test_dataset = CSVDataset(\n        os.path.join(args.data_dir, \"vox/csv/test.csv\"),\n        feat_type='melspectrogram',\n        random_chunk=False,\n        n_mels=config.n_mels,\n        window_size=config.window_size,\n        hop_length=config.hop_size)\n    test_sampler = BatchSampler(\n        test_dataset, batch_size=config.batch_size, shuffle=False)\n    test_loader = DataLoader(test_dataset,\n                            batch_sampler=test_sampler,\n                            collate_fn=lambda x: batch_feature_normalize(\n                                x, mean_norm=True, std_norm=False),\n                            num_workers=config.num_workers,\n                            return_list=True,)\n    # stage5: we must set the model to eval mode\n    model.eval()\n\n    # stage6: global embedding norm to imporve the performance\n    #         and we create the InputNormalization instance to process the embedding mean and std norm\n    logger.info(f\"global embedding norm: {config.global_embedding_norm}\")\n    if config.global_embedding_norm:\n        mean_var_norm_emb = InputNormalization(\n            norm_type=\"global\",\n            mean_norm=config.embedding_mean_norm,\n            std_norm=config.embedding_std_norm)\n\n    # stage 7: score norm need the imposters dataset\n    #          we select the train dataset as the idea imposters dataset\n    #          and we select the config.n_train_snts utterance to as the final imposters dataset\n    if \"score_norm\" in config:\n        logger.info(f\"we will do score norm: {config.score_norm}\")\n        train_dataset = CSVDataset(\n            os.path.join(args.data_dir, \"vox/csv/train.csv\"),\n            feat_type='melspectrogram',\n            n_train_snts=config.n_train_snts,\n            random_chunk=False,\n            n_mels=config.n_mels,\n            window_size=config.window_size,\n            hop_length=config.hop_size)\n        train_sampler = BatchSampler(\n            train_dataset, batch_size=config.batch_size, shuffle=False)\n        train_loader = DataLoader(train_dataset,\n                            batch_sampler=train_sampler,\n                            collate_fn=lambda x: batch_feature_normalize(\n                                x, mean_norm=True, std_norm=False),\n                            num_workers=config.num_workers,\n                            return_list=True,)\n\n    # stage 8: Compute embeddings of audios in enrol and test dataset from model.\n    id2embedding = {}\n    # Run multi times to make embedding normalization more stable.\n    logger.info(\"First loop for enroll and test dataset\")\n    compute_dataset_embedding(enroll_loader, model, mean_var_norm_emb, config,\n                              id2embedding)\n    compute_dataset_embedding(test_loader, model, mean_var_norm_emb, config,\n                              id2embedding)\n\n    logger.info(\"Second loop for enroll and test dataset\")\n    compute_dataset_embedding(enroll_loader, model, mean_var_norm_emb, config,\n                              id2embedding)\n    compute_dataset_embedding(test_loader, model, mean_var_norm_emb, config,\n                              id2embedding)\n    mean_var_norm_emb.save(\n        os.path.join(args.load_checkpoint, \"mean_var_norm_emb\"))\n\n    # stage 9: Compute cosine scores.\n    train_cohort = None\n    if \"score_norm\" in config:\n        train_embeddings = {}\n        # cohort embedding not do mean and std norm\n        compute_dataset_embedding(train_loader, model, None, config,\n                                  train_embeddings)\n        train_cohort = paddle.stack(list(train_embeddings.values()))\n\n    # stage 10: compute the scores\n    scores, labels = compute_verification_scores(id2embedding, train_cohort,\n                                                 config)\n\n    # stage 11: compute the EER and threshold\n    scores = paddle.to_tensor(scores)\n    EER, threshold = compute_eer(np.asarray(labels), scores.numpy())\n    logger.info(\n        f'EER of verification test: {EER*100:.4f}%, score threshold: {threshold:.5f}'\n    )\n\n\nif __name__ == \"__main__\":\n    # yapf: disable\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument('--device',\n                        choices=['cpu', 'gpu'],\n                        default=\"gpu\",\n                        help=\"Select which device to train model, defaults to gpu.\")\n    parser.add_argument(\"--config\",\n                        default=None,\n                        type=str,\n                        help=\"configuration file\")\n    parser.add_argument(\"--data-dir\",\n                        default=\"./data/\",\n                        type=str,\n                        help=\"data directory\")\n    parser.add_argument(\"--load-checkpoint\",\n                        type=str,\n                        default='',\n                        help=\"Directory to load model checkpoint to contiune trainning.\")\n    args = parser.parse_args()\n    # yapf: enable\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n    print(config)\n    main(args, config)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ecapa_tdnn/train.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nimport os\nimport time\n\nimport numpy as np\nimport paddle\nfrom paddle.io import BatchSampler\nfrom paddle.io import DataLoader\nfrom paddle.io import DistributedBatchSampler\nfrom yacs.config import CfgNode\n\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.io.augment import build_augment_pipeline\nfrom paddlespeech.vector.io.augment import waveform_augment\nfrom paddlespeech.vector.io.batch import batch_pad_right\nfrom paddlespeech.vector.io.batch import feature_normalize\nfrom paddlespeech.vector.io.batch import waveform_collate_fn\nfrom paddlespeech.vector.io.dataset import CSVDataset\nfrom paddlespeech.vector.models.ecapa_tdnn import EcapaTdnn\nfrom paddlespeech.vector.modules.loss import AdditiveAngularMargin\nfrom paddlespeech.vector.modules.loss import LogSoftmaxWrapper\nfrom paddlespeech.vector.modules.sid_model import SpeakerIdetification\nfrom paddlespeech.vector.training.scheduler import CyclicLRScheduler\nfrom paddlespeech.vector.training.seeding import seed_everything\nfrom paddlespeech.vector.utils.time import Timer\n\nlogger = Log(__name__).getlog()\n\n\ndef main(args, config):\n    \"\"\"The main process for test the speaker verification model\n\n    Args:\n        args (argparse.Namespace): the command line args namespace\n        config (yacs.config.CfgNode): the yaml config\n    \"\"\"\n    # stage0: set the training device, cpu or gpu\n    paddle.set_device(args.device)\n\n    # stage1: we must call the paddle.distributed.init_parallel_env() api at the beginning\n    paddle.distributed.init_parallel_env()\n    nranks = paddle.distributed.get_world_size()\n    rank = paddle.distributed.get_rank()\n    # set the random seed, it is the necessary measures for multiprocess training\n    seed_everything(config.seed)\n\n    # stage2: data prepare, such vox1 and vox2 data, and augment noise data and pipline\n    # note: some operations must be done in rank==0\n    train_dataset = CSVDataset(\n        csv_path=os.path.join(args.data_dir, \"vox/csv/train.csv\"),\n        label2id_path=os.path.join(args.data_dir, \"vox/meta/label2id.txt\"))\n    dev_dataset = CSVDataset(\n        csv_path=os.path.join(args.data_dir, \"vox/csv/dev.csv\"),\n        label2id_path=os.path.join(args.data_dir, \"vox/meta/label2id.txt\"))\n\n    # we will build the augment pipeline process list\n    if config.augment:\n        augment_pipeline = build_augment_pipeline(target_dir=args.data_dir)\n    else:\n        augment_pipeline = []\n\n    # stage3: build the dnn backbone model network\n    #         in speaker verification period, we use the backbone mode to extract the audio embedding\n    ecapa_tdnn = EcapaTdnn(**config.model)\n\n    # stage4: build the speaker verification train instance with backbone model\n    model = SpeakerIdetification(\n        backbone=ecapa_tdnn, num_class=config.num_speakers)\n\n    # stage5: build the optimizer, we now only construct the AdamW optimizer\n    #         140000 is single gpu steps\n    #         so, in multi-gpu mode, wo reduce the step_size to 140000//nranks to enable CyclicLRScheduler\n    lr_schedule = CyclicLRScheduler(\n        base_lr=config.learning_rate,\n        max_lr=config.max_lr,\n        step_size=config.step_size // nranks)\n    optimizer = paddle.optimizer.AdamW(\n        learning_rate=lr_schedule, parameters=model.parameters())\n\n    # stage6: build the loss function, we now only support LogSoftmaxWrapper\n    criterion = LogSoftmaxWrapper(\n        loss_fn=AdditiveAngularMargin(margin=config.margin, scale=config.scale))\n\n    # stage7: confirm training start epoch\n    #         if pre-trained model exists, start epoch confirmed by the pre-trained model\n    start_epoch = 0\n    if args.load_checkpoint:\n        logger.info(\"load the check point\")\n        args.load_checkpoint = os.path.abspath(\n            os.path.expanduser(args.load_checkpoint))\n        try:\n            # load model checkpoint\n            state_dict = paddle.load(\n                os.path.join(args.load_checkpoint, 'model.pdparams'))\n            model.set_state_dict(state_dict)\n\n            # load optimizer checkpoint\n            state_dict = paddle.load(\n                os.path.join(args.load_checkpoint, 'model.pdopt'))\n            optimizer.set_state_dict(state_dict)\n            if rank == 0:\n                logger.info(f'Checkpoint loaded from {args.load_checkpoint}')\n        except FileExistsError:\n            if rank == 0:\n                logger.info('Train from scratch.')\n\n        try:\n            start_epoch = int(args.load_checkpoint[-1])\n            logger.info(f'Restore training from epoch {start_epoch}.')\n        except ValueError:\n            pass\n\n    # stage8: we build the batch sampler for paddle.DataLoader\n    train_sampler = DistributedBatchSampler(\n        train_dataset,\n        batch_size=config.batch_size,\n        shuffle=True,\n        drop_last=False)\n    train_loader = DataLoader(\n        train_dataset,\n        batch_sampler=train_sampler,\n        num_workers=config.num_workers,\n        collate_fn=waveform_collate_fn,\n        return_list=True,\n        use_buffer_reader=True, )\n\n    # stage9: start to train\n    #         we will comment the training process\n    steps_per_epoch = len(train_sampler)\n    timer = Timer(steps_per_epoch * config.epochs)\n    last_saved_epoch = \"\"\n    timer.start()\n\n    for epoch in range(start_epoch + 1, config.epochs + 1):\n        # at the beginning, model must set to train mode\n        model.train()\n\n        avg_loss = 0\n        num_corrects = 0\n        num_samples = 0\n        train_reader_cost = 0.0\n        train_feat_cost = 0.0\n        train_run_cost = 0.0\n\n        reader_start = time.time()\n        for batch_idx, batch in enumerate(train_loader):\n            train_reader_cost += time.time() - reader_start\n\n            # stage 9-1: batch data is audio sample points and speaker id label\n            feat_start = time.time()\n            waveforms, labels = batch['waveforms'], batch['labels']\n            waveforms, lengths = batch_pad_right(waveforms.numpy())\n            waveforms = paddle.to_tensor(waveforms)\n\n            # stage 9-2: audio sample augment method, which is done on the audio sample point\n            #            the original wavefrom and the augmented waveform is concatented in a batch\n            #            eg. five augment method in the augment pipeline\n            #                the final data nums is batch_size * [five + one] \n            #                -> five augmented waveform batch plus one original batch waveform\n            if len(augment_pipeline) != 0:\n                waveforms = waveform_augment(waveforms, augment_pipeline)\n                labels = paddle.concat(\n                    [labels for i in range(len(augment_pipeline) + 1)])\n\n            # stage 9-3: extract the audio feats,such fbank, mfcc, spectrogram\n            feats = []\n            for waveform in waveforms.numpy():\n                feat = melspectrogram(\n                    x=waveform,\n                    sr=config.sr,\n                    n_mels=config.n_mels,\n                    window_size=config.window_size,\n                    hop_length=config.hop_size)\n                feats.append(feat)\n            feats = paddle.to_tensor(np.asarray(feats))\n\n            # stage 9-4: feature normalize, which help converge and imporve the performance\n            feats = feature_normalize(\n                feats, mean_norm=True, std_norm=False)  # Features normalization\n            train_feat_cost += time.time() - feat_start\n\n            # stage 9-5: model forward, such ecapa-tdnn, x-vector\n            train_start = time.time()\n            logits = model(feats)\n\n            # stage 9-6: loss function criterion, such AngularMargin, AdditiveAngularMargin\n            loss = criterion(logits, labels)\n\n            # stage 9-7: update the gradient and clear the gradient cache\n            loss.backward()\n            optimizer.step()\n            if isinstance(optimizer._learning_rate,\n                          paddle.optimizer.lr.LRScheduler):\n                optimizer._learning_rate.step()\n            optimizer.clear_grad()\n\n            # stage 9-8: Calculate average loss per batch\n            avg_loss = loss.item()\n\n            # stage 9-9: Calculate metrics, which is one-best accuracy\n            preds = paddle.argmax(logits, axis=1)\n            num_corrects += (preds == labels).numpy().sum()\n            num_samples += feats.shape[0]\n            train_run_cost += time.time() - train_start\n            timer.count()  # step plus one in timer\n\n            # stage 9-10: print the log information only on 0-rank per log-freq batchs\n            if (batch_idx + 1) % config.log_interval == 0 and rank == 0:\n                lr = optimizer.get_lr()\n                avg_loss /= config.log_interval\n                avg_acc = num_corrects / num_samples\n\n                print_msg = 'Train Epoch={}/{}, Step={}/{}'.format(\n                    epoch, config.epochs, batch_idx + 1, steps_per_epoch)\n                print_msg += ' loss={:.4f}'.format(avg_loss)\n                print_msg += ' acc={:.4f}'.format(avg_acc)\n                print_msg += ' avg_reader_cost: {:.5f} sec,'.format(\n                    train_reader_cost / config.log_interval)\n                print_msg += ' avg_feat_cost: {:.5f} sec,'.format(\n                    train_feat_cost / config.log_interval)\n                print_msg += ' avg_train_cost: {:.5f} sec,'.format(\n                    train_run_cost / config.log_interval)\n\n                print_msg += ' lr={:.4E} step/sec={:.2f} ips={:.5f}| ETA {}'.format(\n                    lr, timer.timing, timer.ips, timer.eta)\n                logger.info(print_msg)\n\n                avg_loss = 0\n                num_corrects = 0\n                num_samples = 0\n                train_reader_cost = 0.0\n                train_feat_cost = 0.0\n                train_run_cost = 0.0\n\n            reader_start = time.time()\n\n        # stage 9-11: save the model parameters only on 0-rank per save-freq batchs\n        if epoch % config.save_interval == 0 and batch_idx + 1 == steps_per_epoch:\n            if rank != 0:\n                paddle.distributed.barrier(\n                )  # Wait for valid step in main process\n                continue  # Resume trainning on other process\n\n            # stage 9-12: construct the valid dataset dataloader\n            dev_sampler = BatchSampler(\n                dev_dataset,\n                batch_size=config.batch_size,\n                shuffle=False,\n                drop_last=False)\n            dev_loader = DataLoader(\n                dev_dataset,\n                batch_sampler=dev_sampler,\n                collate_fn=waveform_collate_fn,\n                num_workers=config.num_workers,\n                return_list=True, )\n\n            # set the model to eval mode\n            model.eval()\n            num_corrects = 0\n            num_samples = 0\n\n            # stage 9-13: evaluation the valid dataset batch data\n            logger.info('Evaluate on validation dataset')\n            with paddle.no_grad():\n                for batch_idx, batch in enumerate(dev_loader):\n                    waveforms, labels = batch['waveforms'], batch['labels']\n\n                    feats = []\n                    for waveform in waveforms.numpy():\n                        feat = melspectrogram(\n                            x=waveform,\n                            sr=config.sr,\n                            n_mels=config.n_mels,\n                            window_size=config.window_size,\n                            hop_length=config.hop_size)\n                        feats.append(feat)\n\n                    feats = paddle.to_tensor(np.asarray(feats))\n                    feats = feature_normalize(\n                        feats, mean_norm=True, std_norm=False)\n                    logits = model(feats)\n\n                    preds = paddle.argmax(logits, axis=1)\n                    num_corrects += (preds == labels).numpy().sum()\n                    num_samples += feats.shape[0]\n\n            print_msg = '[Evaluation result]'\n            print_msg += ' dev_acc={:.4f}'.format(num_corrects / num_samples)\n            logger.info(print_msg)\n\n            # stage 9-14: Save model parameters\n            save_dir = os.path.join(args.checkpoint_dir,\n                                    'epoch_{}'.format(epoch))\n            last_saved_epoch = os.path.join('epoch_{}'.format(epoch),\n                                            \"model.pdparams\")\n            logger.info('Saving model checkpoint to {}'.format(save_dir))\n            paddle.save(model.state_dict(),\n                        os.path.join(save_dir, 'model.pdparams'))\n            paddle.save(optimizer.state_dict(),\n                        os.path.join(save_dir, 'model.pdopt'))\n\n            if nranks > 1:\n                paddle.distributed.barrier()  # Main process\n\n    # stage 10: create the final trained model.pdparams with soft link\n    if rank == 0:\n        final_model = os.path.join(args.checkpoint_dir, \"model.pdparams\")\n        logger.info(f\"we will create the final model: {final_model}\")\n        if os.path.islink(final_model):\n            logger.info(\n                f\"An {final_model} already exists, we will rm is and create it again\"\n            )\n            os.unlink(final_model)\n        os.symlink(last_saved_epoch, final_model)\n\n\nif __name__ == \"__main__\":\n    # yapf: disable\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument('--device',\n                        choices=['cpu', 'gpu'],\n                        default=\"cpu\",\n                        help=\"Select which device to train model, defaults to gpu.\")\n    parser.add_argument(\"--config\",\n                        default=None,\n                        type=str,\n                        help=\"configuration file\")\n    parser.add_argument(\"--data-dir\",\n                        default=\"./data/\",\n                        type=str,\n                        help=\"data directory\")\n    parser.add_argument(\"--load-checkpoint\",\n                        type=str,\n                        default=None,\n                        help=\"Directory to load model checkpoint to contiune trainning.\")\n    parser.add_argument(\"--checkpoint-dir\",\n                        type=str,\n                        default='./checkpoint',\n                        help=\"Directory to save model checkpoints.\")\n\n    args = parser.parse_args()\n    # yapf: enable\n\n    # https://yaml.org/type/float.html\n    config = CfgNode(new_allowed=True)\n    if args.config:\n        config.merge_from_file(args.config)\n\n    config.freeze()\n    print(config)\n\n    main(args, config)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/__init__.py",
    "content": "# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/audio_processor.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport struct\nfrom pathlib import Path\nfrom warnings import warn\n\nimport librosa\nimport numpy as np\nfrom scipy.ndimage.morphology import binary_dilation\n\ntry:\n    import webrtcvad\nexcept ModuleNotFoundError:\n    warn(\"Unable to import 'webrtcvad'.\"\n         \"This package enables noise removal and is recommended.\")\n    webrtcvad = None\n\nINT16_MAX = (2**15) - 1\n\n\ndef normalize_volume(wav, target_dBFS, increase_only=False,\n                     decrease_only=False):\n    # this function implements Loudness normalization, instead of peak\n    # normalization, See https://en.wikipedia.org/wiki/Audio_normalization\n    # dBFS: Decibels relative to full scale\n    # See https://en.wikipedia.org/wiki/DBFS for more details\n    # for 16Bit PCM audio, minimal level is -96dB\n    # compute the mean dBFS and adjust to target dBFS, with by increasing\n    # or decreasing\n    if increase_only and decrease_only:\n        raise ValueError(\"Both increase only and decrease only are set\")\n    dBFS_change = target_dBFS - 10 * np.log10(np.mean(wav**2))\n    if dBFS_change < 0 and increase_only:\n        return wav\n    if dBFS_change > 0 and decrease_only:\n        return wav\n    gain = 10**(dBFS_change / 20)\n    return wav * gain\n\n\ndef trim_long_silences(wav,\n                       vad_window_length: int,\n                       vad_moving_average_width: int,\n                       vad_max_silence_length: int,\n                       sampling_rate: int):\n    \"\"\"\n    Ensures that segments without voice in the waveform remain no longer than a\n    threshold determined by the VAD parameters in params.py.\n    Parameters\n    ----------\n    wav : np.array\n        the raw waveform as a numpy array of floats\n    Returns\n    ----------\n    np.array\n        the same waveform with silences trimmed away (length <= original wav length)\n    \"\"\"\n    # Compute the voice detection window size\n    samples_per_window = (vad_window_length * sampling_rate) // 1000\n\n    # Trim the end of the audio to have a multiple of the window size\n    wav = wav[:len(wav) - (len(wav) % samples_per_window)]\n\n    # Convert the float waveform to 16-bit mono PCM\n    pcm_wave = struct.pack(\"%dh\" % len(wav),\n                           *(np.round(wav * INT16_MAX)).astype(np.int16))\n\n    # Perform voice activation detection\n    voice_flags = []\n    vad = webrtcvad.Vad(mode=3)\n    for window_start in range(0, len(wav), samples_per_window):\n        window_end = window_start + samples_per_window\n        voice_flags.append(\n            vad.is_speech(\n                pcm_wave[window_start * 2:window_end * 2],\n                sample_rate=sampling_rate))\n    voice_flags = np.array(voice_flags)\n\n    # Smooth the voice detection with a moving average\n    def moving_average(array, width):\n        array_padded = np.concatenate((np.zeros((width - 1) // 2), array,\n                                       np.zeros(width // 2)))\n        ret = np.cumsum(array_padded, dtype=float)\n        ret[width:] = ret[width:] - ret[:-width]\n        return ret[width - 1:] / width\n\n    audio_mask = moving_average(voice_flags, vad_moving_average_width)\n    audio_mask = np.round(audio_mask).astype(bool)\n\n    # Dilate the voiced regions\n    audio_mask = binary_dilation(audio_mask,\n                                 np.ones(vad_max_silence_length + 1))\n    audio_mask = np.repeat(audio_mask, samples_per_window)\n\n    return wav[audio_mask]\n\n\ndef compute_partial_slices(n_samples: int,\n                           partial_utterance_n_frames: int,\n                           hop_length: int,\n                           min_pad_coverage: float=0.75,\n                           overlap: float=0.5):\n    \"\"\"\n    Computes where to split an utterance waveform and its corresponding mel spectrogram to obtain\n    partial utterances of <partial_utterance_n_frames> each. Both the waveform and the mel\n    spectrogram slices are returned, so as to make each partial utterance waveform correspond to\n    its spectrogram. This function assumes that the mel spectrogram parameters used are those\n    defined in params_data.py.\n\n    The returned ranges may be indexing further than the length of the waveform. It is\n    recommended that you pad the waveform with zeros up to wave_slices[-1].stop.\n    Parameters\n    ----------\n    n_samples : int\n        the number of samples in the waveform.\n    partial_utterance_n_frames : int\n        the number of mel spectrogram frames in each partial utterance.\n\n    min_pad_coverage : int\n        when reaching the last partial utterance, it may or may not have enough frames.\n        If at least <min_pad_coverage> of <partial_utterance_n_frames> are present,\n        then the last partial utterance will be considered, as if we padded the audio. Otherwise,\n        it will be discarded, as if we trimmed the audio. If there aren't enough frames for 1 partial\n        utterance, this parameter is ignored so that the function always returns at least 1 slice.\n    overlap : float\n        by how much the partial utterance should overlap. If set to 0, the partial utterances are entirely disjoint.\n    Returns\n    ----------\n        the waveform slices and mel spectrogram slices as lists of array slices.\n        Index respectively the waveform and the mel spectrogram with these slices to obtain the partialutterances.\n    \"\"\"\n    assert 0 <= overlap < 1\n    assert 0 < min_pad_coverage <= 1\n\n    # librosa's function to compute num_frames from num_samples\n    n_frames = int(np.ceil((n_samples + 1) / hop_length))\n    # frame shift between ajacent partials\n    frame_step = max(1,\n                     int(np.round(partial_utterance_n_frames * (1 - overlap))))\n\n    # Compute the slices\n    wav_slices, mel_slices = [], []\n    steps = max(1, n_frames - partial_utterance_n_frames + frame_step + 1)\n    for i in range(0, steps, frame_step):\n        mel_range = np.array([i, i + partial_utterance_n_frames])\n        wav_range = mel_range * hop_length\n        mel_slices.append(slice(*mel_range))\n        wav_slices.append(slice(*wav_range))\n\n    # Evaluate whether extra padding is warranted or not\n    last_wav_range = wav_slices[-1]\n    coverage = (n_samples - last_wav_range.start) / (\n        last_wav_range.stop - last_wav_range.start)\n    if coverage < min_pad_coverage and len(mel_slices) > 1:\n        mel_slices = mel_slices[:-1]\n        wav_slices = wav_slices[:-1]\n\n    return wav_slices, mel_slices\n\n\nclass SpeakerVerificationPreprocessor(object):\n    def __init__(self,\n                 sampling_rate: int,\n                 audio_norm_target_dBFS: float,\n                 vad_window_length,\n                 vad_moving_average_width,\n                 vad_max_silence_length,\n                 mel_window_length,\n                 mel_window_step,\n                 n_mels,\n                 partial_n_frames: int,\n                 min_pad_coverage: float=0.75,\n                 partial_overlap_ratio: float=0.5):\n        self.sampling_rate = sampling_rate\n        self.audio_norm_target_dBFS = audio_norm_target_dBFS\n\n        self.vad_window_length = vad_window_length\n        self.vad_moving_average_width = vad_moving_average_width\n        self.vad_max_silence_length = vad_max_silence_length\n\n        self.n_fft = int(mel_window_length * sampling_rate / 1000)\n        self.hop_length = int(mel_window_step * sampling_rate / 1000)\n        self.n_mels = n_mels\n\n        self.partial_n_frames = partial_n_frames\n        self.min_pad_coverage = min_pad_coverage\n        self.partial_overlap_ratio = partial_overlap_ratio\n\n    def preprocess_wav(self, fpath_or_wav, source_sr=None):\n        # Load the wav from disk if needed\n        if isinstance(fpath_or_wav, (str, Path)):\n            wav, source_sr = librosa.load(str(fpath_or_wav), sr=None)\n        else:\n            wav = fpath_or_wav\n\n        # Resample if numpy.array is passed and sr does not match\n        if source_sr is not None and source_sr != self.sampling_rate:\n            wav = librosa.resample(\n                wav, orig_sr=source_sr, target_sr=self.sampling_rate)\n\n        # loudness normalization\n        wav = normalize_volume(\n            wav, self.audio_norm_target_dBFS, increase_only=True)\n\n        # trim long silence\n        if webrtcvad:\n            wav = trim_long_silences(\n                wav, self.vad_window_length, self.vad_moving_average_width,\n                self.vad_max_silence_length, self.sampling_rate)\n        return wav\n\n    def melspectrogram(self, wav):\n        mel = librosa.feature.melspectrogram(\n            y=wav,\n            sr=self.sampling_rate,\n            n_fft=self.n_fft,\n            hop_length=self.hop_length,\n            n_mels=self.n_mels)\n        mel = mel.astype(np.float32).T\n        return mel\n\n    def extract_mel_partials(self, wav):\n        wav_slices, mel_slices = compute_partial_slices(\n            len(wav), self.partial_n_frames, self.hop_length,\n            self.min_pad_coverage, self.partial_overlap_ratio)\n\n        # pad audio if needed\n        max_wave_length = wav_slices[-1].stop\n        if max_wave_length >= len(wav):\n            wav = np.pad(wav, (0, max_wave_length - len(wav)), \"constant\")\n\n        # Split the utterance into partials\n        frames = self.melspectrogram(wav)\n        frames_batch = np.array([frames[s] for s in mel_slices])\n        return frames_batch  # [B, T, C]\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/config.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom yacs.config import CfgNode\n\n_C = CfgNode()\n\ndata_config = _C.data = CfgNode()\n\n## Audio volume normalization\ndata_config.audio_norm_target_dBFS = -30\n\n## Audio sample rate\ndata_config.sampling_rate = 16000  # Hz\n\n## Voice Activation Detection\n# Window size of the VAD. Must be either 10, 20 or 30 milliseconds.\n# This sets the granularity of the VAD. Should not need to be changed.\ndata_config.vad_window_length = 30  # In milliseconds\n# Number of frames to average together when performing the moving average smoothing.\n# The larger this value, the larger the VAD variations must be to not get smoothed out.\ndata_config.vad_moving_average_width = 8\n# Maximum number of consecutive silent frames a segment can have.\ndata_config.vad_max_silence_length = 6\n\n## Mel-filterbank\ndata_config.mel_window_length = 25  # In milliseconds\ndata_config.mel_window_step = 10  # In milliseconds\ndata_config.n_mels = 40  # mel bands\n\n# Number of spectrogram frames in a partial utterance\ndata_config.partial_n_frames = 160  # 1600 ms\ndata_config.min_pad_coverage = 0.75  # at least 75% of the audio is valid in a partial\ndata_config.partial_overlap_ratio = 0.5  # overlap ratio between ajancent partials\n\nmodel_config = _C.model = CfgNode()\nmodel_config.num_layers = 3\nmodel_config.hidden_size = 256\nmodel_config.embedding_size = 256  # output size\n\ntraining_config = _C.training = CfgNode()\ntraining_config.learning_rate_init = 1e-4\ntraining_config.speakers_per_batch = 64\ntraining_config.utterances_per_speaker = 10\ntraining_config.max_iteration = 1560000\ntraining_config.save_interval = 10000\ntraining_config.valid_interval = 10000\n\n\ndef get_cfg_defaults():\n    return _C.clone()\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/dataset_processors.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport multiprocessing as mp\nfrom functools import partial\nfrom pathlib import Path\nfrom typing import List\n\nimport numpy as np\nfrom tqdm import tqdm\n\nfrom paddlespeech.vector.exps.ge2e.audio_processor import SpeakerVerificationPreprocessor\n\n\ndef _process_utterance(path_pair, processor: SpeakerVerificationPreprocessor):\n    # Load and preprocess the waveform\n    input_path, output_path = path_pair\n    wav = processor.preprocess_wav(input_path)\n    if len(wav) == 0:\n        return\n\n    # Create the mel spectrogram, discard those that are too short\n    frames = processor.melspectrogram(wav)\n    if len(frames) < processor.partial_n_frames:\n        return\n\n    np.save(output_path, frames)\n\n\ndef _process_speaker(speaker_dir: Path,\n                     processor: SpeakerVerificationPreprocessor,\n                     datasets_root: Path,\n                     output_dir: Path,\n                     pattern: str,\n                     skip_existing: bool=False):\n    # datastes root: a reference path to compute speaker_name\n    # we prepand dataset name to speaker_id becase we are mixing serveal\n    # multispeaker datasets together\n    speaker_name = \"_\".join(speaker_dir.relative_to(datasets_root).parts)\n    speaker_output_dir = output_dir / speaker_name\n    speaker_output_dir.mkdir(parents=True, exist_ok=True)\n\n    # load exsiting file set\n    sources_fpath = speaker_output_dir / \"_sources.txt\"\n    if sources_fpath.exists():\n        try:\n            with sources_fpath.open(\"rt\") as sources_file:\n                existing_names = {line.split(\",\")[0] for line in sources_file}\n        except Exception as e:\n            existing_names = {}\n    else:\n        existing_names = {}\n\n    sources_file = sources_fpath.open(\"at\" if skip_existing else \"wt\")\n    for in_fpath in speaker_dir.rglob(pattern):\n        out_name = \"_\".join(\n            in_fpath.relative_to(speaker_dir).with_suffix(\".npy\").parts)\n        if skip_existing and out_name in existing_names:\n            continue\n        out_fpath = speaker_output_dir / out_name\n        _process_utterance((in_fpath, out_fpath), processor)\n        sources_file.write(f\"{out_name},{in_fpath}\\n\")\n\n    sources_file.close()\n\n\ndef _process_dataset(processor: SpeakerVerificationPreprocessor,\n                     datasets_root: Path,\n                     speaker_dirs: List[Path],\n                     dataset_name: str,\n                     output_dir: Path,\n                     pattern: str,\n                     skip_existing: bool=False):\n    print(\n        f\"{dataset_name}: Preprocessing data for {len(speaker_dirs)} speakers.\")\n\n    _func = partial(\n        _process_speaker,\n        processor=processor,\n        datasets_root=datasets_root,\n        output_dir=output_dir,\n        pattern=pattern,\n        skip_existing=skip_existing)\n\n    with mp.Pool(16) as pool:\n        list(\n            tqdm(\n                pool.imap(_func, speaker_dirs),\n                dataset_name,\n                len(speaker_dirs),\n                unit=\"speakers\"))\n    print(f\"Done preprocessing {dataset_name}.\")\n\n\ndef process_librispeech(processor,\n                        datasets_root,\n                        output_dir,\n                        skip_existing=False):\n    dataset_name = \"LibriSpeech/train-other-500\"\n    dataset_root = datasets_root / dataset_name\n    speaker_dirs = list(dataset_root.glob(\"*\"))\n    _process_dataset(processor, datasets_root, speaker_dirs, dataset_name,\n                     output_dir, \"*.flac\", skip_existing)\n\n\ndef process_voxceleb1(processor, datasets_root, output_dir,\n                      skip_existing=False):\n    dataset_name = \"VoxCeleb1\"\n    dataset_root = datasets_root / dataset_name\n\n    anglophone_nationalites = [\"australia\", \"canada\", \"ireland\", \"uk\", \"usa\"]\n    with dataset_root.joinpath(\"vox1_meta.csv\").open(\"rt\") as metafile:\n        metadata = [line.strip().split(\"\\t\") for line in metafile][1:]\n\n    # speaker id -> nationality\n    nationalities = {line[0]: line[3] for line in metadata if line[-1] == \"dev\"}\n    keep_speaker_ids = [\n        speaker_id for speaker_id, nationality in nationalities.items()\n        if nationality.lower() in anglophone_nationalites\n    ]\n    print(\n        \"VoxCeleb1: using samples from {} (presumed anglophone) speakers out of {}.\"\n        .format(len(keep_speaker_ids), len(nationalities)))\n\n    speaker_dirs = list((dataset_root / \"wav\").glob(\"*\"))\n    speaker_dirs = [\n        speaker_dir for speaker_dir in speaker_dirs\n        if speaker_dir.name in keep_speaker_ids\n    ]\n    _process_dataset(processor, datasets_root, speaker_dirs, dataset_name,\n                     output_dir, \"*.wav\", skip_existing)\n\n\ndef process_voxceleb2(processor, datasets_root, output_dir,\n                      skip_existing=False):\n    dataset_name = \"VoxCeleb2\"\n    dataset_root = datasets_root / dataset_name\n    # There is no nationality in meta data for VoxCeleb2\n    speaker_dirs = list((dataset_root / \"wav\").glob(\"*\"))\n    _process_dataset(processor, datasets_root, speaker_dirs, dataset_name,\n                     output_dir, \"*.wav\", skip_existing)\n\n\ndef process_aidatatang_200zh(processor,\n                             datasets_root,\n                             output_dir,\n                             skip_existing=False):\n    dataset_name = \"aidatatang_200zh/train\"\n    dataset_root = datasets_root / dataset_name\n\n    speaker_dirs = list((dataset_root).glob(\"*\"))\n    _process_dataset(processor, datasets_root, speaker_dirs, dataset_name,\n                     output_dir, \"*.wav\", skip_existing)\n\n\ndef process_magicdata(processor, datasets_root, output_dir,\n                      skip_existing=False):\n    dataset_name = \"magicdata/train\"\n    dataset_root = datasets_root / dataset_name\n\n    speaker_dirs = list((dataset_root).glob(\"*\"))\n    _process_dataset(processor, datasets_root, speaker_dirs, dataset_name,\n                     output_dir, \"*.wav\", skip_existing)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/inference.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nimport numpy as np\nimport paddle\nimport tqdm\n\nfrom paddlespeech.vector.exps.ge2e.audio_processor import SpeakerVerificationPreprocessor\nfrom paddlespeech.vector.exps.ge2e.config import get_cfg_defaults\nfrom paddlespeech.vector.models.lstm_speaker_encoder import LSTMSpeakerEncoder\n\n\ndef embed_utterance(processor, model, fpath_or_wav):\n    # audio processor\n    wav = processor.preprocess_wav(fpath_or_wav)\n    mel_partials = processor.extract_mel_partials(wav)\n\n    model.eval()\n    # speaker encoder\n    with paddle.no_grad():\n        mel_partials = paddle.to_tensor(mel_partials)\n        with paddle.no_grad():\n            embed = model.embed_utterance(mel_partials)\n    embed = embed.numpy()\n    return embed\n\n\ndef _process_utterance(ifpath: Path,\n                       input_dir: Path,\n                       output_dir: Path,\n                       processor: SpeakerVerificationPreprocessor,\n                       model: LSTMSpeakerEncoder):\n    rel_path = ifpath.relative_to(input_dir)\n    ofpath = (output_dir / rel_path).with_suffix(\".npy\")\n    ofpath.parent.mkdir(parents=True, exist_ok=True)\n    embed = embed_utterance(processor, model, ifpath)\n    np.save(ofpath, embed)\n\n\ndef main(config, args):\n\n    if args.ngpu == 0:\n        paddle.set_device(\"cpu\")\n    elif args.ngpu > 0:\n        paddle.set_device(\"gpu\")\n    else:\n        print(\"ngpu should >= 0 !\")\n\n    # load model\n    model = LSTMSpeakerEncoder(config.data.n_mels, config.model.num_layers,\n                               config.model.hidden_size,\n                               config.model.embedding_size)\n    weights_fpath = str(Path(args.checkpoint_path).expanduser())\n    model_state_dict = paddle.load(weights_fpath + \".pdparams\")\n    model.set_state_dict(model_state_dict)\n    model.eval()\n    print(f\"Loaded encoder {weights_fpath}\")\n\n    # create audio processor\n    c = config.data\n    processor = SpeakerVerificationPreprocessor(\n        sampling_rate=c.sampling_rate,\n        audio_norm_target_dBFS=c.audio_norm_target_dBFS,\n        vad_window_length=c.vad_window_length,\n        vad_moving_average_width=c.vad_moving_average_width,\n        vad_max_silence_length=c.vad_max_silence_length,\n        mel_window_length=c.mel_window_length,\n        mel_window_step=c.mel_window_step,\n        n_mels=c.n_mels,\n        partial_n_frames=c.partial_n_frames,\n        min_pad_coverage=c.min_pad_coverage,\n        partial_overlap_ratio=c.min_pad_coverage, )\n\n    # input output preparation\n    input_dir = Path(args.input).expanduser()\n    ifpaths = list(input_dir.rglob(args.pattern))\n    print(f\"{len(ifpaths)} utterances in total\")\n    output_dir = Path(args.output).expanduser()\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    for ifpath in tqdm.tqdm(ifpaths, unit=\"utterance\"):\n        _process_utterance(ifpath, input_dir, output_dir, processor, model)\n\n\nif __name__ == \"__main__\":\n    config = get_cfg_defaults()\n    parser = argparse.ArgumentParser(description=\"compute utterance embed.\")\n    parser.add_argument(\n        \"--config\",\n        metavar=\"FILE\",\n        help=\"path of the config file to overwrite to default config with.\")\n    parser.add_argument(\n        \"--input\", type=str, help=\"path of the audio_file folder.\")\n    parser.add_argument(\n        \"--pattern\",\n        type=str,\n        default=\"*.wav\",\n        help=\"pattern to filter audio files.\")\n    parser.add_argument(\n        \"--output\",\n        metavar=\"OUTPUT_DIR\",\n        help=\"path to save checkpoint and logs.\")\n\n    # load from saved checkpoint\n    parser.add_argument(\n        \"--checkpoint_path\", type=str, help=\"path of the checkpoint to load\")\n\n    # overwrite extra config and default config\n    parser.add_argument(\n        \"--opts\",\n        nargs=argparse.REMAINDER,\n        help=\"options to overwrite --config file and the default config, passing in KEY VALUE pairs\"\n    )\n\n    parser.add_argument(\n        \"--ngpu\", type=int, default=1, help=\"if ngpu=0, use cpu.\")\n\n    args = parser.parse_args()\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    print(args)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/preprocess.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport argparse\nfrom pathlib import Path\n\nfrom paddlespeech.vector.exps.ge2e.audio_processor import SpeakerVerificationPreprocessor\nfrom paddlespeech.vector.exps.ge2e.config import get_cfg_defaults\nfrom paddlespeech.vector.exps.ge2e.dataset_processors import process_aidatatang_200zh\nfrom paddlespeech.vector.exps.ge2e.dataset_processors import process_librispeech\nfrom paddlespeech.vector.exps.ge2e.dataset_processors import process_magicdata\nfrom paddlespeech.vector.exps.ge2e.dataset_processors import process_voxceleb1\nfrom paddlespeech.vector.exps.ge2e.dataset_processors import process_voxceleb2\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"preprocess dataset for speaker verification task\")\n    parser.add_argument(\n        \"--datasets_root\",\n        type=Path,\n        help=\"Path to the directory containing your LibriSpeech, LibriTTS and VoxCeleb datasets.\"\n    )\n    parser.add_argument(\n        \"--output_dir\", type=Path, help=\"Path to save processed dataset.\")\n    parser.add_argument(\n        \"--dataset_names\",\n        type=str,\n        default=\"librispeech_other,voxceleb1,voxceleb2\",\n        help=\"comma-separated list of names of the datasets you want to preprocess. only \"\n        \"the train set of these datastes will be used. Possible names: librispeech_other, \"\n        \"voxceleb1, voxceleb2, aidatatang_200zh, magicdata.\")\n    parser.add_argument(\n        \"--skip_existing\",\n        action=\"store_true\",\n        help=\"Whether to skip output files with the same name. Useful if this script was interrupted.\"\n    )\n    parser.add_argument(\n        \"--no_trim\",\n        action=\"store_true\",\n        help=\"Preprocess audio without trimming silences (not recommended).\")\n\n    args = parser.parse_args()\n\n    if not args.no_trim:\n        try:\n            import webrtcvad\n            print(webrtcvad.__version__)\n        except Exception as e:\n            raise ModuleNotFoundError(\n                \"Package 'webrtcvad' not found. This package enables \"\n                \"noise removal and is recommended. Please install and \"\n                \"try again. If installation fails, \"\n                \"use --no_trim to disable this error message.\")\n    del args.no_trim\n\n    args.datasets = [item.strip() for item in args.dataset_names.split(\",\")]\n    if not hasattr(args, \"output_dir\"):\n        args.output_dir = args.dataset_root / \"SV2TTS\" / \"encoder\"\n\n    args.output_dir = args.output_dir.expanduser()\n    args.datasets_root = args.datasets_root.expanduser()\n    assert args.datasets_root.exists()\n    args.output_dir.mkdir(exist_ok=True, parents=True)\n\n    config = get_cfg_defaults()\n    print(args)\n\n    c = config.data\n    processor = SpeakerVerificationPreprocessor(\n        sampling_rate=c.sampling_rate,\n        audio_norm_target_dBFS=c.audio_norm_target_dBFS,\n        vad_window_length=c.vad_window_length,\n        vad_moving_average_width=c.vad_moving_average_width,\n        vad_max_silence_length=c.vad_max_silence_length,\n        mel_window_length=c.mel_window_length,\n        mel_window_step=c.mel_window_step,\n        n_mels=c.n_mels,\n        partial_n_frames=c.partial_n_frames,\n        min_pad_coverage=c.min_pad_coverage,\n        partial_overlap_ratio=c.min_pad_coverage, )\n\n    preprocess_func = {\n        \"librispeech_other\": process_librispeech,\n        \"voxceleb1\": process_voxceleb1,\n        \"voxceleb2\": process_voxceleb2,\n        \"aidatatang_200zh\": process_aidatatang_200zh,\n        \"magicdata\": process_magicdata,\n    }\n\n    for dataset in args.datasets:\n        print(\"Preprocessing %s\" % dataset)\n        preprocess_func[dataset](processor, args.datasets_root, args.output_dir,\n                                 args.skip_existing)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/random_cycle.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport random\n\n\ndef cycle(iterable):\n    # cycle('ABCD') --> A B C D A B C D A B C D ...\n    saved = []\n    for element in iterable:\n        yield element\n        saved.append(element)\n    while saved:\n        for element in saved:\n            yield element\n\n\ndef random_cycle(iterable):\n    # cycle('ABCD') --> A B C D B C D A A D B C ...\n    saved = []\n    for element in iterable:\n        yield element\n        saved.append(element)\n    random.shuffle(saved)\n    while saved:\n        for element in saved:\n            yield element\n        random.shuffle(saved)\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/speaker_verification_dataset.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport random\nfrom pathlib import Path\n\nimport numpy as np\nfrom paddle.io import BatchSampler\nfrom paddle.io import Dataset\n\nfrom paddlespeech.vector.exps.ge2e.random_cycle import random_cycle\n\n\nclass MultiSpeakerMelDataset(Dataset):\n    \"\"\"A 2 layer directory that contains mel spectrograms in *.npy format.\n    An Example file structure tree is shown below. We prefer to preprocess\n    raw datasets and organized them like this.\n\n    dataset_root/\n      speaker1/\n        utterance1.npy\n        utterance2.npy\n        utterance3.npy\n      speaker2/\n        utterance1.npy\n        utterance2.npy\n        utterance3.npy\n    \"\"\"\n\n    def __init__(self, dataset_root: Path):\n        self.root = Path(dataset_root).expanduser()\n        speaker_dirs = []\n        for f in self.root.glob(\"*\"):\n            if f.is_dir():\n                assert list(f.glob(\n                    \"*.npy\")), \"This folder NOT includes any npy data file.\"\n                speaker_dirs.append(f)\n\n        speaker_utterances = {\n            speaker_dir: list(speaker_dir.glob(\"*.npy\"))\n            for speaker_dir in speaker_dirs\n        }\n\n        self.speaker_dirs = speaker_dirs\n        self.speaker_to_utterances = speaker_utterances\n\n        # meta data\n        self.num_speakers = len(self.speaker_dirs)\n        self.num_utterances = np.sum(\n            len(utterances)\n            for speaker, utterances in self.speaker_to_utterances.items())\n\n    def get_example_by_index(self, speaker_index, utterance_index):\n        speaker_dir = self.speaker_dirs[speaker_index]\n        fpath = self.speaker_to_utterances[speaker_dir][utterance_index]\n        return self[fpath]\n\n    def __getitem__(self, fpath):\n        return np.load(fpath)\n\n    def __len__(self):\n        return int(self.num_utterances)\n\n\nclass MultiSpeakerSampler(BatchSampler):\n    \"\"\"A multi-stratal sampler designed for speaker verification task.\n    First, N speakers from all speakers are sampled randomly. Then, for each\n    speaker, randomly sample M utterances from their corresponding utterances.\n    \"\"\"\n\n    def __init__(self,\n                 dataset: MultiSpeakerMelDataset,\n                 speakers_per_batch: int,\n                 utterances_per_speaker: int):\n        self._speakers = list(dataset.speaker_dirs)\n        self._speaker_to_utterances = dataset.speaker_to_utterances\n\n        self.speakers_per_batch = speakers_per_batch\n        self.utterances_per_speaker = utterances_per_speaker\n\n    def __iter__(self):\n        # yield list of Paths\n        speaker_generator = iter(random_cycle(self._speakers))\n        speaker_utterances_generator = {\n            s: iter(random_cycle(us))\n            for s, us in self._speaker_to_utterances.items()\n        }\n\n        while True:\n            speakers = []\n            for _ in range(self.speakers_per_batch):\n                speakers.append(next(speaker_generator))\n\n            utterances = []\n            for s in speakers:\n                us = speaker_utterances_generator[s]\n                for _ in range(self.utterances_per_speaker):\n                    utterances.append(next(us))\n            yield utterances\n\n\nclass RandomClip(object):\n    def __init__(self, frames):\n        self.frames = frames\n\n    def __call__(self, spec):\n        # spec [T, C]\n        T = spec.shape[0]\n        start = random.randint(0, T - self.frames)\n        return spec[start:start + self.frames, :]\n\n\nclass Collate(object):\n    def __init__(self, num_frames):\n        self.random_crop = RandomClip(num_frames)\n\n    def __call__(self, examples):\n        frame_clips = [self.random_crop(mel) for mel in examples]\n        batced_clips = np.stack(frame_clips)\n        return batced_clips\n"
  },
  {
    "path": "paddlespeech/vector/exps/ge2e/train.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\n\nfrom paddle import DataParallel\nfrom paddle import distributed as dist\nfrom paddle.io import DataLoader\nfrom paddle.nn.clip import ClipGradByGlobalNorm\nfrom paddle.optimizer import Adam\n\nfrom paddlespeech.t2s.training import default_argument_parser\nfrom paddlespeech.t2s.training import ExperimentBase\nfrom paddlespeech.vector.exps.ge2e.config import get_cfg_defaults\nfrom paddlespeech.vector.exps.ge2e.speaker_verification_dataset import Collate\nfrom paddlespeech.vector.exps.ge2e.speaker_verification_dataset import MultiSpeakerMelDataset\nfrom paddlespeech.vector.exps.ge2e.speaker_verification_dataset import MultiSpeakerSampler\nfrom paddlespeech.vector.models.lstm_speaker_encoder import LSTMSpeakerEncoder\n\n\nclass Ge2eExperiment(ExperimentBase):\n    def setup_model(self):\n        config = self.config\n        model = LSTMSpeakerEncoder(config.data.n_mels, config.model.num_layers,\n                                   config.model.hidden_size,\n                                   config.model.embedding_size)\n        optimizer = Adam(\n            config.training.learning_rate_init,\n            parameters=model.parameters(),\n            grad_clip=ClipGradByGlobalNorm(3))\n        self.model = DataParallel(model) if self.parallel else model\n        self.model_core = model\n        self.optimizer = optimizer\n\n    def setup_dataloader(self):\n        config = self.config\n        train_dataset = MultiSpeakerMelDataset(self.args.data)\n        sampler = MultiSpeakerSampler(train_dataset,\n                                      config.training.speakers_per_batch,\n                                      config.training.utterances_per_speaker)\n        train_loader = DataLoader(\n            train_dataset,\n            batch_sampler=sampler,\n            collate_fn=Collate(config.data.partial_n_frames),\n            num_workers=16)\n\n        self.train_dataset = train_dataset\n        self.train_loader = train_loader\n\n    def train_batch(self):\n        start = time.time()\n        batch = self.read_batch()\n        data_loader_time = time.time() - start\n\n        self.optimizer.clear_grad()\n        self.model.train()\n        specs = batch\n        loss, eer = self.model(specs, self.config.training.speakers_per_batch)\n        loss.backward()\n        self.model_core.do_gradient_ops()\n        self.optimizer.step()\n        iteration_time = time.time() - start\n\n        # logging\n        loss_value = float(loss)\n        msg = \"Rank: {}, \".format(dist.get_rank())\n        msg += \"step: {}, \".format(self.iteration)\n        msg += \"time: {:>.3f}s/{:>.3f}s, \".format(data_loader_time,\n                                                  iteration_time)\n        msg += 'loss: {:>.6f} err: {:>.6f}'.format(loss_value, eer)\n        self.logger.info(msg)\n\n        if dist.get_rank() == 0:\n            self.visualizer.add_scalar(\"train/loss\", loss_value, self.iteration)\n            self.visualizer.add_scalar(\"train/eer\", eer, self.iteration)\n            self.visualizer.add_scalar(\"param/w\",\n                                       float(self.model_core.similarity_weight),\n                                       self.iteration)\n            self.visualizer.add_scalar(\"param/b\",\n                                       float(self.model_core.similarity_bias),\n                                       self.iteration)\n\n    def valid(self):\n        pass\n\n\ndef main_sp(config, args):\n    exp = Ge2eExperiment(config, args)\n    exp.setup()\n    exp.resume_or_load()\n    exp.run()\n\n\ndef main(config, args):\n    if args.ngpu > 1:\n        dist.spawn(main_sp, args=(config, args), nprocs=args.ngpu)\n    else:\n        main_sp(config, args)\n\n\nif __name__ == \"__main__\":\n    config = get_cfg_defaults()\n    parser = default_argument_parser()\n    args = parser.parse_args()\n    if args.config:\n        config.merge_from_file(args.config)\n    if args.opts:\n        config.merge_from_list(args.opts)\n    config.freeze()\n    print(config)\n    print(args)\n\n    main(config, args)\n"
  },
  {
    "path": "paddlespeech/vector/io/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/io/augment.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# this is modified from SpeechBrain\n# https://github.com/speechbrain/speechbrain/blob/085be635c07f16d42cd1295045bc46c407f1e15b/speechbrain/lobes/augment.py\nimport math\nimport os\nfrom typing import List\n\nimport numpy as np\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\nfrom paddlespeech.s2t.utils.log import Log\nfrom paddlespeech.vector.io.dataset import CSVDataset\nfrom paddlespeech.vector.io.signal_processing import compute_amplitude\nfrom paddlespeech.vector.io.signal_processing import convolve1d\nfrom paddlespeech.vector.io.signal_processing import dB_to_amplitude\nfrom paddlespeech.vector.io.signal_processing import notch_filter\nfrom paddlespeech.vector.io.signal_processing import reverberate\n\nlogger = Log(__name__).getlog()\n\n\n# TODO: Complete type-hint and doc string.\nclass DropFreq(nn.Layer):\n    def __init__(\n            self,\n            drop_freq_low=1e-14,\n            drop_freq_high=1,\n            drop_count_low=1,\n            drop_count_high=2,\n            drop_width=0.05,\n            drop_prob=1, ):\n        super(DropFreq, self).__init__()\n        self.drop_freq_low = drop_freq_low\n        self.drop_freq_high = drop_freq_high\n        self.drop_count_low = drop_count_low\n        self.drop_count_high = drop_count_high\n        self.drop_width = drop_width\n        self.drop_prob = drop_prob\n\n    def forward(self, waveforms):\n        # Don't drop (return early) 1-`drop_prob` portion of the batches\n        dropped_waveform = waveforms.clone()\n        if paddle.rand([1]) > self.drop_prob:\n            return dropped_waveform\n\n        # Add channels dimension\n        if len(waveforms.shape) == 2:\n            dropped_waveform = dropped_waveform.unsqueeze(-1)\n\n        # Pick number of frequencies to drop\n        drop_count = paddle.randint(\n            low=self.drop_count_low, high=self.drop_count_high + 1, shape=[1])\n\n        # Pick a frequency to drop\n        drop_range = self.drop_freq_high - self.drop_freq_low\n        drop_frequency = (\n            paddle.rand([drop_count]) * drop_range + self.drop_freq_low)\n\n        # Filter parameters\n        filter_length = 101\n        pad = filter_length // 2\n\n        # Start with delta function\n        drop_filter = paddle.zeros([1, filter_length, 1])\n        drop_filter[0, pad, 0] = 1\n\n        # Subtract each frequency\n        for frequency in drop_frequency:\n            notch_kernel = notch_filter(frequency, filter_length,\n                                        self.drop_width)\n            drop_filter = convolve1d(drop_filter, notch_kernel, pad)\n\n        # Apply filter\n        dropped_waveform = convolve1d(dropped_waveform, drop_filter, pad)\n\n        # Remove channels dimension if added\n        return dropped_waveform.squeeze(-1)\n\n\nclass DropChunk(nn.Layer):\n    def __init__(\n            self,\n            drop_length_low=100,\n            drop_length_high=1000,\n            drop_count_low=1,\n            drop_count_high=10,\n            drop_start=0,\n            drop_end=None,\n            drop_prob=1,\n            noise_factor=0.0, ):\n        super(DropChunk, self).__init__()\n        self.drop_length_low = drop_length_low\n        self.drop_length_high = drop_length_high\n        self.drop_count_low = drop_count_low\n        self.drop_count_high = drop_count_high\n        self.drop_start = drop_start\n        self.drop_end = drop_end\n        self.drop_prob = drop_prob\n        self.noise_factor = noise_factor\n\n        # Validate low < high\n        if drop_length_low > drop_length_high:\n            raise ValueError(\"Low limit must not be more than high limit\")\n        if drop_count_low > drop_count_high:\n            raise ValueError(\"Low limit must not be more than high limit\")\n\n        # Make sure the length doesn't exceed end - start\n        if drop_end is not None and drop_end >= 0:\n            if drop_start > drop_end:\n                raise ValueError(\"Low limit must not be more than high limit\")\n\n            drop_range = drop_end - drop_start\n            self.drop_length_low = min(drop_length_low, drop_range)\n            self.drop_length_high = min(drop_length_high, drop_range)\n\n    def forward(self, waveforms, lengths):\n        # Reading input list\n        lengths = (lengths * waveforms.shape[1]).astype('int64')\n        batch_size = waveforms.shape[0]\n        dropped_waveform = waveforms.clone()\n\n        # Don't drop (return early) 1-`drop_prob` portion of the batches\n        if paddle.rand([1]) > self.drop_prob:\n            return dropped_waveform\n\n        # Store original amplitude for computing white noise amplitude\n        clean_amplitude = compute_amplitude(waveforms, lengths.unsqueeze(1))\n\n        # Pick a number of times to drop\n        drop_times = paddle.randint(\n            low=self.drop_count_low,\n            high=self.drop_count_high + 1,\n            shape=[batch_size], )\n\n        # Iterate batch to set mask\n        for i in range(batch_size):\n            if drop_times[i] == 0:\n                continue\n\n            # Pick lengths\n            length = paddle.randint(\n                low=self.drop_length_low,\n                high=self.drop_length_high + 1,\n                shape=[drop_times[i]], )\n\n            # Compute range of starting locations\n            start_min = self.drop_start\n            if start_min < 0:\n                start_min += lengths[i]\n            start_max = self.drop_end\n            if start_max is None:\n                start_max = lengths[i]\n            if start_max < 0:\n                start_max += lengths[i]\n            start_max = max(0, start_max - length.max())\n\n            # Pick starting locations\n            start = paddle.randint(\n                low=start_min,\n                high=start_max + 1,\n                shape=[drop_times[i]], )\n\n            end = start + length\n\n            # Update waveform\n            if not self.noise_factor:\n                for j in range(drop_times[i]):\n                    if start[j] < end[j]:\n                        dropped_waveform[i, start[j]:end[j]] = 0.0\n            else:\n                # Uniform distribution of -2 to +2 * avg amplitude should\n                # preserve the average for normalization\n                noise_max = 2 * clean_amplitude[i] * self.noise_factor\n                for j in range(drop_times[i]):\n                    # zero-center the noise distribution\n                    noise_vec = paddle.rand([length[j]], dtype='float32')\n\n                    noise_vec = 2 * noise_max * noise_vec - noise_max\n                    dropped_waveform[i, int(start[j]):int(end[j])] = noise_vec\n\n        return dropped_waveform\n\n\nclass Resample(nn.Layer):\n    def __init__(\n            self,\n            orig_freq=16000,\n            new_freq=16000,\n            lowpass_filter_width=6, ):\n        super(Resample, self).__init__()\n        self.orig_freq = orig_freq\n        self.new_freq = new_freq\n        self.lowpass_filter_width = lowpass_filter_width\n\n        # Compute rate for striding\n        self._compute_strides()\n        assert self.orig_freq % self.conv_stride == 0\n        assert self.new_freq % self.conv_transpose_stride == 0\n\n    def _compute_strides(self):\n        # Compute new unit based on ratio of in/out frequencies\n        base_freq = math.gcd(self.orig_freq, self.new_freq)\n        input_samples_in_unit = self.orig_freq // base_freq\n        self.output_samples = self.new_freq // base_freq\n\n        # Store the appropriate stride based on the new units\n        self.conv_stride = input_samples_in_unit\n        self.conv_transpose_stride = self.output_samples\n\n    def forward(self, waveforms):\n        if not hasattr(self, \"first_indices\"):\n            self._indices_and_weights(waveforms)\n\n        # Don't do anything if the frequencies are the same\n        if self.orig_freq == self.new_freq:\n            return waveforms\n\n        unsqueezed = False\n        if len(waveforms.shape) == 2:\n            waveforms = waveforms.unsqueeze(1)\n            unsqueezed = True\n        elif len(waveforms.shape) == 3:\n            waveforms = waveforms.transpose([0, 2, 1])\n        else:\n            raise ValueError(\"Input must be 2 or 3 dimensions\")\n\n        # Do resampling\n        resampled_waveform = self._perform_resample(waveforms)\n\n        if unsqueezed:\n            resampled_waveform = resampled_waveform.squeeze(1)\n        else:\n            resampled_waveform = resampled_waveform.transpose([0, 2, 1])\n\n        return resampled_waveform\n\n    def _perform_resample(self, waveforms):\n        # Compute output size and initialize\n        batch_size, num_channels, wave_len = waveforms.shape\n        window_size = self.weights.shape[1]\n        tot_output_samp = self._output_samples(wave_len)\n        resampled_waveform = paddle.zeros((batch_size, num_channels,\n                                           tot_output_samp))\n\n        # eye size: (num_channels, num_channels, 1)\n        eye = paddle.eye(num_channels).unsqueeze(2)\n\n        # Iterate over the phases in the polyphase filter\n        for i in range(self.first_indices.shape[0]):\n            wave_to_conv = waveforms\n            first_index = int(self.first_indices[i].item())\n            if first_index >= 0:\n                # trim the signal as the filter will not be applied\n                # before the first_index\n                wave_to_conv = wave_to_conv[:, :, first_index:]\n\n            # pad the right of the signal to allow partial convolutions\n            # meaning compute values for partial windows (e.g. end of the\n            # window is outside the signal length)\n            max_index = (tot_output_samp - 1) // self.output_samples\n            end_index = max_index * self.conv_stride + window_size\n            current_wave_len = wave_len - first_index\n            right_padding = max(0, end_index + 1 - current_wave_len)\n            left_padding = max(0, -first_index)\n            wave_to_conv = paddle.nn.functional.pad(\n                wave_to_conv, [left_padding, right_padding], data_format='NCL')\n            conv_wave = paddle.nn.functional.conv1d(\n                x=wave_to_conv,\n                # weight=self.weights[i].repeat(num_channels, 1, 1),\n                weight=self.weights[i].expand((num_channels, 1, -1)),\n                stride=self.conv_stride,\n                groups=num_channels, )\n\n            # we want conv_wave[:, i] to be at\n            # output[:, i + n*conv_transpose_stride]\n            dilated_conv_wave = paddle.nn.functional.conv1d_transpose(\n                conv_wave, eye, stride=self.conv_transpose_stride)\n\n            # pad dilated_conv_wave so it reaches the output length if needed.\n            left_padding = i\n            previous_padding = left_padding + dilated_conv_wave.shape[-1]\n            right_padding = max(0, tot_output_samp - previous_padding)\n            dilated_conv_wave = paddle.nn.functional.pad(\n                dilated_conv_wave, [left_padding, right_padding],\n                data_format='NCL')\n            dilated_conv_wave = dilated_conv_wave[:, :, :tot_output_samp]\n\n            resampled_waveform += dilated_conv_wave\n\n        return resampled_waveform\n\n    def _output_samples(self, input_num_samp):\n        samp_in = int(self.orig_freq)\n        samp_out = int(self.new_freq)\n\n        tick_freq = abs(samp_in * samp_out) // math.gcd(samp_in, samp_out)\n        ticks_per_input_period = tick_freq // samp_in\n\n        # work out the number of ticks in the time interval\n        # [ 0, input_num_samp/samp_in ).\n        interval_length = input_num_samp * ticks_per_input_period\n        if interval_length <= 0:\n            return 0\n        ticks_per_output_period = tick_freq // samp_out\n\n        # Get the last output-sample in the closed interval,\n        # i.e. replacing [ ) with [ ]. Note: integer division rounds down.\n        # See http://en.wikipedia.org/wiki/Interval_(mathematics) for an\n        # explanation of the notation.\n        last_output_samp = interval_length // ticks_per_output_period\n\n        # We need the last output-sample in the open interval, so if it\n        # takes us to the end of the interval exactly, subtract one.\n        if last_output_samp * ticks_per_output_period == interval_length:\n            last_output_samp -= 1\n\n        # First output-sample index is zero, so the number of output samples\n        # is the last output-sample plus one.\n        num_output_samp = last_output_samp + 1\n\n        return num_output_samp\n\n    def _indices_and_weights(self, waveforms):\n        # Lowpass filter frequency depends on smaller of two frequencies\n        min_freq = min(self.orig_freq, self.new_freq)\n        lowpass_cutoff = 0.99 * 0.5 * min_freq\n\n        assert lowpass_cutoff * 2 <= min_freq\n        window_width = self.lowpass_filter_width / (2.0 * lowpass_cutoff)\n\n        assert lowpass_cutoff < min(self.orig_freq, self.new_freq) / 2\n        output_t = paddle.arange(\n            start=0.0, end=self.output_samples, dtype='int64')\n        output_t /= self.new_freq\n        min_t = output_t - window_width\n        max_t = output_t + window_width\n\n        min_input_index = paddle.ceil(min_t * self.orig_freq)\n        max_input_index = paddle.floor(max_t * self.orig_freq)\n        num_indices = max_input_index - min_input_index + 1\n\n        max_weight_width = num_indices.max()\n        j = paddle.arange(max_weight_width, dtype='float32')\n        input_index = min_input_index.unsqueeze(1) + j.unsqueeze(0)\n        delta_t = (input_index / self.orig_freq) - output_t.unsqueeze(1)\n\n        weights = paddle.zeros_like(delta_t)\n        inside_window_indices = delta_t.abs().less_than(\n            paddle.to_tensor(window_width))\n\n        # raised-cosine (Hanning) window with width `window_width`\n        weights[inside_window_indices] = 0.5 * (1 + paddle.cos(\n            2 * math.pi * lowpass_cutoff / self.lowpass_filter_width *\n            delta_t.masked_select(inside_window_indices)))\n\n        t_eq_zero_indices = delta_t.equal(paddle.zeros_like(delta_t))\n        t_not_eq_zero_indices = delta_t.not_equal(paddle.zeros_like(delta_t))\n\n        # sinc filter function\n        weights = paddle.where(\n            t_not_eq_zero_indices,\n            weights * paddle.sin(2 * math.pi * lowpass_cutoff * delta_t) /\n            (math.pi * delta_t), weights)\n\n        # limit of the function at t = 0\n        weights = paddle.where(t_eq_zero_indices, weights * 2 * lowpass_cutoff,\n                               weights)\n\n        # size (output_samples, max_weight_width)\n        weights /= self.orig_freq\n\n        self.first_indices = min_input_index\n        self.weights = weights\n\n\nclass SpeedPerturb(nn.Layer):\n    def __init__(\n            self,\n            orig_freq,\n            speeds=[90, 100, 110],\n            perturb_prob=1.0, ):\n        super(SpeedPerturb, self).__init__()\n        self.orig_freq = orig_freq\n        self.speeds = speeds\n        self.perturb_prob = perturb_prob\n\n        # Initialize index of perturbation\n        self.samp_index = 0\n\n        # Initialize resamplers\n        self.resamplers = []\n        for speed in self.speeds:\n            config = {\n                \"orig_freq\": self.orig_freq,\n                \"new_freq\": self.orig_freq * speed // 100,\n            }\n            self.resamplers.append(Resample(**config))\n\n    def forward(self, waveform):\n        # Don't perturb (return early) 1-`perturb_prob` portion of the batches\n        if paddle.rand([1]) > self.perturb_prob:\n            return waveform.clone()\n\n        # Perform a random perturbation\n        self.samp_index = paddle.randint(len(self.speeds), shape=[1]).item()\n        perturbed_waveform = self.resamplers[self.samp_index](waveform)\n\n        return perturbed_waveform\n\n\nclass AddNoise(nn.Layer):\n    def __init__(\n            self,\n            noise_dataset=None,  # None for white noise\n            num_workers=0,\n            snr_low=0,\n            snr_high=0,\n            mix_prob=1.0,\n            start_index=None,\n            normalize=False, ):\n        super(AddNoise, self).__init__()\n\n        self.num_workers = num_workers\n        self.snr_low = snr_low\n        self.snr_high = snr_high\n        self.mix_prob = mix_prob\n        self.start_index = start_index\n        self.normalize = normalize\n        self.noise_dataset = noise_dataset\n        self.noise_dataloader = None\n\n    def forward(self, waveforms, lengths=None):\n        if lengths is None:\n            lengths = paddle.ones([len(waveforms)])\n\n        # Copy clean waveform to initialize noisy waveform\n        noisy_waveform = waveforms.clone()\n        lengths = (lengths * waveforms.shape[1]).astype('int64').unsqueeze(1)\n\n        # Don't add noise (return early) 1-`mix_prob` portion of the batches\n        if paddle.rand([1]) > self.mix_prob:\n            return noisy_waveform\n\n        # Compute the average amplitude of the clean waveforms\n        clean_amplitude = compute_amplitude(waveforms, lengths)\n\n        # Pick an SNR and use it to compute the mixture amplitude factors\n        SNR = paddle.rand((len(waveforms), 1))\n        SNR = SNR * (self.snr_high - self.snr_low) + self.snr_low\n        noise_amplitude_factor = 1 / (dB_to_amplitude(SNR) + 1)\n        new_noise_amplitude = noise_amplitude_factor * clean_amplitude\n\n        # Scale clean signal appropriately\n        noisy_waveform *= 1 - noise_amplitude_factor\n\n        # Loop through clean samples and create mixture\n        if self.noise_dataset is None:\n            white_noise = paddle.normal(shape=waveforms.shape)\n            noisy_waveform += new_noise_amplitude * white_noise\n        else:\n            tensor_length = waveforms.shape[1]\n            noise_waveform, noise_length = self._load_noise(\n                lengths,\n                tensor_length, )\n\n            # Rescale and add\n            noise_amplitude = compute_amplitude(noise_waveform, noise_length)\n            noise_waveform *= new_noise_amplitude / (noise_amplitude + 1e-14)\n            noisy_waveform += noise_waveform\n\n        # Normalizing to prevent clipping\n        if self.normalize:\n            abs_max, _ = paddle.max(\n                paddle.abs(noisy_waveform), axis=1, keepdim=True)\n            noisy_waveform = noisy_waveform / abs_max.clip(min=1.0)\n\n        return noisy_waveform\n\n    def _load_noise(self, lengths, max_length):\n        \"\"\"\n        Load a batch of noises\n\n        args\n        lengths(Paddle.Tensor): Num samples of waveforms with shape (N, 1).\n        max_length(int): Width of a batch.\n        \"\"\"\n        lengths = lengths.squeeze(1)\n        batch_size = len(lengths)\n\n        # Load a noise batch\n        if self.noise_dataloader is None:\n\n            def noise_collate_fn(batch):\n                def pad(x, target_length, mode='constant', **kwargs):\n                    x = np.asarray(x)\n                    w = target_length - x.shape[0]\n                    assert w >= 0, f'Target length {target_length} is less than origin length {x.shape[0]}'\n                    return np.pad(x, [0, w], mode=mode, **kwargs)\n\n                ids = [item['utt_id'] for item in batch]\n                lengths = np.asarray([item['feat'].shape[0] for item in batch])\n                waveforms = list(\n                    map(lambda x: pad(x, max(max_length, lengths.max().item())),\n                        [item['feat'] for item in batch]))\n                waveforms = np.stack(waveforms)\n                return {'ids': ids, 'feats': waveforms, 'lengths': lengths}\n\n            # Create noise data loader.\n            self.noise_dataloader = paddle.io.DataLoader(\n                self.noise_dataset,\n                batch_size=batch_size,\n                shuffle=True,\n                num_workers=self.num_workers,\n                collate_fn=noise_collate_fn,\n                return_list=True, )\n            self.noise_data = iter(self.noise_dataloader)\n\n        noise_batch, noise_len = self._load_noise_batch_of_size(batch_size)\n\n        # Select a random starting location in the waveform\n        start_index = self.start_index\n        if self.start_index is None:\n            start_index = 0\n            max_chop = (noise_len - lengths).min().clip(min=1)\n            start_index = paddle.randint(high=max_chop, shape=[1])\n\n        # Truncate noise_batch to max_length\n        noise_batch = noise_batch[:, start_index:start_index + max_length]\n        noise_len = (noise_len - start_index).clip(max=max_length).unsqueeze(1)\n        return noise_batch, noise_len\n\n    def _load_noise_batch_of_size(self, batch_size):\n        \"\"\"Concatenate noise batches, then chop to correct size\"\"\"\n        noise_batch, noise_lens = self._load_noise_batch()\n\n        # Expand\n        while len(noise_batch) < batch_size:\n            noise_batch = paddle.concat((noise_batch, noise_batch))\n            noise_lens = paddle.concat((noise_lens, noise_lens))\n\n        # Contract\n        if len(noise_batch) > batch_size:\n            noise_batch = noise_batch[:batch_size]\n            noise_lens = noise_lens[:batch_size]\n\n        return noise_batch, noise_lens\n\n    def _load_noise_batch(self):\n        \"\"\"Load a batch of noises, restarting iteration if necessary.\"\"\"\n        try:\n            batch = next(self.noise_data)\n        except StopIteration:\n            self.noise_data = iter(self.noise_dataloader)\n            batch = next(self.noise_data)\n\n        noises, lens = batch['feats'], batch['lengths']\n        return noises, lens\n\n\nclass AddReverb(nn.Layer):\n    def __init__(\n            self,\n            rir_dataset,\n            reverb_prob=1.0,\n            rir_scale_factor=1.0,\n            num_workers=0, ):\n        super(AddReverb, self).__init__()\n        self.rir_dataset = rir_dataset\n        self.reverb_prob = reverb_prob\n        self.rir_scale_factor = rir_scale_factor\n\n        # Create rir data loader.\n        def rir_collate_fn(batch):\n            def pad(x, target_length, mode='constant', **kwargs):\n                x = np.asarray(x)\n                w = target_length - x.shape[0]\n                assert w >= 0, f'Target length {target_length} is less than origin length {x.shape[0]}'\n                return np.pad(x, [0, w], mode=mode, **kwargs)\n\n            ids = [item['utt_id'] for item in batch]\n            lengths = np.asarray([item['feat'].shape[0] for item in batch])\n            waveforms = list(\n                map(lambda x: pad(x, lengths.max().item()),\n                    [item['feat'] for item in batch]))\n            waveforms = np.stack(waveforms)\n            return {'ids': ids, 'feats': waveforms, 'lengths': lengths}\n\n        self.rir_dataloader = paddle.io.DataLoader(\n            self.rir_dataset,\n            collate_fn=rir_collate_fn,\n            num_workers=num_workers,\n            shuffle=True,\n            return_list=True, )\n\n        self.rir_data = iter(self.rir_dataloader)\n\n    def forward(self, waveforms, lengths=None):\n        \"\"\"\n        Arguments\n        ---------\n        waveforms : tensor\n            Shape should be `[batch, time]` or `[batch, time, channels]`.\n        lengths : tensor\n            Shape should be a single dimension, `[batch]`.\n\n        Returns\n        -------\n        Tensor of shape `[batch, time]` or `[batch, time, channels]`.\n        \"\"\"\n\n        if lengths is None:\n            lengths = paddle.ones([len(waveforms)])\n\n        # Don't add reverb (return early) 1-`reverb_prob` portion of the time\n        if paddle.rand([1]) > self.reverb_prob:\n            return waveforms.clone()\n\n        # Add channels dimension if necessary\n        channel_added = False\n        if len(waveforms.shape) == 2:\n            waveforms = waveforms.unsqueeze(-1)\n            channel_added = True\n\n        # Load and prepare RIR\n        rir_waveform = self._load_rir()\n\n        # Compress or dilate RIR\n        if self.rir_scale_factor != 1:\n            rir_waveform = F.interpolate(\n                rir_waveform.transpose([0, 2, 1]),\n                scale_factor=self.rir_scale_factor,\n                mode=\"linear\",\n                align_corners=False,\n                data_format='NCW', )\n            # (N, C, L) -> (N, L, C)\n            rir_waveform = rir_waveform.transpose([0, 2, 1])\n\n        rev_waveform = reverberate(\n            waveforms,\n            rir_waveform,\n            self.rir_dataset.sample_rate,\n            rescale_amp=\"avg\")\n\n        # Remove channels dimension if added\n        if channel_added:\n            return rev_waveform.squeeze(-1)\n\n        return rev_waveform\n\n    def _load_rir(self):\n        try:\n            batch = next(self.rir_data)\n        except StopIteration:\n            self.rir_data = iter(self.rir_dataloader)\n            batch = next(self.rir_data)\n\n        rir_waveform = batch['feats']\n\n        # Make sure RIR has correct channels\n        if len(rir_waveform.shape) == 2:\n            rir_waveform = rir_waveform.unsqueeze(-1)\n\n        return rir_waveform\n\n\nclass AddBabble(nn.Layer):\n    def __init__(\n            self,\n            speaker_count=3,\n            snr_low=0,\n            snr_high=0,\n            mix_prob=1, ):\n        super(AddBabble, self).__init__()\n        self.speaker_count = speaker_count\n        self.snr_low = snr_low\n        self.snr_high = snr_high\n        self.mix_prob = mix_prob\n\n    def forward(self, waveforms, lengths=None):\n        if lengths is None:\n            lengths = paddle.ones([len(waveforms)])\n\n        babbled_waveform = waveforms.clone()\n        lengths = (lengths * waveforms.shape[1]).unsqueeze(1)\n        batch_size = len(waveforms)\n\n        # Don't mix (return early) 1-`mix_prob` portion of the batches\n        if paddle.rand([1]) > self.mix_prob:\n            return babbled_waveform\n\n        # Pick an SNR and use it to compute the mixture amplitude factors\n        clean_amplitude = compute_amplitude(waveforms, lengths)\n        SNR = paddle.rand((batch_size, 1))\n        SNR = SNR * (self.snr_high - self.snr_low) + self.snr_low\n        noise_amplitude_factor = 1 / (dB_to_amplitude(SNR) + 1)\n        new_noise_amplitude = noise_amplitude_factor * clean_amplitude\n\n        # Scale clean signal appropriately\n        babbled_waveform *= 1 - noise_amplitude_factor\n\n        # For each speaker in the mixture, roll and add\n        babble_waveform = waveforms.roll((1, ), axis=0)\n        babble_len = lengths.roll((1, ), axis=0)\n        for i in range(1, self.speaker_count):\n            babble_waveform += waveforms.roll((1 + i, ), axis=0)\n            babble_len = paddle.concat(\n                [babble_len, babble_len.roll((1, ), axis=0)], axis=-1).max(\n                    axis=-1, keepdim=True)\n\n        # Rescale and add to mixture\n        babble_amplitude = compute_amplitude(babble_waveform, babble_len)\n        babble_waveform *= new_noise_amplitude / (babble_amplitude + 1e-14)\n        babbled_waveform += babble_waveform\n\n        return babbled_waveform\n\n\nclass TimeDomainSpecAugment(nn.Layer):\n    def __init__(\n            self,\n            perturb_prob=1.0,\n            drop_freq_prob=1.0,\n            drop_chunk_prob=1.0,\n            speeds=[95, 100, 105],\n            sample_rate=16000,\n            drop_freq_count_low=0,\n            drop_freq_count_high=3,\n            drop_chunk_count_low=0,\n            drop_chunk_count_high=5,\n            drop_chunk_length_low=1000,\n            drop_chunk_length_high=2000,\n            drop_chunk_noise_factor=0, ):\n        super(TimeDomainSpecAugment, self).__init__()\n        self.speed_perturb = SpeedPerturb(\n            perturb_prob=perturb_prob,\n            orig_freq=sample_rate,\n            speeds=speeds, )\n        self.drop_freq = DropFreq(\n            drop_prob=drop_freq_prob,\n            drop_count_low=drop_freq_count_low,\n            drop_count_high=drop_freq_count_high, )\n        self.drop_chunk = DropChunk(\n            drop_prob=drop_chunk_prob,\n            drop_count_low=drop_chunk_count_low,\n            drop_count_high=drop_chunk_count_high,\n            drop_length_low=drop_chunk_length_low,\n            drop_length_high=drop_chunk_length_high,\n            noise_factor=drop_chunk_noise_factor, )\n\n    def forward(self, waveforms, lengths=None):\n        if lengths is None:\n            lengths = paddle.ones([len(waveforms)])\n\n        with paddle.no_grad():\n            # Augmentation\n            waveforms = self.speed_perturb(waveforms)\n            waveforms = self.drop_freq(waveforms)\n            waveforms = self.drop_chunk(waveforms, lengths)\n\n        return waveforms\n\n\nclass EnvCorrupt(nn.Layer):\n    def __init__(\n            self,\n            reverb_prob=1.0,\n            babble_prob=1.0,\n            noise_prob=1.0,\n            rir_dataset=None,\n            noise_dataset=None,\n            num_workers=0,\n            babble_speaker_count=0,\n            babble_snr_low=0,\n            babble_snr_high=0,\n            noise_snr_low=0,\n            noise_snr_high=0,\n            rir_scale_factor=1.0, ):\n        super(EnvCorrupt, self).__init__()\n\n        # Initialize corrupters\n        if rir_dataset is not None and reverb_prob > 0.0:\n            self.add_reverb = AddReverb(\n                rir_dataset=rir_dataset,\n                num_workers=num_workers,\n                reverb_prob=reverb_prob,\n                rir_scale_factor=rir_scale_factor, )\n\n        if babble_speaker_count > 0 and babble_prob > 0.0:\n            self.add_babble = AddBabble(\n                speaker_count=babble_speaker_count,\n                snr_low=babble_snr_low,\n                snr_high=babble_snr_high,\n                mix_prob=babble_prob, )\n\n        if noise_dataset is not None and noise_prob > 0.0:\n            self.add_noise = AddNoise(\n                noise_dataset=noise_dataset,\n                num_workers=num_workers,\n                snr_low=noise_snr_low,\n                snr_high=noise_snr_high,\n                mix_prob=noise_prob, )\n\n    def forward(self, waveforms, lengths=None):\n        if lengths is None:\n            lengths = paddle.ones([len(waveforms)])\n\n        # Augmentation\n        with paddle.no_grad():\n            if hasattr(self, \"add_reverb\"):\n                try:\n                    waveforms = self.add_reverb(waveforms, lengths)\n                except Exception:\n                    pass\n            if hasattr(self, \"add_babble\"):\n                waveforms = self.add_babble(waveforms, lengths)\n            if hasattr(self, \"add_noise\"):\n                waveforms = self.add_noise(waveforms, lengths)\n\n        return waveforms\n\n\ndef build_augment_pipeline(target_dir=None) -> List[paddle.nn.Layer]:\n    \"\"\"build augment pipeline\n    Note: this pipeline cannot be used in the paddle.DataLoader\n\n    Returns:\n        List[paddle.nn.Layer]: all augment process\n    \"\"\"\n    logger.info(\"start to build the augment pipeline\")\n    noise_dataset = CSVDataset(csv_path=os.path.join(target_dir,\n                                                     \"rir_noise/csv/noise.csv\"))\n    rir_dataset = CSVDataset(csv_path=os.path.join(target_dir,\n                                                   \"rir_noise/csv/rir.csv\"))\n\n    wavedrop = TimeDomainSpecAugment(\n        sample_rate=16000,\n        speeds=[100], )\n    speed_perturb = TimeDomainSpecAugment(\n        sample_rate=16000,\n        speeds=[95, 100, 105], )\n    add_noise = EnvCorrupt(\n        noise_dataset=noise_dataset,\n        reverb_prob=0.0,\n        noise_prob=1.0,\n        noise_snr_low=0,\n        noise_snr_high=15,\n        rir_scale_factor=1.0, )\n    add_rev = EnvCorrupt(\n        rir_dataset=rir_dataset,\n        reverb_prob=1.0,\n        noise_prob=0.0,\n        rir_scale_factor=1.0, )\n    add_rev_noise = EnvCorrupt(\n        noise_dataset=noise_dataset,\n        rir_dataset=rir_dataset,\n        reverb_prob=1.0,\n        noise_prob=1.0,\n        noise_snr_low=0,\n        noise_snr_high=15,\n        rir_scale_factor=1.0, )\n\n    return [wavedrop, speed_perturb, add_noise, add_rev, add_rev_noise]\n\n\ndef waveform_augment(waveforms: paddle.Tensor,\n                     augment_pipeline: List[paddle.nn.Layer]) -> paddle.Tensor:\n    \"\"\"process the augment pipeline and return all the waveforms\n\n    Args:\n        waveforms (paddle.Tensor): original batch waveform\n        augment_pipeline (List[paddle.nn.Layer]): agument pipeline process\n\n    Returns:\n        paddle.Tensor: all the audio waveform including the original waveform and augmented waveform\n    \"\"\"\n    # stage 0: store the original waveforms\n    waveforms_aug_list = [waveforms]\n\n    # augment the original batch waveform\n    for aug in augment_pipeline:\n        # stage 1: augment the data\n        waveforms_aug = aug(waveforms)  # (N, L)\n        if waveforms_aug.shape[1] >= waveforms.shape[1]:\n            # Trunc\n            waveforms_aug = waveforms_aug[:, :waveforms.shape[1]]\n        else:\n            # Pad\n            lengths_to_pad = waveforms.shape[1] - waveforms_aug.shape[1]\n            waveforms_aug = F.pad(\n                waveforms_aug.unsqueeze(-1), [0, lengths_to_pad],\n                data_format='NLC').squeeze(-1)\n        # stage 2: append the augmented waveform into the list\n        waveforms_aug_list.append(waveforms_aug)\n\n    # get the all the waveforms\n    return paddle.concat(waveforms_aug_list, axis=0)\n"
  },
  {
    "path": "paddlespeech/vector/io/batch.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy\nimport numpy as np\nimport paddle\n\n\ndef waveform_collate_fn(batch):\n    \"\"\"Wrap the waveform into a batch form\n\n    Args:\n        batch (list): the waveform list from the dataloader\n                      the item of data include several field\n                      feat: the utterance waveform data\n                      label: the utterance label encoding data\n\n    Returns:\n        dict: the batch data to dataloader\n    \"\"\"\n    waveforms = np.stack([item['feat'] for item in batch])\n    labels = np.stack([item['label'] for item in batch])\n\n    return {'waveforms': waveforms, 'labels': labels}\n\n\ndef feature_normalize(feats: paddle.Tensor,\n                      mean_norm: bool=True,\n                      std_norm: bool=True,\n                      convert_to_numpy: bool=False):\n    \"\"\"Do one utterance feature normalization\n\n    Args:\n        feats (paddle.Tensor): the original utterance feat, such as fbank, mfcc\n        mean_norm (bool, optional): mean norm flag. Defaults to True.\n        std_norm (bool, optional): std norm flag. Defaults to True.\n        convert_to_numpy (bool, optional): convert the paddle.tensor to numpy \n                                           and do feature norm with numpy. Defaults to False.\n\n    Returns:\n        paddle.Tensor : the normalized feats\n    \"\"\"\n    # Features normalization if needed\n    # numpy.mean is a little with paddle.mean about 1e-6\n    if convert_to_numpy:\n        feats_np = feats.numpy()\n        mean = feats_np.mean(axis=-1, keepdims=True) if mean_norm else 0\n        std = feats_np.std(axis=-1, keepdims=True) if std_norm else 1\n        feats_np = (feats_np - mean) / std\n        feats = paddle.to_tensor(feats_np, dtype=feats.dtype)\n    else:\n        mean = feats.mean(axis=-1, keepdim=True) if mean_norm else 0\n        std = feats.std(axis=-1, keepdim=True) if std_norm else 1\n        feats = (feats - mean) / std\n\n    return feats\n\n\ndef pad_right_2d(x, target_length, axis=-1, mode='constant', **kwargs):\n    x = np.asarray(x)\n    assert len(\n        x.shape) == 2, f'Only 2D arrays supported, but got shape: {x.shape}'\n\n    w = target_length - x.shape[axis]\n    assert w >= 0, f'Target length {target_length} is less than origin length {x.shape[axis]}'\n\n    if axis == 0:\n        pad_width = [[0, w], [0, 0]]\n    else:\n        pad_width = [[0, 0], [0, w]]\n\n    return np.pad(x, pad_width, mode=mode, **kwargs)\n\n\ndef batch_feature_normalize(batch, mean_norm: bool=True, std_norm: bool=True):\n    \"\"\"Do batch utterance features normalization\n\n    Args:\n        batch (list): the batch feature from dataloader\n        mean_norm (bool, optional): mean normalization flag. Defaults to True.\n        std_norm (bool, optional): std normalization flag. Defaults to True.\n\n    Returns:\n        dict: the normalized batch features\n    \"\"\"\n    ids = [item['utt_id'] for item in batch]\n    lengths = np.asarray([item['feat'].shape[1] for item in batch])\n    feats = list(\n        map(lambda x: pad_right_2d(x, lengths.max()),\n            [item['feat'] for item in batch]))\n    feats = np.stack(feats)\n\n    # Features normalization if needed\n    for i in range(len(feats)):\n        feat = feats[i][:, :lengths[i]]  # Excluding pad values.\n        mean = feat.mean(axis=-1, keepdims=True) if mean_norm else 0\n        std = feat.std(axis=-1, keepdims=True) if std_norm else 1\n        feats[i][:, :lengths[i]] = (feat - mean) / std\n        assert feats[i][:, lengths[\n            i]:].sum() == 0  # Padding valus should all be 0.\n\n    # Converts into ratios.\n    # the utterance of the max length doesn't need to padding\n    # the remaining utterances need to padding and all of them will be padded to max length\n    # we convert the original length of each utterance to the ratio of the max length\n    lengths = (lengths / lengths.max()).astype(np.float32)\n\n    return {'ids': ids, 'feats': feats, 'lengths': lengths}\n\n\ndef pad_right_to(array, target_shape, mode=\"constant\", value=0):\n    \"\"\"\n    This function takes a numpy array of arbitrary shape and pads it to target\n    shape by appending values on the right.\n\n    Args:\n        array: input numpy array. Input array whose dimension we need to pad.\n    target_shape : (list, tuple). Target shape we want for the target array its len must be equal to array.ndim\n    mode : str. Pad mode, please refer to numpy.pad documentation.\n    value : float. Pad value, please refer to numpy.pad documentation.\n\n    Returns:\n        array: numpy.array. Padded array.\n        valid_vals : list. List containing proportion for each dimension of original, non-padded values.\n    \"\"\"\n    assert len(target_shape) == array.ndim\n    pads = []  # this contains the abs length of the padding for each dimension.\n    valid_vals = []  # this contains the relative lengths for each dimension.\n    i = 0  # iterating over target_shape ndims\n    while i < len(target_shape):\n        assert (target_shape[i] >= array.shape[i]\n                ), \"Target shape must be >= original shape for every dim\"\n        pads.append([0, target_shape[i] - array.shape[i]])\n        valid_vals.append(array.shape[i] / target_shape[i])\n        i += 1\n\n    array = numpy.pad(array, pads, mode=mode, constant_values=value)\n\n    return array, valid_vals\n\n\ndef batch_pad_right(arrays, mode=\"constant\", value=0):\n    \"\"\"Given a list of numpy arrays it batches them together by padding to the right\n    on each dimension in order to get same length for all.\n\n    Args:\n        arrays : list. List of array we wish to pad together.\n        mode : str. Padding mode see numpy.pad documentation.\n        value : float. Padding value see numpy.pad documentation.\n\n    Returns:\n        array : numpy.array. Padded array.\n        valid_vals : list. List containing proportion for each dimension of original, non-padded values.\n    \"\"\"\n\n    if not len(arrays):\n        raise IndexError(\"arrays list must not be empty\")\n\n    if len(arrays) == 1:\n        # if there is only one array in the batch we simply unsqueeze it.\n        return numpy.expand_dims(arrays[0], axis=0), numpy.array([1.0])\n\n    if not (any(\n        [arrays[i].ndim == arrays[0].ndim for i in range(1, len(arrays))])):\n        raise IndexError(\"All arrays must have same number of dimensions\")\n\n    # FIXME we limit the support here: we allow padding of only the last dimension\n    # need to remove this when feat extraction is updated to handle multichannel.\n    max_shape = []\n    for dim in range(arrays[0].ndim):\n        if dim != (arrays[0].ndim - 1):\n            if not all(\n                [x.shape[dim] == arrays[0].shape[dim] for x in arrays[1:]]):\n                raise EnvironmentError(\n                    \"arrays should have same dimensions except for last one\")\n        max_shape.append(max([x.shape[dim] for x in arrays]))\n\n    batched = []\n    valid = []\n    for t in arrays:\n        # for each array we apply pad_right_to\n        padded, valid_percent = pad_right_to(\n            t, max_shape, mode=mode, value=value)\n        batched.append(padded)\n        valid.append(valid_percent[-1])\n\n    batched = numpy.stack(batched)\n\n    return batched, numpy.array(valid)\n"
  },
  {
    "path": "paddlespeech/vector/io/dataset.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom dataclasses import dataclass\nfrom dataclasses import fields\n\nfrom paddle.io import Dataset\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.s2t.utils.log import Log\nlogger = Log(__name__).getlog()\n\n# the audio meta info in the vector CSVDataset\n# utt_id: the utterance segment name\n# duration: utterance segment time\n# wav: utterance file path\n# start: start point in the original wav file\n# stop: stop point in the original wav file\n# label: the utterance segment's label id\n\n\n@dataclass\nclass meta_info:\n    \"\"\"the audio meta info in the vector CSVDataset\n\n    Args:\n        utt_id (str): the utterance segment name\n        duration (float): utterance segment time\n        wav (str): utterance file path\n        start (int): start point in the original wav file\n        stop (int): stop point in the original wav file\n        lab_id (str): the utterance segment's label id\n    \"\"\"\n    utt_id: str\n    duration: float\n    wav: str\n    start: int\n    stop: int\n    label: str\n\n\n# csv dataset support feature type\n# raw: return the pcm data sample point\n# melspectrogram: fbank feature\nfeat_funcs = {\n    'raw': None,\n    'melspectrogram': melspectrogram,\n}\n\n\nclass CSVDataset(Dataset):\n    def __init__(self,\n                 csv_path,\n                 label2id_path=None,\n                 config=None,\n                 random_chunk=True,\n                 feat_type: str=\"raw\",\n                 n_train_snts: int=-1,\n                 **kwargs):\n        \"\"\"Implement the CSV Dataset\n\n        Args:\n            csv_path (str): csv dataset file path\n            label2id_path (str): the utterance label to integer id map file path\n            config (CfgNode): yaml config\n            feat_type (str): dataset feature type. if it is raw, it return pcm data.\n            n_train_snts (int): select the n_train_snts sample from the dataset. \n                                if n_train_snts = -1, dataset will load all the sample.\n                                Default value is -1.\n            kwargs : feature type args\n        \"\"\"\n        super().__init__()\n        self.csv_path = csv_path\n        self.label2id_path = label2id_path\n        self.config = config\n        self.random_chunk = random_chunk\n        self.feat_type = feat_type\n        self.n_train_snts = n_train_snts\n        self.feat_config = kwargs\n        self.id2label = {}\n        self.label2id = {}\n        self.data = self.load_data_csv()\n        self.load_speaker_to_label()\n\n    def load_data_csv(self):\n        \"\"\"Load the csv dataset content and store them in the data property\n        the csv dataset's format has six fields, \n        that is audio_id or utt_id, audio duration, segment start point, segment stop point \n        and utterance label.\n        Note in training period, the utterance label must has a map to integer id in label2id_path \n\n        Returns:\n            list: the csv data with meta_info type\n        \"\"\"\n        data = []\n\n        with open(self.csv_path, 'r') as rf:\n            for line in rf.readlines()[1:]:\n                audio_id, duration, wav, start, stop, spk_id = line.strip(\n                ).split(',')\n                data.append(\n                    meta_info(audio_id,\n                              float(duration), wav,\n                              int(start), int(stop), spk_id))\n        if self.n_train_snts > 0:\n            sample_num = min(self.n_train_snts, len(data))\n            data = data[0:sample_num]\n\n        return data\n\n    def load_speaker_to_label(self):\n        \"\"\"Load the utterance label map content.\n        In vector domain, we call the utterance label as speaker label.\n        The speaker label is real speaker label in speaker verification domain,\n        and in language identification is language label.\n        \"\"\"\n        if not self.label2id_path:\n            logger.warning(\"No speaker id to label file\")\n            return\n\n        with open(self.label2id_path, 'r') as f:\n            for line in f.readlines():\n                label_name, label_id = line.strip().split(' ')\n                self.label2id[label_name] = int(label_id)\n                self.id2label[int(label_id)] = label_name\n\n    def convert_to_record(self, idx: int):\n        \"\"\"convert the dataset sample to training record the CSV Dataset\n\n        Args:\n            idx (int) : the request index in all the dataset\n        \"\"\"\n        sample = self.data[idx]\n\n        record = {}\n        # To show all fields in a namedtuple: `type(sample)._fields`\n        for field in fields(sample):\n            record[field.name] = getattr(sample, field.name)\n\n        waveform, sr = load_audio(record['wav'])\n\n        # random select a chunk audio samples from the audio\n        if self.config and self.config.random_chunk:\n            num_wav_samples = waveform.shape[0]\n            num_chunk_samples = int(self.config.chunk_duration * sr)\n            start = random.randint(0, num_wav_samples - num_chunk_samples - 1)\n            stop = start + num_chunk_samples\n        else:\n            start = record['start']\n            stop = record['stop']\n\n        # we only return the waveform as feat\n        waveform = waveform[start:stop]\n\n        # all availabel feature type is in feat_funcs\n        assert self.feat_type in feat_funcs.keys(), \\\n            f\"Unknown feat_type: {self.feat_type}, it must be one in {list(feat_funcs.keys())}\"\n        feat_func = feat_funcs[self.feat_type]\n        feat = feat_func(\n            waveform, sr=sr, **self.feat_config) if feat_func else waveform\n\n        record.update({'feat': feat})\n        if self.label2id:\n            record.update({'label': self.label2id[record['label']]})\n\n        return record\n\n    def __getitem__(self, idx):\n        \"\"\"Return the specific index sample\n\n        Args:\n            idx (int) : the request index in all the dataset\n        \"\"\"\n        return self.convert_to_record(idx)\n\n    def __len__(self):\n        \"\"\"Return the dataset length\n\n        Returns:\n            int: the length num of the dataset\n        \"\"\"\n        return len(self.data)\n"
  },
  {
    "path": "paddlespeech/vector/io/dataset_from_json.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport json\nfrom dataclasses import dataclass\nfrom dataclasses import fields\n\nfrom paddle.io import Dataset\n\nfrom paddlespeech.audio.backends import soundfile_load as load_audio\nfrom paddlespeech.audio.compliance.librosa import melspectrogram\nfrom paddlespeech.audio.compliance.librosa import mfcc\n\n\n@dataclass\nclass meta_info:\n    \"\"\"the audio meta info in the vector JSONDataset\n    Args:\n        utt_id (str): the segment name\n        duration (float): segment time\n        wav (str): wav file path\n        start (int): start point in the original wav file\n        stop (int): stop point in the original wav file\n        lab_id (str): the record id\n    \"\"\"\n    utt_id: str\n    duration: float\n    wav: str\n    start: int\n    stop: int\n    record_id: str\n\n\n# json dataset support feature type\nfeat_funcs = {\n    'raw': None,\n    'melspectrogram': melspectrogram,\n    'mfcc': mfcc,\n}\n\n\nclass JSONDataset(Dataset):\n    \"\"\"\n    dataset from json file.\n    \"\"\"\n\n    def __init__(self, json_file: str, feat_type: str='raw', **kwargs):\n        \"\"\"\n        Ags:\n            json_file (:obj:`str`): Data prep JSON file.\n            labels (:obj:`List[int]`): Labels of audio files.\n            feat_type (:obj:`str`, `optional`, defaults to `raw`):\n                It identifies the feature type that user wants to extrace of an audio file.\n        \"\"\"\n        if feat_type not in feat_funcs.keys():\n            raise RuntimeError(\n                f\"Unknown feat_type: {feat_type}, it must be one in {list(feat_funcs.keys())}\"\n            )\n\n        self.json_file = json_file\n        self.feat_type = feat_type\n        self.feat_config = kwargs\n        self._data = self._get_data()\n        super(JSONDataset, self).__init__()\n\n    def _get_data(self):\n        with open(self.json_file, \"r\") as f:\n            meta_data = json.load(f)\n        data = []\n        for key in meta_data:\n            sub_seg = meta_data[key][\"wav\"]\n            wav = sub_seg[\"file\"]\n            duration = sub_seg[\"duration\"]\n            start = sub_seg[\"start\"]\n            stop = sub_seg[\"stop\"]\n            rec_id = str(key).rsplit(\"_\", 2)[0]\n            data.append(\n                meta_info(\n                    str(key),\n                    float(duration), wav, int(start), int(stop), str(rec_id)))\n        return data\n\n    def _convert_to_record(self, idx: int):\n        sample = self._data[idx]\n\n        record = {}\n        # To show all fields in a namedtuple\n        for field in fields(sample):\n            record[field.name] = getattr(sample, field.name)\n\n        waveform, sr = load_audio(record['wav'])\n        waveform = waveform[record['start']:record['stop']]\n\n        feat_func = feat_funcs[self.feat_type]\n        feat = feat_func(\n            waveform, sr=sr, **self.feat_config) if feat_func else waveform\n\n        record.update({'feat': feat})\n\n        return record\n\n    def __getitem__(self, idx):\n        return self._convert_to_record(idx)\n\n    def __len__(self):\n        return len(self._data)\n"
  },
  {
    "path": "paddlespeech/vector/io/embedding_norm.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Dict\n\nimport paddle\n\n\nclass InputNormalization:\n    spk_dict_mean: Dict[int, paddle.Tensor]\n    spk_dict_std: Dict[int, paddle.Tensor]\n    spk_dict_count: Dict[int, int]\n\n    def __init__(\n            self,\n            mean_norm=True,\n            std_norm=True,\n            norm_type=\"global\", ):\n        \"\"\"Do feature or embedding mean and std norm\n\n        Args:\n            mean_norm (bool, optional): mean norm flag. Defaults to True.\n            std_norm (bool, optional): std norm flag. Defaults to True.\n            norm_type (str, optional): norm type. Defaults to \"global\".\n        \"\"\"\n        super().__init__()\n        self.training = True\n        self.mean_norm = mean_norm\n        self.std_norm = std_norm\n        self.norm_type = norm_type\n        self.glob_mean = paddle.to_tensor([0], dtype=\"float32\")\n        self.glob_std = paddle.to_tensor([0], dtype=\"float32\")\n        self.spk_dict_mean = {}\n        self.spk_dict_std = {}\n        self.spk_dict_count = {}\n        self.weight = 1.0\n        self.count = 0\n        self.eps = 1e-10\n\n    def __call__(self,\n                 x,\n                 lengths,\n                 spk_ids=paddle.to_tensor([], dtype=\"float32\")):\n        \"\"\"Returns the tensor with the surrounding context.\n        Args:\n            x (paddle.Tensor): A batch of tensors.\n            lengths (paddle.Tensor): A batch of tensors containing the relative length of each\n                                    sentence (e.g, [0.7, 0.9, 1.0]). It is used to avoid\n                                    computing stats on zero-padded steps.\n            spk_ids (paddle.Tensor, optional): tensor containing the ids of each speaker (e.g, [0 10 6]).\n                                        It is used to perform per-speaker normalization when\n                                        norm_type='speaker'. Defaults to paddle.to_tensor([], dtype=\"float32\").\n        Returns:\n            paddle.Tensor: The normalized feature or embedding\n        \"\"\"\n        N_batches = x.shape[0]\n\n        current_means = []\n        current_stds = []\n\n        for snt_id in range(N_batches):\n\n            # Avoiding padded time steps\n            # actual size is the actual time data length\n            actual_size = paddle.round(lengths[snt_id] *\n                                       x.shape[1]).astype(\"int32\")\n            # computing actual time data statistics\n            # we extract the snt_id embedding from the x\n            # and the target paddle.Tensor will reduce an 0-axis\n            # so we need unsqueeze operation to recover the all axis \n            current_mean, current_std = self._compute_current_stats(\n                x[snt_id, 0:actual_size, ...].unsqueeze(0))\n            current_means.append(current_mean)\n            current_stds.append(current_std)\n\n        if self.norm_type == \"global\":\n            current_mean = paddle.mean(paddle.stack(current_means), axis=0)\n            current_std = paddle.mean(paddle.stack(current_stds), axis=0)\n\n            if self.norm_type == \"global\":\n\n                if self.training:\n                    if self.count == 0:\n                        self.glob_mean = current_mean\n                        self.glob_std = current_std\n\n                    else:\n                        self.weight = 1 / (self.count + 1)\n\n                        self.glob_mean = (\n                            1 - self.weight\n                        ) * self.glob_mean + self.weight * current_mean\n\n                        self.glob_std = (\n                            1 - self.weight\n                        ) * self.glob_std + self.weight * current_std\n\n                    self.glob_mean.detach()\n                    self.glob_std.detach()\n\n                    self.count = self.count + 1\n                x = (x - self.glob_mean) / (self.glob_std)\n        return x\n\n    def _compute_current_stats(self, x):\n        \"\"\"Returns the tensor with the surrounding context.\n\n        Args:\n            x (paddle.Tensor): A batch of tensors.\n\n        Returns:\n             the statistics of the data\n        \"\"\"\n        # Compute current mean\n        if self.mean_norm:\n            current_mean = paddle.mean(x, axis=0).detach()\n        else:\n            current_mean = paddle.to_tensor([0.0], dtype=\"float32\")\n\n        # Compute current std\n        if self.std_norm:\n            current_std = paddle.std(x, axis=0).detach()\n        else:\n            current_std = paddle.to_tensor([1.0], dtype=\"float32\")\n\n        # Improving numerical stability of std\n        current_std = paddle.maximum(current_std,\n                                     self.eps * paddle.ones_like(current_std))\n\n        return current_mean, current_std\n\n    def _statistics_dict(self):\n        \"\"\"Fills the dictionary containing the normalization statistics.\n        \"\"\"\n        state = {}\n        state[\"count\"] = self.count\n        state[\"glob_mean\"] = self.glob_mean\n        state[\"glob_std\"] = self.glob_std\n        state[\"spk_dict_mean\"] = self.spk_dict_mean\n        state[\"spk_dict_std\"] = self.spk_dict_std\n        state[\"spk_dict_count\"] = self.spk_dict_count\n\n        return state\n\n    def _load_statistics_dict(self, state):\n        \"\"\"Loads the dictionary containing the statistics.\n\n        Arguments\n        ---------\n        state : dict\n            A dictionary containing the normalization statistics.\n        \"\"\"\n        self.count = state[\"count\"]\n        if isinstance(state[\"glob_mean\"], int):\n            self.glob_mean = state[\"glob_mean\"]\n            self.glob_std = state[\"glob_std\"]\n        else:\n            self.glob_mean = state[\"glob_mean\"]  # .to(self.device_inp)\n            self.glob_std = state[\"glob_std\"]  # .to(self.device_inp)\n\n        # Loading the spk_dict_mean in the right device\n        self.spk_dict_mean = {}\n        for spk in state[\"spk_dict_mean\"]:\n            self.spk_dict_mean[spk] = state[\"spk_dict_mean\"][spk]\n\n        # Loading the spk_dict_std in the right device\n        self.spk_dict_std = {}\n        for spk in state[\"spk_dict_std\"]:\n            self.spk_dict_std[spk] = state[\"spk_dict_std\"][spk]\n\n        self.spk_dict_count = state[\"spk_dict_count\"]\n\n        return state\n\n    def to(self, device):\n        \"\"\"Puts the needed tensors in the right device.\n        \"\"\"\n        self = super(InputNormalization, self).to(device)\n        self.glob_mean = self.glob_mean.to(device)\n        self.glob_std = self.glob_std.to(device)\n        for spk in self.spk_dict_mean:\n            self.spk_dict_mean[spk] = self.spk_dict_mean[spk].to(device)\n            self.spk_dict_std[spk] = self.spk_dict_std[spk].to(device)\n        return self\n\n    def save(self, path):\n        \"\"\"Save statistic dictionary.\n    \n        Args:\n            path (str): A path where to save the dictionary.\n        \"\"\"\n        stats = self._statistics_dict()\n        paddle.save(stats, path)\n\n    def _load(self, path, end_of_epoch=False, device=None):\n        \"\"\"Load statistic dictionary.\n\n        Arguments\n        ---------\n        path : str\n            The path of the statistic dictionary\n        device : str, None\n            Passed to paddle.load(..., map_location=device)\n        \"\"\"\n        del end_of_epoch  # Unused here.\n        stats = paddle.load(path, map_location=device)\n        self._load_statistics_dict(stats)\n"
  },
  {
    "path": "paddlespeech/vector/io/signal_processing.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\n\n# TODO: Complete type-hint and doc string.\n\n\ndef blackman_window(win_len, dtype=np.float32):\n    arcs = np.pi * np.arange(win_len) / float(win_len)\n    win = np.asarray(\n        [0.42 - 0.5 * np.cos(2 * arc) + 0.08 * np.cos(4 * arc) for arc in arcs],\n        dtype=dtype)\n    return paddle.to_tensor(win)\n\n\ndef compute_amplitude(waveforms, lengths=None, amp_type=\"avg\", scale=\"linear\"):\n    if len(waveforms.shape) == 1:\n        waveforms = waveforms.unsqueeze(0)\n\n    assert amp_type in [\"avg\", \"peak\"]\n    assert scale in [\"linear\", \"dB\"]\n\n    if amp_type == \"avg\":\n        if lengths is None:\n            out = paddle.mean(paddle.abs(waveforms), axis=1, keepdim=True)\n        else:\n            wav_sum = paddle.sum(paddle.abs(waveforms), axis=1, keepdim=True)\n            out = wav_sum / lengths.astype(wav_sum.dtype)\n    elif amp_type == \"peak\":\n        out = paddle.max(paddle.abs(waveforms), axis=1, keepdim=True)\n    else:\n        raise NotImplementedError\n\n    if scale == \"linear\":\n        return out\n    elif scale == \"dB\":\n        return paddle.clip(20 * paddle.log10(out), min=-80)\n    else:\n        raise NotImplementedError\n\n\ndef dB_to_amplitude(SNR):\n    return 10**(SNR / 20)\n\n\ndef convolve1d(\n        waveform,\n        kernel,\n        padding=0,\n        pad_type=\"constant\",\n        stride=1,\n        groups=1, ):\n    if len(waveform.shape) != 3:\n        raise ValueError(\"Convolve1D expects a 3-dimensional tensor\")\n\n    # Padding can be a tuple (left_pad, right_pad) or an int\n    if isinstance(padding, list):\n        waveform = paddle.nn.functional.pad(\n            x=waveform,\n            pad=padding,\n            mode=pad_type,\n            data_format='NLC', )\n\n    # Move time dimension last, which pad and fft and conv expect.\n    # (N, L, C) -> (N, C, L)\n    waveform = waveform.transpose([0, 2, 1])\n    kernel = kernel.transpose([0, 2, 1])\n\n    convolved = paddle.nn.functional.conv1d(\n        x=waveform,\n        weight=kernel,\n        stride=stride,\n        groups=groups,\n        padding=padding if not isinstance(padding, list) else 0, )\n\n    # Return time dimension to the second dimension.\n    return convolved.transpose([0, 2, 1])\n\n\ndef notch_filter(notch_freq, filter_width=101, notch_width=0.05):\n    # Check inputs\n    assert 0 < notch_freq <= 1\n    assert filter_width % 2 != 0\n    pad = filter_width // 2\n    inputs = paddle.arange(filter_width, dtype='float32') - pad\n\n    # Avoid frequencies that are too low\n    notch_freq += notch_width\n\n    # Define sinc function, avoiding division by zero\n    def sinc(x):\n        def _sinc(x):\n            return paddle.sin(x) / x\n\n        # The zero is at the middle index\n        res = paddle.concat(\n            [_sinc(x[:pad]), paddle.ones([1]), _sinc(x[pad + 1:])])\n        return res\n\n    # Compute a low-pass filter with cutoff frequency notch_freq.\n    hlpf = sinc(3 * (notch_freq - notch_width) * inputs)\n    # import torch\n    # hlpf *= paddle.to_tensor(torch.blackman_window(filter_width).detach().numpy())\n    hlpf *= blackman_window(filter_width)\n    hlpf /= paddle.sum(hlpf)\n\n    # Compute a high-pass filter with cutoff frequency notch_freq.\n    hhpf = sinc(3 * (notch_freq + notch_width) * inputs)\n    # hhpf *= paddle.to_tensor(torch.blackman_window(filter_width).detach().numpy())\n    hhpf *= blackman_window(filter_width)\n    hhpf /= -paddle.sum(hhpf)\n    hhpf[pad] += 1\n\n    # Adding filters creates notch filter\n    return (hlpf + hhpf).reshape([1, -1, 1])\n\n\ndef reverberate(waveforms,\n                rir_waveform,\n                sample_rate,\n                impulse_duration=0.3,\n                rescale_amp=\"avg\"):\n    orig_shape = waveforms.shape\n\n    if len(waveforms.shape) > 3 or len(rir_waveform.shape) > 3:\n        raise NotImplementedError\n\n    # if inputs are mono tensors we reshape to 1, samples\n    if len(waveforms.shape) == 1:\n        waveforms = waveforms.unsqueeze(0).unsqueeze(-1)\n    elif len(waveforms.shape) == 2:\n        waveforms = waveforms.unsqueeze(-1)\n\n    if len(rir_waveform.shape) == 1:  # convolve1d expects a 3d tensor !\n        rir_waveform = rir_waveform.unsqueeze(0).unsqueeze(-1)\n    elif len(rir_waveform.shape) == 2:\n        rir_waveform = rir_waveform.unsqueeze(-1)\n\n    # Compute the average amplitude of the clean\n    orig_amplitude = compute_amplitude(waveforms, waveforms.shape[1],\n                                       rescale_amp)\n\n    # Compute index of the direct signal, so we can preserve alignment\n    impulse_index_start = rir_waveform.abs().argmax(axis=1).item()\n    impulse_index_end = min(\n        impulse_index_start + int(sample_rate * impulse_duration),\n        rir_waveform.shape[1])\n    rir_waveform = rir_waveform[:, impulse_index_start:impulse_index_end, :]\n    rir_waveform = rir_waveform / paddle.norm(rir_waveform, p=2)\n    rir_waveform = paddle.flip(rir_waveform, [1])\n\n    waveforms = convolve1d(\n        waveform=waveforms,\n        kernel=rir_waveform,\n        padding=[rir_waveform.shape[1] - 1, 0], )\n\n    # Rescale to the peak amplitude of the clean waveform\n    waveforms = rescale(waveforms, waveforms.shape[1], orig_amplitude,\n                        rescale_amp)\n\n    if len(orig_shape) == 1:\n        waveforms = waveforms.squeeze(0).squeeze(-1)\n    if len(orig_shape) == 2:\n        waveforms = waveforms.squeeze(-1)\n\n    return waveforms\n\n\ndef rescale(waveforms, lengths, target_lvl, amp_type=\"avg\", scale=\"linear\"):\n    assert amp_type in [\"peak\", \"avg\"]\n    assert scale in [\"linear\", \"dB\"]\n\n    batch_added = False\n    if len(waveforms.shape) == 1:\n        batch_added = True\n        waveforms = waveforms.unsqueeze(0)\n\n    waveforms = normalize(waveforms, lengths, amp_type)\n\n    if scale == \"linear\":\n        out = target_lvl * waveforms\n    elif scale == \"dB\":\n        out = dB_to_amplitude(target_lvl) * waveforms\n\n    else:\n        raise NotImplementedError(\"Invalid scale, choose between dB and linear\")\n\n    if batch_added:\n        out = out.squeeze(0)\n\n    return out\n\n\ndef normalize(waveforms, lengths=None, amp_type=\"avg\", eps=1e-14):\n    assert amp_type in [\"avg\", \"peak\"]\n\n    batch_added = False\n    if len(waveforms.shape) == 1:\n        batch_added = True\n        waveforms = waveforms.unsqueeze(0)\n\n    den = compute_amplitude(waveforms, lengths, amp_type) + eps\n    if batch_added:\n        waveforms = waveforms.squeeze(0)\n    return waveforms / den\n"
  },
  {
    "path": "paddlespeech/vector/models/__init__.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/models/ecapa_tdnn.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\n\ndef length_to_mask(length, max_len=None, dtype=None):\n    assert len(length.shape) == 1\n\n    if max_len is None:\n        max_len = length.max().astype(\n            'int').item()  # using arange to generate mask\n    mask = paddle.arange(\n        max_len, dtype=length.dtype).expand(\n            (len(length), max_len)) < length.unsqueeze(1)\n\n    if dtype is None:\n        dtype = length.dtype\n\n    mask = paddle.to_tensor(mask, dtype=dtype)\n    return mask\n\n\nclass Conv1d(nn.Layer):\n    def __init__(\n            self,\n            in_channels,\n            out_channels,\n            kernel_size,\n            stride=1,\n            padding=\"same\",\n            dilation=1,\n            groups=1,\n            bias=True,\n            padding_mode=\"reflect\", ):\n        \"\"\"_summary_\n\n        Args:\n            in_channels (int): intput channel or input data dimensions\n            out_channels (int): output channel or output data dimensions\n            kernel_size (int): kernel size of 1-d convolution\n            stride (int, optional): strid in 1-d convolution . Defaults to 1.\n            padding (str, optional): padding value. Defaults to \"same\".\n            dilation (int, optional): dilation in 1-d convolution. Defaults to 1.\n            groups (int, optional): groups in 1-d convolution. Defaults to 1.\n            bias (bool, optional): bias in 1-d convolution . Defaults to True.\n            padding_mode (str, optional): padding mode. Defaults to \"reflect\".\n        \"\"\"\n        super().__init__()\n\n        self.kernel_size = kernel_size\n        self.stride = stride\n        self.dilation = dilation\n        self.padding = padding\n\n        # padding_mode is forcibly set to 'constant' when using the npu device because npu only support mode=constant right now\n        if paddle.get_device().startswith('npu'):\n            self.padding_mode = 'constant'\n        else:\n            self.padding_mode = padding_mode\n\n        self.conv = nn.Conv1D(\n            in_channels,\n            out_channels,\n            self.kernel_size,\n            stride=self.stride,\n            padding=0,\n            dilation=self.dilation,\n            groups=groups,\n            bias_attr=bias, )\n\n    def forward(self, x):\n        \"\"\"Do conv1d forward\n\n        Args:\n            x (paddle.Tensor): [N, C, L] input data, \n                                N is the batch,\n                                C is the data dimension, \n                                L is the time\n\n        Raises:\n            ValueError: only support the same padding type\n\n        Returns:\n            paddle.Tensor: the value of conv1d\n        \"\"\"\n        if self.padding == \"same\":\n            x = self._manage_padding(x, self.kernel_size, self.dilation,\n                                     self.stride)\n        else:\n            raise ValueError(\"Padding must be 'same'. Got {self.padding}\")\n\n        return self.conv(x)\n\n    def _manage_padding(self, x, kernel_size: int, dilation: int, stride: int):\n        \"\"\"Padding the input data\n\n        Args:\n            x (paddle.Tensor): [N, C, L] input data\n                                N is the batch,\n                                C is the data dimension, \n                                L is the time\n            kernel_size (int): 1-d convolution kernel size\n            dilation (int): 1-d convolution dilation\n            stride (int): 1-d convolution stride\n\n        Returns:\n            paddle.Tensor: the padded input data\n        \"\"\"\n        L_in = x.shape[-1]  # Detecting input shape\n        padding = self._get_padding_elem(L_in, stride, kernel_size,\n                                         dilation)  # Time padding\n        x = F.pad(\n            x, padding, mode=self.padding_mode,\n            data_format=\"NCL\")  # Applying padding\n        return x\n\n    def _get_padding_elem(self,\n                          L_in: int,\n                          stride: int,\n                          kernel_size: int,\n                          dilation: int):\n        \"\"\"Calculate the padding value in same mode\n\n        Args:\n            L_in (int): the times of the input data, \n            stride (int): 1-d convolution stride\n            kernel_size (int): 1-d convolution kernel size\n            dilation (int): 1-d convolution stride\n\n        Returns:\n            int: return the padding value in same mode\n        \"\"\"\n        if stride > 1:\n            n_steps = math.ceil(((L_in - kernel_size * dilation) / stride) + 1)\n            L_out = stride * (n_steps - 1) + kernel_size * dilation\n            padding = [kernel_size // 2, kernel_size // 2]\n        else:\n            L_out = (L_in - dilation * (kernel_size - 1) - 1) // stride + 1\n\n            padding = [(L_in - L_out) // 2, (L_in - L_out) // 2]\n\n        return padding\n\n\nclass BatchNorm1d(nn.Layer):\n    def __init__(\n            self,\n            input_size,\n            eps=1e-05,\n            momentum=0.9,\n            weight_attr=None,\n            bias_attr=None,\n            data_format='NCL',\n            use_global_stats=None, ):\n        super().__init__()\n\n        self.norm = nn.BatchNorm1D(\n            input_size,\n            epsilon=eps,\n            momentum=momentum,\n            weight_attr=weight_attr,\n            bias_attr=bias_attr,\n            data_format=data_format,\n            use_global_stats=use_global_stats, )\n\n    def forward(self, x):\n        x_n = self.norm(x)\n        return x_n\n\n\nclass TDNNBlock(nn.Layer):\n    def __init__(\n            self,\n            in_channels,\n            out_channels,\n            kernel_size,\n            dilation,\n            activation=nn.ReLU, ):\n        \"\"\"Implementation of TDNN network\n\n        Args:\n            in_channels (int): input channels or input embedding dimensions\n            out_channels (int): output channels or output embedding dimensions\n            kernel_size (int): the kernel size of the TDNN network block\n            dilation (int): the dilation of the TDNN network block\n            activation (paddle class, optional): the activation layers. Defaults to nn.ReLU.\n        \"\"\"\n        super().__init__()\n        self.conv = Conv1d(\n            in_channels=in_channels,\n            out_channels=out_channels,\n            kernel_size=kernel_size,\n            dilation=dilation, )\n        self.activation = activation()\n        self.norm = BatchNorm1d(input_size=out_channels)\n\n    def forward(self, x):\n        return self.norm(self.activation(self.conv(x)))\n\n\nclass Res2NetBlock(nn.Layer):\n    def __init__(self, in_channels, out_channels, scale=8, dilation=1):\n        \"\"\"Implementation of Res2Net Block with dilation\n           The paper is refered as \"Res2Net: A New Multi-scale Backbone Architecture\",\n           whose url is https://arxiv.org/abs/1904.01169\n        Args:\n            in_channels (int): input channels or input dimensions\n            out_channels (int): output channels or output dimensions\n            scale (int, optional): scale in res2net bolck. Defaults to 8.\n            dilation (int, optional): dilation of 1-d convolution in TDNN block. Defaults to 1.\n        \"\"\"\n        super().__init__()\n        assert in_channels % scale == 0\n        assert out_channels % scale == 0\n\n        in_channel = in_channels // scale\n        hidden_channel = out_channels // scale\n\n        self.blocks = nn.LayerList([\n            TDNNBlock(\n                in_channel, hidden_channel, kernel_size=3, dilation=dilation)\n            for i in range(scale - 1)\n        ])\n        self.scale = scale\n\n    def forward(self, x):\n        y = []\n        for i, x_i in enumerate(paddle.chunk(x, self.scale, axis=1)):\n            if i == 0:\n                y_i = x_i\n            elif i == 1:\n                y_i = self.blocks[i - 1](x_i)\n            else:\n                y_i = self.blocks[i - 1](x_i + y_i)\n            y.append(y_i)\n        y = paddle.concat(y, axis=1)\n        return y\n\n\nclass SEBlock(nn.Layer):\n    def __init__(self, in_channels, se_channels, out_channels):\n        \"\"\"Implementation of SEBlock\n           The paper is refered as \"Squeeze-and-Excitation Networks\"\n           whose url is https://arxiv.org/abs/1709.01507\n        Args:\n            in_channels (int): input channels or input data dimensions\n            se_channels (_type_): _description_\n            out_channels (int): output channels or output data dimensions\n        \"\"\"\n        super().__init__()\n\n        self.conv1 = Conv1d(\n            in_channels=in_channels, out_channels=se_channels, kernel_size=1)\n        self.relu = paddle.nn.ReLU()\n        self.conv2 = Conv1d(\n            in_channels=se_channels, out_channels=out_channels, kernel_size=1)\n        self.sigmoid = paddle.nn.Sigmoid()\n\n    def forward(self, x, lengths=None):\n        L = x.shape[-1]\n        if lengths is not None:\n            mask = length_to_mask(lengths * L, max_len=L)\n            mask = mask.unsqueeze(1)\n            total = mask.sum(axis=2, keepdim=True)\n            s = (x * mask).sum(axis=2, keepdim=True) / total\n        else:\n            s = x.mean(axis=2, keepdim=True)\n\n        s = self.relu(self.conv1(s))\n        s = self.sigmoid(self.conv2(s))\n\n        return s * x\n\n\nclass AttentiveStatisticsPooling(nn.Layer):\n    def __init__(self, channels, attention_channels=128, global_context=True):\n        \"\"\"Compute the speaker verification statistics\n           The detail info is section 3.1 in https://arxiv.org/pdf/1709.01507.pdf \n        Args:\n            channels (int): input data channel or data dimension\n            attention_channels (int, optional): attention dimension. Defaults to 128.\n            global_context (bool, optional): If use the global context information. Defaults to True.\n        \"\"\"\n        super().__init__()\n\n        self.eps = 1e-12\n        self.global_context = global_context\n        if global_context:\n            self.tdnn = TDNNBlock(channels * 3, attention_channels, 1, 1)\n        else:\n            self.tdnn = TDNNBlock(channels, attention_channels, 1, 1)\n        self.tanh = nn.Tanh()\n        self.conv = Conv1d(\n            in_channels=attention_channels,\n            out_channels=channels,\n            kernel_size=1)\n\n    def forward(self, x, lengths=None):\n        C, L = x.shape[1], x.shape[2]  # KP: (N, C, L)\n\n        def _compute_statistics(x, m, axis=2, eps=self.eps):\n            mean = (m * x).sum(axis)\n            std = paddle.sqrt(\n                (m * (x - mean.unsqueeze(axis)).pow(2)).sum(axis).clip(eps))\n            return mean, std\n\n        if lengths is None:\n            lengths = paddle.ones([x.shape[0]])\n\n        # Make binary mask of shape [N, 1, L]\n        mask = length_to_mask(lengths * L, max_len=L)\n        mask = mask.unsqueeze(1)\n\n        # Expand the temporal context of the pooling layer by allowing the\n        # self-attention to look at global properties of the utterance.\n        if self.global_context:\n            total = mask.sum(axis=2, keepdim=True).astype('float32')\n            mean, std = _compute_statistics(x, mask / total)\n            mean = mean.unsqueeze(2).tile((1, 1, L))\n            std = std.unsqueeze(2).tile((1, 1, L))\n            attn = paddle.concat([x, mean, std], axis=1)\n        else:\n            attn = x\n\n        # Apply layers\n        attn = self.conv(self.tanh(self.tdnn(attn)))\n\n        if paddle.get_device().startswith('npu'):\n            # The following way is designed to fix the 'Broadcast dimension mismatch' error\n            # that occurs when using the npu device and setting padding_mode to 'constant'.\n            inf_tensor = paddle.full_like(attn, float(\"-inf\"))\n        else:\n            # the default way\n            inf_tensor = paddle.ones_like(attn) * float(\"-inf\")\n\n        # Filter out zero-paddings\n        attn = paddle.where(mask.tile((1, C, 1)) == 0, inf_tensor, attn)\n\n        attn = F.softmax(attn, axis=2)\n        mean, std = _compute_statistics(x, attn)\n\n        # Append mean and std of the batch\n        pooled_stats = paddle.concat((mean, std), axis=1)\n        pooled_stats = pooled_stats.unsqueeze(2)\n\n        return pooled_stats\n\n\nclass SERes2NetBlock(nn.Layer):\n    def __init__(\n            self,\n            in_channels,\n            out_channels,\n            res2net_scale=8,\n            se_channels=128,\n            kernel_size=1,\n            dilation=1,\n            activation=nn.ReLU, ):\n        \"\"\"Implementation of Squeeze-Extraction Res2Blocks in ECAPA-TDNN network model\n           The paper is refered \"Squeeze-and-Excitation Networks\"\n           whose url is: https://arxiv.org/pdf/1709.01507.pdf\n        Args:\n            in_channels (int): input channels or input data dimensions\n            out_channels (int): output channels or output data dimensions\n            res2net_scale (int, optional): scale in the res2net block. Defaults to 8.\n            se_channels (int, optional): embedding dimensions of res2net block. Defaults to 128.\n            kernel_size (int, optional): kernel size of 1-d convolution in TDNN block. Defaults to 1.\n            dilation (int, optional): dilation of 1-d convolution in TDNN block. Defaults to 1.\n            activation (paddle.nn.class, optional): activation function. Defaults to nn.ReLU.\n        \"\"\"\n        super().__init__()\n        self.out_channels = out_channels\n        self.tdnn1 = TDNNBlock(\n            in_channels,\n            out_channels,\n            kernel_size=1,\n            dilation=1,\n            activation=activation, )\n        self.res2net_block = Res2NetBlock(out_channels, out_channels,\n                                          res2net_scale, dilation)\n        self.tdnn2 = TDNNBlock(\n            out_channels,\n            out_channels,\n            kernel_size=1,\n            dilation=1,\n            activation=activation, )\n        self.se_block = SEBlock(out_channels, se_channels, out_channels)\n\n        self.shortcut = None\n        if in_channels != out_channels:\n            self.shortcut = Conv1d(\n                in_channels=in_channels,\n                out_channels=out_channels,\n                kernel_size=1, )\n\n    def forward(self, x, lengths=None):\n        residual = x\n        if self.shortcut:\n            residual = self.shortcut(x)\n\n        x = self.tdnn1(x)\n        x = self.res2net_block(x)\n        x = self.tdnn2(x)\n        x = self.se_block(x, lengths)\n\n        return x + residual\n\n\nclass EcapaTdnn(nn.Layer):\n    def __init__(\n            self,\n            input_size,\n            lin_neurons=192,\n            activation=nn.ReLU,\n            channels=[512, 512, 512, 512, 1536],\n            kernel_sizes=[5, 3, 3, 3, 1],\n            dilations=[1, 2, 3, 4, 1],\n            attention_channels=128,\n            res2net_scale=8,\n            se_channels=128,\n            global_context=True, ):\n        \"\"\"Implementation of ECAPA-TDNN backbone model network\n           The paper is refered as \"ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation in TDNN Based Speaker Verification\"\n           whose url is: https://arxiv.org/abs/2005.07143\n        Args:\n            input_size (_type_): input fature dimension\n            lin_neurons (int, optional): speaker embedding size. Defaults to 192.\n            activation (paddle.nn.class, optional): activation function. Defaults to nn.ReLU.\n            channels (list, optional): inter embedding dimension. Defaults to [512, 512, 512, 512, 1536].\n            kernel_sizes (list, optional): kernel size of 1-d convolution in TDNN block . Defaults to [5, 3, 3, 3, 1].\n            dilations (list, optional): dilations of 1-d convolution in TDNN block. Defaults to [1, 2, 3, 4, 1].\n            attention_channels (int, optional): attention dimensions. Defaults to 128.\n            res2net_scale (int, optional): scale value in res2net. Defaults to 8.\n            se_channels (int, optional): dimensions of squeeze-excitation block. Defaults to 128.\n            global_context (bool, optional): global context flag. Defaults to True.\n        \"\"\"\n        super().__init__()\n        assert len(channels) == len(kernel_sizes)\n        assert len(channels) == len(dilations)\n        self.channels = channels\n        self.blocks = nn.LayerList()\n        self.emb_size = lin_neurons\n\n        # The initial TDNN layer\n        self.blocks.append(\n            TDNNBlock(\n                input_size,\n                channels[0],\n                kernel_sizes[0],\n                dilations[0],\n                activation, ))\n\n        # SE-Res2Net layers\n        for i in range(1, len(channels) - 1):\n            self.blocks.append(\n                SERes2NetBlock(\n                    channels[i - 1],\n                    channels[i],\n                    res2net_scale=res2net_scale,\n                    se_channels=se_channels,\n                    kernel_size=kernel_sizes[i],\n                    dilation=dilations[i],\n                    activation=activation, ))\n\n        # Multi-layer feature aggregation\n        self.mfa = TDNNBlock(\n            channels[-1],\n            channels[-1],\n            kernel_sizes[-1],\n            dilations[-1],\n            activation, )\n\n        # Attentive Statistical Pooling\n        self.asp = AttentiveStatisticsPooling(\n            channels[-1],\n            attention_channels=attention_channels,\n            global_context=global_context, )\n        self.asp_bn = BatchNorm1d(input_size=channels[-1] * 2)\n\n        # Final linear transformation\n        self.fc = Conv1d(\n            in_channels=channels[-1] * 2,\n            out_channels=self.emb_size,\n            kernel_size=1, )\n\n    def forward(self, x, lengths=None):\n        \"\"\"\n        Compute embeddings.\n\n        Args:\n            x (paddle.Tensor): Input log-fbanks with shape (N, n_mels, T).\n            lengths (paddle.Tensor, optional): Length proportions of batch length with shape (N). Defaults to None.\n\n        Returns:\n            paddle.Tensor: Output embeddings with shape (N, self.emb_size, 1)\n        \"\"\"\n        xl = []\n        for layer in self.blocks:\n            try:\n                x = layer(x, lengths=lengths)\n            except TypeError:\n                x = layer(x)\n            xl.append(x)\n\n        # Multi-layer feature aggregation\n        x = paddle.concat(xl[1:], axis=1)\n        x = self.mfa(x)\n\n        # Attentive Statistical Pooling\n        x = self.asp(x, lengths=lengths)\n        x = self.asp_bn(x)\n\n        # Final linear transformation\n        x = self.fc(x)\n\n        return x\n"
  },
  {
    "path": "paddlespeech/vector/models/lstm_speaker_encoder.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nimport paddle\nfrom paddle import nn\nfrom paddle.nn import functional as F\nfrom paddle.nn import initializer as I\nfrom scipy.interpolate import interp1d\nfrom scipy.optimize import brentq\nfrom sklearn.metrics import roc_curve\n\n\nclass LSTMSpeakerEncoder(nn.Layer):\n    def __init__(self, n_mels, num_layers, hidden_size, output_size):\n        super().__init__()\n        self.lstm = nn.LSTM(n_mels, hidden_size, num_layers)\n        self.linear = nn.Linear(hidden_size, output_size)\n        self.similarity_weight = self.create_parameter(\n            [1], default_initializer=I.Constant(10.))\n        self.similarity_bias = self.create_parameter(\n            [1], default_initializer=I.Constant(-5.))\n\n    def forward(self, utterances, num_speakers, initial_states=None):\n        normalized_embeds = self.embed_sequences(utterances, initial_states)\n        embeds = normalized_embeds.reshape([num_speakers, -1, num_speakers])\n        loss, eer = self.loss(embeds)\n        return loss, eer\n\n    def embed_sequences(self, utterances, initial_states=None, reduce=False):\n        out, (h, c) = self.lstm(utterances, initial_states)\n        embeds = F.relu(self.linear(h[-1]))\n        normalized_embeds = F.normalize(embeds)\n        if reduce:\n            embed = paddle.mean(normalized_embeds, 0)\n            embed = F.normalize(embed, axis=0)\n            return embed\n        return normalized_embeds\n\n    def embed_utterance(self, utterances, initial_states=None):\n        # utterances: [B, T, C] -> embed [C']\n        embed = self.embed_sequences(utterances, initial_states, reduce=True)\n        return embed\n\n    def similarity_matrix(self, embeds):\n        # (N, M, C)\n        speakers_per_batch, utterances_per_speaker, embed_dim = embeds.shape\n\n        # Inclusive centroids (1 per speaker). Cloning is needed for reverse differentiation\n        centroids_incl = paddle.mean(embeds, axis=1)\n        centroids_incl_norm = paddle.norm(\n            centroids_incl, p=2, axis=1, keepdim=True)\n        normalized_centroids_incl = centroids_incl / centroids_incl_norm\n\n        # Exclusive centroids (1 per utterance)\n        centroids_excl = paddle.broadcast_to(\n            paddle.sum(embeds, axis=1, keepdim=True), embeds.shape) - embeds\n        centroids_excl /= (utterances_per_speaker - 1)\n        centroids_excl_norm = paddle.norm(\n            centroids_excl, p=2, axis=2, keepdim=True)\n        normalized_centroids_excl = centroids_excl / centroids_excl_norm\n\n        p1 = paddle.matmul(\n            embeds.reshape([-1, embed_dim]),\n            normalized_centroids_incl,\n            transpose_y=True)  # (NMN)\n        p1 = p1.reshape([-1])\n        # print(\"p1: \", p1.shape)\n        p2 = paddle.bmm(\n            embeds.reshape([-1, 1, embed_dim]),\n            normalized_centroids_excl.reshape([-1, embed_dim, 1]))  # (NM, 1, 1)\n        p2 = p2.reshape([-1])  # （NM)\n\n        # begin: alternative implementation for scatter\n        with paddle.no_grad():\n            index = paddle.arange(\n                0, speakers_per_batch * utterances_per_speaker,\n                dtype=\"int64\").reshape(\n                    [speakers_per_batch, utterances_per_speaker])\n            index = index * speakers_per_batch + paddle.arange(\n                0, speakers_per_batch, dtype=\"int64\").unsqueeze(-1)\n            index = paddle.reshape(index, [-1])\n        ones = paddle.ones(\n            [speakers_per_batch * utterances_per_speaker * speakers_per_batch])\n        zeros = paddle.zeros_like(index, dtype=ones.dtype)\n        mask_p1 = paddle.scatter(ones, index, zeros)\n        p = p1 * mask_p1 + (1 - mask_p1) * paddle.scatter(ones, index, p2)\n        # end: alternative implementation for scatter\n        # p = paddle.scatter(p1, index, p2)\n\n        p = p * self.similarity_weight + self.similarity_bias  # neg\n        p = p.reshape(\n            [speakers_per_batch * utterances_per_speaker, speakers_per_batch])\n        return p, p1, p2\n\n    def do_gradient_ops(self):\n        for p in [self.similarity_weight, self.similarity_bias]:\n            g = p._grad_ivar()\n            g = g * 0.01\n\n    def inv_argmax(self, i, num):\n        return np.eye(1, num, i, dtype=int)[0]\n\n    def loss(self, embeds):\n        \"\"\"\n        Computes the softmax loss according the section 2.1 of GE2E.\n\n        :param embeds: the embeddings as a tensor of shape (speakers_per_batch, \n        utterances_per_speaker, embedding_size)\n        :return: the loss and the EER for this batch of embeddings.\n        \"\"\"\n        speakers_per_batch, utterances_per_speaker = embeds.shape[:2]\n\n        # Loss\n        sim_matrix, *_ = self.similarity_matrix(embeds)\n        sim_matrix = sim_matrix.reshape(\n            [speakers_per_batch * utterances_per_speaker, speakers_per_batch])\n        target = paddle.arange(\n            0, speakers_per_batch, dtype=\"int64\").unsqueeze(-1)\n        target = paddle.expand(target,\n                               [speakers_per_batch, utterances_per_speaker])\n        target = paddle.reshape(target, [-1])\n\n        loss = nn.CrossEntropyLoss()(sim_matrix, target)\n\n        # EER (not backpropagated)\n        with paddle.no_grad():\n            ground_truth = target.numpy()\n            labels = np.array(\n                [self.inv_argmax(i, speakers_per_batch) for i in ground_truth])\n            preds = sim_matrix.numpy()\n\n            # Snippet from https://yangcha.github.io/EER-ROC/\n            fpr, tpr, thresholds = roc_curve(labels.flatten(), preds.flatten())\n            eer = brentq(lambda x: 1. - x - interp1d(fpr, tpr)(x), 0., 1.)\n\n        return loss, eer\n"
  },
  {
    "path": "paddlespeech/vector/modules/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/modules/layer.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn as nn\nfrom paddle.autograd import PyLayer\n\n\nclass GradientReversalFunction(PyLayer):\n    \"\"\"Gradient Reversal Layer from:\n    Unsupervised Domain Adaptation by Backpropagation (Ganin & Lempitsky, 2015)\n\n    Forward pass is the identity function. In the backward pass,\n    the upstream gradients are multiplied by -lambda (i.e. gradient is reversed)\n    \"\"\"\n\n    @staticmethod\n    def forward(ctx, x, lambda_=1):\n        \"\"\"Forward in networks\n        \"\"\"\n        ctx.save_for_backward(lambda_)\n        return x.clone()\n\n    @staticmethod\n    def backward(ctx, grads):\n        \"\"\"Backward in networks\n        \"\"\"\n        lambda_, = ctx.saved_tensor()\n        dx = -lambda_ * grads\n        return dx\n\n\nclass GradientReversalLayer(nn.Layer):\n    \"\"\"Gradient Reversal Layer from:\n    Unsupervised Domain Adaptation by Backpropagation (Ganin & Lempitsky, 2015)\n\n    Forward pass is the identity function. In the backward pass,\n    the upstream gradients are multiplied by -lambda (i.e. gradient is reversed)\n    \"\"\"\n\n    def __init__(self, lambda_=1):\n        super(GradientReversalLayer, self).__init__()\n        self.lambda_ = lambda_\n\n    def forward(self, x):\n        \"\"\"Forward in networks\n        \"\"\"\n        return GradientReversalFunction.apply(x, self.lambda_)\n\n\nif __name__ == \"__main__\":\n    paddle.set_device(\"cpu\")\n\n    data = paddle.randn([2, 3], dtype=\"float64\")\n    data.stop_gradient = False\n    grl = GradientReversalLayer(1)\n    out = grl(data)\n    out.mean().backward()\n    print(data.grad)\n\n    data = paddle.randn([2, 3], dtype=\"float64\")\n    data.stop_gradient = False\n    grl = GradientReversalLayer(-1)\n    out = grl(data)\n    out.mean().backward()\n    print(data.grad)\n"
  },
  {
    "path": "paddlespeech/vector/modules/loss.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# This is modified from SpeechBrain\n# https://github.com/speechbrain/speechbrain/blob/085be635c07f16d42cd1295045bc46c407f1e15b/speechbrain/nnet/losses.py\nimport math\n\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\nfrom paddle.nn import initializer as I\n\n\nclass AngularMargin(nn.Layer):\n    def __init__(self, margin=0.0, scale=1.0):\n        \"\"\"An implementation of Angular Margin (AM) proposed in the following\n           paper: '''Margin Matters: Towards More Discriminative Deep Neural Network\n           Embeddings for Speaker Recognition''' (https://arxiv.org/abs/1906.07317)\n\n        Args:\n            margin (float, optional): The margin for cosine similiarity. Defaults to 0.0.\n            scale (float, optional): The scale for cosine similiarity. Defaults to 1.0.\n        \"\"\"\n        super(AngularMargin, self).__init__()\n        self.margin = margin\n        self.scale = scale\n\n    def forward(self, outputs, targets):\n        outputs = outputs - self.margin * targets\n        return self.scale * outputs\n\n\nclass AdditiveAngularMargin(AngularMargin):\n    def __init__(self, margin=0.0, scale=1.0, easy_margin=False):\n        \"\"\"The Implementation of Additive Angular Margin (AAM) proposed\n       in the following paper: '''Margin Matters: Towards More Discriminative Deep Neural Network Embeddings for Speaker Recognition'''\n       (https://arxiv.org/abs/1906.07317)\n\n        Args:\n            margin (float, optional): margin factor. Defaults to 0.0.\n            scale (float, optional): scale factor. Defaults to 1.0.\n            easy_margin (bool, optional): easy_margin flag. Defaults to False.\n        \"\"\"\n        super(AdditiveAngularMargin, self).__init__(margin, scale)\n        self.easy_margin = easy_margin\n\n        self.cos_m = math.cos(self.margin)\n        self.sin_m = math.sin(self.margin)\n        self.th = math.cos(math.pi - self.margin)\n        self.mm = math.sin(math.pi - self.margin) * self.margin\n\n    def forward(self, outputs, targets):\n        cosine = outputs.astype('float32')\n        sine = paddle.sqrt(1.0 - paddle.pow(cosine, 2))\n        phi = cosine * self.cos_m - sine * self.sin_m  # cos(theta + m)\n        if self.easy_margin:\n            phi = paddle.where(cosine > 0, phi, cosine)\n        else:\n            phi = paddle.where(cosine > self.th, phi, cosine - self.mm)\n        outputs = (targets * phi) + ((1.0 - targets) * cosine)\n        return self.scale * outputs\n\n\nclass LogSoftmaxWrapper(nn.Layer):\n    def __init__(self, loss_fn):\n        \"\"\"Speaker identificatin loss function wrapper \n           including all of compositions of the loss transformation\n        Args:\n            loss_fn (_type_): the loss value of a batch\n        \"\"\"\n        super(LogSoftmaxWrapper, self).__init__()\n        self.loss_fn = loss_fn\n        self.criterion = paddle.nn.KLDivLoss(reduction=\"sum\")\n\n    def forward(self, outputs, targets, length=None):\n        targets = F.one_hot(targets, outputs.shape[1])\n        try:\n            predictions = self.loss_fn(outputs, targets)\n        except TypeError:\n            predictions = self.loss_fn(outputs)\n\n        predictions = F.log_softmax(predictions, axis=1)\n        loss = self.criterion(predictions, targets) / targets.sum()\n        return loss\n\n\nclass NCELoss(nn.Layer):\n    \"\"\"Noise Contrastive Estimation loss funtion\n\n    Noise Contrastive Estimation (NCE) is an approximation method that is used to\n    work around the huge computational cost of large softmax layer.\n    The basic idea is to convert the prediction problem into classification problem\n    at training stage. It has been proved that these two criterions converges to\n    the same minimal point as long as noise distribution is close enough to real one.\n\n    NCE bridges the gap between generative models and discriminative models,\n    rather than simply speedup the softmax layer.\n    With NCE, you can turn almost anything into posterior with less effort (I think).\n\n    Refs:\n    NCE：http://www.cs.helsinki.fi/u/ahyvarin/papers/Gutmann10AISTATS.pdf\n    Thanks: https://github.com/mingen-pan/easy-to-use-NCE-RNN-for-Pytorch/blob/master/nce.py\n\n    Examples:\n    Q = Q_from_tokens(output_dim)\n    NCELoss(Q)\n    \"\"\"\n\n    def __init__(self, Q, noise_ratio=100, Z_offset=9.5):\n        \"\"\"Noise Contrastive Estimation loss funtion\n\n        Args:\n            Q (tensor): prior model, uniform or guassian\n            noise_ratio (int, optional): noise sampling times. Defaults to 100.\n            Z_offset (float, optional): scale of post processing the score. Defaults to 9.5.\n        \"\"\"\n        super(NCELoss, self).__init__()\n        assert type(noise_ratio) is int\n        self.Q = paddle.to_tensor(Q, stop_gradient=False)\n        self.N = self.Q.shape[0]\n        self.K = noise_ratio\n        self.Z_offset = Z_offset\n\n    def forward(self, output, target):\n        \"\"\"Forward inference\n\n        Args:\n            output (tensor): the model output, which is the input of loss function\n        \"\"\"\n        output = paddle.reshape(output, [-1, self.N])\n        B = output.shape[0]\n        noise_idx = self.get_noise(B)\n        idx = self.get_combined_idx(target, noise_idx)\n        P_target, P_noise = self.get_prob(idx, output, sep_target=True)\n        Q_target, Q_noise = self.get_Q(idx)\n        loss = self.nce_loss(P_target, P_noise, Q_noise, Q_target)\n        return loss.mean()\n\n    def get_Q(self, idx, sep_target=True):\n        \"\"\"Get prior model of batchsize data\n        \"\"\"\n        idx_size = idx.size\n        prob_model = paddle.to_tensor(\n            self.Q.numpy()[paddle.reshape(idx, [-1]).numpy()])\n        prob_model = paddle.reshape(prob_model, [idx.shape[0], idx.shape[1]])\n        if sep_target:\n            return prob_model[:, 0], prob_model[:, 1:]\n        else:\n            return prob_model\n\n    def get_prob(self, idx, scores, sep_target=True):\n        \"\"\"Post processing the score of post model(output of nn) of batchsize data\n        \"\"\"\n        scores = self.get_scores(idx, scores)\n        scale = paddle.to_tensor([self.Z_offset], dtype='float64')\n        scores = paddle.add(scores, -scale)\n        prob = paddle.exp(scores)\n        if sep_target:\n            return prob[:, 0], prob[:, 1:]\n        else:\n            return prob\n\n    def get_scores(self, idx, scores):\n        \"\"\"Get the score of post model(output of nn) of batchsize data\n        \"\"\"\n        B, N = scores.shape\n        K = idx.shape[1]\n        idx_increment = paddle.to_tensor(\n            N * paddle.reshape(paddle.arange(B), [B, 1]) * paddle.ones([1, K]),\n            dtype=\"int64\",\n            stop_gradient=False)\n        new_idx = idx_increment + idx\n        new_scores = paddle.index_select(\n            paddle.reshape(scores, [-1]), paddle.reshape(new_idx, [-1]))\n\n        return paddle.reshape(new_scores, [B, K])\n\n    def get_noise(self, batch_size, uniform=True):\n        \"\"\"Select noise sample\n        \"\"\"\n        if uniform:\n            noise = np.random.randint(self.N, size=self.K * batch_size)\n        else:\n            noise = np.random.choice(\n                self.N, self.K * batch_size, replace=True, p=self.Q.data)\n        noise = paddle.to_tensor(noise, dtype='int64', stop_gradient=False)\n        noise_idx = paddle.reshape(noise, [batch_size, self.K])\n        return noise_idx\n\n    def get_combined_idx(self, target_idx, noise_idx):\n        \"\"\"Combined target and noise\n        \"\"\"\n        target_idx = paddle.reshape(target_idx, [-1, 1])\n        return paddle.concat((target_idx, noise_idx), 1)\n\n    def nce_loss(self, prob_model, prob_noise_in_model, prob_noise,\n                 prob_target_in_noise):\n        \"\"\"Combined the loss of target and noise\n        \"\"\"\n\n        def safe_log(tensor):\n            \"\"\"Safe log\n            \"\"\"\n            EPSILON = 1e-10\n            return paddle.log(EPSILON + tensor)\n\n        model_loss = safe_log(prob_model /\n                              (prob_model + self.K * prob_target_in_noise))\n        model_loss = paddle.reshape(model_loss, [-1])\n\n        noise_loss = paddle.sum(\n            safe_log((self.K * prob_noise) /\n                     (prob_noise_in_model + self.K * prob_noise)), -1)\n        noise_loss = paddle.reshape(noise_loss, [-1])\n\n        loss = -(model_loss + noise_loss)\n\n        return loss\n\n\nclass FocalLoss(nn.Layer):\n    \"\"\"This criterion is a implemenation of Focal Loss, which is proposed in \n    Focal Loss for Dense Object Detection.\n\n        Loss(x, class) = - \\alpha (1-softmax(x)[class])^gamma \\log(softmax(x)[class])\n\n    The losses are averaged across observations for each minibatch.\n\n    Args:\n        alpha(1D Tensor, Variable) : the scalar factor for this criterion\n        gamma(float, double) : gamma > 0; reduces the relative loss for well-classiﬁed examples (p > .5), \n                                putting more focus on hard, misclassiﬁed examples\n        size_average(bool): By default, the losses are averaged over observations for each minibatch.\n                            However, if the field size_average is set to False, the losses are\n                            instead summed for each minibatch.\n    \"\"\"\n\n    def __init__(self, alpha=1, gamma=0, size_average=True, ignore_index=-100):\n        super(FocalLoss, self).__init__()\n        self.alpha = alpha\n        self.gamma = gamma\n        self.size_average = size_average\n        self.ce = nn.CrossEntropyLoss(\n            ignore_index=ignore_index, reduction=\"none\")\n\n    def forward(self, outputs, targets):\n        \"\"\"Forword inference.\n\n        Args:\n            outputs: input tensor\n            target: target label tensor\n        \"\"\"\n        ce_loss = self.ce(outputs, targets)\n        pt = paddle.exp(-ce_loss)\n        focal_loss = self.alpha * (1 - pt)**self.gamma * ce_loss\n        if self.size_average:\n            return focal_loss.mean()\n        else:\n            return focal_loss.sum()\n\n\nclass GE2ELoss(nn.Layer):\n    \"\"\"Generalized end-to-end loss which defined in the paper \"GENERALIZED END-TO-END LOSS FOR SPEAKER VERIFICATION\"\n    \"\"\"\n\n    def __init__(self, init_w=10.0, init_b=-5.0, loss_method=\"softmax\"):\n        super(GE2ELoss, self).__init__()\n        self.loss_method = loss_method.lower()\n        self.w = self.create_parameter(\n            [1], default_initializer=I.Constant(init_w))\n        self.b = self.create_parameter(\n            [1], default_initializer=I.Constant(init_b))\n        assert self.loss_method in [\"softmax\", \"contrast\"]\n\n    def get_cossim(self, embeddings_list, centroids):\n        \"\"\"Compute cosine similarity for each speaker\n        \"\"\"\n        cossims = []\n        for s_idx, embeddings in enumerate(embeddings_list):\n            cossim = F.linear(embeddings, centroids.t())\n            e_num = len(embeddings)\n            if embeddings.ndim > 1 and e_num > 1:\n                expand_centroids = paddle.expand(\n                    centroids[s_idx], shape=[e_num, embeddings.shape[1]])\n                new_centroids = (expand_centroids * e_num - embeddings) / (\n                    e_num - 1)\n                sims = F.cosine_similarity(embeddings, new_centroids)\n                cossim[:, s_idx] = sims\n            cossims.append(self.w * cossim + self.b)\n\n        return cossims\n\n    def cal_softmax_loss(self, cossims):\n        \"\"\"Calculate softmax loss\n        \"\"\"\n        loss = 0.0\n        n = 0\n        for s_idx, cossim in enumerate(cossims):\n            loss += -F.log_softmax(cossim, axis=1)[:, s_idx].sum()\n            n += cossim.shape[0]\n\n        return loss / n\n\n    def cal_contrast_loss(self, cossims):\n        \"\"\"Calculate contrast loss\n        \"\"\"\n        loss = 0.0\n        n = 0\n        for s_idx, cossim in enumerate(cossims):\n            cossim = F.sigmoid(cossim)\n            col_loss = 1. - cossim[:, s_idx]\n            if len(cossims) > 1:\n                if s_idx == 0:\n                    excl_centroids_sigmoids = cossim[:, s_idx + 1:]\n                elif s_idx == (len(cossims) - 1):\n                    excl_centroids_sigmoids = cossim[:, :s_idx]\n                else:\n                    excl_centroids_sigmoids = paddle.concat(\n                        (cossim[:, :s_idx], cossim[:, s_idx + 1:]), axis=1)\n                col_loss += paddle.max(excl_centroids_sigmoids, axis=1)[0]\n            loss += col_loss.sum()\n            n += cossim.shape[0]\n\n        return loss / n\n\n    def forward(self, output, target):\n        \"\"\"Forward inference\n\n            Args:\n                output: input tensor\n                target: target label tensor\n        \"\"\"\n        spkers = paddle.unique(target)\n\n        embeddings_list = []\n        for spkid in spkers:\n            index = (target == spkid).nonzero().reshape([-1])\n            embeddings_list.append(output[index])\n        # cal centroid\n        centroids = []\n        for embeddings in embeddings_list:\n            if (embeddings.ndim > 1):\n                spker_centroid = paddle.mean(embeddings, axis=0)\n            else:\n                spker_centroid = embeddings\n            centroids.append(spker_centroid.clone() / paddle.norm(\n                spker_centroid, axis=0, keepdim=True))\n        centroids = paddle.stack(centroids)\n        # cal cosine similarity\n        cossims = self.get_cossim(embeddings_list, centroids)\n\n        # cal loss\n        if self.loss_method == \"softmax\":\n            loss = self.cal_softmax_loss(cossims)\n        else:\n            loss = self.cal_contrast_loss(cossims)\n\n        return loss\n\n\nif __name__ == \"__main__\":\n    import numpy as np\n    from paddlespeech.vector.utils.vector_utils import Q_from_tokens\n    paddle.set_device(\"cpu\")\n\n    input_data = paddle.uniform([32, 100], dtype=\"float64\")\n    label_data = np.random.randint(0, 4, size=(32)).astype(np.int64)\n    input = paddle.to_tensor(input_data)\n    label = paddle.to_tensor(label_data)\n\n    loss1 = GE2ELoss(loss_method=\"softmax\")\n    loss = loss1.forward(input, label)\n    print(\"GE2ELoss softmax-loss: %.5f\" % (loss[0]))\n\n    loss2 = GE2ELoss(loss_method=\"contrast\")\n    loss = loss2.forward(input, label)\n    print(\"GE2ELoss contrast-loss: %.5f\" % (loss[0]))\n\n    loss3 = FocalLoss()\n    loss = loss3.forward(input, label)\n    print(\"FocalLoss loss: %.5f\" % (loss))\n\n    Q = Q_from_tokens(100)\n    loss4 = NCELoss(Q)\n    loss = loss4.forward(input, label)\n    print(\"NCELoss loss: %.5f\" % (loss))\n"
  },
  {
    "path": "paddlespeech/vector/modules/sid_model.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\nimport paddle.nn as nn\nimport paddle.nn.functional as F\n\n\nclass SpeakerIdetification(nn.Layer):\n    def __init__(\n            self,\n            backbone,\n            num_class,\n            lin_blocks=0,\n            lin_neurons=192,\n            dropout=0.1, ):\n        \"\"\"The speaker identification model, which includes the speaker backbone network \n           and the a linear transform to speaker class num in training\n\n        Args:\n            backbone (Paddle.nn.Layer class): the speaker identification backbone network model\n            num_class (_type_): the speaker class num in the training dataset\n            lin_blocks (int, optional): the linear layer transform between the embedding and the final linear layer. Defaults to 0.\n            lin_neurons (int, optional): the output dimension of final linear layer. Defaults to 192.\n            dropout (float, optional): the dropout factor on the embedding. Defaults to 0.1.\n        \"\"\"\n        super(SpeakerIdetification, self).__init__()\n        # speaker idenfication backbone network model\n        # the output of the backbond network is the target embedding\n        self.backbone = backbone\n        if dropout > 0:\n            self.dropout = nn.Dropout(dropout)\n        else:\n            self.dropout = None\n\n        # construct the speaker classifer\n        input_size = self.backbone.emb_size\n        self.blocks = nn.LayerList()\n        for i in range(lin_blocks):\n            self.blocks.extend([\n                nn.BatchNorm1D(input_size),\n                nn.Linear(in_features=input_size, out_features=lin_neurons),\n            ])\n            input_size = lin_neurons\n\n        # the final layer\n        self.weight = paddle.create_parameter(\n            shape=(input_size, num_class),\n            dtype='float32',\n            attr=paddle.ParamAttr(initializer=nn.initializer.XavierUniform()), )\n\n    def forward(self, x, lengths=None):\n        \"\"\"Do the speaker identification model forwrd, \n           including the speaker embedding model and the classifier model network\n\n        Args:\n            x (paddle.Tensor): input audio feats, \n                               shape=[batch, dimension, times]\n            lengths (paddle.Tensor, optional): input audio length.\n                                        shape=[batch, times]\n                                        Defaults to None.\n\n        Returns:\n            paddle.Tensor: return the logits of the feats\n        \"\"\"\n        # x.shape: (N, C, L)\n        x = self.backbone(x, lengths).squeeze(\n            -1)  # (N, emb_size, 1) -> (N, emb_size)\n        if self.dropout is not None:\n            x = self.dropout(x)\n\n        for fc in self.blocks:\n            x = fc(x)\n\n        logits = F.linear(F.normalize(x), F.normalize(self.weight, axis=0))\n\n        return logits\n"
  },
  {
    "path": "paddlespeech/vector/training/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/training/scheduler.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddle.optimizer.lr import LRScheduler\n\n\nclass CyclicLRScheduler(LRScheduler):\n    def __init__(self,\n                 base_lr: float=1e-8,\n                 max_lr: float=1e-3,\n                 step_size: int=10000):\n\n        super(CyclicLRScheduler, self).__init__()\n\n        self.current_step = -1\n        self.base_lr = base_lr\n        self.max_lr = max_lr\n        self.step_size = step_size\n\n    def step(self):\n        if not hasattr(self, 'current_step'):\n            return\n\n        self.current_step += 1\n        if self.current_step >= 2 * self.step_size:\n            self.current_step %= 2 * self.step_size\n\n        self.last_lr = self.get_lr()\n\n    def get_lr(self):\n        p = self.current_step / (2 * self.step_size)  # Proportion in one cycle.\n        if p < 0.5:  # Increase\n            return self.base_lr + p / 0.5 * (self.max_lr - self.base_lr)\n        else:  # Decrease\n            return self.max_lr - (p / 0.5 - 1) * (self.max_lr - self.base_lr)\n"
  },
  {
    "path": "paddlespeech/vector/training/seeding.py",
    "content": "# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom paddlespeech.s2t.utils.log import Log\n\nlogger = Log(__name__).getlog()\nimport random\n\nimport numpy as np\nimport paddle\n\n\ndef seed_everything(seed: int):\n    \"\"\"Seed paddle, random and np.random to help reproductivity.\"\"\"\n    paddle.seed(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    logger.info(f\"Set the seed of paddle, random, np.random to {seed}.\")\n"
  },
  {
    "path": "paddlespeech/vector/utils/__init__.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "paddlespeech/vector/utils/time.py",
    "content": "# Copyright (c) 2021  PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport math\nimport time\n\n\nclass Timer(object):\n    '''Calculate runing speed and estimated time of arrival(ETA)'''\n\n    def __init__(self, total_step: int):\n        self.total_step = total_step\n        self.last_start_step = 0\n        self.current_step = 0\n        self._is_running = True\n        self.cur_ips = 0\n\n    def start(self):\n        self.last_time = time.time()\n        self.start_time = time.time()\n\n    def stop(self):\n        self._is_running = False\n        self.end_time = time.time()\n\n    def count(self) -> int:\n        if not self.current_step >= self.total_step:\n            self.current_step += 1\n        return self.current_step\n\n    @property\n    def timing(self) -> float:\n        run_steps = self.current_step - self.last_start_step\n        self.last_start_step = self.current_step\n        time_used = time.time() - self.last_time\n        self.last_time = time.time()\n        self.cur_ips = run_steps / time_used\n        return time_used / run_steps\n\n    @property\n    def is_running(self) -> bool:\n        return self._is_running\n\n    @property\n    def ips(self) -> float:\n        return self.cur_ips\n\n    @property\n    def eta(self) -> str:\n        if not self.is_running:\n            return '00:00:00'\n        remaining_time = time.time() - self.start_time\n        return seconds_to_hms(remaining_time)\n\n\ndef seconds_to_hms(seconds: int) -> str:\n    '''Convert the number of seconds to hh:mm:ss'''\n    h = math.floor(seconds / 3600)\n    m = math.floor((seconds - h * 3600) / 60)\n    s = int(seconds - h * 3600 - m * 60)\n    hms_str = '{:0>2}:{:0>2}:{:0>2}'.format(h, m, s)\n    return hms_str\n"
  },
  {
    "path": "paddlespeech/vector/utils/vector_utils.py",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport paddle\n\n\ndef get_chunks(seg_dur, audio_id, audio_duration):\n    \"\"\"Get all chunk segments from a utterance\n\n    Args:\n        seg_dur (float): segment chunk duration, seconds\n        audio_id (str): utterance name, \n        audio_duration (float): utterance duration, seconds\n\n    Returns:\n        List: all the chunk segments \n    \"\"\"\n    num_chunks = int(audio_duration / seg_dur)  # all in seconds\n    chunk_lst = [\n        audio_id + \"_\" + str(i * seg_dur) + \"_\" + str(i * seg_dur + seg_dur)\n        for i in range(num_chunks)\n    ]\n    return chunk_lst\n\n\ndef Q_from_tokens(token_num):\n    \"\"\"Get prior model, data from uniform, would support others(guassian) in future\n    \"\"\"\n    freq = [1] * token_num\n    Q = paddle.to_tensor(freq, dtype='float64')\n    return Q / Q.sum()\n"
  },
  {
    "path": "runtime/.clang-format",
    "content": "# This file is used by clang-format to autoformat paddle source code\n#\n# The clang-format is part of llvm toolchain.\n# It need to install llvm and clang to format source code style.\n#\n# The basic usage is,\n#   clang-format -i -style=file PATH/TO/SOURCE/CODE\n#\n# The -style=file implicit use \".clang-format\" file located in one of\n# parent directory.\n# The -i means inplace change.\n#\n# The document of clang-format is\n#   http://clang.llvm.org/docs/ClangFormat.html\n#   http://clang.llvm.org/docs/ClangFormatStyleOptions.html\n---\nLanguage:        Cpp\nBasedOnStyle:  Google\nIndentWidth:     4\nTabWidth:        4\nContinuationIndentWidth: 4\nMaxEmptyLinesToKeep: 2\nAccessModifierOffset: -2  # The private/protected/public has no indent in class\nStandard:  Cpp11\nAllowAllParametersOfDeclarationOnNextLine: true\nBinPackParameters: false\nBinPackArguments: false\n...\n\n"
  },
  {
    "path": "runtime/.gitignore",
    "content": "engine/common/base/flags.h\nengine/common/base/log.h\n\ntools/valgrind*\n*log\nfc_patch/*\ntest\n"
  },
  {
    "path": "runtime/CMakeLists.txt",
    "content": "# >=3.17 support -DCMAKE_FIND_DEBUG_MODE=ON\ncmake_minimum_required(VERSION 3.17 FATAL_ERROR)\n\nset(CMAKE_PROJECT_INCLUDE_BEFORE \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/EnableCMP0077.cmake\")\n\nset(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} \"${CMAKE_CURRENT_SOURCE_DIR}/cmake\")\n\ninclude(system)\n\nproject(paddlespeech VERSION 0.1)\n\nset(PPS_VERSION_MAJOR 1)\nset(PPS_VERSION_MINOR 0)\nset(PPS_VERSION_PATCH 0)\nset(PPS_VERSION \"${PPS_VERSION_MAJOR}.${PPS_VERSION_MINOR}.${PPS_VERSION_PATCH}\")\n\n# compiler option\n# Keep the same with openfst, -fPIC or -fpic\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} --std=c++14 -pthread -fPIC -O0 -Wall -g -ldl\")\nSET(CMAKE_CXX_FLAGS_DEBUG \"$ENV{CXXFLAGS} --std=c++14 -pthread -fPIC -O0 -Wall -g -ggdb\")\nSET(CMAKE_CXX_FLAGS_RELEASE \"$ENV{CXXFLAGS} --std=c++14 -pthread -fPIC -O3 -Wall\")\n\nset(CMAKE_VERBOSE_MAKEFILE ON)\nset(CMAKE_FIND_DEBUG_MODE OFF)\nset(PPS_CXX_STANDARD 14)\n\n# set std-14\nset(CMAKE_CXX_STANDARD ${PPS_CXX_STANDARD})\n\n# Ninja Generator will set CMAKE_BUILD_TYPE to Debug\nif(NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE \"Release\" CACHE STRING \"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel\" FORCE)\nendif()\n\n# find_* e.g. find_library work when Cross-Compiling\nif(ANDROID)\n    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)\n    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)\n    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)\n    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)\nendif()\n\nif(BUILD_IN_MACOS)\n    add_definitions(\"-DOS_MACOSX\")\nendif()\n\n# install dir into `build/install`\nset(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)\n\ninclude(FetchContent)\ninclude(ExternalProject)\n\n# fc_patch dir\nset(FETCHCONTENT_QUIET off)\nget_filename_component(fc_patch \"fc_patch\" REALPATH BASE_DIR \"${CMAKE_SOURCE_DIR}\")\nset(FETCHCONTENT_BASE_DIR ${fc_patch})\n\n###############################################################################\n# Option Configurations\n###############################################################################\n# https://github.com/google/brotli/pull/655\noption(BUILD_SHARED_LIBS \"Build shared libraries\" ON)\n\noption(WITH_PPS_DEBUG \"debug option\" OFF)\nif (WITH_PPS_DEBUG)\n    add_definitions(\"-DPPS_DEBUG\")\nendif()\n\noption(WITH_ASR \"build asr\" ON)\noption(WITH_CLS \"build cls\" ON)\noption(WITH_VAD \"build vad\" ON)\n\noption(WITH_GPU \"NNet using GPU.\" OFF)\n\noption(WITH_PROFILING \"enable c++ profling\" OFF)\noption(WITH_TESTING \"unit test\" ON)\n\noption(WITH_ONNX \"u2 support onnx runtime\" OFF)\n\n###############################################################################\n# Include Third Party\n###############################################################################\ninclude(gflags)\n\ninclude(glog)\n\ninclude(pybind)\n\n#onnx\nif(WITH_ONNX)\n    add_definitions(-DUSE_ONNX)\nendif()\n\n# gtest\nif(WITH_TESTING)\n    include(gtest) # download, build, install gtest\nendif()\n\n# fastdeploy\ninclude(fastdeploy)\n\nif(WITH_ASR)\n    # openfst\n    include(openfst)\n    add_dependencies(openfst gflags extern_glog)\nendif()\n\n###############################################################################\n# Find Package\n###############################################################################\n# https://github.com/Kitware/CMake/blob/v3.1.0/Modules/FindThreads.cmake#L207\nfind_package(Threads REQUIRED)\n\nif(WITH_ASR)\n    # https://cmake.org/cmake/help/latest/module/FindPython3.html#module:FindPython3\n    find_package(Python3 COMPONENTS Interpreter Development)\n    find_package(pybind11 CONFIG)\n\n    if(Python3_FOUND)\n        message(STATUS \"Python3_FOUND = ${Python3_FOUND}\")\n        message(STATUS \"Python3_EXECUTABLE = ${Python3_EXECUTABLE}\")\n        message(STATUS \"Python3_LIBRARIES = ${Python3_LIBRARIES}\")\n        message(STATUS \"Python3_INCLUDE_DIRS = ${Python3_INCLUDE_DIRS}\")\n        message(STATUS \"Python3_LINK_OPTIONS = ${Python3_LINK_OPTIONS}\")\n        set(PYTHON_LIBRARIES ${Python3_LIBRARIES} CACHE STRING \"python lib\" FORCE)\n        set(PYTHON_INCLUDE_DIR ${Python3_INCLUDE_DIRS} CACHE STRING \"python inc\" FORCE)\n    endif()\n\n    message(STATUS \"PYTHON_LIBRARIES = ${PYTHON_LIBRARIES}\")\n    message(STATUS \"PYTHON_INCLUDE_DIR = ${PYTHON_INCLUDE_DIR}\")\n    include_directories(${PYTHON_INCLUDE_DIR})\n\n    if(pybind11_FOUND)\n        message(STATUS \"pybind11_INCLUDES = ${pybind11_INCLUDE_DIRS}\")\n        message(STATUS \"pybind11_LIBRARIES=${pybind11_LIBRARIES}\")\n        message(STATUS \"pybind11_DEFINITIONS=${pybind11_DEFINITIONS}\")\n    endif()\n\n\n    # paddle libpaddle.so\n    # paddle include and link option\n    # -L/workspace/DeepSpeech-2.x/engine/venv/lib/python3.7/site-packages/paddle/libs -L/workspace/DeepSpeech-2.x/speechx/venv/lib/python3.7/site-packages/paddle/fluid -l:libpaddle.so -l:libdnnl.so.2 -l:libiomp5.so\n    set(EXECUTE_COMMAND \"import os\"\n        \"import paddle\"\n        \"include_dir = paddle.sysconfig.get_include()\"\n        \"paddle_dir=os.path.split(include_dir)[0]\"\n        \"libs_dir=os.path.join(paddle_dir, 'libs')\"\n        \"fluid_dir=os.path.join(paddle_dir, 'fluid')\"\n        \"out=' '.join([\\\"-L\\\" + libs_dir, \\\"-L\\\" + fluid_dir])\"\n        \"out += \\\" -l:libpaddle.so -l:libdnnl.so.2 -l:libiomp5.so\\\"; print(out)\"\n    )\n    execute_process(\n        COMMAND python -c \"${EXECUTE_COMMAND}\"\n        OUTPUT_VARIABLE PADDLE_LINK_FLAGS\n        RESULT_VARIABLE SUCESS)\n\n    message(STATUS PADDLE_LINK_FLAGS= ${PADDLE_LINK_FLAGS})\n    string(STRIP ${PADDLE_LINK_FLAGS} PADDLE_LINK_FLAGS)\n\n    # paddle compile option\n    # -I/workspace/DeepSpeech-2.x/engine/venv/lib/python3.7/site-packages/paddle/include\n    set(EXECUTE_COMMAND \"import paddle\"\n        \"include_dir = paddle.sysconfig.get_include()\"\n        \"print(f\\\"-I{include_dir}\\\")\"\n    )\n    execute_process(\n        COMMAND python -c \"${EXECUTE_COMMAND}\"\n        OUTPUT_VARIABLE PADDLE_COMPILE_FLAGS)\n    message(STATUS PADDLE_COMPILE_FLAGS= ${PADDLE_COMPILE_FLAGS})\n    string(STRIP ${PADDLE_COMPILE_FLAGS} PADDLE_COMPILE_FLAGS)\n\n    # for LD_LIBRARY_PATH\n    # set(PADDLE_LIB_DIRS /workspace/DeepSpeech-2.x/tools/venv/lib/python3.7/site-packages/paddle/fluid:/workspace/DeepSpeech-2.x/tools/venv/lib/python3.7/site-packages/paddle/libs/)\n    set(EXECUTE_COMMAND \"import os\"\n        \"import paddle\"\n        \"include_dir=paddle.sysconfig.get_include()\"\n        \"paddle_dir=os.path.split(include_dir)[0]\"\n        \"libs_dir=os.path.join(paddle_dir, 'libs')\"\n        \"fluid_dir=os.path.join(paddle_dir, 'fluid')\"\n        \"out=':'.join([libs_dir, fluid_dir]); print(out)\"\n        )\n    execute_process(\n        COMMAND python -c \"${EXECUTE_COMMAND}\"\n        OUTPUT_VARIABLE PADDLE_LIB_DIRS)\n    message(STATUS PADDLE_LIB_DIRS= ${PADDLE_LIB_DIRS})\nendif()\n\ninclude(summary)\n\n###############################################################################\n# Add local library\n###############################################################################\nset(ENGINE_ROOT ${CMAKE_SOURCE_DIR}/engine)\n\nadd_subdirectory(engine)\n\n\n###############################################################################\n# CPack library\n###############################################################################\n# build a CPack driven installer package\ninclude (InstallRequiredSystemLibraries)\nset(CPACK_PACKAGE_NAME \"paddlespeech_library\")\nset(CPACK_PACKAGE_VENDOR \"paddlespeech\")\nset(CPACK_PACKAGE_VERSION_MAJOR 1)\nset(CPACK_PACKAGE_VERSION_MINOR 0)\nset(CPACK_PACKAGE_VERSION_PATCH 0)\nset(CPACK_PACKAGE_DESCRIPTION \"paddlespeech library\")\nset(CPACK_PACKAGE_CONTACT \"paddlespeech@baidu.com\")\nset(CPACK_SOURCE_GENERATOR \"TGZ\")\ninclude (CPack)\n"
  },
  {
    "path": "runtime/README.md",
    "content": "\n## Environment\n\nWe develop under:\n* python - >=3.8\n* docker - `registry.baidubce.com/paddlepaddle/paddle:2.2.2-gpu-cuda10.2-cudnn7`\n* os - Ubuntu 16.04.7 LTS\n* gcc/g++/gfortran - 8.2.0\n* cmake - 3.16.0\n\n> Please use `tools/env.sh` to create python `venv`, then `source venv/bin/activate` to build engine.\n\n> We make sure all things work fun under docker, and recommend using it to develop and deploy.\n\n* [How to Install Docker](https://docs.docker.com/engine/install/)\n* [A Docker Tutorial for Beginners](https://docker-curriculum.com/)\n* [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/overview.html)\n\n## Build\n\n1. First to launch docker container.\n\n```\ndocker run --privileged  --net=host --ipc=host -it --rm -v /path/to/paddlespeech:/workspace --name=dev registry.baidubce.com/paddlepaddle/paddle:2.2.2-gpu-cuda10.2-cudnn7 /bin/bash\n```\n\n* More `Paddle` docker images you can see [here](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/docker/linux-docker.html).\n\n2. Create python environment.\n\n```\nbash tools/venv.sh\n```\n\n2. Build `engine` and `examples`.\n\nFor now we are using feature under `develop` branch of paddle, so we need to install `paddlepaddle` nightly build version.\nFor example: \n```\nsource venv/bin/activate\npython -m pip install paddlepaddle==2.4.2 -i https://mirror.baidu.com/pypi/simple\n./build.sh\n```\n\n\n3. Go to `examples` to have a fun.\n\nMore details please see `README.md` under `examples`.\n\n\n## Valgrind (Optional)\n\n> If using docker please check `--privileged` is set when `docker run`.\n\n* Fatal error at startup: `a function redirection which is mandatory for this platform-tool combination cannot be set up`\n```bash\napt-get install libc6-dbg\n```\n\n* Install\n\n```bash\npushd tools\n./setup_valgrind.sh\npopd\n```\n\n## TODO\n\n### Deepspeech2 with linear feature\n* DecibelNormalizer: there is a small difference between the offline and online db norm. The computation of online db norm reads features chunk by chunk, which causes the feature size to be different different with offline db norm. In `normalizer.cc:73`, the `samples.size()` is different, which causes the different result.\n\n## FAQ\n\n1. No moudle named `paddle`. \n\n```\nCMake Error at CMakeLists.txt:119 (string):\n  string sub-command STRIP requires two arguments.\n\n\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nModuleNotFoundError: No module named 'paddle'\n-- PADDLE_COMPILE_FLAGS=\nCMake Error at CMakeLists.txt:131 (string):\n  string sub-command STRIP requires two arguments.\n\n\n  File \"<string>\", line 1\n    import os; import paddle; include_dir=paddle.sysconfig.get_include(); paddle_dir=os.path.split(include_dir)[0]; libs_dir=os.path.join(paddle_dir, 'libs'); fluid_dir=os.path.join(paddle_dir, 'fluid'); out=':'.join([libs_dir, fluid_dir]); print(out);     \n    ^\n```\n\nplease install paddlepaddle >= 2.4rc\n\n2. `u2_recognizer_main: error while loading shared libraries: liblibpaddle.so: cannot open shared object file: No such file or directory`\n\n\n```\ncd $YOUR_ENV_PATH/lib/python3.8/site-packages/paddle/fluid\npatchelf --set-soname libpaddle.so libpaddle.so\n```\n\n3. `u2_recognizer_main: error while loading shared libraries: libgfortran.so.5: cannot open shared object file: No such file or directory`\n\n```\n# my gcc version is 8.2\napt-get install gfortran-8\n```\n\n4. `Undefined reference to '_gfortran_concat_string'`\n\nusing gcc 8.2, gfortran 8.2.\n\n5. `./boost/python/detail/wrap_python.hpp:57:11: fatal error: pyconfig.h: No such file or directory`\n\n```\napt-get install python3-dev\n```\n\nfor more info please see [here](https://github.com/okfn/piati/issues/65).\n"
  },
  {
    "path": "runtime/build.sh",
    "content": "#!/usr/bin/env bash\nset -xe\n\nBUILD_ROOT=build/Linux\nBUILD_DIR=${BUILD_ROOT}/x86_64\n\nmkdir -p ${BUILD_DIR}\n\nBUILD_TYPE=Release\n#BUILD_TYPE=Debug\nBUILD_SO=OFF\nBUILD_ONNX=ON\nBUILD_ASR=ON\nBUILD_CLS=ON\nBUILD_VAD=ON\nPPS_DEBUG=OFF\nFASTDEPLOY_INSTALL_DIR=\"\"\n\n# the build script had verified in the paddlepaddle docker image.\n# please follow the instruction below to install PaddlePaddle image.\n# https://www.paddlepaddle.org.cn/documentation/docs/zh/install/docker/linux-docker.html \n#cmake -B build -DBUILD_SHARED_LIBS=OFF -DWITH_ASR=OFF -DWITH_CLS=OFF -DWITH_VAD=ON -DFASTDEPLOY_INSTALL_DIR=/workspace/zhanghui/paddle/FastDeploy/build/Android/arm64-v8a-api-21/install\ncmake -B ${BUILD_DIR} \\\n       \t-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \\\n       \t-DBUILD_SHARED_LIBS=${BUILD_SO} \\\n\t-DWITH_ONNX=${BUILD_ONNX} \\\n\t-DWITH_ASR=${BUILD_ASR} \\\n\t-DWITH_CLS=${BUILD_CLS} \\\n\t-DWITH_VAD=${BUILD_VAD} \\\n\t-DFASTDEPLOY_INSTALL_DIR=${FASTDEPLOY_INSTALL_DIR} \\\n\t-DWITH_PPS_DEBUG=${PPS_DEBUG}\n\ncmake --build ${BUILD_DIR} -j\n"
  },
  {
    "path": "runtime/build_android.sh",
    "content": "#!/bin/bash\n\nset -ex\n\nANDROID_NDK=/mnt/masimeng/workspace/software/android-ndk-r25b/\n\n# Setting up Android toolchanin\nANDROID_ABI=arm64-v8a  # 'arm64-v8a', 'armeabi-v7a'\nANDROID_PLATFORM=\"android-21\"  # API >= 21\nANDROID_STL=c++_shared  # 'c++_shared', 'c++_static'\nANDROID_TOOLCHAIN=clang  # 'clang' only\nTOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake\n\n# Create build directory\nBUILD_ROOT=build/Android\nBUILD_DIR=${BUILD_ROOT}/${ANDROID_ABI}-api-21\nFASTDEPLOY_INSTALL_DIR=\"/mnt/masimeng/workspace/FastDeploy/build/Android/arm64-v8a-api-21/install\"\n\nmkdir -p ${BUILD_DIR}\ncd ${BUILD_DIR}\n\n# CMake configuration with Android toolchain\ncmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \\\n      -DCMAKE_BUILD_TYPE=MinSizeRel \\\n      -DANDROID_ABI=${ANDROID_ABI} \\\n      -DANDROID_NDK=${ANDROID_NDK} \\\n      -DANDROID_PLATFORM=${ANDROID_PLATFORM} \\\n      -DANDROID_STL=${ANDROID_STL} \\\n      -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN} \\\n      -DBUILD_SHARED_LIBS=OFF \\\n      -DWITH_ASR=OFF \\\n      -DWITH_CLS=OFF \\\n      -DWITH_VAD=ON \\\n      -DFASTDEPLOY_INSTALL_DIR=${FASTDEPLOY_INSTALL_DIR} \\\n      -DCMAKE_FIND_DEBUG_MODE=OFF \\\n      -Wno-dev ../../..\n\n# Build FastDeploy Android C++ SDK\nmake\n"
  },
  {
    "path": "runtime/build_ios.sh",
    "content": "# https://www.jianshu.com/p/33672fb819f5\n\nPATH=\"/Applications/CMake.app/Contents/bin\":\"$PATH\"\ntools_dir=$1\nios_toolchain_cmake=${tools_dir}/\"/ios-cmake-4.2.0/ios.toolchain.cmake\"\nfastdeploy_dir=${tools_dir}\"/fastdeploy-ort-mac-build/\"\nbuild_targets=(\"OS64\")\nbuild_type_array=(\"Release\")\n\n#static_name=\"libocr\"\n#lib_name=\"libocr\"\n\n# Switch to workpath\ncurrent_path=`cd $(dirname $0);pwd`\nwork_path=${current_path}/\nbuild_path=${current_path}/build/\noutput_path=${current_path}/output/\ncd ${work_path}\n\n# Clean\nrm -rf ${build_path}\nrm -rf ${output_path}\n\nif [ \"$1\"x = \"clean\"x ]; then\n    exit 0\nfi\n\n# Build Every Target\nfor target in \"${build_targets[@]}\"\ndo\n    for build_type in \"${build_type_array[@]}\"\n    do    \n        echo -e \"\\033[1;36;40mBuilding ${build_type} ${target} ... \\033[0m\"\n        target_build_path=${build_path}/${target}/${build_type}/\n        mkdir -p ${target_build_path}\n\n        cd ${target_build_path}\n        if [ $? -ne 0 ];then\n            echo -e \"\\033[1;31;40mcd ${target_build_path} failed \\033[0m\"\n            exit -1\n        fi\n        \n        if [ ${target} == \"OS64\" ];then\n            fastdeploy_install_dir=${fastdeploy_dir}/arm64\n\t    else\n            fastdeploy_install_dir=\"\"\n            echo \"fastdeploy_install_dir is null\"\n            exit -1\n\t    fi\n\n        cmake -DCMAKE_TOOLCHAIN_FILE=${ios_toolchain_cmake} \\\n            -DBUILD_IN_MACOS=ON \\\n            -DBUILD_SHARED_LIBS=OFF \\\n            -DWITH_ASR=OFF \\\n            -DWITH_CLS=OFF \\\n            -DWITH_VAD=ON \\\n\t        -DFASTDEPLOY_INSTALL_DIR=${fastdeploy_install_dir} \\\n            -DPLATFORM=${target} ../../../\n\n        cmake --build . --config ${build_type}\n\n\t\tmkdir output\n        cp engine/vad/interface/libpps_vad_interface.a output\n        cp engine/vad/interface/vad_interface_main.app/vad_interface_main output\n        cp ${fastdeploy_install_dir}/lib/libfastdeploy.dylib output\n\t    cp ${fastdeploy_install_dir}/third_libs/install/onnxruntime/lib/libonnxruntime.dylib output\t\n\n    done\ndone\n\n## combine all ios libraries\n#DEVROOT=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/\n#LIPO_TOOL=${DEVROOT}/usr/bin/lipo\n#LIBRARY_PATH=${build_path}\n#LIBRARY_OUTPUT_PATH=${output_path}/IOS\n#mkdir -p ${LIBRARY_OUTPUT_PATH}\n#\n#${LIPO_TOOL}    \\\n#    -arch i386 ${LIBRARY_PATH}/ios_x86/Release/${lib_name}.a          \\\n#    -arch x86_64 ${LIBRARY_PATH}/ios_x86_64/Release/${lib_name}.a     \\\n#    -arch armv7 ${LIBRARY_PATH}/ios_armv7/Release/${lib_name}.a       \\\n#    -arch armv7s ${LIBRARY_PATH}/ios_armv7s/Release/${lib_name}.a     \\\n#    -arch arm64 ${LIBRARY_PATH}/ios_armv8/Release/${lib_name}.a       \\\n#    -output ${LIBRARY_OUTPUT_PATH}/${lib_name}.a -create\n#\n#cp ${work_path}/lib/houyi/lib/ios/libhouyi_score.a ${LIBRARY_OUTPUT_PATH}/\n#cp ${work_path}/interface/ocr-interface.h ${output_path}\n#cp ${work_path}/version/release.v ${output_path}\n#\n#echo -e \"\\033[1;36;40mBuild All Target Success At:\\n${output_path}\\033[0m\"\n#exit 0\n"
  },
  {
    "path": "runtime/cmake/EnableCMP0048.cmake",
    "content": "cmake_policy(SET CMP0048 NEW)"
  },
  {
    "path": "runtime/cmake/EnableCMP0077.cmake",
    "content": "cmake_policy(SET CMP0077 NEW)\n"
  },
  {
    "path": "runtime/cmake/FindGFortranLibs.cmake",
    "content": "#.rst:\n# FindGFortranLibs\n# --------\n#  https://github.com/Argonne-National-Laboratory/PIPS/blob/master/cmake/Modules/FindGFortranLibs.cmake\n#  https://enccs.github.io/cmake-workshop/cxx-fortran/\n#\n# Find gcc Fortran compiler & library paths\n#\n# The module defines the following variables:\n#\n# ::\n#\n#\n#   GFORTRANLIBS_FOUND - true if system has gfortran\n#   LIBGFORTRAN_LIBRARIES - path to libgfortran\n#   LIBQUADMATH_LIBRARIES - path to libquadmath\n#   GFORTRAN_LIBARIES_DIR - directory containing libgfortran, libquadmath\n#   GFORTRAN_INCLUDE_DIR - directory containing gfortran/gcc headers\n#   LIBGOMP_LIBRARIES - path to libgomp\n#   LIBGOMP_INCLUDE_DIR - directory containing omp.h header\n#   GFORTRAN_VERSION_STRING - version of gfortran found\n#\nset(CMAKE_REQUIRED_QUIET ${LIBIOMP_FIND_QUIETLY})\n\nif(NOT CMAKE_REQUIRED_QUIET)\n  message(STATUS \"Looking for gfortran related libraries...\")\nendif()\n\nenable_language(Fortran)\nif(CMAKE_Fortran_COMPILER_ID MATCHES \"GNU\")\n\n  # Basically, call \"gfortran -v\" to dump compiler info to the string\n  # GFORTRAN_VERBOSE_STR, which will be used to get necessary paths\n  message(STATUS \"Extracting library and header information by calling 'gfortran -v'...\")\n  execute_process(COMMAND \"${CMAKE_Fortran_COMPILER}\" \"-v\" ERROR_VARIABLE\n    GFORTRAN_VERBOSE_STR RESULT_VARIABLE FLAG)\n\n  # For debugging\n  message(STATUS \"'gfortran -v' returned:\")\n  message(STATUS \"${GFORTRAN_VERBOSE_STR}\")\n\n  # Detect gfortran version\n  string(REGEX MATCH \"gcc version [^\\t\\n ]+\" GFORTRAN_VER_STR \"${GFORTRAN_VERBOSE_STR}\")\n  string(REGEX REPLACE \"gcc version ([^\\t\\n ]+)\" \"\\\\1\" GFORTRAN_VERSION_STRING \"${GFORTRAN_VER_STR}\")\n  message(STATUS \"Detected gfortran version ${GFORTRAN_VERSION_STRING}\")\n  unset(GFORTRAN_VER_STR)\n\n  set(MATCH_REGEX \"[^\\t\\n ]+[\\t\\n ]+\")\n  set(REPLACE_REGEX \"([^\\t\\n ]+)\")\n\n  # Find architecture for compiler\n  string(REGEX MATCH \"Target: [^\\t\\n ]+\"\n    GFORTRAN_ARCH_STR \"${GFORTRAN_VERBOSE_STR}\")\n  message(STATUS \"Architecture string: ${GFORTRAN_ARCH_STR}\")\n  string(REGEX REPLACE \"Target: ([^\\t\\n ]+)\" \"\\\\1\"\n    GFORTRAN_ARCH \"${GFORTRAN_ARCH_STR}\")\n  message(STATUS \"Detected gfortran architecture: ${GFORTRAN_ARCH}\")\n  unset(GFORTRAN_ARCH_STR)\n\n  # Find install prefix, if it exists; if not, use default\n  string(REGEX MATCH  \"--prefix=[^\\t\\n ]+[\\t\\n ]+\"\n    GFORTRAN_PREFIX_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_PREFIX_STR)\n    message(STATUS \"Detected default gfortran prefix\")\n    set(GFORTRAN_PREFIX_DIR \"/usr/local\") # default prefix for gcc install\n  else()\n    string(REGEX REPLACE \"--prefix=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_PREFIX_DIR \"${GFORTRAN_PREFIX_STR}\")\n  endif()\n  message(STATUS \"Detected gfortran prefix: ${GFORTRAN_PREFIX_DIR}\")\n  unset(GFORTRAN_PREFIX_STR)\n\n  # Find install exec-prefix, if it exists; if not, use default\n  string(REGEX MATCH \"--exec-prefix=[^\\t\\n ]+[\\t\\n ]+\" \"\\\\1\"\n    GFORTRAN_EXEC_PREFIX_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_EXEC_PREFIX_STR)\n    message(STATUS \"Detected default gfortran exec-prefix\")\n    set(GFORTRAN_EXEC_PREFIX_DIR \"${GFORTRAN_PREFIX_DIR}\")\n  else()\n    string(REGEX REPLACE \"--exec-prefix=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_EXEC_PREFIX_DIR \"${GFORTRAN_EXEC_PREFIX_STR}\")\n  endif()\n  message(STATUS \"Detected gfortran exec-prefix: ${GFORTRAN_EXEC_PREFIX_DIR}\")\n  UNSET(GFORTRAN_EXEC_PREFIX_STR)\n\n  # Find library directory and include directory, if library directory specified\n  string(REGEX MATCH \"--libdir=[^\\t\\n ]+\"\n    GFORTRAN_LIB_DIR_STR \"${GFORTRAN_VERBOSE_STR}\")\n  if(NOT GFORTRAN_LIB_DIR_STR)\n    message(STATUS \"Found --libdir flag -- not found\")\n    message(STATUS \"Using default gfortran library & include directory paths\")\n    set(GFORTRAN_LIBRARIES_DIR\n      \"${GFORTRAN_EXEC_PREFIX_DIR}/lib/gcc/${GFORTRAN_ARCH}/${GFORTRAN_VERSION_STRING}\")\n    string(CONCAT GFORTRAN_INCLUDE_DIR \"${GFORTRAN_LIBRARIES_DIR}\" \"/include\")\n  else()\n    message(STATUS \"Found --libdir flag -- yes\")\n    string(REGEX REPLACE \"--libdir=([^\\t\\n ]+)\" \"\\\\1\"\n      GFORTRAN_LIBRARIES_DIR \"${GFORTRAN_LIB_DIR_STR}\")\n    string(CONCAT GFORTRAN_INCLUDE_DIR \"${GFORTRAN_LIBRARIES_DIR}\" \"/gcc/\" \"${GFORTRAN_ARCH}\" \"/\" \"${GFORTRAN_VERSION_STRING}\" \"/include\")\n  endif()\n  message(STATUS \"gfortran libraries path: ${GFORTRAN_LIBRARIES_DIR}\")\n  message(STATUS \"gfortran include path dir: ${GFORTRAN_INCLUDE_DIR}\")\n  unset(GFORTRAN_LIB_DIR_STR)\n\n  # There are lots of other build options for gcc & gfortran. For now, the\n  # options implemented above should cover a lot of common use cases.\n\n  # Clean up be deleting the output string from \"gfortran -v\"\n  unset(GFORTRAN_VERBOSE_STR)\n\n  # Find paths for libgfortran, libquadmath, libgomp\n  # libgomp needed for OpenMP support without Clang\n  find_library(LIBGFORTRAN_LIBRARIES NAMES gfortran libgfortran\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n  find_library(LIBQUADMATH_LIBRARIES NAMES quadmath libquadmath\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n  find_library(LIBGOMP_LIBRARIES NAMES gomp libgomp\n    HINTS ${GFORTRAN_LIBRARIES_DIR})\n\n  # Find OpenMP headers\n  find_path(LIBGOMP_INCLUDE_DIR NAMES omp.h HINTS ${GFORTRAN_INCLUDE_DIR})\n\nelse()\n  message(STATUS \"CMAKE_Fortran_COMPILER_ID does not match 'GNU'!\")\nendif()\n\ninclude(FindPackageHandleStandardArgs)\n\n# Required: libgfortran, libquadmath, path for gfortran libraries\n# Optional: libgomp, path for OpenMP headers, path for gcc/gfortran headers\nfind_package_handle_standard_args(GFortranLibs\n  REQUIRED_VARS LIBGFORTRAN_LIBRARIES LIBQUADMATH_LIBRARIES GFORTRAN_LIBRARIES_DIR\n  VERSION_VAR GFORTRAN_VERSION_STRING)\n\nif(GFORTRANLIBS_FOUND)\n  message(STATUS \"Looking for gfortran libraries -- found\")\n  message(STATUS \"gfortran version: ${GFORTRAN_VERSION_STRING}\")\nelse()\n  message(STATUS \"Looking for gfortran libraries -- not found\")\nendif()\n\nmark_as_advanced(LIBGFORTRAN_LIBRARIES LIBQUADMATH_LIBRARIES\n  LIBGOMP_LIBRARIES LIBGOMP_INCLUDE_DIR\n  GFORTRAN_LIBRARIES_DIR GFORTRAN_INCLUDE_DIR)\n# FindGFortranLIBS.cmake ends here"
  },
  {
    "path": "runtime/cmake/absl.cmake",
    "content": "include(FetchContent)\n\n\nset(BUILD_SHARED_LIBS OFF) # up to you\nset(BUILD_TESTING OFF) # to disable abseil test, or gtest will fail.\nset(ABSL_ENABLE_INSTALL ON) # now you can enable install rules even in subproject...\n\nFetchContent_Declare(\n  absl\n  GIT_REPOSITORY \"https://github.com/abseil/abseil-cpp.git\"\n  GIT_TAG \"20210324.1\"\n)\nFetchContent_MakeAvailable(absl)\n\nset(EIGEN3_INCLUDE_DIR ${Eigen3_SOURCE_DIR})\ninclude_directories(${absl_SOURCE_DIR})"
  },
  {
    "path": "runtime/cmake/boost.cmake",
    "content": "include(FetchContent)\nset(Boost_DEBUG ON)\n\nset(Boost_PREFIX_DIR ${fc_patch}/boost)\nset(Boost_SOURCE_DIR ${fc_patch}/boost-src)\n\nFetchContent_Declare(\n  Boost\n  URL      https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz\n  URL_HASH SHA256=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a\n  PREFIX            ${Boost_PREFIX_DIR}\n  SOURCE_DIR        ${Boost_SOURCE_DIR}\n)\n\nexecute_process(COMMAND bootstrap.sh WORKING_DIRECTORY ${Boost_SOURCE_DIR})\nexecute_process(COMMAND b2 WORKING_DIRECTORY ${Boost_SOURCE_DIR})\n\nFetchContent_MakeAvailable(Boost)\n\nmessage(STATUS \"boost src dir: ${Boost_SOURCE_DIR}\")\nmessage(STATUS \"boost inc dir: ${Boost_INCLUDE_DIR}\")\nmessage(STATUS \"boost bin dir: ${Boost_BINARY_DIR}\")\n\nset(BOOST_ROOT ${Boost_SOURCE_DIR})\nmessage(STATUS \"boost root dir: ${BOOST_ROOT}\")\n\ninclude_directories(${Boost_SOURCE_DIR})"
  },
  {
    "path": "runtime/cmake/eigen.cmake",
    "content": "include(FetchContent)\n\n# update eigen to the commit id f612df27 on 03/16/2021\nset(EIGEN_PREFIX_DIR ${fc_patch}/eigen3)\n\nFetchContent_Declare(\n  Eigen3\n  GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git\n  GIT_TAG master\n  PREFIX            ${EIGEN_PREFIX_DIR}\n  GIT_SHALLOW TRUE\n  GIT_PROGRESS TRUE)\n\nset(EIGEN_BUILD_DOC OFF)\n# note: To disable eigen tests,\n# you should put this code in a add_subdirectory to avoid to change\n# BUILD_TESTING for your own project too since variables are directory\n# scoped\nset(BUILD_TESTING OFF)\nset(EIGEN_BUILD_PKGCONFIG OFF)\nset( OFF)\nFetchContent_MakeAvailable(Eigen3)\n\nmessage(STATUS \"eigen src dir: ${Eigen3_SOURCE_DIR}\")\nmessage(STATUS \"eigen bin dir: ${Eigen3_BINARY_DIR}\")\n#include_directories(${Eigen3_SOURCE_DIR})\n#link_directories(${Eigen3_BINARY_DIR})"
  },
  {
    "path": "runtime/cmake/fastdeploy.cmake",
    "content": "include(FetchContent)\n\nset(EXTERNAL_PROJECT_LOG_ARGS\n    LOG_DOWNLOAD 1 # Wrap download in script to log output\n    LOG_UPDATE 1 # Wrap update in script to log output\n    LOG_PATCH 1\n    LOG_CONFIGURE 1# Wrap configure in script to log output\n    LOG_BUILD 1 # Wrap build in script to log output\n    LOG_INSTALL 1\n    LOG_TEST 1 # Wrap test in script to log output\n    LOG_MERGED_STDOUTERR 1\n    LOG_OUTPUT_ON_FAILURE 1\n)\n\nif(NOT FASTDEPLOY_INSTALL_DIR)\n    if(ANDROID)\n        FetchContent_Declare(\n            fastdeploy\n            URL      https://bj.bcebos.com/fastdeploy/release/android/fastdeploy-android-1.0.4-shared.tgz\n            URL_HASH MD5=2a15301158e9eb157a4f11283689e7ba\n            ${EXTERNAL_PROJECT_LOG_ARGS}\n        )\n        add_definitions(\"-DUSE_PADDLE_LITE_BAKEND\")\n        set(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -g -mfloat-abi=softfp -mfpu=vfpv3 -mfpu=neon -fPIC -pie -fPIE\")\n        set(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -g0 -O3 -mfloat-abi=softfp -mfpu=vfpv3 -mfpu=neon -fPIC -pie -fPIE\")\n    else() # Linux\n        FetchContent_Declare(\n            fastdeploy\n            URL      https://paddlespeech.cdn.bcebos.com/speechx/fastdeploy/fastdeploy-1.0.5-x86_64-onnx.tar.gz \n            URL_HASH MD5=33900d986ea71aa78635e52f0733227c\n            ${EXTERNAL_PROJECT_LOG_ARGS}\n        )\n        set(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -msse -msse2\")\n        set(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -msse -msse2 -mavx -O3\")\n    endif()\n\n    FetchContent_MakeAvailable(fastdeploy)\n\n    set(FASTDEPLOY_INSTALL_DIR ${fc_patch}/fastdeploy-src)\nendif()\n\ninclude(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake)\n\n# fix compiler flags conflict, since fastdeploy using c++11 for project\n# this line must after `include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake)`\nset(CMAKE_CXX_STANDARD ${PPS_CXX_STANDARD})\n\ninclude_directories(${FASTDEPLOY_INCS})\n\n# install fastdeploy and dependents lib\n# install_fastdeploy_libraries(${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})\n# No dynamic libs need to install while using\n# FastDeploy static lib.\nif(ANDROID AND WITH_ANDROID_STATIC_LIB)\n    return()\nendif()\n\nset(DYN_LIB_SUFFIX \"*.so*\")\nif(WIN32)\n    set(DYN_LIB_SUFFIX \"*.dll\")\nelseif(APPLE)\n    set(DYN_LIB_SUFFIX \"*.dylib*\")\nendif()\n\nif(FastDeploy_DIR)\n    set(DYN_SEARCH_DIR ${FastDeploy_DIR})\nelseif(FASTDEPLOY_INSTALL_DIR)\n    set(DYN_SEARCH_DIR ${FASTDEPLOY_INSTALL_DIR})\nelse()\n    message(FATAL_ERROR \"Please set FastDeploy_DIR/FASTDEPLOY_INSTALL_DIR before call install_fastdeploy_libraries.\")\nendif()\n\nfile(GLOB_RECURSE ALL_NEED_DYN_LIBS ${DYN_SEARCH_DIR}/lib/${DYN_LIB_SUFFIX})\nfile(GLOB_RECURSE ALL_DEPS_DYN_LIBS ${DYN_SEARCH_DIR}/third_libs/${DYN_LIB_SUFFIX})\n\nif(ENABLE_VISION)\n    # OpenCV\n    if(ANDROID)\n        file(GLOB_RECURSE ALL_OPENCV_DYN_LIBS ${OpenCV_NATIVE_DIR}/libs/${DYN_LIB_SUFFIX})\n    else()\n        file(GLOB_RECURSE ALL_OPENCV_DYN_LIBS ${OpenCV_DIR}/../../${DYN_LIB_SUFFIX})\n    endif()\n   \n    list(REMOVE_ITEM ALL_DEPS_DYN_LIBS ${ALL_OPENCV_DYN_LIBS})\n\n    if(WIN32)\n        file(GLOB OPENCV_DYN_LIBS ${OpenCV_DIR}/x64/vc15/bin/${DYN_LIB_SUFFIX})\n        install(FILES ${OPENCV_DYN_LIBS} DESTINATION lib)\n    elseif(ANDROID AND (NOT WITH_ANDROID_OPENCV_STATIC))\n        file(GLOB OPENCV_DYN_LIBS ${OpenCV_NATIVE_DIR}/libs/${ANDROID_ABI}/${DYN_LIB_SUFFIX})\n        install(FILES ${OPENCV_DYN_LIBS} DESTINATION lib)\n    else() # linux/mac\n        file(GLOB OPENCV_DYN_LIBS ${OpenCV_DIR}/lib/${DYN_LIB_SUFFIX})\n        install(FILES ${OPENCV_DYN_LIBS} DESTINATION lib)\n    endif()\n\n    # FlyCV\n    if(ENABLE_FLYCV)\n        file(GLOB_RECURSE ALL_FLYCV_DYN_LIBS ${FLYCV_LIB_DIR}/${DYN_LIB_SUFFIX})\n        list(REMOVE_ITEM ALL_DEPS_DYN_LIBS ${ALL_FLYCV_DYN_LIBS})\n        if(ANDROID AND (NOT WITH_ANDROID_FLYCV_STATIC))\n        install(FILES ${ALL_FLYCV_DYN_LIBS} DESTINATION lib)\n        endif()\n    endif()\nendif()\n\nif(ENABLE_OPENVINO_BACKEND)\n    # need plugins.xml for openvino backend\n    set(OPENVINO_RUNTIME_BIN_DIR ${OPENVINO_DIR}/bin)\n    file(GLOB OPENVINO_PLUGIN_XML ${OPENVINO_RUNTIME_BIN_DIR}/*.xml)\n    install(FILES ${OPENVINO_PLUGIN_XML} DESTINATION lib)\nendif()\n\n# Install other libraries\ninstall(FILES ${ALL_NEED_DYN_LIBS} DESTINATION lib)\ninstall(FILES ${ALL_DEPS_DYN_LIBS} DESTINATION lib)\n"
  },
  {
    "path": "runtime/cmake/gflags.cmake",
    "content": "include(FetchContent)\n\nFetchContent_Declare(\n  gflags\n  URL      https://paddleaudio.bj.bcebos.com/build/gflag-2.2.2.zip \n  URL_HASH SHA256=19713a36c9f32b33df59d1c79b4958434cb005b5b47dc5400a7a4b078111d9b5\n)\nFetchContent_MakeAvailable(gflags)\n\n# openfst need\ninclude_directories(${gflags_BINARY_DIR}/include)\nlink_directories(${gflags_BINARY_DIR})\n\n#install(FILES ${gflags_BINARY_DIR}/libgflags_nothreads.a DESTINATION lib)\n"
  },
  {
    "path": "runtime/cmake/glog.cmake",
    "content": "include(FetchContent)\n\nif(ANDROID)\nelse() # UNIX\n  add_definitions(-DWITH_GLOG)\n  FetchContent_Declare(\n    glog\n    URL      https://paddleaudio.bj.bcebos.com/build/glog-0.4.0.zip\n    URL_HASH SHA256=9e1b54eb2782f53cd8af107ecf08d2ab64b8d0dc2b7f5594472f3bd63ca85cdc\n    CMAKE_ARGS      -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\n                    -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\n                    -DCMAKE_CXX_FLAGS=${GLOG_CMAKE_CXX_FLAGS}\n                    -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE}\n                    -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG}\n                    -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}\n                    -DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}\n                    -DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}\n                    -DCMAKE_POSITION_INDEPENDENT_CODE=ON\n                    -DWITH_GFLAGS=OFF\n                    -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n                    ${EXTERNAL_OPTIONAL_ARGS}\n  )\n  set(BUILD_TESTING OFF)\n  FetchContent_MakeAvailable(glog)\n  include_directories(${glog_BINARY_DIR} ${glog_SOURCE_DIR}/src)\nendif()\n\n\nif(ANDROID)\n  add_library(extern_glog INTERFACE)\n  add_dependencies(extern_glog gflags)\nelse() # UNIX\n  add_library(extern_glog ALIAS glog)\n  add_dependencies(glog gflags)\nendif()"
  },
  {
    "path": "runtime/cmake/gtest.cmake",
    "content": "\ninclude(FetchContent)\n\nif(ANDROID)\nelse() # UNIX\n  FetchContent_Declare(\n    gtest\n    URL      https://paddleaudio.bj.bcebos.com/build/gtest-release-1.11.0.zip\n    URL_HASH SHA256=353571c2440176ded91c2de6d6cd88ddd41401d14692ec1f99e35d013feda55a\n  )\n  FetchContent_MakeAvailable(gtest)\n\n  include_directories(${gtest_BINARY_DIR} ${gtest_SOURCE_DIR}/src)\nendif()\n\n\n\nif(ANDROID)\n  add_library(extern_gtest INTERFACE)\nelse() # UNIX\n  add_dependencies(gtest gflags extern_glog)\n  add_library(extern_gtest ALIAS gtest)\nendif()\n\nif(WITH_TESTING)\n  enable_testing()\nendif()\n"
  },
  {
    "path": "runtime/cmake/kenlm.cmake",
    "content": "include(FetchContent)\nFetchContent_Declare(\n  kenlm\n  GIT_REPOSITORY \"https://github.com/kpu/kenlm.git\"\n  GIT_TAG \"df2d717e95183f79a90b2fa6e4307083a351ca6a\"\n)\n# https://github.com/kpu/kenlm/blob/master/cmake/modules/FindEigen3.cmake\nset(EIGEN3_INCLUDE_DIR ${Eigen3_SOURCE_DIR})\nFetchContent_MakeAvailable(kenlm)\ninclude_directories(${kenlm_SOURCE_DIR})"
  },
  {
    "path": "runtime/cmake/libsndfile.cmake",
    "content": "include(FetchContent)\n\n# https://github.com/pongasoft/vst-sam-spl-64/blob/master/libsndfile.cmake\n# https://github.com/popojan/goban/blob/master/CMakeLists.txt#L38\n# https://github.com/ddiakopoulos/libnyquist/blob/master/CMakeLists.txt\n\nif(LIBSNDFILE_ROOT_DIR)\n  # instructs FetchContent to not download or update but use the location instead\n  set(FETCHCONTENT_SOURCE_DIR_LIBSNDFILE ${LIBSNDFILE_ROOT_DIR})\nelse()\n  set(FETCHCONTENT_SOURCE_DIR_LIBSNDFILE \"\")\nendif()\n\nset(LIBSNDFILE_GIT_REPO \"https://github.com/libsndfile/libsndfile.git\" CACHE STRING \"libsndfile git repository url\" FORCE)\nset(LIBSNDFILE_GIT_TAG 1.0.31 CACHE STRING \"libsndfile git tag\" FORCE)\n\nFetchContent_Declare(libsndfile\n      GIT_REPOSITORY    ${LIBSNDFILE_GIT_REPO}\n      GIT_TAG           ${LIBSNDFILE_GIT_TAG}\n      GIT_CONFIG        advice.detachedHead=false\n#      GIT_SHALLOW       true\n      CONFIGURE_COMMAND \"\"\n      BUILD_COMMAND     \"\"\n      INSTALL_COMMAND   \"\"\n      TEST_COMMAND      \"\"\n      )\n\nFetchContent_GetProperties(libsndfile)\nif(NOT libsndfile_POPULATED)\n  if(FETCHCONTENT_SOURCE_DIR_LIBSNDFILE)\n    message(STATUS \"Using libsndfile from local ${FETCHCONTENT_SOURCE_DIR_LIBSNDFILE}\")\n  else()\n    message(STATUS \"Fetching libsndfile ${LIBSNDFILE_GIT_REPO}/tree/${LIBSNDFILE_GIT_TAG}\")\n  endif()\n  FetchContent_Populate(libsndfile)\nendif()\n\nset(LIBSNDFILE_ROOT_DIR ${libsndfile_SOURCE_DIR})\nset(LIBSNDFILE_INCLUDE_DIR \"${libsndfile_BINARY_DIR}/src\")\n\nfunction(libsndfile_build)\n  option(BUILD_PROGRAMS \"Build programs\" OFF)\n  option(BUILD_EXAMPLES \"Build examples\" OFF)\n  option(BUILD_TESTING \"Build examples\" OFF)\n  option(ENABLE_CPACK \"Enable CPack support\" OFF)\n  option(ENABLE_PACKAGE_CONFIG \"Generate and install package config file\" OFF)\n  option(BUILD_REGTEST \"Build regtest\" OFF)\n  # finally we include libsndfile itself\n  add_subdirectory(${libsndfile_SOURCE_DIR} ${libsndfile_BINARY_DIR} EXCLUDE_FROM_ALL)\n  # copying .hh for c++ support\n  #file(COPY \"${libsndfile_SOURCE_DIR}/src/sndfile.hh\" DESTINATION ${LIBSNDFILE_INCLUDE_DIR})\nendfunction()\n\nlibsndfile_build()\n\ninclude_directories(${LIBSNDFILE_INCLUDE_DIR})"
  },
  {
    "path": "runtime/cmake/openblas.cmake",
    "content": "include(FetchContent)\n\nset(OpenBLAS_SOURCE_DIR ${fc_patch}/openblas-src)\nset(OpenBLAS_PREFIX ${fc_patch}/openblas-prefix)\n\n# ######################################################################################################################\n# OPENBLAS  https://github.com/lattice/quda/blob/develop/CMakeLists.txt#L575\n# ######################################################################################################################\nenable_language(Fortran)\n\ninclude(FortranCInterface)\n\n# # Clang doesn't have a Fortran compiler in its suite (yet),\n# # so detect libraries for gfortran; we need equivalents to\n# # libgfortran and libquadmath, which are implicitly\n# # linked by flags in CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES\n# include(FindGFortranLibs REQUIRED)\n# # Add directory containing libgfortran and libquadmath to\n# # linker. Should also contain libgomp, if not using\n# # Intel OpenMP runtime\n# link_directories(${GFORTRAN_LIBRARIES_DIR})\n# # gfortan dir in the docker.\n# link_directories(/usr/local/gcc-8.2/lib64)\n# # if you are working with C and Fortran\n# FortranCInterface_VERIFY()\n\n# # if you are working with C++ and Fortran\n# FortranCInterface_VERIFY(CXX)\n\n\n#TODO: switch to CPM\ninclude(GNUInstallDirs)\nExternalProject_Add(\n    OPENBLAS\n    GIT_REPOSITORY https://github.com/xianyi/OpenBLAS.git\n    GIT_TAG v0.3.10\n    GIT_SHALLOW YES\n    PREFIX ${OpenBLAS_PREFIX}\n    SOURCE_DIR  ${OpenBLAS_SOURCE_DIR}\n    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> \n    CMAKE_GENERATOR \"Unix Makefiles\")\n\n\n# https://cmake.org/cmake/help/latest/module/ExternalProject.html?highlight=externalproject_get_property#external-project-definition\nExternalProject_Get_Property(OPENBLAS INSTALL_DIR)\nmessage(STATUS \"OPENBLAS install dir: ${INSTALL_DIR}\")\nset(OpenBLAS_INSTALL_PREFIX ${INSTALL_DIR})\nadd_library(openblas STATIC IMPORTED)\nadd_dependencies(openblas OPENBLAS)\nset_target_properties(openblas PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES Fortran)\n# ${CMAKE_INSTALL_LIBDIR}  lib\nset_target_properties(openblas PROPERTIES IMPORTED_LOCATION ${OpenBLAS_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libopenblas.a)\n\n\n# https://cmake.org/cmake/help/latest/command/install.html?highlight=cmake_install_libdir#installing-targets\n# ${CMAKE_INSTALL_LIBDIR}  lib\n# ${CMAKE_INSTALL_INCLUDEDIR}  include\nlink_directories(${OpenBLAS_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})\n# include_directories(${OpenBLAS_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})\n# fix for can not find `cblas.h`\ninclude_directories(${OpenBLAS_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/openblas)"
  },
  {
    "path": "runtime/cmake/openfst.cmake",
    "content": "set(openfst_PREFIX_DIR ${fc_patch}/openfst)\nset(openfst_SOURCE_DIR ${fc_patch}/openfst-src)\nset(openfst_BINARY_DIR ${fc_patch}/openfst-build)\n\ninclude(FetchContent)\n# openfst Acknowledgments:\n#Cyril Allauzen, Michael Riley, Johan Schalkwyk, Wojciech Skut and Mehryar Mohri, \n#\"OpenFst: A General and Efficient Weighted Finite-State Transducer Library\", \n#Proceedings of the Ninth International Conference on Implementation and \n#Application of Automata, (CIAA 2007), volume 4783 of Lecture Notes in \n#Computer Science, pages 11-23. Springer, 2007. http://www.openfst.org.\n\nset(EXTERNAL_PROJECT_LOG_ARGS\n    LOG_DOWNLOAD 1 # Wrap download in script to log output\n    LOG_UPDATE 1 # Wrap update in script to log output\n    LOG_CONFIGURE 1# Wrap configure in script to log output\n    LOG_BUILD 1 # Wrap build in script to log output\n    LOG_TEST 1 # Wrap test in script to log output\n    LOG_INSTALL 1 # Wrap install in script to log output\n)\n\nExternalProject_Add(openfst\n  URL               https://paddleaudio.bj.bcebos.com/build/openfst_1.7.2.zip\n  URL_HASH          SHA256=ffc56931025579a8af3515741c0f3b0fc3a854c023421472c07ca0c6389c75e6\n  ${EXTERNAL_PROJECT_LOG_ARGS}\n  PREFIX            ${openfst_PREFIX_DIR} \n  SOURCE_DIR        ${openfst_SOURCE_DIR}\n  BINARY_DIR        ${openfst_BINARY_DIR}\n  BUILD_ALWAYS      0\n  CONFIGURE_COMMAND ${openfst_SOURCE_DIR}/configure --prefix=${openfst_PREFIX_DIR}\n                      \"CPPFLAGS=-I${gflags_BINARY_DIR}/include -I${glog_SOURCE_DIR}/src -I${glog_BINARY_DIR}\"\n                      \"LDFLAGS=-L${gflags_BINARY_DIR} -L${glog_BINARY_DIR}\"\n                      \"LIBS=-lgflags_nothreads -lglog -lpthread -fPIC\"\n  COMMAND           ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/patch/openfst ${openfst_SOURCE_DIR}\n  BUILD_COMMAND     make -j 4\n)\nlink_directories(${openfst_PREFIX_DIR}/lib)\ninclude_directories(${openfst_PREFIX_DIR}/include)\n\n\nmessage(STATUS \"OpenFST inc dir: ${openfst_PREFIX_DIR}/include\")\nmessage(STATUS \"OpenFST lib dir: ${openfst_PREFIX_DIR}/lib\")\n"
  },
  {
    "path": "runtime/cmake/paddleinference.cmake",
    "content": "set(paddle_SOURCE_DIR ${fc_patch}/paddle-lib)\nset(paddle_PREFIX_DIR ${fc_patch}/paddle-lib-prefix)\n\ninclude(FetchContent)\nFetchContent_Declare(\n  paddle\n  URL      https://paddle-inference-lib.bj.bcebos.com/2.2.2/cxx_c/Linux/CPU/gcc8.2_avx_mkl/paddle_inference.tgz\n  URL_HASH SHA256=7c6399e778c6554a929b5a39ba2175e702e115145e8fa690d2af974101d98873\n  PREFIX            ${paddle_PREFIX_DIR} \n  SOURCE_DIR        ${paddle_SOURCE_DIR}\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n)\nFetchContent_MakeAvailable(paddle)\n\nset(PADDLE_LIB_THIRD_PARTY_PATH \"${paddle_SOURCE_DIR}/third_party/install/\")\n\ninclude_directories(\"${paddle_SOURCE_DIR}/paddle/include\")\ninclude_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}protobuf/include\")\ninclude_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}xxhash/include\")\ninclude_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}cryptopp/include\")\n\nlink_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}protobuf/lib\")\nlink_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}xxhash/lib\")\nlink_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}cryptopp/lib\")\nlink_directories(\"${paddle_SOURCE_DIR}/paddle/lib\")\nlink_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}mklml/lib\")\nlink_directories(\"${PADDLE_LIB_THIRD_PARTY_PATH}mkldnn/lib\")\n\n##paddle with mkl\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fopenmp\")\nset(MATH_LIB_PATH \"${PADDLE_LIB_THIRD_PARTY_PATH}mklml\")\ninclude_directories(\"${MATH_LIB_PATH}/include\")\nset(MATH_LIB ${MATH_LIB_PATH}/lib/libmklml_intel${CMAKE_SHARED_LIBRARY_SUFFIX}\n                 ${MATH_LIB_PATH}/lib/libiomp5${CMAKE_SHARED_LIBRARY_SUFFIX})\n\nset(MKLDNN_PATH \"${PADDLE_LIB_THIRD_PARTY_PATH}mkldnn\")\ninclude_directories(\"${MKLDNN_PATH}/include\")\nset(MKLDNN_LIB ${MKLDNN_PATH}/lib/libmkldnn.so.0)\nset(EXTERNAL_LIB \"-lrt -ldl -lpthread\")\n\n# global vars\nset(DEPS ${paddle_SOURCE_DIR}/paddle/lib/libpaddle_inference${CMAKE_SHARED_LIBRARY_SUFFIX} CACHE INTERNAL \"deps\")\nset(DEPS ${DEPS}\n      ${MATH_LIB} ${MKLDNN_LIB}\n      glog gflags protobuf xxhash cryptopp\n      ${EXTERNAL_LIB} CACHE INTERNAL \"deps\")\nmessage(STATUS \"Deps libraries: ${DEPS}\")\n"
  },
  {
    "path": "runtime/cmake/pybind.cmake",
    "content": "#the pybind11 is from:https://github.com/pybind/pybind11\n# Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.\n\nSET(PYBIND_ZIP \"v2.10.0.zip\")\nSET(LOCAL_PYBIND_ZIP ${FETCHCONTENT_BASE_DIR}/${PYBIND_ZIP})\nSET(PYBIND_SRC ${FETCHCONTENT_BASE_DIR}/pybind11)\nSET(DOWNLOAD_URL \"https://paddleaudio.bj.bcebos.com/build/v2.10.0.zip\")\nSET(PYBIND_TIMEOUT 600 CACHE STRING \"Timeout in seconds when downloading pybind.\")\n\nIF(NOT EXISTS ${LOCAL_PYBIND_ZIP})\n    FILE(DOWNLOAD ${DOWNLOAD_URL}\n      ${LOCAL_PYBIND_ZIP}\n      TIMEOUT ${PYBIND_TIMEOUT}\n      STATUS ERR\n      SHOW_PROGRESS\n    )\n\n    IF(ERR EQUAL 0)\n        MESSAGE(STATUS \"download pybind success\")\n    ELSE()\n        MESSAGE(FATAL_ERROR \"download pybind fail\")\n    ENDIF()\nENDIF()\n\nIF(NOT EXISTS ${PYBIND_SRC})\n    EXECUTE_PROCESS(\n      COMMAND ${CMAKE_COMMAND} -E tar xfz ${LOCAL_PYBIND_ZIP}\n       WORKING_DIRECTORY ${FETCHCONTENT_BASE_DIR}\n       RESULT_VARIABLE tar_result\n    )\n\n    file(RENAME ${FETCHCONTENT_BASE_DIR}/pybind11-2.10.0 ${PYBIND_SRC})\n\n  IF (tar_result MATCHES 0)\n      MESSAGE(STATUS \"unzip pybind success\")\n  ELSE()\n      MESSAGE(FATAL_ERROR \"unzip pybind fail\")\n  ENDIF()\n\nENDIF()\n\ninclude_directories(${PYBIND_SRC}/include)\n"
  },
  {
    "path": "runtime/cmake/summary.cmake",
    "content": "# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfunction(pps_summary)\n  message(STATUS \"\")\n  message(STATUS \"*************PaddleSpeech Building Summary**********\")\n  message(STATUS \"  PPS_VERSION               : ${PPS_VERSION}\")\n  message(STATUS \"  CMake version             : ${CMAKE_VERSION}\")\n  message(STATUS \"  CMake command             : ${CMAKE_COMMAND}\")\n  message(STATUS \"  UNIX                      : ${UNIX}\")\n  message(STATUS \"  ANDROID                   : ${ANDROID}\")\n  message(STATUS \"  System                    : ${CMAKE_SYSTEM_NAME}\")\n  message(STATUS \"  C++ compiler              : ${CMAKE_CXX_COMPILER}\")\n  message(STATUS \"  C++ compiler version      : ${CMAKE_CXX_COMPILER_VERSION}\")\n  message(STATUS \"  CXX flags                 : ${CMAKE_CXX_FLAGS}\")\n  message(STATUS \"  Build type                : ${CMAKE_BUILD_TYPE}\")\n  message(STATUS \"  BUILD_SHARED_LIBS         : ${BUILD_SHARED_LIBS}\")\n  get_directory_property(tmp DIRECTORY ${PROJECT_SOURCE_DIR} COMPILE_DEFINITIONS)\n  message(STATUS \"  Compile definitions       : ${tmp}\")\n  message(STATUS \"  CMAKE_PREFIX_PATH         : ${CMAKE_PREFIX_PATH}\")\n  message(STATUS \"  CMAKE_CURRENT_BINARY_DIR  : ${CMAKE_CURRENT_BINARY_DIR}\")\n  message(STATUS \"  CMAKE_INSTALL_PREFIX      : ${CMAKE_INSTALL_PREFIX}\")\n  message(STATUS \"  CMAKE_INSTALL_LIBDIR      : ${CMAKE_INSTALL_LIBDIR}\")\n  message(STATUS \"  CMAKE_MODULE_PATH         : ${CMAKE_MODULE_PATH}\")\n  message(STATUS \"  CMAKE_SYSTEM_NAME         : ${CMAKE_SYSTEM_NAME}\")\n  message(STATUS \"\")\n\n  message(STATUS \"  WITH_ASR                  : ${WITH_ASR}\")\n  message(STATUS \"  WITH_CLS                  : ${WITH_CLS}\")\n  message(STATUS \"  WITH_VAD                  : ${WITH_VAD}\")\n  message(STATUS \"  WITH_GPU                  : ${WITH_GPU}\")\n  message(STATUS \"  WITH_TESTING              : ${WITH_TESTING}\")\n  message(STATUS \"  WITH_PROFILING            : ${WITH_PROFILING}\")\n  message(STATUS \"  FASTDEPLOY_INSTALL_DIR    : ${FASTDEPLOY_INSTALL_DIR}\")\n  message(STATUS \"  FASTDEPLOY_INCS           : ${FASTDEPLOY_INCS}\")\n  message(STATUS \"  FASTDEPLOY_LIBS           : ${FASTDEPLOY_LIBS}\")\n  if(WITH_GPU)\n    message(STATUS \"  CUDA_DIRECTORY            : ${CUDA_DIRECTORY}\")\n  endif()\n\n  if(ANDROID)\n    message(STATUS \"  ANDROID_ABI               : ${ANDROID_ABI}\")\n    message(STATUS \"  ANDROID_PLATFORM          : ${ANDROID_PLATFORM}\")\n    message(STATUS \"  ANDROID_NDK               : ${ANDROID_NDK}\")\n    message(STATUS \"  ANDROID_NDK_VERSION       : ${CMAKE_ANDROID_NDK_VERSION}\")\n  endif() \n  if (WITH_ASR)\n    message(STATUS \"  Python executable         : ${PYTHON_EXECUTABLE}\")\n    message(STATUS \"  Python includes           : ${PYTHON_INCLUDE_DIR}\")\n  endif()\nendfunction()\n\npps_summary()"
  },
  {
    "path": "runtime/cmake/system.cmake",
    "content": "# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# Detects the OS and sets appropriate variables.\n# CMAKE_SYSTEM_NAME only give us a coarse-grained name of the OS CMake is\n# building for, but the host processor name like centos is necessary\n# in some scenes to distinguish system for customization.\n#\n# for instance, protobuf libs path is <install_dir>/lib64\n# on CentOS, but <install_dir>/lib on other systems.\n\nif(UNIX AND NOT APPLE)\n  # except apple from nix*Os family\n  set(LINUX TRUE)\nendif()\n\nif(WIN32)\n  set(HOST_SYSTEM \"win32\")\nelse()\n  if(APPLE)\n    set(HOST_SYSTEM \"macosx\")\n    exec_program(\n      sw_vers ARGS\n      -productVersion\n      OUTPUT_VARIABLE HOST_SYSTEM_VERSION)\n    string(REGEX MATCH \"[0-9]+.[0-9]+\" MACOS_VERSION \"${HOST_SYSTEM_VERSION}\")\n    if(NOT DEFINED $ENV{MACOSX_DEPLOYMENT_TARGET})\n      # Set cache variable - end user may change this during ccmake or cmake-gui configure.\n      set(CMAKE_OSX_DEPLOYMENT_TARGET\n          ${MACOS_VERSION}\n          CACHE\n            STRING\n            \"Minimum OS X version to target for deployment (at runtime); newer APIs weak linked. Set to empty string for default value.\"\n      )\n    endif()\n    set(CMAKE_EXE_LINKER_FLAGS \"-framework CoreFoundation -framework Security\")\n  else()\n\n    if(EXISTS \"/etc/issue\")\n      file(READ \"/etc/issue\" LINUX_ISSUE)\n      if(LINUX_ISSUE MATCHES \"CentOS\")\n        set(HOST_SYSTEM \"centos\")\n      elseif(LINUX_ISSUE MATCHES \"Debian\")\n        set(HOST_SYSTEM \"debian\")\n      elseif(LINUX_ISSUE MATCHES \"Ubuntu\")\n        set(HOST_SYSTEM \"ubuntu\")\n      elseif(LINUX_ISSUE MATCHES \"Red Hat\")\n        set(HOST_SYSTEM \"redhat\")\n      elseif(LINUX_ISSUE MATCHES \"Fedora\")\n        set(HOST_SYSTEM \"fedora\")\n      endif()\n\n      string(REGEX MATCH \"(([0-9]+)\\\\.)+([0-9]+)\" HOST_SYSTEM_VERSION\n                   \"${LINUX_ISSUE}\")\n    endif()\n\n    if(EXISTS \"/etc/redhat-release\")\n      file(READ \"/etc/redhat-release\" LINUX_ISSUE)\n      if(LINUX_ISSUE MATCHES \"CentOS\")\n        set(HOST_SYSTEM \"centos\")\n      endif()\n    endif()\n\n    if(NOT HOST_SYSTEM)\n      set(HOST_SYSTEM ${CMAKE_SYSTEM_NAME})\n    endif()\n\n  endif()\nendif()\n\n# query number of logical cores\ncmake_host_system_information(RESULT CPU_CORES QUERY NUMBER_OF_LOGICAL_CORES)\n\nmark_as_advanced(HOST_SYSTEM CPU_CORES)\n\nmessage(\n  STATUS\n    \"Found Paddle host system: ${HOST_SYSTEM}, version: ${HOST_SYSTEM_VERSION}\")\nmessage(STATUS \"Found Paddle host system's CPU: ${CPU_CORES} cores\")\n\n# external dependencies log output\nset(EXTERNAL_PROJECT_LOG_ARGS\n    LOG_DOWNLOAD\n    0 # Wrap download in script to log output\n    LOG_UPDATE\n    1 # Wrap update in script to log output\n    LOG_CONFIGURE\n    1 # Wrap configure in script to log output\n    LOG_BUILD\n    0 # Wrap build in script to log output\n    LOG_TEST\n    1 # Wrap test in script to log output\n    LOG_INSTALL\n    0 # Wrap install in script to log output\n)"
  },
  {
    "path": "runtime/docker/.gitkeep",
    "content": ""
  },
  {
    "path": "runtime/engine/CMakeLists.txt",
    "content": "project(speechx LANGUAGES CXX)\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR}/kaldi)\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR}/common)\n\nadd_subdirectory(kaldi)\nadd_subdirectory(common)\n\nif(WITH_ASR)\n    add_subdirectory(asr)\nendif()\n\nif(WITH_CLS)\n    add_subdirectory(audio_classification)\nendif()\n\nif(WITH_VAD)\n    add_subdirectory(vad)\nendif()\n\nadd_subdirectory(codelab)\n"
  },
  {
    "path": "runtime/engine/asr/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14 FATAL_ERROR)\n\nproject(ASR LANGUAGES CXX)\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR}/server)\n\nadd_subdirectory(decoder)\nadd_subdirectory(recognizer)\nadd_subdirectory(nnet)\nadd_subdirectory(server)\n"
  },
  {
    "path": "runtime/engine/asr/decoder/CMakeLists.txt",
    "content": "set(srcs)\nlist(APPEND srcs\n  ctc_prefix_beam_search_decoder.cc\n  ctc_tlg_decoder.cc\n)\n\nadd_library(decoder STATIC ${srcs})\ntarget_link_libraries(decoder PUBLIC utils fst frontend nnet kaldi-decoder)\n\n# test\nset(TEST_BINS \n  ctc_prefix_beam_search_decoder_main\n  ctc_tlg_decoder_main\n)\n\nforeach(bin_name IN LISTS TEST_BINS)\n  add_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\n  target_include_directories(${bin_name} PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\n  target_link_libraries(${bin_name} nnet decoder fst utils  gflags glog kaldi-base kaldi-matrix kaldi-util)\n  target_compile_options(${bin_name}  PRIVATE ${PADDLE_COMPILE_FLAGS})\n  target_include_directories(${bin_name}  PRIVATE ${pybind11_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})\n  target_link_libraries(${bin_name}  ${PYTHON_LIBRARIES} ${PADDLE_LINK_FLAGS} -ldl)\nendforeach()\n\n"
  },
  {
    "path": "runtime/engine/asr/decoder/common.h",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n\nstruct DecoderResult {\n    BaseFloat acoustic_score;\n    std::vector<int32> words_idx;\n    std::vector<std::pair<int32, int32>> time_stamp;\n};\n\n\nnamespace ppspeech {\n\nstruct WordPiece {\n    std::string word;\n    int start = -1;\n    int end = -1;\n\n    WordPiece(std::string word, int start, int end)\n        : word(std::move(word)), start(start), end(end) {}\n};\n\nstruct DecodeResult {\n    float score = -kBaseFloatMax;\n    std::string sentence;\n    std::vector<WordPiece> word_pieces;\n\n    static bool CompareFunc(const DecodeResult& a, const DecodeResult& b) {\n        return a.score > b.score;\n    }\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_beam_search_opt.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#pragma once\n\n#include \"base/common.h\"\n#include \"util/parse-options.h\"\n\nnamespace ppspeech {\n\n\nstruct CTCBeamSearchOptions {\n    // common\n    int blank;\n    std::string word_symbol_table;\n\n    // u2\n    int first_beam_size;\n    int second_beam_size;\n    \n    CTCBeamSearchOptions()\n        : blank(0),\n          word_symbol_table(\"vocab.txt\"),\n          first_beam_size(10),\n          second_beam_size(10) {}\n\n    void Register(kaldi::OptionsItf* opts) {\n        std::string module = \"CTCBeamSearchOptions: \";\n        opts->Register(\"word_symbol_table\", &word_symbol_table, module + \"vocab file path.\");\n        opts->Register(\"blank\", &blank, \"blank id, default is 0.\");\n        opts->Register(\n            \"first-beam-size\", &first_beam_size, module + \"first beam size.\");\n        opts->Register(\"second-beam-size\",\n                       &second_beam_size,\n                       module + \"second beam size.\");\n    }\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_prefix_beam_search_decoder.cc",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang, Di Wu)\n//               2022 Binbin Zhang (binbzha@qq.com)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"decoder/ctc_prefix_beam_search_decoder.h\"\n\n#include \"base/common.h\"\n#include \"decoder/ctc_beam_search_opt.h\"\n#include \"decoder/ctc_prefix_beam_search_score.h\"\n#include \"utils/math.h\"\n\n#ifdef WITH_PROFILING\n#include \"paddle/fluid/platform/profiler.h\"\nusing paddle::platform::RecordEvent;\nusing paddle::platform::TracerEventType;\n#endif\n\nnamespace ppspeech {\n\nCTCPrefixBeamSearch::CTCPrefixBeamSearch(const CTCBeamSearchOptions& opts)\n    : opts_(opts) {\n    unit_table_ = std::shared_ptr<fst::SymbolTable>(\n        fst::SymbolTable::ReadText(opts.word_symbol_table));\n    CHECK(unit_table_ != nullptr);\n\n    Reset();\n}\n\nvoid CTCPrefixBeamSearch::Reset() {\n    num_frame_decoded_ = 0;\n\n    cur_hyps_.clear();\n\n    hypotheses_.clear();\n    likelihood_.clear();\n    viterbi_likelihood_.clear();\n    times_.clear();\n    outputs_.clear();\n\n    // empty hyp with Score\n    std::vector<int> empty;\n    PrefixScore prefix_score;\n    prefix_score.InitEmpty();\n    cur_hyps_[empty] = prefix_score;\n\n    outputs_.emplace_back(empty);\n    hypotheses_.emplace_back(empty);\n    likelihood_.emplace_back(prefix_score.TotalScore());\n    times_.emplace_back(empty);\n}\n\nvoid CTCPrefixBeamSearch::InitDecoder() { Reset(); }\n\nvoid CTCPrefixBeamSearch::AdvanceDecode(\n    const std::shared_ptr<kaldi::DecodableInterface>& decodable) {\n    double search_cost = 0.0;\n    double feat_nnet_cost = 0.0;\n    while (1) {\n        // forward frame by frame\n        kaldi::Timer timer;\n        std::vector<kaldi::BaseFloat> frame_prob;\n        bool flag = decodable->FrameLikelihood(num_frame_decoded_, &frame_prob);\n        feat_nnet_cost += timer.Elapsed();\n        if (flag == false) {\n            VLOG(2) << \"decoder advance decode exit.\" << frame_prob.size();\n            break;\n        }\n\n        timer.Reset();\n        std::vector<std::vector<kaldi::BaseFloat>> likelihood;\n        likelihood.push_back(std::move(frame_prob));\n        AdvanceDecoding(likelihood);\n        search_cost += timer.Elapsed();\n\n        VLOG(1) << \"num_frame_decoded_: \" << num_frame_decoded_;\n    }\n    VLOG(2) << \"AdvanceDecode feat + forward  cost: \" << feat_nnet_cost\n            << \" sec.\";\n    VLOG(2) << \"AdvanceDecode search  cost: \" << search_cost << \" sec.\";\n}\n\nstatic bool PrefixScoreCompare(\n    const std::pair<std::vector<int>, PrefixScore>& a,\n    const std::pair<std::vector<int>, PrefixScore>& b) {\n    // log domain\n    return a.second.TotalScore() > b.second.TotalScore();\n}\n\n\nvoid CTCPrefixBeamSearch::AdvanceDecoding(\n    const std::vector<std::vector<kaldi::BaseFloat>>& logp) {\n#ifdef WITH_PROFILING\n    RecordEvent event(\"CtcPrefixBeamSearch::AdvanceDecoding\",\n                      TracerEventType::UserDefined,\n                      1);\n#endif\n\n    if (logp.size() == 0) return;\n\n    int first_beam_size =\n        std::min(static_cast<int>(logp[0].size()), opts_.first_beam_size);\n\n    for (int t = 0; t < logp.size(); ++t, ++num_frame_decoded_) {\n        const std::vector<kaldi::BaseFloat>& logp_t = logp[t];\n        std::unordered_map<std::vector<int>, PrefixScore, PrefixScoreHash>\n            next_hyps;\n\n        // 1. first beam prune, only select topk candidates\n        std::vector<kaldi::BaseFloat> topk_score;\n        std::vector<int32_t> topk_index;\n        TopK(logp_t, first_beam_size, &topk_score, &topk_index);\n        VLOG(2) << \"topk: \" << num_frame_decoded_ << \" \"\n                << *std::max_element(logp_t.begin(), logp_t.end()) << \" \"\n                << topk_score[0];\n        for (int i = 0; i < topk_score.size(); i++) {\n            VLOG(2) << \"topk: \" << num_frame_decoded_ << \" \" << topk_score[i];\n        }\n\n        // 2. token passing\n        for (int i = 0; i < topk_index.size(); ++i) {\n            int id = topk_index[i];\n            auto prob = topk_score[i];\n\n            for (const auto& it : cur_hyps_) {\n                const std::vector<int>& prefix = it.first;\n                const PrefixScore& prefix_score = it.second;\n\n                // If prefix doesn't exist in next_hyps, next_hyps[prefix] will\n                // insert\n                // PrefixScore(-inf, -inf) by default, since the default\n                // constructor\n                // of PrefixScore will set fields b(blank ending Score) and\n                // nb(none blank ending Score) to -inf, respectively.\n\n                if (id == opts_.blank) {\n                    // case 0: *a + <blank> => *a, *a<blank> + <blank> => *a,\n                    // prefix not\n                    // change\n                    PrefixScore& next_score = next_hyps[prefix];\n                    next_score.b =\n                        LogSumExp(next_score.b, prefix_score.Score() + prob);\n\n                    // timestamp, blank is slince, not effact timestamp\n                    next_score.v_b = prefix_score.ViterbiScore() + prob;\n                    next_score.times_b = prefix_score.Times();\n\n                    // Prefix not changed, copy the context from prefix\n                    if (context_graph_ && !next_score.has_context) {\n                        next_score.CopyContext(prefix_score);\n                        next_score.has_context = true;\n                    }\n\n                } else if (!prefix.empty() && id == prefix.back()) {\n                    // case 1: *a + a => *a, prefix not changed\n                    PrefixScore& next_score1 = next_hyps[prefix];\n                    next_score1.nb =\n                        LogSumExp(next_score1.nb, prefix_score.nb + prob);\n\n                    // timestamp, non-blank symbol effact timestamp\n                    if (next_score1.v_nb < prefix_score.v_nb + prob) {\n                        // compute viterbi Score\n                        next_score1.v_nb = prefix_score.v_nb + prob;\n                        if (next_score1.cur_token_prob < prob) {\n                            // store max token prob\n                            next_score1.cur_token_prob = prob;\n                            // update this timestamp as token appeared here.\n                            next_score1.times_nb = prefix_score.times_nb;\n                            assert(next_score1.times_nb.size() > 0);\n                            next_score1.times_nb.back() = num_frame_decoded_;\n                        }\n                    }\n\n                    // Prefix not changed, copy the context from prefix\n                    if (context_graph_ && !next_score1.has_context) {\n                        next_score1.CopyContext(prefix_score);\n                        next_score1.has_context = true;\n                    }\n\n                    // case 2: *a<blank> + a => *aa, prefix changed.\n                    std::vector<int> new_prefix(prefix);\n                    new_prefix.emplace_back(id);\n                    PrefixScore& next_score2 = next_hyps[new_prefix];\n                    next_score2.nb =\n                        LogSumExp(next_score2.nb, prefix_score.b + prob);\n\n                    // timestamp, non-blank symbol effact timestamp\n                    if (next_score2.v_nb < prefix_score.v_b + prob) {\n                        // compute viterbi Score\n                        next_score2.v_nb = prefix_score.v_b + prob;\n                        // new token added\n                        next_score2.cur_token_prob = prob;\n                        next_score2.times_nb = prefix_score.times_b;\n                        next_score2.times_nb.emplace_back(num_frame_decoded_);\n                    }\n\n                    // Prefix changed, calculate the context Score.\n                    if (context_graph_ && !next_score2.has_context) {\n                        next_score2.UpdateContext(\n                            context_graph_, prefix_score, id, prefix.size());\n                        next_score2.has_context = true;\n                    }\n\n                } else {\n                    // id != prefix.back()\n                    // case 3: *a + b => *ab, *a<blank> +b => *ab\n                    std::vector<int> new_prefix(prefix);\n                    new_prefix.emplace_back(id);\n                    PrefixScore& next_score = next_hyps[new_prefix];\n                    next_score.nb =\n                        LogSumExp(next_score.nb, prefix_score.Score() + prob);\n\n                    // timetamp, non-blank symbol effact timestamp\n                    if (next_score.v_nb < prefix_score.ViterbiScore() + prob) {\n                        next_score.v_nb = prefix_score.ViterbiScore() + prob;\n\n                        next_score.cur_token_prob = prob;\n                        next_score.times_nb = prefix_score.Times();\n                        next_score.times_nb.emplace_back(num_frame_decoded_);\n                    }\n\n                    // Prefix changed, calculate the context Score.\n                    if (context_graph_ && !next_score.has_context) {\n                        next_score.UpdateContext(\n                            context_graph_, prefix_score, id, prefix.size());\n                        next_score.has_context = true;\n                    }\n                }\n            }  // end for (const auto& it : cur_hyps_)\n        }      // end for (int i = 0; i < topk_index.size(); ++i)\n\n        // 3. second beam prune, only keep top n best paths\n        std::vector<std::pair<std::vector<int>, PrefixScore>> arr(\n            next_hyps.begin(), next_hyps.end());\n        int second_beam_size =\n            std::min(static_cast<int>(arr.size()), opts_.second_beam_size);\n        std::nth_element(arr.begin(),\n                         arr.begin() + second_beam_size,\n                         arr.end(),\n                         PrefixScoreCompare);\n        arr.resize(second_beam_size);\n        std::sort(arr.begin(), arr.end(), PrefixScoreCompare);\n\n        // 4. update cur_hyps by next_hyps, and get new result\n        UpdateHypotheses(arr);\n    }  // end for (int t = 0; t < logp.size(); ++t, ++num_frame_decoded_)\n}\n\n\nvoid CTCPrefixBeamSearch::UpdateHypotheses(\n    const std::vector<std::pair<std::vector<int>, PrefixScore>>& hyps) {\n    cur_hyps_.clear();\n\n    outputs_.clear();\n    hypotheses_.clear();\n    likelihood_.clear();\n    viterbi_likelihood_.clear();\n    times_.clear();\n\n    for (auto& item : hyps) {\n        cur_hyps_[item.first] = item.second;\n\n        UpdateOutputs(item);\n        hypotheses_.emplace_back(std::move(item.first));\n        likelihood_.emplace_back(item.second.TotalScore());\n        viterbi_likelihood_.emplace_back(item.second.ViterbiScore());\n        times_.emplace_back(item.second.Times());\n    }\n}\n\nvoid CTCPrefixBeamSearch::UpdateOutputs(\n    const std::pair<std::vector<int>, PrefixScore>& prefix) {\n    const std::vector<int>& input = prefix.first;\n    const std::vector<int>& start_boundaries = prefix.second.start_boundaries;\n    const std::vector<int>& end_boundaries = prefix.second.end_boundaries;\n\n    // add <context> </context> tag\n    std::vector<int> output;\n    int s = 0;\n    int e = 0;\n    for (int i = 0; i < input.size(); ++i) {\n        output.emplace_back(input[i]);\n    }\n\n    outputs_.emplace_back(output);\n}\n\nvoid CTCPrefixBeamSearch::FinalizeSearch() {\n    UpdateFinalContext();\n\n    VLOG(2) << \"num_frame_decoded_: \" << num_frame_decoded_;\n    int cnt = 0;\n    for (int i = 0; i < hypotheses_.size(); i++) {\n        VLOG(2) << \"hyp \" << cnt << \" len: \" << hypotheses_[i].size()\n                << \" ctc score: \" << likelihood_[i];\n        for (int j = 0; j < hypotheses_[i].size(); j++) {\n            VLOG(2) << hypotheses_[i][j];\n        }\n    }\n}\n\nvoid CTCPrefixBeamSearch::UpdateFinalContext() {\n    if (context_graph_ == nullptr) return;\n\n    CHECK(hypotheses_.size() == cur_hyps_.size());\n    CHECK(hypotheses_.size() == likelihood_.size());\n\n    // We should backoff the context Score/state when the context is\n    // not fully matched at the last time.\n    for (const auto& prefix : hypotheses_) {\n        PrefixScore& prefix_score = cur_hyps_[prefix];\n        if (prefix_score.context_score != 0) {\n            prefix_score.UpdateContext(\n                context_graph_, prefix_score, 0, prefix.size());\n        }\n    }\n    std::vector<std::pair<std::vector<int>, PrefixScore>> arr(cur_hyps_.begin(),\n                                                              cur_hyps_.end());\n    std::sort(arr.begin(), arr.end(), PrefixScoreCompare);\n\n    // Update cur_hyps_ and get new result\n    UpdateHypotheses(arr);\n}\n\nstd::string CTCPrefixBeamSearch::GetBestPath(int index) {\n    int n_hyps = Outputs().size();\n    CHECK_GT(n_hyps, 0);\n    CHECK_LT(index, n_hyps);\n    std::vector<int> one = Outputs()[index];\n    std::string sentence;\n    for (int i = 0; i < one.size(); i++) {\n        sentence += unit_table_->Find(one[i]);\n    }\n    return sentence;\n}\n\nstd::string CTCPrefixBeamSearch::GetBestPath() { return GetBestPath(0); }\n\nstd::vector<std::pair<double, std::string>> CTCPrefixBeamSearch::GetNBestPath(\n    int n) {\n    int hyps_size = hypotheses_.size();\n    CHECK_GT(hyps_size, 0);\n\n    int min_n = n == -1 ? hypotheses_.size() : std::min(n, hyps_size);\n\n    std::vector<std::pair<double, std::string>> n_best;\n    n_best.reserve(min_n);\n\n    for (int i = 0; i < min_n; i++) {\n        n_best.emplace_back(Likelihood()[i], GetBestPath(i));\n    }\n    return n_best;\n}\n\nstd::vector<std::pair<double, std::string>>\nCTCPrefixBeamSearch::GetNBestPath() {\n    return GetNBestPath(-1);\n}\n\nstd::string CTCPrefixBeamSearch::GetFinalBestPath() { return GetBestPath(); }\n\nstd::string CTCPrefixBeamSearch::GetPartialResult() { return GetBestPath(); }\n\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_prefix_beam_search_decoder.h",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/ctc_prefix_beam_search.cc\n\n#pragma once\n\n#include \"decoder/ctc_beam_search_opt.h\"\n#include \"decoder/ctc_prefix_beam_search_score.h\"\n#include \"decoder/decoder_itf.h\"\n#include \"fst/symbol-table.h\"\n\nnamespace ppspeech {\nclass ContextGraph;\nclass CTCPrefixBeamSearch : public DecoderBase {\n  public:\n    CTCPrefixBeamSearch(const CTCBeamSearchOptions& opts);\n    ~CTCPrefixBeamSearch() {}\n\n    SearchType Type() const { return SearchType::kPrefixBeamSearch; }\n\n    void InitDecoder() override;\n\n    void Reset() override;\n\n    void AdvanceDecode(\n        const std::shared_ptr<kaldi::DecodableInterface>& decodable) override;\n\n    std::string GetFinalBestPath() override;\n    std::string GetPartialResult() override;\n\n    void FinalizeSearch();\n\n    const std::shared_ptr<fst::SymbolTable> WordSymbolTable() const override {\n        return unit_table_;\n    }\n\n    const std::vector<std::vector<int>>& Inputs() const { return hypotheses_; }\n    const std::vector<std::vector<int>>& Outputs() const { return outputs_; }\n    const std::vector<float>& Likelihood() const { return likelihood_; }\n    const std::vector<float>& ViterbiLikelihood() const {\n        return viterbi_likelihood_;\n    }\n    const std::vector<std::vector<int>>& Times() const { return times_; }\n\n  protected:\n    std::string GetBestPath() override;\n    std::vector<std::pair<double, std::string>> GetNBestPath() override;\n    std::vector<std::pair<double, std::string>> GetNBestPath(int n) override;\n\n  private:\n    std::string GetBestPath(int index);\n\n    void AdvanceDecoding(\n        const std::vector<std::vector<kaldi::BaseFloat>>& logp);\n\n    void UpdateOutputs(const std::pair<std::vector<int>, PrefixScore>& prefix);\n    void UpdateHypotheses(\n        const std::vector<std::pair<std::vector<int>, PrefixScore>>& prefix);\n    void UpdateFinalContext();\n\n\n  private:\n    CTCBeamSearchOptions opts_;\n    std::shared_ptr<fst::SymbolTable> unit_table_{nullptr};\n\n    std::unordered_map<std::vector<int>, PrefixScore, PrefixScoreHash>\n        cur_hyps_;\n\n    // n-best list and corresponding likelihood, in sorted order\n    std::vector<std::vector<int>> hypotheses_;\n    std::vector<float> likelihood_;\n\n    std::vector<std::vector<int>> times_;\n    std::vector<float> viterbi_likelihood_;\n\n    // Outputs contain the hypotheses_ and tags lik: <context> and </context>\n    std::vector<std::vector<int>> outputs_;\n\n    std::shared_ptr<ContextGraph> context_graph_{nullptr};\n\n    DISALLOW_COPY_AND_ASSIGN(CTCPrefixBeamSearch);\n};\n\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_prefix_beam_search_decoder_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/common.h\"\n#include \"decoder/ctc_prefix_beam_search_decoder.h\"\n#include \"frontend/data_cache.h\"\n#include \"fst/symbol-table.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/decodable.h\"\n#include \"nnet/nnet_producer.h\"\n#include \"nnet/u2_nnet.h\"\n\nDEFINE_string(feature_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(result_wspecifier, \"\", \"test result wspecifier\");\nDEFINE_string(word_symbol_table, \"\", \"vocab path\");\n\nDEFINE_string(model_path, \"\", \"paddle nnet model\");\n\nDEFINE_int32(receptive_field_length,\n             7,\n             \"receptive field of two CNN(kernel=3) downsampling module.\");\nDEFINE_int32(subsampling_rate,\n             4,\n             \"two CNN(kernel=3) module downsampling rate.\");\n\nDEFINE_int32(nnet_decoder_chunk, 16, \"paddle nnet forward chunk\");\n\nusing kaldi::BaseFloat;\nusing kaldi::Matrix;\nusing std::vector;\n\n// test u2 online decoder by feeding speech feature\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int32 num_done = 0, num_err = 0;\n\n    CHECK_NE(FLAGS_result_wspecifier, \"\");\n    CHECK_NE(FLAGS_feature_rspecifier, \"\");\n    CHECK_NE(FLAGS_word_symbol_table, \"\");\n    CHECK_NE(FLAGS_model_path, \"\");\n    LOG(INFO) << \"model path: \" << FLAGS_model_path;\n    LOG(INFO) << \"Reading vocab table \" << FLAGS_word_symbol_table;\n\n    kaldi::SequentialBaseFloatMatrixReader feature_reader(\n        FLAGS_feature_rspecifier);\n    kaldi::TokenWriter result_writer(FLAGS_result_wspecifier);\n\n    // nnet\n    ppspeech::ModelOptions model_opts;\n    model_opts.model_path = FLAGS_model_path;\n    std::shared_ptr<ppspeech::U2Nnet> nnet =\n        std::make_shared<ppspeech::U2Nnet>(model_opts);\n\n    // decodeable\n    std::shared_ptr<ppspeech::DataCache> raw_data =\n        std::make_shared<ppspeech::DataCache>();\n    std::shared_ptr<ppspeech::NnetProducer> nnet_producer =\n        std::make_shared<ppspeech::NnetProducer>(nnet, raw_data, 1.0);\n    std::shared_ptr<ppspeech::Decodable> decodable =\n        std::make_shared<ppspeech::Decodable>(nnet_producer);\n\n    // decoder\n    ppspeech::CTCBeamSearchOptions opts;\n    opts.blank = 0;\n    opts.first_beam_size = 10;\n    opts.second_beam_size = 10;\n    opts.word_symbol_table = FLAGS_word_symbol_table;\n    ppspeech::CTCPrefixBeamSearch decoder(opts);\n\n\n    int32 chunk_size = FLAGS_receptive_field_length +\n                       (FLAGS_nnet_decoder_chunk - 1) * FLAGS_subsampling_rate;\n    int32 chunk_stride = FLAGS_subsampling_rate * FLAGS_nnet_decoder_chunk;\n    int32 receptive_field_length = FLAGS_receptive_field_length;\n    LOG(INFO) << \"chunk size (frame): \" << chunk_size;\n    LOG(INFO) << \"chunk stride (frame): \" << chunk_stride;\n    LOG(INFO) << \"receptive field (frame): \" << receptive_field_length;\n\n    decoder.InitDecoder();\n\n    kaldi::Timer timer;\n    for (; !feature_reader.Done(); feature_reader.Next()) {\n        string utt = feature_reader.Key();\n        kaldi::Matrix<BaseFloat> feature = feature_reader.Value();\n\n        int nframes = feature.NumRows();\n        int feat_dim = feature.NumCols();\n        raw_data->SetDim(feat_dim);\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"feat shape: \" << nframes << \", \" << feat_dim;\n\n        raw_data->SetDim(feat_dim);\n\n        int32 ori_feature_len = feature.NumRows();\n        int32 num_chunks = feature.NumRows() / chunk_stride + 1;\n        LOG(INFO) << \"num_chunks: \" << num_chunks;\n\n        for (int chunk_idx = 0; chunk_idx < num_chunks; ++chunk_idx) {\n            int32 this_chunk_size = 0;\n            if (ori_feature_len > chunk_idx * chunk_stride) {\n                this_chunk_size = std::min(\n                    ori_feature_len - chunk_idx * chunk_stride, chunk_size);\n            }\n            if (this_chunk_size < receptive_field_length) {\n                LOG(WARNING)\n                    << \"utt: \" << utt << \" skip last \" << this_chunk_size\n                    << \" frames, expect is \" << receptive_field_length;\n                break;\n            }\n\n\n            std::vector<kaldi::BaseFloat> feature_chunk(this_chunk_size *\n                                                        feat_dim);\n            int32 start = chunk_idx * chunk_stride;\n            for (int row_id = 0; row_id < this_chunk_size; ++row_id) {\n                kaldi::SubVector<kaldi::BaseFloat> feat_row(feature, start);\n                std::memcpy(feature_chunk.data() + row_id * feat_dim,\n                            feat_row.Data(),\n                            feat_dim * sizeof(kaldi::BaseFloat));\n                ++start;\n            }\n\n            // feat to frontend pipeline cache\n            raw_data->Accept(feature_chunk);\n\n            // send data finish signal\n            if (chunk_idx == num_chunks - 1) {\n                raw_data->SetFinished();\n            }\n\n            // forward nnet\n            decoder.AdvanceDecode(decodable);\n\n            LOG(INFO) << \"Partial result: \" << decoder.GetPartialResult();\n        }\n\n        decoder.FinalizeSearch();\n\n        // get 1-best result\n        std::string result = decoder.GetFinalBestPath();\n\n        // after process one utt, then reset state.\n        decodable->Reset();\n        decoder.Reset();\n\n        if (result.empty()) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            LOG(INFO) << \" the result of \" << utt << \" is empty\";\n            continue;\n        }\n\n        LOG(INFO) << \" the result of \" << utt << \" is \" << result;\n        result_writer.Write(utt, result);\n\n        ++num_done;\n    }\n\n    double elapsed = timer.Elapsed();\n    LOG(INFO) << \"Program cost:\" << elapsed << \" sec\";\n\n    LOG(INFO) << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_prefix_beam_search_score.h",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/ctc_prefix_beam_search.h\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"utils/math.h\"\n\nnamespace ppspeech {\n\nclass ContextGraph;\n\nstruct PrefixScore {\n    // decoding, unit in log scale\n    float b = -kBaseFloatMax;   // blank ending score\n    float nb = -kBaseFloatMax;  // none-blank ending score\n\n    // decoding score, sum\n    float Score() const { return LogSumExp(b, nb); }\n\n    // timestamp, unit in log sclae\n    float v_b = -kBaseFloatMax;             // viterbi blank ending score\n    float v_nb = -kBaseFloatMax;            // niterbi none-blank ending score\n    float cur_token_prob = -kBaseFloatMax;  // prob of current token\n    std::vector<int> times_b;               // times of viterbi blank path\n    std::vector<int> times_nb;              // times of viterbi non-blank path\n\n\n    // timestamp score, max\n    float ViterbiScore() const { return std::max(v_b, v_nb); }\n\n    // get timestamp\n    const std::vector<int>& Times() const {\n        return v_b > v_nb ? times_b : times_nb;\n    }\n\n    // context state\n    bool has_context = false;\n    int context_state = 0;\n    float context_score = 0;\n    std::vector<int> start_boundaries;\n    std::vector<int> end_boundaries;\n\n\n    // decodign score with context bias\n    float TotalScore() const { return Score() + context_score; }\n\n    void CopyContext(const PrefixScore& prefix_score) {\n        context_state = prefix_score.context_state;\n        context_score = prefix_score.context_score;\n        start_boundaries = prefix_score.start_boundaries;\n        end_boundaries = prefix_score.end_boundaries;\n    }\n\n    void UpdateContext(const std::shared_ptr<ContextGraph>& constext_graph,\n                       const PrefixScore& prefix_score,\n                       int word_id,\n                       int prefix_len) {\n        CHECK(false);\n    }\n\n    void InitEmpty() {\n        b = 0.0f;             // log(1)\n        nb = -kBaseFloatMax;  // log(0)\n        v_b = 0.0f;           // log(1)\n        v_nb = 0.0f;          // log(1)\n    }\n};\n\nstruct PrefixScoreHash {\n    // https://stackoverflow.com/questions/20511347/a-good-hash-function-for-a-vector\n    std::size_t operator()(const std::vector<int>& prefix) const {\n        std::size_t seed = prefix.size();\n        for (auto& i : prefix) {\n            seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\nusing PrefixWithScoreType = std::pair<std::vector<int>, PrefixScoreHash>;\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_tlg_decoder.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"decoder/ctc_tlg_decoder.h\"\n\nnamespace ppspeech {\n\nTLGDecoder::TLGDecoder(TLGDecoderOptions opts) : opts_(opts) {\n    fst_ = opts.fst_ptr;\n    CHECK(fst_ != nullptr);\n\n    CHECK(!opts.word_symbol_table.empty());\n    word_symbol_table_.reset(\n        fst::SymbolTable::ReadText(opts.word_symbol_table));\n\n    decoder_.reset(new kaldi::LatticeFasterOnlineDecoder(*fst_, opts.opts));\n\n    Reset();\n}\n\nvoid TLGDecoder::Reset() {\n    decoder_->InitDecoding();\n    hypotheses_.clear();\n    likelihood_.clear();\n    olabels_.clear();\n    times_.clear();\n\n    num_frame_decoded_ = 0;\n    return;\n}\n\nvoid TLGDecoder::InitDecoder() { Reset(); }\n\nvoid TLGDecoder::AdvanceDecode(\n    const std::shared_ptr<kaldi::DecodableInterface>& decodable) {\n    while (!decodable->IsLastFrame(num_frame_decoded_)) {\n        AdvanceDecoding(decodable.get());\n    }\n}\n\nvoid TLGDecoder::AdvanceDecoding(kaldi::DecodableInterface* decodable) {\n    decoder_->AdvanceDecoding(decodable, 1);\n    num_frame_decoded_++;\n}\n\n\nstd::string TLGDecoder::GetPartialResult() {\n    if (num_frame_decoded_ == 0) {\n        // Assertion failed: (this->NumFramesDecoded() > 0 && \"You cannot call\n        // BestPathEnd if no frames were decoded.\")\n        return std::string(\"\");\n    }\n    kaldi::Lattice lat;\n    kaldi::LatticeWeight weight;\n    std::vector<int> alignment;\n    std::vector<int> words_id;\n    decoder_->GetBestPath(&lat, false);\n    fst::GetLinearSymbolSequence(lat, &alignment, &words_id, &weight);\n    std::string words;\n    for (int32 idx = 0; idx < words_id.size(); ++idx) {\n        std::string word = word_symbol_table_->Find(words_id[idx]);\n        words += word;\n    }\n    return words;\n}\n\nvoid TLGDecoder::FinalizeSearch() {\n    decoder_->FinalizeDecoding();\n    kaldi::CompactLattice clat;\n    decoder_->GetLattice(&clat, true);\n    kaldi::Lattice lat, nbest_lat;\n    fst::ConvertLattice(clat, &lat);\n    fst::ShortestPath(lat, &nbest_lat, opts_.nbest);\n    std::vector<kaldi::Lattice> nbest_lats;\n    fst::ConvertNbestToVector(nbest_lat, &nbest_lats);\n\n    hypotheses_.clear();\n    hypotheses_.reserve(nbest_lats.size());\n    likelihood_.clear();\n    likelihood_.reserve(nbest_lats.size());\n    times_.clear();\n    times_.reserve(nbest_lats.size());\n    for (auto lat : nbest_lats) {\n        kaldi::LatticeWeight weight;\n        std::vector<int> hypothese;\n        std::vector<int> time;\n        std::vector<int> alignment;\n        std::vector<int> words_id;\n        fst::GetLinearSymbolSequence(lat, &alignment, &words_id, &weight);\n        int idx = 0;\n        for (; idx < alignment.size() - 1; ++idx) {\n            if (alignment[idx] == 0) continue;\n            if (alignment[idx] != alignment[idx + 1]) {\n                hypothese.push_back(alignment[idx] - 1);\n                time.push_back(idx);  // fake time, todo later\n            }\n        }\n        hypothese.push_back(alignment[idx] - 1);\n        time.push_back(idx);  // fake time, todo later\n        hypotheses_.push_back(hypothese);\n        times_.push_back(time);\n        olabels_.push_back(words_id);\n        likelihood_.push_back(-(weight.Value2() + weight.Value1()));\n    }\n}\n\nstd::string TLGDecoder::GetFinalBestPath() {\n    if (num_frame_decoded_ == 0) {\n        // Assertion failed: (this->NumFramesDecoded() > 0 && \"You cannot call\n        // BestPathEnd if no frames were decoded.\")\n        return std::string(\"\");\n    }\n    kaldi::Lattice lat;\n    kaldi::LatticeWeight weight;\n    std::vector<int> alignment;\n    std::vector<int> words_id;\n    decoder_->GetBestPath(&lat, true);\n    fst::GetLinearSymbolSequence(lat, &alignment, &words_id, &weight);\n    std::string words;\n    for (int32 idx = 0; idx < words_id.size(); ++idx) {\n        std::string word = word_symbol_table_->Find(words_id[idx]);\n        words += word;\n    }\n    return words;\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_tlg_decoder.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"decoder/decoder_itf.h\"\n#include \"kaldi/decoder/lattice-faster-online-decoder.h\"\n#include \"util/parse-options.h\"\n#include \"utils/file_utils.h\"\n\nDECLARE_string(word_symbol_table);\nDECLARE_string(graph_path);\nDECLARE_int32(max_active);\nDECLARE_double(beam);\nDECLARE_double(lattice_beam);\nDECLARE_int32(nbest);\n\nnamespace ppspeech {\n\nstruct TLGDecoderOptions {\n    kaldi::LatticeFasterDecoderConfig opts{};\n    // todo remove later, add into decode resource\n    std::string word_symbol_table;\n    std::string fst_path;\n    std::shared_ptr<fst::Fst<fst::StdArc>> fst_ptr;\n    int nbest;\n\n    TLGDecoderOptions() : word_symbol_table(\"\"), fst_path(\"\"), fst_ptr(nullptr), nbest(10) {}\n\n    static TLGDecoderOptions InitFromFlags() {\n        TLGDecoderOptions decoder_opts;\n        decoder_opts.word_symbol_table = FLAGS_word_symbol_table;\n        decoder_opts.fst_path = FLAGS_graph_path;\n        LOG(INFO) << \"fst path: \" << decoder_opts.fst_path;\n        LOG(INFO) << \"symbole table: \" << decoder_opts.word_symbol_table;\n\n        if (!decoder_opts.fst_path.empty()) {\n            CHECK(FileExists(decoder_opts.fst_path));\n            decoder_opts.fst_ptr.reset(fst::Fst<fst::StdArc>::Read(FLAGS_graph_path));\n        }\n\n        decoder_opts.opts.max_active = FLAGS_max_active;\n        decoder_opts.opts.beam = FLAGS_beam;\n        decoder_opts.opts.lattice_beam = FLAGS_lattice_beam;\n        decoder_opts.nbest = FLAGS_nbest;\n        LOG(INFO) << \"LatticeFasterDecoder max active: \"\n                  << decoder_opts.opts.max_active;\n        LOG(INFO) << \"LatticeFasterDecoder beam: \" << decoder_opts.opts.beam;\n        LOG(INFO) << \"LatticeFasterDecoder lattice_beam: \"\n                  << decoder_opts.opts.lattice_beam;\n\n        return decoder_opts;\n    }\n};\n\nclass TLGDecoder : public DecoderBase {\n  public:\n    explicit TLGDecoder(TLGDecoderOptions opts);\n    ~TLGDecoder() = default;\n\n    void InitDecoder() override;\n    void Reset() override;\n\n    void AdvanceDecode(\n        const std::shared_ptr<kaldi::DecodableInterface>& decodable) override;\n\n    void Decode();\n\n    std::string GetFinalBestPath() override;\n    std::string GetPartialResult() override;\n\n    const std::shared_ptr<fst::SymbolTable> WordSymbolTable() const override {\n        return word_symbol_table_;\n    }\n\n    int DecodeLikelihoods(const std::vector<std::vector<BaseFloat>>& probs,\n                          const std::vector<std::string>& nbest_words);\n\n    void FinalizeSearch() override;\n    const std::vector<std::vector<int>>& Inputs() const override {\n        return hypotheses_;\n    }\n    const std::vector<std::vector<int>>& Outputs() const override {\n        return olabels_;\n    }  // outputs_; }\n    const std::vector<float>& Likelihood() const override {\n        return likelihood_;\n    }\n    const std::vector<std::vector<int>>& Times() const override {\n        return times_;\n    }\n\n  protected:\n    std::string GetBestPath() override {\n        CHECK(false);\n        return {};\n    }\n    std::vector<std::pair<double, std::string>> GetNBestPath() override {\n        CHECK(false);\n        return {};\n    }\n    std::vector<std::pair<double, std::string>> GetNBestPath(int n) override {\n        CHECK(false);\n        return {};\n    }\n\n  private:\n    void AdvanceDecoding(kaldi::DecodableInterface* decodable);\n\n    int num_frame_decoded_;\n    std::vector<std::vector<int>> hypotheses_;\n    std::vector<std::vector<int>> olabels_;\n    std::vector<float> likelihood_;\n    std::vector<std::vector<int>> times_;\n\n    std::shared_ptr<kaldi::LatticeFasterOnlineDecoder> decoder_;\n    std::shared_ptr<fst::Fst<fst::StdArc>> fst_;\n    std::shared_ptr<fst::SymbolTable> word_symbol_table_;\n    TLGDecoderOptions opts_;\n};\n\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/decoder/ctc_tlg_decoder_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// todo refactor, repalce with gtest\n\n#include \"base/common.h\"\n#include \"decoder/ctc_tlg_decoder.h\"\n#include \"decoder/param.h\"\n#include \"frontend/data_cache.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/decodable.h\"\n#include \"nnet/nnet_producer.h\"\n\n\nDEFINE_string(nnet_prob_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(result_wspecifier, \"\", \"test result wspecifier\");\n\n\nusing kaldi::BaseFloat;\nusing kaldi::Matrix;\nusing std::vector;\n\n// test TLG decoder by feeding speech feature.\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    kaldi::SequentialBaseFloatMatrixReader nnet_prob_reader(\n        FLAGS_nnet_prob_rspecifier);\n    kaldi::TokenWriter result_writer(FLAGS_result_wspecifier);\n\n    int32 num_done = 0, num_err = 0;\n\n    ppspeech::TLGDecoderOptions opts =\n        ppspeech::TLGDecoderOptions::InitFromFlags();\n    opts.opts.beam = 15.0;\n    opts.opts.lattice_beam = 7.5;\n    ppspeech::TLGDecoder decoder(opts);\n\n    ppspeech::ModelOptions model_opts = ppspeech::ModelOptions::InitFromFlags();\n\n    std::shared_ptr<ppspeech::NnetProducer> nnet_producer =\n        std::make_shared<ppspeech::NnetProducer>(nullptr, nullptr, 1.0);\n    std::shared_ptr<ppspeech::Decodable> decodable(\n        new ppspeech::Decodable(nnet_producer, FLAGS_acoustic_scale));\n\n    decoder.InitDecoder();\n    kaldi::Timer timer;\n\n    for (; !nnet_prob_reader.Done(); nnet_prob_reader.Next()) {\n        string utt = nnet_prob_reader.Key();\n        kaldi::Matrix<BaseFloat> prob = nnet_prob_reader.Value();\n        decodable->Acceptlikelihood(prob);\n        decoder.AdvanceDecode(decodable);\n        std::string result;\n        result = decoder.GetFinalBestPath();\n        decodable->Reset();\n        decoder.Reset();\n        if (result.empty()) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            KALDI_LOG << \" the result of \" << utt << \" is empty\";\n            continue;\n        }\n        KALDI_LOG << \" the result of \" << utt << \" is \" << result;\n        result_writer.Write(utt, result);\n        ++num_done;\n    }\n\n    double elapsed = timer.Elapsed();\n    KALDI_LOG << \" cost:\" << elapsed << \" s\";\n\n    KALDI_LOG << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/asr/decoder/decoder_itf.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"fst/symbol-table.h\"\n#include \"kaldi/decoder/decodable-itf.h\"\n\nnamespace ppspeech {\n\nenum SearchType {\n    kPrefixBeamSearch = 0,\n    kWfstBeamSearch = 1,\n};\nclass DecoderInterface {\n  public:\n    virtual ~DecoderInterface() {}\n\n    virtual void InitDecoder() = 0;\n\n    virtual void Reset() = 0;\n\n    // call AdvanceDecoding\n    virtual void AdvanceDecode(\n        const std::shared_ptr<kaldi::DecodableInterface>& decodable) = 0;\n\n    // call GetBestPath\n    virtual std::string GetFinalBestPath() = 0;\n\n    virtual std::string GetPartialResult() = 0;\n\n    virtual const std::shared_ptr<fst::SymbolTable> WordSymbolTable() const = 0;\n    virtual void FinalizeSearch() = 0;\n\n    virtual const std::vector<std::vector<int>>& Inputs() const = 0;\n    virtual const std::vector<std::vector<int>>& Outputs() const = 0;\n    virtual const std::vector<float>& Likelihood() const = 0;\n    virtual const std::vector<std::vector<int>>& Times() const = 0;\n\n  protected:\n    // virtual void AdvanceDecoding(kaldi::DecodableInterface* decodable) = 0;\n\n    // virtual void Decode() = 0;\n\n    virtual std::string GetBestPath() = 0;\n\n    virtual std::vector<std::pair<double, std::string>> GetNBestPath() = 0;\n\n    virtual std::vector<std::pair<double, std::string>> GetNBestPath(int n) = 0;\n};\n\nclass DecoderBase : public DecoderInterface {\n  protected:\n    // start from one\n    int NumFrameDecoded() { return num_frame_decoded_ + 1; }\n\n  protected:\n    // current decoding frame number, abs_time_step_\n    int32 num_frame_decoded_;\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/asr/decoder/param.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n\n// feature\nDEFINE_bool(use_fbank, false, \"False for fbank; or linear feature\");\nDEFINE_bool(fill_zero,\n            false,\n            \"fill zero at last chunk, when chunk < chunk_size\");\n// DEFINE_bool(to_float32, true, \"audio convert to pcm32. True for linear\n// feature, or fbank\");\nDEFINE_int32(num_bins, 161, \"num bins of mel\");\nDEFINE_string(cmvn_file, \"\", \"read cmvn\");\n\n// feature sliding window\nDEFINE_int32(receptive_field_length,\n             7,\n             \"receptive field of two CNN(kernel=3) downsampling module.\");\nDEFINE_int32(subsampling_rate,\n             4,\n             \"two CNN(kernel=3) module downsampling rate.\");\nDEFINE_int32(nnet_decoder_chunk, 1, \"paddle nnet forward chunk\");\n\n// nnet\nDEFINE_string(model_path, \"avg_1.jit.pdmodel\", \"paddle nnet model\");\n#ifdef USE_ONNX\nDEFINE_bool(with_onnx_model, false, \"True mean the model path is onnx model path\");\n#endif\n\n// decoder\nDEFINE_double(acoustic_scale, 1.0, \"acoustic scale\");\nDEFINE_string(graph_path, \"\", \"decoder graph\");\nDEFINE_string(word_symbol_table, \"\", \"word symbol table\");\nDEFINE_int32(max_active, 7500, \"max active\");\nDEFINE_double(beam, 15.0, \"decoder beam\");\nDEFINE_double(lattice_beam, 7.5, \"decoder beam\");\nDEFINE_double(blank_threshold, 0.98, \"blank skip threshold\");\n\n// DecodeOptions flags\nDEFINE_int32(num_left_chunks, -1, \"left chunks in decoding\");\nDEFINE_double(ctc_weight,\n              0.5,\n              \"ctc weight when combining ctc score and rescoring score\");\nDEFINE_double(rescoring_weight,\n              1.0,\n              \"rescoring weight when combining ctc score and rescoring score\");\nDEFINE_double(reverse_weight,\n              0.3,\n              \"used for bitransformer rescoring. it must be 0.0 if decoder is\"\n              \"conventional transformer decoder, and only reverse_weight > 0.0\"\n              \"dose the right to left decoder will be calculated and used\");\nDEFINE_int32(nbest, 10, \"nbest for ctc wfst or prefix search\");\nDEFINE_int32(blank, 0, \"blank id in vocab\");\n"
  },
  {
    "path": "runtime/engine/asr/nnet/CMakeLists.txt",
    "content": "set(srcs decodable.cc nnet_producer.cc)\n\nlist(APPEND srcs u2_nnet.cc)\nif(WITH_ONNX)\n    list(APPEND srcs u2_onnx_nnet.cc)\nendif()\nadd_library(nnet STATIC ${srcs})\ntarget_link_libraries(nnet utils)\nif(WITH_ONNX)\n    target_link_libraries(nnet ${FASTDEPLOY_LIBS})\nendif()\n\ntarget_compile_options(nnet  PUBLIC ${PADDLE_COMPILE_FLAGS})\ntarget_include_directories(nnet  PUBLIC ${pybind11_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})\n\n# test bin  \n#set(bin_name u2_nnet_main)\n#add_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\n#target_compile_options(${bin_name}  PRIVATE ${PADDLE_COMPILE_FLAGS})\n#target_include_directories(${bin_name}  PRIVATE ${pybind11_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})\n#target_link_libraries(${bin_name}  ${PYTHON_LIBRARIES} ${PADDLE_LINK_FLAGS})"
  },
  {
    "path": "runtime/engine/asr/nnet/decodable.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"nnet/decodable.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing kaldi::Matrix;\nusing kaldi::Vector;\nusing std::vector;\n\nDecodable::Decodable(const std::shared_ptr<NnetProducer>& nnet_producer,\n                     kaldi::BaseFloat acoustic_scale)\n    : nnet_producer_(nnet_producer),\n      frame_offset_(0),\n      frames_ready_(0),\n      acoustic_scale_(acoustic_scale) {}\n\n// for debug\nvoid Decodable::Acceptlikelihood(const Matrix<BaseFloat>& likelihood) {\n    nnet_producer_->Acceptlikelihood(likelihood);\n}\n\n// return the size of frame have computed.\nint32 Decodable::NumFramesReady() const { return frames_ready_; }\n\n\n// frame idx is from 0 to frame_ready_ -1;\nbool Decodable::IsLastFrame(int32 frame) {\n    EnsureFrameHaveComputed(frame);\n    return frame >= frames_ready_;\n}\n\nint32 Decodable::NumIndices() const { return 0; }\n\n// the ilable(TokenId) of wfst(TLG) insert <eps>(id = 0) in front of Nnet prob\n// id.\nint32 Decodable::TokenId2NnetId(int32 token_id) { return token_id - 1; }\n\n\nbool Decodable::EnsureFrameHaveComputed(int32 frame) {\n    // decoding frame\n    if (frame >= frames_ready_) {\n        return AdvanceChunk();\n    }\n    return true;\n}\n\nbool Decodable::AdvanceChunk() {\n    kaldi::Timer timer;\n    bool flag = nnet_producer_->Read(&framelikelihood_);\n    if (flag == false) return false;\n    frame_offset_ = frames_ready_;\n    frames_ready_ += 1;\n    VLOG(1) << \"AdvanceChunk feat + forward cost: \" << timer.Elapsed()\n            << \" sec.\";\n    return true;\n}\n\nbool Decodable::AdvanceChunk(kaldi::Vector<kaldi::BaseFloat>* logprobs,\n                             int* vocab_dim) {\n    if (AdvanceChunk() == false) {\n        return false;\n    }\n\n    if (framelikelihood_.empty()) {\n        LOG(WARNING) << \"No new nnet out in cache.\";\n        return false;\n    }\n\n    size_t dim = framelikelihood_.size();\n    logprobs->Resize(framelikelihood_.size());\n    std::memcpy(logprobs->Data(),\n                framelikelihood_.data(),\n                dim * sizeof(kaldi::BaseFloat));\n    *vocab_dim = framelikelihood_.size();\n    return true;\n}\n\n// read one frame likelihood\nbool Decodable::FrameLikelihood(int32 frame, vector<BaseFloat>* likelihood) {\n    if (EnsureFrameHaveComputed(frame) == false) {\n        VLOG(3) << \"framelikehood exit.\";\n        return false;\n    }\n\n    CHECK_EQ(1, (frames_ready_ - frame_offset_));\n    *likelihood = framelikelihood_;\n    return true;\n}\n\nBaseFloat Decodable::LogLikelihood(int32 frame, int32 index) {\n    if (EnsureFrameHaveComputed(frame) == false) {\n        return false;\n    }\n\n    CHECK_LE(index, framelikelihood_.size());\n    CHECK_LE(frame, frames_ready_);\n\n    // the nnet output is prob ranther than log prob\n    // the index - 1, because the ilabel\n    BaseFloat logprob = 0.0;\n    int32 frame_idx = frame - frame_offset_;\n    CHECK_EQ(frame_idx, 0);\n    logprob = framelikelihood_[TokenId2NnetId(index)];\n    return acoustic_scale_ * logprob;\n}\n\nvoid Decodable::Reset() {\n    if (nnet_producer_ != nullptr) nnet_producer_->Reset();\n    frame_offset_ = 0;\n    frames_ready_ = 0;\n    framelikelihood_.clear();\n}\n\nvoid Decodable::AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                                   float reverse_weight,\n                                   std::vector<float>* rescoring_score) {\n    kaldi::Timer timer;\n    nnet_producer_->AttentionRescoring(hyps, reverse_weight, rescoring_score);\n    VLOG(1) << \"Attention Rescoring cost:  \" << timer.Elapsed() << \" sec.\";\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/decodable.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"kaldi/decoder/decodable-itf.h\"\n#include \"matrix/kaldi-matrix.h\"\n#include \"nnet/nnet_itf.h\"\n#include \"nnet/nnet_producer.h\"\n\nnamespace ppspeech {\n\nstruct DecodableOpts;\n\nclass Decodable : public kaldi::DecodableInterface {\n  public:\n    explicit Decodable(const std::shared_ptr<NnetProducer>& nnet_producer,\n                       kaldi::BaseFloat acoustic_scale = 1.0);\n\n    // nnet logprob output, used by wfst\n    virtual kaldi::BaseFloat LogLikelihood(int32 frame, int32 index);\n\n    // nnet output\n    virtual bool FrameLikelihood(int32 frame,\n                                 std::vector<kaldi::BaseFloat>* likelihood);\n\n    // forward nnet with feats\n    bool AdvanceChunk();\n\n    // forward nnet with feats, and get nnet output\n    bool AdvanceChunk(kaldi::Vector<kaldi::BaseFloat>* logprobs,\n                      int* vocab_dim);\n\n    void AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                            float reverse_weight,\n                            std::vector<float>* rescoring_score);\n\n    virtual bool IsLastFrame(int32 frame);\n\n    // nnet output dim, e.g. vocab size\n    virtual int32 NumIndices() const;\n\n    virtual int32 NumFramesReady() const;\n\n    void Reset();\n\n    bool IsInputFinished() const { return nnet_producer_->IsFinished(); }\n\n    bool EnsureFrameHaveComputed(int32 frame);\n\n    int32 TokenId2NnetId(int32 token_id);\n\n    // for offline test\n    void Acceptlikelihood(const kaldi::Matrix<kaldi::BaseFloat>& likelihood);\n\n  private:\n    std::shared_ptr<NnetProducer> nnet_producer_;\n\n    // the frame is nnet prob frame rather than audio feature frame\n    // nnet frame subsample the feature frame\n    // eg: 35 frame features output 8 frame inferences\n    int32 frame_offset_;\n    int32 frames_ready_;\n\n    // todo: feature frame mismatch with nnet inference frame\n    // so use subsampled_frame\n    int32 current_log_post_subsampled_offset_;\n    int32 num_chunk_computed_;\n    std::vector<kaldi::BaseFloat> framelikelihood_;\n\n    kaldi::BaseFloat acoustic_scale_;\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/nnet_itf.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#pragma once\n\n#include \"base/basic_types.h\"\n#include \"kaldi/base/kaldi-types.h\"\n#include \"kaldi/util/options-itf.h\"\n\nDECLARE_int32(subsampling_rate);\nDECLARE_string(model_path);\nDECLARE_string(param_path);\nDECLARE_string(model_input_names);\nDECLARE_string(model_output_names);\nDECLARE_string(model_cache_names);\nDECLARE_string(model_cache_shapes);\n#ifdef USE_ONNX\nDECLARE_bool(with_onnx_model);\n#endif\n\nnamespace ppspeech {\n\nstruct ModelOptions {\n    // common\n    int subsample_rate{1};\n    bool use_gpu{false};\n    std::string model_path;\n#ifdef USE_ONNX\n    bool with_onnx_model{false};\n#endif\n\n    static ModelOptions InitFromFlags() {\n        ModelOptions opts;\n        opts.subsample_rate = FLAGS_subsampling_rate;\n        LOG(INFO) << \"subsampling rate: \" << opts.subsample_rate;\n        opts.model_path = FLAGS_model_path;\n        LOG(INFO) << \"model path: \" << opts.model_path;\n#ifdef USE_ONNX\n        opts.with_onnx_model = FLAGS_with_onnx_model;\n        LOG(INFO) << \"with onnx model: \" << opts.with_onnx_model;\n#endif\n        return opts;\n    }\n};\n\nstruct NnetOut {\n    // nnet out. maybe logprob or prob. Almost time this is logprob.\n    std::vector<kaldi::BaseFloat> logprobs;\n    int32 vocab_dim;\n\n    // nnet state. Only using in Attention model.\n    std::vector<std::vector<kaldi::BaseFloat>> encoder_outs;\n\n    NnetOut() : logprobs({}), vocab_dim(-1), encoder_outs({}) {}\n};\n\n\nclass NnetInterface {\n  public:\n    virtual ~NnetInterface() {}\n\n    // forward feat with nnet.\n    // nnet do not cache feats, feats cached by frontend.\n    // nnet cache model state, i.e. encoder_outs, att_cache, cnn_cache,\n    // frame_offset.\n    virtual void FeedForward(const std::vector<kaldi::BaseFloat>& features,\n                             const int32& feature_dim,\n                             NnetOut* out) = 0;\n\n    virtual void AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                                    float reverse_weight,\n                                    std::vector<float>* rescoring_score) = 0;\n\n    // reset nnet state, e.g. nnet_logprob_cache_, offset_, encoder_outs_.\n    virtual void Reset() = 0;\n\n    // true, nnet output is logprob; otherwise is prob,\n    virtual bool IsLogProb() = 0;\n\n    // using to get encoder outs. e.g. seq2seq with Attention model.\n    virtual void EncoderOuts(\n        std::vector<std::vector<kaldi::BaseFloat>>* encoder_out) const = 0;\n};\n\n\nclass NnetBase : public NnetInterface {\n  public:\n    int SubsamplingRate() const { return subsampling_rate_; }\n    virtual std::shared_ptr<NnetBase> Clone() const = 0;\n  protected:\n    int subsampling_rate_{1};\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/nnet_producer.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"nnet/nnet_producer.h\"\n\n#include \"matrix/kaldi-matrix.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing std::vector;\n\nNnetProducer::NnetProducer(std::shared_ptr<NnetBase> nnet,\n                           std::shared_ptr<FrontendInterface> frontend,\n                           float blank_threshold)\n    : nnet_(nnet), frontend_(frontend), blank_threshold_(blank_threshold) {\n    Reset();\n}\n\nvoid NnetProducer::Accept(const std::vector<kaldi::BaseFloat>& inputs) {\n    frontend_->Accept(inputs);\n}\n\nvoid NnetProducer::Acceptlikelihood(\n    const kaldi::Matrix<BaseFloat>& likelihood) {\n    std::vector<BaseFloat> prob;\n    prob.resize(likelihood.NumCols());\n    for (size_t idx = 0; idx < likelihood.NumRows(); ++idx) {\n        for (size_t col = 0; col < likelihood.NumCols(); ++col) {\n            prob[col] = likelihood(idx, col);\n        }\n        cache_.push_back(prob);\n    }\n}\n\nbool NnetProducer::Read(std::vector<kaldi::BaseFloat>* nnet_prob) {\n    bool flag = cache_.pop(nnet_prob);\n    return flag;\n}\n\nbool NnetProducer::Compute() {\n    vector<BaseFloat> features;\n    if (frontend_ == NULL || frontend_->Read(&features) == false) {\n        // no feat or frontend_ not init.\n        if (frontend_->IsFinished() == true) {\n            finished_ = true;\n        }\n        return false;\n    }\n    CHECK_GE(frontend_->Dim(), 0);\n    VLOG(1) << \"Forward in \" << features.size() / frontend_->Dim() << \" feats.\";\n\n    NnetOut out;\n    nnet_->FeedForward(features, frontend_->Dim(), &out);\n    int32& vocab_dim = out.vocab_dim;\n    size_t nframes = out.logprobs.size() / vocab_dim;\n    VLOG(1) << \"Forward out \" << nframes << \" decoder frames.\";\n    for (size_t idx = 0; idx < nframes; ++idx) {\n        std::vector<BaseFloat> logprob(\n            out.logprobs.data() + idx * vocab_dim,\n            out.logprobs.data() + (idx + 1) * vocab_dim);\n        // process blank prob\n        float blank_prob = std::exp(logprob[0]);\n        if (blank_prob > blank_threshold_) {\n            last_frame_logprob_ = logprob;\n            is_last_frame_skip_ = true;\n            continue;\n        } else {\n            int cur_max = std::max(logprob.begin(), logprob.end()) - logprob.begin();\n            if (cur_max == last_max_elem_ && cur_max != 0 && is_last_frame_skip_) {\n                cache_.push_back(last_frame_logprob_);\n                last_max_elem_ = cur_max;\n            }\n            last_max_elem_ = cur_max;\n            is_last_frame_skip_ = false; \n            cache_.push_back(logprob);\n        }\n    }\n    return true;\n}\n\nvoid NnetProducer::AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                                      float reverse_weight,\n                                      std::vector<float>* rescoring_score) {\n    nnet_->AttentionRescoring(hyps, reverse_weight, rescoring_score);\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/nnet_producer.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"base/safe_queue.h\"\n#include \"frontend/frontend_itf.h\"\n#include \"nnet/nnet_itf.h\"\n\nnamespace ppspeech {\n\nclass NnetProducer {\n  public:\n    explicit NnetProducer(std::shared_ptr<NnetBase> nnet,\n                          std::shared_ptr<FrontendInterface> frontend,\n                          float blank_threshold);\n    // Feed feats or waves\n    void Accept(const std::vector<kaldi::BaseFloat>& inputs);\n\n    void Acceptlikelihood(const kaldi::Matrix<BaseFloat>& likelihood);\n\n    // nnet\n    bool Read(std::vector<kaldi::BaseFloat>* nnet_prob);\n\n    bool Empty() const { return cache_.empty(); }\n\n    void SetInputFinished() {\n        LOG(INFO) << \"set finished\";\n        frontend_->SetFinished();\n    }\n\n    // the compute thread exit\n    bool IsFinished() const { \n        return (frontend_->IsFinished() && finished_); \n    }\n\n    ~NnetProducer() {}\n\n    void Reset() {\n        if (frontend_ != NULL) frontend_->Reset();\n        if (nnet_ != NULL) nnet_->Reset();\n        cache_.clear();\n        finished_ = false;\n    }\n\n    void AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                            float reverse_weight,\n                            std::vector<float>* rescoring_score);\n\n    bool Compute();\n  private:\n\n    std::shared_ptr<FrontendInterface> frontend_;\n    std::shared_ptr<NnetBase> nnet_;\n    SafeQueue<std::vector<kaldi::BaseFloat>> cache_;\n    std::vector<BaseFloat> last_frame_logprob_;\n    bool is_last_frame_skip_ = false;\n    int last_max_elem_ = -1;\n    float blank_threshold_ = 0.0;\n    bool finished_;\n\n    DISALLOW_COPY_AND_ASSIGN(NnetProducer);\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_nnet.cc",
    "content": "// Copyright 2022 Horizon Robotics. All Rights Reserved.\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/asr_model.cc\n\n#include \"nnet/u2_nnet.h\"\n#include <type_traits>\n\n#ifdef WITH_PROFILING\n#include \"paddle/fluid/platform/profiler.h\"\nusing paddle::platform::RecordEvent;\nusing paddle::platform::TracerEventType;\n#endif  // end WITH_PROFILING\n\nnamespace ppspeech {\n\n\nvoid U2Nnet::LoadModel(const std::string& model_path_w_prefix) {\n    paddle::jit::utils::InitKernelSignatureMap();\n\n#ifdef WITH_GPU\n    dev_ = phi::GPUPlace();\n#else\n    dev_ = phi::CPUPlace();\n#endif\n    paddle::jit::Layer model = paddle::jit::Load(model_path_w_prefix, dev_);\n    model_ = std::make_shared<paddle::jit::Layer>(std::move(model));\n\n    subsampling_rate_ = model_->Attribute<int>(\"subsampling_rate\");\n    right_context_ = model_->Attribute<int>(\"right_context\");\n    sos_ = model_->Attribute<int>(\"sos_symbol\");\n    eos_ = model_->Attribute<int>(\"eos_symbol\");\n    is_bidecoder_ = model_->Attribute<int>(\"is_bidirectional_decoder\");\n\n    forward_encoder_chunk_ = model_->Function(\"forward_encoder_chunk\");\n    forward_attention_decoder_ = model_->Function(\"forward_attention_decoder\");\n    ctc_activation_ = model_->Function(\"ctc_activation\");\n    CHECK(forward_encoder_chunk_.IsValid());\n    CHECK(forward_attention_decoder_.IsValid());\n    CHECK(ctc_activation_.IsValid());\n\n    LOG(INFO) << \"Paddle Model Info: \";\n    LOG(INFO) << \"\\tsubsampling_rate \" << subsampling_rate_;\n    LOG(INFO) << \"\\tright context \" << right_context_;\n    LOG(INFO) << \"\\tsos \" << sos_;\n    LOG(INFO) << \"\\teos \" << eos_;\n    LOG(INFO) << \"\\tis bidecoder \" << is_bidecoder_ << std::endl;\n\n    Warmup();\n}\n\nvoid U2Nnet::Warmup() {\n#ifdef WITH_PROFILING\n    RecordEvent event(\"warmup\", TracerEventType::UserDefined, 1);\n#endif\n\n    {\n#ifdef WITH_PROFILING\n        RecordEvent event(\n            \"warmup-encoder-ctc\", TracerEventType::UserDefined, 1);\n#endif\n        int feat_dim = 80;\n        int frame_num = 16 * 4 + 3;  // chunk_size * downsample_rate +\n                                     // (receptive_field - downsample_rate)\n        paddle::Tensor feats = paddle::full(\n            {1, frame_num, feat_dim}, 0.12f, paddle::DataType::FLOAT32);\n        paddle::Tensor offset = paddle::zeros({1}, paddle::DataType::INT32);\n        paddle::Tensor att_cache =\n            paddle::zeros({0, 0, 0, 0}, paddle::DataType::FLOAT32);\n        paddle::Tensor cnn_cache =\n            paddle::zeros({0, 0, 0, 0}, paddle::DataType::FLOAT32);\n        std::vector<paddle::Tensor> inputs = {\n            feats, offset, /*required_cache_size, */ att_cache, cnn_cache};\n        std::vector<paddle::Tensor> outputs = forward_encoder_chunk_(inputs);\n\n        auto chunk_out = outputs[0];\n        inputs = std::move(std::vector<paddle::Tensor>({chunk_out}));\n        outputs = ctc_activation_(inputs);\n    }\n\n    {\n#ifdef WITH_PROFILING\n        RecordEvent event(\"warmup-decoder\", TracerEventType::UserDefined, 1);\n#endif\n        auto hyps =\n            paddle::full({10, 8}, 10, paddle::DataType::INT64, phi::CPUPlace());\n        auto hyps_lens =\n            paddle::full({10}, 8, paddle::DataType::INT64, phi::CPUPlace());\n        auto encoder_out = paddle::ones(\n            {1, 20, 512}, paddle::DataType::FLOAT32, phi::CPUPlace());\n\n        std::vector<paddle::Tensor> inputs{\n            hyps, hyps_lens, encoder_out};\n\n        std::vector<paddle::Tensor> outputs =\n            forward_attention_decoder_(inputs);\n    }\n\n    Reset();\n}\n\nU2Nnet::U2Nnet(const ModelOptions& opts) : opts_(opts) {\n    LoadModel(opts_.model_path);\n}\n\n// shallow copy\nU2Nnet::U2Nnet(const U2Nnet& other) {\n    // copy meta\n    chunk_size_ = other.chunk_size_;\n    num_left_chunks_ = other.num_left_chunks_;\n    offset_ = other.offset_;\n\n    // copy model ptr\n    // model_ = other.model_->Clone();\n    // hack, fix later\n    #ifdef WITH_GPU\n        dev_ = phi::GPUPlace();\n    #else\n        dev_ = phi::CPUPlace();\n    #endif\n    paddle::jit::Layer model = paddle::jit::Load(other.opts_.model_path, dev_);\n    model_ = std::make_shared<paddle::jit::Layer>(std::move(model));\n    ctc_activation_ = model_->Function(\"ctc_activation\");\n    subsampling_rate_ = model_->Attribute<int>(\"subsampling_rate\");\n    right_context_ = model_->Attribute<int>(\"right_context\");\n    sos_ = model_->Attribute<int>(\"sos_symbol\");\n    eos_ = model_->Attribute<int>(\"eos_symbol\");\n    is_bidecoder_ = model_->Attribute<int>(\"is_bidirectional_decoder\");\n\n    forward_encoder_chunk_ = model_->Function(\"forward_encoder_chunk\");\n    forward_attention_decoder_ = model_->Function(\"forward_attention_decoder\");\n    ctc_activation_ = model_->Function(\"ctc_activation\");\n    CHECK(forward_encoder_chunk_.IsValid());\n    CHECK(forward_attention_decoder_.IsValid());\n    CHECK(ctc_activation_.IsValid());\n\n    LOG(INFO) << \"Paddle Model Info: \";\n    LOG(INFO) << \"\\tsubsampling_rate \" << subsampling_rate_;\n    LOG(INFO) << \"\\tright context \" << right_context_;\n    LOG(INFO) << \"\\tsos \" << sos_;\n    LOG(INFO) << \"\\teos \" << eos_;\n    LOG(INFO) << \"\\tis bidecoder \" << is_bidecoder_ << std::endl;\n\n\n    // ignore inner states\n}\n\nstd::shared_ptr<NnetBase> U2Nnet::Clone() const {\n    auto asr_model = std::make_shared<U2Nnet>(*this);\n    // reset inner state for new decoding\n    asr_model->Reset();\n    return asr_model;\n}\n\nvoid U2Nnet::Reset() {\n    offset_ = 0;\n\n    att_cache_ =\n        std::move(paddle::zeros({0, 0, 0, 0}, paddle::DataType::FLOAT32));\n    cnn_cache_ =\n        std::move(paddle::zeros({0, 0, 0, 0}, paddle::DataType::FLOAT32));\n\n    encoder_outs_.clear();\n    VLOG(1) << \"FeedForward cost: \" << cost_time_ << \" sec. \";\n    VLOG(3) << \"u2nnet reset\";\n}\n\n// Debug API\nvoid U2Nnet::FeedEncoderOuts(const paddle::Tensor& encoder_out) {\n    // encoder_out (T,D)\n    encoder_outs_.clear();\n    encoder_outs_.push_back(encoder_out);\n}\n\n\nvoid U2Nnet::FeedForward(const std::vector<BaseFloat>& features,\n                         const int32& feature_dim,\n                         NnetOut* out) {\n    kaldi::Timer timer;\n\n    std::vector<kaldi::BaseFloat> ctc_probs;\n    ForwardEncoderChunkImpl(\n        features, feature_dim, &out->logprobs, &out->vocab_dim);\n    float forward_chunk_time = timer.Elapsed();\n    VLOG(1) << \"FeedForward cost: \" << forward_chunk_time << \" sec. \"\n            << features.size() / feature_dim << \" frames.\";\n    cost_time_ += forward_chunk_time;\n}\n\n\nvoid U2Nnet::ForwardEncoderChunkImpl(\n    const std::vector<kaldi::BaseFloat>& chunk_feats,\n    const int32& feat_dim,\n    std::vector<kaldi::BaseFloat>* out_prob,\n    int32* vocab_dim) {\n#ifdef WITH_PROFILING\n    RecordEvent event(\n        \"ForwardEncoderChunkImpl\", TracerEventType::UserDefined, 1);\n#endif\n\n    // 1. splice cached_feature, and chunk_feats\n    //  First dimension is B, which is 1.\n    // int num_frames = cached_feats_.size() + chunk_feats.size();\n\n    int num_frames = chunk_feats.size() / feat_dim;\n    VLOG(3) << \"num_frames: \" << num_frames;\n    VLOG(3) << \"feat_dim: \" << feat_dim;\n\n    // feats (B=1,T,D)\n    paddle::Tensor feats =\n        paddle::zeros({1, num_frames, feat_dim}, paddle::DataType::FLOAT32);\n    float* feats_ptr = feats.mutable_data<float>();\n\n    // not cache feature in nnet\n    CHECK_EQ(cached_feats_.size(), 0);\n    CHECK_EQ((std::is_same<float, kaldi::BaseFloat>::value), true);\n    std::memcpy(feats_ptr,\n                chunk_feats.data(),\n                chunk_feats.size() * sizeof(kaldi::BaseFloat));\n\n    VLOG(3) << \"feats shape: \" << feats.shape()[0] << \", \" << feats.shape()[1]\n            << \", \" << feats.shape()[2];\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"feat\", std::ios_base::app | std::ios_base::out);\n        path << offset_;\n        std::ofstream feat_fobj(path.str().c_str(), std::ios::out);\n        CHECK(feat_fobj.is_open());\n        // feat_fobj << feats.shape()[0] << \" \" << feats.shape()[1] << \" \"\n        //           << feats.shape()[2] << \"\\n\";\n        for (int i = 0; i < feats.numel(); i++) {\n            feat_fobj << std::setprecision(18) << feats_ptr[i] << \" \";\n            if ((i + 1) % feat_dim == 0) {\n                feat_fobj << \"\\n\";\n            }\n        }\n        feat_fobj << \"\\n\";\n    }\n#endif\n\n// Endocer chunk forward\n#ifdef WITH_GPU\n    feats = feats.copy_to(paddle::GPUPlace(), /*blocking*/ false);\n    att_cache_ = att_cache_.copy_to(paddle::GPUPlace()), /*blocking*/ false;\n    cnn_cache_ = cnn_cache_.copy_to(Paddle::GPUPlace(), /*blocking*/ false);\n#endif\n\n    int required_cache_size = num_left_chunks_ * chunk_size_;  // -1 * 16\n    // must be scalar, but paddle do not have scalar.\n    paddle::Tensor offset = paddle::full({1}, offset_, paddle::DataType::INT32);\n    // freeze `required_cache_size` in graph, so not specific it in function\n    // call.\n    std::vector<paddle::Tensor> inputs = {\n        feats, offset, /*required_cache_size, */ att_cache_, cnn_cache_};\n    CHECK_EQ(inputs.size(), 4);\n    std::vector<paddle::Tensor> outputs = forward_encoder_chunk_(inputs);\n    CHECK_EQ(outputs.size(), 3);\n\n#ifdef WITH_GPU\n    paddle::Tensor chunk_out = outputs[0].copy_to(paddle::CPUPlace());\n    att_cache_ = outputs[1].copy_to(paddle::CPUPlace());\n    cnn_cache_ = outputs[2].copy_to(paddle::CPUPlace());\n#else\n    paddle::Tensor chunk_out = outputs[0];\n    att_cache_ = outputs[1];\n    cnn_cache_ = outputs[2];\n#endif\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_logits\",\n                               std::ios_base::app | std::ios_base::out);\n        auto i = offset_ - chunk_out.shape()[1];\n        path << std::max(i, 0L);\n        std::ofstream logits_fobj(path.str().c_str(), std::ios::out);\n        CHECK(logits_fobj.is_open());\n        logits_fobj << chunk_out.shape()[0] << \" \" << chunk_out.shape()[1]\n                    << \" \" << chunk_out.shape()[2] << \"\\n\";\n        const float* chunk_out_ptr = chunk_out.data<float>();\n        logits_fobj << chunk_out_ptr << std::endl;\n        for (int i = 0; i < chunk_out.numel(); i++) {\n            logits_fobj << chunk_out_ptr[i] << \" \";\n        }\n        logits_fobj << \"\\n\";\n    }\n#endif  // end TEST_DEBUG\n\n    // current offset in decoder frame\n    // not used in nnet\n    offset_ += chunk_out.shape()[1];\n    VLOG(2) << \"encoder out chunk size: \" << chunk_out.shape()[1]\n            << \" total: \" << offset_;\n\n\n    // collects encoder outs.\n    encoder_outs_.push_back(chunk_out);\n    VLOG(2) << \"encoder_outs_ size: \" << encoder_outs_.size();\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_logits_list\",\n                               std::ios_base::app | std::ios_base::out);\n        path << offset_ - encoder_outs_[0].shape()[1];\n        std::ofstream logits_out_fobj(path.str().c_str(), std::ios::out);\n        CHECK(logits_out_fobj.is_open());\n        logits_out_fobj << encoder_outs_[0].shape()[0] << \" \"\n                        << encoder_outs_[0].shape()[1] << \" \"\n                        << encoder_outs_[0].shape()[2] << \"\\n\";\n        const float* encoder_outs_ptr = encoder_outs_[0].data<float>();\n        logits_out_fobj << encoder_outs_ptr << std::endl;\n        for (int i = 0; i < encoder_outs_[0].numel(); i++) {\n            logits_out_fobj << encoder_outs_ptr[i] << \" \";\n        }\n        logits_out_fobj << \"\\n\";\n    }\n#endif  // end TEST_DEBUG\n\n#ifdef WITH_GPU\n\n#error \"Not implementation.\"\n\n#else\n    // compute ctc_activation == log_softmax\n    inputs.clear();\n    outputs.clear();\n    inputs.push_back(chunk_out);\n    CHECK_EQ(inputs.size(), 1);\n    outputs = ctc_activation_(inputs);\n    CHECK_EQ(outputs.size(), 1);\n    paddle::Tensor ctc_log_probs = outputs[0];\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_logprob\",\n                               std::ios_base::app | std::ios_base::out);\n        path << offset_ - chunk_out.shape()[1];\n\n        std::ofstream logprob_fobj(path.str().c_str(), std::ios::out);\n        CHECK(logprob_fobj.is_open());\n        logprob_fobj << ctc_log_probs.shape()[0] << \" \"\n                     << ctc_log_probs.shape()[1] << \" \"\n                     << ctc_log_probs.shape()[2] << \"\\n\";\n        const float* logprob_ptr = ctc_log_probs.data<float>();\n        for (int i = 0; i < ctc_log_probs.numel(); i++) {\n            logprob_fobj << logprob_ptr[i] << \" \";\n            if ((i + 1) % ctc_log_probs.shape()[2] == 0) {\n                logprob_fobj << \"\\n\";\n            }\n        }\n        logprob_fobj << \"\\n\";\n    }\n#endif  // end TEST_DEBUG\n\n#endif  // end WITH_GPU\n\n    // Copy to output, (B=1,T,D)\n    std::vector<int64_t> ctc_log_probs_shape = ctc_log_probs.shape();\n    CHECK_EQ(ctc_log_probs_shape.size(), 3);\n    int B = ctc_log_probs_shape[0];\n    CHECK_EQ(B, 1);\n    int T = ctc_log_probs_shape[1];\n    int D = ctc_log_probs_shape[2];\n    *vocab_dim = D;\n\n    float* ctc_log_probs_ptr = ctc_log_probs.data<float>();\n\n    out_prob->resize(T * D);\n    std::memcpy(\n        out_prob->data(), ctc_log_probs_ptr, T * D * sizeof(kaldi::BaseFloat));\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_logits_list_ctc\",\n                               std::ios_base::app | std::ios_base::out);\n        path << offset_ - encoder_outs_[0].shape()[1];\n        std::ofstream logits_out_fobj(path.str().c_str(), std::ios::out);\n        CHECK(logits_out_fobj.is_open());\n        logits_out_fobj << encoder_outs_[0].shape()[0] << \" \"\n                        << encoder_outs_[0].shape()[1] << \" \"\n                        << encoder_outs_[0].shape()[2] << \"\\n\";\n        const float* encoder_outs_ptr = encoder_outs_[0].data<float>();\n        logits_out_fobj << encoder_outs_ptr << std::endl;\n        for (int i = 0; i < encoder_outs_[0].numel(); i++) {\n            logits_out_fobj << encoder_outs_ptr[i] << \" \";\n        }\n        logits_out_fobj << \"\\n\";\n    }\n#endif  // end TEST_DEBUG\n\n    return;\n}\n\nfloat U2Nnet::ComputePathScore(const paddle::Tensor& prob,\n                               const std::vector<int>& hyp,\n                               int eos) {\n    // sum `hyp` path scores in `prob`\n    // prob (1, Umax, V)\n    // hyp (U,)\n    float score = 0.0f;\n    std::vector<int64_t> dims = prob.shape();\n    CHECK_EQ(dims.size(), 3);\n    VLOG(2) << \"prob shape: \" << dims[0] << \", \" << dims[1] << \", \" << dims[2];\n    CHECK_EQ(dims[0], 1);\n    int vocab_dim = static_cast<int>(dims[2]);\n\n    const float* prob_ptr = prob.data<float>();\n    for (size_t i = 0; i < hyp.size(); ++i) {\n        const float* row = prob_ptr + i * vocab_dim;\n        score += row[hyp[i]];\n    }\n    const float* row = prob_ptr + hyp.size() * vocab_dim;\n    score += row[eos];\n    return score;\n}\n\n\nvoid U2Nnet::AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                                float reverse_weight,\n                                std::vector<float>* rescoring_score) {\n#ifdef WITH_PROFILING\n    RecordEvent event(\"AttentionRescoring\", TracerEventType::UserDefined, 1);\n#endif\n    CHECK(rescoring_score != nullptr);\n\n    int num_hyps = hyps.size();\n    rescoring_score->resize(num_hyps, 0.0f);\n\n    if (num_hyps == 0) return;\n    VLOG(2) << \"num hyps: \" << num_hyps;\n\n    if (encoder_outs_.size() == 0) {\n        // no encoder outs\n        std::cerr << \"encoder_outs_.size() is zero. Please check it.\"\n                  << std::endl;\n        return;\n    }\n\n    // prepare input\n    paddle::Tensor hyps_lens =\n        paddle::zeros({num_hyps}, paddle::DataType::INT64);\n    int64_t* hyps_len_ptr = hyps_lens.mutable_data<int64_t>();\n    int max_hyps_len = 0;\n    for (size_t i = 0; i < num_hyps; ++i) {\n        int len = hyps[i].size() + 1;  // eos\n        max_hyps_len = std::max(max_hyps_len, len);\n        hyps_len_ptr[i] = static_cast<int64_t>(len);\n    }\n    VLOG(2) << \"max_hyps_len: \" << max_hyps_len;\n\n    paddle::Tensor hyps_tensor =\n        paddle::full({num_hyps, max_hyps_len}, eos_, paddle::DataType::INT64);\n    int64_t* hyps_ptr = hyps_tensor.mutable_data<int64_t>();\n    for (size_t i = 0; i < num_hyps; ++i) {\n        const std::vector<int>& hyp = hyps[i];\n        int64_t* row = hyps_ptr + max_hyps_len * i;\n        row[0] = sos_;\n        for (size_t j = 0; j < hyp.size(); ++j) {\n            row[j + 1] = hyp[j];\n        }\n    }\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_logits_concat\",\n                               std::ios_base::app | std::ios_base::out);\n        for (int j = 0; j < encoder_outs_.size(); j++) {\n            path << j;\n            std::ofstream logits_out_fobj(path.str().c_str(), std::ios::out);\n            CHECK(logits_out_fobj.is_open());\n            logits_out_fobj << encoder_outs_[j].shape()[0] << \" \"\n                            << encoder_outs_[j].shape()[1] << \" \"\n                            << encoder_outs_[j].shape()[2] << \"\\n\";\n            const float* encoder_outs_ptr = encoder_outs_[j].data<float>();\n            for (int i = 0; i < encoder_outs_[j].numel(); i++) {\n                logits_out_fobj << encoder_outs_ptr[i] << \" \";\n            }\n            logits_out_fobj << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n    // forward attention decoder by hyps and correspoinding encoder_outs_\n    paddle::Tensor encoder_out = paddle::concat(encoder_outs_, 1);\n    VLOG(2) << \"encoder_outs_ size: \" << encoder_outs_.size();\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_out0\",\n                               std::ios_base::app | std::ios_base::out);\n        std::ofstream encoder_out_fobj(path.str().c_str(), std::ios::out);\n        CHECK(encoder_out_fobj.is_open());\n\n        encoder_out_fobj << encoder_outs_[0].shape()[0] << \" \"\n                         << encoder_outs_[0].shape()[1] << \" \"\n                         << encoder_outs_[0].shape()[2] << \"\\n\";\n        const float* enc_logprob_ptr = encoder_outs_[0].data<float>();\n\n        size_t size = encoder_outs_[0].numel();\n        for (int i = 0; i < size; i++) {\n            encoder_out_fobj << enc_logprob_ptr[i] << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"encoder_out\",\n                               std::ios_base::app | std::ios_base::out);\n        std::ofstream encoder_out_fobj(path.str().c_str(), std::ios::out);\n        CHECK(encoder_out_fobj.is_open());\n\n        encoder_out_fobj << encoder_out.shape()[0] << \" \"\n                         << encoder_out.shape()[1] << \" \"\n                         << encoder_out.shape()[2] << \"\\n\";\n        const float* enc_logprob_ptr = encoder_out.data<float>();\n\n        size_t size = encoder_out.numel();\n        for (int i = 0; i < size; i++) {\n            encoder_out_fobj << enc_logprob_ptr[i] << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n    std::vector<paddle::Tensor> inputs{\n        hyps_tensor, hyps_lens, encoder_out};\n    std::vector<paddle::Tensor> outputs = forward_attention_decoder_(inputs);\n    CHECK_EQ(outputs.size(), 2);\n\n    // (B, Umax, V)\n    paddle::Tensor probs = outputs[0];\n    std::vector<int64_t> probs_shape = probs.shape();\n    CHECK_EQ(probs_shape.size(), 3);\n    CHECK_EQ(probs_shape[0], num_hyps);\n    CHECK_EQ(probs_shape[1], max_hyps_len);\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"decoder_logprob\",\n                               std::ios_base::app | std::ios_base::out);\n        std::ofstream dec_logprob_fobj(path.str().c_str(), std::ios::out);\n        CHECK(dec_logprob_fobj.is_open());\n\n        dec_logprob_fobj << probs.shape()[0] << \" \" << probs.shape()[1] << \" \"\n                         << probs.shape()[2] << \"\\n\";\n        const float* dec_logprob_ptr = probs.data<float>();\n\n        size_t size = probs.numel();\n        for (int i = 0; i < size; i++) {\n            dec_logprob_fobj << dec_logprob_ptr[i] << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"hyps_lens\",\n                               std::ios_base::app | std::ios_base::out);\n        std::ofstream hyps_len_fobj(path.str().c_str(), std::ios::out);\n        CHECK(hyps_len_fobj.is_open());\n\n        const int64_t* hyps_lens_ptr = hyps_lens.data<int64_t>();\n\n        size_t size = hyps_lens.numel();\n        for (int i = 0; i < size; i++) {\n            hyps_len_fobj << hyps_lens_ptr[i] << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n#ifdef PPS_DEBUG\n    {\n        std::stringstream path(\"hyps_tensor\",\n                               std::ios_base::app | std::ios_base::out);\n        std::ofstream hyps_tensor_fobj(path.str().c_str(), std::ios::out);\n        CHECK(hyps_tensor_fobj.is_open());\n\n        const int64_t* hyps_tensor_ptr = hyps_tensor.data<int64_t>();\n\n        size_t size = hyps_tensor.numel();\n        for (int i = 0; i < size; i++) {\n            hyps_tensor_fobj << hyps_tensor_ptr[i] << \"\\n\";\n        }\n    }\n#endif  // end TEST_DEBUG\n\n    paddle::Tensor r_probs = outputs[1];\n    std::vector<int64_t> r_probs_shape = r_probs.shape();\n    if (is_bidecoder_ && reverse_weight > 0) {\n        CHECK_EQ(r_probs_shape.size(), 3);\n        CHECK_EQ(r_probs_shape[0], num_hyps);\n        CHECK_EQ(r_probs_shape[1], max_hyps_len);\n    } else {\n        // dump r_probs\n        CHECK_EQ(r_probs_shape.size(), 1);\n        //CHECK_EQ(r_probs_shape[0], 1) << r_probs_shape[0];\n    }\n\n    // compute rescoring score\n    using IntArray = paddle::experimental::IntArray;\n    std::vector<paddle::Tensor> probs_v =\n        paddle::experimental::split_with_num(probs, num_hyps, 0);\n    VLOG(2) << \"split prob: \" << probs_v.size() << \" \"\n            << probs_v[0].shape().size() << \" 0: \" << probs_v[0].shape()[0]\n            << \", \" << probs_v[0].shape()[1] << \", \" << probs_v[0].shape()[2];\n    //CHECK(static_cast<int>(probs_v.size()) == num_hyps)\n     //   << \": is \" << probs_v.size() << \" expect: \" << num_hyps;\n\n    std::vector<paddle::Tensor> r_probs_v;\n    if (is_bidecoder_ && reverse_weight > 0) {\n        r_probs_v = paddle::experimental::split_with_num(r_probs, num_hyps, 0);\n        //CHECK(static_cast<int>(r_probs_v.size()) == num_hyps)\n         //   << \"r_probs_v size: is \" << r_probs_v.size()\n          //  << \" expect: \" << num_hyps;\n    }\n\n    for (int i = 0; i < num_hyps; ++i) {\n        const std::vector<int>& hyp = hyps[i];\n\n        // left-to-right decoder score\n        float score = 0.0f;\n        score = ComputePathScore(probs_v[i], hyp, eos_);\n\n        // right-to-left decoder score\n        float r_score = 0.0f;\n        if (is_bidecoder_ && reverse_weight > 0) {\n            std::vector<int> r_hyp(hyp.size());\n            std::reverse_copy(hyp.begin(), hyp.end(), r_hyp.begin());\n            r_score = ComputePathScore(r_probs_v[i], r_hyp, eos_);\n        }\n\n        // combinded left-to-right and right-to-lfet score\n        (*rescoring_score)[i] =\n            score * (1 - reverse_weight) + r_score * reverse_weight;\n        VLOG(3) << \"hyp \" << i << \" \" << hyp.size() << \" score: \" << score\n                << \" r_score: \" << r_score\n                << \" reverse_weight: \" << reverse_weight\n                << \" final score: \" << (*rescoring_score)[i];\n    }\n}\n\n\nvoid U2Nnet::EncoderOuts(\n    std::vector<std::vector<kaldi::BaseFloat>>* encoder_out) const {\n    // list of (B=1,T,D)\n    int size = encoder_outs_.size();\n    VLOG(3) << \"encoder_outs_ size: \" << size;\n\n    for (int i = 0; i < size; i++) {\n        const paddle::Tensor& item = encoder_outs_[i];\n        const std::vector<int64_t> shape = item.shape();\n        CHECK_EQ(shape.size(), 3);\n        const int& B = shape[0];\n        const int& T = shape[1];\n        const int& D = shape[2];\n        //CHECK(B == 1) << \"Only support batch one.\";\n        VLOG(3) << \"encoder out \" << i << \" shape: (\" << B << \",\" << T << \",\"\n                << D << \")\";\n\n        const float* this_tensor_ptr = item.data<float>();\n        for (int j = 0; j < T; j++) {\n            const float* cur = this_tensor_ptr + j * D;\n            std::vector<kaldi::BaseFloat> out(D);\n            std::memcpy(out.data(), cur, D * sizeof(kaldi::BaseFloat));\n            encoder_out->emplace_back(out);\n        }\n    }\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_nnet.h",
    "content": "// Copyright 2022 Horizon Robotics. All Rights Reserved.\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/asr_model.h\n#pragma once\n\n#include \"base/common.h\"\n#include \"matrix/kaldi-matrix.h\"\n#include \"nnet/nnet_itf.h\"\n#include \"paddle/extension.h\"\n#include \"paddle/jit/all.h\"\n#include \"paddle/phi/api/all.h\"\n\nnamespace ppspeech {\n\n\nclass U2NnetBase : public NnetBase {\n  public:\n    virtual int Context() const { return right_context_ + 1; }\n    virtual int RightContext() const { return right_context_; }\n\n    virtual int EOS() const { return eos_; }\n    virtual int SOS() const { return sos_; }\n    virtual int IsBidecoder() const { return is_bidecoder_; }\n    // current offset in decoder frame\n    virtual int Offset() const { return offset_; }\n    virtual void SetChunkSize(int chunk_size) { chunk_size_ = chunk_size; }\n    virtual void SetNumLeftChunks(int num_left_chunks) {\n        num_left_chunks_ = num_left_chunks;\n    }\n\n    virtual std::shared_ptr<NnetBase> Clone() const = 0;\n\n  protected:\n    virtual void ForwardEncoderChunkImpl(\n        const std::vector<kaldi::BaseFloat>& chunk_feats,\n        const int32& feat_dim,\n        std::vector<kaldi::BaseFloat>* ctc_probs,\n        int32* vocab_dim) = 0;\n\n  protected:\n    // model specification\n    int right_context_{0};\n\n    int sos_{0};\n    int eos_{0};\n\n    bool is_bidecoder_{false};\n\n    int chunk_size_{16};  // num of decoder frames. If chunk_size > 0, streaming\n                          // case. Otherwise, none streaming case\n    int num_left_chunks_{-1};  // -1 means all left chunks\n\n    // asr decoder state, not used in nnet\n    int offset_{0};  // current offset in encoder output time stamp. Used by\n                     // position embedding.\n    std::vector<std::vector<float>> cached_feats_{};  // features cache\n};\n\n\nclass U2Nnet : public U2NnetBase {\n  public:\n    explicit U2Nnet(const ModelOptions& opts);\n    U2Nnet(const U2Nnet& other);\n\n    void FeedForward(const std::vector<kaldi::BaseFloat>& features,\n                     const int32& feature_dim,\n                     NnetOut* out) override;\n\n    void Reset() override;\n\n    bool IsLogProb() override { return true; }\n\n    void Dim();\n\n    void LoadModel(const std::string& model_path_w_prefix);\n    void Warmup();\n\n    std::shared_ptr<paddle::jit::Layer> model() const { return model_; }\n\n    std::shared_ptr<NnetBase> Clone() const override;\n\n    void ForwardEncoderChunkImpl(\n        const std::vector<kaldi::BaseFloat>& chunk_feats,\n        const int32& feat_dim,\n        std::vector<kaldi::BaseFloat>* ctc_probs,\n        int32* vocab_dim) override;\n\n    float ComputePathScore(const paddle::Tensor& prob,\n                           const std::vector<int>& hyp,\n                           int eos);\n\n    void AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                            float reverse_weight,\n                            std::vector<float>* rescoring_score) override;\n\n    // debug\n    void FeedEncoderOuts(const paddle::Tensor& encoder_out);\n\n    void EncoderOuts(\n        std::vector<std::vector<kaldi::BaseFloat>>* encoder_out) const;\n\n    ModelOptions opts_; // hack, fix later\n  private:\n\n    phi::Place dev_;\n    std::shared_ptr<paddle::jit::Layer> model_{nullptr};\n    std::vector<paddle::Tensor> encoder_outs_;\n    // transformer/conformer attention cache\n    paddle::Tensor att_cache_ = paddle::full({0, 0, 0, 0}, 0.0);\n    // conformer-only conv_module cache\n    paddle::Tensor cnn_cache_ = paddle::full({0, 0, 0, 0}, 0.0);\n\n    paddle::jit::Function forward_encoder_chunk_;\n    paddle::jit::Function forward_attention_decoder_;\n    paddle::jit::Function ctc_activation_;\n    float cost_time_ = 0.0;\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_nnet_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"base/common.h\"\n#include \"decoder/param.h\"\n#include \"frontend/assembler.h\"\n#include \"frontend/data_cache.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/decodable.h\"\n#include \"nnet/u2_nnet.h\"\n\n\nDEFINE_string(feature_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(nnet_prob_wspecifier, \"\", \"nnet porb wspecifier\");\nDEFINE_string(nnet_encoder_outs_wspecifier, \"\", \"nnet encoder outs wspecifier\");\n\nusing kaldi::BaseFloat;\nusing kaldi::Matrix;\nusing std::vector;\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int32 num_done = 0, num_err = 0;\n\n    CHECK_GT(FLAGS_feature_rspecifier.size(), 0);\n    CHECK_GT(FLAGS_nnet_prob_wspecifier.size(), 0);\n    CHECK_GT(FLAGS_model_path.size(), 0);\n    LOG(INFO) << \"input rspecifier: \" << FLAGS_feature_rspecifier;\n    LOG(INFO) << \"output wspecifier: \" << FLAGS_nnet_prob_wspecifier;\n    LOG(INFO) << \"model path: \" << FLAGS_model_path;\n\n    kaldi::SequentialBaseFloatMatrixReader feature_reader(\n        FLAGS_feature_rspecifier);\n    kaldi::BaseFloatMatrixWriter nnet_out_writer(FLAGS_nnet_prob_wspecifier);\n    kaldi::BaseFloatMatrixWriter nnet_encoder_outs_writer(\n        FLAGS_nnet_encoder_outs_wspecifier);\n\n    ppspeech::ModelOptions model_opts = ppspeech::ModelOptions::InitFromFlags();\n\n    int32 chunk_size = (FLAGS_nnet_decoder_chunk - 1) * FLAGS_subsampling_rate +\n                       FLAGS_receptive_field_length;\n    int32 chunk_stride = FLAGS_subsampling_rate * FLAGS_nnet_decoder_chunk;\n    int32 receptive_field_length = FLAGS_receptive_field_length;\n    LOG(INFO) << \"chunk size (frame): \" << chunk_size;\n    LOG(INFO) << \"chunk stride (frame): \" << chunk_stride;\n    LOG(INFO) << \"receptive field (frame): \" << receptive_field_length;\n\n    std::shared_ptr<ppspeech::U2Nnet> nnet(new ppspeech::U2Nnet(model_opts));\n    std::shared_ptr<ppspeech::DataCache> raw_data(new ppspeech::DataCache());\n    std::shared_ptr<ppspeech::Decodable> decodable(\n        new ppspeech::Decodable(nnet, raw_data, FLAGS_acoustic_scale));\n    kaldi::Timer timer;\n\n    for (; !feature_reader.Done(); feature_reader.Next()) {\n        string utt = feature_reader.Key();\n        kaldi::Matrix<BaseFloat> feature = feature_reader.Value();\n\n        int nframes = feature.NumRows();\n        int feat_dim = feature.NumCols();\n        raw_data->SetDim(feat_dim);\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"feat shape: \" << nframes << \", \" << feat_dim;\n\n        int32 frame_idx = 0;\n        int vocab_dim = 0;\n        std::vector<kaldi::Vector<kaldi::BaseFloat>> prob_vec;\n        std::vector<kaldi::Vector<kaldi::BaseFloat>> encoder_out_vec;\n        int32 ori_feature_len = feature.NumRows();\n        int32 num_chunks = feature.NumRows() / chunk_stride + 1;\n        LOG(INFO) << \"num_chunks: \" << num_chunks;\n\n        for (int chunk_idx = 0; chunk_idx < num_chunks; ++chunk_idx) {\n            int32 this_chunk_size = 0;\n            if (ori_feature_len > chunk_idx * chunk_stride) {\n                this_chunk_size = std::min(\n                    ori_feature_len - chunk_idx * chunk_stride, chunk_size);\n            }\n            if (this_chunk_size < receptive_field_length) {\n                LOG(WARNING)\n                    << \"utt: \" << utt << \" skip last \" << this_chunk_size\n                    << \" frames, expect is \" << receptive_field_length;\n                break;\n            }\n\n            kaldi::Vector<kaldi::BaseFloat> feature_chunk(this_chunk_size *\n                                                          feat_dim);\n            int32 start = chunk_idx * chunk_stride;\n            for (int row_id = 0; row_id < this_chunk_size; ++row_id) {\n                kaldi::SubVector<kaldi::BaseFloat> feat_row(feature, start);\n                kaldi::SubVector<kaldi::BaseFloat> feature_chunk_row(\n                    feature_chunk.Data() + row_id * feat_dim, feat_dim);\n\n                feature_chunk_row.CopyFromVec(feat_row);\n                ++start;\n            }\n\n            // feat to frontend pipeline cache\n            raw_data->Accept(feature_chunk);\n\n            // send data finish signal\n            if (chunk_idx == num_chunks - 1) {\n                raw_data->SetFinished();\n            }\n\n            // get nnet outputs\n            kaldi::Timer timer;\n            kaldi::Vector<kaldi::BaseFloat> logprobs;\n            bool isok = decodable->AdvanceChunk(&logprobs, &vocab_dim);\n            CHECK(isok == true);\n            for (int row_idx = 0; row_idx < logprobs.Dim() / vocab_dim;\n                 row_idx++) {\n                kaldi::Vector<kaldi::BaseFloat> vec_tmp(vocab_dim);\n                std::memcpy(vec_tmp.Data(),\n                            logprobs.Data() + row_idx * vocab_dim,\n                            sizeof(kaldi::BaseFloat) * vocab_dim);\n                prob_vec.push_back(vec_tmp);\n            }\n\n            VLOG(2) << \"frame_idx: \" << frame_idx\n                    << \" elapsed: \" << timer.Elapsed() << \" sec.\";\n        }\n\n        // get encoder out\n        decodable->Nnet()->EncoderOuts(&encoder_out_vec);\n\n        // after process one utt, then reset decoder state.\n        decodable->Reset();\n\n        if (prob_vec.size() == 0 || encoder_out_vec.size() == 0) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            LOG(WARNING) << \" the nnet prob/encoder_out of \" << utt\n                         << \" is empty\";\n            continue;\n        }\n\n        {\n            // writer nnet output\n            kaldi::MatrixIndexT nrow = prob_vec.size();\n            kaldi::MatrixIndexT ncol = prob_vec[0].Dim();\n            LOG(INFO) << \"nnet out shape: \" << nrow << \", \" << ncol;\n            kaldi::Matrix<kaldi::BaseFloat> nnet_out(nrow, ncol);\n            for (int32 row_idx = 0; row_idx < nrow; ++row_idx) {\n                for (int32 col_idx = 0; col_idx < ncol; ++col_idx) {\n                    nnet_out(row_idx, col_idx) = prob_vec[row_idx](col_idx);\n                }\n            }\n            nnet_out_writer.Write(utt, nnet_out);\n        }\n\n\n        {\n            // writer nnet encoder outs\n            kaldi::MatrixIndexT nrow = encoder_out_vec.size();\n            kaldi::MatrixIndexT ncol = encoder_out_vec[0].Dim();\n            LOG(INFO) << \"nnet encoder outs shape: \" << nrow << \", \" << ncol;\n            kaldi::Matrix<kaldi::BaseFloat> encoder_outs(nrow, ncol);\n            for (int32 row_idx = 0; row_idx < nrow; ++row_idx) {\n                for (int32 col_idx = 0; col_idx < ncol; ++col_idx) {\n                    encoder_outs(row_idx, col_idx) =\n                        encoder_out_vec[row_idx](col_idx);\n                }\n            }\n            nnet_encoder_outs_writer.Write(utt, encoder_outs);\n        }\n\n        ++num_done;\n    }\n\n\n    double elapsed = timer.Elapsed();\n    LOG(INFO) << \"Program cost:\" << elapsed << \" sec\";\n\n    LOG(INFO) << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_nnet_thread_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef USE_ONNX\n    #include \"nnet/u2_nnet.h\"\n#else\n    #include \"nnet/u2_onnx_nnet.h\"\n#endif\n#include \"base/common.h\"\n#include \"decoder/param.h\"\n#include \"frontend/feature_pipeline.h\"\n#include \"frontend/wave-reader.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/decodable.h\"\n#include \"nnet/nnet_producer.h\"\n#include \"nnet/u2_nnet.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test wav rspecifier\");\nDEFINE_string(nnet_prob_wspecifier, \"\", \"nnet porb wspecifier\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\nDEFINE_int32(sample_rate, 16000, \"sample rate\");\n\nusing kaldi::BaseFloat;\nusing kaldi::Matrix;\nusing std::vector;\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int32 num_done = 0, num_err = 0;\n    int sample_rate = FLAGS_sample_rate;\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * sample_rate;\n\n    CHECK_GT(FLAGS_wav_rspecifier.size(), 0);\n    CHECK_GT(FLAGS_nnet_prob_wspecifier.size(), 0);\n    CHECK_GT(FLAGS_model_path.size(), 0);\n    LOG(INFO) << \"input rspecifier: \" << FLAGS_wav_rspecifier;\n    LOG(INFO) << \"output wspecifier: \" << FLAGS_nnet_prob_wspecifier;\n    LOG(INFO) << \"model path: \" << FLAGS_model_path;\n\n    kaldi::SequentialTableReader<kaldi::WaveHolder> wav_reader(\n        FLAGS_wav_rspecifier);\n    kaldi::BaseFloatMatrixWriter nnet_out_writer(FLAGS_nnet_prob_wspecifier);\n\n    ppspeech::ModelOptions model_opts = ppspeech::ModelOptions::InitFromFlags();\n    ppspeech::FeaturePipelineOptions feature_opts =\n        ppspeech::FeaturePipelineOptions::InitFromFlags();\n    feature_opts.assembler_opts.fill_zero = false;\n\n#ifndef USE_ONNX\n    std::shared_ptr<ppspeech::U2Nnet> nnet(new ppspeech::U2Nnet(model_opts));\n#else\n    std::shared_ptr<ppspeech::U2OnnxNnet> nnet(new ppspeech::U2OnnxNnet(model_opts));\n#endif\n    std::shared_ptr<ppspeech::FeaturePipeline> feature_pipeline(\n        new ppspeech::FeaturePipeline(feature_opts));\n    std::shared_ptr<ppspeech::NnetProducer> nnet_producer(\n        new ppspeech::NnetProducer(nnet, feature_pipeline));\n    kaldi::Timer timer;\n    float tot_wav_duration = 0;\n\n    for (; !wav_reader.Done(); wav_reader.Next()) {\n        std::string utt = wav_reader.Key();\n        const kaldi::WaveData& wave_data = wav_reader.Value();\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"wav dur: \" << wave_data.Duration() << \" sec.\";\n        double dur = wave_data.Duration();\n        tot_wav_duration += dur;\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        int tot_samples = waveform.Dim();\n        LOG(INFO) << \"wav len (sample): \" << tot_samples;\n\n        int sample_offset = 0;\n        kaldi::Timer timer;\n\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            std::vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = waveform(sample_offset + i);\n            }\n\n            nnet_producer->Accept(wav_chunk);\n            if (cur_chunk_size < chunk_sample_size) {\n                nnet_producer->SetInputFinished();\n            }\n\n            // no overlap\n            sample_offset += cur_chunk_size;\n        }\n        CHECK(sample_offset == tot_samples);\n\n        std::vector<std::vector<kaldi::BaseFloat>> prob_vec;\n        while (1) {\n            std::vector<kaldi::BaseFloat> logprobs;\n            bool isok = nnet_producer->Read(&logprobs);\n            if (nnet_producer->IsFinished()) break;\n            if (isok == false) continue;\n            prob_vec.push_back(logprobs);\n        }\n        {\n            // writer nnet output\n            kaldi::MatrixIndexT nrow = prob_vec.size();\n            kaldi::MatrixIndexT ncol = prob_vec[0].size();\n            LOG(INFO) << \"nnet out shape: \" << nrow << \", \" << ncol;\n            kaldi::Matrix<kaldi::BaseFloat> nnet_out(nrow, ncol);\n            for (int32 row_idx = 0; row_idx < nrow; ++row_idx) {\n                for (int32 col_idx = 0; col_idx < ncol; ++col_idx) {\n                    nnet_out(row_idx, col_idx) = prob_vec[row_idx][col_idx];\n                }\n            }\n            nnet_out_writer.Write(utt, nnet_out);\n        }\n        nnet_producer->Reset();\n    }\n\n    nnet_producer->Wait();\n    double elapsed = timer.Elapsed();\n    LOG(INFO) << \"Program cost:\" << elapsed << \" sec\";\n\n    LOG(INFO) << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_onnx_nnet.cc",
    "content": "// Copyright 2022 Horizon Robotics. All Rights Reserved.\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/onnx_asr_model.cc\n\n#include \"nnet/u2_onnx_nnet.h\"\n#include \"common/base/config.h\"\n\nnamespace ppspeech {\n\nvoid U2OnnxNnet::LoadModel(const std::string& model_dir) {\n    std::string encoder_onnx_path = model_dir + \"/encoder.onnx\";\n    std::string rescore_onnx_path = model_dir + \"/decoder.onnx\";\n    std::string ctc_onnx_path = model_dir + \"/ctc.onnx\";\n    std::string param_path = model_dir + \"/param.onnx\";\n    // 1. Load sessions\n    try {\n        encoder_ = std::make_shared<fastdeploy::Runtime>();\n        ctc_ = std::make_shared<fastdeploy::Runtime>();\n        rescore_ = std::make_shared<fastdeploy::Runtime>();\n        fastdeploy::RuntimeOption runtime_option;\n        runtime_option.UseOrtBackend();\n        runtime_option.UseCpu();\n        runtime_option.SetCpuThreadNum(1);\n        runtime_option.SetModelPath(encoder_onnx_path.c_str(), \"\", fastdeploy::ModelFormat::ONNX);\n        assert(encoder_->Init(runtime_option));\n        runtime_option.SetModelPath(rescore_onnx_path.c_str(), \"\", fastdeploy::ModelFormat::ONNX);\n        assert(rescore_->Init(runtime_option));\n        runtime_option.SetModelPath(ctc_onnx_path.c_str(), \"\", fastdeploy::ModelFormat::ONNX);\n        assert(ctc_->Init(runtime_option));\n    } catch (std::exception const& e) {\n        LOG(ERROR) << \"error when load onnx model: \" << e.what();\n        exit(0);\n    }\n\n    Config conf(param_path);\n    encoder_output_size_ = conf.Read(\"output_size\", encoder_output_size_);\n    num_blocks_ = conf.Read(\"num_blocks\", num_blocks_);\n    head_ = conf.Read(\"head\", head_);\n    cnn_module_kernel_ = conf.Read(\"cnn_module_kernel\", cnn_module_kernel_);\n    subsampling_rate_ = conf.Read(\"subsampling_rate\", subsampling_rate_);\n    right_context_ = conf.Read(\"right_context\", right_context_);\n    sos_= conf.Read(\"sos_symbol\", sos_);\n    eos_= conf.Read(\"eos_symbol\", eos_);\n    is_bidecoder_= conf.Read(\"is_bidirectional_decoder\", is_bidecoder_);\n    chunk_size_= conf.Read(\"chunk_size\", chunk_size_);\n    num_left_chunks_ = conf.Read(\"left_chunks\", num_left_chunks_);\n    \n    LOG(INFO) << \"Onnx Model Info:\";\n    LOG(INFO) << \"\\tencoder_output_size \" << encoder_output_size_;\n    LOG(INFO) << \"\\tnum_blocks \" << num_blocks_;\n    LOG(INFO) << \"\\thead \" << head_;\n    LOG(INFO) << \"\\tcnn_module_kernel \" << cnn_module_kernel_;\n    LOG(INFO) << \"\\tsubsampling_rate \" << subsampling_rate_;\n    LOG(INFO) << \"\\tright_context \" << right_context_;\n    LOG(INFO) << \"\\tsos \" << sos_;\n    LOG(INFO) << \"\\teos \" << eos_;\n    LOG(INFO) << \"\\tis bidirectional decoder \" << is_bidecoder_;\n    LOG(INFO) << \"\\tchunk_size \" << chunk_size_;\n    LOG(INFO) << \"\\tnum_left_chunks \" << num_left_chunks_;\n\n    // 3. Read model nodes\n    LOG(INFO) << \"Onnx Encoder:\";\n    GetInputOutputInfo(encoder_, &encoder_in_names_, &encoder_out_names_);\n    LOG(INFO) << \"Onnx CTC:\";\n    GetInputOutputInfo(ctc_, &ctc_in_names_, &ctc_out_names_);\n    LOG(INFO) << \"Onnx Rescore:\";\n    GetInputOutputInfo(rescore_, &rescore_in_names_, &rescore_out_names_);\n}\n\nU2OnnxNnet::U2OnnxNnet(const ModelOptions& opts) : opts_(opts) {\n    LoadModel(opts_.model_path);\n}\n\n// shallow copy\nU2OnnxNnet::U2OnnxNnet(const U2OnnxNnet& other) {\n    // metadatas\n    encoder_output_size_ = other.encoder_output_size_;\n    num_blocks_ = other.num_blocks_;\n    head_ = other.head_;\n    cnn_module_kernel_ = other.cnn_module_kernel_;\n    right_context_ = other.right_context_;\n    subsampling_rate_ = other.subsampling_rate_;\n    sos_ = other.sos_;\n    eos_ = other.eos_;\n    is_bidecoder_ = other.is_bidecoder_;\n    chunk_size_ = other.chunk_size_;\n    num_left_chunks_ = other.num_left_chunks_;\n    offset_ = other.offset_;\n    \n    // session\n    encoder_ = other.encoder_;\n    ctc_ = other.ctc_;\n    rescore_ = other.rescore_;\n\n    // node names\n    encoder_in_names_ = other.encoder_in_names_;\n    encoder_out_names_ = other.encoder_out_names_;\n    ctc_in_names_ = other.ctc_in_names_;\n    ctc_out_names_ = other.ctc_out_names_;\n    rescore_in_names_ = other.rescore_in_names_;\n    rescore_out_names_ = other.rescore_out_names_;\n}\n\nvoid U2OnnxNnet::GetInputOutputInfo(const std::shared_ptr<fastdeploy::Runtime>& runtime,\n                                std::vector<std::string>* in_names, std::vector<std::string>* out_names) {\n    std::vector<fastdeploy::TensorInfo> inputs_info = runtime->GetInputInfos();\n    (*in_names).resize(inputs_info.size());\n    for (int i = 0; i < inputs_info.size(); ++i){\n        fastdeploy::TensorInfo info = inputs_info[i];\n\n        std::stringstream shape;\n        for(int j = 0; j < info.shape.size(); ++j){\n            shape << info.shape[j];\n            shape << \" \";\n        }\n        LOG(INFO) << \"\\tInput \" << i << \" : name=\" << info.name << \" type=\" << info.dtype\n              << \" dims=\" << shape.str();\n        (*in_names)[i] = info.name;\n    }\n    std::vector<fastdeploy::TensorInfo> outputs_info = runtime->GetOutputInfos();\n    (*out_names).resize(outputs_info.size());\n    for (int i = 0; i < outputs_info.size(); ++i){\n        fastdeploy::TensorInfo info = outputs_info[i];\n        \n        std::stringstream shape;\n        for(int j = 0; j < info.shape.size(); ++j){\n            shape << info.shape[j];\n            shape << \" \";\n        }\n        LOG(INFO) << \"\\tOutput \" << i << \" : name=\" << info.name << \" type=\" << info.dtype\n              << \" dims=\" << shape.str();\n        (*out_names)[i] = info.name;\n    }\n}\n\nstd::shared_ptr<NnetBase> U2OnnxNnet::Clone() const {\n    auto asr_model = std::make_shared<U2OnnxNnet>(*this);\n    // reset inner state for new decoding\n    asr_model->Reset();\n    return asr_model;\n}\n\nvoid U2OnnxNnet::Reset() {\n    offset_ = 0;\n    encoder_outs_.clear();\n    cached_feats_.clear();\n    // Reset att_cache\n    if (num_left_chunks_ > 0) {\n        int required_cache_size = chunk_size_ * num_left_chunks_;\n        offset_ = required_cache_size;\n        att_cache_.resize(num_blocks_ * head_ * required_cache_size *\n                            encoder_output_size_ / head_ * 2,\n                        0.0);\n        const std::vector<int64_t> att_cache_shape = {num_blocks_, head_, required_cache_size,\n                                        encoder_output_size_ / head_ * 2};\n        att_cache_ort_.SetExternalData(att_cache_shape, fastdeploy::FDDataType::FP32, att_cache_.data());\n    } else {\n        att_cache_.resize(0, 0.0);\n        const std::vector<int64_t> att_cache_shape = {num_blocks_, head_, 0,\n                                        encoder_output_size_ / head_ * 2};\n        att_cache_ort_.SetExternalData(att_cache_shape, fastdeploy::FDDataType::FP32, att_cache_.data());\n    }\n\n    // Reset cnn_cache\n    cnn_cache_.resize(\n        num_blocks_ * encoder_output_size_ * (cnn_module_kernel_ - 1), 0.0);\n    const std::vector<int64_t> cnn_cache_shape = {num_blocks_, 1, encoder_output_size_,\n                                        cnn_module_kernel_ - 1};\n    cnn_cache_ort_.SetExternalData(cnn_cache_shape, fastdeploy::FDDataType::FP32, cnn_cache_.data());\n}\n\nvoid U2OnnxNnet::FeedForward(const std::vector<BaseFloat>& features,\n                         const int32& feature_dim,\n                         NnetOut* out) {\n    kaldi::Timer timer;\n\n    std::vector<kaldi::BaseFloat> ctc_probs;\n    ForwardEncoderChunkImpl(\n        features, feature_dim, &out->logprobs, &out->vocab_dim);\n    VLOG(1) << \"FeedForward cost: \" << timer.Elapsed() << \" sec. \"\n            << features.size() / feature_dim << \" frames.\";\n}\n\nvoid U2OnnxNnet::ForwardEncoderChunkImpl(\n        const std::vector<kaldi::BaseFloat>& chunk_feats,\n        const int32& feat_dim,\n        std::vector<kaldi::BaseFloat>* out_prob,\n        int32* vocab_dim) {\n        \n    // 1. Prepare onnx required data, splice cached_feature_ and chunk_feats\n    // chunk\n    int num_frames = chunk_feats.size() / feat_dim;\n    VLOG(3) << \"num_frames: \" << num_frames;\n    VLOG(3) << \"feat_dim: \" << feat_dim;\n    const int feature_dim = feat_dim;\n    std::vector<float> feats;\n    feats.insert(feats.end(), chunk_feats.begin(), chunk_feats.end());\n    fastdeploy::FDTensor feats_ort;\n    const std::vector<int64_t> feats_shape = {1, num_frames, feature_dim};\n    feats_ort.SetExternalData(feats_shape, fastdeploy::FDDataType::FP32, feats.data());\n\n    // offset\n    int64_t offset_int64 = static_cast<int64_t>(offset_);\n    fastdeploy::FDTensor offset_ort;\n    offset_ort.SetExternalData({}, fastdeploy::FDDataType::INT64, &offset_int64);\n\n    // required_cache_size\n    int64_t required_cache_size = chunk_size_ * num_left_chunks_;\n    fastdeploy::FDTensor required_cache_size_ort(\"\");\n    required_cache_size_ort.SetExternalData({}, fastdeploy::FDDataType::INT64, &required_cache_size);\n\n    // att_mask\n    fastdeploy::FDTensor att_mask_ort;\n    std::vector<uint8_t> att_mask(required_cache_size + chunk_size_, 1);\n    if (num_left_chunks_ > 0) {\n        int chunk_idx = offset_ / chunk_size_ - num_left_chunks_;\n        if (chunk_idx < num_left_chunks_) {\n            for (int i = 0; i < (num_left_chunks_ - chunk_idx) * chunk_size_; ++i) {\n                att_mask[i] = 0;\n            }\n        }\n        const std::vector<int64_t> att_mask_shape = {1, 1, required_cache_size + chunk_size_};\n        att_mask_ort.SetExternalData(att_mask_shape, fastdeploy::FDDataType::BOOL, reinterpret_cast<bool*>(att_mask.data()));\n    }\n\n    // 2. Encoder chunk forward\n    std::vector<fastdeploy::FDTensor> inputs(encoder_in_names_.size());\n    for (int i = 0; i < encoder_in_names_.size(); ++i) {\n        std::string name = encoder_in_names_[i];\n        if (!strcmp(name.data(), \"chunk\")) {\n            inputs[i] = std::move(feats_ort);\n            inputs[i].name = \"chunk\";\n        } else if (!strcmp(name.data(), \"offset\")) {\n            inputs[i] = std::move(offset_ort);\n            inputs[i].name = \"offset\";\n        } else if (!strcmp(name.data(), \"required_cache_size\")) {\n            inputs[i] = std::move(required_cache_size_ort);\n            inputs[i].name = \"required_cache_size\";\n        } else if (!strcmp(name.data(), \"att_cache\")) {\n            inputs[i] = std::move(att_cache_ort_);\n            inputs[i].name = \"att_cache\";\n        } else if (!strcmp(name.data(), \"cnn_cache\")) {\n            inputs[i] = std::move(cnn_cache_ort_);\n            inputs[i].name = \"cnn_cache\";\n        } else if (!strcmp(name.data(), \"att_mask\")) {\n            inputs[i] = std::move(att_mask_ort);\n            inputs[i].name = \"att_mask\";\n        }\n    }\n   \n    std::vector<fastdeploy::FDTensor> ort_outputs;\n    assert(encoder_->Infer(inputs, &ort_outputs));\n\n    offset_ += static_cast<int>(ort_outputs[0].shape[1]);\n    att_cache_ort_ = std::move(ort_outputs[1]);\n    cnn_cache_ort_ = std::move(ort_outputs[2]);\n\n    std::vector<fastdeploy::FDTensor> ctc_inputs;\n    ctc_inputs.emplace_back(std::move(ort_outputs[0]));\n    // ctc_inputs[0] = std::move(ort_outputs[0]);\n    ctc_inputs[0].name = ctc_in_names_[0];\n\n    std::vector<fastdeploy::FDTensor> ctc_ort_outputs;\n    assert(ctc_->Infer(ctc_inputs, &ctc_ort_outputs));\n    encoder_outs_.emplace_back(std::move(ctc_inputs[0])); // *****\n\n    float* logp_data = reinterpret_cast<float*>(ctc_ort_outputs[0].Data());\n\n    // Copy to output, (B=1,T,D)\n    std::vector<int64_t> ctc_log_probs_shape = ctc_ort_outputs[0].shape;\n    CHECK_EQ(ctc_log_probs_shape.size(), 3);\n    int B = ctc_log_probs_shape[0];\n    CHECK_EQ(B, 1);\n    int T = ctc_log_probs_shape[1];\n    int D = ctc_log_probs_shape[2];\n    *vocab_dim = D;\n\n    out_prob->resize(T * D);\n    std::memcpy(\n        out_prob->data(), logp_data, T * D * sizeof(kaldi::BaseFloat));\n    return;\n}\n\nfloat U2OnnxNnet::ComputeAttentionScore(const float* prob,\n                                          const std::vector<int>& hyp, int eos,\n                                          int decode_out_len) {\n  float score = 0.0f;\n  for (size_t j = 0; j < hyp.size(); ++j) {\n    score += *(prob + j * decode_out_len + hyp[j]);\n  }\n  score += *(prob + hyp.size() * decode_out_len + eos);\n  return score;\n}\n\nvoid U2OnnxNnet::AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                                float reverse_weight,\n                                std::vector<float>* rescoring_score) {\n    CHECK(rescoring_score != nullptr);\n    int num_hyps = hyps.size();\n    rescoring_score->resize(num_hyps, 0.0f);\n\n    if (num_hyps == 0) {\n        return;\n    }\n    // No encoder output\n    if (encoder_outs_.size() == 0) {\n        return;\n    }\n\n    std::vector<int64_t> hyps_lens;\n    int max_hyps_len = 0;\n    for (size_t i = 0; i < num_hyps; ++i) {\n        int length = hyps[i].size() + 1;\n        max_hyps_len = std::max(length, max_hyps_len);\n        hyps_lens.emplace_back(static_cast<int64_t>(length));\n    }\n\n    std::vector<float> rescore_input;\n    int encoder_len = 0;\n    for (int i = 0; i < encoder_outs_.size(); i++) {\n        float* encoder_outs_data = reinterpret_cast<float*>(encoder_outs_[i].Data());\n        for (int j = 0; j < encoder_outs_[i].Numel(); j++) {\n            rescore_input.emplace_back(encoder_outs_data[j]);\n        }\n        encoder_len += encoder_outs_[i].shape[1];\n    }\n\n    std::vector<int64_t> hyps_pad;\n\n    for (size_t i = 0; i < num_hyps; ++i) {\n        const std::vector<int>& hyp = hyps[i];\n        hyps_pad.emplace_back(sos_);\n        size_t j = 0;\n        for (; j < hyp.size(); ++j) {\n            hyps_pad.emplace_back(hyp[j]);\n        }\n        if (j == max_hyps_len - 1) {\n            continue;\n        }\n        for (; j < max_hyps_len - 1; ++j) {\n            hyps_pad.emplace_back(0);\n        }\n    }\n\n    const std::vector<int64_t> hyps_pad_shape = {num_hyps, max_hyps_len};\n    const std::vector<int64_t> hyps_lens_shape = {num_hyps};\n    const std::vector<int64_t> decode_input_shape = {1, encoder_len, encoder_output_size_};\n\n    fastdeploy::FDTensor hyps_pad_tensor_;\n    hyps_pad_tensor_.SetExternalData(hyps_pad_shape, fastdeploy::FDDataType::INT64, hyps_pad.data());\n    fastdeploy::FDTensor hyps_lens_tensor_;\n    hyps_lens_tensor_.SetExternalData(hyps_lens_shape, fastdeploy::FDDataType::INT64, hyps_lens.data());\n    fastdeploy::FDTensor decode_input_tensor_;\n    decode_input_tensor_.SetExternalData(decode_input_shape, fastdeploy::FDDataType::FP32, rescore_input.data());\n\n    std::vector<fastdeploy::FDTensor> rescore_inputs(3);\n\n    rescore_inputs[0] = std::move(hyps_pad_tensor_);\n    rescore_inputs[0].name = rescore_in_names_[0];\n    rescore_inputs[1] = std::move(hyps_lens_tensor_);\n    rescore_inputs[1].name = rescore_in_names_[1];\n    rescore_inputs[2] = std::move(decode_input_tensor_);\n    rescore_inputs[2].name = rescore_in_names_[2];\n\n    std::vector<fastdeploy::FDTensor> rescore_outputs;\n    assert(rescore_->Infer(rescore_inputs, &rescore_outputs));\n\n    float* decoder_outs_data = reinterpret_cast<float*>(rescore_outputs[0].Data());\n    float* r_decoder_outs_data = reinterpret_cast<float*>(rescore_outputs[1].Data());\n\n    int decode_out_len = rescore_outputs[0].shape[2];\n\n    for (size_t i = 0; i < num_hyps; ++i) {\n        const std::vector<int>& hyp = hyps[i];\n        float score = 0.0f;\n        // left to right decoder score\n        score = ComputeAttentionScore(\n            decoder_outs_data + max_hyps_len * decode_out_len * i, hyp, eos_,\n            decode_out_len);\n        // Optional: Used for right to left score\n        float r_score = 0.0f;\n        if (is_bidecoder_ && reverse_weight > 0) {\n        std::vector<int> r_hyp(hyp.size());\n        std::reverse_copy(hyp.begin(), hyp.end(), r_hyp.begin());\n        // right to left decoder score\n        r_score = ComputeAttentionScore(\n            r_decoder_outs_data + max_hyps_len * decode_out_len * i, r_hyp, eos_,\n            decode_out_len);\n        }\n        // combined left-to-right and right-to-left score\n        (*rescoring_score)[i] =\n            score * (1 - reverse_weight) + r_score * reverse_weight;\n    }\n}\n\nvoid U2OnnxNnet::EncoderOuts(\n    std::vector<std::vector<kaldi::BaseFloat>>* encoder_out) const {\n}\n\n} //namepace ppspeech"
  },
  {
    "path": "runtime/engine/asr/nnet/u2_onnx_nnet.h",
    "content": "// Copyright 2022 Horizon Robotics. All Rights Reserved.\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from\n// https://github.com/wenet-e2e/wenet/blob/main/runtime/core/decoder/onnx_asr_model.h\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"matrix/kaldi-matrix.h\"\n#include \"nnet/nnet_itf.h\"\n#include \"nnet/u2_nnet.h\"\n\n#include \"fastdeploy/runtime.h\"\n\nnamespace ppspeech {\n\nclass U2OnnxNnet : public U2NnetBase {\n\n  public:\n    explicit U2OnnxNnet(const ModelOptions& opts);\n    U2OnnxNnet(const U2OnnxNnet& other);\n\n    void FeedForward(const std::vector<kaldi::BaseFloat>& features,\n                     const int32& feature_dim,\n                     NnetOut* out) override;\n\n    void Reset() override;\n\n    bool IsLogProb() override { return true; }\n\n    void Dim();\n\n    void LoadModel(const std::string& model_dir);\n\n    std::shared_ptr<NnetBase> Clone() const override;\n\n    void ForwardEncoderChunkImpl(\n        const std::vector<kaldi::BaseFloat>& chunk_feats,\n        const int32& feat_dim,\n        std::vector<kaldi::BaseFloat>* ctc_probs,\n        int32* vocab_dim) override;\n\n    float ComputeAttentionScore(const float* prob, const std::vector<int>& hyp,\n                              int eos, int decode_out_len);\n\n    void AttentionRescoring(const std::vector<std::vector<int>>& hyps,\n                            float reverse_weight,\n                            std::vector<float>* rescoring_score) override;\n\n    void EncoderOuts(\n        std::vector<std::vector<kaldi::BaseFloat>>* encoder_out) const;\n\n    void GetInputOutputInfo(const std::shared_ptr<fastdeploy::Runtime>& runtime,\n                          std::vector<std::string>* in_names,\n                          std::vector<std::string>* out_names);\n  private:\n    ModelOptions opts_;\n\n    int encoder_output_size_ = 0;\n    int num_blocks_ = 0;\n    int cnn_module_kernel_ = 0;\n    int head_ = 0;\n\n    // sessions\n    std::shared_ptr<fastdeploy::Runtime> encoder_ = nullptr;\n    std::shared_ptr<fastdeploy::Runtime> rescore_ = nullptr;\n    std::shared_ptr<fastdeploy::Runtime> ctc_ = nullptr;\n\n\n    // node names\n    std::vector<std::string> encoder_in_names_, encoder_out_names_;\n    std::vector<std::string> ctc_in_names_, ctc_out_names_;\n    std::vector<std::string> rescore_in_names_, rescore_out_names_;\n\n    // caches\n    fastdeploy::FDTensor att_cache_ort_;\n    fastdeploy::FDTensor cnn_cache_ort_;\n    std::vector<fastdeploy::FDTensor> encoder_outs_;\n\n    std::vector<float> att_cache_;\n    std::vector<float> cnn_cache_;\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/asr/recognizer/CMakeLists.txt",
    "content": "set(srcs)\n\nlist(APPEND srcs\n  recognizer_controller.cc\n  recognizer_controller_impl.cc\n  recognizer_instance.cc\n  recognizer.cc\n)\n\nadd_library(recognizer STATIC ${srcs})\ntarget_link_libraries(recognizer PUBLIC decoder)\n\nset(TEST_BINS \n  recognizer_batch_main\n  recognizer_batch_main2\n  recognizer_main\n)\n\nforeach(bin_name IN LISTS TEST_BINS)\n  add_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\n  target_include_directories(${bin_name} PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\n  target_link_libraries(${bin_name} recognizer nnet decoder fst utils gflags glog kaldi-base kaldi-matrix kaldi-util)\n  target_compile_options(${bin_name}  PRIVATE ${PADDLE_COMPILE_FLAGS})\n  target_include_directories(${bin_name}  PRIVATE ${pybind11_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})\n  target_link_libraries(${bin_name}  ${PYTHON_LIBRARIES} ${PADDLE_LINK_FLAGS} -ldl)\nendforeach()\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"recognizer/recognizer.h\"\n#include \"recognizer/recognizer_instance.h\"\n\nbool InitRecognizer(const std::string& model_file, \n                    const std::string& word_symbol_table_file,\n                    const std::string& fst_file,\n                    int num_instance) {\n    return ppspeech::RecognizerInstance::GetInstance().Init(model_file, \n                                                            word_symbol_table_file, \n                                                            fst_file,\n                                                            num_instance);\n}\n\nint GetRecognizerInstanceId() {\n    return ppspeech::RecognizerInstance::GetInstance().GetRecognizerInstanceId();\n}\n\nvoid InitDecoder(int instance_id) {\n    return ppspeech::RecognizerInstance::GetInstance().InitDecoder(instance_id);\n}\n\nvoid AcceptData(const std::vector<float>& waves, int instance_id) {\n    return ppspeech::RecognizerInstance::GetInstance().Accept(waves, instance_id);\n}\n\nvoid SetInputFinished(int instance_id) {\n    return ppspeech::RecognizerInstance::GetInstance().SetInputFinished(instance_id);\n}\n\nstd::string GetFinalResult(int instance_id) {\n    return ppspeech::RecognizerInstance::GetInstance().GetResult(instance_id);\n}"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <string>\n#include <vector>\n\nbool InitRecognizer(const std::string& model_file, \n                    const std::string& word_symbol_table_file,\n                    const std::string& fst_file,\n                    int num_instance);\nint GetRecognizerInstanceId();\nvoid InitDecoder(int instance_id);\nvoid AcceptData(const std::vector<float>& waves, int instance_id);\nvoid SetInputFinished(int instance_id);\nstd::string GetFinalResult(int instance_id);"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_batch_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"common/base/thread_pool.h\"\n#include \"common/utils/file_utils.h\"\n#include \"common/utils/strings.h\"\n#include \"decoder/param.h\"\n#include \"frontend/wave-reader.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/u2_nnet.h\"\n#include \"recognizer/recognizer_controller.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(result_wspecifier, \"\", \"test result wspecifier\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\nDEFINE_int32(sample_rate, 16000, \"sample rate\");\nDEFINE_int32(njob, 3, \"njob\");\n\nusing std::string;\nusing std::vector;\n\nvoid SplitUtt(string wavlist_file,\n              vector<vector<string>>* uttlists,\n              vector<vector<string>>* wavlists,\n              int njob) {\n    vector<string> wavlist;\n    wavlists->resize(njob);\n    uttlists->resize(njob);\n    ppspeech::ReadFileToVector(wavlist_file, &wavlist);\n    for (size_t idx = 0; idx < wavlist.size(); ++idx) {\n        string utt_str = wavlist[idx];\n        vector<string> utt_wav = ppspeech::StrSplit(utt_str, \" \\t\");\n        LOG(INFO) << utt_wav[0];\n        CHECK_EQ(utt_wav.size(), size_t(2));\n        uttlists->at(idx % njob).push_back(utt_wav[0]);\n        wavlists->at(idx % njob).push_back(utt_wav[1]);\n    }\n}\n\nvoid recognizer_func(ppspeech::RecognizerController* recognizer_controller,\n                     std::vector<string> wavlist,\n                     std::vector<string> uttlist,\n                     std::vector<string>* results) {\n    int32 num_done = 0, num_err = 0;\n    double tot_wav_duration = 0.0;\n    double tot_attention_rescore_time = 0.0;\n    double tot_decode_time = 0.0;\n    int chunk_sample_size = FLAGS_streaming_chunk * FLAGS_sample_rate;\n    if (wavlist.empty()) return;\n\n    results->reserve(wavlist.size());\n    for (size_t idx = 0; idx < wavlist.size(); ++idx) {\n        std::string utt = uttlist[idx];\n        std::string wav_file = wavlist[idx];\n        std::ifstream infile;\n        infile.open(wav_file, std::ifstream::in);\n        kaldi::WaveData wave_data;\n        wave_data.Read(infile);\n        int32 recog_id = -1;\n        while (recog_id == -1) {\n            recog_id = recognizer_controller->GetRecognizerInstanceId();\n        }\n        recognizer_controller->InitDecoder(recog_id);\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"wav dur: \" << wave_data.Duration() << \" sec.\";\n        double dur = wave_data.Duration();\n        tot_wav_duration += dur;\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        int tot_samples = waveform.Dim();\n        LOG(INFO) << \"wav len (sample): \" << tot_samples;\n\n        int sample_offset = 0;\n        kaldi::Timer local_timer;\n\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            std::vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = waveform(sample_offset + i);\n            }\n\n            recognizer_controller->Accept(wav_chunk, recog_id);\n            // no overlap\n            sample_offset += cur_chunk_size;\n        }\n        recognizer_controller->SetInputFinished(recog_id);\n        CHECK(sample_offset == tot_samples);\n        std::string result = recognizer_controller->GetFinalResult(recog_id);\n        if (result.empty()) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            LOG(INFO) << \" the result of \" << utt << \" is empty\";\n            result = \" \";\n        }\n\n        tot_decode_time += local_timer.Elapsed();\n        LOG(INFO) << utt << \" \" << result;\n        LOG(INFO) << \" RTF: \" << local_timer.Elapsed() / dur << \" dur: \" << dur\n                  << \" cost: \" << local_timer.Elapsed();\n\n        results->push_back(result);\n        ++num_done;\n    }\n    LOG(INFO) << \"Done \" << num_done << \" out of \" << (num_err + num_done);\n    LOG(INFO) << \"total wav duration is: \" << tot_wav_duration << \" sec\";\n    LOG(INFO) << \"total decode cost:\" << tot_decode_time << \" sec\";\n    LOG(INFO) << \"RTF is: \" << tot_decode_time / tot_wav_duration;\n}\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int sample_rate = FLAGS_sample_rate;\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * sample_rate;\n    kaldi::TokenWriter result_writer(FLAGS_result_wspecifier);\n    int njob = FLAGS_njob;\n    LOG(INFO) << \"sr: \" << sample_rate;\n    LOG(INFO) << \"chunk size (s): \" << streaming_chunk;\n    LOG(INFO) << \"chunk size (sample): \" << chunk_sample_size;\n\n    ppspeech::RecognizerResource resource =\n        ppspeech::RecognizerResource::InitFromFlags();\n    ppspeech::RecognizerController recognizer_controller(njob, resource);\n    ThreadPool threadpool(njob);\n    vector<vector<string>> wavlist;\n    vector<vector<string>> uttlist;\n    vector<vector<string>> resultlist(njob);\n    vector<std::future<void>> futurelist;\n    SplitUtt(FLAGS_wav_rspecifier, &uttlist, &wavlist, njob);\n    for (size_t i = 0; i < njob; ++i) {\n        std::future<void> f = threadpool.enqueue(recognizer_func,\n                                                 &recognizer_controller,\n                                                 wavlist[i],\n                                                 uttlist[i],\n                                                 &resultlist[i]);\n        futurelist.push_back(std::move(f));\n    }\n\n    for (size_t i = 0; i < njob; ++i) {\n        futurelist[i].get();\n    }\n\n    for (size_t idx = 0; idx < njob; ++idx) {\n        for (size_t utt_idx = 0; utt_idx < uttlist[idx].size(); ++utt_idx) {\n            string utt = uttlist[idx][utt_idx];\n            string result = resultlist[idx][utt_idx];\n            result_writer.Write(utt, result);\n        }\n    }\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_batch_main2.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"common/base/thread_pool.h\"\n#include \"common/utils/file_utils.h\"\n#include \"common/utils/strings.h\"\n#include \"decoder/param.h\"\n#include \"frontend/wave-reader.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"nnet/u2_nnet.h\"\n#include \"recognizer/recognizer.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(result_wspecifier, \"\", \"test result wspecifier\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\nDEFINE_int32(sample_rate, 16000, \"sample rate\");\nDEFINE_int32(njob, 3, \"njob\");\n\nusing std::string;\nusing std::vector;\n\nvoid SplitUtt(string wavlist_file,\n              vector<vector<string>>* uttlists,\n              vector<vector<string>>* wavlists,\n              int njob) {\n    vector<string> wavlist;\n    wavlists->resize(njob);\n    uttlists->resize(njob);\n    ppspeech::ReadFileToVector(wavlist_file, &wavlist);\n    for (size_t idx = 0; idx < wavlist.size(); ++idx) {\n        string utt_str = wavlist[idx];\n        vector<string> utt_wav = ppspeech::StrSplit(utt_str, \" \\t\");\n        LOG(INFO) << utt_wav[0];\n        CHECK_EQ(utt_wav.size(), size_t(2));\n        uttlists->at(idx % njob).push_back(utt_wav[0]);\n        wavlists->at(idx % njob).push_back(utt_wav[1]);\n    }\n}\n\nvoid recognizer_func(std::vector<string> wavlist,\n                     std::vector<string> uttlist,\n                     std::vector<string>* results) {\n    int32 num_done = 0, num_err = 0;\n    double tot_wav_duration = 0.0;\n    double tot_attention_rescore_time = 0.0;\n    double tot_decode_time = 0.0;\n    int chunk_sample_size = FLAGS_streaming_chunk * FLAGS_sample_rate;\n    if (wavlist.empty()) return;\n\n    results->reserve(wavlist.size());\n    for (size_t idx = 0; idx < wavlist.size(); ++idx) {\n        std::string utt = uttlist[idx];\n        std::string wav_file = wavlist[idx];\n        std::ifstream infile;\n        infile.open(wav_file, std::ifstream::in);\n        kaldi::WaveData wave_data;\n        wave_data.Read(infile);\n        int32 recog_id = -1;\n        while (recog_id == -1) {\n            recog_id = GetRecognizerInstanceId();\n        }\n        InitDecoder(recog_id);\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"wav dur: \" << wave_data.Duration() << \" sec.\";\n        double dur = wave_data.Duration();\n        tot_wav_duration += dur;\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        int tot_samples = waveform.Dim();\n        LOG(INFO) << \"wav len (sample): \" << tot_samples;\n\n        int sample_offset = 0;\n        kaldi::Timer local_timer;\n\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            std::vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = waveform(sample_offset + i);\n            }\n\n            AcceptData(wav_chunk, recog_id);\n            // no overlap\n            sample_offset += cur_chunk_size;\n        }\n        SetInputFinished(recog_id);\n        CHECK(sample_offset == tot_samples);\n        std::string result = GetFinalResult(recog_id);\n        if (result.empty()) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            LOG(INFO) << \" the result of \" << utt << \" is empty\";\n            result = \" \";\n        }\n\n        tot_decode_time += local_timer.Elapsed();\n        LOG(INFO) << utt << \" \" << result;\n        LOG(INFO) << \" RTF: \" << local_timer.Elapsed() / dur << \" dur: \" << dur\n                  << \" cost: \" << local_timer.Elapsed();\n\n        results->push_back(result);\n        ++num_done;\n    }\n    LOG(INFO) << \"Done \" << num_done << \" out of \" << (num_err + num_done);\n    LOG(INFO) << \"total wav duration is: \" << tot_wav_duration << \" sec\";\n    LOG(INFO) << \"total decode cost:\" << tot_decode_time << \" sec\";\n    LOG(INFO) << \"RTF is: \" << tot_decode_time / tot_wav_duration;\n}\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int sample_rate = FLAGS_sample_rate;\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * sample_rate;\n    kaldi::TokenWriter result_writer(FLAGS_result_wspecifier);\n    int njob = FLAGS_njob;\n    LOG(INFO) << \"sr: \" << sample_rate;\n    LOG(INFO) << \"chunk size (s): \" << streaming_chunk;\n    LOG(INFO) << \"chunk size (sample): \" << chunk_sample_size;\n\n    InitRecognizer(FLAGS_model_path, FLAGS_word_symbol_table, FLAGS_graph_path, njob);\n    ThreadPool threadpool(njob);\n    vector<vector<string>> wavlist;\n    vector<vector<string>> uttlist;\n    vector<vector<string>> resultlist(njob);\n    vector<std::future<void>> futurelist;\n    SplitUtt(FLAGS_wav_rspecifier, &uttlist, &wavlist, njob);\n    for (size_t i = 0; i < njob; ++i) {\n        std::future<void> f = threadpool.enqueue(recognizer_func,\n                                                 wavlist[i],\n                                                 uttlist[i],\n                                                 &resultlist[i]);\n        futurelist.push_back(std::move(f));\n    }\n\n    for (size_t i = 0; i < njob; ++i) {\n        futurelist[i].get();\n    }\n\n    for (size_t idx = 0; idx < njob; ++idx) {\n        for (size_t utt_idx = 0; utt_idx < uttlist[idx].size(); ++utt_idx) {\n            string utt = uttlist[idx][utt_idx];\n            string result = resultlist[idx][utt_idx];\n            result_writer.Write(utt, result);\n        }\n    }\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_controller.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"recognizer/recognizer_controller.h\"\n#include \"nnet/u2_nnet.h\"\n\nnamespace ppspeech {\n\nRecognizerController::RecognizerController(int num_worker, RecognizerResource resource) {\n    recognizer_workers.resize(num_worker);\n    for (size_t i = 0; i < num_worker; ++i) {\n        recognizer_workers[i].reset(new ppspeech::RecognizerControllerImpl(resource)); \n        waiting_workers.push(i);\n    }\n}\n\nint RecognizerController::GetRecognizerInstanceId() {\n    if (waiting_workers.empty()) {\n        return -1;\n    }\n    int idx = -1;\n    {\n        std::unique_lock<std::mutex> lock(mutex_);\n        idx = waiting_workers.front();\n        waiting_workers.pop();\n    }\n    return idx;\n}\n\nRecognizerController::~RecognizerController() {\n    for (size_t i = 0; i < recognizer_workers.size(); ++i) {\n        recognizer_workers[i]->WaitFinished();\n    }\n}\n\nvoid RecognizerController::InitDecoder(int idx) {\n    recognizer_workers[idx]->InitDecoder();\n}\n\nstd::string RecognizerController::GetFinalResult(int idx) {\n    recognizer_workers[idx]->WaitDecoderFinished();\n    recognizer_workers[idx]->AttentionRescoring();\n    std::string result = recognizer_workers[idx]->GetFinalResult();\n    {\n        std::unique_lock<std::mutex> lock(mutex_);\n        waiting_workers.push(idx);\n    }\n    return result;\n}\n\nvoid RecognizerController::Accept(std::vector<float> data, int idx) {\n    recognizer_workers[idx]->Accept(data);\n}\n\nvoid RecognizerController::SetInputFinished(int idx) {\n    recognizer_workers[idx]->SetInputFinished();\n}\n\n}\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_controller.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <queue>\n#include <memory>\n\n#include \"recognizer/recognizer_controller_impl.h\"\n\nnamespace ppspeech {\n\nclass RecognizerController {\n  public:\n    explicit RecognizerController(int num_worker, RecognizerResource resource);  \n    ~RecognizerController();\n    int GetRecognizerInstanceId();\n    void InitDecoder(int idx);\n    void Accept(std::vector<float> data, int idx);\n    void SetInputFinished(int idx);\n    std::string GetFinalResult(int idx);\n    \n  private:\n    std::queue<int> waiting_workers;  \n    std::mutex mutex_;\n    std::vector<std::unique_ptr<ppspeech::RecognizerControllerImpl>> recognizer_workers;\n  \n    DISALLOW_COPY_AND_ASSIGN(RecognizerController);\n};\n\n}"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_controller_impl.cc",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang, Di Wu)\n//               2022 Binbin Zhang (binbzha@qq.com)\n// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"recognizer/recognizer_controller_impl.h\"\n#include \"decoder/ctc_prefix_beam_search_decoder.h\"\n#include \"common/utils/strings.h\"\n\nnamespace ppspeech {\n\nRecognizerControllerImpl::RecognizerControllerImpl(const RecognizerResource& resource)\n: opts_(resource) {\n    BaseFloat am_scale = resource.acoustic_scale;\n    BaseFloat blank_threshold = resource.blank_threshold;\n    const FeaturePipelineOptions& feature_opts = resource.feature_pipeline_opts;\n    std::shared_ptr<FeaturePipeline> feature_pipeline(\n        new FeaturePipeline(feature_opts));\n    std::shared_ptr<NnetBase> nnet;\n#ifndef USE_ONNX\n    nnet = resource.nnet->Clone();\n#else\n    if (resource.model_opts.with_onnx_model){\n        nnet.reset(new U2OnnxNnet(resource.model_opts));\n    } else {\n        nnet = resource.nnet->Clone();\n    }\n#endif\n    nnet_producer_.reset(new NnetProducer(nnet, feature_pipeline, blank_threshold));\n    nnet_thread_ = std::thread(RunNnetEvaluation, this);\n\n    decodable_.reset(new Decodable(nnet_producer_, am_scale));\n    if (resource.decoder_opts.tlg_decoder_opts.fst_path.empty()) {\n        LOG(INFO) << \"Init PrefixBeamSearch Decoder\";\n        decoder_ = std::make_unique<CTCPrefixBeamSearch>(\n            resource.decoder_opts.ctc_prefix_search_opts);\n    } else {\n        LOG(INFO) << \"Init TLGDecoder\";\n        decoder_ = std::make_unique<TLGDecoder>(\n            resource.decoder_opts.tlg_decoder_opts);\n    }\n\n    symbol_table_ = decoder_->WordSymbolTable();\n    global_frame_offset_ = 0;\n    input_finished_ = false;\n    num_frames_ = 0;\n    result_.clear(); \n}\n\nRecognizerControllerImpl::~RecognizerControllerImpl() {\n    WaitFinished();\n}\n\nvoid RecognizerControllerImpl::Reset() {\n    nnet_producer_->Reset();\n}\n\nvoid RecognizerControllerImpl::RunDecoder(RecognizerControllerImpl* me) {\n    me->RunDecoderInternal();\n}\n\nvoid RecognizerControllerImpl::RunDecoderInternal() {\n    LOG(INFO) << \"DecoderInternal begin\";\n    while (!nnet_producer_->IsFinished()) {\n        nnet_condition_.notify_one();\n        decoder_->AdvanceDecode(decodable_);\n    }\n    decoder_->AdvanceDecode(decodable_);\n    UpdateResult(false);\n    LOG(INFO) << \"DecoderInternal exit\";\n}\n\nvoid RecognizerControllerImpl::WaitDecoderFinished() {\n    if (decoder_thread_.joinable()) decoder_thread_.join();\n}\n\nvoid RecognizerControllerImpl::RunNnetEvaluation(RecognizerControllerImpl* me) {\n    me->RunNnetEvaluationInternal();\n}\n\nvoid RecognizerControllerImpl::SetInputFinished() {\n    nnet_producer_->SetInputFinished();\n    nnet_condition_.notify_one();\n    LOG(INFO) << \"Set Input Finished\";\n}\n\nvoid RecognizerControllerImpl::WaitFinished() {\n    abort_ = true;\n    LOG(INFO) << \"nnet wait finished\";\n    nnet_condition_.notify_one();\n    if (nnet_thread_.joinable()) {\n        nnet_thread_.join();\n    }\n}\n\nvoid RecognizerControllerImpl::RunNnetEvaluationInternal() {\n    bool result = false;\n    LOG(INFO) << \"NnetEvaluationInteral begin\";\n    while (!abort_) {\n        std::unique_lock<std::mutex> lock(nnet_mutex_);\n        nnet_condition_.wait(lock);\n        do {\n            result = nnet_producer_->Compute();\n            decoder_condition_.notify_one();\n        } while (result);\n    }\n    LOG(INFO) << \"NnetEvaluationInteral exit\";    \n}\n\nvoid RecognizerControllerImpl::Accept(std::vector<float> data) {\n    nnet_producer_->Accept(data);\n    nnet_condition_.notify_one();\n}\n\nvoid RecognizerControllerImpl::InitDecoder() {\n    global_frame_offset_ = 0;\n    input_finished_ = false;\n    num_frames_ = 0;\n    result_.clear();\n\n    decodable_->Reset();\n    decoder_->Reset();\n    decoder_thread_ = std::thread(RunDecoder, this);\n}\n\nvoid RecognizerControllerImpl::AttentionRescoring() {\n    decoder_->FinalizeSearch();\n    UpdateResult(false);\n\n    // No need to do rescoring\n    if (0.0 == opts_.decoder_opts.rescoring_weight) {\n        LOG_EVERY_N(WARNING, 3) << \"Not do AttentionRescoring!\";\n        return;\n    }\n    LOG_EVERY_N(WARNING, 3) << \"Do AttentionRescoring!\";\n\n    // Inputs() returns N-best input ids, which is the basic unit for rescoring\n    // In CtcPrefixBeamSearch, inputs are the same to outputs\n    const auto& hypotheses = decoder_->Inputs();\n    int num_hyps = hypotheses.size();\n    if (num_hyps <= 0) {\n        return;\n    }\n\n    std::vector<float> rescoring_score;\n    decodable_->AttentionRescoring(\n        hypotheses, opts_.decoder_opts.reverse_weight, &rescoring_score);\n\n    // combine ctc score and rescoring score\n    for (size_t i = 0; i < num_hyps; i++) {\n        VLOG(3) << \"hyp \" << i << \" rescoring_score: \" << rescoring_score[i]\n                << \" ctc_score: \" << result_[i].score\n                << \" rescoring_weight: \" << opts_.decoder_opts.rescoring_weight\n                << \" ctc_weight: \" << opts_.decoder_opts.ctc_weight;\n        result_[i].score =\n            opts_.decoder_opts.rescoring_weight * rescoring_score[i] +\n            opts_.decoder_opts.ctc_weight * result_[i].score;\n\n        VLOG(3) << \"hyp: \" << result_[0].sentence\n                << \" score: \" << result_[0].score;\n    }\n\n    std::sort(result_.begin(), result_.end(), DecodeResult::CompareFunc);\n    VLOG(3) << \"result: \" << result_[0].sentence\n            << \" score: \" << result_[0].score;\n}\n\nstd::string RecognizerControllerImpl::GetFinalResult() { return result_[0].sentence; }\n\nstd::string RecognizerControllerImpl::GetPartialResult() { return result_[0].sentence; }\n\nvoid RecognizerControllerImpl::UpdateResult(bool finish) {\n    const auto& hypotheses = decoder_->Outputs();\n    const auto& inputs = decoder_->Inputs();\n    const auto& likelihood = decoder_->Likelihood();\n    const auto& times = decoder_->Times();\n    result_.clear();\n\n    CHECK_EQ(inputs.size(), likelihood.size());\n    for (size_t i = 0; i < hypotheses.size(); i++) {\n        const std::vector<int>& hypothesis = hypotheses[i];\n\n        DecodeResult path;\n        path.score = likelihood[i];\n        for (size_t j = 0; j < hypothesis.size(); j++) {\n            std::string word = symbol_table_->Find(hypothesis[j]);\n            path.sentence += (\" \" + word);\n        }\n        path.sentence = DelBlank(path.sentence);\n\n        // TimeStamp is only supported in final result\n        // TimeStamp of the output of CtcWfstBeamSearch may be inaccurate due to\n        // various FST operations when building the decoding graph. So here we\n        // use time stamp of the input(e2e model unit), which is more accurate,\n        // and it requires the symbol table of the e2e model used in training.\n        if (symbol_table_ != nullptr && finish) {\n            int offset = global_frame_offset_ * FrameShiftInMs();\n\n            const std::vector<int>& input = inputs[i];\n            const std::vector<int> time_stamp = times[i];\n            CHECK_EQ(input.size(), time_stamp.size());\n\n            for (size_t j = 0; j < input.size(); j++) {\n                std::string word = symbol_table_->Find(input[j]);\n\n                int start =\n                    time_stamp[j] * FrameShiftInMs() - time_stamp_gap_ > 0\n                        ? time_stamp[j] * FrameShiftInMs() - time_stamp_gap_\n                        : 0;\n                if (j > 0) {\n                    start =\n                        (time_stamp[j] - time_stamp[j - 1]) * FrameShiftInMs() <\n                                time_stamp_gap_\n                            ? (time_stamp[j - 1] + time_stamp[j]) / 2 *\n                                  FrameShiftInMs()\n                            : start;\n                }\n\n                int end = time_stamp[j] * FrameShiftInMs();\n                if (j < input.size() - 1) {\n                    end =\n                        (time_stamp[j + 1] - time_stamp[j]) * FrameShiftInMs() <\n                                time_stamp_gap_\n                            ? (time_stamp[j + 1] + time_stamp[j]) / 2 *\n                                  FrameShiftInMs()\n                            : end;\n                }\n\n                WordPiece word_piece(word, offset + start, offset + end);\n                path.word_pieces.emplace_back(word_piece);\n            }\n        }\n\n        // if (post_processor_ != nullptr) {\n        //   path.sentence = post_processor_->Process(path.sentence, finish);\n        // }\n\n        result_.emplace_back(path);\n    }\n\n    if (DecodedSomething()) {\n        VLOG(1) << \"Partial CTC result \" << result_[0].sentence;\n    }\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_controller_impl.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"decoder/common.h\"\n#include \"fst/fstlib.h\"\n#include \"fst/symbol-table.h\"\n#include \"nnet/u2_nnet.h\"\n#include \"nnet/nnet_producer.h\"\n#ifdef USE_ONNX\n#include \"nnet/u2_onnx_nnet.h\"\n#endif\n#include \"nnet/decodable.h\"\n#include \"recognizer/recognizer_resource.h\"\n\n#include <memory>\n\nnamespace ppspeech {\n\nclass RecognizerControllerImpl {\n  public:\n    explicit RecognizerControllerImpl(const RecognizerResource& resource);\n    ~RecognizerControllerImpl();\n    void Accept(std::vector<float> data);\n    void InitDecoder();\n    void SetInputFinished();\n    std::string GetFinalResult();\n    std::string GetPartialResult();\n    void Rescoring();\n    void Reset();\n    void WaitDecoderFinished();\n    void WaitFinished();\n    void AttentionRescoring();\n    bool DecodedSomething() const {\n      return !result_.empty() && !result_[0].sentence.empty();\n    }\n    int FrameShiftInMs() const {\n      return 1; //todo\n    }\n\n  private:\n\n    static void RunNnetEvaluation(RecognizerControllerImpl* me);\n    void RunNnetEvaluationInternal();\n    static void RunDecoder(RecognizerControllerImpl* me);\n    void RunDecoderInternal();\n    void UpdateResult(bool finish = false);\n\n    std::shared_ptr<Decodable> decodable_;\n    std::unique_ptr<DecoderBase> decoder_;\n    std::shared_ptr<NnetProducer> nnet_producer_;\n\n    // e2e unit symbol table\n    std::shared_ptr<fst::SymbolTable> symbol_table_ = nullptr;\n    std::vector<DecodeResult> result_;\n\n    RecognizerResource opts_;\n    bool abort_ = false;\n    // global decoded frame offset\n    int global_frame_offset_;\n    // cur decoded frame num\n    int num_frames_;\n    // timestamp gap between words in a sentence\n    const int time_stamp_gap_ = 100;\n    bool input_finished_;\n\n    std::mutex nnet_mutex_;\n    std::mutex decoder_mutex_;\n    std::condition_variable nnet_condition_;\n    std::condition_variable decoder_condition_;\n    std::thread nnet_thread_;\n    std::thread decoder_thread_;\n\n    DISALLOW_COPY_AND_ASSIGN(RecognizerControllerImpl);\n};\n\n}\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_instance.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"recognizer/recognizer_instance.h\"\n\n\nnamespace ppspeech {\n\nRecognizerInstance& RecognizerInstance::GetInstance() {\n    static RecognizerInstance instance;\n    return instance;\n}\n\nbool RecognizerInstance::Init(const std::string& model_file, \n                              const std::string& word_symbol_table_file,\n                              const std::string& fst_file,\n                              int num_instance) {\n    RecognizerResource resource = RecognizerResource::InitFromFlags();\n    resource.model_opts.model_path = model_file;\n    //resource.vocab_path = word_symbol_table_file;\n    if (!fst_file.empty()) {\n        resource.decoder_opts.tlg_decoder_opts.fst_path = fst_file;\n        resource.decoder_opts.tlg_decoder_opts.fst_path = word_symbol_table_file;\n    } else {\n        resource.decoder_opts.ctc_prefix_search_opts.word_symbol_table = \n            word_symbol_table_file;\n    }\n    recognizer_controller_ = std::make_unique<RecognizerController>(num_instance, resource);\n    return true;\n}\n\nvoid RecognizerInstance::InitDecoder(int idx) {\n    recognizer_controller_->InitDecoder(idx);\n    return;\n}\n\nint RecognizerInstance::GetRecognizerInstanceId() {\n    return recognizer_controller_->GetRecognizerInstanceId();\n}\n\nvoid RecognizerInstance::Accept(const std::vector<float>& waves, int idx) const {\n    recognizer_controller_->Accept(waves, idx);\n    return;\n} \n\nvoid RecognizerInstance::SetInputFinished(int idx) const {\n    recognizer_controller_->SetInputFinished(idx);\n    return;\n}\n\nstd::string RecognizerInstance::GetResult(int idx) const {\n    return recognizer_controller_->GetFinalResult(idx);\n}\n\n}"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_instance.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"recognizer/recognizer_controller.h\"\n\nnamespace ppspeech {\n\nclass RecognizerInstance {\n  public:\n    static RecognizerInstance& GetInstance();\n    RecognizerInstance() {}\n    ~RecognizerInstance() {}\n    bool Init(const std::string& model_file, \n              const std::string& word_symbol_table_file,\n              const std::string& fst_file,\n              int num_instance);\n    int GetRecognizerInstanceId();\n    void InitDecoder(int idx);\n    void Accept(const std::vector<float>& waves, int idx) const; \n    void SetInputFinished(int idx) const;\n    std::string GetResult(int idx) const;\n\n  private:\n    std::unique_ptr<RecognizerController> recognizer_controller_;\n};\n\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"decoder/param.h\"\n#include \"frontend/wave-reader.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"recognizer/recognizer_controller.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test feature rspecifier\");\nDEFINE_string(result_wspecifier, \"\", \"test result wspecifier\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\nDEFINE_int32(sample_rate, 16000, \"sample rate\");\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    int32 num_done = 0, num_err = 0;\n    double tot_wav_duration = 0.0;\n    double tot_attention_rescore_time = 0.0;\n    double tot_decode_time = 0.0;\n\n    kaldi::SequentialTableReader<kaldi::WaveHolder> wav_reader(\n        FLAGS_wav_rspecifier);\n    kaldi::TokenWriter result_writer(FLAGS_result_wspecifier);\n\n    int sample_rate = FLAGS_sample_rate;\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * sample_rate;\n    LOG(INFO) << \"sr: \" << sample_rate;\n    LOG(INFO) << \"chunk size (s): \" << streaming_chunk;\n    LOG(INFO) << \"chunk size (sample): \" << chunk_sample_size;\n\n    ppspeech::RecognizerResource resource =\n        ppspeech::RecognizerResource::InitFromFlags();\n    std::shared_ptr<ppspeech::RecognizerControllerImpl> recognizer_ptr(\n        new ppspeech::RecognizerControllerImpl(resource));\n\n    for (; !wav_reader.Done(); wav_reader.Next()) {\n        recognizer_ptr->InitDecoder();\n        std::string utt = wav_reader.Key();\n        const kaldi::WaveData& wave_data = wav_reader.Value();\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"wav dur: \" << wave_data.Duration() << \" sec.\";\n        double dur = wave_data.Duration();\n        tot_wav_duration += dur;\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        int tot_samples = waveform.Dim();\n        LOG(INFO) << \"wav len (sample): \" << tot_samples;\n\n        int sample_offset = 0;\n        kaldi::Timer local_timer;\n\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            std::vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = waveform(sample_offset + i);\n            }\n\n            recognizer_ptr->Accept(wav_chunk);\n\n            // no overlap\n            sample_offset += cur_chunk_size;\n        }\n        CHECK(sample_offset == tot_samples);\n        recognizer_ptr->SetInputFinished();\n        recognizer_ptr->WaitDecoderFinished();\n\n        kaldi::Timer timer;\n        recognizer_ptr->AttentionRescoring();\n        float rescore_time = timer.Elapsed();\n        tot_attention_rescore_time += rescore_time;\n\n        std::string result = recognizer_ptr->GetFinalResult();\n        if (result.empty()) {\n            // the TokenWriter can not write empty string.\n            ++num_err;\n            LOG(INFO) << \" the result of \" << utt << \" is empty\";\n            continue;\n        }\n\n        tot_decode_time += local_timer.Elapsed();\n        LOG(INFO) << utt << \" \" << result;\n        LOG(INFO) << \" RTF: \" << local_timer.Elapsed() / dur << \" dur: \" << dur\n                  << \" cost: \" << local_timer.Elapsed() << \" rescore:\" << rescore_time;\n\n        result_writer.Write(utt, result);\n\n        ++num_done;\n    }\n    recognizer_ptr->WaitFinished();\n\n    LOG(INFO) << \"Done \" << num_done << \" out of \" << (num_err + num_done);\n    LOG(INFO) << \"total wav duration is: \" << tot_wav_duration << \" sec\";\n    LOG(INFO) << \"total decode cost:\" << tot_decode_time << \" sec\";\n    LOG(INFO) << \"total rescore cost:\" << tot_attention_rescore_time << \" sec\";\n    LOG(INFO) << \"RTF is: \" << tot_decode_time / tot_wav_duration;\n}\n"
  },
  {
    "path": "runtime/engine/asr/recognizer/recognizer_resource.h",
    "content": "#pragma once\n\n#include \"decoder/ctc_beam_search_opt.h\"\n#include \"decoder/ctc_tlg_decoder.h\"\n#include \"frontend/feature_pipeline.h\"\n\nDECLARE_int32(nnet_decoder_chunk);\nDECLARE_int32(num_left_chunks);\nDECLARE_double(ctc_weight);\nDECLARE_double(rescoring_weight);\nDECLARE_double(reverse_weight);\nDECLARE_int32(nbest);\nDECLARE_int32(blank);\nDECLARE_double(acoustic_scale);\nDECLARE_double(blank_threshold);\nDECLARE_string(word_symbol_table);\n\nnamespace ppspeech {\n\nstruct DecodeOptions {\n    // chunk_size is the frame number of one chunk after subsampling.\n    // e.g. if subsample rate is 4 and chunk_size = 16, the frames in\n    // one chunk are 67=16*4 + 3, stride is 64=16*4\n    int chunk_size{16};\n    int num_left_chunks{-1};\n\n    // final_score = rescoring_weight * rescoring_score + ctc_weight *\n    // ctc_score;\n    // rescoring_score = left_to_right_score * (1 - reverse_weight) +\n    // right_to_left_score * reverse_weight\n    // Please note the concept of ctc_scores\n    // in the following two search methods are different. For\n    // CtcPrefixBeamSerch,\n    // it's a sum(prefix) score + context score For CtcWfstBeamSerch, it's a\n    // max(viterbi) path score + context score So we should carefully set\n    // ctc_weight accroding to the search methods.\n    float ctc_weight{0.0};\n    float rescoring_weight{1.0};\n    float reverse_weight{0.0};\n\n    // CtcEndpointConfig ctc_endpoint_opts;\n    CTCBeamSearchOptions ctc_prefix_search_opts{};\n    TLGDecoderOptions tlg_decoder_opts{};\n\n    static DecodeOptions InitFromFlags() {\n        DecodeOptions decoder_opts;\n        decoder_opts.chunk_size = FLAGS_nnet_decoder_chunk;\n        decoder_opts.num_left_chunks = FLAGS_num_left_chunks;\n        decoder_opts.ctc_weight = FLAGS_ctc_weight;\n        decoder_opts.rescoring_weight = FLAGS_rescoring_weight;\n        decoder_opts.reverse_weight = FLAGS_reverse_weight;\n        decoder_opts.ctc_prefix_search_opts.blank = FLAGS_blank;\n        decoder_opts.ctc_prefix_search_opts.first_beam_size = FLAGS_nbest;\n        decoder_opts.ctc_prefix_search_opts.second_beam_size = FLAGS_nbest;\n        decoder_opts.ctc_prefix_search_opts.word_symbol_table = \n            FLAGS_word_symbol_table;\n        decoder_opts.tlg_decoder_opts =\n            ppspeech::TLGDecoderOptions::InitFromFlags();\n\n        LOG(INFO) << \"chunk_size: \" << decoder_opts.chunk_size;\n        LOG(INFO) << \"num_left_chunks: \" << decoder_opts.num_left_chunks;\n        LOG(INFO) << \"ctc_weight: \" << decoder_opts.ctc_weight;\n        LOG(INFO) << \"rescoring_weight: \" << decoder_opts.rescoring_weight;\n        LOG(INFO) << \"reverse_weight: \" << decoder_opts.reverse_weight;\n        LOG(INFO) << \"blank: \" << FLAGS_blank;\n        LOG(INFO) << \"first_beam_size: \" << FLAGS_nbest;\n        LOG(INFO) << \"second_beam_size: \" << FLAGS_nbest;\n        return decoder_opts;\n    }\n};\n\nstruct RecognizerResource {\n    // decodable opt \n    kaldi::BaseFloat acoustic_scale{1.0};\n    kaldi::BaseFloat blank_threshold{0.98};\n\n    FeaturePipelineOptions feature_pipeline_opts{};\n    ModelOptions model_opts{};\n    DecodeOptions decoder_opts{};\n    std::shared_ptr<NnetBase> nnet;\n\n    static RecognizerResource InitFromFlags() {\n        RecognizerResource resource;\n        resource.acoustic_scale = FLAGS_acoustic_scale;\n        resource.blank_threshold = FLAGS_blank_threshold;\n        LOG(INFO) << \"acoustic_scale: \" << resource.acoustic_scale;\n\n        resource.feature_pipeline_opts =\n            ppspeech::FeaturePipelineOptions::InitFromFlags();\n        resource.feature_pipeline_opts.assembler_opts.fill_zero = false;\n        LOG(INFO) << \"u2 need fill zero be false: \"\n                  << resource.feature_pipeline_opts.assembler_opts.fill_zero;\n        resource.model_opts = ppspeech::ModelOptions::InitFromFlags();\n        resource.decoder_opts = ppspeech::DecodeOptions::InitFromFlags();\n        #ifndef USE_ONNX\n            resource.nnet.reset(new U2Nnet(resource.model_opts));\n        #else\n            if (resource.model_opts.with_onnx_model){\n                resource.nnet.reset(new U2OnnxNnet(resource.model_opts));\n            } else {\n                resource.nnet.reset(new U2Nnet(resource.model_opts));\n            }\n        #endif\n        return resource;\n    }\n};\n\n} //namespace ppspeech"
  },
  {
    "path": "runtime/engine/asr/server/CMakeLists.txt",
    "content": "#add_subdirectory(websocket)\n"
  },
  {
    "path": "runtime/engine/asr/server/websocket/CMakeLists.txt",
    "content": "add_library(websocket STATIC\n  websocket_server.cc\n  websocket_client.cc\n)\ntarget_link_libraries(websocket PUBLIC frontend nnet decoder recognizer)\n\nadd_executable(websocket_server_main ${CMAKE_CURRENT_SOURCE_DIR}/websocket_server_main.cc)\ntarget_include_directories(websocket_server_main PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\ntarget_link_libraries(websocket_server_main PUBLIC fst websocket ${DEPS})\n\nadd_executable(websocket_client_main ${CMAKE_CURRENT_SOURCE_DIR}/websocket_client_main.cc)\ntarget_include_directories(websocket_client_main PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\ntarget_link_libraries(websocket_client_main PUBLIC fst websocket ${DEPS})"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_client.cc",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n//               2022 PaddlePaddle Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"websocket/websocket_client.h\"\n\n#include \"boost/json/src.hpp\"\n\nnamespace json = boost::json;\n\nnamespace ppspeech {\n\nWebSocketClient::WebSocketClient(const std::string& host, int port)\n    : host_(host), port_(port) {\n    Connect();\n    t_.reset(new std::thread(&WebSocketClient::ReadLoopFunc, this));\n}\n\nvoid WebSocketClient::Connect() {\n    tcp::resolver resolver{ioc_};\n    // Look up the domain name\n    auto const results = resolver.resolve(host_, std::to_string(port_));\n    // Make the connection on the IP address we get from a lookup\n    auto ep = asio::connect(ws_.next_layer(), results);\n    // Update the host_ string. This will provide the value of the\n    // Host HTTP header during the WebSocket handshake.\n    // See https://tools.ietf.org/html/rfc7230#section-5.4\n    std::string host = host_ + \":\" + std::to_string(ep.port());\n    // Perform the websocket handshake\n    ws_.handshake(host, \"/\");\n}\n\nvoid WebSocketClient::SendTextData(const std::string& data) {\n    ws_.text(true);\n    ws_.write(asio::buffer(data));\n}\n\nvoid WebSocketClient::SendBinaryData(const void* data, size_t size) {\n    ws_.binary(true);\n    ws_.write(asio::buffer(data, size));\n}\n\nvoid WebSocketClient::Close() { ws_.close(websocket::close_code::normal); }\n\nvoid WebSocketClient::ReadLoopFunc() {\n    try {\n        while (true) {\n            beast::flat_buffer buffer;\n            ws_.read(buffer);\n            std::string message = beast::buffers_to_string(buffer.data());\n            LOG(INFO) << message;\n            CHECK(ws_.got_text());\n            json::object obj = json::parse(message).as_object();\n            if (obj[\"status\"] != \"ok\") {\n                break;\n            }\n            if (obj[\"type\"] == \"final_result\") {\n                result_ = obj[\"result\"].as_string().c_str();\n            }\n            if (obj[\"type\"] == \"partial_result\") {\n                partial_result_ = obj[\"result\"].as_string().c_str();\n            }\n            if (obj[\"type\"] == \"speech_end\") {\n                done_ = true;\n                break;\n            }\n        }\n    } catch (beast::system_error const& se) {\n        // This indicates that the session was closed\n        if (se.code() != websocket::error::closed) {\n            LOG(ERROR) << se.code().message();\n        }\n    } catch (std::exception const& e) {\n        LOG(ERROR) << e.what();\n    }\n}\n\nvoid WebSocketClient::Join() { t_->join(); }\n\nvoid WebSocketClient::SendStartSignal() {\n    json::value start_tag = {{\"signal\", \"start\"}};\n    std::string start_message = json::serialize(start_tag);\n    this->SendTextData(start_message);\n}\n\nvoid WebSocketClient::SendDataEnd() {\n    json::value end_tag = {{\"data\", \"end\"}};\n    std::string end_message = json::serialize(end_tag);\n    this->SendTextData(end_message);\n}\n\nvoid WebSocketClient::SendEndSignal() {\n    json::value end_tag = {{\"signal\", \"end\"}};\n    std::string end_message = json::serialize(end_tag);\n    this->SendTextData(end_message);\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_client.h",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n//               2022 PaddlePaddle Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/common.h\"\n#include \"boost/asio/connect.hpp\"\n#include \"boost/asio/ip/tcp.hpp\"\n#include \"boost/beast/core.hpp\"\n#include \"boost/beast/websocket.hpp\"\n\nnamespace beast = boost::beast;          // from <boost/beast.hpp>\nnamespace http = beast::http;            // from <boost/beast/http.hpp>\nnamespace websocket = beast::websocket;  // from <boost/beast/websocket.hpp>\nnamespace asio = boost::asio;            // from <boost/asio.hpp>\nusing tcp = boost::asio::ip::tcp;        // from <boost/asio/ip/tcp.hpp>\n\nnamespace ppspeech {\n\nclass WebSocketClient {\n  public:\n    WebSocketClient(const std::string& host, int port);\n\n    void SendTextData(const std::string& data);\n    void SendBinaryData(const void* data, size_t size);\n    void ReadLoopFunc();\n    void Close();\n    void Join();\n    void SendStartSignal();\n    void SendEndSignal();\n    void SendDataEnd();\n    bool Done() const { return done_; }\n    std::string GetResult() const { return result_; }\n    std::string GetPartialResult() const { return partial_result_; }\n\n  private:\n    void Connect();\n    std::string host_;\n    std::string result_;\n    std::string partial_result_;\n    int port_;\n    bool done_ = false;\n    asio::io_context ioc_;\n    websocket::stream<tcp::socket> ws_{ioc_};\n    std::unique_ptr<std::thread> t_{nullptr};\n};\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_client_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"kaldi/feat/wave-reader.h\"\n#include \"kaldi/util/kaldi-io.h\"\n#include \"kaldi/util/table-types.h\"\n#include \"websocket/websocket_client.h\"\n\nDEFINE_string(host, \"127.0.0.1\", \"host of websocket server\");\nDEFINE_int32(port, 8082, \"port of websocket server\");\nDEFINE_string(wav_rspecifier, \"\", \"test wav scp path\");\nDEFINE_double(streaming_chunk, 0.1, \"streaming feature chunk size\");\n\nusing kaldi::int16;\nint main(int argc, char* argv[]) {\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n\n    kaldi::SequentialTableReader<kaldi::WaveHolder> wav_reader(\n        FLAGS_wav_rspecifier);\n\n    const int sample_rate = 16000;\n    const float streaming_chunk = FLAGS_streaming_chunk;\n    const int chunk_sample_size = streaming_chunk * sample_rate;\n\n    for (; !wav_reader.Done(); wav_reader.Next()) {\n        ppspeech::WebSocketClient client(FLAGS_host, FLAGS_port);\n\n        client.SendStartSignal();\n        std::string utt = wav_reader.Key();\n        const kaldi::WaveData& wave_data = wav_reader.Value();\n        CHECK_EQ(wave_data.SampFreq(), sample_rate);\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        const int tot_samples = waveform.Dim();\n        int sample_offset = 0;\n\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            std::vector<int16> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = static_cast<int16>(waveform(sample_offset + i));\n            }\n            client.SendBinaryData(wav_chunk.data(),\n                                  wav_chunk.size() * sizeof(int16));\n\n            sample_offset += cur_chunk_size;\n            LOG(INFO) << \"Send \" << cur_chunk_size << \" samples\";\n            std::this_thread::sleep_for(\n                std::chrono::milliseconds(static_cast<int>(1 * 1000)));\n\n            if (cur_chunk_size < chunk_sample_size) {\n                client.SendEndSignal();\n            }\n        }\n\n        while (!client.Done()) {\n        }\n        std::string result = client.GetResult();\n        LOG(INFO) << \"utt: \" << utt << \" \" << result;\n\n        client.Join();\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_server.cc",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n//               2022 PaddlePaddle Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"websocket/websocket_server.h\"\n\n#include \"base/common.h\"\n#include \"boost/json/src.hpp\"\n\nnamespace json = boost::json;\n\nnamespace ppspeech {\n\nConnectionHandler::ConnectionHandler(\n    tcp::socket&& socket, const RecognizerResource& recognizer_resource)\n    : ws_(std::move(socket)), recognizer_resource_(recognizer_resource) {}\n\nvoid ConnectionHandler::OnSpeechStart() {\n    recognizer_ = std::make_shared<Recognizer>(recognizer_resource_);\n    // Start decoder thread\n    decode_thread_ = std::make_shared<std::thread>(\n        &ConnectionHandler::DecodeThreadFunc, this);\n    got_start_tag_ = true;\n    LOG(INFO) << \"Server: Received speech start signal, start reading speech\";\n    json::value rv = {{\"status\", \"ok\"}, {\"type\", \"server_ready\"}};\n    ws_.text(true);\n    ws_.write(asio::buffer(json::serialize(rv)));\n}\n\nvoid ConnectionHandler::OnSpeechEnd() {\n    LOG(INFO) << \"Server: Received speech end signal\";\n    if (recognizer_ != nullptr) {\n        recognizer_->SetFinished();\n    }\n    got_end_tag_ = true;\n}\n\nvoid ConnectionHandler::OnFinalResult(const std::string& result) {\n    LOG(INFO) << \"Server: Final result: \" << result;\n    json::value rv = {\n        {\"status\", \"ok\"}, {\"type\", \"final_result\"}, {\"result\", result}};\n    ws_.text(true);\n    ws_.write(asio::buffer(json::serialize(rv)));\n}\n\nvoid ConnectionHandler::OnFinish() {\n    // Send finish tag\n    json::value rv = {{\"status\", \"ok\"}, {\"type\", \"speech_end\"}};\n    ws_.text(true);\n    ws_.write(asio::buffer(json::serialize(rv)));\n}\n\nvoid ConnectionHandler::OnSpeechData(const beast::flat_buffer& buffer) {\n    // Read binary PCM data\n    int num_samples = buffer.size() / sizeof(int16_t);\n    kaldi::Vector<kaldi::BaseFloat> pcm_data(num_samples);\n    const int16_t* pdata = static_cast<const int16_t*>(buffer.data().data());\n    for (int i = 0; i < num_samples; i++) {\n        pcm_data(i) = static_cast<float>(*pdata);\n        pdata++;\n    }\n    VLOG(2) << \"Server: Received \" << num_samples << \" samples\";\n    LOG(INFO) << \"Server: Received \" << num_samples << \" samples\";\n    CHECK(recognizer_ != nullptr);\n    recognizer_->Accept(pcm_data);\n\n    std::string partial_result = recognizer_->GetPartialResult();\n\n    json::value rv = {{\"status\", \"ok\"},\n                      {\"type\", \"partial_result\"},\n                      {\"result\", partial_result}};\n    ws_.text(true);\n    ws_.write(asio::buffer(json::serialize(rv)));\n}\n\nvoid ConnectionHandler::DecodeThreadFunc() {\n    try {\n        while (true) {\n            recognizer_->Decode();\n            if (recognizer_->IsFinished()) {\n                LOG(INFO) << \"Server: enter finish\";\n                recognizer_->Decode();\n                LOG(INFO) << \"Server: finish\";\n                std::string result = recognizer_->GetFinalResult();\n                OnFinalResult(result);\n                OnFinish();\n                stop_recognition_ = true;\n                break;\n            }\n        }\n    } catch (std::exception const& e) {\n        LOG(ERROR) << e.what();\n    }\n}\n\nvoid ConnectionHandler::OnError(const std::string& message) {\n    json::value rv = {{\"status\", \"failed\"}, {\"message\", message}};\n    ws_.text(true);\n    ws_.write(asio::buffer(json::serialize(rv)));\n    // Close websocket\n    ws_.close(websocket::close_code::normal);\n}\n\nvoid ConnectionHandler::OnText(const std::string& message) {\n    json::value v = json::parse(message);\n    if (v.is_object()) {\n        json::object obj = v.get_object();\n        if (obj.find(\"signal\") != obj.end()) {\n            json::string signal = obj[\"signal\"].as_string();\n            if (signal == \"start\") {\n                OnSpeechStart();\n            } else if (signal == \"end\") {\n                OnSpeechEnd();\n            } else {\n                OnError(\"Unexpected signal type\");\n            }\n        } else {\n            OnError(\"Wrong message header\");\n        }\n    } else {\n        OnError(\"Wrong protocol\");\n    }\n}\n\nvoid ConnectionHandler::operator()() {\n    try {\n        // Accept the websocket handshake\n        ws_.accept();\n        for (;;) {\n            // This buffer will hold the incoming message\n            beast::flat_buffer buffer;\n            // Read a message\n            ws_.read(buffer);\n            if (ws_.got_text()) {\n                std::string message = beast::buffers_to_string(buffer.data());\n                LOG(INFO) << \"Server: Text: \" << message;\n                OnText(message);\n                if (got_end_tag_) {\n                    break;\n                }\n            } else {\n                if (!got_start_tag_) {\n                    OnError(\"Start signal is expected before binary data\");\n                } else {\n                    if (stop_recognition_) {\n                        break;\n                    }\n                    OnSpeechData(buffer);\n                }\n            }\n        }\n\n        LOG(INFO) << \"Server: finished to wait for decoding thread join.\";\n        if (decode_thread_ != nullptr) {\n            decode_thread_->join();\n        }\n    } catch (beast::system_error const& se) {\n        // This indicates that the session was closed\n        if (se.code() != websocket::error::closed) {\n            if (decode_thread_ != nullptr) {\n                decode_thread_->join();\n            }\n            OnSpeechEnd();\n            LOG(ERROR) << se.code().message();\n        }\n    } catch (std::exception const& e) {\n        LOG(ERROR) << e.what();\n    }\n}\n\nvoid WebSocketServer::Start() {\n    try {\n        auto const address = asio::ip::make_address(\"0.0.0.0\");\n        tcp::acceptor acceptor{ioc_, {address, static_cast<uint16_t>(port_)}};\n        for (;;) {\n            // This will receive the new connection\n            tcp::socket socket{ioc_};\n            // Block until we get a connection\n            acceptor.accept(socket);\n            // Launch the session, transferring ownership of the socket\n            ConnectionHandler handler(std::move(socket), recognizer_resource_);\n            std::thread t(std::move(handler));\n            t.detach();\n        }\n    } catch (const std::exception& e) {\n        LOG(FATAL) << e.what();\n    }\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_server.h",
    "content": "// Copyright (c) 2020 Mobvoi Inc (Binbin Zhang)\n//               2022 PaddlePaddle Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"boost/asio/connect.hpp\"\n#include \"boost/asio/ip/tcp.hpp\"\n#include \"boost/beast/core.hpp\"\n#include \"boost/beast/websocket.hpp\"\n#include \"frontend/audio/feature_pipeline.h\"\n#include \"recognizer/recognizer.h\"\n\nnamespace beast = boost::beast;          // from <boost/beast.hpp>\nnamespace http = beast::http;            // from <boost/beast/http.hpp>\nnamespace websocket = beast::websocket;  // from <boost/beast/websocket.hpp>\nnamespace asio = boost::asio;            // from <boost/asio.hpp>\nusing tcp = boost::asio::ip::tcp;        // from <boost/asio/ip/tcp.hpp>\n\nnamespace ppspeech {\nclass ConnectionHandler {\n  public:\n    ConnectionHandler(tcp::socket&& socket,\n                      const RecognizerResource& recognizer_resource_);\n    void operator()();\n\n  private:\n    void OnSpeechStart();\n    void OnSpeechEnd();\n    void OnText(const std::string& message);\n    void OnFinish();\n    void OnSpeechData(const beast::flat_buffer& buffer);\n    void OnError(const std::string& message);\n    void OnFinalResult(const std::string& result);\n    void DecodeThreadFunc();\n    std::string SerializeResult(bool finish);\n\n    bool continuous_decoding_ = false;\n    int nbest_ = 1;\n    websocket::stream<tcp::socket> ws_;\n    RecognizerResource recognizer_resource_;\n\n    bool got_start_tag_ = false;\n    bool got_end_tag_ = false;\n    // When endpoint is detected, stop recognition, and stop receiving data.\n    bool stop_recognition_ = false;\n    std::shared_ptr<ppspeech::Recognizer> recognizer_ = nullptr;\n    std::shared_ptr<std::thread> decode_thread_ = nullptr;\n};\n\nclass WebSocketServer {\n  public:\n    WebSocketServer(int port, const RecognizerResource& recognizer_resource)\n        : port_(port), recognizer_resource_(recognizer_resource) {}\n\n    void Start();\n\n  private:\n    int port_;\n    RecognizerResource recognizer_resource_;\n    // The io_context is required for all I/O\n    asio::io_context ioc_{1};\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/asr/server/websocket/websocket_server_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"decoder/param.h\"\n#include \"websocket/websocket_server.h\"\n\nDEFINE_int32(port, 8082, \"websocket listening port\");\n\nppspeech::RecognizerResource InitRecognizerResoure() {\n    ppspeech::RecognizerResource resource;\n    resource.acoustic_scale = FLAGS_acoustic_scale;\n    resource.feature_pipeline_opts =\n        ppspeech::FeaturePipelineOptions::InitFromFlags();\n    resource.model_opts = ppspeech::ModelOptions::InitFromFlags();\n    resource.tlg_opts = ppspeech::TLGDecoderOptions::InitFromFlags();\n    return resource;\n}\n\nint main(int argc, char *argv[]) {\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n\n    ppspeech::RecognizerResource resource = InitRecognizerResoure();\n\n    ppspeech::WebSocketServer server(FLAGS_port, resource);\n    LOG(INFO) << \"Listening at port \" << FLAGS_port;\n    server.Start();\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/audio_classification/CMakeLists.txt",
    "content": "# add_definitions(\"-DUSE_PADDLE_INFERENCE_BACKEND\")\nadd_definitions(\"-DUSE_ORT_BACKEND\")\nadd_subdirectory(nnet)"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/CMakeLists.txt",
    "content": "set(srcs \n    panns_nnet.cc \n    panns_interface.cc\n)\n\nadd_library(cls SHARED ${srcs})\ntarget_link_libraries(cls PRIVATE ${FASTDEPLOY_LIBS} kaldi-matrix kaldi-base frontend utils )\n\nset(bin_name panns_nnet_main)\nadd_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\ntarget_link_libraries(${bin_name} gflags glog cls)\n"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/panns_interface.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"audio_classification/nnet/panns_interface.h\"\n\n#include \"audio_classification/nnet/panns_nnet.h\"\n#include \"common/base/config.h\"\n\nnamespace ppspeech {\n\nvoid* ClsCreateInstance(const char* conf_path) {\n    Config conf(conf_path);\n    // cls init\n    ppspeech::ClsNnetConf cls_nnet_conf;\n    cls_nnet_conf.wav_normal_ = conf.Read(\"wav_normal\", true);\n    cls_nnet_conf.wav_normal_type_ =\n        conf.Read(\"wav_normal_type\", std::string(\"linear\"));\n    cls_nnet_conf.wav_norm_mul_factor_ = conf.Read(\"wav_norm_mul_factor\", 1.0);\n    cls_nnet_conf.model_file_path_ = conf.Read(\"model_path\", std::string(\"\"));\n    cls_nnet_conf.param_file_path_ = conf.Read(\"param_path\", std::string(\"\"));\n    cls_nnet_conf.dict_file_path_ = conf.Read(\"dict_path\", std::string(\"\"));\n    cls_nnet_conf.num_cpu_thread_ = conf.Read(\"num_cpu_thread\", 12);\n    cls_nnet_conf.samp_freq = conf.Read(\"samp_freq\", 32000);\n    cls_nnet_conf.frame_length_ms = conf.Read(\"frame_length_ms\", 32);\n    cls_nnet_conf.frame_shift_ms = conf.Read(\"frame_shift_ms\", 10);\n    cls_nnet_conf.num_bins = conf.Read(\"num_bins\", 64);\n    cls_nnet_conf.low_freq = conf.Read(\"low_freq\", 50);\n    cls_nnet_conf.high_freq = conf.Read(\"high_freq\", 14000);\n    cls_nnet_conf.dither = conf.Read(\"dither\", 0.0);\n\n    ppspeech::ClsNnet* cls_model = new ppspeech::ClsNnet();\n    int ret = cls_model->Init(cls_nnet_conf);\n    return static_cast<void*>(cls_model);\n}\n\nint ClsDestroyInstance(void* instance) {\n    ppspeech::ClsNnet* cls_model = static_cast<ppspeech::ClsNnet*>(instance);\n    if (cls_model != NULL) {\n        delete cls_model;\n        cls_model = NULL;\n    }\n    return 0;\n}\n\nint ClsFeedForward(void* instance,\n                   const char* wav_path,\n                   int topk,\n                   char* result,\n                   int result_max_len) {\n    ppspeech::ClsNnet* cls_model = static_cast<ppspeech::ClsNnet*>(instance);\n    if (cls_model == NULL) {\n        printf(\"instance is null\\n\");\n        return -1;\n    }\n    int ret = cls_model->Forward(wav_path, topk, result, result_max_len);\n    return 0;\n}\n\nint ClsReset(void* instance) {\n    ppspeech::ClsNnet* cls_model = static_cast<ppspeech::ClsNnet*>(instance);\n    if (cls_model == NULL) {\n        printf(\"instance is null\\n\");\n        return -1;\n    }\n    cls_model->Reset();\n    return 0;\n}\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/panns_interface.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\nnamespace ppspeech {\n\nvoid* ClsCreateInstance(const char* conf_path);\nint ClsDestroyInstance(void* instance);\nint ClsFeedForward(void* instance,\n                   const char* wav_path,\n                   int topk,\n                   char* result,\n                   int result_max_len);\nint ClsReset(void* instance);\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/panns_nnet.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"audio_classification/nnet/panns_nnet.h\"\n#ifdef WITH_PROFILING\n#include \"kaldi/base/timer.h\"\n#endif\n\nnamespace ppspeech {\n\nClsNnet::ClsNnet() {\n    // wav_reader_ = NULL;\n    runtime_ = NULL;\n}\n\nvoid ClsNnet::Reset() {\n    // wav_reader_->Clear();\n    ss_.str(\"\");\n}\n\nint ClsNnet::Init(const ClsNnetConf& conf) {\n    conf_ = conf;\n    // init fbank opts\n    fbank_opts_.frame_opts.samp_freq = conf.samp_freq;\n    fbank_opts_.frame_opts.frame_length_ms = conf.frame_length_ms;\n    fbank_opts_.frame_opts.frame_shift_ms = conf.frame_shift_ms;\n    fbank_opts_.mel_opts.num_bins = conf.num_bins;\n    fbank_opts_.mel_opts.low_freq = conf.low_freq;\n    fbank_opts_.mel_opts.high_freq = conf.high_freq;\n    fbank_opts_.frame_opts.dither = conf.dither;\n    fbank_opts_.use_log_fbank = false;\n\n    // init dict\n    if (conf.dict_file_path_ != \"\") {\n        ReadFileToVector(conf.dict_file_path_, &dict_);\n    }\n\n    // init model\n    fastdeploy::RuntimeOption runtime_option;\n\n#ifdef USE_PADDLE_INFERENCE_BACKEND\n    runtime_option.SetModelPath(conf.model_file_path_,\n                                conf.param_file_path_,\n                                fastdeploy::ModelFormat::PADDLE);\n    runtime_option.UsePaddleInferBackend();\n#elif defined(USE_ORT_BACKEND)\n    runtime_option.SetModelPath(\n        conf.model_file_path_, \"\", fastdeploy::ModelFormat::ONNX);  // onnx\n    runtime_option.UseOrtBackend();                                 // onnx\n#elif defined(USE_PADDLE_LITE_BACKEND)\n    runtime_option.SetModelPath(conf.model_file_path_,\n                                conf.param_file_path_,\n                                fastdeploy::ModelFormat::PADDLE);\n    runtime_option.UseLiteBackend();\n#endif\n\n    runtime_option.SetCpuThreadNum(conf.num_cpu_thread_);\n    // runtime_option.DeletePaddleBackendPass(\"simplify_with_basic_ops_pass\");\n    runtime_ = std::unique_ptr<fastdeploy::Runtime>(new fastdeploy::Runtime());\n    if (!runtime_->Init(runtime_option)) {\n        std::cerr << \"--- Init FastDeploy Runitme Failed! \"\n                  << \"\\n--- Model:  \" << conf.model_file_path_ << std::endl;\n        return -1;\n    } else {\n        std::cout << \"--- Init FastDeploy Runitme Done! \"\n                  << \"\\n--- Model:  \" << conf.model_file_path_ << std::endl;\n    }\n\n    Reset();\n    return 0;\n}\n\nint ClsNnet::Forward(const char* wav_path,\n                     int topk,\n                     char* result,\n                     int result_max_len) {\n#ifdef WITH_PROFILING\n    kaldi::Timer timer;\n    timer.Reset();\n#endif\n    // read wav\n    std::ifstream infile(wav_path, std::ifstream::in);\n    kaldi::WaveData wave_data;\n    wave_data.Read(infile);\n    int32 this_channel = 0;\n    kaldi::Matrix<float> wavform_kaldi = wave_data.Data();\n    // only get channel 0\n    int wavform_len = wavform_kaldi.NumCols();\n    std::vector<float> wavform(wavform_kaldi.Data(),\n                               wavform_kaldi.Data() + wavform_len);\n    WaveformFloatNormal(&wavform);\n    WaveformNormal(&wavform,\n                   conf_.wav_normal_,\n                   conf_.wav_normal_type_,\n                   conf_.wav_norm_mul_factor_);\n#ifdef PPS_DEBUG\n    {\n        std::ofstream fp(\"cls.wavform\", std::ios::out);\n        for (int i = 0; i < wavform.size(); ++i) {\n            fp << std::setprecision(18) << wavform[i] << \" \";\n        }\n        fp << \"\\n\";\n    }\n#endif\n#ifdef WITH_PROFILING\n    printf(\"wav read consume: %fs\\n\", timer.Elapsed());\n#endif\n\n#ifdef WITH_PROFILING\n    timer.Reset();\n#endif\n\n    std::vector<float> feats;\n    std::unique_ptr<ppspeech::FrontendInterface> data_source(\n        new ppspeech::DataCache());\n    ppspeech::Fbank fbank(fbank_opts_, std::move(data_source));\n    fbank.Accept(wavform);\n    fbank.SetFinished();\n    fbank.Read(&feats);\n\n    int feat_dim = fbank_opts_.mel_opts.num_bins;\n    int num_frames = feats.size() / feat_dim;\n\n    for (int i = 0; i < num_frames; ++i) {\n        for (int j = 0; j < feat_dim; ++j) {\n            feats[i * feat_dim + j] = PowerTodb(feats[i * feat_dim + j]);\n        }\n    }\n#ifdef PPS_DEBUG\n    {\n        std::ofstream fp(\"cls.feat\", std::ios::out);\n        for (int i = 0; i < num_frames; ++i) {\n            for (int j = 0; j < feat_dim; ++j) {\n                fp << std::setprecision(18) << feats[i * feat_dim + j] << \" \";\n            }\n            fp << \"\\n\";\n        }\n    }\n#endif\n#ifdef WITH_PROFILING\n    printf(\"extract fbank consume: %fs\\n\", timer.Elapsed());\n#endif\n\n    // infer\n    std::vector<float> model_out;\n#ifdef WITH_PROFILING\n    timer.Reset();\n#endif\n    ModelForward(feats.data(), num_frames, feat_dim, &model_out);\n#ifdef WITH_PROFILING\n    printf(\"fast deploy infer consume: %fs\\n\", timer.Elapsed());\n#endif\n#ifdef PPS_DEBUG\n    {\n        std::ofstream fp(\"cls.logits\", std::ios::out);\n        for (int i = 0; i < model_out.size(); ++i) {\n            fp << std::setprecision(18) << model_out[i] << \"\\n\";\n        }\n    }\n#endif\n\n    // construct result str\n    ss_ << \"{\";\n    GetTopkResult(topk, model_out);\n    ss_ << \"}\";\n\n    if (result_max_len <= ss_.str().size()) {\n        printf(\"result_max_len is short than result len\\n\");\n    }\n    snprintf(result, result_max_len, \"%s\", ss_.str().c_str());\n    return 0;\n}\n\nint ClsNnet::ModelForward(float* features,\n                          const int num_frames,\n                          const int feat_dim,\n                          std::vector<float>* model_out) {\n    // init input tensor shape\n    fastdeploy::TensorInfo info = runtime_->GetInputInfo(0);\n    info.shape = {1, num_frames, feat_dim};\n\n    std::vector<fastdeploy::FDTensor> input_tensors(1);\n    std::vector<fastdeploy::FDTensor> output_tensors(1);\n\n    input_tensors[0].SetExternalData({1, num_frames, feat_dim},\n                                     fastdeploy::FDDataType::FP32,\n                                     static_cast<void*>(features));\n\n    // get input name\n    input_tensors[0].name = info.name;\n\n    runtime_->Infer(input_tensors, &output_tensors);\n\n    // output_tensors[0].PrintInfo();\n    std::vector<int64_t> output_shape = output_tensors[0].Shape();\n    model_out->resize(output_shape[0] * output_shape[1]);\n    memcpy(static_cast<void*>(model_out->data()),\n           output_tensors[0].Data(),\n           output_shape[0] * output_shape[1] * sizeof(float));\n    return 0;\n}\n\nint ClsNnet::GetTopkResult(int k, const std::vector<float>& model_out) {\n    std::vector<float> values;\n    std::vector<int> indics;\n    TopK(model_out, k, &values, &indics);\n    for (int i = 0; i < k; ++i) {\n        if (i != 0) {\n            ss_ << \",\";\n        }\n        ss_ << \"\\\"\" << dict_[indics[i]] << \"\\\":\\\"\" << values[i] << \"\\\"\";\n    }\n    return 0;\n}\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/panns_nnet.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"common/frontend/data_cache.h\"\n#include \"common/frontend/fbank.h\"\n#include \"common/frontend/feature-fbank.h\"\n#include \"common/frontend/frontend_itf.h\"\n#include \"common/frontend/wave-reader.h\"\n#include \"common/utils/audio_process.h\"\n#include \"common/utils/file_utils.h\"\n#include \"fastdeploy/runtime.h\"\n#include \"kaldi/util/kaldi-io.h\"\n#include \"kaldi/util/table-types.h\"\n\nnamespace ppspeech {\nstruct ClsNnetConf {\n    // wav\n    bool wav_normal_;\n    std::string wav_normal_type_;\n    float wav_norm_mul_factor_;\n    // model\n    std::string model_file_path_;\n    std::string param_file_path_;\n    std::string dict_file_path_;\n    int num_cpu_thread_;\n    // fbank\n    float samp_freq;\n    float frame_length_ms;\n    float frame_shift_ms;\n    int num_bins;\n    float low_freq;\n    float high_freq;\n    float dither;\n};\n\nclass ClsNnet {\n  public:\n    ClsNnet();\n    int Init(const ClsNnetConf& conf);\n    int Forward(const char* wav_path,\n                int topk,\n                char* result,\n                int result_max_len);\n    void Reset();\n\n  private:\n    int ModelForward(float* features,\n                     const int num_frames,\n                     const int feat_dim,\n                     std::vector<float>* model_out);\n    int ModelForwardStream(std::vector<float>* feats);\n    int GetTopkResult(int k, const std::vector<float>& model_out);\n\n    ClsNnetConf conf_;\n    knf::FbankOptions fbank_opts_;\n    std::unique_ptr<fastdeploy::Runtime> runtime_;\n    std::vector<std::string> dict_;\n    std::stringstream ss_;\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/audio_classification/nnet/panns_nnet_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <fstream>\n#include <string>\n\n#include \"gflags/gflags.h\"\n#include \"glog/logging.h\"\n#include \"audio_classification/nnet/panns_interface.h\"\n\nDEFINE_string(conf_path, \"\", \"config path\");\nDEFINE_string(scp_path, \"\", \"wav scp path\");\nDEFINE_string(topk, \"\", \"print topk results\");\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n    CHECK_GT(FLAGS_conf_path.size(), 0);\n    CHECK_GT(FLAGS_scp_path.size(), 0);\n    CHECK_GT(FLAGS_topk.size(), 0);\n    void* instance = ppspeech::ClsCreateInstance(FLAGS_conf_path.c_str());\n    int ret = 0;\n    // read wav\n    std::ifstream ifs(FLAGS_scp_path);\n    std::string line = \"\";\n    int topk = std::atoi(FLAGS_topk.c_str());\n    while (getline(ifs, line)) {\n        // read wav\n        char result[1024] = {0};\n        ret = ppspeech::ClsFeedForward(\n            instance, line.c_str(), topk, result, 1024);\n        printf(\"%s %s\\n\", line.c_str(), result);\n        ret = ppspeech::ClsReset(instance);\n    }\n    ret = ppspeech::ClsDestroyInstance(instance);\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/codelab/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14 FATAL_ERROR)\n\nif(ANDROID)\nelse() #Unix\n    add_subdirectory(glog)\nendif()"
  },
  {
    "path": "runtime/engine/codelab/README.md",
    "content": "\n## For Developer  \n\n> Reminder: Only for developer.\n\n* codelab - for speechx developer, using for test.\n"
  },
  {
    "path": "runtime/engine/common/CMakeLists.txt",
    "content": "include_directories(\n${CMAKE_CURRENT_SOURCE_DIR}\n${CMAKE_CURRENT_SOURCE_DIR}/../\n)\nadd_subdirectory(base)\nadd_subdirectory(utils)\nadd_subdirectory(matrix)\n\ninclude_directories(\n${CMAKE_CURRENT_SOURCE_DIR}/frontend\n)\nadd_subdirectory(frontend)\n\nadd_library(common INTERFACE)\ntarget_link_libraries(common  INTERFACE base utils kaldi-matrix frontend)\ninstall(TARGETS base DESTINATION lib)\ninstall(TARGETS utils DESTINATION lib)\ninstall(TARGETS kaldi-matrix DESTINATION lib)\ninstall(TARGETS frontend DESTINATION lib)"
  },
  {
    "path": "runtime/engine/common/base/CMakeLists.txt",
    "content": "\n\nif(WITH_ASR)\n  add_compile_options(-DWITH_ASR)\n  set(PPS_FLAGS_LIB \"fst/flags.h\")\nelse()\n  set(PPS_FLAGS_LIB \"gflags/gflags.h\")\nendif()\n\nif(ANDROID)\n  set(PPS_GLOG_LIB \"base/log_impl.h\")\nelse() #UNIX\n  if(WITH_ASR)\n    set(PPS_GLOG_LIB \"fst/log.h\")\n  else()\n    set(PPS_GLOG_LIB \"glog/logging.h\")\n  endif()\nendif()\n\nconfigure_file(\n    ${CMAKE_CURRENT_SOURCE_DIR}/flags.h.in\n    ${CMAKE_CURRENT_SOURCE_DIR}/flags.h @ONLY\n  )\nmessage(STATUS \"Generated ${CMAKE_CURRENT_SOURCE_DIR}/flags.h\")\n\nconfigure_file(\n    ${CMAKE_CURRENT_SOURCE_DIR}/log.h.in\n    ${CMAKE_CURRENT_SOURCE_DIR}/log.h @ONLY\n  )\nmessage(STATUS \"Generated ${CMAKE_CURRENT_SOURCE_DIR}/log.h\")\n\n\nif(ANDROID)\n  set(csrc\n    log_impl.cc\n    glog_utils.cc\n  )\n  add_library(base ${csrc})\n  target_link_libraries(base gflags)\nelse() # UNIX\n  set(csrc)\n  add_library(base INTERFACE)\nendif()"
  },
  {
    "path": "runtime/engine/common/base/basic_types.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <limits>\n\n#include \"kaldi/base/kaldi-types.h\"\n\ntypedef float BaseFloat;\ntypedef double double64;\n\ntypedef signed char int8;\ntypedef short int16;  // NOLINT\ntypedef int int32;    // NOLINT\n\n#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)\ntypedef long int64;  // NOLINT\n#else\ntypedef long long int64;            // NOLINT\n#endif\n\ntypedef unsigned char uint8;    // NOLINT\ntypedef unsigned short uint16;  // NOLINT\ntypedef unsigned int uint32;    // NOLINT\n\n#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)\ntypedef unsigned long uint64;  // NOLINT\n#else\ntypedef unsigned long long uint64;  // NOLINT\n#endif\n\ntypedef signed int char32;\n\nconst uint8 kuint8max = static_cast<uint8>(0xFF);\nconst uint16 kuint16max = static_cast<uint16>(0xFFFF);\nconst uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);\nconst uint64 kuint64max = static_cast<uint64>(0xFFFFFFFFFFFFFFFFLL);\nconst int8 kint8min = static_cast<int8>(0x80);\nconst int8 kint8max = static_cast<int8>(0x7F);\nconst int16 kint16min = static_cast<int16>(0x8000);\nconst int16 kint16max = static_cast<int16>(0x7FFF);\nconst int32 kint32min = static_cast<int32>(0x80000000);\nconst int32 kint32max = static_cast<int32>(0x7FFFFFFF);\nconst int64 kint64min = static_cast<int64>(0x8000000000000000LL);\nconst int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);\n\nconst BaseFloat kBaseFloatMax = std::numeric_limits<BaseFloat>::max();\nconst BaseFloat kBaseFloatMin = std::numeric_limits<BaseFloat>::min();\n"
  },
  {
    "path": "runtime/engine/common/base/common.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <algorithm>\n#include <cassert>\n#include <cmath>\n#include <condition_variable>\n#include <cstring>\n#include <deque>\n#include <fstream>\n#include <functional>\n#include <future>\n#include <iomanip>\n#include <iostream>\n#include <istream>\n#include <map>\n#include <memory>\n#include <mutex>\n#include <numeric>\n#include <ostream>\n#include <queue>\n#include <set>\n#include <sstream>\n#include <stack>\n#include <stdexcept>\n#include <string>\n#include <thread>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"base/basic_types.h\"\n#include \"base/flags.h\"\n#include \"base/log.h\"\n#include \"base/macros.h\"\n#include \"utils/file_utils.h\"\n#include \"utils/math.h\"\n#include \"utils/timer.h\""
  },
  {
    "path": "runtime/engine/common/base/config.h",
    "content": "// Copyright (c) code is from\n// https://blog.csdn.net/huixingshao/article/details/45969887.\n\n#include <fstream>\n#include <iostream>\n#include <map>\n#include <sstream>\n#include <string>\nusing namespace std;\n\n#pragma once\n\n#ifdef _MSC_VER\n#pragma region ParseIniFile\n#endif\n\n/*\n * \\brief Generic configuration Class\n *\n */\nclass Config {\n    // Data\n  protected:\n    std::string m_Delimiter;  //!< separator between key and value\n    std::string m_Comment;    //!< separator between value and comments\n    std::map<std::string, std::string>\n        m_Contents;  //!< extracted keys and values\n\n    typedef std::map<std::string, std::string>::iterator mapi;\n    typedef std::map<std::string, std::string>::const_iterator mapci;\n    // Methods\n  public:\n    Config(std::string filename,\n           std::string delimiter = \"=\",\n           std::string comment = \"#\");\n    Config();\n    template <class T>\n    T Read(const std::string& in_key) const;  //!< Search for key and read value\n    //! or optional default value, call\n    //! as read<T>\n    template <class T>\n    T Read(const std::string& in_key, const T& in_value) const;\n    template <class T>\n    bool ReadInto(T* out_var, const std::string& in_key) const;\n    template <class T>\n    bool ReadInto(T* out_var,\n                  const std::string& in_key,\n                  const T& in_value) const;\n    bool FileExist(std::string filename);\n    void ReadFile(std::string filename,\n                  std::string delimiter = \"=\",\n                  std::string comment = \"#\");\n\n    // Check whether key exists in configuration\n    bool KeyExists(const std::string& in_key) const;\n\n    // Modify keys and values\n    template <class T>\n    void Add(const std::string& in_key, const T& in_value);\n    void Remove(const std::string& in_key);\n\n    // Check or change configuration syntax\n    std::string GetDelimiter() const { return m_Delimiter; }\n    std::string GetComment() const { return m_Comment; }\n    std::string SetDelimiter(const std::string& in_s) {\n        std::string old = m_Delimiter;\n        m_Delimiter = in_s;\n        return old;\n    }\n    std::string SetComment(const std::string& in_s) {\n        std::string old = m_Comment;\n        m_Comment = in_s;\n        return old;\n    }\n\n    // Write or read configuration\n    friend std::ostream& operator<<(std::ostream& os, const Config& cf);\n    friend std::istream& operator>>(std::istream& is, Config& cf);\n\n  protected:\n    template <class T>\n    static std::string T_as_string(const T& t);\n    template <class T>\n    static T string_as_T(const std::string& s);\n    static void Trim(std::string* inout_s);\n\n\n    // Exception types\n  public:\n    struct File_not_found {\n        std::string filename;\n        explicit File_not_found(const std::string& filename_ = std::string())\n            : filename(filename_) {}\n    };\n    struct Key_not_found {  // thrown only by T read(key) variant of read()\n        std::string key;\n        explicit Key_not_found(const std::string& key_ = std::string())\n            : key(key_) {}\n    };\n};\n\n/* static */\ntemplate <class T>\nstd::string Config::T_as_string(const T& t) {\n    // Convert from a T to a string\n    // Type T must support << operator\n    std::ostringstream ost;\n    ost << t;\n    return ost.str();\n}\n\n\n/* static */\ntemplate <class T>\nT Config::string_as_T(const std::string& s) {\n    // Convert from a string to a T\n    // Type T must support >> operator\n    T t;\n    std::istringstream ist(s);\n    ist >> t;\n    return t;\n}\n\n\n/* static */\ntemplate <>\ninline std::string Config::string_as_T<std::string>(const std::string& s) {\n    // Convert from a string to a string\n    // In other words, do nothing\n    return s;\n}\n\n\n/* static */\ntemplate <>\ninline bool Config::string_as_T<bool>(const std::string& s) {\n    // Convert from a string to a bool\n    // Interpret \"false\", \"F\", \"no\", \"n\", \"0\" as false\n    // Interpret \"true\", \"T\", \"yes\", \"y\", \"1\", \"-1\", or anything else as true\n    bool b = true;\n    std::string sup = s;\n    for (std::string::iterator p = sup.begin(); p != sup.end(); ++p)\n        *p = toupper(*p);  // make string all caps\n    if (sup == std::string(\"FALSE\") || sup == std::string(\"F\") ||\n        sup == std::string(\"NO\") || sup == std::string(\"N\") ||\n        sup == std::string(\"0\") || sup == std::string(\"NONE\"))\n        b = false;\n    return b;\n}\n\n\ntemplate <class T>\nT Config::Read(const std::string& key) const {\n    // Read the value corresponding to key\n    mapci p = m_Contents.find(key);\n    if (p == m_Contents.end()) throw Key_not_found(key);\n    return string_as_T<T>(p->second);\n}\n\n\ntemplate <class T>\nT Config::Read(const std::string& key, const T& value) const {\n    // Return the value corresponding to key or given default value\n    // if key is not found\n    mapci p = m_Contents.find(key);\n    if (p == m_Contents.end()) {\n        printf(\"%s = %s(default)\\n\", key.c_str(), T_as_string(value).c_str());\n        return value;\n    } else {\n        printf(\"%s = %s\\n\", key.c_str(), T_as_string(p->second).c_str());\n        return string_as_T<T>(p->second);\n    }\n}\n\n\ntemplate <class T>\nbool Config::ReadInto(T* var, const std::string& key) const {\n    // Get the value corresponding to key and store in var\n    // Return true if key is found\n    // Otherwise leave var untouched\n    mapci p = m_Contents.find(key);\n    bool found = (p != m_Contents.end());\n    if (found) *var = string_as_T<T>(p->second);\n    return found;\n}\n\n\ntemplate <class T>\nbool Config::ReadInto(T* var, const std::string& key, const T& value) const {\n    // Get the value corresponding to key and store in var\n    // Return true if key is found\n    // Otherwise set var to given default\n    mapci p = m_Contents.find(key);\n    bool found = (p != m_Contents.end());\n    if (found)\n        *var = string_as_T<T>(p->second);\n    else\n        var = value;\n    return found;\n}\n\n\ntemplate <class T>\nvoid Config::Add(const std::string& in_key, const T& value) {\n    // Add a key with given value\n    std::string v = T_as_string(value);\n    std::string key = in_key;\n    Trim(&key);\n    Trim(&v);\n    m_Contents[key] = v;\n    return;\n}\n\nConfig::Config(string filename, string delimiter, string comment)\n    : m_Delimiter(delimiter), m_Comment(comment) {\n    // Construct a Config, getting keys and values from given file\n\n    std::ifstream in(filename.c_str());\n\n    if (!in) throw File_not_found(filename);\n\n    in >> (*this);\n}\n\n\nConfig::Config() : m_Delimiter(string(1, '=')), m_Comment(string(1, '#')) {\n    // Construct a Config without a file; empty\n}\n\n\nbool Config::KeyExists(const string& key) const {\n    // Indicate whether key is found\n    mapci p = m_Contents.find(key);\n    return (p != m_Contents.end());\n}\n\n\n/* static */\nvoid Config::Trim(string* inout_s) {\n    // Remove leading and trailing whitespace\n    static const char whitespace[] = \" \\n\\t\\v\\r\\f\";\n    inout_s->erase(0, inout_s->find_first_not_of(whitespace));\n    inout_s->erase(inout_s->find_last_not_of(whitespace) + 1U);\n}\n\n\nstd::ostream& operator<<(std::ostream& os, const Config& cf) {\n    // Save a Config to os\n    for (Config::mapci p = cf.m_Contents.begin(); p != cf.m_Contents.end();\n         ++p) {\n        os << p->first << \" \" << cf.m_Delimiter << \" \";\n        os << p->second << std::endl;\n    }\n    return os;\n}\n\nvoid Config::Remove(const string& key) {\n    // Remove key and its value\n    m_Contents.erase(m_Contents.find(key));\n    return;\n}\n\nstd::istream& operator>>(std::istream& is, Config& cf) {\n    // Load a Config from is\n    // Read in keys and values, keeping internal whitespace\n    typedef string::size_type pos;\n    const string& delim = cf.m_Delimiter;  // separator\n    const string& comm = cf.m_Comment;     // comment\n    const pos skip = delim.length();       // length of separator\n\n    string nextline = \"\";  // might need to read ahead to see where value ends\n\n    while (is || nextline.length() > 0) {\n        // Read an entire line at a time\n        string line;\n        if (nextline.length() > 0) {\n            line = nextline;  // we read ahead; use it now\n            nextline = \"\";\n        } else {\n            std::getline(is, line);\n        }\n\n        // Ignore comments\n        line = line.substr(0, line.find(comm));\n\n        // Parse the line if it contains a delimiter\n        pos delimPos = line.find(delim);\n        if (delimPos < string::npos) {\n            // Extract the key\n            string key = line.substr(0, delimPos);\n            line.replace(0, delimPos + skip, \"\");\n\n            // See if value continues on the next line\n            // Stop at blank line, next line with a key, end of stream,\n            // or end of file sentry\n            bool terminate = false;\n            while (!terminate && is) {\n                std::getline(is, nextline);\n                terminate = true;\n\n                string nlcopy = nextline;\n                Config::Trim(&nlcopy);\n                if (nlcopy == \"\") continue;\n\n                nextline = nextline.substr(0, nextline.find(comm));\n                if (nextline.find(delim) != string::npos) continue;\n\n                nlcopy = nextline;\n                Config::Trim(&nlcopy);\n                if (nlcopy != \"\") line += \"\\n\";\n                line += nextline;\n                terminate = false;\n            }\n\n            // Store key and value\n            Config::Trim(&key);\n            Config::Trim(&line);\n            cf.m_Contents[key] = line;  // overwrites if key is repeated\n        }\n    }\n\n    return is;\n}\nbool Config::FileExist(std::string filename) {\n    bool exist = false;\n    std::ifstream in(filename.c_str());\n    if (in) exist = true;\n    return exist;\n}\n\nvoid Config::ReadFile(string filename, string delimiter, string comment) {\n    m_Delimiter = delimiter;\n    m_Comment = comment;\n    std::ifstream in(filename.c_str());\n\n    if (!in) throw File_not_found(filename);\n\n    in >> (*this);\n}\n\n#ifdef _MSC_VER\n#pragma endregion ParseIniFIle\n#endif\n"
  },
  {
    "path": "runtime/engine/common/base/flags.h.in",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"@PPS_FLAGS_LIB@\"\n"
  },
  {
    "path": "runtime/engine/common/base/glog_utils.cc",
    "content": "\n#include \"base/glog_utils.h\"\n\nnamespace google {\nvoid InitGoogleLogging(const char* name) {\n    LOG(INFO) << \"dummpy InitGoogleLogging.\";\n}\n\nvoid InstallFailureSignalHandler() {\n    LOG(INFO) << \"dummpy InstallFailureSignalHandler.\";\n}\n}  // namespace google\n"
  },
  {
    "path": "runtime/engine/common/base/glog_utils.h",
    "content": "#pragma once\n\n#include \"base/common.h\"\n\nnamespace google {\nvoid InitGoogleLogging(const char* name);\n\nvoid InstallFailureSignalHandler();\n}  // namespace google"
  },
  {
    "path": "runtime/engine/common/base/log.h.in",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"@PPS_GLOG_LIB@\"\n"
  },
  {
    "path": "runtime/engine/common/base/log_impl.cc",
    "content": "#include \"base/log.h\"\n\nDEFINE_int32(logtostderr, 0, \"logging to stderr\");\n\nnamespace ppspeech {\n\nstatic char __progname[] = \"paddlespeech\";\n\nnamespace log {\n\nstd::mutex LogMessage::lock_;\nstd::string LogMessage::s_debug_logfile_(\"\");\nstd::string LogMessage::s_info_logfile_(\"\");\nstd::string LogMessage::s_warning_logfile_(\"\");\nstd::string LogMessage::s_error_logfile_(\"\");\nstd::string LogMessage::s_fatal_logfile_(\"\");\n\nvoid LogMessage::get_curr_proc_info(std::string* pid, std::string* proc_name) {\n    std::stringstream ss;\n    ss << getpid();\n    ss >> *pid;\n    *proc_name = ::ppspeech::__progname;\n}\n\nLogMessage::LogMessage(const char* file,\n                       int line,\n                       Severity level,\n                       bool verbose,\n                       bool out_to_file /* = false */)\n    : level_(level), verbose_(verbose), out_to_file_(out_to_file) {\n    if (FLAGS_logtostderr == 0) {\n        stream_ = static_cast<std::ostream*>(&std::cout);\n    } else if (FLAGS_logtostderr == 1) {\n        stream_ = static_cast<std::ostream*>(&std::cerr);\n    } else if (out_to_file_) {\n        // logfile\n        lock_.lock();\n        init(file, line);\n    }\n}\n\nLogMessage::~LogMessage() {\n    stream() << std::endl;\n\n    if (out_to_file_) {\n        lock_.unlock();\n    }\n\n    if (verbose_ && level_ == FATAL) {\n        std::abort();\n    }\n}\n\nstd::ostream* LogMessage::nullstream() {\n    thread_local static std::ofstream os;\n    thread_local static bool flag_set = false;\n    if (!flag_set) {\n        os.setstate(std::ios_base::badbit);\n        flag_set = true;\n    }\n    return &os;\n}\n\nvoid LogMessage::init(const char* file, int line) {\n    time_t t = time(0);\n    char tmp[100];\n    strftime(tmp, sizeof(tmp), \"%Y%m%d-%H%M%S\", localtime(&t));\n\n    if (s_info_logfile_.empty()) {\n        std::string pid;\n        std::string proc_name;\n        get_curr_proc_info(&pid, &proc_name);\n\n        s_debug_logfile_ =\n            std::string(\"log.\" + proc_name + \".log.DEBUG.\" + tmp + \".\" + pid);\n        s_info_logfile_ =\n            std::string(\"log.\" + proc_name + \".log.INFO.\" + tmp + \".\" + pid);\n        s_warning_logfile_ =\n            std::string(\"log.\" + proc_name + \".log.WARNING.\" + tmp + \".\" + pid);\n        s_error_logfile_ =\n            std::string(\"log.\" + proc_name + \".log.ERROR.\" + tmp + \".\" + pid);\n        s_fatal_logfile_ =\n            std::string(\"log.\" + proc_name + \".log.FATAL.\" + tmp + \".\" + pid);\n    }\n\n    thread_local static std::ofstream ofs;\n    if (level_ == DEBUG) {\n        ofs.open(s_debug_logfile_.c_str(), std::ios::out | std::ios::app);\n    } else if (level_ == INFO) {\n        ofs.open(s_info_logfile_.c_str(), std::ios::out | std::ios::app);\n    } else if (level_ == WARNING) {\n        ofs.open(s_warning_logfile_.c_str(), std::ios::out | std::ios::app);\n    } else if (level_ == ERROR) {\n        ofs.open(s_error_logfile_.c_str(), std::ios::out | std::ios::app);\n    } else {\n        ofs.open(s_fatal_logfile_.c_str(), std::ios::out | std::ios::app);\n    }\n\n    stream_ = &ofs;\n\n    stream() << tmp << \" \" << file << \" line \" << line << \"; \";\n    stream() << std::flush;\n}\n}  // namespace log\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/base/log_impl.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// modified from https://github.com/Dounm/dlog\n// modified form\n// https://android.googlesource.com/platform/art/+/806defa/src/logging.h\n\n#pragma once\n\n#include <stdlib.h>\n#include <unistd.h>\n\n#include <fstream>\n#include <iostream>\n#include <mutex>\n#include <sstream>\n#include <string>\n#include <thread>\n\n#include \"base/common.h\"\n#include \"base/macros.h\"\n#ifndef WITH_GLOG\n#include \"base/glog_utils.h\"\n#endif\n\nDECLARE_int32(logtostderr);\n\nnamespace ppspeech {\n\nnamespace log {\n\nenum Severity {\n    DEBUG,\n    INFO,\n    WARNING,\n    ERROR,\n    FATAL,\n    NUM_SEVERITIES,\n};\n\nclass LogMessage {\n  public:\n    static void get_curr_proc_info(std::string* pid, std::string* proc_name);\n\n    LogMessage(const char* file,\n               int line,\n               Severity level,\n               bool verbose,\n               bool out_to_file = false);\n\n    ~LogMessage();\n\n    std::ostream& stream() { return verbose_ ? *stream_ : *nullstream(); }\n\n  private:\n    void init(const char* file, int line);\n    std::ostream* nullstream();\n\n  private:\n    std::ostream* stream_;\n    std::ostream* null_stream_;\n    Severity level_;\n    bool verbose_;\n    bool out_to_file_;\n\n    static std::mutex lock_;  // stream write lock\n    static std::string s_debug_logfile_;\n    static std::string s_info_logfile_;\n    static std::string s_warning_logfile_;\n    static std::string s_error_logfile_;\n    static std::string s_fatal_logfile_;\n\n    DISALLOW_COPY_AND_ASSIGN(LogMessage);\n};\n\n\n}  // namespace log\n\n}  // namespace ppspeech\n\n\n#ifndef PPS_DEBUG\n#define DLOG_INFO \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::INFO, false)\n#define DLOG_WARNING \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::WARNING, false)\n#define DLOG_ERROR \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::ERROR, false)\n#define DLOG_FATAL \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::FATAL, false)\n#else\n#define DLOG_INFO \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::INFO, true)\n#define DLOG_WARNING \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::WARNING, true)\n#define DLOG_ERROR \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::ERROR, true)\n#define DLOG_FATAL \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::FATAL, true)\n#endif\n\n\n#define LOG_INFO \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::INFO, true)\n#define LOG_WARNING \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::WARNING, true)\n#define LOG_ERROR \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::ERROR, true)\n#define LOG_FATAL \\\n    ppspeech::log::LogMessage(__FILE__, __LINE__, ppspeech::log::FATAL, true)\n\n\n#define LOG_0 LOG_DEBUG\n#define LOG_1 LOG_INFO\n#define LOG_2 LOG_WARNING\n#define LOG_3 LOG_ERROR\n#define LOG_4 LOG_FATAL\n\n#define LOG(level) LOG_##level.stream()\n\n#define DLOG(level) DLOG_##level.stream()\n\n#define VLOG(verboselevel) LOG(verboselevel)\n\n#define CHECK(exp)                                        \\\n    ppspeech::log::LogMessage(                            \\\n        __FILE__, __LINE__, ppspeech::log::FATAL, !(exp)) \\\n            .stream()                                     \\\n        << \"Check Failed: \" #exp\n\n#define CHECK_EQ(x, y) CHECK((x) == (y))\n#define CHECK_NE(x, y) CHECK((x) != (y))\n#define CHECK_LE(x, y) CHECK((x) <= (y))\n#define CHECK_LT(x, y) CHECK((x) < (y))\n#define CHECK_GE(x, y) CHECK((x) >= (y))\n#define CHECK_GT(x, y) CHECK((x) > (y))\n#ifdef PPS_DEBUG\n#define DCHECK(x) CHECK(x)\n#define DCHECK_EQ(x, y) CHECK_EQ(x, y)\n#define DCHECK_NE(x, y) CHECK_NE(x, y)\n#define DCHECK_LE(x, y) CHECK_LE(x, y)\n#define DCHECK_LT(x, y) CHECK_LT(x, y)\n#define DCHECK_GE(x, y) CHECK_GE(x, y)\n#define DCHECK_GT(x, y) CHECK_GT(x, y)\n#else\n#define DCHECK(condition) \\\n    while (false) CHECK(condition)\n#define DCHECK_EQ(val1, val2) \\\n    while (false) CHECK_EQ(val1, val2)\n#define DCHECK_NE(val1, val2) \\\n    while (false) CHECK_NE(val1, val2)\n#define DCHECK_LE(val1, val2) \\\n    while (false) CHECK_LE(val1, val2)\n#define DCHECK_LT(val1, val2) \\\n    while (false) CHECK_LT(val1, val2)\n#define DCHECK_GE(val1, val2) \\\n    while (false) CHECK_GE(val1, val2)\n#define DCHECK_GT(val1, val2) \\\n    while (false) CHECK_GT(val1, val2)\n#define DCHECK_STREQ(str1, str2) \\\n    while (false) CHECK_STREQ(str1, str2)\n#endif"
  },
  {
    "path": "runtime/engine/common/base/macros.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <limits>\n#include <string>\n\n#ifndef DISALLOW_COPY_AND_ASSIGN\n#define DISALLOW_COPY_AND_ASSIGN(TypeName) \\\n    TypeName(const TypeName&) = delete;    \\\n    void operator=(const TypeName&) = delete\n#endif\n\nnamespace ppspeech {\n\n// kSpaceSymbol in UTF-8 is: ▁\nconst char kSpaceSymbo[] = \"\\xe2\\x96\\x81\";\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/base/safe_queue.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/common.h\"\n\nnamespace ppspeech {\n\ntemplate <typename T>\nclass SafeQueue {\n  public:\n    explicit SafeQueue(size_t capacity = 0);\n    void push_back(const T& in);\n    bool pop(T* out);\n    bool empty() const { return buffer_.empty(); }\n    size_t size() const { return buffer_.size(); }\n    void clear();\n\n\n  private:\n    std::mutex mutex_;\n    std::condition_variable condition_;\n    std::deque<T> buffer_;\n    size_t capacity_;\n};\n\ntemplate <typename T>\nSafeQueue<T>::SafeQueue(size_t capacity) : capacity_(capacity) {}\n\ntemplate <typename T>\nvoid SafeQueue<T>::push_back(const T& in) {\n    std::unique_lock<std::mutex> lock(mutex_);\n    if (capacity_ > 0 && buffer_.size() == capacity_) {\n        condition_.wait(lock, [this] { return capacity_ >= buffer_.size(); });\n    }\n\n    buffer_.push_back(in);\n    condition_.notify_one();\n}\n\ntemplate <typename T>\nbool SafeQueue<T>::pop(T* out) {\n    if (buffer_.empty()) {\n        return false;\n    }\n\n    std::unique_lock<std::mutex> lock(mutex_);\n    condition_.wait(lock, [this] { return buffer_.size() > 0; });\n    *out = std::move(buffer_.front());\n    buffer_.pop_front();\n    condition_.notify_one();\n    return true;\n}\n\ntemplate <typename T>\nvoid SafeQueue<T>::clear() {\n    std::unique_lock<std::mutex> lock(mutex_);\n    buffer_.clear();\n    condition_.notify_one();\n}\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/base/safe_queue_inl.h",
    "content": ""
  },
  {
    "path": "runtime/engine/common/base/thread_pool.h",
    "content": "// Copyright (c) 2012 Jakob Progsch, Václav Zeman\n\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n\n//   1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n\n//   2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n\n//   3. This notice may not be removed or altered from any source\n//   distribution.\n// this code is from https://github.com/progschj/ThreadPool\n\n#ifndef BASE_THREAD_POOL_H\n#define BASE_THREAD_POOL_H\n\n#include <condition_variable>\n#include <functional>\n#include <future>\n#include <memory>\n#include <mutex>\n#include <queue>\n#include <stdexcept>\n#include <thread>\n#include <vector>\n\nclass ThreadPool {\n  public:\n    explicit ThreadPool(size_t);\n    template <class F, class... Args>\n    auto enqueue(F&& f, Args&&... args)\n        -> std::future<typename std::result_of<F(Args...)>::type>;\n    ~ThreadPool();\n\n  private:\n    // need to keep track of threads so we can join them\n    std::vector<std::thread> workers;\n    // the task queue\n    std::queue<std::function<void()>> tasks;\n\n    // synchronization\n    std::mutex queue_mutex;\n    std::condition_variable condition;\n    bool stop;\n};\n\n// the constructor just launches some amount of workers\ninline ThreadPool::ThreadPool(size_t threads) : stop(false) {\n    for (size_t i = 0; i < threads; ++i)\n        workers.emplace_back([this] {\n            for (;;) {\n                std::function<void()> task;\n\n                {\n                    std::unique_lock<std::mutex> lock(this->queue_mutex);\n                    this->condition.wait(lock, [this] {\n                        return this->stop || !this->tasks.empty();\n                    });\n                    if (this->stop && this->tasks.empty()) return;\n                    task = std::move(this->tasks.front());\n                    this->tasks.pop();\n                }\n\n                task();\n            }\n        });\n}\n\n// add new work item to the pool\ntemplate <class F, class... Args>\nauto ThreadPool::enqueue(F&& f, Args&&... args)\n    -> std::future<typename std::result_of<F(Args...)>::type> {\n    using return_type = typename std::result_of<F(Args...)>::type;\n\n    auto task = std::make_shared<std::packaged_task<return_type()>>(\n        std::bind(std::forward<F>(f), std::forward<Args>(args)...));\n\n    std::future<return_type> res = task->get_future();\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex);\n\n        // don't allow enqueueing after stopping the pool\n        if (stop) throw std::runtime_error(\"enqueue on stopped ThreadPool\");\n\n        tasks.emplace([task]() { (*task)(); });\n    }\n    condition.notify_one();\n    return res;\n}\n\n// the destructor joins all threads\ninline ThreadPool::~ThreadPool() {\n    {\n        std::unique_lock<std::mutex> lock(queue_mutex);\n        stop = true;\n    }\n    condition.notify_all();\n    for (std::thread& worker : workers) worker.join();\n}\n\n#endif\n"
  },
  {
    "path": "runtime/engine/common/frontend/CMakeLists.txt",
    "content": "add_library(kaldi-native-fbank-core \n  feature-fbank.cc\n  feature-functions.cc\n  feature-window.cc\n  fftsg.c\n  mel-computations.cc\n  rfft.cc\n)\ntarget_link_libraries(kaldi-native-fbank-core PUBLIC utils base)\ntarget_compile_options(kaldi-native-fbank-core PUBLIC \"-fPIC\")\n\nadd_library(frontend STATIC\n  cmvn.cc\n  audio_cache.cc\n  feature_cache.cc\n  feature_pipeline.cc\n  assembler.cc\n  wave-reader.cc\n)\ntarget_link_libraries(frontend PUBLIC kaldi-native-fbank-core utils base)\n\nset(BINS \n  compute_fbank_main\n)\n\nforeach(bin_name IN LISTS BINS)\n  add_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\n  target_include_directories(${bin_name} PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\n  # https://github.com/Kitware/CMake/blob/v3.1.0/Modules/FindThreads.cmake#L207\n  target_link_libraries(${bin_name} PUBLIC frontend base utils kaldi-util libgflags_nothreads.so Threads::Threads extern_glog)\nendforeach()\n"
  },
  {
    "path": "runtime/engine/common/frontend/assembler.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/assembler.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing std::unique_ptr;\nusing std::vector;\n\nAssembler::Assembler(AssemblerOptions opts,\n                     unique_ptr<FrontendInterface> base_extractor) {\n    fill_zero_ = opts.fill_zero;\n    frame_chunk_stride_ = opts.subsampling_rate * opts.nnet_decoder_chunk;\n    frame_chunk_size_ = (opts.nnet_decoder_chunk - 1) * opts.subsampling_rate +\n                        opts.receptive_filed_length;\n    cache_size_ = frame_chunk_size_ - frame_chunk_stride_;\n    receptive_filed_length_ = opts.receptive_filed_length;\n    base_extractor_ = std::move(base_extractor);\n    dim_ = base_extractor_->Dim();\n}\n\nvoid Assembler::Accept(const std::vector<BaseFloat>& inputs) {\n    // read inputs\n    base_extractor_->Accept(inputs);\n}\n\n// pop feature chunk\nbool Assembler::Read(std::vector<BaseFloat>* feats) {\n    kaldi::Timer timer;\n    bool result = Compute(feats);\n    VLOG(1) << \"Assembler::Read cost: \" << timer.Elapsed() << \" sec.\";\n    return result;\n}\n\n// read frame by frame from base_feature_extractor_ into cache_\nbool Assembler::Compute(vector<BaseFloat>* feats) {\n    // compute and feed frame by frame\n    while (feature_cache_.size() < frame_chunk_size_) {\n        vector<BaseFloat> feature;\n        bool result = base_extractor_->Read(&feature);\n        if (result == false || feature.size() == 0) {\n            VLOG(1) << \"result: \" << result\n                    << \" feature dim: \" << feature.size();\n            if (IsFinished() == false) {\n                VLOG(1) << \"finished reading feature. cache size: \"\n                        << feature_cache_.size();\n                return false;\n            } else {\n                VLOG(1) << \"break\";\n                break;\n            }\n        }\n        feature_cache_.push(feature);\n        nframes_ += 1;\n        VLOG(1) << \"nframes: \" << nframes_;\n    }\n\n    if (feature_cache_.size() < receptive_filed_length_) {\n        VLOG(3) << \"feature_cache less than receptive_filed_length. \"\n                << feature_cache_.size() << \": \" << receptive_filed_length_;\n        return false;\n    }\n\n    if (fill_zero_) {\n        while (feature_cache_.size() < frame_chunk_size_) {\n            vector<BaseFloat> feature(dim_, kaldi::kSetZero);\n            nframes_ += 1;\n            feature_cache_.push(feature);\n        }\n    }\n\n    int32 this_chunk_size =\n        std::min(static_cast<int32>(feature_cache_.size()), frame_chunk_size_);\n    feats->resize(dim_ * this_chunk_size);\n    VLOG(3) << \"read \" << this_chunk_size << \" feat.\";\n\n    int32 counter = 0;\n    while (counter < this_chunk_size) {\n        vector<BaseFloat>& val = feature_cache_.front();\n        CHECK(val.size() == dim_) << val.size();\n\n        int32 start = counter * dim_;\n        std::memcpy(\n            feats->data() + start, val.data(), val.size() * sizeof(BaseFloat));\n\n        if (this_chunk_size - counter <= cache_size_) {\n            feature_cache_.push(val);\n        }\n\n        // val is reference, so we should pop here\n        feature_cache_.pop();\n\n        counter++;\n    }\n    CHECK(feature_cache_.size() == cache_size_);\n\n    return true;\n}\n\n\nvoid Assembler::Reset() {\n    std::queue<std::vector<BaseFloat>> empty;\n    std::swap(feature_cache_, empty);\n    nframes_ = 0;\n    base_extractor_->Reset();\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/assembler.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/frontend_itf.h\"\n\nnamespace ppspeech {\n\nstruct AssemblerOptions {\n    // refer:https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/paddlespeech/s2t/exps/deepspeech2/model.py\n    // the nnet batch forward\n    int32 receptive_filed_length{1};\n    int32 subsampling_rate{1};\n    int32 nnet_decoder_chunk{1};\n    bool fill_zero{false};  // whether fill zero when last chunk is not equal to\n                            // frame_chunk_size_\n};\n\nclass Assembler : public FrontendInterface {\n  public:\n    explicit Assembler(\n        AssemblerOptions opts,\n        std::unique_ptr<FrontendInterface> base_extractor = NULL);\n\n    // Feed feats or waves\n    void Accept(const std::vector<kaldi::BaseFloat>& inputs) override;\n\n    // feats size = num_frames * feat_dim\n    bool Read(std::vector<kaldi::BaseFloat>* feats) override;\n\n    // feat dim\n    size_t Dim() const override { return dim_; }\n\n    void SetFinished() override { base_extractor_->SetFinished(); }\n\n    bool IsFinished() const override { return base_extractor_->IsFinished(); }\n\n    void Reset() override;\n\n  private:\n    bool Compute(std::vector<kaldi::BaseFloat>* feats);\n\n    bool fill_zero_{false};\n\n    int32 dim_;                 // feat dim\n    int32 frame_chunk_size_;    // window\n    int32 frame_chunk_stride_;  // stride\n    int32 cache_size_;          // window - stride\n    int32 receptive_filed_length_;\n    std::queue<std::vector<kaldi::BaseFloat>> feature_cache_;\n    std::unique_ptr<FrontendInterface> base_extractor_;\n\n    int32 nframes_;  // num frame computed\n    DISALLOW_COPY_AND_ASSIGN(Assembler);\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/audio_cache.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/audio_cache.h\"\n\n#include \"kaldi/base/timer.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing std::vector;\n\nAudioCache::AudioCache(int buffer_size, bool to_float32)\n    : finished_(false),\n      capacity_(buffer_size),  // unit: sample\n      size_(0),\n      offset_(0),\n      timeout_(1),  // ms\n      to_float32_(to_float32) {\n    ring_buffer_.resize(capacity_);\n}\n\nBaseFloat AudioCache::Convert2PCM32(BaseFloat val) {\n    // sample type int16, int16->float32\n    return val * (1. / std::pow(2.0, 15));\n}\n\nvoid AudioCache::Accept(const vector<BaseFloat>& waves) {\n    kaldi::Timer timer;\n    std::unique_lock<std::mutex> lock(mutex_);\n    while (size_ + waves.size() > ring_buffer_.size()) {\n        ready_feed_condition_.wait(lock);\n    }\n    for (size_t idx = 0; idx < waves.size(); ++idx) {\n        int32 buffer_idx = (idx + offset_ + size_) % ring_buffer_.size();\n        ring_buffer_[buffer_idx] = waves[idx];\n        if (to_float32_) ring_buffer_[buffer_idx] = Convert2PCM32(waves[idx]);\n    }\n    size_ += waves.size();\n    VLOG(1) << \"AudioCache::Accept cost: \" << timer.Elapsed() << \" sec. \"\n            << waves.size() << \" samples.\";\n}\n\nbool AudioCache::Read(vector<BaseFloat>* waves) {\n    kaldi::Timer timer;\n    size_t chunk_size = waves->size();\n    std::unique_lock<std::mutex> lock(mutex_);\n    if (chunk_size > size_) {\n        if (finished_ == false) {\n            return false;\n        } else {\n            // read last chunk data\n            chunk_size = size_;\n            waves->resize(chunk_size);\n        }\n    }\n\n    for (size_t idx = 0; idx < chunk_size; ++idx) {\n        int buff_idx = (offset_ + idx) % ring_buffer_.size();\n        waves->at(idx) = ring_buffer_[buff_idx];\n    }\n    size_ -= chunk_size;\n    offset_ = (offset_ + chunk_size) % ring_buffer_.size();\n\n    nsamples_ += chunk_size;\n    VLOG(3) << \"nsamples readed: \" << nsamples_;\n\n    ready_feed_condition_.notify_one();\n    VLOG(1) << \"AudioCache::Read cost: \" << timer.Elapsed() << \" sec. \"\n            << chunk_size << \" samples.\";\n    return true;\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/audio_cache.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/frontend_itf.h\"\n\nnamespace ppspeech {\n\n// waves cache\nclass AudioCache : public FrontendInterface {\n  public:\n    explicit AudioCache(int buffer_size = 1000 * kint16max,\n                        bool to_float32 = false);\n\n    virtual void Accept(const std::vector<BaseFloat>& waves);\n\n    virtual bool Read(std::vector<kaldi::BaseFloat>* waves);\n\n    // the audio dim is 1, one sample, which is useless,\n    // so we return size_(cache samples) instead.\n    virtual size_t Dim() const { return size_; }\n\n    virtual void SetFinished() {\n        std::lock_guard<std::mutex> lock(mutex_);\n        finished_ = true;\n    }\n\n    virtual bool IsFinished() const { return finished_ && (size_ == 0); }\n\n    void Reset() override {\n        offset_ = 0;\n        size_ = 0;\n        finished_ = false;\n        nsamples_ = 0;\n    }\n\n  private:\n    kaldi::BaseFloat Convert2PCM32(kaldi::BaseFloat val);\n\n    std::vector<kaldi::BaseFloat> ring_buffer_;\n    size_t offset_;    // offset in ring_buffer_, begin of data\n    size_t size_;      // samples in ring_buffer_, size of valid data\n    size_t capacity_;  // capacity of ring_buffer_, full size of data buffer,\n                       // unit: sample\n    bool finished_;    // reach audio end\n    std::mutex mutex_;\n    std::condition_variable ready_feed_condition_;\n    kaldi::int32 timeout_;  // millisecond\n    bool to_float32_;       // int16 -> float32. used in linear_spectrogram\n\n    int32 nsamples_;  // number samples readed.\n    DISALLOW_COPY_AND_ASSIGN(AudioCache);\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/cmvn.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"frontend/cmvn.h\"\n\n#include \"utils/file_utils.h\"\n#include \"utils/picojson.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing std::unique_ptr;\nusing std::vector;\n\n\nCMVN::CMVN(std::string cmvn_file, unique_ptr<FrontendInterface> base_extractor)\n    : var_norm_(true) {\n    CHECK_NE(cmvn_file, \"\");\n    base_extractor_ = std::move(base_extractor);\n    ReadCMVNFromJson(cmvn_file);\n    dim_ = mean_stats_.size() - 1;\n}\n\nvoid CMVN::ReadCMVNFromJson(std::string cmvn_file) {\n    std::string json_str = ppspeech::ReadFile2String(cmvn_file);\n    picojson::value value;\n    std::string err;\n    const char* json_end = picojson::parse(\n        value, json_str.c_str(), json_str.c_str() + json_str.size(), &err);\n    if (!value.is<picojson::object>()) {\n        LOG(ERROR) << \"Input json file format error.\";\n    }\n    const picojson::value::array& mean_stat =\n        value.get(\"mean_stat\").get<picojson::array>();\n    for (auto it = mean_stat.begin(); it != mean_stat.end(); it++) {\n        mean_stats_.push_back((*it).get<double>());\n    }\n\n    const picojson::value::array& var_stat =\n        value.get(\"var_stat\").get<picojson::array>();\n    for (auto it = var_stat.begin(); it != var_stat.end(); it++) {\n        var_stats_.push_back((*it).get<double>());\n    }\n\n    kaldi::int32 frame_num = value.get(\"frame_num\").get<int64_t>();\n    LOG(INFO) << \"nframe: \" << frame_num;\n    mean_stats_.push_back(frame_num);\n    var_stats_.push_back(0);\n}\n\nvoid CMVN::Accept(const std::vector<kaldi::BaseFloat>& inputs) {\n    // feed waves/feats to compute feature\n    base_extractor_->Accept(inputs);\n    return;\n}\n\nbool CMVN::Read(std::vector<BaseFloat>* feats) {\n    // compute feature\n    if (base_extractor_->Read(feats) == false || feats->size() == 0) {\n        return false;\n    }\n\n    // apply cmvn\n    kaldi::Timer timer;\n    Compute(feats);\n    VLOG(1) << \"CMVN::Read cost: \" << timer.Elapsed() << \" sec.\";\n    return true;\n}\n\n// feats contain num_frames feature.\nvoid CMVN::Compute(vector<BaseFloat>* feats) const {\n    KALDI_ASSERT(feats != NULL);\n\n    if (feats->size() % dim_ != 0) {\n        LOG(ERROR) << \"Dim mismatch: cmvn \" << mean_stats_.size() << ','\n                   << var_stats_.size() - 1 << \", feats \" << feats->size()\n                   << 'x';\n    }\n    if (var_stats_.size() == 0 && var_norm_) {\n        LOG(ERROR)\n            << \"You requested variance normalization but no variance stats_ \"\n            << \"are supplied.\";\n    }\n\n    double count = mean_stats_[dim_];\n    // Do not change the threshold of 1.0 here: in the balanced-cmvn code, when\n    // computing an offset and representing it as stats_, we use a count of one.\n    if (count < 1.0)\n        LOG(ERROR) << \"Insufficient stats_ for cepstral mean and variance \"\n                      \"normalization: \"\n                   << \"count = \" << count;\n\n    if (!var_norm_) {\n        vector<BaseFloat> offset(feats->size());\n        vector<double> mean_stats(mean_stats_);\n        for (size_t i = 0; i < mean_stats.size(); ++i) {\n            mean_stats[i] /= count;\n        }\n        vector<double> mean_stats_apply(feats->size());\n        // fill the datat of mean_stats in mean_stats_appy whose dim_ is equal\n        // with the dim_ of feature.\n        // the dim_ of feats = dim_ * num_frames;\n        for (int32 idx = 0; idx < feats->size() / dim_; ++idx) {\n            std::memcpy(mean_stats_apply.data() + dim_ * idx,\n                        mean_stats.data(),\n                        dim_ * sizeof(double));\n        }\n        for (size_t idx = 0; idx < feats->size(); ++idx) {\n            feats->at(idx) += offset[idx];\n        }\n        return;\n    }\n    // norm(0, d) = mean offset;\n    // norm(1, d) = scale, e.g. x(d) <-- x(d)*norm(1, d) + norm(0, d).\n    vector<BaseFloat> norm0(feats->size());\n    vector<BaseFloat> norm1(feats->size());\n    for (int32 d = 0; d < dim_; d++) {\n        double mean, offset, scale;\n        mean = mean_stats_[d] / count;\n        double var = (var_stats_[d] / count) - mean * mean, floor = 1.0e-20;\n        if (var < floor) {\n            LOG(WARNING) << \"Flooring cepstral variance from \" << var << \" to \"\n                         << floor;\n            var = floor;\n        }\n        scale = 1.0 / sqrt(var);\n        if (scale != scale || 1 / scale == 0.0)\n            LOG(ERROR)\n                << \"NaN or infinity in cepstral mean/variance computation\";\n        offset = -(mean * scale);\n        for (int32 d_skip = d; d_skip < feats->size();) {\n            norm0[d_skip] = offset;\n            norm1[d_skip] = scale;\n            d_skip = d_skip + dim_;\n        }\n    }\n    // Apply the normalization.\n    for (size_t idx = 0; idx < feats->size(); ++idx) {\n        feats->at(idx) *= norm1[idx];\n    }\n\n    for (size_t idx = 0; idx < feats->size(); ++idx) {\n        feats->at(idx) += norm0[idx];\n    }\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/cmvn.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/frontend_itf.h\"\n#include \"kaldi/util/options-itf.h\"\n\nnamespace ppspeech {\n\nclass CMVN : public FrontendInterface {\n  public:\n    explicit CMVN(std::string cmvn_file,\n                  std::unique_ptr<FrontendInterface> base_extractor);\n    virtual void Accept(const std::vector<kaldi::BaseFloat>& inputs);\n\n    // the length of feats = feature_row * feature_dim,\n    // the Matrix is squashed into Vector\n    virtual bool Read(std::vector<kaldi::BaseFloat>* feats);\n    // the dim_ is the feature dim.\n    virtual size_t Dim() const { return dim_; }\n    virtual void SetFinished() { base_extractor_->SetFinished(); }\n    virtual bool IsFinished() const { return base_extractor_->IsFinished(); }\n    virtual void Reset() { base_extractor_->Reset(); }\n\n  private:\n    void ReadCMVNFromJson(std::string cmvn_file);\n    void Compute(std::vector<kaldi::BaseFloat>* feats) const;\n    std::vector<double> mean_stats_;\n    std::vector<double> var_stats_;\n    std::unique_ptr<FrontendInterface> base_extractor_;\n    size_t dim_;\n    bool var_norm_;\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/frontend/compute_fbank_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// todo refactor, repalce with gtest\n\n#include \"base/flags.h\"\n#include \"base/log.h\"\n#include \"frontend/audio_cache.h\"\n#include \"frontend/data_cache.h\"\n#include \"frontend/fbank.h\"\n#include \"frontend/feature_cache.h\"\n#include \"frontend/frontend_itf.h\"\n#include \"frontend/normalizer.h\"\n#include \"frontend/wave-reader.h\"\n#include \"kaldi/util/kaldi-io.h\"\n#include \"kaldi/util/table-types.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test wav scp path\");\nDEFINE_string(feature_wspecifier, \"\", \"output feats wspecifier\");\nDEFINE_string(cmvn_file, \"\", \"read cmvn\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\nDEFINE_int32(num_bins, 161, \"fbank num bins\");\nDEFINE_int32(sample_rate, 16000, \"sampe rate: 16k, 8k.\");\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    CHECK_GT(FLAGS_wav_rspecifier.size(), 0);\n    CHECK_GT(FLAGS_feature_wspecifier.size(), 0);\n    kaldi::SequentialTableReader<kaldi::WaveHolder> wav_reader(\n        FLAGS_wav_rspecifier);\n    kaldi::SequentialTableReader<kaldi::WaveInfoHolder> wav_info_reader(\n        FLAGS_wav_rspecifier);\n    kaldi::BaseFloatMatrixWriter feat_writer(FLAGS_feature_wspecifier);\n\n    int32 num_done = 0, num_err = 0;\n\n    // feature pipeline: wave cache --> povey window\n    // -->fbank --> global cmvn -> feat cache\n\n    std::unique_ptr<ppspeech::FrontendInterface> data_source(\n        new ppspeech::AudioCache(3600 * 1600, false));\n\n    knf::FbankOptions opt;\n    opt.frame_opts.frame_length_ms = 25;\n    opt.frame_opts.frame_shift_ms = 10;\n    opt.mel_opts.num_bins = FLAGS_num_bins;\n    opt.frame_opts.dither = 0.0;\n    LOG(INFO) << \"frame_length_ms: \" << opt.frame_opts.frame_length_ms;\n    LOG(INFO) << \"frame_shift_ms: \" << opt.frame_opts.frame_shift_ms;\n    LOG(INFO) << \"num_bins: \" << opt.mel_opts.num_bins;\n    LOG(INFO) << \"dither: \" << opt.frame_opts.dither;\n\n    std::unique_ptr<ppspeech::FrontendInterface> fbank(\n        new ppspeech::Fbank(opt, std::move(data_source)));\n\n    std::unique_ptr<ppspeech::FrontendInterface> cmvn(\n        new ppspeech::CMVN(FLAGS_cmvn_file, std::move(fbank)));\n\n    // the feature cache output feature chunk by chunk.\n    ppspeech::FeatureCache feature_cache(kint16max, std::move(cmvn));\n    LOG(INFO) << \"fbank: \" << true;\n    LOG(INFO) << \"feat dim: \" << feature_cache.Dim();\n\n\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * FLAGS_sample_rate;\n    LOG(INFO) << \"sr: \" << FLAGS_sample_rate;\n    LOG(INFO) << \"chunk size (sec): \" << streaming_chunk;\n    LOG(INFO) << \"chunk size (sample): \" << chunk_sample_size;\n\n    for (; !wav_reader.Done() && !wav_info_reader.Done();\n         wav_reader.Next(), wav_info_reader.Next()) {\n        const std::string& utt = wav_reader.Key();\n        const kaldi::WaveData& wave_data = wav_reader.Value();\n\n        const std::string& utt2 = wav_info_reader.Key();\n        const kaldi::WaveInfo& wave_info = wav_info_reader.Value();\n\n        CHECK(utt == utt2)\n            << \"wav reader and wav info reader using diff rspecifier!!!\";\n        LOG(INFO) << \"utt: \" << utt;\n        LOG(INFO) << \"samples: \" << wave_info.SampleCount();\n        LOG(INFO) << \"dur: \" << wave_info.Duration() << \" sec\";\n        CHECK(wave_info.SampFreq() == FLAGS_sample_rate)\n            << \"need \" << FLAGS_sample_rate << \" get \" << wave_info.SampFreq();\n\n        // load first channel wav\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n\n        // compute feat chunk by chunk\n        int tot_samples = waveform.Dim();\n        int sample_offset = 0;\n        std::vector<kaldi::Vector<BaseFloat>> feats;\n        int feature_rows = 0;\n        while (sample_offset < tot_samples) {\n            // cur chunk size\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            // get chunk wav\n            std::vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk[i] = waveform(sample_offset + i);\n            }\n\n            // compute feat\n            feature_cache.Accept(wav_chunk);\n\n            // send finish signal\n            if (cur_chunk_size < chunk_sample_size) {\n                feature_cache.SetFinished();\n            }\n\n            // read feat\n            kaldi::Vector<BaseFloat> features(feature_cache.Dim());\n            bool flag = true;\n            do {\n                std::vector<BaseFloat> tmp;\n                flag = feature_cache.Read(&tmp);\n                std::memcpy(features.Data(),\n                            tmp.data(),\n                            tmp.size() * sizeof(BaseFloat));\n                if (flag && features.Dim() != 0) {\n                    feats.push_back(features);\n                    feature_rows += features.Dim() / feature_cache.Dim();\n                }\n            } while (flag == true && features.Dim() != 0);\n\n            // forward offset\n            sample_offset += cur_chunk_size;\n        }\n\n        int cur_idx = 0;\n        kaldi::Matrix<kaldi::BaseFloat> features(feature_rows,\n                                                 feature_cache.Dim());\n        for (auto feat : feats) {\n            int num_rows = feat.Dim() / feature_cache.Dim();\n            for (int row_idx = 0; row_idx < num_rows; ++row_idx) {\n                for (size_t col_idx = 0; col_idx < feature_cache.Dim();\n                     ++col_idx) {\n                    features(cur_idx, col_idx) =\n                        feat(row_idx * feature_cache.Dim() + col_idx);\n                }\n                ++cur_idx;\n            }\n        }\n        LOG(INFO) << \"feat shape: \" << features.NumRows() << \" , \"\n                  << features.NumCols();\n        feat_writer.Write(utt, features);\n\n        // reset frontend pipeline state\n        feature_cache.Reset();\n\n        if (num_done % 50 == 0 && num_done != 0)\n            VLOG(2) << \"Processed \" << num_done << \" utterances\";\n\n        num_done++;\n    }\n\n    LOG(INFO) << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/common/frontend/compute_linear_spectrogram_main.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/flags.h\"\n#include \"base/log.h\"\n#include \"frontend/audio/audio_cache.h\"\n#include \"frontend/audio/data_cache.h\"\n#include \"frontend/audio/feature_cache.h\"\n#include \"frontend/audio/frontend_itf.h\"\n#include \"frontend/audio/linear_spectrogram.h\"\n#include \"frontend/audio/normalizer.h\"\n#include \"kaldi/feat/wave-reader.h\"\n#include \"kaldi/util/kaldi-io.h\"\n#include \"kaldi/util/table-types.h\"\n\nDEFINE_string(wav_rspecifier, \"\", \"test wav scp path\");\nDEFINE_string(feature_wspecifier, \"\", \"output feats wspecifier\");\nDEFINE_string(cmvn_file, \"./cmvn.ark\", \"read cmvn\");\nDEFINE_double(streaming_chunk, 0.36, \"streaming feature chunk size\");\n\nint main(int argc, char* argv[]) {\n    gflags::SetUsageMessage(\"Usage:\");\n    gflags::ParseCommandLineFlags(&argc, &argv, false);\n    google::InitGoogleLogging(argv[0]);\n    google::InstallFailureSignalHandler();\n    FLAGS_logtostderr = 1;\n\n    kaldi::SequentialTableReader<kaldi::WaveHolder> wav_reader(\n        FLAGS_wav_rspecifier);\n    kaldi::BaseFloatMatrixWriter feat_writer(FLAGS_feature_wspecifier);\n\n    int32 num_done = 0, num_err = 0;\n\n    // feature pipeline: wave cache --> hanning window\n    // -->linear_spectrogram --> global cmvn -> feat cache\n\n    std::unique_ptr<ppspeech::FrontendInterface> data_source(\n        new ppspeech::AudioCache(3600 * 1600, true));\n\n    ppspeech::LinearSpectrogramOptions opt;\n    opt.frame_opts.frame_length_ms = 20;\n    opt.frame_opts.frame_shift_ms = 10;\n    opt.frame_opts.dither = 0.0;\n    opt.frame_opts.remove_dc_offset = false;\n    opt.frame_opts.window_type = \"hanning\";\n    opt.frame_opts.preemph_coeff = 0.0;\n    LOG(INFO) << \"linear feature: \" << true;\n    LOG(INFO) << \"frame length (ms): \" << opt.frame_opts.frame_length_ms;\n    LOG(INFO) << \"frame shift (ms): \" << opt.frame_opts.frame_shift_ms;\n\n    std::unique_ptr<ppspeech::FrontendInterface> linear_spectrogram(\n        new ppspeech::LinearSpectrogram(opt, std::move(data_source)));\n\n    std::unique_ptr<ppspeech::FrontendInterface> cmvn(\n        new ppspeech::CMVN(FLAGS_cmvn_file, std::move(linear_spectrogram)));\n\n    ppspeech::FeatureCacheOptions feat_cache_opts;\n    // the feature cache output feature chunk by chunk.\n    ppspeech::FeatureCache feature_cache(feat_cache_opts, std::move(cmvn));\n    LOG(INFO) << \"feat dim: \" << feature_cache.Dim();\n\n    int sample_rate = 16000;\n    float streaming_chunk = FLAGS_streaming_chunk;\n    int chunk_sample_size = streaming_chunk * sample_rate;\n    LOG(INFO) << \"sample rate: \" << sample_rate;\n    LOG(INFO) << \"chunk size (s): \" << streaming_chunk;\n    LOG(INFO) << \"chunk size (sample): \" << chunk_sample_size;\n\n\n    for (; !wav_reader.Done(); wav_reader.Next()) {\n        std::string utt = wav_reader.Key();\n        const kaldi::WaveData& wave_data = wav_reader.Value();\n        LOG(INFO) << \"process utt: \" << utt;\n\n        int32 this_channel = 0;\n        kaldi::SubVector<kaldi::BaseFloat> waveform(wave_data.Data(),\n                                                    this_channel);\n        int tot_samples = waveform.Dim();\n        LOG(INFO) << \"wav len (sample): \" << tot_samples;\n\n        int sample_offset = 0;\n        std::vector<kaldi::Vector<BaseFloat>> feats;\n        int feature_rows = 0;\n        while (sample_offset < tot_samples) {\n            int cur_chunk_size =\n                std::min(chunk_sample_size, tot_samples - sample_offset);\n\n            kaldi::Vector<kaldi::BaseFloat> wav_chunk(cur_chunk_size);\n            for (int i = 0; i < cur_chunk_size; ++i) {\n                wav_chunk(i) = waveform(sample_offset + i);\n            }\n\n            kaldi::Vector<BaseFloat> features;\n            feature_cache.Accept(wav_chunk);\n            if (cur_chunk_size < chunk_sample_size) {\n                feature_cache.SetFinished();\n            }\n            bool flag = true;\n            do {\n                flag = feature_cache.Read(&features);\n                feats.push_back(features);\n                feature_rows += features.Dim() / feature_cache.Dim();\n            } while (flag == true && features.Dim() != 0);\n            sample_offset += cur_chunk_size;\n        }\n\n        int cur_idx = 0;\n        kaldi::Matrix<kaldi::BaseFloat> features(feature_rows,\n                                                 feature_cache.Dim());\n        for (auto feat : feats) {\n            int num_rows = feat.Dim() / feature_cache.Dim();\n            for (int row_idx = 0; row_idx < num_rows; ++row_idx) {\n                for (size_t col_idx = 0; col_idx < feature_cache.Dim();\n                     ++col_idx) {\n                    features(cur_idx, col_idx) =\n                        feat(row_idx * feature_cache.Dim() + col_idx);\n                }\n                ++cur_idx;\n            }\n        }\n        feat_writer.Write(utt, features);\n        feature_cache.Reset();\n\n        if (num_done % 50 == 0 && num_done != 0)\n            KALDI_VLOG(2) << \"Processed \" << num_done << \" utterances\";\n        num_done++;\n    }\n    KALDI_LOG << \"Done \" << num_done << \" utterances, \" << num_err\n              << \" with errors.\";\n    return (num_done != 0 ? 0 : 1);\n}\n"
  },
  {
    "path": "runtime/engine/common/frontend/data_cache.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/frontend_itf.h\"\n\nusing std::vector;\n\nnamespace ppspeech {\n\n// Simulates audio/feature input, by returning data from a Vector.\n// This class is mostly meant to be used for online decoder testing using\n// pre-recorded audio/feature\nclass DataCache : public FrontendInterface {\n  public:\n    DataCache() : finished_{false}, dim_{0} {}\n\n    // accept waves/feats\n    void Accept(const std::vector<kaldi::BaseFloat>& inputs) override {\n        data_ = std::move(inputs);\n    }\n\n    bool Read(vector<kaldi::BaseFloat>* feats) override {\n        if (data_.size() == 0) {\n            return false;\n        }\n        (*feats) = std::move(data_);\n        data_.resize(0);\n        return true;\n    }\n\n    void SetFinished() override { finished_ = true; }\n    bool IsFinished() const override { return finished_; }\n    size_t Dim() const override { return dim_; }\n    void SetDim(int32 dim) { dim_ = dim; }\n    void Reset() override {\n        finished_ = true;\n        dim_ = 0;\n    }\n\n  private:\n    std::vector<kaldi::BaseFloat> data_;\n    bool finished_;\n    int32 dim_;\n\n    DISALLOW_COPY_AND_ASSIGN(DataCache);\n};\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/frontend/db_norm.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"frontend/audio/db_norm.h\"\n\n#include \"kaldi/feat/cmvn.h\"\n#include \"kaldi/util/kaldi-io.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing kaldi::SubVector;\nusing kaldi::Vector;\nusing kaldi::VectorBase;\nusing std::unique_ptr;\nusing std::vector;\n\nDecibelNormalizer::DecibelNormalizer(\n    const DecibelNormalizerOptions& opts,\n    std::unique_ptr<FrontendInterface> base_extractor) {\n    base_extractor_ = std::move(base_extractor);\n    opts_ = opts;\n    dim_ = 1;\n}\n\nvoid DecibelNormalizer::Accept(const kaldi::VectorBase<BaseFloat>& waves) {\n    base_extractor_->Accept(waves);\n}\n\nbool DecibelNormalizer::Read(kaldi::Vector<BaseFloat>* waves) {\n    if (base_extractor_->Read(waves) == false || waves->Dim() == 0) {\n        return false;\n    }\n    Compute(waves);\n    return true;\n}\n\nbool DecibelNormalizer::Compute(VectorBase<BaseFloat>* waves) const {\n    // calculate db rms\n    BaseFloat rms_db = 0.0;\n    BaseFloat mean_square = 0.0;\n    BaseFloat gain = 0.0;\n    BaseFloat wave_float_normlization = 1.0f / (std::pow(2, 16 - 1));\n\n    vector<BaseFloat> samples;\n    samples.resize(waves->Dim());\n    for (size_t i = 0; i < samples.size(); ++i) {\n        samples[i] = (*waves)(i);\n    }\n\n    // square\n    for (auto& d : samples) {\n        if (opts_.convert_int_float) {\n            d = d * wave_float_normlization;\n        }\n        mean_square += d * d;\n    }\n\n    // mean\n    mean_square /= samples.size();\n    rms_db = 10 * std::log10(mean_square);\n    gain = opts_.target_db - rms_db;\n\n    if (gain > opts_.max_gain_db) {\n        LOG(ERROR)\n            << \"Unable to normalize segment to \" << opts_.target_db << \"dB,\"\n            << \"because the probable gain has exceeded opts_.max_gain_db\"\n            << opts_.max_gain_db << \"dB.\";\n        return false;\n    }\n\n    // Note that this is an in-place transformation.\n    for (auto& item : samples) {\n        // python item *= 10.0 ** (gain / 20.0)\n        item *= std::pow(10.0, gain / 20.0);\n    }\n\n    std::memcpy(\n        waves->Data(), samples.data(), sizeof(BaseFloat) * samples.size());\n    return true;\n}\n\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/db_norm.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/audio/frontend_itf.h\"\n#include \"kaldi/matrix/kaldi-matrix.h\"\n#include \"kaldi/util/options-itf.h\"\n\nnamespace ppspeech {\n\nstruct DecibelNormalizerOptions {\n    float target_db;\n    float max_gain_db;\n    bool convert_int_float;\n    DecibelNormalizerOptions()\n        : target_db(-20), max_gain_db(300.0), convert_int_float(false) {}\n\n    void Register(kaldi::OptionsItf* opts) {\n        opts->Register(\n            \"target-db\", &target_db, \"target db for db normalization\");\n        opts->Register(\n            \"max-gain-db\", &max_gain_db, \"max gain db for db normalization\");\n        opts->Register(\"convert-int-float\",\n                       &convert_int_float,\n                       \"if convert int samples to float\");\n    }\n};\n\nclass DecibelNormalizer : public FrontendInterface {\n  public:\n    explicit DecibelNormalizer(\n        const DecibelNormalizerOptions& opts,\n        std::unique_ptr<FrontendInterface> base_extractor);\n    virtual void Accept(const kaldi::VectorBase<kaldi::BaseFloat>& waves);\n    virtual bool Read(kaldi::Vector<kaldi::BaseFloat>* waves);\n    // normalize audio, the dim is 1.\n    virtual size_t Dim() const { return dim_; }\n    virtual void SetFinished() { base_extractor_->SetFinished(); }\n    virtual bool IsFinished() const { return base_extractor_->IsFinished(); }\n    virtual void Reset() { base_extractor_->Reset(); }\n\n  private:\n    bool Compute(kaldi::VectorBase<kaldi::BaseFloat>* waves) const;\n    DecibelNormalizerOptions opts_;\n    size_t dim_;\n    std::unique_ptr<FrontendInterface> base_extractor_;\n    kaldi::Vector<kaldi::BaseFloat> waveform_;\n};\n\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/frontend/fbank.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/feature-fbank.h\"\n#include \"frontend/feature_common.h\"\n\nnamespace ppspeech {\n\ntypedef StreamingFeatureTpl<knf::FbankComputer> Fbank;\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-fbank.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-fbank.cc\n//\n#include \"frontend/feature-fbank.h\"\n\n#include <cmath>\n\n#include \"frontend/feature-functions.h\"\n\nnamespace knf {\n\nstatic void Sqrt(float *in_out, int32_t n) {\n    for (int32_t i = 0; i != n; ++i) {\n        in_out[i] = std::sqrt(in_out[i]);\n    }\n}\n\nstd::ostream &operator<<(std::ostream &os, const FbankOptions &opts) {\n    os << opts.ToString();\n    return os;\n}\n\nFbankComputer::FbankComputer(const FbankOptions &opts)\n    : opts_(opts), rfft_(opts.frame_opts.PaddedWindowSize()) {\n    if (opts.energy_floor > 0.0f) {\n        log_energy_floor_ = logf(opts.energy_floor);\n    }\n\n    // We'll definitely need the filterbanks info for VTLN warping factor 1.0.\n    // [note: this call caches it.]\n    GetMelBanks(1.0f);\n}\n\nFbankComputer::~FbankComputer() {\n    for (auto iter = mel_banks_.begin(); iter != mel_banks_.end(); ++iter)\n        delete iter->second;\n}\n\nconst MelBanks *FbankComputer::GetMelBanks(float vtln_warp) {\n    MelBanks *this_mel_banks = nullptr;\n\n    // std::map<float, MelBanks *>::iterator iter = mel_banks_.find(vtln_warp);\n    auto iter = mel_banks_.find(vtln_warp);\n    if (iter == mel_banks_.end()) {\n        this_mel_banks =\n            new MelBanks(opts_.mel_opts, opts_.frame_opts, vtln_warp);\n        mel_banks_[vtln_warp] = this_mel_banks;\n    } else {\n        this_mel_banks = iter->second;\n    }\n    return this_mel_banks;\n}\n\nvoid FbankComputer::Compute(float signal_raw_log_energy,\n                            float vtln_warp,\n                            std::vector<float> *signal_frame,\n                            float *feature) {\n    const MelBanks &mel_banks = *(GetMelBanks(vtln_warp));\n\n    CHECK_EQ(signal_frame->size(), opts_.frame_opts.PaddedWindowSize());\n\n    // Compute energy after window function (not the raw one).\n    if (opts_.use_energy && !opts_.raw_energy) {\n        signal_raw_log_energy =\n            std::log(std::max<float>(InnerProduct(signal_frame->data(),\n                                                  signal_frame->data(),\n                                                  signal_frame->size()),\n                                     std::numeric_limits<float>::epsilon()));\n    }\n    rfft_.Compute(signal_frame->data());  // signal_frame is modified in-place\n    ComputePowerSpectrum(signal_frame);\n\n    // Use magnitude instead of power if requested.\n    if (!opts_.use_power) {\n        Sqrt(signal_frame->data(), signal_frame->size() / 2 + 1);\n    }\n\n    int32_t mel_offset = ((opts_.use_energy && !opts_.htk_compat) ? 1 : 0);\n\n    // Its length is opts_.mel_opts.num_bins\n    float *mel_energies = feature + mel_offset;\n\n    // Sum with mel filter banks over the power spectrum\n    mel_banks.Compute(signal_frame->data(), mel_energies);\n\n    if (opts_.use_log_fbank) {\n        // Avoid log of zero (which should be prevented anyway by dithering).\n        for (int32_t i = 0; i != opts_.mel_opts.num_bins; ++i) {\n            auto t = std::max(mel_energies[i],\n                              std::numeric_limits<float>::epsilon());\n            mel_energies[i] = std::log(t);\n        }\n    }\n\n    // Copy energy as first value (or the last, if htk_compat == true).\n    if (opts_.use_energy) {\n        if (opts_.energy_floor > 0.0 &&\n            signal_raw_log_energy < log_energy_floor_) {\n            signal_raw_log_energy = log_energy_floor_;\n        }\n        int32_t energy_index = opts_.htk_compat ? opts_.mel_opts.num_bins : 0;\n        feature[energy_index] = signal_raw_log_energy;\n    }\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-fbank.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-fbank.h\n\n#ifndef KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n#define KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n\n#include <limits>\n#include <map>\n\n#include \"frontend/feature-window.h\"\n#include \"frontend/mel-computations.h\"\n#include \"frontend/rfft.h\"\n\nnamespace knf {\n\nstruct FbankOptions {\n    FrameExtractionOptions frame_opts;\n    MelBanksOptions mel_opts;\n    // append an extra dimension with energy to the filter banks\n    bool use_energy = false;\n    float energy_floor = 0.0f;  // active iff use_energy==true\n\n    // If true, compute log_energy before preemphasis and windowing\n    // If false, compute log_energy after preemphasis ans windowing\n    bool raw_energy = true;  // active iff use_energy==true\n\n    // If true, put energy last (if using energy)\n    // If false, put energy first\n    bool htk_compat = false;  // active iff use_energy==true\n\n    // if true (default), produce log-filterbank, else linear\n    bool use_log_fbank = true;\n\n    // if true (default), use power in filterbank\n    // analysis, else magnitude.\n    bool use_power = true;\n\n    FbankOptions() { mel_opts.num_bins = 23; }\n\n    std::string ToString() const {\n        std::ostringstream os;\n        os << \"frame_opts: \\n\";\n        os << frame_opts << \"\\n\";\n        os << \"\\n\";\n\n        os << \"mel_opts: \\n\";\n        os << mel_opts << \"\\n\";\n\n        os << \"use_energy: \" << use_energy << \"\\n\";\n        os << \"energy_floor: \" << energy_floor << \"\\n\";\n        os << \"raw_energy: \" << raw_energy << \"\\n\";\n        os << \"htk_compat: \" << htk_compat << \"\\n\";\n        os << \"use_log_fbank: \" << use_log_fbank << \"\\n\";\n        os << \"use_power: \" << use_power << \"\\n\";\n        return os.str();\n    }\n};\n\nstd::ostream &operator<<(std::ostream &os, const FbankOptions &opts);\n\nclass FbankComputer {\n  public:\n    using Options = FbankOptions;\n\n    explicit FbankComputer(const FbankOptions &opts);\n    ~FbankComputer();\n\n    int32_t Dim() const {\n        return opts_.mel_opts.num_bins + (opts_.use_energy ? 1 : 0);\n    }\n\n    // if true, compute log_energy_pre_window but after dithering and dc removal\n    bool NeedRawLogEnergy() const {\n        return opts_.use_energy && opts_.raw_energy;\n    }\n\n    const FrameExtractionOptions &GetFrameOptions() const {\n        return opts_.frame_opts;\n    }\n\n    const FbankOptions &GetOptions() const { return opts_; }\n\n    /**\n       Function that computes one frame of features from\n       one frame of signal.\n\n       @param [in] signal_raw_log_energy The log-energy of the frame of the\n       signal\n           prior to windowing and pre-emphasis, or\n           log(numeric_limits<float>::min()), whichever is greater.  Must be\n           ignored by this function if this class returns false from\n           this->NeedsRawLogEnergy().\n       @param [in] vtln_warp  The VTLN warping factor that the user wants\n           to be applied when computing features for this utterance.  Will\n           normally be 1.0, meaning no warping is to be done.  The value will\n           be ignored for feature types that don't support VLTN, such as\n           spectrogram features.\n       @param [in] signal_frame  One frame of the signal,\n         as extracted using the function ExtractWindow() using the options\n         returned by this->GetFrameOptions().  The function will use the\n         vector as a workspace, which is why it's a non-const pointer.\n       @param [out] feature  Pointer to a vector of size this->Dim(), to which\n           the computed feature will be written. It should be pre-allocated.\n    */\n    void Compute(float signal_raw_log_energy,\n                 float vtln_warp,\n                 std::vector<float> *signal_frame,\n                 float *feature);\n\n  private:\n    const MelBanks *GetMelBanks(float vtln_warp);\n\n    FbankOptions opts_;\n    float log_energy_floor_;\n    std::map<float, MelBanks *> mel_banks_;  // float is VTLN coefficient.\n    Rfft rfft_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_FEATURE_FBANK_H_\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-functions.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-functions.cc\n\n#include \"frontend/feature-functions.h\"\n\n#include <cstdint>\n#include <vector>\n\nnamespace knf {\n\nvoid ComputePowerSpectrum(std::vector<float> *complex_fft) {\n    int32_t dim = complex_fft->size();\n\n    // now we have in complex_fft, first half of complex spectrum\n    // it's stored as [real0, realN/2, real1, im1, real2, im2, ...]\n\n    float *p = complex_fft->data();\n    int32_t half_dim = dim / 2;\n    float first_energy = p[0] * p[0];\n    float last_energy = p[1] * p[1];  // handle this special case\n\n    for (int32_t i = 1; i < half_dim; ++i) {\n        float real = p[i * 2];\n        float im = p[i * 2 + 1];\n        p[i] = real * real + im * im;\n    }\n    p[0] = first_energy;\n    p[half_dim] = last_energy;  // Will actually never be used, and anyway\n    // if the signal has been bandlimited sensibly this should be zero.\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-functions.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/feature-functions.h\n#ifndef KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n#define KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n\n#include <vector>\nnamespace knf {\n\n// ComputePowerSpectrum converts a complex FFT (as produced by the FFT\n// functions in csrc/rfft.h), and converts it into\n// a power spectrum.  If the complex FFT is a vector of size n (representing\n// half of the complex FFT of a real signal of size n, as described there),\n// this function computes in the first (n/2) + 1 elements of it, the\n// energies of the fft bins from zero to the Nyquist frequency.  Contents of the\n// remaining (n/2) - 1 elements are undefined at output.\n\nvoid ComputePowerSpectrum(std::vector<float> *complex_fft);\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_FEATURE_FUNCTIONS_H\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-window.cc",
    "content": "// kaldi-native-fbank/csrc/feature-window.cc\n//\n// Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n\n// This file is copied/modified from kaldi/src/feat/feature-window.cc\n\n#include \"frontend/feature-window.h\"\n\n#include <cmath>\n#include <limits>\n#include <vector>\n\n#ifndef M_2PI\n#define M_2PI 6.283185307179586476925286766559005\n#endif\n\nnamespace knf {\n\nstd::ostream &operator<<(std::ostream &os, const FrameExtractionOptions &opts) {\n    os << opts.ToString();\n    return os;\n}\n\nFeatureWindowFunction::FeatureWindowFunction(const FrameExtractionOptions &opts)\n    : window_(opts.WindowSize()) {\n    int32_t frame_length = opts.WindowSize();\n    CHECK_GT(frame_length, 0);\n\n    float *window_data = window_.data();\n\n    double a = M_2PI / (frame_length - 1);\n    for (int32_t i = 0; i < frame_length; i++) {\n        double i_fl = static_cast<double>(i);\n        if (opts.window_type == \"hanning\") {\n            window_data[i] = 0.5 - 0.5 * cos(a * i_fl);\n        } else if (opts.window_type == \"sine\") {\n            // when you are checking ws wikipedia, please\n            // note that 0.5 * a = M_PI/(frame_length-1)\n            window_data[i] = sin(0.5 * a * i_fl);\n        } else if (opts.window_type == \"hamming\") {\n            window_data[i] = 0.54 - 0.46 * cos(a * i_fl);\n        } else if (opts.window_type ==\n                   \"povey\") {  // like hamming but goes to zero at edges.\n            window_data[i] = pow(0.5 - 0.5 * cos(a * i_fl), 0.85);\n        } else if (opts.window_type == \"rectangular\") {\n            window_data[i] = 1.0;\n        } else if (opts.window_type == \"blackman\") {\n            window_data[i] = opts.blackman_coeff - 0.5 * cos(a * i_fl) +\n                             (0.5 - opts.blackman_coeff) * cos(2 * a * i_fl);\n        } else {\n            LOG(FATAL) << \"Invalid window type \" << opts.window_type;\n        }\n    }\n}\n\nvoid FeatureWindowFunction::Apply(float *wave) const {\n    int32_t window_size = window_.size();\n    const float *p = window_.data();\n    for (int32_t k = 0; k != window_size; ++k) {\n        wave[k] *= p[k];\n    }\n}\n\nint64_t FirstSampleOfFrame(int32_t frame, const FrameExtractionOptions &opts) {\n    int64_t frame_shift = opts.WindowShift();\n    if (opts.snip_edges) {\n        return frame * frame_shift;\n    } else {\n        int64_t midpoint_of_frame = frame_shift * frame + frame_shift / 2,\n                beginning_of_frame = midpoint_of_frame - opts.WindowSize() / 2;\n        return beginning_of_frame;\n    }\n}\n\nint32_t NumFrames(int64_t num_samples,\n                  const FrameExtractionOptions &opts,\n                  bool flush /*= true*/) {\n    int64_t frame_shift = opts.WindowShift();\n    int64_t frame_length = opts.WindowSize();\n    if (opts.snip_edges) {\n        // with --snip-edges=true (the default), we use a HTK-like approach to\n        // determining the number of frames-- all frames have to fit completely\n        // into\n        // the waveform, and the first frame begins at sample zero.\n        if (num_samples < frame_length)\n            return 0;\n        else\n            return (1 + ((num_samples - frame_length) / frame_shift));\n        // You can understand the expression above as follows: 'num_samples -\n        // frame_length' is how much room we have to shift the frame within the\n        // waveform; 'frame_shift' is how much we shift it each time; and the\n        // ratio\n        // is how many times we can shift it (integer arithmetic rounds down).\n    } else {\n        // if --snip-edges=false, the number of frames is determined by rounding\n        // the\n        // (file-length / frame-shift) to the nearest integer.  The point of\n        // this\n        // formula is to make the number of frames an obvious and predictable\n        // function of the frame shift and signal length, which makes many\n        // segmentation-related questions simpler.\n        //\n        // Because integer division in C++ rounds toward zero, we add (half the\n        // frame-shift minus epsilon) before dividing, to have the effect of\n        // rounding towards the closest integer.\n        int32_t num_frames = (num_samples + (frame_shift / 2)) / frame_shift;\n\n        if (flush) return num_frames;\n\n        // note: 'end' always means the last plus one, i.e. one past the last.\n        int64_t end_sample_of_last_frame =\n            FirstSampleOfFrame(num_frames - 1, opts) + frame_length;\n\n        // the following code is optimized more for clarity than efficiency.\n        // If flush == false, we can't output frames that extend past the end\n        // of the signal.\n        while (num_frames > 0 && end_sample_of_last_frame > num_samples) {\n            num_frames--;\n            end_sample_of_last_frame -= frame_shift;\n        }\n        return num_frames;\n    }\n}\n\nvoid ExtractWindow(int64_t sample_offset,\n                   const std::vector<float> &wave,\n                   int32_t f,\n                   const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   std::vector<float> *window,\n                   float *log_energy_pre_window /*= nullptr*/) {\n    CHECK(sample_offset >= 0 && wave.size() != 0);\n\n    int32_t frame_length = opts.WindowSize();\n    int32_t frame_length_padded = opts.PaddedWindowSize();\n\n    int64_t num_samples = sample_offset + wave.size();\n    int64_t start_sample = FirstSampleOfFrame(f, opts);\n    int64_t end_sample = start_sample + frame_length;\n\n    if (opts.snip_edges) {\n        CHECK(start_sample >= sample_offset && end_sample <= num_samples);\n    } else {\n        CHECK(sample_offset == 0 || start_sample >= sample_offset);\n    }\n\n    if (window->size() != frame_length_padded) {\n        window->resize(frame_length_padded);\n    }\n\n    // wave_start and wave_end are start and end indexes into 'wave', for the\n    // piece of wave that we're trying to extract.\n    int32_t wave_start = int32_t(start_sample - sample_offset);\n    int32_t wave_end = wave_start + frame_length;\n\n    if (wave_start >= 0 && wave_end <= wave.size()) {\n        // the normal case-- no edge effects to consider.\n        std::copy(wave.begin() + wave_start,\n                  wave.begin() + wave_start + frame_length,\n                  window->data());\n    } else {\n        // Deal with any end effects by reflection, if needed.  This code will\n        // only\n        // be reached for about two frames per utterance, so we don't concern\n        // ourselves excessively with efficiency.\n        int32_t wave_dim = wave.size();\n        for (int32_t s = 0; s < frame_length; ++s) {\n            int32_t s_in_wave = s + wave_start;\n            while (s_in_wave < 0 || s_in_wave >= wave_dim) {\n                // reflect around the beginning or end of the wave.\n                // e.g. -1 -> 0, -2 -> 1.\n                // dim -> dim - 1, dim + 1 -> dim - 2.\n                // the code supports repeated reflections, although this\n                // would only be needed in pathological cases.\n                if (s_in_wave < 0)\n                    s_in_wave = -s_in_wave - 1;\n                else\n                    s_in_wave = 2 * wave_dim - 1 - s_in_wave;\n            }\n            (*window)[s] = wave[s_in_wave];\n        }\n    }\n\n    ProcessWindow(opts, window_function, window->data(), log_energy_pre_window);\n}\n\nstatic void RemoveDcOffset(float *d, int32_t n) {\n    float sum = 0;\n    for (int32_t i = 0; i != n; ++i) {\n        sum += d[i];\n    }\n\n    float mean = sum / n;\n\n    for (int32_t i = 0; i != n; ++i) {\n        d[i] -= mean;\n    }\n}\n\nfloat InnerProduct(const float *a, const float *b, int32_t n) {\n    float sum = 0;\n    for (int32_t i = 0; i != n; ++i) {\n        sum += a[i] * b[i];\n    }\n    return sum;\n}\n\nstatic void Preemphasize(float *d, int32_t n, float preemph_coeff) {\n    if (preemph_coeff == 0.0) {\n        return;\n    }\n\n    CHECK(preemph_coeff >= 0.0 && preemph_coeff <= 1.0);\n\n    for (int32_t i = n - 1; i > 0; --i) {\n        d[i] -= preemph_coeff * d[i - 1];\n    }\n    d[0] -= preemph_coeff * d[0];\n}\n\nvoid ProcessWindow(const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   float *window,\n                   float *log_energy_pre_window /*= nullptr*/) {\n    int32_t frame_length = opts.WindowSize();\n\n    // TODO(fangjun): Remove dither\n    CHECK_EQ(opts.dither, 0);\n\n    if (opts.remove_dc_offset) {\n        RemoveDcOffset(window, frame_length);\n    }\n\n    if (log_energy_pre_window != NULL) {\n        float energy =\n            std::max<float>(InnerProduct(window, window, frame_length),\n                            std::numeric_limits<float>::epsilon());\n        *log_energy_pre_window = std::log(energy);\n    }\n\n    if (opts.preemph_coeff != 0.0) {\n        Preemphasize(window, frame_length, opts.preemph_coeff);\n    }\n\n    window_function.Apply(window);\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature-window.h",
    "content": "// kaldi-native-fbank/csrc/feature-window.h\n//\n// Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n\n// This file is copied/modified from kaldi/src/feat/feature-window.h\n\n#ifndef KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n#define KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"base/log.h\"\n\nnamespace knf {\n\ninline int32_t RoundUpToNearestPowerOfTwo(int32_t n) {\n    // copied from kaldi/src/base/kaldi-math.cc\n    CHECK_GT(n, 0);\n    n--;\n    n |= n >> 1;\n    n |= n >> 2;\n    n |= n >> 4;\n    n |= n >> 8;\n    n |= n >> 16;\n    return n + 1;\n}\n\nstruct FrameExtractionOptions {\n    float samp_freq = 16000;\n    float frame_shift_ms = 10.0f;   // in milliseconds.\n    float frame_length_ms = 25.0f;  // in milliseconds.\n    float dither = 1.0f;            // Amount of dithering, 0.0 means no dither.\n    float preemph_coeff = 0.97f;    // Preemphasis coefficient.\n    bool remove_dc_offset = true;   // Subtract mean of wave before FFT.\n    std::string window_type = \"povey\";  // e.g. Hamming window\n    // May be \"hamming\", \"rectangular\", \"povey\", \"hanning\", \"sine\", \"blackman\"\n    // \"povey\" is a window I made to be similar to Hamming but to go to zero at\n    // the edges, it's pow((0.5 - 0.5*cos(n/N*2*pi)), 0.85) I just don't think\n    // the\n    // Hamming window makes sense as a windowing function.\n    bool round_to_power_of_two = true;\n    float blackman_coeff = 0.42f;\n    bool snip_edges = true;\n    // bool allow_downsample = false;\n    // bool allow_upsample = false;\n\n    // Used for streaming feature extraction. It indicates the number\n    // of feature frames to keep in the recycling vector. -1 means to\n    // keep all feature frames.\n    int32_t max_feature_vectors = -1;\n\n    int32_t WindowShift() const {\n        return static_cast<int32_t>(samp_freq * 0.001f * frame_shift_ms);\n    }\n    int32_t WindowSize() const {\n        return static_cast<int32_t>(samp_freq * 0.001f * frame_length_ms);\n    }\n    int32_t PaddedWindowSize() const {\n        return (round_to_power_of_two ? RoundUpToNearestPowerOfTwo(WindowSize())\n                                      : WindowSize());\n    }\n    std::string ToString() const {\n        std::ostringstream os;\n#define KNF_PRINT(x) os << #x << \": \" << x << \"\\n\"\n        KNF_PRINT(samp_freq);\n        KNF_PRINT(frame_shift_ms);\n        KNF_PRINT(frame_length_ms);\n        KNF_PRINT(dither);\n        KNF_PRINT(preemph_coeff);\n        KNF_PRINT(remove_dc_offset);\n        KNF_PRINT(window_type);\n        KNF_PRINT(round_to_power_of_two);\n        KNF_PRINT(blackman_coeff);\n        KNF_PRINT(snip_edges);\n        // KNF_PRINT(allow_downsample);\n        // KNF_PRINT(allow_upsample);\n        KNF_PRINT(max_feature_vectors);\n#undef KNF_PRINT\n        return os.str();\n    }\n};\n\nstd::ostream &operator<<(std::ostream &os, const FrameExtractionOptions &opts);\n\nclass FeatureWindowFunction {\n  public:\n    FeatureWindowFunction() = default;\n    explicit FeatureWindowFunction(const FrameExtractionOptions &opts);\n    /**\n     * @param wave Pointer to a 1-D array of shape [window_size].\n     *             It is modified in-place: wave[i] = wave[i] * window_[i].\n     * @param\n     */\n    void Apply(float *wave) const;\n\n  private:\n    std::vector<float> window_;  // of size opts.WindowSize()\n};\n\nint64_t FirstSampleOfFrame(int32_t frame, const FrameExtractionOptions &opts);\n\n/**\n   This function returns the number of frames that we can extract from a wave\n   file with the given number of samples in it (assumed to have the same\n   sampling rate as specified in 'opts').\n\n      @param [in] num_samples  The number of samples in the wave file.\n      @param [in] opts     The frame-extraction options class\n\n      @param [in] flush   True if we are asserting that this number of samples\n   is 'all there is', false if we expecting more data to possibly come in.  This\n   only makes a difference to the answer\n   if opts.snips_edges== false.  For offline feature extraction you always want\n   flush == true.  In an online-decoding context, once you know (or decide) that\n   no more data is coming in, you'd call it with flush == true at the end to\n   flush out any remaining data.\n*/\nint32_t NumFrames(int64_t num_samples,\n                  const FrameExtractionOptions &opts,\n                  bool flush = true);\n\n/*\n  ExtractWindow() extracts a windowed frame of waveform (possibly with a\n  power-of-two, padded size, depending on the config), including all the\n  processing done by ProcessWindow().\n\n  @param [in] sample_offset  If 'wave' is not the entire waveform, but\n                   part of it to the left has been discarded, then the\n                   number of samples prior to 'wave' that we have\n                   already discarded.  Set this to zero if you are\n                   processing the entire waveform in one piece, or\n                   if you get 'no matching function' compilation\n                   errors when updating the code.\n  @param [in] wave  The waveform\n  @param [in] f     The frame index to be extracted, with\n                    0 <= f < NumFrames(sample_offset + wave.Dim(), opts, true)\n  @param [in] opts  The options class to be used\n  @param [in] window_function  The windowing function, as derived from the\n                    options class.\n  @param [out] window  The windowed, possibly-padded waveform to be\n                     extracted.  Will be resized as needed.\n  @param [out] log_energy_pre_window  If non-NULL, the log-energy of\n                   the signal prior to pre-emphasis and multiplying by\n                   the windowing function will be written to here.\n*/\nvoid ExtractWindow(int64_t sample_offset,\n                   const std::vector<float> &wave,\n                   int32_t f,\n                   const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   std::vector<float> *window,\n                   float *log_energy_pre_window = nullptr);\n\n/**\n  This function does all the windowing steps after actually\n  extracting the windowed signal: depending on the\n  configuration, it does dithering, dc offset removal,\n  preemphasis, and multiplication by the windowing function.\n   @param [in] opts  The options class to be used\n   @param [in] window_function  The windowing function-- should have\n                    been initialized using 'opts'.\n   @param [in,out] window  A vector of size opts.WindowSize().  Note:\n      it will typically be a sub-vector of a larger vector of size\n      opts.PaddedWindowSize(), with the remaining samples zero,\n      as the FFT code is more efficient if it operates on data with\n      power-of-two size.\n   @param [out]   log_energy_pre_window If non-NULL, then after dithering and\n      DC offset removal, this function will write to this pointer the log of\n      the total energy (i.e. sum-squared) of the frame.\n */\nvoid ProcessWindow(const FrameExtractionOptions &opts,\n                   const FeatureWindowFunction &window_function,\n                   float *window,\n                   float *log_energy_pre_window = nullptr);\n\n// Compute the inner product of two vectors\nfloat InnerProduct(const float *a, const float *b, int32_t n);\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FEAT_CSRC_FEATURE_WINDOW_H_\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_cache.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/feature_cache.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing std::unique_ptr;\nusing std::vector;\n\nFeatureCache::FeatureCache(size_t max_size,\n                           unique_ptr<FrontendInterface> base_extractor) {\n    max_size_ = max_size;\n    base_extractor_ = std::move(base_extractor);\n    dim_ = base_extractor_->Dim();\n}\n\nvoid FeatureCache::Accept(const std::vector<kaldi::BaseFloat>& inputs) {\n    // read inputs\n    base_extractor_->Accept(inputs);\n}\n\n// pop feature chunk\nbool FeatureCache::Read(std::vector<kaldi::BaseFloat>* feats) {\n    kaldi::Timer timer;\n    std::unique_lock<std::mutex> lock(mutex_);\n    // feed current data\n    if (cache_.empty()) {\n        bool result = false;\n        do {\n            result = Compute();\n        } while (result);\n    }\n\n    if (cache_.empty()) return false;\n\n    // read from cache\n    *feats = cache_.front();\n    cache_.pop();\n    VLOG(2) << \"FeatureCache::Read cost: \" << timer.Elapsed() << \" sec.\";\n    VLOG(1) << \"FeatureCache::size : \" <<  cache_.size();\n    return true;\n}\n\n// read all data from base_feature_extractor_ into cache_\nbool FeatureCache::Compute() {\n    // compute and feed\n    vector<BaseFloat> feature;\n    bool result = base_extractor_->Read(&feature);\n    if (result == false || feature.size() == 0) return false;\n\n    kaldi::Timer timer;\n\n    int32 num_chunk = feature.size() / dim_;\n    VLOG(3) << \"nframe computed: \" << nframe_;\n\n    for (int chunk_idx = 0; chunk_idx < num_chunk; ++chunk_idx) {\n        int32 start = chunk_idx * dim_;\n        vector<BaseFloat> feature_chunk(feature.data() + start,\n                                        feature.data() + start + dim_);\n        // feed cache\n        cache_.push(feature_chunk);\n        ++nframe_;\n    }\n\n    VLOG(2) << \"FeatureCache::Compute cost: \" << timer.Elapsed() << \" sec. \"\n            << num_chunk << \" feats.\";\n    return true;\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_cache.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/frontend_itf.h\"\n\nnamespace ppspeech {\n\nclass FeatureCache : public FrontendInterface {\n  public:\n    explicit FeatureCache(\n        size_t max_size = kint16max,\n        std::unique_ptr<FrontendInterface> base_extractor = NULL);\n\n    // Feed feats or waves\n    virtual void Accept(const std::vector<kaldi::BaseFloat>& inputs);\n\n    // feats size = num_frames * feat_dim\n    virtual bool Read(std::vector<kaldi::BaseFloat>* feats);\n\n    // feat dim\n    virtual size_t Dim() const { return dim_; }\n\n    virtual void SetFinished() {\n        std::unique_lock<std::mutex> lock(mutex_);\n        base_extractor_->SetFinished();\n    }\n\n    virtual bool IsFinished() const {\n      return base_extractor_->IsFinished() && cache_.empty(); \n    }\n\n    void Reset() override {\n        std::queue<std::vector<BaseFloat>> empty;\n        VLOG(1) << \"feature cache size: \" << cache_.size();\n        std::swap(cache_, empty);\n        nframe_ = 0;\n        base_extractor_->Reset();\n    }\n\n  private:\n    bool Compute();\n\n    int32 dim_;\n    size_t max_size_;  // cache capacity\n    std::unique_ptr<FrontendInterface> base_extractor_;\n\n    std::queue<std::vector<BaseFloat>> cache_;  // feature cache\n    std::mutex mutex_;\n\n    int32 nframe_;  // num of feature computed\n    DISALLOW_COPY_AND_ASSIGN(FeatureCache);\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_common.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"frontend/feature-window.h\"\n#include \"frontend_itf.h\"\n\nnamespace ppspeech {\n\ntemplate <class F>\nclass StreamingFeatureTpl : public FrontendInterface {\n  public:\n    typedef typename F::Options Options;\n    StreamingFeatureTpl(const Options& opts,\n                        std::unique_ptr<FrontendInterface> base_extractor);\n    virtual void Accept(const std::vector<kaldi::BaseFloat>& waves);\n    virtual bool Read(std::vector<kaldi::BaseFloat>* feats);\n\n    // the dim_ is the dim of single frame feature\n    virtual size_t Dim() const { return computer_.Dim(); }\n\n    virtual void SetFinished() { base_extractor_->SetFinished(); }\n\n    virtual bool IsFinished() const { return base_extractor_->IsFinished(); }\n\n    virtual void Reset() {\n        base_extractor_->Reset();\n        remained_wav_.resize(0);\n    }\n\n  private:\n    bool Compute(const std::vector<kaldi::BaseFloat>& waves,\n                 std::vector<kaldi::BaseFloat>* feats);\n    Options opts_;\n    std::unique_ptr<FrontendInterface> base_extractor_;\n    knf::FeatureWindowFunction window_function_;\n    std::vector<kaldi::BaseFloat> remained_wav_;\n    F computer_;\n};\n\n}  // namespace ppspeech\n\n#include \"frontend/feature_common_inl.h\"\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_common_inl.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\nnamespace ppspeech {\n\ntemplate <class F>\nStreamingFeatureTpl<F>::StreamingFeatureTpl(\n    const Options& opts, std::unique_ptr<FrontendInterface> base_extractor)\n    : opts_(opts), computer_(opts), window_function_(opts.frame_opts) {\n    base_extractor_ = std::move(base_extractor);\n}\n\ntemplate <class F>\nvoid StreamingFeatureTpl<F>::Accept(\n    const std::vector<kaldi::BaseFloat>& waves) {\n    base_extractor_->Accept(waves);\n}\n\ntemplate <class F>\nbool StreamingFeatureTpl<F>::Read(std::vector<kaldi::BaseFloat>* feats) {\n    std::vector<kaldi::BaseFloat> wav(base_extractor_->Dim());\n    bool flag = base_extractor_->Read(&wav);\n    if (flag == false || wav.size() == 0) return false;\n\n    // append remaned waves\n    int32 wav_len = wav.size();\n    int32 left_len = remained_wav_.size();\n    std::vector<kaldi::BaseFloat> waves(left_len + wav_len);\n    std::memcpy(waves.data(),\n                remained_wav_.data(),\n                left_len * sizeof(kaldi::BaseFloat));\n    std::memcpy(waves.data() + left_len,\n                wav.data(),\n                wav_len * sizeof(kaldi::BaseFloat));\n\n    // compute speech feature\n    Compute(waves, feats);\n\n    // cache remaned waves\n    knf::FrameExtractionOptions frame_opts = computer_.GetFrameOptions();\n    int32 num_frames = knf::NumFrames(waves.size(), frame_opts);\n    int32 frame_shift = frame_opts.WindowShift();\n    int32 left_samples = waves.size() - frame_shift * num_frames;\n    remained_wav_.resize(left_samples);\n    std::memcpy(remained_wav_.data(),\n                waves.data() + frame_shift * num_frames,\n                left_samples * sizeof(BaseFloat));\n    return true;\n}\n\n// Compute feat\ntemplate <class F>\nbool StreamingFeatureTpl<F>::Compute(const std::vector<kaldi::BaseFloat>& waves,\n                                     std::vector<kaldi::BaseFloat>* feats) {\n    const knf::FrameExtractionOptions& frame_opts = computer_.GetFrameOptions();\n    int32 num_samples = waves.size();\n    int32 frame_length = frame_opts.WindowSize();\n    int32 sample_rate = frame_opts.samp_freq;\n    if (num_samples < frame_length) {\n        return true;\n    }\n\n    int32 num_frames = knf::NumFrames(num_samples, frame_opts);\n    feats->resize(num_frames * Dim());\n\n    std::vector<kaldi::BaseFloat> window;\n    bool need_raw_log_energy = computer_.NeedRawLogEnergy();\n    for (int32 frame = 0; frame < num_frames; frame++) {\n        std::fill(window.begin(), window.end(), 0);\n        kaldi::BaseFloat raw_log_energy = 0.0;\n        kaldi::BaseFloat vtln_warp = 1.0;\n        knf::ExtractWindow(0,\n                           waves,\n                           frame,\n                           frame_opts,\n                           window_function_,\n                           &window,\n                           need_raw_log_energy ? &raw_log_energy : NULL);\n\n        std::vector<kaldi::BaseFloat> this_feature(computer_.Dim());\n        computer_.Compute(\n            raw_log_energy, vtln_warp, &window, this_feature.data());\n        std::memcpy(feats->data() + frame * Dim(),\n                    this_feature.data(),\n                    sizeof(BaseFloat) * Dim());\n    }\n    return true;\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_pipeline.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/feature_pipeline.h\"\n\nnamespace ppspeech {\n\nusing std::unique_ptr;\n\nFeaturePipeline::FeaturePipeline(const FeaturePipelineOptions& opts)\n    : opts_(opts) {\n    unique_ptr<FrontendInterface> data_source(\n        new ppspeech::AudioCache(1000 * kint16max, false));\n\n    unique_ptr<FrontendInterface> base_feature;\n\n    base_feature.reset(\n        new ppspeech::Fbank(opts.fbank_opts, std::move(data_source)));\n\n    // CHECK_NE(opts.cmvn_file, \"\");\n    unique_ptr<FrontendInterface> cache;\n    if (opts.cmvn_file != \"\"){\n        unique_ptr<FrontendInterface> cmvn(\n            new ppspeech::CMVN(opts.cmvn_file, std::move(base_feature)));\n\n        cache.reset(\n            new ppspeech::FeatureCache(kint16max, std::move(cmvn)));\n    } else {\n        cache.reset(\n            new ppspeech::FeatureCache(kint16max, std::move(base_feature)));\n    }\n\n    base_extractor_.reset(\n        new ppspeech::Assembler(opts.assembler_opts, std::move(cache)));\n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/feature_pipeline.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// todo refactor later (SGoat)\n\n#pragma once\n\n#include \"frontend/assembler.h\"\n#include \"frontend/audio_cache.h\"\n#include \"frontend/cmvn.h\"\n#include \"frontend/data_cache.h\"\n#include \"frontend/fbank.h\"\n#include \"frontend/feature_cache.h\"\n#include \"frontend/frontend_itf.h\"\n\n// feature\nDECLARE_bool(fill_zero);\nDECLARE_int32(num_bins);\nDECLARE_string(cmvn_file);\n\n// feature sliding window\nDECLARE_int32(receptive_field_length);\nDECLARE_int32(subsampling_rate);\nDECLARE_int32(nnet_decoder_chunk);\n\nnamespace ppspeech {\n\nstruct FeaturePipelineOptions {\n    std::string cmvn_file{};\n    knf::FbankOptions fbank_opts{};\n    AssemblerOptions assembler_opts{};\n\n    static FeaturePipelineOptions InitFromFlags() {\n        FeaturePipelineOptions opts;\n        opts.cmvn_file = FLAGS_cmvn_file;\n        LOG(INFO) << \"cmvn file: \" << opts.cmvn_file;\n\n        // frame options\n        knf::FrameExtractionOptions frame_opts;\n        frame_opts.dither = 0.0;\n        LOG(INFO) << \"dither: \" << frame_opts.dither;\n        frame_opts.frame_shift_ms = 10;\n        LOG(INFO) << \"frame shift ms: \" << frame_opts.frame_shift_ms;\n        frame_opts.window_type = \"povey\";\n        frame_opts.frame_length_ms = 25;\n        opts.fbank_opts.mel_opts.num_bins = FLAGS_num_bins;\n        LOG(INFO) << \"num bins: \" << opts.fbank_opts.mel_opts.num_bins;\n\n        opts.fbank_opts.frame_opts = frame_opts;\n        LOG(INFO) << \"frame length ms: \" << frame_opts.frame_length_ms;\n\n        // assembler opts\n        opts.assembler_opts.subsampling_rate = FLAGS_subsampling_rate;\n        opts.assembler_opts.receptive_filed_length =\n            FLAGS_receptive_field_length;\n        opts.assembler_opts.nnet_decoder_chunk = FLAGS_nnet_decoder_chunk;\n        opts.assembler_opts.fill_zero = FLAGS_fill_zero;\n        LOG(INFO) << \"subsampling rate: \"\n                  << opts.assembler_opts.subsampling_rate;\n        LOG(INFO) << \"nnet receptive filed length: \"\n                  << opts.assembler_opts.receptive_filed_length;\n        LOG(INFO) << \"nnet chunk size: \"\n                  << opts.assembler_opts.nnet_decoder_chunk;\n        LOG(INFO) << \"frontend fill zeros: \" << opts.assembler_opts.fill_zero;\n        return opts;\n    }\n};\n\n\nclass FeaturePipeline : public FrontendInterface {\n  public:\n    explicit FeaturePipeline(const FeaturePipelineOptions& opts);\n    virtual void Accept(const std::vector<kaldi::BaseFloat>& waves) {\n        base_extractor_->Accept(waves);\n    }\n    virtual bool Read(std::vector<kaldi::BaseFloat>* feats) {\n        return base_extractor_->Read(feats);\n    }\n    virtual size_t Dim() const { return base_extractor_->Dim(); }\n    virtual void SetFinished() { base_extractor_->SetFinished(); }\n    virtual bool IsFinished() const { return base_extractor_->IsFinished(); }\n    virtual void Reset() { base_extractor_->Reset(); }\n\n    const FeaturePipelineOptions& Config() { return opts_; }\n\n    const BaseFloat FrameShift() const {\n        return opts_.fbank_opts.frame_opts.frame_shift_ms;\n    }\n    const BaseFloat FrameLength() const {\n        return opts_.fbank_opts.frame_opts.frame_length_ms;\n    }\n    const BaseFloat SampleRate() const {\n        return opts_.fbank_opts.frame_opts.samp_freq;\n    }\n\n  private:\n    FeaturePipelineOptions opts_;\n    std::unique_ptr<FrontendInterface> base_extractor_;\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/fftsg.c",
    "content": "/* This file is copied from\n * https://www.kurims.kyoto-u.ac.jp/~ooura/fft.html\n */\n/*\nFast Fourier/Cosine/Sine Transform\n    dimension   :one\n    data length :power of 2\n    decimation  :frequency\n    radix       :split-radix\n    data        :inplace\n    table       :use\nfunctions\n    cdft: Complex Discrete Fourier Transform\n    rdft: Real Discrete Fourier Transform\n    ddct: Discrete Cosine Transform\n    ddst: Discrete Sine Transform\n    dfct: Cosine Transform of RDFT (Real Symmetric DFT)\n    dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)\nfunction prototypes\n    void cdft(int, int, double *, int *, double *);\n    void rdft(int, int, double *, int *, double *);\n    void ddct(int, int, double *, int *, double *);\n    void ddst(int, int, double *, int *, double *);\n    void dfct(int, double *, double *, int *, double *);\n    void dfst(int, double *, double *, int *, double *);\nmacro definitions\n    USE_CDFT_PTHREADS : default=not defined\n        CDFT_THREADS_BEGIN_N  : must be >= 512, default=8192\n        CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536\n    USE_CDFT_WINTHREADS : default=not defined\n        CDFT_THREADS_BEGIN_N  : must be >= 512, default=32768\n        CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288\n\n\n-------- Complex DFT (Discrete Fourier Transform) --------\n    [definition]\n        <case1>\n            X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n\n        <case2>\n            X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n\n        (notes: sum_j=0^n-1 is a summation from j=0 to n-1)\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            cdft(2*n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            cdft(2*n, -1, a, ip, w);\n    [parameters]\n        2*n            :data length (int)\n                        n >= 1, n = power of 2\n        a[0...2*n-1]   :input/output data (double *)\n                        input data\n                            a[2*j] = Re(x[j]),\n                            a[2*j+1] = Im(x[j]), 0<=j<n\n                        output data\n                            a[2*k] = Re(X[k]),\n                            a[2*k+1] = Im(X[k]), 0<=k<n\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n/2-1]   :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            cdft(2*n, -1, a, ip, w);\n        is\n            cdft(2*n, 1, a, ip, w);\n            for (j = 0; j <= 2 * n - 1; j++) {\n                a[j] *= 1.0 / n;\n            }\n        .\n\n\n-------- Real DFT / Inverse of Real DFT --------\n    [definition]\n        <case1> RDFT\n            R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2\n            I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2\n        <case2> IRDFT (excluding scale)\n            a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +\n                   sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +\n                   sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            rdft(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            rdft(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        <case1>\n                            output data\n                                a[2*k] = R[k], 0<=k<n/2\n                                a[2*k+1] = I[k], 0<k<n/2\n                                a[1] = R[n/2]\n                        <case2>\n                            input data\n                                a[2*j] = R[j], 0<=j<n/2\n                                a[2*j+1] = I[j], 0<j<n/2\n                                a[1] = R[n/2]\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n/2-1]   :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            rdft(n, 1, a, ip, w);\n        is\n            rdft(n, -1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- DCT (Discrete Cosine Transform) / Inverse of DCT --------\n    [definition]\n        <case1> IDCT (excluding scale)\n            C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n\n        <case2> DCT\n            C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            ddct(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            ddct(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        output data\n                            a[k] = C[k], 0<=k<n\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/4-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            ddct(n, -1, a, ip, w);\n        is\n            a[0] *= 0.5;\n            ddct(n, 1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- DST (Discrete Sine Transform) / Inverse of DST --------\n    [definition]\n        <case1> IDST (excluding scale)\n            S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n\n        <case2> DST\n            S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n\n    [usage]\n        <case1>\n            ip[0] = 0; // first time only\n            ddst(n, 1, a, ip, w);\n        <case2>\n            ip[0] = 0; // first time only\n            ddst(n, -1, a, ip, w);\n    [parameters]\n        n              :data length (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        <case1>\n                            input data\n                                a[j] = A[j], 0<j<n\n                                a[0] = A[n]\n                            output data\n                                a[k] = S[k], 0<=k<n\n                        <case2>\n                            output data\n                                a[k] = S[k], 0<k<n\n                                a[0] = S[n]\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/2)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/4-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            ddst(n, -1, a, ip, w);\n        is\n            a[0] *= 0.5;\n            ddst(n, 1, a, ip, w);\n            for (j = 0; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- Cosine Transform of RDFT (Real Symmetric DFT) --------\n    [definition]\n        C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n\n    [usage]\n        ip[0] = 0; // first time only\n        dfct(n, a, t, ip, w);\n    [parameters]\n        n              :data length - 1 (int)\n                        n >= 2, n = power of 2\n        a[0...n]       :input/output data (double *)\n                        output data\n                            a[k] = C[k], 0<=k<=n\n        t[0...n/2]     :work area (double *)\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/4)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/8-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            a[0] *= 0.5;\n            a[n] *= 0.5;\n            dfct(n, a, t, ip, w);\n        is\n            a[0] *= 0.5;\n            a[n] *= 0.5;\n            dfct(n, a, t, ip, w);\n            for (j = 0; j <= n; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\n-------- Sine Transform of RDFT (Real Anti-symmetric DFT) --------\n    [definition]\n        S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n\n    [usage]\n        ip[0] = 0; // first time only\n        dfst(n, a, t, ip, w);\n    [parameters]\n        n              :data length + 1 (int)\n                        n >= 2, n = power of 2\n        a[0...n-1]     :input/output data (double *)\n                        output data\n                            a[k] = S[k], 0<k<n\n                        (a[0] is used for work area)\n        t[0...n/2-1]   :work area (double *)\n        ip[0...*]      :work area for bit reversal (int *)\n                        length of ip >= 2+sqrt(n/4)\n                        strictly,\n                        length of ip >=\n                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).\n                        ip[0],ip[1] are pointers of the cos/sin table.\n        w[0...n*5/8-1] :cos/sin table (double *)\n                        w[],ip[] are initialized if ip[0] == 0.\n    [remark]\n        Inverse of\n            dfst(n, a, t, ip, w);\n        is\n            dfst(n, a, t, ip, w);\n            for (j = 1; j <= n - 1; j++) {\n                a[j] *= 2.0 / n;\n            }\n        .\n\n\nAppendix :\n    The cos/sin table is recalculated when the larger table required.\n    w[] and ip[] are compatible with all routines.\n*/\n\n\nvoid cdft(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    int nw;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    if (isgn >= 0) {\n        cftfsub(n, a, ip, nw, w);\n    } else {\n        cftbsub(n, a, ip, nw, w);\n    }\n}\n\n\nvoid rdft(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    int nw, nc;\n    double xi;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 2)) {\n        nc = n >> 2;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xi = a[0] - a[1];\n        a[0] += a[1];\n        a[1] = xi;\n    } else {\n        a[1] = 0.5 * (a[0] - a[1]);\n        a[0] -= a[1];\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n}\n\n\nvoid ddct(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    void dctsub(int n, double *a, int nc, double *c);\n    int j, nw, nc;\n    double xr;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > nc) {\n        nc = n;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn < 0) {\n        xr = a[n - 1];\n        for (j = n - 2; j >= 2; j -= 2) {\n            a[j + 1] = a[j] - a[j - 1];\n            a[j] += a[j - 1];\n        }\n        a[1] = a[0] - xr;\n        a[0] += xr;\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n    dctsub(n, a, nc, w + nw);\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xr = a[0] - a[1];\n        a[0] += a[1];\n        for (j = 2; j < n; j += 2) {\n            a[j - 1] = a[j] - a[j + 1];\n            a[j] += a[j + 1];\n        }\n        a[n - 1] = xr;\n    }\n}\n\n\nvoid ddst(int n, int isgn, double *a, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void cftbsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void rftbsub(int n, double *a, int nc, double *c);\n    void dstsub(int n, double *a, int nc, double *c);\n    int j, nw, nc;\n    double xr;\n\n    nw = ip[0];\n    if (n > (nw << 2)) {\n        nw = n >> 2;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > nc) {\n        nc = n;\n        makect(nc, ip, w + nw);\n    }\n    if (isgn < 0) {\n        xr = a[n - 1];\n        for (j = n - 2; j >= 2; j -= 2) {\n            a[j + 1] = -a[j] - a[j - 1];\n            a[j] -= a[j - 1];\n        }\n        a[1] = a[0] + xr;\n        a[0] -= xr;\n        if (n > 4) {\n            rftbsub(n, a, nc, w + nw);\n            cftbsub(n, a, ip, nw, w);\n        } else if (n == 4) {\n            cftbsub(n, a, ip, nw, w);\n        }\n    }\n    dstsub(n, a, nc, w + nw);\n    if (isgn >= 0) {\n        if (n > 4) {\n            cftfsub(n, a, ip, nw, w);\n            rftfsub(n, a, nc, w + nw);\n        } else if (n == 4) {\n            cftfsub(n, a, ip, nw, w);\n        }\n        xr = a[0] - a[1];\n        a[0] += a[1];\n        for (j = 2; j < n; j += 2) {\n            a[j - 1] = -a[j] - a[j + 1];\n            a[j] -= a[j + 1];\n        }\n        a[n - 1] = -xr;\n    }\n}\n\n\nvoid dfct(int n, double *a, double *t, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void dctsub(int n, double *a, int nc, double *c);\n    int j, k, l, m, mh, nw, nc;\n    double xr, xi, yr, yi;\n\n    nw = ip[0];\n    if (n > (nw << 3)) {\n        nw = n >> 3;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 1)) {\n        nc = n >> 1;\n        makect(nc, ip, w + nw);\n    }\n    m = n >> 1;\n    yi = a[m];\n    xi = a[0] + a[n];\n    a[0] -= a[n];\n    t[0] = xi - yi;\n    t[m] = xi + yi;\n    if (n > 2) {\n        mh = m >> 1;\n        for (j = 1; j < mh; j++) {\n            k = m - j;\n            xr = a[j] - a[n - j];\n            xi = a[j] + a[n - j];\n            yr = a[k] - a[n - k];\n            yi = a[k] + a[n - k];\n            a[j] = xr;\n            a[k] = yr;\n            t[j] = xi - yi;\n            t[k] = xi + yi;\n        }\n        t[mh] = a[mh] + a[n - mh];\n        a[mh] -= a[n - mh];\n        dctsub(m, a, nc, w + nw);\n        if (m > 4) {\n            cftfsub(m, a, ip, nw, w);\n            rftfsub(m, a, nc, w + nw);\n        } else if (m == 4) {\n            cftfsub(m, a, ip, nw, w);\n        }\n        a[n - 1] = a[0] - a[1];\n        a[1] = a[0] + a[1];\n        for (j = m - 2; j >= 2; j -= 2) {\n            a[2 * j + 1] = a[j] + a[j + 1];\n            a[2 * j - 1] = a[j] - a[j + 1];\n        }\n        l = 2;\n        m = mh;\n        while (m >= 2) {\n            dctsub(m, t, nc, w + nw);\n            if (m > 4) {\n                cftfsub(m, t, ip, nw, w);\n                rftfsub(m, t, nc, w + nw);\n            } else if (m == 4) {\n                cftfsub(m, t, ip, nw, w);\n            }\n            a[n - l] = t[0] - t[1];\n            a[l] = t[0] + t[1];\n            k = 0;\n            for (j = 2; j < m; j += 2) {\n                k += l << 2;\n                a[k - l] = t[j] - t[j + 1];\n                a[k + l] = t[j] + t[j + 1];\n            }\n            l <<= 1;\n            mh = m >> 1;\n            for (j = 0; j < mh; j++) {\n                k = m - j;\n                t[j] = t[m + k] - t[m + j];\n                t[k] = t[m + k] + t[m + j];\n            }\n            t[mh] = t[m + mh];\n            m = mh;\n        }\n        a[l] = t[0];\n        a[n] = t[2] - t[1];\n        a[0] = t[2] + t[1];\n    } else {\n        a[1] = a[0];\n        a[2] = t[0];\n        a[0] = t[1];\n    }\n}\n\n\nvoid dfst(int n, double *a, double *t, int *ip, double *w) {\n    void makewt(int nw, int *ip, double *w);\n    void makect(int nc, int *ip, double *c);\n    void cftfsub(int n, double *a, int *ip, int nw, double *w);\n    void rftfsub(int n, double *a, int nc, double *c);\n    void dstsub(int n, double *a, int nc, double *c);\n    int j, k, l, m, mh, nw, nc;\n    double xr, xi, yr, yi;\n\n    nw = ip[0];\n    if (n > (nw << 3)) {\n        nw = n >> 3;\n        makewt(nw, ip, w);\n    }\n    nc = ip[1];\n    if (n > (nc << 1)) {\n        nc = n >> 1;\n        makect(nc, ip, w + nw);\n    }\n    if (n > 2) {\n        m = n >> 1;\n        mh = m >> 1;\n        for (j = 1; j < mh; j++) {\n            k = m - j;\n            xr = a[j] + a[n - j];\n            xi = a[j] - a[n - j];\n            yr = a[k] + a[n - k];\n            yi = a[k] - a[n - k];\n            a[j] = xr;\n            a[k] = yr;\n            t[j] = xi + yi;\n            t[k] = xi - yi;\n        }\n        t[0] = a[mh] - a[n - mh];\n        a[mh] += a[n - mh];\n        a[0] = a[m];\n        dstsub(m, a, nc, w + nw);\n        if (m > 4) {\n            cftfsub(m, a, ip, nw, w);\n            rftfsub(m, a, nc, w + nw);\n        } else if (m == 4) {\n            cftfsub(m, a, ip, nw, w);\n        }\n        a[n - 1] = a[1] - a[0];\n        a[1] = a[0] + a[1];\n        for (j = m - 2; j >= 2; j -= 2) {\n            a[2 * j + 1] = a[j] - a[j + 1];\n            a[2 * j - 1] = -a[j] - a[j + 1];\n        }\n        l = 2;\n        m = mh;\n        while (m >= 2) {\n            dstsub(m, t, nc, w + nw);\n            if (m > 4) {\n                cftfsub(m, t, ip, nw, w);\n                rftfsub(m, t, nc, w + nw);\n            } else if (m == 4) {\n                cftfsub(m, t, ip, nw, w);\n            }\n            a[n - l] = t[1] - t[0];\n            a[l] = t[0] + t[1];\n            k = 0;\n            for (j = 2; j < m; j += 2) {\n                k += l << 2;\n                a[k - l] = -t[j] - t[j + 1];\n                a[k + l] = t[j] - t[j + 1];\n            }\n            l <<= 1;\n            mh = m >> 1;\n            for (j = 1; j < mh; j++) {\n                k = m - j;\n                t[j] = t[m + k] + t[m + j];\n                t[k] = t[m + k] - t[m + j];\n            }\n            t[0] = t[m + mh];\n            m = mh;\n        }\n        a[l] = t[0];\n    }\n    a[0] = 0;\n}\n\n\n/* -------- initializing routines -------- */\n\n\n#include <math.h>\n\nvoid makewt(int nw, int *ip, double *w) {\n    void makeipt(int nw, int *ip);\n    int j, nwh, nw0, nw1;\n    double delta, wn4r, wk1r, wk1i, wk3r, wk3i;\n\n    ip[0] = nw;\n    ip[1] = 1;\n    if (nw > 2) {\n        nwh = nw >> 1;\n        delta = atan(1.0) / nwh;\n        wn4r = cos(delta * nwh);\n        w[0] = 1;\n        w[1] = wn4r;\n        if (nwh == 4) {\n            w[2] = cos(delta * 2);\n            w[3] = sin(delta * 2);\n        } else if (nwh > 4) {\n            makeipt(nw, ip);\n            w[2] = 0.5 / cos(delta * 2);\n            w[3] = 0.5 / cos(delta * 6);\n            for (j = 4; j < nwh; j += 4) {\n                w[j] = cos(delta * j);\n                w[j + 1] = sin(delta * j);\n                w[j + 2] = cos(3 * delta * j);\n                w[j + 3] = -sin(3 * delta * j);\n            }\n        }\n        nw0 = 0;\n        while (nwh > 2) {\n            nw1 = nw0 + nwh;\n            nwh >>= 1;\n            w[nw1] = 1;\n            w[nw1 + 1] = wn4r;\n            if (nwh == 4) {\n                wk1r = w[nw0 + 4];\n                wk1i = w[nw0 + 5];\n                w[nw1 + 2] = wk1r;\n                w[nw1 + 3] = wk1i;\n            } else if (nwh > 4) {\n                wk1r = w[nw0 + 4];\n                wk3r = w[nw0 + 6];\n                w[nw1 + 2] = 0.5 / wk1r;\n                w[nw1 + 3] = 0.5 / wk3r;\n                for (j = 4; j < nwh; j += 4) {\n                    wk1r = w[nw0 + 2 * j];\n                    wk1i = w[nw0 + 2 * j + 1];\n                    wk3r = w[nw0 + 2 * j + 2];\n                    wk3i = w[nw0 + 2 * j + 3];\n                    w[nw1 + j] = wk1r;\n                    w[nw1 + j + 1] = wk1i;\n                    w[nw1 + j + 2] = wk3r;\n                    w[nw1 + j + 3] = wk3i;\n                }\n            }\n            nw0 = nw1;\n        }\n    }\n}\n\n\nvoid makeipt(int nw, int *ip) {\n    int j, l, m, m2, p, q;\n\n    ip[2] = 0;\n    ip[3] = 16;\n    m = 2;\n    for (l = nw; l > 32; l >>= 2) {\n        m2 = m << 1;\n        q = m2 << 3;\n        for (j = m; j < m2; j++) {\n            p = ip[j] << 2;\n            ip[m + j] = p;\n            ip[m2 + j] = p + q;\n        }\n        m = m2;\n    }\n}\n\n\nvoid makect(int nc, int *ip, double *c) {\n    int j, nch;\n    double delta;\n\n    ip[1] = nc;\n    if (nc > 1) {\n        nch = nc >> 1;\n        delta = atan(1.0) / nch;\n        c[0] = cos(delta * nch);\n        c[nch] = 0.5 * c[0];\n        for (j = 1; j < nch; j++) {\n            c[j] = 0.5 * cos(delta * j);\n            c[nc - j] = 0.5 * sin(delta * j);\n        }\n    }\n}\n\n\n/* -------- child routines -------- */\n\n\n#ifdef USE_CDFT_PTHREADS\n#define USE_CDFT_THREADS\n#ifndef CDFT_THREADS_BEGIN_N\n#define CDFT_THREADS_BEGIN_N 8192\n#endif\n#ifndef CDFT_4THREADS_BEGIN_N\n#define CDFT_4THREADS_BEGIN_N 65536\n#endif\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#define cdft_thread_t pthread_t\n#define cdft_thread_create(thp, func, argp)                       \\\n    {                                                             \\\n        if (pthread_create(thp, NULL, func, (void *)argp) != 0) { \\\n            fprintf(stderr, \"cdft thread error\\n\");               \\\n            exit(1);                                              \\\n        }                                                         \\\n    }\n#define cdft_thread_wait(th)                        \\\n    {                                               \\\n        if (pthread_join(th, NULL) != 0) {          \\\n            fprintf(stderr, \"cdft thread error\\n\"); \\\n            exit(1);                                \\\n        }                                           \\\n    }\n#endif /* USE_CDFT_PTHREADS */\n\n\n#ifdef USE_CDFT_WINTHREADS\n#define USE_CDFT_THREADS\n#ifndef CDFT_THREADS_BEGIN_N\n#define CDFT_THREADS_BEGIN_N 32768\n#endif\n#ifndef CDFT_4THREADS_BEGIN_N\n#define CDFT_4THREADS_BEGIN_N 524288\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <windows.h>\n#define cdft_thread_t HANDLE\n#define cdft_thread_create(thp, func, argp)                                 \\\n    {                                                                       \\\n        DWORD thid;                                                         \\\n        *(thp) = CreateThread(                                              \\\n            NULL, 0, (LPTHREAD_START_ROUTINE)func, (LPVOID)argp, 0, &thid); \\\n        if (*(thp) == 0) {                                                  \\\n            fprintf(stderr, \"cdft thread error\\n\");                         \\\n            exit(1);                                                        \\\n        }                                                                   \\\n    }\n#define cdft_thread_wait(th)               \\\n    {                                      \\\n        WaitForSingleObject(th, INFINITE); \\\n        CloseHandle(th);                   \\\n    }\n#endif /* USE_CDFT_WINTHREADS */\n\n\nvoid cftfsub(int n, double *a, int *ip, int nw, double *w) {\n    void bitrv2(int n, int *ip, double *a);\n    void bitrv216(double *a);\n    void bitrv208(double *a);\n    void cftf1st(int n, double *a, double *w);\n    void cftrec4(int n, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftfx41(int n, double *a, int nw, double *w);\n    void cftf161(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf040(double *a);\n    void cftx020(double *a);\n#ifdef USE_CDFT_THREADS\n    void cftrec4_th(int n, double *a, int nw, double *w);\n#endif /* USE_CDFT_THREADS */\n\n    if (n > 8) {\n        if (n > 32) {\n            cftf1st(n, a, &w[nw - (n >> 2)]);\n#ifdef USE_CDFT_THREADS\n            if (n > CDFT_THREADS_BEGIN_N) {\n                cftrec4_th(n, a, nw, w);\n            } else\n#endif /* USE_CDFT_THREADS */\n                if (n > 512) {\n                    cftrec4(n, a, nw, w);\n                } else if (n > 128) {\n                    cftleaf(n, 1, a, nw, w);\n                } else {\n                    cftfx41(n, a, nw, w);\n                }\n            bitrv2(n, ip, a);\n        } else if (n == 32) {\n            cftf161(a, &w[nw - 8]);\n            bitrv216(a);\n        } else {\n            cftf081(a, w);\n            bitrv208(a);\n        }\n    } else if (n == 8) {\n        cftf040(a);\n    } else if (n == 4) {\n        cftx020(a);\n    }\n}\n\n\nvoid cftbsub(int n, double *a, int *ip, int nw, double *w) {\n    void bitrv2conj(int n, int *ip, double *a);\n    void bitrv216neg(double *a);\n    void bitrv208neg(double *a);\n    void cftb1st(int n, double *a, double *w);\n    void cftrec4(int n, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftfx41(int n, double *a, int nw, double *w);\n    void cftf161(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftb040(double *a);\n    void cftx020(double *a);\n#ifdef USE_CDFT_THREADS\n    void cftrec4_th(int n, double *a, int nw, double *w);\n#endif /* USE_CDFT_THREADS */\n\n    if (n > 8) {\n        if (n > 32) {\n            cftb1st(n, a, &w[nw - (n >> 2)]);\n#ifdef USE_CDFT_THREADS\n            if (n > CDFT_THREADS_BEGIN_N) {\n                cftrec4_th(n, a, nw, w);\n            } else\n#endif /* USE_CDFT_THREADS */\n                if (n > 512) {\n                    cftrec4(n, a, nw, w);\n                } else if (n > 128) {\n                    cftleaf(n, 1, a, nw, w);\n                } else {\n                    cftfx41(n, a, nw, w);\n                }\n            bitrv2conj(n, ip, a);\n        } else if (n == 32) {\n            cftf161(a, &w[nw - 8]);\n            bitrv216neg(a);\n        } else {\n            cftf081(a, w);\n            bitrv208neg(a);\n        }\n    } else if (n == 8) {\n        cftb040(a);\n    } else if (n == 4) {\n        cftx020(a);\n    }\n}\n\n\nvoid bitrv2(int n, int *ip, double *a) {\n    int j, j1, k, k1, l, m, nh, nm;\n    double xr, xi, yr, yi;\n\n    m = 1;\n    for (l = n >> 2; l > 8; l >>= 2) {\n        m <<= 1;\n    }\n    nh = n >> 1;\n    nm = 4 * m;\n    if (l == 8) {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + 2 * ip[m + k];\n                k1 = 4 * k + 2 * ip[m + j];\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + 2 * ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 += 2 * nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 -= nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= 2;\n            k1 -= nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nh + 2;\n            k1 += nh + 2;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= nh - nm;\n            k1 += 2 * nm - 2;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n        }\n    } else {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + ip[m + k];\n                k1 = 4 * k + ip[m + j];\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = a[j1 + 1];\n                yr = a[k1];\n                yi = a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 += nm;\n            xr = a[j1];\n            xi = a[j1 + 1];\n            yr = a[k1];\n            yi = a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n        }\n    }\n}\n\n\nvoid bitrv2conj(int n, int *ip, double *a) {\n    int j, j1, k, k1, l, m, nh, nm;\n    double xr, xi, yr, yi;\n\n    m = 1;\n    for (l = n >> 2; l > 8; l >>= 2) {\n        m <<= 1;\n    }\n    nh = n >> 1;\n    nm = 4 * m;\n    if (l == 8) {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + 2 * ip[m + k];\n                k1 = 4 * k + 2 * ip[m + j];\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= 2 * nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + 2 * ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n            j1 += nm;\n            k1 += 2 * nm;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nm;\n            k1 -= nm;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= 2;\n            k1 -= nh;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 += nh + 2;\n            k1 += nh + 2;\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            j1 -= nh - nm;\n            k1 += 2 * nm - 2;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n        }\n    } else {\n        for (k = 0; k < m; k++) {\n            for (j = 0; j < k; j++) {\n                j1 = 4 * j + ip[m + k];\n                k1 = 4 * k + ip[m + j];\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nh;\n                k1 += 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += 2;\n                k1 += nh;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 += nm;\n                k1 += nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nh;\n                k1 -= 2;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n                j1 -= nm;\n                k1 -= nm;\n                xr = a[j1];\n                xi = -a[j1 + 1];\n                yr = a[k1];\n                yi = -a[k1 + 1];\n                a[j1] = yr;\n                a[j1 + 1] = yi;\n                a[k1] = xr;\n                a[k1 + 1] = xi;\n            }\n            k1 = 4 * k + ip[m + k];\n            j1 = k1 + 2;\n            k1 += nh;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n            j1 += nm;\n            k1 += nm;\n            a[j1 - 1] = -a[j1 - 1];\n            xr = a[j1];\n            xi = -a[j1 + 1];\n            yr = a[k1];\n            yi = -a[k1 + 1];\n            a[j1] = yr;\n            a[j1 + 1] = yi;\n            a[k1] = xr;\n            a[k1 + 1] = xi;\n            a[k1 + 3] = -a[k1 + 3];\n        }\n    }\n}\n\n\nvoid bitrv216(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i,\n        x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x7r = a[14];\n    x7i = a[15];\n    x8r = a[16];\n    x8i = a[17];\n    x10r = a[20];\n    x10i = a[21];\n    x11r = a[22];\n    x11i = a[23];\n    x12r = a[24];\n    x12i = a[25];\n    x13r = a[26];\n    x13i = a[27];\n    x14r = a[28];\n    x14i = a[29];\n    a[2] = x8r;\n    a[3] = x8i;\n    a[4] = x4r;\n    a[5] = x4i;\n    a[6] = x12r;\n    a[7] = x12i;\n    a[8] = x2r;\n    a[9] = x2i;\n    a[10] = x10r;\n    a[11] = x10i;\n    a[14] = x14r;\n    a[15] = x14i;\n    a[16] = x1r;\n    a[17] = x1i;\n    a[20] = x5r;\n    a[21] = x5i;\n    a[22] = x13r;\n    a[23] = x13i;\n    a[24] = x3r;\n    a[25] = x3i;\n    a[26] = x11r;\n    a[27] = x11i;\n    a[28] = x7r;\n    a[29] = x7i;\n}\n\n\nvoid bitrv216neg(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i,\n        x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i,\n        x14r, x14i, x15r, x15i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x6r = a[12];\n    x6i = a[13];\n    x7r = a[14];\n    x7i = a[15];\n    x8r = a[16];\n    x8i = a[17];\n    x9r = a[18];\n    x9i = a[19];\n    x10r = a[20];\n    x10i = a[21];\n    x11r = a[22];\n    x11i = a[23];\n    x12r = a[24];\n    x12i = a[25];\n    x13r = a[26];\n    x13i = a[27];\n    x14r = a[28];\n    x14i = a[29];\n    x15r = a[30];\n    x15i = a[31];\n    a[2] = x15r;\n    a[3] = x15i;\n    a[4] = x7r;\n    a[5] = x7i;\n    a[6] = x11r;\n    a[7] = x11i;\n    a[8] = x3r;\n    a[9] = x3i;\n    a[10] = x13r;\n    a[11] = x13i;\n    a[12] = x5r;\n    a[13] = x5i;\n    a[14] = x9r;\n    a[15] = x9i;\n    a[16] = x1r;\n    a[17] = x1i;\n    a[18] = x14r;\n    a[19] = x14i;\n    a[20] = x6r;\n    a[21] = x6i;\n    a[22] = x10r;\n    a[23] = x10i;\n    a[24] = x2r;\n    a[25] = x2i;\n    a[26] = x12r;\n    a[27] = x12i;\n    a[28] = x4r;\n    a[29] = x4i;\n    a[30] = x8r;\n    a[31] = x8i;\n}\n\n\nvoid bitrv208(double *a) {\n    double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x6r = a[12];\n    x6i = a[13];\n    a[2] = x4r;\n    a[3] = x4i;\n    a[6] = x6r;\n    a[7] = x6i;\n    a[8] = x1r;\n    a[9] = x1i;\n    a[12] = x3r;\n    a[13] = x3i;\n}\n\n\nvoid bitrv208neg(double *a) {\n    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;\n\n    x1r = a[2];\n    x1i = a[3];\n    x2r = a[4];\n    x2i = a[5];\n    x3r = a[6];\n    x3i = a[7];\n    x4r = a[8];\n    x4i = a[9];\n    x5r = a[10];\n    x5i = a[11];\n    x6r = a[12];\n    x6i = a[13];\n    x7r = a[14];\n    x7i = a[15];\n    a[2] = x7r;\n    a[3] = x7i;\n    a[4] = x3r;\n    a[5] = x3i;\n    a[6] = x5r;\n    a[7] = x5i;\n    a[8] = x1r;\n    a[9] = x1i;\n    a[10] = x6r;\n    a[11] = x6i;\n    a[12] = x2r;\n    a[13] = x2i;\n    a[14] = x4r;\n    a[15] = x4i;\n}\n\n\nvoid cftf1st(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = a[1] + a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = a[1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    a[j2] = x1r - x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r + x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    csc1 = w[2];\n    csc3 = w[3];\n    wd1r = 1;\n    wd1i = 0;\n    wd3r = 1;\n    wd3i = 0;\n    k = 0;\n    for (j = 2; j < mh - 2; j += 4) {\n        k += 4;\n        wk1r = csc1 * (wd1r + w[k]);\n        wk1i = csc1 * (wd1i + w[k + 1]);\n        wk3r = csc3 * (wd3r + w[k + 2]);\n        wk3i = csc3 * (wd3i + w[k + 3]);\n        wd1r = w[k];\n        wd1i = w[k + 1];\n        wd3r = w[k + 2];\n        wd3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = a[j + 1] + a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = a[j + 1] - a[j2 + 1];\n        y0r = a[j + 2] + a[j2 + 2];\n        y0i = a[j + 3] + a[j2 + 3];\n        y1r = a[j + 2] - a[j2 + 2];\n        y1i = a[j + 3] - a[j2 + 3];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 + 2] + a[j3 + 2];\n        y2i = a[j1 + 3] + a[j3 + 3];\n        y3r = a[j1 + 2] - a[j3 + 2];\n        y3i = a[j1 + 3] - a[j3 + 3];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i + x2i;\n        a[j + 2] = y0r + y2r;\n        a[j + 3] = y0i + y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        a[j1 + 2] = y0r - y2r;\n        a[j1 + 3] = y0i - y2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i + y3r;\n        a[j2 + 2] = wd1r * x0r - wd1i * x0i;\n        a[j2 + 3] = wd1r * x0i + wd1i * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i - y3r;\n        a[j3 + 2] = wd3r * x0r + wd3i * x0i;\n        a[j3 + 3] = wd3r * x0i - wd3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = a[j0 + 1] + a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = a[j0 + 1] - a[j2 + 1];\n        y0r = a[j0 - 2] + a[j2 - 2];\n        y0i = a[j0 - 1] + a[j2 - 1];\n        y1r = a[j0 - 2] - a[j2 - 2];\n        y1i = a[j0 - 1] - a[j2 - 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 - 2] + a[j3 - 2];\n        y2i = a[j1 - 1] + a[j3 - 1];\n        y3r = a[j1 - 2] - a[j3 - 2];\n        y3i = a[j1 - 1] - a[j3 - 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i + x2i;\n        a[j0 - 2] = y0r + y2r;\n        a[j0 - 1] = y0i + y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        a[j1 - 2] = y0r - y2r;\n        a[j1 - 1] = y0i - y2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i + y3r;\n        a[j2 - 2] = wd1i * x0r - wd1r * x0i;\n        a[j2 - 1] = wd1i * x0i + wd1r * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i - y3r;\n        a[j3 - 2] = wd3i * x0r + wd3r * x0i;\n        a[j3 - 1] = wd3i * x0i - wd3r * x0r;\n    }\n    wk1r = csc1 * (wd1r + wn4r);\n    wk1i = csc1 * (wd1i + wn4r);\n    wk3r = csc3 * (wd3r - wn4r);\n    wk3i = csc3 * (wd3i - wn4r);\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0 - 2] + a[j2 - 2];\n    x0i = a[j0 - 1] + a[j2 - 1];\n    x1r = a[j0 - 2] - a[j2 - 2];\n    x1i = a[j0 - 1] - a[j2 - 1];\n    x2r = a[j1 - 2] + a[j3 - 2];\n    x2i = a[j1 - 1] + a[j3 - 1];\n    x3r = a[j1 - 2] - a[j3 - 2];\n    x3i = a[j1 - 1] - a[j3 - 1];\n    a[j0 - 2] = x0r + x2r;\n    a[j0 - 1] = x0i + x2i;\n    a[j1 - 2] = x0r - x2r;\n    a[j1 - 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2 - 2] = wk1r * x0r - wk1i * x0i;\n    a[j2 - 1] = wk1r * x0i + wk1i * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3 - 2] = wk3r * x0r + wk3i * x0i;\n    a[j3 - 1] = wk3r * x0i - wk3i * x0r;\n    x0r = a[j0] + a[j2];\n    x0i = a[j0 + 1] + a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = a[j0 + 1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n    x0r = a[j0 + 2] + a[j2 + 2];\n    x0i = a[j0 + 3] + a[j2 + 3];\n    x1r = a[j0 + 2] - a[j2 + 2];\n    x1i = a[j0 + 3] - a[j2 + 3];\n    x2r = a[j1 + 2] + a[j3 + 2];\n    x2i = a[j1 + 3] + a[j3 + 3];\n    x3r = a[j1 + 2] - a[j3 + 2];\n    x3i = a[j1 + 3] - a[j3 + 3];\n    a[j0 + 2] = x0r + x2r;\n    a[j0 + 3] = x0i + x2i;\n    a[j1 + 2] = x0r - x2r;\n    a[j1 + 3] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2 + 2] = wk1i * x0r - wk1r * x0i;\n    a[j2 + 3] = wk1i * x0i + wk1r * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3 + 2] = wk3i * x0r + wk3r * x0i;\n    a[j3 + 3] = wk3i * x0i - wk3r * x0r;\n}\n\n\nvoid cftb1st(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = -a[1] - a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = -a[1] + a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i - x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i + x2i;\n    a[j2] = x1r + x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r - x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    csc1 = w[2];\n    csc3 = w[3];\n    wd1r = 1;\n    wd1i = 0;\n    wd3r = 1;\n    wd3i = 0;\n    k = 0;\n    for (j = 2; j < mh - 2; j += 4) {\n        k += 4;\n        wk1r = csc1 * (wd1r + w[k]);\n        wk1i = csc1 * (wd1i + w[k + 1]);\n        wk3r = csc3 * (wd3r + w[k + 2]);\n        wk3i = csc3 * (wd3i + w[k + 3]);\n        wd1r = w[k];\n        wd1i = w[k + 1];\n        wd3r = w[k + 2];\n        wd3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = -a[j + 1] - a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = -a[j + 1] + a[j2 + 1];\n        y0r = a[j + 2] + a[j2 + 2];\n        y0i = -a[j + 3] - a[j2 + 3];\n        y1r = a[j + 2] - a[j2 + 2];\n        y1i = -a[j + 3] + a[j2 + 3];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 + 2] + a[j3 + 2];\n        y2i = a[j1 + 3] + a[j3 + 3];\n        y3r = a[j1 + 2] - a[j3 + 2];\n        y3i = a[j1 + 3] - a[j3 + 3];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i - x2i;\n        a[j + 2] = y0r + y2r;\n        a[j + 3] = y0i - y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i + x2i;\n        a[j1 + 2] = y0r - y2r;\n        a[j1 + 3] = y0i + y2i;\n        x0r = x1r + x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i + y3r;\n        a[j2 + 2] = wd1r * x0r - wd1i * x0i;\n        a[j2 + 3] = wd1r * x0i + wd1i * x0r;\n        x0r = x1r - x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i - y3r;\n        a[j3 + 2] = wd3r * x0r + wd3i * x0i;\n        a[j3 + 3] = wd3r * x0i - wd3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = -a[j0 + 1] - a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = -a[j0 + 1] + a[j2 + 1];\n        y0r = a[j0 - 2] + a[j2 - 2];\n        y0i = -a[j0 - 1] - a[j2 - 1];\n        y1r = a[j0 - 2] - a[j2 - 2];\n        y1i = -a[j0 - 1] + a[j2 - 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        y2r = a[j1 - 2] + a[j3 - 2];\n        y2i = a[j1 - 1] + a[j3 - 1];\n        y3r = a[j1 - 2] - a[j3 - 2];\n        y3i = a[j1 - 1] - a[j3 - 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i - x2i;\n        a[j0 - 2] = y0r + y2r;\n        a[j0 - 1] = y0i - y2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i + x2i;\n        a[j1 - 2] = y0r - y2r;\n        a[j1 - 1] = y0i + y2i;\n        x0r = x1r + x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = y1r + y3i;\n        x0i = y1i + y3r;\n        a[j2 - 2] = wd1i * x0r - wd1r * x0i;\n        a[j2 - 1] = wd1i * x0i + wd1r * x0r;\n        x0r = x1r - x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n        x0r = y1r - y3i;\n        x0i = y1i - y3r;\n        a[j3 - 2] = wd3i * x0r + wd3r * x0i;\n        a[j3 - 1] = wd3i * x0i - wd3r * x0r;\n    }\n    wk1r = csc1 * (wd1r + wn4r);\n    wk1i = csc1 * (wd1i + wn4r);\n    wk3r = csc3 * (wd3r - wn4r);\n    wk3i = csc3 * (wd3i - wn4r);\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0 - 2] + a[j2 - 2];\n    x0i = -a[j0 - 1] - a[j2 - 1];\n    x1r = a[j0 - 2] - a[j2 - 2];\n    x1i = -a[j0 - 1] + a[j2 - 1];\n    x2r = a[j1 - 2] + a[j3 - 2];\n    x2i = a[j1 - 1] + a[j3 - 1];\n    x3r = a[j1 - 2] - a[j3 - 2];\n    x3i = a[j1 - 1] - a[j3 - 1];\n    a[j0 - 2] = x0r + x2r;\n    a[j0 - 1] = x0i - x2i;\n    a[j1 - 2] = x0r - x2r;\n    a[j1 - 1] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2 - 2] = wk1r * x0r - wk1i * x0i;\n    a[j2 - 1] = wk1r * x0i + wk1i * x0r;\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3 - 2] = wk3r * x0r + wk3i * x0i;\n    a[j3 - 1] = wk3r * x0i - wk3i * x0r;\n    x0r = a[j0] + a[j2];\n    x0i = -a[j0 + 1] - a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = -a[j0 + 1] + a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i - x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n    x0r = a[j0 + 2] + a[j2 + 2];\n    x0i = -a[j0 + 3] - a[j2 + 3];\n    x1r = a[j0 + 2] - a[j2 + 2];\n    x1i = -a[j0 + 3] + a[j2 + 3];\n    x2r = a[j1 + 2] + a[j3 + 2];\n    x2i = a[j1 + 3] + a[j3 + 3];\n    x3r = a[j1 + 2] - a[j3 + 2];\n    x3i = a[j1 + 3] - a[j3 + 3];\n    a[j0 + 2] = x0r + x2r;\n    a[j0 + 3] = x0i - x2i;\n    a[j1 + 2] = x0r - x2r;\n    a[j1 + 3] = x0i + x2i;\n    x0r = x1r + x3i;\n    x0i = x1i + x3r;\n    a[j2 + 2] = wk1i * x0r - wk1r * x0i;\n    a[j2 + 3] = wk1i * x0i + wk1r * x0r;\n    x0r = x1r - x3i;\n    x0i = x1i - x3r;\n    a[j3 + 2] = wk3i * x0r + wk3r * x0i;\n    a[j3 + 3] = wk3i * x0i - wk3r * x0r;\n}\n\n\n#ifdef USE_CDFT_THREADS\nstruct cdft_arg_st {\n    int n0;\n    int n;\n    double *a;\n    int nw;\n    double *w;\n};\ntypedef struct cdft_arg_st cdft_arg_t;\n\n\nvoid cftrec4_th(int n, double *a, int nw, double *w) {\n    void *cftrec1_th(void *p);\n    void *cftrec2_th(void *p);\n    int i, idiv4, m, nthread;\n    cdft_thread_t th[4];\n    cdft_arg_t ag[4];\n\n    nthread = 2;\n    idiv4 = 0;\n    m = n >> 1;\n    if (n > CDFT_4THREADS_BEGIN_N) {\n        nthread = 4;\n        idiv4 = 1;\n        m >>= 1;\n    }\n    for (i = 0; i < nthread; i++) {\n        ag[i].n0 = n;\n        ag[i].n = m;\n        ag[i].a = &a[i * m];\n        ag[i].nw = nw;\n        ag[i].w = w;\n        if (i != idiv4) {\n            cdft_thread_create(&th[i], cftrec1_th, &ag[i]);\n        } else {\n            cdft_thread_create(&th[i], cftrec2_th, &ag[i]);\n        }\n    }\n    for (i = 0; i < nthread; i++) {\n        cdft_thread_wait(th[i]);\n    }\n}\n\n\nvoid *cftrec1_th(void *p) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl1(int n, double *a, double *w);\n    int isplt, j, k, m, n, n0, nw;\n    double *a, *w;\n\n    n0 = ((cdft_arg_t *)p)->n0;\n    n = ((cdft_arg_t *)p)->n;\n    a = ((cdft_arg_t *)p)->a;\n    nw = ((cdft_arg_t *)p)->nw;\n    w = ((cdft_arg_t *)p)->w;\n    m = n0;\n    while (m > 512) {\n        m >>= 2;\n        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);\n    }\n    cftleaf(m, 1, &a[n - m], nw, w);\n    k = 0;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n    return (void *)0;\n}\n\n\nvoid *cftrec2_th(void *p) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    int isplt, j, k, m, n, n0, nw;\n    double *a, *w;\n\n    n0 = ((cdft_arg_t *)p)->n0;\n    n = ((cdft_arg_t *)p)->n;\n    a = ((cdft_arg_t *)p)->a;\n    nw = ((cdft_arg_t *)p)->nw;\n    w = ((cdft_arg_t *)p)->w;\n    k = 1;\n    m = n0;\n    while (m > 512) {\n        m >>= 2;\n        k <<= 2;\n        cftmdl2(m, &a[n - m], &w[nw - m]);\n    }\n    cftleaf(m, 0, &a[n - m], nw, w);\n    k >>= 1;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n    return (void *)0;\n}\n#endif /* USE_CDFT_THREADS */\n\n\nvoid cftrec4(int n, double *a, int nw, double *w) {\n    int cfttree(int n, int j, int k, double *a, int nw, double *w);\n    void cftleaf(int n, int isplt, double *a, int nw, double *w);\n    void cftmdl1(int n, double *a, double *w);\n    int isplt, j, k, m;\n\n    m = n;\n    while (m > 512) {\n        m >>= 2;\n        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);\n    }\n    cftleaf(m, 1, &a[n - m], nw, w);\n    k = 0;\n    for (j = n - m; j > 0; j -= m) {\n        k++;\n        isplt = cfttree(m, j, k, a, nw, w);\n        cftleaf(m, isplt, &a[j - m], nw, w);\n    }\n}\n\n\nint cfttree(int n, int j, int k, double *a, int nw, double *w) {\n    void cftmdl1(int n, double *a, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    int i, isplt, m;\n\n    if ((k & 3) != 0) {\n        isplt = k & 1;\n        if (isplt != 0) {\n            cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]);\n        } else {\n            cftmdl2(n, &a[j - n], &w[nw - n]);\n        }\n    } else {\n        m = n;\n        for (i = k; (i & 3) == 0; i >>= 2) {\n            m <<= 2;\n        }\n        isplt = i & 1;\n        if (isplt != 0) {\n            while (m > 128) {\n                cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]);\n                m >>= 2;\n            }\n        } else {\n            while (m > 128) {\n                cftmdl2(m, &a[j - m], &w[nw - m]);\n                m >>= 2;\n            }\n        }\n    }\n    return isplt;\n}\n\n\nvoid cftleaf(int n, int isplt, double *a, int nw, double *w) {\n    void cftmdl1(int n, double *a, double *w);\n    void cftmdl2(int n, double *a, double *w);\n    void cftf161(double *a, double *w);\n    void cftf162(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf082(double *a, double *w);\n\n    if (n == 512) {\n        cftmdl1(128, a, &w[nw - 64]);\n        cftf161(a, &w[nw - 8]);\n        cftf162(&a[32], &w[nw - 32]);\n        cftf161(&a[64], &w[nw - 8]);\n        cftf161(&a[96], &w[nw - 8]);\n        cftmdl2(128, &a[128], &w[nw - 128]);\n        cftf161(&a[128], &w[nw - 8]);\n        cftf162(&a[160], &w[nw - 32]);\n        cftf161(&a[192], &w[nw - 8]);\n        cftf162(&a[224], &w[nw - 32]);\n        cftmdl1(128, &a[256], &w[nw - 64]);\n        cftf161(&a[256], &w[nw - 8]);\n        cftf162(&a[288], &w[nw - 32]);\n        cftf161(&a[320], &w[nw - 8]);\n        cftf161(&a[352], &w[nw - 8]);\n        if (isplt != 0) {\n            cftmdl1(128, &a[384], &w[nw - 64]);\n            cftf161(&a[480], &w[nw - 8]);\n        } else {\n            cftmdl2(128, &a[384], &w[nw - 128]);\n            cftf162(&a[480], &w[nw - 32]);\n        }\n        cftf161(&a[384], &w[nw - 8]);\n        cftf162(&a[416], &w[nw - 32]);\n        cftf161(&a[448], &w[nw - 8]);\n    } else {\n        cftmdl1(64, a, &w[nw - 32]);\n        cftf081(a, &w[nw - 8]);\n        cftf082(&a[16], &w[nw - 8]);\n        cftf081(&a[32], &w[nw - 8]);\n        cftf081(&a[48], &w[nw - 8]);\n        cftmdl2(64, &a[64], &w[nw - 64]);\n        cftf081(&a[64], &w[nw - 8]);\n        cftf082(&a[80], &w[nw - 8]);\n        cftf081(&a[96], &w[nw - 8]);\n        cftf082(&a[112], &w[nw - 8]);\n        cftmdl1(64, &a[128], &w[nw - 32]);\n        cftf081(&a[128], &w[nw - 8]);\n        cftf082(&a[144], &w[nw - 8]);\n        cftf081(&a[160], &w[nw - 8]);\n        cftf081(&a[176], &w[nw - 8]);\n        if (isplt != 0) {\n            cftmdl1(64, &a[192], &w[nw - 32]);\n            cftf081(&a[240], &w[nw - 8]);\n        } else {\n            cftmdl2(64, &a[192], &w[nw - 64]);\n            cftf082(&a[240], &w[nw - 8]);\n        }\n        cftf081(&a[192], &w[nw - 8]);\n        cftf082(&a[208], &w[nw - 8]);\n        cftf081(&a[224], &w[nw - 8]);\n    }\n}\n\n\nvoid cftmdl1(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, m, mh;\n    double wn4r, wk1r, wk1i, wk3r, wk3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] + a[j2];\n    x0i = a[1] + a[j2 + 1];\n    x1r = a[0] - a[j2];\n    x1i = a[1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    a[j2] = x1r - x3i;\n    a[j2 + 1] = x1i + x3r;\n    a[j3] = x1r + x3i;\n    a[j3 + 1] = x1i - x3r;\n    wn4r = w[1];\n    k = 0;\n    for (j = 2; j < mh; j += 2) {\n        k += 4;\n        wk1r = w[k];\n        wk1i = w[k + 1];\n        wk3r = w[k + 2];\n        wk3i = w[k + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] + a[j2];\n        x0i = a[j + 1] + a[j2 + 1];\n        x1r = a[j] - a[j2];\n        x1i = a[j + 1] - a[j2 + 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        a[j] = x0r + x2r;\n        a[j + 1] = x0i + x2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1r * x0r - wk1i * x0i;\n        a[j2 + 1] = wk1r * x0i + wk1i * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3r * x0r + wk3i * x0i;\n        a[j3 + 1] = wk3r * x0i - wk3i * x0r;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] + a[j2];\n        x0i = a[j0 + 1] + a[j2 + 1];\n        x1r = a[j0] - a[j2];\n        x1i = a[j0 + 1] - a[j2 + 1];\n        x2r = a[j1] + a[j3];\n        x2i = a[j1 + 1] + a[j3 + 1];\n        x3r = a[j1] - a[j3];\n        x3i = a[j1 + 1] - a[j3 + 1];\n        a[j0] = x0r + x2r;\n        a[j0 + 1] = x0i + x2i;\n        a[j1] = x0r - x2r;\n        a[j1 + 1] = x0i - x2i;\n        x0r = x1r - x3i;\n        x0i = x1i + x3r;\n        a[j2] = wk1i * x0r - wk1r * x0i;\n        a[j2 + 1] = wk1i * x0i + wk1r * x0r;\n        x0r = x1r + x3i;\n        x0i = x1i - x3r;\n        a[j3] = wk3i * x0r + wk3r * x0i;\n        a[j3 + 1] = wk3i * x0i - wk3r * x0r;\n    }\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0] + a[j2];\n    x0i = a[j0 + 1] + a[j2 + 1];\n    x1r = a[j0] - a[j2];\n    x1i = a[j0 + 1] - a[j2 + 1];\n    x2r = a[j1] + a[j3];\n    x2i = a[j1 + 1] + a[j3 + 1];\n    x3r = a[j1] - a[j3];\n    x3i = a[j1 + 1] - a[j3 + 1];\n    a[j0] = x0r + x2r;\n    a[j0 + 1] = x0i + x2i;\n    a[j1] = x0r - x2r;\n    a[j1 + 1] = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    a[j2] = wn4r * (x0r - x0i);\n    a[j2 + 1] = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    a[j3] = -wn4r * (x0r + x0i);\n    a[j3 + 1] = -wn4r * (x0i - x0r);\n}\n\n\nvoid cftmdl2(int n, double *a, double *w) {\n    int j, j0, j1, j2, j3, k, kr, m, mh;\n    double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i;\n\n    mh = n >> 3;\n    m = 2 * mh;\n    wn4r = w[1];\n    j1 = m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[0] - a[j2 + 1];\n    x0i = a[1] + a[j2];\n    x1r = a[0] + a[j2 + 1];\n    x1i = a[1] - a[j2];\n    x2r = a[j1] - a[j3 + 1];\n    x2i = a[j1 + 1] + a[j3];\n    x3r = a[j1] + a[j3 + 1];\n    x3i = a[j1 + 1] - a[j3];\n    y0r = wn4r * (x2r - x2i);\n    y0i = wn4r * (x2i + x2r);\n    a[0] = x0r + y0r;\n    a[1] = x0i + y0i;\n    a[j1] = x0r - y0r;\n    a[j1 + 1] = x0i - y0i;\n    y0r = wn4r * (x3r - x3i);\n    y0i = wn4r * (x3i + x3r);\n    a[j2] = x1r - y0i;\n    a[j2 + 1] = x1i + y0r;\n    a[j3] = x1r + y0i;\n    a[j3 + 1] = x1i - y0r;\n    k = 0;\n    kr = 2 * m;\n    for (j = 2; j < mh; j += 2) {\n        k += 4;\n        wk1r = w[k];\n        wk1i = w[k + 1];\n        wk3r = w[k + 2];\n        wk3i = w[k + 3];\n        kr -= 4;\n        wd1i = w[kr];\n        wd1r = w[kr + 1];\n        wd3i = w[kr + 2];\n        wd3r = w[kr + 3];\n        j1 = j + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j] - a[j2 + 1];\n        x0i = a[j + 1] + a[j2];\n        x1r = a[j] + a[j2 + 1];\n        x1i = a[j + 1] - a[j2];\n        x2r = a[j1] - a[j3 + 1];\n        x2i = a[j1 + 1] + a[j3];\n        x3r = a[j1] + a[j3 + 1];\n        x3i = a[j1 + 1] - a[j3];\n        y0r = wk1r * x0r - wk1i * x0i;\n        y0i = wk1r * x0i + wk1i * x0r;\n        y2r = wd1r * x2r - wd1i * x2i;\n        y2i = wd1r * x2i + wd1i * x2r;\n        a[j] = y0r + y2r;\n        a[j + 1] = y0i + y2i;\n        a[j1] = y0r - y2r;\n        a[j1 + 1] = y0i - y2i;\n        y0r = wk3r * x1r + wk3i * x1i;\n        y0i = wk3r * x1i - wk3i * x1r;\n        y2r = wd3r * x3r + wd3i * x3i;\n        y2i = wd3r * x3i - wd3i * x3r;\n        a[j2] = y0r + y2r;\n        a[j2 + 1] = y0i + y2i;\n        a[j3] = y0r - y2r;\n        a[j3 + 1] = y0i - y2i;\n        j0 = m - j;\n        j1 = j0 + m;\n        j2 = j1 + m;\n        j3 = j2 + m;\n        x0r = a[j0] - a[j2 + 1];\n        x0i = a[j0 + 1] + a[j2];\n        x1r = a[j0] + a[j2 + 1];\n        x1i = a[j0 + 1] - a[j2];\n        x2r = a[j1] - a[j3 + 1];\n        x2i = a[j1 + 1] + a[j3];\n        x3r = a[j1] + a[j3 + 1];\n        x3i = a[j1 + 1] - a[j3];\n        y0r = wd1i * x0r - wd1r * x0i;\n        y0i = wd1i * x0i + wd1r * x0r;\n        y2r = wk1i * x2r - wk1r * x2i;\n        y2i = wk1i * x2i + wk1r * x2r;\n        a[j0] = y0r + y2r;\n        a[j0 + 1] = y0i + y2i;\n        a[j1] = y0r - y2r;\n        a[j1 + 1] = y0i - y2i;\n        y0r = wd3i * x1r + wd3r * x1i;\n        y0i = wd3i * x1i - wd3r * x1r;\n        y2r = wk3i * x3r + wk3r * x3i;\n        y2i = wk3i * x3i - wk3r * x3r;\n        a[j2] = y0r + y2r;\n        a[j2 + 1] = y0i + y2i;\n        a[j3] = y0r - y2r;\n        a[j3 + 1] = y0i - y2i;\n    }\n    wk1r = w[m];\n    wk1i = w[m + 1];\n    j0 = mh;\n    j1 = j0 + m;\n    j2 = j1 + m;\n    j3 = j2 + m;\n    x0r = a[j0] - a[j2 + 1];\n    x0i = a[j0 + 1] + a[j2];\n    x1r = a[j0] + a[j2 + 1];\n    x1i = a[j0 + 1] - a[j2];\n    x2r = a[j1] - a[j3 + 1];\n    x2i = a[j1 + 1] + a[j3];\n    x3r = a[j1] + a[j3 + 1];\n    x3i = a[j1 + 1] - a[j3];\n    y0r = wk1r * x0r - wk1i * x0i;\n    y0i = wk1r * x0i + wk1i * x0r;\n    y2r = wk1i * x2r - wk1r * x2i;\n    y2i = wk1i * x2i + wk1r * x2r;\n    a[j0] = y0r + y2r;\n    a[j0 + 1] = y0i + y2i;\n    a[j1] = y0r - y2r;\n    a[j1 + 1] = y0i - y2i;\n    y0r = wk1i * x1r - wk1r * x1i;\n    y0i = wk1i * x1i + wk1r * x1r;\n    y2r = wk1r * x3r - wk1i * x3i;\n    y2i = wk1r * x3i + wk1i * x3r;\n    a[j2] = y0r - y2r;\n    a[j2 + 1] = y0i - y2i;\n    a[j3] = y0r + y2r;\n    a[j3 + 1] = y0i + y2i;\n}\n\n\nvoid cftfx41(int n, double *a, int nw, double *w) {\n    void cftf161(double *a, double *w);\n    void cftf162(double *a, double *w);\n    void cftf081(double *a, double *w);\n    void cftf082(double *a, double *w);\n\n    if (n == 128) {\n        cftf161(a, &w[nw - 8]);\n        cftf162(&a[32], &w[nw - 32]);\n        cftf161(&a[64], &w[nw - 8]);\n        cftf161(&a[96], &w[nw - 8]);\n    } else {\n        cftf081(a, &w[nw - 8]);\n        cftf082(&a[16], &w[nw - 8]);\n        cftf081(&a[32], &w[nw - 8]);\n        cftf081(&a[48], &w[nw - 8]);\n    }\n}\n\n\nvoid cftf161(double *a, double *w) {\n    double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i,\n        y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,\n        y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i,\n        y14r, y14i, y15r, y15i;\n\n    wn4r = w[1];\n    wk1r = w[2];\n    wk1i = w[3];\n    x0r = a[0] + a[16];\n    x0i = a[1] + a[17];\n    x1r = a[0] - a[16];\n    x1i = a[1] - a[17];\n    x2r = a[8] + a[24];\n    x2i = a[9] + a[25];\n    x3r = a[8] - a[24];\n    x3i = a[9] - a[25];\n    y0r = x0r + x2r;\n    y0i = x0i + x2i;\n    y4r = x0r - x2r;\n    y4i = x0i - x2i;\n    y8r = x1r - x3i;\n    y8i = x1i + x3r;\n    y12r = x1r + x3i;\n    y12i = x1i - x3r;\n    x0r = a[2] + a[18];\n    x0i = a[3] + a[19];\n    x1r = a[2] - a[18];\n    x1i = a[3] - a[19];\n    x2r = a[10] + a[26];\n    x2i = a[11] + a[27];\n    x3r = a[10] - a[26];\n    x3i = a[11] - a[27];\n    y1r = x0r + x2r;\n    y1i = x0i + x2i;\n    y5r = x0r - x2r;\n    y5i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y9r = wk1r * x0r - wk1i * x0i;\n    y9i = wk1r * x0i + wk1i * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y13r = wk1i * x0r - wk1r * x0i;\n    y13i = wk1i * x0i + wk1r * x0r;\n    x0r = a[4] + a[20];\n    x0i = a[5] + a[21];\n    x1r = a[4] - a[20];\n    x1i = a[5] - a[21];\n    x2r = a[12] + a[28];\n    x2i = a[13] + a[29];\n    x3r = a[12] - a[28];\n    x3i = a[13] - a[29];\n    y2r = x0r + x2r;\n    y2i = x0i + x2i;\n    y6r = x0r - x2r;\n    y6i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y10r = wn4r * (x0r - x0i);\n    y10i = wn4r * (x0i + x0r);\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y14r = wn4r * (x0r + x0i);\n    y14i = wn4r * (x0i - x0r);\n    x0r = a[6] + a[22];\n    x0i = a[7] + a[23];\n    x1r = a[6] - a[22];\n    x1i = a[7] - a[23];\n    x2r = a[14] + a[30];\n    x2i = a[15] + a[31];\n    x3r = a[14] - a[30];\n    x3i = a[15] - a[31];\n    y3r = x0r + x2r;\n    y3i = x0i + x2i;\n    y7r = x0r - x2r;\n    y7i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    y11r = wk1i * x0r - wk1r * x0i;\n    y11i = wk1i * x0i + wk1r * x0r;\n    x0r = x1r + x3i;\n    x0i = x1i - x3r;\n    y15r = wk1r * x0r - wk1i * x0i;\n    y15i = wk1r * x0i + wk1i * x0r;\n    x0r = y12r - y14r;\n    x0i = y12i - y14i;\n    x1r = y12r + y14r;\n    x1i = y12i + y14i;\n    x2r = y13r - y15r;\n    x2i = y13i - y15i;\n    x3r = y13r + y15r;\n    x3i = y13i + y15i;\n    a[24] = x0r + x2r;\n    a[25] = x0i + x2i;\n    a[26] = x0r - x2r;\n    a[27] = x0i - x2i;\n    a[28] = x1r - x3i;\n    a[29] = x1i + x3r;\n    a[30] = x1r + x3i;\n    a[31] = x1i - x3r;\n    x0r = y8r + y10r;\n    x0i = y8i + y10i;\n    x1r = y8r - y10r;\n    x1i = y8i - y10i;\n    x2r = y9r + y11r;\n    x2i = y9i + y11i;\n    x3r = y9r - y11r;\n    x3i = y9i - y11i;\n    a[16] = x0r + x2r;\n    a[17] = x0i + x2i;\n    a[18] = x0r - x2r;\n    a[19] = x0i - x2i;\n    a[20] = x1r - x3i;\n    a[21] = x1i + x3r;\n    a[22] = x1r + x3i;\n    a[23] = x1i - x3r;\n    x0r = y5r - y7i;\n    x0i = y5i + y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    x0r = y5r + y7i;\n    x0i = y5i - y7r;\n    x3r = wn4r * (x0r - x0i);\n    x3i = wn4r * (x0i + x0r);\n    x0r = y4r - y6i;\n    x0i = y4i + y6r;\n    x1r = y4r + y6i;\n    x1i = y4i - y6r;\n    a[8] = x0r + x2r;\n    a[9] = x0i + x2i;\n    a[10] = x0r - x2r;\n    a[11] = x0i - x2i;\n    a[12] = x1r - x3i;\n    a[13] = x1i + x3r;\n    a[14] = x1r + x3i;\n    a[15] = x1i - x3r;\n    x0r = y0r + y2r;\n    x0i = y0i + y2i;\n    x1r = y0r - y2r;\n    x1i = y0i - y2i;\n    x2r = y1r + y3r;\n    x2i = y1i + y3i;\n    x3r = y1r - y3r;\n    x3i = y1i - y3i;\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x0r - x2r;\n    a[3] = x0i - x2i;\n    a[4] = x1r - x3i;\n    a[5] = x1i + x3r;\n    a[6] = x1r + x3i;\n    a[7] = x1i - x3r;\n}\n\n\nvoid cftf162(double *a, double *w) {\n    double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r,\n        x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r,\n        y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i,\n        y13r, y13i, y14r, y14i, y15r, y15i;\n\n    wn4r = w[1];\n    wk1r = w[4];\n    wk1i = w[5];\n    wk3r = w[6];\n    wk3i = -w[7];\n    wk2r = w[8];\n    wk2i = w[9];\n    x1r = a[0] - a[17];\n    x1i = a[1] + a[16];\n    x0r = a[8] - a[25];\n    x0i = a[9] + a[24];\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    y0r = x1r + x2r;\n    y0i = x1i + x2i;\n    y4r = x1r - x2r;\n    y4i = x1i - x2i;\n    x1r = a[0] + a[17];\n    x1i = a[1] - a[16];\n    x0r = a[8] + a[25];\n    x0i = a[9] - a[24];\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    y8r = x1r - x2i;\n    y8i = x1i + x2r;\n    y12r = x1r + x2i;\n    y12i = x1i - x2r;\n    x0r = a[2] - a[19];\n    x0i = a[3] + a[18];\n    x1r = wk1r * x0r - wk1i * x0i;\n    x1i = wk1r * x0i + wk1i * x0r;\n    x0r = a[10] - a[27];\n    x0i = a[11] + a[26];\n    x2r = wk3i * x0r - wk3r * x0i;\n    x2i = wk3i * x0i + wk3r * x0r;\n    y1r = x1r + x2r;\n    y1i = x1i + x2i;\n    y5r = x1r - x2r;\n    y5i = x1i - x2i;\n    x0r = a[2] + a[19];\n    x0i = a[3] - a[18];\n    x1r = wk3r * x0r - wk3i * x0i;\n    x1i = wk3r * x0i + wk3i * x0r;\n    x0r = a[10] + a[27];\n    x0i = a[11] - a[26];\n    x2r = wk1r * x0r + wk1i * x0i;\n    x2i = wk1r * x0i - wk1i * x0r;\n    y9r = x1r - x2r;\n    y9i = x1i - x2i;\n    y13r = x1r + x2r;\n    y13i = x1i + x2i;\n    x0r = a[4] - a[21];\n    x0i = a[5] + a[20];\n    x1r = wk2r * x0r - wk2i * x0i;\n    x1i = wk2r * x0i + wk2i * x0r;\n    x0r = a[12] - a[29];\n    x0i = a[13] + a[28];\n    x2r = wk2i * x0r - wk2r * x0i;\n    x2i = wk2i * x0i + wk2r * x0r;\n    y2r = x1r + x2r;\n    y2i = x1i + x2i;\n    y6r = x1r - x2r;\n    y6i = x1i - x2i;\n    x0r = a[4] + a[21];\n    x0i = a[5] - a[20];\n    x1r = wk2i * x0r - wk2r * x0i;\n    x1i = wk2i * x0i + wk2r * x0r;\n    x0r = a[12] + a[29];\n    x0i = a[13] - a[28];\n    x2r = wk2r * x0r - wk2i * x0i;\n    x2i = wk2r * x0i + wk2i * x0r;\n    y10r = x1r - x2r;\n    y10i = x1i - x2i;\n    y14r = x1r + x2r;\n    y14i = x1i + x2i;\n    x0r = a[6] - a[23];\n    x0i = a[7] + a[22];\n    x1r = wk3r * x0r - wk3i * x0i;\n    x1i = wk3r * x0i + wk3i * x0r;\n    x0r = a[14] - a[31];\n    x0i = a[15] + a[30];\n    x2r = wk1i * x0r - wk1r * x0i;\n    x2i = wk1i * x0i + wk1r * x0r;\n    y3r = x1r + x2r;\n    y3i = x1i + x2i;\n    y7r = x1r - x2r;\n    y7i = x1i - x2i;\n    x0r = a[6] + a[23];\n    x0i = a[7] - a[22];\n    x1r = wk1i * x0r + wk1r * x0i;\n    x1i = wk1i * x0i - wk1r * x0r;\n    x0r = a[14] + a[31];\n    x0i = a[15] - a[30];\n    x2r = wk3i * x0r - wk3r * x0i;\n    x2i = wk3i * x0i + wk3r * x0r;\n    y11r = x1r + x2r;\n    y11i = x1i + x2i;\n    y15r = x1r - x2r;\n    y15i = x1i - x2i;\n    x1r = y0r + y2r;\n    x1i = y0i + y2i;\n    x2r = y1r + y3r;\n    x2i = y1i + y3i;\n    a[0] = x1r + x2r;\n    a[1] = x1i + x2i;\n    a[2] = x1r - x2r;\n    a[3] = x1i - x2i;\n    x1r = y0r - y2r;\n    x1i = y0i - y2i;\n    x2r = y1r - y3r;\n    x2i = y1i - y3i;\n    a[4] = x1r - x2i;\n    a[5] = x1i + x2r;\n    a[6] = x1r + x2i;\n    a[7] = x1i - x2r;\n    x1r = y4r - y6i;\n    x1i = y4i + y6r;\n    x0r = y5r - y7i;\n    x0i = y5i + y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[8] = x1r + x2r;\n    a[9] = x1i + x2i;\n    a[10] = x1r - x2r;\n    a[11] = x1i - x2i;\n    x1r = y4r + y6i;\n    x1i = y4i - y6r;\n    x0r = y5r + y7i;\n    x0i = y5i - y7r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[12] = x1r - x2i;\n    a[13] = x1i + x2r;\n    a[14] = x1r + x2i;\n    a[15] = x1i - x2r;\n    x1r = y8r + y10r;\n    x1i = y8i + y10i;\n    x2r = y9r - y11r;\n    x2i = y9i - y11i;\n    a[16] = x1r + x2r;\n    a[17] = x1i + x2i;\n    a[18] = x1r - x2r;\n    a[19] = x1i - x2i;\n    x1r = y8r - y10r;\n    x1i = y8i - y10i;\n    x2r = y9r + y11r;\n    x2i = y9i + y11i;\n    a[20] = x1r - x2i;\n    a[21] = x1i + x2r;\n    a[22] = x1r + x2i;\n    a[23] = x1i - x2r;\n    x1r = y12r - y14i;\n    x1i = y12i + y14r;\n    x0r = y13r + y15i;\n    x0i = y13i - y15r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[24] = x1r + x2r;\n    a[25] = x1i + x2i;\n    a[26] = x1r - x2r;\n    a[27] = x1i - x2i;\n    x1r = y12r + y14i;\n    x1i = y12i - y14r;\n    x0r = y13r - y15i;\n    x0i = y13i + y15r;\n    x2r = wn4r * (x0r - x0i);\n    x2i = wn4r * (x0i + x0r);\n    a[28] = x1r - x2i;\n    a[29] = x1i + x2r;\n    a[30] = x1r + x2i;\n    a[31] = x1i - x2r;\n}\n\n\nvoid cftf081(double *a, double *w) {\n    double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i,\n        y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;\n\n    wn4r = w[1];\n    x0r = a[0] + a[8];\n    x0i = a[1] + a[9];\n    x1r = a[0] - a[8];\n    x1i = a[1] - a[9];\n    x2r = a[4] + a[12];\n    x2i = a[5] + a[13];\n    x3r = a[4] - a[12];\n    x3i = a[5] - a[13];\n    y0r = x0r + x2r;\n    y0i = x0i + x2i;\n    y2r = x0r - x2r;\n    y2i = x0i - x2i;\n    y1r = x1r - x3i;\n    y1i = x1i + x3r;\n    y3r = x1r + x3i;\n    y3i = x1i - x3r;\n    x0r = a[2] + a[10];\n    x0i = a[3] + a[11];\n    x1r = a[2] - a[10];\n    x1i = a[3] - a[11];\n    x2r = a[6] + a[14];\n    x2i = a[7] + a[15];\n    x3r = a[6] - a[14];\n    x3i = a[7] - a[15];\n    y4r = x0r + x2r;\n    y4i = x0i + x2i;\n    y6r = x0r - x2r;\n    y6i = x0i - x2i;\n    x0r = x1r - x3i;\n    x0i = x1i + x3r;\n    x2r = x1r + x3i;\n    x2i = x1i - x3r;\n    y5r = wn4r * (x0r - x0i);\n    y5i = wn4r * (x0r + x0i);\n    y7r = wn4r * (x2r - x2i);\n    y7i = wn4r * (x2r + x2i);\n    a[8] = y1r + y5r;\n    a[9] = y1i + y5i;\n    a[10] = y1r - y5r;\n    a[11] = y1i - y5i;\n    a[12] = y3r - y7i;\n    a[13] = y3i + y7r;\n    a[14] = y3r + y7i;\n    a[15] = y3i - y7r;\n    a[0] = y0r + y4r;\n    a[1] = y0i + y4i;\n    a[2] = y0r - y4r;\n    a[3] = y0i - y4i;\n    a[4] = y2r - y6i;\n    a[5] = y2i + y6r;\n    a[6] = y2r + y6i;\n    a[7] = y2i - y6r;\n}\n\n\nvoid cftf082(double *a, double *w) {\n    double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i,\n        y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;\n\n    wn4r = w[1];\n    wk1r = w[2];\n    wk1i = w[3];\n    y0r = a[0] - a[9];\n    y0i = a[1] + a[8];\n    y1r = a[0] + a[9];\n    y1i = a[1] - a[8];\n    x0r = a[4] - a[13];\n    x0i = a[5] + a[12];\n    y2r = wn4r * (x0r - x0i);\n    y2i = wn4r * (x0i + x0r);\n    x0r = a[4] + a[13];\n    x0i = a[5] - a[12];\n    y3r = wn4r * (x0r - x0i);\n    y3i = wn4r * (x0i + x0r);\n    x0r = a[2] - a[11];\n    x0i = a[3] + a[10];\n    y4r = wk1r * x0r - wk1i * x0i;\n    y4i = wk1r * x0i + wk1i * x0r;\n    x0r = a[2] + a[11];\n    x0i = a[3] - a[10];\n    y5r = wk1i * x0r - wk1r * x0i;\n    y5i = wk1i * x0i + wk1r * x0r;\n    x0r = a[6] - a[15];\n    x0i = a[7] + a[14];\n    y6r = wk1i * x0r - wk1r * x0i;\n    y6i = wk1i * x0i + wk1r * x0r;\n    x0r = a[6] + a[15];\n    x0i = a[7] - a[14];\n    y7r = wk1r * x0r - wk1i * x0i;\n    y7i = wk1r * x0i + wk1i * x0r;\n    x0r = y0r + y2r;\n    x0i = y0i + y2i;\n    x1r = y4r + y6r;\n    x1i = y4i + y6i;\n    a[0] = x0r + x1r;\n    a[1] = x0i + x1i;\n    a[2] = x0r - x1r;\n    a[3] = x0i - x1i;\n    x0r = y0r - y2r;\n    x0i = y0i - y2i;\n    x1r = y4r - y6r;\n    x1i = y4i - y6i;\n    a[4] = x0r - x1i;\n    a[5] = x0i + x1r;\n    a[6] = x0r + x1i;\n    a[7] = x0i - x1r;\n    x0r = y1r - y3i;\n    x0i = y1i + y3r;\n    x1r = y5r - y7r;\n    x1i = y5i - y7i;\n    a[8] = x0r + x1r;\n    a[9] = x0i + x1i;\n    a[10] = x0r - x1r;\n    a[11] = x0i - x1i;\n    x0r = y1r + y3i;\n    x0i = y1i - y3r;\n    x1r = y5r + y7r;\n    x1i = y5i + y7i;\n    a[12] = x0r - x1i;\n    a[13] = x0i + x1r;\n    a[14] = x0r + x1i;\n    a[15] = x0i - x1r;\n}\n\n\nvoid cftf040(double *a) {\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    x0r = a[0] + a[4];\n    x0i = a[1] + a[5];\n    x1r = a[0] - a[4];\n    x1i = a[1] - a[5];\n    x2r = a[2] + a[6];\n    x2i = a[3] + a[7];\n    x3r = a[2] - a[6];\n    x3i = a[3] - a[7];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x1r - x3i;\n    a[3] = x1i + x3r;\n    a[4] = x0r - x2r;\n    a[5] = x0i - x2i;\n    a[6] = x1r + x3i;\n    a[7] = x1i - x3r;\n}\n\n\nvoid cftb040(double *a) {\n    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;\n\n    x0r = a[0] + a[4];\n    x0i = a[1] + a[5];\n    x1r = a[0] - a[4];\n    x1i = a[1] - a[5];\n    x2r = a[2] + a[6];\n    x2i = a[3] + a[7];\n    x3r = a[2] - a[6];\n    x3i = a[3] - a[7];\n    a[0] = x0r + x2r;\n    a[1] = x0i + x2i;\n    a[2] = x1r + x3i;\n    a[3] = x1i - x3r;\n    a[4] = x0r - x2r;\n    a[5] = x0i - x2i;\n    a[6] = x1r - x3i;\n    a[7] = x1i + x3r;\n}\n\n\nvoid cftx020(double *a) {\n    double x0r, x0i;\n\n    x0r = a[0] - a[2];\n    x0i = a[1] - a[3];\n    a[0] += a[2];\n    a[1] += a[3];\n    a[2] = x0r;\n    a[3] = x0i;\n}\n\n\nvoid rftfsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr, xi, yr, yi;\n\n    m = n >> 1;\n    ks = 2 * nc / m;\n    kk = 0;\n    for (j = 2; j < m; j += 2) {\n        k = n - j;\n        kk += ks;\n        wkr = 0.5 - c[nc - kk];\n        wki = c[kk];\n        xr = a[j] - a[k];\n        xi = a[j + 1] + a[k + 1];\n        yr = wkr * xr - wki * xi;\n        yi = wkr * xi + wki * xr;\n        a[j] -= yr;\n        a[j + 1] -= yi;\n        a[k] += yr;\n        a[k + 1] -= yi;\n    }\n}\n\n\nvoid rftbsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr, xi, yr, yi;\n\n    m = n >> 1;\n    ks = 2 * nc / m;\n    kk = 0;\n    for (j = 2; j < m; j += 2) {\n        k = n - j;\n        kk += ks;\n        wkr = 0.5 - c[nc - kk];\n        wki = c[kk];\n        xr = a[j] - a[k];\n        xi = a[j + 1] + a[k + 1];\n        yr = wkr * xr + wki * xi;\n        yi = wkr * xi - wki * xr;\n        a[j] -= yr;\n        a[j + 1] -= yi;\n        a[k] += yr;\n        a[k + 1] -= yi;\n    }\n}\n\n\nvoid dctsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr;\n\n    m = n >> 1;\n    ks = nc / n;\n    kk = 0;\n    for (j = 1; j < m; j++) {\n        k = n - j;\n        kk += ks;\n        wkr = c[kk] - c[nc - kk];\n        wki = c[kk] + c[nc - kk];\n        xr = wki * a[j] - wkr * a[k];\n        a[j] = wkr * a[j] + wki * a[k];\n        a[k] = xr;\n    }\n    a[m] *= c[0];\n}\n\n\nvoid dstsub(int n, double *a, int nc, double *c) {\n    int j, k, kk, ks, m;\n    double wkr, wki, xr;\n\n    m = n >> 1;\n    ks = nc / n;\n    kk = 0;\n    for (j = 1; j < m; j++) {\n        k = n - j;\n        kk += ks;\n        wkr = c[kk] - c[nc - kk];\n        wki = c[kk] + c[nc - kk];\n        xr = wki * a[k] - wkr * a[j];\n        a[k] = wkr * a[k] + wki * a[j];\n        a[j] = xr;\n    }\n    a[m] *= c[0];\n}\n"
  },
  {
    "path": "runtime/engine/common/frontend/frontend_itf.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"base/basic_types.h\"\n#include \"matrix/kaldi-vector.h\"\n\nnamespace ppspeech {\n\nclass FrontendInterface {\n  public:\n    // Feed inputs: features(2D saved in 1D) or waveforms(1D).\n    virtual void Accept(const std::vector<float>& inputs) = 0;\n\n    // Fetch processed data: features or waveforms.\n    // For features(2D saved in 1D), the Matrix is squashed into Vector,\n    //    the length of output = feature_row * feature_dim.\n    // For waveforms(1D), samples saved in vector.\n    virtual bool Read(std::vector<float>* outputs) = 0;\n\n    // Dim is the feature dim. For waveforms(1D), Dim is zero; else is specific,\n    // e.g 80 for fbank.\n    virtual size_t Dim() const = 0;\n\n    // End Flag for Streaming Data.\n    virtual void SetFinished() = 0;\n\n    // whether is end of Streaming Data.\n    virtual bool IsFinished() const = 0;\n\n    // Reset to start state.\n    virtual void Reset() = 0;\n};\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/frontend/linear_spectrogram.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/audio/linear_spectrogram.h\"\n\n#include \"kaldi/base/kaldi-math.h\"\n#include \"kaldi/feat/feature-common.h\"\n#include \"kaldi/feat/feature-functions.h\"\n#include \"kaldi/matrix/matrix-functions.h\"\n\nnamespace ppspeech {\n\nusing kaldi::BaseFloat;\nusing kaldi::int32;\nusing kaldi::Matrix;\nusing kaldi::SubVector;\nusing kaldi::Vector;\nusing kaldi::VectorBase;\nusing std::vector;\n\nLinearSpectrogramComputer::LinearSpectrogramComputer(const Options& opts)\n    : opts_(opts) {\n    kaldi::FeatureWindowFunction feature_window_function(opts.frame_opts);\n    int32 window_size = opts.frame_opts.WindowSize();\n    frame_length_ = window_size;\n    dim_ = window_size / 2 + 1;\n    BaseFloat hanning_window_energy = kaldi::VecVec(\n        feature_window_function.window, feature_window_function.window);\n    int32 sample_rate = opts.frame_opts.samp_freq;\n    scale_ = 2.0 / (hanning_window_energy * sample_rate);\n}\n\n// Compute spectrogram feat\nbool LinearSpectrogramComputer::Compute(Vector<BaseFloat>* window,\n                                        Vector<BaseFloat>* feat) {\n    window->Resize(frame_length_, kaldi::kCopyData);\n    RealFft(window, true);\n    kaldi::ComputePowerSpectrum(window);\n    SubVector<BaseFloat> power_spectrum(*window, 0, dim_);\n    power_spectrum.Scale(scale_);\n    power_spectrum(0) = power_spectrum(0) / 2;\n    power_spectrum(dim_ - 1) = power_spectrum(dim_ - 1) / 2;\n    power_spectrum.Add(1e-14);\n    power_spectrum.ApplyLog();\n    feat->CopyFromVec(power_spectrum);\n    return true;\n}\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/frontend/linear_spectrogram.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#pragma once\n\n#include \"base/common.h\"\n#include \"frontend/audio/feature_common.h\"\n#include \"frontend/audio/frontend_itf.h\"\n#include \"kaldi/feat/feature-window.h\"\n\nnamespace ppspeech {\n\nstruct LinearSpectrogramOptions {\n    kaldi::FrameExtractionOptions frame_opts;\n    LinearSpectrogramOptions() : frame_opts() {}\n};\n\nclass LinearSpectrogramComputer {\n  public:\n    typedef LinearSpectrogramOptions Options;\n    explicit LinearSpectrogramComputer(const Options& opts);\n\n    kaldi::FrameExtractionOptions& GetFrameOptions() {\n        return opts_.frame_opts;\n    }\n\n    bool Compute(kaldi::Vector<kaldi::BaseFloat>* window,\n                 kaldi::Vector<kaldi::BaseFloat>* feat);\n\n    int32 Dim() const { return dim_; }\n\n    bool NeedRawLogEnergy() { return false; }\n\n  private:\n    kaldi::BaseFloat scale_;\n    Options opts_;\n    int32 frame_length_;\n    int32 dim_;\n    DISALLOW_COPY_AND_ASSIGN(LinearSpectrogramComputer);\n};\n\ntypedef StreamingFeatureTpl<LinearSpectrogramComputer> LinearSpectrogram;\n\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/frontend/mel-computations.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is copied/modified from kaldi/src/feat/mel-computations.cc\n\n#include \"frontend/mel-computations.h\"\n\n#include <algorithm>\n#include <sstream>\n\n#include \"frontend/feature-window.h\"\n\nnamespace knf {\n\nstd::ostream &operator<<(std::ostream &os, const MelBanksOptions &opts) {\n    os << opts.ToString();\n    return os;\n}\n\nfloat MelBanks::VtlnWarpFreq(\n    float vtln_low_cutoff,  // upper+lower frequency cutoffs for VTLN.\n    float vtln_high_cutoff,\n    float low_freq,  // upper+lower frequency cutoffs in mel computation\n    float high_freq,\n    float vtln_warp_factor,\n    float freq) {\n    /// This computes a VTLN warping function that is not the same as HTK's one,\n    /// but has similar inputs (this function has the advantage of never\n    /// producing\n    /// empty bins).\n\n    /// This function computes a warp function F(freq), defined between low_freq\n    /// and high_freq inclusive, with the following properties:\n    ///  F(low_freq) == low_freq\n    ///  F(high_freq) == high_freq\n    /// The function is continuous and piecewise linear with two inflection\n    ///   points.\n    /// The lower inflection point (measured in terms of the unwarped\n    ///  frequency) is at frequency l, determined as described below.\n    /// The higher inflection point is at a frequency h, determined as\n    ///   described below.\n    /// If l <= f <= h, then F(f) = f/vtln_warp_factor.\n    /// If the higher inflection point (measured in terms of the unwarped\n    ///   frequency) is at h, then max(h, F(h)) == vtln_high_cutoff.\n    ///   Since (by the last point) F(h) == h/vtln_warp_factor, then\n    ///   max(h, h/vtln_warp_factor) == vtln_high_cutoff, so\n    ///   h = vtln_high_cutoff / max(1, 1/vtln_warp_factor).\n    ///     = vtln_high_cutoff * min(1, vtln_warp_factor).\n    /// If the lower inflection point (measured in terms of the unwarped\n    ///   frequency) is at l, then min(l, F(l)) == vtln_low_cutoff\n    ///   This implies that l = vtln_low_cutoff / min(1, 1/vtln_warp_factor)\n    ///                       = vtln_low_cutoff * max(1, vtln_warp_factor)\n\n    if (freq < low_freq || freq > high_freq)\n        return freq;  // in case this gets called\n    // for out-of-range frequencies, just return the freq.\n\n    CHECK_GT(vtln_low_cutoff, low_freq);\n    CHECK_LT(vtln_high_cutoff, high_freq);\n\n    float one = 1.0f;\n    float l = vtln_low_cutoff * std::max(one, vtln_warp_factor);\n    float h = vtln_high_cutoff * std::min(one, vtln_warp_factor);\n    float scale = 1.0f / vtln_warp_factor;\n    float Fl = scale * l;  // F(l);\n    float Fh = scale * h;  // F(h);\n    CHECK(l > low_freq && h < high_freq);\n    // slope of left part of the 3-piece linear function\n    float scale_left = (Fl - low_freq) / (l - low_freq);\n    // [slope of center part is just \"scale\"]\n\n    // slope of right part of the 3-piece linear function\n    float scale_right = (high_freq - Fh) / (high_freq - h);\n\n    if (freq < l) {\n        return low_freq + scale_left * (freq - low_freq);\n    } else if (freq < h) {\n        return scale * freq;\n    } else {  // freq >= h\n        return high_freq + scale_right * (freq - high_freq);\n    }\n}\n\nfloat MelBanks::VtlnWarpMelFreq(\n    float vtln_low_cutoff,  // upper+lower frequency cutoffs for VTLN.\n    float vtln_high_cutoff,\n    float low_freq,  // upper+lower frequency cutoffs in mel computation\n    float high_freq,\n    float vtln_warp_factor,\n    float mel_freq) {\n    return MelScale(VtlnWarpFreq(vtln_low_cutoff,\n                                 vtln_high_cutoff,\n                                 low_freq,\n                                 high_freq,\n                                 vtln_warp_factor,\n                                 InverseMelScale(mel_freq)));\n}\n\nMelBanks::MelBanks(const MelBanksOptions &opts,\n                   const FrameExtractionOptions &frame_opts,\n                   float vtln_warp_factor)\n    : htk_mode_(opts.htk_mode) {\n    int32_t num_bins = opts.num_bins;\n    if (num_bins < 3) LOG(FATAL) << \"Must have at least 3 mel bins\";\n\n    float sample_freq = frame_opts.samp_freq;\n    int32_t window_length_padded = frame_opts.PaddedWindowSize();\n    CHECK_EQ(window_length_padded % 2, 0);\n\n    int32_t num_fft_bins = window_length_padded / 2;\n    float nyquist = 0.5f * sample_freq;\n\n    float low_freq = opts.low_freq, high_freq;\n    if (opts.high_freq > 0.0f)\n        high_freq = opts.high_freq;\n    else\n        high_freq = nyquist + opts.high_freq;\n\n    if (low_freq < 0.0f || low_freq >= nyquist || high_freq <= 0.0f ||\n        high_freq > nyquist || high_freq <= low_freq) {\n        LOG(FATAL) << \"Bad values in options: low-freq \" << low_freq\n                   << \" and high-freq \" << high_freq << \" vs. nyquist \"\n                   << nyquist;\n    }\n\n    float fft_bin_width = sample_freq / window_length_padded;\n    // fft-bin width [think of it as Nyquist-freq / half-window-length]\n\n    float mel_low_freq = MelScale(low_freq);\n    float mel_high_freq = MelScale(high_freq);\n\n    debug_ = opts.debug_mel;\n\n    // divide by num_bins+1 in next line because of end-effects where the bins\n    // spread out to the sides.\n    float mel_freq_delta = (mel_high_freq - mel_low_freq) / (num_bins + 1);\n\n    float vtln_low = opts.vtln_low, vtln_high = opts.vtln_high;\n    if (vtln_high < 0.0f) {\n        vtln_high += nyquist;\n    }\n\n    if (vtln_warp_factor != 1.0f &&\n        (vtln_low < 0.0f || vtln_low <= low_freq || vtln_low >= high_freq ||\n         vtln_high <= 0.0f || vtln_high >= high_freq ||\n         vtln_high <= vtln_low)) {\n        LOG(FATAL) << \"Bad values in options: vtln-low \" << vtln_low\n                   << \" and vtln-high \" << vtln_high << \", versus \"\n                   << \"low-freq \" << low_freq << \" and high-freq \" << high_freq;\n    }\n\n    bins_.resize(num_bins);\n    center_freqs_.resize(num_bins);\n\n    for (int32_t bin = 0; bin < num_bins; ++bin) {\n        float left_mel = mel_low_freq + bin * mel_freq_delta,\n              center_mel = mel_low_freq + (bin + 1) * mel_freq_delta,\n              right_mel = mel_low_freq + (bin + 2) * mel_freq_delta;\n\n        if (vtln_warp_factor != 1.0f) {\n            left_mel = VtlnWarpMelFreq(vtln_low,\n                                       vtln_high,\n                                       low_freq,\n                                       high_freq,\n                                       vtln_warp_factor,\n                                       left_mel);\n            center_mel = VtlnWarpMelFreq(vtln_low,\n                                         vtln_high,\n                                         low_freq,\n                                         high_freq,\n                                         vtln_warp_factor,\n                                         center_mel);\n            right_mel = VtlnWarpMelFreq(vtln_low,\n                                        vtln_high,\n                                        low_freq,\n                                        high_freq,\n                                        vtln_warp_factor,\n                                        right_mel);\n        }\n        center_freqs_[bin] = InverseMelScale(center_mel);\n\n        // this_bin will be a vector of coefficients that is only\n        // nonzero where this mel bin is active.\n        std::vector<float> this_bin(num_fft_bins);\n\n        int32_t first_index = -1, last_index = -1;\n        for (int32_t i = 0; i < num_fft_bins; ++i) {\n            float freq = (fft_bin_width * i);  // Center frequency of this fft\n                                               // bin.\n            float mel = MelScale(freq);\n            if (mel > left_mel && mel < right_mel) {\n                float weight;\n                if (mel <= center_mel)\n                    weight = (mel - left_mel) / (center_mel - left_mel);\n                else\n                    weight = (right_mel - mel) / (right_mel - center_mel);\n                this_bin[i] = weight;\n                if (first_index == -1) first_index = i;\n                last_index = i;\n            }\n        }\n        CHECK(first_index != -1 && last_index >= first_index &&\n              \"You may have set num_mel_bins too large.\");\n\n        bins_[bin].first = first_index;\n        int32_t size = last_index + 1 - first_index;\n        bins_[bin].second.insert(bins_[bin].second.end(),\n                                 this_bin.begin() + first_index,\n                                 this_bin.begin() + first_index + size);\n\n        // Replicate a bug in HTK, for testing purposes.\n        if (opts.htk_mode && bin == 0 && mel_low_freq != 0.0f) {\n            bins_[bin].second[0] = 0.0;\n        }\n    }  // for (int32_t bin = 0; bin < num_bins; ++bin) {\n\n    if (debug_) {\n        std::ostringstream os;\n        for (size_t i = 0; i < bins_.size(); i++) {\n            os << \"bin \" << i << \", offset = \" << bins_[i].first << \", vec = \";\n            for (auto k : bins_[i].second) os << k << \", \";\n            os << \"\\n\";\n        }\n        LOG(INFO) << os.str();\n    }\n}\n\n// \"power_spectrum\" contains fft energies.\nvoid MelBanks::Compute(const float *power_spectrum,\n                       float *mel_energies_out) const {\n    int32_t num_bins = bins_.size();\n\n    for (int32_t i = 0; i < num_bins; i++) {\n        int32_t offset = bins_[i].first;\n        const auto &v = bins_[i].second;\n        float energy = 0;\n        for (int32_t k = 0; k != v.size(); ++k) {\n            energy += v[k] * power_spectrum[k + offset];\n        }\n\n        // HTK-like flooring- for testing purposes (we prefer dither)\n        if (htk_mode_ && energy < 1.0) {\n            energy = 1.0;\n        }\n\n        mel_energies_out[i] = energy;\n\n        // The following assert was added due to a problem with OpenBlas that\n        // we had at one point (it was a bug in that library).  Just to detect\n        // it early.\n        CHECK_EQ(energy, energy);  // check that energy is not nan\n    }\n\n    if (debug_) {\n        fprintf(stderr, \"MEL BANKS:\\n\");\n        for (int32_t i = 0; i < num_bins; i++)\n            fprintf(stderr, \" %f\", mel_energies_out[i]);\n        fprintf(stderr, \"\\n\");\n    }\n}\n\n}  // namespace knf\n"
  },
  {
    "path": "runtime/engine/common/frontend/mel-computations.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// This file is copied/modified from kaldi/src/feat/mel-computations.h\n#ifndef KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n#define KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n\n#include <cmath>\n#include <string>\n\n#include \"frontend/feature-window.h\"\n\nnamespace knf {\n\nstruct MelBanksOptions {\n    int32_t num_bins = 25;  // e.g. 25; number of triangular bins\n    float low_freq = 20;    // e.g. 20; lower frequency cutoff\n\n    // an upper frequency cutoff; 0 -> no cutoff, negative\n    // ->added to the Nyquist frequency to get the cutoff.\n    float high_freq = 0;\n\n    float vtln_low = 100;  // vtln lower cutoff of warping function.\n\n    // vtln upper cutoff of warping function: if negative, added\n    // to the Nyquist frequency to get the cutoff.\n    float vtln_high = -500;\n\n    bool debug_mel = false;\n    // htk_mode is a \"hidden\" config, it does not show up on command line.\n    // Enables more exact compatibility with HTK, for testing purposes.  Affects\n    // mel-energy flooring and reproduces a bug in HTK.\n    bool htk_mode = false;\n\n    std::string ToString() const {\n        std::ostringstream os;\n        os << \"num_bins: \" << num_bins << \"\\n\";\n        os << \"low_freq: \" << low_freq << \"\\n\";\n        os << \"high_freq: \" << high_freq << \"\\n\";\n        os << \"vtln_low: \" << vtln_low << \"\\n\";\n        os << \"vtln_high: \" << vtln_high << \"\\n\";\n        os << \"debug_mel: \" << debug_mel << \"\\n\";\n        os << \"htk_mode: \" << htk_mode << \"\\n\";\n        return os.str();\n    }\n};\n\nstd::ostream &operator<<(std::ostream &os, const MelBanksOptions &opts);\n\nclass MelBanks {\n  public:\n    static inline float InverseMelScale(float mel_freq) {\n        return 700.0f * (expf(mel_freq / 1127.0f) - 1.0f);\n    }\n\n    static inline float MelScale(float freq) {\n        return 1127.0f * logf(1.0f + freq / 700.0f);\n    }\n\n    static float VtlnWarpFreq(\n        float vtln_low_cutoff,\n        float vtln_high_cutoff,  // discontinuities in warp func\n        float low_freq,\n        float high_freq,  // upper+lower frequency cutoffs in\n        // the mel computation\n        float vtln_warp_factor,\n        float freq);\n\n    static float VtlnWarpMelFreq(float vtln_low_cutoff,\n                                 float vtln_high_cutoff,\n                                 float low_freq,\n                                 float high_freq,\n                                 float vtln_warp_factor,\n                                 float mel_freq);\n\n    // TODO(fangjun): Remove vtln_warp_factor\n    MelBanks(const MelBanksOptions &opts,\n             const FrameExtractionOptions &frame_opts,\n             float vtln_warp_factor);\n\n    /// Compute Mel energies (note: not log energies).\n    /// At input, \"fft_energies\" contains the FFT energies (not log).\n    ///\n    /// @param fft_energies 1-D array of size num_fft_bins/2+1\n    /// @param mel_energies_out  1-D array of size num_mel_bins\n    void Compute(const float *fft_energies, float *mel_energies_out) const;\n\n    int32_t NumBins() const { return bins_.size(); }\n\n  private:\n    // center frequencies of bins, numbered from 0 ... num_bins-1.\n    // Needed by GetCenterFreqs().\n    std::vector<float> center_freqs_;\n\n    // the \"bins_\" vector is a vector, one for each bin, of a pair:\n    // (the first nonzero fft-bin), (the vector of weights).\n    std::vector<std::pair<int32_t, std::vector<float>>> bins_;\n\n    // TODO(fangjun): Remove debug_ and htk_mode_\n    bool debug_;\n    bool htk_mode_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_MEL_COMPUTATIONS_H_\n"
  },
  {
    "path": "runtime/engine/common/frontend/normalizer.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include \"frontend/cmvn.h\""
  },
  {
    "path": "runtime/engine/common/frontend/rfft.cc",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include \"frontend/rfft.h\"\n\n#include <cmath>\n#include <memory>\n#include <vector>\n\n#include \"base/log.h\"\n\n// see fftsg.c\n#ifdef __cplusplus\nextern \"C\" void rdft(int n, int isgn, double *a, int *ip, double *w);\n#else\nvoid rdft(int n, int isgn, double *a, int *ip, double *w);\n#endif\n\nnamespace knf {\nclass Rfft::RfftImpl {\n  public:\n    explicit RfftImpl(int32_t n) : n_(n), ip_(2 + std::sqrt(n / 2)), w_(n / 2) {\n        CHECK_EQ(n & (n - 1), 0);\n    }\n\n    void Compute(float *in_out) {\n        std::vector<double> d(in_out, in_out + n_);\n\n        Compute(d.data());\n\n        std::copy(d.begin(), d.end(), in_out);\n    }\n\n    void Compute(double *in_out) {\n        // 1 means forward fft\n        rdft(n_, 1, in_out, ip_.data(), w_.data());\n    }\n\n  private:\n    int32_t n_;\n    std::vector<int32_t> ip_;\n    std::vector<double> w_;\n};\n\nRfft::Rfft(int32_t n) : impl_(std::make_unique<RfftImpl>(n)) {}\n\nRfft::~Rfft() = default;\n\nvoid Rfft::Compute(float *in_out) { impl_->Compute(in_out); }\nvoid Rfft::Compute(double *in_out) { impl_->Compute(in_out); }\n\n}  // namespace knf\n"
  },
  {
    "path": "runtime/engine/common/frontend/rfft.h",
    "content": "/**\n * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)\n *\n * See LICENSE for clarification regarding multiple authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n#define KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n\n#include <memory>\n\nnamespace knf {\n\n// n-point Real discrete Fourier transform\n// where n is a power of 2. n >= 2\n//\n//  R[k] = sum_j=0^n-1 in[j]*cos(2*pi*j*k/n), 0<=k<=n/2\n//  I[k] = sum_j=0^n-1 in[j]*sin(2*pi*j*k/n), 0<k<n/2\nclass Rfft {\n  public:\n    // @param n Number of fft bins. it should be a power of 2.\n    explicit Rfft(int32_t n);\n    ~Rfft();\n\n    /** @param in_out A 1-D array of size n.\n     *             On return:\n     *               in_out[0] = R[0]\n     *               in_out[1] = R[n/2]\n     *               for 1 < k < n/2,\n     *                 in_out[2*k] = R[k]\n     *                 in_out[2*k+1] = I[k]\n     *\n     */\n    void Compute(float *in_out);\n    void Compute(double *in_out);\n\n  private:\n    class RfftImpl;\n    std::unique_ptr<RfftImpl> impl_;\n};\n\n}  // namespace knf\n\n#endif  // KALDI_NATIVE_FBANK_CSRC_RFFT_H_\n"
  },
  {
    "path": "runtime/engine/common/frontend/wave-reader.cc",
    "content": "// feat/wave-reader.cc\n\n// Copyright 2009-2011  Karel Vesely;  Petr Motlicek\n//                2013  Florent Masson\n//                2013  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"frontend/wave-reader.h\"\n\n#include <algorithm>\n#include <cstdio>\n#include <limits>\n#include <sstream>\n#include <vector>\n\n#include \"base/kaldi-error.h\"\n#include \"base/kaldi-utils.h\"\n\nnamespace kaldi {\n\n// A utility class for reading wave header.\nstruct WaveHeaderReadGofer {\n    std::istream &is;\n    bool swap;\n    char tag[5];\n\n    WaveHeaderReadGofer(std::istream &is) : is(is), swap(false) {\n        memset(tag, '\\0', sizeof tag);\n    }\n\n    void Expect4ByteTag(const char *expected) {\n        is.read(tag, 4);\n        if (is.fail())\n            KALDI_ERR << \"WaveData: expected \" << expected\n                      << \", failed to read anything\";\n        if (strcmp(tag, expected))\n            KALDI_ERR << \"WaveData: expected \" << expected << \", got \" << tag;\n    }\n\n    void Read4ByteTag() {\n        is.read(tag, 4);\n        if (is.fail())\n            KALDI_ERR << \"WaveData: expected 4-byte chunk-name, got read error\";\n    }\n\n    uint32 ReadUint32() {\n        union {\n            char result[4];\n            uint32 ans;\n        } u;\n        is.read(u.result, 4);\n        if (swap) KALDI_SWAP4(u.result);\n        if (is.fail())\n            KALDI_ERR << \"WaveData: unexpected end of file or read error\";\n        return u.ans;\n    }\n\n    uint16 ReadUint16() {\n        union {\n            char result[2];\n            int16 ans;\n        } u;\n        is.read(u.result, 2);\n        if (swap) KALDI_SWAP2(u.result);\n        if (is.fail())\n            KALDI_ERR << \"WaveData: unexpected end of file or read error\";\n        return u.ans;\n    }\n};\n\nstatic void WriteUint32(std::ostream &os, int32 i) {\n    union {\n        char buf[4];\n        int i;\n    } u;\n    u.i = i;\n#ifdef __BIG_ENDIAN__\n    KALDI_SWAP4(u.buf);\n#endif\n    os.write(u.buf, 4);\n    if (os.fail()) KALDI_ERR << \"WaveData: error writing to stream.\";\n}\n\nstatic void WriteUint16(std::ostream &os, int16 i) {\n    union {\n        char buf[2];\n        int16 i;\n    } u;\n    u.i = i;\n#ifdef __BIG_ENDIAN__\n    KALDI_SWAP2(u.buf);\n#endif\n    os.write(u.buf, 2);\n    if (os.fail()) KALDI_ERR << \"WaveData: error writing to stream.\";\n}\n\nvoid WaveInfo::Read(std::istream &is) {\n    WaveHeaderReadGofer reader(is);\n    reader.Read4ByteTag();\n    if (strcmp(reader.tag, \"RIFF\") == 0)\n        reverse_bytes_ = false;\n    else if (strcmp(reader.tag, \"RIFX\") == 0)\n        reverse_bytes_ = true;\n    else\n        KALDI_ERR << \"WaveData: expected RIFF or RIFX, got \" << reader.tag;\n\n#ifdef __BIG_ENDIAN__\n    reverse_bytes_ = !reverse_bytes_;\n#endif\n    reader.swap = reverse_bytes_;\n\n    uint32 riff_chunk_size = reader.ReadUint32();\n    reader.Expect4ByteTag(\"WAVE\");\n\n    uint32 riff_chunk_read = 0;\n    riff_chunk_read += 4;  // WAVE included in riff_chunk_size.\n\n    // Possibly skip any RIFF tags between 'WAVE' and 'fmt '.\n    // Apple devices produce a filler tag 'JUNK' for memory alignment.\n    reader.Read4ByteTag();\n    riff_chunk_read += 4;\n    while (strcmp(reader.tag, \"fmt \") != 0) {\n        uint32 filler_size = reader.ReadUint32();\n        riff_chunk_read += 4;\n        for (uint32 i = 0; i < filler_size; i++) {\n            is.get();  // read 1 byte,\n        }\n        riff_chunk_read += filler_size;\n        // get next RIFF tag,\n        reader.Read4ByteTag();\n        riff_chunk_read += 4;\n    }\n\n    KALDI_ASSERT(strcmp(reader.tag, \"fmt \") == 0);\n    uint32 subchunk1_size = reader.ReadUint32();\n    uint16 audio_format = reader.ReadUint16();\n    num_channels_ = reader.ReadUint16();\n    uint32 sample_rate = reader.ReadUint32(), byte_rate = reader.ReadUint32(),\n           block_align = reader.ReadUint16(),\n           bits_per_sample = reader.ReadUint16();\n    samp_freq_ = static_cast<BaseFloat>(sample_rate);\n\n    uint32 fmt_chunk_read = 16;\n    if (audio_format == 1) {\n        if (subchunk1_size < 16) {\n            KALDI_ERR << \"WaveData: expect PCM format data to have fmt chunk \"\n                      << \"of at least size 16.\";\n        }\n    } else if (audio_format == 0xFFFE) {  // WAVE_FORMAT_EXTENSIBLE\n        uint16 extra_size = reader.ReadUint16();\n        if (subchunk1_size < 40 || extra_size < 22) {\n            KALDI_ERR\n                << \"WaveData: malformed WAVE_FORMAT_EXTENSIBLE format data.\";\n        }\n        reader.ReadUint16();  // Unused for PCM.\n        reader.ReadUint32();  // Channel map: we do not care.\n        uint32 guid1 = reader.ReadUint32(), guid2 = reader.ReadUint32(),\n               guid3 = reader.ReadUint32(), guid4 = reader.ReadUint32();\n        fmt_chunk_read = 40;\n\n        // Support only KSDATAFORMAT_SUBTYPE_PCM for now. Interesting formats:\n        // (\"00000001-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_PCM)\n        // (\"00000003-0000-0010-8000-00aa00389b71\",\n        // KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)\n        // (\"00000006-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_ALAW)\n        // (\"00000007-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_MULAW)\n        if (guid1 != 0x00000001 || guid2 != 0x00100000 || guid3 != 0xAA000080 ||\n            guid4 != 0x719B3800) {\n            KALDI_ERR << \"WaveData: unsupported WAVE_FORMAT_EXTENSIBLE format.\";\n        }\n    } else {\n        KALDI_ERR << \"WaveData: can read only PCM data, format id in file is: \"\n                  << audio_format;\n    }\n\n    for (uint32 i = fmt_chunk_read; i < subchunk1_size; ++i)\n        is.get();  // use up extra data.\n\n    if (num_channels_ == 0) KALDI_ERR << \"WaveData: no channels present\";\n    if (bits_per_sample != 16)\n        KALDI_ERR << \"WaveData: unsupported bits_per_sample = \"\n                  << bits_per_sample;\n    if (byte_rate != sample_rate * bits_per_sample / 8 * num_channels_)\n        KALDI_ERR << \"Unexpected byte rate \" << byte_rate << \" vs. \"\n                  << sample_rate << \" * \" << (bits_per_sample / 8) << \" * \"\n                  << num_channels_;\n    if (block_align != num_channels_ * bits_per_sample / 8)\n        KALDI_ERR << \"Unexpected block_align: \" << block_align << \" vs. \"\n                  << num_channels_ << \" * \" << (bits_per_sample / 8);\n\n    riff_chunk_read += 4 + subchunk1_size;\n    // size of what we just read, 4 for subchunk1_size + subchunk1_size itself.\n\n    // We support an optional \"fact\" chunk (which is useless but which\n    // we encountered), and then a single \"data\" chunk.\n\n    reader.Read4ByteTag();\n    riff_chunk_read += 4;\n\n    // Skip any subchunks between \"fmt\" and \"data\".  Usually there will\n    // be a single \"fact\" subchunk, but on Windows there can also be a\n    // \"list\" subchunk.\n    while (strcmp(reader.tag, \"data\") != 0) {\n        // We will just ignore the data in these chunks.\n        uint32 chunk_sz = reader.ReadUint32();\n        if (chunk_sz != 4 && strcmp(reader.tag, \"fact\") == 0)\n            KALDI_WARN << \"Expected fact chunk to be 4 bytes long.\";\n        for (uint32 i = 0; i < chunk_sz; i++) is.get();\n        riff_chunk_read +=\n            4 + chunk_sz;  // for chunk_sz (4) + chunk contents (chunk-sz)\n\n        // Now read the next chunk name.\n        reader.Read4ByteTag();\n        riff_chunk_read += 4;\n    }\n\n    KALDI_ASSERT(strcmp(reader.tag, \"data\") == 0);\n    uint32 data_chunk_size = reader.ReadUint32();\n    riff_chunk_read += 4;\n\n    // Figure out if the file is going to be read to the end. Values as\n    // observed in the wild:\n    bool is_stream_mode =\n        riff_chunk_size == 0 || riff_chunk_size == 0xFFFFFFFF ||\n        data_chunk_size == 0 || data_chunk_size == 0xFFFFFFFF ||\n        data_chunk_size == 0x7FFFF000;  // This value is used by SoX.\n\n    if (is_stream_mode)\n        KALDI_VLOG(1) << \"Read in RIFF chunk size: \" << riff_chunk_size\n                      << \", data chunk size: \" << data_chunk_size\n                      << \". Assume 'stream mode' (reading data to EOF).\";\n\n    if (!is_stream_mode && std::abs(static_cast<int64>(riff_chunk_read) +\n                                    static_cast<int64>(data_chunk_size) -\n                                    static_cast<int64>(riff_chunk_size)) > 1) {\n        // We allow the size to be off by one without warning, because there is\n        // a\n        // weirdness in the format of RIFF files that means that the input may\n        // sometimes be padded with 1 unused byte to make the total size even.\n        KALDI_WARN << \"Expected \" << riff_chunk_size\n                   << \" bytes in RIFF chunk, but \"\n                   << \"after first data block there will be \" << riff_chunk_read\n                   << \" + \" << data_chunk_size << \" bytes \"\n                   << \"(we do not support reading multiple data chunks).\";\n    }\n\n    if (is_stream_mode)\n        samp_count_ = -1;\n    else\n        samp_count_ = data_chunk_size / block_align;\n}\n\nvoid WaveData::Read(std::istream &is) {\n    const uint32 kBlockSize = 1024 * 1024;\n\n    WaveInfo header;\n    header.Read(is);\n\n    data_.Resize(0, 0);  // clear the data.\n    samp_freq_ = header.SampFreq();\n\n    std::vector<char> buffer;\n    uint32 bytes_to_go = header.IsStreamed() ? kBlockSize : header.DataBytes();\n\n    // Once in a while header.DataBytes() will report an insane value;\n    // read the file to the end\n    while (is && bytes_to_go > 0) {\n        uint32 block_bytes = std::min(bytes_to_go, kBlockSize);\n        uint32 offset = buffer.size();\n        buffer.resize(offset + block_bytes);\n        is.read(&buffer[offset], block_bytes);\n        uint32 bytes_read = is.gcount();\n        buffer.resize(offset + bytes_read);\n        if (!header.IsStreamed()) bytes_to_go -= bytes_read;\n    }\n\n    if (is.bad()) KALDI_ERR << \"WaveData: file read error\";\n\n    if (buffer.size() == 0) KALDI_ERR << \"WaveData: empty file (no data)\";\n\n    if (!header.IsStreamed() && buffer.size() < header.DataBytes()) {\n        KALDI_WARN << \"Expected \" << header.DataBytes()\n                   << \" bytes of wave data, \"\n                   << \"but read only \" << buffer.size() << \" bytes. \"\n                   << \"Truncated file?\";\n    }\n\n    uint16 *data_ptr = reinterpret_cast<uint16 *>(&buffer[0]);\n\n    // The matrix is arranged row per channel, column per sample.\n    data_.Resize(header.NumChannels(), buffer.size() / header.BlockAlign());\n    for (uint32 i = 0; i < data_.NumCols(); ++i) {\n        for (uint32 j = 0; j < data_.NumRows(); ++j) {\n            int16 k = *data_ptr++;\n            if (header.ReverseBytes()) KALDI_SWAP2(k);\n            data_(j, i) = k;\n        }\n    }\n}\n\n\n// Write 16-bit PCM.\n\n// note: the WAVE chunk contains 2 subchunks.\n//\n// subchunk2size = data.NumRows() * data.NumCols() * 2.\n\n\nvoid WaveData::Write(std::ostream &os) const {\n    os << \"RIFF\";\n    if (data_.NumRows() == 0)\n        KALDI_ERR << \"Error: attempting to write empty WAVE file\";\n\n    int32 num_chan = data_.NumRows(), num_samp = data_.NumCols(),\n          bytes_per_samp = 2;\n\n    int32 subchunk2size = (num_chan * num_samp * bytes_per_samp);\n    int32 chunk_size = 36 + subchunk2size;\n    WriteUint32(os, chunk_size);\n    os << \"WAVE\";\n    os << \"fmt \";\n    WriteUint32(os, 16);\n    WriteUint16(os, 1);\n    WriteUint16(os, num_chan);\n    KALDI_ASSERT(samp_freq_ > 0);\n    WriteUint32(os, static_cast<int32>(samp_freq_));\n    WriteUint32(os, static_cast<int32>(samp_freq_) * num_chan * bytes_per_samp);\n    WriteUint16(os, num_chan * bytes_per_samp);\n    WriteUint16(os, 8 * bytes_per_samp);\n    os << \"data\";\n    WriteUint32(os, subchunk2size);\n\n    const BaseFloat *data_ptr = data_.Data();\n    int32 stride = data_.Stride();\n\n    int num_clipped = 0;\n    for (int32 i = 0; i < num_samp; i++) {\n        for (int32 j = 0; j < num_chan; j++) {\n            int32 elem = static_cast<int32>(trunc(data_ptr[j * stride + i]));\n            int16 elem_16 = static_cast<int16>(elem);\n            if (elem < std::numeric_limits<int16>::min()) {\n                elem_16 = std::numeric_limits<int16>::min();\n                ++num_clipped;\n            } else if (elem > std::numeric_limits<int16>::max()) {\n                elem_16 = std::numeric_limits<int16>::max();\n                ++num_clipped;\n            }\n#ifdef __BIG_ENDIAN__\n            KALDI_SWAP2(elem_16);\n#endif\n            os.write(reinterpret_cast<char *>(&elem_16), 2);\n        }\n    }\n    if (os.fail()) KALDI_ERR << \"Error writing wave data to stream.\";\n    if (num_clipped > 0)\n        KALDI_WARN << \"WARNING: clipped \" << num_clipped\n                   << \" samples out of total \" << num_chan * num_samp\n                   << \". Reduce volume?\";\n}\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/common/frontend/wave-reader.h",
    "content": "// feat/wave-reader.h\n\n// Copyright 2009-2011  Karel Vesely;  Microsoft Corporation\n//                2013  Florent Masson\n//                2013  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n/*\n// THE WAVE FORMAT IS SPECIFIED IN:\n// https:// ccrma.stanford.edu/courses/422/projects/WaveFormat/\n//\n//\n//\n//  RIFF\n//  |\n//  WAVE\n//  |    \\    \\   \\\n//  fmt_ data ... data\n//\n//\n//  Riff is a general container, which usually contains one WAVE chunk\n//  each WAVE chunk has header sub-chunk 'fmt_'\n//  and one or more data sub-chunks 'data'\n//\n//  [Note from Dan: to say that the wave format was ever \"specified\" anywhere is\n//   not quite right.  The guy who invented the wave format attempted to create\n//   a formal specification but it did not completely make sense.  And there\n//   doesn't seem to be a consensus on what makes a valid wave file,\n//   particularly where the accuracy of header information is concerned.]\n*/\n\n\n#ifndef KALDI_FEAT_WAVE_READER_H_\n#define KALDI_FEAT_WAVE_READER_H_\n\n#include <cstring>\n\n#include \"base/kaldi-types.h\"\n#include \"matrix/kaldi-matrix.h\"\n#include \"matrix/kaldi-vector.h\"\n\n\nnamespace kaldi {\n\n/// For historical reasons, we scale waveforms to the range\n/// (2^15-1)*[-1, 1], not the usual default DSP range [-1, 1].\nconst BaseFloat kWaveSampleMax = 32768.0;\n\n/// This class reads and hold wave file header information.\nclass WaveInfo {\n  public:\n    WaveInfo()\n        : samp_freq_(0), samp_count_(0), num_channels_(0), reverse_bytes_(0) {}\n\n    /// Is stream size unknown? Duration and SampleCount not valid if true.\n    bool IsStreamed() const { return samp_count_ < 0; }\n\n    /// Sample frequency, Hz.\n    BaseFloat SampFreq() const { return samp_freq_; }\n\n    /// Number of samples in stream. Invalid if IsStreamed() is true.\n    uint32 SampleCount() const { return samp_count_; }\n\n    /// Approximate duration, seconds. Invalid if IsStreamed() is true.\n    BaseFloat Duration() const { return samp_count_ / samp_freq_; }\n\n    /// Number of channels, 1 to 16.\n    int32 NumChannels() const { return num_channels_; }\n\n    /// Bytes per sample.\n    size_t BlockAlign() const { return 2 * num_channels_; }\n\n    /// Wave data bytes. Invalid if IsStreamed() is true.\n    size_t DataBytes() const { return samp_count_ * BlockAlign(); }\n\n    /// Is data file byte order different from machine byte order?\n    bool ReverseBytes() const { return reverse_bytes_; }\n\n    /// 'is' should be opened in binary mode. Read() will throw on error.\n    /// On success 'is' will be positioned at the beginning of wave data.\n    void Read(std::istream &is);\n\n  private:\n    BaseFloat samp_freq_;\n    int32 samp_count_;  // 0 if empty, -1 if undefined length.\n    uint8 num_channels_;\n    bool reverse_bytes_;  // File endianness differs from host.\n};\n\n/// This class's purpose is to read in Wave files.\nclass WaveData {\n  public:\n    WaveData(BaseFloat samp_freq, const MatrixBase<BaseFloat> &data)\n        : data_(data), samp_freq_(samp_freq) {}\n\n    WaveData() : samp_freq_(0.0) {}\n\n    /// Read() will throw on error.  It's valid to call Read() more than once--\n    /// in this case it will destroy what was there before.\n    /// \"is\" should be opened in binary mode.\n    void Read(std::istream &is);\n\n    /// Write() will throw on error.   os should be opened in binary mode.\n    void Write(std::ostream &os) const;\n\n    // This function returns the wave data-- it's in a matrix\n    // because there may be multiple channels.  In the normal case\n    // there's just one channel so Data() will have one row.\n    const Matrix<BaseFloat> &Data() const { return data_; }\n\n    BaseFloat SampFreq() const { return samp_freq_; }\n\n    // Returns the duration in seconds\n    BaseFloat Duration() const { return data_.NumCols() / samp_freq_; }\n\n    void CopyFrom(const WaveData &other) {\n        samp_freq_ = other.samp_freq_;\n        data_.CopyFromMat(other.data_);\n    }\n\n    void Clear() {\n        data_.Resize(0, 0);\n        samp_freq_ = 0.0;\n    }\n\n    void Swap(WaveData *other) {\n        data_.Swap(&(other->data_));\n        std::swap(samp_freq_, other->samp_freq_);\n    }\n\n  private:\n    static const uint32 kBlockSize = 1024 * 1024;  // Use 1M bytes.\n    Matrix<BaseFloat> data_;\n    BaseFloat samp_freq_;\n};\n\n\n// Holder class for .wav files that enables us to read (but not write) .wav\n// files. c.f. util/kaldi-holder.h we don't use the KaldiObjectHolder template\n// because we don't want to check for the \\0B binary header. We could have faked\n// it by pretending to read in the wave data in text mode after failing to find\n// the \\0B header, but that would have been a little ugly.\nclass WaveHolder {\n  public:\n    typedef WaveData T;\n\n    static bool Write(std::ostream &os, bool binary, const T &t) {\n        // We don't write the binary-mode header here [always binary].\n        if (!binary)\n            KALDI_ERR << \"Wave data can only be written in binary mode.\";\n        try {\n            t.Write(os);  // throws exception on failure.\n            return true;\n        } catch (const std::exception &e) {\n            KALDI_WARN << \"Exception caught in WaveHolder object (writing). \"\n                       << e.what();\n            return false;  // write failure.\n        }\n    }\n    void Copy(const T &t) { t_.CopyFrom(t); }\n\n    static bool IsReadInBinary() { return true; }\n\n    void Clear() { t_.Clear(); }\n\n    T &Value() { return t_; }\n\n    WaveHolder &operator=(const WaveHolder &other) {\n        t_.CopyFrom(other.t_);\n        return *this;\n    }\n    WaveHolder(const WaveHolder &other) : t_(other.t_) {}\n\n    WaveHolder() {}\n\n    bool Read(std::istream &is) {\n        // We don't look for the binary-mode header here [always binary]\n        try {\n            t_.Read(is);  // Throws exception on failure.\n            return true;\n        } catch (const std::exception &e) {\n            KALDI_WARN << \"Exception caught in WaveHolder::Read(). \"\n                       << e.what();\n            return false;\n        }\n    }\n\n    void Swap(WaveHolder *other) { t_.Swap(&(other->t_)); }\n\n    bool ExtractRange(const WaveHolder &other, const std::string &range) {\n        KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n        return false;\n    }\n\n  private:\n    T t_;\n};\n\n// This is like WaveHolder but when you just want the metadata-\n// it leaves the actual data undefined, it doesn't read it.\nclass WaveInfoHolder {\n  public:\n    typedef WaveInfo T;\n\n    void Clear() { info_ = WaveInfo(); }\n    void Swap(WaveInfoHolder *other) { std::swap(info_, other->info_); }\n    T &Value() { return info_; }\n    static bool IsReadInBinary() { return true; }\n\n    bool Read(std::istream &is) {\n        try {\n            info_.Read(is);  // Throws exception on failure.\n            return true;\n        } catch (const std::exception &e) {\n            KALDI_WARN << \"Exception caught in WaveInfoHolder::Read(). \"\n                       << e.what();\n            return false;\n        }\n    }\n\n    bool ExtractRange(const WaveInfoHolder &other, const std::string &range) {\n        KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n        return false;\n    }\n\n  private:\n    WaveInfo info_;\n};\n\n\n}  // namespace kaldi\n\n#endif  // KALDI_FEAT_WAVE_READER_H_\n"
  },
  {
    "path": "runtime/engine/common/matrix/CMakeLists.txt",
    "content": "\nadd_library(kaldi-matrix\nkaldi-matrix.cc\nkaldi-vector.cc\n)\n\ntarget_link_libraries(kaldi-matrix kaldi-base)\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-matrix-inl.h",
    "content": "// matrix/kaldi-matrix-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Haihua Xu\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_MATRIX_KALDI_MATRIX_INL_H_\n#define KALDI_MATRIX_KALDI_MATRIX_INL_H_ 1\n\n#include \"matrix/kaldi-vector.h\"\n\nnamespace kaldi {\n\n/// Empty constructor\ntemplate <typename Real>\nMatrix<Real>::Matrix() : MatrixBase<Real>(NULL, 0, 0, 0) {}\n\n/*\ntemplate<>\ntemplate<>\nvoid MatrixBase<float>::AddVecVec(const float alpha, const VectorBase<float>\n&ra, const VectorBase<float> &rb);\n\ntemplate<>\ntemplate<>\nvoid MatrixBase<double>::AddVecVec(const double alpha, const VectorBase<double>\n&ra, const VectorBase<double> &rb);\n*/\n\ntemplate <typename Real>\ninline std::ostream& operator<<(std::ostream& os, const MatrixBase<Real>& M) {\n    M.Write(os, false);\n    return os;\n}\n\ntemplate <typename Real>\ninline std::istream& operator>>(std::istream& is, Matrix<Real>& M) {\n    M.Read(is, false);\n    return is;\n}\n\n\ntemplate <typename Real>\ninline std::istream& operator>>(std::istream& is, MatrixBase<Real>& M) {\n    M.Read(is, false);\n    return is;\n}\n\n}  // namespace kaldi\n\n\n#endif  // KALDI_MATRIX_KALDI_MATRIX_INL_H_\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-matrix.cc",
    "content": "// matrix/kaldi-matrix.cc\n\n// Copyright 2009-2011   Lukas Burget;  Ondrej Glembek;  Go Vivace Inc.;\n//                       Microsoft Corporation;  Saarland University;\n//                       Yanmin Qian;  Petr Schwarz;  Jan Silovsky;\n//                       Haihua Xu\n//           2017        Shiyin Kang\n//           2019        Yiwen Shao\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"matrix/kaldi-matrix.h\"\n\nnamespace kaldi {\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::Invert(Real *log_det, Real *det_sign,\n                              bool inverse_needed) {\n  KALDI_ASSERT(num_rows_ == num_cols_);\n  if (num_rows_ == 0) {\n    if (det_sign) *det_sign = 1;\n    if (log_det) *log_det = 0.0;\n    return;\n  }\n#ifndef HAVE_ATLAS\n  KaldiBlasInt *pivot = new KaldiBlasInt[num_rows_];\n  KaldiBlasInt M = num_rows_;\n  KaldiBlasInt N = num_cols_;\n  KaldiBlasInt LDA = stride_;\n  KaldiBlasInt result = -1;\n  KaldiBlasInt l_work = std::max<KaldiBlasInt>(1, N);\n  Real *p_work;\n  void *temp;\n  if ((p_work = static_cast<Real*>(\n          KALDI_MEMALIGN(16, sizeof(Real)*l_work, &temp))) == NULL) {\n    delete[] pivot;\n    throw std::bad_alloc();\n  }\n\n  clapack_Xgetrf2(&M, &N, data_, &LDA, pivot, &result);\n  const int pivot_offset = 1;\n#else\n  int *pivot = new int[num_rows_];\n  int result;\n  clapack_Xgetrf(num_rows_, num_cols_, data_, stride_, pivot, &result);\n  const int pivot_offset = 0;\n#endif\n  KALDI_ASSERT(result >= 0 && \"Call to CLAPACK sgetrf_ or ATLAS clapack_sgetrf \"\n               \"called with wrong arguments\");\n  if (result > 0) {\n    if (inverse_needed) {\n      KALDI_ERR << \"Cannot invert: matrix is singular\";\n    } else {\n      if (log_det) *log_det = -std::numeric_limits<Real>::infinity();\n      if (det_sign) *det_sign = 0;\n      delete[] pivot;\n#ifndef HAVE_ATLAS\n      KALDI_MEMALIGN_FREE(p_work);\n#endif\n      return;\n    }\n  }\n  if (det_sign != NULL) {\n    int sign = 1;\n    for (MatrixIndexT i = 0; i < num_rows_; i++)\n      if (pivot[i] != static_cast<int>(i) + pivot_offset) sign *= -1;\n    *det_sign = sign;\n  }\n  if (log_det != NULL || det_sign != NULL) {  // Compute log determinant.\n    if (log_det != NULL) *log_det = 0.0;\n    Real prod = 1.0;\n    for (MatrixIndexT i = 0; i < num_rows_; i++) {\n      prod *= (*this)(i, i);\n      if (i == num_rows_ - 1 || std::fabs(prod) < 1.0e-10 ||\n          std::fabs(prod) > 1.0e+10) {\n        if (log_det != NULL) *log_det += kaldi::Log(std::fabs(prod));\n        if (det_sign != NULL) *det_sign *= (prod > 0 ? 1.0 : -1.0);\n        prod = 1.0;\n      }\n    }\n  }\n#ifndef HAVE_ATLAS\n  if (inverse_needed) clapack_Xgetri2(&M, data_, &LDA, pivot, p_work, &l_work,\n                              &result);\n  delete[] pivot;\n  KALDI_MEMALIGN_FREE(p_work);\n#else\n  if (inverse_needed)\n    clapack_Xgetri(num_rows_, data_, stride_, pivot, &result);\n  delete [] pivot;\n#endif\n  KALDI_ASSERT(result == 0 && \"Call to CLAPACK sgetri_ or ATLAS clapack_sgetri \"\n               \"called with wrong arguments\");\n}\n\ntemplate<>\ntemplate<>\nvoid MatrixBase<float>::AddVecVec(const float alpha,\n                                  const VectorBase<float> &a,\n                                  const VectorBase<float> &rb) {\n  KALDI_ASSERT(a.Dim() == num_rows_ && rb.Dim() == num_cols_);\n  cblas_Xger(a.Dim(), rb.Dim(), alpha, a.Data(), 1, rb.Data(),\n             1, data_, stride_);\n}\n\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::AddVecVec(const Real alpha,\n                                 const VectorBase<OtherReal> &a,\n                                 const VectorBase<OtherReal> &b) {\n  KALDI_ASSERT(a.Dim() == num_rows_ && b.Dim() == num_cols_);\n  if (num_rows_ * num_cols_ > 100) { // It's probably worth it to allocate\n    // temporary vectors of the right type and use BLAS.\n    Vector<Real> temp_a(a), temp_b(b);\n    cblas_Xger(num_rows_, num_cols_, alpha, temp_a.Data(), 1,\n               temp_b.Data(), 1, data_, stride_);\n  } else {\n    const OtherReal *a_data = a.Data(), *b_data = b.Data();\n    Real *row_data = data_;\n    for (MatrixIndexT i = 0; i < num_rows_; i++, row_data += stride_) {\n      BaseFloat alpha_ai = alpha * a_data[i];\n      for (MatrixIndexT j = 0; j < num_cols_; j++)\n        row_data[j] += alpha_ai * b_data[j];\n    }\n  }\n}\n\n// instantiate the template above.\ntemplate\nvoid MatrixBase<float>::AddVecVec(const float alpha,\n                                  const VectorBase<double> &a,\n                                  const VectorBase<double> &b);\ntemplate\nvoid MatrixBase<double>::AddVecVec(const double alpha,\n                                   const VectorBase<float> &a,\n                                   const VectorBase<float> &b);\n\ntemplate<>\ntemplate<>\nvoid MatrixBase<double>::AddVecVec(const double alpha,\n                                   const VectorBase<double> &a,\n                                   const VectorBase<double> &rb) {\n  KALDI_ASSERT(a.Dim() == num_rows_ && rb.Dim() == num_cols_);\n  if (num_rows_ == 0) return;\n  cblas_Xger(a.Dim(), rb.Dim(), alpha, a.Data(), 1, rb.Data(),\n             1, data_, stride_);\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMatMat(const Real alpha,\n                                  const MatrixBase<Real>& A,\n                                  MatrixTransposeType transA,\n                                  const MatrixBase<Real>& B,\n                                  MatrixTransposeType transB,\n                                  const Real beta) {\n  KALDI_ASSERT((transA == kNoTrans && transB == kNoTrans && A.num_cols_ ==\nB.num_rows_ && A.num_rows_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kTrans && transB == kNoTrans && A.num_rows_ ==\nB.num_rows_ && A.num_cols_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kNoTrans && transB == kTrans && A.num_cols_ ==\nB.num_cols_ && A.num_rows_ == num_rows_ && B.num_rows_ == num_cols_)\n               || (transA == kTrans && transB == kTrans && A.num_rows_ ==\nB.num_cols_ && A.num_cols_ == num_rows_ && B.num_rows_ == num_cols_));\n  KALDI_ASSERT(&A !=  this && &B != this);\n  if (num_rows_ == 0) return;\n  cblas_Xgemm(alpha, transA, A.data_, A.num_rows_, A.num_cols_, A.stride_,\n              transB, B.data_, B.stride_, beta, data_, num_rows_, num_cols_,\nstride_);\n\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::SetMatMatDivMat(const MatrixBase<Real>& A,\n                                       const MatrixBase<Real>& B,\n                                       const MatrixBase<Real>& C) {\n  KALDI_ASSERT(A.NumRows() == B.NumRows() && A.NumCols() == B.NumCols());\n  KALDI_ASSERT(A.NumRows() == C.NumRows() && A.NumCols() == C.NumCols());\n  for (int32 r = 0; r < A.NumRows(); r++) { // each frame...\n    for (int32 c = 0; c < A.NumCols(); c++) {\n      BaseFloat i = C(r, c), o = B(r, c), od = A(r, c),\n          id;\n      if (i != 0.0) {\n        id = od * (o / i); /// o / i is either zero or \"scale\".\n      } else {\n        id = od; /// Just imagine the scale was 1.0.  This is somehow true in\n        /// expectation; anyway, this case should basically never happen so it\ndoesn't\n        /// really matter.\n      }\n      (*this)(r, c) = id;\n    }\n  }\n}\n*/\n\n// template<typename Real>\n// void MatrixBase<Real>::CopyLowerToUpper() {\n// KALDI_ASSERT(num_rows_ == num_cols_);\n// Real *data = data_;\n// MatrixIndexT num_rows = num_rows_, stride = stride_;\n// for (int32 i = 0; i < num_rows; i++)\n// for (int32 j = 0; j < i; j++)\n// data[j * stride + i ] = data[i * stride + j];\n//}\n\n\n// template<typename Real>\n// void MatrixBase<Real>::CopyUpperToLower() {\n// KALDI_ASSERT(num_rows_ == num_cols_);\n// Real *data = data_;\n// MatrixIndexT num_rows = num_rows_, stride = stride_;\n// for (int32 i = 0; i < num_rows; i++)\n// for (int32 j = 0; j < i; j++)\n// data[i * stride + j] = data[j * stride + i];\n//}\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::SymAddMat2(const Real alpha,\n                                  const MatrixBase<Real> &A,\n                                  MatrixTransposeType transA,\n                                  Real beta) {\n  KALDI_ASSERT(num_rows_ == num_cols_ &&\n               ((transA == kNoTrans && A.num_rows_ == num_rows_) ||\n                (transA == kTrans && A.num_cols_ == num_cols_)));\n  KALDI_ASSERT(A.data_ != data_);\n  if (num_rows_ == 0) return;\n\n  /// When the matrix dimension(this->num_rows_) is not less than 56\n  /// and the transpose type transA == kTrans, the cblas_Xsyrk(...)\n  /// function will produce NaN in the output. This is a bug in the\n  /// ATLAS library. To overcome this, the AddMatMat function, which calls\n  /// cblas_Xgemm(...) rather than cblas_Xsyrk(...), is used in this special\n  /// situation.\n  /// Wei Shi: Note this bug is observed for single precision matrix\n  /// on a 64-bit machine\n#ifdef HAVE_ATLAS\n  if (transA == kTrans && num_rows_ >= 56) {\n    this->AddMatMat(alpha, A, kTrans, A, kNoTrans, beta);\n    return;\n  }\n#endif // HAVE_ATLAS\n\n  MatrixIndexT A_other_dim = (transA == kNoTrans ? A.num_cols_ : A.num_rows_);\n\n  // This function call is hard-coded to update the lower triangle.\n  cblas_Xsyrk(transA, num_rows_, A_other_dim, alpha, A.Data(),\n              A.Stride(), beta, this->data_, this->stride_);\n}\n\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMatSmat(const Real alpha,\n                                  const MatrixBase<Real> &A,\n                                  MatrixTransposeType transA,\n                                  const MatrixBase<Real> &B,\n                                  MatrixTransposeType transB,\n                                  const Real beta) {\n  KALDI_ASSERT((transA == kNoTrans && transB == kNoTrans && A.num_cols_ ==\nB.num_rows_ && A.num_rows_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kTrans && transB == kNoTrans && A.num_rows_ ==\nB.num_rows_ && A.num_cols_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kNoTrans && transB == kTrans && A.num_cols_ ==\nB.num_cols_ && A.num_rows_ == num_rows_ && B.num_rows_ == num_cols_)\n               || (transA == kTrans && transB == kTrans && A.num_rows_ ==\nB.num_cols_ && A.num_cols_ == num_rows_ && B.num_rows_ == num_cols_));\n  KALDI_ASSERT(&A !=  this && &B != this);\n\n  // We iterate over the columns of B.\n\n  MatrixIndexT Astride = A.stride_, Bstride = B.stride_, stride = this->stride_,\n      Arows = A.num_rows_, Acols = A.num_cols_;\n  Real *data = this->data_, *Adata = A.data_, *Bdata = B.data_;\n  MatrixIndexT num_cols = this->num_cols_;\n  if (transB == kNoTrans) {\n    // Iterate over the columns of *this and of B.\n    for (MatrixIndexT c = 0; c < num_cols; c++) {\n      // for each column of *this, do\n      // [this column] = [alpha * A * this column of B] + [beta * this column]\n      Xgemv_sparsevec(transA, Arows, Acols, alpha, Adata, Astride,\n                      Bdata + c, Bstride, beta, data + c, stride);\n    }\n  } else {\n    // Iterate over the columns of *this and the rows of B.\n    for (MatrixIndexT c = 0; c < num_cols; c++) {\n      // for each column of *this, do\n      // [this column] = [alpha * A * this row of B] + [beta * this column]\n      Xgemv_sparsevec(transA, Arows, Acols, alpha, Adata, Astride,\n                      Bdata + (c * Bstride), 1, beta, data + c, stride);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddSmatMat(const Real alpha,\n                                  const MatrixBase<Real> &A,\n                                  MatrixTransposeType transA,\n                                  const MatrixBase<Real> &B,\n                                  MatrixTransposeType transB,\n                                  const Real beta) {\n  KALDI_ASSERT((transA == kNoTrans && transB == kNoTrans && A.num_cols_ ==\nB.num_rows_ && A.num_rows_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kTrans && transB == kNoTrans && A.num_rows_ ==\nB.num_rows_ && A.num_cols_ == num_rows_ && B.num_cols_ == num_cols_)\n               || (transA == kNoTrans && transB == kTrans && A.num_cols_ ==\nB.num_cols_ && A.num_rows_ == num_rows_ && B.num_rows_ == num_cols_)\n               || (transA == kTrans && transB == kTrans && A.num_rows_ ==\nB.num_cols_ && A.num_cols_ == num_rows_ && B.num_rows_ == num_cols_));\n  KALDI_ASSERT(&A !=  this && &B != this);\n\n  MatrixIndexT Astride = A.stride_, Bstride = B.stride_, stride = this->stride_,\n      Brows = B.num_rows_, Bcols = B.num_cols_;\n  MatrixTransposeType invTransB = (transB == kTrans ? kNoTrans : kTrans);\n  Real *data = this->data_, *Adata = A.data_, *Bdata = B.data_;\n  MatrixIndexT num_rows = this->num_rows_;\n  if (transA == kNoTrans) {\n    // Iterate over the rows of *this and of A.\n    for (MatrixIndexT r = 0; r < num_rows; r++) {\n      // for each row of *this, do\n      // [this row] = [alpha * (this row of A) * B^T] + [beta * this row]\n      Xgemv_sparsevec(invTransB, Brows, Bcols, alpha, Bdata, Bstride,\n                      Adata + (r * Astride), 1, beta, data + (r * stride), 1);\n    }\n  } else {\n    // Iterate over the rows of *this and the columns of A.\n    for (MatrixIndexT r = 0; r < num_rows; r++) {\n      // for each row of *this, do\n      // [this row] = [alpha * (this column of A) * B^T] + [beta * this row]\n      Xgemv_sparsevec(invTransB, Brows, Bcols, alpha, Bdata, Bstride,\n                      Adata + r, Astride, beta, data + (r * stride), 1);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddSpSp(const Real alpha, const SpMatrix<Real> &A_in,\n                                const SpMatrix<Real> &B_in, const Real beta) {\n  MatrixIndexT sz = num_rows_;\n  KALDI_ASSERT(sz == num_cols_ && sz == A_in.NumRows() && sz == B_in.NumRows());\n\n  Matrix<Real> A(A_in), B(B_in);\n  // CblasLower or CblasUpper would work below as symmetric matrix is copied\n  // fully (to save work, we used the matrix constructor from SpMatrix).\n  // CblasLeft means A is on the left: C <-- alpha A B + beta C\n  if (sz == 0) return;\n  cblas_Xsymm(alpha, sz, A.data_, A.stride_, B.data_, B.stride_, beta, data_,\nstride_);\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMat(const Real alpha, const MatrixBase<Real>& A,\n                               MatrixTransposeType transA) {\n  if (&A == this) {\n    if (transA == kNoTrans) {\n      Scale(alpha + 1.0);\n    } else {\n      KALDI_ASSERT(num_rows_ == num_cols_ && \"AddMat: adding to self\n(transposed): not symmetric.\");\n      Real *data = data_;\n      if (alpha == 1.0) {  // common case-- handle separately.\n        for (MatrixIndexT row = 0; row < num_rows_; row++) {\n          for (MatrixIndexT col = 0; col < row; col++) {\n            Real *lower = data + (row * stride_) + col, *upper = data + (col\n                                                                          *\nstride_) + row;\n            Real sum = *lower + *upper;\n            *lower = *upper = sum;\n          }\n          *(data + (row * stride_) + row) *= 2.0;  // diagonal.\n        }\n      } else {\n        for (MatrixIndexT row = 0; row < num_rows_; row++) {\n          for (MatrixIndexT col = 0; col < row; col++) {\n            Real *lower = data + (row * stride_) + col, *upper = data + (col\n                                                                          *\nstride_) + row;\n            Real lower_tmp = *lower;\n            *lower += alpha * *upper;\n            *upper += alpha * lower_tmp;\n          }\n          *(data + (row * stride_) + row) *= (1.0 + alpha);  // diagonal.\n        }\n      }\n    }\n  } else {\n    int aStride = (int) A.stride_, stride = stride_;\n    Real *adata = A.data_, *data = data_;\n    if (transA == kNoTrans) {\n      KALDI_ASSERT(A.num_rows_ == num_rows_ && A.num_cols_ == num_cols_);\n      if (num_rows_ == 0) return;\n      for (MatrixIndexT row = 0; row < num_rows_; row++, adata += aStride,\n               data += stride) {\n        cblas_Xaxpy(num_cols_, alpha, adata, 1, data, 1);\n      }\n    } else {\n      KALDI_ASSERT(A.num_cols_ == num_rows_ && A.num_rows_ == num_cols_);\n      if (num_rows_ == 0) return;\n      for (MatrixIndexT row = 0; row < num_rows_; row++, adata++, data +=\nstride)\n        cblas_Xaxpy(num_cols_, alpha, adata, aStride, data, 1);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddSmat(Real alpha, const SparseMatrix<Real> &A,\n                               MatrixTransposeType trans) {\n  if (trans == kNoTrans) {\n    KALDI_ASSERT(NumRows() == A.NumRows());\n    KALDI_ASSERT(NumCols() == A.NumCols());\n    MatrixIndexT a_num_rows = A.NumRows();\n    for (MatrixIndexT i = 0; i < a_num_rows; ++i) {\n      const SparseVector<Real> &row = A.Row(i);\n      MatrixIndexT num_elems = row.NumElements();\n      for (MatrixIndexT id = 0; id < num_elems; ++id) {\n        (*this)(i, row.GetElement(id).first) += alpha\n            * row.GetElement(id).second;\n      }\n    }\n  } else {\n    KALDI_ASSERT(NumRows() == A.NumCols());\n    KALDI_ASSERT(NumCols() == A.NumRows());\n    MatrixIndexT a_num_rows = A.NumRows();\n    for (MatrixIndexT i = 0; i < a_num_rows; ++i) {\n      const SparseVector<Real> &row = A.Row(i);\n      MatrixIndexT num_elems = row.NumElements();\n      for (MatrixIndexT id = 0; id < num_elems; ++id) {\n        (*this)(row.GetElement(id).first, i) += alpha\n            * row.GetElement(id).second;\n      }\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddSmatMat(Real alpha, const SparseMatrix<Real> &A,\n                                  MatrixTransposeType transA,\n                                  const MatrixBase<Real> &B, Real beta) {\n  if (transA == kNoTrans) {\n    KALDI_ASSERT(NumRows() == A.NumRows());\n    KALDI_ASSERT(NumCols() == B.NumCols());\n    KALDI_ASSERT(A.NumCols() == B.NumRows());\n\n    this->Scale(beta);\n    MatrixIndexT a_num_rows = A.NumRows(),\n        this_num_cols = this->NumCols();\n    for (MatrixIndexT i = 0; i < a_num_rows; ++i) {\n      Real *this_row_i = this->RowData(i);\n      const SparseVector<Real> &A_row_i = A.Row(i);\n      MatrixIndexT num_elems = A_row_i.NumElements();\n      for (MatrixIndexT e = 0; e < num_elems; ++e) {\n        const std::pair<MatrixIndexT, Real> &p = A_row_i.GetElement(e);\n        MatrixIndexT k = p.first;\n        Real alpha_A_ik = alpha * p.second;\n        const Real *b_row_k = B.RowData(k);\n        cblas_Xaxpy(this_num_cols, alpha_A_ik, b_row_k, 1,\n                    this_row_i, 1);\n        //for (MatrixIndexT j = 0; j < this_num_cols; ++j)\n        //  this_row_i[j] += alpha_A_ik * b_row_k[j];\n      }\n    }\n  } else {\n    KALDI_ASSERT(NumRows() == A.NumCols());\n    KALDI_ASSERT(NumCols() == B.NumCols());\n    KALDI_ASSERT(A.NumRows() == B.NumRows());\n\n    this->Scale(beta);\n    Matrix<Real> buf(NumRows(), NumCols(), kSetZero);\n    MatrixIndexT a_num_rows = A.NumRows(),\n        this_num_cols = this->NumCols();\n    for (int k = 0; k < a_num_rows; ++k) {\n      const Real *b_row_k = B.RowData(k);\n      const SparseVector<Real> &A_row_k = A.Row(k);\n      MatrixIndexT num_elems = A_row_k.NumElements();\n      for (MatrixIndexT e = 0; e < num_elems; ++e) {\n        const std::pair<MatrixIndexT, Real> &p = A_row_k.GetElement(e);\n        MatrixIndexT i = p.first;\n        Real alpha_A_ki = alpha * p.second;\n        Real *this_row_i = this->RowData(i);\n        cblas_Xaxpy(this_num_cols, alpha_A_ki, b_row_k, 1,\n                    this_row_i, 1);\n        //for (MatrixIndexT j = 0; j < this_num_cols; ++j)\n        // this_row_i[j] += alpha_A_ki * b_row_k[j];\n      }\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMatSmat(Real alpha, const MatrixBase<Real> &A,\n                                  const SparseMatrix<Real> &B,\n                                  MatrixTransposeType transB, Real beta) {\n  if (transB == kNoTrans) {\n    KALDI_ASSERT(NumRows() == A.NumRows());\n    KALDI_ASSERT(NumCols() == B.NumCols());\n    KALDI_ASSERT(A.NumCols() == B.NumRows());\n\n    this->Scale(beta);\n    MatrixIndexT b_num_rows = B.NumRows(),\n        this_num_rows = this->NumRows();\n    // Iterate over the rows of sparse matrix B and columns of A.\n    for (MatrixIndexT k = 0; k < b_num_rows; ++k) {\n      const SparseVector<Real> &B_row_k = B.Row(k);\n      MatrixIndexT num_elems = B_row_k.NumElements();\n      const Real *a_col_k = A.Data() + k;\n      for (MatrixIndexT e = 0; e < num_elems; ++e) {\n        const std::pair<MatrixIndexT, Real> &p = B_row_k.GetElement(e);\n        MatrixIndexT j = p.first;\n        Real alpha_B_kj = alpha * p.second;\n        Real *this_col_j = this->Data() + j;\n        // Add to entire 'j'th column of *this at once using cblas_Xaxpy.\n        // pass stride to write a colmun as matrices are stored in row major\norder.\n        cblas_Xaxpy(this_num_rows, alpha_B_kj, a_col_k, A.stride_,\n                    this_col_j, this->stride_);\n        //for (MatrixIndexT i = 0; i < this_num_rows; ++i)\n        // this_col_j[i*this->stride_] +=  alpha_B_kj * a_col_k[i*A.stride_];\n      }\n    }\n  } else {\n    KALDI_ASSERT(NumRows() == A.NumRows());\n    KALDI_ASSERT(NumCols() == B.NumRows());\n    KALDI_ASSERT(A.NumCols() == B.NumCols());\n\n    this->Scale(beta);\n    MatrixIndexT b_num_rows = B.NumRows(),\n        this_num_rows = this->NumRows();\n    // Iterate over the rows of sparse matrix B and columns of *this.\n    for (MatrixIndexT j = 0; j < b_num_rows; ++j) {\n      const SparseVector<Real> &B_row_j = B.Row(j);\n      MatrixIndexT num_elems = B_row_j.NumElements();\n      Real *this_col_j = this->Data() + j;\n      for (MatrixIndexT e = 0; e < num_elems; ++e) {\n        const std::pair<MatrixIndexT, Real> &p = B_row_j.GetElement(e);\n        MatrixIndexT k = p.first;\n        Real alpha_B_jk = alpha * p.second;\n        const Real *a_col_k = A.Data() + k;\n        // Add to entire 'j'th column of *this at once using cblas_Xaxpy.\n        // pass stride to write a column as matrices are stored in row major\norder.\n        cblas_Xaxpy(this_num_rows, alpha_B_jk, a_col_k, A.stride_,\n                    this_col_j, this->stride_);\n        //for (MatrixIndexT i = 0; i < this_num_rows; ++i)\n        // this_col_j[i*this->stride_] +=  alpha_B_jk * a_col_k[i*A.stride_];\n      }\n    }\n  }\n}\n\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::AddSp(const Real alpha, const SpMatrix<OtherReal> &S) {\n  KALDI_ASSERT(S.NumRows() == NumRows() && S.NumRows() == NumCols());\n  Real *data = data_; const OtherReal *sdata = S.Data();\n  MatrixIndexT num_rows = NumRows(), stride = Stride();\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    for (MatrixIndexT j = 0; j < i; j++, sdata++) {\n      data[i*stride + j] += alpha * *sdata;\n      data[j*stride + i] += alpha * *sdata;\n    }\n    data[i*stride + i] += alpha * *sdata++;\n  }\n}\n\n// instantiate the template above.\ntemplate\nvoid MatrixBase<float>::AddSp(const float alpha, const SpMatrix<float> &S);\ntemplate\nvoid MatrixBase<double>::AddSp(const double alpha, const SpMatrix<double> &S);\ntemplate\nvoid MatrixBase<float>::AddSp(const float alpha, const SpMatrix<double> &S);\ntemplate\nvoid MatrixBase<double>::AddSp(const double alpha, const SpMatrix<float> &S);\n\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddDiagVecMat(\n    const Real alpha, const VectorBase<Real> &v,\n    const MatrixBase<Real> &M,\n    MatrixTransposeType transM,\n    Real beta) {\n  if (beta != 1.0) this->Scale(beta);\n\n  if (transM == kNoTrans) {\n    KALDI_ASSERT(SameDim(*this, M));\n  } else {\n    KALDI_ASSERT(M.NumRows() == NumCols() && M.NumCols() == NumRows());\n  }\n  KALDI_ASSERT(v.Dim() == this->NumRows());\n\n  MatrixIndexT M_row_stride = M.Stride(), M_col_stride = 1, stride = stride_,\n      num_rows = num_rows_, num_cols = num_cols_;\n  if (transM == kTrans) std::swap(M_row_stride, M_col_stride);\n  Real *data = data_;\n  const Real *Mdata = M.Data(), *vdata = v.Data();\n  if (num_rows_ == 0) return;\n  for (MatrixIndexT i = 0; i < num_rows; i++, data += stride, Mdata +=\nM_row_stride, vdata++)\n    cblas_Xaxpy(num_cols, alpha * *vdata, Mdata, M_col_stride, data, 1);\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMatDiagVec(\n    const Real alpha,\n    const MatrixBase<Real> &M, MatrixTransposeType transM,\n    VectorBase<Real> &v,\n    Real beta) {\n\n  if (beta != 1.0) this->Scale(beta);\n\n  if (transM == kNoTrans) {\n    KALDI_ASSERT(SameDim(*this, M));\n  } else {\n    KALDI_ASSERT(M.NumRows() == NumCols() && M.NumCols() == NumRows());\n  }\n  KALDI_ASSERT(v.Dim() == this->NumCols());\n\n  MatrixIndexT M_row_stride = M.Stride(),\n               M_col_stride = 1,\n               stride = stride_,\n               num_rows = num_rows_,\n               num_cols = num_cols_;\n\n  if (transM == kTrans)\n    std::swap(M_row_stride, M_col_stride);\n\n  Real *data = data_;\n  const Real *Mdata = M.Data(), *vdata = v.Data();\n  if (num_rows_ == 0) return;\n  for (MatrixIndexT i = 0; i < num_rows; i++){\n      for(MatrixIndexT j = 0; j < num_cols; j ++ ){\n          data[i*stride + j] += alpha * vdata[j] * Mdata[i*M_row_stride +\nj*M_col_stride];\n      }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddMatMatElements(const Real alpha,\n                                         const MatrixBase<Real>& A,\n                                         const MatrixBase<Real>& B,\n                                         const Real beta) {\n    KALDI_ASSERT(A.NumRows() == B.NumRows() && A.NumCols() == B.NumCols());\n    KALDI_ASSERT(A.NumRows() == NumRows() && A.NumCols() == NumCols());\n    Real *data = data_;\n    const Real *dataA = A.Data();\n    const Real *dataB = B.Data();\n\n    for (MatrixIndexT i = 0; i < num_rows_; i++) {\n        for (MatrixIndexT j = 0; j < num_cols_; j++) {\n            data[j] = beta*data[j] + alpha*dataA[j]*dataB[j];\n        }\n        data += Stride();\n        dataA += A.Stride();\n        dataB += B.Stride();\n    }\n}\n\n#if !defined(HAVE_ATLAS) && !defined(USE_KALDI_SVD)\n// ****************************************************************************\n// ****************************************************************************\ntemplate<typename Real>\nvoid MatrixBase<Real>::LapackGesvd(VectorBase<Real> *s, MatrixBase<Real> *U_in,\n                                   MatrixBase<Real> *V_in) {\n  KALDI_ASSERT(s != NULL && U_in != this && V_in != this);\n\n  Matrix<Real> tmpU, tmpV;\n  if (U_in == NULL) tmpU.Resize(this->num_rows_, 1);  // work-space if U_in\nempty.\n  if (V_in == NULL) tmpV.Resize(1, this->num_cols_);  // work-space if V_in\nempty.\n\n  /// Implementation notes:\n  /// Lapack works in column-order, therefore the dimensions of *this are\n  /// swapped as well as the U and V matrices.\n\n  KaldiBlasInt M   = num_cols_;\n  KaldiBlasInt N   = num_rows_;\n  KaldiBlasInt LDA = Stride();\n\n  KALDI_ASSERT(N>=M);  // NumRows >= columns.\n\n  if (U_in) {\n    KALDI_ASSERT((int)U_in->num_rows_ == N && (int)U_in->num_cols_ == M);\n  }\n  if (V_in) {\n    KALDI_ASSERT((int)V_in->num_rows_ == M && (int)V_in->num_cols_ == M);\n  }\n  KALDI_ASSERT((int)s->Dim() == std::min(M, N));\n\n  MatrixBase<Real> *U = (U_in ? U_in : &tmpU);\n  MatrixBase<Real> *V = (V_in ? V_in : &tmpV);\n\n  KaldiBlasInt V_stride      = V->Stride();\n  KaldiBlasInt U_stride      = U->Stride();\n\n  // Original LAPACK recipe\n  // KaldiBlasInt l_work = std::max(std::max<long int>\n  //   (1, 3*std::min(M, N)+std::max(M, N)), 5*std::min(M, N))*2;\n  KaldiBlasInt l_work = -1;\n  Real   work_query;\n  KaldiBlasInt result;\n\n  // query for work space\n  char *u_job = const_cast<char*>(U_in ? \"s\" : \"N\");  // \"s\" == skinny, \"N\" ==\n\"none.\"\n  char *v_job = const_cast<char*>(V_in ? \"s\" : \"N\");  // \"s\" == skinny, \"N\" ==\n\"none.\"\n  clapack_Xgesvd(v_job, u_job,\n                 &M, &N, data_, &LDA,\n                 s->Data(),\n                 V->Data(), &V_stride,\n                 U->Data(), &U_stride,\n                 &work_query, &l_work,\n                 &result);\n\n  KALDI_ASSERT(result >= 0 && \"Call to CLAPACK dgesvd_ called with wrong\narguments\");\n\n  l_work = static_cast<KaldiBlasInt>(work_query);\n  Real *p_work;\n  void *temp;\n  if ((p_work = static_cast<Real*>(\n          KALDI_MEMALIGN(16, sizeof(Real)*l_work, &temp))) == NULL)\n    throw std::bad_alloc();\n\n  // perform svd\n  clapack_Xgesvd(v_job, u_job,\n                 &M, &N, data_, &LDA,\n                 s->Data(),\n                 V->Data(), &V_stride,\n                 U->Data(), &U_stride,\n                 p_work, &l_work,\n                 &result);\n\n  KALDI_ASSERT(result >= 0 && \"Call to CLAPACK dgesvd_ called with wrong\narguments\");\n\n  if (result != 0) {\n    KALDI_WARN << \"CLAPACK sgesvd_ : some weird convergence not satisfied\";\n  }\n  KALDI_MEMALIGN_FREE(p_work);\n}\n\n#endif\n*/\n// Copy constructor.  Copies data to newly allocated memory.\ntemplate <typename Real>\nMatrix<Real>::Matrix(const MatrixBase<Real> &M,\n                     MatrixTransposeType trans /*=kNoTrans*/)\n    : MatrixBase<Real>() {\n    if (trans == kNoTrans) {\n        Resize(M.num_rows_, M.num_cols_);\n        this->CopyFromMat(M);\n    } else {\n        Resize(M.num_cols_, M.num_rows_);\n        this->CopyFromMat(M, kTrans);\n    }\n}\n\n// Copy constructor.  Copies data to newly allocated memory.\ntemplate <typename Real>\nMatrix<Real>::Matrix(const Matrix<Real> &M) : MatrixBase<Real>() {\n    Resize(M.num_rows_, M.num_cols_);\n    this->CopyFromMat(M);\n}\n\n/// Copy constructor from another type.\ntemplate <typename Real>\ntemplate <typename OtherReal>\nMatrix<Real>::Matrix(const MatrixBase<OtherReal> &M, MatrixTransposeType trans)\n    : MatrixBase<Real>() {\n    if (trans == kNoTrans) {\n        Resize(M.NumRows(), M.NumCols());\n        this->CopyFromMat(M);\n    } else {\n        Resize(M.NumCols(), M.NumRows());\n        this->CopyFromMat(M, kTrans);\n    }\n}\n\n// Instantiate this constructor for float->double and double->float.\ntemplate Matrix<float>::Matrix(const MatrixBase<double> &M,\n                               MatrixTransposeType trans);\ntemplate Matrix<double>::Matrix(const MatrixBase<float> &M,\n                                MatrixTransposeType trans);\n\ntemplate <typename Real>\ninline void Matrix<Real>::Init(const MatrixIndexT rows,\n                               const MatrixIndexT cols,\n                               const MatrixStrideType stride_type) {\n    if (rows * cols == 0) {\n        KALDI_ASSERT(rows == 0 && cols == 0);\n        this->num_rows_ = 0;\n        this->num_cols_ = 0;\n        this->stride_ = 0;\n        this->data_ = NULL;\n        return;\n    }\n    KALDI_ASSERT(rows > 0 && cols > 0);\n    MatrixIndexT skip, stride;\n    size_t size;\n    void *data;  // aligned memory block\n    void *temp;  // memory block to be really freed\n\n    // compute the size of skip and real cols\n    skip = ((16 / sizeof(Real)) - cols % (16 / sizeof(Real))) %\n           (16 / sizeof(Real));\n    stride = cols + skip;\n    size =\n        static_cast<size_t>(rows) * static_cast<size_t>(stride) * sizeof(Real);\n\n    // allocate the memory and set the right dimensions and parameters\n    if (NULL != (data = KALDI_MEMALIGN(16, size, &temp))) {\n        MatrixBase<Real>::data_ = static_cast<Real *>(data);\n        MatrixBase<Real>::num_rows_ = rows;\n        MatrixBase<Real>::num_cols_ = cols;\n        MatrixBase<Real>::stride_ =\n            (stride_type == kDefaultStride ? stride : cols);\n    } else {\n        throw std::bad_alloc();\n    }\n}\n\ntemplate <typename Real>\nvoid Matrix<Real>::Resize(const MatrixIndexT rows,\n                          const MatrixIndexT cols,\n                          MatrixResizeType resize_type,\n                          MatrixStrideType stride_type) {\n    // the next block uses recursion to handle what we have to do if\n    // resize_type == kCopyData.\n    if (resize_type == kCopyData) {\n        if (this->data_ == NULL || rows == 0)\n            resize_type = kSetZero;  // nothing to copy.\n        else if (rows == this->num_rows_ && cols == this->num_cols_ &&\n                 (stride_type == kDefaultStride ||\n                  this->stride_ == this->num_cols_)) {\n            return;\n        }  // nothing to do.\n        else {\n            // set tmp to a matrix of the desired size; if new matrix\n            // is bigger in some dimension, zero it.\n            MatrixResizeType new_resize_type =\n                (rows > this->num_rows_ || cols > this->num_cols_) ? kSetZero\n                                                                   : kUndefined;\n            Matrix<Real> tmp(rows, cols, new_resize_type, stride_type);\n            MatrixIndexT rows_min = std::min(rows, this->num_rows_),\n                         cols_min = std::min(cols, this->num_cols_);\n            tmp.Range(0, rows_min, 0, cols_min)\n                .CopyFromMat(this->Range(0, rows_min, 0, cols_min));\n            tmp.Swap(this);\n            // and now let tmp go out of scope, deleting what was in *this.\n            return;\n        }\n    }\n    // At this point, resize_type == kSetZero or kUndefined.\n\n    if (MatrixBase<Real>::data_ != NULL) {\n        if (rows == MatrixBase<Real>::num_rows_ &&\n            cols == MatrixBase<Real>::num_cols_) {\n            if (resize_type == kSetZero) this->SetZero();\n            return;\n        } else\n            Destroy();\n    }\n    Init(rows, cols, stride_type);\n    if (resize_type == kSetZero) MatrixBase<Real>::SetZero();\n}\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid MatrixBase<Real>::CopyFromMat(const MatrixBase<OtherReal> &M,\n                                   MatrixTransposeType Trans) {\n    if (sizeof(Real) == sizeof(OtherReal) &&\n        static_cast<const void *>(M.Data()) ==\n            static_cast<const void *>(this->Data())) {\n        // CopyFromMat called on same data.  Nothing to do (except sanity\n        // checks).\n        KALDI_ASSERT(Trans == kNoTrans && M.NumRows() == NumRows() &&\n                     M.NumCols() == NumCols() && M.Stride() == Stride());\n        return;\n    }\n    if (Trans == kNoTrans) {\n        KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == M.NumCols());\n        for (MatrixIndexT i = 0; i < num_rows_; i++)\n            (*this).Row(i).CopyFromVec(M.Row(i));\n    } else {\n        KALDI_ASSERT(num_cols_ == M.NumRows() && num_rows_ == M.NumCols());\n        int32 this_stride = stride_, other_stride = M.Stride();\n        Real *this_data = data_;\n        const OtherReal *other_data = M.Data();\n        for (MatrixIndexT i = 0; i < num_rows_; i++)\n            for (MatrixIndexT j = 0; j < num_cols_; j++)\n                this_data[i * this_stride + j] =\n                    other_data[j * other_stride + i];\n    }\n}\n\n// template instantiations.\ntemplate void MatrixBase<float>::CopyFromMat(const MatrixBase<double> &M,\n                                             MatrixTransposeType Trans);\ntemplate void MatrixBase<double>::CopyFromMat(const MatrixBase<float> &M,\n                                              MatrixTransposeType Trans);\ntemplate void MatrixBase<float>::CopyFromMat(const MatrixBase<float> &M,\n                                             MatrixTransposeType Trans);\ntemplate void MatrixBase<double>::CopyFromMat(const MatrixBase<double> &M,\n                                              MatrixTransposeType Trans);\n\n/*\n// Specialize the template for CopyFromSp for float, float.\ntemplate<>\ntemplate<>\nvoid MatrixBase<float>::CopyFromSp(const SpMatrix<float> & M) {\n  KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == num_rows_);\n  MatrixIndexT num_rows = num_rows_, stride = stride_;\n  const float *Mdata = M.Data();\n  float *row_data = data_, *col_data = data_;\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    cblas_scopy(i+1, Mdata, 1, row_data, 1); // copy to the row.\n    cblas_scopy(i, Mdata, 1, col_data, stride); // copy to the column.\n    Mdata += i+1;\n    row_data += stride;\n    col_data += 1;\n  }\n}\n\n// Specialize the template for CopyFromSp for double, double.\ntemplate<>\ntemplate<>\nvoid MatrixBase<double>::CopyFromSp(const SpMatrix<double> & M) {\n  KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == num_rows_);\n  MatrixIndexT num_rows = num_rows_, stride = stride_;\n  const double *Mdata = M.Data();\n  double *row_data = data_, *col_data = data_;\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    cblas_dcopy(i+1, Mdata, 1, row_data, 1); // copy to the row.\n    cblas_dcopy(i, Mdata, 1, col_data, stride); // copy to the column.\n    Mdata += i+1;\n    row_data += stride;\n    col_data += 1;\n  }\n}\n\n\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::CopyFromSp(const SpMatrix<OtherReal> & M) {\n  KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == num_rows_);\n  // MORE EFFICIENT IF LOWER TRIANGULAR!  Reverse code otherwise.\n  for (MatrixIndexT i = 0; i < num_rows_; i++) {\n    for (MatrixIndexT j = 0; j < i; j++) {\n      (*this)(j, i)  = (*this)(i, j) = M(i, j);\n    }\n    (*this)(i, i) = M(i, i);\n  }\n}\n\n// Instantiate this function\ntemplate\nvoid MatrixBase<float>::CopyFromSp(const SpMatrix<double> & M);\ntemplate\nvoid MatrixBase<double>::CopyFromSp(const SpMatrix<float> & M);\n\n\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::CopyFromTp(const TpMatrix<OtherReal> & M,\n                                  MatrixTransposeType Trans) {\n  if (Trans == kNoTrans) {\n    KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == num_rows_);\n    SetZero();\n    Real *out_i = data_;\n    const OtherReal *in_i = M.Data();\n    for (MatrixIndexT i = 0; i < num_rows_; i++, out_i += stride_, in_i += i) {\n      for (MatrixIndexT j = 0; j <= i; j++)\n        out_i[j] = in_i[j];\n    }\n  } else {\n    SetZero();\n    KALDI_ASSERT(num_rows_ == M.NumRows() && num_cols_ == num_rows_);\n    MatrixIndexT stride = stride_;\n    Real *out_i = data_;\n    const OtherReal *in_i = M.Data();\n    for (MatrixIndexT i = 0; i < num_rows_; i++, out_i ++, in_i += i) {\n      for (MatrixIndexT j = 0; j <= i; j++)\n        out_i[j*stride] = in_i[j];\n    }\n  }\n}\n\ntemplate\nvoid MatrixBase<float>::CopyFromTp(const TpMatrix<float> & M,\n                                   MatrixTransposeType trans);\ntemplate\nvoid MatrixBase<float>::CopyFromTp(const TpMatrix<double> & M,\n                                   MatrixTransposeType trans);\ntemplate\nvoid MatrixBase<double>::CopyFromTp(const TpMatrix<float> & M,\n                                    MatrixTransposeType trans);\ntemplate\nvoid MatrixBase<double>::CopyFromTp(const TpMatrix<double> & M,\n                                    MatrixTransposeType trans);\n\n*/\ntemplate <typename Real>\nvoid MatrixBase<Real>::CopyRowsFromVec(const VectorBase<Real> &rv) {\n    if (rv.Dim() == num_rows_ * num_cols_) {\n        if (stride_ == num_cols_) {\n            // one big copy operation.\n            const Real *rv_data = rv.Data();\n            std::memcpy(data_, rv_data, sizeof(Real) * num_rows_ * num_cols_);\n        } else {\n            const Real *rv_data = rv.Data();\n            for (MatrixIndexT r = 0; r < num_rows_; r++) {\n                Real *row_data = RowData(r);\n                for (MatrixIndexT c = 0; c < num_cols_; c++) {\n                    row_data[c] = rv_data[c];\n                }\n                rv_data += num_cols_;\n            }\n        }\n    } else if (rv.Dim() == num_cols_) {\n        const Real *rv_data = rv.Data();\n        for (MatrixIndexT r = 0; r < num_rows_; r++)\n            std::memcpy(RowData(r), rv_data, sizeof(Real) * num_cols_);\n    } else {\n        KALDI_ERR << \"Wrong sized arguments\";\n    }\n}\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid MatrixBase<Real>::CopyRowsFromVec(const VectorBase<OtherReal> &rv) {\n    if (rv.Dim() == num_rows_ * num_cols_) {\n        const OtherReal *rv_data = rv.Data();\n        for (MatrixIndexT r = 0; r < num_rows_; r++) {\n            Real *row_data = RowData(r);\n            for (MatrixIndexT c = 0; c < num_cols_; c++) {\n                row_data[c] = static_cast<Real>(rv_data[c]);\n            }\n            rv_data += num_cols_;\n        }\n    } else if (rv.Dim() == num_cols_) {\n        const OtherReal *rv_data = rv.Data();\n        Real *first_row_data = RowData(0);\n        for (MatrixIndexT c = 0; c < num_cols_; c++)\n            first_row_data[c] = rv_data[c];\n        for (MatrixIndexT r = 1; r < num_rows_; r++)\n            std::memcpy(RowData(r), first_row_data, sizeof(Real) * num_cols_);\n    } else {\n        KALDI_ERR << \"Wrong sized arguments.\";\n    }\n}\n\n\ntemplate void MatrixBase<float>::CopyRowsFromVec(const VectorBase<double> &rv);\ntemplate void MatrixBase<double>::CopyRowsFromVec(const VectorBase<float> &rv);\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::CopyColsFromVec(const VectorBase<Real> &rv) {\n    if (rv.Dim() == num_rows_ * num_cols_) {\n        const Real *v_inc_data = rv.Data();\n        Real *m_inc_data = data_;\n\n        for (MatrixIndexT c = 0; c < num_cols_; c++) {\n            for (MatrixIndexT r = 0; r < num_rows_; r++) {\n                m_inc_data[r * stride_] = v_inc_data[r];\n            }\n            v_inc_data += num_rows_;\n            m_inc_data++;\n        }\n    } else if (rv.Dim() == num_rows_) {\n        const Real *v_inc_data = rv.Data();\n        Real *m_inc_data = data_;\n        for (MatrixIndexT r = 0; r < num_rows_; r++) {\n            Real value = *(v_inc_data++);\n            for (MatrixIndexT c = 0; c < num_cols_; c++) m_inc_data[c] = value;\n            m_inc_data += stride_;\n        }\n    } else {\n        KALDI_ERR << \"Wrong size of arguments.\";\n    }\n}\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::CopyRowFromVec(const VectorBase<Real> &rv,\n                                      const MatrixIndexT row) {\n    KALDI_ASSERT(rv.Dim() == num_cols_ &&\n                 static_cast<UnsignedMatrixIndexT>(row) <\n                     static_cast<UnsignedMatrixIndexT>(num_rows_));\n\n    const Real *rv_data = rv.Data();\n    Real *row_data = RowData(row);\n\n    std::memcpy(row_data, rv_data, num_cols_ * sizeof(Real));\n}\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::CopyDiagFromVec(const VectorBase<Real> &rv) {\n  KALDI_ASSERT(rv.Dim() == std::min(num_cols_, num_rows_));\n  const Real *rv_data = rv.Data(), *rv_end = rv_data + rv.Dim();\n  Real *my_data = this->Data();\n  for (; rv_data != rv_end; rv_data++, my_data += (this->stride_+1))\n    *my_data = *rv_data;\n}*/\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::CopyColFromVec(const VectorBase<Real> &rv,\n                                      const MatrixIndexT col) {\n    KALDI_ASSERT(rv.Dim() == num_rows_ &&\n                 static_cast<UnsignedMatrixIndexT>(col) <\n                     static_cast<UnsignedMatrixIndexT>(num_cols_));\n\n    const Real *rv_data = rv.Data();\n    Real *col_data = data_ + col;\n\n    for (MatrixIndexT r = 0; r < num_rows_; r++)\n        col_data[r * stride_] = rv_data[r];\n}\n\n\ntemplate <typename Real>\nvoid Matrix<Real>::RemoveRow(MatrixIndexT i) {\n    KALDI_ASSERT(\n        static_cast<UnsignedMatrixIndexT>(i) <\n            static_cast<UnsignedMatrixIndexT>(MatrixBase<Real>::num_rows_) &&\n        \"Access out of matrix\");\n    for (MatrixIndexT j = i + 1; j < MatrixBase<Real>::num_rows_; j++)\n        MatrixBase<Real>::Row(j - 1).CopyFromVec(MatrixBase<Real>::Row(j));\n    MatrixBase<Real>::num_rows_--;\n}\n\ntemplate <typename Real>\nvoid Matrix<Real>::Destroy() {\n    // we need to free the data block if it was defined\n    if (NULL != MatrixBase<Real>::data_)\n        KALDI_MEMALIGN_FREE(MatrixBase<Real>::data_);\n    MatrixBase<Real>::data_ = NULL;\n    MatrixBase<Real>::num_rows_ = MatrixBase<Real>::num_cols_ =\n        MatrixBase<Real>::stride_ = 0;\n}\n\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::MulElements(const MatrixBase<Real> &a) {\n  KALDI_ASSERT(a.NumRows() == num_rows_ && a.NumCols() == num_cols_);\n\n  if (num_cols_ == stride_ && num_cols_ == a.stride_) {\n    mul_elements(num_rows_ * num_cols_, a.data_, data_);\n  } else {\n    MatrixIndexT a_stride = a.stride_, stride = stride_;\n    Real *data = data_, *a_data = a.data_;\n    for (MatrixIndexT i = 0; i < num_rows_; i++) {\n      mul_elements(num_cols_, a_data, data);\n      a_data += a_stride;\n      data += stride;\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::DivElements(const MatrixBase<Real> &a) {\n  KALDI_ASSERT(a.NumRows() == num_rows_ && a.NumCols() == num_cols_);\n  MatrixIndexT i;\n  MatrixIndexT j;\n\n  for (i = 0; i < num_rows_; i++) {\n    for (j = 0; j < num_cols_; j++) {\n      (*this)(i, j) /= a(i, j);\n    }\n  }\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::Sum() const {\n  double sum = 0.0;\n\n  for (MatrixIndexT i = 0; i < num_rows_; i++) {\n    for (MatrixIndexT j = 0; j < num_cols_; j++) {\n      sum += (*this)(i, j);\n    }\n  }\n\n  return (Real)sum;\n}\n\ntemplate<typename Real> void MatrixBase<Real>::Max(const MatrixBase<Real> &A) {\n  KALDI_ASSERT(A.NumRows() == NumRows() && A.NumCols() == NumCols());\n  for (MatrixIndexT row = 0; row < num_rows_; row++) {\n    Real *row_data = RowData(row);\n    const Real *other_row_data = A.RowData(row);\n    MatrixIndexT num_cols = num_cols_;\n    for (MatrixIndexT col = 0; col < num_cols; col++) {\n      row_data[col] = std::max(row_data[col],\n                               other_row_data[col]);\n    }\n  }\n}\n\ntemplate<typename Real> void MatrixBase<Real>::Min(const MatrixBase<Real> &A) {\n  KALDI_ASSERT(A.NumRows() == NumRows() && A.NumCols() == NumCols());\n  for (MatrixIndexT row = 0; row < num_rows_; row++) {\n    Real *row_data = RowData(row);\n    const Real *other_row_data = A.RowData(row);\n    MatrixIndexT num_cols = num_cols_;\n    for (MatrixIndexT col = 0; col < num_cols; col++) {\n      row_data[col] = std::min(row_data[col],\n                               other_row_data[col]);\n    }\n  }\n}\n\n\ntemplate<typename Real> void MatrixBase<Real>::Scale(Real alpha) {\n  if (alpha == 1.0) return;\n  if (num_rows_ == 0) return;\n  if (num_cols_ == stride_) {\n    cblas_Xscal(static_cast<size_t>(num_rows_) * static_cast<size_t>(num_cols_),\n                alpha, data_,1);\n  } else {\n    Real *data = data_;\n    for (MatrixIndexT i = 0; i < num_rows_; ++i, data += stride_) {\n      cblas_Xscal(num_cols_, alpha, data,1);\n    }\n  }\n}\n\ntemplate<typename Real>  // scales each row by scale[i].\nvoid MatrixBase<Real>::MulRowsVec(const VectorBase<Real> &scale) {\n  KALDI_ASSERT(scale.Dim() == num_rows_);\n  MatrixIndexT M = num_rows_, N = num_cols_;\n\n  for (MatrixIndexT i = 0; i < M; i++) {\n    Real this_scale = scale(i);\n    for (MatrixIndexT j = 0; j < N; j++) {\n      (*this)(i, j) *= this_scale;\n    }\n  }\n}\n\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::MulRowsGroupMat(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(src.NumRows() == this->NumRows() &&\n               this->NumCols() % src.NumCols() == 0);\n  int32 group_size = this->NumCols() / src.NumCols(),\n      num_groups = this->NumCols() / group_size,\n      num_rows = this->NumRows();\n\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    Real *data = this->RowData(i);\n    for (MatrixIndexT j = 0; j < num_groups; j++, data += group_size) {\n      Real scale = src(i, j);\n      cblas_Xscal(group_size, scale, data, 1);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::GroupPnormDeriv(const MatrixBase<Real> &input,\n                                       const MatrixBase<Real> &output,\n                                       Real power) {\n  KALDI_ASSERT(input.NumCols() == this->NumCols() && input.NumRows() ==\nthis->NumRows());\n  KALDI_ASSERT(this->NumCols() % output.NumCols() == 0 &&\n               this->NumRows() == output.NumRows());\n\n  int group_size = this->NumCols() / output.NumCols(),\n    num_rows = this->NumRows(), num_cols = this->NumCols();\n\n  if (power == 1.0) {\n    for (MatrixIndexT i = 0; i < num_rows; i++) {\n      for (MatrixIndexT j = 0; j < num_cols; j++) {\n        Real input_val = input(i, j);\n        (*this)(i, j) = (input_val == 0 ? 0 : (input_val > 0 ? 1 : -1));\n      }\n    }\n  } else if (power == std::numeric_limits<Real>::infinity()) {\n    for (MatrixIndexT i = 0; i < num_rows; i++) {\n      for (MatrixIndexT j = 0; j < num_cols; j++) {\n        Real output_val = output(i, j / group_size), input_val = input(i, j);\n        if (output_val == 0)\n          (*this)(i, j) = 0;\n        else\n          (*this)(i, j) = (std::abs(input_val) == output_val ? 1.0 : 0.0)\n              * (input_val >= 0 ? 1 : -1);\n      }\n    }\n  } else {\n    for (MatrixIndexT i = 0; i < num_rows; i++) {\n      for (MatrixIndexT j = 0; j < num_cols; j++) {\n        Real output_val = output(i, j / group_size),\n          input_val = input(i, j);\n        if (output_val == 0)\n          (*this)(i, j) = 0;\n         else\n            (*this)(i, j) = pow(std::abs(input_val), power - 1) *\n              pow(output_val, 1 - power) * (input_val >= 0 ? 1 : -1) ;\n      }\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::GroupMaxDeriv(const MatrixBase<Real> &input,\n                                     const MatrixBase<Real> &output) {\n  KALDI_ASSERT(input.NumCols() == this->NumCols() &&\n              input.NumRows() == this->NumRows());\n  KALDI_ASSERT(this->NumCols() % output.NumCols() == 0 &&\n               this->NumRows() == output.NumRows());\n\n  int group_size = this->NumCols() / output.NumCols(),\n      num_rows = this->NumRows(), num_cols = this->NumCols();\n\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    for (MatrixIndexT j = 0; j < num_cols; j++) {\n      Real input_val = input(i, j);\n      Real output_val = output(i, j / group_size);\n      (*this)(i, j) = (input_val == output_val ? 1 : 0);\n    }\n  }\n}\n\ntemplate<typename Real>  // scales each column by scale[i].\nvoid MatrixBase<Real>::MulColsVec(const VectorBase<Real> &scale) {\n  KALDI_ASSERT(scale.Dim() == num_cols_);\n  for (MatrixIndexT i = 0; i < num_rows_; i++) {\n    for (MatrixIndexT j = 0; j < num_cols_; j++) {\n      Real this_scale = scale(j);\n      (*this)(i, j) *= this_scale;\n    }\n  }\n}\n*/\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::SetZero() {\n    if (num_cols_ == stride_)\n        memset(data_, 0, sizeof(Real) * num_rows_ * num_cols_);\n    else\n        for (MatrixIndexT row = 0; row < num_rows_; row++)\n            memset(data_ + row * stride_, 0, sizeof(Real) * num_cols_);\n}\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::Set(Real value) {\n    for (MatrixIndexT row = 0; row < num_rows_; row++) {\n        for (MatrixIndexT col = 0; col < num_cols_; col++) {\n            (*this)(row, col) = value;\n        }\n    }\n}\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::SetUnit() {\n  SetZero();\n  for (MatrixIndexT row = 0; row < std::min(num_rows_, num_cols_); row++)\n    (*this)(row, row) = 1.0;\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::SetRandn() {\n  kaldi::RandomState rstate;\n  for (MatrixIndexT row = 0; row < num_rows_; row++) {\n    Real *row_data = this->RowData(row);\n    MatrixIndexT nc = (num_cols_ % 2 == 1) ? num_cols_ - 1 : num_cols_;\n    for (MatrixIndexT col = 0; col < nc; col += 2) {\n      kaldi::RandGauss2(row_data + col, row_data + col + 1, &rstate);\n    }\n    if (nc != num_cols_) row_data[nc] =\nstatic_cast<Real>(kaldi::RandGauss(&rstate));\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::SetRandUniform() {\n  kaldi::RandomState rstate;\n  for (MatrixIndexT row = 0; row < num_rows_; row++) {\n    Real *row_data = this->RowData(row);\n    for (MatrixIndexT col = 0; col < num_cols_; col++, row_data++) {\n      *row_data = static_cast<Real>(kaldi::RandUniform(&rstate));\n    }\n  }\n}\n*/\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::Write(std::ostream &os, bool binary) const {\n    if (!os.good()) {\n        KALDI_ERR << \"Failed to write matrix to stream: stream not good\";\n    }\n    if (binary) {  // Use separate binary and text formats,\n        // since in binary mode we need to know if it's float or double.\n        std::string my_token = (sizeof(Real) == 4 ? \"FM\" : \"DM\");\n\n        WriteToken(os, binary, my_token);\n        {\n            int32 rows = this->num_rows_;  // make the size 32-bit on disk.\n            int32 cols = this->num_cols_;\n            KALDI_ASSERT(this->num_rows_ == (MatrixIndexT)rows);\n            KALDI_ASSERT(this->num_cols_ == (MatrixIndexT)cols);\n            WriteBasicType(os, binary, rows);\n            WriteBasicType(os, binary, cols);\n        }\n        if (Stride() == NumCols())\n            os.write(reinterpret_cast<const char *>(Data()),\n                     sizeof(Real) * static_cast<size_t>(num_rows_) *\n                         static_cast<size_t>(num_cols_));\n        else\n            for (MatrixIndexT i = 0; i < num_rows_; i++)\n                os.write(reinterpret_cast<const char *>(RowData(i)),\n                         sizeof(Real) * num_cols_);\n        if (!os.good()) {\n            KALDI_ERR << \"Failed to write matrix to stream\";\n        }\n    } else {  // text mode.\n        if (num_cols_ == 0) {\n            os << \" [ ]\\n\";\n        } else {\n            os << \" [\";\n            for (MatrixIndexT i = 0; i < num_rows_; i++) {\n                os << \"\\n  \";\n                for (MatrixIndexT j = 0; j < num_cols_; j++)\n                    os << (*this)(i, j) << \" \";\n            }\n            os << \"]\\n\";\n        }\n    }\n}\n\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::Read(std::istream &is, bool binary) {\n    //  In order to avoid rewriting this, we just declare a Matrix and\n    // use it to read the data, then copy.\n    Matrix<Real> tmp;\n    tmp.Read(is, binary);\n    if (tmp.NumRows() != NumRows() || tmp.NumCols() != NumCols()) {\n        KALDI_ERR << \"MatrixBase<Real>::Read, size mismatch \" << NumRows()\n                  << \" x \" << NumCols() << \" versus \" << tmp.NumRows() << \" x \"\n                  << tmp.NumCols();\n    }\n    CopyFromMat(tmp);\n}\n\n\ntemplate <typename Real>\nvoid Matrix<Real>::Read(std::istream &is, bool binary) {\n    // now assume add == false.\n    MatrixIndexT pos_at_start = is.tellg();\n    std::ostringstream specific_error;\n\n    if (binary) {  // Read in binary mode.\n        int peekval = Peek(is, binary);\n        if (peekval == 'C') {\n            // This code enables us to read CompressedMatrix as a regular\n            // matrix.\n            // CompressedMatrix compressed_mat;\n            // compressed_mat.Read(is, binary); // at this point, add == false.\n            // this->Resize(compressed_mat.NumRows(), compressed_mat.NumCols());\n            // compressed_mat.CopyToMat(this);\n            return;\n        }\n        const char *my_token = (sizeof(Real) == 4 ? \"FM\" : \"DM\");\n        char other_token_start = (sizeof(Real) == 4 ? 'D' : 'F');\n        if (peekval == other_token_start) {  // need to instantiate the other\n                                             // type to read it.\n            typedef typename OtherReal<Real>::Real OtherType;  // if Real ==\n                                                               // float,\n                                                               // OtherType ==\n                                                               // double, and\n                                                               // vice versa.\n            Matrix<OtherType> other(this->num_rows_, this->num_cols_);\n            other.Read(is, binary);  // add is false at this point anyway.\n            this->Resize(other.NumRows(), other.NumCols());\n            this->CopyFromMat(other);\n            return;\n        }\n        std::string token;\n        ReadToken(is, binary, &token);\n        if (token != my_token) {\n            if (token.length() > 20) token = token.substr(0, 17) + \"...\";\n            specific_error << \": Expected token \" << my_token << \", got \"\n                           << token;\n            goto bad;\n        }\n        int32 rows, cols;\n        ReadBasicType(is, binary, &rows);  // throws on error.\n        ReadBasicType(is, binary, &cols);  // throws on error.\n        if ((MatrixIndexT)rows != this->num_rows_ ||\n            (MatrixIndexT)cols != this->num_cols_) {\n            this->Resize(rows, cols);\n        }\n        if (this->Stride() == this->NumCols() && rows * cols != 0) {\n            is.read(reinterpret_cast<char *>(this->Data()),\n                    sizeof(Real) * rows * cols);\n            if (is.fail()) goto bad;\n        } else {\n            for (MatrixIndexT i = 0; i < (MatrixIndexT)rows; i++) {\n                is.read(reinterpret_cast<char *>(this->RowData(i)),\n                        sizeof(Real) * cols);\n                if (is.fail()) goto bad;\n            }\n        }\n        if (is.eof()) return;\n        if (is.fail()) goto bad;\n        return;\n    } else {  // Text mode.\n        std::string str;\n        is >> str;  // get a token\n        if (is.fail()) {\n            specific_error << \": Expected \\\"[\\\", got EOF\";\n            goto bad;\n        }\n        // if ((str.compare(\"DM\") == 0) || (str.compare(\"FM\") == 0)) {  // Back\n        // compatibility.\n        // is >> str;  // get #rows\n        //  is >> str;  // get #cols\n        //  is >> str;  // get \"[\"\n        // }\n        if (str == \"[]\") {\n            Resize(0, 0);\n            return;\n        }  // Be tolerant of variants.\n        else if (str != \"[\") {\n            if (str.length() > 20) str = str.substr(0, 17) + \"...\";\n            specific_error << \": Expected \\\"[\\\", got \\\"\" << str << '\"';\n            goto bad;\n        }\n        // At this point, we have read \"[\".\n        std::vector<std::vector<Real> *> data;\n        std::vector<Real> *cur_row = new std::vector<Real>;\n        while (1) {\n            int i = is.peek();\n            if (i == -1) {\n                specific_error << \"Got EOF while reading matrix data\";\n                goto cleanup;\n            } else if (static_cast<char>(i) ==\n                       ']') {  // Finished reading matrix.\n                is.get();      // eat the \"]\".\n                i = is.peek();\n                if (static_cast<char>(i) == '\\r') {\n                    is.get();\n                    is.get();  // get \\r\\n (must eat what we wrote)\n                } else if (static_cast<char>(i) == '\\n') {\n                    is.get();\n                }  // get \\n (must eat what we wrote)\n                if (is.fail()) {\n                    KALDI_WARN << \"After end of matrix data, read error.\";\n                    // we got the data we needed, so just warn for this error.\n                }\n                // Now process the data.\n                if (!cur_row->empty())\n                    data.push_back(cur_row);\n                else\n                    delete (cur_row);\n                cur_row = NULL;\n                if (data.empty()) {\n                    this->Resize(0, 0);\n                    return;\n                } else {\n                    int32 num_rows = data.size(), num_cols = data[0]->size();\n                    this->Resize(num_rows, num_cols);\n                    for (int32 i = 0; i < num_rows; i++) {\n                        if (static_cast<int32>(data[i]->size()) != num_cols) {\n                            specific_error\n                                << \"Matrix has inconsistent #cols: \" << num_cols\n                                << \" vs.\" << data[i]->size()\n                                << \" (processing row\" << i << \")\";\n                            goto cleanup;\n                        }\n                        for (int32 j = 0; j < num_cols; j++)\n                            (*this)(i, j) = (*(data[i]))[j];\n                        delete data[i];\n                        data[i] = NULL;\n                    }\n                }\n                return;\n            } else if (static_cast<char>(i) == '\\n' ||\n                       static_cast<char>(i) == ';') {\n                // End of matrix row.\n                is.get();\n                if (cur_row->size() != 0) {\n                    data.push_back(cur_row);\n                    cur_row = new std::vector<Real>;\n                    cur_row->reserve(data.back()->size());\n                }\n            } else if ((i >= '0' && i <= '9') || i == '-') {  // A number...\n                Real r;\n                is >> r;\n                if (is.fail()) {\n                    specific_error\n                        << \"Stream failure/EOF while reading matrix data.\";\n                    goto cleanup;\n                }\n                cur_row->push_back(r);\n            } else if (isspace(i)) {\n                is.get();  // eat the space and do nothing.\n            } else {       // NaN or inf or error.\n                std::string str;\n                is >> str;\n                if (!KALDI_STRCASECMP(str.c_str(), \"inf\") ||\n                    !KALDI_STRCASECMP(str.c_str(), \"infinity\")) {\n                    cur_row->push_back(std::numeric_limits<Real>::infinity());\n                    KALDI_WARN << \"Reading infinite value into matrix.\";\n                } else if (!KALDI_STRCASECMP(str.c_str(), \"nan\")) {\n                    cur_row->push_back(std::numeric_limits<Real>::quiet_NaN());\n                    KALDI_WARN << \"Reading NaN value into matrix.\";\n                } else {\n                    if (str.length() > 20) str = str.substr(0, 17) + \"...\";\n                    specific_error << \"Expecting numeric matrix data, got \"\n                                   << str;\n                    goto cleanup;\n                }\n            }\n        }\n    // Note, we never leave the while () loop before this\n    // line (we return from it.)\n    cleanup:  // We only reach here in case of error in the while loop above.\n        if (cur_row != NULL) delete cur_row;\n        for (size_t i = 0; i < data.size(); i++)\n            if (data[i] != NULL) delete data[i];\n        // and then go on to \"bad\" below, where we print error.\n    }\nbad:\n    KALDI_ERR << \"Failed to read matrix from stream.  \" << specific_error.str()\n              << \" File position at start is \" << pos_at_start << \", currently \"\n              << is.tellg();\n}\n\n\n// Constructor... note that this is not const-safe as it would\n// be quite complicated to implement a \"const SubMatrix\" class that\n// would not allow its contents to be changed.\ntemplate <typename Real>\nSubMatrix<Real>::SubMatrix(const MatrixBase<Real> &M,\n                           const MatrixIndexT ro,\n                           const MatrixIndexT r,\n                           const MatrixIndexT co,\n                           const MatrixIndexT c) {\n    if (r == 0 || c == 0) {\n        // we support the empty sub-matrix as a special case.\n        KALDI_ASSERT(c == 0 && r == 0);\n        this->data_ = NULL;\n        this->num_cols_ = 0;\n        this->num_rows_ = 0;\n        this->stride_ = 0;\n        return;\n    }\n    KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(ro) <\n                     static_cast<UnsignedMatrixIndexT>(M.num_rows_) &&\n                 static_cast<UnsignedMatrixIndexT>(co) <\n                     static_cast<UnsignedMatrixIndexT>(M.num_cols_) &&\n                 static_cast<UnsignedMatrixIndexT>(r) <=\n                     static_cast<UnsignedMatrixIndexT>(M.num_rows_ - ro) &&\n                 static_cast<UnsignedMatrixIndexT>(c) <=\n                     static_cast<UnsignedMatrixIndexT>(M.num_cols_ - co));\n    // point to the begining of window\n    MatrixBase<Real>::num_rows_ = r;\n    MatrixBase<Real>::num_cols_ = c;\n    MatrixBase<Real>::stride_ = M.Stride();\n    MatrixBase<Real>::data_ =\n        M.Data_workaround() + static_cast<size_t>(co) +\n        static_cast<size_t>(ro) * static_cast<size_t>(M.Stride());\n}\n\n\ntemplate <typename Real>\nSubMatrix<Real>::SubMatrix(Real *data,\n                           MatrixIndexT num_rows,\n                           MatrixIndexT num_cols,\n                           MatrixIndexT stride)\n    : MatrixBase<Real>(\n          data, num_cols, num_rows, stride) {  // caution: reversed order!\n    if (data == NULL) {\n        KALDI_ASSERT(num_rows * num_cols == 0);\n        this->num_rows_ = 0;\n        this->num_cols_ = 0;\n        this->stride_ = 0;\n    } else {\n        KALDI_ASSERT(this->stride_ >= this->num_cols_);\n    }\n}\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::Add(const Real alpha) {\n  Real *data = data_;\n  MatrixIndexT stride = stride_;\n  for (MatrixIndexT r = 0; r < num_rows_; r++)\n    for (MatrixIndexT c = 0; c < num_cols_; c++)\n      data[c + stride*r] += alpha;\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddToDiag(const Real alpha) {\n  Real *data = data_;\n  MatrixIndexT this_stride = stride_ + 1,\n      num_to_add = std::min(num_rows_, num_cols_);\n  for (MatrixIndexT r = 0; r < num_to_add; r++)\n    data[r * this_stride] += alpha;\n}\n\n\ntemplate<typename Real>\nReal MatrixBase<Real>::Cond() const {\n  KALDI_ASSERT(num_rows_ > 0&&num_cols_ > 0);\n  Vector<Real> singular_values(std::min(num_rows_, num_cols_));\n  Svd(&singular_values);  // Get singular values...\n  Real min = singular_values(0), max = singular_values(0);  // both absolute\nvalues...\n  for (MatrixIndexT i = 1;i < singular_values.Dim();i++) {\n    min = std::min((Real)std::abs(singular_values(i)), min); max =\nstd::max((Real)std::abs(singular_values(i)), max);\n  }\n  if (min > 0) return max/min;\n  else return std::numeric_limits<Real>::infinity();\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::Trace(bool check_square) const  {\n  KALDI_ASSERT(!check_square || num_rows_ == num_cols_);\n  Real ans = 0.0;\n  for (MatrixIndexT r = 0;r < std::min(num_rows_, num_cols_);r++) ans += data_\n[r + stride_*r];\n  return ans;\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::Max() const {\n  KALDI_ASSERT(num_rows_ > 0 && num_cols_ > 0);\n  Real ans= *data_;\n  for (MatrixIndexT r = 0; r < num_rows_; r++)\n    for (MatrixIndexT c = 0; c < num_cols_; c++)\n      if (data_[c + stride_*r] > ans)\n        ans = data_[c + stride_*r];\n  return ans;\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::Min() const {\n  KALDI_ASSERT(num_rows_ > 0 && num_cols_ > 0);\n  Real ans= *data_;\n  for (MatrixIndexT r = 0; r < num_rows_; r++)\n    for (MatrixIndexT c = 0; c < num_cols_; c++)\n      if (data_[c + stride_*r] < ans)\n        ans = data_[c + stride_*r];\n  return ans;\n}\n\n\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::AddMatMatMat(Real alpha,\n                                    const MatrixBase<Real> &A,\nMatrixTransposeType transA,\n                                    const MatrixBase<Real> &B,\nMatrixTransposeType transB,\n                                    const MatrixBase<Real> &C,\nMatrixTransposeType transC,\n                                    Real beta) {\n  // Note on time taken with different orders of computation.  Assume not\ntransposed in this /\n  // discussion. Firstly, normalize expressions using A.NumCols == B.NumRows and\nB.NumCols == C.NumRows, prefer\n  // rows where there is a choice.\n  // time taken for (AB) is:  A.NumRows*B.NumRows*C.Rows\n  // time taken for (AB)C is A.NumRows*C.NumRows*C.Cols\n  // so this order is A.NumRows*B.NumRows*C.NumRows +\nA.NumRows*C.NumRows*C.NumCols.\n\n  // time taken for (BC) is: B.NumRows*C.NumRows*C.Cols\n  // time taken for A(BC) is: A.NumRows*B.NumRows*C.Cols\n  // so this order is B.NumRows*C.NumRows*C.NumCols + A.NumRows*B.NumRows*C.Cols\n\n  MatrixIndexT ARows = A.num_rows_, ACols = A.num_cols_, BRows = B.num_rows_,\nBCols = B.num_cols_,\n      CRows = C.num_rows_, CCols = C.num_cols_;\n  if (transA == kTrans) std::swap(ARows, ACols);\n  if (transB == kTrans) std::swap(BRows, BCols);\n  if (transC == kTrans) std::swap(CRows, CCols);\n\n  MatrixIndexT AB_C_time = ARows*BRows*CRows + ARows*CRows*CCols;\n  MatrixIndexT A_BC_time = BRows*CRows*CCols + ARows*BRows*CCols;\n\n  if (AB_C_time < A_BC_time) {\n    Matrix<Real> AB(ARows, BCols);\n    AB.AddMatMat(1.0, A, transA, B, transB, 0.0);  // AB = A * B.\n    (*this).AddMatMat(alpha, AB, kNoTrans, C, transC, beta);\n  } else {\n    Matrix<Real> BC(BRows, CCols);\n    BC.AddMatMat(1.0, B, transB, C, transC, 0.0);  // BC = B * C.\n    (*this).AddMatMat(alpha, A, transA, BC, kNoTrans, beta);\n  }\n}\n\n\n\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::DestructiveSvd(VectorBase<Real> *s, MatrixBase<Real> *U,\nMatrixBase<Real> *Vt) {\n  // Svd, *this = U*diag(s)*Vt.\n  // With (*this).num_rows_ == m, (*this).num_cols_ == n,\n  // Support only skinny Svd with m>=n (NumRows>=NumCols), and zero sizes for U\nand Vt mean\n  // we do not want that output.  We expect that s.Dim() == m,\n  // U is either 0 by 0 or m by n, and rv is either 0 by 0 or n by n.\n  // Throws exception on error.\n\n  KALDI_ASSERT(num_rows_>=num_cols_ && \"Svd requires that #rows by >= #cols.\");\n// For compatibility with JAMA code.\n  KALDI_ASSERT(s->Dim() == num_cols_);  // s should be the smaller dim.\n  KALDI_ASSERT(U == NULL || (U->num_rows_ == num_rows_&&U->num_cols_ ==\nnum_cols_));\n  KALDI_ASSERT(Vt == NULL || (Vt->num_rows_ == num_cols_&&Vt->num_cols_ ==\nnum_cols_));\n\n  Real prescale = 1.0;\n  if ( std::abs((*this)(0, 0) ) < 1.0e-30) {  // Very tiny value... can cause\nproblems in Svd.\n    Real max_elem = LargestAbsElem();\n    if (max_elem != 0) {\n      prescale = 1.0 / max_elem;\n      if (std::abs(prescale) == std::numeric_limits<Real>::infinity()) {\nprescale = 1.0e+40; }\n      (*this).Scale(prescale);\n    }\n  }\n\n#if !defined(HAVE_ATLAS) && !defined(USE_KALDI_SVD)\n  // \"S\" == skinny Svd (only one we support because of compatibility with Jama\none which is only skinny),\n  // \"N\"== no eigenvectors wanted.\n  LapackGesvd(s, U, Vt);\n#else\n  /*  if (num_rows_ > 1 && num_cols_ > 1 && (*this)(0, 0) == (*this)(1, 1)\n      && Max() == Min() && (*this)(0, 0) != 0.0) { // special case that JamaSvd\nsometimes crashes on.\n      KALDI_WARN << \"Jama SVD crashes on this type of matrix, perturbing it to\nprevent crash.\";\n      for(int32 i = 0; i < NumRows(); i++)\n      (*this)(i, i)  *= 1.00001;\n      }*/\n//  bool ans = JamaSvd(s, U, Vt);\n// if (Vt != NULL) Vt->Transpose();  // possibly to do: change this and also the\n// transpose inside the JamaSvd routine.  note, Vt is square.\n// if (!ans) {\n// KALDI_ERR << \"Error doing Svd\";  // This one will be caught.\n//}\n//#endif\n// if (prescale != 1.0) s->Scale(1.0/prescale);\n//}\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::Svd(VectorBase<Real> *s, MatrixBase<Real> *U,\nMatrixBase<Real> *Vt) const {\n  try {\n    if (num_rows_ >= num_cols_) {\n      Matrix<Real> tmp(*this);\n      tmp.DestructiveSvd(s, U, Vt);\n    } else {\n      Matrix<Real> tmp(*this, kTrans);  // transpose of *this.\n      // rVt will have different dim so cannot transpose in-place --> use a temp\nmatrix.\n      Matrix<Real> Vt_Trans(Vt ? Vt->num_cols_ : 0, Vt ? Vt->num_rows_ : 0);\n      // U will be transpose\n      tmp.DestructiveSvd(s, Vt ? &Vt_Trans : NULL, U);\n      if (U) U->Transpose();\n      if (Vt) Vt->CopyFromMat(Vt_Trans, kTrans);  // copy with transpose.\n    }\n  } catch (...) {\n    KALDI_ERR << \"Error doing Svd (did not converge), first part of matrix is\\n\"\n              << SubMatrix<Real>(*this, 0, std::min((MatrixIndexT)10,\nnum_rows_),\n                                 0, std::min((MatrixIndexT)10, num_cols_))\n              << \", min and max are: \" << Min() << \", \" << Max();\n  }\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::IsSymmetric(Real cutoff) const {\n  MatrixIndexT R = num_rows_, C = num_cols_;\n  if (R != C) return false;\n  Real bad_sum = 0.0, good_sum = 0.0;\n  for (MatrixIndexT i = 0;i < R;i++) {\n    for (MatrixIndexT j = 0;j < i;j++) {\n      Real a = (*this)(i, j), b = (*this)(j, i), avg = 0.5*(a+b), diff =\n0.5*(a-b);\n      good_sum += std::abs(avg); bad_sum += std::abs(diff);\n    }\n    good_sum += std::abs((*this)(i, i));\n  }\n  if (bad_sum > cutoff*good_sum) return false;\n  return true;\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::IsDiagonal(Real cutoff) const{\n  MatrixIndexT R = num_rows_, C = num_cols_;\n  Real bad_sum = 0.0, good_sum = 0.0;\n  for (MatrixIndexT i = 0;i < R;i++) {\n    for (MatrixIndexT j = 0;j < C;j++) {\n      if (i == j) good_sum += std::abs((*this)(i, j));\n      else bad_sum += std::abs((*this)(i, j));\n    }\n  }\n  return (!(bad_sum > good_sum * cutoff));\n}\n\n// This does nothing, it's designed to trigger Valgrind errors\n// if any memory is uninitialized.\ntemplate<typename Real>\nvoid MatrixBase<Real>::TestUninitialized() const {\n  MatrixIndexT R = num_rows_, C = num_cols_, positive = 0;\n  for (MatrixIndexT i = 0; i < R; i++)\n    for (MatrixIndexT j = 0; j < C; j++)\n      if ((*this)(i, j) > 0.0) positive++;\n  if (positive > R * C)\n    KALDI_ERR << \"Error....\";\n}\n\n\ntemplate<typename Real>\nbool MatrixBase<Real>::IsUnit(Real cutoff) const {\n  MatrixIndexT R = num_rows_, C = num_cols_;\n  Real bad_max = 0.0;\n  for (MatrixIndexT i = 0; i < R;i++)\n    for (MatrixIndexT j = 0; j < C;j++)\n      bad_max = std::max(bad_max, static_cast<Real>(std::abs( (*this)(i, j) - (i\n== j?1.0:0.0))));\n  return (bad_max <= cutoff);\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::IsZero(Real cutoff)const {\n  MatrixIndexT R = num_rows_, C = num_cols_;\n  Real bad_max = 0.0;\n  for (MatrixIndexT i = 0;i < R;i++)\n    for (MatrixIndexT j = 0;j < C;j++)\n      bad_max = std::max(bad_max, static_cast<Real>(std::abs( (*this)(i, j) )));\n  return (bad_max <= cutoff);\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::FrobeniusNorm() const{\n  return std::sqrt(TraceMatMat(*this, *this, kTrans));\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::ApproxEqual(const MatrixBase<Real> &other, float tol)\nconst {\n  if (num_rows_ != other.num_rows_ || num_cols_ != other.num_cols_)\n    KALDI_ERR << \"ApproxEqual: size mismatch.\";\n  Matrix<Real> tmp(*this);\n  tmp.AddMat(-1.0, other);\n  return (tmp.FrobeniusNorm() <= static_cast<Real>(tol) *\n          this->FrobeniusNorm());\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::Equal(const MatrixBase<Real> &other) const {\n  if (num_rows_ != other.num_rows_ || num_cols_ != other.num_cols_)\n    KALDI_ERR << \"Equal: size mismatch.\";\n  for (MatrixIndexT i = 0; i < num_rows_; i++)\n    for (MatrixIndexT j = 0; j < num_cols_; j++)\n      if ( (*this)(i, j) != other(i, j))\n        return false;\n  return true;\n}\n\n\ntemplate<typename Real>\nReal MatrixBase<Real>::LargestAbsElem() const{\n  MatrixIndexT R = num_rows_, C = num_cols_;\n  Real largest = 0.0;\n  for (MatrixIndexT i = 0;i < R;i++)\n    for (MatrixIndexT j = 0;j < C;j++)\n      largest = std::max(largest, (Real)std::abs((*this)(i, j)));\n  return largest;\n}\n\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::OrthogonalizeRows() {\n  KALDI_ASSERT(NumRows() <= NumCols());\n  MatrixIndexT num_rows = num_rows_;\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    int32 counter = 0;\n    while (1) {\n      Real start_prod = VecVec(this->Row(i), this->Row(i));\n      if (start_prod - start_prod != 0.0 || start_prod == 0.0) {\n        KALDI_WARN << \"Self-product of row \" << i << \" of matrix is \"\n                   << start_prod << \", randomizing.\";\n        this->Row(i).SetRandn();\n        counter++;\n        continue;  // loop again.\n      }\n      for (MatrixIndexT j = 0; j < i; j++) {\n        Real prod = VecVec(this->Row(i), this->Row(j));\n        this->Row(i).AddVec(-prod, this->Row(j));\n      }\n      Real end_prod = VecVec(this->Row(i), this->Row(i));\n      if (end_prod <= 0.01 * start_prod) { // We removed\n        // almost all of the vector during orthogonalization,\n        // so we have reason to doubt (for roundoff reasons)\n        // that it's still orthogonal to the other vectors.\n        // We need to orthogonalize again.\n        if (end_prod == 0.0) { // Row is exactly zero:\n          // generate random direction.\n          this->Row(i).SetRandn();\n        }\n        counter++;\n        if (counter > 100)\n          KALDI_ERR << \"Loop detected while orthogalizing matrix.\";\n      } else {\n        this->Row(i).Scale(1.0 / std::sqrt(end_prod));\n        break;\n      }\n    }\n  }\n}\n\n\n// Uses Svd to compute the eigenvalue decomposition of a symmetric positive\nsemidefinite\n//   matrix:\n// (*this) = rU * diag(rs) * rU^T, with rU an orthogonal matrix so rU^{-1} =\nrU^T.\n// Does this by computing svd (*this) = U diag(rs) V^T ... answer is just U\ndiag(rs) U^T.\n// Throws exception if this failed to within supplied precision (typically\nbecause *this was not\n// symmetric positive definite).\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::SymPosSemiDefEig(VectorBase<Real> *rs, MatrixBase<Real>\n*rU, Real check_thresh) // e.g. check_thresh = 0.001\n{\n  const MatrixIndexT D = num_rows_;\n\n  KALDI_ASSERT(num_rows_ == num_cols_);\n  KALDI_ASSERT(IsSymmetric() && \"SymPosSemiDefEig: expecting input to be\nsymmetrical.\");\n  KALDI_ASSERT(rU->num_rows_ == D && rU->num_cols_ == D && rs->Dim() == D);\n\n  Matrix<Real>  Vt(D, D);\n  Svd(rs, rU, &Vt);\n\n  // First just zero any singular values if the column of U and V do not have\n+ve dot product--\n  // this may mean we have small negative eigenvalues, and if we zero them the\nresult will be closer to correct.\n  for (MatrixIndexT i = 0;i < D;i++) {\n    Real sum = 0.0;\n    for (MatrixIndexT j = 0;j < D;j++) sum += (*rU)(j, i) * Vt(i, j);\n    if (sum < 0.0) (*rs)(i) = 0.0;\n  }\n\n  {\n    Matrix<Real> tmpU(*rU); Vector<Real> tmps(*rs); tmps.ApplyPow(0.5);\n    tmpU.MulColsVec(tmps);\n    SpMatrix<Real> tmpThis(D);\n    tmpThis.AddMat2(1.0, tmpU, kNoTrans, 0.0);\n    Matrix<Real> tmpThisFull(tmpThis);\n    float new_norm = tmpThisFull.FrobeniusNorm();\n    float old_norm = (*this).FrobeniusNorm();\n    tmpThisFull.AddMat(-1.0, (*this));\n\n    if (!(old_norm == 0 && new_norm == 0)) {\n      float diff_norm = tmpThisFull.FrobeniusNorm();\n      if (std::abs(new_norm-old_norm) > old_norm*check_thresh || diff_norm >\nold_norm*check_thresh) {\n        KALDI_WARN << \"SymPosSemiDefEig seems to have failed \" << diff_norm << \"\n!<< \"\n                   << check_thresh << \"*\" << old_norm << \", maybe matrix was not\n\"\n                   << \"positive semi definite.  Continuing anyway.\";\n      }\n    }\n  }\n}\n\n\ntemplate<typename Real>\nReal MatrixBase<Real>::LogDet(Real *det_sign) const {\n  Real log_det;\n  Matrix<Real> tmp(*this);\n  tmp.Invert(&log_det, det_sign, false);  // false== output not needed (saves\nsome computation).\n  return log_det;\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::InvertDouble(Real *log_det, Real *det_sign,\n                                    bool inverse_needed) {\n  double log_det_tmp, det_sign_tmp;\n  Matrix<double> dmat(*this);\n  dmat.Invert(&log_det_tmp, &det_sign_tmp, inverse_needed);\n  if (inverse_needed) (*this).CopyFromMat(dmat);\n  if (log_det) *log_det = log_det_tmp;\n  if (det_sign) *det_sign = det_sign_tmp;\n}\n*/\n\n// template<class Real>\n// void MatrixBase<Real>::CopyFromMat(const CompressedMatrix &mat) {\n// mat.CopyToMat(this);\n//}\n\n// template<class Real>\n// Matrix<Real>::Matrix(const CompressedMatrix &M): MatrixBase<Real>() {\n// Resize(M.NumRows(), M.NumCols(), kUndefined);\n// M.CopyToMat(this);\n//}\n\n\ntemplate <typename Real>\nvoid MatrixBase<Real>::InvertElements() {\n    for (MatrixIndexT r = 0; r < num_rows_; r++) {\n        for (MatrixIndexT c = 0; c < num_cols_; c++) {\n            (*this)(r, c) = static_cast<Real>(1.0 / (*this)(r, c));\n        }\n    }\n}\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::Transpose() {\n  KALDI_ASSERT(num_rows_ == num_cols_);\n  MatrixIndexT M = num_rows_;\n  for (MatrixIndexT i = 0;i < M;i++)\n    for (MatrixIndexT j = 0;j < i;j++) {\n      Real &a = (*this)(i, j), &b = (*this)(j, i);\n      std::swap(a, b);\n    }\n}\n\n\ntemplate<typename Real>\nvoid Matrix<Real>::Transpose() {\n  if (this->num_rows_ != this->num_cols_) {\n    Matrix<Real> tmp(*this, kTrans);\n    Resize(this->num_cols_, this->num_rows_);\n    this->CopyFromMat(tmp);\n  } else {\n    (static_cast<MatrixBase<Real>&>(*this)).Transpose();\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Heaviside(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = (src_row_data[col] > 0 ? 1.0 : 0.0);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Exp(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = kaldi::Exp(src_row_data[col]);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Pow(const MatrixBase<Real> &src, Real power) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++) {\n      row_data[col] = pow(src_row_data[col], power);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::PowAbs(const MatrixBase<Real> &src, Real power, bool\ninclude_sign) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col ++) {\n      if (include_sign == true && src_row_data[col] < 0) {\n    row_data[col] = -pow(std::abs(src_row_data[col]), power);\n      } else {\n    row_data[col] = pow(std::abs(src_row_data[col]), power);\n      }\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Floor(const MatrixBase<Real> &src, Real floor_val) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = (src_row_data[col] < floor_val ? floor_val :\nsrc_row_data[col]);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Ceiling(const MatrixBase<Real> &src, Real ceiling_val) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = (src_row_data[col] > ceiling_val ? ceiling_val :\nsrc_row_data[col]);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Log(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = kaldi::Log(src_row_data[col]);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::ExpSpecial(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++)\n      row_data[col] = (src_row_data[col] < Real(0) ?\nkaldi::Exp(src_row_data[col]) : (src_row_data[col] + Real(1)));\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::ExpLimited(const MatrixBase<Real> &src, Real lower_limit,\nReal upper_limit) {\n  KALDI_ASSERT(SameDim(*this, src));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_;\n  Real *row_data = data_;\n  const Real *src_row_data = src.Data();\n  for (MatrixIndexT row = 0; row < num_rows;\n       row++,row_data += stride_, src_row_data += src.stride_) {\n    for (MatrixIndexT col = 0; col < num_cols; col++) {\n      const Real x = src_row_data[col];\n      if (!(x >= lower_limit))\n    row_data[col] = kaldi::Exp(lower_limit);\n      else if (x > upper_limit)\n    row_data[col] = kaldi::Exp(upper_limit);\n      else\n    row_data[col] = kaldi::Exp(x);\n    }\n  }\n}\n\ntemplate<typename Real>\nbool MatrixBase<Real>::Power(Real power) {\n  KALDI_ASSERT(num_rows_ > 0 && num_rows_ == num_cols_);\n  MatrixIndexT n = num_rows_;\n  Matrix<Real> P(n, n);\n  Vector<Real> re(n), im(n);\n  this->Eig(&P, &re, &im);\n  // Now attempt to take the complex eigenvalues to this power.\n  for (MatrixIndexT i = 0; i < n; i++)\n    if (!AttemptComplexPower(&(re(i)), &(im(i)), power))\n      return false;  // e.g. real and negative, or zero, eigenvalues.\n\n  Matrix<Real> D(n, n);  // D to the power.\n  CreateEigenvalueMatrix(re, im, &D);\n\n  Matrix<Real> tmp(n, n);  // P times D\n  tmp.AddMatMat(1.0, P, kNoTrans, D, kNoTrans, 0.0);  // tmp := P*D\n  P.Invert();\n  // next line is: *this = tmp * P^{-1} = P * D * P^{-1}\n  (*this).AddMatMat(1.0, tmp, kNoTrans, P, kNoTrans, 0.0);\n  return true;\n}\n*/\ntemplate <typename Real>\nvoid Matrix<Real>::Swap(Matrix<Real> *other) {\n    std::swap(this->data_, other->data_);\n    std::swap(this->num_cols_, other->num_cols_);\n    std::swap(this->num_rows_, other->num_rows_);\n    std::swap(this->stride_, other->stride_);\n}\n/*\n// Repeating this comment that appeared in the header:\n// Eigenvalue Decomposition of a square NxN matrix into the form (*this) = P D\n// P^{-1}.  Be careful: the relationship of D to the eigenvalues we output is\n// slightly complicated, due to the need for P to be real.  In the symmetric\n// case D is diagonal and real, but in\n// the non-symmetric case there may be complex-conjugate pairs of eigenvalues.\n// In this case, for the equation (*this) = P D P^{-1} to hold, D must actually\n// be block diagonal, with 2x2 blocks corresponding to any such pairs.  If a\n// pair is lambda +- i*mu, D will have a corresponding 2x2 block\n// [lambda, mu; -mu, lambda].\n// Note that if the input matrix (*this) is non-invertible, P may not be\ninvertible\n// so in this case instead of the equation (*this) = P D P^{-1} holding, we have\n// instead (*this) P = P D.\n//\n// By making the pointer arguments non-NULL or NULL, the user can choose to take\n// not to take the eigenvalues directly, and/or the matrix D which is\nblock-diagonal\n// with 2x2 blocks.\ntemplate<typename Real>\nvoid MatrixBase<Real>::Eig(MatrixBase<Real> *P,\n                           VectorBase<Real> *r,\n                           VectorBase<Real> *i) const {\n  EigenvalueDecomposition<Real>  eig(*this);\n  if (P) eig.GetV(P);\n  if (r) eig.GetRealEigenvalues(r);\n  if (i) eig.GetImagEigenvalues(i);\n}\n\n\n// Begin non-member function definitions.\n\n//  /**\n//   * @brief Extension of the HTK header\n//  */\n// struct HtkHeaderExt\n//  {\n// INT_32 mHeaderSize;\n// INT_32 mVersion;\n// INT_32 mSampSize;\n// };\n/*\ntemplate<typename Real>\nbool ReadHtk(std::istream &is, Matrix<Real> *M_ptr, HtkHeader *header_ptr)\n{\n  // check instantiated with double or float.\n  KALDI_ASSERT_IS_FLOATING_TYPE(Real);\n  Matrix<Real> &M = *M_ptr;\n  HtkHeader htk_hdr;\n\n  // TODO(arnab): this fails if the HTK file has CRC checksum or is compressed.\n  is.read((char*)&htk_hdr, sizeof(htk_hdr));  // we're being really POSIX here!\n  if (is.fail()) {\n    KALDI_WARN << \"Could not read header from HTK feature file \";\n    return false;\n  }\n\n  KALDI_SWAP4(htk_hdr.mNSamples);\n  KALDI_SWAP4(htk_hdr.mSamplePeriod);\n  KALDI_SWAP2(htk_hdr.mSampleSize);\n  KALDI_SWAP2(htk_hdr.mSampleKind);\n\n  bool has_checksum = false;\n  {\n    // See HParm.h in HTK code for sources of these things.\n    enum BaseParmKind{\n      Waveform, Lpc, Lprefc, Lpcepstra, Lpdelcep,\n      Irefc, Mfcc, Fbank, Melspec, User, Discrete, Plp, Anon };\n\n    const int32 IsCompressed = 02000, HasChecksum = 010000, HasVq = 040000,\n        Problem = IsCompressed | HasVq;\n    int32 base_parm = htk_hdr.mSampleKind & (077);\n    has_checksum = (base_parm & HasChecksum) != 0;\n    htk_hdr.mSampleKind &= ~HasChecksum; // We don't support writing with\n                                         // checksum so turn it off.\n    if (htk_hdr.mSampleKind & Problem)\n      KALDI_ERR << \"Code to read HTK features does not support compressed \"\n          \"features, or features with VQ.\";\n    if (base_parm == Waveform || base_parm == Irefc || base_parm == Discrete)\n      KALDI_ERR << \"Attempting to read HTK features from unsupported type \"\n          \"(e.g. waveform or discrete features.\";\n  }\n\n  KALDI_VLOG(3) << \"HTK header: Num Samples: \" << htk_hdr.mNSamples\n                << \"; Sample period: \" << htk_hdr.mSamplePeriod\n                << \"; Sample size: \" << htk_hdr.mSampleSize\n                << \"; Sample kind: \" << htk_hdr.mSampleKind;\n\n  M.Resize(htk_hdr.mNSamples, htk_hdr.mSampleSize / sizeof(float));\n\n  MatrixIndexT i;\n  MatrixIndexT j;\n  if (sizeof(Real) == sizeof(float)) {\n    for (i = 0; i< M.NumRows(); i++) {\n      is.read((char*)M.RowData(i), sizeof(float)*M.NumCols());\n      if (is.fail()) {\n        KALDI_WARN << \"Could not read data from HTK feature file \";\n        return false;\n      }\n      if (MachineIsLittleEndian()) {\n        MatrixIndexT C = M.NumCols();\n        for (j = 0; j < C; j++) {\n          KALDI_SWAP4((M(i, j)));  // The HTK standard is big-endian!\n        }\n      }\n    }\n  } else {\n    float *pmem = new float[M.NumCols()];\n    for (i = 0; i < M.NumRows(); i++) {\n      is.read((char*)pmem, sizeof(float)*M.NumCols());\n      if (is.fail()) {\n        KALDI_WARN << \"Could not read data from HTK feature file \";\n        delete [] pmem;\n        return false;\n      }\n      MatrixIndexT C = M.NumCols();\n      for (j = 0; j < C; j++) {\n        if (MachineIsLittleEndian())  // HTK standard is big-endian!\n          KALDI_SWAP4(pmem[j]);\n        M(i, j) = static_cast<Real>(pmem[j]);\n      }\n    }\n    delete [] pmem;\n  }\n  if (header_ptr) *header_ptr = htk_hdr;\n  if (has_checksum) {\n    int16 checksum;\n    is.read((char*)&checksum, sizeof(checksum));\n    if (is.fail())\n      KALDI_WARN << \"Could not read checksum from HTK feature file \";\n    // We ignore the checksum.\n  }\n  return true;\n}\n\n\ntemplate\nbool ReadHtk(std::istream &is, Matrix<float> *M, HtkHeader *header_ptr);\n\ntemplate\nbool ReadHtk(std::istream &is, Matrix<double> *M, HtkHeader *header_ptr);\n\ntemplate<typename Real>\nbool WriteHtk(std::ostream &os, const MatrixBase<Real> &M, HtkHeader htk_hdr) //\nheader may be derived from a previous call to ReadHtk.  Must be in binary mode.\n{\n  KALDI_ASSERT(M.NumRows() == static_cast<MatrixIndexT>(htk_hdr.mNSamples));\n  KALDI_ASSERT(M.NumCols() == static_cast<MatrixIndexT>(htk_hdr.mSampleSize) /\n               static_cast<MatrixIndexT>(sizeof(float)));\n\n  KALDI_SWAP4(htk_hdr.mNSamples);\n  KALDI_SWAP4(htk_hdr.mSamplePeriod);\n  KALDI_SWAP2(htk_hdr.mSampleSize);\n  KALDI_SWAP2(htk_hdr.mSampleKind);\n\n  os.write((char*)&htk_hdr, sizeof(htk_hdr));\n  if (os.fail())  goto bad;\n\n  MatrixIndexT i;\n  MatrixIndexT j;\n  if (sizeof(Real) == sizeof(float) && !MachineIsLittleEndian()) {\n    for (i = 0; i< M.NumRows(); i++) {  // Unlikely to reach here ever!\n      os.write((char*)M.RowData(i), sizeof(float)*M.NumCols());\n      if (os.fail()) goto bad;\n    }\n  } else {\n    float *pmem = new float[M.NumCols()];\n\n    for (i = 0; i < M.NumRows(); i++) {\n      const Real *rowData = M.RowData(i);\n      for (j = 0;j < M.NumCols();j++)\n        pmem[j] =  static_cast<float> ( rowData[j] );\n      if (MachineIsLittleEndian())\n        for (j = 0;j < M.NumCols();j++)\n          KALDI_SWAP4(pmem[j]);\n      os.write((char*)pmem, sizeof(float)*M.NumCols());\n      if (os.fail()) {\n        delete [] pmem;\n        goto bad;\n      }\n    }\n    delete [] pmem;\n  }\n  return true;\nbad:\n  KALDI_WARN << \"Could not write to HTK feature file \";\n  return false;\n}\n\ntemplate\nbool WriteHtk(std::ostream &os, const MatrixBase<float> &M, HtkHeader htk_hdr);\n\ntemplate\nbool WriteHtk(std::ostream &os, const MatrixBase<double> &M, HtkHeader htk_hdr);\n\ntemplate<class Real>\nbool WriteSphinx(std::ostream &os, const MatrixBase<Real> &M)\n{\n  // CMUSphinx mfc file header contains count of the floats, followed\n  // by the data in float little endian format.\n\n  int size = M.NumRows() * M.NumCols();\n  os.write((char*)&size, sizeof(int));\n  if (os.fail())  goto bad;\n\n  MatrixIndexT i;\n  MatrixIndexT j;\n  if (sizeof(Real) == sizeof(float) && MachineIsLittleEndian()) {\n    for (i = 0; i< M.NumRows(); i++) {  // Unlikely to reach here ever!\n      os.write((char*)M.RowData(i), sizeof(float)*M.NumCols());\n      if (os.fail()) goto bad;\n    }\n  } else {\n    float *pmem = new float[M.NumCols()];\n\n    for (i = 0; i < M.NumRows(); i++) {\n      const Real *rowData = M.RowData(i);\n      for (j = 0;j < M.NumCols();j++)\n        pmem[j] =  static_cast<float> ( rowData[j] );\n      if (!MachineIsLittleEndian())\n        for (j = 0;j < M.NumCols();j++)\n          KALDI_SWAP4(pmem[j]);\n      os.write((char*)pmem, sizeof(float)*M.NumCols());\n      if (os.fail()) {\n        delete [] pmem;\n        goto bad;\n      }\n    }\n    delete [] pmem;\n  }\n  return true;\nbad:\n  KALDI_WARN << \"Could not write to Sphinx feature file\";\n  return false;\n}\n\ntemplate\nbool WriteSphinx(std::ostream &os, const MatrixBase<float> &M);\n\ntemplate\nbool WriteSphinx(std::ostream &os, const MatrixBase<double> &M);\n\ntemplate <typename Real>\nReal TraceMatMatMat(const MatrixBase<Real> &A, MatrixTransposeType transA,\n                    const MatrixBase<Real> &B, MatrixTransposeType transB,\n                    const MatrixBase<Real> &C, MatrixTransposeType transC) {\n  MatrixIndexT ARows = A.NumRows(), ACols = A.NumCols(), BRows = B.NumRows(),\nBCols = B.NumCols(),\n      CRows = C.NumRows(), CCols = C.NumCols();\n  if (transA == kTrans) std::swap(ARows, ACols);\n  if (transB == kTrans) std::swap(BRows, BCols);\n  if (transC == kTrans) std::swap(CRows, CCols);\n  KALDI_ASSERT( CCols == ARows && ACols == BRows && BCols == CRows &&\n\"TraceMatMatMat: args have mismatched dimensions.\");\n  if (ARows*BCols < std::min(BRows*CCols, CRows*ACols)) {\n    Matrix<Real> AB(ARows, BCols);\n    AB.AddMatMat(1.0, A, transA, B, transB, 0.0);  // AB = A * B.\n    return TraceMatMat(AB, C, transC);\n  } else if ( BRows*CCols < CRows*ACols) {\n    Matrix<Real> BC(BRows, CCols);\n    BC.AddMatMat(1.0, B, transB, C, transC, 0.0);  // BC = B * C.\n    return TraceMatMat(BC, A, transA);\n  } else {\n    Matrix<Real> CA(CRows, ACols);\n    CA.AddMatMat(1.0, C, transC, A, transA, 0.0);  // CA = C * A\n    return TraceMatMat(CA, B, transB);\n  }\n}\n\ntemplate\nfloat TraceMatMatMat(const MatrixBase<float> &A, MatrixTransposeType transA,\n                     const MatrixBase<float> &B, MatrixTransposeType transB,\n                     const MatrixBase<float> &C, MatrixTransposeType transC);\n\ntemplate\ndouble TraceMatMatMat(const MatrixBase<double> &A, MatrixTransposeType transA,\n                      const MatrixBase<double> &B, MatrixTransposeType transB,\n                      const MatrixBase<double> &C, MatrixTransposeType transC);\n\n\ntemplate <typename Real>\nReal TraceMatMatMatMat(const MatrixBase<Real> &A, MatrixTransposeType transA,\n                       const MatrixBase<Real> &B, MatrixTransposeType transB,\n                       const MatrixBase<Real> &C, MatrixTransposeType transC,\n                       const MatrixBase<Real> &D, MatrixTransposeType transD) {\n  MatrixIndexT ARows = A.NumRows(), ACols = A.NumCols(), BRows = B.NumRows(),\nBCols = B.NumCols(),\n      CRows = C.NumRows(), CCols = C.NumCols(), DRows = D.NumRows(), DCols =\nD.NumCols();\n  if (transA == kTrans) std::swap(ARows, ACols);\n  if (transB == kTrans) std::swap(BRows, BCols);\n  if (transC == kTrans) std::swap(CRows, CCols);\n  if (transD == kTrans) std::swap(DRows, DCols);\n  KALDI_ASSERT( DCols == ARows && ACols == BRows && BCols == CRows && CCols ==\nDRows && \"TraceMatMatMat: args have mismatched dimensions.\");\n  if (ARows*BCols < std::min(BRows*CCols, std::min(CRows*DCols, DRows*ACols))) {\n    Matrix<Real> AB(ARows, BCols);\n    AB.AddMatMat(1.0, A, transA, B, transB, 0.0);  // AB = A * B.\n    return TraceMatMatMat(AB, kNoTrans, C, transC, D, transD);\n  } else if ((BRows*CCols) < std::min(CRows*DCols, DRows*ACols)) {\n    Matrix<Real> BC(BRows, CCols);\n    BC.AddMatMat(1.0, B, transB, C, transC, 0.0);  // BC = B * C.\n    return TraceMatMatMat(BC, kNoTrans, D, transD, A, transA);\n  } else if (CRows*DCols < DRows*ACols) {\n    Matrix<Real> CD(CRows, DCols);\n    CD.AddMatMat(1.0, C, transC, D, transD, 0.0);  // CD = C * D\n    return TraceMatMatMat(CD, kNoTrans, A, transA, B, transB);\n  } else {\n    Matrix<Real> DA(DRows, ACols);\n    DA.AddMatMat(1.0, D, transD, A, transA, 0.0);  // DA = D * A\n    return TraceMatMatMat(DA, kNoTrans, B, transB, C, transC);\n  }\n}\n\ntemplate\nfloat TraceMatMatMatMat(const MatrixBase<float> &A, MatrixTransposeType transA,\n                        const MatrixBase<float> &B, MatrixTransposeType transB,\n                        const MatrixBase<float> &C, MatrixTransposeType transC,\n                        const MatrixBase<float> &D, MatrixTransposeType transD);\n\ntemplate\ndouble TraceMatMatMatMat(const MatrixBase<double> &A, MatrixTransposeType\ntransA,\n                         const MatrixBase<double> &B, MatrixTransposeType\ntransB,\n                         const MatrixBase<double> &C, MatrixTransposeType\ntransC,\n                         const MatrixBase<double> &D, MatrixTransposeType\ntransD);\n\ntemplate<typename Real> void  SortSvd(VectorBase<Real> *s, MatrixBase<Real> *U,\n                                   MatrixBase<Real> *Vt, bool\nsort_on_absolute_value) {\n  /// Makes sure the Svd is sorted (from greatest to least absolute value).\n  MatrixIndexT num_singval = s->Dim();\n  KALDI_ASSERT(U == NULL || U->NumCols() == num_singval);\n  KALDI_ASSERT(Vt == NULL || Vt->NumRows() == num_singval);\n\n  std::vector<std::pair<Real, MatrixIndexT> > vec(num_singval);\n  // negative because we want revese order.\n  for (MatrixIndexT d = 0; d < num_singval; d++) {\n    Real val = (*s)(d),\n        sort_val = -(sort_on_absolute_value ? std::abs(val) : val);\n    vec[d] = std::pair<Real, MatrixIndexT>(sort_val, d);\n  }\n  std::sort(vec.begin(), vec.end());\n  Vector<Real> s_copy(*s);\n  for (MatrixIndexT d = 0; d < num_singval; d++)\n    (*s)(d) = s_copy(vec[d].second);\n  if (U != NULL) {\n    Matrix<Real> Utmp(*U);\n    MatrixIndexT dim = Utmp.NumRows();\n    for (MatrixIndexT d = 0; d < num_singval; d++) {\n      MatrixIndexT oldidx = vec[d].second;\n      for (MatrixIndexT e = 0; e < dim; e++)\n        (*U)(e, d) = Utmp(e, oldidx);\n    }\n  }\n  if (Vt != NULL) {\n    Matrix<Real> Vttmp(*Vt);\n    for (MatrixIndexT d = 0; d < num_singval; d++)\n      (*Vt).Row(d).CopyFromVec(Vttmp.Row(vec[d].second));\n  }\n}\n\ntemplate\nvoid SortSvd(VectorBase<float> *s, MatrixBase<float> *U,\n             MatrixBase<float> *Vt, bool);\n\ntemplate\nvoid SortSvd(VectorBase<double> *s, MatrixBase<double> *U,\n             MatrixBase<double> *Vt, bool);\n\ntemplate<typename Real>\nvoid CreateEigenvalueMatrix(const VectorBase<Real> &re, const VectorBase<Real>\n&im,\n                            MatrixBase<Real> *D) {\n  MatrixIndexT n = re.Dim();\n  KALDI_ASSERT(im.Dim() == n && D->NumRows() == n && D->NumCols() == n);\n\n  MatrixIndexT j = 0;\n  D->SetZero();\n  while (j < n) {\n    if (im(j) == 0) {  // Real eigenvalue\n      (*D)(j, j) = re(j);\n      j++;\n    } else {  // First of a complex pair\n      KALDI_ASSERT(j+1 < n && ApproxEqual(im(j+1), -im(j))\n                   && ApproxEqual(re(j+1), re(j)));\n      /// if (im(j) < 0.0) KALDI_WARN << \"Negative first im part of pair\";  //\nTEMP\n      Real lambda = re(j), mu = im(j);\n      // create 2x2 block [lambda, mu; -mu, lambda]\n      (*D)(j, j) = lambda;\n      (*D)(j, j+1) = mu;\n      (*D)(j+1, j) = -mu;\n      (*D)(j+1, j+1) = lambda;\n      j += 2;\n    }\n  }\n}\n\ntemplate\nvoid CreateEigenvalueMatrix(const VectorBase<float> &re, const VectorBase<float>\n&im,\n                            MatrixBase<float> *D);\ntemplate\nvoid CreateEigenvalueMatrix(const VectorBase<double> &re, const\nVectorBase<double> &im,\n                            MatrixBase<double> *D);\n\n\n\ntemplate<typename Real>\nbool AttemptComplexPower(Real *x_re, Real *x_im, Real power) {\n  // Used in Matrix<Real>::Power().\n  // Attempts to take the complex value x to the power \"power\",\n  // assuming that power is fractional (i.e. we don't treat integers as a\n  // special case).  Returns false if this is not possible, either\n  // because x is negative and real (hence there is no obvious answer\n  // that is \"closest to 1\", and anyway this case does not make sense\n  // in the Matrix<Real>::Power() routine);\n  // or because power is negative, and x is zero.\n\n  // First solve for r and theta in\n  // x_re = r*cos(theta), x_im = r*sin(theta)\n  if (*x_re < 0.0 && *x_im == 0.0) return false;  // can't do\n  // it for negative real values.\n  Real r = std::sqrt((*x_re * *x_re) + (*x_im * *x_im));  // r == radius.\n  if (power < 0.0 && r == 0.0) return false;\n  Real theta = std::atan2(*x_im, *x_re);\n  // Take the power.\n  r = std::pow(r, power);\n  theta *= power;\n  *x_re = r * std::cos(theta);\n  *x_im = r * std::sin(theta);\n  return true;\n}\n\ntemplate\nbool AttemptComplexPower(float *x_re, float *x_im, float power);\ntemplate\nbool AttemptComplexPower(double *x_re, double *x_im, double power);\n\n\n\ntemplate <typename Real>\nReal TraceMatMat(const MatrixBase<Real> &A,\n                  const MatrixBase<Real> &B,\n                  MatrixTransposeType trans) {  // tr(A B), equivalent to sum of\neach element of A times same element in B'\n  MatrixIndexT aStride = A.stride_, bStride = B.stride_;\n  if (trans == kNoTrans) {\n    KALDI_ASSERT(A.NumRows() == B.NumCols() && A.NumCols() == B.NumRows());\n    Real ans = 0.0;\n    Real *adata = A.data_, *bdata = B.data_;\n    MatrixIndexT arows = A.NumRows(), acols = A.NumCols();\n    for (MatrixIndexT row = 0;row < arows;row++, adata+=aStride, bdata++)\n      ans += cblas_Xdot(acols, adata, 1, bdata, bStride);\n    return ans;\n  } else {\n    KALDI_ASSERT(A.NumRows() == B.NumRows() && A.NumCols() == B.NumCols());\n    Real ans = 0.0;\n    Real *adata = A.data_, *bdata = B.data_;\n    MatrixIndexT arows = A.NumRows(), acols = A.NumCols();\n    for (MatrixIndexT row = 0;row < arows;row++, adata+=aStride, bdata+=bStride)\n      ans += cblas_Xdot(acols, adata, 1, bdata, 1);\n    return ans;\n  }\n}\n\n\n// Instantiate the template above for float and double.\ntemplate\nfloat TraceMatMat(const MatrixBase<float> &A,\n                  const MatrixBase<float> &B,\n                  MatrixTransposeType trans);\ntemplate\ndouble TraceMatMat(const MatrixBase<double> &A,\n                  const MatrixBase<double> &B,\n                  MatrixTransposeType trans);\n\n\ntemplate<typename Real>\nReal MatrixBase<Real>::LogSumExp(Real prune) const {\n  Real sum;\n  if (sizeof(sum) == 8) sum = kLogZeroDouble;\n  else sum = kLogZeroFloat;\n  Real max_elem = Max(), cutoff;\n  if (sizeof(Real) == 4) cutoff = max_elem + kMinLogDiffFloat;\n  else cutoff = max_elem + kMinLogDiffDouble;\n  if (prune > 0.0 && max_elem - prune > cutoff) // explicit pruning...\n    cutoff = max_elem - prune;\n\n  double sum_relto_max_elem = 0.0;\n\n  for (MatrixIndexT i = 0; i < num_rows_; i++) {\n    for (MatrixIndexT j = 0; j < num_cols_; j++) {\n      BaseFloat f = (*this)(i, j);\n      if (f >= cutoff)\n        sum_relto_max_elem += kaldi::Exp(f - max_elem);\n    }\n  }\n  return max_elem + kaldi::Log(sum_relto_max_elem);\n}\n\ntemplate<typename Real>\nReal MatrixBase<Real>::ApplySoftMax() {\n  Real max = this->Max(), sum = 0.0;\n  // the 'max' helps to get in good numeric range.\n  for (MatrixIndexT i = 0; i < num_rows_; i++)\n    for (MatrixIndexT j = 0; j < num_cols_; j++)\n      sum += ((*this)(i, j) = kaldi::Exp((*this)(i, j) - max));\n  this->Scale(1.0 / sum);\n  return max + kaldi::Log(sum);\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Tanh(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n\n  if (num_cols_ == stride_ && src.num_cols_ == src.stride_) {\n    SubVector<Real> src_vec(src.data_, num_rows_ * num_cols_),\n        dst_vec(this->data_, num_rows_ * num_cols_);\n    dst_vec.Tanh(src_vec);\n  } else {\n    for (MatrixIndexT r = 0; r < num_rows_; r++) {\n      SubVector<Real> src_vec(src, r), dest_vec(*this, r);\n      dest_vec.Tanh(src_vec);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::SoftHinge(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n  int32 num_rows = num_rows_, num_cols = num_cols_;\n  for (MatrixIndexT r = 0; r < num_rows; r++) {\n    Real *row_data = this->RowData(r);\n    const Real *src_row_data = src.RowData(r);\n    for (MatrixIndexT c = 0; c < num_cols; c++) {\n      Real x = src_row_data[c], y;\n      if (x > 10.0) y = x; // avoid exponentiating large numbers; function\n      // approaches y=x.\n      else y = Log1p(kaldi::Exp(x)); // these defined in kaldi-math.h\n      row_data[c] = y;\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::GroupPnorm(const MatrixBase<Real> &src, Real power) {\n  KALDI_ASSERT(src.NumCols() % this->NumCols() == 0 &&\n               src.NumRows() == this->NumRows());\n  int group_size = src.NumCols() / this->NumCols(),\n    num_rows = this->NumRows(), num_cols = this->NumCols();\n  for (MatrixIndexT i = 0; i < num_rows; i++)\n    for (MatrixIndexT j = 0; j < num_cols; j++)\n      (*this)(i, j) = src.Row(i).Range(j * group_size,  group_size).Norm(power);\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::GroupMax(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(src.NumCols() % this->NumCols() == 0 &&\n               src.NumRows() == this->NumRows());\n  int group_size = src.NumCols() / this->NumCols(),\n      num_rows = this->NumRows(), num_cols = this->NumCols();\n  for (MatrixIndexT i = 0; i < num_rows; i++) {\n    const Real *src_row_data = src.RowData(i);\n    for (MatrixIndexT j = 0; j < num_cols; j++) {\n      Real max_val = -1e20;\n      for (MatrixIndexT k = 0; k < group_size; k++) {\n        Real src_data = src_row_data[j * group_size + k];\n        if (src_data > max_val)\n          max_val = src_data;\n      }\n      (*this)(i, j) = max_val;\n    }\n  }\n}\n*/\ntemplate <typename Real>\nvoid MatrixBase<Real>::CopyCols(const MatrixBase<Real> &src,\n                                const MatrixIndexT *indices) {\n    KALDI_ASSERT(NumRows() == src.NumRows());\n    MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n                 this_stride = stride_, src_stride = src.stride_;\n    Real *this_data = this->data_;\n    const Real *src_data = src.data_;\n#ifdef KALDI_PARANOID\n    MatrixIndexT src_cols = src.NumCols();\n    for (MatrixIndexT i = 0; i < num_cols; i++)\n        KALDI_ASSERT(indices[i] >= -1 && indices[i] < src_cols);\n#endif\n\n    // For the sake of memory locality we do this row by row, rather\n    // than doing it column-wise using cublas_Xcopy\n    for (MatrixIndexT r = 0; r < num_rows;\n         r++, this_data += this_stride, src_data += src_stride) {\n        const MatrixIndexT *index_ptr = &(indices[0]);\n        for (MatrixIndexT c = 0; c < num_cols; c++, index_ptr++) {\n            if (*index_ptr < 0)\n                this_data[c] = 0;\n            else\n                this_data[c] = src_data[*index_ptr];\n        }\n    }\n}\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddCols(const MatrixBase<Real> &src,\n                               const MatrixIndexT *indices) {\n  KALDI_ASSERT(NumRows() == src.NumRows());\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      this_stride = stride_, src_stride = src.stride_;\n  Real *this_data = this->data_;\n  const Real *src_data = src.data_;\n#ifdef KALDI_PARANOID\n  MatrixIndexT src_cols = src.NumCols();\n  for (MatrixIndexT i = 0; i < num_cols; i++)\n    KALDI_ASSERT(indices[i] >= -1 && indices[i] < src_cols);\n#endif\n\n  // For the sake of memory locality we do this row by row, rather\n  // than doing it column-wise using cublas_Xcopy\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride, src_data\n+= src_stride) {\n    const MatrixIndexT *index_ptr = &(indices[0]);\n    for (MatrixIndexT c = 0; c < num_cols; c++, index_ptr++) {\n      if (*index_ptr >= 0)\n        this_data[c] += src_data[*index_ptr];\n    }\n  }\n}*/\n\n/*\ntemplate<typename Real>\nvoid MatrixBase<Real>::CopyRows(const MatrixBase<Real> &src,\n                                const MatrixIndexT *indices) {\n  KALDI_ASSERT(NumCols() == src.NumCols());\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      this_stride = stride_;\n  Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    MatrixIndexT index = indices[r];\n    if (index < 0) memset(this_data, 0, sizeof(Real) * num_cols_);\n    else cblas_Xcopy(num_cols, src.RowData(index), 1, this_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::CopyRows(const Real *const *src) {\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    const Real *const src_data = src[r];\n    if (src_data == NULL) memset(this_data, 0, sizeof(Real) * num_cols);\n    else cblas_Xcopy(num_cols, src_data, 1, this_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::CopyToRows(Real *const *dst) const {\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  const Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    Real *const dst_data = dst[r];\n    if (dst_data != NULL)\n      cblas_Xcopy(num_cols, this_data, 1, dst_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddRows(Real alpha,\n                               const MatrixBase<Real> &src,\n                               const MatrixIndexT *indexes) {\n  KALDI_ASSERT(NumCols() == src.NumCols());\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    MatrixIndexT index = indexes[r];\n    KALDI_ASSERT(index >= -1 && index < src.NumRows());\n    if (index != -1)\n      cblas_Xaxpy(num_cols, alpha, src.RowData(index), 1, this_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddRows(Real alpha, const Real *const *src) {\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    const Real *const src_data = src[r];\n    if (src_data != NULL)\n      cblas_Xaxpy(num_cols, alpha, src_data, 1, this_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddToRows(Real alpha,\n                                 const MatrixIndexT *indexes,\n                                 MatrixBase<Real> *dst) const {\n  KALDI_ASSERT(NumCols() == dst->NumCols());\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    MatrixIndexT index = indexes[r];\n    KALDI_ASSERT(index >= -1 && index < dst->NumRows());\n    if (index != -1)\n      cblas_Xaxpy(num_cols, alpha, this_data, 1, dst->RowData(index), 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::AddToRows(Real alpha, Real *const *dst) const {\n  MatrixIndexT num_rows = num_rows_,\n      num_cols = num_cols_, this_stride = stride_;\n  const Real *this_data = this->data_;\n\n  for (MatrixIndexT r = 0; r < num_rows; r++, this_data += this_stride) {\n    Real *const dst_data = dst[r];\n    if (dst_data != NULL)\n      cblas_Xaxpy(num_cols, alpha, this_data, 1, dst_data, 1);\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::Sigmoid(const MatrixBase<Real> &src) {\n  KALDI_ASSERT(SameDim(*this, src));\n\n  if (num_cols_ == stride_ && src.num_cols_ == src.stride_) {\n    SubVector<Real> src_vec(src.data_, num_rows_ * num_cols_),\n        dst_vec(this->data_, num_rows_ * num_cols_);\n    dst_vec.Sigmoid(src_vec);\n  } else {\n    for (MatrixIndexT r = 0; r < num_rows_; r++) {\n      SubVector<Real> src_vec(src, r), dest_vec(*this, r);\n      dest_vec.Sigmoid(src_vec);\n    }\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::DiffSigmoid(const MatrixBase<Real> &value,\n                                   const MatrixBase<Real> &diff) {\n  KALDI_ASSERT(SameDim(*this, value) && SameDim(*this, diff));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      stride = stride_, value_stride = value.stride_, diff_stride =\ndiff.stride_;\n  Real *data = data_;\n  const Real *value_data = value.data_, *diff_data = diff.data_;\n  for (MatrixIndexT r = 0; r < num_rows; r++) {\n    for (MatrixIndexT c = 0; c < num_cols; c++)\n      data[c] = diff_data[c] * value_data[c] * (1.0 - value_data[c]);\n    data += stride;\n    value_data += value_stride;\n    diff_data += diff_stride;\n  }\n}\n\ntemplate<typename Real>\nvoid MatrixBase<Real>::DiffTanh(const MatrixBase<Real> &value,\n                                   const MatrixBase<Real> &diff) {\n  KALDI_ASSERT(SameDim(*this, value) && SameDim(*this, diff));\n  MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      stride = stride_, value_stride = value.stride_, diff_stride =\ndiff.stride_;\n  Real *data = data_;\n  const Real *value_data = value.data_, *diff_data = diff.data_;\n  for (MatrixIndexT r = 0; r < num_rows; r++) {\n    for (MatrixIndexT c = 0; c < num_cols; c++)\n      data[c] = diff_data[c] * (1.0 - (value_data[c] * value_data[c]));\n    data += stride;\n    value_data += value_stride;\n    diff_data += diff_stride;\n  }\n}*/\n\n/*\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::AddVecToRows(const Real alpha, const\nVectorBase<OtherReal> &v) {\n  const MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      stride = stride_;\n  KALDI_ASSERT(v.Dim() == num_cols);\n  if(num_cols <= 64) {\n    Real *data = data_;\n    const OtherReal *vdata = v.Data();\n    for (MatrixIndexT i = 0; i < num_rows; i++, data += stride) {\n      for (MatrixIndexT j = 0; j < num_cols; j++)\n        data[j] += alpha * vdata[j];\n    }\n\n  } else {\n    Vector<OtherReal> ones(num_rows);\n    ones.Set(1.0);\n    this->AddVecVec(alpha, ones, v);\n   }\n}\n\ntemplate void MatrixBase<float>::AddVecToRows(const float alpha,\n                                              const VectorBase<float> &v);\ntemplate void MatrixBase<float>::AddVecToRows(const float alpha,\n                                              const VectorBase<double> &v);\ntemplate void MatrixBase<double>::AddVecToRows(const double alpha,\n                                               const VectorBase<float> &v);\ntemplate void MatrixBase<double>::AddVecToRows(const double alpha,\n                                               const VectorBase<double> &v);\n\n\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid MatrixBase<Real>::AddVecToCols(const Real alpha, const\nVectorBase<OtherReal> &v) {\n  const MatrixIndexT num_rows = num_rows_, num_cols = num_cols_,\n      stride = stride_;\n  KALDI_ASSERT(v.Dim() == num_rows);\n\n  if (num_rows <= 64) {\n    Real *data = data_;\n    const OtherReal *vdata = v.Data();\n    for (MatrixIndexT i = 0; i < num_rows; i++, data += stride) {\n      Real to_add = alpha * vdata[i];\n      for (MatrixIndexT j = 0; j < num_cols; j++)\n        data[j] += to_add;\n    }\n\n  } else {\n    Vector<OtherReal> ones(num_cols);\n    ones.Set(1.0);\n    this->AddVecVec(alpha, v, ones);\n  }\n}\n\ntemplate void MatrixBase<float>::AddVecToCols(const float alpha,\n                                              const VectorBase<float> &v);\ntemplate void MatrixBase<float>::AddVecToCols(const float alpha,\n                                              const VectorBase<double> &v);\ntemplate void MatrixBase<double>::AddVecToCols(const double alpha,\n                                               const VectorBase<float> &v);\ntemplate void MatrixBase<double>::AddVecToCols(const double alpha,\n                                               const VectorBase<double> &v);\n*/\n// Explicit instantiation of the classes\n// Apparently, it seems to be necessary that the instantiation\n// happens at the end of the file. Otherwise, not all the member\n// functions will get instantiated.\n\ntemplate class Matrix<float>;\ntemplate class Matrix<double>;\ntemplate class MatrixBase<float>;\ntemplate class MatrixBase<double>;\ntemplate class SubMatrix<float>;\ntemplate class SubMatrix<double>;\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-matrix.h",
    "content": "// matrix/kaldi-matrix.h\n\n// Copyright 2009-2011  Ondrej Glembek;  Microsoft Corporation;  Lukas Burget;\n//                      Saarland University;  Petr Schwarz;  Yanmin Qian;\n//                      Karel Vesely;  Go Vivace Inc.;  Haihua Xu\n//           2017       Shiyin Kang\n//           2019       Yiwen Shao\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_MATRIX_KALDI_MATRIX_H_\n#define KALDI_MATRIX_KALDI_MATRIX_H_ 1\n\n#include <algorithm>\n\n#include \"matrix/matrix-common.h\"\n\nnamespace kaldi {\n\n/// @{ \\addtogroup matrix_funcs_scalar\n\n/// \\addtogroup matrix_group\n/// @{\n\n/// Base class which provides matrix operations not involving resizing\n/// or allocation.   Classes Matrix and SubMatrix inherit from it and take care\n/// of allocation and resizing.\ntemplate <typename Real>\nclass MatrixBase {\n  public:\n    // so this child can access protected members of other instances.\n    friend class Matrix<Real>;\n    friend class SubMatrix<Real>;\n    // friend declarations for CUDA matrices (see ../cudamatrix/)\n\n    /// Returns number of rows (or zero for empty matrix).\n    inline MatrixIndexT NumRows() const { return num_rows_; }\n\n    /// Returns number of columns (or zero for empty matrix).\n    inline MatrixIndexT NumCols() const { return num_cols_; }\n\n    /// Stride (distance in memory between each row).  Will be >= NumCols.\n    inline MatrixIndexT Stride() const { return stride_; }\n\n    /// Returns size in bytes of the data held by the matrix.\n    size_t SizeInBytes() const {\n        return static_cast<size_t>(num_rows_) * static_cast<size_t>(stride_) *\n               sizeof(Real);\n    }\n\n    /// Gives pointer to raw data (const).\n    inline const Real *Data() const { return data_; }\n\n    /// Gives pointer to raw data (non-const).\n    inline Real *Data() { return data_; }\n\n    /// Returns pointer to data for one row (non-const)\n    inline Real *RowData(MatrixIndexT i) {\n        KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                     static_cast<UnsignedMatrixIndexT>(num_rows_));\n        return data_ + i * stride_;\n    }\n\n    /// Returns pointer to data for one row (const)\n    inline const Real *RowData(MatrixIndexT i) const {\n        KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                     static_cast<UnsignedMatrixIndexT>(num_rows_));\n        return data_ + i * stride_;\n    }\n\n    /// Indexing operator, non-const\n    /// (only checks sizes if compiled with -DKALDI_PARANOID)\n    inline Real &operator()(MatrixIndexT r, MatrixIndexT c) {\n        KALDI_PARANOID_ASSERT(\n            static_cast<UnsignedMatrixIndexT>(r) <\n                static_cast<UnsignedMatrixIndexT>(num_rows_) &&\n            static_cast<UnsignedMatrixIndexT>(c) <\n                static_cast<UnsignedMatrixIndexT>(num_cols_));\n        return *(data_ + r * stride_ + c);\n    }\n    /// Indexing operator, provided for ease of debugging (gdb doesn't work\n    /// with parenthesis operator).\n    Real &Index(MatrixIndexT r, MatrixIndexT c) { return (*this)(r, c); }\n\n    /// Indexing operator, const\n    /// (only checks sizes if compiled with -DKALDI_PARANOID)\n    inline const Real operator()(MatrixIndexT r, MatrixIndexT c) const {\n        KALDI_PARANOID_ASSERT(\n            static_cast<UnsignedMatrixIndexT>(r) <\n                static_cast<UnsignedMatrixIndexT>(num_rows_) &&\n            static_cast<UnsignedMatrixIndexT>(c) <\n                static_cast<UnsignedMatrixIndexT>(num_cols_));\n        return *(data_ + r * stride_ + c);\n    }\n\n    /*   Basic setting-to-special values functions. */\n\n    /// Sets matrix to zero.\n    void SetZero();\n    /// Sets all elements to a specific value.\n    void Set(Real);\n    /// Sets to zero, except ones along diagonal [for non-square matrices too]\n\n    /// Copy given matrix. (no resize is done).\n    template <typename OtherReal>\n    void CopyFromMat(const MatrixBase<OtherReal> &M,\n                     MatrixTransposeType trans = kNoTrans);\n\n    /// Copy from compressed matrix.\n    // void CopyFromMat(const CompressedMatrix &M);\n\n    /// Copy given tpmatrix. (no resize is done).\n    // template<typename OtherReal>\n    // void CopyFromTp(const TpMatrix<OtherReal> &M,\n    // MatrixTransposeType trans = kNoTrans);\n\n    /// Copy from CUDA matrix.  Implemented in ../cudamatrix/cu-matrix.h\n    // template<typename OtherReal>\n    // void CopyFromMat(const CuMatrixBase<OtherReal> &M,\n    // MatrixTransposeType trans = kNoTrans);\n\n    /// This function has two modes of operation.  If v.Dim() == NumRows() *\n    /// NumCols(), then treats the vector as a row-by-row concatenation of a\n    /// matrix and copies to *this.\n    /// if v.Dim() == NumCols(), it sets each row of *this to a copy of v.\n    void CopyRowsFromVec(const VectorBase<Real> &v);\n\n    /// This version of CopyRowsFromVec is implemented in\n    /// ../cudamatrix/cu-vector.cc\n    // void CopyRowsFromVec(const CuVectorBase<Real> &v);\n\n    template <typename OtherReal>\n    void CopyRowsFromVec(const VectorBase<OtherReal> &v);\n\n    /// Copies vector into matrix, column-by-column.\n    /// Note that rv.Dim() must either equal NumRows()*NumCols() or NumRows();\n    /// this has two modes of operation.\n    void CopyColsFromVec(const VectorBase<Real> &v);\n\n    /// Copy vector into specific column of matrix.\n    void CopyColFromVec(const VectorBase<Real> &v, const MatrixIndexT col);\n    /// Copy vector into specific row of matrix.\n    void CopyRowFromVec(const VectorBase<Real> &v, const MatrixIndexT row);\n    /// Copy vector into diagonal of matrix.\n    void CopyDiagFromVec(const VectorBase<Real> &v);\n\n    /* Accessing of sub-parts of the matrix. */\n\n    /// Return specific row of matrix [const].\n    inline const SubVector<Real> Row(MatrixIndexT i) const {\n        KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                     static_cast<UnsignedMatrixIndexT>(num_rows_));\n        return SubVector<Real>(data_ + (i * stride_), NumCols());\n    }\n\n    /// Return specific row of matrix.\n    inline SubVector<Real> Row(MatrixIndexT i) {\n        KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                     static_cast<UnsignedMatrixIndexT>(num_rows_));\n        return SubVector<Real>(data_ + (i * stride_), NumCols());\n    }\n\n    /// Return a sub-part of matrix.\n    inline SubMatrix<Real> Range(const MatrixIndexT row_offset,\n                                 const MatrixIndexT num_rows,\n                                 const MatrixIndexT col_offset,\n                                 const MatrixIndexT num_cols) const {\n        return SubMatrix<Real>(\n            *this, row_offset, num_rows, col_offset, num_cols);\n    }\n    inline SubMatrix<Real> RowRange(const MatrixIndexT row_offset,\n                                    const MatrixIndexT num_rows) const {\n        return SubMatrix<Real>(*this, row_offset, num_rows, 0, num_cols_);\n    }\n    inline SubMatrix<Real> ColRange(const MatrixIndexT col_offset,\n                                    const MatrixIndexT num_cols) const {\n        return SubMatrix<Real>(*this, 0, num_rows_, col_offset, num_cols);\n    }\n\n    /*\n      /// Returns sum of all elements in matrix.\n      Real Sum() const;\n      /// Returns trace of matrix.\n      Real Trace(bool check_square = true) const;\n      // If check_square = true, will crash if matrix is not square.\n\n      /// Returns maximum element of matrix.\n      Real Max() const;\n      /// Returns minimum element of matrix.\n      Real Min() const;\n\n      /// Element by element multiplication with a given matrix.\n      void MulElements(const MatrixBase<Real> &A);\n\n      /// Divide each element by the corresponding element of a given matrix.\n      void DivElements(const MatrixBase<Real> &A);\n\n      /// Multiply each element with a scalar value.\n      void Scale(Real alpha);\n\n      /// Set, element-by-element, *this = max(*this, A)\n      void Max(const MatrixBase<Real> &A);\n      /// Set, element-by-element, *this = min(*this, A)\n      void Min(const MatrixBase<Real> &A);\n\n      /// Equivalent to (*this) = (*this) * diag(scale).  Scaling\n      /// each column by a scalar taken from that dimension of the vector.\n      void MulColsVec(const VectorBase<Real> &scale);\n\n      /// Equivalent to (*this) = diag(scale) * (*this).  Scaling\n      /// each row by a scalar taken from that dimension of the vector.\n      void MulRowsVec(const VectorBase<Real> &scale);\n\n      /// Divide each row into src.NumCols() equal groups, and then scale i'th\n      row's\n      /// j'th group of elements by src(i, j).  Requires src.NumRows() ==\n      /// this->NumRows() and this->NumCols() % src.NumCols() == 0.\n      void MulRowsGroupMat(const MatrixBase<Real> &src);\n\n      /// Returns logdet of matrix.\n      Real LogDet(Real *det_sign = NULL) const;\n\n      /// matrix inverse.\n      /// if inverse_needed = false, will fill matrix with garbage.\n      /// (only useful if logdet wanted).\n      void Invert(Real *log_det = NULL, Real *det_sign = NULL,\n                  bool inverse_needed = true);\n      /// matrix inverse [double].\n      /// if inverse_needed = false, will fill matrix with garbage\n      /// (only useful if logdet wanted).\n      /// Does inversion in double precision even if matrix was not double.\n      void InvertDouble(Real *LogDet = NULL, Real *det_sign = NULL,\n                          bool inverse_needed = true);\n    */\n    /// Inverts all the elements of the matrix\n    void InvertElements();\n    /*\n      /// Transpose the matrix.  This one is only\n      /// applicable to square matrices (the one in the\n      /// Matrix child class works also for non-square.\n      void Transpose();\n\n    */\n    /// Copies column r from column indices[r] of src.\n    /// As a special case, if indexes[i] == -1, sets column i to zero.\n    /// all elements of \"indices\" must be in [-1, src.NumCols()-1],\n    /// and src.NumRows() must equal this.NumRows()\n    void CopyCols(const MatrixBase<Real> &src, const MatrixIndexT *indices);\n\n    /// Copies row r from row indices[r] of src (does nothing\n    /// As a special case, if indexes[i] == -1, sets row i to zero.\n    /// all elements of \"indices\" must be in [-1, src.NumRows()-1],\n    /// and src.NumCols() must equal this.NumCols()\n    void CopyRows(const MatrixBase<Real> &src, const MatrixIndexT *indices);\n\n    /// Add column indices[r] of src to column r.\n    /// As a special case, if indexes[i] == -1, skip column i\n    /// indices.size() must equal this->NumCols(),\n    /// all elements of \"reorder\" must be in [-1, src.NumCols()-1],\n    /// and src.NumRows() must equal this.NumRows()\n    // void AddCols(const MatrixBase<Real> &src,\n    //            const MatrixIndexT *indices);\n\n    /// Copies row r of this matrix from an array of floats at the location\n    /// given\n    /// by src[r]. If any src[r] is NULL then this.Row(r) will be set to zero.\n    /// Note: we are using \"pointer to const pointer to const object\" for \"src\",\n    ///       because we may create \"src\" by calling Data() of const CuArray\n    void CopyRows(const Real *const *src);\n\n    /// Copies row r of this matrix to the array of floats at the location given\n    /// by dst[r]. If dst[r] is NULL, does not copy anywhere.  Requires that\n    /// none\n    /// of the memory regions pointed to by the pointers in \"dst\" overlap (e.g.\n    /// none of the pointers should be the same).\n    void CopyToRows(Real *const *dst) const;\n\n    /// Does for each row r, this.Row(r) += alpha * src.row(indexes[r]).\n    /// If indexes[r] < 0, does not add anything. all elements of \"indexes\" must\n    /// be in [-1, src.NumRows()-1], and src.NumCols() must equal\n    /// this.NumCols().\n    // void AddRows(Real alpha,\n    //             const MatrixBase<Real> &src,\n    //            const MatrixIndexT *indexes);\n\n    /// Does for each row r, this.Row(r) += alpha * src[r], treating src[r] as\n    /// the\n    /// beginning of a region of memory representing a vector of floats, of the\n    /// same length as this.NumCols(). If src[r] is NULL, does not add anything.\n    // void AddRows(Real alpha, const Real *const *src);\n\n    /// For each row r of this matrix, adds it (times alpha) to the array of\n    /// floats at the location given by dst[r]. If dst[r] is NULL, does not do\n    /// anything for that row. Requires that none of the memory regions pointed\n    /// to by the pointers in \"dst\" overlap (e.g. none of the pointers should be\n    /// the same).\n    // void AddToRows(Real alpha, Real *const *dst) const;\n\n    /// For each row i of *this, adds this->Row(i) to\n    /// dst->Row(indexes(i)) if indexes(i) >= 0, else do nothing.\n    /// Requires that all the indexes[i] that are >= 0\n    /// be distinct, otherwise the behavior is undefined.\n    // void AddToRows(Real alpha,\n    //              const MatrixIndexT *indexes,\n    //             MatrixBase<Real> *dst) const;\n    /*\n      inline void ApplyPow(Real power) {\n        this -> Pow(*this, power);\n      }\n\n\n      inline void ApplyPowAbs(Real power, bool include_sign=false) {\n        this -> PowAbs(*this, power, include_sign);\n      }\n\n      inline void ApplyHeaviside() {\n        this -> Heaviside(*this);\n      }\n\n      inline void ApplyFloor(Real floor_val) {\n        this -> Floor(*this, floor_val);\n      }\n\n      inline void ApplyCeiling(Real ceiling_val) {\n        this -> Ceiling(*this, ceiling_val);\n      }\n\n      inline void ApplyExp() {\n        this -> Exp(*this);\n      }\n\n      inline void ApplyExpSpecial() {\n        this -> ExpSpecial(*this);\n      }\n\n      inline void ApplyExpLimited(Real lower_limit, Real upper_limit) {\n        this -> ExpLimited(*this, lower_limit, upper_limit);\n      }\n\n      inline void ApplyLog() {\n        this -> Log(*this);\n      }\n    */\n    /// Eigenvalue Decomposition of a square NxN matrix into the form (*this) =\n    /// P D\n    /// P^{-1}.  Be careful: the relationship of D to the eigenvalues we output\n    /// is\n    /// slightly complicated, due to the need for P to be real.  In the\n    /// symmetric\n    /// case D is diagonal and real, but in\n    /// the non-symmetric case there may be complex-conjugate pairs of\n    /// eigenvalues.\n    /// In this case, for the equation (*this) = P D P^{-1} to hold, D must\n    /// actually\n    /// be block diagonal, with 2x2 blocks corresponding to any such pairs.  If\n    /// a\n    /// pair is lambda +- i*mu, D will have a corresponding 2x2 block\n    /// [lambda, mu; -mu, lambda].\n    /// Note that if the input matrix (*this) is non-invertible, P may not be\n    /// invertible\n    /// so in this case instead of the equation (*this) = P D P^{-1} holding, we\n    /// have\n    /// instead (*this) P = P D.\n    ///\n    /// The non-member function CreateEigenvalueMatrix creates D from eigs_real\n    /// and eigs_imag.\n    // void Eig(MatrixBase<Real> *P,\n    //        VectorBase<Real> *eigs_real,\n    //       VectorBase<Real> *eigs_imag) const;\n\n    /// The Power method attempts to take the matrix to a power using a method\n    /// that\n    /// works in general for fractional and negative powers.  The input matrix\n    /// must\n    /// be invertible and have reasonable condition (or we don't guarantee the\n    /// results.  The method is based on the eigenvalue decomposition.  It will\n    /// return false and leave the matrix unchanged, if at entry the matrix had\n    /// real negative eigenvalues (or if it had zero eigenvalues and the power\n    /// was\n    /// negative).\n    //  bool Power(Real pow);\n\n    /** Singular value decomposition\n       Major limitations:\n       For nonsquare matrices, we assume m>=n (NumRows >= NumCols), and we\n       return\n       the \"skinny\" Svd, i.e. the matrix in the middle is diagonal, and the\n       one on the left is rectangular.\n\n       In Svd, *this = U*diag(S)*Vt.\n       Null pointers for U and/or Vt at input mean we do not want that output.\n       We\n       expect that S.Dim() == m, U is either NULL or m by n,\n       and v is either NULL or n by n.\n       The singular values are not sorted (use SortSvd for that).  */\n    // void DestructiveSvd(VectorBase<Real> *s, MatrixBase<Real> *U,\n    //                   MatrixBase<Real> *Vt);  // Destroys calling matrix.\n\n    /// Compute SVD (*this) = U diag(s) Vt.   Note that the V in the call is\n    /// already\n    /// transposed; the normal formulation is U diag(s) V^T.\n    /// Null pointers for U or V mean we don't want that output (this saves\n    /// compute).  The singular values are not sorted (use SortSvd for that).\n    // void Svd(VectorBase<Real> *s, MatrixBase<Real> *U,\n    //        MatrixBase<Real> *Vt) const;\n    /// Compute SVD but only retain the singular values.\n    // void Svd(VectorBase<Real> *s) const { Svd(s, NULL, NULL); }\n\n\n    /// Returns smallest singular value.\n    // Real MinSingularValue() const {\n    // Vector<Real> tmp(std::min(NumRows(), NumCols()));\n    // Svd(&tmp);\n    // return tmp.Min();\n    //}\n\n    // void TestUninitialized() const; // This function is designed so that if\n    // any element\n    // if the matrix is uninitialized memory, valgrind will complain.\n\n    /// Returns condition number by computing Svd.  Works even if cols > rows.\n    /// Returns infinity if all singular values are zero.\n    /*\n    Real Cond() const;\n\n    /// Returns true if matrix is Symmetric.\n    bool IsSymmetric(Real cutoff = 1.0e-05) const;  // replace magic number\n\n    /// Returns true if matrix is Diagonal.\n    bool IsDiagonal(Real cutoff = 1.0e-05) const;  // replace magic number\n\n    /// Returns true if the matrix is all zeros, except for ones on diagonal.\n    (it\n    /// does not have to be square).  More specifically, this function returns\n    /// false if for any i, j, (*this)(i, j) differs by more than cutoff from\n    the\n    /// expression (i == j ? 1 : 0).\n    bool IsUnit(Real cutoff = 1.0e-05) const;     // replace magic number\n\n    /// Returns true if matrix is all zeros.\n    bool IsZero(Real cutoff = 1.0e-05) const;     // replace magic number\n\n    /// Frobenius norm, which is the sqrt of sum of square elements.  Same as\n    Schatten 2-norm,\n    /// or just \"2-norm\".\n    Real FrobeniusNorm() const;\n\n    /// Returns true if ((*this)-other).FrobeniusNorm()\n    /// <= tol * (*this).FrobeniusNorm().\n    bool ApproxEqual(const MatrixBase<Real> &other, float tol = 0.01) const;\n\n    /// Tests for exact equality.  It's usually preferable to use ApproxEqual.\n    bool Equal(const MatrixBase<Real> &other) const;\n\n    /// largest absolute value.\n    Real LargestAbsElem() const;  // largest absolute value.\n\n    /// Returns log(sum(exp())) without exp overflow\n    /// If prune > 0.0, it uses a pruning beam, discarding\n    /// terms less than (max - prune).  Note: in future\n    /// we may change this so that if prune = 0.0, it takes\n    /// the max, so use -1 if you don't want to prune.\n    Real LogSumExp(Real prune = -1.0) const;\n\n    /// Apply soft-max to the collection of all elements of the\n    /// matrix and return normalizer (log sum of exponentials).\n    Real ApplySoftMax();\n\n    /// Set each element to the sigmoid of the corresponding element of \"src\".\n    void Sigmoid(const MatrixBase<Real> &src);\n\n    /// Sets each element to the Heaviside step function (x > 0 ? 1 : 0) of the\n    /// corresponding element in \"src\".  Note: in general you can make different\n    /// choices for x = 0, but for now please leave it as it (i.e. returning\n    zero)\n    /// because it affects the RectifiedLinearComponent in the neural net code.\n    void Heaviside(const MatrixBase<Real> &src);\n\n    void Exp(const MatrixBase<Real> &src);\n\n    void Pow(const MatrixBase<Real> &src, Real power);\n\n    void Log(const MatrixBase<Real> &src);\n\n    /// Apply power to the absolute value of each element.\n    /// If include_sign is true, the result will be multiplied with\n    /// the sign of the input value.\n    /// If the power is negative and the input to the power is zero,\n    /// The output will be set zero. If include_sign is true, it will\n    /// multiply the result by the sign of the input.\n    void PowAbs(const MatrixBase<Real> &src, Real power, bool\n    include_sign=false);\n\n    void Floor(const MatrixBase<Real> &src, Real floor_val);\n\n    void Ceiling(const MatrixBase<Real> &src, Real ceiling_val);\n\n    /// For each element x of the matrix, set it to\n    /// (x < 0 ? exp(x) : x + 1).  This function is used\n    /// in our RNNLM training.\n    void ExpSpecial(const MatrixBase<Real> &src);\n\n    /// This is equivalent to running:\n    /// Floor(src, lower_limit);\n    /// Ceiling(src, upper_limit);\n    /// Exp(src)\n    void ExpLimited(const MatrixBase<Real> &src, Real lower_limit, Real\n    upper_limit);\n\n    /// Set each element to y = log(1 + exp(x))\n    void SoftHinge(const MatrixBase<Real> &src);\n\n    /// Apply the function y(i) = (sum_{j = i*G}^{(i+1)*G-1} x_j^(power))^(1 /\n    p).\n    /// Requires src.NumRows() == this->NumRows() and  src.NumCols() %\n    this->NumCols() == 0.\n    void GroupPnorm(const MatrixBase<Real> &src, Real power);\n\n    /// Calculate derivatives for the GroupPnorm function above...\n    /// if \"input\" is the input to the GroupPnorm function above (i.e. the \"src\"\n    variable),\n    /// and \"output\" is the result of the computation (i.e. the \"this\" of that\n    function\n    /// call), and *this has the same dimension as \"input\", then it sets each\n    element\n    /// of *this to the derivative d(output-elem)/d(input-elem) for each element\n    of \"input\", where\n    /// \"output-elem\" is whichever element of output depends on that input\n    element.\n    void GroupPnormDeriv(const MatrixBase<Real> &input, const MatrixBase<Real>\n    &output,\n                         Real power);\n\n    /// Apply the function y(i) = (max_{j = i*G}^{(i+1)*G-1} x_j\n    /// Requires src.NumRows() == this->NumRows() and  src.NumCols() %\n    this->NumCols() == 0.\n    void GroupMax(const MatrixBase<Real> &src);\n\n    /// Calculate derivatives for the GroupMax function above, where\n    /// \"input\" is the input to the GroupMax function above (i.e. the \"src\"\n    variable),\n    /// and \"output\" is the result of the computation (i.e. the \"this\" of that\n    function\n    /// call), and *this must have the same dimension as \"input\". Each element\n    /// of *this will be set to 1 if the corresponding input equals the output\n    of\n    /// the group, and 0 otherwise. The equals the function derivative where it\n    is\n    /// defined (it's not defined where multiple inputs in the group are equal\n    to the output).\n    void GroupMaxDeriv(const MatrixBase<Real> &input, const MatrixBase<Real>\n    &output);\n\n    /// Set each element to the tanh of the corresponding element of \"src\".\n    void Tanh(const MatrixBase<Real> &src);\n\n    // Function used in backpropagating derivatives of the sigmoid function:\n    // element-by-element, set *this = diff * value * (1.0 - value).\n    void DiffSigmoid(const MatrixBase<Real> &value,\n                     const MatrixBase<Real> &diff);\n\n    // Function used in backpropagating derivatives of the tanh function:\n    // element-by-element, set *this = diff * (1.0 - value^2).\n    void DiffTanh(const MatrixBase<Real> &value,\n                  const MatrixBase<Real> &diff);\n  */\n    /** Uses Svd to compute the eigenvalue decomposition of a symmetric positive\n     * semi-definite matrix: (*this) = rP * diag(rS) * rP^T, with rP an\n     * orthogonal matrix so rP^{-1} = rP^T.   Throws exception if input was not\n     * positive semi-definite (check_thresh controls how stringent the check is;\n     * set it to 2 to ensure it won't ever complain, but it will zero out\n     * negative\n     * dimensions in your matrix.\n     *\n     * Caution: if you want the eigenvalues, it may make more sense to convert\n     * to\n     * SpMatrix and use Eig() function there, which uses eigenvalue\n     * decomposition\n     * directly rather than SVD.\n     */\n\n    /// stream read.\n    /// Use instead of stream<<*this, if you want to add to existing contents.\n    // Will throw exception on failure.\n    void Read(std::istream &in, bool binary);\n    /// write to stream.\n    void Write(std::ostream &out, bool binary) const;\n\n    // Below is internal methods for Svd, user does not have to know about this.\n  protected:\n    ///  Initializer, callable only from child.\n    explicit MatrixBase(Real *data,\n                        MatrixIndexT cols,\n                        MatrixIndexT rows,\n                        MatrixIndexT stride)\n        : data_(data), num_cols_(cols), num_rows_(rows), stride_(stride) {\n        KALDI_ASSERT_IS_FLOATING_TYPE(Real);\n    }\n\n    ///  Initializer, callable only from child.\n    /// Empty initializer, for un-initialized matrix.\n    explicit MatrixBase() : data_(NULL) { KALDI_ASSERT_IS_FLOATING_TYPE(Real); }\n\n    // Make sure pointers to MatrixBase cannot be deleted.\n    ~MatrixBase() {}\n\n    /// A workaround that allows SubMatrix to get a pointer to non-const data\n    /// for const Matrix. Unfortunately C++ does not allow us to declare a\n    /// \"public const\" inheritance or anything like that, so it would require\n    /// a lot of work to make the SubMatrix class totally const-correct--\n    /// we would have to override many of the Matrix functions.\n    inline Real *Data_workaround() const { return data_; }\n\n    /// data memory area\n    Real *data_;\n\n    /// these attributes store the real matrix size as it is stored in memory\n    /// including memalignment\n    MatrixIndexT num_cols_;  /// < Number of columns\n    MatrixIndexT num_rows_;  /// < Number of rows\n    /** True number of columns for the internal matrix. This number may differ\n     * from num_cols_ as memory alignment might be used. */\n    MatrixIndexT stride_;\n\n  private:\n    KALDI_DISALLOW_COPY_AND_ASSIGN(MatrixBase);\n};\n\n/// A class for storing matrices.\ntemplate <typename Real>\nclass Matrix : public MatrixBase<Real> {\n  public:\n    /// Empty constructor.\n    Matrix();\n\n    /// Basic constructor.\n    Matrix(const MatrixIndexT r,\n           const MatrixIndexT c,\n           MatrixResizeType resize_type = kSetZero,\n           MatrixStrideType stride_type = kDefaultStride)\n        : MatrixBase<Real>() {\n        Resize(r, c, resize_type, stride_type);\n    }\n\n    /// Swaps the contents of *this and *other.  Shallow swap.\n    void Swap(Matrix<Real> *other);\n\n    /// Constructor from any MatrixBase. Can also copy with transpose.\n    /// Allocates new memory.\n    explicit Matrix(const MatrixBase<Real> &M,\n                    MatrixTransposeType trans = kNoTrans);\n\n    /// Same as above, but need to avoid default copy constructor.\n    Matrix(const Matrix<Real> &M);  //  (cannot make explicit)\n\n    /// Copy constructor: as above, but from another type.\n    template <typename OtherReal>\n    explicit Matrix(const MatrixBase<OtherReal> &M,\n                    MatrixTransposeType trans = kNoTrans);\n\n    /// Copy constructor taking TpMatrix...\n    // template <typename OtherReal>\n    // explicit Matrix(const TpMatrix<OtherReal> & M,\n    // MatrixTransposeType trans = kNoTrans) : MatrixBase<Real>() {\n    // if (trans == kNoTrans) {\n    // Resize(M.NumRows(), M.NumCols(), kUndefined);\n    // this->CopyFromTp(M);\n    //} else {\n    // Resize(M.NumCols(), M.NumRows(), kUndefined);\n    // this->CopyFromTp(M, kTrans);\n    //}\n    //}\n\n    /// read from stream.\n    // Unlike one in base, allows resizing.\n    void Read(std::istream &in, bool binary);\n\n    /// Remove a specified row.\n    void RemoveRow(MatrixIndexT i);\n\n    /// Transpose the matrix.  Works for non-square\n    /// matrices as well as square ones.\n    // void Transpose();\n\n    /// Distructor to free matrices.\n    ~Matrix() { Destroy(); }\n\n    /// Sets matrix to a specified size (zero is OK as long as both r and c are\n    /// zero).  The value of the new data depends on resize_type:\n    ///   -if kSetZero, the new data will be zero\n    ///   -if kUndefined, the new data will be undefined\n    ///   -if kCopyData, the new data will be the same as the old data in any\n    ///      shared positions, and zero elsewhere.\n    ///\n    /// You can set stride_type to kStrideEqualNumCols to force the stride\n    /// to equal the number of columns; by default it is set so that the stride\n    /// in bytes is a multiple of 16.\n    ///\n    /// This function takes time proportional to the number of data elements.\n    void Resize(const MatrixIndexT r,\n                const MatrixIndexT c,\n                MatrixResizeType resize_type = kSetZero,\n                MatrixStrideType stride_type = kDefaultStride);\n\n    /// Assignment operator that takes MatrixBase.\n    Matrix<Real> &operator=(const MatrixBase<Real> &other) {\n        if (MatrixBase<Real>::NumRows() != other.NumRows() ||\n            MatrixBase<Real>::NumCols() != other.NumCols())\n            Resize(other.NumRows(), other.NumCols(), kUndefined);\n        MatrixBase<Real>::CopyFromMat(other);\n        return *this;\n    }\n\n    /// Assignment operator. Needed for inclusion in std::vector.\n    Matrix<Real> &operator=(const Matrix<Real> &other) {\n        if (MatrixBase<Real>::NumRows() != other.NumRows() ||\n            MatrixBase<Real>::NumCols() != other.NumCols())\n            Resize(other.NumRows(), other.NumCols(), kUndefined);\n        MatrixBase<Real>::CopyFromMat(other);\n        return *this;\n    }\n\n\n  private:\n    /// Deallocates memory and sets to empty matrix (dimension 0, 0).\n    void Destroy();\n\n    /// Init assumes the current class contents are invalid (i.e. junk or have\n    /// already been freed), and it sets the matrix to newly allocated memory\n    /// with\n    /// the specified number of rows and columns.  r == c == 0 is acceptable.\n    /// The data\n    /// memory contents will be undefined.\n    void Init(const MatrixIndexT r,\n              const MatrixIndexT c,\n              const MatrixStrideType stride_type);\n};\n/// @} end \"addtogroup matrix_group\"\n\n/// \\addtogroup matrix_funcs_io\n/// @{\n\n/// A structure containing the HTK header.\n/// [TODO: change the style of the variables to Kaldi-compliant]\n\ntemplate <typename Real>\nclass SubMatrix : public MatrixBase<Real> {\n  public:\n    // Initialize a SubMatrix from part of a matrix; this is\n    // a bit like A(b:c, d:e) in Matlab.\n    // This initializer is against the proper semantics of \"const\", since\n    // SubMatrix can change its contents.  It would be hard to implement\n    // a \"const-safe\" version of this class.\n    SubMatrix(const MatrixBase<Real> &T,\n              const MatrixIndexT ro,  // row offset, 0 < ro < NumRows()\n              const MatrixIndexT r,   // number of rows, r > 0\n              const MatrixIndexT co,  // column offset, 0 < co < NumCols()\n              const MatrixIndexT c);  // number of columns, c > 0\n\n    // This initializer is mostly intended for use in CuMatrix and related\n    // classes.  Be careful!\n    SubMatrix(Real *data,\n              MatrixIndexT num_rows,\n              MatrixIndexT num_cols,\n              MatrixIndexT stride);\n\n    ~SubMatrix<Real>() {}\n\n    /// This type of constructor is needed for Range() to work [in Matrix base\n    /// class]. Cannot make it explicit.\n    SubMatrix<Real>(const SubMatrix &other)\n        : MatrixBase<Real>(\n              other.data_, other.num_cols_, other.num_rows_, other.stride_) {}\n\n  private:\n    /// Disallow assignment.\n    SubMatrix<Real> &operator=(const SubMatrix<Real> &other);\n};\n\n/// @} End of \"addtogroup matrix_funcs_io\".\n\n/// \\addtogroup matrix_funcs_scalar\n/// @{\n\n// Some declarations.  These are traces of products.\n\n/************************\ntemplate<typename Real>\nbool ApproxEqual(const MatrixBase<Real> &A,\n                 const MatrixBase<Real> &B, Real tol = 0.01) {\n  return A.ApproxEqual(B, tol);\n}\n\ntemplate<typename Real>\ninline void AssertEqual(const MatrixBase<Real> &A, const MatrixBase<Real> &B,\n                        float tol = 0.01) {\n  KALDI_ASSERT(A.ApproxEqual(B, tol));\n}\n\n/// Returns trace of matrix.\ntemplate <typename Real>\ndouble TraceMat(const MatrixBase<Real> &A) { return A.Trace(); }\n\n\n/// Returns tr(A B C)\ntemplate <typename Real>\nReal TraceMatMatMat(const MatrixBase<Real> &A, MatrixTransposeType transA,\n                      const MatrixBase<Real> &B, MatrixTransposeType transB,\n                      const MatrixBase<Real> &C, MatrixTransposeType transC);\n\n/// Returns tr(A B C D)\ntemplate <typename Real>\nReal TraceMatMatMatMat(const MatrixBase<Real> &A, MatrixTransposeType transA,\n                         const MatrixBase<Real> &B, MatrixTransposeType transB,\n                         const MatrixBase<Real> &C, MatrixTransposeType transC,\n                         const MatrixBase<Real> &D, MatrixTransposeType transD);\n\n/// @} end \"addtogroup matrix_funcs_scalar\"\n\n\n/// \\addtogroup matrix_funcs_misc\n/// @{\n\n\n/// Function to ensure that SVD is sorted.  This function is made as generic as\n/// possible, to be applicable to other types of problems.  s->Dim() should be\n/// the same as U->NumCols(), and we sort s from greatest to least absolute\n/// value (if sort_on_absolute_value == true) or greatest to least value\n/// otherwise, moving the columns of U, if it exists, and the rows of Vt, if it\n/// exists, around in the same way.  Note: the \"absolute value\" part won't\nmatter\n/// if this is an actual SVD, since singular values are non-negative.\ntemplate<typename Real> void SortSvd(VectorBase<Real> *s, MatrixBase<Real> *U,\n                                     MatrixBase<Real>* Vt = NULL,\n                                     bool sort_on_absolute_value = true);\n\n/// Creates the eigenvalue matrix D that is part of the decomposition used\nMatrix::Eig.\n/// D will be block-diagonal with blocks of size 1 (for real eigenvalues) or 2x2\n/// for complex pairs.  If a complex pair is lambda +- i*mu, D will have a\ncorresponding\n/// 2x2 block [lambda, mu; -mu, lambda].\n/// This function will throw if any complex eigenvalues are not in complex\nconjugate\n/// pairs (or the members of such pairs are not consecutively numbered).\ntemplate<typename Real>\nvoid CreateEigenvalueMatrix(const VectorBase<Real> &real, const VectorBase<Real>\n&imag,\n                            MatrixBase<Real> *D);\n\n/// The following function is used in Matrix::Power, and separately tested, so\nwe\n/// declare it here mainly for the testing code to see.  It takes a complex\nvalue to\n/// a power using a method that will work for noninteger powers (but will fail\nif the\n/// complex value is real and negative).\ntemplate<typename Real>\nbool AttemptComplexPower(Real *x_re, Real *x_im, Real power);\n\n**********/\n\n/// @} end of addtogroup matrix_funcs_misc\n\n/// \\addtogroup matrix_funcs_io\n/// @{\ntemplate <typename Real>\nstd::ostream &operator<<(std::ostream &Out, const MatrixBase<Real> &M);\n\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &In, MatrixBase<Real> &M);\n\n// The Matrix read allows resizing, so we override the MatrixBase one.\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &In, Matrix<Real> &M);\n\ntemplate <typename Real>\nbool SameDim(const MatrixBase<Real> &M, const MatrixBase<Real> &N) {\n    return (M.NumRows() == N.NumRows() && M.NumCols() == N.NumCols());\n}\n\n/// @} end of \\addtogroup matrix_funcs_io\n\n\n}  // namespace kaldi\n\n\n// we need to include the implementation and some\n// template specializations.\n#include \"matrix/kaldi-matrix-inl.h\"\n\n\n#endif  // KALDI_MATRIX_KALDI_MATRIX_H_\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-vector-inl.h",
    "content": "// matrix/kaldi-vector-inl.h\n\n// Copyright 2009-2011   Ondrej Glembek;  Microsoft Corporation;\n//                       Haihua Xu\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n// This is an internal header file, included by other library headers.\n// You should not attempt to use it directly.\n\n#ifndef KALDI_MATRIX_KALDI_VECTOR_INL_H_\n#define KALDI_MATRIX_KALDI_VECTOR_INL_H_ 1\n\nnamespace kaldi {\n\ntemplate <typename Real>\nstd::ostream &operator<<(std::ostream &os, const VectorBase<Real> &rv) {\n    rv.Write(os, false);\n    return os;\n}\n\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &is, VectorBase<Real> &rv) {\n    rv.Read(is, false);\n    return is;\n}\n\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &is, Vector<Real> &rv) {\n    rv.Read(is, false);\n    return is;\n}\n\n// template<>\n// template<>\n// void VectorBase<float>::AddVec(const float alpha, const VectorBase<float>\n// &rv);\n\n// template<>\n// template<>\n// void VectorBase<double>::AddVec<double>(const double alpha,\n// const VectorBase<double> &rv);\n\n}  // namespace kaldi\n\n#endif  // KALDI_MATRIX_KALDI_VECTOR_INL_H_\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-vector.cc",
    "content": "// matrix/kaldi-vector.cc\n\n// Copyright 2009-2011  Microsoft Corporation;  Lukas Burget;\n//                      Saarland University;   Go Vivace Inc.;  Ariya Rastrow;\n//                      Petr Schwarz;  Yanmin Qian;  Jan Silovsky;\n//                      Haihua Xu; Wei Shi\n//                2015  Guoguo Chen\n//                2017  Daniel Galvez\n//                2019  Yiwen Shao\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"matrix/kaldi-vector.h\"\n\n#include <algorithm>\n#include <string>\n\n#include \"matrix/kaldi-matrix.h\"\n\nnamespace kaldi {\n\ntemplate <typename Real>\ninline void Vector<Real>::Init(const MatrixIndexT dim) {\n    KALDI_ASSERT(dim >= 0);\n    if (dim == 0) {\n        this->dim_ = 0;\n        this->data_ = NULL;\n        return;\n    }\n    MatrixIndexT size;\n    void *data;\n    void *free_data;\n\n    size = dim * sizeof(Real);\n\n    if ((data = KALDI_MEMALIGN(16, size, &free_data)) != NULL) {\n        this->data_ = static_cast<Real *>(data);\n        this->dim_ = dim;\n    } else {\n        throw std::bad_alloc();\n    }\n}\n\n\ntemplate <typename Real>\nvoid Vector<Real>::Resize(const MatrixIndexT dim,\n                          MatrixResizeType resize_type) {\n    // the next block uses recursion to handle what we have to do if\n    // resize_type == kCopyData.\n    if (resize_type == kCopyData) {\n        if (this->data_ == NULL || dim == 0)\n            resize_type = kSetZero;  // nothing to copy.\n        else if (this->dim_ == dim) {\n            return;\n        }  // nothing to do.\n        else {\n            // set tmp to a vector of the desired size.\n            Vector<Real> tmp(dim, kUndefined);\n            if (dim > this->dim_) {\n                memcpy(tmp.data_, this->data_, sizeof(Real) * this->dim_);\n                memset(tmp.data_ + this->dim_,\n                       0,\n                       sizeof(Real) * (dim - this->dim_));\n            } else {\n                memcpy(tmp.data_, this->data_, sizeof(Real) * dim);\n            }\n            tmp.Swap(this);\n            // and now let tmp go out of scope, deleting what was in *this.\n            return;\n        }\n    }\n    // At this point, resize_type == kSetZero or kUndefined.\n\n    if (this->data_ != NULL) {\n        if (this->dim_ == dim) {\n            if (resize_type == kSetZero) this->SetZero();\n            return;\n        } else {\n            Destroy();\n        }\n    }\n    Init(dim);\n    if (resize_type == kSetZero) this->SetZero();\n}\n\n\n/// Copy data from another vector\ntemplate <typename Real>\nvoid VectorBase<Real>::CopyFromVec(const VectorBase<Real> &v) {\n    KALDI_ASSERT(Dim() == v.Dim());\n    if (data_ != v.data_) {\n        std::memcpy(this->data_, v.data_, dim_ * sizeof(Real));\n    }\n}\n\n/*\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid VectorBase<Real>::CopyFromPacked(const PackedMatrix<OtherReal>& M) {\n  SubVector<OtherReal> v(M);\n  this->CopyFromVec(v);\n}\n// instantiate the template.\ntemplate void VectorBase<float>::CopyFromPacked(const PackedMatrix<double>\n&other);\ntemplate void VectorBase<float>::CopyFromPacked(const PackedMatrix<float>\n&other);\ntemplate void VectorBase<double>::CopyFromPacked(const PackedMatrix<double>\n&other);\ntemplate void VectorBase<double>::CopyFromPacked(const PackedMatrix<float>\n&other);\n\n/// Load data into the vector\ntemplate<typename Real>\nvoid VectorBase<Real>::CopyFromPtr(const Real *data, MatrixIndexT sz) {\n  KALDI_ASSERT(dim_ == sz);\n  std::memcpy(this->data_, data, Dim() * sizeof(Real));\n}*/\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid VectorBase<Real>::CopyFromVec(const VectorBase<OtherReal> &other) {\n    KALDI_ASSERT(dim_ == other.Dim());\n    Real *__restrict__ ptr = data_;\n    const OtherReal *__restrict__ other_ptr = other.Data();\n    for (MatrixIndexT i = 0; i < dim_; i++) ptr[i] = other_ptr[i];\n}\n\ntemplate void VectorBase<float>::CopyFromVec(const VectorBase<double> &other);\ntemplate void VectorBase<double>::CopyFromVec(const VectorBase<float> &other);\n\n// Remove element from the vector. The vector is not reallocated\ntemplate <typename Real>\nvoid Vector<Real>::RemoveElement(MatrixIndexT i) {\n    KALDI_ASSERT(i < this->dim_ && \"Access out of vector\");\n    for (MatrixIndexT j = i + 1; j < this->dim_; j++)\n        this->data_[j - 1] = this->data_[j];\n    this->dim_--;\n}\n\n\n/// Deallocates memory and sets object to empty vector.\ntemplate <typename Real>\nvoid Vector<Real>::Destroy() {\n    /// we need to free the data block if it was defined\n    if (this->data_ != NULL) KALDI_MEMALIGN_FREE(this->data_);\n    this->data_ = NULL;\n    this->dim_ = 0;\n}\n\ntemplate <typename Real>\nvoid VectorBase<Real>::SetZero() {\n    std::memset(data_, 0, dim_ * sizeof(Real));\n}\n\ntemplate <typename Real>\nbool VectorBase<Real>::IsZero(Real cutoff) const {\n    Real abs_max = 0.0;\n    for (MatrixIndexT i = 0; i < Dim(); i++)\n        abs_max = std::max(std::abs(data_[i]), abs_max);\n    return (abs_max <= cutoff);\n}\n\n/*\ntemplate<typename Real>\nvoid VectorBase<Real>::SetRandn() {\n  kaldi::RandomState rstate;\n  MatrixIndexT last = (Dim() % 2 == 1) ? Dim() - 1 : Dim();\n  for (MatrixIndexT i = 0; i < last; i += 2) {\n    kaldi::RandGauss2(data_ + i, data_ + i + 1, &rstate);\n  }\n  if (Dim() != last) data_[last] = static_cast<Real>(kaldi::RandGauss(&rstate));\n}\n\ntemplate<typename Real>\nvoid VectorBase<Real>::SetRandUniform() {\n  kaldi::RandomState rstate;\n  for (MatrixIndexT i = 0; i < Dim(); i++) {\n    *(data_+i) = RandUniform(&rstate);\n  }\n}\n\ntemplate<typename Real>\nMatrixIndexT VectorBase<Real>::RandCategorical() const {\n  kaldi::RandomState rstate;\n  Real sum = this->Sum();\n  KALDI_ASSERT(this->Min() >= 0.0 && sum > 0.0);\n  Real r = RandUniform(&rstate) * sum;\n  Real *data = this->data_;\n  MatrixIndexT dim = this->dim_;\n  Real running_sum = 0.0;\n  for (MatrixIndexT i = 0; i < dim; i++) {\n    running_sum += data[i];\n    if (r < running_sum) return i;\n  }\n  return dim_ - 1; // Should only happen if RandUniform()\n                   // returns exactly 1, or due to roundoff.\n}*/\n\ntemplate <typename Real>\nvoid VectorBase<Real>::Set(Real f) {\n    // Why not use memset here?\n    // The basic unit of memset is a byte.\n    // If f != 0 and sizeof(Real) > 1, then we cannot use memset.\n    if (f == 0) {\n        this->SetZero();  // calls std::memset\n    } else {\n        for (MatrixIndexT i = 0; i < dim_; i++) {\n            data_[i] = f;\n        }\n    }\n}\n\ntemplate <typename Real>\nvoid VectorBase<Real>::CopyRowsFromMat(const MatrixBase<Real> &mat) {\n    KALDI_ASSERT(dim_ == mat.NumCols() * mat.NumRows());\n\n    Real *inc_data = data_;\n    const MatrixIndexT cols = mat.NumCols(), rows = mat.NumRows();\n\n    if (mat.Stride() == mat.NumCols()) {\n        memcpy(inc_data, mat.Data(), cols * rows * sizeof(Real));\n    } else {\n        for (MatrixIndexT i = 0; i < rows; i++) {\n            // copy the data to the proper position\n            memcpy(inc_data, mat.RowData(i), cols * sizeof(Real));\n            // set new copy position\n            inc_data += cols;\n        }\n    }\n}\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid VectorBase<Real>::CopyRowsFromMat(const MatrixBase<OtherReal> &mat) {\n    KALDI_ASSERT(dim_ == mat.NumCols() * mat.NumRows());\n    Real *vec_data = data_;\n    const MatrixIndexT cols = mat.NumCols(), rows = mat.NumRows();\n\n    for (MatrixIndexT i = 0; i < rows; i++) {\n        const OtherReal *mat_row = mat.RowData(i);\n        for (MatrixIndexT j = 0; j < cols; j++) {\n            vec_data[j] = static_cast<Real>(mat_row[j]);\n        }\n        vec_data += cols;\n    }\n}\n\ntemplate void VectorBase<float>::CopyRowsFromMat(const MatrixBase<double> &mat);\ntemplate void VectorBase<double>::CopyRowsFromMat(const MatrixBase<float> &mat);\n\n\ntemplate <typename Real>\nvoid VectorBase<Real>::CopyColsFromMat(const MatrixBase<Real> &mat) {\n    KALDI_ASSERT(dim_ == mat.NumCols() * mat.NumRows());\n\n    Real *inc_data = data_;\n    const MatrixIndexT cols = mat.NumCols(), rows = mat.NumRows(),\n                       stride = mat.Stride();\n    const Real *mat_inc_data = mat.Data();\n\n    for (MatrixIndexT i = 0; i < cols; i++) {\n        for (MatrixIndexT j = 0; j < rows; j++) {\n            inc_data[j] = mat_inc_data[j * stride];\n        }\n        mat_inc_data++;\n        inc_data += rows;\n    }\n}\n\ntemplate <typename Real>\nvoid VectorBase<Real>::CopyRowFromMat(const MatrixBase<Real> &mat,\n                                      MatrixIndexT row) {\n    KALDI_ASSERT(row < mat.NumRows());\n    KALDI_ASSERT(dim_ == mat.NumCols());\n    const Real *mat_row = mat.RowData(row);\n    memcpy(data_, mat_row, sizeof(Real) * dim_);\n}\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid VectorBase<Real>::CopyRowFromMat(const MatrixBase<OtherReal> &mat,\n                                      MatrixIndexT row) {\n    KALDI_ASSERT(row < mat.NumRows());\n    KALDI_ASSERT(dim_ == mat.NumCols());\n    const OtherReal *mat_row = mat.RowData(row);\n    for (MatrixIndexT i = 0; i < dim_; i++)\n        data_[i] = static_cast<Real>(mat_row[i]);\n}\n\ntemplate void VectorBase<float>::CopyRowFromMat(const MatrixBase<double> &mat,\n                                                MatrixIndexT row);\ntemplate void VectorBase<double>::CopyRowFromMat(const MatrixBase<float> &mat,\n                                                 MatrixIndexT row);\n\n/*\ntemplate<typename Real>\ntemplate<typename OtherReal>\nvoid VectorBase<Real>::CopyRowFromSp(const SpMatrix<OtherReal> &sp, MatrixIndexT\nrow) {\n  KALDI_ASSERT(row < sp.NumRows());\n  KALDI_ASSERT(dim_ == sp.NumCols());\n\n  const OtherReal *sp_data = sp.Data();\n\n  sp_data += (row*(row+1)) / 2; // takes us to beginning of this row.\n  MatrixIndexT i;\n  for (i = 0; i < row; i++) // copy consecutive elements.\n    data_[i] = static_cast<Real>(*(sp_data++));\n  for(; i < dim_; ++i, sp_data += i)\n    data_[i] = static_cast<Real>(*sp_data);\n}\n\ntemplate\nvoid VectorBase<float>::CopyRowFromSp(const SpMatrix<double> &mat, MatrixIndexT\nrow);\ntemplate\nvoid VectorBase<double>::CopyRowFromSp(const SpMatrix<float> &mat, MatrixIndexT\nrow);\ntemplate\nvoid VectorBase<float>::CopyRowFromSp(const SpMatrix<float> &mat, MatrixIndexT\nrow);\ntemplate\nvoid VectorBase<double>::CopyRowFromSp(const SpMatrix<double> &mat, MatrixIndexT\nrow);\n\n// takes absolute value of the elements to a power.\n// Throws exception if could not (but only for power != 1 and power != 2).\ntemplate<typename Real>\nvoid VectorBase<Real>::ApplyPowAbs(Real power, bool include_sign) {\n  if (power == 1.0)\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      data_[i] = (include_sign && data_[i] < 0 ? -1 : 1) * std::abs(data_[i]);\n  if (power == 2.0) {\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      data_[i] = (include_sign && data_[i] < 0 ? -1 : 1) * data_[i] * data_[i];\n  } else if (power == 0.5) {\n    for (MatrixIndexT i = 0; i < dim_; i++) {\n      data_[i] = (include_sign && data_[i] < 0 ? -1 : 1) *\nstd::sqrt(std::abs(data_[i]));\n    }\n  } else if (power < 0.0) {\n    for (MatrixIndexT i = 0; i < dim_; i++) {\n      data_[i] = (data_[i] == 0.0 ? 0.0 : pow(std::abs(data_[i]), power));\n      data_[i] *= (include_sign && data_[i] < 0 ? -1 : 1);\n      if (data_[i] == HUGE_VAL) {  // HUGE_VAL is what errno returns on error.\n        KALDI_ERR << \"Could not raise element \"  << i << \"to power \"\n                  << power << \": returned value = \" << data_[i];\n      }\n    }\n  } else {\n    for (MatrixIndexT i = 0; i < dim_; i++) {\n      data_[i] = (include_sign && data_[i] < 0 ? -1 : 1) *\npow(std::abs(data_[i]), power);\n      if (data_[i] == HUGE_VAL) {  // HUGE_VAL is what errno returns on error.\n        KALDI_ERR << \"Could not raise element \"  << i << \"to power \"\n                  << power << \": returned value = \" << data_[i];\n      }\n    }\n  }\n}\n\n// Computes the p-th norm. Throws exception if could not.\ntemplate<typename Real>\nReal VectorBase<Real>::Norm(Real p) const {\n  KALDI_ASSERT(p >= 0.0);\n  Real sum = 0.0;\n  if (p == 0.0) {\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      if (data_[i] != 0.0) sum += 1.0;\n    return sum;\n  } else if (p == 1.0) {\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      sum += std::abs(data_[i]);\n    return sum;\n  } else if (p == 2.0) {\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      sum += data_[i] * data_[i];\n    return std::sqrt(sum);\n  } else if (p == std::numeric_limits<Real>::infinity()){\n    for (MatrixIndexT i = 0; i < dim_; i++)\n      sum = std::max(sum, std::abs(data_[i]));\n    return sum;\n  } else {\n    Real tmp;\n    bool ok = true;\n    for (MatrixIndexT i = 0; i < dim_; i++) {\n      tmp = pow(std::abs(data_[i]), p);\n      if (tmp == HUGE_VAL) // HUGE_VAL is what pow returns on error.\n        ok = false;\n      sum += tmp;\n    }\n    tmp = pow(sum, static_cast<Real>(1.0/p));\n    KALDI_ASSERT(tmp != HUGE_VAL); // should not happen here.\n    if (ok) {\n      return tmp;\n    } else {\n      Real maximum = this->Max(), minimum = this->Min(),\n          max_abs = std::max(maximum, -minimum);\n      KALDI_ASSERT(max_abs > 0); // Or should not have reached here.\n      Vector<Real> tmp(*this);\n      tmp.Scale(1.0 / max_abs);\n      return tmp.Norm(p) * max_abs;\n    }\n  }\n}\n\ntemplate<typename Real>\nbool VectorBase<Real>::ApproxEqual(const VectorBase<Real> &other, float tol)\nconst {\n  if (dim_ != other.dim_) KALDI_ERR << \"ApproxEqual: size mismatch \"\n                                    << dim_ << \" vs. \" << other.dim_;\n  KALDI_ASSERT(tol >= 0.0);\n  if (tol != 0.0) {\n    Vector<Real> tmp(*this);\n    tmp.AddVec(-1.0, other);\n    return (tmp.Norm(2.0) <= static_cast<Real>(tol) * this->Norm(2.0));\n  } else { // Test for exact equality.\n    const Real *data = data_;\n    const Real *other_data = other.data_;\n    for (MatrixIndexT dim = dim_, i = 0; i < dim; i++)\n      if (data[i] != other_data[i]) return false;\n    return true;\n  }\n}\n\ntemplate<typename Real>\nReal VectorBase<Real>::Max() const {\n  Real ans = - std::numeric_limits<Real>::infinity();\n  const Real *data = data_;\n  MatrixIndexT i, dim = dim_;\n  for (i = 0; i + 4 <= dim; i += 4) {\n    Real a1 = data[i], a2 = data[i+1], a3 = data[i+2], a4 = data[i+3];\n    if (a1 > ans || a2 > ans || a3 > ans || a4 > ans) {\n      Real b1 = (a1 > a2 ? a1 : a2), b2 = (a3 > a4 ? a3 : a4);\n      if (b1 > ans) ans = b1;\n      if (b2 > ans) ans = b2;\n    }\n  }\n  for (; i < dim; i++)\n    if (data[i] > ans) ans = data[i];\n  return ans;\n}\n\ntemplate<typename Real>\nReal VectorBase<Real>::Max(MatrixIndexT *index_out) const {\n  if (dim_ == 0) KALDI_ERR << \"Empty vector\";\n  Real ans = - std::numeric_limits<Real>::infinity();\n  MatrixIndexT index = 0;\n  const Real *data = data_;\n  MatrixIndexT i, dim = dim_;\n  for (i = 0; i + 4 <= dim; i += 4) {\n    Real a1 = data[i], a2 = data[i+1], a3 = data[i+2], a4 = data[i+3];\n    if (a1 > ans || a2 > ans || a3 > ans || a4 > ans) {\n      if (a1 > ans) { ans = a1; index = i; }\n      if (a2 > ans) { ans = a2; index = i + 1; }\n      if (a3 > ans) { ans = a3; index = i + 2; }\n      if (a4 > ans) { ans = a4; index = i + 3; }\n    }\n  }\n  for (; i < dim; i++)\n    if (data[i] > ans) { ans = data[i]; index = i; }\n  *index_out = index;\n  return ans;\n}\n\ntemplate<typename Real>\nReal VectorBase<Real>::Min() const {\n  Real ans = std::numeric_limits<Real>::infinity();\n  const Real *data = data_;\n  MatrixIndexT i, dim = dim_;\n  for (i = 0; i + 4 <= dim; i += 4) {\n    Real a1 = data[i], a2 = data[i+1], a3 = data[i+2], a4 = data[i+3];\n    if (a1 < ans || a2 < ans || a3 < ans || a4 < ans) {\n      Real b1 = (a1 < a2 ? a1 : a2), b2 = (a3 < a4 ? a3 : a4);\n      if (b1 < ans) ans = b1;\n      if (b2 < ans) ans = b2;\n    }\n  }\n  for (; i < dim; i++)\n    if (data[i] < ans) ans = data[i];\n  return ans;\n}\n\ntemplate<typename Real>\nReal VectorBase<Real>::Min(MatrixIndexT *index_out) const {\n  if (dim_ == 0) KALDI_ERR << \"Empty vector\";\n  Real ans = std::numeric_limits<Real>::infinity();\n  MatrixIndexT index = 0;\n  const Real *data = data_;\n  MatrixIndexT i, dim = dim_;\n  for (i = 0; i + 4 <= dim; i += 4) {\n    Real a1 = data[i], a2 = data[i+1], a3 = data[i+2], a4 = data[i+3];\n    if (a1 < ans || a2 < ans || a3 < ans || a4 < ans) {\n      if (a1 < ans) { ans = a1; index = i; }\n      if (a2 < ans) { ans = a2; index = i + 1; }\n      if (a3 < ans) { ans = a3; index = i + 2; }\n      if (a4 < ans) { ans = a4; index = i + 3; }\n    }\n  }\n  for (; i < dim; i++)\n    if (data[i] < ans) { ans = data[i]; index = i; }\n  *index_out = index;\n  return ans;\n}*/\n\n\ntemplate <typename Real>\ntemplate <typename OtherReal>\nvoid VectorBase<Real>::CopyColFromMat(const MatrixBase<OtherReal> &mat,\n                                      MatrixIndexT col) {\n    KALDI_ASSERT(col < mat.NumCols());\n    KALDI_ASSERT(dim_ == mat.NumRows());\n    for (MatrixIndexT i = 0; i < dim_; i++) data_[i] = mat(i, col);\n    // can't do this very efficiently so don't really bother. could improve this\n    // though.\n}\n// instantiate the template above.\ntemplate void VectorBase<float>::CopyColFromMat(const MatrixBase<float> &mat,\n                                                MatrixIndexT col);\ntemplate void VectorBase<float>::CopyColFromMat(const MatrixBase<double> &mat,\n                                                MatrixIndexT col);\ntemplate void VectorBase<double>::CopyColFromMat(const MatrixBase<float> &mat,\n                                                 MatrixIndexT col);\ntemplate void VectorBase<double>::CopyColFromMat(const MatrixBase<double> &mat,\n                                                 MatrixIndexT col);\n\n// template<typename Real>\n// void VectorBase<Real>::CopyDiagFromMat(const MatrixBase<Real> &M) {\n// KALDI_ASSERT(dim_ == std::min(M.NumRows(), M.NumCols()));\n// cblas_Xcopy(dim_, M.Data(), M.Stride() + 1, data_, 1);\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::CopyDiagFromPacked(const PackedMatrix<Real> &M) {\n// KALDI_ASSERT(dim_ == M.NumCols());\n// for (MatrixIndexT i = 0; i < dim_; i++)\n// data_[i] = M(i, i);\n//// could make this more efficient.\n//}\n\n// template<typename Real>\n// Real VectorBase<Real>::Sum() const {\n//// Do a dot-product with a size-1 array with a stride of 0 to\n//// implement sum. This allows us to access SIMD operations in a\n//// cross-platform way via your BLAS library.\n// Real one(1);\n// return cblas_Xdot(dim_, data_, 1, &one, 0);\n//}\n\n// template<typename Real>\n// Real VectorBase<Real>::SumLog() const {\n// double sum_log = 0.0;\n// double prod = 1.0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// prod *= data_[i];\n//// Possible future work (arnab): change these magic values to pre-defined\n//// constants\n// if (prod < 1.0e-10 || prod > 1.0e+10) {\n// sum_log += Log(prod);\n// prod = 1.0;\n//}\n//}\n// if (prod != 1.0) sum_log += Log(prod);\n// return sum_log;\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::AddRowSumMat(Real alpha, const MatrixBase<Real> &M,\n// Real beta) {\n// KALDI_ASSERT(dim_ == M.NumCols());\n// MatrixIndexT num_rows = M.NumRows(), stride = M.Stride(), dim = dim_;\n// Real *data = data_;\n\n//// implement the function according to a dimension cutoff for computation\n/// efficiency\n// if (num_rows <= 64) {\n// cblas_Xscal(dim, beta, data, 1);\n// const Real *m_data = M.Data();\n// for (MatrixIndexT i = 0; i < num_rows; i++, m_data += stride)\n// cblas_Xaxpy(dim, alpha, m_data, 1, data, 1);\n\n//} else {\n// Vector<Real> ones(M.NumRows());\n// ones.Set(1.0);\n// this->AddMatVec(alpha, M, kTrans, ones, beta);\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::AddColSumMat(Real alpha, const MatrixBase<Real> &M,\n// Real beta) {\n// KALDI_ASSERT(dim_ == M.NumRows());\n// MatrixIndexT num_cols = M.NumCols();\n\n//// implement the function according to a dimension cutoff for computation\n/// efficiency\n// if (num_cols <= 64) {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// double sum = 0.0;\n// const Real *src = M.RowData(i);\n// for (MatrixIndexT j = 0; j < num_cols; j++)\n// sum += src[j];\n// data_[i] = alpha * sum + beta * data_[i];\n//}\n//} else {\n// Vector<Real> ones(M.NumCols());\n// ones.Set(1.0);\n// this->AddMatVec(alpha, M, kNoTrans, ones, beta);\n//}\n//}\n\n// template<typename Real>\n// Real VectorBase<Real>::LogSumExp(Real prune) const {\n// Real sum;\n// if (sizeof(sum) == 8) sum = kLogZeroDouble;\n// else sum = kLogZeroFloat;\n// Real max_elem = Max(), cutoff;\n// if (sizeof(Real) == 4) cutoff = max_elem + kMinLogDiffFloat;\n// else cutoff = max_elem + kMinLogDiffDouble;\n// if (prune > 0.0 && max_elem - prune > cutoff) // explicit pruning...\n// cutoff = max_elem - prune;\n\n// double sum_relto_max_elem = 0.0;\n\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// BaseFloat f = data_[i];\n// if (f >= cutoff)\n// sum_relto_max_elem += Exp(f - max_elem);\n//}\n// return max_elem + Log(sum_relto_max_elem);\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::InvertElements() {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = static_cast<Real>(1 / data_[i]);\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::ApplyLog() {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// if (data_[i] < 0.0)\n// KALDI_ERR << \"Trying to take log of a negative number.\";\n// data_[i] = Log(data_[i]);\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::ApplyLogAndCopy(const VectorBase<Real> &v) {\n// KALDI_ASSERT(dim_ == v.Dim());\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = Log(v(i));\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::ApplyExp() {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = Exp(data_[i]);\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::ApplyAbs() {\n// for (MatrixIndexT i = 0; i < dim_; i++) { data_[i] = std::abs(data_[i]); }\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::Floor(const VectorBase<Real> &v, Real floor_val,\n// MatrixIndexT *floored_count) {\n// KALDI_ASSERT(dim_ == v.dim_);\n// if (floored_count == nullptr) {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = std::max(v.data_[i], floor_val);\n//}\n//} else {\n// MatrixIndexT num_floored = 0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// if (v.data_[i] < floor_val) {\n// data_[i] = floor_val;\n// num_floored++;\n//} else {\n// data_[i] = v.data_[i];\n//}\n//}\n//*floored_count = num_floored;\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::Ceiling(const VectorBase<Real> &v, Real ceil_val,\n// MatrixIndexT *ceiled_count) {\n// KALDI_ASSERT(dim_ == v.dim_);\n// if (ceiled_count == nullptr) {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = std::min(v.data_[i], ceil_val);\n//}\n//} else {\n// MatrixIndexT num_changed = 0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// if (v.data_[i] > ceil_val) {\n// data_[i] = ceil_val;\n// num_changed++;\n//} else {\n// data_[i] = v.data_[i];\n//}\n//}\n//*ceiled_count = num_changed;\n//}\n//}\n\n// template<typename Real>\n// MatrixIndexT VectorBase<Real>::ApplyFloor(const VectorBase<Real> &floor_vec)\n// {\n// KALDI_ASSERT(floor_vec.Dim() == dim_);\n// MatrixIndexT num_floored = 0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// if (data_[i] < floor_vec(i)) {\n// data_[i] = floor_vec(i);\n// num_floored++;\n//}\n//}\n// return num_floored;\n//}\n\n// template<typename Real>\n// Real VectorBase<Real>::ApplySoftMax() {\n// Real max = this->Max(), sum = 0.0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// sum += (data_[i] = Exp(data_[i] - max));\n//}\n// this->Scale(1.0 / sum);\n// return max + Log(sum);\n//}\n\n// template<typename Real>\n// Real VectorBase<Real>::ApplyLogSoftMax() {\n// Real max = this->Max(), sum = 0.0;\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// sum += Exp((data_[i] -= max));\n//}\n// sum = Log(sum);\n// this->Add(-1.0 * sum);\n// return max + sum;\n//}\n\n//#ifdef HAVE_MKL\n// template<>\n// void VectorBase<float>::Tanh(const VectorBase<float> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// vsTanh(dim_, src.data_, data_);\n//}\n// template<>\n// void VectorBase<double>::Tanh(const VectorBase<double> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// vdTanh(dim_, src.data_, data_);\n//}\n//#else\n// template<typename Real>\n// void VectorBase<Real>::Tanh(const VectorBase<Real> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// Real x = src.data_[i];\n// if (x > 0.0) {\n// Real inv_expx = Exp(-x);\n// x = -1.0 + 2.0 / (1.0 + inv_expx * inv_expx);\n//} else {\n// Real expx = Exp(x);\n// x = 1.0 - 2.0 / (1.0 + expx * expx);\n//}\n// data_[i] = x;\n//}\n//}\n//#endif\n\n//#ifdef HAVE_MKL\n//// Implementing sigmoid based on tanh.\n// template<>\n// void VectorBase<float>::Sigmoid(const VectorBase<float> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// this->CopyFromVec(src);\n// this->Scale(0.5);\n// vsTanh(dim_, data_, data_);\n// this->Add(1.0);\n// this->Scale(0.5);\n//}\n// template<>\n// void VectorBase<double>::Sigmoid(const VectorBase<double> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// this->CopyFromVec(src);\n// this->Scale(0.5);\n// vdTanh(dim_, data_, data_);\n// this->Add(1.0);\n// this->Scale(0.5);\n//}\n//#else\n// template<typename Real>\n// void VectorBase<Real>::Sigmoid(const VectorBase<Real> &src) {\n// KALDI_ASSERT(dim_ == src.dim_);\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// Real x = src.data_[i];\n//// We aim to avoid floating-point overflow here.\n// if (x > 0.0) {\n// x = 1.0 / (1.0 + Exp(-x));\n//} else {\n// Real ex = Exp(x);\n// x = ex / (ex + 1.0);\n//}\n// data_[i] = x;\n//}\n//}\n//#endif\n\n\n// template<typename Real>\n// void VectorBase<Real>::Add(Real c) {\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] += c;\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::Scale(Real alpha) {\n// cblas_Xscal(dim_, alpha, data_, 1);\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::MulElements(const VectorBase<Real> &v) {\n// KALDI_ASSERT(dim_ == v.dim_);\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] *= v.data_[i];\n//}\n//}\n\n// template<typename Real>  // Set each element to y = (x == orig ? changed :\n// x).\n// void VectorBase<Real>::ReplaceValue(Real orig, Real changed) {\n// Real *data = data_;\n// for (MatrixIndexT i = 0; i < dim_; i++)\n// if (data[i] == orig) data[i] = changed;\n//}\n\n\n// template<typename Real>\n// template<typename OtherReal>\n// void VectorBase<Real>::MulElements(const VectorBase<OtherReal> &v) {\n// KALDI_ASSERT(dim_ == v.Dim());\n// const OtherReal *other_ptr = v.Data();\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] *= other_ptr[i];\n//}\n//}\n//// instantiate template.\n// template\n// void VectorBase<float>::MulElements(const VectorBase<double> &v);\n// template\n// void VectorBase<double>::MulElements(const VectorBase<float> &v);\n\n\n// template<typename Real>\n// void VectorBase<Real>::AddVecVec(Real alpha, const VectorBase<Real> &v,\n// const VectorBase<Real> &r, Real beta) {\n// KALDI_ASSERT(v.data_ != this->data_ && r.data_ != this->data_);\n//// We pretend that v is a band-diagonal matrix.\n// KALDI_ASSERT(dim_ == v.dim_ && dim_ == r.dim_);\n// cblas_Xgbmv(kNoTrans, dim_, dim_, 0, 0, alpha, v.data_, 1,\n// r.data_, 1, beta, this->data_, 1);\n//}\n\n\n// template<typename Real>\n// void VectorBase<Real>::DivElements(const VectorBase<Real> &v) {\n// KALDI_ASSERT(dim_ == v.dim_);\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] /= v.data_[i];\n//}\n//}\n\n// template<typename Real>\n// template<typename OtherReal>\n// void VectorBase<Real>::DivElements(const VectorBase<OtherReal> &v) {\n// KALDI_ASSERT(dim_ == v.Dim());\n// const OtherReal *other_ptr = v.Data();\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] /= other_ptr[i];\n//}\n//}\n//// instantiate template.\n// template\n// void VectorBase<float>::DivElements(const VectorBase<double> &v);\n// template\n// void VectorBase<double>::DivElements(const VectorBase<float> &v);\n\n// template<typename Real>\n// void VectorBase<Real>::AddVecDivVec(Real alpha, const VectorBase<Real> &v,\n// const VectorBase<Real> &rr, Real beta) {\n// KALDI_ASSERT((dim_ == v.dim_ && dim_ == rr.dim_));\n// for (MatrixIndexT i = 0; i < dim_; i++) {\n// data_[i] = alpha * v.data_[i]/rr.data_[i] + beta * data_[i] ;\n//}\n//}\n\n// template<typename Real>\n// template<typename OtherReal>\n// void VectorBase<Real>::AddVec(const Real alpha, const VectorBase<OtherReal>\n// &v) {\n// KALDI_ASSERT(dim_ == v.dim_);\n//// remove __restrict__ if it causes compilation problems.\n// Real *__restrict__ data = data_;\n// OtherReal *__restrict__ other_data = v.data_;\n// MatrixIndexT dim = dim_;\n// if (alpha != 1.0)\n// for (MatrixIndexT i = 0; i < dim; i++)\n// data[i] += alpha * other_data[i];\n// else\n// for (MatrixIndexT i = 0; i < dim; i++)\n// data[i] += other_data[i];\n//}\n\n// template\n// void VectorBase<float>::AddVec(const float alpha, const VectorBase<double>\n// &v);\n// template\n// void VectorBase<double>::AddVec(const double alpha, const VectorBase<float>\n// &v);\n\n// template<typename Real>\n// template<typename OtherReal>\n// void VectorBase<Real>::AddVec2(const Real alpha, const VectorBase<OtherReal>\n// &v) {\n// KALDI_ASSERT(dim_ == v.dim_);\n//// remove __restrict__ if it causes compilation problems.\n// Real *__restrict__ data = data_;\n// OtherReal *__restrict__ other_data = v.data_;\n// MatrixIndexT dim = dim_;\n// if (alpha != 1.0)\n// for (MatrixIndexT i = 0; i < dim; i++)\n// data[i] += alpha * other_data[i] * other_data[i];\n// else\n// for (MatrixIndexT i = 0; i < dim; i++)\n// data[i] += other_data[i] * other_data[i];\n//}\n\n// template\n// void VectorBase<float>::AddVec2(const float alpha, const VectorBase<double>\n// &v);\n// template\n// void VectorBase<double>::AddVec2(const double alpha, const VectorBase<float>\n// &v);\n\n\ntemplate <typename Real>\nvoid VectorBase<Real>::Read(std::istream &is, bool binary) {\n    //  In order to avoid rewriting this, we just declare a Vector and\n    // use it to read the data, then copy.\n    Vector<Real> tmp;\n    tmp.Read(is, binary);\n    if (tmp.Dim() != Dim())\n        KALDI_ERR << \"VectorBase<Real>::Read, size mismatch \" << Dim()\n                  << \" vs. \" << tmp.Dim();\n    CopyFromVec(tmp);\n}\n\n\ntemplate <typename Real>\nvoid Vector<Real>::Read(std::istream &is, bool binary) {\n    std::ostringstream specific_error;\n    MatrixIndexT pos_at_start = is.tellg();\n\n    if (binary) {\n        int peekval = Peek(is, binary);\n        const char *my_token = (sizeof(Real) == 4 ? \"FV\" : \"DV\");\n        char other_token_start = (sizeof(Real) == 4 ? 'D' : 'F');\n        if (peekval == other_token_start) {  // need to instantiate the other\n                                             // type to read it.\n            typedef typename OtherReal<Real>::Real OtherType;  // if Real ==\n                                                               // float,\n                                                               // OtherType ==\n                                                               // double, and\n                                                               // vice versa.\n            Vector<OtherType> other(this->Dim());\n            other.Read(is, binary);  // add is false at this point.\n            if (this->Dim() != other.Dim()) this->Resize(other.Dim());\n            this->CopyFromVec(other);\n            return;\n        }\n        std::string token;\n        ReadToken(is, binary, &token);\n        if (token != my_token) {\n            if (token.length() > 20) token = token.substr(0, 17) + \"...\";\n            specific_error << \": Expected token \" << my_token << \", got \"\n                           << token;\n            goto bad;\n        }\n        int32 size;\n        ReadBasicType(is, binary, &size);  // throws on error.\n        if ((MatrixIndexT)size != this->Dim()) this->Resize(size);\n        if (size > 0)\n            is.read(reinterpret_cast<char *>(this->data_), sizeof(Real) * size);\n        if (is.fail()) {\n            specific_error\n                << \"Error reading vector data (binary mode); truncated \"\n                   \"stream? (size = \"\n                << size << \")\";\n            goto bad;\n        }\n        return;\n    } else {  // Text mode reading; format is \" [ 1.1 2.0 3.4 ]\\n\"\n        std::string s;\n        is >> s;\n        // if ((s.compare(\"DV\") == 0) || (s.compare(\"FV\") == 0)) {  // Back\n        // compatibility.\n        //  is >> s;  // get dimension\n        //  is >> s;  // get \"[\"\n        // }\n        if (is.fail()) {\n            specific_error << \"EOF while trying to read vector.\";\n            goto bad;\n        }\n        if (s.compare(\"[]\") == 0) {\n            Resize(0);\n            return;\n        }  // tolerate this variant.\n        if (s.compare(\"[\")) {\n            if (s.length() > 20) s = s.substr(0, 17) + \"...\";\n            specific_error << \"Expected \\\"[\\\" but got \" << s;\n            goto bad;\n        }\n        std::vector<Real> data;\n        while (1) {\n            int i = is.peek();\n            if (i == '-' || (i >= '0' && i <= '9')) {  // common cases first.\n                Real r;\n                is >> r;\n                if (is.fail()) {\n                    specific_error << \"Failed to read number.\";\n                    goto bad;\n                }\n                if (!std::isspace(is.peek()) && is.peek() != ']') {\n                    specific_error << \"Expected whitespace after number.\";\n                    goto bad;\n                }\n                data.push_back(r);\n                // But don't eat whitespace... we want to check that it's not\n                // newlines\n                // which would be valid only for a matrix.\n            } else if (i == ' ' || i == '\\t') {\n                is.get();\n            } else if (i == ']') {\n                is.get();  // eat the ']'\n                this->Resize(data.size());\n                for (size_t j = 0; j < data.size(); j++)\n                    this->data_[j] = data[j];\n                i = is.peek();\n                if (static_cast<char>(i) == '\\r') {\n                    is.get();\n                    is.get();  // get \\r\\n (must eat what we wrote)\n                } else if (static_cast<char>(i) == '\\n') {\n                    is.get();\n                }  // get \\n (must eat what we wrote)\n                if (is.fail()) {\n                    KALDI_WARN << \"After end of vector data, read error.\";\n                    // we got the data we needed, so just warn for this error.\n                }\n                return;  // success.\n            } else if (i == -1) {\n                specific_error << \"EOF while reading vector data.\";\n                goto bad;\n            } else if (i == '\\n' || i == '\\r') {\n                specific_error << \"Newline found while reading vector (maybe \"\n                                  \"it's a matrix?)\";\n                goto bad;\n            } else {\n                is >> s;  // read string.\n                if (!KALDI_STRCASECMP(s.c_str(), \"inf\") ||\n                    !KALDI_STRCASECMP(s.c_str(), \"infinity\")) {\n                    data.push_back(std::numeric_limits<Real>::infinity());\n                    KALDI_WARN << \"Reading infinite value into vector.\";\n                } else if (!KALDI_STRCASECMP(s.c_str(), \"nan\")) {\n                    data.push_back(std::numeric_limits<Real>::quiet_NaN());\n                    KALDI_WARN << \"Reading NaN value into vector.\";\n                } else {\n                    if (s.length() > 20) s = s.substr(0, 17) + \"...\";\n                    specific_error << \"Expecting numeric vector data, got \"\n                                   << s;\n                    goto bad;\n                }\n            }\n        }\n    }\n// we never reach this line (the while loop returns directly).\nbad:\n    KALDI_ERR << \"Failed to read vector from stream.  \" << specific_error.str()\n              << \" File position at start is \" << pos_at_start << \", currently \"\n              << is.tellg();\n}\n\n\ntemplate <typename Real>\nvoid VectorBase<Real>::Write(std::ostream &os, bool binary) const {\n    if (!os.good()) {\n        KALDI_ERR << \"Failed to write vector to stream: stream not good\";\n    }\n    if (binary) {\n        std::string my_token = (sizeof(Real) == 4 ? \"FV\" : \"DV\");\n        WriteToken(os, binary, my_token);\n\n        int32 size = Dim();  // make the size 32-bit on disk.\n        KALDI_ASSERT(Dim() == (MatrixIndexT)size);\n        WriteBasicType(os, binary, size);\n        os.write(reinterpret_cast<const char *>(Data()), sizeof(Real) * size);\n    } else {\n        os << \" [ \";\n        for (MatrixIndexT i = 0; i < Dim(); i++) os << (*this)(i) << \" \";\n        os << \"]\\n\";\n    }\n    if (!os.good()) KALDI_ERR << \"Failed to write vector to stream\";\n}\n\n\n// template<typename Real>\n// void VectorBase<Real>::AddVec2(const Real alpha, const VectorBase<Real> &v) {\n// KALDI_ASSERT(dim_ == v.dim_);\n// for (MatrixIndexT i = 0; i < dim_; i++)\n// data_[i] += alpha * v.data_[i] * v.data_[i];\n//}\n\n//// this <-- beta*this + alpha*M*v.\n// template<typename Real>\n// void VectorBase<Real>::AddTpVec(const Real alpha, const TpMatrix<Real> &M,\n// const MatrixTransposeType trans,\n// const VectorBase<Real> &v,\n// const Real beta) {\n// KALDI_ASSERT(dim_ == v.dim_ && dim_ == M.NumRows());\n// if (beta == 0.0) {\n// if (&v != this) CopyFromVec(v);\n// MulTp(M, trans);\n// if (alpha != 1.0) Scale(alpha);\n//} else {\n// Vector<Real> tmp(v);\n// tmp.MulTp(M, trans);\n// if (beta != 1.0) Scale(beta);  // *this <-- beta * *this\n// AddVec(alpha, tmp);          // *this += alpha * M * v\n//}\n//}\n\n// template<typename Real>\n// Real VecMatVec(const VectorBase<Real> &v1, const MatrixBase<Real> &M,\n// const VectorBase<Real> &v2) {\n// KALDI_ASSERT(v1.Dim() == M.NumRows() && v2.Dim() == M.NumCols());\n// Vector<Real> vtmp(M.NumRows());\n// vtmp.AddMatVec(1.0, M, kNoTrans, v2, 0.0);\n// return VecVec(v1, vtmp);\n//}\n\n// template\n// float VecMatVec(const VectorBase<float> &v1, const MatrixBase<float> &M,\n// const VectorBase<float> &v2);\n// template\n// double VecMatVec(const VectorBase<double> &v1, const MatrixBase<double> &M,\n// const VectorBase<double> &v2);\n\ntemplate <typename Real>\nvoid Vector<Real>::Swap(Vector<Real> *other) {\n    std::swap(this->data_, other->data_);\n    std::swap(this->dim_, other->dim_);\n}\n\n\n// template<typename Real>\n// void VectorBase<Real>::AddDiagMat2(\n// Real alpha, const MatrixBase<Real> &M,\n// MatrixTransposeType trans, Real beta) {\n// if (trans == kNoTrans) {\n// KALDI_ASSERT(this->dim_ == M.NumRows());\n// MatrixIndexT rows = this->dim_, cols = M.NumCols(),\n// mat_stride = M.Stride();\n// Real *data = this->data_;\n// const Real *mat_data = M.Data();\n// for (MatrixIndexT i = 0; i < rows; i++, mat_data += mat_stride, data++)\n//*data = beta * *data + alpha * cblas_Xdot(cols,mat_data,1,mat_data,1);\n//} else {\n// KALDI_ASSERT(this->dim_ == M.NumCols());\n// MatrixIndexT rows = M.NumRows(), cols = this->dim_,\n// mat_stride = M.Stride();\n// Real *data = this->data_;\n// const Real *mat_data = M.Data();\n// for (MatrixIndexT i = 0; i < cols; i++, mat_data++, data++)\n//*data = beta * *data + alpha * cblas_Xdot(rows, mat_data, mat_stride,\n// mat_data, mat_stride);\n//}\n//}\n\n// template<typename Real>\n// void VectorBase<Real>::AddDiagMatMat(\n// Real alpha,\n// const MatrixBase<Real> &M, MatrixTransposeType transM,\n// const MatrixBase<Real> &N, MatrixTransposeType transN,\n// Real beta) {\n// MatrixIndexT dim = this->dim_,\n// M_col_dim = (transM == kTrans ? M.NumRows() : M.NumCols()),\n// N_row_dim = (transN == kTrans ? N.NumCols() : N.NumRows());\n// KALDI_ASSERT(M_col_dim == N_row_dim); // this is the dimension we sum over\n// MatrixIndexT M_row_stride = M.Stride(), M_col_stride = 1;\n// if (transM == kTrans) std::swap(M_row_stride, M_col_stride);\n// MatrixIndexT N_row_stride = N.Stride(), N_col_stride = 1;\n// if (transN == kTrans) std::swap(N_row_stride, N_col_stride);\n\n// Real *data = this->data_;\n// const Real *Mdata = M.Data(), *Ndata = N.Data();\n// for (MatrixIndexT i = 0; i < dim; i++, Mdata += M_row_stride, Ndata +=\n// N_col_stride, data++) {\n//*data = beta * *data + alpha * cblas_Xdot(M_col_dim, Mdata, M_col_stride,\n// Ndata, N_row_stride);\n//}\n//}\n\n\ntemplate class Vector<float>;\ntemplate class Vector<double>;\ntemplate class VectorBase<float>;\ntemplate class VectorBase<double>;\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/common/matrix/kaldi-vector.h",
    "content": "// matrix/kaldi-vector.h\n\n// Copyright 2009-2012   Ondrej Glembek;  Microsoft Corporation;  Lukas Burget;\n//                       Saarland University (Author: Arnab Ghoshal);\n//                       Ariya Rastrow;  Petr Schwarz;  Yanmin Qian;\n//                       Karel Vesely;  Go Vivace Inc.;  Arnab Ghoshal\n//                       Wei Shi;\n//                2015   Guoguo Chen\n//                2017   Daniel Galvez\n//                2019   Yiwen Shao\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_MATRIX_KALDI_VECTOR_H_\n#define KALDI_MATRIX_KALDI_VECTOR_H_ 1\n\n#include \"matrix/matrix-common.h\"\n\nnamespace kaldi {\n\n/// \\addtogroup matrix_group\n/// @{\n\n///  Provides a vector abstraction class.\n///  This class provides a way to work with vectors in kaldi.\n///  It encapsulates basic operations and memory optimizations.\ntemplate <typename Real>\nclass VectorBase {\n  public:\n    /// Set vector to all zeros.\n    void SetZero();\n\n    /// Returns true if matrix is all zeros.\n    bool IsZero(Real cutoff = 1.0e-06) const;  // replace magic number\n\n    /// Set all members of a vector to a specified value.\n    void Set(Real f);\n\n    /// Returns the  dimension of the vector.\n    inline MatrixIndexT Dim() const { return dim_; }\n\n    /// Returns the size in memory of the vector, in bytes.\n    inline MatrixIndexT SizeInBytes() const { return (dim_ * sizeof(Real)); }\n\n    /// Returns a pointer to the start of the vector's data.\n    inline Real *Data() { return data_; }\n\n    /// Returns a pointer to the start of the vector's data (const).\n    inline const Real *Data() const { return data_; }\n\n    /// Indexing  operator (const).\n    inline Real operator()(MatrixIndexT i) const {\n        KALDI_PARANOID_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                              static_cast<UnsignedMatrixIndexT>(dim_));\n        return *(data_ + i);\n    }\n\n    /// Indexing operator (non-const).\n    inline Real &operator()(MatrixIndexT i) {\n        KALDI_PARANOID_ASSERT(static_cast<UnsignedMatrixIndexT>(i) <\n                              static_cast<UnsignedMatrixIndexT>(dim_));\n        return *(data_ + i);\n    }\n\n    /** @brief Returns a sub-vector of a vector (a range of elements).\n     *  @param o [in] Origin, 0 < o < Dim()\n     *  @param l [in] Length 0 < l < Dim()-o\n     *  @return A SubVector object that aliases the data of the Vector object.\n     *  See @c SubVector class for details   */\n    SubVector<Real> Range(const MatrixIndexT o, const MatrixIndexT l) {\n        return SubVector<Real>(*this, o, l);\n    }\n\n    /** @brief Returns a const sub-vector of a vector (a range of elements).\n     *  @param o [in] Origin, 0 < o < Dim()\n     *  @param l [in] Length 0 < l < Dim()-o\n     *  @return A SubVector object that aliases the data of the Vector object.\n     *  See @c SubVector class for details   */\n    const SubVector<Real> Range(const MatrixIndexT o,\n                                const MatrixIndexT l) const {\n        return SubVector<Real>(*this, o, l);\n    }\n\n    /// Copy data from another vector (must match own size).\n    void CopyFromVec(const VectorBase<Real> &v);\n\n    /// Copy data from another vector of different type (double vs. float)\n    template <typename OtherReal>\n    void CopyFromVec(const VectorBase<OtherReal> &v);\n\n    /// Performs a row stack of the matrix M\n    void CopyRowsFromMat(const MatrixBase<Real> &M);\n    template <typename OtherReal>\n    void CopyRowsFromMat(const MatrixBase<OtherReal> &M);\n\n    /// Performs a column stack of the matrix M\n    void CopyColsFromMat(const MatrixBase<Real> &M);\n\n    /// Extracts a row of the matrix M.  Could also do this with\n    /// this->Copy(M[row]).\n    void CopyRowFromMat(const MatrixBase<Real> &M, MatrixIndexT row);\n    /// Extracts a row of the matrix M with type conversion.\n    template <typename OtherReal>\n    void CopyRowFromMat(const MatrixBase<OtherReal> &M, MatrixIndexT row);\n\n    /// Extracts a column of the matrix M.\n    template <typename OtherReal>\n    void CopyColFromMat(const MatrixBase<OtherReal> &M, MatrixIndexT col);\n\n    /// Reads from C++ stream (option to add to existing contents).\n    /// Throws exception on failure\n    void Read(std::istream &in, bool binary);\n\n    /// Writes to C++ stream (option to write in binary).\n    void Write(std::ostream &Out, bool binary) const;\n\n    friend class VectorBase<double>;\n    friend class VectorBase<float>;\n\n  protected:\n    /// Destructor;  does not deallocate memory, this is handled by child\n    /// classes.\n    /// This destructor is protected so this object can only be\n    /// deleted via a child.\n    ~VectorBase() {}\n\n    /// Empty initializer, corresponds to vector of zero size.\n    explicit VectorBase() : data_(NULL), dim_(0) {\n        KALDI_ASSERT_IS_FLOATING_TYPE(Real);\n    }\n\n    /// data memory area\n    Real *data_;\n    /// dimension of vector\n    MatrixIndexT dim_;\n    KALDI_DISALLOW_COPY_AND_ASSIGN(VectorBase);\n};  // class VectorBase\n\n/** @brief A class representing a vector.\n *\n *  This class provides a way to work with vectors in kaldi.\n *  It encapsulates basic operations and memory optimizations.  */\ntemplate <typename Real>\nclass Vector : public VectorBase<Real> {\n  public:\n    /// Constructor that takes no arguments.  Initializes to empty.\n    Vector() : VectorBase<Real>() {}\n\n    /// Constructor with specific size.  Sets to all-zero by default\n    /// if set_zero == false, memory contents are undefined.\n    explicit Vector(const MatrixIndexT s,\n                    MatrixResizeType resize_type = kSetZero)\n        : VectorBase<Real>() {\n        Resize(s, resize_type);\n    }\n\n    /// Copy constructor from CUDA vector\n    /// This is defined in ../cudamatrix/cu-vector.h\n    // template<typename OtherReal>\n    // explicit Vector(const CuVectorBase<OtherReal> &cu);\n\n    /// Copy constructor.  The need for this is controversial.\n    Vector(const Vector<Real> &v)\n        : VectorBase<Real>() {  //  (cannot be explicit)\n        Resize(v.Dim(), kUndefined);\n        this->CopyFromVec(v);\n    }\n\n    /// Copy-constructor from base-class, needed to copy from SubVector.\n    explicit Vector(const VectorBase<Real> &v) : VectorBase<Real>() {\n        Resize(v.Dim(), kUndefined);\n        this->CopyFromVec(v);\n    }\n\n    /// Type conversion constructor.\n    template <typename OtherReal>\n    explicit Vector(const VectorBase<OtherReal> &v) : VectorBase<Real>() {\n        Resize(v.Dim(), kUndefined);\n        this->CopyFromVec(v);\n    }\n\n    // Took this out since it is unsafe : Arnab\n    //  /// Constructor from a pointer and a size; copies the data to a location\n    //  /// it owns.\n    //  Vector(const Real* Data, const MatrixIndexT s): VectorBase<Real>() {\n    //    Resize(s);\n    //    CopyFromPtr(Data, s);\n    //  }\n\n\n    /// Swaps the contents of *this and *other.  Shallow swap.\n    void Swap(Vector<Real> *other);\n\n    /// Destructor.  Deallocates memory.\n    ~Vector() { Destroy(); }\n\n    /// Read function using C++ streams.  Can also add to existing contents\n    /// of matrix.\n    void Read(std::istream &in, bool binary);\n\n    /// Set vector to a specified size (can be zero).\n    /// The value of the new data depends on resize_type:\n    ///   -if kSetZero, the new data will be zero\n    ///   -if kUndefined, the new data will be undefined\n    ///   -if kCopyData, the new data will be the same as the old data in any\n    ///      shared positions, and zero elsewhere.\n    /// This function takes time proportional to the number of data elements.\n    void Resize(MatrixIndexT length, MatrixResizeType resize_type = kSetZero);\n\n    /// Remove one element and shifts later elements down.\n    void RemoveElement(MatrixIndexT i);\n\n    /// Assignment operator.\n    Vector<Real> &operator=(const Vector<Real> &other) {\n        Resize(other.Dim(), kUndefined);\n        this->CopyFromVec(other);\n        return *this;\n    }\n\n    /// Assignment operator that takes VectorBase.\n    Vector<Real> &operator=(const VectorBase<Real> &other) {\n        Resize(other.Dim(), kUndefined);\n        this->CopyFromVec(other);\n        return *this;\n    }\n\n  private:\n    /// Init assumes the current contents of the class are invalid (i.e. junk or\n    /// has already been freed), and it sets the vector to newly allocated\n    /// memory\n    /// with the specified dimension.  dim == 0 is acceptable.  The memory\n    /// contents\n    /// pointed to by data_ will be undefined.\n    void Init(const MatrixIndexT dim);\n\n    /// Destroy function, called internally.\n    void Destroy();\n};\n\n\n/// Represents a non-allocating general vector which can be defined\n/// as a sub-vector of higher-level vector [or as the row of a matrix].\ntemplate <typename Real>\nclass SubVector : public VectorBase<Real> {\n  public:\n    /// Constructor from a Vector or SubVector.\n    /// SubVectors are not const-safe and it's very hard to make them\n    /// so for now we just give up.  This function contains const_cast.\n    SubVector(const VectorBase<Real> &t,\n              const MatrixIndexT origin,\n              const MatrixIndexT length)\n        : VectorBase<Real>() {\n        // following assert equiv to origin>=0 && length>=0 &&\n        // origin+length <= rt.dim_\n        KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(origin) +\n                         static_cast<UnsignedMatrixIndexT>(length) <=\n                     static_cast<UnsignedMatrixIndexT>(t.Dim()));\n        VectorBase<Real>::data_ = const_cast<Real *>(t.Data() + origin);\n        VectorBase<Real>::dim_ = length;\n    }\n\n    /// This constructor initializes the vector to point at the contents\n    /// of this packed matrix (SpMatrix or TpMatrix).\n    // SubVector(const PackedMatrix<Real> &M) {\n    // VectorBase<Real>::data_ = const_cast<Real*> (M.Data());\n    // VectorBase<Real>::dim_   = (M.NumRows()*(M.NumRows()+1))/2;\n    //}\n\n    /// Copy constructor\n    SubVector(const SubVector &other) : VectorBase<Real>() {\n        // this copy constructor needed for Range() to work in base class.\n        VectorBase<Real>::data_ = other.data_;\n        VectorBase<Real>::dim_ = other.dim_;\n    }\n\n    /// Constructor from a pointer to memory and a length.  Keeps a pointer\n    /// to the data but does not take ownership (will never delete).\n    /// Caution: this constructor enables you to evade const constraints.\n    SubVector(const Real *data, MatrixIndexT length) : VectorBase<Real>() {\n        VectorBase<Real>::data_ = const_cast<Real *>(data);\n        VectorBase<Real>::dim_ = length;\n    }\n\n    /// This operation does not preserve const-ness, so be careful.\n    SubVector(const MatrixBase<Real> &matrix, MatrixIndexT row) {\n        VectorBase<Real>::data_ = const_cast<Real *>(matrix.RowData(row));\n        VectorBase<Real>::dim_ = matrix.NumCols();\n    }\n\n    ~SubVector() {}  ///< Destructor (does nothing; no pointers are owned here).\n\n  private:\n    /// Disallow assignment operator.\n    SubVector &operator=(const SubVector &other) {}\n};\n\n/// @} end of \"addtogroup matrix_group\"\n/// \\addtogroup matrix_funcs_io\n/// @{\n/// Output to a C++ stream.  Non-binary by default (use Write for\n/// binary output).\ntemplate <typename Real>\nstd::ostream &operator<<(std::ostream &out, const VectorBase<Real> &v);\n\n/// Input from a C++ stream.  Will automatically read text or\n/// binary data from the stream.\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &in, VectorBase<Real> &v);\n\n/// Input from a C++ stream. Will automatically read text or\n/// binary data from the stream.\ntemplate <typename Real>\nstd::istream &operator>>(std::istream &in, Vector<Real> &v);\n/// @} end of \\addtogroup matrix_funcs_io\n\n/// \\addtogroup matrix_funcs_scalar\n/// @{\n\n\n// template<typename Real>\n// bool ApproxEqual(const VectorBase<Real> &a,\n// const VectorBase<Real> &b, Real tol = 0.01) {\n// return a.ApproxEqual(b, tol);\n//}\n\n// template<typename Real>\n// inline void AssertEqual(VectorBase<Real> &a, VectorBase<Real> &b,\n// float tol = 0.01) {\n// KALDI_ASSERT(a.ApproxEqual(b, tol));\n//}\n\n\n}  // namespace kaldi\n\n// we need to include the implementation\n#include \"matrix/kaldi-vector-inl.h\"\n\n\n#endif  // KALDI_MATRIX_KALDI_VECTOR_H_\n"
  },
  {
    "path": "runtime/engine/common/matrix/matrix-common.h",
    "content": "// matrix/matrix-common.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_MATRIX_MATRIX_COMMON_H_\n#define KALDI_MATRIX_MATRIX_COMMON_H_\n\n// This file contains some #includes, forward declarations\n// and typedefs that are needed by all the main header\n// files in this directory.\n\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n// this enums equal to CblasTrans and CblasNoTrans constants from CBLAS library\n// we are writing them as literals because we don't want to include here\n// matrix/kaldi-blas.h,\n// which puts many symbols into global scope (like \"real\") via the header f2c.h\ntypedef enum {\n    kTrans = 112,   // = CblasTrans\n    kNoTrans = 111  // = CblasNoTrans\n} MatrixTransposeType;\n\ntypedef enum { kSetZero, kUndefined, kCopyData } MatrixResizeType;\n\n\ntypedef enum {\n    kDefaultStride,\n    kStrideEqualNumCols,\n} MatrixStrideType;\n\ntypedef enum {\n    kTakeLower,\n    kTakeUpper,\n    kTakeMean,\n    kTakeMeanAndCheck\n} SpCopyType;\n\ntemplate <typename Real>\nclass VectorBase;\ntemplate <typename Real>\nclass Vector;\ntemplate <typename Real>\nclass SubVector;\ntemplate <typename Real>\nclass MatrixBase;\ntemplate <typename Real>\nclass SubMatrix;\ntemplate <typename Real>\nclass Matrix;\n\n\n/// This class provides a way for switching between double and float types.\ntemplate <typename T>\nclass OtherReal {};  // useful in reading+writing routines\n                     // to switch double and float.\n/// A specialized class for switching from float to double.\ntemplate <>\nclass OtherReal<float> {\n  public:\n    typedef double Real;\n};\n/// A specialized class for switching from double to float.\ntemplate <>\nclass OtherReal<double> {\n  public:\n    typedef float Real;\n};\n\n\ntypedef int32 MatrixIndexT;\ntypedef int32 SignedMatrixIndexT;\ntypedef uint32 UnsignedMatrixIndexT;\n\n// If you want to use size_t for the index type, do as follows instead:\n// typedef size_t MatrixIndexT;\n// typedef ssize_t SignedMatrixIndexT;\n// typedef size_t UnsignedMatrixIndexT;\n}  // namespace kaldi\n\n\n#endif  // KALDI_MATRIX_MATRIX_COMMON_H_\n"
  },
  {
    "path": "runtime/engine/common/utils/CMakeLists.txt",
    "content": "\n\nset(csrc   \n  file_utils.cc\n  math.cc\n  strings.cc\n  audio_process.cc\n  timer.cc\n)\n\nadd_library(utils ${csrc})\n\nif(WITH_TESTING)\n  enable_testing()\n  \n  if(ANDROID)\n  else() # UNIX\n      link_libraries(gtest_main gmock)\n  \n      add_executable(strings_test strings_test.cc)\n      target_link_libraries(strings_test PUBLIC utils)\n      add_test(\n        NAME strings_test\n        COMMAND strings_test\n      )\n  endif()\nendif()\n\n"
  },
  {
    "path": "runtime/engine/common/utils/audio_process.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"utils/audio_process.h\"\n\nnamespace ppspeech{\n\nint WaveformFloatNormal(std::vector<float>* waveform) {\n    int tot_samples = waveform->size();\n    for (int i = 0; i < tot_samples; i++) {\n        (*waveform)[i] = (*waveform)[i] / 32768.0;\n    }\n    return 0;\n}\n\nint WaveformNormal(std::vector<float>* waveform,\n                   bool wav_normal,\n                   const std::string& wav_normal_type,\n                   float wav_norm_mul_factor) {\n    if (wav_normal == false) {\n        return 0;\n    }\n    if (wav_normal_type == \"linear\") {\n        float amax = INT32_MIN;\n        for (int i = 0; i < waveform->size(); ++i) {\n            float tmp = std::abs((*waveform)[i]);\n            amax = std::max(amax, tmp);\n        }\n        float factor = 1.0 / (amax + 1e-8);\n        for (int i = 0; i < waveform->size(); ++i) {\n            (*waveform)[i] = (*waveform)[i] * factor * wav_norm_mul_factor;\n        }\n    } else if (wav_normal_type == \"gaussian\") {\n        double sum = std::accumulate(waveform->begin(), waveform->end(), 0.0);\n        double mean = sum / waveform->size();  //均值\n\n        double accum = 0.0;\n        std::for_each(waveform->begin(), waveform->end(), [&](const double d) {\n            accum += (d - mean) * (d - mean);\n        });\n\n        double stdev = sqrt(accum / (waveform->size() - 1));  //方差\n        stdev = std::max(stdev, 1e-8);\n\n        for (int i = 0; i < waveform->size(); ++i) {\n            (*waveform)[i] =\n                wav_norm_mul_factor * ((*waveform)[i] - mean) / stdev;\n        }\n    } else {\n        printf(\"don't support\\n\");\n        return -1;\n    }\n    return 0;\n}\n\nfloat PowerTodb(float in, float ref_value, float amin, float top_db) {\n    if (amin <= 0) {\n        printf(\"amin must be strictly positive\\n\");\n        return -1;\n    }\n\n    if (ref_value <= 0) {\n        printf(\"ref_value must be strictly positive\\n\");\n        return -1;\n    }\n\n    float out = 10.0 * log10(std::max(amin, in));\n    out -= 10.0 * log10(std::max(ref_value, amin));\n    return out;\n}\n\n} // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/utils/audio_process.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <math.h>\n\nnamespace ppspeech{\nint WaveformFloatNormal(std::vector<float>* waveform);\nint WaveformNormal(std::vector<float>* waveform,\n                    bool wav_normal,\n                    const std::string& wav_normal_type,\n                    float wav_norm_mul_factor);\nfloat PowerTodb(float in,\n                float ref_value = 1.0,\n                float amin = 1e-10,\n                float top_db = 80.0);\n} // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/utils/blank_process_test.cc",
    "content": "#include \"utils/blank_process.h\"\n\n#include <gtest/gtest.h>\n#include <gmock/gmock.h>\n\nTEST(BlankProcess, BlankProcessTest) {\n    std::string test_str = \"我 今天 去 了 超市 花了 120 元。\";\n    std::string out_str = ppspeech::BlankProcess(test_str);\n    int ret = out_str.compare(\"我今天去了超市花了120元。\");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"how are you today\";\n    out_str = ppspeech::BlankProcess(test_str);\n    ret = out_str.compare(\"how are you today\");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"我 的 paper 在 哪里？\";\n    out_str = ppspeech::BlankProcess(test_str);\n    ret = out_str.compare(\"我的paper在哪里？\");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"我 今天     去 了 超市     花了   120 元。\";\n    out_str = ppspeech::BlankProcess(test_str);\n    ret = out_str.compare(\"我今天去了超市花了120元。\");\n    EXPECT_EQ(ret, 0);\n}"
  },
  {
    "path": "runtime/engine/common/utils/file_utils.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"utils/file_utils.h\"\n\n#include <sys/stat.h>\n\nnamespace ppspeech {\n\nbool ReadFileToVector(const std::string& filename,\n                      std::vector<std::string>* vocabulary) {\n    std::ifstream file_in(filename);\n    if (!file_in) {\n        std::cerr << \"please input a valid file\" << std::endl;\n        return false;\n    }\n\n    std::string line;\n    while (std::getline(file_in, line)) {\n        vocabulary->emplace_back(line);\n    }\n\n    return true;\n}\n\nstd::string ReadFile2String(const std::string& path) {\n    std::ifstream input_file(path);\n    if (!input_file.is_open()) {\n        std::cerr << \"please input a valid file\" << std::endl;\n    }\n    return std::string((std::istreambuf_iterator<char>(input_file)),\n                       std::istreambuf_iterator<char>());\n}\n\nbool FileExists(const std::string& strFilename) { \n    // this function if from:\n    // https://github.com/kaldi-asr/kaldi/blob/master/src/fstext/deterministic-fst-test.cc\n    struct stat stFileInfo; \n    bool blnReturn; \n    int intStat; \n\n    // Attempt to get the file attributes \n    intStat = stat(strFilename.c_str(), &stFileInfo); \n    if (intStat == 0) { \n      // We were able to get the file attributes \n      // so the file obviously exists. \n      blnReturn = true; \n    } else { \n      // We were not able to get the file attributes. \n      // This may mean that we don't have permission to \n      // access the folder which contains this file. If you \n      // need to do that level of checking, lookup the \n      // return values of stat which will give you \n      // more details on why stat failed. \n      blnReturn = false; \n    } \n   \n    return blnReturn; \n}\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/utils/file_utils.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/common.h\"\n\nnamespace ppspeech {\n\nbool ReadFileToVector(const std::string& filename,\n                      std::vector<std::string>* data);\n\nstd::string ReadFile2String(const std::string& path);\n\nbool FileExists(const std::string& filename);\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/utils/math.cc",
    "content": "\n// Copyright (c) 2021 Mobvoi Inc (Zhendong Peng)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"utils/math.h\"\n#include \"base/basic_types.h\"\n\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <string>\n#include <utility>\n#include <vector>\n\n\nnamespace ppspeech {\n\n// Sum in log scale\nfloat LogSumExp(float x, float y) {\n    if (x <= -kBaseFloatMax) return y;\n    if (y <= -kBaseFloatMax) return x;\n    float max = std::max(x, y);\n    return max + std::log(std::exp(x - max) + std::exp(y - max));\n}\n\n// greater compare for smallest priority_queue\ntemplate <typename T>\nstruct ValGreaterComp {\n    bool operator()(const std::pair<T, int32_t>& lhs,\n                    const std::pair<T, int32_t>& rhs) const {\n        return lhs.first > rhs.first ||\n               (lhs.first == rhs.first && lhs.second < rhs.second);\n    }\n};\n\ntemplate <typename T>\nvoid TopK(const std::vector<T>& data,\n          int32_t k,\n          std::vector<T>* values,\n          std::vector<int>* indices) {\n    int n = data.size();\n    int min_k_n = std::min(k, n);\n\n    // smallest heap, (val, idx)\n    std::vector<std::pair<T, int32_t>> smallest_heap;\n    for (int i = 0; i < min_k_n; i++) {\n        smallest_heap.emplace_back(data[i], i);\n    }\n\n    // smallest priority_queue\n    std::priority_queue<std::pair<T, int32_t>,\n                        std::vector<std::pair<T, int32_t>>,\n                        ValGreaterComp<T>>\n        pq(ValGreaterComp<T>(), std::move(smallest_heap));\n\n    // top k\n    for (int i = k; i < n; i++) {\n        if (pq.top().first < data[i]) {\n            pq.pop();\n            pq.emplace(data[i], i);\n        }\n    }\n\n    values->resize(min_k_n);\n    indices->resize(min_k_n);\n\n    // from largest to samllest\n    int cur = values->size() - 1;\n    while (!pq.empty()) {\n        const auto& item = pq.top();\n\n        (*values)[cur] = item.first;\n        (*indices)[cur] = item.second;\n\n        // item if reference, must pop here\n        pq.pop();\n\n        cur--;\n    }\n}\n\ntemplate void TopK<float>(const std::vector<float>& data,\n                          int32_t k,\n                          std::vector<float>* values,\n                          std::vector<int>* indices);\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/utils/math.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <cstdint>\n#include <vector>\n\nnamespace ppspeech {\n\n// Sum in log scale\nfloat LogSumExp(float x, float y);\n\ntemplate <typename T>\nvoid TopK(const std::vector<T>& data,\n          int32_t k,\n          std::vector<T>* values,\n          std::vector<int>* indices);\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/utils/picojson.h",
    "content": "/*\n * Copyright 2009-2010 Cybozu Labs, Inc.\n * Copyright 2011-2014 Kazuho Oku\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef picojson_h\n#define picojson_h\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <iostream>\n#include <iterator>\n#include <limits>\n#include <map>\n#include <stdexcept>\n#include <string>\n#include <utility>\n#include <vector>\n\n#define PICOJSON_USE_INT64 1\n\n// for isnan/isinf\n#if __cplusplus >= 201103L\n#include <cmath>\n#else\nextern \"C\" {\n#ifdef _MSC_VER\n#include <float.h>\n#elif defined(__INTEL_COMPILER)\n#include <mathimf.h>\n#else\n#include <math.h>\n#endif\n}\n#endif\n\n#ifndef PICOJSON_USE_RVALUE_REFERENCE\n#if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || \\\n    (defined(_MSC_VER) && _MSC_VER >= 1600)\n#define PICOJSON_USE_RVALUE_REFERENCE 1\n#else\n#define PICOJSON_USE_RVALUE_REFERENCE 0\n#endif\n#endif  // PICOJSON_USE_RVALUE_REFERENCE\n\n#ifndef PICOJSON_NOEXCEPT\n#if PICOJSON_USE_RVALUE_REFERENCE\n#define PICOJSON_NOEXCEPT noexcept\n#else\n#define PICOJSON_NOEXCEPT throw()\n#endif\n#endif\n\n// experimental support for int64_t (see README.mkdn for detail)\n#ifdef PICOJSON_USE_INT64\n#define __STDC_FORMAT_MACROS\n#include <cerrno>\n#if __cplusplus >= 201103L\n#include <cinttypes>\n#else\nextern \"C\" {\n#include <inttypes.h>\n}\n#endif\n#endif\n\n// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0\n#ifndef PICOJSON_USE_LOCALE\n#define PICOJSON_USE_LOCALE 1\n#endif\n#if PICOJSON_USE_LOCALE\nextern \"C\" {\n#include <locale.h>\n}\n#endif\n\n#ifndef PICOJSON_ASSERT\n#define PICOJSON_ASSERT(e)                      \\\n    do {                                        \\\n        if (!(e)) throw std::runtime_error(#e); \\\n    } while (0)\n#endif\n\n#ifdef _MSC_VER\n#define SNPRINTF _snprintf_s\n#pragma warning(push)\n#pragma warning(disable : 4244)  // conversion from int to char\n#pragma warning(disable : 4127)  // conditional expression is constant\n#pragma warning(disable : 4702)  // unreachable code\n#pragma warning(disable : 4706)  // assignment within conditional expression\n#else\n#define SNPRINTF snprintf\n#endif\n\nnamespace picojson {\n\nenum {\n    null_type,\n    boolean_type,\n    number_type,\n    string_type,\n    array_type,\n    object_type\n#ifdef PICOJSON_USE_INT64\n    ,\n    int64_type\n#endif\n};\n\nenum { INDENT_WIDTH = 2, DEFAULT_MAX_DEPTHS = 100 };\n\nstruct null {};\n\nclass value {\n  public:\n    typedef std::vector<value> array;\n    typedef std::map<std::string, value> object;\n    union _storage {\n        bool boolean_;\n        double number_;\n#ifdef PICOJSON_USE_INT64\n        int64_t int64_;\n#endif\n        std::string *string_;\n        array *array_;\n        object *object_;\n    };\n\n  protected:\n    int type_;\n    _storage u_;\n\n  public:\n    value();\n    value(int type, bool);\n    explicit value(bool b);\n#ifdef PICOJSON_USE_INT64\n    explicit value(int64_t i);\n#endif\n    explicit value(double n);\n    explicit value(const std::string &s);\n    explicit value(const array &a);\n    explicit value(const object &o);\n#if PICOJSON_USE_RVALUE_REFERENCE\n    explicit value(std::string &&s);\n    explicit value(array &&a);\n    explicit value(object &&o);\n#endif\n    explicit value(const char *s);\n    value(const char *s, size_t len);\n    ~value();\n    value(const value &x);\n    value &operator=(const value &x);\n#if PICOJSON_USE_RVALUE_REFERENCE\n    value(value &&x) PICOJSON_NOEXCEPT;\n    value &operator=(value &&x) PICOJSON_NOEXCEPT;\n#endif\n    void swap(value &x) PICOJSON_NOEXCEPT;\n    template <typename T>\n    bool is() const;\n    template <typename T>\n    const T &get() const;\n    template <typename T>\n    T &get();\n    template <typename T>\n    void set(const T &);\n#if PICOJSON_USE_RVALUE_REFERENCE\n    template <typename T>\n    void set(T &&);\n#endif\n    bool evaluate_as_boolean() const;\n    const value &get(const size_t idx) const;\n    const value &get(const std::string &key) const;\n    value &get(const size_t idx);\n    value &get(const std::string &key);\n\n    bool contains(const size_t idx) const;\n    bool contains(const std::string &key) const;\n    std::string to_str() const;\n    template <typename Iter>\n    void serialize(Iter os, bool prettify = false) const;\n    std::string serialize(bool prettify = false) const;\n\n  private:\n    template <typename T>\n    value(const T *);  // intentionally defined to block implicit conversion of\n                       // pointer to bool\n    template <typename Iter>\n    static void _indent(Iter os, int indent);\n    template <typename Iter>\n    void _serialize(Iter os, int indent) const;\n    std::string _serialize(int indent) const;\n    void clear();\n};\n\ntypedef value::array array;\ntypedef value::object object;\n\ninline value::value() : type_(null_type), u_() {}\n\ninline value::value(int type, bool) : type_(type), u_() {\n    switch (type) {\n#define INIT(p, v) \\\n    case p##type:  \\\n        u_.p = v;  \\\n        break\n        INIT(boolean_, false);\n        INIT(number_, 0.0);\n#ifdef PICOJSON_USE_INT64\n        INIT(int64_, 0);\n#endif\n        INIT(string_, new std::string());\n        INIT(array_, new array());\n        INIT(object_, new object());\n#undef INIT\n        default:\n            break;\n    }\n}\n\ninline value::value(bool b) : type_(boolean_type), u_() { u_.boolean_ = b; }\n\n#ifdef PICOJSON_USE_INT64\ninline value::value(int64_t i) : type_(int64_type), u_() { u_.int64_ = i; }\n#endif\n\ninline value::value(double n) : type_(number_type), u_() {\n    if (\n#ifdef _MSC_VER\n        !_finite(n)\n#elif __cplusplus >= 201103L\n        std::isnan(n) || std::isinf(n)\n#else\n        isnan(n) || isinf(n)\n#endif\n            ) {\n        throw std::overflow_error(\"\");\n    }\n    u_.number_ = n;\n}\n\ninline value::value(const std::string &s) : type_(string_type), u_() {\n    u_.string_ = new std::string(s);\n}\n\ninline value::value(const array &a) : type_(array_type), u_() {\n    u_.array_ = new array(a);\n}\n\ninline value::value(const object &o) : type_(object_type), u_() {\n    u_.object_ = new object(o);\n}\n\n#if PICOJSON_USE_RVALUE_REFERENCE\ninline value::value(std::string &&s) : type_(string_type), u_() {\n    u_.string_ = new std::string(std::move(s));\n}\n\ninline value::value(array &&a) : type_(array_type), u_() {\n    u_.array_ = new array(std::move(a));\n}\n\ninline value::value(object &&o) : type_(object_type), u_() {\n    u_.object_ = new object(std::move(o));\n}\n#endif\n\ninline value::value(const char *s) : type_(string_type), u_() {\n    u_.string_ = new std::string(s);\n}\n\ninline value::value(const char *s, size_t len) : type_(string_type), u_() {\n    u_.string_ = new std::string(s, len);\n}\n\ninline void value::clear() {\n    switch (type_) {\n#define DEINIT(p)    \\\n    case p##type:    \\\n        delete u_.p; \\\n        break\n        DEINIT(string_);\n        DEINIT(array_);\n        DEINIT(object_);\n#undef DEINIT\n        default:\n            break;\n    }\n}\n\ninline value::~value() { clear(); }\n\ninline value::value(const value &x) : type_(x.type_), u_() {\n    switch (type_) {\n#define INIT(p, v) \\\n    case p##type:  \\\n        u_.p = v;  \\\n        break\n        INIT(string_, new std::string(*x.u_.string_));\n        INIT(array_, new array(*x.u_.array_));\n        INIT(object_, new object(*x.u_.object_));\n#undef INIT\n        default:\n            u_ = x.u_;\n            break;\n    }\n}\n\ninline value &value::operator=(const value &x) {\n    if (this != &x) {\n        value t(x);\n        swap(t);\n    }\n    return *this;\n}\n\n#if PICOJSON_USE_RVALUE_REFERENCE\ninline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {\n    swap(x);\n}\ninline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {\n    swap(x);\n    return *this;\n}\n#endif\ninline void value::swap(value &x) PICOJSON_NOEXCEPT {\n    std::swap(type_, x.type_);\n    std::swap(u_, x.u_);\n}\n\n#define IS(ctype, jtype)                   \\\n    template <>                            \\\n    inline bool value::is<ctype>() const { \\\n        return type_ == jtype##_type;      \\\n    }\nIS(null, null)\nIS(bool, boolean)\n#ifdef PICOJSON_USE_INT64\nIS(int64_t, int64)\n#endif\nIS(std::string, string)\nIS(array, array)\nIS(object, object)\n#undef IS\ntemplate <>\ninline bool value::is<double>() const {\n    return type_ == number_type\n#ifdef PICOJSON_USE_INT64\n           || type_ == int64_type\n#endif\n        ;\n}\n\n#define GET(ctype, var)                                                        \\\n    template <>                                                                \\\n    inline const ctype &value::get<ctype>() const {                            \\\n        PICOJSON_ASSERT(\"type mismatch! call is<type>() before get<type>()\" && \\\n                        is<ctype>());                                          \\\n        return var;                                                            \\\n    }                                                                          \\\n    template <>                                                                \\\n    inline ctype &value::get<ctype>() {                                        \\\n        PICOJSON_ASSERT(\"type mismatch! call is<type>() before get<type>()\" && \\\n                        is<ctype>());                                          \\\n        return var;                                                            \\\n    }\nGET(bool, u_.boolean_)\nGET(std::string, *u_.string_)\nGET(array, *u_.array_)\nGET(object, *u_.object_)\n#ifdef PICOJSON_USE_INT64\nGET(double,\n    (type_ == int64_type &&\n         (const_cast<value *>(this)->type_ = number_type,\n          (const_cast<value *>(this)->u_.number_ = u_.int64_)),\n     u_.number_))\nGET(int64_t, u_.int64_)\n#else\nGET(double, u_.number_)\n#endif\n#undef GET\n\n#define SET(ctype, jtype, setter)                      \\\n    template <>                                        \\\n    inline void value::set<ctype>(const ctype &_val) { \\\n        clear();                                       \\\n        type_ = jtype##_type;                          \\\n        setter                                         \\\n    }\nSET(bool, boolean, u_.boolean_ = _val;)\nSET(std::string, string, u_.string_ = new std::string(_val);)\nSET(array, array, u_.array_ = new array(_val);)\nSET(object, object, u_.object_ = new object(_val);)\nSET(double, number, u_.number_ = _val;)\n#ifdef PICOJSON_USE_INT64\nSET(int64_t, int64, u_.int64_ = _val;)\n#endif\n#undef SET\n\n#if PICOJSON_USE_RVALUE_REFERENCE\n#define MOVESET(ctype, jtype, setter)              \\\n    template <>                                    \\\n    inline void value::set<ctype>(ctype && _val) { \\\n        clear();                                   \\\n        type_ = jtype##_type;                      \\\n        setter                                     \\\n    }\nMOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)\nMOVESET(array, array, u_.array_ = new array(std::move(_val));)\nMOVESET(object, object, u_.object_ = new object(std::move(_val));)\n#undef MOVESET\n#endif\n\ninline bool value::evaluate_as_boolean() const {\n    switch (type_) {\n        case null_type:\n            return false;\n        case boolean_type:\n            return u_.boolean_;\n        case number_type:\n            return u_.number_ != 0;\n#ifdef PICOJSON_USE_INT64\n        case int64_type:\n            return u_.int64_ != 0;\n#endif\n        case string_type:\n            return !u_.string_->empty();\n        default:\n            return true;\n    }\n}\n\ninline const value &value::get(const size_t idx) const {\n    static value s_null;\n    PICOJSON_ASSERT(is<array>());\n    return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;\n}\n\ninline value &value::get(const size_t idx) {\n    static value s_null;\n    PICOJSON_ASSERT(is<array>());\n    return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;\n}\n\ninline const value &value::get(const std::string &key) const {\n    static value s_null;\n    PICOJSON_ASSERT(is<object>());\n    object::const_iterator i = u_.object_->find(key);\n    return i != u_.object_->end() ? i->second : s_null;\n}\n\ninline value &value::get(const std::string &key) {\n    static value s_null;\n    PICOJSON_ASSERT(is<object>());\n    object::iterator i = u_.object_->find(key);\n    return i != u_.object_->end() ? i->second : s_null;\n}\n\ninline bool value::contains(const size_t idx) const {\n    PICOJSON_ASSERT(is<array>());\n    return idx < u_.array_->size();\n}\n\ninline bool value::contains(const std::string &key) const {\n    PICOJSON_ASSERT(is<object>());\n    object::const_iterator i = u_.object_->find(key);\n    return i != u_.object_->end();\n}\n\ninline std::string value::to_str() const {\n    switch (type_) {\n        case null_type:\n            return \"null\";\n        case boolean_type:\n            return u_.boolean_ ? \"true\" : \"false\";\n#ifdef PICOJSON_USE_INT64\n        case int64_type: {\n            char buf[sizeof(\"-9223372036854775808\")];\n            SNPRINTF(buf, sizeof(buf), \"%\" PRId64, u_.int64_);\n            return buf;\n        }\n#endif\n        case number_type: {\n            char buf[256];\n            double tmp;\n            SNPRINTF(\n                buf,\n                sizeof(buf),\n                fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0\n                    ? \"%.f\"\n                    : \"%.17g\",\n                u_.number_);\n#if PICOJSON_USE_LOCALE\n            char *decimal_point = localeconv()->decimal_point;\n            if (strcmp(decimal_point, \".\") != 0) {\n                size_t decimal_point_len = strlen(decimal_point);\n                for (char *p = buf; *p != '\\0'; ++p) {\n                    if (strncmp(p, decimal_point, decimal_point_len) == 0) {\n                        return std::string(buf, p) + \".\" +\n                               (p + decimal_point_len);\n                    }\n                }\n            }\n#endif\n            return buf;\n        }\n        case string_type:\n            return *u_.string_;\n        case array_type:\n            return \"array\";\n        case object_type:\n            return \"object\";\n        default:\n            PICOJSON_ASSERT(0);\n#ifdef _MSC_VER\n            __assume(0);\n#endif\n    }\n    return std::string();\n}\n\ntemplate <typename Iter>\nvoid copy(const std::string &s, Iter oi) {\n    std::copy(s.begin(), s.end(), oi);\n}\n\ntemplate <typename Iter>\nstruct serialize_str_char {\n    Iter oi;\n    void operator()(char c) {\n        switch (c) {\n#define MAP(val, sym)  \\\n    case val:          \\\n        copy(sym, oi); \\\n        break\n            MAP('\"', \"\\\\\\\"\");\n            MAP('\\\\', \"\\\\\\\\\");\n            MAP('/', \"\\\\/\");\n            MAP('\\b', \"\\\\b\");\n            MAP('\\f', \"\\\\f\");\n            MAP('\\n', \"\\\\n\");\n            MAP('\\r', \"\\\\r\");\n            MAP('\\t', \"\\\\t\");\n#undef MAP\n            default:\n                if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {\n                    char buf[7];\n                    SNPRINTF(buf, sizeof(buf), \"\\\\u%04x\", c & 0xff);\n                    copy(buf, buf + 6, oi);\n                } else {\n                    *oi++ = c;\n                }\n                break;\n        }\n    }\n};\n\ntemplate <typename Iter>\nvoid serialize_str(const std::string &s, Iter oi) {\n    *oi++ = '\"';\n    serialize_str_char<Iter> process_char = {oi};\n    std::for_each(s.begin(), s.end(), process_char);\n    *oi++ = '\"';\n}\n\ntemplate <typename Iter>\nvoid value::serialize(Iter oi, bool prettify) const {\n    return _serialize(oi, prettify ? 0 : -1);\n}\n\ninline std::string value::serialize(bool prettify) const {\n    return _serialize(prettify ? 0 : -1);\n}\n\ntemplate <typename Iter>\nvoid value::_indent(Iter oi, int indent) {\n    *oi++ = '\\n';\n    for (int i = 0; i < indent * INDENT_WIDTH; ++i) {\n        *oi++ = ' ';\n    }\n}\n\ntemplate <typename Iter>\nvoid value::_serialize(Iter oi, int indent) const {\n    switch (type_) {\n        case string_type:\n            serialize_str(*u_.string_, oi);\n            break;\n        case array_type: {\n            *oi++ = '[';\n            if (indent != -1) {\n                ++indent;\n            }\n            for (array::const_iterator i = u_.array_->begin();\n                 i != u_.array_->end();\n                 ++i) {\n                if (i != u_.array_->begin()) {\n                    *oi++ = ',';\n                }\n                if (indent != -1) {\n                    _indent(oi, indent);\n                }\n                i->_serialize(oi, indent);\n            }\n            if (indent != -1) {\n                --indent;\n                if (!u_.array_->empty()) {\n                    _indent(oi, indent);\n                }\n            }\n            *oi++ = ']';\n            break;\n        }\n        case object_type: {\n            *oi++ = '{';\n            if (indent != -1) {\n                ++indent;\n            }\n            for (object::const_iterator i = u_.object_->begin();\n                 i != u_.object_->end();\n                 ++i) {\n                if (i != u_.object_->begin()) {\n                    *oi++ = ',';\n                }\n                if (indent != -1) {\n                    _indent(oi, indent);\n                }\n                serialize_str(i->first, oi);\n                *oi++ = ':';\n                if (indent != -1) {\n                    *oi++ = ' ';\n                }\n                i->second._serialize(oi, indent);\n            }\n            if (indent != -1) {\n                --indent;\n                if (!u_.object_->empty()) {\n                    _indent(oi, indent);\n                }\n            }\n            *oi++ = '}';\n            break;\n        }\n        default:\n            copy(to_str(), oi);\n            break;\n    }\n    if (indent == 0) {\n        *oi++ = '\\n';\n    }\n}\n\ninline std::string value::_serialize(int indent) const {\n    std::string s;\n    _serialize(std::back_inserter(s), indent);\n    return s;\n}\n\ntemplate <typename Iter>\nclass input {\n  protected:\n    Iter cur_, end_;\n    bool consumed_;\n    int line_;\n\n  public:\n    input(const Iter &first, const Iter &last)\n        : cur_(first), end_(last), consumed_(false), line_(1) {}\n    int getc() {\n        if (consumed_) {\n            if (*cur_ == '\\n') {\n                ++line_;\n            }\n            ++cur_;\n        }\n        if (cur_ == end_) {\n            consumed_ = false;\n            return -1;\n        }\n        consumed_ = true;\n        return *cur_ & 0xff;\n    }\n    void ungetc() { consumed_ = false; }\n    Iter cur() const {\n        if (consumed_) {\n            input<Iter> *self = const_cast<input<Iter> *>(this);\n            self->consumed_ = false;\n            ++self->cur_;\n        }\n        return cur_;\n    }\n    int line() const { return line_; }\n    void skip_ws() {\n        while (1) {\n            int ch = getc();\n            if (!(ch == ' ' || ch == '\\t' || ch == '\\n' || ch == '\\r')) {\n                ungetc();\n                break;\n            }\n        }\n    }\n    bool expect(const int expected) {\n        skip_ws();\n        if (getc() != expected) {\n            ungetc();\n            return false;\n        }\n        return true;\n    }\n    bool match(const std::string &pattern) {\n        for (std::string::const_iterator pi(pattern.begin());\n             pi != pattern.end();\n             ++pi) {\n            if (getc() != *pi) {\n                ungetc();\n                return false;\n            }\n        }\n        return true;\n    }\n};\n\ntemplate <typename Iter>\ninline int _parse_quadhex(input<Iter> &in) {\n    int uni_ch = 0, hex;\n    for (int i = 0; i < 4; i++) {\n        if ((hex = in.getc()) == -1) {\n            return -1;\n        }\n        if ('0' <= hex && hex <= '9') {\n            hex -= '0';\n        } else if ('A' <= hex && hex <= 'F') {\n            hex -= 'A' - 0xa;\n        } else if ('a' <= hex && hex <= 'f') {\n            hex -= 'a' - 0xa;\n        } else {\n            in.ungetc();\n            return -1;\n        }\n        uni_ch = uni_ch * 16 + hex;\n    }\n    return uni_ch;\n}\n\ntemplate <typename String, typename Iter>\ninline bool _parse_codepoint(String &out, input<Iter> &in) {\n    int uni_ch;\n    if ((uni_ch = _parse_quadhex(in)) == -1) {\n        return false;\n    }\n    if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {\n        if (0xdc00 <= uni_ch) {\n            // a second 16-bit of a surrogate pair appeared\n            return false;\n        }\n        // first 16-bit of surrogate pair, get the next one\n        if (in.getc() != '\\\\' || in.getc() != 'u') {\n            in.ungetc();\n            return false;\n        }\n        int second = _parse_quadhex(in);\n        if (!(0xdc00 <= second && second <= 0xdfff)) {\n            return false;\n        }\n        uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);\n        uni_ch += 0x10000;\n    }\n    if (uni_ch < 0x80) {\n        out.push_back(static_cast<char>(uni_ch));\n    } else {\n        if (uni_ch < 0x800) {\n            out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));\n        } else {\n            if (uni_ch < 0x10000) {\n                out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));\n            } else {\n                out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));\n                out.push_back(\n                    static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));\n            }\n            out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));\n        }\n        out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));\n    }\n    return true;\n}\n\ntemplate <typename String, typename Iter>\ninline bool _parse_string(String &out, input<Iter> &in) {\n    while (1) {\n        int ch = in.getc();\n        if (ch < ' ') {\n            in.ungetc();\n            return false;\n        } else if (ch == '\"') {\n            return true;\n        } else if (ch == '\\\\') {\n            if ((ch = in.getc()) == -1) {\n                return false;\n            }\n            switch (ch) {\n#define MAP(sym, val)       \\\n    case sym:               \\\n        out.push_back(val); \\\n        break\n                MAP('\"', '\\\"');\n                MAP('\\\\', '\\\\');\n                MAP('/', '/');\n                MAP('b', '\\b');\n                MAP('f', '\\f');\n                MAP('n', '\\n');\n                MAP('r', '\\r');\n                MAP('t', '\\t');\n#undef MAP\n                case 'u':\n                    if (!_parse_codepoint(out, in)) {\n                        return false;\n                    }\n                    break;\n                default:\n                    return false;\n            }\n        } else {\n            out.push_back(static_cast<char>(ch));\n        }\n    }\n    return false;\n}\n\ntemplate <typename Context, typename Iter>\ninline bool _parse_array(Context &ctx, input<Iter> &in) {\n    if (!ctx.parse_array_start()) {\n        return false;\n    }\n    size_t idx = 0;\n    if (in.expect(']')) {\n        return ctx.parse_array_stop(idx);\n    }\n    do {\n        if (!ctx.parse_array_item(in, idx)) {\n            return false;\n        }\n        idx++;\n    } while (in.expect(','));\n    return in.expect(']') && ctx.parse_array_stop(idx);\n}\n\ntemplate <typename Context, typename Iter>\ninline bool _parse_object(Context &ctx, input<Iter> &in) {\n    if (!ctx.parse_object_start()) {\n        return false;\n    }\n    if (in.expect('}')) {\n        return ctx.parse_object_stop();\n    }\n    do {\n        std::string key;\n        if (!in.expect('\"') || !_parse_string(key, in) || !in.expect(':')) {\n            return false;\n        }\n        if (!ctx.parse_object_item(in, key)) {\n            return false;\n        }\n    } while (in.expect(','));\n    return in.expect('}') && ctx.parse_object_stop();\n}\n\ntemplate <typename Iter>\ninline std::string _parse_number(input<Iter> &in) {\n    std::string num_str;\n    while (1) {\n        int ch = in.getc();\n        if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' ||\n            ch == 'E') {\n            num_str.push_back(static_cast<char>(ch));\n        } else if (ch == '.') {\n#if PICOJSON_USE_LOCALE\n            num_str += localeconv()->decimal_point;\n#else\n            num_str.push_back('.');\n#endif\n        } else {\n            in.ungetc();\n            break;\n        }\n    }\n    return num_str;\n}\n\ntemplate <typename Context, typename Iter>\ninline bool _parse(Context &ctx, input<Iter> &in) {\n    in.skip_ws();\n    int ch = in.getc();\n    switch (ch) {\n#define IS(ch, text, op)            \\\n    case ch:                        \\\n        if (in.match(text) && op) { \\\n            return true;            \\\n        } else {                    \\\n            return false;           \\\n        }\n        IS('n', \"ull\", ctx.set_null());\n        IS('f', \"alse\", ctx.set_bool(false));\n        IS('t', \"rue\", ctx.set_bool(true));\n#undef IS\n        case '\"':\n            return ctx.parse_string(in);\n        case '[':\n            return _parse_array(ctx, in);\n        case '{':\n            return _parse_object(ctx, in);\n        default:\n            if (('0' <= ch && ch <= '9') || ch == '-') {\n                double f;\n                char *endp;\n                in.ungetc();\n                std::string num_str(_parse_number(in));\n                if (num_str.empty()) {\n                    return false;\n                }\n#ifdef PICOJSON_USE_INT64\n                {\n                    errno = 0;\n                    intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);\n                    if (errno == 0 &&\n                        std::numeric_limits<int64_t>::min() <= ival &&\n                        ival <= std::numeric_limits<int64_t>::max() &&\n                        endp == num_str.c_str() + num_str.size()) {\n                        ctx.set_int64(ival);\n                        return true;\n                    }\n                }\n#endif\n                f = strtod(num_str.c_str(), &endp);\n                if (endp == num_str.c_str() + num_str.size()) {\n                    ctx.set_number(f);\n                    return true;\n                }\n                return false;\n            }\n            break;\n    }\n    in.ungetc();\n    return false;\n}\n\nclass deny_parse_context {\n  public:\n    bool set_null() { return false; }\n    bool set_bool(bool) { return false; }\n#ifdef PICOJSON_USE_INT64\n    bool set_int64(int64_t) { return false; }\n#endif\n    bool set_number(double) { return false; }\n    template <typename Iter>\n    bool parse_string(input<Iter> &) {\n        return false;\n    }\n    bool parse_array_start() { return false; }\n    template <typename Iter>\n    bool parse_array_item(input<Iter> &, size_t) {\n        return false;\n    }\n    bool parse_array_stop(size_t) { return false; }\n    bool parse_object_start() { return false; }\n    template <typename Iter>\n    bool parse_object_item(input<Iter> &, const std::string &) {\n        return false;\n    }\n};\n\nclass default_parse_context {\n  protected:\n    value *out_;\n    size_t depths_;\n\n  public:\n    default_parse_context(value *out, size_t depths = DEFAULT_MAX_DEPTHS)\n        : out_(out), depths_(depths) {}\n    bool set_null() {\n        *out_ = value();\n        return true;\n    }\n    bool set_bool(bool b) {\n        *out_ = value(b);\n        return true;\n    }\n#ifdef PICOJSON_USE_INT64\n    bool set_int64(int64_t i) {\n        *out_ = value(i);\n        return true;\n    }\n#endif\n    bool set_number(double f) {\n        *out_ = value(f);\n        return true;\n    }\n    template <typename Iter>\n    bool parse_string(input<Iter> &in) {\n        *out_ = value(string_type, false);\n        return _parse_string(out_->get<std::string>(), in);\n    }\n    bool parse_array_start() {\n        if (depths_ == 0) return false;\n        --depths_;\n        *out_ = value(array_type, false);\n        return true;\n    }\n    template <typename Iter>\n    bool parse_array_item(input<Iter> &in, size_t) {\n        array &a = out_->get<array>();\n        a.push_back(value());\n        default_parse_context ctx(&a.back(), depths_);\n        return _parse(ctx, in);\n    }\n    bool parse_array_stop(size_t) {\n        ++depths_;\n        return true;\n    }\n    bool parse_object_start() {\n        if (depths_ == 0) return false;\n        *out_ = value(object_type, false);\n        return true;\n    }\n    template <typename Iter>\n    bool parse_object_item(input<Iter> &in, const std::string &key) {\n        object &o = out_->get<object>();\n        default_parse_context ctx(&o[key], depths_);\n        return _parse(ctx, in);\n    }\n    bool parse_object_stop() {\n        ++depths_;\n        return true;\n    }\n\n  private:\n    default_parse_context(const default_parse_context &);\n    default_parse_context &operator=(const default_parse_context &);\n};\n\nclass null_parse_context {\n  protected:\n    size_t depths_;\n\n  public:\n    struct dummy_str {\n        void push_back(int) {}\n    };\n\n  public:\n    null_parse_context(size_t depths = DEFAULT_MAX_DEPTHS) : depths_(depths) {}\n    bool set_null() { return true; }\n    bool set_bool(bool) { return true; }\n#ifdef PICOJSON_USE_INT64\n    bool set_int64(int64_t) { return true; }\n#endif\n    bool set_number(double) { return true; }\n    template <typename Iter>\n    bool parse_string(input<Iter> &in) {\n        dummy_str s;\n        return _parse_string(s, in);\n    }\n    bool parse_array_start() {\n        if (depths_ == 0) return false;\n        --depths_;\n        return true;\n    }\n    template <typename Iter>\n    bool parse_array_item(input<Iter> &in, size_t) {\n        return _parse(*this, in);\n    }\n    bool parse_array_stop(size_t) {\n        ++depths_;\n        return true;\n    }\n    bool parse_object_start() {\n        if (depths_ == 0) return false;\n        --depths_;\n        return true;\n    }\n    template <typename Iter>\n    bool parse_object_item(input<Iter> &in, const std::string &) {\n        ++depths_;\n        return _parse(*this, in);\n    }\n    bool parse_object_stop() { return true; }\n\n  private:\n    null_parse_context(const null_parse_context &);\n    null_parse_context &operator=(const null_parse_context &);\n};\n\n// obsolete, use the version below\ntemplate <typename Iter>\ninline std::string parse(value &out, Iter &pos, const Iter &last) {\n    std::string err;\n    pos = parse(out, pos, last, &err);\n    return err;\n}\n\ntemplate <typename Context, typename Iter>\ninline Iter _parse(Context &ctx,\n                   const Iter &first,\n                   const Iter &last,\n                   std::string *err) {\n    input<Iter> in(first, last);\n    if (!_parse(ctx, in) && err != NULL) {\n        char buf[64];\n        SNPRINTF(buf, sizeof(buf), \"syntax error at line %d near: \", in.line());\n        *err = buf;\n        while (1) {\n            int ch = in.getc();\n            if (ch == -1 || ch == '\\n') {\n                break;\n            } else if (ch >= ' ') {\n                err->push_back(static_cast<char>(ch));\n            }\n        }\n    }\n    return in.cur();\n}\n\ntemplate <typename Iter>\ninline Iter parse(value &out,\n                  const Iter &first,\n                  const Iter &last,\n                  std::string *err) {\n    default_parse_context ctx(&out);\n    return _parse(ctx, first, last, err);\n}\n\ninline std::string parse(value &out, const std::string &s) {\n    std::string err;\n    parse(out, s.begin(), s.end(), &err);\n    return err;\n}\n\ninline std::string parse(value &out, std::istream &is) {\n    std::string err;\n    parse(out,\n          std::istreambuf_iterator<char>(is.rdbuf()),\n          std::istreambuf_iterator<char>(),\n          &err);\n    return err;\n}\n\ntemplate <typename T>\nstruct last_error_t {\n    static std::string s;\n};\ntemplate <typename T>\nstd::string last_error_t<T>::s;\n\ninline void set_last_error(const std::string &s) { last_error_t<bool>::s = s; }\n\ninline const std::string &get_last_error() { return last_error_t<bool>::s; }\n\ninline bool operator==(const value &x, const value &y) {\n    if (x.is<null>()) return y.is<null>();\n#define PICOJSON_CMP(type) \\\n    if (x.is<type>()) return y.is<type>() && x.get<type>() == y.get<type>()\n    PICOJSON_CMP(bool);\n    PICOJSON_CMP(double);\n    PICOJSON_CMP(std::string);\n    PICOJSON_CMP(array);\n    PICOJSON_CMP(object);\n#undef PICOJSON_CMP\n    PICOJSON_ASSERT(0);\n#ifdef _MSC_VER\n    __assume(0);\n#endif\n    return false;\n}\n\ninline bool operator!=(const value &x, const value &y) { return !(x == y); }\n}\n\n#if !PICOJSON_USE_RVALUE_REFERENCE\nnamespace std {\ntemplate <>\ninline void swap(picojson::value &x, picojson::value &y) {\n    x.swap(y);\n}\n}\n#endif\n\ninline std::istream &operator>>(std::istream &is, picojson::value &x) {\n    picojson::set_last_error(std::string());\n    const std::string err(picojson::parse(x, is));\n    if (!err.empty()) {\n        picojson::set_last_error(err);\n        is.setstate(std::ios::failbit);\n    }\n    return is;\n}\n\ninline std::ostream &operator<<(std::ostream &os, const picojson::value &x) {\n    x.serialize(std::ostream_iterator<char>(os));\n    return os;\n}\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n#endif"
  },
  {
    "path": "runtime/engine/common/utils/strings.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <sstream>\n\n#include \"utils/strings.h\"\n\nnamespace ppspeech {\n\nstd::vector<std::string> StrSplit(const std::string& str,\n                                  const char* delim,\n                                  bool omit_empty_string) {\n    std::vector<std::string> outs;\n    int start = 0;\n    int end = str.size();\n    int found = 0;\n    while (found != std::string::npos) {\n        found = str.find_first_of(delim, start);\n        // start != end condition is for when the delimiter is at the end\n        if (!omit_empty_string || (found != start && start != end)) {\n            outs.push_back(str.substr(start, found - start));\n        }\n        start = found + 1;\n    }\n\n    return outs;\n}\n\n\nstd::string StrJoin(const std::vector<std::string>& strs, const char* delim) {\n    std::stringstream ss;\n    for (ssize_t i = 0; i < strs.size(); ++i) {\n        ss << strs[i];\n        if (i < strs.size() - 1) {\n            ss << std::string(delim);\n        }\n    }\n    return ss.str();\n}\n\nstd::string DelBlank(const std::string& str) {\n    std::string out = \"\";\n    int ptr_in = 0;    //  the pointer of input string (for traversal)\n    int end = str.size();\n    int ptr_out = -1;  //  the pointer of output string (last char)\n    while (ptr_in != end) {\n        while (ptr_in != end && str[ptr_in] == ' ') {\n            ptr_in += 1;\n        }\n        if (ptr_in == end) \n            return out;\n        if (ptr_out != -1 && isalpha(str[ptr_in]) && isalpha(str[ptr_out]) && str[ptr_in-1] == ' ')\n            // add a space when the last and current chars are in English and there have space(s) between them\n            out += ' ';\n        out += str[ptr_in];\n        ptr_out = ptr_in;\n        ptr_in += 1;\n    }\n    return out;\n}\n\nstd::string AddBlank(const std::string& str) {\n    std::string out = \"\";\n    int ptr = 0;  // the pointer of the input string\n    int end = str.size();\n    while (ptr != end) {\n        if (isalpha(str[ptr])) {\n            if (ptr == 0 or str[ptr-1] != ' ')\n                out += \" \";  // add pre-space for an English word\n            while (isalpha(str[ptr])) {\n                out += str[ptr];\n                ptr += 1;\n            }\n            out += \" \";  // add post-space for an English word\n        } else {\n            out += str[ptr];\n            ptr += 1;\n        }\n    }\n    return out;\n}\n\nstd::string ReverseFraction(const std::string& str) {\n    std::string out = \"\";\n    int ptr = 0;   // the pointer of the input string\n    int end = str.size();\n    int left, right, frac;  // the start index of the left tag, right tag and '/'.\n    left = right = frac = 0;\n    int len_tag = 5;  // length of \"<tag>\"\n\n    while (ptr != end) {\n        // find the position of left tag, right tag and '/'. (xxx<tag>num1/num2</tag>)\n        left = str.find(\"<tag>\", ptr);\n        if (left == -1)\n            break;\n        out += str.substr(ptr, left - ptr);  // content before left tag (xxx)\n        frac = str.find(\"/\", left);\n        right = str.find(\"<tag>\", frac);\n        \n        out += str.substr(frac + 1, right - frac - 1) + '/' + \n               str.substr(left + len_tag, frac - left - len_tag);  // num2/num1\n        ptr = right + len_tag;\n    }\n    if (ptr != end) {\n        out += str.substr(ptr, end - ptr);\n    }\n    return out;\n}\n\n#ifdef _MSC_VER\nstd::wstring ToWString(const std::string& str) {\n    unsigned len = str.size() * 2;\n    setlocale(LC_CTYPE, \"\");\n    wchar_t* p = new wchar_t[len];\n    mbstowcs(p, str.c_str(), len);\n    std::wstring wstr(p);\n    delete[] p;\n    return wstr;\n}\n#endif\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/utils/strings.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <string>\n#include <vector>\n\nnamespace ppspeech {\n\nstd::vector<std::string> StrSplit(const std::string& str,\n                                  const char* delim,\n                                  bool omit_empty_string = true);\n\nstd::string StrJoin(const std::vector<std::string>& strs, const char* delim);\n\nstd::string DelBlank(const std::string& str);\n\nstd::string AddBlank(const std::string& str);\n\nstd::string ReverseFraction(const std::string& str);\n\n#ifdef _MSC_VER\nstd::wstring ToWString(const std::string& str);\n#endif\n\n}  // namespace ppspeech\n"
  },
  {
    "path": "runtime/engine/common/utils/strings_test.cc",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"utils/strings.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n\nTEST(StringTest, StrSplitTest) {\n    using ::testing::ElementsAre;\n\n    std::string test_str = \"hello world\";\n    std::vector<std::string> outs = ppspeech::StrSplit(test_str, \" \\t\");\n    EXPECT_THAT(outs, ElementsAre(\"hello\", \"world\"));\n}\n\n\nTEST(StringTest, StrJoinTest) {\n    std::vector<std::string> ins{\"hello\", \"world\"};\n    std::string out = ppspeech::StrJoin(ins, \" \");\n    EXPECT_THAT(out, \"hello world\");\n}\n\nTEST(StringText, DelBlankTest) {\n    std::string test_str = \"我 今天     去 了 超市     花了   120 元。\";\n    std::string out_str = ppspeech::DelBlank(test_str);\n    int ret = out_str.compare(\"我今天去了超市花了120元。\");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"how are you today\";\n    out_str = ppspeech::DelBlank(test_str);\n    ret = out_str.compare(\"how are you today\");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"我 的 paper 在 哪里？\";\n    out_str = ppspeech::DelBlank(test_str);\n    ret = out_str.compare(\"我的paper在哪里？\");\n    EXPECT_EQ(ret, 0);\n}\n\nTEST(StringTest, AddBlankTest) {\n    std::string test_str = \"how are you\";\n    std::string out_str = ppspeech::AddBlank(test_str);\n    int ret = out_str.compare(\" how  are  you \");\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"欢迎来到China。\";\n    out_str = ppspeech::AddBlank(test_str);\n    ret = out_str.compare(\"欢迎来到 China 。\");\n    EXPECT_EQ(ret, 0);\n}\n\nTEST(StringTest, ReverseFractionTest) {\n    std::string test_str = \"<tag>3/1<tag>\";\n    std::string out_str = ppspeech::ReverseFraction(test_str);\n    int ret = out_str.compare(\"1/3\");\n    std::cout<<out_str<<std::endl;\n    EXPECT_EQ(ret, 0);\n\n    test_str = \"<tag>3/1<tag> <tag>100/10000<tag>\";\n    out_str = ppspeech::ReverseFraction(test_str);\n    ret = out_str.compare(\"1/3 10000/100\");\n    std::cout<<out_str<<std::endl;\n    EXPECT_EQ(ret, 0);\n}\n"
  },
  {
    "path": "runtime/engine/common/utils/timer.cc",
    "content": "// Copyright      2020  Xiaomi Corporation (authors: Haowen Qiu)\n//                      Mobvoi Inc.        (authors: Fangjun Kuang)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include <chrono>\n\n#include \"common/utils/timer.h\"\n\nnamespace ppspeech{\n\nstruct TimerImpl{\n    TimerImpl() = default;\n    virtual ~TimerImpl() = default;\n    virtual void Reset() = 0;\n    // time in seconds\n    virtual double Elapsed() = 0;\n};\n\nclass CpuTimerImpl : public TimerImpl {\n public:\n  CpuTimerImpl() { Reset(); }\n\n  using high_resolution_clock = std::chrono::high_resolution_clock;\n\n  void Reset() override { begin_ = high_resolution_clock::now(); }\n\n  // time in seconds\n  double Elapsed() override {\n    auto end = high_resolution_clock::now();\n    auto dur =\n        std::chrono::duration_cast<std::chrono::microseconds>(end - begin_);\n    return dur.count() / 1000000.0;\n  }\n\n private:\n  high_resolution_clock::time_point begin_;\n};\n\nTimer::Timer() {\n    impl_ = std::make_unique<CpuTimerImpl>();\n}\n\nTimer::~Timer() = default;\n\nvoid Timer::Reset() const { impl_->Reset(); }\n\ndouble Timer::Elapsed() const { return impl_->Elapsed(); }\n\n\n} //namespace ppspeech"
  },
  {
    "path": "runtime/engine/common/utils/timer.h",
    "content": "// Copyright      2020  Xiaomi Corporation (authors: Haowen Qiu)\n//                      Mobvoi Inc.        (authors: Fangjun Kuang)\n// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#include <memory>\n\nnamespace ppspeech {\n\nstruct TimerImpl;\n\nclass Timer {\n    public:\n        Timer();\n        ~Timer();\n\n        void Reset() const;\n\n        // time in seconds\n        double Elapsed() const;\n\n    private:\n        std::unique_ptr<TimerImpl> impl_;\n};\n\n} //namespace ppspeech"
  },
  {
    "path": "runtime/engine/kaldi/CMakeLists.txt",
    "content": "include_directories(\n${CMAKE_CURRENT_SOURCE_DIR}\n)\n\nadd_subdirectory(base)\nadd_subdirectory(util)\nif(WITH_ASR)\n    add_subdirectory(lat)\n    add_subdirectory(fstext)\n    add_subdirectory(decoder)\n    add_subdirectory(lm)\n\n    add_subdirectory(fstbin)\n    add_subdirectory(lmbin)\nendif()\n"
  },
  {
    "path": "runtime/engine/kaldi/base/CMakeLists.txt",
    "content": "\nadd_library(kaldi-base  \n  io-funcs.cc\n  kaldi-error.cc\n  kaldi-math.cc\n  kaldi-utils.cc\n  timer.cc)"
  },
  {
    "path": "runtime/engine/kaldi/base/io-funcs-inl.h",
    "content": "// base/io-funcs-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University;\n//                      Jan Silovsky;   Yanmin Qian;\n//                      Johns Hopkins University (Author: Daniel Povey)\n//                2016  Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_IO_FUNCS_INL_H_\n#define KALDI_BASE_IO_FUNCS_INL_H_ 1\n\n// Do not include this file directly.  It is included by base/io-funcs.h\n\n#include <limits>\n#include <vector>\n\nnamespace kaldi {\n\n// Template that covers integers.\ntemplate<class T>  void WriteBasicType(std::ostream &os,\n                                       bool binary, T t) {\n  // Compile time assertion that this is not called with a wrong type.\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  if (binary) {\n    char len_c = (std::numeric_limits<T>::is_signed ? 1 :  -1)\n        * static_cast<char>(sizeof(t));\n    os.put(len_c);\n    os.write(reinterpret_cast<const char *>(&t), sizeof(t));\n  } else {\n    if (sizeof(t) == 1)\n      os << static_cast<int16>(t) << \" \";\n    else\n      os << t << \" \";\n  }\n  if (os.fail()) {\n    KALDI_ERR << \"Write failure in WriteBasicType.\";\n  }\n}\n\n// Template that covers integers.\ntemplate<class T> inline void ReadBasicType(std::istream &is,\n                                            bool binary, T *t) {\n  KALDI_PARANOID_ASSERT(t != NULL);\n  // Compile time assertion that this is not called with a wrong type.\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  if (binary) {\n    int len_c_in = is.get();\n    if (len_c_in == -1)\n      KALDI_ERR << \"ReadBasicType: encountered end of stream.\";\n    char len_c = static_cast<char>(len_c_in), len_c_expected\n      = (std::numeric_limits<T>::is_signed ? 1 :  -1)\n      * static_cast<char>(sizeof(*t));\n    if (len_c !=  len_c_expected) {\n      KALDI_ERR << \"ReadBasicType: did not get expected integer type, \"\n                << static_cast<int>(len_c)\n                << \" vs. \" << static_cast<int>(len_c_expected)\n                << \".  You can change this code to successfully\"\n                << \" read it later, if needed.\";\n      // insert code here to read \"wrong\" type.  Might have a switch statement.\n    }\n    is.read(reinterpret_cast<char *>(t), sizeof(*t));\n  } else {\n    if (sizeof(*t) == 1) {\n      int16 i;\n      is >> i;\n      *t = i;\n    } else {\n      is >> *t;\n    }\n  }\n  if (is.fail()) {\n    KALDI_ERR << \"Read failure in ReadBasicType, file position is \"\n              << is.tellg() << \", next char is \" << is.peek();\n  }\n}\n\n// Template that covers integers.\ntemplate<class T>\ninline void WriteIntegerPairVector(std::ostream &os, bool binary,\n                                   const std::vector<std::pair<T, T> > &v) {\n  // Compile time assertion that this is not called with a wrong type.\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  if (binary) {\n    char sz = sizeof(T);  // this is currently just a check.\n    os.write(&sz, 1);\n    int32 vecsz = static_cast<int32>(v.size());\n    KALDI_ASSERT((size_t)vecsz == v.size());\n    os.write(reinterpret_cast<const char *>(&vecsz), sizeof(vecsz));\n    if (vecsz != 0) {\n      os.write(reinterpret_cast<const char *>(&(v[0])), sizeof(T) * vecsz * 2);\n    }\n  } else {\n    // focus here is on prettiness of text form rather than\n    // efficiency of reading-in.\n    // reading-in is dominated by low-level operations anyway:\n    // for efficiency use binary.\n    os << \"[ \";\n    typename std::vector<std::pair<T, T> >::const_iterator iter = v.begin(),\n                                                            end = v.end();\n    for (; iter != end; ++iter) {\n      if (sizeof(T) == 1)\n        os << static_cast<int16>(iter->first) << ','\n           << static_cast<int16>(iter->second) << ' ';\n      else\n        os << iter->first << ','\n           << iter->second << ' ';\n    }\n    os << \"]\\n\";\n  }\n  if (os.fail()) {\n    KALDI_ERR << \"Write failure in WriteIntegerPairVector.\";\n  }\n}\n\n// Template that covers integers.\ntemplate<class T>\ninline void ReadIntegerPairVector(std::istream &is, bool binary,\n                                  std::vector<std::pair<T, T> > *v) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  KALDI_ASSERT(v != NULL);\n  if (binary) {\n    int sz = is.peek();\n    if (sz == sizeof(T)) {\n      is.get();\n    } else {  // this is currently just a check.\n      KALDI_ERR << \"ReadIntegerPairVector: expected to see type of size \"\n                << sizeof(T) << \", saw instead \" << sz << \", at file position \"\n                << is.tellg();\n    }\n    int32 vecsz;\n    is.read(reinterpret_cast<char *>(&vecsz), sizeof(vecsz));\n    if (is.fail() || vecsz < 0) goto bad;\n    v->resize(vecsz);\n    if (vecsz > 0) {\n      is.read(reinterpret_cast<char *>(&((*v)[0])), sizeof(T)*vecsz*2);\n    }\n  } else {\n    std::vector<std::pair<T, T> > tmp_v;  // use temporary so v doesn't use extra memory\n                           // due to resizing.\n    is >> std::ws;\n    if (is.peek() != static_cast<int>('[')) {\n      KALDI_ERR << \"ReadIntegerPairVector: expected to see [, saw \"\n                << is.peek() << \", at file position \" << is.tellg();\n    }\n    is.get();  // consume the '['.\n    is >> std::ws;  // consume whitespace.\n    while (is.peek() != static_cast<int>(']')) {\n      if (sizeof(T) == 1) {  // read/write chars as numbers.\n        int16 next_t1, next_t2;\n        is >> next_t1;\n        if (is.fail()) goto bad;\n        if (is.peek() != static_cast<int>(','))\n          KALDI_ERR << \"ReadIntegerPairVector: expected to see ',', saw \"\n                    << is.peek() << \", at file position \" << is.tellg();\n        is.get();  // consume the ','.\n        is >> next_t2 >> std::ws;\n        if (is.fail()) goto bad;\n        else\n            tmp_v.push_back(std::make_pair<T, T>((T)next_t1, (T)next_t2));\n      } else {\n        T next_t1, next_t2;\n        is >> next_t1;\n        if (is.fail()) goto bad;\n        if (is.peek() != static_cast<int>(','))\n          KALDI_ERR << \"ReadIntegerPairVector: expected to see ',', saw \"\n                    << is.peek() << \", at file position \" << is.tellg();\n        is.get();  // consume the ','.\n        is >> next_t2 >> std::ws;\n        if (is.fail()) goto bad;\n        else\n            tmp_v.push_back(std::pair<T, T>(next_t1, next_t2));\n      }\n    }\n    is.get();  // get the final ']'.\n    *v = tmp_v;  // could use std::swap to use less temporary memory, but this\n    // uses less permanent memory.\n  }\n  if (!is.fail()) return;\n bad:\n  KALDI_ERR << \"ReadIntegerPairVector: read failure at file position \"\n            << is.tellg();\n}\n\ntemplate<class T> inline void WriteIntegerVector(std::ostream &os, bool binary,\n                                                 const std::vector<T> &v) {\n  // Compile time assertion that this is not called with a wrong type.\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  if (binary) {\n    char sz = sizeof(T);  // this is currently just a check.\n    os.write(&sz, 1);\n    int32 vecsz = static_cast<int32>(v.size());\n    KALDI_ASSERT((size_t)vecsz == v.size());\n    os.write(reinterpret_cast<const char *>(&vecsz), sizeof(vecsz));\n    if (vecsz != 0) {\n      os.write(reinterpret_cast<const char *>(&(v[0])), sizeof(T)*vecsz);\n    }\n  } else {\n    // focus here is on prettiness of text form rather than\n    // efficiency of reading-in.\n    // reading-in is dominated by low-level operations anyway:\n    // for efficiency use binary.\n    os << \"[ \";\n    typename std::vector<T>::const_iterator iter = v.begin(), end = v.end();\n    for (; iter != end; ++iter) {\n      if (sizeof(T) == 1)\n        os << static_cast<int16>(*iter) << \" \";\n      else\n        os << *iter << \" \";\n    }\n    os << \"]\\n\";\n  }\n  if (os.fail()) {\n    KALDI_ERR << \"Write failure in WriteIntegerVector.\";\n  }\n}\n\n\ntemplate<class T> inline void ReadIntegerVector(std::istream &is,\n                                                bool binary,\n                                                std::vector<T> *v) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(T);\n  KALDI_ASSERT(v != NULL);\n  if (binary) {\n    int sz = is.peek();\n    if (sz == sizeof(T)) {\n      is.get();\n    } else {  // this is currently just a check.\n      KALDI_ERR << \"ReadIntegerVector: expected to see type of size \"\n                << sizeof(T) << \", saw instead \" << sz << \", at file position \"\n                << is.tellg();\n    }\n    int32 vecsz;\n    is.read(reinterpret_cast<char *>(&vecsz), sizeof(vecsz));\n    if (is.fail() || vecsz < 0) goto bad;\n    v->resize(vecsz);\n    if (vecsz > 0) {\n      is.read(reinterpret_cast<char *>(&((*v)[0])), sizeof(T)*vecsz);\n    }\n  } else {\n    std::vector<T> tmp_v;  // use temporary so v doesn't use extra memory\n                           // due to resizing.\n    is >> std::ws;\n    if (is.peek() != static_cast<int>('[')) {\n      KALDI_ERR << \"ReadIntegerVector: expected to see [, saw \"\n                << is.peek() << \", at file position \" << is.tellg();\n    }\n    is.get();  // consume the '['.\n    is >> std::ws;  // consume whitespace.\n    while (is.peek() != static_cast<int>(']')) {\n      if (sizeof(T) == 1) {  // read/write chars as numbers.\n        int16 next_t;\n        is >> next_t >> std::ws;\n        if (is.fail()) goto bad;\n        else\n            tmp_v.push_back((T)next_t);\n      } else {\n        T next_t;\n        is >> next_t >> std::ws;\n        if (is.fail()) goto bad;\n        else\n            tmp_v.push_back(next_t);\n      }\n    }\n    is.get();  // get the final ']'.\n    *v = tmp_v;  // could use std::swap to use less temporary memory, but this\n    // uses less permanent memory.\n  }\n  if (!is.fail()) return;\n bad:\n  KALDI_ERR << \"ReadIntegerVector: read failure at file position \"\n            << is.tellg();\n}\n\n\n// Initialize an opened stream for writing by writing an optional binary\n// header and modifying the floating-point precision.\ninline void InitKaldiOutputStream(std::ostream &os, bool binary) {\n  // This does not throw exceptions (does not check for errors).\n  if (binary) {\n    os.put('\\0');\n    os.put('B');\n  }\n  // Note, in non-binary mode we may at some point want to mess with\n  // the precision a bit.\n  // 7 is a bit more than the precision of float..\n  if (os.precision() < 7)\n    os.precision(7);\n}\n\n/// Initialize an opened stream for reading by detecting the binary header and\n// setting the \"binary\" value appropriately.\ninline bool InitKaldiInputStream(std::istream &is, bool *binary) {\n  // Sets the 'binary' variable.\n  // Throws exception in the very unusual situation that stream\n  // starts with '\\0' but not then 'B'.\n\n  if (is.peek() == '\\0') {  // seems to be binary\n    is.get();\n    if (is.peek() != 'B') {\n      return false;\n    }\n    is.get();\n    *binary = true;\n    return true;\n  } else {\n    *binary = false;\n    return true;\n  }\n}\n\n}  // end namespace kaldi.\n\n#endif  // KALDI_BASE_IO_FUNCS_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/io-funcs.cc",
    "content": "// base/io-funcs.cc\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/io-funcs.h\"\n#include \"base/kaldi-math.h\"\n\nnamespace kaldi {\n\ntemplate<>\nvoid WriteBasicType<bool>(std::ostream &os, bool binary, bool b) {\n  os << (b ? \"T\":\"F\");\n  if (!binary) os << \" \";\n  if (os.fail())\n    KALDI_ERR << \"Write failure in WriteBasicType<bool>\";\n}\n\ntemplate<>\nvoid ReadBasicType<bool>(std::istream &is, bool binary, bool *b) {\n  KALDI_PARANOID_ASSERT(b != NULL);\n  if (!binary) is >> std::ws;  // eat up whitespace.\n  char c = is.peek();\n  if (c == 'T') {\n      *b = true;\n      is.get();\n  } else if (c == 'F') {\n      *b = false;\n      is.get();\n  } else {\n    KALDI_ERR << \"Read failure in ReadBasicType<bool>, file position is \"\n              << is.tellg() << \", next char is \" << CharToString(c);\n  }\n}\n\ntemplate<>\nvoid WriteBasicType<float>(std::ostream &os, bool binary, float f) {\n  if (binary) {\n    char c = sizeof(f);\n    os.put(c);\n    os.write(reinterpret_cast<const char *>(&f), sizeof(f));\n  } else {\n    os << f << \" \";\n  }\n}\n\ntemplate<>\nvoid WriteBasicType<double>(std::ostream &os, bool binary, double f) {\n  if (binary) {\n    char c = sizeof(f);\n    os.put(c);\n    os.write(reinterpret_cast<const char *>(&f), sizeof(f));\n  } else {\n    os << f << \" \";\n  }\n}\n\ntemplate<>\nvoid ReadBasicType<float>(std::istream &is, bool binary, float *f) {\n  KALDI_PARANOID_ASSERT(f != NULL);\n  if (binary) {\n    double d;\n    int c = is.peek();\n    if (c == sizeof(*f)) {\n      is.get();\n      is.read(reinterpret_cast<char*>(f), sizeof(*f));\n    } else if (c == sizeof(d)) {\n      ReadBasicType(is, binary, &d);\n      *f = d;\n    } else {\n      KALDI_ERR << \"ReadBasicType: expected float, saw \" << is.peek()\n                << \", at file position \" << is.tellg();\n    }\n  } else {\n    is >> *f;\n  }\n  if (is.fail()) {\n    KALDI_ERR << \"ReadBasicType: failed to read, at file position \"\n              << is.tellg();\n  }\n}\n\ntemplate<>\nvoid ReadBasicType<double>(std::istream &is, bool binary, double *d) {\n  KALDI_PARANOID_ASSERT(d != NULL);\n  if (binary) {\n    float f;\n    int c = is.peek();\n    if (c == sizeof(*d)) {\n      is.get();\n      is.read(reinterpret_cast<char*>(d), sizeof(*d));\n    } else if (c == sizeof(f)) {\n      ReadBasicType(is, binary, &f);\n      *d = f;\n    } else {\n      KALDI_ERR << \"ReadBasicType: expected float, saw \" << is.peek()\n                << \", at file position \" << is.tellg();\n    }\n  } else {\n    is >> *d;\n  }\n  if (is.fail()) {\n    KALDI_ERR << \"ReadBasicType: failed to read, at file position \"\n              << is.tellg();\n  }\n}\n\nvoid CheckToken(const char *token) {\n  if (*token == '\\0')\n    KALDI_ERR << \"Token is empty (not a valid token)\";\n  const char *orig_token = token;\n  while (*token != '\\0') {\n    if (::isspace(*token))\n      KALDI_ERR << \"Token is not a valid token (contains space): '\"\n                << orig_token << \"'\";\n    token++;\n  }\n}\n\nvoid WriteToken(std::ostream &os, bool binary, const char *token) {\n  // binary mode is ignored;\n  // we use space as termination character in either case.\n  KALDI_ASSERT(token != NULL);\n  CheckToken(token);  // make sure it's valid (can be read back)\n  os << token << \" \";\n  if (os.fail()) {\n    KALDI_ERR << \"Write failure in WriteToken.\";\n  }\n}\n\nint Peek(std::istream &is, bool binary) {\n  if (!binary) is >> std::ws;  // eat up whitespace.\n  return is.peek();\n}\n\nvoid WriteToken(std::ostream &os, bool binary, const std::string & token) {\n  WriteToken(os, binary, token.c_str());\n}\n\nvoid ReadToken(std::istream &is, bool binary, std::string *str) {\n  KALDI_ASSERT(str != NULL);\n  if (!binary) is >> std::ws;  // consume whitespace.\n  is >> *str;\n  if (is.fail()) {\n    KALDI_ERR << \"ReadToken, failed to read token at file position \"\n              << is.tellg();\n  }\n  if (!isspace(is.peek())) {\n    KALDI_ERR << \"ReadToken, expected space after token, saw instead \"\n              << CharToString(static_cast<char>(is.peek()))\n              << \", at file position \" << is.tellg();\n  }\n  is.get();  // consume the space.\n}\n\nint PeekToken(std::istream &is, bool binary) {\n  if (!binary) is >> std::ws;  // consume whitespace.\n  bool read_bracket;\n  if (static_cast<char>(is.peek()) == '<') {\n    read_bracket = true;\n    is.get();\n  } else {\n    read_bracket = false;\n  }\n  int ans = is.peek();\n  if (read_bracket) {\n    if (!is.unget()) {\n      // Clear the bad bit. This code can be (and is in fact) reached, since the\n      // C++ standard does not guarantee that a call to unget() must succeed.\n      is.clear();\n    }\n  }\n  return ans;\n}\n\n\nvoid ExpectToken(std::istream &is, bool binary, const char *token) {\n  int pos_at_start = is.tellg();\n  KALDI_ASSERT(token != NULL);\n  CheckToken(token);  // make sure it's valid (can be read back)\n  if (!binary) is >> std::ws;  // consume whitespace.\n  std::string str;\n  is >> str;\n  is.get();  // consume the space.\n  if (is.fail()) {\n    KALDI_ERR << \"Failed to read token [started at file position \"\n              << pos_at_start << \"], expected \" << token;\n  }\n  // The second half of the '&&' expression below is so that if we're expecting\n  // \"<Foo>\", we will accept \"Foo>\" instead.  This is so that the model-reading\n  // code will tolerate errors in PeekToken where is.unget() failed; search for\n  // is.clear() in PeekToken() for an explanation.\n  if (strcmp(str.c_str(), token) != 0 &&\n      !(token[0] == '<' && strcmp(str.c_str(), token + 1) == 0)) {\n    KALDI_ERR << \"Expected token \\\"\" << token << \"\\\", got instead \\\"\"\n              << str <<\"\\\".\";\n  }\n}\n\nvoid ExpectToken(std::istream &is, bool binary, const std::string &token) {\n  ExpectToken(is, binary, token.c_str());\n}\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/base/io-funcs.h",
    "content": "// base/io-funcs.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University;\n//                      Jan Silovsky;   Yanmin Qian\n//                2016  Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_IO_FUNCS_H_\n#define KALDI_BASE_IO_FUNCS_H_\n\n// This header only contains some relatively low-level I/O functions.\n// The full Kaldi I/O declarations are in ../util/kaldi-io.h\n// and ../util/kaldi-table.h\n// They were put in util/ in order to avoid making the Matrix library\n// dependent on them.\n\n#include <cctype>\n#include <vector>\n#include <string>\n\n#include \"base/kaldi-common.h\"\n#include \"base/io-funcs-inl.h\"\n\nnamespace kaldi {\n\n\n\n/*\n  This comment describes the Kaldi approach to I/O.  All objects can be written\n  and read in two modes: binary and text.  In addition we want to make the I/O\n  work if we redefine the typedef \"BaseFloat\" between floats and doubles.\n  We also want to have control over whitespace in text mode without affecting\n  the meaning of the file, for pretty-printing purposes.\n\n  Errors are handled by throwing a KaldiFatalError exception.\n\n  For integer and floating-point types (and boolean values):\n\n   WriteBasicType(std::ostream &, bool binary, const T&);\n   ReadBasicType(std::istream &, bool binary, T*);\n\n  and we expect these functions to be defined in such a way that they work when\n  the type T changes between float and double, so you can read float into double\n  and vice versa].  Note that for efficiency and space-saving reasons, the Vector\n  and Matrix classes do not use these functions [but they preserve the type\n  interchangeability in their own way]\n\n  For a class (or struct) C:\n  class C {\n  ..\n    Write(std::ostream &, bool binary, [possibly extra optional args for specific classes]) const;\n    Read(std::istream &, bool binary, [possibly extra optional args for specific classes]);\n  ..\n  }\n  NOTE: The only actual optional args we used are the \"add\" arguments in\n  Vector/Matrix classes, which specify whether we should sum the data already\n  in the class with the data being read.\n\n  For types which are typedef's involving stl classes, I/O is as follows:\n  typedef std::vector<std::pair<A, B> > MyTypedefName;\n\n  The user should define something like:\n\n   WriteMyTypedefName(std::ostream &, bool binary, const MyTypedefName &t);\n   ReadMyTypedefName(std::ostream &, bool binary, MyTypedefName *t);\n\n  The user would have to write these functions.\n\n  For a type std::vector<T>:\n\n   void WriteIntegerVector(std::ostream &os, bool binary, const std::vector<T> &v);\n   void ReadIntegerVector(std::istream &is, bool binary, std::vector<T> *v);\n\n  For other types, e.g. vectors of pairs, the user should create a routine of the\n  type WriteMyTypedefName.  This is to avoid introducing confusing templated functions;\n  we could easily create templated functions to handle most of these cases but they\n  would have to share the same name.\n\n  It also often happens that the user needs to write/read special tokens as part\n  of a file.  These might be class headers, or separators/identifiers in the class.\n  We provide special functions for manipulating these.  These special tokens must\n  be nonempty and must not contain any whitespace.\n\n    void WriteToken(std::ostream &os, bool binary, const char*);\n    void WriteToken(std::ostream &os, bool binary, const std::string & token);\n    int Peek(std::istream &is, bool binary);\n    void ReadToken(std::istream &is, bool binary, std::string *str);\n    void PeekToken(std::istream &is, bool binary, std::string *str);\n\n  WriteToken writes the token and one space (whether in binary or text mode).\n\n  Peek returns the first character of the next token, by consuming whitespace\n  (in text mode) and then returning the peek() character.  It returns -1 at EOF;\n  it doesn't throw.  It's useful if a class can have various forms based on\n  typedefs and virtual classes, and wants to know which version to read.\n\n  ReadToken allows the caller to obtain the next token.  PeekToken works just\n  like ReadToken, but seeks back to the beginning of the token.  A subsequent\n  call to ReadToken will read the same token again.  This is useful when\n  different object types are written to the same file; using PeekToken one can\n  decide which of the objects to read.\n\n  There is currently no special functionality for writing/reading strings (where the strings\n  contain data rather than \"special tokens\" that are whitespace-free and nonempty).  This is\n  because Kaldi is structured in such a way that strings don't appear, except as OpenFst symbol\n  table entries (and these have their own format).\n\n\n  NOTE: you should not call ReadIntegerType and WriteIntegerType with types,\n  such as int and size_t, that are machine-independent -- at least not\n  if you want your file formats to port between machines.  Use int32 and\n  int64 where necessary.  There is no way to detect this using compile-time\n  assertions because C++ only keeps track of the internal representation of\n  the type.\n*/\n\n/// \\addtogroup io_funcs_basic\n/// @{\n\n\n/// WriteBasicType is the name of the write function for bool, integer types,\n/// and floating-point types. They all throw on error.\ntemplate<class T> void WriteBasicType(std::ostream &os, bool binary, T t);\n\n/// ReadBasicType is the name of the read function for bool, integer types,\n/// and floating-point types. They all throw on error.\ntemplate<class T> void ReadBasicType(std::istream &is, bool binary, T *t);\n\n\n// Declare specialization for bool.\ntemplate<>\nvoid WriteBasicType<bool>(std::ostream &os, bool binary, bool b);\n\ntemplate <>\nvoid ReadBasicType<bool>(std::istream &is, bool binary, bool *b);\n\n// Declare specializations for float and double.\ntemplate<>\nvoid WriteBasicType<float>(std::ostream &os, bool binary, float f);\n\ntemplate<>\nvoid WriteBasicType<double>(std::ostream &os, bool binary, double f);\n\ntemplate<>\nvoid ReadBasicType<float>(std::istream &is, bool binary, float *f);\n\ntemplate<>\nvoid ReadBasicType<double>(std::istream &is, bool binary, double *f);\n\n// Define ReadBasicType that accepts an \"add\" parameter to add to\n// the destination.  Caution: if used in Read functions, be careful\n// to initialize the parameters concerned to zero in the default\n// constructor.\ntemplate<class T>\ninline void ReadBasicType(std::istream &is, bool binary, T *t, bool add) {\n  if (!add) {\n    ReadBasicType(is, binary, t);\n  } else {\n    T tmp = T(0);\n    ReadBasicType(is, binary, &tmp);\n    *t += tmp;\n  }\n}\n\n/// Function for writing STL vectors of integer types.\ntemplate<class T> inline void WriteIntegerVector(std::ostream &os, bool binary,\n                                                 const std::vector<T> &v);\n\n/// Function for reading STL vector of integer types.\ntemplate<class T> inline void ReadIntegerVector(std::istream &is, bool binary,\n                                                std::vector<T> *v);\n\n/// Function for writing STL vectors of pairs of integer types.\ntemplate<class T>\ninline void WriteIntegerPairVector(std::ostream &os, bool binary,\n                                   const std::vector<std::pair<T, T> > &v);\n\n/// Function for reading STL vector of pairs of integer types.\ntemplate<class T>\ninline void ReadIntegerPairVector(std::istream &is, bool binary,\n                                  std::vector<std::pair<T, T> > *v);\n\n/// The WriteToken functions are for writing nonempty sequences of non-space\n/// characters. They are not for general strings.\nvoid WriteToken(std::ostream &os, bool binary, const char *token);\nvoid WriteToken(std::ostream &os, bool binary, const std::string & token);\n\n/// Peek consumes whitespace (if binary == false) and then returns the peek()\n/// value of the stream.\nint Peek(std::istream &is, bool binary);\n\n/// ReadToken gets the next token and puts it in str (exception on failure). If\n/// PeekToken() had been previously called, it is possible that the stream had\n/// failed to unget the starting '<' character. In this case ReadToken() returns\n/// the token string without the leading '<'. You must be prepared to handle\n/// this case. ExpectToken() handles this internally, and is not affected.\nvoid ReadToken(std::istream &is, bool binary, std::string *token);\n\n/// PeekToken will return the first character of the next token, or -1 if end of\n/// file.  It's the same as Peek(), except if the first character is '<' it will\n/// skip over it and will return the next character. It will attempt to unget\n/// the '<' so the stream is where it was before you did PeekToken(), however,\n/// this is not guaranteed (see ReadToken()).\nint PeekToken(std::istream &is, bool binary);\n\n/// ExpectToken tries to read in the given token, and throws an exception\n/// on failure.\nvoid ExpectToken(std::istream &is, bool binary, const char *token);\nvoid ExpectToken(std::istream &is, bool binary, const std::string & token);\n\n/// ExpectPretty attempts to read the text in \"token\", but only in non-binary\n/// mode.  Throws exception on failure.  It expects an exact match except that\n/// arbitrary whitespace matches arbitrary whitespace.\nvoid ExpectPretty(std::istream &is, bool binary, const char *token);\nvoid ExpectPretty(std::istream &is, bool binary, const std::string & token);\n\n/// @} end \"addtogroup io_funcs_basic\"\n\n\n/// InitKaldiOutputStream initializes an opened stream for writing by writing an\n/// optional binary header and modifying the floating-point precision; it will\n/// typically not be called by users directly.\ninline void InitKaldiOutputStream(std::ostream &os, bool binary);\n\n/// InitKaldiInputStream initializes an opened stream for reading by detecting\n/// the binary header and setting the \"binary\" value appropriately;\n/// It will typically not be called by users directly.\ninline bool InitKaldiInputStream(std::istream &is, bool *binary);\n\n}  // end namespace kaldi.\n#endif  // KALDI_BASE_IO_FUNCS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-common.h",
    "content": "// base/kaldi-common.h\n\n// Copyright 2009-2011 Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_KALDI_COMMON_H_\n#define KALDI_BASE_KALDI_COMMON_H_ 1\n\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>  // C string stuff like strcpy\n#include <string>\n#include <sstream>\n#include <stdexcept>\n#include <cassert>\n#include <vector>\n#include <iostream>\n#include <fstream>\n\n#include \"base/kaldi-utils.h\"\n#include \"base/kaldi-error.h\"\n#include \"base/kaldi-types.h\"\n#include \"base/io-funcs.h\"\n#include \"base/kaldi-math.h\"\n#include \"base/timer.h\"\n\n#endif  // KALDI_BASE_KALDI_COMMON_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-error.cc",
    "content": "// base/kaldi-error.cc\n\n// Copyright 2019 LAIX (Yi Sun)\n// Copyright 2019 SmartAction LLC (kkm)\n// Copyright 2016 Brno University of Technology (author: Karel Vesely)\n// Copyright 2009-2011  Microsoft Corporation;  Lukas Burget;  Ondrej Glembek\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifdef HAVE_EXECINFO_H\n#include <execinfo.h> // To get stack trace in error messages.\n// If this #include fails there is an error in the Makefile, it does not\n// support your platform well. Make sure HAVE_EXECINFO_H is undefined,\n// and the code will compile.\n#ifdef HAVE_CXXABI_H\n#include <cxxabi.h> // For name demangling.\n// Useful to decode the stack trace, but only used if we have execinfo.h\n#endif // HAVE_CXXABI_H\n#endif // HAVE_EXECINFO_H\n\n#include \"base/kaldi-common.h\"\n#include \"base/kaldi-error.h\"\n#include \"base/version.h\"\n\nnamespace kaldi {\n\n/***** GLOBAL VARIABLES FOR LOGGING *****/\n\nint32 g_kaldi_verbose_level = 0;\nstatic std::string program_name;\nstatic LogHandler log_handler = NULL;\n\nvoid SetProgramName(const char *basename) {\n  // Using the 'static std::string' for the program name is mostly harmless,\n  // because (a) Kaldi logging is undefined before main(), and (b) no stdc++\n  // string implementation has been found in the wild that would not be just\n  // an empty string when zero-initialized but not yet constructed.\n  program_name = basename;\n}\n\n/***** HELPER FUNCTIONS *****/\n\n// Trim filename to at most 1 trailing directory long. Given a filename like\n// \"/a/b/c/d/e/f.cc\", return \"e/f.cc\". Support both '/' and '\\' as the path\n// separator.\nstatic const char *GetShortFileName(const char *path) {\n  if (path == nullptr)\n    return \"\";\n\n  const char *prev = path, *last = path;\n  while ((path = std::strpbrk(path, \"\\\\/\")) != nullptr) {\n    ++path;\n    prev = last;\n    last = path;\n  }\n  return prev;\n}\n\n/***** STACK TRACE *****/\n\nnamespace internal {\nbool LocateSymbolRange(const std::string &trace_name, size_t *begin,\n                       size_t *end) {\n  // Find the first '_' with leading ' ' or '('.\n  *begin = std::string::npos;\n  for (size_t i = 1; i < trace_name.size(); i++) {\n    if (trace_name[i] != '_') {\n      continue;\n    }\n    if (trace_name[i - 1] == ' ' || trace_name[i - 1] == '(') {\n      *begin = i;\n      break;\n    }\n  }\n  if (*begin == std::string::npos) {\n    return false;\n  }\n  *end = trace_name.find_first_of(\" +\", *begin);\n  return *end != std::string::npos;\n}\n} // namespace internal\n\n#ifdef HAVE_EXECINFO_H\nstatic std::string Demangle(std::string trace_name) {\n#ifndef HAVE_CXXABI_H\n  return trace_name;\n#else  // HAVE_CXXABI_H\n  // Try demangle the symbol. We are trying to support the following formats\n  // produced by different platforms:\n  //\n  // Linux:\n  //   ./kaldi-error-test(_ZN5kaldi13UnitTestErrorEv+0xb) [0x804965d]\n  //\n  // Mac:\n  //   0 server 0x000000010f67614d _ZNK5kaldi13MessageLogger10LogMessageEv + 813\n  //\n  // We want to extract the name e.g., '_ZN5kaldi13UnitTestErrorEv' and\n  // demangle it info a readable name like kaldi::UnitTextError.\n  size_t begin, end;\n  if (!internal::LocateSymbolRange(trace_name, &begin, &end)) {\n    return trace_name;\n  }\n  std::string symbol = trace_name.substr(begin, end - begin);\n  int status;\n  char *demangled_name = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status);\n  if (status == 0 && demangled_name != nullptr) {\n    symbol = demangled_name;\n    free(demangled_name);\n  }\n  return trace_name.substr(0, begin) + symbol +\n         trace_name.substr(end, std::string::npos);\n#endif // HAVE_CXXABI_H\n}\n#endif // HAVE_EXECINFO_H\n\nstatic std::string KaldiGetStackTrace() {\n  std::string ans;\n#ifdef HAVE_EXECINFO_H\n  const size_t KALDI_MAX_TRACE_SIZE = 50;\n  const size_t KALDI_MAX_TRACE_PRINT = 50; // Must be even.\n  // Buffer for the trace.\n  void *trace[KALDI_MAX_TRACE_SIZE];\n  // Get the trace.\n  size_t size = backtrace(trace, KALDI_MAX_TRACE_SIZE);\n  // Get the trace symbols.\n  char **trace_symbol = backtrace_symbols(trace, size);\n  if (trace_symbol == NULL)\n    return ans;\n\n  // Compose a human-readable backtrace string.\n  ans += \"[ Stack-Trace: ]\\n\";\n  if (size <= KALDI_MAX_TRACE_PRINT) {\n    for (size_t i = 0; i < size; i++) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n  } else { // Print out first+last (e.g.) 5.\n    for (size_t i = 0; i < KALDI_MAX_TRACE_PRINT / 2; i++) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n    ans += \".\\n.\\n.\\n\";\n    for (size_t i = size - KALDI_MAX_TRACE_PRINT / 2; i < size; i++) {\n      ans += Demangle(trace_symbol[i]) + \"\\n\";\n    }\n    if (size == KALDI_MAX_TRACE_SIZE)\n      ans += \".\\n.\\n.\\n\"; // Stack was too long, probably a bug.\n  }\n\n  // We must free the array of pointers allocated by backtrace_symbols(),\n  // but not the strings themselves.\n  free(trace_symbol);\n#endif // HAVE_EXECINFO_H\n  return ans;\n}\n\n/***** KALDI LOGGING *****/\n\nMessageLogger::MessageLogger(LogMessageEnvelope::Severity severity,\n                             const char *func, const char *file, int32 line) {\n  // Obviously, we assume the strings survive the destruction of this object.\n  envelope_.severity = severity;\n  envelope_.func = func;\n  envelope_.file = GetShortFileName(file); // Points inside 'file'.\n  envelope_.line = line;\n}\n\nvoid MessageLogger::LogMessage() const {\n  // Send to the logging handler if provided.\n  if (log_handler != NULL) {\n    log_handler(envelope_, GetMessage().c_str());\n    return;\n  }\n\n  // Otherwise, use the default Kaldi logging.\n  // Build the log-message header.\n  std::stringstream full_message;\n  if (envelope_.severity > LogMessageEnvelope::kInfo) {\n    full_message << \"VLOG[\" << envelope_.severity << \"] (\";\n  } else {\n    switch (envelope_.severity) {\n    case LogMessageEnvelope::kInfo:\n      full_message << \"LOG (\";\n      break;\n    case LogMessageEnvelope::kWarning:\n      full_message << \"WARNING (\";\n      break;\n    case LogMessageEnvelope::kAssertFailed:\n      full_message << \"ASSERTION_FAILED (\";\n      break;\n    case LogMessageEnvelope::kError:\n    default: // If not the ERROR, it still an error!\n      full_message << \"ERROR (\";\n      break;\n    }\n  }\n  // Add other info from the envelope and the message text.\n  full_message << program_name.c_str() << \"[\" KALDI_VERSION \"]\" << ':'\n               << envelope_.func << \"():\" << envelope_.file << ':'\n               << envelope_.line << \") \" << GetMessage().c_str();\n\n  // Add stack trace for errors and assertion failures, if available.\n  if (envelope_.severity < LogMessageEnvelope::kWarning) {\n    const std::string &stack_trace = KaldiGetStackTrace();\n    if (!stack_trace.empty()) {\n      full_message << \"\\n\\n\" << stack_trace;\n    }\n  }\n\n  // Print the complete message to stderr.\n  full_message << \"\\n\";\n  std::cerr << full_message.str();\n}\n\n/***** KALDI ASSERTS *****/\n\nvoid KaldiAssertFailure_(const char *func, const char *file, int32 line,\n                         const char *cond_str) {\n  MessageLogger::Log() =\n      MessageLogger(LogMessageEnvelope::kAssertFailed, func, file, line)\n      << \"Assertion failed: (\" << cond_str << \")\";\n  fflush(NULL); // Flush all pending buffers, abort() may not flush stderr.\n  std::abort();\n}\n\n/***** THIRD-PARTY LOG-HANDLER *****/\n\nLogHandler SetLogHandler(LogHandler handler) {\n  LogHandler old_handler = log_handler;\n  log_handler = handler;\n  return old_handler;\n}\n\n} // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-error.h",
    "content": "// base/kaldi-error.h\n\n// Copyright 2019 LAIX (Yi Sun)\n// Copyright 2019 SmartAction LLC (kkm)\n// Copyright 2016 Brno University of Technology (author: Karel Vesely)\n// Copyright 2009-2011  Microsoft Corporation;  Ondrej Glembek;  Lukas Burget;\n//                      Saarland University\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_KALDI_ERROR_H_\n#define KALDI_BASE_KALDI_ERROR_H_ 1\n\n#include <cstdio>\n#include <cstring>\n#include <sstream>\n#include <stdexcept>\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-types.h\"\n#include \"base/kaldi-utils.h\"\n/* Important that this file does not depend on any other kaldi headers. */\n\n#ifdef _MSC_VER\n#define __func__ __FUNCTION__\n#endif\n\nnamespace kaldi {\n\n/// \\addtogroup error_group\n/// @{\n\n/***** PROGRAM NAME AND VERBOSITY LEVEL *****/\n\n/// Called by ParseOptions to set base name (no directory) of the executing\n/// program. The name is printed in logging code along with every message,\n/// because in our scripts, we often mix together the stderr of many programs.\n/// This function is very thread-unsafe.\nvoid SetProgramName(const char *basename);\n\n/// This is set by util/parse-options.{h,cc} if you set --verbose=? option.\n/// Do not use directly, prefer {Get,Set}VerboseLevel().\nextern int32 g_kaldi_verbose_level;\n\n/// Get verbosity level, usually set via command line '--verbose=' switch.\ninline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }\n\n/// This should be rarely used, except by programs using Kaldi as library;\n/// command-line programs set the verbose level automatically from ParseOptions.\ninline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }\n\n/***** KALDI LOGGING *****/\n\n/// Log message severity and source location info.\nstruct LogMessageEnvelope {\n  /// Message severity. In addition to these levels, positive values (1 to 6)\n  /// specify verbose logging level. Verbose messages are produced only when\n  /// SetVerboseLevel() has been called to set logging level to at least the\n  /// corresponding value.\n  enum Severity {\n    kAssertFailed = -3, //!< Assertion failure. abort() will be called.\n    kError = -2,        //!< Fatal error. KaldiFatalError will be thrown.\n    kWarning = -1,      //!< Indicates a recoverable but abnormal condition.\n    kInfo = 0,          //!< Informational message.\n  };\n  int severity;     //!< A Severity value, or positive verbosity level.\n  const char *func; //!< Name of the function invoking the logging.\n  const char *file; //!< Source file name with up to 1 leading directory.\n  int32 line;       //<! Line number in the source file.\n};\n\n/// Kaldi fatal runtime error exception. This exception is thrown from any use\n/// of the KALDI_ERR logging macro after the logging function, either set by\n/// SetLogHandler(), or the Kaldi's internal one, has returned.\nclass KaldiFatalError : public std::runtime_error {\npublic:\n  explicit KaldiFatalError(const std::string &message)\n      : std::runtime_error(message) {}\n  explicit KaldiFatalError(const char *message) : std::runtime_error(message) {}\n\n  /// Returns the exception name, \"kaldi::KaldiFatalError\".\n  virtual const char *what() const noexcept override {\n    return \"kaldi::KaldiFatalError\";\n  }\n\n  /// Returns the Kaldi error message logged by KALDI_ERR.\n  const char *KaldiMessage() const { return std::runtime_error::what(); }\n};\n\n// Class MessageLogger is the workhorse behind the KALDI_ASSERT, KALDI_ERR,\n// KALDI_WARN, KALDI_LOG and KALDI_VLOG macros. It formats the message, then\n// either prints it to stderr or passes to the custom logging handler if\n// provided. Then, in case of the error, throws a KaldiFatalError exception, or\n// in case of failed KALDI_ASSERT, calls std::abort().\nclass MessageLogger {\npublic:\n  /// The constructor stores the message's \"envelope\", a set of data which\n  // identifies the location in source which is sending the message to log.\n  // The pointers to strings are stored internally, and not owned or copied,\n  // so that their storage must outlive this object.\n  MessageLogger(LogMessageEnvelope::Severity severity, const char *func,\n                const char *file, int32 line);\n\n  // The stream insertion operator, used in e.g. 'KALDI_LOG << \"Message\"'.\n  template <typename T> MessageLogger &operator<<(const T &val) {\n    ss_ << val;\n    return *this;\n  }\n\n  // When assigned a MessageLogger, log its contents.\n  struct Log final {\n    void operator=(const MessageLogger &logger) { logger.LogMessage(); }\n  };\n\n  // When assigned a MessageLogger, log its contents and then throw\n  // a KaldiFatalError.\n  struct LogAndThrow final {\n    [[noreturn]] void operator=(const MessageLogger &logger) {\n      logger.LogMessage();\n      throw KaldiFatalError(logger.GetMessage());\n    }\n  };\n\nprivate:\n  std::string GetMessage() const { return ss_.str(); }\n  void LogMessage() const;\n\n  LogMessageEnvelope envelope_;\n  std::ostringstream ss_;\n};\n\n// Logging macros.\n#define KALDI_ERR                                                              \\\n  ::kaldi::MessageLogger::LogAndThrow() = ::kaldi::MessageLogger(              \\\n      ::kaldi::LogMessageEnvelope::kError, __func__, __FILE__, __LINE__)\n#define KALDI_WARN                                                             \\\n  ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger(                      \\\n      ::kaldi::LogMessageEnvelope::kWarning, __func__, __FILE__, __LINE__)\n#define KALDI_LOG                                                              \\\n  ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger(                      \\\n      ::kaldi::LogMessageEnvelope::kInfo, __func__, __FILE__, __LINE__)\n#define KALDI_VLOG(v)                                                          \\\n  if ((v) <= ::kaldi::GetVerboseLevel())                                       \\\n  ::kaldi::MessageLogger::Log() =                                              \\\n      ::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v),       \\\n                             __func__, __FILE__, __LINE__)\n\n/***** KALDI ASSERTS *****/\n\n[[noreturn]] void KaldiAssertFailure_(const char *func, const char *file,\n                                      int32 line, const char *cond_str);\n\n// Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT:\n//\n// A single block {} around if /else  does not work, because it causes\n// syntax error (unmatched else block) in the following code:\n//\n// if (condition)\n//   KALDI_ASSERT(condition2);\n// else\n//   SomethingElse();\n//\n// do {} while(0) -- note there is no semicolon at the end! -- works nicely,\n// and compilers will be able to optimize the loop away (as the condition\n// is always false).\n//\n// Also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h, and\n// KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE, also defined\n// there.\n#ifdef PPS_DEBUG\n#define KALDI_ASSERT(cond)                                                     \\\n  do {                                                                         \\\n    if (cond)                                                                  \\\n      (void)0;                                                                 \\\n    else                                                                       \\\n      ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);       \\\n  } while (0)\n#else\n#define KALDI_ASSERT(cond) (void)0\n#endif\n\n// Some more expensive asserts only checked if this defined.\n#ifdef KALDI_PARANOID\n#define KALDI_PARANOID_ASSERT(cond)                                            \\\n  do {                                                                         \\\n    if (cond)                                                                  \\\n      (void)0;                                                                 \\\n    else                                                                       \\\n      ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);       \\\n  } while (0)\n#else\n#define KALDI_PARANOID_ASSERT(cond) (void)0\n#endif\n\n/***** THIRD-PARTY LOG-HANDLER *****/\n\n/// Type of third-party logging function.\ntypedef void (*LogHandler)(const LogMessageEnvelope &envelope,\n                           const char *message);\n\n/// Set logging handler. If called with a non-NULL function pointer, the\n/// function pointed by it is called to send messages to a caller-provided log.\n/// If called with a NULL pointer, restores default Kaldi error logging to\n/// stderr. This function is obviously not thread safe; the log handler must be.\n/// Returns a previously set logging handler pointer, or NULL.\nLogHandler SetLogHandler(LogHandler);\n\n/// @} end \"addtogroup error_group\"\n\n// Functions within internal is exported for testing only, do not use.\nnamespace internal {\nbool LocateSymbolRange(const std::string &trace_name, size_t *begin,\n                       size_t *end);\n} // namespace internal\n} // namespace kaldi\n\n#endif // KALDI_BASE_KALDI_ERROR_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-math.cc",
    "content": "// base/kaldi-math.cc\n\n// Copyright 2009-2011  Microsoft Corporation;  Yanmin Qian;\n//                      Saarland University;  Jan Silovsky\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-math.h\"\n#ifndef _MSC_VER\n#include <stdlib.h>\n#include <unistd.h>\n#endif\n#include <string>\n#include <mutex>\n\nnamespace kaldi {\n// These routines are tested in matrix/matrix-test.cc\n\nint32 RoundUpToNearestPowerOfTwo(int32 n) {\n  KALDI_ASSERT(n > 0);\n  n--;\n  n |= n >> 1;\n  n |= n >> 2;\n  n |= n >> 4;\n  n |= n >> 8;\n  n |= n >> 16;\n  return n+1;\n}\n\nstatic std::mutex _RandMutex;\n\nint Rand(struct RandomState* state) {\n#if !defined(_POSIX_THREAD_SAFE_FUNCTIONS)\n  // On Windows and Cygwin, just call Rand()\n  return rand();\n#else\n  if (state) {\n    return rand_r(&(state->seed));\n  } else {\n    std::lock_guard<std::mutex> lock(_RandMutex);\n    return rand();\n  }\n#endif\n}\n\nRandomState::RandomState() {\n  // we initialize it as Rand() + 27437 instead of just Rand(), because on some\n  // systems, e.g. at the very least Mac OSX Yosemite and later, it seems to be\n  // the case that rand_r when initialized with rand() will give you the exact\n  // same sequence of numbers that rand() will give if you keep calling rand()\n  // after that initial call.  This can cause problems with repeated sequences.\n  // For example if you initialize two RandomState structs one after the other\n  // without calling rand() in between, they would give you the same sequence\n  // offset by one (if we didn't have the \"+ 27437\" in the code).  27437 is just\n  // a randomly chosen prime number.\n  seed = Rand() + 27437;\n}\n\nbool WithProb(BaseFloat prob, struct RandomState* state) {\n  KALDI_ASSERT(prob >= 0 && prob <= 1.1);  // prob should be <= 1.0,\n  // but we allow slightly larger values that could arise from roundoff in\n  // previous calculations.\n  KALDI_COMPILE_TIME_ASSERT(RAND_MAX > 128 * 128);\n  if (prob == 0) return false;\n  else if (prob == 1.0) return true;\n  else if (prob * RAND_MAX < 128.0) {\n    // prob is very small but nonzero, and the \"main algorithm\"\n    // wouldn't work that well.  So: with probability 1/128, we\n    // return WithProb (prob * 128), else return false.\n    if (Rand(state) < RAND_MAX / 128) {  // with probability 128...\n      // Note: we know that prob * 128.0 < 1.0, because\n      // we asserted RAND_MAX > 128 * 128.\n      return WithProb(prob * 128.0);\n    } else {\n      return false;\n    }\n  } else {\n    return (Rand(state) < ((RAND_MAX + static_cast<BaseFloat>(1.0)) * prob));\n  }\n}\n\nint32 RandInt(int32 min_val, int32 max_val, struct RandomState* state) {\n  // This is not exact.\n  KALDI_ASSERT(max_val >= min_val);\n  if (max_val == min_val) return min_val;\n\n#ifdef _MSC_VER\n  // RAND_MAX is quite small on Windows -> may need to handle larger numbers.\n  if (RAND_MAX > (max_val-min_val)*8) {\n        // *8 to avoid large inaccuracies in probability, from the modulus...\n    return min_val +\n      ((unsigned int)Rand(state) % (unsigned int)(max_val+1-min_val));\n  } else {\n    if ((unsigned int)(RAND_MAX*RAND_MAX) >\n        (unsigned int)((max_val+1-min_val)*8)) {\n        // *8 to avoid inaccuracies in probability, from the modulus...\n      return min_val + ( (unsigned int)( (Rand(state)+RAND_MAX*Rand(state)))\n                    % (unsigned int)(max_val+1-min_val));\n    } else {\n      KALDI_ERR << \"rand_int failed because we do not support such large \"\n          \"random numbers. (Extend this function).\";\n    }\n  }\n#else\n  return min_val +\n      (static_cast<int32>(Rand(state)) % static_cast<int32>(max_val+1-min_val));\n#endif\n}\n\n// Returns poisson-distributed random number.\n// Take care: this takes time proportional\n// to lambda.  Faster algorithms exist but are more complex.\nint32 RandPoisson(float lambda, struct RandomState* state) {\n  // Knuth's algorithm.\n  KALDI_ASSERT(lambda >= 0);\n  float L = expf(-lambda), p = 1.0;\n  int32 k = 0;\n  do {\n    k++;\n    float u = RandUniform(state);\n    p *= u;\n  } while (p > L);\n  return k-1;\n}\n\nvoid RandGauss2(float *a, float *b, RandomState *state) {\n  KALDI_ASSERT(a);\n  KALDI_ASSERT(b);\n  float u1 = RandUniform(state);\n  float u2 = RandUniform(state);\n  u1 = sqrtf(-2.0f * logf(u1));\n  u2 =  2.0f * M_PI * u2;\n  *a = u1 * cosf(u2);\n  *b = u1 * sinf(u2);\n}\n\nvoid RandGauss2(double *a, double *b, RandomState *state) {\n  KALDI_ASSERT(a);\n  KALDI_ASSERT(b);\n  float a_float, b_float;\n  // Just because we're using doubles doesn't mean we need super-high-quality\n  // random numbers, so we just use the floating-point version internally.\n  RandGauss2(&a_float, &b_float, state);\n  *a = a_float;\n  *b = b_float;\n}\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-math.h",
    "content": "// base/kaldi-math.h\n\n// Copyright 2009-2011  Ondrej Glembek;  Microsoft Corporation;  Yanmin Qian;\n//                      Jan Silovsky;  Saarland University\n//\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_KALDI_MATH_H_\n#define KALDI_BASE_KALDI_MATH_H_ 1\n\n#ifdef _MSC_VER\n#include <float.h>\n#endif\n\n#include <cmath>\n#include <limits>\n#include <vector>\n\n#include \"base/kaldi-types.h\"\n#include \"base/kaldi-common.h\"\n\n\n#ifndef DBL_EPSILON\n#define DBL_EPSILON 2.2204460492503131e-16\n#endif\n#ifndef FLT_EPSILON\n#define FLT_EPSILON 1.19209290e-7f\n#endif\n\n#ifndef M_PI\n#define M_PI 3.1415926535897932384626433832795\n#endif\n\n#ifndef M_SQRT2\n#define M_SQRT2 1.4142135623730950488016887\n#endif\n\n#ifndef M_2PI\n#define M_2PI 6.283185307179586476925286766559005\n#endif\n\n#ifndef M_SQRT1_2\n#define M_SQRT1_2 0.7071067811865475244008443621048490\n#endif\n\n#ifndef M_LOG_2PI\n#define M_LOG_2PI 1.8378770664093454835606594728112\n#endif\n\n#ifndef M_LN2\n#define M_LN2 0.693147180559945309417232121458\n#endif\n\n#ifndef M_LN10\n#define M_LN10 2.302585092994045684017991454684\n#endif\n\n\n#define KALDI_ISNAN std::isnan\n#define KALDI_ISINF std::isinf\n#define KALDI_ISFINITE(x) std::isfinite(x)\n\n#if !defined(KALDI_SQR)\n# define KALDI_SQR(x) ((x) * (x))\n#endif\n\nnamespace kaldi {\n\n#if !defined(_MSC_VER) || (_MSC_VER >= 1900)\ninline double Exp(double x) { return exp(x); }\n#ifndef KALDI_NO_EXPF\ninline float Exp(float x) { return expf(x); }\n#else\ninline float Exp(float x) { return exp(static_cast<double>(x)); }\n#endif  // KALDI_NO_EXPF\n#else\ninline double Exp(double x) { return exp(x); }\n#if !defined(__INTEL_COMPILER) && _MSC_VER == 1800 && defined(_M_X64)\n// Microsoft CL v18.0 buggy 64-bit implementation of\n// expf() incorrectly returns -inf for exp(-inf).\ninline float Exp(float x) { return exp(static_cast<double>(x)); }\n#else\ninline float Exp(float x) { return expf(x); }\n#endif  // !defined(__INTEL_COMPILER) && _MSC_VER == 1800 && defined(_M_X64)\n#endif  // !defined(_MSC_VER) || (_MSC_VER >= 1900)\n\ninline double Log(double x) { return log(x); }\ninline float Log(float x) { return logf(x); }\n\n#if !defined(_MSC_VER) || (_MSC_VER >= 1700)\ninline double Log1p(double x) {  return log1p(x); }\ninline float Log1p(float x) {  return log1pf(x); }\n#else\ninline double Log1p(double x) {\n  const double cutoff = 1.0e-08;\n  if (x < cutoff)\n    return x - 0.5 * x * x;\n  else\n    return Log(1.0 + x);\n}\n\ninline float Log1p(float x) {\n  const float cutoff = 1.0e-07;\n  if (x < cutoff)\n    return x - 0.5 * x * x;\n  else\n    return Log(1.0 + x);\n}\n#endif\n\nstatic const double kMinLogDiffDouble = Log(DBL_EPSILON);  // negative!\nstatic const float kMinLogDiffFloat = Log(FLT_EPSILON);  // negative!\n\n// -infinity\nconst float kLogZeroFloat = -std::numeric_limits<float>::infinity();\nconst double kLogZeroDouble = -std::numeric_limits<double>::infinity();\nconst BaseFloat kLogZeroBaseFloat = -std::numeric_limits<BaseFloat>::infinity();\n\n// Returns a random integer between 0 and RAND_MAX, inclusive\nint Rand(struct RandomState* state = NULL);\n\n// State for thread-safe random number generator\nstruct RandomState {\n  RandomState();\n  unsigned seed;\n};\n\n// Returns a random integer between first and last inclusive.\nint32 RandInt(int32 first, int32 last, struct RandomState* state = NULL);\n\n// Returns true with probability \"prob\",\nbool WithProb(BaseFloat prob, struct RandomState* state = NULL);\n// with 0 <= prob <= 1 [we check this].\n// Internally calls Rand().  This function is carefully implemented so\n// that it should work even if prob is very small.\n\n/// Returns a random number strictly between 0 and 1.\ninline float RandUniform(struct RandomState* state = NULL) {\n  return static_cast<float>((Rand(state) + 1.0) / (RAND_MAX+2.0));\n}\n\ninline float RandGauss(struct RandomState* state = NULL) {\n  return static_cast<float>(sqrtf (-2 * Log(RandUniform(state)))\n                            * cosf(2*M_PI*RandUniform(state)));\n}\n\n// Returns poisson-distributed random number.  Uses Knuth's algorithm.\n// Take care: this takes time proportional\n// to lambda.  Faster algorithms exist but are more complex.\nint32 RandPoisson(float lambda, struct RandomState* state = NULL);\n\n// Returns a pair of gaussian random numbers. Uses Box-Muller transform\nvoid RandGauss2(float *a, float *b, RandomState *state = NULL);\nvoid RandGauss2(double *a, double *b, RandomState *state = NULL);\n\n// Also see Vector<float,double>::RandCategorical().\n\n// This is a randomized pruning mechanism that preserves expectations,\n// that we typically use to prune posteriors.\ntemplate<class Float>\ninline Float RandPrune(Float post, BaseFloat prune_thresh,\n                       struct RandomState* state = NULL) {\n  KALDI_ASSERT(prune_thresh >= 0.0);\n  if (post == 0.0 || std::abs(post) >= prune_thresh)\n    return post;\n  return (post >= 0 ? 1.0 : -1.0) *\n      (RandUniform(state) <= fabs(post)/prune_thresh ? prune_thresh : 0.0);\n}\n\n// returns log(exp(x) + exp(y)).\ninline double LogAdd(double x, double y) {\n  double diff;\n\n  if (x < y) {\n    diff = x - y;\n    x = y;\n  } else {\n    diff = y - x;\n  }\n  // diff is negative.  x is now the larger one.\n\n  if (diff >= kMinLogDiffDouble) {\n    double res;\n    res = x + Log1p(Exp(diff));\n    return res;\n  } else {\n    return x;  // return the larger one.\n  }\n}\n\n\n// returns log(exp(x) + exp(y)).\ninline float LogAdd(float x, float y) {\n  float diff;\n\n  if (x < y) {\n    diff = x - y;\n    x = y;\n  } else {\n    diff = y - x;\n  }\n  // diff is negative.  x is now the larger one.\n\n  if (diff >= kMinLogDiffFloat) {\n    float res;\n    res = x + Log1p(Exp(diff));\n    return res;\n  } else {\n    return x;  // return the larger one.\n  }\n}\n\n\n// returns log(exp(x) - exp(y)).\ninline double LogSub(double x, double y) {\n  if (y >= x) {  // Throws exception if y>=x.\n    if (y == x)\n      return kLogZeroDouble;\n    else\n      KALDI_ERR << \"Cannot subtract a larger from a smaller number.\";\n  }\n\n  double diff = y - x;  // Will be negative.\n  double res = x + Log(1.0 - Exp(diff));\n\n  // res might be NAN if diff ~0.0, and 1.0-exp(diff) == 0 to machine precision\n  if (KALDI_ISNAN(res))\n    return kLogZeroDouble;\n  return res;\n}\n\n\n// returns log(exp(x) - exp(y)).\ninline float LogSub(float x, float y) {\n  if (y >= x) {  // Throws exception if y>=x.\n    if (y == x)\n      return kLogZeroDouble;\n    else\n      KALDI_ERR << \"Cannot subtract a larger from a smaller number.\";\n  }\n\n  float diff = y - x;  // Will be negative.\n  float res = x + Log(1.0f - Exp(diff));\n\n  // res might be NAN if diff ~0.0, and 1.0-exp(diff) == 0 to machine precision\n  if (KALDI_ISNAN(res))\n    return kLogZeroFloat;\n  return res;\n}\n\n/// return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).\nstatic inline bool ApproxEqual(float a, float b,\n                               float relative_tolerance = 0.001) {\n  // a==b handles infinities.\n  if (a == b) return true;\n  float diff = std::abs(a-b);\n  if (diff == std::numeric_limits<float>::infinity()\n      || diff != diff) return false;  // diff is +inf or nan.\n  return (diff <= relative_tolerance*(std::abs(a)+std::abs(b)));\n}\n\n/// assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))\nstatic inline void AssertEqual(float a, float b,\n                               float relative_tolerance = 0.001) {\n  // a==b handles infinities.\n  KALDI_ASSERT(ApproxEqual(a, b, relative_tolerance));\n}\n\n\n// RoundUpToNearestPowerOfTwo does the obvious thing. It crashes if n <= 0.\nint32 RoundUpToNearestPowerOfTwo(int32 n);\n\n/// Returns a / b, rounding towards negative infinity in all cases.\nstatic inline int32 DivideRoundingDown(int32 a, int32 b) {\n  KALDI_ASSERT(b != 0);\n  if (a * b >= 0)\n    return a / b;\n  else if (a < 0)\n    return (a - b + 1) / b;\n  else\n    return (a - b - 1) / b;\n}\n\ntemplate<class I> I  Gcd(I m, I n) {\n  if (m == 0 || n == 0) {\n    if (m == 0 && n == 0) {  // gcd not defined, as all integers are divisors.\n      KALDI_ERR << \"Undefined GCD since m = 0, n = 0.\";\n    }\n    return (m == 0 ? (n > 0 ? n : -n) : ( m > 0 ? m : -m));\n    // return absolute value of whichever is nonzero\n  }\n  // could use compile-time assertion\n  // but involves messing with complex template stuff.\n  KALDI_ASSERT(std::numeric_limits<I>::is_integer);\n  while (1) {\n    m %= n;\n    if (m == 0) return (n > 0 ? n : -n);\n    n %= m;\n    if (n == 0) return (m > 0 ? m : -m);\n  }\n}\n\n/// Returns the least common multiple of two integers.  Will\n/// crash unless the inputs are positive.\ntemplate<class I> I  Lcm(I m, I n) {\n  KALDI_ASSERT(m > 0 && n > 0);\n  I gcd = Gcd(m, n);\n  return gcd * (m/gcd) * (n/gcd);\n}\n\n\ntemplate<class I> void Factorize(I m, std::vector<I> *factors) {\n  // Splits a number into its prime factors, in sorted order from\n  // least to greatest,  with duplication.  A very inefficient\n  // algorithm, which is mainly intended for use in the\n  // mixed-radix FFT computation (where we assume most factors\n  // are small).\n  KALDI_ASSERT(factors != NULL);\n  KALDI_ASSERT(m >= 1);  // Doesn't work for zero or negative numbers.\n  factors->clear();\n  I small_factors[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };\n\n  // First try small factors.\n  for (I i = 0; i < 10; i++) {\n    if (m == 1) return;  // We're done.\n    while (m % small_factors[i] == 0) {\n      m /= small_factors[i];\n      factors->push_back(small_factors[i]);\n    }\n  }\n  // Next try all odd numbers starting from 31.\n  for (I j = 31;; j += 2) {\n    if (m == 1) return;\n    while (m % j == 0) {\n      m /= j;\n      factors->push_back(j);\n    }\n  }\n}\n\ninline double Hypot(double x, double y) {  return hypot(x, y); }\ninline float Hypot(float x, float y) {  return hypotf(x, y); }\n\n\n\n\n}  // namespace kaldi\n\n\n#endif  // KALDI_BASE_KALDI_MATH_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-types.h",
    "content": "// base/kaldi-types.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University;\n//                      Jan Silovsky;  Yanmin Qian\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_KALDI_TYPES_H_\n#define KALDI_BASE_KALDI_TYPES_H_ 1\n\nnamespace kaldi {\n// TYPEDEFS ..................................................................\n#if (KALDI_DOUBLEPRECISION != 0)\ntypedef double  BaseFloat;\n#else\ntypedef float   BaseFloat;\n#endif\n}\n\n#ifdef _MSC_VER\n#include <basetsd.h>\n#define ssize_t SSIZE_T\n#endif\n\n// we can do this a different way if some platform\n// we find in the future lacks stdint.h\n#include <stdint.h>\n\n// for discussion on what to do if you need compile kaldi\n// without OpenFST, see the bottom of this file\n\n#ifndef COMPILE_WITHOUT_OPENFST\n\n#ifdef WITH_ASR\n#include <fst/types.h>\n#else\nusing int8 = int8_t;\nusing int16 = int16_t;\nusing int32 = int32_t;\nusing int64 = int64_t;\n\nusing uint8 = uint8_t;\nusing uint16 = uint16_t;\nusing uint32 = uint32_t;\nusing uint64 = uint64_t;\n#endif\n\nnamespace kaldi {\n  using ::int16;\n  using ::int32;\n  using ::int64;\n  using ::uint16;\n  using ::uint32;\n  using ::uint64;\n  typedef float   float32;\n  typedef double double64;\n}  // end namespace kaldi\n\n#else\n// In a theoretical case you decide compile Kaldi without the OpenFST\n// comment the previous namespace statement and uncomment the following\n\nnamespace kaldi {\n  typedef int8_t   int8;\n  typedef int16_t  int16;\n  typedef int32_t  int32;\n  typedef int64_t  int64;\n\n  typedef uint8_t  uint8;\n  typedef uint16_t uint16;\n  typedef uint32_t uint32;\n  typedef uint64_t uint64;\n  typedef float    float32;\n  typedef double   double64;\n}  // end namespace kaldi\n#endif\n\n#endif  // KALDI_BASE_KALDI_TYPES_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-utils.cc",
    "content": "// base/kaldi-utils.cc\n// Copyright 2009-2011   Karel Vesely;  Yanmin Qian;  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifdef _WIN32_WINNT_WIN8\n#include <Synchapi.h>\n#elif defined(_WIN32) || defined(_MSC_VER) || defined(MINGW)\n#include <Windows.h>\n#if defined(_MSC_VER) && _MSC_VER < 1900\n#define snprintf _snprintf\n#endif /* _MSC_VER < 1900 */\n#else\n#include <unistd.h>\n#endif\n\n#include <string>\n#include \"base/kaldi-common.h\"\n\n\nnamespace kaldi {\n\nstd::string CharToString(const char &c) {\n  char buf[20];\n  if (std::isprint(c))\n    snprintf(buf, sizeof(buf), \"\\'%c\\'\", c);\n  else\n    snprintf(buf, sizeof(buf), \"[character %d]\", static_cast<int>(c));\n  return (std::string) buf;\n}\n\nvoid Sleep(float seconds) {\n#if defined(_MSC_VER) || defined(MINGW)\n  ::Sleep(static_cast<int>(seconds * 1000.0));\n#elif defined(__CYGWIN__)\n  sleep(static_cast<int>(seconds));\n#else\n  usleep(static_cast<int>(seconds * 1000000.0));\n#endif\n}\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/base/kaldi-utils.h",
    "content": "// base/kaldi-utils.h\n\n// Copyright 2009-2011  Ondrej Glembek;  Microsoft Corporation;\n//                      Saarland University;  Karel Vesely;  Yanmin Qian\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_BASE_KALDI_UTILS_H_\n#define KALDI_BASE_KALDI_UTILS_H_ 1\n\n#if defined(_MSC_VER)\n# define WIN32_LEAN_AND_MEAN\n# define NOMINMAX\n# include <windows.h>\n#endif\n\n#ifdef _MSC_VER\n#include <stdio.h>\n#define unlink _unlink\n#else\n#include <unistd.h>\n#endif\n\n#include <limits>\n#include <string>\n\n#if defined(_MSC_VER)\n#pragma warning(disable: 4244 4056 4305 4800 4267 4996 4756 4661)\n#if _MSC_VER < 1400\n#define __restrict__\n#else\n#define __restrict__ __restrict\n#endif\n#endif\n\n#if defined(_MSC_VER)\n#  define KALDI_MEMALIGN(align, size, pp_orig) \\\n  (*(pp_orig) = _aligned_malloc(size, align))\n#  define KALDI_MEMALIGN_FREE(x) _aligned_free(x)\n#elif defined(__CYGWIN__)\n#  define KALDI_MEMALIGN(align, size, pp_orig) \\\n  (*(pp_orig) = aligned_alloc(align, size))\n#  define KALDI_MEMALIGN_FREE(x) free(x)\n#else\n#  define KALDI_MEMALIGN(align, size, pp_orig) \\\n     (!posix_memalign(pp_orig, align, size) ? *(pp_orig) : NULL)\n#  define KALDI_MEMALIGN_FREE(x) free(x)\n#endif\n\n#ifdef __ICC\n#pragma warning(disable: 383)  // ICPC remark we don't want.\n#pragma warning(disable: 810)  // ICPC remark we don't want.\n#pragma warning(disable: 981)  // ICPC remark we don't want.\n#pragma warning(disable: 1418)  // ICPC remark we don't want.\n#pragma warning(disable: 444)  // ICPC remark we don't want.\n#pragma warning(disable: 869)  // ICPC remark we don't want.\n#pragma warning(disable: 1287)  // ICPC remark we don't want.\n#pragma warning(disable: 279)  // ICPC remark we don't want.\n#pragma warning(disable: 981)  // ICPC remark we don't want.\n#endif\n\n\nnamespace kaldi {\n\n\n// CharToString prints the character in a human-readable form, for debugging.\nstd::string CharToString(const char &c);\n\n\ninline int MachineIsLittleEndian() {\n  int check = 1;\n  return (*reinterpret_cast<char*>(&check) != 0);\n}\n\n// This function kaldi::Sleep() provides a portable way\n// to sleep for a possibly fractional\n// number of seconds.  On Windows it's only accurate to microseconds.\nvoid Sleep(float seconds);\n}\n\n#define KALDI_SWAP8(a) { \\\n  int t = (reinterpret_cast<char*>(&a))[0];\\\n          (reinterpret_cast<char*>(&a))[0]=(reinterpret_cast<char*>(&a))[7];\\\n          (reinterpret_cast<char*>(&a))[7]=t;\\\n      t = (reinterpret_cast<char*>(&a))[1];\\\n          (reinterpret_cast<char*>(&a))[1]=(reinterpret_cast<char*>(&a))[6];\\\n          (reinterpret_cast<char*>(&a))[6]=t;\\\n      t = (reinterpret_cast<char*>(&a))[2];\\\n          (reinterpret_cast<char*>(&a))[2]=(reinterpret_cast<char*>(&a))[5];\\\n          (reinterpret_cast<char*>(&a))[5]=t;\\\n      t = (reinterpret_cast<char*>(&a))[3];\\\n          (reinterpret_cast<char*>(&a))[3]=(reinterpret_cast<char*>(&a))[4];\\\n          (reinterpret_cast<char*>(&a))[4]=t;}\n#define KALDI_SWAP4(a) { \\\n  int t = (reinterpret_cast<char*>(&a))[0];\\\n          (reinterpret_cast<char*>(&a))[0]=(reinterpret_cast<char*>(&a))[3];\\\n          (reinterpret_cast<char*>(&a))[3]=t;\\\n      t = (reinterpret_cast<char*>(&a))[1];\\\n          (reinterpret_cast<char*>(&a))[1]=(reinterpret_cast<char*>(&a))[2];\\\n          (reinterpret_cast<char*>(&a))[2]=t;}\n#define KALDI_SWAP2(a) { \\\n  int t = (reinterpret_cast<char*>(&a))[0];\\\n          (reinterpret_cast<char*>(&a))[0]=(reinterpret_cast<char*>(&a))[1];\\\n          (reinterpret_cast<char*>(&a))[1]=t;}\n\n\n// Makes copy constructor and operator= private.\n#define KALDI_DISALLOW_COPY_AND_ASSIGN(type)    \\\n  type(const type&);                  \\\n  void operator = (const type&)\n\ntemplate<bool B> class KaldiCompileTimeAssert { };\ntemplate<> class KaldiCompileTimeAssert<true> {\n public:\n  static inline void Check() { }\n};\n\n#define KALDI_COMPILE_TIME_ASSERT(b) KaldiCompileTimeAssert<(b)>::Check()\n\n#define KALDI_ASSERT_IS_INTEGER_TYPE(I) \\\n  KaldiCompileTimeAssert<std::numeric_limits<I>::is_specialized \\\n                 && std::numeric_limits<I>::is_integer>::Check()\n\n#define KALDI_ASSERT_IS_FLOATING_TYPE(F) \\\n  KaldiCompileTimeAssert<std::numeric_limits<F>::is_specialized \\\n                && !std::numeric_limits<F>::is_integer>::Check()\n\n#if defined(_MSC_VER)\n#define KALDI_STRCASECMP _stricmp\n#elif defined(__CYGWIN__)\n#include <strings.h>\n#define KALDI_STRCASECMP strcasecmp\n#else\n#define KALDI_STRCASECMP strcasecmp\n#endif\n#ifdef _MSC_VER\n#  define KALDI_STRTOLL(cur_cstr, end_cstr) _strtoi64(cur_cstr, end_cstr, 10);\n#else\n#  define KALDI_STRTOLL(cur_cstr, end_cstr) strtoll(cur_cstr, end_cstr, 10);\n#endif\n\n#endif  // KALDI_BASE_KALDI_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/timer.cc",
    "content": "// base/timer.cc\n\n// Copyright 2018  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/timer.h\"\n#include \"base/kaldi-error.h\"\n#include <algorithm>\n#include <iomanip>\n#include <map>\n#include <unordered_map>\n\nnamespace kaldi {\n\nclass ProfileStats {\n public:\n  void AccStats(const char *function_name, double elapsed) {\n    std::unordered_map<const char*, ProfileStatsEntry>::iterator\n        iter = map_.find(function_name);\n    if (iter == map_.end()) {\n      map_[function_name] = ProfileStatsEntry(function_name);\n      map_[function_name].total_time = elapsed;\n    } else {\n      iter->second.total_time += elapsed;\n    }\n  }\n  ~ProfileStats() {\n    // This map makes sure we agglomerate the time if there were any duplicate\n    // addresses of strings.\n    std::unordered_map<std::string, double> total_time;\n    for (auto iter = map_.begin(); iter != map_.end(); iter++)\n      total_time[iter->second.name] += iter->second.total_time;\n\n    ReverseSecondComparator comp;\n    std::vector<std::pair<std::string, double> > pairs(total_time.begin(),\n                                                       total_time.end());\n    std::sort(pairs.begin(), pairs.end(), comp);\n    for (size_t i = 0; i < pairs.size(); i++) {\n      KALDI_LOG << \"Time taken in \" << pairs[i].first << \" is \"\n                << std::fixed << std::setprecision(2) << pairs[i].second << \"s.\";\n    }\n  }\n private:\n\n  struct ProfileStatsEntry {\n    std::string name;\n    double total_time;\n    ProfileStatsEntry() { }\n    ProfileStatsEntry(const char *name): name(name) { }\n  };\n\n  struct ReverseSecondComparator {\n    bool operator () (const std::pair<std::string, double> &a,\n                      const std::pair<std::string, double> &b) {\n      return a.second > b.second;\n    }\n  };\n\n  // Note: this map is keyed on the address of the string, there is no proper\n  // hash function.  The assumption is that the strings are compile-time\n  // constants.\n  std::unordered_map<const char*, ProfileStatsEntry> map_;\n};\n\nProfileStats g_profile_stats;\n\nProfiler::~Profiler() {\n  g_profile_stats.AccStats(name_, tim_.Elapsed());\n}\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/base/timer.h",
    "content": "// base/timer.h\n\n// Copyright 2009-2011  Ondrej Glembek;  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_BASE_TIMER_H_\n#define KALDI_BASE_TIMER_H_\n\n#include \"base/kaldi-utils.h\"\n#include \"base/kaldi-error.h\"\n\n\n#if defined(_MSC_VER) || defined(MINGW)\n\nnamespace kaldi {\nclass Timer {\n public:\n  Timer() { Reset(); }\n\n  // You can initialize with bool to control whether or not you want the time to\n  // be set when the object is created.\n  explicit Timer(bool set_timer) { if (set_timer) Reset(); }\n\n  void Reset() {\n    QueryPerformanceCounter(&time_start_);\n  }\n  double Elapsed() const {\n    LARGE_INTEGER time_end;\n    LARGE_INTEGER freq;\n    QueryPerformanceCounter(&time_end);\n\n    if (QueryPerformanceFrequency(&freq) == 0) {\n      //  Hardware does not support this.\n      return 0.0;\n    }\n    return (static_cast<double>(time_end.QuadPart) -\n            static_cast<double>(time_start_.QuadPart)) /\n           (static_cast<double>(freq.QuadPart));\n  }\n private:\n  LARGE_INTEGER time_start_;\n};\n\n\n#else\n#include <sys/time.h>\n#include <unistd.h>\n\nnamespace kaldi {\nclass Timer {\n public:\n  Timer() { Reset(); }\n\n  // You can initialize with bool to control whether or not you want the time to\n  // be set when the object is created.\n  explicit Timer(bool set_timer) { if (set_timer) Reset(); }\n\n  void Reset() { gettimeofday(&this->time_start_, &time_zone_); }\n\n  /// Returns time in seconds.\n  double Elapsed() const {\n    struct timeval time_end;\n    struct timezone time_zone;\n    gettimeofday(&time_end, &time_zone);\n    double t1, t2;\n    t1 =  static_cast<double>(time_start_.tv_sec) +\n          static_cast<double>(time_start_.tv_usec)/(1000*1000);\n    t2 =  static_cast<double>(time_end.tv_sec) +\n          static_cast<double>(time_end.tv_usec)/(1000*1000);\n    return t2-t1;\n  }\n\n private:\n  struct timeval time_start_;\n  struct timezone time_zone_;\n};\n\n#endif\n\nclass Profiler {\n public:\n  // Caution: the 'const char' should always be a string constant; for speed,\n  // internally the profiling code uses the address of it as a lookup key.\n  Profiler(const char *function_name): name_(function_name) { }\n  ~Profiler();\n private:\n  Timer tim_;\n  const char *name_;\n};\n\n//  To add timing info for a function, you just put\n//  KALDI_PROFILE;\n//  at the beginning of the function.  Caution: this doesn't\n//  include the class name.\n#define KALDI_PROFILE Profiler _profiler(__func__)\n\n\n\n}  // namespace kaldi\n\n\n#endif  // KALDI_BASE_TIMER_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/base/version.h",
    "content": "// This file was automatically created by ./get_version.sh.\n// It is only included by ./kaldi-error.cc.\n#define KALDI_VERSION \"5.5.544~2-f21d7\"\n#define KALDI_GIT_HEAD \"f21d7e768635ca98aeeb43f30e2c6a9f14ab8f0f\"\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/CMakeLists.txt",
    "content": "\nadd_library(kaldi-decoder\nlattice-faster-decoder.cc\nlattice-faster-online-decoder.cc\n)\ntarget_link_libraries(kaldi-decoder PUBLIC kaldi-lat)\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/decodable-itf.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// itf/decodable-itf.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University;\n//                      Mirko Hannemann;  Go Vivace Inc.;\n//                2013  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_ITF_DECODABLE_ITF_H_\n#define KALDI_ITF_DECODABLE_ITF_H_ 1\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n/// @ingroup Interfaces\n/// @{\n\n\n/**\n    DecodableInterface provides a link between the (acoustic-modeling and\n    feature-processing) code and the decoder.  The idea is to make this\n    interface as small as possible, and to make it as agnostic as possible about\n    the form of the acoustic model (e.g. don't assume the probabilities are a\n    function of just a vector of floats), and about the decoder (e.g. don't\n    assume it accesses frames in strict left-to-right order).  For normal\n    models, without on-line operation, the \"decodable\" sub-class will just be a\n    wrapper around a matrix of features and an acoustic model, and it will\n    answer the question 'what is the acoustic likelihood for this index and this\n    frame?'.\n\n    For online decoding, where the features are coming in in real time, it is\n    important to understand the IsLastFrame() and NumFramesReady() functions.\n    There are two ways these are used: the old online-decoding code, in\n   ../online/,\n    and the new online-decoding code, in ../online2/.  In the old\n   online-decoding\n    code, the decoder would do:\n    \\code{.cc}\n    for (int frame = 0; !decodable.IsLastFrame(frame); frame++) {\n      // Process this frame\n    }\n    \\endcode\n   and the call to IsLastFrame would block if the features had not arrived yet.\n   The decodable object would have to know when to terminate the decoding.  This\n   online-decoding mode is still supported, it is what happens when you call,\n   for\n   example, LatticeFasterDecoder::Decode().\n\n   We realized that this \"blocking\" mode of decoding is not very convenient\n   because it forces the program to be multi-threaded and makes it complex to\n   control endpointing.  In the \"new\" decoding code, you don't call (for\n   example)\n   LatticeFasterDecoder::Decode(), you call\n   LatticeFasterDecoder::InitDecoding(),\n   and then each time you get more features, you provide them to the decodable\n   object, and you call LatticeFasterDecoder::AdvanceDecoding(), which does\n   something like this:\n   \\code{.cc}\n   while (num_frames_decoded_ < decodable.NumFramesReady()) {\n     // Decode one more frame [increments num_frames_decoded_]\n   }\n   \\endcode\n   So the decodable object never has IsLastFrame() called.  For decoding where\n   you are starting with a matrix of features, the NumFramesReady() function\n   will\n   always just return the number of frames in the file, and IsLastFrame() will\n   return true for the last frame.\n\n   For truly online decoding, the \"old\" online decodable objects in ../online/\n   have a \"blocking\" IsLastFrame() and will crash if you call NumFramesReady().\n   The \"new\" online decodable objects in ../online2/ return the number of frames\n   currently accessible if you call NumFramesReady().  You will likely not need\n   to call IsLastFrame(), but we implement it to only return true for the last\n   frame of the file once we've decided to terminate decoding.\n*/\nclass DecodableInterface {\n  public:\n    virtual ~DecodableInterface() {}\n\n    /// Returns the log likelihood(logprob), which will be negated in the decoder.\n    /// The \"frame\" starts from zero.  You should verify that NumFramesReady() >\n    /// frame\n    /// before calling this.\n    virtual BaseFloat LogLikelihood(int32 frame, int32 index) = 0;\n\n    /// Returns true if this is the last frame.  Frames are zero-based, so the\n    /// first frame is zero.  IsLastFrame(-1) will return false, unless the file\n    /// is empty (which is a case that I'm not sure all the code will handle, so\n    /// be careful).  Caution: the behavior of this function in an online\n    /// setting\n    /// is being changed somewhat.  In future it may return false in cases where\n    /// we haven't yet decided to terminate decoding, but later true if we\n    /// decide\n    /// to terminate decoding.  The plan in future is to rely more on\n    /// NumFramesReady(), and in future, IsLastFrame() would always return false\n    /// in an online-decoding setting, and would only return true in a\n    /// decoding-from-matrix setting where we want to allow the last delta or\n    /// LDA\n    /// features to be flushed out for compatibility with the baseline setup.\n    virtual bool IsLastFrame(int32 frame) = 0;\n\n    /// The call NumFramesReady() will return the number of frames currently\n    /// available\n    /// for this decodable object.  This is for use in setups where you don't\n    /// want the\n    /// decoder to block while waiting for input.  This is newly added as of Jan\n    /// 2014,\n    /// and I hope, going forward, to rely on this mechanism more than\n    /// IsLastFrame to\n    /// know when to stop decoding.\n    virtual int32 NumFramesReady() const {\n        KALDI_ERR\n            << \"NumFramesReady() not implemented for this decodable type.\";\n        return -1;\n    }\n\n    /// Returns the number of states in the acoustic model\n    /// (they will be indexed one-based, i.e. from 1 to NumIndices();\n    /// this is for compatibility with OpenFst).\n    virtual int32 NumIndices() const = 0;\n\n    /// Returns the likelihood(prob), which will be postive in the decoder.\n    /// The \"frame\" starts from zero.  You should verify that NumFramesReady() >\n    /// frame\n    /// before calling this.\n    virtual bool FrameLikelihood(\n        int32 frame, std::vector<kaldi::BaseFloat>* likelihood) = 0;\n};\n/// @}\n}  // namespace Kaldi\n\n#endif  // KALDI_ITF_DECODABLE_ITF_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/lattice-faster-decoder.cc",
    "content": "// decoder/lattice-faster-decoder.cc\n\n// Copyright 2009-2012  Microsoft Corporation  Mirko Hannemann\n//           2013-2018  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n//                2018  Zhehuai Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"decoder/lattice-faster-decoder.h\"\n#include \"lat/lattice-functions.h\"\n\nnamespace kaldi {\n\n// instantiate this class once for each thing you have to decode.\ntemplate <typename FST, typename Token>\nLatticeFasterDecoderTpl<FST, Token>::LatticeFasterDecoderTpl(\n    const FST &fst, const LatticeFasterDecoderConfig &config)\n    : fst_(&fst),\n      delete_fst_(false),\n      config_(config),\n      num_toks_(0),\n      token_pool_(config.memory_pool_tokens_block_size),\n      forward_link_pool_(config.memory_pool_links_block_size) {\n  config.Check();\n  toks_.SetSize(1000);  // just so on the first frame we do something reasonable.\n}\n\ntemplate <typename FST, typename Token>\nLatticeFasterDecoderTpl<FST, Token>::LatticeFasterDecoderTpl(\n    const LatticeFasterDecoderConfig &config, FST *fst)\n    : fst_(fst),\n      delete_fst_(true),\n      config_(config),\n      num_toks_(0),\n      token_pool_(config.memory_pool_tokens_block_size),\n      forward_link_pool_(config.memory_pool_links_block_size) {\n  config.Check();\n  toks_.SetSize(1000);  // just so on the first frame we do something reasonable.\n}\n\ntemplate <typename FST, typename Token>\nLatticeFasterDecoderTpl<FST, Token>::~LatticeFasterDecoderTpl() {\n  DeleteElems(toks_.Clear());\n  ClearActiveTokens();\n  if (delete_fst_) delete fst_;\n}\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::InitDecoding() {\n  // clean up from last time:\n  DeleteElems(toks_.Clear());\n  cost_offsets_.clear();\n  ClearActiveTokens();\n  warned_ = false;\n  num_toks_ = 0;\n  decoding_finalized_ = false;\n  final_costs_.clear();\n  StateId start_state = fst_->Start();\n  KALDI_ASSERT(start_state != fst::kNoStateId);\n  active_toks_.resize(1);\n  Token *start_tok =\n      new (token_pool_.Allocate()) Token(0.0, 0.0, NULL, NULL, NULL);\n  active_toks_[0].toks = start_tok;\n  toks_.Insert(start_state, start_tok);\n  num_toks_++;\n  ProcessNonemitting(config_.beam);\n}\n\n// Returns true if any kind of traceback is available (not necessarily from\n// a final state).  It should only very rarely return false; this indicates\n// an unusual search error.\ntemplate <typename FST, typename Token>\nbool LatticeFasterDecoderTpl<FST, Token>::Decode(DecodableInterface *decodable) {\n  InitDecoding();\n  // We use 1-based indexing for frames in this decoder (if you view it in\n  // terms of features), but note that the decodable object uses zero-based\n  // numbering, which we have to correct for when we call it.\n  AdvanceDecoding(decodable);\n  FinalizeDecoding();\n\n  // Returns true if we have any kind of traceback available (not necessarily\n  // to the end state; query ReachedFinal() for that).\n  return !active_toks_.empty() && active_toks_.back().toks != NULL;\n}\n\n\n// Outputs an FST corresponding to the single best path through the lattice.\ntemplate <typename FST, typename Token>\nbool LatticeFasterDecoderTpl<FST, Token>::GetBestPath(Lattice *olat,\n                                       bool use_final_probs) const {\n  Lattice raw_lat;\n  GetRawLattice(&raw_lat, use_final_probs);\n  ShortestPath(raw_lat, olat);\n  return (olat->NumStates() != 0);\n}\n\n\n// Outputs an FST corresponding to the raw, state-level lattice\ntemplate <typename FST, typename Token>\nbool LatticeFasterDecoderTpl<FST, Token>::GetRawLattice(\n    Lattice *ofst,\n    bool use_final_probs) const {\n  typedef LatticeArc Arc;\n  typedef Arc::StateId StateId;\n  typedef Arc::Weight Weight;\n  typedef Arc::Label Label;\n\n  // Note: you can't use the old interface (Decode()) if you want to\n  // get the lattice with use_final_probs = false.  You'd have to do\n  // InitDecoding() and then AdvanceDecoding().\n  if (decoding_finalized_ && !use_final_probs)\n    KALDI_ERR << \"You cannot call FinalizeDecoding() and then call \"\n              << \"GetRawLattice() with use_final_probs == false\";\n\n  unordered_map<Token*, BaseFloat> final_costs_local;\n\n  const unordered_map<Token*, BaseFloat> &final_costs =\n      (decoding_finalized_ ? final_costs_ : final_costs_local);\n  if (!decoding_finalized_ && use_final_probs)\n    ComputeFinalCosts(&final_costs_local, NULL, NULL);\n\n  ofst->DeleteStates();\n  // num-frames plus one (since frames are one-based, and we have\n  // an extra frame for the start-state).\n  int32 num_frames = active_toks_.size() - 1;\n  KALDI_ASSERT(num_frames > 0);\n  const int32 bucket_count = num_toks_/2 + 3;\n  unordered_map<Token*, StateId> tok_map(bucket_count);\n  // First create all states.\n  std::vector<Token*> token_list;\n  for (int32 f = 0; f <= num_frames; f++) {\n    if (active_toks_[f].toks == NULL) {\n      KALDI_WARN << \"GetRawLattice: no tokens active on frame \" << f\n                 << \": not producing lattice.\\n\";\n      return false;\n    }\n    TopSortTokens(active_toks_[f].toks, &token_list);\n    for (size_t i = 0; i < token_list.size(); i++)\n      if (token_list[i] != NULL)\n        tok_map[token_list[i]] = ofst->AddState();\n  }\n  // The next statement sets the start state of the output FST.  Because we\n  // topologically sorted the tokens, state zero must be the start-state.\n  ofst->SetStart(0);\n\n  KALDI_VLOG(4) << \"init:\" << num_toks_/2 + 3 << \" buckets:\"\n                << tok_map.bucket_count() << \" load:\" << tok_map.load_factor()\n                << \" max:\" << tok_map.max_load_factor();\n  // Now create all arcs.\n  for (int32 f = 0; f <= num_frames; f++) {\n    for (Token *tok = active_toks_[f].toks; tok != NULL; tok = tok->next) {\n      StateId cur_state = tok_map[tok];\n      for (ForwardLinkT *l = tok->links;\n           l != NULL;\n           l = l->next) {\n        typename unordered_map<Token*, StateId>::const_iterator\n            iter = tok_map.find(l->next_tok);\n        StateId nextstate = iter->second;\n        KALDI_ASSERT(iter != tok_map.end());\n        BaseFloat cost_offset = 0.0;\n        if (l->ilabel != 0) {  // emitting..\n          KALDI_ASSERT(f >= 0 && f < cost_offsets_.size());\n          cost_offset = cost_offsets_[f];\n        }\n        Arc arc(l->ilabel, l->olabel,\n                Weight(l->graph_cost, l->acoustic_cost - cost_offset),\n                nextstate);\n        ofst->AddArc(cur_state, arc);\n      }\n      if (f == num_frames) {\n        if (use_final_probs && !final_costs.empty()) {\n          typename unordered_map<Token*, BaseFloat>::const_iterator\n              iter = final_costs.find(tok);\n          if (iter != final_costs.end())\n            ofst->SetFinal(cur_state, LatticeWeight(iter->second, 0));\n        } else {\n          ofst->SetFinal(cur_state, LatticeWeight::One());\n        }\n      }\n    }\n  }\n  return (ofst->NumStates() > 0);\n}\n\n\n// This function is now deprecated, since now we do determinization from outside\n// the LatticeFasterDecoder class.  Outputs an FST corresponding to the\n// lattice-determinized lattice (one path per word sequence).\ntemplate <typename FST, typename Token>\nbool LatticeFasterDecoderTpl<FST, Token>::GetLattice(CompactLattice *ofst,\n                                           bool use_final_probs) const {\n  Lattice raw_fst;\n  GetRawLattice(&raw_fst, use_final_probs);\n  Invert(&raw_fst);  // make it so word labels are on the input.\n  // (in phase where we get backward-costs).\n  fst::ILabelCompare<LatticeArc> ilabel_comp;\n  ArcSort(&raw_fst, ilabel_comp);  // sort on ilabel; makes\n  // lattice-determinization more efficient.\n\n  fst::DeterminizeLatticePrunedOptions lat_opts;\n  lat_opts.max_mem = config_.det_opts.max_mem;\n\n  DeterminizeLatticePruned(raw_fst, config_.lattice_beam, ofst, lat_opts);\n  raw_fst.DeleteStates();  // Free memory-- raw_fst no longer needed.\n  Connect(ofst);  // Remove unreachable states... there might be\n  // a small number of these, in some cases.\n  // Note: if something went wrong and the raw lattice was empty,\n  // we should still get to this point in the code without warnings or failures.\n  return (ofst->NumStates() != 0);\n}\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::PossiblyResizeHash(size_t num_toks) {\n  size_t new_sz = static_cast<size_t>(static_cast<BaseFloat>(num_toks)\n                                      * config_.hash_ratio);\n  if (new_sz > toks_.Size()) {\n    toks_.SetSize(new_sz);\n  }\n}\n\n/*\n  A note on the definition of extra_cost.\n\n  extra_cost is used in pruning tokens, to save memory.\n\n  extra_cost can be thought of as a beta (backward) cost assuming\n  we had set the betas on currently-active tokens to all be the negative\n  of the alphas for those tokens.  (So all currently active tokens would\n  be on (tied) best paths).\n\n  We can use the extra_cost to accurately prune away tokens that we know will\n  never appear in the lattice.  If the extra_cost is greater than the desired\n  lattice beam, the token would provably never appear in the lattice, so we can\n  prune away the token.\n\n  (Note: we don't update all the extra_costs every time we update a frame; we\n  only do it every 'config_.prune_interval' frames).\n */\n\n// FindOrAddToken either locates a token in hash of toks_,\n// or if necessary inserts a new, empty token (i.e. with no forward links)\n// for the current frame.  [note: it's inserted if necessary into hash toks_\n// and also into the singly linked list of tokens active on this frame\n// (whose head is at active_toks_[frame]).\ntemplate <typename FST, typename Token>\ninline typename LatticeFasterDecoderTpl<FST, Token>::Elem*\nLatticeFasterDecoderTpl<FST, Token>::FindOrAddToken(\n      StateId state, int32 frame_plus_one, BaseFloat tot_cost,\n      Token *backpointer, bool *changed) {\n  // Returns the Token pointer.  Sets \"changed\" (if non-NULL) to true\n  // if the token was newly created or the cost changed.\n  KALDI_ASSERT(frame_plus_one < active_toks_.size());\n  Token *&toks = active_toks_[frame_plus_one].toks;\n  Elem *e_found = toks_.Insert(state, NULL);\n  if (e_found->val == NULL) {  // no such token presently.\n    const BaseFloat extra_cost = 0.0;\n    // tokens on the currently final frame have zero extra_cost\n    // as any of them could end up\n    // on the winning path.\n    Token *new_tok = new (token_pool_.Allocate())\n        Token(tot_cost, extra_cost, NULL, toks, backpointer);\n    // NULL: no forward links yet\n    toks = new_tok;\n    num_toks_++;\n    e_found->val = new_tok;\n    if (changed) *changed = true;\n    return e_found;\n  } else {\n    Token *tok = e_found->val;  // There is an existing Token for this state.\n    if (tok->tot_cost > tot_cost) {  // replace old token\n      tok->tot_cost = tot_cost;\n      // SetBackpointer() just does tok->backpointer = backpointer in\n      // the case where Token == BackpointerToken, else nothing.\n      tok->SetBackpointer(backpointer);\n      // we don't allocate a new token, the old stays linked in active_toks_\n      // we only replace the tot_cost\n      // in the current frame, there are no forward links (and no extra_cost)\n      // only in ProcessNonemitting we have to delete forward links\n      // in case we visit a state for the second time\n      // those forward links, that lead to this replaced token before:\n      // they remain and will hopefully be pruned later (PruneForwardLinks...)\n      if (changed) *changed = true;\n    } else {\n      if (changed) *changed = false;\n    }\n    return e_found;\n  }\n}\n\n// prunes outgoing links for all tokens in active_toks_[frame]\n// it's called by PruneActiveTokens\n// all links, that have link_extra_cost > lattice_beam are pruned\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::PruneForwardLinks(\n    int32 frame_plus_one, bool *extra_costs_changed,\n    bool *links_pruned, BaseFloat delta) {\n  // delta is the amount by which the extra_costs must change\n  // If delta is larger,  we'll tend to go back less far\n  //    toward the beginning of the file.\n  // extra_costs_changed is set to true if extra_cost was changed for any token\n  // links_pruned is set to true if any link in any token was pruned\n\n  *extra_costs_changed = false;\n  *links_pruned = false;\n  KALDI_ASSERT(frame_plus_one >= 0 && frame_plus_one < active_toks_.size());\n  if (active_toks_[frame_plus_one].toks == NULL) {  // empty list; should not happen.\n    if (!warned_) {\n      KALDI_WARN << \"No tokens alive [doing pruning].. warning first \"\n          \"time only for each utterance\\n\";\n      warned_ = true;\n    }\n  }\n\n  // We have to iterate until there is no more change, because the links\n  // are not guaranteed to be in topological order.\n  bool changed = true;  // difference new minus old extra cost >= delta ?\n  while (changed) {\n    changed = false;\n    for (Token *tok = active_toks_[frame_plus_one].toks;\n         tok != NULL; tok = tok->next) {\n      ForwardLinkT *link, *prev_link = NULL;\n      // will recompute tok_extra_cost for tok.\n      BaseFloat tok_extra_cost = std::numeric_limits<BaseFloat>::infinity();\n      // tok_extra_cost is the best (min) of link_extra_cost of outgoing links\n      for (link = tok->links; link != NULL; ) {\n        // See if we need to excise this link...\n        Token *next_tok = link->next_tok;\n        BaseFloat link_extra_cost = next_tok->extra_cost +\n            ((tok->tot_cost + link->acoustic_cost + link->graph_cost)\n             - next_tok->tot_cost);  // difference in brackets is >= 0\n        // link_exta_cost is the difference in score between the best paths\n        // through link source state and through link destination state\n        KALDI_ASSERT(link_extra_cost == link_extra_cost);  // check for NaN\n        if (link_extra_cost > config_.lattice_beam) {  // excise link\n          ForwardLinkT *next_link = link->next;\n          if (prev_link != NULL) prev_link->next = next_link;\n          else tok->links = next_link;\n          forward_link_pool_.Free(link);\n          link = next_link;  // advance link but leave prev_link the same.\n          *links_pruned = true;\n        } else {   // keep the link and update the tok_extra_cost if needed.\n          if (link_extra_cost < 0.0) {  // this is just a precaution.\n            if (link_extra_cost < -0.01)\n              KALDI_WARN << \"Negative extra_cost: \" << link_extra_cost;\n            link_extra_cost = 0.0;\n          }\n          if (link_extra_cost < tok_extra_cost)\n            tok_extra_cost = link_extra_cost;\n          prev_link = link;  // move to next link\n          link = link->next;\n        }\n      }  // for all outgoing links\n      if (fabs(tok_extra_cost - tok->extra_cost) > delta)\n        changed = true;   // difference new minus old is bigger than delta\n      tok->extra_cost = tok_extra_cost;\n      // will be +infinity or <= lattice_beam_.\n      // infinity indicates, that no forward link survived pruning\n    }  // for all Token on active_toks_[frame]\n    if (changed) *extra_costs_changed = true;\n\n    // Note: it's theoretically possible that aggressive compiler\n    // optimizations could cause an infinite loop here for small delta and\n    // high-dynamic-range scores.\n  } // while changed\n}\n\n// PruneForwardLinksFinal is a version of PruneForwardLinks that we call\n// on the final frame.  If there are final tokens active, it uses\n// the final-probs for pruning, otherwise it treats all tokens as final.\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::PruneForwardLinksFinal() {\n  KALDI_ASSERT(!active_toks_.empty());\n  int32 frame_plus_one = active_toks_.size() - 1;\n\n  if (active_toks_[frame_plus_one].toks == NULL)  // empty list; should not happen.\n    KALDI_WARN << \"No tokens alive at end of file\";\n\n  typedef typename unordered_map<Token*, BaseFloat>::const_iterator IterType;\n  ComputeFinalCosts(&final_costs_, &final_relative_cost_, &final_best_cost_);\n  decoding_finalized_ = true;\n  // We call DeleteElems() as a nicety, not because it's really necessary;\n  // otherwise there would be a time, after calling PruneTokensForFrame() on the\n  // final frame, when toks_.GetList() or toks_.Clear() would contain pointers\n  // to nonexistent tokens.\n  DeleteElems(toks_.Clear());\n\n  // Now go through tokens on this frame, pruning forward links...  may have to\n  // iterate a few times until there is no more change, because the list is not\n  // in topological order.  This is a modified version of the code in\n  // PruneForwardLinks, but here we also take account of the final-probs.\n  bool changed = true;\n  BaseFloat delta = 1.0e-05;\n  while (changed) {\n    changed = false;\n    for (Token *tok = active_toks_[frame_plus_one].toks;\n         tok != NULL; tok = tok->next) {\n      ForwardLinkT *link, *prev_link = NULL;\n      // will recompute tok_extra_cost.  It has a term in it that corresponds\n      // to the \"final-prob\", so instead of initializing tok_extra_cost to infinity\n      // below we set it to the difference between the (score+final_prob) of this token,\n      // and the best such (score+final_prob).\n      BaseFloat final_cost;\n      if (final_costs_.empty()) {\n        final_cost = 0.0;\n      } else {\n        IterType iter = final_costs_.find(tok);\n        if (iter != final_costs_.end())\n          final_cost = iter->second;\n        else\n          final_cost = std::numeric_limits<BaseFloat>::infinity();\n      }\n      BaseFloat tok_extra_cost = tok->tot_cost + final_cost - final_best_cost_;\n      // tok_extra_cost will be a \"min\" over either directly being final, or\n      // being indirectly final through other links, and the loop below may\n      // decrease its value:\n      for (link = tok->links; link != NULL; ) {\n        // See if we need to excise this link...\n        Token *next_tok = link->next_tok;\n        BaseFloat link_extra_cost = next_tok->extra_cost +\n            ((tok->tot_cost + link->acoustic_cost + link->graph_cost)\n             - next_tok->tot_cost);\n        if (link_extra_cost > config_.lattice_beam) {  // excise link\n          ForwardLinkT *next_link = link->next;\n          if (prev_link != NULL) prev_link->next = next_link;\n          else tok->links = next_link;\n          forward_link_pool_.Free(link);\n          link = next_link; // advance link but leave prev_link the same.\n        } else { // keep the link and update the tok_extra_cost if needed.\n          if (link_extra_cost < 0.0) { // this is just a precaution.\n            if (link_extra_cost < -0.01)\n              KALDI_WARN << \"Negative extra_cost: \" << link_extra_cost;\n            link_extra_cost = 0.0;\n          }\n          if (link_extra_cost < tok_extra_cost)\n            tok_extra_cost = link_extra_cost;\n          prev_link = link;\n          link = link->next;\n        }\n      }\n      // prune away tokens worse than lattice_beam above best path.  This step\n      // was not necessary in the non-final case because then, this case\n      // showed up as having no forward links.  Here, the tok_extra_cost has\n      // an extra component relating to the final-prob.\n      if (tok_extra_cost > config_.lattice_beam)\n        tok_extra_cost = std::numeric_limits<BaseFloat>::infinity();\n      // to be pruned in PruneTokensForFrame\n\n      if (!ApproxEqual(tok->extra_cost, tok_extra_cost, delta))\n        changed = true;\n      tok->extra_cost = tok_extra_cost; // will be +infinity or <= lattice_beam_.\n    }\n  } // while changed\n}\n\ntemplate <typename FST, typename Token>\nBaseFloat LatticeFasterDecoderTpl<FST, Token>::FinalRelativeCost() const {\n  if (!decoding_finalized_) {\n    BaseFloat relative_cost;\n    ComputeFinalCosts(NULL, &relative_cost, NULL);\n    return relative_cost;\n  } else {\n    // we're not allowed to call that function if FinalizeDecoding() has\n    // been called; return a cached value.\n    return final_relative_cost_;\n  }\n}\n\n\n// Prune away any tokens on this frame that have no forward links.\n// [we don't do this in PruneForwardLinks because it would give us\n// a problem with dangling pointers].\n// It's called by PruneActiveTokens if any forward links have been pruned\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::PruneTokensForFrame(int32 frame_plus_one) {\n  KALDI_ASSERT(frame_plus_one >= 0 && frame_plus_one < active_toks_.size());\n  Token *&toks = active_toks_[frame_plus_one].toks;\n  if (toks == NULL)\n    KALDI_WARN << \"No tokens alive [doing pruning]\";\n  Token *tok, *next_tok, *prev_tok = NULL;\n  for (tok = toks; tok != NULL; tok = next_tok) {\n    next_tok = tok->next;\n    if (tok->extra_cost == std::numeric_limits<BaseFloat>::infinity()) {\n      // token is unreachable from end of graph; (no forward links survived)\n      // excise tok from list and delete tok.\n      if (prev_tok != NULL) prev_tok->next = tok->next;\n      else toks = tok->next;\n      token_pool_.Free(tok);\n      num_toks_--;\n    } else {  // fetch next Token\n      prev_tok = tok;\n    }\n  }\n}\n\n// Go backwards through still-alive tokens, pruning them, starting not from\n// the current frame (where we want to keep all tokens) but from the frame before\n// that.  We go backwards through the frames and stop when we reach a point\n// where the delta-costs are not changing (and the delta controls when we consider\n// a cost to have \"not changed\").\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::PruneActiveTokens(BaseFloat delta) {\n  int32 cur_frame_plus_one = NumFramesDecoded();\n  int32 num_toks_begin = num_toks_;\n  // The index \"f\" below represents a \"frame plus one\", i.e. you'd have to subtract\n  // one to get the corresponding index for the decodable object.\n  for (int32 f = cur_frame_plus_one - 1; f >= 0; f--) {\n    // Reason why we need to prune forward links in this situation:\n    // (1) we have never pruned them (new TokenList)\n    // (2) we have not yet pruned the forward links to the next f,\n    // after any of those tokens have changed their extra_cost.\n    if (active_toks_[f].must_prune_forward_links) {\n      bool extra_costs_changed = false, links_pruned = false;\n      PruneForwardLinks(f, &extra_costs_changed, &links_pruned, delta);\n      if (extra_costs_changed && f > 0) // any token has changed extra_cost\n        active_toks_[f-1].must_prune_forward_links = true;\n      if (links_pruned) // any link was pruned\n        active_toks_[f].must_prune_tokens = true;\n      active_toks_[f].must_prune_forward_links = false; // job done\n    }\n    if (f+1 < cur_frame_plus_one &&      // except for last f (no forward links)\n        active_toks_[f+1].must_prune_tokens) {\n      PruneTokensForFrame(f+1);\n      active_toks_[f+1].must_prune_tokens = false;\n    }\n  }\n  KALDI_VLOG(4) << \"PruneActiveTokens: pruned tokens from \" << num_toks_begin\n                << \" to \" << num_toks_;\n}\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::ComputeFinalCosts(\n    unordered_map<Token*, BaseFloat> *final_costs,\n    BaseFloat *final_relative_cost,\n    BaseFloat *final_best_cost) const {\n  KALDI_ASSERT(!decoding_finalized_);\n  if (final_costs != NULL)\n    final_costs->clear();\n  const Elem *final_toks = toks_.GetList();\n  BaseFloat infinity = std::numeric_limits<BaseFloat>::infinity();\n  BaseFloat best_cost = infinity,\n      best_cost_with_final = infinity;\n\n  while (final_toks != NULL) {\n    StateId state = final_toks->key;\n    Token *tok = final_toks->val;\n    const Elem *next = final_toks->tail;\n    BaseFloat final_cost = fst_->Final(state).Value();\n    BaseFloat cost = tok->tot_cost,\n        cost_with_final = cost + final_cost;\n    best_cost = std::min(cost, best_cost);\n    best_cost_with_final = std::min(cost_with_final, best_cost_with_final);\n    if (final_costs != NULL && final_cost != infinity)\n      (*final_costs)[tok] = final_cost;\n    final_toks = next;\n  }\n  if (final_relative_cost != NULL) {\n    if (best_cost == infinity && best_cost_with_final == infinity) {\n      // Likely this will only happen if there are no tokens surviving.\n      // This seems the least bad way to handle it.\n      *final_relative_cost = infinity;\n    } else {\n      *final_relative_cost = best_cost_with_final - best_cost;\n    }\n  }\n  if (final_best_cost != NULL) {\n    if (best_cost_with_final != infinity) { // final-state exists.\n      *final_best_cost = best_cost_with_final;\n    } else { // no final-state exists.\n      *final_best_cost = best_cost;\n    }\n  }\n}\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::AdvanceDecoding(DecodableInterface *decodable,\n                                                int32 max_num_frames) {\n  if (std::is_same<FST, fst::Fst<fst::StdArc> >::value) {\n    // if the type 'FST' is the FST base-class, then see if the FST type of fst_\n    // is actually VectorFst or ConstFst.  If so, call the AdvanceDecoding()\n    // function after casting *this to the more specific type.\n    if (fst_->Type() == \"const\") {\n      LatticeFasterDecoderTpl<fst::ConstFst<fst::StdArc>, Token> *this_cast =\n          reinterpret_cast<LatticeFasterDecoderTpl<fst::ConstFst<fst::StdArc>, Token>* >(this);\n      this_cast->AdvanceDecoding(decodable, max_num_frames);\n      return;\n    } else if (fst_->Type() == \"vector\") {\n      LatticeFasterDecoderTpl<fst::VectorFst<fst::StdArc>, Token> *this_cast =\n          reinterpret_cast<LatticeFasterDecoderTpl<fst::VectorFst<fst::StdArc>, Token>* >(this);\n      this_cast->AdvanceDecoding(decodable, max_num_frames);\n      return;\n    }\n  }\n\n\n  KALDI_ASSERT(!active_toks_.empty() && !decoding_finalized_ &&\n               \"You must call InitDecoding() before AdvanceDecoding\");\n  int32 num_frames_ready = decodable->NumFramesReady();\n  // num_frames_ready must be >= num_frames_decoded, or else\n  // the number of frames ready must have decreased (which doesn't\n  // make sense) or the decodable object changed between calls\n  // (which isn't allowed).\n  KALDI_ASSERT(num_frames_ready >= NumFramesDecoded());\n  int32 target_frames_decoded = num_frames_ready;\n  if (max_num_frames >= 0)\n    target_frames_decoded = std::min(target_frames_decoded,\n                                     NumFramesDecoded() + max_num_frames);\n  while (NumFramesDecoded() < target_frames_decoded) {\n    if (NumFramesDecoded() % config_.prune_interval == 0) {\n      PruneActiveTokens(config_.lattice_beam * config_.prune_scale);\n    }\n    BaseFloat cost_cutoff = ProcessEmitting(decodable);\n    ProcessNonemitting(cost_cutoff);\n  }\n}\n\n// FinalizeDecoding() is a version of PruneActiveTokens that we call\n// (optionally) on the final frame.  Takes into account the final-prob of\n// tokens.  This function used to be called PruneActiveTokensFinal().\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::FinalizeDecoding() {\n  int32 final_frame_plus_one = NumFramesDecoded();\n  int32 num_toks_begin = num_toks_;\n  // PruneForwardLinksFinal() prunes final frame (with final-probs), and\n  // sets decoding_finalized_.\n  PruneForwardLinksFinal();\n  for (int32 f = final_frame_plus_one - 1; f >= 0; f--) {\n    bool b1, b2; // values not used.\n    BaseFloat dontcare = 0.0; // delta of zero means we must always update\n    PruneForwardLinks(f, &b1, &b2, dontcare);\n    PruneTokensForFrame(f + 1);\n  }\n  PruneTokensForFrame(0);\n  KALDI_VLOG(4) << \"pruned tokens from \" << num_toks_begin\n                << \" to \" << num_toks_;\n}\n\n/// Gets the weight cutoff.  Also counts the active tokens.\ntemplate <typename FST, typename Token>\nBaseFloat LatticeFasterDecoderTpl<FST, Token>::GetCutoff(Elem *list_head, size_t *tok_count,\n                                          BaseFloat *adaptive_beam, Elem **best_elem) {\n  BaseFloat best_weight = std::numeric_limits<BaseFloat>::infinity();\n  // positive == high cost == bad.\n  size_t count = 0;\n  if (config_.max_active == std::numeric_limits<int32>::max() &&\n      config_.min_active == 0) {\n    for (Elem *e = list_head; e != NULL; e = e->tail, count++) {\n      BaseFloat w = static_cast<BaseFloat>(e->val->tot_cost);\n      if (w < best_weight) {\n        best_weight = w;\n        if (best_elem) *best_elem = e;\n      }\n    }\n    if (tok_count != NULL) *tok_count = count;\n    if (adaptive_beam != NULL) *adaptive_beam = config_.beam;\n    return best_weight + config_.beam;\n  } else {\n    tmp_array_.clear();\n    for (Elem *e = list_head; e != NULL; e = e->tail, count++) {\n      BaseFloat w = e->val->tot_cost;\n      tmp_array_.push_back(w);\n      if (w < best_weight) {\n        best_weight = w;\n        if (best_elem) *best_elem = e;\n      }\n    }\n    if (tok_count != NULL) *tok_count = count;\n\n    BaseFloat beam_cutoff = best_weight + config_.beam,\n        min_active_cutoff = std::numeric_limits<BaseFloat>::infinity(),\n        max_active_cutoff = std::numeric_limits<BaseFloat>::infinity();\n\n    KALDI_VLOG(6) << \"Number of tokens active on frame \" << NumFramesDecoded()\n                  << \" is \" << tmp_array_.size();\n\n    if (tmp_array_.size() > static_cast<size_t>(config_.max_active)) {\n      std::nth_element(tmp_array_.begin(),\n                       tmp_array_.begin() + config_.max_active,\n                       tmp_array_.end());\n      max_active_cutoff = tmp_array_[config_.max_active];\n    }\n    if (max_active_cutoff < beam_cutoff) { // max_active is tighter than beam.\n      if (adaptive_beam)\n        *adaptive_beam = max_active_cutoff - best_weight + config_.beam_delta;\n      return max_active_cutoff;\n    }\n    if (tmp_array_.size() > static_cast<size_t>(config_.min_active)) {\n      if (config_.min_active == 0) min_active_cutoff = best_weight;\n      else {\n        std::nth_element(tmp_array_.begin(),\n                         tmp_array_.begin() + config_.min_active,\n                         tmp_array_.size() > static_cast<size_t>(config_.max_active) ?\n                         tmp_array_.begin() + config_.max_active :\n                         tmp_array_.end());\n        min_active_cutoff = tmp_array_[config_.min_active];\n      }\n    }\n    if (min_active_cutoff > beam_cutoff) { // min_active is looser than beam.\n      if (adaptive_beam)\n        *adaptive_beam = min_active_cutoff - best_weight + config_.beam_delta;\n      return min_active_cutoff;\n    } else {\n      *adaptive_beam = config_.beam;\n      return beam_cutoff;\n    }\n  }\n}\n\ntemplate <typename FST, typename Token>\nBaseFloat LatticeFasterDecoderTpl<FST, Token>::ProcessEmitting(\n    DecodableInterface *decodable) {\n  KALDI_ASSERT(active_toks_.size() > 0);\n  int32 frame = active_toks_.size() - 1; // frame is the frame-index\n                                         // (zero-based) used to get likelihoods\n                                         // from the decodable object.\n  active_toks_.resize(active_toks_.size() + 1);\n\n  Elem *final_toks = toks_.Clear(); // analogous to swapping prev_toks_ / cur_toks_\n                                   // in simple-decoder.h.   Removes the Elems from\n                                   // being indexed in the hash in toks_.\n  Elem *best_elem = NULL;\n  BaseFloat adaptive_beam;\n  size_t tok_cnt;\n  BaseFloat cur_cutoff = GetCutoff(final_toks, &tok_cnt, &adaptive_beam, &best_elem);\n  KALDI_VLOG(6) << \"Adaptive beam on frame \" << NumFramesDecoded() << \" is \"\n                << adaptive_beam;\n\n  PossiblyResizeHash(tok_cnt);  // This makes sure the hash is always big enough.\n\n  BaseFloat next_cutoff = std::numeric_limits<BaseFloat>::infinity();\n  // pruning \"online\" before having seen all tokens\n\n  BaseFloat cost_offset = 0.0; // Used to keep probabilities in a good\n                               // dynamic range.\n\n\n  // First process the best token to get a hopefully\n  // reasonably tight bound on the next cutoff.  The only\n  // products of the next block are \"next_cutoff\" and \"cost_offset\".\n  if (best_elem) {\n    StateId state = best_elem->key;\n    Token *tok = best_elem->val;\n    cost_offset = - tok->tot_cost;\n    for (fst::ArcIterator<FST> aiter(*fst_, state);\n         !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel != 0) {  // propagate..\n        BaseFloat new_weight = arc.weight.Value() + cost_offset -\n            decodable->LogLikelihood(frame, arc.ilabel) + tok->tot_cost;\n        if (new_weight + adaptive_beam < next_cutoff)\n          next_cutoff = new_weight + adaptive_beam;\n      }\n    }\n  }\n\n  // Store the offset on the acoustic likelihoods that we're applying.\n  // Could just do cost_offsets_.push_back(cost_offset), but we\n  // do it this way as it's more robust to future code changes.\n  cost_offsets_.resize(frame + 1, 0.0);\n  cost_offsets_[frame] = cost_offset;\n\n  // the tokens are now owned here, in final_toks, and the hash is empty.\n  // 'owned' is a complex thing here; the point is we need to call DeleteElem\n  // on each elem 'e' to let toks_ know we're done with them.\n  for (Elem *e = final_toks, *e_tail; e != NULL; e = e_tail) {\n    // loop this way because we delete \"e\" as we go.\n    StateId state = e->key;\n    Token *tok = e->val;\n    if (tok->tot_cost <= cur_cutoff) {\n      for (fst::ArcIterator<FST> aiter(*fst_, state);\n           !aiter.Done();\n           aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        if (arc.ilabel != 0) {  // propagate..\n          BaseFloat ac_cost = cost_offset -\n              decodable->LogLikelihood(frame, arc.ilabel),\n              graph_cost = arc.weight.Value(),\n              cur_cost = tok->tot_cost,\n              tot_cost = cur_cost + ac_cost + graph_cost;\n          if (tot_cost >= next_cutoff) continue;\n          else if (tot_cost + adaptive_beam < next_cutoff)\n            next_cutoff = tot_cost + adaptive_beam; // prune by best current token\n          // Note: the frame indexes into active_toks_ are one-based,\n          // hence the + 1.\n          Elem *e_next = FindOrAddToken(arc.nextstate,\n                                        frame + 1, tot_cost, tok, NULL);\n          // NULL: no change indicator needed\n\n          // Add ForwardLink from tok to next_tok (put on head of list tok->links)\n          tok->links = new (forward_link_pool_.Allocate())\n              ForwardLinkT(e_next->val, arc.ilabel, arc.olabel, graph_cost,\n                           ac_cost, tok->links);\n        }\n      } // for all arcs\n    }\n    e_tail = e->tail;\n    toks_.Delete(e); // delete Elem\n  }\n  return next_cutoff;\n}\n\n// static inline\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::DeleteForwardLinks(Token *tok) {\n  ForwardLinkT *l = tok->links, *m;\n  while (l != NULL) {\n    m = l->next;\n    forward_link_pool_.Free(l);\n    l = m;\n  }\n  tok->links = NULL;\n}\n\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::ProcessNonemitting(BaseFloat cutoff) {\n  KALDI_ASSERT(!active_toks_.empty());\n  int32 frame = static_cast<int32>(active_toks_.size()) - 2;\n  // Note: \"frame\" is the time-index we just processed, or -1 if\n  // we are processing the nonemitting transitions before the\n  // first frame (called from InitDecoding()).\n\n  // Processes nonemitting arcs for one frame.  Propagates within toks_.\n  // Note-- this queue structure is not very optimal as\n  // it may cause us to process states unnecessarily (e.g. more than once),\n  // but in the baseline code, turning this vector into a set to fix this\n  // problem did not improve overall speed.\n\n  KALDI_ASSERT(queue_.empty());\n\n  if (toks_.GetList() == NULL) {\n    if (!warned_) {\n      KALDI_WARN << \"Error, no surviving tokens: frame is \" << frame;\n      warned_ = true;\n    }\n  }\n\n  for (const Elem *e = toks_.GetList(); e != NULL;  e = e->tail) {\n    StateId state = e->key;\n    if (fst_->NumInputEpsilons(state) != 0)\n      queue_.push_back(e);\n  }\n\n  while (!queue_.empty()) {\n    const Elem *e = queue_.back();\n    queue_.pop_back();\n\n    StateId state = e->key;\n    Token *tok = e->val;  // would segfault if e is a NULL pointer but this can't happen.\n    BaseFloat cur_cost = tok->tot_cost;\n    if (cur_cost >= cutoff) // Don't bother processing successors.\n      continue;\n    // If \"tok\" has any existing forward links, delete them,\n    // because we're about to regenerate them.  This is a kind\n    // of non-optimality (remember, this is the simple decoder),\n    // but since most states are emitting it's not a huge issue.\n    DeleteForwardLinks(tok); // necessary when re-visiting\n    tok->links = NULL;\n    for (fst::ArcIterator<FST> aiter(*fst_, state);\n         !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel == 0) {  // propagate nonemitting only...\n        BaseFloat graph_cost = arc.weight.Value(),\n            tot_cost = cur_cost + graph_cost;\n        if (tot_cost < cutoff) {\n          bool changed;\n\n          Elem *e_new = FindOrAddToken(arc.nextstate, frame + 1, tot_cost,\n                                          tok, &changed);\n\n          tok->links = new (forward_link_pool_.Allocate()) ForwardLinkT(\n              e_new->val, 0, arc.olabel, graph_cost, 0, tok->links);\n\n          // \"changed\" tells us whether the new token has a different\n          // cost from before, or is new [if so, add into queue].\n          if (changed && fst_->NumInputEpsilons(arc.nextstate) != 0)\n            queue_.push_back(e_new);\n        }\n      }\n    } // for all arcs\n  } // while queue not empty\n}\n\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::DeleteElems(Elem *list) {\n  for (Elem *e = list, *e_tail; e != NULL; e = e_tail) {\n    e_tail = e->tail;\n    toks_.Delete(e);\n  }\n}\n\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::ClearActiveTokens() { // a cleanup routine, at utt end/begin\n  for (size_t i = 0; i < active_toks_.size(); i++) {\n    // Delete all tokens alive on this frame, and any forward\n    // links they may have.\n    for (Token *tok = active_toks_[i].toks; tok != NULL; ) {\n      DeleteForwardLinks(tok);\n      Token *next_tok = tok->next;\n      token_pool_.Free(tok);\n      num_toks_--;\n      tok = next_tok;\n    }\n  }\n  active_toks_.clear();\n  KALDI_ASSERT(num_toks_ == 0);\n}\n\n// static\ntemplate <typename FST, typename Token>\nvoid LatticeFasterDecoderTpl<FST, Token>::TopSortTokens(\n    Token *tok_list, std::vector<Token*> *topsorted_list) {\n  unordered_map<Token*, int32> token2pos;\n  typedef typename unordered_map<Token*, int32>::iterator IterType;\n  int32 num_toks = 0;\n  for (Token *tok = tok_list; tok != NULL; tok = tok->next)\n    num_toks++;\n  int32 cur_pos = 0;\n  // We assign the tokens numbers num_toks - 1, ... , 2, 1, 0.\n  // This is likely to be in closer to topological order than\n  // if we had given them ascending order, because of the way\n  // new tokens are put at the front of the list.\n  for (Token *tok = tok_list; tok != NULL; tok = tok->next)\n    token2pos[tok] = num_toks - ++cur_pos;\n\n  unordered_set<Token*> reprocess;\n\n  for (IterType iter = token2pos.begin(); iter != token2pos.end(); ++iter) {\n    Token *tok = iter->first;\n    int32 pos = iter->second;\n    for (ForwardLinkT *link = tok->links; link != NULL; link = link->next) {\n      if (link->ilabel == 0) {\n        // We only need to consider epsilon links, since non-epsilon links\n        // transition between frames and this function only needs to sort a list\n        // of tokens from a single frame.\n        IterType following_iter = token2pos.find(link->next_tok);\n        if (following_iter != token2pos.end()) { // another token on this frame,\n                                                 // so must consider it.\n          int32 next_pos = following_iter->second;\n          if (next_pos < pos) { // reassign the position of the next Token.\n            following_iter->second = cur_pos++;\n            reprocess.insert(link->next_tok);\n          }\n        }\n      }\n    }\n    // In case we had previously assigned this token to be reprocessed, we can\n    // erase it from that set because it's \"happy now\" (we just processed it).\n    reprocess.erase(tok);\n  }\n\n  size_t max_loop = 1000000, loop_count; // max_loop is to detect epsilon cycles.\n  for (loop_count = 0;\n       !reprocess.empty() && loop_count < max_loop; ++loop_count) {\n    std::vector<Token*> reprocess_vec;\n    for (typename unordered_set<Token*>::iterator iter = reprocess.begin();\n         iter != reprocess.end(); ++iter)\n      reprocess_vec.push_back(*iter);\n    reprocess.clear();\n    for (typename std::vector<Token*>::iterator iter = reprocess_vec.begin();\n         iter != reprocess_vec.end(); ++iter) {\n      Token *tok = *iter;\n      int32 pos = token2pos[tok];\n      // Repeat the processing we did above (for comments, see above).\n      for (ForwardLinkT *link = tok->links; link != NULL; link = link->next) {\n        if (link->ilabel == 0) {\n          IterType following_iter = token2pos.find(link->next_tok);\n          if (following_iter != token2pos.end()) {\n            int32 next_pos = following_iter->second;\n            if (next_pos < pos) {\n              following_iter->second = cur_pos++;\n              reprocess.insert(link->next_tok);\n            }\n          }\n        }\n      }\n    }\n  }\n  KALDI_ASSERT(loop_count < max_loop && \"Epsilon loops exist in your decoding \"\n               \"graph (this is not allowed!)\");\n\n  topsorted_list->clear();\n  topsorted_list->resize(cur_pos, NULL);  // create a list with NULLs in between.\n  for (IterType iter = token2pos.begin(); iter != token2pos.end(); ++iter)\n    (*topsorted_list)[iter->second] = iter->first;\n}\n\n// Instantiate the template for the combination of token types and FST types\n// that we'll need.\ntemplate class LatticeFasterDecoderTpl<fst::Fst<fst::StdArc>, decoder::StdToken>;\ntemplate class LatticeFasterDecoderTpl<fst::VectorFst<fst::StdArc>, decoder::StdToken >;\ntemplate class LatticeFasterDecoderTpl<fst::ConstFst<fst::StdArc>, decoder::StdToken >;\n\n\ntemplate class LatticeFasterDecoderTpl<fst::Fst<fst::StdArc> , decoder::BackpointerToken>;\ntemplate class LatticeFasterDecoderTpl<fst::VectorFst<fst::StdArc>, decoder::BackpointerToken >;\ntemplate class LatticeFasterDecoderTpl<fst::ConstFst<fst::StdArc>, decoder::BackpointerToken >;\n\n\n} // end namespace kaldi.\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/lattice-faster-decoder.h",
    "content": "// decoder/lattice-faster-decoder.h\n\n// Copyright 2009-2013  Microsoft Corporation;  Mirko Hannemann;\n//           2013-2014  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n//                2018  Zhehuai Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_DECODER_LATTICE_FASTER_DECODER_H_\n#define KALDI_DECODER_LATTICE_FASTER_DECODER_H_\n\n#include \"fst/fstlib.h\"\n#include \"fst/memory.h\"\n#include \"fstext/fstext-lib.h\"\n#include \"decoder/decodable-itf.h\"\n#include \"lat/determinize-lattice-pruned.h\"\n#include \"lat/kaldi-lattice.h\"\n#include \"util/hash-list.h\"\n#include \"util/stl-utils.h\"\n\nnamespace kaldi {\n\nstruct LatticeFasterDecoderConfig {\n  BaseFloat beam;\n  int32 max_active;\n  int32 min_active;\n  BaseFloat lattice_beam;\n  int32 prune_interval;\n  bool determinize_lattice; // not inspected by this class... used in\n                            // command-line program.\n  BaseFloat beam_delta;\n  BaseFloat hash_ratio;\n  // Note: we don't make prune_scale configurable on the command line, it's not\n  // a very important parameter.  It affects the algorithm that prunes the\n  // tokens as we go.\n  BaseFloat prune_scale;\n\n  // Number of elements in the block for Token and ForwardLink memory\n  // pool allocation.\n  int32 memory_pool_tokens_block_size;\n  int32 memory_pool_links_block_size;\n\n  // Most of the options inside det_opts are not actually queried by the\n  // LatticeFasterDecoder class itself, but by the code that calls it, for\n  // example in the function DecodeUtteranceLatticeFaster.\n  fst::DeterminizeLatticePhonePrunedOptions det_opts;\n\n  LatticeFasterDecoderConfig()\n      : beam(16.0),\n        max_active(std::numeric_limits<int32>::max()),\n        min_active(200),\n        lattice_beam(10.0),\n        prune_interval(25),\n        determinize_lattice(true),\n        beam_delta(0.5),\n        hash_ratio(2.0),\n        prune_scale(0.1),\n        memory_pool_tokens_block_size(1 << 8),\n        memory_pool_links_block_size(1 << 8) {}\n  void Register(OptionsItf *opts) {\n    det_opts.Register(opts);\n    opts->Register(\"beam\", &beam, \"Decoding beam.  Larger->slower, more accurate.\");\n    opts->Register(\"max-active\", &max_active, \"Decoder max active states.  Larger->slower; \"\n                   \"more accurate\");\n    opts->Register(\"min-active\", &min_active, \"Decoder minimum #active states.\");\n    opts->Register(\"lattice-beam\", &lattice_beam, \"Lattice generation beam.  Larger->slower, \"\n                   \"and deeper lattices\");\n    opts->Register(\"prune-interval\", &prune_interval, \"Interval (in frames) at \"\n                   \"which to prune tokens\");\n    opts->Register(\"determinize-lattice\", &determinize_lattice, \"If true, \"\n                   \"determinize the lattice (lattice-determinization, keeping only \"\n                   \"best pdf-sequence for each word-sequence).\");\n    opts->Register(\"beam-delta\", &beam_delta, \"Increment used in decoding-- this \"\n                   \"parameter is obscure and relates to a speedup in the way the \"\n                   \"max-active constraint is applied.  Larger is more accurate.\");\n    opts->Register(\"hash-ratio\", &hash_ratio, \"Setting used in decoder to \"\n                   \"control hash behavior\");\n    opts->Register(\"memory-pool-tokens-block-size\", &memory_pool_tokens_block_size,\n                   \"Memory pool block size suggestion for storing tokens (in elements). \"\n                   \"Smaller uses less memory but increases cache misses.\");\n    opts->Register(\"memory-pool-links-block-size\", &memory_pool_links_block_size,\n                   \"Memory pool block size suggestion for storing links (in elements). \"\n                   \"Smaller uses less memory but increases cache misses.\");\n  }\n  void Check() const {\n    KALDI_ASSERT(beam > 0.0 && max_active > 1 && lattice_beam > 0.0\n                 && min_active <= max_active\n                 && prune_interval > 0 && beam_delta > 0.0 && hash_ratio >= 1.0\n                 && prune_scale > 0.0 && prune_scale < 1.0);\n  }\n};\n\nnamespace decoder {\n// We will template the decoder on the token type as well as the FST type; this\n// is a mechanism so that we can use the same underlying decoder code for\n// versions of the decoder that support quickly getting the best path\n// (LatticeFasterOnlineDecoder, see lattice-faster-online-decoder.h) and also\n// those that do not (LatticeFasterDecoder).\n\n\n// ForwardLinks are the links from a token to a token on the next frame.\n// or sometimes on the current frame (for input-epsilon links).\ntemplate <typename Token>\nstruct ForwardLink {\n  using Label = fst::StdArc::Label;\n\n  Token *next_tok;  // the next token [or NULL if represents final-state]\n  Label ilabel;  // ilabel on arc\n  Label olabel;  // olabel on arc\n  BaseFloat graph_cost;  // graph cost of traversing arc (contains LM, etc.)\n  BaseFloat acoustic_cost;  // acoustic cost (pre-scaled) of traversing arc\n  ForwardLink *next;  // next in singly-linked list of forward arcs (arcs\n                      // in the state-level lattice) from a token.\n  inline ForwardLink(Token *next_tok, Label ilabel, Label olabel,\n                     BaseFloat graph_cost, BaseFloat acoustic_cost,\n                     ForwardLink *next):\n      next_tok(next_tok), ilabel(ilabel), olabel(olabel),\n      graph_cost(graph_cost), acoustic_cost(acoustic_cost),\n      next(next) { }\n};\n\n\nstruct StdToken {\n  using ForwardLinkT = ForwardLink<StdToken>;\n  using Token = StdToken;\n\n  // Standard token type for LatticeFasterDecoder.  Each active HCLG\n  // (decoding-graph) state on each frame has one token.\n\n  // tot_cost is the total (LM + acoustic) cost from the beginning of the\n  // utterance up to this point.  (but see cost_offset_, which is subtracted\n  // to keep it in a good numerical range).\n  BaseFloat tot_cost;\n\n  // exta_cost is >= 0.  After calling PruneForwardLinks, this equals the\n  // minimum difference between the cost of the best path that this link is a\n  // part of, and the cost of the absolute best path, under the assumption that\n  // any of the currently active states at the decoding front may eventually\n  // succeed (e.g. if you were to take the currently active states one by one\n  // and compute this difference, and then take the minimum).\n  BaseFloat extra_cost;\n\n  // 'links' is the head of singly-linked list of ForwardLinks, which is what we\n  // use for lattice generation.\n  ForwardLinkT *links;\n\n  //'next' is the next in the singly-linked list of tokens for this frame.\n  Token *next;\n\n  // This function does nothing and should be optimized out; it's needed\n  // so we can share the regular LatticeFasterDecoderTpl code and the code\n  // for LatticeFasterOnlineDecoder that supports fast traceback.\n  inline void SetBackpointer (Token *backpointer) { }\n\n  // This constructor just ignores the 'backpointer' argument.  That argument is\n  // needed so that we can use the same decoder code for LatticeFasterDecoderTpl\n  // and LatticeFasterOnlineDecoderTpl (which needs backpointers to support a\n  // fast way to obtain the best path).\n  inline StdToken(BaseFloat tot_cost, BaseFloat extra_cost, ForwardLinkT *links,\n                  Token *next, Token *backpointer):\n      tot_cost(tot_cost), extra_cost(extra_cost), links(links), next(next) { }\n};\n\nstruct BackpointerToken {\n  using ForwardLinkT = ForwardLink<BackpointerToken>;\n  using Token = BackpointerToken;\n\n  // BackpointerToken is like Token but also\n  // Standard token type for LatticeFasterDecoder.  Each active HCLG\n  // (decoding-graph) state on each frame has one token.\n\n  // tot_cost is the total (LM + acoustic) cost from the beginning of the\n  // utterance up to this point.  (but see cost_offset_, which is subtracted\n  // to keep it in a good numerical range).\n  BaseFloat tot_cost;\n\n  // exta_cost is >= 0.  After calling PruneForwardLinks, this equals\n  // the minimum difference between the cost of the best path, and the cost of\n  // this is on, and the cost of the absolute best path, under the assumption\n  // that any of the currently active states at the decoding front may\n  // eventually succeed (e.g. if you were to take the currently active states\n  // one by one and compute this difference, and then take the minimum).\n  BaseFloat extra_cost;\n\n  // 'links' is the head of singly-linked list of ForwardLinks, which is what we\n  // use for lattice generation.\n  ForwardLinkT *links;\n\n  //'next' is the next in the singly-linked list of tokens for this frame.\n  BackpointerToken *next;\n\n  // Best preceding BackpointerToken (could be a on this frame, connected to\n  // this via an epsilon transition, or on a previous frame).  This is only\n  // required for an efficient GetBestPath function in\n  // LatticeFasterOnlineDecoderTpl; it plays no part in the lattice generation\n  // (the \"links\" list is what stores the forward links, for that).\n  Token *backpointer;\n\n  inline void SetBackpointer (Token *backpointer) {\n    this->backpointer = backpointer;\n  }\n\n  inline BackpointerToken(BaseFloat tot_cost, BaseFloat extra_cost, ForwardLinkT *links,\n                          Token *next, Token *backpointer):\n      tot_cost(tot_cost), extra_cost(extra_cost), links(links), next(next),\n      backpointer(backpointer) { }\n};\n\n}  // namespace decoder\n\n\n/** This is the \"normal\" lattice-generating decoder.\n    See \\ref lattices_generation \\ref decoders_faster and \\ref decoders_simple\n     for more information.\n\n   The decoder is templated on the FST type and the token type.  The token type\n   will normally be StdToken, but also may be BackpointerToken which is to support\n   quick lookup of the current best path (see lattice-faster-online-decoder.h)\n\n   The FST you invoke this decoder which is expected to equal\n   Fst::Fst<fst::StdArc>, a.k.a. StdFst, or GrammarFst.  If you invoke it with\n   FST == StdFst and it notices that the actual FST type is\n   fst::VectorFst<fst::StdArc> or fst::ConstFst<fst::StdArc>, the decoder object\n   will internally cast itself to one that is templated on those more specific\n   types; this is an optimization for speed.\n */\ntemplate <typename FST, typename Token = decoder::StdToken>\nclass LatticeFasterDecoderTpl {\n public:\n  using Arc = typename FST::Arc;\n  using Label = typename Arc::Label;\n  using StateId = typename Arc::StateId;\n  using Weight = typename Arc::Weight;\n  using ForwardLinkT = decoder::ForwardLink<Token>;\n\n  // Instantiate this class once for each thing you have to decode.\n  // This version of the constructor does not take ownership of\n  // 'fst'.\n  LatticeFasterDecoderTpl(const FST &fst,\n                          const LatticeFasterDecoderConfig &config);\n\n  // This version of the constructor takes ownership of the fst, and will delete\n  // it when this object is destroyed.\n  LatticeFasterDecoderTpl(const LatticeFasterDecoderConfig &config,\n                          FST *fst);\n\n  void SetOptions(const LatticeFasterDecoderConfig &config) {\n    config_ = config;\n  }\n\n  const LatticeFasterDecoderConfig &GetOptions() const {\n    return config_;\n  }\n\n  ~LatticeFasterDecoderTpl();\n\n  /// Decodes until there are no more frames left in the \"decodable\" object..\n  /// note, this may block waiting for input if the \"decodable\" object blocks.\n  /// Returns true if any kind of traceback is available (not necessarily from a\n  /// final state).\n  bool Decode(DecodableInterface *decodable);\n\n\n  /// says whether a final-state was active on the last frame.  If it was not, the\n  /// lattice (or traceback) will end with states that are not final-states.\n  bool ReachedFinal() const {\n    return FinalRelativeCost() != std::numeric_limits<BaseFloat>::infinity();\n  }\n\n  /// Outputs an FST corresponding to the single best path through the lattice.\n  /// Returns true if result is nonempty (using the return status is deprecated,\n  /// it will become void).  If \"use_final_probs\" is true AND we reached the\n  /// final-state of the graph then it will include those as final-probs, else\n  /// it will treat all final-probs as one.  Note: this just calls GetRawLattice()\n  /// and figures out the shortest path.\n  bool GetBestPath(Lattice *ofst,\n                   bool use_final_probs = true) const;\n\n  /// Outputs an FST corresponding to the raw, state-level\n  /// tracebacks.  Returns true if result is nonempty.\n  /// If \"use_final_probs\" is true AND we reached the final-state\n  /// of the graph then it will include those as final-probs, else\n  /// it will treat all final-probs as one.\n  /// The raw lattice will be topologically sorted.\n  ///\n  /// See also GetRawLatticePruned in lattice-faster-online-decoder.h,\n  /// which also supports a pruning beam, in case for some reason\n  /// you want it pruned tighter than the regular lattice beam.\n  /// We could put that here in future needed.\n  bool GetRawLattice(Lattice *ofst, bool use_final_probs = true) const;\n\n\n\n  /// [Deprecated, users should now use GetRawLattice and determinize it\n  /// themselves, e.g. using DeterminizeLatticePhonePrunedWrapper].\n  /// Outputs an FST corresponding to the lattice-determinized\n  /// lattice (one path per word sequence).   Returns true if result is nonempty.\n  /// If \"use_final_probs\" is true AND we reached the final-state of the graph\n  /// then it will include those as final-probs, else it will treat all\n  /// final-probs as one.\n  bool GetLattice(CompactLattice *ofst,\n                  bool use_final_probs = true) const;\n\n  /// InitDecoding initializes the decoding, and should only be used if you\n  /// intend to call AdvanceDecoding().  If you call Decode(), you don't need to\n  /// call this.  You can also call InitDecoding if you have already decoded an\n  /// utterance and want to start with a new utterance.\n  void InitDecoding();\n\n  /// This will decode until there are no more frames ready in the decodable\n  /// object.  You can keep calling it each time more frames become available.\n  /// If max_num_frames is specified, it specifies the maximum number of frames\n  /// the function will decode before returning.\n  void AdvanceDecoding(DecodableInterface *decodable,\n                       int32 max_num_frames = -1);\n\n  /// This function may be optionally called after AdvanceDecoding(), when you\n  /// do not plan to decode any further.  It does an extra pruning step that\n  /// will help to prune the lattices output by GetLattice and (particularly)\n  /// GetRawLattice more completely, particularly toward the end of the\n  /// utterance.  If you call this, you cannot call AdvanceDecoding again (it\n  /// will fail), and you cannot call GetLattice() and related functions with\n  /// use_final_probs = false.  Used to be called PruneActiveTokensFinal().\n  void FinalizeDecoding();\n\n  /// FinalRelativeCost() serves the same purpose as ReachedFinal(), but gives\n  /// more information.  It returns the difference between the best (final-cost\n  /// plus cost) of any token on the final frame, and the best cost of any token\n  /// on the final frame.  If it is infinity it means no final-states were\n  /// present on the final frame.  It will usually be nonnegative.  If it not\n  /// too positive (e.g. < 5 is my first guess, but this is not tested) you can\n  /// take it as a good indication that we reached the final-state with\n  /// reasonable likelihood.\n  BaseFloat FinalRelativeCost() const;\n\n\n  // Returns the number of frames decoded so far.  The value returned changes\n  // whenever we call ProcessEmitting().\n  inline int32 NumFramesDecoded() const { return active_toks_.size() - 1; }\n\n protected:\n  // we make things protected instead of private, as code in\n  // LatticeFasterOnlineDecoderTpl, which inherits from this, also uses the\n  // internals.\n\n  // Deletes the elements of the singly linked list tok->links.\n  void DeleteForwardLinks(Token *tok);\n\n  // head of per-frame list of Tokens (list is in topological order),\n  // and something saying whether we ever pruned it using PruneForwardLinks.\n  struct TokenList {\n    Token *toks;\n    bool must_prune_forward_links;\n    bool must_prune_tokens;\n    TokenList(): toks(NULL), must_prune_forward_links(true),\n                 must_prune_tokens(true) { }\n  };\n\n  using Elem = typename HashList<StateId, Token*>::Elem;\n  // Equivalent to:\n  //  struct Elem {\n  //    StateId key;\n  //    Token *val;\n  //    Elem *tail;\n  //  };\n\n  void PossiblyResizeHash(size_t num_toks);\n\n  // FindOrAddToken either locates a token in hash of toks_, or if necessary\n  // inserts a new, empty token (i.e. with no forward links) for the current\n  // frame.  [note: it's inserted if necessary into hash toks_ and also into the\n  // singly linked list of tokens active on this frame (whose head is at\n  // active_toks_[frame]).  The frame_plus_one argument is the acoustic frame\n  // index plus one, which is used to index into the active_toks_ array.\n  // Returns the Token pointer.  Sets \"changed\" (if non-NULL) to true if the\n  // token was newly created or the cost changed.\n  // If Token == StdToken, the 'backpointer' argument has no purpose (and will\n  // hopefully be optimized out).\n  inline Elem *FindOrAddToken(StateId state, int32 frame_plus_one,\n                              BaseFloat tot_cost, Token *backpointer,\n                              bool *changed);\n\n  // prunes outgoing links for all tokens in active_toks_[frame]\n  // it's called by PruneActiveTokens\n  // all links, that have link_extra_cost > lattice_beam are pruned\n  // delta is the amount by which the extra_costs must change\n  // before we set *extra_costs_changed = true.\n  // If delta is larger,  we'll tend to go back less far\n  //    toward the beginning of the file.\n  // extra_costs_changed is set to true if extra_cost was changed for any token\n  // links_pruned is set to true if any link in any token was pruned\n  void PruneForwardLinks(int32 frame_plus_one, bool *extra_costs_changed,\n                         bool *links_pruned,\n                         BaseFloat delta);\n\n  // This function computes the final-costs for tokens active on the final\n  // frame.  It outputs to final-costs, if non-NULL, a map from the Token*\n  // pointer to the final-prob of the corresponding state, for all Tokens\n  // that correspond to states that have final-probs.  This map will be\n  // empty if there were no final-probs.  It outputs to\n  // final_relative_cost, if non-NULL, the difference between the best\n  // forward-cost including the final-prob cost, and the best forward-cost\n  // without including the final-prob cost (this will usually be positive), or\n  // infinity if there were no final-probs.  [c.f. FinalRelativeCost(), which\n  // outputs this quanitity].  It outputs to final_best_cost, if\n  // non-NULL, the lowest for any token t active on the final frame, of\n  // forward-cost[t] + final-cost[t], where final-cost[t] is the final-cost in\n  // the graph of the state corresponding to token t, or the best of\n  // forward-cost[t] if there were no final-probs active on the final frame.\n  // You cannot call this after FinalizeDecoding() has been called; in that\n  // case you should get the answer from class-member variables.\n  void ComputeFinalCosts(unordered_map<Token*, BaseFloat> *final_costs,\n                         BaseFloat *final_relative_cost,\n                         BaseFloat *final_best_cost) const;\n\n  // PruneForwardLinksFinal is a version of PruneForwardLinks that we call\n  // on the final frame.  If there are final tokens active, it uses\n  // the final-probs for pruning, otherwise it treats all tokens as final.\n  void PruneForwardLinksFinal();\n\n  // Prune away any tokens on this frame that have no forward links.\n  // [we don't do this in PruneForwardLinks because it would give us\n  // a problem with dangling pointers].\n  // It's called by PruneActiveTokens if any forward links have been pruned\n  void PruneTokensForFrame(int32 frame_plus_one);\n\n\n  // Go backwards through still-alive tokens, pruning them if the\n  // forward+backward cost is more than lat_beam away from the best path.  It's\n  // possible to prove that this is \"correct\" in the sense that we won't lose\n  // anything outside of lat_beam, regardless of what happens in the future.\n  // delta controls when it considers a cost to have changed enough to continue\n  // going backward and propagating the change.  larger delta -> will recurse\n  // less far.\n  void PruneActiveTokens(BaseFloat delta);\n\n  /// Gets the weight cutoff.  Also counts the active tokens.\n  BaseFloat GetCutoff(Elem *list_head, size_t *tok_count,\n                      BaseFloat *adaptive_beam, Elem **best_elem);\n\n  /// Processes emitting arcs for one frame.  Propagates from prev_toks_ to\n  /// cur_toks_.  Returns the cost cutoff for subsequent ProcessNonemitting() to\n  /// use.\n  BaseFloat ProcessEmitting(DecodableInterface *decodable);\n\n  /// Processes nonemitting (epsilon) arcs for one frame.  Called after\n  /// ProcessEmitting() on each frame.  The cost cutoff is computed by the\n  /// preceding ProcessEmitting().\n  void ProcessNonemitting(BaseFloat cost_cutoff);\n\n  // HashList defined in ../util/hash-list.h.  It actually allows us to maintain\n  // more than one list (e.g. for current and previous frames), but only one of\n  // them at a time can be indexed by StateId.  It is indexed by frame-index\n  // plus one, where the frame-index is zero-based, as used in decodable object.\n  // That is, the emitting probs of frame t are accounted for in tokens at\n  // toks_[t+1].  The zeroth frame is for nonemitting transition at the start of\n  // the graph.\n  HashList<StateId, Token*> toks_;\n\n  std::vector<TokenList> active_toks_; // Lists of tokens, indexed by\n  // frame (members of TokenList are toks, must_prune_forward_links,\n  // must_prune_tokens).\n  std::vector<const Elem* > queue_;  // temp variable used in ProcessNonemitting,\n  std::vector<BaseFloat> tmp_array_;  // used in GetCutoff.\n\n  // fst_ is a pointer to the FST we are decoding from.\n  const FST *fst_;\n  // delete_fst_ is true if the pointer fst_ needs to be deleted when this\n  // object is destroyed.\n  bool delete_fst_;\n\n  std::vector<BaseFloat> cost_offsets_; // This contains, for each\n  // frame, an offset that was added to the acoustic log-likelihoods on that\n  // frame in order to keep everything in a nice dynamic range i.e.  close to\n  // zero, to reduce roundoff errors.\n  LatticeFasterDecoderConfig config_;\n  int32 num_toks_; // current total #toks allocated...\n  bool warned_;\n\n  /// decoding_finalized_ is true if someone called FinalizeDecoding().  [note,\n  /// calling this is optional].  If true, it's forbidden to decode more.  Also,\n  /// if this is set, then the output of ComputeFinalCosts() is in the next\n  /// three variables.  The reason we need to do this is that after\n  /// FinalizeDecoding() calls PruneTokensForFrame() for the final frame, some\n  /// of the tokens on the last frame are freed, so we free the list from toks_\n  /// to avoid having dangling pointers hanging around.\n  bool decoding_finalized_;\n  /// For the meaning of the next 3 variables, see the comment for\n  /// decoding_finalized_ above., and ComputeFinalCosts().\n  unordered_map<Token*, BaseFloat> final_costs_;\n  BaseFloat final_relative_cost_;\n  BaseFloat final_best_cost_;\n\n  // Memory pools for storing tokens and forward links.\n  // We use it to decrease the work put on allocator and to move some of data\n  // together. Too small block sizes will result in more work to allocator but\n  // bigger ones increase the memory usage.\n  fst::MemoryPool<Token> token_pool_;\n  fst::MemoryPool<ForwardLinkT> forward_link_pool_;\n\n  // There are various cleanup tasks... the toks_ structure contains\n  // singly linked lists of Token pointers, where Elem is the list type.\n  // It also indexes them in a hash, indexed by state (this hash is only\n  // maintained for the most recent frame).  toks_.Clear()\n  // deletes them from the hash and returns the list of Elems.  The\n  // function DeleteElems calls toks_.Delete(elem) for each elem in\n  // the list, which returns ownership of the Elem to the toks_ structure\n  // for reuse, but does not delete the Token pointer.  The Token pointers\n  // are reference-counted and are ultimately deleted in PruneTokensForFrame,\n  // but are also linked together on each frame by their own linked-list,\n  // using the \"next\" pointer.  We delete them manually.\n  void DeleteElems(Elem *list);\n\n  // This function takes a singly linked list of tokens for a single frame, and\n  // outputs a list of them in topological order (it will crash if no such order\n  // can be found, which will typically be due to decoding graphs with epsilon\n  // cycles, which are not allowed).  Note: the output list may contain NULLs,\n  // which the caller should pass over; it just happens to be more efficient for\n  // the algorithm to output a list that contains NULLs.\n  static void TopSortTokens(Token *tok_list,\n                            std::vector<Token*> *topsorted_list);\n\n  void ClearActiveTokens();\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(LatticeFasterDecoderTpl);\n};\n\ntypedef LatticeFasterDecoderTpl<fst::StdFst, decoder::StdToken> LatticeFasterDecoder;\n\n\n\n} // end namespace kaldi.\n\n#endif\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/lattice-faster-online-decoder.cc",
    "content": "// decoder/lattice-faster-online-decoder.cc\n\n// Copyright 2009-2012  Microsoft Corporation  Mirko Hannemann\n//           2013-2014  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n//                2014  IMSL, PKU-HKUST (author: Wei Shi)\n//                2018  Zhehuai Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n// see note at the top of lattice-faster-decoder.cc, about how to maintain this\n// file in sync with lattice-faster-decoder.cc\n\n#include \"decoder/lattice-faster-online-decoder.h\"\n#include \"lat/lattice-functions.h\"\n\nnamespace kaldi {\n\ntemplate <typename FST>\nbool LatticeFasterOnlineDecoderTpl<FST>::TestGetBestPath(\n    bool use_final_probs) const {\n  Lattice lat1;\n  {\n    Lattice raw_lat;\n    this->GetRawLattice(&raw_lat, use_final_probs);\n    ShortestPath(raw_lat, &lat1);\n  }\n  Lattice lat2;\n  GetBestPath(&lat2, use_final_probs);\n  BaseFloat delta = 0.1;\n  int32 num_paths = 1;\n  if (!fst::RandEquivalent(lat1, lat2, num_paths, delta, rand())) {\n    KALDI_WARN << \"Best-path test failed\";\n    return false;\n  } else {\n    return true;\n  }\n}\n\n\n// Outputs an FST corresponding to the single best path through the lattice.\ntemplate <typename FST>\nbool LatticeFasterOnlineDecoderTpl<FST>::GetBestPath(Lattice *olat,\n                                                     bool use_final_probs) const {\n  olat->DeleteStates();\n  BaseFloat final_graph_cost;\n  BestPathIterator iter = BestPathEnd(use_final_probs, &final_graph_cost);\n  if (iter.Done())\n    return false;  // would have printed warning.\n  StateId state = olat->AddState();\n  olat->SetFinal(state, LatticeWeight(final_graph_cost, 0.0));\n  while (!iter.Done()) {\n    LatticeArc arc;\n    iter = TraceBackBestPath(iter, &arc);\n    arc.nextstate = state;\n    StateId new_state = olat->AddState();\n    olat->AddArc(new_state, arc);\n    state = new_state;\n  }\n  olat->SetStart(state);\n  return true;\n}\n\ntemplate <typename FST>\ntypename LatticeFasterOnlineDecoderTpl<FST>::BestPathIterator LatticeFasterOnlineDecoderTpl<FST>::BestPathEnd(\n    bool use_final_probs,\n    BaseFloat *final_cost_out) const {\n  if (this->decoding_finalized_ && !use_final_probs)\n    KALDI_ERR << \"You cannot call FinalizeDecoding() and then call \"\n              << \"BestPathEnd() with use_final_probs == false\";\n  KALDI_ASSERT(this->NumFramesDecoded() > 0 &&\n               \"You cannot call BestPathEnd if no frames were decoded.\");\n\n  unordered_map<Token*, BaseFloat> final_costs_local;\n\n  const unordered_map<Token*, BaseFloat> &final_costs =\n      (this->decoding_finalized_ ? this->final_costs_ :final_costs_local);\n  if (!this->decoding_finalized_ && use_final_probs)\n    this->ComputeFinalCosts(&final_costs_local, NULL, NULL);\n\n  // Singly linked list of tokens on last frame (access list through \"next\"\n  // pointer).\n  BaseFloat best_cost = std::numeric_limits<BaseFloat>::infinity();\n  BaseFloat best_final_cost = 0;\n  Token *best_tok = NULL;\n  for (Token *tok = this->active_toks_.back().toks;\n       tok != NULL; tok = tok->next) {\n    BaseFloat cost = tok->tot_cost, final_cost = 0.0;\n    if (use_final_probs && !final_costs.empty()) {\n      // if we are instructed to use final-probs, and any final tokens were\n      // active on final frame, include the final-prob in the cost of the token.\n      typename unordered_map<Token*, BaseFloat>::const_iterator\n          iter = final_costs.find(tok);\n      if (iter != final_costs.end()) {\n        final_cost = iter->second;\n        cost += final_cost;\n      } else {\n        cost = std::numeric_limits<BaseFloat>::infinity();\n      }\n    }\n    if (cost < best_cost) {\n      best_cost = cost;\n      best_tok = tok;\n      best_final_cost = final_cost;\n    }\n  }\n  if (best_tok == NULL) {  // this should not happen, and is likely a code error or\n    // caused by infinities in likelihoods, but I'm not making\n    // it a fatal error for now.\n    KALDI_WARN << \"No final token found.\";\n  }\n  if (final_cost_out)\n    *final_cost_out = best_final_cost;\n  return BestPathIterator(best_tok, this->NumFramesDecoded() - 1);\n}\n\n\ntemplate <typename FST>\ntypename LatticeFasterOnlineDecoderTpl<FST>::BestPathIterator LatticeFasterOnlineDecoderTpl<FST>::TraceBackBestPath(\n    BestPathIterator iter, LatticeArc *oarc) const {\n  KALDI_ASSERT(!iter.Done() && oarc != NULL);\n  Token *tok = static_cast<Token*>(iter.tok);\n  int32 cur_t = iter.frame, step_t = 0;\n  if (tok->backpointer != NULL) {\n    // retrieve the correct forward link(with the best link cost)\n    BaseFloat best_cost = std::numeric_limits<BaseFloat>::infinity();\n    ForwardLinkT *link;\n    for (link = tok->backpointer->links;\n         link != NULL; link = link->next) {\n      if (link->next_tok == tok) { // this is a link to \"tok\"\n        BaseFloat graph_cost = link->graph_cost, \n                  acoustic_cost = link->acoustic_cost;\n        BaseFloat cost = graph_cost + acoustic_cost;\n        if (cost < best_cost) {\n          oarc->ilabel = link->ilabel;\n          oarc->olabel = link->olabel;\n          if (link->ilabel != 0) {\n            KALDI_ASSERT(static_cast<size_t>(cur_t) < this->cost_offsets_.size());\n            acoustic_cost -= this->cost_offsets_[cur_t];\n            step_t = -1;\n          } else {\n            step_t = 0;\n          }\n          oarc->weight = LatticeWeight(graph_cost, acoustic_cost);\n          best_cost = cost;\n        }\n      }\n    }\n    if (link == NULL &&\n        best_cost == std::numeric_limits<BaseFloat>::infinity()) { // Did not find correct link.\n      KALDI_ERR << \"Error tracing best-path back (likely \"\n                << \"bug in token-pruning algorithm)\";\n    }\n  } else {\n    oarc->ilabel = 0;\n    oarc->olabel = 0;\n    oarc->weight = LatticeWeight::One(); // zero costs.\n  }\n  return BestPathIterator(tok->backpointer, cur_t + step_t);\n}\n\ntemplate <typename FST>\nbool LatticeFasterOnlineDecoderTpl<FST>::GetRawLatticePruned(\n    Lattice *ofst,\n    bool use_final_probs,\n    BaseFloat beam) const {\n  typedef LatticeArc Arc;\n  typedef Arc::StateId StateId;\n  typedef Arc::Weight Weight;\n  typedef Arc::Label Label;\n\n  // Note: you can't use the old interface (Decode()) if you want to\n  // get the lattice with use_final_probs = false.  You'd have to do\n  // InitDecoding() and then AdvanceDecoding().\n  if (this->decoding_finalized_ && !use_final_probs)\n    KALDI_ERR << \"You cannot call FinalizeDecoding() and then call \"\n              << \"GetRawLattice() with use_final_probs == false\";\n\n  unordered_map<Token*, BaseFloat> final_costs_local;\n\n  const unordered_map<Token*, BaseFloat> &final_costs =\n      (this->decoding_finalized_ ? this->final_costs_ : final_costs_local);\n  if (!this->decoding_finalized_ && use_final_probs)\n    this->ComputeFinalCosts(&final_costs_local, NULL, NULL);\n\n  ofst->DeleteStates();\n  // num-frames plus one (since frames are one-based, and we have\n  // an extra frame for the start-state).\n  int32 num_frames = this->active_toks_.size() - 1;\n  KALDI_ASSERT(num_frames > 0);\n  for (int32 f = 0; f <= num_frames; f++) {\n    if (this->active_toks_[f].toks == NULL) {\n      KALDI_WARN << \"No tokens active on frame \" << f\n                 << \": not producing lattice.\\n\";\n      return false;\n    }\n  }\n  unordered_map<Token*, StateId> tok_map;\n  std::queue<std::pair<Token*, int32> > tok_queue;\n  // First initialize the queue and states.  Put the initial state on the queue;\n  // this is the last token in the list active_toks_[0].toks.\n  for (Token *tok = this->active_toks_[0].toks;\n       tok != NULL; tok = tok->next) {\n    if (tok->next == NULL) {\n      tok_map[tok] = ofst->AddState();\n      ofst->SetStart(tok_map[tok]);\n      std::pair<Token*, int32> tok_pair(tok, 0);  // #frame = 0\n      tok_queue.push(tok_pair);\n    }\n  }\n\n  // Next create states for \"good\" tokens\n  while (!tok_queue.empty()) {\n    std::pair<Token*, int32> cur_tok_pair = tok_queue.front();\n    tok_queue.pop();\n    Token *cur_tok = cur_tok_pair.first;\n    int32 cur_frame = cur_tok_pair.second;\n    KALDI_ASSERT(cur_frame >= 0 &&\n                 cur_frame <= this->cost_offsets_.size());\n\n    typename unordered_map<Token*, StateId>::const_iterator iter =\n        tok_map.find(cur_tok);\n    KALDI_ASSERT(iter != tok_map.end());\n    StateId cur_state = iter->second;\n\n    for (ForwardLinkT *l = cur_tok->links;\n         l != NULL;\n         l = l->next) {\n      Token *next_tok = l->next_tok;\n      if (next_tok->extra_cost < beam) {\n        // so both the current and the next token are good; create the arc\n        int32 next_frame = l->ilabel == 0 ? cur_frame : cur_frame + 1;\n        StateId nextstate;\n        if (tok_map.find(next_tok) == tok_map.end()) {\n          nextstate = tok_map[next_tok] = ofst->AddState();\n          tok_queue.push(std::pair<Token*, int32>(next_tok, next_frame));\n        } else {\n          nextstate = tok_map[next_tok];\n        }\n        BaseFloat cost_offset = (l->ilabel != 0 ?\n                                 this->cost_offsets_[cur_frame] : 0);\n        Arc arc(l->ilabel, l->olabel,\n                Weight(l->graph_cost, l->acoustic_cost - cost_offset),\n                nextstate);\n        ofst->AddArc(cur_state, arc);\n      }\n    }\n    if (cur_frame == num_frames) {\n      if (use_final_probs && !final_costs.empty()) {\n        typename unordered_map<Token*, BaseFloat>::const_iterator iter =\n            final_costs.find(cur_tok);\n        if (iter != final_costs.end())\n          ofst->SetFinal(cur_state, LatticeWeight(iter->second, 0));\n      } else {\n        ofst->SetFinal(cur_state, LatticeWeight::One());\n      }\n    }\n  }\n  return (ofst->NumStates() != 0);\n}\n\n\n\n// Instantiate the template for the FST types that we'll need.\ntemplate class LatticeFasterOnlineDecoderTpl<fst::Fst<fst::StdArc> >;\ntemplate class LatticeFasterOnlineDecoderTpl<fst::VectorFst<fst::StdArc> >;\ntemplate class LatticeFasterOnlineDecoderTpl<fst::ConstFst<fst::StdArc> >;\n//template class LatticeFasterOnlineDecoderTpl<fst::ConstGrammarFst >;\n//template class LatticeFasterOnlineDecoderTpl<fst::VectorGrammarFst >;\n\n\n} // end namespace kaldi.\n"
  },
  {
    "path": "runtime/engine/kaldi/decoder/lattice-faster-online-decoder.h",
    "content": "// decoder/lattice-faster-online-decoder.h\n\n// Copyright 2009-2013  Microsoft Corporation;  Mirko Hannemann;\n//           2013-2014  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n//                2018  Zhehuai Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n// see note at the top of lattice-faster-decoder.h, about how to maintain this\n// file in sync with lattice-faster-decoder.h\n\n\n#ifndef KALDI_DECODER_LATTICE_FASTER_ONLINE_DECODER_H_\n#define KALDI_DECODER_LATTICE_FASTER_ONLINE_DECODER_H_\n\n#include \"util/stl-utils.h\"\n#include \"util/hash-list.h\"\n#include \"fst/fstlib.h\"\n#include \"decoder/decodable-itf.h\"\n#include \"fstext/fstext-lib.h\"\n#include \"lat/determinize-lattice-pruned.h\"\n#include \"lat/kaldi-lattice.h\"\n#include \"decoder/lattice-faster-decoder.h\"\n\nnamespace kaldi {\n\n\n\n/** LatticeFasterOnlineDecoderTpl is as LatticeFasterDecoderTpl but also\n    supports an efficient way to get the best path (see the function\n    BestPathEnd()), which is useful in endpointing and in situations where you\n    might want to frequently access the best path.\n\n    This is only templated on the FST type, since the Token type is required to\n    be BackpointerToken.  Actually it only makes sense to instantiate\n    LatticeFasterDecoderTpl with Token == BackpointerToken if you do so indirectly via\n    this child class.\n */\ntemplate <typename FST>\nclass LatticeFasterOnlineDecoderTpl:\n      public LatticeFasterDecoderTpl<FST, decoder::BackpointerToken> {\n public:\n  using Arc = typename FST::Arc;\n  using Label = typename Arc::Label;\n  using StateId = typename Arc::StateId;\n  using Weight = typename Arc::Weight;\n  using Token = decoder::BackpointerToken;\n  using ForwardLinkT = decoder::ForwardLink<Token>;\n\n  // Instantiate this class once for each thing you have to decode.\n  // This version of the constructor does not take ownership of\n  // 'fst'.\n  LatticeFasterOnlineDecoderTpl(const FST &fst,\n                                const LatticeFasterDecoderConfig &config):\n      LatticeFasterDecoderTpl<FST, Token>(fst, config) { }\n\n  // This version of the initializer takes ownership of 'fst', and will delete\n  // it when this object is destroyed.\n  LatticeFasterOnlineDecoderTpl(const LatticeFasterDecoderConfig &config,\n                                FST *fst):\n      LatticeFasterDecoderTpl<FST, Token>(config, fst) { }\n\n\n  struct BestPathIterator {\n    void *tok;\n    int32 frame;\n    // note, \"frame\" is the frame-index of the frame you'll get the\n    // transition-id for next time, if you call TraceBackBestPath on this\n    // iterator (assuming it's not an epsilon transition).  Note that this\n    // is one less than you might reasonably expect, e.g. it's -1 for\n    // the nonemitting transitions before the first frame.\n    BestPathIterator(void *t, int32 f): tok(t), frame(f) { }\n    bool Done() const { return tok == NULL; }\n  };\n\n\n  /// Outputs an FST corresponding to the single best path through the lattice.\n  /// This is quite efficient because it doesn't get the entire raw lattice and find\n  /// the best path through it; instead, it uses the BestPathEnd and BestPathIterator\n  /// so it basically traces it back through the lattice.\n  /// Returns true if result is nonempty (using the return status is deprecated,\n  /// it will become void).  If \"use_final_probs\" is true AND we reached the\n  /// final-state of the graph then it will include those as final-probs, else\n  /// it will treat all final-probs as one.\n  bool GetBestPath(Lattice *ofst,\n                   bool use_final_probs = true) const;\n\n\n  /// This function does a self-test of GetBestPath().  Returns true on\n  /// success; returns false and prints a warning on failure.\n  bool TestGetBestPath(bool use_final_probs = true) const;\n\n\n  /// This function returns an iterator that can be used to trace back\n  /// the best path.  If use_final_probs == true and at least one final state\n  /// survived till the end, it will use the final-probs in working out the best\n  /// final Token, and will output the final cost to *final_cost (if non-NULL),\n  /// else it will use only the forward likelihood, and will put zero in\n  /// *final_cost (if non-NULL).\n  /// Requires that NumFramesDecoded() > 0.\n  BestPathIterator BestPathEnd(bool use_final_probs,\n                               BaseFloat *final_cost = NULL) const;\n\n\n  /// This function can be used in conjunction with BestPathEnd() to trace back\n  /// the best path one link at a time (e.g. this can be useful in endpoint\n  /// detection).  By \"link\" we mean a link in the graph; not all links cross\n  /// frame boundaries, but each time you see a nonzero ilabel you can interpret\n  /// that as a frame.  The return value is the updated iterator.  It outputs\n  /// the ilabel and olabel, and the (graph and acoustic) weight to the \"arc\" pointer,\n  /// while leaving its \"nextstate\" variable unchanged.\n  BestPathIterator TraceBackBestPath(\n      BestPathIterator iter, LatticeArc *arc) const;\n\n\n  /// Behaves the same as GetRawLattice but only processes tokens whose\n  /// extra_cost is smaller than the best-cost plus the specified beam.\n  /// It is only worthwhile to call this function if beam is less than\n  /// the lattice_beam specified in the config; otherwise, it would\n  /// return essentially the same thing as GetRawLattice, but more slowly.\n  bool GetRawLatticePruned(Lattice *ofst,\n                           bool use_final_probs,\n                           BaseFloat beam) const;\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(LatticeFasterOnlineDecoderTpl);\n};\n\ntypedef LatticeFasterOnlineDecoderTpl<fst::StdFst> LatticeFasterOnlineDecoder;\n\n\n} // end namespace kaldi.\n\n#endif\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14 FATAL_ERROR)\n\nset(BINS\nfstaddselfloops\nfstisstochastic    \nfstminimizeencoded\nfstdeterminizestar\nfsttablecompose\n)\n\nforeach(binary IN LISTS BINS)\n   add_executable(${binary} ${CMAKE_CURRENT_SOURCE_DIR}/${binary}.cc) \n   target_include_directories(${binary} PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\n   target_link_libraries(${binary} PUBLIC kaldi-fstext glog gflags fst dl)\nendforeach()\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/fstaddselfloops.cc",
    "content": "// fstbin/fstaddselfloops.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n#include \"fstext/determinize-star.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"util/parse-options.h\"\n#include \"util/simple-io-funcs.h\"\n\n/* some test examples:\n  pushd ~/tmpdir\n ( echo 3; echo  4) > in.list\n ( echo 5; echo  6) > out.list\n ( echo \"0 0 0 0\"; echo \"0 0\" ) | fstcompile | fstaddselfloops in.list out.list\n | fstprint ( echo \"0 1 0 1\"; echo \" 0 2 1 0\"; echo \"1 0\"; echo \"2 0\"; ) |\n fstcompile | fstaddselfloops in.list out.list | fstprint\n*/\n\nint main(int argc, char *argv[]) {\n    try {\n        using namespace kaldi;  // NOLINT\n        using namespace fst;    // NOLINT\n        using kaldi::int32;\n\n        const char *usage =\n            \"Adds self-loops to states of an FST to propagate disambiguation \"\n            \"symbols through it\\n\"\n            \"They are added on each final state and each state with \"\n            \"non-epsilon \"\n            \"output symbols\\n\"\n            \"on at least one arc out of the state.  Useful in conjunction with \"\n            \"predeterminize\\n\"\n            \"\\n\"\n            \"Usage:  fstaddselfloops in-disambig-list out-disambig-list  \"\n            \"[in.fst \"\n            \"[out.fst] ]\\n\"\n            \"E.g:  fstaddselfloops in.list out.list < in.fst > withloops.fst\\n\"\n            \"in.list and out.list are lists of integers, one per line, of the\\n\"\n            \"same length.\\n\";\n\n        ParseOptions po(usage);\n        po.Read(argc, argv);\n\n        if (po.NumArgs() < 2 || po.NumArgs() > 4) {\n            po.PrintUsage();\n            exit(1);\n        }\n\n        std::string disambig_in_rxfilename = po.GetArg(1),\n                    disambig_out_rxfilename = po.GetArg(2),\n                    fst_in_filename = po.GetOptArg(3),\n                    fst_out_filename = po.GetOptArg(4);\n\n        VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);\n\n        std::vector<int32> disambig_in;\n        if (!ReadIntegerVectorSimple(disambig_in_rxfilename, &disambig_in))\n            KALDI_ERR << \"fstaddselfloops: Could not read disambiguation \"\n                         \"symbols from \"\n                      << kaldi::PrintableRxfilename(disambig_in_rxfilename);\n\n        std::vector<int32> disambig_out;\n        if (!ReadIntegerVectorSimple(disambig_out_rxfilename, &disambig_out))\n            KALDI_ERR << \"fstaddselfloops: Could not read disambiguation \"\n                         \"symbols from \"\n                      << kaldi::PrintableRxfilename(disambig_out_rxfilename);\n\n        if (disambig_in.size() != disambig_out.size())\n            KALDI_ERR << \"fstaddselfloops: mismatch in size of disambiguation \"\n                         \"symbols\";\n\n        AddSelfLoops(fst, disambig_in, disambig_out);\n\n        WriteFstKaldi(*fst, fst_out_filename);\n\n        delete fst;\n\n        return 0;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/fstdeterminizestar.cc",
    "content": "// fstbin/fstdeterminizestar.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n#include \"fstext/determinize-star.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"util/parse-options.h\"\n#if !defined(_MSC_VER) && !defined(__APPLE__)\n#include <signal.h>  // Comment this line and the call to signal below if\n// it causes compilation problems.  It is only to enable a debugging procedure\n// when determinization does not terminate.  We are disabling this code if\n// compiling on Windows because signal.h is not available there, and on\n// MacOS due to a problem with <signal.h> in the initial release of Sierra.\n#endif\n\n/* some test  examples:\n ( echo \"0 0 0 0\"; echo \"0 0\" ) | fstcompile | fstdeterminizestar | fstprint\n ( echo \"0 0 1 0\"; echo \"0 0\" ) | fstcompile | fstdeterminizestar | fstprint\n ( echo \"0 0 1 0\"; echo \"0 1 1 0\"; echo \"0 0\" ) | fstcompile |\n fstdeterminizestar | fstprint # this last one fails [correctly]: ( echo \"0 0 0\n 1\"; echo \"0 0\" ) | fstcompile | fstdeterminizestar | fstprint\n\n  cd ~/tmpdir\n  while true; do\n    fstrand > 1.fst\n    fstpredeterminize out.lst 1.fst | fstdeterminizestar | fstrmsymbols out.lst\n > 2.fst fstequivalent --random=true 1.fst 2.fst || echo \"Test failed\" echo -n\n \".\" done\n\n Test of debugging [with non-determinizable input]:\n ( echo \" 0 0 1 0 1.0\"; echo \"0 1 1 0\"; echo \"1 1 1 0 0\"; echo \"0 2 2 0\"; echo\n \"2\"; echo \"1\" ) | fstcompile | fstdeterminizestar kill -SIGUSR1 [the process-id\n of fstdeterminizestar] # prints out a bunch of debugging output showing the\n mess it got itself into.\n*/\n\nbool debug_location = false;\nvoid signal_handler(int) { debug_location = true; }\n\nint main(int argc, char *argv[]) {\n    try {\n        using namespace kaldi;  // NOLINT\n        using namespace fst;    // NOLINT\n        using kaldi::int32;\n\n        const char *usage =\n            \"Removes epsilons and determinizes in one step\\n\"\n            \"\\n\"\n            \"Usage:  fstdeterminizestar [in.fst [out.fst] ]\\n\"\n            \"\\n\"\n            \"See also: fstdeterminizelog, lattice-determinize\\n\";\n\n        float delta = kDelta;\n        int max_states = -1;\n        bool use_log = false;\n        ParseOptions po(usage);\n        po.Register(\"use-log\", &use_log, \"Determinize in log semiring.\");\n        po.Register(\"delta\",\n                    &delta,\n                    \"Delta value used to determine equivalence of weights.\");\n        po.Register(\"max-states\",\n                    &max_states,\n                    \"Maximum number of states in determinized FST before it \"\n                    \"will abort.\");\n        po.Read(argc, argv);\n\n        if (po.NumArgs() > 2) {\n            po.PrintUsage();\n            exit(1);\n        }\n\n        std::string fst_in_str = po.GetOptArg(1), fst_out_str = po.GetOptArg(2);\n\n// This enables us to get traceback info from determinization that is\n// not seeming to terminate.\n#if !defined(_MSC_VER) && !defined(__APPLE__)\n        signal(SIGUSR1, signal_handler);\n#endif\n        // Normal case: just files.\n        VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_str);\n\n        ArcSort(fst, ILabelCompare<StdArc>());  // improves speed.\n        if (use_log) {\n            DeterminizeStarInLog(fst, delta, &debug_location, max_states);\n        } else {\n            VectorFst<StdArc> det_fst;\n            DeterminizeStar(*fst, &det_fst, delta, &debug_location, max_states);\n            *fst = det_fst;  // will do shallow copy and then det_fst goes\n                             // out of scope anyway.\n        }\n        WriteFstKaldi(*fst, fst_out_str);\n        delete fst;\n        return 0;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/fstisstochastic.cc",
    "content": "// fstbin/fstisstochastic.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/parse-options.h\"\n\n// e.g. of test:\n// echo \" 0 0\" | fstcompile | fstisstochastic\n// should return 0 and print \"0 0\" [meaning, min and\n// max weight are one = exp(0)]\n// echo \" 0 1\" | fstcompile | fstisstochastic\n// should  return 1, not stochastic, and print 1 1\n// (echo \"0 0 0 0 0.693147 \"; echo \"0 1 0 0 0.693147 \"; echo \"1 0\" ) |\n// fstcompile | fstisstochastic should return 0, stochastic; it prints \"0\n// -1.78e-07\" for me (echo \"0 0 0 0 0.693147 \"; echo \"0 1 0 0 0.693147 \"; echo\n// \"1 0\" ) | fstcompile | fstisstochastic --test-in-log=false should return 1,\n// not stochastic in tropical; it prints \"0 0.693147\" for me (echo \"0 0 0 0 0 \";\n// echo \"0 1 0 0 0 \"; echo \"1 0\" ) | fstcompile | fstisstochastic\n// --test-in-log=false should return 0, stochastic in tropical; it prints \"0 0\"\n// for me (echo \"0 0 0 0 0.693147 \"; echo \"0 1 0 0 0.693147 \"; echo \"1 0\" ) |\n// fstcompile | fstisstochastic --test-in-log=false --delta=1 returns 0 even\n// though not stochastic because we gave it an absurdly large delta.\n\nint main(int argc, char *argv[]) {\n    try {\n        using namespace kaldi;  // NOLINT\n        using namespace fst;    // NOLINT\n        using kaldi::int32;\n\n        const char *usage =\n            \"Checks whether an FST is stochastic and exits with success if \"\n            \"so.\\n\"\n            \"Prints out maximum error (in log units).\\n\"\n            \"\\n\"\n            \"Usage:  fstisstochastic [ in.fst ]\\n\";\n\n        float delta = 0.01;\n        bool test_in_log = true;\n\n        ParseOptions po(usage);\n        po.Register(\"delta\", &delta, \"Maximum error to accept.\");\n        po.Register(\n            \"test-in-log\", &test_in_log, \"Test stochasticity in log semiring.\");\n        po.Read(argc, argv);\n\n        if (po.NumArgs() > 1) {\n            po.PrintUsage();\n            exit(1);\n        }\n\n        std::string fst_in_filename = po.GetOptArg(1);\n\n        Fst<StdArc> *fst = ReadFstKaldiGeneric(fst_in_filename);\n\n        bool ans;\n        StdArc::Weight min, max;\n        if (test_in_log)\n            ans = IsStochasticFstInLog(*fst, delta, &min, &max);\n        else\n            ans = IsStochasticFst(*fst, delta, &min, &max);\n\n        std::cout << min.Value() << \" \" << max.Value() << '\\n';\n        delete fst;\n        if (ans)\n            return 0;  // success;\n        else\n            return 1;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/fstminimizeencoded.cc",
    "content": "// fstbin/fstminimizeencoded.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n#include \"fstext/determinize-star.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/parse-options.h\"\n#include \"util/text-utils.h\"\n\n/* some test  examples:\n ( echo \"0 0 0 0\"; echo \"0 0\" ) | fstcompile | fstminimizeencoded | fstprint\n ( echo \"0 1 0 0\"; echo \" 0 2 0 0\"; echo \"1 0\"; echo \"2 0\"; ) | fstcompile |\n fstminimizeencoded | fstprint\n*/\n\nint main(int argc, char *argv[]) {\n    try {\n        using namespace kaldi;  // NOLINT\n        using namespace fst;    // NOLINT\n        using kaldi::int32;\n\n        const char *usage =\n            \"Minimizes FST after encoding [similar to fstminimize, but no \"\n            \"weight-pushing]\\n\"\n            \"\\n\"\n            \"Usage:  fstminimizeencoded [in.fst [out.fst] ]\\n\";\n\n        float delta = kDelta;\n        ParseOptions po(usage);\n        po.Register(\"delta\",\n                    &delta,\n                    \"Delta likelihood used for quantization of weights\");\n        po.Read(argc, argv);\n\n        if (po.NumArgs() > 2) {\n            po.PrintUsage();\n            exit(1);\n        }\n\n        std::string fst_in_filename = po.GetOptArg(1),\n                    fst_out_filename = po.GetOptArg(2);\n\n        VectorFst<StdArc> *fst = ReadFstKaldi(fst_in_filename);\n\n        MinimizeEncoded(fst, delta);\n\n        WriteFstKaldi(*fst, fst_out_filename);\n\n        delete fst;\n        return 0;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/fstbin/fsttablecompose.cc",
    "content": "// fstbin/fsttablecompose.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n//                2013  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"fstext/table-matcher.h\"\n#include \"util/parse-options.h\"\n\n/*\n  cd ~/tmpdir\n  while true; do\n    fstrand  | fstarcsort --sort_type=olabel > 1.fst; fstrand | fstarcsort\n  > 2.fst fstcompose 1.fst 2.fst > 3a.fst fsttablecompose 1.fst 2.fst > 3b.fst\n    fstequivalent --random=true 3a.fst 3b.fst || echo \"Test failed\"\n    echo -n \".\"\n  done\n\n*/\n\nint main(int argc, char *argv[]) {\n    try {\n        using namespace kaldi;  // NOLINT\n        using namespace fst;    // NOLINT\n        using kaldi::int32;\n        /*\n          fsttablecompose should always give equivalent results to compose,\n          but it is more efficient for certain kinds of inputs.\n          In particular, it is useful when, say, the left FST has states\n          that typically either have epsilon olabels, or\n          one transition out for each of the possible symbols (as the\n          olabel).  The same with the input symbols of the right-hand FST\n          is possible.\n        */\n\n        const char *usage =\n            \"Composition algorithm [between two FSTs of standard type, in \"\n            \"tropical\\n\"\n            \"semiring] that is more efficient for certain cases-- in \"\n            \"particular,\\n\"\n            \"where one of the FSTs (the left one, if --match-side=left) has \"\n            \"large\\n\"\n            \"out-degree\\n\"\n            \"\\n\"\n            \"Usage:  fsttablecompose (fst1-rxfilename|fst1-rspecifier) \"\n            \"(fst2-rxfilename|fst2-rspecifier) \"\n            \"[(out-rxfilename|out-rspecifier)]\\n\";\n\n        ParseOptions po(usage);\n\n        TableComposeOptions opts;\n        std::string match_side = \"left\";\n        std::string compose_filter = \"sequence\";\n\n        po.Register(\n            \"connect\", &opts.connect, \"If true, trim FST before output.\");\n        po.Register(\"match-side\",\n                    &match_side,\n                    \"Side of composition to do table \"\n                    \"match, one of: \\\"left\\\" or \\\"right\\\".\");\n        po.Register(\n            \"compose-filter\",\n            &compose_filter,\n            \"Composition filter to use, \"\n            \"one of: \\\"alt_sequence\\\", \\\"auto\\\", \\\"match\\\", \\\"sequence\\\"\");\n\n        po.Read(argc, argv);\n\n        if (match_side == \"left\") {\n            opts.table_match_type = MATCH_OUTPUT;\n        } else if (match_side == \"right\") {\n            opts.table_match_type = MATCH_INPUT;\n        } else {\n            KALDI_ERR << \"Invalid match-side option: \" << match_side;\n        }\n\n        if (compose_filter == \"alt_sequence\") {\n            opts.filter_type = ALT_SEQUENCE_FILTER;\n        } else if (compose_filter == \"auto\") {\n            opts.filter_type = AUTO_FILTER;\n        } else if (compose_filter == \"match\") {\n            opts.filter_type = MATCH_FILTER;\n        } else if (compose_filter == \"sequence\") {\n            opts.filter_type = SEQUENCE_FILTER;\n        } else {\n            KALDI_ERR << \"Invalid compose-filter option: \" << compose_filter;\n        }\n\n        if (po.NumArgs() < 2 || po.NumArgs() > 3) {\n            po.PrintUsage();\n            exit(1);\n        }\n\n        std::string fst1_in_str = po.GetArg(1), fst2_in_str = po.GetArg(2),\n                    fst_out_str = po.GetOptArg(3);\n\n        VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);\n\n        VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);\n\n        // Checks if <fst1> is olabel sorted and <fst2> is ilabel sorted.\n        if (fst1->Properties(fst::kOLabelSorted, true) == 0) {\n            KALDI_WARN << \"The first FST is not olabel sorted.\";\n        }\n        if (fst2->Properties(fst::kILabelSorted, true) == 0) {\n            KALDI_WARN << \"The second FST is not ilabel sorted.\";\n        }\n\n        VectorFst<StdArc> composed_fst;\n\n        TableCompose(*fst1, *fst2, &composed_fst, opts);\n\n        delete fst1;\n        delete fst2;\n\n        WriteFstKaldi(composed_fst, fst_out_str);\n        return 0;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/CMakeLists.txt",
    "content": "\nadd_library(kaldi-fstext\n  kaldi-fst-io.cc\n)\ntarget_link_libraries(kaldi-fstext PUBLIC kaldi-util)\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/determinize-lattice-inl.h",
    "content": "// fstext/determinize-lattice-inl.h\n\n// Copyright 2009-2012  Microsoft Corporation\n//           2012-2013  Johns Hopkins University (Author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_DETERMINIZE_LATTICE_INL_H_\n#define KALDI_FSTEXT_DETERMINIZE_LATTICE_INL_H_\n// Do not include this file directly.  It is included by determinize-lattice.h\n\n#include <algorithm>\n#include <climits>\n#include <deque>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\nnamespace fst {\n\n// This class maps back and forth from/to integer id's to sequences of strings.\n// used in determinization algorithm.  It is constructed in such a way that\n// finding the string-id of the successor of (string, next-label) has constant\n// time.\n\n// Note: class IntType, typically int32, is the type of the element in the\n// string (typically a template argument of the CompactLatticeWeightTpl).\n\ntemplate <class IntType>\nclass LatticeStringRepository {\n public:\n  struct Entry {\n    const Entry *parent;  // NULL for empty string.\n    IntType i;\n    inline bool operator==(const Entry &other) const {\n      return (parent == other.parent && i == other.i);\n    }\n    Entry() {}\n    Entry(const Entry &e) : parent(e.parent), i(e.i) {}\n  };\n  // Note: all Entry* pointers returned in function calls are\n  // owned by the repository itself, not by the caller!\n\n  // Interface guarantees empty string is NULL.\n  inline const Entry *EmptyString() { return NULL; }\n\n  // Returns string of \"parent\" with i appended.  Pointer\n  // owned by repository\n  const Entry *Successor(const Entry *parent, IntType i) {\n    new_entry_->parent = parent;\n    new_entry_->i = i;\n\n    std::pair<typename SetType::iterator, bool> pr = set_.insert(new_entry_);\n    if (pr.second) {  // Was successfully inserted (was not there).  We need to\n                      // replace the element we inserted, which resides on the\n                      // stack, with one from the heap.\n      const Entry *ans = new_entry_;\n      new_entry_ = new Entry();\n      return ans;\n    } else {  // Was not inserted because an equivalent Entry already\n              // existed.\n      return *pr.first;\n    }\n  }\n\n  const Entry *Concatenate(const Entry *a, const Entry *b) {\n    if (a == NULL)\n      return b;\n    else if (b == NULL)\n      return a;\n    std::vector<IntType> v;\n    ConvertToVector(b, &v);\n    const Entry *ans = a;\n    for (size_t i = 0; i < v.size(); i++) ans = Successor(ans, v[i]);\n    return ans;\n  }\n  const Entry *CommonPrefix(const Entry *a, const Entry *b) {\n    std::vector<IntType> a_vec, b_vec;\n    ConvertToVector(a, &a_vec);\n    ConvertToVector(b, &b_vec);\n    const Entry *ans = NULL;\n    for (size_t i = 0;\n         i < a_vec.size() && i < b_vec.size() && a_vec[i] == b_vec[i]; i++)\n      ans = Successor(ans, a_vec[i]);\n    return ans;\n  }\n\n  // removes any elements from b that are not part of\n  // a common prefix with a.\n  void ReduceToCommonPrefix(const Entry *a, std::vector<IntType> *b) {\n    size_t a_size = Size(a), b_size = b->size();\n    while (a_size > b_size) {\n      a = a->parent;\n      a_size--;\n    }\n    if (b_size > a_size) b_size = a_size;\n    typename std::vector<IntType>::iterator b_begin = b->begin();\n    while (a_size != 0) {\n      if (a->i != *(b_begin + a_size - 1)) b_size = a_size - 1;\n      a = a->parent;\n      a_size--;\n    }\n    if (b_size != b->size()) b->resize(b_size);\n  }\n\n  // removes the first n elements of a.\n  const Entry *RemovePrefix(const Entry *a, size_t n) {\n    if (n == 0) return a;\n    std::vector<IntType> a_vec;\n    ConvertToVector(a, &a_vec);\n    assert(a_vec.size() >= n);\n    const Entry *ans = NULL;\n    for (size_t i = n; i < a_vec.size(); i++) ans = Successor(ans, a_vec[i]);\n    return ans;\n  }\n\n  // Returns true if a is a prefix of b.  If a is prefix of b,\n  // time taken is |b| - |a|.  Else, time taken is |b|.\n  bool IsPrefixOf(const Entry *a, const Entry *b) const {\n    if (a == NULL) return true;  // empty string prefix of all.\n    if (a == b) return true;\n    if (b == NULL) return false;\n    return IsPrefixOf(a, b->parent);\n  }\n\n  inline size_t Size(const Entry *entry) const {\n    size_t ans = 0;\n    while (entry != NULL) {\n      ans++;\n      entry = entry->parent;\n    }\n    return ans;\n  }\n\n  void ConvertToVector(const Entry *entry, std::vector<IntType> *out) const {\n    size_t length = Size(entry);\n    out->resize(length);\n    if (entry != NULL) {\n      typename std::vector<IntType>::reverse_iterator iter = out->rbegin();\n      while (entry != NULL) {\n        *iter = entry->i;\n        entry = entry->parent;\n        ++iter;\n      }\n    }\n  }\n\n  const Entry *ConvertFromVector(const std::vector<IntType> &vec) {\n    const Entry *e = NULL;\n    for (size_t i = 0; i < vec.size(); i++) e = Successor(e, vec[i]);\n    return e;\n  }\n\n  LatticeStringRepository() { new_entry_ = new Entry; }\n\n  void Destroy() {\n    for (typename SetType::iterator iter = set_.begin(); iter != set_.end();\n         ++iter)\n      delete *iter;\n    SetType tmp;\n    tmp.swap(set_);\n    if (new_entry_) {\n      delete new_entry_;\n      new_entry_ = NULL;\n    }\n  }\n\n  // Rebuild will rebuild this object, guaranteeing only\n  // to preserve the Entry values that are in the vector pointed\n  // to (this list does not have to be unique).  The point of\n  // this is to save memory.\n  void Rebuild(const std::vector<const Entry *> &to_keep) {\n    SetType tmp_set;\n    for (typename std::vector<const Entry *>::const_iterator iter =\n             to_keep.begin();\n         iter != to_keep.end(); ++iter)\n      RebuildHelper(*iter, &tmp_set);\n    // Now delete all elems not in tmp_set.\n    for (typename SetType::iterator iter = set_.begin(); iter != set_.end();\n         ++iter) {\n      if (tmp_set.count(*iter) == 0)\n        delete (*iter);  // delete the Entry; not needed.\n    }\n    set_.swap(tmp_set);\n  }\n\n  ~LatticeStringRepository() { Destroy(); }\n  int32 MemSize() const {\n    return set_.size() * sizeof(Entry) * 2;  // this is a lower bound\n    // on the size this structure might take.\n  }\n\n private:\n  class EntryKey {  // Hash function object.\n   public:\n    inline size_t operator()(const Entry *entry) const {\n      size_t prime = 49109;\n      return static_cast<size_t>(entry->i) +\n             prime * reinterpret_cast<size_t>(entry->parent);\n    }\n  };\n  class EntryEqual {\n   public:\n    inline bool operator()(const Entry *e1, const Entry *e2) const {\n      return (*e1 == *e2);\n    }\n  };\n  typedef std::unordered_set<const Entry *, EntryKey, EntryEqual> SetType;\n\n  void RebuildHelper(const Entry *to_add, SetType *tmp_set) {\n    while (true) {\n      if (to_add == NULL) return;\n      typename SetType::iterator iter = tmp_set->find(to_add);\n      if (iter == tmp_set->end()) {  // not in tmp_set.\n        tmp_set->insert(to_add);\n        to_add = to_add->parent;  // and loop.\n      } else {\n        return;\n      }\n    }\n  }\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(LatticeStringRepository);\n  Entry *new_entry_;  // We always have a pre-allocated Entry ready to use,\n                      // to avoid unnecessary news and deletes.\n  SetType set_;\n};\n\n// class LatticeDeterminizer is templated on the same types that\n// CompactLatticeWeight is templated on: the base weight (Weight), typically\n// LatticeWeightTpl<float> etc. but could also be e.g. TropicalWeight, and the\n// IntType, typically int32, used for the output symbols in the compact\n// representation of strings [note: the output symbols would usually be\n// p.d.f. id's in the anticipated use of this code] It has a special requirement\n// on the Weight type: that there should be a Compare function on the weights\n// such that Compare(w1, w2) returns -1 if w1 < w2, 0 if w1 == w2, and +1 if w1\n// > w2.  This requires that there be a total order on the weights.\n\ntemplate <class Weight, class IntType>\nclass LatticeDeterminizer {\n public:\n  // Output to Gallic acceptor (so the strings go on weights, and there is a 1-1\n  // correspondence between our states and the states in ofst.  If destroy ==\n  // true, release memory as we go (but we cannot output again).\n\n  typedef CompactLatticeWeightTpl<Weight, IntType> CompactWeight;\n  typedef ArcTpl<CompactWeight>\n      CompactArc;              // arc in compact, acceptor form of lattice\n  typedef ArcTpl<Weight> Arc;  // arc in non-compact version of lattice\n\n  // Output to standard FST with CompactWeightTpl<Weight> as its weight type\n  // (the weight stores the original output-symbol strings).  If destroy ==\n  // true, release memory as we go (but we cannot output again).\n  void Output(MutableFst<CompactArc> *ofst, bool destroy = true) {\n    assert(determinized_);\n    typedef typename Arc::StateId StateId;\n    StateId nStates = static_cast<StateId>(output_arcs_.size());\n    if (destroy) FreeMostMemory();\n    ofst->DeleteStates();\n    ofst->SetStart(kNoStateId);\n    if (nStates == 0) {\n      return;\n    }\n    for (StateId s = 0; s < nStates; s++) {\n      OutputStateId news = ofst->AddState();\n      assert(news == s);\n    }\n    ofst->SetStart(0);\n    // now process transitions.\n    for (StateId this_state = 0; this_state < nStates; this_state++) {\n      std::vector<TempArc> &this_vec(output_arcs_[this_state]);\n      typename std::vector<TempArc>::const_iterator iter = this_vec.begin(),\n                                                    end = this_vec.end();\n\n      for (; iter != end; ++iter) {\n        const TempArc &temp_arc(*iter);\n        CompactArc new_arc;\n        std::vector<Label> seq;\n        repository_.ConvertToVector(temp_arc.string, &seq);\n        CompactWeight weight(temp_arc.weight, seq);\n        if (temp_arc.nextstate == kNoStateId) {  // is really final weight.\n          ofst->SetFinal(this_state, weight);\n        } else {  // is really an arc.\n          new_arc.nextstate = temp_arc.nextstate;\n          new_arc.ilabel = temp_arc.ilabel;\n          new_arc.olabel = temp_arc.ilabel;  // acceptor.  input == output.\n          new_arc.weight = weight;           // includes string and weight.\n          ofst->AddArc(this_state, new_arc);\n        }\n      }\n      // Free up memory.  Do this inside the loop as ofst is also allocating\n      // memory\n      if (destroy) {\n        std::vector<TempArc> temp;\n        std::swap(temp, this_vec);\n      }\n    }\n    if (destroy) {\n      std::vector<std::vector<TempArc> > temp;\n      std::swap(temp, output_arcs_);\n    }\n  }\n\n  // Output to standard FST with Weight as its weight type.  We will create\n  // extra states to handle sequences of symbols on the output.  If destroy ==\n  // true, release memory as we go (but we cannot output again).\n  void Output(MutableFst<Arc> *ofst, bool destroy = true) {\n    // Outputs to standard fst.\n    OutputStateId nStates = static_cast<OutputStateId>(output_arcs_.size());\n    ofst->DeleteStates();\n    if (nStates == 0) {\n      ofst->SetStart(kNoStateId);\n      return;\n    }\n    if (destroy) FreeMostMemory();\n    // Add basic states-- but we will add extra ones to account for strings on\n    // output.\n    for (OutputStateId s = 0; s < nStates; s++) {\n      OutputStateId news = ofst->AddState();\n      assert(news == s);\n    }\n    ofst->SetStart(0);\n    for (OutputStateId this_state = 0; this_state < nStates; this_state++) {\n      std::vector<TempArc> &this_vec(output_arcs_[this_state]);\n\n      typename std::vector<TempArc>::const_iterator iter = this_vec.begin(),\n                                                    end = this_vec.end();\n      for (; iter != end; ++iter) {\n        const TempArc &temp_arc(*iter);\n        std::vector<Label> seq;\n        repository_.ConvertToVector(temp_arc.string, &seq);\n\n        if (temp_arc.nextstate == kNoStateId) {  // Really a final weight.\n          // Make a sequence of states going to a final state, with the strings\n          // as labels.  Put the weight on the first arc.\n          OutputStateId cur_state = this_state;\n          for (size_t i = 0; i < seq.size(); i++) {\n            OutputStateId next_state = ofst->AddState();\n            Arc arc;\n            arc.nextstate = next_state;\n            arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n            arc.ilabel = 0;  // epsilon.\n            arc.olabel = seq[i];\n            ofst->AddArc(cur_state, arc);\n            cur_state = next_state;\n          }\n          ofst->SetFinal(cur_state,\n                         (seq.size() == 0 ? temp_arc.weight : Weight::One()));\n        } else {  // Really an arc.\n          OutputStateId cur_state = this_state;\n          // Have to be careful with this integer comparison (i+1 < seq.size())\n          // because unsigned. i < seq.size()-1 could fail for zero-length\n          // sequences.\n          for (size_t i = 0; i + 1 < seq.size(); i++) {\n            // for all but the last element of seq, create new state.\n            OutputStateId next_state = ofst->AddState();\n            Arc arc;\n            arc.nextstate = next_state;\n            arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n            arc.ilabel = (i == 0 ? temp_arc.ilabel\n                                 : 0);  // put ilabel on first element of seq.\n            arc.olabel = seq[i];\n            ofst->AddArc(cur_state, arc);\n            cur_state = next_state;\n          }\n          // Add the final arc in the sequence.\n          Arc arc;\n          arc.nextstate = temp_arc.nextstate;\n          arc.weight = (seq.size() <= 1 ? temp_arc.weight : Weight::One());\n          arc.ilabel = (seq.size() <= 1 ? temp_arc.ilabel : 0);\n          arc.olabel = (seq.size() > 0 ? seq.back() : 0);\n          ofst->AddArc(cur_state, arc);\n        }\n      }\n      // Free up memory.  Do this inside the loop as ofst is also allocating\n      // memory\n      if (destroy) {\n        std::vector<TempArc> temp;\n        temp.swap(this_vec);\n      }\n    }\n    if (destroy) {\n      std::vector<std::vector<TempArc> > temp;\n      temp.swap(output_arcs_);\n      repository_.Destroy();\n    }\n  }\n\n  // Initializer.  After initializing the object you will typically\n  // call Determinize() and then call one of the Output functions.\n  // Note: ifst.Copy() will generally do a\n  // shallow copy.  We do it like this for memory safety, rather than\n  // keeping a reference or pointer to ifst_.\n  LatticeDeterminizer(const Fst<Arc> &ifst, DeterminizeLatticeOptions opts)\n      : num_arcs_(0),\n        num_elems_(0),\n        ifst_(ifst.Copy()),\n        opts_(opts),\n        equal_(opts_.delta),\n        determinized_(false),\n        minimal_hash_(3, hasher_, equal_),\n        initial_hash_(3, hasher_, equal_) {\n    KALDI_ASSERT(Weight::Properties() & kIdempotent);  // this algorithm won't\n    // work correctly otherwise.\n  }\n\n  // frees all except output_arcs_, which contains the important info\n  // we need to output the FST.\n  void FreeMostMemory() {\n    if (ifst_) {\n      delete ifst_;\n      ifst_ = NULL;\n    }\n    for (typename MinimalSubsetHash::iterator iter = minimal_hash_.begin();\n         iter != minimal_hash_.end(); ++iter)\n      delete iter->first;\n    {\n      MinimalSubsetHash tmp;\n      tmp.swap(minimal_hash_);\n    }\n    for (typename InitialSubsetHash::iterator iter = initial_hash_.begin();\n         iter != initial_hash_.end(); ++iter)\n      delete iter->first;\n    {\n      InitialSubsetHash tmp;\n      tmp.swap(initial_hash_);\n    }\n    {\n      std::vector<std::vector<Element> *> output_states_tmp;\n      output_states_tmp.swap(output_states_);\n    }\n    {\n      std::vector<char> tmp;\n      tmp.swap(isymbol_or_final_);\n    }\n    {\n      std::vector<OutputStateId> tmp;\n      tmp.swap(queue_);\n    }\n    {\n      std::vector<std::pair<Label, Element> > tmp;\n      tmp.swap(all_elems_tmp_);\n    }\n  }\n\n  ~LatticeDeterminizer() {\n    FreeMostMemory();  // rest is deleted by destructors.\n  }\n  void RebuildRepository() {  // rebuild the string repository,\n    // freeing stuff we don't need.. we call this when memory usage\n    // passes a supplied threshold.  We need to accumulate all the\n    // strings we need the repository to \"remember\", then tell it\n    // to clean the repository.\n    std::vector<StringId> needed_strings;\n    for (size_t i = 0; i < output_arcs_.size(); i++)\n      for (size_t j = 0; j < output_arcs_[i].size(); j++)\n        needed_strings.push_back(output_arcs_[i][j].string);\n\n    // the following loop covers strings present in minimal_hash_\n    // which are also accessible via output_states_.\n    for (size_t i = 0; i < output_states_.size(); i++)\n      for (size_t j = 0; j < output_states_[i]->size(); j++)\n        needed_strings.push_back((*(output_states_[i]))[j].string);\n\n    // the following loop covers strings present in initial_hash_.\n    for (typename InitialSubsetHash::const_iterator iter =\n             initial_hash_.begin();\n         iter != initial_hash_.end(); ++iter) {\n      const std::vector<Element> &vec = *(iter->first);\n      Element elem = iter->second;\n      for (size_t i = 0; i < vec.size(); i++)\n        needed_strings.push_back(vec[i].string);\n      needed_strings.push_back(elem.string);\n    }\n\n    std::sort(needed_strings.begin(), needed_strings.end());\n    needed_strings.erase(\n        std::unique(needed_strings.begin(), needed_strings.end()),\n        needed_strings.end());  // uniq the strings.\n    repository_.Rebuild(needed_strings);\n  }\n\n  bool CheckMemoryUsage() {\n    int32 repo_size = repository_.MemSize(),\n          arcs_size = num_arcs_ * sizeof(TempArc),\n          elems_size = num_elems_ * sizeof(Element),\n          total_size = repo_size + arcs_size + elems_size;\n    if (opts_.max_mem > 0 &&\n        total_size > opts_.max_mem) {  // We passed the memory threshold.\n      // This is usually due to the repository getting large, so we\n      // clean this out.\n      RebuildRepository();\n      int32 new_repo_size = repository_.MemSize(),\n            new_total_size = new_repo_size + arcs_size + elems_size;\n\n      KALDI_VLOG(2) << \"Rebuilt repository in determinize-lattice: repository \"\n                       \"shrank from \"\n                    << repo_size << \" to \" << new_repo_size\n                    << \" bytes (approximately)\";\n\n      if (new_total_size > static_cast<int32>(opts_.max_mem * 0.8)) {\n        // Rebuilding didn't help enough-- we need a margin to stop\n        // having to rebuild too often.\n        KALDI_WARN << \"Failure in determinize-lattice: size exceeds maximum \"\n                   << opts_.max_mem << \" bytes; (repo,arcs,elems) = (\"\n                   << repo_size << \",\" << arcs_size << \",\" << elems_size\n                   << \"), after rebuilding, repo size was \" << new_repo_size;\n        return false;\n      }\n    }\n    return true;\n  }\n\n  // Returns true on success.  Can fail for out-of-memory\n  // or max-states related reasons.\n  bool Determinize(bool *debug_ptr) {\n    assert(!determinized_);\n    // This determinizes the input fst but leaves it in the \"special format\"\n    // in \"output_arcs_\".  Must be called after Initialize().  To get the\n    // output, call one of the Output routines.\n    try {\n      InitializeDeterminization();  // some start-up tasks.\n      while (!queue_.empty()) {\n        OutputStateId out_state = queue_.back();\n        queue_.pop_back();\n        ProcessState(out_state);\n        if (debug_ptr && *debug_ptr) Debug();  // will exit.\n        if (!CheckMemoryUsage()) return false;\n      }\n      return (determinized_ = true);\n    } catch (const std::bad_alloc &) {\n      int32 repo_size = repository_.MemSize(),\n            arcs_size = num_arcs_ * sizeof(TempArc),\n            elems_size = num_elems_ * sizeof(Element),\n            total_size = repo_size + arcs_size + elems_size;\n      KALDI_WARN\n          << \"Memory allocation error doing lattice determinization; using \"\n          << total_size << \" bytes (max = \" << opts_.max_mem\n          << \" (repo,arcs,elems) = (\" << repo_size << \",\" << arcs_size << \",\"\n          << elems_size << \")\";\n      return (determinized_ = false);\n    } catch (const std::runtime_error &) {\n      KALDI_WARN << \"Caught exception doing lattice determinization\";\n      return (determinized_ = false);\n    }\n  }\n\n private:\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId\n      StateId;  // use this when we don't know if it's input or output.\n  typedef typename Arc::StateId InputStateId;   // state in the input FST.\n  typedef typename Arc::StateId OutputStateId;  // same as above but distinguish\n                                                // states in output Fst.\n\n  typedef LatticeStringRepository<IntType> StringRepositoryType;\n  typedef const typename StringRepositoryType::Entry *StringId;\n\n  // Element of a subset [of original states]\n  struct Element {\n    StateId state;  // use StateId as this is usually InputStateId but in one\n                    // case OutputStateId.\n    StringId string;\n    Weight weight;\n    bool operator!=(const Element &other) const {\n      return (state != other.state || string != other.string ||\n              weight != other.weight);\n    }\n    // This operator is only intended to support sorting in EpsilonClosure()\n    bool operator<(const Element &other) const { return state < other.state; }\n  };\n\n  // Arcs in the format we temporarily create in this class (a representation,\n  // essentially of a Gallic Fst).\n  struct TempArc {\n    Label ilabel;\n    StringId string;  // Look it up in the StringRepository, it's a sequence of\n                      // Labels.\n    OutputStateId nextstate;  // or kNoState for final weights.\n    Weight weight;\n  };\n\n  // Hashing function used in hash of subsets.\n  // A subset is a pointer to vector<Element>.\n  // The Elements are in sorted order on state id, and without repeated states.\n  // Because the order of Elements is fixed, we can use a hashing function that\n  // is order-dependent.  However the weights are not included in the hashing\n  // function-- we hash subsets that differ only in weight to the same key. This\n  // is not optimal in terms of the O(N) performance but typically if we have a\n  // lot of determinized states that differ only in weight then the input\n  // probably was pathological in some way, or even non-determinizable.\n  //   We don't quantize the weights, in order to avoid inexactness in simple\n  //   cases.\n  // Instead we apply the delta when comparing subsets for equality, and allow a\n  // small difference.\n\n  class SubsetKey {\n   public:\n    size_t operator()(const std::vector<Element> *subset)\n        const {  // hashes only the state and string.\n      size_t hash = 0, factor = 1;\n      for (typename std::vector<Element>::const_iterator iter = subset->begin();\n           iter != subset->end(); ++iter) {\n        hash *= factor;\n        hash += iter->state + reinterpret_cast<size_t>(iter->string);\n        factor *= 23531;  // these numbers are primes.\n      }\n      return hash;\n    }\n  };\n\n  // This is the equality operator on subsets.  It checks for exact match on\n  // state-id and string, and approximate match on weights.\n  class SubsetEqual {\n   public:\n    bool operator()(const std::vector<Element> *s1,\n                    const std::vector<Element> *s2) const {\n      size_t sz = s1->size();\n      assert(sz >= 0);\n      if (sz != s2->size()) return false;\n      typename std::vector<Element>::const_iterator iter1 = s1->begin(),\n                                                    iter1_end = s1->end(),\n                                                    iter2 = s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state || iter1->string != iter2->string ||\n            !ApproxEqual(iter1->weight, iter2->weight, delta_))\n          return false;\n      }\n      return true;\n    }\n    float delta_;\n    explicit SubsetEqual(float delta) : delta_(delta) {}\n    SubsetEqual() : delta_(kDelta) {}\n  };\n\n  // Operator that says whether two Elements have the same states.\n  // Used only for debug.\n  class SubsetEqualStates {\n   public:\n    bool operator()(const std::vector<Element> *s1,\n                    const std::vector<Element> *s2) const {\n      size_t sz = s1->size();\n      assert(sz >= 0);\n      if (sz != s2->size()) return false;\n      typename std::vector<Element>::const_iterator iter1 = s1->begin(),\n                                                    iter1_end = s1->end(),\n                                                    iter2 = s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state) return false;\n      }\n      return true;\n    }\n  };\n\n  // Define the hash type we use to map subsets (in minimal\n  // representation) to OutputStateId.\n  typedef std::unordered_map<const std::vector<Element> *, OutputStateId,\n                             SubsetKey, SubsetEqual>\n      MinimalSubsetHash;\n\n  // Define the hash type we use to map subsets (in initial\n  // representation) to OutputStateId, together with an\n  // extra weight. [note: we interpret the Element.state in here\n  // as an OutputStateId even though it's declared as InputStateId;\n  // these types are the same anyway].\n  typedef std::unordered_map<const std::vector<Element> *, Element, SubsetKey,\n                             SubsetEqual>\n      InitialSubsetHash;\n\n  // converts the representation of the subset from canonical (all states) to\n  // minimal (only states with output symbols on arcs leaving them, and final\n  // states).  Output is not necessarily normalized, even if input_subset was.\n  void ConvertToMinimal(std::vector<Element> *subset) {\n    assert(!subset->empty());\n    typename std::vector<Element>::iterator cur_in = subset->begin(),\n                                            cur_out = subset->begin(),\n                                            end = subset->end();\n    while (cur_in != end) {\n      if (IsIsymbolOrFinal(cur_in->state)) {  // keep it...\n        *cur_out = *cur_in;\n        cur_out++;\n      }\n      cur_in++;\n    }\n    subset->resize(cur_out - subset->begin());\n  }\n\n  // Takes a minimal, normalized subset, and converts it to an OutputStateId.\n  // Involves a hash lookup, and possibly adding a new OutputStateId.\n  // If it creates a new OutputStateId, it adds it to the queue.\n  OutputStateId MinimalToStateId(const std::vector<Element> &subset) {\n    typename MinimalSubsetHash::const_iterator iter =\n        minimal_hash_.find(&subset);\n    if (iter != minimal_hash_.end())  // Found a matching subset.\n      return iter->second;\n    OutputStateId ans = static_cast<OutputStateId>(output_arcs_.size());\n    std::vector<Element> *subset_ptr = new std::vector<Element>(subset);\n    output_states_.push_back(subset_ptr);\n    num_elems_ += subset_ptr->size();\n    output_arcs_.push_back(std::vector<TempArc>());\n    minimal_hash_[subset_ptr] = ans;\n    queue_.push_back(ans);\n    return ans;\n  }\n\n  // Given a normalized initial subset of elements (i.e. before epsilon\n  // closure), compute the corresponding output-state.\n  OutputStateId InitialToStateId(const std::vector<Element> &subset_in,\n                                 Weight *remaining_weight,\n                                 StringId *common_prefix) {\n    typename InitialSubsetHash::const_iterator iter =\n        initial_hash_.find(&subset_in);\n    if (iter != initial_hash_.end()) {  // Found a matching subset.\n      const Element &elem = iter->second;\n      *remaining_weight = elem.weight;\n      *common_prefix = elem.string;\n      if (elem.weight == Weight::Zero()) KALDI_WARN << \"Zero weight!\";  // TEMP\n      return elem.state;\n    }\n    // else no matching subset-- have to work it out.\n    std::vector<Element> subset(subset_in);\n    // Follow through epsilons.  Will add no duplicate states.  note: after\n    // EpsilonClosure, it is the same as \"canonical\" subset, except not\n    // normalized (actually we never compute the normalized canonical subset,\n    // only the normalized minimal one).\n    EpsilonClosure(&subset);    // follow epsilons.\n    ConvertToMinimal(&subset);  // remove all but emitting and final states.\n\n    Element elem;  // will be used to store remaining weight and string, and\n                   // OutputStateId, in initial_hash_;\n    NormalizeSubset(&subset, &elem.weight,\n                    &elem.string);  // normalize subset; put\n    // common string and weight in \"elem\".  The subset is now a minimal,\n    // normalized subset.\n\n    OutputStateId ans = MinimalToStateId(subset);\n    *remaining_weight = elem.weight;\n    *common_prefix = elem.string;\n    if (elem.weight == Weight::Zero()) KALDI_WARN << \"Zero weight!\";  // TEMP\n\n    // Before returning \"ans\", add the initial subset to the hash,\n    // so that we can bypass the epsilon-closure etc., next time\n    // we process the same initial subset.\n    std::vector<Element> *initial_subset_ptr =\n        new std::vector<Element>(subset_in);\n    elem.state = ans;\n    initial_hash_[initial_subset_ptr] = elem;\n    num_elems_ += initial_subset_ptr->size();  // keep track of memory usage.\n    return ans;\n  }\n\n  // returns the Compare value (-1 if a < b, 0 if a == b, 1 if a > b) according\n  // to the ordering we defined on strings for the CompactLatticeWeightTpl.\n  // see function\n  // inline int Compare (const CompactLatticeWeightTpl<WeightType,IntType> &w1,\n  //                     const CompactLatticeWeightTpl<WeightType,IntType> &w2)\n  // in lattice-weight.h.\n  // this is the same as that, but optimized for our data structures.\n  inline int Compare(const Weight &a_w, StringId a_str, const Weight &b_w,\n                     StringId b_str) const {\n    int weight_comp = fst::Compare(a_w, b_w);\n    if (weight_comp != 0) return weight_comp;\n    // now comparing strings.\n    if (a_str == b_str) return 0;\n    std::vector<IntType> a_vec, b_vec;\n    repository_.ConvertToVector(a_str, &a_vec);\n    repository_.ConvertToVector(b_str, &b_vec);\n    // First compare their lengths.\n    int a_len = a_vec.size(), b_len = b_vec.size();\n    // use opposite order on the string lengths (c.f. Compare in\n    // lattice-weight.h)\n    if (a_len > b_len)\n      return -1;\n    else if (a_len < b_len)\n      return 1;\n    for (int i = 0; i < a_len; i++) {\n      if (a_vec[i] < b_vec[i])\n        return -1;\n      else if (a_vec[i] > b_vec[i])\n        return 1;\n    }\n    assert(\n        0);  // because we checked if a_str == b_str above, shouldn't reach here\n    return 0;\n  }\n\n  // This function computes epsilon closure of subset of states by following\n  // epsilon links. Called by InitialToStateId and Initialize. Has no side\n  // effects except on the string repository.  The \"output_subset\" is not\n  // necessarily normalized (in the sense of there being no common substring),\n  // unless input_subset was.\n  void EpsilonClosure(std::vector<Element> *subset) {\n    // at input, subset must have only one example of each StateId.  [will still\n    // be so at output].  This function follows input-epsilons, and augments the\n    // subset accordingly.\n\n    std::deque<Element> queue;\n    std::unordered_map<InputStateId, Element> cur_subset;\n    typedef\n        typename std::unordered_map<InputStateId, Element>::iterator MapIter;\n    typedef typename std::vector<Element>::const_iterator VecIter;\n\n    for (VecIter iter = subset->begin(); iter != subset->end(); ++iter) {\n      queue.push_back(*iter);\n      cur_subset[iter->state] = *iter;\n    }\n\n    // find whether input fst is known to be sorted on input label.\n    bool sorted =\n        ((ifst_->Properties(kILabelSorted, false) & kILabelSorted) != 0);\n    bool replaced_elems = false;  // relates to an optimization, see below.\n    int counter =\n        0;  // stops infinite loops here for non-lattice-determinizable input;\n    // useful in testing.\n    while (queue.size() != 0) {\n      Element elem = queue.front();\n      queue.pop_front();\n\n      // The next if-statement is a kind of optimization.  It's to prevent us\n      // unnecessarily repeating the processing of a state.  \"cur_subset\" always\n      // contains only one Element with a particular state.  The issue is that\n      // whenever we modify the Element corresponding to that state in\n      // \"cur_subset\", both the new (optimal) and old (less-optimal) Element\n      // will still be in \"queue\".  The next if-statement stops us from wasting\n      // compute by processing the old Element.\n      if (replaced_elems && cur_subset[elem.state] != elem) continue;\n      if (opts_.max_loop > 0 && counter++ > opts_.max_loop) {\n        KALDI_ERR << \"Lattice determinization aborted since looped more than \"\n                  << opts_.max_loop << \" times during epsilon closure\";\n      }\n      for (ArcIterator<Fst<Arc> > aiter(*ifst_, elem.state); !aiter.Done();\n           aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        if (sorted && arc.ilabel != 0)\n          break;  // Break from the loop: due to sorting there will be no\n        // more transitions with epsilons as input labels.\n        if (arc.ilabel == 0 &&\n            arc.weight != Weight::Zero()) {  // Epsilon transition.\n          Element next_elem;\n          next_elem.state = arc.nextstate;\n          next_elem.weight = Times(elem.weight, arc.weight);\n          // now must append strings\n          if (arc.olabel == 0)\n            next_elem.string = elem.string;\n          else\n            next_elem.string = repository_.Successor(elem.string, arc.olabel);\n\n          MapIter iter = cur_subset.find(next_elem.state);\n          if (iter == cur_subset.end()) {\n            // was no such StateId: insert and add to queue.\n            cur_subset[next_elem.state] = next_elem;\n            queue.push_back(next_elem);\n          } else {\n            // was not inserted because one already there.  In normal\n            // determinization we'd add the weights.  Here, we find which one\n            // has the better weight, and keep its corresponding string.\n            int comp = Compare(next_elem.weight, next_elem.string,\n                               iter->second.weight, iter->second.string);\n            if (comp ==\n                1) {  // next_elem is better, so use its (weight, string)\n              iter->second.string = next_elem.string;\n              iter->second.weight = next_elem.weight;\n              queue.push_back(next_elem);\n              replaced_elems = true;\n            }\n            // else it is the same or worse, so use original one.\n          }\n        }\n      }\n    }\n\n    {  // copy cur_subset to subset.\n      subset->clear();\n      subset->reserve(cur_subset.size());\n      MapIter iter = cur_subset.begin(), end = cur_subset.end();\n      for (; iter != end; ++iter) subset->push_back(iter->second);\n      // sort by state ID, because the subset hash function is\n      // order-dependent(see SubsetKey)\n      std::sort(subset->begin(), subset->end());\n    }\n  }\n\n  // This function works out the final-weight of the determinized state.\n  // called by ProcessSubset.\n  // Has no side effects except on the variable repository_, and output_arcs_.\n\n  void ProcessFinal(OutputStateId output_state) {\n    const std::vector<Element> &minimal_subset =\n        *(output_states_[output_state]);\n    // processes final-weights for this subset.\n\n    // minimal_subset may be empty if the graphs is not connected/trimmed, I\n    // think, do don't check that it's nonempty.\n    bool is_final = false;\n    StringId final_string = NULL;  // = NULL to keep compiler happy.\n    Weight final_weight = Weight::Zero();\n    typename std::vector<Element>::const_iterator iter = minimal_subset.begin(),\n                                                  end = minimal_subset.end();\n    for (; iter != end; ++iter) {\n      const Element &elem = *iter;\n      Weight this_final_weight = Times(elem.weight, ifst_->Final(elem.state));\n      StringId this_final_string = elem.string;\n      if (this_final_weight != Weight::Zero() &&\n          (!is_final || Compare(this_final_weight, this_final_string,\n                                final_weight, final_string) == 1)) {  // the new\n        // (weight, string) pair is more in semiring than our current\n        // one.\n        is_final = true;\n        final_weight = this_final_weight;\n        final_string = this_final_string;\n      }\n    }\n    if (is_final) {\n      // store final weights in TempArc structure, just like a transition.\n      TempArc temp_arc;\n      temp_arc.ilabel = 0;\n      temp_arc.nextstate =\n          kNoStateId;  // special marker meaning \"final weight\".\n      temp_arc.string = final_string;\n      temp_arc.weight = final_weight;\n      output_arcs_[output_state].push_back(temp_arc);\n      num_arcs_++;\n    }\n  }\n\n  // NormalizeSubset normalizes the subset \"elems\" by\n  // removing any common string prefix (putting it in common_str),\n  // and dividing by the total weight (putting it in tot_weight).\n  void NormalizeSubset(std::vector<Element> *elems, Weight *tot_weight,\n                       StringId *common_str) {\n    if (elems->empty()) {              // just set common_str, tot_weight\n      KALDI_WARN << \"[empty subset]\";  // TEMP\n      // to defaults and return...\n      *common_str = repository_.EmptyString();\n      *tot_weight = Weight::Zero();\n      return;\n    }\n    size_t size = elems->size();\n    std::vector<IntType> common_prefix;\n    repository_.ConvertToVector((*elems)[0].string, &common_prefix);\n    Weight weight = (*elems)[0].weight;\n    for (size_t i = 1; i < size; i++) {\n      weight = Plus(weight, (*elems)[i].weight);\n      repository_.ReduceToCommonPrefix((*elems)[i].string, &common_prefix);\n    }\n    assert(weight != Weight::Zero());  // we made sure to ignore arcs with zero\n    // weights on them, so we shouldn't have zero here.\n    size_t prefix_len = common_prefix.size();\n    for (size_t i = 0; i < size; i++) {\n      (*elems)[i].weight = Divide((*elems)[i].weight, weight, DIVIDE_LEFT);\n      (*elems)[i].string =\n          repository_.RemovePrefix((*elems)[i].string, prefix_len);\n    }\n    *common_str = repository_.ConvertFromVector(common_prefix);\n    *tot_weight = weight;\n  }\n\n  // Take a subset of Elements that is sorted on state, and\n  // merge any Elements that have the same state (taking the best\n  // (weight, string) pair in the semiring).\n  void MakeSubsetUnique(std::vector<Element> *subset) {\n    typedef typename std::vector<Element>::iterator IterType;\n\n    // This assert is designed to fail (usually) if the subset is not sorted on\n    // state.\n    assert(subset->size() < 2 || (*subset)[0].state <= (*subset)[1].state);\n\n    IterType cur_in = subset->begin(), cur_out = cur_in, end = subset->end();\n    size_t num_out = 0;\n    // Merge elements with same state-id\n    while (cur_in != end) {  // while we have more elements to process.\n      // At this point, cur_out points to location of next place we want to put\n      // an element, cur_in points to location of next element we want to\n      // process.\n      if (cur_in != cur_out) *cur_out = *cur_in;\n      cur_in++;\n      while (cur_in != end && cur_in->state == cur_out->state) {\n        if (Compare(cur_in->weight, cur_in->string, cur_out->weight,\n                    cur_out->string) == 1) {\n          // if *cur_in > *cur_out in semiring, then take *cur_in.\n          cur_out->string = cur_in->string;\n          cur_out->weight = cur_in->weight;\n        }\n        cur_in++;\n      }\n      cur_out++;\n      num_out++;\n    }\n    subset->resize(num_out);\n  }\n\n  // ProcessTransition is called from \"ProcessTransitions\".  Broken out for\n  // clarity.  Processes a transition from state \"state\".  The set of Elements\n  // represents a set of next-states with associated weights and strings, each\n  // one arising from an arc from some state in a determinized-state; the\n  // next-states are not necessarily unique (i.e. there may be >1 entry\n  // associated with each), and any such sets of Elements have to be merged\n  // within this routine (we take the [weight, string] pair that's better in the\n  // semiring).\n  void ProcessTransition(OutputStateId state, Label ilabel,\n                         std::vector<Element> *subset) {\n    MakeSubsetUnique(subset);  // remove duplicates with the same state.\n\n    StringId common_str;\n    Weight tot_weight;\n    NormalizeSubset(subset, &tot_weight, &common_str);\n\n    OutputStateId nextstate;\n    {\n      Weight next_tot_weight;\n      StringId next_common_str;\n      nextstate = InitialToStateId(*subset, &next_tot_weight, &next_common_str);\n      common_str = repository_.Concatenate(common_str, next_common_str);\n      tot_weight = Times(tot_weight, next_tot_weight);\n    }\n\n    // Now add an arc to the next state (would have been created if necessary by\n    // InitialToStateId).\n    TempArc temp_arc;\n    temp_arc.ilabel = ilabel;\n    temp_arc.nextstate = nextstate;\n    temp_arc.string = common_str;\n    temp_arc.weight = tot_weight;\n    output_arcs_[state].push_back(temp_arc);  // record the arc.\n    num_arcs_++;\n  }\n\n  // \"less than\" operator for pair<Label, Element>.   Used in\n  // ProcessTransitions. Lexicographical order, which only compares the state\n  // when ordering the \"Element\" member of the pair.\n\n  class PairComparator {\n   public:\n    inline bool operator()(const std::pair<Label, Element> &p1,\n                           const std::pair<Label, Element> &p2) {\n      if (p1.first < p2.first) {\n        return true;\n      } else if (p1.first > p2.first) {\n        return false;\n      } else {\n        return p1.second.state < p2.second.state;\n      }\n    }\n  };\n\n  // ProcessTransitions processes emitting transitions (transitions\n  // with ilabels) out of this subset of states.\n  // Does not consider final states.  Breaks the emitting transitions up by\n  // ilabel, and creates a new transition in the determinized FST for each\n  // unique ilabel. Does this by creating a big vector of pairs <Label, Element>\n  // and then sorting them using a lexicographical ordering, and calling\n  // ProcessTransition for each range with the same ilabel. Side effects on\n  // repository, and (via ProcessTransition) on Q_, hash_, and output_arcs_.\n\n  void ProcessTransitions(OutputStateId output_state) {\n    const std::vector<Element> &minimal_subset =\n        *(output_states_[output_state]);\n    // it's possible that minimal_subset could be empty if there are\n    // unreachable parts of the graph, so don't check that it's nonempty.\n    std::vector<std::pair<Label, Element> > &all_elems(\n        all_elems_tmp_);  // use class member\n    // to avoid memory allocation/deallocation.\n    {\n      // Push back into \"all_elems\", elements corresponding to all\n      // non-epsilon-input transitions out of all states in \"minimal_subset\".\n      typename std::vector<Element>::const_iterator iter =\n                                                        minimal_subset.begin(),\n                                                    end = minimal_subset.end();\n      for (; iter != end; ++iter) {\n        const Element &elem = *iter;\n        for (ArcIterator<Fst<Arc> > aiter(*ifst_, elem.state); !aiter.Done();\n             aiter.Next()) {\n          const Arc &arc = aiter.Value();\n          if (arc.ilabel != 0 &&\n              arc.weight != Weight::Zero()) {  // Non-epsilon transition --\n                                               // ignore epsilons here.\n            std::pair<Label, Element> this_pr;\n            this_pr.first = arc.ilabel;\n            Element &next_elem(this_pr.second);\n            next_elem.state = arc.nextstate;\n            next_elem.weight = Times(elem.weight, arc.weight);\n            if (arc.olabel == 0)  // output epsilon\n              next_elem.string = elem.string;\n            else\n              next_elem.string = repository_.Successor(elem.string, arc.olabel);\n            all_elems.push_back(this_pr);\n          }\n        }\n      }\n    }\n    PairComparator pc;\n    std::sort(all_elems.begin(), all_elems.end(), pc);\n    // now sorted first on input label, then on state.\n    typedef typename std::vector<std::pair<Label, Element> >::const_iterator\n        PairIter;\n    PairIter cur = all_elems.begin(), end = all_elems.end();\n    std::vector<Element> this_subset;\n    while (cur != end) {\n      // Process ranges that share the same input symbol.\n      Label ilabel = cur->first;\n      this_subset.clear();\n      while (cur != end && cur->first == ilabel) {\n        this_subset.push_back(cur->second);\n        cur++;\n      }\n      // We now have a subset for this ilabel.\n      assert(!this_subset.empty());  // temp.\n      ProcessTransition(output_state, ilabel, &this_subset);\n    }\n    all_elems.clear();  // as it's a class variable-- want it to stay\n    // emtpy.\n  }\n\n  // ProcessState does the processing of a determinized state, i.e. it creates\n  // transitions out of it and the final-probability if any.\n  void ProcessState(OutputStateId output_state) {\n    ProcessFinal(output_state);\n    ProcessTransitions(output_state);\n  }\n\n  void Debug() {  // this function called if you send a signal\n    // SIGUSR1 to the process (and it's caught by the handler in\n    // fstdeterminizestar).  It prints out some traceback\n    // info and exits.\n\n    KALDI_WARN << \"Debug function called (probably SIGUSR1 caught)\";\n    // free up memory from the hash as we need a little memory\n    {\n      MinimalSubsetHash hash_tmp;\n      hash_tmp.swap(minimal_hash_);\n    }\n\n    if (output_arcs_.size() <= 2) {\n      KALDI_ERR << \"Nothing to trace back\";\n    }\n    size_t max_state = output_arcs_.size() - 2;  // Don't take the last\n    // one as we might be halfway into constructing it.\n\n    std::vector<OutputStateId> predecessor(max_state + 1, kNoStateId);\n    for (size_t i = 0; i < max_state; i++) {\n      for (size_t j = 0; j < output_arcs_[i].size(); j++) {\n        OutputStateId nextstate = output_arcs_[i][j].nextstate;\n        // Always find an earlier-numbered predecessor; this\n        // is always possible because of the way the algorithm\n        // works.\n        if (nextstate <= max_state && nextstate > i) predecessor[nextstate] = i;\n      }\n    }\n    std::vector<std::pair<Label, StringId> > traceback;\n    // 'traceback' is a pair of (ilabel, olabel-seq).\n    OutputStateId cur_state = max_state;  // A recently constructed state.\n\n    while (cur_state != 0 && cur_state != kNoStateId) {\n      OutputStateId last_state = predecessor[cur_state];\n      std::pair<Label, StringId> p;\n      size_t i;\n      for (i = 0; i < output_arcs_[last_state].size(); i++) {\n        if (output_arcs_[last_state][i].nextstate == cur_state) {\n          p.first = output_arcs_[last_state][i].ilabel;\n          p.second = output_arcs_[last_state][i].string;\n          traceback.push_back(p);\n          break;\n        }\n      }\n      KALDI_ASSERT(i != output_arcs_[last_state].size());  // Or fell off loop.\n      cur_state = last_state;\n    }\n    if (cur_state == kNoStateId)\n      KALDI_WARN << \"Traceback did not reach start state \"\n                 << \"(possibly debug-code error)\";\n\n    std::stringstream ss;\n    ss << \"Traceback follows in format \"\n       << \"ilabel (olabel olabel) ilabel (olabel) ... :\";\n    for (ssize_t i = traceback.size() - 1; i >= 0; i--) {\n      ss << ' ' << traceback[i].first << \" ( \";\n      std::vector<Label> seq;\n      repository_.ConvertToVector(traceback[i].second, &seq);\n      for (size_t j = 0; j < seq.size(); j++) ss << seq[j] << ' ';\n      ss << ')';\n    }\n    KALDI_ERR << ss.str();\n  }\n\n  bool IsIsymbolOrFinal(InputStateId state) {  // returns true if this state\n    // of the input FST either is final or has an osymbol on an arc out of it.\n    // Uses the vector isymbol_or_final_ as a cache for this info.\n    assert(state >= 0);\n    if (isymbol_or_final_.size() <= state)\n      isymbol_or_final_.resize(state + 1, static_cast<char>(OSF_UNKNOWN));\n    if (isymbol_or_final_[state] == static_cast<char>(OSF_NO))\n      return false;\n    else if (isymbol_or_final_[state] == static_cast<char>(OSF_YES))\n      return true;\n    // else work it out...\n    isymbol_or_final_[state] = static_cast<char>(OSF_NO);\n    if (ifst_->Final(state) != Weight::Zero())\n      isymbol_or_final_[state] = static_cast<char>(OSF_YES);\n    for (ArcIterator<Fst<Arc> > aiter(*ifst_, state); !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel != 0 && arc.weight != Weight::Zero()) {\n        isymbol_or_final_[state] = static_cast<char>(OSF_YES);\n        return true;\n      }\n    }\n    return IsIsymbolOrFinal(state);  // will only recurse once.\n  }\n\n  void InitializeDeterminization() {\n    if (ifst_->Properties(kExpanded, false) != 0) {  // if we know the number of\n      // states in ifst_, it might be a bit more efficient\n      // to pre-size the hashes so we're not constantly rebuilding them.\n#if !(__GNUC__ == 4 && __GNUC_MINOR__ == 0)\n      StateId num_states =\n          down_cast<const ExpandedFst<Arc> *, const Fst<Arc> >(ifst_)\n              ->NumStates();\n      minimal_hash_.rehash(num_states / 2 + 3);\n      initial_hash_.rehash(num_states / 2 + 3);\n#endif\n    }\n    InputStateId start_id = ifst_->Start();\n    if (start_id != kNoStateId) {\n      /* Insert determinized-state corresponding to the start state into hash\n         and queue.  Unlike all the other states, we don't \"normalize\" the\n         representation of this determinized-state before we put it into\n         minimal_hash_.  This is actually what we want, as otherwise we'd have\n         problems dealing with any extra weight and string and might have to\n         create a \"super-initial\" state which would make the output\n         nondeterministic.  Normalization is only needed to make the\n         determinized output more minimal anyway, it's not needed for\n         correctness. Note, we don't put anything in the initial_hash_.  The\n         initial_hash_ is only a lookaside buffer anyway, so this isn't a\n         problem-- it will get populated later if it needs to be.\n      */\n      Element elem;\n      elem.state = start_id;\n      elem.weight = Weight::One();\n      elem.string = repository_.EmptyString();  // Id of empty sequence.\n      std::vector<Element> subset;\n      subset.push_back(elem);\n      EpsilonClosure(&subset);    // follow through epsilon-inputs links\n      ConvertToMinimal(&subset);  // remove all but final states and\n      // states with input-labels on arcs out of them.\n      std::vector<Element> *subset_ptr = new std::vector<Element>(subset);\n      assert(output_arcs_.empty() && output_states_.empty());\n      // add the new state...\n      output_states_.push_back(subset_ptr);\n      output_arcs_.push_back(std::vector<TempArc>());\n      OutputStateId initial_state = 0;\n      minimal_hash_[subset_ptr] = initial_state;\n      queue_.push_back(initial_state);\n    }\n  }\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(LatticeDeterminizer);\n\n  std::vector<std::vector<Element> *>\n      output_states_;  // maps from output state to\n                       // minimal representation [normalized].\n                       // View pointers as owned in\n                       // minimal_hash_.\n  std::vector<std::vector<TempArc> >\n      output_arcs_;  // essentially an FST in our format.\n\n  int num_arcs_;   // keep track of memory usage: number of arcs in output_arcs_\n  int num_elems_;  // keep track of memory usage: number of elems in\n                   // output_states_\n\n  const Fst<Arc> *ifst_;\n  DeterminizeLatticeOptions opts_;\n  SubsetKey hasher_;  // object that computes keys-- has no data members.\n  SubsetEqual\n      equal_;  // object that compares subsets-- only data member is delta_.\n  bool determinized_;  // set to true when user called Determinize(); used to\n                       // make\n  // sure this object is used correctly.\n  MinimalSubsetHash\n      minimal_hash_;  // hash from Subset to OutputStateId.  Subset is \"minimal\n                      // representation\" (only include final and states and\n                      // states with nonzero ilabel on arc out of them.  Owns\n                      // the pointers in its keys.\n  InitialSubsetHash initial_hash_;  // hash from Subset to Element, which\n                                    // represents the OutputStateId together\n                                    // with an extra weight and string.  Subset\n                                    // is \"initial representation\".  The extra\n                                    // weight and string is needed because after\n                                    // we convert to minimal representation and\n                                    // normalize, there may be an extra weight\n                                    // and string.  Owns the pointers\n                                    // in its keys.\n  std::vector<OutputStateId>\n      queue_;  // Queue of output-states to process.  Starts with\n  // state 0, and increases and then (hopefully) decreases in length during\n  // determinization.  LIFO queue (queue discipline doesn't really matter).\n\n  std::vector<std::pair<Label, Element> >\n      all_elems_tmp_;  // temporary vector used in ProcessTransitions.\n\n  enum IsymbolOrFinal { OSF_UNKNOWN = 0, OSF_NO = 1, OSF_YES = 2 };\n\n  std::vector<char> isymbol_or_final_;  // A kind of cache; it says whether\n  // each state is (emitting or final) where emitting means it has at least one\n  // non-epsilon output arc.  Only accessed by IsIsymbolOrFinal()\n\n  LatticeStringRepository<IntType>\n      repository_;  // defines a compact and fast way of\n  // storing sequences of labels.\n};\n\n// normally Weight would be LatticeWeight<float> (which has two floats),\n// or possibly TropicalWeightTpl<float>, and IntType would be int32.\ntemplate <class Weight, class IntType>\nbool DeterminizeLattice(const Fst<ArcTpl<Weight> > &ifst,\n                        MutableFst<ArcTpl<Weight> > *ofst,\n                        DeterminizeLatticeOptions opts, bool *debug_ptr) {\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  ofst->SetOutputSymbols(ifst.OutputSymbols());\n  LatticeDeterminizer<Weight, IntType> det(ifst, opts);\n  if (!det.Determinize(debug_ptr)) return false;\n  det.Output(ofst);\n  return true;\n}\n\n// normally Weight would be LatticeWeight<float> (which has two floats),\n// or possibly TropicalWeightTpl<float>, and IntType would be int32.\ntemplate <class Weight, class IntType>\nbool DeterminizeLattice(\n    const Fst<ArcTpl<Weight> > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n    DeterminizeLatticeOptions opts, bool *debug_ptr) {\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  ofst->SetOutputSymbols(ifst.OutputSymbols());\n  LatticeDeterminizer<Weight, IntType> det(ifst, opts);\n  if (!det.Determinize(debug_ptr)) return false;\n  det.Output(ofst);\n  return true;\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_DETERMINIZE_LATTICE_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/determinize-lattice.h",
    "content": "// fstext/determinize-lattice.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_DETERMINIZE_LATTICE_H_\n#define KALDI_FSTEXT_DETERMINIZE_LATTICE_H_\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <vector>\n#include \"fstext/lattice-weight.h\"\n\nnamespace fst {\n\n/// \\addtogroup fst_extensions\n///  @{\n\n// For example of usage, see test-determinize-lattice.cc\n\n/*\n   DeterminizeLattice implements a special form of determinization\n   with epsilon removal, optimized for a phase of lattice generation.\n   Its input is an FST with weight-type BaseWeightType (usually a pair of\n   floats, with a lexicographical type of order, such as\n   LatticeWeightTpl<float>). Typically this would be a state-level lattice, with\n   input symbols equal to words, and output-symbols equal to p.d.f's (so like\n   the inverse of HCLG).  Imagine representing this as an acceptor of type\n   CompactLatticeWeightTpl<float>, in which the input/output symbols are words,\n   and the weights contain the original weights together with strings (with zero\n   or one symbol in them) containing the original output labels (the p.d.f.'s).\n   We determinize this using acceptor determinization with epsilon removal.\n   Remember (from lattice-weight.h) that CompactLatticeWeightTpl has a special\n   kind of semiring where we always take the string corresponding to the best\n   cost (of type BaseWeightType), and discard the other.  This corresponds to\n   taking the best output-label sequence (of p.d.f.'s) for each input-label\n   sequence (of words).  We couldn't use the Gallic weight for this, or it would\n   die as soon as it detected that the input FST was non-functional.  In our\n   case, any acyclic FST (and many cyclic ones) can be determinized. We assume\n   that there is a function Compare(const BaseWeightType &a, const\n   BaseWeightType &b) that returns (-1, 0, 1) according to whether (a < b, a ==\n   b, a > b) in the total order on the BaseWeightType... this information should\n   be the same as NaturalLess would give, but it's more efficient to do it this\n   way. You can define this for things like TropicalWeight if you need to\n   instantiate this class for that weight type.\n\n   We implement this determinization in a special way to make it efficient for\n   the types of FSTs that we will apply it to.  One issue is that if we\n   explicitly represent the strings (in CompactLatticeWeightTpl) as vectors of\n   type vector<IntType>, the algorithm takes time quadratic in the length of\n   words (in states), because propagating each arc involves copying a whole\n   vector (of integers representing p.d.f.'s).  Instead we use a hash structure\n   where each string is a pointer (Entry*), and uses a hash from (Entry*,\n   IntType), to the successor string (and a way to get the latest IntType and\n   the ancestor Entry*).  [this is the class LatticeStringRepository].\n\n   Another issue is that rather than representing a determinized-state as a\n   collection of (state, weight), we represent it in a couple of reduced forms.\n   Suppose a determinized-state is a collection of (state, weight) pairs; call\n   this the \"canonical representation\".  Note: these collections are always\n   normalized to remove any common weight and string part.  Define end-states as\n   the subset of states that have an arc out of them with a label on, or are\n   final.  If we represent a determinized-state a the set of just its\n   (end-state, weight) pairs, this will be a valid and more compact\n   representation, and will lead to a smaller set of determinized states (like\n   early minimization).  Call this collection of (end-state, weight) pairs the\n   \"minimal representation\".  As a mechanism to reduce compute, we can also\n   consider another representation. In the determinization algorithm, we start\n   off with a set of (begin-state, weight) pairs (where the \"begin-states\" are\n   initial or have a label on the transition into them), and the \"canonical\n   representation\" consists of the epsilon-closure of this set (i.e. follow\n   epsilons).  Call this set of (begin-state, weight) pairs, appropriately\n   normalized, the \"initial representation\".  If two initial representations are\n   the same, the \"canonical representation\" and hence the \"minimal\n   representation\" will be the same.  We can use this to reduce compute.  Note\n   that if two initial representations are different, this does not preclude the\n   other representations from being the same.\n\n*/\n\nstruct DeterminizeLatticeOptions {\n  float delta;  // A small offset used to measure equality of weights.\n  int max_mem;  // If >0, determinization will fail and return false\n  // when the algorithm's (approximate) memory consumption crosses this\n  // threshold.\n  int max_loop;  // If >0, can be used to detect non-determinizable input\n  // (a case that wouldn't be caught by max_mem).\n  DeterminizeLatticeOptions() : delta(kDelta), max_mem(-1), max_loop(-1) {}\n};\n\n/**\n    This function implements the normal version of DeterminizeLattice, in which\n    the output strings are represented using sequences of arcs, where all but\n    the first one has an epsilon on the input side.  The debug_ptr argument is\n    an optional pointer to a bool that, if it becomes true while the algorithm\n    is executing, the algorithm will print a traceback and terminate (used in\n    fstdeterminizestar.cc debug non-terminating determinization).  More\n    efficient if ifst is arc-sorted on input label.  If the number of arcs gets\n    more than max_states, it will throw std::runtime_error (otherwise this code\n    does not use exceptions).  This is mainly useful for debug.  */\ntemplate <class Weight, class IntType>\nbool DeterminizeLattice(\n    const Fst<ArcTpl<Weight> > &ifst, MutableFst<ArcTpl<Weight> > *ofst,\n    DeterminizeLatticeOptions opts = DeterminizeLatticeOptions(),\n    bool *debug_ptr = NULL);\n\n/*  This is a version of DeterminizeLattice with a slightly more \"natural\"\n   output format, where the output sequences are encoded using the\n   CompactLatticeArcTpl template (i.e. the sequences of output symbols are\n   represented directly as strings) More efficient if ifst is arc-sorted on\n   input label. If the #arcs gets more than max_arcs, it will throw\n   std::runtime_error (otherwise this code does not use exceptions).  This is\n   mainly useful for debug.\n*/\ntemplate <class Weight, class IntType>\nbool DeterminizeLattice(\n    const Fst<ArcTpl<Weight> > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n    DeterminizeLatticeOptions opts = DeterminizeLatticeOptions(),\n    bool *debug_ptr = NULL);\n\n/// @} end \"addtogroup fst_extensions\"\n\n}  // end namespace fst\n\n#include \"fstext/determinize-lattice-inl.h\"\n\n#endif  // KALDI_FSTEXT_DETERMINIZE_LATTICE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/determinize-star-inl.h",
    "content": "// fstext/determinize-star-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Jan Silovsky\n//           2015 Hainan Xu\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_DETERMINIZE_STAR_INL_H_\n#define KALDI_FSTEXT_DETERMINIZE_STAR_INL_H_\n// Do not include this file directly.  It is included by determinize-star.h\n\n#include <algorithm>\n#include <climits>\n#include <deque>\n#include <limits>\n#include <string>\n#include <unordered_map>\n#include <utility>\n#include <vector>\nusing std::unordered_map;\n\n#include \"base/kaldi-error.h\"\n\nnamespace fst {\n\n// This class maps back and forth from/to integer id's to sequences of strings.\n// used in determinization algorithm.\n\ntemplate <class Label, class StringId>\nclass StringRepository {\n  // Label and StringId are both integer types, possibly the same.\n  // This is a utility that maps back and forth between a vector<Label> and\n  // StringId representation of sequences of Labels.  It is to save memory, and\n  // to save compute. We treat sequences of length zero and one separately, for\n  // efficiency.\n\n public:\n  class VectorKey {  // Hash function object.\n   public:\n    size_t operator()(const std::vector<Label> *vec) const {\n      assert(vec != NULL);\n      size_t hash = 0, factor = 1;\n      for (typename std::vector<Label>::const_iterator it = vec->begin();\n           it != vec->end(); it++) {\n        hash += factor * (*it);\n        factor *= 103333;  // just an arbitrary prime number.\n      }\n      return hash;\n    }\n  };\n  class VectorEqual {  // Equality-operator function object.\n   public:\n    size_t operator()(const std::vector<Label> *vec1,\n                      const std::vector<Label> *vec2) const {\n      return (*vec1 == *vec2);\n    }\n  };\n\n  typedef unordered_map<const std::vector<Label> *, StringId, VectorKey,\n                        VectorEqual>\n      MapType;\n\n  StringId IdOfEmpty() { return no_symbol; }\n\n  StringId IdOfLabel(Label l) {\n    if (l >= 0 && l <= (Label)single_symbol_range) {\n      return l + single_symbol_start;\n    } else {\n      // l is out of the allowed range so we have to treat it as a sequence of\n      // length one.  Should be v. rare.\n      std::vector<Label> v;\n      v.push_back(l);\n      return IdOfSeqInternal(v);\n    }\n  }\n\n  StringId IdOfSeq(\n      const std::vector<Label> &v) {  // also works for sizes 0 and 1.\n    size_t sz = v.size();\n    if (sz == 0)\n      return no_symbol;\n    else if (v.size() == 1)\n      return IdOfLabel(v[0]);\n    else\n      return IdOfSeqInternal(v);\n  }\n\n  inline bool IsEmptyString(StringId id) { return id == no_symbol; }\n  void SeqOfId(StringId id, std::vector<Label> *v) {\n    if (id == no_symbol) {\n      v->clear();\n    } else if (id >= single_symbol_start) {\n      v->resize(1);\n      (*v)[0] = id - single_symbol_start;\n    } else {\n      assert(static_cast<size_t>(id) < vec_.size());\n      *v = *(vec_[id]);\n    }\n  }\n  StringId RemovePrefix(StringId id, size_t prefix_len) {\n    if (prefix_len == 0) {\n      return id;\n    } else {\n      std::vector<Label> v;\n      SeqOfId(id, &v);\n      size_t sz = v.size();\n      assert(sz >= prefix_len);\n      std::vector<Label> v_noprefix(sz - prefix_len);\n      for (size_t i = 0; i < sz - prefix_len; i++)\n        v_noprefix[i] = v[i + prefix_len];\n      return IdOfSeq(v_noprefix);\n    }\n  }\n\n  StringRepository() {\n    // The following are really just constants but don't want to complicate\n    // compilation so make them class variables.  Due to the brokenness of\n    // <limits>, they can't be accessed as constants.\n    string_end = (std::numeric_limits<StringId>::max() / 2) -\n                 1;  // all hash values must be <= this.\n    no_symbol = (std::numeric_limits<StringId>::max() /\n                 2);  // reserved for empty sequence.\n    single_symbol_start = (std::numeric_limits<StringId>::max() / 2) + 1;\n    single_symbol_range =\n        std::numeric_limits<StringId>::max() - single_symbol_start;\n  }\n  void Destroy() {\n    for (typename std::vector<std::vector<Label> *>::iterator iter =\n             vec_.begin();\n         iter != vec_.end(); ++iter)\n      delete *iter;\n    std::vector<std::vector<Label> *> tmp_vec;\n    tmp_vec.swap(vec_);\n    MapType tmp_map;\n    tmp_map.swap(map_);\n  }\n  ~StringRepository() { Destroy(); }\n\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(StringRepository);\n\n  StringId IdOfSeqInternal(const std::vector<Label> &v) {\n    typename MapType::iterator iter = map_.find(&v);\n    if (iter != map_.end()) {\n      return iter->second;\n    } else {  // must add it to map.\n      StringId this_id = (StringId)vec_.size();\n      std::vector<Label> *v_new = new std::vector<Label>(v);\n      vec_.push_back(v_new);\n      map_[v_new] = this_id;\n      assert(this_id < string_end);  // or we used up the labels.\n      return this_id;\n    }\n  }\n\n  std::vector<std::vector<Label> *> vec_;\n  MapType map_;\n\n  static const StringId string_start =\n      (StringId)0;      // This must not change.  It's assumed.\n  StringId string_end;  // = (numeric_limits<StringId>::max() / 2) - 1; // all\n                        // hash values must be <= this.\n  StringId no_symbol;   // = (numeric_limits<StringId>::max() / 2); // reserved\n                        // for empty sequence.\n  StringId\n      single_symbol_start;  // =  (numeric_limits<StringId>::max() / 2) + 1;\n  StringId single_symbol_range;  // =  numeric_limits<StringId>::max() -\n                                 // single_symbol_start;\n};\n\ntemplate <class F>\nclass DeterminizerStar {\n  typedef typename F::Arc Arc;\n\n public:\n  // Output to Gallic acceptor (so the strings go on weights, and there is a 1-1\n  // correspondence between our states and the states in ofst.  If destroy ==\n  // true, release memory as we go (but we cannot output again).\n  void Output(MutableFst<GallicArc<Arc> > *ofst, bool destroy = true);\n\n  // Output to standard FST.  We will create extra states to handle sequences of\n  // symbols on the output.  If destroy == true, release memory as we go (but we\n  // cannot output again).\n\n  void Output(MutableFst<Arc> *ofst, bool destroy = true);\n\n  // Initializer.  After initializing the object you will typically call\n  // Determinize() and then one of the Output functions.\n  DeterminizerStar(const Fst<Arc> &ifst, float delta = kDelta,\n                   int max_states = -1, bool allow_partial = false)\n      : ifst_(ifst.Copy()),\n        delta_(delta),\n        max_states_(max_states),\n        determinized_(false),\n        allow_partial_(allow_partial),\n        is_partial_(false),\n        equal_(delta),\n        hash_(ifst.Properties(kExpanded, false)\n                  ? down_cast<const ExpandedFst<Arc> *, const Fst<Arc> >(&ifst)\n                                ->NumStates() /\n                            2 +\n                        3\n                  : 20,\n              hasher_, equal_),\n        epsilon_closure_(ifst_, max_states, &repository_, delta) {}\n\n  void Determinize(bool *debug_ptr) {\n    assert(!determinized_);\n    // This determinizes the input fst but leaves it in the \"special format\"\n    // in \"output_arcs_\".\n    InputStateId start_id = ifst_->Start();\n    if (start_id == kNoStateId) {\n      determinized_ = true;\n      return;  // Nothing to do.\n    } else {   // Insert start state into hash and queue.\n      Element elem;\n      elem.state = start_id;\n      elem.weight = Weight::One();\n      elem.string = repository_.IdOfEmpty();  // Id of empty sequence.\n      std::vector<Element> vec;\n      vec.push_back(elem);\n      OutputStateId cur_id = SubsetToStateId(vec);\n      assert(cur_id == 0 && \"Do not call Determinize twice.\");\n    }\n    while (!Q_.empty()) {\n      std::pair<std::vector<Element> *, OutputStateId> cur_pair = Q_.front();\n      Q_.pop_front();\n      ProcessSubset(cur_pair);\n      if (debug_ptr && *debug_ptr) Debug();  // will exit.\n      if (max_states_ > 0 && output_arcs_.size() > max_states_) {\n        if (allow_partial_ == false) {\n          KALDI_ERR << \"Determinization aborted since passed \" << max_states_\n                    << \" states\";\n        } else {\n          KALDI_WARN << \"Determinization terminated since passed \"\n                     << max_states_\n                     << \" states, partial results will be generated\";\n          is_partial_ = true;\n          break;\n        }\n      }\n    }\n    determinized_ = true;\n  }\n\n  bool IsPartial() { return is_partial_; }\n\n  // frees all except output_arcs_, which contains the important info\n  // we need to output.\n  void FreeMostMemory() {\n    if (ifst_) {\n      delete ifst_;\n      ifst_ = NULL;\n    }\n    for (typename SubsetHash::iterator iter = hash_.begin();\n         iter != hash_.end(); ++iter)\n      delete iter->first;\n    SubsetHash tmp;\n    tmp.swap(hash_);\n  }\n\n  ~DeterminizerStar() { FreeMostMemory(); }\n\n private:\n  typedef typename Arc::Label Label;\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId InputStateId;\n  typedef typename Arc::StateId\n      OutputStateId;  // same as above but distinguish states in output Fst.\n  typedef typename Arc::Label StringId;  // Id type used in the StringRepository\n  typedef StringRepository<Label, StringId> StringRepositoryType;\n\n  // Element of a subset [of original states]\n\n  struct Element {\n    InputStateId state;\n    StringId string;\n    Weight weight;\n    bool operator!=(const Element &other) const {\n      return (state != other.state || string != other.string ||\n              weight != other.weight);\n    }\n  };\n\n  // Arcs in the format we temporarily create in this class (a representation,\n  // essentially of a Gallic Fst).\n  struct TempArc {\n    Label ilabel;\n    StringId ostring;  // Look it up in the StringRepository, it's a sequence of\n                       // Labels.\n    OutputStateId nextstate;  // or kNoState for final weights.\n    Weight weight;\n  };\n\n  // Hashing function used in hash of subsets.\n  // A subset is a pointer to vector<Element>.\n  // The Elements are in sorted order on state id, and without repeated states.\n  // Because the order of Elements is fixed, we can use a hashing function that\n  // is order-dependent.  However the weights are not included in the hashing\n  // function-- we hash subsets that differ only in weight to the same key. This\n  // is not optimal in terms of the O(N) performance but typically if we have a\n  // lot of determinized states that differ only in weight then the input\n  // probably was pathological in some way, or even non-determinizable.\n  //   We don't quantize the weights, in order to avoid inexactness in simple\n  //   cases.\n  // Instead we apply the delta when comparing subsets for equality, and allow a\n  // small difference.\n\n  class SubsetKey {\n   public:\n    size_t operator()(const std::vector<Element> *subset)\n        const {  // hashes only the state and string.\n      size_t hash = 0, factor = 1;\n      for (typename std::vector<Element>::const_iterator iter = subset->begin();\n           iter != subset->end(); ++iter) {\n        hash *= factor;\n        hash += iter->state + 103333 * iter->string;\n        factor *= 23531;  // these numbers are primes.\n      }\n      return hash;\n    }\n  };\n\n  // This is the equality operator on subsets.  It checks for exact match on\n  // state-id and string, and approximate match on weights.\n  class SubsetEqual {\n   public:\n    bool operator()(const std::vector<Element> *s1,\n                    const std::vector<Element> *s2) const {\n      size_t sz = s1->size();\n      assert(sz >= 0);\n      if (sz != s2->size()) return false;\n      typename std::vector<Element>::const_iterator iter1 = s1->begin(),\n                                                    iter1_end = s1->end(),\n                                                    iter2 = s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state || iter1->string != iter2->string ||\n            !ApproxEqual(iter1->weight, iter2->weight, delta_))\n          return false;\n      }\n      return true;\n    }\n    float delta_;\n    explicit SubsetEqual(float delta) : delta_(delta) {}\n    SubsetEqual() : delta_(kDelta) {}\n  };\n\n  // Operator that says whether two Elements have the same states.\n  // Used only for debug.\n  class SubsetEqualStates {\n   public:\n    bool operator()(const std::vector<Element> *s1,\n                    const std::vector<Element> *s2) const {\n      size_t sz = s1->size();\n      assert(sz >= 0);\n      if (sz != s2->size()) return false;\n      typename std::vector<Element>::const_iterator iter1 = s1->begin(),\n                                                    iter1_end = s1->end(),\n                                                    iter2 = s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state) return false;\n      }\n      return true;\n    }\n  };\n\n  // Define the hash type we use to store subsets.\n  typedef unordered_map<const std::vector<Element> *, OutputStateId, SubsetKey,\n                        SubsetEqual>\n      SubsetHash;\n\n  class EpsilonClosure {\n   public:\n    EpsilonClosure(const Fst<Arc> *ifst, int max_states,\n                   StringRepository<Label, StringId> *repository, float delta)\n        : ifst_(ifst),\n          max_states_(max_states),\n          repository_(repository),\n          delta_(delta) {}\n\n    // This function computes epsilon closure of subset of states by following\n    // epsilon links. Called by ProcessSubset. Has no side effects except on the\n    // repository.\n    void GetEpsilonClosure(const std::vector<Element> &input_subset,\n                           std::vector<Element> *output_subset);\n\n   private:\n    struct EpsilonClosureInfo {\n      EpsilonClosureInfo() {}\n      EpsilonClosureInfo(const Element &e, const Weight &w, bool i)\n          : element(e), weight_to_process(w), in_queue(i) {}\n      // the weight in the Element struct is the total current weight\n      // that has been processed already\n      Element element;\n      // this stores the weight that we haven't processed (propagated)\n      Weight weight_to_process;\n      // whether \"this\" struct is in the queue\n      // we store the info here so that we don't have to look it up every time\n      bool in_queue;\n      bool operator<(const EpsilonClosureInfo &other) const {\n        return this->element.state < other.element.state;\n      }\n    };\n\n    // to further speed up EpsilonClosure() computation, we have 2 queues\n    // the 2nd queue is used when we first iterate over the input set -\n    // if queue_2_.empty() then we directly set output_set equal to input_set\n    // and return immediately\n    // Since Epsilon arcs are relatively rare, this way we could efficiently\n    // detect the epsilon-free case, without having to waste our computation\n    // e.g. allocating the EpsilonClosureInfo structure; this also lets us do a\n    // level-by-level traversal, which could avoid some (unfortunately not all)\n    // duplicate computation if epsilons form a DAG that is not a tree\n    //\n    // We put the queues here for better efficiency for memory allocation\n    std::deque<typename Arc::StateId> queue_;\n    std::vector<Element> queue_2_;\n\n    // the following 2 structures together form our *virtual \"map\"*\n    // basically we need a map from state_id to EpsilonClosureInfo that operates\n    // in O(1) time, while still takes relatively small mem, and this does it\n    // well for efficiency we don't clear id_to_index_ of its outdated\n    // information As a result each time we do a look-up, we need to check if\n    // (ecinfo_[id_to_index_[id]].element.state == id) Yet this is still faster\n    // than using a std::map<StateId, EpsilonClosureInfo>\n    std::vector<int> id_to_index_;\n    // unlike id_to_index_, we clear the content of ecinfo_ each time we call\n    // EpsilonClosure(). This needed because we need an efficient way to\n    // traverse the virtual map - it is just too costly to traverse the\n    // id_to_index_ vector.\n    std::vector<EpsilonClosureInfo> ecinfo_;\n\n    // Add one element (elem) into cur_subset\n    // it also adds the necessary stuff to queue_, set the correct weight\n    void AddOneElement(const Element &elem, const Weight &unprocessed_weight);\n\n    // Sub-routine that we call in EpsilonClosure()\n    // It takes the current \"unprocessed_weight\" and propagate it to the\n    // states accessible from elem.state by an epsilon arc\n    // and add the results to cur_subset.\n    // save_to_queue_2 is set true when we iterate over the initial subset\n    // - then we save it to queue_2 s.t. if it's empty, we directly return\n    // the input set\n    void ExpandOneElement(const Element &elem, bool sorted,\n                          const Weight &unprocessed_weight,\n                          bool save_to_queue_2 = false);\n\n    // no pointers below would take the ownership\n    const Fst<Arc> *ifst_;\n    int max_states_;\n    StringRepository<Label, StringId> *repository_;\n    float delta_;\n  };\n\n  // This function works out the final-weight of the determinized state.\n  // called by ProcessSubset.\n  // Has no side effects except on the variable repository_, and output_arcs_.\n\n  void ProcessFinal(const std::vector<Element> &closed_subset,\n                    OutputStateId state) {\n    // processes final-weights for this subset.\n    bool is_final = false;\n    StringId final_string = 0;  // = 0 to keep compiler happy.\n    Weight final_weight =\n        Weight::One();  // This value will never be accessed, and\n    // we just set it to avoid spurious compiler warnings.  We avoid setting it\n    // to Zero() because floating-point infinities can sometimes generate\n    // interrupts and slow things down.\n    typename std::vector<Element>::const_iterator iter = closed_subset.begin(),\n                                                  end = closed_subset.end();\n    for (; iter != end; ++iter) {\n      const Element &elem = *iter;\n      Weight this_final_weight = ifst_->Final(elem.state);\n      if (this_final_weight != Weight::Zero()) {\n        if (!is_final) {  // first final-weight\n          final_string = elem.string;\n          final_weight = Times(elem.weight, this_final_weight);\n          is_final = true;\n        } else {  // already have one.\n          if (final_string != elem.string) {\n            KALDI_ERR << \"FST was not functional -> not determinizable\";\n          }\n          final_weight =\n              Plus(final_weight, Times(elem.weight, this_final_weight));\n        }\n      }\n    }\n    if (is_final) {\n      // store final weights in TempArc structure, just like a transition.\n      TempArc temp_arc;\n      temp_arc.ilabel = 0;\n      temp_arc.nextstate =\n          kNoStateId;  // special marker meaning \"final weight\".\n      temp_arc.ostring = final_string;\n      temp_arc.weight = final_weight;\n      output_arcs_[state].push_back(temp_arc);\n    }\n  }\n\n  // ProcessTransition is called from \"ProcessTransitions\".  Broken out for\n  // clarity.  Has side effects on output_arcs_, and (via SubsetToStateId), Q_\n  // and hash_.\n  void ProcessTransition(OutputStateId state, Label ilabel,\n                         std::vector<Element> *subset);\n\n  // \"less than\" operator for pair<Label, Element>.   Used in\n  // ProcessTransitions. Lexicographical order, with comparing the state only\n  // for \"Element\".\n\n  class PairComparator {\n   public:\n    inline bool operator()(const std::pair<Label, Element> &p1,\n                           const std::pair<Label, Element> &p2) {\n      if (p1.first < p2.first) {\n        return true;\n      } else if (p1.first > p2.first) {\n        return false;\n      } else {\n        return p1.second.state < p2.second.state;\n      }\n    }\n  };\n\n  // ProcessTransitions handles transitions out of this subset of states.\n  // Ignores epsilon transitions (epsilon closure already handled that).\n  // Does not consider final states.  Breaks the transitions up by ilabel,\n  // and creates a new transition in determinized FST, for each ilabel.\n  // Does this by creating a big vector of pairs <Label, Element> and then\n  // sorting them using a lexicographical ordering, and calling\n  // ProcessTransition for each range with the same ilabel. Side effects on\n  // repository, and (via ProcessTransition) on Q_, hash_, and output_arcs_.\n  void ProcessTransitions(const std::vector<Element> &closed_subset,\n                          OutputStateId state) {\n    std::vector<std::pair<Label, Element> > all_elems;\n    {  // Push back into \"all_elems\", elements corresponding to all\n       // non-epsilon-input transitions\n      // out of all states in \"closed_subset\".\n      typename std::vector<Element>::const_iterator iter =\n                                                        closed_subset.begin(),\n                                                    end = closed_subset.end();\n      for (; iter != end; ++iter) {\n        const Element &elem = *iter;\n        for (ArcIterator<Fst<Arc> > aiter(*ifst_, elem.state); !aiter.Done();\n             aiter.Next()) {\n          const Arc &arc = aiter.Value();\n          if (arc.ilabel !=\n              0) {  // Non-epsilon transition -- ignore epsilons here.\n            std::pair<Label, Element> this_pr;\n            this_pr.first = arc.ilabel;\n            Element &next_elem(this_pr.second);\n            next_elem.state = arc.nextstate;\n            next_elem.weight = Times(elem.weight, arc.weight);\n            if (arc.olabel == 0) {  // output epsilon-- this is simple case so\n                                    // handle separately for efficiency\n              next_elem.string = elem.string;\n            } else {\n              std::vector<Label> seq;\n              repository_.SeqOfId(elem.string, &seq);\n              seq.push_back(arc.olabel);\n              next_elem.string = repository_.IdOfSeq(seq);\n            }\n            all_elems.push_back(this_pr);\n          }\n        }\n      }\n    }\n    PairComparator pc;\n    std::sort(all_elems.begin(), all_elems.end(), pc);\n    // now sorted first on input label, then on state.\n    typedef typename std::vector<std::pair<Label, Element> >::const_iterator\n        PairIter;\n    PairIter cur = all_elems.begin(), end = all_elems.end();\n    std::vector<Element> this_subset;\n    while (cur != end) {\n      // Process ranges that share the same input symbol.\n      Label ilabel = cur->first;\n      this_subset.clear();\n      while (cur != end && cur->first == ilabel) {\n        this_subset.push_back(cur->second);\n        cur++;\n      }\n      // We now have a subset for this ilabel.\n      ProcessTransition(state, ilabel, &this_subset);\n    }\n  }\n\n  // SubsetToStateId converts a subset (vector of Elements) to a StateId in the\n  // output fst.  This is a hash lookup; if no such state exists, it adds a new\n  // state to the hash and adds a new pair to the queue. Side effects on hash_\n  // and Q_, and on output_arcs_ [just affects the size].\n  OutputStateId SubsetToStateId(\n      const std::vector<Element> &subset) {  // may add the subset to the queue.\n    typedef typename SubsetHash::iterator IterType;\n    IterType iter = hash_.find(&subset);\n    if (iter == hash_.end()) {  // was not there.\n      std::vector<Element> *new_subset = new std::vector<Element>(subset);\n      OutputStateId new_state_id = (OutputStateId)output_arcs_.size();\n      bool ans =\n          hash_\n              .insert(std::pair<const std::vector<Element> *, OutputStateId>(\n                  new_subset, new_state_id))\n              .second;\n      assert(ans);\n      output_arcs_.push_back(std::vector<TempArc>());\n      if (allow_partial_ == false) {\n        // If --allow-partial is not requested, we do the old way.\n        Q_.push_front(std::pair<std::vector<Element> *, OutputStateId>(\n            new_subset, new_state_id));\n      } else {\n        // If --allow-partial is requested, we do breadth first search. This\n        // ensures that when we return partial results, we return the states\n        // that are reachable by the fewest steps from the start state.\n        Q_.push_back(std::pair<std::vector<Element> *, OutputStateId>(\n            new_subset, new_state_id));\n      }\n      return new_state_id;\n    } else {\n      return iter->second;  // the OutputStateId.\n    }\n  }\n\n  // ProcessSubset does the processing of a determinized state, i.e. it creates\n  // transitions out of it and adds new determinized states to the queue if\n  // necessary. The first stage is \"EpsilonClosure\" (follow epsilons to get a\n  // possibly larger set of (states, weights)).  After that we ignore epsilons.\n  // We process the final-weight of the state, and then handle transitions out\n  // (this may add more determinized states to the queue).\n  void ProcessSubset(\n      const std::pair<std::vector<Element> *, OutputStateId> &pair) {\n    const std::vector<Element> *subset = pair.first;\n    OutputStateId state = pair.second;\n\n    std::vector<Element> closed_subset;  // subset after epsilon closure.\n    epsilon_closure_.GetEpsilonClosure(*subset, &closed_subset);\n\n    // Now follow non-epsilon arcs [and also process final states]\n    ProcessFinal(closed_subset, state);\n\n    // Now handle transitions out of these states.\n    ProcessTransitions(closed_subset, state);\n  }\n\n  void Debug();\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(DeterminizerStar);\n  std::deque<std::pair<std::vector<Element> *, OutputStateId> >\n      Q_;  // queue of subsets to be processed.\n\n  std::vector<std::vector<TempArc> >\n      output_arcs_;  // essentially an FST in our format.\n\n  const Fst<Arc> *ifst_;\n  float delta_;\n  int max_states_;\n  bool determinized_;   // used to check usage.\n  bool allow_partial_;  // output paritial results or not\n  bool is_partial_;     // if we get partial results or not\n  SubsetKey hasher_;    // object that computes keys-- has no data members.\n  SubsetEqual\n      equal_;  // object that compares subsets-- only data member is delta_.\n  SubsetHash hash_;  // hash from Subset to StateId in final Fst.\n\n  StringRepository<Label, StringId>\n      repository_;  // associate integer id's with sequences of labels.\n  EpsilonClosure epsilon_closure_;\n};\n\ntemplate <class F>\nbool DeterminizeStar(F &ifst,  // NOLINT\n                     MutableFst<typename F::Arc> *ofst, float delta,\n                     bool *debug_ptr, int max_states, bool allow_partial) {\n  ofst->SetOutputSymbols(ifst.OutputSymbols());\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  DeterminizerStar<F> det(ifst, delta, max_states, allow_partial);\n  det.Determinize(debug_ptr);\n  det.Output(ofst);\n  return det.IsPartial();\n}\n\ntemplate <class F>\nbool DeterminizeStar(F &ifst,  // NOLINT\n                     MutableFst<GallicArc<typename F::Arc> > *ofst, float delta,\n                     bool *debug_ptr, int max_states, bool allow_partial) {\n  ofst->SetOutputSymbols(ifst.InputSymbols());\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  DeterminizerStar<F> det(ifst, delta, max_states, allow_partial);\n  det.Determinize(debug_ptr);\n  det.Output(ofst);\n  return det.IsPartial();\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::EpsilonClosure::GetEpsilonClosure(\n    const std::vector<Element> &input_subset,\n    std::vector<Element> *output_subset) {\n  ecinfo_.resize(0);\n  size_t size = input_subset.size();\n  // find whether input fst is known to be sorted in input label.\n  bool sorted =\n      ((ifst_->Properties(kILabelSorted, false) & kILabelSorted) != 0);\n\n  // size is still the input_subset.size()\n  for (size_t i = 0; i < size; i++) {\n    ExpandOneElement(input_subset[i], sorted, input_subset[i].weight, true);\n  }\n\n  size_t s = queue_2_.size();\n  if (s == 0) {\n    *output_subset = input_subset;\n    return;\n  } else {\n    // queue_2 not empty. Need to create the vector<info>\n    for (size_t i = 0; i < size; i++) {\n      // the weight has not been processed yet,\n      // so put all of them in the \"weight_to_process\"\n      ecinfo_.push_back(\n          EpsilonClosureInfo(input_subset[i], input_subset[i].weight, false));\n      ecinfo_.back().element.weight = Weight::Zero();  // clear the weight\n\n      if (id_to_index_.size() < input_subset[i].state + 1) {\n        id_to_index_.resize(2 * input_subset[i].state + 1, -1);\n      }\n      id_to_index_[input_subset[i].state] = ecinfo_.size() - 1;\n    }\n  }\n\n  {\n    Element elem;\n    elem.weight = Weight::Zero();\n    for (size_t i = 0; i < s; i++) {\n      elem.state = queue_2_[i].state;\n      elem.string = queue_2_[i].string;\n      AddOneElement(elem, queue_2_[i].weight);\n    }\n    queue_2_.resize(0);\n  }\n\n  int counter = 0;  // relates to max-states option, used for test.\n  while (!queue_.empty()) {\n    InputStateId id = queue_.front();\n\n    // no need to check validity of the index\n    // since anything in the queue we are sure they're in the \"virtual set\"\n    int index = id_to_index_[id];\n    EpsilonClosureInfo &info = ecinfo_[index];\n    Element &elem = info.element;\n    Weight unprocessed_weight = info.weight_to_process;\n\n    elem.weight = Plus(elem.weight, unprocessed_weight);\n    info.weight_to_process = Weight::Zero();\n\n    info.in_queue = false;\n    queue_.pop_front();\n\n    if (max_states_ > 0 && counter++ > max_states_) {\n      KALDI_ERR << \"Determinization aborted since looped more than \"\n                << max_states_ << \" times during epsilon closure\";\n    }\n\n    // generally we need to be careful about iterator-invalidation problem\n    // here we pass a reference (elem), which could be an issue.\n    // In the beginning of ExpandOneElement, we make a copy of elem.string\n    // to avoid that issue\n    ExpandOneElement(elem, sorted, unprocessed_weight);\n  }\n\n  {\n    // this sorting is based on StateId\n    sort(ecinfo_.begin(), ecinfo_.end());\n\n    output_subset->clear();\n\n    size = ecinfo_.size();\n    output_subset->reserve(size);\n    for (size_t i = 0; i < size; i++) {\n      EpsilonClosureInfo &info = ecinfo_[i];\n      if (info.weight_to_process != Weight::Zero()) {\n        info.element.weight = Plus(info.element.weight, info.weight_to_process);\n      }\n      output_subset->push_back(info.element);\n    }\n  }\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::EpsilonClosure::AddOneElement(\n    const Element &elem, const Weight &unprocessed_weight) {\n  // first we try to find the element info in the ecinfo_ vector\n  int index = -1;\n  if (elem.state < id_to_index_.size()) {\n    index = id_to_index_[elem.state];\n  }\n  if (index != -1) {\n    if (index >= ecinfo_.size()) {\n      index = -1;\n    } else if (ecinfo_[index].element.state != elem.state) {\n      // since ecinfo_ might store outdated information, we need to check\n      index = -1;\n    }\n  }\n\n  if (index == -1) {\n    // was no such StateId: insert and add to queue.\n    ecinfo_.push_back(EpsilonClosureInfo(elem, unprocessed_weight, true));\n    size_t size = id_to_index_.size();\n    if (size < elem.state + 1) {\n      // double the size to reduce memory operations\n      id_to_index_.resize(2 * elem.state + 1, -1);\n    }\n    id_to_index_[elem.state] = ecinfo_.size() - 1;\n    queue_.push_back(elem.state);\n\n  } else {  // one is already there.  Add weights.\n    EpsilonClosureInfo &info = ecinfo_[index];\n    if (info.element.string != elem.string) {\n      // Non-functional FST.\n      std::ostringstream ss;\n      ss << \"FST was not functional -> not determinizable.\";\n      {  // Print some debugging information.  Can be helpful to debug\n        // the inputs when FSTs are mysteriously non-functional.\n        std::vector<Label> tmp_seq;\n        repository_->SeqOfId(info.element.string, &tmp_seq);\n        ss << \"\\nFirst string:\";\n        for (size_t i = 0; i < tmp_seq.size(); i++) ss << ' ' << tmp_seq[i];\n        ss << \"\\nSecond string:\";\n        repository_->SeqOfId(elem.string, &tmp_seq);\n        for (size_t i = 0; i < tmp_seq.size(); i++) ss << ' ' << tmp_seq[i];\n      }\n      KALDI_ERR << ss.str();\n    }\n\n    info.weight_to_process = Plus(info.weight_to_process, unprocessed_weight);\n\n    if (!info.in_queue) {\n      // this is because the code in \"else\" below: the\n      // iter->second.weight_to_process might not be Zero()\n      Weight weight = Plus(info.element.weight, info.weight_to_process);\n\n      // What is done below is, we propagate the weight (by adding them\n      // to the queue only when the change is big enough;\n      // otherwise we just store the weight, until before returning\n      // we add the element.weight and weight_to_process together\n      if (!ApproxEqual(weight, info.element.weight, delta_)) {\n        // add extra part of weight to queue.\n        info.in_queue = true;\n        queue_.push_back(elem.state);\n      }\n    }\n  }\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::EpsilonClosure::ExpandOneElement(\n    const Element &elem, bool sorted, const Weight &unprocessed_weight,\n    bool save_to_queue_2) {\n  StringId str =\n      elem.string;  // copy it here because there is an iterator-\n                    // - invalidation problem (it really happens for some FSTs)\n\n  // now we are going to propagate the \"unprocessed_weight\"\n  for (ArcIterator<Fst<Arc> > aiter(*ifst_, elem.state); !aiter.Done();\n       aiter.Next()) {\n    const Arc &arc = aiter.Value();\n    if (sorted && arc.ilabel > 0) {\n      break;\n      // Break from the loop: due to sorting there will be no\n      // more transitions with epsilons as input labels.\n    }\n    if (arc.ilabel != 0) {\n      continue;  // we only process epsilons here\n    }\n    Element next_elem;\n    next_elem.state = arc.nextstate;\n    next_elem.weight = Weight::Zero();\n    Weight next_unprocessed_weight = Times(unprocessed_weight, arc.weight);\n\n    // now must append strings\n    if (arc.olabel == 0) {\n      next_elem.string = str;\n    } else {\n      std::vector<Label> seq;\n      repository_->SeqOfId(str, &seq);\n      if (arc.olabel != 0) seq.push_back(arc.olabel);\n      next_elem.string = repository_->IdOfSeq(seq);\n    }\n    if (save_to_queue_2) {\n      next_elem.weight = next_unprocessed_weight;\n      queue_2_.push_back(next_elem);\n    } else {\n      AddOneElement(next_elem, next_unprocessed_weight);\n    }\n  }\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::Output(MutableFst<GallicArc<Arc> > *ofst,\n                                 bool destroy) {\n  assert(determinized_);\n  if (destroy) determinized_ = false;\n  typedef GallicWeight<Label, Weight> ThisGallicWeight;\n  typedef typename Arc::StateId StateId;\n  if (destroy) FreeMostMemory();\n  StateId nStates = static_cast<StateId>(output_arcs_.size());\n  ofst->DeleteStates();\n  ofst->SetStart(kNoStateId);\n  if (nStates == 0) {\n    return;\n  }\n  for (StateId s = 0; s < nStates; s++) {\n    OutputStateId news = ofst->AddState();\n    assert(news == s);\n  }\n  ofst->SetStart(0);\n  // now process transitions.\n  for (StateId this_state = 0; this_state < nStates; this_state++) {\n    std::vector<TempArc> &this_vec(output_arcs_[this_state]);\n    typename std::vector<TempArc>::const_iterator iter = this_vec.begin(),\n                                                  end = this_vec.end();\n    for (; iter != end; ++iter) {\n      const TempArc &temp_arc(*iter);\n      GallicArc<Arc> new_arc;\n      std::vector<Label> seq;\n      repository_.SeqOfId(temp_arc.ostring, &seq);\n      StringWeight<Label, STRING_LEFT> string_weight;\n      for (size_t i = 0; i < seq.size(); i++) string_weight.PushBack(seq[i]);\n      ThisGallicWeight gallic_weight(string_weight, temp_arc.weight);\n\n      if (temp_arc.nextstate == kNoStateId) {  // is really final weight.\n        ofst->SetFinal(this_state, gallic_weight);\n      } else {  // is really an arc.\n        new_arc.nextstate = temp_arc.nextstate;\n        new_arc.ilabel = temp_arc.ilabel;\n        new_arc.olabel = temp_arc.ilabel;  // acceptor.  input == output.\n        new_arc.weight = gallic_weight;    // includes string and weight.\n        ofst->AddArc(this_state, new_arc);\n      }\n    }\n    // Free up memory.  Do this inside the loop as ofst is also allocating\n    // memory\n    if (destroy) {\n      std::vector<TempArc> temp;\n      temp.swap(this_vec);\n    }\n  }\n  if (destroy) {\n    std::vector<std::vector<TempArc> > temp;\n    temp.swap(output_arcs_);\n  }\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::Output(MutableFst<Arc> *ofst, bool destroy) {\n  assert(determinized_);\n  if (destroy) determinized_ = false;\n  // Outputs to standard fst.\n  OutputStateId num_states = static_cast<OutputStateId>(output_arcs_.size());\n  if (destroy) FreeMostMemory();\n  ofst->DeleteStates();\n  if (num_states == 0) {\n    ofst->SetStart(kNoStateId);\n    return;\n  }\n  // Add basic states-- but will add extra ones to account for strings on\n  // output.\n  for (OutputStateId s = 0; s < num_states; s++) {\n    OutputStateId news = ofst->AddState();\n    assert(news == s);\n  }\n  ofst->SetStart(0);\n  for (OutputStateId this_state = 0; this_state < num_states; this_state++) {\n    std::vector<TempArc> &this_vec(output_arcs_[this_state]);\n\n    typename std::vector<TempArc>::const_iterator iter = this_vec.begin(),\n                                                  end = this_vec.end();\n    for (; iter != end; ++iter) {\n      const TempArc &temp_arc(*iter);\n      std::vector<Label> seq;\n      repository_.SeqOfId(temp_arc.ostring, &seq);\n      if (temp_arc.nextstate == kNoStateId) {  // Really a final weight.\n        // Make a sequence of states going to a final state, with the strings as\n        // labels. Put the weight on the first arc.\n        OutputStateId cur_state = this_state;\n        for (size_t i = 0; i < seq.size(); i++) {\n          OutputStateId next_state = ofst->AddState();\n          Arc arc;\n          arc.nextstate = next_state;\n          arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n          arc.ilabel = 0;  // epsilon.\n          arc.olabel = seq[i];\n          ofst->AddArc(cur_state, arc);\n          cur_state = next_state;\n        }\n        ofst->SetFinal(cur_state,\n                       (seq.size() == 0 ? temp_arc.weight : Weight::One()));\n      } else {  // Really an arc.\n        OutputStateId cur_state = this_state;\n        // Have to be careful with this integer comparison (i+1 < seq.size())\n        // because unsigned. i < seq.size()-1 could fail for zero-length\n        // sequences.\n        for (size_t i = 0; i + 1 < seq.size(); i++) {\n          // for all but the last element of seq, create new state.\n          OutputStateId next_state = ofst->AddState();\n          Arc arc;\n          arc.nextstate = next_state;\n          arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n          arc.ilabel = (i == 0 ? temp_arc.ilabel\n                               : 0);  // put ilabel on first element of seq.\n          arc.olabel = seq[i];\n          ofst->AddArc(cur_state, arc);\n          cur_state = next_state;\n        }\n        // Add the final arc in the sequence.\n        Arc arc;\n        arc.nextstate = temp_arc.nextstate;\n        arc.weight = (seq.size() <= 1 ? temp_arc.weight : Weight::One());\n        arc.ilabel = (seq.size() <= 1 ? temp_arc.ilabel : 0);\n        arc.olabel = (seq.size() > 0 ? seq.back() : 0);\n        ofst->AddArc(cur_state, arc);\n      }\n    }\n    // Free up memory.  Do this inside the loop as ofst is also allocating\n    // memory\n    if (destroy) {\n      std::vector<TempArc> temp;\n      temp.swap(this_vec);\n    }\n  }\n  if (destroy) {\n    std::vector<std::vector<TempArc> > temp;\n    temp.swap(output_arcs_);\n    repository_.Destroy();\n  }\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::ProcessTransition(OutputStateId state, Label ilabel,\n                                            std::vector<Element> *subset) {\n  // At input, \"subset\" may contain duplicates for a given dest state (but in\n  // sorted order).  This function removes duplicates from \"subset\", normalizes\n  // it, and adds a transition to the dest. state (possibly affecting Q_ and\n  // hash_, if state did not exist).\n\n  typedef typename std::vector<Element>::iterator IterType;\n  {  // This block makes the subset have one unique Element per state, adding\n     // the weights.\n    IterType cur_in = subset->begin(), cur_out = cur_in, end = subset->end();\n    size_t num_out = 0;\n    // Merge elements with same state-id\n    while (cur_in != end) {  // while we have more elements to process.\n      // At this point, cur_out points to location of next place we want to put\n      // an element, cur_in points to location of next element we want to\n      // process.\n      if (cur_in != cur_out) *cur_out = *cur_in;\n      cur_in++;\n      while (cur_in != end &&\n             cur_in->state == cur_out->state) {  // merge elements.\n        if (cur_in->string != cur_out->string) {\n          KALDI_ERR << \"FST was not functional -> not determinizable\";\n        }\n        cur_out->weight = Plus(cur_out->weight, cur_in->weight);\n        cur_in++;\n      }\n      cur_out++;\n      num_out++;\n    }\n    subset->resize(num_out);\n  }\n\n  StringId common_str;\n  Weight tot_weight;\n  {  // This block computes common_str and tot_weight (essentially: the common\n     // divisor)\n    // and removes them from the elements.\n    std::vector<Label> seq;\n\n    IterType begin = subset->begin(), iter, end = subset->end();\n    {  // This block computes \"seq\", which is the common prefix, and\n       // \"common_str\",\n      // which is the StringId version of \"seq\".\n      std::vector<Label> tmp_seq;\n      for (iter = begin; iter != end; ++iter) {\n        if (iter == begin) {\n          repository_.SeqOfId(iter->string, &seq);\n        } else {\n          repository_.SeqOfId(iter->string, &tmp_seq);\n          if (tmp_seq.size() < seq.size())\n            seq.resize(tmp_seq.size());  // size of shortest one.\n          for (size_t i = 0; i < seq.size();\n               i++)  // seq.size() is the shorter one at this point.\n            if (tmp_seq[i] != seq[i]) seq.resize(i);\n        }\n        if (seq.size() == 0) break;  // will not get any prefix.\n      }\n      common_str = repository_.IdOfSeq(seq);\n    }\n\n    {  // This block computes \"tot_weight\".\n      iter = begin;\n      tot_weight = iter->weight;\n      for (++iter; iter != end; ++iter)\n        tot_weight = Plus(tot_weight, iter->weight);\n    }\n\n    // Now divide out common stuff from elements.\n    size_t prefix_len = seq.size();\n    for (iter = begin; iter != end; ++iter) {\n      iter->weight = Divide(iter->weight, tot_weight);\n      iter->string = repository_.RemovePrefix(iter->string, prefix_len);\n    }\n  }\n\n  // Now add an arc to the state that the subset represents.\n  // We may create a new state id for this (in SubsetToStateId).\n  TempArc temp_arc;\n  temp_arc.ilabel = ilabel;\n  temp_arc.nextstate =\n      SubsetToStateId(*subset);  // may or may not really add the subset.\n  temp_arc.ostring = common_str;\n  temp_arc.weight = tot_weight;\n  output_arcs_[state].push_back(temp_arc);  // record the arc.\n}\n\ntemplate <class F>\nvoid DeterminizerStar<F>::Debug() {\n  // this function called if you send a signal\n  // SIGUSR1 to the process (and it's caught by the handler in\n  // fstdeterminizestar).  It prints out some traceback\n  // info and exits.\n\n  KALDI_WARN << \"Debug function called (probably SIGUSR1 caught)\";\n  // free up memory from the hash as we need a little memory\n  {\n    SubsetHash hash_tmp;\n    std::swap(hash_tmp, hash_);\n  }\n\n  if (output_arcs_.size() <= 2) {\n    KALDI_ERR << \"Nothing to trace back\";\n  }\n  size_t max_state = output_arcs_.size() - 2;  // don't take the last\n  // one as we might be halfway into constructing it.\n\n  std::vector<OutputStateId> predecessor(max_state + 1, kNoStateId);\n  for (size_t i = 0; i < max_state; i++) {\n    for (size_t j = 0; j < output_arcs_[i].size(); j++) {\n      OutputStateId nextstate = output_arcs_[i][j].nextstate;\n      // Always find an earlier-numbered predecessor; this\n      // is always possible because of the way the algorithm\n      // works.\n      if (nextstate <= max_state && nextstate > i) predecessor[nextstate] = i;\n    }\n  }\n  std::vector<std::pair<Label, StringId> > traceback;\n  // 'traceback' is a pair of (ilabel, olabel-seq).\n  OutputStateId cur_state = max_state;  // A recently constructed state.\n\n  while (cur_state != 0 && cur_state != kNoStateId) {\n    OutputStateId last_state = predecessor[cur_state];\n    std::pair<Label, StringId> p;\n    size_t i;\n    for (i = 0; i < output_arcs_[last_state].size(); i++) {\n      if (output_arcs_[last_state][i].nextstate == cur_state) {\n        p.first = output_arcs_[last_state][i].ilabel;\n        p.second = output_arcs_[last_state][i].ostring;\n        traceback.push_back(p);\n        break;\n      }\n    }\n    KALDI_ASSERT(i != output_arcs_[last_state].size());  // Or fell off loop.\n    cur_state = last_state;\n  }\n  if (cur_state == kNoStateId)\n    KALDI_WARN << \"Traceback did not reach start state \"\n               << \"(possibly debug-code error)\";\n\n  std::stringstream ss;\n  ss << \"Traceback follows in format \"\n     << \"ilabel (olabel olabel) ilabel (olabel) ... :\";\n  for (ssize_t i = traceback.size() - 1; i >= 0; i--) {\n    ss << ' ' << traceback[i].first << \" ( \";\n    std::vector<Label> seq;\n    repository_.SeqOfId(traceback[i].second, &seq);\n    for (size_t j = 0; j < seq.size(); j++) ss << seq[j] << ' ';\n    ss << ')';\n  }\n  KALDI_ERR << ss.str();\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_DETERMINIZE_STAR_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/determinize-star.h",
    "content": "// fstext/determinize-star.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//                2014  Guoguo Chen\n//                2015  Hainan Xu\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_DETERMINIZE_STAR_H_\n#define KALDI_FSTEXT_DETERMINIZE_STAR_H_\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <stdexcept>  // this algorithm uses exceptions\n#include <vector>\n\nnamespace fst {\n\n/// \\addtogroup fst_extensions\n///  @{\n\n// For example of usage, see test-determinize-star.cc\n\n/*\n   DeterminizeStar implements determinization with epsilon removal, which we\n   distinguish with a star.\n\n   We define a determinized* FST as one in which no state has more than one\n   transition with the same input-label.  Epsilon input labels are not allowed\n   except starting from states that have exactly one arc exiting them (and are\n   not final).  [In the normal definition of determinized, epsilon-input labels\n   are not allowed at all, whereas in Mohri's definition, epsilons are treated\n   as ordinary symbols].  The determinized* definition is intended to simulate\n   the effect of allowing strings of output symbols at each state.\n\n   The algorithm implemented here takes an Fst<Arc>, and a pointer to a\n   MutableFst<Arc> where it puts its output.  The weight type is assumed to be a\n   float-weight.  It does epsilon removal and determinization.\n   This algorithm may fail if the input has epsilon cycles under\n   certain circumstances (i.e. the semiring is non-idempotent, e.g. the log\n   semiring, or there are negative cost epsilon cycles).\n\n   This implementation is much less fancy than the one in fst/determinize.h, and\n   does not have an \"on-demand\" version.\n\n   The algorithm is a fairly normal determinization algorithm.  We keep in\n   memory the subsets of states, together with their leftover strings and their\n   weights.  The only difference is we detect input epsilon transitions and\n   treat them \"specially\".\n*/\n\n// This algorithm will be slightly faster if you sort the input fst on input\n// label.\n\n/**\n    This function implements the normal version of DeterminizeStar, in which the\n    output strings are represented using sequences of arcs, where all but the\n    first one has an epsilon on the input side.  The debug_ptr argument is an\n    optional pointer to a bool that, if it becomes true while the algorithm is\n    executing, the algorithm will print a traceback and terminate (used in\n    fstdeterminizestar.cc debug non-terminating determinization).\n    If max_states is positive, it will stop determinization and throw an\n    exception as soon as the max-states is reached. This can be useful in test.\n    If allow_partial is true, the algorithm will output partial results when the\n    specified max_states is reached (when larger than zero), instead of throwing\n    out an error.\n\n    Caution, the return status is un-intuitive: this function will return false\n   if determinization completed normally, and true if it was stopped early by\n    reaching the 'max-states' limit, and a partial FST was generated.\n*/\ntemplate <class F>\nbool DeterminizeStar(F &ifst, MutableFst<typename F::Arc> *ofst,  // NOLINT\n                     float delta = kDelta, bool *debug_ptr = NULL,\n                     int max_states = -1, bool allow_partial = false);\n\n/*  This is a version of DeterminizeStar with a slightly more \"natural\" output\n   format, where the output sequences are encoded using the GallicArc (i.e. the\n   output symbols are strings. If max_states is positive, it will stop\n   determinization and throw an exception as soon as the max-states is reached.\n   This can be useful in test. If allow_partial is true, the algorithm will\n   output partial results when the specified max_states is reached (when larger\n   than zero), instead of throwing out an error.\n\n    Caution, the return status is un-intuitive: this function will return false\n   if determinization completed normally, and true if it was stopped early by\n    reaching the 'max-states' limit, and a partial FST was generated.\n*/\ntemplate <class F>\nbool DeterminizeStar(F &ifst,  // NOLINT\n                     MutableFst<GallicArc<typename F::Arc> > *ofst,\n                     float delta = kDelta, bool *debug_ptr = NULL,\n                     int max_states = -1, bool allow_partial = false);\n\n/// @} end \"addtogroup fst_extensions\"\n\n}  // end namespace fst\n\n#include \"fstext/determinize-star-inl.h\"\n\n#endif  // KALDI_FSTEXT_DETERMINIZE_STAR_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/fstext-lib.h",
    "content": "// fstext/fstext-lib.h\n\n// Copyright 2009-2012  Microsoft Corporation  Johns Hopkins University (author:\n// Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_FSTEXT_LIB_H_\n#define KALDI_FSTEXT_FSTEXT_LIB_H_\n\n#include \"fst/fstlib.h\"\n#include \"fstext/determinize-lattice.h\"\n#include \"fstext/determinize-star.h\"\n#include \"fstext/fstext-utils.h\"\n#include \"fstext/kaldi-fst-io.h\"\n#include \"fstext/lattice-utils.h\"\n#include \"fstext/lattice-weight.h\"\n#include \"fstext/pre-determinize.h\"\n#include \"fstext/table-matcher.h\"\n\n#endif  // KALDI_FSTEXT_FSTEXT_LIB_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/fstext-utils-inl.h",
    "content": "// fstext/fstext-utils-inl.h\n\n// Copyright 2009-2012  Microsoft Corporation  Johns Hopkins University (Author:\n// Daniel Povey)\n//                2014  Telepoint Global Hosting Service, LLC. (Author: David\n//                Snyder)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_FSTEXT_UTILS_INL_H_\n#define KALDI_FSTEXT_FSTEXT_UTILS_INL_H_\n\n#include <algorithm>\n#include <cstring>\n#include <map>\n#include <set>\n#include <sstream>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"base/kaldi-common.h\"\n#include \"fstext/determinize-star.h\"\n#include \"fstext/pre-determinize.h\"\n#include \"util/const-integer-set.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/stl-utils.h\"\n#include \"util/text-utils.h\"\n\nnamespace fst {\n\ntemplate <class Arc>\ntypename Arc::Label HighestNumberedOutputSymbol(const Fst<Arc> &fst) {\n  typename Arc::Label ans = 0;\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    typename Arc::StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      ans = std::max(ans, arc.olabel);\n    }\n  }\n  return ans;\n}\n\ntemplate <class Arc>\ntypename Arc::Label HighestNumberedInputSymbol(const Fst<Arc> &fst) {\n  typename Arc::Label ans = 0;\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    typename Arc::StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      ans = std::max(ans, arc.ilabel);\n    }\n  }\n  return ans;\n}\n\ntemplate <class Arc>\ntypename Arc::StateId NumArcs(const ExpandedFst<Arc> &fst) {\n  typedef typename Arc::StateId StateId;\n  StateId num_arcs = 0;\n  for (StateId s = 0; s < fst.NumStates(); s++) num_arcs += fst.NumArcs(s);\n  return num_arcs;\n}\n\ntemplate <class Arc, class I>\nvoid GetOutputSymbols(const Fst<Arc> &fst, bool include_eps,\n                      std::vector<I> *symbols) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  std::set<I> all_syms;\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    typename Arc::StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      all_syms.insert(arc.olabel);\n    }\n  }\n\n  // Remove epsilon, if instructed.\n  if (!include_eps && !all_syms.empty() && *all_syms.begin() == 0)\n    all_syms.erase(0);\n  KALDI_ASSERT(symbols != NULL);\n  kaldi::CopySetToVector(all_syms, symbols);\n}\n\ntemplate <class Arc, class I>\nvoid GetInputSymbols(const Fst<Arc> &fst, bool include_eps,\n                     std::vector<I> *symbols) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  unordered_set<I> all_syms;\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    typename Arc::StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      all_syms.insert(arc.ilabel);\n    }\n  }\n  // Remove epsilon, if instructed.\n  if (!include_eps && all_syms.count(0) != 0) all_syms.erase(0);\n  KALDI_ASSERT(symbols != NULL);\n  kaldi::CopySetToVector(all_syms, symbols);\n  std::sort(symbols->begin(), symbols->end());\n}\n\ntemplate <class Arc, class I>\nclass RemoveSomeInputSymbolsMapper {\n public:\n  Arc operator()(const Arc &arc_in) {\n    Arc ans = arc_in;\n    if (to_remove_set_.count(ans.ilabel) != 0)\n      ans.ilabel = 0;  // remove this symbol\n    return ans;\n  }\n  MapFinalAction FinalAction() { return MAP_NO_SUPERFINAL; }\n  MapSymbolsAction InputSymbolsAction() { return MAP_CLEAR_SYMBOLS; }\n  MapSymbolsAction OutputSymbolsAction() { return MAP_COPY_SYMBOLS; }\n  uint64 Properties(uint64 props) const {\n    // remove the following as we don't know now if any of them are true.\n    uint64 to_remove = kAcceptor | kNotAcceptor | kIDeterministic |\n                       kNonIDeterministic | kNoEpsilons | kNoIEpsilons |\n                       kILabelSorted | kNotILabelSorted;\n    return props & ~to_remove;\n  }\n  explicit RemoveSomeInputSymbolsMapper(const std::vector<I> &to_remove)\n      : to_remove_set_(to_remove) {\n    KALDI_ASSERT_IS_INTEGER_TYPE(I);\n    assert(to_remove_set_.count(0) == 0);  // makes no sense to remove epsilon.\n  }\n\n private:\n  kaldi::ConstIntegerSet<I> to_remove_set_;\n};\n\ntemplate <class Arc, class I>\nusing LookaheadFst = ArcMapFst<Arc, Arc, RemoveSomeInputSymbolsMapper<Arc, I> >;\n\n// Lookahead composition is used for optimized online\n// composition of FSTs during decoding. See\n// nnet3/nnet3-latgen-faster-lookahead.cc. For details of compose filters\n// see DefaultLookAhead in fst/compose.h\ntemplate <class Arc, class I>\nLookaheadFst<Arc, I> *LookaheadComposeFst(const Fst<Arc> &ifst1,\n                                          const Fst<Arc> &ifst2,\n                                          const std::vector<I> &to_remove) {\n  fst::CacheOptions cache_opts(true, 1 << 25LL);\n  fst::CacheOptions cache_opts_map(true, 0);\n  fst::ArcMapFstOptions arcmap_opts(cache_opts);\n  RemoveSomeInputSymbolsMapper<Arc, I> mapper(to_remove);\n  return new LookaheadFst<Arc, I>(ComposeFst<Arc>(ifst1, ifst2, cache_opts),\n                                  mapper, arcmap_opts);\n}\n\ntemplate <class Arc, class I>\nvoid RemoveSomeInputSymbols(const std::vector<I> &to_remove,\n                            MutableFst<Arc> *fst) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  RemoveSomeInputSymbolsMapper<Arc, I> mapper(to_remove);\n  Map(fst, mapper);\n}\n\ntemplate <class Arc, class I>\nclass MapInputSymbolsMapper {\n public:\n  Arc operator()(const Arc &arc_in) {\n    Arc ans = arc_in;\n    if (ans.ilabel > 0 && ans.ilabel < static_cast<typename Arc::Label>(\n                                           (*symbol_mapping_).size()))\n      ans.ilabel = (*symbol_mapping_)[ans.ilabel];\n    return ans;\n  }\n  MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }\n  MapSymbolsAction InputSymbolsAction() const { return MAP_CLEAR_SYMBOLS; }\n  MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS; }\n  uint64 Properties(uint64 props) const {  // Not tested.\n    bool remove_epsilons =\n        (symbol_mapping_->size() > 0 && (*symbol_mapping_)[0] != 0);\n    bool add_epsilons = (symbol_mapping_->size() > 1 &&\n                         *std::min_element(symbol_mapping_->begin() + 1,\n                                           symbol_mapping_->end()) == 0);\n\n    // remove the following as we don't know now if any of them are true.\n    uint64 props_to_remove = kAcceptor | kNotAcceptor | kIDeterministic |\n                             kNonIDeterministic | kILabelSorted |\n                             kNotILabelSorted;\n    if (remove_epsilons) props_to_remove |= kEpsilons | kIEpsilons;\n    if (add_epsilons) props_to_remove |= kNoEpsilons | kNoIEpsilons;\n    uint64 props_to_add = 0;\n    if (remove_epsilons && !add_epsilons)\n      props_to_add |= kNoEpsilons | kNoIEpsilons;\n    return (props & ~props_to_remove) | props_to_add;\n  }\n  // initialize with copy = false only if the \"to_remove\" argument will not be\n  // deleted in the lifetime of this object.\n  MapInputSymbolsMapper(const std::vector<I> &to_remove, bool copy) {\n    KALDI_ASSERT_IS_INTEGER_TYPE(I);\n    if (copy)\n      symbol_mapping_ = new std::vector<I>(to_remove);\n    else\n      symbol_mapping_ = &to_remove;\n    owned = copy;\n  }\n  ~MapInputSymbolsMapper() {\n    if (owned && symbol_mapping_ != NULL) delete symbol_mapping_;\n  }\n\n private:\n  bool owned;\n  const std::vector<I> *symbol_mapping_;\n};\n\ntemplate <class Arc, class I>\nvoid MapInputSymbols(const std::vector<I> &symbol_mapping,\n                     MutableFst<Arc> *fst) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  // false == don't copy the \"symbol_mapping\", retain pointer--\n  // safe since short-lived object.\n  MapInputSymbolsMapper<Arc, I> mapper(symbol_mapping, false);\n  Map(fst, mapper);\n}\n\ntemplate <class Arc, class I>\nbool GetLinearSymbolSequence(const Fst<Arc> &fst, std::vector<I> *isymbols_out,\n                             std::vector<I> *osymbols_out,\n                             typename Arc::Weight *tot_weight_out) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n\n  Weight tot_weight = Weight::One();\n  std::vector<I> ilabel_seq;\n  std::vector<I> olabel_seq;\n\n  StateId cur_state = fst.Start();\n  if (cur_state == kNoStateId) {  // empty sequence.\n    if (isymbols_out != NULL) isymbols_out->clear();\n    if (osymbols_out != NULL) osymbols_out->clear();\n    if (tot_weight_out != NULL) *tot_weight_out = Weight::Zero();\n    return true;\n  }\n  while (1) {\n    Weight w = fst.Final(cur_state);\n    if (w != Weight::Zero()) {  // is final..\n      tot_weight = Times(w, tot_weight);\n      if (fst.NumArcs(cur_state) != 0) return false;\n      if (isymbols_out != NULL) *isymbols_out = ilabel_seq;\n      if (osymbols_out != NULL) *osymbols_out = olabel_seq;\n      if (tot_weight_out != NULL) *tot_weight_out = tot_weight;\n      return true;\n    } else {\n      if (fst.NumArcs(cur_state) != 1) return false;\n\n      ArcIterator<Fst<Arc> > iter(fst, cur_state);  // get the only arc.\n      const Arc &arc = iter.Value();\n      tot_weight = Times(arc.weight, tot_weight);\n      if (arc.ilabel != 0) ilabel_seq.push_back(arc.ilabel);\n      if (arc.olabel != 0) olabel_seq.push_back(arc.olabel);\n      cur_state = arc.nextstate;\n    }\n  }\n}\n\n// see fstext-utils.h for comment.\ntemplate <class Arc>\nvoid ConvertNbestToVector(const Fst<Arc> &fst,\n                          std::vector<VectorFst<Arc> > *fsts_out) {\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId StateId;\n  fsts_out->clear();\n  StateId start_state = fst.Start();\n  if (start_state == kNoStateId) return;  // No output.\n  size_t n_arcs = fst.NumArcs(start_state);\n  bool start_is_final = (fst.Final(start_state) != Weight::Zero());\n  fsts_out->reserve(n_arcs + (start_is_final ? 1 : 0));\n\n  if (start_is_final) {\n    fsts_out->resize(fsts_out->size() + 1);\n    StateId start_state_out = fsts_out->back().AddState();\n    fsts_out->back().SetFinal(start_state_out, fst.Final(start_state));\n  }\n\n  for (ArcIterator<Fst<Arc> > start_aiter(fst, start_state);\n       !start_aiter.Done(); start_aiter.Next()) {\n    fsts_out->resize(fsts_out->size() + 1);\n    VectorFst<Arc> &ofst = fsts_out->back();\n    const Arc &first_arc = start_aiter.Value();\n    StateId cur_state = start_state, cur_ostate = ofst.AddState();\n    ofst.SetStart(cur_ostate);\n    StateId next_ostate = ofst.AddState();\n    ofst.AddArc(cur_ostate, Arc(first_arc.ilabel, first_arc.olabel,\n                                first_arc.weight, next_ostate));\n    cur_state = first_arc.nextstate;\n    cur_ostate = next_ostate;\n    while (1) {\n      size_t this_n_arcs = fst.NumArcs(cur_state);\n      KALDI_ASSERT(this_n_arcs <= 1);  // or it violates our assumptions\n                                       // about the input.\n      if (this_n_arcs == 1) {\n        KALDI_ASSERT(fst.Final(cur_state) == Weight::Zero());\n        // or problem with ShortestPath.\n        ArcIterator<Fst<Arc> > aiter(fst, cur_state);\n        const Arc &arc = aiter.Value();\n        next_ostate = ofst.AddState();\n        ofst.AddArc(cur_ostate,\n                    Arc(arc.ilabel, arc.olabel, arc.weight, next_ostate));\n        cur_state = arc.nextstate;\n        cur_ostate = next_ostate;\n      } else {\n        KALDI_ASSERT(fst.Final(cur_state) != Weight::Zero());\n        // or problem with ShortestPath.\n        ofst.SetFinal(cur_ostate, fst.Final(cur_state));\n        break;\n      }\n    }\n  }\n}\n\n// see fstext-utils.sh for comment.\ntemplate <class Arc>\nvoid NbestAsFsts(const Fst<Arc> &fst, size_t n,\n                 std::vector<VectorFst<Arc> > *fsts_out) {\n  KALDI_ASSERT(n > 0);\n  KALDI_ASSERT(fsts_out != NULL);\n  VectorFst<Arc> nbest_fst;\n  ShortestPath(fst, &nbest_fst, n);\n  ConvertNbestToVector(nbest_fst, fsts_out);\n}\n\ntemplate <class Arc, class I>\nvoid MakeLinearAcceptorWithAlternatives(\n    const std::vector<std::vector<I> > &labels, MutableFst<Arc> *ofst) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n\n  ofst->DeleteStates();\n  StateId cur_state = ofst->AddState();\n  ofst->SetStart(cur_state);\n  for (size_t i = 0; i < labels.size(); i++) {\n    KALDI_ASSERT(labels[i].size() != 0);\n    StateId next_state = ofst->AddState();\n    for (size_t j = 0; j < labels[i].size(); j++) {\n      Arc arc(labels[i][j], labels[i][j], Weight::One(), next_state);\n      ofst->AddArc(cur_state, arc);\n    }\n    cur_state = next_state;\n  }\n  ofst->SetFinal(cur_state, Weight::One());\n}\n\ntemplate <class Arc, class I>\nvoid MakeLinearAcceptor(const std::vector<I> &labels, MutableFst<Arc> *ofst) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n\n  ofst->DeleteStates();\n  StateId cur_state = ofst->AddState();\n  ofst->SetStart(cur_state);\n  for (size_t i = 0; i < labels.size(); i++) {\n    StateId next_state = ofst->AddState();\n    Arc arc(labels[i], labels[i], Weight::One(), next_state);\n    ofst->AddArc(cur_state, arc);\n    cur_state = next_state;\n  }\n  ofst->SetFinal(cur_state, Weight::One());\n}\n\ntemplate <class I>\nvoid GetSymbols(const SymbolTable &symtab, bool include_eps,\n                std::vector<I> *syms_out) {\n  KALDI_ASSERT(syms_out != NULL);\n  syms_out->clear();\n  for (SymbolTableIterator iter(symtab); !iter.Done(); iter.Next()) {\n    if (include_eps || iter.Value() != 0) {\n      syms_out->push_back(iter.Value());\n      KALDI_ASSERT(syms_out->back() ==\n                   iter.Value());  // an integer-range thing.\n    }\n  }\n}\n\ntemplate <class Arc>\nvoid SafeDeterminizeWrapper(MutableFst<Arc> *ifst, MutableFst<Arc> *ofst,\n                            float delta) {\n  typename Arc::Label highest_sym = HighestNumberedInputSymbol(*ifst);\n  std::vector<typename Arc::Label> extra_syms;\n  PreDeterminize(ifst, (typename Arc::Label)(highest_sym + 1), &extra_syms);\n  DeterminizeStar(*ifst, ofst, delta);\n  RemoveSomeInputSymbols(extra_syms, ofst);  // remove the extra symbols.\n}\n\ntemplate <class Arc>\nvoid SafeDeterminizeMinimizeWrapper(MutableFst<Arc> *ifst, VectorFst<Arc> *ofst,\n                                    float delta) {\n  typename Arc::Label highest_sym = HighestNumberedInputSymbol(*ifst);\n  std::vector<typename Arc::Label> extra_syms;\n  PreDeterminize(ifst, (typename Arc::Label)(highest_sym + 1), &extra_syms);\n  DeterminizeStar(*ifst, ofst, delta);\n  RemoveSomeInputSymbols(extra_syms, ofst);  // remove the extra symbols.\n  RemoveEpsLocal(ofst);  // this is \"safe\" and will never hurt.\n  MinimizeEncoded(ofst, delta);\n}\n\ninline void DeterminizeStarInLog(VectorFst<StdArc> *fst, float delta,\n                                 bool *debug_ptr, int max_states) {\n  // DeterminizeStarInLog determinizes 'fst' in the log semiring, using\n  // the DeterminizeStar algorithm (which also removes epsilons).\n\n  ArcSort(fst, ILabelCompare<StdArc>());  // helps DeterminizeStar to be faster.\n  VectorFst<LogArc> *fst_log =\n      new VectorFst<LogArc>;  // Want to determinize in log semiring.\n  Cast(*fst, fst_log);\n  VectorFst<StdArc> tmp;\n  *fst = tmp;  // make fst empty to free up memory. [actually may make no\n               // difference..]\n  VectorFst<LogArc> *fst_det_log = new VectorFst<LogArc>;\n  DeterminizeStar(*fst_log, fst_det_log, delta, debug_ptr, max_states);\n  Cast(*fst_det_log, fst);\n  delete fst_log;\n  delete fst_det_log;\n}\n\ninline void DeterminizeInLog(VectorFst<StdArc> *fst) {\n  // DeterminizeInLog determinizes 'fst' in the log semiring.\n\n  ArcSort(fst, ILabelCompare<StdArc>());  // helps DeterminizeStar to be faster.\n  VectorFst<LogArc> *fst_log =\n      new VectorFst<LogArc>;  // Want to determinize in log semiring.\n  Cast(*fst, fst_log);\n  VectorFst<StdArc> tmp;\n  *fst = tmp;  // make fst empty to free up memory. [actually may make no\n               // difference..]\n  VectorFst<LogArc> *fst_det_log = new VectorFst<LogArc>;\n  Determinize(*fst_log, fst_det_log);\n  Cast(*fst_det_log, fst);\n  delete fst_log;\n  delete fst_det_log;\n}\n\n// make it inline to avoid having to put it in a .cc file.\n// destructive algorithm (changes ifst as well as ofst).\ninline void SafeDeterminizeMinimizeWrapperInLog(VectorFst<StdArc> *ifst,\n                                                VectorFst<StdArc> *ofst,\n                                                float delta) {\n  VectorFst<LogArc> *ifst_log =\n      new VectorFst<LogArc>;  // Want to determinize in log semiring.\n  Cast(*ifst, ifst_log);\n  VectorFst<LogArc> *ofst_log = new VectorFst<LogArc>;\n  SafeDeterminizeWrapper(ifst_log, ofst_log, delta);\n  Cast(*ofst_log, ofst);\n  delete ifst_log;\n  delete ofst_log;\n  RemoveEpsLocal(ofst);  // this is \"safe\" and will never hurt.  Do this in\n                         // tropical, which is important.\n  MinimizeEncoded(ofst, delta);  // Non-deterministic minimization will fail in\n                                 // log semiring so do it with StdARc.\n}\n\ninline void SafeDeterminizeWrapperInLog(VectorFst<StdArc> *ifst,\n                                        VectorFst<StdArc> *ofst, float delta) {\n  VectorFst<LogArc> *ifst_log =\n      new VectorFst<LogArc>;  // Want to determinize in log semiring.\n  Cast(*ifst, ifst_log);\n  VectorFst<LogArc> *ofst_log = new VectorFst<LogArc>;\n  SafeDeterminizeWrapper(ifst_log, ofst_log, delta);\n  Cast(*ofst_log, ofst);\n  delete ifst_log;\n  delete ofst_log;\n}\n\ntemplate <class Arc>\nvoid RemoveWeights(MutableFst<Arc> *ifst) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n\n  for (StateIterator<MutableFst<Arc> > siter(*ifst); !siter.Done();\n       siter.Next()) {\n    StateId s = siter.Value();\n    for (MutableArcIterator<MutableFst<Arc> > aiter(ifst, s); !aiter.Done();\n         aiter.Next()) {\n      Arc arc(aiter.Value());\n      arc.weight = Weight::One();\n      aiter.SetValue(arc);\n    }\n    if (ifst->Final(s) != Weight::Zero()) ifst->SetFinal(s, Weight::One());\n  }\n  ifst->SetProperties(kUnweighted, kUnweighted);\n}\n\n// Used in PrecedingInputSymbolsAreSame (non-functor version), and\n// similar routines.\ntemplate <class T>\nstruct IdentityFunction {\n  typedef T Arg;\n  typedef T Result;\n  T operator()(const T &t) const { return t; }\n};\n\ntemplate <class Arc>\nbool PrecedingInputSymbolsAreSame(bool start_is_epsilon, const Fst<Arc> &fst) {\n  IdentityFunction<typename Arc::Label> f;\n  return PrecedingInputSymbolsAreSameClass(start_is_epsilon, fst, f);\n}\n\ntemplate <class Arc, class F>  // F is functor type from labels to classes.\nbool PrecedingInputSymbolsAreSameClass(bool start_is_epsilon,\n                                       const Fst<Arc> &fst, const F &f) {\n  typedef typename F::Result ClassType;\n  typedef typename Arc::StateId StateId;\n  std::vector<ClassType> classes;\n  ClassType noClass = f(kNoLabel);\n\n  if (start_is_epsilon) {\n    StateId start_state = fst.Start();\n    if (start_state < 0 || start_state == kNoStateId)\n      return true;  // empty fst-- doesn't matter.\n    classes.resize(start_state + 1, noClass);\n    classes[start_state] = 0;\n  }\n\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (classes.size() <= arc.nextstate)\n        classes.resize(arc.nextstate + 1, noClass);\n      if (classes[arc.nextstate] == noClass)\n        classes[arc.nextstate] = f(arc.ilabel);\n      else if (classes[arc.nextstate] != f(arc.ilabel))\n        return false;\n    }\n  }\n  return true;\n}\n\ntemplate <class Arc>\nbool FollowingInputSymbolsAreSame(bool end_is_epsilon, const Fst<Arc> &fst) {\n  IdentityFunction<typename Arc::Label> f;\n  return FollowingInputSymbolsAreSameClass(end_is_epsilon, fst, f);\n}\n\ntemplate <class Arc, class F>\nbool FollowingInputSymbolsAreSameClass(bool end_is_epsilon, const Fst<Arc> &fst,\n                                       const F &f) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  typedef typename F::Result ClassType;\n  const ClassType noClass = f(kNoLabel), epsClass = f(0);\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    ClassType c = noClass;\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (c == noClass)\n        c = f(arc.ilabel);\n      else if (c != f(arc.ilabel))\n        return false;\n    }\n    if (end_is_epsilon && c != noClass && c != epsClass &&\n        fst.Final(s) != Weight::Zero())\n      return false;\n  }\n  return true;\n}\n\ntemplate <class Arc>\nvoid MakePrecedingInputSymbolsSame(bool start_is_epsilon,\n                                   MutableFst<Arc> *fst) {\n  IdentityFunction<typename Arc::Label> f;\n  MakePrecedingInputSymbolsSameClass(start_is_epsilon, fst, f);\n}\n\ntemplate <class Arc, class F>\nvoid MakePrecedingInputSymbolsSameClass(bool start_is_epsilon,\n                                        MutableFst<Arc> *fst, const F &f) {\n  typedef typename F::Result ClassType;\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  std::vector<ClassType> classes;\n  ClassType noClass = f(kNoLabel);\n  ClassType epsClass = f(0);\n  if (start_is_epsilon) {  // treat having-start-state as epsilon in-transition.\n    StateId start_state = fst->Start();\n    if (start_state < 0 || start_state == kNoStateId)  // empty FST.\n      return;\n    classes.resize(start_state + 1, noClass);\n    classes[start_state] = epsClass;\n  }\n\n  // Find bad states (states with multiple input-symbols into them).\n  std::set<StateId> bad_states;  // states that we need to change.\n  for (StateIterator<Fst<Arc> > siter(*fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(*fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (classes.size() <= static_cast<size_t>(arc.nextstate))\n        classes.resize(arc.nextstate + 1, noClass);\n      if (classes[arc.nextstate] == noClass)\n        classes[arc.nextstate] = f(arc.ilabel);\n      else if (classes[arc.nextstate] != f(arc.ilabel))\n        bad_states.insert(arc.nextstate);\n    }\n  }\n  if (bad_states.empty()) return;  // Nothing to do.\n  kaldi::ConstIntegerSet<StateId> bad_states_ciset(\n      bad_states);  // faster lookup.\n\n  // Work out list of arcs we have to change as (state, arc-offset).\n  // Can't do the actual changes in this pass, since we have to add new\n  // states which invalidates the iterators.\n  std::vector<std::pair<StateId, size_t> > arcs_to_change;\n  for (StateIterator<Fst<Arc> > siter(*fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    for (ArcIterator<Fst<Arc> > aiter(*fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel != 0 && bad_states_ciset.count(arc.nextstate) != 0)\n        arcs_to_change.push_back(std::make_pair(s, aiter.Position()));\n    }\n  }\n  KALDI_ASSERT(!arcs_to_change.empty());  // since !bad_states.empty().\n\n  std::map<std::pair<StateId, ClassType>, StateId> state_map;\n  // state_map is a map from (bad-state, input-symbol-class) to dummy-state.\n\n  for (size_t i = 0; i < arcs_to_change.size(); i++) {\n    StateId s = arcs_to_change[i].first;\n    ArcIterator<MutableFst<Arc> > aiter(*fst, s);\n    aiter.Seek(arcs_to_change[i].second);\n    Arc arc = aiter.Value();\n\n    // Transition is non-eps transition to \"bad\" state.  Introduce new state (or\n    // find existing one).\n    std::pair<StateId, ClassType> p(arc.nextstate, f(arc.ilabel));\n    if (state_map.count(p) == 0) {\n      StateId newstate = state_map[p] = fst->AddState();\n      fst->AddArc(newstate, Arc(0, 0, Weight::One(), arc.nextstate));\n    }\n    StateId dst_state = state_map[p];\n    arc.nextstate = dst_state;\n\n    // Initialize the MutableArcIterator only now, as the call to NewState()\n    // may have invalidated the first arc iterator.\n    MutableArcIterator<MutableFst<Arc> > maiter(fst, s);\n    maiter.Seek(arcs_to_change[i].second);\n    maiter.SetValue(arc);\n  }\n}\n\ntemplate <class Arc>\nvoid MakeFollowingInputSymbolsSame(bool end_is_epsilon, MutableFst<Arc> *fst) {\n  IdentityFunction<typename Arc::Label> f;\n  MakeFollowingInputSymbolsSameClass(end_is_epsilon, fst, f);\n}\n\ntemplate <class Arc, class F>\nvoid MakeFollowingInputSymbolsSameClass(bool end_is_epsilon,\n                                        MutableFst<Arc> *fst, const F &f) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  typedef typename F::Result ClassType;\n  std::vector<StateId> bad_states;\n  ClassType noClass = f(kNoLabel);\n  ClassType epsClass = f(0);\n  for (StateIterator<Fst<Arc> > siter(*fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    ClassType c = noClass;\n    bool bad = false;\n    for (ArcIterator<Fst<Arc> > aiter(*fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (c == noClass) {\n        c = f(arc.ilabel);\n      } else if (c != f(arc.ilabel)) {\n        bad = true;\n        break;\n      }\n    }\n    if (end_is_epsilon && c != noClass && c != epsClass &&\n        fst->Final(s) != Weight::Zero())\n      bad = true;\n    if (bad) bad_states.push_back(s);\n  }\n  std::vector<Arc> my_arcs;\n  for (size_t i = 0; i < bad_states.size(); i++) {\n    StateId s = bad_states[i];\n    my_arcs.clear();\n    for (ArcIterator<MutableFst<Arc> > aiter(*fst, s); !aiter.Done();\n         aiter.Next())\n      my_arcs.push_back(aiter.Value());\n\n    for (size_t j = 0; j < my_arcs.size(); j++) {\n      Arc &arc = my_arcs[j];\n      if (arc.ilabel != 0) {\n        StateId newstate = fst->AddState();\n        // Create a new state for each non-eps arc in original FST, out of each\n        // bad state. Not as optimal as it could be, but does avoid some\n        // complicated weight-pushing issues in which, to maintain\n        // stochasticity, we would have to know which semiring we want to\n        // maintain stochasticity in.\n        fst->AddArc(newstate, Arc(arc.ilabel, 0, Weight::One(), arc.nextstate));\n        MutableArcIterator<MutableFst<Arc> > maiter(fst, s);\n        maiter.Seek(j);\n        maiter.SetValue(Arc(0, arc.olabel, arc.weight, newstate));\n      }\n    }\n  }\n}\n\ntemplate <class Arc>\nVectorFst<Arc> *MakeLoopFst(const std::vector<const ExpandedFst<Arc> *> &fsts) {\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Label Label;\n\n  VectorFst<Arc> *ans = new VectorFst<Arc>;\n  StateId loop_state = ans->AddState();  // = 0.\n  ans->SetStart(loop_state);\n  ans->SetFinal(loop_state, Weight::One());\n\n  // \"cache\" is used as an optimization when some of the pointers in \"fsts\"\n  // may have the same value.\n  unordered_map<const ExpandedFst<Arc> *, Arc> cache;\n\n  for (Label i = 0; i < static_cast<Label>(fsts.size()); i++) {\n    const ExpandedFst<Arc> *fst = fsts[i];\n    if (fst == NULL) continue;\n    {  // optimization with cache: helpful if some members of \"fsts\" may\n      // contain the same pointer value (e.g. in GetHTransducer).\n      typename unordered_map<const ExpandedFst<Arc> *, Arc>::iterator iter =\n          cache.find(fst);\n      if (iter != cache.end()) {\n        Arc arc = iter->second;\n        arc.olabel = i;\n        ans->AddArc(0, arc);\n        continue;\n      }\n    }\n\n    KALDI_ASSERT(fst->Properties(kAcceptor, true) ==\n                 kAcceptor);  // expect acceptor.\n\n    StateId fst_num_states = fst->NumStates();\n    StateId fst_start_state = fst->Start();\n\n    if (fst_start_state == kNoStateId) continue;  // empty fst.\n\n    bool share_start_state =\n        fst->Properties(kInitialAcyclic, true) == kInitialAcyclic &&\n        fst->NumArcs(fst_start_state) == 1 &&\n        fst->Final(fst_start_state) == Weight::Zero();\n\n    std::vector<StateId> state_map(fst_num_states);  // fst state -> ans state\n    for (StateId s = 0; s < fst_num_states; s++) {\n      if (s == fst_start_state && share_start_state)\n        state_map[s] = loop_state;\n      else\n        state_map[s] = ans->AddState();\n    }\n    if (!share_start_state) {\n      Arc arc(0, i, Weight::One(), state_map[fst_start_state]);\n      cache[fst] = arc;\n      ans->AddArc(0, arc);\n    }\n    for (StateId s = 0; s < fst_num_states; s++) {\n      // Add arcs out of state s.\n      for (ArcIterator<ExpandedFst<Arc> > aiter(*fst, s); !aiter.Done();\n           aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        Label olabel = (s == fst_start_state && share_start_state ? i : 0);\n        Arc newarc(arc.ilabel, olabel, arc.weight, state_map[arc.nextstate]);\n        ans->AddArc(state_map[s], newarc);\n        if (s == fst_start_state && share_start_state) cache[fst] = newarc;\n      }\n      if (fst->Final(s) != Weight::Zero()) {\n        KALDI_ASSERT(!(s == fst_start_state && share_start_state));\n        ans->AddArc(state_map[s], Arc(0, 0, fst->Final(s), loop_state));\n      }\n    }\n  }\n  return ans;\n}\n\ntemplate <class Arc>\nvoid ClearSymbols(bool clear_input, bool clear_output, MutableFst<Arc> *fst) {\n  for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n       siter.Next()) {\n    typename Arc::StateId s = siter.Value();\n    for (MutableArcIterator<MutableFst<Arc> > aiter(fst, s); !aiter.Done();\n         aiter.Next()) {\n      Arc arc = aiter.Value();\n      bool change = false;\n      if (clear_input && arc.ilabel != 0) {\n        arc.ilabel = 0;\n        change = true;\n      }\n      if (clear_output && arc.olabel != 0) {\n        arc.olabel = 0;\n        change = true;\n      }\n      if (change) {\n        aiter.SetValue(arc);\n      }\n    }\n  }\n}\n\ntemplate <class Arc>\nvoid ApplyProbabilityScale(float scale, MutableFst<Arc> *fst) {\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId StateId;\n  for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n       siter.Next()) {\n    StateId s = siter.Value();\n    for (MutableArcIterator<MutableFst<Arc> > aiter(fst, s); !aiter.Done();\n         aiter.Next()) {\n      Arc arc = aiter.Value();\n      arc.weight = Weight(arc.weight.Value() * scale);\n      aiter.SetValue(arc);\n    }\n    if (fst->Final(s) != Weight::Zero())\n      fst->SetFinal(s, Weight(fst->Final(s).Value() * scale));\n  }\n}\n\n// return arc-offset of self-loop with ilabel (or -1 if none exists).\n// if more than one such self-loop, pick first one.\ntemplate <class Arc>\nssize_t FindSelfLoopWithILabel(const Fst<Arc> &fst, typename Arc::StateId s) {\n  for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next())\n    if (aiter.Value().nextstate == s && aiter.Value().ilabel != 0)\n      return static_cast<ssize_t>(aiter.Position());\n  return static_cast<ssize_t>(-1);\n}\n\ntemplate <class Arc>\nbool EqualAlign(const Fst<Arc> &ifst, typename Arc::StateId length,\n                int rand_seed, MutableFst<Arc> *ofst, int num_retries) {\n  srand(rand_seed);\n  KALDI_ASSERT(ofst->NumStates() == 0);  // make sure ofst empty.\n  // make sure all states can reach final-state (or this algorithm may enter\n  // infinite loop.\n  KALDI_ASSERT(ifst.Properties(kCoAccessible, true) == kCoAccessible);\n\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n\n  if (ifst.Start() == kNoStateId) {\n    KALDI_WARN << \"Empty input fst.\";\n    return false;\n  }\n  // First select path through ifst.\n  std::vector<StateId> path;\n  std::vector<size_t> arc_offsets;  // arc taken out of each state.\n  std::vector<int> nof_ilabels;\n\n  StateId num_ilabels = 0;\n  int retry_no = 0;\n\n  // Under normal circumstances, this will be one-pass-only process\n  // Multiple tries might be needed in special cases, typically when\n  // the number of frames is close to number of transitions from\n  // the start node to the final node. It usually happens for really\n  // short utterances\n  do {\n    num_ilabels = 0;\n    arc_offsets.clear();\n    path.clear();\n    path.push_back(ifst.Start());\n\n    while (1) {\n      // Select either an arc or final-prob.\n      StateId s = path.back();\n      size_t num_arcs = ifst.NumArcs(s);\n      size_t num_arcs_tot = num_arcs;\n      if (ifst.Final(s) != Weight::Zero()) num_arcs_tot++;\n      // kaldi::RandInt is a bit like Rand(), but gets around situations\n      // where RAND_MAX is very small.\n      // Change this to Rand() % num_arcs_tot if compile issues arise\n      size_t arc_offset =\n          static_cast<size_t>(kaldi::RandInt(0, num_arcs_tot - 1));\n\n      if (arc_offset < num_arcs) {  // an actual arc.\n        ArcIterator<Fst<Arc> > aiter(ifst, s);\n        aiter.Seek(arc_offset);\n        const Arc &arc = aiter.Value();\n        if (arc.nextstate == s) {\n          continue;  // don't take this self-loop arc\n        } else {\n          arc_offsets.push_back(arc_offset);\n          path.push_back(arc.nextstate);\n          if (arc.ilabel != 0) num_ilabels++;\n        }\n      } else {\n        break;  // Chose final-prob.\n      }\n    }\n\n    nof_ilabels.push_back(num_ilabels);\n  } while ((++retry_no < num_retries) && (num_ilabels > length));\n\n  if (num_ilabels > length) {\n    std::stringstream ilabel_vec;\n    std::copy(nof_ilabels.begin(), nof_ilabels.end(),\n              std::ostream_iterator<int>(ilabel_vec, \",\"));\n    std::string s = ilabel_vec.str();\n    s.erase(s.end() - 1);\n    KALDI_WARN << \"EqualAlign: the randomly constructed paths lengths: \" << s;\n    KALDI_WARN << \"EqualAlign: utterance has too few frames \" << length\n               << \" to align.\";\n    return false;  // can't make it shorter by adding self-loops!.\n  }\n\n  StateId num_self_loops = 0;\n  std::vector<ssize_t> self_loop_offsets(path.size());\n  for (size_t i = 0; i < path.size(); i++)\n    if ((self_loop_offsets[i] = FindSelfLoopWithILabel(ifst, path[i])) !=\n        static_cast<ssize_t>(-1))\n      num_self_loops++;\n\n  if (num_self_loops == 0 && num_ilabels < length) {\n    KALDI_WARN << \"No self-loops on chosen path; cannot match length.\";\n    return false;  // no self-loops to make it longer.\n  }\n\n  StateId num_extra = length - num_ilabels;  // Number of self-loops we need.\n\n  StateId min_num_loops = 0;\n  if (num_extra != 0)\n    min_num_loops = num_extra / num_self_loops;  // prevent div by zero.\n  StateId num_with_one_more_loop = num_extra - (min_num_loops * num_self_loops);\n  KALDI_ASSERT(num_with_one_more_loop < num_self_loops || num_self_loops == 0);\n\n  ofst->AddState();\n  ofst->SetStart(0);\n  StateId cur_state = 0;\n  StateId counter = 0;  // tell us when we should stop adding one more loop.\n  for (size_t i = 0; i < path.size(); i++) {\n    // First, add any self-loops that are necessary.\n    StateId num_loops = 0;\n    if (self_loop_offsets[i] != static_cast<ssize_t>(-1)) {\n      num_loops = min_num_loops + (counter < num_with_one_more_loop ? 1 : 0);\n      counter++;\n    }\n    for (StateId j = 0; j < num_loops; j++) {\n      ArcIterator<Fst<Arc> > aiter(ifst, path[i]);\n      aiter.Seek(self_loop_offsets[i]);\n      Arc arc = aiter.Value();\n      KALDI_ASSERT(arc.nextstate == path[i] &&\n                   arc.ilabel != 0);  // make sure self-loop with ilabel.\n      StateId next_state = ofst->AddState();\n      ofst->AddArc(cur_state,\n                   Arc(arc.ilabel, arc.olabel, arc.weight, next_state));\n      cur_state = next_state;\n    }\n    if (i + 1 < path.size()) {  // add forward transition.\n      ArcIterator<Fst<Arc> > aiter(ifst, path[i]);\n      aiter.Seek(arc_offsets[i]);\n      Arc arc = aiter.Value();\n      KALDI_ASSERT(arc.nextstate == path[i + 1]);\n      StateId next_state = ofst->AddState();\n      ofst->AddArc(cur_state,\n                   Arc(arc.ilabel, arc.olabel, arc.weight, next_state));\n      cur_state = next_state;\n    } else {  // add final-prob.\n      Weight weight = ifst.Final(path[i]);\n      KALDI_ASSERT(weight != Weight::Zero());\n      ofst->SetFinal(cur_state, weight);\n    }\n  }\n  return true;\n}\n\n// This function identifies two types of useless arcs:\n// those where arc A and arc B both go from state X to\n// state Y with the same input symbol (remove the one\n// with smaller probability, or an arbitrary one if they\n// are the same); and those where A is an arc from state X\n// to state X, with epsilon input symbol [remove A].\n// Only works for tropical (not log) semiring as it uses\n// NaturalLess.\ntemplate <class Arc>\nvoid RemoveUselessArcs(MutableFst<Arc> *fst) {\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  NaturalLess<Weight> nl;\n  StateId non_coacc_state = kNoStateId;\n  size_t num_arcs_removed = 0, tot_arcs = 0;\n  for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n       siter.Next()) {\n    std::vector<size_t> arcs_to_delete;\n    std::vector<Arc> arcs;\n    // pair2arclist lets us look up the arcs\n    std::map<std::pair<Label, StateId>, std::vector<size_t> > pair2arclist;\n    StateId state = siter.Value();\n    for (ArcIterator<MutableFst<Arc> > aiter(*fst, state); !aiter.Done();\n         aiter.Next()) {\n      size_t pos = arcs.size();\n      const Arc &arc = aiter.Value();\n      arcs.push_back(arc);\n      pair2arclist[std::make_pair(arc.ilabel, arc.nextstate)].push_back(pos);\n    }\n    typename std::map<std::pair<Label, StateId>, std::vector<size_t> >::iterator\n        iter = pair2arclist.begin(),\n        end = pair2arclist.end();\n    for (; iter != end; ++iter) {\n      const std::vector<size_t> &poslist = iter->second;\n      if (poslist.size() > 1) {  // >1 arc with same ilabel, dest-state\n        size_t best_pos = poslist[0];\n        Weight best_weight = arcs[best_pos].weight;\n        for (size_t j = 1; j < poslist.size(); j++) {\n          size_t pos = poslist[j];\n          Weight this_weight = arcs[pos].weight;\n          if (nl(this_weight,\n                 best_weight)) {  // NaturalLess seems to be somehow\n            // \"backwards\".\n            best_weight = this_weight;  // found a better one.\n            best_pos = pos;\n          }\n        }\n        for (size_t j = 0; j < poslist.size(); j++)\n          if (poslist[j] != best_pos) arcs_to_delete.push_back(poslist[j]);\n      } else {\n        KALDI_ASSERT(poslist.size() == 1);\n        size_t pos = poslist[0];\n        Arc &arc = arcs[pos];\n        if (arc.ilabel == 0 && arc.nextstate == state)\n          arcs_to_delete.push_back(pos);\n      }\n    }\n    tot_arcs += arcs.size();\n    if (arcs_to_delete.size() != 0) {\n      num_arcs_removed += arcs_to_delete.size();\n      if (non_coacc_state == kNoStateId) non_coacc_state = fst->AddState();\n      MutableArcIterator<MutableFst<Arc> > maiter(fst, state);\n      for (size_t j = 0; j < arcs_to_delete.size(); j++) {\n        size_t pos = arcs_to_delete[j];\n        maiter.Seek(pos);\n        arcs[pos].nextstate = non_coacc_state;\n        maiter.SetValue(arcs[pos]);\n      }\n    }\n  }\n  if (non_coacc_state != kNoStateId) Connect(fst);\n  KALDI_VLOG(1) << \"removed \" << num_arcs_removed << \" of \" << tot_arcs\n                << \"arcs.\";\n}\n\ntemplate <class Arc>\nvoid PhiCompose(const Fst<Arc> &fst1, const Fst<Arc> &fst2,\n                typename Arc::Label phi_label, MutableFst<Arc> *ofst) {\n  KALDI_ASSERT(phi_label !=\n               kNoLabel);  // just use regular compose in this case.\n  typedef Fst<Arc> F;\n  typedef PhiMatcher<SortedMatcher<F> > PM;\n  CacheOptions base_opts;\n  base_opts.gc_limit = 0;  // Cache only the last state for fastest copy.\n  // ComposeFstImplOptions templated on matcher for fst1, matcher for fst2.\n  // The matcher for fst1 doesn't matter; we'll use fst2's matcher.\n  ComposeFstImplOptions<SortedMatcher<F>, PM> impl_opts(base_opts);\n\n  // the false below is something called phi_loop which is something I don't\n  // fully understand, but I don't think we want it.\n\n  // These pointers are taken ownership of, by ComposeFst.\n  PM *phi_matcher = new PM(fst2, MATCH_INPUT, phi_label, false);\n  SortedMatcher<F> *sorted_matcher =\n      new SortedMatcher<F>(fst1, MATCH_NONE);  // tell it\n  // not to use this matcher, as this would mean we would\n  // not follow phi transitions.\n  impl_opts.matcher1 = sorted_matcher;\n  impl_opts.matcher2 = phi_matcher;\n  *ofst = ComposeFst<Arc>(fst1, fst2, impl_opts);\n  Connect(ofst);\n}\n\ntemplate <class Arc>\nvoid PropagateFinalInternal(typename Arc::Label phi_label,\n                            typename Arc::StateId s, MutableFst<Arc> *fst) {\n  typedef typename Arc::Weight Weight;\n  if (fst->Final(s) == Weight::Zero()) {\n    // search for phi transition.  We assume there\n    // is just one-- phi nondeterminism is not allowed\n    // anyway.\n    int num_phis = 0;\n    for (ArcIterator<Fst<Arc> > aiter(*fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel == phi_label) {\n        num_phis++;\n        if (arc.nextstate == s) continue;  // don't expect\n        // phi loops but ignore them anyway.\n\n        // If this recurses infinitely, it means there\n        // are loops of phi transitions, which there should\n        // not be in a normal backoff LM.  We could make this\n        // routine work for this case, but currently there is\n        // no need.\n        PropagateFinalInternal(phi_label, arc.nextstate, fst);\n        if (fst->Final(arc.nextstate) != Weight::Zero())\n          fst->SetFinal(s, Times(fst->Final(arc.nextstate), arc.weight));\n      }\n      KALDI_ASSERT(num_phis <= 1 && \"Phi nondeterminism found\");\n    }\n  }\n}\n\ntemplate <class Arc>\nvoid PropagateFinal(typename Arc::Label phi_label, MutableFst<Arc> *fst) {\n  typedef typename Arc::StateId StateId;\n  if (fst->Properties(kIEpsilons, true))  // just warn.\n    KALDI_WARN << \"PropagateFinal: this may not work as desired \"\n                  \"since your FST has input epsilons.\";\n  StateId num_states = fst->NumStates();\n  for (StateId s = 0; s < num_states; s++)\n    PropagateFinalInternal(phi_label, s, fst);\n}\n\ntemplate <class Arc>\nvoid RhoCompose(const Fst<Arc> &fst1, const Fst<Arc> &fst2,\n                typename Arc::Label rho_label, MutableFst<Arc> *ofst) {\n  KALDI_ASSERT(rho_label !=\n               kNoLabel);  // just use regular compose in this case.\n  typedef Fst<Arc> F;\n  typedef RhoMatcher<SortedMatcher<F> > RM;\n  CacheOptions base_opts;\n  base_opts.gc_limit = 0;  // Cache only the last state for fastest copy.\n  // ComposeFstImplOptions templated on matcher for fst1, matcher for fst2.\n  // The matcher for fst1 doesn't matter; we'll use fst2's matcher.\n  ComposeFstImplOptions<SortedMatcher<F>, RM> impl_opts(base_opts);\n\n  // the false below is something called rho_loop which is something I don't\n  // fully understand, but I don't think we want it.\n\n  // These pointers are taken ownership of, by ComposeFst.\n  RM *rho_matcher = new RM(fst2, MATCH_INPUT, rho_label);\n  SortedMatcher<F> *sorted_matcher =\n      new SortedMatcher<F>(fst1, MATCH_NONE);  // tell it\n  // not to use this matcher, as this would mean we would\n  // not follow rho transitions.\n  impl_opts.matcher1 = sorted_matcher;\n  impl_opts.matcher2 = rho_matcher;\n  *ofst = ComposeFst<Arc>(fst1, fst2, impl_opts);\n  Connect(ofst);\n}\n\n// Declare an override of the template below.\ntemplate <>\ninline bool IsStochasticFst(const Fst<LogArc> &fst, float delta,\n                            LogArc::Weight *min_sum, LogArc::Weight *max_sum);\n\n// Will override this for LogArc where NaturalLess will not work.\ntemplate <class Arc>\ninline bool IsStochasticFst(const Fst<Arc> &fst, float delta,\n                            typename Arc::Weight *min_sum,\n                            typename Arc::Weight *max_sum) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  NaturalLess<Weight> nl;\n  bool first_time = true;\n  bool ans = true;\n  if (min_sum) *min_sum = Arc::Weight::One();\n  if (max_sum) *max_sum = Arc::Weight::One();\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    Weight sum = fst.Final(s);\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      sum = Plus(sum, arc.weight);\n    }\n    if (!ApproxEqual(Weight::One(), sum, delta)) ans = false;\n    if (first_time) {\n      first_time = false;\n      if (max_sum) *max_sum = sum;\n      if (min_sum) *min_sum = sum;\n    } else {\n      if (max_sum && nl(*max_sum, sum)) *max_sum = sum;\n      if (min_sum && nl(sum, *min_sum)) *min_sum = sum;\n    }\n  }\n  if (first_time) {  // just avoid NaNs if FST was empty.\n    if (max_sum) *max_sum = Weight::One();\n    if (min_sum) *min_sum = Weight::One();\n  }\n  return ans;\n}\n\n// Overriding template for LogArc as NaturalLess does not work there.\ntemplate <>\ninline bool IsStochasticFst(const Fst<LogArc> &fst, float delta,\n                            LogArc::Weight *min_sum, LogArc::Weight *max_sum) {\n  typedef LogArc Arc;\n  typedef Arc::StateId StateId;\n  typedef Arc::Weight Weight;\n  bool first_time = true;\n  bool ans = true;\n  if (min_sum) *min_sum = LogArc::Weight::One();\n  if (max_sum) *max_sum = LogArc::Weight::One();\n  for (StateIterator<Fst<Arc> > siter(fst); !siter.Done(); siter.Next()) {\n    StateId s = siter.Value();\n    Weight sum = fst.Final(s);\n    for (ArcIterator<Fst<Arc> > aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      sum = Plus(sum, arc.weight);\n    }\n    if (!ApproxEqual(Weight::One(), sum, delta)) ans = false;\n    if (first_time) {\n      first_time = false;\n      if (max_sum) *max_sum = sum;\n      if (min_sum) *min_sum = sum;\n    } else {\n      // note that max and min are reversed from their normal\n      // meanings here (max and min w.r.t. the underlying probabilities).\n      if (max_sum && sum.Value() < max_sum->Value()) *max_sum = sum;\n      if (min_sum && sum.Value() > min_sum->Value()) *min_sum = sum;\n    }\n  }\n  if (first_time) {  // just avoid NaNs if FST was empty.\n    if (max_sum) *max_sum = Weight::One();\n    if (min_sum) *min_sum = Weight::One();\n  }\n  return ans;\n}\n\n// Tests whether a tropical FST is stochastic in the log\n// semiring. (casts it and does the check.)\n// This function deals with the generic fst.\n// This version currently supports ConstFst<StdArc> or VectorFst<StdArc>.\n// Otherwise, it will be died with an error.\ninline bool IsStochasticFstInLog(const Fst<StdArc> &fst, float delta,\n                                 StdArc::Weight *min_sum,\n                                 StdArc::Weight *max_sum) {\n  bool ans = false;\n  LogArc::Weight log_min = LogArc::Weight::One(),\n                 log_max = LogArc::Weight::Zero();\n  if (fst.Type() == \"const\") {\n    ConstFst<LogArc> logfst;\n    Cast(dynamic_cast<const ConstFst<StdArc> &>(fst), &logfst);\n    ans = IsStochasticFst(logfst, delta, &log_min, &log_max);\n  } else if (fst.Type() == \"vector\") {\n    VectorFst<LogArc> logfst;\n    Cast(dynamic_cast<const VectorFst<StdArc> &>(fst), &logfst);\n    ans = IsStochasticFst(logfst, delta, &log_min, &log_max);\n  } else {\n    KALDI_ERR << \"This version currently supports ConstFst<StdArc> \"\n              << \"or VectorFst<StdArc>\";\n  }\n  if (min_sum) *min_sum = StdArc::Weight(log_min.Value());\n  if (max_sum) *max_sum = StdArc::Weight(log_max.Value());\n  return ans;\n}\n\n}  // namespace fst.\n\n#endif  // KALDI_FSTEXT_FSTEXT_UTILS_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/fstext-utils.h",
    "content": "// fstext/fstext-utils.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//           2012-2013  Johns Hopkins University (Author: Daniel Povey)\n//                2013  Guoguo Chen\n//                2014  Telepoint Global Hosting Service, LLC. (Author: David\n//                Snyder)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_FSTEXT_UTILS_H_\n#define KALDI_FSTEXT_FSTEXT_UTILS_H_\n\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n\n#include <algorithm>\n#include <map>\n#include <set>\n#include <vector>\n\n#include \"fstext/determinize-star.h\"\n#include \"fstext/remove-eps-local.h\"\n#include \"base/kaldi-common.h\"  // for error reporting macros.\n#include \"util/text-utils.h\"  // for SplitStringToVector\n#include \"fst/script/print-impl.h\"\n\nnamespace fst {\n\n/// Returns the highest numbered output symbol id of the FST (or zero\n/// for an empty FST.\ntemplate <class Arc>\ntypename Arc::Label HighestNumberedOutputSymbol(const Fst<Arc> &fst);\n\n/// Returns the highest numbered input symbol id of the FST (or zero\n/// for an empty FST.\ntemplate <class Arc>\ntypename Arc::Label HighestNumberedInputSymbol(const Fst<Arc> &fst);\n\n/// Returns the total number of arcs in an FST.\ntemplate <class Arc>\ntypename Arc::StateId NumArcs(const ExpandedFst<Arc> &fst);\n\n/// GetInputSymbols gets the list of symbols on the input of fst\n/// (including epsilon, if include_eps == true), as a sorted, unique\n/// list.\ntemplate <class Arc, class I>\nvoid GetInputSymbols(const Fst<Arc> &fst, bool include_eps,\n                     std::vector<I> *symbols);\n\n/// GetOutputSymbols gets the list of symbols on the output of fst\n/// (including epsilon, if include_eps == true)\ntemplate <class Arc, class I>\nvoid GetOutputSymbols(const Fst<Arc> &fst, bool include_eps,\n                      std::vector<I> *symbols);\n\n/// ClearSymbols sets all the symbols on the input and/or\n/// output side of the FST to zero, as specified.\n/// It does not alter the symbol tables.\ntemplate <class Arc>\nvoid ClearSymbols(bool clear_input, bool clear_output, MutableFst<Arc> *fst);\n\ntemplate <class I>\nvoid GetSymbols(const SymbolTable &symtab, bool include_eps,\n                std::vector<I> *syms_out);\n\ninline void DeterminizeStarInLog(VectorFst<StdArc> *fst, float delta = kDelta,\n                                 bool *debug_ptr = NULL, int max_states = -1);\n\n// e.g. of using this function: PushInLog<REWEIGHT_TO_INITIAL>(fst,\n// kPushWeights|kPushLabels);\n\ntemplate <ReweightType rtype>  // == REWEIGHT_TO_{INITIAL, FINAL}\nvoid PushInLog(VectorFst<StdArc> *fst, uint32 ptype, float delta = kDelta) {\n  // PushInLog pushes the FST\n  // and returns a new pushed FST (labels and weights pushed to the left).\n  VectorFst<LogArc> *fst_log =\n      new VectorFst<LogArc>;  // Want to determinize in log semiring.\n  Cast(*fst, fst_log);\n  VectorFst<StdArc> tmp;\n  *fst = tmp;  // free up memory.\n  VectorFst<LogArc> *fst_pushed_log = new VectorFst<LogArc>;\n  Push<LogArc, rtype>(*fst_log, fst_pushed_log, ptype, delta);\n  Cast(*fst_pushed_log, fst);\n  delete fst_log;\n  delete fst_pushed_log;\n}\n\n// Minimizes after encoding; applicable to all FSTs.  It is like what you get\n// from the Minimize() function, except it will not push the weights, or the\n// symbols.  This is better for our recipes, as we avoid ever pushing the\n// weights.  However, it will only minimize optimally if your graphs are such\n// that the symbols are as far to the left as they can go, and the weights\n// in combinable paths are the same... hard to formalize this, but it's\n// something that is satisified by our normal FSTs.\ntemplate <class Arc>\nvoid MinimizeEncoded(VectorFst<Arc> *fst, float delta = kDelta) {\n  Map(fst, QuantizeMapper<Arc>(delta));\n  EncodeMapper<Arc> encoder(kEncodeLabels | kEncodeWeights, ENCODE);\n  Encode(fst, &encoder);\n  internal::AcceptorMinimize(fst);\n  Decode(fst, encoder);\n}\n\n/// GetLinearSymbolSequence gets the symbol sequence from a linear FST.\n/// If the FST is not just a linear sequence, it returns false.   If it is\n/// a linear sequence (including the empty FST), it returns true.  In this\n/// case it outputs the symbol\n/// sequences as \"isymbols_out\" and \"osymbols_out\" (removing epsilons), and\n/// the total weight as \"tot_weight\". The total weight will be Weight::Zero()\n/// if the FST is empty.  If any of the output pointers are NULL, it does not\n/// create that output.\ntemplate <class Arc, class I>\nbool GetLinearSymbolSequence(const Fst<Arc> &fst, std::vector<I> *isymbols_out,\n                             std::vector<I> *osymbols_out,\n                             typename Arc::Weight *tot_weight_out);\n\n/// This function converts an FST with a special structure, which is\n/// output by the OpenFst functions ShortestPath and RandGen, and converts\n/// them into a std::vector of separate FSTs.  This special structure is that\n/// the only state that has more than one (arcs-out or final-prob) is the\n/// start state.  fsts_out is resized to the appropriate size.\ntemplate <class Arc>\nvoid ConvertNbestToVector(const Fst<Arc> &fst,\n                          std::vector<VectorFst<Arc> > *fsts_out);\n\n/// Takes the n-shortest-paths (using ShortestPath), but outputs\n/// the result as a vector of up to n fsts.  This function will\n/// size the \"fsts_out\" vector to however many paths it got\n/// (which will not exceed n).  n must be >= 1.\ntemplate <class Arc>\nvoid NbestAsFsts(const Fst<Arc> &fst, size_t n,\n                 std::vector<VectorFst<Arc> > *fsts_out);\n\n/// Creates unweighted linear acceptor from symbol sequence.\ntemplate <class Arc, class I>\nvoid MakeLinearAcceptor(const std::vector<I> &labels, MutableFst<Arc> *ofst);\n\n/// Creates an unweighted acceptor with a linear structure, with alternatives\n/// at each position.  Epsilon is treated like a normal symbol here.\n/// Each position in \"labels\" must have at least one alternative.\ntemplate <class Arc, class I>\nvoid MakeLinearAcceptorWithAlternatives(\n    const std::vector<std::vector<I> > &labels, MutableFst<Arc> *ofst);\n\n/// Does PreDeterminize and DeterminizeStar and then removes the disambiguation\n/// symbols. This is a form of determinization that will never blow up. Note\n/// that ifst is non-const and can be considered to be destroyed by this\n/// operation.\n/// Does not do epsilon removal (RemoveEpsLocal)-- this is so it's safe to cast\n/// to log and do this, and maintain equivalence in tropical.\n\ntemplate <class Arc>\nvoid SafeDeterminizeWrapper(MutableFst<Arc> *ifst, MutableFst<Arc> *ofst,\n                            float delta = kDelta);\n\n/// SafeDeterminizeMinimizeWapper is as SafeDeterminizeWrapper except that it\n/// also minimizes (encoded minimization, which is safe).  This algorithm will\n/// destroy \"ifst\".\ntemplate <class Arc>\nvoid SafeDeterminizeMinimizeWrapper(MutableFst<Arc> *ifst, VectorFst<Arc> *ofst,\n                                    float delta = kDelta);\n\n/// SafeDeterminizeMinimizeWapperInLog is as SafeDeterminizeMinimizeWrapper\n/// except it first casts tothe log semiring.\nvoid SafeDeterminizeMinimizeWrapperInLog(VectorFst<StdArc> *ifst,\n                                         VectorFst<StdArc> *ofst,\n                                         float delta = kDelta);\n\n/// RemoveSomeInputSymbols removes any symbol that appears in \"to_remove\", from\n/// the input side of the FST, replacing them with epsilon.\ntemplate <class Arc, class I>\nvoid RemoveSomeInputSymbols(const std::vector<I> &to_remove,\n                            MutableFst<Arc> *fst);\n\n// MapInputSymbols will replace any input symbol i that is between 0 and\n// symbol_map.size()-1, with symbol_map[i].  It removes the input symbol\n// table of the FST.\ntemplate <class Arc, class I>\nvoid MapInputSymbols(const std::vector<I> &symbol_map, MutableFst<Arc> *fst);\n\ntemplate <class Arc>\nvoid RemoveWeights(MutableFst<Arc> *fst);\n\n/// Returns true if and only if the FST is such that the input symbols\n/// on arcs entering any given state all have the same value.\n/// if \"start_is_epsilon\", treat start-state as an epsilon input arc\n/// [i.e. ensure only epsilon can enter start-state].\ntemplate <class Arc>\nbool PrecedingInputSymbolsAreSame(bool start_is_epsilon, const Fst<Arc> &fst);\n\n/// This is as PrecedingInputSymbolsAreSame, but with a functor f that maps\n/// labels to classes. The function tests whether the symbols preceding any\n/// given state are in the same class. Formally, f is of a type F that has an\n/// operator of type F::Result F::operator() (F::Arg a) const; where F::Result\n/// is an integer type and F::Arc can be constructed from Arc::Label. this must\n/// apply to valid labels and also to kNoLabel (so we can have a marker for the\n/// invalid labels.\ntemplate <class Arc, class F>\nbool PrecedingInputSymbolsAreSameClass(bool start_is_epsilon,\n                                       const Fst<Arc> &fst, const F &f);\n\n/// Returns true if and only if the FST is such that the input symbols\n/// on arcs exiting any given state all have the same value.\n/// If end_is_epsilon, treat end-state as an epsilon output arc [i.e. ensure\n/// end-states cannot have non-epsilon output transitions.]\ntemplate <class Arc>\nbool FollowingInputSymbolsAreSame(bool end_is_epsilon, const Fst<Arc> &fst);\n\ntemplate <class Arc, class F>\nbool FollowingInputSymbolsAreSameClass(bool end_is_epsilon, const Fst<Arc> &fst,\n                                       const F &f);\n\n/// MakePrecedingInputSymbolsSame ensures that all arcs entering any given fst\n/// state have the same input symbol.  It does this by detecting states\n/// that have differing input symbols going in, and inserting, for each of\n/// the preceding arcs with non-epsilon input symbol, a new dummy state that\n/// has an epsilon link to the fst state.\n/// If \"start_is_epsilon\", ensure that start-state can have only epsilon-links\n/// into it.\ntemplate <class Arc>\nvoid MakePrecedingInputSymbolsSame(bool start_is_epsilon, MutableFst<Arc> *fst);\n\n/// As MakePrecedingInputSymbolsSame, but takes a functor object that maps\n/// labels to classes.\ntemplate <class Arc, class F>\nvoid MakePrecedingInputSymbolsSameClass(bool start_is_epsilon,\n                                        MutableFst<Arc> *fst, const F &f);\n\n/// MakeFollowingInputSymbolsSame ensures that all arcs exiting any given fst\n/// state have the same input symbol.  It does this by detecting states that\n/// have differing input symbols on arcs that exit it, and inserting, for each\n/// of the following arcs with non-epsilon input symbol, a new dummy state that\n/// has an input-epsilon link from the fst state.  The output symbol and weight\n/// stay on the link to the dummy state (in order to keep the FST\n/// output-deterministic and stochastic, if it already was). If end_is_epsilon,\n/// treat \"being a final-state\" like having an epsilon output link.\ntemplate <class Arc>\nvoid MakeFollowingInputSymbolsSame(bool end_is_epsilon, MutableFst<Arc> *fst);\n\n/// As MakeFollowingInputSymbolsSame, but takes a functor object that maps\n/// labels to classes.\ntemplate <class Arc, class F>\nvoid MakeFollowingInputSymbolsSameClass(bool end_is_epsilon,\n                                        MutableFst<Arc> *fst, const F &f);\n\n/// MakeLoopFst creates an FST that has a state that is both initial and\n/// final (weight == Weight::One()), and for each non-NULL pointer fsts[i],\n/// it has an arc out whose output-symbol is i and which goes to a\n/// sub-graph whose input language is equivalent to fsts[i], where the\n/// final-state becomes a transition to the loop-state.  Each fst in \"fsts\"\n/// should be an acceptor.  The fst MakeLoopFst returns is output-deterministic,\n/// but not output-epsilon free necessarily, and arcs are sorted on output\n/// label. Note: if some of the pointers in the input vector \"fsts\" have the\n/// same value, \"MakeLoopFst\" uses this to speed up the computation.\n\n/// Formally: suppose I is the set of indexes i such that fsts[i] != NULL.\n/// Let L[i] be the language that the acceptor fsts[i] accepts.\n/// Let the language K be the set of input-output pairs i:l such\n/// that i in I and l in L[i].  Then the FST returned by MakeLoopFst\n/// accepts the language K*, where * is the Kleene closure (CLOSURE_STAR)\n/// of K.\n\n/// We could have implemented this via a combination of \"project\",\n/// \"concat\", \"union\" and \"closure\".  But that FST would have been\n/// less well optimized and would have a lot of final-states.\n\ntemplate <class Arc>\nVectorFst<Arc> *MakeLoopFst(const std::vector<const ExpandedFst<Arc> *> &fsts);\n\n/// ApplyProbabilityScale is applicable to FSTs in the log or tropical semiring.\n/// It multiplies the arc and final weights by \"scale\" [this is not the Mul\n/// operation of the semiring, it's actual multiplication, which is equivalent\n/// to taking a power in the semiring].\ntemplate <class Arc>\nvoid ApplyProbabilityScale(float scale, MutableFst<Arc> *fst);\n\n/// EqualAlign is similar to RandGen, but it generates a sequence with exactly\n/// \"length\" input symbols.  It returns true on success, false on failure\n/// (failure is partly random but should never happen in practice for normal\n/// speech models.) It generates a random path through the input FST, finds out\n/// which subset of the states it visits along the way have self-loops with\n/// inupt symbols on them, and outputs a path with exactly enough self-loops to\n/// have the requested number of input symbols. Note that EqualAlign does not\n/// use the probabilities on the FST.  It just uses equal probabilities in the\n/// first stage of selection (since the output will anyway not be a truly random\n/// sample from the FST). The input fst \"ifst\" must be connected or this may\n/// enter an infinite loop.\ntemplate <class Arc>\nbool EqualAlign(const Fst<Arc> &ifst, typename Arc::StateId length,\n                int rand_seed, MutableFst<Arc> *ofst, int num_retries = 10);\n\n// RemoveUselessArcs removes arcs such that there is no input symbol\n// sequence for which the best path through the FST would contain\n// those arcs [for these purposes, epsilon is not treated as a real symbol].\n// This is mainly geared towards decoding-graph FSTs which may contain\n// transitions that have less likely words on them that would never be\n// taken.  We do not claim that this algorithm removes all such arcs;\n// it just does the best job it can.\n// Only works for tropical (not log) semiring as it uses\n// NaturalLess.\ntemplate <class Arc>\nvoid RemoveUselessArcs(MutableFst<Arc> *fst);\n\n// PhiCompose is a version of composition where\n// the right hand FST (fst2) is treated as a backoff\n// LM, with the phi symbol (e.g. #0) treated as a\n// \"failure transition\", only taken when we don't\n// have a match for the requested symbol.\ntemplate <class Arc>\nvoid PhiCompose(const Fst<Arc> &fst1, const Fst<Arc> &fst2,\n                typename Arc::Label phi_label, MutableFst<Arc> *fst);\n\n// PropagateFinal propagates final-probs through\n// \"phi\" transitions (note that here, phi_label may\n// be epsilon if you want).  If you have a backoff LM\n// with special symbols (\"phi\") on the backoff arcs\n// instead of epsilon, you may use PhiCompose to compose\n// with it, but this won't do the right thing w.r.t.\n// final probabilities.  You should first call PropagateFinal\n// on the FST with phi's i it (fst2 in PhiCompose above),\n// to fix this.  If a state does not have a final-prob,\n// but has a phi transition, it makes the state's final-prob\n// (phi-prob * final-prob-of-dest-state), and does this\n// recursively i.e. follows phi transitions on the dest state\n// first.  It behaves as if there were a super-final state\n// with a special symbol leading to it, from each currently\n// final state.  Note that this may not behave as desired\n// if there are epsilons in your FST; it might be better\n// to remove those before calling this function.\n\ntemplate <class Arc>\nvoid PropagateFinal(typename Arc::Label phi_label, MutableFst<Arc> *fst);\n\n// PhiCompose is a version of composition where\n// the right hand FST (fst2) has speciall \"rho transitions\"\n// which are taken whenever no normal transition matches; these\n// transitions will be rewritten with whatever symbol was on\n// the first FST.\ntemplate <class Arc>\nvoid RhoCompose(const Fst<Arc> &fst1, const Fst<Arc> &fst2,\n                typename Arc::Label rho_label, MutableFst<Arc> *fst);\n\n/** This function returns true if, in the semiring of the FST, the sum (within\n    the semiring) of all the arcs out of each state in the FST is one, to within\n    delta.  After MakeStochasticFst, this should be true (for a connected FST).\n\n    @param fst [in] the FST that we are testing.\n    @param delta [in] the tolerance to within which we test equality to 1.\n    @param min_sum [out] if non, NULL, contents will be set to the minimum sum\n   of weights.\n    @param max_sum [out] if non, NULL, contents will be set to the maximum sum\n   of weights.\n    @return Returns true if the FST is stochastic, and false otherwise.\n*/\n\ntemplate <class Arc>\nbool IsStochasticFst(const Fst<Arc> &fst,\n                     float delta = kDelta,  // kDelta = 1.0/1024.0 by default.\n                     typename Arc::Weight *min_sum = NULL,\n                     typename Arc::Weight *max_sum = NULL);\n\n// IsStochasticFstInLog makes sure it's stochastic after casting to log.\ninline bool IsStochasticFstInLog(\n    const Fst<StdArc> &fst,\n    float delta = kDelta,  // kDelta = 1.0/1024.0 by default.\n    StdArc::Weight *min_sum = NULL, StdArc::Weight *max_sum = NULL);\n\n}  // end namespace fst\n\n#include \"fstext/fstext-utils-inl.h\"\n\n#endif  // KALDI_FSTEXT_FSTEXT_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/kaldi-fst-io-inl.h",
    "content": "// fstext/kaldi-fst-io-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//           2012-2015  Johns Hopkins University (Author: Daniel Povey)\n//                2013  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_KALDI_FST_IO_INL_H_\n#define KALDI_FSTEXT_KALDI_FST_IO_INL_H_\n\n#include <string>\n#include <vector>\n\n#include \"util/text-utils.h\"\n\nnamespace fst {\n\ntemplate <class Arc>\nvoid WriteFstKaldi(std::ostream &os, bool binary, const VectorFst<Arc> &t) {\n  bool ok;\n  if (binary) {\n    // Binary-mode writing.\n    ok = t.Write(os, FstWriteOptions());\n  } else {\n    // Text-mode output.  Note: we expect that t.InputSymbols() and\n    // t.OutputSymbols() would always return NULL.  The corresponding input\n    // routine would not work if the FST actually had symbols attached.  Write a\n    // newline to start the FST; in a table, the first line of the FST will\n    // appear on its own line.\n    os << '\\n';\n    bool acceptor = false, write_one = false;\n    FstPrinter<Arc> printer(t, t.InputSymbols(), t.OutputSymbols(), NULL,\n                            acceptor, write_one, \"\\t\");\n    printer.Print(&os, \"<unknown>\");\n    if (os.fail()) KALDI_ERR << \"Stream failure detected writing FST to stream\";\n    // Write another newline as a terminating character.  The read routine will\n    // detect this [this is a Kaldi mechanism, not something in the original\n    // OpenFst code].\n    os << '\\n';\n    ok = os.good();\n  }\n  if (!ok) {\n    KALDI_ERR << \"Error writing FST to stream\";\n  }\n}\n\n// Utility function used in ReadFstKaldi\ntemplate <class W>\ninline bool StrToWeight(const std::string &s, bool allow_zero, W *w) {\n  std::istringstream strm(s);\n  strm >> *w;\n  if (strm.fail() || (!allow_zero && *w == W::Zero())) {\n    return false;\n  }\n  return true;\n}\n\ntemplate <class Arc>\nvoid ReadFstKaldi(std::istream &is, bool binary, VectorFst<Arc> *fst) {\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId StateId;\n  if (binary) {\n    // We don't have access to the filename here, so write [unknown].\n    VectorFst<Arc> *ans =\n        VectorFst<Arc>::Read(is, fst::FstReadOptions(std::string(\"[unknown]\")));\n    if (ans == NULL) {\n      KALDI_ERR << \"Error reading FST from stream.\";\n    }\n    *fst = *ans;  // shallow copy.\n    delete ans;\n  } else {\n    // Consume the \\r on Windows, the \\n that the text-form FST format starts\n    // with, and any extra spaces that might have got in there somehow.\n    while (std::isspace(is.peek()) && is.peek() != '\\n') is.get();\n    if (is.peek() == '\\n') {\n      is.get();  // consume the newline.\n    } else {     // saw spaces but no newline.. this is not expected.\n      KALDI_ERR << \"Reading FST: unexpected sequence of spaces \"\n                << \" at file position \" << is.tellg();\n    }\n    using kaldi::ConvertStringToInteger;\n    using kaldi::SplitStringToIntegers;\n    using std::string;\n    using std::vector;\n    fst->DeleteStates();\n    string line;\n    size_t nline = 0;\n    string separator = FLAGS_fst_field_separator + \"\\r\\n\";\n    while (std::getline(is, line)) {\n      nline++;\n      vector<string> col;\n      // on Windows we'll write in text and read in binary mode.\n      kaldi::SplitStringToVector(line, separator.c_str(), true, &col);\n      if (col.size() == 0) break;  // Empty line is a signal to stop, in our\n      // archive format.\n      if (col.size() > 5) {\n        KALDI_ERR << \"Bad line in FST: \" << line;\n      }\n      StateId s;\n      if (!ConvertStringToInteger(col[0], &s)) {\n        KALDI_ERR << \"Bad line in FST: \" << line;\n      }\n      while (s >= fst->NumStates()) fst->AddState();\n      if (nline == 1) fst->SetStart(s);\n\n      bool ok = true;\n      Arc arc;\n      Weight w;\n      StateId d = s;\n      switch (col.size()) {\n        case 1:\n          fst->SetFinal(s, Weight::One());\n          break;\n        case 2:\n          if (!StrToWeight(col[1], true, &w))\n            ok = false;\n          else\n            fst->SetFinal(s, w);\n          break;\n        case 3:  // 3 columns not ok for Lattice format; it's not an acceptor.\n          ok = false;\n          break;\n        case 4:\n          ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n               ConvertStringToInteger(col[2], &arc.ilabel) &&\n               ConvertStringToInteger(col[3], &arc.olabel);\n          if (ok) {\n            d = arc.nextstate;\n            arc.weight = Weight::One();\n            fst->AddArc(s, arc);\n          }\n          break;\n        case 5:\n          ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n               ConvertStringToInteger(col[2], &arc.ilabel) &&\n               ConvertStringToInteger(col[3], &arc.olabel) &&\n               StrToWeight(col[4], false, &arc.weight);\n          if (ok) {\n            d = arc.nextstate;\n            fst->AddArc(s, arc);\n          }\n          break;\n        default:\n          ok = false;\n      }\n      while (d >= fst->NumStates()) fst->AddState();\n      if (!ok) KALDI_ERR << \"Bad line in FST: \" << line;\n    }\n  }\n}\n\ntemplate <class Arc>  // static\nbool VectorFstTplHolder<Arc>::Write(std::ostream &os, bool binary, const T &t) {\n  try {\n    WriteFstKaldi(os, binary, t);\n    return true;\n  } catch (...) {\n    return false;\n  }\n}\n\ntemplate <class Arc>  // static\nbool VectorFstTplHolder<Arc>::Read(std::istream &is) {\n  Clear();\n  int c = is.peek();\n  if (c == -1) {\n    KALDI_WARN << \"End of stream detected reading Fst\";\n    return false;\n  } else if (isspace(c)) {  // The text form of the FST begins\n    // with space (normally, '\\n'), so this means it's text (the binary form\n    // cannot begin with space because it starts with the FST Type() which is\n    // not space).\n    try {\n      t_ = new VectorFst<Arc>();\n      ReadFstKaldi(is, false, t_);\n    } catch (...) {\n      Clear();\n      return false;\n    }\n  } else {  // reading a binary FST.\n    try {\n      t_ = new VectorFst<Arc>();\n      ReadFstKaldi(is, true, t_);\n    } catch (...) {\n      Clear();\n      return false;\n    }\n  }\n  return true;\n}\n\n}  // namespace fst.\n\n#endif  // KALDI_FSTEXT_KALDI_FST_IO_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/kaldi-fst-io.cc",
    "content": "// fstext/kaldi-fst-io.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n//           2012-2015  Johns Hopkins University (Author: Daniel Povey)\n//                2013  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"fstext/kaldi-fst-io.h\"\n\n#include <string>\n\n#include \"base/kaldi-error.h\"\n#include \"base/kaldi-math.h\"\n#include \"util/kaldi-io.h\"\n\nnamespace fst {\n\nVectorFst<StdArc> *ReadFstKaldi(std::string rxfilename) {\n  if (rxfilename == \"\") rxfilename = \"-\";  // interpret \"\" as stdin,\n  // for compatibility with OpenFst conventions.\n  kaldi::Input ki(rxfilename);\n  fst::FstHeader hdr;\n  if (!hdr.Read(ki.Stream(), rxfilename))\n    KALDI_ERR << \"Reading FST: error reading FST header from \"\n              << kaldi::PrintableRxfilename(rxfilename);\n  FstReadOptions ropts(\"<unspecified>\", &hdr);\n  VectorFst<StdArc> *fst = VectorFst<StdArc>::Read(ki.Stream(), ropts);\n  if (!fst)\n    KALDI_ERR << \"Could not read fst from \"\n              << kaldi::PrintableRxfilename(rxfilename);\n  return fst;\n}\n\n// Register const fst to load it automatically. Other types like\n// olabel_lookahead or ngram or compact_fst should be registered\n// through OpenFst registration API.\nstatic fst::FstRegisterer<VectorFst<StdArc>> VectorFst_StdArc_registerer;\nstatic fst::FstRegisterer<ConstFst<StdArc>> ConstFst_StdArc_registerer;\n\nFst<StdArc> *ReadFstKaldiGeneric(std::string rxfilename, bool throw_on_err) {\n  if (rxfilename == \"\") rxfilename = \"-\";  // interpret \"\" as stdin,\n  // for compatibility with OpenFst conventions.\n  kaldi::Input ki(rxfilename);\n  fst::FstHeader hdr;\n  // Read FstHeader which contains the type of FST\n  if (!hdr.Read(ki.Stream(), rxfilename)) {\n    if (throw_on_err) {\n      KALDI_ERR << \"Reading FST: error reading FST header from \"\n                << kaldi::PrintableRxfilename(rxfilename);\n    } else {\n      KALDI_WARN << \"We fail to read FST header from \"\n                 << kaldi::PrintableRxfilename(rxfilename)\n                 << \". A NULL pointer is returned.\";\n      return NULL;\n    }\n  }\n  // Check the type of Arc\n  if (hdr.ArcType() != fst::StdArc::Type()) {\n    if (throw_on_err) {\n      KALDI_ERR << \"FST with arc type \" << hdr.ArcType()\n                << \" is not supported.\";\n    } else {\n      KALDI_WARN << \"Fst with arc type\" << hdr.ArcType()\n                 << \" is not supported. A NULL pointer is returned.\";\n      return NULL;\n    }\n  }\n  // Read the FST\n  FstReadOptions ropts(\"<unspecified>\", &hdr);\n  Fst<StdArc> *fst = Fst<StdArc>::Read(ki.Stream(), ropts);\n  if (!fst) {\n    if (throw_on_err) {\n      KALDI_ERR << \"Could not read fst from \"\n                << kaldi::PrintableRxfilename(rxfilename);\n    } else {\n      KALDI_WARN << \"Could not read fst from \"\n                 << kaldi::PrintableRxfilename(rxfilename)\n                 << \". A NULL pointer is returned.\";\n      return NULL;\n    }\n  }\n  return fst;\n}\n\nVectorFst<StdArc> *CastOrConvertToVectorFst(Fst<StdArc> *fst) {\n  // This version currently supports ConstFst<StdArc> or VectorFst<StdArc>\n  std::string real_type = fst->Type();\n  KALDI_ASSERT(real_type == \"vector\" || real_type == \"const\");\n  if (real_type == \"vector\") {\n    return dynamic_cast<VectorFst<StdArc> *>(fst);\n  } else {\n    // As the 'fst' can't cast to VectorFst, we create a new\n    // VectorFst<StdArc> initialized by 'fst', and delete 'fst'.\n    VectorFst<StdArc> *new_fst = new VectorFst<StdArc>(*fst);\n    delete fst;\n    return new_fst;\n  }\n}\n\nvoid ReadFstKaldi(std::string rxfilename, fst::StdVectorFst *ofst) {\n  fst::StdVectorFst *fst = ReadFstKaldi(rxfilename);\n  *ofst = *fst;\n  delete fst;\n}\n\nvoid WriteFstKaldi(const VectorFst<StdArc> &fst, std::string wxfilename) {\n  if (wxfilename == \"\") wxfilename = \"-\";  // interpret \"\" as stdout,\n  // for compatibility with OpenFst conventions.\n  bool write_binary = true, write_header = false;\n  kaldi::Output ko(wxfilename, write_binary, write_header);\n  FstWriteOptions wopts(kaldi::PrintableWxfilename(wxfilename));\n  fst.Write(ko.Stream(), wopts);\n}\n\nfst::VectorFst<fst::StdArc> *ReadAndPrepareLmFst(std::string rxfilename) {\n  // ReadFstKaldi() will die with exception on failure.\n  fst::VectorFst<fst::StdArc> *ans = fst::ReadFstKaldi(rxfilename);\n  if (ans->Properties(fst::kAcceptor, true) == 0) {\n    // If it's not already an acceptor, project on the output, i.e. copy olabels\n    // to ilabels.  Generally the G.fst's on disk will have the disambiguation\n    // symbol #0 on the input symbols of the backoff arc, and projection will\n    // replace them with epsilons which is what is on the output symbols of\n    // those arcs.\n    fst::Project(ans, fst::PROJECT_OUTPUT);\n  }\n  if (ans->Properties(fst::kILabelSorted, true) == 0) {\n    // Make sure LM is sorted on ilabel.\n    fst::ILabelCompare<fst::StdArc> ilabel_comp;\n    fst::ArcSort(ans, ilabel_comp);\n  }\n  return ans;\n}\n\n}  // end namespace fst\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/kaldi-fst-io.h",
    "content": "// fstext/kaldi-fst-io.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//           2012-2015  Johns Hopkins University (Author: Daniel Povey)\n//                2013  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_KALDI_FST_IO_H_\n#define KALDI_FSTEXT_KALDI_FST_IO_H_\n\n#include <string>\n#include <utility>\n\n#include \"fst/fst-decl.h\"\n#include \"fst/fstlib.h\"\n#include \"fst/script/print-impl.h\"\n\n#include \"base/kaldi-common.h\"\n\n// Some functions for writing Fsts.\n// I/O for FSTs is a bit of a mess, and not very well integrated with Kaldi's\n// generic I/O mechanisms, because we want files containing just FSTs to\n// be readable by OpenFST's native binaries, which is not compatible\n// with the normal \\0B header that identifies Kaldi files as containing\n// binary data.\n// So use the functions here with your eyes open, and with caution!\nnamespace fst {\n\n// Read a binary FST using Kaldi I/O mechanisms (pipes, etc.)\n// On error returns NULL. Only supports VectorFst and exists\n// mainly for backward code compabibility.\nVectorFst<StdArc> *ReadFstKaldi(std::string rxfilename);\n\n// Read a binary FST using Kaldi I/O mechanisms (pipes, etc.)\n// If it can't read the FST, if throw_on_err == true it throws using KALDI_ERR;\n// otherwise it prints a warning and returns. Note:this\n// doesn't support the text-mode option that we generally like to support.\n// This version currently supports ConstFst<StdArc> or VectorFst<StdArc>\n// (const-fst can give better performance for decoding). Other\n// types could be also loaded if registered inside OpenFst.\nFst<StdArc> *ReadFstKaldiGeneric(std::string rxfilename,\n                                 bool throw_on_err = true);\n\n// This function attempts to dynamic_cast the pointer 'fst' (which will likely\n// have been returned by ReadFstGeneric()), to the more derived\n// type VectorFst<StdArc>. If this succeeds, it returns the same pointer;\n// if it fails, it converts the FST type (by creating a new VectorFst<stdArc>\n// initialized by 'fst'), prints a warning, and deletes 'fst'.\nVectorFst<StdArc> *CastOrConvertToVectorFst(Fst<StdArc> *fst);\n\n// Version of ReadFstKaldi() that writes to a pointer.  Assumes\n// the FST is binary with no binary marker.  Crashes on error.\nvoid ReadFstKaldi(std::string rxfilename, VectorFst<StdArc> *ofst);\n\n// Write an FST using Kaldi I/O mechanisms (pipes, etc.)\n// On error, throws using KALDI_ERR.  For use only in code in fstbin/,\n// as it doesn't support the text-mode option.\nvoid WriteFstKaldi(const VectorFst<StdArc> &fst, std::string wxfilename);\n\n// This is a more general Kaldi-type-IO mechanism of writing FSTs to\n// streams, supporting binary or text-mode writing.  (note: we just\n// write the integers, symbol tables are not supported).\n// On error, throws using KALDI_ERR.\ntemplate <class Arc>\nvoid WriteFstKaldi(std::ostream &os, bool binary, const VectorFst<Arc> &fst);\n\n// A generic Kaldi-type-IO mechanism of reading FSTs from streams,\n// supporting binary or text-mode reading/writing.\ntemplate <class Arc>\nvoid ReadFstKaldi(std::istream &is, bool binary, VectorFst<Arc> *fst);\n\n// Read an FST file for LM (G.fst) and make it an acceptor,\n// and make sure it is sorted on labels\nfst::VectorFst<fst::StdArc> *ReadAndPrepareLmFst(std::string rxfilename);\n\n// This is a Holder class with T = VectorFst<Arc>, that meets the requirements\n// of a Holder class as described in ../util/kaldi-holder.h. This enables us to\n// read/write collections of FSTs indexed by strings, using the Table concept (\n// see ../util/kaldi-table.h).\n// Originally it was only templated on T = VectorFst<StdArc>, but as the keyword\n// spotting stuff introduced more types of FSTs, we made it also templated on\n// the arc.\ntemplate <class Arc>\nclass VectorFstTplHolder {\n public:\n  typedef VectorFst<Arc> T;\n\n  VectorFstTplHolder() : t_(NULL) {}\n\n  static bool Write(std::ostream &os, bool binary, const T &t);\n\n  void Copy(const T &t) {  // copies it into the holder.\n    Clear();\n    t_ = new T(t);\n  }\n\n  // Reads into the holder.\n  bool Read(std::istream &is);\n\n  // It's potentially a binary format, so must read in binary mode (linefeed\n  // translation will corrupt the file.  We don't know till we open the file if\n  // it's really binary, so we need to read in binary mode to be on the safe\n  // side.  Extra linefeeds won't matter, the text-mode reading code ignores\n  // them.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {\n    // code error if !t_.\n    if (!t_) KALDI_ERR << \"VectorFstTplHolder::Value() called wrongly.\";\n    return *t_;\n  }\n\n  void Clear() {\n    if (t_) {\n      delete t_;\n      t_ = NULL;\n    }\n  }\n\n  void Swap(VectorFstTplHolder<Arc> *other) { std::swap(t_, other->t_); }\n\n  bool ExtractRange(const VectorFstTplHolder<Arc> &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~VectorFstTplHolder() { Clear(); }\n  // No destructor.  Assignment and\n  // copy constructor take their default implementations.\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(VectorFstTplHolder);\n  T *t_;\n};\n\n// Now make the original VectorFstHolder as the typedef of\n// VectorFstHolder<StdArc>.\ntypedef VectorFstTplHolder<StdArc> VectorFstHolder;\n\n}  // end namespace fst\n\n#include \"fstext/kaldi-fst-io-inl.h\"\n\n#endif  // KALDI_FSTEXT_KALDI_FST_IO_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/lattice-utils-inl.h",
    "content": "// fstext/lattice-utils-inl.h\n\n// Copyright 2009-2012  Microsoft Corporation  Johns Hopkins University (Author:\n// Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_LATTICE_UTILS_INL_H_\n#define KALDI_FSTEXT_LATTICE_UTILS_INL_H_\n// Do not include this file directly.  It is included by lattice-utils.h\n\n#include <utility>\n#include <vector>\n\nnamespace fst {\n\n/* Convert from FST with arc-type Weight, to one with arc-type\n   CompactLatticeWeight.  Uses FactorFst to identify chains\n   of states which can be turned into a single output arc. */\n\ntemplate <class Weight, class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<Weight> > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > *ofst,\n    bool invert) {\n  typedef ArcTpl<Weight> Arc;\n  typedef typename Arc::StateId StateId;\n  typedef CompactLatticeWeightTpl<Weight, Int> CompactWeight;\n  typedef ArcTpl<CompactWeight> CompactArc;\n\n  VectorFst<ArcTpl<Weight> > ffst;\n  std::vector<std::vector<Int> > labels;\n  if (invert) {  // normal case: want the ilabels as sequences on the arcs of\n    Factor(ifst, &ffst, &labels);  // the output... Factor makes seqs of\n                                   // ilabels.\n  } else {\n    VectorFst<ArcTpl<Weight> > invfst(ifst);\n    Invert(&invfst);\n    Factor(invfst, &ffst, &labels);\n  }\n\n  TopSort(&ffst);  // Put the states in ffst in topological order, which is\n  // easier on the eye when reading the text-form lattices and corresponds to\n  // what we get when we generate the lattices in the decoder.\n\n  ofst->DeleteStates();\n\n  // The states will be numbered exactly the same as the original FST.\n  // Add the states to the new FST.\n  StateId num_states = ffst.NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    StateId news = ofst->AddState();\n    assert(news == s);\n  }\n  ofst->SetStart(ffst.Start());\n  for (StateId s = 0; s < num_states; s++) {\n    Weight final_weight = ffst.Final(s);\n    if (final_weight != Weight::Zero()) {\n      CompactWeight final_compact_weight(final_weight, std::vector<Int>());\n      ofst->SetFinal(s, final_compact_weight);\n    }\n    for (ArcIterator<ExpandedFst<Arc> > iter(ffst, s); !iter.Done();\n         iter.Next()) {\n      const Arc &arc = iter.Value();\n      KALDI_PARANOID_ASSERT(arc.weight != Weight::Zero());\n      // note: zero-weight arcs not allowed anyway so weight should not be zero,\n      // but no harm in checking.\n      CompactArc compact_arc(arc.olabel, arc.olabel,\n                             CompactWeight(arc.weight, labels[arc.ilabel]),\n                             arc.nextstate);\n      ofst->AddArc(s, compact_arc);\n    }\n  }\n}\n\ntemplate <class Weight, class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > &ifst,\n    MutableFst<ArcTpl<Weight> > *ofst, bool invert) {\n  typedef ArcTpl<Weight> Arc;\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Label Label;\n  typedef CompactLatticeWeightTpl<Weight, Int> CompactWeight;\n  typedef ArcTpl<CompactWeight> CompactArc;\n  ofst->DeleteStates();\n  // make the states in the new FST have the same numbers as\n  // the original ones, and add chains of states as necessary\n  // to encode the string-valued weights.\n  StateId num_states = ifst.NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    StateId news = ofst->AddState();\n    assert(news == s);\n  }\n  ofst->SetStart(ifst.Start());\n  for (StateId s = 0; s < num_states; s++) {\n    CompactWeight final_weight = ifst.Final(s);\n    if (final_weight != CompactWeight::Zero()) {\n      StateId cur_state = s;\n      size_t string_length = final_weight.String().size();\n      for (size_t n = 0; n < string_length; n++) {\n        StateId next_state = ofst->AddState();\n        Label ilabel = 0;\n        Arc arc(ilabel, final_weight.String()[n],\n                (n == 0 ? final_weight.Weight() : Weight::One()), next_state);\n        if (invert) std::swap(arc.ilabel, arc.olabel);\n        ofst->AddArc(cur_state, arc);\n        cur_state = next_state;\n      }\n      ofst->SetFinal(cur_state,\n                     string_length > 0 ? Weight::One() : final_weight.Weight());\n    }\n    for (ArcIterator<ExpandedFst<CompactArc> > iter(ifst, s); !iter.Done();\n         iter.Next()) {\n      const CompactArc &arc = iter.Value();\n      size_t string_length = arc.weight.String().size();\n      StateId cur_state = s;\n      // for all but the last element in the string--\n      // add a temporary state.\n      for (size_t n = 0; n + 1 < string_length; n++) {\n        StateId next_state = ofst->AddState();\n        Label ilabel = (n == 0 ? arc.ilabel : 0),\n              olabel = static_cast<Label>(arc.weight.String()[n]);\n        Weight weight = (n == 0 ? arc.weight.Weight() : Weight::One());\n        Arc new_arc(ilabel, olabel, weight, next_state);\n        if (invert) std::swap(new_arc.ilabel, new_arc.olabel);\n        ofst->AddArc(cur_state, new_arc);\n        cur_state = next_state;\n      }\n      Label ilabel = (string_length <= 1 ? arc.ilabel : 0),\n            olabel = (string_length > 0 ? arc.weight.String()[string_length - 1]\n                                        : 0);\n      Weight weight =\n          (string_length <= 1 ? arc.weight.Weight() : Weight::One());\n      Arc new_arc(ilabel, olabel, weight, arc.nextstate);\n      if (invert) std::swap(new_arc.ilabel, new_arc.olabel);\n      ofst->AddArc(cur_state, new_arc);\n    }\n  }\n}\n\n// This function converts lattices between float and double;\n// it works for both CompactLatticeWeight and LatticeWeight.\ntemplate <class WeightIn, class WeightOut>\nvoid ConvertLattice(const ExpandedFst<ArcTpl<WeightIn> > &ifst,\n                    MutableFst<ArcTpl<WeightOut> > *ofst) {\n  typedef ArcTpl<WeightIn> ArcIn;\n  typedef ArcTpl<WeightOut> ArcOut;\n  typedef typename ArcIn::StateId StateId;\n  ofst->DeleteStates();\n  // The states will be numbered exactly the same as the original FST.\n  // Add the states to the new FST.\n  StateId num_states = ifst.NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    StateId news = ofst->AddState();\n    assert(news == s);\n  }\n  ofst->SetStart(ifst.Start());\n  for (StateId s = 0; s < num_states; s++) {\n    WeightIn final_iweight = ifst.Final(s);\n    if (final_iweight != WeightIn::Zero()) {\n      WeightOut final_oweight;\n      ConvertLatticeWeight(final_iweight, &final_oweight);\n      ofst->SetFinal(s, final_oweight);\n    }\n    for (ArcIterator<ExpandedFst<ArcIn> > iter(ifst, s); !iter.Done();\n         iter.Next()) {\n      ArcIn arc = iter.Value();\n      KALDI_PARANOID_ASSERT(arc.weight != WeightIn::Zero());\n      ArcOut oarc;\n      ConvertLatticeWeight(arc.weight, &oarc.weight);\n      oarc.ilabel = arc.ilabel;\n      oarc.olabel = arc.olabel;\n      oarc.nextstate = arc.nextstate;\n      ofst->AddArc(s, oarc);\n    }\n  }\n}\n\ntemplate <class Weight, class ScaleFloat>\nvoid ScaleLattice(const std::vector<std::vector<ScaleFloat> > &scale,\n                  MutableFst<ArcTpl<Weight> > *fst) {\n  assert(scale.size() == 2 && scale[0].size() == 2 && scale[1].size() == 2);\n  if (scale == DefaultLatticeScale())  // nothing to do.\n    return;\n  typedef ArcTpl<Weight> Arc;\n  typedef MutableFst<Arc> Fst;\n  typedef typename Arc::StateId StateId;\n  StateId num_states = fst->NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    for (MutableArcIterator<Fst> aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      Arc arc = aiter.Value();\n      arc.weight = Weight(ScaleTupleWeight(arc.weight, scale));\n      aiter.SetValue(arc);\n    }\n    Weight final_weight = fst->Final(s);\n    if (final_weight != Weight::Zero())\n      fst->SetFinal(s, Weight(ScaleTupleWeight(final_weight, scale)));\n  }\n}\n\ntemplate <class Weight, class Int>\nvoid RemoveAlignmentsFromCompactLattice(\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > *fst) {\n  typedef CompactLatticeWeightTpl<Weight, Int> W;\n  typedef ArcTpl<W> Arc;\n  typedef MutableFst<Arc> Fst;\n  typedef typename Arc::StateId StateId;\n  StateId num_states = fst->NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    for (MutableArcIterator<Fst> aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      Arc arc = aiter.Value();\n      arc.weight = W(arc.weight.Weight(), std::vector<Int>());\n      aiter.SetValue(arc);\n    }\n    W final_weight = fst->Final(s);\n    if (final_weight != W::Zero())\n      fst->SetFinal(s, W(final_weight.Weight(), std::vector<Int>()));\n  }\n}\n\ntemplate <class Weight, class Int>\nbool CompactLatticeHasAlignment(\n    const ExpandedFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > &fst) {\n  typedef CompactLatticeWeightTpl<Weight, Int> W;\n  typedef ArcTpl<W> Arc;\n  typedef ExpandedFst<Arc> Fst;\n  typedef typename Arc::StateId StateId;\n  StateId num_states = fst.NumStates();\n  for (StateId s = 0; s < num_states; s++) {\n    for (ArcIterator<Fst> aiter(fst, s); !aiter.Done(); aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (!arc.weight.String().empty()) return true;\n    }\n    W final_weight = fst.Final(s);\n    if (!final_weight.String().empty()) return true;\n  }\n  return false;\n}\n\ntemplate <class Real>\nvoid ConvertFstToLattice(const ExpandedFst<ArcTpl<TropicalWeight> > &ifst,\n                         MutableFst<ArcTpl<LatticeWeightTpl<Real> > > *ofst) {\n  int32 num_states_cache = 50000;\n  fst::CacheOptions cache_opts(true, num_states_cache);\n  fst::MapFstOptions mapfst_opts(cache_opts);\n  StdToLatticeMapper<Real> mapper;\n  MapFst<StdArc, ArcTpl<LatticeWeightTpl<Real> >, StdToLatticeMapper<Real> >\n      map_fst(ifst, mapper, mapfst_opts);\n  *ofst = map_fst;\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_LATTICE_UTILS_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/lattice-utils.h",
    "content": "// fstext/lattice-utils.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_LATTICE_UTILS_H_\n#define KALDI_FSTEXT_LATTICE_UTILS_H_\n\n#include <vector>\n\n#include \"fst/fstlib.h\"\n#include \"fstext/lattice-weight.h\"\n\nnamespace fst {\n\n// The template ConvertLattice does conversions to and from\n// LatticeWeight FSTs and CompactLatticeWeight FSTs, and\n// between float and double, and to convert from LatticeWeight\n// to TropicalWeight.  It's used in the I/O code for lattices,\n// and for converting lattices to standard FSTs (e.g. for creating\n// decoding graphs from lattices).\n\n/**\n   Convert lattice from a normal FST to a CompactLattice FST.\n   This is a bit like converting to the Gallic semiring, except\n   the semiring behaves in a different way (designed to take\n   the best path).\n   Note: the ilabels end up as the symbols on the arcs of the\n   output acceptor, and the olabels go to the strings.  To make\n   it the other way around (useful for the speech-recognition\n   application), set invert=true [the default].\n*/\ntemplate <class Weight, class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<Weight> > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > *ofst,\n    bool invert = true);\n\n/**\n   Convert lattice CompactLattice  format to Lattice.  This is a bit\n   like converting from the Gallic semiring.  As for any CompactLattice, \"ifst\"\n   must be an acceptor (i.e., ilabels and olabels should be identical).  If\n   invert=false, the labels on \"ifst\" become the ilabels on \"ofst\" and the\n   strings in the weights of \"ifst\" becomes the olabels.  If invert=true\n   [default], this is reversed (useful for speech recognition lattices; our\n   standard non-compact format has the words on the output side to match HCLG).\n   */\ntemplate <class Weight, class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > &ifst,\n    MutableFst<ArcTpl<Weight> > *ofst, bool invert = true);\n\n/**\n  Convert between CompactLattices and Lattices of different floating point\n  types... this works between any pair of weight types for which\n  ConvertLatticeWeight is defined (c.f. lattice-weight.h), and also includes\n  conversion from LatticeWeight to TropicalWeight.\n */\ntemplate <class WeightIn, class WeightOut>\nvoid ConvertLattice(const ExpandedFst<ArcTpl<WeightIn> > &ifst,\n                    MutableFst<ArcTpl<WeightOut> > *ofst);\n\n// Now define some ConvertLattice functions that require two phases of\n// conversion (don't bother coding these separately as they will be used rarely.\n\n// Lattice with float to CompactLattice with double.\ntemplate <class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<LatticeWeightTpl<float> > > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<double>, Int> > >\n        *ofst) {\n  VectorFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<float>, Int> > >\n      fst;\n  ConvertLattice(ifst, &fst);\n  ConvertLattice(fst, ofst);\n}\n\n// Lattice with double to CompactLattice with float.\ntemplate <class Int>\nvoid ConvertLattice(\n    const ExpandedFst<ArcTpl<LatticeWeightTpl<double> > > &ifst,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<float>, Int> > >\n        *ofst) {\n  VectorFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<double>, Int> > >\n      fst;\n  ConvertLattice(ifst, &fst);\n  ConvertLattice(fst, ofst);\n}\n\n/// Converts CompactLattice with double to Lattice with float.\ntemplate <class Int>\nvoid ConvertLattice(\n    const ExpandedFst<\n        ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<double>, Int> > > &ifst,\n    MutableFst<ArcTpl<LatticeWeightTpl<float> > > *ofst) {\n  VectorFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<float>, Int> > >\n      fst;\n  ConvertLattice(ifst, &fst);\n  ConvertLattice(fst, ofst);\n}\n\n/// Converts CompactLattice with float to Lattice with double.\ntemplate <class Int>\nvoid ConvertLattice(\n    const ExpandedFst<\n        ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<float>, Int> > > &ifst,\n    MutableFst<ArcTpl<LatticeWeightTpl<double> > > *ofst) {\n  VectorFst<ArcTpl<CompactLatticeWeightTpl<LatticeWeightTpl<double>, Int> > >\n      fst;\n  ConvertLattice(ifst, &fst);\n  ConvertLattice(fst, ofst);\n}\n\n/// Converts TropicalWeight to LatticeWeight (puts all the weight on\n/// the first float in the lattice's pair).\ntemplate <class Real>\nvoid ConvertFstToLattice(const ExpandedFst<ArcTpl<TropicalWeight> > &ifst,\n                         MutableFst<ArcTpl<LatticeWeightTpl<Real> > > *ofst);\n\n/** Returns a default 2x2 matrix scaling factor for LatticeWeight */\ninline std::vector<std::vector<double> > DefaultLatticeScale() {\n  std::vector<std::vector<double> > ans(2);\n  ans[0].resize(2, 0.0);\n  ans[1].resize(2, 0.0);\n  ans[0][0] = ans[1][1] = 1.0;\n  return ans;\n}\n\ninline std::vector<std::vector<double> > AcousticLatticeScale(double acwt) {\n  std::vector<std::vector<double> > ans(2);\n  ans[0].resize(2, 0.0);\n  ans[1].resize(2, 0.0);\n  ans[0][0] = 1.0;\n  ans[1][1] = acwt;\n  return ans;\n}\n\ninline std::vector<std::vector<double> > GraphLatticeScale(double lmwt) {\n  std::vector<std::vector<double> > ans(2);\n  ans[0].resize(2, 0.0);\n  ans[1].resize(2, 0.0);\n  ans[0][0] = lmwt;\n  ans[1][1] = 1.0;\n  return ans;\n}\n\ninline std::vector<std::vector<double> > LatticeScale(double lmwt,\n                                                      double acwt) {\n  std::vector<std::vector<double> > ans(2);\n  ans[0].resize(2, 0.0);\n  ans[1].resize(2, 0.0);\n  ans[0][0] = lmwt;\n  ans[1][1] = acwt;\n  return ans;\n}\n\n/** Scales the pairs of weights in LatticeWeight or CompactLatticeWeight by\n    viewing the pair (a, b) as a 2-vector and pre-multiplying by the 2x2 matrix\n    in \"scale\".  E.g. typically scale would equal\n     [ 1   0;\n       0  acwt ]\n    if we want to scale the acoustics by \"acwt\".\n */\ntemplate <class Weight, class ScaleFloat>\nvoid ScaleLattice(const std::vector<std::vector<ScaleFloat> > &scale,\n                  MutableFst<ArcTpl<Weight> > *fst);\n\n/// Removes state-level alignments (the strings that are\n/// part of the weights).\ntemplate <class Weight, class Int>\nvoid RemoveAlignmentsFromCompactLattice(\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > *fst);\n\n/// Returns true if lattice has alignments, i.e. it has\n/// any nonempty strings inside its weights.\ntemplate <class Weight, class Int>\nbool CompactLatticeHasAlignment(\n    const ExpandedFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > &fst);\n\n/// Class StdToLatticeMapper maps a normal arc (StdArc)\n/// to a LatticeArc by putting the StdArc weight as the first\n/// element of the LatticeWeight.  Useful when doing LM\n/// rescoring.\ntemplate <class Real>\nclass StdToLatticeMapper {\n  typedef LatticeWeightTpl<Real> LatticeWeight;\n  typedef ArcTpl<LatticeWeight> LatticeArc;\n\n public:\n  LatticeArc operator()(const StdArc &arc) {\n    // Note: we have to check whether the arc's weight is zero below,\n    // and if so return (infinity, infinity) and not (infinity, zero),\n    // because (infinity, zero) is not a valid LatticeWeight, which should\n    // either be both finite, or both infinite (i.e. Zero()).\n    return LatticeArc(\n        arc.ilabel, arc.olabel,\n        LatticeWeight(arc.weight.Value(), arc.weight == StdArc::Weight::Zero()\n                                              ? arc.weight.Value()\n                                              : 0.0),\n        arc.nextstate);\n  }\n  MapFinalAction FinalAction() { return MAP_NO_SUPERFINAL; }\n\n  MapSymbolsAction InputSymbolsAction() { return MAP_COPY_SYMBOLS; }\n\n  MapSymbolsAction OutputSymbolsAction() { return MAP_COPY_SYMBOLS; }\n\n  // I believe all properties are preserved.\n  uint64 Properties(uint64 props) { return props; }\n};\n\n/// Class LatticeToStdMapper maps a LatticeArc to a normal arc (StdArc)\n/// by adding the elements of the LatticeArc weight.\n\ntemplate <class Real>\nclass LatticeToStdMapper {\n  typedef LatticeWeightTpl<Real> LatticeWeight;\n  typedef ArcTpl<LatticeWeight> LatticeArc;\n\n public:\n  StdArc operator()(const LatticeArc &arc) {\n    return StdArc(arc.ilabel, arc.olabel,\n                  StdArc::Weight(arc.weight.Value1() + arc.weight.Value2()),\n                  arc.nextstate);\n  }\n  MapFinalAction FinalAction() { return MAP_NO_SUPERFINAL; }\n\n  MapSymbolsAction InputSymbolsAction() { return MAP_COPY_SYMBOLS; }\n\n  MapSymbolsAction OutputSymbolsAction() { return MAP_COPY_SYMBOLS; }\n\n  // I believe all properties are preserved.\n  uint64 Properties(uint64 props) { return props; }\n};\n\ntemplate <class Weight, class Int>\nvoid PruneCompactLattice(\n    Weight beam,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, Int> > > *fst);\n\n}  // end namespace fst\n\n#include \"fstext/lattice-utils-inl.h\"\n\n#endif  // KALDI_FSTEXT_LATTICE_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/lattice-weight.h",
    "content": "// fstext/lattice-weight.h\n// Copyright 2009-2012  Microsoft Corporation\n//                      Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_LATTICE_WEIGHT_H_\n#define KALDI_FSTEXT_LATTICE_WEIGHT_H_\n\n#include <algorithm>\n#include <limits>\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-common.h\"\n#include \"fst/fstlib.h\"\n\nnamespace fst {\n\n// Declare weight type for lattice... will import to namespace kaldi.  has two\n// members, value1_ and value2_, of type BaseFloat (normally equals float).  It\n// is basically the same as the tropical semiring on value1_+value2_, except it\n// keeps track of a and b separately.  More precisely, it is equivalent to the\n// lexicographic semiring on (value1_+value2_), (value1_-value2_)\n\ntemplate <class FloatType>\nclass LatticeWeightTpl;\n\ntemplate <class FloatType>\ninline std::ostream &operator<<(std::ostream &strm,\n                                const LatticeWeightTpl<FloatType> &w);\n\ntemplate <class FloatType>\ninline std::istream &operator>>(std::istream &strm,\n                                LatticeWeightTpl<FloatType> &w);\n\ntemplate <class FloatType>\nclass LatticeWeightTpl {\n public:\n  typedef FloatType T;  // normally float.\n  typedef LatticeWeightTpl ReverseWeight;\n\n  inline T Value1() const { return value1_; }\n\n  inline T Value2() const { return value2_; }\n\n  inline void SetValue1(T f) { value1_ = f; }\n\n  inline void SetValue2(T f) { value2_ = f; }\n\n  LatticeWeightTpl() : value1_{}, value2_{} {}\n\n  LatticeWeightTpl(T a, T b) : value1_(a), value2_(b) {}\n\n  LatticeWeightTpl(const LatticeWeightTpl &other)\n      : value1_(other.value1_), value2_(other.value2_) {}\n\n  LatticeWeightTpl &operator=(const LatticeWeightTpl &w) {\n    value1_ = w.value1_;\n    value2_ = w.value2_;\n    return *this;\n  }\n\n  LatticeWeightTpl<FloatType> Reverse() const { return *this; }\n\n  static const LatticeWeightTpl Zero() {\n    return LatticeWeightTpl(std::numeric_limits<T>::infinity(),\n                            std::numeric_limits<T>::infinity());\n  }\n\n  static const LatticeWeightTpl One() { return LatticeWeightTpl(0.0, 0.0); }\n\n  static const std::string &Type() {\n    static const std::string type = (sizeof(T) == 4 ? \"lattice4\" : \"lattice8\");\n    return type;\n  }\n\n  static const LatticeWeightTpl NoWeight() {\n    return LatticeWeightTpl(std::numeric_limits<FloatType>::quiet_NaN(),\n                            std::numeric_limits<FloatType>::quiet_NaN());\n  }\n\n  bool Member() const {\n    // value1_ == value1_ tests for NaN.\n    // also test for no -inf, and either both or neither\n    // must be +inf, and\n    if (value1_ != value1_ || value2_ != value2_) return false;  // NaN\n    if (value1_ == -std::numeric_limits<T>::infinity() ||\n        value2_ == -std::numeric_limits<T>::infinity())\n      return false;  // -infty not allowed\n    if (value1_ == std::numeric_limits<T>::infinity() ||\n        value2_ == std::numeric_limits<T>::infinity()) {\n      if (value1_ != std::numeric_limits<T>::infinity() ||\n          value2_ != std::numeric_limits<T>::infinity())\n        return false;  // both must be +infty;\n      // this is necessary so that the semiring has only one zero.\n    }\n    return true;\n  }\n\n  LatticeWeightTpl Quantize(float delta = kDelta) const {\n    if (value1_ + value2_ == -std::numeric_limits<T>::infinity()) {\n      return LatticeWeightTpl(-std::numeric_limits<T>::infinity(),\n                              -std::numeric_limits<T>::infinity());\n    } else if (value1_ + value2_ == std::numeric_limits<T>::infinity()) {\n      return LatticeWeightTpl(std::numeric_limits<T>::infinity(),\n                              std::numeric_limits<T>::infinity());\n    } else if (value1_ + value2_ != value1_ + value2_) {  // NaN\n      return LatticeWeightTpl(value1_ + value2_, value1_ + value2_);\n    } else {\n      return LatticeWeightTpl(floor(value1_ / delta + 0.5F) * delta,\n                              floor(value2_ / delta + 0.5F) * delta);\n    }\n  }\n  static constexpr uint64 Properties() {\n    return kLeftSemiring | kRightSemiring | kCommutative | kPath | kIdempotent;\n  }\n\n  // This is used in OpenFst for binary I/O.  This is OpenFst-style,\n  // not Kaldi-style, I/O.\n  std::istream &Read(std::istream &strm) {\n    // Always read/write as float, even if T is double,\n    // so we can use OpenFst-style read/write and still maintain\n    // compatibility when compiling with different FloatTypes\n    ReadType(strm, &value1_);\n    ReadType(strm, &value2_);\n    return strm;\n  }\n\n  // This is used in OpenFst for binary I/O.  This is OpenFst-style,\n  // not Kaldi-style, I/O.\n  std::ostream &Write(std::ostream &strm) const {\n    WriteType(strm, value1_);\n    WriteType(strm, value2_);\n    return strm;\n  }\n\n  size_t Hash() const {\n    size_t ans;\n    union {\n      T f;\n      size_t s;\n    } u;\n    u.s = 0;\n    u.f = value1_;\n    ans = u.s;\n    u.f = value2_;\n    ans += u.s;\n    return ans;\n  }\n\n protected:\n  inline static void WriteFloatType(std::ostream &strm, const T &f) {\n    if (f == std::numeric_limits<T>::infinity())\n      strm << \"Infinity\";\n    else if (f == -std::numeric_limits<T>::infinity())\n      strm << \"-Infinity\";\n    else if (f != f)\n      strm << \"BadNumber\";\n    else\n      strm << f;\n  }\n\n  // Internal helper function, used in ReadNoParen.\n  inline static void ReadFloatType(std::istream &strm, T &f) {  // NOLINT\n    std::string s;\n    strm >> s;\n    if (s == \"Infinity\") {\n      f = std::numeric_limits<T>::infinity();\n    } else if (s == \"-Infinity\") {\n      f = -std::numeric_limits<T>::infinity();\n    } else if (s == \"BadNumber\") {\n      f = std::numeric_limits<T>::quiet_NaN();\n    } else {\n      char *p;\n      f = strtod(s.c_str(), &p);\n      if (p < s.c_str() + s.size()) strm.clear(std::ios::badbit);\n    }\n  }\n\n  // Reads LatticeWeight when there are no parentheses around pair terms...\n  // currently the only form supported.\n  inline std::istream &ReadNoParen(std::istream &strm, char separator) {\n    int c;\n    do {\n      c = strm.get();\n    } while (isspace(c));\n\n    std::string s1;\n    while (c != separator) {\n      if (c == EOF) {\n        strm.clear(std::ios::badbit);\n        return strm;\n      }\n      s1 += c;\n      c = strm.get();\n    }\n    std::istringstream strm1(s1);\n    ReadFloatType(strm1, value1_);  // ReadFloatType is class member function\n    // read second element\n    ReadFloatType(strm, value2_);\n    return strm;\n  }\n\n  friend std::istream &operator>>\n      <FloatType>(std::istream &, LatticeWeightTpl<FloatType> &);\n  friend std::ostream &operator<<<FloatType>(\n      std::ostream &, const LatticeWeightTpl<FloatType> &);\n\n private:\n  T value1_;\n  T value2_;\n};\n\n/* ScaleTupleWeight is a function defined for LatticeWeightTpl and\n   CompactLatticeWeightTpl that mutliplies the pair (value1_, value2_) by a 2x2\n   matrix.  Used, for example, in applying acoustic scaling.\n */\ntemplate <class FloatType, class ScaleFloatType>\ninline LatticeWeightTpl<FloatType> ScaleTupleWeight(\n    const LatticeWeightTpl<FloatType> &w,\n    const std::vector<std::vector<ScaleFloatType> > &scale) {\n  // Without the next special case we'd get NaNs from infinity * 0\n  if (w.Value1() == std::numeric_limits<FloatType>::infinity())\n    return LatticeWeightTpl<FloatType>::Zero();\n  return LatticeWeightTpl<FloatType>(\n      scale[0][0] * w.Value1() + scale[0][1] * w.Value2(),\n      scale[1][0] * w.Value1() + scale[1][1] * w.Value2());\n}\n\n/* For testing purposes and in case it's ever useful, we define a similar\n   function to apply to LexicographicWeight and the like, templated on\n   TropicalWeight<float> etc.; we use PairWeight which is the base class of\n   LexicographicWeight.\n*/\ntemplate <class FloatType, class ScaleFloatType>\ninline PairWeight<TropicalWeightTpl<FloatType>, TropicalWeightTpl<FloatType> >\nScaleTupleWeight(const PairWeight<TropicalWeightTpl<FloatType>,\n                                  TropicalWeightTpl<FloatType> > &w,\n                 const std::vector<std::vector<ScaleFloatType> > &scale) {\n  typedef TropicalWeightTpl<FloatType> BaseType;\n  typedef PairWeight<BaseType, BaseType> PairType;\n  const BaseType zero = BaseType::Zero();\n  // Without the next special case we'd get NaNs from infinity * 0\n  if (w.Value1() == zero || w.Value2() == zero) return PairType(zero, zero);\n  FloatType f1 = w.Value1().Value(), f2 = w.Value2().Value();\n  return PairType(BaseType(scale[0][0] * f1 + scale[0][1] * f2),\n                  BaseType(scale[1][0] * f1 + scale[1][1] * f2));\n}\n\ntemplate <class FloatType>\ninline bool operator==(const LatticeWeightTpl<FloatType> &wa,\n                       const LatticeWeightTpl<FloatType> &wb) {\n  // Volatile qualifier thwarts over-aggressive compiler optimizations\n  // that lead to problems esp. with NaturalLess().\n  volatile FloatType va1 = wa.Value1(), va2 = wa.Value2(), vb1 = wb.Value1(),\n                     vb2 = wb.Value2();\n  return (va1 == vb1 && va2 == vb2);\n}\n\ntemplate <class FloatType>\ninline bool operator!=(const LatticeWeightTpl<FloatType> &wa,\n                       const LatticeWeightTpl<FloatType> &wb) {\n  // Volatile qualifier thwarts over-aggressive compiler optimizations\n  // that lead to problems esp. with NaturalLess().\n  volatile FloatType va1 = wa.Value1(), va2 = wa.Value2(), vb1 = wb.Value1(),\n                     vb2 = wb.Value2();\n  return (va1 != vb1 || va2 != vb2);\n}\n\n// We define a Compare function LatticeWeightTpl even though it's\n// not required by the semiring standard-- it's just more efficient\n// to do it this way rather than using the NaturalLess template.\n\n/// Compare returns -1 if w1 < w2, +1 if w1 > w2, and 0 if w1 == w2.\n\ntemplate <class FloatType>\ninline int Compare(const LatticeWeightTpl<FloatType> &w1,\n                   const LatticeWeightTpl<FloatType> &w2) {\n  FloatType f1 = w1.Value1() + w1.Value2(), f2 = w2.Value1() + w2.Value2();\n  if (f1 < f2) {  // having smaller cost means you're larger\n    return 1;\n  } else if (f1 > f2) {  // in the semiring [higher probability]\n    return -1;\n  } else if (w1.Value1() < w2.Value1()) {\n  // mathematically we should be comparing (w1.value1_-w1.value2_ <\n  // w2.value1_-w2.value2_) in the next line, but add w1.value1_+w1.value2_ =\n  // w2.value1_+w2.value2_ to both sides and divide by two, and we get the\n  // simpler equivalent form w1.value1_ < w2.value1_.\n    return 1;\n  } else if (w1.Value1() > w2.Value1()) {\n    return -1;\n  } else {\n    return 0;\n  }\n}\n\ntemplate <class FloatType>\ninline LatticeWeightTpl<FloatType> Plus(const LatticeWeightTpl<FloatType> &w1,\n                                        const LatticeWeightTpl<FloatType> &w2) {\n  return (Compare(w1, w2) >= 0 ? w1 : w2);\n}\n\n// For efficiency, override the NaturalLess template class.\ntemplate <class FloatType>\nclass NaturalLess<LatticeWeightTpl<FloatType> > {\n public:\n  typedef LatticeWeightTpl<FloatType> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\ntemplate <>\nclass NaturalLess<LatticeWeightTpl<float> > {\n public:\n  typedef LatticeWeightTpl<float> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\ntemplate <>\nclass NaturalLess<LatticeWeightTpl<double> > {\n public:\n  typedef LatticeWeightTpl<double> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\n\ntemplate <class FloatType>\ninline LatticeWeightTpl<FloatType> Times(\n    const LatticeWeightTpl<FloatType> &w1,\n    const LatticeWeightTpl<FloatType> &w2) {\n  return LatticeWeightTpl<FloatType>(w1.Value1() + w2.Value1(),\n                                     w1.Value2() + w2.Value2());\n}\n\n// divide w1 by w2 (on left/right/any doesn't matter as\n// commutative).\ntemplate <class FloatType>\ninline LatticeWeightTpl<FloatType> Divide(const LatticeWeightTpl<FloatType> &w1,\n                                          const LatticeWeightTpl<FloatType> &w2,\n                                          DivideType typ = DIVIDE_ANY) {\n  typedef FloatType T;\n  T a = w1.Value1() - w2.Value1(), b = w1.Value2() - w2.Value2();\n  if (a != a || b != b || a == -std::numeric_limits<T>::infinity() ||\n      b == -std::numeric_limits<T>::infinity()) {\n    KALDI_WARN << \"LatticeWeightTpl::Divide, NaN or invalid number produced. \"\n               << \"[dividing by zero?]  Returning zero\";\n    return LatticeWeightTpl<T>::Zero();\n  }\n  if (a == std::numeric_limits<T>::infinity() ||\n      b == std::numeric_limits<T>::infinity())\n    return LatticeWeightTpl<T>::Zero();  // not a valid number if only one is\n                                         // infinite.\n  return LatticeWeightTpl<T>(a, b);\n}\n\ntemplate <class FloatType>\ninline bool ApproxEqual(const LatticeWeightTpl<FloatType> &w1,\n                        const LatticeWeightTpl<FloatType> &w2,\n                        float delta = kDelta) {\n  if (w1.Value1() == w2.Value1() && w1.Value2() == w2.Value2())\n    return true;  // handles Zero().\n  return (fabs((w1.Value1() + w1.Value2()) - (w2.Value1() + w2.Value2())) <=\n          delta);\n}\n\ntemplate <class FloatType>\ninline std::ostream &operator<<(std::ostream &strm,\n                                const LatticeWeightTpl<FloatType> &w) {\n  LatticeWeightTpl<FloatType>::WriteFloatType(strm, w.Value1());\n  CHECK(FLAGS_fst_weight_separator.size() == 1);  // NOLINT\n  strm << FLAGS_fst_weight_separator[0];  // comma by default;\n  // may or may not be settable from Kaldi programs.\n  LatticeWeightTpl<FloatType>::WriteFloatType(strm, w.Value2());\n  return strm;\n}\n\ntemplate <class FloatType>\ninline std::istream &operator>>(std::istream &strm,\n                                LatticeWeightTpl<FloatType> &w1) {\n  CHECK(FLAGS_fst_weight_separator.size() == 1);  // NOLINT\n  // separator defaults to ','\n  return w1.ReadNoParen(strm, FLAGS_fst_weight_separator[0]);\n}\n\n// CompactLattice will be an acceptor (accepting the words/output-symbols),\n// with the weights and input-symbol-seqs on the arcs.\n// There must be a total order on W.  We assume for the sake of efficiency\n// that there is a function\n// Compare(W w1, W w2) that returns -1 if w1 < w2, +1 if w1 > w2, and\n// zero if w1 == w2, and Plus for type W returns (Compare(w1,w2) >= 0 ? w1 :\n// w2).\n\ntemplate <class WeightType, class IntType>\nclass CompactLatticeWeightTpl {\n public:\n  typedef WeightType W;\n\n  typedef CompactLatticeWeightTpl<WeightType, IntType> ReverseWeight;\n\n  // Plus is like LexicographicWeight on the pair (weight_, string_), but where\n  // we use standard lexicographic order on string_ [this is not the same as\n  // NaturalLess on the StringWeight equivalent, which does not define a\n  // total order].\n  // Times, Divide obvious... (support both left & right division..)\n  // CommonDivisor would need to be coded separately.\n\n  CompactLatticeWeightTpl() {}\n\n  CompactLatticeWeightTpl(const WeightType &w, const std::vector<IntType> &s)\n      : weight_(w), string_(s) {}\n\n  CompactLatticeWeightTpl &operator=(\n      const CompactLatticeWeightTpl<WeightType, IntType> &w) {\n    weight_ = w.weight_;\n    string_ = w.string_;\n    return *this;\n  }\n\n  const W &Weight() const { return weight_; }\n\n  const std::vector<IntType> &String() const { return string_; }\n\n  void SetWeight(const W &w) { weight_ = w; }\n\n  void SetString(const std::vector<IntType> &s) { string_ = s; }\n\n  static const CompactLatticeWeightTpl<WeightType, IntType> Zero() {\n    return CompactLatticeWeightTpl<WeightType, IntType>(WeightType::Zero(),\n                                                        std::vector<IntType>());\n  }\n\n  static const CompactLatticeWeightTpl<WeightType, IntType> One() {\n    return CompactLatticeWeightTpl<WeightType, IntType>(WeightType::One(),\n                                                        std::vector<IntType>());\n  }\n\n  inline static std::string GetIntSizeString() {\n    char buf[2];\n    buf[0] = '0' + sizeof(IntType);\n    buf[1] = '\\0';\n    return buf;\n  }\n  static const std::string &Type() {\n    static const std::string type =\n        \"compact\" + WeightType::Type() + GetIntSizeString();\n    return type;\n  }\n\n  static const CompactLatticeWeightTpl<WeightType, IntType> NoWeight() {\n    return CompactLatticeWeightTpl<WeightType, IntType>(WeightType::NoWeight(),\n                                                        std::vector<IntType>());\n  }\n\n  CompactLatticeWeightTpl<WeightType, IntType> Reverse() const {\n    size_t s = string_.size();\n    std::vector<IntType> v(s);\n    for (size_t i = 0; i < s; i++) v[i] = string_[s - i - 1];\n    return CompactLatticeWeightTpl<WeightType, IntType>(weight_, v);\n  }\n\n  bool Member() const {\n    // a semiring has only one zero, this is the important property\n    // we're trying to maintain here.  So force string_ to be empty if\n    // w_ == zero.\n    if (!weight_.Member()) return false;\n    if (weight_ == WeightType::Zero())\n      return string_.empty();\n    else\n      return true;\n  }\n\n  CompactLatticeWeightTpl Quantize(float delta = kDelta) const {\n    return CompactLatticeWeightTpl(weight_.Quantize(delta), string_);\n  }\n\n  static constexpr uint64 Properties() {\n    return kLeftSemiring | kRightSemiring | kPath | kIdempotent;\n  }\n\n  // This is used in OpenFst for binary I/O.  This is OpenFst-style,\n  // not Kaldi-style, I/O.\n  std::istream &Read(std::istream &strm) {\n    weight_.Read(strm);\n    if (strm.fail()) {\n      return strm;\n    }\n    int32 sz;\n    ReadType(strm, &sz);\n    if (strm.fail()) {\n      return strm;\n    }\n    if (sz < 0) {\n      KALDI_WARN << \"Negative string size!  Read failure\";\n      strm.clear(std::ios::badbit);\n      return strm;\n    }\n    string_.resize(sz);\n    for (int32 i = 0; i < sz; i++) {\n      ReadType(strm, &(string_[i]));\n    }\n    return strm;\n  }\n\n  // This is used in OpenFst for binary I/O.  This is OpenFst-style,\n  // not Kaldi-style, I/O.\n  std::ostream &Write(std::ostream &strm) const {\n    weight_.Write(strm);\n    if (strm.fail()) {\n      return strm;\n    }\n    int32 sz = static_cast<int32>(string_.size());\n    WriteType(strm, sz);\n    for (int32 i = 0; i < sz; i++) WriteType(strm, string_[i]);\n    return strm;\n  }\n  size_t Hash() const {\n    size_t ans = weight_.Hash();\n    // any weird numbers here are largish primes\n    size_t sz = string_.size(), mult = 6967;\n    for (size_t i = 0; i < sz; i++) {\n      ans += string_[i] * mult;\n      mult *= 7499;\n    }\n    return ans;\n  }\n\n private:\n  W weight_;\n  std::vector<IntType> string_;\n};\n\ntemplate <class WeightType, class IntType>\ninline bool operator==(const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n                       const CompactLatticeWeightTpl<WeightType, IntType> &w2) {\n  return (w1.Weight() == w2.Weight() && w1.String() == w2.String());\n}\n\ntemplate <class WeightType, class IntType>\ninline bool operator!=(const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n                       const CompactLatticeWeightTpl<WeightType, IntType> &w2) {\n  return (w1.Weight() != w2.Weight() || w1.String() != w2.String());\n}\n\ntemplate <class WeightType, class IntType>\ninline bool ApproxEqual(const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n                        const CompactLatticeWeightTpl<WeightType, IntType> &w2,\n                        float delta = kDelta) {\n  return (ApproxEqual(w1.Weight(), w2.Weight(), delta) &&\n          w1.String() == w2.String());\n}\n\n// Compare is not part of the standard for weight types, but used internally for\n// efficiency.  The comparison here first compares the weight; if this is the\n// same, it compares the string.  The comparison on strings is: first compare\n// the length, if this is the same, use lexicographical order.  We can't just\n// use the lexicographical order because this would destroy the distributive\n// property of multiplication over addition, taking into account that addition\n// uses Compare.  The string element of \"Compare\" isn't super-important in\n// practical terms; it's only needed to ensure that Plus always give consistent\n// answers and is symmetric.  It's essentially for tie-breaking, but we need to\n// make sure all the semiring axioms are satisfied otherwise OpenFst might\n// break.\n\ntemplate <class WeightType, class IntType>\ninline int Compare(const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n                   const CompactLatticeWeightTpl<WeightType, IntType> &w2) {\n  int c1 = Compare(w1.Weight(), w2.Weight());\n  if (c1 != 0) return c1;\n  int l1 = w1.String().size(), l2 = w2.String().size();\n  // Use opposite order on the string lengths, so that if the costs are the\n  // same, the shorter string wins.\n  if (l1 > l2)\n    return -1;\n  else if (l1 < l2)\n    return 1;\n  for (int i = 0; i < l1; i++) {\n    if (w1.String()[i] < w2.String()[i])\n      return -1;\n    else if (w1.String()[i] > w2.String()[i])\n      return 1;\n  }\n  return 0;\n}\n\n// For efficiency, override the NaturalLess template class.\ntemplate <class FloatType, class IntType>\nclass NaturalLess<\n    CompactLatticeWeightTpl<LatticeWeightTpl<FloatType>, IntType> > {\n public:\n  typedef CompactLatticeWeightTpl<LatticeWeightTpl<FloatType>, IntType> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\ntemplate <>\nclass NaturalLess<CompactLatticeWeightTpl<LatticeWeightTpl<float>, int32> > {\n public:\n  typedef CompactLatticeWeightTpl<LatticeWeightTpl<float>, int32> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\ntemplate <>\nclass NaturalLess<CompactLatticeWeightTpl<LatticeWeightTpl<double>, int32> > {\n public:\n  typedef CompactLatticeWeightTpl<LatticeWeightTpl<double>, int32> Weight;\n\n  NaturalLess() {}\n\n  bool operator()(const Weight &w1, const Weight &w2) const {\n    // NaturalLess is a negative order (opposite to normal ordering).\n    // This operator () corresponds to \"<\" in the negative order, which\n    // corresponds to the \">\" in the normal order.\n    return (Compare(w1, w2) == 1);\n  }\n};\n\n// Make sure Compare is defined for TropicalWeight, so everything works\n// if we substitute LatticeWeight for TropicalWeight.\ninline int Compare(const TropicalWeight &w1, const TropicalWeight &w2) {\n  float f1 = w1.Value(), f2 = w2.Value();\n  if (f1 == f2)\n    return 0;\n  else if (f1 > f2)\n    return -1;\n  else\n    return 1;\n}\n\ntemplate <class WeightType, class IntType>\ninline CompactLatticeWeightTpl<WeightType, IntType> Plus(\n    const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n    const CompactLatticeWeightTpl<WeightType, IntType> &w2) {\n  return (Compare(w1, w2) >= 0 ? w1 : w2);\n}\n\ntemplate <class WeightType, class IntType>\ninline CompactLatticeWeightTpl<WeightType, IntType> Times(\n    const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n    const CompactLatticeWeightTpl<WeightType, IntType> &w2) {\n  WeightType w = Times(w1.Weight(), w2.Weight());\n  if (w == WeightType::Zero()) {\n    return CompactLatticeWeightTpl<WeightType, IntType>::Zero();\n    // special case to ensure zero is unique\n  } else {\n    std::vector<IntType> v;\n    v.resize(w1.String().size() + w2.String().size());\n    typename std::vector<IntType>::iterator iter = v.begin();\n    iter = std::copy(w1.String().begin(), w1.String().end(),\n                     iter);  // returns end of first range.\n    std::copy(w2.String().begin(), w2.String().end(), iter);\n    return CompactLatticeWeightTpl<WeightType, IntType>(w, v);\n  }\n}\n\ntemplate <class WeightType, class IntType>\ninline CompactLatticeWeightTpl<WeightType, IntType> Divide(\n    const CompactLatticeWeightTpl<WeightType, IntType> &w1,\n    const CompactLatticeWeightTpl<WeightType, IntType> &w2,\n    DivideType div = DIVIDE_ANY) {\n  if (w1.Weight() == WeightType::Zero()) {\n    if (w2.Weight() != WeightType::Zero()) {\n      return CompactLatticeWeightTpl<WeightType, IntType>::Zero();\n    } else {\n      KALDI_ERR << \"Division by zero [0/0]\";\n    }\n  } else if (w2.Weight() == WeightType::Zero()) {\n    KALDI_ERR << \"Error: division by zero\";\n  }\n  WeightType w = Divide(w1.Weight(), w2.Weight());\n\n  const std::vector<IntType> v1 = w1.String(), v2 = w2.String();\n  if (v2.size() > v1.size()) {\n    KALDI_ERR << \"Cannot divide, length mismatch\";\n  }\n  typename std::vector<IntType>::const_iterator v1b = v1.begin(),\n                                                v1e = v1.end(),\n                                                v2b = v2.begin(),\n                                                v2e = v2.end();\n  if (div == DIVIDE_LEFT) {\n    if (!std::equal(v2b, v2e,\n                    v1b)) {  // v2 must be identical to first part of v1.\n      KALDI_ERR << \"Cannot divide, data mismatch\";\n    }\n    return CompactLatticeWeightTpl<WeightType, IntType>(\n        w, std::vector<IntType>(v1b + (v2e - v2b),\n                                v1e));  // return last part of v1.\n  } else if (div == DIVIDE_RIGHT) {\n    if (!std::equal(\n            v2b, v2e,\n            v1e - (v2e - v2b))) {  // v2 must be identical to last part of v1.\n      KALDI_ERR << \"Cannot divide, data mismatch\";\n    }\n    return CompactLatticeWeightTpl<WeightType, IntType>(\n        w, std::vector<IntType>(\n               v1b, v1e - (v2e - v2b)));  // return first part of v1.\n\n  } else {\n    KALDI_ERR << \"Cannot divide CompactLatticeWeightTpl with DIVIDE_ANY\";\n  }\n  return CompactLatticeWeightTpl<WeightType,\n                                 IntType>::Zero();  // keep compiler happy.\n}\n\ntemplate <class WeightType, class IntType>\ninline std::ostream &operator<<(\n    std::ostream &strm, const CompactLatticeWeightTpl<WeightType, IntType> &w) {\n  strm << w.Weight();\n  CHECK(FLAGS_fst_weight_separator.size() == 1);  // NOLINT\n  strm << FLAGS_fst_weight_separator[0];  // comma by default.\n  for (size_t i = 0; i < w.String().size(); i++) {\n    strm << w.String()[i];\n    if (i + 1 < w.String().size())\n      strm << kStringSeparator;  // '_'; defined in string-weight.h in OpenFst\n                                 // code.\n  }\n  return strm;\n}\n\ntemplate <class WeightType, class IntType>\ninline std::istream &operator>>(\n    std::istream &strm, CompactLatticeWeightTpl<WeightType, IntType> &w) {\n  std::string s;\n  strm >> s;\n  if (strm.fail()) {\n    return strm;\n  }\n  CHECK(FLAGS_fst_weight_separator.size() == 1);  // NOLINT\n  size_t pos = s.find_last_of(FLAGS_fst_weight_separator);  // normally \",\"\n  if (pos == std::string::npos) {\n    strm.clear(std::ios::badbit);\n    return strm;\n  }\n  // get parts of str before and after the separator (default: ',');\n  std::string s1(s, 0, pos), s2(s, pos + 1);\n  std::istringstream strm1(s1);\n  WeightType weight;\n  strm1 >> weight;\n  w.SetWeight(weight);\n  if (strm1.fail() || !strm1.eof()) {\n    strm.clear(std::ios::badbit);\n    return strm;\n  }\n  // read string part.\n  std::vector<IntType> string;\n  const char *c = s2.c_str();\n  while (*c != '\\0') {\n    if (*c == kStringSeparator)  // '_'\n      c++;\n    char *c2;\n    int64_t i = strtol(c, &c2, 10);\n    if (c2 == c || static_cast<int64_t>(static_cast<IntType>(i)) != i) {\n      strm.clear(std::ios::badbit);\n      return strm;\n    }\n    c = c2;\n    string.push_back(static_cast<IntType>(i));\n  }\n  w.SetString(string);\n  return strm;\n}\n\ntemplate <class BaseWeightType, class IntType>\nclass CompactLatticeWeightCommonDivisorTpl {\n public:\n  typedef CompactLatticeWeightTpl<BaseWeightType, IntType> Weight;\n\n  Weight operator()(const Weight &w1, const Weight &w2) const {\n    // First find longest common prefix of the strings.\n    typename std::vector<IntType>::const_iterator s1b = w1.String().begin(),\n                                                  s1e = w1.String().end(),\n                                                  s2b = w2.String().begin(),\n                                                  s2e = w2.String().end();\n    while (s1b < s1e && s2b < s2e && *s1b == *s2b) {\n      s1b++;\n      s2b++;\n    }\n    return Weight(Plus(w1.Weight(), w2.Weight()),\n                  std::vector<IntType>(w1.String().begin(), s1b));\n  }\n};\n\n/** Scales the pair (a, b) of floating-point weights inside a\n    CompactLatticeWeight by premultiplying it (viewed as a vector)\n    by a 2x2 matrix \"scale\".\n    Assumes there is a ScaleTupleWeight function that applies to \"Weight\";\n    this currently only works if Weight equals LatticeWeightTpl<FloatType>\n    for some FloatType.\n*/\ntemplate <class Weight, class IntType, class ScaleFloatType>\ninline CompactLatticeWeightTpl<Weight, IntType> ScaleTupleWeight(\n    const CompactLatticeWeightTpl<Weight, IntType> &w,\n    const std::vector<std::vector<ScaleFloatType> > &scale) {\n  return CompactLatticeWeightTpl<Weight, IntType>(\n      Weight(ScaleTupleWeight(w.Weight(), scale)), w.String());\n}\n\n/** Define some ConvertLatticeWeight functions that are used in various lattice\n    conversions... make them all templates, some with no arguments, since some\n    must be templates.*/\ntemplate <class Float1, class Float2>\ninline void ConvertLatticeWeight(const LatticeWeightTpl<Float1> &w_in,\n                                 LatticeWeightTpl<Float2> *w_out) {\n  w_out->SetValue1(w_in.Value1());\n  w_out->SetValue2(w_in.Value2());\n}\n\ntemplate <class Float1, class Float2, class Int>\ninline void ConvertLatticeWeight(\n    const CompactLatticeWeightTpl<LatticeWeightTpl<Float1>, Int> &w_in,\n    CompactLatticeWeightTpl<LatticeWeightTpl<Float2>, Int> *w_out) {\n  LatticeWeightTpl<Float2> weight2(w_in.Weight().Value1(),\n                                   w_in.Weight().Value2());\n  w_out->SetWeight(weight2);\n  w_out->SetString(w_in.String());\n}\n\n// to convert from Lattice to standard FST\ntemplate <class Float1, class Float2>\ninline void ConvertLatticeWeight(const LatticeWeightTpl<Float1> &w_in,\n                                 TropicalWeightTpl<Float2> *w_out) {\n  TropicalWeightTpl<Float2> w1(w_in.Value1());\n  TropicalWeightTpl<Float2> w2(w_in.Value2());\n  *w_out = Times(w1, w2);\n}\n\ntemplate <class Float>\ninline double ConvertToCost(const LatticeWeightTpl<Float> &w) {\n  return static_cast<double>(w.Value1()) + static_cast<double>(w.Value2());\n}\n\ntemplate <class Float, class Int>\ninline double ConvertToCost(\n    const CompactLatticeWeightTpl<LatticeWeightTpl<Float>, Int> &w) {\n  return static_cast<double>(w.Weight().Value1()) +\n         static_cast<double>(w.Weight().Value2());\n}\n\ntemplate <class Float>\ninline double ConvertToCost(const TropicalWeightTpl<Float> &w) {\n  return w.Value();\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_LATTICE_WEIGHT_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/pre-determinize-inl.h",
    "content": "// fstext/pre-determinize-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_PRE_DETERMINIZE_INL_H_\n#define KALDI_FSTEXT_PRE_DETERMINIZE_INL_H_\n\n#include <algorithm>\n#include <map>\n#include <set>\n#include <string>\n#include <utility>\n#include <vector>\n\n/* Do not include this file directly.  It is an implementation file included by\n * PreDeterminize.h */\n\n/*\n  Predeterminization\n\n    This is a function that makes an FST compactly determinizable by inserting\n  symbols on the input side as necessary for disambiguation.  Note that we do\n  not treat epsilon as a real symbol when measuring determinizability in this\n  sense.   The extra symbols are added to the vocabulary, on the input side;\n  these are of the form (prefix)1, (prefix)2, and so on without limit, where\n  (prefix) is some prefix the user provides, e.g. '#' (the function checks that\n  this will not lead to conflicts with symbols already in the FST).  The\n  function tells us how many such symbols it created.\n\n   Note that there is a paper \"Generalized optimization algorithm for speech\n  recognition transducers\" by Allauzen and Mohri, that deals with a similar\n  issue, but this is a very different algorithm that only aims to ensure\n  determinizability, but not *compact* determinizability.\n\n   Our algorithm is slightly heuristic, and probably not optimal, but does\n  ensure that the output is compactly determinizable, possibly at the expense of\n  inserting unnecessary symbols.  We considered more sophisticated algorithms,\n  but these were extremely complicated and would give the same output for the\n  kinds of inputs that we envisage.\n\n   Suppose the input FST is T.  We want to ensure that in det(T), if we consider\n  the states of det(T) as weighted subsets of states of T, each state of T only\n  appears once in any given subset.  This ensures that det(T) is no larger than\n  T in an appropriate sense.  The way we do this is as follows.  We identify all\n  states in T that have multiple input transitions (counting \"being an initial\n  state\" as an input transition). Let's call these \"problematic\" states.  For a\n  problematic state p we stipulate that it can never appear in any state of\n  det(T) unless that state equals (p, \\bar{1}) [i.e. p, unweighted].  In order\n  to ensure this, we insert input symbols on the transitions to these\n   problematic states (this may necessitate adding extra states).\n      We also stipulate that the path through det(T) should always be sufficient\n  to tell us the path through T (and we insert extra symbols sufficient to make\n  this so).  This is to simplify the algorithm, so that we don't have to\n  consider the output symbols or weights when predeterminizing.\n\n   The algorithm is as follows.\n\n    (A) Definitions\n\n      (i)  Define a *problematic state* as a state that either has multiple\n  input transitions, or is an initial state and has at least one input\n  transition.\n\n     (ii)  For an arc a, define:\n            i[a] = input symbol on a\n            o[a] = output symbol on a\n            n[a] = dest-state of a\n            p[a] = origin-state of a\n\n           For a state q, define\n            E[q] = set of transitions leaving q.\n           For a set of states Q, define\n            E[Q] = set of transitions leaving some q in Q\n\n    (iii)  For a state s, define Closure(s) as the union of state s, and all\n  states t that are reachable via sequences of arcs a such that i[a]=epsilon and\n  n[a] is not problematic.\n\n           For a set of states S, define Closure(S) as the union of the closures\n  of states s in S.\n\n    (B) Inputs and outputs.\n\n     (i) Inputs and preconditions.  Input is an FST, which should have a symbol\n  table compiled into it, and a prefix (e.g. #) for symbols to be added.  We\n  check that the input FST is trim, and that it does not have any symbols that\n  appear on its arcs, that are equal to the prefix followed by digits.\n\n    (ii) Outputs: The algorithm modifies the FST that is given to it, and\n  returns the number of the highest numbered \"extra symbol\" inserted.  The extra\n  symbols are numbered #1, #2 and so on without limit (as integers).  They are\n  inserted into the symbol table in a sequential way by calling AvailableKey()\n         for each in turn (this is stipulated in case we need to keep other\n  symbol tables in sync).\n\n     (C) Sub-algorithm: Closure(S).  This requires the array p(s), defined\n  below, which is true if s is problematic.  This also requires, for efficiency,\n  that the arcs be sorted on input label. Input: a set of states S.  [plus, the\n  fst and the array p]. Output: a set of states T. Algorithm: set T <-- S, Q <--\n  S. while Q is nonempty: pop a state s from Q. for each transition a from state\n  s with epsilon on the input label [we can find these efficiently using the\n  sorting on arcs]: If p(n[a]) is false and n[a] is not in T: Insert n[a] into\n  T. Add n[a] to Q. return T.\n\n\n     (D) Main algorithm.\n\n\n       (i) (a) Check preconditions (FST is trim)\n           (b) Make sure there is just one final state (insert epsilon\n  transitions as necessary). (c) Sort arcs on input label (so epsilon arcs are\n  at the start of arc lists).\n\n\n      (ii) Work out the set of problematic states by constructing a boolean\n  array indexed by states, i.e. p(s) which is true if the state is problematic.\n  We can do this by constructing an array t(s) to store the number of\n  transitions into each state [adding one for the initial state], and then\n  setting p(s) = true if t(s) > 1.\n\n           Also create a boolean array d(s), defined for states, and set d(s) =\n  false. This array is purely for sanity-checking that we are processing each\n  state exactly once.\n\n     (iii) Set up an array of integers m(a), indexed by arcs (how exactly we\n  store these is implementation-dependent, but this will probably be a hash from\n  (state, arc-index) to integers.  m(a) will store the extra symbol, if any, to\n  be added to that arc (or -1 if no such symbol; we can also simply have the arc\n  not present in the hash).  The initial value of m(a) is -1 (if array), or\n  undefined (if hash).\n\n      (iv) Initialize a set of sets-of-states S, and a queue of pairs Q, as\n  follows. The pairs in Q are a pair of (set-of-states, integer), where the\n  integer is the number of \"special symbols\" already used up for that state.\n\n            Note that we use a special indexing for the sets in both S and Q,\n  rather than using std::set.  We use a sorted vector of StateId's.  And in S,\n  we index them by the lowest-numbered state-id.  Because each state is supposed\n  to only ever be a member of one set, if there is an attempt to add another,\n  different set with the same lowest-numbered state-id, we detect an error.\n\n            Let I be the single initial state (OpenFST only supports one).\n            We set:\n              S = { Closure(I) }\n              Push (Closure(I), 0)  onto Q.\n            Then for each state s such that p(s) = true, and s is not an initial\n  state: S <-- S u { Closure(s) } Push (Closure(s), 0)  onto Q.\n\n       (v) While Q is nonempty:\n\n          (a) Pop pair (A, n) from Q (queue discipline is arbitrary).\n\n          (b) For each state s in A, check that d(s) is false, and set d(s) to\n  true. This is for sanity checking only.\n\n          (c)\n             Let S_\\eps be the set of epsilon-transitions from members of A to\n  problematic states (i.e. S_\\eps = \\{ a \\in E[A]: i[a]=\\epsilon, p(n[a]) = true\n  \\}).\n\n             Next, we will define, for each t \\neq \\epsilon, S_t as the set of\n               transitions from some state s in S with t as the input label,\n  i.e.: S_t = \\{ a \\in E[A]: i[a] = t \\} We further define T_t and U_t as the\n  subsets of S where the destination state is problematic and non-problematic\n  respectively, i.e: T_t = \\{ a \\in E[A]: i[a] = t, p(n[a]) = true \\} U_t = \\{ a\n  \\in E[A]: i[a] = t, p(n[a]) = false \\}\n\n             The easiest way to obtain these sets is probably to have a hash\n  indexed by t that maps to a list of pairs (state, arc-offset) that stores S_t.\n               From this we can work out the sizes of T_t and U_t on the fly.\n\n         (d)\n             for each transition a in S_\\eps:\n                m(a) <-- n # Will put symbol n on this transition.\n                n <-- n+1  # Note, same n as in pair (A, n)\n\n         (e)\n             next,\n             for each t\\neq epsilon s.t. S_t is nonempty,\n\n                if |S_t| > 1 #if-statement is because if |S_t|=|T_t|=1, no need\n  for prefix. k = 0 for each transition a in T_t: set m(a) to k. set k = k+1\n\n                if |U_t| > 0\n                   Let V_t be the set of destination-states of arcs in U_t.\n                   if Closure(V_t) is not in S:\n                     insert Closure(V_t) into S, and add the pair (Closure(V_t),\n  k) to Q.\n\n       (vi) Check that for each state in the FST, d(s) = true.\n\n      (vii) Let n = max_a m(a).  This is the highest-numbered extra symbol\n  (extra symbols start from zero, in this numbering which doesn't correspond to\n  the symbol-table numbering).  Here we add n+1 extra symbols to the symbol\n  table and store the mappings from 0, 1, ... n to the symbol-id.\n\n     (viii) Set up a hash h from (state, int) to (state-id) such that\n             t = h(s, k)\n            will be the state-id of a newly-created state that has a transition\n  to state s with input-label #k.\n\n      (ix) For each arc a such that m(a) != 0:\n             If i[a] = epsilon (the input label is epsilon):\n                Change i[a] to #m(a). [i.e. prefix then digit m(a)]\n             Otherwise:\n                If t = h(n[a], m(a)) is not defined [where n[a] is the\n  dest-state]: create a new state t with a transition to n[a], with input-label\n  #m(a) and no output-label or weight.  Set h(n[a], m(a)) = t. Change n[a] to\n  h(n[a], m(a)).\n\n\n*/\nnamespace fst {\n\nnamespace pre_determinize_helpers {\n\n// make it inline to avoid having to put it in a .cc file which most functions\n// here could not go in.\ninline bool HasBannedPrefixPlusDigits(SymbolTable *symTable, std::string prefix,\n                                      std::string *bad_sym) {\n  // returns true if the symbol table contains any string consisting of this\n  // (possibly empty) prefix followed by a nonempty sequence of digits (0 to 9).\n  // requires symTable to be non-NULL.\n  // if bad_sym != NULL, puts the first bad symbol it finds in *bad_sym.\n  assert(symTable != NULL);\n  const char *prefix_ptr = prefix.c_str();\n  size_t prefix_len =\n      strlen(prefix_ptr);  // allowed to be zero but not encouraged.\n  for (SymbolTableIterator siter(*symTable); !siter.Done(); siter.Next()) {\n    const std::string &sym = siter.Symbol();\n    if (!strncmp(prefix_ptr, sym.c_str(), prefix_len)) {  // has prefix.\n      if (isdigit(sym[prefix_len])) {  // we don't allow prefix followed by a\n                                       // digit, as a symbol.\n        // Has at least one digit.\n        size_t pos;\n        for (pos = prefix_len; sym[pos] != '\\0'; pos++)\n          if (!isdigit(sym[pos])) break;\n        if (sym[pos] == '\\0') {  // All remaining characters were digits.\n          if (bad_sym != NULL) *bad_sym = sym;\n          return true;\n        }\n      }  // else OK because prefix was followed by '\\0' or a non-digit.\n    }\n  }\n  return false;  // doesn't have banned symbol.\n}\n\ntemplate <class T>\nvoid CopySetToVector(const std::set<T> s, std::vector<T> *v) {\n  // adds members of s to v, in sorted order from lowest to highest\n  // (because the set was in sorted order).\n  assert(v != NULL);\n  v->resize(s.size());\n  typename std::set<T>::const_iterator siter = s.begin();\n  typename std::vector<T>::iterator viter = v->begin();\n  for (; siter != s.end(); ++siter, ++viter) {\n    assert(viter != v->end());\n    *viter = *siter;\n  }\n}\n\n// Warning.  This function calls 'new'.\ntemplate <class T>\nstd::vector<T> *InsertMember(const std::vector<T> m,\n                             std::vector<std::vector<T> *> *S) {\n  assert(m.size() > 0);\n  T idx = m[0];\n  assert(idx >= (T)0 && idx < (T)S->size());\n  if ((*S)[idx] != NULL) {\n    assert(*((*S)[idx]) == m);\n    // The vectors should be the same.  Otherwise this is a bug in the\n    // algorithm. It could either be a programming error or a deeper conceptual\n    // bug.\n    return NULL;  // nothing was inserted.\n  } else {\n    std::vector<T> *ret = (*S)[idx] = new std::vector<T>(m);  // New copy of m.\n    return ret;                                               // was inserted.\n  }\n}\n\n// See definition of Closure(S) in item A(iii) in the comment above. it's the\n// set of states that are reachable from S via sequences of arcs a such that\n// i[a]=epsilon and n[a] is not problematic.  We assume that the fst is sorted\n// on input label (so epsilon arcs first) The algorithm is described in section\n// (C) above.  We use the same variable for S and T.\ntemplate <class Arc>\nvoid Closure(MutableFst<Arc> *fst, std::set<typename Arc::StateId> *S,\n             const std::vector<bool> &pVec) {\n  typedef typename Arc::StateId StateId;\n  std::vector<StateId> Q;\n  CopySetToVector(*S, &Q);\n  while (Q.size() != 0) {\n    StateId s = Q.back();\n    Q.pop_back();\n    for (ArcIterator<MutableFst<Arc> > aiter(*fst, s); !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel != 0)\n        break;  // Break from the loop: due to sorting there will be no\n      // more transitions with epsilons as input labels.\n      if (!pVec[arc.nextstate]) {  // Next state is not problematic -> we can\n                                   // use this transition.\n        std::pair<typename std::set<StateId>::iterator, bool> p =\n            S->insert(arc.nextstate);\n        if (p.second) {  // True means: was inserted into S (wasn't already\n                         // there).\n          Q.push_back(arc.nextstate);\n        }\n      }\n    }\n  }\n}  // end function Closure.\n\n}  // end namespace pre_determinize_helpers.\n\ntemplate <class Arc, class Int>\nvoid PreDeterminize(MutableFst<Arc> *fst, typename Arc::Label first_new_sym,\n                    std::vector<Int> *symsOut) {\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n  typedef size_t ArcId;  // Our own typedef, not standard OpenFst.  Use size_t\n  // for compatibility with argument of ArcIterator::Seek().\n  typedef typename Arc::Weight Weight;\n  assert(first_new_sym > 0);\n  assert(fst != NULL);\n  if (fst->Start() == kNoStateId) return;  // for empty FST, nothing to do.\n  assert(symsOut != NULL &&\n         symsOut->size() == 0);  // we will output the symbols we add into this.\n\n  {  // (D)(i)(a): check is trim (i.e. connected, in OpenFST parlance).\n    KALDI_VLOG(2) << \"PreDeterminize: Checking FST properties\";\n    uint64 props = fst->Properties(\n        kAccessible | kCoAccessible,\n        true);  // true-> computes properties if unknown at time when called.\n    if (props !=\n        (kAccessible | kCoAccessible)) {  // All states are not both accessible\n                                          // and co-accessible...\n      KALDI_ERR << \"PreDeterminize: FST is not trim\";\n    }\n  }\n\n  {  // (D)(i)(b): make single final state.\n    KALDI_VLOG(2) << \"PreDeterminize: creating single final state\";\n    CreateSuperFinal(fst);\n  }\n\n  {  // (D)(i)(c): sort arcs on input.\n    KALDI_VLOG(2) << \"PreDeterminize: sorting arcs on input\";\n    ILabelCompare<Arc> icomp;\n    ArcSort(fst, icomp);\n  }\n\n  StateId n_states = 0,\n          max_state =\n              0;  // Compute n_states, max_state = highest-numbered state.\n  {               // compute nStates, maxStates.\n    for (StateIterator<MutableFst<Arc> > iter(*fst); !iter.Done();\n         iter.Next()) {\n      StateId state = iter.Value();\n      assert(state >= 0);\n      n_states++;\n      if (state > max_state) max_state = state;\n    }\n    KALDI_VLOG(2) << \"PreDeterminize: n_states = \" << (n_states)\n                  << \", max_state =\" << (max_state);\n  }\n\n  std::vector<bool> p_vec(max_state + 1, false);  // compute this next.\n  {  // D(ii): computing the array p. [\"problematic states, i.e. states with >1\n     // input transition,\n    // counting being the initial state as an input transition\"].\n    std::vector<bool> seen_vec(\n        max_state + 1,\n        false);  // rather than counting incoming transitions we just have a\n                 // bool that says we saw at least one.\n\n    seen_vec[fst->Start()] = true;\n    for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n         siter.Next()) {\n      for (ArcIterator<MutableFst<Arc> > aiter(*fst, siter.Value());\n           !aiter.Done(); aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        assert(arc.nextstate >= 0 && arc.nextstate < max_state + 1);\n        if (seen_vec[arc.nextstate])\n          p_vec[arc.nextstate] =\n              true;  // now have >1 transition in, so problematic.\n        else\n          seen_vec[arc.nextstate] = true;\n      }\n    }\n  }\n  // D(iii): set up m(a)\n  std::map<std::pair<StateId, ArcId>, size_t> m_map;\n  // This is the array m, indexed by arcs.  It maps to the index of the symbol\n  // we add.\n\n  // WARNING: we should be sure to clean up this memory before exiting.  Do not\n  // return or throw an exception from this function, later than this point,\n  // without cleaning up! Note that the vectors are shared between Q and S (they\n  // \"belong to\" S.\n  std::vector<std::vector<StateId> *> S(max_state + 1,\n                                        (std::vector<StateId> *)(void *)0);\n  std::vector<std::pair<std::vector<StateId> *, size_t> > Q;\n\n  // D(iv): initialize S and Q.\n  {\n    std::vector<StateId>\n        all_seed_states;  // all \"problematic\" states, plus initial state (if\n                          // not problematic).\n    if (!p_vec[fst->Start()]) all_seed_states.push_back(fst->Start());\n    for (StateId s = 0; s <= max_state; s++)\n      if (p_vec[s]) all_seed_states.push_back(s);\n\n    for (size_t idx = 0; idx < all_seed_states.size(); idx++) {\n      StateId s = all_seed_states[idx];\n      std::set<StateId> closure_s;\n      closure_s.insert(s);  // insert \"seed\" state.\n      pre_determinize_helpers::Closure(\n          fst, &closure_s,\n          p_vec);  // follow epsilons to non-problematic states.\n      // Closure in this case whis will usually not add anything, for typical\n      // topologies in speech\n      std::vector<StateId> closure_s_vec;\n      pre_determinize_helpers::CopySetToVector(closure_s, &closure_s_vec);\n      KALDI_ASSERT(closure_s_vec.size() != 0);\n      std::vector<StateId> *ptr =\n          pre_determinize_helpers::InsertMember(closure_s_vec, &S);\n      KALDI_ASSERT(ptr != NULL);  // Or conceptual bug or programming error.\n      Q.push_back(std::pair<std::vector<StateId> *, size_t>(ptr, 0));\n    }\n  }\n\n  std::vector<bool> d_vec(max_state + 1,\n                          false);  // \"done vector\".  Purely for debugging.\n\n  size_t num_extra_det_states = 0;\n\n  // (D)(v)\n  while (Q.size() != 0) {\n    // (D)(v)(a)\n    std::pair<std::vector<StateId> *, size_t> cur_pair(Q.back());\n    Q.pop_back();\n    const std::vector<StateId> &A(*cur_pair.first);\n    size_t n = cur_pair.second;  // next special symbol to add.\n\n    // (D)(v)(b)\n    for (size_t idx = 0; idx < A.size(); idx++) {\n      assert(d_vec[A[idx]] == false &&\n             \"This state has been seen before.  Algorithm error.\");\n      d_vec[A[idx]] = true;\n    }\n\n    // From here is (D)(v)(c).  We work out S_\\eps and S_t (for t\\neq eps)\n    // simultaneously at first.\n    std::map<Label, std::set<std::pair<std::pair<StateId, ArcId>, StateId> > >\n        arc_hash;\n    // arc_hash is a hash with info of all arcs from states in the set A to\n    // non-problematic states.\n    // It is a map from ilabel to pair(pair(start-state, arc-offset),\n    // end-state). Here, arc-offset reflects the order in which we accessed the\n    // arc using the ArcIterator (zero for the first arc).\n\n    {  // This block sets up arc_hash\n      for (size_t idx = 0; idx < A.size(); idx++) {\n        StateId s = A[idx];\n        assert(s >= 0 && s <= max_state);\n        ArcId arc_id = 0;\n        for (ArcIterator<MutableFst<Arc> > aiter(*fst, s); !aiter.Done();\n             aiter.Next(), ++arc_id) {\n          const Arc &arc = aiter.Value();\n\n          std::pair<std::pair<StateId, ArcId>, StateId> this_pair(\n              std::pair<StateId, ArcId>(s, arc_id), arc.nextstate);\n          bool inserted = (arc_hash[arc.ilabel].insert(this_pair)).second;\n          assert(inserted);  // Otherwise we had a duplicate.\n        }\n      }\n    }\n\n    // (D)(v)(d)\n    if (arc_hash.count(0) == 1) {  // We have epsilon transitions out.\n      std::set<std::pair<std::pair<StateId, ArcId>, StateId> > &eps_set =\n          arc_hash[0];\n      typedef typename std::set<\n          std::pair<std::pair<StateId, ArcId>, StateId> >::iterator set_iter_t;\n      for (set_iter_t siter = eps_set.begin(); siter != eps_set.end();\n           ++siter) {\n        const std::pair<std::pair<StateId, ArcId>, StateId> &this_pr = *siter;\n        if (p_vec[this_pr.second]) {  // Eps-transition to problematic state.\n          assert(m_map.count(this_pr.first) == 0);\n          m_map[this_pr.first] = n;\n          n++;\n        }\n      }\n    }\n\n    // (D)(v)(e)\n    {\n      typedef typename std::map<\n          Label,\n          std::set<std::pair<std::pair<StateId, ArcId>, StateId> > >::iterator\n          map_iter_t;\n      typedef typename std::set<\n          std::pair<std::pair<StateId, ArcId>, StateId> >::iterator set_iter_t2;\n      for (map_iter_t miter = arc_hash.begin(); miter != arc_hash.end();\n           ++miter) {\n        Label t = miter->first;\n        std::set<std::pair<std::pair<StateId, ArcId>, StateId> > &S_t =\n            miter->second;\n        if (t != 0) {             // For t != epsilon,\n          std::set<StateId> V_t;  // set of destination non-problem states. Will\n                                  // create this set now.\n\n          // exists_noproblem is true iff |U_t| > 0.\n          size_t k = 0;\n\n          // First loop \"for each transition a in T_t\" (i.e. transitions to\n          // problematic states) The if-statement if (|S_t|>1) is pushed inside\n          // the loop, as the loop also computes the set V_t.\n          for (set_iter_t2 siter = S_t.begin(); siter != S_t.end(); ++siter) {\n            const std::pair<std::pair<StateId, ArcId>, StateId> &this_pr =\n                *siter;\n            if (p_vec[this_pr.second]) {  // only consider problematic states\n                                          // (just set T_t)\n              if (S_t.size() >\n                  1) {  // This is where we pushed the if-statement in.\n                assert(m_map.count(this_pr.first) == 0);\n                m_map[this_pr.first] = k;\n                k++;\n                num_extra_det_states++;\n              }\n            } else {  // Create the set V_t.\n              V_t.insert(this_pr.second);\n            }\n          }\n          if (V_t.size() != 0) {\n            pre_determinize_helpers::Closure(\n                fst, &V_t,\n                p_vec);  // follow epsilons to non-problematic states.\n            std::vector<StateId> closure_V_t_vec;\n            pre_determinize_helpers::CopySetToVector(V_t, &closure_V_t_vec);\n            std::vector<StateId> *ptr =\n                pre_determinize_helpers::InsertMember(closure_V_t_vec, &S);\n            if (ptr != NULL) {  // was inserted.\n              Q.push_back(std::pair<std::vector<StateId> *, size_t>(ptr, k));\n            }\n          }\n        }\n      }\n    }\n  }  // end while (Q.size() != 0)\n\n  {  // (D)(vi): Check that for each state in the FST, d(s) = true.\n    for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n         siter.Next()) {\n      StateId val = siter.Value();\n      assert(d_vec[val] == true);\n    }\n  }\n\n  {  // (D)(vii): compute symbol-table ID's.\n    // sets up symsOut array.\n    int64 n = -1;\n    for (typename std::map<std::pair<StateId, ArcId>, size_t>::iterator m_iter =\n             m_map.begin();\n         m_iter != m_map.end(); ++m_iter) {\n      n = std::max(n,\n                   static_cast<int64>(\n                       m_iter->second));  // m_iter->second is of type size_t.\n    }\n    // At this point n is the highest symbol-id (type size_t) of symbols we must\n    // add.\n    n++;  // This is now the number of symbols we must add.\n    for (size_t i = 0; static_cast<int64>(i) < n; i++)\n      symsOut->push_back(first_new_sym + i);\n  }\n\n  // (D)(viii): set up hash.\n  std::map<std::pair<StateId, size_t>, StateId> h_map;\n\n  {  // D(ix): add extra symbols!  This is where the work gets done.\n    // Core part of this is below, search for (*)\n    size_t n_states_added = 0;\n\n    for (typename std::map<std::pair<StateId, ArcId>, size_t>::iterator m_iter =\n             m_map.begin();\n         m_iter != m_map.end(); ++m_iter) {\n      StateId state = m_iter->first.first;\n      ArcId arcpos = m_iter->first.second;\n      size_t m_a = m_iter->second;\n\n      MutableArcIterator<MutableFst<Arc> > aiter(fst, state);\n      aiter.Seek(arcpos);\n      Arc arc = aiter.Value();\n\n      // (*) core part here.\n      if (arc.ilabel == 0) {\n        arc.ilabel = (*symsOut)[m_a];\n      } else {\n        std::pair<StateId, size_t> pr(arc.nextstate, m_a);\n        if (!h_map.count(pr)) {\n          n_states_added++;\n          StateId newstate = fst->AddState();\n          assert(newstate >= 0);\n          Arc new_arc((*symsOut)[m_a], (Label)0, Weight::One(), arc.nextstate);\n          fst->AddArc(newstate, new_arc);\n          h_map[pr] = newstate;\n        }\n        arc.nextstate = h_map[pr];\n      }\n      aiter.SetValue(arc);\n    }\n\n    KALDI_VLOG(2) << \"Added \" << (n_states_added)\n                  << \" new states and added/changed \" << (m_map.size())\n                  << \" arcs\";\n  }\n  // Now free up memory.\n  for (size_t i = 0; i < S.size(); i++) delete S[i];\n}  // end function PreDeterminize\n\ntemplate <class Label>\nvoid CreateNewSymbols(SymbolTable *input_sym_table, int nSym,\n                      std::string prefix, std::vector<Label> *symsOut) {\n  // Creates nSym new symbols named (prefix)0, (prefix)1 and so on.\n  // Crashes if it cannot create them because one or more of them were in the\n  // symbol table already.\n  assert(symsOut && symsOut->size() == 0);\n  for (int i = 0; i < nSym; i++) {\n    std::stringstream ss;\n    ss << prefix << i;\n    std::string str = ss.str();\n    if (input_sym_table->Find(str) != -1) {  // should not be present.\n    }\n    assert(symsOut);\n    symsOut->push_back((Label)input_sym_table->AddSymbol(str));\n  }\n}\n\n// see pre-determinize.h for documentation.\ntemplate <class Arc>\nvoid AddSelfLoops(MutableFst<Arc> *fst,\n                  const std::vector<typename Arc::Label> &isyms,\n                  const std::vector<typename Arc::Label> &osyms) {\n  assert(fst != NULL);\n  assert(isyms.size() == osyms.size());\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  size_t n = isyms.size();\n  if (n == 0) return;  // Nothing to do.\n\n  // {\n  // the following declarations and statements are for quick detection of these\n  // symbols, which is purely for debugging/checking purposes.\n  Label isyms_min = *std::min_element(isyms.begin(), isyms.end()),\n        isyms_max = *std::max_element(isyms.begin(), isyms.end()),\n        osyms_min = *std::min_element(osyms.begin(), osyms.end()),\n        osyms_max = *std::max_element(osyms.begin(), osyms.end());\n  std::set<Label> isyms_set, osyms_set;\n  for (size_t i = 0; i < isyms.size(); i++) {\n    assert(isyms[i] > 0 &&\n           osyms[i] > 0);  // should not have epsilon or invalid symbols.\n    isyms_set.insert(isyms[i]);\n    osyms_set.insert(osyms[i]);\n  }\n  assert(isyms_set.size() == n && osyms_set.size() == n);\n  // } end block.\n\n  for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n       siter.Next()) {\n    StateId state = siter.Value();\n    bool this_state_needs_self_loops = (fst->Final(state) != Weight::Zero());\n    for (ArcIterator<MutableFst<Arc> > aiter(*fst, state); !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      // If one of the following asserts fails, it means that the input FST\n      // already had the symbols we are inserting.  This is contrary to the\n      // preconditions of this algorithm.\n      assert(!(arc.ilabel >= isyms_min && arc.ilabel <= isyms_max &&\n               isyms_set.count(arc.ilabel) != 0));\n      assert(!(arc.olabel >= osyms_min && arc.olabel <= osyms_max &&\n               osyms_set.count(arc.olabel) != 0));\n      if (arc.olabel != 0)  // Has non-epsilon output label -> need self loops.\n        this_state_needs_self_loops = true;\n    }\n    if (this_state_needs_self_loops) {\n      for (size_t i = 0; i < n; i++) {\n        Arc arc;\n        arc.ilabel = isyms[i];\n        arc.olabel = osyms[i];\n        arc.weight = Weight::One();\n        arc.nextstate = state;\n        fst->AddArc(state, arc);\n      }\n    }\n  }\n}\n\ntemplate <class Arc>\nint64 DeleteISymbols(MutableFst<Arc> *fst,\n                     std::vector<typename Arc::Label> isyms) {\n  // We could do this using the Mapper concept, but this is much easier to\n  // understand.\n\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n\n  int64 num_deleted = 0;\n\n  if (isyms.size() == 0) return 0;\n  Label isyms_min = *std::min_element(isyms.begin(), isyms.end()),\n        isyms_max = *std::max_element(isyms.begin(), isyms.end());\n  bool isyms_consecutive =\n      (isyms_max + 1 - isyms_min == static_cast<Label>(isyms.size()));\n  std::set<Label> isyms_set;\n  if (!isyms_consecutive) {\n    for (size_t i = 0; i < isyms.size(); i++) isyms_set.insert(isyms[i]);\n  }\n\n  for (StateIterator<MutableFst<Arc> > siter(*fst); !siter.Done();\n       siter.Next()) {\n    StateId state = siter.Value();\n    for (MutableArcIterator<MutableFst<Arc> > aiter(fst, state); !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel >= isyms_min && arc.ilabel <= isyms_max) {\n        if (isyms_consecutive || isyms_set.count(arc.ilabel) != 0) {\n          num_deleted++;\n          Arc mod_arc(arc);\n          mod_arc.ilabel = 0;  // change label to epsilon.\n          aiter.SetValue(mod_arc);\n        }\n      }\n    }\n  }\n  return num_deleted;\n}\n\ntemplate <class Arc>\ntypename Arc::StateId CreateSuperFinal(MutableFst<Arc> *fst) {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Weight Weight;\n  assert(fst != NULL);\n  StateId num_states = fst->NumStates();\n  StateId num_final = 0;\n  std::vector<StateId> final_states;\n  for (StateId s = 0; s < num_states; s++) {\n    if (fst->Final(s) != Weight::Zero()) {\n      num_final++;\n      final_states.push_back(s);\n    }\n  }\n  if (final_states.size() == 1) {\n    if (fst->Final(final_states[0]) == Weight::One()) {\n      ArcIterator<MutableFst<Arc> > iter(*fst, final_states[0]);\n      if (iter.Done()) {\n        // We already have a final state w/ no transitions out and unit weight.\n        // So we're done.\n        return final_states[0];\n      }\n    }\n  }\n\n  StateId final_state = fst->AddState();\n  fst->SetFinal(final_state, Weight::One());\n  for (size_t idx = 0; idx < final_states.size(); idx++) {\n    StateId s = final_states[idx];\n    Weight weight = fst->Final(s);\n    fst->SetFinal(s, Weight::Zero());\n    Arc arc;\n    arc.ilabel = 0;\n    arc.olabel = 0;\n    arc.nextstate = final_state;\n    arc.weight = weight;\n    fst->AddArc(s, arc);\n  }\n  return final_state;\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_PRE_DETERMINIZE_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/pre-determinize.h",
    "content": "// fstext/pre-determinize.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_PRE_DETERMINIZE_H_\n#define KALDI_FSTEXT_PRE_DETERMINIZE_H_\n\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n\n#include <algorithm>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-common.h\"\n\nnamespace fst {\n\n/* PreDeterminize inserts extra symbols on the input side of an FST as necessary\n   to ensure that, after epsilon removal, it will be compactly determinizable by\n   the determinize* algorithm.  By compactly determinizable we mean that no\n   original FST state is represented in more than one determinized state).\n\n   Caution: this code is now only used in testing.\n\n   The new symbols start from the value \"first_new_symbol\", which should be\n   higher than the largest-numbered symbol currently in the FST.  The new\n   symbols added are put in the array syms_out, which should be empty at start.\n*/\n\ntemplate <class Arc, class Int>\nvoid PreDeterminize(MutableFst<Arc> *fst, typename Arc::Label first_new_symbol,\n                    std::vector<Int> *syms_out);\n\n/* CreateNewSymbols is a helper function used inside PreDeterminize, and is also\n   useful when you need to add a number of extra symbols to a different\n   vocabulary from the one modified by PreDeterminize. */\n\ntemplate <class Label>\nvoid CreateNewSymbols(SymbolTable *inputSymTable, int nSym, std::string prefix,\n                      std::vector<Label> *syms_out);\n\n/** AddSelfLoops is a function you will probably want to use alongside\n   PreDeterminize, to add self-loops to any FSTs that you compose on the left\n   hand side of the one modified by PreDeterminize.\n\n    This function inserts loops with \"special symbols\" [e.g. \\#0, \\#1] into an\n   FST. This is done at each final state and each state with non-epsilon output\n   symbols on at least one arc out of it.  This is to ensure that these symbols,\n   when inserted into the input side of an FST we will compose with on the\n   right, can \"pass through\" this FST.\n\n    At input, isyms and osyms must be vectors of the same size n, corresponding\n    to symbols that currently do not exist in 'fst'.  For each state in n that\n   has non-epsilon symbols on the output side of arcs leaving it, or which is a\n   final state, this function inserts n self-loops with unit weight and one of\n   the n pairs of symbols on its input and output.\n*/\ntemplate <class Arc>\nvoid AddSelfLoops(MutableFst<Arc> *fst,\n                  const std::vector<typename Arc::Label> &isyms,\n                  const std::vector<typename Arc::Label> &osyms);\n\n/* DeleteSymbols replaces any instances of symbols in the vector symsIn,\n   appearing on the input side, with epsilon. */\n/* It returns the number of instances of symbols deleted. */\ntemplate <class Arc>\nint64 DeleteISymbols(MutableFst<Arc> *fst,\n                     std::vector<typename Arc::Label> symsIn);\n\n/* CreateSuperFinal takes an FST, and creates an equivalent FST with a single\n   final state with no transitions out and unit final weight, by inserting\n   epsilon transitions as necessary. */\ntemplate <class Arc>\ntypename Arc::StateId CreateSuperFinal(MutableFst<Arc> *fst);\n\n}  // end namespace fst\n\n#include \"fstext/pre-determinize-inl.h\"\n\n#endif  // KALDI_FSTEXT_PRE_DETERMINIZE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/remove-eps-local-inl.h",
    "content": "// fstext/remove-eps-local-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//                2014  Johns Hopkins University (author: Daniel Povey\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_REMOVE_EPS_LOCAL_INL_H_\n#define KALDI_FSTEXT_REMOVE_EPS_LOCAL_INL_H_\n\n#include <vector>\n\nnamespace fst {\n\ntemplate <class Weight>\nstruct ReweightPlusDefault {\n  inline Weight operator()(const Weight &a, const Weight &b) {\n    return Plus(a, b);\n  }\n};\n\nstruct ReweightPlusLogArc {\n  inline TropicalWeight operator()(const TropicalWeight &a,\n                                   const TropicalWeight &b) {\n    LogWeight a_log(a.Value()), b_log(b.Value());\n    return TropicalWeight(Plus(a_log, b_log).Value());\n  }\n};\n\ntemplate <class Arc,\n          class ReweightPlus = ReweightPlusDefault<typename Arc::Weight> >\nclass RemoveEpsLocalClass {\n  typedef typename Arc::StateId StateId;\n  typedef typename Arc::Label Label;\n  typedef typename Arc::Weight Weight;\n\n public:\n  explicit RemoveEpsLocalClass(MutableFst<Arc> *fst) : fst_(fst) {\n    if (fst_->Start() == kNoStateId) return;  // empty.\n    non_coacc_state_ = fst_->AddState();\n    InitNumArcs();\n    StateId num_states = fst_->NumStates();\n    for (StateId s = 0; s < num_states; s++)\n      for (size_t pos = 0; pos < fst_->NumArcs(s); pos++) RemoveEps(s, pos);\n    assert(CheckNumArcs());\n    Connect(fst);  // remove inaccessible states.\n  }\n\n private:\n  MutableFst<Arc> *fst_;\n  StateId non_coacc_state_;  //  use this to delete arcs: make it nextstate\n  std::vector<StateId> num_arcs_in_;  // The number of arcs into the state, plus\n                                      // one if it's the start state.\n  std::vector<StateId> num_arcs_out_;  // The number of arcs out of the state,\n                                       // plus one if it's a final state.\n  ReweightPlus reweight_plus_;\n\n  bool CanCombineArcs(const Arc &a, const Arc &b, Arc *c) {\n    if (a.ilabel != 0 && b.ilabel != 0) return false;\n    if (a.olabel != 0 && b.olabel != 0) return false;\n    c->weight = Times(a.weight, b.weight);\n    c->ilabel = (a.ilabel != 0 ? a.ilabel : b.ilabel);\n    c->olabel = (a.olabel != 0 ? a.olabel : b.olabel);\n    c->nextstate = b.nextstate;\n    return true;\n  }\n\n  static bool CanCombineFinal(const Arc &a, Weight final_prob,\n                              Weight *final_prob_out) {\n    if (a.ilabel != 0 || a.olabel != 0) {\n      return false;\n    } else {\n      *final_prob_out = Times(a.weight, final_prob);\n      return true;\n    }\n  }\n\n  void InitNumArcs() {  // init num transitions in/out of each state.\n    StateId num_states = fst_->NumStates();\n    num_arcs_in_.resize(num_states);\n    num_arcs_out_.resize(num_states);\n    num_arcs_in_[fst_->Start()]++;  // count start as trans in.\n    for (StateId s = 0; s < num_states; s++) {\n      if (fst_->Final(s) != Weight::Zero())\n        num_arcs_out_[s]++;  // count final as transition.\n      for (ArcIterator<MutableFst<Arc> > aiter(*fst_, s); !aiter.Done();\n           aiter.Next()) {\n        num_arcs_in_[aiter.Value().nextstate]++;\n        num_arcs_out_[s]++;\n      }\n    }\n  }\n\n  bool CheckNumArcs() {  // check num arcs in/out of each state, at end.  Debug.\n    num_arcs_in_[fst_->Start()]--;  // count start as trans in.\n    StateId num_states = fst_->NumStates();\n    for (StateId s = 0; s < num_states; s++) {\n      if (s == non_coacc_state_) continue;\n      if (fst_->Final(s) != Weight::Zero())\n        num_arcs_out_[s]--;  // count final as transition.\n      for (ArcIterator<MutableFst<Arc> > aiter(*fst_, s); !aiter.Done();\n           aiter.Next()) {\n        if (aiter.Value().nextstate == non_coacc_state_) continue;\n        num_arcs_in_[aiter.Value().nextstate]--;\n        num_arcs_out_[s]--;\n      }\n    }\n    for (StateId s = 0; s < num_states; s++) {\n      assert(num_arcs_in_[s] == 0);\n      assert(num_arcs_out_[s] == 0);\n    }\n    return true;  // always does this.  so we can assert it w/o warnings.\n  }\n\n  inline void GetArc(StateId s, size_t pos, Arc *arc) const {\n    ArcIterator<MutableFst<Arc> > aiter(*fst_, s);\n    aiter.Seek(pos);\n    *arc = aiter.Value();\n  }\n\n  inline void SetArc(StateId s, size_t pos, const Arc &arc) {\n    MutableArcIterator<MutableFst<Arc> > aiter(fst_, s);\n    aiter.Seek(pos);\n    aiter.SetValue(arc);\n  }\n\n  void Reweight(StateId s, size_t pos, Weight reweight) {\n    // Reweight is called from RemoveEpsPattern1; it is a step we\n    // do to preserve stochasticity.  This function multiplies the\n    // arc at (s, pos) by reweight and divides all the arcs [+final-prob]\n    // out of the next state by the same.  This is only valid if\n    // the next state has only one arc in and is not the start state.\n    assert(reweight != Weight::Zero());\n    MutableArcIterator<MutableFst<Arc> > aiter(fst_, s);\n    aiter.Seek(pos);\n    Arc arc = aiter.Value();\n    assert(num_arcs_in_[arc.nextstate] == 1);\n    arc.weight = Times(arc.weight, reweight);\n    aiter.SetValue(arc);\n\n    for (MutableArcIterator<MutableFst<Arc> > aiter_next(fst_, arc.nextstate);\n         !aiter_next.Done(); aiter_next.Next()) {\n      Arc nextarc = aiter_next.Value();\n      if (nextarc.nextstate != non_coacc_state_) {\n        nextarc.weight = Divide(nextarc.weight, reweight, DIVIDE_LEFT);\n        aiter_next.SetValue(nextarc);\n      }\n    }\n    Weight final = fst_->Final(arc.nextstate);\n    if (final != Weight::Zero()) {\n      fst_->SetFinal(arc.nextstate, Divide(final, reweight, DIVIDE_LEFT));\n    }\n  }\n\n  // RemoveEpsPattern1 applies where this arc, which is not a\n  // self-loop, enters a state which has only one input transition\n  // [and is not the start state], and has multiple output\n  // transitions [counting being the final-state as a final-transition].\n\n  void RemoveEpsPattern1(StateId s, size_t pos, Arc arc) {\n    const StateId nextstate = arc.nextstate;\n    Weight total_removed = Weight::Zero(),\n           total_kept = Weight::Zero();  // totals out of nextstate.\n    std::vector<Arc> arcs_to_add;        // to add to state s.\n    for (MutableArcIterator<MutableFst<Arc> > aiter_next(fst_, nextstate);\n         !aiter_next.Done(); aiter_next.Next()) {\n      Arc nextarc = aiter_next.Value();\n      if (nextarc.nextstate == non_coacc_state_) continue;  // deleted.\n      Arc combined;\n      if (CanCombineArcs(arc, nextarc, &combined)) {\n        total_removed = reweight_plus_(total_removed, nextarc.weight);\n        num_arcs_out_[nextstate]--;\n        num_arcs_in_[nextarc.nextstate]--;\n        nextarc.nextstate = non_coacc_state_;\n        aiter_next.SetValue(nextarc);\n        arcs_to_add.push_back(combined);\n      } else {\n        total_kept = reweight_plus_(total_kept, nextarc.weight);\n      }\n    }\n\n    {  // now final-state.\n      Weight next_final = fst_->Final(nextstate);\n      if (next_final != Weight::Zero()) {\n        Weight new_final;\n        if (CanCombineFinal(arc, next_final, &new_final)) {\n          total_removed = reweight_plus_(total_removed, next_final);\n          if (fst_->Final(s) == Weight::Zero())\n            num_arcs_out_[s]++;  // final is counted as arc.\n          fst_->SetFinal(s, Plus(fst_->Final(s), new_final));\n          num_arcs_out_[nextstate]--;\n          fst_->SetFinal(nextstate, Weight::Zero());\n        } else {\n          total_kept = reweight_plus_(total_kept, next_final);\n        }\n      }\n    }\n\n    if (total_removed != Weight::Zero()) {  // did something...\n      if (total_kept == Weight::Zero()) {   // removed everything: remove arc.\n        num_arcs_out_[s]--;\n        num_arcs_in_[arc.nextstate]--;\n        arc.nextstate = non_coacc_state_;\n        SetArc(s, pos, arc);\n      } else {\n        // Have to reweight.\n        Weight total = reweight_plus_(total_removed, total_kept);\n        Weight reweight = Divide(total_kept, total, DIVIDE_LEFT);  // <=1\n        Reweight(s, pos, reweight);\n      }\n    }\n    // Now add the arcs we were going to add.\n    for (size_t i = 0; i < arcs_to_add.size(); i++) {\n      num_arcs_out_[s]++;\n      num_arcs_in_[arcs_to_add[i].nextstate]++;\n      fst_->AddArc(s, arcs_to_add[i]);\n    }\n  }\n\n  void RemoveEpsPattern2(StateId s, size_t pos, Arc arc) {\n    // Pattern 2 is where \"nextstate\" has only one arc out, counting\n    // being-the-final-state as an arc, but possibly multiple arcs in.\n    // Also, nextstate != s.\n\n    const StateId nextstate = arc.nextstate;\n    bool can_delete_next = (num_arcs_in_[nextstate] == 1);  // if\n    // we combine, can delete the corresponding out-arc/final-prob\n    // of nextstate.\n    bool delete_arc = false;  // set to true if this arc to be deleted.\n\n    Weight next_final = fst_->Final(arc.nextstate);\n    if (next_final !=\n        Weight::Zero()) {  // nextstate has no actual arcs out, only final-prob.\n      Weight new_final;\n      if (CanCombineFinal(arc, next_final, &new_final)) {\n        if (fst_->Final(s) == Weight::Zero())\n          num_arcs_out_[s]++;  // final is counted as arc.\n        fst_->SetFinal(s, Plus(fst_->Final(s), new_final));\n        delete_arc = true;  // will delete \"arc\".\n        if (can_delete_next) {\n          num_arcs_out_[nextstate]--;\n          fst_->SetFinal(nextstate, Weight::Zero());\n        }\n      }\n    } else {  // has an arc but no final prob.\n      MutableArcIterator<MutableFst<Arc> > aiter_next(fst_, nextstate);\n      assert(!aiter_next.Done());\n      while (aiter_next.Value().nextstate == non_coacc_state_) {\n        aiter_next.Next();\n        assert(!aiter_next.Done());\n      }\n      // now aiter_next points to a real arc out of nextstate.\n      Arc nextarc = aiter_next.Value();\n      Arc combined;\n      if (CanCombineArcs(arc, nextarc, &combined)) {\n        delete_arc = true;\n        if (can_delete_next) {  // do it before we invalidate iterators\n          num_arcs_out_[nextstate]--;\n          num_arcs_in_[nextarc.nextstate]--;\n          nextarc.nextstate = non_coacc_state_;\n          aiter_next.SetValue(nextarc);\n        }\n        num_arcs_out_[s]++;\n        num_arcs_in_[combined.nextstate]++;\n        fst_->AddArc(s, combined);\n      }\n    }\n    if (delete_arc) {\n      num_arcs_out_[s]--;\n      num_arcs_in_[nextstate]--;\n      arc.nextstate = non_coacc_state_;\n      SetArc(s, pos, arc);\n    }\n  }\n\n  void RemoveEps(StateId s, size_t pos) {\n    // Tries to do local epsilon-removal for arc sequences starting with this\n    // arc\n    Arc arc;\n    GetArc(s, pos, &arc);\n    StateId nextstate = arc.nextstate;\n    if (nextstate == non_coacc_state_) return;  // deleted arc.\n    if (nextstate == s) return;  // don't handle self-loops: too complex.\n\n    if (num_arcs_in_[nextstate] == 1 && num_arcs_out_[nextstate] > 1) {\n      RemoveEpsPattern1(s, pos, arc);\n    } else if (num_arcs_out_[nextstate] == 1) {\n      RemoveEpsPattern2(s, pos, arc);\n    }\n  }\n};\n\ntemplate <class Arc>\nvoid RemoveEpsLocal(MutableFst<Arc> *fst) {\n  RemoveEpsLocalClass<Arc> c(fst);  // work gets done in initializer.\n}\n\nvoid RemoveEpsLocalSpecial(MutableFst<StdArc> *fst) {\n  // work gets done in initializer.\n  RemoveEpsLocalClass<StdArc, ReweightPlusLogArc> c(fst);\n}\n\n}  // end namespace fst.\n\n#endif  // KALDI_FSTEXT_REMOVE_EPS_LOCAL_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/remove-eps-local.h",
    "content": "// fstext/remove-eps-local.h\n\n// Copyright 2009-2011  Microsoft Corporation\n//                2014  Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_REMOVE_EPS_LOCAL_H_\n#define KALDI_FSTEXT_REMOVE_EPS_LOCAL_H_\n\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n\nnamespace fst {\n\n/// RemoveEpsLocal remove some (but not necessarily all) epsilons in an FST,\n/// using an algorithm that is guaranteed to never increase the number of arcs\n/// in the FST (and will also never increase the number of states).  The\n/// algorithm is not optimal but is reasonably clever.  It does not just remove\n/// epsilon arcs;it also combines pairs of input-epsilon and output-epsilon arcs\n/// into one.\n/// The algorithm preserves equivalence and stochasticity in the given semiring.\n/// If you want to preserve stochasticity in a different semiring (e.g. log),\n/// then use RemoveEpsLocalSpecial, which only works for StdArc but which\n/// preserves stochasticity, where possible (*) in the LogArc sense.  The reason\n/// that we can't just cast to a different semiring is that in that case we\n/// would no longer be able to guarantee equivalence in the original semiring\n/// (this arises from what happens when we combine identical arcs).\n/// (*) by \"where possible\".. there are situations where we wouldn't be able to\n/// preserve stochasticity in the LogArc sense while maintaining equivalence in\n/// the StdArc sense, so in these situations we maintain equivalence.\n\ntemplate <class Arc>\nvoid RemoveEpsLocal(MutableFst<Arc> *fst);\n\n/// As RemoveEpsLocal but takes care to preserve stochasticity\n/// when cast to LogArc.\ninline void RemoveEpsLocalSpecial(MutableFst<StdArc> *fst);\n\n}  // namespace fst\n\n#include \"fstext/remove-eps-local-inl.h\"\n\n#endif  // KALDI_FSTEXT_REMOVE_EPS_LOCAL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/fstext/table-matcher.h",
    "content": "// fstext/table-matcher.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_FSTEXT_TABLE_MATCHER_H_\n#define KALDI_FSTEXT_TABLE_MATCHER_H_\n\n#include <fst/fst-decl.h>\n#include <fst/fstlib.h>\n\n#include <memory>\n#include <vector>\n\nnamespace fst {\n\n/// TableMatcher is a matcher specialized for the case where the output\n/// side of the left FST always has either all-epsilons coming out of\n/// a state, or a majority of the symbol table.  Therefore we can\n/// either store nothing (for the all-epsilon case) or store a lookup\n/// table from Labels to arc offsets.  Since the TableMatcher has to\n/// iterate over all arcs in each left-hand state the first time it sees\n/// it, this matcher type is not efficient if you compose with\n/// something very small on the right-- unless you do it multiple\n/// times and keep the matcher around. To do this requires using the\n/// most advanced form of ComposeFst in Compose.h, that initializes\n/// with ComposeFstImplOptions.\n\nstruct TableMatcherOptions {\n  float\n      table_ratio;  // we construct the table if it would be at least this full.\n  int min_table_size;\n  TableMatcherOptions() : table_ratio(0.25), min_table_size(4) {}\n};\n\n// Introducing an \"impl\" class for TableMatcher because\n// we need to do a shallow copy of the Matcher for when\n// we want to cache tables for multiple compositions.\ntemplate <class F, class BackoffMatcher = SortedMatcher<F> >\nclass TableMatcherImpl : public MatcherBase<typename F::Arc> {\n public:\n  typedef F FST;\n  typedef typename F::Arc Arc;\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n  typedef StateId\n      ArcId;  // Use this type to store arc offsets [it's actually size_t\n  // in the Seek function of ArcIterator, but StateId should be big enough].\n  typedef typename Arc::Weight Weight;\n\n public:\n  TableMatcherImpl(const FST &fst, MatchType match_type,\n                   const TableMatcherOptions &opts = TableMatcherOptions())\n      : match_type_(match_type),\n        fst_(fst.Copy()),\n        loop_(match_type == MATCH_INPUT\n                  ? Arc(kNoLabel, 0, Weight::One(), kNoStateId)\n                  : Arc(0, kNoLabel, Weight::One(), kNoStateId)),\n        aiter_(NULL),\n        s_(kNoStateId),\n        opts_(opts),\n        backoff_matcher_(fst, match_type) {\n    assert(opts_.min_table_size > 0);\n    if (match_type == MATCH_INPUT)\n      assert(fst_->Properties(kILabelSorted, true) == kILabelSorted);\n    else if (match_type == MATCH_OUTPUT)\n      assert(fst_->Properties(kOLabelSorted, true) == kOLabelSorted);\n    else\n      assert(0 && \"Invalid FST properties\");\n  }\n\n  virtual const FST &GetFst() const { return *fst_; }\n\n  virtual ~TableMatcherImpl() {\n    std::vector<ArcId> *const empty =\n        ((std::vector<ArcId> *)(NULL)) + 1;  // special marker.\n    for (size_t i = 0; i < tables_.size(); i++) {\n      if (tables_[i] != NULL && tables_[i] != empty) delete tables_[i];\n    }\n    delete aiter_;\n    delete fst_;\n  }\n\n  virtual MatchType Type(bool test) const { return match_type_; }\n\n  void SetState(StateId s) {\n    if (aiter_) {\n      delete aiter_;\n      aiter_ = NULL;\n    }\n    if (match_type_ == MATCH_NONE) LOG(FATAL) << \"TableMatcher: bad match type\";\n    s_ = s;\n    std::vector<ArcId> *const empty =\n        ((std::vector<ArcId> *)(NULL)) + 1;  // special marker.\n    if (static_cast<size_t>(s) >= tables_.size()) {\n      assert(s >= 0);\n      tables_.resize(s + 1, NULL);\n    }\n    std::vector<ArcId> *&this_table_ = tables_[s];  // note: ref to ptr.\n    if (this_table_ == empty) {\n      backoff_matcher_.SetState(s);\n      return;\n    } else if (this_table_ == NULL) {  // NULL means has not been set.\n      ArcId num_arcs = fst_->NumArcs(s);\n      if (num_arcs == 0 || num_arcs < opts_.min_table_size) {\n        this_table_ = empty;\n        backoff_matcher_.SetState(s);\n        return;\n      }\n      ArcIterator<FST> aiter(*fst_, s);\n      aiter.SetFlags(\n          kArcNoCache |\n              (match_type_ == MATCH_OUTPUT ? kArcOLabelValue : kArcILabelValue),\n          kArcNoCache | kArcValueFlags);\n      // the statement above, says: \"Don't cache stuff; and I only need the\n      // ilabel/olabel to be computed.\n      aiter.Seek(num_arcs - 1);\n      Label highest_label =\n          (match_type_ == MATCH_OUTPUT ? aiter.Value().olabel\n                                       : aiter.Value().ilabel);\n      if ((highest_label + 1) * opts_.table_ratio > num_arcs) {\n        this_table_ = empty;\n        backoff_matcher_.SetState(s);\n        return;  // table would be too sparse.\n      }\n      // OK, now we are creating the table.\n      this_table_ = new std::vector<ArcId>(highest_label + 1, kNoStateId);\n      ArcId pos = 0;\n      for (aiter.Seek(0); !aiter.Done(); aiter.Next(), pos++) {\n        Label label = (match_type_ == MATCH_OUTPUT ? aiter.Value().olabel\n                                                   : aiter.Value().ilabel);\n        assert(static_cast<size_t>(label) <=\n               static_cast<size_t>(highest_label));  // also checks >= 0.\n        if ((*this_table_)[label] == kNoStateId) (*this_table_)[label] = pos;\n        // set this_table_[label] to first position where arc has this\n        // label.\n      }\n    }\n    // At this point in the code, this_table_ != NULL and != empty.\n    aiter_ = new ArcIterator<FST>(*fst_, s);\n    aiter_->SetFlags(kArcNoCache,\n                     kArcNoCache);  // don't need to cache arcs as may only\n    // need a small subset.\n    loop_.nextstate = s;\n    // aiter_ = NULL;\n    // backoff_matcher_.SetState(s);\n  }\n\n  bool Find(Label match_label) {\n    if (!aiter_) {\n      return backoff_matcher_.Find(match_label);\n    } else {\n      match_label_ = match_label;\n      current_loop_ = (match_label == 0);\n      // kNoLabel means the implicit loop on the other FST --\n      // matches real epsilons but not the self-loop.\n      match_label_ = (match_label_ == kNoLabel ? 0 : match_label_);\n      if (static_cast<size_t>(match_label_) < tables_[s_]->size() &&\n          (*(tables_[s_]))[match_label_] != kNoStateId) {\n        aiter_->Seek((*(tables_[s_]))[match_label_]);  // label exists.\n        return true;\n      }\n      return current_loop_;\n    }\n  }\n  const Arc &Value() const {\n    if (aiter_)\n      return current_loop_ ? loop_ : aiter_->Value();\n    else\n      return backoff_matcher_.Value();\n  }\n\n  void Next() {\n    if (aiter_) {\n      if (current_loop_)\n        current_loop_ = false;\n      else\n        aiter_->Next();\n    } else {\n      backoff_matcher_.Next();\n    }\n  }\n\n  bool Done() const {\n    if (aiter_ != NULL) {\n      if (current_loop_) return false;\n      if (aiter_->Done()) return true;\n      Label label = (match_type_ == MATCH_OUTPUT ? aiter_->Value().olabel\n                                                 : aiter_->Value().ilabel);\n      return (label != match_label_);\n    } else {\n      return backoff_matcher_.Done();\n    }\n  }\n  const Arc &Value() {\n    if (aiter_ != NULL) {\n      return (current_loop_ ? loop_ : aiter_->Value());\n    } else {\n      return backoff_matcher_.Value();\n    }\n  }\n\n  virtual TableMatcherImpl<FST> *Copy(bool safe = false) const {\n    assert(0);  // shouldn't be called.  This is not a \"real\" matcher,\n    // although we derive from MatcherBase for convenience.\n    return NULL;\n  }\n\n  virtual uint64 Properties(uint64 props) const {\n    return props;\n  }  // simple matcher that does\n     // not change its FST, so properties are properties of FST it is applied to\n\n private:\n  virtual void SetState_(StateId s) { SetState(s); }\n  virtual bool Find_(Label label) { return Find(label); }\n  virtual bool Done_() const { return Done(); }\n  virtual const Arc &Value_() const { return Value(); }\n  virtual void Next_() { Next(); }\n\n  MatchType match_type_;\n  FST *fst_;\n  bool current_loop_;\n  Label match_label_;\n  Arc loop_;\n  ArcIterator<FST> *aiter_;\n  StateId s_;\n  std::vector<std::vector<ArcId> *> tables_;\n  TableMatcherOptions opts_;\n  BackoffMatcher backoff_matcher_;\n};\n\ntemplate <class F, class BackoffMatcher = SortedMatcher<F> >\nclass TableMatcher : public MatcherBase<typename F::Arc> {\n public:\n  typedef F FST;\n  typedef typename F::Arc Arc;\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;\n  typedef StateId\n      ArcId;  // Use this type to store arc offsets [it's actually size_t\n  // in the Seek function of ArcIterator, but StateId should be big enough].\n  typedef typename Arc::Weight Weight;\n  typedef TableMatcherImpl<F, BackoffMatcher> Impl;\n\n  TableMatcher(const FST &fst, MatchType match_type,\n               const TableMatcherOptions &opts = TableMatcherOptions())\n      : impl_(std::make_shared<Impl>(fst, match_type, opts)) {}\n\n  TableMatcher(const TableMatcher<FST, BackoffMatcher> &matcher,\n               bool safe = false)\n      : impl_(matcher.impl_) {\n    if (safe == true) {\n      LOG(FATAL) << \"TableMatcher: Safe copy not supported\";\n    }\n  }\n\n  virtual const FST &GetFst() const { return impl_->GetFst(); }\n\n  virtual MatchType Type(bool test) const { return impl_->Type(test); }\n\n  void SetState(StateId s) { return impl_->SetState(s); }\n\n  bool Find(Label match_label) { return impl_->Find(match_label); }\n\n  const Arc &Value() const { return impl_->Value(); }\n\n  void Next() { return impl_->Next(); }\n\n  bool Done() const { return impl_->Done(); }\n\n  const Arc &Value() { return impl_->Value(); }\n\n  virtual TableMatcher<FST, BackoffMatcher> *Copy(bool safe = false) const {\n    return new TableMatcher<FST, BackoffMatcher>(*this, safe);\n  }\n\n  virtual uint64 Properties(uint64 props) const {\n    return impl_->Properties(props);\n  }  // simple matcher that does\n     // not change its FST, so properties are properties of FST it is applied to\n private:\n  std::shared_ptr<Impl> impl_;\n\n  virtual void SetState_(StateId s) { impl_->SetState(s); }\n  virtual bool Find_(Label label) { return impl_->Find(label); }\n  virtual bool Done_() const { return impl_->Done(); }\n  virtual const Arc &Value_() const { return impl_->Value(); }\n  virtual void Next_() { impl_->Next(); }\n\n  TableMatcher &operator=(const TableMatcher &) = delete;\n};\n\nstruct TableComposeOptions : public TableMatcherOptions {\n  bool connect;               // Connect output\n  ComposeFilter filter_type;  // Which pre-defined filter to use\n  MatchType table_match_type;\n\n  explicit TableComposeOptions(const TableMatcherOptions &mo, bool c = true,\n                               ComposeFilter ft = SEQUENCE_FILTER,\n                               MatchType tms = MATCH_OUTPUT)\n      : TableMatcherOptions(mo),\n        connect(c),\n        filter_type(ft),\n        table_match_type(tms) {}\n  TableComposeOptions()\n      : connect(true),\n        filter_type(SEQUENCE_FILTER),\n        table_match_type(MATCH_OUTPUT) {}\n};\n\ntemplate <class Arc>\nvoid TableCompose(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,\n                  MutableFst<Arc> *ofst,\n                  const TableComposeOptions &opts = TableComposeOptions()) {\n  typedef Fst<Arc> F;\n  CacheOptions nopts;\n  nopts.gc_limit = 0;  // Cache only the last state for fastest copy.\n  if (opts.table_match_type == MATCH_OUTPUT) {\n    // ComposeFstImplOptions templated on matcher for fst1, matcher for fst2.\n    ComposeFstImplOptions<TableMatcher<F>, SortedMatcher<F> > impl_opts(nopts);\n    impl_opts.matcher1 = new TableMatcher<F>(ifst1, MATCH_OUTPUT, opts);\n    *ofst = ComposeFst<Arc>(ifst1, ifst2, impl_opts);\n  } else {\n    assert(opts.table_match_type == MATCH_INPUT);\n    // ComposeFstImplOptions templated on matcher for fst1, matcher for fst2.\n    ComposeFstImplOptions<SortedMatcher<F>, TableMatcher<F> > impl_opts(nopts);\n    impl_opts.matcher2 = new TableMatcher<F>(ifst2, MATCH_INPUT, opts);\n    *ofst = ComposeFst<Arc>(ifst1, ifst2, impl_opts);\n  }\n  if (opts.connect) Connect(ofst);\n}\n\n/// TableComposeCache lets us do multiple compositions while caching the same\n/// matcher.\ntemplate <class F>\nstruct TableComposeCache {\n  TableMatcher<F> *matcher;\n  TableComposeOptions opts;\n  explicit TableComposeCache(\n      const TableComposeOptions &opts = TableComposeOptions())\n      : matcher(NULL), opts(opts) {}\n  ~TableComposeCache() { delete (matcher); }\n};\n\ntemplate <class Arc>\nvoid TableCompose(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,\n                  MutableFst<Arc> *ofst, TableComposeCache<Fst<Arc> > *cache) {\n  typedef Fst<Arc> F;\n  assert(cache != NULL);\n  CacheOptions nopts;\n  nopts.gc_limit = 0;  // Cache only the last state for fastest copy.\n  if (cache->opts.table_match_type == MATCH_OUTPUT) {\n    ComposeFstImplOptions<TableMatcher<F>, SortedMatcher<F> > impl_opts(nopts);\n    if (cache->matcher == NULL)\n      cache->matcher = new TableMatcher<F>(ifst1, MATCH_OUTPUT, cache->opts);\n    impl_opts.matcher1 = cache->matcher->Copy();  // not passing \"safe\": may not\n    // be thread-safe-- anway I don't understand this part.\n    *ofst = ComposeFst<Arc>(ifst1, ifst2, impl_opts);\n  } else {\n    assert(cache->opts.table_match_type == MATCH_INPUT);\n    ComposeFstImplOptions<SortedMatcher<F>, TableMatcher<F> > impl_opts(nopts);\n    if (cache->matcher == NULL)\n      cache->matcher = new TableMatcher<F>(ifst2, MATCH_INPUT, cache->opts);\n    impl_opts.matcher2 = cache->matcher->Copy();\n    *ofst = ComposeFst<Arc>(ifst1, ifst2, impl_opts);\n  }\n  if (cache->opts.connect) Connect(ofst);\n}\n\n}  // namespace fst\n\n#endif  // KALDI_FSTEXT_TABLE_MATCHER_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/CMakeLists.txt",
    "content": "\nadd_library(kaldi-lat\ndeterminize-lattice-pruned.cc\nlattice-functions.cc\n)\ntarget_link_libraries(kaldi-lat PUBLIC kaldi-util)"
  },
  {
    "path": "runtime/engine/kaldi/lat/determinize-lattice-pruned.cc",
    "content": "// lat/determinize-lattice-pruned.cc\n\n// Copyright 2009-2012  Microsoft Corporation\n//           2012-2013  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include <vector>\n#include <climits>\n#include \"fstext/determinize-lattice.h\" // for LatticeStringRepository\n#include \"fstext/fstext-utils.h\"\n#include \"lat/lattice-functions.h\"  // for PruneLattice\n// #include \"lat/minimize-lattice.h\"   // for minimization\n// #include \"lat/push-lattice.h\"       // for minimization\n#include \"lat/determinize-lattice-pruned.h\"\n\nnamespace fst {\n\nusing std::vector;\nusing std::pair;\nusing std::greater;\n\n// class LatticeDeterminizerPruned is templated on the same types that\n// CompactLatticeWeight is templated on: the base weight (Weight), typically\n// LatticeWeightTpl<float> etc. but could also be e.g. TropicalWeight, and the\n// IntType, typically int32, used for the output symbols in the compact\n// representation of strings [note: the output symbols would usually be\n// p.d.f. id's in the anticipated use of this code] It has a special requirement\n// on the Weight type: that there should be a Compare function on the weights\n// such that Compare(w1, w2) returns -1 if w1 < w2, 0 if w1 == w2, and +1 if w1 >\n// w2.  This requires that there be a total order on the weights.\n\ntemplate<class Weight, class IntType> class LatticeDeterminizerPruned {\n public:\n  // Output to Gallic acceptor (so the strings go on weights, and there is a 1-1 correspondence\n  // between our states and the states in ofst.  If destroy == true, release memory as we go\n  // (but we cannot output again).\n\n  typedef CompactLatticeWeightTpl<Weight, IntType> CompactWeight;\n  typedef ArcTpl<CompactWeight> CompactArc; // arc in compact, acceptor form of lattice\n  typedef ArcTpl<Weight> Arc; // arc in non-compact version of lattice\n\n  // Output to standard FST with CompactWeightTpl<Weight> as its weight type (the\n  // weight stores the original output-symbol strings).  If destroy == true,\n  // release memory as we go (but we cannot output again).\n  void Output(MutableFst<CompactArc>  *ofst, bool destroy = true) {\n    KALDI_ASSERT(determinized_);\n    typedef typename Arc::StateId StateId;\n    StateId nStates = static_cast<StateId>(output_states_.size());\n    if (destroy)\n      FreeMostMemory();\n    ofst->DeleteStates();\n    ofst->SetStart(kNoStateId);\n    if (nStates == 0) {\n      return;\n    }\n    for (StateId s = 0;s < nStates;s++) {\n      OutputStateId news = ofst->AddState();\n      KALDI_ASSERT(news == s);\n    }\n    ofst->SetStart(0);\n    // now process transitions.\n    for (StateId this_state_id = 0; this_state_id < nStates; this_state_id++) {\n      OutputState &this_state = *(output_states_[this_state_id]);\n      vector<TempArc> &this_vec(this_state.arcs);\n      typename vector<TempArc>::const_iterator iter = this_vec.begin(), end = this_vec.end();\n\n      for (;iter != end; ++iter) {\n        const TempArc &temp_arc(*iter);\n        CompactArc new_arc;\n        vector<Label> olabel_seq;\n        repository_.ConvertToVector(temp_arc.string, &olabel_seq);\n        CompactWeight weight(temp_arc.weight, olabel_seq);\n        if (temp_arc.nextstate == kNoStateId) {  // is really final weight.\n          ofst->SetFinal(this_state_id, weight);\n        } else {  // is really an arc.\n          new_arc.nextstate = temp_arc.nextstate;\n          new_arc.ilabel = temp_arc.ilabel;\n          new_arc.olabel = temp_arc.ilabel;  // acceptor.  input == output.\n          new_arc.weight = weight;  // includes string and weight.\n          ofst->AddArc(this_state_id, new_arc);\n        }\n      }\n      // Free up memory.  Do this inside the loop as ofst is also allocating memory,\n      // and we want to reduce the maximum amount ever allocated.\n      if (destroy) { vector<TempArc> temp; temp.swap(this_vec); }\n    }\n    if (destroy) {\n      FreeOutputStates();\n      repository_.Destroy();\n    }\n  }\n\n  // Output to standard FST with Weight as its weight type.  We will create extra\n  // states to handle sequences of symbols on the output.  If destroy == true,\n  // release memory as we go (but we cannot output again).\n  void  Output(MutableFst<Arc> *ofst, bool destroy = true) {\n    // Outputs to standard fst.\n    OutputStateId nStates = static_cast<OutputStateId>(output_states_.size());\n    ofst->DeleteStates();\n    if (nStates == 0) {\n      ofst->SetStart(kNoStateId);\n      return;\n    }\n    if (destroy)\n      FreeMostMemory();\n    // Add basic states-- but we will add extra ones to account for strings on output.\n    for (OutputStateId s = 0; s< nStates;s++) {\n      OutputStateId news = ofst->AddState();\n      KALDI_ASSERT(news == s);\n    }\n    ofst->SetStart(0);\n    for (OutputStateId this_state_id = 0; this_state_id < nStates; this_state_id++) {\n      OutputState &this_state = *(output_states_[this_state_id]);\n      vector<TempArc> &this_vec(this_state.arcs);\n\n      typename vector<TempArc>::const_iterator iter = this_vec.begin(), end = this_vec.end();\n      for (; iter != end; ++iter) {\n        const TempArc &temp_arc(*iter);\n        vector<Label> seq;\n        repository_.ConvertToVector(temp_arc.string, &seq);\n\n        if (temp_arc.nextstate == kNoStateId) {  // Really a final weight.\n          // Make a sequence of states going to a final state, with the strings\n          // as labels.  Put the weight on the first arc.\n          OutputStateId cur_state = this_state_id;\n          for (size_t i = 0; i < seq.size(); i++) {\n            OutputStateId next_state = ofst->AddState();\n            Arc arc;\n            arc.nextstate = next_state;\n            arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n            arc.ilabel = 0;  // epsilon.\n            arc.olabel = seq[i];\n            ofst->AddArc(cur_state, arc);\n            cur_state = next_state;\n          }\n          ofst->SetFinal(cur_state, (seq.size() == 0 ? temp_arc.weight : Weight::One()));\n        } else {  // Really an arc.\n          OutputStateId cur_state = this_state_id;\n          // Have to be careful with this integer comparison (i+1 < seq.size()) because unsigned.\n          // i < seq.size()-1 could fail for zero-length sequences.\n          for (size_t i = 0; i+1 < seq.size();i++) {\n            // for all but the last element of seq, create new state.\n            OutputStateId next_state = ofst->AddState();\n            Arc arc;\n            arc.nextstate = next_state;\n            arc.weight = (i == 0 ? temp_arc.weight : Weight::One());\n            arc.ilabel = (i == 0 ? temp_arc.ilabel : 0);  // put ilabel on first element of seq.\n            arc.olabel = seq[i];\n            ofst->AddArc(cur_state, arc);\n            cur_state = next_state;\n          }\n          // Add the final arc in the sequence.\n          Arc arc;\n          arc.nextstate = temp_arc.nextstate;\n          arc.weight = (seq.size() <= 1 ? temp_arc.weight : Weight::One());\n          arc.ilabel = (seq.size() <= 1 ? temp_arc.ilabel : 0);\n          arc.olabel = (seq.size() > 0 ? seq.back() : 0);\n          ofst->AddArc(cur_state, arc);\n        }\n      }\n      // Free up memory.  Do this inside the loop as ofst is also allocating memory\n      if (destroy) { vector<TempArc> temp; temp.swap(this_vec); }\n    }\n    if (destroy) {\n      FreeOutputStates();\n      repository_.Destroy();\n    }\n  }\n\n\n  // Initializer.  After initializing the object you will typically\n  // call Determinize() and then call one of the Output functions.\n  // Note: ifst.Copy() will generally do a\n  // shallow copy.  We do it like this for memory safety, rather than\n  // keeping a reference or pointer to ifst_.\n  LatticeDeterminizerPruned(const ExpandedFst<Arc> &ifst,\n                            double beam,\n                            DeterminizeLatticePrunedOptions opts):\n      num_arcs_(0), num_elems_(0), ifst_(ifst.Copy()), beam_(beam), opts_(opts),\n      equal_(opts_.delta), determinized_(false),\n      minimal_hash_(3, hasher_, equal_), initial_hash_(3, hasher_, equal_) {\n    KALDI_ASSERT(Weight::Properties() & kIdempotent); // this algorithm won't\n    // work correctly otherwise.\n  }\n\n  void FreeOutputStates() {\n    for (size_t i = 0; i < output_states_.size(); i++)\n      delete output_states_[i];\n    vector<OutputState*> temp;\n    temp.swap(output_states_);\n  }\n\n  // frees all memory except the info (in output_states_[ ]->arcs)\n  // that we need to output the FST.\n  void FreeMostMemory() {\n    if (ifst_) {\n      delete ifst_;\n      ifst_ = NULL;\n    }\n    { MinimalSubsetHash tmp; tmp.swap(minimal_hash_); }\n\n    for (size_t i = 0; i < output_states_.size(); i++) {\n      vector<Element> empty_subset;\n      empty_subset.swap(output_states_[i]->minimal_subset);\n    }\n\n    for (typename InitialSubsetHash::iterator iter = initial_hash_.begin();\n         iter != initial_hash_.end(); ++iter)\n      delete iter->first;\n    { InitialSubsetHash tmp; tmp.swap(initial_hash_); }\n    for (size_t i = 0; i < output_states_.size(); i++) {\n      vector<Element> tmp;\n      tmp.swap(output_states_[i]->minimal_subset);\n    }\n    { vector<char> tmp;  tmp.swap(isymbol_or_final_); }\n    { // Free up the queue.  I'm not sure how to make sure all\n      // the memory is really freed (no swap() function)... doesn't really\n      // matter much though.\n      while (!queue_.empty()) {\n        Task *t = queue_.top();\n        delete t;\n        queue_.pop();\n      }\n    }\n    { vector<pair<Label, Element> > tmp; tmp.swap(all_elems_tmp_); }\n  }\n\n  ~LatticeDeterminizerPruned() {\n    FreeMostMemory();\n    FreeOutputStates();\n    // rest is deleted by destructors.\n  }\n\n  void RebuildRepository() { // rebuild the string repository,\n    // freeing stuff we don't need.. we call this when memory usage\n    // passes a supplied threshold.  We need to accumulate all the\n    // strings we need the repository to \"remember\", then tell it\n    // to clean the repository.\n    std::vector<StringId> needed_strings;\n    for (size_t i = 0; i < output_states_.size(); i++) {\n      AddStrings(output_states_[i]->minimal_subset, &needed_strings);\n      for (size_t j = 0; j < output_states_[i]->arcs.size(); j++)\n        needed_strings.push_back(output_states_[i]->arcs[j].string);\n    }\n\n    { // the queue doesn't allow us access to the underlying vector,\n      // so we have to resort to a temporary collection.\n      std::vector<Task*> tasks;\n      while (!queue_.empty()) {\n        Task *task = queue_.top();\n        queue_.pop();\n        tasks.push_back(task);\n        AddStrings(task->subset, &needed_strings);\n      }\n      for (size_t i = 0; i < tasks.size(); i++)\n        queue_.push(tasks[i]);\n    }\n\n    // the following loop covers strings present in initial_hash_.\n    for (typename InitialSubsetHash::const_iterator\n             iter = initial_hash_.begin();\n         iter != initial_hash_.end(); ++iter) {\n      const vector<Element> &vec = *(iter->first);\n      Element elem = iter->second;\n      AddStrings(vec, &needed_strings);\n      needed_strings.push_back(elem.string);\n    }\n    std::sort(needed_strings.begin(), needed_strings.end());\n    needed_strings.erase(std::unique(needed_strings.begin(),\n                                     needed_strings.end()),\n                         needed_strings.end()); // uniq the strings.\n    KALDI_LOG << \"Rebuilding repository.\";\n\n    repository_.Rebuild(needed_strings);\n  }\n\n  bool CheckMemoryUsage() {\n    int32 repo_size = repository_.MemSize(),\n        arcs_size = num_arcs_ * sizeof(TempArc),\n        elems_size = num_elems_ * sizeof(Element),\n        total_size = repo_size + arcs_size + elems_size;\n    if (opts_.max_mem > 0 && total_size > opts_.max_mem) { // We passed the memory threshold.\n      // This is usually due to the repository getting large, so we\n      // clean this out.\n      RebuildRepository();\n      int32 new_repo_size = repository_.MemSize(),\n          new_total_size = new_repo_size + arcs_size + elems_size;\n\n      KALDI_VLOG(2) << \"Rebuilt repository in determinize-lattice: repository shrank from \"\n                    << repo_size << \" to \" << new_repo_size << \" bytes (approximately)\";\n\n      if (new_total_size > static_cast<int32>(opts_.max_mem * 0.8)) {\n        // Rebuilding didn't help enough-- we need a margin to stop\n        // having to rebuild too often.  We'll just return to the user at\n        // this point, with a partial lattice that's pruned tighter than\n        // the specified beam.  Here we figure out what the effective\n        // beam was.\n        double effective_beam = beam_;\n        if (!queue_.empty()) { // Note: queue should probably not be empty; we're\n          // just being paranoid here.\n          Task *task = queue_.top();\n          double total_weight = backward_costs_[ifst_->Start()]; // best weight of FST.\n          effective_beam = task->priority_cost - total_weight;\n        }\n        KALDI_WARN << \"Did not reach requested beam in determinize-lattice: \"\n                   << \"size exceeds maximum \" << opts_.max_mem\n                   << \" bytes; (repo,arcs,elems) = (\" << repo_size << \",\"\n                   << arcs_size << \",\" << elems_size\n                   << \"), after rebuilding, repo size was \" << new_repo_size\n                   << \", effective beam was \" << effective_beam\n                   << \" vs. requested beam \" << beam_;\n        return false;\n      }\n    }\n    return true;\n  }\n\n  bool Determinize(double *effective_beam) {\n    KALDI_ASSERT(!determinized_);\n    // This determinizes the input fst but leaves it in the \"special format\"\n    // in \"output_arcs_\".  Must be called after Initialize().  To get the\n    // output, call one of the Output routines.\n\n    InitializeDeterminization(); // some start-up tasks.\n    while (!queue_.empty()) {\n      Task *task = queue_.top();\n      // Note: the queue contains only tasks that are \"within the beam\".\n      // We also have to check whether we have reached one of the user-specified\n      // maximums, of estimated memory, arcs, or states.  The condition for\n      // ending is:\n      // num-states is more than user specified, OR\n      // num-arcs is more than user specified, OR\n      // memory passed a user-specified threshold and cleanup failed\n      //  to get it below that threshold.\n      size_t num_states = output_states_.size();\n      if ((opts_.max_states > 0 && num_states > opts_.max_states) ||\n          (opts_.max_arcs > 0 && num_arcs_ > opts_.max_arcs) ||\n          (num_states % 10 == 0 && !CheckMemoryUsage())) { // note: at some point\n        // it was num_states % 100, not num_states % 10, but I encountered an example\n        // where memory was exhausted before we reached state #100.\n        KALDI_VLOG(1) << \"Lattice determinization terminated but not \"\n                      << \" because of lattice-beam.  (#states, #arcs) is ( \"\n                      << output_states_.size() << \", \" << num_arcs_\n                      << \" ), versus limits ( \" << opts_.max_states << \", \"\n                      << opts_.max_arcs << \" ) (else, may be memory limit).\";\n        break;\n        // we terminate the determinization here-- whatever we already expanded is\n        // what we'll return...  because we expanded stuff in order of total\n        // (forward-backward) weight, the stuff we returned first is the most\n        // important.\n      }\n      queue_.pop();\n      ProcessTransition(task->state, task->label, &(task->subset));\n      delete task;\n    }\n    determinized_ = true;\n    if (effective_beam != NULL) {\n      if (queue_.empty()) *effective_beam = beam_;\n      else\n        *effective_beam = queue_.top()->priority_cost -\n            backward_costs_[ifst_->Start()];\n    }\n    return (queue_.empty()); // return success if queue was empty, i.e. we processed\n    // all tasks and did not break out of the loop early due to reaching a memory,\n    // arc or state limit.\n  }\n private:\n\n  typedef typename Arc::Label Label;\n  typedef typename Arc::StateId StateId;  // use this when we don't know if it's input or output.\n  typedef typename Arc::StateId InputStateId;  // state in the input FST.\n  typedef typename Arc::StateId OutputStateId;  // same as above but distinguish\n                                                // states in output Fst.\n\n  typedef LatticeStringRepository<IntType> StringRepositoryType;\n  typedef const typename StringRepositoryType::Entry* StringId;\n\n  // Element of a subset [of original states]\n  struct Element {\n    StateId state; // use StateId as this is usually InputStateId but in one case\n                   // OutputStateId.\n    StringId string;\n    Weight weight;\n    bool operator != (const Element &other) const {\n      return (state != other.state || string != other.string ||\n              weight != other.weight);\n    }\n    // This operator is only intended for the priority_queue in the function\n    // EpsilonClosure().\n    bool operator > (const Element &other) const {\n      return state > other.state;\n    }\n    // This operator is only intended to support sorting in EpsilonClosure()\n    bool operator < (const Element &other) const {\n      return state < other.state;\n    }\n  };\n\n  // Arcs in the format we temporarily create in this class (a representation, essentially of\n  // a Gallic Fst).\n  struct TempArc {\n    Label ilabel;\n    StringId string;  // Look it up in the StringRepository, it's a sequence of Labels.\n    OutputStateId nextstate;  // or kNoState for final weights.\n    Weight weight;\n  };\n\n  // Hashing function used in hash of subsets.\n  // A subset is a pointer to vector<Element>.\n  // The Elements are in sorted order on state id, and without repeated states.\n  // Because the order of Elements is fixed, we can use a hashing function that is\n  // order-dependent.  However the weights are not included in the hashing function--\n  // we hash subsets that differ only in weight to the same key.  This is not optimal\n  // in terms of the O(N) performance but typically if we have a lot of determinized\n  // states that differ only in weight then the input probably was pathological in some way,\n  // or even non-determinizable.\n  //   We don't quantize the weights, in order to avoid inexactness in simple cases.\n  // Instead we apply the delta when comparing subsets for equality, and allow a small\n  // difference.\n\n  class SubsetKey {\n   public:\n    size_t operator ()(const vector<Element> * subset) const {  // hashes only the state and string.\n      size_t hash = 0, factor = 1;\n      for (typename vector<Element>::const_iterator iter= subset->begin(); iter != subset->end(); ++iter) {\n        hash *= factor;\n        hash += iter->state + reinterpret_cast<size_t>(iter->string);\n        factor *= 23531;  // these numbers are primes.\n      }\n      return hash;\n    }\n  };\n\n  // This is the equality operator on subsets.  It checks for exact match on state-id\n  // and string, and approximate match on weights.\n  class SubsetEqual {\n   public:\n    bool operator ()(const vector<Element> * s1, const vector<Element> * s2) const {\n      size_t sz = s1->size();\n      KALDI_ASSERT(sz>=0);\n      if (sz != s2->size()) return false;\n      typename vector<Element>::const_iterator iter1 = s1->begin(),\n          iter1_end = s1->end(), iter2=s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state ||\n           iter1->string != iter2->string ||\n            ! ApproxEqual(iter1->weight, iter2->weight, delta_)) return false;\n      }\n      return true;\n    }\n    float delta_;\n    SubsetEqual(float delta): delta_(delta) {}\n    SubsetEqual(): delta_(kDelta) {}\n  };\n\n  // Operator that says whether two Elements have the same states.\n  // Used only for debug.\n  class SubsetEqualStates {\n   public:\n    bool operator ()(const vector<Element> * s1, const vector<Element> * s2) const {\n      size_t sz = s1->size();\n      KALDI_ASSERT(sz>=0);\n      if (sz != s2->size()) return false;\n      typename vector<Element>::const_iterator iter1 = s1->begin(),\n          iter1_end = s1->end(), iter2=s2->begin();\n      for (; iter1 < iter1_end; ++iter1, ++iter2) {\n        if (iter1->state != iter2->state) return false;\n      }\n      return true;\n    }\n  };\n\n  // Define the hash type we use to map subsets (in minimal\n  // representation) to OutputStateId.\n  typedef unordered_map<const vector<Element>*, OutputStateId,\n                        SubsetKey, SubsetEqual> MinimalSubsetHash;\n\n  // Define the hash type we use to map subsets (in initial\n  // representation) to OutputStateId, together with an\n  // extra weight. [note: we interpret the Element.state in here\n  // as an OutputStateId even though it's declared as InputStateId;\n  // these types are the same anyway].\n  typedef unordered_map<const vector<Element>*, Element,\n                        SubsetKey, SubsetEqual> InitialSubsetHash;\n\n\n  // converts the representation of the subset from canonical (all states) to\n  // minimal (only states with output symbols on arcs leaving them, and final\n  // states).  Output is not necessarily normalized, even if input_subset was.\n  void ConvertToMinimal(vector<Element> *subset) {\n    KALDI_ASSERT(!subset->empty());\n    typename vector<Element>::iterator cur_in = subset->begin(),\n        cur_out = subset->begin(), end = subset->end();\n    while (cur_in != end) {\n      if(IsIsymbolOrFinal(cur_in->state)) {  // keep it...\n        *cur_out = *cur_in;\n        cur_out++;\n      }\n      cur_in++;\n    }\n    subset->resize(cur_out - subset->begin());\n  }\n\n  // Takes a minimal, normalized subset, and converts it to an OutputStateId.\n  // Involves a hash lookup, and possibly adding a new OutputStateId.\n  // If it creates a new OutputStateId, it creates a new record for it, works\n  // out its final-weight, and puts stuff on the queue relating to its\n  // transitions.\n  OutputStateId MinimalToStateId(const vector<Element> &subset,\n                                 const double forward_cost) {\n    typename MinimalSubsetHash::const_iterator iter\n        = minimal_hash_.find(&subset);\n    if (iter != minimal_hash_.end()) { // Found a matching subset.\n      OutputStateId state_id = iter->second;\n      const OutputState &state = *(output_states_[state_id]);\n      // Below is just a check that the algorithm is working...\n      if (forward_cost < state.forward_cost - 0.1) {\n        // for large weights, this check could fail due to roundoff.\n        KALDI_WARN << \"New cost is less (check the difference is small) \"\n                   << forward_cost << \", \"\n                   << state.forward_cost;\n      }\n      return state_id;\n    }\n    OutputStateId state_id = static_cast<OutputStateId>(output_states_.size());\n    OutputState *new_state = new OutputState(subset, forward_cost);\n    minimal_hash_[&(new_state->minimal_subset)] = state_id;\n    output_states_.push_back(new_state);\n    num_elems_ += subset.size();\n    // Note: in the previous algorithm, we pushed the new state-id onto the queue\n    // at this point.  Here, the queue happens elsewhere, and we directly process\n    // the state (which result in stuff getting added to the queue).\n    ProcessFinal(state_id); // will work out the final-prob.\n    ProcessTransitions(state_id); // will process transitions and add stuff to the queue.\n    return state_id;\n  }\n\n\n  // Given a normalized initial subset of elements (i.e. before epsilon closure),\n  // compute the corresponding output-state.\n  OutputStateId InitialToStateId(const vector<Element> &subset_in,\n                                 double forward_cost,\n                                 Weight *remaining_weight,\n                                 StringId *common_prefix) {\n    typename InitialSubsetHash::const_iterator iter\n        = initial_hash_.find(&subset_in);\n    if (iter != initial_hash_.end()) { // Found a matching subset.\n      const Element &elem = iter->second;\n      *remaining_weight = elem.weight;\n      *common_prefix = elem.string;\n      if (elem.weight == Weight::Zero())\n        KALDI_WARN << \"Zero weight!\";\n      return elem.state;\n    }\n    // else no matching subset-- have to work it out.\n    vector<Element> subset(subset_in);\n    // Follow through epsilons.  Will add no duplicate states.  note: after\n    // EpsilonClosure, it is the same as \"canonical\" subset, except not\n    // normalized (actually we never compute the normalized canonical subset,\n    // only the normalized minimal one).\n    EpsilonClosure(&subset); // follow epsilons.\n    ConvertToMinimal(&subset); // remove all but emitting and final states.\n\n    Element elem; // will be used to store remaining weight and string, and\n                 // OutputStateId, in initial_hash_;\n    NormalizeSubset(&subset, &elem.weight, &elem.string); // normalize subset; put\n    // common string and weight in \"elem\".  The subset is now a minimal,\n    // normalized subset.\n\n    forward_cost += ConvertToCost(elem.weight);\n    OutputStateId ans = MinimalToStateId(subset, forward_cost);\n    *remaining_weight = elem.weight;\n    *common_prefix = elem.string;\n    if (elem.weight == Weight::Zero())\n      KALDI_WARN << \"Zero weight!\";\n\n    // Before returning \"ans\", add the initial subset to the hash,\n    // so that we can bypass the epsilon-closure etc., next time\n    // we process the same initial subset.\n    vector<Element> *initial_subset_ptr = new vector<Element>(subset_in);\n    elem.state = ans;\n    initial_hash_[initial_subset_ptr] = elem;\n    num_elems_ += initial_subset_ptr->size(); // keep track of memory usage.\n    return ans;\n  }\n\n  // returns the Compare value (-1 if a < b, 0 if a == b, 1 if a > b) according\n  // to the ordering we defined on strings for the CompactLatticeWeightTpl.\n  // see function\n  // inline int Compare (const CompactLatticeWeightTpl<WeightType,IntType> &w1,\n  //                     const CompactLatticeWeightTpl<WeightType,IntType> &w2)\n  // in lattice-weight.h.\n  // this is the same as that, but optimized for our data structures.\n  inline int Compare(const Weight &a_w, StringId a_str,\n                     const Weight &b_w, StringId b_str) const {\n    int weight_comp = fst::Compare(a_w, b_w);\n    if (weight_comp != 0) return weight_comp;\n    // now comparing strings.\n    if (a_str == b_str) return 0;\n    vector<IntType> a_vec, b_vec;\n    repository_.ConvertToVector(a_str, &a_vec);\n    repository_.ConvertToVector(b_str, &b_vec);\n    // First compare their lengths.\n    int a_len = a_vec.size(), b_len = b_vec.size();\n    // use opposite order on the string lengths (c.f. Compare in\n    // lattice-weight.h)\n    if (a_len > b_len) return -1;\n    else if (a_len < b_len) return 1;\n    for(int i = 0; i < a_len; i++) {\n      if (a_vec[i] < b_vec[i]) return -1;\n      else if (a_vec[i] > b_vec[i]) return 1;\n    }\n    KALDI_ASSERT(0); // because we checked if a_str == b_str above, shouldn't reach here\n    return 0;\n  }\n\n  // This function computes epsilon closure of subset of states by following epsilon links.\n  // Called by InitialToStateId and Initialize.\n  // Has no side effects except on the string repository.  The \"output_subset\" is not\n  // necessarily normalized (in the sense of there being no common substring), unless\n  // input_subset was.\n  void EpsilonClosure(vector<Element> *subset) {\n    // at input, subset must have only one example of each StateId.  [will still\n    // be so at output].  This function follows input-epsilons, and augments the\n    // subset accordingly.\n\n    std::priority_queue<Element, vector<Element>, greater<Element> > queue;\n    unordered_map<InputStateId, Element> cur_subset;\n    typedef typename unordered_map<InputStateId, Element>::iterator MapIter;\n    typedef typename vector<Element>::const_iterator VecIter;\n\n    for (VecIter iter = subset->begin(); iter != subset->end(); ++iter) {\n      queue.push(*iter);\n      cur_subset[iter->state] = *iter;\n    }\n\n    // find whether input fst is known to be sorted on input label.\n    bool sorted = ((ifst_->Properties(kILabelSorted, false) & kILabelSorted) != 0);\n    bool replaced_elems = false; // relates to an optimization, see below.\n    int counter = 0; // stops infinite loops here for non-lattice-determinizable input\n    // (e.g. input with negative-cost epsilon loops); useful in testing.\n    while (queue.size() != 0) {\n      Element elem = queue.top();\n      queue.pop();\n\n      // The next if-statement is a kind of optimization.  It's to prevent us\n      // unnecessarily repeating the processing of a state.  \"cur_subset\" always\n      // contains only one Element with a particular state.  The issue is that\n      // whenever we modify the Element corresponding to that state in \"cur_subset\",\n      // both the new (optimal) and old (less-optimal) Element will still be in\n      // \"queue\".  The next if-statement stops us from wasting compute by\n      // processing the old Element.\n      if (replaced_elems && cur_subset[elem.state] != elem)\n        continue;\n      if (opts_.max_loop > 0 && counter++ > opts_.max_loop) {\n        KALDI_ERR << \"Lattice determinization aborted since looped more than \"\n                  << opts_.max_loop << \" times during epsilon closure.\";\n      }\n      for (ArcIterator<ExpandedFst<Arc> > aiter(*ifst_, elem.state); !aiter.Done(); aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        if (sorted && arc.ilabel != 0) break;  // Break from the loop: due to sorting there will be no\n        // more transitions with epsilons as input labels.\n        if (arc.ilabel == 0\n            && arc.weight != Weight::Zero()) {  // Epsilon transition.\n          Element next_elem;\n          next_elem.state = arc.nextstate;\n          next_elem.weight = Times(elem.weight, arc.weight);\n          // next_elem.string is not set up yet... create it only\n          // when we know we need it (this is an optimization)\n\n          MapIter iter = cur_subset.find(next_elem.state);\n          if (iter == cur_subset.end()) {\n            // was no such StateId: insert and add to queue.\n            next_elem.string = (arc.olabel == 0 ? elem.string :\n                                repository_.Successor(elem.string, arc.olabel));\n            cur_subset[next_elem.state] = next_elem;\n            queue.push(next_elem);\n          } else {\n            // was not inserted because one already there.  In normal\n            // determinization we'd add the weights.  Here, we find which one\n            // has the better weight, and keep its corresponding string.\n            int comp = fst::Compare(next_elem.weight, iter->second.weight);\n            if (comp == 0) { // A tie on weights.  This should be a rare case;\n                             // we don't optimize for it.\n              next_elem.string = (arc.olabel == 0 ? elem.string :\n                                  repository_.Successor(elem.string,\n                                                        arc.olabel));\n              comp = Compare(next_elem.weight, next_elem.string,\n                             iter->second.weight, iter->second.string);\n            }\n            if(comp == 1) { // next_elem is better, so use its (weight, string)\n              next_elem.string = (arc.olabel == 0 ? elem.string :\n                                  repository_.Successor(elem.string, arc.olabel));\n              iter->second.string = next_elem.string;\n              iter->second.weight = next_elem.weight;\n              queue.push(next_elem);\n              replaced_elems = true;\n            }\n            // else it is the same or worse, so use original one.\n          }\n        }\n      }\n    }\n\n    { // copy cur_subset to subset.\n      subset->clear();\n      subset->reserve(cur_subset.size());\n      MapIter iter = cur_subset.begin(), end = cur_subset.end();\n      for (; iter != end; ++iter) subset->push_back(iter->second);\n      // sort by state ID, because the subset hash function is order-dependent(see SubsetKey)\n      std::sort(subset->begin(), subset->end());\n    }\n  }\n\n\n  // This function works out the final-weight of the determinized state.\n  // called by ProcessSubset.\n  // Has no side effects except on the variable repository_, and\n  // output_states_[output_state_id].arcs\n\n  void ProcessFinal(OutputStateId output_state_id) {\n    OutputState &state = *(output_states_[output_state_id]);\n    const vector<Element> &minimal_subset = state.minimal_subset;\n    // processes final-weights for this subset.  state.minimal_subset_ may be\n    // empty if the graphs is not connected/trimmed, I think, do don't check\n    // that it's nonempty.\n    StringId final_string = repository_.EmptyString();  // set it to keep the\n    // compiler happy; if it doesn't get set in the loop, we won't use the value anyway.\n    Weight final_weight = Weight::Zero();\n    bool is_final = false;\n    typename vector<Element>::const_iterator iter = minimal_subset.begin(), end = minimal_subset.end();\n    for (; iter != end; ++iter) {\n      const Element &elem = *iter;\n      Weight this_final_weight = Times(elem.weight, ifst_->Final(elem.state));\n      StringId this_final_string = elem.string;\n      if (this_final_weight != Weight::Zero() &&\n         (!is_final || Compare(this_final_weight, this_final_string,\n                               final_weight, final_string) == 1)) { // the new\n        // (weight, string) pair is more in semiring than our current\n        // one.\n        is_final = true;\n        final_weight = this_final_weight;\n        final_string = this_final_string;\n      }\n    }\n    if (is_final &&\n        ConvertToCost(final_weight) + state.forward_cost <= cutoff_) {\n      // store final weights in TempArc structure, just like a transition.\n      // Note: we only store the final-weight if it's inside the pruning beam, hence\n      // the stuff with Compare.\n      TempArc temp_arc;\n      temp_arc.ilabel = 0;\n      temp_arc.nextstate = kNoStateId;  // special marker meaning \"final weight\".\n      temp_arc.string = final_string;\n      temp_arc.weight = final_weight;\n      state.arcs.push_back(temp_arc);\n      num_arcs_++;\n    }\n  }\n\n  // NormalizeSubset normalizes the subset \"elems\" by\n  // removing any common string prefix (putting it in common_str),\n  // and dividing by the total weight (putting it in tot_weight).\n  void NormalizeSubset(vector<Element> *elems,\n                       Weight *tot_weight,\n                       StringId *common_str) {\n    if(elems->empty()) { // just set common_str, tot_weight\n      // to defaults and return...\n      KALDI_WARN << \"empty subset\";\n      *common_str = repository_.EmptyString();\n      *tot_weight = Weight::Zero();\n      return;\n    }\n    size_t size = elems->size();\n    vector<IntType> common_prefix;\n    repository_.ConvertToVector((*elems)[0].string, &common_prefix);\n    Weight weight = (*elems)[0].weight;\n    for(size_t i = 1; i < size; i++) {\n      weight = Plus(weight, (*elems)[i].weight);\n      repository_.ReduceToCommonPrefix((*elems)[i].string, &common_prefix);\n    }\n    KALDI_ASSERT(weight != Weight::Zero()); // we made sure to ignore arcs with zero\n    // weights on them, so we shouldn't have zero here.\n    size_t prefix_len = common_prefix.size();\n    for(size_t i = 0; i < size; i++) {\n      (*elems)[i].weight = Divide((*elems)[i].weight, weight, DIVIDE_LEFT);\n      (*elems)[i].string =\n          repository_.RemovePrefix((*elems)[i].string, prefix_len);\n    }\n    *common_str = repository_.ConvertFromVector(common_prefix);\n    *tot_weight = weight;\n  }\n\n  // Take a subset of Elements that is sorted on state, and\n  // merge any Elements that have the same state (taking the best\n  // (weight, string) pair in the semiring).\n  void MakeSubsetUnique(vector<Element> *subset) {\n    typedef typename vector<Element>::iterator IterType;\n\n    // This KALDI_ASSERT is designed to fail (usually) if the subset is not sorted on\n    // state.\n    KALDI_ASSERT(subset->size() < 2 || (*subset)[0].state <= (*subset)[1].state);\n\n    IterType cur_in = subset->begin(), cur_out = cur_in, end = subset->end();\n    size_t num_out = 0;\n    // Merge elements with same state-id\n    while (cur_in != end) {  // while we have more elements to process.\n      // At this point, cur_out points to location of next place we want to put an element,\n      // cur_in points to location of next element we want to process.\n      if (cur_in != cur_out) *cur_out = *cur_in;\n      cur_in++;\n      while (cur_in != end && cur_in->state == cur_out->state) {\n        if (Compare(cur_in->weight, cur_in->string,\n                   cur_out->weight, cur_out->string) == 1) {\n          // if *cur_in > *cur_out in semiring, then take *cur_in.\n          cur_out->string = cur_in->string;\n          cur_out->weight = cur_in->weight;\n        }\n        cur_in++;\n      }\n      cur_out++;\n      num_out++;\n    }\n    subset->resize(num_out);\n  }\n\n  // ProcessTransition was called from \"ProcessTransitions\" in the non-pruned\n  // code, but now we in effect put the calls to ProcessTransition on a priority\n  // queue, and it now gets called directly from Determinize().  This function\n  // processes a transition from state \"ostate_id\".  The set \"subset\" of Elements\n  // represents a set of next-states with associated weights and strings, each\n  // one arising from an arc from some state in a determinized-state; the\n  // next-states are unique (there is only one Entry assocated with each)\n  void ProcessTransition(OutputStateId ostate_id, Label ilabel, vector<Element> *subset) {\n\n    double forward_cost = output_states_[ostate_id]->forward_cost;\n    StringId common_str;\n    Weight tot_weight;\n    NormalizeSubset(subset, &tot_weight, &common_str);\n    forward_cost += ConvertToCost(tot_weight);\n\n    OutputStateId nextstate;\n    {\n      Weight next_tot_weight;\n      StringId next_common_str;\n      nextstate = InitialToStateId(*subset,\n                                   forward_cost,\n                                   &next_tot_weight,\n                                   &next_common_str);\n      common_str = repository_.Concatenate(common_str, next_common_str);\n      tot_weight = Times(tot_weight, next_tot_weight);\n    }\n\n    // Now add an arc to the next state (would have been created if necessary by\n    // InitialToStateId).\n    TempArc temp_arc;\n    temp_arc.ilabel = ilabel;\n    temp_arc.nextstate = nextstate;\n    temp_arc.string = common_str;\n    temp_arc.weight = tot_weight;\n    output_states_[ostate_id]->arcs.push_back(temp_arc);  // record the arc.\n    num_arcs_++;\n  }\n\n\n  // \"less than\" operator for pair<Label, Element>.   Used in ProcessTransitions.\n  // Lexicographical order, which only compares the state when ordering the\n  // \"Element\" member of the pair.\n\n  class PairComparator {\n   public:\n    inline bool operator () (const pair<Label, Element> &p1, const pair<Label, Element> &p2) {\n      if (p1.first < p2.first) return true;\n      else if (p1.first > p2.first) return false;\n      else {\n        return p1.second.state < p2.second.state;\n      }\n    }\n  };\n\n\n  // ProcessTransitions processes emitting transitions (transitions with\n  // ilabels) out of this subset of states.  It actualy only creates records\n  // (\"Task\") that get added to the queue.  The transitions will be processed in\n  // priority order from Determinize().  This function soes not consider final\n  // states.  Partitions the emitting transitions up by ilabel (by sorting on\n  // ilabel), and for each unique ilabel, it creates a Task record that contains\n  // the information we need to process the transition.\n\n  void ProcessTransitions(OutputStateId output_state_id) {\n    const vector<Element> &minimal_subset = output_states_[output_state_id]->minimal_subset;\n    // it's possible that minimal_subset could be empty if there are\n    // unreachable parts of the graph, so don't check that it's nonempty.\n    vector<pair<Label, Element> > &all_elems(all_elems_tmp_); // use class member\n    // to avoid memory allocation/deallocation.\n    {\n      // Push back into \"all_elems\", elements corresponding to all\n      // non-epsilon-input transitions out of all states in \"minimal_subset\".\n      typename vector<Element>::const_iterator iter = minimal_subset.begin(), end = minimal_subset.end();\n      for (;iter != end; ++iter) {\n        const Element &elem = *iter;\n        for (ArcIterator<ExpandedFst<Arc> > aiter(*ifst_, elem.state); ! aiter.Done(); aiter.Next()) {\n          const Arc &arc = aiter.Value();\n          if (arc.ilabel != 0\n              && arc.weight != Weight::Zero()) {  // Non-epsilon transition -- ignore epsilons here.\n            pair<Label, Element> this_pr;\n            this_pr.first = arc.ilabel;\n            Element &next_elem(this_pr.second);\n            next_elem.state = arc.nextstate;\n            next_elem.weight = Times(elem.weight, arc.weight);\n            if (arc.olabel == 0) // output epsilon\n              next_elem.string = elem.string;\n            else\n              next_elem.string = repository_.Successor(elem.string, arc.olabel);\n            all_elems.push_back(this_pr);\n          }\n        }\n      }\n    }\n    PairComparator pc;\n    std::sort(all_elems.begin(), all_elems.end(), pc);\n    // now sorted first on input label, then on state.\n    typedef typename vector<pair<Label, Element> >::const_iterator PairIter;\n    PairIter cur = all_elems.begin(), end = all_elems.end();\n    while (cur != end) {\n      // The old code (non-pruned) called ProcessTransition; here, instead,\n      // we'll put the calls into a priority queue.\n      Task *task = new Task;\n      // Process ranges that share the same input symbol.\n      Label ilabel = cur->first;\n      task->state = output_state_id;\n      task->priority_cost = std::numeric_limits<double>::infinity();\n      task->label = ilabel;\n      while (cur != end && cur->first == ilabel) {\n        task->subset.push_back(cur->second);\n        const Element &element = cur->second;\n        // Note: we'll later include the term \"forward_cost\" in the\n        // priority_cost.\n        task->priority_cost = std::min(task->priority_cost,\n                                       ConvertToCost(element.weight) +\n                                       backward_costs_[element.state]);\n        cur++;\n      }\n\n      // After the command below, the \"priority_cost\" is a value comparable to\n      // the total-weight of the input FST, like a total-path weight... of\n      // course, it will typically be less (in the semiring) than that.\n      // note: we represent it just as a double.\n      task->priority_cost += output_states_[output_state_id]->forward_cost;\n\n      if (task->priority_cost > cutoff_) {\n        // This task would never get done as it's past the pruning cutoff.\n        delete task;\n      } else {\n        MakeSubsetUnique(&(task->subset)); // remove duplicate Elements with the same state.\n        queue_.push(task); // Push the task onto the queue.  The queue keeps it\n        // in prioritized order, so we always process the one with the \"best\"\n        // weight (highest in the semiring).\n\n        { // this is a check.\n          double best_cost = backward_costs_[ifst_->Start()],\n              tolerance = 0.01 + 1.0e-04 * std::abs(best_cost);\n          if (task->priority_cost < best_cost - tolerance) {\n            KALDI_WARN << \"Cost below best cost was encountered:\"\n                       << task->priority_cost << \" < \" << best_cost;\n          }\n        }\n      }\n    }\n    all_elems.clear(); // as it's a reference to a class variable; we want it to stay\n    // empty.\n  }\n\n\n  bool IsIsymbolOrFinal(InputStateId state) { // returns true if this state\n    // of the input FST either is final or has an osymbol on an arc out of it.\n    // Uses the vector isymbol_or_final_ as a cache for this info.\n    KALDI_ASSERT(state >= 0);\n    if (isymbol_or_final_.size() <= state)\n      isymbol_or_final_.resize(state+1, static_cast<char>(OSF_UNKNOWN));\n    if (isymbol_or_final_[state] == static_cast<char>(OSF_NO))\n      return false;\n    else if (isymbol_or_final_[state] == static_cast<char>(OSF_YES))\n      return true;\n    // else work it out...\n    isymbol_or_final_[state] = static_cast<char>(OSF_NO);\n    if (ifst_->Final(state) != Weight::Zero())\n      isymbol_or_final_[state] = static_cast<char>(OSF_YES);\n    for (ArcIterator<ExpandedFst<Arc> > aiter(*ifst_, state);\n         !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc = aiter.Value();\n      if (arc.ilabel != 0 && arc.weight != Weight::Zero()) {\n        isymbol_or_final_[state] = static_cast<char>(OSF_YES);\n        return true;\n      }\n    }\n    return IsIsymbolOrFinal(state); // will only recurse once.\n  }\n\n  void ComputeBackwardWeight() {\n    // Sets up the backward_costs_ array, and the cutoff_ variable.\n    KALDI_ASSERT(beam_ > 0);\n\n    // Only handle the toplogically sorted case.\n    backward_costs_.resize(ifst_->NumStates());\n    for (StateId s = ifst_->NumStates() - 1; s >= 0; s--) {\n      double &cost = backward_costs_[s];\n      cost = ConvertToCost(ifst_->Final(s));\n      for (ArcIterator<ExpandedFst<Arc> > aiter(*ifst_, s);\n           !aiter.Done(); aiter.Next()) {\n        const Arc &arc = aiter.Value();\n        cost = std::min(cost,\n                        ConvertToCost(arc.weight) + backward_costs_[arc.nextstate]);\n      }\n    }\n\n    if (ifst_->Start() == kNoStateId) return; // we'll be returning\n    // an empty FST.\n\n    double best_cost = backward_costs_[ifst_->Start()];\n    if (best_cost == std::numeric_limits<double>::infinity())\n      KALDI_WARN << \"Total weight of input lattice is zero.\";\n    cutoff_ = best_cost + beam_;\n  }\n\n  void InitializeDeterminization() {\n    // We insist that the input lattice be topologically sorted.  This is not a\n    // fundamental limitation of the algorithm (which in principle should be\n    // applicable to even cyclic FSTs), but it helps us more efficiently\n    // compute the backward_costs_ array.  There may be some other reason we\n    // require this, that escapes me at the moment.\n    KALDI_ASSERT(ifst_->Properties(kTopSorted, true) != 0);\n    ComputeBackwardWeight();\n#if !(__GNUC__ == 4 && __GNUC_MINOR__ == 0)\n    if(ifst_->Properties(kExpanded, false) != 0) { // if we know the number of\n      // states in ifst_, it might be a bit more efficient\n      // to pre-size the hashes so we're not constantly rebuilding them.\n      StateId num_states =\n          down_cast<const ExpandedFst<Arc>*, const Fst<Arc> >(ifst_)->NumStates();\n      minimal_hash_.rehash(num_states/2 + 3);\n      initial_hash_.rehash(num_states/2 + 3);\n    }\n#endif\n    InputStateId start_id = ifst_->Start();\n    if (start_id != kNoStateId) {\n      /* Create determinized-state corresponding to the start state....\n         Unlike all the other states, we don't \"normalize\" the representation\n         of this determinized-state before we put it into minimal_hash_.  This is actually\n         what we want, as otherwise we'd have problems dealing with any extra weight\n         and string and might have to create a \"super-initial\" state which would make\n         the output nondeterministic.  Normalization is only needed to make the\n         determinized output more minimal anyway, it's not needed for correctness.\n         Note, we don't put anything in the initial_hash_.  The initial_hash_ is only\n         a lookaside buffer anyway, so this isn't a problem-- it will get populated\n         later if it needs to be.\n      */\n      vector<Element> subset(1);\n      subset[0].state = start_id;\n      subset[0].weight = Weight::One();\n      subset[0].string = repository_.EmptyString();  // Id of empty sequence.\n      EpsilonClosure(&subset); // follow through epsilon-input links\n      ConvertToMinimal(&subset); // remove all but final states and\n      // states with input-labels on arcs out of them.\n      // Weight::One() is the \"forward-weight\" of this determinized state...\n      // i.e. the minimal cost from the start of the determinized FST to this\n      // state [One() because it's the start state].\n      OutputState *initial_state = new OutputState(subset, 0);\n      KALDI_ASSERT(output_states_.empty());\n      output_states_.push_back(initial_state);\n      num_elems_ += subset.size();\n      OutputStateId initial_state_id = 0;\n      minimal_hash_[&(initial_state->minimal_subset)] = initial_state_id;\n      ProcessFinal(initial_state_id);\n      ProcessTransitions(initial_state_id); // this will add tasks to\n      // the queue, which we'll start processing in Determinize().\n    }\n  }\n\n  KALDI_DISALLOW_COPY_AND_ASSIGN(LatticeDeterminizerPruned);\n\n  struct OutputState {\n    vector<Element> minimal_subset;\n    vector<TempArc> arcs; // arcs out of the state-- those that have been processed.\n    // Note: the final-weight is included here with kNoStateId as the state id.  We\n    // always process the final-weight regardless of the beam; when producing the\n    // output we may have to ignore some of these.\n    double forward_cost; // Represents minimal cost from start-state\n    // to this state.  Used in prioritization of tasks, and pruning.\n    // Note: we know this minimal cost from when we first create the OutputState;\n    // this is because of the priority-queue we use, that ensures that the\n    // \"best\" path into the state will be expanded first.\n    OutputState(const vector<Element> &minimal_subset,\n                double forward_cost): minimal_subset(minimal_subset),\n                                      forward_cost(forward_cost) { }\n  };\n\n  vector<OutputState*> output_states_; // All the info about the output states.\n\n  int num_arcs_; // keep track of memory usage: number of arcs in output_states_[ ]->arcs\n  int num_elems_; // keep track of memory usage: number of elems in output_states_ and\n  // the keys of initial_hash_\n\n  const ExpandedFst<Arc> *ifst_;\n  std::vector<double> backward_costs_; // This vector stores, for every state in ifst_,\n  // the minimal cost to the end-state (i.e. the sum of weights; they are guaranteed to\n  // have \"take-the-minimum\" semantics).  We get the double from the ConvertToCost()\n  // function on the lattice weights.\n\n  double beam_;\n  double cutoff_; // beam plus total-weight of input (and note, the weight is\n  // guaranteed to be \"tropical-like\" so the sum does represent a min-cost.\n\n  DeterminizeLatticePrunedOptions opts_;\n  SubsetKey hasher_;  // object that computes keys-- has no data members.\n  SubsetEqual equal_;  // object that compares subsets-- only data member is delta_.\n  bool determinized_; // set to true when user called Determinize(); used to make\n  // sure this object is used correctly.\n  MinimalSubsetHash minimal_hash_;  // hash from Subset to OutputStateId.  Subset is \"minimal\n                                    // representation\" (only include final and states and states with\n                                    // nonzero ilabel on arc out of them.  Owns the pointers\n                                    // in its keys.\n  InitialSubsetHash initial_hash_;   // hash from Subset to Element, which\n                                     // represents the OutputStateId together\n                                     // with an extra weight and string.  Subset\n                                     // is \"initial representation\".  The extra\n                                     // weight and string is needed because after\n                                     // we convert to minimal representation and\n                                     // normalize, there may be an extra weight\n                                     // and string.  Owns the pointers\n                                     // in its keys.\n\n  struct Task {\n    OutputStateId state; // State from which we're processing the transition.\n    Label label; // Label on the transition we're processing out of this state.\n    vector<Element> subset; // Weighted subset of states (with strings)-- not normalized.\n    double priority_cost; // Cost used in deciding priority of tasks.  Note:\n    // we assume there is a ConvertToCost() function that converts the semiring to double.\n  };\n\n  struct TaskCompare {\n    inline int operator() (const Task *t1, const Task *t2) {\n      // view this like operator <, which is the default template parameter\n      // to std::priority_queue.\n      // returns true if t1 is worse than t2.\n      return (t1->priority_cost > t2->priority_cost);\n    }\n  };\n\n  // This priority queue contains \"Task\"s to be processed; these correspond\n  // to transitions out of determinized states.  We process these in priority\n  // order according to the best weight of any path passing through these\n  // determinized states... it's possible to work this out.\n  std::priority_queue<Task*, vector<Task*>, TaskCompare> queue_;\n\n  vector<pair<Label, Element> > all_elems_tmp_; // temporary vector used in ProcessTransitions.\n\n  enum IsymbolOrFinal { OSF_UNKNOWN = 0, OSF_NO = 1, OSF_YES = 2 };\n\n  vector<char> isymbol_or_final_; // A kind of cache; it says whether\n  // each state is (emitting or final) where emitting means it has at least one\n  // non-epsilon output arc.  Only accessed by IsIsymbolOrFinal()\n\n  LatticeStringRepository<IntType> repository_;  // defines a compact and fast way of\n  // storing sequences of labels.\n\n  void AddStrings(const vector<Element> &vec,\n                  vector<StringId> *needed_strings) {\n    for (typename std::vector<Element>::const_iterator iter = vec.begin();\n         iter != vec.end(); ++iter)\n      needed_strings->push_back(iter->string);\n  }\n};\n\n\n// normally Weight would be LatticeWeight<float> (which has two floats),\n// or possibly TropicalWeightTpl<float>, and IntType would be int32.\n// Caution: there are two versions of the function DeterminizeLatticePruned,\n// with identical code but different output FST types.\ntemplate<class Weight, class IntType>\nbool DeterminizeLatticePruned(\n    const ExpandedFst<ArcTpl<Weight> >&ifst,\n    double beam,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > >*ofst,\n    DeterminizeLatticePrunedOptions opts) {\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  ofst->SetOutputSymbols(ifst.OutputSymbols());\n  if (ifst.NumStates() == 0) {\n    ofst->DeleteStates();\n    return true;\n  }\n  KALDI_ASSERT(opts.retry_cutoff >= 0.0 && opts.retry_cutoff < 1.0);\n  int32 max_num_iters = 10;  // avoid the potential for infinite loops if\n                             // retrying.\n  VectorFst<ArcTpl<Weight> > temp_fst;\n\n  for (int32 iter = 0; iter < max_num_iters; iter++) {\n    LatticeDeterminizerPruned<Weight, IntType> det(iter == 0 ? ifst : temp_fst,\n                                                   beam, opts);\n    double effective_beam;\n    bool ans = det.Determinize(&effective_beam);\n    // if it returns false it will typically still produce reasonable output,\n    // just with a narrower beam than \"beam\".  If the user specifies an infinite\n    // beam we don't do this beam-narrowing.\n    if (effective_beam >= beam * opts.retry_cutoff ||\n        beam == std::numeric_limits<double>::infinity() ||\n        iter + 1 == max_num_iters) {\n      det.Output(ofst);\n      return ans;\n    } else {\n      // The code below to set \"beam\" is a heuristic.\n      // If effective_beam is very small, we want to reduce by a lot.\n      // But never change the beam by more than a factor of two.\n      if (effective_beam < 0.0) effective_beam = 0.0;\n      double new_beam = beam * sqrt(effective_beam / beam);\n      if (new_beam < 0.5 * beam) new_beam = 0.5 * beam;\n      beam = new_beam;\n      if (iter == 0) temp_fst = ifst;\n      kaldi::PruneLattice(beam, &temp_fst);\n      KALDI_LOG << \"Pruned state-level lattice with beam \" << beam\n                << \" and retrying determinization with that beam.\";\n    }\n  }\n  return false; // Suppress compiler warning; this code is unreachable.\n}\n\n\n// normally Weight would be LatticeWeight<float> (which has two floats),\n// or possibly TropicalWeightTpl<float>, and IntType would be int32.\n// Caution: there are two versions of the function DeterminizeLatticePruned,\n// with identical code but different output FST types.\ntemplate<class Weight>\nbool DeterminizeLatticePruned(const ExpandedFst<ArcTpl<Weight> > &ifst,\n                              double beam,\n                              MutableFst<ArcTpl<Weight> > *ofst,\n                              DeterminizeLatticePrunedOptions opts) {\n  typedef int32 IntType;\n  ofst->SetInputSymbols(ifst.InputSymbols());\n  ofst->SetOutputSymbols(ifst.OutputSymbols());\n  KALDI_ASSERT(opts.retry_cutoff >= 0.0 && opts.retry_cutoff < 1.0);\n  if (ifst.NumStates() == 0) {\n    ofst->DeleteStates();\n    return true;\n  }\n  int32 max_num_iters = 10;  // avoid the potential for infinite loops if\n                             // retrying.\n  VectorFst<ArcTpl<Weight> > temp_fst;\n\n  for (int32 iter = 0; iter < max_num_iters; iter++) {\n    LatticeDeterminizerPruned<Weight, IntType> det(iter == 0 ? ifst : temp_fst,\n                                                   beam, opts);\n    double effective_beam;\n    bool ans = det.Determinize(&effective_beam);\n    // if it returns false it will typically still\n    // produce reasonable output, just with a\n    // narrower beam than \"beam\".\n    if (effective_beam >= beam * opts.retry_cutoff ||\n        iter + 1 == max_num_iters) {\n      det.Output(ofst);\n      return ans;\n    } else {\n      // The code below to set \"beam\" is a heuristic.\n      // If effective_beam is very small, we want to reduce by a lot.\n      // But never change the beam by more than a factor of two.\n      if (effective_beam < 0)\n        effective_beam = 0;\n      double new_beam = beam * sqrt(effective_beam / beam);\n      if (new_beam < 0.5 * beam) new_beam = 0.5 * beam;\n      KALDI_WARN << \"Effective beam \" << effective_beam << \" was less than beam \"\n                 << beam << \" * cutoff \" << opts.retry_cutoff << \", pruning raw \"\n                 << \"lattice with new beam \" << new_beam << \" and retrying.\";\n      beam = new_beam;\n      if (iter == 0) temp_fst = ifst;\n      kaldi::PruneLattice(beam, &temp_fst);\n    }\n  }\n  return false; // Suppress compiler warning; this code is unreachable.\n}\n\n// template<class Weight>\n// typename ArcTpl<Weight>::Label DeterminizeLatticeInsertPhones(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<ArcTpl<Weight> > *fst) {\n//   // Define some types.\n//   typedef ArcTpl<Weight> Arc;\n//   typedef typename Arc::StateId StateId;\n//   typedef typename Arc::Label Label;\n//\n//   // Work out the first phone symbol. This is more related to the phone\n//   // insertion function, so we put it here and make it the returning value of\n//   // DeterminizeLatticeInsertPhones().\n//   Label first_phone_label = HighestNumberedInputSymbol(*fst) + 1;\n//\n//   // Insert phones here.\n//   for (StateIterator<MutableFst<Arc> > siter(*fst);\n//        !siter.Done(); siter.Next()) {\n//     StateId state = siter.Value();\n//     if (state == fst->Start())\n//       continue;\n//     for (MutableArcIterator<MutableFst<Arc> > aiter(fst, state);\n//          !aiter.Done(); aiter.Next()) {\n//       Arc arc = aiter.Value();\n//\n//       // Note: the words are on the input symbol side and transition-id's are on\n//       // the output symbol side.\n//       if ((arc.olabel != 0)\n//           && (trans_model.TransitionIdToHmmState(arc.olabel) == 0)\n//           && (!trans_model.IsSelfLoop(arc.olabel))) {\n//         Label phone =\n//             static_cast<Label>(trans_model.TransitionIdToPhone(arc.olabel));\n//\n//         // Skips <eps>.\n//         KALDI_ASSERT(phone != 0);\n//\n//         if (arc.ilabel == 0) {\n//           // If there is no word on the arc, insert the phone directly.\n//           arc.ilabel = first_phone_label + phone;\n//         } else {\n//           // Otherwise, add an additional arc.\n//           StateId additional_state = fst->AddState();\n//           StateId next_state = arc.nextstate;\n//           arc.nextstate = additional_state;\n//           fst->AddArc(additional_state,\n//                       Arc(first_phone_label + phone, 0,\n//                           Weight::One(), next_state));\n//         }\n//       }\n//\n//       aiter.SetValue(arc);\n//     }\n//   }\n//\n//   return first_phone_label;\n// }\n//\n// template<class Weight>\n// void DeterminizeLatticeDeletePhones(\n//     typename ArcTpl<Weight>::Label first_phone_label,\n//     MutableFst<ArcTpl<Weight> > *fst) {\n//   // Define some types.\n//   typedef ArcTpl<Weight> Arc;\n//   typedef typename Arc::StateId StateId;\n//   typedef typename Arc::Label Label;\n//\n//   // Delete phones here.\n//   for (StateIterator<MutableFst<Arc> > siter(*fst);\n//        !siter.Done(); siter.Next()) {\n//     StateId state = siter.Value();\n//     for (MutableArcIterator<MutableFst<Arc> > aiter(fst, state);\n//          !aiter.Done(); aiter.Next()) {\n//       Arc arc = aiter.Value();\n//\n//       if (arc.ilabel >= first_phone_label)\n//         arc.ilabel = 0;\n//\n//       aiter.SetValue(arc);\n//     }\n//   }\n// }\n// instantiate for type LatticeWeight\n// template\n// void DeterminizeLatticeDeletePhones(\n//     ArcTpl<kaldi::LatticeWeight>::Label first_phone_label,\n//     MutableFst<ArcTpl<kaldi::LatticeWeight> > *fst);\n//\n// /** This function does a first pass determinization with phone symbols inserted\n//     at phone boundary. It uses a transition model to work out the transition-id\n//     to phone map. First, phones will be inserted into the word level lattice.\n//     Second, determinization will be applied on top of the phone + word lattice.\n//     Finally, the inserted phones will be removed, converting the lattice back to\n//     a word level lattice. The output lattice of this pass is not deterministic,\n//     since we remove the phone symbols as a last step. It is supposed to be\n//     followed by another pass of determinization at the word level. It could also\n//     be useful for some other applications such as fMLLR estimation, confidence\n//     estimation, discriminative training, etc.\n// */\n// template<class Weight, class IntType>\n// bool DeterminizeLatticePhonePrunedFirstPass(\n//     const kaldi::TransitionModel &trans_model,\n//     double beam,\n//     MutableFst<ArcTpl<Weight> > *fst,\n//     const DeterminizeLatticePrunedOptions &opts) {\n//   // First, insert the phones.\n//   typename ArcTpl<Weight>::Label first_phone_label =\n//       DeterminizeLatticeInsertPhones(trans_model, fst);\n//   TopSort(fst);\n//\n//   // Second, do determinization with phone inserted.\n//   bool ans = DeterminizeLatticePruned<Weight>(*fst, beam, fst, opts);\n//\n//   // Finally, remove the inserted phones.\n//   DeterminizeLatticeDeletePhones(first_phone_label, fst);\n//   TopSort(fst);\n//\n//   return ans;\n// }\n//\n// // \"Destructive\" version of DeterminizeLatticePhonePruned() where the input\n// // lattice might be modified.\n// template<class Weight, class IntType>\n// bool DeterminizeLatticePhonePruned(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<ArcTpl<Weight> > *ifst,\n//     double beam,\n//     MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts) {\n//   // Returning status.\n//   bool ans = true;\n//\n//   // Make sure at least one of opts.phone_determinize and opts.word_determinize\n//   // is not false, otherwise calling this function doesn't make any sense.\n//   if ((opts.phone_determinize || opts.word_determinize) == false) {\n//     KALDI_WARN << \"Both --phone-determinize and --word-determinize are set to \"\n//                << \"false, copying lattice without determinization.\";\n//     // We are expecting the words on the input side.\n//     ConvertLattice<Weight, IntType>(*ifst, ofst, false);\n//     return ans;\n//   }\n//\n//   // Determinization options.\n//   DeterminizeLatticePrunedOptions det_opts;\n//   det_opts.delta = opts.delta;\n//   det_opts.max_mem = opts.max_mem;\n//\n//   // If --phone-determinize is true, do the determinization on phone + word\n//   // lattices.\n//   if (opts.phone_determinize) {\n//     KALDI_VLOG(3) << \"Doing first pass of determinization on phone + word \"\n//                   << \"lattices.\";\n//     ans = DeterminizeLatticePhonePrunedFirstPass<Weight, IntType>(\n//         trans_model, beam, ifst, det_opts) && ans;\n//\n//     // If --word-determinize is false, we've finished the job and return here.\n//     if (!opts.word_determinize) {\n//       // We are expecting the words on the input side.\n//       ConvertLattice<Weight, IntType>(*ifst, ofst, false);\n//       return ans;\n//     }\n//   }\n//\n//   // If --word-determinize is true, do the determinization on word lattices.\n//   if (opts.word_determinize) {\n//     KALDI_VLOG(3) << \"Doing second pass of determinization on word lattices.\";\n//     ans = DeterminizeLatticePruned<Weight, IntType>(\n//         *ifst, beam, ofst, det_opts) && ans;\n//   }\n//\n//   // If --minimize is true, push and minimize after determinization.\n//   if (opts.minimize) {\n//     KALDI_VLOG(3) << \"Pushing and minimizing on word lattices.\";\n//     ans = PushCompactLatticeStrings<Weight, IntType>(ofst) && ans;\n//     ans = PushCompactLatticeWeights<Weight, IntType>(ofst) && ans;\n//     ans = MinimizeCompactLattice<Weight, IntType>(ofst) && ans;\n//   }\n//\n//   return ans;\n// }\n//\n// // Normal verson of DeterminizeLatticePhonePruned(), where the input lattice\n// // will be kept as unchanged.\n// template<class Weight, class IntType>\n// bool DeterminizeLatticePhonePruned(\n//     const kaldi::TransitionModel &trans_model,\n//     const ExpandedFst<ArcTpl<Weight> > &ifst,\n//     double beam,\n//     MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts) {\n//   VectorFst<ArcTpl<Weight> > temp_fst(ifst);\n//   return DeterminizeLatticePhonePruned(trans_model, &temp_fst,\n//                                        beam, ofst, opts);\n// }\n//\n// bool DeterminizeLatticePhonePrunedWrapper(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<kaldi::LatticeArc> *ifst,\n//     double beam,\n//     MutableFst<kaldi::CompactLatticeArc> *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts) {\n//   bool ans = true;\n//   Invert(ifst);\n//   if (ifst->Properties(fst::kTopSorted, true) == 0) {\n//     if (!TopSort(ifst)) {\n//       // Cannot topologically sort the lattice -- determinization will fail.\n//       KALDI_ERR << \"Topological sorting of state-level lattice failed (probably\"\n//                 << \" your lexicon has empty words or your LM has epsilon cycles\"\n//                 << \").\";\n//     }\n//   }\n//   ILabelCompare<kaldi::LatticeArc> ilabel_comp;\n//   ArcSort(ifst, ilabel_comp);\n//   ans = DeterminizeLatticePhonePruned<kaldi::LatticeWeight, kaldi::int32>(\n//       trans_model, ifst, beam, ofst, opts);\n//   Connect(ofst);\n//   return ans;\n// }\n\n// Instantiate the templates for the types we might need.\n// Note: there are actually four templates, each of which\n// we instantiate for a single type.\ntemplate\nbool DeterminizeLatticePruned<kaldi::LatticeWeight>(\n    const ExpandedFst<kaldi::LatticeArc> &ifst,\n    double prune,\n    MutableFst<kaldi::CompactLatticeArc> *ofst,\n    DeterminizeLatticePrunedOptions opts);\n\ntemplate\nbool DeterminizeLatticePruned<kaldi::LatticeWeight>(\n    const ExpandedFst<kaldi::LatticeArc> &ifst,\n    double prune,\n    MutableFst<kaldi::LatticeArc> *ofst,\n    DeterminizeLatticePrunedOptions opts);\n\n// template\n// bool DeterminizeLatticePhonePruned<kaldi::LatticeWeight, kaldi::int32>(\n//     const kaldi::TransitionModel &trans_model,\n//     const ExpandedFst<kaldi::LatticeArc> &ifst,\n//     double prune,\n//     MutableFst<kaldi::CompactLatticeArc> *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts);\n//\n// template\n// bool DeterminizeLatticePhonePruned<kaldi::LatticeWeight, kaldi::int32>(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<kaldi::LatticeArc> *ifst,\n//     double prune,\n//     MutableFst<kaldi::CompactLatticeArc> *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts);\n\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/determinize-lattice-pruned.h",
    "content": "// lat/determinize-lattice-pruned.h\n\n// Copyright 2009-2012  Microsoft Corporation\n//           2012-2013  Johns Hopkins University (Author: Daniel Povey)\n//                2014  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_LAT_DETERMINIZE_LATTICE_PRUNED_H_\n#define KALDI_LAT_DETERMINIZE_LATTICE_PRUNED_H_\n#include <fst/fstlib.h>\n#include <fst/fst-decl.h>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <vector>\n#include \"fstext/lattice-weight.h\"\n// #include \"hmm/transition-model.h\"\n#include \"util/options-itf.h\"\n#include \"lat/kaldi-lattice.h\"\n\nnamespace fst {\n\n/// \\addtogroup fst_extensions\n///  @{\n\n\n// For example of usage, see test-determinize-lattice-pruned.cc\n\n/*\n   DeterminizeLatticePruned implements a special form of determinization with\n   epsilon removal, optimized for a phase of lattice generation.  This algorithm\n   also does pruning at the same time-- the combination is more efficient as it\n   somtimes prevents us from creating a lot of states that would later be pruned\n   away.  This allows us to increase the lattice-beam and not have the algorithm\n   blow up.  Also, because our algorithm processes states in order from those\n   that appear on high-scoring paths down to those that appear on low-scoring\n   paths, we can easily terminate the algorithm after a certain specified number\n   of states or arcs.\n\n   The input is an FST with weight-type BaseWeightType (usually a pair of floats,\n   with a lexicographical type of order, such as LatticeWeightTpl<float>).\n   Typically this would be a state-level lattice, with input symbols equal to\n   words, and output-symbols equal to p.d.f's (so like the inverse of HCLG).  Imagine representing this as an\n   acceptor of type CompactLatticeWeightTpl<float>, in which the input/output\n   symbols are words, and the weights contain the original weights together with\n   strings (with zero or one symbol in them) containing the original output labels\n   (the p.d.f.'s).  We determinize this using acceptor determinization with\n   epsilon removal.  Remember (from lattice-weight.h) that\n   CompactLatticeWeightTpl has a special kind of semiring where we always take\n   the string corresponding to the best cost (of type BaseWeightType), and\n   discard the other.  This corresponds to taking the best output-label sequence\n   (of p.d.f.'s) for each input-label sequence (of words).  We couldn't use the\n   Gallic weight for this, or it would die as soon as it detected that the input\n   FST was non-functional.  In our case, any acyclic FST (and many cyclic ones)\n   can be determinized.\n   We assume that there is a function\n      Compare(const BaseWeightType &a, const BaseWeightType &b)\n   that returns (-1, 0, 1) according to whether (a < b, a == b, a > b) in the\n   total order on the BaseWeightType... this information should be the\n   same as NaturalLess would give, but it's more efficient to do it this way.\n   You can define this for things like TropicalWeight if you need to instantiate\n   this class for that weight type.\n\n   We implement this determinization in a special way to make it efficient for\n   the types of FSTs that we will apply it to.  One issue is that if we\n   explicitly represent the strings (in CompactLatticeWeightTpl) as vectors of\n   type vector<IntType>, the algorithm takes time quadratic in the length of\n   words (in states), because propagating each arc involves copying a whole\n   vector (of integers representing p.d.f.'s).  Instead we use a hash structure\n   where each string is a pointer (Entry*), and uses a hash from (Entry*,\n   IntType), to the successor string (and a way to get the latest IntType and the\n   ancestor Entry*).  [this is the class LatticeStringRepository].\n\n   Another issue is that rather than representing a determinized-state as a\n   collection of (state, weight), we represent it in a couple of reduced forms.\n   Suppose a determinized-state is a collection of (state, weight) pairs; call\n   this the \"canonical representation\".  Note: these collections are always\n   normalized to remove any common weight and string part.  Define end-states as\n   the subset of states that have an arc out of them with a label on, or are\n   final.  If we represent a determinized-state a the set of just its (end-state,\n   weight) pairs, this will be a valid and more compact representation, and will\n   lead to a smaller set of determinized states (like early minimization).  Call\n   this collection of (end-state, weight) pairs the \"minimal representation\".  As\n   a mechanism to reduce compute, we can also consider another representation.\n   In the determinization algorithm, we start off with a set of (begin-state,\n   weight) pairs (where the \"begin-states\" are initial or have a label on the\n   transition into them), and the \"canonical representation\" consists of the\n   epsilon-closure of this set (i.e. follow epsilons).  Call this set of\n   (begin-state, weight) pairs, appropriately normalized, the \"initial\n   representation\".  If two initial representations are the same, the \"canonical\n   representation\" and hence the \"minimal representation\" will be the same.  We\n   can use this to reduce compute.  Note that if two initial representations are\n   different, this does not preclude the other representations from being the same.\n\n*/\n\n\nstruct DeterminizeLatticePrunedOptions {\n  float delta; // A small offset used to measure equality of weights.\n  int max_mem; // If >0, determinization will fail and return false\n  // when the algorithm's (approximate) memory consumption crosses this threshold.\n  int max_loop; // If >0, can be used to detect non-determinizable input\n  // (a case that wouldn't be caught by max_mem).\n  int max_states;\n  int max_arcs;\n  float retry_cutoff;\n  DeterminizeLatticePrunedOptions(): delta(kDelta),\n                                     max_mem(-1),\n                                     max_loop(-1),\n                                     max_states(-1),\n                                     max_arcs(-1),\n                                     retry_cutoff(0.5) { }\n  void Register (kaldi::OptionsItf *opts) {\n    opts->Register(\"delta\", &delta, \"Tolerance used in determinization\");\n    opts->Register(\"max-mem\", &max_mem, \"Maximum approximate memory usage in \"\n                   \"determinization (real usage might be many times this)\");\n    opts->Register(\"max-arcs\", &max_arcs, \"Maximum number of arcs in \"\n                   \"output FST (total, not per state\");\n    opts->Register(\"max-states\", &max_states, \"Maximum number of arcs in output \"\n                   \"FST (total, not per state\");\n    opts->Register(\"max-loop\", &max_loop, \"Option used to detect a particular \"\n                   \"type of determinization failure, typically due to invalid input \"\n                   \"(e.g., negative-cost loops)\");\n    opts->Register(\"retry-cutoff\", &retry_cutoff, \"Controls pruning un-determinized \"\n                   \"lattice and retrying determinization: if effective-beam < \"\n                   \"retry-cutoff * beam, we prune the raw lattice and retry.  Avoids \"\n                   \"ever getting empty output for long segments.\");\n  }\n};\n\nstruct DeterminizeLatticePhonePrunedOptions {\n  // delta: a small offset used to measure equality of weights.\n  float delta;\n  // max_mem: if > 0, determinization will fail and return false when the\n  // algorithm's (approximate) memory consumption crosses this threshold.\n  int max_mem;\n  // phone_determinize: if true, do a first pass determinization on both phones\n  // and words.\n  bool phone_determinize;\n  // word_determinize: if true, do a second pass determinization on words only.\n  bool word_determinize;\n  // minimize: if true, push and minimize after determinization.\n  bool minimize;\n  DeterminizeLatticePhonePrunedOptions(): delta(kDelta),\n                                          max_mem(50000000),\n                                          phone_determinize(true),\n                                          word_determinize(true),\n                                          minimize(false) {}\n  void Register (kaldi::OptionsItf *opts) {\n    opts->Register(\"delta\", &delta, \"Tolerance used in determinization\");\n    opts->Register(\"max-mem\", &max_mem, \"Maximum approximate memory usage in \"\n                   \"determinization (real usage might be many times this).\");\n    opts->Register(\"phone-determinize\", &phone_determinize, \"If true, do an \"\n                   \"initial pass of determinization on both phones and words (see\"\n                   \" also --word-determinize)\");\n    opts->Register(\"word-determinize\", &word_determinize, \"If true, do a second \"\n                   \"pass of determinization on words only (see also \"\n                   \"--phone-determinize)\");\n    opts->Register(\"minimize\", &minimize, \"If true, push and minimize after \"\n                   \"determinization.\");\n  }\n};\n\n/**\n    This function implements the normal version of DeterminizeLattice, in which the\n    output strings are represented using sequences of arcs, where all but the\n    first one has an epsilon on the input side.  It also prunes using the beam\n    in the \"prune\" parameter.  The input FST must be topologically sorted in order\n    for the algorithm to work. For efficiency it is recommended to sort ilabel as well.\n    Returns true on success, and false if it had to terminate the determinization\n    earlier than specified by the \"prune\" beam-- that is, if it terminated because\n    of the max_mem, max_loop or max_arcs constraints in the options.\n    CAUTION: you may want to use the version below which outputs to CompactLattice.\n*/\ntemplate<class Weight>\nbool DeterminizeLatticePruned(\n    const ExpandedFst<ArcTpl<Weight> > &ifst,\n    double prune,\n    MutableFst<ArcTpl<Weight> > *ofst,\n    DeterminizeLatticePrunedOptions opts = DeterminizeLatticePrunedOptions());\n\n\n/*  This is a version of DeterminizeLattice with a slightly more \"natural\" output format,\n    where the output sequences are encoded using the CompactLatticeArcTpl template\n    (i.e. the sequences of output symbols are represented directly as strings The input\n    FST must be topologically sorted in order for the algorithm to work. For efficiency\n    it is recommended to sort the ilabel for the input FST as well.\n    Returns true on normal success, and false if it had to terminate the determinization\n    earlier than specified by the \"prune\" beam-- that is, if it terminated because\n    of the max_mem, max_loop or max_arcs constraints in the options.\n    CAUTION: if Lattice is the input, you need to Invert() before calling this,\n    so words are on the input side.\n*/\ntemplate<class Weight, class IntType>\nbool DeterminizeLatticePruned(\n    const ExpandedFst<ArcTpl<Weight> >&ifst,\n    double prune,\n    MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n    DeterminizeLatticePrunedOptions opts = DeterminizeLatticePrunedOptions());\n\n// /** This function takes in lattices and inserts phones at phone boundaries. It\n//     uses the transition model to work out the transition_id to phone map. The\n//     returning value is the starting index of the phone label. Typically we pick\n//     (maximum_output_label_index + 1) as this value. The inserted phones are then\n//     mapped to (returning_value + original_phone_label) in the new lattice. The\n//     returning value will be used by DeterminizeLatticeDeletePhones() where it\n//     works out the phones according to this value.\n// */\n// template<class Weight>\n// typename ArcTpl<Weight>::Label DeterminizeLatticeInsertPhones(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<ArcTpl<Weight> > *fst);\n//\n// /** This function takes in lattices and deletes \"phones\" from them. The \"phones\"\n//     here are actually any label that is larger than first_phone_label because\n//     when we insert phones into the lattice, we map the original phone label to\n//     (first_phone_label + original_phone_label). It is supposed to be used\n//     together with DeterminizeLatticeInsertPhones()\n// */\n// template<class Weight>\n// void DeterminizeLatticeDeletePhones(\n//     typename ArcTpl<Weight>::Label first_phone_label,\n//     MutableFst<ArcTpl<Weight> > *fst);\n//\n// /** This function is a wrapper of DeterminizeLatticePhonePrunedFirstPass() and\n//     DeterminizeLatticePruned(). If --phone-determinize is set to true, it first\n//     calls DeterminizeLatticePhonePrunedFirstPass() to do the initial pass of\n//     determinization on the phone + word lattices. If --word-determinize is set\n//     true, it then does a second pass of determinization on the word lattices by\n//     calling DeterminizeLatticePruned(). If both are set to false, then it gives\n//     a warning and copying the lattices without determinization.\n//\n//     Note: the point of doing first a phone-level determinization pass and then\n//     a word-level determinization pass is that it allows us to determinize\n//     deeper lattices without \"failing early\" and returning a too-small lattice\n//     due to the max-mem constraint.  The result should be the same as word-level\n//     determinization in general, but for deeper lattices it is a bit faster,\n//     despite the fact that we now have two passes of determinization by default.\n// */\n// template<class Weight, class IntType>\n// bool DeterminizeLatticePhonePruned(\n//     const kaldi::TransitionModel &trans_model,\n//     const ExpandedFst<ArcTpl<Weight> > &ifst,\n//     double prune,\n//     MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts\n//       = DeterminizeLatticePhonePrunedOptions());\n//\n// /** \"Destructive\" version of DeterminizeLatticePhonePruned() where the input\n//     lattice might be changed.\n// */\n// template<class Weight, class IntType>\n// bool DeterminizeLatticePhonePruned(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<ArcTpl<Weight> > *ifst,\n//     double prune,\n//     MutableFst<ArcTpl<CompactLatticeWeightTpl<Weight, IntType> > > *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts\n//       = DeterminizeLatticePhonePrunedOptions());\n//\n// /** This function is a wrapper of DeterminizeLatticePhonePruned() that works for\n//     Lattice type FSTs.  It simplifies the calling process by calling\n//     TopSort() Invert() and ArcSort() for you.\n//     Unlike other determinization routines, the function\n//     requires \"ifst\" to have transition-id's on the input side and words on the\n//     output side.\n//     This function can be used as the top-level interface to all the determinization\n//     code.\n// */\n// bool DeterminizeLatticePhonePrunedWrapper(\n//     const kaldi::TransitionModel &trans_model,\n//     MutableFst<kaldi::LatticeArc> *ifst,\n//     double prune,\n//     MutableFst<kaldi::CompactLatticeArc> *ofst,\n//     DeterminizeLatticePhonePrunedOptions opts\n//       = DeterminizeLatticePhonePrunedOptions());\n\n/// @} end \"addtogroup fst_extensions\"\n\n} // end namespace fst\n\n#endif\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/kaldi-lattice.cc",
    "content": "// lat/kaldi-lattice.cc\n\n// Copyright 2009-2011     Microsoft Corporation\n//                2013     Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"lat/kaldi-lattice.h\"\n#include \"fst/script/print-impl.h\"\n\nnamespace kaldi {\n\n/// Converts lattice types if necessary, deleting its input.\ntemplate<class OrigWeightType>\nCompactLattice* ConvertToCompactLattice(fst::VectorFst<OrigWeightType> *ifst) {\n  if (!ifst) return NULL;\n  CompactLattice *ofst = new CompactLattice();\n  ConvertLattice(*ifst, ofst);\n  delete ifst;\n  return ofst;\n}\n\n// This overrides the template if there is no type conversion going on\n// (for efficiency).\ntemplate<>\nCompactLattice* ConvertToCompactLattice(CompactLattice *ifst) {\n  return ifst;\n}\n\n/// Converts lattice types if necessary, deleting its input.\ntemplate<class OrigWeightType>\nLattice* ConvertToLattice(fst::VectorFst<OrigWeightType> *ifst) {\n  if (!ifst) return NULL;\n  Lattice *ofst = new Lattice();\n  ConvertLattice(*ifst, ofst);\n  delete ifst;\n  return ofst;\n}\n\n// This overrides the template if there is no type conversion going on\n// (for efficiency).\ntemplate<>\nLattice* ConvertToLattice(Lattice *ifst) {\n  return ifst;\n}\n\n\nbool WriteCompactLattice(std::ostream &os, bool binary,\n                         const CompactLattice &t) {\n  if (binary) {\n    fst::FstWriteOptions opts;\n    // Leave all the options default.  Normally these lattices wouldn't have any\n    // osymbols/isymbols so no point directing it not to write them (who knows what\n    // we'd want to if we had them).\n    return t.Write(os, opts);\n  } else {\n    // Text-mode output.  Note: we expect that t.InputSymbols() and\n    // t.OutputSymbols() would always return NULL.  The corresponding input\n    // routine would not work if the FST actually had symbols attached.\n    // Write a newline after the key, so the first line of the FST appears\n    // on its own line.\n    os << '\\n';\n    bool acceptor = true, write_one = false;\n    fst::FstPrinter<CompactLatticeArc> printer(t, t.InputSymbols(),\n                                               t.OutputSymbols(),\n                                               NULL, acceptor, write_one, \"\\t\");\n    printer.Print(&os, \"<unknown>\");\n    if (os.fail())\n      KALDI_WARN << \"Stream failure detected.\";\n    // Write another newline as a terminating character.  The read routine will\n    // detect this [this is a Kaldi mechanism, not somethig in the original\n    // OpenFst code].\n    os << '\\n';\n    return os.good();\n  }\n}\n\n/// LatticeReader provides (static) functions for reading both Lattice\n/// and CompactLattice, in text form.\nclass LatticeReader {\n  typedef LatticeArc Arc;\n  typedef LatticeWeight Weight;\n  typedef CompactLatticeArc CArc;\n  typedef CompactLatticeWeight CWeight;\n  typedef Arc::Label Label;\n  typedef Arc::StateId StateId;\n public:\n  // everything is static in this class.\n\n  /** This function reads from the FST text format; it does not know in advance\n      whether it's a Lattice or CompactLattice in the stream so it tries to\n      read both formats until it becomes clear which is the correct one.\n  */\n  static std::pair<Lattice*, CompactLattice*> ReadText(\n      std::istream &is) {\n    typedef std::pair<Lattice*, CompactLattice*> PairT;\n    using std::string;\n    using std::vector;\n    Lattice *fst = new Lattice();\n    CompactLattice *cfst = new CompactLattice();\n    string line;\n    size_t nline = 0;\n    string separator = FLAGS_fst_field_separator + \"\\r\\n\";\n    while (std::getline(is, line)) {\n      nline++;\n      vector<string> col;\n      // on Windows we'll write in text and read in binary mode.\n      SplitStringToVector(line, separator.c_str(), true, &col);\n      if (col.size() == 0) break; // Empty line is a signal to stop, in our\n      // archive format.\n      if (col.size() > 5) {\n        KALDI_WARN << \"Reading lattice: bad line in FST: \" << line;\n        delete fst;\n        delete cfst;\n        return PairT(static_cast<Lattice*>(NULL),\n                     static_cast<CompactLattice*>(NULL));\n      }\n      StateId s;\n      if (!ConvertStringToInteger(col[0], &s)) {\n        KALDI_WARN << \"FstCompiler: bad line in FST: \" << line;\n        delete fst;\n        delete cfst;\n        return PairT(static_cast<Lattice*>(NULL),\n                     static_cast<CompactLattice*>(NULL));\n      }\n      if (fst)\n        while (s >= fst->NumStates())\n          fst->AddState();\n      if (cfst)\n        while (s >= cfst->NumStates())\n          cfst->AddState();\n      if (nline == 1) {\n        if (fst) fst->SetStart(s);\n        if (cfst) cfst->SetStart(s);\n      }\n\n      if (fst) { // we still have fst; try to read that arc.\n        bool ok = true;\n        Arc arc;\n        Weight w;\n        StateId d = s;\n        switch (col.size()) {\n          case 1 :\n            fst->SetFinal(s, Weight::One());\n            break;\n          case 2:\n            if (!StrToWeight(col[1], true, &w)) ok = false;\n            else fst->SetFinal(s, w);\n            break;\n          case 3: // 3 columns not ok for Lattice format; it's not an acceptor.\n            ok = false;\n            break;\n          case 4:\n            ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n                ConvertStringToInteger(col[2], &arc.ilabel) &&\n                ConvertStringToInteger(col[3], &arc.olabel);\n            if (ok) {\n              d = arc.nextstate;\n              arc.weight = Weight::One();\n              fst->AddArc(s, arc);\n            }\n            break;\n          case 5:\n            ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n                ConvertStringToInteger(col[2], &arc.ilabel) &&\n                ConvertStringToInteger(col[3], &arc.olabel) &&\n                StrToWeight(col[4], false, &arc.weight);\n            if (ok) {\n              d = arc.nextstate;\n              fst->AddArc(s, arc);\n            }\n            break;\n          default:\n            ok = false;\n        }\n        while (d >= fst->NumStates())\n          fst->AddState();\n        if (!ok) {\n          delete fst;\n          fst = NULL;\n        }\n      }\n      if (cfst) {\n        bool ok = true;\n        CArc arc;\n        CWeight w;\n        StateId d = s;\n        switch (col.size()) {\n          case 1 :\n            cfst->SetFinal(s, CWeight::One());\n            break;\n          case 2:\n            if (!StrToCWeight(col[1], true, &w)) ok = false;\n            else cfst->SetFinal(s, w);\n            break;\n          case 3: // compact-lattice is acceptor format: state, next-state, label.\n            ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n                ConvertStringToInteger(col[2], &arc.ilabel);\n            if (ok) {\n              d = arc.nextstate;\n              arc.olabel = arc.ilabel;\n              arc.weight = CWeight::One();\n              cfst->AddArc(s, arc);\n            }\n            break;\n          case 4:\n            ok = ConvertStringToInteger(col[1], &arc.nextstate) &&\n                ConvertStringToInteger(col[2], &arc.ilabel) &&\n                StrToCWeight(col[3], false, &arc.weight);\n            if (ok) {\n              d = arc.nextstate;\n              arc.olabel = arc.ilabel;\n              cfst->AddArc(s, arc);\n            }\n            break;\n          case 5: default:\n            ok = false;\n        }\n        while (d >= cfst->NumStates())\n          cfst->AddState();\n        if (!ok) {\n          delete cfst;\n          cfst = NULL;\n        }\n      }\n      if (!fst && !cfst) {\n        KALDI_WARN << \"Bad line in lattice text format: \" << line;\n        // read until we get an empty line, so at least we\n        // have a chance to read the next one (although this might\n        // be a bit futile since the calling code will get unhappy\n        // about failing to read this one.\n        while (std::getline(is, line)) {\n          SplitStringToVector(line, separator.c_str(), true, &col);\n          if (col.empty()) break;\n        }\n        return PairT(static_cast<Lattice*>(NULL),\n                     static_cast<CompactLattice*>(NULL));\n      }\n    }\n    return PairT(fst, cfst);\n  }\n\n  static bool StrToWeight(const std::string &s, bool allow_zero, Weight *w) {\n    std::istringstream strm(s);\n    strm >> *w;\n    if (!strm || (!allow_zero && *w == Weight::Zero())) {\n      return false;\n    }\n    return true;\n  }\n\n  static  bool StrToCWeight(const std::string &s, bool allow_zero, CWeight *w) {\n    std::istringstream strm(s);\n    strm >> *w;\n    if (!strm || (!allow_zero && *w == CWeight::Zero())) {\n      return false;\n    }\n    return true;\n  }\n};\n\n\nCompactLattice *ReadCompactLatticeText(std::istream &is) {\n  std::pair<Lattice*, CompactLattice*> lat_pair = LatticeReader::ReadText(is);\n  if (lat_pair.second != NULL) {\n    delete lat_pair.first;\n    return lat_pair.second;\n  } else if (lat_pair.first != NULL) {\n    // note: ConvertToCompactLattice frees its input.\n    return ConvertToCompactLattice(lat_pair.first);\n  } else {\n    return NULL;\n  }\n}\n\n\nLattice *ReadLatticeText(std::istream &is) {\n  std::pair<Lattice*, CompactLattice*> lat_pair = LatticeReader::ReadText(is);\n  if (lat_pair.first != NULL) {\n    delete lat_pair.second;\n    return lat_pair.first;\n  } else if (lat_pair.second != NULL) {\n    // note: ConvertToLattice frees its input.\n    return ConvertToLattice(lat_pair.second);\n  } else {\n    return NULL;\n  }\n}\n\nbool ReadCompactLattice(std::istream &is, bool binary,\n                        CompactLattice **clat) {\n  KALDI_ASSERT(*clat == NULL);\n  if (binary) {\n    fst::FstHeader hdr;\n    if (!hdr.Read(is, \"<unknown>\")) {\n      KALDI_WARN << \"Reading compact lattice: error reading FST header.\";\n      return false;\n    }\n    if (hdr.FstType() != \"vector\") {\n      KALDI_WARN << \"Reading compact lattice: unsupported FST type: \"\n                 << hdr.FstType();\n      return false;\n    }\n    fst::FstReadOptions ropts(\"<unspecified>\",\n                              &hdr);\n\n    typedef fst::CompactLatticeWeightTpl<fst::LatticeWeightTpl<float>, int32> T1;\n    typedef fst::CompactLatticeWeightTpl<fst::LatticeWeightTpl<double>, int32> T2;\n    typedef fst::LatticeWeightTpl<float> T3;\n    typedef fst::LatticeWeightTpl<double> T4;\n    typedef fst::VectorFst<fst::ArcTpl<T1> > F1;\n    typedef fst::VectorFst<fst::ArcTpl<T2> > F2;\n    typedef fst::VectorFst<fst::ArcTpl<T3> > F3;\n    typedef fst::VectorFst<fst::ArcTpl<T4> > F4;\n\n    CompactLattice *ans = NULL;\n    if (hdr.ArcType() == T1::Type()) {\n      ans = ConvertToCompactLattice(F1::Read(is, ropts));\n    } else if (hdr.ArcType() == T2::Type()) {\n      ans = ConvertToCompactLattice(F2::Read(is, ropts));\n    } else if (hdr.ArcType() == T3::Type()) {\n      ans = ConvertToCompactLattice(F3::Read(is, ropts));\n    } else if (hdr.ArcType() == T4::Type()) {\n      ans = ConvertToCompactLattice(F4::Read(is, ropts));\n    } else {\n      KALDI_WARN << \"FST with arc type \" << hdr.ArcType()\n                 << \" cannot be converted to CompactLattice.\\n\";\n      return false;\n    }\n    if (ans == NULL) {\n      KALDI_WARN << \"Error reading compact lattice (after reading header).\";\n      return false;\n    }\n    *clat = ans;\n    return true;\n  } else {\n    // The next line would normally consume the \\r on Windows, plus any\n    // extra spaces that might have got in there somehow.\n    while (std::isspace(is.peek()) && is.peek() != '\\n') is.get();\n    if (is.peek() == '\\n') is.get(); // consume the newline.\n    else { // saw spaces but no newline.. this is not expected.\n      KALDI_WARN << \"Reading compact lattice: unexpected sequence of spaces \"\n                 << \" at file position \" << is.tellg();\n      return false;\n    }\n    *clat = ReadCompactLatticeText(is); // that routine will warn on error.\n    return (*clat != NULL);\n  }\n}\n\n\nbool CompactLatticeHolder::Read(std::istream &is) {\n  Clear(); // in case anything currently stored.\n  int c = is.peek();\n  if (c == -1) {\n    KALDI_WARN << \"End of stream detected reading CompactLattice.\";\n    return false;\n  } else if (isspace(c)) { // The text form of the lattice begins\n    // with space (normally, '\\n'), so this means it's text (the binary form\n    // cannot begin with space because it starts with the FST Type() which is not\n    // space).\n    return ReadCompactLattice(is, false, &t_);\n  } else if (c != 214) { // 214 is first char of FST magic number,\n    // on little-endian machines which is all we support (\\326 octal)\n    KALDI_WARN << \"Reading compact lattice: does not appear to be an FST \"\n               << \" [non-space but no magic number detected], file pos is \"\n               << is.tellg();\n    return false;\n  } else {\n    return ReadCompactLattice(is, true, &t_);\n  }\n}\n\nbool WriteLattice(std::ostream &os, bool binary, const Lattice &t) {\n  if (binary) {\n    fst::FstWriteOptions opts;\n    // Leave all the options default.  Normally these lattices wouldn't have any\n    // osymbols/isymbols so no point directing it not to write them (who knows what\n    // we'd want to do if we had them).\n    return t.Write(os, opts);\n  } else {\n    // Text-mode output.  Note: we expect that t.InputSymbols() and\n    // t.OutputSymbols() would always return NULL.  The corresponding input\n    // routine would not work if the FST actually had symbols attached.\n    // Write a newline after the key, so the first line of the FST appears\n    // on its own line.\n    os << '\\n';\n    bool acceptor = false, write_one = false;\n    fst::FstPrinter<LatticeArc> printer(t, t.InputSymbols(),\n                                        t.OutputSymbols(),\n                                        NULL, acceptor, write_one, \"\\t\");\n    printer.Print(&os, \"<unknown>\");\n    if (os.fail())\n      KALDI_WARN << \"Stream failure detected.\";\n    // Write another newline as a terminating character.  The read routine will\n    // detect this [this is a Kaldi mechanism, not something in the original\n    // OpenFst code].\n    os << '\\n';\n    return os.good();\n  }\n}\n\nbool ReadLattice(std::istream &is, bool binary,\n                 Lattice **lat) {\n  KALDI_ASSERT(*lat == NULL);\n  if (binary) {\n    fst::FstHeader hdr;\n    if (!hdr.Read(is, \"<unknown>\")) {\n      KALDI_WARN << \"Reading lattice: error reading FST header.\";\n      return false;\n    }\n    if (hdr.FstType() != \"vector\") {\n      KALDI_WARN << \"Reading lattice: unsupported FST type: \"\n                 << hdr.FstType();\n      return false;\n    }\n    fst::FstReadOptions ropts(\"<unspecified>\",\n                              &hdr);\n\n    typedef fst::CompactLatticeWeightTpl<fst::LatticeWeightTpl<float>, int32> T1;\n    typedef fst::CompactLatticeWeightTpl<fst::LatticeWeightTpl<double>, int32> T2;\n    typedef fst::LatticeWeightTpl<float> T3;\n    typedef fst::LatticeWeightTpl<double> T4;\n    typedef fst::VectorFst<fst::ArcTpl<T1> > F1;\n    typedef fst::VectorFst<fst::ArcTpl<T2> > F2;\n    typedef fst::VectorFst<fst::ArcTpl<T3> > F3;\n    typedef fst::VectorFst<fst::ArcTpl<T4> > F4;\n\n    Lattice *ans = NULL;\n    if (hdr.ArcType() == T1::Type()) {\n      ans = ConvertToLattice(F1::Read(is, ropts));\n    } else if (hdr.ArcType() == T2::Type()) {\n      ans = ConvertToLattice(F2::Read(is, ropts));\n    } else if (hdr.ArcType() == T3::Type()) {\n      ans = ConvertToLattice(F3::Read(is, ropts));\n    } else if (hdr.ArcType() == T4::Type()) {\n      ans = ConvertToLattice(F4::Read(is, ropts));\n    } else {\n      KALDI_WARN << \"FST with arc type \" << hdr.ArcType()\n                 << \" cannot be converted to Lattice.\\n\";\n      return false;\n    }\n    if (ans == NULL) {\n      KALDI_WARN << \"Error reading lattice (after reading header).\";\n      return false;\n    }\n    *lat = ans;\n    return true;\n  } else {\n    // The next line would normally consume the \\r on Windows, plus any\n    // extra spaces that might have got in there somehow.\n    while (std::isspace(is.peek()) && is.peek() != '\\n') is.get();\n    if (is.peek() == '\\n') is.get(); // consume the newline.\n    else { // saw spaces but no newline.. this is not expected.\n      KALDI_WARN << \"Reading compact lattice: unexpected sequence of spaces \"\n                 << \" at file position \" << is.tellg();\n      return false;\n    }\n    *lat = ReadLatticeText(is); // that routine will warn on error.\n    return (*lat != NULL);\n  }\n}\n\n\n/* Since we don't write the binary headers for this type of holder,\n   we use a different method to work out whether we're in binary mode.\n */\nbool LatticeHolder::Read(std::istream &is) {\n  Clear(); // in case anything currently stored.\n  int c = is.peek();\n  if (c == -1) {\n    KALDI_WARN << \"End of stream detected reading Lattice.\";\n    return false;\n  } else if (isspace(c)) { // The text form of the lattice begins\n    // with space (normally, '\\n'), so this means it's text (the binary form\n    // cannot begin with space because it starts with the FST Type() which is not\n    // space).\n    return ReadLattice(is, false, &t_);\n  } else if (c != 214) { // 214 is first char of FST magic number,\n    // on little-endian machines which is all we support (\\326 octal)\n    KALDI_WARN << \"Reading compact lattice: does not appear to be an FST \"\n               << \" [non-space but no magic number detected], file pos is \"\n               << is.tellg();\n    return false;\n  } else {\n    return ReadLattice(is, true, &t_);\n  }\n}\n\n\n\n} // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/kaldi-lattice.h",
    "content": "// lat/kaldi-lattice.h\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_LAT_KALDI_LATTICE_H_\n#define KALDI_LAT_KALDI_LATTICE_H_\n\n#include \"fstext/fstext-lib.h\"\n#include \"base/kaldi-common.h\"\n// #include \"util/common-utils.h\"\n\n\nnamespace kaldi {\n// will import some things above...\n\ntypedef fst::LatticeWeightTpl<BaseFloat> LatticeWeight;\n\n// careful: kaldi::int32 is not always the same C type as fst::int32\ntypedef fst::CompactLatticeWeightTpl<LatticeWeight, int32> CompactLatticeWeight;\n\ntypedef fst::CompactLatticeWeightCommonDivisorTpl<LatticeWeight, int32>\n  CompactLatticeWeightCommonDivisor;\n\ntypedef fst::ArcTpl<LatticeWeight> LatticeArc;\n\ntypedef fst::ArcTpl<CompactLatticeWeight> CompactLatticeArc;\n\ntypedef fst::VectorFst<LatticeArc> Lattice;\n\ntypedef fst::VectorFst<CompactLatticeArc> CompactLattice;\n\n// The following functions for writing and reading lattices in binary or text\n// form are provided here in case you need to include lattices in larger,\n// Kaldi-type objects with their own Read and Write functions.  Caution: these\n// functions return false on stream failure rather than throwing an exception as\n// most similar Kaldi functions would do.\n\nbool WriteCompactLattice(std::ostream &os, bool binary,\n                         const CompactLattice &clat);\nbool WriteLattice(std::ostream &os, bool binary,\n                  const Lattice &lat);\n\n// the following function requires that *clat be\n// NULL when called.\nbool ReadCompactLattice(std::istream &is, bool binary,\n                        CompactLattice **clat);\n// the following function requires that *lat be\n// NULL when called.\nbool ReadLattice(std::istream &is, bool binary,\n                 Lattice **lat);\n\n\nclass CompactLatticeHolder {\n public:\n  typedef CompactLattice T;\n\n  CompactLatticeHolder() { t_ = NULL; }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    // Note: we don't include the binary-mode header when writing\n    // this object to disk; this ensures that if we write to single\n    // files, the result can be read by OpenFst.\n    return WriteCompactLattice(os, binary, t);\n  }\n\n  bool Read(std::istream &is);\n\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {\n    KALDI_ASSERT(t_ != NULL && \"Called Value() on empty CompactLatticeHolder\");\n    return *t_;\n  }\n\n  void Clear() { delete t_; t_ = NULL; }\n\n  void Swap(CompactLatticeHolder *other) {\n    std::swap(t_, other->t_);\n  }\n\n  bool ExtractRange(const CompactLatticeHolder &other, const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~CompactLatticeHolder() { Clear(); }\n private:\n  T *t_;\n};\n\nclass LatticeHolder {\n public:\n  typedef Lattice T;\n\n  LatticeHolder() { t_ = NULL; }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    // Note: we don't include the binary-mode header when writing\n    // this object to disk; this ensures that if we write to single\n    // files, the result can be read by OpenFst.\n    return WriteLattice(os, binary, t);\n  }\n\n  bool Read(std::istream &is);\n\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {\n    KALDI_ASSERT(t_ != NULL && \"Called Value() on empty LatticeHolder\");\n    return *t_;\n  }\n\n  void Clear() {  delete t_; t_ = NULL; }\n\n  void Swap(LatticeHolder *other) {\n    std::swap(t_, other->t_);\n  }\n\n  bool ExtractRange(const LatticeHolder &other, const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~LatticeHolder() { Clear(); }\n private:\n  T *t_;\n};\n\n// typedef TableWriter<LatticeHolder> LatticeWriter;\n// typedef SequentialTableReader<LatticeHolder> SequentialLatticeReader;\n// typedef RandomAccessTableReader<LatticeHolder> RandomAccessLatticeReader;\n//\n// typedef TableWriter<CompactLatticeHolder> CompactLatticeWriter;\n// typedef SequentialTableReader<CompactLatticeHolder> SequentialCompactLatticeReader;\n// typedef RandomAccessTableReader<CompactLatticeHolder> RandomAccessCompactLatticeReader;\n\n\n} // namespace kaldi\n\n#endif  // KALDI_LAT_KALDI_LATTICE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/lattice-functions.cc",
    "content": "// lat/lattice-functions.cc\n\n// Copyright 2009-2011  Saarland University (Author: Arnab Ghoshal)\n//           2012-2013  Johns Hopkins University (Author: Daniel Povey);  Chao Weng;\n//                      Bagher BabaAli\n//                2013  Cisco Systems (author: Neha Agrawal) [code modified\n//                      from original code in ../gmmbin/gmm-rescore-lattice.cc]\n//                2014  Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"lat/lattice-functions.h\"\n// #include \"hmm/transition-model.h\"\n// #include \"util/stl-utils.h\"\n#include \"base/kaldi-math.h\"\n// #include \"hmm/hmm-utils.h\"\n\nnamespace kaldi {\nusing std::map;\nusing std::vector;\n\n// void GetPerFrameAcousticCosts(const Lattice &nbest,\n//                               Vector<BaseFloat> *per_frame_loglikes) {\n//   using namespace fst;\n//   typedef Lattice::Arc::Weight Weight;\n//   vector<BaseFloat> loglikes;\n//\n//   int32 cur_state = nbest.Start();\n//   int32 prev_frame = -1;\n//   BaseFloat eps_acwt = 0.0;\n//   while(1) {\n//     Weight w = nbest.Final(cur_state);\n//     if (w != Weight::Zero()) {\n//       KALDI_ASSERT(nbest.NumArcs(cur_state) == 0);\n//       if (per_frame_loglikes != NULL)  {\n//         SubVector<BaseFloat> subvec(&(loglikes[0]), loglikes.size());\n//         Vector<BaseFloat> vec(subvec);\n//         *per_frame_loglikes = vec;\n//       }\n//       break;\n//     } else {\n//       KALDI_ASSERT(nbest.NumArcs(cur_state) == 1);\n//       fst::ArcIterator<Lattice> iter(nbest, cur_state);\n//       const Lattice::Arc &arc = iter.Value();\n//       BaseFloat acwt = arc.weight.Value2();\n//       if (arc.ilabel != 0) {\n//         if (eps_acwt > 0) {\n//           acwt += eps_acwt;\n//           eps_acwt = 0.0;\n//         }\n//         loglikes.push_back(acwt);\n//         prev_frame++;\n//       } else if (acwt == acwt){\n//         if (prev_frame > -1) {\n//           loglikes[prev_frame] += acwt;\n//         } else {\n//           eps_acwt += acwt;\n//         }\n//       }\n//       cur_state = arc.nextstate;\n//     }\n//   }\n// }\n//\n// int32 LatticeStateTimes(const Lattice &lat, vector<int32> *times) {\n//   if (!lat.Properties(fst::kTopSorted, true))\n//     KALDI_ERR << \"Input lattice must be topologically sorted.\";\n//   KALDI_ASSERT(lat.Start() == 0);\n//   int32 num_states = lat.NumStates();\n//   times->clear();\n//   times->resize(num_states, -1);\n//   (*times)[0] = 0;\n//   for (int32 state = 0; state < num_states; state++) {\n//     int32 cur_time = (*times)[state];\n//     for (fst::ArcIterator<Lattice> aiter(lat, state); !aiter.Done();\n//         aiter.Next()) {\n//       const LatticeArc &arc = aiter.Value();\n//\n//       if (arc.ilabel != 0) {  // Non-epsilon input label on arc\n//         // next time instance\n//         if ((*times)[arc.nextstate] == -1) {\n//           (*times)[arc.nextstate] = cur_time + 1;\n//         } else {\n//           KALDI_ASSERT((*times)[arc.nextstate] == cur_time + 1);\n//         }\n//       } else {  // epsilon input label on arc\n//         // Same time instance\n//         if ((*times)[arc.nextstate] == -1)\n//           (*times)[arc.nextstate] = cur_time;\n//         else\n//           KALDI_ASSERT((*times)[arc.nextstate] == cur_time);\n//       }\n//     }\n//   }\n//   return (*std::max_element(times->begin(), times->end()));\n// }\n//\n// int32 CompactLatticeStateTimes(const CompactLattice &lat,\n//                                vector<int32> *times) {\n//   if (!lat.Properties(fst::kTopSorted, true))\n//     KALDI_ERR << \"Input lattice must be topologically sorted.\";\n//   KALDI_ASSERT(lat.Start() == 0);\n//   int32 num_states = lat.NumStates();\n//   times->clear();\n//   times->resize(num_states, -1);\n//   (*times)[0] = 0;\n//   int32 utt_len = -1;\n//   for (int32 state = 0; state < num_states; state++) {\n//     int32 cur_time = (*times)[state];\n//     for (fst::ArcIterator<CompactLattice> aiter(lat, state); !aiter.Done();\n//         aiter.Next()) {\n//       const CompactLatticeArc &arc = aiter.Value();\n//       int32 arc_len = static_cast<int32>(arc.weight.String().size());\n//       if ((*times)[arc.nextstate] == -1)\n//         (*times)[arc.nextstate] = cur_time + arc_len;\n//       else\n//         KALDI_ASSERT((*times)[arc.nextstate] == cur_time + arc_len);\n//     }\n//     if (lat.Final(state) != CompactLatticeWeight::Zero()) {\n//       int32 this_utt_len = (*times)[state] + lat.Final(state).String().size();\n//       if (utt_len == -1) utt_len = this_utt_len;\n//       else {\n//         if (this_utt_len != utt_len) {\n//           KALDI_WARN << \"Utterance does not \"\n//               \"seem to have a consistent length.\";\n//           utt_len = std::max(utt_len, this_utt_len);\n//         }\n//       }\n//     }\n//   }\n//   if (utt_len == -1) {\n//     KALDI_WARN << \"Utterance does not have a final-state.\";\n//     return 0;\n//   }\n//   return utt_len;\n// }\n//\n// bool ComputeCompactLatticeAlphas(const CompactLattice &clat,\n//                                  vector<double> *alpha) {\n//   using namespace fst;\n//\n//   // typedef the arc, weight types\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   //Make sure the lattice is topologically sorted.\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     KALDI_WARN << \"Input lattice must be topologically sorted.\";\n//     return false;\n//   }\n//   if (clat.Start() != 0) {\n//     KALDI_WARN << \"Input lattice must start from state 0.\";\n//     return false;\n//   }\n//\n//   int32 num_states = clat.NumStates();\n//   (*alpha).resize(0);\n//   (*alpha).resize(num_states, kLogZeroDouble);\n//\n//   // Now propagate alphas forward. Note that we don't acount the weight of the\n//   // final state to alpha[final_state] -- we acount it to beta[final_state];\n//   (*alpha)[0] = 0.0;\n//   for (StateId s = 0; s < num_states; s++) {\n//     double this_alpha = (*alpha)[s];\n//     for (ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -(arc.weight.Weight().Value1() +\n//                           arc.weight.Weight().Value2());\n//       (*alpha)[arc.nextstate] = LogAdd((*alpha)[arc.nextstate],\n//                                        this_alpha + arc_like);\n//     }\n//   }\n//\n//   return true;\n// }\n//\n// bool ComputeCompactLatticeBetas(const CompactLattice &clat,\n//                                 vector<double> *beta) {\n//   using namespace fst;\n//\n//   // typedef the arc, weight types\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   // Make sure the lattice is topologically sorted.\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     KALDI_WARN << \"Input lattice must be topologically sorted.\";\n//     return false;\n//   }\n//   if (clat.Start() != 0) {\n//     KALDI_WARN << \"Input lattice must start from state 0.\";\n//     return false;\n//   }\n//\n//   int32 num_states = clat.NumStates();\n//   (*beta).resize(0);\n//   (*beta).resize(num_states, kLogZeroDouble);\n//\n//   // Now propagate betas backward. Note that beta[final_state] contains the\n//   // weight of the final state in the lattice -- compare that with alpha.\n//   for (StateId s = num_states-1; s >= 0; s--) {\n//     Weight f = clat.Final(s);\n//     double this_beta = -(f.Weight().Value1()+f.Weight().Value2());\n//     for (ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -(arc.weight.Weight().Value1() +\n//                           arc.weight.Weight().Value2());\n//       double arc_beta = (*beta)[arc.nextstate] + arc_like;\n//       this_beta = LogAdd(this_beta, arc_beta);\n//     }\n//     (*beta)[s] = this_beta;\n//   }\n//\n//   return true;\n// }\n\ntemplate<class LatType>  // could be Lattice or CompactLattice\nbool PruneLattice(BaseFloat beam, LatType *lat) {\n  typedef typename LatType::Arc Arc;\n  typedef typename Arc::Weight Weight;\n  typedef typename Arc::StateId StateId;\n\n  KALDI_ASSERT(beam > 0.0);\n  if (!lat->Properties(fst::kTopSorted, true)) {\n    if (fst::TopSort(lat) == false) {\n      KALDI_WARN << \"Cycles detected in lattice\";\n      return false;\n    }\n  }\n  // We assume states before \"start\" are not reachable, since\n  // the lattice is topologically sorted.\n  int32 start = lat->Start();\n  int32 num_states = lat->NumStates();\n  if (num_states == 0) return false;\n  std::vector<double> forward_cost(num_states,\n                                   std::numeric_limits<double>::infinity());  // viterbi forward.\n  forward_cost[start] = 0.0; // lattice can't have cycles so couldn't be\n  // less than this.\n  double best_final_cost = std::numeric_limits<double>::infinity();\n  // Update the forward probs.\n  // Thanks to Jing Zheng for finding a bug here.\n  for (int32 state = 0; state < num_states; state++) {\n    double this_forward_cost = forward_cost[state];\n    for (fst::ArcIterator<LatType> aiter(*lat, state);\n         !aiter.Done();\n         aiter.Next()) {\n      const Arc &arc(aiter.Value());\n      StateId nextstate = arc.nextstate;\n      KALDI_ASSERT(nextstate > state && nextstate < num_states);\n      double next_forward_cost = this_forward_cost +\n          ConvertToCost(arc.weight);\n      if (forward_cost[nextstate] > next_forward_cost)\n        forward_cost[nextstate] = next_forward_cost;\n    }\n    Weight final_weight = lat->Final(state);\n    double this_final_cost = this_forward_cost +\n        ConvertToCost(final_weight);\n    if (this_final_cost < best_final_cost)\n      best_final_cost = this_final_cost;\n  }\n  int32 bad_state = lat->AddState(); // this state is not final.\n  double cutoff = best_final_cost + beam;\n\n  // Go backwards updating the backward probs (which share memory with the\n  // forward probs), and pruning arcs and deleting final-probs.  We prune arcs\n  // by making them point to the non-final state \"bad_state\".  We'll then use\n  // Trim() to remove unnecessary arcs and states.  [this is just easier than\n  // doing it ourselves.]\n  std::vector<double> &backward_cost(forward_cost);\n  for (int32 state = num_states - 1; state >= 0; state--) {\n    double this_forward_cost = forward_cost[state];\n    double this_backward_cost = ConvertToCost(lat->Final(state));\n    if (this_backward_cost + this_forward_cost > cutoff\n        && this_backward_cost != std::numeric_limits<double>::infinity())\n      lat->SetFinal(state, Weight::Zero());\n    for (fst::MutableArcIterator<LatType> aiter(lat, state);\n         !aiter.Done();\n         aiter.Next()) {\n      Arc arc(aiter.Value());\n      StateId nextstate = arc.nextstate;\n      KALDI_ASSERT(nextstate > state && nextstate < num_states);\n      double arc_cost = ConvertToCost(arc.weight),\n          arc_backward_cost = arc_cost + backward_cost[nextstate],\n          this_fb_cost = this_forward_cost + arc_backward_cost;\n      if (arc_backward_cost < this_backward_cost)\n        this_backward_cost = arc_backward_cost;\n      if (this_fb_cost > cutoff) { // Prune the arc.\n        arc.nextstate = bad_state;\n        aiter.SetValue(arc);\n      }\n    }\n    backward_cost[state] = this_backward_cost;\n  }\n  fst::Connect(lat);\n  return (lat->NumStates() > 0);\n}\n\n// instantiate the template for lattice and CompactLattice.\ntemplate bool PruneLattice(BaseFloat beam, Lattice *lat);\ntemplate bool PruneLattice(BaseFloat beam, CompactLattice *lat);\n\n\n// BaseFloat LatticeForwardBackward(const Lattice &lat, Posterior *post,\n//                                  double *acoustic_like_sum) {\n//   // Note, Posterior is defined as follows:  Indexed [frame], then a list\n//   // of (transition-id, posterior-probability) pairs.\n//   // typedef std::vector<std::vector<std::pair<int32, BaseFloat> > > Posterior;\n//   using namespace fst;\n//   typedef Lattice::Arc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   if (acoustic_like_sum) *acoustic_like_sum = 0.0;\n//\n//   // Make sure the lattice is topologically sorted.\n//   if (lat.Properties(fst::kTopSorted, true) == 0)\n//     KALDI_ERR << \"Input lattice must be topologically sorted.\";\n//   KALDI_ASSERT(lat.Start() == 0);\n//\n//   int32 num_states = lat.NumStates();\n//   vector<int32> state_times;\n//   int32 max_time = LatticeStateTimes(lat, &state_times);\n//   std::vector<double> alpha(num_states, kLogZeroDouble);\n//   std::vector<double> &beta(alpha); // we re-use the same memory for\n//   // this, but it's semantically distinct so we name it differently.\n//   double tot_forward_prob = kLogZeroDouble;\n//\n//   post->clear();\n//   post->resize(max_time);\n//\n//   alpha[0] = 0.0;\n//   // Propagate alphas forward.\n//   for (StateId s = 0; s < num_states; s++) {\n//     double this_alpha = alpha[s];\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight);\n//       alpha[arc.nextstate] = LogAdd(alpha[arc.nextstate], this_alpha + arc_like);\n//     }\n//     Weight f = lat.Final(s);\n//     if (f != Weight::Zero()) {\n//       double final_like = this_alpha - (f.Value1() + f.Value2());\n//       tot_forward_prob = LogAdd(tot_forward_prob, final_like);\n//       KALDI_ASSERT(state_times[s] == max_time &&\n//                    \"Lattice is inconsistent (final-prob not at max_time)\");\n//     }\n//   }\n//   for (StateId s = num_states-1; s >= 0; s--) {\n//     Weight f = lat.Final(s);\n//     double this_beta = -(f.Value1() + f.Value2());\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight),\n//           arc_beta = beta[arc.nextstate] + arc_like;\n//       this_beta = LogAdd(this_beta, arc_beta);\n//       int32 transition_id = arc.ilabel;\n//\n//       // The following \"if\" is an optimization to avoid un-needed exp().\n//       if (transition_id != 0 || acoustic_like_sum != NULL) {\n//         double posterior = Exp(alpha[s] + arc_beta - tot_forward_prob);\n//\n//         if (transition_id != 0) // Arc has a transition-id on it [not epsilon]\n//           (*post)[state_times[s]].push_back(std::make_pair(transition_id,\n//                                                            static_cast<kaldi::BaseFloat>(posterior)));\n//         if (acoustic_like_sum != NULL)\n//           *acoustic_like_sum -= posterior * arc.weight.Value2();\n//       }\n//     }\n//     if (acoustic_like_sum != NULL && f != Weight::Zero()) {\n//       double final_logprob = - ConvertToCost(f),\n//           posterior = Exp(alpha[s] + final_logprob - tot_forward_prob);\n//       *acoustic_like_sum -= posterior * f.Value2();\n//     }\n//     beta[s] = this_beta;\n//   }\n//   double tot_backward_prob = beta[0];\n//   if (!ApproxEqual(tot_forward_prob, tot_backward_prob, 1e-8)) {\n//     KALDI_WARN << \"Total forward probability over lattice = \" << tot_forward_prob\n//               << \", while total backward probability = \" << tot_backward_prob;\n//   }\n//   // Now combine any posteriors with the same transition-id.\n//   for (int32 t = 0; t < max_time; t++)\n//     MergePairVectorSumming(&((*post)[t]));\n//   return tot_backward_prob;\n// }\n//\n//\n// void LatticeActivePhones(const Lattice &lat, const TransitionModel &trans,\n//                          const vector<int32> &silence_phones,\n//                          vector< std::set<int32> > *active_phones) {\n//   KALDI_ASSERT(IsSortedAndUniq(silence_phones));\n//   vector<int32> state_times;\n//   int32 num_states = lat.NumStates();\n//   int32 max_time = LatticeStateTimes(lat, &state_times);\n//   active_phones->clear();\n//   active_phones->resize(max_time);\n//   for (int32 state = 0; state < num_states; state++) {\n//     int32 cur_time = state_times[state];\n//     for (fst::ArcIterator<Lattice> aiter(lat, state); !aiter.Done();\n//         aiter.Next()) {\n//       const LatticeArc &arc = aiter.Value();\n//       if (arc.ilabel != 0) {  // Non-epsilon arc\n//         int32 phone = trans.TransitionIdToPhone(arc.ilabel);\n//         if (!std::binary_search(silence_phones.begin(),\n//                                 silence_phones.end(), phone))\n//           (*active_phones)[cur_time].insert(phone);\n//       }\n//     }  // end looping over arcs\n//   }  // end looping over states\n// }\n//\n// void ConvertLatticeToPhones(const TransitionModel &trans,\n//                             Lattice *lat) {\n//   typedef LatticeArc Arc;\n//   int32 num_states = lat->NumStates();\n//   for (int32 state = 0; state < num_states; state++) {\n//     for (fst::MutableArcIterator<Lattice> aiter(lat, state); !aiter.Done();\n//         aiter.Next()) {\n//       Arc arc(aiter.Value());\n//       arc.olabel = 0; // remove any word.\n//       if ((arc.ilabel != 0) // has a transition-id on input..\n//           && (trans.TransitionIdToHmmState(arc.ilabel) == 0)\n//           && (!trans.IsSelfLoop(arc.ilabel))) {\n//          // && trans.IsFinal(arc.ilabel)) // there is one of these per phone...\n//         arc.olabel = trans.TransitionIdToPhone(arc.ilabel);\n//       }\n//       aiter.SetValue(arc);\n//     }  // end looping over arcs\n//   }  // end looping over states\n// }\n//\n//\n// static inline double LogAddOrMax(bool viterbi, double a, double b) {\n//   if (viterbi)\n//     return std::max(a, b);\n//   else\n//     return LogAdd(a, b);\n// }\n//\n// template<typename LatticeType>\n// double ComputeLatticeAlphasAndBetas(const LatticeType &lat,\n//                                     bool viterbi,\n//                                     vector<double> *alpha,\n//                                     vector<double> *beta) {\n//   typedef typename LatticeType::Arc Arc;\n//   typedef typename Arc::Weight Weight;\n//   typedef typename Arc::StateId StateId;\n//\n//   StateId num_states = lat.NumStates();\n//   KALDI_ASSERT(lat.Properties(fst::kTopSorted, true) == fst::kTopSorted);\n//   KALDI_ASSERT(lat.Start() == 0);\n//   alpha->clear();\n//   beta->clear();\n//   alpha->resize(num_states, kLogZeroDouble);\n//   beta->resize(num_states, kLogZeroDouble);\n//\n//   double tot_forward_prob = kLogZeroDouble;\n//   (*alpha)[0] = 0.0;\n//   // Propagate alphas forward.\n//   for (StateId s = 0; s < num_states; s++) {\n//     double this_alpha = (*alpha)[s];\n//     for (fst::ArcIterator<LatticeType> aiter(lat, s); !aiter.Done();\n//          aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight);\n//       (*alpha)[arc.nextstate] = LogAddOrMax(viterbi, (*alpha)[arc.nextstate],\n//                                                 this_alpha + arc_like);\n//     }\n//     Weight f = lat.Final(s);\n//     if (f != Weight::Zero()) {\n//       double final_like = this_alpha - ConvertToCost(f);\n//       tot_forward_prob = LogAddOrMax(viterbi, tot_forward_prob, final_like);\n//     }\n//   }\n//   for (StateId s = num_states-1; s >= 0; s--) { // it's guaranteed signed.\n//     double this_beta = -ConvertToCost(lat.Final(s));\n//     for (fst::ArcIterator<LatticeType> aiter(lat, s); !aiter.Done();\n//          aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight),\n//           arc_beta = (*beta)[arc.nextstate] + arc_like;\n//       this_beta = LogAddOrMax(viterbi, this_beta, arc_beta);\n//     }\n//     (*beta)[s] = this_beta;\n//   }\n//   double tot_backward_prob = (*beta)[lat.Start()];\n//   if (!ApproxEqual(tot_forward_prob, tot_backward_prob, 1e-8)) {\n//     KALDI_WARN << \"Total forward probability over lattice = \" << tot_forward_prob\n//                << \", while total backward probability = \" << tot_backward_prob;\n//   }\n//   // Split the difference when returning... they should be the same.\n//   return 0.5 * (tot_backward_prob + tot_forward_prob);\n// }\n//\n// // instantiate the template for Lattice and CompactLattice\n// template\n// double ComputeLatticeAlphasAndBetas(const Lattice &lat,\n//                                     bool viterbi,\n//                                     vector<double> *alpha,\n//                                     vector<double> *beta);\n//\n// template\n// double ComputeLatticeAlphasAndBetas(const CompactLattice &lat,\n//                                     bool viterbi,\n//                                     vector<double> *alpha,\n//                                     vector<double> *beta);\n//\n//\n//\n// /// This is used in CompactLatticeLimitDepth.\n// struct LatticeArcRecord {\n//   BaseFloat logprob; // logprob <= 0 is the best Viterbi logprob of this arc,\n//                      // minus the overall best-cost of the lattice.\n//   CompactLatticeArc::StateId state; // state in the lattice.\n//   size_t arc; // arc index within the state.\n//   bool operator < (const LatticeArcRecord &other) const {\n//     return logprob < other.logprob;\n//   }\n// };\n//\n// void CompactLatticeLimitDepth(int32 max_depth_per_frame,\n//                               CompactLattice *clat) {\n//   typedef CompactLatticeArc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   if (clat->Start() == fst::kNoStateId) {\n//     KALDI_WARN << \"Limiting depth of empty lattice.\";\n//     return;\n//   }\n//   if (clat->Properties(fst::kTopSorted, true) == 0) {\n//     if (!TopSort(clat))\n//       KALDI_ERR << \"Topological sorting of lattice failed.\";\n//   }\n//\n//   vector<int32> state_times;\n//   int32 T = CompactLatticeStateTimes(*clat, &state_times);\n//\n//   // The alpha and beta quantities here are \"viterbi\" alphas and beta.\n//   std::vector<double> alpha;\n//   std::vector<double> beta;\n//   bool viterbi = true;\n//   double best_prob = ComputeLatticeAlphasAndBetas(*clat, viterbi,\n//                                                   &alpha, &beta);\n//\n//   std::vector<std::vector<LatticeArcRecord> > arc_records(T);\n//\n//   StateId num_states = clat->NumStates();\n//   for (StateId s = 0; s < num_states; s++) {\n//     for (fst::ArcIterator<CompactLattice> aiter(*clat, s); !aiter.Done();\n//          aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       LatticeArcRecord arc_record;\n//       arc_record.state = s;\n//       arc_record.arc = aiter.Position();\n//       arc_record.logprob =\n//           (alpha[s] + beta[arc.nextstate] - ConvertToCost(arc.weight))\n//            - best_prob;\n//       KALDI_ASSERT(arc_record.logprob < 0.1); // Should be zero or negative.\n//       int32 num_frames = arc.weight.String().size(), start_t = state_times[s];\n//       for (int32 t = start_t; t < start_t + num_frames; t++) {\n//         KALDI_ASSERT(t < T);\n//         arc_records[t].push_back(arc_record);\n//       }\n//     }\n//   }\n//   StateId dead_state = clat->AddState(); // A non-coaccesible state which we use\n//                                          // to remove arcs (make them end\n//                                          // there).\n//   size_t max_depth = max_depth_per_frame;\n//   for (int32 t = 0; t < T; t++) {\n//     size_t size = arc_records[t].size();\n//     if (size > max_depth) {\n//       // we sort from worst to best, so we keep the later-numbered ones,\n//       // and delete the lower-numbered ones.\n//       size_t cutoff = size - max_depth;\n//       std::nth_element(arc_records[t].begin(),\n//                        arc_records[t].begin() + cutoff,\n//                        arc_records[t].end());\n//       for (size_t index = 0; index < cutoff; index++) {\n//         LatticeArcRecord record(arc_records[t][index]);\n//         fst::MutableArcIterator<CompactLattice> aiter(clat, record.state);\n//         aiter.Seek(record.arc);\n//         Arc arc = aiter.Value();\n//         if (arc.nextstate != dead_state) { // not already killed.\n//           arc.nextstate = dead_state;\n//           aiter.SetValue(arc);\n//         }\n//       }\n//     }\n//   }\n//   Connect(clat);\n//   TopSortCompactLatticeIfNeeded(clat);\n// }\n//\n//\n// void TopSortCompactLatticeIfNeeded(CompactLattice *clat) {\n//   if (clat->Properties(fst::kTopSorted, true) == 0) {\n//     if (fst::TopSort(clat) == false) {\n//       KALDI_ERR << \"Topological sorting failed\";\n//     }\n//   }\n// }\n//\n// void TopSortLatticeIfNeeded(Lattice *lat) {\n//   if (lat->Properties(fst::kTopSorted, true) == 0) {\n//     if (fst::TopSort(lat) == false) {\n//       KALDI_ERR << \"Topological sorting failed\";\n//     }\n//   }\n// }\n//\n//\n// /// Returns the depth of the lattice, defined as the average number of\n// /// arcs crossing any given frame.  Returns 1 for empty lattices.\n// /// Requires that input is topologically sorted.\n// BaseFloat CompactLatticeDepth(const CompactLattice &clat,\n//                               int32 *num_frames) {\n//   typedef CompactLattice::Arc::StateId StateId;\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     KALDI_ERR << \"Lattice input to CompactLatticeDepth was not topologically \"\n//               << \"sorted.\";\n//   }\n//   if (clat.Start() == fst::kNoStateId) {\n//     *num_frames = 0;\n//     return 1.0;\n//   }\n//   size_t num_arc_frames = 0;\n//   int32 t;\n//   {\n//     vector<int32> state_times;\n//     t = CompactLatticeStateTimes(clat, &state_times);\n//   }\n//   if (num_frames != NULL)\n//     *num_frames = t;\n//   for (StateId s = 0; s < clat.NumStates(); s++) {\n//     for (fst::ArcIterator<CompactLattice> aiter(clat, s); !aiter.Done();\n//          aiter.Next()) {\n//       const CompactLatticeArc &arc = aiter.Value();\n//       num_arc_frames += arc.weight.String().size();\n//     }\n//     num_arc_frames += clat.Final(s).String().size();\n//   }\n//   return num_arc_frames / static_cast<BaseFloat>(t);\n// }\n//\n//\n// void CompactLatticeDepthPerFrame(const CompactLattice &clat,\n//                                  std::vector<int32> *depth_per_frame) {\n//   typedef CompactLattice::Arc::StateId StateId;\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     KALDI_ERR << \"Lattice input to CompactLatticeDepthPerFrame was not \"\n//               << \"topologically sorted.\";\n//   }\n//   if (clat.Start() == fst::kNoStateId) {\n//     depth_per_frame->clear();\n//     return;\n//   }\n//   vector<int32> state_times;\n//   int32 T = CompactLatticeStateTimes(clat, &state_times);\n//\n//   depth_per_frame->clear();\n//   if (T <= 0) {\n//     return;\n//   } else {\n//     depth_per_frame->resize(T, 0);\n//     for (StateId s = 0; s < clat.NumStates(); s++) {\n//       int32 start_time = state_times[s];\n//       for (fst::ArcIterator<CompactLattice> aiter(clat, s); !aiter.Done();\n//            aiter.Next()) {\n//         const CompactLatticeArc &arc = aiter.Value();\n//         int32 len = arc.weight.String().size();\n//         for (int32 t = start_time; t < start_time + len; t++) {\n//           KALDI_ASSERT(t < T);\n//           (*depth_per_frame)[t]++;\n//         }\n//       }\n//       int32 final_len = clat.Final(s).String().size();\n//       for (int32 t = start_time; t < start_time + final_len; t++) {\n//         KALDI_ASSERT(t < T);\n//         (*depth_per_frame)[t]++;\n//       }\n//     }\n//   }\n// }\n//\n//\n//\n// void ConvertCompactLatticeToPhones(const TransitionModel &trans,\n//                                    CompactLattice *clat) {\n//   typedef CompactLatticeArc Arc;\n//   typedef Arc::Weight Weight;\n//   int32 num_states = clat->NumStates();\n//   for (int32 state = 0; state < num_states; state++) {\n//     for (fst::MutableArcIterator<CompactLattice> aiter(clat, state);\n//          !aiter.Done();\n//          aiter.Next()) {\n//       Arc arc(aiter.Value());\n//       std::vector<int32> phone_seq;\n//       const std::vector<int32> &tid_seq = arc.weight.String();\n//       for (std::vector<int32>::const_iterator iter = tid_seq.begin();\n//            iter != tid_seq.end(); ++iter) {\n//         if (trans.IsFinal(*iter))// note: there is one of these per phone...\n//           phone_seq.push_back(trans.TransitionIdToPhone(*iter));\n//       }\n//       arc.weight.SetString(phone_seq);\n//       aiter.SetValue(arc);\n//     } // end looping over arcs\n//     Weight f = clat->Final(state);\n//     if (f != Weight::Zero()) {\n//       std::vector<int32> phone_seq;\n//       const std::vector<int32> &tid_seq = f.String();\n//       for (std::vector<int32>::const_iterator iter = tid_seq.begin();\n//            iter != tid_seq.end(); ++iter) {\n//         if (trans.IsFinal(*iter))// note: there is one of these per phone...\n//           phone_seq.push_back(trans.TransitionIdToPhone(*iter));\n//       }\n//       f.SetString(phone_seq);\n//       clat->SetFinal(state, f);\n//     }\n//   }  // end looping over states\n// }\n//\n// bool LatticeBoost(const TransitionModel &trans,\n//                   const std::vector<int32> &alignment,\n//                   const std::vector<int32> &silence_phones,\n//                   BaseFloat b,\n//                   BaseFloat max_silence_error,\n//                   Lattice *lat) {\n//   TopSortLatticeIfNeeded(lat);\n//\n//   // get all stored properties (test==false means don't test if not known).\n//   uint64 props = lat->Properties(fst::kFstProperties,\n//                                  false);\n//\n//   KALDI_ASSERT(IsSortedAndUniq(silence_phones));\n//   KALDI_ASSERT(max_silence_error >= 0.0 && max_silence_error <= 1.0);\n//   vector<int32> state_times;\n//   int32 num_states = lat->NumStates();\n//   int32 num_frames = LatticeStateTimes(*lat, &state_times);\n//   KALDI_ASSERT(num_frames == static_cast<int32>(alignment.size()));\n//   for (int32 state = 0; state < num_states; state++) {\n//     int32 cur_time = state_times[state];\n//     for (fst::MutableArcIterator<Lattice> aiter(lat, state); !aiter.Done();\n//          aiter.Next()) {\n//       LatticeArc arc = aiter.Value();\n//       if (arc.ilabel != 0) {  // Non-epsilon arc\n//         if (arc.ilabel < 0 || arc.ilabel > trans.NumTransitionIds()) {\n//           KALDI_WARN << \"Lattice has out-of-range transition-ids: \"\n//                      << \"lattice/model mismatch?\";\n//           return false;\n//         }\n//         int32 phone = trans.TransitionIdToPhone(arc.ilabel),\n//             ref_phone = trans.TransitionIdToPhone(alignment[cur_time]);\n//         BaseFloat frame_error;\n//         if (phone == ref_phone) {\n//           frame_error = 0.0;\n//         } else { // an error...\n//           if (std::binary_search(silence_phones.begin(), silence_phones.end(), phone))\n//             frame_error = max_silence_error;\n//           else\n//             frame_error = 1.0;\n//         }\n//         BaseFloat delta_cost = -b * frame_error; // negative cost if\n//         // frame is wrong, to boost likelihood of arcs with errors on them.\n//         // Add this cost to the graph part.\n//         arc.weight.SetValue1(arc.weight.Value1() + delta_cost);\n//         aiter.SetValue(arc);\n//       }\n//     }\n//   }\n//   // All we changed is the weights, so any properties that were\n//   // known before, are still known, except for whether or not the\n//   // lattice was weighted.\n//   lat->SetProperties(props,\n//                      ~(fst::kWeighted|fst::kUnweighted));\n//\n//   return true;\n// }\n//\n//\n//\n// BaseFloat LatticeForwardBackwardMpeVariants(\n//     const TransitionModel &trans,\n//     const std::vector<int32> &silence_phones,\n//     const Lattice &lat,\n//     const std::vector<int32> &num_ali,\n//     std::string criterion,\n//     bool one_silence_class,\n//     Posterior *post) {\n//   using namespace fst;\n//   typedef Lattice::Arc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   KALDI_ASSERT(criterion == \"mpfe\" || criterion == \"smbr\");\n//   bool is_mpfe = (criterion == \"mpfe\");\n//\n//   if (lat.Properties(fst::kTopSorted, true) == 0)\n//     KALDI_ERR << \"Input lattice must be topologically sorted.\";\n//   KALDI_ASSERT(lat.Start() == 0);\n//\n//   int32 num_states = lat.NumStates();\n//   vector<int32> state_times;\n//   int32 max_time = LatticeStateTimes(lat, &state_times);\n//   KALDI_ASSERT(max_time == static_cast<int32>(num_ali.size()));\n//   std::vector<double> alpha(num_states, kLogZeroDouble),\n//       alpha_smbr(num_states, 0), //forward variable for sMBR\n//       beta(num_states, kLogZeroDouble),\n//       beta_smbr(num_states, 0); //backward variable for sMBR\n//\n//   double tot_forward_prob = kLogZeroDouble;\n//   double tot_forward_score = 0;\n//\n//   post->clear();\n//   post->resize(max_time);\n//\n//   alpha[0] = 0.0;\n//   // First Pass Forward,\n//   for (StateId s = 0; s < num_states; s++) {\n//     double this_alpha = alpha[s];\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight);\n//       alpha[arc.nextstate] = LogAdd(alpha[arc.nextstate], this_alpha + arc_like);\n//     }\n//     Weight f = lat.Final(s);\n//     if (f != Weight::Zero()) {\n//       double final_like = this_alpha - (f.Value1() + f.Value2());\n//       tot_forward_prob = LogAdd(tot_forward_prob, final_like);\n//       KALDI_ASSERT(state_times[s] == max_time &&\n//                    \"Lattice is inconsistent (final-prob not at max_time)\");\n//     }\n//   }\n//   // First Pass Backward,\n//   for (StateId s = num_states-1; s >= 0; s--) {\n//     Weight f = lat.Final(s);\n//     double this_beta = -(f.Value1() + f.Value2());\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight),\n//           arc_beta = beta[arc.nextstate] + arc_like;\n//       this_beta = LogAdd(this_beta, arc_beta);\n//     }\n//     beta[s] = this_beta;\n//   }\n//   // First Pass Forward-Backward Check\n//   double tot_backward_prob = beta[0];\n//   // may loose the condition somehow here 1e-6 (was 1e-8)\n//   if (!ApproxEqual(tot_forward_prob, tot_backward_prob, 1e-6)) {\n//     KALDI_ERR << \"Total forward probability over lattice = \" << tot_forward_prob\n//               << \", while total backward probability = \" << tot_backward_prob;\n//   }\n//\n//   alpha_smbr[0] = 0.0;\n//   // Second Pass Forward, calculate forward for MPFE/SMBR\n//   for (StateId s = 0; s < num_states; s++) {\n//     double this_alpha = alpha[s];\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight);\n//       double frame_acc = 0.0;\n//       if (arc.ilabel != 0) {\n//         int32 cur_time = state_times[s];\n//         int32 phone = trans.TransitionIdToPhone(arc.ilabel),\n//             ref_phone = trans.TransitionIdToPhone(num_ali[cur_time]);\n//         bool phone_is_sil = std::binary_search(silence_phones.begin(),\n//                                                silence_phones.end(),\n//                                                phone),\n//             ref_phone_is_sil = std::binary_search(silence_phones.begin(),\n//                                                   silence_phones.end(),\n//                                                   ref_phone),\n//             both_sil = phone_is_sil && ref_phone_is_sil;\n//         if (!is_mpfe) { // smbr.\n//           int32 pdf = trans.TransitionIdToPdf(arc.ilabel),\n//               ref_pdf = trans.TransitionIdToPdf(num_ali[cur_time]);\n//           if (!one_silence_class)  // old behavior\n//             frame_acc = (pdf == ref_pdf && !phone_is_sil) ? 1.0 : 0.0;\n//           else\n//             frame_acc = (pdf == ref_pdf || both_sil) ? 1.0 : 0.0;\n//         } else {\n//           if (!one_silence_class)  // old behavior\n//             frame_acc = (phone == ref_phone && !phone_is_sil) ? 1.0 : 0.0;\n//           else\n//             frame_acc = (phone == ref_phone || both_sil) ? 1.0 : 0.0;\n//         }\n//       }\n//       double arc_scale = Exp(alpha[s] + arc_like - alpha[arc.nextstate]);\n//       alpha_smbr[arc.nextstate] += arc_scale * (alpha_smbr[s] + frame_acc);\n//     }\n//     Weight f = lat.Final(s);\n//     if (f != Weight::Zero()) {\n//       double final_like = this_alpha - (f.Value1() + f.Value2());\n//       double arc_scale = Exp(final_like - tot_forward_prob);\n//       tot_forward_score += arc_scale * alpha_smbr[s];\n//       KALDI_ASSERT(state_times[s] == max_time &&\n//                    \"Lattice is inconsistent (final-prob not at max_time)\");\n//     }\n//   }\n//   // Second Pass Backward, collect Mpe style posteriors\n//   for (StateId s = num_states-1; s >= 0; s--) {\n//     for (ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_like = -ConvertToCost(arc.weight),\n//           arc_beta = beta[arc.nextstate] + arc_like;\n//       double frame_acc = 0.0;\n//       int32 transition_id = arc.ilabel;\n//       if (arc.ilabel != 0) {\n//         int32 cur_time = state_times[s];\n//         int32 phone = trans.TransitionIdToPhone(arc.ilabel),\n//             ref_phone = trans.TransitionIdToPhone(num_ali[cur_time]);\n//         bool phone_is_sil = std::binary_search(silence_phones.begin(),\n//                                                silence_phones.end(), phone),\n//             ref_phone_is_sil = std::binary_search(silence_phones.begin(),\n//                                                   silence_phones.end(),\n//                                                   ref_phone),\n//             both_sil = phone_is_sil && ref_phone_is_sil;\n//         if (!is_mpfe) { // smbr.\n//           int32 pdf = trans.TransitionIdToPdf(arc.ilabel),\n//               ref_pdf = trans.TransitionIdToPdf(num_ali[cur_time]);\n//           if (!one_silence_class)  // old behavior\n//             frame_acc = (pdf == ref_pdf && !phone_is_sil) ? 1.0 : 0.0;\n//           else\n//             frame_acc = (pdf == ref_pdf || both_sil) ? 1.0 : 0.0;\n//         } else {\n//           if (!one_silence_class)  // old behavior\n//             frame_acc = (phone == ref_phone && !phone_is_sil) ? 1.0 : 0.0;\n//           else\n//             frame_acc = (phone == ref_phone || both_sil) ? 1.0 : 0.0;\n//         }\n//       }\n//       double arc_scale = Exp(beta[arc.nextstate] + arc_like - beta[s]);\n//       // check arc_scale NAN,\n//       // this is to prevent partial paths in Lattices\n//       // i.e., paths don't survive to the final state\n//       if (KALDI_ISNAN(arc_scale)) arc_scale = 0;\n//       beta_smbr[s] += arc_scale * (beta_smbr[arc.nextstate] + frame_acc);\n//\n//       if (transition_id != 0) { // Arc has a transition-id on it [not epsilon]\n//         double posterior = Exp(alpha[s] + arc_beta - tot_forward_prob);\n//         double acc_diff = alpha_smbr[s] + frame_acc + beta_smbr[arc.nextstate]\n//                                - tot_forward_score;\n//         double posterior_smbr = posterior * acc_diff;\n//         (*post)[state_times[s]].push_back(std::make_pair(transition_id,\n//                                                          static_cast<BaseFloat>(posterior_smbr)));\n//       }\n//     }\n//   }\n//\n//   //Second Pass Forward Backward check\n//   double tot_backward_score = beta_smbr[0];  // Initial state id == 0\n//   // may loose the condition somehow here 1e-5/1e-4\n//   if (!ApproxEqual(tot_forward_score, tot_backward_score, 1e-4)) {\n//     KALDI_ERR << \"Total forward score over lattice = \" << tot_forward_score\n//               << \", while total backward score = \" << tot_backward_score;\n//   }\n//\n//   // Output the computed posteriors\n//   for (int32 t = 0; t < max_time; t++)\n//     MergePairVectorSumming(&((*post)[t]));\n//   return tot_forward_score;\n// }\n//\n// bool CompactLatticeToWordAlignment(const CompactLattice &clat,\n//                                    std::vector<int32> *words,\n//                                    std::vector<int32> *begin_times,\n//                                    std::vector<int32> *lengths) {\n//   words->clear();\n//   begin_times->clear();\n//   lengths->clear();\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Label Label;\n//   typedef CompactLattice::StateId StateId;\n//   typedef CompactLattice::Weight Weight;\n//   using namespace fst;\n//   StateId state = clat.Start();\n//   int32 cur_time = 0;\n//   if (state == kNoStateId) {\n//     KALDI_WARN << \"Empty lattice.\";\n//     return false;\n//   }\n//   while (1) {\n//     Weight final = clat.Final(state);\n//     size_t num_arcs = clat.NumArcs(state);\n//     if (final != Weight::Zero()) {\n//       if (num_arcs != 0) {\n//         KALDI_WARN << \"Lattice is not linear.\";\n//         return false;\n//       }\n//       if (! final.String().empty()) {\n//         KALDI_WARN << \"Lattice has alignments on final-weight: probably \"\n//             \"was not word-aligned (alignments will be approximate)\";\n//       }\n//       return true;\n//     } else {\n//       if (num_arcs != 1) {\n//         KALDI_WARN << \"Lattice is not linear: num-arcs = \" << num_arcs;\n//         return false;\n//       }\n//       fst::ArcIterator<CompactLattice> aiter(clat, state);\n//       const Arc &arc = aiter.Value();\n//       Label word_id = arc.ilabel; // Note: ilabel==olabel, since acceptor.\n//       // Also note: word_id may be zero; we output it anyway.\n//       int32 length = arc.weight.String().size();\n//       words->push_back(word_id);\n//       begin_times->push_back(cur_time);\n//       lengths->push_back(length);\n//       cur_time += length;\n//       state = arc.nextstate;\n//     }\n//   }\n// }\n//\n//\n// bool CompactLatticeToWordProns(\n//     const TransitionModel &tmodel,\n//     const CompactLattice &clat,\n//     std::vector<int32> *words,\n//     std::vector<int32> *begin_times,\n//     std::vector<int32> *lengths,\n//     std::vector<std::vector<int32> > *prons,\n//     std::vector<std::vector<int32> > *phone_lengths) {\n//   words->clear();\n//   begin_times->clear();\n//   lengths->clear();\n//   prons->clear();\n//   phone_lengths->clear();\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Label Label;\n//   typedef CompactLattice::StateId StateId;\n//   typedef CompactLattice::Weight Weight;\n//   using namespace fst;\n//   StateId state = clat.Start();\n//   int32 cur_time = 0;\n//   if (state == kNoStateId) {\n//     KALDI_WARN << \"Empty lattice.\";\n//     return false;\n//   }\n//   while (1) {\n//     Weight final = clat.Final(state);\n//     size_t num_arcs = clat.NumArcs(state);\n//     if (final != Weight::Zero()) {\n//       if (num_arcs != 0) {\n//         KALDI_WARN << \"Lattice is not linear.\";\n//         return false;\n//       }\n//       if (! final.String().empty()) {\n//         KALDI_WARN << \"Lattice has alignments on final-weight: probably \"\n//             \"was not word-aligned (alignments will be approximate)\";\n//       }\n//       return true;\n//     } else {\n//       if (num_arcs != 1) {\n//         KALDI_WARN << \"Lattice is not linear: num-arcs = \" << num_arcs;\n//         return false;\n//       }\n//       fst::ArcIterator<CompactLattice> aiter(clat, state);\n//       const Arc &arc = aiter.Value();\n//       Label word_id = arc.ilabel; // Note: ilabel==olabel, since acceptor.\n//       // Also note: word_id may be zero; we output it anyway.\n//       int32 length = arc.weight.String().size();\n//       words->push_back(word_id);\n//       begin_times->push_back(cur_time);\n//       lengths->push_back(length);\n//       const std::vector<int32> &arc_alignment = arc.weight.String();\n//       std::vector<std::vector<int32> > split_alignment;\n//       SplitToPhones(tmodel, arc_alignment, &split_alignment);\n//       std::vector<int32> phones(split_alignment.size());\n//       std::vector<int32> plengths(split_alignment.size());\n//       for (size_t i = 0; i < split_alignment.size(); i++) {\n//         KALDI_ASSERT(!split_alignment[i].empty());\n//         phones[i] = tmodel.TransitionIdToPhone(split_alignment[i][0]);\n//         plengths[i] = split_alignment[i].size();\n//       }\n//       prons->push_back(phones);\n//       phone_lengths->push_back(plengths);\n//\n//       cur_time += length;\n//       state = arc.nextstate;\n//     }\n//   }\n// }\n//\n//\n//\n// void CompactLatticeShortestPath(const CompactLattice &clat,\n//                                 CompactLattice *shortest_path) {\n//   using namespace fst;\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     CompactLattice clat_copy(clat);\n//     if (!TopSort(&clat_copy))\n//       KALDI_ERR << \"Was not able to topologically sort lattice (cycles found?)\";\n//     CompactLatticeShortestPath(clat_copy, shortest_path);\n//     return;\n//   }\n//   // Now we can assume it's topologically sorted.\n//   shortest_path->DeleteStates();\n//   if (clat.Start() == kNoStateId) return;\n//   typedef CompactLatticeArc Arc;\n//   typedef Arc::StateId StateId;\n//   typedef CompactLatticeWeight Weight;\n//   vector<std::pair<double, StateId> > best_cost_and_pred(clat.NumStates() + 1);\n//   StateId superfinal = clat.NumStates();\n//   for (StateId s = 0; s <= clat.NumStates(); s++) {\n//     best_cost_and_pred[s].first = std::numeric_limits<double>::infinity();\n//     best_cost_and_pred[s].second = fst::kNoStateId;\n//   }\n//   best_cost_and_pred[clat.Start()].first = 0;\n//   for (StateId s = 0; s < clat.NumStates(); s++) {\n//     double my_cost = best_cost_and_pred[s].first;\n//     for (ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done();\n//          aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double arc_cost = ConvertToCost(arc.weight),\n//           next_cost = my_cost + arc_cost;\n//       if (next_cost < best_cost_and_pred[arc.nextstate].first) {\n//         best_cost_and_pred[arc.nextstate].first = next_cost;\n//         best_cost_and_pred[arc.nextstate].second = s;\n//       }\n//     }\n//     double final_cost = ConvertToCost(clat.Final(s)),\n//         tot_final = my_cost + final_cost;\n//     if (tot_final < best_cost_and_pred[superfinal].first) {\n//       best_cost_and_pred[superfinal].first = tot_final;\n//       best_cost_and_pred[superfinal].second = s;\n//     }\n//   }\n//   std::vector<StateId> states; // states on best path.\n//   StateId cur_state = superfinal, start_state = clat.Start();\n//   while (cur_state != start_state) {\n//     StateId prev_state = best_cost_and_pred[cur_state].second;\n//     if (prev_state == kNoStateId) {\n//       KALDI_WARN << \"Failure in best-path algorithm for lattice (infinite costs?)\";\n//       return; // return empty best-path.\n//     }\n//     states.push_back(prev_state);\n//     KALDI_ASSERT(cur_state != prev_state && \"Lattice with cycles\");\n//     cur_state = prev_state;\n//   }\n//   std::reverse(states.begin(), states.end());\n//   for (size_t i = 0; i < states.size(); i++)\n//     shortest_path->AddState();\n//   for (StateId s = 0; static_cast<size_t>(s) < states.size(); s++) {\n//     if (s == 0) shortest_path->SetStart(s);\n//     if (static_cast<size_t>(s + 1) < states.size()) { // transition to next state.\n//       bool have_arc = false;\n//       Arc cur_arc;\n//       for (ArcIterator<CompactLattice> aiter(clat, states[s]);\n//            !aiter.Done();\n//            aiter.Next()) {\n//         const Arc &arc = aiter.Value();\n//         if (arc.nextstate == states[s+1]) {\n//           if (!have_arc ||\n//               ConvertToCost(arc.weight) < ConvertToCost(cur_arc.weight)) {\n//             cur_arc = arc;\n//             have_arc = true;\n//           }\n//         }\n//       }\n//       KALDI_ASSERT(have_arc && \"Code error.\");\n//       shortest_path->AddArc(s, Arc(cur_arc.ilabel, cur_arc.olabel,\n//                                    cur_arc.weight, s+1));\n//     } else { // final-prob.\n//       shortest_path->SetFinal(s, clat.Final(states[s]));\n//     }\n//   }\n// }\n//\n//\n// void ExpandCompactLattice(const CompactLattice &clat,\n//                           double epsilon,\n//                           CompactLattice *expand_clat) {\n//   using namespace fst;\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//   typedef std::pair<StateId, StateId> StatePair;\n//   typedef unordered_map<StatePair, StateId, PairHasher<StateId> > MapType;\n//   typedef MapType::iterator IterType;\n//\n//   if (clat.Start() == kNoStateId) return;\n//   // Make sure the input lattice is topologically sorted.\n//   if (clat.Properties(kTopSorted, true) == 0) {\n//     CompactLattice clat_copy(clat);\n//     KALDI_LOG << \"Topsort this lattice.\";\n//     if (!TopSort(&clat_copy))\n//       KALDI_ERR << \"Was not able to topologically sort lattice (cycles found?)\";\n//     ExpandCompactLattice(clat_copy, epsilon, expand_clat);\n//     return;\n//   }\n//\n//   // Compute backward logprobs betas for the expanded lattice.\n//   // Note: the backward logprobs in the original lattice <clat> and the\n//   // expanded lattice <expand_clat> are the same.\n//   int32 num_states = clat.NumStates();\n//   std::vector<double> beta(num_states, kLogZeroDouble);\n//   ComputeCompactLatticeBetas(clat, &beta);\n//   double tot_backward_logprob = beta[0];\n//   std::vector<double> alpha;\n//   alpha.push_back(0.0);\n//   expand_clat->DeleteStates();\n//   MapType state_map; // Map from state pair (orig_state, copy_state) to\n//   // copy_state, where orig_state is a state in the original lattice, and\n//   // copy_state is its corresponding one in the expanded lattice.\n//   unordered_map<StateId, StateId> states; // Map from orig_state to its\n//   // copy_state for states with incoming arcs' posteriors <= epsilon.\n//   std::queue<StatePair> state_queue;\n//\n//   // Set start state in the expanded lattice.\n//   StateId start_state = expand_clat->AddState();\n//   expand_clat->SetStart(start_state);\n//   StatePair start_pair(clat.Start(), start_state);\n//   state_queue.push(start_pair);\n//   std::pair<IterType, bool> result =\n//     state_map.insert(std::make_pair(start_pair, start_state));\n//   KALDI_ASSERT(result.second == true);\n//\n//   // Expand <clat> and update forward logprobs alphas in <expand_clat>.\n//   while (!state_queue.empty()) {\n//     StatePair s = state_queue.front();\n//     StateId s1 = s.first,\n//             s2 = s.second;\n//     state_queue.pop();\n//\n//     Weight f = clat.Final(s1);\n//     if (f != Weight::Zero()) {\n//       KALDI_ASSERT(state_map.find(s) != state_map.end());\n//       expand_clat->SetFinal(state_map[s], f);\n//     }\n//\n//     for (ArcIterator<CompactLattice> aiter(clat, s1);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       StateId orig_state = arc.nextstate;\n//       double arc_like = -ConvertToCost(arc.weight),\n//              this_alpha = alpha[s2] + arc_like,\n//              arc_post = Exp(this_alpha + beta[orig_state] -\n//                             tot_backward_logprob);\n//       // Generate the expanded lattice.\n//       StateId copy_state;\n//       if (arc_post > epsilon) {\n//         copy_state = expand_clat->AddState();\n//         StatePair next_pair(orig_state, copy_state);\n//         std::pair<IterType, bool> result =\n//           state_map.insert(std::make_pair(next_pair, copy_state));\n//         KALDI_ASSERT(result.second == true);\n//         state_queue.push(next_pair);\n//       } else {\n//         unordered_map<StateId, StateId>::iterator iter = states.find(orig_state);\n//         if (iter == states.end() ) { // The counterpart state of orig_state\n//                                    // has not been created in <expand_clat> yet.\n//           copy_state = expand_clat->AddState();\n//           StatePair next_pair(orig_state, copy_state);\n//           std::pair<IterType, bool> result =\n//             state_map.insert(std::make_pair(next_pair, copy_state));\n//           KALDI_ASSERT(result.second == true);\n//           state_queue.push(next_pair);\n//           states[orig_state] = copy_state;\n//         } else {\n//           copy_state = iter->second;\n//         }\n//       }\n//       // Create an arc from state_map[s] to copy_state in the expanded lattice.\n//       expand_clat->AddArc(state_map[s], Arc(arc.ilabel, arc.olabel, arc.weight,\n//                                             copy_state));\n//       // Compute forward logprobs alpha for the expanded lattice.\n//       if ((alpha.size() - 1) < copy_state) { // The first time to compute alpha\n//                                              // for copy_state in <expand_clat>.\n//         alpha.push_back(this_alpha);\n//       } else { // Accumulate alpha.\n//         alpha[copy_state] = LogAdd(alpha[copy_state], this_alpha);\n//       }\n//     }\n//   } // end while\n// }\n//\n//\n// void CompactLatticeBestCostsAndTracebacks(\n//     const CompactLattice &clat,\n//     CostTraceType *forward_best_cost_and_pred,\n//     CostTraceType *backward_best_cost_and_pred) {\n//\n//   // typedef the arc, weight types\n//   typedef CompactLatticeArc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//\n//   forward_best_cost_and_pred->clear();\n//   backward_best_cost_and_pred->clear();\n//   forward_best_cost_and_pred->resize(clat.NumStates());\n//   backward_best_cost_and_pred->resize(clat.NumStates());\n//   // Initialize the cost and predecessor state for each state.\n//   for (StateId s = 0; s < clat.NumStates(); s++) {\n//     (*forward_best_cost_and_pred)[s].first =\n//                                         std::numeric_limits<double>::infinity();\n//     (*backward_best_cost_and_pred)[s].first =\n//                                         std::numeric_limits<double>::infinity();\n//     (*forward_best_cost_and_pred)[s].second = fst::kNoStateId;\n//     (*backward_best_cost_and_pred)[s].second = fst::kNoStateId;\n//   }\n//\n//   StateId start_state = clat.Start();\n//   (*forward_best_cost_and_pred)[start_state].first = 0;\n//   // Transverse the lattice forwardly to compute the best cost from the start\n//   // state to each state and the best predecessor state of each state.\n//   for (StateId s = 0; s < clat.NumStates(); s++) {\n//     double cur_cost = (*forward_best_cost_and_pred)[s].first;\n//     for (fst::ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double next_cost = cur_cost + ConvertToCost(arc.weight);\n//       if (next_cost < (*forward_best_cost_and_pred)[arc.nextstate].first) {\n//         (*forward_best_cost_and_pred)[arc.nextstate].first = next_cost;\n//         (*forward_best_cost_and_pred)[arc.nextstate].second = s;\n//       }\n//     }\n//   }\n//   // Transverse the lattice backwardly to compute the best cost from a final\n//   // state to each state and the best predecessor state of each state.\n//   for (StateId s = clat.NumStates() - 1; s >= 0; s--) {\n//     double this_cost = ConvertToCost(clat.Final(s));\n//     for (fst::ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       double next_cost = (*backward_best_cost_and_pred)[arc.nextstate].first +\n//         ConvertToCost(arc.weight);\n//       if (next_cost < this_cost) {\n//         this_cost = next_cost;\n//         (*backward_best_cost_and_pred)[s].second = arc.nextstate;\n//       }\n//     }\n//     (*backward_best_cost_and_pred)[s].first = this_cost;\n//   }\n// }\n//\n//\n// void AddNnlmScoreToCompactLattice(const MapT &nnlm_scores,\n//                                   CompactLattice *clat) {\n//   if (clat->Start() == fst::kNoStateId) return;\n//   // Make sure the input lattice is topologically sorted.\n//   if (clat->Properties(fst::kTopSorted, true) == 0) {\n//     KALDI_LOG << \"Topsort this lattice.\";\n//     if (!TopSort(clat))\n//       KALDI_ERR << \"Was not able to topologically sort lattice (cycles found?)\";\n//     AddNnlmScoreToCompactLattice(nnlm_scores, clat);\n//     return;\n//   }\n//\n//   // typedef the arc, weight types\n//   typedef CompactLatticeArc Arc;\n//   typedef Arc::Weight Weight;\n//   typedef Arc::StateId StateId;\n//   typedef std::pair<int32, int32> StatePair;\n//\n//   int32 num_states = clat->NumStates();\n//   unordered_map<StatePair, bool, PairHasher<int32> > final_state_check;\n//   for (StateId s = 0; s < num_states; s++) {\n//     for (fst::MutableArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       Arc arc(aiter.Value());\n//       StatePair arc_index = std::make_pair(static_cast<int32>(s),\n//                                            static_cast<int32>(arc.nextstate));\n//       MapT::const_iterator it = nnlm_scores.find(arc_index);\n//       double nnlm_score;\n//       if (it != nnlm_scores.end())\n//         nnlm_score = it->second;\n//       else\n//         KALDI_ERR << \"Some arc does not have neural language model score.\";\n//       if (arc.ilabel != 0) { // if there is a word on this arc\n//         LatticeWeight weight = arc.weight.Weight();\n//         // Add associated neural LM score to each arc.\n//         weight.SetValue1(weight.Value1() + nnlm_score);\n//         arc.weight.SetWeight(weight);\n//         aiter.SetValue(arc);\n//       }\n//       Weight clat_final = clat->Final(arc.nextstate);\n//       StatePair final_pair = std::make_pair(arc.nextstate, arc.nextstate);\n//       // Add neural LM scores to each final state only once.\n//       if (clat_final != CompactLatticeWeight::Zero() &&\n//           final_state_check.find(final_pair) == final_state_check.end()) {\n//         MapT::const_iterator final_it = nnlm_scores.find(final_pair);\n//         double final_nnlm_score = 0.0;\n//         if (final_it != nnlm_scores.end())\n//           final_nnlm_score = final_it->second;\n//         // Add neural LM scores to the final weight.\n//         Weight final_weight(LatticeWeight(clat_final.Weight().Value1() +\n//                                           final_nnlm_score,\n//                                           clat_final.Weight().Value2()),\n//                                           clat_final.String());\n//         clat->SetFinal(arc.nextstate, final_weight);\n//         final_state_check[final_pair] = true;\n//       }\n//     } // end looping over arcs\n//   } // end looping over states\n// }\n//\n// void AddWordInsPenToCompactLattice(BaseFloat word_ins_penalty,\n//                                    CompactLattice *clat) {\n//   typedef CompactLatticeArc Arc;\n//   int32 num_states = clat->NumStates();\n//\n//   //scan the lattice\n//   for (int32 state = 0; state < num_states; state++) {\n//     for (fst::MutableArcIterator<CompactLattice> aiter(clat, state);\n//          !aiter.Done(); aiter.Next()) {\n//\n//       Arc arc(aiter.Value());\n//\n//       if (arc.ilabel != 0) { // if there is a word on this arc\n//         LatticeWeight weight = arc.weight.Weight();\n//         // add word insertion penalty to lattice\n//         weight.SetValue1( weight.Value1() + word_ins_penalty);\n//         arc.weight.SetWeight(weight);\n//         aiter.SetValue(arc);\n//       }\n//     } // end looping over arcs\n//   }  // end looping over states\n// }\n//\n// struct ClatRescoreTuple {\n//   ClatRescoreTuple(int32 state, int32 arc, int32 tid):\n//       state_id(state), arc_id(arc), tid(tid) { }\n//   int32 state_id;\n//   int32 arc_id;\n//   int32 tid;\n// };\n//\n// /** RescoreCompactLatticeInternal is the internal code for both\n//     RescoreCompactLattice and RescoreCompatLatticeSpeedup.  For\n//     RescoreCompactLattice, \"tmodel\" will be NULL and speedup_factor will be 1.0.\n//  */\n// bool RescoreCompactLatticeInternal(\n//     const TransitionModel *tmodel,\n//     BaseFloat speedup_factor,\n//     DecodableInterface *decodable,\n//     CompactLattice *clat) {\n//   KALDI_ASSERT(speedup_factor >= 1.0);\n//   if (clat->NumStates() == 0) {\n//     KALDI_WARN << \"Rescoring empty lattice\";\n//     return false;\n//   }\n//   if (!clat->Properties(fst::kTopSorted, true)) {\n//     if (fst::TopSort(clat) == false) {\n//       KALDI_WARN << \"Cycles detected in lattice.\";\n//       return false;\n//     }\n//   }\n//   std::vector<int32> state_times;\n//   int32 utt_len = kaldi::CompactLatticeStateTimes(*clat, &state_times);\n//\n//   std::vector<std::vector<ClatRescoreTuple> > time_to_state(utt_len);\n//\n//   int32 num_states = clat->NumStates();\n//   KALDI_ASSERT(num_states == state_times.size());\n//   for (size_t state = 0; state < num_states; state++) {\n//     KALDI_ASSERT(state_times[state] >= 0);\n//     int32 t = state_times[state];\n//     int32 arc_id = 0;\n//     for (fst::MutableArcIterator<CompactLattice> aiter(clat, state);\n//          !aiter.Done(); aiter.Next(), arc_id++) {\n//       CompactLatticeArc arc = aiter.Value();\n//       std::vector<int32> arc_string = arc.weight.String();\n//\n//       for (size_t offset = 0; offset < arc_string.size(); offset++) {\n//         if (t < utt_len) { // end state may be past this..\n//           int32 tid = arc_string[offset];\n//           time_to_state[t+offset].push_back(ClatRescoreTuple(state, arc_id, tid));\n//         } else {\n//           if (t != utt_len) {\n//             KALDI_WARN << \"There appears to be lattice/feature mismatch, \"\n//                        << \"aborting.\";\n//             return false;\n//           }\n//         }\n//       }\n//     }\n//     if (clat->Final(state) != CompactLatticeWeight::Zero()) {\n//       arc_id = -1;\n//       std::vector<int32> arc_string = clat->Final(state).String();\n//       for (size_t offset = 0; offset < arc_string.size(); offset++) {\n//         KALDI_ASSERT(t + offset < utt_len); // already checked in\n//         // CompactLatticeStateTimes, so would be code error.\n//         time_to_state[t+offset].push_back(\n//             ClatRescoreTuple(state, arc_id, arc_string[offset]));\n//       }\n//     }\n//   }\n//\n//   for (int32 t = 0; t < utt_len; t++) {\n//     if ((t < utt_len - 1) && decodable->IsLastFrame(t)) {\n//       KALDI_WARN << \"Features are too short for lattice: utt-len is \"\n//                  << utt_len << \", \" << t << \" is last frame\";\n//       return false;\n//     }\n//     // frame_scale is the scale we put on the computed acoustic probs for this\n//     // frame.  It will always be 1.0 if tmodel == NULL (i.e. if we are not doing\n//     // the \"speedup\" code).  For frames with multiple pdf-ids it will be one.\n//     // For frames with only one pdf-id, it will equal speedup_factor (>=1.0)\n//     // with probability 1.0 / speedup_factor, and zero otherwise.  If it is zero,\n//     // we can avoid computing the probabilities.\n//     BaseFloat frame_scale = 1.0;\n//     KALDI_ASSERT(!time_to_state[t].empty());\n//     if (tmodel != NULL) {\n//       int32 pdf_id = tmodel->TransitionIdToPdf(time_to_state[t][0].tid);\n//       bool frame_has_multiple_pdfs = false;\n//       for (size_t i = 1; i < time_to_state[t].size(); i++) {\n//         if (tmodel->TransitionIdToPdf(time_to_state[t][i].tid) != pdf_id) {\n//           frame_has_multiple_pdfs = true;\n//           break;\n//         }\n//       }\n//       if (frame_has_multiple_pdfs) {\n//         frame_scale = 1.0;\n//       } else {\n//         if (WithProb(1.0 / speedup_factor)) {\n//           frame_scale = speedup_factor;\n//         } else {\n//           frame_scale = 0.0;\n//         }\n//       }\n//       if (frame_scale == 0.0)\n//         continue; // the code below would be pointless.\n//     }\n//\n//     for (size_t i = 0; i < time_to_state[t].size(); i++) {\n//       int32 state = time_to_state[t][i].state_id;\n//       int32 arc_id = time_to_state[t][i].arc_id;\n//       int32 tid = time_to_state[t][i].tid;\n//\n//       if (arc_id == -1) { // Final state\n//         // Access the trans_id\n//         CompactLatticeWeight curr_clat_weight = clat->Final(state);\n//\n//         // Calculate likelihood\n//         BaseFloat log_like = decodable->LogLikelihood(t, tid) * frame_scale;\n//         // update weight\n//         CompactLatticeWeight new_clat_weight = curr_clat_weight;\n//         LatticeWeight new_lat_weight = new_clat_weight.Weight();\n//         new_lat_weight.SetValue2(-log_like + curr_clat_weight.Weight().Value2());\n//         new_clat_weight.SetWeight(new_lat_weight);\n//         clat->SetFinal(state, new_clat_weight);\n//       } else {\n//         fst::MutableArcIterator<CompactLattice> aiter(clat, state);\n//\n//         aiter.Seek(arc_id);\n//         CompactLatticeArc arc = aiter.Value();\n//\n//         // Calculate likelihood\n//         BaseFloat log_like = decodable->LogLikelihood(t, tid) * frame_scale;\n//         // update weight\n//         LatticeWeight new_weight = arc.weight.Weight();\n//         new_weight.SetValue2(-log_like + arc.weight.Weight().Value2());\n//         arc.weight.SetWeight(new_weight);\n//         aiter.SetValue(arc);\n//       }\n//     }\n//   }\n//   return true;\n// }\n//\n//\n// bool RescoreCompactLatticeSpeedup(\n//     const TransitionModel &tmodel,\n//     BaseFloat speedup_factor,\n//     DecodableInterface *decodable,\n//     CompactLattice *clat) {\n//   return RescoreCompactLatticeInternal(&tmodel, speedup_factor, decodable, clat);\n// }\n//\n// bool RescoreCompactLattice(DecodableInterface *decodable,\n//                            CompactLattice *clat) {\n//   return RescoreCompactLatticeInternal(NULL, 1.0, decodable, clat);\n// }\n//\n//\n// bool RescoreLattice(DecodableInterface *decodable,\n//                     Lattice *lat) {\n//   if (lat->NumStates() == 0) {\n//     KALDI_WARN << \"Rescoring empty lattice\";\n//     return false;\n//   }\n//   if (!lat->Properties(fst::kTopSorted, true)) {\n//     if (fst::TopSort(lat) == false) {\n//       KALDI_WARN << \"Cycles detected in lattice.\";\n//       return false;\n//     }\n//   }\n//   std::vector<int32> state_times;\n//   int32 utt_len = kaldi::LatticeStateTimes(*lat, &state_times);\n//\n//   std::vector<std::vector<int32> > time_to_state(utt_len );\n//\n//   int32 num_states = lat->NumStates();\n//   KALDI_ASSERT(num_states == state_times.size());\n//   for (size_t state = 0; state < num_states; state++) {\n//     int32 t = state_times[state];\n//     // Don't check t >= 0 because non-accessible states could have t = -1.\n//     KALDI_ASSERT(t <= utt_len);\n//     if (t >= 0 && t < utt_len)\n//       time_to_state[t].push_back(state);\n//   }\n//\n//   for (int32 t = 0; t < utt_len; t++) {\n//     if ((t < utt_len - 1) && decodable->IsLastFrame(t)) {\n//       KALDI_WARN << \"Features are too short for lattice: utt-len is \"\n//                  << utt_len << \", \" << t << \" is last frame\";\n//       return false;\n//     }\n//     for (size_t i = 0; i < time_to_state[t].size(); i++) {\n//       int32 state = time_to_state[t][i];\n//       for (fst::MutableArcIterator<Lattice> aiter(lat, state);\n//            !aiter.Done(); aiter.Next()) {\n//         LatticeArc arc = aiter.Value();\n//         if (arc.ilabel != 0) {\n//           int32 trans_id = arc.ilabel; // Note: it doesn't necessarily\n//           // have to be a transition-id, just whatever the Decodable\n//           // object is expecting, but it's normally a transition-id.\n//\n//           BaseFloat log_like = decodable->LogLikelihood(t, trans_id);\n//           arc.weight.SetValue2(-log_like + arc.weight.Value2());\n//           aiter.SetValue(arc);\n//         }\n//       }\n//     }\n//   }\n//   return true;\n// }\n//\n//\n// BaseFloat LatticeForwardBackwardMmi(\n//     const TransitionModel &tmodel,\n//     const Lattice &lat,\n//     const std::vector<int32> &num_ali,\n//     bool drop_frames,\n//     bool convert_to_pdf_ids,\n//     bool cancel,\n//     Posterior *post) {\n//   // First compute the MMI posteriors.\n//\n//   Posterior den_post;\n//   BaseFloat ans = LatticeForwardBackward(lat,\n//                                          &den_post,\n//                                          NULL);\n//\n//   Posterior num_post;\n//   AlignmentToPosterior(num_ali, &num_post);\n//\n//   // Now negate the MMI posteriors and add the numerator\n//   // posteriors.\n//   ScalePosterior(-1.0, &den_post);\n//\n//   if (convert_to_pdf_ids) {\n//     Posterior num_tmp;\n//     ConvertPosteriorToPdfs(tmodel, num_post, &num_tmp);\n//     num_tmp.swap(num_post);\n//     Posterior den_tmp;\n//     ConvertPosteriorToPdfs(tmodel, den_post, &den_tmp);\n//     den_tmp.swap(den_post);\n//   }\n//\n//   MergePosteriors(num_post, den_post,\n//                   cancel, drop_frames, post);\n//\n//   return ans;\n// }\n//\n//\n// int32 LongestSentenceLength(const Lattice &lat) {\n//   typedef Lattice::Arc Arc;\n//   typedef Arc::Label Label;\n//   typedef Arc::StateId StateId;\n//\n//   if (lat.Properties(fst::kTopSorted, true) == 0) {\n//     Lattice lat_copy(lat);\n//     if (!TopSort(&lat_copy))\n//       KALDI_ERR << \"Was not able to topologically sort lattice (cycles found?)\";\n//     return LongestSentenceLength(lat_copy);\n//   }\n//   std::vector<int32> max_length(lat.NumStates(), 0);\n//   int32 lattice_max_length = 0;\n//   for (StateId s = 0; s < lat.NumStates(); s++) {\n//     int32 this_max_length = max_length[s];\n//     for (fst::ArcIterator<Lattice> aiter(lat, s); !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       bool arc_has_word = (arc.olabel != 0);\n//       StateId nextstate = arc.nextstate;\n//       KALDI_ASSERT(static_cast<size_t>(nextstate) < max_length.size());\n//       if (arc_has_word) {\n//         // A lattice should ideally not have cycles anyway; a cycle with a word\n//         // on is something very bad.\n//         KALDI_ASSERT(nextstate > s && \"Lattice has cycles with words on.\");\n//         max_length[nextstate] = std::max(max_length[nextstate],\n//                                          this_max_length + 1);\n//       } else {\n//         max_length[nextstate] = std::max(max_length[nextstate],\n//                                          this_max_length);\n//       }\n//     }\n//     if (lat.Final(s) != LatticeWeight::Zero())\n//       lattice_max_length = std::max(lattice_max_length, max_length[s]);\n//   }\n//   return lattice_max_length;\n// }\n//\n// int32 LongestSentenceLength(const CompactLattice &clat) {\n//   typedef CompactLattice::Arc Arc;\n//   typedef Arc::Label Label;\n//   typedef Arc::StateId StateId;\n//\n//   if (clat.Properties(fst::kTopSorted, true) == 0) {\n//     CompactLattice clat_copy(clat);\n//     if (!TopSort(&clat_copy))\n//       KALDI_ERR << \"Was not able to topologically sort lattice (cycles found?)\";\n//     return LongestSentenceLength(clat_copy);\n//   }\n//   std::vector<int32> max_length(clat.NumStates(), 0);\n//   int32 lattice_max_length = 0;\n//   for (StateId s = 0; s < clat.NumStates(); s++) {\n//     int32 this_max_length = max_length[s];\n//     for (fst::ArcIterator<CompactLattice> aiter(clat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       bool arc_has_word = (arc.ilabel != 0); // note: olabel == ilabel.\n//       // also note: for normal CompactLattice, e.g. as produced by\n//       // determinization, all arcs will have nonzero labels, but the user might\n//       // decide to remplace some of the labels with zero for some reason, and we\n//       // want to support this.\n//       StateId nextstate = arc.nextstate;\n//       KALDI_ASSERT(static_cast<size_t>(nextstate) < max_length.size());\n//       KALDI_ASSERT(nextstate > s && \"CompactLattice has cycles\");\n//       if (arc_has_word)\n//         max_length[nextstate] = std::max(max_length[nextstate],\n//                                          this_max_length + 1);\n//       else\n//         max_length[nextstate] = std::max(max_length[nextstate],\n//                                          this_max_length);\n//     }\n//     if (clat.Final(s) != CompactLatticeWeight::Zero())\n//       lattice_max_length = std::max(lattice_max_length, max_length[s]);\n//   }\n//   return lattice_max_length;\n// }\n//\n// void ComposeCompactLatticeDeterministic(\n//     const CompactLattice& clat,\n//     fst::DeterministicOnDemandFst<fst::StdArc>* det_fst,\n//     CompactLattice* composed_clat) {\n//   // StdFst::Arc and CompactLatticeArc has the same StateId type.\n//   typedef fst::StdArc::StateId StateId;\n//   typedef fst::StdArc::Weight Weight1;\n//   typedef CompactLatticeArc::Weight Weight2;\n//   typedef std::pair<StateId, StateId> StatePair;\n//   typedef unordered_map<StatePair, StateId, PairHasher<StateId> > MapType;\n//   typedef MapType::iterator IterType;\n//\n//   // Empties the output FST.\n//   KALDI_ASSERT(composed_clat != NULL);\n//   composed_clat->DeleteStates();\n//\n//   MapType state_map;\n//   std::queue<StatePair> state_queue;\n//\n//   // Sets start state in <composed_clat>.\n//   StateId start_state = composed_clat->AddState();\n//   StatePair start_pair(clat.Start(), det_fst->Start());\n//   composed_clat->SetStart(start_state);\n//   state_queue.push(start_pair);\n//   std::pair<IterType, bool> result =\n//       state_map.insert(std::make_pair(start_pair, start_state));\n//   KALDI_ASSERT(result.second == true);\n//\n//   // Starts composition here.\n//   while (!state_queue.empty()) {\n//     // Gets the first state in the queue.\n//     StatePair s = state_queue.front();\n//     StateId s1 = s.first;\n//     StateId s2 = s.second;\n//     state_queue.pop();\n//\n//\n//     Weight2 clat_final = clat.Final(s1);\n//     if (clat_final.Weight().Value1() !=\n//         std::numeric_limits<BaseFloat>::infinity()) {\n//       // Test for whether the final-prob of state s1 was zero.\n//       Weight1 det_fst_final = det_fst->Final(s2);\n//       if (det_fst_final.Value() !=\n//           std::numeric_limits<BaseFloat>::infinity()) {\n//         // Test for whether the final-prob of state s2 was zero.  If neither\n//         // source-state final prob was zero, then we should create final state\n//         // in fst_composed. We compute the product manually since this is more\n//         // efficient.\n//         Weight2 final_weight(LatticeWeight(clat_final.Weight().Value1() +\n//                                            det_fst_final.Value(),\n//                                            clat_final.Weight().Value2()),\n//                              clat_final.String());\n//         // we can assume final_weight is not Zero(), since neither of\n//         // the sources was zero.\n//         KALDI_ASSERT(state_map.find(s) != state_map.end());\n//         composed_clat->SetFinal(state_map[s], final_weight);\n//       }\n//     }\n//\n//     // Loops over pair of edges at s1 and s2.\n//     for (fst::ArcIterator<CompactLattice> aiter(clat, s1);\n//          !aiter.Done(); aiter.Next()) {\n//       const CompactLatticeArc& arc1 = aiter.Value();\n//       fst::StdArc arc2;\n//       StateId next_state1 = arc1.nextstate, next_state2;\n//       bool matched = false;\n//\n//       if (arc1.olabel == 0) {\n//         // If the symbol on <arc1> is <epsilon>, we transit to the next state\n//         // for <clat>, but keep <det_fst> at the current state.\n//         matched = true;\n//         next_state2 = s2;\n//       } else {\n//         // Otherwise try to find the matched arc in <det_fst>.\n//         matched = det_fst->GetArc(s2, arc1.olabel, &arc2);\n//         if (matched) {\n//           next_state2 = arc2.nextstate;\n//         }\n//       }\n//\n//       // If matched arc is found in <det_fst>, then we have to add new arcs to\n//       // <composed_clat>.\n//       if (matched) {\n//         StatePair next_state_pair(next_state1, next_state2);\n//         IterType siter = state_map.find(next_state_pair);\n//         StateId next_state;\n//\n//         // Adds composed state to <state_map>.\n//         if (siter == state_map.end()) {\n//           // If the composed state has not been created yet, create it.\n//           next_state = composed_clat->AddState();\n//           std::pair<const StatePair, StateId> next_state_map(next_state_pair,\n//                                                              next_state);\n//           std::pair<IterType, bool> result = state_map.insert(next_state_map);\n//           KALDI_ASSERT(result.second);\n//           state_queue.push(next_state_pair);\n//         } else {\n//           // If the composed state is already in <state_map>, we can directly\n//           // use that.\n//           next_state = siter->second;\n//         }\n//\n//         // Adds arc to <composed_clat>.\n//         if (arc1.olabel == 0) {\n//           composed_clat->AddArc(state_map[s],\n//                                 CompactLatticeArc(arc1.ilabel, 0,\n//                                                   arc1.weight, next_state));\n//         } else {\n//           Weight2 composed_weight(\n//               LatticeWeight(arc1.weight.Weight().Value1() +\n//                             arc2.weight.Value(),\n//                             arc1.weight.Weight().Value2()),\n//               arc1.weight.String());\n//           composed_clat->AddArc(state_map[s],\n//                                 CompactLatticeArc(arc1.ilabel, arc2.olabel,\n//                                                   composed_weight, next_state));\n//         }\n//       }\n//     }\n//   }\n//   fst::Connect(composed_clat);\n// }\n//\n//\n// void ComputeAcousticScoresMap(\n//     const Lattice &lat,\n//     unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//                                         PairHasher<int32> > *acoustic_scores) {\n//   // typedef the arc, weight types\n//   typedef Lattice::Arc Arc;\n//   typedef Arc::Weight LatticeWeight;\n//   typedef Arc::StateId StateId;\n//\n//   acoustic_scores->clear();\n//\n//   std::vector<int32> state_times;\n//   LatticeStateTimes(lat, &state_times);   // Assumes the input is top sorted\n//\n//   KALDI_ASSERT(lat.Start() == 0);\n//\n//   for (StateId s = 0; s < lat.NumStates(); s++) {\n//     int32 t = state_times[s];\n//     for (fst::ArcIterator<Lattice> aiter(lat, s); !aiter.Done();\n//           aiter.Next()) {\n//       const Arc &arc = aiter.Value();\n//       const LatticeWeight &weight = arc.weight;\n//\n//       int32 tid = arc.ilabel;\n//\n//       if (tid != 0) {\n//         unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//           PairHasher<int32> >::iterator it = acoustic_scores->find(std::make_pair(t, tid));\n//         if (it == acoustic_scores->end()) {\n//           acoustic_scores->insert(std::make_pair(std::make_pair(t, tid),\n//                                           std::make_pair(weight.Value2(), 1)));\n//         } else {\n//           if (it->second.second == 2\n//                 && it->second.first / it->second.second != weight.Value2()) {\n//             KALDI_VLOG(2) << \"Transitions on the same frame have different \"\n//                           << \"acoustic costs for tid \" << tid << \"; \"\n//                           << it->second.first / it->second.second\n//                           << \" vs \" << weight.Value2();\n//           }\n//           it->second.first += weight.Value2();\n//           it->second.second++;\n//         }\n//       } else {\n//         // Arcs with epsilon input label (tid) must have 0 acoustic cost\n//         KALDI_ASSERT(weight.Value2() == 0);\n//       }\n//     }\n//\n//     LatticeWeight f = lat.Final(s);\n//     if (f != LatticeWeight::Zero()) {\n//       // Final acoustic cost must be 0 as we are reading from\n//       // non-determinized, non-compact lattice\n//       KALDI_ASSERT(f.Value2() == 0.0);\n//     }\n//   }\n// }\n//\n// void ReplaceAcousticScoresFromMap(\n//     const unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//                                         PairHasher<int32> > &acoustic_scores,\n//     Lattice *lat) {\n//   // typedef the arc, weight types\n//   typedef Lattice::Arc Arc;\n//   typedef Arc::Weight LatticeWeight;\n//   typedef Arc::StateId StateId;\n//\n//   TopSortLatticeIfNeeded(lat);\n//\n//   std::vector<int32> state_times;\n//   LatticeStateTimes(*lat, &state_times);\n//\n//   KALDI_ASSERT(lat->Start() == 0);\n//\n//   for (StateId s = 0; s < lat->NumStates(); s++) {\n//     int32 t = state_times[s];\n//     for (fst::MutableArcIterator<Lattice> aiter(lat, s);\n//          !aiter.Done(); aiter.Next()) {\n//       Arc arc(aiter.Value());\n//\n//       int32 tid = arc.ilabel;\n//       if (tid != 0) {\n//         unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//           PairHasher<int32> >::const_iterator it = acoustic_scores.find(std::make_pair(t, tid));\n//         if (it == acoustic_scores.end()) {\n//           KALDI_ERR << \"Could not find tid \" << tid << \" at time \" << t\n//                     << \" in the acoustic scores map.\";\n//         } else {\n//           arc.weight.SetValue2(it->second.first / it->second.second);\n//         }\n//       } else {\n//         // For epsilon arcs, set acoustic cost to 0.0\n//         arc.weight.SetValue2(0.0);\n//       }\n//       aiter.SetValue(arc);\n//     }\n//\n//     LatticeWeight f = lat->Final(s);\n//     if (f != LatticeWeight::Zero()) {\n//       // Set final acoustic cost to 0.0\n//       f.SetValue2(0.0);\n//       lat->SetFinal(s, f);\n//     }\n//   }\n// }\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/lat/lattice-functions.h",
    "content": "// lat/lattice-functions.h\n\n// Copyright 2009-2012   Saarland University (author: Arnab Ghoshal)\n//           2012-2013   Johns Hopkins University (Author: Daniel Povey);\n//                       Bagher BabaAli\n//                2014   Guoguo Chen\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_LAT_LATTICE_FUNCTIONS_H_\n#define KALDI_LAT_LATTICE_FUNCTIONS_H_\n\n#include <vector>\n#include <map>\n\n#include \"base/kaldi-common.h\"\n// #include \"hmm/posterior.h\"\n#include \"fstext/fstext-lib.h\"\n// #include \"hmm/transition-model.h\"\n#include \"lat/kaldi-lattice.h\"\n// #include \"itf/decodable-itf.h\"\n\nnamespace kaldi {\n\n// /**\n//    This function extracts the per-frame log likelihoods from a linear\n//    lattice (which we refer to as an 'nbest' lattice elsewhere in Kaldi code).\n//    The dimension of *per_frame_loglikes will be set to the\n//    number of input symbols in 'nbest'.  The elements of\n//    '*per_frame_loglikes' will be set to the .Value2() elements of the lattice\n//    weights, which represent the acoustic costs; you may want to scale this\n//    vector afterward by -1/acoustic_scale to get the original loglikes.\n//    If there are acoustic costs on input-epsilon arcs or the final-prob in 'nbest'\n//    (and this should not normally be the case in situations where it makes\n//    sense to call this function), they will be included to the cost of the\n//    preceding input symbol, or the following input symbol for input-epsilons\n//    encountered prior to any input symbol.  If 'nbest' has no input symbols,\n//    'per_frame_loglikes' will be set to the empty vector.\n// **/\n// void GetPerFrameAcousticCosts(const Lattice &nbest,\n//                               Vector<BaseFloat> *per_frame_loglikes);\n//\n// /// This function iterates over the states of a topologically sorted lattice and\n// /// counts the time instance corresponding to each state. The times are returned\n// /// in a vector of integers 'times' which is resized to have a size equal to the\n// /// number of states in the lattice. The function also returns the maximum time\n// /// in the lattice (this will equal the number of frames in the file).\n// int32 LatticeStateTimes(const Lattice &lat, std::vector<int32> *times);\n//\n// /// As LatticeStateTimes, but in the CompactLattice format.  Note: must\n// /// be topologically sorted.  Returns length of the utterance in frames, which\n// /// might not be the same as the maximum time in the lattice, due to frames\n// /// in the final-prob.\n// int32 CompactLatticeStateTimes(const CompactLattice &clat,\n//                                std::vector<int32> *times);\n//\n// /// This function does the forward-backward over lattices and computes the\n// /// posterior probabilities of the arcs. It returns the total log-probability\n// /// of the lattice.  The Posterior quantities contain pairs of (transition-id, weight)\n// /// on each frame.\n// /// If the pointer \"acoustic_like_sum\" is provided, this value is set to\n// /// the sum over the arcs, of the posterior of the arc times the\n// /// acoustic likelihood [i.e. negated acoustic score] on that link.\n// /// This is used in combination with other quantities to work out\n// /// the objective function in MMI discriminative training.\n// BaseFloat LatticeForwardBackward(const Lattice &lat,\n//                                  Posterior *arc_post,\n//                                  double *acoustic_like_sum = NULL);\n//\n// // This function is something similar to LatticeForwardBackward(), but it is on\n// // the CompactLattice lattice format. Also we only need the alpha in the forward\n// // path, not the posteriors.\n// bool ComputeCompactLatticeAlphas(const CompactLattice &lat,\n//                                  std::vector<double> *alpha);\n//\n// // A sibling of the function CompactLatticeAlphas()... We compute the beta from\n// // the backward path here.\n// bool ComputeCompactLatticeBetas(const CompactLattice &lat,\n//                                 std::vector<double> *beta);\n//\n//\n// // Computes (normal or Viterbi) alphas and betas; returns (total-prob, or\n// // best-path negated cost) Note: in either case, the alphas and betas are\n// // negated costs.  Requires that lat be topologically sorted.  This code\n// // will work for either CompactLattice or Latice.\n// template<typename LatticeType>\n// double ComputeLatticeAlphasAndBetas(const LatticeType &lat,\n//                                     bool viterbi,\n//                                     std::vector<double> *alpha,\n//                                     std::vector<double> *beta);\n//\n//\n// /// Topologically sort the compact lattice if not already topologically sorted.\n// /// Will crash if the lattice cannot be topologically sorted.\n// void TopSortCompactLatticeIfNeeded(CompactLattice *clat);\n//\n//\n// /// Topologically sort the lattice if not already topologically sorted.\n// /// Will crash if lattice cannot be topologically sorted.\n// void TopSortLatticeIfNeeded(Lattice *clat);\n//\n// /// Returns the depth of the lattice, defined as the average number of arcs (or\n// /// final-prob strings) crossing any given frame.  Returns 1 for empty lattices.\n// /// Requires that clat is topologically sorted!\n// BaseFloat CompactLatticeDepth(const CompactLattice &clat,\n//                               int32 *num_frames = NULL);\n//\n// /// This function returns, for each frame, the number of arcs crossing that\n// /// frame.\n// void CompactLatticeDepthPerFrame(const CompactLattice &clat,\n//                                  std::vector<int32> *depth_per_frame);\n//\n//\n// /// This function limits the depth of the lattice, per frame: that means, it\n// /// does not allow more than a specified number of arcs active on any given\n// /// frame.  This can be used to reduce the size of the \"very deep\" portions of\n// /// the lattice.\n// void CompactLatticeLimitDepth(int32 max_arcs_per_frame,\n//                               CompactLattice *clat);\n//\n//\n// /// Given a lattice, and a transition model to map pdf-ids to phones,\n// /// outputs for each frame the set of phones active on that frame.  If\n// /// sil_phones (which must be sorted and uniq) is nonempty, it excludes\n// /// phones in this list.\n// void LatticeActivePhones(const Lattice &lat, const TransitionModel &trans,\n//                          const std::vector<int32> &sil_phones,\n//                          std::vector<std::set<int32> > *active_phones);\n//\n// /// Given a lattice, and a transition model to map pdf-ids to phones,\n// /// replace the output symbols (presumably words), with phones; we\n// /// use the TransitionModel to work out the phone sequence.  Note\n// /// that the phone labels are not exactly aligned with the phone\n// /// boundaries.  We put a phone label to coincide with any transition\n// /// to the final, nonemitting state of a phone (this state always exists,\n// /// we ensure this in HmmTopology::Check()).  This would be the last\n// /// transition-id in the phone if reordering is not done (but typically\n// /// we do reorder).\n// /// Also see PhoneAlignLattice, in phone-align-lattice.h.\n// void ConvertLatticeToPhones(const TransitionModel &trans_model,\n//                             Lattice *lat);\n\n/// Prunes a lattice or compact lattice.  Returns true on success, false if\n/// there was some kind of failure.\ntemplate<class LatticeType>\nbool PruneLattice(BaseFloat beam, LatticeType *lat);\n\n//\n// /// Given a lattice, and a transition model to map pdf-ids to phones,\n// /// replace the sequences of transition-ids with sequences of phones.\n// /// Note that this is different from ConvertLatticeToPhones, in that\n// /// we replace the transition-ids not the words.\n// void ConvertCompactLatticeToPhones(const TransitionModel &trans_model,\n//                                    CompactLattice *clat);\n//\n// /// Boosts LM probabilities by b * [number of frame errors]; equivalently, adds\n// /// -b*[number of frame errors] to the graph-component of the cost of each arc/path.\n// /// There is a frame error if a particular transition-id on a particular frame\n// /// corresponds to a phone not matching transcription's alignment for that frame.\n// /// This is used in \"margin-inspired\" discriminative training, esp. Boosted MMI.\n// /// The TransitionModel is used to map transition-ids in the lattice\n// /// input-side to phones; the phones appearing in\n// /// \"silence_phones\" are treated specially in that we replace the frame error f\n// /// (either zero or 1) for a frame, with the minimum of f or max_silence_error.\n// /// For the normal recipe, max_silence_error would be zero.\n// /// Returns true on success, false if there was some kind of mismatch.\n// /// At input, silence_phones must be sorted and unique.\n// bool LatticeBoost(const TransitionModel &trans,\n//                   const std::vector<int32> &alignment,\n//                   const std::vector<int32> &silence_phones,\n//                   BaseFloat b,\n//                   BaseFloat max_silence_error,\n//                   Lattice *lat);\n//\n//\n// /**\n//    This function implements either the MPFE (minimum phone frame error) or SMBR\n//    (state-level minimum bayes risk) forward-backward, depending on whether\n//    \"criterion\" is \"mpfe\" or \"smbr\".  It returns the MPFE\n//    criterion of SMBR criterion for this utterance, and outputs the posteriors (which\n//    may be positive or negative) into \"post\".\n//\n//    @param [in] trans    The transition model. Used to map the\n//                         transition-ids to phones or pdfs.\n//    @param [in] silence_phones   A list of integer ids of silence phones. The\n//                         silence frames i.e. the frames where num_ali\n//                         corresponds to a silence phones are treated specially.\n//                         The behavior is determined by 'one_silence_class'\n//                         being false (traditional behavior) or true.\n//                         Usually in our setup, several phones including\n//                         the silence, vocalized noise, non-spoken noise\n//                         and unk are treated as \"silence phones\"\n//    @param [in] lat      The denominator lattice\n//    @param [in] num_ali  The numerator alignment\n//    @param [in] criterion    The objective function. Must be \"mpfe\" or \"smbr\"\n//                         for MPFE (minimum phone frame error) or sMBR\n//                         (state minimum bayes risk) training.\n//    @param [in] one_silence_class   Determines how the silence frames are treated.\n//                         Setting this to false gives the old traditional behavior,\n//                         where the silence frames (according to num_ali) are\n//                         treated as incorrect. However, this means that the\n//                         insertions are not penalized by the objective.\n//                         Setting this to true gives the new behaviour, where we\n//                         treat silence as any other phone, except that all pdfs\n//                         of silence phones are collapsed into a single class for\n//                         the frame-error computation. This can possible reduce\n//                         the insertions in the trained model. This is closer to\n//                         the WER metric that we actually care about, since WER is\n//                         generally computed after filtering out noises, but\n//                         does penalize insertions.\n//     @param [out] post   The \"MBR posteriors\" i.e. derivatives w.r.t to the\n//                         pseudo log-likelihoods of states at each frame.\n// */\n// BaseFloat LatticeForwardBackwardMpeVariants(\n//     const TransitionModel &trans,\n//     const std::vector<int32> &silence_phones,\n//     const Lattice &lat,\n//     const std::vector<int32> &num_ali,\n//     std::string criterion,\n//     bool one_silence_class,\n//     Posterior *post);\n//\n// /**\n//    This function can be used to compute posteriors for MMI, with a positive contribution\n//    for the numerator and a negative one for the denominator.  This function is not actually\n//    used in our normal MMI training recipes, where it's instead done using various command\n//    line programs that each do a part of the job.  This function was written for use in\n//    neural-net MMI training.\n//\n//    @param [in] trans    The transition model. Used to map the\n//                         transition-ids to phones or pdfs.\n//    @param [in] lat      The denominator lattice\n//    @param [in] num_ali  The numerator alignment\n//    @param [in] drop_frames   If \"drop_frames\" is true, it will not compute any\n//                         posteriors on frames where the num and den have disjoint\n//                         pdf-ids.\n//    @param [in] convert_to_pdf_ids   If \"convert_to_pdfs_ids\" is true, it will\n//                         convert the output to be at the level of pdf-ids, not\n//                         transition-ids.\n//    @param [in] cancel   If \"cancel\" is true, it will cancel out any positive and\n//                         negative parts from the same transition-id (or pdf-id,\n//                         if convert_to_pdf_ids == true).\n//    @param [out] arc_post   The output MMI posteriors of transition-ids (or\n//                         pdf-ids if convert_to_pdf_ids == true) at each frame\n//                         i.e. the difference between the numerator\n//                         and denominator posteriors.\n//\n//    It returns the forward-backward likelihood of the lattice. */\n// BaseFloat LatticeForwardBackwardMmi(\n//     const TransitionModel &trans,\n//     const Lattice &lat,\n//     const std::vector<int32> &num_ali,\n//     bool drop_frames,\n//     bool convert_to_pdf_ids,\n//     bool cancel,\n//     Posterior *arc_post);\n//\n//\n// /// This function takes a CompactLattice that should only contain a single\n// /// linear sequence (e.g. derived from lattice-1best), and that should have been\n// /// processed so that the arcs in the CompactLattice align correctly with the\n// /// word boundaries (e.g. by lattice-align-words).  It outputs 3 vectors of the\n// /// same size, which give, for each word in the lattice (in sequence), the word\n// /// label and the begin time and length in frames.  This is done even for zero\n// /// (epsilon) words, generally corresponding to optional silence-- if you don't\n// /// want them, just ignore them in the output.\n// /// This function will print a warning and return false, if the lattice\n// /// did not have the correct format (e.g. if it is empty or it is not\n// /// linear).\n// bool CompactLatticeToWordAlignment(const CompactLattice &clat,\n//                                    std::vector<int32> *words,\n//                                    std::vector<int32> *begin_times,\n//                                    std::vector<int32> *lengths);\n//\n// /// This function takes a CompactLattice that should only contain a single\n// /// linear sequence (e.g. derived from lattice-1best), and that should have been\n// /// processed so that the arcs in the CompactLattice align correctly with the\n// /// word boundaries (e.g. by lattice-align-words).  It outputs 4 vectors of the\n// /// same size, which give, for each word in the lattice (in sequence), the word\n// /// label, the begin time and length in frames, and the pronunciation (sequence\n// /// of phones).  This is done even for zero words, corresponding to optional\n// /// silences -- if you don't want them, just ignore them in the output.\n// /// This function will print a warning and return false, if the lattice\n// /// did not have the correct format (e.g. if it is empty or it is not\n// /// linear).\n// bool CompactLatticeToWordProns(\n//     const TransitionModel &tmodel,\n//     const CompactLattice &clat,\n//     std::vector<int32> *words,\n//     std::vector<int32> *begin_times,\n//     std::vector<int32> *lengths,\n//     std::vector<std::vector<int32> > *prons,\n//     std::vector<std::vector<int32> > *phone_lengths);\n//\n//\n// /// A form of the shortest-path/best-path algorithm that's specially coded for\n// /// CompactLattice.  Requires that clat be acyclic.\n// void CompactLatticeShortestPath(const CompactLattice &clat,\n//                                 CompactLattice *shortest_path);\n//\n// /// This function expands a CompactLattice to ensure high-probability paths\n// /// have unique histories. Arcs with posteriors larger than epsilon get splitted.\n// void ExpandCompactLattice(const CompactLattice &clat,\n//                           double epsilon,\n//                           CompactLattice *expand_clat);\n//\n// /// For each state, compute forward and backward best (viterbi) costs and its\n// /// traceback states (for generating best paths later). The forward best cost\n// /// for a state is the cost of the best path from the start state to the state.\n// /// The traceback state of this state is its predecessor state in the best path.\n// /// The backward best cost for a state is the cost of the best path from the\n// /// state to a final one. Its traceback state is the successor state in the best\n// /// path in the forward direction.\n// /// Note: final weights of states are in backward_best_cost_and_pred.\n// /// Requires the input CompactLattice clat be acyclic.\n// typedef std::vector<std::pair<double,\n//         CompactLatticeArc::StateId> > CostTraceType;\n// void CompactLatticeBestCostsAndTracebacks(\n//     const CompactLattice &clat,\n//     CostTraceType *forward_best_cost_and_pred,\n//     CostTraceType *backward_best_cost_and_pred);\n//\n// /// This function adds estimated neural language model scores of words in a\n// /// minimal list of hypotheses that covers a lattice, to the graph scores on the\n// /// arcs. The list of hypotheses are generated by latbin/lattice-path-cover.\n// typedef unordered_map<std::pair<int32, int32>, double, PairHasher<int32> > MapT;\n// void AddNnlmScoreToCompactLattice(const MapT &nnlm_scores,\n//                                   CompactLattice *clat);\n//\n// /// This function add the word insertion penalty to graph score of each word\n// /// in the compact lattice\n// void AddWordInsPenToCompactLattice(BaseFloat word_ins_penalty,\n//                                    CompactLattice *clat);\n//\n// /// This function *adds* the negated scores obtained from the Decodable object,\n// /// to the acoustic scores on the arcs.  If you want to replace them, you should\n// /// use ScaleCompactLattice to first set the acoustic scores to zero.  Returns\n// /// true on success, false on error (typically some kind of mismatched inputs).\n// bool RescoreCompactLattice(DecodableInterface *decodable,\n//                            CompactLattice *clat);\n//\n//\n// /// This function returns the number of words in the longest sentence in a\n// /// CompactLattice (i.e. the maximum of any path, of the count of\n// /// olabels on that path).\n// int32 LongestSentenceLength(const Lattice &lat);\n//\n// /// This function returns the number of words in the longest sentence in a\n// /// CompactLattice, i.e. the maximum of any path, of the count of\n// /// labels on that path... note, in CompactLattice, the ilabels and olabels\n// /// are identical because it is an acceptor.\n// int32 LongestSentenceLength(const CompactLattice &lat);\n//\n//\n// /// This function is like RescoreCompactLattice, but it is modified to avoid\n// /// computing probabilities on most frames where all the pdf-ids are the same.\n// /// (it needs the transition-model to work out whether two transition-ids map to\n// /// the same pdf-id, and it assumes that the lattice has transition-ids on it).\n// /// The naive thing would be to just set all probabilities to zero on frames\n// /// where all the pdf-ids are the same (because this value won't affect the\n// /// lattice posterior).  But this would become confusing when we compute\n// /// corpus-level diagnostics such as the MMI objective function.  Instead,\n// /// imagine speedup_factor = 100 (it must be >= 1.0)... with probability (1.0 /\n// /// speedup_factor) we compute those likelihoods and multiply them by\n// /// speedup_factor; otherwise we set them to zero.  This gives the right\n// /// expected probability so our corpus-level diagnostics will be about right.\n// bool RescoreCompactLatticeSpeedup(\n//     const TransitionModel &tmodel,\n//     BaseFloat speedup_factor,\n//     DecodableInterface *decodable,\n//     CompactLattice *clat);\n//\n//\n// /// This function *adds* the negated scores obtained from the Decodable object,\n// /// to the acoustic scores on the arcs.  If you want to replace them, you should\n// /// use ScaleCompactLattice to first set the acoustic scores to zero.  Returns\n// /// true on success, false on error (e.g. some kind of mismatched inputs).\n// /// The input labels, if nonzero, are interpreted as transition-ids or whatever\n// /// other index the Decodable object expects.\n// bool RescoreLattice(DecodableInterface *decodable,\n//                     Lattice *lat);\n//\n// /// This function Composes a CompactLattice format lattice with a\n// /// DeterministicOnDemandFst<fst::StdFst> format fst, and outputs another\n// /// CompactLattice format lattice. The first element (the one that corresponds\n// /// to LM weight) in CompactLatticeWeight is used for composition.\n// ///\n// /// Note that the DeterministicOnDemandFst interface is not \"const\", therefore\n// /// we cannot use \"const\" for <det_fst>.\n// void ComposeCompactLatticeDeterministic(\n//     const CompactLattice& clat,\n//     fst::DeterministicOnDemandFst<fst::StdArc>* det_fst,\n//     CompactLattice* composed_clat);\n//\n// /// This function computes the mapping from the pair\n// /// (frame-index, transition-id) to the pair\n// /// (sum-of-acoustic-scores, num-of-occurrences) over all occurrences of the\n// /// transition-id in that frame.\n// /// frame-index in the lattice.\n// /// This function is useful for retaining the acoustic scores in a\n// /// non-compact lattice after a process like determinization where the\n// /// frame-level acoustic scores are typically lost.\n// /// The function ReplaceAcousticScoresFromMap is used to restore the\n// /// acoustic scores computed by this function.\n// ///\n// ///   @param [in] lat   Input lattice. Expected to be top-sorted. Otherwise the\n// ///                     function will crash.\n// ///   @param [out] acoustic_scores\n// ///                     Pointer to a map from the pair (frame-index,\n// ///                     transition-id) to a pair (sum-of-acoustic-scores,\n// ///                     num-of-occurrences).\n// ///                     Usually the acoustic scores for a pdf-id (and hence\n// ///                     transition-id) on a frame will be the same for all the\n// ///                     occurrences of the pdf-id in that frame.\n// ///                     But if not, we will take the average of the acoustic\n// ///                     scores. Hence, we store both the sum-of-acoustic-scores\n// ///                     and the num-of-occurrences of the transition-id in that\n// ///                     frame.\n// void ComputeAcousticScoresMap(\n//     const Lattice &lat,\n//     unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//                                         PairHasher<int32> > *acoustic_scores);\n//\n// /// This function restores acoustic scores computed using the function\n// /// ComputeAcousticScoresMap into the lattice.\n// ///\n// ///   @param [in] acoustic_scores\n// ///                      A map from the pair (frame-index, transition-id) to a\n// ///                      pair (sum-of-acoustic-scores, num-of-occurrences) of\n// ///                      the occurrences of the transition-id in that frame.\n// ///                      See the comments for ComputeAcousticScoresMap for\n// ///                      details.\n// ///   @param [out] lat   Pointer to the output lattice.\n// void ReplaceAcousticScoresFromMap(\n//     const unordered_map<std::pair<int32, int32>, std::pair<BaseFloat, int32>,\n//                                         PairHasher<int32> > &acoustic_scores,\n//     Lattice *lat);\n\n}  // namespace kaldi\n\n#endif  // KALDI_LAT_LATTICE_FUNCTIONS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/lm/CMakeLists.txt",
    "content": "\nadd_library(kaldi-lm\n  arpa-file-parser.cc\n  arpa-lm-compiler.cc\n)\ntarget_link_libraries(kaldi-lm PUBLIC kaldi-util)"
  },
  {
    "path": "runtime/engine/kaldi/lm/arpa-file-parser.cc",
    "content": "// lm/arpa-file-parser.cc\n\n// Copyright 2014  Guoguo Chen\n// Copyright 2016  Smart Action Company LLC (kkm)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include <fst/fstlib.h>\n\n#include <sstream>\n\n#include \"base/kaldi-error.h\"\n#include \"base/kaldi-math.h\"\n#include \"lm/arpa-file-parser.h\"\n#include \"util/text-utils.h\"\n\nnamespace kaldi {\n\nArpaFileParser::ArpaFileParser(const ArpaParseOptions& options,\n                               fst::SymbolTable* symbols)\n    : options_(options), symbols_(symbols),\n      line_number_(0), warning_count_(0) {\n}\n\nArpaFileParser::~ArpaFileParser() {\n}\n\nvoid TrimTrailingWhitespace(std::string *str) {\n  str->erase(str->find_last_not_of(\" \\n\\r\\t\") + 1);\n}\n\nvoid ArpaFileParser::Read(std::istream &is) {\n  // Argument sanity checks.\n  if (options_.bos_symbol <= 0 || options_.eos_symbol <= 0 ||\n      options_.bos_symbol == options_.eos_symbol)\n    KALDI_ERR << \"BOS and EOS symbols are required, must not be epsilons, and \"\n              << \"differ from each other. Given:\"\n              << \" BOS=\" << options_.bos_symbol\n              << \" EOS=\" << options_.eos_symbol;\n  if (symbols_ != NULL &&\n      options_.oov_handling == ArpaParseOptions::kReplaceWithUnk &&\n      (options_.unk_symbol <= 0 ||\n       options_.unk_symbol == options_.bos_symbol ||\n       options_.unk_symbol == options_.eos_symbol))\n    KALDI_ERR << \"When symbol table is given and OOV mode is kReplaceWithUnk, \"\n              << \"UNK symbol is required, must not be epsilon, and \"\n              << \"differ from both BOS and EOS symbols. Given:\"\n              << \" UNK=\" << options_.unk_symbol\n              << \" BOS=\" << options_.bos_symbol\n              << \" EOS=\" << options_.eos_symbol;\n  if (symbols_ != NULL && symbols_->Find(options_.bos_symbol).empty())\n    KALDI_ERR << \"BOS symbol must exist in symbol table\";\n  if (symbols_ != NULL && symbols_->Find(options_.eos_symbol).empty())\n    KALDI_ERR << \"EOS symbol must exist in symbol table\";\n  if (symbols_ != NULL && options_.unk_symbol > 0 &&\n      symbols_->Find(options_.unk_symbol).empty())\n    KALDI_ERR << \"UNK symbol must exist in symbol table\";\n\n  ngram_counts_.clear();\n  line_number_ = 0;\n  warning_count_ = 0;\n  current_line_.clear();\n\n#define PARSE_ERR KALDI_ERR << LineReference() << \": \"\n\n  // Give derived class an opportunity to prepare its state.\n  ReadStarted();\n\n  // Processes \"\\data\\\" section.\n  bool keyword_found = false;\n  while (++line_number_, getline(is, current_line_) && !is.eof()) {\n    if (current_line_.find_first_not_of(\" \\t\\n\\r\") == std::string::npos) {\n      continue;\n    }\n\n    TrimTrailingWhitespace(&current_line_);\n\n    // Continue skipping lines until the \\data\\ marker alone on a line is found.\n    if (!keyword_found) {\n      if (current_line_ == \"\\\\data\\\\\") {\n        KALDI_LOG << \"Reading \\\\data\\\\ section.\";\n        keyword_found = true;\n      }\n      continue;\n    }\n\n    if (current_line_[0] == '\\\\') break;\n\n    // Enters \"\\data\\\" section, and looks for patterns like \"ngram 1=1000\",\n    // which means there are 1000 unigrams.\n    std::size_t equal_symbol_pos = current_line_.find(\"=\");\n    if (equal_symbol_pos != std::string::npos)\n      // Guaranteed spaces around the \"=\".\n      current_line_.replace(equal_symbol_pos, 1, \" = \");\n    std::vector<std::string> col;\n    SplitStringToVector(current_line_, \" \\t\", true, &col);\n    if (col.size() == 4 && col[0] == \"ngram\" && col[2] == \"=\") {\n      int32 order, ngram_count = 0;\n      if (!ConvertStringToInteger(col[1], &order) ||\n          !ConvertStringToInteger(col[3], &ngram_count)) {\n        PARSE_ERR << \"cannot parse ngram count\";\n      }\n      if (ngram_counts_.size() <= order) {\n        ngram_counts_.resize(order);\n      }\n      ngram_counts_[order - 1] = ngram_count;\n    } else {\n      KALDI_WARN << LineReference()\n                 << \": uninterpretable line in \\\\data\\\\ section\";\n    }\n  }\n\n  if (ngram_counts_.size() == 0)\n    PARSE_ERR << \"\\\\data\\\\ section missing or empty.\";\n\n  // Signal that grammar order and n-gram counts are known.\n  HeaderAvailable();\n\n  NGram ngram;\n  ngram.words.reserve(ngram_counts_.size());\n\n  // Processes \"\\N-grams:\" section.\n  for (int32 cur_order = 1; cur_order <= ngram_counts_.size(); ++cur_order) {\n    // Skips n-grams with zero count.\n    if (ngram_counts_[cur_order - 1] == 0)\n      KALDI_WARN << \"Zero ngram count in ngram order \" << cur_order\n                 << \"(look for 'ngram \" << cur_order << \"=0' in the \\\\data\\\\ \"\n                 << \" section). There is possibly a problem with the file.\";\n\n    // Must be looking at a \\k-grams: directive at this point.\n    std::ostringstream keyword;\n    keyword << \"\\\\\" << cur_order << \"-grams:\";\n    if (current_line_ != keyword.str()) {\n      PARSE_ERR << \"invalid directive, expecting '\" << keyword.str() << \"'\";\n    }\n    KALDI_LOG << \"Reading \" << current_line_ << \" section.\";\n\n    int32 ngram_count = 0;\n    while (++line_number_, getline(is, current_line_) && !is.eof()) {\n      if (current_line_.find_first_not_of(\" \\n\\t\\r\") == std::string::npos) {\n        continue;\n      }\n      if (current_line_[0] == '\\\\') {\n        TrimTrailingWhitespace(&current_line_);\n        std::ostringstream next_keyword;\n        next_keyword << \"\\\\\" << cur_order + 1 << \"-grams:\";\n        if ((current_line_ != next_keyword.str()) &&\n            (current_line_ != \"\\\\end\\\\\")) {\n          if (ShouldWarn()) {\n            KALDI_WARN << \"ignoring possible directive '\" << current_line_\n                       << \"' expecting '\" << next_keyword.str() << \"'\";\n\n            if (warning_count_ > 0 &&\n                warning_count_ > static_cast<uint32>(options_.max_warnings)) {\n              KALDI_WARN << \"Of \" << warning_count_ << \" parse warnings, \"\n                         << options_.max_warnings << \" were reported. \"\n                         << \"Run program with --max-arpa-warnings=-1 \"\n                         << \"to see all warnings\";\n            }\n          }\n        } else {\n          break;\n        }\n      }\n\n      std::vector<std::string> col;\n      SplitStringToVector(current_line_, \" \\t\", true, &col);\n\n      if (col.size() < 1 + cur_order ||\n          col.size() > 2 + cur_order ||\n          (cur_order == ngram_counts_.size() && col.size() != 1 + cur_order)) {\n        PARSE_ERR << \"Invalid n-gram data line\";\n      }\n      ++ngram_count;\n\n      // Parse out n-gram logprob and, if present, backoff weight.\n      if (!ConvertStringToReal(col[0], &ngram.logprob)) {\n        PARSE_ERR << \"invalid n-gram logprob '\" << col[0] << \"'\";\n      }\n      ngram.backoff = 0.0;\n      if (col.size() > cur_order + 1) {\n        if (!ConvertStringToReal(col[cur_order + 1], &ngram.backoff))\n          PARSE_ERR << \"invalid backoff weight '\" << col[cur_order + 1] << \"'\";\n      }\n      // Convert to natural log.\n      ngram.logprob *= M_LN10;\n      ngram.backoff *= M_LN10;\n\n      ngram.words.resize(cur_order);\n      bool skip_ngram = false;\n      for (int32 index = 0; !skip_ngram && index < cur_order; ++index) {\n        int32 word;\n        if (symbols_) {\n          // Symbol table provided, so symbol labels are expected.\n          if (options_.oov_handling == ArpaParseOptions::kAddToSymbols) {\n            word = symbols_->AddSymbol(col[1 + index]);\n          } else {\n            word = symbols_->Find(col[1 + index]);\n            if (word == -1) { // fst::kNoSymbol\n              switch (options_.oov_handling) {\n                case ArpaParseOptions::kReplaceWithUnk:\n                  word = options_.unk_symbol;\n                  break;\n                case ArpaParseOptions::kSkipNGram:\n                  if (ShouldWarn())\n                    KALDI_WARN << LineReference() << \" skipped: word '\"\n                               << col[1 + index] << \"' not in symbol table\";\n                  skip_ngram = true;\n                  break;\n                default:\n                  PARSE_ERR << \"word '\"  << col[1 + index]\n                            << \"' not in symbol table\";\n              }\n            }\n          }\n        } else {\n          // Symbols not provided, LM file should contain integers.\n          if (!ConvertStringToInteger(col[1 + index], &word) || word < 0) {\n            PARSE_ERR << \"invalid symbol '\" << col[1 + index] << \"'\";\n          }\n        }\n        // Whichever way we got it, an epsilon is invalid.\n        if (word == 0) {\n          PARSE_ERR << \"epsilon symbol '\" << col[1 + index]\n                    << \"' is illegal in ARPA LM\";\n        }\n        ngram.words[index] = word;\n      }\n      if (!skip_ngram) {\n        ConsumeNGram(ngram);\n      }\n    }\n    if (ngram_count > ngram_counts_[cur_order - 1]) {\n      PARSE_ERR << \"header said there would be \" << ngram_counts_[cur_order - 1]\n                << \" n-grams of order \" << cur_order\n                << \", but we saw more already.\";\n    }\n  }\n\n  if (current_line_ != \"\\\\end\\\\\") {\n    PARSE_ERR << \"invalid or unexpected directive line, expecting \\\\end\\\\\";\n  }\n\n  if (warning_count_ > 0 &&\n      warning_count_ > static_cast<uint32>(options_.max_warnings)) {\n    KALDI_WARN << \"Of \" << warning_count_ << \" parse warnings, \"\n               << options_.max_warnings << \" were reported. Run program with \"\n               << \"--max-arpa-warnings=-1 to see all warnings\";\n  }\n\n  current_line_.clear();\n  ReadComplete();\n\n#undef PARSE_ERR\n}\n\nstd::string ArpaFileParser::LineReference() const {\n  std::ostringstream ss;\n  ss << \"line \" << line_number_ << \" [\" << current_line_ << \"]\";\n  return ss.str();\n}\n\nbool ArpaFileParser::ShouldWarn() {\n  return (warning_count_ != -1) &&\n    (++warning_count_ <= static_cast<uint32>(options_.max_warnings));\n}\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/lm/arpa-file-parser.h",
    "content": "// lm/arpa-file-parser.h\n\n// Copyright 2014  Guoguo Chen\n// Copyright 2016  Smart Action Company LLC (kkm)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_LM_ARPA_FILE_PARSER_H_\n#define KALDI_LM_ARPA_FILE_PARSER_H_\n\n#include <fst/fst-decl.h>\n\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-types.h\"\n#include \"util/options-itf.h\"\n\nnamespace kaldi {\n\n/**\n  Options that control ArpaFileParser\n*/\nstruct ArpaParseOptions {\n  enum OovHandling {\n    kRaiseError,     ///< Abort on OOV words\n    kAddToSymbols,   ///< Add novel words to the symbol table.\n    kReplaceWithUnk,  ///< Replace OOV words with <unk>.\n    kSkipNGram       ///< Skip n-gram with OOV word and continue.\n  };\n\n  ArpaParseOptions():\n      bos_symbol(-1), eos_symbol(-1), unk_symbol(-1),\n      oov_handling(kRaiseError), max_warnings(30) { }\n\n  void Register(OptionsItf *opts) {\n    // Registering only the max_warnings count, since other options are\n    // treated differently by client programs: some want integer symbols,\n    // while other are passed words in their command line.\n    opts->Register(\"max-arpa-warnings\", &max_warnings,\n                   \"Maximum warnings to report on ARPA parsing, \"\n                   \"0 to disable, -1 to show all\");\n  }\n\n  int32 bos_symbol;  ///< Symbol for <s>, Required non-epsilon.\n  int32 eos_symbol;  ///< Symbol for </s>, Required non-epsilon.\n  int32 unk_symbol;  ///< Symbol for <unk>, Required for kReplaceWithUnk.\n  OovHandling oov_handling;  ///< How to handle OOV words in the file.\n  int32 max_warnings;  ///< Maximum warnings to report, <0 unlimited.\n};\n\n/**\n   A parsed n-gram from ARPA LM file.\n*/\nstruct NGram {\n  NGram() : logprob(0.0), backoff(0.0) { }\n  std::vector<int32> words;  ///< Symbols in left to right order.\n  float logprob;             ///< Log-prob of the n-gram.\n  float backoff;             ///< log-backoff weight of the n-gram.\n                             ///< Defaults to zero if not specified.\n};\n\n/**\n    ArpaFileParser is an abstract base class for ARPA LM file conversion.\n\n    See ConstArpaLmBuilder and ArpaLmCompiler for usage examples.\n*/\nclass ArpaFileParser {\n public:\n  /// Constructs the parser with the given options and optional symbol table.\n  /// If symbol table is provided, then the file should contain text n-grams,\n  /// and the words are mapped to symbols through it. bos_symbol and\n  /// eos_symbol in the options structure must be valid symbols in the table,\n  /// and so must be unk_symbol if provided. The table is not owned by the\n  /// parser, but may be augmented, if oov_handling is set to kAddToSymbols.\n  /// If symbol table is a null pointer, the file should contain integer\n  /// symbol values, and oov_handling has no effect. bos_symbol and eos_symbol\n  /// must be valid symbols still.\n  ArpaFileParser(const ArpaParseOptions& options, fst::SymbolTable* symbols);\n  virtual ~ArpaFileParser();\n\n  /// Read ARPA LM file from a stream.\n  void Read(std::istream &is);\n\n  /// Parser options.\n  const ArpaParseOptions& Options() const { return options_; }\n\n protected:\n  /// Override called before reading starts. This is the point to prepare\n  /// any state in the derived class.\n  virtual void ReadStarted() { }\n\n  /// Override function called to signal that ARPA header with the expected\n  /// number of n-grams has been read, and ngram_counts() is now valid.\n  virtual void HeaderAvailable() { }\n\n  /// Pure override that must be implemented to process current n-gram. The\n  /// n-grams are sent in the file order, which guarantees that all\n  /// (k-1)-grams are processed before the first k-gram is.\n  virtual void ConsumeNGram(const NGram&) = 0;\n\n  /// Override function called after the last n-gram has been consumed.\n  virtual void ReadComplete() { }\n\n  /// Read-only access to symbol table. Not owned, do not make public.\n  const fst::SymbolTable* Symbols() const { return symbols_; }\n\n  /// Inside ConsumeNGram(), provides the current line number.\n  int32 LineNumber() const { return line_number_; }\n\n  /// Inside ConsumeNGram(), returns a formatted reference to the line being\n  /// compiled, to print out as part of diagnostics.\n  std::string LineReference() const;\n\n  /// Increments warning count, and returns true if a warning should be\n  /// printed or false if the count has exceeded the set maximum.\n  bool ShouldWarn();\n\n  /// N-gram counts. Valid from the point when HeaderAvailable() is called.\n  const std::vector<int32>& NgramCounts() const { return ngram_counts_; }\n\n private:\n  ArpaParseOptions options_;\n  fst::SymbolTable* symbols_;  // the pointer is not owned here.\n  int32 line_number_;\n  uint32 warning_count_;\n  std::string current_line_;\n  std::vector<int32> ngram_counts_;\n};\n\n}  // namespace kaldi\n\n#endif  // KALDI_LM_ARPA_FILE_PARSER_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/lm/arpa-lm-compiler.cc",
    "content": "// lm/arpa-lm-compiler.cc\n\n// Copyright 2009-2011 Gilles Boulianne\n// Copyright 2016 Smart Action LLC (kkm)\n// Copyright 2017 Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <limits>\n#include <sstream>\n#include <utility>\n\n#include \"base/kaldi-math.h\"\n#include \"lm/arpa-lm-compiler.h\"\n#include \"util/stl-utils.h\"\n#include \"util/text-utils.h\"\n#include \"fstext/remove-eps-local.h\"\n\nnamespace kaldi {\n\nclass ArpaLmCompilerImplInterface {\n public:\n  virtual ~ArpaLmCompilerImplInterface() { }\n  virtual void ConsumeNGram(const NGram& ngram, bool is_highest) = 0;\n};\n\nnamespace {\n\ntypedef int32 StateId;\ntypedef int32 Symbol;\n\n// GeneralHistKey can represent state history in an arbitrarily large n\n// n-gram model with symbol ids fitting int32.\nclass GeneralHistKey {\n public:\n  // Construct key from being and end iterators.\n  template<class InputIt>\n  GeneralHistKey(InputIt begin, InputIt end) : vector_(begin, end) { }\n  // Construct empty history key.\n  GeneralHistKey() : vector_() { }\n  // Return tails of the key as a GeneralHistKey. The tails of an n-gram\n  // w[1..n] is the sequence w[2..n] (and the heads is w[1..n-1], but the\n  // key class does not need this operartion).\n  GeneralHistKey Tails() const {\n    return GeneralHistKey(vector_.begin() + 1, vector_.end());\n  }\n  // Keys are equal if represent same state.\n  friend bool operator==(const GeneralHistKey& a, const GeneralHistKey& b) {\n    return a.vector_ == b.vector_;\n  }\n  // Public typename HashType for hashing.\n  struct HashType : public std::unary_function<GeneralHistKey, size_t> {\n    size_t operator()(const GeneralHistKey& key) const {\n      return VectorHasher<Symbol>().operator()(key.vector_);\n    }\n  };\n\n private:\n  std::vector<Symbol> vector_;\n};\n\n// OptimizedHistKey combines 3 21-bit symbol ID values into one 64-bit\n// machine word. allowing significant memory reduction and some runtime\n// benefit over GeneralHistKey. Since 3 symbols are enough to track history\n// in a 4-gram model, this optimized key is used for smaller models with up\n// to 4-gram and symbol values up to 2^21-1.\n//\n// See GeneralHistKey for interface requirements of a key class.\nclass OptimizedHistKey {\n public:\n  enum {\n    kShift = 21,  // 21 * 3 = 63 bits for data.\n    kMaxData = (1 << kShift) - 1\n  };\n  template<class InputIt>\n  OptimizedHistKey(InputIt begin, InputIt end) : data_(0) {\n    for (uint32 shift = 0; begin != end; ++begin, shift += kShift) {\n      data_ |= static_cast<uint64>(*begin) << shift;\n    }\n  }\n  OptimizedHistKey() : data_(0) { }\n  OptimizedHistKey Tails() const {\n    return OptimizedHistKey(data_ >> kShift);\n  }\n  friend bool operator==(const OptimizedHistKey& a, const OptimizedHistKey& b) {\n    return a.data_ == b.data_;\n  }\n  struct HashType : public std::unary_function<OptimizedHistKey, size_t> {\n    size_t operator()(const OptimizedHistKey& key) const { return key.data_; }\n  };\n\n private:\n  explicit OptimizedHistKey(uint64 data) : data_(data) { }\n  uint64 data_;\n};\n\n}  // namespace\n\ntemplate <class HistKey>\nclass ArpaLmCompilerImpl : public ArpaLmCompilerImplInterface {\n public:\n  ArpaLmCompilerImpl(ArpaLmCompiler* parent, fst::StdVectorFst* fst,\n                     Symbol sub_eps);\n\n  virtual void ConsumeNGram(const NGram &ngram, bool is_highest);\n\n private:\n  StateId AddStateWithBackoff(HistKey key, float backoff);\n  void CreateBackoff(HistKey key, StateId state, float weight);\n\n  ArpaLmCompiler *parent_;  // Not owned.\n  fst::StdVectorFst* fst_;  // Not owned.\n  Symbol bos_symbol_;\n  Symbol eos_symbol_;\n  Symbol sub_eps_;\n\n  StateId eos_state_;\n  typedef unordered_map<HistKey, StateId,\n                        typename HistKey::HashType> HistoryMap;\n  HistoryMap history_;\n};\n\ntemplate <class HistKey>\nArpaLmCompilerImpl<HistKey>::ArpaLmCompilerImpl(\n    ArpaLmCompiler* parent, fst::StdVectorFst* fst, Symbol sub_eps)\n    : parent_(parent), fst_(fst), bos_symbol_(parent->Options().bos_symbol),\n      eos_symbol_(parent->Options().eos_symbol), sub_eps_(sub_eps) {\n  // The algorithm maintains state per history. The 0-gram is a special state\n  // for empty history. All unigrams (including BOS) backoff into this state.\n  StateId zerogram = fst_->AddState();\n  history_[HistKey()] = zerogram;\n\n  // Also, if </s> is not treated as epsilon, create a common end state for\n  // all transitions accepting the </s>, since they do not back off. This small\n  // optimization saves about 2% states in an average grammar.\n  if (sub_eps_ == 0) {\n    eos_state_ = fst_->AddState();\n    fst_->SetFinal(eos_state_, 0);\n  }\n}\n\ntemplate <class HistKey>\nvoid ArpaLmCompilerImpl<HistKey>::ConsumeNGram(const NGram &ngram,\n                                               bool is_highest) {\n  // Generally, we do the following. Suppose we are adding an n-gram \"A B\n  // C\". Then find the node for \"A B\", add a new node for \"A B C\", and connect\n  // them with the arc accepting \"C\" with the specified weight. Also, add a\n  // backoff arc from the new \"A B C\" node to its backoff state \"B C\".\n  //\n  // Two notable exceptions are the highest order n-grams, and final n-grams.\n  //\n  // When adding a highest order n-gram (e. g., our \"A B C\" is in a 3-gram LM),\n  // the following optimization is performed. There is no point adding a node\n  // for \"A B C\" with a \"C\" arc from \"A B\", since there will be no other\n  // arcs ingoing to this node, and an epsilon backoff arc into the backoff\n  // model \"B C\", with the weight of \\bar{1}. To save a node, create an arc\n  // accepting \"C\" directly from \"A B\" to \"B C\". This saves as many nodes\n  // as there are the highest order n-grams, which is typically about half\n  // the size of a large 3-gram model.\n  //\n  // Indeed, this does not apply to n-grams ending in EOS, since they do not\n  // back off. These are special, as they do not have a back-off state, and\n  // the node for \"(..anything..) </s>\" is always final. These are handled\n  // in one of the two possible ways, If symbols <s> and </s> are being\n  // replaced by epsilons, neither node nor arc is created, and the logprob\n  // of the n-gram is applied to its source node as final weight. If <s> and\n  // </s> are preserved, then a special final node for </s> is allocated and\n  // used as the destination of the \"</s>\" acceptor arc.\n  HistKey heads(ngram.words.begin(), ngram.words.end() - 1);\n  typename HistoryMap::iterator source_it = history_.find(heads);\n  if (source_it == history_.end()) {\n    // There was no \"A B\", therefore the probability of \"A B C\" is zero.\n    // Print a warning and discard current n-gram.\n    if (parent_->ShouldWarn())\n      KALDI_WARN << parent_->LineReference()\n                 << \" skipped: no parent (n-1)-gram exists\";\n    return;\n  }\n\n  StateId source = source_it->second;\n  StateId dest;\n  Symbol sym = ngram.words.back();\n  float weight = -ngram.logprob;\n  if (sym == sub_eps_ || sym == 0) {\n    KALDI_ERR << \" <eps> or disambiguation symbol \" << sym << \"found in the ARPA file. \";\n  }\n  if (sym == eos_symbol_) {\n    if (sub_eps_ == 0) {\n      // Keep </s> as a real symbol when not substituting.\n      dest = eos_state_;\n    } else {\n      // Treat </s> as if it was epsilon: mark source final, with the weight\n      // of the n-gram.\n      fst_->SetFinal(source, weight);\n      return;\n    }\n  } else {\n    // For the highest order n-gram, this may find an existing state, for\n    // non-highest, will create one (unless there are duplicate n-grams\n    // in the grammar, which cannot be reliably detected if highest order,\n    // so we better do not do that at all).\n    dest = AddStateWithBackoff(\n        HistKey(ngram.words.begin() + (is_highest ? 1 : 0),\n                ngram.words.end()),\n        -ngram.backoff);\n  }\n\n  if (sym == bos_symbol_) {\n    weight = 0;  // Accepting <s> is always free.\n    if (sub_eps_ == 0) {\n      // <s> is as a real symbol, only accepted in the start state.\n      source = fst_->AddState();\n      fst_->SetStart(source);\n    } else {\n      // The new state for <s> unigram history *is* the start state.\n      fst_->SetStart(dest);\n      return;\n    }\n  }\n\n  // Add arc from source to dest, whichever way it was found.\n  fst_->AddArc(source, fst::StdArc(sym, sym, weight, dest));\n  return;\n}\n\n// Find or create a new state for n-gram defined by key, and ensure it has a\n// backoff transition.  The key is either the current n-gram for all but\n// highest orders, or the tails of the n-gram for the highest order. The\n// latter arises from the chain-collapsing optimization described above.\ntemplate <class HistKey>\nStateId ArpaLmCompilerImpl<HistKey>::AddStateWithBackoff(HistKey key,\n                                                         float backoff) {\n  typename HistoryMap::iterator dest_it = history_.find(key);\n  if (dest_it != history_.end()) {\n    // Found an existing state in the history map. Invariant: if the state in\n    // the map, then its backoff arc is in the FST. We are done.\n    return dest_it->second;\n  }\n  // Otherwise create a new state and its backoff arc, and register in the map.\n  StateId dest = fst_->AddState();\n  history_[key] = dest;\n  CreateBackoff(key.Tails(), dest, backoff);\n  return dest;\n}\n\n// Create a backoff arc for a state. Key is a backoff destination that may or\n// may not exist. When the destination is not found, naturally fall back to\n// the lower order model, and all the way down until one is found (since the\n// 0-gram model is always present, the search is guaranteed to terminate).\ntemplate <class HistKey>\ninline void ArpaLmCompilerImpl<HistKey>::CreateBackoff(\n    HistKey key, StateId state, float weight) {\n  typename HistoryMap::iterator dest_it = history_.find(key);\n  while (dest_it == history_.end()) {\n    key = key.Tails();\n    dest_it = history_.find(key);\n  }\n\n  // The arc should transduce either <eos> or #0 to <eps>, depending on the\n  // epsilon substitution mode. This is the only case when input and output\n  // label may differ.\n  fst_->AddArc(state, fst::StdArc(sub_eps_, 0, weight, dest_it->second));\n}\n\nArpaLmCompiler::~ArpaLmCompiler() {\n  if (impl_ != NULL)\n    delete impl_;\n}\n\nvoid ArpaLmCompiler::HeaderAvailable() {\n  KALDI_ASSERT(impl_ == NULL);\n  // Use optimized implementation if the grammar is 4-gram or less, and the\n  // maximum attained symbol id will fit into the optimized range.\n  int64 max_symbol = 0;\n  if (Symbols() != NULL)\n    max_symbol = Symbols()->AvailableKey() - 1;\n  // If augmenting the symbol table, assume the worst case when all words in\n  // the model being read are novel.\n  if (Options().oov_handling == ArpaParseOptions::kAddToSymbols)\n    max_symbol += NgramCounts()[0];\n\n  if (NgramCounts().size() <= 4 && max_symbol < OptimizedHistKey::kMaxData) {\n    impl_ = new ArpaLmCompilerImpl<OptimizedHistKey>(this, &fst_, sub_eps_);\n  } else {\n    impl_ = new ArpaLmCompilerImpl<GeneralHistKey>(this, &fst_, sub_eps_);\n    KALDI_LOG << \"Reverting to slower state tracking because model is large: \"\n              << NgramCounts().size() << \"-gram with symbols up to \"\n              << max_symbol;\n  }\n}\n\nvoid ArpaLmCompiler::ConsumeNGram(const NGram &ngram) {\n  // <s> is invalid in tails, </s> in heads of an n-gram.\n  for (int i = 0; i < ngram.words.size(); ++i) {\n    if ((i > 0 && ngram.words[i] == Options().bos_symbol) ||\n        (i + 1 < ngram.words.size()\n         && ngram.words[i] == Options().eos_symbol)) {\n      if (ShouldWarn())\n        KALDI_WARN << LineReference()\n                   << \" skipped: n-gram has invalid BOS/EOS placement\";\n      return;\n    }\n  }\n\n  bool is_highest = ngram.words.size() == NgramCounts().size();\n  impl_->ConsumeNGram(ngram, is_highest);\n}\n\nvoid ArpaLmCompiler::RemoveRedundantStates() {\n  fst::StdArc::Label backoff_symbol = sub_eps_;\n  if (backoff_symbol == 0) {\n    // The method of removing redundant states implemented in this function\n    // leads to slow determinization of L o G when people use the older style of\n    // usage of arpa2fst where the --disambig-symbol option was not specified.\n    // The issue seems to be that it creates a non-deterministic FST, while G is\n    // supposed to be deterministic.  By 'return'ing below, we just disable this\n    // method if people were using an older script.  This method isn't really\n    // that consequential anyway, and people will move to the newer-style\n    // scripts (see current utils/format_lm.sh), so this isn't much of a\n    // problem.\n    return;\n  }\n\n  fst::StdArc::StateId num_states = fst_.NumStates();\n\n\n  // replace the #0 symbols on the input of arcs out of redundant states (states\n  // that are not final and have only a backoff arc leaving them), with <eps>.\n  for (fst::StdArc::StateId state = 0; state < num_states; state++) {\n    if (fst_.NumArcs(state) == 1 && fst_.Final(state) == fst::TropicalWeight::Zero()) {\n      fst::MutableArcIterator<fst::StdVectorFst> iter(&fst_, state);\n      fst::StdArc arc = iter.Value();\n      if (arc.ilabel == backoff_symbol) {\n        arc.ilabel = 0;\n        iter.SetValue(arc);\n      }\n    }\n  }\n\n  // we could call fst::RemoveEps, and it would have the same effect in normal\n  // cases, where backoff_symbol != 0 and there are no epsilons in unexpected\n  // places, but RemoveEpsLocal is a bit safer in case something weird is going\n  // on; it guarantees not to blow up the FST.\n  fst::RemoveEpsLocal(&fst_);\n  KALDI_LOG << \"Reduced num-states from \" << num_states << \" to \"\n            << fst_.NumStates();\n}\n\nvoid ArpaLmCompiler::Check() const {\n  if (fst_.Start() == fst::kNoStateId) {\n    KALDI_ERR << \"Arpa file did not contain the beginning-of-sentence symbol \"\n              << Symbols()->Find(Options().bos_symbol) << \".\";\n  }\n}\n\nvoid ArpaLmCompiler::ReadComplete() {\n  fst_.SetInputSymbols(Symbols());\n  fst_.SetOutputSymbols(Symbols());\n  RemoveRedundantStates();\n  Check();\n}\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/lm/arpa-lm-compiler.h",
    "content": "// lm/arpa-lm-compiler.h\n\n// Copyright 2009-2011 Gilles Boulianne\n// Copyright 2016 Smart Action LLC (kkm)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_LM_ARPA_LM_COMPILER_H_\n#define KALDI_LM_ARPA_LM_COMPILER_H_\n\n#include <fst/fstlib.h>\n\n#include \"lm/arpa-file-parser.h\"\n\nnamespace kaldi {\n\nclass ArpaLmCompilerImplInterface;\n\nclass ArpaLmCompiler : public ArpaFileParser {\n public:\n  ArpaLmCompiler(const ArpaParseOptions& options, int sub_eps,\n                 fst::SymbolTable* symbols)\n      : ArpaFileParser(options, symbols),\n        sub_eps_(sub_eps), impl_(NULL) {\n  }\n  ~ArpaLmCompiler();\n\n  const fst::StdVectorFst& Fst() const { return fst_; }\n  fst::StdVectorFst* MutableFst() { return &fst_; }\n\n protected:\n  // ArpaFileParser overrides.\n  virtual void HeaderAvailable();\n  virtual void ConsumeNGram(const NGram& ngram);\n  virtual void ReadComplete();\n\n\n private:\n  // this function removes states that only have a backoff arc coming\n  // out of them.\n  void RemoveRedundantStates();\n  void Check() const;\n\n  int sub_eps_;\n  ArpaLmCompilerImplInterface* impl_;  // Owned.\n  fst::StdVectorFst fst_;\n  template <class HistKey> friend class ArpaLmCompilerImpl;\n};\n\n}  // namespace kaldi\n\n#endif  // KALDI_LM_ARPA_LM_COMPILER_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/lmbin/CMakeLists.txt",
    "content": "\nadd_executable(arpa2fst ${CMAKE_CURRENT_SOURCE_DIR}/arpa2fst.cc)\ntarget_include_directories(arpa2fst PRIVATE ${SPEECHX_ROOT} ${SPEECHX_ROOT}/kaldi)\ntarget_link_libraries(arpa2fst PUBLIC kaldi-lm glog gflags fst)\n"
  },
  {
    "path": "runtime/engine/kaldi/lmbin/arpa2fst.cc",
    "content": "// bin/arpa2fst.cc\n//\n// Copyright 2009-2011  Gilles Boulianne.\n//\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABILITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"lm/arpa-lm-compiler.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/parse-options.h\"\n\nint main(int argc, char *argv[]) {\n    using namespace kaldi;  // NOLINT\n    try {\n        const char *usage =\n            \"Convert an ARPA format language model into an FST\\n\"\n            \"Usage: arpa2fst [opts] <input-arpa> <output-fst>\\n\"\n            \" e.g.: arpa2fst --disambig-symbol=#0 --read-symbol-table=\"\n            \"data/lang/words.txt lm/input.arpa G.fst\\n\\n\"\n            \"Note: When called without switches, the output G.fst will \"\n            \"contain\\n\"\n            \"an embedded symbol table. This is compatible with the way a \"\n            \"previous\\n\"\n            \"version of arpa2fst worked.\\n\";\n\n        ParseOptions po(usage);\n\n        ArpaParseOptions options;\n        options.Register(&po);\n\n        // Option flags.\n        std::string bos_symbol = \"<s>\";\n        std::string eos_symbol = \"</s>\";\n        std::string disambig_symbol;\n        std::string read_syms_filename;\n        std::string write_syms_filename;\n        bool keep_symbols = false;\n        bool ilabel_sort = true;\n\n        po.Register(\"bos-symbol\", &bos_symbol, \"Beginning of sentence symbol\");\n        po.Register(\"eos-symbol\", &eos_symbol, \"End of sentence symbol\");\n        po.Register(\n            \"disambig-symbol\",\n            &disambig_symbol,\n            \"Disambiguator. If provided (e. g. #0), used on input side of \"\n            \"backoff links, and <s> and </s> are replaced with epsilons\");\n        po.Register(\"read-symbol-table\",\n                    &read_syms_filename,\n                    \"Use existing symbol table\");\n        po.Register(\"write-symbol-table\",\n                    &write_syms_filename,\n                    \"Write generated symbol table to a file\");\n        po.Register(\n            \"keep-symbols\",\n            &keep_symbols,\n            \"Store symbol table with FST. Symbols always saved to FST if \"\n            \"symbol tables are neither read or written (otherwise symbols \"\n            \"would be lost entirely)\");\n        po.Register(\"ilabel-sort\", &ilabel_sort, \"Ilabel-sort the output FST\");\n\n        po.Read(argc, argv);\n\n        if (po.NumArgs() != 1 && po.NumArgs() != 2) {\n            po.PrintUsage();\n            exit(1);\n        }\n        std::string arpa_rxfilename = po.GetArg(1),\n                    fst_wxfilename = po.GetOptArg(2);\n\n        int64 disambig_symbol_id = 0;\n\n        fst::SymbolTable *symbols;\n        if (!read_syms_filename.empty()) {\n            // Use existing symbols. Required symbols must be in the table.\n            kaldi::Input kisym(read_syms_filename);\n            symbols = fst::SymbolTable::ReadText(\n                kisym.Stream(), PrintableWxfilename(read_syms_filename));\n            if (symbols == NULL)\n                KALDI_ERR << \"Could not read symbol table from file \"\n                          << read_syms_filename;\n\n            options.oov_handling = ArpaParseOptions::kSkipNGram;\n            if (!disambig_symbol.empty()) {\n                disambig_symbol_id = symbols->Find(disambig_symbol);\n                if (disambig_symbol_id == -1)  // fst::kNoSymbol\n                    KALDI_ERR << \"Symbol table \" << read_syms_filename\n                              << \" has no symbol for \" << disambig_symbol;\n            }\n        } else {\n            // Create a new symbol table and populate it from ARPA file.\n            symbols = new fst::SymbolTable(PrintableWxfilename(fst_wxfilename));\n            options.oov_handling = ArpaParseOptions::kAddToSymbols;\n            symbols->AddSymbol(\"<eps>\", 0);\n            if (!disambig_symbol.empty()) {\n                disambig_symbol_id = symbols->AddSymbol(disambig_symbol);\n            }\n        }\n\n        // Add or use existing BOS and EOS.\n        options.bos_symbol = symbols->AddSymbol(bos_symbol);\n        options.eos_symbol = symbols->AddSymbol(eos_symbol);\n\n        // If producing new (not reading existing) symbols and not saving them,\n        // need to keep symbols with FST, otherwise they would be lost.\n        if (read_syms_filename.empty() && write_syms_filename.empty())\n            keep_symbols = true;\n\n        // Actually compile LM.\n        KALDI_ASSERT(symbols != NULL);\n        ArpaLmCompiler lm_compiler(options, disambig_symbol_id, symbols);\n        {\n            Input ki(arpa_rxfilename);\n            lm_compiler.Read(ki.Stream());\n        }\n\n        // Sort the FST in-place if requested by options.\n        if (ilabel_sort) {\n            fst::ArcSort(lm_compiler.MutableFst(), fst::StdILabelCompare());\n        }\n\n        // Write symbols if requested.\n        if (!write_syms_filename.empty()) {\n            kaldi::Output kosym(write_syms_filename, false);\n            symbols->WriteText(kosym.Stream());\n        }\n\n        // Write LM FST.\n        bool write_binary = true, write_header = false;\n        kaldi::Output kofst(fst_wxfilename, write_binary, write_header);\n        fst::FstWriteOptions wopts(PrintableWxfilename(fst_wxfilename));\n        wopts.write_isymbols = wopts.write_osymbols = keep_symbols;\n        lm_compiler.Fst().Write(kofst.Stream(), wopts);\n\n        delete symbols;\n    } catch (const std::exception &e) {\n        std::cerr << e.what();\n        return -1;\n    }\n}\n"
  },
  {
    "path": "runtime/engine/kaldi/util/CMakeLists.txt",
    "content": "add_library(kaldi-util\n  kaldi-holder.cc\n  kaldi-io.cc\n  kaldi-semaphore.cc\n  kaldi-table.cc\n  kaldi-thread.cc\n  parse-options.cc\n  simple-io-funcs.cc\n  simple-options.cc\n  text-utils.cc\n)\ntarget_link_libraries(kaldi-util PUBLIC kaldi-base kaldi-matrix)"
  },
  {
    "path": "runtime/engine/kaldi/util/basic-filebuf.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// This is a modified version of the std::basic_filebuf from libc++\n// (http://libcxx.llvm.org/).\n// It allows one to create basic_filebuf from an existing FILE* handle or file\n// descriptor.\n//\n// This file is dual licensed under the MIT and the University of Illinois Open\n// Source License licenses. See LICENSE.TXT for details (included at the\n// bottom).\n///////////////////////////////////////////////////////////////////////////////\n#ifndef KALDI_UTIL_BASIC_FILEBUF_H_\n#define KALDI_UTIL_BASIC_FILEBUF_H_\n\n///////////////////////////////////////////////////////////////////////////////\n#include <fstream>\n#include <cstdio>\n#include <cstring>\n#include <string>\n#include <algorithm>\n\n///////////////////////////////////////////////////////////////////////////////\nnamespace kaldi {\n///////////////////////////////////////////////////////////////////////////////\ntemplate <typename CharT, typename Traits = std::char_traits<CharT> >\nclass basic_filebuf : public std::basic_streambuf<CharT, Traits> {\n public:\n    typedef CharT                            char_type;\n    typedef Traits                           traits_type;\n    typedef typename traits_type::int_type   int_type;\n    typedef typename traits_type::pos_type   pos_type;\n    typedef typename traits_type::off_type   off_type;\n    typedef typename traits_type::state_type state_type;\n\n    basic_filebuf();\n    basic_filebuf(basic_filebuf&& rhs);\n    virtual ~basic_filebuf();\n\n    basic_filebuf& operator=(basic_filebuf&& rhs);\n    void swap(basic_filebuf& rhs);\n\n    bool is_open() const;\n    basic_filebuf* open(const char* s, std::ios_base::openmode mode);\n    basic_filebuf* open(const std::string& s, std::ios_base::openmode mode);\n    basic_filebuf* open(int fd, std::ios_base::openmode mode);\n    basic_filebuf* open(FILE* f, std::ios_base::openmode mode);\n    basic_filebuf* close();\n\n    FILE* file() { return this->_M_file; }\n    int fd() { return fileno(this->_M_file); }\n\n protected:\n    int_type underflow() override;\n    int_type pbackfail(int_type c = traits_type::eof()) override;\n    int_type overflow(int_type c = traits_type::eof()) override;\n    std::basic_streambuf<char_type, traits_type>*\n      setbuf(char_type* s, std::streamsize n) override;\n    pos_type seekoff(off_type off, std::ios_base::seekdir way,\n                     std::ios_base::openmode wch =\n                     std::ios_base::in | std::ios_base::out) override;\n    pos_type seekpos(pos_type sp,\n                     std::ios_base::openmode wch =\n                     std::ios_base::in | std::ios_base::out) override;\n    int sync() override;\n    void imbue(const std::locale& loc) override;\n\n protected:\n    char*       _M_extbuf;\n    const char* _M_extbufnext;\n    const char* _M_extbufend;\n    char _M_extbuf_min[8];\n    size_t _M_ebs;\n    char_type* _M_intbuf;\n    size_t _M_ibs;\n    FILE* _M_file;\n    const std::codecvt<char_type, char, state_type>* _M_cv;\n    state_type _M_st;\n    state_type _M_st_last;\n    std::ios_base::openmode _M_om;\n    std::ios_base::openmode _M_cm;\n    bool _M_owns_eb;\n    bool _M_owns_ib;\n    bool _M_always_noconv;\n\n    const char* _M_get_mode(std::ios_base::openmode mode);\n    bool _M_read_mode();\n    void _M_write_mode();\n};\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>::basic_filebuf()\n    : _M_extbuf(nullptr),\n      _M_extbufnext(nullptr),\n      _M_extbufend(nullptr),\n      _M_ebs(0),\n      _M_intbuf(nullptr),\n      _M_ibs(0),\n      _M_file(nullptr),\n      _M_cv(nullptr),\n      _M_st(),\n      _M_st_last(),\n      _M_om(std::ios_base::openmode(0)),\n      _M_cm(std::ios_base::openmode(0)),\n      _M_owns_eb(false),\n      _M_owns_ib(false),\n      _M_always_noconv(false) {\n    if (std::has_facet<std::codecvt<char_type, char, state_type> >\n        (this->getloc())) {\n        _M_cv = &std::use_facet<std::codecvt<char_type, char, state_type> >\n          (this->getloc());\n        _M_always_noconv = _M_cv->always_noconv();\n    }\n    setbuf(0, 4096);\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>::basic_filebuf(basic_filebuf&& rhs)\n    : std::basic_streambuf<CharT, Traits>(rhs) {\n    if (rhs._M_extbuf == rhs._M_extbuf_min) {\n        _M_extbuf = _M_extbuf_min;\n        _M_extbufnext = _M_extbuf + (rhs._M_extbufnext - rhs._M_extbuf);\n        _M_extbufend = _M_extbuf + (rhs._M_extbufend - rhs._M_extbuf);\n    } else {\n        _M_extbuf = rhs._M_extbuf;\n        _M_extbufnext = rhs._M_extbufnext;\n        _M_extbufend = rhs._M_extbufend;\n    }\n    _M_ebs = rhs._M_ebs;\n    _M_intbuf = rhs._M_intbuf;\n    _M_ibs = rhs._M_ibs;\n    _M_file = rhs._M_file;\n    _M_cv = rhs._M_cv;\n    _M_st = rhs._M_st;\n    _M_st_last = rhs._M_st_last;\n    _M_om = rhs._M_om;\n    _M_cm = rhs._M_cm;\n    _M_owns_eb = rhs._M_owns_eb;\n    _M_owns_ib = rhs._M_owns_ib;\n    _M_always_noconv = rhs._M_always_noconv;\n    if (rhs.pbase()) {\n        if (rhs.pbase() == rhs._M_intbuf)\n            this->setp(_M_intbuf, _M_intbuf + (rhs. epptr() - rhs.pbase()));\n        else\n            this->setp(reinterpret_cast<char_type*>(_M_extbuf),\n                       reinterpret_cast<char_type*>(_M_extbuf)\n                       + (rhs. epptr() - rhs.pbase()));\n        this->pbump(rhs. pptr() - rhs.pbase());\n    } else if (rhs.eback()) {\n        if (rhs.eback() == rhs._M_intbuf)\n            this->setg(_M_intbuf, _M_intbuf + (rhs.gptr() - rhs.eback()),\n                                  _M_intbuf + (rhs.egptr() - rhs.eback()));\n        else\n            this->setg(reinterpret_cast<char_type*>(_M_extbuf),\n                       reinterpret_cast<char_type*>(_M_extbuf) +\n                       (rhs.gptr() - rhs.eback()),\n                       reinterpret_cast<char_type*>(_M_extbuf) +\n                       (rhs.egptr() - rhs.eback()));\n    }\n    rhs._M_extbuf = nullptr;\n    rhs._M_extbufnext = nullptr;\n    rhs._M_extbufend = nullptr;\n    rhs._M_ebs = 0;\n    rhs._M_intbuf = nullptr;\n    rhs._M_ibs = 0;\n    rhs._M_file = nullptr;\n    rhs._M_st = state_type();\n    rhs._M_st_last = state_type();\n    rhs._M_om = std::ios_base::openmode(0);\n    rhs._M_cm = std::ios_base::openmode(0);\n    rhs._M_owns_eb = false;\n    rhs._M_owns_ib = false;\n    rhs.setg(0, 0, 0);\n    rhs.setp(0, 0);\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ninline\nbasic_filebuf<CharT, Traits>&\nbasic_filebuf<CharT, Traits>::operator=(basic_filebuf&& rhs) {\n    close();\n    swap(rhs);\n    return *this;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>::~basic_filebuf() {\n    // try\n    // {\n    //     close();\n    // }\n    // catch (...)\n    // {\n    // }\n    if (_M_owns_eb)\n        delete [] _M_extbuf;\n    if (_M_owns_ib)\n        delete [] _M_intbuf;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nvoid\nbasic_filebuf<CharT, Traits>::swap(basic_filebuf& rhs) {\n    std::basic_streambuf<char_type, traits_type>::swap(rhs);\n    if (_M_extbuf != _M_extbuf_min && rhs._M_extbuf != rhs._M_extbuf_min) {\n        std::swap(_M_extbuf, rhs._M_extbuf);\n        std::swap(_M_extbufnext, rhs._M_extbufnext);\n        std::swap(_M_extbufend, rhs._M_extbufend);\n    } else {\n        ptrdiff_t ln = _M_extbufnext - _M_extbuf;\n        ptrdiff_t le = _M_extbufend - _M_extbuf;\n        ptrdiff_t rn = rhs._M_extbufnext - rhs._M_extbuf;\n        ptrdiff_t re = rhs._M_extbufend - rhs._M_extbuf;\n        if (_M_extbuf == _M_extbuf_min && rhs._M_extbuf != rhs._M_extbuf_min) {\n            _M_extbuf = rhs._M_extbuf;\n            rhs._M_extbuf = rhs._M_extbuf_min;\n        } else if (_M_extbuf != _M_extbuf_min &&\n            rhs._M_extbuf == rhs._M_extbuf_min) {\n            rhs._M_extbuf = _M_extbuf;\n            _M_extbuf = _M_extbuf_min;\n        }\n        _M_extbufnext = _M_extbuf + rn;\n        _M_extbufend = _M_extbuf + re;\n        rhs._M_extbufnext = rhs._M_extbuf + ln;\n        rhs._M_extbufend = rhs._M_extbuf + le;\n    }\n    std::swap(_M_ebs, rhs._M_ebs);\n    std::swap(_M_intbuf, rhs._M_intbuf);\n    std::swap(_M_ibs, rhs._M_ibs);\n    std::swap(_M_file, rhs._M_file);\n    std::swap(_M_cv, rhs._M_cv);\n    std::swap(_M_st, rhs._M_st);\n    std::swap(_M_st_last, rhs._M_st_last);\n    std::swap(_M_om, rhs._M_om);\n    std::swap(_M_cm, rhs._M_cm);\n    std::swap(_M_owns_eb, rhs._M_owns_eb);\n    std::swap(_M_owns_ib, rhs._M_owns_ib);\n    std::swap(_M_always_noconv, rhs._M_always_noconv);\n    if (this->eback() == reinterpret_cast<char_type*>(rhs._M_extbuf_min)) {\n        ptrdiff_t n = this->gptr() - this->eback();\n        ptrdiff_t e = this->egptr() - this->eback();\n        this->setg(reinterpret_cast<char_type*>(_M_extbuf_min),\n                   reinterpret_cast<char_type*>(_M_extbuf_min) + n,\n                   reinterpret_cast<char_type*>(_M_extbuf_min) + e);\n    } else if (this->pbase() ==\n               reinterpret_cast<char_type*>(rhs._M_extbuf_min)) {\n        ptrdiff_t n = this->pptr() - this->pbase();\n        ptrdiff_t e = this->epptr() - this->pbase();\n        this->setp(reinterpret_cast<char_type*>(_M_extbuf_min),\n                   reinterpret_cast<char_type*>(_M_extbuf_min) + e);\n        this->pbump(n);\n    }\n    if (rhs.eback() == reinterpret_cast<char_type*>(_M_extbuf_min)) {\n        ptrdiff_t n = rhs.gptr() - rhs.eback();\n        ptrdiff_t e = rhs.egptr() - rhs.eback();\n        rhs.setg(reinterpret_cast<char_type*>(rhs._M_extbuf_min),\n                 reinterpret_cast<char_type*>(rhs._M_extbuf_min) + n,\n                 reinterpret_cast<char_type*>(rhs._M_extbuf_min) + e);\n    } else if (rhs.pbase() == reinterpret_cast<char_type*>(_M_extbuf_min)) {\n        ptrdiff_t n = rhs.pptr() - rhs.pbase();\n        ptrdiff_t e = rhs.epptr() - rhs.pbase();\n        rhs.setp(reinterpret_cast<char_type*>(rhs._M_extbuf_min),\n                 reinterpret_cast<char_type*>(rhs._M_extbuf_min) + e);\n        rhs.pbump(n);\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ninline\nvoid\nswap(basic_filebuf<CharT, Traits>& x, basic_filebuf<CharT, Traits>& y) {\n    x.swap(y);\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ninline\nbool\nbasic_filebuf<CharT, Traits>::is_open() const {\n    return _M_file != nullptr;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nconst char* basic_filebuf<CharT, Traits>::\n_M_get_mode(std::ios_base::openmode mode) {\n    switch ((mode & ~std::ios_base::ate) | 0) {\n    case std::ios_base::out:\n    case std::ios_base::out | std::ios_base::trunc:\n        return \"w\";\n    case std::ios_base::out | std::ios_base::app:\n    case std::ios_base::app:\n        return \"a\";\n        break;\n    case std::ios_base::in:\n        return \"r\";\n    case std::ios_base::in  | std::ios_base::out:\n        return \"r+\";\n    case std::ios_base::in  | std::ios_base::out | std::ios_base::trunc:\n        return \"w+\";\n    case std::ios_base::in  | std::ios_base::out | std::ios_base::app:\n    case std::ios_base::in  | std::ios_base::app:\n        return \"a+\";\n    case std::ios_base::out | std::ios_base::binary:\n    case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:\n        return \"wb\";\n    case std::ios_base::out | std::ios_base::app | std::ios_base::binary:\n    case std::ios_base::app | std::ios_base::binary:\n        return \"ab\";\n    case std::ios_base::in  | std::ios_base::binary:\n        return \"rb\";\n    case std::ios_base::in  | std::ios_base::out | std::ios_base::binary:\n        return \"r+b\";\n    case std::ios_base::in  | std::ios_base::out | std::ios_base::trunc |\n      std::ios_base::binary:\n        return \"w+b\";\n    case std::ios_base::in  | std::ios_base::out | std::ios_base::app |\n      std::ios_base::binary:\n    case std::ios_base::in  | std::ios_base::app | std::ios_base::binary:\n        return \"a+b\";\n    default:\n        return nullptr;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::\nopen(const char* s, std::ios_base::openmode mode) {\n    basic_filebuf<CharT, Traits>* rt = nullptr;\n    if (_M_file == nullptr) {\n        const char* md= _M_get_mode(mode);\n        if (md) {\n            _M_file = fopen(s, md);\n            if (_M_file) {\n                rt = this;\n                _M_om = mode;\n                if (mode & std::ios_base::ate) {\n                    if (fseek(_M_file, 0, SEEK_END)) {\n                        fclose(_M_file);\n                        _M_file = nullptr;\n                        rt = nullptr;\n                    }\n                }\n            }\n        }\n    }\n    return rt;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ninline\nbasic_filebuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::open(const std::string& s,\n    std::ios_base::openmode mode) {\n    return open(s.c_str(), mode);\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::open(int fd, std::ios_base::openmode mode) {\n    const char* md= this->_M_get_mode(mode);\n    if (md) {\n        this->_M_file= fdopen(fd, md);\n        this->_M_om = mode;\n        return this;\n    } else {\n      return nullptr;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::open(FILE* f, std::ios_base::openmode mode) {\n    this->_M_file = f;\n    this->_M_om = mode;\n    return this;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbasic_filebuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::close() {\n    basic_filebuf<CharT, Traits>* rt = nullptr;\n    if (_M_file) {\n        rt = this;\n        std::unique_ptr<FILE, int(*)(FILE*)> h(_M_file, fclose);\n        if (sync())\n            rt = nullptr;\n        if (fclose(h.release()) == 0)\n            _M_file = nullptr;\n        else\n            rt = nullptr;\n    }\n    return rt;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ntypename basic_filebuf<CharT, Traits>::int_type\nbasic_filebuf<CharT, Traits>::underflow() {\n    if (_M_file == nullptr)\n        return traits_type::eof();\n    bool initial = _M_read_mode();\n    char_type buf;\n    if (this->gptr() == nullptr)\n        this->setg(&buf, &buf+1, &buf+1);\n    const size_t unget_sz = initial ? 0 : std::\n      min<size_t>((this->egptr() - this->eback()) / 2, 4);\n    int_type c = traits_type::eof();\n    if (this->gptr() == this->egptr()) {\n        memmove(this->eback(), this->egptr() - unget_sz,\n            unget_sz * sizeof(char_type));\n        if (_M_always_noconv) {\n            size_t nmemb = static_cast<size_t>\n              (this->egptr() - this->eback() - unget_sz);\n            nmemb = fread(this->eback() + unget_sz, 1, nmemb, _M_file);\n            if (nmemb != 0) {\n                this->setg(this->eback(),\n                           this->eback() + unget_sz,\n                           this->eback() + unget_sz + nmemb);\n                c = traits_type::to_int_type(*this->gptr());\n            }\n        } else {\n            memmove(_M_extbuf, _M_extbufnext, _M_extbufend - _M_extbufnext);\n            _M_extbufnext = _M_extbuf + (_M_extbufend - _M_extbufnext);\n            _M_extbufend = _M_extbuf +\n              (_M_extbuf == _M_extbuf_min ? sizeof(_M_extbuf_min) : _M_ebs);\n            size_t nmemb = std::min(static_cast<size_t>(_M_ibs - unget_sz),\n                                    static_cast<size_t>\n                                    (_M_extbufend - _M_extbufnext));\n            std::codecvt_base::result r;\n            _M_st_last = _M_st;\n            size_t nr = fread(\n                reinterpret_cast<void*>(const_cast<char_type*>(_M_extbufnext)),\n                1, nmemb, _M_file);\n            if (nr != 0) {\n                if (!_M_cv)\n                    throw std::bad_cast();\n                _M_extbufend = _M_extbufnext + nr;\n                char_type*  inext;\n                r = _M_cv->in(_M_st, _M_extbuf, _M_extbufend, _M_extbufnext,\n                              this->eback() + unget_sz,\n                              this->eback() + _M_ibs, inext);\n                if (r == std::codecvt_base::noconv) {\n                    this->setg(reinterpret_cast<char_type*>(_M_extbuf),\n                               reinterpret_cast<char_type*>(_M_extbuf),\n                               const_cast<char_type*>(_M_extbufend));\n                    c = traits_type::to_int_type(*this->gptr());\n                } else if (inext != this->eback() + unget_sz) {\n                    this->setg(this->eback(), this->eback() + unget_sz, inext);\n                    c = traits_type::to_int_type(*this->gptr());\n                }\n            }\n        }\n    } else {\n        c = traits_type::to_int_type(*this->gptr());\n    }\n    if (this->eback() == &buf)\n        this->setg(0, 0, 0);\n    return c;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ntypename basic_filebuf<CharT, Traits>::int_type\nbasic_filebuf<CharT, Traits>::pbackfail(int_type c) {\n    if (_M_file && this->eback() < this->gptr()) {\n        if (traits_type::eq_int_type(c, traits_type::eof())) {\n            this->gbump(-1);\n            return traits_type::not_eof(c);\n        }\n        if ((_M_om & std::ios_base::out) ||\n            traits_type::eq(traits_type::to_char_type(c), this->gptr()[-1])) {\n            this->gbump(-1);\n            *this->gptr() = traits_type::to_char_type(c);\n            return c;\n        }\n    }\n    return traits_type::eof();\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ntypename basic_filebuf<CharT, Traits>::int_type\nbasic_filebuf<CharT, Traits>::overflow(int_type c) {\n    if (_M_file == nullptr)\n        return traits_type::eof();\n    _M_write_mode();\n    char_type buf;\n    char_type* pb_save = this->pbase();\n    char_type* epb_save = this->epptr();\n    if (!traits_type::eq_int_type(c, traits_type::eof())) {\n        if (this->pptr() == nullptr)\n            this->setp(&buf, &buf+1);\n        *this->pptr() = traits_type::to_char_type(c);\n        this->pbump(1);\n    }\n    if (this->pptr() != this->pbase()) {\n        if (_M_always_noconv) {\n            size_t nmemb = static_cast<size_t>(this->pptr() - this->pbase());\n            if (fwrite(this->pbase(), sizeof(char_type),\n                  nmemb, _M_file) != nmemb)\n                return traits_type::eof();\n        } else {\n            char* extbe = _M_extbuf;\n            std::codecvt_base::result r;\n            do {\n                if (!_M_cv)\n                    throw std::bad_cast();\n                const char_type* e;\n                r = _M_cv->out(_M_st, this->pbase(), this->pptr(), e,\n                               _M_extbuf, _M_extbuf + _M_ebs, extbe);\n                if (e == this->pbase())\n                    return traits_type::eof();\n                if (r == std::codecvt_base::noconv) {\n                    size_t nmemb = static_cast<size_t>\n                      (this->pptr() - this->pbase());\n                    if (fwrite(this->pbase(), 1, nmemb, _M_file) != nmemb)\n                        return traits_type::eof();\n                } else if (r == std::codecvt_base::ok ||\n                    r == std::codecvt_base::partial) {\n                    size_t nmemb = static_cast<size_t>(extbe - _M_extbuf);\n                    if (fwrite(_M_extbuf, 1, nmemb, _M_file) != nmemb)\n                        return traits_type::eof();\n                    if (r == std::codecvt_base::partial) {\n                        this->setp(const_cast<char_type*>(e),\n                            this->pptr());\n                        this->pbump(this->epptr() - this->pbase());\n                    }\n                } else {\n                    return traits_type::eof();\n                }\n            } while (r == std::codecvt_base::partial);\n        }\n        this->setp(pb_save, epb_save);\n    }\n    return traits_type::not_eof(c);\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nstd::basic_streambuf<CharT, Traits>*\nbasic_filebuf<CharT, Traits>::setbuf(char_type* s, std::streamsize n) {\n    this->setg(0, 0, 0);\n    this->setp(0, 0);\n    if (_M_owns_eb)\n        delete [] _M_extbuf;\n    if (_M_owns_ib)\n        delete [] _M_intbuf;\n    _M_ebs = n;\n    if (_M_ebs > sizeof(_M_extbuf_min)) {\n        if (_M_always_noconv && s) {\n            _M_extbuf = reinterpret_cast<char*>(s);\n            _M_owns_eb = false;\n        } else {\n            _M_extbuf = new char[_M_ebs];\n            _M_owns_eb = true;\n        }\n    } else {\n        _M_extbuf = _M_extbuf_min;\n        _M_ebs = sizeof(_M_extbuf_min);\n        _M_owns_eb = false;\n    }\n    if (!_M_always_noconv) {\n        _M_ibs = std::max<std::streamsize>(n, sizeof(_M_extbuf_min));\n        if (s && _M_ibs >= sizeof(_M_extbuf_min)) {\n            _M_intbuf = s;\n            _M_owns_ib = false;\n        } else {\n            _M_intbuf = new char_type[_M_ibs];\n            _M_owns_ib = true;\n        }\n    } else {\n        _M_ibs = 0;\n        _M_intbuf = 0;\n        _M_owns_ib = false;\n    }\n    return this;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ntypename basic_filebuf<CharT, Traits>::pos_type\nbasic_filebuf<CharT, Traits>::seekoff(off_type off, std::ios_base::seekdir way,\n                                      std::ios_base::openmode) {\n    if (!_M_cv)\n        throw std::bad_cast();\n    int width = _M_cv->encoding();\n    if (_M_file == nullptr || (width <= 0 && off != 0) || sync())\n        return pos_type(off_type(-1));\n    // width > 0 || off == 0\n    int whence;\n    switch (way) {\n    case std::ios_base::beg:\n        whence = SEEK_SET;\n        break;\n    case std::ios_base::cur:\n        whence = SEEK_CUR;\n        break;\n    case std::ios_base::end:\n        whence = SEEK_END;\n        break;\n    default:\n        return pos_type(off_type(-1));\n    }\n#if _WIN32\n    if (fseek(_M_file, width > 0 ? width * off : 0, whence))\n        return pos_type(off_type(-1));\n    pos_type r = ftell(_M_file);\n#else\n    if (fseeko(_M_file, width > 0 ? width * off : 0, whence))\n        return pos_type(off_type(-1));\n    pos_type r = ftello(_M_file);\n#endif\n    r.state(_M_st);\n    return r;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\ntypename basic_filebuf<CharT, Traits>::pos_type\nbasic_filebuf<CharT, Traits>::seekpos(pos_type sp, std::ios_base::openmode) {\n    if (_M_file == nullptr || sync())\n        return pos_type(off_type(-1));\n#if _WIN32\n    if (fseek(_M_file, sp, SEEK_SET))\n        return pos_type(off_type(-1));\n#else\n    if (fseeko(_M_file, sp, SEEK_SET))\n        return pos_type(off_type(-1));\n#endif\n    _M_st = sp.state();\n    return sp;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nint\nbasic_filebuf<CharT, Traits>::sync() {\n    if (_M_file == nullptr)\n        return 0;\n    if (!_M_cv)\n        throw std::bad_cast();\n    if (_M_cm & std::ios_base::out) {\n        if (this->pptr() != this->pbase())\n            if (overflow() == traits_type::eof())\n                return -1;\n        std::codecvt_base::result r;\n        do {\n            char* extbe;\n            r = _M_cv->unshift(_M_st, _M_extbuf, _M_extbuf + _M_ebs, extbe);\n            size_t nmemb = static_cast<size_t>(extbe - _M_extbuf);\n            if (fwrite(_M_extbuf, 1, nmemb, _M_file) != nmemb)\n                return -1;\n        } while (r == std::codecvt_base::partial);\n        if (r == std::codecvt_base::error)\n            return -1;\n        if (fflush(_M_file))\n            return -1;\n    } else if (_M_cm & std::ios_base::in) {\n        off_type c;\n        state_type state = _M_st_last;\n        bool update_st = false;\n        if (_M_always_noconv) {\n            c = this->egptr() - this->gptr();\n        } else {\n            int width = _M_cv->encoding();\n            c = _M_extbufend - _M_extbufnext;\n            if (width > 0) {\n                c += width * (this->egptr() - this->gptr());\n            } else {\n                if (this->gptr() != this->egptr()) {\n                    const int off = _M_cv->length(state, _M_extbuf,\n                                                  _M_extbufnext,\n                                                  this->gptr() - this->eback());\n                    c += _M_extbufnext - _M_extbuf - off;\n                    update_st = true;\n                }\n            }\n        }\n#if _WIN32\n        if (fseek(_M_file_, -c, SEEK_CUR))\n            return -1;\n#else\n        if (fseeko(_M_file, -c, SEEK_CUR))\n            return -1;\n#endif\n        if (update_st)\n            _M_st = state;\n        _M_extbufnext = _M_extbufend = _M_extbuf;\n        this->setg(0, 0, 0);\n        _M_cm = std::ios_base::openmode(0);\n    }\n    return 0;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nvoid\nbasic_filebuf<CharT, Traits>::imbue(const std::locale& loc) {\n    sync();\n    _M_cv = &std::use_facet<std::codecvt<char_type, char, state_type> >(loc);\n    bool old_anc = _M_always_noconv;\n    _M_always_noconv = _M_cv->always_noconv();\n    if (old_anc != _M_always_noconv) {\n        this->setg(0, 0, 0);\n        this->setp(0, 0);\n        // invariant, char_type is char, else we couldn't get here\n        // need to dump _M_intbuf\n        if (_M_always_noconv) {\n            if (_M_owns_eb)\n                delete [] _M_extbuf;\n            _M_owns_eb = _M_owns_ib;\n            _M_ebs = _M_ibs;\n            _M_extbuf = reinterpret_cast<char*>(_M_intbuf);\n            _M_ibs = 0;\n            _M_intbuf = nullptr;\n            _M_owns_ib = false;\n        } else {  // need to obtain an _M_intbuf.\n         // If _M_extbuf is user-supplied, use it, else new _M_intbuf\n            if (!_M_owns_eb && _M_extbuf != _M_extbuf_min) {\n                _M_ibs = _M_ebs;\n                _M_intbuf = reinterpret_cast<char_type*>(_M_extbuf);\n                _M_owns_ib = false;\n                _M_extbuf = new char[_M_ebs];\n                _M_owns_eb = true;\n            } else {\n                _M_ibs = _M_ebs;\n                _M_intbuf = new char_type[_M_ibs];\n                _M_owns_ib = true;\n            }\n        }\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nbool\nbasic_filebuf<CharT, Traits>::_M_read_mode() {\n    if (!(_M_cm & std::ios_base::in)) {\n        this->setp(0, 0);\n        if (_M_always_noconv)\n            this->setg(reinterpret_cast<char_type*>(_M_extbuf),\n                       reinterpret_cast<char_type*>(_M_extbuf) + _M_ebs,\n                       reinterpret_cast<char_type*>(_M_extbuf) + _M_ebs);\n        else\n            this->setg(_M_intbuf, _M_intbuf + _M_ibs, _M_intbuf + _M_ibs);\n        _M_cm = std::ios_base::in;\n        return true;\n    }\n    return false;\n}\n\n///////////////////////////////////////////////////////////////////////////////\ntemplate <class CharT, class Traits>\nvoid\nbasic_filebuf<CharT, Traits>::_M_write_mode() {\n    if (!(_M_cm & std::ios_base::out)) {\n        this->setg(0, 0, 0);\n        if (_M_ebs > sizeof(_M_extbuf_min)) {\n            if (_M_always_noconv)\n                this->setp(reinterpret_cast<char_type*>(_M_extbuf),\n                           reinterpret_cast<char_type*>(_M_extbuf) +\n                           (_M_ebs - 1));\n            else\n                this->setp(_M_intbuf, _M_intbuf + (_M_ibs - 1));\n        } else {\n            this->setp(0, 0);\n        }\n        _M_cm = std::ios_base::out;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\n}\n\n///////////////////////////////////////////////////////////////////////////////\n#endif  // KALDI_UTIL_BASIC_FILEBUF_H_\n\n///////////////////////////////////////////////////////////////////////////////\n\n/*\n * ============================================================================\n * libc++ License\n * ============================================================================\n *\n * The libc++ library is dual licensed under both the University of Illinois\n * \"BSD-Like\" license and the MIT license.  As a user of this code you may\n * choose to use it under either license.  As a contributor, you agree to allow\n * your code to be used under both.\n *\n * Full text of the relevant licenses is included below.\n *\n * ============================================================================\n *\n * University of Illinois/NCSA\n * Open Source License\n *\n * Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT (included below)\n *\n * All rights reserved.\n *\n * Developed by:\n *\n *     LLVM Team\n *\n *     University of Illinois at Urbana-Champaign\n *\n *     http://llvm.org\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this software and associated documentation files (the \"Software\"), to deal with\n * the Software without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Software, and to permit persons to whom the Software is furnished to do\n * so, subject to the following conditions:\n *\n *     * Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimers.\n *\n *     * Redistributions in binary form must reproduce the above copyright notice,\n *       this list of conditions and the following disclaimers in the\n *       documentation and/or other materials provided with the distribution.\n *\n *     * Neither the names of the LLVM Team, University of Illinois at\n *       Urbana-Champaign, nor the names of its contributors may be used to\n *       endorse or promote products derived from this Software without specific\n *       prior written permission.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE\n * SOFTWARE.\n *\n * ==============================================================================\n *\n * Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT (included below)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * ==============================================================================\n *\n * This file is a partial list of people who have contributed to the LLVM/libc++\n * project.  If you have contributed a patch or made some other contribution to\n * LLVM/libc++, please submit a patch to this file to add yourself, and it will be\n * done!\n *\n * The list is sorted by surname and formatted to allow easy grepping and\n * beautification by scripts.  The fields are: name (N), email (E), web-address\n * (W), PGP key ID and fingerprint (P), description (D), and snail-mail address\n * (S).\n *\n * N: Saleem Abdulrasool\n * E: compnerd@compnerd.org\n * D: Minor patches and Linux fixes.\n *\n * N: Dimitry Andric\n * E: dimitry@andric.com\n * D: Visibility fixes, minor FreeBSD portability patches.\n *\n * N: Holger Arnold\n * E: holgerar@gmail.com\n * D: Minor fix.\n *\n * N: Ruben Van Boxem\n * E: vanboxem dot ruben at gmail dot com\n * D: Initial Windows patches.\n *\n * N: David Chisnall\n * E: theraven at theravensnest dot org\n * D: FreeBSD and Solaris ports, libcxxrt support, some atomics work.\n *\n * N: Marshall Clow\n * E: mclow.lists@gmail.com\n * E: marshall@idio.com\n * D: C++14 support, patches and bug fixes.\n *\n * N: Bill Fisher\n * E: william.w.fisher@gmail.com\n * D: Regex bug fixes.\n *\n * N: Matthew Dempsky\n * E: matthew@dempsky.org\n * D: Minor patches and bug fixes.\n *\n * N: Google Inc.\n * D: Copyright owner and contributor of the CityHash algorithm\n *\n * N: Howard Hinnant\n * E: hhinnant@apple.com\n * D: Architect and primary author of libc++\n *\n * N: Hyeon-bin Jeong\n * E: tuhertz@gmail.com\n * D: Minor patches and bug fixes.\n *\n * N: Argyrios Kyrtzidis\n * E: kyrtzidis@apple.com\n * D: Bug fixes.\n *\n * N: Bruce Mitchener, Jr.\n * E: bruce.mitchener@gmail.com\n * D: Emscripten-related changes.\n *\n * N: Michel Morin\n * E: mimomorin@gmail.com\n * D: Minor patches to is_convertible.\n *\n * N: Andrew Morrow\n * E: andrew.c.morrow@gmail.com\n * D: Minor patches and Linux fixes.\n *\n * N: Arvid Picciani\n * E: aep at exys dot org\n * D: Minor patches and musl port.\n *\n * N: Bjorn Reese\n * E: breese@users.sourceforge.net\n * D: Initial regex prototype\n *\n * N: Nico Rieck\n * E: nico.rieck@gmail.com\n * D: Windows fixes\n *\n * N: Jonathan Sauer\n * D: Minor patches, mostly related to constexpr\n *\n * N: Craig Silverstein\n * E: csilvers@google.com\n * D: Implemented Cityhash as the string hash function on 64-bit machines\n *\n * N: Richard Smith\n * D: Minor patches.\n *\n * N: Joerg Sonnenberger\n * E: joerg@NetBSD.org\n * D: NetBSD port.\n *\n * N: Stephan Tolksdorf\n * E: st@quanttec.com\n * D: Minor <atomic> fix\n *\n * N: Michael van der Westhuizen\n * E: r1mikey at gmail dot com\n *\n * N: Klaas de Vries\n * E: klaas at klaasgaaf dot nl\n * D: Minor bug fix.\n *\n * N: Zhang Xiongpang\n * E: zhangxiongpang@gmail.com\n * D: Minor patches and bug fixes.\n *\n * N: Xing Xue\n * E: xingxue@ca.ibm.com\n * D: AIX port\n *\n * N: Zhihao Yuan\n * E: lichray@gmail.com\n * D: Standard compatibility fixes.\n *\n * N: Jeffrey Yasskin\n * E: jyasskin@gmail.com\n * E: jyasskin@google.com\n * D: Linux fixes.\n */\n"
  },
  {
    "path": "runtime/engine/kaldi/util/common-utils.h",
    "content": "// util/common-utils.h\n\n// Copyright 2009-2011 Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_UTIL_COMMON_UTILS_H_\n#define KALDI_UTIL_COMMON_UTILS_H_\n\n#include \"base/kaldi-common.h\"\n#include \"util/parse-options.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/simple-io-funcs.h\"\n#include \"util/kaldi-holder.h\"\n#include \"util/kaldi-table.h\"\n#include \"util/table-types.h\"\n#include \"util/text-utils.h\"\n\n#endif  // KALDI_UTIL_COMMON_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/const-integer-set-inl.h",
    "content": "// util/const-integer-set-inl.h\n\n// Copyright 2009-2011     Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_CONST_INTEGER_SET_INL_H_\n#define KALDI_UTIL_CONST_INTEGER_SET_INL_H_\n\n// Do not include this file directly.  It is included by const-integer-set.h\n\n\nnamespace kaldi {\n\ntemplate<class I>\nvoid ConstIntegerSet<I>::InitInternal() {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  quick_set_.clear();  // just in case we previously had data.\n  if (slow_set_.size() == 0) {\n    lowest_member_=(I) 1;\n    highest_member_=(I) 0;\n    contiguous_ = false;\n    quick_ = false;\n  } else {\n    lowest_member_ = slow_set_.front();\n    highest_member_ = slow_set_.back();\n    size_t range = highest_member_ + 1 - lowest_member_;\n    if (range == slow_set_.size()) {\n      contiguous_ = true;\n      quick_= false;\n    } else {\n      contiguous_ = false;\n      // If it would be more compact to store as bool\n      if (range < slow_set_.size() * 8 * sizeof(I)) {\n        // (assuming 1 bit per element)...\n        quick_set_.resize(range, false);\n        for (size_t i = 0;i < slow_set_.size();i++)\n          quick_set_[slow_set_[i] - lowest_member_] = true;\n        quick_ = true;\n      } else {\n        quick_ = false;\n      }\n    }\n  }\n}\n\ntemplate<class I>\nint ConstIntegerSet<I>::count(I i) const {\n  if (i < lowest_member_ || i > highest_member_) {\n    return 0;\n  } else {\n    if (contiguous_) return true;\n    if (quick_) {\n      return (quick_set_[i-lowest_member_] ? 1 : 0);\n    } else {\n      bool ans = std::binary_search(slow_set_.begin(), slow_set_.end(), i);\n      return (ans ? 1 : 0);\n    }\n  }\n}\n\ntemplate<class I>\nvoid ConstIntegerSet<I>::Write(std::ostream &os, bool binary) const {\n  WriteIntegerVector(os, binary, slow_set_);\n}\n\ntemplate<class I>\nvoid ConstIntegerSet<I>::Read(std::istream &is, bool binary) {\n  ReadIntegerVector(is, binary, &slow_set_);\n  InitInternal();\n}\n\n\n\n}  // end namespace kaldi\n\n#endif  // KALDI_UTIL_CONST_INTEGER_SET_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/const-integer-set.h",
    "content": "// util/const-integer-set.h\n\n// Copyright 2009-2011     Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_CONST_INTEGER_SET_H_\n#define KALDI_UTIL_CONST_INTEGER_SET_H_\n#include <vector>\n#include <set>\n#include <algorithm>\n#include <limits>\n#include <cassert>\n#include \"util/stl-utils.h\"\n\n  /* ConstIntegerSet is a way to efficiently test whether something is in a\n     supplied set of integers.  It can be initialized from a vector or set, but\n     never changed after that. It either uses a sorted vector or an array of\n     bool, depending on the input.  It behaves like a const version of an STL set, with\n     only a subset of the functionality, except all the member functions are\n     upper-case.\n\n     Note that we could get rid of the member slow_set_, but we'd have to\n     do more work to implement an iterator type.  This would save memory.\n  */\n\nnamespace kaldi {\n\ntemplate<class I> class ConstIntegerSet {\n public:\n  ConstIntegerSet(): lowest_member_(1), highest_member_(0) { }\n\n  void Init(const std::vector<I> &input) {\n    slow_set_ = input;\n    SortAndUniq(&slow_set_);\n    InitInternal();\n  }\n\n  void Init(const std::set<I> &input) {\n    CopySetToVector(input, &slow_set_);\n    InitInternal();\n  }\n\n  explicit ConstIntegerSet(const std::vector<I> &input): slow_set_(input) {\n    SortAndUniq(&slow_set_);\n    InitInternal();\n  }\n  explicit ConstIntegerSet(const std::set<I> &input) {\n    CopySetToVector(input, &slow_set_);\n    InitInternal();\n  }\n  explicit ConstIntegerSet(const ConstIntegerSet<I> &other):\n                           slow_set_(other.slow_set_) {\n    InitInternal();\n  }\n\n  int count(I i) const;  // returns 1 or 0.\n\n  typedef typename std::vector<I>::const_iterator iterator;\n  iterator begin() const { return slow_set_.begin(); }\n  iterator end() const { return slow_set_.end(); }\n  size_t size() const { return slow_set_.size(); }\n  bool empty() const { return slow_set_.empty(); }\n\n  void Write(std::ostream &os, bool binary) const;\n  void Read(std::istream &is, bool binary);\n\n private:\n  I lowest_member_;\n  I highest_member_;\n  bool contiguous_;\n  bool quick_;\n  std::vector<bool> quick_set_;\n  std::vector<I> slow_set_;\n  void InitInternal();\n};\n\n}  // end namespace kaldi\n\n#include \"util/const-integer-set-inl.h\"\n\n#endif  // KALDI_UTIL_CONST_INTEGER_SET_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/edit-distance-inl.h",
    "content": "// util/edit-distance-inl.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Haihua Xu;  Yanmin Qian\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_EDIT_DISTANCE_INL_H_\n#define KALDI_UTIL_EDIT_DISTANCE_INL_H_\n#include <algorithm>\n#include <utility>\n#include <vector>\n#include \"util/stl-utils.h\"\n\nnamespace kaldi {\n\ntemplate<class T>\nint32 LevenshteinEditDistance(const std::vector<T> &a,\n                              const std::vector<T> &b) {\n  // Algorithm:\n  //  write A and B for the sequences, with elements a_0 ..\n  //  let |A| = M and |B| = N be the lengths, and have\n  //  elements a_0 ... a_{M-1} and b_0 ... b_{N-1}.\n  //  We are computing the recursion\n  //     E(m, n) = min(  E(m-1, n-1) + (1-delta(a_{m-1}, b_{n-1})),\n  //                    E(m-1, n) + 1,\n  //                    E(m, n-1) + 1).\n  //  where E(m, n) is defined for m = 0..M and n = 0..N and out-of-\n  //  bounds quantities are considered to be infinity (i.e. the\n  //  recursion does not visit them).\n\n  // We do this computation using a vector e of size N+1.\n  // The outer iterations range over m = 0..M.\n\n  int M = a.size(), N = b.size();\n  std::vector<int32> e(N+1);\n  std::vector<int32> e_tmp(N+1);\n  // initialize e.\n  for (size_t i = 0; i < e.size(); i++)\n    e[i] = i;\n  for (int32 m = 1; m <= M; m++) {\n    // computing E(m, .) from E(m-1, .)\n    // handle special case n = 0:\n    e_tmp[0] = e[0] + 1;\n\n    for (int32 n = 1; n <= N; n++) {\n      int32 term1 = e[n-1] + (a[m-1] == b[n-1] ? 0 : 1);\n      int32 term2 = e[n] + 1;\n      int32 term3 = e_tmp[n-1] + 1;\n      e_tmp[n] = std::min(term1, std::min(term2, term3));\n    }\n    e = e_tmp;\n  }\n  return e.back();\n}\n//\nstruct error_stats {\n  int32 ins_num;\n  int32 del_num;\n  int32 sub_num;\n  int32 total_cost;  // minimum total cost to the current alignment.\n};\n// Note that both hyp and ref should not contain noise word in\n// the following implementation.\n\ntemplate<class T>\nint32 LevenshteinEditDistance(const std::vector<T> &ref,\n                              const std::vector<T> &hyp,\n                              int32 *ins, int32 *del, int32 *sub) {\n  // temp sequence to remember error type and stats.\n  std::vector<error_stats> e(ref.size()+1);\n  std::vector<error_stats> cur_e(ref.size()+1);\n  // initialize the first hypothesis aligned to the reference at each\n  // position:[hyp_index =0][ref_index]\n  for (size_t i =0; i < e.size(); i ++) {\n    e[i].ins_num = 0;\n    e[i].sub_num = 0;\n    e[i].del_num = i;\n    e[i].total_cost = i;\n  }\n\n  // for other alignments\n  for (size_t hyp_index = 1; hyp_index <= hyp.size(); hyp_index ++) {\n    cur_e[0] = e[0];\n    cur_e[0].ins_num++;\n    cur_e[0].total_cost++;\n    for (size_t ref_index = 1; ref_index <= ref.size(); ref_index ++) {\n     int32 ins_err = e[ref_index].total_cost + 1;\n     int32 del_err = cur_e[ref_index-1].total_cost + 1;\n     int32 sub_err = e[ref_index-1].total_cost;\n      if (hyp[hyp_index-1] != ref[ref_index-1])\n       sub_err++;\n\n     if (sub_err < ins_err && sub_err < del_err) {\n        cur_e[ref_index] =e[ref_index-1];\n        if (hyp[hyp_index-1] != ref[ref_index-1])\n          cur_e[ref_index].sub_num++;  // substitution error should be increased\n        cur_e[ref_index].total_cost = sub_err;\n     } else if (del_err < ins_err) {\n        cur_e[ref_index] = cur_e[ref_index-1];\n        cur_e[ref_index].total_cost = del_err;\n        cur_e[ref_index].del_num++;    // deletion number is increased.\n     } else {\n        cur_e[ref_index] = e[ref_index];\n        cur_e[ref_index].total_cost = ins_err;\n        cur_e[ref_index].ins_num++;    // insertion number is increased.\n     }\n  }\n  e = cur_e;  // alternate for the next recursion.\n  }\n  size_t ref_index = e.size()-1;\n  *ins = e[ref_index].ins_num, *del =\n    e[ref_index].del_num, *sub = e[ref_index].sub_num;\n  return e[ref_index].total_cost;\n}\n\ntemplate<class T>\nint32 LevenshteinAlignment(const std::vector<T> &a,\n                           const std::vector<T> &b,\n                           T eps_symbol,\n                           std::vector<std::pair<T, T> > *output) {\n  // Check inputs:\n  {\n    KALDI_ASSERT(output != NULL);\n    for (size_t i = 0; i < a.size(); i++) KALDI_ASSERT(a[i] != eps_symbol);\n    for (size_t i = 0; i < b.size(); i++) KALDI_ASSERT(b[i] != eps_symbol);\n  }\n  output->clear();\n  // This is very memory-inefficiently implemented using a vector of vectors.\n  size_t M = a.size(), N = b.size();\n  size_t m, n;\n  std::vector<std::vector<int32> > e(M+1);\n  for (m = 0; m <=M; m++) e[m].resize(N+1);\n  for (n = 0; n <= N; n++)\n    e[0][n]  = n;\n  for (m = 1; m <= M; m++) {\n    e[m][0] = e[m-1][0] + 1;\n    for (n = 1; n <= N; n++) {\n      int32 sub_or_ok = e[m-1][n-1] + (a[m-1] == b[n-1] ? 0 : 1);\n      int32 del = e[m-1][n] + 1;  // assumes a == ref, b == hyp.\n      int32 ins = e[m][n-1] + 1;\n      e[m][n] = std::min(sub_or_ok, std::min(del, ins));\n    }\n  }\n  // get time-reversed output first: trace back.\n  m = M;\n  n = N;\n  while (m != 0 || n != 0) {\n    size_t last_m, last_n;\n    if (m == 0) {\n      last_m = m;\n      last_n = n-1;\n    } else if (n == 0) {\n      last_m = m-1;\n      last_n = n;\n    } else {\n      int32 sub_or_ok = e[m-1][n-1] + (a[m-1] == b[n-1] ? 0 : 1);\n      int32 del = e[m-1][n] + 1;  // assumes a == ref, b == hyp.\n      int32 ins = e[m][n-1] + 1;\n      // choose sub_or_ok if all else equal.\n      if (sub_or_ok <= std::min(del, ins)) {\n        last_m = m-1;\n        last_n = n-1;\n      } else {\n        if (del <= ins) {  // choose del over ins if equal.\n          last_m = m-1;\n          last_n = n;\n        } else {\n          last_m = m;\n          last_n = n-1;\n        }\n      }\n    }\n    T a_sym, b_sym;\n    a_sym = (last_m == m ? eps_symbol : a[last_m]);\n    b_sym = (last_n == n ? eps_symbol : b[last_n]);\n    output->push_back(std::make_pair(a_sym, b_sym));\n    m = last_m;\n    n = last_n;\n  }\n  ReverseVector(output);\n  return e[M][N];\n}\n\n\n}  // end namespace kaldi\n\n#endif  // KALDI_UTIL_EDIT_DISTANCE_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/edit-distance.h",
    "content": "// util/edit-distance.h\n\n// Copyright 2009-2011     Microsoft Corporation;  Haihua Xu\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_EDIT_DISTANCE_H_\n#define KALDI_UTIL_EDIT_DISTANCE_H_\n#include <vector>\n#include <set>\n#include <algorithm>\n#include <limits>\n#include <cassert>\n#include <utility>\n#include \"util/edit-distance-inl.h\"\n#include \"base/kaldi-types.h\"\n\nnamespace kaldi {\n\n// Compute the edit-distance between two strings.\ntemplate<class T>\nint32 LevenshteinEditDistance(const std::vector<T> &a,\n                              const std::vector<T> &b);\n\n\n// edit distance calculation with conventional method.\n// note: noise word must be filtered out from the hypothesis and\n// reference sequence\n// before the following procedure conducted.\ntemplate<class T>\nint32 LevenshteinEditDistance(const std::vector<T> &ref,\n                              const std::vector<T> &hyp,\n                              int32 *ins, int32 *del, int32 *sub);\n\n// This version of the edit-distance computation outputs the alignment\n// between the two.  This is a vector of pairs of (symbol a, symbol b).\n// The epsilon symbol (eps_symbol) must not occur in sequences a or b.\n// Where one aligned to no symbol in the other (insertion or deletion),\n// epsilon will be the corresponding member of the pair.\n// It returns the edit-distance between the two strings.\n\ntemplate<class T>\nint32 LevenshteinAlignment(const std::vector<T> &a,\n                           const std::vector<T> &b,\n                           T eps_symbol,\n                           std::vector<std::pair<T, T> > *output);\n\n}  // end namespace kaldi\n\n#endif  // KALDI_UTIL_EDIT_DISTANCE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/hash-list-inl.h",
    "content": "// util/hash-list-inl.h\n\n// Copyright 2009-2011   Microsoft Corporation\n//                2013   Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_HASH_LIST_INL_H_\n#define KALDI_UTIL_HASH_LIST_INL_H_\n\n// Do not include this file directly.  It is included by fast-hash.h\n\n\nnamespace kaldi {\n\ntemplate<class I, class T> HashList<I, T>::HashList() {\n  list_head_ = NULL;\n  bucket_list_tail_ = static_cast<size_t>(-1);  // invalid.\n  hash_size_ = 0;\n  freed_head_ = NULL;\n}\n\ntemplate<class I, class T> void HashList<I, T>::SetSize(size_t size) {\n  hash_size_ = size;\n  KALDI_ASSERT(list_head_ == NULL &&\n      bucket_list_tail_ == static_cast<size_t>(-1));  // make sure empty.\n  if (size > buckets_.size())\n    buckets_.resize(size, HashBucket(0, NULL));\n}\n\ntemplate<class I, class T>\ntypename HashList<I, T>::Elem* HashList<I, T>::Clear() {\n  // Clears the hashtable and gives ownership of the currently contained list\n  // to the user.\n  for (size_t cur_bucket = bucket_list_tail_;\n      cur_bucket != static_cast<size_t>(-1);\n      cur_bucket = buckets_[cur_bucket].prev_bucket) {\n    buckets_[cur_bucket].last_elem = NULL;  // this is how we indicate \"empty\".\n  }\n  bucket_list_tail_ = static_cast<size_t>(-1);\n  Elem *ans = list_head_;\n  list_head_ = NULL;\n  return ans;\n}\n\ntemplate<class I, class T>\nconst typename HashList<I, T>::Elem* HashList<I, T>::GetList() const {\n  return list_head_;\n}\n\ntemplate<class I, class T>\ninline void HashList<I, T>::Delete(Elem *e) {\n  e->tail = freed_head_;\n  freed_head_ = e;\n}\n\ntemplate<class I, class T>\ninline typename HashList<I, T>::Elem* HashList<I, T>::Find(I key) {\n  size_t index = (static_cast<size_t>(key) % hash_size_);\n  HashBucket &bucket = buckets_[index];\n  if (bucket.last_elem == NULL) {\n    return NULL;  // empty bucket.\n  } else {\n    Elem *head = (bucket.prev_bucket == static_cast<size_t>(-1) ?\n                  list_head_ :\n                  buckets_[bucket.prev_bucket].last_elem->tail),\n        *tail = bucket.last_elem->tail;\n    for (Elem *e = head; e != tail; e = e->tail)\n      if (e->key == key) return e;\n    return NULL;  // Not found.\n  }\n}\n\ntemplate<class I, class T>\ninline typename HashList<I, T>::Elem* HashList<I, T>::New() {\n  if (freed_head_) {\n    Elem *ans = freed_head_;\n    freed_head_ = freed_head_->tail;\n    return ans;\n  } else {\n    Elem *tmp = new Elem[allocate_block_size_];\n    for (size_t i = 0; i+1 < allocate_block_size_; i++)\n      tmp[i].tail = tmp+i+1;\n    tmp[allocate_block_size_-1].tail = NULL;\n    freed_head_ = tmp;\n    allocated_.push_back(tmp);\n    return this->New();\n  }\n}\n\ntemplate<class I, class T>\nHashList<I, T>::~HashList() {\n  // First test whether we had any memory leak within the\n  // HashList, i.e. things for which the user did not call Delete().\n  size_t num_in_list = 0, num_allocated = 0;\n  for (Elem *e = freed_head_; e != NULL; e = e->tail)\n    num_in_list++;\n  for (size_t i = 0; i < allocated_.size(); i++) {\n    num_allocated += allocate_block_size_;\n    delete[] allocated_[i];\n  }\n  if (num_in_list != num_allocated) {\n    KALDI_WARN << \"Possible memory leak: \" << num_in_list\n               << \" != \" << num_allocated\n               << \": you might have forgotten to call Delete on \"\n               << \"some Elems\";\n  }\n}\n\ntemplate<class I, class T>\ninline typename HashList<I, T>::Elem* HashList<I, T>::Insert(I key, T val) {\n  size_t index = (static_cast<size_t>(key) % hash_size_);\n  HashBucket &bucket = buckets_[index];\n  // Check the element is existing or not.\n  if (bucket.last_elem != NULL) {\n    Elem *head = (bucket.prev_bucket == static_cast<size_t>(-1) ?\n                  list_head_ :\n                  buckets_[bucket.prev_bucket].last_elem->tail),\n         *tail = bucket.last_elem->tail;\n    for (Elem *e = head; e != tail; e = e->tail)\n      if (e->key == key) return e;\n  }\n\n  // This is a new element. Insert it.\n  Elem *elem = New();\n  elem->key = key;\n  elem->val = val;\n  if (bucket.last_elem == NULL) {  // Unoccupied bucket.  Insert at\n    // head of bucket list (which is tail of regular list, they go in\n    // opposite directions).\n    if (bucket_list_tail_ == static_cast<size_t>(-1)) {\n      // list was empty so this is the first elem.\n      KALDI_ASSERT(list_head_ == NULL);\n      list_head_ = elem;\n    } else {\n      // link in to the chain of Elems\n      buckets_[bucket_list_tail_].last_elem->tail = elem;\n    }\n    elem->tail = NULL;\n    bucket.last_elem = elem;\n    bucket.prev_bucket = bucket_list_tail_;\n    bucket_list_tail_ = index;\n  } else {\n    // Already-occupied bucket.  Insert at tail of list of elements within\n    // the bucket.\n    elem->tail = bucket.last_elem->tail;\n    bucket.last_elem->tail = elem;\n    bucket.last_elem = elem;\n  }\n  return elem;\n}\n\ntemplate<class I, class T>\nvoid HashList<I, T>::InsertMore(I key, T val) {\n  size_t index = (static_cast<size_t>(key) % hash_size_);\n  HashBucket &bucket = buckets_[index];\n  Elem *elem = New();\n  elem->key = key;\n  elem->val = val;\n\n  KALDI_ASSERT(bucket.last_elem != NULL);  // assume one element is already here\n  if (bucket.last_elem->key == key) {  // standard behavior: add as last element\n    elem->tail = bucket.last_elem->tail;\n    bucket.last_elem->tail = elem;\n    bucket.last_elem = elem;\n    return;\n  }\n  Elem *e = (bucket.prev_bucket == static_cast<size_t>(-1) ?\n             list_head_ : buckets_[bucket.prev_bucket].last_elem->tail);\n  // find place to insert in linked list\n  while (e != bucket.last_elem->tail && e->key != key) e = e->tail;\n  KALDI_ASSERT(e->key == key);  // not found? - should not happen\n  elem->tail = e->tail;\n  e->tail = elem;\n}\n\n\n}  // end namespace kaldi\n\n#endif  // KALDI_UTIL_HASH_LIST_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/hash-list.h",
    "content": "// util/hash-list.h\n\n// Copyright 2009-2011   Microsoft Corporation\n//                2013   Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_HASH_LIST_H_\n#define KALDI_UTIL_HASH_LIST_H_\n#include <vector>\n#include <set>\n#include <algorithm>\n#include <limits>\n#include <cassert>\n#include \"util/stl-utils.h\"\n\n\n/* This header provides utilities for a structure that's used in a decoder (but\n   is quite generic in nature so we implement and test it separately).\n   Basically it's a singly-linked list, but implemented in such a way that we\n   can quickly search for elements in the list.  We give it a slightly richer\n   interface than just a hash and a list.  The idea is that we want to separate\n   the hash part and the list part: basically, in the decoder, we want to have a\n   single hash for the current frame and the next frame, because by the time we\n   need to access the hash for the next frame we no longer need the hash for the\n   previous frame.  So we have an operation that clears the hash but leaves the\n   list structure intact.  We also control memory management inside this object,\n   to avoid repeated new's/deletes.\n\n   See hash-list-test.cc for an example of how to use this object.\n*/\n\n\nnamespace kaldi {\n\ntemplate<class I, class T> class HashList {\n public:\n  struct Elem {\n    I key;\n    T val;\n    Elem *tail;\n  };\n\n  /// Constructor takes no arguments.\n  /// Call SetSize to inform it of the likely size.\n  HashList();\n\n  /// Clears the hash and gives the head of the current list to the user;\n  /// ownership is transferred to the user (the user must call Delete()\n  /// for each element in the list, at his/her leisure).\n  Elem *Clear();\n\n  /// Gives the head of the current list to the user.  Ownership retained in the\n  /// class.  Caution: in December 2013 the return type was changed to const\n  /// Elem* and this function was made const.  You may need to change some types\n  /// of local Elem* variables to const if this produces compilation errors.\n  const Elem *GetList() const;\n\n  /// Think of this like delete().  It is to be called for each Elem in turn\n  /// after you \"obtained ownership\" by doing Clear().  This is not the opposite\n  /// of. Insert, it is the opposite of New.  It's really a memory operation.\n  inline void Delete(Elem *e);\n\n  /// This should probably not be needed to be called directly by the user.\n  /// Think of it as opposite\n  /// to Delete();\n  inline Elem *New();\n\n  /// Find tries to find this element in the current list using the hashtable.\n  /// It returns NULL if not present.  The Elem it returns is not owned by the\n  /// user, it is part of the internal list owned by this object, but the user\n  /// is free to modify the \"val\" element.\n  inline Elem *Find(I key);\n\n  /// Insert inserts a new element into the hashtable/stored list.\n  /// Because element keys in a hashtable are unique, this operation checks\n  /// whether each inserted element has a key equivalent to the one of an\n  /// element already in the hashtable. If so, the element is not inserted,\n  /// returning an pointer to this existing element.\n  inline Elem *Insert(I key, T val);\n\n  /// Insert inserts another element with same key into the hashtable/\n  /// stored list.\n  /// By calling this, the user asserts that one element with that key is\n  /// already present.\n  /// We insert it that way, that all elements with the same key\n  /// follow each other.\n  /// Find() will return the first one of the elements with the same key.\n  inline void InsertMore(I key, T val);\n\n  /// SetSize tells the object how many hash buckets to allocate (should\n  /// typically be at least twice the number of objects we expect to go in the\n  /// structure, for fastest performance).  It must be called while the hash\n  /// is empty (e.g. after Clear() or after initializing the object, but before\n  /// adding anything to the hash.\n  void SetSize(size_t sz);\n\n  /// Returns current number of hash buckets.\n  inline size_t Size() { return hash_size_; }\n\n  ~HashList();\n private:\n\n  struct HashBucket {\n    size_t prev_bucket;  // index to next bucket (-1 if list tail).  Note:\n    // list of buckets goes in opposite direction to list of Elems.\n    Elem *last_elem;  // pointer to last element in this bucket (NULL if empty)\n    inline HashBucket(size_t i, Elem *e): prev_bucket(i), last_elem(e) {}\n  };\n\n  Elem *list_head_;  // head of currently stored list.\n  size_t bucket_list_tail_;  // tail of list of active hash buckets.\n\n  size_t hash_size_;  // number of hash buckets.\n\n  std::vector<HashBucket> buckets_;\n\n  Elem *freed_head_;  // head of list of currently freed elements. [ready for\n  // allocation]\n\n  std::vector<Elem*> allocated_;  // list of allocated blocks.\n\n  static const size_t allocate_block_size_ = 1024;  // Number of Elements to\n  // allocate in one block.  Must be largish so storing allocated_ doesn't\n  // become a problem.\n};\n\n\n}  // end namespace kaldi\n\n#include \"util/hash-list-inl.h\"\n\n#endif  // KALDI_UTIL_HASH_LIST_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-cygwin-io-inl.h",
    "content": "// util/kaldi-cygwin-io-inl.h\n\n// Copyright 2015 Smart Action Company LLC (author: Kirill Katsnelson)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_UTIL_KALDI_CYGWIN_IO_INL_H_\n#define KALDI_UTIL_KALDI_CYGWIN_IO_INL_H_\n\n#ifndef _MSC_VER\n#error This is a Windows-compatibility file. Something went wery wrong.\n#endif\n\n#include <string>\n\n// This file is included only into kaldi-io.cc, and only if\n// KALDI_CYGWIN_COMPAT is enabled.\n//\n// The routines map unix-ey paths passed to Windows programs from shell\n// scripts in egs. Since shell scripts run under cygwin, they use cygwin's\n// own mount table and a mapping to the file system. It is quite possible to\n// create quite an intricate mapping that only own cygwin API would be able\n// to untangle. Unfortunately, the API to map between filenames is not\n// available to non-cygwin programs. Running cygpath for every file operation\n// would as well be cumbersome. So this is only a simplistic path resolution,\n// assuming that the default cygwin prefix /cygdrive is used, and that all\n// resolved unix-style full paths end up prefixed with /cygdrive. This is\n// quite a sensible approach. We'll also try to map /dev/null and /tmp/**,\n// die on all other /dev/** and warn about all other rooted paths.\n\nnamespace kaldi {\n\nstatic bool prefixp(const std::string& pfx, const std::string& str) {\n  return pfx.length() <= str.length() &&\n    std::equal(pfx.begin(), pfx.end(), str.begin());\n}\n\nstatic std::string cygprefix(\"/cygdrive/\");\n\nstatic std::string MapCygwinPathNoTmp(const std::string &filename) {\n  // UNC(?), relative, native Windows and empty paths are ok already.\n  if (prefixp(\"//\", filename) || !prefixp(\"/\", filename))\n    return filename;\n\n  // /dev/...\n  if (filename == \"/dev/null\")\n    return \"\\\\\\\\.\\\\nul\";\n  if (prefixp(\"/dev/\", filename)) {\n      KALDI_ERR << \"Unable to resolve path '\" << filename\n                << \"' - only have /dev/null here.\";\n      return \"\\\\\\\\.\\\\invalid\";\n  }\n\n  // /cygdrive/?[/....]\n  int preflen = cygprefix.size();\n  if (prefixp(cygprefix, filename)\n      && filename.size() >= preflen + 1 && isalpha(filename[preflen])\n      && (filename.size() == preflen + 1 || filename[preflen + 1] == '/')) {\n    return std::string() + filename[preflen] + ':' +\n       (filename.size() > preflen + 1 ? filename.substr(preflen + 1) : \"/\");\n  }\n\n  KALDI_WARN << \"Unable to resolve path '\" << filename\n             << \"' - cannot map unix prefix. \"\n             << \"Will go on, but breakage will likely ensue.\";\n  return filename;\n}\n\n// extern for unit testing.\nstd::string MapCygwinPath(const std::string &filename) {\n  // /tmp[/....]\n  if (filename != \"/tmp\" && !prefixp(\"/tmp/\", filename)) {\n    return MapCygwinPathNoTmp(filename);\n  }\n  char *tmpdir = std::getenv(\"TMP\");\n  if (tmpdir == nullptr)\n    tmpdir = std::getenv(\"TEMP\");\n  if (tmpdir == nullptr) {\n    KALDI_ERR << \"Unable to resolve path '\" << filename\n              << \"' - unable to find temporary directory. Set TMP.\";\n    return filename;\n  }\n  // Map the value of tmpdir again, as cygwin environment actually may contain\n  // unix-style paths.\n  return MapCygwinPathNoTmp(std::string(tmpdir) + filename.substr(4));\n}\n\n// A popen implementation that passes the command line through cygwin\n// bash.exe. This is necessary since some piped commands are cygwin links\n// (e. g. fgrep is a soft link to grep), and some are #!-files, such as\n// gunzip which is a shell script that invokes gzip, or kaldi's own run.pl\n// which is a perl script.\n//\n// _popen uses cmd.exe or whatever shell is specified via the COMSPEC\n// variable. Unfortunately, it adds a hardcoded \" /c \" to it, so we cannot\n// just substitute the environment variable COMSPEC to point to bash.exe.\n// Instead, quote the command and pass it to bash via its -c switch.\nstatic FILE *CygwinCompatPopen(const char* command, const char* mode) {\n  // To speed up command launch marginally, optionally accept full path\n  // to bash.exe. This will not work if the path contains spaces, but\n  // no sane person would install cygwin into a space-ridden path.\n  const char* bash_exe = std::getenv(\"BASH_EXE\");\n  std::string qcmd(bash_exe != nullptr ? bash_exe : \"bash.exe\");\n  qcmd += \" -c \\\"\";\n  for (; *command; ++command) {\n    if (*command == '\\\"')\n      qcmd += '\\\"';\n    qcmd += *command;\n  }\n  qcmd += '\\\"';\n\n  return _popen(qcmd.c_str(), mode);\n}\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_KALDI_CYGWIN_IO_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-holder-inl.h",
    "content": "// util/kaldi-holder-inl.h\n\n// Copyright 2009-2011     Microsoft Corporation\n//                2016     Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_KALDI_HOLDER_INL_H_\n#define KALDI_UTIL_KALDI_HOLDER_INL_H_\n\n#include <algorithm>\n#include <vector>\n#include <utility>\n#include <string>\n\n#include \"base/kaldi-utils.h\"\n#include \"util/kaldi-io.h\"\n#include \"util/text-utils.h\"\n#include \"matrix/kaldi-matrix.h\"\n\nnamespace kaldi {\n\n/// \\addtogroup holders\n/// @{\n\n\n// KaldiObjectHolder is valid only for Kaldi objects with\n// copy constructors, default constructors, and \"normal\"\n// Kaldi Write and Read functions.  E.g. it works for\n// Matrix and Vector.\ntemplate<class KaldiType> class KaldiObjectHolder {\n public:\n  typedef KaldiType T;\n\n  KaldiObjectHolder(): t_(NULL) { }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    InitKaldiOutputStream(os, binary);  // Puts binary header if binary mode.\n    try {\n      t.Write(os, binary);\n      return os.good();\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught writing Table object. \" << e.what();\n      return false;  // Write failure.\n    }\n  }\n\n  void Clear() {\n    if (t_) {\n      delete t_;\n      t_ = NULL;\n    }\n  }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    delete t_;\n    t_ = new T;\n    // Don't want any existing state to complicate the read function: get new\n    // object.\n    bool is_binary;\n    if (!InitKaldiInputStream(is, &is_binary)) {\n      KALDI_WARN << \"Reading Table object, failed reading binary header\\n\";\n      return false;\n    }\n    try {\n      t_->Read(is, is_binary);\n      return true;\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught reading Table object. \" << e.what();\n      delete t_;\n      t_ = NULL;\n      return false;\n    }\n  }\n\n  // Kaldi objects always have the stream open in binary mode for\n  // reading.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {\n    // code error if !t_.\n    if (!t_) KALDI_ERR << \"KaldiObjectHolder::Value() called wrongly.\";\n    return *t_;\n  }\n\n  void Swap(KaldiObjectHolder<T> *other) {\n    // the t_ values are pointers so this is a shallow swap.\n    std::swap(t_, other->t_);\n  }\n\n  bool ExtractRange(const KaldiObjectHolder<T> &other,\n                    const std::string &range) {\n    KALDI_ASSERT(other.t_ != NULL);\n    delete t_;\n    t_ = new T;\n    // this call will fail for most object types.\n    return ExtractObjectRange(*(other.t_), range, t_);\n  }\n\n  ~KaldiObjectHolder() { delete t_; }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(KaldiObjectHolder);\n  T *t_;\n};\n\n\n// BasicHolder is valid for float, double, bool, and integer\n// types.  There will be a compile time error otherwise, because\n// we make sure that the {Write, Read}BasicType functions do not\n// get instantiated for other types.\n\ntemplate<class BasicType> class BasicHolder {\n public:\n  typedef BasicType T;\n\n  BasicHolder(): t_(static_cast<T>(-1)) { }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    InitKaldiOutputStream(os, binary);  // Puts binary header if binary mode.\n    try {\n      WriteBasicType(os, binary, t);\n      if (!binary) os << '\\n';  // Makes output format more readable and\n      // easier to manipulate.\n      return os.good();\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught writing Table object. \" << e.what();\n      return false;  // Write failure.\n    }\n  }\n\n  void Clear() { }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    bool is_binary;\n    if (!InitKaldiInputStream(is, &is_binary)) {\n      KALDI_WARN << \"Reading Table object [integer type], failed reading binary\"\n          \" header\\n\";\n      return false;\n    }\n    try {\n      int c;\n      if (!is_binary) {  // This is to catch errors, the class would work\n        // without it..\n        // Eat up any whitespace and make sure it's not newline.\n        while (isspace((c = is.peek())) && c != static_cast<int>('\\n')) {\n          is.get();\n        }\n        if (is.peek() == '\\n') {\n          KALDI_WARN << \"Found newline but expected basic type.\";\n          return false;  // This is just to catch a more-\n          // likely-than average type of error (empty line before the token),\n          // since ReadBasicType will eat it up.\n        }\n      }\n\n      ReadBasicType(is, is_binary, &t_);\n\n      if (!is_binary) {  // This is to catch errors, the class would work\n        // without it..\n        // make sure there is a newline.\n        while (isspace((c = is.peek())) && c != static_cast<int>('\\n')) {\n          is.get();\n        }\n        if (is.peek() != '\\n') {\n          KALDI_WARN << \"BasicHolder::Read, expected newline, got \"\n                     << CharToString(is.peek()) << \", position \" << is.tellg();\n          return false;\n        }\n        is.get();  // Consume the newline.\n      }\n      return true;\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught reading Table object. \" << e.what();\n      return false;\n    }\n  }\n\n  // Objects read/written with the Kaldi I/O functions always have the stream\n  // open in binary mode for reading.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {\n    return t_;\n  }\n\n  void Swap(BasicHolder<T> *other) {\n    std::swap(t_, other->t_);\n  }\n\n  bool ExtractRange(const BasicHolder<T> &other, const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~BasicHolder() { }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(BasicHolder);\n\n  T t_;\n};\n\n\n/// A Holder for a vector of basic types, e.g.\n/// std::vector<int32>, std::vector<float>, and so on.\n/// Note: a basic type is defined as a type for which ReadBasicType\n/// and WriteBasicType are implemented, i.e. integer and floating\n/// types, and bool.\ntemplate<class BasicType> class BasicVectorHolder {\n public:\n  typedef std::vector<BasicType> T;\n\n  BasicVectorHolder() { }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    InitKaldiOutputStream(os, binary);  // Puts binary header if binary mode.\n    try {\n      if (binary) {  // need to write the size, in binary mode.\n        KALDI_ASSERT(static_cast<size_t>(static_cast<int32>(t.size())) ==\n                     t.size());\n        // Or this Write routine cannot handle such a large vector.\n        // use int32 because it's fixed size regardless of compilation.\n        // change to int64 (plus in Read function) if this becomes a problem.\n        WriteBasicType(os, binary, static_cast<int32>(t.size()));\n        for (typename std::vector<BasicType>::const_iterator iter = t.begin();\n             iter != t.end(); ++iter)\n          WriteBasicType(os, binary, *iter);\n\n      } else {\n        for (typename std::vector<BasicType>::const_iterator iter = t.begin();\n             iter != t.end(); ++iter)\n          WriteBasicType(os, binary, *iter);\n        os << '\\n';  // Makes output format more readable and\n        // easier to manipulate.  In text mode, this function writes something\n        // like \"1 2 3\\n\".\n      }\n      return os.good();\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught writing Table object (BasicVector). \"\n                 << e.what();\n      return false;  // Write failure.\n    }\n  }\n\n  void Clear() { t_.clear(); }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    t_.clear();\n    bool is_binary;\n    if (!InitKaldiInputStream(is, &is_binary)) {\n      KALDI_WARN << \"Reading Table object [integer type], failed reading binary\"\n          \" header\\n\";\n      return false;\n    }\n    if (!is_binary) {\n      // In text mode, we terminate with newline.\n      std::string line;\n      getline(is, line);  // this will discard the \\n, if present.\n      if (is.fail()) {\n        KALDI_WARN << \"BasicVectorHolder::Read, error reading line \" <<\n            (is.eof() ? \"[eof]\" : \"\");\n        return false;  // probably eof.  fail in any case.\n      }\n      std::istringstream line_is(line);\n      try {\n        while (1) {\n          line_is >> std::ws;  // eat up whitespace.\n          if (line_is.eof()) break;\n          BasicType bt;\n          ReadBasicType(line_is, false, &bt);\n          t_.push_back(bt);\n        }\n        return true;\n      } catch(const std::exception &e) {\n        KALDI_WARN << \"BasicVectorHolder::Read, could not interpret line: \"\n                   << \"'\" << line << \"'\" << \"\\n\" << e.what();\n        return false;\n      }\n    } else {  // binary mode.\n      size_t filepos = is.tellg();\n      try {\n        int32 size;\n        ReadBasicType(is, true, &size);\n        t_.resize(size);\n        for (typename std::vector<BasicType>::iterator iter = t_.begin();\n             iter != t_.end();\n             ++iter) {\n          ReadBasicType(is, true, &(*iter));\n        }\n        return true;\n      } catch(...) {\n        KALDI_WARN << \"BasicVectorHolder::Read, read error or unexpected data\"\n            \" at archive entry beginning at file position \" << filepos;\n        return false;\n      }\n    }\n  }\n\n  // Objects read/written with the Kaldi I/O functions always have the stream\n  // open in binary mode for reading.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() { return t_; }\n\n  void Swap(BasicVectorHolder<BasicType> *other) {\n    t_.swap(other->t_);\n  }\n\n  bool ExtractRange(const BasicVectorHolder<BasicType> &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~BasicVectorHolder() { }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(BasicVectorHolder);\n  T t_;\n};\n\n\n/// BasicVectorVectorHolder is a Holder for a vector of vector of\n/// a basic type, e.g. std::vector<std::vector<int32> >.\n/// Note: a basic type is defined as a type for which ReadBasicType\n/// and WriteBasicType are implemented, i.e. integer and floating\n/// types, and bool.\ntemplate<class BasicType> class BasicVectorVectorHolder {\n public:\n  typedef std::vector<std::vector<BasicType> > T;\n\n  BasicVectorVectorHolder() { }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    InitKaldiOutputStream(os, binary);  // Puts binary header if binary mode.\n    try {\n      if (binary) {  // need to write the size, in binary mode.\n        KALDI_ASSERT(static_cast<size_t>(static_cast<int32>(t.size())) ==\n                     t.size());\n        // Or this Write routine cannot handle such a large vector.\n        // use int32 because it's fixed size regardless of compilation.\n        // change to int64 (plus in Read function) if this becomes a problem.\n        WriteBasicType(os, binary, static_cast<int32>(t.size()));\n        for (typename std::vector<std::vector<BasicType> >::const_iterator\n                 iter = t.begin();\n             iter != t.end(); ++iter) {\n          KALDI_ASSERT(static_cast<size_t>(static_cast<int32>(iter->size()))\n                       == iter->size());\n          WriteBasicType(os, binary, static_cast<int32>(iter->size()));\n          for (typename std::vector<BasicType>::const_iterator\n                   iter2 = iter->begin();\n               iter2 != iter->end(); ++iter2) {\n            WriteBasicType(os, binary, *iter2);\n          }\n        }\n      } else {  // text mode...\n        // In text mode, we write out something like (for integers):\n        // \"1 2 3 ; 4 5 ; 6 ; ; 7 8 9 ;\\n\"\n        // where the semicolon is a terminator, not a separator\n        // (a separator would cause ambiguity between an\n        // empty list, and a list containing a single empty list).\n        for (typename std::vector<std::vector<BasicType> >::const_iterator\n                 iter = t.begin();\n             iter != t.end();\n             ++iter) {\n          for (typename std::vector<BasicType>::const_iterator\n                   iter2 = iter->begin();\n               iter2 != iter->end(); ++iter2)\n            WriteBasicType(os, binary, *iter2);\n          os << \"; \";\n        }\n        os << '\\n';\n      }\n      return os.good();\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught writing Table object. \" << e.what();\n      return false;  // Write failure.\n    }\n  }\n\n  void Clear() { t_.clear(); }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    t_.clear();\n    bool is_binary;\n    if (!InitKaldiInputStream(is, &is_binary)) {\n      KALDI_WARN << \"Failed reading binary header\\n\";\n      return false;\n    }\n    if (!is_binary) {\n      // In text mode, we terminate with newline.\n      try {  // catching errors from ReadBasicType..\n        std::vector<BasicType> v;  // temporary vector\n        while (1) {\n          int i = is.peek();\n          if (i == -1) {\n            KALDI_WARN << \"Unexpected EOF\";\n            return false;\n          } else if (static_cast<char>(i) == '\\n') {\n            if (!v.empty()) {\n              KALDI_WARN << \"No semicolon before newline (wrong format)\";\n              return false;\n            } else {\n              is.get();\n              return true;\n            }\n          } else if (std::isspace(i)) {\n            is.get();\n          } else if (static_cast<char>(i) == ';') {\n            t_.push_back(v);\n            v.clear();\n            is.get();\n          } else {  // some object we want to read...\n            BasicType b;\n            ReadBasicType(is, false, &b);  // throws on error.\n            v.push_back(b);\n          }\n        }\n      } catch(const std::exception &e) {\n        KALDI_WARN << \"BasicVectorVectorHolder::Read, read error. \" << e.what();\n        return false;\n      }\n    } else {  // binary mode.\n      size_t filepos = is.tellg();\n      try {\n        int32 size;\n        ReadBasicType(is, true, &size);\n        t_.resize(size);\n        for (typename std::vector<std::vector<BasicType> >::iterator\n                 iter = t_.begin();\n             iter != t_.end();\n             ++iter) {\n          int32 size2;\n          ReadBasicType(is, true, &size2);\n          iter->resize(size2);\n          for (typename std::vector<BasicType>::iterator iter2 = iter->begin();\n               iter2 != iter->end();\n               ++iter2)\n            ReadBasicType(is, true, &(*iter2));\n        }\n        return true;\n      } catch(...) {\n        KALDI_WARN << \"Read error or unexpected data at archive entry beginning\"\n            \" at file position \" << filepos;\n        return false;\n      }\n    }\n  }\n\n  // Objects read/written with the Kaldi I/O functions always have the stream\n  // open in binary mode for reading.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {  return t_; }\n\n  void Swap(BasicVectorVectorHolder<BasicType> *other) {\n    t_.swap(other->t_);\n  }\n\n  bool ExtractRange(BasicVectorVectorHolder<BasicType> &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~BasicVectorVectorHolder() { }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(BasicVectorVectorHolder);\n  T t_;\n};\n\n\n/// BasicPairVectorHolder is a Holder for a vector of pairs of\n/// a basic type, e.g. std::vector<std::pair<int32, int32> >.\n/// Note: a basic type is defined as a type for which ReadBasicType\n/// and WriteBasicType are implemented, i.e. integer and floating\n/// types, and bool.\ntemplate<class BasicType> class BasicPairVectorHolder {\n public:\n  typedef std::vector<std::pair<BasicType, BasicType> > T;\n\n  BasicPairVectorHolder() { }\n\n  static bool Write(std::ostream &os, bool binary, const T &t) {\n    InitKaldiOutputStream(os, binary);  // Puts binary header if binary mode.\n    try {\n      if (binary) {  // need to write the size, in binary mode.\n        KALDI_ASSERT(static_cast<size_t>(static_cast<int32>(t.size())) ==\n                     t.size());\n        // Or this Write routine cannot handle such a large vector.\n        // use int32 because it's fixed size regardless of compilation.\n        // change to int64 (plus in Read function) if this becomes a problem.\n        WriteBasicType(os, binary, static_cast<int32>(t.size()));\n        for (typename T::const_iterator iter = t.begin();\n             iter != t.end(); ++iter) {\n          WriteBasicType(os, binary, iter->first);\n          WriteBasicType(os, binary, iter->second);\n        }\n      } else {  // text mode...\n        // In text mode, we write out something like (for integers):\n        // \"1 2 ; 4 5 ; 6 7 ; 8 9 \\n\"\n        // where the semicolon is a separator, not a terminator.\n        for (typename T::const_iterator iter = t.begin();\n             iter != t.end();) {\n          WriteBasicType(os, binary, iter->first);\n          WriteBasicType(os, binary, iter->second);\n          ++iter;\n          if (iter != t.end())\n            os << \"; \";\n        }\n        os << '\\n';\n      }\n      return os.good();\n    } catch(const std::exception &e) {\n      KALDI_WARN << \"Exception caught writing Table object. \" << e.what();\n      return false;  // Write failure.\n    }\n  }\n\n  void Clear() { t_.clear(); }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    t_.clear();\n    bool is_binary;\n    if (!InitKaldiInputStream(is, &is_binary)) {\n      KALDI_WARN << \"Reading Table object [integer type], failed reading binary\"\n          \" header\\n\";\n      return false;\n    }\n    if (!is_binary) {\n      // In text mode, we terminate with newline.\n      try {  // catching errors from ReadBasicType..\n        std::vector<BasicType> v;  // temporary vector\n        while (1) {\n          int i = is.peek();\n          if (i == -1) {\n            KALDI_WARN << \"Unexpected EOF\";\n            return false;\n          } else if (static_cast<char>(i) == '\\n') {\n            if (t_.empty() && v.empty()) {\n              is.get();\n              return true;\n            } else if (v.size() == 2) {\n              t_.push_back(std::make_pair(v[0], v[1]));\n              is.get();\n              return true;\n            } else {\n              KALDI_WARN << \"Unexpected newline, reading vector<pair<?> >; got \"\n                         << v.size() << \" elements, expected 2.\";\n              return false;\n            }\n          } else if (std::isspace(i)) {\n            is.get();\n          } else if (static_cast<char>(i) == ';') {\n            if (v.size() != 2) {\n              KALDI_WARN << \"Wrong input format, reading vector<pair<?> >; got \"\n                         << v.size() << \" elements, expected 2.\";\n              return false;\n            }\n            t_.push_back(std::make_pair(v[0], v[1]));\n            v.clear();\n            is.get();\n          } else {  // some object we want to read...\n            BasicType b;\n            ReadBasicType(is, false, &b);  // throws on error.\n            v.push_back(b);\n          }\n        }\n      } catch(const std::exception &e) {\n        KALDI_WARN << \"BasicPairVectorHolder::Read, read error. \" << e.what();\n        return false;\n      }\n    } else {  // binary mode.\n      size_t filepos = is.tellg();\n      try {\n        int32 size;\n        ReadBasicType(is, true, &size);\n        t_.resize(size);\n        for (typename T::iterator iter = t_.begin();\n             iter != t_.end();\n             ++iter) {\n          ReadBasicType(is, true, &(iter->first));\n          ReadBasicType(is, true, &(iter->second));\n        }\n        return true;\n      } catch(...) {\n        KALDI_WARN << \"BasicVectorHolder::Read, read error or unexpected data\"\n            \" at archive entry beginning at file position \" << filepos;\n        return false;\n      }\n    }\n  }\n\n  // Objects read/written with the Kaldi I/O functions always have the stream\n  // open in binary mode for reading.\n  static bool IsReadInBinary() { return true; }\n\n  T &Value() {  return t_; }\n\n  void Swap(BasicPairVectorHolder<BasicType> *other) {\n    t_.swap(other->t_);\n  }\n\n  bool ExtractRange(const BasicPairVectorHolder<BasicType> &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  ~BasicPairVectorHolder() { }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(BasicPairVectorHolder);\n  T t_;\n};\n\n\n\n\n// We define a Token as a nonempty, printable, whitespace-free std::string.\n// The binary and text formats here are the same (newline-terminated)\n// and as such we don't bother with the binary-mode headers.\nclass TokenHolder {\n public:\n  typedef std::string T;\n\n  TokenHolder() {}\n\n  static bool Write(std::ostream &os, bool, const T &t) {  // ignore binary-mode\n    KALDI_ASSERT(IsToken(t));\n    os << t << '\\n';\n    return os.good();\n  }\n\n  void Clear() { t_.clear(); }\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    is >> t_;\n    if (is.fail()) return false;\n    char c;\n    while (isspace(c = is.peek()) && c!= '\\n') is.get();\n    if (is.peek() != '\\n') {\n      KALDI_WARN << \"TokenHolder::Read, expected newline, got char \"\n        << CharToString(is.peek())\n        << \", at stream pos \" << is.tellg();\n      return false;\n    }\n    is.get();  // get '\\n'\n    return true;\n  }\n\n\n  // Since this is fundamentally a text format, read in text mode (would work\n  // fine either way, but doing it this way will exercise more of the code).\n  static bool IsReadInBinary() { return false; }\n\n  T &Value() { return t_; }\n\n  ~TokenHolder() { }\n\n  void Swap(TokenHolder *other) {\n    t_.swap(other->t_);\n  }\n\n  bool ExtractRange(const TokenHolder &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(TokenHolder);\n  T t_;\n};\n\n// A Token is a nonempty, whitespace-free std::string.\n// Class TokenVectorHolder is a Holder class for vectors of these.\nclass TokenVectorHolder {\n public:\n  typedef std::vector<std::string> T;\n\n  TokenVectorHolder() { }\n\n  static bool Write(std::ostream &os, bool, const T &t) {  // ignore binary-mode\n    for (std::vector<std::string>::const_iterator iter = t.begin();\n         iter != t.end();\n         ++iter) {\n      KALDI_ASSERT(IsToken(*iter));  // make sure it's whitespace-free,\n      // printable and nonempty.\n      os << *iter << ' ';\n    }\n    os << '\\n';\n    return os.good();\n  }\n\n  void Clear() { t_.clear(); }\n\n\n  // Reads into the holder.\n  bool Read(std::istream &is) {\n    t_.clear();\n\n    // there is no binary/non-binary mode.\n\n    std::string line;\n    getline(is, line);  // this will discard the \\n, if present.\n    if (is.fail()) {\n      KALDI_WARN << \"BasicVectorHolder::Read, error reading line \" << (is.eof()\n                                                                       ? \"[eof]\" : \"\");\n      return false;  // probably eof.  fail in any case.\n    }\n    const char *white_chars = \" \\t\\n\\r\\f\\v\";\n    SplitStringToVector(line, white_chars, true, &t_);  // true== omit\n    // empty strings e.g. between spaces.\n    return true;\n  }\n\n  // Read in text format since it's basically a text-mode thing.. doesn't really\n  // matter, it would work either way since we ignore the extra '\\r'.\n  static bool IsReadInBinary() { return false; }\n\n  T &Value() { return t_; }\n\n  void Swap(TokenVectorHolder *other) {\n    t_.swap(other->t_);\n  }\n\n  bool ExtractRange(const TokenVectorHolder &other,\n                    const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(TokenVectorHolder);\n  T t_;\n};\n\n\n//class HtkMatrixHolder {\n //public:\n  //typedef std::pair<Matrix<BaseFloat>, HtkHeader> T;\n\n  //HtkMatrixHolder() {}\n\n  //static bool Write(std::ostream &os, bool binary, const T &t) {\n    //if (!binary)\n      //KALDI_ERR << \"Non-binary HTK-format write not supported.\";\n    //bool ans = WriteHtk(os, t.first, t.second);\n    //if (!ans)\n      //KALDI_WARN << \"Error detected writing HTK-format matrix.\";\n    //return ans;\n  //}\n\n  //void Clear() { t_.first.Resize(0, 0); }\n\n  //// Reads into the holder.\n  //bool Read(std::istream &is) {\n    //bool ans = ReadHtk(is, &t_.first, &t_.second);\n    //if (!ans) {\n      //KALDI_WARN << \"Error detected reading HTK-format matrix.\";\n      //return false;\n    //}\n    //return ans;\n  //}\n\n  //// HTK-format matrices only read in binary.\n  //static bool IsReadInBinary() { return true; }\n\n  //T &Value() { return t_; }\n\n  //void Swap(HtkMatrixHolder *other) {\n    //t_.first.Swap(&(other->t_.first));\n    //std::swap(t_.second, other->t_.second);\n  //}\n\n  //bool ExtractRange(const HtkMatrixHolder &other,\n                    //const std::string &range) {\n    //KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    //return false;\n  //}\n  //// Default destructor.\n //private:\n  //KALDI_DISALLOW_COPY_AND_ASSIGN(HtkMatrixHolder);\n  //T t_;\n//};\n\n// SphinxMatrixHolder can be used to read and write feature files in\n// CMU Sphinx format. 13-dimensional big-endian features are assumed.\n// The ultimate reference is SphinxBase's source code (for example see\n// feat_s2mfc_read() in src/libsphinxbase/feat/feat.c).\n// We can't fully automate the detection of machine/feature file endianess\n// mismatch here, because for this Sphinx relies on comparing the feature\n// file's size with the number recorded in its header. We are working with\n// streams, however(what happens if this is a Kaldi archive?). This should\n// be no problem, because the usage help of Sphinx' \"wave2feat\" for example\n// says that Sphinx features are always big endian.\n// Note: the kFeatDim defaults to 13, see forward declaration in kaldi-holder.h\n//template<int kFeatDim> class SphinxMatrixHolder {\n //public:\n  //typedef Matrix<BaseFloat> T;\n\n  //SphinxMatrixHolder() {}\n\n  //void Clear() { feats_.Resize(0, 0); }\n\n  //// Writes Sphinx-format features\n  //static bool Write(std::ostream &os, bool binary, const T &m) {\n    //if (!binary) {\n      //KALDI_WARN << \"SphinxMatrixHolder can't write Sphinx features in text \";\n      //return false;\n    //}\n\n    //int32 size = m.NumRows() * m.NumCols();\n    //if (MachineIsLittleEndian())\n      //KALDI_SWAP4(size);\n    //// write the header\n    //os.write(reinterpret_cast<char*> (&size), sizeof(size));\n\n    //for (MatrixIndexT i = 0; i < m.NumRows(); i++) {\n      //std::vector<float32> tmp(m.NumCols());\n      //for (MatrixIndexT j = 0; j < m.NumCols(); j++) {\n        //tmp[j] = static_cast<float32>(m(i, j));\n        //if (MachineIsLittleEndian())\n          //KALDI_SWAP4(tmp[j]);\n      //}\n      //os.write(reinterpret_cast<char*>(&(tmp[0])),\n               //tmp.size() * 4);\n    //}\n    //return true;\n  //}\n\n  //// Reads the features into a Kaldi Matrix\n  //bool Read(std::istream &is) {\n    //int32 nmfcc;\n\n    //is.read(reinterpret_cast<char*> (&nmfcc), sizeof(nmfcc));\n    //if (MachineIsLittleEndian())\n      //KALDI_SWAP4(nmfcc);\n    //KALDI_VLOG(2) << \"#feats: \" << nmfcc;\n    //int32 nfvec = nmfcc / kFeatDim;\n    //if ((nmfcc % kFeatDim) != 0) {\n      //KALDI_WARN << \"Sphinx feature count is inconsistent with vector length \";\n      //return false;\n    //}\n\n    //feats_.Resize(nfvec, kFeatDim);\n    //for (MatrixIndexT i = 0; i < feats_.NumRows(); i++) {\n      //if (sizeof(BaseFloat) == sizeof(float32)) {\n        //is.read(reinterpret_cast<char*> (feats_.RowData(i)),\n                //kFeatDim * sizeof(float32));\n        //if (!is.good()) {\n          //KALDI_WARN << \"Unexpected error/EOF while reading Sphinx features \";\n          //return false;\n        //}\n        //if (MachineIsLittleEndian()) {\n          //for (MatrixIndexT j = 0; j < kFeatDim; j++)\n            //KALDI_SWAP4(feats_(i, j));\n        //}\n      //} else {  // KALDI_DOUBLEPRECISION=1\n        //float32 tmp[kFeatDim];\n        //is.read(reinterpret_cast<char*> (tmp), sizeof(tmp));\n        //if (!is.good()) {\n          //KALDI_WARN << \"Unexpected error/EOF while reading Sphinx features \";\n          //return false;\n        //}\n        //for (MatrixIndexT j = 0; j < kFeatDim; j++) {\n          //if (MachineIsLittleEndian())\n            //KALDI_SWAP4(tmp[j]);\n          //feats_(i, j) = static_cast<BaseFloat>(tmp[j]);\n        //}\n      //}\n    //}\n\n    //return true;\n  //}\n\n  //// Only read in binary\n  //static bool IsReadInBinary() { return true; }\n\n  //T &Value() { return feats_; }\n\n  //void Swap(SphinxMatrixHolder *other) {\n    //feats_.Swap(&(other->feats_));\n  //}\n\n  //bool ExtractRange(const SphinxMatrixHolder &other,\n                    //const std::string &range) {\n    //KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    //return false;\n  //}\n\n //private:\n  //KALDI_DISALLOW_COPY_AND_ASSIGN(SphinxMatrixHolder);\n  //T feats_;\n//};\n\n\n/// @} end \"addtogroup holders\"\n\n}  // end namespace kaldi\n\n\n\n#endif  // KALDI_UTIL_KALDI_HOLDER_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-holder.cc",
    "content": "// util/kaldi-holder.cc\n\n// Copyright 2009-2011     Microsoft Corporation\n//                2016     Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"util/kaldi-holder.h\"\n#include \"matrix/kaldi-matrix.h\"\n\nnamespace kaldi {\n\n// Parse matrix range specifier in form r1:r2,c1:c2\n// where any of those four numbers can be missing. In those\n// cases, the missing number is set either to 0 (for r1 or c1)\n// or the value of parameter rows -1 or columns -1 (which\n// represent the dimensions of the original matrix) for missing\n// r2 or c2, respectively.\n// Examples of valid ranges: 0:39,: or :,:3 or :,5:10\nbool ParseMatrixRangeSpecifier(const std::string &range,\n                         const int rows, const int cols,\n                          std::vector<int32> *row_range,\n                          std::vector<int32> *col_range) {\n  if (range.empty()) {\n    KALDI_ERR << \"Empty range specifier.\";\n    return false;\n  }\n  std::vector<std::string> splits;\n  SplitStringToVector(range, \",\", false, &splits);\n  if (!((splits.size() == 1 && !splits[0].empty()) ||\n        (splits.size() == 2  && !splits[0].empty() && !splits[1].empty()))) {\n    KALDI_ERR << \"Invalid range specifier for matrix: \" << range;\n    return false;\n  }\n\n  bool status = true;\n\n  if (splits[0] != \":\")\n    status = SplitStringToIntegers(splits[0], \":\", false, row_range);\n\n  if (splits.size() == 2 && splits[1] != \":\") {\n    status = status && SplitStringToIntegers(splits[1], \":\", false, col_range);\n  }\n  if (row_range->size() == 0) {\n    row_range->push_back(0);\n    row_range->push_back(rows - 1);\n  }\n  if (col_range->size() == 0) {\n    col_range->push_back(0);\n    col_range->push_back(cols - 1);\n  }\n\n  // Length tolerance of 3 -- 2 to account for edge effects when\n  // frame-length is 25ms and frame-shift is 10ms, and 1 for rounding effects\n  // since segments are usually retained up to 2 decimal places.\n  int32 length_tolerance = 3;\n  if (!(status && row_range->size() == 2 && col_range->size() == 2 &&\n        row_range->at(0) >= 0 && row_range->at(0) <= row_range->at(1) &&\n        row_range->at(1) < rows + length_tolerance &&\n        col_range->at(0) >=0 &&\n        col_range->at(0) <= col_range->at(1) && col_range->at(1) < cols)) {\n    KALDI_ERR << \"Invalid range specifier: \" << range\n              << \" for matrix of size \" << rows\n              << \"x\" << cols;\n    return false;\n  }\n\n  if (row_range->at(1) >= rows)\n    KALDI_WARN << \"Row range \" << row_range->at(0) << \":\" << row_range->at(1)\n               << \" goes beyond the number of rows of the \"\n               << \"matrix \" << rows;\n  return status;\n}\n\n/*bool ExtractObjectRange(const GeneralMatrix &input, const std::string &range,\n                        GeneralMatrix *output) {\n  // We just inspect input's type and forward to the correct implementation\n  // if available. For kSparseMatrix, we do just fairly inefficient conversion\n  // to a full matrix.\n  Matrix<BaseFloat> output_mat;\n  if (input.Type() == kFullMatrix) {\n    const Matrix<BaseFloat> &in = input.GetFullMatrix();\n    ExtractObjectRange(in, range, &output_mat);\n  } else if (input.Type() == kCompressedMatrix) {\n    const CompressedMatrix &in = input.GetCompressedMatrix();\n    ExtractObjectRange(in, range, &output_mat);\n  } else {\n    KALDI_ASSERT(input.Type() == kSparseMatrix);\n    // NOTE: this is fairly inefficient, so if this happens to be bottleneck\n    // it should be re-implemented more efficiently.\n    Matrix<BaseFloat> input_mat;\n    input.GetMatrix(&input_mat);\n    ExtractObjectRange(input_mat, range, &output_mat);\n  }\n  output->Clear();\n  output->SwapFullMatrix(&output_mat);\n  return true;\n}\n\ntemplate<class Real>\nbool ExtractObjectRange(const CompressedMatrix &input, const std::string &range,\n                        Matrix<Real> *output) {\n  std::vector<int32> row_range, col_range;\n\n  if (!ParseMatrixRangeSpecifier(range, input.NumRows(), input.NumCols(),\n                                 &row_range, &col_range)) {\n    KALDI_ERR << \"Could not parse range specifier \\\"\" << range << \"\\\".\";\n  }\n\n  int32 row_size = std::min(row_range[1], input.NumRows() - 1)\n                   - row_range[0] + 1,\n        col_size = col_range[1] - col_range[0] + 1;\n\n  output->Resize(row_size, col_size, kUndefined);\n  input.CopyToMat(row_range[0], col_range[0], output);\n  return true;\n}\n\n// template instantiation\ntemplate bool ExtractObjectRange(const CompressedMatrix &, const std::string &,\n                                 Matrix<float> *);\ntemplate bool ExtractObjectRange(const CompressedMatrix &, const std::string &,\n                                 Matrix<double> *);\n\n*/\ntemplate<class Real>\nbool ExtractObjectRange(const Matrix<Real> &input, const std::string &range,\n                        Matrix<Real> *output) {\n  std::vector<int32> row_range, col_range;\n\n  if (!ParseMatrixRangeSpecifier(range, input.NumRows(), input.NumCols(),\n                                 &row_range, &col_range)) {\n    KALDI_ERR << \"Could not parse range specifier \\\"\" << range << \"\\\".\";\n  }\n\n  int32 row_size = std::min(row_range[1], input.NumRows() - 1)\n                   - row_range[0] + 1,\n        col_size = col_range[1] - col_range[0] + 1;\n  output->Resize(row_size, col_size, kUndefined);\n  output->CopyFromMat(input.Range(row_range[0], row_size,\n                                  col_range[0], col_size));\n  return true;\n}\n\n// template instantiation\ntemplate bool ExtractObjectRange(const Matrix<double> &, const std::string &,\n                                 Matrix<double> *);\ntemplate bool ExtractObjectRange(const Matrix<float> &, const std::string &,\n                                 Matrix<float> *);\n\ntemplate<class Real>\nbool ExtractObjectRange(const Vector<Real> &input, const std::string &range,\n                        Vector<Real> *output) {\n  if (range.empty()) {\n    KALDI_ERR << \"Empty range specifier.\";\n    return false;\n  }\n  std::vector<std::string> splits;\n  SplitStringToVector(range, \",\", false, &splits);\n  if (!((splits.size() == 1 && !splits[0].empty()))) {\n    KALDI_ERR << \"Invalid range specifier for vector: \" << range;\n    return false;\n  }\n  std::vector<int32> index_range;\n  bool status = true;\n  if (splits[0] != \":\")\n    status = SplitStringToIntegers(splits[0], \":\", false, &index_range);\n\n  if (index_range.size() == 0) {\n    index_range.push_back(0);\n    index_range.push_back(input.Dim() - 1);\n  }\n\n  // Length tolerance of 3 -- 2 to account for edge effects when\n  // frame-length is 25ms and frame-shift is 10ms, and 1 for rounding effects\n  // since segments are usually retained up to 2 decimal places.\n  int32 length_tolerance = 3;\n  if (!(status && index_range.size() == 2 &&\n        index_range[0] >= 0 && index_range[0] <= index_range[1] &&\n        index_range[1] < input.Dim() + length_tolerance)) {\n    KALDI_ERR << \"Invalid range specifier: \" << range\n              << \" for vector of size \" << input.Dim();\n    return false;\n  }\n\n  if (index_range[1] >= input.Dim())\n    KALDI_WARN << \"Range \" << index_range[0] << \":\" << index_range[1]\n               << \" goes beyond the vector dimension \" << input.Dim();\n  int32 size = std::min(index_range[1], input.Dim() - 1) - index_range[0] + 1;\n  output->Resize(size, kUndefined);\n  output->CopyFromVec(input.Range(index_range[0], size));\n  return true;\n}\n\n// template instantiation\ntemplate bool ExtractObjectRange(const Vector<double> &, const std::string &,\n                                 Vector<double> *);\ntemplate bool ExtractObjectRange(const Vector<float> &, const std::string &,\n                                 Vector<float> *);\n\nbool ExtractRangeSpecifier(const std::string &rxfilename_with_range,\n                           std::string *data_rxfilename,\n                           std::string *range) {\n  if (rxfilename_with_range.empty() ||\n      rxfilename_with_range[rxfilename_with_range.size()-1] != ']')\n    KALDI_ERR << \"ExtractRangeRspecifier called wrongly.\";\n  std::vector<std::string> splits;\n  SplitStringToVector(rxfilename_with_range, \"[\", false, &splits);\n  if (splits.size() == 2 && !splits[0].empty() && splits[1].size() > 1) {\n    *data_rxfilename = splits[0];\n    range->assign(splits[1], 0, splits[1].size()-1);\n    return true;\n  }\n  return false;\n}\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-holder.h",
    "content": "// util/kaldi-holder.h\n\n// Copyright 2009-2011     Microsoft Corporation\n//                2016     Johns Hopkins University (author: Daniel Povey)\n//                2016     Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_KALDI_HOLDER_H_\n#define KALDI_UTIL_KALDI_HOLDER_H_\n\n#include <algorithm>\n#include \"util/kaldi-io.h\"\n#include \"util/text-utils.h\"\n#include \"matrix/kaldi-vector.h\"\n\nnamespace kaldi {\n\n\n// The Table class uses a Holder class to wrap objects, and make them behave\n// in a \"normalized\" way w.r.t. reading and writing, so the Table class can\n// be template-ized without too much trouble. Look below this\n// comment (search for GenericHolder) to see what it looks like.\n//\n//  Requirements of the holder class:\n//\n// They can only contain objects that can be read/written without external\n// information; other objects cannot be stored in this type of archive.\n//\n// In terms of what functions it should have, see GenericHolder below.\n// It is just for documentation.\n//\n// (1) Requirements of the Read and Write functions\n//\n// The Read and Write functions should have the property that in a longer\n// file, if the Read function is started from where the Write function started\n// writing, it should go to where the Write function stopped writing, in either\n// text or binary mode (but it's OK if it doesn't eat up trailing space).\n//\n//     [Desirable property: when writing in text mode the output should contain\n//      exactly one newline, at the end of the output; this makes it easier to\n//      manipulate]\n//\n//     [Desirable property for classes: the output should just be a binary-mode\n//      header (if in binary mode and it's a Kaldi object, or no header\n//      othewise), and then the output of Object.Write().  This means that when\n//      written to individual files with the scp: type of wspecifier, we can\n//      read the individual files in the \"normal\" Kaldi way by reading the\n//      binary header and then the object.]\n//\n//\n// The Write function takes a 'binary' argument.  In general, each object will\n// have two formats: text and binary.  However, it's permitted to throw() if\n// asked to read in the text format if there is none.  The file will be open, if\n// the file system has binary/text modes, in the corresponding mode.  However,\n// the object should have a file-mode in which it can read either text or binary\n// output.  It announces this via the static IsReadInBinary() function.  This\n// will generally be the binary mode and it means that where necessary, in text\n// formats, we must ignore \\r characters.\n//\n// Memory requirements: if it allocates memory, the destructor should\n// free that memory.  Copying and assignment of Holder objects may be\n// disallowed as the Table code never does this.\n\n\n/// GenericHolder serves to document the requirements of the Holder interface;\n/// it's not intended to be used.\ntemplate<class SomeType> class GenericHolder {\n public:\n  typedef SomeType T;\n\n  /// Must have a constructor that takes no arguments.\n  GenericHolder() { }\n\n  /// Write() writes this object of type T.  Possibly also writes a binary-mode\n  /// header so that the Read function knows which mode to read in (since the\n  /// Read function does not get this information).  It's a static member so we\n  /// can write those not inside this class (can use this function with Value()\n  /// to write from this class).  The Write method may throw if it cannot write\n  /// the object in the given (binary/non-binary) mode.  The holder object can\n  /// assume the stream has been opened in the given mode (where relevant).  The\n  /// object can write the data how it likes.\n  static bool Write(std::ostream &os, bool binary, const T &t);\n\n  /// Reads into the holder.  Must work out from the stream (which will be\n  /// opened on Windows in binary mode if the IsReadInBinary() function of this\n  /// class returns true, and text mode otherwise) whether the actual data is\n  /// binary or not (usually via reading the Kaldi binary-mode header).\n  /// We put the responsibility for reading the Kaldi binary-mode header in the\n  /// Read function (rather than making the binary mode an argument to this\n  /// function), so that for non-Kaldi binary files we don't have to write the\n  /// header, which would prevent the file being read by non-Kaldi programs\n  /// (e.g. if we write to individual files using an scp).\n  /// Read must deallocate any existing data we have here, if applicable (must\n  /// not assume the object was newly constructed).\n  /// Returns true on success.\n  /// If Read() returns false, the contents of this object and hence the value\n  /// returned by Value() may be undefined.\n  bool Read(std::istream &is);\n\n  /// IsReadInBinary() will return true if the object wants the file to be\n  /// opened in binary for reading (if the file system has binary/text modes),\n  /// and false otherwise.  Static function.  Kaldi objects always return true\n  /// as they always read in binary mode.  Note that we must be able to read, in\n  /// this mode, objects written in both text and binary mode by Write (which\n  /// may mean ignoring \"\\r\" characters).  I doubt we will ever want this\n  /// function to return false.\n  static bool IsReadInBinary() { return true; }\n\n  /// Returns the value of the object held here.  Will only\n  /// ever be called if Read() has been previously called and it returned\n  /// true (so OK to throw exception if no object was read).\n  T &Value() { return t_; }  // if t is a pointer, would return *t_;\n\n  /// The Clear() function doesn't have to do anything.  Its purpose is to\n  /// allow the object to free resources if they're no longer needed.\n  void Clear() { }\n\n  /// This swaps the objects held by *this and *other (preferably a shallow\n  /// swap).  Note, this is just an example.  The swap is with the *same type*\n  /// of holder, not with some nonexistent base-class (remember, GenericHolder is\n  /// an example for documentation, not a base-class).\n  void Swap(GenericHolder<T> *other) { std::swap(t_, other->t_); }\n\n  /// At the time of writing this will only do something meaningful\n  /// KaldiObjectHolder holding matrix objects, in order to extract a holder\n  /// holding a sub-matrix specified by 'range', e.g. [0:3,2:10], like in Matlab\n  /// but with zero-based indexing. It returns true with successful extraction\n  /// of the range, false if the range was invalid or outside the bounds of the\n  /// matrix.  For other types of holder it just throws an error.\n  bool ExtractRange(const GenericHolder<T> &other, const std::string &range) {\n    KALDI_ERR << \"ExtractRange is not defined for this type of holder.\";\n    return false;\n  }\n\n  /// If the object held pointers, the destructor would free them.\n  ~GenericHolder() { }\n\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(GenericHolder);\n  T t_;  // t_ may alternatively be of type T*.\n};\n\n\n// See kaldi-holder-inl.h for examples of some actual Holder\n// classes and templates.\n\n\n// The following two typedefs should probably be in their own file, but they're\n// here until there are enough of them to warrant their own header.\n\n\n/// \\addtogroup holders\n/// @{\n\n/// KaldiObjectHolder works for Kaldi objects that have the \"standard\" Read\n/// and Write functions, and a copy constructor.\ntemplate<class KaldiType> class KaldiObjectHolder;\n\n/// BasicHolder is valid for float, double, bool, and integer\n/// types.  There will be a compile time error otherwise, because\n/// we make sure that the {Write, Read}BasicType functions do not\n/// get instantiated for other types.\ntemplate<class BasicType> class BasicHolder;\n\n\n// A Holder for a vector of basic types, e.g.\n// std::vector<int32>, std::vector<float>, and so on.\n// Note: a basic type is defined as a type for which ReadBasicType\n// and WriteBasicType are implemented, i.e. integer and floating\n// types, and bool.\ntemplate<class BasicType> class BasicVectorHolder;\n\n\n// A holder for vectors of vectors of basic types, e.g.\n// std::vector<std::vector<int32> >, and so on.\n// Note: a basic type is defined as a type for which ReadBasicType\n// and WriteBasicType are implemented, i.e. integer and floating\n// types, and bool.\ntemplate<class BasicType> class BasicVectorVectorHolder;\n\n// A holder for vectors of pairs of basic types, e.g.\n// std::vector<std::pair<int32, int32> >, and so on.\n// Note: a basic type is defined as a type for which ReadBasicType\n// and WriteBasicType are implemented, i.e. integer and floating\n// types, and bool.  Text format is (e.g. for integers),\n// \"1 12 ; 43 61 ; 17 8 \\n\"\ntemplate<class BasicType> class BasicPairVectorHolder;\n\n/// We define a Token (not a typedef, just a word) as a nonempty, printable,\n/// whitespace-free std::string.  The binary and text formats here are the same\n/// (newline-terminated) and as such we don't bother with the binary-mode\n/// headers.\nclass TokenHolder;\n\n/// Class TokenVectorHolder is a Holder class for vectors of Tokens\n/// (T == std::string).\nclass TokenVectorHolder;\n\n/// A class for reading/writing HTK-format matrices.\n/// T == std::pair<Matrix<BaseFloat>, HtkHeader>\n//class HtkMatrixHolder;\n\n/// A class for reading/writing Sphinx format matrices.\n//template<int kFeatDim = 13> class SphinxMatrixHolder;\n\n/// This templated function exists so that we can write .scp files with\n/// 'object ranges' specified: the canonical example is a [first:last] range\n/// of rows of a matrix, or [first-row:last-row,first-column,last-column]\n/// of a matrix.  We can also support [begin-time:end-time] of a wave\n/// file.  The string 'range' is whatever is in the square brackets; it is\n/// parsed inside this function.\n/// This function returns true if the partial object was successfully extracted,\n/// and false if there was an error such as an invalid range.\n/// The generic version of this function just fails; we overload the template\n/// whenever we need it for a specific class.\ntemplate <class T>\nbool ExtractObjectRange(const T &input, const std::string &range, T *output) {\n  KALDI_ERR << \"Ranges not supported for objects of this type.\";\n  return false;\n}\n\n/// The template is specialized with a version that actually does something,\n/// for types Matrix<float> and Matrix<double>.  We can later add versions of\n/// this template for other types, such as Vector, which can meaningfully\n/// have ranges extracted.\ntemplate <class Real>\nbool ExtractObjectRange(const Matrix<Real> &input, const std::string &range,\n                        Matrix<Real> *output);\n\n/// The template is specialized types Vector<float> and Vector<double>.\ntemplate <class Real>\nbool ExtractObjectRange(const Vector<Real> &input, const std::string &range,\n                        Vector<Real> *output);\n\n/// GeneralMatrix is always of type BaseFloat\n//bool ExtractObjectRange(const GeneralMatrix &input, const std::string &range,\n //                       GeneralMatrix *output);\n\n/// CompressedMatrix is always of the type BaseFloat but it is more\n/// efficient to provide template as it uses CompressedMatrix's own\n/// conversion to Matrix<Real>\n//template <class Real>\n//bool ExtractObjectRange(const CompressedMatrix &input, const std::string &range,\n //                       Matrix<Real> *output);\n\n// In SequentialTableReaderScriptImpl and RandomAccessTableReaderScriptImpl, for\n// cases where the scp contained 'range specifiers' (things in square brackets\n// identifying parts of objects like matrices), use this function to separate\n// the input string 'rxfilename_with_range' (e.g \"1.ark:100[1:2,2:10]\") into the data_rxfilename\n// (e.g. \"1.ark:100\") and the optional range specifier which will be everything\n// inside the square brackets.  It returns true if everything seems OK, and\n// false if for example the string contained more than one '['.  This function\n// should only be called if 'line' ends in ']', otherwise it is an error.\nbool ExtractRangeSpecifier(const std::string &rxfilename_with_range,\n                           std::string *data_rxfilename,\n                           std::string *range);\n\n\n/// @} end \"addtogroup holders\"\n\n\n}  // end namespace kaldi\n\n#include \"util/kaldi-holder-inl.h\"\n\n#endif  // KALDI_UTIL_KALDI_HOLDER_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-io-inl.h",
    "content": "// util/kaldi-io-inl.h\n\n// Copyright 2009-2011 Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_UTIL_KALDI_IO_INL_H_\n#define KALDI_UTIL_KALDI_IO_INL_H_\n\n#include<string>\n\nnamespace kaldi {\n\nbool Input::Open(const std::string &rxfilename, bool *binary) {\n  return OpenInternal(rxfilename, true, binary);\n}\n\nbool Input::OpenTextMode(const std::string &rxfilename) {\n  return OpenInternal(rxfilename, false, NULL);\n}\n\nbool Input::IsOpen() {\n  return impl_ != NULL;\n}\n\nbool Output::IsOpen() {\n  return impl_ != NULL;\n}\n\n\n}  // end namespace kaldi.\n\n\n#endif  // KALDI_UTIL_KALDI_IO_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-io.cc",
    "content": "// util/kaldi-io.cc\n\n// Copyright 2009-2011  Microsoft Corporation;  Jan Silovsky\n//                2016  Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#include \"util/kaldi-io.h\"\n#include <errno.h>\n#include <cstdlib>\n#include \"base/kaldi-math.h\"\n#include \"util/text-utils.h\"\n#include \"util/parse-options.h\"\n#include \"util/kaldi-holder.h\"\n#include \"util/kaldi-pipebuf.h\"\n#include \"util/kaldi-table.h\"  // for Classify{W,R}specifier\n#include <stdio.h>\n#include <stdlib.h>\n\n#ifdef KALDI_CYGWIN_COMPAT\n#include \"util/kaldi-cygwin-io-inl.h\"\n#define MapOsPath(x) MapCygwinPath(x)\n#else  // KALDI_CYGWIN_COMPAT\n#define MapOsPath(x) x\n#endif  // KALDI_CYGWIN_COMPAT\n\n\n#if defined(_MSC_VER) \nstatic FILE *popen(const char* command, const char* mode) {\n#ifdef KALDI_CYGWIN_COMPAT\n  return kaldi::CygwinCompatPopen(command, mode);\n#else  // KALDI_CYGWIN_COMPAT\n  return _popen(command, mode);\n#endif  // KALDI_CYGWIN_COMPAT\n}\n#endif  // _MSC_VER\n\nnamespace kaldi {\n\n#ifndef _MSC_VER  // on VS, we don't need this type.\n// could replace basic_pipebuf<char> with stdio_filebuf<char> on some platforms.\n// Would mean we could use less of our own code.\ntypedef basic_pipebuf<char> PipebufType;\n#endif\n}\n\nnamespace kaldi {\n\nstd::string PrintableRxfilename(const std::string &rxfilename) {\n  if (rxfilename == \"\" || rxfilename == \"-\") {\n    return \"standard input\";\n  } else {\n    // If this call to Escape later causes compilation issues,\n    // just replace it with \"return rxfilename\"; it's only a\n    // pretty-printing issue.\n    return ParseOptions::Escape(rxfilename);\n  }\n}\n\n\nstd::string PrintableWxfilename(const std::string &wxfilename) {\n  if (wxfilename == \"\" || wxfilename == \"-\") {\n    return \"standard output\";\n  } else {\n    // If this call to Escape later causes compilation issues,\n    // just replace it with \"return wxfilename\"; it's only a\n    // pretty-printing issue.\n    return ParseOptions::Escape(wxfilename);\n  }\n}\n\n\nOutputType ClassifyWxfilename(const std::string &filename) {\n  const char *c = filename.c_str();\n  size_t length = filename.length();\n  char first_char = c[0],\n      last_char = (length == 0 ? '\\0' : c[filename.length()-1]);\n\n  // if 'filename' is \"\" or \"-\", return kStandardOutput.\n  if (length == 0 || (length == 1 && first_char == '-'))\n    return kStandardOutput;\n  else if (first_char == '|') return kPipeOutput;  // An output pipe like \"|blah\".\n  else if (isspace(first_char) || isspace(last_char) || last_char == '|') {\n      return kNoOutput;  // Leading or trailing space: can't interpret this.\n                         // Final '|' would represent an input pipe, not an\n                         // output pipe.\n  } else if ((first_char == 'a' || first_char == 's') &&\n             strchr(c, ':') != NULL &&\n             (ClassifyWspecifier(filename, NULL, NULL, NULL) != kNoWspecifier ||\n              ClassifyRspecifier(filename, NULL, NULL) != kNoRspecifier)) {\n    // e.g. ark:something or scp:something... this is almost certainly a\n    // scripting error, so call it an error rather than treating it as a file.\n    // In practice in modern kaldi scripts all (r,w)filenames begin with \"ark\"\n    // or \"scp\", even though technically speaking options like \"b\", \"t\", \"s\" or\n    // \"cs\" can appear before the ark or scp, like \"b,ark\".  For efficiency,\n    // and because this code is really just a nicety to catch errors earlier\n    // than they would otherwise be caught, we only call those extra functions\n    // for filenames beginning with 'a' or 's'.\n    return kNoOutput;\n  } else if (isdigit(last_char)) {\n    // This could be a file, but we have to see if it's an offset into a file\n    // (like foo.ark:4314328), which is not allowed for writing (but is\n    // allowed for reaching).  This eliminates some things which would be\n    // valid UNIX filenames but are not allowed by Kaldi.  (Even if we allowed\n    // such filenames for writing, we woudln't be able to correctly read them).\n    const char *d = c + length - 1;\n    while (isdigit(*d) && d > c) d--;\n    if (*d == ':') return kNoOutput;\n    // else it could still be a filename; continue to the next check.\n  }\n\n  // At this point it matched no other pattern so we assume a filename, but we\n  // check for internal '|' as it's a common source of errors to have pipe\n  // commands without the pipe in the right place.  Say that it can't be\n  // classified.\n  if (strchr(c, '|') != NULL) {\n    KALDI_WARN << \"Trying to classify wxfilename with pipe symbol in the\"\n        \" wrong place (pipe without | at the beginning?): \" <<\n        filename;\n    return kNoOutput;\n  }\n  return kFileOutput;  // It matched no other pattern: assume it's a filename.\n}\n\n\nInputType ClassifyRxfilename(const std::string &filename) {\n  const char *c = filename.c_str();\n  size_t length = filename.length();\n  char first_char = c[0],\n      last_char = (length == 0 ? '\\0' : c[filename.length()-1]);\n\n  // if 'filename' is \"\" or \"-\", return kStandardInput.\n  if (length == 0 || (length == 1 && first_char == '-')) {\n    return kStandardInput;\n  } else if (first_char == '|') {\n    return kNoInput;  // An output pipe like \"|blah\": not\n                      // valid for input.\n  } else if (last_char == '|') {\n    return kPipeInput;\n  } else if (isspace(first_char) || isspace(last_char)) {\n    return kNoInput;  // We don't allow leading or trailing space in a filename.\n  } else if ((first_char == 'a' || first_char == 's') &&\n             strchr(c, ':') != NULL &&\n            (ClassifyWspecifier(filename, NULL, NULL, NULL) != kNoWspecifier ||\n             ClassifyRspecifier(filename, NULL, NULL) != kNoRspecifier)) {\n    // e.g. ark:something or scp:something... this is almost certainly a\n    // scripting error, so call it an error rather than treating it as a file.\n    // In practice in modern kaldi scripts all (r,w)filenames begin with \"ark\"\n    // or \"scp\", even though technically speaking options like \"b\", \"t\", \"s\" or\n    // \"cs\" can appear before the ark or scp, like \"b,ark\".  For efficiency,\n    // and because this code is really just a nicety to catch errors earlier\n    // than they would otherwise be caught, we only call those extra functions\n    // for filenames beginning with 'a' or 's'.\n    return kNoInput;\n  } else if (isdigit(last_char)) {\n    const char *d = c + length - 1;\n    while (isdigit(*d) && d > c) d--;\n    if (*d == ':') return kOffsetFileInput;  // Filename is like\n                                             // some_file:12345\n    // otherwise it could still be a filename; continue to the next check.\n  }\n\n\n  // At this point it matched no other pattern so we assume a filename, but\n  // we check for '|' as it's a common source of errors to have pipe\n  // commands without the pipe in the right place.  Say that it can't be\n  // classified in this case.\n  if (strchr(c, '|') != NULL) {\n    KALDI_WARN << \"Trying to classify rxfilename with pipe symbol in the\"\n        \" wrong place (pipe without | at the end?): \" << filename;\n    return kNoInput;\n  }\n  return kFileInput;  // It matched no other pattern: assume it's a filename.\n}\n\nclass OutputImplBase {\n public:\n  // Open will open it as a file (no header), and return true\n  // on success.  It cannot be called on an already open stream.\n  virtual bool Open(const std::string &filename, bool binary) = 0;\n  virtual std::ostream &Stream() = 0;\n  virtual bool Close() = 0;\n  virtual ~OutputImplBase() { }\n};\n\n\nclass FileOutputImpl: public OutputImplBase {\n public:\n  virtual bool Open(const std::string &filename, bool binary) {\n    if (os_.is_open()) KALDI_ERR << \"FileOutputImpl::Open(), \"\n                                << \"open called on already open file.\";\n    filename_ = filename;\n    os_.open(MapOsPath(filename_).c_str(),\n             binary ? std::ios_base::out | std::ios_base::binary\n                    : std::ios_base::out);\n    return os_.is_open();\n  }\n\n  virtual std::ostream &Stream() {\n    if (!os_.is_open())\n      KALDI_ERR << \"FileOutputImpl::Stream(), file is not open.\";\n      // I believe this error can only arise from coding error.\n    return os_;\n  }\n\n  virtual bool Close() {\n    if (!os_.is_open())\n      KALDI_ERR << \"FileOutputImpl::Close(), file is not open.\";\n    // I believe this error can only arise from coding error.\n    os_.close();\n    return !(os_.fail());\n  }\n  virtual ~FileOutputImpl() {\n    if (os_.is_open()) {\n      os_.close();\n      if (os_.fail())\n        KALDI_ERR << \"Error closing output file \" << filename_;\n    }\n  }\n private:\n  std::string filename_;\n  std::ofstream os_;\n};\n\nclass StandardOutputImpl: public OutputImplBase {\n public:\n  StandardOutputImpl(): is_open_(false) { }\n\n  virtual bool Open(const std::string &filename, bool binary) {\n    if (is_open_) KALDI_ERR << \"StandardOutputImpl::Open(), \"\n                     \"open called on already open file.\";\n#ifdef _MSC_VER\n    _setmode(_fileno(stdout), binary ? _O_BINARY : _O_TEXT);\n#endif\n    is_open_ = std::cout.good();\n    return is_open_;\n  }\n\n  virtual std::ostream &Stream() {\n    if (!is_open_)\n      KALDI_ERR << \"StandardOutputImpl::Stream(), object not initialized.\";\n    // I believe this error can only arise from coding error.\n    return std::cout;\n  }\n\n  virtual bool Close() {\n    if (!is_open_)\n      KALDI_ERR << \"StandardOutputImpl::Close(), file is not open.\";\n    is_open_ = false;\n    std::cout << std::flush;\n    return !(std::cout.fail());\n  }\n  virtual ~StandardOutputImpl() {\n    if (is_open_) {\n      std::cout << std::flush;\n      if (std::cout.fail())\n        KALDI_ERR << \"Error writing to standard output\";\n    }\n  }\n private:\n  bool is_open_;\n};\n\nclass PipeOutputImpl: public OutputImplBase {\n public:\n  PipeOutputImpl(): f_(NULL), os_(NULL) { }\n\n  virtual bool Open(const std::string &wxfilename, bool binary) {\n    filename_ = wxfilename;\n    KALDI_ASSERT(f_ == NULL);  // Make sure closed.\n    KALDI_ASSERT(wxfilename.length() != 0 && wxfilename[0] == '|');  // should\n    // start with '|'\n    std::string cmd_name(wxfilename, 1);\n#if defined(_MSC_VER) || defined(__CYGWIN__)\n    f_ = popen(cmd_name.c_str(), (binary ? \"wb\" : \"w\"));\n#else\n    f_ = popen(cmd_name.c_str(), \"w\");\n#endif\n    if (!f_) {  // Failure.\n      KALDI_WARN << \"Failed opening pipe for writing, command is: \"\n                 << cmd_name << \", errno is \" << strerror(errno);\n      return false;\n    } else {\n#ifndef _MSC_VER\n      fb_ = new PipebufType(f_,  // Using this constructor won't make the\n                                 // destructor try to close the stream when\n                                 // we're done.\n                                  (binary ? std::ios_base::out|\n                                   std::ios_base::binary\n                                   :std::ios_base::out));\n      KALDI_ASSERT(fb_ != NULL);  // or would be alloc error.\n      os_ = new std::ostream(fb_);\n#else\n      os_ = new std::ofstream(f_);\n#endif\n      return os_->good();\n    }\n  }\n\n  virtual std::ostream &Stream() {\n    if (os_ == NULL) KALDI_ERR << \"PipeOutputImpl::Stream(),\"\n                                  \" object not initialized.\";\n    // I believe this error can only arise from coding error.\n    return *os_;\n  }\n\n  virtual bool Close() {\n    if (os_ == NULL) KALDI_ERR << \"PipeOutputImpl::Close(), file is not open.\";\n    bool ok = true;\n    os_->flush();\n    if (os_->fail()) ok = false;\n    delete os_;\n    os_ = NULL;\n    int status;\n#ifdef _MSC_VER\n    status = _pclose(f_);\n#else\n    status = pclose(f_);\n#endif\n    if (status)\n      KALDI_WARN << \"Pipe \" << filename_ << \" had nonzero return status \"\n                 << status;\n    f_ = NULL;\n#ifndef _MSC_VER\n    delete fb_;\n    fb_ = NULL;\n#endif\n    return ok;\n  }\n  virtual ~PipeOutputImpl() {\n    if (os_) {\n      if (!Close())\n        KALDI_ERR << \"Error writing to pipe \" << PrintableWxfilename(filename_);\n    }\n  }\n private:\n  std::string filename_;\n  FILE *f_;\n#ifndef _MSC_VER\n  PipebufType *fb_;\n#endif\n  std::ostream *os_;\n};\n\n\n\nclass InputImplBase {\n public:\n  // Open will open it as a file, and return true on success.\n  // May be called twice only for kOffsetFileInput (otherwise,\n  // if called twice, we just create a new Input object, to avoid\n  // having to deal with the extra hassle of reopening with the\n  // same object.\n  // Note that we will to call Open with true (binary) for\n  // for text-mode Kaldi files; the only actual text-mode input\n  // is for non-Kaldi files.\n  virtual bool Open(const std::string &filename, bool binary) = 0;\n  virtual std::istream &Stream() = 0;\n  virtual int32 Close() = 0;  // We only need to check failure in the case of\n                              // kPipeInput.\n  // on close for input streams.\n  virtual InputType MyType() = 0;  // Because if it's kOffsetFileInput, we may\n                                   // call Open twice\n  // (has efficiency benefits).\n\n  virtual ~InputImplBase() { }\n};\n\nclass FileInputImpl: public InputImplBase {\n public:\n  virtual bool Open(const std::string &filename, bool binary) {\n    if (is_.is_open()) KALDI_ERR << \"FileInputImpl::Open(), \"\n                                << \"open called on already open file.\";\n    is_.open(MapOsPath(filename).c_str(),\n             binary ? std::ios_base::in | std::ios_base::binary\n                    : std::ios_base::in);\n    return is_.is_open();\n  }\n\n  virtual std::istream &Stream() {\n    if (!is_.is_open())\n      KALDI_ERR << \"FileInputImpl::Stream(), file is not open.\";\n    // I believe this error can only arise from coding error.\n    return is_;\n  }\n\n  virtual int32 Close() {\n    if (!is_.is_open())\n      KALDI_ERR << \"FileInputImpl::Close(), file is not open.\";\n    // I believe this error can only arise from coding error.\n    is_.close();\n    // Don't check status.\n    return 0;\n  }\n\n  virtual InputType MyType() { return kFileInput; }\n\n  virtual ~FileInputImpl() {\n    // Stream will automatically be closed, and we don't care about\n    // whether it fails.\n  }\n private:\n  std::ifstream is_;\n};\n\n\nclass StandardInputImpl: public InputImplBase {\n public:\n  StandardInputImpl(): is_open_(false) { }\n\n  virtual bool Open(const std::string &filename, bool binary) {\n    if (is_open_) KALDI_ERR << \"StandardInputImpl::Open(), \"\n                     \"open called on already open file.\";\n    is_open_ = true;\n#ifdef _MSC_VER\n    _setmode(_fileno(stdin), binary ? _O_BINARY : _O_TEXT);\n#endif\n    return true;  // Don't check good() because would be false if\n    // eof, which may be valid input.\n  }\n\n  virtual std::istream &Stream() {\n    if (!is_open_)\n      KALDI_ERR << \"StandardInputImpl::Stream(), object not initialized.\";\n    // I believe this error can only arise from coding error.\n    return std::cin;\n  }\n\n  virtual InputType MyType() { return kStandardInput; }\n\n  virtual int32 Close() {\n    if (!is_open_) KALDI_ERR << \"StandardInputImpl::Close(), file is not open.\";\n    is_open_ = false;\n    return 0;\n  }\n  virtual ~StandardInputImpl() { }\n private:\n  bool is_open_;\n};\n\nclass PipeInputImpl: public InputImplBase {\n public:\n  PipeInputImpl(): f_(NULL), is_(NULL) { }\n\n  virtual bool Open(const std::string &rxfilename, bool binary) {\n    filename_ = rxfilename;\n    KALDI_ASSERT(f_ == NULL);  // Make sure closed.\n    KALDI_ASSERT(rxfilename.length() != 0 &&\n           rxfilename[rxfilename.length()-1] == '|');  // should end with '|'\n    std::string cmd_name(rxfilename, 0, rxfilename.length()-1);\n#if defined(_MSC_VER) || defined(__CYGWIN__)\n    f_ = popen(cmd_name.c_str(), (binary ? \"rb\" : \"r\"));\n#else\n    f_ = popen(cmd_name.c_str(), \"r\");\n#endif\n\n    if (!f_) {  // Failure.\n      KALDI_WARN << \"Failed opening pipe for reading, command is: \"\n                 << cmd_name << \", errno is \" << strerror(errno);\n      return false;\n    } else {\n#ifndef _MSC_VER\n      fb_ = new PipebufType(f_,  // Using this constructor won't lead the\n                                 // destructor to close the stream.\n                                 (binary ? std::ios_base::in|\n                                  std::ios_base::binary\n                                  :std::ios_base::in));\n      KALDI_ASSERT(fb_ != NULL);  // or would be alloc error.\n      is_ = new std::istream(fb_);\n#else\n      is_ = new std::ifstream(f_);\n#endif\n      if (is_->fail() || is_->bad()) return false;\n      if (is_->eof()) {\n        KALDI_WARN << \"Pipe opened with command \"\n                   << PrintableRxfilename(rxfilename)\n                   << \" is empty.\";\n        // don't return false: empty may be valid.\n      }\n      return true;\n    }\n  }\n\n  virtual std::istream &Stream() {\n    if (is_ == NULL)\n      KALDI_ERR << \"PipeInputImpl::Stream(), object not initialized.\";\n    // I believe this error can only arise from coding error.\n    return *is_;\n  }\n\n  virtual int32 Close() {\n    if (is_ == NULL)\n      KALDI_ERR << \"PipeInputImpl::Close(), file is not open.\";\n    delete is_;\n    is_ = NULL;\n    int32 status;\n#ifdef _MSC_VER\n    status = _pclose(f_);\n#else\n    status = pclose(f_);\n#endif\n    if (status)\n      KALDI_WARN << \"Pipe \" << filename_ << \" had nonzero return status \"\n                 << status;\n    f_ = NULL;\n#ifndef _MSC_VER\n    delete fb_;\n    fb_ = NULL;\n#endif\n    return status;\n  }\n  virtual ~PipeInputImpl() {\n    if (is_)\n      Close();\n  }\n  virtual InputType MyType() { return kPipeInput; }\n private:\n  std::string filename_;\n  FILE *f_;\n#ifndef _MSC_VER\n  PipebufType *fb_;\n#endif\n  std::istream *is_;\n};\n\n/*\n#else\n\n// Just have an empty implementation of the pipe input that crashes if\n// called.\nclass PipeInputImpl: public InputImplBase {\n public:\n  PipeInputImpl() { KALDI_ASSERT(0 && \"Pipe input not yet supported on this\n  platform.\"); }\n  virtual bool Open(const std::string, bool) { return 0; }\n  virtual std::istream &Stream() const { return NULL; }\n  virtual void Close() {}\n  virtual InputType MyType() { return kPipeInput; }\n};\n\n#endif\n*/\n\nclass OffsetFileInputImpl: public InputImplBase {\n  // This class is a bit more complicated than the\n\n public:\n  // splits a filename like /my/file:123 into /my/file and the\n  // number 123.  Crashes if not this format.\n  static void SplitFilename(const std::string &rxfilename,\n                            std::string *filename,\n                            size_t *offset) {\n    size_t pos = rxfilename.find_last_of(':');\n    KALDI_ASSERT(pos != std::string::npos);  // would indicate error in calling\n    // code, as the filename is supposed to be of the correct form at this\n    // point.\n    *filename = std::string(rxfilename, 0, pos);\n    std::string number(rxfilename, pos+1);\n    bool ans = ConvertStringToInteger(number, offset);\n    if (!ans)\n      KALDI_ERR << \"Cannot get offset from filename \" << rxfilename\n                << \" (possibly you compiled in 32-bit and have a >32-bit\"\n                << \" byte offset into a file; you'll have to compile 64-bit.\";\n  }\n\n  bool Seek(size_t offset) {\n    size_t cur_pos = is_.tellg();\n    if (cur_pos == offset) return true;\n    else if (cur_pos<offset && cur_pos+100 > offset) {\n      // We're close enough that it may be faster to just\n      // read that data, rather than seek.\n      for (size_t i = cur_pos; i < offset; i++)\n        is_.get();\n      return (is_.tellg() == std::streampos(offset));\n    }\n    // Try to actually seek.\n    is_.seekg(offset, std::ios_base::beg);\n    if (is_.fail()) {  // failbit or badbit is set [error happened]\n      is_.close();\n      return false;  // failure.\n    } else {\n      is_.clear();  // Clear any failure bits (e.g. eof).\n      return true;  // success.\n    }\n  }\n\n  // This Open routine is unusual in that it is designed to work even\n  // if it was already open.  This for efficiency when seeking multiple\n  // times.\n  virtual bool Open(const std::string &rxfilename, bool binary) {\n    if (is_.is_open()) {\n      // We are opening when we have an already-open file.\n      // We may have to seek within this file, or else close it and\n      // open a different one.\n      std::string tmp_filename;\n      size_t offset;\n      SplitFilename(rxfilename, &tmp_filename, &offset);\n      if (tmp_filename == filename_ && binary == binary_) {  // Just seek\n        is_.clear();  // clear fail bit, etc.\n        return Seek(offset);\n      } else {\n        is_.close();  // don't bother checking error status of is_.\n        filename_ = tmp_filename;\n        is_.open(MapOsPath(filename_).c_str(),\n                 binary ? std::ios_base::in | std::ios_base::binary\n                        : std::ios_base::in);\n        if (!is_.is_open()) return false;\n        else\n          return Seek(offset);\n      }\n    } else {\n      size_t offset;\n      SplitFilename(rxfilename, &filename_, &offset);\n      binary_ = binary;\n      is_.open(MapOsPath(filename_).c_str(),\n                binary ? std::ios_base::in | std::ios_base::binary\n                      : std::ios_base::in);\n      if (!is_.is_open()) return false;\n      else\n        return Seek(offset);\n    }\n  }\n\n  virtual std::istream &Stream() {\n    if (!is_.is_open())\n      KALDI_ERR << \"FileInputImpl::Stream(), file is not open.\";\n    // I believe this error can only arise from coding error.\n    return is_;\n  }\n\n  virtual int32 Close() {\n    if (!is_.is_open())\n      KALDI_ERR << \"FileInputImpl::Close(), file is not open.\";\n    // I believe this error can only arise from coding error.\n    is_.close();\n    // Don't check status.\n    return 0;\n  }\n\n  virtual InputType MyType() { return kOffsetFileInput; }\n\n  virtual ~OffsetFileInputImpl() {\n    // Stream will automatically be closed, and we don't care about\n    // whether it fails.\n  }\n private:\n  std::string filename_;  // the actual filename\n  bool binary_;  // true if was opened in binary mode.\n  std::ifstream is_;\n};\n\n\nOutput::Output(const std::string &wxfilename, bool binary,\n               bool write_header):impl_(NULL) {\n  if (!Open(wxfilename, binary, write_header)) {\n    if (impl_) {\n      delete impl_;\n      impl_ = NULL;\n    }\n    KALDI_ERR << \"Error opening output stream \" <<\n        PrintableWxfilename(wxfilename);\n  }\n}\n\nbool Output::Close() {\n  if (!impl_) {\n    return false;  // error to call Close if not open.\n  } else {\n    bool ans = impl_->Close();\n    delete impl_;\n    impl_ = NULL;\n    return ans;\n  }\n}\n\nOutput::~Output() {\n  if (impl_) {\n    bool ok = impl_->Close();\n    delete impl_;\n    impl_ = NULL;\n    if (!ok)\n      KALDI_ERR << \"Error closing output file \"\n                << PrintableWxfilename(filename_)\n                << (ClassifyWxfilename(filename_) == kFileOutput ?\n                    \" (disk full?)\" : \"\");\n  }\n}\n\nstd::ostream &Output::Stream() {  // will throw if not open; else returns\n  // stream.\n  if (!impl_) KALDI_ERR << \"Output::Stream() called but not open.\";\n  return impl_->Stream();\n}\n\nbool Output::Open(const std::string &wxfn, bool binary, bool header) {\n  if (IsOpen()) {\n    if (!Close()) {  // Throw here rather than return status, as it's an error\n      // about something else: if the user wanted to avoid the exception he/she\n      // could have called Close().\n      KALDI_ERR << \"Output::Open(), failed to close output stream: \"\n                << PrintableWxfilename(filename_);\n    }\n  }\n\n  filename_ = wxfn;\n\n  OutputType type = ClassifyWxfilename(wxfn);\n  KALDI_ASSERT(impl_ == NULL);\n\n  if (type ==  kFileOutput) {\n    impl_ = new FileOutputImpl();\n  } else if (type == kStandardOutput) {\n    impl_ = new StandardOutputImpl();\n  } else if (type == kPipeOutput) {\n    impl_ = new PipeOutputImpl();\n  } else {  // type == kNoOutput\n    KALDI_WARN << \"Invalid output filename format \"<<\n        PrintableWxfilename(wxfn);\n    return false;\n  }\n  if (!impl_->Open(wxfn, binary)) {\n    delete impl_;\n    impl_ = NULL;\n    return false;  // failed to open.\n  } else {  // successfully opened it.\n    if (header) {\n      InitKaldiOutputStream(impl_->Stream(), binary);\n      bool ok = impl_->Stream().good();  // still OK?\n      if (!ok) {\n        delete impl_;\n        impl_ = NULL;\n        return false;\n      }\n      return true;\n    } else {\n      return true;\n    }\n  }\n}\n\n\nInput::Input(const std::string &rxfilename, bool *binary): impl_(NULL) {\n  if (!Open(rxfilename, binary)) {\n    KALDI_ERR << \"Error opening input stream \"\n              << PrintableRxfilename(rxfilename);\n  }\n}\n\nint32 Input::Close() {\n  if (impl_) {\n    int32 ans = impl_->Close();\n    delete impl_;\n    impl_ = NULL;\n    return ans;\n  } else {\n    return 0;\n  }\n}\n\nbool Input::OpenInternal(const std::string &rxfilename,\n                         bool file_binary,\n                         bool *contents_binary) {\n  InputType type = ClassifyRxfilename(rxfilename);\n  if (IsOpen()) {\n    // May have to close the stream first.\n    if (type == kOffsetFileInput && impl_->MyType() == kOffsetFileInput) {\n      // We want to use the same object to Open... this is in case\n      // the files are the same, so we can just seek.\n      if (!impl_->Open(rxfilename, file_binary)) {  // true is binary mode--\n        // always open in binary.\n        delete impl_;\n        impl_ = NULL;\n        return false;\n      }\n      // read the binary header, if requested.\n      if (contents_binary != NULL)\n        return InitKaldiInputStream(impl_->Stream(), contents_binary);\n      else\n        return true;\n    } else {\n      Close();\n      // and fall through to code below which actually opens the file.\n    }\n  }\n  if (type ==  kFileInput) {\n    impl_ = new FileInputImpl();\n  } else if (type == kStandardInput) {\n    impl_ = new StandardInputImpl();\n  } else if (type == kPipeInput) {\n    impl_ = new PipeInputImpl();\n  } else if (type == kOffsetFileInput) {\n    impl_ = new OffsetFileInputImpl();\n  } else {  // type == kNoInput\n    KALDI_WARN << \"Invalid input filename format \"<<\n        PrintableRxfilename(rxfilename);\n    return false;\n  }\n  if (!impl_->Open(rxfilename, file_binary)) {  // true is binary mode--\n    // always read in binary.\n    delete impl_;\n    impl_ = NULL;\n    return false;\n  }\n  if (contents_binary != NULL)\n    return InitKaldiInputStream(impl_->Stream(), contents_binary);\n  else\n    return true;\n}\n\n\nInput::~Input() { if (impl_) Close(); }\n\n\nstd::istream &Input::Stream() {\n  if (!IsOpen()) KALDI_ERR << \"Input::Stream(), not open.\";\n  return impl_->Stream();\n}\n\n\ntemplate <> void ReadKaldiObject(const std::string &filename,\n                                 Matrix<float> *m) {\n  if (!filename.empty() && filename[filename.size() - 1] == ']') {\n    // This filename seems to have a 'range'... like foo.ark:4312423[20:30].\n    // (the bit in square brackets is the range).\n    std::string rxfilename, range;\n    if (!ExtractRangeSpecifier(filename, &rxfilename, &range)) {\n      KALDI_ERR << \"Could not make sense of possible range specifier in filename \"\n                << \"while reading matrix: \" << filename;\n    }\n    Matrix<float> temp;\n    bool binary_in;\n    Input ki(rxfilename, &binary_in);\n    temp.Read(ki.Stream(), binary_in);\n    if (!ExtractObjectRange(temp, range, m)) {\n      KALDI_ERR << \"Error extracting range of object: \" << filename;\n    }\n  } else {\n    // The normal case, there is no range.\n    bool binary_in;\n    Input ki(filename, &binary_in);\n    m->Read(ki.Stream(), binary_in);\n  }\n}\n\ntemplate <> void ReadKaldiObject(const std::string &filename,\n                                 Matrix<double> *m) {\n  if (!filename.empty() && filename[filename.size() - 1] == ']') {\n    // This filename seems to have a 'range'... like foo.ark:4312423[20:30].\n    // (the bit in square brackets is the range).\n    std::string rxfilename, range;\n    if (!ExtractRangeSpecifier(filename, &rxfilename, &range)) {\n      KALDI_ERR << \"Could not make sense of possible range specifier in filename \"\n                << \"while reading matrix: \" << filename;\n    }\n    Matrix<double> temp;\n    bool binary_in;\n    Input ki(rxfilename, &binary_in);\n    temp.Read(ki.Stream(), binary_in);\n    if (!ExtractObjectRange(temp, range, m)) {\n      KALDI_ERR << \"Error extracting range of object: \" << filename;\n    }\n  } else {\n    // The normal case, there is no range.\n    bool binary_in;\n    Input ki(filename, &binary_in);\n    m->Read(ki.Stream(), binary_in);\n  }\n}\n\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-io.h",
    "content": "// util/kaldi-io.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Jan Silovsky\n//                2016  Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_UTIL_KALDI_IO_H_\n#define KALDI_UTIL_KALDI_IO_H_\n\n#ifdef _MSC_VER\n# include <fcntl.h>\n# include <io.h>\n#endif\n#include <cctype>  // For isspace.\n#include <limits>\n#include <string>\n#include \"base/kaldi-common.h\"\n#include \"matrix/kaldi-matrix.h\"\n\n\nnamespace kaldi {\n\nclass OutputImplBase;  // Forward decl; defined in a .cc file\nclass InputImplBase;  // Forward decl; defined in a .cc file\n\n/// \\addtogroup io_group\n/// @{\n\n// The Output and Input classes handle stream-opening for \"extended\" filenames\n// that include actual files, standard-input/standard-output, pipes, and\n// offsets into actual files.  They also handle reading and writing the\n// binary-mode headers for Kaldi files, where applicable.  The classes have\n// versions of the Open routines that throw and do not throw, depending whether\n// the calling code wants to catch the errors or not; there are also versions\n// that write (or do not write) the Kaldi binary-mode header that says if it's\n// binary mode.  Generally files that contain Kaldi objects will have the header\n// on, so we know upon reading them whether they have the header.  So you would\n// use the OpenWithHeader routines for these (or the constructor); but other\n// types of objects (e.g. FSTs) would have files without a header so you would\n// use OpenNoHeader.\n\n// We now document the types of extended filenames that we use.\n//\n// A \"wxfilename\"  is an extended filename for writing. It can take three forms:\n// (1) Filename: e.g.    \"/some/filename\", \"./a/b/c\", \"c:\\Users\\dpovey\\My\n//                        Documents\\\\boo\"\n//          (whatever the actual file-system interprets)\n// (2) Standard output:  \"\" or \"-\"\n// (3) A pipe: e.g. \"| gzip -c > /tmp/abc.gz\"\n//\n//\n// A \"rxfilename\" is an extended filename for reading.  It can take four forms:\n// (1) An actual filename, whatever the file-system can read, e.g. \"/my/file\".\n// (2) Standard input: \"\" or \"-\"\n// (3) A pipe: e.g.  \"gunzip -c /tmp/abc.gz |\"\n// (4) An offset into a file, e.g.: \"/mnt/blah/data/1.ark:24871\"\n//   [these are created by the Table and TableWriter classes; I may also write\n//    a program that creates them for arbitrary files]\n//\n\n\n// Typical usage:\n// ...\n// bool binary;\n// MyObject.Write(Output(some_filename, binary).Stream(), binary);\n//\n// ... more extensive example:\n// {\n//    Output ko(some_filename, binary);\n//    MyObject1.Write(ko.Stream(), binary);\n//    MyObject2.Write(ko.Stream(), binary);\n// }\n\n\n\nenum OutputType {\n  kNoOutput,\n  kFileOutput,\n  kStandardOutput,\n  kPipeOutput\n};\n\n/// ClassifyWxfilename interprets filenames as follows:\n///  - kNoOutput: invalid filenames (leading or trailing space, things that look\n///     like wspecifiers and rspecifiers or like pipes to read from with leading\n///     |.\n///  - kFileOutput: Normal filenames\n///  - kStandardOutput: The empty string or \"-\", interpreted as standard output\n///  - kPipeOutput: pipes, e.g. \"| gzip -c > /tmp/abc.gz\"\nOutputType ClassifyWxfilename(const std::string &wxfilename);\n\nenum InputType {\n  kNoInput,\n  kFileInput,\n  kStandardInput,\n  kOffsetFileInput,\n  kPipeInput\n};\n\n/// ClassifyRxfilenames interprets filenames for reading as follows:\n///  - kNoInput: invalid filenames (leading or trailing space, things that\n///       look like wspecifiers and rspecifiers or pipes to write to\n///       with trailing |.\n///  - kFileInput: normal filenames\n///  - kStandardInput: the empty string or \"-\"\n///  - kPipeInput: e.g. \"gunzip -c /tmp/abc.gz |\"\n///  - kOffsetFileInput: offsets into files, e.g.  /some/filename:12970\nInputType ClassifyRxfilename(const std::string &rxfilename);\n\n\nclass Output {\n public:\n  // The normal constructor, provided for convenience.\n  // Equivalent to calling with default constructor then Open()\n  // with these arguments.\n  Output(const std::string &filename, bool binary, bool write_header = true);\n\n  Output(): impl_(NULL) {}\n\n  /// This opens the stream, with the given mode (binary or text).  It returns\n  /// true on success and false on failure.  However, it will throw if something\n  /// was already open and could not be closed (to avoid this, call Close()\n  /// first.  if write_header == true and binary == true, it writes the Kaldi\n  /// binary-mode header ('\\0' then 'B').  You may call Open even if it is\n  /// already open; it will close the existing stream and reopen (however if\n  /// closing the old stream failed it will throw).\n  bool Open(const std::string &wxfilename, bool binary, bool write_header);\n\n  inline bool IsOpen();  // return true if we have an open stream.  Does not\n  // imply stream is good for writing.\n\n  std::ostream &Stream();  // will throw if not open; else returns stream.\n\n  // Close closes the stream. Calling Close is never necessary unless you\n  // want to avoid exceptions being thrown.  There are times when calling\n  // Close will hurt efficiency (basically, when using offsets into files,\n  // and using the same Input object),\n  // but most of the time the user won't be doing this directly, it will\n  // be done in kaldi-table.{h, cc}, so you don't have to worry about it.\n  bool Close();\n\n  // This will throw if stream could not be closed (to check error status,\n  // call Close()).\n  ~Output();\n\n private:\n  OutputImplBase *impl_;  // non-NULL if open.\n  std::string filename_;\n  KALDI_DISALLOW_COPY_AND_ASSIGN(Output);\n};\n\n\n// bool binary_in;\n// Input ki(some_filename, &binary_in);\n// MyObject.Read(ki.Stream(), binary_in);\n//\n// ... more extensive example:\n//\n// {\n//    bool binary_in;\n//    Input ki(some_filename, &binary_in);\n//    MyObject1.Read(ki.Stream(), &binary_in);\n//    MyObject2.Write(ki.Stream(), &binary_in);\n// }\n// Note that to catch errors you need to use try.. catch.\n// Input communicates errors by throwing exceptions.\n\n\n// Input interprets four kinds of filenames:\n//  (1) Normal filenames\n//  (2) The empty string or \"-\", interpreted as standard output\n//  (3) A pipe: e.g.  \"gunzip -c /tmp/abc.gz |\"\n//  (4) Offsets into [real] files, e.g. \"/my/filename:12049\"\n// The last one has no correspondence in Output.\n\n\nclass Input {\n public:\n  /// The normal constructor.  Opens the stream in binary mode.\n  /// Equivalent to calling the default constructor followed by Open(); then, if\n  /// binary != NULL, it calls ReadHeader(), putting the output in \"binary\"; it\n  /// throws on error.\n  Input(const std::string &rxfilename, bool *contents_binary = NULL);\n\n  Input(): impl_(NULL) {}\n\n  // Open opens the stream for reading (the mode, where relevant, is binary; use\n  // OpenTextMode for text-mode, we made this a separate function rather than a\n  // boolean argument, to avoid confusion with Kaldi's text/binary distinction,\n  // since reading in the file system's text mode is unusual.)  If\n  // contents_binary != NULL, it reads the binary-mode header and puts it in the\n  // \"binary\" variable.  Returns true on success.  If it returns false it will\n  // not be open.  You may call Open even if it is already open; it will close\n  // the existing stream and reopen (however if closing the old stream failed it\n  // will throw).\n  inline bool Open(const std::string &rxfilename, bool *contents_binary = NULL);\n\n  // As Open but (if the file system has text/binary modes) opens in text mode;\n  // you shouldn't ever have to use this as in Kaldi we read even text files in\n  // binary mode (and ignore the \\r).\n  inline bool OpenTextMode(const std::string &rxfilename);\n\n  // Return true if currently open for reading and Stream() will\n  // succeed.  Does not guarantee that the stream is good.\n  inline bool IsOpen();\n\n  // It is never necessary or helpful to call Close, except if\n  // you are concerned about to many filehandles being open.\n  // Close does not throw. It returns the exit code as int32\n  // in the case of a pipe [kPipeInput], and always zero otherwise.\n  int32 Close();\n\n  // Returns the underlying stream. Throws if !IsOpen()\n  std::istream &Stream();\n\n  // Destructor does not throw: input streams may legitimately fail so we\n  // don't worry about the status when we close them.\n  ~Input();\n private:\n  bool OpenInternal(const std::string &rxfilename, bool file_binary,\n                    bool *contents_binary);\n  InputImplBase *impl_;\n  KALDI_DISALLOW_COPY_AND_ASSIGN(Input);\n};\n\ntemplate <class C> void ReadKaldiObject(const std::string &filename,\n                                        C *c) {\n  bool binary_in;\n  Input ki(filename, &binary_in);\n  c->Read(ki.Stream(), binary_in);\n}\n\n// Specialize the template for reading matrices, because we want to be able to\n// support reading 'ranges' (row and column ranges), like foo.mat[10:20].\ntemplate <> void ReadKaldiObject(const std::string &filename,\n                                 Matrix<float> *m);\n\n\ntemplate <> void ReadKaldiObject(const std::string &filename,\n                                 Matrix<double> *m);\n\n\n\ntemplate <class C> inline void WriteKaldiObject(const C &c,\n                                                const std::string &filename,\n                                                bool binary) {\n  Output ko(filename, binary);\n  c.Write(ko.Stream(), binary);\n}\n\n/// PrintableRxfilename turns the rxfilename into a more human-readable\n/// form for error reporting, i.e. it does quoting and escaping and\n/// replaces \"\" or \"-\" with \"standard input\".\nstd::string PrintableRxfilename(const std::string &rxfilename);\n\n/// PrintableWxfilename turns the wxfilename into a more human-readable\n/// form for error reporting, i.e. it does quoting and escaping and\n/// replaces \"\" or \"-\" with \"standard output\".\nstd::string PrintableWxfilename(const std::string &wxfilename);\n\n/// @}\n\n}  // end namespace kaldi.\n\n#include \"util/kaldi-io-inl.h\"\n\n#endif  // KALDI_UTIL_KALDI_IO_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-pipebuf.h",
    "content": "// util/kaldi-pipebuf.h\n\n// Copyright 2009-2011  Ondrej Glembek\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n/** @file kaldi-pipebuf.h\n *  This is an Kaldi C++ Library header.\n */\n\n#ifndef KALDI_UTIL_KALDI_PIPEBUF_H_\n#define KALDI_UTIL_KALDI_PIPEBUF_H_\n\n#include<string>\n#if !defined(_LIBCPP_VERSION)  // libc++\n#include <fstream>\n#else\n#include \"util/basic-filebuf.h\"\n#endif\n\nnamespace kaldi {\n// This class provides a way to initialize a filebuf with a FILE* pointer\n// directly; it will not close the file pointer when it is deleted.\n// The C++ standard does not allow implementations of C++ to provide\n// this constructor within basic_filebuf, which makes it hard to deal\n// with pipes using completely native C++.  This is a workaround\n\n#ifdef _MSC_VER\n#elif defined(_LIBCPP_VERSION)  // libc++\ntemplate<class CharType, class Traits = std::char_traits<CharType> >\nclass basic_pipebuf : public basic_filebuf<CharType, Traits> {\n public:\n  typedef basic_pipebuf<CharType, Traits>   ThisType;\n\n public:\n  basic_pipebuf(FILE *fptr, std::ios_base::openmode mode)\n      : basic_filebuf<CharType, Traits>() {\n    this->open(fptr, mode);\n    if (!this->is_open()) {\n      KALDI_WARN << \"Error initializing pipebuf\";  // probably indicates\n      // code error, if the fptr was good.\n      return;\n    }\n  }\n};  // class basic_pipebuf\n#else\ntemplate<class CharType, class Traits = std::char_traits<CharType> >\nclass basic_pipebuf : public std::basic_filebuf<CharType, Traits> {\n public:\n  typedef basic_pipebuf<CharType, Traits>   ThisType;\n\n public:\n  basic_pipebuf(FILE *fptr, std::ios_base::openmode mode)\n      : std::basic_filebuf<CharType, Traits>() {\n    this->_M_file.sys_open(fptr, mode);\n    if (!this->is_open()) {\n      KALDI_WARN << \"Error initializing pipebuf\";  // probably indicates\n      // code error, if the fptr was good.\n      return;\n    }\n    this->_M_mode = mode;\n    this->_M_buf_size = BUFSIZ;\n    this->_M_allocate_internal_buffer();\n    this->_M_reading = false;\n    this->_M_writing = false;\n    this->_M_set_buffer(-1);\n  }\n};  // class basic_pipebuf\n#endif  // _MSC_VER\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_KALDI_PIPEBUF_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-semaphore.cc",
    "content": "// util/kaldi-semaphore.cc\n\n// Copyright 2012  Karel Vesely (Brno University of Technology)\n//           2017  Dogan Can (University of Southern California)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n\n#include \"base/kaldi-error.h\"\n#include \"util/kaldi-semaphore.h\"\n\nnamespace kaldi {\n\nSemaphore::Semaphore(int32 count) {\n  KALDI_ASSERT(count >= 0);\n  count_ = count;\n}\n\nSemaphore::~Semaphore() {}\n\nbool Semaphore::TryWait() {\n  std::unique_lock<std::mutex> lock(mutex_);\n  if(count_) {\n      count_--;\n      return true;\n  }\n  return false;\n}\n\nvoid Semaphore::Wait() {\n  std::unique_lock<std::mutex> lock(mutex_);\n  while(!count_)\n    condition_variable_.wait(lock);\n  count_--;\n}\n\nvoid Semaphore::Signal() {\n  std::unique_lock<std::mutex> lock(mutex_);\n  count_++;\n  condition_variable_.notify_one();\n}\n\n} // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-semaphore.h",
    "content": "// util/kaldi-semaphore.h\n\n// Copyright 2012  Karel Vesely (Brno University of Technology)\n//           2017  Dogan Can (University of Southern California)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_THREAD_KALDI_SEMAPHORE_H_\n#define KALDI_THREAD_KALDI_SEMAPHORE_H_ 1\n\n#include <mutex>\n#include <condition_variable>\n\nnamespace kaldi {\n\nclass Semaphore {\n public:\n  Semaphore(int32 count = 0);\n\n  ~Semaphore();\n\n  bool TryWait();  ///< Returns true if Wait() goes through\n  void Wait();     ///< decrease the counter\n  void Signal();   ///< increase the counter\n\n private:\n  int32 count_;    ///< the semaphore counter, 0 means block on Wait()\n\n  std::mutex mutex_;\n  std::condition_variable condition_variable_;\n  KALDI_DISALLOW_COPY_AND_ASSIGN(Semaphore);\n};\n\n} //namespace\n\n#endif // KALDI_THREAD_KALDI_SEMAPHORE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-table-inl.h",
    "content": "// util/kaldi-table-inl.h\n\n// Copyright 2009-2011    Microsoft Corporation\n//                2013    Johns Hopkins University (author: Daniel Povey)\n//                2016    Xiaohui Zhang\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_KALDI_TABLE_INL_H_\n#define KALDI_UTIL_KALDI_TABLE_INL_H_\n\n#include <algorithm>\n#include <string>\n#include <thread>\n#include <utility>\n#include <vector>\n#include <errno.h>\n#include \"util/kaldi-io.h\"\n#include \"util/kaldi-holder.h\"\n#include \"util/text-utils.h\"\n#include \"util/stl-utils.h\"  // for StringHasher.\n#include \"util/kaldi-semaphore.h\"\n\n\nnamespace kaldi {\n\n/// \\addtogroup table_impl_types\n/// @{\n\ntemplate<class Holder> class SequentialTableReaderImplBase {\n public:\n  typedef typename Holder::T T;\n  // note that Open takes rxfilename not rspecifier.  Open will only be\n  // called on a just-allocated object.\n  virtual bool Open(const std::string &rxfilename) = 0;\n  // Done() should be called on a successfully opened, not-closed object.\n  // only throws if called at the wrong time (i.e. code error).\n  virtual bool Done() const = 0;\n  // Returns true if the reader is open [i.e. Open() succeeded and\n  // the user has not called Close()]\n  virtual bool IsOpen() const = 0;\n  // Returns the current key; it is valid to call this if Done() returned false.\n  // Only throws on code error (i.e. called at the wrong time).\n  virtual std::string Key() = 0;\n  // Returns the value associated with the current key.  Valid to call it if\n  // Done() returned false.  It throws if the value could not be read.  [However\n  // if you use the ,p modifier it will never throw, unless you call it at the\n  // wrong time, i.e. unless there is a code error.]\n  virtual T &Value() = 0;\n  virtual void FreeCurrent() = 0;\n  // move to the next object.  This won't throw unless called wrongly (e.g. on\n  // non-open archive.]\n  virtual void Next() = 0;\n  // Close the table.  Returns its status as bool so it won't throw, unless\n  // called wrongly [i.e. on non-open archive.]\n  virtual bool Close() = 0;\n  // SwapHolder() is not part of the public interface of SequentialTableReader.\n  // It should be called when it would be valid to call Value() or FreeCurrent()\n  // (i.e. when a value is stored), and after this it's not valid to get the\n  // value any more until you call Next().  It swaps the contents of\n  // this->holder_ with those of 'other_holder'.  It's needed as part of how\n  // we implement SequentialTableReaderBackgroundImpl.\n  virtual void SwapHolder(Holder *other_holder) = 0;\n  SequentialTableReaderImplBase() { }\n  virtual ~SequentialTableReaderImplBase() { }  // throws.\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(SequentialTableReaderImplBase);\n};\n\n// This is the implementation for SequentialTableReader\n// when it's actually a script file.\ntemplate<class Holder>  class SequentialTableReaderScriptImpl:\n      public SequentialTableReaderImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  SequentialTableReaderScriptImpl(): state_(kUninitialized) { }\n\n  // You may call Open from states kUninitialized and kError.\n  // It may leave the object in any of the states.\n  virtual bool Open(const std::string &rspecifier) {\n    if (state_ != kUninitialized && state_ != kError)\n      if (!Close())  // call Close() yourself to suppress this exception.\n        KALDI_ERR << \"Error closing previous input: \"\n                  << \"rspecifier was \" << rspecifier_;\n    bool binary;\n    rspecifier_ = rspecifier;\n    RspecifierType rs = ClassifyRspecifier(rspecifier, &script_rxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(rs == kScriptRspecifier);\n    if (!script_input_.Open(script_rxfilename_, &binary)) {  // Failure on Open\n      KALDI_WARN << \"Failed to open script file \"\n                 << PrintableRxfilename(script_rxfilename_);\n      state_ = kUninitialized;\n      return false;\n    } else {  // Open succeeded.\n      if (binary) {\n        KALDI_WARN << \"Script file should not be binary file.\";\n        SetErrorState();\n        return false;\n      } else {\n        state_ = kFileStart;\n        Next();\n        if (state_ == kError)\n          return false;\n        // any other status, including kEof, is OK from the point of view of\n        // the 'open' function (empty scp file is not inherently an error).\n        return true;\n      }\n    }\n  }\n\n  virtual bool IsOpen() const {\n    switch (state_) {\n      case kEof: case kHaveScpLine: case kHaveObject: case kHaveRange:\n        return true;\n      case kUninitialized: case kError:\n        return false;\n      default: KALDI_ERR << \"IsOpen() called on invalid object.\";\n        // note: kFileStart is not a valid state for the user to call a member\n        // function (we never return from a public function in this state).\n        return false;\n    }\n  }\n\n  virtual bool Done() const {\n    switch (state_) {\n      case kHaveScpLine: case kHaveObject: case kHaveRange: return false;\n      case kEof: case kError: return true;  // Error condition, like Eof, counts\n        // as Done(); the destructor/Close() will inform the user of the error.\n      default: KALDI_ERR << \"Done() called on TableReader object at the wrong\"\n          \" time.\";\n        return false;\n    }\n  }\n\n  virtual std::string Key() {\n    // Valid to call this whenever Done() returns false.\n    switch (state_) {\n      case kHaveScpLine: case kHaveObject: case kHaveRange: break;\n      default:\n        // coding error.\n        KALDI_ERR << \"Key() called on TableReader object at the wrong time.\";\n    }\n    return key_;\n  }\n\n  T &Value() {\n    if (!EnsureObjectLoaded())\n      KALDI_ERR << \"Failed to load object from \"\n                << PrintableRxfilename(data_rxfilename_)\n                << \" (to suppress this error, add the permissive \"\n                << \"(p, ) option to the rspecifier.\";\n    // Because EnsureObjectLoaded() returned with success, we know\n    // that if range_ is nonempty (i.e. a range was requested), the\n    // state will be kHaveRange.\n    if (state_ == kHaveRange) {\n      return range_holder_.Value();\n    } else {\n      KALDI_ASSERT(state_ == kHaveObject);\n      return holder_.Value();\n    }\n  }\n\n  void FreeCurrent() {\n    if (state_ == kHaveObject) {\n      holder_.Clear();\n      state_ = kHaveScpLine;\n    } else if (state_ == kHaveRange) {\n      range_holder_.Clear();\n      state_ = kHaveObject;\n    } else {\n      KALDI_WARN << \"FreeCurrent called at the wrong time.\";\n    }\n  }\n\n  void SwapHolder(Holder *other_holder) {\n    // call Value() to ensure we have a value, and ignore its return value while\n    // suppressing compiler warnings by casting to void.  It will cause the\n    // program to die with KALDI_ERR if we couldn't get a value.\n    (void) Value();\n    // At this point we know that we successfully loaded an object,\n    // and if there was a range specified, it's in range_holder_.\n    if (state_ == kHaveObject) {\n      holder_.Swap(other_holder);\n      state_ = kHaveScpLine;\n    } else if (state_ == kHaveRange) {\n      range_holder_.Swap(other_holder);\n      state_ = kHaveObject;\n      // This indicates that we still have the base object (but no range).\n    } else {\n      KALDI_ERR << \"Code error\";\n    }\n    // Note: after this call there may be some junk left in range_holder_ or\n    // holder_, but it won't matter.  We avoid calling Clear() on them, as this\n    // function needs to be lightweight for the 'bg' feature to work well.\n  }\n\n  // Next goes to the next object.\n  // It can leave the object in most of the statuses, but\n  // the only circumstances under which it will return are:\n  //  either:\n  //  - if Done() returned true, i.e. kError or kEof.\n  //  or:\n  //  - in non-permissive mode, status kHaveScpLine or kHaveObjecct\n  //  - in permissive mode, only when we successfully have an object,\n  //    which means either (kHaveObject and range_.empty()), or\n  //    kHaveRange.\n  void Next() {\n    while (1) {\n      NextScpLine();\n      if (Done()) return;\n      if (opts_.permissive) {\n        // Permissive mode means, when reading scp files, we treat keys whose\n        // scp entry cannot be read as nonexistent.  This means trying to read.\n        if (EnsureObjectLoaded()) return;  // Success.\n        // else try the next scp line.\n      } else {\n        return;  // We go the next key; Value() will crash if we can't read the\n                 // object on the scp line.\n      }\n    }\n  }\n\n  // This function may be entered at in any state.  At exit, the object will be\n  // in state kUninitialized.  It only returns false in the situation where we\n  // were at the end of the stream (kEof) and the script_input_ was a pipe and\n  // it ended with error status; this is so that we can catch errors from\n  // programs that we invoked via a pipe.\n  virtual bool Close() {\n    int32 status = 0;\n    if (script_input_.IsOpen())\n      status = script_input_.Close();\n    if (data_input_.IsOpen())\n      data_input_.Close();\n    range_holder_.Clear();\n    holder_.Clear();\n    if (!this->IsOpen())\n      KALDI_ERR << \"Close() called on input that was not open.\";\n    StateType old_state = state_;\n    state_ = kUninitialized;\n    if (old_state == kError || (old_state == kEof && status != 0)) {\n      if (opts_.permissive) {\n        KALDI_WARN << \"Close() called on scp file with read error, ignoring the\"\n            \" error because permissive mode specified.\";\n        return true;\n      } else {\n        return false;  // User will do something with the error status.\n      }\n    } else {\n      return true;\n    }\n    // Possible states                                          Return value\n    // kLoadSucceeded/kRangeSucceeded/kRangeFailed              true\n    // kError (if opts_.permissive)                             true\n    // kError (if !opts_.permissive)                            false\n    // kEof (if script_input_.Close() && !opts.permissive)      false\n    // kEof (if !script_input_.Close() || opts.permissive)      true\n    // kUninitialized/kFileStart/kHaveScpLine                   true\n    // kUnitialized                                             true\n  }\n\n  virtual ~SequentialTableReaderScriptImpl() {\n    if (this->IsOpen() && !Close())\n      KALDI_ERR << \"TableReader: reading script file failed: from scp \"\n                      << PrintableRxfilename(script_rxfilename_);\n  }\n private:\n\n  // Function EnsureObjectLoaded() ensures that we have fully loaded any object\n  // (including object range) associated with the current key, and returns true\n  // on success (i.e. we have the object) and false on failure.\n  //\n  // Possible entry states: kHaveScpLine, kLoadSucceeded, kRangeSucceeded\n  //\n  // Possible exit states: kHaveScpLine, kLoadSucceeded, kRangeSucceeded.\n  //\n  // Note: the return status has information that cannot be deduced from\n  // just the exit state.  If the object could not be loaded we go to state\n  // kHaveScpLine but return false; and if the range was requested but\n  // could not be extracted, we go to state kLoadSucceeded but return false.\n  bool EnsureObjectLoaded() {\n    if (!(state_ == kHaveScpLine || state_ == kHaveObject ||\n          state_ == kHaveRange))\n      KALDI_ERR << \"Invalid state (code error)\";\n\n    if (state_ == kHaveScpLine) {  // need to load the object into holder_.\n      bool ans;\n      // note, NULL means it doesn't read the binary-mode header\n      if (Holder::IsReadInBinary()) {\n        ans = data_input_.Open(data_rxfilename_, NULL);\n      } else {\n        ans = data_input_.OpenTextMode(data_rxfilename_);\n      }\n      if (!ans) {\n        KALDI_WARN << \"Failed to open file \"\n                   << PrintableRxfilename(data_rxfilename_);\n        return false;\n      } else {\n        if (holder_.Read(data_input_.Stream())) {\n          state_ = kHaveObject;\n        } else {  // holder_ will not contain data.\n          KALDI_WARN << \"Failed to load object from \"\n                     << PrintableRxfilename(data_rxfilename_);\n          return false;\n        }\n      }\n    }\n    // OK, at this point the state must be either\n    // kHaveObject or kHaveRange.\n    if (range_.empty()) {\n      // if range_ is the empty string, we should not be in the state\n      // kHaveRange.\n      KALDI_ASSERT(state_ == kHaveObject);\n      return true;\n    }\n    // range_ is nonempty.\n    if (state_ == kHaveRange) {\n      // range was already extracted, so there nothing to do.\n      return true;\n    }\n    // OK, range_ is nonempty and state_ is kHaveObject.  We attempt to extract\n    // the range object.  Note: ExtractRange() will throw with KALDI_ERR if the\n    // object type doesn't support ranges.\n    if (!range_holder_.ExtractRange(holder_, range_)) {\n      KALDI_WARN  << \"Failed to load object from \"\n                  << PrintableRxfilename(data_rxfilename_)\n                  << \"[\" << range_ << \"]\";\n      return false;\n    } else {\n      state_ = kHaveRange;\n      return true;\n    }\n  }\n\n  void SetErrorState() {\n    state_ = kError;\n    script_input_.Close();\n    data_input_.Close();\n    holder_.Clear();\n    range_holder_.Clear();\n  }\n\n  // Reads the next line in the script file.\n  // Possible entry states: kHaveObject, kHaveRange, kHaveScpLine, kFileStart.\n  // Possible exit states: kEof, kError, kHaveScpLine, kHaveObject.\n  void NextScpLine() {\n    switch (state_) {  // Check and simplify the state.\n      case kHaveRange:\n        range_holder_.Clear();\n        state_ = kHaveObject;\n        break;\n      case kHaveScpLine: case kHaveObject: case kFileStart: break;\n      default:\n        // No other states are valid to call Next() from.\n        KALDI_ERR << \"Reading script file: Next called wrongly.\";\n    }\n    // at this point the state will be kHaveObject, kHaveScpLine, or kFileStart.\n    std::string line;\n    if (getline(script_input_.Stream(), line)) {\n      // After extracting \"key\" from \"line\", we put the rest\n      // of \"line\" into \"rest\", and then extract data_rxfilename_\n      // (e.g. 1.ark:100) and possibly the range_ specifer\n      // (e.g. [1:2,2:10]) from \"rest\".\n      std::string data_rxfilename, rest;\n      SplitStringOnFirstSpace(line, &key_, &rest);\n      if (!key_.empty() && !rest.empty()) {\n        // Got a valid line.\n        if (rest[rest.size()-1] == ']') {\n          if(!ExtractRangeSpecifier(rest, &data_rxfilename, &range_)) {\n            KALDI_WARN << \"Reading rspecifier '\" << rspecifier_\n                       << \", cannot make sense of scp line \"\n                       << line;\n            SetErrorState();\n            return;\n          }\n        } else {\n          data_rxfilename = rest;\n          range_ = \"\";\n        }\n        bool filenames_equal = (data_rxfilename_ == data_rxfilename);\n        if (!filenames_equal)\n          data_rxfilename_ = data_rxfilename;\n        if (state_ == kHaveObject) {\n          if (!filenames_equal) {\n            holder_.Clear();\n            state_ = kHaveScpLine;\n          }\n          // else leave state_ at kHaveObject and leave the object in the\n          // holder.\n        } else {\n          state_ = kHaveScpLine;\n        }\n      } else {\n        KALDI_WARN << \"We got an invalid line in the scp file. \"\n                   << \"It should look like: some_key 1.ark:10, got: \"\n                   << line;\n        SetErrorState();\n      }\n    } else {\n      state_ = kEof;  // there is nothing more in the scp file.  Might as well\n                      // close input streams as we don't need them.\n      script_input_.Close();\n      if (data_input_.IsOpen())\n        data_input_.Close();\n      holder_.Clear();  // clear the holder if it was nonempty.\n      range_holder_.Clear();  // clear the range holder if it was nonempty.\n    }\n  }\n\n  std::string rspecifier_;  // the rspecifier that this class was opened with.\n  RspecifierOptions opts_;  // options.\n  std::string script_rxfilename_;  // rxfilename of the script file.\n\n  Input script_input_;  // Input object for the .scp file\n  Input data_input_;   // Input object for the entries in the script file;\n                       // we make this a class member instead of a local variable,\n                       // so that rspecifiers of the form filename:byte-offset,\n                       // e.g. foo.ark:12345, can be handled using fseek().\n\n  Holder holder_;       // Holds the object.\n  Holder range_holder_; // Holds the partial object corresponding to the object\n                        // range specifier 'range_'; this is only used when\n                        // 'range_' is specified, i.e. when the .scp file\n                        // contains lines of the form rspecifier[range], like\n                        // foo.ark:242[0:9] (representing a row range of a\n                        // matrix).\n\n\n  std::string key_;  // the key of the current scp line we're processing\n  std::string data_rxfilename_;  // the rxfilename corresponding to the current key\n  std::string range_;  // the range of object corresponding to the current key, if an\n                       // object range was specified in the script file, else \"\".\n\n  enum StateType {\n    //  Summary of the states this object can be in (state_).\n    //\n    //                (*) Does holder_ contain the object corresponding to\n    //                    data_rxfilename_ ?\n    //                    (*) Does range_holder_ contain a range object?\n    //                         (*) is script_input_ open?\n    //                             (*) are key_, data_rxfilename_ and range_ [if applicable] set?\n    //\n    kUninitialized, // no  no  no  no            Uninitialized or closed object.\n    kFileStart,     // no  no  yes no            We just opened the .scp file (we'll never be in this\n                    //                           state when a user-visible function is called.)\n    kEof,           // no  no  no  no            We did Next() and found eof in script file.\n    kError,         // no  no  no  no            Error reading or parsing script file.\n    kHaveScpLine,   // no  no  yes yes           Have a line of the script file but nothing else.\n    kHaveObject,    // yes no  yes yes           holder_ contains an object but range_holder_ does not.\n    kHaveRange,     // yes yes yes yes           we have the range object in range_holder_ (implies\n                    //                           range_ nonempty).\n  } state_;\n\n\n};\n\n\n// This is the implementation for SequentialTableReader\n// when it's an archive.  Note that the archive format is:\n// key1 [space] object1 key2 [space]\n// object2 ... eof.\n// \"object1\" is the output of the Holder::Write function and will\n// typically contain a binary header (in binary mode) and then\n// the output of object.Write(os, binary).\n// The archive itself does not care whether it is in binary\n// or text mode, for reading purposes.\n\ntemplate<class Holder>  class SequentialTableReaderArchiveImpl:\n      public SequentialTableReaderImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  SequentialTableReaderArchiveImpl(): state_(kUninitialized) { }\n\n  virtual bool Open(const std::string &rspecifier) {\n    if (state_ != kUninitialized) {\n      if (!Close()) {  // call Close() yourself to suppress this exception.\n        if (opts_.permissive)\n          KALDI_WARN << \"Error closing previous input \"\n              \"(only warning, since permissive mode).\";\n        else\n          KALDI_ERR << \"Error closing previous input.\";\n      }\n    }\n    rspecifier_ = rspecifier;\n    RspecifierType rs = ClassifyRspecifier(rspecifier,\n                                           &archive_rxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(rs == kArchiveRspecifier);\n\n    bool ans;\n    // NULL means don't expect binary-mode header\n    if (Holder::IsReadInBinary())\n      ans = input_.Open(archive_rxfilename_, NULL);\n    else\n      ans = input_.OpenTextMode(archive_rxfilename_);\n    if (!ans) {  // header.\n      KALDI_WARN << \"Failed to open stream \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kUninitialized;  // Failure on Open\n      return false;  // User should print the error message.\n    }\n    state_ = kFileStart;\n    Next();\n    if (state_ == kError) {\n      KALDI_WARN << \"Error beginning to read archive file (wrong filename?): \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      input_.Close();\n      state_ = kUninitialized;\n      return false;\n    }\n    KALDI_ASSERT(state_ == kHaveObject || state_ == kEof);\n    return true;\n  }\n\n  virtual void Next() {\n    switch (state_) {\n      case kHaveObject:\n        holder_.Clear();\n        break;\n      case kFileStart: case kFreedObject:\n        break;\n      default:\n        KALDI_ERR << \"Next() called wrongly.\";\n    }\n    std::istream &is = input_.Stream();\n    is.clear();  // Clear any fail bits that may have been set... just in case\n    // this happened in the Read function.\n    is >> key_;  // This eats up any leading whitespace and gets the string.\n    if (is.eof()) {\n      state_ = kEof;\n      return;\n    }\n    if (is.fail()) {  // This shouldn't really happen, barring file-system\n                      // errors.\n      KALDI_WARN << \"Error reading archive \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kError;\n      return;\n    }\n    int c;\n    if ((c = is.peek()) != ' ' && c != '\\t' && c != '\\n') {  // We expect a\n                                                     // space ' ' after the key.\n      // We also allow tab [which is consumed] and newline [which is not], just\n      // so we can read archives generated by scripts that may not be fully\n      // aware of how this format works.\n      KALDI_WARN << \"Invalid archive file format: expected space after key \"\n                 << key_ << \", got character \"\n                 << CharToString(static_cast<char>(is.peek())) << \", reading \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kError;\n      return;\n    }\n    if (c != '\\n') is.get();  // Consume the space or tab.\n    if (holder_.Read(is)) {\n      state_ = kHaveObject;\n      return;\n    } else {\n      KALDI_WARN << \"Object read failed, reading archive \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kError;\n      return;\n    }\n  }\n\n  virtual bool IsOpen() const {\n    switch (state_) {\n      case kEof: case kError: case kHaveObject: case kFreedObject: return true;\n      case kUninitialized: return false;\n      default: KALDI_ERR << \"IsOpen() called on invalid object.\";  // kFileStart\n        // is not valid state for user to call something on.\n        return false;\n    }\n  }\n\n  virtual bool Done() const {\n    switch (state_) {\n      case kHaveObject:\n        return false;\n      case kEof: case kError:\n        return true;  // Error-state counts as Done(), but destructor\n        // will fail (unless you check the status with Close()).\n      default:\n        KALDI_ERR << \"Done() called on TableReader object at the wrong time.\";\n        return false;\n    }\n  }\n\n  virtual std::string Key() {\n    // Valid to call this whenever Done() returns false\n    switch (state_) {\n      case kHaveObject: break;  // only valid case.\n      default:\n        // coding error.\n        KALDI_ERR << \"Key() called on TableReader object at the wrong time.\";\n    }\n    return key_;\n  }\n\n  T &Value() {\n    switch (state_) {\n      case kHaveObject:\n        break;  // only valid case.\n      default:\n        // coding error.\n        KALDI_ERR << \"Value() called on TableReader object at the wrong time.\";\n    }\n    return holder_.Value();\n  }\n\n  virtual void FreeCurrent() {\n    if (state_ == kHaveObject) {\n      holder_.Clear();\n      state_ = kFreedObject;\n    } else {\n      KALDI_WARN << \"FreeCurrent called at the wrong time.\";\n    }\n  }\n\n  void SwapHolder(Holder *other_holder) {\n    // call Value() to ensure we have a value, and ignore its return value while\n    // suppressing compiler warnings by casting to void.\n    (void) Value();\n    if (state_ == kHaveObject) {\n      holder_.Swap(other_holder);\n      state_ = kFreedObject;\n    } else {\n      KALDI_ERR << \"SwapHolder called at the wrong time \"\n                   \"(error related to ',bg' modifier).\";\n    }\n  }\n\n  virtual bool Close() {\n    // To clean up, Close() also closes the Input object if\n    // it's open.  It will succeed if the stream was not in an error state,\n    // and the Input object isn't in an error state  we've found eof in the archive.\n    if (!this->IsOpen())\n      KALDI_ERR << \"Close() called on TableReader twice or otherwise wrongly.\";\n    int32 status = 0;\n    if (input_.IsOpen())\n      status = input_.Close();\n    if (state_ == kHaveObject)\n      holder_.Clear();\n    StateType old_state = state_;\n    state_ = kUninitialized;\n    if (old_state == kError || (old_state == kEof && status != 0)) {\n      if (opts_.permissive) {\n        KALDI_WARN << \"Error detected closing TableReader for archive \"\n                   << PrintableRxfilename(archive_rxfilename_)\n                   << \" but ignoring \"\n                   << \"it as permissive mode specified.\";\n        return true;\n      } else {\n        return false;\n      }\n    } else {\n      return true;\n    }\n  }\n\n  virtual ~SequentialTableReaderArchiveImpl() {\n    if (this->IsOpen() && !Close())\n      KALDI_ERR << \"TableReader: error detected closing archive \"\n                << PrintableRxfilename(archive_rxfilename_);\n  }\n private:\n  Input input_;  // Input object for the archive\n  Holder holder_;     // Holds the object.\n  std::string key_;\n  std::string rspecifier_;\n  std::string archive_rxfilename_;\n  RspecifierOptions opts_;\n  enum StateType {  //  [The state of the reading process]        [does holder_ [is input_\n    //                                                     have object]   open]\n    kUninitialized,  // Uninitialized or closed.                  no         no\n    kFileStart,      // [state we use internally: just opened.]   no         yes\n    kEof,     // We did Next() and found eof in archive           no         no\n    kError,   // Some other error                                 no         no\n    kHaveObject,  // We read the key and the object after it.     yes        yes\n    kFreedObject,  // The user called FreeCurrent().              no         yes\n  } state_;\n};\n\n// this is for when someone adds the 'th' modifier; it wraps around the basic\n// implementation and allows it to do the reading in a background thread.\ntemplate<class Holder>\nclass SequentialTableReaderBackgroundImpl:\n      public SequentialTableReaderImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  SequentialTableReaderBackgroundImpl(\n      SequentialTableReaderImplBase<Holder> *base_reader):\n      base_reader_(base_reader) {}\n\n  // This function ignores the rxfilename argument.\n  // We use the same function signature as the regular Open(),\n  // for convenience.\n  virtual bool Open(const std::string &rxfilename) {\n    KALDI_ASSERT(base_reader_ != NULL &&\n                 base_reader_->IsOpen());  // or code error.\n    {\n      thread_ = std::thread(SequentialTableReaderBackgroundImpl<Holder>::run,\n                            this);\n    }\n\n    if (!base_reader_->Done())\n      Next();\n    return true;\n  }\n\n  virtual bool IsOpen() const {\n    // Close() sets base_reader_ to NULL, and we never initialize this object\n    // with a non-open base_reader_, so no need to check if it's open.\n    return base_reader_ != NULL;\n  }\n\n  void RunInBackground() {\n    try {\n      // This function is called in the background thread.  The whole point of\n      // the background thread is that we don't want to do the actual reading\n      // (inside Next()) in the foreground.\n      while (base_reader_ != NULL && !base_reader_->Done()) {\n        consumer_sem_.Signal();\n        // Here is where the consumer process (parent thread) gets to do its\n        // stuff.  Principally it calls SwapHolder()-- a shallow swap that is\n        // cheap.\n        producer_sem_.Wait();\n        // we check that base_reader_ is not NULL in case Close() was\n        // called in the main thread.\n        if (base_reader_ != NULL)\n          base_reader_->Next();   //  here is where the work happens.\n      }\n      // this signal will be waited on in the Next() function of the foreground\n      // thread if it is still running, or Close() otherwise.\n      consumer_sem_.Signal();\n      // this signal may be waited on in Close().\n      consumer_sem_.Signal();\n    } catch (...) {\n      // There is nothing we called above that could potentially throw due to\n      // user data.  So we treat reaching this point as a code-error condition.\n      // Closing base_reader_ will trigger an exception in Next() in the main\n      // thread when it checks that base_reader_->IsOpen().\n      if (base_reader_->IsOpen()) {\n        base_reader_->Close();\n        delete base_reader_;\n        base_reader_ = NULL;\n      }\n      consumer_sem_.Signal();\n      return;\n    }\n  }\n  static void run(SequentialTableReaderBackgroundImpl<Holder> *object) {\n    object->RunInBackground();\n  }\n  virtual bool Done() const {\n    return key_.empty();\n  }\n  virtual std::string Key() {\n    if (key_.empty())\n      KALDI_ERR << \"Calling Key() at the wrong time.\";\n    return key_;\n  }\n  virtual T &Value() {\n    if (key_.empty())\n      KALDI_ERR << \"Calling Value() at the wrong time.\";\n    return holder_.Value();\n  }\n  void SwapHolder(Holder *other_holder) {\n    KALDI_ERR << \"SwapHolder() should not be called on this class.\";\n  }\n  virtual void FreeCurrent() {\n    if (key_.empty())\n      KALDI_ERR << \"Calling FreeCurrent() at the wrong time.\";\n    // note: ideally a call to Value() should crash if you have just called\n    // FreeCurrent().  For typical holders such as KaldiObjectHolder this will\n    // happen inside the holder_.Value() call.  This won't be the case for all\n    // holders, but it's not a great loss (just a missed opportunity to spot a\n    // code error).\n    holder_.Clear();\n  }\n  virtual void Next() {\n    consumer_sem_.Wait();\n    if (base_reader_ == NULL || !base_reader_->IsOpen())\n      KALDI_ERR << \"Error detected (likely code error) in background \"\n                << \"reader (',bg' option)\";\n    if (base_reader_->Done()) {\n      // there is nothing else to read.\n      key_ = \"\";\n    } else {\n      key_ = base_reader_->Key();\n      base_reader_->SwapHolder(&holder_);\n    }\n    // this Signal() tells the producer thread, in the background,\n    // that it's now safe to read the next value.\n    producer_sem_.Signal();\n  }\n\n  // note: we can be sure that Close() won't be called twice, as the TableReader\n  // object will delete this object after calling Close.\n  virtual bool Close() {\n    KALDI_ASSERT(base_reader_ != NULL && thread_.joinable());\n    // wait until the producer thread is idle.\n    consumer_sem_.Wait();\n    bool ans = true;\n    try {\n      ans = base_reader_->Close();\n    } catch (...) {\n      ans = false;\n    }\n    delete base_reader_;\n    // setting base_reader_ to NULL will cause the loop in the producer thread\n    // to exit.\n    base_reader_ = NULL;\n    producer_sem_.Signal();\n\n    thread_.join();\n    return ans;\n  }\n  ~SequentialTableReaderBackgroundImpl() {\n    if (base_reader_) {\n      if (!Close()) {\n        KALDI_ERR << \"Error detected closing background reader \"\n                  << \"(relates to ',bg' modifier)\";\n      }\n    }\n  }\n private:\n  std::string key_;\n  Holder holder_;\n  // I couldn't figure out what to call these semaphores.  consumer_sem_ is the\n  // one that the consumer (main thread) waits on; producer_sem_ is the one\n  // that the producer (background thread) waits on.\n  Semaphore consumer_sem_;\n  Semaphore producer_sem_;\n  std::thread thread_;\n  SequentialTableReaderImplBase<Holder> *base_reader_;\n\n};\n\ntemplate<class Holder>\nSequentialTableReader<Holder>::SequentialTableReader(const std::string\n                                                     &rspecifier): impl_(NULL) {\n  if (rspecifier != \"\" && !Open(rspecifier))\n    KALDI_ERR << \"Error constructing TableReader: rspecifier is \" << rspecifier;\n}\n\ntemplate<class Holder>\nbool SequentialTableReader<Holder>::Open(const std::string &rspecifier) {\n  if (IsOpen())\n    if (!Close())\n      KALDI_ERR << \"Could not close previously open object.\";\n  // now impl_ will be NULL.\n\n  RspecifierOptions opts;\n  RspecifierType wt = ClassifyRspecifier(rspecifier, NULL, &opts);\n  switch (wt) {\n    case kArchiveRspecifier:\n      impl_ = new SequentialTableReaderArchiveImpl<Holder>();\n      break;\n    case kScriptRspecifier:\n      impl_ = new SequentialTableReaderScriptImpl<Holder>();\n      break;\n    case kNoRspecifier: default:\n      KALDI_WARN << \"Invalid rspecifier \" << rspecifier;\n      return false;\n  }\n  if (!impl_->Open(rspecifier)) {\n    delete impl_;\n    impl_ = NULL;\n    return false;  // sub-object will have printed warnings.\n  }\n  if (opts.background) {\n    impl_ = new SequentialTableReaderBackgroundImpl<Holder>(\n        impl_);\n    if (!impl_->Open(\"\")) {\n      // the rxfilename is ignored in that Open() call.\n      // It should only return false on code error.\n      return false;\n    }\n  }\n  return true;\n}\n\ntemplate<class Holder>\nbool SequentialTableReader<Holder>::Close() {\n  CheckImpl();\n  bool ans = impl_->Close();\n  delete impl_;  // We don't keep around empty impl_ objects.\n  impl_ = NULL;\n  return ans;\n}\n\n\ntemplate<class Holder>\nbool SequentialTableReader<Holder>::IsOpen() const {\n  return (impl_ != NULL);  // Because we delete the object whenever\n  // that object is not open.  Thus, the IsOpen functions of the\n  // Impl objects are not really needed.\n}\n\ntemplate<class Holder>\nstd::string SequentialTableReader<Holder>::Key() {\n  CheckImpl();\n  return impl_->Key();  // this call may throw if called wrongly in other ways,\n  // e.g. eof.\n}\n\n\ntemplate<class Holder>\nvoid SequentialTableReader<Holder>::FreeCurrent() {\n  CheckImpl();\n  impl_->FreeCurrent();\n}\n\n\ntemplate<class Holder>\ntypename SequentialTableReader<Holder>::T &\nSequentialTableReader<Holder>::Value() {\n  CheckImpl();\n  return impl_->Value();  // This may throw (if EnsureObjectLoaded() returned false you\n                          // are safe.).\n}\n\n\ntemplate<class Holder>\nvoid SequentialTableReader<Holder>::Next() {\n  CheckImpl();\n  impl_->Next();\n}\n\ntemplate<class Holder>\nbool SequentialTableReader<Holder>::Done() {\n  CheckImpl();\n  return impl_->Done();\n}\n\n\ntemplate<class Holder>\nSequentialTableReader<Holder>::~SequentialTableReader() {\n  delete impl_;\n  // Destructor of impl_ may throw.\n}\n\n\n\ntemplate<class Holder> class TableWriterImplBase {\n public:\n  typedef typename Holder::T T;\n\n  virtual bool Open(const std::string &wspecifier) = 0;\n\n  // Write returns true on success, false on failure, but\n  // some errors may not be detected until we call Close().\n  // It throws (via KALDI_ERR) if called wrongly.  We could\n  // have just thrown on all errors, since this is what\n  // TableWriter does; it was designed this way because originally\n  // TableWriter::Write returned an exit status.\n  virtual bool Write(const std::string &key, const T &value) = 0;\n\n  // Flush will flush any archive; it does not return error status,\n  //  any errors will be reported on the next Write or Close.\n  virtual void Flush() = 0;\n\n  virtual bool Close() = 0;\n\n  virtual bool IsOpen() const = 0;\n\n  // May throw on write error if Close was not called.\n  virtual ~TableWriterImplBase() { }\n\n  TableWriterImplBase() { }\n private:\n  KALDI_DISALLOW_COPY_AND_ASSIGN(TableWriterImplBase);\n};\n\n\n// The implementation of TableWriter we use when writing directly\n// to an archive with no associated scp.\ntemplate<class Holder>\nclass TableWriterArchiveImpl: public TableWriterImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  virtual bool Open(const std::string &wspecifier) {\n    switch (state_) {\n      case kUninitialized:\n        break;\n      case kWriteError:\n        KALDI_ERR << \"Opening stream, already open with write error.\";\n      case kOpen: default:\n        if (!Close())  // throw because this error may not have been previously\n          // detected by the user.\n          KALDI_ERR << \"Opening stream, error closing previously open stream.\";\n    }\n    wspecifier_ = wspecifier;\n    WspecifierType ws = ClassifyWspecifier(wspecifier,\n                                           &archive_wxfilename_,\n                                           NULL,\n                                           &opts_);\n    KALDI_ASSERT(ws == kArchiveWspecifier);  // or wrongly called.\n\n    if (output_.Open(archive_wxfilename_, opts_.binary, false)) {  // false\n                                                      // means no binary header.\n      state_ = kOpen;\n      return true;\n    } else {\n      // stream will not be open.  User will report this error\n      // (we return bool), so don't bother printing anything.\n      state_ = kUninitialized;\n      return false;\n    }\n  }\n\n  virtual bool IsOpen() const {\n    switch (state_) {\n      case kUninitialized: return false;\n      case kOpen: case kWriteError: return true;\n      default: KALDI_ERR << \"IsOpen() called on TableWriter in invalid state.\";\n    }\n    return false;\n  }\n\n  // Write returns true on success, false on failure, but\n  // some errors may not be detected till we call Close().\n  virtual bool Write(const std::string &key, const T &value) {\n    switch (state_) {\n      case kOpen: break;\n      case kWriteError:\n        // user should have known from the last\n        // call to Write that there was a problem.\n        KALDI_WARN << \"Attempting to write to invalid stream.\";\n        return false;\n      case kUninitialized: default:\n        KALDI_ERR << \"Write called on invalid stream\";\n    }\n    // state is now kOpen or kWriteError.\n    if (!IsToken(key))  // e.g. empty string or has spaces...\n      KALDI_ERR << \"Using invalid key \" << key;\n    output_.Stream() << key << ' ';\n    if (!Holder::Write(output_.Stream(), opts_.binary, value)) {\n      KALDI_WARN << \"Write failure to \"\n                 << PrintableWxfilename(archive_wxfilename_);\n      state_ = kWriteError;\n      return false;\n    }\n    if (state_ == kWriteError) return false;  // Even if this Write seems to\n    // have succeeded, we fail because a previous Write failed and the archive\n    // may be corrupted and unreadable.\n\n    if (opts_.flush)\n      Flush();\n    return true;\n  }\n\n  // Flush will flush any archive; it does not return error status,\n  //  any errors will be reported on the next Write or Close.\n  virtual void Flush() {\n    switch (state_) {\n      case kWriteError: case kOpen:\n        output_.Stream().flush();  // Don't check error status.\n        return;\n      default:\n        KALDI_WARN << \"Flush called on not-open writer.\";\n    }\n  }\n\n  virtual bool Close() {\n    if (!this->IsOpen() || !output_.IsOpen())\n      KALDI_ERR << \"Close called on a stream that was not open.\"\n                << this->IsOpen() << \", \" << output_.IsOpen();\n    bool close_success = output_.Close();\n    if (!close_success) {\n      KALDI_WARN << \"Error closing stream: wspecifier is \" << wspecifier_;\n      state_ = kUninitialized;\n      return false;\n    }\n    if (state_ == kWriteError) {\n      KALDI_WARN << \"Closing writer in error state: wspecifier is \"\n                 << wspecifier_;\n      state_ = kUninitialized;\n      return false;\n    }\n    state_ = kUninitialized;\n    return true;\n  }\n\n  TableWriterArchiveImpl(): state_(kUninitialized) {}\n\n  // May throw on write error if Close was not called.\n  virtual ~TableWriterArchiveImpl() {\n    if (!IsOpen()) return;\n    else if (!Close())\n      KALDI_ERR << \"At TableWriter destructor: Write failed or stream close \"\n                << \"failed: wspecifier is \"<<  wspecifier_;\n  }\n\n private:\n  Output output_;\n  WspecifierOptions opts_;\n  std::string wspecifier_;\n  std::string archive_wxfilename_;\n  enum {               // is stream open?\n    kUninitialized,    // no\n    kOpen,             // yes\n    kWriteError,       // yes\n  } state_;\n};\n\n\n\n\n// The implementation of TableWriter we use when writing to\n// individual files (more generally, wxfilenames) specified\n// in an scp file that we read.\n\n// Note: the code for this class is similar to\n// RandomAccessTableReaderScriptImpl; try to keep them in sync.\n\ntemplate<class Holder>\nclass TableWriterScriptImpl: public TableWriterImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  TableWriterScriptImpl(): last_found_(0), state_(kUninitialized) {}\n\n  virtual bool Open(const std::string &wspecifier) {\n    switch (state_) {\n      case kReadScript:\n        KALDI_ERR << \" Opening already open TableWriter: call Close first.\";\n      case kUninitialized: case kNotReadScript:\n        break;\n    }\n    wspecifier_ = wspecifier;\n    WspecifierType ws = ClassifyWspecifier(wspecifier,\n                                           NULL,\n                                           &script_rxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(ws == kScriptWspecifier);  // or wrongly called.\n    KALDI_ASSERT(script_.empty());  // no way it could be nonempty at this point.\n\n    if (!ReadScriptFile(script_rxfilename_,\n                         true,  // print any warnings\n                         &script_)) {  // error reading script file or invalid\n                                       // format\n      state_ = kNotReadScript;\n      return false;  // no need to print further warnings.  user gets the error.\n    }\n    std::sort(script_.begin(), script_.end());\n    for (size_t i = 0; i+1 < script_.size(); i++) {\n      if (script_[i].first.compare(script_[i+1].first) >= 0) {\n        // script[i] not < script[i+1] in lexical order...\n        KALDI_WARN << \"Script file \" << PrintableRxfilename(script_rxfilename_)\n                   << \" contains duplicate key \" << script_[i].first;\n        state_ = kNotReadScript;\n        return false;\n      }\n    }\n    state_ = kReadScript;\n    return true;\n  }\n\n  virtual bool IsOpen() const {  return (state_ == kReadScript);  }\n\n  virtual bool Close() {\n    if (!IsOpen())\n      KALDI_ERR << \"Close() called on TableWriter that was not open.\";\n    state_ = kUninitialized;\n    last_found_ = 0;\n    script_.clear();\n    return true;\n  }\n\n  // Write returns true on success, false on failure, but\n  // some errors may not be detected till we call Close().\n  virtual bool Write(const std::string &key, const T &value) {\n    if (!IsOpen())\n      KALDI_ERR << \"Write called on invalid stream\";\n\n    if (!IsToken(key))  // e.g. empty string or has spaces...\n      KALDI_ERR << \"Using invalid key \" << key;\n\n    std::string wxfilename;\n    if (!LookupFilename(key, &wxfilename)) {\n      if (opts_.permissive) {\n        return true;  // In permissive mode, it's as if we're writing to\n                     // /dev/null for missing keys.\n      } else {\n        KALDI_WARN << \"Script file \"\n                   << PrintableRxfilename(script_rxfilename_)\n                   << \" has no entry for key \" <<key;\n        return false;\n      }\n    }\n    Output output;\n    if (!output.Open(wxfilename, opts_.binary, false)) {\n      // Open in the text/binary mode (on Windows) given by member var. \"binary\"\n      // (obtained from wspecifier), but do not put the binary-mode header (it\n      // will be written, if needed, by the Holder::Write function.)\n      KALDI_WARN << \"Failed to open stream: \"\n                 << PrintableWxfilename(wxfilename);\n      return false;\n    }\n    if (!Holder::Write(output.Stream(), opts_.binary, value)\n        || !output.Close()) {\n      KALDI_WARN << \"Failed to write data to \"\n                 << PrintableWxfilename(wxfilename);\n\n      return false;\n    }\n    return true;\n  }\n\n  // Flush does nothing in this implementation, there is nothing to flush.\n  virtual void Flush() { }\n\n\n  virtual ~TableWriterScriptImpl() {\n    // Nothing to do in destructor.\n  }\n\n private:\n  // Note: this function is almost the same as in\n  // RandomAccessTableReaderScriptImpl.\n  bool LookupFilename(const std::string &key, std::string *wxfilename) {\n    // First, an optimization: if we're going consecutively, this will\n    // make the lookup very fast.\n    last_found_++;\n    if (last_found_ < script_.size() && script_[last_found_].first == key) {\n      *wxfilename = script_[last_found_].second;\n      return true;\n    }\n    std::pair<std::string, std::string> pr(key, \"\");  // Important that \"\"\n    // compares less than or equal to any string, so lower_bound points to the\n    // element that has the same key.\n    typedef typename std::vector<std::pair<std::string, std::string> >\n                     ::const_iterator IterType;\n    IterType iter = std::lower_bound(script_.begin(), script_.end(), pr);\n    if (iter != script_.end() && iter->first == key) {\n      last_found_ = iter - script_.begin();\n      *wxfilename = iter->second;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n\n  WspecifierOptions opts_;\n  std::string wspecifier_;\n  std::string script_rxfilename_;\n\n  // the script_ variable contains pairs of (key, filename), sorted using\n  // std::sort.  This can be used with binary_search to look up filenames for\n  // writing.  If this becomes inefficient we can use std::unordered_map (but I\n  // suspect this wouldn't be significantly faster & would use more memory).\n  // If memory becomes a problem here, the user should probably be passing\n  // only the relevant part of the scp file rather than expecting us to get too\n  // clever in the code.\n  std::vector<std::pair<std::string, std::string> > script_;\n  size_t last_found_;  // This is for an optimization used in LookupFilename.\n\n  enum {\n    kUninitialized,\n    kReadScript,\n    kNotReadScript,  // read of script failed.\n  } state_;\n};\n\n\n// The implementation of TableWriter we use when writing directly\n// to an archive plus an associated scp.\ntemplate<class Holder>\nclass TableWriterBothImpl: public TableWriterImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  virtual bool Open(const std::string &wspecifier) {\n    switch (state_) {\n      case kUninitialized:\n        break;\n      case kWriteError:\n        KALDI_ERR << \"Opening stream, already open with write error.\";\n      case kOpen: default:\n        if (!Close())  // throw because this error may not have been previously\n                       // detected by user.\n          KALDI_ERR << \"Opening stream, error closing previously open stream.\";\n    }\n    wspecifier_ = wspecifier;\n    WspecifierType ws = ClassifyWspecifier(wspecifier,\n                                           &archive_wxfilename_,\n                                           &script_wxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(ws == kBothWspecifier);  // or wrongly called.\n    if (ClassifyWxfilename(archive_wxfilename_) != kFileOutput)\n      KALDI_WARN << \"When writing to both archive and script, the script file \"\n          \"will generally not be interpreted correctly unless the archive is \"\n          \"an actual file: wspecifier = \" << wspecifier;\n\n    if (!archive_output_.Open(archive_wxfilename_, opts_.binary, false)) {\n      // false means no binary header.\n      state_ = kUninitialized;\n      return false;\n    }\n    if (!script_output_.Open(script_wxfilename_, false, false)) {  // first\n      // false means text mode: script files always text-mode.   second false\n      //  means don't write header (doesn't matter for text mode).\n      archive_output_.Close();  // Don't care about status: error anyway.\n      state_ = kUninitialized;\n      return false;\n    }\n    state_ = kOpen;\n    return true;\n  }\n\n  virtual bool IsOpen() const {\n    switch (state_) {\n      case kUninitialized: return false;\n      case kOpen: case kWriteError: return true;\n      default: KALDI_ERR << \"IsOpen() called on TableWriter in invalid state.\";\n    }\n    return false;\n  }\n\n  void MakeFilename(typename std::ostream::pos_type streampos,\n                    std::string *output) const {\n    std::ostringstream ss;\n    ss << ':' << streampos;\n    KALDI_ASSERT(ss.str() != \":-1\");\n    *output = archive_wxfilename_ + ss.str();\n\n    // e.g. /some/file:12302.\n    // Note that we warned if archive_wxfilename_ is not an actual filename;\n    // the philosophy is we give the user rope and if they want to hang\n    // themselves, with it, fine.\n  }\n\n  // Write returns true on success, false on failure, but\n  // some errors may not be detected till we call Close().\n  virtual bool Write(const std::string &key, const T &value) {\n    switch (state_) {\n      case kOpen: break;\n      case kWriteError:\n        // user should have known from the last\n        // call to Write that there was a problem.  Warn about it.\n        KALDI_WARN << \"Writing to non-open TableWriter object.\";\n        return false;\n      case kUninitialized: default:\n        KALDI_ERR << \"Write called on invalid stream\";\n    }\n    // state is now kOpen or kWriteError.\n    if (!IsToken(key))  // e.g. empty string or has spaces...\n      KALDI_ERR << \"Using invalid key \" << key;\n    std::ostream &archive_os = archive_output_.Stream();\n    archive_os << key << ' ';\n    typename std::ostream::pos_type archive_os_pos = archive_os.tellp();\n    // position at start of Write() to archive.  We will record this in the\n    // script file.\n    std::string offset_rxfilename;  // rxfilename with offset into the archive,\n    // e.g. some_archive_name.ark:431541423\n    MakeFilename(archive_os_pos, &offset_rxfilename);\n\n    // Write to the script file first.\n    // The idea is that we want to get all the information possible into the\n    // script file, to make it easier to unwind errors later.\n    std::ostream &script_os = script_output_.Stream();\n    script_output_.Stream() << key << ' ' << offset_rxfilename << '\\n';\n\n    if (!Holder::Write(archive_output_.Stream(), opts_.binary, value)) {\n      KALDI_WARN << \"Write failure to\"\n                 << PrintableWxfilename(archive_wxfilename_);\n      state_ = kWriteError;\n      return false;\n    }\n\n    if (script_os.fail()) {\n      KALDI_WARN << \"Write failure to script file detected: \"\n                 << PrintableWxfilename(script_wxfilename_);\n      state_ = kWriteError;\n      return false;\n    }\n\n    if (archive_os.fail()) {\n      KALDI_WARN << \"Write failure to archive file detected: \"\n                 << PrintableWxfilename(archive_wxfilename_);\n      state_ = kWriteError;\n      return false;\n    }\n\n    if (state_ == kWriteError) return false;  // Even if this Write seems to\n    // have succeeded, we fail because a previous Write failed and the archive\n    // may be corrupted and unreadable.\n\n    if (opts_.flush)\n      Flush();\n    return true;\n  }\n\n  // Flush will flush any archive; it does not return error status,\n  //  any errors will be reported on the next Write or Close.\n  virtual void Flush() {\n    switch (state_) {\n      case kWriteError: case kOpen:\n        archive_output_.Stream().flush();  // Don't check error status.\n        script_output_.Stream().flush();  // Don't check error status.\n        return;\n      default:\n        KALDI_WARN << \"Flush called on not-open writer.\";\n    }\n  }\n\n  virtual bool Close() {\n    if (!this->IsOpen())\n      KALDI_ERR << \"Close called on a stream that was not open.\";\n    bool close_success = true;\n    if (archive_output_.IsOpen())\n      if (!archive_output_.Close()) close_success = false;\n    if (script_output_.IsOpen())\n      if (!script_output_.Close()) close_success = false;\n    bool ans = close_success && (state_ != kWriteError);\n    state_ = kUninitialized;\n    return ans;\n  }\n\n  TableWriterBothImpl(): state_(kUninitialized) {}\n\n  // May throw on write error if Close() was not called.\n  // User can get the error status by calling Close().\n  virtual ~TableWriterBothImpl() {\n    if (!IsOpen()) return;\n    else if (!Close())\n      KALDI_ERR << \"Write failed or stream close failed: \"\n                << wspecifier_;\n  }\n\n private:\n  Output archive_output_;\n  Output script_output_;\n  WspecifierOptions opts_;\n  std::string archive_wxfilename_;\n  std::string script_wxfilename_;\n  std::string wspecifier_;\n  enum {               // is stream open?\n    kUninitialized,    // no\n    kOpen,             // yes\n    kWriteError,       // yes\n  } state_;\n};\n\n\ntemplate<class Holder>\nTableWriter<Holder>::TableWriter(const std::string &wspecifier): impl_(NULL) {\n  if (wspecifier != \"\" && !Open(wspecifier))\n    KALDI_ERR << \"Failed to open table for writing with wspecifier: \" << wspecifier\n              << \": errno (in case it's relevant) is: \" << strerror(errno);\n}\n\ntemplate<class Holder>\nbool TableWriter<Holder>::IsOpen() const {\n  return (impl_ != NULL);\n}\n\n\ntemplate<class Holder>\nbool TableWriter<Holder>::Open(const std::string &wspecifier) {\n  if (IsOpen()) {\n    if (!Close())  // call Close() yourself to suppress this exception.\n      KALDI_ERR << \"Failed to close previously open writer.\";\n  }\n  KALDI_ASSERT(impl_ == NULL);\n  WspecifierType wtype = ClassifyWspecifier(wspecifier, NULL, NULL, NULL);\n  switch (wtype) {\n    case kBothWspecifier:\n      impl_ = new TableWriterBothImpl<Holder>();\n      break;\n    case kArchiveWspecifier:\n      impl_ = new TableWriterArchiveImpl<Holder>();\n      break;\n    case kScriptWspecifier:\n      impl_ = new TableWriterScriptImpl<Holder>();\n      break;\n    case kNoWspecifier: default:\n      KALDI_WARN << \"ClassifyWspecifier: invalid wspecifier \" << wspecifier;\n      return false;\n  }\n  if (impl_->Open(wspecifier)) {\n    return true;\n  } else {  // The class will have printed a more specific warning.\n    delete impl_;\n    impl_ = NULL;\n    return false;\n  }\n}\n\ntemplate<class Holder>\nvoid TableWriter<Holder>::Write(const std::string &key,\n                                const T &value) const {\n  CheckImpl();\n  if (!impl_->Write(key, value))\n    KALDI_ERR << \"Error in TableWriter::Write\";\n  // More specific warning will have\n  // been printed in the Write function.\n}\n\ntemplate<class Holder>\nvoid TableWriter<Holder>::Flush() {\n  CheckImpl();\n  impl_->Flush();\n}\n\ntemplate<class Holder>\nbool TableWriter<Holder>::Close() {\n  CheckImpl();\n  bool ans = impl_->Close();\n  delete impl_;  // We don't keep around non-open impl_ objects\n                 // [c.f. definition of IsOpen()]\n  impl_ = NULL;\n  return ans;\n}\n\ntemplate<class Holder>\nTableWriter<Holder>::~TableWriter() {\n  if (IsOpen() && !Close()) {\n    KALDI_ERR << \"Error closing TableWriter [in destructor].\";\n  }\n}\n\n\n// Types of RandomAccessTableReader:\n// In principle, we would like to have four types of RandomAccessTableReader:\n//  the 4 combinations  [scp, archive], [seekable, not-seekable],\n// where if something is seekable we only store a file offset.  However,\n// it seems sufficient for now to only implement two of these, in both\n// cases assuming it's not seekable so we never store file offsets and always\n// store either the scp line or the data in the archive.  The reasons are:\n// (1)\n// For scp files, storing the actual entry is not that much more expensive\n// than storing the file offsets (since the entries are just filenames), and\n// avoids a lot of fseek operations that might be expensive.\n// (2)\n// For archive files, there is no real reason, if you have the archive file\n// on disk somewhere, why you wouldn't access it via its associated scp.\n// [i.e. write it as ark, scp].  The main reason to read archives directly\n// is if they are part of a pipe, and in this case it's not seekable, so\n// we implement only this case.\n//\n// Note that we will rarely in practice have to keep in memory everything in\n// the archive, as long as things are only read once from the archive (the\n// \"o, \" or \"once\" option) and as long as we keep our keys in sorted order;\n// to take advantage of this we need the \"s, \" (sorted) option, so we would\n// read archives as e.g. \"s, o, ark:-\" (this is the rspecifier we would use if\n// it was the standard input and these conditions held).\n\ntemplate<class Holder> class RandomAccessTableReaderImplBase {\n public:\n  typedef typename Holder::T T;\n\n  virtual bool Open(const std::string &rspecifier) = 0;\n\n  virtual bool HasKey(const std::string &key) = 0;\n\n  virtual const T &Value(const std::string &key) = 0;\n\n  virtual bool Close() = 0;\n\n  virtual ~RandomAccessTableReaderImplBase() {}\n};\n\n\n// Implementation of RandomAccessTableReader for a script file; for simplicity\n// we just read it in all in one go, as it's unlikely someone would generate\n// this from a pipe.  In principle we could read it on-demand as for the\n// archives, but this would probably be overkill.\n\n// Note: the code for this class is similar to TableWriterScriptImpl:\n// try to keep them in sync.\ntemplate<class Holder>\nclass RandomAccessTableReaderScriptImpl:\n      public RandomAccessTableReaderImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  RandomAccessTableReaderScriptImpl(): last_found_(0), state_(kUninitialized) {}\n\n  virtual bool Open(const std::string &rspecifier) {\n    switch (state_) {\n      case kNotHaveObject: case kHaveObject: case kHaveRange:\n        KALDI_ERR << \" Opening already open RandomAccessTableReader:\"\n                     \" call Close first.\";\n      case kUninitialized: case kNotReadScript:\n        break;\n    }\n    rspecifier_ = rspecifier;\n    RspecifierType rs = ClassifyRspecifier(rspecifier,\n                                           &script_rxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(rs == kScriptRspecifier);  // or wrongly called.\n    KALDI_ASSERT(script_.empty());  // no way it could be nonempty at this point\n\n    if (!ReadScriptFile(script_rxfilename_,\n                        true,  // print any warnings\n                        &script_)) {  // error reading script file or invalid\n                                      // format\n      state_ = kNotReadScript;\n      return false;  // no need to print further warnings.  user gets the error.\n    }\n\n    rspecifier_ = rspecifier;\n    // If opts_.sorted, the user has asserted that the keys are already sorted.\n    // Although we could easily sort them, we want to let the user know of this\n    // mistake.  This same mistake could have serious effects if used with an\n    // archive rather than a script.\n    if (!opts_.sorted)\n      std::sort(script_.begin(), script_.end());\n    for (size_t i = 0; i + 1 < script_.size(); i++) {\n      if (script_[i].first.compare(script_[i+1].first) >= 0) {\n        // script[i] not < script[i+1] in lexical order...\n        bool same = (script_[i].first == script_[i+1].first);\n        KALDI_WARN << \"Script file \" << PrintableRxfilename(script_rxfilename_)\n                   << (same ? \" contains duplicate key: \" :\n                       \" is not sorted (remove s, option or add ns, option):\"\n                       \" key is \") << script_[i].first;\n        state_ = kNotReadScript;\n        return false;\n      }\n    }\n    state_ = kNotHaveObject;\n    key_ = \"\";  // make sure we don't have a key set\n    return true;\n  }\n\n  virtual bool IsOpen() const {\n    return  (state_ == kNotHaveObject || state_ == kHaveObject ||\n             state_ == kHaveRange);\n  }\n\n  virtual bool Close() {\n    if (!IsOpen())\n      KALDI_ERR << \"Close() called on RandomAccessTableReader that was not\"\n                   \" open.\";\n    holder_.Clear();\n    range_holder_.Clear();\n    state_ = kUninitialized;\n    last_found_ = 0;\n    script_.clear();\n    key_ = \"\";\n    range_ = \"\";\n    data_rxfilename_ = \"\";\n    // This cannot fail because any errors of a \"global\" nature would have been\n    // detected when we did Open().  With archives it's different.\n    return true;\n  }\n\n  virtual bool HasKey(const std::string &key) {\n    bool preload = opts_.permissive;\n    // In permissive mode, we have to check that we can read\n    // the scp entry before we assert that the key is there.\n    return HasKeyInternal(key, preload);\n  }\n\n\n  // Write returns true on success, false on failure, but\n  // some errors may not be detected till we call Close().\n  virtual const T&  Value(const std::string &key) {\n    if (!HasKeyInternal(key, true)) // true == preload.\n      KALDI_ERR << \"Could not get item for key \" << key\n                << \", rspecifier is \" << rspecifier_ << \" [to ignore this, \"\n                 << \"add the p, (permissive) option to the rspecifier.\";\n    KALDI_ASSERT(key_ == key);\n    if (state_ == kHaveObject) {\n      return holder_.Value();\n    } else {\n      KALDI_ASSERT(state_ == kHaveRange);\n      return range_holder_.Value();\n    }\n  }\n\n  virtual ~RandomAccessTableReaderScriptImpl() { }\n\n private:\n\n  // HasKeyInternal when called with preload == false just tells us whether the\n  // key is in the scp.  With preload == true, which happens when the ,p\n  // (permissive) option is given in the rspecifier (or when called from\n  // Value()), it will also check that we can preload the object from disk\n  // (loading from the rxfilename in the scp), and only return true if we can.\n  // This function is called both from HasKey and from Value().\n  virtual bool HasKeyInternal(const std::string &key, bool preload) {\n    switch (state_) {\n      case kUninitialized: case kNotReadScript:\n        KALDI_ERR << \"HasKey called on RandomAccessTableReader object that is\"\n                     \" not open.\";\n      case kHaveObject:\n        if (key == key_ && range_.empty())\n          return true;\n        break;\n      case kHaveRange:\n        if (key == key_)\n          return true;\n        break;\n      case kNotHaveObject: default: break;\n    }\n    KALDI_ASSERT(IsToken(key));\n    size_t key_pos = 0;\n    if (!LookupKey(key, &key_pos)) {\n      return false;\n    } else {\n      if (!preload) {\n        return true;  // we have the key, and were not asked to verify that the\n                      // object could be read.\n      } else {  // preload specified, so we have to attempt to pre-load the\n                // object before returning.\n        std::string data_rxfilename, range; // We will split\n        // script_[key_pos].second (e.g. \"1.ark:100[0:2]\" into data_rxfilename\n        // (e.g. \"1.ark:100\") and range (if any), e.g. \"0:2\".\n        if (script_[key_pos].second[script_[key_pos].second.size()-1] == ']') {\n          if(!ExtractRangeSpecifier(script_[key_pos].second,\n                                    &data_rxfilename,\n                                    &range)) {\n            KALDI_ERR << \"TableReader: failed to parse range in '\"\n                      << script_[key_pos].second << \"'\";\n          }\n        } else {\n          data_rxfilename = script_[key_pos].second;\n        }\n        if (state_ == kHaveRange) {\n          if (data_rxfilename_ == data_rxfilename && range_ == range) {\n            // the odd situation where two keys had the same rxfilename and range:\n            // just change the key and keep the object.\n            key_ = key;\n            return true;\n          } else {\n            range_holder_.Clear();\n            state_ = kHaveObject;\n          }\n        }\n        // OK, at this point the state will be kHaveObject or kNotHaveObject.\n        if (state_ == kHaveObject) {\n          if (data_rxfilename_ != data_rxfilename) {\n            // clear out the object.\n            state_ = kNotHaveObject;\n            holder_.Clear();\n          }\n        }\n        // At this point we can safely switch to the new key, data_rxfilename\n        // and range, and we know that if we have an object, it will already be\n        // the correct one.  The state is now kHaveObject or kNotHaveObject.\n        key_ = key;\n        data_rxfilename_ = data_rxfilename;\n        range_ = range;\n        if (state_ == kNotHaveObject) {\n          // we need to read the object.\n          if (!input_.Open(data_rxfilename)) {\n            KALDI_WARN << \"Error opening stream \"\n                       << PrintableRxfilename(data_rxfilename);\n            return false;\n          } else {\n            if (holder_.Read(input_.Stream())) {\n              state_ = kHaveObject;\n            } else {\n              KALDI_WARN << \"Error reading object from \"\n                  \"stream \" << PrintableRxfilename(data_rxfilename);\n              return false;\n            }\n          }\n        }\n        // At this point the state is kHaveObject.\n        if (range.empty())\n          return true;  // we're done: no range was requested.\n        if (range_holder_.ExtractRange(holder_, range)) {\n          state_ = kHaveRange;\n          return true;\n        } else {\n          KALDI_WARN  << \"Failed to load object from \"\n                      << PrintableRxfilename(data_rxfilename)\n                      << \"[\" << range << \"]\";\n          // leave state at kHaveObject.\n          return false;\n        }\n      }\n    }\n  }\n\n  // This function attempts to look up the key \"key\" in the sorted array\n  // script_.  If it was found it returns true and puts the array offset into\n  // 'script_offset'; otherwise it returns false.\n  bool LookupKey(const std::string &key, size_t *script_offset) {\n    // First, an optimization: if we're going consecutively, this will\n    // make the lookup very fast.  Since we may call HasKey and then\n    // Value(), which both may look up the key, we test if either the\n    // current or next position are correct.\n    if (last_found_ < script_.size() && script_[last_found_].first == key) {\n      *script_offset = last_found_;\n      return true;\n    }\n    last_found_++;\n    if (last_found_ < script_.size() && script_[last_found_].first == key) {\n      *script_offset = last_found_;\n      return true;\n    }\n    std::pair<std::string, std::string> pr(key, \"\");  // Important that \"\"\n    // compares less than or equal to any string, so lower_bound points to the\n    // element that has the same key.\n    typedef typename std::vector<std::pair<std::string, std::string> >\n                     ::const_iterator IterType;\n    IterType iter = std::lower_bound(script_.begin(), script_.end(), pr);\n    if (iter != script_.end() && iter->first == key) {\n      last_found_ = *script_offset = iter - script_.begin();\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n\n  Input input_;  // Use the same input_ object for reading each file, in case\n                 // the scp specifies offsets in an archive so we can keep the\n                 // same file open.\n  RspecifierOptions opts_;\n  std::string rspecifier_;  // rspecifier used to open this object; used in\n                            // debug messages\n  std::string script_rxfilename_;  // rxfilename of script file that we read.\n\n  std::string key_;  // The current key of the object that we have, but see the\n                     // notes regarding states_ for more explanation of the\n                     // semantics.\n\n  Holder holder_;\n  Holder range_holder_; // Holds the partial object corresponding to the object\n                        // range specifier 'range_'. this is only used when\n                        // 'range_' is specified.\n  std::string range_; // range within which we read the object from holder_.\n                      // If key_ is set, always correspond to the key.\n  std::string data_rxfilename_;  // the rxfilename corresponding to key_,\n                                 // always set when key_ is set.\n\n\n  // the script_ variable contains pairs of (key, filename), sorted using\n  // std::sort.  This can be used with binary_search to look up filenames for\n  // writing.  If this becomes inefficient we can use std::unordered_map (but I\n  // suspect this wouldn't be significantly faster & would use more memory).\n  // If memory becomes a problem here, the user should probably be passing\n  // only the relevant part of the scp file rather than expecting us to get too\n  // clever in the code.\n  std::vector<std::pair<std::string, std::string> > script_;\n  size_t last_found_;  // This is for an optimization used in FindFilename.\n\n  enum {\n    //                   (*) is script_ set up?\n    //                          (*) does holder_ contain an object?\n    //                               (*) does range_holder_ contain and object?\n    //\n    //\n    kUninitialized,  //    no    no    no\n    kNotReadScript,  //    no    no    no\n    kNotHaveObject,  //    yes   no    no\n    kHaveObject,     //    yes   yes   no\n    kHaveRange,      //    yes   yes   yes\n\n    // If we are in a state where holder_ contains an object, it always contains\n    // the object from 'key_', and the corresponding rxfilename is always\n    // 'data_rxfilename_'.  If range_holder_ contains an object, it always\n    // corresponds to the range 'range_' of the object in 'holder_', and always\n    // corresponds to the current key.\n  } state_;\n};\n\n\n\n\n// This is the base-class (with some implemented functions) for the\n// implementations of RandomAccessTableReader when it's an archive.  This\n// base-class handles opening the files, storing the state of the reading\n// process, and loading objects.  This is the only case in which we have\n// an intermediate class in the hierarchy between the virtual ImplBase\n// class and the actual Impl classes.\n// The child classes vary in the assumptions regarding sorting, etc.\n\ntemplate<class Holder>\nclass RandomAccessTableReaderArchiveImplBase:\n      public RandomAccessTableReaderImplBase<Holder> {\n public:\n  typedef typename Holder::T T;\n\n  RandomAccessTableReaderArchiveImplBase(): holder_(NULL),\n                                            state_(kUninitialized) { }\n\n  virtual bool Open(const std::string &rspecifier) {\n    if (state_ != kUninitialized) {\n      if (!this->Close())  // call Close() yourself to suppress this exception.\n        KALDI_ERR << \"Error closing previous input.\";\n    }\n    rspecifier_ = rspecifier;\n    RspecifierType rs = ClassifyRspecifier(rspecifier, &archive_rxfilename_,\n                                           &opts_);\n    KALDI_ASSERT(rs == kArchiveRspecifier);\n\n    // NULL means don't expect binary-mode header\n    bool ans;\n    if (Holder::IsReadInBinary())\n      ans = input_.Open(archive_rxfilename_, NULL);\n    else\n      ans = input_.OpenTextMode(archive_rxfilename_);\n    if (!ans) {  // header.\n      KALDI_WARN << \"Failed to open stream \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kUninitialized;  // Failure on Open\n      return false;  // User should print the error message.\n    } else {\n      state_ = kNoObject;\n    }\n    return true;\n  }\n\n  // ReadNextObject() requires that the state be kNoObject,\n  // and it will try read the next object.  If it succeeds,\n  // it sets the state to kHaveObject, and\n  // cur_key_ and holder_ have the key and value.  If it fails,\n  // it sets the state to kError or kEof.\n  void ReadNextObject() {\n    if (state_ != kNoObject)\n      KALDI_ERR << \"ReadNextObject() called from wrong state.\";\n    // Code error somewhere in this class or a child class.\n    std::istream &is = input_.Stream();\n    is.clear();  // Clear any fail bits that may have been set... just in case\n    // this happened in the Read function.\n    is >> cur_key_;  // This eats up any leading whitespace and gets the string.\n    if (is.eof()) {\n      state_ = kEof;\n      return;\n    }\n    if (is.fail()) {  // This shouldn't really happen, barring file-system\n                      // errors.\n      KALDI_WARN << \"Error reading archive: rspecifier is \" << rspecifier_;\n      state_ = kError;\n      return;\n    }\n    int c;\n    if ((c = is.peek()) != ' ' && c != '\\t' && c != '\\n') {  // We expect a\n      // space ' ' after the key.\n      // We also allow tab, just so we can read archives generated by scripts\n      // that may not be fully aware of how this format works.\n      KALDI_WARN << \"Invalid archive file format: expected space after key \"\n                 <<cur_key_\n                 <<\", got character \"\n                 << CharToString(static_cast<char>(is.peek()))\n                 << \", reading archive \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kError;\n      return;\n    }\n    if (c != '\\n') is.get();  // Consume the space or tab.\n    holder_ = new Holder;\n    if (holder_->Read(is)) {\n      state_ = kHaveObject;\n      return;\n    } else {\n      KALDI_WARN << \"Object read failed, reading archive \"\n                 << PrintableRxfilename(archive_rxfilename_);\n      state_ = kError;\n      delete holder_;\n      holder_ = NULL;\n      return;\n    }\n  }\n\n  virtual bool IsOpen() const {\n    switch (state_) {\n      case kEof: case kError: case kHaveObject: case kNoObject: return true;\n      case kUninitialized: return false;\n      default: KALDI_ERR << \"IsOpen() called on invalid object.\";\n        return false;\n    }\n  }\n\n  // Called by the child-class virutal Close() functions; does the\n  // shared parts of the cleanup.\n  bool CloseInternal() {\n    if (!this->IsOpen())\n      KALDI_ERR << \"Close() called on TableReader twice or otherwise wrongly.\";\n    if (input_.IsOpen())\n      input_.Close();\n    if (state_ == kHaveObject) {\n      KALDI_ASSERT(holder_ != NULL);\n      delete holder_;\n      holder_ = NULL;\n    } else {\n      KALDI_ASSERT(holder_ == NULL);\n    }\n    bool ans = (state_ != kError);\n    state_ = kUninitialized;\n    if (!ans && opts_.permissive) {\n      KALDI_WARN << \"Error state detected closing reader.  \"\n                 << \"Ignoring it because you specified permissive mode.\";\n      return true;\n    }\n    return ans;\n  }\n\n  ~RandomAccessTableReaderArchiveImplBase() {\n    // The child class has the responsibility to call CloseInternal().\n    KALDI_ASSERT(state_ == kUninitialized && holder_ == NULL);\n  }\n private:\n  Input input_;       // Input object for the archive\n protected:\n  // The variables below are accessed by child classes.\n\n  std::string cur_key_;   // current key (if state == kHaveObject).\n  Holder *holder_;    // Holds the object we just read (if state == kHaveObject)\n\n  std::string rspecifier_;\n  std::string archive_rxfilename_;\n  RspecifierOptions opts_;\n\n  enum {  //  [The state of the reading process]        [does holder_ [is input_\n    //                                                      have object]   open]\n    kUninitialized,  // Uninitialized or closed                   no         no\n    kNoObject,      // Do not have object in holder_              no         yes\n    kHaveObject,    // Have object in holder_                     yes        yes\n    kEof,           // End of file                                no         yes\n    kError,         // Some kind of error-state in the reading.   no         yes\n  } state_;\n};\n\n\n// RandomAccessTableReaderDSortedArchiveImpl (DSorted for \"doubly sorted\") is\n// the implementation for random-access reading of archives when both the\n// archive, and the calling code, are in sorted order (i.e. we ask for the keys\n// in sorted order).  This is when the s and cs options are both given.  It only\n// ever has to keep one object in memory.  It inherits from\n// RandomAccessTableReaderArchiveImplBase which implements the common parts of\n// RandomAccessTableReader that are used when it's an archive we're reading from\n\ntemplate<class Holder>\nclass RandomAccessTableReaderDSortedArchiveImpl:\n      public RandomAccessTableReaderArchiveImplBase<Holder> {\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kUninitialized;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kHaveObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kNoObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kEof;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kError;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::state_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::opts_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::cur_key_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::holder_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::rspecifier_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::archive_rxfilename_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::ReadNextObject;\n public:\n  typedef typename Holder::T T;\n\n  RandomAccessTableReaderDSortedArchiveImpl() { }\n\n  virtual bool Close() {\n    // We don't have anything additional to clean up, so just\n    // call generic base-class one.\n    return this->CloseInternal();\n  }\n\n  virtual bool HasKey(const std::string &key) {\n    return FindKeyInternal(key);\n  }\n  virtual const T & Value(const std::string &key) {\n    if (!FindKeyInternal(key)) {\n      KALDI_ERR << \"Value() called but no such key \" << key\n                << \" in archive \" << PrintableRxfilename(archive_rxfilename_);\n    }\n    KALDI_ASSERT(this->state_ == kHaveObject && key == this->cur_key_\n                 && holder_ != NULL);\n    return this->holder_->Value();\n  }\n\n  virtual ~RandomAccessTableReaderDSortedArchiveImpl() {\n    if (this->IsOpen())\n      if (!Close())  // more specific warning will already have been printed.\n        // we are in some kind of error state & user did not find out by\n        // calling Close().\n        KALDI_ERR << \"Error closing RandomAccessTableReader: rspecifier is \"\n                  << rspecifier_;\n  }\n private:\n  // FindKeyInternal tries to find the key by calling \"ReadNextObject()\"\n  // as many times as necessary till we get to it.  It is called from\n  // both FindKey and Value().\n  bool FindKeyInternal(const std::string &key) {\n    // First check that the user is calling us right: should be\n    // in sorted order.  If not, error.\n    if (!last_requested_key_.empty()) {\n      if (key.compare(last_requested_key_) < 0) {  // key < last_requested_key_\n        KALDI_ERR << \"You provided the \\\"cs\\\" option \"\n                  << \"but are not calling with keys in sorted order: \"\n                  << key << \" < \" << last_requested_key_ << \": rspecifier is \"\n                  << rspecifier_;\n      }\n    }\n    // last_requested_key_ is just for debugging of order of calling.\n    last_requested_key_ = key;\n\n    if (state_ == kNoObject)\n      ReadNextObject();  // This can only happen\n      // once, the first time someone calls HasKey() or Value().  We don't\n      // do it in the initializer to stop the program hanging too soon,\n      // if reading from a pipe.\n\n    if (state_ == kEof || state_ == kError) return false;\n\n    if (state_ == kUninitialized)\n      KALDI_ERR << \"Trying to access a RandomAccessTableReader object that is\"\n                   \" not open.\";\n\n    std::string last_key_;  // To check that\n    // the archive we're reading is in sorted order.\n    while (1) {\n      KALDI_ASSERT(state_ == kHaveObject);\n      int compare = key.compare(cur_key_);\n      if (compare == 0) {  // key == key_\n        return true;  // we got it..\n      } else if (compare < 0) {  // key < cur_key_, so we already read past the\n        // place where we want to be.  This implies that we will never find it\n        // [due to the sorting etc., this means it just isn't in the archive].\n        return false;\n      } else {  // compare > 0, key > cur_key_.  We need to read further ahead.\n        last_key_ = cur_key_;\n        // read next object.. we have to set state to kNoObject first.\n        KALDI_ASSERT(holder_ != NULL);\n        delete holder_;\n        holder_ = NULL;\n        state_ = kNoObject;\n        ReadNextObject();\n        if (state_ != kHaveObject)\n          return false;  // eof or read error.\n        if (cur_key_.compare(last_key_) <= 0) {\n          KALDI_ERR << \"You provided the \\\"s\\\" option \"\n                    << \" (sorted order), but keys are out of order or\"\n                       \" duplicated: \"\n                    << last_key_ << \" is followed by \" << cur_key_\n                    << \": rspecifier is \" << rspecifier_;\n        }\n      }\n    }\n  }\n\n  /// Last string provided to HasKey() or Value();\n  std::string last_requested_key_;\n};\n\n// RandomAccessTableReaderSortedArchiveImpl is for random-access reading of\n// archives when the user specified the sorted (s) option but not the\n// called-sorted (cs) options.\ntemplate<class Holder>\nclass RandomAccessTableReaderSortedArchiveImpl:\n      public RandomAccessTableReaderArchiveImplBase<Holder> {\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kUninitialized;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kHaveObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kNoObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kEof;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kError;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::state_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::opts_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::cur_key_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::holder_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::rspecifier_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::archive_rxfilename_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::ReadNextObject;\n\n public:\n  typedef typename Holder::T T;\n\n  RandomAccessTableReaderSortedArchiveImpl():\n      last_found_index_(static_cast<size_t>(-1)),\n      pending_delete_(static_cast<size_t>(-1)) { }\n\n  virtual bool Close() {\n    for (size_t i = 0; i < seen_pairs_.size(); i++)\n      delete seen_pairs_[i].second;\n    seen_pairs_.clear();\n\n    pending_delete_ = static_cast<size_t>(-1);\n    last_found_index_ = static_cast<size_t>(-1);\n\n    return this->CloseInternal();\n  }\n  virtual bool HasKey(const std::string &key) {\n    HandlePendingDelete();\n    size_t index;\n    bool ans = FindKeyInternal(key, &index);\n    if (ans && opts_.once && seen_pairs_[index].second == NULL) {\n      // Just do a check RE the once option. \"&&opts_.once\" is for\n      // efficiency since this can only happen in that case.\n      KALDI_ERR << \"Error: HasKey called after Value() already called for \"\n                << \" that key, and once (o) option specified: rspecifier is \"\n                << rspecifier_;\n    }\n    return ans;\n  }\n  virtual const T & Value(const std::string &key) {\n    HandlePendingDelete();\n    size_t index;\n    if (!FindKeyInternal(key, &index)) {\n      KALDI_ERR << \"Value() called but no such key \" << key\n                << \" in archive \" << PrintableRxfilename(archive_rxfilename_);\n    }\n    if (seen_pairs_[index].second == NULL) {  // can happen if opts.once_\n      KALDI_ERR << \"Error: Value() called more than once for key \"\n                << key << \" and once (o) option specified: rspecifier is \"\n                << rspecifier_;\n    }\n    if (opts_.once)\n      pending_delete_ = index;  // mark this index to be deleted on next call.\n    return seen_pairs_[index].second->Value();\n  }\n  virtual ~RandomAccessTableReaderSortedArchiveImpl() {\n    if (this->IsOpen())\n      if (!Close())  // more specific warning will already have been printed.\n        // we are in some kind of error state & user did not find out by\n        // calling Close().\n        KALDI_ERR << \"Error closing RandomAccessTableReader: rspecifier is \"\n                  << rspecifier_;\n  }\n private:\n  void HandlePendingDelete() {\n    const size_t npos = static_cast<size_t>(-1);\n    if (pending_delete_ != npos) {\n      KALDI_ASSERT(pending_delete_ < seen_pairs_.size());\n      KALDI_ASSERT(seen_pairs_[pending_delete_].second != NULL);\n      delete seen_pairs_[pending_delete_].second;\n      seen_pairs_[pending_delete_].second = NULL;\n      pending_delete_ = npos;\n    }\n  }\n\n  // FindKeyInternal tries to find the key in the array \"seen_pairs_\".\n  // If it is not already there, it reads ahead as far as necessary\n  // to determine whether we have the key or not.  On success it returns\n  // true and puts the index into the array seen_pairs_, into \"index\";\n  // on failure it returns false.\n  // It will leave the state as either kNoObject, kEof or kError.\n  // FindKeyInternal does not do any checking about whether you are asking\n  // about a key that has been already given (with the \"once\" option).\n  // That is the user's responsibility.\n\n  bool FindKeyInternal(const std::string &key, size_t *index) {\n    // First, an optimization in case the previous call was for the\n    // same key, and we found it.\n    if (last_found_index_ < seen_pairs_.size()\n       && seen_pairs_[last_found_index_].first == key) {\n      *index = last_found_index_;\n      return true;\n    }\n\n    if (state_ == kUninitialized)\n      KALDI_ERR << \"Trying to access a RandomAccessTableReader object that is\"\n                   \" not open.\";\n\n    // Step one is to see whether we have to read ahead for the object..\n    // Note, the possible states right now are kNoObject, kEof or kError.\n    // We are never in the state kHaveObject except just after calling\n    // ReadNextObject().\n    bool looped = false;\n    while (state_ == kNoObject &&\n          (seen_pairs_.empty() || key.compare(seen_pairs_.back().first) > 0)) {\n      looped = true;\n      // Read this as:\n      //  while ( the stream is potentially good for reading &&\n      //        ([got no keys] || key > most_recent_key) ) { ...\n      //     Try to read a new object.\n      // Note that the keys in seen_pairs_ are ordered from least to greatest.\n      ReadNextObject();\n      if (state_ == kHaveObject) {  // Successfully read object.\n        if (!seen_pairs_.empty() &&  // This is just a check.\n           cur_key_.compare(seen_pairs_.back().first) <= 0) {\n          // read the expression above as: !( cur_key_ > previous_key).\n          // it means we are not in sorted order [the user specified that we\n          // are, or we would not be using this implementation].\n          KALDI_ERR << \"You provided the sorted (s) option but keys in archive \"\n                    << PrintableRxfilename(archive_rxfilename_) << \" are not \"\n                    << \"in sorted order: \" << seen_pairs_.back().first\n                    << \" is followed by \" << cur_key_;\n        }\n        KALDI_ASSERT(holder_ != NULL);\n        seen_pairs_.push_back(std::make_pair(cur_key_, holder_));\n        holder_ = NULL;\n        state_ = kNoObject;\n      }\n    }\n    if (looped) {  // We only need to check the last element of the seen_pairs_\n      // array, since we would not have read more after getting \"key\".\n      if (!seen_pairs_.empty() && seen_pairs_.back().first == key) {\n        last_found_index_ = *index = seen_pairs_.size() - 1;\n        return true;\n      } else {\n        return false;\n      }\n    }\n    // Now we have do an actual binary search in the seen_pairs_ array.\n    std::pair<std::string, Holder*> pr(key, static_cast<Holder*>(NULL));\n    typename std::vector<std::pair<std::string, Holder*> >::iterator\n        iter = std::lower_bound(seen_pairs_.begin(), seen_pairs_.end(),\n                                pr, PairCompare());\n    if (iter != seen_pairs_.end() &&\n       key == iter->first) {\n      last_found_index_ = *index = (iter - seen_pairs_.begin());\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  // These are the pairs of (key, object) we have read.  We keep all the keys we\n  // have read but the actual objects (if they are stored with pointers inside\n  // the Holder object) may be deallocated if once == true, and the Holder\n  // pointer set to NULL.\n  std::vector<std::pair<std::string, Holder*> > seen_pairs_;\n  size_t last_found_index_;  // An optimization s.t. if FindKeyInternal called\n  // twice with same key (as it often will), it doesn't have to do the key\n  // search twice.\n  size_t pending_delete_;  // If opts_.once == true, this is the index of\n  // element of seen_pairs_ that is pending deletion.\n  struct PairCompare {\n    // PairCompare is the Less-than operator for the pairs of(key, Holder).\n    // compares the keys.\n    inline bool operator() (const std::pair<std::string, Holder*> &pr1,\n                            const std::pair<std::string, Holder*> &pr2) {\n      return  (pr1.first.compare(pr2.first) < 0);\n    }\n  };\n};\n\n\n\n// RandomAccessTableReaderUnsortedArchiveImpl is for random-access reading of\n// archives when the user does not specify the sorted (s) option (in this case\n// the called-sorted, or \"cs\" option, is ignored).  This is the least efficient\n// of the random access archive readers, in general, but it can be as efficient\n// as the others, in speed, memory and latency, if the \"once\" option is\n// specified and it happens that the keys of the archive are the same as the\n// keys the code is called with (to HasKey() and Value()), and in the same\n// order.  However, if you ask it for a key that's not present it will have to\n// read the archive till the end and store it all in memory.\n\ntemplate<class Holder>\nclass RandomAccessTableReaderUnsortedArchiveImpl:\n      public RandomAccessTableReaderArchiveImplBase<Holder> {\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kUninitialized;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kHaveObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kNoObject;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kEof;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::kError;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::state_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::opts_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::cur_key_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::holder_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::rspecifier_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::archive_rxfilename_;\n  using RandomAccessTableReaderArchiveImplBase<Holder>::ReadNextObject;\n\n  typedef typename Holder::T T;\n\n public:\n  RandomAccessTableReaderUnsortedArchiveImpl(): to_delete_iter_(map_.end()),\n                                                to_delete_iter_valid_(false) {\n    map_.max_load_factor(0.5);  // make it quite empty -> quite efficient.\n    // default seems to be 1.\n  }\n\n  virtual bool Close() {\n    for (typename MapType::iterator iter = map_.begin();\n        iter != map_.end();\n        ++iter) {\n      delete iter->second;\n    }\n    map_.clear();\n    first_deleted_string_ = \"\";\n    to_delete_iter_valid_ = false;\n    return this->CloseInternal();\n  }\n\n  virtual bool HasKey(const std::string &key) {\n    HandlePendingDelete();\n    return FindKeyInternal(key, NULL);\n  }\n  virtual const T & Value(const std::string &key) {\n    HandlePendingDelete();\n    const T *ans_ptr = NULL;\n    if (!FindKeyInternal(key, &ans_ptr))\n      KALDI_ERR << \"Value() called but no such key \" << key\n                << \" in archive \" << PrintableRxfilename(archive_rxfilename_);\n    return *ans_ptr;\n  }\n  virtual ~RandomAccessTableReaderUnsortedArchiveImpl() {\n    if (this->IsOpen())\n      if (!Close())  // more specific warning will already have been printed.\n        // we are in some kind of error state & user did not find out by\n        // calling Close().\n        KALDI_ERR << \"Error closing RandomAccessTableReader: rspecifier is \"\n                  << rspecifier_;\n  }\n private:\n  void HandlePendingDelete() {\n    if (to_delete_iter_valid_) {\n      to_delete_iter_valid_ = false;\n      delete to_delete_iter_->second;  // Delete Holder object.\n      if (first_deleted_string_.length() == 0)\n        first_deleted_string_ = to_delete_iter_->first;\n      map_.erase(to_delete_iter_);  // delete that element.\n    }\n  }\n\n  // FindKeyInternal tries to find the key in the map \"map_\"\n  // If it is not already there, it reads ahead either until it finds the\n  // key, or until end of file.  If called with value_ptr == NULL,\n  // it assumes it's called from HasKey() and just returns true or false\n  // and doesn't otherwise have side effects.  If called with value_ptr !=\n  // NULL, it assumes it's called from Value().  Thus, it will crash\n  // if it cannot find the key.  If it can find it it puts its address in\n  // *value_ptr, and if opts_once == true it will mark that element of the\n  // map to be deleted.\n\n  bool FindKeyInternal(const std::string &key, const T **value_ptr = NULL) {\n    typename MapType::iterator iter = map_.find(key);\n    if (iter != map_.end()) {  // Found in the map...\n      if (value_ptr == NULL) {  // called from HasKey\n        return true;  // this is all we have to do.\n      } else {\n        *value_ptr = &(iter->second->Value());\n        if (opts_.once) {  // value won't be needed again, so mark\n          // for deletion.\n          to_delete_iter_ = iter;  // pending delete.\n          KALDI_ASSERT(!to_delete_iter_valid_);\n          to_delete_iter_valid_ = true;\n        }\n        return true;\n      }\n    }\n    while (state_ == kNoObject) {\n      ReadNextObject();\n      if (state_ == kHaveObject) {  // Successfully read object.\n        state_ = kNoObject;  // we are about to transfer ownership\n        // of the object in holder_ to map_.\n        // Insert it into map_.\n        std::pair<typename MapType::iterator, bool> pr =\n            map_.insert(typename MapType::value_type(cur_key_, holder_));\n\n        if (!pr.second) {  // Was not inserted-- previous element w/ same key\n          delete holder_;  // map was not changed, no ownership transferred.\n          holder_ = NULL;\n          KALDI_ERR << \"Error in RandomAccessTableReader: duplicate key \"\n                    << cur_key_ << \" in archive \" << archive_rxfilename_;\n        }\n        holder_ = NULL;  // ownership transferred to map_.\n        if (cur_key_ == key) {  // the one we wanted..\n          if (value_ptr == NULL) {  // called from HasKey\n            return true;\n          } else {  // called from Value()\n            *value_ptr = &(pr.first->second->Value());  // this gives us the\n            // Value() from the Holder in the map.\n            if (opts_.once) {  // mark for deletion, as won't be needed again.\n              to_delete_iter_ = pr.first;\n              KALDI_ASSERT(!to_delete_iter_valid_);\n              to_delete_iter_valid_ = true;\n            }\n            return true;\n          }\n        }\n      }\n    }\n    if (opts_.once && key == first_deleted_string_) {\n      KALDI_ERR << \"You specified the once (o) option but \"\n                << \"you are calling using key \" << key\n                << \" more than once: rspecifier is \" << rspecifier_;\n    }\n    return false;  // We read the entire archive (or got to error state) and\n    // didn't find it.\n  }\n\n  typedef unordered_map<std::string, Holder*, StringHasher>  MapType;\n  MapType map_;\n\n  typename MapType::iterator to_delete_iter_;\n  bool to_delete_iter_valid_;\n\n  std::string first_deleted_string_;  // keep the first string we deleted\n  // from map_ (if opts_.once == true).  It's for an inexact spot-check that the\n  // \"once\" option isn't being used incorrectly.\n};\n\n\n\n\n\ntemplate<class Holder>\nRandomAccessTableReader<Holder>::RandomAccessTableReader(const\n                                                       std::string &rspecifier):\n    impl_(NULL) {\n  if (rspecifier != \"\" && !Open(rspecifier))\n    KALDI_ERR << \"Error opening RandomAccessTableReader object \"\n        \" (rspecifier is: \" << rspecifier << \")\";\n}\n\ntemplate<class Holder>\nbool RandomAccessTableReader<Holder>::Open(const std::string &rspecifier) {\n  if (IsOpen())\n    KALDI_ERR << \"Already open.\";\n  RspecifierOptions opts;\n  RspecifierType rs = ClassifyRspecifier(rspecifier, NULL, &opts);\n  switch (rs) {\n    case kScriptRspecifier:\n      impl_ = new RandomAccessTableReaderScriptImpl<Holder>();\n      break;\n    case kArchiveRspecifier:\n      if (opts.sorted) {\n        if (opts.called_sorted)  // \"doubly\" sorted case.\n          impl_ = new RandomAccessTableReaderDSortedArchiveImpl<Holder>();\n        else\n          impl_ = new RandomAccessTableReaderSortedArchiveImpl<Holder>();\n      } else {\n        impl_ = new RandomAccessTableReaderUnsortedArchiveImpl<Holder>();\n      }\n      break;\n    case kNoRspecifier: default:\n      KALDI_WARN << \"Invalid rspecifier: \"\n                 << rspecifier;\n      return false;\n  }\n  if (!impl_->Open(rspecifier)) {\n    // A warning will already have been printed.\n    delete impl_;\n    impl_ = NULL;\n    return false;\n  }\n  return true;\n}\n\ntemplate<class Holder>\nbool RandomAccessTableReader<Holder>::HasKey(const std::string &key) {\n  CheckImpl();\n  if (!IsToken(key))\n    KALDI_ERR << \"Invalid key \\\"\" << key << '\"';\n  return impl_->HasKey(key);\n}\n\n\ntemplate<class Holder>\nconst typename RandomAccessTableReader<Holder>::T&\nRandomAccessTableReader<Holder>::Value(const std::string &key) {\n  CheckImpl();\n  return impl_->Value(key);\n}\n\ntemplate<class Holder>\nbool RandomAccessTableReader<Holder>::Close() {\n  CheckImpl();\n  bool ans =impl_->Close();\n  delete impl_;\n  impl_ = NULL;\n  return ans;\n}\n\ntemplate<class Holder>\nRandomAccessTableReader<Holder>::~RandomAccessTableReader() {\n  if (IsOpen() && !Close())  // call Close() yourself to stop this being thrown.\n    KALDI_ERR << \"failure detected in destructor.\";\n}\n\ntemplate<class Holder>\nvoid SequentialTableReader<Holder>::CheckImpl() const {\n  if (!impl_) {\n    KALDI_ERR << \"Trying to use empty SequentialTableReader (perhaps you \"\n              << \"passed the empty string as an argument to a program?)\";\n  }\n}\n\ntemplate<class Holder>\nvoid RandomAccessTableReader<Holder>::CheckImpl() const {\n  if (!impl_) {\n    KALDI_ERR << \"Trying to use empty RandomAccessTableReader (perhaps you \"\n              << \"passed the empty string as an argument to a program?)\";\n  }\n}\n\ntemplate<class Holder>\nvoid TableWriter<Holder>::CheckImpl() const {\n  if (!impl_) {\n    KALDI_ERR << \"Trying to use empty TableWriter (perhaps you \"\n              << \"passed the empty string as an argument to a program?)\";\n  }\n}\n\ntemplate<class Holder>\nRandomAccessTableReaderMapped<Holder>::RandomAccessTableReaderMapped(\n    const std::string &table_rxfilename,\n    const std::string &utt2spk_rxfilename):\n    reader_(table_rxfilename), token_reader_(table_rxfilename.empty() ? \"\" :\n                                             utt2spk_rxfilename),\n    utt2spk_rxfilename_(utt2spk_rxfilename) { }\n\ntemplate<class Holder>\nbool RandomAccessTableReaderMapped<Holder>::Open(\n    const std::string &table_rxfilename,\n    const std::string &utt2spk_rxfilename) {\n  if (reader_.IsOpen()) reader_.Close();\n  if (token_reader_.IsOpen()) token_reader_.Close();\n  KALDI_ASSERT(!table_rxfilename.empty());\n  if (!reader_.Open(table_rxfilename)) return false;  // will have printed\n  // warning internally, probably.\n  if (!utt2spk_rxfilename.empty()) {\n    if (!token_reader_.Open(utt2spk_rxfilename)) {\n      reader_.Close();\n      return false;\n    }\n  }\n  return true;\n}\n\n\ntemplate<class Holder>\nbool RandomAccessTableReaderMapped<Holder>::HasKey(const std::string &utt) {\n  // We don't check IsOpen, we let the call go through to the member variable\n  // (reader_), which will crash with a more informative error message than\n  // we can give here, as we don't any longer know the rxfilename.\n  if (token_reader_.IsOpen()) {  // We need to map the key from utt to spk.\n    if (!token_reader_.HasKey(utt))\n      KALDI_ERR << \"Attempting to read key \" << utt << \", which is not present \"\n                << \"in utt2spk map or similar map being read from \"\n                << PrintableRxfilename(utt2spk_rxfilename_);\n    const std::string &spk = token_reader_.Value(utt);\n    return reader_.HasKey(spk);\n  } else {\n    return reader_.HasKey(utt);\n  }\n}\n\ntemplate<class Holder>\nconst typename Holder::T& RandomAccessTableReaderMapped<Holder>::Value(\n    const std::string &utt) {\n  if (token_reader_.IsOpen()) {  // We need to map the key from utt to spk.\n    if (!token_reader_.HasKey(utt))\n      KALDI_ERR << \"Attempting to read key \" << utt << \", which is not present \"\n                << \"in utt2spk map or similar map being read from \"\n                << PrintableRxfilename(utt2spk_rxfilename_);\n    const std::string &spk = token_reader_.Value(utt);\n    return reader_.Value(spk);\n  } else {\n    return reader_.Value(utt);\n  }\n}\n\n\n\n/// @}\n\n}  // end namespace kaldi\n\n\n\n#endif  // KALDI_UTIL_KALDI_TABLE_INL_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-table.cc",
    "content": "// util/kaldi-table.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"util/kaldi-table.h\"\n#include \"util/text-utils.h\"\n\nnamespace kaldi {\n\n\nbool ReadScriptFile(const std::string &rxfilename,\n                    bool warn,\n                    std::vector<std::pair<std::string, std::string> >\n                    *script_out) {\n  bool is_binary;\n  Input input;\n\n  if (!input.Open(rxfilename, &is_binary)) {\n    if (warn) KALDI_WARN << \"Error opening script file: \" <<\n                 PrintableRxfilename(rxfilename);\n    return false;\n  }\n  if (is_binary) {\n    if (warn) KALDI_WARN << \"Error: script file appears to be binary: \" <<\n                 PrintableRxfilename(rxfilename);\n    return false;\n  }\n\n  bool ans = ReadScriptFile(input.Stream(), warn, script_out);\n  if (warn && !ans)\n    KALDI_WARN << \"[script file was: \" << PrintableRxfilename(rxfilename) <<\n                  \"]\";\n  return ans;\n}\n\nbool ReadScriptFile(std::istream &is,\n                    bool warn,\n                    std::vector<std::pair<std::string, std::string> >\n                    *script_out) {\n  KALDI_ASSERT(script_out != NULL);\n  std::string line;\n  int line_number = 0;\n  while (getline(is, line)) {\n    line_number++;\n    const char *c = line.c_str();\n    if (*c == '\\0') {\n      if (warn)\n        KALDI_WARN << \"Empty \" << line_number << \"'th line in script file\";\n      return false;  // Empty line so invalid scp file format..\n    }\n\n    std::string key, rest;\n    SplitStringOnFirstSpace(line, &key, &rest);\n\n    if (key.empty() || rest.empty()) {\n      if (warn)\n        KALDI_WARN << \"Invalid \" << line_number << \"'th line in script file\"\n                          <<\":\\\"\" << line << '\"';\n      return false;\n    }\n    script_out->resize(script_out->size()+1);\n    script_out->back().first = key;\n    script_out->back().second = rest;\n  }\n  return true;\n}\n\nbool WriteScriptFile(std::ostream &os,\n                     const std::vector<std::pair<std::string, std::string> >\n                     &script) {\n  if (!os.good()) {\n    KALDI_WARN << \"WriteScriptFile: attempting to write to invalid stream.\";\n    return false;\n  }\n  std::vector<std::pair<std::string, std::string> >::const_iterator iter;\n  for (iter = script.begin(); iter != script.end(); ++iter) {\n    if (!IsToken(iter->first)) {\n      KALDI_WARN << \"WriteScriptFile: using invalid token \\\"\" << iter->first <<\n                    '\"';\n      return false;\n    }\n    if (iter->second.find('\\n') != std::string::npos ||\n       (iter->second.length() != 0 &&\n        (isspace(iter->second[0]) ||\n         isspace(iter->second[iter->second.length()-1])))) {\n      // second part contains newline or leading or trailing space.\n      KALDI_WARN << \"WriteScriptFile: attempting to write invalid line \\\"\" <<\n                    iter->second << '\"';\n      return false;\n    }\n    os << iter->first << ' ' << iter->second << '\\n';\n  }\n  if (!os.good()) {\n    KALDI_WARN << \"WriteScriptFile: stream in error state.\";\n    return false;\n  }\n  return true;\n}\n\nbool WriteScriptFile(const std::string &wxfilename,\n                     const std::vector<std::pair<std::string, std::string> >\n                     &script) {\n  Output output;\n  if (!output.Open(wxfilename, false, false)) {  // false, false means not\n    // binary, no binary-mode header.\n    KALDI_ERR << \"Error opening output stream for script file: \"\n              << PrintableWxfilename(wxfilename);\n    return false;\n  }\n  if (!WriteScriptFile(output.Stream(), script)) {\n    KALDI_ERR << \"Error writing script file to stream \"\n              << PrintableWxfilename(wxfilename);\n    return false;\n  }\n  return true;\n}\n\n\n\nWspecifierType ClassifyWspecifier(const std::string &wspecifier,\n                                  std::string *archive_wxfilename,\n                                  std::string *script_wxfilename,\n                                  WspecifierOptions *opts) {\n  //  Examples:\n  //  ark,t:wxfilename -> kArchiveWspecifier\n  //  ark,b:wxfilename -> kArchiveWspecifier\n  //  scp,t:rxfilename -> kScriptWspecifier\n  //  scp,t:rxfilename -> kScriptWspecifier\n  //  ark,scp,t:filename, wxfilename -> kBothWspecifier\n  //  ark,scp:filename, wxfilename ->  kBothWspecifier\n  //  Note we can include the flush option (f) or no-flush (nf)\n  // anywhere: e.g.\n  //  ark,scp,f:filename, wxfilename ->  kBothWspecifier\n  // or:\n  //  scp,t,nf:rxfilename -> kScriptWspecifier\n\n  if (archive_wxfilename) archive_wxfilename->clear();\n  if (script_wxfilename) script_wxfilename->clear();\n\n  size_t pos = wspecifier.find(':');\n  if (pos == std::string::npos) return kNoWspecifier;\n  if (isspace(*(wspecifier.rbegin()))) return kNoWspecifier;  // Trailing space\n  // disallowed.\n\n  std::string before_colon(wspecifier, 0, pos), after_colon(wspecifier, pos+1);\n\n  std::vector<std::string> split_first_part;  // Split part before ':' on ', '.\n  SplitStringToVector(before_colon, \", \", false, &split_first_part);  // false==\n  // don't omit empty strings between commas.\n\n  WspecifierType ws = kNoWspecifier;\n\n  if (opts != NULL)\n    *opts = WspecifierOptions();  // Make sure all the defaults are as in the\n                                  // default constructor of the options class.\n\n  for (size_t i = 0; i < split_first_part.size(); i++) {\n    const std::string &str = split_first_part[i];  // e.g. \"b\", \"t\", \"f\", \"ark\",\n    // \"scp\".\n    const char *c = str.c_str();\n    if (!strcmp(c, \"b\")) {\n      if (opts) opts->binary = true;\n    } else if (!strcmp(c, \"f\")) {\n      if (opts) opts->flush = true;\n    } else if (!strcmp(c, \"nf\")) {\n      if (opts) opts->flush = false;\n    } else if (!strcmp(c, \"t\")) {\n      if (opts) opts->binary = false;\n    } else if (!strcmp(c, \"p\")) {\n      if (opts) opts->permissive = true;\n    } else if (!strcmp(c, \"ark\")) {\n      if (ws == kNoWspecifier) ws = kArchiveWspecifier;\n      else\n        return kNoWspecifier;  // We do not allow \"scp, ark\", only \"ark,\n      // scp\".\n    } else if (!strcmp(c, \"scp\")) {\n      if (ws == kNoWspecifier) ws = kScriptWspecifier;\n      else if (ws == kArchiveWspecifier) ws = kBothWspecifier;\n      else\n        return kNoWspecifier;  // repeated \"scp\" option: invalid.\n    } else {\n      return kNoWspecifier;  // Could not interpret this option.\n    }\n  }\n\n  switch (ws) {\n    case kArchiveWspecifier:\n      if (archive_wxfilename)\n        *archive_wxfilename = after_colon;\n      break;\n    case kScriptWspecifier:\n      if (script_wxfilename)\n        *script_wxfilename = after_colon;\n      break;\n    case kBothWspecifier:\n      pos = after_colon.find(',');  // first comma.\n      if (pos == std::string::npos) return kNoWspecifier;\n      if (archive_wxfilename)\n        *archive_wxfilename = std::string(after_colon, 0, pos);\n      if (script_wxfilename)\n        *script_wxfilename = std::string(after_colon, pos+1);\n      break;\n    case kNoWspecifier: default: break;\n  }\n  return ws;\n}\n\n\n\nRspecifierType ClassifyRspecifier(const std::string &rspecifier,\n                                  std::string *rxfilename,\n                                  RspecifierOptions *opts) {\n  // Examples\n  // ark:rxfilename  ->  kArchiveRspecifier\n  // scp:rxfilename  -> kScriptRspecifier\n  //\n  // We also allow the meaningless prefixes b, and t,\n  // plus the options o (once), no (not-once),\n  // s (sorted) and ns (not-sorted), p (permissive)\n  // and np (not-permissive).\n  // so the following would be valid:\n  //\n  // f, o, b, np, ark:rxfilename  ->  kArchiveRspecifier\n  //\n  // Examples:\n  //\n  // b, ark:rxfilename  ->  kArchiveRspecifier\n  // t, ark:rxfilename  ->  kArchiveRspecifier\n  // b, scp:rxfilename  -> kScriptRspecifier\n  // t, no, s, scp:rxfilename  -> kScriptRspecifier\n  // t, ns, scp:rxfilename  -> kScriptRspecifier\n\n  // Improperly formed Rspecifiers will be classified as kNoRspecifier.\n\n  if (rxfilename) rxfilename->clear();\n\n  if (opts != NULL)\n    *opts = RspecifierOptions();  // Make sure all the defaults are as in the\n                                  // default constructor of the options class.\n\n  size_t pos = rspecifier.find(':');\n  if (pos == std::string::npos) return kNoRspecifier;\n\n  if (isspace(*(rspecifier.rbegin()))) return kNoRspecifier;  // Trailing space\n  // disallowed.\n\n  std::string before_colon(rspecifier, 0, pos),\n      after_colon(rspecifier, pos+1);\n\n  std::vector<std::string> split_first_part;  // Split part before ':' on ', '.\n  SplitStringToVector(before_colon, \", \", false, &split_first_part);  // false==\n  // don't omit empty strings between commas.\n\n  RspecifierType rs = kNoRspecifier;\n\n  for (size_t i = 0; i < split_first_part.size(); i++) {\n    const std::string &str = split_first_part[i];  // e.g. \"b\", \"t\", \"f\", \"ark\",\n    // \"scp\".\n    const char *c = str.c_str();\n    if (!strcmp(c, \"b\"));  // Ignore this option.  It's so we can use the same\n    // specifiers for rspecifiers and wspecifiers.\n    else if (!strcmp(c, \"t\"));  // Ignore this option too.\n    else if (!strcmp(c, \"o\")) {\n      if (opts) opts->once = true;\n    } else if (!strcmp(c, \"no\")) {\n      if (opts) opts->once = false;\n    } else if (!strcmp(c, \"p\")) {\n      if (opts) opts->permissive = true;\n    } else if (!strcmp(c, \"np\")) {\n      if (opts) opts->permissive = false;\n    } else if (!strcmp(c, \"s\")) {\n      if (opts) opts->sorted = true;\n    } else if (!strcmp(c, \"ns\")) {\n      if (opts) opts->sorted = false;\n    } else if (!strcmp(c, \"cs\")) {\n      if (opts) opts->called_sorted = true;\n    } else if (!strcmp(c, \"ncs\")) {\n      if (opts) opts->called_sorted = false;\n    } else if (!strcmp(c, \"bg\")) {\n      if (opts) opts->background = true;\n    } else if (!strcmp(c, \"ark\")) {\n      if (rs == kNoRspecifier) rs = kArchiveRspecifier;\n      else\n        return kNoRspecifier;  // Repeated or combined ark and scp options\n      // invalid.\n    } else if (!strcmp(c, \"scp\")) {\n      if (rs == kNoRspecifier) rs = kScriptRspecifier;\n      else\n        return kNoRspecifier;  // Repeated or combined ark and scp options\n      // invalid.\n    } else {\n      return kNoRspecifier;  // Could not interpret this option.\n    }\n  }\n  if ((rs == kArchiveRspecifier || rs == kScriptRspecifier)\n     && rxfilename != NULL)\n    *rxfilename = after_colon;\n  return rs;\n}\n\n\n\n\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-table.h",
    "content": "// util/kaldi-table.h\n\n// Copyright 2009-2011    Microsoft Corporation\n//                2013    Johns Hopkins University (author: Daniel Povey)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_KALDI_TABLE_H_\n#define KALDI_UTIL_KALDI_TABLE_H_\n\n#include <string>\n#include <vector>\n#include <utility>\n\n#include \"base/kaldi-common.h\"\n#include \"util/kaldi-holder.h\"\n\nnamespace kaldi {\n\n// Forward declarations\ntemplate<class Holder> class RandomAccessTableReaderImplBase;\ntemplate<class Holder>  class SequentialTableReaderImplBase;\ntemplate<class Holder>  class TableWriterImplBase;\n\n/// \\addtogroup table_group\n/// @{\n\n// This header defines the Table classes (RandomAccessTableReader,\n// SequentialTableReader and TableWriter) and explains what the Holder classes,\n// which the Table class requires as a template argument, are like.  It also\n// explains the \"rspecifier\" and \"wspecifier\" concepts (these are strings that\n// explain how to read/write objects via archives or scp files.  A table is\n// conceptually a collection of objects of a particular type T indexed by keys\n// of type std::string (these Keys additionally have an order within\n// each table).\n// The Table classes are templated on a type (call it Holder) such that\n// Holder::T is a typedef equal to T.\n\n// see kaldi-holder.h for detail on the Holder classes.\n\ntypedef std::vector<std::string> KeyList;\n\n// Documentation for \"wspecifier\"\n// \"wspecifier\" describes how we write a set of objects indexed by keys.\n// The basic, unadorned wspecifiers are as follows:\n//\n//  ark:wxfilename\n//  scp:rxfilename\n//  ark,scp:filename,wxfilename\n//  ark,scp:filename,wxfilename\n//\n//\n//  We also allow the following modifiers:\n//  t means text mode.\n//  b means binary mode.\n//  f means flush the stream after writing each entry.\n//   (nf means don't flush, and the default is not to flush).\n//  p means permissive mode, when writing to an \"scp\" file only: will ignore\n//     missing scp entries, i.e. won't write anything for those files but will\n//     return success status).\n//\n//  So the following are valid wspecifiers:\n//  ark,b,f:foo\n//  \"ark,b,b:| gzip -c > foo\"\n//  \"ark,scp,t,nf:foo.ark,|gzip -c > foo.scp.gz\"\n//  ark,b:-\n//\n//  The meanings of rxfilename and wxfilename are as described in\n//  kaldi-io.h (they are filenames but include pipes, stdin/stdout\n//  and so on; filename is a regular filename.\n//\n\n//  The ark:wxfilename type of wspecifier instructs the class to\n//  write directly to an archive.  For small objects (e.g. lists of ints),\n//  the text archive format will generally be human readable with one line\n//  per entry in the archive.\n//\n//  The type \"scp:xfilename\" refers to an scp file which should\n//  already exist on disk, and tells us where to write the data for\n//  each key (usually an actual file); each line of the scp file\n//  would be:\n//   key xfilename\n//\n//  The type ark,scp:filename,wxfilename means\n//  we write both an archive and an scp file that specifies offsets into the\n//  archive, with lines like:\n//    key filename:12407\n//  where the number is the byte offset into the file.\n//  In this case we restrict the archive-filename to be an actual filename,\n//  as we can't see a situation where an extended filename would make sense\n//  for this (we can't fseek() in pipes).\n\nenum WspecifierType  {\n  kNoWspecifier,\n  kArchiveWspecifier,\n  kScriptWspecifier,\n  kBothWspecifier\n};\n\nstruct WspecifierOptions {\n  bool binary;\n  bool flush;\n  bool permissive;  // will ignore absent scp entries.\n  WspecifierOptions(): binary(true), flush(false), permissive(false) { }\n};\n\n// ClassifyWspecifier returns the type of the wspecifier string,\n// and (if pointers are non-NULL) outputs the extra information\n// about the options, and the script and archive\n// filenames.\nWspecifierType ClassifyWspecifier(const std::string &wspecifier,\n                                  std::string *archive_wxfilename,\n                                  std::string *script_wxfilename,\n                                  WspecifierOptions *opts);\n\n// ReadScriptFile reads an .scp file in its entirety, and appends it\n// (in order as it was in the scp file) in script_out_, which contains\n// pairs of (key, xfilename).  The .scp\n// file format is: on each line, key xfilename\n// where xfilename means rxfilename or wxfilename, and may contain internal\n// spaces (we trim away any leading or trailing space).  The key is space-free.\n// ReadScriptFile returns true if the format was valid (empty files\n// are valid).\n// If 'print_warnings', it will print out warning messages that explain what\n// kind of error there was.\nbool ReadScriptFile(const std::string &rxfilename,\n                    bool print_warnings,\n                    std::vector<std::pair<std::string, std::string> >\n                    *script_out);\n\n// This version of ReadScriptFile works from an istream.\nbool ReadScriptFile(std::istream &is,\n                    bool print_warnings,\n                    std::vector<std::pair<std::string, std::string> >\n                    *script_out);\n\n// Writes, for each entry in script, the first element, then ' ', then the\n// second element then '\\n'.  Checks that the keys (first elements of pairs) are\n// valid tokens (nonempty, no whitespace), and the values (second elements of\n// pairs) are newline-free and contain no leading or trailing space.  Returns\n// true on success.\nbool WriteScriptFile(const std::string &wxfilename,\n                     const std::vector<std::pair<std::string, std::string> >\n                     &script);\n\n// This version writes to an ostream.\nbool WriteScriptFile(std::ostream &os,\n                     const std::vector<std::pair<std::string, std::string> >\n                     &script);\n\n// Documentation for \"rspecifier\"\n// \"rspecifier\" describes how we read a set of objects indexed by keys.\n// The possibilities are:\n//\n// ark:rxfilename\n// scp:rxfilename\n//\n// We also allow various modifiers:\n//   o   means the program will only ask for each key once, which enables\n//       the reader to discard already-asked-for values.\n//   s   means the keys are sorted on input (means we don't have to read till\n//       eof if someone asked for a key that wasn't there).\n//   cs  means that it is called in sorted order (we are generally asserting\n//       this based on knowledge of how the program works).\n//   p   means \"permissive\", and causes it to skip over keys whose corresponding\n//       scp-file entries cannot be read. [and to ignore errors in archives and\n//       script files, and just consider the \"good\" entries].\n//       We allow the negation of the options above, as in no, ns, np,\n//       but these aren't currently very useful (just equivalent to omitting the\n//       corresponding option).\n//       [any of the above options can be prefixed by n to negate them, e.g. no,\n//       ns, ncs, np; but these aren't currently useful as you could just omit\n//       the option].\n//   bg means \"background\".  It currently has no effect for random-access readers,\n//       but for sequential readers it will cause it to \"read ahead\" to the next\n//       value, in a background thread.  Recommended when reading larger objects\n//       such as neural-net training examples, especially when you want to\n//       maximize GPU usage.\n//\n//   b   is ignored [for scripting convenience]\n//   t   is ignored [for scripting convenience]\n//\n//\n//  So for instance the following would be a valid rspecifier:\n//\n//   \"o, s, p, ark:gunzip -c foo.gz|\"\n\nstruct  RspecifierOptions {\n  // These options only make a difference for the RandomAccessTableReader class.\n  bool once;   // we assert that the program will only ask for each key once.\n  bool sorted;  // we assert that the keys are sorted.\n  bool called_sorted;  // we assert that the (HasKey(), Value() functions will\n  // also be called in sorted order.  [this implies \"once\" but not vice versa].\n  bool permissive;  // If \"permissive\", when reading from scp files it treats\n  // scp files that can't be read as if the corresponding key were not there.\n  // For archive files it will suppress errors getting thrown if the archive\n  // is corrupted and can't be read to the end.\n  bool background;  // For sequential readers, if the background option (\"bg\")\n                    // is provided, it will read ahead to the next object in a\n                    // background thread.\n  RspecifierOptions(): once(false), sorted(false),\n                       called_sorted(false), permissive(false),\n                       background(false) { }\n};\n\nenum RspecifierType  {\n  kNoRspecifier,\n  kArchiveRspecifier,\n  kScriptRspecifier\n};\n\nRspecifierType ClassifyRspecifier(const std::string &rspecifier,\n                                  std::string *rxfilename,\n                                  RspecifierOptions *opts);\n\n\n/// Allows random access to a collection\n/// of objects in an archive or script file; see \\ref io_sec_tables.\ntemplate<class Holder>\nclass RandomAccessTableReader {\n public:\n  typedef typename Holder::T T;\n\n  RandomAccessTableReader(): impl_(NULL) { }\n\n  // This constructor is equivalent to default constructor + \"open\", but\n  // throws on error.\n  explicit RandomAccessTableReader(const std::string &rspecifier);\n\n  // Opens the table.\n  bool Open(const std::string &rspecifier);\n\n  // Returns true if table is open.\n  bool IsOpen() const { return (impl_ != NULL); }\n\n  // Close() will close the table [throws if it was not open],\n  // and returns true on success (false if we were reading an\n  // archive and we discovered an error in the archive).\n  bool Close();\n\n  // Says if it has this key.\n  // If you are using the \"permissive\" (p) read option,\n  // it will return false for keys whose corresponding entry\n  // in the scp file cannot be read.\n\n  bool HasKey(const std::string &key);\n\n  // Value() may throw if you are reading an scp file, you\n  // do not have the \"permissive\" (p) option, and an entry\n  // in the scp file cannot be read.  Typically you won't\n  // want to catch this error.\n  const T &Value(const std::string &key);\n\n  ~RandomAccessTableReader();\n\n  // Allow copy-constructor only for non-opened readers (needed for inclusion in\n  // stl vector)\n  RandomAccessTableReader(const RandomAccessTableReader<Holder>\n                          &other):\n      impl_(NULL) { KALDI_ASSERT(other.impl_ == NULL); }\n private:\n  // Disallow assignment.\n  RandomAccessTableReader &operator=(const RandomAccessTableReader<Holder>&);\n  void CheckImpl() const;  // Checks that impl_ is non-NULL; prints an error\n                           // message and dies (with KALDI_ERR) if NULL.\n  RandomAccessTableReaderImplBase<Holder> *impl_;\n};\n\n\n\n/// A templated class for reading objects sequentially from an archive or script\n/// file; see \\ref io_sec_tables.\ntemplate<class Holder>\nclass SequentialTableReader {\n public:\n  typedef typename Holder::T T;\n\n  SequentialTableReader(): impl_(NULL) { }\n\n  // This constructor equivalent to default constructor + \"open\", but\n  // throws on error.\n  explicit SequentialTableReader(const std::string &rspecifier);\n\n  // Opens the table.  Returns exit status; but does throw if previously open\n  // stream was in error state.  You can call Close to prevent this; anyway,\n  // calling Open more than once is not usually needed.\n  bool Open(const std::string &rspecifier);\n\n  // Returns true if we're done.  It will also return true if there's some kind\n  // of error and we can't read any more; in this case, you can detect the\n  // error by calling Close and checking the return status; otherwise\n  // the destructor will throw.\n  inline bool Done();\n\n  // Only valid to call Key() if Done() returned false.\n  inline std::string Key();\n\n  // FreeCurrent() is provided as an optimization to save memory, for large\n  // objects.  It instructs the class to deallocate the current value. The\n  // reference Value() will be invalidated by this.\n  void FreeCurrent();\n\n  // Return reference to the current value.  It's only valid to call this if\n  // Done() returned false.  The reference is valid till next call to this\n  // object.  It will throw if you are reading an scp file, did not specify the\n  // \"permissive\" (p) option and the file cannot be read.  [The permissive\n  // option makes it behave as if that key does not even exist, if the\n  // corresponding file cannot be read.]  You probably wouldn't want to catch\n  // this exception; the user can just specify the p option in the rspecifier.\n  // We make this non-const to enable things like shallow swap on the held\n  // object in situations where this would avoid making a redundant copy.\n  T &Value();\n\n  // Next goes to the next key.  It will not throw; any error will\n  // result in Done() returning true, and then the destructor will\n  // throw unless you call Close().\n  void Next();\n\n  // Returns true if table is open for reading (does not imply\n  // stream is in good state).\n  bool IsOpen() const;\n\n  // Close() will return false (failure) if Done() became true\n  // because of an error/ condition rather than because we are\n  // really done [e.g. because of an error or early termination\n  // in the archive].\n  // If there is an error and you don't call Close(), the destructor\n  // will fail.\n  // Close()\n  bool Close();\n\n  // The destructor may throw.  This is the desired behaviour, as it's the way\n  // we signal the error to the user (to detect it, call Close().  The issue is\n  // that otherwise the user has no way to tell whether Done() returned true\n  // because we reached the end of the archive or script, or because there was\n  // an error that prevented further reading.\n  ~SequentialTableReader();\n\n  // Allow copy-constructor only for non-opened readers (needed for inclusion in\n  // stl vector)\n  SequentialTableReader(const SequentialTableReader<Holder> &other):\n      impl_(NULL) { KALDI_ASSERT(other.impl_ == NULL); }\n private:\n  // Disallow assignment.\n  SequentialTableReader &operator = (const SequentialTableReader<Holder>&);\n  void CheckImpl() const;  // Checks that impl_ is non-NULL; prints an error\n                           // message and dies (with KALDI_ERR) if NULL.\n  SequentialTableReaderImplBase<Holder> *impl_;\n};\n\n\n/// A templated class for writing objects to an\n/// archive or script file; see \\ref io_sec_tables.\ntemplate<class Holder>\nclass TableWriter {\n public:\n  typedef typename Holder::T T;\n\n  TableWriter(): impl_(NULL) { }\n\n  // This constructor equivalent to default constructor\n  // + \"open\", but throws on error.  See docs for\n  // wspecifier above.\n  explicit TableWriter(const std::string &wspecifier);\n\n  // Opens the table.  See docs for wspecifier above.\n  // If it returns true, it is open.\n  bool Open(const std::string &wspecifier);\n\n  // Returns true if open for writing.\n  bool IsOpen() const;\n\n  // Write the object. Throws KaldiFatalError on error via the KALDI_ERR macro.\n  inline void Write(const std::string &key, const T &value) const;\n\n\n  // Flush will flush any archive; it does not return error status\n  // or throw, any errors will be reported on the next Write or Close.\n  // Useful if we may be writing to a command in a pipe and want\n  // to ensure good CPU utilization.\n  void Flush();\n\n  // Close() is not necessary to call, as the destructor\n  // closes it; it's mainly useful if you want to handle\n  // error states because the destructor will throw on\n  // error if you do not call Close().\n  bool Close();\n\n  ~TableWriter();\n\n  // Allow copy-constructor only for non-opened writers (needed for inclusion in\n  // stl vector)\n  TableWriter(const TableWriter &other): impl_(NULL) {\n    KALDI_ASSERT(other.impl_ == NULL);\n  }\n private:\n  TableWriter &operator = (const TableWriter&);  // Disallow assignment.\n\n  void CheckImpl() const;  // Checks that impl_ is non-NULL; prints an error\n                           // message and dies (with KALDI_ERR) if NULL.\n  TableWriterImplBase<Holder> *impl_;\n};\n\n\n/// This class is for when you are reading something in random access, but\n/// it may actually be stored per-speaker (or something similar) but the\n/// keys you're using are per utterance.  So you also provide an \"rxfilename\"\n/// for a file containing lines like\n/// utt1 spk1\n/// utt2 spk1\n/// utt3 spk1\n/// and so on.  Note: this is optional; if it is an empty string, we just won't\n/// do the mapping.  Also, \"table_rxfilename\" may be the empty string (as for\n/// a regular table), in which case the table just won't be opened.\n/// We provide only the most frequently used of the functions of\n/// RandomAccessTableReader.\n\ntemplate<class Holder>\nclass RandomAccessTableReaderMapped {\n public:\n  typedef typename Holder::T T;\n  /// Note: \"utt2spk_rxfilename\" will in the normal case be an rxfilename\n  /// for an utterance to speaker map, but this code is general; it accepts\n  /// a generic map.\n  RandomAccessTableReaderMapped(const std::string &table_rxfilename,\n                                const std::string &utt2spk_rxfilename);\n\n  RandomAccessTableReaderMapped() {}\n\n  /// Note: when calling Open, utt2spk_rxfilename may be empty.\n  bool Open(const std::string &table_rxfilename,\n            const std::string &utt2spk_rxfilename);\n\n  bool HasKey(const std::string &key);\n  const T &Value(const std::string &key);\n  inline bool IsOpen() const { return reader_.IsOpen(); }\n  inline bool Close() { return reader_.Close(); }\n\n\n\n  // The default copy-constructor will do what we want: it will crash for\n  // already-opened readers, by calling the member-variable copy-constructors.\n private:\n  // Disallow assignment.\n  RandomAccessTableReaderMapped &operator =\n    (const RandomAccessTableReaderMapped<Holder>&);\n  RandomAccessTableReader<Holder> reader_;\n  RandomAccessTableReader<TokenHolder> token_reader_;\n  std::string utt2spk_rxfilename_;  // Used only in diagnostic messages.\n};\n\n\n/// @} end \"addtogroup table_group\"\n}  // end namespace kaldi\n\n#include \"util/kaldi-table-inl.h\"\n\n#endif  // KALDI_UTIL_KALDI_TABLE_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-thread.cc",
    "content": "// util/kaldi-thread.cc\n\n// Copyright 2012  Johns Hopkins University (Author: Daniel Povey)\n//                 Frantisek Skala\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"base/kaldi-common.h\"\n#include \"util/kaldi-thread.h\"\n\nnamespace kaldi {\nint32 g_num_threads = 8;  // Initialize this global variable.\n\nMultiThreadable::~MultiThreadable() {\n  // default implementation does nothing\n}\n\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/kaldi-thread.h",
    "content": "// util/kaldi-thread.h\n\n// Copyright 2012  Johns Hopkins University (Author: Daniel Povey)\n//                 Frantisek Skala\n//           2017  University of Southern California (Author: Dogan Can)\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_THREAD_KALDI_THREAD_H_\n#define KALDI_THREAD_KALDI_THREAD_H_ 1\n\n#include <thread>\n#include \"util/options-itf.h\"\n#include \"util/kaldi-semaphore.h\"\n\n// This header provides convenient mechanisms for parallelization.\n//\n// The class MultiThreader, and the function RunMultiThreaded provide a\n// mechanism to run a specified number of jobs in parellel and wait for them\n// all to finish. They accept objects of some class C that derives from the\n// base class MultiThreadable. C needs to define the operator () that takes\n// no arguments. See ExampleClass below.\n//\n// The class TaskSequencer addresses a different problem typically encountered\n// in Kaldi command-line programs that process a sequence of items. The items\n// to be processed are coming in. They are all of different sizes, e.g.\n// utterances with different numbers of frames. We would like them to be\n// processed in parallel to make good use of the threads available but they\n// must be output in the same order they came in. Here, we again accept objects\n// of some class C with an operator () that takes no arguments. C may also have\n// a destructor with side effects (typically some kind of output).\n// TaskSequencer is responsible for running the jobs in parallel. It has a\n// function Run() that will accept a new object of class C; this will block\n// until a thread is free, at which time it will spawn a thread that starts\n// running the operator () of the object. When threads are finished running,\n// the objects will be deleted. TaskSequencer guarantees that the destructors\n// will be called sequentially (not in parallel) and in the same order the\n// objects were given to the Run() function, so that it is safe for the\n// destructor to have side effects such as outputting data.\n// Note: the destructor of TaskSequencer will wait for any remaining jobs that\n// are still running and will call the destructors.\n\n\nnamespace kaldi {\n\nextern int32 g_num_threads;  // Maximum number of threads (for programs that\n// use threads, which is not many of them, e.g. the SGMM update program does.\n// This is 8 by default.  You can change this on the command line, where\n// used, with --num-threads.  Programs that think they will use threads\n// should register it with their ParseOptions, as something like:\n// po.Register(\"num-threads\", &g_num_threads, \"Number of threads to use.\");\n\nclass MultiThreadable {\n  // To create a function object that does part of the job, inherit from this\n  // class, implement a copy constructor calling the default copy constructor\n  // of this base class (so that thread_id_ and num_threads_ are copied to new\n  // instances), and finally implement the operator() that does part of the job\n  // based on thread_id_ and num_threads_ variables.\n  // Note: example implementations are in util/kaldi-thread-test.cc\n public:\n  virtual void operator() () = 0;\n  // Does the main function of the class\n  //  Subclasses have to redefine this\n  virtual ~MultiThreadable();\n  // Optional destructor.  Note: the destructor of the object passed by the user\n  // will also be called, so watch out.\n\n public:\n  // Do not redeclare thread_id_ and num_threads_ in derived classes.\n  int32 thread_id_;  // 0 <= thread_id_ < num_threads_\n  int32 num_threads_;\n\n private:\n  // Have additional member variables as needed.\n};\n\n\nclass ExampleClass: public MultiThreadable {\n public:\n  ExampleClass(int32 *foo); // Typically there will be an initializer that\n  // takes arguments.\n\n  ExampleClass(const ExampleClass &other); // A copy constructor is also needed;\n  // some example classes use the default version of this.\n\n  void operator() () {\n    // Does the main function of the class.  This\n    // function will typically want to look at the values of the\n    // member variables thread_id_ and num_threads_, inherited\n    // from MultiThreadable.\n  }\n  ~ExampleClass() {\n    // Optional destructor.  Sometimes useful things happen here,\n    // for example summing up of certain quantities.  See code\n    // that uses RunMultiThreaded for examples.\n  }\n private:\n  // Have additional member variables as needed.\n};\n\n\ntemplate<class C>\nclass MultiThreader {\n public:\n  MultiThreader(int32 num_threads, const C &c_in) :\n    threads_(std::max<int32>(1, num_threads)),\n    cvec_(std::max<int32>(1, num_threads), c_in) {\n    if (num_threads == 0) {\n      // This is a special case with num_threads == 0, which behaves like with\n      // num_threads == 1 but without creating extra threads.  This can be\n      // useful in GPU computations where threads cannot be used.\n      cvec_[0].thread_id_ = 0;\n      cvec_[0].num_threads_ = 1;\n      (cvec_[0])();\n    } else {\n      for (int32 i = 0; i < threads_.size(); i++) {\n        cvec_[i].thread_id_ = i;\n        cvec_[i].num_threads_ = threads_.size();\n        threads_[i] = std::thread(std::ref(cvec_[i]));\n      }\n    }\n  }\n  ~MultiThreader() {\n    for (size_t i = 0; i < threads_.size(); i++)\n      if (threads_[i].joinable())\n        threads_[i].join();\n  }\n private:\n  std::vector<std::thread> threads_;\n  std::vector<C> cvec_;\n};\n\n/// Here, class C should inherit from MultiThreadable.  Note: if you want to\n/// control the number of threads yourself, or need to do something in the main\n/// thread of the program while the objects exist, just initialize the\n/// MultiThreader<C> object yourself.\ntemplate<class C> void RunMultiThreaded(const C &c_in) {\n  MultiThreader<C> m(g_num_threads, c_in);\n}\n\n\nstruct TaskSequencerConfig {\n  int32 num_threads;\n  int32 num_threads_total;\n  TaskSequencerConfig(): num_threads(1), num_threads_total(0)  { }\n  void Register(OptionsItf *opts) {\n    opts->Register(\"num-threads\", &num_threads, \"Number of actively processing \"\n                   \"threads to run in parallel\");\n    opts->Register(\"num-threads-total\", &num_threads_total, \"Total number of \"\n                   \"threads, including those that are waiting on other threads \"\n                   \"to produce their output.  Controls memory use.  If <= 0, \"\n                   \"defaults to --num-threads plus 20.  Otherwise, must \"\n                   \"be >= num-threads.\");\n  }\n};\n\n// C should have an operator () taking no arguments, that does some kind\n// of computation, and a destructor that produces some kind of output (the\n// destructors will be run sequentially in the same order Run as called.\ntemplate<class C>\nclass TaskSequencer {\n public:\n  TaskSequencer(const TaskSequencerConfig &config):\n      num_threads_(config.num_threads),\n      threads_avail_(config.num_threads),\n      tot_threads_avail_(config.num_threads_total > 0 ? config.num_threads_total :\n                         config.num_threads + 20),\n      thread_list_(NULL) {\n    KALDI_ASSERT((config.num_threads_total <= 0 ||\n                  config.num_threads_total >= config.num_threads) &&\n                 \"num-threads-total, if specified, must be >= num-threads\");\n  }\n\n  /// This function takes ownership of the pointer \"c\", and will delete it\n  /// in the same sequence as Run was called on the jobs.\n  void Run(C *c) {\n    // run in main thread\n    if (num_threads_ == 0) {\n      (*c)();\n      delete c;\n      return;\n    }\n\n    threads_avail_.Wait(); // wait till we have a thread for computation free.\n    tot_threads_avail_.Wait(); // this ensures we don't have too many threads\n    // waiting on I/O, and consume too much memory.\n\n    // put the new RunTaskArgsList object at head of the singly\n    // linked list thread_list_.\n    thread_list_ = new RunTaskArgsList(this, c, thread_list_);\n    thread_list_->thread = std::thread(TaskSequencer<C>::RunTask,\n                                       thread_list_);\n  }\n\n  void Wait() { // You call this at the end if it's more convenient\n    // than waiting for the destructor.  It waits for all tasks to finish.\n    if (thread_list_ != NULL) {\n      thread_list_->thread.join();\n      KALDI_ASSERT(thread_list_->tail == NULL); // thread would not\n      // have exited without setting tail to NULL.\n      delete thread_list_;\n      thread_list_ = NULL;\n    }\n  }\n\n  /// The destructor waits for the last thread to exit.\n  ~TaskSequencer() {\n    Wait();\n  }\n private:\n  struct RunTaskArgsList {\n    TaskSequencer *me; // Think of this as a \"this\" pointer.\n    C *c; // Clist element of the task we're expected\n    std::thread thread;\n    RunTaskArgsList *tail;\n    RunTaskArgsList(TaskSequencer *me, C *c, RunTaskArgsList *tail):\n        me(me), c(c), tail(tail) {}\n  };\n  // This static function gets run in the threads that we create.\n  static void RunTask(RunTaskArgsList *args) {\n    // (1) run the job.\n    (*(args->c))(); // call operator () on args->c, which does the computation.\n    args->me->threads_avail_.Signal(); // Signal that the compute-intensive\n    // part of the thread is done (we want to run no more than\n    // config_.num_threads of these.)\n\n    // (2) we want to destroy the object \"c\" now, by deleting it.  But for\n    //     correct sequencing (this is the whole point of this class, it\n    //     is intended to ensure the output of the program is in correct order),\n    //     we first wait till the previous thread, whose details will be in \"tail\",\n    //     is finished.\n    if (args->tail != NULL) {\n      args->tail->thread.join();\n    }\n\n    delete args->c; // delete the object \"c\".  This may cause some output,\n    // e.g. to a stream.  We don't need to worry about concurrent access to\n    // the output stream, because each thread waits for the previous thread\n    // to be done, before doing this.  So there is no risk of concurrent\n    // access.\n    args->c = NULL;\n\n    if (args->tail != NULL) {\n      KALDI_ASSERT(args->tail->tail == NULL); // Because we already\n      // did join on args->tail->thread, which means that\n      // thread was done, and before it exited, it would have\n      // deleted and set to NULL its tail (which is the next line of code).\n      delete args->tail;\n      args->tail = NULL;\n    }\n    // At this point we are exiting from the thread.  Signal the\n    // \"tot_threads_avail_\" semaphore which is used to limit the total number of threads that are alive, including\n    // not onlhy those that are in active computation in c->operator (), but those\n    // that are waiting on I/O or other threads.\n    args->me->tot_threads_avail_.Signal();\n  }\n\n  int32 num_threads_; // copy of config.num_threads (since Semaphore doesn't store original count)\n\n  Semaphore threads_avail_; // Initialized to the number of threads we are\n  // supposed to run with; the function Run() waits on this.\n\n  Semaphore tot_threads_avail_; // We use this semaphore to ensure we don't\n  // consume too much memory...\n  RunTaskArgsList *thread_list_;\n\n};\n\n} // namespace kaldi\n\n#endif  // KALDI_THREAD_KALDI_THREAD_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/options-itf.h",
    "content": "// itf/options-itf.h\n\n// Copyright 2013  Tanel Alumae, Tallinn University of Technology\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_ITF_OPTIONS_ITF_H_\n#define KALDI_ITF_OPTIONS_ITF_H_ 1\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n\nclass OptionsItf {\n public:\n  \n  virtual void Register(const std::string &name,\n                bool *ptr, const std::string &doc) = 0; \n  virtual void Register(const std::string &name,\n                int32 *ptr, const std::string &doc) = 0; \n  virtual void Register(const std::string &name,\n                uint32 *ptr, const std::string &doc) = 0; \n  virtual void Register(const std::string &name,\n                float *ptr, const std::string &doc) = 0; \n  virtual void Register(const std::string &name,\n                double *ptr, const std::string &doc) = 0; \n  virtual void Register(const std::string &name,\n                std::string *ptr, const std::string &doc) = 0; \n  \n  virtual ~OptionsItf() {}\n};\n\n}  // namespace Kaldi\n\n#endif  // KALDI_ITF_OPTIONS_ITF_H_\n\n\n"
  },
  {
    "path": "runtime/engine/kaldi/util/parse-options.cc",
    "content": "// util/parse-options.cc\n\n// Copyright 2009-2011  Karel Vesely;  Microsoft Corporation;\n//                      Saarland University (Author: Arnab Ghoshal);\n// Copyright 2012-2013  Johns Hopkins University (Author: Daniel Povey);\n//                      Frantisek Skala;  Arnab Ghoshal\n// Copyright 2013       Tanel Alumae\n//\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include <iostream>\n#include <iomanip>\n#include <fstream>\n#include <algorithm>\n#include <cstdlib>\n#include <cassert>\n#include <cstring>\n\n#include \"util/parse-options.h\"\n#include \"util/text-utils.h\"\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n\n\nParseOptions::ParseOptions(const std::string &prefix,\n                           OptionsItf *other):\n    print_args_(false), help_(false), usage_(\"\"), argc_(0), argv_(NULL) {\n  ParseOptions *po = dynamic_cast<ParseOptions*>(other);\n  if (po != NULL && po->other_parser_ != NULL) {\n    // we get here if this constructor is used twice, recursively.\n    other_parser_ = po->other_parser_;\n  } else {\n    other_parser_ = other;\n  }\n  if (po != NULL && po->prefix_ != \"\") {\n    prefix_ = po->prefix_ + std::string(\".\") + prefix;\n  } else {\n    prefix_ = prefix;\n  }\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            bool *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            int32 *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            uint32 *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            float *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            double *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\nvoid ParseOptions::Register(const std::string &name,\n                            std::string *ptr, const std::string &doc) {\n  RegisterTmpl(name, ptr, doc);\n}\n\n// old-style, used for registering application-specific parameters\ntemplate<typename T>\nvoid ParseOptions::RegisterTmpl(const std::string &name, T *ptr,\n                                const std::string &doc) {\n  if (other_parser_ == NULL) {\n    this->RegisterCommon(name, ptr, doc, false);\n  } else {\n    KALDI_ASSERT(prefix_ != \"\" &&\n                 \"Cannot use empty prefix when registering with prefix.\");\n    std::string new_name = prefix_ + '.' + name;  // name becomes prefix.name\n    other_parser_->Register(new_name, ptr, doc);\n  }\n}\n\n// does the common part of the job of registering a parameter\ntemplate<typename T>\nvoid ParseOptions::RegisterCommon(const std::string &name, T *ptr,\n                                  const std::string &doc, bool is_standard) {\n  KALDI_ASSERT(ptr != NULL);\n  std::string idx = name;\n  NormalizeArgName(&idx);\n  if (doc_map_.find(idx) != doc_map_.end())\n    KALDI_WARN << \"Registering option twice, ignoring second time: \" << name;\n  this->RegisterSpecific(name, idx, ptr, doc, is_standard);\n}\n\n// used to register standard parameters (those that are present in all of the\n// applications)\ntemplate<typename T>\nvoid ParseOptions::RegisterStandard(const std::string &name, T *ptr,\n                            const std::string &doc) {\n  this->RegisterCommon(name, ptr, doc, true);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    bool *b,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  bool_map_[idx] = b;\n  doc_map_[idx] = DocInfo(name, doc + \" (bool, default = \"\n                          + ((*b)? \"true)\" : \"false)\"), is_standard);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    int32 *i,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  int_map_[idx] = i;\n  std::ostringstream ss;\n  ss << doc << \" (int, default = \" << *i << \")\";\n  doc_map_[idx] = DocInfo(name, ss.str(), is_standard);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    uint32 *u,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  uint_map_[idx] = u;\n  std::ostringstream ss;\n  ss << doc << \" (uint, default = \" << *u << \")\";\n  doc_map_[idx] = DocInfo(name, ss.str(), is_standard);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    float *f,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  float_map_[idx] = f;\n  std::ostringstream ss;\n  ss << doc << \" (float, default = \" << *f << \")\";\n  doc_map_[idx] = DocInfo(name, ss.str(), is_standard);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    double *f,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  double_map_[idx] = f;\n  std::ostringstream ss;\n  ss << doc << \" (double, default = \" << *f << \")\";\n  doc_map_[idx] = DocInfo(name, ss.str(), is_standard);\n}\n\nvoid ParseOptions::RegisterSpecific(const std::string &name,\n                                    const std::string &idx,\n                                    std::string *s,\n                                    const std::string &doc,\n                                    bool is_standard) {\n  string_map_[idx] = s;\n  doc_map_[idx] = DocInfo(name, doc + \" (string, default = \\\"\" + *s + \"\\\")\",\n                          is_standard);\n}\nvoid ParseOptions::DisableOption(const std::string &name) {\n  if (argv_ != NULL)\n    KALDI_ERR << \"DisableOption must not be called after calling Read().\";\n  if (doc_map_.erase(name) == 0)\n    KALDI_ERR << \"Option \" << name\n              << \" was not registered so cannot be disabled: \";\n  bool_map_.erase(name);\n  int_map_.erase(name);\n  uint_map_.erase(name);\n  float_map_.erase(name);\n  double_map_.erase(name);\n  string_map_.erase(name);\n}\n\n\nint ParseOptions::NumArgs() const {\n  return positional_args_.size();\n}\n\nstd::string ParseOptions::GetArg(int i) const {\n  // use KALDI_ERR if code error\n  if (i < 1 || i > static_cast<int>(positional_args_.size()))\n    KALDI_ERR << \"ParseOptions::GetArg, invalid index \" << i;\n  return positional_args_[i - 1];\n}\n\n// We currently do not support any other options.\nenum ShellType { kBash = 0 };\n\n// This can be changed in the code if it ever does need to be changed (as it's\n// unlikely that one compilation of this tool-set would use both shells).\nstatic ShellType kShellType = kBash;\n\n// Returns true if we need to escape a string before putting it into\n// a shell (mainly thinking of bash shell, but should work for others)\n// This is for the convenience of the user so command-lines that are\n// printed out by ParseOptions::Read (with --print-args=true) are\n// paste-able into the shell and will run. If you use a different type of\n// shell, it might be necessary to change this function.\n// But it's mostly a cosmetic issue as it basically affects how\n// the program echoes its command-line arguments to the screen.\nstatic bool MustBeQuoted(const std::string &str, ShellType st) {\n  // Only Bash is supported (for the moment).\n  KALDI_ASSERT(st == kBash && \"Invalid shell type.\");\n\n  const char *c = str.c_str();\n  if (*c == '\\0') {\n    return true;  // Must quote empty string\n  } else {\n    const char *ok_chars[2];\n\n    // These seem not to be interpreted as long as there are no other \"bad\"\n    // characters involved (e.g. \",\" would be interpreted as part of something\n    // like a{b,c}, but not on its own.\n    ok_chars[kBash] = \"[]~#^_-+=:.,/\";\n\n    // Just want to make sure that a space character doesn't get automatically\n    // inserted here via an automated style-checking script, like it did before.\n    KALDI_ASSERT(!strchr(ok_chars[kBash], ' '));\n\n    for (; *c != '\\0'; c++) {\n      // For non-alphanumeric characters we have a list of characters which\n      // are OK. All others are forbidden (this is easier since the shell\n      // interprets most non-alphanumeric characters).\n      if (!isalnum(*c)) {\n        const char *d;\n        for (d = ok_chars[st]; *d != '\\0'; d++) if (*c == *d) break;\n        // If not alphanumeric or one of the \"ok_chars\", it must be escaped.\n        if (*d == '\\0') return true;\n      }\n    }\n    return false;  // The string was OK. No quoting or escaping.\n  }\n}\n\n// Returns a quoted and escaped version of \"str\"\n// which has previously been determined to need escaping.\n// Our aim is to print out the command line in such a way that if it's\n// pasted into a shell of ShellType \"st\" (only bash for now), it\n// will get passed to the program in the same way.\nstatic std::string QuoteAndEscape(const std::string &str, ShellType st) {\n  // Only Bash is supported (for the moment).\n  KALDI_ASSERT(st == kBash && \"Invalid shell type.\");\n\n  // For now we use the following rules:\n  // In the normal case, we quote with single-quote \"'\", and to escape\n  // a single-quote we use the string: '\\'' (interpreted as closing the\n  // single-quote, putting an escaped single-quote from the shell, and\n  // then reopening the single quote).\n  char quote_char = '\\'';\n  const char *escape_str = \"'\\\\''\";  // e.g. echo 'a'\\''b' returns a'b\n\n  // If the string contains single-quotes that would need escaping this\n  // way, and we determine that the string could be safely double-quoted\n  // without requiring any escaping, then we double-quote the string.\n  // This is the case if the characters \"`$\\ do not appear in the string.\n  // e.g. see http://www.redhat.com/mirrors/LDP/LDP/abs/html/quotingvar.html\n  const char *c_str = str.c_str();\n  if (strchr(c_str, '\\'') && !strpbrk(c_str, \"\\\"`$\\\\\")) {\n    quote_char = '\"';\n    escape_str = \"\\\\\\\"\";  // should never be accessed.\n  }\n\n  char buf[2];\n  buf[1] = '\\0';\n\n  buf[0] = quote_char;\n  std::string ans = buf;\n  const char *c = str.c_str();\n  for (;*c != '\\0'; c++) {\n    if (*c == quote_char) {\n      ans += escape_str;\n    } else {\n      buf[0] = *c;\n      ans += buf;\n    }\n  }\n  buf[0] = quote_char;\n  ans += buf;\n  return ans;\n}\n\n// static function\nstd::string ParseOptions::Escape(const std::string &str) {\n  return MustBeQuoted(str, kShellType) ? QuoteAndEscape(str, kShellType) : str;\n}\n\n\nint ParseOptions::Read(int argc, const char *const argv[]) {\n  argc_ = argc;\n  argv_ = argv;\n  std::string key, value;\n  int i;\n  if (argc > 0) {\n    // set global \"const char*\" g_program_name (name of the program)\n    // so it can be printed out in error messages;\n    // it's useful because often the stderr of different programs will\n    // be mixed together in the same log file.\n#ifdef _MSC_VER\n    const char *c = strrchr(argv[0], '\\\\');\n#else\n    const char *c = strrchr(argv[0], '/');\n#endif\n    SetProgramName(c == NULL ? argv[0] : c + 1);\n  }\n  // first pass: look for config parameter, look for priority\n  for (i = 1; i < argc; i++) {\n    if (std::strncmp(argv[i], \"--\", 2) == 0) {\n      if (std::strcmp(argv[i], \"--\") == 0) {\n        // a lone \"--\" marks the end of named options\n        break;\n      }\n      bool has_equal_sign;\n      SplitLongArg(argv[i], &key, &value, &has_equal_sign);\n      NormalizeArgName(&key);\n      Trim(&value);\n      if (key.compare(\"config\") == 0) {\n        ReadConfigFile(value);\n      }\n      if (key.compare(\"help\") == 0) {\n        PrintUsage();\n        exit(0);\n      }\n    }\n  }\n  bool double_dash_seen = false;\n  // second pass: add the command line options\n  for (i = 1; i < argc; i++) {\n    if (std::strncmp(argv[i], \"--\", 2) == 0) {\n      if (std::strcmp(argv[i], \"--\") == 0) {\n        // A lone \"--\" marks the end of named options.\n        // Skip that option and break the processing of named options\n        i += 1;\n        double_dash_seen = true;\n        break;\n      }\n      bool has_equal_sign;\n      SplitLongArg(argv[i], &key, &value, &has_equal_sign);\n      NormalizeArgName(&key);\n      Trim(&value);\n      if (!SetOption(key, value, has_equal_sign)) {\n        PrintUsage(true);\n        KALDI_ERR << \"Invalid option \" << argv[i];\n      }\n    } else {\n      break;\n    }\n  }\n\n  // process remaining arguments as positional\n  for (; i < argc; i++) {\n    if ((std::strcmp(argv[i], \"--\") == 0) && !double_dash_seen) {\n      double_dash_seen = true;\n    } else {\n      positional_args_.push_back(std::string(argv[i]));\n    }\n  }\n\n  // if the user did not suppress this with --print-args = false....\n  if (print_args_) {\n    std::ostringstream strm;\n    for (int j = 0; j < argc; j++)\n      strm << Escape(argv[j]) << \" \";\n    strm << '\\n';\n    std::cerr << strm.str() << std::flush;\n  }\n  return i;\n}\n\n\nvoid ParseOptions::PrintUsage(bool print_command_line) {\n  std::cerr << '\\n' << usage_ << '\\n';\n  DocMapType::iterator it;\n  // first we print application-specific options\n  bool app_specific_header_printed = false;\n  for (it = doc_map_.begin(); it != doc_map_.end(); ++it) {\n    if (it->second.is_standard_ == false) {  // application-specific option\n      if (app_specific_header_printed == false) {  // header was not yet printed\n        std::cerr << \"Options:\" << '\\n';\n        app_specific_header_printed = true;\n      }\n      std::cerr << \"  --\" << std::setw(25) << std::left << it->second.name_\n          << \" : \" << it->second.use_msg_ << '\\n';\n    }\n  }\n  if (app_specific_header_printed == true) {\n    std::cerr << '\\n';\n  }\n\n  // then the standard options\n  std::cerr << \"Standard options:\" << '\\n';\n  for (it = doc_map_.begin(); it != doc_map_.end(); ++it) {\n    if (it->second.is_standard_ == true) {  // we have standard option\n      std::cerr << \"  --\" << std::setw(25) << std::left << it->second.name_\n          << \" : \" << it->second.use_msg_ << '\\n';\n    }\n  }\n  std::cerr << '\\n';\n  if (print_command_line) {\n    std::ostringstream strm;\n    strm << \"Command line was: \";\n    for (int j = 0; j < argc_; j++)\n      strm << Escape(argv_[j]) << \" \";\n    strm << '\\n';\n    std::cerr << strm.str() << std::flush;\n  }\n}\n\nvoid ParseOptions::PrintConfig(std::ostream &os) {\n  os << '\\n' << \"[[ Configuration of UI-Registered options ]]\" << '\\n';\n  std::string key;\n  DocMapType::iterator it;\n  for (it = doc_map_.begin(); it != doc_map_.end(); ++it) {\n    key = it->first;\n    os << it->second.name_ << \" = \";\n    if (bool_map_.end() != bool_map_.find(key)) {\n      os << (*bool_map_[key] ? \"true\" : \"false\");\n    } else if (int_map_.end() != int_map_.find(key)) {\n      os << (*int_map_[key]);\n    } else if (uint_map_.end() != uint_map_.find(key)) {\n      os << (*uint_map_[key]);\n    } else if (float_map_.end() != float_map_.find(key)) {\n      os << (*float_map_[key]);\n    } else if (double_map_.end() != double_map_.find(key)) {\n      os << (*double_map_[key]);\n    } else if (string_map_.end() != string_map_.find(key)) {\n      os << \"'\" << *string_map_[key] << \"'\";\n    } else {\n      KALDI_ERR << \"PrintConfig: unrecognized option \" << key << \"[code error]\";\n    }\n    os << '\\n';\n  }\n  os << '\\n';\n}\n\n\nvoid ParseOptions::ReadConfigFile(const std::string &filename) {\n  std::ifstream is(filename.c_str(), std::ifstream::in);\n  if (!is.good()) {\n    KALDI_ERR << \"Cannot open config file: \" << filename;\n  }\n\n  std::string line, key, value;\n  int32 line_number = 0;\n  while (std::getline(is, line)) {\n    line_number++;\n    // trim out the comments\n    size_t pos;\n    if ((pos = line.find_first_of('#')) != std::string::npos) {\n      line.erase(pos);\n    }\n    // skip empty lines\n    Trim(&line);\n    if (line.length() == 0) continue;\n\n    if (line.substr(0, 2) != \"--\") {\n      KALDI_ERR << \"Reading config file \" << filename\n                << \": line \" << line_number << \" does not look like a line \"\n                << \"from a Kaldi command-line program's config file: should \"\n                << \"be of the form --x=y.  Note: config files intended to \"\n                << \"be sourced by shell scripts lack the '--'.\";\n    }\n\n    // parse option\n    bool has_equal_sign;\n    SplitLongArg(line, &key, &value, &has_equal_sign);\n    NormalizeArgName(&key);\n    Trim(&value);\n    if (!SetOption(key, value, has_equal_sign)) {\n      PrintUsage(true);\n      KALDI_ERR << \"Invalid option \" << line << \" in config file \" << filename;\n    }\n  }\n}\n\n\n\nvoid ParseOptions::SplitLongArg(const std::string &in,\n                                std::string *key,\n                                std::string *value,\n                                bool *has_equal_sign) {\n  KALDI_ASSERT(in.substr(0, 2) == \"--\");  // precondition.\n  size_t pos = in.find_first_of('=', 0);\n  if (pos == std::string::npos) {  // we allow --option for bools\n    // defaults to empty.  We handle this differently in different cases.\n    *key = in.substr(2, in.size()-2);  // 2 because starts with --.\n    *value = \"\";\n    *has_equal_sign = false;\n  } else if (pos == 2) {  // we also don't allow empty keys: --=value\n    PrintUsage(true);\n    KALDI_ERR << \"Invalid option (no key): \" << in;\n  } else {  // normal case: --option=value\n    *key = in.substr(2, pos-2);  // 2 because starts with --.\n    *value = in.substr(pos + 1);\n    *has_equal_sign = true;\n  }\n}\n\n\nvoid ParseOptions::NormalizeArgName(std::string *str) {\n  std::string out;\n  std::string::iterator it;\n\n  for (it = str->begin(); it != str->end(); ++it) {\n    if (*it == '_')\n      out += '-';  // convert _ to -\n    else\n      out += std::tolower(*it);\n  }\n  *str = out;\n\n  KALDI_ASSERT(str->length() > 0);\n}\n\n\n\n\nbool ParseOptions::SetOption(const std::string &key,\n                             const std::string &value,\n                             bool has_equal_sign) {\n  if (bool_map_.end() != bool_map_.find(key)) {\n    if (has_equal_sign && value == \"\")\n      KALDI_ERR << \"Invalid option --\" << key << \"=\";\n    *(bool_map_[key]) = ToBool(value);\n  } else if (int_map_.end() != int_map_.find(key)) {\n    *(int_map_[key]) = ToInt(value);\n  } else if (uint_map_.end() != uint_map_.find(key)) {\n    *(uint_map_[key]) = ToUint(value);\n  } else if (float_map_.end() != float_map_.find(key)) {\n    *(float_map_[key]) = ToFloat(value);\n  } else if (double_map_.end() != double_map_.find(key)) {\n    *(double_map_[key]) = ToDouble(value);\n  } else if (string_map_.end() != string_map_.find(key)) {\n    if (!has_equal_sign)\n      KALDI_ERR << \"Invalid option --\" << key\n                << \" (option format is --x=y).\";\n    *(string_map_[key]) = value;\n  } else {\n    return false;\n  }\n  return true;\n}\n\n\n\nbool ParseOptions::ToBool(std::string str) {\n  std::transform(str.begin(), str.end(), str.begin(), ::tolower);\n\n  // allow \"\" as a valid option for \"true\", so that --x is the same as --x=true\n  if ((str.compare(\"true\") == 0) || (str.compare(\"t\") == 0)\n      || (str.compare(\"1\") == 0) || (str.compare(\"\") == 0)) {\n    return true;\n  }\n  if ((str.compare(\"false\") == 0) || (str.compare(\"f\") == 0)\n      || (str.compare(\"0\") == 0)) {\n    return false;\n  }\n  // if it is neither true nor false:\n  PrintUsage(true);\n  KALDI_ERR << \"Invalid format for boolean argument [expected true or false]: \"\n            << str;\n  return false;  // never reached\n}\n\n\nint32 ParseOptions::ToInt(const std::string &str) {\n  int32 ret;\n  if (!ConvertStringToInteger(str, &ret))\n    KALDI_ERR << \"Invalid integer option \\\"\" << str << \"\\\"\";\n  return ret;\n}\n\nuint32 ParseOptions::ToUint(const std::string &str) {\n  uint32 ret;\n  if (!ConvertStringToInteger(str, &ret))\n    KALDI_ERR << \"Invalid integer option \\\"\" << str << \"\\\"\";\n  return ret;\n}\n\nfloat ParseOptions::ToFloat(const std::string &str) {\n  float ret;\n  if (!ConvertStringToReal(str, &ret))\n    KALDI_ERR << \"Invalid floating-point option \\\"\" << str << \"\\\"\";\n  return ret;\n}\n\ndouble ParseOptions::ToDouble(const std::string &str) {\n  double ret;\n  if (!ConvertStringToReal(str, &ret))\n    KALDI_ERR << \"Invalid floating-point option \\\"\" << str << \"\\\"\";\n  return ret;\n}\n\n// instantiate templates\ntemplate void ParseOptions::RegisterTmpl(const std::string &name, bool *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterTmpl(const std::string &name, int32 *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterTmpl(const std::string &name, uint32 *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterTmpl(const std::string &name, float *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterTmpl(const std::string &name, double *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterTmpl(const std::string &name,\n                            std::string *ptr, const std::string &doc);\n\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            bool *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            int32 *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            uint32 *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            float *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            double *ptr,\n                            const std::string &doc);\ntemplate void ParseOptions::RegisterStandard(const std::string &name,\n                            std::string *ptr,\n                            const std::string &doc);\n\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            bool *ptr,\n                            const std::string &doc, bool is_standard);\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            int32 *ptr,\n                            const std::string &doc, bool is_standard);\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            uint32 *ptr,\n                            const std::string &doc, bool is_standard);\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            float *ptr,\n                            const std::string &doc, bool is_standard);\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            double *ptr,\n                            const std::string &doc, bool is_standard);\ntemplate void ParseOptions::RegisterCommon(const std::string &name,\n                            std::string *ptr,\n                            const std::string &doc, bool is_standard);\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/parse-options.h",
    "content": "// util/parse-options.h\n\n// Copyright 2009-2011  Karel Vesely;  Microsoft Corporation;\n//                      Saarland University (Author: Arnab Ghoshal);\n// Copyright 2012-2013  Frantisek Skala;  Arnab Ghoshal\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_PARSE_OPTIONS_H_\n#define KALDI_UTIL_PARSE_OPTIONS_H_\n\n#include <map>\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-common.h\"\n#include \"util/options-itf.h\"\n\nnamespace kaldi {\n\n/// The class ParseOptions is for parsing command-line options; see\n/// \\ref parse_options for more documentation.\nclass ParseOptions : public OptionsItf {\n public:\n  explicit ParseOptions(const char *usage) :\n    print_args_(true), help_(false), usage_(usage), argc_(0), argv_(NULL),\n    prefix_(\"\"), other_parser_(NULL) {\n#if !defined(_MSC_VER) && !defined(__CYGWIN__) // This is just a convenient place to set the stderr to line\n    setlinebuf(stderr);  // buffering mode, since it's called at program start.\n#endif  // This helps ensure different programs' output is not mixed up.\n    RegisterStandard(\"config\", &config_, \"Configuration file to read (this \"\n                     \"option may be repeated)\");\n    RegisterStandard(\"print-args\", &print_args_,\n                     \"Print the command line arguments (to stderr)\");\n    RegisterStandard(\"help\", &help_, \"Print out usage message\");\n    RegisterStandard(\"verbose\", &g_kaldi_verbose_level,\n                     \"Verbose level (higher->more logging)\");\n  }\n\n  /**\n    This is a constructor for the special case where some options are\n    registered with a prefix to avoid conflicts.  The object thus created will\n    only be used temporarily to register an options class with the original\n    options parser (which is passed as the *other pointer) using the given\n    prefix.  It should not be used for any other purpose, and the prefix must\n    not be the empty string.  It seems to be the least bad way of implementing\n    options with prefixes at this point.\n    Example of usage is:\n     ParseOptions po;  // original ParseOptions object\n     ParseOptions po_mfcc(\"mfcc\", &po); // object with prefix.\n     MfccOptions mfcc_opts;\n     mfcc_opts.Register(&po_mfcc);\n    The options will now get registered as, e.g., --mfcc.frame-shift=10.0\n    instead of just --frame-shift=10.0\n   */\n  ParseOptions(const std::string &prefix, OptionsItf *other);\n\n  ~ParseOptions() {}\n\n  // Methods from the interface\n  void Register(const std::string &name,\n                bool *ptr, const std::string &doc);\n  void Register(const std::string &name,\n                int32 *ptr, const std::string &doc);\n  void Register(const std::string &name,\n                uint32 *ptr, const std::string &doc);\n  void Register(const std::string &name,\n                float *ptr, const std::string &doc);\n  void Register(const std::string &name,\n                double *ptr, const std::string &doc);\n  void Register(const std::string &name,\n                std::string *ptr, const std::string &doc);\n\n  /// If called after registering an option and before calling\n  /// Read(), disables that option from being used.  Will crash\n  /// at runtime if that option had not been registered.\n  void DisableOption(const std::string &name);\n\n  /// This one is used for registering standard parameters of all the programs\n  template<typename T>\n  void RegisterStandard(const std::string &name,\n                        T *ptr, const std::string &doc);\n\n  /**\n    Parses the command line options and fills the ParseOptions-registered\n    variables. This must be called after all the variables were registered!!!\n\n    Initially the variables have implicit values,\n    then the config file values are set-up,\n    finally the command line values given.\n    Returns the first position in argv that was not used.\n    [typically not useful: use NumParams() and GetParam(). ]\n   */\n  int Read(int argc, const char *const *argv);\n\n  /// Prints the usage documentation [provided in the constructor].\n  void PrintUsage(bool print_command_line = false);\n  /// Prints the actual configuration of all the registered variables\n  void PrintConfig(std::ostream &os);\n\n  /// Reads the options values from a config file.  Must be called after\n  /// registering all options.  This is usually used internally after the\n  /// standard --config option is used, but it may also be called from a\n  /// program.\n  void ReadConfigFile(const std::string &filename);\n\n  /// Number of positional parameters (c.f. argc-1).\n  int NumArgs() const;\n\n  /// Returns one of the positional parameters; 1-based indexing for argc/argv\n  /// compatibility. Will crash if param is not >=1 and <=NumArgs().\n  std::string GetArg(int param) const;\n\n  std::string GetOptArg(int param) const {\n    return (param <= NumArgs() ? GetArg(param) : \"\");\n  }\n\n  /// The following function will return a possibly quoted and escaped\n  /// version of \"str\", according to the current shell.  Currently\n  /// this is just hardwired to bash.  It's useful for debug output.\n  static std::string Escape(const std::string &str);\n\n private:\n  /// Template to register various variable types,\n  /// used for program-specific parameters\n  template<typename T>\n  void RegisterTmpl(const std::string &name, T *ptr, const std::string &doc);\n\n  // Following functions do just the datatype-specific part of the job\n  /// Register boolean variable\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        bool *b, const std::string &doc, bool is_standard);\n  /// Register int32 variable\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        int32 *i, const std::string &doc, bool is_standard);\n  /// Register unsinged  int32 variable\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        uint32 *u,\n                        const std::string &doc, bool is_standard);\n  /// Register float variable\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        float *f, const std::string &doc, bool is_standard);\n  /// Register double variable [useful as we change BaseFloat type].\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        double *f, const std::string &doc, bool is_standard);\n  /// Register string variable\n  void RegisterSpecific(const std::string &name, const std::string &idx,\n                        std::string *s, const std::string &doc,\n                        bool is_standard);\n\n  /// Does the actual job for both kinds of parameters\n  /// Does the common part of the job for all datatypes,\n  /// then calls RegisterSpecific\n  template<typename T>\n  void RegisterCommon(const std::string &name,\n                      T *ptr, const std::string &doc, bool is_standard);\n\n  /// Set option with name \"key\" to \"value\"; will crash if can't do it.\n  /// \"has_equal_sign\" is used to allow --x for a boolean option x,\n  /// and --y=, for a string option y.\n  bool SetOption(const std::string &key, const std::string &value,\n                 bool has_equal_sign);\n\n  bool ToBool(std::string str);\n  int32 ToInt(const std::string &str);\n  uint32 ToUint(const std::string &str);\n  float ToFloat(const std::string &str);\n  double ToDouble(const std::string &str);\n\n  // maps for option variables\n  std::map<std::string, bool*> bool_map_;\n  std::map<std::string, int32*> int_map_;\n  std::map<std::string, uint32*> uint_map_;\n  std::map<std::string, float*> float_map_;\n  std::map<std::string, double*> double_map_;\n  std::map<std::string, std::string*> string_map_;\n\n  /**\n     Structure for options' documentation\n   */\n  struct DocInfo {\n    DocInfo() {}\n    DocInfo(const std::string &name, const std::string &usemsg)\n      : name_(name), use_msg_(usemsg), is_standard_(false) {}\n    DocInfo(const std::string &name, const std::string &usemsg,\n            bool is_standard)\n      : name_(name), use_msg_(usemsg),  is_standard_(is_standard) {}\n\n    std::string name_;\n    std::string use_msg_;\n    bool is_standard_;\n  };\n  typedef std::map<std::string, DocInfo> DocMapType;\n  DocMapType doc_map_;  ///< map for the documentation\n\n  bool print_args_;     ///< variable for the implicit --print-args parameter\n  bool help_;           ///< variable for the implicit --help parameter\n  std::string config_;  ///< variable for the implicit --config parameter\n  std::vector<std::string> positional_args_;\n  const char *usage_;\n  int argc_;\n  const char *const *argv_;\n\n  /// These members are not normally used. They are only used when the object\n  /// is constructed with a prefix\n  std::string prefix_;\n  OptionsItf *other_parser_;\n protected:\n    /// SplitLongArg parses an argument of the form --a=b, --a=, or --a,\n  /// and sets \"has_equal_sign\" to true if an equals-sign was parsed..\n  /// this is needed in order to correctly allow --x for a boolean option\n  /// x, and --y= for a string option y, and to disallow --x= and --y.\n  void SplitLongArg(const std::string &in, std::string *key,\n                    std::string *value, bool *has_equal_sign);\n\n  void NormalizeArgName(std::string *str);\n};\n\n/// This template is provided for convenience in reading config classes from\n/// files; this is not the standard way to read configuration options, but may\n/// occasionally be needed.  This function assumes the config has a function\n/// \"void Register(OptionsItf *opts)\" which it can call to register the\n/// ParseOptions object.\ntemplate<class C> void ReadConfigFromFile(const std::string &config_filename,\n                                          C *c) {\n  std::ostringstream usage_str;\n  usage_str << \"Parsing config from \"\n            << \"from '\" << config_filename << \"'\";\n  ParseOptions po(usage_str.str().c_str());\n  c->Register(&po);\n  po.ReadConfigFile(config_filename);\n}\n\n/// This variant of the template ReadConfigFromFile is for if you need to read\n/// two config classes from the same file.\ntemplate<class C1, class C2> void ReadConfigsFromFile(const std::string &conf,\n                                                      C1 *c1, C2 *c2) {\n  std::ostringstream usage_str;\n  usage_str << \"Parsing config from \"\n            << \"from '\" << conf << \"'\";\n  ParseOptions po(usage_str.str().c_str());\n  c1->Register(&po);\n  c2->Register(&po);\n  po.ReadConfigFile(conf);\n}\n\n\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_PARSE_OPTIONS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/simple-io-funcs.cc",
    "content": "// util/simple-io-funcs.cc\n\n// Copyright 2009-2011  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#include \"util/simple-io-funcs.h\"\n#include \"util/text-utils.h\"\n\nnamespace kaldi {\n\nbool WriteIntegerVectorSimple(const std::string &wxfilename,\n                              const std::vector<int32> &list) {\n  kaldi::Output ko;\n  // false, false is: text-mode, no Kaldi header.\n  if (!ko.Open(wxfilename, false, false)) return false;\n  for (size_t i = 0; i < list.size(); i++) ko.Stream() << list[i] << '\\n';\n  return ko.Close();\n}\n\nbool ReadIntegerVectorSimple(const std::string &rxfilename,\n                             std::vector<int32> *list) {\n  kaldi::Input ki;\n  if (!ki.OpenTextMode(rxfilename)) return false;\n  std::istream &is = ki.Stream();\n  int32 i;\n  list->clear();\n  while ( !(is >> i).fail() )\n    list->push_back(i);\n  is >> std::ws;\n  return is.eof();  // should be eof, or junk at end of file.\n}\n\nbool WriteIntegerVectorVectorSimple(const std::string &wxfilename,\n                                 const std::vector<std::vector<int32> > &list) {\n  kaldi::Output ko;\n  // false, false is: text-mode, no Kaldi header.\n  if (!ko.Open(wxfilename, false, false)) return false;\n  std::ostream &os = ko.Stream();\n  for (size_t i = 0; i < list.size(); i++) {\n    for (size_t j = 0; j < list[i].size(); j++) {\n      os << list[i][j];\n      if (j+1 < list[i].size()) os << ' ';\n    }\n    os << '\\n';\n  }\n  return ko.Close();\n}\n\nbool ReadIntegerVectorVectorSimple(const std::string &rxfilename,\n                                   std::vector<std::vector<int32> > *list) {\n  kaldi::Input ki;\n  if (!ki.OpenTextMode(rxfilename)) return false;\n  std::istream &is = ki.Stream();\n  list->clear();\n  std::string line;\n  while (std::getline(is, line)) {\n    std::vector<int32> v;\n    if (!SplitStringToIntegers(line, \" \\t\\r\", true, &v)) {\n      list->clear();\n      return false;\n    }\n    list->push_back(v);\n  }\n  return is.eof();  // if we're not at EOF, something weird happened.\n}\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/simple-io-funcs.h",
    "content": "// util/simple-io-funcs.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Jan Silovsky\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n#ifndef KALDI_UTIL_SIMPLE_IO_FUNCS_H_\n#define KALDI_UTIL_SIMPLE_IO_FUNCS_H_\n\n#include <string>\n#include <vector>\n#include \"util/kaldi-io.h\"\n\n// This header contains some utilities for reading some common, simple text\n// formats:integers in files, one per line, and integers in files, possibly\n// multiple per line. these are not really fully native Kaldi formats; they are\n// mostly for small files that might be generated by scripts, and can be read\n// all at one time. for longer files of this type, we would probably use the\n// Table code.\n\nnamespace kaldi {\n\n/// WriteToList attempts to write this list of integers, one per line,\n/// to the given file, in text format.\n/// returns true if succeeded.\nbool WriteIntegerVectorSimple(const std::string &wxfilename,\n                              const std::vector<int32> &v);\n\n/// ReadFromList attempts to read this list of integers, one per line,\n/// from the given file, in text format.\n/// returns true if succeeded.\nbool ReadIntegerVectorSimple(const std::string &rxfilename,\n                             std::vector<int32> *v);\n\n// This is a file format like:\n// 1 2\n// 3\n//\n// 4 5 6\n// etc.\nbool WriteIntegerVectorVectorSimple(const std::string &wxfilename,\n                                    const std::vector<std::vector<int32> > &v);\n\nbool ReadIntegerVectorVectorSimple(const std::string &rxfilename,\n                                   std::vector<std::vector<int32> > *v);\n\n\n}  // end namespace kaldi.\n\n\n#endif  // KALDI_UTIL_SIMPLE_IO_FUNCS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/simple-options.cc",
    "content": "// util/simple-options.cc\n\n// Copyright 2013  Tanel Alumae, Tallinn University of Technology\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"util/simple-options.h\"\n\n\nnamespace kaldi {\n\nvoid SimpleOptions::Register(const std::string &name,\n                             bool *value,\n                             const std::string &doc) {\n  bool_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kBool)));\n}\n\nvoid SimpleOptions::Register(const std::string &name,\n                             int32 *value,\n                             const std::string &doc) {\n  int_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kInt32)));\n}\n\nvoid SimpleOptions::Register(const std::string &name,\n                             uint32 *value,\n                             const std::string &doc) {\n  uint_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kUint32)));\n}\n\nvoid SimpleOptions::Register(const std::string &name,\n                             float *value,\n                             const std::string &doc) {\n  float_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kFloat)));\n}\n\nvoid SimpleOptions::Register(const std::string &name,\n                             double *value,\n                             const std::string &doc) {\n  double_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kDouble)));\n}\n\nvoid SimpleOptions::Register(const std::string &name,\n                             std::string *value,\n                             const std::string &doc) {\n  string_map_[name] = value;\n  option_info_list_.push_back(std::make_pair(name, OptionInfo(doc, kString)));\n}\n\ntemplate<typename T>\nstatic bool SetOptionImpl(const std::string &key, const T &value,\n                          std::map<std::string, T*> &some_map) {\n  if (some_map.end() != some_map.find(key)) {\n    *(some_map[key]) = value;\n    return true;\n  }\n  return false;\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const bool &value) {\n  return SetOptionImpl(key, value, bool_map_);\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const int32 &value) {\n  if (!SetOptionImpl(key, value, int_map_)) {\n    if (!SetOptionImpl(key, static_cast<uint32>(value), uint_map_)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const uint32 &value) {\n  if (!SetOptionImpl(key, value, uint_map_)) {\n    if (!SetOptionImpl(key, static_cast<int32>(value), int_map_)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const float &value) {\n  if (!SetOptionImpl(key, value, float_map_)) {\n    if (!SetOptionImpl(key, static_cast<double>(value), double_map_)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const double &value) {\n  if (!SetOptionImpl(key, value, double_map_)) {\n    if (!SetOptionImpl(key, static_cast<float>(value), float_map_)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool SimpleOptions::SetOption(const std::string &key,\n                              const std::string &value) {\n  return SetOptionImpl(key, value, string_map_);\n}\n\nbool SimpleOptions::SetOption(const std::string &key, const char *value) {\n  std::string str_value = std::string(value);\n  return SetOptionImpl(key, str_value, string_map_);\n}\n\n\ntemplate<typename T>\nstatic bool GetOptionImpl(const std::string &key, T *value,\n                          std::map<std::string, T*> &some_map) {\n  typename std::map<std::string, T*>::iterator it  = some_map.find(key);\n  if (it != some_map.end()) {\n    *value = *(it->second);\n    return true;\n  }\n  return false;\n}\n\nbool SimpleOptions::GetOption(const std::string &key, bool *value) {\n  return GetOptionImpl(key, value, bool_map_);\n}\n\nbool SimpleOptions::GetOption(const std::string &key, int32 *value) {\n  return GetOptionImpl(key, value, int_map_);\n}\n\nbool SimpleOptions::GetOption(const std::string &key, uint32 *value) {\n  return GetOptionImpl(key, value, uint_map_);\n}\n\nbool SimpleOptions::GetOption(const std::string &key, float *value) {\n  return GetOptionImpl(key, value, float_map_);\n}\n\nbool SimpleOptions::GetOption(const std::string &key, double *value) {\n  return GetOptionImpl(key, value, double_map_);\n}\n\nbool SimpleOptions::GetOption(const std::string &key, std::string *value) {\n  return GetOptionImpl(key, value, string_map_);\n}\n\nstd::vector<std::pair<std::string, SimpleOptions::OptionInfo> >\nSimpleOptions::GetOptionInfoList() {\n  return option_info_list_;\n}\n\nbool SimpleOptions::GetOptionType(const std::string &key, OptionType *type) {\n  for (std::vector <std::pair<std::string,\n      OptionInfo> >::iterator dx = option_info_list_.begin();\n      dx != option_info_list_.end(); dx++) {\n    std::pair<std::string, SimpleOptions::OptionInfo> info_pair = (*dx);\n    if (info_pair.first == key) {\n      *type = info_pair.second.type;\n      return true;\n    }\n  }\n  return false;\n}\n\n\n\n}  // namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/simple-options.h",
    "content": "// util/simple-options.h\n\n// Copyright 2013  Tanel Alumae, Tallinn University of Technology\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_SIMPLE_OPTIONS_H_\n#define KALDI_UTIL_SIMPLE_OPTIONS_H_\n\n#include <map>\n#include <string>\n#include <vector>\n\n#include \"base/kaldi-common.h\"\n#include \"util/options-itf.h\"\n\nnamespace kaldi {\n\n\n/// The class SimpleOptions is an implementation of OptionsItf that allows\n/// setting and getting option values programmatically, i.e., via getter\n/// and setter methods. It doesn't provide any command line parsing\n/// functionality.\n/// The class ParseOptions should be used for command-line options.\nclass SimpleOptions : public OptionsItf {\n public:\n  SimpleOptions() {\n  }\n\n  virtual ~SimpleOptions() {\n  }\n\n  // Methods from the interface\n  void Register(const std::string &name, bool *ptr, const std::string &doc);\n  void Register(const std::string &name, int32 *ptr, const std::string &doc);\n  void Register(const std::string &name, uint32 *ptr, const std::string &doc);\n  void Register(const std::string &name, float *ptr, const std::string &doc);\n  void Register(const std::string &name, double *ptr, const std::string &doc);\n  void Register(const std::string &name, std::string *ptr,\n                const std::string &doc);\n\n  // set option with the specified key, return true if successful\n  bool SetOption(const std::string &key, const bool &value);\n  bool SetOption(const std::string &key, const int32 &value);\n  bool SetOption(const std::string &key, const uint32 &value);\n  bool SetOption(const std::string &key, const float &value);\n  bool SetOption(const std::string &key, const double &value);\n  bool SetOption(const std::string &key, const std::string &value);\n  bool SetOption(const std::string &key, const char* value);\n\n  // get option with the specified key and put to 'value',\n  // return true if successful\n  bool GetOption(const std::string &key, bool *value);\n  bool GetOption(const std::string &key, int32 *value);\n  bool GetOption(const std::string &key, uint32 *value);\n  bool GetOption(const std::string &key, float *value);\n  bool GetOption(const std::string &key, double *value);\n  bool GetOption(const std::string &key, std::string *value);\n\n  enum OptionType {\n    kBool,\n    kInt32,\n    kUint32,\n    kFloat,\n    kDouble,\n    kString\n  };\n\n  struct OptionInfo {\n    OptionInfo(const std::string &doc, OptionType type) :\n      doc(doc), type(type) {\n    }\n    std::string doc;\n    OptionType type;\n  };\n\n  std::vector<std::pair<std::string, OptionInfo> > GetOptionInfoList();\n\n  /*\n   * Puts the type of the option with name 'key' in the argument 'type'.\n   * Return true if such option is found, false otherwise.\n   */\n  bool GetOptionType(const std::string &key, OptionType *type);\n\n private:\n\n  std::vector<std::pair<std::string, OptionInfo> > option_info_list_;\n\n  // maps for option variables\n  std::map<std::string, bool*> bool_map_;\n  std::map<std::string, int32*> int_map_;\n  std::map<std::string, uint32*> uint_map_;\n  std::map<std::string, float*> float_map_;\n  std::map<std::string, double*> double_map_;\n  std::map<std::string, std::string*> string_map_;\n};\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_SIMPLE_OPTIONS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/stl-utils.h",
    "content": "// util/stl-utils.h\n\n// Copyright 2009-2011  Microsoft Corporation;  Saarland University\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_STL_UTILS_H_\n#define KALDI_UTIL_STL_UTILS_H_\n\n#include <unordered_map>\n#include <unordered_set>\nusing std::unordered_map;\nusing std::unordered_set;\n\n#include <algorithm>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n\n/// Sorts and uniq's (removes duplicates) from a vector.\ntemplate<typename T>\ninline void SortAndUniq(std::vector<T> *vec) {\n  std::sort(vec->begin(), vec->end());\n  vec->erase(std::unique(vec->begin(), vec->end()), vec->end());\n}\n\n\n/// Returns true if the vector is sorted.\ntemplate<typename T>\ninline bool IsSorted(const std::vector<T> &vec) {\n  typename std::vector<T>::const_iterator iter = vec.begin(), end = vec.end();\n  if (iter == end) return true;\n  while (1) {\n    typename std::vector<T>::const_iterator next_iter = iter;\n    ++next_iter;\n    if (next_iter == end) return true;  // end of loop and nothing out of order\n    if (*next_iter < *iter) return false;\n    iter = next_iter;\n  }\n}\n\n\n/// Returns true if the vector is sorted and contains each element\n/// only once.\ntemplate<typename T>\ninline bool IsSortedAndUniq(const std::vector<T> &vec) {\n  typename std::vector<T>::const_iterator iter = vec.begin(), end = vec.end();\n  if (iter == end) return true;\n  while (1) {\n    typename std::vector<T>::const_iterator next_iter = iter;\n    ++next_iter;\n    if (next_iter == end) return true;  // end of loop and nothing out of order\n    if (*next_iter <= *iter) return false;\n    iter = next_iter;\n  }\n}\n\n\n/// Removes duplicate elements from a sorted list.\ntemplate<typename T>\ninline void Uniq(std::vector<T> *vec) {  // must be already sorted.\n  KALDI_PARANOID_ASSERT(IsSorted(*vec));\n  KALDI_ASSERT(vec);\n  vec->erase(std::unique(vec->begin(), vec->end()), vec->end());\n}\n\n/// Copies the elements of a set to a vector.\ntemplate<class T>\nvoid CopySetToVector(const std::set<T> &s, std::vector<T> *v) {\n  // copies members of s into v, in sorted order from lowest to highest\n  // (because the set was in sorted order).\n  KALDI_ASSERT(v != NULL);\n  v->resize(s.size());\n  typename std::set<T>::const_iterator siter = s.begin(), send = s.end();\n  typename std::vector<T>::iterator viter = v->begin();\n  for (; siter != send; ++siter, ++viter) {\n    *viter = *siter;\n  }\n}\n\ntemplate<class T>\nvoid CopySetToVector(const unordered_set<T> &s, std::vector<T> *v) {\n  KALDI_ASSERT(v != NULL);\n  v->resize(s.size());\n  typename unordered_set<T>::const_iterator siter = s.begin(), send = s.end();\n  typename std::vector<T>::iterator viter = v->begin();\n  for (; siter != send; ++siter, ++viter) {\n    *viter = *siter;\n  }\n}\n\n\n/// Copies the (key, value) pairs in a map to a vector of pairs.\ntemplate<class A, class B>\nvoid CopyMapToVector(const std::map<A, B> &m,\n                     std::vector<std::pair<A, B> > *v) {\n  KALDI_ASSERT(v != NULL);\n  v->resize(m.size());\n  typename std::map<A, B>::const_iterator miter = m.begin(), mend = m.end();\n  typename std::vector<std::pair<A, B> >::iterator viter = v->begin();\n  for (; miter != mend; ++miter, ++viter) {\n    *viter = std::make_pair(miter->first, miter->second);\n    // do it like this because of const casting.\n  }\n}\n\n/// Copies the keys in a map to a vector.\ntemplate<class A, class B>\nvoid CopyMapKeysToVector(const std::map<A, B> &m, std::vector<A> *v) {\n  KALDI_ASSERT(v != NULL);\n  v->resize(m.size());\n  typename std::map<A, B>::const_iterator miter = m.begin(), mend = m.end();\n  typename std::vector<A>::iterator viter = v->begin();\n  for (; miter != mend; ++miter, ++viter) {\n    *viter = miter->first;\n  }\n}\n\n/// Copies the values in a map to a vector.\ntemplate<class A, class B>\nvoid CopyMapValuesToVector(const std::map<A, B> &m, std::vector<B> *v) {\n  KALDI_ASSERT(v != NULL);\n  v->resize(m.size());\n  typename std::map<A, B>::const_iterator miter = m.begin(), mend = m.end();\n  typename std::vector<B>::iterator viter = v->begin();\n  for (; miter != mend; ++miter, ++viter) {\n    *viter = miter->second;\n  }\n}\n\n/// Copies the keys in a map to a set.\ntemplate<class A, class B>\nvoid CopyMapKeysToSet(const std::map<A, B> &m, std::set<A> *s) {\n  KALDI_ASSERT(s != NULL);\n  s->clear();\n  typename std::map<A, B>::const_iterator miter = m.begin(), mend = m.end();\n  for (; miter != mend; ++miter) {\n    s->insert(s->end(), miter->first);\n  }\n}\n\n/// Copies the values in a map to a set.\ntemplate<class A, class B>\nvoid CopyMapValuesToSet(const std::map<A, B> &m, std::set<B> *s) {\n  KALDI_ASSERT(s != NULL);\n  s->clear();\n  typename std::map<A, B>::const_iterator miter = m.begin(), mend = m.end();\n  for (; miter != mend; ++miter)\n    s->insert(s->end(), miter->second);\n}\n\n\n/// Copies the contents of a vector to a set.\ntemplate<class A>\nvoid CopyVectorToSet(const std::vector<A> &v, std::set<A> *s) {\n  KALDI_ASSERT(s != NULL);\n  s->clear();\n  typename std::vector<A>::const_iterator iter = v.begin(), end = v.end();\n  for (; iter != end; ++iter)\n    s->insert(s->end(), *iter);\n  // s->end() is a hint in case v was sorted.  will work regardless.\n}\n\n/// Deletes any non-NULL pointers in the vector v, and sets\n/// the corresponding entries of v to NULL\ntemplate<class A>\nvoid DeletePointers(std::vector<A*> *v) {\n  KALDI_ASSERT(v != NULL);\n  typename std::vector<A*>::iterator iter = v->begin(), end = v->end();\n  for (; iter != end; ++iter) {\n    if (*iter != NULL) {\n      delete *iter;\n      *iter = NULL;  // set to NULL for extra safety.\n    }\n  }\n}\n\n/// Returns true if the vector of pointers contains NULL pointers.\ntemplate<class A>\nbool ContainsNullPointers(const std::vector<A*> &v) {\n  typename std::vector<A*>::const_iterator iter = v.begin(), end = v.end();\n  for (; iter != end; ++iter)\n    if (*iter == static_cast<A*> (NULL)) return true;\n  return false;\n}\n\n/// Copies the contents a vector of one type to a vector\n/// of another type.\ntemplate<typename A, typename B>\nvoid CopyVectorToVector(const std::vector<A> &vec_in, std::vector<B> *vec_out) {\n  KALDI_ASSERT(vec_out != NULL);\n  vec_out->resize(vec_in.size());\n  for (size_t i = 0; i < vec_in.size(); i++)\n    (*vec_out)[i] = static_cast<B> (vec_in[i]);\n}\n\n/// A hashing function-object for vectors.\ntemplate<typename Int>\nstruct VectorHasher {  // hashing function for vector<Int>.\n  size_t operator()(const std::vector<Int> &x) const noexcept {\n    size_t ans = 0;\n    typename std::vector<Int>::const_iterator iter = x.begin(), end = x.end();\n    for (; iter != end; ++iter) {\n      ans *= kPrime;\n      ans += *iter;\n    }\n    return ans;\n  }\n  VectorHasher() {  // Check we're instantiated with an integer type.\n    KALDI_ASSERT_IS_INTEGER_TYPE(Int);\n  }\n private:\n  static const int kPrime = 7853;\n};\n\n/// A hashing function-object for pairs of ints\ntemplate<typename Int1, typename Int2 = Int1>\nstruct PairHasher {  // hashing function for pair<int>\n  size_t operator()(const std::pair<Int1, Int2> &x) const noexcept {\n    // 7853 was chosen at random from a list of primes.\n    return x.first + x.second * 7853;\n  }\n  PairHasher() {  // Check we're instantiated with an integer type.\n    KALDI_ASSERT_IS_INTEGER_TYPE(Int1);\n    KALDI_ASSERT_IS_INTEGER_TYPE(Int2);\n  }\n};\n\n\n/// A hashing function object for strings.\nstruct StringHasher {  // hashing function for std::string\n  size_t operator()(const std::string &str) const noexcept {\n    size_t ans = 0, len = str.length();\n    const char *c = str.c_str(), *end = c + len;\n    for (; c != end; c++) {\n      ans *= kPrime;\n      ans += *c;\n    }\n    return ans;\n  }\n private:\n  static const int kPrime = 7853;\n};\n\n/// Reverses the contents of a vector.\ntemplate<typename T>\ninline void ReverseVector(std::vector<T> *vec) {\n  KALDI_ASSERT(vec != NULL);\n  size_t sz = vec->size();\n  for (size_t i = 0; i < sz/2; i++)\n    std::swap( (*vec)[i], (*vec)[sz-1-i]);\n}\n\n\n/// Comparator object for pairs that compares only the first pair.\ntemplate<class A, class B>\nstruct CompareFirstMemberOfPair {\n  inline bool operator() (const std::pair<A, B> &p1,\n                          const std::pair<A, B> &p2) {\n    return p1.first < p2.first;\n  }\n};\n\n/// For a vector of pair<I, F> where I is an integer and F a floating-point or\n/// integer type, this function sorts a vector of type vector<pair<I, F> > on\n/// the I value and then merges elements with equal I values, summing these over\n/// the F component and then removing any F component with zero value.  This\n/// is for where the vector of pairs represents a map from the integer to float\n/// component, with an \"adding\" type of semantics for combining the elements.\ntemplate<typename I, typename F>\ninline void MergePairVectorSumming(std::vector<std::pair<I, F> > *vec) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  CompareFirstMemberOfPair<I, F> c;\n  std::sort(vec->begin(), vec->end(), c);  // sort on 1st element.\n  typename std::vector<std::pair<I, F> >::iterator out = vec->begin(),\n      in = vec->begin(), end = vec->end();\n  // special case: while there is nothing to be changed, skip over\n  // initial input (avoids unnecessary copying).\n  while (in + 1 < end && in[0].first != in[1].first && in[0].second != 0.0) {\n    in++;\n    out++;\n  }\n  while (in < end) {\n    // We reach this point only at the first element of\n    // each stretch of identical .first elements.\n    *out = *in;\n    ++in;\n    while (in < end && in->first == out->first) {\n      out->second += in->second;  // this is the merge operation.\n      ++in;\n    }\n    if (out->second != static_cast<F>(0))  // Don't keep zero elements.\n      out++;\n  }\n  vec->erase(out, end);\n}\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_STL_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/table-types.h",
    "content": "// util/table-types.h\n\n// Copyright 2009-2011     Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n\n#ifndef KALDI_UTIL_TABLE_TYPES_H_\n#define KALDI_UTIL_TABLE_TYPES_H_\n#include \"base/kaldi-common.h\"\n#include \"util/kaldi-table.h\"\n#include \"util/kaldi-holder.h\"\n#include \"matrix/kaldi-matrix.h\"\n#include \"matrix/kaldi-vector.h\"\n\nnamespace kaldi {\n\n// This header defines typedefs that are specific instantiations of\n// the Table types.\n\n/// \\addtogroup table_types\n/// @{\n\ntypedef TableWriter<KaldiObjectHolder<Matrix<BaseFloat> > >\n                    BaseFloatMatrixWriter;\ntypedef SequentialTableReader<KaldiObjectHolder<Matrix<BaseFloat> > >\n                             SequentialBaseFloatMatrixReader;\ntypedef RandomAccessTableReader<KaldiObjectHolder<Matrix<BaseFloat> > >\n                                RandomAccessBaseFloatMatrixReader;\ntypedef RandomAccessTableReaderMapped<KaldiObjectHolder<Matrix<BaseFloat> > >\n                                      RandomAccessBaseFloatMatrixReaderMapped;\n\ntypedef TableWriter<KaldiObjectHolder<Matrix<double> > >\n                                      DoubleMatrixWriter;\ntypedef SequentialTableReader<KaldiObjectHolder<Matrix<double> > >\n                              SequentialDoubleMatrixReader;\ntypedef RandomAccessTableReader<KaldiObjectHolder<Matrix<double> > >\n                                RandomAccessDoubleMatrixReader;\ntypedef RandomAccessTableReaderMapped<KaldiObjectHolder<Matrix<double> > >\n                                      RandomAccessDoubleMatrixReaderMapped;\n\n//typedef TableWriter<KaldiObjectHolder<CompressedMatrix> >\n                                      //CompressedMatrixWriter;\n\ntypedef TableWriter<KaldiObjectHolder<Vector<BaseFloat> > >\n                                      BaseFloatVectorWriter;\ntypedef SequentialTableReader<KaldiObjectHolder<Vector<BaseFloat> > >\n                              SequentialBaseFloatVectorReader;\ntypedef RandomAccessTableReader<KaldiObjectHolder<Vector<BaseFloat> > >\n                                RandomAccessBaseFloatVectorReader;\ntypedef RandomAccessTableReaderMapped<KaldiObjectHolder<Vector<BaseFloat> > >\n                                      RandomAccessBaseFloatVectorReaderMapped;\n\ntypedef TableWriter<KaldiObjectHolder<Vector<double> > >\n                                      DoubleVectorWriter;\ntypedef SequentialTableReader<KaldiObjectHolder<Vector<double> > >\n                              SequentialDoubleVectorReader;\ntypedef RandomAccessTableReader<KaldiObjectHolder<Vector<double> > >\n                                RandomAccessDoubleVectorReader;\n\n//typedef TableWriter<KaldiObjectHolder<CuMatrix<BaseFloat> > >\n                                      //BaseFloatCuMatrixWriter;\n//typedef SequentialTableReader<KaldiObjectHolder<CuMatrix<BaseFloat> > >\n                              //SequentialBaseFloatCuMatrixReader;\n//typedef RandomAccessTableReader<KaldiObjectHolder<CuMatrix<BaseFloat> > >\n                                //RandomAccessBaseFloatCuMatrixReader;\n//typedef RandomAccessTableReaderMapped<KaldiObjectHolder<CuMatrix<BaseFloat> > >\n                                      //RandomAccessBaseFloatCuMatrixReaderMapped;\n\n//typedef TableWriter<KaldiObjectHolder<CuMatrix<double> > >\n                                      //DoubleCuMatrixWriter;\n//typedef SequentialTableReader<KaldiObjectHolder<CuMatrix<double> > >\n                              //SequentialDoubleCuMatrixReader;\n//typedef RandomAccessTableReader<KaldiObjectHolder<CuMatrix<double> > >\n                                //RandomAccessDoubleCuMatrixReader;\n//typedef RandomAccessTableReaderMapped<KaldiObjectHolder<CuMatrix<double> > >\n                                      //RandomAccessDoubleCuMatrixReaderMapped;\n\n//typedef TableWriter<KaldiObjectHolder<CuVector<BaseFloat> > >\n                    //BaseFloatCuVectorWriter;\n//typedef SequentialTableReader<KaldiObjectHolder<CuVector<BaseFloat> > >\n                              //SequentialBaseFloatCuVectorReader;\n//typedef RandomAccessTableReader<KaldiObjectHolder<CuVector<BaseFloat> > >\n                                //RandomAccessBaseFloatCuVectorReader;\n//typedef RandomAccessTableReaderMapped<KaldiObjectHolder<CuVector<BaseFloat> > >\n                                      //RandomAccessBaseFloatCuVectorReaderMapped;\n\n//typedef TableWriter<KaldiObjectHolder<CuVector<double> > >\n                    //DoubleCuVectorWriter;\n//typedef SequentialTableReader<KaldiObjectHolder<CuVector<double> > >\n                              //SequentialDoubleCuVectorReader;\n//typedef RandomAccessTableReader<KaldiObjectHolder<CuVector<double> > >\n                                //RandomAccessDoubleCuVectorReader;\n\n\ntypedef TableWriter<BasicHolder<int32> >  Int32Writer;\ntypedef SequentialTableReader<BasicHolder<int32> >  SequentialInt32Reader;\ntypedef RandomAccessTableReader<BasicHolder<int32> >  RandomAccessInt32Reader;\n\ntypedef TableWriter<BasicVectorHolder<int32> >  Int32VectorWriter;\ntypedef SequentialTableReader<BasicVectorHolder<int32> >\n                              SequentialInt32VectorReader;\ntypedef RandomAccessTableReader<BasicVectorHolder<int32> >\n                                RandomAccessInt32VectorReader;\n\ntypedef TableWriter<BasicVectorVectorHolder<int32> >  Int32VectorVectorWriter;\ntypedef SequentialTableReader<BasicVectorVectorHolder<int32> >\n                              SequentialInt32VectorVectorReader;\ntypedef RandomAccessTableReader<BasicVectorVectorHolder<int32> >\n                                RandomAccessInt32VectorVectorReader;\n\ntypedef TableWriter<BasicPairVectorHolder<int32> >  Int32PairVectorWriter;\ntypedef SequentialTableReader<BasicPairVectorHolder<int32> >\n                              SequentialInt32PairVectorReader;\ntypedef RandomAccessTableReader<BasicPairVectorHolder<int32> >\n                                RandomAccessInt32PairVectorReader;\n\ntypedef TableWriter<BasicPairVectorHolder<BaseFloat> >\n                    BaseFloatPairVectorWriter;\ntypedef SequentialTableReader<BasicPairVectorHolder<BaseFloat> >\n                              SequentialBaseFloatPairVectorReader;\ntypedef RandomAccessTableReader<BasicPairVectorHolder<BaseFloat> >\n                                RandomAccessBaseFloatPairVectorReader;\n\ntypedef TableWriter<BasicHolder<BaseFloat> >  BaseFloatWriter;\ntypedef SequentialTableReader<BasicHolder<BaseFloat> >\n                              SequentialBaseFloatReader;\ntypedef RandomAccessTableReader<BasicHolder<BaseFloat> >\n                                RandomAccessBaseFloatReader;\ntypedef RandomAccessTableReaderMapped<BasicHolder<BaseFloat> >\n                                      RandomAccessBaseFloatReaderMapped;\n\ntypedef TableWriter<BasicHolder<double> >  DoubleWriter;\ntypedef SequentialTableReader<BasicHolder<double> >  SequentialDoubleReader;\ntypedef RandomAccessTableReader<BasicHolder<double> >  RandomAccessDoubleReader;\n\ntypedef TableWriter<BasicHolder<bool> >  BoolWriter;\ntypedef SequentialTableReader<BasicHolder<bool> >  SequentialBoolReader;\ntypedef RandomAccessTableReader<BasicHolder<bool> >  RandomAccessBoolReader;\n\n/// TokenWriter is a writer specialized for std::string where the strings\n/// are nonempty and whitespace-free.   T == std::string\ntypedef TableWriter<TokenHolder> TokenWriter;\ntypedef SequentialTableReader<TokenHolder> SequentialTokenReader;\ntypedef RandomAccessTableReader<TokenHolder> RandomAccessTokenReader;\n\n\n/// TokenVectorWriter is a writer specialized for sequences of\n/// std::string where the strings are nonempty and whitespace-free.\n/// T == std::vector<std::string>\ntypedef TableWriter<TokenVectorHolder> TokenVectorWriter;\n// Ditto for SequentialTokenVectorReader.\ntypedef SequentialTableReader<TokenVectorHolder> SequentialTokenVectorReader;\ntypedef RandomAccessTableReader<TokenVectorHolder>\n                                RandomAccessTokenVectorReader;\n\n\n//typedef TableWriter<KaldiObjectHolder<GeneralMatrix> >\n//                                      GeneralMatrixWriter;\n//typedef SequentialTableReader<KaldiObjectHolder<GeneralMatrix> >\n //                             SequentialGeneralMatrixReader;\n//typedef RandomAccessTableReader<KaldiObjectHolder<GeneralMatrix> >\n //                               RandomAccessGeneralMatrixReader;\n//typedef RandomAccessTableReaderMapped<KaldiObjectHolder<GeneralMatrix> >\n //                                     RandomAccessGeneralMatrixReaderMapped;\n\n\n\n/// @}\n\n// Note: for FST reader/writer, see ../fstext/fstext-utils.h\n// [not done yet].\n\n}  // end namespace kaldi\n\n\n\n#endif  // KALDI_UTIL_TABLE_TYPES_H_\n"
  },
  {
    "path": "runtime/engine/kaldi/util/text-utils.cc",
    "content": "// util/text-utils.cc\n\n// Copyright 2009-2011  Saarland University;  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//  http://www.apache.org/licenses/LICENSE-2.0\n\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"util/text-utils.h\"\n#include <limits>\n#include <map>\n#include <algorithm>\n#include \"base/kaldi-common.h\"\n\nnamespace kaldi {\n\n\ntemplate<class F>\nbool SplitStringToFloats(const std::string &full,\n                         const char *delim,\n                         bool omit_empty_strings,  // typically false\n                         std::vector<F> *out) {\n  KALDI_ASSERT(out != NULL);\n  if (*(full.c_str()) == '\\0') {\n    out->clear();\n    return true;\n  }\n  std::vector<std::string> split;\n  SplitStringToVector(full, delim, omit_empty_strings, &split);\n  out->resize(split.size());\n  for (size_t i = 0; i < split.size(); i++) {\n    F f = 0;\n    if (!ConvertStringToReal(split[i], &f))\n      return false;\n    (*out)[i] = f;\n  }\n  return true;\n}\n\n// Instantiate the template above for float and double.\ntemplate\nbool SplitStringToFloats(const std::string &full,\n                         const char *delim,\n                         bool omit_empty_strings,\n                         std::vector<float> *out);\ntemplate\nbool SplitStringToFloats(const std::string &full,\n                         const char *delim,\n                         bool omit_empty_strings,\n                         std::vector<double> *out);\n\nvoid SplitStringToVector(const std::string &full, const char *delim,\n                         bool omit_empty_strings,\n                         std::vector<std::string> *out) {\n  size_t start = 0, found = 0, end = full.size();\n  out->clear();\n  while (found != std::string::npos) {\n    found = full.find_first_of(delim, start);\n    // start != end condition is for when the delimiter is at the end\n    if (!omit_empty_strings || (found != start && start != end))\n      out->push_back(full.substr(start, found - start));\n    start = found + 1;\n  }\n}\n\nvoid JoinVectorToString(const std::vector<std::string> &vec_in,\n                        const char *delim, bool omit_empty_strings,\n                        std::string *str_out) {\n  std::string tmp_str;\n  for (size_t i = 0; i < vec_in.size(); i++) {\n    if (!omit_empty_strings || !vec_in[i].empty()) {\n      tmp_str.append(vec_in[i]);\n      if (i < vec_in.size() - 1)\n        if (!omit_empty_strings || !vec_in[i+1].empty())\n          tmp_str.append(delim);\n    }\n  }\n  str_out->swap(tmp_str);\n}\n\nvoid Trim(std::string *str) {\n  const char *white_chars = \" \\t\\n\\r\\f\\v\";\n\n  std::string::size_type pos = str->find_last_not_of(white_chars);\n  if (pos != std::string::npos)  {\n    str->erase(pos + 1);\n    pos = str->find_first_not_of(white_chars);\n    if (pos != std::string::npos) str->erase(0, pos);\n  } else {\n    str->erase(str->begin(), str->end());\n  }\n}\n\nbool IsToken(const std::string &token) {\n  size_t l = token.length();\n  if (l == 0) return false;\n  for (size_t i = 0; i < l; i++) {\n    unsigned char c = token[i];\n    if ((!isprint(c) || isspace(c)) && (isascii(c) || c == (unsigned char)255))\n      return false;\n    // The \"&& (isascii(c) || c == 255)\" was added so that we won't reject\n    // non-ASCII characters such as French characters with accents [except for\n    // 255 which is \"nbsp\", a form of space].\n  }\n  return true;\n}\n\n\nvoid SplitStringOnFirstSpace(const std::string &str,\n                             std::string *first,\n                             std::string *rest) {\n  const char *white_chars = \" \\t\\n\\r\\f\\v\";\n  typedef std::string::size_type I;\n  const I npos = std::string::npos;\n  I first_nonwhite = str.find_first_not_of(white_chars);\n  if (first_nonwhite == npos) {\n    first->clear();\n    rest->clear();\n    return;\n  }\n  // next_white is first whitespace after first nonwhitespace.\n  I next_white = str.find_first_of(white_chars, first_nonwhite);\n\n  if (next_white == npos) {  // no more whitespace...\n    *first = std::string(str, first_nonwhite);\n    rest->clear();\n    return;\n  }\n  I next_nonwhite = str.find_first_not_of(white_chars, next_white);\n  if (next_nonwhite == npos) {\n    *first = std::string(str, first_nonwhite, next_white-first_nonwhite);\n    rest->clear();\n    return;\n  }\n\n  I last_nonwhite = str.find_last_not_of(white_chars);\n  KALDI_ASSERT(last_nonwhite != npos);  // or coding error.\n\n  *first = std::string(str, first_nonwhite, next_white-first_nonwhite);\n  *rest = std::string(str, next_nonwhite, last_nonwhite+1-next_nonwhite);\n}\n\nbool IsLine(const std::string &line) {\n  if (line.find('\\n') != std::string::npos) return false;\n  if (line.empty()) return true;\n  if (isspace(*(line.begin()))) return false;\n  if (isspace(*(line.rbegin()))) return false;\n  std::string::const_iterator iter = line.begin(), end = line.end();\n  for (; iter != end; iter++)\n    if (!isprint(*iter)) return false;\n  return true;\n}\n\ntemplate <class T>\nclass NumberIstream{\n public:\n  explicit NumberIstream(std::istream &i) : in_(i) {}\n\n  NumberIstream & operator >> (T &x) {\n    if (!in_.good()) return *this;\n    in_ >> x;\n    if (!in_.fail() && RemainderIsOnlySpaces()) return *this;\n    return ParseOnFail(&x);\n  }\n\n private:\n  std::istream &in_;\n\n  bool RemainderIsOnlySpaces() {\n    if (in_.tellg() != std::istream::pos_type(-1)) {\n      std::string rem;\n      in_ >> rem;\n\n      if (rem.find_first_not_of(' ') != std::string::npos) {\n        // there is not only spaces\n        return false;\n      }\n    }\n\n    in_.clear();\n    return true;\n  }\n\n  NumberIstream & ParseOnFail(T *x) {\n    std::string str;\n    in_.clear();\n    in_.seekg(0);\n    // If the stream is broken even before trying\n    // to read from it or if there are many tokens,\n    // it's pointless to try.\n    if (!(in_ >> str) || !RemainderIsOnlySpaces()) {\n      in_.setstate(std::ios_base::failbit);\n      return *this;\n    }\n\n    std::map<std::string, T> inf_nan_map;\n    // we'll keep just uppercase values.\n    inf_nan_map[\"INF\"] = std::numeric_limits<T>::infinity();\n    inf_nan_map[\"+INF\"] = std::numeric_limits<T>::infinity();\n    inf_nan_map[\"-INF\"] = - std::numeric_limits<T>::infinity();\n    inf_nan_map[\"INFINITY\"] = std::numeric_limits<T>::infinity();\n    inf_nan_map[\"+INFINITY\"] = std::numeric_limits<T>::infinity();\n    inf_nan_map[\"-INFINITY\"] = - std::numeric_limits<T>::infinity();\n    inf_nan_map[\"NAN\"] = std::numeric_limits<T>::quiet_NaN();\n    inf_nan_map[\"+NAN\"] = std::numeric_limits<T>::quiet_NaN();\n    inf_nan_map[\"-NAN\"] = - std::numeric_limits<T>::quiet_NaN();\n    // MSVC\n    inf_nan_map[\"1.#INF\"] = std::numeric_limits<T>::infinity();\n    inf_nan_map[\"-1.#INF\"] = - std::numeric_limits<T>::infinity();\n    inf_nan_map[\"1.#QNAN\"] = std::numeric_limits<T>::quiet_NaN();\n    inf_nan_map[\"-1.#QNAN\"] = - std::numeric_limits<T>::quiet_NaN();\n\n    std::transform(str.begin(), str.end(), str.begin(), ::toupper);\n\n    if (inf_nan_map.find(str) != inf_nan_map.end()) {\n      *x = inf_nan_map[str];\n    } else {\n      in_.setstate(std::ios_base::failbit);\n    }\n\n    return *this;\n  }\n};\n\n\ntemplate <typename T>\nbool ConvertStringToReal(const std::string &str,\n                         T *out) {\n  std::istringstream iss(str);\n\n  NumberIstream<T> i(iss);\n\n  i >> *out;\n\n  if (iss.fail()) {\n    // Number conversion failed.\n    return false;\n  }\n\n  return true;\n}\n\ntemplate\nbool ConvertStringToReal(const std::string &str,\n                         float *out);\ntemplate\nbool ConvertStringToReal(const std::string &str,\n                         double *out);\n\n\n\n/*\n  This function is a helper function of StringsApproxEqual.  It should be\n  thought of as a recursive function-- it was designed that way-- but rather\n  than actually recursing (which would cause problems with stack overflow), we\n  just set the args and return to the start.\n\n  The 'decimal_places_tolerance' argument is just passed in from outside,\n  see the documentation for StringsApproxEqual in text-utils.h to see an\n  explanation.  The argument 'places_into_number' provides some information\n  about the strings 'a' and 'b' that precedes the current pointers.\n  For purposes of this comment, let's define the 'decimal' of a number\n  as the part that comes after the decimal point, e.g. in '99.123',\n  '123' would be the decimal.  If 'places_into_number' is -1, it means\n  we're not currently inside some place like that (i.e. it's not the\n  case that we're pointing to the '1' or the '2' or the '3').\n  If it's 0, then we'd be pointing to the first place after the decimal,\n  '1' in this case.  Note if one of the numbers is shorter than the\n  other, like '99.123' versus '99.1234' and 'a' points to the first '3'\n  while 'b' points to the second '4', 'places_into_number' referes to the\n  shorter of the two, i.e. it would be 2 in this example.\n\n\n */\nbool StringsApproxEqualInternal(const char *a, const char *b,\n                                int32 decimal_places_tolerance,\n                                int32 places_into_number) {\nstart:\n  char ca = *a, cb = *b;\n  if (ca == cb) {\n    if (ca == '\\0') {\n      return true;\n    } else {\n      if (places_into_number >= 0) {\n        if (isdigit(ca)) {\n          places_into_number++;\n        } else {\n          places_into_number = -1;\n        }\n      } else {\n        if (ca == '.') {\n          places_into_number = 0;\n        }\n      }\n      a++;\n      b++;\n      goto start;\n    }\n  } else {\n    if (places_into_number  >= decimal_places_tolerance &&\n        (isdigit(ca) || isdigit(cb))) {\n      // we're potentially willing to accept this difference between the\n      // strings.\n      if (isdigit(ca)) a++;\n      if (isdigit(cb)) b++;\n      // we'll have advanced at least one of the two strings.\n      goto start;\n    } else if (places_into_number >= 0 &&\n               ((ca == '0' && !isdigit(cb)) || (cb == '0' && !isdigit(ca)))) {\n      // this clause is designed to ensure that, for example,\n      // \"0.1\" would count the same as \"0.100001\".\n      if (ca == '0') a++;\n      else b++;\n      places_into_number++;\n      goto start;\n    } else {\n      return false;\n    }\n  }\n\n}\n\n\nbool StringsApproxEqual(const std::string &a,\n                        const std::string &b,\n                        int32 decimal_places_tolerance) {\n  return StringsApproxEqualInternal(a.c_str(), b.c_str(),\n                                    decimal_places_tolerance, -1);\n}\n\n\nbool ConfigLine::ParseLine(const std::string &line) {\n  data_.clear();\n  whole_line_ = line;\n  if (line.size() == 0) return false;   // Empty line\n  size_t pos = 0, size = line.size();\n  while (isspace(line[pos]) && pos < size) pos++;\n  if (pos == size)\n    return false;  // whitespace-only line\n  size_t first_token_start_pos = pos;\n  // first get first_token_.\n  while (!isspace(line[pos]) && pos < size) {\n    if (line[pos] == '=') {\n      // If the first block of non-whitespace looks like \"foo-bar=...\",\n      // then we ignore it: there is no initial token, and FirstToken()\n      // is empty.\n      pos = first_token_start_pos;\n      break;\n    }\n    pos++;\n  }\n  first_token_ = std::string(line, first_token_start_pos, pos - first_token_start_pos);\n  // first_token_ is expected to be either empty or something like\n  // \"component-node\", which actually is a slightly more restrictive set of\n  // strings than IsValidName() checks for this is a convenient way to check it.\n  if (!first_token_.empty() && !IsValidName(first_token_))\n    return false;\n\n  while (pos < size) {\n    if (isspace(line[pos])) {\n      pos++;\n      continue;\n    }\n\n    // OK, at this point we know that we are pointing at nonspace.\n    size_t next_equals_sign = line.find_first_of(\"=\", pos);\n    if (next_equals_sign == pos || next_equals_sign == std::string::npos) {\n      // we're looking for something like 'key=value'.  If there is no equals sign,\n      // or it's not preceded by something, it's a parsing failure.\n      return false;\n    }\n    std::string key(line, pos, next_equals_sign - pos);\n    if (!IsValidName(key)) return false;\n\n    // handle any quotes.  we support key='blah blah' or key=\"foo bar\".\n    // no escaping is supported.\n    if (line[next_equals_sign+1] == '\\'' || line[next_equals_sign+1] == '\"') {\n      char my_quote = line[next_equals_sign+1];\n      size_t next_quote = line.find_first_of(my_quote, next_equals_sign + 2);\n      if (next_quote == std::string::npos) {  // no matching quote was found.\n        KALDI_WARN << \"No matching quote for \" << my_quote << \" in config line '\"\n                   << line << \"'\";\n        return false;\n      } else {\n        std::string value(line, next_equals_sign + 2,\n                          next_quote - next_equals_sign - 2);\n        data_.insert(std::make_pair(key, std::make_pair(value, false)));\n        pos = next_quote + 1;\n        continue;\n      }\n    } else {\n      // we want to be able to parse something like \"... input=Offset(a, -1) foo=bar\":\n      // in general, config values with spaces in them, even without quoting.\n\n      size_t next_next_equals_sign = line.find_first_of(\"=\", next_equals_sign + 1),\n          terminating_space = size;\n\n      if (next_next_equals_sign != std::string::npos) {  // found a later equals sign.\n        size_t preceding_space = line.find_last_of(\" \\t\", next_next_equals_sign);\n        if (preceding_space != std::string::npos &&\n            preceding_space > next_equals_sign)\n          terminating_space = preceding_space;\n      }\n      while (isspace(line[terminating_space - 1]) && terminating_space > 0)\n        terminating_space--;\n\n      std::string value(line, next_equals_sign + 1,\n                        terminating_space - (next_equals_sign + 1));\n      data_.insert(std::make_pair(key, std::make_pair(value, false)));\n      pos = terminating_space;\n    }\n  }\n  return true;\n}\n\nbool ConfigLine::GetValue(const std::string &key, std::string *value) {\n  KALDI_ASSERT(value != NULL);\n  std::map<std::string, std::pair<std::string, bool> >::iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (it->first == key) {\n      *value = (it->second).first;\n      (it->second).second = true;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ConfigLine::GetValue(const std::string &key, BaseFloat *value) {\n  KALDI_ASSERT(value != NULL);\n  std::map<std::string, std::pair<std::string, bool> >::iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (it->first == key) {\n      if (!ConvertStringToReal((it->second).first, value))\n        return false;\n      (it->second).second = true;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ConfigLine::GetValue(const std::string &key, int32 *value) {\n  KALDI_ASSERT(value != NULL);\n  std::map<std::string, std::pair<std::string, bool> >::iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (it->first == key) {\n      if (!ConvertStringToInteger((it->second).first, value))\n        return false;\n      (it->second).second = true;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ConfigLine::GetValue(const std::string &key, std::vector<int32> *value) {\n  KALDI_ASSERT(value != NULL);\n  value->clear();\n  std::map<std::string, std::pair<std::string, bool> >::iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (it->first == key) {\n      if (!SplitStringToIntegers((it->second).first, \":,\", true, value)) {\n        // KALDI_WARN << \"Bad option \" << (it->second).first;\n        return false;\n      }\n      (it->second).second = true;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ConfigLine::GetValue(const std::string &key, bool *value) {\n  KALDI_ASSERT(value != NULL);\n  std::map<std::string, std::pair<std::string, bool> >::iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (it->first == key) {\n      if ((it->second).first.size() == 0) return false;\n      switch (((it->second).first)[0]) {\n        case 'F':\n        case 'f':\n          *value = false;\n          break;\n        case 'T':\n        case 't':\n          *value = true;\n          break;\n        default:\n          return false;\n      }\n      (it->second).second = true;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ConfigLine::HasUnusedValues() const {\n  std::map<std::string, std::pair<std::string, bool> >::const_iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (!(it->second).second) return true;\n  }\n  return false;\n}\n\nstd::string ConfigLine::UnusedValues() const {\n  std::string unused_str;\n  std::map<std::string, std::pair<std::string, bool> >::const_iterator it = data_.begin();\n  for (; it != data_.end(); ++it) {\n    if (!(it->second).second) {\n      if (unused_str == \"\")\n        unused_str = it->first + \"=\" + (it->second).first;\n      else\n        unused_str += \" \" + it->first + \"=\" + (it->second).first;\n    }\n  }\n  return unused_str;\n}\n\n// This is like ExpectToken but for two tokens, and it\n// will either accept token1 and then token2, or just token2.\n// This is useful in Read functions where the first token\n// may already have been consumed.\nvoid ExpectOneOrTwoTokens(std::istream &is, bool binary,\n                          const std::string &token1,\n                          const std::string &token2) {\n  KALDI_ASSERT(token1 != token2);\n  std::string temp;\n  ReadToken(is, binary, &temp);\n  if (temp == token1) {\n    ExpectToken(is, binary, token2);\n  } else {\n    if (temp != token2) {\n      KALDI_ERR << \"Expecting token \" << token1 << \" or \" << token2\n                << \" but got \" << temp;\n    }\n  }\n}\n\n\nbool IsValidName(const std::string &name) {\n  if (name.size() == 0) return false;\n  for (size_t i = 0; i < name.size(); i++) {\n    if (i == 0 && !isalpha(name[i]) && name[i] != '_')\n      return false;\n    if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.')\n      return false;\n  }\n  return true;\n}\n\nvoid ReadConfigLines(std::istream &is,\n                    std::vector<std::string> *lines) {\n  KALDI_ASSERT(lines != NULL);\n  std::string line;\n  while (std::getline(is, line)) {\n    if (line.size() == 0) continue;\n    size_t start = line.find_first_not_of(\" \\t\");\n    size_t end = line.find_first_of('#');\n    if (start == std::string::npos || start == end) continue;\n    end = line.find_last_not_of(\" \\t\", end - 1);\n    KALDI_ASSERT(end >= start);\n    lines->push_back(line.substr(start, end - start + 1));\n  }\n}\n\nvoid ParseConfigLines(const std::vector<std::string> &lines,\n                      std::vector<ConfigLine> *config_lines) {\n  config_lines->resize(lines.size());\n  for (size_t i = 0; i < lines.size(); i++) {\n    bool ret = (*config_lines)[i].ParseLine(lines[i]);\n    if (!ret) {\n      KALDI_ERR << \"Error parsing config line: \" << lines[i];\n    }\n  }\n}\n\n\n}  // end namespace kaldi\n"
  },
  {
    "path": "runtime/engine/kaldi/util/text-utils.h",
    "content": "// util/text-utils.h\n\n// Copyright 2009-2011  Saarland University;  Microsoft Corporation\n\n// See ../../COPYING for clarification regarding multiple authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n// MERCHANTABLITY OR NON-INFRINGEMENT.\n// See the Apache 2 License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef KALDI_UTIL_TEXT_UTILS_H_\n#define KALDI_UTIL_TEXT_UTILS_H_\n\n#include <errno.h>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <vector>\n#include <limits>\n#include \"base/kaldi-common.h\"\n\n\nnamespace kaldi {\n\n/// Split a string using any of the single character delimiters.\n/// If omit_empty_strings == true, the output will contain any\n/// nonempty strings after splitting on any of the\n/// characters in the delimiter.  If omit_empty_strings == false,\n/// the output will contain n+1 strings if there are n characters\n/// in the set \"delim\" within the input string.  In this case\n/// the empty string is split to a single empty string.\nvoid SplitStringToVector(const std::string &full, const char *delim,\n                         bool omit_empty_strings,\n                         std::vector<std::string> *out);\n\n/// Joins the elements of a vector of strings into a single string using\n/// \"delim\" as the delimiter. If omit_empty_strings == true, any empty strings\n/// in the vector are skipped. A vector of empty strings results in an empty\n/// string on the output.\nvoid JoinVectorToString(const std::vector<std::string> &vec_in,\n                        const char *delim, bool omit_empty_strings,\n                        std::string *str_out);\n\n/**\n  \\brief Split a string (e.g. 1:2:3) into a vector of integers.\n\n  \\param [in]  delim  String containing a list of characters, any of which\n                      is allowed as a delimiter.\n  \\param [in] omit_empty_strings If true, empty strings between delimiters are\n                      allowed and will not produce an output integer; if false,\n                      instances of characters in 'delim' that are consecutive or\n                      at the start or end of the string would be an error.\n                      You'll normally want this to be true if 'delim' consists\n                      of spaces, and false otherwise.\n  \\param [out] out   The output list of integers.\n*/\ntemplate<class I>\nbool SplitStringToIntegers(const std::string &full,\n                           const char *delim,\n                           bool omit_empty_strings,  // typically false [but\n                                                     // should probably be true\n                                                     // if \"delim\" is spaces].\n                           std::vector<I> *out) {\n  KALDI_ASSERT(out != NULL);\n  KALDI_ASSERT_IS_INTEGER_TYPE(I);\n  if (*(full.c_str()) == '\\0') {\n    out->clear();\n    return true;\n  }\n  std::vector<std::string> split;\n  SplitStringToVector(full, delim, omit_empty_strings, &split);\n  out->resize(split.size());\n  for (size_t i = 0; i < split.size(); i++) {\n    const char *this_str = split[i].c_str();\n    char *end = NULL;\n    int64 j = 0;\n    j = KALDI_STRTOLL(this_str, &end);\n    if (end == this_str || *end != '\\0') {\n      out->clear();\n      return false;\n    } else {\n      I jI = static_cast<I>(j);\n      if (static_cast<int64>(jI) != j) {\n        // output type cannot fit this integer.\n        out->clear();\n        return false;\n      }\n      (*out)[i] = jI;\n    }\n  }\n  return true;\n}\n\n// This is defined for F = float and double.\ntemplate<class F>\nbool SplitStringToFloats(const std::string &full,\n                         const char *delim,\n                         bool omit_empty_strings,  // typically false\n                         std::vector<F> *out);\n\n\n/// Converts a string into an integer via strtoll and returns false if there was\n/// any kind of problem (i.e. the string was not an integer or contained extra\n/// non-whitespace junk, or the integer was too large to fit into the type it is\n/// being converted into).  Only sets *out if everything was OK and it returns\n/// true.\ntemplate<class Int>\nbool ConvertStringToInteger(const std::string &str,\n                            Int *out) {\n  KALDI_ASSERT_IS_INTEGER_TYPE(Int);\n  const char *this_str = str.c_str();\n  char *end = NULL;\n  errno = 0;\n  int64 i = KALDI_STRTOLL(this_str, &end);\n  if (end != this_str)\n    while (isspace(*end)) end++;\n  if (end == this_str || *end != '\\0' || errno != 0)\n    return false;\n  Int iInt = static_cast<Int>(i);\n  if (static_cast<int64>(iInt) != i ||\n      (i < 0 && !std::numeric_limits<Int>::is_signed)) {\n    return false;\n  }\n  *out = iInt;\n  return true;\n}\n\n\n/// ConvertStringToReal converts a string into either float or double\n/// and returns false if there was any kind of problem (i.e. the string\n/// was not a floating point number or contained extra non-whitespace junk).\n/// Be careful- this function will successfully read inf's or nan's.\ntemplate <typename T>\nbool ConvertStringToReal(const std::string &str,\n                         T *out);\n\n/// Removes the beginning and trailing whitespaces from a string\nvoid Trim(std::string *str);\n\n\n/// Removes leading and trailing white space from the string, then splits on the\n/// first section of whitespace found (if present), putting the part before the\n/// whitespace in \"first\" and the rest in \"rest\".  If there is no such space,\n/// everything that remains after removing leading and trailing whitespace goes\n/// in \"first\".\nvoid SplitStringOnFirstSpace(const std::string &line,\n                             std::string *first,\n                             std::string *rest);\n\n\n/// Returns true if \"token\" is nonempty, and all characters are\n/// printable and whitespace-free.\nbool IsToken(const std::string &token);\n\n\n/// Returns true if \"line\" is free of \\n characters and unprintable\n/// characters, and does not contain leading or trailing whitespace.\nbool IsLine(const std::string &line);\n\n\n\n/**\n   This function returns true when two text strings are approximately equal, and\n   false when they are not.  The definition of 'equal' is normal string\n   equality, except that two substrings like \"0.31134\" and \"0.311341\" would be\n   considered equal.  'decimal_places_tolerance' controls how many digits after\n   the '.' have to match up.\n   E.g. StringsApproxEqual(\"hello 0.23 there\", \"hello 0.24 there\", 2) would\n   return false because there is a difference in the 2nd decimal, but with\n   an argument of 1 it would return true.\n */\nbool StringsApproxEqual(const std::string &a,\n                        const std::string &b,\n                        int32 decimal_places_check = 2);\n\n/**\n   This class is responsible for parsing input like\n    hi-there xx=yyy a=b c empty= f-oo=Append(bar, sss) ba_z=123 bing='a b c' baz=\"a b c d='a b' e\"\n   and giving you access to the fields, in this case\n\n   FirstToken() == \"hi-there\", and key->value pairs:\n\n   xx->yyy, a->\"b c\", empty->\"\", f-oo->\"Append(bar, sss)\", ba_z->\"123\",\n   bing->\"a b c\", baz->\"a b c d='a b' e\"\n\n   The first token is optional, if the line started with a key-value pair then\n   FirstValue() will be empty.\n\n   Note: it can parse value fields with space inside them only if they are free of the '='\n   character.  If values are going to contain the '=' character, you need to quote them\n   with either single or double quotes.\n\n   Key values may contain -_a-zA-Z0-9, but must begin with a-zA-Z_.\n */\nclass ConfigLine {\n public:\n  // Tries to parse the line as a config-file line.  Returns false\n  // if it could not for some reason, e.g. parsing failure.  In most cases\n  // prints no warnings; the user should do this.  Does not expect comments.\n  bool ParseLine(const std::string &line);\n\n  // the GetValue functions are overloaded for various types.  They return true\n  // if the key exists with value that can be converted to that type, and false\n  // otherwise.  They also mark the key-value pair as having been read.  It is\n  // not an error to read values twice.\n  bool GetValue(const std::string &key, std::string *value);\n  bool GetValue(const std::string &key, BaseFloat *value);\n  bool GetValue(const std::string &key, int32 *value);\n  // Values may be separated by \":\" or by \",\".\n  bool GetValue(const std::string &key, std::vector<int32> *value);\n  bool GetValue(const std::string &key, bool *value);\n\n  bool HasUnusedValues() const;\n  /// returns e.g. foo=bar xxx=yyy if foo and xxx were not consumed by one\n  /// of the GetValue() functions.\n  std::string UnusedValues() const;\n\n  const std::string &FirstToken() const { return first_token_; }\n\n  const std::string WholeLine() { return whole_line_; }\n  // use default assignment operator and copy constructor.\n private:\n  std::string whole_line_;\n  // the first token of the line, e.g. if line is\n  // foo-bar baz=bing\n  // then first_token_ would be \"foo-bar\".\n  std::string first_token_;\n\n  // data_ maps from key to (value, is-this-value-consumed?).\n  std::map<std::string, std::pair<std::string, bool> > data_;\n\n};\n\n/// This function is like ExpectToken but for two tokens, and it will either\n/// accept token1 and then token2, or just token2.  This is useful in Read\n/// functions where the first token may already have been consumed.\nvoid ExpectOneOrTwoTokens(std::istream &is, bool binary,\n                          const std::string &token1,\n                          const std::string &token2);\n\n\n/**\n   This function reads in a config file and *appends* its contents to a vector of\n   lines; it is responsible for removing comments (anything after '#') and\n   stripping out any lines that contain only whitespace after comment removal.\n */\nvoid ReadConfigLines(std::istream &is,\n                     std::vector<std::string> *lines);\n\n\n/**\n   This function converts config-lines from a simple sequence of strings\n   as output by ReadConfigLines(), into a sequence of first-tokens and\n   name-value pairs.  The general format is:\n      \"command-type bar=baz xx=yyy\"\n   etc., although there are subtleties as to what exactly is allowed, see\n   documentation for class ConfigLine for details.\n   This function will die if there was a parsing failure.\n */\nvoid ParseConfigLines(const std::vector<std::string> &lines,\n                      std::vector<ConfigLine> *config_lines);\n\n\n/// Returns true if 'name' would be a valid name for a component or node in a\n/// nnet3Nnet.  This is a nonempty string beginning with A-Za-z_, and containing only\n/// '-', '_', '.', A-Z, a-z, or 0-9.\nbool IsValidName(const std::string &name);\n\n}  // namespace kaldi\n\n#endif  // KALDI_UTIL_TEXT_UTILS_H_\n"
  },
  {
    "path": "runtime/engine/vad/CMakeLists.txt",
    "content": "include_directories(${CMAKE_CURRENT_SOURCE_DIR})\n\nadd_subdirectory(nnet)\n\nadd_subdirectory(interface)"
  },
  {
    "path": "runtime/engine/vad/frontend/wav.h",
    "content": "// Copyright (c) 2016 Personal (Binbin Zhang)\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#pragma once\n#include <assert.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <iostream>\n#include <string>\n\nnamespace wav {\n\nstruct WavHeader {\n    char riff[4];  // \"riff\"\n    unsigned int size;\n    char wav[4];  // \"WAVE\"\n    char fmt[4];  // \"fmt \"\n    unsigned int fmt_size;\n    uint16_t format;\n    uint16_t channels;\n    unsigned int sample_rate;\n    unsigned int bytes_per_second;\n    uint16_t block_size;\n    uint16_t bit;\n    char data[4];  // \"data\"\n    unsigned int data_size;\n};\n\nclass WavReader {\n  public:\n    WavReader() : data_(nullptr) {}\n    explicit WavReader(const std::string& filename) { Open(filename); }\n\n    bool Open(const std::string& filename) {\n        FILE* fp = fopen(filename.c_str(), \"rb\");\n        if (NULL == fp) {\n            std::cout << \"Error in read \" << filename;\n            return false;\n        }\n\n        WavHeader header;\n        fread(&header, 1, sizeof(header), fp);\n        if (header.fmt_size < 16) {\n            fprintf(stderr,\n                    \"WaveData: expect PCM format data \"\n                    \"to have fmt chunk of at least size 16.\\n\");\n            return false;\n        } else if (header.fmt_size > 16) {\n            int offset = 44 - 8 + header.fmt_size - 16;\n            fseek(fp, offset, SEEK_SET);\n            fread(header.data, 8, sizeof(char), fp);\n        }\n        // check \"riff\" \"WAVE\" \"fmt \" \"data\"\n\n        // Skip any sub-chunks between \"fmt\" and \"data\".  Usually there will\n        // be a single \"fact\" sub chunk, but on Windows there can also be a\n        // \"list\" sub chunk.\n        while (0 != strncmp(header.data, \"data\", 4)) {\n            // We will just ignore the data in these chunks.\n            fseek(fp, header.data_size, SEEK_CUR);\n            // read next sub chunk\n            fread(header.data, 8, sizeof(char), fp);\n        }\n\n        num_channel_ = header.channels;\n        sample_rate_ = header.sample_rate;\n        bits_per_sample_ = header.bit;\n        int num_data = header.data_size / (bits_per_sample_ / 8);\n        data_ = new float[num_data];  // Create 1-dim array\n        num_samples_ = num_data / num_channel_;\n\n        for (int i = 0; i < num_data; ++i) {\n            switch (bits_per_sample_) {\n                case 8: {\n                    char sample;\n                    fread(&sample, 1, sizeof(char), fp);\n                    data_[i] = static_cast<float>(sample);\n                    break;\n                }\n                case 16: {\n                    int16_t sample;\n                    fread(&sample, 1, sizeof(int16_t), fp);\n                    // std::cout << sample;\n                    data_[i] = static_cast<float>(sample);\n                    // std::cout << data_[i];\n                    break;\n                }\n                case 32: {\n                    int sample;\n                    fread(&sample, 1, sizeof(int), fp);\n                    data_[i] = static_cast<float>(sample);\n                    break;\n                }\n                default:\n                    fprintf(stderr, \"unsupported quantization bits\");\n                    exit(1);\n            }\n        }\n        fclose(fp);\n        return true;\n    }\n\n    int num_channel() const { return num_channel_; }\n    int sample_rate() const { return sample_rate_; }\n    int bits_per_sample() const { return bits_per_sample_; }\n    int num_samples() const { return num_samples_; }\n    const float* data() const { return data_; }\n\n  private:\n    int num_channel_;\n    int sample_rate_;\n    int bits_per_sample_;\n    int num_samples_;  // sample points per channel\n    float* data_;\n};\n\nclass WavWriter {\n  public:\n    WavWriter(const float* data,\n              int num_samples,\n              int num_channel,\n              int sample_rate,\n              int bits_per_sample)\n        : data_(data),\n          num_samples_(num_samples),\n          num_channel_(num_channel),\n          sample_rate_(sample_rate),\n          bits_per_sample_(bits_per_sample) {}\n\n    void Write(const std::string& filename) {\n        FILE* fp = fopen(filename.c_str(), \"w\");\n        // init char 'riff' 'WAVE' 'fmt ' 'data'\n        WavHeader header;\n        char wav_header[44] = {\n            0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,\n            0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,\n            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n            0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00};\n        memcpy(&header, wav_header, sizeof(header));\n        header.channels = num_channel_;\n        header.bit = bits_per_sample_;\n        header.sample_rate = sample_rate_;\n        header.data_size = num_samples_ * num_channel_ * (bits_per_sample_ / 8);\n        header.size = sizeof(header) - 8 + header.data_size;\n        header.bytes_per_second =\n            sample_rate_ * num_channel_ * (bits_per_sample_ / 8);\n        header.block_size = num_channel_ * (bits_per_sample_ / 8);\n\n        fwrite(&header, 1, sizeof(header), fp);\n\n        for (int i = 0; i < num_samples_; ++i) {\n            for (int j = 0; j < num_channel_; ++j) {\n                switch (bits_per_sample_) {\n                    case 8: {\n                        char sample =\n                            static_cast<char>(data_[i * num_channel_ + j]);\n                        fwrite(&sample, 1, sizeof(sample), fp);\n                        break;\n                    }\n                    case 16: {\n                        int16_t sample =\n                            static_cast<int16_t>(data_[i * num_channel_ + j]);\n                        fwrite(&sample, 1, sizeof(sample), fp);\n                        break;\n                    }\n                    case 32: {\n                        int sample =\n                            static_cast<int>(data_[i * num_channel_ + j]);\n                        fwrite(&sample, 1, sizeof(sample), fp);\n                        break;\n                    }\n                }\n            }\n        }\n        fclose(fp);\n    }\n\n  private:\n    const float* data_;\n    int num_samples_;  // total float points in data_\n    int num_channel_;\n    int sample_rate_;\n    int bits_per_sample_;\n};\n\n}  // namespace wav\n"
  },
  {
    "path": "runtime/engine/vad/interface/CMakeLists.txt",
    "content": "set(srcs \n    vad_interface.cc \n)\n\nadd_library(pps_vad_interface SHARED ${srcs})\ntarget_link_libraries(pps_vad_interface PUBLIC pps_vad extern_glog)\n\n\nset(bin_name vad_interface_main)\nadd_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\ntarget_link_libraries(${bin_name} pps_vad_interface)\n# set_target_properties(${bin_name} PROPERTIES PUBLIC_HEADER \"vad_interface.h;../frontend/wav.h\")\n\nfile(RELATIVE_PATH DEST_DIR ${ENGINE_ROOT} ${CMAKE_CURRENT_SOURCE_DIR})\ninstall(TARGETS pps_vad_interface DESTINATION lib)\ninstall(FILES vad_interface.h DESTINATION include/${DEST_DIR})\n\ninstall(TARGETS vad_interface_main \n        RUNTIME DESTINATION bin\n        LIBRARY DESTINATION lib\n        ARCHIVE DESTINATION lib\n        PUBLIC_HEADER DESTINATION include/${DEST_DIR}\n)\ninstall(FILES vad_interface_main.cc DESTINATION demo/${DEST_DIR})"
  },
  {
    "path": "runtime/engine/vad/interface/vad_interface.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"vad/interface/vad_interface.h\"\n\n#include \"common/base/config.h\"\n#include \"vad/nnet/vad.h\"\n\n\nPPSHandle_t PPSVadCreateInstance(const char* conf_path) {\n    Config conf(conf_path);\n    ppspeech::VadNnetConf nnet_conf;\n    nnet_conf.sr = conf.Read(\"sr\", 16000);\n    nnet_conf.frame_ms = conf.Read(\"frame_ms\", 32);\n    nnet_conf.threshold = conf.Read(\"threshold\", 0.45f);\n    nnet_conf.beam = conf.Read(\"beam\", 0.15f);\n    nnet_conf.min_silence_duration_ms =\n        conf.Read(\"min_silence_duration_ms\", 200);\n    nnet_conf.speech_pad_left_ms = conf.Read(\"speech_pad_left_ms\", 0);\n    nnet_conf.speech_pad_right_ms = conf.Read(\"speech_pad_right_ms\", 0);\n\n    nnet_conf.model_file_path = conf.Read(\"model_path\", std::string(\"\"));\n    nnet_conf.param_file_path = conf.Read(\"param_path\", std::string(\"\"));\n    nnet_conf.num_cpu_thread = conf.Read(\"num_cpu_thread\", 1);\n\n    ppspeech::Vad* model = new ppspeech::Vad(nnet_conf.model_file_path);\n\n    // custom config, but must be set before init\n    model->SetConfig(nnet_conf);\n    model->Init();\n\n    return static_cast<PPSHandle_t>(model);\n}\n\n\nint PPSVadDestroyInstance(PPSHandle_t instance) {\n    ppspeech::Vad* model = static_cast<ppspeech::Vad*>(instance);\n    if (model != nullptr) {\n        delete model;\n        model = nullptr;\n    }\n    return 0;\n}\n\nint PPSVadChunkSizeSamples(PPSHandle_t instance) {\n    ppspeech::Vad* model = static_cast<ppspeech::Vad*>(instance);\n    if (model == nullptr) {\n        printf(\"instance is null\\n\");\n        return -1;\n    }\n\n    return model->WindowSizeSamples();\n}\n\nPPSVadState_t PPSVadFeedForward(PPSHandle_t instance,\n                                float* chunk,\n                                int num_element) {\n    ppspeech::Vad* model = static_cast<ppspeech::Vad*>(instance);\n    if (model == nullptr) {\n        printf(\"instance is null\\n\");\n        return PPS_VAD_ILLEGAL;\n    }\n\n    std::vector<float> chunk_in(chunk, chunk + num_element);\n    if (!model->ForwardChunk(chunk_in)) {\n        printf(\"forward chunk failed\\n\");\n        return PPS_VAD_ILLEGAL;\n    }\n    ppspeech::Vad::State s = model->Postprocess();\n    PPSVadState_t ret = (PPSVadState_t)s;\n    return ret;\n}\n\nint PPSVadReset(PPSHandle_t instance) {\n    ppspeech::Vad* model = static_cast<ppspeech::Vad*>(instance);\n    if (model == nullptr) {\n        printf(\"instance is null\\n\");\n        return -1;\n    }\n    model->Reset();\n    return 0;\n}\n\nint PPSVadGetResult(PPSHandle_t instance, char* result, int max_len){\n    ppspeech::Vad* model = static_cast<ppspeech::Vad*>(instance);\n    if (model == nullptr) {\n        printf(\"instance is null\\n\");\n        return -1;\n    }\n    return model->GetResult(result, max_len);\n};"
  },
  {
    "path": "runtime/engine/vad/interface/vad_interface.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef void* PPSHandle_t;\n\ntypedef enum {\n    PPS_VAD_ILLEGAL = 0,  // error\n    PPS_VAD_SIL,          // silence\n    PPS_VAD_START,        // start speech\n    PPS_VAD_SPEECH,       // in speech\n    PPS_VAD_END,          // end speech\n    PPS_VAD_NUMSTATES,    // number of states\n} PPSVadState_t;\n\nPPSHandle_t PPSVadCreateInstance(const char* conf_path);\n\nint PPSVadDestroyInstance(PPSHandle_t instance);\n\nint PPSVadReset(PPSHandle_t instance);\n\nint PPSVadChunkSizeSamples(PPSHandle_t instance);\n\nPPSVadState_t PPSVadFeedForward(PPSHandle_t instance,\n                                float* chunk,\n                                int num_element);\n\nint PPSVadGetResult(PPSHandle_t instance, char* result, int max_len);\n#ifdef __cplusplus\n}\n#endif  // __cplusplus"
  },
  {
    "path": "runtime/engine/vad/interface/vad_interface_main.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include <iostream>\n#include <vector>\n\n#include <fstream>\n#include \"common/base/common.h\"\n#include \"vad/frontend/wav.h\"\n#include \"vad/interface/vad_interface.h\"\n\nint main(int argc, char* argv[]) {\n    if (argc < 3) {\n        std::cout << \"Usage: vad_interface_main path/to/config wav.scp\"\n                     \"run_option, \"\n                     \"e.g ./vad_interface_main config wav.scp\"\n                  << std::endl;\n        return -1;\n    }\n\n    std::string config_path = argv[1];\n    std::string wav_scp = argv[2];\n\n    PPSHandle_t handle = PPSVadCreateInstance(config_path.c_str());\n\n    std::ifstream fp_wav(wav_scp);\n    std::string line = \"\";\n    while(getline(fp_wav, line)){\n        std::vector<float> inputWav;  // [0, 1]\n        wav::WavReader wav_reader = wav::WavReader(line);\n        auto sr = wav_reader.sample_rate();\n        CHECK(sr == 16000) << \" sr is \" << sr << \" expect 16000\";\n\n        auto num_samples = wav_reader.num_samples();\n        inputWav.resize(num_samples);\n        for (int i = 0; i < num_samples; i++) {\n            inputWav[i] = wav_reader.data()[i] / 32768;\n        }\n\n        ppspeech::Timer timer;\n        int window_size_samples = PPSVadChunkSizeSamples(handle);\n        for (int64_t j = 0; j < num_samples; j += window_size_samples) {\n            auto start = j;\n            auto end = start + window_size_samples >= num_samples\n                        ? num_samples\n                        : start + window_size_samples;\n            std::vector<float> r(window_size_samples, 0);\n            auto current_chunk_size = end - start;\n            memcpy(r.data(), inputWav.data() + start, current_chunk_size * sizeof(float));\n\n            PPSVadState_t s = PPSVadFeedForward(handle, r.data(), r.size());\n        }\n\n        std::cout << \"RTF=\" << timer.Elapsed() / double(num_samples / sr)\n                << std::endl;\n\n        char result[10240] = {0};\n        PPSVadGetResult(handle, result, 10240);\n        std::cout << line << \" \" << result << std::endl;\n        \n        PPSVadReset(handle);\n        // getchar();\n    }\n    PPSVadDestroyInstance(handle);\n    return 0;\n}\n"
  },
  {
    "path": "runtime/engine/vad/nnet/CMakeLists.txt",
    "content": "set(srcs \n    vad.cc \n)\n\nadd_library(pps_vad ${srcs})\ntarget_link_libraries(pps_vad PUBLIC ${FASTDEPLOY_LIBS} common extern_glog)\n\n\nset(bin_name vad_nnet_main)\nadd_executable(${bin_name} ${CMAKE_CURRENT_SOURCE_DIR}/${bin_name}.cc)\ntarget_link_libraries(${bin_name} pps_vad)\n\nfile(RELATIVE_PATH DEST_DIR ${ENGINE_ROOT} ${CMAKE_CURRENT_SOURCE_DIR})\ninstall(TARGETS pps_vad DESTINATION lib)\nif(ANDROID)\n    install(TARGETS extern_glog DESTINATION lib)\nelse() # UNIX\n    install(TARGETS glog DESTINATION lib)\nendif()\n"
  },
  {
    "path": "runtime/engine/vad/nnet/vad.cc",
    "content": "// Copyright (c) 2023 Chen Qianhe Authors. All Rights Reserved.\n// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"vad/nnet/vad.h\"\n\n#include <cstring>\n#include <iomanip>\n\n#include \"common/base/common.h\"\n\n\nnamespace ppspeech {\n\nVad::Vad(const std::string& model_file,\n         const fastdeploy::RuntimeOption&\n             custom_option /* = fastdeploy::RuntimeOption() */) {\n    valid_cpu_backends = {fastdeploy::Backend::ORT,\n                          fastdeploy::Backend::OPENVINO};\n    valid_gpu_backends = {fastdeploy::Backend::ORT, fastdeploy::Backend::TRT};\n\n    runtime_option = custom_option;\n    // ORT backend\n    runtime_option.UseCpu();\n    runtime_option.UseOrtBackend();\n    runtime_option.model_format = fastdeploy::ModelFormat::ONNX;\n    // grap opt level\n    runtime_option.ort_option.graph_optimization_level = 99;\n    // one-thread\n    runtime_option.ort_option.intra_op_num_threads = 1;\n    runtime_option.ort_option.inter_op_num_threads = 1;\n    // model path\n    runtime_option.model_file = model_file;\n}\n\nvoid Vad::Init() {\n    std::lock_guard<std::mutex> lock(init_lock_);\n    Initialize();\n}\n\nstd::string Vad::ModelName() const { return \"VAD\"; }\n\nvoid Vad::SetConfig(const VadNnetConf conf) {\n    SetConfig(conf.sr,\n              conf.frame_ms,\n              conf.threshold,\n              conf.beam,\n              conf.min_silence_duration_ms,\n              conf.speech_pad_left_ms,\n              conf.speech_pad_right_ms);\n}\n\nvoid Vad::SetConfig(const int& sr,\n                    const int& frame_ms,\n                    const float& threshold,\n                    const float& beam,\n                    const int& min_silence_duration_ms,\n                    const int& speech_pad_left_ms,\n                    const int& speech_pad_right_ms) {\n    if (initialized_) {\n        fastdeploy::FDERROR << \"SetConfig must be called before init\"\n                            << std::endl;\n        throw std::runtime_error(\"SetConfig must be called before init\");\n    }\n    sample_rate_ = sr;\n    sr_per_ms_ = sr / 1000;\n    threshold_ = threshold;\n    beam_ = beam;\n    frame_ms_ = frame_ms;\n    min_silence_samples_ = min_silence_duration_ms * sr_per_ms_;\n    speech_pad_left_samples_ = speech_pad_left_ms * sr_per_ms_;\n    speech_pad_right_samples_ = speech_pad_right_ms * sr_per_ms_;\n\n    // init chunk size\n    window_size_samples_ = frame_ms * sr_per_ms_;\n    current_chunk_size_ = window_size_samples_;\n\n    fastdeploy::FDINFO << \"sr=\" << sr_per_ms_ << \" threshold=\" << threshold_\n                       << \" beam=\" << beam_ << \" frame_ms=\" << frame_ms_\n                       << \" min_silence_duration_ms=\" << min_silence_duration_ms\n                       << \" speech_pad_left_ms=\" << speech_pad_left_ms\n                       << \" speech_pad_right_ms=\" << speech_pad_right_ms;\n}\n\nvoid Vad::Reset() {\n    std::memset(h_.data(), 0.0f, h_.size() * sizeof(float));\n    std::memset(c_.data(), 0.0f, c_.size() * sizeof(float));\n\n    triggerd_ = false;\n    temp_end_ = 0;\n    current_sample_ = 0;\n\n    speechStart_.clear();\n    speechEnd_.clear();\n\n    states_.clear();\n}\n\nbool Vad::Initialize() {\n    // input & output holder\n    inputTensors_.resize(4);\n    outputTensors_.resize(3);\n\n    // input shape\n    input_node_dims_.emplace_back(1);\n    input_node_dims_.emplace_back(window_size_samples_);\n    // sr buffer\n    sr_.resize(1);\n    sr_[0] = sample_rate_;\n    // hidden state buffer\n    h_.resize(size_hc_);\n    c_.resize(size_hc_);\n\n    Reset();\n\n\n    // InitRuntime\n    if (!InitRuntime()) {\n        fastdeploy::FDERROR << \"Failed to initialize fastdeploy backend.\"\n                            << std::endl;\n        return false;\n    }\n\n    initialized_ = true;\n\n\n    fastdeploy::FDINFO << \"init done.\";\n    return true;\n}\n\nbool Vad::ForwardChunk(std::vector<float>& chunk) {\n    // last chunk may not be window_size_samples_\n    input_node_dims_.back() = chunk.size();\n    assert(window_size_samples_ >= chunk.size());\n    current_chunk_size_ = chunk.size();\n\n    inputTensors_[0].name = \"input\";\n    inputTensors_[0].SetExternalData(\n        input_node_dims_, fastdeploy::FDDataType::FP32, chunk.data());\n    inputTensors_[1].name = \"sr\";\n    inputTensors_[1].SetExternalData(\n        sr_node_dims_, fastdeploy::FDDataType::INT64, sr_.data());\n    inputTensors_[2].name = \"h\";\n    inputTensors_[2].SetExternalData(\n        hc_node_dims_, fastdeploy::FDDataType::FP32, h_.data());\n    inputTensors_[3].name = \"c\";\n    inputTensors_[3].SetExternalData(\n        hc_node_dims_, fastdeploy::FDDataType::FP32, c_.data());\n\n    if (!Infer(inputTensors_, &outputTensors_)) {\n        return false;\n    }\n\n    // Push forward sample index\n    current_sample_ += current_chunk_size_;\n    return true;\n}\n\nconst Vad::State& Vad::Postprocess() {\n    // update prob, h, c\n    outputProb_ = *(float*)outputTensors_[0].Data();\n    auto* hn = static_cast<float*>(outputTensors_[1].MutableData());\n    std::memcpy(h_.data(), hn, h_.size() * sizeof(float));\n    auto* cn = static_cast<float*>(outputTensors_[2].MutableData());\n    std::memcpy(c_.data(), cn, c_.size() * sizeof(float));\n\n    if (outputProb_ < threshold_ && !triggerd_) {\n        // 1. Silence\n#ifdef PPS_DEBUG\n        DLOG(INFO) << \"{ silence: \" << 1.0 * current_sample_ / sample_rate_\n                   << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n        states_.emplace_back(Vad::State::SIL);\n    } else if (outputProb_ >= threshold_ && !triggerd_) {\n        // 2. Start\n        triggerd_ = true;\n        speech_start_ =\n            current_sample_ - current_chunk_size_ - speech_pad_left_samples_;\n        speech_start_ = std::max(int(speech_start_), 0);\n        float start_sec = 1.0 * speech_start_ / sample_rate_;\n        speechStart_.emplace_back(start_sec);\n#ifdef PPS_DEBUG\n        DLOG(INFO) << \"{ speech start: \" << start_sec\n                   << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n        states_.emplace_back(Vad::State::START);\n    } else if (outputProb_ >= threshold_ - beam_ && triggerd_) {\n        // 3. Continue\n\n        if (temp_end_ != 0) {\n            // speech prob relaxation, speech continues again\n#ifdef PPS_DEBUG\n            DLOG(INFO)\n                << \"{ speech fake end(sil < min_silence_ms) to continue: \"\n                << 1.0 * current_sample_ / sample_rate_\n                << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n            temp_end_ = 0;\n        } else {\n            // speech prob relaxation, keep tracking speech\n#ifdef PPS_DEBUG\n            DLOG(INFO) << \"{ speech continue: \"\n                       << 1.0 * current_sample_ / sample_rate_\n                       << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n        }\n\n        states_.emplace_back(Vad::State::SPEECH);\n    } else if (outputProb_ < threshold_ - beam_ && triggerd_) {\n        // 4. End\n        if (temp_end_ == 0) {\n            temp_end_ = current_sample_;\n        }\n\n        // check possible speech end\n        if (current_sample_ - temp_end_ < min_silence_samples_) {\n            // a. silence < min_slience_samples, continue speaking\n#ifdef PPS_DEBUG\n            DLOG(INFO) << \"{ speech fake end(sil < min_silence_ms): \"\n                       << 1.0 * current_sample_ / sample_rate_\n                       << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n            states_.emplace_back(Vad::State::SIL);\n        } else {\n            // b. silence >= min_slience_samples, end speaking\n            speech_end_ = current_sample_ + speech_pad_right_samples_;\n            temp_end_ = 0;\n            triggerd_ = false;\n            auto end_sec = 1.0 * speech_end_ / sample_rate_;\n            speechEnd_.emplace_back(end_sec);\n#ifdef PPS_DEBUG\n            DLOG(INFO) << \"{ speech end: \" << end_sec\n                       << \" s; prob: \" << outputProb_ << \" }\";\n#endif\n            states_.emplace_back(Vad::State::END);\n        }\n    }\n\n    return states_.back();\n}\n\nstd::string Vad::ConvertTime(float time_s) const{\n    float seconds_tmp, minutes_tmp, hours_tmp;\n    float seconds;\n    int minutes, hours;\n \n\t//\t计算小时\n\thours_tmp = time_s / 60 / 60;  // 1\n\thours = (int)hours_tmp;\n \n\t// 计算分钟\n\tminutes_tmp = time_s / 60;\n\tif (minutes_tmp >= 60) {\n\t\tminutes = minutes_tmp - 60 * (double)hours;\n\t}\n\telse {\n\t\tminutes = minutes_tmp;\n\t}\n \n\t// 计算秒数\n\tseconds_tmp = (60 * 60 * hours) + (60 * minutes);\n\tseconds = time_s - seconds_tmp;\n \n\t// 输出格式\n    std::stringstream ss;\n    ss << hours << \":\" << minutes << \":\" << seconds;\n \n\treturn ss.str();\n}\n\nint Vad::GetResult(char* result, int max_len,\n    float removeThreshold,\n    float expandHeadThreshold,\n    float expandTailThreshold,\n    float mergeThreshold) const {\n    float audioLength = 1.0 * current_sample_ / sample_rate_;\n    if (speechStart_.empty() && speechEnd_.empty()) {\n        return {};\n    }\n    if (speechEnd_.size() != speechStart_.size()) {\n        // set the audio length as the last end\n        speechEnd_.emplace_back(audioLength);\n    }\n    \n    std::string json = \"[\";\n\n    for (int i = 0; i < speechStart_.size(); ++i) {\n        json += \"{\\\"s\\\":\\\"\" + ConvertTime(speechStart_[i]) + \"\\\",\\\"e\\\":\\\"\" + ConvertTime(speechEnd_[i]) + \"\\\"},\";\n    }\n    json.pop_back();\n    json += \"]\";\n    \n    if(result != NULL){\n        snprintf(result, max_len, \"%s\", json.c_str());\n    } else {\n        DLOG(INFO) << \"result is NULL\";\n    }\n    return 0;\n}\n\nstd::ostream& operator<<(std::ostream& os, const Vad::State& s) {\n    switch (s) {\n        case Vad::State::SIL:\n            os << \"[SIL]\";\n            break;\n        case Vad::State::START:\n            os << \"[STA]\";\n            break;\n        case Vad::State::SPEECH:\n            os << \"[SPE]\";\n            break;\n        case Vad::State::END:\n            os << \"[END]\";\n            break;\n        default:\n            // illegal state\n            os << \"[ILL]\";\n            break;\n    }\n    return os;\n}\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/vad/nnet/vad.h",
    "content": "// Copyright (c) 2023 Chen Qianhe Authors. All Rights Reserved.\n// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n#include <iostream>\n#include <mutex>\n#include <vector>\n\n#include \"fastdeploy/fastdeploy_model.h\"\n#include \"fastdeploy/runtime.h\"\n#include \"vad/frontend/wav.h\"\n\nnamespace ppspeech {\n\nstruct VadNnetConf {\n    // wav\n    int sr;\n    int frame_ms;\n    float threshold;\n    float beam;\n    int min_silence_duration_ms;\n    int speech_pad_left_ms;\n    int speech_pad_right_ms;\n\n    // model\n    std::string model_file_path;\n    std::string param_file_path;\n    std::string dict_file_path;\n    int num_cpu_thread;   // 1 thred\n    std::string backend;  // ort,lite, etc.\n};\n\nclass Vad : public fastdeploy::FastDeployModel {\n  public:\n    enum class State { ILLEGAL = 0, SIL, START, SPEECH, END };\n    friend std::ostream& operator<<(std::ostream& os, const Vad::State& s);\n\n    Vad(const std::string& model_file,\n        const fastdeploy::RuntimeOption& custom_option =\n            fastdeploy::RuntimeOption());\n\n    virtual ~Vad() {}\n\n    void Init();\n\n    void Reset();\n\n    void SetConfig(const int& sr,\n                   const int& frame_ms,\n                   const float& threshold,\n                   const float& beam,\n                   const int& min_silence_duration_ms,\n                   const int& speech_pad_left_ms,\n                   const int& speech_pad_right_ms);\n    void SetConfig(const VadNnetConf conf);\n\n    bool ForwardChunk(std::vector<float>& chunk);\n\n    const State& Postprocess();\n\n    int GetResult(char* result, int max_len,\n        float removeThreshold = 0.0,\n        float expandHeadThreshold = 0.0,\n        float expandTailThreshold = 0,\n        float mergeThreshold = 0.0) const;\n\n    const std::vector<State> GetStates() const { return states_; }\n\n    int SampleRate() const { return sample_rate_; }\n\n    int FrameMs() const { return frame_ms_; }\n    int64_t WindowSizeSamples() const { return window_size_samples_; }\n\n    float Threshold() const { return threshold_; }\n\n    int MinSilenceDurationMs() const {\n        return min_silence_samples_ / sample_rate_;\n    }\n    int SpeechPadLeftMs() const {\n        return speech_pad_left_samples_ / sample_rate_;\n    }\n    int SpeechPadRightMs() const {\n        return speech_pad_right_samples_ / sample_rate_;\n    }\n\n    int MinSilenceSamples() const { return min_silence_samples_; }\n    int SpeechPadLeftSamples() const { return speech_pad_left_samples_; }\n    int SpeechPadRightSamples() const { return speech_pad_right_samples_; }\n\n    std::string ModelName() const override;\n\n  private:\n    bool Initialize();\n    std::string ConvertTime(float time_s) const;\n\n  private:\n    std::mutex init_lock_;\n    bool initialized_{false};\n\n    // input and output\n    std::vector<fastdeploy::FDTensor> inputTensors_;\n    std::vector<fastdeploy::FDTensor> outputTensors_;\n\n    // model states\n    bool triggerd_ = false;\n    unsigned int speech_start_ = 0;\n    unsigned int speech_end_ = 0;\n    unsigned int temp_end_ = 0;\n    unsigned int current_sample_ = 0;\n    unsigned int current_chunk_size_ = 0;\n    // MAX 4294967295 samples / 8sample per ms / 1000 / 60 = 8947 minutes\n    float outputProb_;\n\n    std::vector<float> speechStart_;\n    mutable std::vector<float> speechEnd_;\n\n    std::vector<State> states_;\n\n    /* ========================================================================\n     */\n    int sample_rate_ = 16000;\n    int frame_ms_ = 32;  // 32, 64, 96 for 16k\n    float threshold_ = 0.5f;\n    float beam_ = 0.15f;\n\n    int64_t window_size_samples_;  // support 256 512 768 for 8k; 512 1024 1536\n                                   // for 16k.\n    int sr_per_ms_;                // support 8 or 16\n    int min_silence_samples_;      // sr_per_ms_ * frame_ms_\n    int speech_pad_left_samples_{0};   // usually 250ms\n    int speech_pad_right_samples_{0};  // usually 0\n\n    /* ========================================================================\n     */\n    std::vector<int64_t> sr_;\n    const size_t size_hc_ = 2 * 1 * 64;  // It's FIXED.\n    std::vector<float> h_;\n    std::vector<float> c_;\n\n    std::vector<int64_t> input_node_dims_;\n    const std::vector<int64_t> sr_node_dims_ = {1};\n    const std::vector<int64_t> hc_node_dims_ = {2, 1, 64};\n};\n\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/engine/vad/nnet/vad_nnet_main.cc",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n#include \"common/base/common.h\"\n#include \"vad/nnet/vad.h\"\n\nint main(int argc, char* argv[]) {\n    if (argc < 3) {\n        std::cout << \"Usage: vad_nnet_main path/to/model path/to/audio \"\n                     \"run_option, \"\n                     \"e.g ./vad_nnet_main silero_vad.onnx sample.wav\"\n                  << std::endl;\n        return -1;\n    }\n\n    std::string model_file = argv[1];\n    std::string audio_file = argv[2];\n\n    int sr = 16000;\n    ppspeech::Vad vad(model_file);\n    // custom config, but must be set before init\n    vad.SetConfig(sr, 32, 0.5f, 0.15, 200, 0, 0);\n    vad.Init();\n\n    std::vector<float> inputWav;  // [0, 1]\n    wav::WavReader wav_reader = wav::WavReader(audio_file);\n    assert(wav_reader.sample_rate() == sr);\n\n\n    auto num_samples = wav_reader.num_samples();\n    inputWav.resize(num_samples);\n    for (int i = 0; i < num_samples; i++) {\n        inputWav[i] = wav_reader.data()[i] / 32768;\n    }\n\n    ppspeech::Timer timer;\n    int window_size_samples = vad.WindowSizeSamples();\n    for (int64_t j = 0; j < num_samples; j += window_size_samples) {\n        auto start = j;\n        auto end = start + window_size_samples >= num_samples\n                       ? num_samples\n                       : start + window_size_samples;\n        auto current_chunk_size = end - start;\n\n        std::vector<float> r{&inputWav[0] + start, &inputWav[0] + end};\n        assert(r.size() == static_cast<size_t>(current_chunk_size));\n\n        if (!vad.ForwardChunk(r)) {\n            std::cerr << \"Failed to inference while using model:\"\n                      << vad.ModelName() << \".\" << std::endl;\n            return false;\n        }\n\n        ppspeech::Vad::State s = vad.Postprocess();\n        std::cout << s << \" \";\n    }\n    std::cout << std::endl;\n\n    std::cout << \"RTF=\" << timer.Elapsed() / double(num_samples / sr)\n              << std::endl;\n    std::cout << \"\\b\\b \" << std::endl;\n\n    vad.Reset();\n\n    return 0;\n}\n"
  },
  {
    "path": "runtime/examples/.gitignore",
    "content": "*.ark\n*.scp\npaddle_asr_model/\n"
  },
  {
    "path": "runtime/examples/README.md",
    "content": "# Examples for SpeechX\n\n> `u2pp_ol` is recommended.\n\n* `u2pp_ol` - u2++ streaming asr test under `aishell-1` test dataset.\n* `ds2_ol` - ds2 streaming test under `aishell-1` test dataset. \n\n\n## How to run  \n\n### Create env\n\nUsing `tools/evn.sh` under `speechx` to create python env.\n\n```\nbash tools/env.sh\n```\n\nSource env before play with example.\n```\n. venv/bin/activate\n```\n\n### Play with example\n\n`run.sh` is the entry point for every example.\n\nExample to play `u2pp_ol`:\n\n```\npushd u2pp_ol/wenetspeech\nbash run.sh --stop_stage 4\n```\n\n## Display Model with [Netron](https://github.com/lutzroeder/netron)  \n\nIf you have a model, we can using this commend to show model graph.\n\nFor example:\n```\npip install netron\nnetron exp/deepspeech2_online/checkpoints/avg_1.jit.pdmodel  --port 8022 --host 10.21.55.20\n```\n\n## For Developer  \n\n> Reminder: Only for developer, make sure you know what's it.\n\n* codelab - for speechx developer, using for test.\n"
  },
  {
    "path": "runtime/examples/android/VadJni/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n"
  },
  {
    "path": "runtime/examples/android/VadJni/app/.gitignore",
    "content": "/build\n/cache\n"
  },
  {
    "path": "runtime/examples/android/VadJni/app/build.gradle",
    "content": "plugins {\n    id 'com.android.application'\n}\n\nandroid {\n    namespace 'com.baidu.paddlespeech.vadjni'\n    compileSdk 33\n    ndkVersion '23.1.7779620'\n\n    defaultConfig {\n        applicationId \"com.baidu.paddlespeech.vadjni\"\n        minSdk 21\n        targetSdk 33\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n\n        externalNativeBuild {\n            cmake {\n                arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_shared', \"-DANDROID_TOOLCHAIN=clang\"\n                abiFilters 'arm64-v8a'\n                cppFlags \"-std=c++11\"\n            }\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    externalNativeBuild {\n        cmake {\n            path file('src/main/cpp/CMakeLists.txt')\n            version '3.22.1'\n        }\n    }\n    buildFeatures {\n        viewBinding true\n    }\n    sourceSets {\n        main {\n            jniLibs.srcDirs = ['libs']\n        }\n    }\n}\n\ndependencies {\n    // Dependency on local binaries\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    // Dependency on a remote binary\n    implementation 'androidx.appcompat:appcompat:1.4.1'\n    implementation 'com.google.android.material:material:1.5.0'\n    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.3'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'\n}\n\ndef CXX_LIB = [\n//        [\n//                'src' : 'https://bj.bcebos.com/fastdeploy/dev/android/fastdeploy-android-with-text-0.0.0-shared.tgz',\n//                'dest': 'libs',\n//                'name': 'fastdeploy-android-latest-shared-dev'\n//        ]\n]\n\ntask downloadAndExtractLibs(type: DefaultTask) {\n    doFirst {\n        println \"[INFO] Downloading and extracting fastdeploy android c++ lib ...\"\n    }\n    doLast {\n        String cachePath = \"cache\"\n        if (!file(\"${cachePath}\").exists()) {\n            mkdir \"${cachePath}\"\n        }\n\n        CXX_LIB.eachWithIndex { lib, index ->\n\n            String[] libPaths = lib.src.split(\"/\")\n            String sdkName = lib.name\n            String libName = libPaths[libPaths.length - 1]\n            libName = libName.substring(0, libName.indexOf(\"tgz\") - 1)\n            String cacheName = cachePath + \"/\" + \"${libName}.tgz\"\n\n            String libDir = lib.dest + \"/\" + libName\n            String sdkDir = lib.dest + \"/\" + sdkName\n\n            boolean copyFiles = false\n            if (!file(\"${sdkDir}\").exists()) {\n                // Download lib and rename to sdk name later.\n                if (!file(\"${cacheName}\").exists()) {\n                    println \"[INFO] Downloading ${lib.src} -> ${cacheName}\"\n                    ant.get(src: lib.src, dest: file(\"${cacheName}\"))\n                }\n                copyFiles = true\n            }\n\n            if (copyFiles) {\n                println \"[INFO] Taring ${cacheName} -> ${libDir}\"\n                copy { from(tarTree(\"${cacheName}\")) into(\"${lib.dest}\") }\n                if (!libName.equals(sdkName)) {\n                    if (file(\"${sdkDir}\").exists()) {\n                        delete(\"${sdkDir}\")\n                        println \"[INFO] Remove old ${sdkDir}\"\n                    }\n                    mkdir \"${sdkDir}\"\n                    println \"[INFO] Coping ${libDir} -> ${sdkDir}\"\n                    copy { from(\"${libDir}\") into(\"${sdkDir}\") }\n                    delete(\"${libDir}\")\n                    println \"[INFO] Removed ${libDir}\"\n                    println \"[INFO] Update ${sdkDir} done!\"\n                }\n            } else {\n                println \"[INFO] ${sdkDir} already exists!\"\n                println \"[WARN] Please delete ${cacheName} and ${sdkDir} \" +\n                        \"if you want to UPDATE ${sdkName} c++ lib. Then, rebuild this sdk.\"\n            }\n        }\n    }\n}\n\npreBuild.dependsOn downloadAndExtractLibs"
  },
  {
    "path": "runtime/examples/android/VadJni/app/libs/.gitkeep",
    "content": ""
  },
  {
    "path": "runtime/examples/android/VadJni/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/androidTest/java/com/baidu/paddlespeech/vadjni/ExampleInstrumentedTest.java",
    "content": "package com.baidu.paddlespeech.vadjni;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.ext.junit.runners.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();\n        assertEquals(\"com.baidu.paddlespeech.vadjni\", appContext.getPackageName());\n    }\n}"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:dataExtractionRules=\"@xml/data_extraction_rules\"\n        android:fullBackupContent=\"@xml/backup_rules\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.VadJni\"\n        tools:targetApi=\"31\">\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/cpp/CMakeLists.txt",
    "content": "# For more information about using CMake with Android Studio, read the\n# documentation: https://d.android.com/studio/projects/add-native-code.html\n\n# Sets the minimum version of CMake required to build the native library.\n\ncmake_minimum_required(VERSION 3.22.1)\n\n# Declares and names the project.\n\nproject(\"vadjni\")\n\n\nset(PPS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${ANDROID_ABI})\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\n\n# Creates and names a library, sets it as either STATIC\n# or SHARED, and provides the relative paths to its source code.\n# You can define multiple libraries, and CMake builds them for you.\n# Gradle automatically packages shared libraries with your APK.\n\nadd_library( # Sets the name of the library.\n        vadjni\n\n        # Sets the library as a shared library.\n        SHARED\n\n        # Provides a relative path to your source file(s).\n        native-lib.cpp)\n\n# Searches for a specified prebuilt library and stores the path as a\n# variable. Because CMake includes system libraries in the search path by\n# default, you only need to specify the name of the public NDK library\n# you want to add. CMake verifies that the library exists before\n# completing its build.\n\nfind_library( # Sets the name of the path variable.\n        log-lib\n\n        # Specifies the name of the NDK library that\n        # you want CMake to locate.\n        log)\n\n# Specifies libraries CMake should link to your target library. You\n# can link multiple libraries, such as libraries you define in this\n# build script, prebuilt third-party libraries, or system libraries.\n\nmessage(STATUS \"PPS_DIR=${PPS_DIR}\")\ntarget_link_libraries( # Specifies the target library.\n        vadjni\n        ${PPS_DIR}/libfastdeploy.so\n        ${PPS_DIR}/libonnxruntime.so\n        ${PPS_DIR}/libgflags_nothreads.a\n        ${PPS_DIR}/libbase.a\n        ${PPS_DIR}/libpps_vad.a\n        ${PPS_DIR}/libpps_vad_interface.a\n        # Links the target library to the log library\n        # included in the NDK.\n        ${log-lib})"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/cpp/native-lib.cpp",
    "content": "\n#include <string>\n#include \"vad_interface.h\"\n#include <jni.h>\n\nextern \"C\"\nJNIEXPORT jstring JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_stringFromJNI(\n        JNIEnv* env,\n        jobject /* this */) {\n    std::string hello = \"Hello from C++\";\n    return env->NewStringUTF(hello.c_str());\n}\n\nextern \"C\"\nJNIEXPORT jlong JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_createInstance(\n        JNIEnv* env,\n        jobject thiz,\n        jstring conf_path){\n    const char* path = env->GetStringUTFChars(conf_path, JNI_FALSE);\n    PPSHandle_t handle = PPSVadCreateInstance(path);\n\n    return (jlong)(handle);\n    return 0;\n}\n\n\nextern \"C\"\nJNIEXPORT jint JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_destroyInstance(JNIEnv *env, jobject thiz,\n                                                                jlong instance) {\n    PPSHandle_t handle = (PPSHandle_t)(instance);\n    return (jint)PPSVadDestroyInstance(handle);\n}\nextern \"C\"\nJNIEXPORT jint JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_reset(JNIEnv *env, jobject thiz, jlong instance) {\n    PPSHandle_t handle = (PPSHandle_t)(instance);\n    return (jint)PPSVadReset(handle);\n}\nextern \"C\"\nJNIEXPORT jint JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_chunkSizeSamples(JNIEnv *env, jobject thiz,\n                                                                 jlong instance) {\n    PPSHandle_t handle = (PPSHandle_t)(instance);\n    return (jint)PPSVadChunkSizeSamples(handle);\n}\nextern \"C\"\nJNIEXPORT jint JNICALL\nJava_com_baidu_paddlespeech_vadjni_MainActivity_feedForward(JNIEnv *env, jobject thiz,\n                                                            jlong instance, jfloatArray chunk) {\n    PPSHandle_t handle = (PPSHandle_t)(instance);\n    jsize num_elms = env->GetArrayLength(chunk);\n    jfloat* chunk_ptr = env->GetFloatArrayElements(chunk, JNI_FALSE);\n    return (jint)PPSVadFeedForward(handle, (float*)chunk_ptr, (int)num_elms);\n}"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/cpp/vad_interface.h",
    "content": "// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef void* PPSHandle_t;\n\ntypedef enum {\n    PPS_VAD_ILLEGAL = 0,  // error\n    PPS_VAD_SIL,          // silence\n    PPS_VAD_START,        // start speech\n    PPS_VAD_SPEECH,       // in speech\n    PPS_VAD_END,          // end speech\n    PPS_VAD_NUMSTATES,    // number of states\n} PPSVadState_t;\n\nPPSHandle_t PPSVadCreateInstance(const char* conf_path);\n\nint PPSVadDestroyInstance(PPSHandle_t instance);\n\nint PPSVadReset(PPSHandle_t instance);\n\nint PPSVadChunkSizeSamples(PPSHandle_t instance);\n\nPPSVadState_t PPSVadFeedForward(PPSHandle_t instance,\n                                float* chunk,\n                                int num_element);\n\n#ifdef __cplusplus\n}\n#endif  // __cplusplus"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/java/com/baidu/paddlespeech/vadjni/MainActivity.java",
    "content": "package com.baidu.paddlespeech.vadjni;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\nimport android.widget.Button;\nimport android.widget.TextView;\n\nimport com.baidu.paddlespeech.vadjni.databinding.ActivityMainBinding;\n\npublic class MainActivity extends AppCompatActivity {\n\n    // Used to load the 'vadjni' library on application startup.\n    static {\n        System.loadLibrary(\"vadjni\");\n    }\n\n    private ActivityMainBinding binding;\n    private long instance;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        binding = ActivityMainBinding.inflate(getLayoutInflater());\n        setContentView(binding.getRoot());\n\n        // Example of a call to a native method\n        TextView tv = binding.sampleText;\n        tv.setText(stringFromJNI());\n\n        Button lw = binding.loadWav;\n    }\n\n    /**\n     * A native method that is implemented by the 'vadjni' native library,\n     * which is packaged with this application.\n     */\n    public native String stringFromJNI();\n\n    public static native long createInstance(String config_path);\n\n    public static native int destroyInstance(long instance);\n\n    public static native int reset(long instance);\n\n    public static native int chunkSizeSamples(long instance);\n\n    public static native int feedForward(long instance, float[] chunk);\n}"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\">\n\n    <TextView\n        android:id=\"@+id/sample_text\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Hello World!\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.483\" />\n\n    <Button\n        android:id=\"@+id/load_wav\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Load Wav\"\n        tools:layout_editor_absoluteX=\"150dp\"\n        tools:layout_editor_absoluteY=\"429dp\" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n    <monochrome android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"white\">#FFFFFFFF</color>\n</resources>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">VadJni</string>\n</resources>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.VadJni\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_500</item>\n        <item name=\"colorPrimaryVariant\">@color/purple_700</item>\n        <item name=\"colorOnPrimary\">@color/white</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_700</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/values-night/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.VadJni\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_200</item>\n        <item name=\"colorPrimaryVariant\">@color/purple_700</item>\n        <item name=\"colorOnPrimary\">@color/black</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_200</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/xml/backup_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample backup rules file; uncomment and customize as necessary.\n   See https://developer.android.com/guide/topics/data/autobackup\n   for details.\n   Note: This file is ignored for devices older that API 31\n   See https://developer.android.com/about/versions/12/backup-restore\n-->\n<full-backup-content>\n    <!--\n   <include domain=\"sharedpref\" path=\".\"/>\n   <exclude domain=\"sharedpref\" path=\"device.xml\"/>\n-->\n</full-backup-content>"
  },
  {
    "path": "runtime/examples/android/VadJni/app/src/main/res/xml/data_extraction_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample data extraction rules file; uncomment and customize as necessary.\n   See https://developer.android.com/about/versions/12/backup-restore#xml-changes\n   for details.\n-->\n<data-extraction-rules>\n    <cloud-backup>\n        <!-- TODO: Use <include> and <exclude> to control what is backed up.\n        <include .../>\n        <exclude .../>\n        -->\n    </cloud-backup>\n    <!--\n    <device-transfer>\n        <include .../>\n        <exclude .../>\n    </device-transfer>\n    -->\n</data-extraction-rules>"
  },
  {
    "path": "runtime/examples/android/VadJni/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nplugins {\n    id 'com.android.application' version '7.4.2' apply false\n    id 'com.android.library' version '7.4.2' apply false\n}"
  },
  {
    "path": "runtime/examples/android/VadJni/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Mar 08 19:23:10 CST 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-bin.zip\ndistributionPath=wrapper/dists\nzipStorePath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\n"
  },
  {
    "path": "runtime/examples/android/VadJni/gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app's APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Enables namespacing of each library's R class so that its R class includes only the\n# resources declared in the library itself and none from the library's dependencies,\n# thereby reducing the size of the R class for that library\nandroid.nonTransitiveRClass=true"
  },
  {
    "path": "runtime/examples/android/VadJni/gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "runtime/examples/android/VadJni/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "runtime/examples/android/VadJni/settings.gradle",
    "content": "pluginManagement {\n    repositories {\n        google()\n        mavenCentral()\n        gradlePluginPortal()\n    }\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\nrootProject.name = \"VadJni\"\ninclude ':app'\n"
  },
  {
    "path": "runtime/examples/audio_classification/README.md",
    "content": "# audio classification\n\nThis directory provieds audio classification on CPU\n\n## conf\nconfig is the input of engine\n\n    [CONF]\n    wav_normal=true\n    wav_normal_type=linear\n    wav_norm_mul_factor=1.0\n    model_path=./inference.onnx\n    param_path=\n    dict_path=./label_list\n    num_cpu_thread=1\n    samp_freq=32000\n    frame_length_ms=32\n    frame_shift_ms=10\n    num_bins=64\n    low_freq=50\n    high_freq=14000\n    dither=0.0\n## label_list\nmodel output label\n\n    Dog\n    Rooster\n    Pig\n    Cow\n    Frog\n    Cat\n    Hen\n    Insects (flying)\n    Sheep\n    Crow\n    Rain\n    Sea waves\n    Crackling fire\n    .....\n## scp && test.wav\nscp is the input of engine and each line in scp is wav\n## execute\n../../build/Linux/x86_64/engine/audio_classification/nnet/panns_nnet_main --conf_path=./conf --scp_path=./scp --topk=1\nusage: panns_nnet_main conf scp topk\noutput such as:\n\n    wav_normal = true\n    wav_normal_type = linear\n    wav_norm_mul_factor = 1.0\n    model_path = ./inference.onnx\n    param_path = \n    dict_path = ./label_list\n    num_cpu_thread = 1\n    samp_freq = 32000\n    frame_length_ms = 32\n    frame_shift_ms = 10\n    num_bins = 64\n    low_freq = 50\n    high_freq = 14000\n    dither = 0.0\n    [INFO] fastdeploy/runtime/runtime.cc(293)::CreateOrtBackend     Runtime initialized with Backend::ORT in Device::CPU.\n    --- Init FastDeploy Runitme Done! \n    --- Model:  ./inference.onnx\n    test.wav{\"Clock alarm\":\"16.5309\"}\n## android demo\n### install\n#### copy lib & interface\ncd ../../\nsh build_android.sh\ncp build/Android/arm64-v8a-api-21/cls-android-out/*.so examples/audio_classification/android_demo/app/src/main/cpp/jniLibs/arm64-v8a/\ncp build/Android/arm64-v8a-api-21/cls-android-out/panns_interface.h examples/audio_classification/android_demo/app/src/main/cpp/\nincludes/\n\n#### set path\npush resource into android phone\n\n1. change resource path in conf to global path, such as:\n\n    [CONF]\n    wav_normal=true\n    wav_normal_type=linear\n    wav_norm_mul_factor=1.0\n    model_path=/data/local/tmp/inference.onnx\n    param_path=\n    dict_path=/data/local/tmp/label_list\n    num_cpu_thread=1\n    samp_freq=32000\n    frame_length_ms=32\n    frame_shift_ms=10\n    num_bins=64\n    low_freq=50\n    high_freq=14000\n    dither=0.0\n2. adb push conf label_list scp test.wav /data/local/tmp/\n3. set resource path in android demo(android_demo/app/src/main/cpp/native-lib.cpp) to actual path, such as:\n\nstd::string conf_path = \"/data/local/tmp/conf\";\nstd::string wav_path = \"/data/local/tmp/test.wav\";\n\n4. execute android_demo in android studio\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/.gitignore",
    "content": "/build"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/build.gradle",
    "content": "plugins {\n    id 'com.android.application'\n    id 'org.jetbrains.kotlin.android'\n}\n\nandroid {\n    namespace 'com.baidu.paddlespeech.cls'\n    compileSdk 32\n\n    defaultConfig {\n        applicationId \"com.baidu.paddlespeech.cls\"\n        minSdk 28\n        targetSdk 32\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n        externalNativeBuild {\n            cmake {\n                cppFlags ''\n            }\n        }\n        // 设置ndk编译的cpu架构\n        ndk {\n            abiFilters 'arm64-v8a'\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n    externalNativeBuild {\n        cmake {\n            path file('src/main/cpp/CMakeLists.txt')\n            version '3.22.1'\n        }\n    }\n    //我们将外部so库放在jniLibs文件夹下，因此要将它设置为jniLibs使工程在打包的时候能将它包含进去，否则app运行时会报无法找到so库的错误。\n    sourceSets {\n        main {\n            jniLibs.srcDirs = ['src/main/cpp/jniLibs']\n            resources { srcDirs = ['src/main/cpp/resources'] }\n        }\n    }\n}\n\ndependencies {\n\n    //noinspection GradleCompatible\n    implementation 'com.android.support:appcompat-v7:28.0.0'\n    implementation 'com.android.support.constraint:constraint-layout:2.0.4'\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n}"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/androidTest/java/com/example/cls/ExampleInstrumentedTest.kt",
    "content": "package com.example.cls\n\nimport android.support.test.InstrumentationRegistry\nimport android.support.test.runner.AndroidJUnit4\n\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\nimport org.junit.Assert.*\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n    @Test\n    fun useAppContext() {\n        // Context of the app under test.\n        val appContext = InstrumentationRegistry.getInstrumentation().targetContext\n        assertEquals(\"com.example.cls\", appContext.packageName)\n    }\n}"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\" >\n\n    <application\n        android:allowBackup=\"true\"\n        android:dataExtractionRules=\"@xml/data_extraction_rules\"\n        android:fullBackupContent=\"@xml/backup_rules\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.Cls\"\n        tools:targetApi=\"31\" >\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n\n            <meta-data\n                android:name=\"android.app.lib_name\"\n                android:value=\"\" />\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/cpp/CMakeLists.txt",
    "content": "\n# For more information about using CMake with Android Studio, read the\n# documentation: https://d.android.com/studio/projects/add-native-code.html\n\n# Sets the minimum version of CMake required to build the native library.\n\ncmake_minimum_required(VERSION 3.18.1)\n\n# Declares and names the project.\n\nproject(\"cls\")\n\ninclude_directories(src/main/cpp/)\nfile(GLOB CPP_FILES \"src/main/cpp/*.cpp\")\n\n# 添加so库存放位置\nset(distribution_DIR ${CMAKE_SOURCE_DIR}/jniLibs)\n\n# Creates and names a library, sets it as either STATIC\n# or SHARED, and provides the relative paths to its source code.\n# You can define multiple libraries, and CMake builds them for you.\n# Gradle automatically packages shared libraries with your APK.\n\nadd_library( # Sets the name of the library.\n        native-lib\n\n        # Sets the library as a shared library.\n        SHARED\n\n        # Provides a relative path to your source file(s).\n        ${CMAKE_CURRENT_SOURCE_DIR}/native-lib.cpp )\n\n# Searches for a specified prebuilt library and stores the path as a\n# variable. Because CMake includes system libraries in the search path by\n# default, you only need to specify the name of the public NDK library\n# you want to add. CMake verifies that the library exists before\n# completing its build.\n\nfind_library( # Sets the name of the path variable.\n        log-lib\n\n        # Specifies the name of the NDK library that\n        # you want CMake to locate.\n        log )\n\n# Specifies libraries CMake should link to your target library. You\n# can link multiple libraries, such as libraries you define in this\n# build script, prebuilt third-party libraries, or system libraries.\n\ntarget_link_libraries( # Specifies the target library.\n        native-lib\n        ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libc++_shared.so\n        ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libcls.so\n        ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libfastdeploy.so\n        ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libonnxruntime.so\n        # Links the target library to the log library\n        # included in the NDK.\n        ${log-lib}\n        )\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/cpp/includes/panns_interface.h",
    "content": "// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#pragma once\n\nnamespace ppspeech {\n\nvoid* ClsCreateInstance(const char* conf_path);\nint ClsDestroyInstance(void* instance);\nint ClsFeedForward(void* instance,\n                   const char* wav_path,\n                   int topk,\n                   char* result,\n                   int result_max_len);\nint ClsReset(void* instance);\n}  // namespace ppspeech"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/cpp/native-lib.cpp",
    "content": "// Write C++ code here.\n//\n// Do not forget to dynamically load the C++ library into your application.\n//\n// For instance,\n//\n// In MainActivity.java:\n//    static {\n//       System.loadLibrary(\"mysotest\");\n//    }\n//\n// Or, in MainActivity.kt:\n//    companion object {\n//      init {\n//         System.loadLibrary(\"mysotest\")\n//      }\n//    }\n\n#include <jni.h>\n#include <stdlib.h>\n#include <iostream>\n#include \"includes/panns_interface.h\"\n\n//如果你不想用引入头文件的方法，可以把导入头文件的include语句注释掉，然后将下面这句取消注释。\n//string getStringFromSoLibrary();\n\nvoid* cls_instance = nullptr;\n\nextern \"C\"\nJNIEXPORT jboolean JNICALL Java_com_baidu_paddlespeech_cls_MainActivity_nClsCreateInstance(JNIEnv *env, jobject instance)\n{\n    if (cls_instance != nullptr) {\n        ppspeech::ClsDestroyInstance(cls_instance);\n        cls_instance = nullptr;\n    }\n    std::string conf_path = \"/data/local/tmp/masimeng/cls/conf\";\n    cls_instance = ppspeech::ClsCreateInstance(conf_path.c_str());\n    return true;\n}\n\nextern \"C\"\nJNIEXPORT jboolean JNICALL Java_com_baidu_paddlespeech_cls_MainActivity_nClsDestroyInstance(JNIEnv *env, jobject instance){\n    if (cls_instance != nullptr) {\n        ppspeech::ClsDestroyInstance(cls_instance);\n        cls_instance = nullptr;\n    }\n    return true;\n}\n\nextern \"C\"\nJNIEXPORT jstring JNICALL Java_com_baidu_paddlespeech_cls_MainActivity_nClsFeedForward(JNIEnv *env, jobject instance){\n    if (cls_instance != nullptr) {\n        char result[1024] = {0};\n        std::string wav_path = \"/data/local/tmp/masimeng/cls/test.wav\";\n        int ret = ppspeech::ClsFeedForward(cls_instance, wav_path.c_str(), 1, result, 1024);\n        return env->NewStringUTF(result);\n    }\n    return env->NewStringUTF(NULL);\n}\n\nextern \"C\"\nJNIEXPORT jboolean JNICALL Java_com_baidu_paddlespeech_cls_MainActivity_nClsReset(JNIEnv *env, jobject instance){\n    if (cls_instance != nullptr) {\n        ppspeech::ClsReset(cls_instance);\n    }\n    return true;\n}"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/java/com/example/cls/MainActivity.kt",
    "content": "package com.baidu.paddlespeech.cls\n\nimport android.support.v7.app.AppCompatActivity\nimport android.os.Bundle\nimport android.widget.TextView\n\nclass MainActivity : AppCompatActivity() {\n    private lateinit var tvContent: TextView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n        tvContent = findViewById(R.id.tv_content)\n\n        nClsCreateInstance()\n        tvContent.text = nClsFeedForward()\n        nClsReset()\n        nClsDestroyInstance()\n    }\n\n    external fun nClsCreateInstance(): Boolean\n    external fun nClsDestroyInstance(): Boolean\n    external fun nClsFeedForward(): String\n    external fun nClsReset(): Boolean\n\n    companion object{\n        init {\n            System.loadLibrary(\"native-lib\")\n        }\n    }\n}"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\">\n    <TextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Hello World!\"\n        android:id=\"@+id/tv_content\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n  </android.support.constraint.ConstraintLayout>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"white\">#FFFFFFFF</color>\n</resources>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">cls</string>\n</resources>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.Cls\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_500</item>\n        <item name=\"colorPrimaryDark\">@color/purple_700</item>\n        <item name=\"colorAccent\">@color/teal_200</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/values-night/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.Cls\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_200</item>\n        <item name=\"colorPrimaryDark\">@color/purple_700</item>\n        <item name=\"colorAccent\">@color/teal_200</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/xml/backup_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample backup rules file; uncomment and customize as necessary.\n   See https://developer.android.com/guide/topics/data/autobackup\n   for details.\n   Note: This file is ignored for devices older that API 31\n   See https://developer.android.com/about/versions/12/backup-restore\n-->\n<full-backup-content>\n    <!--\n   <include domain=\"sharedpref\" path=\".\"/>\n   <exclude domain=\"sharedpref\" path=\"device.xml\"/>\n-->\n</full-backup-content>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/app/src/main/res/xml/data_extraction_rules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n   Sample data extraction rules file; uncomment and customize as necessary.\n   See https://developer.android.com/about/versions/12/backup-restore#xml-changes\n   for details.\n-->\n<data-extraction-rules>\n    <cloud-backup>\n        <!-- TODO: Use <include> and <exclude> to control what is backed up.\n        <include .../>\n        <exclude .../>\n        -->\n    </cloud-backup>\n    <!--\n    <device-transfer>\n        <include .../>\n        <exclude .../>\n    </device-transfer>\n    -->\n</data-extraction-rules>"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nplugins {\n    id 'com.android.application' version '7.3.1' apply false\n    id 'com.android.library' version '7.3.1' apply false\n    id 'org.jetbrains.kotlin.android' version '1.7.20' apply false\n}"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Jan 16 16:37:04 CST 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.4-bin.zip\ndistributionPath=wrapper/dists\nzipStorePath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\n# Enables namespacing of each library's R class so that its R class includes only the\n# resources declared in the library itself and none from the library's dependencies,\n# thereby reducing the size of the R class for that library\nandroid.nonTransitiveRClass=true"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "runtime/examples/audio_classification/android_demo/settings.gradle",
    "content": "pluginManagement {\n    repositories {\n        gradlePluginPortal()\n        google()\n        mavenCentral()\n    }\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\nrootProject.name = \"cls\"\ninclude ':app'\n"
  },
  {
    "path": "runtime/examples/audio_classification/conf",
    "content": "[CONF]\nwav_normal=true\nwav_normal_type=linear\nwav_norm_mul_factor=1.0\nmodel_path=./inference.onnx\nparam_path=\ndict_path=./label_list\nnum_cpu_thread=1\nsamp_freq=32000\nframe_length_ms=32\nframe_shift_ms=10\nnum_bins=64\nlow_freq=50\nhigh_freq=14000\ndither=0.0\n"
  },
  {
    "path": "runtime/examples/audio_classification/label_list",
    "content": "Dog\nRooster\nPig\nCow\nFrog\nCat\nHen\nInsects (flying)\nSheep\nCrow\nRain\nSea waves\nCrackling fire\nCrickets\nChirping birds\nWater drops\nWind\nPouring water\nToilet flush\nThunderstorm\nCrying baby\nSneezing\nClapping\nBreathing\nCoughing\nFootsteps\nLaughing\nBrushing teeth\nSnoring\nDrinking, sipping\nDoor knock\nMouse click\nKeyboard typing\nDoor, wood creaks\nCan opening\nWashing machine\nVacuum cleaner\nClock alarm\nClock tick\nGlass breaking\nHelicopter\nChainsaw\nSiren\nCar horn\nEngine\nTrain\nChurch bells\nAirplane\nFireworks\nHand saw\n"
  },
  {
    "path": "runtime/examples/audio_classification/scp",
    "content": "test.wav\n"
  },
  {
    "path": "runtime/examples/codelab/README.md",
    "content": "# Codelab\n\n> The below is for developing and offline testing. \n> Do not run it only if you know what it is.\n\n* nnet\n* feat\n* decoder\n* u2\n"
  },
  {
    "path": "runtime/examples/codelab/decoder/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "runtime/examples/codelab/decoder/README.md",
    "content": "# ASR Decoder\n\nASR Decoder test bins. We using theses bins to test CTC BeamSearch decoder and WFST decoder.\n\n* decoder_test_main.cc \nfeed nnet output logprob, and only test decoder\n\n* offline_decoder_sliding_chunk_main.cc\nfeed streaming audio feature, decode as streaming manner.\n\n* offline_wfst_decoder_main.cc\nfeed streaming audio feature, decode using WFST as streaming manner.\n"
  },
  {
    "path": "runtime/examples/codelab/decoder/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nSPEECHX_ROOT=$PWD/../../../\nSPEECHX_BUILD=$SPEECHX_ROOT/build/speechx\n\nSPEECHX_TOOLS=$SPEECHX_ROOT/tools\nTOOLS_BIN=$SPEECHX_TOOLS/valgrind/install/bin\n\n[ -d $SPEECHX_BUILD ] || { echo \"Error: 'build/speechx' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nSPEECHX_BIN=$SPEECHX_ROOT/build/speechx/decoder:$SPEECHX_ROOT/build/speechx/frontend/audio\nexport PATH=$PATH:$SPEECHX_BIN:$TOOLS_BIN\n"
  },
  {
    "path": "runtime/examples/codelab/decoder/run.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\n. path.sh\n\n# 1. compile\nif [ ! -d ${SPEECHX_EXAMPLES} ]; then\n    pushd ${SPEECHX_ROOT} \n    bash build.sh\n    popd\nfi\n\n# input\nmkdir -p data\ndata=$PWD/data\nckpt_dir=$data/model\nmodel_dir=$ckpt_dir/exp/deepspeech2_online/checkpoints/\nvocb_dir=$ckpt_dir/data/lang_char/\n\nlm=$data/zh_giga.no_cna_cmn.prune01244.klm\n\n# output\nexp_dir=./exp\nmkdir -p $exp_dir\n\n# 2. download model\nif [[ ! -f data/model/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz ]]; then\n    mkdir -p data/model\n    pushd data/model\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    tar xzfv asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    popd\nfi\n\n# produce wav scp\nif [ ! -f data/wav.scp ]; then\n    pushd data\n    wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n    echo \"utt1 \" $PWD/zh.wav > wav.scp\n    popd \nfi\n\n# download lm\nif [ ! -f $lm ]; then\n    pushd data\n    wget -c https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm\n    popd\nfi\n\nfeat_wspecifier=$exp_dir/feats.ark\ncmvn=$exp_dir/cmvn.ark\n\nexport GLOG_logtostderr=1\n\n# dump json cmvn to kaldi\ncmvn_json2kaldi_main \\\n    --json_file  $ckpt_dir/data/mean_std.json \\\n    --cmvn_write_path $cmvn \\\n    --binary=false\necho \"convert json cmvn to kaldi ark.\"\n\n\n# generate linear feature as streaming\ncompute_linear_spectrogram_main \\\n    --wav_rspecifier=scp:$data/wav.scp \\\n    --feature_wspecifier=ark,t:$feat_wspecifier \\\n    --cmvn_file=$cmvn\necho \"compute linear spectrogram feature.\"\n\n# run ctc beam search decoder as streaming\nctc_beam_search_decoder_main \\\n    --result_wspecifier=ark,t:$exp_dir/result.txt \\\n    --feature_rspecifier=ark:$feat_wspecifier \\\n    --model_path=$model_dir/avg_1.jit.pdmodel \\\n    --param_path=$model_dir/avg_1.jit.pdiparams \\\n    --dict_file=$vocb_dir/vocab.txt \\\n    --lm_path=$lm\n"
  },
  {
    "path": "runtime/examples/codelab/decoder/valgrind.sh",
    "content": "#!/bin/bash\n\n# this script is for memory check, so please run ./run.sh first.\n\nset +x\nset -e\n\n. ./path.sh\n\nif [ ! -d ${SPEECHX_TOOLS}/valgrind/install ]; then\n  echo \"please install valgrind in the speechx tools dir.\\n\" \n  exit 1\nfi\n\nmodel_dir=../paddle_asr_model\nfeat_wspecifier=./feats.ark\ncmvn=./cmvn.ark\n\nvalgrind --tool=memcheck --track-origins=yes --leak-check=full --show-leak-kinds=all \\\n  offline_decoder_main \\\n  --feature_respecifier=ark:$feat_wspecifier \\\n  --model_path=$model_dir/avg_1.jit.pdmodel \\\n  --param_path=$model_dir/avg_1.jit.pdparams \\\n  --dict_file=$model_dir/vocab.txt \\\n  --lm_path=$model_dir/avg_1.jit.klm\n\n"
  },
  {
    "path": "runtime/examples/codelab/feat/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "runtime/examples/codelab/feat/README.md",
    "content": "# Deepspeech2 Straming Audio Feature\n\nASR audio feature test bins. We using theses bins to test linaer/fbank/mfcc asr feature as streaming manner.\n\n* compute_linear_spectrogram_main.cc\n\ncompute linear spectrogram without db norm in streaming manner.\n"
  },
  {
    "path": "runtime/examples/codelab/feat/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nSPEECHX_ROOT=$PWD/../../../\nSPEECHX_BUILD=$SPEECHX_ROOT/build/speechx\n\nSPEECHX_TOOLS=$SPEECHX_ROOT/tools\nTOOLS_BIN=$SPEECHX_TOOLS/valgrind/install/bin\n\n[ -d $SPEECHX_BUILD ] || { echo \"Error: 'build/speechx' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nSPEECHX_BIN=$SPEECHX_ROOT/build/speechx/decoder:$SPEECHX_ROOT/build/speechx/frontend/audio\nexport PATH=$PATH:$SPEECHX_BIN:$TOOLS_BIN\n"
  },
  {
    "path": "runtime/examples/codelab/feat/run.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\n. ./path.sh\n\n# 1. compile\nif [ ! -d ${SPEECHX_EXAMPLES} ]; then\n    pushd ${SPEECHX_ROOT} \n    bash build.sh\n    popd\nfi\n\n# 2. download model\nif [ ! -e data/model/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz ]; then\n    mkdir -p data/model\n    pushd data/model\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    tar xzfv asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    popd\nfi\n\n# produce wav scp\nif [ ! -f data/wav.scp ]; then\n    mkdir -p data\n    pushd data\n    wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n    echo \"utt1 \" $PWD/zh.wav > wav.scp\n    popd \nfi\n\n\n# input\ndata_dir=./data\nexp_dir=./exp\nmodel_dir=$data_dir/model/\n\nmkdir -p $exp_dir\n\n\n# 3. run feat\nexport GLOG_logtostderr=1\n\ncmvn_json2kaldi_main \\\n    --json_file=$model_dir/data/mean_std.json \\\n    --cmvn_write_path=$exp_dir/cmvn.ark \\\n    --binary=false\necho \"convert json cmvn to kaldi ark.\"\n\n\ncompute_linear_spectrogram_main \\\n    --wav_rspecifier=scp:$data_dir/wav.scp \\\n    --feature_wspecifier=ark,t:$exp_dir/feats.ark \\\n    --cmvn_file=$exp_dir/cmvn.ark\necho \"compute linear spectrogram feature.\"\n\ncompute_fbank_main \\\n    --num_bins=161 \\\n    --wav_rspecifier=scp:$data_dir/wav.scp \\\n    --feature_wspecifier=ark,t:$exp_dir/fbank.ark \\\n    --cmvn_file=$exp_dir/cmvn.ark\necho \"compute fbank feature.\"\n\n"
  },
  {
    "path": "runtime/examples/codelab/feat/valgrind.sh",
    "content": "#!/bin/bash\n\n# this script is for memory check, so please run ./run.sh first.\n\nset +x\nset -e\n\n. ./path.sh\n\nif [ ! -d ${SPEECHX_TOOLS}/valgrind/install ]; then\n  echo \"please install valgrind in the speechx tools dir.\\n\" \n  exit 1\nfi\n\nmodel_dir=../paddle_asr_model\nfeat_wspecifier=./feats.ark\ncmvn=./cmvn.ark\n\nvalgrind --tool=memcheck --track-origins=yes --leak-check=full --show-leak-kinds=all \\\n  compute_linear_spectrogram_main \\\n  --wav_rspecifier=scp:$model_dir/wav.scp \\\n  --feature_wspecifier=ark,t:$feat_wspecifier \\\n  --cmvn_write_path=$cmvn\n\n"
  },
  {
    "path": "runtime/examples/codelab/nnet/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "runtime/examples/codelab/nnet/README.md",
    "content": "# Deepspeech2 Streaming NNet Test\n\nUsing for ds2 streaming nnet inference test.\n"
  },
  {
    "path": "runtime/examples/codelab/nnet/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nSPEECHX_ROOT=$PWD/../../../\nSPEECHX_BUILD=$SPEECHX_ROOT/build/speechx\n\nSPEECHX_TOOLS=$SPEECHX_ROOT/tools\nTOOLS_BIN=$SPEECHX_TOOLS/valgrind/install/bin\n\n[ -d $SPEECHX_BUILD ] || { echo \"Error: 'build/speechx' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nSPEECHX_BIN=$SPEECHX_BUILD/codelab/nnet\nexport PATH=$PATH:$SPEECHX_BIN:$TOOLS_BIN\n"
  },
  {
    "path": "runtime/examples/codelab/nnet/run.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\n. path.sh\n\n# 1. compile\nif [ ! -d ${SPEECHX_EXAMPLES} ]; then\n    pushd ${SPEECHX_ROOT} \n    bash build.sh\n    popd\nfi\n\n# 2. download model\nif [ ! -f data/model/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz ]; then\n    mkdir -p data/model\n    pushd data/model\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    tar xzfv asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz\n    popd\nfi\n\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/exp/deepspeech2_online/checkpoints/\n\nds2_model_test_main \\\n    --model_path=$model_dir/avg_1.jit.pdmodel \\\n    --param_path=$model_dir/avg_1.jit.pdiparams\n\n"
  },
  {
    "path": "runtime/examples/codelab/nnet/valgrind.sh",
    "content": "#!/bin/bash\n\n# this script is for memory check, so please run ./run.sh first.\n\nset +x\nset -e\n\n. ./path.sh\n\nif [ ! -d ${SPEECHX_TOOLS}/valgrind/install ]; then\n  echo \"please install valgrind in the speechx tools dir.\\n\" \n  exit 1\nfi\n\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/exp/deepspeech2_online/checkpoints/\n\nvalgrind --tool=memcheck --track-origins=yes --leak-check=full --show-leak-kinds=all \\\n  ds2_model_test_main \\\n  --model_path=$model_dir/avg_1.jit.pdmodel \\\n  --param_path=$model_dir/avg_1.jit.pdparams\n"
  },
  {
    "path": "runtime/examples/codelab/u2/.gitignore",
    "content": "data\n"
  },
  {
    "path": "runtime/examples/codelab/u2/README.md",
    "content": "# u2/u2pp Streaming Test\n"
  },
  {
    "path": "runtime/examples/codelab/u2/local/decode.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\n. path.sh\n\ndata=data\nexp=exp\nmkdir -p $exp\nckpt_dir=$data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/\n\nctc_prefix_beam_search_decoder_main \\\n    --model_path=$model_dir/export.jit \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --vocab_path=$model_dir/unit.txt \\\n    --feature_rspecifier=ark,t:$exp/fbank.ark \\\n    --result_wspecifier=ark,t:$exp/result.ark\n\necho \"u2 ctc prefix beam search decode.\"\n"
  },
  {
    "path": "runtime/examples/codelab/u2/local/feat.sh",
    "content": "#!/bin/bash\nset -x\nset -e\n\n. path.sh\n\ndata=data\nexp=exp\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/\n\n\ncmvn_json2kaldi_main \\\n    --json_file  $model_dir/mean_std.json \\\n    --cmvn_write_path $exp/cmvn.ark \\\n    --binary=false\n\necho \"convert json cmvn to kaldi ark.\"\n\ncompute_fbank_main \\\n    --num_bins 80 \\\n    --wav_rspecifier=scp:$data/wav.scp \\\n    --cmvn_file=$exp/cmvn.ark \\\n    --feature_wspecifier=ark,t:$exp/fbank.ark\n\necho \"compute fbank feature.\"\n"
  },
  {
    "path": "runtime/examples/codelab/u2/local/nnet.sh",
    "content": "#!/bin/bash\nset -x\nset -e\n\n. path.sh\n\ndata=data\nexp=exp\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/\n\nu2_nnet_main \\\n    --model_path=$model_dir/export.jit \\\n    --feature_rspecifier=ark,t:$exp/fbank.ark \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --acoustic_scale=1.0 \\\n    --nnet_encoder_outs_wspecifier=ark,t:$exp/encoder_outs.ark \\\n    --nnet_prob_wspecifier=ark,t:$exp/logprobs.ark\necho \"u2 nnet decode.\"\n\n"
  },
  {
    "path": "runtime/examples/codelab/u2/local/recognizer.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\ndata=data\nexp=exp\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/\n\nu2_recognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --cmvn_file=$exp/cmvn.ark \\\n    --model_path=$model_dir/export.jit \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --vocab_path=$model_dir/unit.txt \\\n    --wav_rspecifier=scp:$data/wav.scp \\\n    --result_wspecifier=ark,t:$exp/result.ark\n"
  },
  {
    "path": "runtime/examples/codelab/u2/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nunset GREP_OPTIONS\n\nSPEECHX_ROOT=$PWD/../../../\nSPEECHX_BUILD=$SPEECHX_ROOT/build/speechx\n\nSPEECHX_TOOLS=$SPEECHX_ROOT/tools\nTOOLS_BIN=$SPEECHX_TOOLS/valgrind/install/bin\n\n[ -d $SPEECHX_BUILD ] || { echo \"Error: 'build/speechx' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nexport PATH=$PATH:$TOOLS_BIN:$SPEECHX_BUILD/nnet:$SPEECHX_BUILD/decoder:$SPEECHX_BUILD/frontend/audio:$SPEECHX_BUILD/recognizer\n\nPADDLE_LIB_PATH=$(python -c \"import os; import paddle; include_dir=paddle.sysconfig.get_include(); paddle_dir=os.path.split(include_dir)[0]; libs_dir=os.path.join(paddle_dir, 'libs'); fluid_dir=os.path.join(paddle_dir, 'fluid'); out=':'.join([libs_dir, fluid_dir]); print(out);\")\nexport LD_LIBRARY_PATH=$PADDLE_LIB_PATH:$LD_LIBRARY_PATH\n"
  },
  {
    "path": "runtime/examples/codelab/u2/run.sh",
    "content": "#!/bin/bash\nset -x\nset -e\n\n. path.sh\n\n# 1. compile\nif [ ! -d ${SPEECHX_EXAMPLES} ]; then\n    pushd ${SPEECHX_ROOT} \n    bash build.sh\n    popd\nfi\n\n# 2. download model\nif [ ! -f data/model/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model.tar.gz ]; then\n    mkdir -p data/model\n    pushd data/model\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/static/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model.tar.gz\n    tar xzfv asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model.tar.gz\n    popd\nfi\n\n# produce wav scp\nif [ ! -f data/wav.scp ]; then\n    mkdir -p data\n    pushd data\n    wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n    echo \"utt1 \" $PWD/zh.wav > wav.scp\n    popd \nfi\n\ndata=data\nexp=exp\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/\n\n\n./local/feat.sh\n\n./local/nnet.sh\n\n./local/decode.sh\n"
  },
  {
    "path": "runtime/examples/custom_asr/README.md",
    "content": "# Customized ASR\n\n## introduction\nThese scripts are tutorials to show you how build your own decoding graph.\n\neg:\n* G with slot: 打车到 \"address_slot\"。\n![](https://ai-studio-static-online.cdn.bcebos.com/28d9ef132a7f47a895a65ae9e5c4f55b8f472c9f3dd24be8a2e66e0b88b173a4)\n\n* this is address slot wfst, you can add the address which want to recognize.\n![](https://ai-studio-static-online.cdn.bcebos.com/47c89100ef8c465bac733605ffc53d76abefba33d62f4d818d351f8cea3c8fe2)\n\n* after replace operation, G = fstreplace(G_with_slot, address_slot), we will get the customized graph.\n![](https://ai-studio-static-online.cdn.bcebos.com/60a3095293044f10b73039ab10c7950d139a6717580a44a3ba878c6e74de402b)\n\nThese operations are in the scripts, please check out. we will launch more detail scripts.\n\n## How to run\n\n```\nbash run.sh\n```\n\n## Results\n\n### CTC WFST\n\n```\nOverall -> 1.23 % N=1134 C=1126 S=6 D=2 I=6\nMandarin -> 1.24 % N=1132 C=1124 S=6 D=2 I=6\nEnglish -> 0.00 % N=2 C=2 S=0 D=0 I=0\n```\n"
  },
  {
    "path": "runtime/examples/custom_asr/local/compile_lexicon_token_fst.sh",
    "content": "#!/bin/bash\n# Copyright 2015       Yajie Miao    (Carnegie Mellon University)\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#  http://www.apache.org/licenses/LICENSE-2.0\n#\n# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\n# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\n# MERCHANTABLITY OR NON-INFRINGEMENT.\n# See the Apache 2 License for the specific language governing permissions and\n# limitations under the License.\n\n# This script compiles the lexicon and CTC tokens into FSTs. FST compiling slightly differs between the\n# phoneme and character-based lexicons.\nset -eo pipefail\n. utils/parse_options.sh\n\nif [ $# -ne 3 ]; then\n  echo \"usage: utils/fst/compile_lexicon_token_fst.sh <dict-src-dir> <tmp-dir> <lang-dir>\"\n  echo \"e.g.: utils/fst/compile_lexicon_token_fst.sh data/local/dict data/local/lang_tmp data/lang\"\n  echo \"<dict-src-dir> should contain the following files:\"\n  echo \"lexicon.txt lexicon_numbers.txt units.txt\"\n  echo \"options: \"\n  exit 1;\nfi\n\nsrcdir=$1\ntmpdir=$2\ndir=$3\nmkdir -p $dir $tmpdir\n\n[ -f path.sh ] && . ./path.sh\n\ncp $srcdir/units.txt $dir\n\n# Add probabilities to lexicon entries. There is in fact no point of doing this here since all the entries have 1.0.\n# But utils/make_lexicon_fst.pl requires a probabilistic version, so we just leave it as it is.\nperl -ape 's/(\\S+\\s+)(.+)/${1}1.0\\t$2/;' < $srcdir/lexicon.txt > $tmpdir/lexiconp.txt || exit 1;\n\n# Add disambiguation symbols to the lexicon. This is necessary for determinizing the composition of L.fst and G.fst.\n# Without these symbols, determinization will fail.\n# default first disambiguation is #1\nndisambig=`utils/fst/add_lex_disambig.pl $tmpdir/lexiconp.txt $tmpdir/lexiconp_disambig.txt`\n# add #0 (#0 reserved for symbol in grammar).\nndisambig=$[$ndisambig+1];\n\n( for n in `seq 0 $ndisambig`; do echo '#'$n; done ) > $tmpdir/disambig.list\n\n# Get the full list of CTC tokens used in FST. These tokens include <eps>, the blank <blk>,\n# the actual model unit, and the disambiguation symbols.\ncat $srcdir/units.txt | awk '{print $1}' > $tmpdir/units.list\n(echo '<eps>';) | cat - $tmpdir/units.list $tmpdir/disambig.list | awk '{print $1 \" \" (NR-1)}' > $dir/tokens.txt\n\n# ctc_token_fst_corrected is too big and too slow for character based chinese modeling,\n# so here just use simple ctc_token_fst\nutils/fst/ctc_token_fst.py --token_file $dir/tokens.txt | \\\n  fstcompile --isymbols=$dir/tokens.txt --osymbols=$dir/tokens.txt --keep_isymbols=false --keep_osymbols=false | \\\n  fstarcsort --sort_type=olabel > $dir/T.fst || exit 1;\n\n# Encode the words with indices. Will be used in lexicon and language model FST compiling.\ncat $tmpdir/lexiconp.txt | awk '{print $1}' | sort | awk '\n  BEGIN {\n    print \"<eps> 0\";\n  }\n  {\n    printf(\"%s %d\\n\", $1, NR);\n  }\n  END {\n    printf(\"#0 %d\\n\", NR+1);\n    printf(\"<s> %d\\n\", NR+2);\n    printf(\"</s> %d\\n\", NR+3);\n    printf(\"ROOT %d\\n\", NR+4);\n  }' > $dir/words.txt || exit 1;\n\n# Now compile the lexicon FST. Depending on the size of your lexicon, it may take some time.\ntoken_disambig_symbol=`grep \\#0 $dir/tokens.txt | awk '{print $2}'`\nword_disambig_symbol=`grep \\#0 $dir/words.txt | awk '{print $2}'`\n\nutils/fst/make_lexicon_fst.pl --pron-probs $tmpdir/lexiconp_disambig.txt 0 \"sil\" '#'$ndisambig | \\\n  fstcompile --isymbols=$dir/tokens.txt --osymbols=$dir/words.txt \\\n  --keep_isymbols=false --keep_osymbols=false |   \\\n  fstaddselfloops  \"echo $token_disambig_symbol |\" \"echo $word_disambig_symbol |\" | \\\n  fstarcsort --sort_type=olabel > $dir/L.fst || exit 1;\n\necho \"Lexicon and Token FSTs compiling succeeded\"\n"
  },
  {
    "path": "runtime/examples/custom_asr/local/mk_slot_graph.sh",
    "content": "#!/bin/bash\n\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License\n\ngraph_slot=$1\ndir=$2\n\n[ -f path.sh ] && . ./path.sh\n\nsym=$dir/../lang/words.txt\ncat > $dir/address_slot.txt <<EOF\n0 1 南山 南山\n0 1 南京 南京\n0 1 光明 光明   \n0 1 龙岗 龙岗\n0 1 北苑 北苑\n0 1 北京 北京\n0 1 酒店 酒店\n0 1 合肥 合肥\n0 1 望京搜后 望京搜后\n0 1 地铁站 地铁站\n0 1 海淀黄庄 海淀黄庄\n0 1 佛山 佛山\n0 1 广州 广州\n0 1 苏州 苏州\n0 1 百度大厦 百度大厦\n0 1 龙泽苑东区 龙泽苑东区\n0 1 首都机场 首都机场\n0 1 朝来家园 朝来家园\n0 1 深大 深大\n0 1 双龙 双龙\n0 1 公司 公司\n0 1 上海 上海\n0 1 家 家\n0 1 机场 机场\n0 1 华祝 华祝\n0 1 上海虹桥 上海虹桥\n0 2 检验 检验\n2 1 中心 中心\n0 3 苏州 苏州\n3 1 街 街\n3 8 高铁 高铁\n8 1 站 站\n0 4 杭州 杭州\n4 1 东站 东站\n4 1 <eps> <eps>\n0 5 上海 上海\n0 5 北京 北京\n0 5 合肥 合肥\n5 1 南站 南站\n0 6 立水 立水\n6 1 桥 桥\n0 7 青岛 青岛\n7 1 站 站\n1\nEOF\n\nfstcompile --isymbols=$sym --osymbols=$sym $dir/address_slot.txt $dir/address_slot.fst\nfstcompile --isymbols=$sym --osymbols=$sym $graph_slot/time_slot.txt $dir/time_slot.fst\nfstcompile --isymbols=$sym --osymbols=$sym $graph_slot/date_slot.txt $dir/date_slot.fst\nfstcompile --isymbols=$sym --osymbols=$sym $graph_slot/money_slot.txt $dir/money_slot.fst\nfstcompile --isymbols=$sym --osymbols=$sym $graph_slot/year_slot.txt $dir/year_slot.fst\n"
  },
  {
    "path": "runtime/examples/custom_asr/local/mk_tlg_with_slot.sh",
    "content": "#!/bin/bash\n\n# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License\n\nlm=$1\nlang=$2\ntgt_lang=$3\n\nunset GREP_OPTIONS\n\nsym=$lang/words.txt\narpa_lm=$lm/lm.arpa\n# Compose the language model to FST\ncat $arpa_lm | \\\n   grep -v '<s> <s>' | \\\n   grep -v '</s> <s>' | \\\n   grep -v '</s> </s>' | \\\n   grep -v -i '<unk>' | \\\n   grep -v -i '<spoken_noise>' | \\\n   arpa2fst --read-symbol-table=$sym --keep-symbols=true - | fstprint | \\\n   utils/fst/eps2disambig.pl | utils/fst/s2eps.pl | fstcompile --isymbols=$sym \\\n     --osymbols=$sym --keep_isymbols=false --keep_osymbols=false | \\\n    fstrmepsilon | fstarcsort --sort_type=ilabel > $tgt_lang/G_with_slot.fst\n\nroot_label=`grep ROOT $sym | awk '{print $2}'`\naddress_slot_label=`grep \\<ADDRESS_SLOT\\> $sym | awk '{print $2}'`\ntime_slot_label=`grep \\<TIME_SLOT\\> $sym | awk '{print $2}'`\ndate_slot_label=`grep \\<DATE_SLOT\\> $sym | awk '{print $2}'`\nmoney_slot_label=`grep \\<MONEY_SLOT\\> $sym | awk '{print $2}'`\nyear_slot_label=`grep \\<YEAR_SLOT\\> $sym | awk '{print $2}'`\n\nfstisstochastic $tgt_lang/G_with_slot.fst\n\nfstreplace --epsilon_on_replace $tgt_lang/G_with_slot.fst \\\n  $root_label $tgt_lang/address_slot.fst $address_slot_label \\\n  $tgt_lang/date_slot.fst $date_slot_label \\\n  $tgt_lang/money_slot.fst $money_slot_label \\\n  $tgt_lang/time_slot.fst $time_slot_label \\\n  $tgt_lang/year_slot.fst $year_slot_label $tgt_lang/G.fst\n\nfstisstochastic $tgt_lang/G.fst\n\n# Compose the token, lexicon and language-model FST into the final decoding graph\nfsttablecompose $lang/L.fst $tgt_lang/G.fst | fstdeterminizestar --use-log=true | \\\n    fstminimizeencoded | fstarcsort --sort_type=ilabel > $tgt_lang/LG.fst || exit 1;\nfsttablecompose $lang/T.fst $tgt_lang/LG.fst > $tgt_lang/TLG.fst || exit 1;\nrm $tgt_lang/LG.fst\n\necho \"Composing decoding graph TLG.fst succeeded\""
  },
  {
    "path": "runtime/examples/custom_asr/local/train_lm_with_slot.sh",
    "content": "#!/bin/bash\n\n# To be run from one directory above this script.\n. ./path.sh\nsrc=ds2_graph_with_slot\ntext=$src/train_text\nlexicon=$src/local/dict/lexicon.txt\n\ndir=$src/local/lm\nmkdir -p $dir\n\nfor f in \"$text\" \"$lexicon\"; do\n  [ ! -f $x ] && echo \"$0: No such file $f\" && exit 1;\ndone\n\n# Check SRILM tools\nif ! which ngram-count > /dev/null; then\n  pushd $MAIN_ROOT/tools\n  make srilm.done\n  popd\nfi\n\n# This script takes no arguments.  It assumes you have already run\n# It takes as input the files\n# data/local/lm/text\n# data/local/dict/lexicon.txt\n\n\ncleantext=$dir/text.no_oov\n\ncat $text | awk -v lex=$lexicon 'BEGIN{while((getline<lex) >0){ seen[$1]=1; } }\n  {for(n=1; n<=NF;n++) {  if (seen[$n]) { printf(\"%s \", $n); } else {printf(\"<SPOKEN_NOISE> \");} } printf(\"\\n\");}' \\\n  > $cleantext || exit 1;\n\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | sort | uniq -c | \\\n   sort -nr > $dir/word.counts || exit 1;\n# Get counts from acoustic training transcripts, and add  one-count\n# for each word in the lexicon (but not silence, we don't want it\n# in the LM-- we'll add it optionally later).\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | \\\n  cat - <(grep -w -v '!SIL' $lexicon | awk '{print $1}') | \\\n   sort | uniq -c | sort -nr > $dir/unigram.counts || exit 1;\n\n# filter the words which are not in the text\ncat $dir/unigram.counts | awk '$1>1{print $0}' | awk '{print $2}' | cat - <(echo \"<s>\"; echo \"</s>\" ) > $dir/wordlist\n\n# kaldi_lm results\nmkdir -p $dir\ncat $cleantext | awk '{for(n=2;n<=NF;n++){ printf $n; if(n<NF) printf \" \"; else print \"\"; }}' > $dir/train\n\nngram-count -text $dir/train -order 3 -limit-vocab -vocab $dir/wordlist -unk \\\n  -map-unk \"<UNK>\" -gt3max 0 -gt2max 0 -gt1max 0 -lm $dir/lm.arpa\n\n#ngram-count -text $dir/train -order 3 -limit-vocab -vocab $dir/wordlist -unk \\\n#  -map-unk \"<UNK>\" -lm $dir/lm2.arpa"
  },
  {
    "path": "runtime/examples/custom_asr/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nMAIN_ROOT=`realpath $PWD/../../../`\nRUNTIME_ROOT=`realpath $MAIN_ROOT/runtime`\nRUNTIME_EXAMPLES=$RUNTIME_ROOT/build/examples\n\nexport LC_AL=C\n\n# srilm\nexport LIBLBFGS=${MAIN_ROOT}/tools/liblbfgs-1.10\nexport LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:${LIBLBFGS}/lib/.libs\nexport SRILM=${MAIN_ROOT}/tools/srilm\n\n# kaldi lm\nKALDI_DIR=$RUNTIME_ROOT/build/engine/kaldi/\nOPENFST_DIR=$RUNTIME_ROOT/fc_patch/openfst-build/src\nexport PATH=${PATH}:${SRILM}/bin:${SRILM}/bin/i686-m64:$KALDI_DIR/lmbin:$KALDI_DIR/fstbin:$OPENFST_DIR/bin:$SPEECHX_EXAMPLES/ds2_ol/decoder\n"
  },
  {
    "path": "runtime/examples/custom_asr/run.sh",
    "content": "#!/bin/bash\nset +x\nset -e\n\nexport GLOG_logtostderr=1\n\n. ./path.sh || exit 1;\n\n# ds2 means deepspeech2 (acoutic model type)\ndir=$PWD/exp/ds2_graph_with_slot\ndata=$PWD/data\nstage=0\nstop_stage=10\n\nmkdir -p $dir\n\nmodel_dir=$PWD/resource/model\nvocab=$model_dir/vocab.txt\ncmvn=$data/cmvn.ark\ntext_with_slot=$data/text_with_slot\nresource=$PWD/resource\n# download resource\nif [ ! -f $cmvn ]; then\n    wget -c https://paddlespeech.cdn.bcebos.com/s2t/paddle_asr_online/resource.tar.gz\n    tar xzfv resource.tar.gz\n    ln -s ./resource/data .\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n  # make dict\n  unit_file=$vocab\n  mkdir -p $dir/local/dict\n  cp $unit_file $dir/local/dict/units.txt\n  cp $text_with_slot $dir/train_text\n  utils/fst/prepare_dict.py --unit_file $unit_file --in_lexicon $data/lexicon.txt \\\n    --out_lexicon $dir/local/dict/lexicon.txt\n  # add slot to lexicon, just in case the lm training script filter the slot.\n  echo \"<MONEY_SLOT> 一\" >> $dir/local/dict/lexicon.txt\n  echo \"<DATE_SLOT> 一\" >> $dir/local/dict/lexicon.txt\n  echo \"<ADDRESS_SLOT> 一\" >> $dir/local/dict/lexicon.txt\n  echo \"<YEAR_SLOT> 一\" >> $dir/local/dict/lexicon.txt\n  echo \"<TIME_SLOT> 一\" >> $dir/local/dict/lexicon.txt\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n  # train lm\n  lm=$dir/local/lm\n  mkdir -p $lm\n  # this script is different with the common lm training script\n  local/train_lm_with_slot.sh\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n  # make T & L\n  local/compile_lexicon_token_fst.sh $dir/local/dict $dir/local/tmp $dir/local/lang\n  mkdir -p $dir/local/lang_test\n  # make slot graph\n  local/mk_slot_graph.sh $resource/graph $dir/local/lang_test\n  # make TLG\n  local/mk_tlg_with_slot.sh $dir/local/lm $dir/local/lang $dir/local/lang_test || exit 1;\n  mv $dir/local/lang_test/TLG.fst $dir/local/lang/\nfi\n\nif [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then\n  # test TLG\n  model_dir=$PWD/resource/model\n  cmvn=$data/cmvn.ark\n  wav_scp=$data/wav.scp\n  graph=$dir/local/lang\n\n  recognizer_test_main \\\n    --wav_rspecifier=scp:$wav_scp \\\n    --cmvn_file=$cmvn \\\n    --use_fbank=true \\\n    --model_path=$model_dir/avg_10.jit.pdmodel \\\n    --param_path=$model_dir/avg_10.jit.pdiparams \\\n    --model_cache_shapes=\"5-1-2048,5-1-2048\" \\\n    --model_output_names=softmax_0.tmp_0,tmp_5,concat_0.tmp_0,concat_1.tmp_0 \\\n    --word_symbol_table=$graph/words.txt \\\n    --graph_path=$graph/TLG.fst --max_active=7500 \\\n    --acoustic_scale=12 \\\n    --result_wspecifier=ark,t:./exp/result_run.txt\n\n    # the data/wav.trans is the label.\n    utils/compute-wer.py --char=1 --v=1 data/wav.trans exp/result_run.txt > exp/wer_run\n    tail -n 7 exp/wer_run\nfi\n"
  },
  {
    "path": "runtime/examples/text_lm/.gitignore",
    "content": "data\n"
  },
  {
    "path": "runtime/examples/text_lm/README.md",
    "content": "# Text PreProcess for building ngram LM\n\n## Input\n\n```\ndata/\n|-- text\n```\n\nInput file is kaldi-style, which has `utt` at first column: \n```\nY0000000000_--5llN02F84_S00000  怎么样这些日子住得还习惯吧\nY0000000000_--5llN02F84_S00002  挺好的\nY0000000000_--5llN02F84_S00003  对了美静这段日子经常不和我们一起用餐\nY0000000000_--5llN02F84_S00004  是不是对我回来有什么想法啊\nY0000000000_--5llN02F84_S00005  哪有的事啊\nY0000000000_--5llN02F84_S00006  她这两天挺累的身体也不太舒服\nY0000000000_--5llN02F84_S00007  我让她多睡一会那就好如果要是觉得不方便\nY0000000000_--5llN02F84_S00009  我就搬出去住\nY0000000000_--5llN02F84_S00010  你看你这个人你就是疑心太重\nY0000000000_--5llN02F84_S00011  你现在多好一切都井然有序的\n```\n\n\n## Output\n\n```\ndata/\n`-- text.tn\n```\n\nOutput file like this:\n\n```\nBAC009S0002W0122 而 对 楼市 成交 抑制 作用 最 大 的 限 购\nBAC009S0002W0123 也 成为 地方 政府 的 眼中 钉\nBAC009S0002W0124 自 六月 底 呼和浩特 市 率先 宣布 取消 限 购 后\nBAC009S0002W0125 各地 政府 便 纷纷 跟进\nBAC009S0002W0126 仅 一 个 多 月 的 时间 里\nBAC009S0002W0127 除了 北京 上海 广州 深圳 四 个 一 线 城市 和 三亚 之外\nBAC009S0002W0128 四十六 个 限 购 城市 当中\nBAC009S0002W0129 四十一 个 已 正式 取消 或 变相 放松 了 限 购\nBAC009S0002W0130 财政 金融 政策 紧随 其后 而来\n```\n"
  },
  {
    "path": "runtime/examples/text_lm/local/mmseg.py",
    "content": "#!/usr/bin/env python3\n# modify from https://sites.google.com/site/homepageoffuyanwei/Home/remarksandexcellentdiscussion/page-2\n\n\nclass Word:\n    def __init__(self, text='', freq=0):\n        self.text = text\n        self.freq = freq\n        self.length = len(text)\n\n\nclass Chunk:\n    def __init__(self, w1, w2=None, w3=None):\n        self.words = []\n        self.words.append(w1)\n        if w2:\n            self.words.append(w2)\n        if w3:\n            self.words.append(w3)\n\n    #计算chunk的总长度  \n    def totalWordLength(self):\n        length = 0\n        for word in self.words:\n            length += len(word.text)\n        return length\n\n    #计算平均长度  \n    def averageWordLength(self):\n        return float(self.totalWordLength()) / float(len(self.words))\n\n    #计算标准差  \n    def standardDeviation(self):\n        average = self.averageWordLength()\n        sum = 0.0\n        for word in self.words:\n            tmp = (len(word.text) - average)\n            sum += float(tmp) * float(tmp)\n        return sum\n\n    #自由语素度  \n    def wordFrequency(self):\n        sum = 0\n        for word in self.words:\n            sum += word.freq\n        return sum\n\n\nclass ComplexCompare:\n    def takeHightest(self, chunks, comparator):\n        i = 1\n        for j in range(1, len(chunks)):\n            rlt = comparator(chunks[j], chunks[0])\n            if rlt > 0:\n                i = 0\n            if rlt >= 0:\n                chunks[i], chunks[j] = chunks[j], chunks[i]\n                i += 1\n        return chunks[0:i]\n\n    #以下四个函数是mmseg算法的四种过滤原则，核心算法  \n    def mmFilter(self, chunks):\n        def comparator(a, b):\n            return a.totalWordLength() - b.totalWordLength()\n\n        return self.takeHightest(chunks, comparator)\n\n    def lawlFilter(self, chunks):\n        def comparator(a, b):\n            return a.averageWordLength() - b.averageWordLength()\n\n        return self.takeHightest(chunks, comparator)\n\n    def svmlFilter(self, chunks):\n        def comparator(a, b):\n            return b.standardDeviation() - a.standardDeviation()\n\n        return self.takeHightest(chunks, comparator)\n\n    def logFreqFilter(self, chunks):\n        def comparator(a, b):\n            return a.wordFrequency() - b.wordFrequency()\n\n        return self.takeHightest(chunks, comparator)\n\n\n#加载词组字典和字符字典\ndictWord = {}\nmaxWordLength = 0\n\n\ndef loadDictChars(filepath):\n    global maxWordLength\n    fsock = open(filepath)\n    for line in fsock:\n        freq, word = line.split()\n        word = word.strip()\n        dictWord[word] = (len(word), int(freq))\n        maxWordLength = len(word) if maxWordLength < len(\n            word) else maxWordLength\n    fsock.close()\n\n\ndef loadDictWords(filepath):\n    global maxWordLength\n    fsock = open(filepath)\n    for line in fsock.readlines():\n        word = line.strip()\n        dictWord[word] = (len(word), 0)\n        maxWordLength = len(word) if maxWordLength < len(\n            word) else maxWordLength\n    fsock.close()\n\n\n#判断该词word是否在字典dictWord中      \ndef getDictWord(word):\n    result = dictWord.get(word)\n    if result:\n        return Word(word, result[1])\n    return None\n\n\n#开始加载字典  \ndef run():\n    from os.path import join, dirname\n    loadDictChars(join(dirname(__file__), 'data', 'chars.dic'))\n    loadDictWords(join(dirname(__file__), 'data', 'words.dic'))\n\n\nclass Analysis:\n    def __init__(self, text):\n        self.text = text\n        self.cacheSize = 3\n        self.pos = 0\n        self.textLength = len(self.text)\n        self.cache = []\n        self.cacheIndex = 0\n        self.complexCompare = ComplexCompare()\n\n        #简单小技巧，用到个缓存，不知道具体有没有用处  \n        for i in range(self.cacheSize):\n            self.cache.append([-1, Word()])\n\n        #控制字典只加载一次  \n        if not dictWord:\n            run()\n\n    def __iter__(self):\n        while True:\n            token = self.getNextToken()\n            if token is None:\n                raise StopIteration\n            yield token\n\n    def getNextChar(self):\n        return self.text[self.pos]\n\n    #判断该字符是否是中文字符（不包括中文标点）    \n    def isChineseChar(self, character):\n        return 0x4e00 <= ord(character) < 0x9fa6\n\n    #判断是否是ASCII码  \n    def isASCIIChar(self, ch):\n        import string\n        if ch in string.whitespace:\n            return False\n        if ch in string.punctuation:\n            return False\n        return ch in string.printable\n\n    #得到下一个切割结果  \n    def getNextToken(self):\n        while self.pos < self.textLength:\n            if self.isChineseChar(self.getNextChar()):\n                token = self.getChineseWords()\n            else:\n                token = self.getASCIIWords() + '/'\n            if len(token) > 0:\n                return token\n        return None\n\n    #切割出非中文词  \n    def getASCIIWords(self):\n        # Skip pre-word whitespaces and punctuations  \n        #跳过中英文标点和空格  \n        while self.pos < self.textLength:\n            ch = self.getNextChar()\n            if self.isASCIIChar(ch) or self.isChineseChar(ch):\n                break\n            self.pos += 1\n        #得到英文单词的起始位置      \n        start = self.pos\n\n        #找出英文单词的结束位置  \n        while self.pos < self.textLength:\n            ch = self.getNextChar()\n            if not self.isASCIIChar(ch):\n                break\n            self.pos += 1\n        end = self.pos\n\n        #Skip chinese word whitespaces and punctuations  \n        #跳过中英文标点和空格  \n        while self.pos < self.textLength:\n            ch = self.getNextChar()\n            if self.isASCIIChar(ch) or self.isChineseChar(ch):\n                break\n            self.pos += 1\n\n        #返回英文单词  \n        return self.text[start:end]\n\n    #切割出中文词，并且做处理，用上述4种方法  \n    def getChineseWords(self):\n        chunks = self.createChunks()\n        if len(chunks) > 1:\n            chunks = self.complexCompare.mmFilter(chunks)\n        if len(chunks) > 1:\n            chunks = self.complexCompare.lawlFilter(chunks)\n        if len(chunks) > 1:\n            chunks = self.complexCompare.svmlFilter(chunks)\n        if len(chunks) > 1:\n            chunks = self.complexCompare.logFreqFilter(chunks)\n        if len(chunks) == 0:\n            return ''\n\n        #最后只有一种切割方法  \n        word = chunks[0].words\n        token = \"\"\n        length = 0\n        for x in word:\n            if x.length != -1:\n                token += x.text + \"/\"\n                length += len(x.text)\n        self.pos += length\n        return token\n\n    #三重循环来枚举切割方法，这里也可以运用递归来实现  \n    def createChunks(self):\n        chunks = []\n        originalPos = self.pos\n        words1 = self.getMatchChineseWords()\n\n        for word1 in words1:\n            self.pos += len(word1.text)\n            if self.pos < self.textLength:\n                words2 = self.getMatchChineseWords()\n                for word2 in words2:\n                    self.pos += len(word2.text)\n                    if self.pos < self.textLength:\n                        words3 = self.getMatchChineseWords()\n                        for word3 in words3:\n                            # print(word3.length, word3.text)\n                            if word3.length == -1:\n                                chunk = Chunk(word1, word2)\n                            else:\n                                chunk = Chunk(word1, word2, word3)\n                            chunks.append(chunk)\n                    elif self.pos == self.textLength:\n                        chunks.append(Chunk(word1, word2))\n                    self.pos -= len(word2.text)\n            elif self.pos == self.textLength:\n                chunks.append(Chunk(word1))\n            self.pos -= len(word1.text)\n\n        self.pos = originalPos\n        return chunks\n\n    #运用正向最大匹配算法结合字典来切割中文文本    \n    def getMatchChineseWords(self):\n        #use cache,check it   \n        for i in range(self.cacheSize):\n            if self.cache[i][0] == self.pos:\n                return self.cache[i][1]\n\n        originalPos = self.pos\n        words = []\n        index = 0\n        while self.pos < self.textLength:\n            if index >= maxWordLength:\n                break\n            if not self.isChineseChar(self.getNextChar()):\n                break\n            self.pos += 1\n            index += 1\n\n            text = self.text[originalPos:self.pos]\n            word = getDictWord(text)\n            if word:\n                words.append(word)\n\n        self.pos = originalPos\n        #没有词则放置个‘X’，将文本长度标记为-1  \n        if not words:\n            word = Word()\n            word.length = -1\n            word.text = 'X'\n            words.append(word)\n\n        self.cache[self.cacheIndex] = (self.pos, words)\n        self.cacheIndex += 1\n        if self.cacheIndex >= self.cacheSize:\n            self.cacheIndex = 0\n        return words\n\n\nif __name__ == \"__main__\":\n\n    def cuttest(text):\n        #cut =  Analysis(text)  \n        tmp = \"\"\n        try:\n            for word in iter(Analysis(text)):\n                tmp += word\n        except Exception as e:\n            pass\n\n        print(tmp)\n        print(\"================================\")\n\n    cuttest(u\"研究生命来源\")\n    cuttest(u\"南京市长江大桥欢迎您\")\n    cuttest(u\"请把手抬高一点儿\")\n    cuttest(u\"长春市长春节致词。\")\n    cuttest(u\"长春市长春药店。\")\n    cuttest(u\"我的和服务必在明天做好。\")\n    cuttest(u\"我发现有很多人喜欢他。\")\n    cuttest(u\"我喜欢看电视剧大长今。\")\n    cuttest(u\"半夜给拎起来陪看欧洲杯糊着两眼半晌没搞明白谁和谁踢。\")\n    cuttest(u\"李智伟高高兴兴以及王晓薇出去玩，后来智伟和晓薇又单独去玩了。\")\n    cuttest(u\"一次性交出去很多钱。 \")\n    cuttest(u\"这是一个伸手不见五指的黑夜。我叫孙悟空，我爱北京，我爱Python和C++。\")\n    cuttest(u\"我不喜欢日本和服。\")\n    cuttest(u\"雷猴回归人间。\")\n    cuttest(u\"工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作\")\n    cuttest(u\"我需要廉租房\")\n    cuttest(u\"永和服装饰品有限公司\")\n    cuttest(u\"我爱北京天安门\")\n    cuttest(u\"abc\")\n    cuttest(u\"隐马尔可夫\")\n    cuttest(u\"雷猴是个好网站\")\n    cuttest(u\"“Microsoft”一词由“MICROcomputer（微型计算机）”和“SOFTware（软件）”两部分组成\")\n    cuttest(u\"草泥马和欺实马是今年的流行词汇\")\n    cuttest(u\"伊藤洋华堂总府店\")\n    cuttest(u\"中国科学院计算技术研究所\")\n    cuttest(u\"罗密欧与朱丽叶\")\n    cuttest(u\"我购买了道具和服装\")\n    cuttest(u\"PS: 我觉得开源有一个好处，就是能够敦促自己不断改进，避免敞帚自珍\")\n    cuttest(u\"湖北省石首市\")\n    cuttest(u\"总经理完成了这件事情\")\n    cuttest(u\"电脑修好了\")\n    cuttest(u\"做好了这件事情就一了百了了\")\n    cuttest(u\"人们审美的观点是不同的\")\n    cuttest(u\"我们买了一个美的空调\")\n    cuttest(u\"线程初始化时我们要注意\")\n    cuttest(u\"一个分子是由好多原子组织成的\")\n    cuttest(u\"祝你马到功成\")\n    cuttest(u\"他掉进了无底洞里\")\n    cuttest(u\"中国的首都是北京\")\n    cuttest(u\"孙君意\")\n    cuttest(u\"外交部发言人马朝旭\")\n    cuttest(u\"领导人会议和第四届东亚峰会\")\n    cuttest(u\"在过去的这五年\")\n    cuttest(u\"还需要很长的路要走\")\n    cuttest(u\"60周年首都阅兵\")\n    cuttest(u\"你好人们审美的观点是不同的\")\n    cuttest(u\"买水果然后来世博园\")\n    cuttest(u\"买水果然后去世博园\")\n    cuttest(u\"但是后来我才知道你是对的\")\n    cuttest(u\"存在即合理\")\n    cuttest(u\"的的的的的在的的的的就以和和和\")\n    cuttest(u\"I love你，不以为耻，反以为rong\")\n    cuttest(u\" \")\n    cuttest(u\"\")\n    cuttest(u\"hello你好人们审美的观点是不同的\")\n    cuttest(u\"很好但主要是基于网页形式\")\n    cuttest(u\"hello你好人们审美的观点是不同的\")\n    cuttest(u\"为什么我不能拥有想要的生活\")\n    cuttest(u\"后来我才\")\n    cuttest(u\"此次来中国是为了\")\n    cuttest(u\"使用了它就可以解决一些问题\")\n    cuttest(u\",使用了它就可以解决一些问题\")\n    cuttest(u\"其实使用了它就可以解决一些问题\")\n    cuttest(u\"好人使用了它就可以解决一些问题\")\n    cuttest(u\"是因为和国家\")\n    cuttest(u\"老年搜索还支持\")\n    cuttest(\n        u\"干脆就把那部蒙人的闲法给废了拉倒！RT @laoshipukong : 27日，全国人大常委会第三次审议侵权责任法草案，删除了有关医疗损害责任“举证倒置”的规定。在医患纠纷中本已处于弱势地位的消费者由此将陷入万劫不复的境地。 \"\n    )\n    cuttest(\"2022年12月30日是星期几？\")\n    cuttest(\"二零二二年十二月三十日是星期几？\")\n"
  },
  {
    "path": "runtime/examples/text_lm/path.sh",
    "content": "MAIN_ROOT=`realpath $PWD/../../../`\nENGINE_ROOT=`realpath $MAIN_ROOT/runtime`\n\nexport LC_AL=C\n"
  },
  {
    "path": "runtime/examples/text_lm/run.sh",
    "content": "#!/bin/bash\nset -eo pipefail\n\n. path.sh\n\nstage=0\nstop_stage=100\nhas_key=true\ntoken_type=word\n\n. utils/parse_options.sh || exit -1;\n\ntext=data/text\n\nif [ ! -f $text ]; then\n    echo \"$0: Not find $1\";\n    exit -1;\nfi\n\nif [ $stage -le 0 ] && [ $stop_stage -ge 0 ];then\n    echo \"text tn & wordseg preprocess\"\n    rm -rf ${text}.tn\n    python3 utils/zh_tn.py --has_key $has_key --token_type $token_type ${text} ${text}.tn\nfi"
  },
  {
    "path": "runtime/examples/u2pp_ol/README.md",
    "content": "# U2/U2++ Streaming ASR\n\n## Examples\n\n* `wenetspeech` - Streaming Decoding with wenetspeech u2/u2++ model. Using aishell test data for testing.    \n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/.gitignore",
    "content": "data\nexp\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/README.md",
    "content": "# U2/U2++ Streaming ASR \n\nA C++ deployment example for `PaddleSpeech/examples/wenetspeech/asr1` recipe. The model is static model from `export`, how to export model please see [here](../../../../examples/wenetspeech/asr1/). If you want using exported model, `run.sh` will download it, for the model link please see `run.sh`.\n\nThis example will demonstrate how to using the u2/u2++ model to recognize `wav` and compute `CER`. We using AISHELL-1 as test data.\n\n## Testing with Aishell Test Data\n\n## Source path.sh\n\n```bash\n. path.sh\n```\n\nSpeechX bins is under `echo $SPEECHX_BUILD`, more info please see `path.sh`.\n\n\n### Download dataset and model\n\n```\n./run.sh --stop_stage 0\n```\n\n### process `cmvn` and compute feature\n\n```bash\n./run.sh --stage 1 --stop_stage 1\n```\n\nIf you only want to convert `cmvn` file format, can using this cmd:\n\n```bash \n./local/feat.sh --stage 1 --stop_stage 1\n```\n\n### Decoding using `feature` input\n\n```\n./run.sh --stage 2 --stop_stage 2\n```\n\n### Decoding using `wav` input\n\n```\n./run.sh --stage 3 --stop_stage 3\n```\n\nThis stage using `u2_recognizer_main` to recognize wav file.\n\nThe input is `scp` file which look like this:\n```text\n# head data/split1/1/aishell_test.scp \nBAC009S0764W0121        /workspace/PaddleSpeech/runtime/examples/u2pp_ol/wenetspeech/data/test/S0764/BAC009S0764W0121.wav\nBAC009S0764W0122        /workspace/PaddleSpeech/runtime/examples/u2pp_ol/wenetspeech/data/test/S0764/BAC009S0764W0122.wav\n...\nBAC009S0764W0125        /workspace/PaddleSpeech/runtime/examples/u2pp_ol/wenetspeech/data/test/S0764/BAC009S0764W0125.wav\n```\n\nIf you want to recognize one wav, you can make `scp` file like this:\n```text\nkey  path/to/wav/file\n```\n\nThen specify `--wav_rspecifier=` param for `u2_recognizer_main` bin. For other flags meaning, please see `help`:\n```bash\nu2_recognizer_main --help\n```\n\nThe exmaple using `u2_recgonize_main` bin please see `local/recognizer.sh`.\n\n### Decoding with `wav` using quant model\n\n`local/recognizer_quant.sh` is same to `local/recognizer.sh`, but using quanted model.\n\n\n## Results\n\nPlease see [here](./RESULTS.md).\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/RESULTS.md",
    "content": "# aishell test\n\n7176 utts, duration 36108.9 sec.\n\n## U2++ Attention Rescore\n\n> Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz, support `avx512_vnni`\n> RTF with feature and decoder which is more end to end.\n\n### FP32\n\n`local/recognizer.sh`\n\n#### CER\n\n```\nOverall -> 5.75 % N=104765 C=99035 S=5587 D=143 I=294\nMandarin -> 5.75 % N=104762 C=99035 S=5584 D=143 I=294\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n#### RTF \n\n```\nI1027 10:52:38.662868 51665 recognizer_main.cc:122] total wav duration is: 36108.9 sec\nI1027 10:52:38.662858 51665 recognizer_main.cc:121] total cost:9577.31 sec\nI1027 10:52:38.662876 51665 recognizer_main.cc:123] RTF is: 0.265234\n```\n\n### INT8\n\n`local/recognizer_quant.sh`\n\n#### CER\n\n```\nOverall -> 5.83 % N=104765 C=98943 S=5675 D=147 I=286\nMandarin -> 5.83 % N=104762 C=98943 S=5672 D=147 I=286\nEnglish -> 0.00 % N=0 C=0 S=0 D=0 I=0\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n#### RTF \n\n```\nI1110 09:59:52.551712 37249 u2_recognizer_main.cc:122] total wav duration is: 36108.9 sec\nI1110 09:59:52.551717 37249 u2_recognizer_main.cc:123] total decode cost:9737.63 sec\nI1110 09:59:52.551723 37249 u2_recognizer_main.cc:124] RTF is: 0.269674\n```\n\n### TLG decoder without attention rescore\n\n`local/recognizer_wfst.sh`\n\n#### CER\n\n```\nOverall -> 4.73 % N=104765 C=100001 S=4283 D=481 I=187\nMandarin -> 4.72 % N=104762 C=100001 S=4280 D=481 I=187\nOther -> 100.00 % N=3 C=0 S=3 D=0 I=0\n```\n\n#### RTF\n```\nI0417 08:07:15.300631 75784 recognizer_main.cc:113] total wav duration is: 36108.9 sec\nI0417 08:07:15.300642 75784 recognizer_main.cc:114] total decode cost:10247.7 sec\nI0417 08:07:15.300648 75784 recognizer_main.cc:115] total rescore cost:908.228 sec\nI0417 08:07:15.300653 75784 recognizer_main.cc:116] RTF is: 0.283\n```\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/aishell_train_lms.sh",
    "content": "#!/bin/bash\n\n# To be run from one directory above this script.\n. ./path.sh\n\nnj=40\ntext=data/local/lm/text\nlexicon=data/local/dict/lexicon.txt\n\nfor f in \"$text\" \"$lexicon\"; do\n  [ ! -f $x ] && echo \"$0: No such file $f\" && exit 1;\ndone\n\n# Check SRILM tools\nif ! which ngram-count > /dev/null; then\n    echo \"srilm tools are not found, please download it and install it from: \"\n    echo \"http://www.speech.sri.com/projects/srilm/download.html\"\n    echo \"Then add the tools to your PATH\"\n    exit 1\nfi\n\n# This script takes no arguments.  It assumes you have already run\n# aishell_data_prep.sh.\n# It takes as input the files\n# data/local/lm/text\n# data/local/dict/lexicon.txt\ndir=data/local/lm\nmkdir -p $dir\n\ncleantext=$dir/text.no_oov\n\n# oov to <SPOKEN_NOISE>\n# lexicon line: word char0 ... charn\n# text line: utt word0 ... wordn -> line: <SPOKEN_NOISE> word0 ... wordn\ntext_dir=$(dirname $text)\nsplit_name=$(basename $text)\n./local/split_data.sh $text_dir $text $split_name $nj\n\nutils/run.pl JOB=1:$nj $text_dir/split${nj}/JOB/${split_name}.no_oov.log \\\n  cat ${text_dir}/split${nj}/JOB/${split_name} \\| awk -v lex=$lexicon 'BEGIN{while((getline<lex) >0){ seen[$1]=1; } }\n    {for(n=1; n<=NF;n++) {  if (seen[$n]) { printf(\"%s \", $n); } else {printf(\"<SPOKEN_NOISE> \");} } printf(\"\\n\");}' \\\n    \\> ${text_dir}/split${nj}/JOB/${split_name}.no_oov || exit 1;\ncat ${text_dir}/split${nj}/*/${split_name}.no_oov  > $cleantext\n\n# compute word counts, sort in descending order\n# line: count word\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | sort --parallel=`nproc` | uniq -c | \\\n   sort --parallel=`nproc` -nr > $dir/word.counts || exit 1;\n\n# Get counts from acoustic training transcripts, and add  one-count\n# for each word in the lexicon (but not silence, we don't want it\n# in the LM-- we'll add it optionally later).\ncat $cleantext | awk '{for(n=2;n<=NF;n++) print $n; }' | \\\n  cat - <(grep -w -v '!SIL' $lexicon | awk '{print $1}') | \\\n   sort --parallel=`nproc` | uniq -c | sort --parallel=`nproc` -nr > $dir/unigram.counts || exit 1;\n\n# word with <s> </s>\ncat $dir/unigram.counts | awk '{print $2}' | cat - <(echo \"<s>\"; echo \"</s>\" ) > $dir/wordlist\n\n# hold out to compute ppl\nheldout_sent=10000 # Don't change this if you want result to be comparable with kaldi_lm results\n\nmkdir -p $dir\ncat $cleantext | awk '{for(n=2;n<=NF;n++){ printf $n; if(n<NF) printf \" \"; else print \"\"; }}' | \\\n  head -$heldout_sent > $dir/heldout\ncat $cleantext | awk '{for(n=2;n<=NF;n++){ printf $n; if(n<NF) printf \" \"; else print \"\"; }}' | \\\n  tail -n +$heldout_sent > $dir/train\n\nngram-count -text $dir/train -order 3 -limit-vocab -vocab $dir/wordlist -unk \\\n  -map-unk \"<UNK>\" -kndiscount -interpolate -lm $dir/lm.arpa\nngram -lm $dir/lm.arpa -ppl $dir/heldout"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/decode.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\ndata=data\nexp=exp\nnj=20\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model/\ntext=$data/test/text\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/decoder.log \\\nctc_prefix_beam_search_decoder_main \\\n    --model_path=$model_dir/export.jit \\\n    --word_symbol_table=$model_dir/unit.txt \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --feature_rspecifier=scp:$data/split${nj}/JOB/fbank.scp \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/result_decode.ark\n\ncat $data/split${nj}/*/result_decode.ark > $exp/aishell.decode.rsl\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell.decode.rsl > $exp/aishell.decode.err\ntail -n 7 $exp/aishell.decode.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/feat.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\nnj=20\nstage=-1\nstop_stage=100\n\n. utils/parse_options.sh\n\ndata=data\nexp=exp\nmkdir -p $exp\n\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model/\naishell_wav_scp=aishell_test.scp\n\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n    \n    utils/run.pl JOB=1:$nj $data/split${nj}/JOB/feat.log \\\n    compute_fbank_main \\\n        --num_bins 80 \\\n        --cmvn_file=$model_dir/mean_std.json \\\n        --streaming_chunk=36 \\\n        --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n        --feature_wspecifier=ark,scp:$data/split${nj}/JOB/fbank.ark,$data/split${nj}/JOB/fbank.scp\n    \n    echo \"compute fbank feature.\"\nfi\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/nnet.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\nnj=20\ndata=data\nexp=exp\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model/\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/nnet.log \\\nu2_nnet_main \\\n    --model_path=$model_dir/export.jit \\\n    --vocab_path=$model_dir/unit.txt \\\n    --feature_rspecifier=ark,t:${data}/split${nj}/JOB/fbank.ark \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --acoustic_scale=1.0 \\\n    --nnet_encoder_outs_wspecifier=ark,t:$exp/encoder_outs.ark \\\n    --nnet_prob_wspecifier=ark,t:$exp/logprobs.ark\necho \"u2 nnet decode.\"\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/recognizer.sh",
    "content": "#!/bin/bash\nset -e\n\ndata=data\nexp=exp\nnj=20\n\n. utils/parse_options.sh\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model/\naishell_wav_scp=aishell_test.scp\ntext=$data/test/text\n\n./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/recognizer.log \\\nrecognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --cmvn_file=$model_dir/mean_std.json \\\n    --model_path=$model_dir/export.jit \\\n    --word_symbol_table=$model_dir/unit.txt \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/result_recognizer.ark\n\n\ncat $data/split${nj}/*/result_recognizer.ark > $exp/aishell_recognizer\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell_recognizer > $exp/aishell.recognizer.err\necho \"recognizer test have finished!!!\"\necho \"please checkout in $exp/aishell.recognizer.err\"\ntail -n 7 $exp/aishell.recognizer.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/recognizer_fastdeploy.sh",
    "content": "#!/bin/bash\nset -e\n\ndata=data\nexp=exp\nnj=20\n\n. utils/parse_options.sh\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/onnx_model/\naishell_wav_scp=aishell_test.scp\ntext=$data/test/text\n\n./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/recognizer.fd.log \\\nrecognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --model_path=$model_dir \\\n    --word_symbol_table=$model_dir/unit.txt \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --with_onnx_model=true \\\n    --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/recognizer.fd.rsl.ark\n\n\ncat $data/split${nj}/*/recognizer.fd.rsl.ark > $exp/aishell.recognizer.fd.rsl\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell.recognizer.fd.rsl > $exp/aishell.recognizer.fd.err\necho \"recognizer fd test have finished!!!\"\necho \"please checkout in $exp/aishell.recognizer.fd.err\"\ntail -n 7 $exp/aishell.recognizer.fd.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/recognizer_quant.sh",
    "content": "#!/bin/bash\nset -e\n\ndata=data\nexp=exp\nnj=20\n\n. utils/parse_options.sh\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_quant_1.3.0.model/\naishell_wav_scp=aishell_test.scp\ntext=$data/test/text\n\n./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/recognizer.quant.log \\\nrecognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --cmvn_file=$model_dir/mean_std.json \\\n    --model_path=$model_dir/export \\\n    --word_symbol_table=$model_dir/unit.txt \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/recognizer.quant.rsl.ark\n\n\ncat $data/split${nj}/*/recognizer.quant.rsl.ark > $exp/aishell.recognizer.quant.rsl\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell.recognizer.quant.rsl > $exp/aishell.recognizer.quant.err\necho \"recognizer quant test have finished!!!\"\necho \"please checkout in $exp/aishell.recognizer.quant.err\"\ntail -n 7 $exp/aishell.recognizer.quant.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/recognizer_wfst.sh",
    "content": "#!/bin/bash\nset -e\n\ndata=data\nexp=exp\nnj=20\n\n. utils/parse_options.sh\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model/\naishell_wav_scp=aishell_test.scp\ntext=$data/test/text\n\n./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n\nlang_dir=./data/lang_test/\ngraph=$lang_dir/TLG.fst\nword_table=$lang_dir/words.txt\n\nif [ ! -f $graph ]; then\n    # download ngram, if you want to make graph by yourself, please refer local/run_build_tlg.sh\n    mkdir -p $lang_dir\n    pushd $lang_dir\n    wget -c https://paddlespeech.cdn.bcebos.com/speechx/examples/ngram/zh/tlg.zip\n    unzip tlg.zip\n    popd\nfi\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/recognizer_wfst.log \\\nrecognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --cmvn_file=$model_dir/mean_std.json \\\n    --model_path=$model_dir/export.jit \\\n    --graph_path=$lang_dir/TLG.fst \\\n    --word_symbol_table=$word_table \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n    --rescoring_weight=0.0 \\\n    --acoustic_scale=2 \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/result_recognizer_wfst.ark\n\n\ncat $data/split${nj}/*/result_recognizer_wfst.ark > $exp/aishell_recognizer_wfst\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell_recognizer_wfst > $exp/aishell.recognizer_wfst.err\necho \"recognizer test have finished!!!\"\necho \"please checkout in $exp/aishell.recognizer_wfst.err\"\ntail -n 7 $exp/aishell.recognizer_wfst.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/recognizer_wfst_fastdeploy.sh",
    "content": "#!/bin/bash\nset -e\n\ndata=data\nexp=exp\nnj=20\n\n. utils/parse_options.sh\n\nmkdir -p $exp\nckpt_dir=./data/model\nmodel_dir=$ckpt_dir/onnx_model/\naishell_wav_scp=aishell_test.scp\ntext=$data/test/text\n\n./local/split_data.sh $data $data/$aishell_wav_scp $aishell_wav_scp $nj\n\nlang_dir=./data/lang_test/\ngraph=$lang_dir/TLG.fst\nword_table=$lang_dir/words.txt\n\nif [ ! -f $graph ]; then\n    # download ngram, if you want to make graph by yourself, please refer local/run_build_tlg.sh\n    mkdir -p $lang_dir\n    pushd $lang_dir\n    wget -c https://paddlespeech.cdn.bcebos.com/speechx/examples/ngram/zh/tlg.zip\n    unzip tlg.zip\n    popd\nfi\n\nutils/run.pl JOB=1:$nj $data/split${nj}/JOB/recognizer_wfst_fd.log \\\nrecognizer_main \\\n    --use_fbank=true \\\n    --num_bins=80 \\\n    --model_path=$model_dir \\\n    --graph_path=$lang_dir/TLG.fst \\\n    --word_symbol_table=$word_table \\\n    --nnet_decoder_chunk=16 \\\n    --receptive_field_length=7 \\\n    --subsampling_rate=4 \\\n    --wav_rspecifier=scp:$data/split${nj}/JOB/${aishell_wav_scp} \\\n    --rescoring_weight=0.0 \\\n    --acoustic_scale=2 \\\n    --result_wspecifier=ark,t:$data/split${nj}/JOB/result_recognizer_wfst_fd.ark\n\n\ncat $data/split${nj}/*/result_recognizer_wfst_fd.ark > $exp/aishell_recognizer_wfst_fd\nutils/compute-wer.py --char=1 --v=1 $text $exp/aishell_recognizer_wfst_fd > $exp/aishell.recognizer_wfst_fd.err\necho \"recognizer test have finished!!!\"\necho \"please checkout in $exp/aishell.recognizer_wfst_fd.err\"\ntail -n 7 $exp/aishell.recognizer_wfst_fd.err\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/run_build_tlg.sh",
    "content": "#!/bin/bash\nset -eo pipefail\n\n#. path.sh\n\n# attention, please replace the vocab is only for this script. \n# different acustic model has different vocab\nckpt_dir=data/model/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model\nunit=$ckpt_dir/vocab.txt       # vocab file, line: char/spm_pice\n\nstage=2\nstop_stage=100\ncorpus=aishell\nlexicon=data/lexicon.txt  # line: word ph0 ... phn, aishell/resource_aishell/lexicon.txt\ntext=data/text            # line: utt text, aishell/data_aishell/transcript/aishell_transcript_v0.8.txt filter by data/train/text\n\n. utils/parse_options.sh\n\ndata=$PWD/data\nmkdir -p $data\n\nif [ $stage -le -1 ] && [ $stop_stage -ge -1 ]; then\n    if [ ! -f $data/speech.ngram.zh.tar.gz ];then\n        # download ngram\n        pushd $data\n        wget -c http://paddlespeech.cdn.bcebos.com/speechx/examples/ngram/zh/speech.ngram.zh.tar.gz\n        tar xvzf speech.ngram.zh.tar.gz\n        popd\n    fi\nfi\n\nif [ ! -f $unit ]; then\n    echo \"$0: No such file $unit\"\n    exit 1;\nfi\n\nif ! which ngram-count; then\n    # need srilm install\n    pushd $MAIN_ROOT/tools\n    make srilm.done\n    popd\nfi\n\necho \"done.\"\nmkdir -p data/local/dict\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then\n    # Prepare dict\n    # line: char/spm_pices\n    cp $unit data/local/dict/units.txt\n\n    if [ ! -f $lexicon ];then\n       utils/text_to_lexicon.py --has_key true --text $text --lexicon $lexicon\n        echo \"Generate $lexicon from $text\"\n    fi\n\n    # filter by vocab\n    # line: word ph0 ... phn -> line: word char0 ... charn\n    utils/fst/prepare_dict.py \\\n        --unit_file $unit \\\n        --in_lexicon ${lexicon} \\\n        --out_lexicon data/local/dict/lexicon.txt\nfi\n\nlm=data/local/lm\nmkdir -p $lm\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # Train ngram lm\n    cp $text $lm/text\n    local/aishell_train_lms.sh\n    echo \"build LM done.\"\nfi\n\n# build TLG\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n  # build T & L\n  utils/fst/compile_lexicon_token_fst.sh \\\n      data/local/dict data/local/tmp data/local/lang\n \n  # build G & TLG\n  utils/fst/make_tlg.sh data/local/lm data/local/lang data/lang_test || exit 1;\n\nfi\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/local/split_data.sh",
    "content": "#!/usr/bin/env bash\n\nset -eo pipefail\n\ndata=$1\nscp=$2\nsplit_name=$3\nnumsplit=$4\n\n# save in $data/split{n}\n# $scp to split\n# \n\nif [[ ! $numsplit -gt 0 ]]; then\n  echo \"$0: Invalid num-split argument\";\n  exit 1;\nfi\n\ndirectories=$(for n in `seq $numsplit`; do echo $data/split${numsplit}/$n; done)\nscp_splits=$(for n in `seq $numsplit`; do echo $data/split${numsplit}/$n/${split_name}; done)\n\n# if this mkdir fails due to argument-list being too long, iterate.\nif ! mkdir -p $directories >&/dev/null; then\n  for n in `seq $numsplit`; do\n    mkdir -p $data/split${numsplit}/$n\n  done\nfi\n\necho \"utils/split_scp.pl $scp $scp_splits\"\nutils/split_scp.pl $scp $scp_splits\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nunset GREP_OPTIONS\n\nENGINE_ROOT=$PWD/../../../\nENGINE_BUILD=$ENGINE_ROOT/build/Linux/x86_64/engine/asr\n\nENGINE_TOOLS=$ENGINE_ROOT/tools\nTOOLS_BIN=$ENGINE_TOOLS/valgrind/install/bin\n\n[ -d $ENGINE_BUILD ] || { echo \"Error: 'build/runtime' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nexport PATH=$PATH:$TOOLS_BIN:$ENGINE_BUILD/nnet:$ENGINE_BUILD/decoder:$ENGINE_BUILD/../common/frontend/audio:$ENGINE_BUILD/recognizer:../../../fc_patch/openfst/bin:$ENGINE_BUILD/../kaldi/fstbin:$ENGINE_BUILD/../kaldi/lmbin\n\n#PADDLE_LIB_PATH=$(python -c \"import os; import paddle; include_dir=paddle.sysconfig.get_include(); paddle_dir=os.path.split(include_dir)[0]; libs_dir=os.path.join(paddle_dir, 'libs'); fluid_dir=os.path.join(paddle_dir, 'fluid'); out=':'.join([libs_dir, fluid_dir]); print(out);\")\nexport LD_LIBRARY_PATH=$PADDLE_LIB_PATH:$LD_LIBRARY_PATH\n"
  },
  {
    "path": "runtime/examples/u2pp_ol/wenetspeech/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\nnj=40\nstage=-1\nstop_stage=100\n\n. utils/parse_options.sh\n\n# input\ndata=data\nexp=exp\nmkdir -p $exp $data\naishell_wav_scp=aishell_test.scp\n\n# 1. compile\nif [ ! -d ${SPEECHX_BUILD} ]; then\n    pushd ${SPEECHX_ROOT} \n    bash build.sh\n    popd\nfi\n\nckpt_dir=$data/model\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ];then\n    #  download u2pp model\n    if [ ! -f $ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model.tar.gz ]; then\n        mkdir -p $ckpt_dir\n        pushd $ckpt_dir\n\n        wget -c https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/static/asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model.tar.gz\n        tar xzfv asr1_chunk_conformer_u2pp_wenetspeech_static_1.3.0.model.tar.gz\n\n        popd\n    fi\n\n    # download u2pp quant model\n    if [ ! -f $ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_quant_1.3.0.model.tar.gz ]; then\n        mkdir -p $ckpt_dir\n        pushd $ckpt_dir\n\n        wget -c https://paddlespeech.cdn.bcebos.com/s2t/wenetspeech/asr1/static/asr1_chunk_conformer_u2pp_wenetspeech_static_quant_1.3.0.model.tar.gz\n        tar xzfv asr1_chunk_conformer_u2pp_wenetspeech_static_quant_1.3.0.model.tar.gz\n\n        popd\n    fi\n\n    # test wav scp\n    if [ ! -f data/wav.scp ]; then\n        mkdir -p $data\n        pushd $data\n        wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav\n        echo \"utt1 \" $PWD/zh.wav > wav.scp\n        popd \n    fi\n\n    # aishell wav scp\n    if [ ! -d $data/test ]; then\n        pushd $data\n        wget -c https://paddlespeech.cdn.bcebos.com/s2t/paddle_asr_online/aishell_test.zip\n        unzip  aishell_test.zip\n        popd\n\n        realpath $data/test/*/*.wav > $data/wavlist\n        awk -F '/' '{ print $(NF) }' $data/wavlist | awk -F '.' '{ print $1 }' > $data/utt_id\n        paste $data/utt_id $data/wavlist > $data/$aishell_wav_scp\n    fi\nfi\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    # decode with wav input\n    ./local/recognizer.sh\nfi\n\nif [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then\n    # decode with wav input with quanted model\n    ./local/recognizer_quant.sh\nfi\n\nif [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then\n    # decode with wfst \n    ./local/recognizer_wfst.sh\nfi\n"
  },
  {
    "path": "runtime/examples/vad/.gitignore",
    "content": "data\n"
  },
  {
    "path": "runtime/examples/vad/README.md",
    "content": "# Silero VAD - pre-trained enterprise-grade Voice Activity Detector\n\nThis directory provides VAD models on CPU/GPU.\n\n![](https://user-images.githubusercontent.com/36505480/198026365-8da383e0-5398-4a12-b7f8-22c2c0059512.png)\n\n\n## VAD Interface\n\nFor vad interface please see [](../../engine/vad/interface/).\n\n### Create Handdle\n\n```c++\nPPSHandle_t PPSVadCreateInstance(const char* conf_path);\n```\n\n### Destroy Handdle\n\n```c++\nint PPSVadDestroyInstance(PPSHandle_t instance);\n```\n\n### Reset Vad State\n\n```c++\nint PPSVadReset(PPSHandle_t instance);\n```\n\nReset Vad state before processing next `wav`.\n\n### Get Chunk Size\n\n```c++\nint PPSVadChunkSizeSamples(PPSHandle_t instance);\n```\n\nThis API will return chunk size in `sample` unit.\nWhen do forward, we need feed `chunk size` samples, except last chunk.\n\n### Vad Forward\n\n```c++\nPPSVadState_t PPSVadFeedForward(PPSHandle_t instance,\n                                float* chunk,\n                                int num_element);\n```\n\nVad has below states:\n```c++\ntypedef enum {\n    PPS_VAD_ILLEGAL = 0,  // error\n    PPS_VAD_SIL,          // silence\n    PPS_VAD_START,        // start speech\n    PPS_VAD_SPEECH,       // in speech\n    PPS_VAD_END,          // end speech\n    PPS_VAD_NUMSTATES,    // number of states\n} PPSVadState_t;\n```\n\nIf `PPSVadFeedForward` occur an error will return `PPS_VAD_ILLEGAL` state.\n\n\n## Linux\n\n### Build Runtime\n```bash\n# cd /path/to/paddlespeech/runtime\ncmake -B build -DBUILD_SHARED_LIBS=OFF -DWITH_ASR=OFF -DWITH_CLS=OFF -DWITH_VAD=ON\ncmake --build build\n```\n\nSince VAD using FastDeploy runtime, if you have another FastDeploy Library, you can using this command to build:\n\n```bash\n# cd /path/to/paddlespeech/runtime\ncmake -B build -DBUILD_SHARED_LIBS=OFF -DWITH_ASR=OFF -DWITH_CLS=OFF -DWITH_VAD=ON -DFASTDEPLOY_INSTALL_DIR=/workspace//paddle/FastDeploy/build/Linux/x86_64/install\ncmake --build build\n```\n\n`DFASTDEPLOY_INSTALL_DIR` is the directory of FastDeploy Library.\n\n### Run Demo\n\nAfter building success, we can do this to run demo under this example dir:\n\n```bash \nbash run.sh\n```\n\nThe output like these:\n\n```bash\n/workspace//PaddleSpeech/runtime/engine/vad/nnet/vad.cc(88)::SetConfig  sr=16 threshold=0.5 beam=0.15 frame_ms=32 min_silence_duration_ms=200 speech_pad_left_ms=0 speech_pad_right_ms=0[INFO] fastdeploy/runtime/runtime.cc(293)::CreateOrtBackend     Runtime initialized with Backend::ORT in Device::CPU./workspace//PaddleSpeech/runtime/engine/vad/nnet/vad.cc(137)::Initialize        init done.[SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [STA] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [END] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [STA] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SIL] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [END] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [STA] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [END] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [STA] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SPE] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [END] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] [SIL] \nRTF=0.00774591\nspeak start: 0.32 s, end: 2.464 s | speak start: 3.296 s, end: 4.64 s | speak start: 5.408 s, end: 7.872 s | speak start: 8.192 s, end: 10.72 s   \nvad_nnet_main done!\nsr = 16000\nframe_ms = 32\nthreshold = 0.5\nbeam = 0.15\nmin_silence_duration_ms = 200\nspeech_pad_left_ms = 0\nspeech_pad_right_ms = 0\nmodel_path = ./data/silero_vad/silero_vad.onnx\nparam_path = (default)num_cpu_thread = 1(default)/workspace//PaddleSpeech/runtime/engine/vad/nnet/vad.cc(88)::SetConfig  sr=16 threshold=0.5 beam=0.15 frame_ms=32 min_silence_duration_ms=200 speech_pad_left_ms=0 speech_pad_right_ms=0[INFO] fastdeploy/runtime/runtime.cc(293)::CreateOrtBackend     Runtime initialized with Backend::ORT in Device::CPU./workspace//PaddleSpeech/runtime/engine/vad/nnet/vad.cc(137)::Initialize        init done.\n1 1 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3 3 3 3 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 1 \nRTF=0.00778218\nvad_interface_main done!\n```\n\n## Android\n\nWhen to using on Android, please setup your `NDK` enverment before, then do as below:\n\n```bash\n# cd /path/to/paddlespeech/runtime\nbash build_android.sh\n```\n\n## Result\n\n| Arch | RTF | Runtime Size |\n|--|--|--|\n| x86_64    | 0.00778218 |  |\n| arm64-v8a | 0.00744745 | ~10.532MB |\n\n## Machine Information\n\n#### x86_64\n\nThe environment as below:\n\n```text\nArchitecture:        x86_64\nCPU op-mode(s):      32-bit, 64-bit\nByte Order:          Little Endian\nCPU(s):              80\nOn-line CPU(s) list: 0-79\nThread(s) per core:  2\nCore(s) per socket:  20\nSocket(s):           2\nNUMA node(s):        2\nVendor ID:           GenuineIntel\nCPU family:          6\nModel:               85\nModel name:          Intel(R) Xeon(R) Gold 6271C CPU @ 2.60GHz\nStepping:            7\nCPU MHz:             2599.998\nBogoMIPS:            5199.99\nHypervisor vendor:   KVM\nVirtualization type: full\nL1d cache:           32K\nL1i cache:           32K\nL2 cache:            1024K\nL3 cache:            33792K\nNUMA node0 CPU(s):   0-39\nNUMA node1 CPU(s):   40-79\nFlags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 arat umip pku ospke avx512_vnni spec_ctrl arch_capabilities\n```\n\n#### arm64-v8a\n\n```text\nProcessor       : AArch64 Processor rev 14 (aarch64)\nprocessor       : 0\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x805\nCPU revision    : 14\n\nprocessor       : 1\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x805\nCPU revision    : 14\n\nprocessor       : 2\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x805\nCPU revision    : 14\n\nprocessor       : 3\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x805\nCPU revision    : 14\n\nprocessor       : 4\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x804\nCPU revision    : 14\n\nprocessor       : 5\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x804\nCPU revision    : 14\n\nprocessor       : 6\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x804\nCPU revision    : 14\n\nprocessor       : 7\nBogoMIPS        : 38.40\nFeatures        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop\nCPU implementer : 0x51\nCPU architecture: 8\nCPU variant     : 0xd\nCPU part        : 0x804\nCPU revision    : 14\n\nHardware        : Qualcomm Technologies, Inc SM8150\n```\n\n\n## Download Pre-trained ONNX Model\n\nFor developers' testing, model exported by VAD are provided below. Developers can download them directly.\n\n| 模型                                                         | 大小  | 备注                                                         |\n| :----------------------------------------------------------- | :---- | :----------------------------------------------------------- |\n| [silero-vad](https://bj.bcebos.com/paddlehub/fastdeploy/silero_vad.tgz) | 1.8MB | This model file is sourced from [snakers4/silero-vad](https://github.com/snakers4/silero-vad)，MIT License |\n\n\n## FastDeploy Runtime\n\nFor FastDeploy software and hardware requements, and pre-released library please to see [FastDeploy](https://github.com/PaddlePaddle/FastDeploy):\n\n- 1. [FastDeploy Environment Requirements](https://github.com/PaddlePaddle/FastDeploy/docs/en/build_and_install/download_prebuilt_libraries.md).\n- 2. [FastDeploy Precompiled Library](https://github.com/PaddlePaddle/FastDeploy/docs/en/build_and_install/download_prebuilt_libraries.md).\n\n\n## Reference\n* https://github.com/snakers4/silero-vad\n* https://github.com/PaddlePaddle/FastDeploy/blob/develop/examples/audio/silero-vad/README.md\n"
  },
  {
    "path": "runtime/examples/vad/conf/vad.ini",
    "content": "[model]\nmodel_path=./data/silero_vad/silero_vad.onnx\n\n[vad]\nsr = 16000 # 16k\nframe_ms = 32 # 32, 64, 96 for 16k\nthreshold = 0.5\nbeam = 0.15\nmin_silence_duration_ms = 200\nspeech_pad_left_ms = 0\nspeech_pad_right_ms = 0\n"
  },
  {
    "path": "runtime/examples/vad/local/build.sh",
    "content": "ANDROID_NDK=/workspace/zhanghui/android-sdk/android-ndk-r25c\nANDROID_TOOLCHAIN=clang\nFASTDEPLOY_INSTALL_DIR=./fdlib/fastdeploy-android-1.0.3-shared/\nTOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake\n\ncmake -B build  -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \\\n         -DCMAKE_BUILD_TYPE=Release \\\n         -DANDROID_ABI=\"arm64-v8a\" \\\n         -DANDROID_NDK=${ANDROID_NDK} \\\n         -DANDROID_PLATFORM=\"android-21\" \\\n         -DANDROID_STL=c++_shared \\\n         -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN} \\\n         -DFASTDEPLOY_INSTALL_DIR=${FASTDEPLOY_INSTALL_DIR} \\\n         -Wno-dev\n"
  },
  {
    "path": "runtime/examples/vad/local/build_android.sh",
    "content": "ANDROID_NDK=/workspace/zhanghui/android-sdk/android-ndk-r25c\nFASTDEPLOY_INSTALL_DIR=./fdlib/fastdeploy-android-1.0.4-shared/\n\n# Setting up Android toolchanin\nANDROID_ABI=arm64-v8a  # 'arm64-v8a', 'armeabi-v7a'\nANDROID_PLATFORM=\"android-21\"  # API >= 21\nANDROID_STL=c++_shared  # 'c++_shared', 'c++_static'\nANDROID_TOOLCHAIN=clang  # 'clang' only\nTOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake\n\n# Create build directory\nBUILD_ROOT=build/Android\nBUILD_DIR=${BUILD_ROOT}/${ANDROID_ABI}-api-21\n#FASDEPLOY_INSTALL_DIR=\"${BUILD_DIR}/install\"\n#mkdir build && mkdir ${BUILD_ROOT} && mkdir ${BUILD_DIR}\nmkdir -p ${BUILD_DIR}\ncd ${BUILD_DIR}\n\n# CMake configuration with Android toolchain\ncmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \\\n      -DCMAKE_BUILD_TYPE=MinSizeRel \\\n      -DANDROID_ABI=${ANDROID_ABI} \\\n      -DANDROID_NDK=${ANDROID_NDK} \\\n      -DANDROID_PLATFORM=${ANDROID_PLATFORM} \\\n      -DANDROID_STL=${ANDROID_STL} \\\n      -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN} \\\n      -DFASTDEPLOY_INSTALL_DIR=${FASTDEPLOY_INSTALL_DIR} \\\n      -Wno-dev ../../..\n\n# Build FastDeploy Android C++ SDK\nmake -j8\n"
  },
  {
    "path": "runtime/examples/vad/local/download.sh",
    "content": "#!/bin/bash\n\nmkdir -p data\ncd data\n\nwget -c https://bj.bcebos.com/paddlehub/fastdeploy/silero_vad.tgz\n\ntest -e silero_vad || tar zxvf silero_vad.tgz\n\nwget -c https://bj.bcebos.com/paddlehub/fastdeploy/silero_vad_sample.wav\n"
  },
  {
    "path": "runtime/examples/vad/path.sh",
    "content": "# This contains the locations of binarys build required for running the examples.\n\nunset GREP_OPTIONS\n\nENGINE_ROOT=$PWD/../../\nENGINE_BUILD=$ENGINE_ROOT/build/Linux/x86_64/engine/vad\n\nENGINE_TOOLS=$ENGINE_ROOT/tools\nTOOLS_BIN=$ENGINE_TOOLS/valgrind/install/bin\n\n[ -d $ENGINE_BUILD ] || { echo \"Error: 'build/runtime' directory not found. please ensure that the project build successfully\"; }\n\nexport LC_AL=C\n\nexport PATH=$PATH:$TOOLS_BIN:$ENGINE_BUILD/nnet:$ENGINE_BUILD/interface\n\nexport LD_LIBRARY_PATH=$PADDLE_LIB_PATH:$LD_LIBRARY_PATH\n"
  },
  {
    "path": "runtime/examples/vad/run.sh",
    "content": "#!/bin/bash\nset -e\n\n. path.sh\n\nnj=40\nstage=-1\nstop_stage=100\n\n. utils/parse_options.sh\n\n# input\ndata=data\nexp=exp\nmkdir -p $exp $data\n\n# 1. compile\nif [ ! -d ${ENGINE_BUILD} ]; then\n    pushd ${ENGINE_ROOT} \n    bash build.sh\n\n    # build for android armv8/armv7\n    # bash build_android.sh\n    popd\nfi\n\n\nif [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ];then\n    ./local/download.sh\nfi\n\n\nif [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then\n    ./local/decode.sh \nfi\n\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/.gradle/6.1.1/gc.properties",
    "content": ""
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/.gradle/buildOutputCleanup/cache.properties",
    "content": "#Wed Mar 29 16:03:45 CST 2023\ngradle.version=6.1.1\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/.gradle/vcs-1/gc.properties",
    "content": ""
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/LICENSE.md",
    "content": "Copyright 2019 Georgiy Konovalov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, \nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, \nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT \nNOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/README",
    "content": "'''\nINSTALL\n'''\n执行目录为speechx根目录\nsh build_android.sh\ncp build/Android/arm64-v8a-api-21/vad-android-out/*.so examples/vad/vad-android-demo/vad/src/main/cpp/jniLibs/arm64-v8a\ncp build/Android/arm64-v8a-api-21/vad-android-out/vad_interface.h examples/vad/vad-android-demo/vad/src/main/cpp/includes/\n\n'''\nUSEAGE\n'''\n1. 根据vad资源实际放在手机中的位置，更改vad-android-demo/app/src/main/cpp/vad/src/main/cpp/native-lib.cpp中的conf_path、fp_pcm_name、fp_log_name\n2. 在AndroidStudio中编译执行\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/README.md",
    "content": "This VAD library can process audio in real-time utilizing \n[Gaussian Mixture Model](http://en.wikipedia.org/wiki/Mixture_model#Gaussian_mixture_model) (GMM)\nwhich helps identify presence of human speech in an audio sample that contains a mixture of speech \nand noise. VAD work offline and all processing done on device.\n  \nLibrary based on \n[WebRTC VAD](https://chromium.googlesource.com/external/webrtc/+/branch-heads/43/webrtc/common_audio/vad/) \nfrom Google which is reportedly one of the best available: it's fast, modern and free.\nThis  algorithm has  found  wide adoption and has recently become one of \nthe gold-standards for delay-sensitive scenarios like web-based interaction.\n  \nIf you are looking for a higher accuracy and faster processing time I recommend to use Deep Neural \nNetworks(DNN). Please see for reference the following paper with \n[DNN vs GMM](https://www.microsoft.com/en-us/research/uploads/prod/2018/02/KoPhiliposeTashevZarar_ICASSP_2018.pdf)\ncomparison.\n\n<p align=\"center\">\n<img src=\"https://raw.githubusercontent.com/gkonovalov/android-vad/master/demo.gif\" alt=\"drawing\" height=\"400\"/>\n</p>\n\n## Parameters\nVAD library only accepts 16-bit mono PCM audio stream and can work with next Sample Rates, Frame Sizes and Classifiers. \n<table>\n<tr>\n<td>\n&nbsp\n\n| Valid Sample Rate  | Valid Frame Size  |   \n|:-------------------|:------------------|   \n| 8000Hz             | 80, 160, 240      |  \n| 16000Hz            | 160, 320, 480     |   \n| 32000Hz            | 320, 640, 960     |   \n| 48000Hz            | 480, 960, 1440    |   \n</td>\n<td>\n&nbsp\n\n| Valid Classifiers |\n|:------------------|\n| NORMAL            |\n| LOW_BITRATE       |\n| AGGRESSIVE        |\n| VERY_AGGRESSIVE   |\n</td>\n</tr>\n</table>\n\n\n**Silence duration (ms)** - this parameter used in Continuous Speech detector,\nthe value of this parameter will define the necessary and sufficient \nduration of negative results to recognize it as silence.\n \n**Voice duration (ms)** - this parameter used in Continuous Speech detector,\nthe value of this parameter will define the necessary and sufficient \nduration of positive results to recognize result as speech.\n\nRecommended parameters:\n* Sample Rate - **16KHz**,\n* Frame Size - **160**,\n* Mode - **VERY_AGGRESSIVE**,\n* Silence Duration - **500ms**,\n* Voice Duration - **500ms**;\n\n## Usage\nVAD supports 2 different ways of detecting speech:\n1. Continuous Speech listener was designed to detect long utterances \nwithout returning false positive results when user makes pauses between \nsentences.\n```java\n Vad vad = new Vad(VadConfig.newBuilder()\n                .setSampleRate(VadConfig.SampleRate.SAMPLE_RATE_16K)\n                .setFrameSize(VadConfig.FrameSize.FRAME_SIZE_160)\n                .setMode(VadConfig.Mode.VERY_AGGRESSIVE)\n                .setSilenceDurationMillis(500)\n                .setVoiceDurationMillis(500)\n                .build());\n\n        vad.start();\n        \n        vad.addContinuousSpeechListener(short[] audioFrame, new VadListener() {\n            @Override\n            public void onSpeechDetected() {\n                //speech detected!\n            }\n\n            @Override\n            public void onNoiseDetected() {\n                //noise detected!\n            }\n        });\n        \n        vad.stop();\n```\n\n2. Speech detector was designed to detect speech/noise in small audio \nframes and return result for every frame. This method will not work for \nlong utterances.\n```java\n Vad vad = new Vad(VadConfig.newBuilder()\n                .setSampleRate(VadConfig.SampleRate.SAMPLE_RATE_16K)\n                .setFrameSize(VadConfig.FrameSize.FRAME_SIZE_160)\n                .setMode(VadConfig.Mode.VERY_AGGRESSIVE)\n                .build());\n\n        vad.start();\n        \n        boolean isSpeech = vad.isSpeech(short[] audioFrame);\n        \n        vad.stop();\n```\n## Requirements\nAndroid VAD supports Android 4.1 (Jelly Bean) and later.\n\n## Development\n\nTo open the project in Android Studio:\n\n1. Go to *File* menu or the *Welcome Screen*\n2. Click on *Open...*\n3. Navigate to VAD's root directory.\n4. Select `setting.gradle`\n\n## Download\n[![](https://jitpack.io/v/gkonovalov/android-vad.svg)](https://jitpack.io/#gkonovalov/android-vad)\n\n\nGradle is the only supported build configuration, so just add the dependency to your project `build.gradle` file:\n1. Add it in your root build.gradle at the end of repositories:\n```groovy\nallprojects {\n   repositories {\n     maven { url 'https://jitpack.io' }\n   }\n}\n```\n\n2. Add the dependency\n```groovy\ndependencies {\n    implementation 'com.github.gkonovalov:android-vad:1.0.1'\n}\n```\n\nYou also can download precompiled AAR library and APK files from GitHub's [releases page](https://github.com/gkonovalov/android-vad/releases).\n\n------------\nGeorgiy Konovalov 2021 (c) [MIT License](https://opensource.org/licenses/MIT)"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        google()\n        jcenter()\n        maven { url 'https://jitpack.io' }\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:4.0.2'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n        maven { url 'https://jitpack.io' }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 29\n    buildToolsVersion \"29.0.2\"\n    defaultConfig {\n        applicationId \"com.konovalov.vad.example\"\n        minSdkVersion 16\n        targetSdkVersion 29\n        versionCode 2\n        versionName \"1.0.1\"\n\n        setProperty(\"archivesBaseName\", \"Android-VAD-v\" + versionName)\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation 'androidx.appcompat:appcompat:1.3.0'\n    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'\n\n    implementation 'com.airbnb.android:lottie:3.4.0'\n    implementation 'org.permissionsdispatcher:permissionsdispatcher:4.8.0'\n    annotationProcessor 'org.permissionsdispatcher:permissionsdispatcher-processor:4.8.0'\n    implementation project(path: ':vad')\n\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test:runner:1.3.0'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'\n    implementation 'com.google.android.material:material:1.3.0'\n}\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/local.properties",
    "content": "## This file must *NOT* be checked into Version Control Systems,\n# as it contains information specific to your local configuration.\n#\n# Location of the SDK. This is only used by Gradle.\n# For customization when using a Version Control System, please read the\n# header note.\n#Thu Mar 30 16:37:21 CST 2023\nsdk.dir=/Users/masimeng/Library/Android/sdk\nndk.dir=/Users/masimeng/Library/Android/sdk/ndk/23.1.7779620/\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/androidTest/java/com/konovalov/vad/example/ExampleInstrumentedTest.java",
    "content": "package com.konovalov.vad.example;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\nimport androidx.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();\n\n        assertEquals(\"com.konovalov.vad.example\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.konovalov.vad.example\">\n\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"></uses-permission>\n    <uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"\n        tools:ignore=\"ProtectedPermissions\"></uses-permission>\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:screenOrientation=\"portrait\"\n        android:theme=\"@style/AppTheme.NoActionBar\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/java/com/konovalov/vad/example/recorder/VoiceRecorder.java",
    "content": "package com.konovalov.vad.example.recorder;\n\nimport android.media.AudioFormat;\nimport android.media.AudioRecord;\nimport android.media.MediaRecorder;\nimport android.util.Log;\n\nimport com.konovalov.vad.example.recorder.VoiceRecorderConfig;\n\nimport com.konovalov.vad.Vad;\n//import com.konovalov.vad.VadConfig;\nimport com.konovalov.vad.VadListener;\n\nimport static android.media.AudioFormat.CHANNEL_IN_MONO;\nimport static android.media.AudioFormat.CHANNEL_IN_STEREO;\n\nimport java.io.File;\n\n/**\n * Created by George Konovalov on 11/16/2019.\n */\n\npublic class VoiceRecorder {\n    private static final int PCM_CHANNEL = CHANNEL_IN_MONO;\n    private static final int PCM_ENCODING_BIT = AudioFormat.ENCODING_PCM_16BIT;\n\n    private VoiceRecorderConfig config;\n    private Vad vad;\n    private AudioRecord audioRecord;\n    private Listener callback;\n    private Thread thread;\n\n    private boolean isListening = false;\n\n    private static final String TAG = VoiceRecorder.class.getSimpleName();\n\n    public VoiceRecorder(Listener callback, VoiceRecorderConfig config) {\n        this.callback = callback;\n        this.config = config;\n        this.vad = new Vad();\n    }\n\n    public void updateConfig(VoiceRecorderConfig config) {\n        this.config = config;\n    }\n\n    public void start() {\n        stop();\n        audioRecord = createAudioRecord();\n        if (audioRecord != null) {\n            isListening = true;\n            audioRecord.startRecording();\n\n            thread = new Thread(new ProcessVoice());\n            thread.start();\n            vad.start();\n        } else {\n            Log.w(TAG, \"Failed start Voice Recorder!\");\n        }\n    }\n\n\n    public void stop() {\n        isListening = false;\n        if (thread != null) {\n            thread.interrupt();\n            thread = null;\n        }\n        if (audioRecord != null) {\n            try {\n                audioRecord.release();\n            } catch (Exception e) {\n                Log.e(TAG, \"Error stop AudioRecord \", e);\n            }\n            audioRecord = null;\n        }\n        if (vad != null) {\n            vad.stop();\n        }\n    }\n\n\n    private AudioRecord createAudioRecord() {\n        try {\n            final int minBufSize = AudioRecord.getMinBufferSize(config.getSampleRate().getValue(), PCM_CHANNEL, PCM_ENCODING_BIT);\n            int frame_size = config.getFrameSize().getValue();\n            if (minBufSize > frame_size) {\n                Log.e(TAG, \"minBufSize > frame_size\");\n                return null;\n            }\n            Log.i(TAG, \"minBufSize : \" + minBufSize);\n            final AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, config.getSampleRate().getValue(), PCM_CHANNEL, PCM_ENCODING_BIT, frame_size);\n            Log.i(TAG, \"config.getSampleRate().getValue() : \" + config.getSampleRate().getValue());\n\n            if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {\n                return audioRecord;\n            } else {\n                audioRecord.release();\n            }\n        } catch (IllegalArgumentException e) {\n            Log.e(TAG, \"Error can't create AudioRecord \", e);\n        }\n\n        return null;\n    }\n\n    private int getNumberOfChannels() {\n        switch (PCM_CHANNEL) {\n            case CHANNEL_IN_MONO:\n                return 1;\n            case CHANNEL_IN_STEREO:\n                return 2;\n        }\n        return 1;\n    }\n\n    private class ProcessVoice implements Runnable {\n\n        @Override\n        public void run() {\n            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);\n            final int minBufSize = AudioRecord.getMinBufferSize(config.getSampleRate().getValue(), PCM_CHANNEL, PCM_ENCODING_BIT);\n            while (!Thread.interrupted() && isListening && audioRecord != null) {\n                short[] buffer = new short[config.getFrameSize().getValue()];\n                audioRecord.read(buffer, 0, buffer.length);\n                detectSpeech(buffer);\n            }\n        }\n\n        private void detectSpeech(short[] buffer) {\n            vad.addContinuousSpeechListener(buffer, new VadListener() {\n                @Override\n                public void onSpeechDetected() {\n                    callback.onSpeechDetected();\n                }\n\n                @Override\n                public void onNoiseDetected() {\n                    callback.onNoiseDetected();\n                }\n            });\n        }\n    }\n\n    public interface Listener {\n        void onSpeechDetected();\n\n        void onNoiseDetected();\n    }\n\n}\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/java/com/konovalov/vad/example/recorder/VoiceRecorderConfig.java",
    "content": "package com.konovalov.vad.example.recorder;\n\n\n/**\n * Created by George Konovalov on 11/16/2019.\n */\n\npublic class VoiceRecorderConfig {\n    private SampleRate sampleRate;\n    private Mode mode;\n    private FrameSize frameSize;\n    private int voiceDurationMillis;\n    private int silenceDurationMillis;\n\n    public VoiceRecorderConfig() {\n    }\n\n    public VoiceRecorderConfig(Builder builder) {\n        this.voiceDurationMillis = builder.voiceDurationMillis;\n        this.silenceDurationMillis = builder.silenceDurationMillis;\n        this.sampleRate = builder.sampleRate;\n        this.frameSize = builder.frameSize;\n        this.mode = builder.mode;\n    }\n\n    public SampleRate getSampleRate() {\n        return sampleRate;\n    }\n\n    public Mode getMode() {\n        return mode;\n    }\n\n    public FrameSize getFrameSize() {\n        return frameSize;\n    }\n\n    public int getVoiceDurationMillis() {\n        return voiceDurationMillis;\n    }\n\n    public int getSilenceDurationMillis() {\n        return silenceDurationMillis;\n    }\n\n    public void setSampleRate(SampleRate sampleRate) {\n        this.sampleRate = sampleRate;\n    }\n\n    public void setMode(Mode mode) {\n        this.mode = mode;\n    }\n\n    public void setFrameSize(FrameSize frameSize) {\n        this.frameSize = frameSize;\n    }\n\n    public void setVoiceDurationMillis(int voiceDurationMillis) {\n        this.voiceDurationMillis = voiceDurationMillis;\n    }\n\n    public void setSilenceDurationMillis(int silenceDurationMillis) {\n        this.silenceDurationMillis = silenceDurationMillis;\n    }\n\n    public static Builder newBuilder() {\n        return new Builder();\n    }\n\n    public static class Builder {\n        private SampleRate sampleRate = SampleRate.SAMPLE_RATE_16K;\n        private Mode mode = Mode.VERY_AGGRESSIVE;\n        private FrameSize frameSize;\n        private int voiceDurationMillis = 500;\n        private int silenceDurationMillis = 500;\n\n        private Builder() {\n        }\n\n        public Builder setSampleRate(SampleRate sampleRate) {\n            this.sampleRate = sampleRate;\n            return this;\n        }\n\n        public Builder setMode(Mode mode) {\n            this.mode = mode;\n            return this;\n        }\n\n        public Builder setFrameSize(FrameSize frameSize) {\n            this.frameSize = frameSize;\n            return this;\n        }\n\n        public Builder setVoiceDurationMillis(int voiceDurationMillis) {\n            this.voiceDurationMillis = voiceDurationMillis;\n            return this;\n        }\n\n        public Builder setSilenceDurationMillis(int silenceDurationMillis) {\n            this.silenceDurationMillis = silenceDurationMillis;\n            return this;\n        }\n\n        public VoiceRecorderConfig build() {\n            return new VoiceRecorderConfig(this);\n        }\n    }\n\n    public enum SampleRate {\n        SAMPLE_RATE_16K(16000);\n\n        private int sampleRate;\n\n        public int getValue() {\n            return sampleRate;\n        }\n\n        SampleRate(int sampleRate) {\n            this.sampleRate = sampleRate;\n        }\n    }\n\n    public enum Mode {\n        NORMAL(0),\n        LOW_BITRATE(1),\n        AGGRESSIVE(2),\n        VERY_AGGRESSIVE(3);\n\n        private int mode;\n\n        public int getValue() {\n            return mode;\n        }\n\n        Mode(int mode) {\n            this.mode = mode;\n        }\n    }\n\n    public enum FrameSize {\n        FRAME_SIZE_1536(1536);\n\n        private int frameSize;\n\n        public int getValue() {\n            return frameSize;\n        }\n\n        FrameSize(int frameSize) {\n            this.frameSize = frameSize;\n        }\n    }\n\n\n\n}\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillType=\"evenOdd\"\n        android:pathData=\"M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"78.5885\"\n                android:endY=\"90.9159\"\n                android:startX=\"48.7653\"\n                android:startY=\"61.0927\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#000000</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#FFFFFF</color>\n    <color name=\"colorPrimaryText\">#FFFFFF</color>\n</resources>\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/example/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Android VAD</string>\n    <string name=\"speech_detected\">Speech detected!</string>\n    <string name=\"noise_detected\">Noise detected!</string>\n    <string name=\"press_button_to_start\">Press button to start VAD!</string>\n    <string name=\"start\">Start</string>\n    <string name=\"stop\">Stop</string>\n    <string name=\"sample_rate\">Sample Rate:</string>\n    <string name=\"frame_size\">Frame Size:</string>\n    <string name=\"mode\">Mode:</string>\n</resources>\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/local.properties",
    "content": "## This file must *NOT* be checked into Version Control Systems,\n# as it contains information specific to your local configuration.\n#\n# Location of the SDK. This is only used by Gradle.\n# For customization when using a Version Control System, please read the\n# header note.\n#Wed Mar 29 16:03:45 CST 2023\nsdk.dir=/Users/masimeng/Library/Android/sdk\nndk.dir=/Users/masimeng/Library/Android/sdk/ndk/20.0.5594570/\n"
  },
  {
    "path": "runtime/examples/vad/vad-android-demo/vad/consumer-rules.pro",
    "content": ""
  },
  {
    "path": "third_party/__init__.py",
    "content": ""
  }
]